@@ -83,6 +83,10 @@ public final class TerminalEmulator {
8383 private static final int ESC_APC = 20 ;
8484 /** Escape processing: "ESC _" or Application Program Command (APC), followed by Escape. */
8585 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 ;
8690
8791 /** The number of parameter arguments including colon separated sub-parameters. */
8892 private static final int MAX_ESCAPE_PARAMETERS = 32 ;
@@ -658,6 +662,10 @@ public void processCodePoint(int b) {
658662 case ESC_CSI :
659663 doCsi (b );
660664 break ;
665+ case ESC_CSI_UNSUPPORTED_PARAMETER_BYTE :
666+ case ESC_CSI_UNSUPPORTED_INTERMEDIATE_BYTE :
667+ doCsiUnsupportedParameterOrIntermediateByte (b );
668+ break ;
661669 case ESC_CSI_EXCLAMATION :
662670 if (b == 'p' ) { // Soft terminal reset (DECSTR, http://vt100.net/docs/vt510-rm/DECSTR).
663671 reset ();
@@ -1059,6 +1067,37 @@ private int nextTabStop(int numTabs) {
10591067 return mRightMargin - 1 ;
10601068 }
10611069
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+
10621101 /** Process byte while in the {@link #ESC_CSI_QUESTIONMARK} escape state. */
10631102 private void doCsiQuestionMark (int b ) {
10641103 switch (b ) {
@@ -1656,12 +1695,16 @@ private void doCsi(int b) {
16561695 }
16571696 mCursorCol = newCol ;
16581697 break ;
1659- case '?' : // Esc [ ? -- start of a private mode set
1698+ case '?' : // Esc [ ? -- start of a private parameter byte
16601699 continueSequence (ESC_CSI_QUESTIONMARK );
16611700 break ;
1662- case '>' : // "Esc [ >" --
1701+ case '>' : // "Esc [ >" -- start of a private parameter byte
16631702 continueSequence (ESC_CSI_BIGGERTHAN );
16641703 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 ;
16651708 case '`' : // Horizontal position absolute (HPA - http://www.vt100.net/docs/vt510-rm/HPA).
16661709 setCursorColRespectingOriginMode (getArg0 (1 ) - 1 );
16671710 break ;
0 commit comments