chiark / gitweb /
terminal/idev: add helper to match keyboard shortcuts
[elogind.git] / src / libsystemd-terminal / term-internal.h
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 #pragma once
23
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include "term.h"
28 #include "util.h"
29
30 typedef struct term_char term_char_t;
31 typedef struct term_charbuf term_charbuf_t;
32
33 typedef struct term_cell term_cell;
34 typedef struct term_line term_line;
35
36 typedef struct term_page term_page;
37 typedef struct term_history term_history;
38
39 typedef uint32_t term_charset[96];
40
41 /*
42  * Miscellaneous
43  * Sundry things and external helpers.
44  */
45
46 int mk_wcwidth(wchar_t ucs4);
47 int mk_wcwidth_cjk(wchar_t ucs4);
48 int mk_wcswidth(const wchar_t *str, size_t len);
49 int mk_wcswidth_cjk(const wchar_t *str, size_t len);
50
51 /*
52  * Characters
53  * Each cell in a terminal page contains only a single character. This is
54  * usually a single UCS-4 value. However, Unicode allows combining-characters,
55  * therefore, the number of UCS-4 characters per cell must be unlimited. The
56  * term_char_t object wraps the internal combining char API so it can be
57  * treated as a single object.
58  */
59
60 struct term_char {
61         /* never access this value directly */
62         uint64_t _value;
63 };
64
65 struct term_charbuf {
66         /* 3 bytes + zero-terminator */
67         uint32_t buf[4];
68 };
69
70 #define TERM_CHAR_INIT(_val) ((term_char_t){ ._value = (_val) })
71 #define TERM_CHAR_NULL TERM_CHAR_INIT(0)
72
73 term_char_t term_char_set(term_char_t previous, uint32_t append_ucs4);
74 term_char_t term_char_merge(term_char_t base, uint32_t append_ucs4);
75 term_char_t term_char_dup(term_char_t ch);
76 term_char_t term_char_dup_append(term_char_t base, uint32_t append_ucs4);
77
78 const uint32_t *term_char_resolve(term_char_t ch, size_t *s, term_charbuf_t *b);
79 unsigned int term_char_lookup_width(term_char_t ch);
80
81 /* true if @ch is TERM_CHAR_NULL, otherwise false */
82 static inline bool term_char_is_null(term_char_t ch) {
83         return ch._value == 0;
84 }
85
86 /* true if @ch is dynamically allocated and needs to be freed */
87 static inline bool term_char_is_allocated(term_char_t ch) {
88         return !term_char_is_null(ch) && !(ch._value & 0x1);
89 }
90
91 /* true if (a == b), otherwise false; this is (a == b), NOT (*a == *b) */
92 static inline bool term_char_same(term_char_t a, term_char_t b) {
93         return a._value == b._value;
94 }
95
96 /* true if (*a == *b), otherwise false; this is implied by (a == b) */
97 static inline bool term_char_equal(term_char_t a, term_char_t b) {
98         const uint32_t *sa, *sb;
99         term_charbuf_t ca, cb;
100         size_t na, nb;
101
102         sa = term_char_resolve(a, &na, &ca);
103         sb = term_char_resolve(b, &nb, &cb);
104         return na == nb && !memcmp(sa, sb, sizeof(*sa) * na);
105 }
106
107 /* free @ch in case it is dynamically allocated */
108 static inline term_char_t term_char_free(term_char_t ch) {
109         if (term_char_is_allocated(ch))
110                 term_char_set(ch, 0);
111
112         return TERM_CHAR_NULL;
113 }
114
115 /* gcc _cleanup_ helpers */
116 #define _term_char_free_ _cleanup_(term_char_freep)
117 static inline void term_char_freep(term_char_t *p) {
118         term_char_free(*p);
119 }
120
121 /*
122  * Cells
123  * The term_cell structure respresents a single cell in a terminal page. It
124  * contains the stored character, the age of the cell and all its attributes.
125  */
126
127 struct term_cell {
128         term_char_t ch;         /* stored char or TERM_CHAR_NULL */
129         term_age_t age;         /* cell age or TERM_AGE_NULL */
130         term_attr attr;         /* cell attributes */
131         unsigned int cwidth;    /* cached term_char_lookup_width(cell->ch) */
132 };
133
134 /*
135  * Lines
136  * Instead of storing cells in a 2D array, we store them in an array of
137  * dynamically allocated lines. This way, scrolling can be implemented very
138  * fast without moving any cells at all. Similarly, the scrollback-buffer is
139  * much simpler to implement.
140  * We use term_line to store a single line. It contains an array of cells, a
141  * fill-state which remembers the amount of blanks on the right side, a
142  * separate age just for the line which can overwrite the age for all cells,
143  * and some management data.
144  */
145
146 struct term_line {
147         term_line *lines_next;          /* linked-list for histories */
148         term_line *lines_prev;          /* linked-list for histories */
149
150         unsigned int width;             /* visible width of line */
151         unsigned int n_cells;           /* # of allocated cells */
152         term_cell *cells;               /* cell-array */
153
154         term_age_t age;                 /* line age */
155         unsigned int fill;              /* # of valid cells; starting left */
156 };
157
158 int term_line_new(term_line **out);
159 term_line *term_line_free(term_line *line);
160
161 #define _term_line_free_ _cleanup_(term_line_freep)
162 DEFINE_TRIVIAL_CLEANUP_FUNC(term_line*, term_line_free);
163
164 int term_line_reserve(term_line *line, unsigned int width, const term_attr *attr, term_age_t age, unsigned int protect_width);
165 void term_line_set_width(term_line *line, unsigned int width);
166 void term_line_write(term_line *line, unsigned int pos_x, term_char_t ch, unsigned int cwidth, const term_attr *attr, term_age_t age, bool insert_mode);
167 void term_line_insert(term_line *line, unsigned int from, unsigned int num, const term_attr *attr, term_age_t age);
168 void term_line_delete(term_line *line, unsigned int from, unsigned int num, const term_attr *attr, term_age_t age);
169 void term_line_append_combchar(term_line *line, unsigned int pos_x, uint32_t ucs4, term_age_t age);
170 void term_line_erase(term_line *line, unsigned int from, unsigned int num, const term_attr *attr, term_age_t age, bool keep_protected);
171 void term_line_reset(term_line *line, const term_attr *attr, term_age_t age);
172
173 void term_line_link(term_line *line, term_line **first, term_line **last);
174 void term_line_link_tail(term_line *line, term_line **first, term_line **last);
175 void term_line_unlink(term_line *line, term_line **first, term_line **last);
176
177 #define TERM_LINE_LINK(_line, _head) term_line_link((_line), &(_head)->lines_first, &(_head)->lines_last)
178 #define TERM_LINE_LINK_TAIL(_line, _head) term_line_link_tail((_line), &(_head)->lines_first, &(_head)->lines_last)
179 #define TERM_LINE_UNLINK(_line, _head) term_line_unlink((_line), &(_head)->lines_first, &(_head)->lines_last)
180
181 /*
182  * Pages
183  * A page represents the 2D table containing all cells of a terminal. It stores
184  * lines as an array of pointers so scrolling becomes a simple line-shuffle
185  * operation.
186  * Scrolling is always targeted only at the scroll-region defined via scroll_idx
187  * and scroll_num. The fill-state keeps track of the number of touched lines in
188  * the scroll-region. @width and @height describe the visible region of the page
189  * and are guaranteed to be allocated at all times.
190  */
191
192 struct term_page {
193         term_age_t age;                 /* page age */
194
195         term_line **lines;              /* array of line-pointers */
196         term_line **line_cache;         /* cache for temporary operations */
197         unsigned int n_lines;           /* # of allocated lines */
198
199         unsigned int width;             /* width of visible area */
200         unsigned int height;            /* height of visible area */
201         unsigned int scroll_idx;        /* scrolling-region start index */
202         unsigned int scroll_num;        /* scrolling-region length in lines */
203         unsigned int scroll_fill;       /* # of valid scroll-lines */
204 };
205
206 int term_page_new(term_page **out);
207 term_page *term_page_free(term_page *page);
208
209 #define _term_page_free_ _cleanup_(term_page_freep)
210 DEFINE_TRIVIAL_CLEANUP_FUNC(term_page*, term_page_free);
211
212 term_cell *term_page_get_cell(term_page *page, unsigned int x, unsigned int y);
213
214 int term_page_reserve(term_page *page, unsigned int cols, unsigned int rows, const term_attr *attr, term_age_t age);
215 void term_page_resize(term_page *page, unsigned int cols, unsigned int rows, const term_attr *attr, term_age_t age, term_history *history);
216 void term_page_write(term_page *page, unsigned int pos_x, unsigned int pos_y, term_char_t ch, unsigned int cwidth, const term_attr *attr, term_age_t age, bool insert_mode);
217 void term_page_insert_cells(term_page *page, unsigned int from_x, unsigned int from_y, unsigned int num, const term_attr *attr, term_age_t age);
218 void term_page_delete_cells(term_page *page, unsigned int from_x, unsigned int from_y, unsigned int num, const term_attr *attr, term_age_t age);
219 void term_page_append_combchar(term_page *page, unsigned int pos_x, unsigned int pos_y, uint32_t ucs4, term_age_t age);
220 void term_page_erase(term_page *page, unsigned int from_x, unsigned int from_y, unsigned int to_x, unsigned int to_y, const term_attr *attr, term_age_t age, bool keep_protected);
221 void term_page_reset(term_page *page, const term_attr *attr, term_age_t age);
222
223 void term_page_set_scroll_region(term_page *page, unsigned int idx, unsigned int num);
224 void term_page_scroll_up(term_page *page, unsigned int num, const term_attr *attr, term_age_t age, term_history *history);
225 void term_page_scroll_down(term_page *page, unsigned int num, const term_attr *attr, term_age_t age, term_history *history);
226 void term_page_insert_lines(term_page *page, unsigned int pos_y, unsigned int num, const term_attr *attr, term_age_t age);
227 void term_page_delete_lines(term_page *page, unsigned int pos_y, unsigned int num, const term_attr *attr, term_age_t age);
228
229 /*
230  * Histories
231  * Scroll-back buffers use term_history objects to store scroll-back lines. A
232  * page is independent of the history used. All page operations that modify a
233  * history take it as separate argument. You're free to pass NULL at all times
234  * if no history should be used.
235  * Lines are stored in a linked list as no complex operations are ever done on
236  * history lines, besides pushing/poping. Note that history lines do not have a
237  * guaranteed minimum length. Any kind of line might be stored there. Missing
238  * cells should be cleared to the background color.
239  */
240
241 struct term_history {
242         term_line *lines_first;
243         term_line *lines_last;
244         unsigned int n_lines;
245         unsigned int max_lines;
246 };
247
248 int term_history_new(term_history **out);
249 term_history *term_history_free(term_history *history);
250
251 #define _term_history_free_ _cleanup_(term_history_freep)
252 DEFINE_TRIVIAL_CLEANUP_FUNC(term_history*, term_history_free);
253
254 void term_history_clear(term_history *history);
255 void term_history_trim(term_history *history, unsigned int max);
256 void term_history_push(term_history *history, term_line *line);
257 term_line *term_history_pop(term_history *history, unsigned int reserve_width, const term_attr *attr, term_age_t age);
258 unsigned int term_history_peek(term_history *history, unsigned int max, unsigned int reserve_width, const term_attr *attr, term_age_t age);
259
260 /*
261  * Parsers
262  * The term_parser object parses control-sequences for both host and terminal
263  * side. Based on this parser, there is a set of command-parsers that take a
264  * term_seq sequence and returns the command it represents. This is different
265  * for host and terminal side so a different set of parsers is provided.
266  */
267
268 enum {
269         TERM_SEQ_NONE,                  /* placeholder, no sequence parsed */
270
271         TERM_SEQ_IGNORE,                /* no-op character */
272         TERM_SEQ_GRAPHIC,               /* graphic character */
273         TERM_SEQ_CONTROL,               /* control character */
274         TERM_SEQ_ESCAPE,                /* escape sequence */
275         TERM_SEQ_CSI,                   /* control sequence function */
276         TERM_SEQ_DCS,                   /* device control string */
277         TERM_SEQ_OSC,                   /* operating system control */
278
279         TERM_SEQ_CNT
280 };
281
282 enum {
283         /* these must be kept compatible to (1U << (ch - 0x20)) */
284
285         TERM_SEQ_FLAG_SPACE             = (1U <<  0),   /* char:   */
286         TERM_SEQ_FLAG_BANG              = (1U <<  1),   /* char: ! */
287         TERM_SEQ_FLAG_DQUOTE            = (1U <<  2),   /* char: " */
288         TERM_SEQ_FLAG_HASH              = (1U <<  3),   /* char: # */
289         TERM_SEQ_FLAG_CASH              = (1U <<  4),   /* char: $ */
290         TERM_SEQ_FLAG_PERCENT           = (1U <<  5),   /* char: % */
291         TERM_SEQ_FLAG_AND               = (1U <<  6),   /* char: & */
292         TERM_SEQ_FLAG_SQUOTE            = (1U <<  7),   /* char: ' */
293         TERM_SEQ_FLAG_POPEN             = (1U <<  8),   /* char: ( */
294         TERM_SEQ_FLAG_PCLOSE            = (1U <<  9),   /* char: ) */
295         TERM_SEQ_FLAG_MULT              = (1U << 10),   /* char: * */
296         TERM_SEQ_FLAG_PLUS              = (1U << 11),   /* char: + */
297         TERM_SEQ_FLAG_COMMA             = (1U << 12),   /* char: , */
298         TERM_SEQ_FLAG_MINUS             = (1U << 13),   /* char: - */
299         TERM_SEQ_FLAG_DOT               = (1U << 14),   /* char: . */
300         TERM_SEQ_FLAG_SLASH             = (1U << 15),   /* char: / */
301
302         /* 16-35 is reserved for numbers; unused */
303
304         /* COLON is reserved            = (1U << 26),      char: : */
305         /* SEMICOLON is reserved        = (1U << 27),      char: ; */
306         TERM_SEQ_FLAG_LT                = (1U << 28),   /* char: < */
307         TERM_SEQ_FLAG_EQUAL             = (1U << 29),   /* char: = */
308         TERM_SEQ_FLAG_GT                = (1U << 30),   /* char: > */
309         TERM_SEQ_FLAG_WHAT              = (1U << 31),   /* char: ? */
310 };
311
312 enum {
313         TERM_CMD_NONE,                          /* placeholder */
314         TERM_CMD_GRAPHIC,                       /* graphics character */
315
316         TERM_CMD_BEL,                           /* bell */
317         TERM_CMD_BS,                            /* backspace */
318         TERM_CMD_CBT,                           /* cursor-backward-tabulation */
319         TERM_CMD_CHA,                           /* cursor-horizontal-absolute */
320         TERM_CMD_CHT,                           /* cursor-horizontal-forward-tabulation */
321         TERM_CMD_CNL,                           /* cursor-next-line */
322         TERM_CMD_CPL,                           /* cursor-previous-line */
323         TERM_CMD_CR,                            /* carriage-return */
324         TERM_CMD_CUB,                           /* cursor-backward */
325         TERM_CMD_CUD,                           /* cursor-down */
326         TERM_CMD_CUF,                           /* cursor-forward */
327         TERM_CMD_CUP,                           /* cursor-position */
328         TERM_CMD_CUU,                           /* cursor-up */
329         TERM_CMD_DA1,                           /* primary-device-attributes */
330         TERM_CMD_DA2,                           /* secondary-device-attributes */
331         TERM_CMD_DA3,                           /* tertiary-device-attributes */
332         TERM_CMD_DC1,                           /* device-control-1 or XON */
333         TERM_CMD_DC3,                           /* device-control-3 or XOFF */
334         TERM_CMD_DCH,                           /* delete-character */
335         TERM_CMD_DECALN,                        /* screen-alignment-pattern */
336         TERM_CMD_DECANM,                        /* ansi-mode */
337         TERM_CMD_DECBI,                         /* back-index */
338         TERM_CMD_DECCARA,                       /* change-attributes-in-rectangular-area */
339         TERM_CMD_DECCRA,                        /* copy-rectangular-area */
340         TERM_CMD_DECDC,                         /* delete-column */
341         TERM_CMD_DECDHL_BH,                     /* double-width-double-height-line: bottom half */
342         TERM_CMD_DECDHL_TH,                     /* double-width-double-height-line: top half */
343         TERM_CMD_DECDWL,                        /* double-width-single-height-line */
344         TERM_CMD_DECEFR,                        /* enable-filter-rectangle */
345         TERM_CMD_DECELF,                        /* enable-local-functions */
346         TERM_CMD_DECELR,                        /* enable-locator-reporting */
347         TERM_CMD_DECERA,                        /* erase-rectangular-area */
348         TERM_CMD_DECFI,                         /* forward-index */
349         TERM_CMD_DECFRA,                        /* fill-rectangular-area */
350         TERM_CMD_DECIC,                         /* insert-column */
351         TERM_CMD_DECID,                         /* return-terminal-id */
352         TERM_CMD_DECINVM,                       /* invoke-macro */
353         TERM_CMD_DECKBD,                        /* keyboard-language-selection */
354         TERM_CMD_DECKPAM,                       /* keypad-application-mode */
355         TERM_CMD_DECKPNM,                       /* keypad-numeric-mode */
356         TERM_CMD_DECLFKC,                       /* local-function-key-control */
357         TERM_CMD_DECLL,                         /* load-leds */
358         TERM_CMD_DECLTOD,                       /* load-time-of-day */
359         TERM_CMD_DECPCTERM,                     /* pcterm-mode */
360         TERM_CMD_DECPKA,                        /* program-key-action */
361         TERM_CMD_DECPKFMR,                      /* program-key-free-memory-report */
362         TERM_CMD_DECRARA,                       /* reverse-attributes-in-rectangular-area */
363         TERM_CMD_DECRC,                         /* restore-cursor */
364         TERM_CMD_DECREQTPARM,                   /* request-terminal-parameters */
365         TERM_CMD_DECRPKT,                       /* report-key-type */
366         TERM_CMD_DECRQCRA,                      /* request-checksum-of-rectangular-area */
367         TERM_CMD_DECRQDE,                       /* request-display-extent */
368         TERM_CMD_DECRQKT,                       /* request-key-type */
369         TERM_CMD_DECRQLP,                       /* request-locator-position */
370         TERM_CMD_DECRQM_ANSI,                   /* request-mode-ansi */
371         TERM_CMD_DECRQM_DEC,                    /* request-mode-dec */
372         TERM_CMD_DECRQPKFM,                     /* request-program-key-free-memory */
373         TERM_CMD_DECRQPSR,                      /* request-presentation-state-report */
374         TERM_CMD_DECRQTSR,                      /* request-terminal-state-report */
375         TERM_CMD_DECRQUPSS,                     /* request-user-preferred-supplemental-set */
376         TERM_CMD_DECSACE,                       /* select-attribute-change-extent */
377         TERM_CMD_DECSASD,                       /* select-active-status-display */
378         TERM_CMD_DECSC,                         /* save-cursor */
379         TERM_CMD_DECSCA,                        /* select-character-protection-attribute */
380         TERM_CMD_DECSCL,                        /* select-conformance-level */
381         TERM_CMD_DECSCP,                        /* select-communication-port */
382         TERM_CMD_DECSCPP,                       /* select-columns-per-page */
383         TERM_CMD_DECSCS,                        /* select-communication-speed */
384         TERM_CMD_DECSCUSR,                      /* set-cursor-style */
385         TERM_CMD_DECSDDT,                       /* select-disconnect-delay-time */
386         TERM_CMD_DECSDPT,                       /* select-digital-printed-data-type */
387         TERM_CMD_DECSED,                        /* selective-erase-in-display */
388         TERM_CMD_DECSEL,                        /* selective-erase-in-line */
389         TERM_CMD_DECSERA,                       /* selective-erase-rectangular-area */
390         TERM_CMD_DECSFC,                        /* select-flow-control */
391         TERM_CMD_DECSKCV,                       /* set-key-click-volume */
392         TERM_CMD_DECSLCK,                       /* set-lock-key-style */
393         TERM_CMD_DECSLE,                        /* select-locator-events */
394         TERM_CMD_DECSLPP,                       /* set-lines-per-page */
395         TERM_CMD_DECSLRM_OR_SC,                 /* set-left-and-right-margins or save-cursor */
396         TERM_CMD_DECSMBV,                       /* set-margin-bell-volume */
397         TERM_CMD_DECSMKR,                       /* select-modifier-key-reporting */
398         TERM_CMD_DECSNLS,                       /* set-lines-per-screen */
399         TERM_CMD_DECSPP,                        /* set-port-parameter */
400         TERM_CMD_DECSPPCS,                      /* select-pro-printer-character-set */
401         TERM_CMD_DECSPRTT,                      /* select-printer-type */
402         TERM_CMD_DECSR,                         /* secure-reset */
403         TERM_CMD_DECSRFR,                       /* select-refresh-rate */
404         TERM_CMD_DECSSCLS,                      /* set-scroll-speed */
405         TERM_CMD_DECSSDT,                       /* select-status-display-line-type */
406         TERM_CMD_DECSSL,                        /* select-setup-language */
407         TERM_CMD_DECST8C,                       /* set-tab-at-every-8-columns */
408         TERM_CMD_DECSTBM,                       /* set-top-and-bottom-margins */
409         TERM_CMD_DECSTR,                        /* soft-terminal-reset */
410         TERM_CMD_DECSTRL,                       /* set-transmit-rate-limit */
411         TERM_CMD_DECSWBV,                       /* set-warning-bell-volume */
412         TERM_CMD_DECSWL,                        /* single-width-single-height-line */
413         TERM_CMD_DECTID,                        /* select-terminal-id */
414         TERM_CMD_DECTME,                        /* terminal-mode-emulation */
415         TERM_CMD_DECTST,                        /* invoke-confidence-test */
416         TERM_CMD_DL,                            /* delete-line */
417         TERM_CMD_DSR_ANSI,                      /* device-status-report-ansi */
418         TERM_CMD_DSR_DEC,                       /* device-status-report-dec */
419         TERM_CMD_ECH,                           /* erase-character */
420         TERM_CMD_ED,                            /* erase-in-display */
421         TERM_CMD_EL,                            /* erase-in-line */
422         TERM_CMD_ENQ,                           /* enquiry */
423         TERM_CMD_EPA,                           /* end-of-guarded-area */
424         TERM_CMD_FF,                            /* form-feed */
425         TERM_CMD_HPA,                           /* horizontal-position-absolute */
426         TERM_CMD_HPR,                           /* horizontal-position-relative */
427         TERM_CMD_HT,                            /* horizontal-tab */
428         TERM_CMD_HTS,                           /* horizontal-tab-set */
429         TERM_CMD_HVP,                           /* horizontal-and-vertical-position */
430         TERM_CMD_ICH,                           /* insert-character */
431         TERM_CMD_IL,                            /* insert-line */
432         TERM_CMD_IND,                           /* index */
433         TERM_CMD_LF,                            /* line-feed */
434         TERM_CMD_LS1R,                          /* locking-shift-1-right */
435         TERM_CMD_LS2,                           /* locking-shift-2 */
436         TERM_CMD_LS2R,                          /* locking-shift-2-right */
437         TERM_CMD_LS3,                           /* locking-shift-3 */
438         TERM_CMD_LS3R,                          /* locking-shift-3-right */
439         TERM_CMD_MC_ANSI,                       /* media-copy-ansi */
440         TERM_CMD_MC_DEC,                        /* media-copy-dec */
441         TERM_CMD_NEL,                           /* next-line */
442         TERM_CMD_NP,                            /* next-page */
443         TERM_CMD_NULL,                          /* null */
444         TERM_CMD_PP,                            /* preceding-page */
445         TERM_CMD_PPA,                           /* page-position-absolute */
446         TERM_CMD_PPB,                           /* page-position-backward */
447         TERM_CMD_PPR,                           /* page-position-relative */
448         TERM_CMD_RC,                            /* restore-cursor */
449         TERM_CMD_REP,                           /* repeat */
450         TERM_CMD_RI,                            /* reverse-index */
451         TERM_CMD_RIS,                           /* reset-to-initial-state */
452         TERM_CMD_RM_ANSI,                       /* reset-mode-ansi */
453         TERM_CMD_RM_DEC,                        /* reset-mode-dec */
454         TERM_CMD_S7C1T,                         /* set-7bit-c1-terminal */
455         TERM_CMD_S8C1T,                         /* set-8bit-c1-terminal */
456         TERM_CMD_SCS,                           /* select-character-set */
457         TERM_CMD_SD,                            /* scroll-down */
458         TERM_CMD_SGR,                           /* select-graphics-rendition */
459         TERM_CMD_SI,                            /* shift-in */
460         TERM_CMD_SM_ANSI,                       /* set-mode-ansi */
461         TERM_CMD_SM_DEC,                        /* set-mode-dec */
462         TERM_CMD_SO,                            /* shift-out */
463         TERM_CMD_SPA,                           /* start-of-protected-area */
464         TERM_CMD_SS2,                           /* single-shift-2 */
465         TERM_CMD_SS3,                           /* single-shift-3 */
466         TERM_CMD_ST,                            /* string-terminator */
467         TERM_CMD_SU,                            /* scroll-up */
468         TERM_CMD_SUB,                           /* substitute */
469         TERM_CMD_TBC,                           /* tab-clear */
470         TERM_CMD_VPA,                           /* vertical-line-position-absolute */
471         TERM_CMD_VPR,                           /* vertical-line-position-relative */
472         TERM_CMD_VT,                            /* vertical-tab */
473         TERM_CMD_XTERM_CLLHP,                   /* xterm-cursor-lower-left-hp-bugfix */
474         TERM_CMD_XTERM_IHMT,                    /* xterm-initiate-highlight-mouse-tracking*/
475         TERM_CMD_XTERM_MLHP,                    /* xterm-memory-lock-hp-bugfix */
476         TERM_CMD_XTERM_MUHP,                    /* xterm-memory-unlock-hp-bugfix */
477         TERM_CMD_XTERM_RPM,                     /* xterm-restore-private-mode */
478         TERM_CMD_XTERM_RRV,                     /* xterm-reset-resource-value */
479         TERM_CMD_XTERM_RTM,                     /* xterm-reset-title-mode */
480         TERM_CMD_XTERM_SACL1,                   /* xterm-set-ansi-conformance-level-1 */
481         TERM_CMD_XTERM_SACL2,                   /* xterm-set-ansi-conformance-level-2 */
482         TERM_CMD_XTERM_SACL3,                   /* xterm-set-ansi-conformance-level-3 */
483         TERM_CMD_XTERM_SDCS,                    /* xterm-set-default-character-set */
484         TERM_CMD_XTERM_SGFX,                    /* xterm-sixel-graphics */
485         TERM_CMD_XTERM_SPM,                     /* xterm-set-private-mode */
486         TERM_CMD_XTERM_SRV,                     /* xterm-set-resource-value */
487         TERM_CMD_XTERM_STM,                     /* xterm-set-title-mode */
488         TERM_CMD_XTERM_SUCS,                    /* xterm-set-utf8-character-set */
489         TERM_CMD_XTERM_WM,                      /* xterm-window-management */
490
491         TERM_CMD_CNT
492 };
493
494 enum {
495         /*
496          * Charsets: DEC marks charsets according to "Digital Equ. Corp.".
497          *           NRCS marks charsets according to the "National Replacement
498          *           Character Sets". ISO marks charsets according to ISO-8859.
499          * The USERDEF charset is special and can be modified by the host.
500          */
501
502         TERM_CHARSET_NONE,
503
504         /* 96-compat charsets */
505         TERM_CHARSET_ISO_LATIN1_SUPPLEMENTAL,
506         TERM_CHARSET_BRITISH_NRCS = TERM_CHARSET_ISO_LATIN1_SUPPLEMENTAL,
507         TERM_CHARSET_ISO_LATIN2_SUPPLEMENTAL,
508         TERM_CHARSET_AMERICAN_NRCS = TERM_CHARSET_ISO_LATIN2_SUPPLEMENTAL,
509         TERM_CHARSET_ISO_LATIN5_SUPPLEMENTAL,
510         TERM_CHARSET_ISO_GREEK_SUPPLEMENTAL,
511         TERM_CHARSET_ISO_HEBREW_SUPPLEMENTAL,
512         TERM_CHARSET_ISO_LATIN_CYRILLIC,
513
514         TERM_CHARSET_96_CNT,
515
516         /* 94-compat charsets */
517         TERM_CHARSET_DEC_SPECIAL_GRAPHIC = TERM_CHARSET_96_CNT,
518         TERM_CHARSET_DEC_SUPPLEMENTAL,
519         TERM_CHARSET_DEC_TECHNICAL,
520         TERM_CHARSET_CYRILLIC_DEC,
521         TERM_CHARSET_DUTCH_NRCS,
522         TERM_CHARSET_FINNISH_NRCS,
523         TERM_CHARSET_FRENCH_NRCS,
524         TERM_CHARSET_FRENCH_CANADIAN_NRCS,
525         TERM_CHARSET_GERMAN_NRCS,
526         TERM_CHARSET_GREEK_DEC,
527         TERM_CHARSET_GREEK_NRCS,
528         TERM_CHARSET_HEBREW_DEC,
529         TERM_CHARSET_HEBREW_NRCS,
530         TERM_CHARSET_ITALIAN_NRCS,
531         TERM_CHARSET_NORWEGIAN_DANISH_NRCS,
532         TERM_CHARSET_PORTUGUESE_NRCS,
533         TERM_CHARSET_RUSSIAN_NRCS,
534         TERM_CHARSET_SCS_NRCS,
535         TERM_CHARSET_SPANISH_NRCS,
536         TERM_CHARSET_SWEDISH_NRCS,
537         TERM_CHARSET_SWISS_NRCS,
538         TERM_CHARSET_TURKISH_DEC,
539         TERM_CHARSET_TURKISH_NRCS,
540
541         TERM_CHARSET_94_CNT,
542
543         /* special charsets */
544         TERM_CHARSET_USERPREF_SUPPLEMENTAL = TERM_CHARSET_94_CNT,
545
546         TERM_CHARSET_CNT,
547 };
548
549 extern term_charset term_unicode_lower;
550 extern term_charset term_unicode_upper;
551 extern term_charset term_dec_supplemental_graphics;
552 extern term_charset term_dec_special_graphics;
553
554 #define TERM_PARSER_ARG_MAX (16)
555 #define TERM_PARSER_ST_MAX (4096)
556
557 struct term_seq {
558         unsigned int type;
559         unsigned int command;
560         uint32_t terminator;
561         unsigned int intermediates;
562         unsigned int charset;
563         unsigned int n_args;
564         int args[TERM_PARSER_ARG_MAX];
565         unsigned int n_st;
566         char *st;
567 };
568
569 struct term_parser {
570         term_seq seq;
571         size_t st_alloc;
572         unsigned int state;
573
574         bool is_host : 1;
575 };
576
577 /*
578  * Screens
579  * A term_screen object represents the terminal-side of the communication. It
580  * connects the term-parser and term-pages and handles all required commands.
581  * All state is managed by it.
582  */
583
584 enum {
585         TERM_FLAG_7BIT_MODE                     = (1U << 0),    /* 7bit mode (default: off) */
586         TERM_FLAG_HIDE_CURSOR                   = (1U << 1),    /* hide cursor caret (default: off) */
587         TERM_FLAG_INHIBIT_TPARM                 = (1U << 2),    /* do not send TPARM unrequested (default: off) */
588         TERM_FLAG_NEWLINE_MODE                  = (1U << 3),    /* perform carriage-return on line-feeds (default: off) */
589         TERM_FLAG_ORIGIN_MODE                   = (1U << 4),    /* in origin mode, the cursor is bound by the margins (default: off) */
590         TERM_FLAG_PENDING_WRAP                  = (1U << 5),    /* wrap-around is pending */
591         TERM_FLAG_AUTO_WRAP                     = (1U << 6),    /* auto-wrap mode causes line-wraps at line-ends (default: off) */
592         TERM_FLAG_KEYPAD_MODE                   = (1U << 7),    /* application-keypad mode (default: off) */
593         TERM_FLAG_CURSOR_KEYS                   = (1U << 8),    /* enable application cursor-keys (default: off) */
594 };
595
596 enum {
597         TERM_CONFORMANCE_LEVEL_VT52,
598         TERM_CONFORMANCE_LEVEL_VT100,
599         TERM_CONFORMANCE_LEVEL_VT400,
600         TERM_CONFORMANCE_LEVEL_CNT,
601 };
602
603 struct term_screen {
604         unsigned long ref;
605         term_age_t age;
606
607         term_page *page;
608         term_page *page_main;
609         term_page *page_alt;
610         term_history *history;
611         term_history *history_main;
612
613         unsigned int n_tabs;
614         uint8_t *tabs;
615
616         term_utf8 utf8;
617         term_parser *parser;
618
619         term_screen_write_fn write_fn;
620         void *write_fn_data;
621         term_screen_cmd_fn cmd_fn;
622         void *cmd_fn_data;
623
624         unsigned int flags;
625         unsigned int conformance_level;
626         unsigned int cursor_x;
627         unsigned int cursor_y;
628         term_attr attr;
629         term_attr default_attr;
630
631         term_charset **gl;
632         term_charset **gr;
633         term_charset **glt;
634         term_charset **grt;
635         term_charset *g0;
636         term_charset *g1;
637         term_charset *g2;
638         term_charset *g3;
639
640         char *answerback;
641
642         struct {
643                 unsigned int cursor_x;
644                 unsigned int cursor_y;
645                 term_attr attr;
646                 term_charset **gl;
647                 term_charset **gr;
648                 term_charset **glt;
649                 term_charset **grt;
650                 unsigned int flags;
651         } saved;
652 };