ansiprsr.cpp
上传用户:tigerk9
上传日期:2020-03-10
资源大小:237k
文件大小:40k
源码类别:

Telnet客户端

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //Telnet Win32 : an ANSI telnet client.
  3. //Copyright (C) 1998-2000 Paul Brannan
  4. //Copyright (C) 1998 I.Ioannou
  5. //Copyright (C) 1997 Brad Johnson
  6. //
  7. //This program is free software; you can redistribute it and/or
  8. //modify it under the terms of the GNU General Public License
  9. //as published by the Free Software Foundation; either version 2
  10. //of the License, or (at your option) any later version.
  11. //
  12. //This program is distributed in the hope that it will be useful,
  13. //but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. //GNU General Public License for more details.
  16. //
  17. //You should have received a copy of the GNU General Public License
  18. //along with this program; if not, write to the Free Software
  19. //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. //
  21. //I.Ioannou
  22. //roryt@hol.gr
  23. //
  24. ///////////////////////////////////////////////////////////////////////////
  25. ///////////////////////////////////////////////////////////////////////////////
  26. //
  27. // Module: ansiprsr.cpp
  28. //
  29. // Contents: ANSI parser base class
  30. //
  31. // Product: telnet
  32. //
  33. // Revisions: August 30, 1998 Paul Brannan <pbranna@clemson.edu>
  34. //            July 29, 1998 pbranna@clemson.edu
  35. //            June 15, 1998 pbranna@clemson.edu
  36. //            May 19, 1998  pbranna@clemson.edu
  37. //            24 Dec, 1997  Andrey.V.Smilianets
  38. //            05. Sep.1997  roryt@hol.gr (I.Ioannou)
  39. //            11.May.1997   roryt@hol.gr (I.Ioannou)
  40. //            6.April.1997  roryt@hol.gr (I.Ioannou)
  41. //            5.April.1997  jbj@nounname.com
  42. //            30.M剅z.1997 Titus_Boxberg@public.uni-hamburg.de
  43. //       14.Sept.1996  jbj@nounname.com
  44. //            Version 2.0
  45. //
  46. //            13.Jul.1995 igor.milavec@uni-lj.si
  47. //   Original code
  48. //
  49. ///////////////////////////////////////////////////////////////////////////////
  50. #include <windows.h>
  51. #include <string.h>
  52. #include "ansiprsr.h"
  53. // The constructor now takes different arguments and initializes different
  54. // variables (Paul Brannan 6/15/98)
  55. TANSIParser::TANSIParser(TConsole &RefConsole, KeyTranslator &RefKeyTrans,
  56.  TScroller &RefScroller, TNetwork &RefNetwork,
  57.  TCharmap &RefCharmap):
  58. TParser(RefConsole, RefKeyTrans, RefScroller, RefNetwork, RefCharmap) {
  59. Init();
  60. iSavedAttributes = (unsigned char) 7;
  61. // must also check to make sure the string is non-NULL
  62. // (Paul Brannan 5/8/98)
  63. if ((ini.get_dumpfile() != NULL) && (*ini.get_dumpfile() != '')){
  64. dumpfile = fopen(ini.get_dumpfile(), "wb");
  65. }else {
  66. dumpfile = NULL;
  67. }
  68. InPrintMode = 0;
  69. printfile = NULL;
  70. fast_write = ini.get_fast_write(); // Paul Brannan 6/28/98
  71. Scroller.init(&StripBuffer);
  72. }
  73. TANSIParser::~TANSIParser(){
  74. if (dumpfile) fclose (dumpfile);
  75. // Added I.Ioannou 06 April, 1997
  76. if (printfile != NULL) fclose (printfile);
  77. }
  78. // Created Init() function to initialize the parser but not clear the screen
  79. // (Paul Brannan 9/23/98)
  80. void TANSIParser::Init() {
  81. // Paul Brannan 6/25/98
  82. map_G0 = 'B'; map_G1 = 'B';
  83. Charmap.setmap(map_G0);
  84. current_map = 'B';
  85. ignore_margins = 0;
  86. vt52_mode = 0;
  87. print_ctrl = 0;
  88. newline_mode = false;
  89. KeyTrans.clear_ext_mode();
  90. iSavedCurY = 0; // Reset Variables
  91. iSavedCurX = 0;
  92. inGraphMode = 0;
  93. Console.SetScroll(-1, -1);
  94. Console.Normal(); // Reset Attributes
  95. // Set tabs stops
  96. resetTabStops();
  97. }
  98. void TANSIParser::ResetTerminal() {
  99. Init();
  100. Console.ClearScreen(); // Clear Screen
  101. Console.SetRawCursorPosition(0,0); // Home Cursor
  102. }
  103. void TANSIParser::SaveCurY(int iY){
  104. iSavedCurY=iY;
  105. }
  106. void TANSIParser::SaveCurX(int iX){
  107. iSavedCurX=iX;
  108. }
  109. void TANSIParser::resetTabStops() {
  110. for(int j = 0; j < MAX_TAB_POSITIONS; j++) {
  111. tab_stops[j] = 8 + j - (j%8);
  112. }
  113. }
  114. void TANSIParser::ConSetAttribute(unsigned char TextAttrib){
  115. // Paul Brannan 5/8/98
  116. // Made this go a little bit faster by changing from switch{} to an array
  117. // for the colors
  118. if(TextAttrib >= 30) {
  119. if(TextAttrib <= 37) {
  120. Console.SetForeground(ANSIColors[TextAttrib-30]);
  121. return;
  122. } else if((TextAttrib >= 40) && (TextAttrib <= 47)) {
  123. Console.SetBackground(ANSIColors[TextAttrib-40]);
  124. return;
  125. }
  126. }
  127. switch (TextAttrib){
  128. // Text Attributes
  129. case 0: Console.Normal();           break; // Normal video
  130. case 1: Console.HighVideo();        break; // High video
  131. case 2: Console.LowVideo();         break; // Low video
  132. case 4: Console.UnderlineOn(); break; // Underline on (I.Ioannou)
  133. case 5: Console.BlinkOn(); break; // Blink video
  134. // Corrected by I.Ioannou 11 May, 1997
  135. case 7: Console.ReverseOn(); break; // Reverse video
  136. case 8: break; // hidden
  137. // All from 10 thru 27 are hacked from linux kernel
  138. // I.Ioannou 06 April, 1997
  139. case 10:
  140. //  I.Ioannou 04 Sep 1997 turn on/off high bit
  141. inGraphMode = 0;
  142. print_ctrl = 0;
  143. Charmap.setmap(current_map ? map_G1:map_G0); // Paul Brannan 6/25/98
  144. break; // ANSI X3.64-1979 (SCO-ish?)
  145. // Select primary font,
  146. // don't display control chars
  147. // if defined, don't set
  148. // bit 8 on output (normal)
  149. case 11:
  150. inGraphMode = 0;
  151. print_ctrl = 1;
  152. Charmap.setmap(0); // Paul Brannan 6/25/98
  153. break; // ANSI X3.64-1979 (SCO-ish?)
  154. // Select first alternate font,
  155. // let chars < 32 be displayed
  156. // as ROM chars
  157. case 12:
  158. inGraphMode = 1;
  159. print_ctrl = 1;
  160. Charmap.setmap(0); // Paul Brannan 6/25/98
  161. break; // ANSI X3.64-1979 (SCO-ish?)
  162. // Select second alternate font,
  163. // toggle high bit before
  164. // displaying as ROM char.
  165. case 21: // not really Low video
  166. case 22: Console.LowVideo(); break; // but this works good also
  167. case 24: Console.UnderlineOff(); break; // Underline off
  168. case 25: Console.BlinkOff(); break; // blink off
  169. // Corrected by I.Ioannou 11 May, 1997
  170. case 27: Console.ReverseOff(); break; //Reverse video off
  171. // Mutt needs this (Paul Brannan, Peter Jordan 12/31/98)
  172. // This is from the Linux kernel source
  173.     case 38: /* ANSI X3.64-1979 (SCO-ish?)
  174.   * Enables underscore, white foreground
  175.   * with white underscore (Linux - use
  176.   * default foreground).
  177.   */
  178. Console.UnderlineOn();
  179. Console.SetForeground(ini.get_normal_fg());
  180. break;
  181. case 39: /* ANSI X3.64-1979 (SCO-ish?)
  182.   * Disable underline option.
  183.   * Reset colour to default? It did this
  184.   * before...
  185.   */
  186. Console.UnderlineOff();
  187. Console.SetForeground(ini.get_normal_fg());
  188. break;
  189. case 49:
  190. Console.SetBackground(ini.get_normal_bg());
  191. break;
  192. }
  193. }
  194. void TANSIParser::ConSetCursorPos(int x, int y) {
  195. if(ignore_margins)
  196. Console.SetRawCursorPosition(x, y);
  197. else
  198. Console.SetCursorPosition(x, y);
  199. }
  200. char* TANSIParser::GetTerminalID()
  201. {
  202. return "33[?1;2c";
  203. }
  204. // All of the Telnet protocol stuff has been moved to TTelHndl.cpp
  205. // This is more consistent with what OO should be
  206. // (Paul Brannan 6/15/98)
  207. #ifdef __BORLANDC__
  208. // argsused doesn't work on MSVC++
  209. #pragma argsused
  210. #endif
  211. // Use this for the VT100 flags (Paul Brannan 12/2/98)
  212. #define FLAG_DOLLAR 0x0001
  213. #define FLAG_QMARK 0x0002
  214. #define FLAG_GREATER 0x0004
  215. #define FLAG_LESS 0x0008
  216. #define FLAG_EXCLAM 0x0010
  217. #define FLAG_AMPERSAND 0x0020
  218. #define FLAG_SLASH 0x0040
  219. #define FLAG_EQUAL 0x0080
  220. #define FLAG_QUOTE 0x0100
  221. #define FLAG_OTHER 0x8000
  222. char* TANSIParser::ParseEscapeANSI(char* pszBuffer, char* pszBufferEnd)
  223. {
  224. // The buffer contains something like <ESC>[pA
  225. // where p is an optional decimal number specifying the count by which the
  226. // appropriate action should take place.
  227. // The pointer pszBuffer points us to the p, <ESC> and [ are
  228. // already 'consumed'
  229. // TITUS: Simplification of the code: Assume default count of 1 in case
  230. // there are no parameters.
  231. char tmpc;
  232. const int nParam = 10; // Maximum number of parameters
  233. int iParam[nParam] = {1, 0, 0, 0, 0}; // Assume 1 Parameter, Default 1
  234. int iCurrentParam = 0;
  235. DWORD flag = 0;
  236. int missing_param = 0;
  237. // Get parameters from escape sequence.
  238. while ((tmpc = *pszBuffer) <= '?') {
  239. if(tmpc < '0' || tmpc > '9') {
  240. // Check for parameter delimiter.
  241. if(tmpc == ';') {
  242. // This is a hack (Paul Brannan 6/27/98)
  243. if(*(pszBuffer - 1) == '[') missing_param = iCurrentParam+1;
  244. pszBuffer++;
  245. continue;
  246. }
  247. // It is legal to have control characters inside ANSI sequences
  248. // (Paul Brannan 6/26/98)
  249. if(tmpc < ' ') {
  250. Console.WriteCtrlChar(tmpc);
  251. pszBuffer++;
  252. continue;
  253. }
  254. // A new way of handling flags (Paul Brannan 12/2/98)
  255. switch(tmpc) {
  256. case '$': flag |= FLAG_DOLLAR; break;
  257. case '?': flag |= FLAG_QMARK; break;
  258. case '>': flag |= FLAG_GREATER; break;
  259. case '<': flag |= FLAG_LESS; break;
  260. case '!': flag |= FLAG_EXCLAM; break;
  261. case '&': flag |= FLAG_AMPERSAND; break;
  262. case '/': flag |= FLAG_SLASH; break;
  263. case '=': flag |= FLAG_EQUAL; break;
  264. case '"': flag |= FLAG_QUOTE; break;
  265. default: flag |= FLAG_OTHER; break;
  266. }
  267. pszBuffer++;
  268. }
  269. //  Got Numerical Parameter.
  270. iParam[iCurrentParam] = strtoul(pszBuffer, &pszBuffer, 10);
  271. if (iCurrentParam < nParam)
  272. iCurrentParam++;
  273. }
  274. //~~~ TITUS: Apparently the digit is optional (look at termcap or terminfo)
  275. // So: If there is no digit, assume a count of 1
  276. switch ((unsigned char)*pszBuffer++) {
  277. // Insert Character
  278. case '@':
  279. if(iParam[0] == 0) iParam[0] = 1; // Paul Brannan 9/1/98
  280. Console.InsertCharacter(iParam[0]); break;
  281. // Move cursor up.
  282. case 'A':
  283. if(iParam[0] == 0) iParam[0] = 1;
  284. Console.MoveCursorPosition(0, -iParam[0]); break;
  285. // Move cursor down.
  286. // Added by I.Ioannou 06 April, 1997
  287. case 'B':
  288. case 'e':
  289. if(iParam[0] == 0) iParam[0] = 1;
  290. Console.MoveCursorPosition(0, iParam[0]);
  291. break;
  292. // Move cursor right.
  293. // Added by I.Ioannou 06 April, 1997
  294. case 'C':
  295. case 'a':
  296. // Handle cursor size sequences (Jose Cesar Otero Rodriquez and
  297. // Paul Brannan, 3/27/1999)
  298. if(flag & FLAG_EQUAL) {
  299. switch(iParam[0]) {
  300. case 7: Console.SetCursorSize(50); break;
  301. case 11: Console.SetCursorSize(6); break;
  302. case 32: Console.SetCursorSize(0); break;
  303. default: Console.SetCursorSize(13);
  304. }
  305. } else {
  306. if(iParam[0] == 0) iParam[0] = 1;
  307. Console.MoveCursorPosition(iParam[0], 0);
  308. break;
  309. }
  310. // Move cursor left.
  311. case 'D':
  312. if(iParam[0] == 0) iParam[0] = 1;
  313. Console.MoveCursorPosition(-iParam[0], 0);
  314. break;
  315. // Move cursor to beginning of line, p lines down.
  316. // Added by I.Ioannou 06 April, 1997
  317. case 'E': 
  318. Console.MoveCursorPosition(-Console.GetCursorX(), iParam[0]);
  319. break;
  320. // Moves active position to beginning of line, p lines up
  321. // Added by I.Ioannou 06 April, 1997
  322. // With '=' this changes the default fg color (Paul Brannan 6/27/98)
  323. case 'F':
  324. if(flag & FLAG_EQUAL)
  325. Console.setDefaultFg(iParam[0]);
  326. else
  327. Console.MoveCursorPosition(-Console.GetCursorX(), -iParam[0]);
  328. break;
  329. // Go to column p
  330. // Added by I.Ioannou 06 April, 1997
  331. // With '=' this changes the default bg color (Paul Brannan 6/27/98)
  332. case '`': 
  333. case 'G': // 'G' is from Linux kernel sources
  334. if(flag & FLAG_EQUAL) {
  335. Console.setDefaultBg(iParam[0]);
  336. } else {
  337. if (iCurrentParam < 1) // Alter Default
  338. iParam[0] = 0;
  339. // this was backward, and we should subtract 1 from x
  340. // (Paul Brannan 5/27/98)
  341. ConSetCursorPos(iParam[0] - 1, Console.GetCursorY());
  342. }
  343. break;
  344. // Set cursor position.
  345. case 'f': 
  346. case 'H':
  347. if (iCurrentParam < 2 || iParam[1] < 1)
  348. iParam[1] = 1;
  349. ConSetCursorPos(iParam[1] - 1, iParam[0] - 1);
  350. break;
  351. // Clear screen
  352. case 'J': 
  353. if ( iCurrentParam < 1 ) iParam[0] = 0; // Alter Default
  354. switch (iParam[0]) {
  355. case 0: Console.ClearEOScreen(); break;
  356. case 1: Console.ClearBOScreen(); break;
  357. case 2:
  358. Console.ClearScreen();
  359. Console.SetRawCursorPosition(0, 0);
  360. break;
  361. }
  362. break;
  363. // Clear line
  364. case 'K': 
  365. if (iCurrentParam < 1) // Alter Default
  366. iParam[0] = 0;
  367. switch (iParam[0]) {
  368. case 0: Console.ClearEOLine(); break;
  369. case 1: Console.ClearBOLine(); break;
  370. case 2: Console.ClearLine(); break;
  371. }
  372. break;
  373. //  Insert p new, blank lines.
  374. // Added by I.Ioannou 06 April, 1997
  375. case 'L': 
  376. {
  377. // for (int i = 1; i <= iParam[0]; i++)
  378. // This should speed things up a bit (Paul Brannan 9/2/98)
  379. Console.ScrollDown(Console.GetRawCursorY(), -1, iParam[0]);
  380. break;
  381. }
  382. //  Delete p lines.
  383. // Added by I.Ioannou 06 April, 1997
  384. case 'M': 
  385. {
  386. for (int i = 1; i <= iParam[0]; i++)
  387. // This should speed things up a bit (Paul Brannan 9/2/98)
  388. Console.ScrollDown(Console.GetRawCursorY(), -1, -1);
  389. break;
  390. }
  391. // DELETE CHAR
  392. case 'P': 
  393. Console.DeleteCharacter(iParam[0]);
  394. break;
  395. // Scrolls screen up (down? -- PB) p lines,
  396. // Added by I.Ioannou 06 April, 1997
  397. // ANSI X3.64-1979 references this but I didn't
  398. // found it in any telnet implementation
  399. // note 05 Oct 97  : but SCO terminfo uses them, so uncomment them !!
  400. case 'S': 
  401. {
  402. //for (int i = 1; i <= iParam[0]; i++)
  403. // This should speed things up a bit (Paul Brannan 9/2/98)
  404. Console.ScrollDown(-1, -1, -iParam[0]);
  405. break;
  406. }
  407. // Scrolls screen up p lines,
  408. // Added by I.Ioannou 06 April, 1997
  409. // ANSI X3.64-1979 references this but I didn't
  410. // found it in any telnet implementation
  411. // note 05 Oct 97  : but SCO terminfo uses them, so uncomment them !!
  412. case 'T': 
  413. {
  414. // for (int i = 1; i <= iParam[0]; i++)
  415. // This should speed things up a bit (Paul Brannan 9/2/98)
  416. Console.ScrollDown(-1, -1, iParam[0]);
  417. break;
  418. }
  419. //  Erases p characters up to the end of line
  420. // Added by I.Ioannou 06 April, 1997
  421. case 'X': 
  422. {
  423. int iKeepX = Console.GetRawCursorX();
  424. int iKeepY = Console.GetRawCursorY();
  425. if (iParam[0] > Console.GetWidth())
  426. iParam[0] = Console.GetWidth(); // up to the end of line
  427. for ( int i = 1; i <= iParam[0]; i++ )
  428. Console.WriteString(" ", 1);
  429. Console.SetRawCursorPosition(iKeepX , iKeepY);
  430. break;
  431. }
  432. // Go back p tab stops
  433. // Added by I.Ioannou 06 April, 1997
  434. // Implemented by Paul Brannan, 4/13/2000
  435. case 'Z':
  436. {
  437. int x = Console.GetCursorX();
  438. for(int j = 0; x > 0 && j < iParam[0]; j++)
  439. while(x > 0 && tab_stops[j] == tab_stops[x]) x--;
  440. Console.SetCursorPosition(x, Console.GetCursorY());
  441. }
  442. break;
  443. // Get Terminal ID
  444. case 'c': 
  445. {
  446. char* szTerminalId = GetTerminalID();
  447. Network.WriteString(szTerminalId, strlen(szTerminalId));
  448. break;
  449. }
  450. // TITUS++ 2. November 1998: Repeat Character.
  451. case 'b':
  452. // isprint may be causing problems (Paul Brannan 3/27/99)
  453. // if ( isprint(last_char) ) {
  454. char    buf[150];       // at most 1 line (max 132 chars)
  455. if ( iParam[0] > 149 ) iParam[0] = 149;
  456. memset(buf, last_char, iParam[0]);
  457. buf[iParam[0]] = 0;
  458. if ( fast_write )
  459. Console.WriteStringFast(buf, iParam[0]);
  460. else
  461. Console.WriteString(buf, iParam[0]);
  462. // } /* IF */
  463. break;
  464. // Go to line p
  465. // Added by I.Ioannou 06 April, 1997
  466. case 'd': 
  467. if (iCurrentParam < 1) // Alter Default
  468. iParam[0] = 0;
  469. // this was backward, and we should subtract 1 from y
  470. // (Paul Brannan 5/27/98)
  471. ConSetCursorPos(Console.GetCursorX(), iParam[0] - 1);
  472. break;
  473. // iBCS2 tab erase
  474. // Added by I.Ioannou 06 April, 1997
  475. case 'g': 
  476. if (iCurrentParam < 1) // Alter Default
  477. iParam[0] = 0;
  478. switch (iParam[0]) {
  479. case 0:
  480. {
  481. // Clear the horizontal tab stop at the current active position
  482. for(int j = 0; j < MAX_TAB_POSITIONS; j++) {
  483. int x = Console.GetCursorX();
  484. if(tab_stops[j] == x) tab_stops[j] = tab_stops[x + 1];
  485. }
  486. }
  487. break;
  488. case 2:
  489. // I think this might be "set as default?"
  490. break;
  491. case 3:
  492. {
  493. // Clear all tab stops
  494. for(int j = 0; j < MAX_TAB_POSITIONS; j++)
  495. tab_stops[j] = -1;
  496. }
  497. break;
  498. }
  499. break;
  500. // Set extended mode
  501. case 'h': 
  502. {
  503. for (int i = 0; i < iCurrentParam; i++) {
  504. // Changed to a switch statement (Paul Brannan 5/27/98)
  505. if(flag & FLAG_QMARK) {
  506. switch(iParam[i]) {
  507. case 1: // App cursor keys
  508. KeyTrans.set_ext_mode(APP_KEY);
  509. break;
  510. case 2: // VT102 mode
  511. vt52_mode = 0;
  512. KeyTrans.unset_ext_mode(APP2_KEY);
  513. break;
  514. case 3: // 132 columns
  515. if(ini.get_wide_enable()) {
  516. Console.SetWindowSize(132, -1);
  517. }
  518. break;
  519. case 4: // smooth scrolling
  520. break;
  521. case 5: // Light background
  522. Console.Lightbg();
  523. break;
  524. case 6: // Stay in margins
  525. ignore_margins = 0;
  526. break;
  527. case 7:
  528. Console.setLineWrap(true);
  529. break;
  530. case 8: // Auto-repeat keys
  531. break;
  532. case 18: // Send FF to printer
  533. break;
  534. case 19: // Entire screen legal for printer
  535. break;
  536. case 25: // Visible cursor
  537. break;
  538. case 66: // Application numeric keypad
  539. break;
  540. default:
  541. #ifdef DEBUG
  542. Console.Beep();
  543. #endif
  544. break;
  545. }
  546. } else {
  547. switch(iParam[i]) {
  548. case 2: // Lock keyboard
  549. break;
  550. case 3: // Act upon control codes (PB 12/5/98)
  551. print_ctrl = 0;
  552. break;
  553. case 4: // Set insert mode
  554. Console.InsertMode(1);
  555. break;
  556. case 12: // Local echo off
  557. break;
  558. case 20: // Newline sends cr/lf
  559. KeyTrans.set_ext_mode(APP4_KEY);
  560. newline_mode = true;
  561. break;
  562. default:
  563. #ifdef DEBUG
  564. Console.Beep();
  565. #endif
  566. break;
  567. }
  568. }
  569. }
  570. }
  571. break;
  572. // Print Screen
  573. case 'i': 
  574. if (iCurrentParam < 1)
  575. iParam[0]=0;
  576. switch (iParam[0]){
  577. case 0: break; // Print Screen
  578. case 1: break; // Print Line
  579. // Added I.Ioannou 06 April, 1997
  580. case 4:
  581. // Stop Print Log
  582. InPrintMode = 0;
  583. if ( printfile != NULL )
  584. fclose(printfile);
  585. break;
  586. case 5:
  587. // Start Print Log
  588. printfile = fopen(ini.get_printer_name(), "ab");
  589. if (printfile != NULL) InPrintMode = 1;
  590. break;
  591. }
  592. break;
  593. // Unset extended mode
  594. case 'l': 
  595. {
  596. for (int i = 0; i < iCurrentParam; i++) {
  597. // Changed to a switch statement (Paul Brannan 5/27/98)
  598. if(flag & FLAG_QMARK) {
  599. switch(iParam[i]) {
  600. case 1: // Numeric cursor keys
  601. KeyTrans.unset_ext_mode(APP_KEY);
  602. break;
  603. case 2: // VT52 mode
  604. vt52_mode = 1;
  605. KeyTrans.set_ext_mode(APP2_KEY);
  606. break;
  607. case 3: // 80 columns
  608. if(ini.get_wide_enable()) {
  609. Console.SetWindowSize(80, -1);
  610. }
  611. break;
  612. case 4: // jump scrolling
  613. break;
  614. case 5: // Dark background
  615. Console.Darkbg();
  616. break;
  617. case 6: // Ignore margins
  618. ignore_margins = 1;
  619. break;
  620. case 7:
  621. Console.setLineWrap(false);
  622. break;
  623. case 8: // Auto-repeat keys
  624. break;
  625. case 19: // Only send scrolling region to printer
  626. break;
  627. case 25: // Invisible cursor
  628. break;
  629. case 66: // Numeric keypad
  630. break;
  631. default:
  632. #ifdef DEBUG
  633. Console.Beep();
  634. #endif
  635. break;
  636. }
  637. } else {
  638. switch(iParam[i]) {
  639. case 2: // Unlock keyboard
  640. break;
  641. case 3: // Display control codes (PB 12/5/98)
  642. print_ctrl = 1;
  643. break;
  644. case 4: // Set overtype mode
  645. Console.InsertMode(0);
  646. break;
  647. case 12: // Local echo on
  648. break;
  649. case 20: // sends lf only
  650. KeyTrans.unset_ext_mode(APP4_KEY);
  651. newline_mode = false;
  652. break;
  653. default:
  654. #ifdef DEBUG
  655. Console.Beep();
  656. #endif
  657. break;
  658. }
  659. }
  660. }
  661. }
  662. break;
  663. // Set color
  664. case 'm':
  665. if(missing_param) Console.Normal();
  666. if(iCurrentParam == 0) {
  667. Console.Normal();
  668. } else {
  669. for(int i = 0; i < iCurrentParam; i++)
  670. ConSetAttribute(iParam[i]);
  671. }
  672. break;
  673. // report cursor position Row X Col
  674. case 'n': 
  675. if (iCurrentParam == 1 && iParam[0]==5) {
  676. // report the cursor position
  677. Network.WriteString("x1B[0n", 6);
  678. break;
  679. }
  680. if (iCurrentParam == 1 && iParam[0]==6){
  681. // report the cursor position
  682. // The cursor position needs to be sent as a single string
  683. // (Paul Brannan 6/27/98)
  684. char szCursorReport[40] = "x1B[";
  685. itoa(Console.GetCursorY() + 1,
  686. &szCursorReport[strlen(szCursorReport)], 10);
  687. strcat(szCursorReport, ";");
  688. itoa(Console.GetCursorX() + 1,
  689. &szCursorReport[strlen(szCursorReport)], 10);
  690. strcat(szCursorReport, "R");
  691. Network.WriteString(szCursorReport, strlen(szCursorReport));
  692. }
  693. break;
  694. // Miscellaneous weird sequences (Paul Brannan 6/27/98)
  695. case 'p':
  696. // Set conformance level
  697. if(flag & FLAG_QUOTE) {
  698. break;
  699. }
  700. // Soft terminal reset
  701. if(flag & FLAG_EXCLAM) {
  702. break;
  703. }
  704. // Report mode settings
  705. if(flag & FLAG_DOLLAR) {
  706. break;
  707. }
  708. break;
  709. // Scroll Screen
  710. case 'r': 
  711. if (iCurrentParam < 1) {
  712. // Enable scrolling for entire display
  713. Console.SetScroll(-1, -1);
  714. break;
  715. }
  716. if (iCurrentParam >1) {
  717. // Enable scrolling from row1 to row2
  718. Console.SetScroll(iParam[0] - 1, iParam[1] - 1);
  719. // If the cursor is outside the scrolling range, fix it
  720. // (Paul Brannan 6/26/98)
  721. // if(Console.GetRawCursorY() < iParam[0] - 1) {
  722. //  Console.SetRawCursorPosition(Console.GetCursorX(),
  723. //  iParam[0] - 1);
  724. // }
  725. // if(Console.GetRawCursorY() > iParam[1] - 1) {
  726. //  Console.SetRawCursorPosition(Console.GetCursorX(),
  727. //  iParam[1] - 1);
  728. // }
  729. }
  730. // Move the cursor to the home position (Paul Brannan 12/2/98)
  731. Console.SetCursorPosition(0, 0);
  732. break;
  733. // Save cursor position
  734. case 's': 
  735. SaveCurY(Console.GetRawCursorY());
  736. SaveCurX(Console.GetRawCursorX());
  737. break;
  738. // Restore cursor position
  739. case 'u': 
  740. Console.SetRawCursorPosition(iSavedCurX, iSavedCurY);
  741. break;
  742. // DEC terminal report (Paul Brannan 6/28/98)
  743. case 'x':
  744. if(iParam[0])
  745. Network.WriteString("33[3;1;1;128;128;1;0x", 20);
  746. else
  747. Network.WriteString("33[2;1;1;128;128;1;0x", 20);
  748. break;
  749. default:
  750. #ifdef DEBUG
  751. Console.Beep();
  752. #endif
  753. break;
  754. }
  755. return pszBuffer;
  756. }
  757. #ifdef MTE_SUPPORT
  758. // Added by Frediano Ziglio, 5/31/2000
  759. // MTE extension
  760. // initially copied from ParseEscapeANSI
  761. char* TANSIParser::ParseEscapeMTE(char* pszBuffer, char* pszBufferEnd)
  762. {
  763. //      The buffer contains something like <ESC>~pA
  764. //      where p is an optional decimal number specifying the count by which the
  765. //      appropriate action should take place.
  766. //      The pointer pszBuffer points us to the p, <ESC> and ~ are
  767. //      already 'consumed'
  768. //      TITUS: Simplification of the code: Assume default count of 1 in case
  769. //      there are no parameters.
  770. char tmpc;
  771. const int nParam = 10;  // Maximum number of parameters
  772. int     iParam[nParam] = {1, 0, 0, 0, 0};       // Assume 1 parameter, Default 1
  773. int iCurrentParam = 0;
  774. char sRepeat[2];
  775. // Get parameters from escape sequence.
  776. while ((tmpc = *pszBuffer) <= '?') {
  777. if(tmpc < '0' || tmpc > '9') {
  778. // Check for parameter delimiter.
  779. if(tmpc == ';') {
  780. pszBuffer++;
  781. continue;
  782. }
  783. pszBuffer++;
  784. }
  785. //  Got Numerical Parameter.
  786. iParam[iCurrentParam] = strtoul(pszBuffer, &pszBuffer, 10);
  787. if (iCurrentParam < nParam)
  788. iCurrentParam++;
  789. }
  790. //~~~ TITUS: Apparently the digit is optional (look at termcap or terminfo)
  791. // So: If there is no digit, assume a count of 1
  792. switch ((unsigned char)*pszBuffer++) {
  793. case 'A':
  794. // set colors
  795. if (iCurrentParam < 2 )
  796. break;
  797. if (iParam[0] <= 15 && iParam[1] <= 15)
  798. Console.SetAttrib( (iParam[1] << 4) | iParam[0] );
  799. break;
  800. case 'R':
  801. // define region
  802. mteRegionXF = -1;
  803. if (iCurrentParam < 2 )
  804. break;
  805. mteRegionXF = iParam[1]-1;
  806. mteRegionYF = iParam[0]-1;
  807. break;
  808. case 'F':
  809. // fill with char
  810. {
  811. if (mteRegionXF == -1 || iCurrentParam < 1)
  812. break;
  813. sRepeat[0] = (char)iParam[0];
  814. sRepeat[1] = '';
  815. int xi = Console.GetCursorX(),yi = Console.GetCursorY();
  816. int xf = mteRegionXF;
  817. int yf = mteRegionYF;
  818. mteRegionXF = -1;
  819. for(int y=yi;y<=yf;++y)
  820. {
  821. Console.SetCursorPosition(xi,y);
  822. for(int x=xi;x<=xf;++x)
  823. Console.WriteStringFast(sRepeat,1);
  824. }
  825. }
  826. break;
  827. case 'S':
  828. // Scroll region
  829. {
  830. if (mteRegionXF == -1 || iCurrentParam < 2)
  831. break;
  832. int /*x = Console.GetCursorX(),*/y = Console.GetCursorY();
  833. // int xf = mteRegionXF;
  834. int yf = mteRegionYF;
  835. mteRegionXF = -1;
  836. // !!! don't use x during scroll
  837. int diff = (iParam[0]-1)-y;
  838. if (diff<0)
  839. Console.ScrollDown(y-1,yf,diff);
  840. else
  841. Console.ScrollDown(y,yf+1,diff);
  842. }
  843. break;
  844. // Meridian main version ??
  845. case 'x':
  846. // disable echo and line mode
  847. Network.set_local_echo(0);
  848. Network.set_line_mode(0);
  849. // Meridian Server handle cursor itself
  850. Console.SetCursorSize(0);
  851. break;
  852. // query ??
  853. case 'Q':
  854. if (iParam[0] == 1)
  855. Network.WriteString("33vga.",5);
  856. break;
  857. default:
  858. #ifdef DEBUG
  859. Console.Beep();
  860. #endif
  861. break;
  862. }
  863. return pszBuffer;
  864.  }
  865. #endif
  866. char* TANSIParser::ParseEscape(char* pszBuffer, char* pszBufferEnd) {
  867. char *pszChar;
  868. // Check if we have enough characters in buffer.
  869. if ((pszBufferEnd - pszBuffer) < 2)
  870. return pszBuffer;
  871. //  I.Ioannou 04 Sep 1997
  872. // there is no need for pszBuffer++; after each command
  873. // Decode the command.
  874. pszBuffer++;
  875. switch (*pszBuffer++) {
  876. case 'A': // Cursor up
  877. Console.MoveCursorPosition(0, -1);
  878. break;
  879. // Cursor down
  880. case 'B': 
  881.    Console.MoveCursorPosition(0, 1);
  882. break;
  883. // Cursor right
  884. case 'C':
  885.    Console.MoveCursorPosition(1, 0);
  886. break;
  887. // LF *or* cursor left (Paul Brannan 6/27/98)
  888. case 'D':
  889. if(vt52_mode)
  890. Console.MoveCursorPosition(-1, 0);
  891. else
  892. Console.index();
  893. break;
  894. // CR/LF (Paul Brannan 6/26/98)
  895. case 'E':
  896. Console.WriteCtrlString("rn", 2);
  897. break;
  898. // Special graphics char set (Paul Brannan 6/27/98)
  899. case 'F':
  900. Charmap.setmap('0');
  901. break;
  902. // ASCII char set (Paul Brannan 6/27/98)
  903. case 'G':
  904. Charmap.setmap('B');
  905. break;
  906. // Home cursor/tab set
  907. case 'H': 
  908. if(ini.get_vt100_mode()) {
  909. int x = Console.GetCursorX();
  910. if(x != 0) {
  911. int t = tab_stops[x - 1];
  912. for(int j = x - 1; j >= 0 && tab_stops[j] == t; j--)
  913. tab_stops[j] = x;
  914. }
  915. } else {
  916. //  I.Ioannou 04 Sep 1997 (0,0) not (1,1)
  917. ConSetCursorPos(0, 0);
  918. }
  919. break;
  920. // Reverse line feed (Paul Brannan 6/27/98)
  921. // FIX ME!!!  reverse_index is wrong to be calling here
  922. // (Paul Brannan 12/2/98)
  923. case 'I':
  924. Console.reverse_index();
  925. break;
  926. // Erase end of screen
  927. case 'J': 
  928. Console.ClearEOScreen();
  929. break;
  930. // Erase EOL
  931. case 'K':
  932. Console.ClearEOLine();
  933. break;
  934. // Scroll Up one line //Reverse index
  935. case 'M':
  936. Console.reverse_index();
  937. break;
  938. // Direct cursor addressing
  939. case 'Y':
  940. if ((pszBufferEnd - pszBuffer) >= 2){
  941. // if we subtract 'x1F', then we may end up with a negative
  942. // cursor position! (Paul Brannan 6/26/98)
  943. ConSetCursorPos(pszBuffer[1] - ' ', pszBuffer[0] - ' ');
  944. pszBuffer+=2;
  945. } else {
  946. pszBuffer--; // Paul Brannan 6/26/98
  947. }
  948. break;
  949. // Terminal ID Request
  950. case 'Z':
  951. {
  952. char* szTerminalId = GetTerminalID();
  953. Network.WriteString(szTerminalId, strlen(szTerminalId));
  954. break;
  955. }
  956. // reset terminal to defaults
  957. case 'c':
  958. ResetTerminal();
  959. break;
  960. // Enter alternate keypad mode
  961. case '=':
  962. KeyTrans.set_ext_mode(APP3_KEY);
  963. break;
  964. // Exit alternate keypad mode
  965. case '>':
  966. KeyTrans.unset_ext_mode(APP3_KEY);
  967. break;
  968. // Enter ANSI mode
  969. case '<':
  970. KeyTrans.unset_ext_mode(APP2_KEY); // exit vt52 mode
  971. break;
  972. // Graphics processor on (See note 3)
  973. case '1':
  974. break;
  975. // Line size commands
  976. case '#':        //Line size commands
  977. // (Paul Brannan 6/26/98)
  978. if(pszBuffer < pszBufferEnd) {
  979. switch(*pszBuffer++) {
  980. case '3': break; // top half of a double-height line
  981. case '4': break; // bottom half of a double-height line
  982. case '6': break; // current line becomes double-width
  983. case '8': Console.ClearScreen('E'); break;
  984. }
  985. } else {
  986. pszBuffer--;
  987. }
  988. break;
  989. // Graphics processor off (See note 3)
  990. case '2':
  991. break;
  992. // Save cursor and attribs
  993. case '7':
  994. SaveCurY(Console.GetRawCursorY());
  995. SaveCurX(Console.GetRawCursorX());
  996. iSavedAttributes = Console.GetAttrib();
  997. break;
  998. // Restore cursor position and attribs
  999. case '8':
  1000. Console.SetRawCursorPosition(iSavedCurX, iSavedCurY);
  1001. Console.SetAttrib(iSavedAttributes);
  1002. break;
  1003. // Set G0 map (Paul Brannan 6/25/98)
  1004. case '(':
  1005. if (pszBuffer < pszBufferEnd) {
  1006. map_G0 = *pszBuffer;
  1007. if(current_map == 0) Charmap.setmap(map_G0);
  1008. pszBuffer++;
  1009. } else {
  1010. pszBuffer--;
  1011. }
  1012. break;
  1013. // Set G1 map (Paul Brannan 6/25/98)
  1014. case ')':
  1015. if (pszBuffer < pszBufferEnd) {
  1016. map_G1 = *pszBuffer;
  1017. if(current_map == 1) Charmap.setmap(map_G1);
  1018. pszBuffer++;
  1019. } else {
  1020. pszBuffer--;
  1021. }
  1022. break;
  1023. // This doesn't do anything, as far as I can tell, but it does take
  1024. // a parameter (Paul Brannan 6/27/98)
  1025. case '%':
  1026. if (pszBuffer < pszBufferEnd) {
  1027. pszBuffer++;
  1028. } else {
  1029. pszBuffer--;
  1030. }
  1031. break;
  1032. // ANSI escape sequence
  1033. case '[':
  1034. // Check if we have whole escape sequence in buffer.
  1035. // This should not be isalpha anymore (Paul Brannan 9/1/98)
  1036. pszChar = pszBuffer;
  1037. while ((pszChar < pszBufferEnd) && (*pszChar <= '?'))
  1038. pszChar++;
  1039. if (pszChar == pszBufferEnd)
  1040. pszBuffer -= 2;
  1041. else
  1042. pszBuffer = ParseEscapeANSI(pszBuffer, pszBufferEnd);
  1043. break;
  1044. #ifdef MTE_SUPPORT
  1045. case '~':
  1046. // Frediano Ziglio, 5/31/2000
  1047. // Meridian Terminal Emulator extension
  1048. // !!! same as ANSI
  1049. // !!! should put in MTE procedure
  1050. pszChar = pszBuffer;
  1051. while ((pszChar < pszBufferEnd) && (*pszChar <= '?'))
  1052. pszChar++;
  1053. if (pszChar == pszBufferEnd)
  1054. pszBuffer -= 2;
  1055. else
  1056. pszBuffer = ParseEscapeMTE(pszBuffer, pszBufferEnd);
  1057. break;
  1058. #endif
  1059. default:
  1060. #ifdef DEBUG
  1061. Console.Beep();
  1062. #endif
  1063. break;
  1064. }
  1065. return pszBuffer;
  1066. }
  1067. // This function now only parses the ANSI buffer and does not do anything
  1068. // with IAC sequences.  That code has been moved to TTelHndl.cpp.
  1069. // The scroller update routines have been moved to TScroll.cpp.
  1070. // (Paul Brannan 6/15/98)
  1071. char* TANSIParser::ParseBuffer(char* pszHead, char* pszTail){
  1072. // copy into ANSI buffer
  1073. char * pszResult;
  1074. // Parse the buffer for ANSI or display
  1075. while (pszHead < pszTail) {
  1076. if(!ini.get_output_redir()) {
  1077. pszResult = ParseANSIBuffer(pszHead, pszTail);
  1078. } else {
  1079. // Output is being redirected
  1080. if(ini.get_strip_redir()) {
  1081. // Skip the WriteFile() altogether and pass the buffer to a filter
  1082. // Mark Miesfield 09/24/2000
  1083. pszResult = PrintGoodChars(pszHead, pszTail);
  1084. } else {
  1085. DWORD Result;
  1086. // Paul Brannan 7/29/98
  1087. // Note that this has the unforunate effect of printing out
  1088. // NULL (ascii 0) characters onto the screen
  1089. if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pszHead,
  1090. pszTail - pszHead, &Result, NULL)) pszResult = pszHead;
  1091. pszResult = pszHead + Result;
  1092. }
  1093. }
  1094. if (dumpfile)
  1095. fwrite( pszHead, sizeof (char), pszResult-pszHead, dumpfile);
  1096. if(ini.get_scroll_enable()) Scroller.update(pszHead, pszResult);
  1097. if (pszResult == pszHead) break;
  1098. pszHead = pszResult;
  1099. }
  1100. // return the new head to the buffer
  1101. return pszHead;
  1102. }
  1103. // A simple routine to strip ANSI sequences
  1104. // This isn't perfect, but it does an okay job (Paul Brannan 7/5/98)
  1105. // Fixed a line counting bug (Paul Brannan 12/4/98)
  1106. int TANSIParser::StripBuffer(char* pszHead, char* pszTail, int width) {
  1107. int lines = 0, c = 0;
  1108. char *pszBuf = pszHead;
  1109. while(pszHead < pszTail) {
  1110. if(iscntrl(*pszHead)) {
  1111. switch(*(pszHead++)) {
  1112. case 8:
  1113. case 127:
  1114. if(c>0) {
  1115. if(!(c%width)) lines--;
  1116. c--;
  1117. pszBuf--;
  1118. }
  1119. break;
  1120. case 10: lines++;
  1121. case 13:
  1122. *(pszBuf++) = *(pszHead - 1);
  1123. c = 0;
  1124. break;
  1125. case 27:
  1126. switch(*(pszHead++)) {
  1127. case 'Y': pszHead += 2; break;
  1128. case '#':
  1129. case '(':
  1130. case ')':
  1131. case '%': pszHead++; break;
  1132. case '[':
  1133. while((pszHead < pszTail) && (*pszHead < '?'))
  1134. pszHead++;
  1135. pszHead++;
  1136. break;
  1137. }
  1138. }
  1139. } else {
  1140. *(pszBuf++) = *(pszHead++);
  1141. c++;
  1142. }
  1143. if(c != 0 && !(c%width))
  1144. lines++;
  1145. }
  1146. // Fill in the end of the buffer with blanks
  1147. while(pszBuf <= pszTail) *pszBuf++ = ' ';
  1148. return lines;
  1149. }
  1150. char* TANSIParser::ParseANSIBuffer(char* pszBuffer, char* pszBufferEnd)
  1151. {
  1152. if(InPrintMode) {
  1153. return PrintBuffer(pszBuffer, pszBufferEnd);
  1154. }
  1155. unsigned char tmpc = *(unsigned char *)pszBuffer;
  1156. if(tmpc == 27) {
  1157. return ParseEscape(pszBuffer, pszBufferEnd);
  1158. }
  1159. // if((fast_write && tmpc < 32) ||
  1160. // !print_ctrl && (tmpc < 32 || (EightBit_Ansi &&
  1161. // (tmpc > 128 && tmpc < 128 + ' ')))) {
  1162. // We shouldn't print ctrl characters when fast write is enabled
  1163. // and ctrl chars are disabled (Paul Brannan 9/1/98)
  1164. if(tmpc < 32) {
  1165. // From the Linux kernel (Paul Brannan 12/5/98):
  1166. /* A bitmap for codes <32. A bit of 1 indicates that the code
  1167.  * corresponding to that bit number invokes some special action
  1168.  * (such as cursor movement) and should not be displayed as a
  1169.  * glyph unless the disp_ctrl mode is explicitly enabled.
  1170.  */
  1171. const long CTRL_ACTION = 0x0d00ff81;
  1172. const long CTRL_ALWAYS = 0x0800f501;
  1173. if(!(((print_ctrl?CTRL_ALWAYS:CTRL_ACTION)>>tmpc)&1)) {
  1174. Console.WriteString((char *)&tmpc, 1);
  1175. pszBuffer++;
  1176. return pszBuffer;
  1177. }
  1178. switch (tmpc) {
  1179. case 0:
  1180. pszBuffer++;
  1181. break;
  1182. // I.Ioannou 5/30/98
  1183. case 7:
  1184. Console.Beep();
  1185. pszBuffer++;
  1186. break;
  1187. // destructive backspace
  1188. case 8:
  1189. // Added option for destructive backspace (Paul Brannan 5/13/98)
  1190. // Changed to ConWriteCtrlString so that the cursor position can be
  1191. // updated (Paul Brannan 5/25/98)
  1192. if(ini.get_dstrbksp()) {
  1193. Console.WriteCtrlChar('b');
  1194. Console.WriteString(" ", 1);
  1195. Console.WriteCtrlChar('b');
  1196. }
  1197. else Console.WriteCtrlChar('b');
  1198. pszBuffer++;
  1199. break;
  1200. // horizontal tab
  1201. case 9:
  1202. {
  1203. pszBuffer++;
  1204. int x = Console.GetCursorX();
  1205. if(x != -1)
  1206. Console.SetCursorPosition(tab_stops[x], Console.GetCursorY());
  1207. }
  1208. break;
  1209. // Line Feed Char
  1210. case 10:
  1211. // Test for local echo (Paul Brannan 8/25/98)
  1212. if(Network.get_local_echo() || newline_mode) // &&
  1213. Console.WriteCtrlChar('x0d');
  1214. Console.WriteCtrlChar('x0a');
  1215. pszBuffer++;
  1216. break;
  1217. // form feed
  1218. case 12:
  1219. pszBuffer++;
  1220. Console.ClearScreen();
  1221. Console.SetRawCursorPosition(Console.GetCursorX(), 1); // changed fm 1
  1222. break;
  1223. case 13:
  1224. Console.WriteCtrlChar('x0d');
  1225. pszBuffer++;
  1226. break;
  1227. case 14:  // shift out of alternate chararcter set
  1228. pszBuffer++;
  1229. Charmap.setmap(map_G1); // Paul Brannan 6/25/98
  1230. current_map = 1;
  1231. break;
  1232. case 15:  // shift in
  1233. pszBuffer++;
  1234. Charmap.setmap(map_G0); // Paul Brannan 6/25/98
  1235. current_map = 0;
  1236. break;
  1237. // Paul Brannan 9/1/98 - Is this okay?
  1238. default:
  1239. pszBuffer++;
  1240. }
  1241. return pszBuffer;
  1242. }
  1243. //  added by I.Ioannou 06 April, 1997
  1244. //  In 8 bit systems the server may send 0x9b instead of ESC[
  1245. //  Well, this will produce troubles in Greek 737 Code page
  1246. //  which uses 0x9b as the small "delta" - and I thing that there
  1247. //  is another European country with the same problem.
  1248. //  If we have to stay 8-bit clean we may have to
  1249. //  give the ability of ROM characters (ESC[11m),
  1250. //  for striped 8'th bit (ESC[12m) as SCO does,
  1251. //  or a parameter at compile (or run ?) time.
  1252. // We now check for a flag in the ini file (Paul Brannan 5/13/98)
  1253. // We also handle any 8-bit ESC sequence (Paul Brannan 6/28/98)
  1254. if(ini.get_eightbit_ansi() && (tmpc > 128 && tmpc < 128 + ' ')) {
  1255. // There's a chance the sequence might not parse.  If this happens
  1256. // then pszBuffer will be one character too far back, since
  1257. // ParseEscape is expecting two characters, not one.
  1258. // In that case we must handle it.
  1259. char *pszCurrent = pszBuffer;
  1260. pszBuffer = ParseEscape(pszBuffer, pszBufferEnd);
  1261. if(pszBuffer < pszCurrent) pszBuffer = pszCurrent;
  1262. }
  1263. char* pszCurrent = pszBuffer + 1;
  1264. // I.Ioannou 04 Sep 1997 FIXME with ESC[11m must show chars < 32
  1265. // Fixed (Paul Brannan 6/28/98)
  1266. while ((pszCurrent < pszBufferEnd) && (!iscntrl(*pszCurrent))) {
  1267. // I.Ioannou 04 Sep 1997 strip on high bit
  1268. if ( (inGraphMode) && (*pszCurrent > (char)32) )
  1269. *pszCurrent |= 0x80 ;
  1270. pszCurrent++;
  1271. }
  1272. // Note that this may break dumpfiles slightly.
  1273. // If 'B' is set to anything other than ASCII, this will cause problems
  1274. // (Paul Brannan 6/28/98)
  1275. if(current_map != 'B' && Charmap.enabled)
  1276. Charmap.translate_buffer(pszBuffer, pszCurrent);    
  1277. last_char = *(pszCurrent-1);    // TITUS++: Remember last char
  1278. if(fast_write) {
  1279. pszBuffer += Console.WriteStringFast(pszBuffer,
  1280. pszCurrent - pszBuffer);
  1281. } else {
  1282. pszBuffer += Console.WriteString(pszBuffer,
  1283. pszCurrent - pszBuffer);
  1284. }
  1285. return pszBuffer;
  1286. }
  1287. // Added by I.Ioannou 06 April, 1997
  1288. // Print the buffer until you reach ESC[4i
  1289. char* TANSIParser::PrintBuffer(char* pszBuffer, char* pszBufferEnd) {
  1290. // Check if we have enough characters in buffer.
  1291. if ((pszBufferEnd - pszBuffer) < 4)
  1292. return pszBuffer;
  1293. char *tmpChar;
  1294. tmpChar = pszBuffer;
  1295. if ( *tmpChar == 27 ) {
  1296. tmpChar++;
  1297. if ( *tmpChar == '[' ) {
  1298. tmpChar++;
  1299. if ( *tmpChar == '4' ) {
  1300. tmpChar++;
  1301. if ( *tmpChar == 'i' ) {
  1302. InPrintMode = 0; // Stop Print Log
  1303. if ( printfile != NULL )
  1304. fclose(printfile);
  1305. pszBuffer += 4;
  1306. return pszBuffer;
  1307. }
  1308. }
  1309. }
  1310. }
  1311. if (printfile != NULL) {
  1312. fputc( *pszBuffer, printfile);
  1313. pszBuffer++;
  1314. } else
  1315. InPrintMode = 0;
  1316. return pszBuffer;
  1317. }
  1318. /* - PrintGoodChars( pszHead, pszTail ) - - - - - - - - - - - - - - - - - - -
  1319. -*
  1320.   Mark Miesfield 09/24/2000
  1321.   Prints the characters in a buffer, from the specified head to the specified
  1322.   tail, to standard out, skipping any control characters or ANSI escape
  1323.   sequences.
  1324.   Parameters on entry:
  1325.     pszHead  ->  Starting point in buffer.
  1326.     pszTail  ->  Ending point in buffer.
  1327.   Returns:
  1328.     Pointer to the first character in the buffer that was not output to
  1329.     standard out.  (Since no error checking is done, this is in effect
  1330.     pszTail.)
  1331.   Side Effects:
  1332.     None.
  1333. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1334. */
  1335. char * TANSIParser::PrintGoodChars( char * pszHead, char * pszTail )  {
  1336.   while ( pszHead < pszTail )  {
  1337.     if ( iscntrl( *pszHead ) )  {
  1338.       switch ( *(pszHead++) )  {
  1339.         case 10 :
  1340.           putc( 10, stdout );
  1341.           break;
  1342.         case 13 :
  1343.           putc( 13, stdout );
  1344.           break;
  1345.         case 27:
  1346.           switch ( *(pszHead++) )  {
  1347.             case 'Y':
  1348.               pszHead += 2;
  1349.               break;
  1350.             case '#':
  1351.             case '(':
  1352.             case ')':
  1353.             case '%': pszHead++; break;
  1354.             case '[':
  1355.               while ( (pszHead < pszTail) && (*pszHead < '?') )
  1356.                 pszHead++;
  1357.               pszHead++;
  1358.               break;
  1359.             default :
  1360.               break;
  1361.           }
  1362.           break;
  1363.         default :
  1364.           break;
  1365.       }
  1366.     }
  1367.     else
  1368.       putc( *(pszHead++), stdout );
  1369.   }
  1370.   return ( pszTail );
  1371. }
  1372. // End of function:  PrintGoodChars( pszHead, pszTail )