Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5485 lines
191 KiB

  1. //Copyright (c) Microsoft Corporation. All rights reserved.
  2. #include <windows.h> //required for all Windows applications
  3. #pragma warning (disable: 4201) // disable "nonstandard extension used : nameless struct/union"
  4. #include <commdlg.h>
  5. #pragma warning (default: 4201)
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. #pragma warning( disable: 4100 )
  11. #pragma warning( disable: 4244 )
  12. #include <imm.h>
  13. #include "WinTel.h" // specific to this program
  14. #include "debug.h"
  15. #include "trmio.h"
  16. #include "vtnt.h"
  17. static UCHAR pchNBBuffer[ READ_BUF_SZ ];
  18. static void NewLineUp(WI *, TRM *);
  19. static void NewLine(WI *pwi, TRM *);
  20. static void SetBufferStart(TRM *);
  21. static BOOL FAddTabToBuffer( TRM *, DWORD );
  22. static BOOL FAddCharToBuffer(TRM *, UCHAR);
  23. static void FlushBuffer(WI *pwi, TRM *);
  24. static void CursorUp(TRM *);
  25. static void CursorDown(TRM *);
  26. static void CursorRight(TRM *);
  27. static void CursorLeft(TRM *);
  28. static void ClearLine(WI *pwi, TRM *, DWORD);
  29. static void SetMargins(TRM *, DWORD, DWORD);
  30. //For eg: home key: ^[[2~. 'x' needs replacement for each particular key
  31. static CHAR szVt302KeySequence[] = { 0x1B, '[', 'x', '~', 0 };
  32. static CHAR szVt302LongKeySequence[] = { 0x1B, '[', 'x', 'x', '~', 0 };
  33. static CHAR szVt302ShortKeySequence[] = { 0x1B, '[', 'x', 0 };
  34. UCHAR uchOutPrev = 0;
  35. UCHAR uchInPrev = 0;
  36. #define IsEUCCode(uch) (((uch) > 0xa0) ? TRUE : FALSE)
  37. #define IsKatakana(uch) (((uch) > 0xa0) ? ((uch < 0xe0) ? TRUE : FALSE) : FALSE)
  38. void jistosjis( UCHAR *, UCHAR *);
  39. void euctosjis( UCHAR *, UCHAR *);
  40. void sjistojis( UCHAR *, UCHAR *);
  41. void sjistoeuc( UCHAR *, UCHAR *);
  42. //void DBCSTextOut( HDC, int, int, LPCSTR, int, int);
  43. void ForceJISRomanSend( WI *);
  44. VOID SetImeWindow(TRM *ptrm);
  45. void PrepareForNAWS( );
  46. void DoNawsSubNegotiation( WI * );
  47. extern POINT ptWindowMaxSize;
  48. #define MAX_TABSTOPS 100 //Max tabstops
  49. extern WI gwi;
  50. SMALL_RECT srOldClientWindow = { 0, 0, 0, 0 };
  51. CONSOLE_SCREEN_BUFFER_INFO consoleBufferInfo;
  52. DWORD g_rgdwHTS[ MAX_TABSTOPS ]; //Array of tab stops
  53. WORD g_iHTS = 0; //Index in to the tab stops array
  54. WORD wSaveCurrentLine = 0;
  55. static BOOL g_bIsToBeLogged = FALSE;
  56. void WriteCharInfoToLog( CHAR_INFO pCharInfo[], COORD coSize )
  57. {
  58. WORD wRows = 0;
  59. while( wRows < coSize.Y )
  60. {
  61. DWORD nBytes = 0;
  62. DWORD length = 0;
  63. UCHAR *pcTmp = NULL;
  64. WORD wSrc = 0;
  65. WORD wDst = 0;
  66. while( wSrc < coSize.X )
  67. {
  68. DWORD dwSize = 0;
  69. dwSize = WideCharToMultiByte( GetConsoleCP(), 0,
  70. &( ( *( pCharInfo + wRows * coSize.X + wSrc ) ).Char.UnicodeChar ),
  71. 1, NULL, 0, NULL, NULL );
  72. if( !WideCharToMultiByte( GetConsoleCP(), 0,
  73. &( ( *( pCharInfo + wRows * coSize.X + wSrc ) ).Char.UnicodeChar ),
  74. 1, ( PCHAR ) ( g_rgchRow+wDst ), dwSize, NULL, NULL ) )
  75. {
  76. g_rgchRow[ wDst++ ] =
  77. ( *( pCharInfo + wRows * coSize.X + wSrc ) ).Char.AsciiChar;
  78. wSrc++;
  79. }
  80. else
  81. {
  82. wDst += ( WORD )dwSize;
  83. if( (*(pCharInfo + wRows * coSize.X + wSrc )).Attributes & COMMON_LVB_LEADING_BYTE )
  84. {
  85. ++wSrc;
  86. }
  87. wSrc++ ;
  88. }
  89. }
  90. pcTmp = g_rgchRow + ( coSize.X - 1 );
  91. //
  92. // Find the last non space character in the string.
  93. //
  94. while ( pcTmp != g_rgchRow && *pcTmp == ' ' )
  95. {
  96. pcTmp -= 1;
  97. }
  98. length = (DWORD)( pcTmp - g_rgchRow ) + 1;
  99. WriteFile(ui.hLogFile, g_rgchRow, length, &nBytes, NULL);
  100. WriteFile(ui.hLogFile, ( PUCHAR )szNewLine, strlen( ( const char * ) szNewLine), &nBytes, NULL);
  101. wRows++ ;
  102. }
  103. }
  104. void WriteToLog( DWORD dwLine )
  105. {
  106. SMALL_RECT srRead = { 0, 0, 0, 0};
  107. COORD coSize = { 0, 1 }, coOrigin = { 0, 0 };
  108. if( !g_bIsToBeLogged )
  109. {
  110. return;
  111. }
  112. coSize.X = ( WORD )ui.dwMaxCol;
  113. srRead.Top = ( WORD )dwLine, srRead.Bottom = ( WORD ) ( dwLine + 1 );
  114. srRead.Left = 0, srRead.Right = ( WORD ) ( ui.dwMaxCol - 1 );
  115. if( ReadConsoleOutput( gwi.hOutput, g_rgciCharInfo, coSize, coOrigin, &srRead ) )
  116. {
  117. coSize.Y = srRead.Bottom - srRead.Top + 1;
  118. coSize.X = srRead.Right - srRead.Left + 1;
  119. WriteCharInfoToLog( g_rgciCharInfo, coSize );
  120. }
  121. g_bIsToBeLogged = FALSE;
  122. }
  123. void GetWindowCoordinates( SMALL_RECT *srClientWindow, COORD* coordSize )
  124. {
  125. CONSOLE_SCREEN_BUFFER_INFO csbiRestore;
  126. ASSERT( srClientWindow );
  127. if( GetConsoleScreenBufferInfo( gwi.hOutput, &csbiRestore ) )
  128. {
  129. *srClientWindow = csbiRestore.srWindow;
  130. if( coordSize )
  131. {
  132. *coordSize = csbiRestore.dwSize;
  133. }
  134. }
  135. else
  136. {
  137. srClientWindow->Bottom = 0;
  138. srClientWindow->Top = 0;
  139. srClientWindow->Right = 0;
  140. srClientWindow->Left = 0;
  141. if( coordSize )
  142. {
  143. coordSize->X = 0;
  144. coordSize->Y = 0;
  145. }
  146. }
  147. }
  148. void SetWindowSize( HANDLE hConsoleToBeChanged )
  149. {
  150. COORD coordSize = { 0, 0 };
  151. SMALL_RECT srPromptWindow = { 0, 0, 0, 0 };
  152. HANDLE hOldConsole = NULL;
  153. COORD coordLargest = { 0, 0 };
  154. hOldConsole = gwi.hOutput;
  155. gwi.hOutput = hConsoleToBeChanged;
  156. GetWindowCoordinates( &srPromptWindow, &coordSize );
  157. gwi.hOutput = hOldConsole;
  158. //if error, return
  159. if( coordSize.X == 0 || srPromptWindow.Bottom == 0 )
  160. {
  161. return;
  162. }
  163. if( srPromptWindow.Bottom - srPromptWindow.Top != gwi.sbi.srWindow.Bottom - gwi.sbi.srWindow.Top ||
  164. srPromptWindow.Right - srPromptWindow.Left != gwi.sbi.srWindow.Right - gwi.sbi.srWindow.Left )
  165. {
  166. srPromptWindow.Right += ( gwi.sbi.srWindow.Right - gwi.sbi.srWindow.Left ) -
  167. ( srPromptWindow.Right - srPromptWindow.Left );
  168. srPromptWindow.Bottom += ( gwi.sbi.srWindow.Bottom - gwi.sbi.srWindow.Top ) -
  169. ( srPromptWindow.Bottom - srPromptWindow.Top );
  170. coordLargest = GetLargestConsoleWindowSize( gwi.hOutput );
  171. if( srPromptWindow.Right - srPromptWindow.Left >= coordLargest.X )
  172. {
  173. srPromptWindow.Right = srPromptWindow.Left + coordLargest.X - 1;
  174. }
  175. if( srPromptWindow.Bottom - srPromptWindow.Top >= coordLargest.Y )
  176. {
  177. srPromptWindow.Bottom = srPromptWindow.Top + coordLargest.Y - 1;
  178. }
  179. }
  180. if ( ( coordSize.X < gwi.sbi.dwSize.X ) || ( coordSize.Y < gwi.sbi.dwSize.Y ) )
  181. {
  182. COORD coordTmpSize = { 0, 0 };
  183. coordTmpSize .X = ( coordSize.X < gwi.sbi.dwSize.X ) ? gwi.sbi.dwSize.X : coordSize.X ;
  184. coordTmpSize .Y = ( coordSize.Y < gwi.sbi.dwSize.Y ) ? gwi.sbi.dwSize.Y : coordSize.Y ;
  185. SetConsoleScreenBufferSize( hConsoleToBeChanged, coordTmpSize );
  186. SetConsoleWindowInfo( hConsoleToBeChanged, TRUE, &srPromptWindow );
  187. SetConsoleScreenBufferSize ( hConsoleToBeChanged, gwi.sbi.dwSize );
  188. }
  189. else
  190. {
  191. SetConsoleWindowInfo( hConsoleToBeChanged, TRUE, &srPromptWindow );
  192. SetConsoleScreenBufferSize( hConsoleToBeChanged, gwi.sbi.dwSize );
  193. }
  194. }
  195. void CheckForChangeInWindowSize()
  196. {
  197. SMALL_RECT srClientWindow = { 0, 0, 0, 0 };
  198. COORD coordSize = { 0, 0 };
  199. GetWindowCoordinates( &srClientWindow, &coordSize );
  200. if( gwi.nd.fRespondedToDoNAWS && !g_bDontNAWSReceived &&
  201. ( srClientWindow.Bottom - srClientWindow.Top != srOldClientWindow.Bottom - srOldClientWindow.Top ||
  202. srOldClientWindow.Right - srOldClientWindow.Left != srClientWindow.Right - srClientWindow.Left ) )
  203. {
  204. //We found that window size has changed and we already did naws.
  205. //Do naws again
  206. COORD coordLargest = { 0, 0 };
  207. BOOL fChangedFromUserSetting = FALSE;
  208. coordLargest = GetLargestConsoleWindowSize( gwi.hOutput );
  209. if( srClientWindow.Right - srOldClientWindow.Left >= coordLargest.X )
  210. {
  211. srClientWindow.Right = srClientWindow.Left + coordLargest.X - 1;
  212. fChangedFromUserSetting = TRUE;
  213. }
  214. if( srClientWindow.Bottom - srOldClientWindow.Top >= coordLargest.Y )
  215. {
  216. srClientWindow.Bottom = srClientWindow.Top + coordLargest.Y - 1;
  217. fChangedFromUserSetting = TRUE;
  218. }
  219. if( fChangedFromUserSetting )
  220. {
  221. //The max window size that can be set through the ui on cmd is larger than what GetLargestConsoleWindowSize
  222. //returns. In that case, force the window size to be smaller
  223. SetConsoleWindowInfo( gwi.hOutput, TRUE, &srClientWindow );
  224. if( srClientWindow.Bottom - srClientWindow.Top == srOldClientWindow.Bottom - srOldClientWindow.Top &&
  225. srOldClientWindow.Right - srOldClientWindow.Left == srClientWindow.Right - srClientWindow.Left )
  226. {
  227. //This is needed so that we don't do NAWS when unnecessary
  228. return;
  229. }
  230. }
  231. if( srClientWindow.Bottom < srOldClientWindow.Bottom )
  232. {
  233. WORD wDifference = ( srOldClientWindow.Bottom - srClientWindow.Bottom );
  234. if( srClientWindow.Bottom + wDifference < coordSize.Y )
  235. {
  236. //Move the window to bottom
  237. srClientWindow.Top = srClientWindow.Top + wDifference;
  238. srClientWindow.Bottom = srOldClientWindow.Bottom;
  239. SetConsoleWindowInfo( gwi.hOutput, TRUE, &srClientWindow );
  240. }
  241. if( ( WORD ) gwi.trm.dwCurLine > srClientWindow.Bottom )
  242. {
  243. gwi.trm.dwCurLine = srClientWindow.Bottom;
  244. }
  245. }
  246. srOldClientWindow = srClientWindow;
  247. if( FGetCodeMode(eCodeModeIMEFarEast) )
  248. {
  249. srOldClientWindow.Bottom--; //Last row for IME status
  250. }
  251. gwi.sbi.srWindow = srOldClientWindow;
  252. gwi.sbi.dwSize = coordSize;
  253. PrepareForNAWS();
  254. DoNawsSubNegotiation( &gwi );
  255. SetMargins( &(gwi.trm), 1, gwi.sbi.dwSize.Y );
  256. SetWindowSize( g_hTelnetPromptConsoleBuffer );
  257. }
  258. else
  259. {
  260. //if the buffer size has changed
  261. if( gwi.sbi.dwSize.X != coordSize.X || gwi.sbi.dwSize.Y != coordSize.Y )
  262. {
  263. gwi.sbi.dwSize = coordSize;
  264. srOldClientWindow = srClientWindow; //window changes
  265. PrepareForNAWS();
  266. SetMargins( &(gwi.trm), 1, gwi.sbi.dwSize.Y );
  267. if( ( WORD ) gwi.trm.dwCurLine > srClientWindow.Bottom )
  268. {
  269. gwi.trm.dwCurLine = srClientWindow.Bottom;
  270. }
  271. }
  272. }
  273. }
  274. void SaveCurrentWindowCoords()
  275. {
  276. SMALL_RECT srClientWindow = { 0, 0, 0, 0 };
  277. GetWindowCoordinates( &srClientWindow, NULL );
  278. srOldClientWindow = srClientWindow;
  279. }
  280. void RestoreWindowCoordinates( )
  281. {
  282. SMALL_RECT srClientWindow = { 0, 0, 0, 0 };
  283. GetWindowCoordinates( &srClientWindow, NULL );
  284. if( ( srClientWindow.Bottom != 0 ) &&//valid values of srClientWindow?
  285. ( srOldClientWindow.Bottom != 0 ) &&
  286. ( srOldClientWindow.Top != srClientWindow.Top ||
  287. srOldClientWindow.Left != srClientWindow.Left ) ) //Window position over the buffer changed ?
  288. {
  289. SetConsoleWindowInfo( gwi.hOutput, TRUE, &srOldClientWindow );
  290. }
  291. if( srOldClientWindow.Bottom == 0 )
  292. {
  293. srOldClientWindow = srClientWindow;
  294. }
  295. }
  296. void
  297. ReSizeWindow(HWND hwnd, long cx, long cy)
  298. {
  299. BOOL bScrollBars;
  300. NONCLIENTMETRICS NonClientMetrics;
  301. ASSERT( ( 0, 0 ) );
  302. NonClientMetrics.cbSize = sizeof( NonClientMetrics );
  303. SystemParametersInfo( SPI_GETNONCLIENTMETRICS,
  304. 0,
  305. &NonClientMetrics,
  306. FALSE );
  307. //
  308. // if cx and cy are -1, then set the window size to the desktop
  309. // minus the offset of the window. This sets the window to the
  310. // maximum size that will still be contained on the desktop
  311. //
  312. if ( cx == -1 && cy == -1 )
  313. {
  314. RECT rect;
  315. GetWindowRect( hwnd, &rect );
  316. cx = (SHORT) (GetSystemMetrics( SM_CXFULLSCREEN ) - rect.left);
  317. cy = (SHORT) (GetSystemMetrics( SM_CYFULLSCREEN ) - rect.top);
  318. }
  319. if (( ui.dwClientRow < ui.dwMaxRow ) &&
  320. ( ui.dwClientCol < ui.dwMaxCol ) &&
  321. ( (( cy + NonClientMetrics.iScrollHeight ) ) == (LONG)ui.dwMaxRow ) &&
  322. ( (( cx + NonClientMetrics.iScrollWidth ) ) == (LONG)ui.dwMaxCol ) )
  323. {
  324. cy += NonClientMetrics.iScrollHeight;
  325. cx += NonClientMetrics.iScrollWidth;
  326. }
  327. ui.dwClientRow = cy;
  328. ui.dwClientCol = cx;
  329. ui.dwClientRow = min ( ui.dwClientRow, ui.dwMaxRow);
  330. ui.dwClientCol = min ( ui.dwClientCol, ui.dwMaxCol);
  331. if ( (ui.dwClientRow < ui.dwMaxRow) ||
  332. (ui.dwClientCol < ui.dwMaxCol) )
  333. {
  334. ui.nScrollMaxRow = (SHORT)(ui.dwMaxRow - ui.dwClientRow);
  335. ui.nScrollRow = ( WORD )min (ui.nScrollRow, ui.nScrollMaxRow);
  336. ui.nScrollMaxCol = (SHORT)(ui.dwMaxCol - ui.dwClientCol);
  337. ui.nScrollCol = ( WORD )min (ui.nScrollCol, ui.nScrollMaxCol);
  338. bScrollBars = TRUE;
  339. }
  340. else
  341. {
  342. ui.nScrollRow = 0;
  343. ui.nScrollMaxRow = 0;
  344. ui.nScrollCol = 0;
  345. ui.nScrollMaxCol = 0;
  346. bScrollBars = FALSE;
  347. }
  348. }
  349. static void
  350. InsertLine(WI *pwi, TRM *ptrm, DWORD iLine)
  351. {
  352. COORD dwDest;
  353. SMALL_RECT rect;
  354. rect.Top = ( short )( iLine );
  355. rect.Bottom = ( short )( ptrm->dwScrollBottom - 1 - 1 );
  356. rect.Left = 0;
  357. rect.Right = ( short )( ui.nCxChar * ui.dwMaxCol );
  358. dwDest.X = 0;
  359. dwDest.Y = ( short )( iLine + 1 );
  360. pwi->cinfo.Attributes = pwi->sbi.wAttributes;
  361. ScrollConsoleScreenBuffer( pwi->hOutput, &rect, NULL, dwDest, &pwi->cinfo );
  362. }
  363. static void
  364. NewLineUp( WI* pwi, TRM* ptrm )
  365. {
  366. if (ui.bLogging)
  367. {
  368. WriteToLog( ptrm->dwCurLine );
  369. }
  370. if( ptrm->dwCurLine <= ptrm->dwScrollTop )
  371. {
  372. ptrm->dwCurLine = ptrm->dwScrollTop;
  373. InsertLine( pwi, ptrm, ptrm->dwScrollTop );
  374. }
  375. else
  376. {
  377. ptrm->dwCurLine -= 1;
  378. if( ( SHORT )ptrm->dwCurLine < srOldClientWindow.Top )
  379. {
  380. /*SetConsoleWindowInfo should fail when the top reaches buffer top*/
  381. srOldClientWindow.Top -= 1;
  382. srOldClientWindow.Bottom -= 1;
  383. SetConsoleWindowInfo( gwi.hOutput, TRUE, &srOldClientWindow );
  384. }
  385. }
  386. }
  387. static void
  388. DeleteLine(WI *pwi, TRM *ptrm, DWORD iLine)
  389. {
  390. SMALL_RECT rect;
  391. COORD dwDest;
  392. rect.Top = ( WORD )( iLine + 1 * iCursorHeight );
  393. rect.Bottom = ( WORD )( ( ptrm->dwScrollBottom - 1 ) * iCursorHeight );
  394. rect.Left = 0;
  395. rect.Right = ( WORD )( ui.nCxChar * ui.dwMaxCol );
  396. dwDest.X = 0;
  397. dwDest.Y = ( WORD ) ( iLine + 1 - 1 );
  398. pwi->cinfo.Attributes = pwi->sbi.wAttributes;
  399. ScrollConsoleScreenBuffer( pwi->hOutput, &rect, NULL, dwDest, &pwi->cinfo );
  400. }
  401. void MoveOneLineDownTheBuffer( WI *pwi, TRM *ptrm )
  402. {
  403. DWORD dwNumWritten = 0;
  404. COORD coCursorPosition = { 0, 0 };
  405. /* SetConsoleWindowInfo should fail when the bottom reaches buffer bottom*/
  406. srOldClientWindow.Top += 1;
  407. srOldClientWindow.Bottom += 1;
  408. //To avoid the color flickering paint it first and then scroll
  409. coCursorPosition.X=0; coCursorPosition.Y=srOldClientWindow.Bottom;
  410. FillConsoleOutputAttribute( pwi->hOutput, pwi->sbi.wAttributes,
  411. srOldClientWindow.Right - srOldClientWindow.Left + 1,
  412. coCursorPosition, &dwNumWritten );
  413. SetConsoleWindowInfo( gwi.hOutput, TRUE, &srOldClientWindow );
  414. }
  415. static void
  416. NewLine(WI *pwi, TRM *ptrm)
  417. {
  418. if (ui.bLogging)
  419. {
  420. WriteToLog( ptrm->dwCurLine );
  421. }
  422. if(( ptrm->dwCurLine + 1 ) >= ptrm->dwScrollBottom )
  423. {
  424. // DeleteLines( pwi, ptrm, ptrm->dwScrollTop, 1 );
  425. DeleteLine( pwi, ptrm, ptrm->dwScrollTop );
  426. }
  427. else
  428. {
  429. WORD bottom = srOldClientWindow.Bottom;
  430. if( FGetCodeMode( eCodeModeFarEast ) )
  431. {
  432. bottom--;
  433. }
  434. ptrm->dwCurLine += 1;
  435. if( ptrm->dwCurLine > bottom )
  436. {
  437. MoveOneLineDownTheBuffer( pwi, ptrm);
  438. }
  439. }
  440. if(( ptrm->dwCurLine > ( ui.dwMaxRow - ( ui.nScrollMaxRow - ui.nScrollRow ))) &&
  441. ( ui.nScrollRow < ui.nScrollMaxRow ) )
  442. {
  443. ui.nScrollRow += 1;
  444. //ScrollWindow(hwnd, 0, -ui.nCyChar, NULL, NULL);
  445. }
  446. }
  447. static void
  448. SetBufferStart(TRM *ptrm)
  449. {
  450. ptrm->dwCurCharBT = ptrm->dwCurChar;
  451. ptrm->dwCurLineBT = ptrm->dwCurLine;
  452. ptrm->fInverseBT = ptrm->fInverse;
  453. }
  454. static BOOL
  455. FAddCharToBuffer(TRM *ptrm, UCHAR uch)
  456. {
  457. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  458. {
  459. if(FIsVT80(ptrm) || GetACP() == KOR_CODEPAGE )
  460. {
  461. if( FIsJISKanji(ptrm) || FIsJIS78Kanji(ptrm) || FIsNECKanji(ptrm) || FIsACOSKanji(ptrm) )
  462. {
  463. if( !(GetKanjiStatus(ptrm) & JIS_KANJI_CODE) )
  464. {
  465. if( GetKanjiStatus(ptrm) & (SINGLE_SHIFT_2|SINGLE_SHIFT_3) )
  466. {
  467. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  468. ptrm->dwCurChar++;
  469. ClearKanjiStatus(ptrm,(SINGLE_SHIFT_2|SINGLE_SHIFT_3));
  470. PopCharSet(ptrm,GRAPHIC_LEFT);
  471. PopCharSet(ptrm,GRAPHIC_RIGHT);
  472. uchOutPrev = 0;
  473. }
  474. else
  475. {
  476. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  477. ptrm->dwCurChar++;
  478. uchOutPrev = 0;
  479. }
  480. }
  481. else
  482. {
  483. if ( uchOutPrev == 0 )
  484. {
  485. uchOutPrev = uch;
  486. }
  487. else
  488. {
  489. jistosjis(&uchOutPrev,&uch);
  490. ptrm->rgchBufferText[ptrm->cchBufferText++] = uchOutPrev;
  491. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  492. ptrm->dwCurChar+=2;
  493. uchOutPrev = 0;
  494. }
  495. }
  496. }
  497. else if( FIsSJISKanji(ptrm) || GetACP() == KOR_CODEPAGE )
  498. {
  499. if( uchOutPrev == 0 && IsDBCSLeadByte(uch) )
  500. {
  501. /* do not write only LeadByte into buffer.
  502. keep current leadbyte character */
  503. uchOutPrev = uch;
  504. }
  505. else
  506. {
  507. if( uchOutPrev == 0 )
  508. {
  509. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  510. ptrm->dwCurChar++;
  511. }
  512. else
  513. {
  514. ptrm->rgchBufferText[ptrm->cchBufferText++] = uchOutPrev;
  515. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  516. ptrm->dwCurChar+=2;
  517. uchOutPrev = 0;
  518. }
  519. }
  520. }
  521. else if( FIsEUCKanji(ptrm) || FIsDECKanji(ptrm) )
  522. {
  523. if( GetKanjiStatus(ptrm) & (SINGLE_SHIFT_2|SINGLE_SHIFT_3) )
  524. {
  525. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  526. ptrm->dwCurChar++;
  527. ClearKanjiStatus(ptrm,(SINGLE_SHIFT_2|SINGLE_SHIFT_3));
  528. PopCharSet(ptrm,GRAPHIC_LEFT);
  529. PopCharSet(ptrm,GRAPHIC_RIGHT);
  530. uchOutPrev = 0;
  531. }
  532. else if( IsEUCCode(uch) || uchOutPrev != 0 )
  533. {
  534. if( uchOutPrev == 0 )
  535. {
  536. uchOutPrev = uch;
  537. }
  538. else
  539. {
  540. euctosjis(&uchOutPrev,&uch);
  541. ptrm->rgchBufferText[ptrm->cchBufferText++] = uchOutPrev;
  542. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  543. ptrm->dwCurChar+=2;
  544. uchOutPrev = 0;
  545. }
  546. }
  547. else
  548. {
  549. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  550. ptrm->dwCurChar++;
  551. uchOutPrev = 0;
  552. }
  553. }
  554. }
  555. else
  556. {
  557. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  558. ptrm->dwCurChar++;
  559. }
  560. return (ptrm->cchBufferText >= sizeof(ptrm->rgchBufferText));
  561. }
  562. ASSERT(!(FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)));
  563. ptrm->rgchBufferText[ptrm->cchBufferText++] = uch;
  564. return (ptrm->cchBufferText >= sizeof(ptrm->rgchBufferText));
  565. }
  566. static BOOL FAddTabToBuffer(TRM *ptrm, DWORD wSpaces)
  567. {
  568. (void)memset((void *)(ptrm->rgchBufferText+ptrm->cchBufferText), (int)' ', (size_t)wSpaces);
  569. ptrm->cchBufferText += wSpaces;
  570. return (ptrm->cchBufferText >= sizeof(ptrm->rgchBufferText));
  571. }
  572. void ResetColors( WI* pwi )
  573. {
  574. pwi->sbi.wAttributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  575. }
  576. void SetForegroundColor( WI* pwi, UCHAR color )
  577. {
  578. pwi->sbi.wAttributes = ( WORD )( ( pwi->sbi.wAttributes & ~( ( UCHAR )( FOREGROUND_RED |
  579. FOREGROUND_GREEN | FOREGROUND_BLUE ))) | color );
  580. }
  581. void SetBackgroundColor( WI* pwi, UCHAR color )
  582. {
  583. pwi->sbi.wAttributes =( WORD ) ( ( pwi->sbi.wAttributes & ~( ( UCHAR )( BACKGROUND_RED |
  584. BACKGROUND_GREEN | BACKGROUND_BLUE ))) | (( UCHAR) ( color << 4 )) );
  585. }
  586. void NegativeImageOn( WI* pwi )
  587. {
  588. //pwi->sbi.wAttributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
  589. pwi->sbi.wAttributes = ( WORD )( (( pwi->sbi.wAttributes &
  590. ( BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE )) >> 4 ) |
  591. (( pwi->sbi.wAttributes & ( FOREGROUND_RED | FOREGROUND_GREEN |
  592. FOREGROUND_BLUE )) << 4 ) | ( pwi->sbi.wAttributes &
  593. FOREGROUND_INTENSITY ) | ( pwi->sbi.wAttributes &
  594. BACKGROUND_INTENSITY ) );
  595. }
  596. void NegativeImageOff( WI* pwi )
  597. {
  598. //pwi->sbi.wAttributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  599. pwi->sbi.wAttributes = ( WORD ) ( (( pwi->sbi.wAttributes &
  600. ( BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE )) >> 4 ) |
  601. (( pwi->sbi.wAttributes & ( FOREGROUND_RED | FOREGROUND_GREEN |
  602. FOREGROUND_BLUE )) << 4 ) | ( pwi->sbi.wAttributes &
  603. FOREGROUND_INTENSITY ) | ( pwi->sbi.wAttributes &
  604. BACKGROUND_INTENSITY ) );
  605. }
  606. void BoldOff( WI* pwi )
  607. {
  608. pwi->sbi.wAttributes &= (UCHAR) ~( FOREGROUND_INTENSITY );
  609. }
  610. void BoldOn( WI* pwi )
  611. {
  612. pwi->sbi.wAttributes |= (UCHAR) FOREGROUND_INTENSITY;
  613. }
  614. void SetLightBackground( WI* pwi )
  615. {
  616. WORD* pAttribs = NULL;
  617. COORD co = { 0, 0 };
  618. DWORD dwNumRead;
  619. DWORD dwNumWritten;
  620. int j;
  621. DWORD dwStatus;
  622. CONSOLE_SCREEN_BUFFER_INFO cSBInfo;
  623. COORD dwSize;
  624. GetConsoleScreenBufferInfo( gwi.hOutput, &cSBInfo );
  625. dwSize.X = ( WORD ) ( cSBInfo.srWindow.Bottom - cSBInfo.srWindow.Top + 1 );
  626. dwSize.Y = ( WORD ) ( cSBInfo.srWindow.Right - cSBInfo.srWindow.Left + 1 );
  627. pAttribs = ( WORD* ) malloc( sizeof( WORD ) * dwSize.X * dwSize.Y );
  628. if( !pAttribs)
  629. return;
  630. co.X = cSBInfo.srWindow.Left;
  631. co.Y = cSBInfo.srWindow.Top;
  632. dwStatus = ReadConsoleOutputAttribute( pwi->hOutput, pAttribs,
  633. ( DWORD ) dwSize.X * ( DWORD ) dwSize.Y , co, &dwNumRead );
  634. #ifdef DEBUG
  635. if( !dwStatus )
  636. {
  637. _snwprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, L"Error: SetLightBackground() -- %d",
  638. GetLastError() );
  639. OutputDebugString(rgchDbgBfr);
  640. }
  641. #endif
  642. for( j = 0; j < dwSize.X * dwSize.Y; j++ )
  643. {
  644. pAttribs[j] |= (UCHAR) BACKGROUND_INTENSITY;
  645. }
  646. dwStatus = WriteConsoleOutputAttribute( pwi->hOutput, pAttribs,
  647. ( DWORD )dwSize.Y * ( DWORD )dwSize.X, co, &dwNumWritten );
  648. #ifdef DEBUG
  649. if( !dwStatus )
  650. {
  651. _snwprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, L"Error: SetLightBackground() -- %d",
  652. GetLastError() );
  653. OutputDebugString(rgchDbgBfr);
  654. }
  655. #endif
  656. pwi->sbi.wAttributes |= (UCHAR) BACKGROUND_INTENSITY;
  657. free( pAttribs );
  658. }
  659. void SetDarkBackground( WI* pwi )
  660. {
  661. //I am doing this for the whole console screen buffer
  662. //beacuse right now we don't support scrolling and expect
  663. //the console screen buffer size to be same as window size
  664. //but if and when we implement scrolling then we can optimize
  665. //this stuff so that we change the attributes only for the
  666. //current visible part of the screen buffer
  667. WORD* pAttribs = ( WORD* ) malloc( sizeof( WORD) * pwi->sbi.dwSize.X
  668. * pwi->sbi.dwSize.Y );
  669. DWORD dwNumRead;
  670. DWORD dwNumWritten;
  671. int j;
  672. COORD co = { 0, 0 };
  673. if (!pAttribs)
  674. return;
  675. ReadConsoleOutputAttribute( pwi->hOutput, pAttribs,
  676. ( DWORD ) ( pwi->sbi.dwSize.X ) * ( DWORD ) ( pwi->sbi.dwSize.Y ),
  677. co, &dwNumRead );
  678. for( j = 0; j < ( pwi->sbi.dwSize.X ) * ( pwi->sbi.dwSize.Y ); j++ )
  679. {
  680. pAttribs[j] &= (UCHAR) ~( BACKGROUND_INTENSITY );
  681. }
  682. WriteConsoleOutputAttribute( pwi->hOutput, pAttribs,
  683. ( DWORD ) ( pwi->sbi.dwSize.Y ) * ( DWORD )( pwi->sbi.dwSize.X ),
  684. co, &dwNumWritten );
  685. pwi->sbi.wAttributes &= (UCHAR) ~( BACKGROUND_INTENSITY );
  686. free( pAttribs );
  687. }
  688. static void FlushBuffer( WI* pwi, TRM* ptrm )
  689. {
  690. if( ptrm->cchBufferText != 0 )
  691. {
  692. DWORD dwNumWritten;
  693. COORD dwCursorPosition;
  694. if( ui.bLogging )
  695. {
  696. g_bIsToBeLogged = TRUE; //There is data to be logged
  697. }
  698. dwCursorPosition.X = ( short ) ( ptrm->dwCurCharBT - ui.nScrollCol );
  699. dwCursorPosition.Y = ( short ) ( ptrm->dwCurLineBT - ui.nScrollRow);
  700. //WriteConsole is a tty ( kind of sending to stdout ) function.
  701. //When you write on the right most bottom char on a window, it makes the
  702. //widow scroll. It can make the screen look ugly in the presence of
  703. //colors. So unless, 81st char on the bottom row is a DBCS char,
  704. //use WriteConsoleOutPutCharacter.
  705. //Each DBCS char requires two cells on the console screen
  706. if( FGetCodeMode(eCodeModeFarEast ) &&
  707. ( srOldClientWindow.Bottom - 1 == ( WORD )ptrm->dwCurLine ) &&
  708. ptrm->dwCurCharBT + ptrm->cchBufferText > ui.dwMaxCol
  709. )
  710. {
  711. //This is the bottom of the fareast client windows
  712. DeleteLine( pwi, ptrm, ptrm->dwScrollTop );
  713. dwCursorPosition.Y--;
  714. ptrm->dwCurLine--;
  715. }
  716. SetConsoleCursorPosition( pwi->hOutput, dwCursorPosition );
  717. if( srOldClientWindow.Bottom == ( WORD )ptrm->dwCurLine )
  718. {
  719. //This will never happen on non FE lang m/cs since status line will be
  720. //present at the bottom
  721. WriteConsoleOutputCharacterA( pwi->hOutput, (PCHAR)ptrm->rgchBufferText,
  722. ptrm->cchBufferText, dwCursorPosition, &dwNumWritten );
  723. }
  724. else
  725. {
  726. WriteConsoleA( pwi->hOutput, ptrm->rgchBufferText,
  727. ptrm->cchBufferText, &dwNumWritten, NULL );
  728. }
  729. FillConsoleOutputAttribute( pwi->hOutput, pwi->sbi.wAttributes,
  730. ptrm->cchBufferText, dwCursorPosition, &dwNumWritten );
  731. //part of fix for Bug 1470 - DBCS char disappearance at 81 column.
  732. if( FGetCodeMode(eCodeModeFarEast ) )
  733. {
  734. CONSOLE_SCREEN_BUFFER_INFO csbiCurrent;
  735. if( GetConsoleScreenBufferInfo( gwi.hOutput, &csbiCurrent ) )
  736. {
  737. if( csbiCurrent.dwCursorPosition.Y > dwCursorPosition.Y )
  738. {
  739. //Occupied some space even on next row
  740. ptrm->dwCurChar = csbiCurrent.dwCursorPosition.X;
  741. }
  742. }
  743. }
  744. // Reset parameters
  745. ptrm->cchBufferText = 0;
  746. ptrm->dwCurCharBT = 0;
  747. ptrm->dwCurLineBT = 0;
  748. ptrm->fInverseBT = FALSE;
  749. }
  750. }
  751. void
  752. DoTermReset(WI *pwi, TRM *ptrm)
  753. {
  754. ptrm->dwVT100Flags = 0;
  755. //ui.dwCrLf ? SetLineMode(ptrm): ClearLineMode(ptrm);
  756. SetVTWrap(ptrm);
  757. ptrm->fSavedState = FALSE;
  758. ptrm->fRelCursor = FALSE;
  759. SetMargins( ptrm, 1, ui.dwMaxRow );
  760. ptrm->cchBufferText = 0;
  761. ptrm->dwCurCharBT = 0;
  762. ptrm->dwCurLineBT = 0;
  763. ptrm->fInverseBT = FALSE;
  764. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  765. {
  766. ClearKanjiFlag(ptrm);
  767. ClearKanjiStatus(ptrm,CLEAR_ALL);
  768. SetupCharSet( ptrm );
  769. }
  770. else
  771. {
  772. ptrm->puchCharSet = rgchNormalChars;
  773. ptrm->currCharSet = 'B';
  774. ptrm->G0 = 'B';
  775. ptrm->G1 = 'B';
  776. }
  777. ptrm->fEsc = 0;
  778. ptrm->cEscParams = 0;
  779. ptrm->fFlushToEOL = FALSE;
  780. ptrm->fLongLine = FALSE;
  781. }
  782. static void
  783. CursorUp(TRM *ptrm)
  784. {
  785. if( ui.bLogging )
  786. {
  787. WriteToLog( ptrm->dwCurLine );
  788. }
  789. if( ptrm->dwEscCodes[0] == 0 )
  790. {
  791. ptrm->dwEscCodes[0] = 1;
  792. }
  793. if( ptrm->dwCurLine < (DWORD)ptrm->dwEscCodes[0] )
  794. {
  795. ptrm->dwCurLine = 0;
  796. }
  797. else
  798. {
  799. ptrm->dwCurLine -= ptrm->dwEscCodes[0];
  800. }
  801. if(( ptrm->fRelCursor == TRUE ) && ( ptrm->dwCurLine < ptrm->dwScrollTop ))
  802. {
  803. ptrm->dwCurLine = ptrm->dwScrollTop;
  804. }
  805. ptrm->fEsc = 0;
  806. }
  807. static void
  808. CursorDown(TRM *ptrm)
  809. {
  810. if( ui.bLogging )
  811. {
  812. WriteToLog( ptrm->dwCurLine );
  813. }
  814. if (ptrm->dwEscCodes[0] == 0)
  815. ptrm->dwEscCodes[0]=1;
  816. ptrm->dwCurLine += ptrm->dwEscCodes[0];
  817. if (ptrm->dwCurLine >= ui.dwMaxRow)
  818. ptrm->dwCurLine = ui.dwMaxRow - 1;
  819. if ((ptrm->fRelCursor == TRUE) &&
  820. (ptrm->dwCurLine >= ptrm->dwScrollBottom))
  821. {
  822. ptrm->dwCurLine = ptrm->dwScrollBottom-1;
  823. }
  824. ptrm->fEsc = 0;
  825. }
  826. static void
  827. CursorRight(TRM *ptrm)
  828. {
  829. if( ptrm->dwEscCodes[0] == 0 )
  830. {
  831. ptrm->dwEscCodes[0] = 1;
  832. }
  833. ptrm->dwCurChar += ptrm->dwEscCodes[0];
  834. if( ptrm->dwCurChar >= ui.dwMaxCol )
  835. {
  836. ptrm->dwCurChar = ui.dwMaxCol - 1;
  837. }
  838. ptrm->fEsc = 0;
  839. }
  840. static void
  841. CursorLeft(TRM *ptrm)
  842. {
  843. if( ptrm->dwEscCodes[0] == 0 )
  844. {
  845. ptrm->dwEscCodes[0] = 1;
  846. }
  847. if( ptrm->dwCurChar < ( DWORD ) ptrm->dwEscCodes[0] )
  848. {
  849. ptrm->dwCurChar = 0;
  850. }
  851. else
  852. {
  853. ptrm->dwCurChar -= ptrm->dwEscCodes[0];
  854. }
  855. ptrm->fEsc = 0;
  856. ptrm->fFlushToEOL = FALSE;
  857. }
  858. void
  859. ClearScreen(WI *pwi, TRM *ptrm, DWORD dwType)
  860. {
  861. DWORD dwNumWritten;
  862. COORD dwWriteCoord;
  863. if( dwType <= fdwEntireScreen )
  864. {
  865. ptrm->fInverse = FALSE;
  866. /*
  867. * If the cursor is already at the top-left corner
  868. * and we're supposed to clear from the cursor
  869. * to the end of the screen, then just clear
  870. * the entire screen.
  871. */
  872. if(( ptrm->dwCurChar == 0 ) && ( ptrm->dwCurLine == 0 ) &&
  873. ( dwType == fdwCursorToEOS ))
  874. {
  875. dwType = fdwEntireScreen;
  876. }
  877. if (dwType == fdwEntireScreen)
  878. {
  879. /* Clear entire screen */
  880. ptrm->dwCurChar = srOldClientWindow.Left;
  881. ptrm->dwCurLine = srOldClientWindow.Top;
  882. // if (ui.nScrollRow > 0)
  883. {
  884. dwWriteCoord.X = 0; dwWriteCoord.Y = 0;
  885. FillConsoleOutputCharacter( pwi->hOutput,
  886. ' ', ( pwi->sbi.dwSize.X ) * ( pwi->sbi.dwSize.Y ),
  887. dwWriteCoord, &dwNumWritten );
  888. FillConsoleOutputAttribute( pwi->hOutput, pwi->sbi.wAttributes,
  889. ( pwi->sbi.dwSize.X ) * ( pwi->sbi.dwSize.Y ), dwWriteCoord,
  890. &dwNumWritten );
  891. ui.nScrollRow = 0;
  892. }
  893. }
  894. else if( dwType == fdwBOSToCursor )
  895. {
  896. // Clear from beginning of screen to cursor
  897. dwWriteCoord.X = 0;
  898. dwWriteCoord.Y = 0;
  899. FillConsoleOutputCharacter( pwi->hOutput, ' ',
  900. ptrm->dwCurLine * pwi->sbi.dwSize.X + ptrm->dwCurChar + 1,
  901. dwWriteCoord, &dwNumWritten );
  902. FillConsoleOutputAttribute( pwi->hOutput, pwi->sbi.wAttributes,
  903. ptrm->dwCurLine * pwi->sbi.dwSize.X + ptrm->dwCurChar + 1,
  904. dwWriteCoord, &dwNumWritten );
  905. }
  906. else
  907. {
  908. // Clear from cursor to end of screen
  909. dwWriteCoord.X = ( short ) ptrm->dwCurChar;
  910. dwWriteCoord.Y = ( short ) ptrm->dwCurLine;
  911. FillConsoleOutputCharacter( pwi->hOutput, ' ',
  912. ( pwi->sbi.dwSize.Y - ( ptrm->dwCurLine + 1 )) * pwi->sbi.dwSize.X +
  913. ( pwi->sbi.dwSize.X - ptrm->dwCurChar ), dwWriteCoord,
  914. &dwNumWritten );
  915. FillConsoleOutputAttribute( pwi->hOutput, pwi->sbi.wAttributes,
  916. ( pwi->sbi.dwSize.Y - ( ptrm->dwCurLine + 1 )) * pwi->sbi.dwSize.X +
  917. ( pwi->sbi.dwSize.X - ptrm->dwCurChar ), dwWriteCoord,
  918. &dwNumWritten );
  919. }
  920. }
  921. ptrm->fEsc = 0;
  922. }
  923. // Fill Screen With E's
  924. void
  925. DECALN(WI *pwi, TRM *ptrm )
  926. {
  927. DWORD dwNumWritten;
  928. COORD dwWriteCoord;
  929. ptrm->fInverse = FALSE;
  930. ptrm->dwCurLine = ptrm->dwCurChar = 0;
  931. // if (ui.nScrollRow > 0)
  932. {
  933. dwWriteCoord.X = 0; dwWriteCoord.Y = 0;
  934. FillConsoleOutputCharacter( pwi->hOutput, 'E',
  935. ( pwi->sbi.dwSize.X ) * ( pwi->sbi.dwSize.Y ), dwWriteCoord,
  936. &dwNumWritten );
  937. ui.nScrollRow = 0;
  938. }
  939. ptrm->fEsc = 0;
  940. }
  941. static void
  942. ClearLine(WI *pwi, TRM *ptrm, DWORD dwType)
  943. {
  944. DWORD dwStart;
  945. DWORD cch;
  946. COORD dwWriteCoord;
  947. DWORD dwNumWritten;
  948. if (dwType <= fdwEntireLine)
  949. {
  950. ptrm->fInverse = FALSE;
  951. /* Set starting point and # chars to clear
  952. *
  953. * fdwCursorToEOL (0) = from cursor to end of line (inclusive)
  954. * fdwBOLToCursor (1) = from beginning of line to cursor (inclusive)
  955. * fdwEntireLine (2) = entire line
  956. */
  957. dwStart = (dwType == fdwCursorToEOL) ? ptrm->dwCurChar : 0;
  958. cch = (dwType == fdwBOLToCursor)
  959. ? ptrm->dwCurChar+1 : ui.dwMaxCol-dwStart;
  960. dwWriteCoord.X = (short)(dwStart-ui.nScrollCol);
  961. dwWriteCoord.Y = (short)(ptrm->dwCurLine-ui.nScrollRow);
  962. FillConsoleOutputCharacter( pwi->hOutput,
  963. ' ',
  964. cch,
  965. dwWriteCoord,
  966. &dwNumWritten );
  967. FillConsoleOutputAttribute( pwi->hOutput, pwi->sbi.wAttributes,
  968. cch, dwWriteCoord, &dwNumWritten );
  969. }
  970. ptrm->fEsc = 0;
  971. }
  972. static void
  973. SetMargins(TRM* ptrm, DWORD dwMarginTop, DWORD dwMarginBottom )
  974. {
  975. if( dwMarginTop > 0 )
  976. {
  977. ptrm->dwScrollTop = dwMarginTop - 1;
  978. }
  979. if( dwMarginBottom <= ui.dwMaxRow )
  980. {
  981. ptrm->dwScrollBottom = dwMarginBottom ;
  982. }
  983. }
  984. #define MAX_VTNT_BUF_SIZE 81920
  985. #define MAX_ROWS 300
  986. #define MAX_COLS 300
  987. static int dwCurBufSize = 0;
  988. static UCHAR szBuffer[MAX_VTNT_BUF_SIZE];
  989. BOOL bDoVtNTFirstTime = 1;
  990. BOOL
  991. DoVTNTOutput( WI* pwi, TRM* ptrm, int cbTermOut, UCHAR* pchTermOut )
  992. {
  993. COORD coDest = { 0, 0 };
  994. CHAR_INFO *pCharInfo;
  995. int dwRequire;
  996. VTNT_CHAR_INFO* pOutCharInfo;
  997. CONSOLE_SCREEN_BUFFER_INFO csbInfo;
  998. CHAR pTmp[4];
  999. DWORD dwWritten = 0;
  1000. RestoreWindowCoordinates( );
  1001. do
  1002. {
  1003. // we should wait atleast until we get the whole VTNT_CHAR_INFO struct.
  1004. if ( (cbTermOut + dwCurBufSize) < sizeof(VTNT_CHAR_INFO) )
  1005. {
  1006. if( bDoVtNTFirstTime )
  1007. {
  1008. //This hack is meant to work well with SUN.
  1009. //This is necessary because SUN accepts to talk in VTNT but
  1010. //sends out vt100/ansi
  1011. bDoVtNTFirstTime = 0;
  1012. if( !strncmp( ( CHAR * )pchTermOut,"\r\n\r\nSunOS ", 10 ) )
  1013. {
  1014. return FALSE;
  1015. }
  1016. }
  1017. // we copy all the data that we are called with.
  1018. if(MAX_VTNT_BUF_SIZE > dwCurBufSize+cbTermOut)
  1019. {
  1020. //copy maximum 'n' bytes where 'n' is the available buffer size
  1021. memcpy(szBuffer + dwCurBufSize, pchTermOut, cbTermOut);
  1022. dwCurBufSize += cbTermOut;
  1023. }
  1024. SaveCurrentWindowCoords();
  1025. return TRUE;
  1026. }
  1027. if ( dwCurBufSize == 0 )
  1028. pOutCharInfo = (VTNT_CHAR_INFO*) pchTermOut;
  1029. else
  1030. {
  1031. if ( dwCurBufSize < sizeof(VTNT_CHAR_INFO) )
  1032. {
  1033. memcpy(szBuffer + dwCurBufSize, pchTermOut, sizeof(VTNT_CHAR_INFO) - dwCurBufSize );//no overflow. Check already present.
  1034. cbTermOut -= (sizeof(VTNT_CHAR_INFO) - dwCurBufSize);
  1035. pchTermOut += (sizeof(VTNT_CHAR_INFO) - dwCurBufSize);
  1036. dwCurBufSize = sizeof(VTNT_CHAR_INFO);
  1037. }
  1038. pOutCharInfo = (VTNT_CHAR_INFO *) szBuffer;
  1039. }
  1040. if( pOutCharInfo->coSizeOfData.X > MAX_COLS || pOutCharInfo->coSizeOfData.X < 0 )
  1041. return FALSE;
  1042. if( pOutCharInfo->coSizeOfData.Y > MAX_ROWS || pOutCharInfo->coSizeOfData.Y < 0 )
  1043. return FALSE;
  1044. dwRequire = sizeof(VTNT_CHAR_INFO) +
  1045. pOutCharInfo->coSizeOfData.X * pOutCharInfo->coSizeOfData.Y * sizeof(CHAR_INFO);
  1046. if( dwRequire > MAX_VTNT_BUF_SIZE )
  1047. return FALSE;
  1048. // we also wait until we get all of the CHAR_INFO structures.
  1049. if ( (cbTermOut + dwCurBufSize) < dwRequire )
  1050. {
  1051. // we copy all the data that we are called with.
  1052. memcpy(szBuffer + dwCurBufSize, pchTermOut, cbTermOut);//no overflow. Check present.
  1053. dwCurBufSize += cbTermOut;
  1054. SaveCurrentWindowCoords();
  1055. return TRUE;
  1056. }
  1057. if ( dwCurBufSize == 0 )
  1058. {
  1059. pCharInfo = (CHAR_INFO *)(pchTermOut + sizeof(VTNT_CHAR_INFO));
  1060. // adjust the pointers for one more go around the while loop.
  1061. // we are consuming as much as we require
  1062. cbTermOut -= dwRequire;
  1063. pchTermOut += dwRequire;
  1064. }
  1065. else
  1066. {
  1067. if(MAX_VTNT_BUF_SIZE>dwRequire-dwCurBufSize)
  1068. {
  1069. memcpy(szBuffer + dwCurBufSize, pchTermOut, dwRequire - dwCurBufSize);
  1070. // adjust the pointers for one more go around the while loop.
  1071. // we are consuming only what we require which is dwRequire - dwCurBufSize.
  1072. cbTermOut -= (dwRequire - dwCurBufSize);
  1073. pchTermOut += (dwRequire - dwCurBufSize);
  1074. pCharInfo = (CHAR_INFO *)(szBuffer + sizeof(VTNT_CHAR_INFO));
  1075. }
  1076. }
  1077. if ( !GetConsoleScreenBufferInfo( pwi->hOutput, &csbInfo ) )
  1078. {
  1079. csbInfo.srWindow.Top = csbInfo.srWindow.Bottom = 0;
  1080. csbInfo.srWindow.Left = csbInfo.srWindow.Right = 0;
  1081. }
  1082. if( FGetCodeMode(eCodeModeFarEast) )
  1083. {
  1084. //Last line is meant for IME status
  1085. csbInfo.srWindow.Bottom--;
  1086. }
  1087. //Update cursor Position
  1088. pOutCharInfo->coCursorPos.Y += csbInfo.srWindow.Top ;
  1089. pOutCharInfo->coCursorPos.X += csbInfo.srWindow.Left;
  1090. //check if there is data
  1091. if( !( pOutCharInfo->coSizeOfData.X == 0 && pOutCharInfo->coSizeOfData.Y == 0 ))
  1092. {
  1093. //See if we have to scroll
  1094. //csbi.wAttributes is filled by v2 server with following meaning
  1095. //When a scrolling case is detected, this is set to 1.
  1096. if( pOutCharInfo->csbi.wAttributes == ABSOLUTE_COORDS )
  1097. {
  1098. //No scroling at all
  1099. //Update rectangle to write to
  1100. pOutCharInfo->srDestRegion.Top += csbInfo.srWindow.Top ;
  1101. pOutCharInfo->srDestRegion.Left += csbInfo.srWindow.Left;
  1102. pOutCharInfo->srDestRegion.Right += csbInfo.srWindow.Left;
  1103. pOutCharInfo->srDestRegion.Bottom += csbInfo.srWindow.Top;
  1104. }
  1105. if( pOutCharInfo->csbi.wAttributes == RELATIVE_COORDS )
  1106. {
  1107. if( pOutCharInfo->srDestRegion.Left > 0 && pOutCharInfo->coSizeOfData.Y == 1 &&
  1108. pOutCharInfo->srDestRegion.Top < csbInfo.srWindow.Bottom - csbInfo.srWindow.Top + 1)
  1109. {
  1110. //This condition is for VTNT stream mode.
  1111. //Append to the last row
  1112. pOutCharInfo->srDestRegion.Top = csbInfo.srWindow.Bottom;
  1113. pOutCharInfo->srDestRegion.Left += csbInfo.srWindow.Left;
  1114. pOutCharInfo->srDestRegion.Right += pOutCharInfo->coSizeOfData.X - 1;
  1115. pOutCharInfo->srDestRegion.Bottom = csbInfo.srWindow.Bottom;
  1116. //Update cursor Position
  1117. pOutCharInfo->coCursorPos.Y = csbInfo.srWindow.Bottom;
  1118. }
  1119. else if( csbInfo.srWindow.Bottom + pOutCharInfo->coSizeOfData.Y > csbInfo.dwSize.Y - 1 )
  1120. {
  1121. //need to scroll the buffer itself
  1122. SMALL_RECT srRect = { 0, 0, 0, 0 };
  1123. COORD coDestination = { 0, 0 };
  1124. CHAR_INFO cInfo;
  1125. srRect.Top = pOutCharInfo->coSizeOfData.Y;
  1126. srRect.Left = 0;
  1127. srRect.Bottom = csbInfo.dwSize.Y - 1;
  1128. srRect.Right = csbInfo.dwSize.X - 1;
  1129. if( FGetCodeMode(eCodeModeFarEast) )
  1130. {
  1131. //Last line is meant for IME status
  1132. srRect.Bottom++;
  1133. }
  1134. cInfo.Char.UnicodeChar = L' ';
  1135. cInfo.Attributes = csbInfo.wAttributes;
  1136. //We have to scroll screen buffer. we need space to write.
  1137. ScrollConsoleScreenBuffer( pwi->hOutput,
  1138. &srRect,
  1139. NULL,
  1140. coDestination,
  1141. &cInfo );
  1142. pOutCharInfo->srDestRegion.Top = csbInfo.srWindow.Bottom - pOutCharInfo->coSizeOfData.Y + 1;
  1143. pOutCharInfo->srDestRegion.Bottom = csbInfo.srWindow.Bottom;
  1144. //Update cursor Position
  1145. pOutCharInfo->coCursorPos.Y = csbInfo.srWindow.Bottom;
  1146. }
  1147. else
  1148. {
  1149. //Update rectangle to write to
  1150. //Append to the bootom of the screen
  1151. pOutCharInfo->srDestRegion.Top = csbInfo.srWindow.Bottom + 1 ;
  1152. pOutCharInfo->srDestRegion.Left = csbInfo.srWindow.Left;
  1153. pOutCharInfo->srDestRegion.Right = pOutCharInfo->coSizeOfData.X - 1;
  1154. pOutCharInfo->srDestRegion.Bottom = ( csbInfo.srWindow.Bottom + 1 ) +
  1155. ( pOutCharInfo->coSizeOfData.Y - 1 );
  1156. //Update cursor Position
  1157. pOutCharInfo->coCursorPos.Y = csbInfo.srWindow.Bottom + pOutCharInfo->coSizeOfData.Y;
  1158. if( FGetCodeMode(eCodeModeFarEast) )
  1159. {
  1160. if( csbInfo.srWindow.Bottom + pOutCharInfo->coSizeOfData.Y < csbInfo.dwSize.Y )
  1161. {
  1162. csbInfo.srWindow.Top += pOutCharInfo->coSizeOfData.Y;
  1163. csbInfo.srWindow.Bottom += pOutCharInfo->coSizeOfData.Y;
  1164. }
  1165. else
  1166. {
  1167. SHORT sDiff = csbInfo.srWindow.Bottom - csbInfo.srWindow.Top;
  1168. csbInfo.srWindow.Bottom = csbInfo.dwSize.Y - 1;
  1169. csbInfo.srWindow.Top = csbInfo.srWindow.Bottom - sDiff;
  1170. }
  1171. }
  1172. }
  1173. }
  1174. WriteConsoleOutput( pwi->hOutput, pCharInfo,
  1175. pOutCharInfo->coSizeOfData, coDest,
  1176. &pOutCharInfo->srDestRegion );
  1177. if( ui.bLogging )
  1178. {
  1179. WriteCharInfoToLog( pCharInfo, pOutCharInfo->coSizeOfData );
  1180. }
  1181. }
  1182. if( FGetCodeMode(eCodeModeFarEast) )
  1183. {
  1184. //Last line is meant for IME status
  1185. csbInfo.srWindow.Bottom ++;
  1186. SetConsoleWindowInfo( pwi->hOutput, TRUE, &csbInfo.srWindow );
  1187. }
  1188. SetConsoleCursorPosition( pwi->hOutput, pOutCharInfo->coCursorPos );
  1189. // reset for the new loop.
  1190. dwCurBufSize = 0;
  1191. } while ( cbTermOut >= 0 );
  1192. // cbTermOut is negative, that is impossible.
  1193. return FALSE;
  1194. }
  1195. void SetGraphicRendition( WI *pwi, TRM *ptrm, INT iIndex,
  1196. DWORD rgdwGraphicRendition[] )
  1197. {
  1198. INT i=0;
  1199. for( i=0; i<= iIndex; i++ )
  1200. {
  1201. switch ( rgdwGraphicRendition[i] )
  1202. {
  1203. case 40:
  1204. //black
  1205. SetBackgroundColor( pwi, 0 );
  1206. break;
  1207. case 41:
  1208. //red
  1209. SetBackgroundColor( pwi, FOREGROUND_RED );
  1210. break;
  1211. case 42:
  1212. //green
  1213. SetBackgroundColor( pwi, FOREGROUND_GREEN );
  1214. break;
  1215. case 43:
  1216. SetBackgroundColor( pwi, ( FOREGROUND_RED |
  1217. FOREGROUND_GREEN ) );
  1218. break;
  1219. case 44:
  1220. SetBackgroundColor( pwi, FOREGROUND_BLUE );
  1221. break;
  1222. case 45:
  1223. SetBackgroundColor( pwi, ( FOREGROUND_RED |
  1224. FOREGROUND_BLUE ) );
  1225. break;
  1226. case 46:
  1227. SetBackgroundColor( pwi, ( FOREGROUND_BLUE |
  1228. FOREGROUND_GREEN ) );
  1229. break;
  1230. case 47:
  1231. //white
  1232. SetBackgroundColor( pwi, ( FOREGROUND_RED |
  1233. FOREGROUND_BLUE | FOREGROUND_GREEN ) );
  1234. break;
  1235. case 30:
  1236. //black
  1237. SetForegroundColor( pwi, 0 );
  1238. break;
  1239. case 31:
  1240. //red
  1241. SetForegroundColor( pwi, FOREGROUND_RED );
  1242. break;
  1243. case 32:
  1244. //green
  1245. SetForegroundColor( pwi, FOREGROUND_GREEN );
  1246. break;
  1247. case 33:
  1248. SetForegroundColor( pwi, ( FOREGROUND_RED |
  1249. FOREGROUND_GREEN ) );
  1250. break;
  1251. case 34:
  1252. SetForegroundColor( pwi, FOREGROUND_BLUE );
  1253. break;
  1254. case 35:
  1255. SetForegroundColor( pwi, ( FOREGROUND_RED |
  1256. FOREGROUND_BLUE ) );
  1257. break;
  1258. case 36:
  1259. SetForegroundColor( pwi, ( FOREGROUND_BLUE |
  1260. FOREGROUND_GREEN ) );
  1261. break;
  1262. case 37:
  1263. //white
  1264. SetForegroundColor( pwi, ( FOREGROUND_RED |
  1265. FOREGROUND_BLUE | FOREGROUND_GREEN ) );
  1266. break;
  1267. case 21:
  1268. case 22:
  1269. BoldOff( pwi );
  1270. break;
  1271. case 24: // Underscore off
  1272. break;
  1273. case 25: // Blink off
  1274. break;
  1275. case 27: // Negative (reverse) image off
  1276. if( ptrm->fInverse == TRUE )
  1277. {
  1278. ptrm->fInverse = FALSE;
  1279. NegativeImageOff( pwi );
  1280. }
  1281. break;
  1282. case 10:
  1283. break;
  1284. case 11:
  1285. break;
  1286. case 12:
  1287. break;
  1288. case 8:
  1289. break;
  1290. case 7: // Negative (reverse) image; reverse video
  1291. ptrm->fInverse = TRUE;
  1292. NegativeImageOn( pwi );
  1293. break;
  1294. case 5: // Blink
  1295. //have to wait until WIN32 console provides
  1296. //a way to do this :-(
  1297. break;
  1298. case 4: // Underscore / underline
  1299. //have to wait until WIN32 console provides
  1300. //a way to do this :-(
  1301. break;
  1302. case 2: // low video
  1303. BoldOff( pwi );
  1304. break;
  1305. case 1: // Bold or increased intensity; high video
  1306. BoldOn( pwi );
  1307. break;
  1308. case 0: // Attributes Off; normal video
  1309. if( ptrm->fInverse == TRUE )
  1310. {
  1311. ptrm->fInverse = FALSE;
  1312. NegativeImageOff( pwi );
  1313. //BoldOff( pwi );
  1314. }
  1315. BoldOff( pwi );
  1316. ResetColors( pwi );
  1317. break;
  1318. default:
  1319. //ptrm->fInverse = FALSE;
  1320. if( ptrm->fInverse == TRUE )
  1321. {
  1322. ptrm->fInverse = FALSE;
  1323. NegativeImageOff( pwi );
  1324. //BoldOff( pwi );
  1325. }
  1326. BoldOff( pwi );
  1327. break;
  1328. }
  1329. }
  1330. return;
  1331. }
  1332. /* This is meant only for FAREAST IME. In this case, there will be one blank
  1333. * line at the bottom whose presence is not known to the server. i.e; During
  1334. * NAWS we gave window size - 1 as our actual size. To maintain this during
  1335. * scrolling we need to write extra blank line. When the cursor is at the
  1336. * bottom, if we try to write one char just down the buffer, we get a blank line
  1337. * Otherwise, no effect.*/
  1338. void WriteOneBlankLine( HANDLE hOutput, WORD wRow )
  1339. {
  1340. COORD coWrite = { 0, 0 };
  1341. if( wRow <= gwi.trm.dwScrollBottom )
  1342. {
  1343. coWrite.Y = wRow;
  1344. SetConsoleCursorPosition( hOutput, coWrite );
  1345. }
  1346. }
  1347. /*///////////////////////////////////////////////////////////////////////////////
  1348. VT100 NOTES:
  1349. This info was obatined from
  1350. http://www.cs.utk.edu/~shuford/terminal/vt100_codes_news.txt
  1351. The following describes information needed for controlling the VT100 terminal
  1352. from a remote computer. All of the information was derived from the VT100
  1353. user's manual, Programmer's Information section. Full documentation can be
  1354. obtain from DIGITAL'S Accessory and Supplies Group.
  1355. [The notation <ESC> denotes a single ASCII Escape character, 1Bx.]
  1356. ANSI mode w/cursor ANSI mode w/cursor
  1357. Cursor Key VT52 mode key mode reset key mode set
  1358. --------------------------------------------------------------------------
  1359. UP <ESC>A <ESC>[A <ESC>OA
  1360. DOWN <ESC>B <ESC>[B <ESC>OB
  1361. RIGHT <ESC>C <ESC>[C <ESC>OC
  1362. LEFT <ESC>D <ESC>[D <ESC>OD
  1363. --------------------------
  1364. | Terminal Control Commands |
  1365. --------------------------
  1366. Control Characters
  1367. ------------------
  1368. look for details in code below
  1369. The VT100 is an upward and downward software-compatible terminal;
  1370. that is, previous Digital video terminals have Digital's private standards
  1371. for control sequences. The American National Standards Institute has since
  1372. standardized escape and control sequences in terminals in documents X3.41-1974
  1373. and X3.64-1977.
  1374. The VT100 is compatible with both the previous Digital standard and
  1375. ANSI standards. Customers may use existing Digital software designed around
  1376. the VT52 or new VT100 software. The VT100 has a "VT52 compatible" mode in
  1377. which the VT100 responds to control sequences like a VT52. In this mode, most
  1378. of the new VT100 features cannot be used.
  1379. Throughout this document references will be made to "VT52 mode" or
  1380. "ANSI mode". These two terms are used to indicate the VT100's software
  1381. compatibility.
  1382. NOTE: The ANSI standards allow the manufacturer flexibility in implementing
  1383. each function. This document describes how the VT100 will respond to the
  1384. implemented ANSI central function.
  1385. NOTE: ANSI standards may be obtained by writing:
  1386. American National Standards Institute
  1387. Sales Department
  1388. 1430 Broadway
  1389. New York, NY, 10018
  1390. [July 1995 update: current address for ordering ANSI standards:
  1391. American National Standards Institute
  1392. Attn: Customer Service
  1393. 11 West 42nd Street
  1394. New York, NY 10036
  1395. USA
  1396. ANSI's fax number for placing publication orders is +1 212/302-1286.]
  1397. [Further update, from Tim Lasko <lasko@regent.enet.dec.com>:
  1398. "ANSI X3.64 has been withdrawn in favor of the more complete and
  1399. updated ISO standard 6429. (ECMA-48 is equivalent to ISO DP6429,
  1400. last I checked.) X3.64 has been out of date for some time. At the
  1401. time when I was on the relevant committee, we couldn't get enough
  1402. resources to really do a good job of updating the standard.
  1403. Later, the proposal came up to withdraw it in favor of the ISO
  1404. standard.]
  1405. Definitions
  1406. -----------
  1407. Control Sequence Introducer (CSI) - An escape sequence that provides
  1408. supplementary controls and is itself a prefix affecting the
  1409. interpretation of a limited number of contiguous characters.
  1410. In the VT100, the CSI is: <ESC>[
  1411. Parameter: (1) A string of zero or more decimal characters which
  1412. represent a single value. Leading zeros are ignored. The
  1413. decimal characters have a range of 0 (060) to 9 (071).
  1414. (2) The value so represented.
  1415. Numeric Parameter: A parameter that represents a number, designated by
  1416. Pn.
  1417. Selective Parameter: A parameter that selects a subfunction from a
  1418. specified set of subfunctions, designated by Ps. In general, a
  1419. control sequence with more than one selective parameter causes
  1420. the same effect as several control sequences, each with one
  1421. selective parameter, e.g., CSI Psa; Psb; Psc F is identical to
  1422. CSI Psa F CSI Psb F CSI Psc F.
  1423. Parameter String: A string of parameters separated by a semicolon.
  1424. Default: A function-dependent value that is assumed when no explicit
  1425. value, or a value of 0, is specified.
  1426. Final character: A character whose bit combination terminates an
  1427. escape or control sequence.
  1428. EXAMPLE: Control sequence to turn off all character attributes, then
  1429. turn on underscore and blink attributes (SGR). <ESC>[0;4;5m
  1430. Sequence:
  1431. Delimiters
  1432. / \
  1433. / \
  1434. | |
  1435. \ / \ /
  1436. <ESC>[ 0 ; 4 ; 5 m
  1437. ^^^^^^ ^ ^ ^ ^
  1438. |||||| | | | |
  1439. \||||/ \ | / +------Final character
  1440. \||/ \ | /
  1441. CSI Selective
  1442. Parameters
  1443. The octal representation of this string is:
  1444. 033 0133 060 073 064 073 065 0155
  1445. <ESC> [ 0 ; 4 ; 5 m
  1446. Alternate sequences which will accomplish the same thing:
  1447. 1) <ESC>[;4;m
  1448. 2) <ESC>[m
  1449. <ESC>[4m
  1450. <ESC>[5m
  1451. 3) <ESC>[0;04;005m
  1452. Control Sequences
  1453. -----------------
  1454. All of the following control sequences are transmitted from the Host to
  1455. VT100 unless otherwise noted. All of the control sequences are a subset of
  1456. those defined in ANSI X 3.64 1977 and ANSI X 3.41 1974.
  1457. The following text conforms to these formatting conventions:
  1458. 1) Control characters are designated by angle brackets (e.g.
  1459. the Escape character is <ESC>).
  1460. 2) Parameters are indicated by curly braces.
  1461. 3) Parameter types usually are indicated as one of:
  1462. {Pn} A string of digits representing a numerical
  1463. value.
  1464. {Ps} A character that selects an item from a list.
  1465. {a-z} Any lowercase sequence of one44 or more
  1466. characters in braces represent a value to be
  1467. entered (as in {Pn}), and the name in the
  1468. braces will be referred to in explanatory text.
  1469. 4) Spaces in the control sequence are present for clarity and
  1470. may be omitted. Spaces which are required will be
  1471. surrounded by single quotes: ' '.
  1472. 5) All other characters are literals.
  1473. look for details in code below
  1474. CPR Cursor Position Report VT100 to Host
  1475. <ESC>[ {Pn} ; {Pn} R Default Value: 1
  1476. The CPR sequence reports the active position by means of the
  1477. parameters. This sequence has two parameter values, the first
  1478. specifying the line and the second specifying the column. The default
  1479. condition with no parameters present, or parameters of 0, is equivelent
  1480. to a cursor at home position.
  1481. The numbering of the lines depends upon the state of the Origin Mode
  1482. (DECOM).
  1483. This control sequence is sent in reply to a device status report (DSR)
  1484. command sent from the host.
  1485. CUB
  1486. CUD
  1487. CUF
  1488. CUP
  1489. CUU
  1490. DA
  1491. "I doubt if a lot of these DEC commands work..a few do.. (like scroll areas)"
  1492. I think that this guy means that he doubts whether they even work on a real
  1493. vt100
  1494. DECALN
  1495. DECANM
  1496. DECARM
  1497. DECAWM
  1498. DECCKM
  1499. DECCOLM
  1500. DECDHL
  1501. DECDWL
  1502. DECID
  1503. DECINLM
  1504. DECKPAM
  1505. DECKNPNM
  1506. DECLL
  1507. DECOM
  1508. DECRC
  1509. DECREPTPARM Report Terminal Parameters VT100 to Host
  1510. <ESC>[ {sol} ; {par} ; {nbits} ; {xspd} ; {rspd} ; {cmul} ; {flags} x
  1511. This sequence is generated by the VT100 to notify the host of the
  1512. status of selected terminal parameters. The status sequence may be
  1513. sent when requested by the host (via DECREQTPARM) or at the terminal's
  1514. discretion. On power up or reset, the VT100 is inhibited from sending
  1515. unsolicited reports.
  1516. The meanings of the sequence paramters are:
  1517. Parameter Value Meaning
  1518. ------------------------------------------------------------------
  1519. {sol} 1 This message is a report.
  1520. 2 This message is a report, and the terminal is
  1521. only reporting on request.
  1522. {par} 1 No parity set
  1523. 4 Parity set and odd
  1524. 5 Parity set and even
  1525. {nbits} 1 8 bits per character
  1526. 2 7 bits per character
  1527. {xspd} 0 Speed set to 50 bps
  1528. -and- 8 Speed set to 75 bps
  1529. {rspd} 16 Speed set to 110 bps
  1530. 24 Speed set to 134.5 bps
  1531. {xspd}= 32 Speed set to 150 bps
  1532. Transmit 40 Speed set to 200 bps
  1533. Speed 48 Speed set to 300 bps
  1534. 56 Speed set to 600 bps
  1535. {rspd}= 64 Speed set to 1200 bps
  1536. Recieve 72 Speed set to 1800 bps
  1537. Speed 80 Speed set to 2000 bps
  1538. 88 Speed set to 2400 bps
  1539. 96 Speed set to 3600 bps
  1540. 104 Speed set to 4800 bps
  1541. 112 Speed set to 9600 bps
  1542. 120 Speed set tp 19200 bps
  1543. {cmul} 1 The bit rate multiplier is 16
  1544. {flags} 0-15 This value communicates the four switch values
  1545. in block 5 of SET-UP B, which are only visible
  1546. to the user when an STP option is installed.
  1547. DECREQTPARM
  1548. DECSC
  1549. DECSCLM
  1550. DECSCNM
  1551. DECSTBM
  1552. DECSWL
  1553. DECTST
  1554. DSR
  1555. ED
  1556. EL
  1557. HTS
  1558. HVP
  1559. IND
  1560. LNM
  1561. MODES The Following is a list of VT100 modes which may be changed with Set
  1562. Mode (SM) and Reset Mode (RM) controls.
  1563. ANSI Specified Modes
  1564. Parameter Mnemonic Function
  1565. ------------------------------------------------------------------
  1566. 0 Error (Ignored)
  1567. 20 LNM Line Feed/New Line Mode
  1568. DEC Private Modes
  1569. If the first character in the parameter string is ? (077), the
  1570. parameters are interpreted as DEC private parameters according to the
  1571. following:
  1572. Parameter Mnemonic Function
  1573. -------------------------------------------------------------------
  1574. 0 Error (Ignored)
  1575. 1 DECCKM Cursor Key
  1576. 2 DECANM ANSI/VT52
  1577. 3 DECCOLM Column
  1578. 4 DECSCLM Scrolling
  1579. 5 DECSCNM Screen
  1580. 6 DECOM Origin
  1581. 7 DECAWM Auto Wrap
  1582. 8 DECARM Auto Repeat
  1583. 9 DECINLM Interlace
  1584. Any other parameter values are ignored.
  1585. The following modes, which are specified in the ANSI standard, may be
  1586. considered to be permanently set, permanently reset, or not applicable,
  1587. as noted.
  1588. Mnemonic Function State
  1589. ------------------------------------------------------
  1590. CRM Control Representation Reset
  1591. EBM Editing Boundary Reset
  1592. ERM Erasure Set
  1593. FEAM Format Effector Action Reset
  1594. FETM Format Effector Transfer Reset
  1595. GATM Guarded Area Transfer NA
  1596. HEM Horizontal Editing NA
  1597. IRM Insertion-replacement Reset
  1598. KAM Keyboard Action Reset
  1599. MATM Multiple area transfer NA
  1600. PUM Positioning Unit Reset
  1601. SATM Selected Area Transfer NA
  1602. SRTM Status Reporting Transfer Reset
  1603. TSM Tabulation Stop Reset
  1604. TTM Transfer Termination NA
  1605. VEM Vertical Editing NA
  1606. NEL
  1607. RI
  1608. RIS
  1609. RM
  1610. SCS
  1611. SGR
  1612. SM
  1613. TBC
  1614. *////////////////////////////////////////////////////////////////////////////////
  1615. /*///////////////////////////////////////////////////////////////////////////////
  1616. DoIBMANSIOutput
  1617. Purpose:
  1618. Interpret any IBM ANSI escape sequences in the output stream
  1619. and perform the correct terminal emulation in response.
  1620. Normal text is just output to the screen.
  1621. Changes for v4.1:
  1622. - now support Clear to end of display ESC[J
  1623. - better support for the FTCU machine by "eating" certain
  1624. unknown escape sequences, namely ESC)0 and ESC[?7h.
  1625. *////////////////////////////////////////////////////////////////////////////////
  1626. void
  1627. DoIBMANSIOutput( WI *pwi, TRM *ptrm, DWORD cbTermOut, UCHAR *pchTermOut )
  1628. {
  1629. DWORD ich;
  1630. DWORD i = 0;
  1631. DWORD dwDECMode = 0;
  1632. UCHAR *pchT;
  1633. COORD cp;
  1634. COORD dwSize, dwMaximumWindowSize;
  1635. DWORD dwSavedCurPos;
  1636. CHAR *pchTemp = NULL;
  1637. //* suppress cursor on screen
  1638. ptrm->fHideCursor = TRUE;
  1639. ptrm->cTilde = 0;
  1640. RestoreWindowCoordinates( );
  1641. CheckForChangeInWindowSize( );
  1642. for( ich = 0, pchT = pchTermOut; ich < cbTermOut; ++ich, ++pchT )
  1643. {
  1644. if( ( !FGetCodeMode(eCodeModeFarEast) && !FGetCodeMode(eCodeModeVT80))
  1645. && IS_EXTENDED_CHAR( *pchT ) )
  1646. {
  1647. DWORD dwNumWritten;
  1648. COORD dwCursorPosition;
  1649. FlushBuffer( pwi, ptrm );
  1650. dwCursorPosition.X = ( short ) ( ptrm->dwCurChar - ui.nScrollCol );
  1651. dwCursorPosition.Y = ( short ) ( ptrm->dwCurLine - ui.nScrollRow);
  1652. ptrm->dwCurChar++;
  1653. SetConsoleCursorPosition( pwi->hOutput, dwCursorPosition );
  1654. WriteConsoleA( pwi->hOutput, (CHAR *)pchT, 1, &dwNumWritten, NULL );
  1655. FillConsoleOutputAttribute( pwi->hOutput, pwi->sbi.wAttributes,
  1656. 1, dwCursorPosition, &dwNumWritten );
  1657. if( ui.bLogging )
  1658. {
  1659. g_bIsToBeLogged = TRUE; //There is data to be logged
  1660. }
  1661. continue;
  1662. }
  1663. // process character
  1664. switch ( ptrm->fEsc )
  1665. {
  1666. case 0: // normal processing
  1667. /*
  1668. Control Characters
  1669. ------------------
  1670. The control characters recognized by the VT100 are listed below. All
  1671. other control characters cause no action to be taken.
  1672. Control characters (codes 00 - 037 inclusive) are specifically
  1673. excluded from the control sequence syntax, but may be embedded within a
  1674. control sequence. Embedded control characters are executed as soon as
  1675. they are encountered by the VT100. The processing of the control
  1676. sequence then continues with the next character recieved. The exceptions
  1677. are: if the <ESC> character occurs, the current control sequence is
  1678. aborted, and a new one commences beginning with the <ESC> just recieved.
  1679. If the character <CAN> (030) or the character <SUB> (032) occurs, the
  1680. current control sequence is aborted. The ability to embed control
  1681. characters allows the synchronization characters XON and XOFF to be
  1682. interpreted properly without affecting the control sequence.
  1683. detailed comments below are in the format
  1684. // Control Character; Octal Code; Action Taken
  1685. */
  1686. switch( *pchT )
  1687. {
  1688. case 0x1B: // ESC?
  1689. //<ESC>; 0033; Introduces a control sequence.
  1690. ptrm->fEsc = 1;
  1691. break;
  1692. case 0:
  1693. //<NUL>; 0000; Ignored on input, not stored in buffer
  1694. break;
  1695. case 0x05 :
  1696. //<ENQ>; 0005; Transmit ANSWERBACK message
  1697. break;
  1698. case 0x08: // Backspace
  1699. //<BS>; 0010; Move cursor to the left one position, unless it is
  1700. //at the left margin, in which case no action is taken.
  1701. if( ptrm->dwCurChar > 0 )
  1702. {
  1703. --ptrm->dwCurChar;
  1704. }
  1705. FlushBuffer( pwi, ptrm );
  1706. break;
  1707. case 0x07:
  1708. //<BEL>; 0007; Sound bell
  1709. MessageBeep( ( UINT ) (~0) );
  1710. break;
  1711. case 0x09: // TAB
  1712. //<HT>; 0011; Move cursor to the next tab stop, or to the right
  1713. //margin if no further tabs are set.
  1714. dwSavedCurPos = ptrm->dwCurChar;
  1715. if( g_iHTS )
  1716. {
  1717. int x=0;
  1718. while( x < g_iHTS )
  1719. {
  1720. if( g_rgdwHTS[ x ] > ptrm->dwCurChar
  1721. && g_rgdwHTS[ x ] != -1 )
  1722. {
  1723. break;
  1724. }
  1725. x++;
  1726. }
  1727. while( x < g_iHTS && g_rgdwHTS[ x ] == -1 )
  1728. {
  1729. x++;
  1730. }
  1731. if( x < g_iHTS )
  1732. {
  1733. ptrm->dwCurChar = g_rgdwHTS[ x ];
  1734. }
  1735. else
  1736. {
  1737. ptrm->dwCurChar += TAB_LENGTH;
  1738. ptrm->dwCurChar -= ptrm->dwCurChar % TAB_LENGTH;
  1739. }
  1740. }
  1741. else
  1742. {
  1743. ptrm->dwCurChar += TAB_LENGTH;
  1744. ptrm->dwCurChar -= ptrm->dwCurChar % TAB_LENGTH;
  1745. }
  1746. if( ui.fDebug & fdwTABtoSpaces )
  1747. {
  1748. if( ptrm->cchBufferText == 0 )
  1749. {
  1750. SetBufferStart( ptrm );
  1751. }
  1752. if( FAddTabToBuffer( ptrm, ptrm->dwCurChar-dwSavedCurPos ) )
  1753. {
  1754. FlushBuffer( pwi, ptrm );
  1755. }
  1756. }
  1757. if( !( ui.fDebug & fdwTABtoSpaces ) )
  1758. {
  1759. FlushBuffer(pwi, ptrm);
  1760. }
  1761. if( ptrm->dwCurChar >= ui.dwMaxCol )
  1762. {
  1763. if( ui.fDebug & fdwTABtoSpaces )
  1764. {
  1765. FlushBuffer( pwi, ptrm );
  1766. }
  1767. ptrm->dwCurChar = 0;
  1768. NewLine( pwi, ptrm );
  1769. }
  1770. break;
  1771. case '\r': // Carriage Return
  1772. //<CR>; 0015 ;Move the cursor to the left margin of the current
  1773. //line.
  1774. ptrm->dwCurChar = 0;
  1775. ptrm->fFlushToEOL = FALSE;
  1776. FlushBuffer( pwi, ptrm );
  1777. break;
  1778. case 11:
  1779. //<VT>; 0013; Same as <LF>.
  1780. case 12: // Form feed
  1781. //<FF>; 0014 ;Same as <LF>.
  1782. case '\n': //Line Feed
  1783. //<LF>; 0012; Causes either a line feed or new line operation
  1784. //(See new line mode.)
  1785. if( ptrm->fFlushToEOL )
  1786. {
  1787. ptrm->fLongLine = FALSE;
  1788. ptrm->fFlushToEOL = FALSE;
  1789. break;
  1790. }
  1791. if( ptrm->fLongLine )
  1792. {
  1793. ptrm->fLongLine = FALSE;
  1794. break;
  1795. }
  1796. FlushBuffer( pwi, ptrm );
  1797. NewLine( pwi, ptrm );
  1798. break;
  1799. case 0x0F:
  1800. //<SI>; 0017; Invoke the G0 character set, as selected by the <ESC>(
  1801. //sequence.
  1802. ptrm->currCharSet = 0; // 0 signifies G0
  1803. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  1804. {
  1805. if(FIsVT80(ptrm)) {
  1806. SetCharSet(ptrm,GRAPHIC_LEFT,ptrm->g0);
  1807. } else {
  1808. SetCharSet(ptrm,GRAPHIC_LEFT,rgchIBMAnsiChars);
  1809. }
  1810. break;
  1811. }
  1812. ASSERT(!(FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)));
  1813. switch( ptrm->G0 ) {
  1814. case '0' :
  1815. ptrm->puchCharSet = rgchSpecialGraphicsChars;
  1816. break;
  1817. case '1':
  1818. ptrm->puchCharSet = rgchNormalChars;
  1819. break;
  1820. case '2' :
  1821. ptrm->puchCharSet = rgchSpecialGraphicsChars;
  1822. break;
  1823. case 'A' :
  1824. ptrm->puchCharSet = rgchUKChars;
  1825. break;
  1826. case 'B' :
  1827. ptrm->puchCharSet = rgchNormalChars;
  1828. break;
  1829. default:
  1830. break;
  1831. }
  1832. break;
  1833. case 0x0E:
  1834. //<SO>; 0016; Invoke the G1 character set, as designated by the
  1835. //SCS control sequence.
  1836. ptrm->currCharSet = 1; // 1 signifies G1
  1837. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  1838. {
  1839. if(FIsVT80(ptrm)) {
  1840. SetCharSet(ptrm,GRAPHIC_LEFT,ptrm->g1);
  1841. } else {
  1842. SetCharSet(ptrm,GRAPHIC_LEFT,rgchGraphicsChars);
  1843. }
  1844. break;
  1845. }
  1846. ASSERT(!(FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)));
  1847. switch( ptrm->G1 ) {
  1848. case '0' :
  1849. ptrm->puchCharSet = rgchSpecialGraphicsChars;
  1850. break;
  1851. case '1':
  1852. ptrm->puchCharSet = rgchNormalChars;
  1853. break;
  1854. case '2' :
  1855. ptrm->puchCharSet = rgchSpecialGraphicsChars;
  1856. break;
  1857. case 'A' :
  1858. ptrm->puchCharSet = rgchUKChars;
  1859. break;
  1860. case 'B' :
  1861. ptrm->puchCharSet = rgchNormalChars;
  1862. break;
  1863. default:
  1864. break;
  1865. }
  1866. break;
  1867. case 0x8E:
  1868. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80) && FIsVT80(ptrm))
  1869. {
  1870. if( !(GetKanjiStatus(ptrm) & JIS_KANJI_CODE) &&
  1871. (FIsJISKanji(ptrm) || FIsJIS78Kanji(ptrm) ||
  1872. FIsEUCKanji(ptrm) || FIsDECKanji(ptrm) ) ) {
  1873. PushCharSet(ptrm,GRAPHIC_LEFT,ptrm->g2);
  1874. PushCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g2);
  1875. SetKanjiStatus(ptrm,SINGLE_SHIFT_2);
  1876. #ifdef DEBUG
  1877. wsprintf(rgchDbgBfr,"VT80 EUC/DEC/JIS SS2 Mode Enter\n");
  1878. OutputDebugString(rgchDbgBfr);
  1879. #endif /* DEBUG */
  1880. } else {
  1881. goto Fall_Through;
  1882. }
  1883. } else {
  1884. goto Fall_Through;
  1885. }
  1886. break;
  1887. case 0x8F:
  1888. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80) )
  1889. {
  1890. if( FIsVT80(ptrm) )
  1891. {
  1892. if( !(GetKanjiStatus(ptrm) & JIS_KANJI_CODE) &&
  1893. (FIsJISKanji(ptrm) || FIsJIS78Kanji(ptrm) ||
  1894. FIsEUCKanji(ptrm) || FIsDECKanji(ptrm) ) ) {
  1895. PushCharSet(ptrm,GRAPHIC_LEFT,ptrm->g3);
  1896. PushCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g3);
  1897. SetKanjiStatus(ptrm,SINGLE_SHIFT_3);
  1898. #ifdef DEBUG
  1899. wsprintf(rgchDbgBfr,"VT80 EUC/DEC/JIS SS3 Mode Enter\n");
  1900. OutputDebugString(rgchDbgBfr);
  1901. #endif /* DEBUG */
  1902. } else {
  1903. goto Fall_Through;
  1904. }
  1905. } else {
  1906. goto Fall_Through;
  1907. }
  1908. }
  1909. break;
  1910. case 0x1A:
  1911. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  1912. {
  1913. if (FIsACOSKanji(ptrm) && (ui.fAcosSupportFlag & fAcosSupport)) {
  1914. ptrm->fEsc = 7;
  1915. } else {
  1916. //goto Fall_Through;
  1917. break;
  1918. }
  1919. }
  1920. break;
  1921. case 0021:
  1922. //<DC1>; 0021; Causes terminal to resume transmission (XON).
  1923. break;
  1924. case 0023:
  1925. //<DC3>; 0023; Causes terminal to stop transmitting all codes
  1926. //except XOFF and XON (XOFF).
  1927. break;
  1928. // case 0032:
  1929. case 0030:
  1930. //<CAN>; 0030; If sent during a control sequence, the sequence is
  1931. //immediately terminated and not executed. It also causes the
  1932. //error character (checkerboard) to be displayed.
  1933. break;
  1934. case 0177:
  1935. //<DEL>; 0177; Ignored on input; not stored in buffer.
  1936. break;
  1937. case '~':
  1938. // optimization to detect ~~Begin TelXFer signature
  1939. ++ptrm->cTilde;
  1940. // fall through
  1941. default:
  1942. Fall_Through:
  1943. if ( ptrm->dwCurChar >= ui.dwMaxCol )
  1944. {
  1945. ptrm->dwCurChar = 0;
  1946. FlushBuffer( pwi, ptrm );
  1947. NewLine( pwi, ptrm );
  1948. ptrm->fLongLine = TRUE;
  1949. if( !FIsVTWrap( ptrm ))
  1950. {
  1951. ptrm->fFlushToEOL = TRUE;
  1952. }
  1953. }
  1954. if( ptrm->fFlushToEOL )
  1955. {
  1956. break;
  1957. }
  1958. ptrm->fLongLine = FALSE;
  1959. if( ptrm->cchBufferText == 0 )
  1960. {
  1961. SetBufferStart( ptrm );
  1962. }
  1963. if( FAddCharToBuffer( ptrm, ptrm->puchCharSet[*pchT] ))
  1964. {
  1965. FlushBuffer( pwi, ptrm );
  1966. }
  1967. /* For FE Incremantation was done in FAddCharToBuffer() */
  1968. if (!(FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)))
  1969. ( ptrm->dwCurChar) ++ ;
  1970. break;
  1971. }
  1972. break;
  1973. case 1: /* ESC entered, wait for [ */
  1974. //If there is some data to be flushed
  1975. if( ptrm->cchBufferText != 0 )
  1976. {
  1977. FlushBuffer(pwi, ptrm);
  1978. }
  1979. if (((*pchT) != '[') && ((*pchT) != '#'))
  1980. ptrm->fEsc = 0;
  1981. switch (*pchT)
  1982. {
  1983. case '1':
  1984. break;
  1985. case '2':
  1986. break;
  1987. case '7':
  1988. //
  1989. // DECSC
  1990. // Save cursor position, origin mode etc.
  1991. //
  1992. //DECSC Save Cursor (DEC Private)
  1993. //<ESC>7
  1994. //Causes the cursor position, graphic rendition, and character
  1995. //set to be saved. (See DECRC)
  1996. GetConsoleScreenBufferInfo( gwi.hOutput, &consoleBufferInfo );
  1997. ptrm->fSavedState = TRUE;
  1998. ptrm->dwSaveChar = ptrm->dwCurChar;
  1999. ptrm->dwSaveLine = ptrm->dwCurLine;
  2000. ptrm->dwSaveRelCursor = ptrm->fRelCursor;
  2001. ptrm->pSaveUchCharSet = ptrm->puchCharSet;
  2002. ptrm->iSaveCurrCharSet = ptrm->currCharSet;
  2003. ptrm->cSaveG0 = ptrm->G0;
  2004. ptrm->cSaveG1 = ptrm->G1;
  2005. ptrm->dwSaveIndexOfGraphicRendition =
  2006. ptrm->dwIndexOfGraphicRendition;
  2007. for( i=0; ( WORD) i<= ptrm->dwSaveIndexOfGraphicRendition; i++ )
  2008. {
  2009. ptrm->rgdwSaveGraphicRendition[i] =
  2010. ptrm->rgdwGraphicRendition[i];
  2011. }
  2012. break;
  2013. case '8':
  2014. //
  2015. // DECRC
  2016. // Restore cursor position, etc. from DECSC
  2017. //DECRC Restore Cursor (DEC Private)
  2018. //<ESC>8
  2019. //This sequence causes the previously saved cursor position,
  2020. //graphic rendition, and character set to be restored.
  2021. //
  2022. //Restore charset
  2023. if( ptrm->pSaveUchCharSet )
  2024. {
  2025. ptrm->puchCharSet = ptrm->pSaveUchCharSet;
  2026. ptrm->currCharSet = ptrm->iSaveCurrCharSet;
  2027. ptrm->G0 = ptrm->cSaveG0;
  2028. ptrm->G1 = ptrm->cSaveG1;
  2029. }
  2030. //Restore Graphic rendition
  2031. {
  2032. BOOL fNeedToRestore = 0;
  2033. if( ptrm->dwSaveIndexOfGraphicRendition !=
  2034. ptrm->dwIndexOfGraphicRendition )
  2035. {
  2036. fNeedToRestore = 1;
  2037. }
  2038. for( i=0; ( WORD )i<= ptrm->dwSaveIndexOfGraphicRendition &&
  2039. !fNeedToRestore; i++ )
  2040. {
  2041. if( ptrm->rgdwSaveGraphicRendition[i] !=
  2042. ptrm->rgdwGraphicRendition[i] )
  2043. {
  2044. fNeedToRestore = 1;
  2045. }
  2046. }
  2047. if( fNeedToRestore )
  2048. {
  2049. SetGraphicRendition( pwi, ptrm,
  2050. ptrm->dwSaveIndexOfGraphicRendition,
  2051. ptrm->rgdwSaveGraphicRendition );
  2052. }
  2053. }
  2054. //Restore Cursor position
  2055. SetConsoleWindowInfo( gwi.hOutput, TRUE, &(consoleBufferInfo.
  2056. srWindow ) );
  2057. if( ptrm->fSavedState == FALSE )
  2058. {
  2059. ptrm->dwCurChar = 1;
  2060. ptrm->dwCurLine = ( ptrm->fRelCursor )
  2061. ? ptrm->dwScrollTop : 0;
  2062. break;
  2063. }
  2064. ptrm->dwCurChar = ptrm->dwSaveChar;
  2065. ptrm->dwCurLine = ptrm->dwSaveLine;
  2066. ptrm->fRelCursor = ( BOOL ) ( ptrm->dwSaveRelCursor );
  2067. break;
  2068. case '[':
  2069. // VT102 - CSI Control Sequence Introducer
  2070. ptrm->fEsc = 2;
  2071. ptrm->dwEscCodes[0] = 0xFFFFFFFF;
  2072. ptrm->dwEscCodes[1] = 0xFFFFFFFF;
  2073. ptrm->cEscParams = 0;
  2074. ptrm->dwSum = 0xFFFFFFFF;
  2075. dwDECMode = FALSE;
  2076. break;
  2077. case '#':
  2078. ptrm->fEsc = 3;
  2079. break;
  2080. case 'A':
  2081. if( FIsVT52( ptrm ) )
  2082. {
  2083. // VT52 - Cursor up
  2084. ptrm->dwEscCodes[0] = 1;
  2085. CursorUp( ptrm );
  2086. }
  2087. break;
  2088. case 'B':
  2089. if( FIsVT52( ptrm ) )
  2090. {
  2091. // VT52 - Cursor down
  2092. ptrm->dwEscCodes[0] = 1;
  2093. CursorDown( ptrm );
  2094. }
  2095. break;
  2096. case 'C':
  2097. if( FIsVT52(ptrm) )
  2098. {
  2099. // VT52 - Cursor right
  2100. ptrm->dwEscCodes[0] = 1;
  2101. CursorRight( ptrm );
  2102. }
  2103. break;
  2104. case 'D':
  2105. if( FIsVT52(ptrm) )
  2106. {
  2107. // VT52 - Cursor left
  2108. ptrm->dwEscCodes[0] = 1;
  2109. CursorLeft( ptrm );
  2110. }
  2111. else
  2112. {
  2113. //VT102 - IND, Index cursor down 1 line, can scroll
  2114. //IND Index
  2115. //<ESC>D
  2116. //This sequence causes the cursor to move downward one line
  2117. //without changing the column. If the cursor is at the
  2118. //bottom margin, a scroll up is performed. Format Effector.
  2119. NewLine( pwi, ptrm );
  2120. }
  2121. break;
  2122. case 'E': // Next Line ; cr/lf
  2123. //
  2124. // VT102 - NEL, New Line
  2125. // cursor to start of line below, can scroll
  2126. //
  2127. //NEL Next Line
  2128. //<ESC>E
  2129. //This causes the cursor to move to the first position of the
  2130. //next line down. If the cursor is on the bottom line, a scroll
  2131. //is performed. Format Effector.
  2132. ptrm->dwCurChar = 0;
  2133. NewLine( pwi, ptrm );
  2134. break;
  2135. case 'F':
  2136. // VT52 - Enter graphics mode ; alternate graphics character set
  2137. if( FIsVT52( ptrm ) )
  2138. {
  2139. SetVT52Graphics( ptrm );
  2140. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  2141. SetCharSet(ptrm,GRAPHIC_LEFT,rgchGraphicsChars);
  2142. else
  2143. ptrm->puchCharSet = rgchAlternateChars;
  2144. }
  2145. break;
  2146. case 'G':
  2147. // VT52 - Exit graphics mode ; ASCII character set
  2148. if( FIsVT52( ptrm ))
  2149. {
  2150. ClearVT52Graphics( ptrm );
  2151. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  2152. SetCharSet(ptrm,GRAPHIC_LEFT,rgchIBMAnsiChars);
  2153. else
  2154. ptrm->puchCharSet = rgchNormalChars;
  2155. }
  2156. break;
  2157. case 'H':
  2158. if ( (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)) && ( FIsVT80(ptrm) && FIsNECKanji(ptrm) ) )
  2159. {
  2160. /* NEC Kanji OUT (JIS Roman to G0(GL)) */
  2161. ClearKanjiStatus(ptrm,JIS_KANJI_CODE);
  2162. SetCharSet(ptrm,GRAPHIC_LEFT,rgchJISRomanChars);
  2163. }
  2164. else
  2165. if( FIsVT52( ptrm ) )
  2166. {
  2167. // VT52 - Cursor Home
  2168. CONSOLE_SCREEN_BUFFER_INFO info;
  2169. if( !GetConsoleScreenBufferInfo( gwi.hOutput,
  2170. &info ) )
  2171. {
  2172. info.srWindow.Top = 0;
  2173. info.srWindow.Left = 0;
  2174. }
  2175. ptrm->dwCurLine = info.srWindow.Top;
  2176. ptrm->dwCurChar = info.srWindow.Left;
  2177. }
  2178. else
  2179. {
  2180. // VT102 - HTS Set Tab Stop
  2181. //HTS Horizontal Tab Set
  2182. //<ESC>H
  2183. //Set a tab stop at the current cursor position.
  2184. //Format Effector.
  2185. if( g_iHTS < MAX_TABSTOPS )
  2186. {
  2187. g_rgdwHTS[ g_iHTS++ ] = ptrm->dwCurChar;
  2188. }
  2189. }
  2190. break;
  2191. case 'I':
  2192. if ( FIsVT52(ptrm) )
  2193. {
  2194. // VT52 - Reverse linefeed
  2195. NewLineUp( pwi, ptrm );
  2196. }
  2197. break;
  2198. case 'J':
  2199. if( FIsVT52( ptrm ))
  2200. {
  2201. // VT52 - Clears to end of screen
  2202. ClearScreen( pwi, ptrm, fdwCursorToEOS );
  2203. }
  2204. break;
  2205. case 'K':
  2206. if ((FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)) && FIsVT80(ptrm) && FIsNECKanji(ptrm) )
  2207. {
  2208. /* NEC Kanji IN (Kanji to G0(GL)) */
  2209. SetKanjiStatus(ptrm,JIS_KANJI_CODE);
  2210. SetCharSet(ptrm,GRAPHIC_LEFT,rgchJISKanjiChars);
  2211. }
  2212. else
  2213. if( FIsVT52( ptrm ))
  2214. {
  2215. // VT52 - Erases to end of line
  2216. ClearLine( pwi, ptrm, fdwCursorToEOL );
  2217. }
  2218. break;
  2219. case 'M':
  2220. // VT102 - RI Reverse Index, cursor up 1 line, can scroll
  2221. //RI Reverse Index
  2222. //<ESC>M
  2223. //Move the cursor up one line without changing columns. If the
  2224. //cursor is on the top line, a scroll down is performed.
  2225. NewLineUp( pwi, ptrm );
  2226. break;
  2227. case 'N':
  2228. if ((FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)))
  2229. {
  2230. if(FIsVT80(ptrm)) {
  2231. if( !(GetKanjiStatus(ptrm) & JIS_KANJI_CODE) &&
  2232. (FIsJISKanji(ptrm) || FIsJIS78Kanji(ptrm) ||
  2233. FIsEUCKanji(ptrm) || FIsDECKanji(ptrm) ) ) {
  2234. PushCharSet(ptrm,GRAPHIC_LEFT,ptrm->g2);
  2235. PushCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g2);
  2236. SetKanjiStatus(ptrm,SINGLE_SHIFT_2);
  2237. #ifdef DEBUG
  2238. wsprintf(rgchDbgBfr,"VT80 EUC/DEC/JIS SS2 Mode Enter\n");
  2239. OutputDebugString(rgchDbgBfr);
  2240. #endif /* DEBUG */
  2241. }
  2242. }
  2243. }
  2244. break;
  2245. case 'O':
  2246. if ((FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)))
  2247. {
  2248. if(FIsVT80(ptrm)) {
  2249. if( !(GetKanjiStatus(ptrm) & JIS_KANJI_CODE) &&
  2250. (FIsJISKanji(ptrm) || FIsJIS78Kanji(ptrm) ||
  2251. FIsEUCKanji(ptrm) || FIsDECKanji(ptrm) ) ) {
  2252. PushCharSet(ptrm,GRAPHIC_LEFT,ptrm->g3);
  2253. PushCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g3);
  2254. SetKanjiStatus(ptrm,SINGLE_SHIFT_3);
  2255. #ifdef DEBUG
  2256. wsprintf(rgchDbgBfr,"VT80 EUC/DEC/JIS SS3 Mode Enter\n");
  2257. OutputDebugString(rgchDbgBfr);
  2258. #endif /* DEBUG */
  2259. }
  2260. }
  2261. }
  2262. break;
  2263. case 'Y':
  2264. if ( FIsVT52(ptrm) )
  2265. {
  2266. // VT52 - direct cursor address
  2267. if(( ich + 3 ) <= cbTermOut )
  2268. {
  2269. DWORD dwNewLine = ptrm->dwCurLine;
  2270. dwNewLine = ( pchT[1] > 31 ) ? pchT[1]-32 : 0;
  2271. if (dwNewLine != ptrm->dwCurLine)
  2272. {
  2273. WriteToLog(ptrm->dwCurLine);
  2274. }
  2275. ptrm->dwCurLine = dwNewLine;
  2276. ptrm->dwCurChar = ( pchT[2] > 31 ) ? pchT[2]-32 : 0;
  2277. {
  2278. CONSOLE_SCREEN_BUFFER_INFO info;
  2279. if( !GetConsoleScreenBufferInfo( gwi.hOutput,
  2280. &info ) )
  2281. {
  2282. info.srWindow.Top = 0;
  2283. info.srWindow.Left = 0;
  2284. }
  2285. ptrm->dwCurLine += info.srWindow.Top;
  2286. ptrm->dwCurChar += info.srWindow.Left;
  2287. }
  2288. ich += 2;
  2289. pchT += 2;
  2290. }
  2291. else
  2292. {
  2293. ptrm->fEsc = 4;
  2294. ptrm->dwEscCodes[0] = 0xFFFFFFFF;
  2295. ptrm->dwEscCodes[1] = 0xFFFFFFFF;
  2296. ptrm->cEscParams = 0;
  2297. }
  2298. }
  2299. break;
  2300. case 'Z':
  2301. //DECID Identify Terminal (DEC Private)
  2302. //<ESC>Z
  2303. //This sequence causes the same response as the DA sequence.
  2304. //This sequence will not be supported in future models.
  2305. if( !FIsVT52(ptrm) )
  2306. {
  2307. if ((FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)) && ( FIsVT80(ptrm) ))
  2308. {
  2309. /* VT80 - DECID Identify terminal */
  2310. pchNBBuffer[0] = 0x1B;
  2311. pchNBBuffer[1] = '[';
  2312. pchNBBuffer[2] = '?';
  2313. pchNBBuffer[3] = '1';
  2314. pchNBBuffer[4] = '8';
  2315. pchNBBuffer[5] = ';';
  2316. pchNBBuffer[6] = '2';
  2317. pchNBBuffer[7] = 'c';
  2318. i = 8;
  2319. }
  2320. else
  2321. {
  2322. // VT102 - DECID Identify terminal
  2323. pchNBBuffer[0] = 0x1B;
  2324. pchNBBuffer[1] = '[';
  2325. pchNBBuffer[2] = '?';
  2326. pchNBBuffer[3] = '1';
  2327. pchNBBuffer[4] = ';';
  2328. pchNBBuffer[5] = '0';
  2329. pchNBBuffer[6] = 'c';
  2330. i = 7;
  2331. }
  2332. }
  2333. else
  2334. {
  2335. // VT52 - Identify terminal
  2336. pchNBBuffer[0] = 0x1B;
  2337. pchNBBuffer[1] = '/';
  2338. pchNBBuffer[2] = 'Z';
  2339. i = 3;
  2340. }
  2341. ( void ) FWriteToNet( pwi, ( LPSTR ) pchNBBuffer, ( int ) i );
  2342. break;
  2343. case 'c':
  2344. // VT102 RIS Hard reset, reset term to initial state
  2345. //RIS Reset to Initial State
  2346. //<ESC>c
  2347. //Resets the VT100 to the state is has upon power up. This also
  2348. //causes the execution of the POST and signal INT H to be
  2349. //asserted briefly.
  2350. FlushBuffer( pwi, ptrm );
  2351. DoTermReset( pwi, ptrm );
  2352. break;
  2353. case '=':
  2354. // VT102 - DECKPAM Enter numeric keypad app mode
  2355. //DECKPAM Keypad Application Mode (DEC Private)
  2356. //<ESC>=
  2357. //The auxiliary keypad keys will transmit control sequences.
  2358. ClearVTKeypad( ptrm );
  2359. break;
  2360. case '>':
  2361. // VT102 - DECKNPNM Enter numeric keypad numeric mode
  2362. //DECKPNM Keypad Numeric Mode (DEC Private)
  2363. //<ESC> >
  2364. //The auxiliary keypad keys will send ASCII codes corresponding
  2365. //to the characters engraved on their keys.
  2366. SetVTKeypad( ptrm );
  2367. break;
  2368. case '<':
  2369. // ENTER - ANSI Mode if in VT52.
  2370. if( FIsVT52(ptrm) )
  2371. {
  2372. SetANSI(ptrm);
  2373. }
  2374. break;
  2375. case '(':
  2376. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  2377. {
  2378. if ( FIsVT80(ptrm) &&
  2379. (FIsJISKanji(ptrm) || FIsJIS78Kanji(ptrm))) {
  2380. // SetKanjiStatus(ptrm,JIS_INVOKE_MB);
  2381. ptrm->fEsc = 5;
  2382. }
  2383. break;
  2384. }
  2385. else
  2386. {
  2387. ++ich;
  2388. ++pchT;
  2389. ptrm->G0 = *pchT;
  2390. break;
  2391. }
  2392. case '$':
  2393. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  2394. {
  2395. if ( FIsVT80(ptrm) &&
  2396. (FIsJISKanji(ptrm) || FIsJIS78Kanji(ptrm))) {
  2397. // SetKanjiStatus(ptrm,JIS_INVOKE_SB);
  2398. ptrm->fEsc = 6;
  2399. #if DEBUG
  2400. _snwprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1,"VT80 JIS MB Invoke Enter\n");
  2401. OutputDebugString(rgchDbgBfr);
  2402. #endif /* DEBUG */
  2403. }
  2404. }
  2405. break;
  2406. case ')':
  2407. // VT102 SCS
  2408. //SCS Select Character Set
  2409. //The appropriate D0 and G1 character sets are
  2410. //designated from one of the five possible sets. The G0
  2411. //and G1 sets are invokedd by the characters <SI> and
  2412. //<SO>, respectively.
  2413. //G0 Sets G1 Sets
  2414. //Sequence Sequence Meaning
  2415. //------------------------------------------------------
  2416. //<ESC>(A <ESC>)A United Kingdom Set
  2417. //<ESC>(B <ESC>)B ASCII Set
  2418. //<ESC>(0 <ESC>)0 Special Graphics
  2419. //<ESC>(1 <ESC>)1 Alternate Character ROM
  2420. // Standard Character Set
  2421. //<ESC>(2 <ESC>)2 Alternate Character ROM
  2422. // Special Graphics
  2423. //
  2424. //
  2425. //The United Kingdom and ASCII sets conform to the "ISO
  2426. //international register of character sets to be used
  2427. //with escape sequences". The other sets are private
  2428. //character sets. Special graphics means that the
  2429. //graphic characters fpr the codes 0137 to 0176 are
  2430. //replaced with other characters. The specified
  2431. //character set will be used until another SCS is
  2432. //recieved.
  2433. ++ich;
  2434. ++pchT;
  2435. ptrm->G1 = *pchT;
  2436. break;
  2437. case '%':
  2438. break;
  2439. case '~':
  2440. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  2441. {
  2442. if(FIsVT80(ptrm)) {
  2443. SetCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g1);
  2444. }
  2445. }
  2446. else
  2447. break;
  2448. default:
  2449. // Is if a form feed?
  2450. if( *pchT == 12 )
  2451. {
  2452. ptrm->dwCurChar = ptrm->dwCurLine = 0;
  2453. ClearScreen( pwi, ptrm, fdwCursorToEOS );
  2454. }
  2455. break;
  2456. }
  2457. break;
  2458. case 2: // ESC [ entered
  2459. /*
  2460. * HACK: Handle the problem where a number has been read
  2461. * and then a letter. The number won't be in the dwEscCodes[]
  2462. * since only on a ';' does it get put in there.
  2463. * So, check to see if we have a character which
  2464. * signifies an Control Sequence,
  2465. * i.e. !(0...9) && !'?' && !';'
  2466. *
  2467. * Also, zero out the following element in the dwEscCodes[]
  2468. * array to be safe.
  2469. */
  2470. if( ! (( '0' <= *pchT ) && ( *pchT <= '9' )) &&
  2471. ( *pchT != '?' ) && ( *pchT != ';' ))
  2472. {
  2473. if( ptrm->dwSum == 0xFFFFFFFF )
  2474. {
  2475. ptrm->dwSum = 0;
  2476. }
  2477. ptrm->dwEscCodes[ptrm->cEscParams++] = ptrm->dwSum;
  2478. if( ptrm->cEscParams < 10 )
  2479. {
  2480. ptrm->dwEscCodes[ptrm->cEscParams] = 0;
  2481. }
  2482. }
  2483. switch( *pchT )
  2484. {
  2485. case 0x08: // Backspace
  2486. if( ptrm->dwCurChar > 0 )
  2487. {
  2488. --ptrm->dwCurChar;
  2489. }
  2490. break;
  2491. case '\n': //Line Feed
  2492. //<LF>; 0012; Causes either a line feed or new line operation
  2493. //(See new line mode.)
  2494. if( ptrm->fFlushToEOL )
  2495. {
  2496. ptrm->fLongLine = FALSE;
  2497. ptrm->fFlushToEOL = FALSE;
  2498. break;
  2499. }
  2500. if( ptrm->fLongLine )
  2501. {
  2502. ptrm->fLongLine = FALSE;
  2503. break;
  2504. }
  2505. FlushBuffer( pwi, ptrm );
  2506. NewLine( pwi, ptrm );
  2507. break;
  2508. case '0':
  2509. case '1':
  2510. case '2':
  2511. case '3':
  2512. case '4':
  2513. case '5':
  2514. case '6':
  2515. case '7':
  2516. case '8':
  2517. case '9':
  2518. if( ptrm->dwSum == 0xFFFFFFFF )
  2519. {
  2520. ptrm->dwSum = ( *pchT ) - '0';
  2521. }
  2522. else
  2523. {
  2524. ptrm->dwSum = ( 10 * ptrm->dwSum ) + ( *pchT ) - '0';
  2525. }
  2526. break;
  2527. /////////////////////////////////////////////////////
  2528. // Hack for FTCU machine
  2529. // 'Eat' the Esc?7h escape sequence emitted from FTCU
  2530. /////////////////////////////////////////////////////
  2531. case '?':
  2532. // Sets or resets DEC mode
  2533. dwDECMode = TRUE;
  2534. break;
  2535. case ';':
  2536. if( ptrm->cEscParams < 9 )
  2537. {
  2538. ptrm->dwEscCodes[ptrm->cEscParams++] = ptrm->dwSum;
  2539. ptrm->dwEscCodes[ptrm->cEscParams] = 0xFFFFFFFF;
  2540. ptrm->dwSum = 0xFFFFFFFF;
  2541. break;
  2542. }
  2543. break;
  2544. case 'A': // VT102 CUU cursor up
  2545. //CUU Cursor Up Host to VT100 & VT100 to Host
  2546. // <ESC>[ {Pn} A Default Value: 1
  2547. //Moves the cursor up without changing columns. The cursor is
  2548. //moved up a number of lines as indicated by the parameter. The
  2549. //cursor cannot be moved beyond the top margin. Editor Function.
  2550. CursorUp( ptrm );
  2551. break;
  2552. case 'B': // VT102 CUD cursor down
  2553. case 'e':
  2554. //CUD Cursor Down Host to VT100 & VT100 to Host
  2555. // <ESC>[ {Pn} B Default value: 1
  2556. //Moves the cursor down a number of lines as specified in the
  2557. //parameter without changing columns. The cursor cannot be
  2558. //moved past the bottom margin. Editor Function.
  2559. CursorDown( ptrm );
  2560. break;
  2561. case 'C': // VT102 CUF cursor right
  2562. case 'a':
  2563. //CUF Cursor Forward Host to VT100 & VT100 to Host
  2564. // <ESC>[ {Pn} C Default Value: 1
  2565. //The CUF sequence moves the cursor to the right a number of
  2566. //positions specified in the parameter. The cursor cannot be
  2567. //moved past the right margin. Editor Function.
  2568. CursorRight( ptrm );
  2569. break;
  2570. case 'D': // VT102 CUB cursor left
  2571. //CUB Cursor Backward Host to VT100 & VT100 to Host
  2572. // <ESC>[ {Pn} D Default Value: 1
  2573. //The CUB sequence move the cursor to the left. The distance
  2574. //moved is determined by the parameter. If the parameter
  2575. //missing, zero, or one,the cursor is moved one position.
  2576. //The cursor cannot be moved past the left margin.
  2577. //Editor Function.
  2578. CursorLeft( ptrm );
  2579. break;
  2580. case 'E': // Move cursor to beginning of line, p lines down.
  2581. break;
  2582. case 'F': // Move active position to beginning of line, p lines up
  2583. break;
  2584. case '`': // move cursor to column p
  2585. case 'G':
  2586. break;
  2587. case 'H': // VT102 CUP position cursor
  2588. //HVP Horizontal and Vertical Position
  2589. //<ESC>[ {Pn} ; {Pn} f
  2590. //Moves the cursor to the position specified by the parameters.
  2591. //The first parameter specifies the line, and the second
  2592. //specifies the column. A parameter of 0 or 1 causes the active
  2593. //position to move to the first line or column in the display.
  2594. //In the VT100, this control behaves identically with it's editor
  2595. //counterpart, CUP. The numbering of the lines depends upon the
  2596. //state of the Origin Mode (DECOM). Format Effector.
  2597. case 'f': // VT102 HVP position cursor
  2598. //CUP Cursor Position
  2599. //<ESC>[ {Pn} ; {Pn} H Default Value: 1
  2600. //The CUP sequence moves the curor to the position specified by
  2601. //the parameters. The first parameter specifies the line, and
  2602. //the second specifies the column. A value of zero for either
  2603. //line or column moves the cursor to the first line or column in
  2604. //the display. The default string (<ESC>H) homes the cursor. In
  2605. //the VT100, this command behaves identically to it's format
  2606. //effector counterpart, HVP.The numbering of the lines depends
  2607. //upon the state of the Origin Mode (DECOM). Editor Function.
  2608. if( ptrm->dwEscCodes[0] == 0 )
  2609. {
  2610. ptrm->dwEscCodes[0] = 1;
  2611. }
  2612. if( ptrm->dwEscCodes[1] == 0 )
  2613. {
  2614. ptrm->dwEscCodes[1] = 1;
  2615. }
  2616. {
  2617. DWORD dwNewLine = 0;
  2618. CONSOLE_SCREEN_BUFFER_INFO info;
  2619. if( !GetConsoleScreenBufferInfo( gwi.hOutput,
  2620. &info ) )
  2621. {
  2622. info.srWindow.Top = 0;
  2623. info.srWindow.Left = 0;
  2624. }
  2625. dwNewLine = info.srWindow.Top +
  2626. ( ptrm->dwEscCodes[0] - 1 );
  2627. ptrm->dwCurChar = info.srWindow.Left +
  2628. ( ptrm->dwEscCodes[1] - 1 );
  2629. if( ( SHORT )ptrm->dwCurChar >= info.srWindow.Right )
  2630. {
  2631. ptrm->dwCurChar = info.srWindow.Right;
  2632. }
  2633. if( ( SHORT )dwNewLine >= info.srWindow.Bottom )
  2634. {
  2635. dwNewLine = info.srWindow.Bottom;
  2636. }
  2637. if( ui.bLogging && dwNewLine != ptrm->dwCurLine )
  2638. {
  2639. WriteToLog( ptrm->dwCurLine );
  2640. }
  2641. ptrm->dwCurLine = dwNewLine;
  2642. }
  2643. if(( ptrm->fRelCursor == TRUE ) && ( ptrm->dwCurLine < ptrm->dwScrollTop ))
  2644. {
  2645. ptrm->dwCurLine = ptrm->dwScrollTop;
  2646. }
  2647. if ((ptrm->fRelCursor == TRUE) && (ptrm->dwCurLine >= ptrm->dwScrollBottom))
  2648. {
  2649. ptrm->dwCurLine = ptrm->dwScrollBottom - 1;
  2650. }
  2651. ptrm->fEsc = 0;
  2652. ptrm->fFlushToEOL = FALSE;
  2653. ptrm->fLongLine = FALSE;
  2654. break;
  2655. case 'J': // VT102 ED erase display
  2656. //ED Erase in Display
  2657. //<ESC>[ {Ps} J Default: 0
  2658. //This sequence erases some or all of the characters in the
  2659. //display according to the parameter. Any complete line erased
  2660. //by this sequence will return that line to single width mode.
  2661. //Editor Function.
  2662. //Parameter Meaning
  2663. //-------------------------------------------------------------
  2664. // 0 Erase from the cursor to the end of the screen.
  2665. // 1 Erase from the start of the screen to the cursor.
  2666. // 2 Erase the entire screen.
  2667. ClearScreen( pwi, ptrm, ptrm->dwEscCodes[0] );
  2668. break;
  2669. case 'K': // VT102 EL erase line
  2670. //EL Erase in Line
  2671. //<ESC>[ {Ps} K Default: 0
  2672. //Erases some or all characters in the active line, according to
  2673. //the parameter. Editor Function.
  2674. //Parameter Meaning
  2675. //-------------------------------------------------------------
  2676. //0 Erase from cursor to the end of the line.
  2677. //1 Erase from the start of the line to the cursor.
  2678. //2 Erase the entire line.
  2679. ClearLine( pwi, ptrm, ptrm->dwEscCodes[0] );
  2680. break;
  2681. case 'L': // VT102 IL insert lines
  2682. {
  2683. int j;
  2684. if( ptrm->dwEscCodes[0] == 0 )
  2685. {
  2686. ptrm->dwEscCodes[0] = 1;
  2687. }
  2688. for( j = 0 ; ( WORD )j < ptrm->dwEscCodes[0]; j++ )
  2689. {
  2690. InsertLine( pwi, ptrm, ptrm->dwCurLine );
  2691. }
  2692. ptrm->fEsc = 0;
  2693. break;
  2694. }
  2695. case 'M': // VT102 DL delete line
  2696. {
  2697. int j;
  2698. if( ptrm->dwEscCodes[0] == 0 )
  2699. {
  2700. ptrm->dwEscCodes[0] = 1;
  2701. }
  2702. //DeleteLines( pwi, ptrm, ptrm->dwCurLine, ptrm->dwEscCodes[0] );
  2703. for( j = 0 ; ( WORD )j < ptrm->dwEscCodes[0]; j++ )
  2704. {
  2705. DeleteLine( pwi, ptrm, ptrm->dwCurLine );
  2706. }
  2707. ptrm->fEsc = 0;
  2708. break;
  2709. }
  2710. case '@': // VT102 ICH? insert characters
  2711. if( ptrm->dwEscCodes[0] == 0 )
  2712. {
  2713. ptrm->dwEscCodes[0] = 1;
  2714. }
  2715. if( ptrm->dwEscCodes[0] > ( ui.dwMaxCol - ptrm->dwCurChar ))
  2716. {
  2717. ptrm->dwEscCodes[0] = ui.dwMaxCol - ptrm->dwCurChar;
  2718. }
  2719. i = ptrm->dwCurChar+ptrm->dwEscCodes[0];
  2720. if(( ui.dwMaxCol-i ) > 0 )
  2721. {
  2722. SMALL_RECT lineRect;
  2723. COORD dwDest;
  2724. // Form a rectangle for the line.
  2725. lineRect.Bottom = ( short ) ptrm->dwCurLine;
  2726. lineRect.Top = ( short ) ptrm->dwCurLine;
  2727. lineRect.Left = ( short ) ptrm->dwCurChar;
  2728. lineRect.Right = ( short ) ( ui.dwMaxCol );
  2729. // Destination is one character to the right.
  2730. dwDest.X = ( short ) (i);
  2731. dwDest.Y = ( short ) ptrm->dwCurLine;
  2732. pwi->cinfo.Attributes = pwi->sbi.wAttributes;
  2733. ScrollConsoleScreenBuffer( pwi->hOutput, &lineRect, NULL, dwDest, &pwi->cinfo );
  2734. }
  2735. if( ui.bLogging )
  2736. {
  2737. WriteToLog( ptrm->dwCurLine );
  2738. }
  2739. ptrm->fEsc = 0;
  2740. break;
  2741. case 'P': // VT102 DCH delete chars
  2742. if( ptrm->dwEscCodes[0] == 0 )
  2743. {
  2744. ptrm->dwEscCodes[0] = 1;
  2745. }
  2746. if( ptrm->dwEscCodes[0] > ( ui.dwMaxCol-ptrm->dwCurChar ))
  2747. {
  2748. ptrm->dwEscCodes[0] = ui.dwMaxCol-ptrm->dwCurChar;
  2749. }
  2750. if(( ui.dwMaxCol - ptrm->dwCurChar - 1) > 0 )
  2751. {
  2752. SMALL_RECT lineRect;
  2753. COORD dwDest;
  2754. SMALL_RECT clipRect;
  2755. // Form a rectangle for the line.
  2756. lineRect.Bottom = ( short ) ptrm->dwCurLine;
  2757. lineRect.Top = ( short ) ptrm->dwCurLine;
  2758. lineRect.Left = ( short ) ptrm->dwCurChar;
  2759. lineRect.Right = ( short )( ui.dwMaxCol );
  2760. clipRect = lineRect;
  2761. // Destination is one character to the right.
  2762. dwDest.X = ( short ) ( ptrm->dwCurChar - ptrm->dwEscCodes[0] );
  2763. dwDest.Y = ( short ) ptrm->dwCurLine;
  2764. pwi->cinfo.Attributes = pwi->sbi.wAttributes;
  2765. ScrollConsoleScreenBuffer( pwi->hOutput, &lineRect, &clipRect, dwDest, &pwi->cinfo );
  2766. }
  2767. if( ui.bLogging )
  2768. {
  2769. WriteToLog( ptrm->dwCurLine );
  2770. }
  2771. ptrm->fEsc = 0;
  2772. break;
  2773. case 'S':
  2774. break;
  2775. case 'T':
  2776. break;
  2777. case 'X': // Erase p characters up to the end of line
  2778. break;
  2779. case 'Z': // move back p tab stops
  2780. break;
  2781. case 'c': // VT102 DA Same as DECID
  2782. //DA Device Attributes Host to VT100 & VT100 to Host
  2783. // <ESC>[ {Pn} c Default Value: 0
  2784. //1) The host requests the VT100 to send a DA sequence to
  2785. //indentify itself. This is done by sending the DA sequence
  2786. //with no parameters, or with a parameter of zero.
  2787. //2) Response to the request described above (VT100 to host) is
  2788. //generated by the VT100 as a DA control sequencewith the
  2789. //numeric parameters as follows:
  2790. //Option Present Sequence Sent
  2791. //---------------------------------------------
  2792. //No options <ESC>[?1;0c
  2793. //Processor Option (STP) <ESC>[?1;1c
  2794. //Advanced Video Option (AVO) <ESC>[?1;2c
  2795. //AVO and STP <ESC>[?1;3c
  2796. //Graphics Option (GPO) <ESC>[?1;4c
  2797. //GPO and STP <ESC>[?1;5c
  2798. //GPO and AVO <ESC>[?1;6c
  2799. //GPO, ACO, and STP <ESC>[?1;7c
  2800. pchNBBuffer[0] = 0x1B;
  2801. pchNBBuffer[1] = '[';
  2802. pchNBBuffer[2] = '?';
  2803. pchNBBuffer[3] = '1';
  2804. pchNBBuffer[4] = ';';
  2805. pchNBBuffer[5] = '0';
  2806. pchNBBuffer[6] = 'c';
  2807. i = 7;
  2808. ( void ) FWriteToNet( pwi, ( LPSTR ) pchNBBuffer, ( int ) i );
  2809. ptrm->fEsc = 0;
  2810. break;
  2811. case 'd': // move to line p
  2812. break;
  2813. case 'g': // VT102 TBC Clear Tabs
  2814. //TBC Tabulation Clear
  2815. //<ESC>[ {Ps} g
  2816. //If the parameter is missing or 0, this will clear the tab stop
  2817. //at the cursor's position. If it is 3, this will clear all of
  2818. //the tab stops. Any other parameter is ignored. Format Effector.
  2819. if( ptrm->dwEscCodes[0] == 3 )
  2820. {
  2821. // Clear all tabs
  2822. g_iHTS = 0;
  2823. }
  2824. else if( ptrm->dwEscCodes[0] == 0 && g_iHTS )
  2825. {
  2826. // Clear tab stop at current position
  2827. int x=0;
  2828. while( x < g_iHTS )
  2829. {
  2830. if( g_rgdwHTS[ x ] >= ptrm->dwCurChar &&
  2831. g_rgdwHTS[ x ] != -1 )
  2832. {
  2833. if( g_rgdwHTS[ x ] == ptrm->dwCurChar )
  2834. {
  2835. g_rgdwHTS[ x ] = ( DWORD )-1; //clear the tab stop
  2836. }
  2837. break;
  2838. }
  2839. x++;
  2840. }
  2841. }
  2842. ptrm->fEsc = 0;
  2843. break;
  2844. case 'h':
  2845. //SM Set Mode
  2846. //<ESC> [ {Ps} ; {Ps} h
  2847. //Causes one or more modes to be set within the VT100 as
  2848. //specified by each selective parameter string. Each mode to be
  2849. //set is specified by a seperate parameter. A mode is
  2850. //considered set until it is reset by a Reset Mode (RM) control
  2851. //sequence. See RM and MODES.
  2852. //[Editor's note: The original DEC VT100 documentation
  2853. //EK-VT100-UG-003 erroneously omitted the "[" character from the
  2854. //SM sequence.]
  2855. for( i = 0; i < ptrm->cEscParams; ++i )
  2856. {
  2857. if( dwDECMode == TRUE )
  2858. {
  2859. switch( ptrm->dwEscCodes[i] )
  2860. { // Field specs
  2861. case 0:
  2862. //Error (ignored)
  2863. break;
  2864. case 1: // DECCKM
  2865. //DECCKM Cursor Keys Mode (DEC Private)
  2866. //This is a private parameter to the SM and RM
  2867. //control requences. This mode is only effective
  2868. //when the terminal is in keypad application mode
  2869. //(DECPAM) and the ANSI/VT52 mode (DECANM) is set.
  2870. //Under these conditions, if this mode is reset,
  2871. //the cursor keys will send ANSI cursor control
  2872. //commands. If setm the cursor keys will send
  2873. //application function commands (See MODES, RM,
  2874. //and SM).
  2875. /*This is a hack so that in vt100, vi works properly
  2876. * */
  2877. {
  2878. CONSOLE_SCREEN_BUFFER_INFO info;
  2879. if( !GetConsoleScreenBufferInfo( gwi.hOutput,
  2880. &info ) )
  2881. {
  2882. consoleBufferInfo.srWindow.Top = 0;
  2883. consoleBufferInfo.srWindow.Bottom = 0;
  2884. }
  2885. if( FGetCodeMode(eCodeModeFarEast) )
  2886. {
  2887. SetMargins( ptrm, info.srWindow.Top,
  2888. info.srWindow.Bottom );
  2889. }
  2890. else
  2891. {
  2892. SetMargins( ptrm, info.srWindow.Top,
  2893. info.srWindow.Bottom + 1);
  2894. }
  2895. }
  2896. SetVTArrow( ptrm );
  2897. break;
  2898. case 2: // DECANM : ANSI/VT52
  2899. //DECANM ANSI/VT52 Mode (DEC Private)
  2900. //This is a private parameter to the SM and RM
  2901. //control sequences. The reset state causes only
  2902. //VT52 compatible escape sequences to be recognized.
  2903. //The set state causes only ANSI compatible escape
  2904. //sequences to be recognized. See the entries for
  2905. //MODES, SM, and RM.
  2906. SetANSI( ptrm ); //ClearVT52(ptrm);
  2907. ClearVT52Graphics( ptrm );
  2908. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  2909. SetCharSet(ptrm,GRAPHIC_LEFT,rgchIBMAnsiChars);
  2910. else
  2911. ptrm->puchCharSet = rgchNormalChars;
  2912. break;
  2913. case 3: // DECCOLM : Col = 132
  2914. //DECCOLM Column Mode (DEC Private)
  2915. //This is a private parameter to the SM and RM
  2916. //control sequences. The reset state causes an 80
  2917. //column screen to be used. The set state causes a
  2918. //132 column screen to be used. See MODES, RM, and
  2919. //SM.
  2920. SetDECCOLM(ptrm);
  2921. GetConsoleScreenBufferInfo( gwi.hOutput,
  2922. &consoleBufferInfo );
  2923. consoleBufferInfo.srWindow.Right = 131;
  2924. dwSize.X = 132;
  2925. dwSize.Y = consoleBufferInfo.dwSize.Y;
  2926. dwMaximumWindowSize =
  2927. GetLargestConsoleWindowSize( gwi.hOutput );
  2928. if( 131 > dwMaximumWindowSize.X )
  2929. {
  2930. consoleBufferInfo.srWindow.Right =
  2931. ( SHORT )( dwMaximumWindowSize.X - 1 -
  2932. consoleBufferInfo.srWindow.Left );
  2933. }
  2934. if( consoleBufferInfo.dwSize.X <= 132 )
  2935. {
  2936. SetConsoleScreenBufferSize( gwi.hOutput,
  2937. dwSize );
  2938. SetConsoleWindowInfo( gwi.hOutput, TRUE,
  2939. &(consoleBufferInfo.srWindow) );
  2940. }
  2941. else
  2942. {
  2943. SetConsoleWindowInfo( gwi.hOutput, TRUE,
  2944. &(consoleBufferInfo.srWindow) );
  2945. SetConsoleScreenBufferSize( gwi.hOutput,
  2946. dwSize );
  2947. }
  2948. //update global data structures
  2949. ui.dwMaxCol = 132;
  2950. gwi.sbi.dwSize.X = 132;
  2951. consoleBufferInfo.dwSize.X = 132;
  2952. ClearScreen( pwi, ptrm, fdwEntireScreen );
  2953. break;
  2954. case 4: // DECSCLM : smooth scroll
  2955. // Scrolling Mode (DEC Private)
  2956. // This is a private parameter to RM and
  2957. // SM control sequences. The reset
  2958. // state causes scrolls to "jump"
  2959. // instantaneuously one line at a time.
  2960. // The set state causes the scrolls to be
  2961. // "smooth", and scrolls at a maximum rate
  2962. // of siz lines/sec. See MODES, RM, and SM.
  2963. break;
  2964. case 5: // DECSCNM : Light background
  2965. //DECSCNM Screen Mode (DEC Private)
  2966. //This is a private parameter to RM and SM
  2967. //control sequences. The reset state causes
  2968. //the screen to be black with white
  2969. //characters; the set state causes the
  2970. //screen to be white with black characters.
  2971. //See MODES, RM, and SM.
  2972. if( FIsDECSCNM( ptrm ) )
  2973. {
  2974. break;
  2975. }
  2976. SetDECSCNM( ptrm );
  2977. SetLightBackground( pwi );
  2978. break;
  2979. case 6: // DECOM : Relative origin ; stay in margin
  2980. //DECOM Origin Mode (DEC Private)
  2981. //This is a private parameter to SM and RM control
  2982. //sequences. The reset state causes the origin (or
  2983. //home position) to be the upper left character
  2984. //position of the screen. Line and column numbers
  2985. //are, therefore, independent of current margin
  2986. //settings. The cursor may be positioned outside
  2987. //the margins with a cursor position (CUP) or
  2988. //horizontal and vertical position (HVP) control.
  2989. //The set state causes the origin to be at the upper
  2990. //left character position within the current margins.
  2991. //Line and column numbers are, therefore, relative
  2992. //to the current margin settings. The cursor cannot
  2993. //be positioned outside of the margins.
  2994. //The cursor is moved to the new home position when
  2995. //this mode is set or reset. Lines and columns are
  2996. //numbered consecutively, with the origin being
  2997. //line 1, column 1.
  2998. ptrm->fRelCursor = TRUE;
  2999. ptrm->dwCurChar = 0;
  3000. ptrm->dwCurLine = ptrm->dwScrollTop;
  3001. break;
  3002. case 7: // DECAWM
  3003. //DECAWM Autowrap Mode (DEC Private)
  3004. //This is a private parameter to the SM and RM
  3005. //control sequences. The reset state prevents the
  3006. //cursor from moving when characters are recieved
  3007. //while at the right margin. The set state causes
  3008. //these characters to advance to the next line,
  3009. //causing a scroll up if required and permitted.
  3010. //See MODES, SM, and RM.
  3011. SetVTWrap( ptrm );
  3012. break;
  3013. case 8: // DECARM : auto-repeat keys
  3014. //DECARM Auto Repeat Mode (DEC Private)
  3015. //This is a private parameter to the SM and RM
  3016. //control sequences. The reset state causes no
  3017. //keyboard keys to auto-repeat, the set state
  3018. //causes most of them to. See MODES, SM, and RM.
  3019. break;
  3020. case 9: // DECINLM
  3021. //DECINLM Interlace Mode (DEC Private)
  3022. //This is a private parameter to the RM and SM
  3023. //control sequences. The reset state
  3024. //(non-interlace) causes the video processor to
  3025. //display 240 scan lines per frame. The set state
  3026. //causes the video processor to display 480 scan
  3027. //lines per screen. See MODES, RM, and SM.
  3028. break;
  3029. case 18: // Send FF to printer
  3030. break;
  3031. case 19: // Entire screen legal for printer
  3032. break;
  3033. case 25: // Visible cursor
  3034. break;
  3035. case 66: // Application numeric keypad
  3036. break;
  3037. default:
  3038. break;
  3039. }
  3040. }
  3041. else
  3042. {
  3043. switch( ptrm->dwEscCodes[i] )
  3044. {
  3045. case 0:
  3046. // Error (Ignored)
  3047. break;
  3048. case 2: // Keyboard locked
  3049. SetKeyLock( ptrm );
  3050. break;
  3051. case 3: // act on control codes
  3052. break;
  3053. case 4: // Ansi insert mode
  3054. SetInsertMode( ptrm );
  3055. break;
  3056. case 12: // Local echo off
  3057. break;
  3058. case 20: // Ansi linefeed mode ; Newline sends cr/lf
  3059. //LNM Line Feed/New Line Mode
  3060. //This is a parameter to SM and RM control sequences.
  3061. //The reset state causes the interpretation of the
  3062. //<LF> character to imply only vertical movement of
  3063. //the cursor and causes the RETURN key to send the
  3064. //single code <CR>. The set state causes the <LF>
  3065. //character to imply movement to the first position
  3066. //of the following line, and causes the RETURN key
  3067. //to send the code pair <CR><LF>. This is the New
  3068. //Line option.
  3069. //This mode does not affect the Index (IND) or the
  3070. //next line (NEL) format effectors.
  3071. SetLineMode( ptrm );
  3072. break;
  3073. default:
  3074. break;
  3075. }
  3076. }
  3077. }
  3078. ptrm->fEsc = 0;
  3079. break;
  3080. case 'l': // Reset Mode ( unset extended mode )
  3081. //RM Reset Mode
  3082. //<ESC>[ {Ps} ; {Ps} l
  3083. //Resets one or more VT100 modes as specified by each selective
  3084. //parameter in the parameter string. Each mode to be reset is
  3085. //specified by a separate parameter. See MODES and SM.
  3086. for( i = 0; i < ptrm->cEscParams; ++i )
  3087. {
  3088. if( dwDECMode == TRUE )
  3089. {
  3090. switch( ptrm->dwEscCodes[i] )
  3091. { // Field specs
  3092. case 0:
  3093. //Error (Ignored)
  3094. break;
  3095. case 1: // DECCKM : numeric cursor keys
  3096. //DECCKM Cursor Keys Mode (DEC Private)
  3097. //This is a private parameter to the SM and RM
  3098. //control requences. This mode is only effective
  3099. //when the terminal is in keypad application mode
  3100. //(DECPAM) and the ANSI/VT52 mode (DECANM) is set.
  3101. //Under these conditions, if this mode is reset,
  3102. //the cursor keys will send ANSI cursor control
  3103. //commands. If setm the cursor keys will send
  3104. //application function commands (See MODES, RM,
  3105. //and SM).
  3106. /* This is a hack so that you will scroll even after
  3107. * coming out of vi in vt100.
  3108. * In vt100, vi sets scroll regions. but does not
  3109. * reset when vi is exited */
  3110. {
  3111. CONSOLE_SCREEN_BUFFER_INFO info;
  3112. if( !GetConsoleScreenBufferInfo( gwi.hOutput,
  3113. &info ) )
  3114. {
  3115. consoleBufferInfo.dwSize.Y = 0;
  3116. }
  3117. SetMargins( ptrm, 1, info.dwSize.Y );
  3118. }
  3119. ClearVTArrow( ptrm );
  3120. break;
  3121. case 2: // DECANM : ANSI/VT52
  3122. //DECANM ANSI/VT52 Mode (DEC Private)
  3123. //This is a private parameter to the SM and RM
  3124. //control sequences. The reset state causes only
  3125. //VT52 compatible escape sequences to be recognized.
  3126. //The set state causes only ANSI compatible escape
  3127. //sequences to be recognized. See the entries for
  3128. //MODES, SM, and RM.
  3129. SetVT52( ptrm );
  3130. ClearVT52Graphics( ptrm );
  3131. break;
  3132. case 3: // DECCOLM : 80 col
  3133. //DECCOLM Column Mode (DEC Private)
  3134. //This is a private parameter to the SM and RM
  3135. //control sequences. The reset state causes an 80
  3136. //column screen to be used. The set state causes a
  3137. //132 column screen to be used. See MODES, RM, and
  3138. //SM.
  3139. ClearDECCOLM( ptrm );
  3140. GetConsoleScreenBufferInfo( gwi.hOutput,
  3141. &consoleBufferInfo );
  3142. consoleBufferInfo.srWindow.Right = 79;
  3143. dwMaximumWindowSize =
  3144. GetLargestConsoleWindowSize( gwi.hOutput );
  3145. if( 79 > dwMaximumWindowSize.X )
  3146. {
  3147. consoleBufferInfo.srWindow.Right =
  3148. ( SHORT ) ( dwMaximumWindowSize.X - 1 -
  3149. consoleBufferInfo.srWindow.Left );
  3150. }
  3151. dwSize.X = 80;
  3152. dwSize.Y = consoleBufferInfo.dwSize.Y;
  3153. if( consoleBufferInfo.dwSize.X <= 80 )
  3154. {
  3155. SetConsoleScreenBufferSize( gwi.hOutput,
  3156. dwSize );
  3157. SetConsoleWindowInfo( gwi.hOutput, TRUE,
  3158. &(consoleBufferInfo.srWindow) );
  3159. }
  3160. else
  3161. {
  3162. SetConsoleWindowInfo( gwi.hOutput, TRUE,
  3163. &(consoleBufferInfo.srWindow) );
  3164. SetConsoleScreenBufferSize( gwi.hOutput,
  3165. dwSize );
  3166. }
  3167. //Update global data structures.
  3168. ui.dwMaxCol = 80;
  3169. gwi.sbi.dwSize.X = 80;
  3170. consoleBufferInfo.dwSize.X = 80;
  3171. ClearScreen( pwi, ptrm, fdwEntireScreen );
  3172. break;
  3173. case 4: // DECSCLM : jump scroll
  3174. // Scrolling Mode (DEC Private)
  3175. // This is a private parameter to RM and
  3176. // SM control sequences. The reset
  3177. // state causes scrolls to "jump"
  3178. // instantaneuously one line at a time.
  3179. // The set state causes the scrolls to be
  3180. // "smooth", and scrolls at a maximum rate
  3181. // of siz lines/sec. See MODES, RM, and SM.
  3182. break;
  3183. case 5: // DECSCNM ; dark background
  3184. //DECSCNM Screen Mode (DEC Private)
  3185. //This is a private parameter to RM and SM
  3186. //control sequences. The reset state causes
  3187. //the screen to be black with white
  3188. //characters; the set state causes the
  3189. //screen to be white with black characters.
  3190. //See MODES, RM, and SM.
  3191. if( !FIsDECSCNM( ptrm ) )
  3192. {
  3193. break;
  3194. }
  3195. //was setting instead of clearing
  3196. //SetDECSCNM( ptrm );
  3197. ClearDECSCNM( ptrm );
  3198. SetDarkBackground( pwi );
  3199. break;
  3200. case 6: // DECOM : Relative origin ; ignore margins
  3201. //DECOM Origin Mode (DEC Private)
  3202. //This is a private parameter to SM and RM control
  3203. //sequences. The reset state causes the origin (or
  3204. //home position) to be the upper left character
  3205. //position of the screen. Line and column numbers
  3206. //are, therefore, independent of current margin
  3207. //settings. The cursor may be positioned outside
  3208. //the margins with a cursor position (CUP) or
  3209. //horizontal and vertical position (HVP) control.
  3210. //The set state causes the origin to be at the upper
  3211. //left character position within the current margins.
  3212. //Line and column numbers are, therefore, relative
  3213. //to the current margin settings. The cursor cannot
  3214. //be positioned outside of the margins.
  3215. //The cursor is moved to the new home position when
  3216. //this mode is set or reset. Lines and columns are
  3217. //numbered consecutively, with the origin being
  3218. //line 1, column 1.
  3219. ptrm->fRelCursor = FALSE;
  3220. ptrm->dwCurChar = ptrm->dwCurLine = 0;
  3221. break;
  3222. case 7: // DECAWM
  3223. //DECAWM Autowrap Mode (DEC Private)
  3224. //This is a private parameter to the SM and RM
  3225. //control sequences. The reset state prevents the
  3226. //cursor from moving when characters are recieved
  3227. //while at the right margin. The set state causes
  3228. //these characters to advance to the next line,
  3229. //causing a scroll up if required and permitted.
  3230. //See MODES, SM, and RM.
  3231. ClearVTWrap( ptrm );
  3232. break;
  3233. case 8: // DECARM ; auto-repeat keys
  3234. //DECARM Auto Repeat Mode (DEC Private)
  3235. //This is a private parameter to the SM and RM
  3236. //control sequences. The reset state causes no
  3237. //keyboard keys to auto-repeat, the set state
  3238. //causes most of them to. See MODES, SM, and RM.
  3239. break;
  3240. case 9: // DECINLM
  3241. //DECINLM Interlace Mode (DEC Private)
  3242. //This is a private parameter to the RM and SM
  3243. //control sequences. The reset state
  3244. //(non-interlace) causes the video processor to
  3245. //display 240 scan lines per frame. The set state
  3246. //causes the video processor to display 480 scan
  3247. //lines per screen. See MODES, RM, and SM.
  3248. break;
  3249. case 19: // send only scrolling region to printer
  3250. break;
  3251. case 25: // cursor should be invisible
  3252. break;
  3253. case 66: // Numeric keypad
  3254. break;
  3255. default:
  3256. break;
  3257. }
  3258. }
  3259. else
  3260. {
  3261. switch ( ptrm->dwEscCodes[i] )
  3262. {
  3263. case 0:
  3264. //Error (Ignored)
  3265. break;
  3266. case 2: // Keyboard unlocked
  3267. ClearKeyLock( ptrm );
  3268. break;
  3269. case 3: // display control codes
  3270. case 4: // Ansi insert mode ; set overtype mode
  3271. ClearInsertMode( ptrm );
  3272. break;
  3273. case 12: // local echo on
  3274. break;
  3275. case 20: // Ansi linefeed mode ; new-line sends only lf
  3276. //LNM Line Feed/New Line Mode
  3277. //This is a parameter to SM and RM control sequences.
  3278. //The reset state causes the interpretation of the
  3279. //<LF> character to imply only vertical movement of
  3280. //the cursor and causes the RETURN key to send the
  3281. //single code <CR>. The set state causes the <LF>
  3282. //character to imply movement to the first position
  3283. //of the following line, and causes the RETURN key
  3284. //to send the code pair <CR><LF>. This is the New
  3285. //Line option.
  3286. //This mode does not affect the Index (IND) or the
  3287. //next line (NEL) format effectors.
  3288. ClearLineMode( ptrm );
  3289. break;
  3290. default:
  3291. break;
  3292. }
  3293. }
  3294. }
  3295. ptrm->fEsc = 0;
  3296. break;
  3297. case 'i': // VT102 MC Media Copy ; print screen
  3298. if( ptrm->dwEscCodes[0] == 5 )
  3299. {
  3300. // Enter Media copy
  3301. }
  3302. else if( ptrm->dwEscCodes[0] == 4 )
  3303. {
  3304. // Exit Media copy
  3305. }
  3306. ptrm->fEsc = 0;
  3307. case '=':
  3308. break;
  3309. case '}':
  3310. case 'm': // VT102 SGR Select graphic rendition ; set color
  3311. //SGR Select Graphic Rendition
  3312. //<ESC>[ {Ps} ; {Ps} m
  3313. //Invoke the graphic rendition specified by the
  3314. //parameter(s). All following characters transmitted
  3315. //to the VT100 are rendered according to the
  3316. //parameter(s) until the next occurrence of an SGR.
  3317. //FormatEffector.
  3318. //
  3319. //Parameter Meaning
  3320. //---------------------------------------------
  3321. // 0 Attributes Off
  3322. // 1 Bold or increased intensity
  3323. // 4 Underscore
  3324. // 5 Blink
  3325. // 7 Negative (reverse) image
  3326. //
  3327. //All other parameter values are ignored.
  3328. //
  3329. //Without the Advanced Video Option, only one type of
  3330. //character attribute is possible, as determined by the
  3331. //cursor selection; in that case specifying either
  3332. //underscore or reverse will activate the currently
  3333. //selected attribute.
  3334. //
  3335. //[Update: DP6429 defines parameters in the 30-37 range
  3336. //to change foreground color and in the 40-47 range to
  3337. //change background.]
  3338. for( i = 0; i < ( DWORD )ptrm->cEscParams; ++i )
  3339. {
  3340. ptrm->rgdwGraphicRendition[i] = ptrm->dwEscCodes[i];
  3341. ptrm->dwIndexOfGraphicRendition = i;
  3342. }
  3343. SetGraphicRendition( pwi, ptrm, ptrm->dwIndexOfGraphicRendition,
  3344. ptrm->rgdwGraphicRendition );
  3345. ptrm->fEsc = 0;
  3346. break;
  3347. case 'n': // VT102 DSR ; // report cursor position Row X Col
  3348. //DSR Device Status Report Host to VT100 & VT100 to Host
  3349. //<ESC>[ {Ps} n
  3350. //Requests and reports the general status of the VT100 according
  3351. //to the following parameters:
  3352. //Parameter Meaning
  3353. //--------------------------------------------------------------
  3354. // 0 Response from VT100 - Ready, no faults detected
  3355. // 3 Response from VT100 - Malfunction Detected
  3356. // 5 Command from host - Report Status (using a DSR
  3357. // control sequence)
  3358. // 6 Command from host - Report Active Position
  3359. // (using a CPR sequence)
  3360. //DSR with a parameter of 0 or 3 is always sent as a response to
  3361. //a requesting DSR with a parameter of 5.
  3362. pchNBBuffer[0] = 0;
  3363. if( ptrm->dwEscCodes[0] == 5 )
  3364. {
  3365. // Terminal Status Report
  3366. pchNBBuffer[0] = 0x1B;
  3367. pchNBBuffer[1] = '[';
  3368. pchNBBuffer[2] = 'c';
  3369. i = 3;
  3370. }
  3371. else if( ptrm->dwEscCodes[0] == 6 )
  3372. {
  3373. CONSOLE_SCREEN_BUFFER_INFO info;
  3374. if( !GetConsoleScreenBufferInfo( gwi.hOutput,
  3375. &info ) )
  3376. {
  3377. info.srWindow.Top = 0;
  3378. info.srWindow.Left = 0;
  3379. }
  3380. i = _snprintf( ( CHAR * )pchNBBuffer,sizeof(pchNBBuffer)-1,"%c[%d;%dR",
  3381. ( char ) 0x1B,
  3382. (ptrm->dwCurLine + 1 - info.srWindow.Top),
  3383. (ptrm->dwCurChar + 1 - info.srWindow.Left));
  3384. }
  3385. if( pchNBBuffer[0] != 0 )
  3386. {
  3387. ( void ) FWriteToNet( pwi, ( LPSTR ) pchNBBuffer,
  3388. ( int ) i );
  3389. }
  3390. // fall through
  3391. case 'q': // Load LEDs
  3392. //DECLL Load LEDs (DEC Private)
  3393. //<ESC>[ {Ps} q Default Value: 0
  3394. //Load the four programmable LEDs on the keyboard according to
  3395. //theparameter(s).
  3396. //Parameter Meaning
  3397. //-----------------------
  3398. // 0 Clear All LEDs
  3399. // 1 Light L1
  3400. // 2 Light L2
  3401. // 3 Light L3
  3402. // 4 Light L4
  3403. ptrm->fEsc = 0;
  3404. break; // (nothing)
  3405. case 'p':
  3406. break;
  3407. case 'r': // VT102 DECSTBM ; scroll screen
  3408. //DECSTBM Set Top and Bottom Margins (DEC Private)
  3409. //<ESC>[ {Pn} ; {Pn} r Default Values: See Below
  3410. //This sequence sets the top and bottom margins to define the
  3411. //scrolling region. The first parameter is the line number of
  3412. //the first line in the scrolling region; the second parameter
  3413. //is the line number of the bottom line of the scrolling region.
  3414. //Default is the entire screen (no margins). The minimum region
  3415. //allowed is two lines, i.e., the top line must be less than the
  3416. //bottom. The cursor is placed in the home position (See DECOM).
  3417. if( ( ptrm->cEscParams < 2 ) || ( ptrm->dwEscCodes[1] == 0 ) )
  3418. {
  3419. ptrm->dwEscCodes[1] = ui.dwMaxRow;
  3420. }
  3421. if( ptrm->dwEscCodes[0] == 0 )
  3422. {
  3423. ptrm->dwEscCodes[0] = 1;
  3424. }
  3425. {
  3426. CONSOLE_SCREEN_BUFFER_INFO info;
  3427. if( !GetConsoleScreenBufferInfo( gwi.hOutput,
  3428. &info ) )
  3429. {
  3430. consoleBufferInfo.srWindow.Top = 0;
  3431. }
  3432. if(( ptrm->dwEscCodes[0] > 0 ) &&
  3433. ( ptrm->dwEscCodes[0] < ptrm->dwEscCodes[1]) &&
  3434. ( ptrm->dwEscCodes[1] <= ui.dwMaxRow ))
  3435. {
  3436. SetMargins( ptrm,
  3437. info.srWindow.Top + ptrm->dwEscCodes[0],
  3438. info.srWindow.Top + ptrm->dwEscCodes[1] );
  3439. ptrm->dwCurChar = 0;
  3440. ptrm->dwCurLine = ( ptrm->fRelCursor == TRUE )
  3441. ? ptrm->dwScrollTop : 0;
  3442. ptrm->fFlushToEOL = FALSE;
  3443. }
  3444. }
  3445. ptrm->fEsc = 0;
  3446. break;
  3447. case 's': // ANSI.SYS save current cursor pos
  3448. ptrm->dwSaveChar = ptrm->dwCurChar;
  3449. ptrm->dwSaveLine = ptrm->dwCurLine;
  3450. ptrm->fEsc = 0;
  3451. break;
  3452. case 'u': // ANSI.SYS restore current cursor pos
  3453. ptrm->dwCurChar = ptrm->dwSaveChar;
  3454. ptrm->dwCurLine = ptrm->dwSaveLine;
  3455. ptrm->fEsc = 0;
  3456. ptrm->fFlushToEOL = FALSE;
  3457. break;
  3458. case 'x': // DEC terminal report
  3459. // DECREQTPARM Request Terminal Parameters
  3460. // <ESC>[ {Ps} x
  3461. //The host sends this sequence to request the VT100 to
  3462. //send a DECREPTPARM sequence back. {Ps} can be either
  3463. //0 or 1. If 0, the terminal will be allowed to send
  3464. //unsolicited DECREPTPARMs. These reports will be
  3465. //generated each time the terminal exits the SET-UP
  3466. //mode. If {Ps} is 1, then the terminal will only
  3467. //generate DECREPTPARMs in response to a request.
  3468. if( ptrm->dwEscCodes[0] )
  3469. {
  3470. strncpy( pchNBBuffer,"\033[3;1;1;128;128;1;0x",sizeof(pchNBBuffer)-1);
  3471. i = strlen(pchNBBuffer);
  3472. }
  3473. else
  3474. {
  3475. strncpy( pchNBBuffer,"\033[3;1;1;128;128;1;0x",sizeof(pchNBBuffer)-1 );
  3476. i = strlen(pchNBBuffer);
  3477. }
  3478. if( pchNBBuffer[0] != 0 )
  3479. {
  3480. ( void ) FWriteToNet( pwi, ( LPSTR ) pchNBBuffer, i );
  3481. }
  3482. break;
  3483. case 'y':
  3484. //
  3485. //DECTST Invoke Confidence Test
  3486. // <ESC>[ 2 ; {Ps} y
  3487. //Ps is the parameter indicating the test to be done. It is
  3488. //computed by taking the weight indicated for each desired test
  3489. //and adding them together. If Ps is 0, no test is performed
  3490. //but the VT100 is reset.
  3491. //Test Weight
  3492. //--------------------------------------------------------------
  3493. //POST (ROM checksum, RAM NVR, keyboardm and AVO) 1
  3494. //Data Loop Back (Loopback connector required) 2
  3495. //EIA Modem Control Test (Loopback connector req.) 4
  3496. //Repeat Testing until failure 8
  3497. break;
  3498. default: // unhandled
  3499. ptrm->fEsc = 0;
  3500. }
  3501. break;
  3502. case 3:
  3503. // Handle VT102's Esc#
  3504. switch( *pchT )
  3505. {
  3506. case '8': // Fill Screen with "E"
  3507. // DECALN Screen Alignment Display (DEC private)
  3508. // <ESC># 8
  3509. //This command causes the VT100 to fill it's screen with
  3510. //uppercase Es for screen focus and alignment.
  3511. DECALN( pwi, ptrm );
  3512. break;
  3513. //DECDHL Double Height Line (DEC Private)
  3514. //Top Half: <ESC>#3
  3515. //Bottom Half: <ESC>#4
  3516. //These sequences cause the line containing the cursor to become the
  3517. //top or bottom half of a double-height, double width line. The
  3518. //sequences should be used in pairs on adjacent lines with each line
  3519. //containing the same character string. If the line was single
  3520. //width single height, all characters to the right of the center of
  3521. //the screen will be lost. The cursor remains over the same
  3522. //character position, unless it would be to the right of the right
  3523. //margin, in which case it is moved to the right margin.
  3524. case 3:
  3525. break;
  3526. case 4:
  3527. break;
  3528. case 5:
  3529. //DECSWL Single-width Line (DEC Private)
  3530. //<ESC>#5
  3531. //This causes the line which contains the cursor to become
  3532. //single-width, single-height. The cursor remains on the same
  3533. //character position. This is the default condition for all new
  3534. //lines on the screen.
  3535. break;
  3536. case 6:
  3537. //DECDWL Double Width Line (DEC Private)
  3538. //<ESC>#6
  3539. //This causes the line that contains the cursor to become
  3540. //double-width single height. If the line was single width, all
  3541. //characters ro the right of the center of the screen will be
  3542. //lost. The cursor remains over the same character position,
  3543. //unless it would be to the right of the right margin, in which
  3544. //case it is moved to the right margin.
  3545. default:
  3546. break;
  3547. }
  3548. ptrm->fEsc = 0;
  3549. break;
  3550. case 4:
  3551. // Handle VT52's Esc Y
  3552. if(( *pchT ) >= ' ')
  3553. {
  3554. ptrm->dwEscCodes[ptrm->cEscParams++] = *pchT - 0x20;
  3555. if( ptrm->cEscParams == 2 )
  3556. {
  3557. ptrm->dwCurLine = ptrm->dwEscCodes[0];
  3558. ptrm->dwCurChar = ptrm->dwEscCodes[1];
  3559. ptrm->fEsc = 0;
  3560. ptrm->fFlushToEOL = FALSE;
  3561. }
  3562. }
  3563. else
  3564. {
  3565. ptrm->fEsc = 0;
  3566. }
  3567. break;
  3568. case 5:
  3569. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  3570. {
  3571. /* Single-Byte char invoke */
  3572. if (((*pchT) == 'B') || ((*pchT) =='J') || ((*pchT) == 'H'))
  3573. {
  3574. ClearKanjiStatus(ptrm,JIS_KANJI_CODE);
  3575. SetCharSet(ptrm,GRAPHIC_LEFT,rgchJISRomanChars);
  3576. #ifdef DEBUG
  3577. _snwprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1,"VT80 JIS Roman Mode Enter\n");
  3578. OutputDebugString(rgchDbgBfr);
  3579. #endif /* DEBUG */
  3580. }
  3581. ptrm->fEsc = 0;
  3582. }
  3583. break;
  3584. case 6:
  3585. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  3586. {
  3587. /* Multi-Byte char invoke */
  3588. if (((*pchT) == '@') || ((*pchT) =='B'))
  3589. {
  3590. SetKanjiStatus(ptrm,JIS_KANJI_CODE);
  3591. SetCharSet(ptrm,GRAPHIC_LEFT,rgchJISKanjiChars);
  3592. #ifdef DEBUG
  3593. _snwprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1,"VT80 JIS Kanji Mode Enter\n");
  3594. OutputDebugString(rgchDbgBfr);
  3595. #endif /* DEBUG */
  3596. }
  3597. ptrm->fEsc = 0;
  3598. }
  3599. break;
  3600. case 7: /* SUB */
  3601. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  3602. {
  3603. switch( *pchT )
  3604. {
  3605. case 'p':
  3606. /* ACOS Kanji IN (Kanji to G0(GL)) */
  3607. SetKanjiStatus(ptrm,JIS_KANJI_CODE);
  3608. SetCharSet(ptrm,GRAPHIC_LEFT,rgchJISKanjiChars);
  3609. break;
  3610. case 'q':
  3611. /* ACOS Kanji OUT (JIS Roman to G0(GL)) */
  3612. ClearKanjiStatus(ptrm,JIS_KANJI_CODE);
  3613. SetCharSet(ptrm,GRAPHIC_LEFT,rgchJISRomanChars);
  3614. break;
  3615. default:
  3616. break;
  3617. }
  3618. ptrm->fEsc = 0;
  3619. }
  3620. break;
  3621. default:
  3622. break;
  3623. }
  3624. }
  3625. FlushBuffer(pwi, ptrm);
  3626. if( FGetCodeMode(eCodeModeIMEFarEast) )
  3627. {
  3628. if (ui.fDebug & fdwKanjiModeMask)
  3629. {
  3630. SetImeWindow(ptrm);
  3631. }
  3632. }
  3633. cp.X = ( short )ptrm->dwCurChar;
  3634. cp.Y = ( short )ptrm->dwCurLine;
  3635. if( wSaveCurrentLine != cp.Y )
  3636. {
  3637. wSaveCurrentLine = cp.Y;
  3638. if( FGetCodeMode( eCodeModeIMEFarEast ) )
  3639. {
  3640. WriteOneBlankLine( pwi->hOutput, ( WORD )( cp.Y + 1 ) );
  3641. }
  3642. }
  3643. SetConsoleCursorPosition( pwi->hOutput, cp );
  3644. ptrm->fHideCursor = FALSE;
  3645. SaveCurrentWindowCoords();
  3646. }
  3647. void
  3648. HandleCharEvent(WI *pwi, CHAR AsciiChar, DWORD dwControlKeyState)
  3649. {
  3650. DWORD i;
  3651. //This is for informing change in window size to server, if any, before sending a char
  3652. CheckForChangeInWindowSize( );
  3653. /* Map Alt-Control-C to Delete */
  3654. if ((AsciiChar == 3) && ((dwControlKeyState & ALT_PRESSED) && (dwControlKeyState & CTRL_PRESSED)))
  3655. AsciiChar = 0x7F;
  3656. /*Map Ctrl-space to ASCII NUL (0) */
  3657. if( (AsciiChar == ' ') && (dwControlKeyState & CTRL_PRESSED) &&
  3658. !( dwControlKeyState & ( SHIFT_PRESSED | ALT_PRESSED ) ) )
  3659. {
  3660. AsciiChar = 0;
  3661. }
  3662. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  3663. {
  3664. //
  3665. // Fix to bug 1149
  3666. // if (GetKeyState(VK_CONTROL) < 0) {
  3667. //
  3668. if (dwControlKeyState & CTRL_PRESSED) {
  3669. UCHAR RevChar = LOBYTE(LOWORD(AsciiChar));
  3670. UCHAR SendChar;
  3671. ForceJISRomanSend(pwi);
  3672. if(RevChar == VK_SPACE) {
  3673. /*
  3674. * !!! This code is nessesary to control Unix IME
  3675. */
  3676. SendChar = 0x00;
  3677. /* write to network */
  3678. FWriteToNet(pwi, (LPSTR)&SendChar, 1);
  3679. return;
  3680. } else {
  3681. if((RevChar >= '@') && (RevChar <= ']')) {
  3682. SendChar = ( UCHAR ) ( RevChar - '@' );
  3683. /* write to network */
  3684. FWriteToNet(pwi, (LPSTR)&SendChar, 1);
  3685. return;
  3686. } else if((RevChar >= 'a') && (RevChar <= 'z')) {
  3687. SendChar = (UCHAR)toupper(RevChar);
  3688. SendChar -= (UCHAR)'@';
  3689. /* write to network */
  3690. FWriteToNet(pwi, (LPSTR)&SendChar, 1);
  3691. return;
  3692. } else {
  3693. FWriteToNet(pwi, (LPSTR)&RevChar, 1);
  3694. return;
  3695. }
  3696. }
  3697. } else if (FIsVT80(&pwi->trm)) {
  3698. DWORD j = 0;
  3699. BOOL bWriteToNet = TRUE;
  3700. UCHAR *WriteBuffer = pchNBBuffer + 3; /* +3:room for escape sequence.*/
  3701. /* INPUT SJIS -> */
  3702. if (uchInPrev != 0) {
  3703. WriteBuffer[0] = uchInPrev;
  3704. WriteBuffer[1] = (CHAR)AsciiChar;
  3705. uchInPrev = 0;
  3706. j = 2;
  3707. } else if(IsDBCSLeadByte((CHAR)AsciiChar) && uchInPrev == 0) {
  3708. uchInPrev = (CHAR)AsciiChar;
  3709. bWriteToNet = FALSE; /* don't send only lead byte */
  3710. } else {
  3711. WriteBuffer[0] = (CHAR)AsciiChar;
  3712. j = 1;
  3713. }
  3714. /* Do convert */
  3715. if (bWriteToNet) {
  3716. if (WriteBuffer[0] == ASCII_CR && (FIsLineMode(&(gwi.trm)) || ui.nottelnet)) {
  3717. //
  3718. // Automatically add a line feed to a carriage return
  3719. //
  3720. WriteBuffer[1] = ASCII_LF;
  3721. j = 2;
  3722. } else if (FIsJISKanji(&pwi->trm) || FIsJIS78Kanji(&pwi->trm)) {
  3723. /* OUTPUT -> JIS Kanji or JIS 78 Kanji */
  3724. if(j==2) {
  3725. /* full width area code */
  3726. sjistojis( &(WriteBuffer[0]), &(WriteBuffer[1]) );
  3727. /* if we still not send Kanji esc. send it. */
  3728. if( !(GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) ) {
  3729. WriteBuffer -= 3;
  3730. if (FIsJISKanji(&pwi->trm)) {
  3731. WriteBuffer[0] = (UCHAR)0x1B; // Ecs
  3732. WriteBuffer[1] = (UCHAR)'$';
  3733. WriteBuffer[2] = (UCHAR)'B'; // JIS Kanji 1983
  3734. } else {
  3735. WriteBuffer[0] = (UCHAR)0x1B; // Ecs
  3736. WriteBuffer[1] = (UCHAR)'$';
  3737. WriteBuffer[2] = (UCHAR)'@'; // JIS Kanji 1978
  3738. }
  3739. SetKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  3740. j += 3;
  3741. }
  3742. } else {
  3743. /* half width area code */
  3744. /* if we are in Kanji mode, clear it */
  3745. if( GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) {
  3746. WriteBuffer -= 3;
  3747. WriteBuffer[0] = (UCHAR)0x1B; // Ecs
  3748. WriteBuffer[1] = (UCHAR)'(';
  3749. WriteBuffer[2] = (UCHAR)'J'; // JIS Roman
  3750. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  3751. j += 3;
  3752. }
  3753. }
  3754. } else if (FIsEUCKanji(&pwi->trm) || FIsDECKanji(&pwi->trm)) {
  3755. /* OUTPUT -> Japanese EUC / DEC Kanji */
  3756. if(j==2) {
  3757. /* full width area code */
  3758. sjistoeuc( &(WriteBuffer[0]), &(WriteBuffer[1]) );
  3759. } else {
  3760. /* half width area code */
  3761. if(IsKatakana(WriteBuffer[0])) {
  3762. /* Add escape sequence for Katakana */
  3763. WriteBuffer--;
  3764. WriteBuffer[0] = (UCHAR)0x8E; // 0x8E == SS2
  3765. j++;
  3766. }
  3767. }
  3768. } else if (FIsNECKanji(&pwi->trm)) {
  3769. /* OUTPUT -> NEC Kanji */
  3770. if(j==2) {
  3771. /* full width area code */
  3772. sjistojis( &(WriteBuffer[0]), &(WriteBuffer[1]) );
  3773. /* if we still not send Kanji esc. send it. */
  3774. if( !(GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) ) {
  3775. WriteBuffer -= 2;
  3776. WriteBuffer[0] = (UCHAR)0x1B; // Ecs
  3777. WriteBuffer[1] = (UCHAR)'K'; // NEC Kanji IN
  3778. SetKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  3779. j += 2;
  3780. }
  3781. } else {
  3782. /* half width area code */
  3783. /* if we are in Kanji mode, clear it */
  3784. if( GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) {
  3785. WriteBuffer -= 2;
  3786. WriteBuffer[0] = (UCHAR)0x1B; // Ecs
  3787. WriteBuffer[1] = (UCHAR)'H'; // NEC Kanji OUT
  3788. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  3789. j += 2;
  3790. }
  3791. }
  3792. } else if (FIsACOSKanji(&pwi->trm)) {
  3793. /* OUTPUT -> ACOS Kanji */
  3794. if(j==2) {
  3795. /* full width area code */
  3796. sjistojis( &(WriteBuffer[0]), &(WriteBuffer[1]) );
  3797. /* if we still not send Kanji esc. send it. */
  3798. if( !(GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) ) {
  3799. WriteBuffer -= 2;
  3800. WriteBuffer[0] = (UCHAR)0x1A; // Sub
  3801. WriteBuffer[1] = (UCHAR)'p'; // ACOS Kanji IN
  3802. SetKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  3803. j += 2;
  3804. }
  3805. } else {
  3806. /* half width area code */
  3807. /* if we are in Kanji mode, clear it */
  3808. if( GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) {
  3809. WriteBuffer -= 2;
  3810. WriteBuffer[0] = (UCHAR)0x1A; // Sub
  3811. WriteBuffer[1] = (UCHAR)'q'; // ACOS Kanji OUT
  3812. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  3813. j += 2;
  3814. }
  3815. }
  3816. } else {
  3817. /* OUTPUT -> SJIS */
  3818. /* Nothing to do */ ;
  3819. }
  3820. /* echo to local */
  3821. if (ui.nottelnet || (ui.fDebug & fdwLocalEcho)) {
  3822. //InvalidateEntryLine(hwnd, &pwi->trm);
  3823. DoIBMANSIOutput(pwi, &pwi->trm, j, WriteBuffer);
  3824. }
  3825. /* write to network */
  3826. FWriteToNet(pwi, (LPSTR)WriteBuffer, j);
  3827. }
  3828. return;
  3829. }
  3830. }
  3831. pchNBBuffer[0] = (UCHAR)AsciiChar;
  3832. //
  3833. // Automatically add a line feed to a carriage return
  3834. //
  3835. i = 1;
  3836. if (pchNBBuffer[0] == ASCII_CR) // Check whether we need to translate cr->crlf
  3837. {
  3838. if (FIsLineMode(&(gwi.trm)) || ui.nottelnet)
  3839. {
  3840. pchNBBuffer[i++] = ASCII_LF;
  3841. }
  3842. }
  3843. if (ui.nottelnet || (ui.fDebug & fdwLocalEcho))
  3844. {
  3845. DoIBMANSIOutput(pwi, &pwi->trm, i, pchNBBuffer);
  3846. }
  3847. FWriteToNet(pwi, (LPSTR)pchNBBuffer, i);
  3848. }
  3849. BOOL
  3850. FHandleKeyDownEvent(WI *pwi, CHAR AsciiChar, DWORD dwControlKeyState)
  3851. {
  3852. int iIndex = 2; //needed for forming vt302 key sequence
  3853. //This is for informing change in window size to server, if any, before sending a char
  3854. CheckForChangeInWindowSize( );
  3855. switch( LOWORD(AsciiChar) )
  3856. {
  3857. case VK_PAUSE:
  3858. szVt302ShortKeySequence[ iIndex ] = VT302_PAUSE;
  3859. FWriteToNet(pwi, szVt302ShortKeySequence, strlen( szVt302ShortKeySequence ) );
  3860. break;
  3861. case VK_HOME:
  3862. szVt302KeySequence[ iIndex ] = VT302_HOME;
  3863. FWriteToNet(pwi, szVt302KeySequence, strlen( szVt302KeySequence ) );
  3864. break;
  3865. case VK_END:
  3866. szVt302KeySequence[ iIndex ] = VT302_END;
  3867. FWriteToNet(pwi, szVt302KeySequence, strlen( szVt302KeySequence ) );
  3868. break;
  3869. case VK_INSERT:
  3870. szVt302KeySequence[ iIndex ] = VT302_INSERT;
  3871. FWriteToNet(pwi, szVt302KeySequence, strlen( szVt302KeySequence ) );
  3872. break;
  3873. case VK_PRIOR:
  3874. szVt302KeySequence[ iIndex ] = VT302_PRIOR;
  3875. FWriteToNet(pwi, szVt302KeySequence, strlen( szVt302KeySequence ) );
  3876. break;
  3877. case VK_NEXT:
  3878. szVt302KeySequence[ iIndex ] = VT302_NEXT;
  3879. FWriteToNet(pwi, szVt302KeySequence, strlen( szVt302KeySequence ) );
  3880. break;
  3881. case VK_DELETE:
  3882. {
  3883. UCHAR ucCharToBeSent = 0;
  3884. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  3885. {
  3886. ForceJISRomanSend(pwi);
  3887. }
  3888. ucCharToBeSent = ASCII_DEL; //0x7F;
  3889. pchNBBuffer[0] = ucCharToBeSent;
  3890. FWriteToNet(pwi, (LPSTR)pchNBBuffer, 1);
  3891. }
  3892. break;
  3893. case VK_RETURN:
  3894. if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
  3895. {
  3896. ForceJISRomanSend(pwi);
  3897. }
  3898. {
  3899. INT x = 0;
  3900. pchNBBuffer[ x++ ] = ( UCHAR ) LOWORD(AsciiChar);
  3901. if( FIsLineMode( &( gwi.trm ) ) )
  3902. {
  3903. pchNBBuffer[ x++ ] = ( UCHAR ) ASCII_LF;
  3904. }
  3905. FWriteToNet(pwi, (LPSTR)pchNBBuffer, x );
  3906. }
  3907. break;
  3908. case VK_DIVIDE:
  3909. FWriteToNet(pwi, "/", 1);
  3910. break;
  3911. /*F5 to F12 are not used in VT100. Using VT302 sequences*/
  3912. case VK_F5:
  3913. szVt302LongKeySequence[ iIndex ] = CHAR_ONE;
  3914. szVt302LongKeySequence[ iIndex+1 ] = CHAR_FIVE;
  3915. FWriteToNet(pwi, szVt302LongKeySequence, strlen( szVt302LongKeySequence ) );
  3916. break;
  3917. case VK_F6:
  3918. szVt302LongKeySequence[ iIndex ] = CHAR_ONE;
  3919. szVt302LongKeySequence[ iIndex+1 ] = CHAR_SEVEN;
  3920. FWriteToNet(pwi, szVt302LongKeySequence, strlen( szVt302LongKeySequence ) );
  3921. break;
  3922. case VK_F7:
  3923. szVt302LongKeySequence[ iIndex ] = CHAR_ONE;
  3924. szVt302LongKeySequence[ iIndex+1 ] = CHAR_EIGHT;
  3925. FWriteToNet(pwi, szVt302LongKeySequence, strlen( szVt302LongKeySequence ) );
  3926. break;
  3927. case VK_F8:
  3928. szVt302LongKeySequence[ iIndex ] = CHAR_ONE;
  3929. szVt302LongKeySequence[ iIndex+1 ] = CHAR_NINE;
  3930. FWriteToNet(pwi, szVt302LongKeySequence, strlen( szVt302LongKeySequence ) );
  3931. break;
  3932. case VK_F9:
  3933. szVt302LongKeySequence[ iIndex ] = CHAR_TWO;
  3934. szVt302LongKeySequence[ iIndex+1 ] = CHAR_ZERO;
  3935. FWriteToNet(pwi, szVt302LongKeySequence, strlen( szVt302LongKeySequence ) );
  3936. break;
  3937. case VK_F10:
  3938. szVt302LongKeySequence[ iIndex ] = CHAR_TWO;
  3939. szVt302LongKeySequence[ iIndex+1 ] = CHAR_ONE;
  3940. FWriteToNet(pwi, szVt302LongKeySequence, strlen( szVt302LongKeySequence ) );
  3941. break;
  3942. case VK_F11:
  3943. szVt302LongKeySequence[ iIndex ] = CHAR_TWO;
  3944. szVt302LongKeySequence[ iIndex+1 ] = CHAR_THREE;
  3945. FWriteToNet(pwi, szVt302LongKeySequence, strlen( szVt302LongKeySequence ) );
  3946. break;
  3947. case VK_F12:
  3948. szVt302LongKeySequence[ iIndex ] = CHAR_TWO;
  3949. szVt302LongKeySequence[ iIndex+1 ] = CHAR_FOUR;
  3950. FWriteToNet(pwi, szVt302LongKeySequence, strlen( szVt302LongKeySequence ) );
  3951. break;
  3952. default:
  3953. if ( !(ui.fDebug & fdwNoVT100Keys) )
  3954. {
  3955. /*
  3956. * When F1-F4 or the up/down/right/left cursor keys
  3957. * are hit, the bytes sent to the connected machine
  3958. * depend on what mode the terminal emulator is in.
  3959. * There are three relevant modes, VT102 Application,
  3960. * VT102 Cursor, VT52.
  3961. *
  3962. * Mode Pattern sent
  3963. * VT102 App EscO* (3 bytes)
  3964. * VT102 Cursor Esc[* (3 bytes)
  3965. * VT52 Esc* (2 bytes)
  3966. *
  3967. * where '*' represents the byte to be sent and
  3968. * is dependant upon the key that was hit.
  3969. * For the function keys F1-F4, their VT102
  3970. * Cursor mode is the same as their VT102 App mode.
  3971. */
  3972. DWORD iPos = (FIsVT52(&pwi->trm)) ? 1 : 2;
  3973. DWORD cch = (FIsVT52(&pwi->trm)) ? 2 : 3;
  3974. WORD wKeyCode = LOWORD(AsciiChar);
  3975. pchNBBuffer[0] = 0;
  3976. pchNBBuffer[1] = ( UCHAR ) ( (FIsVTArrow(&pwi->trm)) ? 'O' : '[' );
  3977. if ((wKeyCode == VK_F1) || (wKeyCode == VK_F2) ||
  3978. (wKeyCode == VK_F3) || (wKeyCode == VK_F4))
  3979. {
  3980. pchNBBuffer[0] = 0x1B;
  3981. pchNBBuffer[1] = 'O';
  3982. pchNBBuffer[iPos] = ( UCHAR ) ( ((UCHAR)'P'+(UCHAR)(wKeyCode-VK_F1)));
  3983. }
  3984. else if (wKeyCode == VK_UP)
  3985. {
  3986. pchNBBuffer[0] = 0x1B;
  3987. pchNBBuffer[iPos] = 'A';
  3988. }
  3989. else if (wKeyCode == VK_DOWN)
  3990. {
  3991. pchNBBuffer[0] = 0x1B;
  3992. pchNBBuffer[iPos] = 'B';
  3993. }
  3994. else if (wKeyCode == VK_RIGHT)
  3995. {
  3996. pchNBBuffer[0] = 0x1B;
  3997. pchNBBuffer[iPos] = 'C';
  3998. }
  3999. else if (wKeyCode == VK_LEFT)
  4000. {
  4001. pchNBBuffer[0] = 0x1B;
  4002. pchNBBuffer[iPos] = 'D';
  4003. }
  4004. if (pchNBBuffer[0] == 0x1B)
  4005. {
  4006. FWriteToNet(pwi, (LPSTR)pchNBBuffer, (int)cch);
  4007. }
  4008. }
  4009. }
  4010. return TRUE;
  4011. }
  4012. void SetCharSet( TRM *ptrm , INT iCodeArea , UCHAR *pSource )
  4013. {
  4014. if( iCodeArea == GRAPHIC_LEFT )
  4015. ptrm->CurrentCharSet[0] = pSource;
  4016. else
  4017. ptrm->CurrentCharSet[1] = pSource;
  4018. RtlCopyMemory( (PBYTE)((ptrm->puchCharSet) + iCodeArea) ,
  4019. pSource ,
  4020. 128
  4021. ); //Attack ? Size of destination not known.
  4022. }
  4023. void PushCharSet( TRM *ptrm , INT iCodeArea , UCHAR *pSource )
  4024. {
  4025. if( iCodeArea == GRAPHIC_LEFT )
  4026. ptrm->PreviousCharSet[0] = ptrm->CurrentCharSet[0];
  4027. else
  4028. ptrm->PreviousCharSet[1] = ptrm->CurrentCharSet[1];
  4029. SetCharSet( ptrm , iCodeArea , pSource );
  4030. }
  4031. void PopCharSet( TRM *ptrm , INT iCodeArea )
  4032. {
  4033. if( iCodeArea == GRAPHIC_LEFT )
  4034. SetCharSet( ptrm , iCodeArea , ptrm->PreviousCharSet[0]);
  4035. else
  4036. SetCharSet( ptrm , iCodeArea , ptrm->PreviousCharSet[1]);
  4037. }
  4038. void SetupCharSet( TRM *ptrm )
  4039. {
  4040. if( ui.fDebug & fdwVT80Mode ) {
  4041. SetVT80(ptrm);
  4042. ClearKanjiFlag(ptrm);
  4043. #ifdef DEBUG
  4044. snprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, "VT80 - ");
  4045. OutputDebugString(rgchDbgBfr);
  4046. #endif
  4047. switch( ui.fDebug & fdwKanjiModeMask ) {
  4048. case fdwJISKanjiMode :
  4049. case fdwJIS78KanjiMode :
  4050. #ifdef DEBUG
  4051. snprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, "JIS or JIS78 Kanji Mode\n");
  4052. OutputDebugString(rgchDbgBfr);
  4053. #endif
  4054. if((ui.fDebug & fdwKanjiModeMask) == fdwJIS78KanjiMode)
  4055. SetJIS78Kanji(ptrm);
  4056. else
  4057. SetJISKanji(ptrm);
  4058. ptrm->g0 = rgchJISRomanChars;
  4059. ptrm->g1 = rgchKatakanaChars;
  4060. ptrm->g2 = rgchJISKanjiChars;
  4061. ptrm->g3 = rgchNullChars; // rgchJISHojyoKanjiChars;
  4062. SetCharSet(ptrm,GRAPHIC_LEFT ,ptrm->g0);
  4063. SetCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g1);
  4064. break;
  4065. case fdwSJISKanjiMode :
  4066. #ifdef DEBUG
  4067. snprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, "ShiftJIS Kanji Mode\n");
  4068. OutputDebugString(rgchDbgBfr);
  4069. #endif
  4070. SetSJISKanji(ptrm);
  4071. ptrm->g0 = rgchJISRomanChars;
  4072. ptrm->g1 = rgchKatakanaChars;
  4073. ptrm->g2 = rgchNullChars; // N/A
  4074. ptrm->g3 = rgchNullChars; // N/A
  4075. SetCharSet(ptrm,GRAPHIC_LEFT ,ptrm->g0);
  4076. SetCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g1);
  4077. break;
  4078. case fdwEUCKanjiMode :
  4079. #ifdef DEBUG
  4080. snprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, "EUC Kanji Mode\n");
  4081. OutputDebugString(rgchDbgBfr);
  4082. #endif
  4083. SetEUCKanji(ptrm);
  4084. ptrm->g0 = rgchJISRomanChars;
  4085. ptrm->g1 = rgchEUCKanjiChars;
  4086. ptrm->g2 = rgchKatakanaChars;
  4087. ptrm->g3 = rgchNullChars; // rgchEUCHojyoKanjiChars;
  4088. SetCharSet(ptrm,GRAPHIC_LEFT ,ptrm->g0);
  4089. SetCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g1);
  4090. break;
  4091. case fdwNECKanjiMode :
  4092. #ifdef DEBUG
  4093. snprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, "NEC Kanji Mode\n");
  4094. OutputDebugString(rgchDbgBfr);
  4095. #endif
  4096. SetNECKanji(ptrm);
  4097. ptrm->g0 = rgchJISRomanChars;
  4098. ptrm->g1 = rgchKatakanaChars;
  4099. ptrm->g2 = rgchJISKanjiChars;
  4100. ptrm->g3 = rgchNullChars; // rgchJISHojyoKanjiChars;
  4101. SetCharSet(ptrm,GRAPHIC_LEFT ,ptrm->g0);
  4102. SetCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g1);
  4103. break;
  4104. case fdwACOSKanjiMode :
  4105. #ifdef DEBUG
  4106. snprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, "ACOS Kanji Mode\n");
  4107. OutputDebugString(rgchDbgBfr);
  4108. #endif
  4109. SetACOSKanji(ptrm);
  4110. ptrm->g0 = rgchJISRomanChars;
  4111. ptrm->g1 = rgchKatakanaChars;
  4112. ptrm->g2 = rgchJISKanjiChars;
  4113. ptrm->g3 = rgchNullChars; // rgchJISHojyoKanjiChars;
  4114. SetCharSet(ptrm,GRAPHIC_LEFT ,ptrm->g0);
  4115. SetCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g1);
  4116. break;
  4117. case fdwDECKanjiMode :
  4118. #ifdef DEBUG
  4119. snprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, "DEC Kanji Mode\n");
  4120. OutputDebugString(rgchDbgBfr);
  4121. #endif
  4122. SetDECKanji(ptrm);
  4123. ptrm->g0 = rgchJISRomanChars;
  4124. ptrm->g1 = rgchGraphicsChars;
  4125. ptrm->g2 = rgchKatakanaChars;
  4126. ptrm->g3 = rgchDECKanjiChars;
  4127. SetCharSet(ptrm,GRAPHIC_LEFT ,ptrm->g0);
  4128. SetCharSet(ptrm,GRAPHIC_RIGHT,ptrm->g3); // Kanji Terminal Mode
  4129. break;
  4130. }
  4131. } else {
  4132. #ifdef DEBUG
  4133. snprintf(rgchDbgBfr,sizeof(rgchDbgBfr)-1, "VT52/100 Non Kanji Mode\n");
  4134. OutputDebugString(rgchDbgBfr);
  4135. #endif
  4136. if( ui.fDebug & fdwVT52Mode ) SetVT52( ptrm );
  4137. SetCharSet(ptrm,GRAPHIC_LEFT ,rgchIBMAnsiChars);
  4138. SetCharSet(ptrm,GRAPHIC_RIGHT,rgchDefaultRightChars);
  4139. }
  4140. }
  4141. void jistosjis( UCHAR *p1 , UCHAR *p2 )
  4142. {
  4143. UCHAR c1 = *p1;
  4144. UCHAR c2 = *p2;
  4145. int rowOffset = c1 < 95 ? 112 : 176;
  4146. int cellOffset = c1 % 2 ? (c2 > 95 ? 32 : 31) : 126;
  4147. *p1 = ( UCHAR ) ( ((c1 + 1) >> 1) + rowOffset );
  4148. *p2 = ( UCHAR ) ( *p2 + cellOffset );
  4149. }
  4150. void euctosjis( UCHAR *p1 , UCHAR *p2 )
  4151. {
  4152. *p1 -= 128;
  4153. *p2 -= 128;
  4154. jistosjis( p1 , p2 );
  4155. }
  4156. void sjistojis( UCHAR *p1 , UCHAR *p2 )
  4157. {
  4158. UCHAR c1 = *p1;
  4159. UCHAR c2 = *p2;
  4160. int adjust = c2 < 159;
  4161. int rowOffset = c1 < 160 ? 112 : 176;
  4162. int cellOffset = adjust ? (c2 > 127 ? 32 : 31) : 126;
  4163. *p1 = ( UCHAR ) ( ((c1 - rowOffset) << 1) - adjust );
  4164. *p2 = ( UCHAR ) ( *p2 - cellOffset );
  4165. }
  4166. void sjistoeuc( UCHAR *p1 , UCHAR *p2 )
  4167. {
  4168. sjistojis( p1 , p2 );
  4169. *p1 += 128;
  4170. *p2 += 128;
  4171. }
  4172. /******
  4173. BOOL
  4174. IsDBCSCharPoint(
  4175. POINT *ppt
  4176. )
  4177. {
  4178. LPSTR lpstrRow;
  4179. lpstrRow = apcRows[ppt->y];
  4180. return(IsDBCSLeadByte(*(lpstrRow+ppt->x)));
  4181. }
  4182. void
  4183. AlignDBCSPosition(
  4184. POINT *ppt,
  4185. BOOL bLeftAlign
  4186. )
  4187. {
  4188. LPSTR lpstrRow;
  4189. LONG current = 0;
  4190. BOOL bDBCSChar;
  4191. lpstrRow = apcRows[ppt->y];
  4192. while( current < ppt->x ) {
  4193. bDBCSChar = FALSE;
  4194. if(IsDBCSLeadByte(*lpstrRow)) {
  4195. bDBCSChar = TRUE;
  4196. lpstrRow++;
  4197. current++;
  4198. }
  4199. lpstrRow++;
  4200. current++;
  4201. }
  4202. if(bLeftAlign) {
  4203. if(bDBCSChar) {
  4204. current -= 2;
  4205. } else {
  4206. current --;
  4207. }
  4208. }
  4209. ppt->x = current;
  4210. }
  4211. void
  4212. AlignDBCSPosition2(
  4213. POINT *ppt,
  4214. LPCSTR pch,
  4215. BOOL bLeftAlign
  4216. )
  4217. {
  4218. LPCSTR lpstrRow;
  4219. LONG current = 0;
  4220. BOOL bDBCSChar = FALSE;
  4221. lpstrRow = pch;
  4222. while( current < ppt->x ) {
  4223. bDBCSChar = FALSE;
  4224. if(IsDBCSLeadByte(*lpstrRow)) {
  4225. bDBCSChar = TRUE;
  4226. lpstrRow++;
  4227. current++;
  4228. }
  4229. lpstrRow++;
  4230. current++;
  4231. }
  4232. if(bLeftAlign) {
  4233. if(bDBCSChar) {
  4234. current -= 2;
  4235. } else {
  4236. current --;
  4237. }
  4238. }
  4239. ppt->x = current;
  4240. }
  4241. void DBCSTextOut(HDC hdc, int j, int i, LPCSTR pch, int offset, int len)
  4242. {
  4243. POINT pt;
  4244. int x, y;
  4245. int delta;
  4246. pt.x = offset;
  4247. pt.y = i;
  4248. if(offset)
  4249. AlignDBCSPosition2(&pt,pch,(fHSCROLL ? TRUE : FALSE));
  4250. if( (delta = offset - pt.x) > 0 )
  4251. x = aixPos(j) - aixPos(delta);
  4252. else
  4253. x = aixPos(j);
  4254. y = aiyPos(i);
  4255. (void)TextOut((HDC)hdc,x,y,pch+pt.x,len);
  4256. }
  4257. *****/
  4258. void ForceJISRomanSend(WI *pwi)
  4259. {
  4260. CHAR Buffer[5];
  4261. CHAR *WriteBuffer = Buffer;
  4262. int j = 0;
  4263. if( FIsVT80(&pwi->trm) ) {
  4264. if( GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) {
  4265. if(FIsJISKanji(&pwi->trm) || FIsJIS78Kanji(&pwi->trm)) {
  4266. *WriteBuffer++ = (UCHAR)0x1B; // Ecs
  4267. *WriteBuffer++ = (UCHAR)'(';
  4268. *WriteBuffer++ = (UCHAR)'J'; // JIS Roman
  4269. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4270. j = 3;
  4271. } else if (FIsNECKanji(&pwi->trm)) {
  4272. *WriteBuffer++ = (UCHAR)0x1B; // Ecs
  4273. *WriteBuffer++ = (UCHAR)'H'; // NEC Kanji OUT
  4274. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4275. j = 2;
  4276. } else if (FIsACOSKanji(&pwi->trm)) {
  4277. *WriteBuffer++ = (UCHAR)0x1A; // Sub
  4278. *WriteBuffer++ = (UCHAR)'q'; // ACOS Kanji OUT
  4279. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4280. j = 2;
  4281. }
  4282. if( j ) FWriteToNet(pwi, (LPSTR)Buffer, j);
  4283. }
  4284. }
  4285. }
  4286. void FWriteTextDataToNet(HWND hwnd, LPSTR szString, int c)
  4287. {
  4288. WI *pwi = (WI *)GetWindowLongPtr(hwnd, WL_TelWI);
  4289. if ( FIsVT80(&pwi->trm) && !FIsSJISKanji(&pwi->trm) )
  4290. {
  4291. DWORD j = 0;
  4292. UCHAR* WriteBuffer = pchNBBuffer;
  4293. if (FIsJISKanji(&pwi->trm) || FIsJIS78Kanji(&pwi->trm)) {
  4294. while(c > 0) {
  4295. /* OUTPUT -> JIS Kanji or JIS 78 Kanji */
  4296. if (IsDBCSLeadByte(*szString)) {
  4297. /* full width area code */
  4298. if( !(GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) ) {
  4299. if (FIsJISKanji(&pwi->trm)) {
  4300. *WriteBuffer++ = (UCHAR)0x1B; // Ecs
  4301. *WriteBuffer++ = (UCHAR)'$';
  4302. *WriteBuffer++ = (UCHAR)'B'; // JIS Kanji 1983
  4303. } else {
  4304. *WriteBuffer++ = (UCHAR)0x1B; // Ecs
  4305. *WriteBuffer++ = (UCHAR)'$';
  4306. *WriteBuffer++ = (UCHAR)'@'; // JIS Kanji 1978
  4307. }
  4308. SetKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4309. j += 3;
  4310. }
  4311. *WriteBuffer = *szString++;
  4312. *(WriteBuffer+1) = *szString++;
  4313. c -= 2;
  4314. /* convert sjis -> jis */
  4315. sjistojis( WriteBuffer, WriteBuffer+1 );
  4316. WriteBuffer += 2;
  4317. j += 2;
  4318. } else {
  4319. /* half width area code */
  4320. /* if we are in Kanji mode, clear it */
  4321. if( GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) {
  4322. *WriteBuffer++ = (UCHAR)0x1B; // Ecs
  4323. *WriteBuffer++ = (UCHAR)'(';
  4324. *WriteBuffer++ = (UCHAR)'J'; // JIS Roman
  4325. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4326. j += 3;
  4327. }
  4328. /* copy to destination */
  4329. *WriteBuffer++ = *szString++;
  4330. c--; j++;
  4331. }
  4332. }
  4333. } else if (FIsEUCKanji(&pwi->trm) || FIsDECKanji(&pwi->trm)) {
  4334. /* OUTPUT -> Japanese EUC / DEC Kanji */
  4335. while(c > 0) {
  4336. if (IsDBCSLeadByte(*szString)) {
  4337. /* full width area code */
  4338. *WriteBuffer = *szString++;
  4339. *(WriteBuffer+1) = *szString++;
  4340. c -= 2;
  4341. /* convert sjis -> euc */
  4342. sjistoeuc( WriteBuffer, WriteBuffer+1 );
  4343. WriteBuffer += 2;
  4344. j += 2;
  4345. } else {
  4346. /* half width area code */
  4347. if(IsKatakana(*szString)) {
  4348. /* Add escape sequence for Katakana */
  4349. *WriteBuffer++ = (UCHAR)0x8E; // 0x8E == SS2
  4350. j++;
  4351. }
  4352. *WriteBuffer++ = *szString++;
  4353. c--; j++;
  4354. }
  4355. }
  4356. } else if (FIsNECKanji(&pwi->trm)) {
  4357. while(c > 0) {
  4358. /* OUTPUT -> NEC Kanji */
  4359. if (IsDBCSLeadByte(*szString)) {
  4360. /* full width area code */
  4361. if( !(GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) ) {
  4362. *WriteBuffer++ = (UCHAR)0x1B; // Ecs
  4363. *WriteBuffer++ = (UCHAR)'K'; // NEC Kanji IN
  4364. SetKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4365. j += 2;
  4366. }
  4367. *WriteBuffer = *szString++;
  4368. *(WriteBuffer+1) = *szString++;
  4369. c -= 2;
  4370. /* convert sjis -> jis */
  4371. sjistojis( WriteBuffer, WriteBuffer+1 );
  4372. WriteBuffer += 2;
  4373. j += 2;
  4374. } else {
  4375. /* half width area code */
  4376. /* if we are in Kanji mode, clear it */
  4377. if( GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) {
  4378. *WriteBuffer++ = (UCHAR)0x1B; // Ecs
  4379. *WriteBuffer++ = (UCHAR)'H'; // NEC Kanji OUT
  4380. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4381. j += 2;
  4382. }
  4383. /* copy to destination */
  4384. *WriteBuffer++ = *szString++;
  4385. c--; j++;
  4386. }
  4387. }
  4388. } else if (FIsACOSKanji(&pwi->trm)) {
  4389. while(c > 0) {
  4390. /* OUTPUT -> NEC Kanji */
  4391. if (IsDBCSLeadByte(*szString)) {
  4392. /* full width area code */
  4393. if( !(GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) ) {
  4394. *WriteBuffer++ = (UCHAR)0x1A; // Sub
  4395. *WriteBuffer++ = (UCHAR)'p'; // ACOS Kanji IN
  4396. SetKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4397. j += 2;
  4398. }
  4399. *WriteBuffer = *szString++;
  4400. *(WriteBuffer+1) = *szString++;
  4401. c -= 2;
  4402. /* convert sjis -> jis */
  4403. sjistojis( WriteBuffer, WriteBuffer+1 );
  4404. WriteBuffer += 2;
  4405. j += 2;
  4406. } else {
  4407. /* half width area code */
  4408. /* if we are in Kanji mode, clear it */
  4409. if( GetKanjiStatus(&pwi->trm) & JIS_SENDING_KANJI ) {
  4410. *WriteBuffer++ = (UCHAR)0x1A; // Sub
  4411. *WriteBuffer++ = (UCHAR)'q'; // ACOS Kanji OUT
  4412. ClearKanjiStatus(&pwi->trm,JIS_SENDING_KANJI);
  4413. j += 2;
  4414. }
  4415. /* copy to destination */
  4416. *WriteBuffer++ = *szString++;
  4417. c--; j++;
  4418. }
  4419. }
  4420. }
  4421. /* write to network */
  4422. FWriteToNet( ( struct _WI * )hwnd, (LPSTR)pchNBBuffer, j);
  4423. } else {
  4424. /* write to network */
  4425. FWriteToNet( ( struct _WI * )hwnd, (LPSTR)szString, c);
  4426. }
  4427. }
  4428. VOID SetImeWindow(TRM *ptrm)
  4429. {
  4430. COMPOSITIONFORM cf;
  4431. cf.dwStyle = CFS_POINT;
  4432. cf.ptCurrentPos.x = aixPos(ptrm->dwCurChar-ui.nScrollCol);
  4433. cf.ptCurrentPos.y = aiyPos(ptrm->dwCurLine-ui.nScrollRow);
  4434. SetRectEmpty(&cf.rcArea);
  4435. ImmSetCompositionWindow(hImeContext,&cf);
  4436. }