1 /*
2  * libtsm - VT Emulator
3  *
4  * Copyright (c) 2018 Aetf <aetf@unlimitedcodeworks.xyz>
5  * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
6  *
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:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
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.
25  */
26 
27 /*
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.
35  *
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.
43  *
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.
47  */
48 
49 #include <errno.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include "libtsm.h"
54 #include "libtsm-int.h"
55 #include "shl-llog.h"
56 
57 #include <xkbcommon/xkbcommon-keysyms.h>
58 
59 #define LLOG_SUBSYSTEM "tsm-vte"
60 
61 /* Input parser states */
62 enum parser_state {
63 	STATE_NONE,		/* placeholder */
64 	STATE_GROUND,		/* initial state and ground */
65 	STATE_ESC,		/* ESC sequence was started */
66 	STATE_ESC_INT,		/* intermediate escape characters */
67 	STATE_CSI_ENTRY,	/* starting CSI sequence */
68 	STATE_CSI_PARAM,	/* CSI parameters */
69 	STATE_CSI_INT,		/* intermediate CSI characters */
70 	STATE_CSI_IGNORE,	/* CSI error; ignore this CSI sequence */
71 	STATE_DCS_ENTRY,	/* starting DCS sequence */
72 	STATE_DCS_PARAM,	/* DCS parameters */
73 	STATE_DCS_INT,		/* intermediate DCS characters */
74 	STATE_DCS_PASS,		/* DCS data passthrough */
75 	STATE_DCS_IGNORE,	/* DCS error; ignore this DCS sequence */
76 	STATE_OSC_STRING,	/* parsing OCS sequence */
77 	STATE_ST_IGNORE,	/* unimplemented seq; ignore until ST */
78 	STATE_NUM
79 };
80 
81 /* Input parser actions */
82 enum parser_action {
83 	ACTION_NONE,		/* placeholder */
84 	ACTION_IGNORE,		/* ignore the character entirely */
85 	ACTION_PRINT,		/* print the character on the console */
86 	ACTION_EXECUTE,		/* execute single control character (C0/C1) */
87 	ACTION_CLEAR,		/* clear current parameter state */
88 	ACTION_COLLECT,		/* collect intermediate character */
89 	ACTION_PARAM,		/* collect parameter character */
90 	ACTION_ESC_DISPATCH,	/* dispatch escape sequence */
91 	ACTION_CSI_DISPATCH,	/* dispatch csi sequence */
92 	ACTION_DCS_START,	/* start of DCS data */
93 	ACTION_DCS_COLLECT,	/* collect DCS data */
94 	ACTION_DCS_END,		/* end of DCS data */
95 	ACTION_OSC_START,	/* start of OSC data */
96 	ACTION_OSC_COLLECT,	/* collect OSC data */
97 	ACTION_OSC_END,		/* end of OSC data */
98 	ACTION_NUM
99 };
100 
101 /* CSI flags */
102 #define CSI_BANG	0x0001		/* CSI: ! */
103 #define CSI_CASH	0x0002		/* CSI: $ */
104 #define CSI_WHAT	0x0004		/* CSI: ? */
105 #define CSI_GT		0x0008		/* CSI: > */
106 #define CSI_SPACE	0x0010		/* CSI:   */
107 #define CSI_SQUOTE	0x0020		/* CSI: ' */
108 #define CSI_DQUOTE	0x0040		/* CSI: " */
109 #define CSI_MULT	0x0080		/* CSI: * */
110 #define CSI_PLUS	0x0100		/* CSI: + */
111 #define CSI_POPEN	0x0200		/* CSI: ( */
112 #define CSI_PCLOSE	0x0400		/* CSI: ) */
113 
114 /* max CSI arguments */
115 #define CSI_ARG_MAX 16
116 
117 /* terminal flags */
118 #define FLAG_CURSOR_KEY_MODE			0x00000001 /* DEC cursor key mode */
119 #define FLAG_KEYPAD_APPLICATION_MODE		0x00000002 /* DEC keypad application mode; TODO: toggle on numlock? */
120 #define FLAG_LINE_FEED_NEW_LINE_MODE		0x00000004 /* DEC line-feed/new-line mode */
121 #define FLAG_8BIT_MODE				0x00000008 /* Disable UTF-8 mode and enable 8bit compatible mode */
122 #define FLAG_7BIT_MODE				0x00000010 /* Disable 8bit mode and use 7bit compatible mode */
123 #define FLAG_USE_C1				0x00000020 /* Explicitly use 8bit C1 codes; TODO: implement */
124 #define FLAG_KEYBOARD_ACTION_MODE		0x00000040 /* Disable keyboard; TODO: implement? */
125 #define FLAG_INSERT_REPLACE_MODE		0x00000080 /* Enable insert mode */
126 #define FLAG_SEND_RECEIVE_MODE			0x00000100 /* Disable local echo */
127 #define FLAG_TEXT_CURSOR_MODE			0x00000200 /* Show cursor */
128 #define FLAG_INVERSE_SCREEN_MODE		0x00000400 /* Inverse colors */
129 #define FLAG_ORIGIN_MODE			0x00000800 /* Relative origin for cursor */
130 #define FLAG_AUTO_WRAP_MODE			0x00001000 /* Auto line wrap mode */
131 #define FLAG_AUTO_REPEAT_MODE			0x00002000 /* Auto repeat key press; TODO: implement */
132 #define FLAG_NATIONAL_CHARSET_MODE		0x00004000 /* Send keys from nation charsets; TODO: implement */
133 #define FLAG_BACKGROUND_COLOR_ERASE_MODE	0x00008000 /* Set background color on erase (bce) */
134 #define FLAG_PREPEND_ESCAPE			0x00010000 /* Prepend escape character to next output */
135 #define FLAG_TITE_INHIBIT_MODE			0x00020000 /* Prevent switching to alternate screen buffer */
136 #define FLAG_BRACKETED_PASTE_MODE		0x00040000
137 
138 #define ENDPASTE "\e[201~"
139 
140 struct vte_saved_state {
141 	int cursor_x;
142 	int cursor_y;
143 	struct tsm_screen_attr cattr;
144 	tsm_vte_charset **gl;
145 	tsm_vte_charset **gr;
146 	bool wrap_mode;
147 	bool origin_mode;
148 };
149 
150 struct tsm_vte {
151 	unsigned long ref;
152 	struct tsm_screen *con;
153 	tsm_vte_write_cb write_cb;
154 	void *data;
155 	char *palette_name;
156 
157 	struct tsm_utf8_mach *mach;
158 	unsigned long parse_cnt;
159 
160 	unsigned int state;
161 	tsm_symbol_t last_sym;
162 	int csi_argc;
163 	int csi_argv[CSI_ARG_MAX];
164 	unsigned int csi_flags;
165 
166 	uint8_t (*palette)[3];
167 	struct tsm_screen_attr def_attr;
168 	struct tsm_screen_attr cattr;
169 	unsigned int flags;
170 
171 	tsm_vte_charset **gl;
172 	tsm_vte_charset **gr;
173 	tsm_vte_charset **glt;
174 	tsm_vte_charset **grt;
175 	tsm_vte_charset *g0;
176 	tsm_vte_charset *g1;
177 	tsm_vte_charset *g2;
178 	tsm_vte_charset *g3;
179 
180 	struct vte_saved_state saved_state;
181 	int alt_cursor_x;
182 	int alt_cursor_y;
183 
184 	bool pasting;
185 	int endpaste_i;
186 };
187 
188 static uint8_t default_palette[TSM_COLOR_NUM][3] = {
189 	[TSM_COLOR_BLACK]         = {   0,   0,   0 }, /* black */
190 	[TSM_COLOR_RED]           = { 205,   0,   0 }, /* red */
191 	[TSM_COLOR_GREEN]         = {   0, 205,   0 }, /* green */
192 	[TSM_COLOR_YELLOW]        = { 205, 205,   0 }, /* yellow */
193 	[TSM_COLOR_BLUE]          = {   0,   0, 238 }, /* blue */
194 	[TSM_COLOR_MAGENTA]       = { 205,   0, 205 }, /* magenta */
195 	[TSM_COLOR_CYAN]          = {   0, 205, 205 }, /* cyan */
196 	[TSM_COLOR_LIGHT_GREY]    = { 229, 229, 229 }, /* light grey */
197 	[TSM_COLOR_DARK_GREY]     = { 127, 127, 127 }, /* dark grey */
198 	[TSM_COLOR_LIGHT_RED]     = { 255,   0,   0 }, /* light red */
199 	[TSM_COLOR_LIGHT_GREEN]   = {   0, 255,   0 }, /* light green */
200 	[TSM_COLOR_LIGHT_YELLOW]  = { 255, 255,   0 }, /* light yellow */
201 	[TSM_COLOR_LIGHT_BLUE]    = {  92,  92, 255 }, /* light blue */
202 	[TSM_COLOR_LIGHT_MAGENTA] = { 255,   0, 255 }, /* light magenta */
203 	[TSM_COLOR_LIGHT_CYAN]    = {   0, 255, 255 }, /* light cyan */
204 	[TSM_COLOR_WHITE]         = { 255, 255, 255 }, /* white */
205 
206 	[TSM_COLOR_FOREGROUND]    = { 229, 229, 229 }, /* light grey */
207 	[TSM_COLOR_BACKGROUND]    = {   0,   0,   0 }, /* black */
208 };
209 
210 /* Several effects may occur when non-RGB colors are used. For instance, if bold
211  * is enabled, then a dark color code is always converted to a light color to
212  * simulate bold (even though bold may actually be supported!). To support this,
213  * we need to differentiate between a set color-code and a set rgb-color.
214  * This function actually converts a set color-code into an RGB color. This must
215  * be called before passing the attribute to the console layer so the console
216  * layer can always work with RGB values and does not have to care for color
217  * codes. */
to_rgb(struct tsm_vte * vte,struct tsm_screen_attr * attr)218 static void to_rgb(struct tsm_vte *vte, struct tsm_screen_attr *attr)
219 {
220 	int8_t code;
221 
222 	code = attr->fccode;
223 	if (code >= 0) {
224 		/* bold causes light colors */
225 		if (attr->bold && code < 8)
226 			code += 8;
227 		if (code >= TSM_COLOR_NUM)
228 			code = TSM_COLOR_FOREGROUND;
229 
230 		attr->fr = vte->palette[code][0];
231 		attr->fg = vte->palette[code][1];
232 		attr->fb = vte->palette[code][2];
233 	}
234 
235 	code = attr->bccode;
236 	if (code >= 0) {
237 		if (code >= TSM_COLOR_NUM)
238 			code = TSM_COLOR_BACKGROUND;
239 
240 		attr->br = vte->palette[code][0];
241 		attr->bg = vte->palette[code][1];
242 		attr->bb = vte->palette[code][2];
243 	}
244 }
245 
copy_fcolor(struct tsm_screen_attr * dest,const struct tsm_screen_attr * src)246 static void copy_fcolor(struct tsm_screen_attr *dest,
247 			const struct tsm_screen_attr *src)
248 {
249 	dest->fccode = src->fccode;
250 	dest->fr = src->fr;
251 	dest->fg = src->fg;
252 	dest->fb = src->fb;
253 }
254 
copy_bcolor(struct tsm_screen_attr * dest,const struct tsm_screen_attr * src)255 static void copy_bcolor(struct tsm_screen_attr *dest,
256 			const struct tsm_screen_attr *src)
257 {
258 	dest->bccode = src->bccode;
259 	dest->br = src->br;
260 	dest->bg = src->bg;
261 	dest->bb = src->bb;
262 }
263 
264 SHL_EXPORT
tsm_vte_new(struct tsm_vte ** out,struct tsm_screen * con,tsm_vte_write_cb write_cb,void * data)265 int tsm_vte_new(struct tsm_vte **out, struct tsm_screen *con,
266 		tsm_vte_write_cb write_cb, void *data)
267 {
268 	struct tsm_vte *vte;
269 	int ret;
270 
271 	vte = malloc(sizeof(*vte));
272 	if (!vte)
273 		return -ENOMEM;
274 
275 	memset(vte, 0, sizeof(*vte));
276 	vte->ref = 1;
277 	vte->con = con;
278 	vte->write_cb = write_cb;
279 	vte->data = data;
280 	vte->palette = default_palette;
281 	vte->def_attr.fccode = TSM_COLOR_FOREGROUND;
282 	vte->def_attr.bccode = TSM_COLOR_BACKGROUND;
283 	to_rgb(vte, &vte->def_attr);
284 
285 	ret = tsm_utf8_mach_new(&vte->mach);
286 	if (ret)
287 		goto err_free;
288 
289 	tsm_vte_reset(vte);
290 	tsm_screen_erase_screen(vte->con, false);
291 
292 	tsm_screen_ref(vte->con);
293 	*out = vte;
294 	return 0;
295 
296 err_free:
297 	free(vte);
298 	return ret;
299 }
300 
301 SHL_EXPORT
tsm_vte_ref(struct tsm_vte * vte)302 void tsm_vte_ref(struct tsm_vte *vte)
303 {
304 	vte->ref++;
305 }
306 
307 SHL_EXPORT
tsm_vte_unref(struct tsm_vte * vte)308 void tsm_vte_unref(struct tsm_vte *vte)
309 {
310 	if (!vte->ref || --vte->ref)
311 		return;
312 
313 	tsm_screen_unref(vte->con);
314 	tsm_utf8_mach_free(vte->mach);
315 	free(vte);
316 }
317 
318 SHL_EXPORT
tsm_vte_set_palette(struct tsm_vte * vte,uint8_t (* palette)[3])319 int tsm_vte_set_palette(struct tsm_vte *vte, uint8_t (*palette)[3])
320 {
321 	vte->palette = palette;
322 	vte->def_attr.fccode = TSM_COLOR_FOREGROUND;
323 	vte->def_attr.bccode = TSM_COLOR_BACKGROUND;
324 
325 	to_rgb(vte, &vte->def_attr);
326 	memcpy(&vte->cattr, &vte->def_attr, sizeof(vte->cattr));
327 
328 	tsm_screen_set_def_attr(vte->con, &vte->def_attr);
329 	tsm_screen_erase_screen(vte->con, false);
330 
331 	return 0;
332 }
333 
334 SHL_EXPORT
tsm_vte_get_def_attr(struct tsm_vte * vte,struct tsm_screen_attr * out)335 void tsm_vte_get_def_attr(struct tsm_vte *vte, struct tsm_screen_attr *out)
336 {
337 	memcpy(out, &vte->def_attr, sizeof(*out));
338 }
339 
write_safe(struct tsm_vte * vte,const char * u8,size_t len)340 static void write_safe(struct tsm_vte *vte, const char *u8, size_t len)
341 {
342 	if (vte->pasting) {
343 		if (*u8 == ENDPASTE[vte->endpaste_i]) {
344 			if (ENDPASTE[++vte->endpaste_i] == '\0') {
345 				llog_warning(vte, "ignoring ESC[201~ escape "
346 						  "sequence in pasted text");
347 				vte->endpaste_i = 0;
348 			}
349 			return;
350 		} else if (vte->endpaste_i) {
351 			vte->write_cb(vte, ENDPASTE, vte->endpaste_i,
352 				      vte->data);
353 			vte->endpaste_i = 0;
354 			if (*u8 == '\e')
355 				vte->endpaste_i++;
356 		}
357 	}
358 	vte->write_cb(vte, u8, len, vte->data);
359 }
360 
361 /*
362  * Write raw byte-stream to pty.
363  * When writing data to the client we must make sure that we send the correct
364  * encoding. For backwards-compatibility reasons we should always send 7bit
365  * characters exclusively. However, when FLAG_7BIT_MODE is not set, then we can
366  * also send raw 8bit characters. For instance, in FLAG_8BIT_MODE we can use the
367  * GR characters as keyboard input and send them directly or even use the C1
368  * escape characters. In unicode mode (default) we can send multi-byte utf-8
369  * characters which are also 8bit. When sending these characters, set the \raw
370  * flag to true so this function does not perform debug checks on data we send.
371  * If debugging is disabled, these checks are also disabled and won't affect
372  * performance.
373  * For better debugging, we also use the __LINE__ and __FILE__ macros. Use the
374  * vte_write() and vte_write_raw() macros below for more convenient use.
375  *
376  * As a rule of thumb do never send 8bit characters in escape sequences and also
377  * avoid all 8bit escape codes including the C1 codes. This will guarantee that
378  * all kind of clients are always compatible to us.
379  *
380  * If SEND_RECEIVE_MODE is off (that is, local echo is on) we have to send all
381  * data directly to ourself again. However, we must avoid recursion when
382  * tsm_vte_input() itself calls vte_write*(), therefore, we increase the
383  * PARSER counter when entering tsm_vte_input() and reset it when leaving it
384  * so we never echo data that origins from tsm_vte_input().
385  * But note that SEND_RECEIVE_MODE is inherently broken for escape sequences
386  * that request answers. That is, if we send a request to the client that awaits
387  * a response and parse that request via local echo ourself, then we will also
388  * send a response to the client even though he didn't request one. This
389  * recursion fix does not avoid this but only prevents us from endless loops
390  * here. Anyway, only few applications rely on local echo so we can safely
391  * ignore this.
392  */
vte_write_debug(struct tsm_vte * vte,const char * u8,size_t len,bool raw,const char * file,int line)393 static void vte_write_debug(struct tsm_vte *vte, const char *u8, size_t len,
394 			    bool raw, const char *file, int line)
395 {
396 #ifdef BUILD_ENABLE_DEBUG
397 	/* in debug mode we check that escape sequences are always <0x7f so they
398 	 * are correctly parsed by non-unicode and non-8bit-mode clients. */
399 	size_t i;
400 
401 	if (!raw) {
402 		for (i = 0; i < len; ++i) {
403 			if (u8[i] & 0x80)
404 				llog_warning(vte, "sending 8bit character inline to client in %s:%d",
405 					     file, line);
406 		}
407 	}
408 #endif
409 
410 	/* in local echo mode, directly parse the data again */
411 	if (!vte->parse_cnt && !(vte->flags & FLAG_SEND_RECEIVE_MODE)) {
412 		if (vte->flags & FLAG_PREPEND_ESCAPE && u8[0] != '\e')
413 			tsm_vte_input(vte, "\e", 1);
414 		tsm_vte_input(vte, u8, len);
415 	}
416 
417 	if (vte->flags & FLAG_PREPEND_ESCAPE && u8[0] != '\e')
418 		write_safe(vte, "\e", 1);
419 	write_safe(vte, u8, len);
420 
421 	vte->flags &= ~FLAG_PREPEND_ESCAPE;
422 }
423 
424 #define vte_write(_vte, _u8, _len) \
425 	vte_write_debug((_vte), (_u8), (_len), false, __FILE__, __LINE__)
426 #define vte_write_raw(_vte, _u8, _len) \
427 	vte_write_debug((_vte), (_u8), (_len), true, __FILE__, __LINE__)
428 
vte_write_fnkey(struct tsm_vte * vte,bool ss3,unsigned int mods,int index,char c)429 static void vte_write_fnkey(struct tsm_vte *vte, bool ss3, unsigned int mods,
430 			    int index, char c)
431 {
432 	char buf[10];
433 	int len;
434 	int fnmod = 1
435 		  + (mods & TSM_SHIFT_MASK ? 1 : 0)
436 		  + (mods & TSM_ALT_MASK ? 2 : 0)
437 		  + (mods & TSM_CONTROL_MASK ? 4 : 0);
438 
439 	if (fnmod > 1) {
440 		if (index <= 0)
441 			index = 1;
442 		len = sprintf(buf, "\e[%d;%d%c", index, fnmod, c);
443 	} else {
444 		len = sprintf(buf, "\e%c%.0d%c", ss3 ? 'O' : '[', index, c);
445 	}
446 	vte_write(vte, buf, len);
447 }
448 
449 /* write to console */
write_console(struct tsm_vte * vte,tsm_symbol_t sym)450 static void write_console(struct tsm_vte *vte, tsm_symbol_t sym)
451 {
452 	vte->last_sym = sym;
453 	to_rgb(vte, &vte->cattr);
454 	tsm_screen_write(vte->con, sym, &vte->cattr);
455 }
456 
reset_state(struct tsm_vte * vte)457 static void reset_state(struct tsm_vte *vte)
458 {
459 	vte->saved_state.cursor_x = 0;
460 	vte->saved_state.cursor_y = 0;
461 	vte->saved_state.origin_mode = false;
462 	vte->saved_state.wrap_mode = true;
463 	vte->saved_state.gl = &vte->g0;
464 	vte->saved_state.gr = &vte->g1;
465 
466 	copy_fcolor(&vte->saved_state.cattr, &vte->def_attr);
467 	copy_bcolor(&vte->saved_state.cattr, &vte->def_attr);
468 	vte->saved_state.cattr.bold = 0;
469 	vte->saved_state.cattr.underline = 0;
470 	vte->saved_state.cattr.inverse = 0;
471 	vte->saved_state.cattr.protect = 0;
472 	vte->saved_state.cattr.blink = 0;
473 }
474 
save_state(struct tsm_vte * vte)475 static void save_state(struct tsm_vte *vte)
476 {
477 	vte->saved_state.cursor_x = tsm_screen_get_cursor_x(vte->con);
478 	vte->saved_state.cursor_y = tsm_screen_get_cursor_y(vte->con);
479 	vte->saved_state.cattr = vte->cattr;
480 	vte->saved_state.gl = vte->gl;
481 	vte->saved_state.gr = vte->gr;
482 	vte->saved_state.wrap_mode = vte->flags & FLAG_AUTO_WRAP_MODE;
483 	vte->saved_state.origin_mode = vte->flags & FLAG_ORIGIN_MODE;
484 }
485 
restore_state(struct tsm_vte * vte)486 static void restore_state(struct tsm_vte *vte)
487 {
488 	tsm_screen_move_to(vte->con, vte->saved_state.cursor_x,
489 			       vte->saved_state.cursor_y);
490 	vte->cattr = vte->saved_state.cattr;
491 	to_rgb(vte, &vte->cattr);
492 	if (vte->flags & FLAG_BACKGROUND_COLOR_ERASE_MODE)
493 		tsm_screen_set_def_attr(vte->con, &vte->cattr);
494 	vte->gl = vte->saved_state.gl;
495 	vte->gr = vte->saved_state.gr;
496 
497 	if (vte->saved_state.wrap_mode) {
498 		vte->flags |= FLAG_AUTO_WRAP_MODE;
499 		tsm_screen_set_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
500 	} else {
501 		vte->flags &= ~FLAG_AUTO_WRAP_MODE;
502 		tsm_screen_reset_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
503 	}
504 
505 	if (vte->saved_state.origin_mode) {
506 		vte->flags |= FLAG_ORIGIN_MODE;
507 		tsm_screen_set_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
508 	} else {
509 		vte->flags &= ~FLAG_ORIGIN_MODE;
510 		tsm_screen_reset_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
511 	}
512 }
513 
514 /*
515  * Reset VTE state
516  * This performs a soft reset of the VTE. That is, everything is reset to the
517  * same state as when the VTE was created. This does not affect the console,
518  * though.
519  */
520 SHL_EXPORT
tsm_vte_reset(struct tsm_vte * vte)521 void tsm_vte_reset(struct tsm_vte *vte)
522 {
523 	vte->flags = 0;
524 	vte->flags |= FLAG_TEXT_CURSOR_MODE;
525 	vte->flags |= FLAG_AUTO_REPEAT_MODE;
526 	vte->flags |= FLAG_SEND_RECEIVE_MODE;
527 	vte->flags |= FLAG_AUTO_WRAP_MODE;
528 	vte->flags |= FLAG_BACKGROUND_COLOR_ERASE_MODE;
529 	tsm_screen_reset(vte->con);
530 	tsm_screen_set_flags(vte->con, TSM_SCREEN_AUTO_WRAP);
531 
532 	tsm_utf8_mach_reset(vte->mach);
533 	vte->state = STATE_GROUND;
534 	vte->last_sym = ' ';
535 	vte->gl = &vte->g0;
536 	vte->gr = &vte->g1;
537 	vte->glt = NULL;
538 	vte->grt = NULL;
539 	vte->g0 = &tsm_vte_unicode_lower;
540 	vte->g1 = &tsm_vte_unicode_upper;
541 	vte->g2 = &tsm_vte_unicode_lower;
542 	vte->g3 = &tsm_vte_unicode_upper;
543 
544 	memcpy(&vte->cattr, &vte->def_attr, sizeof(vte->cattr));
545 	to_rgb(vte, &vte->cattr);
546 	tsm_screen_set_def_attr(vte->con, &vte->def_attr);
547 
548 	reset_state(vte);
549 }
550 
551 SHL_EXPORT
tsm_vte_hard_reset(struct tsm_vte * vte)552 void tsm_vte_hard_reset(struct tsm_vte *vte)
553 {
554 	tsm_vte_reset(vte);
555 	tsm_screen_erase_screen(vte->con, false);
556 	tsm_screen_clear_sb(vte->con);
557 	tsm_screen_move_to(vte->con, 0, 0);
558 }
559 
send_primary_da(struct tsm_vte * vte)560 static void send_primary_da(struct tsm_vte *vte)
561 {
562 	vte_write(vte, "\e[?62;1;6;9;15c", 15);
563 }
564 
565 /* execute control character (C0 or C1) */
do_execute(struct tsm_vte * vte,uint32_t ctrl)566 static void do_execute(struct tsm_vte *vte, uint32_t ctrl)
567 {
568 	switch (ctrl) {
569 	case 0x00: /* NUL */
570 		/* Ignore on input */
571 		break;
572 	case 0x05: /* ENQ */
573 		/* Transmit answerback message */
574 		/* TODO: is there a better answer than ACK?  */
575 		vte_write(vte, "\x06", 1);
576 		break;
577 	case 0x07: /* BEL */
578 		/* Sound bell tone */
579 		/* TODO: I always considered this annying, however, we
580 		 * should at least provide some way to enable it if the
581 		 * user *really* wants it.
582 		 */
583 		break;
584 	case 0x08: /* BS */
585 		/* Move cursor one position left */
586 		tsm_screen_move_left(vte->con, 1);
587 		break;
588 	case 0x09: /* HT */
589 		/* Move to next tab stop or end of line */
590 		tsm_screen_tab_right(vte->con, 1);
591 		break;
592 	case 0x0a: /* LF */
593 	case 0x0b: /* VT */
594 	case 0x0c: /* FF */
595 		/* Line feed or newline (CR/NL mode) */
596 		if (vte->flags & FLAG_LINE_FEED_NEW_LINE_MODE)
597 			tsm_screen_newline(vte->con);
598 		else
599 			tsm_screen_move_down(vte->con, 1, true);
600 		break;
601 	case 0x0d: /* CR */
602 		/* Move cursor to left margin */
603 		tsm_screen_move_line_home(vte->con);
604 		break;
605 	case 0x0e: /* SO */
606 		/* Map G1 character set into GL */
607 		vte->gl = &vte->g1;
608 		break;
609 	case 0x0f: /* SI */
610 		/* Map G0 character set into GL */
611 		vte->gl = &vte->g0;
612 		break;
613 	case 0x11: /* XON */
614 		/* Resume transmission */
615 		/* TODO */
616 		break;
617 	case 0x13: /* XOFF */
618 		/* Stop transmission */
619 		/* TODO */
620 		break;
621 	case 0x18: /* CAN */
622 		/* Cancel escape sequence */
623 		/* nothing to do here */
624 		break;
625 	case 0x1a: /* SUB */
626 		/* Discard current escape sequence and show err-sym */
627 		write_console(vte, 0xbf);
628 		break;
629 	case 0x1b: /* ESC */
630 		/* Invokes an escape sequence */
631 		/* nothing to do here */
632 		break;
633 	case 0x1f: /* DEL */
634 		/* Ignored */
635 		break;
636 	case 0x84: /* IND */
637 		/* Move down one row, perform scroll-up if needed */
638 		tsm_screen_move_down(vte->con, 1, true);
639 		break;
640 	case 0x85: /* NEL */
641 		/* CR/NL with scroll-up if needed */
642 		tsm_screen_newline(vte->con);
643 		break;
644 	case 0x88: /* HTS */
645 		/* Set tab stop at current position */
646 		tsm_screen_set_tabstop(vte->con);
647 		break;
648 	case 0x8d: /* RI */
649 		/* Move up one row, perform scroll-down if needed */
650 		tsm_screen_move_up(vte->con, 1, true);
651 		break;
652 	case 0x8e: /* SS2 */
653 		/* Temporarily map G2 into GL for next char only */
654 		vte->glt = &vte->g2;
655 		break;
656 	case 0x8f: /* SS3 */
657 		/* Temporarily map G3 into GL for next char only */
658 		vte->glt = &vte->g3;
659 		break;
660 	case 0x9a: /* DECID */
661 		/* Send device attributes response like ANSI DA */
662 		send_primary_da(vte);
663 		break;
664 	case 0x9c: /* ST */
665 		/* End control string */
666 		/* nothing to do here */
667 		break;
668 	default:
669 		llog_debug(vte, "unhandled control char %u", ctrl);
670 	}
671 }
672 
do_clear(struct tsm_vte * vte)673 static void do_clear(struct tsm_vte *vte)
674 {
675 	int i;
676 
677 	vte->csi_argc = 0;
678 	for (i = 0; i < CSI_ARG_MAX; ++i)
679 		vte->csi_argv[i] = -1;
680 	vte->csi_flags = 0;
681 }
682 
do_collect(struct tsm_vte * vte,uint32_t data)683 static void do_collect(struct tsm_vte *vte, uint32_t data)
684 {
685 	switch (data) {
686 	case '!':
687 		vte->csi_flags |= CSI_BANG;
688 		break;
689 	case '$':
690 		vte->csi_flags |= CSI_CASH;
691 		break;
692 	case '?':
693 		vte->csi_flags |= CSI_WHAT;
694 		break;
695 	case '>':
696 		vte->csi_flags |= CSI_GT;
697 		break;
698 	case ' ':
699 		vte->csi_flags |= CSI_SPACE;
700 		break;
701 	case '\'':
702 		vte->csi_flags |= CSI_SQUOTE;
703 		break;
704 	case '"':
705 		vte->csi_flags |= CSI_DQUOTE;
706 		break;
707 	case '*':
708 		vte->csi_flags |= CSI_MULT;
709 		break;
710 	case '+':
711 		vte->csi_flags |= CSI_PLUS;
712 		break;
713 	case '(':
714 		vte->csi_flags |= CSI_POPEN;
715 		break;
716 	case ')':
717 		vte->csi_flags |= CSI_PCLOSE;
718 		break;
719 	}
720 }
721 
do_param(struct tsm_vte * vte,uint32_t data)722 static void do_param(struct tsm_vte *vte, uint32_t data)
723 {
724 	int new;
725 
726 	if (data == ';') {
727 		if (vte->csi_argc < CSI_ARG_MAX)
728 			vte->csi_argc++;
729 		return;
730 	}
731 
732 	if (vte->csi_argc >= CSI_ARG_MAX)
733 		return;
734 
735 	/* avoid integer overflows; max allowed value is 16384 anyway */
736 	if (vte->csi_argv[vte->csi_argc] > 0xffff)
737 		return;
738 
739 	if (data >= '0' && data <= '9') {
740 		new = vte->csi_argv[vte->csi_argc];
741 		if (new <= 0)
742 			new = data - '0';
743 		else
744 			new = new * 10 + data - '0';
745 		vte->csi_argv[vte->csi_argc] = new;
746 	}
747 }
748 
set_charset(struct tsm_vte * vte,tsm_vte_charset * set)749 static bool set_charset(struct tsm_vte *vte, tsm_vte_charset *set)
750 {
751 	if (vte->csi_flags & CSI_POPEN)
752 		vte->g0 = set;
753 	else if (vte->csi_flags & CSI_PCLOSE)
754 		vte->g1 = set;
755 	else if (vte->csi_flags & CSI_MULT)
756 		vte->g2 = set;
757 	else if (vte->csi_flags & CSI_PLUS)
758 		vte->g3 = set;
759 	else
760 		return false;
761 
762 	return true;
763 }
764 
do_esc(struct tsm_vte * vte,uint32_t data)765 static void do_esc(struct tsm_vte *vte, uint32_t data)
766 {
767 	switch (data) {
768 	case 'B': /* map ASCII into G0-G3 */
769 		if (set_charset(vte, &tsm_vte_unicode_lower))
770 			return;
771 		break;
772 	case '<': /* map DEC supplemental into G0-G3 */
773 		if (set_charset(vte, &tsm_vte_dec_supplemental_graphics))
774 			return;
775 		break;
776 	case '0': /* map DEC special into G0-G3 */
777 		if (set_charset(vte, &tsm_vte_dec_special_graphics))
778 			return;
779 		break;
780 	case 'A': /* map British into G0-G3 */
781 		/* TODO: create British charset from DEC */
782 		if (set_charset(vte, &tsm_vte_unicode_upper))
783 			return;
784 		break;
785 	case '4': /* map Dutch into G0-G3 */
786 		/* TODO: create Dutch charset from DEC */
787 		if (set_charset(vte, &tsm_vte_unicode_upper))
788 			return;
789 		break;
790 	case 'C':
791 	case '5': /* map Finnish into G0-G3 */
792 		/* TODO: create Finnish charset from DEC */
793 		if (set_charset(vte, &tsm_vte_unicode_upper))
794 			return;
795 		break;
796 	case 'R': /* map French into G0-G3 */
797 		/* TODO: create French charset from DEC */
798 		if (set_charset(vte, &tsm_vte_unicode_upper))
799 			return;
800 		break;
801 	case 'Q': /* map French-Canadian into G0-G3 */
802 		/* TODO: create French-Canadian charset from DEC */
803 		if (set_charset(vte, &tsm_vte_unicode_upper))
804 			return;
805 		break;
806 	case 'K': /* map German into G0-G3 */
807 		/* TODO: create German charset from DEC */
808 		if (set_charset(vte, &tsm_vte_unicode_upper))
809 			return;
810 		break;
811 	case 'Y': /* map Italian into G0-G3 */
812 		/* TODO: create Italian charset from DEC */
813 		if (set_charset(vte, &tsm_vte_unicode_upper))
814 			return;
815 		break;
816 	case 'E':
817 	case '6': /* map Norwegian/Danish into G0-G3 */
818 		/* TODO: create Norwegian/Danish charset from DEC */
819 		if (set_charset(vte, &tsm_vte_unicode_upper))
820 			return;
821 		break;
822 	case 'Z': /* map Spanish into G0-G3 */
823 		/* TODO: create Spanish charset from DEC */
824 		if (set_charset(vte, &tsm_vte_unicode_upper))
825 			return;
826 		break;
827 	case 'H':
828 	case '7': /* map Swedish into G0-G3 */
829 		/* TODO: create Swedish charset from DEC */
830 		if (set_charset(vte, &tsm_vte_unicode_upper))
831 			return;
832 		break;
833 	case '=': /* map Swiss into G0-G3 */
834 		/* TODO: create Swiss charset from DEC */
835 		if (set_charset(vte, &tsm_vte_unicode_upper))
836 			return;
837 		break;
838 	case 'F':
839 		if (vte->csi_flags & CSI_SPACE) {
840 			/* S7C1T */
841 			/* Disable 8bit C1 mode */
842 			vte->flags &= ~FLAG_USE_C1;
843 			return;
844 		}
845 		break;
846 	case 'G':
847 		if (vte->csi_flags & CSI_SPACE) {
848 			/* S8C1T */
849 			/* Enable 8bit C1 mode */
850 			vte->flags |= FLAG_USE_C1;
851 			return;
852 		}
853 		break;
854 	}
855 
856 	/* everything below is only valid without CSI flags */
857 	if (vte->csi_flags) {
858 		llog_debug(vte, "unhandled escape seq %u", data);
859 		return;
860 	}
861 
862 	switch (data) {
863 	case 'D': /* IND */
864 		/* Move down one row, perform scroll-up if needed */
865 		tsm_screen_move_down(vte->con, 1, true);
866 		break;
867 	case 'E': /* NEL */
868 		/* CR/NL with scroll-up if needed */
869 		tsm_screen_newline(vte->con);
870 		break;
871 	case 'H': /* HTS */
872 		/* Set tab stop at current position */
873 		tsm_screen_set_tabstop(vte->con);
874 		break;
875 	case 'M': /* RI */
876 		/* Move up one row, perform scroll-down if needed */
877 		tsm_screen_move_up(vte->con, 1, true);
878 		break;
879 	case 'N': /* SS2 */
880 		/* Temporarily map G2 into GL for next char only */
881 		vte->glt = &vte->g2;
882 		break;
883 	case 'O': /* SS3 */
884 		/* Temporarily map G3 into GL for next char only */
885 		vte->glt = &vte->g3;
886 		break;
887 	case 'Z': /* DECID */
888 		/* Send device attributes response like ANSI DA */
889 		send_primary_da(vte);
890 		break;
891 	case '\\': /* ST */
892 		/* End control string */
893 		/* nothing to do here */
894 		break;
895 	case '~': /* LS1R */
896 		/* Invoke G1 into GR */
897 		vte->gr = &vte->g1;
898 		break;
899 	case 'n': /* LS2 */
900 		/* Invoke G2 into GL */
901 		vte->gl = &vte->g2;
902 		break;
903 	case '}': /* LS2R */
904 		/* Invoke G2 into GR */
905 		vte->gr = &vte->g2;
906 		break;
907 	case 'o': /* LS3 */
908 		/* Invoke G3 into GL */
909 		vte->gl = &vte->g3;
910 		break;
911 	case '|': /* LS3R */
912 		/* Invoke G3 into GR */
913 		vte->gr = &vte->g3;
914 		break;
915 	case '=': /* DECKPAM */
916 		/* Set application keypad mode */
917 		vte->flags |= FLAG_KEYPAD_APPLICATION_MODE;
918 		break;
919 	case '>': /* DECKPNM */
920 		/* Set numeric keypad mode */
921 		vte->flags &= ~FLAG_KEYPAD_APPLICATION_MODE;
922 		break;
923 	case 'c': /* RIS */
924 		/* hard reset */
925 		tsm_vte_hard_reset(vte);
926 		break;
927 	case '7': /* DECSC */
928 		/* save console state */
929 		save_state(vte);
930 		break;
931 	case '8': /* DECRC */
932 		/* restore console state */
933 		restore_state(vte);
934 		break;
935 	default:
936 		llog_debug(vte, "unhandled escape seq %u", data);
937 	}
938 }
939 
csi_attribute(struct tsm_vte * vte)940 static void csi_attribute(struct tsm_vte *vte)
941 {
942 	static const uint8_t bval[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
943 	int i, code, val;
944 	uint8_t cr, cg, cb;
945 
946 	if (vte->csi_argc <= 1 && vte->csi_argv[0] == -1) {
947 		vte->csi_argc = 1;
948 		vte->csi_argv[0] = 0;
949 	}
950 
951 	for (i = 0; i < vte->csi_argc; ++i) {
952 		switch (vte->csi_argv[i]) {
953 		case -1:
954 			break;
955 		case 0:
956 			copy_fcolor(&vte->cattr, &vte->def_attr);
957 			copy_bcolor(&vte->cattr, &vte->def_attr);
958 			vte->cattr.bold = 0;
959 			vte->cattr.underline = 0;
960 			vte->cattr.inverse = 0;
961 			vte->cattr.blink = 0;
962 			break;
963 		case 1:
964 			vte->cattr.bold = 1;
965 			break;
966 		case 4:
967 			vte->cattr.underline = 1;
968 			break;
969 		case 5:
970 			vte->cattr.blink = 1;
971 			break;
972 		case 7:
973 			vte->cattr.inverse = 1;
974 			break;
975 		case 22:
976 			vte->cattr.bold = 0;
977 			break;
978 		case 24:
979 			vte->cattr.underline = 0;
980 			break;
981 		case 25:
982 			vte->cattr.blink = 0;
983 			break;
984 		case 27:
985 			vte->cattr.inverse = 0;
986 			break;
987 		case 30:
988 			vte->cattr.fccode = TSM_COLOR_BLACK;
989 			break;
990 		case 31:
991 			vte->cattr.fccode = TSM_COLOR_RED;
992 			break;
993 		case 32:
994 			vte->cattr.fccode = TSM_COLOR_GREEN;
995 			break;
996 		case 33:
997 			vte->cattr.fccode = TSM_COLOR_YELLOW;
998 			break;
999 		case 34:
1000 			vte->cattr.fccode = TSM_COLOR_BLUE;
1001 			break;
1002 		case 35:
1003 			vte->cattr.fccode = TSM_COLOR_MAGENTA;
1004 			break;
1005 		case 36:
1006 			vte->cattr.fccode = TSM_COLOR_CYAN;
1007 			break;
1008 		case 37:
1009 			vte->cattr.fccode = TSM_COLOR_LIGHT_GREY;
1010 			break;
1011 		case 39:
1012 			copy_fcolor(&vte->cattr, &vte->def_attr);
1013 			break;
1014 		case 40:
1015 			vte->cattr.bccode = TSM_COLOR_BLACK;
1016 			break;
1017 		case 41:
1018 			vte->cattr.bccode = TSM_COLOR_RED;
1019 			break;
1020 		case 42:
1021 			vte->cattr.bccode = TSM_COLOR_GREEN;
1022 			break;
1023 		case 43:
1024 			vte->cattr.bccode = TSM_COLOR_YELLOW;
1025 			break;
1026 		case 44:
1027 			vte->cattr.bccode = TSM_COLOR_BLUE;
1028 			break;
1029 		case 45:
1030 			vte->cattr.bccode = TSM_COLOR_MAGENTA;
1031 			break;
1032 		case 46:
1033 			vte->cattr.bccode = TSM_COLOR_CYAN;
1034 			break;
1035 		case 47:
1036 			vte->cattr.bccode = TSM_COLOR_LIGHT_GREY;
1037 			break;
1038 		case 49:
1039 			copy_bcolor(&vte->cattr, &vte->def_attr);
1040 			break;
1041 		case 90:
1042 			vte->cattr.fccode = TSM_COLOR_DARK_GREY;
1043 			break;
1044 		case 91:
1045 			vte->cattr.fccode = TSM_COLOR_LIGHT_RED;
1046 			break;
1047 		case 92:
1048 			vte->cattr.fccode = TSM_COLOR_LIGHT_GREEN;
1049 			break;
1050 		case 93:
1051 			vte->cattr.fccode = TSM_COLOR_LIGHT_YELLOW;
1052 			break;
1053 		case 94:
1054 			vte->cattr.fccode = TSM_COLOR_LIGHT_BLUE;
1055 			break;
1056 		case 95:
1057 			vte->cattr.fccode = TSM_COLOR_LIGHT_MAGENTA;
1058 			break;
1059 		case 96:
1060 			vte->cattr.fccode = TSM_COLOR_LIGHT_CYAN;
1061 			break;
1062 		case 97:
1063 			vte->cattr.fccode = TSM_COLOR_WHITE;
1064 			break;
1065 		case 100:
1066 			vte->cattr.bccode = TSM_COLOR_DARK_GREY;
1067 			break;
1068 		case 101:
1069 			vte->cattr.bccode = TSM_COLOR_LIGHT_RED;
1070 			break;
1071 		case 102:
1072 			vte->cattr.bccode = TSM_COLOR_LIGHT_GREEN;
1073 			break;
1074 		case 103:
1075 			vte->cattr.bccode = TSM_COLOR_LIGHT_YELLOW;
1076 			break;
1077 		case 104:
1078 			vte->cattr.bccode = TSM_COLOR_LIGHT_BLUE;
1079 			break;
1080 		case 105:
1081 			vte->cattr.bccode = TSM_COLOR_LIGHT_MAGENTA;
1082 			break;
1083 		case 106:
1084 			vte->cattr.bccode = TSM_COLOR_LIGHT_CYAN;
1085 			break;
1086 		case 107:
1087 			vte->cattr.bccode = TSM_COLOR_WHITE;
1088 			break;
1089 		case 38:
1090 			/* fallthrough */
1091 		case 48:
1092 			val = vte->csi_argv[i];
1093 			if (vte->csi_argv[i + 1] == 5) {
1094 				if (i + 2 >= vte->csi_argc ||
1095 					vte->csi_argv[i + 2] < 0) {
1096 					llog_debug(vte, "invalid 256color SGR");
1097 					break;
1098 				}
1099 				code = vte->csi_argv[i + 2];
1100 				if (code < 16) {
1101 				} else if (code < 232) {
1102 					code -= 16;
1103 					cb = bval[code % 6];
1104 					code /= 6;
1105 					cg = bval[code % 6];
1106 					code /= 6;
1107 					cr = bval[code % 6];
1108 					code = -1;
1109 				} else {
1110 					code = (code - 232) * 10 + 8;
1111 					cr = code;
1112 					cg = code;
1113 					cb = code;
1114 					code = -1;
1115 				}
1116 				i += 2;
1117 			} else if (vte->csi_argv[i + 1] == 2) {
1118 				if (i + 4 >= vte->csi_argc ||
1119 					vte->csi_argv[i + 2] < 0 ||
1120 					vte->csi_argv[i + 3] < 0 ||
1121 					vte->csi_argv[i + 4] < 0) {
1122 						llog_debug(vte, "invalid true color SGR");
1123 						break;
1124 					}
1125 				cr = vte->csi_argv[i + 2];
1126 				cg = vte->csi_argv[i + 3];
1127 				cb = vte->csi_argv[i + 4];
1128 				code = -1;
1129 				i += 4;
1130 			} else {
1131 				llog_debug(vte, "invalid SGR");
1132 				break;
1133 			}
1134 			if (val == 38) {
1135 				vte->cattr.fccode = code;
1136 				vte->cattr.fr = cr;
1137 				vte->cattr.fg = cg;
1138 				vte->cattr.fb = cb;
1139 			} else {
1140 				vte->cattr.bccode = code;
1141 				vte->cattr.br = cr;
1142 				vte->cattr.bg = cg;
1143 				vte->cattr.bb = cb;
1144 			}
1145 
1146 			break;
1147 		default:
1148 			llog_debug(vte, "unhandled SGR attr %i",
1149 				   vte->csi_argv[i]);
1150 		}
1151 	}
1152 
1153 	to_rgb(vte, &vte->cattr);
1154 	if (vte->flags & FLAG_BACKGROUND_COLOR_ERASE_MODE)
1155 		tsm_screen_set_def_attr(vte->con, &vte->cattr);
1156 }
1157 
csi_soft_reset(struct tsm_vte * vte)1158 static void csi_soft_reset(struct tsm_vte *vte)
1159 {
1160 	tsm_vte_reset(vte);
1161 }
1162 
csi_compat_mode(struct tsm_vte * vte)1163 static void csi_compat_mode(struct tsm_vte *vte)
1164 {
1165 	/* always perform soft reset */
1166 	csi_soft_reset(vte);
1167 
1168 	if (vte->csi_argv[0] == 61) {
1169 		/* Switching to VT100 compatibility mode. We do
1170 		 * not support this mode, so ignore it. In fact,
1171 		 * we are almost compatible to it, anyway, so
1172 		 * there is no need to explicitly select it.
1173 		 * However, we enable 7bit mode to avoid
1174 		 * character-table problems */
1175 		vte->flags |= FLAG_7BIT_MODE;
1176 		vte->g0 = &tsm_vte_unicode_lower;
1177 		vte->g1 = &tsm_vte_dec_supplemental_graphics;
1178 	} else if (vte->csi_argv[0] == 62 ||
1179 		   vte->csi_argv[0] == 63 ||
1180 		   vte->csi_argv[0] == 64) {
1181 		/* Switching to VT2/3/4 compatibility mode. We
1182 		 * are always compatible with this so ignore it.
1183 		 * We always send 7bit controls so we also do
1184 		 * not care for the parameter value here that
1185 		 * select the control-mode.
1186 		 * VT220 defines argument 2 as 7bit mode but
1187 		 * VT3xx up to VT5xx use it as 8bit mode. We
1188 		 * choose to conform with the latter here.
1189 		 * We also enable 8bit mode when VT220
1190 		 * compatibility is requested explicitly. */
1191 		if (vte->csi_argv[1] == 1 ||
1192 		    vte->csi_argv[1] == 2)
1193 			vte->flags |= FLAG_USE_C1;
1194 
1195 		vte->flags |= FLAG_8BIT_MODE;
1196 		vte->g0 = &tsm_vte_unicode_lower;
1197 		vte->g1 = &tsm_vte_dec_supplemental_graphics;
1198 	} else {
1199 		llog_debug(vte, "unhandled DECSCL 'p' CSI %i, switching to utf-8 mode again",
1200 			   vte->csi_argv[0]);
1201 	}
1202 }
1203 
set_reset_flag(struct tsm_vte * vte,bool set,unsigned int flag)1204 static inline void set_reset_flag(struct tsm_vte *vte, bool set,
1205 				  unsigned int flag)
1206 {
1207 	if (set)
1208 		vte->flags |= flag;
1209 	else
1210 		vte->flags &= ~flag;
1211 }
1212 
csi_mode(struct tsm_vte * vte,bool set)1213 static void csi_mode(struct tsm_vte *vte, bool set)
1214 {
1215 	int i;
1216 
1217 	for (i = 0; i < vte->csi_argc; ++i) {
1218 		if (!(vte->csi_flags & CSI_WHAT)) {
1219 			switch (vte->csi_argv[i]) {
1220 			case -1:
1221 				continue;
1222 			case 2: /* KAM */
1223 				set_reset_flag(vte, set,
1224 					       FLAG_KEYBOARD_ACTION_MODE);
1225 				continue;
1226 			case 4: /* IRM */
1227 				set_reset_flag(vte, set,
1228 					       FLAG_INSERT_REPLACE_MODE);
1229 				if (set)
1230 					tsm_screen_set_flags(vte->con,
1231 						TSM_SCREEN_INSERT_MODE);
1232 				else
1233 					tsm_screen_reset_flags(vte->con,
1234 						TSM_SCREEN_INSERT_MODE);
1235 				continue;
1236 			case 12: /* SRM */
1237 				set_reset_flag(vte, set,
1238 					       FLAG_SEND_RECEIVE_MODE);
1239 				continue;
1240 			case 20: /* LNM */
1241 				set_reset_flag(vte, set,
1242 					       FLAG_LINE_FEED_NEW_LINE_MODE);
1243 				continue;
1244 			default:
1245 				llog_debug(vte, "unknown non-DEC (Re)Set-Mode %d",
1246 					   vte->csi_argv[i]);
1247 				continue;
1248 			}
1249 		}
1250 
1251 		switch (vte->csi_argv[i]) {
1252 		case -1:
1253 			continue;
1254 		case 1: /* DECCKM */
1255 			set_reset_flag(vte, set, FLAG_CURSOR_KEY_MODE);
1256 			continue;
1257 		case 2: /* DECANM */
1258 			/* Select VT52 mode */
1259 			/* We do not support VT52 mode. Is there any reason why
1260 			 * we should support it? We ignore it here and do not
1261 			 * mark it as to-do item unless someone has strong
1262 			 * arguments to support it. */
1263 			continue;
1264 		case 3: /* DECCOLM */
1265 			/* If set, select 132 column mode, otherwise use 80
1266 			 * column mode. If neither is selected explicitly, we
1267 			 * use dynamic mode, that is, we send SIGWCH when the
1268 			 * size changes and we allow arbitrary buffer
1269 			 * dimensions. On soft-reset, we automatically fall back
1270 			 * to the default, that is, dynamic mode.
1271 			 * Dynamic-mode can be forced to a static mode in the
1272 			 * config. That is, every time dynamic-mode becomes
1273 			 * active, the terminal will be set to the dimensions
1274 			 * that were selected in the config. This allows setting
1275 			 * a fixed size for the terminal regardless of the
1276 			 * display size.
1277 			 * TODO: Implement this */
1278 			continue;
1279 		case 4: /* DECSCLM */
1280 			/* Select smooth scrolling. We do not support the
1281 			 * classic smooth scrolling because we have a scrollback
1282 			 * buffer. There is no need to implement smooth
1283 			 * scrolling so ignore this here. */
1284 			continue;
1285 		case 5: /* DECSCNM */
1286 			set_reset_flag(vte, set, FLAG_INVERSE_SCREEN_MODE);
1287 			if (set)
1288 				tsm_screen_set_flags(vte->con,
1289 						TSM_SCREEN_INVERSE);
1290 			else
1291 				tsm_screen_reset_flags(vte->con,
1292 						TSM_SCREEN_INVERSE);
1293 			continue;
1294 		case 6: /* DECOM */
1295 			set_reset_flag(vte, set, FLAG_ORIGIN_MODE);
1296 			if (set)
1297 				tsm_screen_set_flags(vte->con,
1298 						TSM_SCREEN_REL_ORIGIN);
1299 			else
1300 				tsm_screen_reset_flags(vte->con,
1301 						TSM_SCREEN_REL_ORIGIN);
1302 			continue;
1303 		case 7: /* DECAWM */
1304 			set_reset_flag(vte, set, FLAG_AUTO_WRAP_MODE);
1305 			if (set)
1306 				tsm_screen_set_flags(vte->con,
1307 						TSM_SCREEN_AUTO_WRAP);
1308 			else
1309 				tsm_screen_reset_flags(vte->con,
1310 						TSM_SCREEN_AUTO_WRAP);
1311 			continue;
1312 		case 8: /* DECARM */
1313 			set_reset_flag(vte, set, FLAG_AUTO_REPEAT_MODE);
1314 			continue;
1315 		case 12: /* blinking cursor */
1316 			/* TODO: implement */
1317 			continue;
1318 		case 18: /* DECPFF */
1319 			/* If set, a form feed (FF) is sent to the printer after
1320 			 * every screen that is printed. We don't have printers
1321 			 * these days directly attached to terminals so we
1322 			 * ignore this here. */
1323 			continue;
1324 		case 19: /* DECPEX */
1325 			/* If set, the full screen is printed instead of
1326 			 * scrolling region only. We have no printer so ignore
1327 			 * this mode. */
1328 			continue;
1329 		case 25: /* DECTCEM */
1330 			set_reset_flag(vte, set, FLAG_TEXT_CURSOR_MODE);
1331 			if (set)
1332 				tsm_screen_reset_flags(vte->con,
1333 						TSM_SCREEN_HIDE_CURSOR);
1334 			else
1335 				tsm_screen_set_flags(vte->con,
1336 						TSM_SCREEN_HIDE_CURSOR);
1337 			continue;
1338 		case 42: /* DECNRCM */
1339 			set_reset_flag(vte, set, FLAG_NATIONAL_CHARSET_MODE);
1340 			continue;
1341 		case 47: /* Alternate screen buffer */
1342 			if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1343 				continue;
1344 
1345 			if (set)
1346 				tsm_screen_set_flags(vte->con,
1347 						     TSM_SCREEN_ALTERNATE);
1348 			else
1349 				tsm_screen_reset_flags(vte->con,
1350 						       TSM_SCREEN_ALTERNATE);
1351 			continue;
1352 		case 1047: /* Alternate screen buffer with post-erase */
1353 			if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1354 				continue;
1355 
1356 			if (set) {
1357 				tsm_screen_set_flags(vte->con,
1358 						     TSM_SCREEN_ALTERNATE);
1359 			} else {
1360 				tsm_screen_erase_screen(vte->con, false);
1361 				tsm_screen_reset_flags(vte->con,
1362 						       TSM_SCREEN_ALTERNATE);
1363 			}
1364 			continue;
1365 		case 1048: /* Set/Reset alternate-screen buffer cursor */
1366 			if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1367 				continue;
1368 
1369 			if (set) {
1370 				vte->alt_cursor_x =
1371 					tsm_screen_get_cursor_x(vte->con);
1372 				vte->alt_cursor_y =
1373 					tsm_screen_get_cursor_y(vte->con);
1374 			} else {
1375 				tsm_screen_move_to(vte->con, vte->alt_cursor_x,
1376 						   vte->alt_cursor_y);
1377 			}
1378 			continue;
1379 		case 1049: /* Alternate screen buffer with pre-erase+cursor */
1380 			if (vte->flags & FLAG_TITE_INHIBIT_MODE)
1381 				continue;
1382 
1383 			if (set) {
1384 				vte->alt_cursor_x =
1385 					tsm_screen_get_cursor_x(vte->con);
1386 				vte->alt_cursor_y =
1387 					tsm_screen_get_cursor_y(vte->con);
1388 				tsm_screen_set_flags(vte->con,
1389 						     TSM_SCREEN_ALTERNATE);
1390 				tsm_screen_erase_screen(vte->con, false);
1391 			} else {
1392 				tsm_screen_reset_flags(vte->con,
1393 						       TSM_SCREEN_ALTERNATE);
1394 				tsm_screen_move_to(vte->con, vte->alt_cursor_x,
1395 						   vte->alt_cursor_y);
1396 			}
1397 			continue;
1398 		case 2004:
1399 			set_reset_flag(vte, set, FLAG_BRACKETED_PASTE_MODE);
1400 			continue;
1401 		default:
1402 			llog_debug(vte, "unknown DEC %set-Mode %d",
1403 				   set?"S":"Res", vte->csi_argv[i]);
1404 			continue;
1405 		}
1406 	}
1407 }
1408 
csi_dev_attr(struct tsm_vte * vte)1409 static void csi_dev_attr(struct tsm_vte *vte)
1410 {
1411 	if (vte->csi_argc <= 1 && vte->csi_argv[0] <= 0) {
1412 		if (vte->csi_flags == 0) {
1413 			send_primary_da(vte);
1414 			return;
1415 		} else if (vte->csi_flags & CSI_GT) {
1416 			vte_write(vte, "\e[>1;1;0c", 9);
1417 			return;
1418 		}
1419 	}
1420 
1421 	llog_debug(vte, "unhandled DA: %x %d %d %d...", vte->csi_flags,
1422 		   vte->csi_argv[0], vte->csi_argv[1], vte->csi_argv[2]);
1423 }
1424 
csi_dsr(struct tsm_vte * vte)1425 static void csi_dsr(struct tsm_vte *vte)
1426 {
1427 	char buf[64];
1428 	int x, y;
1429 	unsigned int len;
1430 
1431 	if (vte->csi_argv[0] == 5) {
1432 		vte_write(vte, "\e[0n", 4);
1433 	} else if (vte->csi_argv[0] == 6) {
1434 		x = tsm_screen_get_cursor_x(vte->con);
1435 		y = tsm_screen_get_cursor_y(vte->con);
1436 		len = snprintf(buf, sizeof(buf), "\e[%u;%uR", y + 1, x + 1);
1437 		if (len >= sizeof(buf))
1438 			vte_write(vte, "\e[0;0R", 6);
1439 		else
1440 			vte_write(vte, buf, len);
1441 	}
1442 }
1443 
do_csi(struct tsm_vte * vte,uint32_t data)1444 static void do_csi(struct tsm_vte *vte, uint32_t data)
1445 {
1446 	int num, x, y, upper, lower;
1447 	bool protect;
1448 
1449 	if (vte->csi_argc < CSI_ARG_MAX)
1450 		vte->csi_argc++;
1451 
1452 	switch (data) {
1453 	case 'A': /* CUU */
1454 		/* move cursor up */
1455 		num = vte->csi_argv[0];
1456 		if (num <= 0)
1457 			num = 1;
1458 		tsm_screen_move_up(vte->con, num, false);
1459 		break;
1460 	case 'B': /* CUD */
1461 		/* move cursor down */
1462 		num = vte->csi_argv[0];
1463 		if (num <= 0)
1464 			num = 1;
1465 		tsm_screen_move_down(vte->con, num, false);
1466 		break;
1467 	case 'b': /* REP */
1468 		/* repeat the preceding character */
1469 		num = vte->csi_argv[0];
1470 		if (num <= 0)
1471 			num = 1;
1472 		while (num--)
1473 			write_console(vte, vte->last_sym);
1474 		break;
1475 	case 'C': /* CUF */
1476 		/* move cursor forward */
1477 		num = vte->csi_argv[0];
1478 		if (num <= 0)
1479 			num = 1;
1480 		tsm_screen_move_right(vte->con, num);
1481 		break;
1482 	case 'D': /* CUB */
1483 		/* move cursor backward */
1484 		num = vte->csi_argv[0];
1485 		if (num <= 0)
1486 			num = 1;
1487 		tsm_screen_move_left(vte->con, num);
1488 		break;
1489 	case 'd': /* VPA */
1490 		/* Vertical Line Position Absolute */
1491 		num = vte->csi_argv[0];
1492 		if (num <= 0)
1493 			num = 1;
1494 		x = tsm_screen_get_cursor_x(vte->con);
1495 		tsm_screen_move_to(vte->con, x, num - 1);
1496 		break;
1497 	case 'e': /* VPR */
1498 		/* Vertical Line Position Relative */
1499 		num = vte->csi_argv[0];
1500 		if (num <= 0)
1501 			num = 1;
1502 		x = tsm_screen_get_cursor_x(vte->con);
1503 		y = tsm_screen_get_cursor_y(vte->con);
1504 		tsm_screen_move_to(vte->con, x, y + num);
1505 		break;
1506 	case 'H': /* CUP */
1507 	case 'f': /* HVP */
1508 		/* position cursor */
1509 		x = vte->csi_argv[0];
1510 		if (x <= 0)
1511 			x = 1;
1512 		y = vte->csi_argv[1];
1513 		if (y <= 0)
1514 			y = 1;
1515 		tsm_screen_move_to(vte->con, y - 1, x - 1);
1516 		break;
1517 	case 'G': /* CHA */
1518 		/* Cursor Character Absolute */
1519 		num = vte->csi_argv[0];
1520 		if (num <= 0)
1521 			num = 1;
1522 		y = tsm_screen_get_cursor_y(vte->con);
1523 		tsm_screen_move_to(vte->con, num - 1, y);
1524 		break;
1525 	case 'J':
1526 		if (vte->csi_flags & CSI_WHAT)
1527 			protect = true;
1528 		else
1529 			protect = false;
1530 
1531 		if (vte->csi_argv[0] <= 0)
1532 			tsm_screen_erase_cursor_to_screen(vte->con,
1533 							      protect);
1534 		else if (vte->csi_argv[0] == 1)
1535 			tsm_screen_erase_screen_to_cursor(vte->con,
1536 							      protect);
1537 		else if (vte->csi_argv[0] == 2)
1538 			tsm_screen_erase_screen(vte->con, protect);
1539 		else
1540 			llog_debug(vte, "unknown parameter to CSI-J: %d",
1541 				   vte->csi_argv[0]);
1542 		break;
1543 	case 'K':
1544 		if (vte->csi_flags & CSI_WHAT)
1545 			protect = true;
1546 		else
1547 			protect = false;
1548 
1549 		if (vte->csi_argv[0] <= 0)
1550 			tsm_screen_erase_cursor_to_end(vte->con, protect);
1551 		else if (vte->csi_argv[0] == 1)
1552 			tsm_screen_erase_home_to_cursor(vte->con, protect);
1553 		else if (vte->csi_argv[0] == 2)
1554 			tsm_screen_erase_current_line(vte->con, protect);
1555 		else
1556 			llog_debug(vte, "unknown parameter to CSI-K: %d",
1557 				   vte->csi_argv[0]);
1558 		break;
1559 	case 'X': /* ECH */
1560 		/* erase characters */
1561 		num = vte->csi_argv[0];
1562 		if (num <= 0)
1563 			num = 1;
1564 		tsm_screen_erase_chars(vte->con, num);
1565 		break;
1566 	case 'm':
1567 		csi_attribute(vte);
1568 		break;
1569 	case 'p':
1570 		if (vte->csi_flags & CSI_GT) {
1571 			/* xterm: select X11 visual cursor mode */
1572 			csi_soft_reset(vte);
1573 		} else if (vte->csi_flags & CSI_BANG) {
1574 			/* DECSTR: Soft Reset */
1575 			csi_soft_reset(vte);
1576 		} else if (vte->csi_flags & CSI_CASH) {
1577 			/* DECRQM: Request DEC Private Mode */
1578 			/* If CSI_WHAT is set, then enable,
1579 			 * otherwise disable */
1580 			csi_soft_reset(vte);
1581 		} else {
1582 			/* DECSCL: Compatibility Level */
1583 			/* Sometimes CSI_DQUOTE is set here, too */
1584 			csi_compat_mode(vte);
1585 		}
1586 		break;
1587 	case 'h': /* SM: Set Mode */
1588 		csi_mode(vte, true);
1589 		break;
1590 	case 'l': /* RM: Reset Mode */
1591 		csi_mode(vte, false);
1592 		break;
1593 	case 'r': /* DECSTBM */
1594 		/* set margin size */
1595 		upper = vte->csi_argv[0];
1596 		if (upper < 0)
1597 			upper = 0;
1598 		lower = vte->csi_argv[1];
1599 		if (lower < 0)
1600 			lower = 0;
1601 		tsm_screen_set_margins(vte->con, upper, lower);
1602 		tsm_screen_move_to(vte->con, 0, 0);
1603 		break;
1604 	case 'c': /* DA */
1605 		/* device attributes */
1606 		csi_dev_attr(vte);
1607 		break;
1608 	case 'L': /* IL */
1609 		/* insert lines */
1610 		num = vte->csi_argv[0];
1611 		if (num <= 0)
1612 			num = 1;
1613 		tsm_screen_insert_lines(vte->con, num);
1614 		break;
1615 	case 'M': /* DL */
1616 		/* delete lines */
1617 		num = vte->csi_argv[0];
1618 		if (num <= 0)
1619 			num = 1;
1620 		tsm_screen_delete_lines(vte->con, num);
1621 		break;
1622 	case 'g': /* TBC */
1623 		/* tabulation clear */
1624 		num = vte->csi_argv[0];
1625 		if (num <= 0)
1626 			tsm_screen_reset_tabstop(vte->con);
1627 		else if (num == 3)
1628 			tsm_screen_reset_all_tabstops(vte->con);
1629 		else
1630 			llog_debug(vte, "invalid parameter %d to TBC CSI", num);
1631 		break;
1632 	case '@': /* ICH */
1633 		/* insert characters */
1634 		num = vte->csi_argv[0];
1635 		if (num <= 0)
1636 			num = 1;
1637 		tsm_screen_insert_chars(vte->con, num);
1638 		break;
1639 	case 'P': /* DCH */
1640 		/* delete characters */
1641 		num = vte->csi_argv[0];
1642 		if (num <= 0)
1643 			num = 1;
1644 		tsm_screen_delete_chars(vte->con, num);
1645 		break;
1646 	case 'Z': /* CBT */
1647 		/* cursor horizontal backwards tab */
1648 		num = vte->csi_argv[0];
1649 		if (num <= 0)
1650 			num = 1;
1651 		tsm_screen_tab_left(vte->con, num);
1652 		break;
1653 	case 'I': /* CHT */
1654 		/* cursor horizontal forward tab */
1655 		num = vte->csi_argv[0];
1656 		if (num <= 0)
1657 			num = 1;
1658 		tsm_screen_tab_right(vte->con, num);
1659 		break;
1660 	case 'n': /* DSR */
1661 		/* device status reports */
1662 		csi_dsr(vte);
1663 		break;
1664 	case 'S': /* SU */
1665 		/* scroll up */
1666 		num = vte->csi_argv[0];
1667 		if (num <= 0)
1668 			num = 1;
1669 		tsm_screen_scroll_up(vte->con, num);
1670 		break;
1671 	case 'T': /* SD */
1672 		/* scroll down */
1673 		num = vte->csi_argv[0];
1674 		if (num <= 0)
1675 			num = 1;
1676 		tsm_screen_scroll_down(vte->con, num);
1677 		break;
1678 	default:
1679 		llog_debug(vte, "unhandled CSI sequence %c", data);
1680 	}
1681 }
1682 
1683 /* map a character according to current GL and GR maps */
vte_map(struct tsm_vte * vte,uint32_t val)1684 static uint32_t vte_map(struct tsm_vte *vte, uint32_t val)
1685 {
1686 	/* 32, 127, 160 and 255 map to identity like all values >255 */
1687 	switch (val) {
1688 	case 33 ... 126:
1689 		if (vte->glt) {
1690 			val = (**vte->glt)[val - 32];
1691 			vte->glt = NULL;
1692 		} else {
1693 			val = (**vte->gl)[val - 32];
1694 		}
1695 		break;
1696 	case 161 ... 254:
1697 		if (vte->grt) {
1698 			val = (**vte->grt)[val - 160];
1699 			vte->grt = NULL;
1700 		} else {
1701 			val = (**vte->gr)[val - 160];
1702 		}
1703 		break;
1704 	}
1705 
1706 	return val;
1707 }
1708 
1709 /* perform parser action */
do_action(struct tsm_vte * vte,uint32_t data,int action)1710 static void do_action(struct tsm_vte *vte, uint32_t data, int action)
1711 {
1712 	tsm_symbol_t sym;
1713 
1714 	switch (action) {
1715 		case ACTION_NONE:
1716 			/* do nothing */
1717 			return;
1718 		case ACTION_IGNORE:
1719 			/* ignore character */
1720 			break;
1721 		case ACTION_PRINT:
1722 			sym = tsm_symbol_make(vte_map(vte, data));
1723 			write_console(vte, sym);
1724 			break;
1725 		case ACTION_EXECUTE:
1726 			do_execute(vte, data);
1727 			break;
1728 		case ACTION_CLEAR:
1729 			do_clear(vte);
1730 			break;
1731 		case ACTION_COLLECT:
1732 			do_collect(vte, data);
1733 			break;
1734 		case ACTION_PARAM:
1735 			do_param(vte, data);
1736 			break;
1737 		case ACTION_ESC_DISPATCH:
1738 			do_esc(vte, data);
1739 			break;
1740 		case ACTION_CSI_DISPATCH:
1741 			do_csi(vte, data);
1742 			break;
1743 		case ACTION_DCS_START:
1744 			break;
1745 		case ACTION_DCS_COLLECT:
1746 			break;
1747 		case ACTION_DCS_END:
1748 			break;
1749 		case ACTION_OSC_START:
1750 			break;
1751 		case ACTION_OSC_COLLECT:
1752 			break;
1753 		case ACTION_OSC_END:
1754 			break;
1755 		default:
1756 			llog_warning(vte, "invalid action %d", action);
1757 	}
1758 }
1759 
1760 /* entry actions to be performed when entering the selected state */
1761 static const int entry_action[] = {
1762 	[STATE_CSI_ENTRY] = ACTION_CLEAR,
1763 	[STATE_DCS_ENTRY] = ACTION_CLEAR,
1764 	[STATE_DCS_PASS] = ACTION_DCS_START,
1765 	[STATE_ESC] = ACTION_CLEAR,
1766 	[STATE_OSC_STRING] = ACTION_OSC_START,
1767 	[STATE_NUM] = ACTION_NONE,
1768 };
1769 
1770 /* exit actions to be performed when leaving the selected state */
1771 static const int exit_action[] = {
1772 	[STATE_DCS_PASS] = ACTION_DCS_END,
1773 	[STATE_OSC_STRING] = ACTION_OSC_END,
1774 	[STATE_NUM] = ACTION_NONE,
1775 };
1776 
1777 /* perform state transition and dispatch related actions */
do_trans(struct tsm_vte * vte,uint32_t data,int state,int act)1778 static void do_trans(struct tsm_vte *vte, uint32_t data, int state, int act)
1779 {
1780 	if (state != STATE_NONE) {
1781 		/* A state transition occurs. Perform exit-action,
1782 		 * transition-action and entry-action. Even when performing a
1783 		 * transition to the same state as the current state we do this.
1784 		 * Use STATE_NONE if this is not the desired behavior.
1785 		 */
1786 		do_action(vte, data, exit_action[vte->state]);
1787 		do_action(vte, data, act);
1788 		do_action(vte, data, entry_action[state]);
1789 		vte->state = state;
1790 	} else {
1791 		do_action(vte, data, act);
1792 	}
1793 }
1794 
1795 /*
1796  * Escape sequence parser
1797  * This parses the new input character \data. It performs state transition and
1798  * calls the right callbacks for each action.
1799  */
parse_data(struct tsm_vte * vte,uint32_t raw)1800 static void parse_data(struct tsm_vte *vte, uint32_t raw)
1801 {
1802 	/* events that may occur in any state */
1803 	switch (raw) {
1804 		case 0x18:
1805 		case 0x1a:
1806 		case 0x80 ... 0x8f:
1807 		case 0x91 ... 0x97:
1808 		case 0x99:
1809 		case 0x9a:
1810 		case 0x9c:
1811 			do_trans(vte, raw, STATE_GROUND, ACTION_EXECUTE);
1812 			return;
1813 		case 0x1b:
1814 			do_trans(vte, raw, STATE_ESC, ACTION_NONE);
1815 			return;
1816 		case 0x98:
1817 		case 0x9e:
1818 		case 0x9f:
1819 			do_trans(vte, raw, STATE_ST_IGNORE, ACTION_NONE);
1820 			return;
1821 		case 0x90:
1822 			do_trans(vte, raw, STATE_DCS_ENTRY, ACTION_NONE);
1823 			return;
1824 		case 0x9d:
1825 			do_trans(vte, raw, STATE_OSC_STRING, ACTION_NONE);
1826 			return;
1827 		case 0x9b:
1828 			do_trans(vte, raw, STATE_CSI_ENTRY, ACTION_NONE);
1829 			return;
1830 	}
1831 
1832 	/* events that depend on the current state */
1833 	switch (vte->state) {
1834 	case STATE_GROUND:
1835 		switch (raw) {
1836 		case 0x00 ... 0x17:
1837 		case 0x19:
1838 		case 0x1c ... 0x1f:
1839 		case 0x80 ... 0x8f:
1840 		case 0x91 ... 0x9a:
1841 		case 0x9c:
1842 			do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1843 			return;
1844 		case 0x20 ... 0x7f:
1845 			do_trans(vte, raw, STATE_NONE, ACTION_PRINT);
1846 			return;
1847 		}
1848 		do_trans(vte, raw, STATE_NONE, ACTION_PRINT);
1849 		return;
1850 	case STATE_ESC:
1851 		switch (raw) {
1852 		case 0x00 ... 0x17:
1853 		case 0x19:
1854 		case 0x1c ... 0x1f:
1855 			do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1856 			return;
1857 		case 0x7f:
1858 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1859 			return;
1860 		case 0x20 ... 0x2f:
1861 			do_trans(vte, raw, STATE_ESC_INT, ACTION_COLLECT);
1862 			return;
1863 		case 0x30 ... 0x4f:
1864 		case 0x51 ... 0x57:
1865 		case 0x59:
1866 		case 0x5a:
1867 		case 0x5c:
1868 		case 0x60 ... 0x7e:
1869 			do_trans(vte, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1870 			return;
1871 		case 0x5b:
1872 			do_trans(vte, raw, STATE_CSI_ENTRY, ACTION_NONE);
1873 			return;
1874 		case 0x5d:
1875 			do_trans(vte, raw, STATE_OSC_STRING, ACTION_NONE);
1876 			return;
1877 		case 0x50:
1878 			do_trans(vte, raw, STATE_DCS_ENTRY, ACTION_NONE);
1879 			return;
1880 		case 0x58:
1881 		case 0x5e:
1882 		case 0x5f:
1883 			do_trans(vte, raw, STATE_ST_IGNORE, ACTION_NONE);
1884 			return;
1885 		}
1886 		do_trans(vte, raw, STATE_ESC_INT, ACTION_COLLECT);
1887 		return;
1888 	case STATE_ESC_INT:
1889 		switch (raw) {
1890 		case 0x00 ... 0x17:
1891 		case 0x19:
1892 		case 0x1c ... 0x1f:
1893 			do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1894 			return;
1895 		case 0x20 ... 0x2f:
1896 			do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1897 			return;
1898 		case 0x7f:
1899 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1900 			return;
1901 		case 0x30 ... 0x7e:
1902 			do_trans(vte, raw, STATE_GROUND, ACTION_ESC_DISPATCH);
1903 			return;
1904 		}
1905 		do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1906 		return;
1907 	case STATE_CSI_ENTRY:
1908 		switch (raw) {
1909 		case 0x00 ... 0x17:
1910 		case 0x19:
1911 		case 0x1c ... 0x1f:
1912 			do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1913 			return;
1914 		case 0x7f:
1915 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1916 			return;
1917 		case 0x20 ... 0x2f:
1918 			do_trans(vte, raw, STATE_CSI_INT, ACTION_COLLECT);
1919 			return;
1920 		case 0x3a:
1921 			do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1922 			return;
1923 		case 0x30 ... 0x39:
1924 		case 0x3b:
1925 			do_trans(vte, raw, STATE_CSI_PARAM, ACTION_PARAM);
1926 			return;
1927 		case 0x3c ... 0x3f:
1928 			do_trans(vte, raw, STATE_CSI_PARAM, ACTION_COLLECT);
1929 			return;
1930 		case 0x40 ... 0x7e:
1931 			do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1932 			return;
1933 		}
1934 		do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1935 		return;
1936 	case STATE_CSI_PARAM:
1937 		switch (raw) {
1938 		case 0x00 ... 0x17:
1939 		case 0x19:
1940 		case 0x1c ... 0x1f:
1941 			do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1942 			return;
1943 		case 0x30 ... 0x39:
1944 		case 0x3b:
1945 			do_trans(vte, raw, STATE_NONE, ACTION_PARAM);
1946 			return;
1947 		case 0x7f:
1948 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1949 			return;
1950 		case 0x3a:
1951 		case 0x3c ... 0x3f:
1952 			do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1953 			return;
1954 		case 0x20 ... 0x2f:
1955 			do_trans(vte, raw, STATE_CSI_INT, ACTION_COLLECT);
1956 			return;
1957 		case 0x40 ... 0x7e:
1958 			do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1959 			return;
1960 		}
1961 		do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1962 		return;
1963 	case STATE_CSI_INT:
1964 		switch (raw) {
1965 		case 0x00 ... 0x17:
1966 		case 0x19:
1967 		case 0x1c ... 0x1f:
1968 			do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1969 			return;
1970 		case 0x20 ... 0x2f:
1971 			do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
1972 			return;
1973 		case 0x7f:
1974 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1975 			return;
1976 		case 0x30 ... 0x3f:
1977 			do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1978 			return;
1979 		case 0x40 ... 0x7e:
1980 			do_trans(vte, raw, STATE_GROUND, ACTION_CSI_DISPATCH);
1981 			return;
1982 		}
1983 		do_trans(vte, raw, STATE_CSI_IGNORE, ACTION_NONE);
1984 		return;
1985 	case STATE_CSI_IGNORE:
1986 		switch (raw) {
1987 		case 0x00 ... 0x17:
1988 		case 0x19:
1989 		case 0x1c ... 0x1f:
1990 			do_trans(vte, raw, STATE_NONE, ACTION_EXECUTE);
1991 			return;
1992 		case 0x20 ... 0x3f:
1993 		case 0x7f:
1994 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
1995 			return;
1996 		case 0x40 ... 0x7e:
1997 			do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
1998 			return;
1999 		}
2000 		do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2001 		return;
2002 	case STATE_DCS_ENTRY:
2003 		switch (raw) {
2004 		case 0x00 ... 0x17:
2005 		case 0x19:
2006 		case 0x1c ... 0x1f:
2007 		case 0x7f:
2008 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2009 			return;
2010 		case 0x3a:
2011 			do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2012 			return;
2013 		case 0x20 ... 0x2f:
2014 			do_trans(vte, raw, STATE_DCS_INT, ACTION_COLLECT);
2015 			return;
2016 		case 0x30 ... 0x39:
2017 		case 0x3b:
2018 			do_trans(vte, raw, STATE_DCS_PARAM, ACTION_PARAM);
2019 			return;
2020 		case 0x3c ... 0x3f:
2021 			do_trans(vte, raw, STATE_DCS_PARAM, ACTION_COLLECT);
2022 			return;
2023 		case 0x40 ... 0x7e:
2024 			do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2025 			return;
2026 		}
2027 		do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2028 		return;
2029 	case STATE_DCS_PARAM:
2030 		switch (raw) {
2031 		case 0x00 ... 0x17:
2032 		case 0x19:
2033 		case 0x1c ... 0x1f:
2034 		case 0x7f:
2035 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2036 			return;
2037 		case 0x30 ... 0x39:
2038 		case 0x3b:
2039 			do_trans(vte, raw, STATE_NONE, ACTION_PARAM);
2040 			return;
2041 		case 0x3a:
2042 		case 0x3c ... 0x3f:
2043 			do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2044 			return;
2045 		case 0x20 ... 0x2f:
2046 			do_trans(vte, raw, STATE_DCS_INT, ACTION_COLLECT);
2047 			return;
2048 		case 0x40 ... 0x7e:
2049 			do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2050 			return;
2051 		}
2052 		do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2053 		return;
2054 	case STATE_DCS_INT:
2055 		switch (raw) {
2056 		case 0x00 ... 0x17:
2057 		case 0x19:
2058 		case 0x1c ... 0x1f:
2059 		case 0x7f:
2060 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2061 			return;
2062 		case 0x20 ... 0x2f:
2063 			do_trans(vte, raw, STATE_NONE, ACTION_COLLECT);
2064 			return;
2065 		case 0x30 ... 0x3f:
2066 			do_trans(vte, raw, STATE_DCS_IGNORE, ACTION_NONE);
2067 			return;
2068 		case 0x40 ... 0x7e:
2069 			do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2070 			return;
2071 		}
2072 		do_trans(vte, raw, STATE_DCS_PASS, ACTION_NONE);
2073 		return;
2074 	case STATE_DCS_PASS:
2075 		switch (raw) {
2076 		case 0x00 ... 0x17:
2077 		case 0x19:
2078 		case 0x1c ... 0x1f:
2079 		case 0x20 ... 0x7e:
2080 			do_trans(vte, raw, STATE_NONE, ACTION_DCS_COLLECT);
2081 			return;
2082 		case 0x7f:
2083 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2084 			return;
2085 		case 0x9c:
2086 			do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2087 			return;
2088 		}
2089 		do_trans(vte, raw, STATE_NONE, ACTION_DCS_COLLECT);
2090 		return;
2091 	case STATE_DCS_IGNORE:
2092 		switch (raw) {
2093 		case 0x00 ... 0x17:
2094 		case 0x19:
2095 		case 0x1c ... 0x1f:
2096 		case 0x20 ... 0x7f:
2097 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2098 			return;
2099 		case 0x9c:
2100 			do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2101 			return;
2102 		}
2103 		do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2104 		return;
2105 	case STATE_OSC_STRING:
2106 		switch (raw) {
2107 		case 0x00 ... 0x06:
2108 		case 0x08 ... 0x17:
2109 		case 0x19:
2110 		case 0x1c ... 0x1f:
2111 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2112 			return;
2113 		case 0x20 ... 0x7f:
2114 			do_trans(vte, raw, STATE_NONE, ACTION_OSC_COLLECT);
2115 			return;
2116 		case 0x07:
2117 		case 0x9c:
2118 			do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2119 			return;
2120 		}
2121 		do_trans(vte, raw, STATE_NONE, ACTION_OSC_COLLECT);
2122 		return;
2123 	case STATE_ST_IGNORE:
2124 		switch (raw) {
2125 		case 0x00 ... 0x17:
2126 		case 0x19:
2127 		case 0x1c ... 0x1f:
2128 		case 0x20 ... 0x7f:
2129 			do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2130 			return;
2131 		case 0x9c:
2132 			do_trans(vte, raw, STATE_GROUND, ACTION_NONE);
2133 			return;
2134 		}
2135 		do_trans(vte, raw, STATE_NONE, ACTION_IGNORE);
2136 		return;
2137 	}
2138 
2139 	llog_warning(vte, "unhandled input %u in state %d", raw, vte->state);
2140 }
2141 
2142 SHL_EXPORT
tsm_vte_input(struct tsm_vte * vte,const char * u8,size_t len)2143 void tsm_vte_input(struct tsm_vte *vte, const char *u8, size_t len)
2144 {
2145 	int state;
2146 	uint32_t ucs4;
2147 	size_t i;
2148 
2149 	++vte->parse_cnt;
2150 	for (i = 0; i < len; ++i) {
2151 		if (vte->flags & FLAG_7BIT_MODE) {
2152 			if (u8[i] & 0x80)
2153 				llog_debug(vte, "receiving 8bit character U+%d from pty while in 7bit mode",
2154 					   (int)u8[i]);
2155 			parse_data(vte, u8[i] & 0x7f);
2156 		} else if (vte->flags & FLAG_8BIT_MODE) {
2157 			parse_data(vte, u8[i]);
2158 		} else {
2159 			state = tsm_utf8_mach_feed(vte->mach, u8[i]);
2160 			if (state == TSM_UTF8_ACCEPT ||
2161 			    state == TSM_UTF8_REJECT) {
2162 				ucs4 = tsm_utf8_mach_get(vte->mach);
2163 				parse_data(vte, ucs4);
2164 			}
2165 		}
2166 	}
2167 	--vte->parse_cnt;
2168 }
2169 
2170 SHL_EXPORT
tsm_vte_handle_keyboard(struct tsm_vte * vte,uint32_t keysym,uint32_t ascii,unsigned int mods,uint32_t unicode)2171 bool tsm_vte_handle_keyboard(struct tsm_vte *vte, uint32_t keysym,
2172 			     uint32_t ascii, unsigned int mods,
2173 			     uint32_t unicode)
2174 {
2175 	char val, u8[4];
2176 	size_t len;
2177 	uint32_t sym;
2178 
2179 	/* MOD1 (mostly labeled 'Alt') prepends an escape character to every
2180 	 * input that is sent by a key.
2181 	 * TODO: Transform this huge handler into a lookup table to save a lot
2182 	 * of code and make such modifiers easier to implement.
2183 	 * Also check whether altSendsEscape should be the default (xterm
2184 	 * disables this by default, why?) and whether we should implement the
2185 	 * fallback shifting that xterm does. */
2186 	if (mods & TSM_ALT_MASK)
2187 		vte->flags |= FLAG_PREPEND_ESCAPE;
2188 
2189 	/* A user might actually use multiple layouts for keyboard input. The
2190 	 * @keysym variable contains the actual keysym that the user used. But
2191 	 * if this keysym is not in the ascii range, the input handler does
2192 	 * check all other layouts that the user specified whether one of them
2193 	 * maps the key to some ASCII keysym and provides this via @ascii.
2194 	 * We always use the real keysym except when handling CTRL+<XY>
2195 	 * shortcuts we use the ascii keysym. This is for compatibility to xterm
2196 	 * et. al. so ctrl+c always works regardless of the currently active
2197 	 * keyboard layout.
2198 	 * But if no ascii-sym is found, we still use the real keysym. */
2199 	sym = ascii;
2200 	if (sym == XKB_KEY_NoSymbol)
2201 		sym = keysym;
2202 
2203 	if (mods & TSM_CONTROL_MASK) {
2204 		switch (sym) {
2205 		case XKB_KEY_2:
2206 		case XKB_KEY_space:
2207 			vte_write(vte, "\x00", 1);
2208 			return true;
2209 		case XKB_KEY_a:
2210 		case XKB_KEY_A:
2211 			vte_write(vte, "\x01", 1);
2212 			return true;
2213 		case XKB_KEY_b:
2214 		case XKB_KEY_B:
2215 			vte_write(vte, "\x02", 1);
2216 			return true;
2217 		case XKB_KEY_c:
2218 		case XKB_KEY_C:
2219 			vte_write(vte, "\x03", 1);
2220 			return true;
2221 		case XKB_KEY_d:
2222 		case XKB_KEY_D:
2223 			vte_write(vte, "\x04", 1);
2224 			return true;
2225 		case XKB_KEY_e:
2226 		case XKB_KEY_E:
2227 			vte_write(vte, "\x05", 1);
2228 			return true;
2229 		case XKB_KEY_f:
2230 		case XKB_KEY_F:
2231 			vte_write(vte, "\x06", 1);
2232 			return true;
2233 		case XKB_KEY_g:
2234 		case XKB_KEY_G:
2235 			vte_write(vte, "\x07", 1);
2236 			return true;
2237 		case XKB_KEY_h:
2238 		case XKB_KEY_H:
2239 			vte_write(vte, "\x08", 1);
2240 			return true;
2241 		case XKB_KEY_i:
2242 		case XKB_KEY_I:
2243 			vte_write(vte, "\x09", 1);
2244 			return true;
2245 		case XKB_KEY_j:
2246 		case XKB_KEY_J:
2247 			vte_write(vte, "\x0a", 1);
2248 			return true;
2249 		case XKB_KEY_k:
2250 		case XKB_KEY_K:
2251 			vte_write(vte, "\x0b", 1);
2252 			return true;
2253 		case XKB_KEY_l:
2254 		case XKB_KEY_L:
2255 			vte_write(vte, "\x0c", 1);
2256 			return true;
2257 		case XKB_KEY_m:
2258 		case XKB_KEY_M:
2259 			vte_write(vte, "\x0d", 1);
2260 			return true;
2261 		case XKB_KEY_n:
2262 		case XKB_KEY_N:
2263 			vte_write(vte, "\x0e", 1);
2264 			return true;
2265 		case XKB_KEY_o:
2266 		case XKB_KEY_O:
2267 			vte_write(vte, "\x0f", 1);
2268 			return true;
2269 		case XKB_KEY_p:
2270 		case XKB_KEY_P:
2271 			vte_write(vte, "\x10", 1);
2272 			return true;
2273 		case XKB_KEY_q:
2274 		case XKB_KEY_Q:
2275 			vte_write(vte, "\x11", 1);
2276 			return true;
2277 		case XKB_KEY_r:
2278 		case XKB_KEY_R:
2279 			vte_write(vte, "\x12", 1);
2280 			return true;
2281 		case XKB_KEY_s:
2282 		case XKB_KEY_S:
2283 			vte_write(vte, "\x13", 1);
2284 			return true;
2285 		case XKB_KEY_t:
2286 		case XKB_KEY_T:
2287 			vte_write(vte, "\x14", 1);
2288 			return true;
2289 		case XKB_KEY_u:
2290 		case XKB_KEY_U:
2291 			vte_write(vte, "\x15", 1);
2292 			return true;
2293 		case XKB_KEY_v:
2294 		case XKB_KEY_V:
2295 			vte_write(vte, "\x16", 1);
2296 			return true;
2297 		case XKB_KEY_w:
2298 		case XKB_KEY_W:
2299 			vte_write(vte, "\x17", 1);
2300 			return true;
2301 		case XKB_KEY_x:
2302 		case XKB_KEY_X:
2303 			vte_write(vte, "\x18", 1);
2304 			return true;
2305 		case XKB_KEY_y:
2306 		case XKB_KEY_Y:
2307 			vte_write(vte, "\x19", 1);
2308 			return true;
2309 		case XKB_KEY_z:
2310 		case XKB_KEY_Z:
2311 			vte_write(vte, "\x1a", 1);
2312 			return true;
2313 		case XKB_KEY_3:
2314 		case XKB_KEY_bracketleft:
2315 		case XKB_KEY_braceleft:
2316 			vte_write(vte, "\x1b", 1);
2317 			return true;
2318 		case XKB_KEY_4:
2319 		case XKB_KEY_backslash:
2320 		case XKB_KEY_bar:
2321 			vte_write(vte, "\x1c", 1);
2322 			return true;
2323 		case XKB_KEY_5:
2324 		case XKB_KEY_bracketright:
2325 		case XKB_KEY_braceright:
2326 			vte_write(vte, "\x1d", 1);
2327 			return true;
2328 		case XKB_KEY_6:
2329 		case XKB_KEY_grave:
2330 		case XKB_KEY_asciitilde:
2331 			vte_write(vte, "\x1e", 1);
2332 			return true;
2333 		case XKB_KEY_7:
2334 		case XKB_KEY_slash:
2335 		case XKB_KEY_question:
2336 			vte_write(vte, "\x1f", 1);
2337 			return true;
2338 		case XKB_KEY_8:
2339 			vte_write(vte, "\x7f", 1);
2340 			return true;
2341 		}
2342 	}
2343 
2344 	switch (keysym) {
2345 		case XKB_KEY_BackSpace:
2346 			vte_write(vte, "\x7f", 1);
2347 			return true;
2348 		case XKB_KEY_Tab:
2349 		case XKB_KEY_KP_Tab:
2350 			vte_write(vte, "\x09", 1);
2351 			return true;
2352 		case XKB_KEY_ISO_Left_Tab:
2353 			vte_write(vte, "\e[Z", 3);
2354 			return true;
2355 		case XKB_KEY_Linefeed:
2356 			vte_write(vte, "\x0a", 1);
2357 			return true;
2358 		case XKB_KEY_Clear:
2359 			vte_write(vte, "\x0b", 1);
2360 			return true;
2361 		/*
2362 		 TODO: What should we do with this key? Sending XOFF is awful as
2363 		       there is no simple way on modern keyboards to send XON
2364 		       again. If someone wants this, we can re-eanble it and set
2365 		       some flag.
2366 		case XKB_KEY_Pause:
2367 			vte_write(vte, "\x13", 1);
2368 			return true;
2369 		*/
2370 		/*
2371 		 TODO: What should we do on scroll-lock? Sending 0x14 is what
2372 		       the specs say but it is not used today the way most
2373 		       users would expect so we disable it. If someone wants
2374 		       this, we can re-enable it and set some flag.
2375 		case XKB_KEY_Scroll_Lock:
2376 			vte_write(vte, "\x14", 1);
2377 			return true;
2378 		*/
2379 		case XKB_KEY_Sys_Req:
2380 			vte_write(vte, "\x15", 1);
2381 			return true;
2382 		case XKB_KEY_Escape:
2383 			vte_write(vte, "\x1b", 1);
2384 			return true;
2385 		case XKB_KEY_KP_Enter:
2386 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE) {
2387 				vte_write(vte, "\eOM", 3);
2388 				return true;
2389 			}
2390 			/* fallthrough */
2391 		case XKB_KEY_Return:
2392 			if (vte->flags & FLAG_LINE_FEED_NEW_LINE_MODE)
2393 				vte_write(vte, "\x0d\x0a", 2);
2394 			else
2395 				vte_write(vte, "\x0d", 1);
2396 			return true;
2397 		case XKB_KEY_Find:
2398 			vte_write_fnkey(vte, false, mods, 1, '~');
2399 			return true;
2400 		case XKB_KEY_Insert:
2401 			vte_write_fnkey(vte, false, mods, 2, '~');
2402 			return true;
2403 		case XKB_KEY_Delete:
2404 			vte_write_fnkey(vte, false, mods, 3, '~');
2405 			return true;
2406 		case XKB_KEY_Select:
2407 			vte_write_fnkey(vte, false, mods, 4, '~');
2408 			return true;
2409 		case XKB_KEY_Page_Up:
2410 		case XKB_KEY_KP_Page_Up:
2411 			vte_write_fnkey(vte, false, mods, 5, '~');
2412 			return true;
2413 		case XKB_KEY_Page_Down:
2414 		case XKB_KEY_KP_Page_Down:
2415 			vte_write_fnkey(vte, false, mods, 6, '~');
2416 			return true;
2417 		case XKB_KEY_Up:
2418 		case XKB_KEY_KP_Up:
2419 			vte_write_fnkey(vte, vte->flags & FLAG_CURSOR_KEY_MODE,
2420 					mods, 0, 'A');
2421 			return true;
2422 		case XKB_KEY_Down:
2423 		case XKB_KEY_KP_Down:
2424 			vte_write_fnkey(vte, vte->flags & FLAG_CURSOR_KEY_MODE,
2425 					mods, 0, 'B');
2426 			return true;
2427 		case XKB_KEY_Right:
2428 		case XKB_KEY_KP_Right:
2429 			vte_write_fnkey(vte, vte->flags & FLAG_CURSOR_KEY_MODE,
2430 					mods, 0, 'C');
2431 			return true;
2432 		case XKB_KEY_Left:
2433 		case XKB_KEY_KP_Left:
2434 			vte_write_fnkey(vte, vte->flags & FLAG_CURSOR_KEY_MODE,
2435 					mods, 0, 'D');
2436 			return true;
2437 		case XKB_KEY_KP_Insert:
2438 		case XKB_KEY_KP_0:
2439 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2440 				vte_write(vte, "\eOp", 3);
2441 			else
2442 				vte_write(vte, "0", 1);
2443 			return true;
2444 		case XKB_KEY_KP_1:
2445 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2446 				vte_write(vte, "\eOq", 3);
2447 			else
2448 				vte_write(vte, "1", 1);
2449 			return true;
2450 		case XKB_KEY_KP_2:
2451 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2452 				vte_write(vte, "\eOr", 3);
2453 			else
2454 				vte_write(vte, "2", 1);
2455 			return true;
2456 		case XKB_KEY_KP_3:
2457 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2458 				vte_write(vte, "\eOs", 3);
2459 			else
2460 				vte_write(vte, "3", 1);
2461 			return true;
2462 		case XKB_KEY_KP_4:
2463 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2464 				vte_write(vte, "\eOt", 3);
2465 			else
2466 				vte_write(vte, "4", 1);
2467 			return true;
2468 		case XKB_KEY_KP_5:
2469 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2470 				vte_write(vte, "\eOu", 3);
2471 			else
2472 				vte_write(vte, "5", 1);
2473 			return true;
2474 		case XKB_KEY_KP_6:
2475 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2476 				vte_write(vte, "\eOv", 3);
2477 			else
2478 				vte_write(vte, "6", 1);
2479 			return true;
2480 		case XKB_KEY_KP_7:
2481 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2482 				vte_write(vte, "\eOw", 3);
2483 			else
2484 				vte_write(vte, "7", 1);
2485 			return true;
2486 		case XKB_KEY_KP_8:
2487 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2488 				vte_write(vte, "\eOx", 3);
2489 			else
2490 				vte_write(vte, "8", 1);
2491 			return true;
2492 		case XKB_KEY_KP_9:
2493 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2494 				vte_write(vte, "\eOy", 3);
2495 			else
2496 				vte_write(vte, "9", 1);
2497 			return true;
2498 		case XKB_KEY_KP_Subtract:
2499 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2500 				vte_write(vte, "\eOm", 3);
2501 			else
2502 				vte_write(vte, "-", 1);
2503 			return true;
2504 		case XKB_KEY_KP_Separator:
2505 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2506 				vte_write(vte, "\eOl", 3);
2507 			else
2508 				vte_write(vte, ",", 1);
2509 			return true;
2510 		case XKB_KEY_KP_Delete:
2511 		case XKB_KEY_KP_Decimal:
2512 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2513 				vte_write(vte, "\eOn", 3);
2514 			else
2515 				vte_write(vte, ".", 1);
2516 			return true;
2517 		case XKB_KEY_KP_Equal:
2518 		case XKB_KEY_KP_Divide:
2519 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2520 				vte_write(vte, "\eOj", 3);
2521 			else
2522 				vte_write(vte, "/", 1);
2523 			return true;
2524 		case XKB_KEY_KP_Multiply:
2525 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2526 				vte_write(vte, "\eOo", 3);
2527 			else
2528 				vte_write(vte, "*", 1);
2529 			return true;
2530 		case XKB_KEY_KP_Add:
2531 			if (vte->flags & FLAG_KEYPAD_APPLICATION_MODE)
2532 				vte_write(vte, "\eOk", 3);
2533 			else
2534 				vte_write(vte, "+", 1);
2535 			return true;
2536 		case XKB_KEY_Home:
2537 		case XKB_KEY_KP_Home:
2538 			vte_write_fnkey(vte, vte->flags & FLAG_CURSOR_KEY_MODE,
2539 					mods, 0, 'H');
2540 			return true;
2541 		case XKB_KEY_End:
2542 		case XKB_KEY_KP_End:
2543 			vte_write_fnkey(vte, vte->flags & FLAG_CURSOR_KEY_MODE,
2544 					mods, 0, 'F');
2545 			return true;
2546 		case XKB_KEY_KP_Space:
2547 			vte_write(vte, " ", 1);
2548 			return true;
2549 		case XKB_KEY_F1:
2550 		case XKB_KEY_KP_F1:
2551 			vte_write_fnkey(vte, true, mods, 0, 'P');
2552 			return true;
2553 		case XKB_KEY_F2:
2554 		case XKB_KEY_KP_F2:
2555 			vte_write_fnkey(vte, true, mods, 0, 'Q');
2556 			return true;
2557 		case XKB_KEY_F3:
2558 		case XKB_KEY_KP_F3:
2559 			vte_write_fnkey(vte, true, mods, 0, 'R');
2560 			return true;
2561 		case XKB_KEY_F4:
2562 		case XKB_KEY_KP_F4:
2563 			vte_write_fnkey(vte, true, mods, 0, 'S');
2564 			return true;
2565 		case XKB_KEY_F5:
2566 			vte_write_fnkey(vte, false, mods, 15, '~');
2567 			return true;
2568 		case XKB_KEY_F6:
2569 			vte_write_fnkey(vte, false, mods, 17, '~');
2570 			return true;
2571 		case XKB_KEY_F7:
2572 			vte_write_fnkey(vte, false, mods, 18, '~');
2573 			return true;
2574 		case XKB_KEY_F8:
2575 			vte_write_fnkey(vte, false, mods, 19, '~');
2576 			return true;
2577 		case XKB_KEY_F9:
2578 			vte_write_fnkey(vte, false, mods, 20, '~');
2579 			return true;
2580 		case XKB_KEY_F10:
2581 			vte_write_fnkey(vte, false, mods, 21, '~');
2582 			return true;
2583 		case XKB_KEY_F11:
2584 			vte_write_fnkey(vte, false, mods, 23, '~');
2585 			return true;
2586 		case XKB_KEY_F12:
2587 			vte_write_fnkey(vte, false, mods, 24, '~');
2588 			return true;
2589 		case XKB_KEY_F13:
2590 			vte_write_fnkey(vte, false, mods, 25, '~');
2591 			return true;
2592 		case XKB_KEY_F14:
2593 			vte_write_fnkey(vte, false, mods, 26, '~');
2594 			return true;
2595 		case XKB_KEY_F15:
2596 			vte_write_fnkey(vte, false, mods, 28, '~');
2597 			return true;
2598 		case XKB_KEY_F16:
2599 			vte_write_fnkey(vte, false, mods, 29, '~');
2600 			return true;
2601 		case XKB_KEY_F17:
2602 			vte_write_fnkey(vte, false, mods, 31, '~');
2603 			return true;
2604 		case XKB_KEY_F18:
2605 			vte_write_fnkey(vte, false, mods, 32, '~');
2606 			return true;
2607 		case XKB_KEY_F19:
2608 			vte_write_fnkey(vte, false, mods, 33, '~');
2609 			return true;
2610 		case XKB_KEY_F20:
2611 			vte_write_fnkey(vte, false, mods, 34, '~');
2612 			return true;
2613 	}
2614 
2615 	if (unicode != TSM_VTE_INVALID) {
2616 		if (vte->flags & FLAG_7BIT_MODE) {
2617 			val = unicode;
2618 			if (unicode & 0x80) {
2619 				llog_debug(vte, "invalid keyboard input in 7bit mode U+%x; mapping to '?'",
2620 					   unicode);
2621 				val = '?';
2622 			}
2623 			vte_write(vte, &val, 1);
2624 		} else if (vte->flags & FLAG_8BIT_MODE) {
2625 			val = unicode;
2626 			if (unicode > 0xff) {
2627 				llog_debug(vte, "invalid keyboard input in 8bit mode U+%x; mapping to '?'",
2628 					   unicode);
2629 				val = '?';
2630 			}
2631 			vte_write_raw(vte, &val, 1);
2632 		} else {
2633 			len = tsm_ucs4_to_utf8(tsm_symbol_make(unicode), u8);
2634 			vte_write_raw(vte, u8, len);
2635 		}
2636 		return true;
2637 	}
2638 
2639 	vte->flags &= ~FLAG_PREPEND_ESCAPE;
2640 	return false;
2641 }
2642 
2643 SHL_EXPORT
tsm_vte_paste_begin(struct tsm_vte * vte)2644 void tsm_vte_paste_begin(struct tsm_vte *vte)
2645 {
2646 	if (vte->flags & FLAG_BRACKETED_PASTE_MODE) {
2647 		vte_write(vte, "\e[200~", 6);
2648 		vte->pasting = true;
2649 		vte->endpaste_i = 0;
2650 	}
2651 }
2652 
2653 SHL_EXPORT
tsm_vte_paste_end(struct tsm_vte * vte)2654 void tsm_vte_paste_end(struct tsm_vte *vte)
2655 {
2656 	if (vte->pasting) {
2657 		vte->pasting = false;
2658 		if (vte->endpaste_i)
2659 			vte->write_cb(vte, ENDPASTE, vte->endpaste_i,
2660 				      vte->data);
2661 		vte_write(vte, "\e[201~", 6);
2662 	}
2663 }
2664