[vte] parser: Fix charset detection



commit b512050c16e8ae9e9c40efc41b1eba6a52abdca7
Author: Christian Persch <chpe src gnome org>
Date:   Tue Mar 27 19:40:12 2018 +0200

    parser: Fix charset detection
    
    And remove the old parser and test programme.

 src/Makefile.am              |   42 +--
 src/caps-list.hh             |  318 ------------------
 src/interpret-old.cc         |  302 -----------------
 src/matcher.cc               |  221 ------------
 src/matcher.hh               |   88 -----
 src/parser-charset-tables.hh |  230 +++++++++++++
 src/parser-charset.hh        |  306 +++++++++++++++++
 src/parser-cmd.hh            |   15 +-
 src/parser-glue.hh           |    4 +
 src/parser-test.cc           |  246 ++++++++++++++-
 src/parser.cc                |  512 ++++++++++++----------------
 src/parser.hh                |   61 +---
 src/table.cc                 |  761 ------------------------------------------
 src/table.hh                 |   55 ---
 src/vteseq-list.hh           |    8 -
 src/vteseq-str.hh            |  156 ---------
 src/vteseq.cc                |  403 +++++++++++------------
 17 files changed, 1213 insertions(+), 2515 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 64ff262..aedd030 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -58,6 +58,8 @@ libvte_@VTE_API_MAJOR_VERSION@_@VTE_API_MINOR_VERSION@_la_SOURCES = \
        parser.cc \
        parser.hh \
        parser-arg.hh \
+       parser-charset.hh \
+       parser-charset-tables.hh \
        parser-cmd.hh \
        parser-glue.hh \
        pty.cc \
@@ -173,7 +175,7 @@ vteresources.cc: vte.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES) --
 
 # Misc unit tests and utilities
 
-noinst_PROGRAMS += interpret interpret-old slowcat test-parser
+noinst_PROGRAMS += interpret slowcat test-parser
 noinst_SCRIPTS = decset osc window
 EXTRA_DIST += $(noinst_SCRIPTS)
 
@@ -237,6 +239,8 @@ interpret_SOURCES = \
        iso2022.h \
        parser.cc \
        parser.hh \
+       parser-charset.hh \
+       parser-charset-tables.hh \
        parser-cmd.hh \
        parser-glue.hh \
        vteconv.cc \
@@ -262,40 +266,6 @@ interpret_LDADD = \
        $(GLIB_LIBS) \
        $(GOBJECT_LIBS)
 
-interpret_old_SOURCES = \
-       buffer.h \
-       caps.hh \
-       debug.cc \
-       debug.h \
-       iso2022.cc \
-       iso2022.h \
-       matcher.cc \
-       matcher.hh \
-       table.cc \
-       table.hh \
-       vteconv.cc \
-       vteconv.h \
-       interpret-old.cc
-interpret_old_CPPFLAGS = \
-       -DINTERPRET_OLD_MAIN \
-       -DVTE_API_VERSION=\"$(VTE_API_VERSION)\" \
-       -I$(builddir) \
-       -I$(srcdir) \
-       $(AM_CPPFLAGS)
-interpret_old_CFLAGS = \
-       $(GLIB_CFLAGS) \
-       $(GOBJECT_CFLAGS) \
-       $(GTK_CFLAGS) \
-       $(AM_CFLAGS)
-interpret_old_CXXFLAGS = \
-       $(GLIB_CFLAGS) \
-       $(GOBJECT_CFLAGS) \
-       $(GTK_CFLAGS) \
-       $(AM_CXXFLAGS)
-interpret_old_LDADD = \
-       $(GLIB_LIBS) \
-       $(GOBJECT_LIBS)
-
 slowcat_SOURCES = \
        slowcat.c \
        $(NULL)
@@ -309,6 +279,8 @@ test_parser_SOURCES = \
        parser.hh \
        parser-arg.hh \
        parser-cmd.hh \
+       parser-charset.hh \
+       parser-charset-tables.hh \
        parser-glue.hh \
        $(NULL)
 test_parser_CPPFLAGS = \
