// Copyright (C) 2000
//          by the Massachusetts Institute of Technology
//
//    Export of this software from the United States of America may
//    require a specific license from the United States Government.  It
//    is the responsibility of any person or organization contemplating
//    export to obtain such a license before exporting.
//
// WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
// distribute this software and its documentation for any purpose and
// without fee is hereby granted, provided that the above copyright
// notice appear in all copies and that both that copyright notice and
// this permission notice appear in supporting documentation, and that
// the name of M.I.T. not be used in advertising or publicity pertaining
// to distribution of the software without specific, written prior
// permission.  M.I.T. makes no representations about the suitability of
// this software for any purpose.  It is provided "as is" without express
// or implied warranty.

// TermCap.cpp: implementation of the CTermCap class.

//#include <ctype.h>

#include <mbstring.h>		 //for _mbslen
#include "winssh.h"
#include "Errors.h"
#include "TermCap.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTermCap::CTermCap()
{
	memset(m_szVtName, 0x00, 10);
	m_iCommandCount = 0;
	ulLastCommand = 0L;
	memset(m_uszIncompleteCommand, NULL, sizeof(m_uszIncompleteCommand));
	m_usIncompleteCommandLen = 0;
}

CTermCap::~CTermCap()
{
	//memseteverything again
}

//////////////////////////////////////////////////////////////////////
// le Publik functions
//////////////////////////////////////////////////////////////////////

int CTermCap::Initialize(UINT TermType)
{
	int i=0; //loop counter

	if (TermType == TC_VT100)
	{
		// clear all commands in Queue
		m_iCommandCount = 0;
		for (i=0; i<TC_MAXCQUEUE; i++)
		{
			m_QUEUE[i].ulCommand = 0L;
			m_QUEUE[i].iArg1 = 0;
			m_QUEUE[i].iArg2 = 0;
		}

		m_iRProcessIndex = 0;
		
		strcpy(&m_szVtName[0], "VT100");
		memset(m_szVtName, 0x00, 10);
		
	}
	else if (TermType == TC_VT102)
	{
		// initialize stuff here
	} else return -1;

	return 0;
}

//////////////////////////////////////////////////////////////////////
// Process Sending Functions

int CTermCap::VtSendProcess(const UINT nChar, UCHAR* pszOut)
{
	int iSequenceLength = 0;

	switch (nChar)
	{
	case VK_BACK:	// backspace
		strncpy((char*)pszOut,"\b",2);		iSequenceLength = 1;				break;
	case VK_RETURN:
		strncpy((char*)pszOut,"\r",2);		iSequenceLength = 1;				break;
	case VK_TAB:
		strncpy((char*)pszOut,"\t",2);		iSequenceLength = 1;				break;
	case VK_HOME:
		strncpy((char*)pszOut,"\x01b[1~",5);iSequenceLength = 4;				break;
	case VK_SPACE:
		strncpy((char*)pszOut," ",2);		iSequenceLength = 1;				break;
	case VK_INSERT:
		strncpy((char*)pszOut,"\x01b[2~",5);iSequenceLength = 4;				break;
	case VK_DELETE:
		strncpy((char*)pszOut,"\x01b[3~",5);iSequenceLength = 4;				break;
	case VK_END:
		strncpy((char*)pszOut,"\x01b[4~",5);iSequenceLength = 4;				break;
	case VK_UP:
		strncpy((char*)pszOut,"\x01bOA",4);	iSequenceLength = 3;				break;
	case VK_DOWN:
		strncpy((char*)pszOut,"\x01bOB",4);	iSequenceLength = 3;				break;
	case VK_RIGHT:
		strncpy((char*)pszOut,"\x01bOC",4);	iSequenceLength = 3;				break;
	case VK_LEFT:
		strncpy((char*)pszOut,"\x01bOD",4);	iSequenceLength = 3;				break;
	default:		//ignored
		iSequenceLength = -1;									break;
	}
		
	return iSequenceLength;
}

//////////////////////////////////////////////////////////////////////
// Process Sending Functions

