ansiprsr.cpp

来自「一个类似windows」· C++ 代码 · 共 1,477 行 · 第 1/3 页

CPP
1,477
字号
///////////////////////////////////////////////////////////////////////////////
//Telnet Win32 : an ANSI telnet client.
//Copyright (C) 1998-2000 Paul Brannan
//Copyright (C) 1998 I.Ioannou
//Copyright (C) 1997 Brad Johnson
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//I.Ioannou
//roryt@hol.gr
//
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Module:		ansiprsr.cpp
//
// Contents:	ANSI parser base class
//
// Product:		telnet
//
// Revisions: August 30, 1998 Paul Brannan <pbranna@clemson.edu>
//            July 29, 1998 pbranna@clemson.edu
//            June 15, 1998 pbranna@clemson.edu
//            May 19, 1998  pbranna@clemson.edu
//            24 Dec, 1997  Andrey.V.Smilianets
//            05. Sep.1997  roryt@hol.gr (I.Ioannou)
//            11.May.1997   roryt@hol.gr (I.Ioannou)
//            6.April.1997  roryt@hol.gr (I.Ioannou)
//            5.April.1997  jbj@nounname.com
//            30.M剅z.1997	Titus_Boxberg@public.uni-hamburg.de
//		      14.Sept.1996  jbj@nounname.com
//            Version 2.0
//
//            13.Jul.1995	igor.milavec@uni-lj.si
//					  Original code
//
///////////////////////////////////////////////////////////////////////////////

//#include <windows.h>
#include <string.h>
#include "ansiprsr.h"

const int ANSIColors[] = {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE};

// The constructor now takes different arguments and initializes different
// variables (Paul Brannan 6/15/98)
TANSIParser::TANSIParser(TConsole &RefConsole, KeyTranslator &RefKeyTrans,
						 TScroller &RefScroller, TNetwork &RefNetwork,
						 TCharmap &RefCharmap):
TParser(RefConsole, RefKeyTrans, RefScroller, RefNetwork, RefCharmap) {
	Init();
	iSavedAttributes = (unsigned char) 7;
	// must also check to make sure the string is non-NULL
	// (Paul Brannan 5/8/98)
	if ((ini.get_dumpfile() != NULL) && (*ini.get_dumpfile() != '\0')){
		dumpfile = fopen(ini.get_dumpfile(), "wb");
	}else {
		dumpfile = NULL;
	}
	InPrintMode = 0;
	printfile = NULL;

	fast_write = ini.get_fast_write(); // Paul Brannan 6/28/98
	Scroller.init(&StripBuffer);
}

TANSIParser::~TANSIParser(){
	if (dumpfile) fclose (dumpfile);
	// Added I.Ioannou 06 April, 1997
	if (printfile != NULL) fclose (printfile);
}

// Created Init() function to initialize the parser but not clear the screen
// (Paul Brannan 9/23/98)
void TANSIParser::Init() {
	// Paul Brannan 6/25/98
	map_G0 = 'B'; map_G1 = 'B';
	Charmap.setmap(map_G0);
	current_map = 'B';

	ignore_margins = 0;
	vt52_mode = 0;
	print_ctrl = 0;
	newline_mode = false;

	KeyTrans.clear_ext_mode();

	iSavedCurY = 0;							// Reset Variables
	iSavedCurX = 0;
	inGraphMode = 0;
	Console.SetScroll(-1, -1);
	Console.Normal();						// Reset Attributes

	// Set tabs stops
	resetTabStops();
}

void TANSIParser::ResetTerminal() {
	Init();
	Console.ClearScreen();					// Clear Screen
	Console.SetRawCursorPosition(0,0);		// Home Cursor
}
void TANSIParser::SaveCurY(int iY){
	iSavedCurY=iY;
}

void TANSIParser::SaveCurX(int iX){
	iSavedCurX=iX;
}

void TANSIParser::resetTabStops() {
	for(int j = 0; j < MAX_TAB_POSITIONS; j++) {
		tab_stops[j] = 8 + j - (j%8);
	}
}

