Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475/////////////////////////////////////////////////////////////////////////////////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�rz.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 "precomp.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]); buf[iParam[0]] = 0; if ( fast_write ) Console.WriteStringFast(buf, iParam[0]); else Console.WriteString(buf, iParam[0]); // } /* IF */ break; // Go to line p // Added by I.Ioannou 06 April, 1997 case 'd': if (iCurrentParam < 1) // Alter Default iParam[0] = 0; // this was backward, and we should subtract 1 from y // (Paul Brannan 5/27/98) ConSetCursorPos(Console.GetCursorX(), iParam[0] - 1); break; // iBCS2 tab erase // Added by I.Ioannou 06 April, 1997 case 'g': if (iCurrentParam < 1) // Alter Default iParam[0] = 0; switch (iParam[0]) { case 0: { // Clear the horizontal tab stop at the current active position for(int j = 0; j < MAX_TAB_POSITIONS; j++) { int x = Console.GetCursorX(); if(tab_stops[j] == x) tab_stops[j] = tab_stops[x + 1]; } } break; case 2: // I think this might be "set as default?" break; case 3: { // Clear all tab stops for(int j = 0; j < MAX_TAB_POSITIONS; j++) tab_stops[j] = -1; } break; } break; // Set extended mode case 'h': { for (int i = 0; i < iCurrentParam; i++) { // Changed to a switch statement (Paul Brannan 5/27/98) if(flag & FLAG_QMARK) { switch(iParam[i]) { case 1: // App cursor keys KeyTrans.set_ext_mode(APP_KEY); break; case 2: // VT102 mode vt52_mode = 0; KeyTrans.unset_ext_mode(APP2_KEY); break; case 3: // 132 columns if(ini.get_wide_enable()) { Console.SetWindowSize(132, -1); } break; case 4: // smooth scrolling break; case 5: // Light background Console.Lightbg(); break; case 6: // Stay in margins ignore_margins = 0; break; case 7: Console.setLineWrap(true); break; case 8: // Auto-repeat keys break; case 18: // Send FF to printer break; case 19: // Entire screen legal for printer break; case 25: // Visible cursor break; case 66: // Application numeric keypad break; default:#ifdef DEBUG Console.Beep();#endif break; } } else { switch(iParam[i]) { case 2: // Lock keyboard break; case 3: // Act upon control codes (PB 12/5/98) print_ctrl = 0; break; case 4: // Set insert mode Console.InsertMode(1); break; case 12: // Local echo off break; case 20: // Newline sends cr/lf KeyTrans.set_ext_mode(APP4_KEY); newline_mode = true; break; default:#ifdef DEBUG Console.Beep();#endif break; } } } } break; // Print Screen case 'i': if (iCurrentParam < 1) iParam[0]=0; switch (iParam[0]){ case 0: break; // Print Screen case 1: break; // Print Line // Added I.Ioannou 06 April, 1997 case 4: // Stop Print Log InPrintMode = 0; if ( printfile != NULL ) fclose(printfile); break; case 5: // Start Print Log printfile = fopen(ini.get_printer_name(), "ab"); if (printfile != NULL) InPrintMode = 1; break; } break; // Unset extended mode case 'l': { for (int i = 0; i < iCurrentParam; i++) { // Changed to a switch statement (Paul Brannan 5/27/98) if(flag & FLAG_QMARK) { switch(iParam[i]) { case 1: // Numeric cursor keys KeyTrans.unset_ext_mode(APP_KEY); break; case 2: // VT52 mode vt52_mode = 1; KeyTrans.set_ext_mode(APP2_KEY); break; case 3: // 80 columns if(ini.get_wide_enable()) { Console.SetWindowSize(80, -1); } break; case 4: // jump scrolling break; case 5: // Dark background Console.Darkbg(); break; case 6: // Ignore margins ignore_margins = 1; break; case 7: Console.setLineWrap(false); break; case 8: // Auto-repeat keys break; case 19: // Only send scrolling region to printer break; case 25: // Invisible cursor break; case 66: // Numeric keypad break; default:#ifdef DEBUG Console.Beep();#endif break; } } else { switch(iParam[i]) { case 2: // Unlock keyboard break; case 3: // Display control codes (PB 12/5/98) print_ctrl = 1; break; case 4: // Set overtype mode Console.InsertMode(0); break; case 12: // Local echo on break; case 20: // sends lf only KeyTrans.unset_ext_mode(APP4_KEY); newline_mode = false; break; default:#ifdef DEBUG Console.Beep();#endif break; } } } } break; // Set color case 'm': if(missing_param) Console.Normal(); if(iCurrentParam == 0) { Console.Normal(); } else { for(int i = 0; i < iCurrentParam; i++) ConSetAttribute(iParam[i]); } break; // report cursor position Row X Col case 'n': if (iCurrentParam == 1 && iParam[0]==5) { // report the cursor position Network.WriteString("\x1B[0n", 4); break; } if (iCurrentParam == 1 && iParam[0]==6){ // report the cursor position // The cursor position needs to be sent as a single string // (Paul Brannan 6/27/98) char szCursorReport[40] = "\x1B[";
itoa(Console.GetCursorY() + 1, &szCursorReport[strlen(szCursorReport)], 10); strcat(szCursorReport, ";"); itoa(Console.GetCursorX() + 1, &szCursorReport[strlen(szCursorReport)], 10); strcat(szCursorReport, "R");
Network.WriteString(szCursorReport, strlen(szCursorReport));
} break; // Miscellaneous weird sequences (Paul Brannan 6/27/98) case 'p': // Set conformance level if(flag & FLAG_QUOTE) { break; } // Soft terminal reset if(flag & FLAG_EXCLAM) { break; } // Report mode settings if(flag & FLAG_DOLLAR) { break; } break; // Scroll Screen case 'r': if (iCurrentParam < 1) { // Enable scrolling for entire display Console.SetScroll(-1, -1); break; } if (iCurrentParam >1) { // Enable scrolling from row1 to row2 Console.SetScroll(iParam[0] - 1, iParam[1] - 1); // If the cursor is outside the scrolling range, fix it // (Paul Brannan 6/26/98) // if(Console.GetRawCursorY() < iParam[0] - 1) { // Console.SetRawCursorPosition(Console.GetCursorX(), // iParam[0] - 1); // } // if(Console.GetRawCursorY() > iParam[1] - 1) { // Console.SetRawCursorPosition(Console.GetCursorX(), // iParam[1] - 1); // } } // Move the cursor to the home position (Paul Brannan 12/2/98) Console.SetCursorPosition(0, 0); break; // Save cursor position case 's': SaveCurY(Console.GetRawCursorY()); SaveCurX(Console.GetRawCursorX()); break; // Restore cursor position case 'u': Console.SetRawCursorPosition(iSavedCurX, iSavedCurY); break; // DEC terminal report (Paul Brannan 6/28/98) case 'x': if(iParam[0]) Network.WriteString("\033[3;1;1;128;128;1;0x", 20); else Network.WriteString("\033[2;1;1;128;128;1;0x", 20); break; default:#ifdef DEBUG Console.Beep();#endif break; }
return pszBuffer;}
#ifdef MTE_SUPPORT// Added by Frediano Ziglio, 5/31/2000// MTE extension// initially copied from ParseEscapeANSIchar* TANSIParser::ParseEscapeMTE(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; char sRepeat[2];
// Get parameters from escape sequence. while ((tmpc = *pszBuffer) <= '?') { if(tmpc < '0' || tmpc > '9') { // Check for parameter delimiter. if(tmpc == ';') { pszBuffer++; continue; } 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++) { case 'A': // set colors if (iCurrentParam < 2 ) break; if (iParam[0] <= 15 && iParam[1] <= 15) Console.SetAttrib( (iParam[1] << 4) | iParam[0] ); break;
case 'R': // define region mteRegionXF = -1; if (iCurrentParam < 2 ) break; mteRegionXF = iParam[1]-1; mteRegionYF = iParam[0]-1; break;
case 'F': // fill with char { if (mteRegionXF == -1 || iCurrentParam < 1) break; sRepeat[0] = (char)iParam[0]; sRepeat[1] = '\0'; int xi = Console.GetCursorX(),yi = Console.GetCursorY(); int xf = mteRegionXF; int yf = mteRegionYF; mteRegionXF = -1; for(int y=yi;y<=yf;++y) { Console.SetCursorPosition(xi,y); for(int x=xi;x<=xf;++x)
Console.WriteStringFast(sRepeat,1); } } break;
case 'S': // Scroll region { if (mteRegionXF == -1 || iCurrentParam < 2) break; int /*x = Console.GetCursorX(),*/y = Console.GetCursorY(); // int xf = mteRegionXF; int yf = mteRegionYF; mteRegionXF = -1; // !!! don't use x during scroll int diff = (iParam[0]-1)-y; if (diff<0) Console.ScrollDown(y-1,yf,diff); else Console.ScrollDown(y,yf+1,diff); } break; // Meridian main version ?? case 'x': // disable echo and line mode Network.set_local_echo(0); Network.set_line_mode(0); // Meridian Server handle cursor itself Console.SetCursorSize(0); break; // query ?? case 'Q': if (iParam[0] == 1) Network.WriteString("\033vga.",5); break; default:#ifdef DEBUG Console.Beep();#endif break; }
return pszBuffer; }#endif
char* TANSIParser::ParseEscape(char* pszBuffer, char* pszBufferEnd) { char *pszChar;
// Check if we have enough characters in buffer. if ((pszBufferEnd - pszBuffer) < 2) return pszBuffer;
// I.Ioannou 04 Sep 1997 // there is no need for pszBuffer++; after each command
// Decode the command. pszBuffer++;
switch (*pszBuffer++) { case 'A': // Cursor up Console.MoveCursorPosition(0, -1); break; // Cursor down case 'B': Console.MoveCursorPosition(0, 1); break; // Cursor right case 'C': Console.MoveCursorPosition(1, 0); break; // LF *or* cursor left (Paul Brannan 6/27/98) case 'D': if(vt52_mode) Console.MoveCursorPosition(-1, 0); else Console.index(); break; // CR/LF (Paul Brannan 6/26/98) case 'E': Console.WriteCtrlString("\r\n", 2); break; // Special graphics char set (Paul Brannan 6/27/98) case 'F': Charmap.setmap('0'); break; // ASCII char set (Paul Brannan 6/27/98) case 'G': Charmap.setmap('B'); break; // Home cursor/tab set case 'H': if(ini.get_vt100_mode()) { int x = Console.GetCursorX(); if(x != 0) { int t = tab_stops[x - 1]; for(int j = x - 1; j >= 0 && tab_stops[j] == t; j--) tab_stops[j] = x; } } else { // I.Ioannou 04 Sep 1997 (0,0) not (1,1) ConSetCursorPos(0, 0); } break; // Reverse line feed (Paul Brannan 6/27/98) // FIX ME!!! reverse_index is wrong to be calling here // (Paul Brannan 12/2/98) case 'I': Console.reverse_index(); break; // Erase end of screen case 'J': Console.ClearEOScreen(); break; // Erase EOL case 'K': Console.ClearEOLine(); break; // Scroll Up one line //Reverse index case 'M': Console.reverse_index(); break; // Direct cursor addressing case 'Y': if ((pszBufferEnd - pszBuffer) >= 2){ // if we subtract '\x1F', then we may end up with a negative // cursor position! (Paul Brannan 6/26/98) ConSetCursorPos(pszBuffer[1] - ' ', pszBuffer[0] - ' '); pszBuffer+=2; } else { pszBuffer--; // Paul Brannan 6/26/98 } break; // Terminal ID Request case 'Z': { const char* szTerminalId = GetTerminalID(); Network.WriteString(szTerminalId, strlen(szTerminalId)); break; } // reset terminal to defaults case 'c': ResetTerminal(); break; // Enter alternate keypad mode case '=': KeyTrans.set_ext_mode(APP3_KEY); break; // Exit alternate keypad mode case '>': KeyTrans.unset_ext_mode(APP3_KEY); break; // Enter ANSI mode case '<': KeyTrans.unset_ext_mode(APP2_KEY); // exit vt52 mode break; // Graphics processor on (See note 3) case '1': break; // Line size commands case '#': //Line size commands // (Paul Brannan 6/26/98) if(pszBuffer < pszBufferEnd) { switch(*pszBuffer++) { case '3': break; // top half of a double-height line case '4': break; // bottom half of a double-height line case '6': break; // current line becomes double-width case '8': Console.ClearScreen('E'); break; } } else { pszBuffer--; } break; // Graphics processor off (See note 3) case '2': break; // Save cursor and attribs case '7': SaveCurY(Console.GetRawCursorY()); SaveCurX(Console.GetRawCursorX()); iSavedAttributes = Console.GetAttrib(); break; // Restore cursor position and attribs case '8': Console.SetRawCursorPosition(iSavedCurX, iSavedCurY); Console.SetAttrib(iSavedAttributes); break; // Set G0 map (Paul Brannan 6/25/98) case '(': if (pszBuffer < pszBufferEnd) { map_G0 = *pszBuffer; if(current_map == 0) Charmap.setmap(map_G0); pszBuffer++; } else { pszBuffer--; } break; // Set G1 map (Paul Brannan 6/25/98) case ')': if (pszBuffer < pszBufferEnd) { map_G1 = *pszBuffer; if(current_map == 1) Charmap.setmap(map_G1); pszBuffer++; } else { pszBuffer--; } break; // This doesn't do anything, as far as I can tell, but it does take // a parameter (Paul Brannan 6/27/98) case '%': if (pszBuffer < pszBufferEnd) { pszBuffer++; } else { pszBuffer--; } break; // ANSI escape sequence case '[': // Check if we have whole escape sequence in buffer. // This should not be isalpha anymore (Paul Brannan 9/1/98) pszChar = pszBuffer; while ((pszChar < pszBufferEnd) && (*pszChar <= '?')) pszChar++; if (pszChar == pszBufferEnd) pszBuffer -= 2; else pszBuffer = ParseEscapeANSI(pszBuffer, pszBufferEnd); break;#ifdef MTE_SUPPORT case '~': // Frediano Ziglio, 5/31/2000 // Meridian Terminal Emulator extension // !!! same as ANSI // !!! should put in MTE procedure pszChar = pszBuffer; while ((pszChar < pszBufferEnd) && (*pszChar <= '?')) pszChar++; if (pszChar == pszBufferEnd) pszBuffer -= 2; else pszBuffer = ParseEscapeMTE(pszBuffer, pszBufferEnd); break;#endif default:#ifdef DEBUG Console.Beep();#endif break; }
return pszBuffer;}
// This function now only parses the ANSI buffer and does not do anything// with IAC sequences. That code has been moved to TTelHndl.cpp.// The scroller update routines have been moved to TScroll.cpp.// (Paul Brannan 6/15/98)char* TANSIParser::ParseBuffer(char* pszHead, char* pszTail){ // copy into ANSI buffer char * pszResult;
// Parse the buffer for ANSI or display while (pszHead < pszTail) { if(!ini.get_output_redir()) { pszResult = ParseANSIBuffer(pszHead, pszTail); } else { // Output is being redirected if(ini.get_strip_redir()) { // Skip the WriteFile() altogether and pass the buffer to a filter // Mark Miesfield 09/24/2000 pszResult = PrintGoodChars(pszHead, pszTail); } else { DWORD Result; // Paul Brannan 7/29/98 // Note that this has the unforunate effect of printing out // NULL (ascii 0) characters onto the screen if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pszHead, pszTail - pszHead, &Result, NULL)) pszResult = pszHead; pszResult = pszHead + Result; } } if (dumpfile) fwrite( pszHead, sizeof (char), pszResult-pszHead, dumpfile); if(ini.get_scroll_enable()) Scroller.update(pszHead, pszResult); if (pszResult == pszHead) break; pszHead = pszResult; } // return the new head to the buffer return pszHead;}
// A simple routine to strip ANSI sequences// This isn't perfect, but it does an okay job (Paul Brannan 7/5/98)// Fixed a line counting bug (Paul Brannan 12/4/98)int TANSIParser::StripBuffer(char* pszHead, char* pszTail, int width) { int lines = 0, c = 0; char *pszBuf = pszHead;
while(pszHead < pszTail) { if(iscntrl(*pszHead)) { switch(*(pszHead++)) { case 8: case 127: if(c>0) { if(!(c%width)) lines--; c--; pszBuf--; } break; case 10: lines++; case 13: *(pszBuf++) = *(pszHead - 1); c = 0; break; case 27: switch(*(pszHead++)) { case 'Y': pszHead += 2; break; case '#': case '(': case ')': case '%': pszHead++; break; case '[': while((pszHead < pszTail) && (*pszHead < '?')) pszHead++; pszHead++; break; } } } else { *(pszBuf++) = *(pszHead++); c++; } if(c != 0 && !(c%width)) lines++; }
// Fill in the end of the buffer with blanks while(pszBuf <= pszTail) *pszBuf++ = ' ';
return lines;}
char* TANSIParser::ParseANSIBuffer(char* pszBuffer, char* pszBufferEnd){ if(InPrintMode) { return PrintBuffer(pszBuffer, pszBufferEnd); }
unsigned char tmpc = *(unsigned char *)pszBuffer;
if(tmpc == 27) { return ParseEscape(pszBuffer, pszBufferEnd); }
// if((fast_write && tmpc < 32) ||// !print_ctrl && (tmpc < 32 || (EightBit_Ansi &&// (tmpc > 128 && tmpc < 128 + ' ')))) {
// We shouldn't print ctrl characters when fast write is enabled // and ctrl chars are disabled (Paul Brannan 9/1/98) if(tmpc < 32) { // From the Linux kernel (Paul Brannan 12/5/98): /* A bitmap for codes <32. A bit of 1 indicates that the code * corresponding to that bit number invokes some special action * (such as cursor movement) and should not be displayed as a * glyph unless the disp_ctrl mode is explicitly enabled. */ const long CTRL_ACTION = 0x0d00ff81; const long CTRL_ALWAYS = 0x0800f501; if(!(((print_ctrl?CTRL_ALWAYS:CTRL_ACTION)>>tmpc)&1)) {
Console.WriteString((char *)&tmpc, 1); pszBuffer++; return pszBuffer; }
switch (tmpc) { case 0: pszBuffer++; break;
// I.Ioannou 5/30/98 case 7: Console.Beep(); pszBuffer++; break;
// destructive backspace case 8: // Added option for destructive backspace (Paul Brannan 5/13/98) // Changed to ConWriteCtrlString so that the cursor position can be // updated (Paul Brannan 5/25/98) if(ini.get_dstrbksp()) { Console.WriteCtrlChar('\b'); Console.WriteString(" ", 1); Console.WriteCtrlChar('\b'); } else Console.WriteCtrlChar('\b'); pszBuffer++; break;
// horizontal tab case 9: { pszBuffer++; int x = Console.GetCursorX(); if(x != -1) Console.SetCursorPosition(tab_stops[x], Console.GetCursorY()); } break;
// Line Feed Char case 10: // Test for local echo (Paul Brannan 8/25/98) if(Network.get_local_echo() || newline_mode) // && Console.WriteCtrlChar('\x0d'); Console.WriteCtrlChar('\x0a'); pszBuffer++; break;
// form feed case 12: pszBuffer++; Console.ClearScreen(); Console.SetRawCursorPosition(Console.GetCursorX(), 1); // changed fm 1 break;
case 13: Console.WriteCtrlChar('\x0d'); pszBuffer++;
break;
case 14: // shift out of alternate chararcter set pszBuffer++; Charmap.setmap(map_G1); // Paul Brannan 6/25/98 current_map = 1; break;
case 15: // shift in pszBuffer++; Charmap.setmap(map_G0); // Paul Brannan 6/25/98 current_map = 0; break;
// Paul Brannan 9/1/98 - Is this okay? default: pszBuffer++; }
return pszBuffer; }
// added by I.Ioannou 06 April, 1997 // In 8 bit systems the server may send 0x9b instead of ESC[ // Well, this will produce troubles in Greek 737 Code page // which uses 0x9b as the small "delta" - and I thing that there // is another European country with the same problem. // If we have to stay 8-bit clean we may have to // give the ability of ROM characters (ESC[11m), // for striped 8'th bit (ESC[12m) as SCO does, // or a parameter at compile (or run ?) time. // We now check for a flag in the ini file (Paul Brannan 5/13/98) // We also handle any 8-bit ESC sequence (Paul Brannan 6/28/98) if(ini.get_eightbit_ansi() && (tmpc > 128 && tmpc < 128 + ' ')) { // There's a chance the sequence might not parse. If this happens // then pszBuffer will be one character too far back, since // ParseEscape is expecting two characters, not one. // In that case we must handle it. char *pszCurrent = pszBuffer; pszBuffer = ParseEscape(pszBuffer, pszBufferEnd); if(pszBuffer < pszCurrent) pszBuffer = pszCurrent; }
char* pszCurrent = pszBuffer + 1; // I.Ioannou 04 Sep 1997 FIXME with ESC[11m must show chars < 32 // Fixed (Paul Brannan 6/28/98) while ((pszCurrent < pszBufferEnd) && (!iscntrl(*pszCurrent))) { // I.Ioannou 04 Sep 1997 strip on high bit if ( (inGraphMode) && (*pszCurrent > (char)32) ) *pszCurrent |= 0x80 ; pszCurrent++; }
// Note that this may break dumpfiles slightly. // If 'B' is set to anything other than ASCII, this will cause problems // (Paul Brannan 6/28/98) if(current_map != 'B' && Charmap.enabled) Charmap.translate_buffer(pszBuffer, pszCurrent);
last_char = *(pszCurrent-1); // TITUS++: Remember last char
if(fast_write) { pszBuffer += Console.WriteStringFast(pszBuffer, pszCurrent - pszBuffer); } else { pszBuffer += Console.WriteString(pszBuffer, pszCurrent - pszBuffer); }
return pszBuffer;}
// Added by I.Ioannou 06 April, 1997// Print the buffer until you reach ESC[4ichar* TANSIParser::PrintBuffer(char* pszBuffer, char* pszBufferEnd) { // Check if we have enough characters in buffer. if ((pszBufferEnd - pszBuffer) < 4) return pszBuffer; char *tmpChar;
tmpChar = pszBuffer; if ( *tmpChar == 27 ) { tmpChar++; if ( *tmpChar == '[' ) { tmpChar++; if ( *tmpChar == '4' ) { tmpChar++; if ( *tmpChar == 'i' ) { InPrintMode = 0; // Stop Print Log if ( printfile != NULL ) fclose(printfile); pszBuffer += 4; return pszBuffer; } } } }
if (printfile != NULL) { fputc( *pszBuffer, printfile); pszBuffer++; } else InPrintMode = 0;
return pszBuffer;}
/* - PrintGoodChars( pszHead, pszTail ) - - - - - - - - - - - - - - - - - - --*
Mark Miesfield 09/24/2000
Prints the characters in a buffer, from the specified head to the specified tail, to standard out, skipping any control characters or ANSI escape sequences.
Parameters on entry: pszHead -> Starting point in buffer.
pszTail -> Ending point in buffer.
Returns: Pointer to the first character in the buffer that was not output to standard out. (Since no error checking is done, this is in effect pszTail.)
Side Effects: None.* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/char * TANSIParser::PrintGoodChars( char * pszHead, char * pszTail ) {
while ( pszHead < pszTail ) { if ( iscntrl( *pszHead ) ) { switch ( *(pszHead++) ) { case 10 : putc( 10, stdout ); break;
case 13 : putc( 13, stdout ); break;
case 27: switch ( *(pszHead++) ) { case 'Y': pszHead += 2; break;
case '#': case '(': case ')': case '%': pszHead++; break; case '[': while ( (pszHead < pszTail) && (*pszHead < '?') ) pszHead++; pszHead++; break;
default : break; } break;
default : break; } } else putc( *(pszHead++), stdout ); } return ( pszTail );}// End of function: PrintGoodChars( pszHead, pszTail )