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