4 * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Virtual Terminal Emulator
28 * This is the VT implementation. It is written from scratch. It uses the
29 * screen state-machine as output and is tightly bound to it. It supports
30 * functionality from vt100 up to vt500 series. It doesn't implement an
31 * explicitly selected terminal but tries to support the most important commands
32 * to be compatible with existing implementations. However, full vt102
33 * compatibility is the least that is provided.
35 * The main parser in this file controls the parser-state and dispatches the
36 * actions to the related handlers. The parser is based on the state-diagram
37 * from Paul Williams: http://vt100.net/emu/
38 * It is written from scratch, though.
39 * This parser is fully compatible up to the vt500 series. It requires UTF-8 and
40 * does not support any other input encoding. The G0 and G1 sets are therefore
41 * defined as subsets of UTF-8. You may still map G0-G3 into GL, though.
43 * However, the CSI/DCS/etc handlers are not designed after a specific VT
44 * series. We try to support all vt102 commands but implement several other
45 * often used sequences, too. Feel free to add further.
56 #ifdef BUILD_HAVE_XKBCOMMON
57 # include <xkbcommon/xkbcommon-keysyms.h>
59 # include "external/xkbcommon-keysyms.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;
553 vte->saved_state.cattr.blink = 0;
556 static void save_state(struct tsm_vte *vte)
558 vte->saved_state.cursor_x = tsm_screen_get_cursor_x(vte->con);
559 vte->saved_state.cursor_y = tsm_screen_get_cursor_y(vte->con);
560 vte->saved_state.cattr = vte->cattr;
561 vte->saved_state.gl = vte->gl;
562 vte->saved_state.gr = vte->gr;
563 vte->saved_state.wrap_mode = vte->flags & FLAG_AUTO_WRAP_MODE;
564 vte->saved_state.origin_mode = vte->flags & FLAG_ORIGIN_MODE;
567 static void restore_state(struct tsm_vte *vte)
569 tsm_screen_move_to(vte->con, vte->saved_state.cursor_x,
570 vte->saved_state.cursor_y);
571 vte->cattr = vte->saved_state.cattr;
572 to_rgb(vte, &vte->cattr);
573 if (vte->flags & FLAG_BACKGROUND_COLOR_ERASE_MODE)
574 tsm_screen_set_def_attr(vte->con, &vte->cattr);
575 vte->gl = vte->saved_state.gl;
576 vte->gr = vte->saved_state.gr;
578 if (vte->saved_state.wrap_mode) {
579 vte->flags |= FLAG_AUTO_WRAP_MODE;
580 tsm_screen_set_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
582 vte->flags &= ~FLAG_AUTO_WRAP_MODE;
583 tsm_screen_reset_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
586 if (vte->saved_state.origin_mode) {
587 vte->flags |= FLAG_ORIGIN_MODE;
588 tsm_screen_set_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
590 vte->flags &= ~FLAG_ORIGIN_MODE;
591 tsm_screen_reset_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
597 * This performs a soft reset of the VTE. That is, everything is reset to the
598 * same state as when the VTE was created. This does not affect the console,
602 void tsm_vte_reset(struct tsm_vte *vte)
608 vte->flags |= FLAG_TEXT_CURSOR_MODE;
609 vte->flags |= FLAG_AUTO_REPEAT_MODE;
610 vte->flags |= FLAG_SEND_RECEIVE_MODE;
611 vte->flags |= FLAG_AUTO_WRAP_MODE;
612 vte->flags |= FLAG_BACKGROUND_COLOR_ERASE_MODE;
613 tsm_screen_reset(vte->con);
614 tsm_screen_set_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
616 tsm_utf8_mach_reset(vte->mach);
617 vte->state = STATE_GROUND;
622 vte->g0 = &tsm_vte_unicode_lower;
623 vte->g1 = &tsm_vte_unicode_upper;
624 vte->g2 = &tsm_vte_unicode_lower;
625 vte->g3 = &tsm_vte_unicode_upper;
627 memcpy(&vte->cattr, &vte->def_attr, sizeof(vte->cattr));
628 to_rgb(vte, &vte->cattr);
629 tsm_screen_set_def_attr(vte->con, &vte->def_attr);
635 void tsm_vte_hard_reset(struct tsm_vte *vte)
638 tsm_screen_erase_screen(vte->con, false);
639 tsm_screen_clear_sb(vte->con);
640 tsm_screen_move_to(vte->con, 0, 0);
643 static void send_primary_da(struct tsm_vte *vte)
645 vte_write(vte, "\e[?60;1;6;9;15c", 17);
648 /* execute control character (C0 or C1) */
649 static void do_execute(struct tsm_vte *vte, uint32_t ctrl)
653 /* Ignore on input */
656 /* Transmit answerback message */
657 /* TODO: is there a better answer than ACK? */
658 vte_write(vte, "\x06", 1);
661 /* Sound bell tone */
662 /* TODO: I always considered this annying, however, we
663 * should at least provide some way to enable it if the
664 * user *really* wants it.
668 /* Move cursor one position left */
669 tsm_screen_move_left(vte->con, 1);
672 /* Move to next tab stop or end of line */
673 tsm_screen_tab_right(vte->con, 1);
678 /* Line feed or newline (CR/NL mode) */
679 if (vte->flags & FLAG_LINE_FEED_NEW_LINE_MODE)
680 tsm_screen_newline(vte->con);
682 tsm_screen_move_down(vte->con, 1, true);
685 /* Move cursor to left margin */
686 tsm_screen_move_line_home(vte->con);
689 /* Map G1 character set into GL */
693 /* Map G0 character set into GL */
697 /* Resume transmission */
700 case 0x13: /* XOFF */
701 /* Stop transmission */
705 /* Cancel escape sequence */
706 /* nothing to do here */
709 /* Discard current escape sequence and show err-sym */
710 write_console(vte, 0xbf);
713 /* Invokes an escape sequence */
714 /* nothing to do here */
720 /* Move down one row, perform scroll-up if needed */
721 tsm_screen_move_down(vte->con, 1, true);
724 /* CR/NL with scroll-up if needed */
725 tsm_screen_newline(vte->con);
728 /* Set tab stop at current position */
729 tsm_screen_set_tabstop(vte->con);
732 /* Move up one row, perform scroll-down if needed */
733 tsm_screen_move_up(vte->con, 1, true);
736 /* Temporarily map G2 into GL for next char only */
740 /* Temporarily map G3 into GL for next char only */
743 case 0x9a: /* DECID */
744 /* Send device attributes response like ANSI DA */
745 send_primary_da(vte);
748 /* End control string */
749 /* nothing to do here */
752 llog_debug(vte, "unhandled control char %u", ctrl);
756 static void do_clear(struct tsm_vte *vte)
761 for (i = 0; i < CSI_ARG_MAX; ++i)
762 vte->csi_argv[i] = -1;
766 static void do_collect(struct tsm_vte *vte, uint32_t data)
770 vte->csi_flags |= CSI_BANG;
773 vte->csi_flags |= CSI_CASH;
776 vte->csi_flags |= CSI_WHAT;
779 vte->csi_flags |= CSI_GT;
782 vte->csi_flags |= CSI_SPACE;
785 vte->csi_flags |= CSI_SQUOTE;
788 vte->csi_flags |= CSI_DQUOTE;
791 vte->csi_flags |= CSI_MULT;
794 vte->csi_flags |= CSI_PLUS;
797 vte->csi_flags |= CSI_POPEN;
800 vte->csi_flags |= CSI_PCLOSE;
805 static void do_param(struct tsm_vte *vte, uint32_t data)
810 if (vte->csi_argc < CSI_ARG_MAX)
815 if (vte->csi_argc >= CSI_ARG_MAX)
818 /* avoid integer overflows; max allowed value is 16384 anyway */
819 if (vte->csi_argv[vte->csi_argc] > 0xffff)
822 if (data >= '0' && data <= '9') {
823 new = vte->csi_argv[vte->csi_argc];
827 new = new * 10 + data - '0';
828 vte->csi_argv[vte->csi_argc] = new;
832 static bool set_charset(struct tsm_vte *vte, tsm_vte_charset *set)
834 if (vte->csi_flags & CSI_POPEN)
836 else if (vte->csi_flags & CSI_PCLOSE)
838 else if (vte->csi_flags & CSI_MULT)
840 else if (vte->csi_flags & CSI_PLUS)
848 static void do_esc(struct tsm_vte *vte, uint32_t data)
851 case 'B': /* map ASCII into G0-G3 */
852 if (set_charset(vte, &tsm_vte_unicode_lower))
855 case '<': /* map DEC supplemental into G0-G3 */
856 if (set_charset(vte, &tsm_vte_dec_supplemental_graphics))
859 case '0': /* map DEC special into G0-G3 */
860 if (set_charset(vte, &tsm_vte_dec_special_graphics))
863 case 'A': /* map British into G0-G3 */
864 /* TODO: create British charset from DEC */
865 if (set_charset(vte, &tsm_vte_unicode_upper))
868 case '4': /* map Dutch into G0-G3 */
869 /* TODO: create Dutch charset from DEC */
870 if (set_charset(vte, &tsm_vte_unicode_upper))
874 case '5': /* map Finnish into G0-G3 */
875 /* TODO: create Finnish charset from DEC */
876 if (set_charset(vte, &tsm_vte_unicode_upper))
879 case 'R': /* map French into G0-G3 */
880 /* TODO: create French charset from DEC */
881 if (set_charset(vte, &tsm_vte_unicode_upper))
884 case 'Q': /* map French-Canadian into G0-G3 */
885 /* TODO: create French-Canadian charset from DEC */
886 if (set_charset(vte, &tsm_vte_unicode_upper))
889 case 'K': /* map German into G0-G3 */
890 /* TODO: create German charset from DEC */
891 if (set_charset(vte, &tsm_vte_unicode_upper))
894 case 'Y': /* map Italian into G0-G3 */
895 /* TODO: create Italian charset from DEC */
896 if (set_charset(vte, &tsm_vte_unicode_upper))
900 case '6': /* map Norwegian/Danish into G0-G3 */
901 /* TODO: create Norwegian/Danish charset from DEC */
902 if (set_charset(vte, &tsm_vte_unicode_upper))
905 case 'Z': /* map Spanish into G0-G3 */
906 /* TODO: create Spanish charset from DEC */
907 if (set_charset(vte, &tsm_vte_unicode_upper))
911 case '7': /* map Swedish into G0-G3 */
912 /* TODO: create Swedish charset from DEC */
913 if (set_charset(vte, &tsm_vte_unicode_upper))
916 case '=': /* map Swiss into G0-G3 */
917 /* TODO: create Swiss charset from DEC */
918 if (set_charset(vte, &tsm_vte_unicode_upper))
922 if (vte->csi_flags & CSI_SPACE) {
924 /* Disable 8bit C1 mode */
925 vte->flags &= ~FLAG_USE_C1;
930 if (vte->csi_flags & CSI_SPACE) {
932 /* Enable 8bit C1 mode */
933 vte->flags |= FLAG_USE_C1;
939 /* everything below is only valid without CSI flags */
940 if (vte->csi_flags) {
941 llog_debug(vte, "unhandled escape seq %u", data);
947 /* Move down one row, perform scroll-up if needed */
948 tsm_screen_move_down(vte->con, 1, true);
951 /* CR/NL with scroll-up if needed */
952 tsm_screen_newline(vte->con);
955 /* Set tab stop at current position */
956 tsm_screen_set_tabstop(vte->con);
959 /* Move up one row, perform scroll-down if needed */
960 tsm_screen_move_up(vte->con, 1, true);
963 /* Temporarily map G2 into GL for next char only */
967 /* Temporarily map G3 into GL for next char only */
970 case 'Z': /* DECID */
971 /* Send device attributes response like ANSI DA */
972 send_primary_da(vte);
975 /* End control string */
976 /* nothing to do here */
979 /* Invoke G1 into GR */
983 /* Invoke G2 into GL */
987 /* Invoke G2 into GR */
991 /* Invoke G3 into GL */
995 /* Invoke G3 into GR */
998 case '=': /* DECKPAM */
999 /* Set application keypad mode */
1000 vte->flags |= FLAG_KEYPAD_APPLICATION_MODE;
1002 case '>': /* DECKPNM */
1003 /* Set numeric keypad mode */
1004 vte->flags &= ~FLAG_KEYPAD_APPLICATION_MODE;
1008 tsm_vte_hard_reset(vte);
1010 case '7': /* DECSC */
1011 /* save console state */
1014 case '8': /* DECRC */
1015 /* restore console state */
1019 llog_debug(vte, "unhandled escape seq %u", data);
1023 static void csi_attribute(struct tsm_vte *vte)
1025 static const uint8_t bval[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
1026 unsigned int i, code;
1028 if (vte->csi_argc <= 1 && vte->csi_argv[0] == -1) {
1030 vte->csi_argv[0] = 0;
1033 for (i = 0; i < vte->csi_argc; ++i) {
1034 switch (vte->csi_argv[i]) {
1038 copy_fcolor(&vte->cattr, &vte->def_attr);
1039 copy_bcolor(&vte->cattr, &vte->def_attr);
1040 vte->cattr.bold = 0;
1041 vte->cattr.underline = 0;
1042 vte->cattr.inverse = 0;
1043 vte->cattr.blink = 0;
1046 vte->cattr.bold = 1;
1049 vte->cattr.underline = 1;
1052 vte->cattr.blink = 1;
1055 vte->cattr.inverse = 1;
1058 vte->cattr.bold = 0;
1061 vte->cattr.underline = 0;
1064 vte->cattr.blink = 0;
1067 vte->cattr.inverse = 0;
1070 vte->cattr.fccode = COLOR_BLACK;
1073 vte->cattr.fccode = COLOR_RED;
1076 vte->cattr.fccode = COLOR_GREEN;
1079 vte->cattr.fccode = COLOR_YELLOW;
1082 vte->cattr.fccode = COLOR_BLUE;
1085 vte->cattr.fccode = COLOR_MAGENTA;
1088 vte->cattr.fccode = COLOR_CYAN;
1091 vte->cattr.fccode = COLOR_LIGHT_GREY;
1094 copy_fcolor(&vte->cattr, &vte->def_attr);
1097 vte->cattr.bccode = COLOR_BLACK;
1100 vte->cattr.bccode = COLOR_RED;
1103 vte->cattr.bccode = COLOR_GREEN;
1106 vte->cattr.bccode = COLOR_YELLOW;
1109 vte->cattr.bccode = COLOR_BLUE;
1112 vte->cattr.bccode = COLOR_MAGENTA;
1115 vte->cattr.bccode = COLOR_CYAN;
1118 vte->cattr.bccode = COLOR_LIGHT_GREY;
1121 copy_bcolor(&vte->cattr, &vte->def_attr);
1124 vte->cattr.fccode = COLOR_DARK_GREY;
1127 vte->cattr.fccode = COLOR_LIGHT_RED;
1130 vte->cattr.fccode = COLOR_LIGHT_GREEN;
1133 vte->cattr.fccode = COLOR_LIGHT_YELLOW;
1136 vte->cattr.fccode = COLOR_LIGHT_BLUE;
1139 vte->cattr.fccode = COLOR_LIGHT_MAGENTA;
1142 vte->cattr.fccode = COLOR_LIGHT_CYAN;
1145 vte->cattr.fccode = COLOR_WHITE;
1148 vte->cattr.bccode = COLOR_DARK_GREY;
1151 vte->cattr.bccode = COLOR_LIGHT_RED;
1154 vte->cattr.bccode = COLOR_LIGHT_GREEN;
1157 vte->cattr.bccode = COLOR_LIGHT_YELLOW;
1160 vte->cattr.bccode = COLOR_LIGHT_BLUE;
1163 vte->cattr.bccode = COLOR_LIGHT_MAGENTA;
1166 vte->cattr.bccode = COLOR_LIGHT_CYAN;
1169 vte->cattr.bccode = COLOR_WHITE;
1174 if (i + 2 >= vte->csi_argc ||
1175 vte->csi_argv[i + 1] != 5 ||
1176 vte->csi_argv[i + 2] < 0) {
1177 llog_debug(vte, "invalid 256color SGR");
1181 code = vte->csi_argv[i + 2];
1182 if (vte->csi_argv[i] == 38) {
1184 vte->cattr.fccode = code;
1185 } else if (code < 232) {
1186 vte->cattr.fccode = -1;
1188 vte->cattr.fb = bval[code % 6];
1190 vte->cattr.fg = bval[code % 6];
1192 vte->cattr.fr = bval[code % 6];
1194 vte->cattr.fccode = -1;
1195 code = (code - 232) * 10 + 8;
1196 vte->cattr.fr = code;
1197 vte->cattr.fg = code;
1198 vte->cattr.fb = code;
1202 vte->cattr.bccode = code;
1203 } else if (code < 232) {
1204 vte->cattr.bccode = -1;
1206 vte->cattr.bb = bval[code % 6];
1208 vte->cattr.bg = bval[code % 6];
1210 vte->cattr.br = bval[code % 6];
1212 vte->cattr.bccode = -1;
1213 code = (code - 232) * 10 + 8;
1214 vte->cattr.br = code;
1215 vte->cattr.bg = code;
1216 vte->cattr.bb = code;
1223 llog_debug(vte, "unhandled SGR attr %i",
1228 to_rgb(vte, &vte->cattr);
1229 if (vte->flags & FLAG_BACKGROUND_COLOR_ERASE_MODE)
1230 tsm_screen_set_def_attr(vte->con, &vte->cattr);
1233 static void csi_soft_reset(struct tsm_vte *vte)
1238 static void csi_compat_mode(struct tsm_vte *vte)
1240 /* always perform soft reset */
1241 csi_soft_reset(vte);
1243 if (vte->csi_argv[0] == 61) {
1244 /* Switching to VT100 compatibility mode. We do
1245 * not support this mode, so ignore it. In fact,
1246 * we are almost compatible to it, anyway, so
1247 * there is no need to explicitly select it.
1248 * However, we enable 7bit mode to avoid
1249 * character-table problems */
1250 vte->flags |= FLAG_7BIT_MODE;
1251 vte->g0 = &tsm_vte_unicode_lower;
1252 vte->g1 = &tsm_vte_dec_supplemental_graphics;
1253 } else if (vte->csi_argv[0] == 62 ||
1254 vte->csi_argv[0] == 63 ||
1255 vte->csi_argv[0] == 64) {
1256 /* Switching to VT2/3/4 compatibility mode. We
1257 * are always compatible with this so ignore it.
1258 * We always send 7bit controls so we also do
1259 * not care for the parameter value here that
1260 * select the control-mode.
1261 * VT220 defines argument 2 as 7bit mode but
1262 * VT3xx up to VT5xx use it as 8bit mode. We
1263 * choose to conform with the latter here.
1264 * We also enable 8bit mode when VT220
1265 * compatibility is requested explicitly. */
1266 if (vte->csi_argv[1] == 1 ||
1267 vte->csi_argv[1] == 2)
1268 vte->flags |= FLAG_USE_C1;
1270 vte->flags |= FLAG_8BIT_MODE;
1271 vte->g0 = &tsm_vte_unicode_lower;
1272 vte->g1 = &tsm_vte_dec_supplemental_graphics;
1274 llog_debug(vte, "unhandled DECSCL 'p' CSI %i, switching to utf-8 mode again",
1279 static inline void set_reset_flag(struct tsm_vte *vte, bool set,
1285 vte->flags &= ~flag;
1288 static void csi_mode(struct tsm_vte *vte, bool set)
1292 for (i = 0; i < vte->csi_argc; ++i) {
1293 if (!(vte->csi_flags & CSI_WHAT)) {
1294 switch (vte->csi_argv[i]) {
1298 set_reset_flag(vte, set,
1299 FLAG_KEYBOARD_ACTION_MODE);
1302 set_reset_flag(vte, set,
1303 FLAG_INSERT_REPLACE_MODE);
1305 tsm_screen_set_flags(vte->con,
1306 TSM_SCREEN_INSERT_MODE);
1308 tsm_screen_reset_flags(vte->con,
1309 TSM_SCREEN_INSERT_MODE);
1312 set_reset_flag(vte, set,
1313 FLAG_SEND_RECEIVE_MODE);
1316 set_reset_flag(vte, set,
1317 FLAG_LINE_FEED_NEW_LINE_MODE);
1320 llog_debug(vte, "unknown non-DEC (Re)Set-Mode %d",
1326 switch (vte->csi_argv[i]) {
1329 case 1: /* DECCKM */
1330 set_reset_flag(vte, set, FLAG_CURSOR_KEY_MODE);
1332 case 2: /* DECANM */
1333 /* Select VT52 mode */
1334 /* We do not support VT52 mode. Is there any reason why
1335 * we should support it? We ignore it here and do not
1336 * mark it as to-do item unless someone has strong
1337 * arguments to support it. */
1339 case 3: /* DECCOLM */
1340 /* If set, select 132 column mode, otherwise use 80
1341 * column mode. If neither is selected explicitly, we
1342 * use dynamic mode, that is, we send SIGWCH when the
1343 * size changes and we allow arbitrary buffer
1344 * dimensions. On soft-reset, we automatically fall back
1345 * to the default, that is, dynamic mode.
1346 * Dynamic-mode can be forced to a static mode in the
1347 * config. That is, every time dynamic-mode becomes
1348 * active, the terminal will be set to the dimensions
1349 * that were selected in the config. This allows setting
1350 * a fixed size for the terminal regardless of the
1352 * TODO: Implement this */
1354 case 4: /* DECSCLM */
1355 /* Select smooth scrolling. We do not support the
1356 * classic smooth scrolling because we have a scrollback
1357 * buffer. There is no need to implement smooth
1358 * scrolling so ignore this here. */
1360 case 5: /* DECSCNM */
1361 set_reset_flag(vte, set, FLAG_INVERSE_SCREEN_MODE);
1363 tsm_screen_set_flags(vte->con,
1364 TSM_SCREEN_INVERSE);
1366 tsm_screen_reset_flags(vte->con,
1367 TSM_SCREEN_INVERSE);
1370 set_reset_flag(vte, set, FLAG_ORIGIN_MODE);
1372 tsm_screen_set_flags(vte->con,
1373 TSM_SCREEN_REL_ORIGIN);
1375 tsm_screen_reset_flags(vte->con,
1376 TSM_SCREEN_REL_ORIGIN);
1378 case 7: /* DECAWN */
1379 set_reset_flag(vte, set, FLAG_AUTO_WRAP_MODE);
1381 tsm_screen_set_flags(vte->con,
1382 TSM_SCREEN_AUTO_WRAP);
1384 tsm_screen_reset_flags(vte->con,
1385 TSM_SCREEN_AUTO_WRAP);
1387 case 8: /* DECARM */
1388 set_reset_flag(vte, set, FLAG_AUTO_REPEAT_MODE);
1390 case 12: /* blinking cursor */
1391 /* TODO: implement */
1393 case 18: /* DECPFF */
1394 /* If set, a form feed (FF) is sent to the printer after
1395 * every screen that is printed. We don't have printers
1396 * these days directly attached to terminals so we
1397 * ignore this here. */
1399 case 19: /* DECPEX */
1400 /* If set, the full screen is printed instead of
1401 * scrolling region only. We have no printer so ignore
1404 case 25: /* DECTCEM */
1405 set_reset_flag(vte, set, FLAG_TEXT_CURSOR_MODE);
1407 tsm_screen_reset_flags(vte->con,
1408 TSM_SCREEN_HIDE_CURSOR);
1410 tsm_screen_set_flags(vte->con,
1411 TSM_SCREEN_HIDE_CURSOR);
1413 case 42: /* DECNRCM */
1414 set_reset_flag(vte, set, FLAG_NATIONAL_CHARSET_MODE);
1416 case 47: /* Alternate screen buffer */
1417 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1421 tsm_screen_set_flags(vte->con,
1422 TSM_SCREEN_ALTERNATE);
1424 tsm_screen_reset_flags(vte->con,
1425 TSM_SCREEN_ALTERNATE);
1427 case 1047: /* Alternate screen buffer with post-erase */
1428 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1432 tsm_screen_set_flags(vte->con,
1433 TSM_SCREEN_ALTERNATE);
1435 tsm_screen_erase_screen(vte->con, false);
1436 tsm_screen_reset_flags(vte->con,
1437 TSM_SCREEN_ALTERNATE);
1440 case 1048: /* Set/Reset alternate-screen buffer cursor */
1441 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1446 tsm_screen_get_cursor_x(vte->con);
1448 tsm_screen_get_cursor_y(vte->con);
1450 tsm_screen_move_to(vte->con, vte->alt_cursor_x,
1454 case 1049: /* Alternate screen buffer with pre-erase+cursor */
1455 if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1460 tsm_screen_get_cursor_x(vte->con);
1462 tsm_screen_get_cursor_y(vte->con);
1463 tsm_screen_set_flags(vte->con,
1464 TSM_SCREEN_ALTERNATE);
1465 tsm_screen_erase_screen(vte->con, false);
1467 tsm_screen_reset_flags(vte->con,
1468 TSM_SCREEN_ALTERNATE);
1469 tsm_screen_move_to(vte->con, vte->alt_cursor_x,
1474 llog_debug(vte, "unknown DEC %set-Mode %d",
1475 set?"S":"Res", vte->csi_argv[i]);
1481 static void csi_dev_attr(struct tsm_vte *vte)
1483 if (vte->csi_argc <= 1 && vte->csi_argv[0] <= 0) {
1484 if (vte->csi_flags == 0) {
1485 send_primary_da(vte);
1487 } else if (vte->csi_flags & CSI_GT) {
1488 vte_write(vte, "\e[>1;1;0c", 9);
1493 llog_debug(vte, "unhandled DA: %x %d %d %d...", vte->csi_flags,
1494 vte->csi_argv[0], vte->csi_argv[1], vte->csi_argv[2]);
1497 static void csi_dsr(struct tsm_vte *vte)
1500 unsigned int x, y, len;
1502 if (vte->csi_argv[0] == 5) {
1503 vte_write(vte, "\e[0n", 4);
1504 } else if (vte->csi_argv[0] == 6) {
1505 x = tsm_screen_get_cursor_x(vte->con);
1506 y = tsm_screen_get_cursor_y(vte->con);
1507 len = snprintf(buf, sizeof(buf), "\e[%u;%uR", x, y);
1508 if (len >= sizeof(buf))
1509 vte_write(vte, "\e[0;0R", 6);
1511 vte_write(vte, buf, len);
1515 static void do_csi(struct tsm_vte *vte, uint32_t data)
1517 int num, x, y, upper, lower;
1520 if (vte->csi_argc < CSI_ARG_MAX)
1525 /* move cursor up */
1526 num = vte->csi_argv[0];
1529 tsm_screen_move_up(vte->con, num, false);
1532 /* move cursor down */
1533 num = vte->csi_argv[0];
1536 tsm_screen_move_down(vte->con, num, false);
1539 /* move cursor forward */
1540 num = vte->csi_argv[0];
1543 tsm_screen_move_right(vte->con, num);
1546 /* move cursor backward */
1547 num = vte->csi_argv[0];
1550 tsm_screen_move_left(vte->con, num);
1553 /* Vertical Line Position Absolute */
1554 num = vte->csi_argv[0];
1557 x = tsm_screen_get_cursor_x(vte->con);
1558 tsm_screen_move_to(vte->con, x, num - 1);
1561 /* Vertical Line Position Relative */
1562 num = vte->csi_argv[0];
1565 x = tsm_screen_get_cursor_x(vte->con);
1566 y = tsm_screen_get_cursor_y(vte->con);
1567 tsm_screen_move_to(vte->con, x, y + num);
1571 /* position cursor */
1572 x = vte->csi_argv[0];
1575 y = vte->csi_argv[1];
1578 tsm_screen_move_to(vte->con, y - 1, x - 1);
1581 /* Cursor Character Absolute */
1582 num = vte->csi_argv[0];
1585 y = tsm_screen_get_cursor_y(vte->con);
1586 tsm_screen_move_to(vte->con, num - 1, y);
1589 if (vte->csi_flags & CSI_WHAT)
1594 if (vte->csi_argv[0] <= 0)
1595 tsm_screen_erase_cursor_to_screen(vte->con,
1597 else if (vte->csi_argv[0] == 1)
1598 tsm_screen_erase_screen_to_cursor(vte->con,
1600 else if (vte->csi_argv[0] == 2)
1601 tsm_screen_erase_screen(vte->con, protect);
1603 llog_debug(vte, "unknown parameter to CSI-J: %d",
1607 if (vte->csi_flags & CSI_WHAT)
1612 if (vte->csi_argv[0] <= 0)
1613 tsm_screen_erase_cursor_to_end(vte->con, protect);
1614 else if (vte->csi_argv[0] == 1)
1615 tsm_screen_erase_home_to_cursor(vte->con, protect);
1616 else if (vte->csi_argv[0] == 2)
1617 tsm_screen_erase_current_line(vte->con, protect);
1619 llog_debug(vte, "unknown parameter to CSI-K: %d",
1623 /* erase characters */
1624 num = vte->csi_argv[0];
1627 tsm_screen_erase_chars(vte->con, num);
1633 if (vte->csi_flags & CSI_GT) {
1634 /* xterm: select X11 visual cursor mode */
1635 csi_soft_reset(vte);
1636 } else if (vte->csi_flags & CSI_BANG) {
1637 /* DECSTR: Soft Reset */
1638 csi_soft_reset(vte);
1639 } else if (vte->csi_flags & CSI_CASH) {
1640 /* DECRQM: Request DEC Private Mode */
1641 /* If CSI_WHAT is set, then enable,
1642 * otherwise disable */
1643 csi_soft_reset(vte);
1645 /* DECSCL: Compatibility Level */
1646 /* Sometimes CSI_DQUOTE is set here, too */
1647 csi_compat_mode(vte);
1650 case 'h': /* SM: Set Mode */
1651 csi_mode(vte, true);
1653 case 'l': /* RM: Reset Mode */
1654 csi_mode(vte, false);
1656 case 'r': /* DECSTBM */
1657 /* set margin size */
1658 upper = vte->csi_argv[0];
1661 lower = vte->csi_argv[1];
1664 tsm_screen_set_margins(vte->con, upper, lower);
1667 /* device attributes */
1672 num = vte->csi_argv[0];
1675 tsm_screen_insert_lines(vte->con, num);
1679 num = vte->csi_argv[0];
1682 tsm_screen_delete_lines(vte->con, num);
1685 /* tabulation clear */
1686 num = vte->csi_argv[0];
1688 tsm_screen_reset_tabstop(vte->con);
1690 tsm_screen_reset_all_tabstops(vte->con);
1692 llog_debug(vte, "invalid parameter %d to TBC CSI", num);
1695 /* insert characters */
1696 num = vte->csi_argv[0];
1699 tsm_screen_insert_chars(vte->con, num);
1702 /* delete characters */
1703 num = vte->csi_argv[0];
1706 tsm_screen_delete_chars(vte->con, num);
1709 /* cursor horizontal backwards tab */
1710 num = vte->csi_argv[0];
1713 tsm_screen_tab_left(vte->con, num);
1716 /* cursor horizontal forward tab */
1717 num = vte->csi_argv[0];
1720 tsm_screen_tab_right(vte->con, num);
1723 /* device status reports */
1728 num = vte->csi_argv[0];
1731 tsm_screen_scroll_up(vte->con, num);
1735 num = vte->csi_argv[0];
1738 tsm_screen_scroll_down(vte->con, num);
1741 llog_debug(vte, "unhandled CSI sequence %c", data);
1745 /* map a character according to current GL and GR maps */
1746 static uint32_t vte_map(struct tsm_vte *vte, uint32_t val)
1748 /* 32, 127, 160 and 255 map to identity like all values >255 */
1752 val = (**vte->glt)[val - 32];
1755 val = (**vte->gl)[val - 32];
1760 val = (**vte->grt)[val - 160];
1763 val = (**vte->gr)[val - 160];
1771 /* perform parser action */
1772 static void do_action(struct tsm_vte *vte, uint32_t data, int action)
1781 /* ignore character */
1784 sym = tsm_symbol_make(vte_map(vte, data));
1785 write_console(vte, sym);
1787 case ACTION_EXECUTE:
1788 do_execute(vte, data);
1793 case ACTION_COLLECT:
1794 do_collect(vte, data);
1797 do_param(vte, data);
1799 case ACTION_ESC_DISPATCH:
1802 case ACTION_CSI_DISPATCH:
1805 case ACTION_DCS_START:
1807 case ACTION_DCS_COLLECT:
1809 case ACTION_DCS_END:
1811 case ACTION_OSC_START:
1813 case ACTION_OSC_COLLECT:
1815 case ACTION_OSC_END:
1818 llog_warn(vte, "invalid action %d", action);
1822 /* entry actions to be performed when entering the selected state */
1823 static const int entry_action[] = {
1824 [STATE_CSI_ENTRY] = ACTION_CLEAR,
1825 [STATE_DCS_ENTRY] = ACTION_CLEAR,
1826 [STATE_DCS_PASS] = ACTION_DCS_START,
1827 [STATE_ESC] = ACTION_CLEAR,
1828 [STATE_OSC_STRING] = ACTION_OSC_START,
1829 [STATE_NUM] = ACTION_NONE,
1832 /* exit actions to be performed when leaving the selected state */
1833 static const int exit_action[] = {
1834 [STATE_DCS_PASS] = ACTION_DCS_END,
1835 [STATE_OSC_STRING] = ACTION_OSC_END,
1836 [STATE_NUM] = ACTION_NONE,
1839 /* perform state transition and dispatch related actions */
1840 static void do_trans(struct tsm_vte *vte, uint32_t data, int state, int act)
1842 if (state != STATE_NONE) {
1843 /* A state transition occurs. Perform exit-action,
1844 * transition-action and entry-action. Even when performing a
1845 * transition to the same state as the current state we do this.
1846 * Use STATE_NONE if this is not the desired behavior.
1848 do_action(vte, data, exit_action[vte->state]);
1849 do_action(vte, data, act);
1850 do_action(vte, data, entry_action[state]);
1853 do_action(vte, data, act);
1858 * Escape sequence parser
1859 * This parses the new input character \data. It performs state transition and
1860 * calls the right callbacks for each action.
1862 static void parse_data(struct tsm_vte *vte, uint32_t raw)
1864 /* events that may occur in any state */
1873 do_trans(vte, raw, STATE_GROUND, ACTION_EXECUTE);
1876 do_trans(vte, raw, STATE_ESC, ACTION_NONE);
1881 do_trans(vte, raw, STATE_ST_IGNORE, ACTION_NONE);
1884 do_trans(vte, raw, STATE_DCS_ENTRY, ACTION_NONE);
1887 do_trans(vte, raw, STATE_OSC_STRING, ACTION_NONE);
1890 do_trans(vte, raw, STATE_CSI_ENTRY, ACTION_NONE);
1894 /* events that depend on the current state */
1895 switch (vte->state) {
1904 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1907 do_trans(vte, raw, STATE_NONE, ACTION_PRINT);
1910 do_trans(vte, raw, STATE_NONE, ACTION_PRINT);
1917 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1920 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1923 do_trans(vte, raw, STATE_ESC_INT, ACTION_COLLECT);
1931 do_trans(vte, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1934 do_trans(vte, raw, STATE_CSI_ENTRY, ACTION_NONE);
1937 do_trans(vte, raw, STATE_OSC_STRING, ACTION_NONE);
1940 do_trans(vte, raw, STATE_DCS_ENTRY, ACTION_NONE);
1945 do_trans(vte, raw, STATE_ST_IGNORE, ACTION_NONE);
1948 do_trans(vte, raw, STATE_ESC_INT, ACTION_COLLECT);
1955 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1958 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1961 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1964 do_trans(vte, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1967 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1969 case STATE_CSI_ENTRY:
1974 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1977 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1980 do_trans(vte, raw, STATE_CSI_INT, ACTION_COLLECT);
1983 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1987 do_trans(vte, raw, STATE_CSI_PARAM, ACTION_PARAM);
1990 do_trans(vte, raw, STATE_CSI_PARAM, ACTION_COLLECT);
1993 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1996 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1998 case STATE_CSI_PARAM:
2003 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
2007 do_trans(vte, raw, STATE_NONE, ACTION_PARAM);
2010 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2014 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2017 do_trans(vte, raw, STATE_CSI_INT, ACTION_COLLECT);
2020 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
2023 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2030 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
2033 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
2036 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2039 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2042 do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
2045 do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
2047 case STATE_CSI_IGNORE:
2052 do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
2056 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2059 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2062 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2064 case STATE_DCS_ENTRY:
2070 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2073 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2076 do_trans(vte, raw, STATE_DCS_INT, ACTION_COLLECT);
2080 do_trans(vte, raw, STATE_DCS_PARAM, ACTION_PARAM);
2083 do_trans(vte, raw, STATE_DCS_PARAM, ACTION_COLLECT);
2086 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2089 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2091 case STATE_DCS_PARAM:
2097 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2101 do_trans(vte, raw, STATE_NONE, ACTION_PARAM);
2105 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2108 do_trans(vte, raw, STATE_DCS_INT, ACTION_COLLECT);
2111 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2114 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2122 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2125 do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
2128 do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2131 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2134 do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2136 case STATE_DCS_PASS:
2142 do_trans(vte, raw, STATE_NONE, ACTION_DCS_COLLECT);
2145 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2148 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2151 do_trans(vte, raw, STATE_NONE, ACTION_DCS_COLLECT);
2153 case STATE_DCS_IGNORE:
2159 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2162 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2165 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2167 case STATE_OSC_STRING:
2173 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2176 do_trans(vte, raw, STATE_NONE, ACTION_OSC_COLLECT);
2180 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2183 do_trans(vte, raw, STATE_NONE, ACTION_OSC_COLLECT);
2185 case STATE_ST_IGNORE:
2191 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2194 do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2197 do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2201 llog_warn(vte, "unhandled input %u in state %d", raw, vte->state);
2205 void tsm_vte_input(struct tsm_vte *vte, const char *u8, size_t len)
2211 if (!vte || !vte->con)
2215 for (i = 0; i < len; ++i) {
2216 if (vte->flags & FLAG_7BIT_MODE) {
2218 llog_debug(vte, "receiving 8bit character U+%d from pty while in 7bit mode",
2220 parse_data(vte, u8[i] & 0x7f);
2221 } else if (vte->flags & FLAG_8BIT_MODE) {
2222 parse_data(vte, u8[i]);
2224 state = tsm_utf8_mach_feed(vte->mach, u8[i]);
2225 if (state == TSM_UTF8_ACCEPT ||
2226 state == TSM_UTF8_REJECT) {
2227 ucs4 = tsm_utf8_mach_get(vte->mach);
2228 parse_data(vte, ucs4);
2236 bool tsm_vte_handle_keyboard(struct tsm_vte *vte, uint32_t keysym,
2237 uint32_t ascii, unsigned int mods,
2244 /* MOD1 (mostly labeled 'Alt') prepends an escape character to every
2245 * input that is sent by a key.
2246 * TODO: Transform this huge handler into a lookup table to save a lot
2247 * of code and make such modifiers easier to implement.
2248 * Also check whether altSendsEscape should be the default (xterm
2249 * disables this by default, why?) and whether we should implement the
2250 * fallback shifting that xterm does. */
2251 if (mods & TSM_ALT_MASK)
2252 vte->flags |= FLAG_PREPEND_ESCAPE;
2254 /* A user might actually use multiple layouts for keyboard input. The
2255 * @keysym variable contains the actual keysym that the user used. But
2256 * if this keysym is not in the ascii range, the input handler does
2257 * check all other layouts that the user specified whether one of them
2258 * maps the key to some ASCII keysym and provides this via @ascii.
2259 * We always use the real keysym except when handling CTRL+<XY>
2260 * shortcuts we use the ascii keysym. This is for compatibility to xterm
2261 * et. al. so ctrl+c always works regardless of the currently active
2263 * But if no ascii-sym is found, we still use the real keysym. */
2265 if (sym == XKB_KEY_NoSymbol)
2268 if (mods & TSM_CONTROL_MASK) {
2272 vte_write(vte, "\x00", 1);
2276 vte_write(vte, "\x01", 1);
2280 vte_write(vte, "\x02", 1);
2284 vte_write(vte, "\x03", 1);
2288 vte_write(vte, "\x04", 1);
2292 vte_write(vte, "\x05", 1);
2296 vte_write(vte, "\x06", 1);
2300 vte_write(vte, "\x07", 1);
2304 vte_write(vte, "\x08", 1);
2308 vte_write(vte, "\x09", 1);
2312 vte_write(vte, "\x0a", 1);
2316 vte_write(vte, "\x0b", 1);
2320 vte_write(vte, "\x0c", 1);
2324 vte_write(vte, "\x0d", 1);
2328 vte_write(vte, "\x0e", 1);
2332 vte_write(vte, "\x0f", 1);
2336 vte_write(vte, "\x10", 1);
2340 vte_write(vte, "\x11", 1);
2344 vte_write(vte, "\x12", 1);
2348 vte_write(vte, "\x13", 1);
2352 vte_write(vte, "\x14", 1);
2356 vte_write(vte, "\x15", 1);
2360 vte_write(vte, "\x16", 1);
2364 vte_write(vte, "\x17", 1);
2368 vte_write(vte, "\x18", 1);
2372 vte_write(vte, "\x19", 1);
2376 vte_write(vte, "\x1a", 1);
2379 case XKB_KEY_bracketleft:
2380 case XKB_KEY_braceleft:
2381 vte_write(vte, "\x1b", 1);
2384 case XKB_KEY_backslash:
2386 vte_write(vte, "\x1c", 1);
2389 case XKB_KEY_bracketright:
2390 case XKB_KEY_braceright:
2391 vte_write(vte, "\x1d", 1);
2395 case XKB_KEY_asciitilde:
2396 vte_write(vte, "\x1e", 1);
2400 case XKB_KEY_question:
2401 vte_write(vte, "\x1f", 1);
2404 vte_write(vte, "\x7f", 1);
2410 case XKB_KEY_BackSpace:
2411 vte_write(vte, "\x08", 1);
2414 case XKB_KEY_KP_Tab:
2415 vte_write(vte, "\x09", 1);
2417 case XKB_KEY_ISO_Left_Tab:
2418 vte_write(vte, "\e[Z", 3);
2420 case XKB_KEY_Linefeed:
2421 vte_write(vte, "\x0a", 1);
2424 vte_write(vte, "\x0b", 1);
2427 TODO: What should we do with this key? Sending XOFF is awful as
2428 there is no simple way on modern keyboards to send XON
2429 again. If someone wants this, we can re-eanble it and set
2432 vte_write(vte, "\x13", 1);
2436 TODO: What should we do on scroll-lock? Sending 0x14 is what
2437 the specs say but it is not used today the way most
2438 users would expect so we disable it. If someone wants
2439 this, we can re-enable it and set some flag.
2440 case XKB_KEY_Scroll_Lock:
2441 vte_write(vte, "\x14", 1);
2444 case XKB_KEY_Sys_Req:
2445 vte_write(vte, "\x15", 1);
2447 case XKB_KEY_Escape:
2448 vte_write(vte, "\x1b", 1);
2450 case XKB_KEY_KP_Enter:
2451 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE) {
2452 vte_write(vte, "\eOM", 3);
2456 case XKB_KEY_Return:
2457 if (vte->flags & FLAG_LINE_FEED_NEW_LINE_MODE)
2458 vte_write(vte, "\x0d\x0a", 2);
2460 vte_write(vte, "\x0d", 1);
2463 vte_write(vte, "\e[1~", 4);
2465 case XKB_KEY_Insert:
2466 vte_write(vte, "\e[2~", 4);
2468 case XKB_KEY_Delete:
2469 vte_write(vte, "\e[3~", 4);
2471 case XKB_KEY_Select:
2472 vte_write(vte, "\e[4~", 4);
2474 case XKB_KEY_Page_Up:
2475 case XKB_KEY_KP_Page_Up:
2476 vte_write(vte, "\e[5~", 4);
2478 case XKB_KEY_KP_Page_Down:
2479 case XKB_KEY_Page_Down:
2480 vte_write(vte, "\e[6~", 4);
2484 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2485 vte_write(vte, "\eOA", 3);
2487 vte_write(vte, "\e[A", 3);
2490 case XKB_KEY_KP_Down:
2491 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2492 vte_write(vte, "\eOB", 3);
2494 vte_write(vte, "\e[B", 3);
2497 case XKB_KEY_KP_Right:
2498 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2499 vte_write(vte, "\eOC", 3);
2501 vte_write(vte, "\e[C", 3);
2504 case XKB_KEY_KP_Left:
2505 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2506 vte_write(vte, "\eOD", 3);
2508 vte_write(vte, "\e[D", 3);
2510 case XKB_KEY_KP_Insert:
2512 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2513 vte_write(vte, "\eOp", 3);
2515 vte_write(vte, "0", 1);
2518 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2519 vte_write(vte, "\eOq", 3);
2521 vte_write(vte, "1", 1);
2524 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2525 vte_write(vte, "\eOr", 3);
2527 vte_write(vte, "2", 1);
2530 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2531 vte_write(vte, "\eOs", 3);
2533 vte_write(vte, "3", 1);
2536 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2537 vte_write(vte, "\eOt", 3);
2539 vte_write(vte, "4", 1);
2542 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2543 vte_write(vte, "\eOu", 3);
2545 vte_write(vte, "5", 1);
2548 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2549 vte_write(vte, "\eOv", 3);
2551 vte_write(vte, "6", 1);
2554 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2555 vte_write(vte, "\eOw", 3);
2557 vte_write(vte, "7", 1);
2560 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2561 vte_write(vte, "\eOx", 3);
2563 vte_write(vte, "8", 1);
2566 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2567 vte_write(vte, "\eOy", 3);
2569 vte_write(vte, "9", 1);
2571 case XKB_KEY_KP_Subtract:
2572 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2573 vte_write(vte, "\eOm", 3);
2575 vte_write(vte, "-", 1);
2577 case XKB_KEY_KP_Separator:
2578 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2579 vte_write(vte, "\eOl", 3);
2581 vte_write(vte, ",", 1);
2583 case XKB_KEY_KP_Delete:
2584 case XKB_KEY_KP_Decimal:
2585 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2586 vte_write(vte, "\eOn", 3);
2588 vte_write(vte, ".", 1);
2590 case XKB_KEY_KP_Equal:
2591 case XKB_KEY_KP_Divide:
2592 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2593 vte_write(vte, "\eOj", 3);
2595 vte_write(vte, "/", 1);
2597 case XKB_KEY_KP_Multiply:
2598 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2599 vte_write(vte, "\eOo", 3);
2601 vte_write(vte, "*", 1);
2603 case XKB_KEY_KP_Add:
2604 if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2605 vte_write(vte, "\eOk", 3);
2607 vte_write(vte, "+", 1);
2610 case XKB_KEY_KP_Home:
2611 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2612 vte_write(vte, "\eOH", 3);
2614 vte_write(vte, "\e[H", 3);
2617 case XKB_KEY_KP_End:
2618 if (vte->flags & FLAG_CURSOR_KEY_MODE)
2619 vte_write(vte, "\eOF", 3);
2621 vte_write(vte, "\e[F", 3);
2623 case XKB_KEY_KP_Space:
2624 vte_write(vte, " ", 1);
2626 /* TODO: check what to transmit for functions keys when
2627 * shift/ctrl etc. are pressed. Every terminal behaves
2628 * differently here which is really weird.
2629 * We now map F4 to F14 if shift is pressed and so on for all
2630 * keys. However, such mappings should rather be done via
2631 * xkb-configurations and we should instead add a flags argument
2632 * to the CSIs as some of the keys here already do. */
2635 if (mods & TSM_SHIFT_MASK)
2636 vte_write(vte, "\e[23~", 5);
2638 vte_write(vte, "\eOP", 3);
2642 if (mods & TSM_SHIFT_MASK)
2643 vte_write(vte, "\e[24~", 5);
2645 vte_write(vte, "\eOQ", 3);
2649 if (mods & TSM_SHIFT_MASK)
2650 vte_write(vte, "\e[25~", 5);
2652 vte_write(vte, "\eOR", 3);
2656 if (mods & TSM_SHIFT_MASK)
2657 //vte_write(vte, "\e[1;2S", 6);
2658 vte_write(vte, "\e[26~", 5);
2660 vte_write(vte, "\eOS", 3);
2663 if (mods & TSM_SHIFT_MASK)
2664 //vte_write(vte, "\e[15;2~", 7);
2665 vte_write(vte, "\e[28~", 5);
2667 vte_write(vte, "\e[15~", 5);
2670 if (mods & TSM_SHIFT_MASK)
2671 //vte_write(vte, "\e[17;2~", 7);
2672 vte_write(vte, "\e[29~", 5);
2674 vte_write(vte, "\e[17~", 5);
2677 if (mods & TSM_SHIFT_MASK)
2678 //vte_write(vte, "\e[18;2~", 7);
2679 vte_write(vte, "\e[31~", 5);
2681 vte_write(vte, "\e[18~", 5);
2684 if (mods & TSM_SHIFT_MASK)
2685 //vte_write(vte, "\e[19;2~", 7);
2686 vte_write(vte, "\e[32~", 5);
2688 vte_write(vte, "\e[19~", 5);
2691 if (mods & TSM_SHIFT_MASK)
2692 //vte_write(vte, "\e[20;2~", 7);
2693 vte_write(vte, "\e[33~", 5);
2695 vte_write(vte, "\e[20~", 5);
2698 if (mods & TSM_SHIFT_MASK)
2699 //vte_write(vte, "\e[21;2~", 7);
2700 vte_write(vte, "\e[34~", 5);
2702 vte_write(vte, "\e[21~", 5);
2705 if (mods & TSM_SHIFT_MASK)
2706 vte_write(vte, "\e[23;2~", 7);
2708 vte_write(vte, "\e[23~", 5);
2711 if (mods & TSM_SHIFT_MASK)
2712 vte_write(vte, "\e[24;2~", 7);
2714 vte_write(vte, "\e[24~", 5);
2717 if (mods & TSM_SHIFT_MASK)
2718 vte_write(vte, "\e[25;2~", 7);
2720 vte_write(vte, "\e[25~", 5);
2723 if (mods & TSM_SHIFT_MASK)
2724 vte_write(vte, "\e[26;2~", 7);
2726 vte_write(vte, "\e[26~", 5);
2729 if (mods & TSM_SHIFT_MASK)
2730 vte_write(vte, "\e[28;2~", 7);
2732 vte_write(vte, "\e[28~", 5);
2735 if (mods & TSM_SHIFT_MASK)
2736 vte_write(vte, "\e[29;2~", 7);
2738 vte_write(vte, "\e[29~", 5);
2741 if (mods & TSM_SHIFT_MASK)
2742 vte_write(vte, "\e[31;2~", 7);
2744 vte_write(vte, "\e[31~", 5);
2747 if (mods & TSM_SHIFT_MASK)
2748 vte_write(vte, "\e[32;2~", 7);
2750 vte_write(vte, "\e[32~", 5);
2753 if (mods & TSM_SHIFT_MASK)
2754 vte_write(vte, "\e[33;2~", 7);
2756 vte_write(vte, "\e[33~", 5);
2759 if (mods & TSM_SHIFT_MASK)
2760 vte_write(vte, "\e[34;2~", 7);
2762 vte_write(vte, "\e[34~", 5);
2766 if (unicode != TSM_VTE_INVALID) {
2767 if (vte->flags & FLAG_7BIT_MODE) {
2769 if (unicode & 0x80) {
2770 llog_debug(vte, "invalid keyboard input in 7bit mode U+%x; mapping to '?'",
2774 vte_write(vte, &val, 1);
2775 } else if (vte->flags & FLAG_8BIT_MODE) {
2777 if (unicode > 0xff) {
2778 llog_debug(vte, "invalid keyboard input in 8bit mode U+%x; mapping to '?'",
2782 vte_write_raw(vte, &val, 1);
2784 len = tsm_ucs4_to_utf8(tsm_symbol_make(unicode), u8);
2785 vte_write_raw(vte, u8, len);
2790 vte->flags &= ~FLAG_PREPEND_ESCAPE;