From a2c9c56f1962ce02e71582c06f389e53d1869e90 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Tue, 8 Jun 2021 21:09:40 +0100 Subject: [PATCH] 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 '\\':