@@ -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 ;
@@ -655,6 +659,10 @@ public void processCodePoint(int b) {
655659 case ESC_CSI :
656660 doCsi (b );
657661 break ;
662+ case ESC_CSI_UNSUPPORTED_PARAMETER_BYTE :
663+ case ESC_CSI_UNSUPPORTED_INTERMEDIATE_BYTE :
664+ doCsiUnsupportedParameterOrIntermediateByte (b );
665+ break ;
658666 case ESC_CSI_EXCLAMATION :
659667 if (b == 'p' ) { // Soft terminal reset (DECSTR, http://vt100.net/docs/vt510-rm/DECSTR).
660668 reset ();
@@ -1056,6 +1064,37 @@ private int nextTabStop(int numTabs) {
10561064 return mRightMargin - 1 ;
10571065 }
10581066
1067+ /**
1068+ * Process byte while in the {@link #ESC_CSI_UNSUPPORTED_PARAMETER_BYTE} or
1069+ * {@link #ESC_CSI_UNSUPPORTED_INTERMEDIATE_BYTE} escape state.
1070+ *
1071+ * Parse unsupported parameter, intermediate and final bytes but ignore them.
1072+ *
1073+ * > For Control Sequence Introducer, ... the ESC [ is followed by
1074+ * > - any number (including none) of "parameter bytes" in the range 0x30–0x3F (ASCII 0–9:;<=>?),
1075+ * > - then by any number of "intermediate bytes" in the range 0x20–0x2F (ASCII space and !"#$%&'()*+,-./),
1076+ * > - then finally by a single "final byte" in the range 0x40–0x7E (ASCII @A–Z[\]^_`a–z{|}~).
1077+ *
1078+ * - https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands
1079+ * - https://invisible-island.net/xterm/ecma-48-parameter-format.html#section5.4
1080+ */
1081+ private void doCsiUnsupportedParameterOrIntermediateByte (int b ) {
1082+ if (mEscapeState == ESC_CSI_UNSUPPORTED_PARAMETER_BYTE && b >= 0x30 && b <= 0x3F ) {
1083+ // Supported `0–9:;>?` or unsupported `<=` parameter byte after an
1084+ // initial unsupported parameter byte in `doCsi()`, or a sequential parameter byte.
1085+ continueSequence (ESC_CSI_UNSUPPORTED_PARAMETER_BYTE );
1086+ } else if (b >= 0x20 && b <= 0x2F ) {
1087+ // Optional intermediate byte `!"#$%&'()*+,-./` after parameter or intermediate byte.
1088+ continueSequence (ESC_CSI_UNSUPPORTED_INTERMEDIATE_BYTE );
1089+ } else if (b >= 0x40 && b <= 0x7E ) {
1090+ // Final byte `@A–Z[\]^_`a–z{|}~` after parameter or intermediate byte.
1091+ // Calling `unknownSequence()` would log an error with only a final byte, so ignore it for now.
1092+ finishSequence ();
1093+ } else {
1094+ unknownSequence (b );
1095+ }
1096+ }
1097+
10591098 /** Process byte while in the {@link #ESC_CSI_QUESTIONMARK} escape state. */
10601099 private void doCsiQuestionMark (int b ) {
10611100 switch (b ) {
@@ -1653,12 +1692,16 @@ private void doCsi(int b) {
16531692 }
16541693 mCursorCol = newCol ;
16551694 break ;
1656- case '?' : // Esc [ ? -- start of a private mode set
1695+ case '?' : // Esc [ ? -- start of a private parameter byte
16571696 continueSequence (ESC_CSI_QUESTIONMARK );
16581697 break ;
1659- case '>' : // "Esc [ >" --
1698+ case '>' : // "Esc [ >" -- start of a private parameter byte
16601699 continueSequence (ESC_CSI_BIGGERTHAN );
16611700 break ;
1701+ case '<' : // "Esc [ <" -- start of a private parameter byte
1702+ case '=' : // "Esc [ =" -- start of a private parameter byte
1703+ continueSequence (ESC_CSI_UNSUPPORTED_PARAMETER_BYTE );
1704+ break ;
16621705 case '`' : // Horizontal position absolute (HPA - http://www.vt100.net/docs/vt510-rm/HPA).
16631706 setCursorColRespectingOriginMode (getArg0 (1 ) - 1 );
16641707 break ;
0 commit comments