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>
58 #include "tsm_screen.h"
59 #include "tsm_unicode.h"
62 #define LLOG_SUBSYSTEM "tsm_vte"
64 /* Input parser states */
66 STATE_NONE, /* placeholder */
67 STATE_GROUND, /* initial state and ground */
68 STATE_ESC, /* ESC sequence was started */
69 STATE_ESC_INT, /* intermediate escape characters */
70 STATE_CSI_ENTRY, /* starting CSI sequence */
71 STATE_CSI_PARAM, /* CSI parameters */
72 STATE_CSI_INT, /* intermediate CSI characters */
73 STATE_CSI_IGNORE, /* CSI error; ignore this CSI sequence */
74 STATE_DCS_ENTRY, /* starting DCS sequence */
75 STATE_DCS_PARAM, /* DCS parameters */
76 STATE_DCS_INT, /* intermediate DCS characters */
77 STATE_DCS_PASS, /* DCS data passthrough */
78 STATE_DCS_IGNORE, /* DCS error; ignore this DCS sequence */
79 STATE_OSC_STRING, /* parsing OCS sequence */
80 STATE_ST_IGNORE, /* unimplemented seq; ignore until ST */
84 /* Input parser actions */
86 ACTION_NONE, /* placeholder */
87 ACTION_IGNORE, /* ignore the character entirely */
88 ACTION_PRINT, /* print the character on the console */
89 ACTION_EXECUTE, /* execute single control character (C0/C1) */
90 ACTION_CLEAR, /* clear current parameter state */
91 ACTION_COLLECT, /* collect intermediate character */
92 ACTION_PARAM, /* collect parameter character */
93 ACTION_ESC_DISPATCH, /* dispatch escape sequence */
94 ACTION_CSI_DISPATCH, /* dispatch csi sequence */
95 ACTION_DCS_START, /* start of DCS data */
96 ACTION_DCS_COLLECT, /* collect DCS data */
97 ACTION_DCS_END, /* end of DCS data */
98 ACTION_OSC_START, /* start of OSC data */
99 ACTION_OSC_COLLECT, /* collect OSC data */
100 ACTION_OSC_END, /* end of OSC data */
105 #define CSI_BANG 0x0001 /* CSI: ! */
106 #define CSI_CASH 0x0002 /* CSI: $ */
107 #define CSI_WHAT 0x0004 /* CSI: ? */
108 #define CSI_GT 0x0008 /* CSI: > */
109 #define CSI_SPACE 0x0010 /* CSI: */
110 #define CSI_SQUOTE 0x0020 /* CSI: ' */
111 #define CSI_DQUOTE 0x0040 /* CSI: " */
112 #define CSI_MULT 0x0080 /* CSI: * */
113 #define CSI_PLUS 0x0100 /* CSI: + */
114 #define CSI_POPEN 0x0200 /* CSI: ( */
115 #define CSI_PCLOSE 0x0400 /* CSI: ) */
117 /* max CSI arguments */
118 #define CSI_ARG_MAX 16
121 #define FLAG_CURSOR_KEY_MODE 0x00000001 /* DEC cursor key mode */
122 #define FLAG_KEYPAD_APPLICATION_MODE 0x00000002 /* DEC keypad application mode; TODO: toggle on numlock? */
123 #define FLAG_LINE_FEED_NEW_LINE_MODE 0x00000004 /* DEC line-feed/new-line mode */
124 #define FLAG_8BIT_MODE 0x00000008 /* Disable UTF-8 mode and enable 8bit compatible mode */
125 #define FLAG_7BIT_MODE 0x00000010 /* Disable 8bit mode and use 7bit compatible mode */
126 #define FLAG_USE_C1 0x00000020 /* Explicitly use 8bit C1 codes; TODO: implement */
127 #define FLAG_KEYBOARD_ACTION_MODE 0x00000040 /* Disable keyboard; TODO: implement? */
128 #define FLAG_INSERT_REPLACE_MODE 0x00000080 /* Enable insert mode */
129 #define FLAG_SEND_RECEIVE_MODE 0x00000100 /* Disable local echo */
130 #define FLAG_TEXT_CURSOR_MODE 0x00000200 /* Show cursor */
131 #define FLAG_INVERSE_SCREEN_MODE 0x00000400 /* Inverse colors */
132 #define FLAG_ORIGIN_MODE 0x00000800 /* Relative origin for cursor */
133 #define FLAG_AUTO_WRAP_MODE 0x00001000 /* Auto line wrap mode */
134 #define FLAG_AUTO_REPEAT_MODE 0x00002000 /* Auto repeat key press; TODO: implement */
135 #define FLAG_NATIONAL_CHARSET_MODE 0x00004000 /* Send keys from nation charsets; TODO: implement */
136 #define FLAG_BACKGROUND_COLOR_ERASE_MODE 0x00008000 /* Set background color on erase (bce) */
137 #define FLAG_PREPEND_ESCAPE 0x00010000 /* Prepend escape character to next output */
138 #define FLAG_TITE_INHIBIT_MODE 0x00020000 /* Prevent switching to alternate screen buffer */
140 struct vte_saved_state {
141 unsigned int cursor_x;
142 unsigned int cursor_y;
143 struct tsm_screen_attr cattr;
144 tsm_vte_charset **gl;
145 tsm_vte_charset **gr;
154 struct tsm_screen *con;
155 tsm_vte_write_cb write_cb;
159 struct tsm_utf8_mach *mach;
160 unsigned long parse_cnt;
163 unsigned int csi_argc;
164 int csi_argv[CSI_ARG_MAX];
165 unsigned int csi_flags;
167 uint8_t (*palette)[3];
168 struct tsm_screen_attr def_attr;
169 struct tsm_screen_attr cattr;
172 tsm_vte_charset **gl;
173 tsm_vte_charset **gr;
174 tsm_vte_charset **glt;
175 tsm_vte_charset **grt;
181 struct vte_saved_state saved_state;
182 unsigned int alt_cursor_x;
183 unsigned int alt_cursor_y;
208 static uint8_t color_palette[COLOR_NUM][3] = {
209 [COLOR_BLACK] = { 0, 0, 0 }, /* black */
210 [COLOR_RED] = { 205, 0, 0 }, /* red */
211 [COLOR_GREEN] = { 0, 205, 0 }, /* green */
212 [COLOR_YELLOW] = { 205, 205, 0 }, /* yellow */
213 [COLOR_BLUE] = { 0, 0, 238 }, /* blue */
214 [COLOR_MAGENTA] = { 205, 0, 205 }, /* magenta */
215 [COLOR_CYAN] = { 0, 205, 205 }, /* cyan */
216 [COLOR_LIGHT_GREY] = { 229, 229, 229 }, /* light grey */
217 [COLOR_DARK_GREY] = { 127, 127, 127 }, /* dark grey */
218 [COLOR_LIGHT_RED] = { 255, 0, 0 }, /* light red */
219 [COLOR_LIGHT_GREEN] = { 0, 255, 0 }, /* light green */
220 [COLOR_LIGHT_YELLOW] = { 255, 255, 0 }, /* light yellow */
221 [COLOR_LIGHT_BLUE] = { 92, 92, 255 }, /* light blue */
222 [COLOR_LIGHT_MAGENTA] = { 255, 0, 255 }, /* light magenta */
223 [COLOR_LIGHT_CYAN] = { 0, 255, 255 }, /* light cyan */
224 [COLOR_WHITE] = { 255, 255, 255 }, /* white */
226 [COLOR_FOREGROUND] = { 229, 229, 229 }, /* light grey */
227 [COLOR_BACKGROUND] = { 0, 0, 0 }, /* black */
230 static uint8_t color_palette_solarized[COLOR_NUM][3] = {
231 [COLOR_BLACK] = { 7, 54, 66 }, /* black */
232 [COLOR_RED] = { 220, 50, 47 }, /* red */
233 [COLOR_GREEN] = { 133, 153, 0 }, /* green */
234 [COLOR_YELLOW] = { 181, 137, 0 }, /* yellow */
235 [COLOR_BLUE] = { 38, 139, 210 }, /* blue */
236 [COLOR_MAGENTA] = { 211, 54, 130 }, /* magenta */
237 [COLOR_CYAN] = { 42, 161, 152 }, /* cyan */
238 [COLOR_LIGHT_GREY] = { 238, 232, 213 }, /* light grey */
239 [COLOR_DARK_GREY] = { 0, 43, 54 }, /* dark grey */
240 [COLOR_LIGHT_RED] = { 203, 75, 22 }, /* light red */
241 [COLOR_LIGHT_GREEN] = { 88, 110, 117 }, /* light green */
242 [COLOR_LIGHT_YELLOW] = { 101, 123, 131 }, /* light yellow */
243 [COLOR_LIGHT_BLUE] = { 131, 148, 150 }, /* light blue */
244 [COLOR_LIGHT_MAGENTA] = { 108, 113, 196 }, /* light magenta */
245 [COLOR_LIGHT_CYAN] = { 147, 161, 161 }, /* light cyan */
246 [COLOR_WHITE] = { 253, 246, 227 }, /* white */
248 [COLOR_FOREGROUND] = { 238, 232, 213 }, /* light grey */
249 [COLOR_BACKGROUND] = { 7, 54, 66 }, /* black */
252 static uint8_t color_palette_solarized_black[COLOR_NUM][3] = {
253 [COLOR_BLACK] = { 0, 0, 0 }, /* black */
254 [COLOR_RED] = { 220, 50, 47 }, /* red */
255 [COLOR_GREEN] = { 133, 153, 0 }, /* green */
256 [COLOR_YELLOW] = { 181, 137, 0 }, /* yellow */
257 [COLOR_BLUE] = { 38, 139, 210 }, /* blue */
258 [COLOR_MAGENTA] = { 211, 54, 130 }, /* magenta */
259 [COLOR_CYAN] = { 42, 161, 152 }, /* cyan */
260 [COLOR_LIGHT_GREY] = { 238, 232, 213 }, /* light grey */
261 [COLOR_DARK_GREY] = { 0, 43, 54 }, /* dark grey */
262 [COLOR_LIGHT_RED] = { 203, 75, 22 }, /* light red */
263 [COLOR_LIGHT_GREEN] = { 88, 110, 117 }, /* light green */
264 [COLOR_LIGHT_YELLOW] = { 101, 123, 131 }, /* light yellow */
265 [COLOR_LIGHT_BLUE] = { 131, 148, 150 }, /* light blue */
266 [COLOR_LIGHT_MAGENTA] = { 108, 113, 196 }, /* light magenta */
267 [COLOR_LIGHT_CYAN] = { 147, 161, 161 }, /* light cyan */
268 [COLOR_WHITE] = { 253, 246, 227 }, /* white */
270 [COLOR_FOREGROUND] = { 238, 232, 213 }, /* light grey */
271 [COLOR_BACKGROUND] = { 0, 0, 0 }, /* black */
274 static uint8_t color_palette_solarized_white[COLOR_NUM][3] = {
275 [COLOR_BLACK] = { 7, 54, 66 }, /* black */
276 [COLOR_RED] = { 220, 50, 47 }, /* red */
277 [COLOR_GREEN] = { 133, 153, 0 }, /* green */
278 [COLOR_YELLOW] = { 181, 137, 0 }, /* yellow */
279 [COLOR_BLUE] = { 38, 139, 210 }, /* blue */
280 [COLOR_MAGENTA] = { 211, 54, 130 }, /* magenta */
281 [COLOR_CYAN] = { 42, 161, 152 }, /* cyan */
282 [COLOR_LIGHT_GREY] = { 238, 232, 213 }, /* light grey */
283 [COLOR_DARK_GREY] = { 0, 43, 54 }, /* dark grey */
284 [COLOR_LIGHT_RED] = { 203, 75, 22 }, /* light red */
285 [COLOR_LIGHT_GREEN] = { 88, 110, 117 }, /* light green */
286 [COLOR_LIGHT_YELLOW] = { 101, 123, 131 }, /* light yellow */
287 [COLOR_LIGHT_BLUE] = { 131, 148, 150 }, /* light blue */
288 [COLOR_LIGHT_MAGENTA] = { 108, 113, 196 }, /* light magenta */
289 [COLOR_LIGHT_CYAN] = { 147, 161, 161 }, /* light cyan */
290 [COLOR_WHITE] = { 253, 246, 227 }, /* white */
292 [COLOR_FOREGROUND] = { 7, 54, 66 }, /* black */
293 [COLOR_BACKGROUND] = { 238, 232, 213 }, /* light grey */
296 static uint8_t (*get_palette(struct tsm_vte *vte))[3]
298 if (!vte->palette_name)
299 return color_palette;
301 if (!strcmp(vte->palette_name, "solarized"))
302 return color_palette_solarized;
303 if (!strcmp(vte->palette_name, "solarized-black"))
304 return color_palette_solarized_black;
305 if (!strcmp(vte->palette_name, "solarized-white"))
306 return color_palette_solarized_white;
308 return color_palette;
311 /* Several effects may occur when non-RGB colors are used. For instance, if bold
312 * is enabled, then a dark color code is always converted to a light color to
313 * simulate bold (even though bold may actually be supported!). To support this,
314 * we need to differentiate between a set color-code and a set rgb-color.
315 * This function actually converts a set color-code into an RGB color. This must
316 * be called before passing the attribute to the console layer so the console
317 * layer can always work with RGB values and does not have to care for color
319 static void to_rgb(struct tsm_vte *vte, struct tsm_screen_attr *attr)
325 /* bold causes light colors */
326 if (attr->bold && code < 8)
328 if (code >= COLOR_NUM)
329 code = COLOR_FOREGROUND;
331 attr->fr = vte->palette[code][0];
332 attr->fg = vte->palette[code][1];
333 attr->fb = vte->palette[code][2];
338 if (code >= COLOR_NUM)
339 code = COLOR_BACKGROUND;
341 attr->br = vte->palette[code][0];
342 attr->bg = vte->palette[code][1];
343 attr->bb = vte->palette[code][2];
347 static void copy_fcolor(struct tsm_screen_attr *dest,
348 const struct tsm_screen_attr *src)
350 dest->fccode = src->fccode;
356 static void copy_bcolor(struct tsm_screen_attr *dest,
357 const struct tsm_screen_attr *src)
359 dest->bccode = src->bccode;
366 int tsm_vte_new(struct tsm_vte **out, struct tsm_screen *con,
367 tsm_vte_write_cb write_cb, void *data,
368 tsm_log_t log, void *log_data)
373 if (!out || !con || !write_cb)
376 vte = malloc(sizeof(*vte));
380 memset(vte, 0, sizeof(*vte));
383 vte->llog_data = log_data;
385 vte->write_cb = write_cb;
387 vte->palette = get_palette(vte);
388 vte->def_attr.fccode = COLOR_FOREGROUND;
389 vte->def_attr.bccode = COLOR_BACKGROUND;
390 to_rgb(vte, &vte->def_attr);
392 ret = tsm_utf8_mach_new(&vte->mach);
397 tsm_screen_erase_screen(vte->con, false);
399 llog_debug(vte, "new vte object");
400 tsm_screen_ref(vte->con);
410 void tsm_vte_ref(struct tsm_vte *vte)
419 void tsm_vte_unref(struct tsm_vte *vte)
421 if (!vte || !vte->ref)
427 llog_debug(vte, "destroying vte object");
428 tsm_screen_unref(vte->con);
429 tsm_utf8_mach_free(vte->mach);
434 int tsm_vte_set_palette(struct tsm_vte *vte, const char *palette)
442 tmp = strdup(palette);
447 free(vte->palette_name);
448 vte->palette_name = tmp;
450 vte->palette = get_palette(vte);
451 vte->def_attr.fccode = COLOR_FOREGROUND;
452 vte->def_attr.bccode = COLOR_BACKGROUND;
454 to_rgb(vte, &vte->def_attr);
455 memcpy(&vte->cattr, &vte->def_attr, sizeof(vte->cattr));
457 tsm_screen_set_def_attr(vte->con, &vte->def_attr);
458 tsm_screen_erase_screen(vte->con, false);
464 * Write raw byte-stream to pty.
465 * When writing data to the client we must make sure that we send the correct
466 * encoding. For backwards-compatibility reasons we should always send 7bit
467 * characters exclusively. However, when FLAG_7BIT_MODE is not set, then we can
468 * also send raw 8bit characters. For instance, in FLAG_8BIT_MODE we can use the
469 * GR characters as keyboard input and send them directly or even use the C1
470 * escape characters. In unicode mode (default) we can send multi-byte utf-8
471 * characters which are also 8bit. When sending these characters, set the \raw
472 * flag to true so this function does not perform debug checks on data we send.
473 * If debugging is disabled, these checks are also disabled and won't affect
475 * For better debugging, we also use the __LINE__ and __FILE__ macros. Use the
476 * vte_write() and vte_write_raw() macros below for more convenient use.
478 * As a rule of thumb do never send 8bit characters in escape sequences and also
479 * avoid all 8bit escape codes including the C1 codes. This will guarantee that
480 * all kind of clients are always compatible to us.
482 * If SEND_RECEIVE_MODE is off (that is, local echo is on) we have to send all
483 * data directly to ourself again. However, we must avoid recursion when
484 * tsm_vte_input() itself calls vte_write*(), therefore, we increase the
485 * PARSER counter when entering tsm_vte_input() and reset it when leaving it
486 * so we never echo data that origins from tsm_vte_input().
487 * But note that SEND_RECEIVE_MODE is inherently broken for escape sequences
488 * that request answers. That is, if we send a request to the client that awaits
489 * a response and parse that request via local echo ourself, then we will also
490 * send a response to the client even though he didn't request one. This
491 * recursion fix does not avoid this but only prevents us from endless loops
492 * here. Anyway, only few applications rely on local echo so we can safely
495 static void vte_write_debug(struct tsm_vte *vte, const char *u8, size_t len,
496 bool raw, const char *file, int line)
498 #ifdef BUILD_ENABLE_DEBUG
499 /* in debug mode we check that escape sequences are always <0x7f so they
500 * are correctly parsed by non-unicode and non-8bit-mode clients. */
504 for (i = 0; i < len; ++i) {
506 llog_warning(vte, "sending 8bit character inline to client in %s:%d",
512 /* in local echo mode, directly parse the data again */
513 if (!vte->parse_cnt && !(vte->flags & FLAG_SEND_RECEIVE_MODE)) {
514 if (vte->flags & FLAG_PREPEND_ESCAPE)
515 tsm_vte_input(vte, "\e", 1);
516 tsm_vte_input(vte, u8, len);
519 if (vte->flags & FLAG_PREPEND_ESCAPE)
520 vte->write_cb(vte, "\e", 1, vte->data);
521 vte->write_cb(vte, u8, len, vte->data);
523 vte->flags &= ~FLAG_PREPEND_ESCAPE;
526 #define vte_write(_vte, _u8, _len) \
527 vte_write_debug((_vte), (_u8), (_len), false, __FILE__, __LINE__)
528 #define vte_write_raw(_vte, _u8, _len) \
529 vte_write_debug((_vte), (_u8), (_len), true, __FILE__, __LINE__)
531 /* write to console */
532 static void write_console(struct tsm_vte *vte, tsm_symbol_t sym)
534 to_rgb(vte, &vte->cattr);
535 tsm_screen_write(vte->con, sym, &vte->cattr);
538 static void reset_state(struct tsm_vte *vte)
540 vte->saved_state.cursor_x = 0;
541 vte->saved_state.cursor_y = 0;
542 vte->saved_state.origin_mode = false;
543 vte->saved_state.wrap_mode = true;
544 vte->saved_state.gl = &vte->g0;
545 vte->saved_state.gr = &vte->g1;
547 copy_fcolor(&vte->saved_state.cattr, &vte->def_attr);
548 copy_bcolor(&vte->saved_state.cattr, &vte->def_attr);
549 vte->saved_state.cattr.bold = 0;
550 vte->saved_state.cattr.underline = 0;
551 vte->saved_state.cattr.inverse = 0;
552 vte->saved_state.cattr.protect = 0;
555 static void save_state(struct tsm_vte *vte)
557 vte->saved_state.cursor_x = tsm_screen_get_cursor_x(vte->con);
558 vte->saved_state.cursor_y = tsm_screen_get_cursor_y(vte->con);
559 vte->saved_state.cattr = vte->cattr;
560 vte->saved_state.gl = vte->gl;
561 vte->saved_state.gr = vte->gr;
562 vte->saved_state.wrap_mode = vte->flags & FLAG_AUTO_WRAP_MODE;
563 vte->saved_state.origin_mode = vte->flags & FLAG_ORIGIN_MODE;
566 static void restore_state(struct tsm_vte *vte)
568 tsm_screen_move_to(vte->con, vte->saved_state.cursor_x,
569 vte->saved_state.cursor_y);
570 vte->cattr = vte->saved_state.cattr;
571 to_rgb(vte, &vte->cattr);
572 if (vte->flags & FLAG_BACKGROUND_COLOR_ERASE_MODE)
573 tsm_screen_set_def_attr(vte->con, &vte->cattr);
574 vte->gl = vte->saved_state.gl;
575 vte->gr = vte->saved_state.gr;
577 if (vte->saved_state.wrap_mode) {
578 vte->flags |= FLAG_AUTO_WRAP_MODE;
579 tsm_screen_set_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
581 vte->flags &= ~FLAG_AUTO_WRAP_MODE;
582 tsm_screen_reset_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
585 if (vte->saved_state.origin_mode) {
586 vte->flags |= FLAG_ORIGIN_MODE;
587 tsm_screen_set_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
589 vte->flags &= ~FLAG_ORIGIN_MODE;
590 tsm_screen_reset_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
596 * This performs a soft reset of the VTE. That is, everything is reset to the
597 * same state as when the VTE was created. This does not affect the console,
601 void tsm_vte_reset(struct tsm_vte *vte)
607 vte->flags |= FLAG_TEXT_CURSOR_MODE;
608 vte->flags |= FLAG_AUTO_REPEAT_MODE;
609 vte->flags |= FLAG_SEND_RECEIVE_MODE;
610 vte->flags |= FLAG_AUTO_WRAP_MODE;
611 vte->flags |= FLAG_BACKGROUND_COLOR_ERASE_MODE;
612 tsm_screen_reset(vte->con);
613 tsm_screen_set_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
615 tsm_utf8_mach_reset(vte->mach);
616 vte->state = STATE_GROUND;
621 vte->g0 = &tsm_vte_unicode_lower;
622 vte->g1 = &tsm_vte_unicode_upper;
623 vte->g2 = &tsm_vte_unicode_lower;
624 vte->g3 = &tsm_vte_unicode_upper;
626 memcpy(&vte->cattr, &vte->def_attr, sizeof(vte->cattr));
627 to_rgb(vte, &vte->cattr);
628 tsm_screen_set_def_attr(vte->con, &vte->def_attr);
634 void tsm_vte_hard_reset(struct tsm_vte *vte)
637 tsm_screen_erase_screen(vte->con, false);
638 tsm_screen_clear_sb(vte->con);
639 tsm_screen_move_to(vte->con, 0, 0);
642 static void send_primary_da(struct tsm_vte *vte)
644 vte_write(vte, "\e[?60;1;6;9;15c", 17);
647 /* execute control character (C0 or C1) */
648 static void do_execute(struct tsm_vte *vte, uint32_t ctrl)
652 /* Ignore on input */
655 /* Transmit answerback message */
656 /* TODO: is there a better answer than ACK? */
657 vte_write(vte, "\x06", 1);
660 /* Sound bell tone */
661 /* TODO: I always considered this annying, however, we
662 * should at least provide some way to enable it if the
663 * user *really* wants it.
667 /* Move cursor one position left */
668 tsm_screen_move_left(vte->con, 1);
671 /* Move to next tab stop or end of line */
672 tsm_screen_tab_right(vte->con, 1);
677 /* Line feed or newline (CR/NL mode) */
678 if (vte->flags & FLAG_LINE_FEED_NEW_LINE_MODE)
679 tsm_screen_newline(vte->con);
681 tsm_screen_move_down(vte->con, 1, true);
684 /* Move cursor to left margin */
685 tsm_screen_move_line_home(vte->con);
688 /* Map G1 character set into GL */
692 /* Map G0 character set into GL */
696 /* Resume transmission */
699 case 0x13: /* XOFF */
700 /* Stop transmission */
704 /* Cancel escape sequence */
705 /* nothing to do here */
708 /* Discard current escape sequence and show err-sym */
709 write_console(vte, 0xbf);
712 /* Invokes an escape sequence */
713 /* nothing to do here */
719 /* Move down one row, perform scroll-up if needed */
720 tsm_screen_move_down(vte->con, 1, true);
723 /* CR/NL with scroll-up if needed */
724 tsm_screen_newline(vte->con);
727 /* Set tab stop at current position */
728 tsm_screen_set_tabstop(vte->con);
731 /* Move up one row, perform scroll-down if needed */
732 tsm_screen_move_up(vte->con, 1, true);
735 /* Temporarily map G2 into GL for next char only */
739 /* Temporarily map G3 into GL for next char only */
742 case 0x9a: /* DECID */
743 /* Send device attributes response like ANSI DA */
744 send_primary_da(vte);
747 /* End control string */
748 /* nothing to do here */
751 llog_debug(vte, "unhandled control char %u", ctrl);
755 static void do_clear(struct tsm_vte *vte)
760 for (i = 0; i < CSI_ARG_MAX; ++i)
761 vte->csi_argv[i] = -1;
765 static void do_collect(struct tsm_vte *vte, uint32_t data)
769 vte->csi_flags |= CSI_BANG;
772 vte->csi_flags |= CSI_CASH;
775 vte->csi_flags |= CSI_WHAT;
778 vte->csi_flags |= CSI_GT;
781 vte->csi_flags |= CSI_SPACE;
784 vte->csi_flags |= CSI_SQUOTE;
787 vte->csi_flags |= CSI_DQUOTE;
790 vte->csi_flags |= CSI_MULT;
793 vte->csi_flags |= CSI_PLUS;
796 vte->csi_flags |= CSI_POPEN;
799 vte->csi_flags |= CSI_PCLOSE;
804 static void do_param(struct tsm_vte *vte, uint32_t data)
809 if (vte->csi_argc < CSI_ARG_MAX)
814 if (vte->csi_argc >= CSI_ARG_MAX)
817 /* avoid integer overflows; max allowed value is 16384 anyway */
818 if (vte->csi_argv[vte->csi_argc] > 0xffff)
821 if (data >= '0' && data <= '9') {
822 new = vte->csi_argv[vte->csi_argc];
826 new = new * 10 + data - '0';
827 vte->csi_argv[vte->csi_argc] = new;
831 static bool set_charset(struct tsm_vte *vte, tsm_vte_charset *set)
833 if (vte->csi_flags & CSI_POPEN)
835 else if (vte->csi_flags & CSI_PCLOSE)
837 else if (vte->csi_flags & CSI_MULT)
839 else if (vte->csi_flags & CSI_PLUS)
847 static void do_esc(struct tsm_vte *vte, uint32_t data)
850 case 'B': /* map ASCII into G0-G3 */
851 if (set_charset(vte, &tsm_vte_unicode_lower))
854 case '<': /* map DEC supplemental into G0-G3 */
855 if (set_charset(vte, &tsm_vte_dec_supplemental_graphics))
858 case '0': /* map DEC special into G0-G3 */
859 if (set_charset(vte, &tsm_vte_dec_special_graphics))
862 case 'A': /* map British into G0-G3 */
863 /* TODO: create British charset from DEC */
864 if (set_charset(vte, &tsm_vte_unicode_upper))
867 case '4': /* map Dutch into G0-G3 */
868 /* TODO: create Dutch charset from DEC */
869 if (set_charset(vte, &tsm_vte_unicode_upper))
873 case '5': /* map Finnish into G0-G3 */
874 /* TODO: create Finnish charset from DEC */
875 if (set_charset(vte, &tsm_vte_unicode_upper))
878 case 'R': /* map French into G0-G3 */
879 /* TODO: create French charset from DEC */
880 if (set_charset(vte, &tsm_vte_unicode_upper))
883 case 'Q': /* map French-Canadian into G0-G3 */
884 /* TODO: create French-Canadian charset from DEC */
885 if (set_charset(vte, &tsm_vte_unicode_upper))
888 case 'K': /* map German into G0-G3 */
889 /* TODO: create German charset from DEC */
890 if (set_charset(vte, &tsm_vte_unicode_upper))
893 case 'Y': /* map Italian into G0-G3 */
894 /* TODO: create Italian charset from DEC */
895 if (set_charset(vte, &tsm_vte_unicode_upper))
899 case '6': /* map Norwegian/Danish into G0-G3 */
900 /* TODO: create Norwegian/Danish charset from DEC */
901 if (set_charset(vte, &tsm_vte_unicode_upper))
904 case 'Z': /* map Spanish into G0-G3 */
905 /* TODO: create Spanish charset from DEC */
906 if (set_charset(vte, &tsm_vte_unicode_upper))
910 case '7': /* map Swedish into G0-G3 */
911 /* TODO: create Swedish charset from DEC */
912 if (set_charset(vte, &tsm_vte_unicode_upper))
915 case '=': /* map Swiss into G0-G3 */
916 /* TODO: create Swiss charset from DEC */
917 if (set_charset(vte, &tsm_vte_unicode_upper))
921 if (vte->csi_flags & CSI_SPACE) {
923 /* Disable 8bit C1 mode */
924 vte->flags &= ~FLAG_USE_C1;
929 if (vte->csi_flags & CSI_SPACE) {
931 /* Enable 8bit C1 mode */
932 vte->flags |= FLAG_USE_C1;
938 /* everything below is only valid without CSI flags */
939 if (vte->csi_flags) {
940 llog_debug(vte, "unhandled escape seq %u", data);
946 /* Move down one row, perform scroll-up if needed */
947 tsm_screen_move_down(vte->con, 1, true);
950 /* CR/NL with scroll-up if needed */
951 tsm_screen_newline(vte->con);
954 /* Set tab stop at current position */
955 tsm_screen_set_tabstop(vte->con);
958 /* Move up one row, perform scroll-down if needed */
959 tsm_screen_move_up(vte->con, 1, true);
962 /* Temporarily map G2 into GL for next char only */
966 /* Temporarily map G3 into GL for next char only */
969 case 'Z': /* DECID */
970 /* Send device attributes response like ANSI DA */
971 send_primary_da(vte);
974 /* End control string */
975 /* nothing to do here */
978 /* Invoke G1 into GR */
982 /* Invoke G2 into GL */
986 /* Invoke G2 into GR */
990 /* Invoke G3 into GL */
994 /* Invoke G3 into GR */
997 case '=': /* DECKPAM */
998 /* Set application keypad mode */
999 vte->flags |= FLAG_KEYPAD_APPLICATION_MODE;
1001 case '>': /* DECKPNM */
1002 /* Set numeric keypad mode */
1003 vte->flags &= ~FLAG_KEYPAD_APPLICATION_MODE;
1007 tsm_vte_hard_reset(vte);
1009 case '7': /* DECSC */
1010 /* save console state */
1013 case '8': /* DECRC */
1014 /* restore console state */
1018 llog_debug(vte, "unhandled escape seq %u", data);
1022 static void csi_attribute(struct tsm_vte *vte)
1024 static const uint8_t bval[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
1025 unsigned int i, code;
1027 if (vte->csi_argc <= 1 && vte->csi_argv[0] == -1) {
1029 vte->csi_argv[0] = 0;
1032 for (i = 0; i < vte->csi_argc; ++i) {
1033 switch (vte->csi_argv[i]) {
1037 copy_fcolor(&vte->cattr, &vte->def_attr);
1038 copy_bcolor(&vte->cattr, &vte->def_attr);
1039 vte->cattr.bold = 0;
1040 vte->cattr.underline = 0;
1041 vte->cattr.inverse = 0;
1044 vte->cattr.bold = 1;
1047 vte->cattr.underline = 1;
1050 vte->cattr.inverse = 1;
1053 vte->cattr.bold = 0;
1056 vte->cattr.underline = 0;
1059 vte->cattr.inverse = 0;
1062 vte->cattr.fccode = COLOR_BLACK;
1065 vte->cattr.fccode = COLOR_RED;
1068 vte->cattr.fccode = COLOR_GREEN;
1071 vte->cattr.fccode = COLOR_YELLOW;
1074 vte->cattr.fccode = COLOR_BLUE;
1077 vte->cattr.fccode = COLOR_MAGENTA;
1080 vte->cattr.fccode = COLOR_CYAN;
1083 vte->cattr.fccode = COLOR_LIGHT_GREY;
1086 copy_fcolor(&vte->cattr, &vte->def_attr);
1089 vte->cattr.bccode = COLOR_BLACK;
1092 vte->cattr.bccode = COLOR_RED;
1095 vte->cattr.bccode = COLOR_GREEN;
1098 vte->cattr.bccode = COLOR_YELLOW;
1101 vte->cattr.bccode = COLOR_BLUE;
1104 vte->cattr.bccode = COLOR_MAGENTA;
1107 vte->cattr.bccode = COLOR_CYAN;
1110 vte->cattr.bccode = COLOR_LIGHT_GREY;
1113 copy_bcolor(&vte->cattr, &vte->def_attr);
1116 vte->cattr.fccode = COLOR_DARK_GREY;
1119 vte->cattr.fccode = COLOR_LIGHT_RED;
1122 vte->cattr.fccode = COLOR_LIGHT_GREEN;
1125 vte->cattr.fccode = COLOR_LIGHT_YELLOW;
1128 vte->cattr.fccode = COLOR_LIGHT_BLUE;
1131 vte->cattr.fccode = COLOR_LIGHT_MAGENTA;
1134 vte->cattr.fccode = COLOR_LIGHT_CYAN;
1137 vte->cattr.fccode = COLOR_WHITE;
1140 vte->cattr.bccode = COLOR_DARK_GREY;
1143 vte->cattr.bccode = COLOR_LIGHT_RED;
1146 vte->cattr.bccode = COLOR_LIGHT_GREEN;
1149 vte->cattr.bccode = COLOR_LIGHT_YELLOW;
1152 vte->cattr.bccode = COLOR_LIGHT_BLUE;
1155 vte->cattr.bccode = COLOR_LIGHT_MAGENTA;
1158 vte->cattr.bccode = COLOR_LIGHT_CYAN;
1161 vte->cattr.bccode = COLOR_WHITE;
1166 if (i + 2 >= vte->csi_argc ||
1167 vte->csi_argv[i + 1] != 5 ||
1168 vte->csi_argv[i + 2] < 0) {
1169 llog_debug(vte, "invalid 256color SGR");
1173 code = vte->csi_argv[i + 2];
1174 if (vte->csi_argv[i] == 38) {
1176 vte->cattr.fccode = code;
1177 } else if (code < 232) {
1178 vte->cattr.fccode = -1;
1180 vte->cattr.fb = bval[code % 6];
1182 vte->cattr.fg = bval[code % 6];
1184 vte->cattr.fr = bval[code % 6];
1186 vte->cattr.fccode = -1;
1187 code = (code - 232) * 10 + 8;
1188 vte->cattr.fr = code;
1189 vte->cattr.fg = code;
1190 vte->cattr.fb = code;
1194 vte->cattr.bccode = code;
1195 } else if (code < 232) {
1196 vte->cattr.bccode = -1;
1198 vte->cattr.bb = bval[code % 6];
1200 vte->cattr.bg = bval[code % 6];
1202 vte->cattr.br = bval[code % 6];
1204 vte->cattr.bccode = -1;
1205 code = (code - 232) * 10 + 8;
1206 vte->cattr.br = code;
1207 vte->cattr.bg = code;
1208 vte->cattr.bb = code;
1215 llog_debug(vte, "unhandled SGR attr %i",
1220 to_rgb(vte, &vte->cattr);
1221 if (vte->flags & FLAG_BACKGROUND_COLOR_ERASE_MODE)
1222 tsm_screen_set_def_attr(vte->con, &vte->cattr);
1225 static void csi_soft_reset(struct tsm_vte *vte)
1230 static void csi_compat_mode(struct tsm_vte *vte)
1232 /* always perform soft reset */
1233 csi_soft_reset(vte);
1235 if (vte->csi_argv[0] == 61) {
1236 /* Switching to VT100 compatibility mode. We do
1237 * not support this mode, so ignore it. In fact,
1238 * we are almost compatible to it, anyway, so
1239 * there is no need to explicitly select it.
1240 * However, we enable 7bit mode to avoid
1241 * character-table problems */
1242 vte->flags |= FLAG_7BIT_MODE;
1243 vte->g0 = &tsm_vte_unicode_lower;
1244 vte->g1 = &tsm_vte_dec_supplemental_graphics;
1245 } else if (vte->csi_argv[0] == 62 ||
1246 vte->csi_argv[0] == 63 ||
1247 vte->csi_argv[0] == 64) {
1248 /* Switching to VT2/3/4 compatibility mode. We
1249 * are always compatible with this so ignore it.
1250 * We always send 7bit controls so we also do
1251 * not care for the parameter value here that
1252 * select the control-mode.
1253 * VT220 defines argument 2 as 7bit mode but
1254 * VT3xx up to VT5xx use it as 8bit mode. We
1255 * choose to conform with the latter here.
1256 * We also enable 8bit mode when VT220
1257 * compatibility is requested explicitly. */
1258 if (vte->csi_argv[1] == 1 ||
1259 vte->csi_argv[1] == 2)
1260 vte->flags |= FLAG_USE_C1;
1262 vte->flags |= FLAG_8BIT_MODE;
1263 vte->g0 = &tsm_vte_unicode_lower;
1264 vte->g1 = &tsm_vte_dec_supplemental_graphics;
1266 llog_debug(vte, "unhandled DECSCL 'p' CSI %i, switching to utf-8 mode again",
1271 static inline void set_reset_flag(struct tsm_vte *vte, bool set,
1277 vte->flags &= ~flag;
1280 static void csi_mode(struct tsm_vte *vte, bool set)
1284 for (i = 0; i < vte->csi_argc; ++i) {
1285 if (!(vte->csi_flags & CSI_WHAT)) {
1286 switch (vte->csi_argv[i]) {
1290 set_reset_flag(vte, set,
1291 FLAG_KEYBOARD_ACTION_MODE);
1294 set_reset_flag(vte, set,
1295 FLAG_INSERT_REPLACE_MODE);
1297 tsm_screen_set_flags(vte->con,
1298 TSM_SCREEN_INSERT_MODE);
1300 tsm_screen_reset_flags(vte->con,
1301 TSM_SCREEN_INSERT_MODE);
1304 set_reset_flag(vte, set,
1305 FLAG_SEND_RECEIVE_MODE);
1308 set_reset_flag(vte, set,
1309 FLAG_LINE_FEED_NEW_LINE_MODE);
1312 llog_debug(vte, "unknown non-DEC (Re)Set-Mode %d",
1318 switch (vte->csi_argv[i]) {
1321 case 1: /* DECCKM */
1322 set_reset_flag(vte, set, FLAG_CURSOR_KEY_MODE);
1324 case 2: /* DECANM */
1325 /* Select VT52 mode */
1326 /* We do not support VT52 mode. Is there any reason why
1327 * we should support it? We ignore it here and do not
1328 * mark it as to-do item unless someone has strong
1329 * arguments to support it. */
1331 case 3: /* DECCOLM */
1332 /* If set, select 132 column mode, otherwise use 80
1333 * column mode. If neither is selected explicitly, we
1334 * use dynamic mode, that is, we send SIGWCH when the
1335 * size changes and we allow arbitrary buffer
1336 * dimensions. On soft-reset, we automatically fall back
1337 * to the default, that is, dynamic mode.
1338 * Dynamic-mode can be forced to a static mode in the
1339 * config. That is, every time dynamic-mode becomes
1340 * active, the terminal will be set to the dimensions
1341 * that were selected in the config. This allows setting
1342 * a fixed size for the terminal regardless of the
1344 * TODO: Implement this */
1346 case 4: /* DECSCLM */
1347 /* Select smooth scrolling. We do not support the
1348 * classic smooth scrolling because we have a scrollback
1349 * buffer. There is no need to implement smooth
1350 * scrolling so ignore this here. */
1352 case 5: /* DECSCNM */
1353 set_reset_flag(vte, set, FLAG_INVERSE_SCREEN_MODE);
1355 tsm_screen_set_flags(vte->con,
1356 TSM_SCREEN_INVERSE);
1358 tsm_screen_reset_flags(vte->con,
1359 TSM_SCREEN_INVERSE);
1362 set_reset_flag(vte, set, FLAG_ORIGIN_MODE);
1364 tsm_screen_set_flags(vte->con,
1365 TSM_SCREEN_REL_ORIGIN);
1367 tsm_screen_reset_flags(vte->con,
1368 TSM_SCREEN_REL_ORIGIN);
1370 case 7: /* DECAWN */
1371 set_reset_flag(vte, set, FLAG_AUTO_WRAP_MODE);
1373 tsm_screen_set_flags(vte->con,
1374 TSM_SCREEN_AUTO_WRAP);
1376 tsm_screen_reset_flags(vte->con,
1377 TSM_SCREEN_AUTO_WRAP);
1379 case 8: /* DECARM */
1380 set_reset_flag(vte, set, FLAG_AUTO_REPEAT_MODE);
1382 case 12: /* blinking cursor */
1383 /* TODO: implement */
1385 case 18: /* DECPFF */
1386 /* If set, a form feed (FF) is sent to the printer after
1387 * every screen that is printed. We don't have printers
1388 * these days directly attached to terminals so we
1389 * ignore this here. */
1391 case 19: /* DECPEX */
1392 /* If set, the full screen is printed instead of
1393 * scrolling region only. We have no printer so ignore
1396 case 25: /* DECTCEM */
1397 set_reset_flag(vte, set, FLAG_TEXT_CURSOR_MODE);
1399 tsm_screen_reset_flags(vte->con,
1400 TSM_SCREEN_HIDE_CURSOR);
1402 tsm_screen_set_flags(vte->con,
1403 TSM_SCREEN_HIDE_CURSOR);
1405 case 42: /* DECNRCM */
1406 set_reset_flag(vte, set, FLAG_NATIONAL_CHARSET_MODE);
1408 case 47: /* Alternate screen buffer */
1409 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1413 tsm_screen_set_flags(vte->con,
1414 TSM_SCREEN_ALTERNATE);
1416 tsm_screen_reset_flags(vte->con,
1417 TSM_SCREEN_ALTERNATE);
1419 case 1047: /* Alternate screen buffer with post-erase */
1420 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1424 tsm_screen_set_flags(vte->con,
1425 TSM_SCREEN_ALTERNATE);
1427 tsm_screen_erase_screen(vte->con, false);
1428 tsm_screen_reset_flags(vte->con,
1429 TSM_SCREEN_ALTERNATE);
1432 case 1048: /* Set/Reset alternate-screen buffer cursor */
1433 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1438 tsm_screen_get_cursor_x(vte->con);
1440 tsm_screen_get_cursor_y(vte->con);
1442 tsm_screen_move_to(vte->con, vte->alt_cursor_x,
1446 case 1049: /* Alternate screen buffer with pre-erase+cursor */
1447 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1452 tsm_screen_get_cursor_x(vte->con);
1454 tsm_screen_get_cursor_y(vte->con);
1455 tsm_screen_set_flags(vte->con,
1456 TSM_SCREEN_ALTERNATE);
1457 tsm_screen_erase_screen(vte->con, false);
1459 tsm_screen_reset_flags(vte->con,
1460 TSM_SCREEN_ALTERNATE);
1461 tsm_screen_move_to(vte->con, vte->alt_cursor_x,
1466 llog_debug(vte, "unknown DEC %set-Mode %d",
1467 set?"S":"Res", vte->csi_argv[i]);
1473 static void csi_dev_attr(struct tsm_vte *vte)
1475 if (vte->csi_argc <= 1 && vte->csi_argv[0] <= 0) {
1476 if (vte->csi_flags == 0) {
1477 send_primary_da(vte);
1479 } else if (vte->csi_flags & CSI_GT) {
1480 vte_write(vte, "\e[>1;1;0c", 9);
1485 llog_debug(vte, "unhandled DA: %x %d %d %d...", vte->csi_flags,
1486 vte->csi_argv[0], vte->csi_argv[1], vte->csi_argv[2]);
1489 static void csi_dsr(struct tsm_vte *vte)
1492 unsigned int x, y, len;
1494 if (vte->csi_argv[0] == 5) {
1495 vte_write(vte, "\e[0n", 4);
1496 } else if (vte->csi_argv[0] == 6) {
1497 x = tsm_screen_get_cursor_x(vte->con);
1498 y = tsm_screen_get_cursor_y(vte->con);
1499 len = snprintf(buf, sizeof(buf), "\e[%u;%uR", x, y);
1500 if (len >= sizeof(buf))
1501 vte_write(vte, "\e[0;0R", 6);
1503 vte_write(vte, buf, len);
1507 static void do_csi(struct tsm_vte *vte, uint32_t data)
1509 int num, x, y, upper, lower;
1512 if (vte->csi_argc < CSI_ARG_MAX)
1517 /* move cursor up */
1518 num = vte->csi_argv[0];
1521 tsm_screen_move_up(vte->con, num, false);
1524 /* move cursor down */
1525 num = vte->csi_argv[0];
1528 tsm_screen_move_down(vte->con, num, false);
1531 /* move cursor forward */
1532 num = vte->csi_argv[0];
1535 tsm_screen_move_right(vte->con, num);
1538 /* move cursor backward */
1539 num = vte->csi_argv[0];
1542 tsm_screen_move_left(vte->con, num);
1545 /* Vertical Line Position Absolute */
1546 num = vte->csi_argv[0];
1549 x = tsm_screen_get_cursor_x(vte->con);
1550 tsm_screen_move_to(vte->con, x, num - 1);
1553 /* Vertical Line Position Relative */
1554 num = vte->csi_argv[0];
1557 x = tsm_screen_get_cursor_x(vte->con);
1558 y = tsm_screen_get_cursor_y(vte->con);
1559 tsm_screen_move_to(vte->con, x, y + num);
1563 /* position cursor */
1564 x = vte->csi_argv[0];
1567 y = vte->csi_argv[1];
1570 tsm_screen_move_to(vte->con, y - 1, x - 1);
1573 /* Cursor Character Absolute */
1574 num = vte->csi_argv[0];
1577 y = tsm_screen_get_cursor_y(vte->con);
1578 tsm_screen_move_to(vte->con, num - 1, y);
1581 if (vte->csi_flags & CSI_WHAT)
1586 if (vte->csi_argv[0] <= 0)
1587 tsm_screen_erase_cursor_to_screen(vte->con,
1589 else if (vte->csi_argv[0] == 1)
1590 tsm_screen_erase_screen_to_cursor(vte->con,
1592 else if (vte->csi_argv[0] == 2)
1593 tsm_screen_erase_screen(vte->con, protect);
1595 llog_debug(vte, "unknown parameter to CSI-J: %d",
1599 if (vte->csi_flags & CSI_WHAT)
1604 if (vte->csi_argv[0] <= 0)
1605 tsm_screen_erase_cursor_to_end(vte->con, protect);
1606 else if (vte->csi_argv[0] == 1)
1607 tsm_screen_erase_home_to_cursor(vte->con, protect);
1608 else if (vte->csi_argv[0] == 2)
1609 tsm_screen_erase_current_line(vte->con, protect);
1611 llog_debug(vte, "unknown parameter to CSI-K: %d",
1615 /* erase characters */
1616 num = vte->csi_argv[0];
1619 tsm_screen_erase_chars(vte->con, num);
1625 if (vte->csi_flags & CSI_GT) {
1626 /* xterm: select X11 visual cursor mode */
1627 csi_soft_reset(vte);
1628 } else if (vte->csi_flags & CSI_BANG) {
1629 /* DECSTR: Soft Reset */
1630 csi_soft_reset(vte);
1631 } else if (vte->csi_flags & CSI_CASH) {
1632 /* DECRQM: Request DEC Private Mode */
1633 /* If CSI_WHAT is set, then enable,
1634 * otherwise disable */
1635 csi_soft_reset(vte);
1637 /* DECSCL: Compatibility Level */
1638 /* Sometimes CSI_DQUOTE is set here, too */
1639 csi_compat_mode(vte);
1642 case 'h': /* SM: Set Mode */
1643 csi_mode(vte, true);
1645 case 'l': /* RM: Reset Mode */
1646 csi_mode(vte, false);
1648 case 'r': /* DECSTBM */
1649 /* set margin size */
1650 upper = vte->csi_argv[0];
1653 lower = vte->csi_argv[1];
1656 tsm_screen_set_margins(vte->con, upper, lower);
1659 /* device attributes */
1664 num = vte->csi_argv[0];
1667 tsm_screen_insert_lines(vte->con, num);
1671 num = vte->csi_argv[0];
1674 tsm_screen_delete_lines(vte->con, num);
1677 /* tabulation clear */
1678 num = vte->csi_argv[0];
1680 tsm_screen_reset_tabstop(vte->con);
1682 tsm_screen_reset_all_tabstops(vte->con);
1684 llog_debug(vte, "invalid parameter %d to TBC CSI", num);
1687 /* insert characters */
1688 num = vte->csi_argv[0];
1691 tsm_screen_insert_chars(vte->con, num);
1694 /* delete characters */
1695 num = vte->csi_argv[0];
1698 tsm_screen_delete_chars(vte->con, num);
1701 /* cursor horizontal backwards tab */
1702 num = vte->csi_argv[0];
1705 tsm_screen_tab_left(vte->con, num);
1708 /* cursor horizontal forward tab */
1709 num = vte->csi_argv[0];
1712 tsm_screen_tab_right(vte->con, num);
1715 /* device status reports */
1720 num = vte->csi_argv[0];
1723 tsm_screen_scroll_up(vte->con, num);
1727 num = vte->csi_argv[0];
1730 tsm_screen_scroll_down(vte->con, num);
1733 llog_debug(vte, "unhandled CSI sequence %c", data);
1737 /* map a character according to current GL and GR maps */
1738 static uint32_t vte_map(struct tsm_vte *vte, uint32_t val)
1740 /* 32, 127, 160 and 255 map to identity like all values >255 */
1744 val = (**vte->glt)[val - 32];
1747 val = (**vte->gl)[val - 32];
1752 val = (**vte->grt)[val - 160];
1755 val = (**vte->gr)[val - 160];
1763 /* perform parser action */
1764 static void do_action(struct tsm_vte *vte, uint32_t data, int action)
1773 /* ignore character */
1776 sym = tsm_symbol_make(vte_map(vte, data));
1777 write_console(vte, sym);
1779 case ACTION_EXECUTE:
1780 do_execute(vte, data);
1785 case ACTION_COLLECT:
1786 do_collect(vte, data);
1789 do_param(vte, data);
1791 case ACTION_ESC_DISPATCH:
1794 case ACTION_CSI_DISPATCH:
1797 case ACTION_DCS_START:
1799 case ACTION_DCS_COLLECT:
1801 case ACTION_DCS_END:
1803 case ACTION_OSC_START:
1805 case ACTION_OSC_COLLECT:
1807 case ACTION_OSC_END:
1810 llog_warn(vte, "invalid action %d", action);
1814 /* entry actions to be performed when entering the selected state */
1815 static const int entry_action[] = {
1816 [STATE_CSI_ENTRY] = ACTION_CLEAR,
1817 [STATE_DCS_ENTRY] = ACTION_CLEAR,
1818 [STATE_DCS_PASS] = ACTION_DCS_START,
1819 [STATE_ESC] = ACTION_CLEAR,
1820 [STATE_OSC_STRING] = ACTION_OSC_START,
1821 [STATE_NUM] = ACTION_NONE,
1824 /* exit actions to be performed when leaving the selected state */
1825 static const int exit_action[] = {
1826 [STATE_DCS_PASS] = ACTION_DCS_END,
1827 [STATE_OSC_STRING] = ACTION_OSC_END,
1828 [STATE_NUM] = ACTION_NONE,
1831 /* perform state transition and dispatch related actions */
1832 static void do_trans(struct tsm_vte *vte, uint32_t data, int state, int act)
1834 if (state != STATE_NONE) {
1835 /* A state transition occurs. Perform exit-action,
1836 * transition-action and entry-action. Even when performing a
1837 * transition to the same state as the current state we do this.
1838 * Use STATE_NONE if this is not the desired behavior.
1840 do_action(vte, data, exit_action[vte->state]);
1841 do_action(vte, data, act);
1842 do_action(vte, data, entry_action[state]);
1845 do_action(vte, data, act);
1850 * Escape sequence parser
1851 * This parses the new input character \data. It performs state transition and
1852 * calls the right callbacks for each action.
1854 static void parse_data(struct tsm_vte *vte, uint32_t raw)
1856 /* events that may occur in any state */
1865 do_trans(vte, raw, STATE_GROUND, ACTION_EXECUTE);
1868 do_trans(vte, raw, STATE_ESC, ACTION_NONE);
1873 do_trans(vte, raw, STATE_ST_IGNORE, ACTION_NONE);
1876 do_trans(vte, raw, STATE_DCS_ENTRY, ACTION_NONE);
1879 do_trans(vte, raw, STATE_OSC_STRING, ACTION_NONE);
1882 do_trans(vte, raw, STATE_CSI_ENTRY, ACTION_NONE);
1886 /* events that depend on the current state */
1887 switch (vte->state) {
1896 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1899 do_trans(vte, raw, STATE_NONE, ACTION_PRINT);
1902 do_trans(vte, raw, STATE_NONE, ACTION_PRINT);
1909 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1912 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1915 do_trans(vte, raw, STATE_ESC_INT, ACTION_COLLECT);
1923 do_trans(vte, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1926 do_trans(vte, raw, STATE_CSI_ENTRY, ACTION_NONE);
1929 do_trans(vte, raw, STATE_OSC_STRING, ACTION_NONE);
1932 do_trans(vte, raw, STATE_DCS_ENTRY, ACTION_NONE);
1937 do_trans(vte, raw, STATE_ST_IGNORE, ACTION_NONE);
1940 do_trans(vte, raw, STATE_ESC_INT, ACTION_COLLECT);
1947 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1950 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1953 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1956 do_trans(vte, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1959 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1961 case STATE_CSI_ENTRY:
1966 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1969 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1972 do_trans(vte, raw, STATE_CSI_INT, ACTION_COLLECT);
1975 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1979 do_trans(vte, raw, STATE_CSI_PARAM, ACTION_PARAM);
1982 do_trans(vte, raw, STATE_CSI_PARAM, ACTION_COLLECT);
1985 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1988 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1990 case STATE_CSI_PARAM:
1995 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1999 do_trans(vte, raw, STATE_NONE, ACTION_PARAM);
2002 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2006 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2009 do_trans(vte, raw, STATE_CSI_INT, ACTION_COLLECT);
2012 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
2015 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2022 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
2025 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
2028 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2031 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2034 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
2037 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2039 case STATE_CSI_IGNORE:
2044 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
2048 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2051 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2054 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2056 case STATE_DCS_ENTRY:
2062 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2065 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2068 do_trans(vte, raw, STATE_DCS_INT, ACTION_COLLECT);
2072 do_trans(vte, raw, STATE_DCS_PARAM, ACTION_PARAM);
2075 do_trans(vte, raw, STATE_DCS_PARAM, ACTION_COLLECT);
2078 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2081 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2083 case STATE_DCS_PARAM:
2089 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2093 do_trans(vte, raw, STATE_NONE, ACTION_PARAM);
2097 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2100 do_trans(vte, raw, STATE_DCS_INT, ACTION_COLLECT);
2103 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2106 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2114 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2117 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
2120 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2123 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2126 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2128 case STATE_DCS_PASS:
2134 do_trans(vte, raw, STATE_NONE, ACTION_DCS_COLLECT);
2137 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2140 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2143 do_trans(vte, raw, STATE_NONE, ACTION_DCS_COLLECT);
2145 case STATE_DCS_IGNORE:
2151 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2154 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2157 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2159 case STATE_OSC_STRING:
2165 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2168 do_trans(vte, raw, STATE_NONE, ACTION_OSC_COLLECT);
2172 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2175 do_trans(vte, raw, STATE_NONE, ACTION_OSC_COLLECT);
2177 case STATE_ST_IGNORE:
2183 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2186 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2189 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2193 llog_warn(vte, "unhandled input %u in state %d", raw, vte->state);
2197 void tsm_vte_input(struct tsm_vte *vte, const char *u8, size_t len)
2203 if (!vte || !vte->con)
2207 for (i = 0; i < len; ++i) {
2208 if (vte->flags & FLAG_7BIT_MODE) {
2210 llog_debug(vte, "receiving 8bit character U+%d from pty while in 7bit mode",
2212 parse_data(vte, u8[i] & 0x7f);
2213 } else if (vte->flags & FLAG_8BIT_MODE) {
2214 parse_data(vte, u8[i]);
2216 state = tsm_utf8_mach_feed(vte->mach, u8[i]);
2217 if (state == TSM_UTF8_ACCEPT ||
2218 state == TSM_UTF8_REJECT) {
2219 ucs4 = tsm_utf8_mach_get(vte->mach);
2220 parse_data(vte, ucs4);
2228 bool tsm_vte_handle_keyboard(struct tsm_vte *vte, uint32_t keysym,
2229 uint32_t ascii, unsigned int mods,
2236 /* MOD1 (mostly labeled 'Alt') prepends an escape character to every
2237 * input that is sent by a key.
2238 * TODO: Transform this huge handler into a lookup table to save a lot
2239 * of code and make such modifiers easier to implement.
2240 * Also check whether altSendsEscape should be the default (xterm
2241 * disables this by default, why?) and whether we should implement the
2242 * fallback shifting that xterm does. */
2243 if (mods & TSM_ALT_MASK)
2244 vte->flags |= FLAG_PREPEND_ESCAPE;
2246 /* A user might actually use multiple layouts for keyboard input. The
2247 * @keysym variable contains the actual keysym that the user used. But
2248 * if this keysym is not in the ascii range, the input handler does
2249 * check all other layouts that the user specified whether one of them
2250 * maps the key to some ASCII keysym and provides this via @ascii.
2251 * We always use the real keysym except when handling CTRL+<XY>
2252 * shortcuts we use the ascii keysym. This is for compatibility to xterm
2253 * et. al. so ctrl+c always works regardless of the currently active
2255 * But if no ascii-sym is found, we still use the real keysym. */
2257 if (sym == XKB_KEY_NoSymbol)
2260 if (mods & TSM_CONTROL_MASK) {
2264 vte_write(vte, "\x00", 1);
2268 vte_write(vte, "\x01", 1);
2272 vte_write(vte, "\x02", 1);
2276 vte_write(vte, "\x03", 1);
2280 vte_write(vte, "\x04", 1);
2284 vte_write(vte, "\x05", 1);
2288 vte_write(vte, "\x06", 1);
2292 vte_write(vte, "\x07", 1);
2296 vte_write(vte, "\x08", 1);
2300 vte_write(vte, "\x09", 1);
2304 vte_write(vte, "\x0a", 1);
2308 vte_write(vte, "\x0b", 1);
2312 vte_write(vte, "\x0c", 1);
2316 vte_write(vte, "\x0d", 1);
2320 vte_write(vte, "\x0e", 1);
2324 vte_write(vte, "\x0f", 1);
2328 vte_write(vte, "\x10", 1);
2332 vte_write(vte, "\x11", 1);
2336 vte_write(vte, "\x12", 1);
2340 vte_write(vte, "\x13", 1);
2344 vte_write(vte, "\x14", 1);
2348 vte_write(vte, "\x15", 1);
2352 vte_write(vte, "\x16", 1);
2356 vte_write(vte, "\x17", 1);
2360 vte_write(vte, "\x18", 1);
2364 vte_write(vte, "\x19", 1);
2368 vte_write(vte, "\x1a", 1);
2371 case XKB_KEY_bracketleft:
2372 case XKB_KEY_braceleft:
2373 vte_write(vte, "\x1b", 1);
2376 case XKB_KEY_backslash:
2378 vte_write(vte, "\x1c", 1);
2381 case XKB_KEY_bracketright:
2382 case XKB_KEY_braceright:
2383 vte_write(vte, "\x1d", 1);
2387 case XKB_KEY_asciitilde:
2388 vte_write(vte, "\x1e", 1);
2392 case XKB_KEY_question:
2393 vte_write(vte, "\x1f", 1);
2396 vte_write(vte, "\x7f", 1);
2402 case XKB_KEY_BackSpace:
2403 vte_write(vte, "\x08", 1);
2406 case XKB_KEY_KP_Tab:
2407 vte_write(vte, "\x09", 1);
2409 case XKB_KEY_ISO_Left_Tab:
2410 vte_write(vte, "\e[Z", 3);
2412 case XKB_KEY_Linefeed:
2413 vte_write(vte, "\x0a", 1);
2416 vte_write(vte, "\x0b", 1);
2419 TODO: What should we do with this key? Sending XOFF is awful as
2420 there is no simple way on modern keyboards to send XON
2421 again. If someone wants this, we can re-eanble it and set
2424 vte_write(vte, "\x13", 1);
2428 TODO: What should we do on scroll-lock? Sending 0x14 is what
2429 the specs say but it is not used today the way most
2430 users would expect so we disable it. If someone wants
2431 this, we can re-enable it and set some flag.
2432 case XKB_KEY_Scroll_Lock:
2433 vte_write(vte, "\x14", 1);
2436 case XKB_KEY_Sys_Req:
2437 vte_write(vte, "\x15", 1);
2439 case XKB_KEY_Escape:
2440 vte_write(vte, "\x1b", 1);
2442 case XKB_KEY_KP_Enter:
2443 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE) {
2444 vte_write(vte, "\eOM", 3);
2448 case XKB_KEY_Return:
2449 if (vte->flags & FLAG_LINE_FEED_NEW_LINE_MODE)
2450 vte_write(vte, "\x0d\x0a", 2);
2452 vte_write(vte, "\x0d", 1);
2455 vte_write(vte, "\e[1~", 4);
2457 case XKB_KEY_Insert:
2458 vte_write(vte, "\e[2~", 4);
2460 case XKB_KEY_Delete:
2461 vte_write(vte, "\e[3~", 4);
2463 case XKB_KEY_Select:
2464 vte_write(vte, "\e[4~", 4);
2466 case XKB_KEY_Page_Up:
2467 case XKB_KEY_KP_Page_Up:
2468 vte_write(vte, "\e[5~", 4);
2470 case XKB_KEY_KP_Page_Down:
2471 case XKB_KEY_Page_Down:
2472 vte_write(vte, "\e[6~", 4);
2476 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2477 vte_write(vte, "\eOA", 3);
2479 vte_write(vte, "\e[A", 3);
2482 case XKB_KEY_KP_Down:
2483 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2484 vte_write(vte, "\eOB", 3);
2486 vte_write(vte, "\e[B", 3);
2489 case XKB_KEY_KP_Right:
2490 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2491 vte_write(vte, "\eOC", 3);
2493 vte_write(vte, "\e[C", 3);
2496 case XKB_KEY_KP_Left:
2497 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2498 vte_write(vte, "\eOD", 3);
2500 vte_write(vte, "\e[D", 3);
2502 case XKB_KEY_KP_Insert:
2504 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2505 vte_write(vte, "\eOp", 3);
2507 vte_write(vte, "0", 1);
2510 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2511 vte_write(vte, "\eOq", 3);
2513 vte_write(vte, "1", 1);
2516 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2517 vte_write(vte, "\eOr", 3);
2519 vte_write(vte, "2", 1);
2522 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2523 vte_write(vte, "\eOs", 3);
2525 vte_write(vte, "3", 1);
2528 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2529 vte_write(vte, "\eOt", 3);
2531 vte_write(vte, "4", 1);
2534 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2535 vte_write(vte, "\eOu", 3);
2537 vte_write(vte, "5", 1);
2540 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2541 vte_write(vte, "\eOv", 3);
2543 vte_write(vte, "6", 1);
2546 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2547 vte_write(vte, "\eOw", 3);
2549 vte_write(vte, "7", 1);
2552 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2553 vte_write(vte, "\eOx", 3);
2555 vte_write(vte, "8", 1);
2558 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2559 vte_write(vte, "\eOy", 3);
2561 vte_write(vte, "9", 1);
2563 case XKB_KEY_KP_Subtract:
2564 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2565 vte_write(vte, "\eOm", 3);
2567 vte_write(vte, "-", 1);
2569 case XKB_KEY_KP_Separator:
2570 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2571 vte_write(vte, "\eOl", 3);
2573 vte_write(vte, ",", 1);
2575 case XKB_KEY_KP_Delete:
2576 case XKB_KEY_KP_Decimal:
2577 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2578 vte_write(vte, "\eOn", 3);
2580 vte_write(vte, ".", 1);
2582 case XKB_KEY_KP_Equal:
2583 case XKB_KEY_KP_Divide:
2584 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2585 vte_write(vte, "\eOj", 3);
2587 vte_write(vte, "/", 1);
2589 case XKB_KEY_KP_Multiply:
2590 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2591 vte_write(vte, "\eOo", 3);
2593 vte_write(vte, "*", 1);
2595 case XKB_KEY_KP_Add:
2596 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2597 vte_write(vte, "\eOk", 3);
2599 vte_write(vte, "+", 1);
2602 case XKB_KEY_KP_Home:
2603 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2604 vte_write(vte, "\eOH", 3);
2606 vte_write(vte, "\e[H", 3);
2609 case XKB_KEY_KP_End:
2610 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2611 vte_write(vte, "\eOF", 3);
2613 vte_write(vte, "\e[F", 3);
2615 case XKB_KEY_KP_Space:
2616 vte_write(vte, " ", 1);
2618 /* TODO: check what to transmit for functions keys when
2619 * shift/ctrl etc. are pressed. Every terminal behaves
2620 * differently here which is really weird.
2621 * We now map F4 to F14 if shift is pressed and so on for all
2622 * keys. However, such mappings should rather be done via
2623 * xkb-configurations and we should instead add a flags argument
2624 * to the CSIs as some of the keys here already do. */
2627 if (mods & TSM_SHIFT_MASK)
2628 vte_write(vte, "\e[23~", 5);
2630 vte_write(vte, "\eOP", 3);
2634 if (mods & TSM_SHIFT_MASK)
2635 vte_write(vte, "\e[24~", 5);
2637 vte_write(vte, "\eOQ", 3);
2641 if (mods & TSM_SHIFT_MASK)
2642 vte_write(vte, "\e[25~", 5);
2644 vte_write(vte, "\eOR", 3);
2648 if (mods & TSM_SHIFT_MASK)
2649 //vte_write(vte, "\e[1;2S", 6);
2650 vte_write(vte, "\e[26~", 5);
2652 vte_write(vte, "\eOS", 3);
2655 if (mods & TSM_SHIFT_MASK)
2656 //vte_write(vte, "\e[15;2~", 7);
2657 vte_write(vte, "\e[28~", 5);
2659 vte_write(vte, "\e[15~", 5);
2662 if (mods & TSM_SHIFT_MASK)
2663 //vte_write(vte, "\e[17;2~", 7);
2664 vte_write(vte, "\e[29~", 5);
2666 vte_write(vte, "\e[17~", 5);
2669 if (mods & TSM_SHIFT_MASK)
2670 //vte_write(vte, "\e[18;2~", 7);
2671 vte_write(vte, "\e[31~", 5);
2673 vte_write(vte, "\e[18~", 5);
2676 if (mods & TSM_SHIFT_MASK)
2677 //vte_write(vte, "\e[19;2~", 7);
2678 vte_write(vte, "\e[32~", 5);
2680 vte_write(vte, "\e[19~", 5);
2683 if (mods & TSM_SHIFT_MASK)
2684 //vte_write(vte, "\e[20;2~", 7);
2685 vte_write(vte, "\e[33~", 5);
2687 vte_write(vte, "\e[20~", 5);
2690 if (mods & TSM_SHIFT_MASK)
2691 //vte_write(vte, "\e[21;2~", 7);
2692 vte_write(vte, "\e[34~", 5);
2694 vte_write(vte, "\e[21~", 5);
2697 if (mods & TSM_SHIFT_MASK)
2698 vte_write(vte, "\e[23;2~", 7);
2700 vte_write(vte, "\e[23~", 5);
2703 if (mods & TSM_SHIFT_MASK)
2704 vte_write(vte, "\e[24;2~", 7);
2706 vte_write(vte, "\e[24~", 5);
2709 if (mods & TSM_SHIFT_MASK)
2710 vte_write(vte, "\e[25;2~", 7);
2712 vte_write(vte, "\e[25~", 5);
2715 if (mods & TSM_SHIFT_MASK)
2716 vte_write(vte, "\e[26;2~", 7);
2718 vte_write(vte, "\e[26~", 5);
2721 if (mods & TSM_SHIFT_MASK)
2722 vte_write(vte, "\e[28;2~", 7);
2724 vte_write(vte, "\e[28~", 5);
2727 if (mods & TSM_SHIFT_MASK)
2728 vte_write(vte, "\e[29;2~", 7);
2730 vte_write(vte, "\e[29~", 5);
2733 if (mods & TSM_SHIFT_MASK)
2734 vte_write(vte, "\e[31;2~", 7);
2736 vte_write(vte, "\e[31~", 5);
2739 if (mods & TSM_SHIFT_MASK)
2740 vte_write(vte, "\e[32;2~", 7);
2742 vte_write(vte, "\e[32~", 5);
2745 if (mods & TSM_SHIFT_MASK)
2746 vte_write(vte, "\e[33;2~", 7);
2748 vte_write(vte, "\e[33~", 5);
2751 if (mods & TSM_SHIFT_MASK)
2752 vte_write(vte, "\e[34;2~", 7);
2754 vte_write(vte, "\e[34~", 5);
2758 if (unicode != TSM_VTE_INVALID) {
2759 if (vte->flags & FLAG_7BIT_MODE) {
2761 if (unicode & 0x80) {
2762 llog_debug(vte, "invalid keyboard input in 7bit mode U+%x; mapping to '?'",
2766 vte_write(vte, &val, 1);
2767 } else if (vte->flags & FLAG_8BIT_MODE) {
2769 if (unicode > 0xff) {
2770 llog_debug(vte, "invalid keyboard input in 8bit mode U+%x; mapping to '?'",
2774 vte_write_raw(vte, &val, 1);
2776 len = tsm_ucs4_to_utf8(tsm_symbol_make(unicode), u8);
2777 vte_write_raw(vte, u8, len);
2782 vte->flags &= ~FLAG_PREPEND_ESCAPE;