// new version of VtRecvProcess() 31 Jan 1999.
int CTermCap::VtRecvProcess(UCHAR* pszProcessBuffer,const UINT BufLen)
{
	int iProcessReturn;

	memset(m_uszIncompleteCommand, NULL, sizeof(m_uszIncompleteCommand));
	m_usIncompleteCommandLen = 0;

	m_iRProcessIndex = 0;	//set to beginning of recvBuffer
	m_iRProcessEnd = (int)BufLen; // Set to End of recvBuffer

	while (m_iRProcessIndex < m_iRProcessEnd)
	{
		if ( ((BYTE)pszProcessBuffer[m_iRProcessIndex] < TK_ESC) ||
				((BYTE)pszProcessBuffer[m_iRProcessIndex] == TK_DEL))
			iProcessReturn = ProcessC0Command(pszProcessBuffer);
		else if ((BYTE)pszProcessBuffer[m_iRProcessIndex] == TK_ESC)
		{
			if ((BYTE)pszProcessBuffer[m_iRProcessIndex+1] == '[')
				iProcessReturn = ProcessEscBracketCommand(pszProcessBuffer);
			else
				iProcessReturn = ProcessEscCommand(pszProcessBuffer);
		}
		else
				iProcessReturn = ProcessNonCommand(pszProcessBuffer);

		// Process returns -l when see an incomplete cmd or empty buf.
		// or see if ProcessBuffer is empty
		if (iProcessReturn == -1)
			break;
	}// end while

	 return ((int)_mbslen(pszProcessBuffer));
}
int CTermCap::DequeueCommand(ULONG& Command, int& Arg1, int& Arg2)
{
	int		i; // loop counter

	if (m_iCommandCount <= 0)
		return 0;
	else
	{
		ulLastCommand = m_QUEUE[0].ulCommand;
		Command = ulLastCommand;
		Arg1 = m_QUEUE[0].iArg1;
		Arg2 = m_QUEUE[0].iArg2;
		
		//push everything up one
		for (i=0; i< m_iCommandCount; i++)
		{
			m_QUEUE[i] = m_QUEUE[i+1];
		}
		m_iCommandCount--;
	}
	return 1;
}

ULONG CTermCap::PeekCommand(int Index)
{
	if (Index >= m_iCommandCount)
		return 0L;
	else
		return m_QUEUE[Index].ulCommand;
}

//////////////////////////////////////////////////////////////////////
// el Privato functions
//////////////////////////////////////////////////////////////////////

//new version of QueueCommand() 31 Jan 99
int CTermCap::QueueCommand(UCHAR* pszProcessBuffer, ULONG Cmd, int Arg1, int Arg2)
{
#ifdef DEBUG_SSH
	if (Cmd == TC_UNKNOWN)
	{
		UCHAR	uszDebugCommand[10];
		memset(uszDebugCommand, NULL, 10);
		int iDebugLen = m_iRProcessEnd - m_iRProcessIndex;
		if (iDebugLen > 10) iDebugLen = 10;
		memcpy(uszDebugCommand, &pszProcessBuffer[m_iRProcessIndex], iDebugLen);
		for (int i=0; i<iDebugLen; i++)
		{
			if ((BYTE)uszDebugCommand[i] == TK_ESC) 
				uszDebugCommand[i] = '\\';			//replace with a '\'
			if ((BYTE)uszDebugCommand[i] < TK_ESC)
				uszDebugCommand[i] = '.';			//replace with dots
		}
		Debug("CTermCap() Found UNKNOWN Terminal Sequence - %s, len=%d", uszDebugCommand, iDebugLen);
	}
#endif
	if (m_iCommandCount >= TC_MAXCQUEUE-1)
		return -1;
	else
	{
		m_QUEUE[m_iCommandCount].ulCommand = Cmd;
		m_QUEUE[m_iCommandCount].iArg1 = Arg1;
		m_QUEUE[m_iCommandCount].iArg2 = Arg2;
		m_iCommandCount++;
		//replace command character to TC_CMDSIGNAL.
		pszProcessBuffer[m_iRProcessIndex++] = TC_CMDSIGNAL;
	}
	return 0;
}

void CTermCap::QueueCommandFiller(UCHAR* pszProcessBuffer, int iCharCount)
{
	for (int i=0; i<iCharCount; i++)
		pszProcessBuffer[m_iRProcessIndex++] = TC_CMDFILLER;
}