diff --git a/src/parser-charset-tables.hh b/src/parser-charset-tables.hh
new file mode 100644
index 0000000..855c221
--- /dev/null
+++ b/src/parser-charset-tables.hh
@@ -0,0 +1,230 @@
+/*
+ * Copyright © 2018 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define IR(num)    VTE_CHARSET_ISO_2375_IR_##num
+#define DEC(name)  VTE_CHARSET_DEC_##name
+#define NRCS(name) VTE_CHARSET_##name##_NRCS
+#define EMPTY      VTE_CHARSET_EMPTY
+#define NA         VTE_CHARSET_NONE
+#define RET        VTE_CHARSET_RETURN
+
+/* 94-character graphic character sets:
+ * G0: ESC 2/8 F
+ * G1: ESC 2/9 F
+ * G2: ESC 2/10 F
+ * G3: ESC 2/11 F
+ * C0: -
+ * C1: -
+ */
+/* NOTE: 4/8 'H' for IR(11) (SWEDISH_NRCS) conflicts with the
+ * primary choice on ISO_HEBREW_SUPPLEMENTAL.
+ * VT510 always chooses HEBREW; the table below prefers IR #11.
+ */
+static uint8_t const charset_graphic_94[] = {
+        /* 3/0..3/15 */
+        DEC(SPECIAL_GRAPHIC), NA, NA, NA, NRCS(DUTCH), NRCS(FINNISH), NRCS(NORWEGIAN_DANISH), NRCS(SWEDISH),
+        NA, NRCS(FRENCH_CANADIAN), NA, NA, DEC(UPSS), NRCS(SWISS), DEC(TECHNICAL), NA,
+        /* 4/0..4/15 */
+        IR(2), IR(4), IR(6), IR(8_1), IR(8_2), IR(9_1), IR(9_2), IR(10),
+        IR(11), IR(13), IR(14), IR(21), IR(16), IR(39), IR(37), IR(38),
+        /* 5/0..5/15 */
+        IR(53), IR(54), IR(25), IR(55), IR(57), IR(27), IR(47), IR(49),
+        IR(31), IR(15), IR(17), IR(18), IR(19), IR(50), IR(51), IR(59),
+        /* 6/0..6/15 */
+        IR(60), IR(61), IR(70), IR(71), IR(72_OR_173), IR(68), IR(69), IR(84),
+        IR(85), IR(86), IR(88), IR(89), IR(90), IR(91), IR(92), IR(93),
+        /* 7/0..7/13 */
+        IR(94), IR(95), IR(96), IR(98), IR(99), IR(102), IR(103), IR(121),
+        IR(122), IR(137), IR(141), IR(146), IR(128), IR(147), EMPTY
+};
+
+/* 94-character graphic character sets, with second intermediate byte 2/1:
+ * G0: ESC 2/8 2/1 F
+ * G1: ESC 2/9 2/1 F
+ * G2: ESC 2/10 2/1 F
+ * G3: ESC 2/11 2/1 F
+ * C0: -
+ * C1: -
+ */
+static uint8_t const charset_graphic_94_with_2_1[] = {
+        /* 4/0..4/6 */
+        IR(150), IR(151), IR(170), IR(207), IR(230), IR(231), IR(232)
+};
+
+/* 94-character graphic character sets, with second intermediate byte 2/2:
+ * G0: ESC 2/8 2/1 F
+ * G1: ESC 2/9 2/1 F
+ * G2: ESC 2/10 2/1 F
+ * G3: ESC 2/11 2/1 F
+ * C0: -
+ * C1: -
+ */
+static uint8_t const charset_graphic_94_with_2_2[] = {
+        /* 3/0..3/15 */
+        NA, NA, NA, NA, DEC(HEBREW), NA, NA, NA,
+        NA, NA, NA, NA, NA, NA, NRCS(GREEK), DEC(GREEK),
+};
+
+/* 94-character graphic character sets, with second intermediate byte 2/5:
+ * G0: ESC 2/8 2/1 F
+ * G1: ESC 2/9 2/1 F
+ * G2: ESC 2/10 2/1 F
+ * G3: ESC 2/11 2/1 F
+ * C0: -
+ * C1: -
+ */
+static uint8_t const charset_graphic_94_with_2_5[] = {
+        /* 3/0..3/15 */
+        DEC(TURKISH), NA, NRCS(TURKISH), NRCS(SOFT), NA, DEC(SUPPLEMENTAL_GRAPHIC), NRCS(PORTUGUESE), NA,
+        NA, NA, NA, NA, NA, NRCS(HEBREW), NA, NA,
+};
+
+/* 94-character graphic character sets, with second intermediate byte 2/6:
+ * G0: ESC 2/8 2/1 F
+ * G1: ESC 2/9 2/1 F
+ * G2: ESC 2/10 2/1 F
+ * G3: ESC 2/11 2/1 F
+ * C0: -
+ * C1: -
+ */
+static uint8_t const charset_graphic_94_with_2_6[] = {
+        /* 3/0..3/15 */
+        NA, NA, NA, DEC(THAI), DEC(CYRILLIC), NRCS(RUSSIAN), NA, NA,
+        NA, NA, NA, NA, NA, NA, NA, NA,
+};
+
+/* 96-characters graphic character sets:
+ * G0: -
+ * G1: ESC 2/13 F
+ * G2: ESC 2/14 F
+ * G3: ESC 2/15 F
+ * C0: -
+ * C1: -
+ */
+static uint8_t const charset_graphic_96[] = {
+        /* 3/0..3/15 */
+        NA, NA, NA, NA, NA, NA, NA, NA,
+        NA, NA, NA, NA, DEC(UPSS), NA, NA, NA,
+        /* 4/0..4/15 */
+        IR(111), IR(100), IR(101), IR(109), IR(110), IR(123), IR(126), IR(127),
+        IR(138), IR(139), IR(142), IR(143), IR(144), IR(148), IR(152), IR(153),
+        /* 5/0..5/15 */
+        IR(154), IR(155), IR(156), IR(164), IR(166), IR(167), IR(157), NA,
+        IR(158), IR(179), IR(180), IR(181), IR(182), IR(197), IR(198), IR(199),
+        /* 6/0..6/15 */
+        IR(200), IR(201), IR(203), IR(204), IR(205), IR(206), IR(226), IR(208),
+        IR(209), IR(227), IR(234), NA, NA, NA, NA, NA,
+        /* 7/0..7/14 */
+        NA, NA, NA, NA, NA, NA, NA, NA,
+        NA, NA, NA, NA, NA, IR(129), EMPTY
+};
+
+/* Multibyte graphic character sets:
+ * G0: ESC 2/4 2/8 F
+ * G1: ESC 2/4 2/9 F
+ * G2: ESC 2/4 2/10 F
+ * G3: ESC 2/4 2/11 F
+ * C0: -
+ * C1: -
+ *
+ * Note that exceptionally, ESC 2/4 4/0, ESC 2/4 4/1 and ESC 2/4 4/2 designate
+ * G0 sets for compatibility with an earlier version of ISO-2022.
+ */
+static uint8_t const charset_graphic_94_n[] = {
+        /* 3/0..3/15 */
+        NA, DEC(KANJI_1978), NA, DEC(KANJI_1983), NA, NA, NA, NA,
+        NA, NA, NA, NA, NA, NA, NA, NA,
+        /* 4/0..4/15 */
+        IR(42), IR(58), IR(87_OR_168), IR(149), IR(159), IR(165), IR(169), IR(171),
+        IR(172), IR(183), IR(184), IR(185), IR(186), IR(187), IR(202), IR(228),
+        /* 5/0..5/15 */
+        IR(229), IR(233), NA, NA, NA, NA, NA, NA,
+        NA, NA, NA, NA, NA, NA, NA, NA,
+        /* 6/0..6/15 */
+        NA, NA, NA, NA, NA, NA, NA, NA,
+        NA, NA, NA, NA, NA, NA, NA, NA,
+        /* 7/0..7/14 */
+        NA, NA, NA, NA, NA, NA, NA, NA,
+        NA, NA, NA, NA, NA, NA, EMPTY,
+};
+
+/* C0 control character sets:
+ * G0: -
+ * G1: -
+ * G2: -
+ * G3: -
+ * C0: ESC 2/1 F
+ * C1: -
+ */
+static uint8_t const charset_control_c0[] = {
+        /* 4/0..4/12 */
+        IR(1), IR(7), IR(48), IR(26), IR(36), IR(106), IR(74), IR(104),
+        IR(130), IR(132), IR(134), IR(135), IR(140)
+};
+
+/* C1 control character sets:
+ * G0: -
+ * G1: -
+ * G2: -
+ * G3: -
+ * C0: -
+ * C1: ESC 2/2 F
+ */
+static uint8_t const charset_control_c1[] = {
+        /* 4/0..4/8 */
+        IR(56), IR(73), IR(67_OR_124), IR(77), IR(133), IR(40), IR(136), IR(105),
+        IR(107)
+};
+
+#if 0
+/* Single control functions as two-byte escape sequences
+ * ESC F
+ */
+static uint8_t const charset_control_single[] = {
+        /* 6/0..6/15 */
+        IR(32), IR(33), IR(34), IR(35), IR(189), NA, NA, NA,
+        NA, NA, NA, NA, NA, NA, IR(62), IR(63),
+        /* 7/0..7/14 */
+        NA, NA, NA, NA, NA, NA, NA, NA,
+        NA, NA, NA, NA, IR(64), IR(65), IR(66)
+};
+#endif
+
+/* Non-ISO-2022 coding systems, with standard return:
+ * ESC 2/5 F
+ */
+static uint8_t const charset_ocs_with_return[] = {
+        /* 4/0..4/8 */
+        RET, IR(108), IR(178), IR(131), IR(145), IR(160), IR(161), IR(196),
+        IR(188)
+};
+
+/* Non-ISO-2022 coding systems, without standard return:
+ * ESC 2/5 2/15 F
+ */
+static uint8_t const charset_ocs_without_return[] = {
+        /* 4/0..4/12 */
+        IR(162), IR(163), IR(125), IR(174), IR(175), IR(176), IR(177), IR(190),
+        IR(191), IR(192), IR(193), IR(194), IR(195)
+};
+
+#undef IR
+#undef DEC
+#undef NRCS
+#undef EMPTY
+#undef NA
+#undef RET
diff --git a/src/parser-charset.hh b/src/parser-charset.hh
new file mode 100644
index 0000000..1798cce
--- /dev/null
+++ b/src/parser-charset.hh
@@ -0,0 +1,306 @@
+/*
+ * Copyright © 2018 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define IR_NAME(num) ISO_2375_IR_##num
+#define DEC_NAME(name) DEC_##name
+#define NRCS_NAME(name) name##_NRCS
+#define SUPPLEMENTAL_NAME(name) ISO_##name##_SUPPLEMENTAL
+
+#define IR(num) _VTE_CHARSET(IR_NAME(num))
+#define DEC(name) _VTE_CHARSET(DEC_NAME(name))
+#define NRCS(name) _VTE_CHARSET(NRCS_NAME(name))
+#define ALIAS(name1,name2) _VTE_CHARSET_ALIAS(name1,name2)
+
+_VTE_CHARSET(NONE)
+
+/* See ECMA-35 § 14.4 for the meaning of this */
+_VTE_CHARSET(DRCS)
+
+_VTE_CHARSET(EMPTY)
+
+/* Return to ISO-2022 */
+_VTE_CHARSET(RETURN)
+
+/* ISO 2375 IR sets */
+
+IR(1)
+IR(2)
+IR(4)
+IR(6)
+IR(7)
+IR(8_1)
+IR(8_2)
+IR(9_1)
+IR(9_2)
+IR(10)
+IR(11)
+IR(13)
+IR(14)
+IR(15)
+IR(16)
+IR(17)
+IR(18)
+IR(19)
+IR(21)
+IR(25)
+IR(26)
+IR(27)
+IR(31)
+IR(32)
+IR(33)
+IR(34)
+IR(35)
+IR(36)
+IR(37)
+IR(38)
+IR(39)
+IR(40)
+IR(42)
+IR(47)
+IR(48)
+IR(49)
+IR(50)
+IR(51)
+IR(53)
+IR(54)
+IR(55)
+IR(56)
+IR(57)
+IR(58)
+IR(59)
+IR(60)
+IR(61)
+IR(62)
+IR(63)
+IR(64)
+IR(65)
+IR(66)
+IR(67)
+IR(68)
+IR(69)
+IR(70)
+IR(71)
+IR(72)
+IR(73)
+IR(74)
+IR(77)
+IR(84)
+IR(85)
+IR(86)
+IR(87)
+IR(88)
+IR(89)
+IR(90)
+IR(91)
+IR(92)
+IR(93)
+IR(94)
+IR(95)
+IR(96)
+IR(98)
+IR(99)
+IR(100)
+IR(101)
+IR(102)
+IR(103)
+IR(104)
+IR(105)
+IR(106)
+IR(107)
+IR(108)
+IR(109)
+IR(110)
+IR(111)
+IR(121)
+IR(122)
+IR(123)
+IR(124)
+IR(125)
+IR(126)
+IR(127)
+IR(128)
+IR(129)
+IR(130)
+IR(131)
+IR(132)
+IR(133)
+IR(134)
+IR(135)
+IR(136)
+IR(137)
+IR(138)
+IR(139)
+IR(140)
+IR(141)
+IR(142)
+IR(143)
+IR(144)
+IR(145)
+IR(146)
+IR(147)
+IR(148)
+IR(149)
+IR(150)
+IR(151)
+IR(152)
+IR(153)
+IR(154)
+IR(155)
+IR(156)
+IR(157)
+IR(158)
+IR(159)
+IR(160)
+IR(161)
+IR(162)
+IR(163)
+IR(164)
+IR(165)
+IR(166)
+IR(167)
+IR(168)
+IR(169)
+IR(170)
+IR(171)
+IR(172)
+IR(173)
+IR(174)
+IR(175)
+IR(176)
+IR(177)
+IR(178)
+IR(179)
+IR(180)
+IR(181)
+IR(182)
+IR(183)
+IR(184)
+IR(185)
+IR(186)
+IR(187)
+IR(188)
+IR(189)
+IR(190)
+IR(191)
+IR(192)
+IR(193)
+IR(194)
+IR(195)
+IR(196)
+IR(197)
+IR(198)
+IR(199)
+IR(200)
+IR(201)
+IR(202)
+IR(203)
+IR(204)
+IR(205)
+IR(206)
+IR(207)
+IR(208)
+IR(209)
+IR(226)
+IR(227)
+IR(228)
+IR(229)
+IR(230)
+IR(231)
+IR(232)
+IR(233)
+IR(234)
+
+/* Use IRR to choose between them */
+IR(67_OR_124)
+IR(72_OR_173)
+IR(87_OR_168)
+
+/* DEC 94-sets */
+
+/* This is referred to variously as DEC Supplemental or DEC Supplemental Graphic */
+DEC(SUPPLEMENTAL_GRAPHIC) /* ESC I 2/5 3/5 */
+DEC(SPECIAL_GRAPHIC) /* ESC I 3/0 */
+DEC(TECHNICAL) /* ESC I 3/14 */
+/* UPSS: User Preferred Supplemental Set */
+DEC(UPSS) /* ESC I 3/12 */
+DEC(CYRILLIC) /* ESC I 2/6 3/4 */
+DEC(GREEK) /* ESC I 2/2 3/15 */
+DEC(HEBREW) /* ESC I 2/2 3/4 */
+DEC(THAI) /* ESC I 2/6 3/3 */
+DEC(TURKISH) /* ESC I 2/5 3/0 */
+
+/* DEC NRCS 94-sets */
+
+/* FRENCH_CANADIAN: this has a secondary choice of ESC I 5/1 which is registered as
+ * ISO IR #54 (cyrillic), so we don't implement that alias
+*/
+NRCS(FRENCH_CANADIAN) /* ESC I 3/9 */
+
+/* FIXME: check if these correspond to any IR sets and make them an alias if so */
+NRCS(DUTCH) /* ESC I 3/4 */
+NRCS(GREEK) /* ESC I 2/2 3/14 */
+NRCS(HEBREW) /* ESC I 2/5 3/13 */
+NRCS(PORTUGUESE) /* ESC I 2/5 3/6 */
+NRCS(RUSSIAN) /* ESC I 2/6 3/5 */
+NRCS(SWISS) /* ESC I 3/13 */
+NRCS(TURKISH) /* ESC I 2/5 3/2 */
+
+NRCS(SOFT) /* ESC I 2/5 3/3 */
+
+/* Aliases. They were identified as an alias by their ISO IR sequence.
+ * Some have a secondary sequence.
+ */
+
+ALIAS(DEC_NAME(KANJI_1978), IR_NAME(42)) /* G3 only: ESC 2/4 2/11 3/1 */
+ALIAS(DEC_NAME(KANJI_1983), IR_NAME(87)) /* G3 only: ESC 2/4 2/11 3/3 */
+
+ALIAS(NRCS_NAME(AMERICAN), IR_NAME(6))
+ALIAS(NRCS_NAME(BRITISH), IR_NAME(4))
+ALIAS(NRCS_NAME(FINNISH), IR_NAME(8_1)) /* ESC I 3/5 */
+
+/* ISO IR #25 is withdrawn in favour of #69; check which one DEC actually uses */
+ALIAS(NRCS_NAME(FRENCH), IR_NAME(25))
+
+ALIAS(NRCS_NAME(GERMAN), IR_NAME(21))
+ALIAS(NRCS_NAME(ITALIAN), IR_NAME(15))
+
+/* NORWEGIAN_DANISH: this has primary choice ESC I 6/0 which is ISO IR #60,
+ * secondary choice ESC I 4/5 which is ISO IR #9-1 and
+ * tertiary choice ESC 3/6. We link the tertiary choice to IR #9-1 since
+ * the VT220 manual only lists the 4/5 and 3/6 choices.
+ */
+ALIAS(NRCS_NAME(NORWEGIAN_DANISH), IR_NAME(9_1))
+
+ALIAS(NRCS_NAME(SPANISH), IR_NAME(17))
+ALIAS(NRCS_NAME(SWEDISH), IR_NAME(11)) /* ESC I 3/7 */
+
+ALIAS(SUPPLEMENTAL_NAME(GREEK), IR_NAME(126))
+ALIAS(SUPPLEMENTAL_NAME(HEBREW), IR_NAME(138))
+ALIAS(SUPPLEMENTAL_NAME(LATIN_1), IR_NAME(100))
+ALIAS(SUPPLEMENTAL_NAME(LATIN_2), IR_NAME(101))
+ALIAS(SUPPLEMENTAL_NAME(LATIN_5), IR_NAME(148))
+ALIAS(SUPPLEMENTAL_NAME(LATIN_CYRILLIC), IR_NAME(144))
+
+#undef IR_NAME
+#undef DEC_NAME
+#undef NRCS_NAME
+#undef SUPPLEMENTAL_NAME
+
+#undef IR
+#undef DEC
+#undef NRCS
+#undef ALIAS
diff --git a/src/parser-cmd.hh b/src/parser-cmd.hh
index 8f8d640..0c0fdac 100644
--- a/src/parser-cmd.hh
+++ b/src/parser-cmd.hh
@@ -17,11 +17,13 @@
 
 _VTE_CMD(NONE) /* placeholder */
 _VTE_CMD(GRAPHIC) /* graphics character */
