From 4caf8a6b14111cafa917355b9bfb0c5d8b443aa9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 15 Feb 2024 12:50:54 +0530 Subject: [PATCH] Restore support for alternate character sets Needed by the execrable ncurses. Adds an extra branch in the hot path, sigh. Thanks to branch prediction it doesnt have any measurable impact on the benchmark, thankfully. --- kitty/charsets.c | 159 ++++++++++++++++++++++++++++++++++++++++++ kitty/charsets.h | 1 + kitty/screen.c | 48 ++++++++++++- kitty/screen.h | 9 ++- kitty/vt-parser.c | 6 +- kitty_tests/parser.py | 14 ++++ 6 files changed, 231 insertions(+), 6 deletions(-) diff --git a/kitty/charsets.c b/kitty/charsets.c index 3be565d54..9223ac3b6 100644 --- a/kitty/charsets.c +++ b/kitty/charsets.c @@ -9,6 +9,165 @@ #include "data-types.h" +static uint32_t charset_translations[4][256] = { + /* VT100 graphics mapped to Unicode */ + { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f, + 0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0, + 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1, + 0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba, + 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c, + 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff + }, + /* IBM Codepage 437 mapped to Unicode */ + { + 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, + 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c, + 0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8, + 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, + 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, + 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 + }, + // VAX 42 map + { + 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, + 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c, + 0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8, + 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc, + 0x0020, 0x043b, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x0435, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0441, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0435, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x043a, + 0x0070, 0x0071, 0x0442, 0x0073, 0x043b, 0x0435, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, + 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, + 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 + }, + /* UK mapping, same as 8-bit Latin1 except the pound sign replaces # */ + { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x00a3, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff + }, +}; + +uint32_t* +translation_table(uint32_t which) { + switch(which){ + default: + return NULL; + case '0': + return charset_translations[0]; + case 'U': + return charset_translations[1]; + case 'V': + return charset_translations[2]; + case 'A': + return charset_translations[3]; + } +} + // UTF-8 decode taken from: https://bjoern.hoehrmann.de/utf-8/decoder/dfa/ diff --git a/kitty/charsets.h b/kitty/charsets.h index cb27e51f5..2f9549799 100644 --- a/kitty/charsets.h +++ b/kitty/charsets.h @@ -12,3 +12,4 @@ uint32_t decode_utf8(uint32_t*, uint32_t*, uint8_t byte); size_t decode_utf8_string(const char *src, size_t sz, uint32_t *dest); unsigned int encode_utf8(uint32_t ch, char* dest); +uint32_t* translation_table(uint32_t which); diff --git a/kitty/screen.c b/kitty/screen.c index 03ddef5bd..c26eddf76 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -14,6 +14,7 @@ #include "state.h" #include "iqsort.h" #include "fonts.h" +#include "charsets.h" #include "lineops.h" #include "hyperlink.h" #include @@ -187,6 +188,7 @@ screen_reset(Screen *self) { R(default_fg); R(default_bg); R(cursor_color); R(highlight_fg); R(highlight_bg); #undef R reset_vt_parser(self->vt_parser); + zero_at_ptr(&self->charset); self->margin_top = 0; self->margin_bottom = self->lines - 1; screen_normal_keypad_mode(self); init_tabstops(self->main_tabstops, self->columns); @@ -680,12 +682,47 @@ move_cursor_off_wide_char_trailer(Screen *self, text_loop_state *s) { zero_cells(s, s->cp + self->cursor->x, s->gp + self->cursor->x); } +static void +screen_change_charset(Screen *self, uint32_t which) { + switch(which) { + case 0: + self->charset.current_num = 0; + self->charset.current = self->charset.zero; + break; + case 1: + self->charset.current_num = 1; + self->charset.current = self->charset.one; + break; + } +} + +void +screen_designate_charset(Screen *self, uint32_t which, uint32_t as) { + switch(which) { + case 0: + self->charset.zero = translation_table(as); + if (self->charset.current_num == 0) self->charset.current = self->charset.zero; + break; + case 1: + self->charset.one = translation_table(as); + if (self->charset.current_num == 1) self->charset.current = self->charset.one; + break; + } +} + + +static uint32_t +map_char(Screen *self, const uint32_t ch) { + return UNLIKELY(self->charset.current && ch < 256) ? self->charset.current[ch] : ch; +} + static void draw_text_loop(Screen *self, const uint32_t *chars, size_t num_chars, text_loop_state *s) { init_text_loop_line(self, s); - if (cursor_on_wide_char_trailer(self, s) && ' ' <= chars[0] && chars[0] != DEL && !is_combining_char(chars[0])) move_cursor_off_wide_char_trailer(self, s); + const uint32_t first_char = map_char(self, chars[0]); + if (cursor_on_wide_char_trailer(self, s) && ' ' <= first_char && first_char != DEL && !is_combining_char(first_char)) move_cursor_off_wide_char_trailer(self, s); for (size_t i = 0; i < num_chars; i++) { - uint32_t ch = chars[i]; + uint32_t ch = map_char(self, chars[i]); if (ch < ' ') { switch (ch) { case BEL: @@ -694,6 +731,10 @@ draw_text_loop(Screen *self, const uint32_t *chars, size_t num_chars, text_loop_ screen_backspace(self); break; case HT: screen_tab(self); break; + case SI: + screen_change_charset(self, 0); break; + case SO: + screen_change_charset(self, 1); break; case LF: case VT: case FF: @@ -1569,6 +1610,7 @@ screen_save_cursor(Screen *self) { sp->mDECOM = self->modes.mDECOM; sp->mDECAWM = self->modes.mDECAWM; sp->mDECSCNM = self->modes.mDECSCNM; + memcpy(&sp->charset, &self->charset, sizeof(self->charset)); sp->is_valid = true; } @@ -1646,11 +1688,13 @@ screen_restore_cursor(Screen *self) { screen_cursor_position(self, 1, 1); screen_reset_mode(self, DECOM); screen_reset_mode(self, DECSCNM); + zero_at_ptr(&self->charset); } else { set_mode_from_const(self, DECOM, sp->mDECOM); set_mode_from_const(self, DECAWM, sp->mDECAWM); set_mode_from_const(self, DECSCNM, sp->mDECSCNM); cursor_copy_to(&(sp->cursor), self->cursor); + memcpy(&self->charset, &sp->charset, sizeof(self->charset)); screen_ensure_bounds(self, false, false); } } diff --git a/kitty/screen.h b/kitty/screen.h index 4f6cda922..2af650c9f 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -56,9 +56,14 @@ typedef struct { #define SAVEPOINTS_SZ 256 +typedef struct CharsetState { + uint32_t *zero, *one, *current, current_num; +} CharsetState; + typedef struct { Cursor cursor; bool mDECOM, mDECAWM, mDECSCNM; + CharsetState charset; bool is_valid; } Savepoint; @@ -83,7 +88,7 @@ typedef struct { typedef struct { PyObject_HEAD - unsigned int columns, lines, margin_top, margin_bottom, charset, scrolled_by; + unsigned int columns, lines, margin_top, margin_bottom, scrolled_by; double pending_scroll_pixels_x, pending_scroll_pixels_y; CellPixelSize cell_size; OverlayLine overlay_line; @@ -160,6 +165,7 @@ typedef struct { GraphicsManager *grman; Selections selections, url_ranges; } paused_rendering; + CharsetState charset; } Screen; @@ -272,6 +278,7 @@ bool get_line_edge_colors(Screen *self, color_type *left, color_type *right); bool parse_sgr(Screen *screen, const uint8_t *buf, unsigned int num, const char *report_name, bool is_deccara); bool screen_pause_rendering(Screen *self, bool pause, int for_in_ms); void screen_check_pause_rendering(Screen *self, monotonic_t now); +void screen_designate_charset(Screen *self, uint32_t which, uint32_t as); #define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen); DECLARE_CH_SCREEN_HANDLER(bell) DECLARE_CH_SCREEN_HANDLER(backspace) diff --git a/kitty/vt-parser.c b/kitty/vt-parser.c index 3d8a37a4a..34044162f 100644 --- a/kitty/vt-parser.c +++ b/kitty/vt-parser.c @@ -96,6 +96,8 @@ _report_params(PyObject *dump_callback, id_type window_id, const char *name, int case BEL: REPORT_COMMAND(screen_bell); break; \ case BS: REPORT_COMMAND(screen_backspace); break; \ case HT: REPORT_COMMAND(screen_tab); break; \ + case SI: REPORT_COMMAND(screen_change_charset, 0); break; \ + case SO: REPORT_COMMAND(screen_change_charset, 1); break; \ case LF: case VT: case FF: REPORT_COMMAND(screen_linefeed); break; \ case CR: REPORT_COMMAND(screen_carriage_return); break; \ default: \ @@ -321,9 +323,7 @@ consume_esc(PS *self) { case '0': case 'U': case 'V': - // dont report this error as fish shell designates charsets for some unholy reason, creating lot of noise in the tests - /* REPORT_ERROR("Ignoring attempt to designate charset as we support only UTF-8"); */ - break; + CALL_ED2(screen_designate_charset, prev_ch - '(', ch); break; default: REPORT_ERROR("Unknown charset: 0x%x", ch); break; } diff --git a/kitty_tests/parser.py b/kitty_tests/parser.py index a766bbd45..6afb23a80 100644 --- a/kitty_tests/parser.py +++ b/kitty_tests/parser.py @@ -76,6 +76,20 @@ class TestParser(BaseTest): parse_bytes(s, x, cd) self.ae(cmds, cd.get_result()) + def test_charsets(self): + s = self.create_screen() + pb = partial(self.parse_bytes_dump, s) + pb(b'\xc3') + pb(b'\xa1', ('draw', b'\xc3\xa1'.decode('utf-8'))) + s = self.create_screen() + pb = partial(self.parse_bytes_dump, s) + pb('\033)0\x0e/_', ('screen_designate_charset', 1, ord('0')), ('screen_change_charset', 1), '/_') + self.ae(str(s.line(0)), '/\xa0') + s = self.create_screen() + pb = partial(self.parse_bytes_dump, s) + pb('\033(0/_', ('screen_designate_charset', 0, ord('0')), '/_') + self.ae(str(s.line(0)), '/\xa0') + def test_parser_threading(self): s = self.create_screen()