int CTermCap::SaveIncompleteCommand(UCHAR* pszProcessBuffer)
{
	m_usIncompleteCommandLen = (unsigned short) (m_iRProcessEnd - m_iRProcessIndex);
	if (m_usIncompleteCommandLen > sizeof(m_uszIncompleteCommand))
		m_usIncompleteCommandLen = sizeof(m_uszIncompleteCommand);
	memset(m_uszIncompleteCommand, NULL, sizeof(m_uszIncompleteCommand));
	memcpy(m_uszIncompleteCommand, &pszProcessBuffer[m_iRProcessIndex], m_usIncompleteCommandLen);

	QueueCommandFiller(pszProcessBuffer, m_usIncompleteCommandLen);
	
	return -1;
}

//////////////////////////////////////////////////////////////////////
// ProcessCommand Functions
//////////////////////////////////////////////////////////////////////

//new version of ProcessC0Command() 31 Jan 99
int CTermCap::ProcessC0Command(UCHAR* pszProcessBuffer)
{
	int		iReturnCode;
	int		iErrorCheck = 1;	// 0 command found; -1 error
	
	switch(pszProcessBuffer[m_iRProcessIndex])
	{			// Ctrl   Dec.	Shorthand
	case NULL:	
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_NULL);			break;
	case TK_ENQ://	^E		05
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_ANSWERBACK);		break;
	case TK_BEL://	^G		07	\a
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_BELL);			break;
	case TK_BS:	//	^H		08	\b
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_BACKSPACE);		break;
	case TK_HT:	//	^I		09	\t
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_TAB);			break;
	case TK_LF:	//	^J		10	\l or \n
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_LINEFEED);		break;
	case TK_VT:	//	^K		11	\v
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_VERTTAB);		break;
	case TK_FF:	//	^L		12	\f			
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_FORMFEED);		break;
	case TK_CR:	//	^M		13	\r
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_RETURN);			break;
	case TK_SO:
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_INVOKEG1);		break;
	case TK_SI:
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_INVOKEG0);		break;
	case TK_CAN: //	^X		24
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_CANCELESC);		break;
	case TK_DEL: //		127
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_BACKSPACE);		break;
	default:
		iErrorCheck = QueueCommand(pszProcessBuffer,TC_UNKNOWN);
		break;
	} // end switch
		
	// Error Checking and Check bound conditions
	if ((iErrorCheck == -1) || (m_iRProcessIndex >= m_iRProcessEnd))
		iReturnCode = -1;
	else
		iReturnCode = 0;
	
	return iReturnCode;
} //// END (CTermCap::ProcessC0Command) ////