+_VTE_CMD(ACS) /* announce-code-structure */
 _VTE_CMD(BEL) /* bell */
 _VTE_CMD(BS) /* backspace */
 _VTE_CMD(CBT) /* cursor-backward-tabulation */
 _VTE_CMD(CHA) /* cursor-horizontal-absolute */
 _VTE_CMD(CHT) /* cursor-horizontal-forward-tabulation */
+_VTE_CMD(CMD) /* coding-method-delimiter */
 _VTE_CMD(CNL) /* cursor-next-line */
 _VTE_CMD(CPL) /* cursor-previous-line */
 _VTE_CMD(CR) /* carriage-return */
@@ -30,6 +32,7 @@ _VTE_CMD(CUD) /* cursor-down */
 _VTE_CMD(CUF) /* cursor-forward */
 _VTE_CMD(CUP) /* cursor-position */
 _VTE_CMD(CUU) /* cursor-up */
+_VTE_CMD(CnD) /* Cn-designate */
 _VTE_CMD(DA1) /* primary-device-attributes */
 _VTE_CMD(DA2) /* secondary-device-attributes */
 _VTE_CMD(DA3) /* tertiary-device-attributes */
@@ -118,6 +121,7 @@ _VTE_CMD(DECTID) /* select-terminal-id */
 _VTE_CMD(DECTME) /* terminal-mode-emulation */
 _VTE_CMD(DECTST) /* invoke-confidence-test */
 _VTE_CMD(DL) /* delete-line */
+_VTE_CMD(DOCS) /* designate-other-coding-system */
 _VTE_CMD(DSR_ANSI) /* device-status-report-ansi */
 _VTE_CMD(DSR_DEC) /* device-status-report-dec */
 _VTE_CMD(ECH) /* erase-character */
@@ -126,6 +130,8 @@ _VTE_CMD(EL) /* erase-in-line */
 _VTE_CMD(ENQ) /* enquiry */
 _VTE_CMD(EPA) /* end-of-guarded-area */
 _VTE_CMD(FF) /* form-feed */
+_VTE_CMD(GnDm) /* Gn-designate-9m-charset */
+_VTE_CMD(GnDMm) /* Gn-designate-multibyte-9m-charset */
 _VTE_CMD(HPA) /* horizontal-position-absolute */
 _VTE_CMD(HPR) /* horizontal-position-relative */
 _VTE_CMD(HT) /* horizontal-tab */
@@ -134,6 +140,7 @@ _VTE_CMD(HVP) /* horizontal-and-vertical-position */
 _VTE_CMD(ICH) /* insert-character */
 _VTE_CMD(IL) /* insert-line */
 _VTE_CMD(IND) /* index */
+_VTE_CMD(IRR) /* identify-revised-registration */
 _VTE_CMD(LF) /* line-feed */
 _VTE_CMD(LS1R) /* locking-shift-1-right */
 _VTE_CMD(LS2) /* locking-shift-2 */
@@ -155,9 +162,6 @@ _VTE_CMD(RI) /* reverse-index */
 _VTE_CMD(RIS) /* reset-to-initial-state */
 _VTE_CMD(RM_ANSI) /* reset-mode-ansi */
 _VTE_CMD(RM_DEC) /* reset-mode-dec */
-_VTE_CMD(S7C1T) /* set-7bit-c1-terminal */
-_VTE_CMD(S8C1T) /* set-8bit-c1-terminal */
-_VTE_CMD(SCS) /* select-character-set */
 _VTE_CMD(SD) /* scroll-down */
 _VTE_CMD(SGR) /* select-graphics-rendition */
 _VTE_CMD(SI) /* shift-in */
@@ -181,13 +185,8 @@ _VTE_CMD(XTERM_MUHP) /* xterm-memory-unlock-hp-bugfix */
 _VTE_CMD(XTERM_RPM) /* xterm-restore-private-mode */
 _VTE_CMD(XTERM_RRV) /* xterm-reset-resource-value */
 _VTE_CMD(XTERM_RTM) /* xterm-reset-title-mode */
-_VTE_CMD(XTERM_SACL1) /* xterm-set-ansi-conformance-level-1 */
-_VTE_CMD(XTERM_SACL2) /* xterm-set-ansi-conformance-level-2 */
-_VTE_CMD(XTERM_SACL3) /* xterm-set-ansi-conformance-level-3 */
-_VTE_CMD(XTERM_SDCS) /* xterm-set-default-character-set */
 _VTE_CMD(XTERM_SGFX) /* xterm-sixel-graphics */
 _VTE_CMD(XTERM_SPM) /* xterm-set-private-mode */
 _VTE_CMD(XTERM_SRV) /* xterm-set-resource-value */
 _VTE_CMD(XTERM_STM) /* xterm-set-title-mode */
-_VTE_CMD(XTERM_SUCS) /* xterm-set-utf8-character-set */
 _VTE_CMD(XTERM_WM) /* xterm-window-management */
diff --git a/src/parser-glue.hh b/src/parser-glue.hh
index e730a23..c06bf19 100644
--- a/src/parser-glue.hh
+++ b/src/parser-glue.hh
@@ -36,6 +36,10 @@ public:
 
         inline unsigned int command() const { return m_seq->command; }
 
+        inline unsigned int charset() const { return m_seq->charset; }
+
+        inline unsigned int intermediates() const { return m_seq->intermediates; }
+
         inline uint32_t terminator() const { return m_seq->terminator; }
 
         inline unsigned int size() const
diff --git a/src/parser-test.cc b/src/parser-test.cc
index d8da13b..ccaee2e 100644
--- a/src/parser-test.cc
+++ b/src/parser-test.cc
@@ -27,6 +27,7 @@
 #include <glib.h>
 
 #include "parser.hh"
+#include "parser-charset-tables.hh"
 
 static struct vte_parser* parser;
 
@@ -61,6 +62,26 @@ cmd_to_str(unsigned int command)
                 return buf;
         }
 }
