@@ -126,6 +126,10 @@ public final class TerminalEmulator {
126126 private String mTitle ;
127127 private final Stack <String > mTitleStack = new Stack <>();
128128
129+ /** If processing first character of first parameter of {@link #ESC_CSI}. */
130+ private boolean mIsCSIStart ;
131+ /** The last character processed of a parameter of {@link #ESC_CSI}. */
132+ private Integer mLastCSIArg ;
129133
130134 /** The cursor position. Between (0,0) and (mRows-1, mColumns-1). */
131135 private int mCursorRow , mCursorCol ;
@@ -1386,6 +1390,8 @@ private void doEsc(int b) {
13861390 break ;
13871391 case '[' :
13881392 continueSequence (ESC_CSI );
1393+ mIsCSIStart = true ;
1394+ mLastCSIArg = null ;
13891395 break ;
13901396 case '=' : // DECKPAM
13911397 setDecsetinternalBit (DECSET_BIT_APPLICATION_KEYPAD , true );
@@ -2093,28 +2099,55 @@ private void scrollDownOneLine() {
20932099 }
20942100 }
20952101
2096- /** Process the next ASCII character of a parameter. */
2097- private void parseArg (int b ) {
2098- if (b >= '0' && b <= '9' ) {
2099- if (mArgIndex < mArgs .length ) {
2100- int oldValue = mArgs [mArgIndex ];
2101- int thisDigit = b - '0' ;
2102- int value ;
2103- if (oldValue >= 0 ) {
2104- value = oldValue * 10 + thisDigit ;
2105- } else {
2106- value = thisDigit ;
2107- }
2108- mArgs [mArgIndex ] = value ;
2102+ /**
2103+ * Process the next ASCII character of a parameter.
2104+ *
2105+ * Parameter characters modify the action or interpretation of the sequence. You can use up to
2106+ * 16 parameters per sequence. You must use the ; character to separate parameters.
2107+ * All parameters are unsigned, positive decimal integers, with the most significant
2108+ * digit sent first. Any parameter greater than 9999 (decimal) is set to 9999
2109+ * (decimal). If you do not specify a value, a 0 value is assumed. A 0 value
2110+ * or omitted parameter indicates a default value for the sequence. For most
2111+ * sequences, the default value is 1.
2112+ *
2113+ * https://vt100.net/docs/vt510-rm/chapter4.html#S4.3.3
2114+ * */
2115+ private void parseArg (int inputByte ) {
2116+ int [] bytes = new int []{inputByte };
2117+ // Only doing this for ESC_CSI and not for other ESC_CSI_* since they seem to be using their
2118+ // own defaults with getArg*() calls, but there may be missed cases
2119+ if (mEscapeState == ESC_CSI ) {
2120+ if ((mIsCSIStart && inputByte == ';' ) || // If sequence starts with a ; character, like \033[;m
2121+ (!mIsCSIStart && mLastCSIArg != null && mLastCSIArg == ';' && inputByte == ';' )) { // If sequence contains sequential ; characters, like \033[;;m
2122+ bytes = new int []{'0' , ';' }; // Assume 0 was passed
21092123 }
2110- continueSequence (mEscapeState );
2111- } else if (b == ';' ) {
2112- if (mArgIndex < mArgs .length ) {
2113- mArgIndex ++;
2124+ }
2125+
2126+ mIsCSIStart = false ;
2127+
2128+ for (int b : bytes ) {
2129+ if (b >= '0' && b <= '9' ) {
2130+ if (mArgIndex < mArgs .length ) {
2131+ int oldValue = mArgs [mArgIndex ];
2132+ int thisDigit = b - '0' ;
2133+ int value ;
2134+ if (oldValue >= 0 ) {
2135+ value = oldValue * 10 + thisDigit ;
2136+ } else {
2137+ value = thisDigit ;
2138+ }
2139+ mArgs [mArgIndex ] = value ;
2140+ }
2141+ continueSequence (mEscapeState );
2142+ } else if (b == ';' ) {
2143+ if (mArgIndex < mArgs .length ) {
2144+ mArgIndex ++;
2145+ }
2146+ continueSequence (mEscapeState );
2147+ } else {
2148+ unknownSequence (b );
21142149 }
2115- continueSequence (mEscapeState );
2116- } else {
2117- unknownSequence (b );
2150+ mLastCSIArg = b ;
21182151 }
21192152 }
21202153
0 commit comments