@@ -83,6 +83,10 @@ public final class TerminalEmulator {
83
83
private static final int ESC_APC = 20 ;
84
84
/** Escape processing: "ESC _" or Application Program Command (APC), followed by Escape. */
85
85
private static final int ESC_APC_ESCAPE = 21 ;
86
+ /** Escape processing: ESC [ <parameter bytes> */
87
+ private static final int ESC_CSI_UNSUPPORTED_PARAMETER_BYTE = 22 ;
88
+ /** Escape processing: ESC [ <parameter bytes> <intermediate bytes> */
89
+ private static final int ESC_CSI_UNSUPPORTED_INTERMEDIATE_BYTE = 23 ;
86
90
87
91
/** The number of parameter arguments including colon separated sub-parameters. */
88
92
private static final int MAX_ESCAPE_PARAMETERS = 32 ;
@@ -658,6 +662,10 @@ public void processCodePoint(int b) {
658
662
case ESC_CSI :
659
663
doCsi (b );
660
664
break ;
665
+ case ESC_CSI_UNSUPPORTED_PARAMETER_BYTE :
666
+ case ESC_CSI_UNSUPPORTED_INTERMEDIATE_BYTE :
667
+ doCsiUnsupportedParameterOrIntermediateByte (b );
668
+ break ;
661
669
case ESC_CSI_EXCLAMATION :
662
670
if (b == 'p' ) { // Soft terminal reset (DECSTR, http://vt100.net/docs/vt510-rm/DECSTR).
663
671
reset ();
@@ -1059,6 +1067,37 @@ private int nextTabStop(int numTabs) {
1059
1067
return mRightMargin - 1 ;
1060
1068
}
1061
1069
1070
+ /**
1071
+ * Process byte while in the {@link #ESC_CSI_UNSUPPORTED_PARAMETER_BYTE} or
1072
+ * {@link #ESC_CSI_UNSUPPORTED_INTERMEDIATE_BYTE} escape state.
1073
+ *
1074
+ * Parse unsupported parameter, intermediate and final bytes but ignore them.
1075
+ *
1076
+ * > For Control Sequence Introducer, ... the ESC [ is followed by
1077
+ * > - any number (including none) of "parameter bytes" in the range 0x30–0x3F (ASCII 0–9:;<=>?),
1078
+ * > - then by any number of "intermediate bytes" in the range 0x20–0x2F (ASCII space and !"#$%&'()*+,-./),
1079
+ * > - then finally by a single "final byte" in the range 0x40–0x7E (ASCII @A–Z[\]^_`a–z{|}~).
1080
+ *
1081
+ * - https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands
1082
+ * - https://invisible-island.net/xterm/ecma-48-parameter-format.html#section5.4
1083
+ */
1084
+ private void doCsiUnsupportedParameterOrIntermediateByte (int b ) {
1085
+ if (mEscapeState == ESC_CSI_UNSUPPORTED_PARAMETER_BYTE && b >= 0x30 && b <= 0x3F ) {
1086
+ // Supported `0–9:;>?` or unsupported `<=` parameter byte after an
1087
+ // initial unsupported parameter byte in `doCsi()`, or a sequential parameter byte.
1088
+ continueSequence (ESC_CSI_UNSUPPORTED_PARAMETER_BYTE );
1089
+ } else if (b >= 0x20 && b <= 0x2F ) {
1090
+ // Optional intermediate byte `!"#$%&'()*+,-./` after parameter or intermediate byte.
1091
+ continueSequence (ESC_CSI_UNSUPPORTED_INTERMEDIATE_BYTE );
1092
+ } else if (b >= 0x40 && b <= 0x7E ) {
1093
+ // Final byte `@A–Z[\]^_`a–z{|}~` after parameter or intermediate byte.
1094
+ // Calling `unknownSequence()` would log an error with only a final byte, so ignore it for now.
1095
+ finishSequence ();
1096
+ } else {
1097
+ unknownSequence (b );
1098
+ }
1099
+ }
1100
+
1062
1101
/** Process byte while in the {@link #ESC_CSI_QUESTIONMARK} escape state. */
1063
1102
private void doCsiQuestionMark (int b ) {
1064
1103
switch (b ) {
@@ -1656,12 +1695,16 @@ private void doCsi(int b) {
1656
1695
}
1657
1696
mCursorCol = newCol ;
1658
1697
break ;
1659
- case '?' : // Esc [ ? -- start of a private mode set
1698
+ case '?' : // Esc [ ? -- start of a private parameter byte
1660
1699
continueSequence (ESC_CSI_QUESTIONMARK );
1661
1700
break ;
1662
- case '>' : // "Esc [ >" --
1701
+ case '>' : // "Esc [ >" -- start of a private parameter byte
1663
1702
continueSequence (ESC_CSI_BIGGERTHAN );
1664
1703
break ;
1704
+ case '<' : // "Esc [ <" -- start of a private parameter byte
1705
+ case '=' : // "Esc [ =" -- start of a private parameter byte
1706
+ continueSequence (ESC_CSI_UNSUPPORTED_PARAMETER_BYTE );
1707
+ break ;
1665
1708
case '`' : // Horizontal position absolute (HPA - http://www.vt100.net/docs/vt510-rm/HPA).
1666
1709
setCursorColRespectingOriginMode (getArg0 (1 ) - 1 );
1667
1710
break ;
0 commit comments