282 lines
9.4 KiB
Plaintext
282 lines
9.4 KiB
Plaintext
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Note:
|
|
//
|
|
|
|
using System;
|
|
//using Microsoft.Singularity;
|
|
//using Microsoft.SingSharp;
|
|
using Pipe = Microsoft.Singularity.Io.Tty;
|
|
|
|
namespace Microsoft.Singularity.Applications
|
|
{
|
|
|
|
class Terminal
|
|
{
|
|
private bool openBracketSeen;
|
|
private string numberString;
|
|
private bool haveNumber;
|
|
private bool inNumber;
|
|
private int repeat;
|
|
private string history; //debug remove
|
|
|
|
public Terminal()
|
|
{
|
|
openBracketSeen = false;
|
|
inNumber = false;
|
|
haveNumber = false;
|
|
numberString = "";
|
|
history = "";
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
openBracketSeen = false;
|
|
inNumber = false;
|
|
haveNumber = false;
|
|
history = "";
|
|
numberString = "";
|
|
}
|
|
|
|
public bool ProcessEscape(char c, out Pipe.EscapeCodes code, out int repeat)
|
|
{
|
|
code = Pipe.EscapeCodes.NOCODE;
|
|
repeat = 1;
|
|
bool notProcessed = false;
|
|
|
|
history = history + c;
|
|
//DebugStub.WriteLine("esc: processing({0}. history={1})",__arglist(c, history));
|
|
|
|
if (Char.IsWhiteSpace(c)) {
|
|
code = Pipe.EscapeCodes.NOCODE;
|
|
return true;
|
|
}
|
|
|
|
if (c == '[') {
|
|
Reset();
|
|
openBracketSeen = true;
|
|
code = Pipe.EscapeCodes.NOCODE;
|
|
return true;
|
|
}
|
|
|
|
if (Char.IsNumber(c)) {
|
|
if (!inNumber) {
|
|
inNumber = true;
|
|
}
|
|
numberString = numberString +c;
|
|
return true;
|
|
}
|
|
|
|
if (Char.IsLetter(c)) {
|
|
if (inNumber) {
|
|
inNumber = false;
|
|
haveNumber = true;
|
|
repeat = int.Parse(numberString);
|
|
}
|
|
switch (c) {
|
|
case 'A':
|
|
code = Pipe.EscapeCodes.UP;
|
|
break;
|
|
case 'B':
|
|
code = Pipe.EscapeCodes.DOWN;
|
|
break;
|
|
case 'C':
|
|
code = Pipe.EscapeCodes.RIGHT;
|
|
break;
|
|
case 'D':
|
|
code = Pipe.EscapeCodes.LEFT;
|
|
break;
|
|
case 'K':
|
|
code = Pipe.EscapeCodes.ERASE_FROM_CURSOR;
|
|
break;
|
|
case 'S':
|
|
code = Pipe.EscapeCodes.SET_CURSOR_SIZE;
|
|
break;
|
|
case 'J':
|
|
if (haveNumber) {
|
|
if (repeat == 2) {
|
|
code = Pipe.EscapeCodes.CLEAR_SCREEN;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
//DebugStub.Break();
|
|
notProcessed = true;
|
|
break;
|
|
}
|
|
if (notProcessed) {
|
|
return true;
|
|
}
|
|
else {
|
|
Reset();
|
|
return false;
|
|
}
|
|
|
|
}
|
|
else if (c == '~') {
|
|
DebugStub.WriteLine("term: ~ seen. inNumber={0}", __arglist(inNumber));
|
|
if (inNumber) {
|
|
inNumber = false;
|
|
haveNumber = true;
|
|
int num = int.Parse(numberString);
|
|
DebugStub.WriteLine("term: Number={0}", __arglist(num));
|
|
switch (num) {
|
|
case 1:
|
|
code = Pipe.EscapeCodes.HOME;
|
|
break;
|
|
case 2:
|
|
code = Pipe.EscapeCodes.INSERT;
|
|
break;
|
|
case 3:
|
|
code = Pipe.EscapeCodes.DELETE;
|
|
break;
|
|
case 4:
|
|
code = Pipe.EscapeCodes.END;
|
|
break;
|
|
case 5:
|
|
code = Pipe.EscapeCodes.PAGE_UP;
|
|
break;
|
|
case 6:
|
|
code = Pipe.EscapeCodes.PAGE_DOWN;
|
|
break;
|
|
default:
|
|
notProcessed = true;
|
|
break;
|
|
}
|
|
if (notProcessed) {
|
|
return true;
|
|
}
|
|
else {
|
|
Reset();
|
|
return false;
|
|
}
|
|
}
|
|
// hit ~ but not processing a number?
|
|
DebugStub.Break();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private Pipe.EscapeCodes GetCodeFromSequence(char[]! sequence)
|
|
{
|
|
int pos, num, qual;
|
|
string numString= "";
|
|
string qualString= "";
|
|
bool qualifierEncountered = false;
|
|
num = 0;
|
|
|
|
assert sequence[0] == '[';
|
|
for (pos = 1; pos < sequence.Length; pos++) {
|
|
if (sequence[pos] == ';') {
|
|
// handle qualifier
|
|
qualifierEncountered = true;
|
|
continue;
|
|
}
|
|
if (sequence[pos] =='~') {
|
|
//end of sequence
|
|
break;
|
|
}
|
|
if (qualifierEncountered) {
|
|
qualString = qualString + sequence[pos];
|
|
}
|
|
else {
|
|
numString = numString + sequence[pos];
|
|
}
|
|
}
|
|
try {
|
|
num = int.Parse(numString);
|
|
if (qualifierEncountered) {
|
|
#if false
|
|
qual = int.Parse(qualString);
|
|
DebugStub.WriteLine("shell: key qualifier encountered {0} in sequence ",
|
|
__arglist(qual));
|
|
#endif
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
Console.WriteLine("Exception encountered: {0}", e.ToString());
|
|
}
|
|
return (Pipe.EscapeCodes) num;
|
|
|
|
}
|
|
|
|
public void SetCursorSize(char size)
|
|
{
|
|
char[] buffer = new char[10];
|
|
int pos;
|
|
|
|
if (buffer != null) {
|
|
buffer[0] = (char) 0x1b;
|
|
buffer[1] = '[';
|
|
pos = 2;
|
|
buffer[pos++] = size;
|
|
buffer[pos++] = 'S';
|
|
Console.Write(buffer,0,pos);
|
|
}
|
|
}
|
|
|
|
public void GenerateAndSendEscapeSequence(Pipe.EscapeCodes code)
|
|
{
|
|
char[] buffer = new char[10];
|
|
int pos;
|
|
|
|
if (buffer != null) {
|
|
buffer[0] = (char) 0x1b;
|
|
buffer[1] = '[';
|
|
pos = 2;
|
|
switch (code) {
|
|
case Pipe.EscapeCodes.PAGE_UP:
|
|
buffer[pos++] = '5';
|
|
buffer[pos++] = '~';
|
|
break;
|
|
case Pipe.EscapeCodes.PAGE_DOWN:
|
|
buffer[pos++] = '6';
|
|
buffer[pos++] = '~';
|
|
break;
|
|
case Pipe.EscapeCodes.UP:
|
|
buffer[pos++] = 'A';
|
|
break;
|
|
case Pipe.EscapeCodes.DOWN:
|
|
buffer[pos++] = 'B';
|
|
break;
|
|
case Pipe.EscapeCodes.LEFT:
|
|
buffer[pos++] = 'D';
|
|
break;
|
|
case Pipe.EscapeCodes.RIGHT:
|
|
buffer[pos++] = 'C';
|
|
break;
|
|
case Pipe.EscapeCodes.ERASE_FROM_CURSOR:
|
|
buffer[pos++] = 'K';
|
|
break;
|
|
case Pipe.EscapeCodes.CLEAR_SCREEN:
|
|
buffer[pos++] = '2';
|
|
buffer[pos++] = 'J';
|
|
break;
|
|
case Pipe.EscapeCodes.HOME:
|
|
buffer[pos++] = '1';
|
|
buffer[pos++] = '~';
|
|
break;
|
|
case Pipe.EscapeCodes.END:
|
|
buffer[pos++] = '4';
|
|
buffer[pos++] = '~';
|
|
break;
|
|
case Pipe.EscapeCodes.INSERT:
|
|
buffer[pos++] = '2';
|
|
buffer[pos++] = '~';
|
|
break;
|
|
case Pipe.EscapeCodes.DELETE:
|
|
buffer[pos++] = '~';
|
|
buffer[pos++] = '3';
|
|
break;
|
|
}
|
|
|
|
Console.Write(buffer,0,pos);
|
|
}
|
|
}
|
|
}
|
|
}
|