/* ansiprsr.c * Author: Pragma Systems, Inc. * Contribution by Pragma Systems, Inc. for Microsoft openssh win32 port * Copyright (c) 2011, 2015 Pragma Systems, Inc. * All rights reserved * * ANSI Parser to run on Win32 based operating systems. * * 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. * 2. Binaries produced provide no direct or implied warranties or any * guarantee of performance or suitability. */ #include #include #include #include #include #include #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 lftocrlf; 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= (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_LF; lftocrlf = 1; }else{ VTMode &= ~MODE_LNM; Parameters.nReceiveCRLF = ENUM_CRLF; lftocrlf = 0; } 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 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': // 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; }