@@ -126,6 +126,10 @@ public final class TerminalEmulator {
126
126
private String mTitle ;
127
127
private final Stack <String > mTitleStack = new Stack <>();
128
128
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 ;
129
133
130
134
/** The cursor position. Between (0,0) and (mRows-1, mColumns-1). */
131
135
private int mCursorRow , mCursorCol ;
@@ -1386,6 +1390,8 @@ private void doEsc(int b) {
1386
1390
break ;
1387
1391
case '[' :
1388
1392
continueSequence (ESC_CSI );
1393
+ mIsCSIStart = true ;
1394
+ mLastCSIArg = null ;
1389
1395
break ;
1390
1396
case '=' : // DECKPAM
1391
1397
setDecsetinternalBit (DECSET_BIT_APPLICATION_KEYPAD , true );
@@ -2093,28 +2099,55 @@ private void scrollDownOneLine() {
2093
2099
}
2094
2100
}
2095
2101
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
2109
2123
}
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 );
2114
2149
}
2115
- continueSequence (mEscapeState );
2116
- } else {
2117
- unknownSequence (b );
2150
+ mLastCSIArg = b ;
2118
2151
}
2119
2152
}
2120
2153
0 commit comments