mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-08-16 23:48:30 +02:00
Typically LF is sent when Return key is hit. But for sshd servers that sent us via ANSI escape sequence that CRLF is to be sent, ssh.exe client will do so which is used commonly used by sshd servers in Windows - like our own win32 port sshd.
939 lines
19 KiB
C
939 lines
19 KiB
C
/*
|
|
* Author: Microsoft Corp.
|
|
*
|
|
* Copyright (c) 2015 Microsoft Corp.
|
|
* All rights reserved
|
|
*
|
|
* Microsoft openssh win32 port
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
/* ansiprsr.c
|
|
*
|
|
* ANSI Parser to run on Win32 based operating systems.
|
|
*
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#include <winsock2.h>
|
|
#include <windows.h>
|
|
|
|
#include "ansiprsr.h"
|
|
#include "tncon.h"
|
|
#include "tnnet.h"
|
|
|
|
#define TS_IS 0
|
|
#define TS_SEND 1
|
|
|
|
// items used from other modules
|
|
int NetWriteString(char* pszString, size_t cbString);
|
|
TelParams Parameters;
|
|
|
|
extern int ScreenX;
|
|
extern int ScreenY;
|
|
extern int ScrollTop;
|
|
extern int ScrollBottom;
|
|
// end of imports from outside module
|
|
|
|
bool gbVTAppMode = false;
|
|
|
|
// private message for port printing to
|
|
unsigned char VT_ST[] = { 0x1b, '/', '\0' };
|
|
|
|
static int AutoWrap = 1;
|
|
|
|
int marginTop, marginBottom;
|
|
BOOL bAtEOLN = FALSE;
|
|
|
|
static int term_mode;
|
|
|
|
// ParseANSI globals - these need to be here, because sometimes blocks are sent
|
|
// in mid ANSI sequence
|
|
int iParam[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
int iCurrentParam = 0;
|
|
int bDelimiter = 0;
|
|
int bMode = 0;
|
|
int fcompletion = 1;
|
|
int bExtMode = 0;
|
|
int bCS0 = 0;
|
|
int bCS1 = 0;
|
|
int bBkMode = 0;
|
|
int bCharMode = 0;
|
|
|
|
|
|
BOOL fShiftOut = FALSE;
|
|
BOOL InPrintMode = FALSE;
|
|
BOOL fPcMode = FALSE;
|
|
|
|
char printErr[] = "Unable to Print: Printer not assigned. Press any key to continue...";
|
|
|
|
#define MODE_CURSORAPP 0x0001
|
|
#define MODE_ANSIVT52 0x0002
|
|
#define MODE_COL132 0x0004
|
|
#define MODE_SMOOTHSCROLL 0x0008
|
|
#define MODE_REVERSESCREEN 0x0010
|
|
#define MODE_ORIGINREL 0x0020
|
|
#define MODE_WRAPAROUND 0x0040
|
|
#define MODE_AUTOREPEAT 0x0080
|
|
#define MODE_APPMODE 0x0100
|
|
#define MODE_LNM 0x0200
|
|
#define MODE_IRM_INSERT 0x0400
|
|
|
|
int VTMode = 0;
|
|
|
|
#define MODE_CURSORAPP 0x0001
|
|
#define MODE_ANSIVT52 0x0002
|
|
#define MODE_COL132 0x0004
|
|
#define MODE_SMOOTHSCROLL 0x0008
|
|
#define MODE_REVERSESCREEN 0x0010
|
|
#define MODE_ORIGINREL 0x0020
|
|
#define MODE_WRAPAROUND 0x0040
|
|
#define MODE_AUTOREPEAT 0x0080
|
|
#define MODE_APPMODE 0x0100
|
|
#define MODE_LNM 0x0200
|
|
|
|
char *GetTerminalId()
|
|
{
|
|
return "\033[?1;2c";
|
|
}
|
|
|
|
char * GetStatusReport()
|
|
{
|
|
return "\033[2;5R";
|
|
}
|
|
|
|
void BufConvertToG2(char * pszBuffer, int length)
|
|
{
|
|
int i;
|
|
|
|
for (i=0;i<length;i++)
|
|
pszBuffer[i]='|';
|
|
//*(pszBuffer+i) += 20;
|
|
}
|
|
|
|
|
|
void GoToNextLine()
|
|
{
|
|
if (ConGetCursorY() >= (ConWindowSizeY()-1))
|
|
{
|
|
ConScrollDown(ScrollTop,ScrollBottom);
|
|
ConMoveCursorPosition(-ConGetCursorX(),0);
|
|
}
|
|
else
|
|
ConMoveCursorPosition(-ConGetCursorX(),1);
|
|
bAtEOLN = FALSE;
|
|
}
|
|
|
|
unsigned char* ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd)
|
|
{
|
|
int CurrentX;
|
|
int CurrentY;
|
|
int rc = 0, bufLen, cmpLen, i;
|
|
|
|
|
|
if (!fcompletion)
|
|
{
|
|
if (pszBuffer < pszBufferEnd -1)
|
|
{
|
|
unsigned char * pszCurrent = pszBuffer+1;
|
|
unsigned char * pszNewCurrent = pszCurrent;
|
|
|
|
if (term_mode == TERM_ANSI)
|
|
{
|
|
pszNewCurrent = ParseANSI(pszCurrent, pszBufferEnd);
|
|
}
|
|
else if (term_mode == TERM_VT52)
|
|
{
|
|
pszNewCurrent = ParseVT52(pszCurrent, pszBufferEnd);
|
|
}
|
|
if ( pszCurrent == pszNewCurrent ) // didn't move inside Parsefunction
|
|
{
|
|
pszNewCurrent += ConWriteString( (char *)pszCurrent, 1);
|
|
return pszBuffer + 1;
|
|
}
|
|
if (pszNewCurrent > pszCurrent )
|
|
pszBuffer = pszNewCurrent;
|
|
}
|
|
}
|
|
switch ((unsigned char) (*pszBuffer))
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 11:
|
|
pszBuffer++;
|
|
break;
|
|
|
|
case 7:
|
|
Beep( 1000, 400);
|
|
pszBuffer++;
|
|
break;
|
|
|
|
case 8:
|
|
pszBuffer++;
|
|
if (!bAtEOLN)
|
|
{
|
|
CurrentX = ConGetCursorX();
|
|
if (CurrentX == 0)
|
|
{
|
|
ConMoveCursorPosition( ScreenX-1,-1);
|
|
ConWriteString(" ",1);
|
|
// ConMoveCursorPosition(-1,0);
|
|
}
|
|
else
|
|
{
|
|
ConClearNFromCursorLeft(1);
|
|
ConMoveCursorPosition( -1, 0 );
|
|
}
|
|
}
|
|
bAtEOLN = FALSE;
|
|
|
|
//ConWriteString( " ", 1 );
|
|
//ConMoveCursorPosition( -1, 0 );
|
|
break;
|
|
|
|
case 9:
|
|
{
|
|
if (bAtEOLN) GoToNextLine();
|
|
int i, MoveRight = 8 - (ConGetCursorX() % 8);
|
|
|
|
for ( i = 0; i < MoveRight; i++ )
|
|
ConWriteString( " ", 1 );
|
|
pszBuffer++;
|
|
AutoWrap = 1;
|
|
bAtEOLN = FALSE;
|
|
}
|
|
break;
|
|
|
|
case 10:
|
|
|
|
|
|
pszBuffer++;
|
|
CurrentY = ConGetCursorY();
|
|
|
|
|
|
if (CurrentY >= marginBottom )
|
|
{
|
|
if (VTMode & MODE_APPMODE)
|
|
ConScrollDown(marginTop,marginBottom);
|
|
else
|
|
printf("\n");
|
|
ConMoveCursorPosition(-ConGetCursorX(),0);
|
|
}
|
|
else
|
|
{
|
|
ConMoveCursorPosition(0,1);
|
|
}
|
|
if ( Parameters.nReceiveCRLF == ENUM_LF )
|
|
ConMoveCursorPosition(-ConGetCursorX(),0);
|
|
AutoWrap = 1;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
|
|
case 12:
|
|
pszBuffer++;
|
|
ConSetCursorPosition(0, 0);
|
|
ConClearScreen();
|
|
AutoWrap = 1;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
|
|
case 13:
|
|
pszBuffer++;
|
|
ConMoveCursorPosition(-ConGetCursorX(),0);
|
|
AutoWrap = 1;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
|
|
case 14:
|
|
pszBuffer++;
|
|
fShiftOut = TRUE;
|
|
break;
|
|
|
|
case 15:
|
|
fShiftOut = FALSE;
|
|
pszBuffer++;
|
|
break;
|
|
|
|
case 27:
|
|
if (pszBuffer < pszBufferEnd -1)
|
|
{
|
|
unsigned char * pszCurrent = pszBuffer+1;
|
|
unsigned char * pszNewCurrent = pszCurrent;
|
|
|
|
if ( *pszCurrent == 27 )
|
|
{
|
|
pszNewCurrent += ConWriteString( (char *)pszCurrent, 1);
|
|
return pszBuffer + 1;
|
|
}
|
|
else
|
|
{
|
|
if (term_mode == TERM_ANSI)
|
|
{
|
|
pszNewCurrent = ParseANSI(pszCurrent, pszBufferEnd);
|
|
}
|
|
else if (term_mode == TERM_VT52)
|
|
{
|
|
pszNewCurrent = ParseVT52(pszCurrent, pszBufferEnd);
|
|
}
|
|
}
|
|
if (pszNewCurrent > pszCurrent )
|
|
pszBuffer = pszNewCurrent;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if (bAtEOLN) GoToNextLine();
|
|
|
|
unsigned char* pszCurrent = pszBuffer;
|
|
CurrentX = ConGetCursorX();
|
|
|
|
while ((pszCurrent < pszBufferEnd) && (*pszCurrent != (unsigned char)27)
|
|
&& (*pszCurrent > (unsigned char)15) && (*pszCurrent != (unsigned char)255)
|
|
&& (CurrentX++ < ScreenX ))
|
|
// (*pszCurrent != (char)15) && (*pszCurrent != (char)14) &&
|
|
// (*pszCurrent != (char)12) && (*pszCurrent != (char)13) && (*pszCurrent != (char)8) &&
|
|
// (*pszCurrent != (char)9))
|
|
pszCurrent++;
|
|
|
|
if (fShiftOut)
|
|
memset( pszBuffer, '|', pszCurrent-pszBuffer );
|
|
|
|
pszBuffer += ConWriteString((char *)pszBuffer, (int)(pszCurrent - pszBuffer));
|
|
|
|
if ((CurrentX >= ScreenX) && AutoWrap && !(VTMode & MODE_CURSORAPP) )
|
|
{
|
|
bAtEOLN = TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pszBuffer;
|
|
}
|
|
|
|
|
|
unsigned char * GetNextChar(unsigned char * pszBuffer, unsigned char *pszBufferEnd)
|
|
{
|
|
if (++pszBuffer > pszBufferEnd)
|
|
return NULL;
|
|
else
|
|
return pszBuffer;
|
|
}
|
|
|
|
void ConSetExtendedMode(int iFunction, BOOL bEnable)
|
|
{
|
|
switch(iFunction)
|
|
{
|
|
case 1:
|
|
if (bEnable){
|
|
VTMode |= MODE_CURSORAPP;
|
|
gbVTAppMode = true;
|
|
}else{
|
|
VTMode &= ~MODE_CURSORAPP;
|
|
gbVTAppMode = false;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (!bEnable)
|
|
VTMode |= MODE_ANSIVT52;
|
|
break;
|
|
case 3:
|
|
if (bEnable)
|
|
VTMode |= MODE_COL132;
|
|
else
|
|
VTMode &= ~MODE_COL132;
|
|
break;
|
|
case 4:
|
|
if (bEnable)
|
|
VTMode |= MODE_SMOOTHSCROLL;
|
|
else
|
|
VTMode &= ~MODE_SMOOTHSCROLL;
|
|
break;
|
|
case 5:
|
|
if (bEnable)
|
|
VTMode |= MODE_REVERSESCREEN;
|
|
else
|
|
VTMode &= ~MODE_REVERSESCREEN;
|
|
break;
|
|
case 6:
|
|
if (bEnable)
|
|
VTMode |= MODE_ORIGINREL;
|
|
else
|
|
VTMode &= ~MODE_ORIGINREL;
|
|
break;
|
|
case 7:
|
|
if (bEnable)
|
|
VTMode |= MODE_WRAPAROUND;
|
|
else
|
|
VTMode &= ~MODE_WRAPAROUND;
|
|
break;
|
|
case 8:
|
|
if (bEnable)
|
|
VTMode |= MODE_AUTOREPEAT;
|
|
else
|
|
VTMode &= ~MODE_AUTOREPEAT;
|
|
break;
|
|
case 20: // LNM Mode CSI 20h
|
|
if (bEnable){
|
|
VTMode |= MODE_LNM;
|
|
Parameters.nReceiveCRLF = ENUM_CRLF;
|
|
}else{
|
|
VTMode &= ~MODE_LNM;
|
|
Parameters.nReceiveCRLF = ENUM_LF;
|
|
}
|
|
break;
|
|
case 25:
|
|
ConDisplayCursor(bEnable);
|
|
break;
|
|
|
|
}
|
|
|
|
if ((iFunction == 2) && (bEnable))
|
|
{
|
|
term_mode = TERM_VT52;
|
|
}
|
|
}
|
|
|
|
#define MODE_EXT 0x00000001
|
|
#define MODE_CS0 0x00000002
|
|
#define MODE_CS1 0x00000004
|
|
#define MODE_CS2 0x00000008
|
|
#define MODE_CS3 0x00000010
|
|
#define MODE_BRK 0x00000020
|
|
#define MODE_CHAR 0x00000040
|
|
#define MODE_K 0x00000080
|
|
|
|
#define DIGI_MASK (MODE_CS0 | MODE_CS1 | MODE_CS2 | MODE_CS3 | MODE_CHAR)
|
|
|
|
unsigned char * ParseANSI(unsigned char * pszBuffer, unsigned char * pszBufferEnd)
|
|
{
|
|
unsigned char * pszCurrent = pszBuffer;
|
|
const int nParam = 10; // Maximum number of parameters
|
|
int rc = 0;
|
|
static int SavedX = 0;
|
|
static int SavedY = 0;
|
|
SCREEN_HANDLE hScreen = NULL;
|
|
char anyKey[2] = " ";
|
|
WORD BytesRead;
|
|
char pszServerPort[10];
|
|
int indx;
|
|
char jobName[40];
|
|
|
|
fcompletion = 0;
|
|
do
|
|
{
|
|
switch ((unsigned char) *pszCurrent)
|
|
{
|
|
case ';': // delimiter
|
|
bDelimiter = TRUE;
|
|
break;
|
|
// Modifiers
|
|
case '?': // Extended Mode
|
|
bMode |= MODE_EXT;
|
|
break;
|
|
case '(':
|
|
bMode |= MODE_CS0;
|
|
break;
|
|
case ')':
|
|
bMode |= MODE_CS1;
|
|
break;
|
|
case '*':
|
|
bMode |= MODE_CS2;
|
|
break;
|
|
case '+':
|
|
bMode |= MODE_CS3;
|
|
break;
|
|
case '[':
|
|
bMode |= MODE_BRK;
|
|
break;
|
|
case '#':
|
|
bMode |= MODE_CHAR;
|
|
break;
|
|
|
|
// Termination Options
|
|
case 0:
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case '}':
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case '<': // character set
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case '\\':
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case '~':
|
|
fcompletion = 1;
|
|
break;
|
|
case '^': // private message pszCurrent++;
|
|
while (_strnicmp((const char *)pszCurrent, (const char *)VT_ST, strlen((const char *)VT_ST) ) )// while not stop
|
|
{
|
|
if (_strnicmp((const char *)pszCurrent, (const char *)VT_ST, strlen((const char *)VT_ST) ) )
|
|
pszCurrent++;
|
|
}
|
|
pszCurrent += strlen((const char *)VT_ST) - 1;
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'A': // British Character Set or Cursor Up
|
|
if (bMode & MODE_CHAR)
|
|
{
|
|
// Britsh Character Set
|
|
}
|
|
else if (bMode & MODE_BRK)
|
|
{
|
|
// Cursor UP
|
|
if (iCurrentParam < 1)
|
|
iParam[0] = 1;
|
|
ConMoveCursorPosition(0, -iParam[0]);
|
|
// AutoWrap = 0;
|
|
}
|
|
fcompletion = 1;
|
|
break;
|
|
case 'B': // US ASCII or Cursor down
|
|
if (bMode & MODE_CHAR)
|
|
{
|
|
// US ASCII Character Set
|
|
}
|
|
else if (bMode & MODE_BRK)
|
|
{
|
|
// Cursor DOWN
|
|
if (iCurrentParam < 1)
|
|
iParam[0] = 1;
|
|
ConMoveCursorPosition(0, iParam[0]);
|
|
// AutoWrap = 0;
|
|
}
|
|
fcompletion = 1;
|
|
break;
|
|
case 'C': // Finish Character Set or Cursor right
|
|
if (bMode & MODE_CHAR)
|
|
{
|
|
// Britsh Character Set
|
|
}
|
|
else if (bMode & MODE_BRK)
|
|
{
|
|
// Cursor right
|
|
if (iCurrentParam < 1)
|
|
iParam[0] = 1;
|
|
ConMoveCursorPosition(iParam[0], 0);
|
|
// AutoWrap = 0;
|
|
}
|
|
fcompletion = 1;
|
|
break;
|
|
case 'D': // Cursor left
|
|
if (bMode & MODE_BRK)
|
|
{
|
|
// Cursor left
|
|
if (iCurrentParam < 1)
|
|
iParam[0] = 1;
|
|
ConMoveCursorPosition(-iParam[0], 0);
|
|
// AutoWrap = 0;
|
|
}
|
|
else if (bMode == 0)
|
|
{
|
|
// Index
|
|
ConScrollDown(ScrollTop,ScrollBottom);
|
|
}
|
|
fcompletion = 1;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
|
|
|
|
case '=': // application mode
|
|
VTMode |= MODE_APPMODE;
|
|
fcompletion = 1;
|
|
break;
|
|
case '>': // numeric mode
|
|
VTMode &= ~MODE_APPMODE;
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case '%': // character set definitions
|
|
|
|
fcompletion = 1;
|
|
break;
|
|
case 'h':
|
|
case 'l': // ^[?25h
|
|
if (bMode & MODE_EXT)
|
|
{
|
|
if (iParam[0] == 4){
|
|
VTMode |= MODE_IRM_INSERT;
|
|
}
|
|
// iParam[0] = atoi( (pszCurrent - iCurrentParam) );
|
|
int i;
|
|
for ( i = 0; i < iCurrentParam; i++ )
|
|
ConSetExtendedMode(iParam[i], *pszCurrent=='h'?1:0);
|
|
}
|
|
else if (bMode & MODE_BRK)
|
|
{
|
|
// Possible set Line feed (option 20)
|
|
// Possible set Line feed (option 20)
|
|
if (iParam[0] == 20)
|
|
ConSetExtendedMode(iParam[0], *pszCurrent=='h'?1:0);
|
|
if (iParam[0] == 4){
|
|
VTMode &= ~MODE_IRM_INSERT;
|
|
}
|
|
}
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'L':
|
|
if (iParam[0])
|
|
{
|
|
int i;
|
|
for (i=0; i<iParam[0]; i++)
|
|
ConScrollUp(ConGetCursorY()-1,ScrollTop + ConWindowSizeY()-2);
|
|
}
|
|
else
|
|
{
|
|
if (ConGetCursorY() <= ScrollTop + ConWindowSizeY()-2)
|
|
{
|
|
ConScrollUp(ConGetCursorY()-1,ScrollTop + ConWindowSizeY()-2);
|
|
}
|
|
}
|
|
fcompletion = 1;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
case 'N':
|
|
case 'O':
|
|
fcompletion =1;
|
|
break;
|
|
case 'm':
|
|
if (iCurrentParam < 1)
|
|
iParam[0] = 0;
|
|
ConSetAttribute(iParam, iCurrentParam);
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'r':
|
|
marginTop = (iParam[0] > 0) ? iParam[0] - 1 : 0;
|
|
marginBottom = (iParam[1] > 0) ? iParam[1] - 1 : 0;
|
|
|
|
fcompletion = 1;
|
|
break;
|
|
case 'H':
|
|
case 'f':
|
|
if (bMode & MODE_BRK)
|
|
{
|
|
if ((iParam[0]-1) > ConWindowSizeY())
|
|
ConSetScreenRect(ConWindowSizeX(), iParam[0]-1);
|
|
ConSetCursorPosition((iParam[1] > 0) ? iParam[1] - 1 : 0, (iParam[0] > 0) ? iParam[0] - 1 : 0);
|
|
//AutoWrap = 0;
|
|
}
|
|
else if (bMode == 0)
|
|
{
|
|
//Set tab
|
|
}
|
|
fcompletion = 1;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
|
|
case 'M':
|
|
if (iParam[0])
|
|
{
|
|
int i ;
|
|
for (i=0; i<iParam[0]; i++)
|
|
ConScrollUp(ConGetCursorY(),ScrollTop + marginBottom - ConGetCursorY());
|
|
}
|
|
else
|
|
{
|
|
if (ConGetCursorY() <= ScrollTop + ConWindowSizeY()-2)
|
|
{
|
|
ConScrollUp(ConGetCursorY(),ScrollTop + marginBottom - ConGetCursorY());
|
|
}
|
|
}
|
|
fcompletion = 1;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
case 'E':
|
|
case 'g':
|
|
fcompletion = 1;
|
|
break;
|
|
case 'i': // ANSI or VTXXX Print
|
|
fcompletion = 1;//
|
|
if ( iParam[0] == 5 )
|
|
{
|
|
}
|
|
else if ( iParam[0] == 4 )
|
|
InPrintMode = FALSE;
|
|
break;
|
|
case 'K':
|
|
if (bMode & MODE_BRK)
|
|
{
|
|
if (iCurrentParam < 1)
|
|
iParam[0] = 0;
|
|
switch (iParam[0])
|
|
{
|
|
case 0:
|
|
ConClearEOLine();
|
|
break;
|
|
case 1:
|
|
ConClearBOLine();
|
|
break;
|
|
case 2:
|
|
ConClearLine();
|
|
break;
|
|
}
|
|
}
|
|
else if (bMode == 0)
|
|
{
|
|
bMode |= MODE_K;
|
|
}
|
|
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'J':
|
|
if (iCurrentParam < 1)
|
|
iParam[0] = 0;
|
|
switch (iParam[0])
|
|
{
|
|
case 0:
|
|
ConClearEOScreen();
|
|
break;
|
|
case 1:
|
|
ConClearBOScreen();
|
|
break;
|
|
case 2:
|
|
ConClearScreen();
|
|
break;
|
|
}
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'n':
|
|
if (iCurrentParam < 1)
|
|
{
|
|
if (iParam[0] == 5)
|
|
{
|
|
char * szStatus = GetStatusReport();
|
|
NetWriteString(szStatus, strlen(szStatus));
|
|
}
|
|
else if ( iParam[0] == 6 )
|
|
{
|
|
char * szStatus = GetStatusReport();
|
|
NetWriteString(szStatus, strlen(szStatus));
|
|
}
|
|
}
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
if (bMode == (MODE_BRK & MODE_EXT))
|
|
{
|
|
// What are you response
|
|
}
|
|
else if (bMode == MODE_BRK)
|
|
{
|
|
char* szTerminalId = GetTerminalId();
|
|
NetWriteString(szTerminalId, strlen(szTerminalId));
|
|
}
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'y':
|
|
case 'q':
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'Z': // Identify - This is really a VT52 command
|
|
{
|
|
char* szTerminalId = GetTerminalId();
|
|
NetWriteString(szTerminalId, strlen(szTerminalId));
|
|
}
|
|
fcompletion = 1;
|
|
break;
|
|
|
|
case 'P':
|
|
ConDeleteChars(iParam[0]);
|
|
fcompletion = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// pszHead should point to digit now. Otherwise we got bad escape
|
|
// sequence, so we just get out of here!
|
|
if (!isdigit(*pszCurrent))
|
|
{
|
|
pszCurrent = pszBuffer;
|
|
return pszCurrent;
|
|
}
|
|
|
|
iParam[iCurrentParam] = strtoul((const char *)pszCurrent, (char **)&pszCurrent, 10);
|
|
|
|
pszCurrent--;
|
|
|
|
if (iCurrentParam < nParam)
|
|
iCurrentParam++;
|
|
|
|
// Check for digit completion
|
|
if (bMode & DIGI_MASK)
|
|
fcompletion = 1;
|
|
|
|
if (bMode == 0)
|
|
{
|
|
switch(iParam[0])
|
|
{
|
|
case 7:
|
|
SavedX = ConGetCursorX();
|
|
SavedY = ConGetCursorY();
|
|
break;
|
|
case 8:
|
|
ConSetCursorPosition(SavedX,SavedY);
|
|
break;
|
|
}
|
|
fcompletion = 1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
} while ((++pszCurrent < pszBufferEnd) && !fcompletion);
|
|
|
|
if (fcompletion)
|
|
{
|
|
memset(iParam, '\0', sizeof(iParam));
|
|
iCurrentParam = 0;
|
|
bDelimiter = 0;
|
|
bMode = 0;
|
|
// fcompletion = 0;
|
|
bExtMode = 0;
|
|
bCS0 = 0;
|
|
bCS1 = 0;
|
|
bBkMode = 0;
|
|
bCharMode = 0;
|
|
return pszCurrent;
|
|
}
|
|
else
|
|
return pszBuffer;
|
|
}
|
|
|
|
unsigned char * ParseVT52(unsigned char * pszBuffer, unsigned char * pszBufferEnd)
|
|
{
|
|
unsigned char * pszCurrent = pszBuffer;
|
|
int iLine;
|
|
int iColumn;
|
|
|
|
switch ((unsigned char) *pszCurrent)
|
|
{
|
|
|
|
case 'A': // Cursor Up
|
|
ConMoveCursorPosition(0, -1);
|
|
pszCurrent++;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
|
|
case 'B': // Cursor Down
|
|
ConMoveCursorPosition(0, 1);
|
|
pszCurrent++;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
case 'C': // Cursor Right
|
|
ConMoveCursorPosition(1, 0);
|
|
pszCurrent++;
|
|
break;
|
|
case 'D': // Cursor Left
|
|
ConMoveCursorPosition(-1, 0);
|
|
pszCurrent++;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
case 'F': // Special Graphics Character Set
|
|
case 'G': // ASCII Character Set
|
|
pszCurrent++;
|
|
break;
|
|
case 'H': // Cursor Home
|
|
|
|
ConSetCursorPosition(1, 1);
|
|
pszCurrent++;
|
|
bAtEOLN = FALSE;
|
|
break;
|
|
case 'I': // Reverse Line Feed
|
|
pszCurrent++;
|
|
break;
|
|
case 'J': // Erase to End of Screen
|
|
ConClearEOScreen();
|
|
pszCurrent++;
|
|
break;
|
|
case 'K': // Erase to End of Line
|
|
ConClearEOLine();
|
|
pszCurrent++;
|
|
break;
|
|
case 'Y': // Direct Cursor Addressing
|
|
pszCurrent = GetNextChar(pszCurrent,pszBufferEnd);
|
|
if (pszCurrent != NULL)
|
|
{
|
|
iLine = *pszCurrent - 31;
|
|
|
|
pszCurrent = GetNextChar(pszCurrent,pszBufferEnd);
|
|
if (pszCurrent != NULL)
|
|
{
|
|
iColumn = *pszCurrent - 31;
|
|
ConSetCursorPosition(iLine,iColumn);
|
|
pszCurrent++;
|
|
}
|
|
else
|
|
pszCurrent = pszBuffer;
|
|
}
|
|
else
|
|
pszCurrent = pszBuffer;
|
|
break;
|
|
|
|
case 'Z': // Identify
|
|
NetWriteString("\033/Z",3);
|
|
pszCurrent++;
|
|
break;
|
|
case '=': // Enter Alt Keypad mode
|
|
case '>': // Exit Alt Keypad mode
|
|
case '1': // Graphics processor on
|
|
case '2': // Graphics processor off
|
|
pszCurrent++;
|
|
break;
|
|
case '<': // Enter ANSI mode
|
|
term_mode = TERM_ANSI;
|
|
pszCurrent++;
|
|
break;
|
|
default:
|
|
pszCurrent++;
|
|
}
|
|
|
|
return pszCurrent;
|
|
|
|
}
|