diff --git a/CHANGELOG.md b/CHANGELOG.md index 95bd6b85..bd701ca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +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 + (https://codeberg.org/dnkl/foot/issues/581). ### Changed @@ -166,6 +168,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 (https://codeberg.org/dnkl/foot/issues/580). ### Security diff --git a/terminal.c b/terminal.c index 3d6c20d4..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); @@ -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_single_shift(struct terminal *term, enum charset_designator idx) +{ + term->charsets.saved = term->charsets.selected; + term->charsets.selected = idx; + 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..b96621fd 100644 --- a/terminal.h +++ b/terminal.h @@ -189,9 +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; + enum charset_designator selected; + enum charset_designator saved; enum charset set[4]; /* G0-G3 */ }; @@ -605,6 +607,7 @@ bool term_shutdown(struct terminal *term); int term_destroy(struct terminal *term); void term_update_ascii_printer(struct terminal *term); +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 7c884cca..723f0450 100644 --- a/vt.c +++ b/vt.c @@ -234,13 +234,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; @@ -426,6 +426,18 @@ action_esc_dispatch(struct terminal *term, uint8_t final) term_reset(term, true); break; + case 'n': + /* LS2 - Locking Shift 2 */ + term->charsets.selected = G2; + term_update_ascii_printer(term); + break; + + case 'o': + /* LS3 - Locking Shift 3 */ + term->charsets.selected = G3; + term_update_ascii_printer(term); + break; + case 'D': term_linefeed(term); break; @@ -452,14 +464,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_single_shift(term, G2); break; case 'O': /* SS3 - Single Shift 3 */ - term->charsets.selected = 3; /* G3 */ - term_update_ascii_printer(term); + term_single_shift(term, G3); break; case '\\': @@ -488,7 +498,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; @@ -496,7 +506,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;