/**
*
*/
package com.jediterm.terminal.emulator;
import com.google.common.collect.Lists;
import com.jediterm.terminal.CharacterUtils;
import com.jediterm.terminal.TerminalDataStream;
import java.io.IOException;
import java.util.ArrayList;
public class ControlSequence {
private int myArgc;
private int[] myArgv;
private char myFinalChar;
private ArrayList<Character> myUnhandledChars;
private boolean myStartsWithQuestionMark = false; // true when CSI ?
private boolean myStartsWithMoreMark = false; // true when CSI >
private final StringBuilder mySequenceString = new StringBuilder();
ControlSequence(final TerminalDataStream channel) throws IOException {
myArgv = new int[5];
myArgc = 0;
readControlSequence(channel);
}
private void readControlSequence(final TerminalDataStream channel) throws IOException {
myArgc = 0;
// Read integer arguments
int digit = 0;
int seenDigit = 0;
int pos = -1;
while (true) {
final char b = channel.getChar();
mySequenceString.append(b);
pos++;
if (b == '?' && pos == 0) {
myStartsWithQuestionMark = true;
}
else if (b == '>' && pos == 0) {
myStartsWithMoreMark = true;
}
else if (b == ';') {
if (digit > 0) {
myArgc++;
if (myArgc == myArgv.length) {
int[] replacement = new int[myArgv.length * 2];
System.arraycopy(myArgv, 0, replacement, 0, myArgv.length);
myArgv = replacement;
}
myArgv[myArgc] = 0;
digit = 0;
}
}
else if ('0' <= b && b <= '9') {
myArgv[myArgc] = myArgv[myArgc] * 10 + b - '0';
digit++;
seenDigit = 1;
}
else if (':' <= b && b <= '?') {
addUnhandled(b);
}
else if (0x40 <= b && b <= 0x7E) {
myFinalChar = b;
break;
}
else {
addUnhandled(b);
}
}
myArgc += seenDigit;
}
private void addUnhandled(final char b) {
if (myUnhandledChars == null) {
myUnhandledChars = Lists.newArrayList();
}
myUnhandledChars.add(b);
}
public boolean pushBackReordered(final TerminalDataStream channel) throws IOException {
if (myUnhandledChars == null) return false;
final char[] bytes = new char[1024]; // can't be more than the whole buffer...
int i = 0;
for (final char b : myUnhandledChars) {
bytes[i++] = b;
}
bytes[i++] = (byte)CharacterUtils.ESC;
bytes[i++] = (byte)'[';
if (myStartsWithQuestionMark) {
bytes[i++] = (byte)'?';
}
if (myStartsWithMoreMark) {
bytes[i++] = (byte)'>';
}
for (int argi = 0; argi < myArgc; argi++) {
if (argi != 0) bytes[i++] = ';';
String s = Integer.toString(myArgv[argi]);
for (int j = 0; j < s.length(); j++) {
bytes[i++] = s.charAt(j);
}
}
bytes[i++] = myFinalChar;
channel.pushBackBuffer(bytes, i);
return true;
}
int getCount() {
return myArgc;
}
final int getArg(final int index, final int defaultValue) {
if (index >= myArgc) {
return defaultValue;
}
return myArgv[index];
}
public String appendTo(final String str) {
StringBuilder sb = new StringBuilder(str);
appendToBuffer(sb);
return sb.toString();
}
public final void appendToBuffer(final StringBuilder sb) {
sb.append("ESC[");
if (myStartsWithQuestionMark) {
sb.append("?");
}
if (myStartsWithMoreMark) {
sb.append(">");
}
String sep = "";
for (int i = 0; i < myArgc; i++) {
sb.append(sep);
sb.append(myArgv[i]);
sep = ";";
}
sb.append(myFinalChar);
if (myUnhandledChars != null) {
sb.append(" Unhandled:");
CharacterUtils.CharacterType last = CharacterUtils.CharacterType.NONE;
for (final char b : myUnhandledChars) {
last = CharacterUtils.appendChar(sb, last, (char)b);
}
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
appendToBuffer(sb);
return sb.toString();
}
public char getFinalChar() {
return myFinalChar;
}
public boolean startsWithQuestionMark() {
return myStartsWithQuestionMark;
}
public boolean startsWithMoreMark() {
return myStartsWithMoreMark;
}
public String getSequenceString() {
return mySequenceString.toString();
}
}