////////////////////////////////////////////////////////////////////////////
int CTermCap::ProcessEscCommand(UCHAR* pszProcessBuffer)
{
	int		iReturnCode;
	UINT	i;			// loop Counter
	int		iErrorCheck;	// 0 command found; -1 error
	int		iSequenceLength = 1;// ESC Sequence Length
	bool	b_ScanFlag	= TRUE;
	
	// Check Ending Index of TProcessBuffer;
	//if (_mbslen(m_szTProcessBuffer) >= TC_MAXBUFLEN)
	//	return -1;
	
	iSequenceLength = 2;	// pretty much default
	switch(pszProcessBuffer[m_iRProcessIndex+1])
	{
	case 'D':
		iErrorCheck = QueueCommand(pszProcessBuffer, TC_SCROLLFWD);
		QueueCommandFiller(pszProcessBuffer);
		break;
	case 'E':
		iErrorCheck = QueueCommand(pszProcessBuffer, TC_NEWLINE);
		QueueCommandFiller(pszProcessBuffer);
		break;
	case 'H': // st: set tab stop all rows, current column
		iErrorCheck = QueueCommand(pszProcessBuffer, TC_SETTAB);
		QueueCommandFiller(pszProcessBuffer);
		break;
	case 'M':
		iErrorCheck = QueueCommand(pszProcessBuffer, TC_SCROLLREV);
		QueueCommandFiller(pszProcessBuffer);
		break;
	case '7':
		iErrorCheck = QueueCommand(pszProcessBuffer, TC_SAVECURSOR);
		QueueCommandFiller(pszProcessBuffer);
		break;
	case '8':
		iErrorCheck = QueueCommand(pszProcessBuffer, TC_RESTORECURSOR);
		QueueCommandFiller(pszProcessBuffer);
		break;
	case '(':
		iSequenceLength = 3;  // default Seq. length
		if (pszProcessBuffer[m_iRProcessIndex+2] == '0')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_ALTCHARSET_ON);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else if (pszProcessBuffer[m_iRProcessIndex+2] == 'B')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_ALTCHARSET_OFF);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else // UNKNOWN or incomplete VT100 command
		{
			if (m_iRProcessIndex+2 >= m_iRProcessEnd) // end of string; incomplete command
				iErrorCheck = SaveIncompleteCommand(pszProcessBuffer);
			else
			{
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
				QueueCommandFiller(pszProcessBuffer, 2);
			}
		}
		break;
	case 'O':
		iSequenceLength = 3;
		if (pszProcessBuffer[m_iRProcessIndex+2] == 'A')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_UP);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else if (pszProcessBuffer[m_iRProcessIndex+2] == 'B')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_DOWN);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else if (pszProcessBuffer[m_iRProcessIndex+2] == 'C')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_RIGHT);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else if (pszProcessBuffer[m_iRProcessIndex+2] == 'D')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_LEFT);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else if (pszProcessBuffer[m_iRProcessIndex+2] == 'P')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F1);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else if (pszProcessBuffer[m_iRProcessIndex+2] == 'Q')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F2);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else if (pszProcessBuffer[m_iRProcessIndex+2] == 'R')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F3);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else if (pszProcessBuffer[m_iRProcessIndex+2] == 'S')
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F4);
			QueueCommandFiller(pszProcessBuffer, 2);
		}
		else // UNKNOWN or incomplete VT100 command
		{
			if (m_iRProcessIndex+2 >= m_iRProcessEnd) // end of string; incomplete command
				iErrorCheck = SaveIncompleteCommand(pszProcessBuffer);
			else
			{
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
				QueueCommandFiller(pszProcessBuffer, 2);
			}
		}
		break;
	case '>':	//   is  or   rs
 		b_ScanFlag = TRUE;	i = 2;	//starting from char after "\E>"
		iSequenceLength = 0;
		while (b_ScanFlag)
		{
			if ((pszProcessBuffer[m_iRProcessIndex+i] == '1') && 
				(pszProcessBuffer[m_iRProcessIndex+i+1] == 'H'))
			{
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_INIT_STR);
				QueueCommandFiller(pszProcessBuffer, i+1);
				b_ScanFlag = FALSE;
				iSequenceLength = 3;
			}
			else if (pszProcessBuffer[m_iRProcessIndex+i] == '\0') //incomplete 'is' string
				b_ScanFlag = FALSE;
			i++;
		}
		b_ScanFlag = TRUE;	i = 2;
		if (iSequenceLength == 0) // 'is' was never found
		{	while (b_ScanFlag)
			{
				if ((pszProcessBuffer[m_iRProcessIndex+i] == '8') &&
					(pszProcessBuffer[m_iRProcessIndex+i+1] == 'h'))
				{
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_RESET_STR);
					QueueCommandFiller(pszProcessBuffer, i+1);
					b_ScanFlag = FALSE;
				}
				else if (pszProcessBuffer[m_iRProcessIndex+i] == '\0')
					b_ScanFlag = FALSE;
				i++;
			}
		} // endif
		if (iSequenceLength == 0) // 'is' nor 'rs' ever found
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
			QueueCommandFiller(pszProcessBuffer);
		}
		break;
	default:
		if (m_iRProcessIndex+1 >= m_iRProcessEnd) // end of string; incomplete command
			iErrorCheck = SaveIncompleteCommand(pszProcessBuffer);
		else
		{
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
			QueueCommandFiller(pszProcessBuffer, 1);
		}
	} // end switch

	// Error Checking and Check bound conditions
	if ((iErrorCheck == -1) || (m_iRProcessIndex >= m_iRProcessEnd))
		iReturnCode = -1;
	else	// incomplete or end of ESC
		iReturnCode = 0;
	
	return iReturnCode;

}  //// END (CTermCap::ProcessEscCommand) ////

