From e72e8b1b8e7ffcd32c97260e6a4ef2466591f628 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Tue, 8 Jun 2021 21:06:18 +0100 Subject: [PATCH 1/4] vt: add support for LS2 and LS3 locking shifts --- CHANGELOG.md | 1 + vt.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b96667dd..3b68f2c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ _Private Usage Area_ codepoints to be treated as double-width characters. * OSC 9 desktop notifications (iTerm2 compatible). +* Support for LS2 and LS3 (locking shift) escape sequences. ### Changed diff --git a/vt.c b/vt.c index d0d215f1..97f45c48 100644 --- a/vt.c +++ b/vt.c @@ -388,6 +388,18 @@ action_esc_dispatch(struct terminal *term, uint8_t final) term_reset(term, true); break; + case 'n': + /* LS2 - Locking Shift 2 */ + term->charsets.selected = 2; /* G2 */ + term_update_ascii_printer(term); + break; + + case 'o': + /* LS3 - Locking Shift 3 */ + term->charsets.selected = 3; /* G3 */ + term_update_ascii_printer(term); + break; + case 'D': term_linefeed(term); break; From a2c9c56f1962ce02e71582c06f389e53d1869e90 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Tue, 8 Jun 2021 21:09:40 +0100 Subject: [PATCH 2/4] vt: fix SS2/SS3 escape sequences to act correctly as single shifts These sequences are supposed to affect the next printable ASCII character and then reset to the previous character set, but before this commit they were behaving like locking shifts. --- CHANGELOG.md | 2 ++ terminal.c | 16 ++++++++++++++++ terminal.h | 2 ++ vt.c | 6 ++---- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b68f2c2..1ace3be1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -162,6 +162,8 @@ * Restore `SIGHUP` in spawned processes. * Text reflow performance (https://codeberg.org/dnkl/foot/issues/504). * IL+DL (`CSI Ps L` + `CSI Ps M`) now moves the cursor to column 0. +* SS2 and SS3 (single shift) escape sequences behaving like locking + shifts. ### Security diff --git a/terminal.c b/terminal.c index 3d6c20d4..5ba7b854 100644 --- a/terminal.c +++ b/terminal.c @@ -2839,6 +2839,14 @@ ascii_printer_fast(struct terminal *term, wchar_t wc) xassert(!term->grid->cursor.lcf); } +static void +ascii_printer_single_shift(struct terminal *term, wchar_t wc) +{ + ascii_printer_generic(term, wc); + term->charsets.selected = term->charsets.saved; + term_update_ascii_printer(term); +} + void term_update_ascii_printer(struct terminal *term) { @@ -2860,6 +2868,14 @@ term_update_ascii_printer(struct terminal *term) term->ascii_printer = new_printer; } +void +term_set_single_shift_ascii_printer(struct terminal *term, int selected) +{ + term->charsets.saved = term->charsets.selected; + term->charsets.selected = selected; + term->ascii_printer = &ascii_printer_single_shift; +} + enum term_surface term_surface_kind(const struct terminal *term, const struct wl_surface *surface) { diff --git a/terminal.h b/terminal.h index 1721a4c1..a54185e2 100644 --- a/terminal.h +++ b/terminal.h @@ -192,6 +192,7 @@ enum charset { CHARSET_ASCII, CHARSET_GRAPHIC }; struct charsets { int selected; + int saved; enum charset set[4]; /* G0-G3 */ }; @@ -605,6 +606,7 @@ bool term_shutdown(struct terminal *term); int term_destroy(struct terminal *term); void term_update_ascii_printer(struct terminal *term); +void term_set_single_shift_ascii_printer(struct terminal *term, int selected); void term_reset(struct terminal *term, bool hard); bool term_to_slave(struct terminal *term, const void *data, size_t len); diff --git a/vt.c b/vt.c index 97f45c48..26affcd2 100644 --- a/vt.c +++ b/vt.c @@ -426,14 +426,12 @@ action_esc_dispatch(struct terminal *term, uint8_t final) case 'N': /* SS2 - Single Shift 2 */ - term->charsets.selected = 2; /* G2 */ - term_update_ascii_printer(term); + term_set_single_shift_ascii_printer(term, 2); /* G2 */ break; case 'O': /* SS3 - Single Shift 3 */ - term->charsets.selected = 3; /* G3 */ - term_update_ascii_printer(term); + term_set_single_shift_ascii_printer(term, 3); /* G3 */ break; case '\\': From 3c609771c5e546d9596cdec2c3bee52d551bdb7e Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Wed, 9 Jun 2021 09:30:34 +0100 Subject: [PATCH 3/4] changelog: add issue links for previous 2 entries --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ace3be1..a8a42691 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,7 +61,8 @@ _Private Usage Area_ codepoints to be treated as double-width characters. * OSC 9 desktop notifications (iTerm2 compatible). -* Support for LS2 and LS3 (locking shift) escape sequences. +* Support for LS2 and LS3 (locking shift) escape sequences + (https://codeberg.org/dnkl/foot/issues/581). ### Changed @@ -163,7 +164,7 @@ * Text reflow performance (https://codeberg.org/dnkl/foot/issues/504). * IL+DL (`CSI Ps L` + `CSI Ps M`) now moves the cursor to column 0. * SS2 and SS3 (single shift) escape sequences behaving like locking - shifts. + shifts (https://codeberg.org/dnkl/foot/issues/580). ### Security From e030a2ca08d92eb431e9b8e494c63affeeb8c0e1 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Wed, 9 Jun 2021 09:51:48 +0100 Subject: [PATCH 4/4] terminal: add 'charset_designator' enum to make code more self-documenting This commit also renames the term_set_single_shift_ascii_printer() function to term_single_shift(), since the former is overly verbose and not really even accurate. --- terminal.c | 14 +++++++------- terminal.h | 7 ++++--- vt.c | 16 ++++++++-------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/terminal.c b/terminal.c index 5ba7b854..ddc93cad 100644 --- a/terminal.c +++ b/terminal.c @@ -1606,11 +1606,11 @@ term_reset(struct terminal *term, bool hard) term->bell_action_enabled = true; term->mouse_tracking = MOUSE_NONE; term->mouse_reporting = MOUSE_NORMAL; - term->charsets.selected = 0; - term->charsets.set[0] = CHARSET_ASCII; - term->charsets.set[1] = CHARSET_ASCII; - term->charsets.set[2] = CHARSET_ASCII; - term->charsets.set[3] = CHARSET_ASCII; + term->charsets.selected = G0; + term->charsets.set[G0] = CHARSET_ASCII; + term->charsets.set[G1] = CHARSET_ASCII; + term->charsets.set[G2] = CHARSET_ASCII; + term->charsets.set[G3] = CHARSET_ASCII; term->saved_charsets = term->charsets; tll_free_and_free(term->window_title_stack, free); term_set_window_title(term, term->conf->title); @@ -2869,10 +2869,10 @@ term_update_ascii_printer(struct terminal *term) } void -term_set_single_shift_ascii_printer(struct terminal *term, int selected) +term_single_shift(struct terminal *term, enum charset_designator idx) { term->charsets.saved = term->charsets.selected; - term->charsets.selected = selected; + term->charsets.selected = idx; term->ascii_printer = &ascii_printer_single_shift; } diff --git a/terminal.h b/terminal.h index a54185e2..b96621fd 100644 --- a/terminal.h +++ b/terminal.h @@ -189,10 +189,11 @@ enum cursor_origin { ORIGIN_ABSOLUTE, ORIGIN_RELATIVE }; enum cursor_keys { CURSOR_KEYS_DONTCARE, CURSOR_KEYS_NORMAL, CURSOR_KEYS_APPLICATION }; enum keypad_keys { KEYPAD_DONTCARE, KEYPAD_NUMERICAL, KEYPAD_APPLICATION }; enum charset { CHARSET_ASCII, CHARSET_GRAPHIC }; +enum charset_designator { G0, G1, G2, G3 }; struct charsets { - int selected; - int saved; + enum charset_designator selected; + enum charset_designator saved; enum charset set[4]; /* G0-G3 */ }; @@ -606,7 +607,7 @@ bool term_shutdown(struct terminal *term); int term_destroy(struct terminal *term); void term_update_ascii_printer(struct terminal *term); -void term_set_single_shift_ascii_printer(struct terminal *term, int selected); +void term_single_shift(struct terminal *term, enum charset_designator idx); void term_reset(struct terminal *term, bool hard); bool term_to_slave(struct terminal *term, const void *data, size_t len); diff --git a/vt.c b/vt.c index 26affcd2..3bd831a8 100644 --- a/vt.c +++ b/vt.c @@ -196,13 +196,13 @@ action_execute(struct terminal *term, uint8_t c) case '\x0e': /* SO - shift out */ - term->charsets.selected = 1; /* G1 */ + term->charsets.selected = G1; term_update_ascii_printer(term); break; case '\x0f': /* SI - shift in */ - term->charsets.selected = 0; /* G0 */ + term->charsets.selected = G0; term_update_ascii_printer(term); break; @@ -390,13 +390,13 @@ action_esc_dispatch(struct terminal *term, uint8_t final) case 'n': /* LS2 - Locking Shift 2 */ - term->charsets.selected = 2; /* G2 */ + term->charsets.selected = G2; term_update_ascii_printer(term); break; case 'o': /* LS3 - Locking Shift 3 */ - term->charsets.selected = 3; /* G3 */ + term->charsets.selected = G3; term_update_ascii_printer(term); break; @@ -426,12 +426,12 @@ action_esc_dispatch(struct terminal *term, uint8_t final) case 'N': /* SS2 - Single Shift 2 */ - term_set_single_shift_ascii_printer(term, 2); /* G2 */ + term_single_shift(term, G2); break; case 'O': /* SS3 - Single Shift 3 */ - term_set_single_shift_ascii_printer(term, 3); /* G3 */ + term_single_shift(term, G3); break; case '\\': @@ -460,7 +460,7 @@ action_esc_dispatch(struct terminal *term, uint8_t final) switch (final) { case '0': { size_t idx = term->vt.private - '('; - xassert(idx <= 3); + xassert(idx <= G3); term->charsets.set[idx] = CHARSET_GRAPHIC; term_update_ascii_printer(term); break; @@ -468,7 +468,7 @@ action_esc_dispatch(struct terminal *term, uint8_t final) case 'B': { size_t idx = term->vt.private - '('; - xassert(idx <= 3); + xassert(idx <= G3); term->charsets.set[idx] = CHARSET_ASCII; term_update_ascii_printer(term); break;