+
+static char const*
+charset_to_str(unsigned int cs)
+{
+        switch (cs) {
+#define _VTE_CHARSET_PASTE(name) case VTE_CHARSET_##name: return #name;
+#define _VTE_CHARSET(name) _VTE_CHARSET_PASTE(name)
+#define _VTE_CHARSET_ALIAS_PASTE(name1,name2)
+#define _VTE_CHARSET_ALIAS(name1,name2)
+#include "parser-charset.hh"
+#undef _VTE_CHARSET_PASTE
+#undef _VTE_CHARSET
+#undef _VTE_CHARSET_ALIAS_PASTE
+#undef _VTE_CHARSET_ALIAS
+        default:
+                static char buf[32];
+                snprintf(buf, sizeof(buf), "UNKOWN(%u)", cs);
+                return buf;
+        }
+}
 #endif
 
 static const char c0str[][6] = {
@@ -259,8 +280,6 @@ feed_parser(vte_seq_builder& b,
         std::u32string s;
         b.to_string(s, c1);
 
-        //        print_escaped(s);
-
         int rv = VTE_SEQ_NONE;
         for (auto it : s) {
                 rv = vte_parser_feed(parser, seq, (uint32_t)(char32_t)it);
@@ -443,6 +462,223 @@ test_seq_esc_nF(void)
 }
 
 static void
+test_seq_esc_charset(uint32_t f, /* final */
+                     uint32_t i[], /* intermediates */
+                     unsigned int ni, /* number of intermediates */
+                     unsigned int cmd, /* expected command */
+                     unsigned int cs /* expected charset */)
+{
+        vte_seq_builder b{VTE_SEQ_ESCAPE, f};
+        b.set_intermediates(i, ni);
+
+        vte_parser_reset(parser);
+        struct vte_seq* seq;
+        auto rv = feed_parser(b, &seq);
+        g_assert_cmpint(rv, ==, VTE_SEQ_ESCAPE);
+        b.assert_equal(seq);
+
+        g_assert_cmpint(seq->command, ==, cmd);
+        g_assert_cmpint(seq->charset, ==, cs);
+}
+
+static void
+test_seq_esc_charset(uint32_t i[], /* intermediates */
+                     unsigned int ni, /* number of intermediates */
+                     uint8_t const* const table, /* table */
+                     unsigned int ntable, /* number of table entries */
+                     uint32_t ts, /* start of table */
+                     unsigned int cmd, /* expected command */
+                     unsigned int defaultcs /* default charset */)
+{
+        for (uint32_t f = 0x30; f < 0x7f; f++) {
+                int cs;
+
+                if (f >= ts && f < (ts + ntable))
+                        cs = table[f - ts];
+                else
+                        cs = defaultcs;
+
+                test_seq_esc_charset(f, i, ni, cmd, cs);
+        }
+}
+
+static void
+test_seq_esc_charset_94(void)
+{
+        uint32_t i[4];
+
+        /* Single byte 94-sets */
+        for (i[0] = 0x28; i[0] <= 0x2b; i[0]++) {
+                test_seq_esc_charset(i, 1,
+                                     charset_graphic_94,
+                                     G_N_ELEMENTS(charset_graphic_94),
+                                     0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE);
+
+                i[1] = 0x20;
+                test_seq_esc_charset(i, 2, nullptr, 0, 0,
+                                     VTE_CMD_GnDm, VTE_CHARSET_DRCS);
+
+                i[1] = 0x21;
+                test_seq_esc_charset(i, 2,
+                                     charset_graphic_94_with_2_1,
+                                     G_N_ELEMENTS(charset_graphic_94_with_2_1),
+                                     0x40, VTE_CMD_GnDm, VTE_CHARSET_NONE);
+
+                i[1] = 0x22;
+                test_seq_esc_charset(i, 2,
+                                     charset_graphic_94_with_2_2,
+                                     G_N_ELEMENTS(charset_graphic_94_with_2_2),
+                                     0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE);
+
+                i[1] = 0x23;
+                test_seq_esc_charset(i, 2, nullptr, 0,
+                                     0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE);
+
+                /* 2/4 is multibyte charsets */
+
+                i[1] = 0x25;
+                test_seq_esc_charset(i, 2,
+                                     charset_graphic_94_with_2_5,
+                                     G_N_ELEMENTS(charset_graphic_94_with_2_5),
+                                     0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE);
+
+                i[1] = 0x26;
+                test_seq_esc_charset(i, 2,
+                                     charset_graphic_94_with_2_6,
+                                     G_N_ELEMENTS(charset_graphic_94_with_2_6),
+                                     0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE);
+
+                i[1] = 0x27;
+                test_seq_esc_charset(i, 2, nullptr, 0, 0,
+                                     VTE_CMD_GnDm, VTE_CHARSET_NONE);
+        }
+}
+
+static void
+test_seq_esc_charset_96(void)
+{
+        uint32_t i[4];
+
+        /* Single byte 96-sets */
+        for (i[0] = 0x2d; i[0] <= 0x2f; i[0]++) {
+                test_seq_esc_charset(i, 1,
+                                     charset_graphic_96,
+                                     G_N_ELEMENTS(charset_graphic_96),
+                                     0x30, VTE_CMD_GnDm, VTE_CHARSET_NONE);
+
+                i[1] = 0x20;
+                test_seq_esc_charset(i, 2, nullptr, 0, 0,
+                                     VTE_CMD_GnDm, VTE_CHARSET_DRCS);
+
+                /* 2/4 is multibyte charsets, 2/5 is DOCS. Other indermediates may be present
+                 * in Fp sequences, but none are actually in use.
+                 */
+                for (i[1] = 0x21; i[1] < 0x28; i[1]++) {
+                        if (i[1] == 0x24 || i[1] == 0x25)
+                                continue;
+
+                        test_seq_esc_charset(i, 2, nullptr, 0, 0,
+                                             VTE_CMD_GnDm, VTE_CHARSET_NONE);
+                }
+        }
+}
+
+static void
+test_seq_esc_charset_94_n(void)
+{
+        uint32_t i[4];
+
+        /* Multibyte 94-sets */
+        i[0] = 0x24;
+        for (i[1] = 0x28; i[1] <= 0x2b; i[1]++) {
+                test_seq_esc_charset(i, 2,
+                                     charset_graphic_94_n,
+                                     G_N_ELEMENTS(charset_graphic_94_n),
+                                     0x30, VTE_CMD_GnDMm, VTE_CHARSET_NONE);
+
+                i[2] = 0x20;
+                test_seq_esc_charset(i, 3, nullptr, 0, 0,
+                                     VTE_CMD_GnDMm, VTE_CHARSET_DRCS);
+
+                /* There could be one more intermediate byte. */
+                for (i[2] = 0x21; i[2] < 0x28; i[2]++) {
+                        if (i[2] == 0x24) /* TODO */
+                                continue;
+
+                        test_seq_esc_charset(i, 3, nullptr, 0, 0,
+                                             VTE_CMD_GnDMm, VTE_CHARSET_NONE);
+                }
+        }
+
+        /* As a special exception, ESC 2/4 4/[012] are also possible */
+        test_seq_esc_charset(0x40, i, 1, VTE_CMD_GnDMm, charset_graphic_94_n[0x40 - 0x30]);
+        test_seq_esc_charset(0x41, i, 1, VTE_CMD_GnDMm, charset_graphic_94_n[0x41 - 0x30]);
+        test_seq_esc_charset(0x42, i, 1, VTE_CMD_GnDMm, charset_graphic_94_n[0x42 - 0x30]);
+}
+
+static void
+test_seq_esc_charset_96_n(void)
+{
+        uint32_t i[4];
+
+        /* Multibyte 94-sets */
+        i[0] = 0x24;
+        for (i[1] = 0x2d; i[1] <= 0x2f; i[1]++) {
+                test_seq_esc_charset(i, 2, nullptr, 0, 0,
+                                     VTE_CMD_GnDMm, VTE_CHARSET_NONE);
+
+                i[2] = 0x20;
+                test_seq_esc_charset(i, 3, nullptr, 0, 0,
+                                     VTE_CMD_GnDMm, VTE_CHARSET_DRCS);
+
+                /* There could be one more intermediate byte. */
+                for (i[2] = 0x21; i[2] < 0x28; i[2]++) {
+                        test_seq_esc_charset(i, 3, nullptr, 0, 0,
+                                             VTE_CMD_GnDMm, VTE_CHARSET_NONE);
+                }
+        }
+}
+
+static void
+test_seq_esc_charset_control(void)
+{
+        uint32_t i[4];
+
+        /* C0 controls: ESC 2/1 F */
+        i[0] = 0x21;
+        test_seq_esc_charset(i, 1,
+                             charset_control_c0,
+                             G_N_ELEMENTS(charset_control_c0),
+                             0x40, VTE_CMD_CnD, VTE_CHARSET_NONE);
+
+        /* C1 controls: ESC 2/2 F */
+        i[0] = 0x22;
+        test_seq_esc_charset(i, 1,
+                             charset_control_c1,
+                             G_N_ELEMENTS(charset_control_c1),
+                             0x40, VTE_CMD_CnD, VTE_CHARSET_NONE);
+}
+
+static void
+test_seq_esc_charset_other(void)
+{
+        uint32_t i[4];
+
+        /* Other coding systems: ESC 2/5 F or ESC 2/5 2/15 F */
+        i[0] = 0x25;
+        test_seq_esc_charset(i, 1,
+                             charset_ocs_with_return,
+                             G_N_ELEMENTS(charset_ocs_with_return),
+                             0x40, VTE_CMD_DOCS, VTE_CHARSET_NONE);
+
+        i[1] = 0x2f;
+        test_seq_esc_charset(i, 2,
+                             charset_ocs_without_return,
+                             G_N_ELEMENTS(charset_ocs_without_return),
+                             0x40, VTE_CMD_DOCS, VTE_CHARSET_NONE);
+}
+
+static void
 test_seq_esc_Fpes(void)
 {
         /* Tests Fp, Fe and Ft sequences, that is ESC 3/n .. ESC 7/14 */
@@ -574,6 +810,12 @@ main(int argc,
         g_test_add_func("/vte/parser/sequences/arg", test_seq_arg);
         g_test_add_func("/vte/parser/sequences/control", test_seq_control);
         g_test_add_func("/vte/parser/sequences/escape/invalid", test_seq_esc_invalid);
+        g_test_add_func("/vte/parser/sequences/escape/charset/94", test_seq_esc_charset_94);
+        g_test_add_func("/vte/parser/sequences/escape/charset/96", test_seq_esc_charset_96);
+        g_test_add_func("/vte/parser/sequences/escape/charset/94^n", test_seq_esc_charset_94_n);
+        g_test_add_func("/vte/parser/sequences/escape/charset/96^n", test_seq_esc_charset_96_n);
+        g_test_add_func("/vte/parser/sequences/escape/charset/control", test_seq_esc_charset_control);
+        g_test_add_func("/vte/parser/sequences/escape/charset/other", test_seq_esc_charset_other);
         g_test_add_func("/vte/parser/sequences/escape/nF", test_seq_esc_nF);
         g_test_add_func("/vte/parser/sequences/escape/F[pes]", test_seq_esc_Fpes);
         g_test_add_func("/vte/parser/sequences/csi", test_seq_csi);
diff --git a/src/parser.cc b/src/parser.cc
index 9dd9b23..5cf74fe 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -27,6 +27,8 @@
 
 #include <glib.h>
 
+#include "parser-charset-tables.hh"
+
 #define WARN(num,str) do { } while (0)
 #define hweight32(v) (__builtin_popcount(v))
 #define kzalloc(n,v) calloc((n),1)
@@ -139,350 +141,272 @@ static unsigned int vte_parse_host_control(const struct vte_seq *seq)
         return VTE_CMD_NONE;
 }
 
-static int vte_charset_from_cmd(uint32_t raw, unsigned int flags, bool require_96)
+static unsigned int vte_parse_charset_94(uint32_t raw,
+                                         unsigned int flags)
 {
-#if 0
-        static const struct {
-                uint32_t raw;
-                unsigned int flags;
-        } charset_cmds[] = {
-                /* 96-compat charsets */
-                [VTE_CHARSET_ISO_LATIN1_SUPPLEMENTAL] =
-                        { .raw = 'A', .flags = 0 },
-                [VTE_CHARSET_ISO_LATIN2_SUPPLEMENTAL] =
-                        { .raw = 'B', .flags = 0 },
-                [VTE_CHARSET_ISO_LATIN5_SUPPLEMENTAL] =
-                        { .raw = 'M', .flags = 0 },
-                [VTE_CHARSET_ISO_GREEK_SUPPLEMENTAL] =
-                        { .raw = 'F', .flags = 0 },
-                [VTE_CHARSET_ISO_HEBREW_SUPPLEMENTAL] =
-                        { .raw = 'H', .flags = 0 },
-                [VTE_CHARSET_ISO_LATIN_CYRILLIC] =
-                        { .raw = 'L', .flags = 0 },
-
-                /* 94-compat charsets */
-                [VTE_CHARSET_DEC_SPECIAL_GRAPHIC] =
-                        { .raw = '0', .flags = 0 },
-                [VTE_CHARSET_DEC_SUPPLEMENTAL] =
-                        { .raw = '5', .flags = VTE_SEQ_FLAG_PERCENT },
-                [VTE_CHARSET_DEC_TECHNICAL] =
-                        { .raw = '>', .flags = 0 },
-                [VTE_CHARSET_CYRILLIC_DEC] =
-                        { .raw = '4', .flags = VTE_SEQ_FLAG_AND },
-                [VTE_CHARSET_DUTCH_NRCS] =
-                        { .raw = '4', .flags = 0 },
-                [VTE_CHARSET_FINNISH_NRCS] =
-                        { .raw = '5', .flags = 0 },
-                [VTE_CHARSET_FRENCH_NRCS] =
-                        { .raw = 'R', .flags = 0 },
-                [VTE_CHARSET_FRENCH_CANADIAN_NRCS] =
-                        { .raw = '9', .flags = 0 },
-                [VTE_CHARSET_GERMAN_NRCS] =
-                        { .raw = 'K', .flags = 0 },
-                [VTE_CHARSET_GREEK_DEC] =
-                        { .raw = '?', .flags = VTE_SEQ_FLAG_DQUOTE },
-                [VTE_CHARSET_GREEK_NRCS] =
-                        { .raw = '>', .flags = VTE_SEQ_FLAG_DQUOTE },
-                [VTE_CHARSET_HEBREW_DEC] =
-                        { .raw = '4', .flags = VTE_SEQ_FLAG_DQUOTE },
-                [VTE_CHARSET_HEBREW_NRCS] =
-                        { .raw = '=', .flags = VTE_SEQ_FLAG_PERCENT },
-                [VTE_CHARSET_ITALIAN_NRCS] =
-                        { .raw = 'Y', .flags = 0 },
-                [VTE_CHARSET_NORWEGIAN_DANISH_NRCS] =
-                        { .raw = '`', .flags = 0 },
-                [VTE_CHARSET_PORTUGUESE_NRCS] =
-                        { .raw = '6', .flags = VTE_SEQ_FLAG_PERCENT },
-                [VTE_CHARSET_RUSSIAN_NRCS] =
-                        { .raw = '5', .flags = VTE_SEQ_FLAG_AND },
-                [VTE_CHARSET_SCS_NRCS] =
-                        { .raw = '3', .flags = VTE_SEQ_FLAG_PERCENT },
-                [VTE_CHARSET_SPANISH_NRCS] =
-                        { .raw = 'Z', .flags = 0 },
-                [VTE_CHARSET_SWEDISH_NRCS] =
-                        { .raw = '7', .flags = 0 },
-                [VTE_CHARSET_SWISS_NRCS] =
-                        { .raw = '=', .flags = 0 },
-                [VTE_CHARSET_TURKISH_DEC] =
-                        { .raw = '0', .flags = VTE_SEQ_FLAG_PERCENT },
-                [VTE_CHARSET_TURKISH_NRCS] =
-                        { .raw = '2', .flags = VTE_SEQ_FLAG_PERCENT },
-
-                /* special charsets */
-                [VTE_CHARSET_USERPREF_SUPPLEMENTAL] =
-                        { .raw = '<', .flags = 0 },
-
-                /* secondary choices */
-                [VTE_CHARSET_N + VTE_CHARSET_FINNISH_NRCS] =
-                        { .raw = 'C', .flags = 0 },
-                [VTE_CHARSET_N + VTE_CHARSET_FRENCH_NRCS] =
-                        { .raw = 'f', .flags = 0 },
-                [VTE_CHARSET_N + VTE_CHARSET_FRENCH_CANADIAN_NRCS] =
-                        { .raw = 'Q', .flags = 0 },
-                [VTE_CHARSET_N + VTE_CHARSET_NORWEGIAN_DANISH_NRCS] =
-                        { .raw = 'E', .flags = 0 },
-                [VTE_CHARSET_N + VTE_CHARSET_SWEDISH_NRCS] =
-                        /* unused; conflicts with ISO_HEBREW */
-                        { .raw = 'H', .flags = 0 },
-
-                /* tertiary choices */
-                [VTE_CHARSET_N + VTE_CHARSET_N +
-                 VTE_CHARSET_NORWEGIAN_DANISH_NRCS] =
-                        { .raw = '6', .flags = 0 },
-        };
-        size_t i, cs;
+        assert (raw >= 0x30 && raw < 0x7f);
 
-        /*
-         * Secondary choice on SWEDISH_NRCS and primary choice on
-         * ISO_HEBREW_SUPPLEMENTAL have a conflict: raw=="H", flags==0.
-         * We always choose the ISO 96-compat set, which is what VT510 does.
-         */
+        if (flags & VTE_SEQ_FLAG_SPACE)
+                return VTE_CHARSET_DRCS;
 
-        for (i = 0; i < ARRAY_SIZE(charset_cmds); ++i) {
-                if (charset_cmds[i].raw == raw &&
-                    charset_cmds[i].flags == flags) {
-                        cs = i;
-                        while (cs >= VTE_CHARSET_N)
-                                cs -= VTE_CHARSET_N;
-
-                        if (!require_96 ||
-                            cs < VTE_CHARSET_96_N ||
-                            cs >= VTE_CHARSET_94_N)
-                                return cs;
-                }
+        switch (flags) {
+        case 0:
+                if (raw < (0x30 + G_N_ELEMENTS(charset_graphic_94)))
+                        return charset_graphic_94[raw - 0x30];
+                break;
+
+        case VTE_SEQ_FLAG_BANG:
+                if (raw >= 0x40 && (raw < 0x40 + G_N_ELEMENTS(charset_graphic_94_with_2_1)))
+                        return charset_graphic_94_with_2_1[raw - 0x40];
+                break;
+
+        case VTE_SEQ_FLAG_DQUOTE:
+                if (raw < (0x30 + G_N_ELEMENTS(charset_graphic_94_with_2_2)))
+                        return charset_graphic_94_with_2_2[raw - 0x30];
+                break;
+
+        case VTE_SEQ_FLAG_HASH:
+                break;
+
+        case VTE_SEQ_FLAG_CASH:
+                if (raw < (0x30 + G_N_ELEMENTS(charset_graphic_94_n)))
+                        return charset_graphic_94_n[raw - 0x30];
+                break;
+
+        case VTE_SEQ_FLAG_PERCENT:
+                if (raw < (0x30 + G_N_ELEMENTS(charset_graphic_94_with_2_5)))
+                        return charset_graphic_94_with_2_5[raw - 0x30];
+                break;
+
+        case VTE_SEQ_FLAG_AND:
+                if (raw < (0x30 + G_N_ELEMENTS(charset_graphic_94_with_2_6)))
+                        return charset_graphic_94_with_2_6[raw - 0x30];
+                break;
         }
-#endif
-        return -ENOENT;
+
+        return VTE_CHARSET_NONE;
 }
 
-static unsigned int vte_parse_host_escape(const struct vte_seq *seq,
-                                             unsigned int *cs_out)
+static unsigned int vte_parse_charset_96(uint32_t raw,
+                                         unsigned int flags)
 {
-        unsigned int t, flags;
-        int cs;
+        assert (raw >= 0x30 && raw < 0x7f);
 
-        flags = seq->intermediates;
-        t = VTE_SEQ_FLAG_POPEN | VTE_SEQ_FLAG_PCLOSE |
-            VTE_SEQ_FLAG_MULT  | VTE_SEQ_FLAG_PLUS   |
-            VTE_SEQ_FLAG_MINUS | VTE_SEQ_FLAG_DOT    |
-            VTE_SEQ_FLAG_SLASH;
+        if (flags == 0) { /* Graphic 96-set */
+                if (raw < (0x30 + G_N_ELEMENTS(charset_graphic_96)))
+                        return charset_graphic_96[raw - 0x30];
+        } else if (flags & VTE_SEQ_FLAG_SPACE) { /* DRCS */
+                return VTE_CHARSET_DRCS;
+        }
 
-        if (hweight32(flags & t) == 1) {
-                switch (flags & t) {
-                case VTE_SEQ_FLAG_POPEN:
-                case VTE_SEQ_FLAG_PCLOSE:
-                case VTE_SEQ_FLAG_MULT:
-                case VTE_SEQ_FLAG_PLUS:
-                        cs = vte_charset_from_cmd(seq->terminator,
-                                                     flags & ~t, false);
-                        break;
-                case VTE_SEQ_FLAG_MINUS:
-                case VTE_SEQ_FLAG_DOT:
-                case VTE_SEQ_FLAG_SLASH:
-                        cs = vte_charset_from_cmd(seq->terminator,
-                                                     flags & ~t, true);
-                        break;
-                default:
-                        cs = -ENOENT;
-                        break;
-                }
+        return VTE_CHARSET_NONE;
+}
 
-                if (cs >= 0) {
-                        if (cs_out)
-                                *cs_out = cs;
-                        return VTE_CMD_SCS;
-                }
+static unsigned int vte_parse_charset_ocs(uint32_t raw,
+                                          unsigned int flags)
+{
+        assert (raw >= 0x30 && raw < 0x7f);
+
+        if (flags == VTE_SEQ_FLAG_PERCENT) {
+                /* OCS with standard return */
+                if (raw >= 0x40 && raw < (0x40 + G_N_ELEMENTS(charset_ocs_with_return)))
+                        return charset_ocs_with_return[raw - 0x40];
+        } else if (flags == (VTE_SEQ_FLAG_PERCENT | VTE_SEQ_FLAG_SLASH)) {
+                /* OCS without standard return */
+                if (raw >= 0x40 && raw < (0x40 + G_N_ELEMENTS(charset_ocs_without_return)))
+                        return charset_ocs_without_return[raw - 0x40];
+        }
 
-                /* looked like a charset-cmd but wasn't; continue */
+        return VTE_CHARSET_NONE;
+}
+
+static unsigned int vte_parse_charset_control(uint32_t raw,
+                                              unsigned int flags)
+{
+        assert (raw >= 0x30 && raw < 0x7f);
+
+        if (flags == VTE_SEQ_FLAG_BANG) { /* C0 controls */
+                if (raw >= 0x40 && raw < (0x40 + G_N_ELEMENTS(charset_control_c0)))
+                        return charset_control_c0[raw - 0x40];
+        } else if (flags == VTE_SEQ_FLAG_DQUOTE) { /* C1 controls */
+                if (raw >= 0x40 && raw < (0x40 + G_N_ELEMENTS(charset_control_c1)))
+                        return charset_control_c1[raw - 0x40];
         }
 
-        switch (seq->terminator) {
-        case '3':
-                if (flags == VTE_SEQ_FLAG_HASH) /* DECDHL top-half */
-                        return VTE_CMD_DECDHL_TH;
-                break;
-        case '4':
-                if (flags == VTE_SEQ_FLAG_HASH) /* DECDHL bottom-half */
-                        return VTE_CMD_DECDHL_BH;
-                break;
-        case '5':
-                if (flags == VTE_SEQ_FLAG_HASH) /* DECSWL */
-                        return VTE_CMD_DECSWL;
-                break;
-        case '6':
-                if (flags == 0) /* DECBI */
+        return VTE_CHARSET_NONE;
+}
+
+static unsigned int vte_parse_host_escape(const struct vte_seq *seq,
+                                          unsigned int *cs_out)
+{
+        unsigned int const flags = seq->intermediates;
+
+        if (flags == 0) {
+                switch (seq->terminator) {
+                case '6': /* DECBI */
                         return VTE_CMD_DECBI;
-                else if (flags == VTE_SEQ_FLAG_HASH) /* DECDWL */
-                        return VTE_CMD_DECDWL;
-                break;
-        case '7':
-                if (flags == 0) /* DECSC */
+                case '7': /* DECSC */
                         return VTE_CMD_DECSC;
-                break;
-        case '8':
-                if (flags == 0) /* DECRC */
+                case '8': /* DECRC */
                         return VTE_CMD_DECRC;
-                else if (flags == VTE_SEQ_FLAG_HASH) /* DECALN */
-                        return VTE_CMD_DECALN;
-                break;
-        case '9':
-                if (flags == 0) /* DECFI */
+                case '9': /* DECFI */
                         return VTE_CMD_DECFI;
-                break;
-        case '<':
-                if (flags == 0) /* DECANM */
+                case '<': /* DECANM */
                         return VTE_CMD_DECANM;
-                break;
-        case '=':
-                if (flags == 0) /* DECKPAM */
+                case '=': /* DECKPAM */
                         return VTE_CMD_DECKPAM;
-                break;
-        case '>':
-                if (flags == 0) /* DECKPNM */
+                case '>': /* DECKPNM */
                         return VTE_CMD_DECKPNM;
-                break;
-        case '@':
-                if (flags == VTE_SEQ_FLAG_PERCENT) {
-                        /* Select default char-set */
-                        return VTE_CMD_XTERM_SDCS;
-                }
-                break;
-        case 'D':
-                if (flags == 0) /* IND */
+                case 'D': /* IND */
                         return VTE_CMD_IND;
-                break;
-        case 'E':
-                if (flags == 0) /* NEL */
+                case 'E': /* NEL */
                         return VTE_CMD_NEL;
-                break;
-        case 'F':
-                if (flags == 0) /* Cursor to lower-left corner of screen */
+                case 'F': /* Cursor to lower-left corner of screen */
                         return VTE_CMD_XTERM_CLLHP;
-                else if (flags == VTE_SEQ_FLAG_SPACE) /* S7C1T */
-                        return VTE_CMD_S7C1T;
-                break;
-        case 'G':
-                if (flags == VTE_SEQ_FLAG_SPACE) { /* S8C1T */
-                        return VTE_CMD_S8C1T;
-                } else if (flags == VTE_SEQ_FLAG_PERCENT) {
-                        /* Select UTF-8 character set */
-                        return VTE_CMD_XTERM_SUCS;
-                }
-                break;
-        case 'H':
-                if (flags == 0) /* HTS */
+                case 'H': /* HTS */
                         return VTE_CMD_HTS;
-                break;
-        case 'L':
-                if (flags == VTE_SEQ_FLAG_SPACE) {
-                        /* Set ANSI conformance level 1 */
-                        return VTE_CMD_XTERM_SACL1;
-                }
-                break;
-        case 'M':
-                if (flags == 0) { /* RI */
+                case 'M': /* RI */
                         return VTE_CMD_RI;
-                } else if (flags == VTE_SEQ_FLAG_SPACE) {
-                        /* Set ANSI conformance level 2 */
-                        return VTE_CMD_XTERM_SACL2;
-                }
-                break;
-        case 'N':
-                if (flags == 0) { /* SS2 */
+                case 'N': /* SS2 */
                         return VTE_CMD_SS2;
-                } else if (flags == VTE_SEQ_FLAG_SPACE) {
-                        /* Set ANSI conformance level 3 */
-                        return VTE_CMD_XTERM_SACL3;
-                }
-                break;
-        case 'O':
-                if (flags == 0) /* SS3 */
+                case 'O': /* SS3 */
                         return VTE_CMD_SS3;
-                break;
-        case 'P':
-                if (flags == 0) { /* DCS */
+                case 'P': /* DCS */
                         /* this is already handled by the state-machine */
                         break;
-                }
-                break;
-        case 'V':
-                if (flags == 0) /* SPA */
+                case 'V': /* SPA */
                         return VTE_CMD_SPA;
-                break;
-        case 'W':
-                if (flags == 0) /* EPA */
+                case 'W': /* EPA */
                         return VTE_CMD_EPA;
-                break;
-        case 'X':
-                if (flags == 0) { /* SOS */
+                case 'X': /* SOS */
                         /* this is already handled by the state-machine */
                         break;
-                }
-                break;
-        case 'Z':
-                if (flags == 0) /* DECID */
+                case 'Z': /* DECID */
                         return VTE_CMD_DECID;
-                break;
-        case '[':
-                if (flags == 0) { /* CSI */
+                case '[': /* CSI */
                         /* this is already handled by the state-machine */
                         break;
-                }
-                break;
-        case '\\':
-                if (flags == 0) /* ST */
+                case '\\': /* ST */
                         return VTE_CMD_ST;
-                break;
-        case ']':
-                if (flags == 0) { /* OSC */
+                case ']': /* OSC */
                         /* this is already handled by the state-machine */
                         break;
-                }
-                break;
-        case '^':
-                if (flags == 0) { /* PM */
+                case '^': /* PM */
                         /* this is already handled by the state-machine */
                         break;
-                }
-                break;
-        case '_':
-                if (flags == 0) { /* APC */
+                case '_': /* APC */
                         /* this is already handled by the state-machine */
                         break;
-                }
-                break;
-        case 'c':
-                if (flags == 0) /* RIS */
+                case 'c': /* RIS */
                         return VTE_CMD_RIS;
-                break;
-        case 'l':
-                if (flags == 0) /* Memory lock */
+                case 'd': /* CMD */
+                        return VTE_CMD_CMD;
+                case 'l': /* Memory lock */
                         return VTE_CMD_XTERM_MLHP;
-                break;
-        case 'm':
-                if (flags == 0) /* Memory unlock */
+                case 'm': /* Memory unlock */
                         return VTE_CMD_XTERM_MUHP;
-                break;
-        case 'n':
-                if (flags == 0) /* LS2 */
+                case 'n': /* LS2 */
                         return VTE_CMD_LS2;
-                break;
-        case 'o':
-                if (flags == 0) /* LS3 */
+                case 'o': /* LS3 */
                         return VTE_CMD_LS3;
-                break;
-        case '|':
-                if (flags == 0) /* LS3R */
+                case '|': /* LS3R */
                         return VTE_CMD_LS3R;
-                break;
-        case '}':
-                if (flags == 0) /* LS2R */
+                case '}': /* LS2R */
                         return VTE_CMD_LS2R;
-                break;
-        case '~':
-                if (flags == 0) /* LS1R */
+                case '~': /* LS1R */
                         return VTE_CMD_LS1R;
+                }
+
+                return VTE_CMD_NONE;
+        }
+
+        unsigned int const g_designators =
+                VTE_SEQ_FLAG_POPEN | VTE_SEQ_FLAG_PCLOSE |
+                VTE_SEQ_FLAG_MULT  | VTE_SEQ_FLAG_PLUS   |
+                VTE_SEQ_FLAG_MINUS | VTE_SEQ_FLAG_DOT    |
+                VTE_SEQ_FLAG_SLASH;
+
+        if (hweight32(flags & g_designators) == 1) {
+                unsigned int const remaining_flags = flags & ~g_designators;
+                int cmd = (remaining_flags & VTE_SEQ_FLAG_CASH) ? VTE_CMD_GnDMm : VTE_CMD_GnDm;
+                int cs = VTE_CHARSET_NONE;
+
+                switch (flags & g_designators) {
+                case VTE_SEQ_FLAG_POPEN:
+                case VTE_SEQ_FLAG_PCLOSE:
+                case VTE_SEQ_FLAG_MULT:
+                case VTE_SEQ_FLAG_PLUS:
+                        cs = vte_parse_charset_94(seq->terminator, remaining_flags);
+                        break;
+                case VTE_SEQ_FLAG_SLASH:
+                        if (remaining_flags == VTE_SEQ_FLAG_PERCENT) { /* DOCS */
+                                cmd = VTE_CMD_DOCS;
+                                cs = vte_parse_charset_ocs(seq->terminator, /* all */ flags);
+                                break;
+                        }
+                        /* fallthrough */
+                case VTE_SEQ_FLAG_MINUS:
+                case VTE_SEQ_FLAG_DOT:
+                        cs = vte_parse_charset_96(seq->terminator, remaining_flags);
+                        break;
+                }
+
+                if (cs_out)
+                        *cs_out = cs;
+
+                return cmd;
+        }
+
+        switch (flags) {
+        case VTE_SEQ_FLAG_SPACE: /* ACS */
+                return VTE_CMD_ACS;
+
+        case VTE_SEQ_FLAG_BANG: /* C0-designate */
+        case VTE_SEQ_FLAG_DQUOTE: /* C1-designate */
+                if (cs_out)
+                        *cs_out = vte_parse_charset_control(seq->terminator, flags);
+                return VTE_CMD_CnD;
+
+        case VTE_SEQ_FLAG_HASH:
+                switch (seq->terminator) {
+                case '3': /* DECDHL top-half */
+                        return VTE_CMD_DECDHL_TH;
+                case '4': /* DECDHL bottom-half */
+                        return VTE_CMD_DECDHL_BH;
+                case '5': /* DECSWL */
+                        return VTE_CMD_DECSWL;
+                case '6': /* DECDWL */
+                        return VTE_CMD_DECDWL;
+                case '8': /* DECALN */
+                        return VTE_CMD_DECALN;
+                }
                 break;
+
+        case VTE_SEQ_FLAG_CASH:
+                /* For compatibility with an earlier version of ISO-2022,
+                 * ESC 2/4 4/0, ESC 2/4 4/1 and ESC 2/4 4/2 designate G0
+                 * sets (i.e., without the 2/8 as 2nd intermediate byte).
+                 */
+                switch (seq->terminator) {
+                case '@':
+                case 'A':
+                case 'B': /* G0-designate multibyte charset */
+                        if (cs_out)
+                                *cs_out = vte_parse_charset_94(seq->terminator,
+                                                               flags /* | VTE_SEQ_FLAG_POPEN */);
+                        return VTE_CMD_GnDMm;
+                }
+                break;
+
+        case VTE_SEQ_FLAG_PERCENT: /* DOCS */
+        case VTE_SEQ_FLAG_PERCENT | VTE_SEQ_FLAG_SLASH: /* DOCS, but already handled above */
+                if (cs_out)
+                        *cs_out = vte_parse_charset_ocs(seq->terminator, flags);
+
+                return VTE_CMD_DOCS;
+
+        case VTE_SEQ_FLAG_AND: /* IRR */
+                return VTE_CMD_IRR;
         }
 
         return VTE_CMD_NONE;
diff --git a/src/parser.hh b/src/parser.hh
index 8718a18..68b440e 100644
--- a/src/parser.hh
+++ b/src/parser.hh
@@ -122,58 +122,15 @@ enum {
 };
 
 enum {
-        /*
-         * Charsets: DEC marks charsets according to "Digital Equ. Corp.".
-         *           NRCS marks charsets according to the "National Replacement
-         *           Character Sets". ISO marks charsets according to ISO-8859.
-         * The USERDEF charset is special and can be modified by the host.
-         */
-
-        VTE_CHARSET_NONE,
-
-        /* 96-compat charsets */
-        VTE_CHARSET_ISO_LATIN1_SUPPLEMENTAL,
-        VTE_CHARSET_BRITISH_NRCS = VTE_CHARSET_ISO_LATIN1_SUPPLEMENTAL,
-        VTE_CHARSET_ISO_LATIN2_SUPPLEMENTAL,
-        VTE_CHARSET_AMERICAN_NRCS = VTE_CHARSET_ISO_LATIN2_SUPPLEMENTAL,
-        VTE_CHARSET_ISO_LATIN5_SUPPLEMENTAL,
-        VTE_CHARSET_ISO_GREEK_SUPPLEMENTAL,
-        VTE_CHARSET_ISO_HEBREW_SUPPLEMENTAL,
-        VTE_CHARSET_ISO_LATIN_CYRILLIC,
-
-        VTE_CHARSET_96_N,
-
-        /* 94-compat charsets */
-        VTE_CHARSET_DEC_SPECIAL_GRAPHIC = VTE_CHARSET_96_N,
-        VTE_CHARSET_DEC_SUPPLEMENTAL,
-        VTE_CHARSET_DEC_TECHNICAL,
-        VTE_CHARSET_CYRILLIC_DEC,
-        VTE_CHARSET_DUTCH_NRCS,
-        VTE_CHARSET_FINNISH_NRCS,
-        VTE_CHARSET_FRENCH_NRCS,
-        VTE_CHARSET_FRENCH_CANADIAN_NRCS,
-        VTE_CHARSET_GERMAN_NRCS,
-        VTE_CHARSET_GREEK_DEC,
-        VTE_CHARSET_GREEK_NRCS,
-        VTE_CHARSET_HEBREW_DEC,
-        VTE_CHARSET_HEBREW_NRCS,
-        VTE_CHARSET_ITALIAN_NRCS,
-        VTE_CHARSET_NORWEGIAN_DANISH_NRCS,
-        VTE_CHARSET_PORTUGUESE_NRCS,
-        VTE_CHARSET_RUSSIAN_NRCS,
-        VTE_CHARSET_SCS_NRCS,
-        VTE_CHARSET_SPANISH_NRCS,
-        VTE_CHARSET_SWEDISH_NRCS,
-        VTE_CHARSET_SWISS_NRCS,
-        VTE_CHARSET_TURKISH_DEC,
-        VTE_CHARSET_TURKISH_NRCS,
-
-        VTE_CHARSET_94_N,
-
-        /* special charsets */
-        VTE_CHARSET_USERPREF_SUPPLEMENTAL = VTE_CHARSET_94_N,
-
-        VTE_CHARSET_N,
+#define _VTE_CHARSET_PASTE(name) VTE_CHARSET_##name,
+#define _VTE_CHARSET(name) _VTE_CHARSET_PASTE(name)
+#define _VTE_CHARSET_ALIAS_PASTE(name1,name2) VTE_CHARSET_##name1 = VTE_CHARSET_##name2,
+#define _VTE_CHARSET_ALIAS(name1,name2) _VTE_CHARSET_ALIAS_PASTE(name1,name2)
+#include "parser-charset.hh"
+#undef _VTE_CHARSET_PASTE
+#undef _VTE_CHARSET
+#undef _VTE_CHARSET_ALIAS_PASTE
+#undef _VTE_CHARSET_ALIAS
 };
 
 struct vte_seq {
diff --git a/src/vteseq-list.hh b/src/vteseq-list.hh
index 1dda448..ddc666b 100644
--- a/src/vteseq-list.hh
+++ b/src/vteseq-list.hh
@@ -48,15 +48,8 @@ SEQUENCE_HANDLER(dec_device_status_report)
 SEQUENCE_HANDLER(dec_media_copy)
 SEQUENCE_HANDLER(decreset)
 SEQUENCE_HANDLER(decset)
-SEQUENCE_HANDLER(default_character_set)
 SEQUENCE_HANDLER(delete_characters)
 SEQUENCE_HANDLER(delete_lines)
-SEQUENCE_HANDLER(designate_g0_british)
-SEQUENCE_HANDLER(designate_g0_line_drawing)
-SEQUENCE_HANDLER(designate_g0_plain)
-SEQUENCE_HANDLER(designate_g1_british)
-SEQUENCE_HANDLER(designate_g1_line_drawing)
-SEQUENCE_HANDLER(designate_g1_plain)
 SEQUENCE_HANDLER(device_control_string)
 SEQUENCE_HANDLER(device_status_report)
 SEQUENCE_HANDLER(double_height_bottom_half)
@@ -151,6 +144,5 @@ SEQUENCE_HANDLER(tab)
 SEQUENCE_HANDLER(tab_clear)
 SEQUENCE_HANDLER(tab_set)
 SEQUENCE_HANDLER(urxvt_777)
-SEQUENCE_HANDLER(utf_8_character_set)
 SEQUENCE_HANDLER(vertical_tab)
 SEQUENCE_HANDLER(window_manipulation)
diff --git a/src/vteseq.cc b/src/vteseq.cc
index bea3ee8..94407bd 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -886,56 +886,6 @@ VteTerminalPrivate::seq_nop(vte::parser::Params const& params)
 }
 
 void
-VteTerminalPrivate::set_character_replacements(unsigned slot,
-                                               VteCharacterReplacement replacement)
-{
-        g_assert(slot < G_N_ELEMENTS(m_character_replacements));
-        m_character_replacements[slot] = replacement;
-}
-
-/* G0 character set is a pass-thru (no mapping). */
-void
-VteTerminalPrivate::seq_designate_g0_plain(vte::parser::Params const& params)
-{
-        set_character_replacements(0, VTE_CHARACTER_REPLACEMENT_NONE);
-}
-
-/* G0 character set is DEC Special Character and Line Drawing Set. */
-void
-VteTerminalPrivate::seq_designate_g0_line_drawing(vte::parser::Params const& params)
-{
-        set_character_replacements(0, VTE_CHARACTER_REPLACEMENT_LINE_DRAWING);
-}
-
-/* G0 character set is British (# is converted to £). */
-void
-VteTerminalPrivate::seq_designate_g0_british(vte::parser::Params const& params)
-{
-        set_character_replacements(0, VTE_CHARACTER_REPLACEMENT_BRITISH);
-}
-
-/* G1 character set is a pass-thru (no mapping). */
-void
-VteTerminalPrivate::seq_designate_g1_plain(vte::parser::Params const& params)
-{
-        set_character_replacements(1, VTE_CHARACTER_REPLACEMENT_NONE);
-}
-
-/* G1 character set is DEC Special Character and Line Drawing Set. */
-void
-VteTerminalPrivate::seq_designate_g1_line_drawing(vte::parser::Params const& params)
-{
-        set_character_replacements(1, VTE_CHARACTER_REPLACEMENT_LINE_DRAWING);
-}
-
-/* G1 character set is British (# is converted to £). */
-void
-VteTerminalPrivate::seq_designate_g1_british(vte::parser::Params const& params)
-{
-        set_character_replacements(1, VTE_CHARACTER_REPLACEMENT_BRITISH);
-}
-
-void
 VteTerminalPrivate::set_character_replacement(unsigned slot)
 {
         g_assert(slot < G_N_ELEMENTS(m_character_replacements));
@@ -3114,7 +3064,6 @@ UNIMPLEMENTED_SEQUENCE_HANDLER(change_tek_foreground_color_bel)
 UNIMPLEMENTED_SEQUENCE_HANDLER(change_tek_foreground_color_st)
 UNIMPLEMENTED_SEQUENCE_HANDLER(cursor_lower_left)
 UNIMPLEMENTED_SEQUENCE_HANDLER(dec_media_copy)
-UNIMPLEMENTED_SEQUENCE_HANDLER(default_character_set)
 UNIMPLEMENTED_SEQUENCE_HANDLER(device_control_string)
 UNIMPLEMENTED_SEQUENCE_HANDLER(double_height_bottom_half)
 UNIMPLEMENTED_SEQUENCE_HANDLER(double_height_top_half)
@@ -3154,7 +3103,6 @@ UNIMPLEMENTED_SEQUENCE_HANDLER(single_shift_g3)
 UNIMPLEMENTED_SEQUENCE_HANDLER(single_width)
 UNIMPLEMENTED_SEQUENCE_HANDLER(start_of_guarded_area)
 UNIMPLEMENTED_SEQUENCE_HANDLER(start_or_end_of_string)
-UNIMPLEMENTED_SEQUENCE_HANDLER(utf_8_character_set)
 
 #undef UNIMPLEMENTED_UNIMPLEMENTED_SEQUENCE_HANDLER
 
@@ -3243,6 +3191,69 @@ VteTerminalPrivate::GRAPHIC(vte::parser::Sequence const& seq)
         insert_char(seq.terminator(), false, false);
 }
 
+
+void
+VteTerminalPrivate::ACS(vte::parser::Sequence const& seq)
+{
+        /* ACS - announce-code-structure
+         *
+         * The final byte of the sequence identifies the facility number
+         * from 1 to 62 starting with 4/01.
+         *
+         * References: ECMA-35 § 15.2
+         */
+
+        /* Since we don't implement ISO-2022 anymore, we can mostly ignore this */
+
+        switch (seq.terminator() - 0x40) {
+        case 6:
+                /*
+                 * This causes the terminal to start sending C1 controls as 7bit
+                 * sequences instead of 8bit C1 controls.
+                 * This is ignored if the terminal is below level-2 emulation mode
+                 * (VT100 and below), the terminal already sends 7bit controls then.
+                 */
+#if 0
+                if (screen->conformance_level > VTE_CONFORMANCE_LEVEL_VT100)
+                        screen->flags |= VTE_FLAG_7BIT_MODE;
+#endif
+                break;
+
+        case 7:
+                /*
+                 * This causes the terminal to start sending C1 controls as 8bit C1
+                 * control instead of 7bit sequences.
+                 * This is ignored if the terminal is below level-2 emulation mode
+                 * (VT100 and below). The terminal always sends 7bit controls in those
+                 * modes.
+                 */
+#if 0
+                if (screen->conformance_level > VTE_CONFORMANCE_LEVEL_VT100)
+                        screen->flags &= ~VTE_FLAG_7BIT_MODE;
+#endif
+                break;
+
+        case 12:
+                /* Use Level 1 of ECMA-43
+                 *
+                 * Probably not worth implementing.
+                 */
+                break;
+        case 13:
+                /* Use Level 2 of ECMA-43
+                 *
+                 * Probably not worth implementing.
+                 */
+                break;
+        case 14:
+                /* Use Level 3 of ECMA-43
+                 *
+                 * Probably not worth implementing.
+                 */
+                break;
+        }
+}
+
 void
 VteTerminalPrivate::BEL(vte::parser::Sequence const& seq)
 {
@@ -3358,6 +3369,16 @@ VteTerminalPrivate::CHT(vte::parser::Sequence const& seq)
 }
 
 void
+VteTerminalPrivate::CMD(vte::parser::Sequence const& seq)
+{
+        /*
+         * CMD - coding method delimiter
+         *
+         * References: ECMA-35 §15.3
+         */
+}
+
+void
 VteTerminalPrivate::CNL(vte::parser::Sequence const& seq)
 {
         /*
@@ -3549,6 +3570,22 @@ VteTerminalPrivate::CUU(vte::parser::Sequence const& seq)
         seq_cursor_up(seq);
 }
 
+
+void
+VteTerminalPrivate::CnD(vte::parser::Sequence const& seq)
+{
+        /*
+         * CnD - Cn-designate
+         *
+         * Designate a set of control functions.
+         *
+         * References: ECMA-35 § 14.2
+         *             ISO 2375 IR
+         */
+
+        /* Since we don't implement ISO-2022 anymore, we can ignore this */
+}
+
 void
 VteTerminalPrivate::DA1(vte::parser::Sequence const& seq)
 {
@@ -4854,6 +4891,19 @@ VteTerminalPrivate::DL(vte::parser::Sequence const& seq)
 }
 
 void
+VteTerminalPrivate::DOCS(vte::parser::Sequence const& seq)
+{
+        /*
+         * DOCS - designate other coding systyem
+         *
+         * References: ECMA-35 § 15.4
+         *             ISO 2375 IR
+         *
+         * TODO: implement (bug #787228)
+         */
+}
+
+void
 VteTerminalPrivate::DSR_ANSI(vte::parser::Sequence const& seq)
 {
         /*
@@ -4971,6 +5021,78 @@ VteTerminalPrivate::FF(vte::parser::Sequence const& seq)
 }
 
 void
+VteTerminalPrivate::GnDm(vte::parser::Sequence const& seq)
+{
+        /*
+         * GnDm - Gn-designate 9m-charset
+         *
+         * Designate character sets to G-sets.
+         *
+         * References: ECMA-35 § 14.3
+         *             ISO 2375 IR
+         */
+
+        /* Since we don't implement ISO-2022 anymore, we can mostly ignore this. */
+
+        VteCharacterReplacement replacement;
+        switch (seq.charset()) {
+        case VTE_CHARSET_DEC_SPECIAL_GRAPHIC:
+                /* Some characters replaced by line drawing characters.
+                 * This is still used by ncurses :-(
+                 */
+                replacement = VTE_CHARACTER_REPLACEMENT_LINE_DRAWING;
+                break;
+
+        case VTE_CHARSET_BRITISH_NRCS:
+                /* # is converted to £ */
+                /* FIXME: Remove this */
+                replacement = VTE_CHARACTER_REPLACEMENT_BRITISH;
+                break;
+
+        /* FIXME: are any of the other charsets still useful? */
+        default:
+                replacement = VTE_CHARACTER_REPLACEMENT_NONE;
+                break;
+        }
+
+        unsigned int slot = 0;
+        if (seq.intermediates() & VTE_SEQ_FLAG_POPEN)
+                slot = 0;
+        else if (seq.intermediates() & VTE_SEQ_FLAG_PCLOSE)
+                slot = 1;
+        else if (seq.intermediates() & VTE_SEQ_FLAG_MULT)
+                slot = 2;
+        else if (seq.intermediates() & VTE_SEQ_FLAG_PLUS)
+                slot = 3;
+        else if (seq.intermediates() & VTE_SEQ_FLAG_MINUS)
+                slot = 1;
+        else if (seq.intermediates() & VTE_SEQ_FLAG_DOT)
+                slot = 2;
+        else if (seq.intermediates() & VTE_SEQ_FLAG_SLASH)
+                slot = 3;
+
+        if (slot >= G_N_ELEMENTS(m_character_replacements))
+                return;
+
+        m_character_replacements[slot] = replacement;
+}
+
+void
+VteTerminalPrivate::GnDMm(vte::parser::Sequence const& seq)
+{
+        /*
+         * GnDm - Gn-designate multibyte 9m-charset
+         *
+         * Designate multibyte character sets to G-sets.
+         *
+         * References: ECMA-35 § 14.3
+         *             ISO 2375 IR
+         */
+
+        /* Since we don't implement ISO-2022 anymore, we can ignore this */
+}
+
+void
 VteTerminalPrivate::HPA(vte::parser::Sequence const& seq)
 {
         /*
@@ -5149,6 +5271,20 @@ VteTerminalPrivate::IND(vte::parser::Sequence const& seq)
 }
 
 void
+VteTerminalPrivate::IRR(vte::parser::Sequence const& seq)
+{
+        /*
+         * IRR - identify-revised-registration
+         *
+         * References: ECMA-35 § 14.5
+         *
+         * Probably not worth implementing.
+         */
+
+        /* Since we don't implement ISO-2022 anymore, we can ignore this */
+}
+
+void
 VteTerminalPrivate::LF(vte::parser::Sequence const& seq)
 {
         /*
@@ -5431,118 +5567,6 @@ VteTerminalPrivate::RM_DEC(vte::parser::Sequence const& seq)
 }
 
 void
-VteTerminalPrivate::S7C1T(vte::parser::Sequence const& seq)
-{
-        /*
-         * S7C1T - set-7bit-c1-terminal
-         * This causes the terminal to start sending C1 controls as 7bit
-         * sequences instead of 8bit C1 controls.
-         * This is ignored if the terminal is below level-2 emulation mode
-         * (VT100 and below), the terminal already sends 7bit controls then.
-         */
-
-#if 0
-        if (screen->conformance_level > VTE_CONFORMANCE_LEVEL_VT100)
-                screen->flags |= VTE_FLAG_7BIT_MODE;
-#endif
-}
-
-void
-VteTerminalPrivate::S8C1T(vte::parser::Sequence const& seq)
-{
-        /*
-         * S8C1T - set-8bit-c1-terminal
-         * This causes the terminal to start sending C1 controls as 8bit C1
-         * control instead of 7bit sequences.
-         * This is ignored if the terminal is below level-2 emulation mode
-         * (VT100 and below). The terminal always sends 7bit controls in those
-         * modes.
-         */
-#if 0
-        if (screen->conformance_level > VTE_CONFORMANCE_LEVEL_VT100)
-                screen->flags &= ~VTE_FLAG_7BIT_MODE;
-#endif
-}
-
-void
-VteTerminalPrivate::SCS(vte::parser::Sequence const& seq)
-{
-        /*
-         * SCS - select-character-set
-         * Designate character sets to G-sets. The mapping from intermediates
-         * and terminal characters in the escape sequence to G-sets and
-         * character-sets is non-trivial and implemented separately. See there
-         * for more information.
-         * This call simply sets the selected G-set to the desired
-         * character-set.
-         */
-#if 0
-        vte_charset *cs = NULL;
-
-        /* TODO: support more of them? */
-        switch (seq->charset) {
-        case VTE_CHARSET_ISO_LATIN1_SUPPLEMENTAL:
-        case VTE_CHARSET_ISO_LATIN2_SUPPLEMENTAL:
-        case VTE_CHARSET_ISO_LATIN5_SUPPLEMENTAL:
-        case VTE_CHARSET_ISO_GREEK_SUPPLEMENTAL:
-        case VTE_CHARSET_ISO_HEBREW_SUPPLEMENTAL:
-        case VTE_CHARSET_ISO_LATIN_CYRILLIC:
-                break;
-
-        case VTE_CHARSET_DEC_SPECIAL_GRAPHIC:
-                cs = &vte_dec_special_graphics;
-                break;
-        case VTE_CHARSET_DEC_SUPPLEMENTAL:
-                cs = &vte_dec_supplemental_graphics;
-                break;
-        case VTE_CHARSET_DEC_TECHNICAL:
-        case VTE_CHARSET_CYRILLIC_DEC:
-        case VTE_CHARSET_DUTCH_NRCS:
-        case VTE_CHARSET_FINNISH_NRCS:
-        case VTE_CHARSET_FRENCH_NRCS:
-        case VTE_CHARSET_FRENCH_CANADIAN_NRCS:
-        case VTE_CHARSET_GERMAN_NRCS:
-        case VTE_CHARSET_GREEK_DEC:
-        case VTE_CHARSET_GREEK_NRCS:
-        case VTE_CHARSET_HEBREW_DEC:
-        case VTE_CHARSET_HEBREW_NRCS:
-        case VTE_CHARSET_ITALIAN_NRCS:
-        case VTE_CHARSET_NORWEGIAN_DANISH_NRCS:
-        case VTE_CHARSET_PORTUGUESE_NRCS:
-        case VTE_CHARSET_RUSSIAN_NRCS:
-        case VTE_CHARSET_SCS_NRCS:
-        case VTE_CHARSET_SPANISH_NRCS:
-        case VTE_CHARSET_SWEDISH_NRCS:
-        case VTE_CHARSET_SWISS_NRCS:
-        case VTE_CHARSET_TURKISH_DEC:
-        case VTE_CHARSET_TURKISH_NRCS:
-                break;
-
-        case VTE_CHARSET_USERPREF_SUPPLEMENTAL:
-                break;
-        }
-
-        if (seq->intermediates & VTE_SEQ_FLAG_POPEN)
-                screen->g0 = cs ? : &vte_unicode_lower;
-        else if (seq->intermediates & VTE_SEQ_FLAG_PCLOSE)
-                screen->g1 = cs ? : &vte_unicode_upper;
-        else if (seq->intermediates & VTE_SEQ_FLAG_MULT)
-                screen->g2 = cs ? : &vte_unicode_lower;
-        else if (seq->intermediates & VTE_SEQ_FLAG_PLUS)
-                screen->g3 = cs ? : &vte_unicode_upper;
-        else if (seq->intermediates & VTE_SEQ_FLAG_MINUS)
-                screen->g1 = cs ? : &vte_unicode_upper;
-        else if (seq->intermediates & VTE_SEQ_FLAG_DOT)
-                screen->g2 = cs ? : &vte_unicode_lower;
-        else if (seq->intermediates & VTE_SEQ_FLAG_SLASH)
-                screen->g3 = cs ? : &vte_unicode_upper;
-#endif
-
-        // FIXMEchpe: seq_designate_*(seq);
-        set_character_replacements(0, VTE_CHARACTER_REPLACEMENT_NONE);
-}
-
-void
 VteTerminalPrivate::SD(vte::parser::Sequence const& seq)
 {
         /*
@@ -6018,47 +6042,6 @@ VteTerminalPrivate::XTERM_RTM(vte::parser::Sequence const& seq)
 }
 
 void
-VteTerminalPrivate::XTERM_SACL1(vte::parser::Sequence const& seq)
-{
-        /*
-         * XTERM_SACL1 - xterm-set-ansi-conformance-level-1
-         *
-         * Probably not worth implementing.
-         */
-}
-
-void
-VteTerminalPrivate::XTERM_SACL2(vte::parser::Sequence const& seq)
-{
-        /*
-         * XTERM_SACL2 - xterm-set-ansi-conformance-level-2
-         *
-         * Probably not worth implementing.
-         */
-}
-
-void
-VteTerminalPrivate::XTERM_SACL3(vte::parser::Sequence const& seq)
-{
-        /*
-         * XTERM_SACL3 - xterm-set-ansi-conformance-level-3
-         *
-         * Probably not worth implementing.
-         */
-}
-
-void
-VteTerminalPrivate::XTERM_SDCS(vte::parser::Sequence const& seq)
-{
-        /*
-         * XTERM_SDCS - xterm-set-default-character-set
-         * Select the default character set. We treat this the same as UTF-8 as
-         * this is our default character set. As we always use UTF-8, this
-         * becomes as no-op.
-         */
-}
-
-void
 VteTerminalPrivate::XTERM_SGFX(vte::parser::Sequence const& seq)
 {
         /*
@@ -6099,16 +6082,6 @@ VteTerminalPrivate::XTERM_STM(vte::parser::Sequence const& seq)
 }
 
 void
-VteTerminalPrivate::XTERM_SUCS(vte::parser::Sequence const& seq)
-{
-        /*
-         * XTERM_SUCS - xterm-select-utf8-character-set
-         * Select UTF-8 as character set. This is our default and only
-         * character set. Hence, this is a no-op.
-         */
-}
-
-void
 VteTerminalPrivate::XTERM_WM(vte::parser::Sequence const& seq)
 {
         /*


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]