4 * Copyright (c) 2011 David Herrmann <dh.herrmann@googlemail.com>
5 * Copyright (c) 2011 University of Tuebingen
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Virtual Terminal Emulator
29 * This is the VT implementation. It is written from scratch. It uses the
30 * screen state-machine as output and is tightly bound to it. It supports
31 * functionality from vt100 up to vt500 series. It doesn't implement an
32 * explicitly selected terminal but tries to support the most important commands
33 * to be compatible with existing implementations. However, full vt102
34 * compatibility is the least that is provided.
36 * The main parser in this file controls the parser-state and dispatches the
37 * actions to the related handlers. The parser is based on the state-diagram
38 * from Paul Williams: http://vt100.net/emu/
39 * It is written from scratch, though.
40 * This parser is fully compatible up to the vt500 series. It requires UTF-8 and
41 * does not support any other input encoding. The G0 and G1 sets are therefore
42 * defined as subsets of UTF-8. You may still map G0-G3 into GL, though.
44 * However, the CSI/DCS/etc handlers are not designed after a specific VT
45 * series. We try to support all vt102 commands but implement several other
46 * often used sequences, too. Feel free to add further.
48 * See ./doc/vte.txt for more information on this VT-emulator.
55 #include <xkbcommon/xkbcommon-keysyms.h>
57 #include "tsm_screen.h"
58 #include "tsm_unicode.h"
61 #define LLOG_SUBSYSTEM "tsm_vte"
63 /* Input parser states */
65 STATE_NONE, /* placeholder */
66 STATE_GROUND, /* initial state and ground */
67 STATE_ESC, /* ESC sequence was started */
68 STATE_ESC_INT, /* intermediate escape characters */
69 STATE_CSI_ENTRY, /* starting CSI sequence */
70 STATE_CSI_PARAM, /* CSI parameters */
71 STATE_CSI_INT, /* intermediate CSI characters */
72 STATE_CSI_IGNORE, /* CSI error; ignore this CSI sequence */
73 STATE_DCS_ENTRY, /* starting DCS sequence */
74 STATE_DCS_PARAM, /* DCS parameters */
75 STATE_DCS_INT, /* intermediate DCS characters */
76 STATE_DCS_PASS, /* DCS data passthrough */
77 STATE_DCS_IGNORE, /* DCS error; ignore this DCS sequence */
78 STATE_OSC_STRING, /* parsing OCS sequence */
79 STATE_ST_IGNORE, /* unimplemented seq; ignore until ST */
83 /* Input parser actions */
85 ACTION_NONE, /* placeholder */
86 ACTION_IGNORE, /* ignore the character entirely */
87 ACTION_PRINT, /* print the character on the console */
88 ACTION_EXECUTE, /* execute single control character (C0/C1) */
89 ACTION_CLEAR, /* clear current parameter state */
90 ACTION_COLLECT, /* collect intermediate character */
91 ACTION_PARAM, /* collect parameter character */
92 ACTION_ESC_DISPATCH, /* dispatch escape sequence */
93 ACTION_CSI_DISPATCH, /* dispatch csi sequence */
94 ACTION_DCS_START, /* start of DCS data */
95 ACTION_DCS_COLLECT, /* collect DCS data */
96 ACTION_DCS_END, /* end of DCS data */
97 ACTION_OSC_START, /* start of OSC data */
98 ACTION_OSC_COLLECT, /* collect OSC data */
99 ACTION_OSC_END, /* end of OSC data */
104 #define CSI_BANG 0x0001 /* CSI: ! */
105 #define CSI_CASH 0x0002 /* CSI: $ */
106 #define CSI_WHAT 0x0004 /* CSI: ? */
107 #define CSI_GT 0x0008 /* CSI: > */
108 #define CSI_SPACE 0x0010 /* CSI: */
109 #define CSI_SQUOTE 0x0020 /* CSI: ' */
110 #define CSI_DQUOTE 0x0040 /* CSI: " */
111 #define CSI_MULT 0x0080 /* CSI: * */
112 #define CSI_PLUS 0x0100 /* CSI: + */
113 #define CSI_POPEN 0x0200 /* CSI: ( */
114 #define CSI_PCLOSE 0x0400 /* CSI: ) */
116 /* max CSI arguments */
117 #define CSI_ARG_MAX 16
120 #define FLAG_CURSOR_KEY_MODE 0x00000001 /* DEC cursor key mode */
121 #define FLAG_KEYPAD_APPLICATION_MODE 0x00000002 /* DEC keypad application mode; TODO: toggle on numlock? */
122 #define FLAG_LINE_FEED_NEW_LINE_MODE 0x00000004 /* DEC line-feed/new-line mode */
123 #define FLAG_8BIT_MODE 0x00000008 /* Disable UTF-8 mode and enable 8bit compatible mode */
124 #define FLAG_7BIT_MODE 0x00000010 /* Disable 8bit mode and use 7bit compatible mode */
125 #define FLAG_USE_C1 0x00000020 /* Explicitely use 8bit C1 codes; TODO: implement */
126 #define FLAG_KEYBOARD_ACTION_MODE 0x00000040 /* Disable keyboard; TODO: implement? */
127 #define FLAG_INSERT_REPLACE_MODE 0x00000080 /* Enable insert mode */
128 #define FLAG_SEND_RECEIVE_MODE 0x00000100 /* Disable local echo */
129 #define FLAG_TEXT_CURSOR_MODE 0x00000200 /* Show cursor */
130 #define FLAG_INVERSE_SCREEN_MODE 0x00000400 /* Inverse colors */
131 #define FLAG_ORIGIN_MODE 0x00000800 /* Relative origin for cursor */
132 #define FLAG_AUTO_WRAP_MODE 0x00001000 /* Auto line wrap mode */
133 #define FLAG_AUTO_REPEAT_MODE 0x00002000 /* Auto repeat key press; TODO: implement */
134 #define FLAG_NATIONAL_CHARSET_MODE 0x00004000 /* Send keys from nation charsets; TODO: implement */
135 #define FLAG_BACKGROUND_COLOR_ERASE_MODE 0x00008000 /* Set background color on erase (bce) */
136 #define FLAG_PREPEND_ESCAPE 0x00010000 /* Prepend escape character to next output */
137 #define FLAG_TITE_INHIBIT_MODE 0x00020000 /* Prevent switching to alternate screen buffer */
139 struct vte_saved_state {
140 unsigned int cursor_x;
141 unsigned int cursor_y;
142 struct tsm_screen_attr cattr;
152 struct tsm_screen *con;
153 tsm_vte_write_cb write_cb;
157 struct tsm_utf8_mach *mach;
158 unsigned long parse_cnt;
161 unsigned int csi_argc;
162 int csi_argv[CSI_ARG_MAX];
163 unsigned int csi_flags;
165 uint8_t (*palette)[3];
166 struct tsm_screen_attr def_attr;
167 struct tsm_screen_attr cattr;
172 tsm_vte_charset *glt;
173 tsm_vte_charset *grt;
179 struct vte_saved_state saved_state;
180 unsigned int alt_cursor_x;
181 unsigned int alt_cursor_y;
206 static uint8_t color_palette[COLOR_NUM][3] = {
207 [COLOR_BLACK] = { 0, 0, 0 }, /* black */
208 [COLOR_RED] = { 205, 0, 0 }, /* red */
209 [COLOR_GREEN] = { 0, 205, 0 }, /* green */
210 [COLOR_YELLOW] = { 205, 205, 0 }, /* yellow */
211 [COLOR_BLUE] = { 0, 0, 238 }, /* blue */
212 [COLOR_MAGENTA] = { 205, 0, 205 }, /* magenta */
213 [COLOR_CYAN] = { 0, 205, 205 }, /* cyan */
214 [COLOR_LIGHT_GREY] = { 229, 229, 229 }, /* light grey */
215 [COLOR_DARK_GREY] = { 127, 127, 127 }, /* dark grey */
216 [COLOR_LIGHT_RED] = { 255, 0, 0 }, /* light red */
217 [COLOR_LIGHT_GREEN] = { 0, 255, 0 }, /* light green */
218 [COLOR_LIGHT_YELLOW] = { 255, 255, 0 }, /* light yellow */
219 [COLOR_LIGHT_BLUE] = { 92, 92, 255 }, /* light blue */
220 [COLOR_LIGHT_MAGENTA] = { 255, 0, 255 }, /* light magenta */
221 [COLOR_LIGHT_CYAN] = { 0, 255, 255 }, /* light cyan */
222 [COLOR_WHITE] = { 255, 255, 255 }, /* white */
224 [COLOR_FOREGROUND] = { 229, 229, 229 }, /* light grey */
225 [COLOR_BACKGROUND] = { 0, 0, 0 }, /* black */
228 static uint8_t color_palette_solarized[COLOR_NUM][3] = {
229 [COLOR_BLACK] = { 7, 54, 66 }, /* black */
230 [COLOR_RED] = { 220, 50, 47 }, /* red */
231 [COLOR_GREEN] = { 133, 153, 0 }, /* green */
232 [COLOR_YELLOW] = { 181, 137, 0 }, /* yellow */
233 [COLOR_BLUE] = { 38, 139, 210 }, /* blue */
234 [COLOR_MAGENTA] = { 211, 54, 130 }, /* magenta */
235 [COLOR_CYAN] = { 42, 161, 152 }, /* cyan */
236 [COLOR_LIGHT_GREY] = { 238, 232, 213 }, /* light grey */
237 [COLOR_DARK_GREY] = { 0, 43, 54 }, /* dark grey */
238 [COLOR_LIGHT_RED] = { 203, 75, 22 }, /* light red */
239 [COLOR_LIGHT_GREEN] = { 88, 110, 117 }, /* light green */
240 [COLOR_LIGHT_YELLOW] = { 101, 123, 131 }, /* light yellow */
241 [COLOR_LIGHT_BLUE] = { 131, 148, 150 }, /* light blue */
242 [COLOR_LIGHT_MAGENTA] = { 108, 113, 196 }, /* light magenta */
243 [COLOR_LIGHT_CYAN] = { 147, 161, 161 }, /* light cyan */
244 [COLOR_WHITE] = { 253, 246, 227 }, /* white */
246 [COLOR_FOREGROUND] = { 238, 232, 213 }, /* light grey */
247 [COLOR_BACKGROUND] = { 7, 54, 66 }, /* black */
250 static uint8_t color_palette_solarized_black[COLOR_NUM][3] = {
251 [COLOR_BLACK] = { 0, 0, 0 }, /* black */
252 [COLOR_RED] = { 220, 50, 47 }, /* red */
253 [COLOR_GREEN] = { 133, 153, 0 }, /* green */
254 [COLOR_YELLOW] = { 181, 137, 0 }, /* yellow */
255 [COLOR_BLUE] = { 38, 139, 210 }, /* blue */
256 [COLOR_MAGENTA] = { 211, 54, 130 }, /* magenta */
257 [COLOR_CYAN] = { 42, 161, 152 }, /* cyan */
258 [COLOR_LIGHT_GREY] = { 238, 232, 213 }, /* light grey */
259 [COLOR_DARK_GREY] = { 0, 43, 54 }, /* dark grey */
260 [COLOR_LIGHT_RED] = { 203, 75, 22 }, /* light red */
261 [COLOR_LIGHT_GREEN] = { 88, 110, 117 }, /* light green */
262 [COLOR_LIGHT_YELLOW] = { 101, 123, 131 }, /* light yellow */
263 [COLOR_LIGHT_BLUE] = { 131, 148, 150 }, /* light blue */
264 [COLOR_LIGHT_MAGENTA] = { 108, 113, 196 }, /* light magenta */
265 [COLOR_LIGHT_CYAN] = { 147, 161, 161 }, /* light cyan */
266 [COLOR_WHITE] = { 253, 246, 227 }, /* white */
268 [COLOR_FOREGROUND] = { 238, 232, 213 }, /* light grey */
269 [COLOR_BACKGROUND] = { 0, 0, 0 }, /* black */
272 static uint8_t color_palette_solarized_white[COLOR_NUM][3] = {
273 [COLOR_BLACK] = { 7, 54, 66 }, /* black */
274 [COLOR_RED] = { 220, 50, 47 }, /* red */
275 [COLOR_GREEN] = { 133, 153, 0 }, /* green */
276 [COLOR_YELLOW] = { 181, 137, 0 }, /* yellow */
277 [COLOR_BLUE] = { 38, 139, 210 }, /* blue */
278 [COLOR_MAGENTA] = { 211, 54, 130 }, /* magenta */
279 [COLOR_CYAN] = { 42, 161, 152 }, /* cyan */
280 [COLOR_LIGHT_GREY] = { 238, 232, 213 }, /* light grey */
281 [COLOR_DARK_GREY] = { 0, 43, 54 }, /* dark grey */
282 [COLOR_LIGHT_RED] = { 203, 75, 22 }, /* light red */
283 [COLOR_LIGHT_GREEN] = { 88, 110, 117 }, /* light green */
284 [COLOR_LIGHT_YELLOW] = { 101, 123, 131 }, /* light yellow */
285 [COLOR_LIGHT_BLUE] = { 131, 148, 150 }, /* light blue */
286 [COLOR_LIGHT_MAGENTA] = { 108, 113, 196 }, /* light magenta */
287 [COLOR_LIGHT_CYAN] = { 147, 161, 161 }, /* light cyan */
288 [COLOR_WHITE] = { 253, 246, 227 }, /* white */
290 [COLOR_FOREGROUND] = { 7, 54, 66 }, /* black */
291 [COLOR_BACKGROUND] = { 238, 232, 213 }, /* light grey */
294 static uint8_t (*get_palette(struct tsm_vte *vte))[3]
296 if (!vte->palette_name)
297 return color_palette;
299 if (!strcmp(vte->palette_name, "solarized"))
300 return color_palette_solarized;
301 if (!strcmp(vte->palette_name, "solarized-black"))
302 return color_palette_solarized_black;
303 if (!strcmp(vte->palette_name, "solarized-white"))
304 return color_palette_solarized_white;
306 return color_palette;
309 /* Several effects may occur when non-RGB colors are used. For instance, if bold
310 * is enabled, then a dark color code is always converted to a light color to
311 * simulate bold (even though bold may actually be supported!). To support this,
312 * we need to differentiate between a set color-code and a set rgb-color.
313 * This function actually converts a set color-code into an RGB color. This must
314 * be called before passing the attribute to the console layer so the console
315 * layer can always work with RGB values and does not have to care for color
317 static void to_rgb(struct tsm_vte *vte, struct tsm_screen_attr *attr)
323 /* bold causes light colors */
324 if (attr->bold && code < 8)
326 if (code >= COLOR_NUM)
327 code = COLOR_FOREGROUND;
329 attr->fr = vte->palette[code][0];
330 attr->fg = vte->palette[code][1];
331 attr->fb = vte->palette[code][2];
336 if (code >= COLOR_NUM)
337 code = COLOR_BACKGROUND;
339 attr->br = vte->palette[code][0];
340 attr->bg = vte->palette[code][1];
341 attr->bb = vte->palette[code][2];
345 static void copy_fcolor(struct tsm_screen_attr *dest,
346 const struct tsm_screen_attr *src)
348 dest->fccode = src->fccode;
354 static void copy_bcolor(struct tsm_screen_attr *dest,
355 const struct tsm_screen_attr *src)
357 dest->bccode = src->bccode;
363 int tsm_vte_new(struct tsm_vte **out, struct tsm_screen *con,
364 tsm_vte_write_cb write_cb, void *data,
370 if (!out || !con || !write_cb)
373 vte = malloc(sizeof(*vte));
377 memset(vte, 0, sizeof(*vte));
381 vte->write_cb = write_cb;
383 vte->palette = get_palette(vte);
384 vte->def_attr.fccode = COLOR_FOREGROUND;
385 vte->def_attr.bccode = COLOR_BACKGROUND;
386 to_rgb(vte, &vte->def_attr);
388 ret = tsm_utf8_mach_new(&vte->mach);
393 tsm_screen_erase_screen(vte->con, false);
395 llog_debug(vte, "new vte object");
396 tsm_screen_ref(vte->con);
405 void tsm_vte_ref(struct tsm_vte *vte)
413 void tsm_vte_unref(struct tsm_vte *vte)
415 if (!vte || !vte->ref)
421 llog_debug(vte, "destroying vte object");
422 tsm_screen_unref(vte->con);
423 tsm_utf8_mach_free(vte->mach);
427 int tsm_vte_set_palette(struct tsm_vte *vte, const char *palette)
435 tmp = strdup(palette);
440 free(vte->palette_name);
441 vte->palette_name = tmp;
443 vte->palette = get_palette(vte);
444 vte->def_attr.fccode = COLOR_FOREGROUND;
445 vte->def_attr.bccode = COLOR_BACKGROUND;
447 to_rgb(vte, &vte->def_attr);
448 memcpy(&vte->cattr, &vte->def_attr, sizeof(vte->cattr));
450 tsm_screen_set_def_attr(vte->con, &vte->def_attr);
451 tsm_screen_erase_screen(vte->con, false);
457 * Write raw byte-stream to pty.
458 * When writing data to the client we must make sure that we send the correct
459 * encoding. For backwards-compatibility reasons we should always send 7bit
460 * characters exclusively. However, when FLAG_7BIT_MODE is not set, then we can
461 * also send raw 8bit characters. For instance, in FLAG_8BIT_MODE we can use the
462 * GR characters as keyboard input and send them directly or even use the C1
463 * escape characters. In unicode mode (default) we can send multi-byte utf-8
464 * characters which are also 8bit. When sending these characters, set the \raw
465 * flag to true so this function does not perform debug checks on data we send.
466 * If debugging is disabled, these checks are also disabled and won't affect
468 * For better debugging, we also use the __LINE__ and __FILE__ macros. Use the
469 * vte_write() and vte_write_raw() macros below for more convenient use.
471 * As a rule of thumb do never send 8bit characters in escape sequences and also
472 * avoid all 8bit escape codes including the C1 codes. This will guarantee that
473 * all kind of clients are always compatible to us.
475 * If SEND_RECEIVE_MODE is off (that is, local echo is on) we have to send all
476 * data directly to ourself again. However, we must avoid recursion when
477 * tsm_vte_input() itself calls vte_write*(), therefore, we increase the
478 * PARSER counter when entering tsm_vte_input() and reset it when leaving it
479 * so we never echo data that origins from tsm_vte_input().
480 * But note that SEND_RECEIVE_MODE is inherently broken for escape sequences
481 * that request answers. That is, if we send a request to the client that awaits
482 * a response and parse that request via local echo ourself, then we will also
483 * send a response to the client even though he didn't request one. This
484 * recursion fix does not avoid this but only prevents us from endless loops
485 * here. Anyway, only few applications rely on local echo so we can safely
488 static void vte_write_debug(struct tsm_vte *vte, const char *u8, size_t len,
489 bool raw, const char *file, int line)
491 #ifdef BUILD_ENABLE_DEBUG
492 /* in debug mode we check that escape sequences are always <0x7f so they
493 * are correctly parsed by non-unicode and non-8bit-mode clients. */
497 for (i = 0; i < len; ++i) {
499 llog_warning(vte, "sending 8bit character inline to client in %s:%d",
505 /* in local echo mode, directly parse the data again */
506 if (!vte->parse_cnt && !(vte->flags & FLAG_SEND_RECEIVE_MODE)) {
507 if (vte->flags & FLAG_PREPEND_ESCAPE)
508 tsm_vte_input(vte, "\e", 1);
509 tsm_vte_input(vte, u8, len);
512 if (vte->flags & FLAG_PREPEND_ESCAPE)
513 vte->write_cb(vte, "\e", 1, vte->data);
514 vte->write_cb(vte, u8, len, vte->data);
516 vte->flags &= ~FLAG_PREPEND_ESCAPE;
519 #define vte_write(_vte, _u8, _len) \
520 vte_write_debug((_vte), (_u8), (_len), false, __FILE__, __LINE__)
521 #define vte_write_raw(_vte, _u8, _len) \
522 vte_write_debug((_vte), (_u8), (_len), true, __FILE__, __LINE__)
524 /* write to console */
525 static void write_console(struct tsm_vte *vte, tsm_symbol_t sym)
527 to_rgb(vte, &vte->cattr);
528 tsm_screen_write(vte->con, sym, &vte->cattr);
531 static void reset_state(struct tsm_vte *vte)
533 vte->saved_state.cursor_x = 0;
534 vte->saved_state.cursor_y = 0;
535 vte->saved_state.origin_mode = false;
536 vte->saved_state.wrap_mode = true;
537 vte->saved_state.gl = &tsm_vte_unicode_lower;
538 vte->saved_state.gr = &tsm_vte_unicode_upper;
540 copy_fcolor(&vte->saved_state.cattr, &vte->def_attr);
541 copy_bcolor(&vte->saved_state.cattr, &vte->def_attr);
542 vte->saved_state.cattr.bold = 0;
543 vte->saved_state.cattr.underline = 0;
544 vte->saved_state.cattr.inverse = 0;
545 vte->saved_state.cattr.protect = 0;
548 static void save_state(struct tsm_vte *vte)
550 vte->saved_state.cursor_x = tsm_screen_get_cursor_x(vte->con);
551 vte->saved_state.cursor_y = tsm_screen_get_cursor_y(vte->con);
552 vte->saved_state.cattr = vte->cattr;
553 vte->saved_state.gl = vte->gl;
554 vte->saved_state.gr = vte->gr;
555 vte->saved_state.wrap_mode = vte->flags & FLAG_AUTO_WRAP_MODE;
556 vte->saved_state.origin_mode = vte->flags & FLAG_ORIGIN_MODE;
559 static void restore_state(struct tsm_vte *vte)
561 tsm_screen_move_to(vte->con, vte->saved_state.cursor_x,
562 vte->saved_state.cursor_y);
563 vte->cattr = vte->saved_state.cattr;
564 to_rgb(vte, &vte->cattr);
565 if (vte->flags & FLAG_BACKGROUND_COLOR_ERASE_MODE)
566 tsm_screen_set_def_attr(vte->con, &vte->cattr);
567 vte->gl = vte->saved_state.gl;
568 vte->gr = vte->saved_state.gr;
570 if (vte->saved_state.wrap_mode) {
571 vte->flags |= FLAG_AUTO_WRAP_MODE;
572 tsm_screen_set_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
574 vte->flags &= ~FLAG_AUTO_WRAP_MODE;
575 tsm_screen_reset_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
578 if (vte->saved_state.origin_mode) {
579 vte->flags |= FLAG_ORIGIN_MODE;
580 tsm_screen_set_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
582 vte->flags &= ~FLAG_ORIGIN_MODE;
583 tsm_screen_reset_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
589 * This performs a soft reset of the VTE. That is, everything is reset to the
590 * same state as when the VTE was created. This does not affect the console,
593 void tsm_vte_reset(struct tsm_vte *vte)
599 vte->flags |= FLAG_TEXT_CURSOR_MODE;
600 vte->flags |= FLAG_AUTO_REPEAT_MODE;
601 vte->flags |= FLAG_SEND_RECEIVE_MODE;
602 vte->flags |= FLAG_AUTO_WRAP_MODE;
603 vte->flags |= FLAG_BACKGROUND_COLOR_ERASE_MODE;
604 tsm_screen_reset(vte->con);
605 tsm_screen_set_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
607 tsm_utf8_mach_reset(vte->mach);
608 vte->state = STATE_GROUND;
609 vte->gl = &tsm_vte_unicode_lower;
610 vte->gr = &tsm_vte_unicode_upper;
613 vte->g0 = &tsm_vte_unicode_lower;
614 vte->g1 = &tsm_vte_unicode_upper;
615 vte->g2 = &tsm_vte_unicode_lower;
616 vte->g3 = &tsm_vte_unicode_upper;
618 memcpy(&vte->cattr, &vte->def_attr, sizeof(vte->cattr));
619 to_rgb(vte, &vte->cattr);
620 tsm_screen_set_def_attr(vte->con, &vte->def_attr);
625 void tsm_vte_hard_reset(struct tsm_vte *vte)
628 tsm_screen_erase_screen(vte->con, false);
629 tsm_screen_clear_sb(vte->con);
630 tsm_screen_move_to(vte->con, 0, 0);
633 static void send_primary_da(struct tsm_vte *vte)
635 vte_write(vte, "\e[?60;1;6;9;15c", 17);
638 /* execute control character (C0 or C1) */
639 static void do_execute(struct tsm_vte *vte, uint32_t ctrl)
643 /* Ignore on input */
646 /* Transmit answerback message */
647 /* TODO: is there a better answer than ACK? */
648 vte_write(vte, "\x06", 1);
651 /* Sound bell tone */
652 /* TODO: I always considered this annying, however, we
653 * should at least provide some way to enable it if the
654 * user *really* wants it.
658 /* Move cursor one position left */
659 tsm_screen_move_left(vte->con, 1);
662 /* Move to next tab stop or end of line */
663 tsm_screen_tab_right(vte->con, 1);
668 /* Line feed or newline (CR/NL mode) */
669 if (vte->flags & FLAG_LINE_FEED_NEW_LINE_MODE)
670 tsm_screen_newline(vte->con);
672 tsm_screen_move_down(vte->con, 1, true);
675 /* Move cursor to left margin */
676 tsm_screen_move_line_home(vte->con);
679 /* Map G1 character set into GL */
683 /* Map G0 character set into GL */
687 /* Resume transmission */
690 case 0x13: /* XOFF */
691 /* Stop transmission */
695 /* Cancel escape sequence */
696 /* nothing to do here */
699 /* Discard current escape sequence and show err-sym */
700 write_console(vte, 0xbf);
703 /* Invokes an escape sequence */
704 /* nothing to do here */
710 /* Move down one row, perform scroll-up if needed */
711 tsm_screen_move_down(vte->con, 1, true);
714 /* CR/NL with scroll-up if needed */
715 tsm_screen_newline(vte->con);
718 /* Set tab stop at current position */
719 tsm_screen_set_tabstop(vte->con);
722 /* Move up one row, perform scroll-down if needed */
723 tsm_screen_move_up(vte->con, 1, true);
726 /* Temporarily map G2 into GL for next char only */
730 /* Temporarily map G3 into GL for next char only */
733 case 0x9a: /* DECID */
734 /* Send device attributes response like ANSI DA */
735 send_primary_da(vte);
738 /* End control string */
739 /* nothing to do here */
742 llog_debug(vte, "unhandled control char %u", ctrl);
746 static void do_clear(struct tsm_vte *vte)
751 for (i = 0; i < CSI_ARG_MAX; ++i)
752 vte->csi_argv[i] = -1;
756 static void do_collect(struct tsm_vte *vte, uint32_t data)
760 vte->csi_flags |= CSI_BANG;
763 vte->csi_flags |= CSI_CASH;
766 vte->csi_flags |= CSI_WHAT;
769 vte->csi_flags |= CSI_GT;
772 vte->csi_flags |= CSI_SPACE;
775 vte->csi_flags |= CSI_SQUOTE;
778 vte->csi_flags |= CSI_DQUOTE;
781 vte->csi_flags |= CSI_MULT;
784 vte->csi_flags |= CSI_PLUS;
787 vte->csi_flags |= CSI_POPEN;
790 vte->csi_flags |= CSI_PCLOSE;
795 static void do_param(struct tsm_vte *vte, uint32_t data)
800 if (vte->csi_argc < CSI_ARG_MAX)
805 if (vte->csi_argc >= CSI_ARG_MAX)
808 /* avoid integer overflows; max allowed value is 16384 anyway */
809 if (vte->csi_argv[vte->csi_argc] > 0xffff)
812 if (data >= '0' && data <= '9') {
813 new = vte->csi_argv[vte->csi_argc];
817 new = new * 10 + data - '0';
818 vte->csi_argv[vte->csi_argc] = new;
822 static bool set_charset(struct tsm_vte *vte, tsm_vte_charset *set)
824 if (vte->csi_flags & CSI_POPEN)
826 else if (vte->csi_flags & CSI_PCLOSE)
828 else if (vte->csi_flags & CSI_MULT)
830 else if (vte->csi_flags & CSI_PLUS)
838 static void do_esc(struct tsm_vte *vte, uint32_t data)
841 case 'B': /* map ASCII into G0-G3 */
842 if (set_charset(vte, &tsm_vte_unicode_lower))
845 case '<': /* map DEC supplemental into G0-G3 */
846 if (set_charset(vte, &tsm_vte_dec_supplemental_graphics))
849 case '0': /* map DEC special into G0-G3 */
850 if (set_charset(vte, &tsm_vte_dec_special_graphics))
853 case 'A': /* map British into G0-G3 */
854 /* TODO: create British charset from DEC */
855 if (set_charset(vte, &tsm_vte_unicode_upper))
858 case '4': /* map Dutch into G0-G3 */
859 /* TODO: create Dutch charset from DEC */
860 if (set_charset(vte, &tsm_vte_unicode_upper))
864 case '5': /* map Finnish into G0-G3 */
865 /* TODO: create Finnish charset from DEC */
866 if (set_charset(vte, &tsm_vte_unicode_upper))
869 case 'R': /* map French into G0-G3 */
870 /* TODO: create French charset from DEC */
871 if (set_charset(vte, &tsm_vte_unicode_upper))
874 case 'Q': /* map French-Canadian into G0-G3 */
875 /* TODO: create French-Canadian charset from DEC */
876 if (set_charset(vte, &tsm_vte_unicode_upper))
879 case 'K': /* map German into G0-G3 */
880 /* TODO: create German charset from DEC */
881 if (set_charset(vte, &tsm_vte_unicode_upper))
884 case 'Y': /* map Italian into G0-G3 */
885 /* TODO: create Italian charset from DEC */
886 if (set_charset(vte, &tsm_vte_unicode_upper))
890 case '6': /* map Norwegian/Danish into G0-G3 */
891 /* TODO: create Norwegian/Danish charset from DEC */
892 if (set_charset(vte, &tsm_vte_unicode_upper))
895 case 'Z': /* map Spanish into G0-G3 */
896 /* TODO: create Spanish charset from DEC */
897 if (set_charset(vte, &tsm_vte_unicode_upper))
901 case '7': /* map Swedish into G0-G3 */
902 /* TODO: create Swedish charset from DEC */
903 if (set_charset(vte, &tsm_vte_unicode_upper))
906 case '=': /* map Swiss into G0-G3 */
907 /* TODO: create Swiss charset from DEC */
908 if (set_charset(vte, &tsm_vte_unicode_upper))
912 if (vte->csi_flags & CSI_SPACE) {
914 /* Disable 8bit C1 mode */
915 vte->flags &= ~FLAG_USE_C1;
920 if (vte->csi_flags & CSI_SPACE) {
922 /* Enable 8bit C1 mode */
923 vte->flags |= FLAG_USE_C1;
929 /* everything below is only valid without CSI flags */
930 if (vte->csi_flags) {
931 llog_debug(vte, "unhandled escape seq %u", data);
937 /* Move down one row, perform scroll-up if needed */
938 tsm_screen_move_down(vte->con, 1, true);
941 /* CR/NL with scroll-up if needed */
942 tsm_screen_newline(vte->con);
945 /* Set tab stop at current position */
946 tsm_screen_set_tabstop(vte->con);
949 /* Move up one row, perform scroll-down if needed */
950 tsm_screen_move_up(vte->con, 1, true);
953 /* Temporarily map G2 into GL for next char only */
957 /* Temporarily map G3 into GL for next char only */
960 case 'Z': /* DECID */
961 /* Send device attributes response like ANSI DA */
962 send_primary_da(vte);
965 /* End control string */
966 /* nothing to do here */
969 /* Invoke G1 into GR */
973 /* Invoke G2 into GL */
977 /* Invoke G2 into GR */
981 /* Invoke G3 into GL */
985 /* Invoke G3 into GR */
988 case '=': /* DECKPAM */
989 /* Set application keypad mode */
990 vte->flags |= FLAG_KEYPAD_APPLICATION_MODE;
992 case '>': /* DECKPNM */
993 /* Set numeric keypad mode */
994 vte->flags &= ~FLAG_KEYPAD_APPLICATION_MODE;
998 tsm_vte_hard_reset(vte);
1000 case '7': /* DECSC */
1001 /* save console state */
1004 case '8': /* DECRC */
1005 /* restore console state */
1009 llog_debug(vte, "unhandled escape seq %u", data);
1013 static void csi_attribute(struct tsm_vte *vte)
1015 static const uint8_t bval[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
1016 unsigned int i, code;
1018 if (vte->csi_argc <= 1 && vte->csi_argv[0] == -1) {
1020 vte->csi_argv[0] = 0;
1023 for (i = 0; i < vte->csi_argc; ++i) {
1024 switch (vte->csi_argv[i]) {
1028 copy_fcolor(&vte->cattr, &vte->def_attr);
1029 copy_bcolor(&vte->cattr, &vte->def_attr);
1030 vte->cattr.bold = 0;
1031 vte->cattr.underline = 0;
1032 vte->cattr.inverse = 0;
1035 vte->cattr.bold = 1;
1038 vte->cattr.underline = 1;
1041 vte->cattr.inverse = 1;
1044 vte->cattr.bold = 0;
1047 vte->cattr.underline = 0;
1050 vte->cattr.inverse = 0;
1053 vte->cattr.fccode = COLOR_BLACK;
1056 vte->cattr.fccode = COLOR_RED;
1059 vte->cattr.fccode = COLOR_GREEN;
1062 vte->cattr.fccode = COLOR_YELLOW;
1065 vte->cattr.fccode = COLOR_BLUE;
1068 vte->cattr.fccode = COLOR_MAGENTA;
1071 vte->cattr.fccode = COLOR_CYAN;
1074 vte->cattr.fccode = COLOR_LIGHT_GREY;
1077 copy_fcolor(&vte->cattr, &vte->def_attr);
1080 vte->cattr.bccode = COLOR_BLACK;
1083 vte->cattr.bccode = COLOR_RED;
1086 vte->cattr.bccode = COLOR_GREEN;
1089 vte->cattr.bccode = COLOR_YELLOW;
1092 vte->cattr.bccode = COLOR_BLUE;
1095 vte->cattr.bccode = COLOR_MAGENTA;
1098 vte->cattr.bccode = COLOR_CYAN;
1101 vte->cattr.bccode = COLOR_LIGHT_GREY;
1104 copy_bcolor(&vte->cattr, &vte->def_attr);
1107 vte->cattr.fccode = COLOR_DARK_GREY;
1110 vte->cattr.fccode = COLOR_LIGHT_RED;
1113 vte->cattr.fccode = COLOR_LIGHT_GREEN;
1116 vte->cattr.fccode = COLOR_LIGHT_YELLOW;
1119 vte->cattr.fccode = COLOR_LIGHT_BLUE;
1122 vte->cattr.fccode = COLOR_LIGHT_MAGENTA;
1125 vte->cattr.fccode = COLOR_LIGHT_CYAN;
1128 vte->cattr.fccode = COLOR_WHITE;
1131 vte->cattr.bccode = COLOR_DARK_GREY;
1134 vte->cattr.bccode = COLOR_LIGHT_RED;
1137 vte->cattr.bccode = COLOR_LIGHT_GREEN;
1140 vte->cattr.bccode = COLOR_LIGHT_YELLOW;
1143 vte->cattr.bccode = COLOR_LIGHT_BLUE;
1146 vte->cattr.bccode = COLOR_LIGHT_MAGENTA;
1149 vte->cattr.bccode = COLOR_LIGHT_CYAN;
1152 vte->cattr.bccode = COLOR_WHITE;
1157 if (i + 2 >= vte->csi_argc ||
1158 vte->csi_argv[i + 1] != 5 ||
1159 vte->csi_argv[i + 2] < 0) {
1160 llog_debug(vte, "invalid 256color SGR");
1164 code = vte->csi_argv[i + 2];
1165 if (vte->csi_argv[i] == 38) {
1167 vte->cattr.fccode = code;
1168 } else if (code < 232) {
1169 vte->cattr.fccode = -1;
1171 vte->cattr.fb = bval[code % 6];
1173 vte->cattr.fg = bval[code % 6];
1175 vte->cattr.fr = bval[code % 6];
1177 vte->cattr.fccode = -1;
1178 code = (code - 232) * 10 + 8;
1179 vte->cattr.fr = code;
1180 vte->cattr.fg = code;
1181 vte->cattr.fb = code;
1185 vte->cattr.bccode = code;
1186 } else if (code < 232) {
1187 vte->cattr.bccode = -1;
1189 vte->cattr.bb = bval[code % 6];
1191 vte->cattr.bg = bval[code % 6];
1193 vte->cattr.br = bval[code % 6];
1195 vte->cattr.bccode = -1;
1196 code = (code - 232) * 10 + 8;
1197 vte->cattr.br = code;
1198 vte->cattr.bg = code;
1199 vte->cattr.bb = code;
1206 llog_debug(vte, "unhandled SGR attr %i",
1211 to_rgb(vte, &vte->cattr);
1212 if (vte->flags & FLAG_BACKGROUND_COLOR_ERASE_MODE)
1213 tsm_screen_set_def_attr(vte->con, &vte->cattr);
1216 static void csi_soft_reset(struct tsm_vte *vte)
1221 static void csi_compat_mode(struct tsm_vte *vte)
1223 /* always perform soft reset */
1224 csi_soft_reset(vte);
1226 if (vte->csi_argv[0] == 61) {
1227 /* Switching to VT100 compatibility mode. We do
1228 * not support this mode, so ignore it. In fact,
1229 * we are almost compatible to it, anyway, so
1230 * there is no need to explicitely select it.
1231 * However, we enable 7bit mode to avoid
1232 * character-table problems */
1233 vte->flags |= FLAG_7BIT_MODE;
1234 vte->gl = &tsm_vte_unicode_lower;
1235 vte->gr = &tsm_vte_dec_supplemental_graphics;
1236 } else if (vte->csi_argv[0] == 62 ||
1237 vte->csi_argv[0] == 63 ||
1238 vte->csi_argv[0] == 64) {
1239 /* Switching to VT2/3/4 compatibility mode. We
1240 * are always compatible with this so ignore it.
1241 * We always send 7bit controls so we also do
1242 * not care for the parameter value here that
1243 * select the control-mode.
1244 * VT220 defines argument 2 as 7bit mode but
1245 * VT3xx up to VT5xx use it as 8bit mode. We
1246 * choose to conform with the latter here.
1247 * We also enable 8bit mode when VT220
1248 * compatibility is requested explicitely. */
1249 if (vte->csi_argv[1] == 1 ||
1250 vte->csi_argv[1] == 2)
1251 vte->flags |= FLAG_USE_C1;
1253 vte->flags |= FLAG_8BIT_MODE;
1254 vte->gl = &tsm_vte_unicode_lower;
1255 vte->gr = &tsm_vte_dec_supplemental_graphics;
1257 llog_debug(vte, "unhandled DECSCL 'p' CSI %i, switching to utf-8 mode again",
1262 static inline void set_reset_flag(struct tsm_vte *vte, bool set,
1268 vte->flags &= ~flag;
1271 static void csi_mode(struct tsm_vte *vte, bool set)
1275 for (i = 0; i < vte->csi_argc; ++i) {
1276 if (!(vte->csi_flags & CSI_WHAT)) {
1277 switch (vte->csi_argv[i]) {
1281 set_reset_flag(vte, set,
1282 FLAG_KEYBOARD_ACTION_MODE);
1285 set_reset_flag(vte, set,
1286 FLAG_INSERT_REPLACE_MODE);
1288 tsm_screen_set_flags(vte->con,
1289 TSM_SCREEN_INSERT_MODE);
1291 tsm_screen_reset_flags(vte->con,
1292 TSM_SCREEN_INSERT_MODE);
1295 set_reset_flag(vte, set,
1296 FLAG_SEND_RECEIVE_MODE);
1299 set_reset_flag(vte, set,
1300 FLAG_LINE_FEED_NEW_LINE_MODE);
1303 llog_debug(vte, "unknown non-DEC (Re)Set-Mode %d",
1309 switch (vte->csi_argv[i]) {
1312 case 1: /* DECCKM */
1313 set_reset_flag(vte, set, FLAG_CURSOR_KEY_MODE);
1315 case 2: /* DECANM */
1316 /* Select VT52 mode */
1317 /* We do not support VT52 mode. Is there any reason why
1318 * we should support it? We ignore it here and do not
1319 * mark it as to-do item unless someone has strong
1320 * arguments to support it. */
1322 case 3: /* DECCOLM */
1323 /* If set, select 132 column mode, otherwise use 80
1324 * column mode. If neither is selected explicitely, we
1325 * use dynamic mode, that is, we send SIGWCH when the
1326 * size changes and we allow arbitrary buffer
1327 * dimensions. On soft-reset, we automatically fall back
1328 * to the default, that is, dynamic mode.
1329 * Dynamic-mode can be forced to a static mode in the
1330 * config. That is, everytime dynamic-mode becomes
1331 * active, the terminal will be set to the dimensions
1332 * that were selected in the config. This allows setting
1333 * a fixed size for the terminal regardless of the
1335 * TODO: Implement this */
1337 case 4: /* DECSCLM */
1338 /* Select smooth scrolling. We do not support the
1339 * classic smooth scrolling because we have a scrollback
1340 * buffer. There is no need to implement smooth
1341 * scrolling so ignore this here. */
1343 case 5: /* DECSCNM */
1344 set_reset_flag(vte, set, FLAG_INVERSE_SCREEN_MODE);
1346 tsm_screen_set_flags(vte->con,
1347 TSM_SCREEN_INVERSE);
1349 tsm_screen_reset_flags(vte->con,
1350 TSM_SCREEN_INVERSE);
1353 set_reset_flag(vte, set, FLAG_ORIGIN_MODE);
1355 tsm_screen_set_flags(vte->con,
1356 TSM_SCREEN_REL_ORIGIN);
1358 tsm_screen_reset_flags(vte->con,
1359 TSM_SCREEN_REL_ORIGIN);
1361 case 7: /* DECAWN */
1362 set_reset_flag(vte, set, FLAG_AUTO_WRAP_MODE);
1364 tsm_screen_set_flags(vte->con,
1365 TSM_SCREEN_AUTO_WRAP);
1367 tsm_screen_reset_flags(vte->con,
1368 TSM_SCREEN_AUTO_WRAP);
1370 case 8: /* DECARM */
1371 set_reset_flag(vte, set, FLAG_AUTO_REPEAT_MODE);
1373 case 12: /* blinking cursor */
1374 /* TODO: implement */
1376 case 18: /* DECPFF */
1377 /* If set, a form feed (FF) is sent to the printer after
1378 * every screen that is printed. We don't have printers
1379 * these days directly attached to terminals so we
1380 * ignore this here. */
1382 case 19: /* DECPEX */
1383 /* If set, the full screen is printed instead of
1384 * scrolling region only. We have no printer so ignore
1387 case 25: /* DECTCEM */
1388 set_reset_flag(vte, set, FLAG_TEXT_CURSOR_MODE);
1390 tsm_screen_reset_flags(vte->con,
1391 TSM_SCREEN_HIDE_CURSOR);
1393 tsm_screen_set_flags(vte->con,
1394 TSM_SCREEN_HIDE_CURSOR);
1396 case 42: /* DECNRCM */
1397 set_reset_flag(vte, set, FLAG_NATIONAL_CHARSET_MODE);
1399 case 47: /* Alternate screen buffer */
1400 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1404 tsm_screen_set_flags(vte->con,
1405 TSM_SCREEN_ALTERNATE);
1407 tsm_screen_reset_flags(vte->con,
1408 TSM_SCREEN_ALTERNATE);
1410 case 1047: /* Alternate screen buffer with post-erase */
1411 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1415 tsm_screen_set_flags(vte->con,
1416 TSM_SCREEN_ALTERNATE);
1418 tsm_screen_erase_screen(vte->con, false);
1419 tsm_screen_reset_flags(vte->con,
1420 TSM_SCREEN_ALTERNATE);
1423 case 1048: /* Set/Reset alternate-screen buffer cursor */
1424 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1429 tsm_screen_get_cursor_x(vte->con);
1431 tsm_screen_get_cursor_y(vte->con);
1433 tsm_screen_move_to(vte->con, vte->alt_cursor_x,
1437 case 1049: /* Alternate screen buffer with pre-erase+cursor */
1438 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1443 tsm_screen_get_cursor_x(vte->con);
1445 tsm_screen_get_cursor_y(vte->con);
1446 tsm_screen_set_flags(vte->con,
1447 TSM_SCREEN_ALTERNATE);
1448 tsm_screen_erase_screen(vte->con, false);
1450 tsm_screen_reset_flags(vte->con,
1451 TSM_SCREEN_ALTERNATE);
1452 tsm_screen_move_to(vte->con, vte->alt_cursor_x,
1457 llog_debug(vte, "unknown DEC %set-Mode %d",
1458 set?"S":"Res", vte->csi_argv[i]);
1464 static void csi_dev_attr(struct tsm_vte *vte)
1466 if (vte->csi_argc <= 1 && vte->csi_argv[0] <= 0) {
1467 if (vte->csi_flags == 0) {
1468 send_primary_da(vte);
1470 } else if (vte->csi_flags & CSI_GT) {
1471 vte_write(vte, "\e[>1;1;0c", 9);
1476 llog_debug(vte, "unhandled DA: %x %d %d %d...", vte->csi_flags,
1477 vte->csi_argv[0], vte->csi_argv[1], vte->csi_argv[2]);
1480 static void csi_dsr(struct tsm_vte *vte)
1483 unsigned int x, y, len;
1485 if (vte->csi_argv[0] == 5) {
1486 vte_write(vte, "\e[0n", 4);
1487 } else if (vte->csi_argv[0] == 6) {
1488 x = tsm_screen_get_cursor_x(vte->con);
1489 y = tsm_screen_get_cursor_y(vte->con);
1490 len = snprintf(buf, sizeof(buf), "\e[%u;%uR", x, y);
1491 if (len >= sizeof(buf))
1492 vte_write(vte, "\e[0;0R", 6);
1494 vte_write(vte, buf, len);
1498 static void do_csi(struct tsm_vte *vte, uint32_t data)
1500 int num, x, y, upper, lower;
1503 if (vte->csi_argc < CSI_ARG_MAX)
1508 /* move cursor up */
1509 num = vte->csi_argv[0];
1512 tsm_screen_move_up(vte->con, num, false);
1515 /* move cursor down */
1516 num = vte->csi_argv[0];
1519 tsm_screen_move_down(vte->con, num, false);
1522 /* move cursor forward */
1523 num = vte->csi_argv[0];
1526 tsm_screen_move_right(vte->con, num);
1529 /* move cursor backward */
1530 num = vte->csi_argv[0];
1533 tsm_screen_move_left(vte->con, num);
1536 /* Vertical Line Position Absolute */
1537 num = vte->csi_argv[0];
1540 x = tsm_screen_get_cursor_x(vte->con);
1541 tsm_screen_move_to(vte->con, x, num - 1);
1544 /* Vertical Line Position Relative */
1545 num = vte->csi_argv[0];
1548 x = tsm_screen_get_cursor_x(vte->con);
1549 y = tsm_screen_get_cursor_y(vte->con);
1550 tsm_screen_move_to(vte->con, x, y + num);
1554 /* position cursor */
1555 x = vte->csi_argv[0];
1558 y = vte->csi_argv[1];
1561 tsm_screen_move_to(vte->con, y - 1, x - 1);
1564 /* Cursor Character Absolute */
1565 num = vte->csi_argv[0];
1568 y = tsm_screen_get_cursor_y(vte->con);
1569 tsm_screen_move_to(vte->con, num - 1, y);
1572 if (vte->csi_flags & CSI_WHAT)
1577 if (vte->csi_argv[0] <= 0)
1578 tsm_screen_erase_cursor_to_screen(vte->con,
1580 else if (vte->csi_argv[0] == 1)
1581 tsm_screen_erase_screen_to_cursor(vte->con,
1583 else if (vte->csi_argv[0] == 2)
1584 tsm_screen_erase_screen(vte->con, protect);
1586 llog_debug(vte, "unknown parameter to CSI-J: %d",
1590 if (vte->csi_flags & CSI_WHAT)
1595 if (vte->csi_argv[0] <= 0)
1596 tsm_screen_erase_cursor_to_end(vte->con, protect);
1597 else if (vte->csi_argv[0] == 1)
1598 tsm_screen_erase_home_to_cursor(vte->con, protect);
1599 else if (vte->csi_argv[0] == 2)
1600 tsm_screen_erase_current_line(vte->con, protect);
1602 llog_debug(vte, "unknown parameter to CSI-K: %d",
1606 /* erase characters */
1607 num = vte->csi_argv[0];
1610 tsm_screen_erase_chars(vte->con, num);
1616 if (vte->csi_flags & CSI_GT) {
1617 /* xterm: select X11 visual cursor mode */
1618 csi_soft_reset(vte);
1619 } else if (vte->csi_flags & CSI_BANG) {
1620 /* DECSTR: Soft Reset */
1621 csi_soft_reset(vte);
1622 } else if (vte->csi_flags & CSI_CASH) {
1623 /* DECRQM: Request DEC Private Mode */
1624 /* If CSI_WHAT is set, then enable,
1625 * otherwise disable */
1626 csi_soft_reset(vte);
1628 /* DECSCL: Compatibility Level */
1629 /* Sometimes CSI_DQUOTE is set here, too */
1630 csi_compat_mode(vte);
1633 case 'h': /* SM: Set Mode */
1634 csi_mode(vte, true);
1636 case 'l': /* RM: Reset Mode */
1637 csi_mode(vte, false);
1639 case 'r': /* DECSTBM */
1640 /* set margin size */
1641 upper = vte->csi_argv[0];
1644 lower = vte->csi_argv[1];
1647 tsm_screen_set_margins(vte->con, upper, lower);
1650 /* device attributes */
1655 num = vte->csi_argv[0];
1658 tsm_screen_insert_lines(vte->con, num);
1662 num = vte->csi_argv[0];
1665 tsm_screen_delete_lines(vte->con, num);
1668 /* tabulation clear */
1669 num = vte->csi_argv[0];
1671 tsm_screen_reset_tabstop(vte->con);
1673 tsm_screen_reset_all_tabstops(vte->con);
1675 llog_debug(vte, "invalid parameter %d to TBC CSI", num);
1678 /* insert characters */
1679 num = vte->csi_argv[0];
1682 tsm_screen_insert_chars(vte->con, num);
1685 /* delete characters */
1686 num = vte->csi_argv[0];
1689 tsm_screen_delete_chars(vte->con, num);
1692 /* cursor horizontal backwards tab */
1693 num = vte->csi_argv[0];
1696 tsm_screen_tab_left(vte->con, num);
1699 /* cursor horizontal forward tab */
1700 num = vte->csi_argv[0];
1703 tsm_screen_tab_right(vte->con, num);
1706 /* device status reports */
1711 num = vte->csi_argv[0];
1714 tsm_screen_scroll_up(vte->con, num);
1718 num = vte->csi_argv[0];
1721 tsm_screen_scroll_down(vte->con, num);
1724 llog_debug(vte, "unhandled CSI sequence %c", data);
1728 /* map a character according to current GL and GR maps */
1729 static uint32_t vte_map(struct tsm_vte *vte, uint32_t val)
1731 /* 32, 127, 160 and 255 map to identity like all values >255 */
1735 val = (*vte->glt)[val - 32];
1738 val = (*vte->gl)[val - 32];
1743 val = (*vte->grt)[val - 160];
1746 val = (*vte->gr)[val - 160];
1754 /* perform parser action */
1755 static void do_action(struct tsm_vte *vte, uint32_t data, int action)
1764 /* ignore character */
1767 sym = tsm_symbol_make(vte_map(vte, data));
1768 write_console(vte, sym);
1770 case ACTION_EXECUTE:
1771 do_execute(vte, data);
1776 case ACTION_COLLECT:
1777 do_collect(vte, data);
1780 do_param(vte, data);
1782 case ACTION_ESC_DISPATCH:
1785 case ACTION_CSI_DISPATCH:
1788 case ACTION_DCS_START:
1790 case ACTION_DCS_COLLECT:
1792 case ACTION_DCS_END:
1794 case ACTION_OSC_START:
1796 case ACTION_OSC_COLLECT:
1798 case ACTION_OSC_END:
1801 llog_warn(vte, "invalid action %d", action);
1805 /* entry actions to be performed when entering the selected state */
1806 static const int entry_action[] = {
1807 [STATE_CSI_ENTRY] = ACTION_CLEAR,
1808 [STATE_DCS_ENTRY] = ACTION_CLEAR,
1809 [STATE_DCS_PASS] = ACTION_DCS_START,
1810 [STATE_ESC] = ACTION_CLEAR,
1811 [STATE_OSC_STRING] = ACTION_OSC_START,
1812 [STATE_NUM] = ACTION_NONE,
1815 /* exit actions to be performed when leaving the selected state */
1816 static const int exit_action[] = {
1817 [STATE_DCS_PASS] = ACTION_DCS_END,
1818 [STATE_OSC_STRING] = ACTION_OSC_END,
1819 [STATE_NUM] = ACTION_NONE,
1822 /* perform state transision and dispatch related actions */
1823 static void do_trans(struct tsm_vte *vte, uint32_t data, int state, int act)
1825 if (state != STATE_NONE) {
1826 /* A state transition occurs. Perform exit-action,
1827 * transition-action and entry-action. Even when performing a
1828 * transition to the same state as the current state we do this.
1829 * Use STATE_NONE if this is not the desired behavior.
1831 do_action(vte, data, exit_action[vte->state]);
1832 do_action(vte, data, act);
1833 do_action(vte, data, entry_action[state]);
1836 do_action(vte, data, act);
1841 * Escape sequence parser
1842 * This parses the new input character \data. It performs state transition and
1843 * calls the right callbacks for each action.
1845 static void parse_data(struct tsm_vte *vte, uint32_t raw)
1847 /* events that may occur in any state */
1856 do_trans(vte, raw, STATE_GROUND, ACTION_EXECUTE);
1859 do_trans(vte, raw, STATE_ESC, ACTION_NONE);
1864 do_trans(vte, raw, STATE_ST_IGNORE, ACTION_NONE);
1867 do_trans(vte, raw, STATE_DCS_ENTRY, ACTION_NONE);
1870 do_trans(vte, raw, STATE_OSC_STRING, ACTION_NONE);
1873 do_trans(vte, raw, STATE_CSI_ENTRY, ACTION_NONE);
1877 /* events that depend on the current state */
1878 switch (vte->state) {
1887 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1890 do_trans(vte, raw, STATE_NONE, ACTION_PRINT);
1893 do_trans(vte, raw, STATE_NONE, ACTION_PRINT);
1900 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1903 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1906 do_trans(vte, raw, STATE_ESC_INT, ACTION_COLLECT);
1914 do_trans(vte, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1917 do_trans(vte, raw, STATE_CSI_ENTRY, ACTION_NONE);
1920 do_trans(vte, raw, STATE_OSC_STRING, ACTION_NONE);
1923 do_trans(vte, raw, STATE_DCS_ENTRY, ACTION_NONE);
1928 do_trans(vte, raw, STATE_ST_IGNORE, ACTION_NONE);
1931 do_trans(vte, raw, STATE_ESC_INT, ACTION_COLLECT);
1938 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1941 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1944 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1947 do_trans(vte, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1950 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1952 case STATE_CSI_ENTRY:
1957 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1960 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1963 do_trans(vte, raw, STATE_CSI_INT, ACTION_COLLECT);
1966 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1970 do_trans(vte, raw, STATE_CSI_PARAM, ACTION_PARAM);
1973 do_trans(vte, raw, STATE_CSI_PARAM, ACTION_COLLECT);
1976 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1979 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1981 case STATE_CSI_PARAM:
1986 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1990 do_trans(vte, raw, STATE_NONE, ACTION_PARAM);
1993 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1997 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2000 do_trans(vte, raw, STATE_CSI_INT, ACTION_COLLECT);
2003 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
2006 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2013 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
2016 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
2019 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2022 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2025 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
2028 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2030 case STATE_CSI_IGNORE:
2035 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
2039 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2042 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2045 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2047 case STATE_DCS_ENTRY:
2053 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2056 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2059 do_trans(vte, raw, STATE_DCS_INT, ACTION_COLLECT);
2063 do_trans(vte, raw, STATE_DCS_PARAM, ACTION_PARAM);
2066 do_trans(vte, raw, STATE_DCS_PARAM, ACTION_COLLECT);
2069 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2072 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2074 case STATE_DCS_PARAM:
2080 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2084 do_trans(vte, raw, STATE_NONE, ACTION_PARAM);
2088 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2091 do_trans(vte, raw, STATE_DCS_INT, ACTION_COLLECT);
2094 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2097 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2105 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2108 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
2111 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2114 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2117 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2119 case STATE_DCS_PASS:
2125 do_trans(vte, raw, STATE_NONE, ACTION_DCS_COLLECT);
2128 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2131 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2134 do_trans(vte, raw, STATE_NONE, ACTION_DCS_COLLECT);
2136 case STATE_DCS_IGNORE:
2142 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2145 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2148 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2150 case STATE_OSC_STRING:
2156 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2159 do_trans(vte, raw, STATE_NONE, ACTION_OSC_COLLECT);
2163 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2166 do_trans(vte, raw, STATE_NONE, ACTION_OSC_COLLECT);
2168 case STATE_ST_IGNORE:
2174 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2177 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2180 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2184 llog_warn(vte, "unhandled input %u in state %d", raw, vte->state);
2187 void tsm_vte_input(struct tsm_vte *vte, const char *u8, size_t len)
2193 if (!vte || !vte->con)
2197 for (i = 0; i < len; ++i) {
2198 if (vte->flags & FLAG_7BIT_MODE) {
2200 llog_debug(vte, "receiving 8bit character U+%d from pty while in 7bit mode",
2202 parse_data(vte, u8[i] & 0x7f);
2203 } else if (vte->flags & FLAG_8BIT_MODE) {
2204 parse_data(vte, u8[i]);
2206 state = tsm_utf8_mach_feed(vte->mach, u8[i]);
2207 if (state == TSM_UTF8_ACCEPT ||
2208 state == TSM_UTF8_REJECT) {
2209 ucs4 = tsm_utf8_mach_get(vte->mach);
2210 parse_data(vte, ucs4);
2217 bool tsm_vte_handle_keyboard(struct tsm_vte *vte, uint32_t keysym,
2218 uint32_t ascii, unsigned int mods,
2225 /* MOD1 (mostly labeled 'Alt') prepends an escape character to every
2226 * input that is sent by a key.
2227 * TODO: Transform this huge handler into a lookup table to save a lot
2228 * of code and make such modifiers easier to implement.
2229 * Also check whether altSendsEscape should be the default (xterm
2230 * disables this by default, why?) and whether we should implement the
2231 * fallback shifting that xterm does. */
2232 if (mods & TSM_ALT_MASK)
2233 vte->flags |= FLAG_PREPEND_ESCAPE;
2235 /* A user might actually use multiple layouts for keyboard input. The
2236 * @keysym variable contains the actual keysym that the user used. But
2237 * if this keysym is not in the ascii range, the input handler does
2238 * check all other layouts that the user specified whether one of them
2239 * maps the key to some ASCII keysym and provides this via @ascii.
2240 * We always use the real keysym except when handling CTRL+<XY>
2241 * shortcuts we use the ascii keysym. This is for compatibility to xterm
2242 * et. al. so ctrl+c always works regardless of the currently active
2244 * But if no ascii-sym is found, we still use the real keysym. */
2246 if (sym == XKB_KEY_NoSymbol)
2249 if (mods & TSM_CONTROL_MASK) {
2253 vte_write(vte, "\x00", 1);
2257 vte_write(vte, "\x01", 1);
2261 vte_write(vte, "\x02", 1);
2265 vte_write(vte, "\x03", 1);
2269 vte_write(vte, "\x04", 1);
2273 vte_write(vte, "\x05", 1);
2277 vte_write(vte, "\x06", 1);
2281 vte_write(vte, "\x07", 1);
2285 vte_write(vte, "\x08", 1);
2289 vte_write(vte, "\x09", 1);
2293 vte_write(vte, "\x0a", 1);
2297 vte_write(vte, "\x0b", 1);
2301 vte_write(vte, "\x0c", 1);
2305 vte_write(vte, "\x0d", 1);
2309 vte_write(vte, "\x0e", 1);
2313 vte_write(vte, "\x0f", 1);
2317 vte_write(vte, "\x10", 1);
2321 vte_write(vte, "\x11", 1);
2325 vte_write(vte, "\x12", 1);
2329 vte_write(vte, "\x13", 1);
2333 vte_write(vte, "\x14", 1);
2337 vte_write(vte, "\x15", 1);
2341 vte_write(vte, "\x16", 1);
2345 vte_write(vte, "\x17", 1);
2349 vte_write(vte, "\x18", 1);
2353 vte_write(vte, "\x19", 1);
2357 vte_write(vte, "\x1a", 1);
2360 case XKB_KEY_bracketleft:
2361 case XKB_KEY_braceleft:
2362 vte_write(vte, "\x1b", 1);
2365 case XKB_KEY_backslash:
2367 vte_write(vte, "\x1c", 1);
2370 case XKB_KEY_bracketright:
2371 case XKB_KEY_braceright:
2372 vte_write(vte, "\x1d", 1);
2376 case XKB_KEY_asciitilde:
2377 vte_write(vte, "\x1e", 1);
2381 case XKB_KEY_question:
2382 vte_write(vte, "\x1f", 1);
2385 vte_write(vte, "\x7f", 1);
2391 case XKB_KEY_BackSpace:
2392 vte_write(vte, "\x08", 1);
2395 case XKB_KEY_KP_Tab:
2396 vte_write(vte, "\x09", 1);
2398 case XKB_KEY_ISO_Left_Tab:
2399 vte_write(vte, "\e[Z", 3);
2401 case XKB_KEY_Linefeed:
2402 vte_write(vte, "\x0a", 1);
2405 vte_write(vte, "\x0b", 1);
2408 TODO: What should we do with this key? Sending XOFF is awful as
2409 there is no simple way on modern keyboards to send XON
2410 again. If someone wants this, we can re-eanble it and set
2413 vte_write(vte, "\x13", 1);
2417 TODO: What should we do on scroll-lock? Sending 0x14 is what
2418 the specs say but it is not used today the way most
2419 users would expect so we disable it. If someone wants
2420 this, we can re-enable it and set some flag.
2421 case XKB_KEY_Scroll_Lock:
2422 vte_write(vte, "\x14", 1);
2425 case XKB_KEY_Sys_Req:
2426 vte_write(vte, "\x15", 1);
2428 case XKB_KEY_Escape:
2429 vte_write(vte, "\x1b", 1);
2431 case XKB_KEY_KP_Enter:
2432 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE) {
2433 vte_write(vte, "\eOM", 3);
2437 case XKB_KEY_Return:
2438 if (vte->flags & FLAG_LINE_FEED_NEW_LINE_MODE)
2439 vte_write(vte, "\x0d\x0a", 2);
2441 vte_write(vte, "\x0d", 1);
2444 vte_write(vte, "\e[1~", 4);
2446 case XKB_KEY_Insert:
2447 vte_write(vte, "\e[2~", 4);
2449 case XKB_KEY_Delete:
2450 vte_write(vte, "\e[3~", 4);
2452 case XKB_KEY_Select:
2453 vte_write(vte, "\e[4~", 4);
2455 case XKB_KEY_Page_Up:
2456 case XKB_KEY_KP_Page_Up:
2457 vte_write(vte, "\e[5~", 4);
2459 case XKB_KEY_KP_Page_Down:
2460 case XKB_KEY_Page_Down:
2461 vte_write(vte, "\e[6~", 4);
2465 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2466 vte_write(vte, "\eOA", 3);
2468 vte_write(vte, "\e[A", 3);
2471 case XKB_KEY_KP_Down:
2472 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2473 vte_write(vte, "\eOB", 3);
2475 vte_write(vte, "\e[B", 3);
2478 case XKB_KEY_KP_Right:
2479 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2480 vte_write(vte, "\eOC", 3);
2482 vte_write(vte, "\e[C", 3);
2485 case XKB_KEY_KP_Left:
2486 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2487 vte_write(vte, "\eOD", 3);
2489 vte_write(vte, "\e[D", 3);
2491 case XKB_KEY_KP_Insert:
2493 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2494 vte_write(vte, "\eOp", 3);
2496 vte_write(vte, "0", 1);
2499 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2500 vte_write(vte, "\eOq", 3);
2502 vte_write(vte, "1", 1);
2505 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2506 vte_write(vte, "\eOr", 3);
2508 vte_write(vte, "2", 1);
2511 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2512 vte_write(vte, "\eOs", 3);
2514 vte_write(vte, "3", 1);
2517 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2518 vte_write(vte, "\eOt", 3);
2520 vte_write(vte, "4", 1);
2523 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2524 vte_write(vte, "\eOu", 3);
2526 vte_write(vte, "5", 1);
2529 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2530 vte_write(vte, "\eOv", 3);
2532 vte_write(vte, "6", 1);
2535 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2536 vte_write(vte, "\eOw", 3);
2538 vte_write(vte, "7", 1);
2541 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2542 vte_write(vte, "\eOx", 3);
2544 vte_write(vte, "8", 1);
2547 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2548 vte_write(vte, "\eOy", 3);
2550 vte_write(vte, "9", 1);
2552 case XKB_KEY_KP_Subtract:
2553 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2554 vte_write(vte, "\eOm", 3);
2556 vte_write(vte, "-", 1);
2558 case XKB_KEY_KP_Separator:
2559 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2560 vte_write(vte, "\eOl", 3);
2562 vte_write(vte, ",", 1);
2564 case XKB_KEY_KP_Delete:
2565 case XKB_KEY_KP_Decimal:
2566 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2567 vte_write(vte, "\eOn", 3);
2569 vte_write(vte, ".", 1);
2571 case XKB_KEY_KP_Equal:
2572 case XKB_KEY_KP_Divide:
2573 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2574 vte_write(vte, "\eOj", 3);
2576 vte_write(vte, "/", 1);
2578 case XKB_KEY_KP_Multiply:
2579 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2580 vte_write(vte, "\eOo", 3);
2582 vte_write(vte, "*", 1);
2584 case XKB_KEY_KP_Add:
2585 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2586 vte_write(vte, "\eOk", 3);
2588 vte_write(vte, "+", 1);
2591 case XKB_KEY_KP_Home:
2592 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2593 vte_write(vte, "\eOH", 3);
2595 vte_write(vte, "\e[H", 3);
2598 case XKB_KEY_KP_End:
2599 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2600 vte_write(vte, "\eOF", 3);
2602 vte_write(vte, "\e[F", 3);
2604 case XKB_KEY_KP_Space:
2605 vte_write(vte, " ", 1);
2607 /* TODO: check what to transmit for functions keys when
2608 * shift/ctrl etc. are pressed. Every terminal behaves
2609 * differently here which is really weird.
2610 * We now map F4 to F14 if shift is pressed and so on for all
2611 * keys. However, such mappings should rather be done via
2612 * xkb-configurations and we should instead add a flags argument
2613 * to the CSIs as some of the keys here already do. */
2616 if (mods & TSM_SHIFT_MASK)
2617 vte_write(vte, "\e[23~", 5);
2619 vte_write(vte, "\eOP", 3);
2623 if (mods & TSM_SHIFT_MASK)
2624 vte_write(vte, "\e[24~", 5);
2626 vte_write(vte, "\eOQ", 3);
2630 if (mods & TSM_SHIFT_MASK)
2631 vte_write(vte, "\e[25~", 5);
2633 vte_write(vte, "\eOR", 3);
2637 if (mods & TSM_SHIFT_MASK)
2638 //vte_write(vte, "\e[1;2S", 6);
2639 vte_write(vte, "\e[26~", 5);
2641 vte_write(vte, "\eOS", 3);
2644 if (mods & TSM_SHIFT_MASK)
2645 //vte_write(vte, "\e[15;2~", 7);
2646 vte_write(vte, "\e[28~", 5);
2648 vte_write(vte, "\e[15~", 5);
2651 if (mods & TSM_SHIFT_MASK)
2652 //vte_write(vte, "\e[17;2~", 7);
2653 vte_write(vte, "\e[29~", 5);
2655 vte_write(vte, "\e[17~", 5);
2658 if (mods & TSM_SHIFT_MASK)
2659 //vte_write(vte, "\e[18;2~", 7);
2660 vte_write(vte, "\e[31~", 5);
2662 vte_write(vte, "\e[18~", 5);
2665 if (mods & TSM_SHIFT_MASK)
2666 //vte_write(vte, "\e[19;2~", 7);
2667 vte_write(vte, "\e[32~", 5);
2669 vte_write(vte, "\e[19~", 5);
2672 if (mods & TSM_SHIFT_MASK)
2673 //vte_write(vte, "\e[20;2~", 7);
2674 vte_write(vte, "\e[33~", 5);
2676 vte_write(vte, "\e[20~", 5);
2679 if (mods & TSM_SHIFT_MASK)
2680 //vte_write(vte, "\e[21;2~", 7);
2681 vte_write(vte, "\e[34~", 5);
2683 vte_write(vte, "\e[21~", 5);
2686 if (mods & TSM_SHIFT_MASK)
2687 vte_write(vte, "\e[23;2~", 7);
2689 vte_write(vte, "\e[23~", 5);
2692 if (mods & TSM_SHIFT_MASK)
2693 vte_write(vte, "\e[24;2~", 7);
2695 vte_write(vte, "\e[24~", 5);
2698 if (mods & TSM_SHIFT_MASK)
2699 vte_write(vte, "\e[25;2~", 7);
2701 vte_write(vte, "\e[25~", 5);
2704 if (mods & TSM_SHIFT_MASK)
2705 vte_write(vte, "\e[26;2~", 7);
2707 vte_write(vte, "\e[26~", 5);
2710 if (mods & TSM_SHIFT_MASK)
2711 vte_write(vte, "\e[28;2~", 7);
2713 vte_write(vte, "\e[28~", 5);
2716 if (mods & TSM_SHIFT_MASK)
2717 vte_write(vte, "\e[29;2~", 7);
2719 vte_write(vte, "\e[29~", 5);
2722 if (mods & TSM_SHIFT_MASK)
2723 vte_write(vte, "\e[31;2~", 7);
2725 vte_write(vte, "\e[31~", 5);
2728 if (mods & TSM_SHIFT_MASK)
2729 vte_write(vte, "\e[32;2~", 7);
2731 vte_write(vte, "\e[32~", 5);
2734 if (mods & TSM_SHIFT_MASK)
2735 vte_write(vte, "\e[33;2~", 7);
2737 vte_write(vte, "\e[33~", 5);
2740 if (mods & TSM_SHIFT_MASK)
2741 vte_write(vte, "\e[34;2~", 7);
2743 vte_write(vte, "\e[34~", 5);
2747 if (unicode != TSM_VTE_INVALID) {
2748 if (vte->flags & FLAG_7BIT_MODE) {
2750 if (unicode & 0x80) {
2751 llog_debug(vte, "invalid keyboard input in 7bit mode U+%x; mapping to '?'",
2755 vte_write(vte, &val, 1);
2756 } else if (vte->flags & FLAG_8BIT_MODE) {
2758 if (unicode > 0xff) {
2759 llog_debug(vte, "invalid keyboard input in 8bit mode U+%x; mapping to '?'",
2763 vte_write_raw(vte, &val, 1);
2765 len = tsm_ucs4_to_utf8(tsm_symbol_make(unicode), u8);
2766 vte_write_raw(vte, u8, len);
2771 vte->flags &= ~FLAG_PREPEND_ESCAPE;