private static TerminalSequence ConsumeEscapeSequence(XTermInputBuffer stream) { stream.PushState(); var next = stream.Read(); switch (next) { case '[': return(ConsumeCSI(stream)); case ']': return(ConsumeOSC(stream)); case 'P': return(ConsumeDeviceControlStringSequence(stream)); case '#': return(ConsumeCharacterSize(stream)); case ' ': return(ConsumeCompliance(stream)); case '%': return(ConsumeUnicode(stream)); case '(': case ')': case '*': case '+': case '-': case '.': case '/': return(ConsumeCharacterSet(next, stream)); case 'Y': var vt52mc = new Vt52MoveCursorSequence { Row = stream.ReadRaw() - ' ', Column = stream.ReadRaw() - ' ' }; stream.Commit(); System.Diagnostics.Debug.WriteLine(vt52mc.ToString()); return(vt52mc); default: var esc = new EscapeSequence { Command = next.ToString() }; stream.Commit(); //System.Diagnostics.Debug.WriteLine(esc.ToString()); return(esc); } }
public static TerminalSequence ConsumeNextSequence(XTermInputBuffer stream, bool utf8) { stream.PushState(); var next = stream.Read(utf8); TerminalSequence sequence = null; switch (next) { case '\u001b': // ESC sequence = ConsumeEscapeSequence(stream); break; case '\u008e': // SS2 sequence = ConsumeSS2Sequence(stream); break; case '\u008f': // SS3 sequence = ConsumeSS3Sequence(stream); break; case '\u0090': // DCS sequence = ConsumeDeviceControlStringSequence(stream); break; default: break; } if (sequence == null) { sequence = new CharacterSequence { Character = next }; stream.Commit(); } return(sequence); }
private static TerminalSequence ConsumeDeviceControlStringSequence(XTermInputBuffer stream) { stream.PushState(); string command = ""; bool readingCommand = false; bool atStart = true; bool isQuery = false; bool isSend = false; bool isBang = false; char? modifier = null; int currentParameter = -1; List <int> Parameters = new List <int>(); while (!stream.AtEnd) { var next = stream.Read(); if (readingCommand) { if (next == 0x07 || next == 0x9C) // BEL or ST { var dcs = new DcsSequence { Parameters = Parameters, IsQuery = isQuery, IsSend = isSend, IsBang = isBang, Command = (modifier.HasValue ? modifier.Value.ToString() : "") + command }; stream.Commit(); //System.Diagnostics.Debug.WriteLine(dcs.ToString()); return(dcs); } else if (next == 0x1B) // ESC { var stChar = stream.Read(); if (stChar == '\\') { var dcs = new DcsSequence { Parameters = Parameters, IsQuery = isQuery, IsSend = isSend, IsBang = isBang, Command = (modifier.HasValue ? modifier.Value.ToString() : "") + command }; stream.Commit(); //System.Diagnostics.Debug.WriteLine(dcs.ToString()); return(dcs); } else { throw new EscapeSequenceException("ESC \\ is needed to terminate DCS. Encounterd wrong character.", stream.Stacked); } } else { command += next; } } else { if (atStart && next == '?') { isQuery = true; } else if (atStart && next == '>') { isSend = true; } else if (atStart && next == '!') { isBang = true; } else if (next == ';') { if (currentParameter == -1) { throw new EscapeSequenceException("Invalid position for ';' in DCS", stream.Stacked); } Parameters.Add(currentParameter); currentParameter = -1; } else if (char.IsDigit(next)) { atStart = false; if (currentParameter == -1) { currentParameter = Convert.ToInt32(next - '0'); } else { currentParameter = (currentParameter * 10) + Convert.ToInt32(next - '0'); } } else if (next == '$' || next == '"' || next == ' ') { if (modifier.HasValue) { throw new EscapeSequenceException("There appears to be two modifiers in a row", stream.Stacked); } if (currentParameter != -1) { Parameters.Add(currentParameter); currentParameter = -1; } modifier = next; } else { if (currentParameter != -1) { Parameters.Add(currentParameter); currentParameter = -1; } command += next; readingCommand = true; } } } stream.PopState(); return(null); }
private static TerminalSequence ConsumeOSC(XTermInputBuffer stream) { stream.PushState(); string command = ""; bool readingCommand = false; bool atStart = true; bool isQuery = false; bool isSend = false; bool isBang = false; char? modifier = null; int currentParameter = -1; List <int> Parameters = new List <int>(); while (true) { if (stream.AtEnd) { return(null); } var next = stream.Read(); if (readingCommand) { if (next == 0x07 || next == 0x9C) // BEL or ST { var osc = new OscSequence { Parameters = Parameters, IsQuery = isQuery, IsSend = isSend, IsBang = isBang, Command = command }; stream.Commit(); //System.Diagnostics.Debug.WriteLine(osc.ToString()); return(osc); } else { command += next; } } else { if (atStart && next == '?') { isQuery = true; } else if (atStart && next == '>') { isSend = true; } else if (atStart && next == '!') { isBang = true; } else if (next == ';') { if (currentParameter == -1) { throw new EscapeSequenceException("Invalid position for ';' in OSC", stream.Stacked); } Parameters.Add(currentParameter); currentParameter = -1; } else if (char.IsDigit(next)) { atStart = false; if (currentParameter == -1) { currentParameter = Convert.ToInt32(next - '0'); } else { currentParameter = (currentParameter * 10) + Convert.ToInt32(next - '0'); } } else if (next == '$' || next == '"' || next == ' ') { if (modifier.HasValue) { throw new EscapeSequenceException("There appears to be two modifiers in a row", stream.Stacked); } if (currentParameter != -1) { Parameters.Add(currentParameter); currentParameter = -1; } modifier = next; } else { if (currentParameter != -1) { Parameters.Add(currentParameter); currentParameter = -1; } command += next; readingCommand = true; } } } }
private static TerminalSequence ConsumeCSI(XTermInputBuffer stream) { stream.PushState(); bool atStart = true; bool isQuery = false; bool isSend = false; bool isBang = false; char?modifier = null; int currentParameter = -1; List <int> Parameters = new List <int>(); List <TerminalSequence> ProcesFirst = new List <TerminalSequence>(); while (true) { var next = stream.Read(); if (atStart && next == '?') { isQuery = true; } else if (atStart && next == '>') { isSend = true; } else if (atStart && next == '!') { isBang = true; } else if (next == ';') { if (currentParameter == -1) { //currentParameter = 1; // ctrlseqs.txt seems to always default to 1 here. Might not be a great idea atStart = false; //throw new EscapeSequenceException("Invalid position for ';' in CSI", stream.Stacked); } Parameters.Add(currentParameter); currentParameter = -1; } else if (char.IsDigit(next)) { atStart = false; if (currentParameter == -1) { currentParameter = Convert.ToInt32(next - '0'); } else { currentParameter = (currentParameter * 10) + Convert.ToInt32(next - '0'); } } else if (next == '$' || next == '"' || next == ' ' || next == '\'') { if (modifier.HasValue) { throw new EscapeSequenceException("There appears to be two modifiers in a row", stream.Stacked); } if (currentParameter != -1) { Parameters.Add(currentParameter); currentParameter = -1; } modifier = next; } else if (next == '\b' || next == '\r' || next == '\u000B') { // Trash chars that have to be processed before this sequence ProcesFirst.Add( new CharacterSequence { Character = next } ); } else if (next == '\0') { // Trash null characters. Telnet is injecting them after carriage returns for // some horrible reason } else { if (currentParameter != -1) { Parameters.Add(currentParameter); currentParameter = -1; } var csi = new CsiSequence { Parameters = Parameters, IsQuery = isQuery, IsSend = isSend, IsBang = isBang, Command = (modifier.HasValue ? modifier.Value.ToString() : "") + next.ToString(), ProcessFirst = ProcesFirst.Count > 0 ? ProcesFirst : null }; stream.Commit(); //System.Diagnostics.Debug.WriteLine(csi.ToString()); return(csi); } } }