////////////////////////////////////////////////////////////////////////////
int CTermCap::ProcessEscBracketCommand(UCHAR* pszProcessBuffer)
{
	int		iReturnCode;
	int		j;
	UINT	iIndex;					// points at first non-digit
	int		iErrorCheck;			// 0 command found; -1 error
	int		iSequenceLength = 1;				// ESC Sequence Length
	int		iTempArgs[20];						//Temporary Arguments
	int		iArgCount = 0;
	int		iEndOfSequence;
	
	if ((isdigit((char)pszProcessBuffer[m_iRProcessIndex+2])) ||
						(pszProcessBuffer[m_iRProcessIndex+2]) == ';')
	{
		memset(iTempArgs, 0x00, sizeof(iTempArgs));
		iArgCount = 0;
		iIndex = 1;

		do
		{
			iIndex++;
			while (isdigit((char)pszProcessBuffer[m_iRProcessIndex+iIndex]))
			{
				iTempArgs[iArgCount] = iTempArgs[iArgCount] * 10;
				iTempArgs[iArgCount] +=	(BYTE)pszProcessBuffer[m_iRProcessIndex+iIndex] - '0';
				iIndex++;
			} // end of Reading Arg1; iIndex should be pointing at the first nondigit
			iArgCount++;
		}
		while (pszProcessBuffer[m_iRProcessIndex+iIndex] == ';');


		iEndOfSequence = m_iRProcessIndex+iIndex;
		// read argument until ~,m,g,,ABCD,n
		switch (pszProcessBuffer[m_iRProcessIndex+iIndex])
		{
		case 'm': // one of the charcter modes
			for (j=0; j<iArgCount; j++)
			{
				if      (iTempArgs[j] == 1)
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_ATTR_BOLD);
				else if (iTempArgs[j] == 4)
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_ATTR_UNDERLINE);
				else if (iTempArgs[j] == 5)
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_ATTR_BLINK);
				else if (iTempArgs[j] == 7)
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_ATTR_REVERSE);
				else
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
			}
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case 'n':  // Device Status Report
			for (j=0; j<iArgCount; j++)
			{
				if		(iTempArgs[j] == 5)
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_DEVICE_STATUS);
				else if (iTempArgs[j] == 6)
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_DEVICE_CURSOR);
				else
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
			}
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case '~':
			for (j=0; j<iArgCount; j++)
			{
				switch (iTempArgs[j])
				{
				case 1:		// kh : Sent by Home
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_HOME);		break;
				case 2:		// kI : Sent by Insert
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_INSERT);	break;
				case 3:		// kD : Sent by Delete
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_DELETE);	break;
				case 4:		// @7 : End key
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_END);					break;
				case 5:		// kP : Sent by PageUp
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_PAGEUP);	break;
				case 6:		// kN : Sent by PageDown
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_PAGEDOWN);	break;
				case 10:	// k0 : Sent by F0
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F0);			break;
				case 15:	// k5 : F5
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F5);			break;
				case 17:	// k6 : F6
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F6);			break;
				case 18:	// k7 : F7
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F7);			break;
				case 19:	// k8 : F8
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F8);			break;
				case 20:	// k9 : F9
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F9);			break;
				case 21:	// k; : 11th function
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F10);		break;
				case 23:	// F1 : F11
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F11);		break;
				case 24:	// F2 : F12
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_SENTBY_F12);		break;
				default:
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);			break;
				}
			}
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case 'g':
			for (j=0; j<iArgCount; j++)
			{
				switch (iTempArgs[j])
				{
				case 3:		// ct : Clear all tab stops
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_CLEAR_TAB);			break;
				default:
					iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);			break;
				}
			}
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case 'A':
			for (j=0; j<iArgCount; j++)
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSOR_UP_ARG,iTempArgs[j]);
			QueueCommandFiller(pszProcessBuffer,iIndex);
			break;
		case 'B':
			for (j=0; j<iArgCount; j++)
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSOR_DOWN_ARG,iTempArgs[j]);
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case 'C':
			for (j=0; j<iArgCount; j++)
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSOR_RIGHT_ARG,iTempArgs[j]);
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case 'D':
			for (j=0; j<iArgCount; j++)
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSOR_LEFT_ARG,iTempArgs[j]);
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case 'H':	//cm default is 1 1
			if (iTempArgs[0] == 0)	iTempArgs[0] = 1;
			if	(iTempArgs[1] == 0)	iTempArgs[1] = 1;
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSORTO_ARG_ARG,iTempArgs[0],iTempArgs[1]);
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case 'J':	//clear after cursor
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_CLR_AFTERCURSOR,iTempArgs[0],iTempArgs[1]);
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		case 'r':
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_SCROLLTO_ARG_ARG,iTempArgs[0],iTempArgs[1]);
			QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			break;
		default:
			if (iEndOfSequence >= m_iRProcessEnd)
				iErrorCheck = SaveIncompleteCommand(pszProcessBuffer);
			else
			{
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
				QueueCommandFiller(pszProcessBuffer, iEndOfSequence - m_iRProcessIndex + 1);
			}
			break;
		} // end switch
	
	} // end of all numeric commands
	else
	{
		iSequenceLength = 3;
		// this switch doesnt to numeric brackets
		switch(pszProcessBuffer[m_iRProcessIndex+2])
		{
		case 'A':	//up
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSOR_UP);
			QueueCommandFiller(pszProcessBuffer,2);
			break;
		case 'B':	//do
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSOR_DOWN);
			QueueCommandFiller(pszProcessBuffer,2);
			break;
		case 'C':	//nd
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSOR_RIGHT);			
			QueueCommandFiller(pszProcessBuffer,2);
			break;
		case 'J':	//cd
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_CLR_AFTERCURSOR);		
			QueueCommandFiller(pszProcessBuffer,2);
			break;
		case 'K':	//ce
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_CLR_TO_EOLN);			
			QueueCommandFiller(pszProcessBuffer,2);
			break;
		case 'H':	// ho (or) cl
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_CURSOR_HOME);			
			QueueCommandFiller(pszProcessBuffer,2);
			break;
		case 'm':	// me: turn off all attributes
			iErrorCheck = QueueCommand(pszProcessBuffer, TC_ATTR_OFF);				
			QueueCommandFiller(pszProcessBuffer,2);
			break;
		case '?': // ks or ke
			if (pszProcessBuffer[m_iRProcessIndex+3] != '1')
			{
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
				QueueCommandFiller(pszProcessBuffer,2);
			}
			else if (pszProcessBuffer[m_iRProcessIndex+4] == 'h')
			{
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_KEYPAD_ON);
				QueueCommandFiller(pszProcessBuffer, 4);
			}
			else if (pszProcessBuffer[m_iRProcessIndex+4] == 'l')
			{
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_KEYPAD_OFF);
				QueueCommandFiller(pszProcessBuffer, 4);
			}
			else iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
			break;
		default:
			if (m_iRProcessIndex+2 >= m_iRProcessEnd)
				iErrorCheck = SaveIncompleteCommand(pszProcessBuffer);
			else
			{
				iErrorCheck = QueueCommand(pszProcessBuffer, TC_UNKNOWN);
				QueueCommandFiller(pszProcessBuffer,2);
			}
			break;
		} // end switch

	} // end if-else (iswdigit)


	// Error Checking and Check bound conditions
	if ((iErrorCheck == -1) || (m_iRProcessIndex >= m_iRProcessEnd))
		iReturnCode = -1;
	else	// incomplete or end of ESC[ commands
		iReturnCode = 0;

	return iReturnCode;
} //// END (CTermCap::ProcessEscBracketCommand) ////

////////////////////////////////////////////////////////////////////////////////////////////
//new version of ProcessNonCommand() 31 Jan 99
int CTermCap::ProcessNonCommand(UCHAR* pszProcessBuffer)
{
	int		iReturnCode;
	bool	b_ContinueProcess = TRUE;

	while ( (pszProcessBuffer[m_iRProcessIndex] > TK_ESC) && (m_iRProcessIndex <= m_iRProcessEnd))
	{
		if ((BYTE)pszProcessBuffer[m_iRProcessIndex] != 0xff)
			m_iRProcessIndex++;
		else								// junk (IAC) Command: 3 bytes long
											// we skip over those
		{
			pszProcessBuffer[m_iRProcessIndex++] = TC_CMDFILLER;
			pszProcessBuffer[m_iRProcessIndex++] = TC_CMDFILLER;
			pszProcessBuffer[m_iRProcessIndex++] = TC_CMDFILLER;
		}
	}

	// Check bound conditions
	if (m_iRProcessIndex >= m_iRProcessEnd)
		iReturnCode = -1;
	else 
		iReturnCode = 0;

	return iReturnCode;
} //// END (CTermCap::ProcessNonCommand) ////
