windows-nt/Source/XPSP1/NT/base/headless/tcsrv/client/parser.c

571 lines
18 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*
* Copyright (c) Microsoft Corporation
*
* Module Name :
* parser.c
*
* This is the file containing the client code for parsing vt100 escape sequences
* into console mode output.
*
*
* Sadagopan Rajaram -- Nov 3, 1999
*
*/
#include "tcclnt.h"
CHAR FinalCharacters[] = "mHJKr";
HANDLE hConsoleOutput;
BOOLEAN InEscape=FALSE;
BOOLEAN lastCharM = FALSE;
CHAR EscapeBuffer[MAX_TERMINAL_WIDTH];
int index=0;
SHORT ScrollTop = 0;
SHORT ScrollBottom = MAX_TERMINAL_HEIGHT -1;
#ifdef UNICODE
int DBCSIndex = 0;
CHAR DBCSArray[MB_CUR_MAX+1];
#endif
VOID (*AttributeFunction)(PCHAR, int);
VOID
PrintChar(
CHAR c
)
{
// A boolean variable to check if we are processing an escape sequence
if(c == '\033'){
InEscape = TRUE;
EscapeBuffer[0] = c;
index = 1;
return;
}
if(InEscape == TRUE){
if(index == MAX_TERMINAL_WIDTH){
// vague escape sequence,give up processing
InEscape = FALSE;
index=0;
return;
}
EscapeBuffer[index]=c;
index++;
if(FinalCharacter(c)){
if(c=='m'){
// maybe getting \017
lastCharM = TRUE;
}
ProcessEscapeSequence(EscapeBuffer, index);
InEscape = FALSE;
index=0;
}
return;
}
if(lastCharM && c == '\017'){
lastCharM = FALSE;
return;
}
OutputConsole(c);
return;
}
BOOLEAN
FinalCharacter(
CHAR c
)
{
if(strchr(FinalCharacters,c)){
return TRUE;
}
return FALSE;
}
VOID
ProcessEscapeSequence(
PCHAR Buffer,
int length
)
{
// BUGBUG - Function too big, can optimize code size by having
// an action variable which is initialized when the strings are
// compared, so that cut and paste code can be eliminated.
CONSOLE_SCREEN_BUFFER_INFO csbInfo;
ULONG charsToWrite;
ULONG charsWritten;
PCHAR pTemp;
int RetVal;
if (length == 3) {
// One of the home cursor or clear to end of display
if (strncmp(Buffer,"\033[H",length)==0) {
// Home the cursor
csbInfo.dwCursorPosition.X = 0;
csbInfo.dwCursorPosition.Y = 0;
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
return;
}
if(strncmp(Buffer,"\033[J", length) == 0){
// clear to end of display assuming 80 X 24 size
RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
&csbInfo
);
if (RetVal == FALSE) {
return;
}
SetConsoleMode(hConsoleOutput,
ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT
);
charsToWrite = (MAX_TERMINAL_HEIGHT -
csbInfo.dwCursorPosition.Y)*MAX_TERMINAL_WIDTH -
csbInfo.dwCursorPosition.X;
RetVal = FillConsoleOutputAttribute(hConsoleOutput,
csbInfo.wAttributes,
charsToWrite,
csbInfo.dwCursorPosition,
&charsWritten
);
RetVal = FillConsoleOutputCharacter(hConsoleOutput,
0,
charsToWrite,
csbInfo.dwCursorPosition,
&charsWritten
);
SetConsoleMode(hConsoleOutput,
ENABLE_PROCESSED_OUTPUT
);
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
return;
}
if(strncmp(Buffer,"\033[K", length) == 0){
// clear to end of line assuming 80 X 24 size
RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
&csbInfo
);
if (RetVal == FALSE) {
return;
}
charsToWrite = (MAX_TERMINAL_WIDTH - csbInfo.dwCursorPosition.X);
RetVal = FillConsoleOutputAttribute(hConsoleOutput,
csbInfo.wAttributes,
charsToWrite,
csbInfo.dwCursorPosition,
&charsWritten
);
RetVal = FillConsoleOutputCharacter(hConsoleOutput,
0,
charsToWrite,
csbInfo.dwCursorPosition,
&charsWritten
);
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
return;
}
if (strncmp(Buffer,"\033[r", length) == 0) {
ScrollTop = 0;
ScrollBottom = MAX_TERMINAL_HEIGHT -1;
}
}
if (length == 4) {
// One of the home cursor or clear to end of display
if (strncmp(Buffer,"\033[0H",length)==0) {
// Home the cursor
csbInfo.dwCursorPosition.X = 0;
csbInfo.dwCursorPosition.Y = 0;
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
return;
}
if(strncmp(Buffer,"\033[2J",length) == 0){
// Home the cursor
csbInfo.dwCursorPosition.X = 0;
csbInfo.dwCursorPosition.Y = 0;
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
sprintf(Buffer, "\033[0J");
}
if(strncmp(Buffer,"\033[0J", length) == 0){
// clear to end of display assuming 80 X 24 size
RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
&csbInfo
);
if (RetVal == FALSE) {
return;
}
SetConsoleMode(hConsoleOutput,
ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT
);
charsToWrite = (MAX_TERMINAL_HEIGHT -
csbInfo.dwCursorPosition.Y)*MAX_TERMINAL_WIDTH -
csbInfo.dwCursorPosition.X;
RetVal = FillConsoleOutputAttribute(hConsoleOutput,
csbInfo.wAttributes,
charsToWrite,
csbInfo.dwCursorPosition,
&charsWritten
);
RetVal = FillConsoleOutputCharacter(hConsoleOutput,
0,
charsToWrite,
csbInfo.dwCursorPosition,
&charsWritten
);
SetConsoleMode(hConsoleOutput,
ENABLE_PROCESSED_OUTPUT
);
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
return;
}
if((strncmp(Buffer,"\033[0K", length) == 0) ||
(strncmp(Buffer,"\033[2K",length) == 0)){
// clear to end of line assuming 80 X 24 size
RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
&csbInfo
);
if (RetVal == FALSE) {
return;
}
charsToWrite = (MAX_TERMINAL_WIDTH - csbInfo.dwCursorPosition.X);
RetVal = FillConsoleOutputAttribute(hConsoleOutput,
csbInfo.wAttributes,
charsToWrite,
csbInfo.dwCursorPosition,
&charsWritten
);
RetVal = FillConsoleOutputCharacter(hConsoleOutput,
0,
charsToWrite,
csbInfo.dwCursorPosition,
&charsWritten
);
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
return;
}
if((strncmp(Buffer,"\033[0m", length) == 0)||
(strncmp(Buffer,"\033[m\017", length) == 0)){
// clear all attributes and set Text attributes to black on white
SetConsoleTextAttribute(hConsoleOutput,
FOREGROUND_RED |FOREGROUND_BLUE |FOREGROUND_GREEN
);
return;
}
}
if(Buffer[length-1] == 'm'){
//set the text attributes
// clear all attributes and set Text attributes to white on black
SetConsoleTextAttribute(hConsoleOutput,
FOREGROUND_RED |FOREGROUND_BLUE |FOREGROUND_GREEN
);
AttributeFunction(Buffer, length);
return;
}
if(Buffer[length -1] == 'H'){
// Set cursor position
if (sscanf(Buffer,"\033[%d;%d", &charsToWrite, &charsWritten) == 2) {
csbInfo.dwCursorPosition.Y = (SHORT)(charsToWrite -1);
csbInfo.dwCursorPosition.X = (SHORT)(charsWritten -1);
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
}
return;
}
if(Buffer[length -1] == 'r'){
// Set scroll region
sscanf(Buffer,"\033[%d;%d", &charsToWrite,&charsWritten);
if ((charsToWrite < 1)
|| (charsToWrite > MAX_TERMINAL_HEIGHT)
|| (charsWritten < charsToWrite)) {
return;
}
ScrollTop = (SHORT)(charsToWrite -1);
ScrollBottom = (SHORT)(charsWritten -1);
}
return;
}
VOID
ProcessTextAttributes(
PCHAR Buffer,
int length
)
{
PCHAR CurrLoc = Buffer;
ULONG Attribute;
WORD TextAttribute = 0;
BOOLEAN Reverse = FALSE;
PCHAR pTemp;
while(*CurrLoc != 'm'){
if((*CurrLoc < '0') || (*CurrLoc >'9' )){
CurrLoc ++;
}else{
if (sscanf(CurrLoc,"%d", &Attribute) != 1) {
return;
}
switch(Attribute){
case 1:
TextAttribute = TextAttribute | FOREGROUND_INTENSITY;
break;
case 37:
TextAttribute = TextAttribute|FOREGROUND_RED |FOREGROUND_BLUE |FOREGROUND_GREEN;
break;
case 47:
TextAttribute = TextAttribute|BACKGROUND_RED |BACKGROUND_BLUE |BACKGROUND_GREEN;
break;
case 34:
TextAttribute = TextAttribute|FOREGROUND_BLUE;
break;
case 44:
TextAttribute = TextAttribute|BACKGROUND_BLUE;
break;
case 31:
TextAttribute = TextAttribute|FOREGROUND_RED;
break;
case 41:
TextAttribute = TextAttribute|BACKGROUND_RED;
break;
case 33:
TextAttribute = TextAttribute|FOREGROUND_GREEN|FOREGROUND_BLUE;
break;
case 43:
TextAttribute = TextAttribute|BACKGROUND_GREEN|BACKGROUND_BLUE;
break;
case 7:
// Reverse the background and foreground colors
Reverse=TRUE;
default:
break;
}
pTemp = strchr(CurrLoc, ';');
if(pTemp == NULL){
pTemp = strchr(CurrLoc, 'm');
}
if(pTemp == NULL) {
break;
}
CurrLoc = pTemp;
}
}
if (Reverse) {
if ((!TextAttribute) ||
(TextAttribute == FOREGROUND_INTENSITY)) {
// Reverse vt100 escape sequence.
TextAttribute = TextAttribute |
BACKGROUND_RED |BACKGROUND_BLUE |BACKGROUND_GREEN;
}
}
if(TextAttribute){
SetConsoleTextAttribute(hConsoleOutput,
TextAttribute
);
}
return;
}
VOID
vt100Attributes(
PCHAR Buffer,
int length
)
{
PCHAR CurrLoc = Buffer;
ULONG Attribute;
WORD TextAttribute = 0;
PCHAR pTemp;
while(*CurrLoc != 'm'){
if((*CurrLoc < '0') || (*CurrLoc >'9' )){
CurrLoc ++;
}else{
if (sscanf(CurrLoc,"%d", &Attribute) != 1) {
return;
}
switch(Attribute){
case 1:
TextAttribute = TextAttribute | FOREGROUND_INTENSITY;
break;
case 5:
TextAttribute = TextAttribute | BACKGROUND_INTENSITY;
break;
case 7:
TextAttribute = TextAttribute |
BACKGROUND_RED |BACKGROUND_BLUE |BACKGROUND_GREEN;
break;
default:
break;
}
pTemp = strchr(CurrLoc, ';');
if(pTemp == NULL){
pTemp = strchr(CurrLoc, 'm');
}
if(pTemp == NULL) {
break;
}
CurrLoc = pTemp;
}
}
if(TextAttribute){
SetConsoleTextAttribute(hConsoleOutput,
TextAttribute
);
}
return;
}
VOID
OutputConsole(
CHAR byte
)
{
CONSOLE_SCREEN_BUFFER_INFO csbInfo;
COORD dwBufferCoord;
SMALL_RECT sRect;
BOOL RetVal;
TCHAR Char;
SHORT ypos;
CHAR_INFO Fill;
DWORD charsWritten;
if (byte == '\n'){
RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
&csbInfo
);
if (RetVal == FALSE) {
return;
}
ypos = csbInfo.dwCursorPosition.Y;
if ((ypos == ScrollBottom ) || (ypos == MAX_TERMINAL_HEIGHT -1 )) {
// Do the scrolling
dwBufferCoord.X = 0;
dwBufferCoord.Y = ScrollBottom;
Fill.Char.UnicodeChar = (WCHAR) 0;
Fill.Attributes = FOREGROUND_RED |FOREGROUND_BLUE |FOREGROUND_GREEN;
if ((ypos == ScrollBottom)
&& (ScrollTop != ScrollBottom)) {
sRect.Left = 0;
sRect.Top = ScrollTop + 1;
sRect.Right = MAX_TERMINAL_WIDTH-1;
sRect.Bottom = ScrollBottom;
dwBufferCoord.Y = ScrollTop;
dwBufferCoord.X = 0;
RetVal = ScrollConsoleScreenBuffer(hConsoleOutput,
&sRect,
NULL,
dwBufferCoord,
&Fill
);
dwBufferCoord.Y = ScrollBottom;
} else {
if (ypos == MAX_TERMINAL_HEIGHT -1){
sRect.Left = 0;
sRect.Top = 1;
sRect.Right = MAX_TERMINAL_WIDTH-1;
sRect.Bottom = MAX_TERMINAL_HEIGHT - 1;
dwBufferCoord.Y = 0;
dwBufferCoord.X = 0;
RetVal = ScrollConsoleScreenBuffer(hConsoleOutput,
&sRect,
NULL,
dwBufferCoord,
&Fill
);
dwBufferCoord.Y = MAX_TERMINAL_HEIGHT -1;
}
}
RetVal = FillConsoleOutputCharacter(hConsoleOutput,
(TCHAR) 0,
MAX_TERMINAL_WIDTH,
dwBufferCoord,
&charsWritten
);
return;
} else {
csbInfo.dwCursorPosition.Y = ypos + 1;
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
}
return;
}
if (byte == '\r'){
RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
&csbInfo
);
if (RetVal == FALSE) {
return;
}
csbInfo.dwCursorPosition.X = 0;
SetConsoleCursorPosition(hConsoleOutput,
csbInfo.dwCursorPosition
);
return;
}
Char = (TCHAR) byte;
#ifdef UNICODE
DBCSArray[DBCSIndex] = byte;
if(DBCSIndex ==0){
if(isleadbyte(byte)){
DBCSIndex ++;
return;
}
}
else{
mbtowc(&Char, DBCSArray, 2);
DBCSIndex = 0;
}
#endif
_tprintf(_T("%c"),Char);
return;
}