void TANSIParser::ConSetAttribute(unsigned char TextAttrib){
	// Paul Brannan 5/8/98
	// Made this go a little bit faster by changing from switch{} to an array
	// for the colors
	if(TextAttrib >= 30) {
		if(TextAttrib <= 37) {
			Console.SetForeground(ANSIColors[TextAttrib-30]);
			return;
		} else if((TextAttrib >= 40) && (TextAttrib <= 47)) {
			Console.SetBackground(ANSIColors[TextAttrib-40]);
			return;
		}
	}
	
	switch (TextAttrib){
		// Text Attributes
	case 0: Console.Normal();           break;	// Normal video
	case 1: Console.HighVideo();        break;	// High video
	case 2: Console.LowVideo();         break;	// Low video
	case 4: Console.UnderlineOn();		break;	// Underline on (I.Ioannou)
	case 5: Console.BlinkOn();			break;	// Blink video
		// Corrected by I.Ioannou 11 May, 1997
	case 7: Console.ReverseOn();		break;	// Reverse video
	case 8:								break;	// hidden
		// All from 10 thru 27 are hacked from linux kernel
		// I.Ioannou 06 April, 1997
	case 10:
		//  I.Ioannou 04 Sep 1997 turn on/off high bit
		inGraphMode = 0;
		print_ctrl = 0;
		Charmap.setmap(current_map ? map_G1:map_G0); // Paul Brannan 6/25/98
		break; // ANSI X3.64-1979 (SCO-ish?)
		// Select primary font,
		// don't display control chars
		// if defined, don't set
		// bit 8 on output (normal)
	case 11:
		inGraphMode = 0;
		print_ctrl = 1;
		Charmap.setmap(0); // Paul Brannan 6/25/98
		break; // ANSI X3.64-1979 (SCO-ish?)
		// Select first alternate font,
		// let chars < 32 be displayed
		// as ROM chars
	case 12:
		inGraphMode = 1;
		print_ctrl = 1;
		Charmap.setmap(0); // Paul Brannan 6/25/98
		break; // ANSI X3.64-1979 (SCO-ish?)
		// Select second alternate font,
		// toggle high bit before
		// displaying as ROM char.
		
	case 21:									// not really Low video
	case 22: Console.LowVideo();		break;	// but this works good also
	case 24: Console.UnderlineOff();	break;	// Underline off
	case 25: Console.BlinkOff();		break;	// blink off
		// Corrected by I.Ioannou 11 May, 1997
	case 27: Console.ReverseOff();		break;	//Reverse video off

	// Mutt needs this (Paul Brannan, Peter Jordan 12/31/98)
	// This is from the Linux kernel source
    case 38: /* ANSI X3.64-1979 (SCO-ish?)
			  * Enables underscore, white foreground
			  * with white underscore (Linux - use
			  * default foreground).
			  */
			Console.UnderlineOn();
			Console.SetForeground(ini.get_normal_fg());
			break;
	case 39: /* ANSI X3.64-1979 (SCO-ish?)
			  * Disable underline option.
			  * Reset colour to default? It did this
			  * before...
			  */
			Console.UnderlineOff();
			Console.SetForeground(ini.get_normal_fg());
			break;
	case 49:
			Console.SetBackground(ini.get_normal_bg());
			break;

	}
}

void TANSIParser::ConSetCursorPos(int x, int y) {
	if(ignore_margins)
		Console.SetRawCursorPosition(x, y);
	else
		Console.SetCursorPosition(x, y);
}

const char* TANSIParser::GetTerminalID()
{
	return "\033[?1;2c";
}

// All of the Telnet protocol stuff has been moved to TTelHndl.cpp
// This is more consistent with what OO should be
// (Paul Brannan 6/15/98)

#ifdef __BORLANDC__
// argsused doesn't work on MSVC++
#pragma argsused
#endif

// Use this for the VT100 flags (Paul Brannan 12/2/98)
#define FLAG_DOLLAR		0x0001
#define FLAG_QMARK		0x0002
#define FLAG_GREATER	0x0004
#define FLAG_LESS		0x0008
#define FLAG_EXCLAM		0x0010
#define FLAG_AMPERSAND	0x0020
#define FLAG_SLASH		0x0040
#define FLAG_EQUAL		0x0080
#define FLAG_QUOTE		0x0100
#define FLAG_OTHER		0x8000

