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