chiark / gitweb /
timesyncd: Support timesyncd.conf.d directories in the usual search paths
[elogind.git] / src / libsystemd-terminal / term-screen.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 /*
23  * Terminal Screens
24  * The term_screen layer implements the terminal-side. It handles all commands
25  * returned by the seq-parser and applies them to its own pages.
26  *
27  * While there are a lot of legacy control-sequences, we only support a small
28  * subset. There is no reason to implement unused codes like horizontal
29  * scrolling.
30  * If you implement new commands, make sure to document them properly.
31  *
32  * Standards:
33  *   ECMA-48
34  *   ANSI X3.64
35  *   ISO/IEC 6429
36  * References:
37  *   http://www.vt100.net/emu/ctrlseq_dec.html
38  *   http://www.vt100.net/docs/vt100-ug/chapter3.html
39  *   http://www.vt100.net/docs/vt510-rm/chapter4
40  *   http://www.vt100.net/docs/vt510-rm/contents
41  *   http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
42  *   ASCII
43  *   http://en.wikipedia.org/wiki/C0_and_C1_control_codes
44  *   https://en.wikipedia.org/wiki/ANSI_color
45  */
46
47 #include <stdbool.h>
48 #include <stdint.h>
49 #include <stdlib.h>
50 #include <xkbcommon/xkbcommon-keysyms.h>
51 #include "macro.h"
52 #include "term-internal.h"
53 #include "util.h"
54
55 int term_screen_new(term_screen **out, term_screen_write_fn write_fn, void *write_fn_data, term_screen_cmd_fn cmd_fn, void *cmd_fn_data) {
56         _cleanup_(term_screen_unrefp) term_screen *screen = NULL;
57         int r;
58
59         assert_return(out, -EINVAL);
60
61         screen = new0(term_screen, 1);
62         if (!screen)
63                 return -ENOMEM;
64
65         screen->ref = 1;
66         screen->age = 1;
67         screen->write_fn = write_fn;
68         screen->write_fn_data = write_fn_data;
69         screen->cmd_fn = cmd_fn;
70         screen->cmd_fn_data = cmd_fn_data;
71         screen->flags = TERM_FLAG_7BIT_MODE;
72         screen->conformance_level = TERM_CONFORMANCE_LEVEL_VT400;
73         screen->g0 = &term_unicode_lower;
74         screen->g1 = &term_unicode_upper;
75         screen->g2 = &term_unicode_lower;
76         screen->g3 = &term_unicode_upper;
77         screen->state.gl = &screen->g0;
78         screen->state.gr = &screen->g1;
79         screen->saved = screen->state;
80         screen->saved_alt = screen->saved;
81
82         r = term_page_new(&screen->page_main);
83         if (r < 0)
84                 return r;
85
86         r = term_page_new(&screen->page_alt);
87         if (r < 0)
88                 return r;
89
90         r = term_parser_new(&screen->parser, false);
91         if (r < 0)
92                 return r;
93
94         r = term_history_new(&screen->history_main);
95         if (r < 0)
96                 return r;
97
98         screen->page = screen->page_main;
99         screen->history = screen->history_main;
100
101         *out = screen;
102         screen = NULL;
103         return 0;
104 }
105
106 term_screen *term_screen_ref(term_screen *screen) {
107         if (!screen)
108                 return NULL;
109
110         assert_return(screen->ref > 0, NULL);
111
112         ++screen->ref;
113         return screen;
114 }
115
116 term_screen *term_screen_unref(term_screen *screen) {
117         if (!screen)
118                 return NULL;
119
120         assert_return(screen->ref > 0, NULL);
121
122         if (--screen->ref)
123                 return NULL;
124
125         free(screen->answerback);
126         free(screen->tabs);
127         term_history_free(screen->history_main);
128         term_page_free(screen->page_alt);
129         term_page_free(screen->page_main);
130         term_parser_free(screen->parser);
131         free(screen);
132
133         return NULL;
134 }
135
136 /*
137  * Write-Helpers
138  * Unfortunately, 7bit/8bit compat mode requires us to send C1 controls encoded
139  * as 7bit if asked by the application. This is really used in the wild, so we
140  * cannot fall back to "always 7bit".
141  * screen_write() is the underlying backend which forwards any writes to the
142  * users's callback. It's the users responsibility to buffer these and write
143  * them out once their call to term_screen_feed_*() returns.
144  * The SEQ_WRITE() and SEQ_WRITE_KEY() macros allow constructing C0/C1 sequences
145  * directly in the code-base without requiring any intermediate buffer during
146  * runtime.
147  */
148
149 #define C0_CSI "\e["
150 #define C1_CSI "\x9b"
151
152 #define SEQ(_screen, _prefix_esc, _c0, _c1, _seq) \
153                 (((_screen)->flags & TERM_FLAG_7BIT_MODE) ? \
154                         ((_prefix_esc) ? ("\e" _c0 _seq) : (_c0 _seq)) : \
155                         ((_prefix_esc) ? ("\e" _c1 _seq) : (_c1 _seq)))
156
157 #define SEQ_SIZE(_screen, _prefix_esc, _c0, _c1, _seq) \
158                 (((_screen)->flags & TERM_FLAG_7BIT_MODE) ? \
159                         ((_prefix_esc) ? sizeof("\e" _c0 _seq) : sizeof(_c0 _seq)) : \
160                         ((_prefix_esc) ? sizeof("\e" _c1 _seq) : sizeof(_c1 _seq)))
161
162 #define SEQ_WRITE_KEY(_screen, _prefix_esc, _c0, _c1, _seq) \
163                 screen_write((_screen), \
164                              SEQ((_screen), (_prefix_esc), \
165                                  _c0, _c1, _seq), \
166                              SEQ_SIZE((_screen), (_prefix_esc), \
167                                      _c0, _c1, _seq) - 1)
168
169 #define SEQ_WRITE(_screen, _c0, _c1, _seq) \
170                 SEQ_WRITE_KEY((_screen), false, _c0, _c1, _seq)
171
172 static int screen_write(term_screen *screen, const void *buf, size_t len) {
173         if (len < 1 || !screen->write_fn)
174                 return 0;
175
176         return screen->write_fn(screen, screen->write_fn_data, buf, len);
177 }
178
179 /*
180  * Command Forwarding
181  * Some commands cannot be handled by the screen-layer directly. Those are
182  * forwarded to the command-handler of the caller. This is rarely used and can
183  * safely be set to NULL.
184  */
185
186 static int screen_forward(term_screen *screen, unsigned int cmd, const term_seq *seq) {
187         if (!screen->cmd_fn)
188                 return 0;
189
190         return screen->cmd_fn(screen, screen->cmd_fn_data, cmd, seq);
191 }
192
193 /*
194  * Screen Helpers
195  * These helpers implement common-operations like cursor-handler and more, which
196  * are used by several command dispatchers.
197  */
198
199 static unsigned int screen_clamp_x(term_screen *screen, unsigned int x) {
200         if (x >= screen->page->width)
201                 return (screen->page->width > 0) ? screen->page->width - 1 : 0;
202
203         return x;
204 }
205
206 static unsigned int screen_clamp_y(term_screen *screen, unsigned int y) {
207         if (y >= screen->page->height)
208                 return (screen->page->height > 0) ? screen->page->height - 1 : 0;
209
210         return y;
211 }
212
213 static bool screen_tab_is_set(term_screen *screen, unsigned int pos) {
214         if (pos >= screen->page->width)
215                 return false;
216
217         return screen->tabs[pos / 8] & (1 << (pos % 8));
218 }
219
220 static inline void screen_age_cursor(term_screen *screen) {
221         term_cell *cell;
222
223         cell = term_page_get_cell(screen->page, screen->state.cursor_x, screen->state.cursor_y);
224         if (cell)
225                 cell->age = screen->age;
226 }
227
228 static void screen_cursor_clear_wrap(term_screen *screen) {
229         screen->flags &= ~TERM_FLAG_PENDING_WRAP;
230 }
231
232 static void screen_cursor_set(term_screen *screen, unsigned int x, unsigned int y) {
233         x = screen_clamp_x(screen, x);
234         y = screen_clamp_y(screen, y);
235
236         if (x == screen->state.cursor_x && y == screen->state.cursor_y)
237                 return;
238
239         if (!(screen->flags & TERM_FLAG_HIDE_CURSOR))
240                 screen_age_cursor(screen);
241
242         screen->state.cursor_x = x;
243         screen->state.cursor_y = y;
244
245         if (!(screen->flags & TERM_FLAG_HIDE_CURSOR))
246                 screen_age_cursor(screen);
247 }
248
249 static void screen_cursor_set_rel(term_screen *screen, unsigned int x, unsigned int y) {
250         if (screen->state.origin_mode) {
251                 x = screen_clamp_x(screen, x);
252                 y = screen_clamp_x(screen, y) + screen->page->scroll_idx;
253
254                 if (y >= screen->page->scroll_idx + screen->page->scroll_num) {
255                         y = screen->page->scroll_idx + screen->page->scroll_num;
256                         if (screen->page->scroll_num > 0)
257                                 y -= 1;
258                 }
259         }
260
261         screen_cursor_set(screen, x, y);
262 }
263
264 static void screen_cursor_left(term_screen *screen, unsigned int num) {
265         if (num > screen->state.cursor_x)
266                 num = screen->state.cursor_x;
267
268         screen_cursor_set(screen, screen->state.cursor_x - num, screen->state.cursor_y);
269 }
270
271 static void screen_cursor_left_tab(term_screen *screen, unsigned int num) {
272         unsigned int i;
273
274         i = screen->state.cursor_x;
275         while (i > 0 && num > 0) {
276                 if (screen_tab_is_set(screen, --i))
277                         --num;
278         }
279
280         screen_cursor_set(screen, i, screen->state.cursor_y);
281 }
282
283 static void screen_cursor_right(term_screen *screen, unsigned int num) {
284         if (num > screen->page->width)
285                 num = screen->page->width;
286
287         screen_cursor_set(screen, screen->state.cursor_x + num, screen->state.cursor_y);
288 }
289
290 static void screen_cursor_right_tab(term_screen *screen, unsigned int num) {
291         unsigned int i;
292
293         i = screen->state.cursor_x;
294         while (i + 1 < screen->page->width && num > 0) {
295                 if (screen_tab_is_set(screen, ++i))
296                         --num;
297         }
298
299         screen_cursor_set(screen, i, screen->state.cursor_y);
300 }
301
302 static void screen_cursor_up(term_screen *screen, unsigned int num, bool scroll) {
303         unsigned int max;
304
305         if (screen->state.cursor_y < screen->page->scroll_idx) {
306                 if (num > screen->state.cursor_y)
307                         num = screen->state.cursor_y;
308
309                 screen_cursor_set(screen, screen->state.cursor_x, screen->state.cursor_y - num);
310         } else {
311                 max = screen->state.cursor_y - screen->page->scroll_idx;
312                 if (num > max) {
313                         if (num < 1)
314                                 return;
315
316                         if (!(screen->flags & TERM_FLAG_HIDE_CURSOR))
317                                 screen_age_cursor(screen);
318
319                         if (scroll)
320                                 term_page_scroll_down(screen->page, num - max, &screen->state.attr, screen->age, NULL);
321
322                         screen->state.cursor_y = screen->page->scroll_idx;
323
324                         if (!(screen->flags & TERM_FLAG_HIDE_CURSOR))
325                                 screen_age_cursor(screen);
326                 } else {
327                         screen_cursor_set(screen, screen->state.cursor_x, screen->state.cursor_y - num);
328                 }
329         }
330 }
331
332 static void screen_cursor_down(term_screen *screen, unsigned int num, bool scroll) {
333         unsigned int max;
334
335         if (screen->state.cursor_y >= screen->page->scroll_idx + screen->page->scroll_num) {
336                 if (num > screen->page->height)
337                         num = screen->page->height;
338
339                 screen_cursor_set(screen, screen->state.cursor_x, screen->state.cursor_y - num);
340         } else {
341                 max = screen->page->scroll_idx + screen->page->scroll_num - 1 - screen->state.cursor_y;
342                 if (num > max) {
343                         if (num < 1)
344                                 return;
345
346                         if (!(screen->flags & TERM_FLAG_HIDE_CURSOR))
347                                 screen_age_cursor(screen);
348
349                         if (scroll)
350                                 term_page_scroll_up(screen->page, num - max, &screen->state.attr, screen->age, screen->history);
351
352                         screen->state.cursor_y = screen->page->scroll_idx + screen->page->scroll_num - 1;
353
354                         if (!(screen->flags & TERM_FLAG_HIDE_CURSOR))
355                                 screen_age_cursor(screen);
356                 } else {
357                         screen_cursor_set(screen, screen->state.cursor_x, screen->state.cursor_y + num);
358                 }
359         }
360 }
361
362 static void screen_save_state(term_screen *screen, term_state *where) {
363         *where = screen->state;
364 }
365
366 static void screen_restore_state(term_screen *screen, term_state *from) {
367         screen_cursor_set(screen, from->cursor_x, from->cursor_y);
368         screen->state = *from;
369 }
370
371 static void screen_reset_page(term_screen *screen, term_page *page) {
372         term_page_set_scroll_region(page, 0, page->height);
373         term_page_erase(page, 0, 0, page->width, page->height, &screen->state.attr, screen->age, false);
374 }
375
376 static void screen_change_alt(term_screen *screen, bool set) {
377         if (set) {
378                 screen->page = screen->page_alt;
379                 screen->history = NULL;
380         } else {
381                 screen->page = screen->page_main;
382                 screen->history = screen->history_main;
383         }
384
385         screen->page->age = screen->age;
386 }
387
388 static inline void set_reset(term_screen *screen, unsigned int flag, bool set) {
389         if (set)
390                 screen->flags |= flag;
391         else
392                 screen->flags &= ~flag;
393 }
394
395 static void screen_mode_change_ansi(term_screen *screen, unsigned mode, bool set) {
396         switch (mode) {
397         case 20:
398                 /*
399                  * LNM: line-feed/new-line mode
400                  * TODO
401                  */
402                 set_reset(screen, TERM_FLAG_NEWLINE_MODE, set);
403
404                 break;
405         default:
406                 log_debug("terminal: failed to %s unknown ANSI mode %u", set ? "set" : "unset", mode);
407         }
408 }
409
410 static void screen_mode_change_dec(term_screen *screen, unsigned int mode, bool set) {
411         switch (mode) {
412         case 1:
413                 /*
414                  * DECCKM: cursor-keys
415                  * TODO
416                  */
417                 set_reset(screen, TERM_FLAG_CURSOR_KEYS, set);
418
419                 break;
420         case 6:
421                 /*
422                  * DECOM: origin-mode
423                  * TODO
424                  */
425                 screen->state.origin_mode = set;
426
427                 break;
428         case 7:
429                 /*
430                  * DECAWN: auto-wrap mode
431                  * TODO
432                  */
433                 screen->state.auto_wrap = set;
434
435                 break;
436         case 25:
437                 /*
438                  * DECTCEM: text-cursor-enable
439                  * TODO
440                  */
441                 set_reset(screen, TERM_FLAG_HIDE_CURSOR, !set);
442                 screen_age_cursor(screen);
443
444                 break;
445         case 47:
446                 /*
447                  * XTERM-ASB: alternate-screen-buffer
448                  * This enables/disables the alternate screen-buffer.
449                  * It effectively saves the current page content and
450                  * allows you to restore it when changing to the
451                  * original screen-buffer again.
452                  */
453                 screen_change_alt(screen, set);
454
455                 break;
456         case 1047:
457                 /*
458                  * XTERM-ASBPE: alternate-screen-buffer-post-erase
459                  * This is the same as XTERM-ASB but erases the
460                  * alternate screen-buffer before switching back to the
461                  * original buffer. Use it to discard any data on the
462                  * alternate screen buffer when done.
463                  */
464                 if (!set)
465                         screen_reset_page(screen, screen->page_alt);
466
467                 screen_change_alt(screen, set);
468
469                 break;
470         case 1048:
471                 /*
472                  * XTERM-ASBCS: alternate-screen-buffer-cursor-state
473                  * This has the same effect as DECSC/DECRC, but uses a
474                  * separate state buffer. It is usually used in
475                  * combination with alternate screen buffers to provide
476                  * stacked state storage.
477                  */
478                 if (set)
479                         screen_save_state(screen, &screen->saved_alt);
480                 else
481                         screen_restore_state(screen, &screen->saved_alt);
482
483                 break;
484         case 1049:
485                 /*
486                  * XTERM-ASBX: alternate-screen-buffer-extended
487                  * This combines XTERM-ASBPE and XTERM-ASBCS somewhat.
488                  * When enabling, state is saved, alternate screen
489                  * buffer is activated and cleared.
490                  * When disabled, alternate screen buffer is cleared,
491                  * then normal screen buffer is enabled and state is
492                  * restored.
493                  */
494                 if (set)
495                         screen_save_state(screen, &screen->saved_alt);
496
497                 screen_reset_page(screen, screen->page_alt);
498                 screen_change_alt(screen, set);
499
500                 if (!set)
501                         screen_restore_state(screen, &screen->saved_alt);
502
503                 break;
504         default:
505                 log_debug("terminal: failed to %s unknown DEC mode %u", set ? "set" : "unset", mode);
506         }
507 }
508
509 /* map a character according to current GL and GR maps */
510 static uint32_t screen_map(term_screen *screen, uint32_t val) {
511         uint32_t nval = -1U;
512
513         /* 32 and 127 always map to identity. 160 and 255 map to identity iff a
514          * 96 character set is loaded into GR. Values above 255 always map to
515          * identity. */
516         switch (val) {
517         case 33 ... 126:
518                 if (screen->state.glt) {
519                         nval = (**screen->state.glt)[val - 32];
520                         screen->state.glt = NULL;
521                 } else {
522                         nval = (**screen->state.gl)[val - 32];
523                 }
524                 break;
525         case 160 ... 255:
526                 if (screen->state.grt) {
527                         nval = (**screen->state.grt)[val - 160];
528                         screen->state.grt = NULL;
529                 } else {
530                         nval = (**screen->state.gr)[val - 160];
531                 }
532                 break;
533         }
534
535         return (nval == -1U) ? val : nval;
536 }
537
538 /*
539  * Command Handlers
540  * This is the unofficial documentation of all the TERM_CMD_* definitions. Each
541  * handled command has a separate function with an extensive comment on the
542  * semantics of the command.
543  * Note that many semantics are unknown and need to be verified. This is mostly
544  * about error-handling, though. Applications rarely rely on those features.
545  */
546
547 static int screen_DA1(term_screen *screen, const term_seq *seq);
548 static int screen_LF(term_screen *screen, const term_seq *seq);
549
550 static int screen_GRAPHIC(term_screen *screen, const term_seq *seq) {
551         term_char_t ch = TERM_CHAR_NULL;
552         uint32_t c;
553
554         if (screen->state.cursor_x + 1 == screen->page->width
555             && screen->flags & TERM_FLAG_PENDING_WRAP
556             && screen->state.auto_wrap) {
557                 screen_cursor_down(screen, 1, true);
558                 screen_cursor_set(screen, 0, screen->state.cursor_y);
559         }
560
561         screen_cursor_clear_wrap(screen);
562
563         c = screen_map(screen, seq->terminator);
564         ch = term_char_merge(ch, screen_map(screen, c));
565         term_page_write(screen->page, screen->state.cursor_x, screen->state.cursor_y, ch, 1, &screen->state.attr, screen->age, false);
566
567         if (screen->state.cursor_x + 1 == screen->page->width)
568                 screen->flags |= TERM_FLAG_PENDING_WRAP;
569         else
570                 screen_cursor_right(screen, 1);
571
572         return 0;
573 }
574
575 static int screen_BEL(term_screen *screen, const term_seq *seq) {
576         /*
577          * BEL - sound bell tone
578          * This command should trigger an acoustic bell. Usually, this is
579          * forwarded directly to the pcspkr. However, bells have become quite
580          * uncommon and annoying, so we're not implementing them here. Instead,
581          * it's one of the commands we forward to the caller.
582          */
583
584         return screen_forward(screen, TERM_CMD_BEL, seq);
585 }
586
587 static int screen_BS(term_screen *screen, const term_seq *seq) {
588         /*
589          * BS - backspace
590          * Move cursor one cell to the left. If already at the left margin,
591          * nothing happens.
592          */
593
594         screen_cursor_clear_wrap(screen);
595         screen_cursor_left(screen, 1);
596         return 0;
597 }
598
599 static int screen_CBT(term_screen *screen, const term_seq *seq) {
600         /*
601          * CBT - cursor-backward-tabulation
602          * Move the cursor @args[0] tabs backwards (to the left). The
603          * current cursor cell, in case it's a tab, is not counted.
604          * Furthermore, the cursor cannot be moved beyond position 0 and
605          * it will stop there.
606          *
607          * Defaults:
608          *   args[0]: 1
609          */
610
611         unsigned int num = 1;
612
613         if (seq->args[0] > 0)
614                 num = seq->args[0];
615
616         screen_cursor_clear_wrap(screen);
617         screen_cursor_left_tab(screen, num);
618
619         return 0;
620 }
621
622 static int screen_CHA(term_screen *screen, const term_seq *seq) {
623         /*
624          * CHA - cursor-horizontal-absolute
625          * Move the cursor to position @args[0] in the current line. The
626          * cursor cannot be moved beyond the rightmost cell and will stop
627          * there.
628          *
629          * Defaults:
630          *   args[0]: 1
631          */
632
633         unsigned int pos = 1;
634
635         if (seq->args[0] > 0)
636                 pos = seq->args[0];
637
638         screen_cursor_clear_wrap(screen);
639         screen_cursor_set(screen, pos - 1, screen->state.cursor_y);
640
641         return 0;
642 }
643
644 static int screen_CHT(term_screen *screen, const term_seq *seq) {
645         /*
646          * CHT - cursor-horizontal-forward-tabulation
647          * Move the cursor @args[0] tabs forward (to the right). The
648          * current cursor cell, in case it's a tab, is not counted.
649          * Furthermore, the cursor cannot be moved beyond the rightmost cell
650          * and will stop there.
651          *
652          * Defaults:
653          *   args[0]: 1
654          */
655
656         unsigned int num = 1;
657
658         if (seq->args[0] > 0)
659                 num = seq->args[0];
660
661         screen_cursor_clear_wrap(screen);
662         screen_cursor_right_tab(screen, num);
663
664         return 0;
665 }
666
667 static int screen_CNL(term_screen *screen, const term_seq *seq) {
668         /*
669          * CNL - cursor-next-line
670          * Move the cursor @args[0] lines down.
671          *
672          * TODO: Does this stop at the bottom or cause a scroll-up?
673          *
674          * Defaults:
675          *   args[0]: 1
676          */
677
678         unsigned int num = 1;
679
680         if (seq->args[0] > 0)
681                 num = seq->args[0];
682
683         screen_cursor_clear_wrap(screen);
684         screen_cursor_down(screen, num, false);
685
686         return 0;
687 }
688
689 static int screen_CPL(term_screen *screen, const term_seq *seq) {
690         /*
691          * CPL - cursor-preceding-line
692          * Move the cursor @args[0] lines up.
693          *
694          * TODO: Does this stop at the top or cause a scroll-up?
695          *
696          * Defaults:
697          *   args[0]: 1
698          */
699
700         unsigned int num = 1;
701
702         if (seq->args[0] > 0)
703                 num = seq->args[0];
704
705         screen_cursor_clear_wrap(screen);
706         screen_cursor_up(screen, num, false);
707
708         return 0;
709 }
710
711 static int screen_CR(term_screen *screen, const term_seq *seq) {
712         /*
713          * CR - carriage-return
714          * Move the cursor to the left margin on the current line.
715          */
716
717         screen_cursor_clear_wrap(screen);
718         screen_cursor_set(screen, 0, screen->state.cursor_y);
719
720         return 0;
721 }
722
723 static int screen_CUB(term_screen *screen, const term_seq *seq) {
724         /*
725          * CUB - cursor-backward
726          * Move the cursor @args[0] positions to the left. The cursor stops
727          * at the left-most position.
728          *
729          * Defaults:
730          *   args[0]: 1
731          */
732
733         unsigned int num = 1;
734
735         if (seq->args[0] > 0)
736                 num = seq->args[0];
737
738         screen_cursor_clear_wrap(screen);
739         screen_cursor_left(screen, num);
740
741         return 0;
742 }
743
744 static int screen_CUD(term_screen *screen, const term_seq *seq) {
745         /*
746          * CUD - cursor-down
747          * Move the cursor @args[0] positions down. The cursor stops at the
748          * bottom margin. If it was already moved further, it stops at the
749          * bottom line.
750          *
751          * Defaults:
752          *   args[0]: 1
753          */
754
755         unsigned int num = 1;
756
757         if (seq->args[0] > 0)
758                 num = seq->args[0];
759
760         screen_cursor_clear_wrap(screen);
761         screen_cursor_down(screen, num, false);
762
763         return 0;
764 }
765
766 static int screen_CUF(term_screen *screen, const term_seq *seq) {
767         /*
768          * CUF -cursor-forward
769          * Move the cursor @args[0] positions to the right. The cursor stops
770          * at the right-most position.
771          *
772          * Defaults:
773          *   args[0]: 1
774          */
775
776         unsigned int num = 1;
777
778         if (seq->args[0] > 0)
779                 num = seq->args[0];
780
781         screen_cursor_clear_wrap(screen);
782         screen_cursor_right(screen, num);
783
784         return 0;
785 }
786
787 static int screen_CUP(term_screen *screen, const term_seq *seq) {
788         /*
789          * CUP - cursor-position
790          * Moves the cursor to position @args[1] x @args[0]. If either is 0, it
791          * is treated as 1. The positions are subject to the origin-mode and
792          * clamped to the addressable with/height.
793          *
794          * Defaults:
795          *   args[0]: 1
796          *   args[1]: 1
797          */
798
799         unsigned int x = 1, y = 1;
800
801         if (seq->args[0] > 0)
802                 y = seq->args[0];
803         if (seq->args[1] > 0)
804                 x = seq->args[1];
805
806         screen_cursor_clear_wrap(screen);
807         screen_cursor_set_rel(screen, x - 1, y - 1);
808
809         return 0;
810 }
811
812 static int screen_CUU(term_screen *screen, const term_seq *seq) {
813         /*
814          * CUU - cursor-up
815          * Move the cursor @args[0] positions up. The cursor stops at the
816          * top margin. If it was already moved further, it stops at the
817          * top line.
818          *
819          * Defaults:
820          *   args[0]: 1
821          *
822          */
823
824         unsigned int num = 1;
825
826         if (seq->args[0] > 0)
827                 num = seq->args[0];
828
829         screen_cursor_clear_wrap(screen);
830         screen_cursor_up(screen, num, false);
831
832         return 0;
833 }
834
835 static int screen_DA1(term_screen *screen, const term_seq *seq) {
836         /*
837          * DA1 - primary-device-attributes
838          * The primary DA asks for basic terminal features. We simply return
839          * a hard-coded list of features we implement.
840          * Note that the primary DA asks for supported features, not currently
841          * enabled features.
842          *
843          * The terminal's answer is:
844          *   ^[ ? 64 ; ARGS c
845          * The first argument, 64, is fixed and denotes a VT420, the last
846          * DEC-term that extended this number.
847          * All following arguments denote supported features. Note
848          * that at most 15 features can be sent (max CSI args). It is safe to
849          * send more, but clients might not be able to parse them. This is a
850          * client's problem and we shouldn't care. There is no other way to
851          * send those feature lists, so we have to extend them beyond 15 in
852          * those cases.
853          *
854          * Known modes:
855          *    1: 132 column mode
856          *       The 132 column mode is supported by the terminal.
857          *    2: printer port
858          *       A priner-port is supported and can be addressed via
859          *       control-codes.
860          *    3: ReGIS graphics
861          *       Support for ReGIS graphics is available. The ReGIS routines
862          *       provide the "remote graphics instruction set" and allow basic
863          *       vector-rendering.
864          *    4: sixel
865          *       Support of Sixel graphics is available. This provides access
866          *       to the sixel bitmap routines.
867          *    6: selective erase
868          *       The terminal supports DECSCA and related selective-erase
869          *       functions. This allows to protect specific cells from being
870          *       erased, if specified.
871          *    7: soft character set (DRCS)
872          *       TODO: ?
873          *    8: user-defined keys (UDKs)
874          *       TODO: ?
875          *    9: national-replacement character sets (NRCS)
876          *       National-replacement character-sets are available.
877          *   12: Yugoslavian (SCS)
878          *       TODO: ?
879          *   15: technical character set
880          *       The DEC technical-character-set is available.
881          *   18: windowing capability
882          *       TODO: ?
883          *   21: horizontal scrolling
884          *       TODO: ?
885          *   22: ANSII color
886          *       TODO: ?
887          *   23: Greek
888          *       TODO: ?
889          *   24: Turkish
890          *       TODO: ?
891          *   29: ANSI text locator
892          *       TODO: ?
893          *   42: ISO Latin-2 character set
894          *       TODO: ?
895          *   44: PCTerm
896          *       TODO: ?
897          *   45: soft keymap
898          *       TODO: ?
899          *   46: ASCII emulation
900          *       TODO: ?
901          */
902
903         return SEQ_WRITE(screen, C0_CSI, C1_CSI, "?64;1;6;9;15c");
904 }
905
906 static int screen_DA2(term_screen *screen, const term_seq *seq) {
907         /*
908          * DA2 - secondary-device-attributes
909          * The secondary DA asks for the terminal-ID, firmware versions and
910          * other non-primary attributes. All these values are
911          * informational-only and should not be used by the host to detect
912          * terminal features.
913          *
914          * The terminal's response is:
915          *   ^[ > 61 ; FIRMWARE ; KEYBOARD c
916          * whereas 65 is fixed for VT525 terminals, the last terminal-line that
917          * increased this number. FIRMWARE is the firmware
918          * version encoded as major/minor (20 == 2.0) and KEYBOARD is 0 for STD
919          * keyboard and 1 for PC keyboards.
920          *
921          * We replace the firmware-version with the systemd-version so clients
922          * can decode it again.
923          */
924
925         return SEQ_WRITE(screen, C0_CSI, C1_CSI, ">65;" PACKAGE_VERSION ";1c");
926 }
927
928 static int screen_DA3(term_screen *screen, const term_seq *seq) {
929         /*
930          * DA3 - tertiary-device-attributes
931          * The tertiary DA is used to query the terminal-ID.
932          *
933          * The terminal's response is:
934          *   ^P ! | XX AA BB CC ^\
935          * whereas all four parameters are hexadecimal-encoded pairs. XX
936          * denotes the manufacturing site, AA BB CC is the terminal's ID.
937          */
938
939         /* we do not support tertiary DAs */
940         return 0;
941 }
942
943 static int screen_DC1(term_screen *screen, const term_seq *seq) {
944         /*
945          * DC1 - device-control-1 or XON
946          * This clears any previous XOFF and resumes terminal-transmission.
947          */
948
949         /* we do not support XON */
950         return 0;
951 }
952
953 static int screen_DC3(term_screen *screen, const term_seq *seq) {
954         /*
955          * DC3 - device-control-3 or XOFF
956          * Stops terminal transmission. No further characters are sent until
957          * an XON is received.
958          */
959
960         /* we do not support XOFF */
961         return 0;
962 }
963
964 static int screen_DCH(term_screen *screen, const term_seq *seq) {
965         /*
966          * DCH - delete-character
967          * This deletes @argv[0] characters at the current cursor position. As
968          * characters are deleted, the remaining characters between the cursor
969          * and right margin move to the left. Character attributes move with the
970          * characters. The terminal adds blank spaces with no visual character
971          * attributes at the right margin. DCH has no effect outside the
972          * scrolling margins.
973          *
974          * Defaults:
975          *   args[0]: 1
976          */
977
978         unsigned int num = 1;
979
980         if (seq->args[0] > 0)
981                 num = seq->args[0];
982
983         screen_cursor_clear_wrap(screen);
984         term_page_delete_cells(screen->page, screen->state.cursor_x, screen->state.cursor_y, num, &screen->state.attr, screen->age);
985
986         return 0;
987 }
988
989 static int screen_DECALN(term_screen *screen, const term_seq *seq) {
990         /*
991          * DECALN - screen-alignment-pattern
992          *
993          * Probably not worth implementing.
994          */
995
996         return 0;
997 }
998
999 static int screen_DECANM(term_screen *screen, const term_seq *seq) {
1000         /*
1001          * DECANM - ansi-mode
1002          * Set the terminal into VT52 compatibility mode. Control sequences
1003          * overlap with regular sequences so we have to detect them early before
1004          * dispatching them.
1005          *
1006          * Probably not worth implementing.
1007          */
1008
1009         return 0;
1010 }
1011
1012 static int screen_DECBI(term_screen *screen, const term_seq *seq) {
1013         /*
1014          * DECBI - back-index
1015          * This control function moves the cursor backward one column. If the
1016          * cursor is at the left margin, then all screen data within the margin
1017          * moves one column to the right. The column that shifted past the right
1018          * margin is lost.
1019          * DECBI adds a new column at the left margin with no visual attributes.
1020          * DECBI does not affect the margins. If the cursor is beyond the
1021          * left-margin at the left border, then the terminal ignores DECBI.
1022          *
1023          * Probably not worth implementing.
1024          */
1025
1026         return 0;
1027 }
1028
1029 static int screen_DECCARA(term_screen *screen, const term_seq *seq) {
1030         /*
1031          * DECCARA - change-attributes-in-rectangular-area
1032          *
1033          * Probably not worth implementing.
1034          */
1035
1036         return 0;
1037 }
1038
1039 static int screen_DECCRA(term_screen *screen, const term_seq *seq) {
1040         /*
1041          * DECCRA - copy-rectangular-area
1042          *
1043          * Probably not worth implementing.
1044          */
1045
1046         return 0;
1047 }
1048
1049 static int screen_DECDC(term_screen *screen, const term_seq *seq) {
1050         /*
1051          * DECDC - delete-column
1052          *
1053          * Probably not worth implementing.
1054          */
1055
1056         return 0;
1057 }
1058
1059 static int screen_DECDHL_BH(term_screen *screen, const term_seq *seq) {
1060         /*
1061          * DECDHL_BH - double-width-double-height-line: bottom half
1062          *
1063          * Probably not worth implementing.
1064          */
1065
1066         return 0;
1067 }
1068
1069 static int screen_DECDHL_TH(term_screen *screen, const term_seq *seq) {
1070         /*
1071          * DECDHL_TH - double-width-double-height-line: top half
1072          *
1073          * Probably not worth implementing.
1074          */
1075
1076         return 0;
1077 }
1078
1079 static int screen_DECDWL(term_screen *screen, const term_seq *seq) {
1080         /*
1081          * DECDWL - double-width-single-height-line
1082          *
1083          * Probably not worth implementing.
1084          */
1085
1086         return 0;
1087 }
1088
1089 static int screen_DECEFR(term_screen *screen, const term_seq *seq) {
1090         /*
1091          * DECEFR - enable-filter-rectangle
1092          * Defines the coordinates of a filter rectangle (top, left, bottom,
1093          * right as @args[0] to @args[3]) and activates it.
1094          * Anytime the locator is detected outside of the filter rectangle, an
1095          * outside rectangle event is generated and the rectangle is disabled.
1096          * Filter rectangles are always treated as "one-shot" events. Any
1097          * parameters that are omitted default to the current locator position.
1098          * If all parameters are omitted, any locator motion will be reported.
1099          * DECELR always cancels any prevous rectangle definition.
1100          *
1101          * The locator is usually associated with the mouse-cursor, but based
1102          * on cells instead of pixels. See DECELR how to initialize and enable
1103          * it. DECELR can also enable pixel-mode instead of cell-mode.
1104          *
1105          * TODO: implement
1106          */
1107
1108         return 0;
1109 }
1110
1111 static int screen_DECELF(term_screen *screen, const term_seq *seq) {
1112         /*
1113          * DECELF - enable-local-functions
1114          *
1115          * Probably not worth implementing.
1116          */
1117
1118         return 0;
1119 }
1120
1121 static int screen_DECELR(term_screen *screen, const term_seq *seq) {
1122         /*
1123          * DECELR - enable-locator-reporting
1124          * This changes the locator-reporting mode. @args[0] specifies the mode
1125          * to set, 0 disables locator-reporting, 1 enables it continuously, 2
1126          * enables it for a single report. @args[1] specifies the
1127          * precision-mode. 0 and 2 set the reporting to cell-precision, 1 sets
1128          * pixel-precision.
1129          *
1130          * Defaults:
1131          *   args[0]: 0
1132          *   args[1]: 0
1133          *
1134          * TODO: implement
1135          */
1136
1137         return 0;
1138 }
1139
1140 static int screen_DECERA(term_screen *screen, const term_seq *seq) {
1141         /*
1142          * DECERA - erase-rectangular-area
1143          *
1144          * Probably not worth implementing.
1145          */
1146
1147         return 0;
1148 }
1149
1150 static int screen_DECFI(term_screen *screen, const term_seq *seq) {
1151         /*
1152          * DECFI - forward-index
1153          * This control function moves the cursor forward one column. If the
1154          * cursor is at the right margin, then all screen data within the
1155          * margins moves one column to the left. The column shifted past the
1156          * left margin is lost.
1157          * DECFI adds a new column at the right margin, with no visual
1158          * attributes. DECFI does not affect margins. If the cursor is beyond
1159          * the right margin at the border of the page when the terminal
1160          * receives DECFI, then the terminal ignores DECFI.
1161          *
1162          * Probably not worth implementing.
1163          */
1164
1165         return 0;
1166 }
1167
1168 static int screen_DECFRA(term_screen *screen, const term_seq *seq) {
1169         /*
1170          * DECFRA - fill-rectangular-area
1171          *
1172          * Probably not worth implementing.
1173          */
1174
1175         return 0;
1176 }
1177
1178 static int screen_DECIC(term_screen *screen, const term_seq *seq) {
1179         /*
1180          * DECIC - insert-column
1181          *
1182          * Probably not worth implementing.
1183          */
1184
1185         return 0;
1186 }
1187
1188 static int screen_DECID(term_screen *screen, const term_seq *seq) {
1189         /*
1190          * DECID - return-terminal-id
1191          * This is an obsolete form of TERM_CMD_DA1.
1192          */
1193
1194         return screen_DA1(screen, seq);
1195 }
1196
1197 static int screen_DECINVM(term_screen *screen, const term_seq *seq) {
1198         /*
1199          * DECINVM - invoke-macro
1200          *
1201          * Probably not worth implementing.
1202          */
1203
1204         return 0;
1205 }
1206
1207 static int screen_DECKBD(term_screen *screen, const term_seq *seq) {
1208         /*
1209          * DECKBD - keyboard-language-selection
1210          *
1211          * Probably not worth implementing.
1212          */
1213
1214         return 0;
1215 }
1216
1217 static int screen_DECKPAM(term_screen *screen, const term_seq *seq) {
1218         /*
1219          * DECKPAM - keypad-application-mode
1220          * Enables the keypad-application mode. If enabled, the keypad sends
1221          * special characters instead of the printed characters. This way,
1222          * applications can detect whether a numeric key was pressed on the
1223          * top-row or on the keypad.
1224          * Default is keypad-numeric-mode.
1225          */
1226
1227         screen->flags |= TERM_FLAG_KEYPAD_MODE;
1228
1229         return 0;
1230 }
1231
1232 static int screen_DECKPNM(term_screen *screen, const term_seq *seq) {
1233         /*
1234          * DECKPNM - keypad-numeric-mode
1235          * This disables the keypad-application-mode (DECKPAM) and returns to
1236          * the keypad-numeric-mode. Keypresses on the keypad generate the same
1237          * sequences as corresponding keypresses on the main keyboard.
1238          * Default is keypad-numeric-mode.
1239          */
1240
1241         screen->flags &= ~TERM_FLAG_KEYPAD_MODE;
1242
1243         return 0;
1244 }
1245
1246 static int screen_DECLFKC(term_screen *screen, const term_seq *seq) {
1247         /*
1248          * DECLFKC - local-function-key-control
1249          *
1250          * Probably not worth implementing.
1251          */
1252
1253         return 0;
1254 }
1255
1256 static int screen_DECLL(term_screen *screen, const term_seq *seq) {
1257         /*
1258          * DECLL - load-leds
1259          *
1260          * Probably not worth implementing.
1261          */
1262
1263         return 0;
1264 }
1265
1266 static int screen_DECLTOD(term_screen *screen, const term_seq *seq) {
1267         /*
1268          * DECLTOD - load-time-of-day
1269          *
1270          * Probably not worth implementing.
1271          */
1272
1273         return 0;
1274 }
1275
1276 static int screen_DECPCTERM(term_screen *screen, const term_seq *seq) {
1277         /*
1278          * DECPCTERM - pcterm-mode
1279          * This enters/exits the PCTerm mode. Default mode is VT-mode. It can
1280          * also select parameters for scancode/keycode mappings in SCO mode.
1281          *
1282          * Definitely not worth implementing. Lets kill PCTerm/SCO modes!
1283          */
1284
1285         return 0;
1286 }
1287
1288 static int screen_DECPKA(term_screen *screen, const term_seq *seq) {
1289         /*
1290          * DECPKA - program-key-action
1291          *
1292          * Probably not worth implementing.
1293          */
1294
1295         return 0;
1296 }
1297
1298 static int screen_DECPKFMR(term_screen *screen, const term_seq *seq) {
1299         /*
1300          * DECPKFMR - program-key-free-memory-report
1301          *
1302          * Probably not worth implementing.
1303          */
1304
1305         return 0;
1306 }
1307
1308 static int screen_DECRARA(term_screen *screen, const term_seq *seq) {
1309         /*
1310          * DECRARA - reverse-attributes-in-rectangular-area
1311          *
1312          * Probably not worth implementing.
1313          */
1314
1315         return 0;
1316 }
1317
1318 static int screen_DECRC(term_screen *screen, const term_seq *seq) {
1319         /*
1320          * DECRC - restore-cursor
1321          * Restores the terminal to the state saved by the save cursor (DECSC)
1322          * function. This includes more than just the cursor-position.
1323          *
1324          * If nothing was saved by DECSC, then DECRC performs the following
1325          * actions:
1326          *   * Moves the cursor to the home position (upper left of screen).
1327          *   * Resets origin mode (DECOM).
1328          *   * Turns all character attributes off (normal setting).
1329          *   * Maps the ASCII character set into GL, and the DEC Supplemental
1330          *     Graphic set into GR.
1331          *
1332          * The terminal maintains a separate DECSC buffer for the main display
1333          * and the status line. This feature lets you save a separate operating
1334          * state for the main display and the status line.
1335          */
1336
1337         screen_restore_state(screen, &screen->saved);
1338
1339         return 0;
1340 }
1341
1342 static int screen_DECREQTPARM(term_screen *screen, const term_seq *seq) {
1343         /*
1344          * DECREQTPARM - request-terminal-parameters
1345          * The sequence DECREPTPARM is sent by the terminal controller to notify
1346          * the host of the status of selected terminal parameters. The status
1347          * sequence may be sent when requested by the host or at the terminal's
1348          * discretion. DECREPTPARM is sent upon receipt of a DECREQTPARM.
1349          *
1350          * If @args[0] is 0, this marks a request and the terminal is allowed
1351          * to send DECREPTPARM messages without request. If it is 1, the same
1352          * applies but the terminal should no longer send DECREPTPARM
1353          * unrequested.
1354          * 2 and 3 mark a report, but 3 is only used if the terminal answers as
1355          * an explicit request with @args[0] == 1.
1356          *
1357          * The other arguments are ignored in requests, but have the following
1358          * meaning in responses:
1359          *   args[1]: 1=no-parity-set 4=parity-set-and-odd 5=parity-set-and-even
1360          *   args[2]: 1=8bits-per-char 2=7bits-per-char
1361          *   args[3]: transmission-speed
1362          *   args[4]: receive-speed
1363          *   args[5]: 1=bit-rate-multiplier-is-16
1364          *   args[6]: This value communicates the four switch values in block 5
1365          *            of SETUP B, which are only visible to the user when an STP
1366          *            option is installed. These bits may be assigned for an STP
1367          *            device. The four bits are a decimal-encoded binary number.
1368          *            Value between 0-15.
1369          *
1370          * The transmission/receive speeds have mappings for number => bits/s
1371          * which are quite weird. Examples are: 96->3600, 112->9600, 120->19200
1372          *
1373          * Defaults:
1374          *   args[0]: 0
1375          */
1376
1377         if (seq->n_args < 1 || seq->args[0] == 0) {
1378                 screen->flags &= ~TERM_FLAG_INHIBIT_TPARM;
1379                 return SEQ_WRITE(screen, C0_CSI, C1_CSI, "2;1;1;120;120;1;0x");
1380         } else if (seq->args[0] == 1) {
1381                 screen->flags |= TERM_FLAG_INHIBIT_TPARM;
1382                 return SEQ_WRITE(screen, C0_CSI, C1_CSI, "3;1;1;120;120;1;0x");
1383         } else {
1384                 return 0;
1385         }
1386 }
1387
1388 static int screen_DECRPKT(term_screen *screen, const term_seq *seq) {
1389         /*
1390          * DECRPKT - report-key-type
1391          * Response to DECRQKT, we can safely ignore it as we're the one sending
1392          * it to the host.
1393          */
1394
1395         return 0;
1396 }
1397
1398 static int screen_DECRQCRA(term_screen *screen, const term_seq *seq) {
1399         /*
1400          * DECRQCRA - request-checksum-of-rectangular-area
1401          *
1402          * Probably not worth implementing.
1403          */
1404
1405         return 0;
1406 }
1407
1408 static int screen_DECRQDE(term_screen *screen, const term_seq *seq) {
1409         /*
1410          * DECRQDE - request-display-extent
1411          *
1412          * Probably not worth implementing.
1413          */
1414
1415         return 0;
1416 }
1417
1418 static int screen_DECRQKT(term_screen *screen, const term_seq *seq) {
1419         /*
1420          * DECRQKT - request-key-type
1421          *
1422          * Probably not worth implementing.
1423          */
1424
1425         return 0;
1426 }
1427
1428 static int screen_DECRQLP(term_screen *screen, const term_seq *seq) {
1429         /*
1430          * DECRQLP - request-locator-position
1431          * See DECELR for locator-information.
1432          *
1433          * TODO: document and implement
1434          */
1435
1436         return 0;
1437 }
1438
1439 static int screen_DECRQM_ANSI(term_screen *screen, const term_seq *seq) {
1440         /*
1441          * DECRQM_ANSI - request-mode-ansi
1442          * The host sends this control function to find out if a particular mode
1443          * is set or reset. The terminal responds with a report mode function.
1444          * @args[0] contains the mode to query.
1445          *
1446          * Response is DECRPM with the first argument set to the mode that was
1447          * queried, second argument is 0 if mode is invalid, 1 if mode is set,
1448          * 2 if mode is not set (reset), 3 if mode is permanently set and 4 if
1449          * mode is permanently not set (reset):
1450          *   ANSI: ^[ MODE ; VALUE $ y
1451          *   DEC:  ^[ ? MODE ; VALUE $ y
1452          *
1453          * TODO: implement
1454          */
1455
1456         return 0;
1457 }
1458
1459 static int screen_DECRQM_DEC(term_screen *screen, const term_seq *seq) {
1460         /*
1461          * DECRQM_DEC - request-mode-dec
1462          * Same as DECRQM_ANSI but for DEC modes.
1463          *
1464          * TODO: implement
1465          */
1466
1467         return 0;
1468 }
1469
1470 static int screen_DECRQPKFM(term_screen *screen, const term_seq *seq) {
1471         /*
1472          * DECRQPKFM - request-program-key-free-memory
1473          *
1474          * Probably not worth implementing.
1475          */
1476
1477         return 0;
1478 }
1479
1480 static int screen_DECRQPSR(term_screen *screen, const term_seq *seq) {
1481         /*
1482          * DECRQPSR - request-presentation-state-report
1483          *
1484          * Probably not worth implementing.
1485          */
1486
1487         return 0;
1488 }
1489
1490 static int screen_DECRQTSR(term_screen *screen, const term_seq *seq) {
1491         /*
1492          * DECRQTSR - request-terminal-state-report
1493          *
1494          * Probably not worth implementing.
1495          */
1496
1497         return 0;
1498 }
1499
1500 static int screen_DECRQUPSS(term_screen *screen, const term_seq *seq) {
1501         /*
1502          * DECRQUPSS - request-user-preferred-supplemental-set
1503          *
1504          * Probably not worth implementing.
1505          */
1506
1507         return 0;
1508 }
1509
1510 static int screen_DECSACE(term_screen *screen, const term_seq *seq) {
1511         /*
1512          * DECSACE - select-attribute-change-extent
1513          *
1514          * Probably not worth implementing.
1515          */
1516
1517         return 0;
1518 }
1519
1520 static int screen_DECSASD(term_screen *screen, const term_seq *seq) {
1521         /*
1522          * DECSASD - select-active-status-display
1523          *
1524          * Probably not worth implementing.
1525          */
1526
1527         return 0;
1528 }
1529
1530 static int screen_DECSC(term_screen *screen, const term_seq *seq) {
1531         /*
1532          * DECSC - save-cursor
1533          * Save cursor and terminal state so it can be restored later on.
1534          * Saves the following items in the terminal's memory:
1535          *   * Cursor position
1536          *   * Character attributes set by the SGR command
1537          *   * Character sets (G0, G1, G2, or G3) currently in GL and GR
1538          *   * Wrap flag (autowrap or no autowrap)
1539          *   * State of origin mode (DECOM)
1540          *   * Selective erase attribute
1541          *   * Any single shift 2 (SS2) or single shift 3 (SS3) functions sent
1542          */
1543
1544         screen_save_state(screen, &screen->saved);
1545
1546         return 0;
1547 }
1548
1549 static int screen_DECSCA(term_screen *screen, const term_seq *seq) {
1550         /*
1551          * DECSCA - select-character-protection-attribute
1552          * Defines the characters that come after it as erasable or not erasable
1553          * from the screen. The selective erase control functions (DECSED and
1554          * DECSEL) can only erase characters defined as erasable.
1555          *
1556          * @args[0] specifies the new mode. 0 and 2 mark any following character
1557          * as erasable, 1 marks it as not erasable.
1558          *
1559          * Defaults:
1560          *   args[0]: 0
1561          */
1562
1563         unsigned int mode = 0;
1564
1565         if (seq->args[0] > 0)
1566                 mode = seq->args[0];
1567
1568         switch (mode) {
1569         case 0:
1570         case 2:
1571                 screen->state.attr.protect = 0;
1572                 break;
1573         case 1:
1574                 screen->state.attr.protect = 1;
1575                 break;
1576         }
1577
1578         return 0;
1579 }
1580
1581 static int screen_DECSCL(term_screen *screen, const term_seq *seq) {
1582         /*
1583          * DECSCL - select-conformance-level
1584          * Select the terminal's operating level. The factory default is
1585          * level 4 (VT Level 4 mode, 7-bit controls).
1586          * When you change the conformance level, the terminal performs a hard
1587          * reset (RIS).
1588          *
1589          * @args[0] defines the conformance-level, valid values are:
1590          *   61: Level 1 (VT100)
1591          *   62: Level 2 (VT200)
1592          *   63: Level 3 (VT300)
1593          *   64: Level 4 (VT400)
1594          * @args[1] defines the 8bit-mode, valid values are:
1595          *    0: 8-bit controls
1596          *    1: 7-bit controls
1597          *    2: 8-bit controls (same as 0)
1598          *
1599          * If @args[0] is 61, then @args[1] is ignored and 7bit controls are
1600          * enforced.
1601          *
1602          * Defaults:
1603          *   args[0]: 64
1604          *   args[1]: 0
1605          */
1606
1607         unsigned int level = 64, bit = 0;
1608
1609         if (seq->n_args > 0) {
1610                 level = seq->args[0];
1611                 if (seq->n_args > 1)
1612                         bit = seq->args[1];
1613         }
1614
1615         term_screen_hard_reset(screen);
1616
1617         switch (level) {
1618         case 61:
1619                 screen->conformance_level = TERM_CONFORMANCE_LEVEL_VT100;
1620                 screen->flags |= TERM_FLAG_7BIT_MODE;
1621                 break;
1622         case 62 ... 69:
1623                 screen->conformance_level = TERM_CONFORMANCE_LEVEL_VT400;
1624                 if (bit == 1)
1625                         screen->flags |= TERM_FLAG_7BIT_MODE;
1626                 else
1627                         screen->flags &= ~TERM_FLAG_7BIT_MODE;
1628                 break;
1629         }
1630
1631         return 0;
1632 }
1633
1634 static int screen_DECSCP(term_screen *screen, const term_seq *seq) {
1635         /*
1636          * DECSCP - select-communication-port
1637          *
1638          * Probably not worth implementing.
1639          */
1640
1641         return 0;
1642 }
1643
1644 static int screen_DECSCPP(term_screen *screen, const term_seq *seq) {
1645         /*
1646          * DECSCPP - select-columns-per-page
1647          * Select columns per page. The number of rows is unaffected by this.
1648          * @args[0] selectes the number of columns (width), DEC only defines 80
1649          * and 132, but we allow any integer here. 0 is equivalent to 80.
1650          * Page content is *not* cleared and the cursor is left untouched.
1651          * However, if the page is reduced in width and the cursor would be
1652          * outside the visible region, it's set to the right border. Newly added
1653          * cells are cleared. No data is retained outside the visible region.
1654          *
1655          * Defaults:
1656          *   args[0]: 0
1657          *
1658          * TODO: implement
1659          */
1660
1661         return 0;
1662 }
1663
1664 static int screen_DECSCS(term_screen *screen, const term_seq *seq) {
1665         /*
1666          * DECSCS - select-communication-speed
1667          *
1668          * Probably not worth implementing.
1669          */
1670
1671         return 0;
1672 }
1673
1674 static int screen_DECSCUSR(term_screen *screen, const term_seq *seq) {
1675         /*
1676          * DECSCUSR - set-cursor-style
1677          * This changes the style of the cursor. @args[0] can be one of:
1678          *   0, 1: blinking block
1679          *      2: steady block
1680          *      3: blinking underline
1681          *      4: steady underline
1682          * Changing this setting does _not_ affect the cursor visibility itself.
1683          * Use DECTCEM for that.
1684          *
1685          * Defaults:
1686          *   args[0]: 0
1687          *
1688          * TODO: implement
1689          */
1690
1691         return 0;
1692 }
1693
1694 static int screen_DECSDDT(term_screen *screen, const term_seq *seq) {
1695         /*
1696          * DECSDDT - select-disconnect-delay-time
1697          *
1698          * Probably not worth implementing.
1699          */
1700
1701         return 0;
1702 }
1703
1704 static int screen_DECSDPT(term_screen *screen, const term_seq *seq) {
1705         /*
1706          * DECSDPT - select-digital-printed-data-type
1707          *
1708          * Probably not worth implementing.
1709          */
1710
1711         return 0;
1712 }
1713
1714 static int screen_DECSED(term_screen *screen, const term_seq *seq) {
1715         /*
1716          * DECSED - selective-erase-in-display
1717          * This control function erases some or all of the erasable characters
1718          * in the display. DECSED can only erase characters defined as erasable
1719          * by the DECSCA control function. DECSED works inside or outside the
1720          * scrolling margins.
1721          *
1722          * @args[0] defines which regions are erased. If it is 0, all cells from
1723          * the cursor (inclusive) till the end of the display are erase. If it
1724          * is 1, all cells from the start of the display till the cursor
1725          * (inclusive) are erased. If it is 2, all cells are erased.
1726          *
1727          * Defaults:
1728          *   args[0]: 0
1729          */
1730
1731         unsigned int mode = 0;
1732
1733         if (seq->args[0] > 0)
1734                 mode = seq->args[0];
1735
1736         switch (mode) {
1737         case 0:
1738                 term_page_erase(screen->page,
1739                                 screen->state.cursor_x, screen->state.cursor_y,
1740                                 screen->page->width, screen->page->height,
1741                                 &screen->state.attr, screen->age, true);
1742                 break;
1743         case 1:
1744                 term_page_erase(screen->page,
1745                                 0, 0,
1746                                 screen->state.cursor_x, screen->state.cursor_y,
1747                                 &screen->state.attr, screen->age, true);
1748                 break;
1749         case 2:
1750                 term_page_erase(screen->page,
1751                                 0, 0,
1752                                 screen->page->width, screen->page->height,
1753                                 &screen->state.attr, screen->age, true);
1754                 break;
1755         }
1756
1757         return 0;
1758 }
1759
1760 static int screen_DECSEL(term_screen *screen, const term_seq *seq) {
1761         /*
1762          * DECSEL - selective-erase-in-line
1763          * This control function erases some or all of the erasable characters
1764          * in a single line of text. DECSEL erases only those characters defined
1765          * as erasable by the DECSCA control function. DECSEL works inside or
1766          * outside the scrolling margins.
1767          *
1768          * @args[0] defines the region to be erased. If it is 0, all cells from
1769          * the cursor (inclusive) till the end of the line are erase. If it is
1770          * 1, all cells from the start of the line till the cursor (inclusive)
1771          * are erased. If it is 2, the whole line of the cursor is erased.
1772          *
1773          * Defaults:
1774          *   args[0]: 0
1775          */
1776
1777         unsigned int mode = 0;
1778
1779         if (seq->args[0] > 0)
1780                 mode = seq->args[0];
1781
1782         switch (mode) {
1783         case 0:
1784                 term_page_erase(screen->page,
1785                                 screen->state.cursor_x, screen->state.cursor_y,
1786                                 screen->page->width, screen->state.cursor_y,
1787                                 &screen->state.attr, screen->age, true);
1788                 break;
1789         case 1:
1790                 term_page_erase(screen->page,
1791                                 0, screen->state.cursor_y,
1792                                 screen->state.cursor_x, screen->state.cursor_y,
1793                                 &screen->state.attr, screen->age, true);
1794                 break;
1795         case 2:
1796                 term_page_erase(screen->page,
1797                                 0, screen->state.cursor_y,
1798                                 screen->page->width, screen->state.cursor_y,
1799                                 &screen->state.attr, screen->age, true);
1800                 break;
1801         }
1802
1803         return 0;
1804 }
1805
1806 static int screen_DECSERA(term_screen *screen, const term_seq *seq) {
1807         /*
1808          * DECSERA - selective-erase-rectangular-area
1809          *
1810          * Probably not worth implementing.
1811          */
1812
1813         return 0;
1814 }
1815
1816 static int screen_DECSFC(term_screen *screen, const term_seq *seq) {
1817         /*
1818          * DECSFC - select-flow-control
1819          *
1820          * Probably not worth implementing.
1821          */
1822
1823         return 0;
1824 }
1825
1826 static int screen_DECSKCV(term_screen *screen, const term_seq *seq) {
1827         /*
1828          * DECSKCV - set-key-click-volume
1829          *
1830          * Probably not worth implementing.
1831          */
1832
1833         return 0;
1834 }
1835
1836 static int screen_DECSLCK(term_screen *screen, const term_seq *seq) {
1837         /*
1838          * DECSLCK - set-lock-key-style
1839          *
1840          * Probably not worth implementing.
1841          */
1842
1843         return 0;
1844 }
1845
1846 static int screen_DECSLE(term_screen *screen, const term_seq *seq) {
1847         /*
1848          * DECSLE - select-locator-events
1849          *
1850          * TODO: implement
1851          */
1852
1853         return 0;
1854 }
1855
1856 static int screen_DECSLPP(term_screen *screen, const term_seq *seq) {
1857         /*
1858          * DECSLPP - set-lines-per-page
1859          * Set the number of lines used for the page. @args[0] specifies the
1860          * number of lines to be used. DEC only allows a limited number of
1861          * choices, however, we allow all integers. 0 is equivalent to 24.
1862          *
1863          * Defaults:
1864          *   args[0]: 0
1865          *
1866          * TODO: implement
1867          */
1868
1869         return 0;
1870 }
1871
1872 static int screen_DECSLRM_OR_SC(term_screen *screen, const term_seq *seq) {
1873         /*
1874          * DECSLRM_OR_SC - set-left-and-right-margins or save-cursor
1875          *
1876          * TODO: Detect save-cursor and run it. DECSLRM is not worth
1877          *       implementing.
1878          */
1879
1880         return 0;
1881 }
1882
1883 static int screen_DECSMBV(term_screen *screen, const term_seq *seq) {
1884         /*
1885          * DECSMBV - set-margin-bell-volume
1886          *
1887          * Probably not worth implementing.
1888          */
1889
1890         return 0;
1891 }
1892
1893 static int screen_DECSMKR(term_screen *screen, const term_seq *seq) {
1894         /*
1895          * DECSMKR - select-modifier-key-reporting
1896          *
1897          * Probably not worth implementing.
1898          */
1899
1900         return 0;
1901 }
1902
1903 static int screen_DECSNLS(term_screen *screen, const term_seq *seq) {
1904         /*
1905          * DECSNLS - set-lines-per-screen
1906          *
1907          * Probably not worth implementing.
1908          */
1909
1910         return 0;
1911 }
1912
1913 static int screen_DECSPP(term_screen *screen, const term_seq *seq) {
1914         /*
1915          * DECSPP - set-port-parameter
1916          *
1917          * Probably not worth implementing.
1918          */
1919
1920         return 0;
1921 }
1922
1923 static int screen_DECSPPCS(term_screen *screen, const term_seq *seq) {
1924         /*
1925          * DECSPPCS - select-pro-printer-character-set
1926          *
1927          * Probably not worth implementing.
1928          */
1929
1930         return 0;
1931 }
1932
1933 static int screen_DECSPRTT(term_screen *screen, const term_seq *seq) {
1934         /*
1935          * DECSPRTT - select-printer-type
1936          *
1937          * Probably not worth implementing.
1938          */
1939
1940         return 0;
1941 }
1942
1943 static int screen_DECSR(term_screen *screen, const term_seq *seq) {
1944         /*
1945          * DECSR - secure-reset
1946          *
1947          * Probably not worth implementing.
1948          */
1949
1950         return 0;
1951 }
1952
1953 static int screen_DECSRFR(term_screen *screen, const term_seq *seq) {
1954         /*
1955          * DECSRFR - select-refresh-rate
1956          *
1957          * Probably not worth implementing.
1958          */
1959
1960         return 0;
1961 }
1962
1963 static int screen_DECSSCLS(term_screen *screen, const term_seq *seq) {
1964         /*
1965          * DECSSCLS - set-scroll-speed
1966          *
1967          * Probably not worth implementing.
1968          */
1969
1970         return 0;
1971 }
1972
1973 static int screen_DECSSDT(term_screen *screen, const term_seq *seq) {
1974         /*
1975          * DECSSDT - select-status-display-line-type
1976          *
1977          * Probably not worth implementing.
1978          */
1979
1980         return 0;
1981 }
1982
1983 static int screen_DECSSL(term_screen *screen, const term_seq *seq) {
1984         /*
1985          * DECSSL - select-setup-language
1986          *
1987          * Probably not worth implementing.
1988          */
1989
1990         return 0;
1991 }
1992
1993 static int screen_DECST8C(term_screen *screen, const term_seq *seq) {
1994         /*
1995          * DECST8C - set-tab-at-every-8-columns
1996          * Clear the tab-ruler and reset it to a tab at every 8th column,
1997          * starting at 9 (though, setting a tab at 1 is fine as it has no
1998          * effect).
1999          */
2000
2001         unsigned int i;
2002
2003         for (i = 0; i < screen->page->width; i += 8)
2004                 screen->tabs[i / 8] = 0x1;
2005
2006         return 0;
2007 }
2008
2009 static int screen_DECSTBM(term_screen *screen, const term_seq *seq) {
2010         /*
2011          * DECSTBM - set-top-and-bottom-margins
2012          * This control function sets the top and bottom margins for the current
2013          * page. You cannot perform scrolling outside the margins.
2014          *
2015          * @args[0] defines the top margin, @args[1] defines the bottom margin.
2016          * The bottom margin must be lower than the top-margin.
2017          *
2018          * This call resets the cursor position to 0/0 of the page.
2019          *
2020          * Defaults:
2021          *   args[0]: 1
2022          *   args[1]: last page-line
2023          */
2024
2025         unsigned int top, bottom;
2026
2027         top = 1;
2028         bottom = screen->page->height;
2029
2030         if (seq->args[0] > 0)
2031                 top = seq->args[0];
2032         if (seq->args[1] > 0)
2033                 bottom = seq->args[1];
2034
2035         if (top > screen->page->height)
2036                 top = screen->page->height;
2037         if (bottom > screen->page->height)
2038                 bottom = screen->page->height;
2039
2040         if (top >= bottom || top > screen->page->height || bottom > screen->page->height) {
2041                 top = 1;
2042                 bottom = screen->page->height;
2043         }
2044
2045         term_page_set_scroll_region(screen->page, top - 1, bottom - top + 1);
2046         screen_cursor_clear_wrap(screen);
2047         screen_cursor_set(screen, 0, 0);
2048
2049         return 0;
2050 }
2051
2052 static int screen_DECSTR(term_screen *screen, const term_seq *seq) {
2053         /*
2054          * DECSTR - soft-terminal-reset
2055          * Perform a soft reset to the default values.
2056          */
2057
2058         term_screen_soft_reset(screen);
2059
2060         return 0;
2061 }
2062
2063 static int screen_DECSTRL(term_screen *screen, const term_seq *seq) {
2064         /*
2065          * DECSTRL - set-transmit-rate-limit
2066          *
2067          * Probably not worth implementing.
2068          */
2069
2070         return 0;
2071 }
2072
2073 static int screen_DECSWBV(term_screen *screen, const term_seq *seq) {
2074         /*
2075          * DECSWBV - set-warning-bell-volume
2076          *
2077          * Probably not worth implementing.
2078          */
2079
2080         return 0;
2081 }
2082
2083 static int screen_DECSWL(term_screen *screen, const term_seq *seq) {
2084         /*
2085          * DECSWL - single-width-single-height-line
2086          *
2087          * Probably not worth implementing.
2088          */
2089
2090         return 0;
2091 }
2092
2093 static int screen_DECTID(term_screen *screen, const term_seq *seq) {
2094         /*
2095          * DECTID - select-terminal-id
2096          *
2097          * Probably not worth implementing.
2098          */
2099
2100         return 0;
2101 }
2102
2103 static int screen_DECTME(term_screen *screen, const term_seq *seq) {
2104         /*
2105          * DECTME - terminal-mode-emulation
2106          *
2107          * Probably not worth implementing.
2108          */
2109
2110         return 0;
2111 }
2112
2113 static int screen_DECTST(term_screen *screen, const term_seq *seq) {
2114         /*
2115          * DECTST - invoke-confidence-test
2116          *
2117          * Probably not worth implementing.
2118          */
2119
2120         return 0;
2121 }
2122
2123 static int screen_DL(term_screen *screen, const term_seq *seq) {
2124         /*
2125          * DL - delete-line
2126          * This control function deletes one or more lines in the scrolling
2127          * region, starting with the line that has the cursor. @args[0] defines
2128          * the number of lines to delete. 0 is treated the same as 1.
2129          * As lines are deleted, lines below the cursor and in the scrolling
2130          * region move up. The terminal adds blank lines with no visual
2131          * character attributes at the bottom of the scrolling region. If it is
2132          * greater than the number of lines remaining on the page, DL deletes
2133          * only the remaining lines. DL has no effect outside the scrolling
2134          * margins.
2135          *
2136          * Defaults:
2137          *   args[0]: 1
2138          */
2139
2140         unsigned int num = 1;
2141
2142         if (seq->args[0] > 0)
2143                 num = seq->args[0];
2144
2145         term_page_delete_lines(screen->page, screen->state.cursor_y, num, &screen->state.attr, screen->age);
2146
2147         return 0;
2148 }
2149
2150 static int screen_DSR_ANSI(term_screen *screen, const term_seq *seq) {
2151         /*
2152          * DSR_ANSI - device-status-report-ansi
2153          *
2154          * TODO: implement
2155          */
2156
2157         return 0;
2158 }
2159
2160 static int screen_DSR_DEC(term_screen *screen, const term_seq *seq) {
2161         /*
2162          * DSR_DEC - device-status-report-dec
2163          *
2164          * TODO: implement
2165          */
2166
2167         return 0;
2168 }
2169
2170 static int screen_ECH(term_screen *screen, const term_seq *seq) {
2171         /*
2172          * ECH - erase-character
2173          * This control function erases one or more characters, from the cursor
2174          * position to the right. ECH clears character attributes from erased
2175          * character positions. ECH works inside or outside the scrolling
2176          * margins.
2177          * @args[0] defines the number of characters to erase. 0 is treated the
2178          * same as 1.
2179          *
2180          * Defaults:
2181          *   args[0]: 1
2182          */
2183
2184         unsigned int num = 1;
2185
2186         if (seq->args[0] > 0)
2187                 num = seq->args[0];
2188
2189         term_page_erase(screen->page,
2190                         screen->state.cursor_x, screen->state.cursor_y,
2191                         screen->state.cursor_x + num, screen->state.cursor_y,
2192                         &screen->state.attr, screen->age, false);
2193
2194         return 0;
2195 }
2196
2197 static int screen_ED(term_screen *screen, const term_seq *seq) {
2198         /*
2199          * ED - erase-in-display
2200          * This control function erases characters from part or all of the
2201          * display. When you erase complete lines, they become single-height,
2202          * single-width lines, with all visual character attributes cleared. ED
2203          * works inside or outside the scrolling margins.
2204          *
2205          * @args[0] defines the region to erase. 0 means from cursor (inclusive)
2206          * till the end of the screen. 1 means from the start of the screen till
2207          * the cursor (inclusive) and 2 means the whole screen.
2208          *
2209          * Defaults:
2210          *   args[0]: 0
2211          */
2212
2213         unsigned int mode = 0;
2214
2215         if (seq->args[0] > 0)
2216                 mode = seq->args[0];
2217
2218         switch (mode) {
2219         case 0:
2220                 term_page_erase(screen->page,
2221                                 screen->state.cursor_x, screen->state.cursor_y,
2222                                 screen->page->width, screen->page->height,
2223                                 &screen->state.attr, screen->age, false);
2224                 break;
2225         case 1:
2226                 term_page_erase(screen->page,
2227                                 0, 0,
2228                                 screen->state.cursor_x, screen->state.cursor_y,
2229                                 &screen->state.attr, screen->age, false);
2230                 break;
2231         case 2:
2232                 term_page_erase(screen->page,
2233                                 0, 0,
2234                                 screen->page->width, screen->page->height,
2235                                 &screen->state.attr, screen->age, false);
2236                 break;
2237         }
2238
2239         return 0;
2240 }
2241
2242 static int screen_EL(term_screen *screen, const term_seq *seq) {
2243         /*
2244          * EL - erase-in-line
2245          * This control function erases characters on the line that has the
2246          * cursor. EL clears all character attributes from erased character
2247          * positions. EL works inside or outside the scrolling margins.
2248          *
2249          * @args[0] defines the region to erase. 0 means from cursor (inclusive)
2250          * till the end of the line. 1 means from the start of the line till the
2251          * cursor (inclusive) and 2 means the whole line.
2252          *
2253          * Defaults:
2254          *   args[0]: 0
2255          */
2256
2257         unsigned int mode = 0;
2258
2259         if (seq->args[0] > 0)
2260                 mode = seq->args[0];
2261
2262         switch (mode) {
2263         case 0:
2264                 term_page_erase(screen->page,
2265                                 screen->state.cursor_x, screen->state.cursor_y,
2266                                 screen->page->width, screen->state.cursor_y,
2267                                 &screen->state.attr, screen->age, false);
2268                 break;
2269         case 1:
2270                 term_page_erase(screen->page,
2271                                 0, screen->state.cursor_y,
2272                                 screen->state.cursor_x, screen->state.cursor_y,
2273                                 &screen->state.attr, screen->age, false);
2274                 break;
2275         case 2:
2276                 term_page_erase(screen->page,
2277                                 0, screen->state.cursor_y,
2278                                 screen->page->width, screen->state.cursor_y,
2279                                 &screen->state.attr, screen->age, false);
2280                 break;
2281         }
2282
2283         return 0;
2284 }
2285
2286 static int screen_ENQ(term_screen *screen, const term_seq *seq) {
2287         /*
2288          * ENQ - enquiry
2289          * Transmit the answerback-string. If none is set, do nothing.
2290          */
2291
2292         if (screen->answerback)
2293                 return screen_write(screen, screen->answerback, strlen(screen->answerback));
2294
2295         return 0;
2296 }
2297
2298 static int screen_EPA(term_screen *screen, const term_seq *seq) {
2299         /*
2300          * EPA - end-of-guarded-area
2301          *
2302          * TODO: What is this?
2303          */
2304
2305         return 0;
2306 }
2307
2308 static int screen_FF(term_screen *screen, const term_seq *seq) {
2309         /*
2310          * FF - form-feed
2311          * This causes the cursor to jump to the next line. It is treated the
2312          * same as LF.
2313          */
2314
2315         return screen_LF(screen, seq);
2316 }
2317
2318 static int screen_HPA(term_screen *screen, const term_seq *seq) {
2319         /*
2320          * HPA - horizontal-position-absolute
2321          * HPA causes the active position to be moved to the n-th horizontal
2322          * position of the active line. If an attempt is made to move the active
2323          * position past the last position on the line, then the active position
2324          * stops at the last position on the line.
2325          *
2326          * @args[0] defines the horizontal position. 0 is treated as 1.
2327          *
2328          * Defaults:
2329          *   args[0]: 1
2330          */
2331
2332         unsigned int num = 1;
2333
2334         if (seq->args[0] > 0)
2335                 num = seq->args[0];
2336
2337         screen_cursor_clear_wrap(screen);
2338         screen_cursor_set(screen, num - 1, screen->state.cursor_y);
2339
2340         return 0;
2341 }
2342
2343 static int screen_HPR(term_screen *screen, const term_seq *seq) {
2344         /*
2345          * HPR - horizontal-position-relative
2346          * HPR causes the active position to be moved to the n-th following
2347          * horizontal position of the active line. If an attempt is made to move
2348          * the active position past the last position on the line, then the
2349          * active position stops at the last position on the line.
2350          *
2351          * @args[0] defines the horizontal position. 0 is treated as 1.
2352          *
2353          * Defaults:
2354          *   args[0]: 1
2355          */
2356
2357         unsigned int num = 1;
2358
2359         if (seq->args[0] > 0)
2360                 num = seq->args[0];
2361
2362         screen_cursor_clear_wrap(screen);
2363         screen_cursor_right(screen, num);
2364
2365         return 0;
2366 }
2367
2368 static int screen_HT(term_screen *screen, const term_seq *seq) {
2369         /*
2370          * HT - horizontal-tab
2371          * Moves the cursor to the next tab stop. If there are no more tab
2372          * stops, the cursor moves to the right margin. HT does not cause text
2373          * to auto wrap.
2374          */
2375
2376         screen_cursor_clear_wrap(screen);
2377         screen_cursor_right_tab(screen, 1);
2378
2379         return 0;
2380 }
2381
2382 static int screen_HTS(term_screen *screen, const term_seq *seq) {
2383         /*
2384          * HTS - horizontal-tab-set
2385          * HTS sets a horizontal tab stop at the column position indicated by
2386          * the value of the active column when the terminal receives an HTS.
2387          *
2388          * Executing an HTS does not effect the other horizontal tab stop
2389          * settings.
2390          */
2391
2392         unsigned int pos;
2393
2394         pos = screen->state.cursor_x;
2395         if (screen->page->width > 0)
2396                 screen->tabs[pos / 8] |= 1U << (pos % 8);
2397
2398         return 0;
2399 }
2400
2401 static int screen_HVP(term_screen *screen, const term_seq *seq) {
2402         /*
2403          * HVP - horizontal-and-vertical-position
2404          * This control function works the same as the cursor position (CUP)
2405          * function. Origin mode (DECOM) selects line numbering and the ability
2406          * to move the cursor into margins.
2407          *
2408          * Defaults:
2409          *   args[0]: 1
2410          *   args[1]: 1
2411          */
2412
2413         return screen_CUP(screen, seq);
2414 }
2415
2416 static int screen_ICH(term_screen *screen, const term_seq *seq) {
2417         /*
2418          * ICH - insert-character
2419          * This control function inserts one or more space (SP) characters
2420          * starting at the cursor position. @args[0] is the number of characters
2421          * to insert. 0 is treated as 1.
2422          *
2423          * The ICH sequence inserts blank characters with the normal
2424          * character attribute. The cursor remains at the beginning of the blank
2425          * characters. Text between the cursor and right margin moves to the
2426          * right. Characters scrolled past the right margin are lost. ICH has no
2427          * effect outside the scrolling margins.
2428          *
2429          * Defaults:
2430          *   args[0]: 1
2431          */
2432
2433         unsigned int num = 1;
2434
2435         if (seq->args[0] > 0)
2436                 num = seq->args[0];
2437
2438         screen_cursor_clear_wrap(screen);
2439         term_page_insert_cells(screen->page, screen->state.cursor_x, screen->state.cursor_y, num, &screen->state.attr, screen->age);
2440
2441         return 0;
2442 }
2443
2444 static int screen_IL(term_screen *screen, const term_seq *seq) {
2445         /*
2446          * IL - insert-line
2447          * This control function inserts one or more blank lines, starting at
2448          * the cursor. @args[0] is the number of lines to insert. 0 is treated
2449          * as 1.
2450          *
2451          * As lines are inserted, lines below the cursor and in the scrolling
2452          * region move down. Lines scrolled off the page are lost. IL has no
2453          * effect outside the page margins.
2454          *
2455          * Defaults:
2456          *   args[0]: 1
2457          */
2458
2459         unsigned int num = 1;
2460
2461         if (seq->args[0] > 0)
2462                 num = seq->args[0];
2463
2464         screen_cursor_clear_wrap(screen);
2465         term_page_insert_lines(screen->page, screen->state.cursor_y, num, &screen->state.attr, screen->age);
2466
2467         return 0;
2468 }
2469
2470 static int screen_IND(term_screen *screen, const term_seq *seq) {
2471         /*
2472          * IND - index
2473          * IND moves the cursor down one line in the same column. If the cursor
2474          * is at the bottom margin, then the screen performs a scroll-up.
2475          */
2476
2477         screen_cursor_down(screen, 1, true);
2478
2479         return 0;
2480 }
2481
2482 static int screen_LF(term_screen *screen, const term_seq *seq) {
2483         /*
2484          * LF - line-feed
2485          * Causes a line feed or a new line operation, depending on the setting
2486          * of line feed/new line mode.
2487          */
2488
2489         screen_cursor_down(screen, 1, true);
2490         if (screen->flags & TERM_FLAG_NEWLINE_MODE)
2491                 screen_cursor_left(screen, screen->state.cursor_x);
2492
2493         return 0;
2494 }
2495
2496 static int screen_LS1R(term_screen *screen, const term_seq *seq) {
2497         /*
2498          * LS1R - locking-shift-1-right
2499          * Map G1 into GR.
2500          */
2501
2502         screen->state.gr = &screen->g1;
2503
2504         return 0;
2505 }
2506
2507 static int screen_LS2(term_screen *screen, const term_seq *seq) {
2508         /*
2509          * LS2 - locking-shift-2
2510          * Map G2 into GL.
2511          */
2512
2513         screen->state.gl = &screen->g2;
2514
2515         return 0;
2516 }
2517
2518 static int screen_LS2R(term_screen *screen, const term_seq *seq) {
2519         /*
2520          * LS2R - locking-shift-2-right
2521          * Map G2 into GR.
2522          */
2523
2524         screen->state.gr = &screen->g2;
2525
2526         return 0;
2527 }
2528
2529 static int screen_LS3(term_screen *screen, const term_seq *seq) {
2530         /*
2531          * LS3 - locking-shift-3
2532          * Map G3 into GL.
2533          */
2534
2535         screen->state.gl = &screen->g3;
2536
2537         return 0;
2538 }
2539
2540 static int screen_LS3R(term_screen *screen, const term_seq *seq) {
2541         /*
2542          * LS3R - locking-shift-3-right
2543          * Map G3 into GR.
2544          */
2545
2546         screen->state.gr = &screen->g3;
2547
2548         return 0;
2549 }
2550
2551 static int screen_MC_ANSI(term_screen *screen, const term_seq *seq) {
2552         /*
2553          * MC_ANSI - media-copy-ansi
2554          *
2555          * Probably not worth implementing.
2556          */
2557
2558         return 0;
2559 }
2560
2561 static int screen_MC_DEC(term_screen *screen, const term_seq *seq) {
2562         /*
2563          * MC_DEC - media-copy-dec
2564          *
2565          * Probably not worth implementing.
2566          */
2567
2568         return 0;
2569 }
2570
2571 static int screen_NEL(term_screen *screen, const term_seq *seq) {
2572         /*
2573          * NEL - next-line
2574          * Moves cursor to first position on next line. If cursor is at bottom
2575          * margin, then screen performs a scroll-up.
2576          */
2577
2578         screen_cursor_clear_wrap(screen);
2579         screen_cursor_down(screen, 1, true);
2580         screen_cursor_set(screen, 0, screen->state.cursor_y);
2581
2582         return 0;
2583 }
2584
2585 static int screen_NP(term_screen *screen, const term_seq *seq) {
2586         /*
2587          * NP - next-page
2588          * This control function moves the cursor forward to the home position
2589          * on one of the following pages in page memory. If there is only one
2590          * page, then the terminal ignores NP.
2591          * If NP tries to move the cursor past the last page in memory, then the
2592          * cursor stops at the last page.
2593          *
2594          * @args[0] defines the number of pages to forward. 0 is treated as 1.
2595          *
2596          * Defaults:
2597          *   args[0]: 1
2598          *
2599          * Probably not worth implementing. We only support a single page.
2600          */
2601
2602         return 0;
2603 }
2604
2605 static int screen_NULL(term_screen *screen, const term_seq *seq) {
2606         /*
2607          * NULL - null
2608          * The NULL operation does nothing. ASCII NULL is always ignored.
2609          */
2610
2611         return 0;
2612 }
2613
2614 static int screen_PP(term_screen *screen, const term_seq *seq) {
2615         /*
2616          * PP - preceding-page
2617          * This control function moves the cursor backward to the home position
2618          * on one of the preceding pages in page memory. If there is only one
2619          * page, then the terminal ignores PP.
2620          * If PP tries to move the cursor back farther than the first page in
2621          * memory, then the cursor stops at the first page.
2622          *
2623          * @args[0] defines the number of pages to go backwards. 0 is treated
2624          * as 1.
2625          *
2626          * Defaults:
2627          *   args[0]: 1
2628          *
2629          * Probably not worth implementing. We only support a single page.
2630          */
2631
2632         return 0;
2633 }
2634
2635 static int screen_PPA(term_screen *screen, const term_seq *seq) {
2636         /*
2637          * PPA - page-position-absolute
2638          * This control function can move the cursor to the corresponding row
2639          * and column on any page in page memory. You select the page by its
2640          * number. If there is only one page, then the terminal ignores PPA.
2641          *
2642          * @args[0] is the number of the page to move the cursor to. If it is
2643          * greater than the number of the last page in memory, then the cursor
2644          * stops at the last page. If it is less than the number of the first
2645          * page, then the cursor stops at the first page.
2646          *
2647          * Defaults:
2648          *   args[0]: 1
2649          *
2650          * Probably not worth implementing. We only support a single page.
2651          */
2652
2653         return 0;
2654 }
2655
2656 static int screen_PPB(term_screen *screen, const term_seq *seq) {
2657         /*
2658          * PPB - page-position-backward
2659          * This control function moves the cursor backward to the corresponding
2660          * row and column on one of the preceding pages in page memory. If there
2661          * is only one page, then the terminal ignores PPB.
2662          *
2663          * @args[0] indicates the number of pages to move the cursor backward.
2664          * If it tries to move the cursor back farther than the first page in
2665          * memory, then the cursor stops at the first page. 0 is treated as 1.
2666          *
2667          * Defaults:
2668          *   args[0]: 1
2669          *
2670          * Probably not worth implementing. We only support a single page.
2671          */
2672
2673         return 0;
2674 }
2675
2676 static int screen_PPR(term_screen *screen, const term_seq *seq) {
2677         /*
2678          * PPR - page-position-relative
2679          * This control function moves the cursor forward to the corresponding
2680          * row and column on one of the following pages in page memory. If there
2681          * is only one page, then the terminal ignores PPR.
2682          *
2683          * @args[0] indicates how many pages to move the cursor forward. If it
2684          * tries to move the cursor beyond the last page in memory, then the
2685          * cursor stops at the last page. 0 is treated as 1.
2686          *
2687          * Defaults:
2688          *   args[0]: 1
2689          *
2690          * Probably not worth implementing. We only support a single page.
2691          */
2692
2693         return 0;
2694 }
2695
2696 static int screen_RC(term_screen *screen, const term_seq *seq) {
2697         /*
2698          * RC - restore-cursor
2699          */
2700
2701         return screen_DECRC(screen, seq);
2702 }
2703
2704 static int screen_REP(term_screen *screen, const term_seq *seq) {
2705         /*
2706          * REP - repeat
2707          * Repeat the preceding graphics-character the given number of times.
2708          * @args[0] specifies how often it shall be repeated. 0 is treated as 1.
2709          *
2710          * Defaults:
2711          *   args[0]: 1
2712          *
2713          * Probably not worth implementing.
2714          */
2715
2716         return 0;
2717 }
2718
2719 static int screen_RI(term_screen *screen, const term_seq *seq) {
2720         /*
2721          * RI - reverse-index
2722          * Moves the cursor up one line in the same column. If the cursor is at
2723          * the top margin, the page scrolls down.
2724          */
2725
2726         screen_cursor_up(screen, 1, true);
2727
2728         return 0;
2729 }
2730
2731 static int screen_RIS(term_screen *screen, const term_seq *seq) {
2732         /*
2733          * RIS - reset-to-initial-state
2734          * This control function causes a nonvolatile memory (NVR) recall to
2735          * occur. RIS replaces all set-up features with their saved settings.
2736          *
2737          * The terminal stores these saved settings in NVR memory. The saved
2738          * setting for a feature is the same as the factory-default setting,
2739          * unless you saved a new setting.
2740          */
2741
2742         term_screen_hard_reset(screen);
2743
2744         return 0;
2745 }
2746
2747 static int screen_RM_ANSI(term_screen *screen, const term_seq *seq) {
2748         /*
2749          * RM_ANSI - reset-mode-ansi
2750          *
2751          * TODO: implement (see VT510rm manual)
2752          */
2753
2754         unsigned int i;
2755
2756         for (i = 0; i < seq->n_args; ++i)
2757                 screen_mode_change_ansi(screen, seq->args[i], false);
2758
2759         return 0;
2760 }
2761
2762 static int screen_RM_DEC(term_screen *screen, const term_seq *seq) {
2763         /*
2764          * RM_DEC - reset-mode-dec
2765          * This is the same as RM_ANSI but for DEC modes.
2766          */
2767
2768         unsigned int i;
2769
2770         for (i = 0; i < seq->n_args; ++i)
2771                 screen_mode_change_dec(screen, seq->args[i], false);
2772
2773         return 0;
2774 }
2775
2776 static int screen_S7C1T(term_screen *screen, const term_seq *seq) {
2777         /*
2778          * S7C1T - set-7bit-c1-terminal
2779          * This causes the terminal to start sending C1 controls as 7bit
2780          * sequences instead of 8bit C1 controls.
2781          * This is ignored if the terminal is below level-2 emulation mode
2782          * (VT100 and below), the terminal already sends 7bit controls then.
2783          */
2784
2785         if (screen->conformance_level > TERM_CONFORMANCE_LEVEL_VT100)
2786                 screen->flags |= TERM_FLAG_7BIT_MODE;
2787
2788         return 0;
2789 }
2790
2791 static int screen_S8C1T(term_screen *screen, const term_seq *seq) {
2792         /*
2793          * S8C1T - set-8bit-c1-terminal
2794          * This causes the terminal to start sending C1 controls as 8bit C1
2795          * control instead of 7bit sequences.
2796          * This is ignored if the terminal is below level-2 emulation mode
2797          * (VT100 and below). The terminal always sends 7bit controls in those
2798          * modes.
2799          */
2800
2801         if (screen->conformance_level > TERM_CONFORMANCE_LEVEL_VT100)
2802                 screen->flags &= ~TERM_FLAG_7BIT_MODE;
2803
2804         return 0;
2805 }
2806
2807 static int screen_SCS(term_screen *screen, const term_seq *seq) {
2808         /*
2809          * SCS - select-character-set
2810          * Designate character sets to G-sets. The mapping from intermediates
2811          * and terminal characters in the escape sequence to G-sets and
2812          * character-sets is non-trivial and implemented separately. See there
2813          * for more information.
2814          * This call simply sets the selected G-set to the desired
2815          * character-set.
2816          */
2817
2818         term_charset *cs = NULL;
2819
2820         /* TODO: support more of them? */
2821         switch (seq->charset) {
2822         case TERM_CHARSET_ISO_LATIN1_SUPPLEMENTAL:
2823         case TERM_CHARSET_ISO_LATIN2_SUPPLEMENTAL:
2824         case TERM_CHARSET_ISO_LATIN5_SUPPLEMENTAL:
2825         case TERM_CHARSET_ISO_GREEK_SUPPLEMENTAL:
2826         case TERM_CHARSET_ISO_HEBREW_SUPPLEMENTAL:
2827         case TERM_CHARSET_ISO_LATIN_CYRILLIC:
2828                 break;
2829
2830         case TERM_CHARSET_DEC_SPECIAL_GRAPHIC:
2831                 cs = &term_dec_special_graphics;
2832                 break;
2833         case TERM_CHARSET_DEC_SUPPLEMENTAL:
2834                 cs = &term_dec_supplemental_graphics;
2835                 break;
2836         case TERM_CHARSET_DEC_TECHNICAL:
2837         case TERM_CHARSET_CYRILLIC_DEC:
2838         case TERM_CHARSET_DUTCH_NRCS:
2839         case TERM_CHARSET_FINNISH_NRCS:
2840         case TERM_CHARSET_FRENCH_NRCS:
2841         case TERM_CHARSET_FRENCH_CANADIAN_NRCS:
2842         case TERM_CHARSET_GERMAN_NRCS:
2843         case TERM_CHARSET_GREEK_DEC:
2844         case TERM_CHARSET_GREEK_NRCS:
2845         case TERM_CHARSET_HEBREW_DEC:
2846         case TERM_CHARSET_HEBREW_NRCS:
2847         case TERM_CHARSET_ITALIAN_NRCS:
2848         case TERM_CHARSET_NORWEGIAN_DANISH_NRCS:
2849         case TERM_CHARSET_PORTUGUESE_NRCS:
2850         case TERM_CHARSET_RUSSIAN_NRCS:
2851         case TERM_CHARSET_SCS_NRCS:
2852         case TERM_CHARSET_SPANISH_NRCS:
2853         case TERM_CHARSET_SWEDISH_NRCS:
2854         case TERM_CHARSET_SWISS_NRCS:
2855         case TERM_CHARSET_TURKISH_DEC:
2856         case TERM_CHARSET_TURKISH_NRCS:
2857                 break;
2858
2859         case TERM_CHARSET_USERPREF_SUPPLEMENTAL:
2860                 break;
2861         }
2862
2863         if (seq->intermediates & TERM_SEQ_FLAG_POPEN)
2864                 screen->g0 = cs ? : &term_unicode_lower;
2865         else if (seq->intermediates & TERM_SEQ_FLAG_PCLOSE)
2866                 screen->g1 = cs ? : &term_unicode_upper;
2867         else if (seq->intermediates & TERM_SEQ_FLAG_MULT)
2868                 screen->g2 = cs ? : &term_unicode_lower;
2869         else if (seq->intermediates & TERM_SEQ_FLAG_PLUS)
2870                 screen->g3 = cs ? : &term_unicode_upper;
2871         else if (seq->intermediates & TERM_SEQ_FLAG_MINUS)
2872                 screen->g1 = cs ? : &term_unicode_upper;
2873         else if (seq->intermediates & TERM_SEQ_FLAG_DOT)
2874                 screen->g2 = cs ? : &term_unicode_lower;
2875         else if (seq->intermediates & TERM_SEQ_FLAG_SLASH)
2876                 screen->g3 = cs ? : &term_unicode_upper;
2877
2878         return 0;
2879 }
2880
2881 static int screen_SD(term_screen *screen, const term_seq *seq) {
2882         /*
2883          * SD - scroll-down
2884          * This control function moves the user window down a specified number
2885          * of lines in page memory.
2886          * @args[0] is the number of lines to move the
2887          * user window up in page memory. New lines appear at the top of the
2888          * display. Old lines disappear at the bottom of the display. You
2889          * cannot pan past the top margin of the current page. 0 is treated
2890          * as 1.
2891          *
2892          * Defaults:
2893          *   args[0]: 1
2894          */
2895
2896         unsigned int num = 1;
2897
2898         if (seq->args[0] > 0)
2899                 num = seq->args[0];
2900
2901         term_page_scroll_down(screen->page, num, &screen->state.attr, screen->age, NULL);
2902
2903         return 0;
2904 }
2905
2906 static int screen_SGR(term_screen *screen, const term_seq *seq) {
2907         /*
2908          * SGR - select-graphics-rendition
2909          */
2910
2911         term_color *dst;
2912         unsigned int i, code;
2913         int v;
2914
2915         if (seq->n_args < 1) {
2916                 zero(screen->state.attr);
2917                 return 0;
2918         }
2919
2920         for (i = 0; i < seq->n_args; ++i) {
2921                 v = seq->args[i];
2922                 switch (v) {
2923                 case 1:
2924                         screen->state.attr.bold = 1;
2925                         break;
2926                 case 3:
2927                         screen->state.attr.italic = 1;
2928                         break;
2929                 case 4:
2930                         screen->state.attr.underline = 1;
2931                         break;
2932                 case 5:
2933                         screen->state.attr.blink = 1;
2934                         break;
2935                 case 7:
2936                         screen->state.attr.inverse = 1;
2937                         break;
2938                 case 8:
2939                         screen->state.attr.hidden = 1;
2940                         break;
2941                 case 22:
2942                         screen->state.attr.bold = 0;
2943                         break;
2944                 case 23:
2945                         screen->state.attr.italic = 0;
2946                         break;
2947                 case 24:
2948                         screen->state.attr.underline = 0;
2949                         break;
2950                 case 25:
2951                         screen->state.attr.blink = 0;
2952                         break;
2953                 case 27:
2954                         screen->state.attr.inverse = 0;
2955                         break;
2956                 case 28:
2957                         screen->state.attr.hidden = 0;
2958                         break;
2959                 case 30 ... 37:
2960                         screen->state.attr.fg.ccode = v - 30 + TERM_CCODE_BLACK;
2961                         break;
2962                 case 39:
2963                         screen->state.attr.fg.ccode = 0;
2964                         break;
2965                 case 40 ... 47:
2966                         screen->state.attr.bg.ccode = v - 40 + TERM_CCODE_BLACK;
2967                         break;
2968                 case 49:
2969                         screen->state.attr.bg.ccode = 0;
2970                         break;
2971                 case 90 ... 97:
2972                         screen->state.attr.fg.ccode = v - 90 + TERM_CCODE_LIGHT_BLACK;
2973                         break;
2974                 case 100 ... 107:
2975                         screen->state.attr.bg.ccode = v - 100 + TERM_CCODE_LIGHT_BLACK;
2976                         break;
2977                 case 38:
2978                         /* fallthrough */
2979                 case 48:
2980
2981                         if (v == 38)
2982                                 dst = &screen->state.attr.fg;
2983                         else
2984                                 dst = &screen->state.attr.bg;
2985
2986                         ++i;
2987                         if (i >= seq->n_args)
2988                                 break;
2989
2990                         switch (seq->args[i]) {
2991                         case 2:
2992                                 /* 24bit-color support */
2993
2994                                 i += 3;
2995                                 if (i >= seq->n_args)
2996                                         break;
2997
2998                                 dst->ccode = TERM_CCODE_RGB;
2999                                 dst->red = (seq->args[i - 2] >= 0) ? seq->args[i - 2] : 0;
3000                                 dst->green = (seq->args[i - 1] >= 0) ? seq->args[i - 1] : 0;
3001                                 dst->blue = (seq->args[i] >= 0) ? seq->args[i] : 0;
3002
3003                                 break;
3004                         case 5:
3005                                 /* 256-color support */
3006
3007                                 ++i;
3008                                 if (i >= seq->n_args || seq->args[i] < 0)
3009                                         break;
3010
3011                                 dst->ccode = TERM_CCODE_256;
3012                                 code = seq->args[i];
3013                                 dst->c256 = code < 256 ? code : 0;
3014
3015                                 break;
3016                         }
3017
3018                         break;
3019                 case -1:
3020                         /* fallthrough */
3021                 case 0:
3022                         zero(screen->state.attr);
3023                         break;
3024                 }
3025         }
3026
3027         return 0;
3028 }
3029
3030 static int screen_SI(term_screen *screen, const term_seq *seq) {
3031         /*
3032          * SI - shift-in
3033          * Map G0 into GL.
3034          */
3035
3036         screen->state.gl = &screen->g0;
3037
3038         return 0;
3039 }
3040
3041 static int screen_SM_ANSI(term_screen *screen, const term_seq *seq) {
3042         /*
3043          * SM_ANSI - set-mode-ansi
3044          *
3045          * TODO: implement
3046          */
3047
3048         unsigned int i;
3049
3050         for (i = 0; i < seq->n_args; ++i)
3051                 screen_mode_change_ansi(screen, seq->args[i], true);
3052
3053         return 0;
3054 }
3055
3056 static int screen_SM_DEC(term_screen *screen, const term_seq *seq) {
3057         /*
3058          * SM_DEC - set-mode-dec
3059          * This is the same as SM_ANSI but for DEC modes.
3060          */
3061
3062         unsigned int i;
3063
3064         for (i = 0; i < seq->n_args; ++i)
3065                 screen_mode_change_dec(screen, seq->args[i], true);
3066
3067         return 0;
3068 }
3069
3070 static int screen_SO(term_screen *screen, const term_seq *seq) {
3071         /*
3072          * SO - shift-out
3073          * Map G1 into GL.
3074          */
3075
3076         screen->state.gl = &screen->g1;
3077
3078         return 0;
3079 }
3080
3081 static int screen_SPA(term_screen *screen, const term_seq *seq) {
3082         /*
3083          * SPA - start-of-protected-area
3084          *
3085          * TODO: What is this?
3086          */
3087
3088         return 0;
3089 }
3090
3091 static int screen_SS2(term_screen *screen, const term_seq *seq) {
3092         /*
3093          * SS2 - single-shift-2
3094          * Temporarily map G2 into GL for the next graphics character.
3095          */
3096
3097         screen->state.glt = &screen->g2;
3098
3099         return 0;
3100 }
3101
3102 static int screen_SS3(term_screen *screen, const term_seq *seq) {
3103         /*
3104          * SS3 - single-shift-3
3105          * Temporarily map G3 into GL for the next graphics character
3106          */
3107
3108         screen->state.glt = &screen->g3;
3109
3110         return 0;
3111 }
3112
3113 static int screen_ST(term_screen *screen, const term_seq *seq) {
3114         /*
3115          * ST - string-terminator
3116          * The string-terminator is usually part of control-sequences and
3117          * handled by the parser. In all other situations it is silently
3118          * ignored.
3119          */
3120
3121         return 0;
3122 }
3123
3124 static int screen_SU(term_screen *screen, const term_seq *seq) {
3125         /*
3126          * SU - scroll-up
3127          * This control function moves the user window up a specified number of
3128          * lines in page memory.
3129          * @args[0] is the number of lines to move the
3130          * user window down in page memory. New lines appear at the bottom of
3131          * the display. Old lines disappear at the top of the display. You
3132          * cannot pan past the bottom margin of the current page. 0 is treated
3133          * as 1.
3134          *
3135          * Defaults:
3136          *   args[0]: 1
3137          */
3138
3139         unsigned int num = 1;
3140
3141         if (seq->args[0] > 0)
3142                 num = seq->args[0];
3143
3144         term_page_scroll_up(screen->page, num, &screen->state.attr, screen->age, screen->history);
3145
3146         return 0;
3147 }
3148
3149 static int screen_SUB(term_screen *screen, const term_seq *seq) {
3150         /*
3151          * SUB - substitute
3152          * Cancel the current control-sequence and print a replacement
3153          * character. Our parser already handles this so all we have to do is
3154          * print the replacement character.
3155          */
3156
3157         static const term_seq rep = {
3158                 .type = TERM_SEQ_GRAPHIC,
3159                 .command = TERM_CMD_GRAPHIC,
3160                 .terminator = 0xfffd,
3161         };
3162
3163         return screen_GRAPHIC(screen, &rep);
3164 }
3165
3166 static int screen_TBC(term_screen *screen, const term_seq *seq) {
3167         /*
3168          * TBC - tab-clear
3169          * This clears tab-stops. If @args[0] is 0, the tab-stop at the current
3170          * cursor position is cleared. If it is 3, all tab stops are cleared.
3171          *
3172          * Defaults:
3173          *   args[0]: 0
3174          */
3175
3176         unsigned int mode = 0, pos;
3177
3178         if (seq->args[0] > 0)
3179                 mode = seq->args[0];
3180
3181         switch (mode) {
3182         case 0:
3183                 pos = screen->state.cursor_x;
3184                 if (screen->page->width > 0)
3185                         screen->tabs[pos / 8] &= ~(1U << (pos % 8));
3186                 break;
3187         case 3:
3188                 if (screen->page->width > 0)
3189                         memset(screen->tabs, 0, (screen->page->width + 7) / 8);
3190                 break;
3191         }
3192
3193         return 0;
3194 }
3195
3196 static int screen_VPA(term_screen *screen, const term_seq *seq) {
3197         /*
3198          * VPA - vertical-line-position-absolute
3199          * VPA causes the active position to be moved to the corresponding
3200          * horizontal position. @args[0] specifies the line to jump to. If an
3201          * attempt is made to move the active position below the last line, then
3202          * the active position stops on the last line. 0 is treated as 1.
3203          *
3204          * Defaults:
3205          *   args[0]: 1
3206          */
3207
3208         unsigned int pos = 1;
3209
3210         if (seq->args[0] > 0)
3211                 pos = seq->args[0];
3212
3213         screen_cursor_clear_wrap(screen);
3214         screen_cursor_set_rel(screen, screen->state.cursor_x, pos - 1);
3215
3216         return 0;
3217 }
3218
3219 static int screen_VPR(term_screen *screen, const term_seq *seq) {
3220         /*
3221          * VPR - vertical-line-position-relative
3222          * VPR causes the active position to be moved to the corresponding
3223          * horizontal position. @args[0] specifies the number of lines to jump
3224          * down relative to the current cursor position. If an attempt is made
3225          * to move the active position below the last line, the active position
3226          * stops at the last line. 0 is treated as 1.
3227          *
3228          * Defaults:
3229          *   args[0]: 1
3230          */
3231
3232         unsigned int num = 1;
3233
3234         if (seq->args[0] > 0)
3235                 num = seq->args[0];
3236
3237         screen_cursor_clear_wrap(screen);
3238         screen_cursor_down(screen, num, false);
3239
3240         return 0;
3241 }
3242
3243 static int screen_VT(term_screen *screen, const term_seq *seq) {
3244         /*
3245          * VT - vertical-tab
3246          * This causes a vertical jump by one line. Terminals treat it exactly
3247          * the same as LF.
3248          */
3249
3250         return screen_LF(screen, seq);
3251 }
3252
3253 static int screen_XTERM_CLLHP(term_screen *screen, const term_seq *seq) {
3254         /*
3255          * XTERM_CLLHP - xterm-cursor-lower-left-hp-bugfix
3256          * Move the cursor to the lower-left corner of the page. This is an HP
3257          * bugfix by xterm.
3258          *
3259          * Probably not worth implementing.
3260          */
3261
3262         return 0;
3263 }
3264
3265 static int screen_XTERM_IHMT(term_screen *screen, const term_seq *seq) {
3266         /*
3267          * XTERM_IHMT - xterm-initiate-highlight-mouse-tracking
3268          *
3269          * Probably not worth implementing.
3270          */
3271
3272         return 0;
3273 }
3274
3275 static int screen_XTERM_MLHP(term_screen *screen, const term_seq *seq) {
3276         /*
3277          * XTERM_MLHP - xterm-memory-lock-hp-bugfix
3278          *
3279          * Probably not worth implementing.
3280          */
3281
3282         return 0;
3283 }
3284
3285 static int screen_XTERM_MUHP(term_screen *screen, const term_seq *seq) {
3286         /*
3287          * XTERM_MUHP - xterm-memory-unlock-hp-bugfix
3288          *
3289          * Probably not worth implementing.
3290          */
3291
3292         return 0;
3293 }
3294
3295 static int screen_XTERM_RPM(term_screen *screen, const term_seq *seq) {
3296         /*
3297          * XTERM_RPM - xterm-restore-private-mode
3298          *
3299          * Probably not worth implementing.
3300          */
3301
3302         return 0;
3303 }
3304
3305 static int screen_XTERM_RRV(term_screen *screen, const term_seq *seq) {
3306         /*
3307          * XTERM_RRV - xterm-reset-resource-value
3308          *
3309          * Probably not worth implementing.
3310          */
3311
3312         return 0;
3313 }
3314
3315 static int screen_XTERM_RTM(term_screen *screen, const term_seq *seq) {
3316         /*
3317          * XTERM_RTM - xterm-reset-title-mode
3318          *
3319          * Probably not worth implementing.
3320          */
3321
3322         return 0;
3323 }
3324
3325 static int screen_XTERM_SACL1(term_screen *screen, const term_seq *seq) {
3326         /*
3327          * XTERM_SACL1 - xterm-set-ansi-conformance-level-1
3328          *
3329          * Probably not worth implementing.
3330          */
3331
3332         return 0;
3333 }
3334
3335 static int screen_XTERM_SACL2(term_screen *screen, const term_seq *seq) {
3336         /*
3337          * XTERM_SACL2 - xterm-set-ansi-conformance-level-2
3338          *
3339          * Probably not worth implementing.
3340          */
3341
3342         return 0;
3343 }
3344
3345 static int screen_XTERM_SACL3(term_screen *screen, const term_seq *seq) {
3346         /*
3347          * XTERM_SACL3 - xterm-set-ansi-conformance-level-3
3348          *
3349          * Probably not worth implementing.
3350          */
3351
3352         return 0;
3353 }
3354
3355 static int screen_XTERM_SDCS(term_screen *screen, const term_seq *seq) {
3356         /*
3357          * XTERM_SDCS - xterm-set-default-character-set
3358          * Select the default character set. We treat this the same as UTF-8 as
3359          * this is our default character set. As we always use UTF-8, this
3360          * becomes as no-op.
3361          */
3362
3363         return 0;
3364 }
3365
3366 static int screen_XTERM_SGFX(term_screen *screen, const term_seq *seq) {
3367         /*
3368          * XTERM_SGFX - xterm-sixel-graphics
3369          *
3370          * Probably not worth implementing.
3371          */
3372
3373         return 0;
3374 }
3375
3376 static int screen_XTERM_SPM(term_screen *screen, const term_seq *seq) {
3377         /*
3378          * XTERM_SPM - xterm-set-private-mode
3379          *
3380          * Probably not worth implementing.
3381          */
3382
3383         return 0;
3384 }
3385
3386 static int screen_XTERM_SRV(term_screen *screen, const term_seq *seq) {
3387         /*
3388          * XTERM_SRV - xterm-set-resource-value
3389          *
3390          * Probably not worth implementing.
3391          */
3392
3393         return 0;
3394 }
3395
3396 static int screen_XTERM_STM(term_screen *screen, const term_seq *seq) {
3397         /*
3398          * XTERM_STM - xterm-set-title-mode
3399          *
3400          * Probably not worth implementing.
3401          */
3402
3403         return 0;
3404 }
3405
3406 static int screen_XTERM_SUCS(term_screen *screen, const term_seq *seq) {
3407         /*
3408          * XTERM_SUCS - xterm-select-utf8-character-set
3409          * Select UTF-8 as character set. This is our default on only character
3410          * set. Hence, this is a no-op.
3411          */
3412
3413         return 0;
3414 }
3415
3416 static int screen_XTERM_WM(term_screen *screen, const term_seq *seq) {
3417         /*
3418          * XTERM_WM - xterm-window-management
3419          *
3420          * Probably not worth implementing.
3421          */
3422
3423         return 0;
3424 }
3425
3426 /*
3427  * Feeding data
3428  * The screen_feed_*() handlers take data from the user and feed it into the
3429  * screen. Once the parser has detected a sequence, we parse the command-type
3430  * and forward it to the command-dispatchers.
3431  */
3432
3433 static int screen_feed_cmd(term_screen *screen, const term_seq *seq) {
3434         switch (seq->command) {
3435         case TERM_CMD_GRAPHIC:
3436                 return screen_GRAPHIC(screen, seq);
3437         case TERM_CMD_BEL:
3438                 return screen_BEL(screen, seq);
3439         case TERM_CMD_BS:
3440                 return screen_BS(screen, seq);
3441         case TERM_CMD_CBT:
3442                 return screen_CBT(screen, seq);
3443         case TERM_CMD_CHA:
3444                 return screen_CHA(screen, seq);
3445         case TERM_CMD_CHT:
3446                 return screen_CHT(screen, seq);
3447         case TERM_CMD_CNL:
3448                 return screen_CNL(screen, seq);
3449         case TERM_CMD_CPL:
3450                 return screen_CPL(screen, seq);
3451         case TERM_CMD_CR:
3452                 return screen_CR(screen, seq);
3453         case TERM_CMD_CUB:
3454                 return screen_CUB(screen, seq);
3455         case TERM_CMD_CUD:
3456                 return screen_CUD(screen, seq);
3457         case TERM_CMD_CUF:
3458                 return screen_CUF(screen, seq);
3459         case TERM_CMD_CUP:
3460                 return screen_CUP(screen, seq);
3461         case TERM_CMD_CUU:
3462                 return screen_CUU(screen, seq);
3463         case TERM_CMD_DA1:
3464                 return screen_DA1(screen, seq);
3465         case TERM_CMD_DA2:
3466                 return screen_DA2(screen, seq);
3467         case TERM_CMD_DA3:
3468                 return screen_DA3(screen, seq);
3469         case TERM_CMD_DC1:
3470                 return screen_DC1(screen, seq);
3471         case TERM_CMD_DC3:
3472                 return screen_DC3(screen, seq);
3473         case TERM_CMD_DCH:
3474                 return screen_DCH(screen, seq);
3475         case TERM_CMD_DECALN:
3476                 return screen_DECALN(screen, seq);
3477         case TERM_CMD_DECANM:
3478                 return screen_DECANM(screen, seq);
3479         case TERM_CMD_DECBI:
3480                 return screen_DECBI(screen, seq);
3481         case TERM_CMD_DECCARA:
3482                 return screen_DECCARA(screen, seq);
3483         case TERM_CMD_DECCRA:
3484                 return screen_DECCRA(screen, seq);
3485         case TERM_CMD_DECDC:
3486                 return screen_DECDC(screen, seq);
3487         case TERM_CMD_DECDHL_BH:
3488                 return screen_DECDHL_BH(screen, seq);
3489         case TERM_CMD_DECDHL_TH:
3490                 return screen_DECDHL_TH(screen, seq);
3491         case TERM_CMD_DECDWL:
3492                 return screen_DECDWL(screen, seq);
3493         case TERM_CMD_DECEFR:
3494                 return screen_DECEFR(screen, seq);
3495         case TERM_CMD_DECELF:
3496                 return screen_DECELF(screen, seq);
3497         case TERM_CMD_DECELR:
3498                 return screen_DECELR(screen, seq);
3499         case TERM_CMD_DECERA:
3500                 return screen_DECERA(screen, seq);
3501         case TERM_CMD_DECFI:
3502                 return screen_DECFI(screen, seq);
3503         case TERM_CMD_DECFRA:
3504                 return screen_DECFRA(screen, seq);
3505         case TERM_CMD_DECIC:
3506                 return screen_DECIC(screen, seq);
3507         case TERM_CMD_DECID:
3508                 return screen_DECID(screen, seq);
3509         case TERM_CMD_DECINVM:
3510                 return screen_DECINVM(screen, seq);
3511         case TERM_CMD_DECKBD:
3512                 return screen_DECKBD(screen, seq);
3513         case TERM_CMD_DECKPAM:
3514                 return screen_DECKPAM(screen, seq);
3515         case TERM_CMD_DECKPNM:
3516                 return screen_DECKPNM(screen, seq);
3517         case TERM_CMD_DECLFKC:
3518                 return screen_DECLFKC(screen, seq);
3519         case TERM_CMD_DECLL:
3520                 return screen_DECLL(screen, seq);
3521         case TERM_CMD_DECLTOD:
3522                 return screen_DECLTOD(screen, seq);
3523         case TERM_CMD_DECPCTERM:
3524                 return screen_DECPCTERM(screen, seq);
3525         case TERM_CMD_DECPKA:
3526                 return screen_DECPKA(screen, seq);
3527         case TERM_CMD_DECPKFMR:
3528                 return screen_DECPKFMR(screen, seq);
3529         case TERM_CMD_DECRARA:
3530                 return screen_DECRARA(screen, seq);
3531         case TERM_CMD_DECRC:
3532                 return screen_DECRC(screen, seq);
3533         case TERM_CMD_DECREQTPARM:
3534                 return screen_DECREQTPARM(screen, seq);
3535         case TERM_CMD_DECRPKT:
3536                 return screen_DECRPKT(screen, seq);
3537         case TERM_CMD_DECRQCRA:
3538                 return screen_DECRQCRA(screen, seq);
3539         case TERM_CMD_DECRQDE:
3540                 return screen_DECRQDE(screen, seq);
3541         case TERM_CMD_DECRQKT:
3542                 return screen_DECRQKT(screen, seq);
3543         case TERM_CMD_DECRQLP:
3544                 return screen_DECRQLP(screen, seq);
3545         case TERM_CMD_DECRQM_ANSI:
3546                 return screen_DECRQM_ANSI(screen, seq);
3547         case TERM_CMD_DECRQM_DEC:
3548                 return screen_DECRQM_DEC(screen, seq);
3549         case TERM_CMD_DECRQPKFM:
3550                 return screen_DECRQPKFM(screen, seq);
3551         case TERM_CMD_DECRQPSR:
3552                 return screen_DECRQPSR(screen, seq);
3553         case TERM_CMD_DECRQTSR:
3554                 return screen_DECRQTSR(screen, seq);
3555         case TERM_CMD_DECRQUPSS:
3556                 return screen_DECRQUPSS(screen, seq);
3557         case TERM_CMD_DECSACE:
3558                 return screen_DECSACE(screen, seq);
3559         case TERM_CMD_DECSASD:
3560                 return screen_DECSASD(screen, seq);
3561         case TERM_CMD_DECSC:
3562                 return screen_DECSC(screen, seq);
3563         case TERM_CMD_DECSCA:
3564                 return screen_DECSCA(screen, seq);
3565         case TERM_CMD_DECSCL:
3566                 return screen_DECSCL(screen, seq);
3567         case TERM_CMD_DECSCP:
3568                 return screen_DECSCP(screen, seq);
3569         case TERM_CMD_DECSCPP:
3570                 return screen_DECSCPP(screen, seq);
3571         case TERM_CMD_DECSCS:
3572                 return screen_DECSCS(screen, seq);
3573         case TERM_CMD_DECSCUSR:
3574                 return screen_DECSCUSR(screen, seq);
3575         case TERM_CMD_DECSDDT:
3576                 return screen_DECSDDT(screen, seq);
3577         case TERM_CMD_DECSDPT:
3578                 return screen_DECSDPT(screen, seq);
3579         case TERM_CMD_DECSED:
3580                 return screen_DECSED(screen, seq);
3581         case TERM_CMD_DECSEL:
3582                 return screen_DECSEL(screen, seq);
3583         case TERM_CMD_DECSERA:
3584                 return screen_DECSERA(screen, seq);
3585         case TERM_CMD_DECSFC:
3586                 return screen_DECSFC(screen, seq);
3587         case TERM_CMD_DECSKCV:
3588                 return screen_DECSKCV(screen, seq);
3589         case TERM_CMD_DECSLCK:
3590                 return screen_DECSLCK(screen, seq);
3591         case TERM_CMD_DECSLE:
3592                 return screen_DECSLE(screen, seq);
3593         case TERM_CMD_DECSLPP:
3594                 return screen_DECSLPP(screen, seq);
3595         case TERM_CMD_DECSLRM_OR_SC:
3596                 return screen_DECSLRM_OR_SC(screen, seq);
3597         case TERM_CMD_DECSMBV:
3598                 return screen_DECSMBV(screen, seq);
3599         case TERM_CMD_DECSMKR:
3600                 return screen_DECSMKR(screen, seq);
3601         case TERM_CMD_DECSNLS:
3602                 return screen_DECSNLS(screen, seq);
3603         case TERM_CMD_DECSPP:
3604                 return screen_DECSPP(screen, seq);
3605         case TERM_CMD_DECSPPCS:
3606                 return screen_DECSPPCS(screen, seq);
3607         case TERM_CMD_DECSPRTT:
3608                 return screen_DECSPRTT(screen, seq);
3609         case TERM_CMD_DECSR:
3610                 return screen_DECSR(screen, seq);
3611         case TERM_CMD_DECSRFR:
3612                 return screen_DECSRFR(screen, seq);
3613         case TERM_CMD_DECSSCLS:
3614                 return screen_DECSSCLS(screen, seq);
3615         case TERM_CMD_DECSSDT:
3616                 return screen_DECSSDT(screen, seq);
3617         case TERM_CMD_DECSSL:
3618                 return screen_DECSSL(screen, seq);
3619         case TERM_CMD_DECST8C:
3620                 return screen_DECST8C(screen, seq);
3621         case TERM_CMD_DECSTBM:
3622                 return screen_DECSTBM(screen, seq);
3623         case TERM_CMD_DECSTR:
3624                 return screen_DECSTR(screen, seq);
3625         case TERM_CMD_DECSTRL:
3626                 return screen_DECSTRL(screen, seq);
3627         case TERM_CMD_DECSWBV:
3628                 return screen_DECSWBV(screen, seq);
3629         case TERM_CMD_DECSWL:
3630                 return screen_DECSWL(screen, seq);
3631         case TERM_CMD_DECTID:
3632                 return screen_DECTID(screen, seq);
3633         case TERM_CMD_DECTME:
3634                 return screen_DECTME(screen, seq);
3635         case TERM_CMD_DECTST:
3636                 return screen_DECTST(screen, seq);
3637         case TERM_CMD_DL:
3638                 return screen_DL(screen, seq);
3639         case TERM_CMD_DSR_ANSI:
3640                 return screen_DSR_ANSI(screen, seq);
3641         case TERM_CMD_DSR_DEC:
3642                 return screen_DSR_DEC(screen, seq);
3643         case TERM_CMD_ECH:
3644                 return screen_ECH(screen, seq);
3645         case TERM_CMD_ED:
3646                 return screen_ED(screen, seq);
3647         case TERM_CMD_EL:
3648                 return screen_EL(screen, seq);
3649         case TERM_CMD_ENQ:
3650                 return screen_ENQ(screen, seq);
3651         case TERM_CMD_EPA:
3652                 return screen_EPA(screen, seq);
3653         case TERM_CMD_FF:
3654                 return screen_FF(screen, seq);
3655         case TERM_CMD_HPA:
3656                 return screen_HPA(screen, seq);
3657         case TERM_CMD_HPR:
3658                 return screen_HPR(screen, seq);
3659         case TERM_CMD_HT:
3660                 return screen_HT(screen, seq);
3661         case TERM_CMD_HTS:
3662                 return screen_HTS(screen, seq);
3663         case TERM_CMD_HVP:
3664                 return screen_HVP(screen, seq);
3665         case TERM_CMD_ICH:
3666                 return screen_ICH(screen, seq);
3667         case TERM_CMD_IL:
3668                 return screen_IL(screen, seq);
3669         case TERM_CMD_IND:
3670                 return screen_IND(screen, seq);
3671         case TERM_CMD_LF:
3672                 return screen_LF(screen, seq);
3673         case TERM_CMD_LS1R:
3674                 return screen_LS1R(screen, seq);
3675         case TERM_CMD_LS2:
3676                 return screen_LS2(screen, seq);
3677         case TERM_CMD_LS2R:
3678                 return screen_LS2R(screen, seq);
3679         case TERM_CMD_LS3:
3680                 return screen_LS3(screen, seq);
3681         case TERM_CMD_LS3R:
3682                 return screen_LS3R(screen, seq);
3683         case TERM_CMD_MC_ANSI:
3684                 return screen_MC_ANSI(screen, seq);
3685         case TERM_CMD_MC_DEC:
3686                 return screen_MC_DEC(screen, seq);
3687         case TERM_CMD_NEL:
3688                 return screen_NEL(screen, seq);
3689         case TERM_CMD_NP:
3690                 return screen_NP(screen, seq);
3691         case TERM_CMD_NULL:
3692                 return screen_NULL(screen, seq);
3693         case TERM_CMD_PP:
3694                 return screen_PP(screen, seq);
3695         case TERM_CMD_PPA:
3696                 return screen_PPA(screen, seq);
3697         case TERM_CMD_PPB:
3698                 return screen_PPB(screen, seq);
3699         case TERM_CMD_PPR:
3700                 return screen_PPR(screen, seq);
3701         case TERM_CMD_RC:
3702                 return screen_RC(screen, seq);
3703         case TERM_CMD_REP:
3704                 return screen_REP(screen, seq);
3705         case TERM_CMD_RI:
3706                 return screen_RI(screen, seq);
3707         case TERM_CMD_RIS:
3708                 return screen_RIS(screen, seq);
3709         case TERM_CMD_RM_ANSI:
3710                 return screen_RM_ANSI(screen, seq);
3711         case TERM_CMD_RM_DEC:
3712                 return screen_RM_DEC(screen, seq);
3713         case TERM_CMD_S7C1T:
3714                 return screen_S7C1T(screen, seq);
3715         case TERM_CMD_S8C1T:
3716                 return screen_S8C1T(screen, seq);
3717         case TERM_CMD_SCS:
3718                 return screen_SCS(screen, seq);
3719         case TERM_CMD_SD:
3720                 return screen_SD(screen, seq);
3721         case TERM_CMD_SGR:
3722                 return screen_SGR(screen, seq);
3723         case TERM_CMD_SI:
3724                 return screen_SI(screen, seq);
3725         case TERM_CMD_SM_ANSI:
3726                 return screen_SM_ANSI(screen, seq);
3727         case TERM_CMD_SM_DEC:
3728                 return screen_SM_DEC(screen, seq);
3729         case TERM_CMD_SO:
3730                 return screen_SO(screen, seq);
3731         case TERM_CMD_SPA:
3732                 return screen_SPA(screen, seq);
3733         case TERM_CMD_SS2:
3734                 return screen_SS2(screen, seq);
3735         case TERM_CMD_SS3:
3736                 return screen_SS3(screen, seq);
3737         case TERM_CMD_ST:
3738                 return screen_ST(screen, seq);
3739         case TERM_CMD_SU:
3740                 return screen_SU(screen, seq);
3741         case TERM_CMD_SUB:
3742                 return screen_SUB(screen, seq);
3743         case TERM_CMD_TBC:
3744                 return screen_TBC(screen, seq);
3745         case TERM_CMD_VPA:
3746                 return screen_VPA(screen, seq);
3747         case TERM_CMD_VPR:
3748                 return screen_VPR(screen, seq);
3749         case TERM_CMD_VT:
3750                 return screen_VT(screen, seq);
3751         case TERM_CMD_XTERM_CLLHP:
3752                 return screen_XTERM_CLLHP(screen, seq);
3753         case TERM_CMD_XTERM_IHMT:
3754                 return screen_XTERM_IHMT(screen, seq);
3755         case TERM_CMD_XTERM_MLHP:
3756                 return screen_XTERM_MLHP(screen, seq);
3757         case TERM_CMD_XTERM_MUHP:
3758                 return screen_XTERM_MUHP(screen, seq);
3759         case TERM_CMD_XTERM_RPM:
3760                 return screen_XTERM_RPM(screen, seq);
3761         case TERM_CMD_XTERM_RRV:
3762                 return screen_XTERM_RRV(screen, seq);
3763         case TERM_CMD_XTERM_RTM:
3764                 return screen_XTERM_RTM(screen, seq);
3765         case TERM_CMD_XTERM_SACL1:
3766                 return screen_XTERM_SACL1(screen, seq);
3767         case TERM_CMD_XTERM_SACL2:
3768                 return screen_XTERM_SACL2(screen, seq);
3769         case TERM_CMD_XTERM_SACL3:
3770                 return screen_XTERM_SACL3(screen, seq);
3771         case TERM_CMD_XTERM_SDCS:
3772                 return screen_XTERM_SDCS(screen, seq);
3773         case TERM_CMD_XTERM_SGFX:
3774                 return screen_XTERM_SGFX(screen, seq);
3775         case TERM_CMD_XTERM_SPM:
3776                 return screen_XTERM_SPM(screen, seq);
3777         case TERM_CMD_XTERM_SRV:
3778                 return screen_XTERM_SRV(screen, seq);
3779         case TERM_CMD_XTERM_STM:
3780                 return screen_XTERM_STM(screen, seq);
3781         case TERM_CMD_XTERM_SUCS:
3782                 return screen_XTERM_SUCS(screen, seq);
3783         case TERM_CMD_XTERM_WM:
3784                 return screen_XTERM_WM(screen, seq);
3785         }
3786
3787         return 0;
3788 }
3789
3790 unsigned int term_screen_get_width(term_screen *screen) {
3791         assert_return(screen, -EINVAL);
3792
3793         return screen->page->width;
3794 }
3795
3796 unsigned int term_screen_get_height(term_screen *screen) {
3797         assert_return(screen, -EINVAL);
3798
3799         return screen->page->height;
3800 }
3801
3802 uint64_t term_screen_get_age(term_screen *screen) {
3803         assert_return(screen, 0);
3804
3805         return screen->age;
3806 }
3807
3808 int term_screen_feed_text(term_screen *screen, const uint8_t *in, size_t size) {
3809         uint32_t *ucs4_str;
3810         size_t i, j, ucs4_len;
3811         const term_seq *seq;
3812         int r;
3813
3814         assert_return(screen, -EINVAL);
3815
3816         ++screen->age;
3817
3818         /* Feed bytes into utf8 decoder and handle parsed ucs4 chars. We always
3819          * treat data as UTF-8, but the parser makes sure to fall back to raw
3820          * 8bit mode if the stream is not valid UTF-8. This should be more than
3821          * enough to support old 7bit/8bit modes. */
3822         for (i = 0; i < size; ++i) {
3823                 ucs4_len = term_utf8_decode(&screen->utf8, &ucs4_str, in[i]);
3824                 for (j = 0; j < ucs4_len; ++j) {
3825                         r = term_parser_feed(screen->parser, &seq, ucs4_str[j]);
3826                         if (r < 0) {
3827                                 return r;
3828                         } else if (r != TERM_SEQ_NONE) {
3829                                 r = screen_feed_cmd(screen, seq);
3830                                 if (r < 0)
3831                                         return r;
3832                         }
3833                 }
3834         }
3835
3836         return 0;
3837 }
3838
3839 static char *screen_map_key(term_screen *screen,
3840                             char *p,
3841                             const uint32_t *keysyms,
3842                             size_t n_syms,
3843                             uint32_t ascii,
3844                             const uint32_t *ucs4,
3845                             unsigned int mods) {
3846         char ch, ch2, ch_mods;
3847         uint32_t v;
3848         size_t i;
3849
3850         /* TODO: All these key-mappings need to be verified. Public information
3851          * on those mappings is pretty scarce and every emulator seems to do it
3852          * slightly differently.
3853          * A lot of mappings are also missing. */
3854
3855         if (n_syms < 1)
3856                 return p;
3857
3858         if (n_syms == 1)
3859                 v = keysyms[0];
3860         else
3861                 v = XKB_KEY_NoSymbol;
3862
3863         /* In some mappings, the modifiers are encoded as CSI parameters. The
3864          * encoding is rather arbitrary, but seems to work. */
3865         ch_mods = 0;
3866         switch (mods & (TERM_KBDMOD_SHIFT | TERM_KBDMOD_ALT | TERM_KBDMOD_CTRL)) {
3867         case TERM_KBDMOD_SHIFT:
3868                 ch_mods = '2';
3869                 break;
3870         case TERM_KBDMOD_ALT:
3871                 ch_mods = '3';
3872                 break;
3873         case TERM_KBDMOD_SHIFT | TERM_KBDMOD_ALT:
3874                 ch_mods = '4';
3875                 break;
3876         case TERM_KBDMOD_CTRL:
3877                 ch_mods = '5';
3878                 break;
3879         case TERM_KBDMOD_CTRL | TERM_KBDMOD_SHIFT:
3880                 ch_mods = '6';
3881                 break;
3882         case TERM_KBDMOD_CTRL | TERM_KBDMOD_ALT:
3883                 ch_mods = '7';
3884                 break;
3885         case TERM_KBDMOD_CTRL | TERM_KBDMOD_SHIFT | TERM_KBDMOD_ALT:
3886                 ch_mods = '8';
3887                 break;
3888         }
3889
3890         /* A user might actually use multiple layouts for keyboard
3891          * input. @keysyms[0] contains the actual keysym that the user
3892          * used. But if this keysym is not in the ascii range, the
3893          * input handler does check all other layouts that the user
3894          * specified whether one of them maps the key to some ASCII
3895          * keysym and provides this via @ascii. We always use the real
3896          * keysym except when handling CTRL+<XY> shortcuts we use the
3897          * ascii keysym. This is for compatibility to xterm et. al. so
3898          * ctrl+c always works regardless of the currently active
3899          * keyboard layout. But if no ascii-sym is found, we still use
3900          * the real keysym. */
3901         if (ascii == XKB_KEY_NoSymbol)
3902                 ascii = v;
3903
3904         /* map CTRL+<ascii> */
3905         if (mods & TERM_KBDMOD_CTRL) {
3906                 switch (ascii) {
3907                 case 0x60 ... 0x7e:
3908                         /* Right hand side is mapped to the left and then
3909                          * treated equally. Fall through to left-hand side.. */
3910                         ascii -= 0x20;
3911                 case 0x20 ... 0x5f:
3912                         /* Printable ASCII is mapped 1-1 in XKB and in
3913                          * combination with CTRL bit 7 is flipped. This
3914                          * is equivalent to the caret-notation. */
3915                         *p++ = ascii ^ 0x40;
3916                         return p;
3917                 }
3918         }
3919
3920         /* map cursor keys */
3921         ch = 0;
3922         switch (v) {
3923         case XKB_KEY_Up:
3924                 ch = 'A';
3925                 break;
3926         case XKB_KEY_Down:
3927                 ch = 'B';
3928                 break;
3929         case XKB_KEY_Right:
3930                 ch = 'C';
3931                 break;
3932         case XKB_KEY_Left:
3933                 ch = 'D';
3934                 break;
3935         case XKB_KEY_Home:
3936                 ch = 'H';
3937                 break;
3938         case XKB_KEY_End:
3939                 ch = 'F';
3940                 break;
3941         }
3942         if (ch) {
3943                 *p++ = 0x1b;
3944                 if (screen->flags & TERM_FLAG_CURSOR_KEYS)
3945                         *p++ = 'O';
3946                 else
3947                         *p++ = '[';
3948                 if (ch_mods) {
3949                         *p++ = '1';
3950                         *p++ = ';';
3951                         *p++ = ch_mods;
3952                 }
3953                 *p++ = ch;
3954                 return p;
3955         }
3956
3957         /* map action keys */
3958         ch = 0;
3959         switch (v) {
3960         case XKB_KEY_Find:
3961                 ch = '1';
3962                 break;
3963         case XKB_KEY_Insert:
3964                 ch = '2';
3965                 break;
3966         case XKB_KEY_Delete:
3967                 ch = '3';
3968                 break;
3969         case XKB_KEY_Select:
3970                 ch = '4';
3971                 break;
3972         case XKB_KEY_Page_Up:
3973                 ch = '5';
3974                 break;
3975         case XKB_KEY_Page_Down:
3976                 ch = '6';
3977                 break;
3978         }
3979         if (ch) {
3980                 *p++ = 0x1b;
3981                 *p++ = '[';
3982                 *p++ = ch;
3983                 if (ch_mods) {
3984                         *p++ = ';';
3985                         *p++ = ch_mods;
3986                 }
3987                 *p++ = '~';
3988                 return p;
3989         }
3990
3991         /* map lower function keys */
3992         ch = 0;
3993         switch (v) {
3994         case XKB_KEY_F1:
3995                 ch = 'P';
3996                 break;
3997         case XKB_KEY_F2:
3998                 ch = 'Q';
3999                 break;
4000         case XKB_KEY_F3:
4001                 ch = 'R';
4002                 break;
4003         case XKB_KEY_F4:
4004                 ch = 'S';
4005                 break;
4006         }
4007         if (ch) {
4008                 if (ch_mods) {
4009                         *p++ = 0x1b;
4010                         *p++ = '[';
4011                         *p++ = '1';
4012                         *p++ = ';';
4013                         *p++ = ch_mods;
4014                         *p++ = ch;
4015                 } else {
4016                         *p++ = 0x1b;
4017                         *p++ = 'O';
4018                         *p++ = ch;
4019                 }
4020
4021                 return p;
4022         }
4023
4024         /* map upper function keys */
4025         ch = 0;
4026         ch2 = 0;
4027         switch (v) {
4028         case XKB_KEY_F5:
4029                 ch = '1';
4030                 ch2 = '5';
4031                 break;
4032         case XKB_KEY_F6:
4033                 ch = '1';
4034                 ch2 = '7';
4035                 break;
4036         case XKB_KEY_F7:
4037                 ch = '1';
4038                 ch2 = '8';
4039                 break;
4040         case XKB_KEY_F8:
4041                 ch = '1';
4042                 ch2 = '9';
4043                 break;
4044         case XKB_KEY_F9:
4045                 ch = '2';
4046                 ch2 = '0';
4047                 break;
4048         case XKB_KEY_F10:
4049                 ch = '2';
4050                 ch2 = '1';
4051                 break;
4052         case XKB_KEY_F11:
4053                 ch = '2';
4054                 ch2 = '2';
4055                 break;
4056         case XKB_KEY_F12:
4057                 ch = '2';
4058                 ch2 = '3';
4059                 break;
4060         }
4061         if (ch) {
4062                 *p++ = 0x1b;
4063                 *p++ = '[';
4064                 *p++ = ch;
4065                 if (ch2)
4066                         *p++ = ch2;
4067                 if (ch_mods) {
4068                         *p++ = ';';
4069                         *p++ = ch_mods;
4070                 }
4071                 *p++ = '~';
4072                 return p;
4073         }
4074
4075         /* map special keys */
4076         switch (v) {
4077         case 0xff08: /* XKB_KEY_BackSpace */
4078         case 0xff09: /* XKB_KEY_Tab */
4079         case 0xff0a: /* XKB_KEY_Linefeed */
4080         case 0xff0b: /* XKB_KEY_Clear */
4081         case 0xff15: /* XKB_KEY_Sys_Req */
4082         case 0xff1b: /* XKB_KEY_Escape */
4083         case 0xffff: /* XKB_KEY_Delete */
4084                 *p++ = v - 0xff00;
4085                 return p;
4086         case 0xff13: /* XKB_KEY_Pause */
4087                 /* TODO: What should we do with this key?
4088                  * Sending XOFF is awful as there is no simple
4089                  * way on modern keyboards to send XON again.
4090                  * If someone wants this, we can re-eanble
4091                  * optionally. */
4092                 return p;
4093         case 0xff14: /* XKB_KEY_Scroll_Lock */
4094                 /* TODO: What should we do on scroll-lock?
4095                  * Sending 0x14 is what the specs say but it is
4096                  * not used today the way most users would
4097                  * expect so we disable it. If someone wants
4098                  * this, we can re-enable it (optionally). */
4099                 return p;
4100         case XKB_KEY_Return:
4101                 *p++ = 0x0d;
4102                 if (screen->flags & TERM_FLAG_NEWLINE_MODE)
4103                         *p++ = 0x0a;
4104                 return p;
4105         case XKB_KEY_ISO_Left_Tab:
4106                 *p++ = 0x09;
4107                 return p;
4108         }
4109
4110         /* map unicode keys */
4111         for (i = 0; i < n_syms; ++i)
4112                 p += term_utf8_encode(p, ucs4[i]);
4113
4114         return p;
4115 }
4116
4117 int term_screen_feed_keyboard(term_screen *screen,
4118                               const uint32_t *keysyms,
4119                               size_t n_syms,
4120                               uint32_t ascii,
4121                               const uint32_t *ucs4,
4122                               unsigned int mods) {
4123         _cleanup_free_ char *dyn = NULL;
4124         static const size_t padding = 1;
4125         char buf[128], *start, *p;
4126
4127         assert_return(screen, -EINVAL);
4128
4129         /* allocate buffer if too small */
4130         start = buf;
4131         if (4 * n_syms + padding > sizeof(buf)) {
4132                 dyn = malloc(4 * n_syms + padding);
4133                 if (!dyn)
4134                         return -ENOMEM;
4135
4136                 start = dyn;
4137         }
4138
4139         /* reserve prefix space */
4140         start += padding;
4141         p = start;
4142
4143         p = screen_map_key(screen, p, keysyms, n_syms, ascii, ucs4, mods);
4144         if (!p || p - start < 1)
4145                 return 0;
4146
4147         /* The ALT modifier causes ESC to be prepended to any key-stroke. We
4148          * already accounted for that buffer space above, so simply prepend it
4149          * here.
4150          * TODO: is altSendsEscape a suitable default? What are the semantics
4151          * exactly? Is it used in C0/C1 conversion? Is it prepended if there
4152          * already is an escape character? */
4153         if (mods & TERM_KBDMOD_ALT && *start != 0x1b)
4154                 *--start = 0x1b;
4155
4156         /* turn C0 into C1 */
4157         if (!(screen->flags & TERM_FLAG_7BIT_MODE) && p - start >= 2)
4158                 if (start[0] == 0x1b && start[1] >= 0x40 && start[1] <= 0x5f)
4159                         *++start ^= 0x40;
4160
4161         return screen_write(screen, start, p - start);
4162 }
4163
4164 int term_screen_resize(term_screen *screen, unsigned int x, unsigned int y) {
4165         unsigned int i;
4166         uint8_t *t;
4167         int r;
4168
4169         assert_return(screen, -EINVAL);
4170
4171         r = term_page_reserve(screen->page_main, x, y, &screen->state.attr, screen->age);
4172         if (r < 0)
4173                 return r;
4174
4175         r = term_page_reserve(screen->page_alt, x, y, &screen->state.attr, screen->age);
4176         if (r < 0)
4177                 return r;
4178
4179         if (x > screen->n_tabs) {
4180                 t = realloc(screen->tabs, (x + 7) / 8);
4181                 if (!t)
4182                         return -ENOMEM;
4183
4184                 screen->tabs = t;
4185                 screen->n_tabs = x;
4186         }
4187
4188         for (i = (screen->page->width + 7) / 8 * 8; i < x; i += 8)
4189                 screen->tabs[i / 8] = 0x1;
4190
4191         term_page_resize(screen->page_main, x, y, &screen->state.attr, screen->age, screen->history);
4192         term_page_resize(screen->page_alt, x, y, &screen->state.attr, screen->age, NULL);
4193
4194         screen->state.cursor_x = screen_clamp_x(screen, screen->state.cursor_x);
4195         screen->state.cursor_y = screen_clamp_x(screen, screen->state.cursor_y);
4196         screen_cursor_clear_wrap(screen);
4197
4198         return 0;
4199 }
4200
4201 void term_screen_soft_reset(term_screen *screen) {
4202         unsigned int i;
4203
4204         assert(screen);
4205
4206         screen->g0 = &term_unicode_lower;
4207         screen->g1 = &term_unicode_upper;
4208         screen->g2 = &term_unicode_lower;
4209         screen->g3 = &term_unicode_upper;
4210         screen->state.attr = screen->default_attr;
4211         screen->state.gl = &screen->g0;
4212         screen->state.gr = &screen->g1;
4213         screen->state.glt = NULL;
4214         screen->state.grt = NULL;
4215         screen->state.auto_wrap = 0;
4216         screen->state.origin_mode = 0;
4217
4218         screen->saved = screen->state;
4219         screen->saved.cursor_x = 0;
4220         screen->saved.cursor_y = 0;
4221         screen->saved_alt = screen->saved;
4222
4223         screen->page = screen->page_main;
4224         screen->history = screen->history_main;
4225         screen->flags = TERM_FLAG_7BIT_MODE;
4226         screen->conformance_level = TERM_CONFORMANCE_LEVEL_VT400;
4227
4228         for (i = 0; i < screen->page->width; i += 8)
4229                 screen->tabs[i / 8] = 0x1;
4230
4231         term_page_set_scroll_region(screen->page_main, 0, screen->page->height);
4232         term_page_set_scroll_region(screen->page_alt, 0, screen->page->height);
4233 }
4234
4235 void term_screen_hard_reset(term_screen *screen) {
4236         assert(screen);
4237
4238         term_screen_soft_reset(screen);
4239         zero(screen->utf8);
4240         screen->state.cursor_x = 0;
4241         screen->state.cursor_y = 0;
4242         term_page_erase(screen->page_main, 0, 0, screen->page->width, screen->page->height, &screen->state.attr, screen->age, false);
4243         term_page_erase(screen->page_alt, 0, 0, screen->page->width, screen->page->height, &screen->state.attr, screen->age, false);
4244 }
4245
4246 int term_screen_set_answerback(term_screen *screen, const char *answerback) {
4247         char *t = NULL;
4248
4249         assert_return(screen, -EINVAL);
4250
4251         if (answerback) {
4252                 t = strdup(answerback);
4253                 if (!t)
4254                         return -ENOMEM;
4255         }
4256
4257         free(screen->answerback);
4258         screen->answerback = t;
4259
4260         return 0;
4261 }
4262
4263 int term_screen_draw(term_screen *screen,
4264                      int (*draw_fn) (term_screen *screen,
4265                                      void *userdata,
4266                                      unsigned int x,
4267                                      unsigned int y,
4268                                      const term_attr *attr,
4269                                      const uint32_t *ch,
4270                                      size_t n_ch,
4271                                      unsigned int ch_width),
4272                      void *userdata,
4273                      uint64_t *fb_age) {
4274         uint64_t cell_age, line_age, age = 0;
4275         term_charbuf_t ch_buf;
4276         const uint32_t *ch_str;
4277         unsigned int i, j, cw;
4278         term_page *page;
4279         term_line *line;
4280         term_cell *cell;
4281         size_t ch_n;
4282         int r;
4283
4284         assert(screen);
4285         assert(draw_fn);
4286
4287         if (fb_age)
4288                 age = *fb_age;
4289
4290         page = screen->page;
4291
4292         for (j = 0; j < page->height; ++j) {
4293                 line = page->lines[j];
4294                 line_age = MAX(line->age, page->age);
4295
4296                 for (i = 0; i < page->width; ++i) {
4297                         term_attr attr;
4298
4299                         cell = &line->cells[i];
4300                         cell_age = MAX(cell->age, line_age);
4301
4302                         if (age != 0 && cell_age <= age)
4303                                 continue;
4304
4305                         ch_str = term_char_resolve(cell->ch, &ch_n, &ch_buf);
4306
4307                         /* Character-width of 0 is used for cleared cells.
4308                          * Always treat this as single-cell character, so
4309                          * renderers can assume ch_width is set properpy. */
4310                         cw = MAX(cell->cwidth, 1U);
4311
4312                         attr = cell->attr;
4313                         if (i == screen->state.cursor_x && j == screen->state.cursor_y &&
4314                             !(screen->flags & TERM_FLAG_HIDE_CURSOR))
4315                                 attr.inverse ^= 1;
4316
4317                         r = draw_fn(screen,
4318                                     userdata,
4319                                     i,
4320                                     j,
4321                                     &attr,
4322                                     ch_str,
4323                                     ch_n,
4324                                     cw);
4325                         if (r != 0)
4326                                 return r;
4327                 }
4328         }
4329
4330         if (fb_age)
4331                 *fb_age = screen->age;
4332
4333         return 0;
4334 }