char* TANSIParser::ParseEscapeANSI(char* pszBuffer, char* pszBufferEnd)
{
	
	//	The buffer contains something like <ESC>[pA
	//	where p is an optional decimal number specifying the count by which the
	//	appropriate action should take place.
	//	The pointer pszBuffer points us to the p, <ESC> and [ are
	//	already 'consumed'
	
	//	TITUS: Simplification of the code: Assume default count of 1 in case
	//	there are no parameters.
	char tmpc;
	const int nParam = 10;	// Maximum number of parameters
	int	iParam[nParam] = {1, 0, 0, 0, 0};	// Assume 1 Parameter, Default 1
	int iCurrentParam = 0;
	DWORD flag = 0;
	int missing_param = 0;

	// Get parameters from escape sequence.
	while ((tmpc = *pszBuffer) <= '?') {

		if(tmpc < '0' || tmpc > '9') {
			// Check for parameter delimiter.
			if(tmpc == ';') {
				// This is a hack (Paul Brannan 6/27/98)
				if(*(pszBuffer - 1) == '[') missing_param = iCurrentParam+1;
				pszBuffer++;
				continue;
			}

			// It is legal to have control characters inside ANSI sequences
			// (Paul Brannan 6/26/98)
			if(tmpc < ' ') {
				Console.WriteCtrlChar(tmpc);
				pszBuffer++;
				continue;
			}

			// A new way of handling flags (Paul Brannan 12/2/98)
			switch(tmpc) {
			case '$': flag |= FLAG_DOLLAR; break;
			case '?': flag |= FLAG_QMARK; break;
			case '>': flag |= FLAG_GREATER; break;
			case '<': flag |= FLAG_LESS; break;
			case '!': flag |= FLAG_EXCLAM; break;
			case '&': flag |= FLAG_AMPERSAND; break;
			case '/': flag |= FLAG_SLASH; break;
			case '=': flag |= FLAG_EQUAL; break;
			case '\"': flag |= FLAG_QUOTE; break;
			default: flag |= FLAG_OTHER; break;
			}

			pszBuffer++;
		}

		//  Got Numerical Parameter.
		iParam[iCurrentParam] = strtoul(pszBuffer, &pszBuffer, 10);
		if (iCurrentParam < nParam)
			iCurrentParam++;
	}
	
	//~~~ TITUS: Apparently the digit is optional (look at termcap or terminfo)
	// So: If there is no digit, assume a count of 1
	
	switch ((unsigned char)*pszBuffer++) {
		// Insert Character
		case '@':
			if(iParam[0] == 0) iParam[0] = 1; // Paul Brannan 9/1/98
			Console.InsertCharacter(iParam[0]); break;
		// Move cursor up.
		case 'A':
			if(iParam[0] == 0) iParam[0] = 1;
			Console.MoveCursorPosition(0, -iParam[0]); break;
		// Move cursor down.
		// Added by I.Ioannou 06 April, 1997
		case 'B':
		case 'e':
			if(iParam[0] == 0) iParam[0] = 1;
			Console.MoveCursorPosition(0, iParam[0]);
			break;
		// Move cursor right.
		// Added by I.Ioannou 06 April, 1997
		case 'C':
		case 'a':
			// Handle cursor size sequences (Jose Cesar Otero Rodriquez and
			// Paul Brannan, 3/27/1999)
			if(flag & FLAG_EQUAL) {
				switch(iParam[0]) {
				case 7: Console.SetCursorSize(50); break;
				case 11: Console.SetCursorSize(6); break;
				case 32: Console.SetCursorSize(0); break;
				default: Console.SetCursorSize(13);
				}
			} else {
				if(iParam[0] == 0) iParam[0] = 1;
				Console.MoveCursorPosition(iParam[0], 0);
				break;
			}
		// Move cursor left.
		case 'D':
			if(iParam[0] == 0) iParam[0] = 1;
			Console.MoveCursorPosition(-iParam[0], 0);
			break;
		// Move cursor to beginning of line, p lines down.
		// Added by I.Ioannou 06 April, 1997
		case 'E': 
			Console.MoveCursorPosition(-Console.GetCursorX(), iParam[0]);
			break;
		// Moves active position to beginning of line, p lines up
		// Added by I.Ioannou 06 April, 1997
		// With '=' this changes the default fg color (Paul Brannan 6/27/98)
		case 'F':
			if(flag & FLAG_EQUAL)
				Console.setDefaultFg(iParam[0]);
			else
				Console.MoveCursorPosition(-Console.GetCursorX(), -iParam[0]);
			break;
		// Go to column p
		// Added by I.Ioannou 06 April, 1997
		// With '=' this changes the default bg color (Paul Brannan 6/27/98)
		case '`': 
		case 'G': // 'G' is from Linux kernel sources
			if(flag & FLAG_EQUAL) {
				Console.setDefaultBg(iParam[0]);
			} else {
				if (iCurrentParam < 1)			// Alter Default
					iParam[0] = 0;
				// this was backward, and we should subtract 1 from x
				// (Paul Brannan 5/27/98)
				ConSetCursorPos(iParam[0] - 1, Console.GetCursorY());
			}
			break;
		// Set cursor position.
		case 'f': 
		case 'H':
			if (iCurrentParam < 2 || iParam[1] < 1)
				iParam[1] = 1;
			ConSetCursorPos(iParam[1] - 1, iParam[0] - 1);
			break;
		// Clear screen
		case 'J': 
			if ( iCurrentParam < 1 ) iParam[0] = 0;	// Alter Default
			switch (iParam[0]) {
				case 0: Console.ClearEOScreen(); break;
				case 1: Console.ClearBOScreen(); break;
				case 2:
					Console.ClearScreen();
					Console.SetRawCursorPosition(0, 0);
					break;
			}
			break;
		// Clear line
		case 'K': 
			if (iCurrentParam < 1)			// Alter Default
				iParam[0] = 0;
			switch (iParam[0]) {
				case 0: Console.ClearEOLine(); break;
				case 1: Console.ClearBOLine(); break;
				case 2: Console.ClearLine(); break;
			}
			break;
		//  Insert p new, blank lines.
		// Added by I.Ioannou 06 April, 1997
		case 'L': 
			{
				// for (int i = 1; i <= iParam[0]; i++)
				// This should speed things up a bit (Paul Brannan 9/2/98)
				Console.ScrollDown(Console.GetRawCursorY(), -1, iParam[0]);
				break;
			}
		//  Delete p lines.
		// Added by I.Ioannou 06 April, 1997
		case 'M': 
			{
				for (int i = 1; i <= iParam[0]; i++)
				// This should speed things up a bit (Paul Brannan 9/2/98)
				Console.ScrollDown(Console.GetRawCursorY(), -1, -1);
				break;
			}
		// DELETE CHAR
		case 'P': 
			Console.DeleteCharacter(iParam[0]);
			break;
		// Scrolls screen up (down? -- PB) p lines,
		// Added by I.Ioannou 06 April, 1997
		// ANSI X3.64-1979 references this but I didn't
		// found it in any telnet implementation
		// note 05 Oct 97  : but SCO terminfo uses them, so uncomment them !!
		case 'S': 
			{
				//for (int i = 1; i <= iParam[0]; i++)
				// This should speed things up a bit (Paul Brannan 9/2/98)
				Console.ScrollDown(-1, -1, -iParam[0]);
				break;
			}
		// Scrolls screen up p lines,
		// Added by I.Ioannou 06 April, 1997
		// ANSI X3.64-1979 references this but I didn't
		// found it in any telnet implementation
		// note 05 Oct 97  : but SCO terminfo uses them, so uncomment them !!
		case 'T': 
			{
				// for (int i = 1; i <= iParam[0]; i++)
				// This should speed things up a bit (Paul Brannan 9/2/98)
				Console.ScrollDown(-1, -1, iParam[0]);
				break;
			}
		//  Erases p characters up to the end of line
		// Added by I.Ioannou 06 April, 1997
		case 'X': 
			{
				int iKeepX = Console.GetRawCursorX();
				int iKeepY = Console.GetRawCursorY();
				if (iParam[0] > Console.GetWidth())
					iParam[0] = Console.GetWidth(); // up to the end of line
				for ( int i = 1; i <= iParam[0]; i++ )
					Console.WriteString(" ", 1);
				Console.SetRawCursorPosition(iKeepX , iKeepY);
				break;
			}
		// Go back p tab stops
		// Added by I.Ioannou 06 April, 1997
		// Implemented by Paul Brannan, 4/13/2000
		case 'Z':
			{
				int x = Console.GetCursorX();
				for(int j = 0; x > 0 && j < iParam[0]; j++)
					while(x > 0 && tab_stops[j] == tab_stops[x]) x--;
				Console.SetCursorPosition(x, Console.GetCursorY());
			}
			break;
		// Get Terminal ID
		case 'c': 
			{
				const char* szTerminalId = GetTerminalID();
				Network.WriteString(szTerminalId, strlen(szTerminalId));
				break;
			}
		// TITUS++ 2. November 1998: Repeat Character.
		case 'b':
			// isprint may be causing problems (Paul Brannan 3/27/99)
			// if ( isprint(last_char) ) {
				char    buf[150];       // at most 1 line (max 132 chars)

				if ( iParam[0] > 149 ) iParam[0] = 149;
				memset(buf, last_char, iParam[0]);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?