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.

1816 lines
44 KiB

  1. /* File: D:\WACKER\emu\vt100.c (Created: 08-Dec-1993)
  2. *
  3. * Copyright 1994, 1998 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 11 $
  7. * $Date: 3/04/02 12:00p $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <tdll\stdtyp.h>
  12. #include <tdll\tdll.h>
  13. #include <tdll\htchar.h>
  14. #include <tdll\session.h>
  15. #include <tdll\chars.h>
  16. #include <tdll\com.h>
  17. #include <tdll\cloop.h>
  18. #include <tdll\assert.h>
  19. #include <tdll\print.h>
  20. #include <tdll\capture.h>
  21. #include <tdll\update.h>
  22. #include <tdll\backscrl.h>
  23. #include <tdll\mc.h>
  24. #include "emu.h"
  25. #include "emu.hh"
  26. #include "emudec.hh"
  27. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  28. * FUNCTION:
  29. * emuDecGraphic
  30. *
  31. * DESCRIPTION:
  32. * This function is called to display the normal range of characters
  33. * for the emulators. It handles insertion modes, end of line wrapping,
  34. * and cursor positioning.
  35. *
  36. * ARGUMENTS:
  37. *
  38. * RETURNS:
  39. *
  40. */
  41. void emuDecGraphic(const HHEMU hhEmu)
  42. {
  43. ECHAR ccode = hhEmu->emu_code;
  44. ECHAR aechBuf[10];
  45. int iCharsToMove;
  46. int fDecColHold = FALSE;
  47. int iRow = hhEmu->emu_currow;
  48. int iCol = hhEmu->emu_curcol;
  49. ECHAR *tp = hhEmu->emu_apText[hhEmu->emu_imgrow];
  50. PSTATTR ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
  51. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  52. // Initialize a test flag. This is used for a special case when
  53. // emulating a VT100 (and maybe other DEC emulators) and the
  54. // current column position is the maximum. When a character is placed
  55. // at emu_maxcol, instead of advancing the cursor to column 0 of the
  56. // next line, it is instead placed under that last character. When the
  57. // next character arrives, it is placed at column 0 on the next line, and
  58. // then the cursor is advanced as expected.
  59. //
  60. // Special DEC test.
  61. //
  62. if (hhEmu->mode_AWM && iCol == hhEmu->emu_maxcol)
  63. {
  64. if (pstPRI->fDecColHold)
  65. {
  66. fDecColHold = FALSE;
  67. CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession),
  68. CF_CAP_LINES,
  69. tp,
  70. emuRowLen(hhEmu, hhEmu->emu_imgrow));
  71. printEchoString(hhEmu->hPrintEcho,
  72. tp,
  73. emuRowLen(hhEmu, hhEmu->emu_imgrow));
  74. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\r\n"),
  75. StrCharGetByteCount(TEXT("\r\n")));
  76. printEchoString(hhEmu->hPrintEcho,
  77. aechBuf,
  78. sizeof(ECHAR) * 2);
  79. if (iRow == hhEmu->bottom_margin)
  80. (*hhEmu->emu_scroll)(hhEmu, 1, TRUE);
  81. else
  82. ++iRow;
  83. iCol = 0;
  84. (*hhEmu->emu_setcurpos)(hhEmu, iRow, iCol);
  85. tp = hhEmu->emu_apText[hhEmu->emu_imgrow];
  86. ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
  87. }
  88. else
  89. {
  90. iCol = hhEmu->emu_maxcol;
  91. fDecColHold = TRUE;
  92. }
  93. }
  94. // Is the emulator in insert mode?
  95. //
  96. if (hhEmu->mode_IRM == SET)
  97. {
  98. iCharsToMove = (hhEmu->emu_aiEnd[hhEmu->emu_imgrow] - iCol + 1);
  99. if (iCharsToMove + iCol >= hhEmu->emu_maxcol)
  100. iCharsToMove -= 1;
  101. if (iCharsToMove > 0)
  102. {
  103. memmove(&tp[iCol+1],
  104. &tp[iCol],
  105. (unsigned)iCharsToMove * sizeof(ECHAR));
  106. memmove(&ap[iCol+1],
  107. &ap[iCol],
  108. (unsigned)iCharsToMove * sizeof(ECHAR));
  109. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] =
  110. min(hhEmu->emu_aiEnd[hhEmu->emu_imgrow] + 1,
  111. hhEmu->emu_maxcol - 1);
  112. }
  113. }
  114. // Our competetor's are eating the NULL's. DOS ANSI doesn't.
  115. // For now we'll try it their way... - mrw
  116. //
  117. if (ccode == (ECHAR)0)
  118. return;
  119. // Place the character and the current attribute into the image.
  120. //
  121. if (((hhEmu->stUserSettings.nEmuId == EMU_VT100) ||
  122. (hhEmu->stUserSettings.nEmuId == EMU_VT220) ||
  123. (hhEmu->stUserSettings.nEmuId == EMU_VT320) ||
  124. (hhEmu->stUserSettings.nEmuId == EMU_VT100PLUS) ||
  125. (hhEmu->stUserSettings.nEmuId == EMU_VTUTF8)) &&
  126. ccode < sizeof(hhEmu->dspchar))
  127. ccode = hhEmu->dspchar[ccode];
  128. tp[iCol] = ccode;
  129. ap[iCol] = hhEmu->emu_charattr;
  130. // Check for double high, double wide processing.
  131. //
  132. if (pstPRI->aiLineAttr[hhEmu->emu_imgrow] != NO_LINE_ATTR)
  133. {
  134. int iColPrev = iCol;
  135. ap[iCol].dblwilf = 1;
  136. ap[iCol].dblwirt = 0;
  137. ap[iCol].dblhihi = (pstPRI->aiLineAttr[hhEmu->emu_imgrow] == DBL_WIDE_HI) ? 1 : 0;
  138. ap[iCol].dblhilo = (pstPRI->aiLineAttr[hhEmu->emu_imgrow] == DBL_WIDE_LO) ? 1 : 0;
  139. iCol = min(iCol+1, hhEmu->emu_maxcol);
  140. tp[iCol] = ccode;
  141. ap[iCol] = ap[iColPrev];
  142. ap[iCol].dblwilf = 0;
  143. ap[iCol].dblwirt = 1;
  144. }
  145. #ifndef CHAR_NARROW
  146. // Process Double Byte Characters
  147. //
  148. if (QueryCLoopMBCSState(sessQueryCLoopHdl(hhEmu->hSession)))
  149. {
  150. if (isDBCSChar(ccode))
  151. {
  152. int iColPrev = iCol;
  153. ap[iCol].wilf = 1;
  154. ap[iCol].wirt = 0;
  155. iCol = min(iCol+1, hhEmu->emu_maxcol);
  156. tp[iCol] = ccode;
  157. ap[iCol] = ap[iColPrev];
  158. ap[iCol].wilf = 0;
  159. ap[iCol].wirt = 1;
  160. }
  161. #if 0
  162. //mpt:1-23-98 handles the case when an incoming character
  163. // (single or double byte) overwrites the first half of
  164. // a double byte character
  165. if ( iCol < hhEmu->emu_maxcol )
  166. {
  167. //if we orphaned a right half of a dbcs char
  168. if (hhEmu->emu_apAttr[iRow][iCol + 1].wirt == TRUE)
  169. {
  170. //slide characters and attribs to left
  171. iCharsToMove = hhEmu->emu_aiEnd[hhEmu->emu_imgrow] - iCol - 1;
  172. if (iCol + 2 < hhEmu->emu_maxcol && iCharsToMove > 0)
  173. {
  174. memmove(&tp[iCol + 1],
  175. &tp[iCol + 2],
  176. (unsigned)iCharsToMove * sizeof(ECHAR));
  177. memmove(&ap[iCol + 1],
  178. &ap[iCol + 2],
  179. (unsigned)iCharsToMove * sizeof(ECHAR));
  180. }
  181. //blank out character at end of line
  182. tp[hhEmu->emu_aiEnd[hhEmu->emu_imgrow]] = 32;
  183. ap[hhEmu->emu_aiEnd[hhEmu->emu_imgrow]].wirt = 0;
  184. //move end of row since we removed a character
  185. hhEmu->emu_aiEnd[hhEmu->emu_imgrow]--;
  186. //update the image
  187. updateChar(sessQueryUpdateHdl(hhEmu->hSession),
  188. hhEmu->emu_imgrow,
  189. hhEmu->emu_aiEnd[hhEmu->emu_imgrow],
  190. hhEmu->mode_IRM ?
  191. hhEmu->emu_maxcol :
  192. hhEmu->emu_aiEnd[hhEmu->emu_imgrow]);
  193. }
  194. }
  195. #endif
  196. }
  197. #endif //CHAR_NARROW
  198. // Update the end of row index if necessary.
  199. //
  200. if (iCol > hhEmu->emu_aiEnd[hhEmu->emu_imgrow])
  201. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = iCol;
  202. // Update the image.
  203. //
  204. updateChar(sessQueryUpdateHdl(hhEmu->hSession),
  205. iRow,
  206. hhEmu->emu_curcol,
  207. hhEmu->mode_IRM ? hhEmu->emu_maxcol : iCol);
  208. // Move the position of the cursor ahead of the last character
  209. // displayed, checking for end of line wrap.
  210. //
  211. iCol += 1;
  212. // Finally, set the cursor position. This wil reset emu_currow
  213. // and emu_curcol.
  214. //
  215. (*hhEmu->emu_setcurpos)(hhEmu, iRow, iCol);
  216. // Whenever we call setcurpos, it resets pstPRI->fDecColHold so
  217. // don't set till after we postion cursor.
  218. //
  219. pstPRI->fDecColHold = fDecColHold;
  220. return;
  221. }
  222. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  223. * ANSI_DA
  224. *
  225. * DESCRIPTION:
  226. * Sends the device attribute (DA) report to the host.
  227. *
  228. * ARGUMENTS:
  229. * none
  230. *
  231. * RETURNS:
  232. * nothing
  233. */
  234. void ANSI_DA(const HHEMU hhEmu)
  235. {
  236. int fOldValue;
  237. ECHAR ech[15];
  238. CnvrtMBCStoECHAR(ech, sizeof(ech), TEXT("\033[?1;2c"),
  239. StrCharGetByteCount(TEXT("\033[?1;2c")));
  240. fOldValue = CLoopGetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession));
  241. CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), FALSE);
  242. emuSendString(hhEmu, ech, (int)StrCharGetEcharByteCount(ech));
  243. CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), fOldValue);
  244. }
  245. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  246. * vt100_savecursor
  247. *
  248. * DESCRIPTION:
  249. * Saves the current cursor postion; and, it also
  250. * saves display attributes, character set, wrap mode, and origin mode.
  251. *
  252. * ARGUMENTS:
  253. * none
  254. *
  255. * RETURNS:
  256. * nothing
  257. *
  258. * NOTES:
  259. * This function contains Auto Detect code.
  260. */
  261. void vt100_savecursor(const HHEMU hhEmu)
  262. {
  263. ECHAR sel;
  264. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  265. sel = hhEmu->emu_code;
  266. if (sel == ETEXT('7')) /* save cursor & attributes */
  267. {
  268. (*hhEmu->emu_getcurpos)(hhEmu, &pstPRI->sv_row, &pstPRI->sv_col);
  269. pstPRI->sv_state = hhEmu->iCurAttrState;
  270. pstPRI->sv_attr = hhEmu->attrState[hhEmu->iCurAttrState];
  271. vt_charset_save(hhEmu);
  272. pstPRI->sv_AWM = hhEmu->mode_AWM;
  273. pstPRI->sv_DECOM = hhEmu->mode_DECOM;
  274. pstPRI->sv_protectmode = hhEmu->mode_protect;
  275. pstPRI->fAttrsSaved = TRUE;
  276. }
  277. else if (sel == ETEXT('8')) /* restore cursor and attr. */
  278. {
  279. (*hhEmu->emu_setcurpos)(hhEmu, pstPRI->sv_row, pstPRI->sv_col);
  280. //if (pstPRI->sv_col == hhEmu->emu_maxcol)
  281. // hhEmu->emu_curcol = pstPRI->sv_col; /* in order to wrap on next char */
  282. if (pstPRI->fAttrsSaved)
  283. {
  284. hhEmu->iCurAttrState = pstPRI->sv_state;
  285. hhEmu->attrState[hhEmu->iCurAttrState] = pstPRI->sv_attr;
  286. hhEmu->emu_charattr = hhEmu->attrState[hhEmu->iCurAttrState];
  287. }
  288. vt_charset_restore(hhEmu);
  289. hhEmu->mode_AWM = pstPRI->sv_AWM;
  290. hhEmu->mode_DECOM = pstPRI->sv_DECOM;
  291. hhEmu->mode_protect = pstPRI->sv_protectmode;
  292. }
  293. else /* clear saved conditions */
  294. {
  295. pstPRI->sv_row = pstPRI->sv_col = 0;
  296. pstPRI->sv_state = hhEmu->iCurAttrState;
  297. pstPRI->sv_AWM = pstPRI->sv_DECOM = RESET;
  298. pstPRI->sv_protectmode = FALSE;
  299. pstPRI->fAttrsSaved = FALSE;
  300. }
  301. }
  302. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  303. * vt100_answerback
  304. *
  305. * DESCRIPTION:
  306. * Sends the answerback message defined on the menus.
  307. *
  308. * ARGUMENTS:
  309. * none
  310. *
  311. * RETURNS:
  312. * nothing
  313. */
  314. void vt100_answerback(const HHEMU hhEmu)
  315. {
  316. int fOldValue;
  317. TCHAR *sp;
  318. ECHAR *pech = NULL;
  319. sp = hhEmu->acAnswerback;
  320. // If there is nothing to send, there is nothing to send
  321. if (StrCharGetStrLength(sp) == 0)
  322. return;
  323. pech = malloc((unsigned int)StrCharGetByteCount(sp));
  324. if (pech == NULL)
  325. {
  326. assert(FALSE);
  327. return;
  328. }
  329. CnvrtMBCStoECHAR(pech, StrCharGetByteCount(sp), sp, StrCharGetByteCount(sp));
  330. /* to not get recursive answerback's in half duplex */
  331. fOldValue = CLoopGetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession));
  332. CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), FALSE);
  333. emuSendString(hhEmu, pech, (int)StrCharGetEcharByteCount(pech));
  334. free(pech);
  335. pech = NULL;
  336. CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), fOldValue);
  337. }
  338. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  339. * vt100_hostreset
  340. *
  341. * DESCRIPTION:
  342. * Calls vt100_reset() when told to reset by the host.
  343. *
  344. * ARGUMENTS:
  345. * none
  346. *
  347. * RETURNS:
  348. * nothing
  349. */
  350. void vt100_hostreset(const HHEMU hhEmu)
  351. {
  352. vt100_reset(hhEmu, TRUE);
  353. }
  354. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  355. * vt100_reset
  356. *
  357. * DESCRIPTION:
  358. * Resets the emulator.
  359. *
  360. * ARGUMENTS:
  361. * host_request -- TRUE when told to reset by the host.
  362. *
  363. * RETURNS:
  364. * nothing
  365. */
  366. int vt100_reset(const HHEMU hhEmu, const int host_request)
  367. {
  368. hhEmu->mode_KAM = hhEmu->mode_IRM = hhEmu->mode_VEM =
  369. hhEmu->mode_HEM = hhEmu->mode_LNM = hhEmu->mode_DECCKM =
  370. hhEmu->mode_DECOM = hhEmu->mode_DECCOLM = hhEmu->mode_DECPFF =
  371. hhEmu->mode_DECPEX = hhEmu->mode_DECSCNM = hhEmu->mode_25enab =
  372. hhEmu->mode_protect = hhEmu->mode_block =
  373. hhEmu->mode_local = RESET;
  374. hhEmu->mode_SRM = hhEmu->mode_DECTCEM = SET;
  375. hhEmu->mode_AWM = hhEmu->stUserSettings.fWrapLines;
  376. vt_charset_init(hhEmu);
  377. if (host_request)
  378. {
  379. ANSI_Pn_Clr(hhEmu);
  380. ANSI_SGR(hhEmu);
  381. ANSI_RIS(hhEmu);
  382. }
  383. hhEmu->emu_code = ETEXT('>');
  384. vt_alt_kpmode(hhEmu);
  385. if (hhEmu->stUserSettings.nEmuId == EMU_ANSI ||
  386. hhEmu->stUserSettings.nEmuId == EMU_AUTO)
  387. hhEmu->emu_kbdin = ansi_kbdin;
  388. else
  389. hhEmu->emu_kbdin = vt100_kbdin;
  390. hhEmu->mode_AWM = RESET;
  391. hhEmu->stUserSettings.fWrapLines = RESET;
  392. return 0;
  393. }
  394. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  395. * vt100_report
  396. *
  397. * DESCRIPTION:
  398. * Sends the current terminal parameters specified by the DECREQTPARM.
  399. *
  400. * ARGUMENTS:
  401. * none
  402. *
  403. * RETURNS:
  404. * nothing
  405. */
  406. void vt100_report(const HHEMU hhEmu)
  407. {
  408. int sol, i = 0, xspeed = 0;
  409. TCHAR str[20];
  410. TCHAR tempstr[4];
  411. ECHAR ech[20];
  412. int fOldValue;
  413. TCHAR *sp;
  414. long lBaud;
  415. int nDataBits, nParity;
  416. HCOM hCom;
  417. static int baudrates[] = {50, 75, 110, 135, 150, 200, 300, 600, 1200,
  418. 1800, 2000, 2400, 2600, 4800, 9600, 19200};
  419. sol = hhEmu->num_param[0];
  420. if (sol != 0 && sol != 1)
  421. return;
  422. wsprintf(str, TEXT("\x01B[%s;"),
  423. sol == 0 ? (LPTSTR)TEXT("2") : (LPTSTR)TEXT("3"));
  424. hCom = sessQueryComHdl(hhEmu->hSession);
  425. ComGetBaud(hCom, &lBaud);
  426. ComGetDataBits(hCom, &nDataBits);
  427. ComGetParity(hCom, &nParity);
  428. // Parity
  429. //
  430. if (nParity == 0) // None
  431. StrCharCat(str, TEXT("1;"));
  432. else if (nParity == 1) // Odd
  433. StrCharCat(str, TEXT("4;"));
  434. else // Even
  435. StrCharCat(str, TEXT("5;"));
  436. // Data bits
  437. //
  438. nDataBits == 8 ? StrCharCat(str, TEXT("1;")) : StrCharCat(str, TEXT("2;"));
  439. while (xspeed < 120)
  440. {
  441. if ((long)baudrates[i] >= lBaud)
  442. break;
  443. i++;
  444. xspeed += 8;
  445. }
  446. // Recieving speed
  447. //
  448. wsprintf(tempstr, "%d", xspeed);
  449. StrCharCat(str, tempstr);
  450. // Sending speed
  451. //
  452. StrCharCat(str, TEXT(";"));
  453. StrCharCat(str, tempstr);
  454. // Bit rate multiplier ; Flags
  455. //
  456. StrCharCat(str, TEXT(";1;0x"));
  457. sp = str;
  458. CnvrtMBCStoECHAR(ech, sizeof(ech), sp, StrCharGetByteCount(sp));
  459. /* to not get recursive vt100_report's if half duplex */
  460. fOldValue = CLoopGetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession));
  461. CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), FALSE);
  462. emuSendString(hhEmu, ech, (int)StrCharGetEcharByteCount(ech));
  463. CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), fOldValue);
  464. }
  465. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  466. * vt100_kbdin
  467. *
  468. * DESCRIPTION:
  469. * Processes local keyboard keys for the VT100 emulator.
  470. * Note: mode_DECKPAM is TRUE or SET when in DEC KeyPad Aplication Mode.
  471. * Removed key processing 1/3/92. Will replace with something resonable
  472. * later - mrw.
  473. *
  474. * ARGUMENTS:
  475. * key -- key to process
  476. *
  477. * RETURNS:
  478. * nothing
  479. */
  480. int vt100_kbdin(const HHEMU hhEmu, int key, const int fTest)
  481. {
  482. int index = 0;
  483. /* -------------- Check Backspace & Delete keys ------------- */
  484. if (hhEmu->stUserSettings.fReverseDelBk && ((key == VK_BACKSPACE) ||
  485. (key == DELETE_KEY) || (key == DELETE_KEY_EXT)))
  486. {
  487. key = (key == VK_BACKSPACE) ? DELETE_KEY : VK_BACKSPACE;
  488. }
  489. /* -------------- Mapped PF1-PF4 keys ------------- */
  490. #if 0 // mrw:11/3/95 - removed because we can't control num-lock
  491. // in Win95
  492. else if (hhEmu->stUserSettings.fMapPFkeys &&
  493. (index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl4)) != -1)
  494. {
  495. if (!fTest)
  496. emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl4);
  497. }
  498. #endif
  499. /* -------------- Cursor Key Mode ------------- */
  500. else if (hhEmu->mode_DECCKM == SET &&
  501. (index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl3)) != -1)
  502. {
  503. if (!fTest)
  504. emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl3);
  505. }
  506. /* -------------- Keypad Application Mode ------------- */
  507. else if (hhEmu->mode_DECKPAM &&
  508. (index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl2)) != -1)
  509. {
  510. if (!fTest)
  511. emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl2);
  512. }
  513. /* -------------- Normal keys ------------- */
  514. else if ((index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl)) != -1)
  515. {
  516. if (!fTest)
  517. emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl);
  518. }
  519. else
  520. {
  521. index = std_kbdin(hhEmu, key, fTest);
  522. }
  523. return index;
  524. }
  525. #if FALSE // Never used in HyperTerminal.
  526. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  527. * fakevt_kbdin
  528. *
  529. * DESCRIPTION:
  530. * Processes local keyboard keys for the WANG, IBM3278 & RENX3278 emulators.
  531. *
  532. * ARGUMENTS:
  533. * key -- key to process
  534. *
  535. * RETURNS:
  536. * nothing
  537. */
  538. int fakevt_kbdin(const HHEMU hhEmu, int key, const int fTest)
  539. {
  540. int index;
  541. /* -------------- Check Backspace & Delete keys ------------- */
  542. if (hhEmu->stUserSettings.fReverseDelBk && ((key == VK_BACKSPACE) ||
  543. (key == DELETE_KEY) || key == DELETE_KEY_EXT))
  544. {
  545. key = (key == VK_BACKSPACE) ? DELETE_KEY : VK_BACKSPACE;
  546. }
  547. if ((index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl)) != -1)
  548. {
  549. if (!fTest)
  550. emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl);
  551. }
  552. else
  553. {
  554. index = std_kbdin(hhEmu, key, fTest);
  555. }
  556. return index;
  557. }
  558. #endif
  559. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  560. * vt100PrintCommands
  561. *
  562. * DESCRIPTION:
  563. * Processes VT100 printing commands.
  564. *
  565. * ARGUMENTS:
  566. * none
  567. *
  568. * RETURNS:
  569. * nothing
  570. */
  571. void vt100PrintCommands(const HHEMU hhEmu)
  572. {
  573. int line;
  574. int from;
  575. int to;
  576. ECHAR sel;
  577. ECHAR aechBuf[10];
  578. sel = (ECHAR)hhEmu->selector[0];
  579. switch (sel)
  580. {
  581. // Auto print on.
  582. //
  583. case ETEXT(0xF5):
  584. hhEmu->print_echo = TRUE;
  585. printSetStatus(hhEmu->hPrintEcho, TRUE);
  586. break;
  587. // Auto print off.
  588. //
  589. case ETEXT(0xF4):
  590. hhEmu->print_echo = FALSE;
  591. printSetStatus(hhEmu->hPrintEcho, FALSE);
  592. printEchoClose(hhEmu->hPrintEcho);
  593. break;
  594. // Print screen.
  595. //
  596. case ETEXT(0x00):
  597. if (hhEmu->mode_DECPEX == RESET)
  598. from = hhEmu->top_margin, to = hhEmu->bottom_margin;
  599. else
  600. from = 0, to = EMU_DEFAULT_MAXROW;
  601. for (line = from; line <= to; ++line)
  602. printEchoLine(hhEmu->hPrintHost,
  603. hhEmu->emu_apText[row_index(hhEmu, line)],
  604. emuRowLen(hhEmu, row_index(hhEmu, line)));
  605. if (hhEmu->mode_DECPFF == SET) /* print form feed */
  606. {
  607. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("0x0C"),
  608. StrCharGetByteCount(TEXT("0x0C")));
  609. printEchoLine(hhEmu->hPrintHost, aechBuf, sizeof(ECHAR));
  610. }
  611. break;
  612. // Print Cursor line.
  613. //
  614. case ETEXT(0xF1):
  615. printEchoLine(hhEmu->hPrintEcho,
  616. hhEmu->emu_apText[row_index(hhEmu,
  617. hhEmu->emu_currow)],
  618. emuRowLen(hhEmu,
  619. row_index(hhEmu, hhEmu->emu_currow)));
  620. break;
  621. // Enter printer controller mode. State is hard coded for now...
  622. // Bad news.
  623. //
  624. case ETEXT(0x05):
  625. hhEmu->state = 6;
  626. printSetStatus(hhEmu->hPrintHost, TRUE);
  627. break;
  628. // Exit printer controller mode. This is seen when not in
  629. // controller mode.
  630. //
  631. case ETEXT(0x04):
  632. break;
  633. default:
  634. break;
  635. }
  636. }
  637. void vt100_prnc(const HHEMU hhEmu)
  638. {
  639. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  640. ECHAR aechBuf[10];
  641. size_t size;
  642. *pstPRI->pntr++ = hhEmu->emu_code;
  643. *pstPRI->pntr = 0;
  644. ++pstPRI->len_s;
  645. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\033[4i"),
  646. StrCharGetByteCount(TEXT("\033[4i")));
  647. size = (size_t)StrCharGetByteCount(TEXT("\033[4i"));
  648. if ((pstPRI->len_s >= 4) && (memcmp(pstPRI->pntr - 4, aechBuf, size) == 0))
  649. {
  650. /* received termination string, wrap it up */
  651. #if defined(INCL_PRINT_PASSTHROUGH)
  652. if( !hhEmu->stUserSettings.fPrintRaw)
  653. {
  654. printEchoRaw(hhEmu->hPrintHost, pstPRI->storage, pstPRI->len_s - ((*(pstPRI->pntr - 3) == (TCHAR)TEXT('\233')) ? 3 : 4));
  655. }
  656. else
  657. #endif
  658. {
  659. emuPrintChars(hhEmu, pstPRI->storage, pstPRI->len_s - ((*(pstPRI->pntr - 3) == (TCHAR)TEXT('\233')) ? 3 : 4));
  660. printEchoChar(hhEmu->hPrintHost, ETEXT('\n'));
  661. }
  662. pstPRI->pntr = pstPRI->storage;
  663. pstPRI->len_s = 0;
  664. hhEmu->state = 0; /* drop out of this routine */
  665. // Finish-up print job
  666. DbgOutStr("print-control off\r\n", 0, 0, 0, 0, 0);
  667. printEchoClose(hhEmu->hPrintHost);
  668. return;
  669. }
  670. /* haven't received termination sequence yet, is storage filled? */
  671. if (pstPRI->len_s >= (int)(sizeof(pstPRI->storage) - 1))
  672. {
  673. /* copy most of string to print buffer */
  674. #if defined(INCL_PRINT_PASSTHROUGH)
  675. if( !hhEmu->stUserSettings.fPrintRaw )
  676. {
  677. printEchoRaw(hhEmu->hPrintHost, pstPRI->storage, pstPRI->len_s - 4);
  678. }
  679. else
  680. #endif
  681. {
  682. emuPrintChars(hhEmu, pstPRI->storage, pstPRI->len_s - 4);\
  683. }
  684. /* move end of string to beginning of storage */
  685. memmove(pstPRI->storage, &pstPRI->storage[pstPRI->len_s - 4], 4 * sizeof(ECHAR));
  686. pstPRI->pntr = pstPRI->storage + 4;
  687. pstPRI->len_s = 4;
  688. }
  689. }
  690. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  691. * FUNCTION:
  692. *
  693. * DESCRIPTION:
  694. *
  695. * ARGUMENTS:
  696. *
  697. * RETURNS:
  698. *
  699. */
  700. void emuSetDoubleAttr(const HHEMU hhEmu)
  701. {
  702. switch(hhEmu->emu_code)
  703. {
  704. // Double width, double height, top half.
  705. //
  706. case '3':
  707. emuSetDoubleAttrRow(hhEmu, DBL_WIDE_HI);
  708. break;
  709. // Double width double height, bottom half.
  710. //
  711. case '4':
  712. emuSetDoubleAttrRow(hhEmu, DBL_WIDE_LO);
  713. break;
  714. // Single width single height.
  715. //
  716. case '5':
  717. emuSetSingleAttrRow(hhEmu);
  718. break;
  719. // Double width, single height.
  720. //
  721. case '6':
  722. emuSetDoubleAttrRow(hhEmu, DBL_WIDE_SINGLE_HEIGHT);
  723. break;
  724. default:
  725. break;
  726. }
  727. return;
  728. }
  729. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  730. * FUNCTION:
  731. *
  732. * DESCRIPTION:
  733. *
  734. * ARGUMENTS:
  735. *
  736. * RETURNS:
  737. *
  738. */
  739. void emuSetSingleAttrRow(const HHEMU hhEmu)
  740. {
  741. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  742. int iOldRow,
  743. iOldCol,
  744. iImgRow;
  745. // Determine the image row.
  746. //
  747. iImgRow = row_index(hhEmu, hhEmu->emu_currow);
  748. // If the current line attribute is the same as the one we're
  749. // being asked to change to, get out-a-town.
  750. //
  751. if (pstPRI->aiLineAttr[iImgRow] == NO_LINE_ATTR)
  752. return;
  753. // Get the current cursor position.
  754. //
  755. std_getcurpos(hhEmu, &iOldRow, &iOldCol);
  756. // Convert the current row.
  757. //
  758. emuFromDblToSingle(hhEmu);
  759. // Update the line.
  760. //
  761. updateLine(sessQueryUpdateHdl(hhEmu->hSession),
  762. hhEmu->emu_currow,
  763. hhEmu->emu_currow);
  764. // Put the cursor back to where it was, or at the new rightmost
  765. // margin, whichever is less.
  766. //
  767. iOldCol = iOldCol / 2;
  768. iOldCol = min(iOldCol, hhEmu->emu_maxcol);
  769. std_setcurpos(hhEmu, iOldRow, iOldCol);
  770. // Finally, update this rows line attribute value.
  771. //
  772. pstPRI->aiLineAttr[iImgRow] = NO_LINE_ATTR;
  773. return;
  774. }
  775. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  776. * FUNCTION:
  777. *
  778. * DESCRIPTION:
  779. *
  780. * ARGUMENTS:
  781. *
  782. * RETURNS:
  783. *
  784. */
  785. void emuSetDoubleAttrRow(const HHEMU hhEmu, const int iLineAttr)
  786. {
  787. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  788. int iChar,
  789. iImgRow,
  790. iOldRow,
  791. iOldCol,
  792. iUpperAttr,
  793. iLowerAttr;
  794. // Determine the image row.
  795. //
  796. iImgRow = row_index(hhEmu, hhEmu->emu_currow);
  797. // If the current line attribute is the same as the one we're
  798. // being asked to change to, get out-a-town.
  799. //
  800. if (pstPRI->aiLineAttr[iImgRow] == iLineAttr)
  801. return;
  802. // Get the current cursor position.
  803. //
  804. std_getcurpos(hhEmu, &iOldRow, &iOldCol);
  805. // If the current line attribute is anything but NO_LINE_ATTR, call
  806. // a routine that will first put the row back into that state. That
  807. // is, this routine converts FROM a standard line INTO a double wide
  808. // line.
  809. //
  810. if (pstPRI->aiLineAttr[iImgRow] != NO_LINE_ATTR)
  811. {
  812. emuFromDblToSingle(hhEmu);
  813. iOldCol = iOldCol / 2;
  814. }
  815. // Start a shell game!
  816. //
  817. iChar = (hhEmu->emu_maxcol+1) / 2;
  818. // Remember that both of the following values will be zero in the
  819. // case of processing a DBL_WIDE_SINGLE_HEIGHT request.
  820. //
  821. iUpperAttr = (iLineAttr == DBL_WIDE_HI) ? 1 : 0;
  822. iLowerAttr = (iLineAttr == DBL_WIDE_LO) ? 1 : 0;
  823. while (iChar >= 0)
  824. {
  825. hhEmu->emu_apText[iImgRow][(iChar * 2) + 1] = hhEmu->emu_apText[iImgRow][iChar];
  826. hhEmu->emu_apAttr[iImgRow][(iChar * 2) + 1].dblwirt = 1;
  827. hhEmu->emu_apAttr[iImgRow][(iChar * 2) + 1].dblwilf = 0;
  828. hhEmu->emu_apAttr[iImgRow][(iChar * 2) + 1].dblhihi = (unsigned)iUpperAttr;
  829. hhEmu->emu_apAttr[iImgRow][(iChar * 2) + 1].dblhilo = (unsigned)iLowerAttr;
  830. hhEmu->emu_apText[iImgRow][(iChar * 2)] = hhEmu->emu_apText[iImgRow][iChar];
  831. hhEmu->emu_apAttr[iImgRow][(iChar * 2)].dblwirt = 0;
  832. hhEmu->emu_apAttr[iImgRow][(iChar * 2)].dblwilf = 1;
  833. hhEmu->emu_apAttr[iImgRow][(iChar * 2)].dblhihi = (unsigned)iUpperAttr;
  834. hhEmu->emu_apAttr[iImgRow][(iChar * 2)].dblhilo = (unsigned)iLowerAttr;
  835. iChar--;
  836. }
  837. // Null terminate the new text image.
  838. //
  839. hhEmu->emu_apText[iImgRow][hhEmu->emu_maxcol + 1] = ETEXT('\0');
  840. // Update the line.
  841. //
  842. updateLine(sessQueryUpdateHdl(hhEmu->hSession),
  843. hhEmu->emu_currow,
  844. hhEmu->emu_currow);
  845. // Put the cursor back to where it was, or at the new rightmost
  846. // margin, whichever is less.
  847. //
  848. iOldCol = iOldCol * 2;
  849. iOldCol = min(iOldCol, hhEmu->emu_maxcol);
  850. std_setcurpos(hhEmu, iOldRow, iOldCol);
  851. // Finally, update this rows line attribute value.
  852. //
  853. pstPRI->aiLineAttr[iImgRow] = iLineAttr;
  854. return;
  855. }
  856. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  857. * FUNCTION:
  858. * emuFromDblToSingle
  859. *
  860. * DESCRIPTION:
  861. * Note that this is a utility function and does not update the emulator
  862. * image. The calling function should do this.
  863. *
  864. * ARGUMENTS:
  865. *
  866. * RETURNS:
  867. *
  868. */
  869. void emuFromDblToSingle(const HHEMU hhEmu)
  870. {
  871. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  872. register int i;
  873. int iSource,
  874. iDest,
  875. iLastCol,
  876. iImgRow;
  877. // Determine the image row.
  878. //
  879. iImgRow = row_index(hhEmu, hhEmu->emu_currow);
  880. // If the current line attribute is the same as the one we're
  881. // being asked to change to, get out-a-town.
  882. //
  883. if (pstPRI->aiLineAttr[iImgRow] == NO_LINE_ATTR)
  884. return;
  885. // A new shell game.
  886. //
  887. iSource = 0;
  888. iDest = 0;
  889. iLastCol = (hhEmu->emu_maxcol+1) / 2;
  890. // TODO: JCM - in two location below, the text buffer is set to
  891. // spaces, instead of nulls. Figure out why this is the case. We
  892. // should be able to set these to nulls.
  893. while (iSource <= hhEmu->emu_maxcol)
  894. {
  895. if (hhEmu->emu_apText[iImgRow][iSource] == ETEXT('\0')) // TODO 1:
  896. hhEmu->emu_apText[iImgRow][iDest] = ETEXT(' ');
  897. else
  898. hhEmu->emu_apText[iImgRow][iDest] =
  899. hhEmu->emu_apText[iImgRow][iSource];
  900. hhEmu->emu_apAttr[iImgRow][iDest].dblwirt = 0;
  901. hhEmu->emu_apAttr[iImgRow][iDest].dblwilf = 0;
  902. hhEmu->emu_apAttr[iImgRow][iDest].dblhihi = 0;
  903. hhEmu->emu_apAttr[iImgRow][iDest].dblhilo = 0;
  904. iSource += 2;
  905. iDest += 1;
  906. }
  907. for (i = iLastCol; i < MAX_EMUCOLS ; ++i)
  908. {
  909. hhEmu->emu_apText[iImgRow][i] = ETEXT(' '); // TODO 2:
  910. hhEmu->emu_apAttr[iImgRow][i] = hhEmu->emu_clearattr;
  911. /*
  912. hhEmu->emu_apAttr[iImgRow][i].dblwirt = 0;
  913. hhEmu->emu_apAttr[iImgRow][i].dblwilf = 0;
  914. hhEmu->emu_apAttr[iImgRow][i].dblhihi = 0;
  915. hhEmu->emu_apAttr[iImgRow][i].dblhilo = 0;
  916. */
  917. }
  918. pstPRI->aiLineAttr[iImgRow] = NO_LINE_ATTR;
  919. return;
  920. }
  921. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  922. * FUNCTION:
  923. *
  924. * DESCRIPTION:
  925. *
  926. * ARGUMENTS:
  927. *
  928. * RETURNS:
  929. *
  930. */
  931. void emuDecTab(const HHEMU hhEmu)
  932. {
  933. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  934. int col;
  935. col = hhEmu->emu_curcol;
  936. while (col <= hhEmu->emu_maxcol)
  937. {
  938. if (hhEmu->tab_stop[++col])
  939. {
  940. break;
  941. }
  942. }
  943. if (pstPRI->aiLineAttr[hhEmu->emu_imgrow] != NO_LINE_ATTR)
  944. col = (col * 2) - 1;
  945. (*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, col);
  946. }
  947. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  948. * emuDecCUF
  949. *
  950. * DESCRIPTION:
  951. * Moves the cursor forward the specified number of characters, but stops
  952. * at the last character in the current line.
  953. *
  954. * ARGUMENTS:
  955. * none
  956. *
  957. * RETURNS:
  958. * nothing
  959. */
  960. void emuDecCUF(const HHEMU hhEmu)
  961. {
  962. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  963. int nchars, col;
  964. nchars = hhEmu->num_param[hhEmu->num_param_cnt];
  965. if (nchars < 1)
  966. nchars = 1;
  967. if (pstPRI->aiLineAttr[hhEmu->emu_imgrow])
  968. nchars = (nchars * 2);
  969. col = hhEmu->emu_curcol;
  970. col += nchars;
  971. (*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, col);
  972. }
  973. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  974. * emuDecCUP
  975. *
  976. * DESCRIPTION:
  977. * Positions the cursor at the specified row and column. The row & column
  978. * numbering start at 1. If origin mode is on, the positioning is relative
  979. * to the home of the scrolling region.
  980. *
  981. * ARGUMENTS:
  982. * none
  983. *
  984. * RETURNS:
  985. * nothing
  986. */
  987. void emuDecCUP(const HHEMU hhEmu)
  988. {
  989. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  990. int row, col;
  991. row = hhEmu->num_param[0];
  992. col = hhEmu->num_param_cnt > 0 ? hhEmu->num_param[1] : 0;
  993. if (pstPRI->aiLineAttr[row_index(hhEmu, row)] != NO_LINE_ATTR)
  994. col = (col * 2) - 1;
  995. if (row <= 1)
  996. row = 1;
  997. if (col <= 1)
  998. col = 1;
  999. if (hhEmu->mode_DECOM) /* VT100 Origin mode - position rel to margin */
  1000. {
  1001. row += hhEmu->top_margin;
  1002. if (row > hhEmu->bottom_margin + 1)
  1003. row = hhEmu->bottom_margin + 1;
  1004. }
  1005. else /* Position is one-based from upper left */
  1006. {
  1007. if (row > hhEmu->emu_maxrow + 1)
  1008. row = hhEmu->emu_maxrow + 1;
  1009. }
  1010. if (col > hhEmu->emu_maxcol + 1)
  1011. col = hhEmu->emu_maxcol + 1;
  1012. (*hhEmu->emu_setcurpos)(hhEmu, row - 1, col - 1); /* ANSI is one-based, HA zero-based */
  1013. }
  1014. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1015. * emuDecCUB
  1016. *
  1017. * DESCRIPTION: Moves the cursor backwards (to the left) the specified number
  1018. * of characters, but stops at the 1st character in the current
  1019. * line. The vt emus need a special function to handle the
  1020. * virtual column beyond the edge of the screen.
  1021. *
  1022. * ARGUMENTS: none
  1023. *
  1024. * RETURNS: nothing
  1025. */
  1026. void emuDecCUB(const HHEMU hhEmu)
  1027. {
  1028. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1029. int nchars;
  1030. nchars = hhEmu->num_param[hhEmu->num_param_cnt];
  1031. if (nchars < 1)
  1032. nchars = 1;
  1033. if (pstPRI->aiLineAttr[hhEmu->emu_imgrow])
  1034. nchars = (nchars * 2);
  1035. (*hhEmu->emu_setcurpos)(hhEmu,
  1036. hhEmu->emu_currow,
  1037. hhEmu->emu_curcol - nchars);
  1038. }
  1039. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1040. * emuDecED
  1041. *
  1042. * DESCRIPTION:
  1043. * Erases some or all of the virtual screen image and corresponding
  1044. * real screen.
  1045. *
  1046. * ARGUMENTS:
  1047. * none
  1048. *
  1049. * RETURNS:
  1050. * nothing
  1051. */
  1052. void emuDecED(const HHEMU hhEmu)
  1053. {
  1054. int selector = hhEmu->selector[0];
  1055. switch (selector)
  1056. {
  1057. case 0: /* cursor to end of screen */
  1058. case 0x0F:
  1059. case 0xF0:
  1060. (*hhEmu->emu_clearscreen)(hhEmu, 0);
  1061. break;
  1062. case 1: /* start of screen to cursor */
  1063. case 0xF1:
  1064. (*hhEmu->emu_clearscreen)(hhEmu, 1);
  1065. break;
  1066. case 2: /* Entire screen */
  1067. case 0xF2:
  1068. (*hhEmu->emu_clearscreen)(hhEmu, 2);
  1069. break;
  1070. default:
  1071. commanderror(hhEmu);
  1072. break;
  1073. }
  1074. }
  1075. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1076. * emuDecUnload
  1077. *
  1078. * DESCRIPTION:
  1079. * Unloads current emulator by freeing used memory.
  1080. *
  1081. * ARGUMENTS:
  1082. * none
  1083. *
  1084. * RETURNS:
  1085. * nothing
  1086. */
  1087. void emuVT100Unload(const HHEMU hhEmu)
  1088. {
  1089. PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1090. assert(hhEmu);
  1091. if (pstPRI)
  1092. {
  1093. if (pstPRI->aiLineAttr)
  1094. {
  1095. free(pstPRI->aiLineAttr);
  1096. pstPRI->aiLineAttr = 0;
  1097. }
  1098. free(hhEmu->pvPrivate);
  1099. hhEmu->pvPrivate = 0;
  1100. }
  1101. //
  1102. // Make sure to free the key tables that were created when the emulator
  1103. // was loaded, otherwise there is a memory leak. REV: 05/09/2001
  1104. //
  1105. emuKeyTableFree(&hhEmu->stEmuKeyTbl);
  1106. emuKeyTableFree(&hhEmu->stEmuKeyTbl2);
  1107. emuKeyTableFree(&hhEmu->stEmuKeyTbl3);
  1108. emuKeyTableFree(&hhEmu->stEmuKeyTbl4);
  1109. return;
  1110. }
  1111. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1112. * emuDecIND
  1113. *
  1114. * DESCRIPTION:
  1115. * Moves cursor down 1 line and scrolls 1 line if necessary. IND stands
  1116. * for index.
  1117. *
  1118. * ARGUMENTS:
  1119. * none
  1120. *
  1121. * RETURNS:
  1122. * nothing
  1123. */
  1124. void emuDecIND(const HHEMU hhEmu)
  1125. {
  1126. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1127. int fSourceIsDbl, fDestIsDbl;
  1128. int iCol;
  1129. // If we're at the bottom line, scroll.
  1130. //
  1131. if (hhEmu->emu_currow == hhEmu->bottom_margin)
  1132. {
  1133. (*hhEmu->emu_scroll)(hhEmu, 1, TRUE);
  1134. return;
  1135. }
  1136. fSourceIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)] == NO_LINE_ATTR)
  1137. ? FALSE : TRUE;
  1138. fDestIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow + 1)] == NO_LINE_ATTR)
  1139. ? FALSE : TRUE;
  1140. iCol = hhEmu->emu_curcol;
  1141. // If both source and dest are the same, regardless of size, go
  1142. // ahead and make the move. It only matters if they're different.
  1143. //
  1144. if (fSourceIsDbl == fDestIsDbl) // Both the same
  1145. iCol = iCol;
  1146. else if (fSourceIsDbl) // Source is double, dest is single.
  1147. iCol = iCol / 2;
  1148. else // Source is singel, dest is double.
  1149. iCol = iCol * 2;
  1150. (*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow + 1, iCol);
  1151. }
  1152. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1153. * emuDecRI
  1154. *
  1155. * DESCRIPTION:
  1156. * Moves cursor up 1 line and scrolls 1 line if necessary.
  1157. *
  1158. * ARGUMENTS:
  1159. * none
  1160. *
  1161. * RETURNS:
  1162. * nothing
  1163. */
  1164. void emuDecRI(const HHEMU hhEmu)
  1165. {
  1166. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1167. int fSourceIsDbl, fDestIsDbl;
  1168. int iCol;
  1169. // If we're at the bottom line, scroll.
  1170. //
  1171. if (hhEmu->emu_currow == hhEmu->top_margin)
  1172. {
  1173. (*hhEmu->emu_scroll)(hhEmu, 1, FALSE);
  1174. return;
  1175. }
  1176. fSourceIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)] == NO_LINE_ATTR)
  1177. ? FALSE : TRUE;
  1178. fDestIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow - 1)] == NO_LINE_ATTR)
  1179. ? FALSE : TRUE;
  1180. iCol = hhEmu->emu_curcol;
  1181. // If both source and dest are the same, regardless of size, go
  1182. // ahead and make the move. It only matters if they're different.
  1183. //
  1184. if (fSourceIsDbl == fDestIsDbl) // Both the same
  1185. iCol = iCol;
  1186. else if (fSourceIsDbl) // Source is double, dest is single.
  1187. iCol = iCol / 2;
  1188. else // Source is singel, dest is double.
  1189. iCol = iCol * 2;
  1190. (*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow - 1, iCol);
  1191. }
  1192. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1193. * emuDecCUU
  1194. *
  1195. * DESCRIPTION: Moves the cursor up the specified number of lines, but stops
  1196. * at the top of the scrolling region. The column is constant.
  1197. * If above the scrolling region, it stops at the top of the
  1198. * screen.
  1199. *
  1200. * ARGUMENTS:
  1201. * none
  1202. *
  1203. * RETURNS:
  1204. * nothing
  1205. */
  1206. void emuDecCUU(const HHEMU hhEmu)
  1207. {
  1208. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1209. int nlines,
  1210. row,
  1211. fSourceIsDbl,
  1212. fDestIsDbl,
  1213. iCol;
  1214. nlines = hhEmu->num_param[hhEmu->num_param_cnt];
  1215. if (nlines < 1)
  1216. nlines = 1;
  1217. row = hhEmu->emu_currow;
  1218. row -= nlines;
  1219. fSourceIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)] == NO_LINE_ATTR)
  1220. ? FALSE : TRUE;
  1221. fDestIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow - nlines)] == NO_LINE_ATTR)
  1222. ? FALSE : TRUE;
  1223. iCol = hhEmu->emu_curcol;
  1224. // The following code adjusts the column value for double wide
  1225. // characters.
  1226. //
  1227. if (fSourceIsDbl == fDestIsDbl) // Both the same
  1228. iCol = iCol;
  1229. else if (fSourceIsDbl) // Source is double, dest is single.
  1230. iCol = iCol / 2;
  1231. else // Source is singel, dest is double.
  1232. iCol = iCol * 2;
  1233. if (row < hhEmu->top_margin && (hhEmu->emu_currow >= hhEmu->top_margin || hhEmu->emu_currow < 0))
  1234. row = hhEmu->top_margin;
  1235. (*hhEmu->emu_setcurpos)(hhEmu, row, iCol);
  1236. }
  1237. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1238. * emuDecCUD
  1239. *
  1240. * DESCRIPTION: Moves the cursor down the specified number of lines, but stops
  1241. * at the bottom of the scrolling region. The column is constant.
  1242. * If below the scrolling region, it stops at the bottom of the
  1243. * screen.
  1244. *
  1245. * ARGUMENTS:
  1246. * none
  1247. *
  1248. * RETURNS:
  1249. * nothing
  1250. */
  1251. void emuDecCUD(const HHEMU hhEmu)
  1252. {
  1253. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1254. int nlines,
  1255. row,
  1256. fSourceIsDbl,
  1257. fDestIsDbl,
  1258. iCol;
  1259. nlines = hhEmu->num_param[hhEmu->num_param_cnt];
  1260. if (nlines < 1)
  1261. nlines = 1;
  1262. row = hhEmu->emu_currow;
  1263. row += nlines;
  1264. fSourceIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)] == NO_LINE_ATTR)
  1265. ? FALSE : TRUE;
  1266. fDestIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow + nlines)] == NO_LINE_ATTR)
  1267. ? FALSE : TRUE;
  1268. iCol = hhEmu->emu_curcol;
  1269. // The following code adjusts the column value for double wide
  1270. // characters.
  1271. //
  1272. if (fSourceIsDbl == fDestIsDbl) // Both the same
  1273. iCol = iCol;
  1274. else if (fSourceIsDbl) // Source is double, dest is single.
  1275. iCol = iCol / 2;
  1276. else // Source is singel, dest is double.
  1277. iCol = iCol * 2;
  1278. if (row > hhEmu->bottom_margin &&
  1279. (hhEmu->emu_currow <= hhEmu->bottom_margin || hhEmu->emu_currow > hhEmu->emu_maxrow))
  1280. row = hhEmu->bottom_margin;
  1281. (*hhEmu->emu_setcurpos)(hhEmu, row, iCol);
  1282. }
  1283. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1284. * emuDecSetCurPos
  1285. *
  1286. * DESCRIPTION:
  1287. * Moves the cursor to the specified position on the virtual screen.
  1288. * If the cursor is beyond the end of existing text, the virtual screen
  1289. * line is filled out with spaces. If the cursor is beyond the edges of
  1290. * the video display, the video cursor is placed as close as possible
  1291. * to the desired position as the cursor display is changed.
  1292. *
  1293. * ARGUMENTS:
  1294. *
  1295. * RETURNS:
  1296. * nothing
  1297. */
  1298. void emuDecSetCurPos(const HHEMU hhEmu, const int iRow, const int iCol)
  1299. {
  1300. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1301. int iTempCol;
  1302. int i;
  1303. // If we move the cursor, we need to clear the pstPRI->fDecHoldFlag;
  1304. //
  1305. pstPRI->fDecColHold = FALSE;
  1306. hhEmu->emu_currow = max(min(iRow, hhEmu->emu_maxrow), 0);
  1307. hhEmu->emu_curcol = max(min(iCol, hhEmu->emu_maxcol), 0);
  1308. iTempCol = hhEmu->emu_curcol;
  1309. // If the row is a double wide character row, don't ever let the
  1310. // cursor land on an odd column number. If it's there now, back
  1311. // it up one.
  1312. //
  1313. i = row_index(hhEmu, hhEmu->emu_currow);
  1314. if (pstPRI->aiLineAttr[i])
  1315. {
  1316. if (iTempCol % 2 == 1)
  1317. {
  1318. iTempCol -= 1;
  1319. }
  1320. }
  1321. updateCursorPos(sessQueryUpdateHdl(hhEmu->hSession), iRow, iTempCol);
  1322. hhEmu->emu_imgrow = row_index(hhEmu, hhEmu->emu_currow);
  1323. return;
  1324. #if 0
  1325. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1326. int iTempCol;
  1327. hhEmu->emu_currow = max(min(iRow, hhEmu->emu_maxrow), 0);
  1328. hhEmu->emu_curcol = max(min(iCol, hhEmu->emu_maxcol), 0);
  1329. iTempCol = hhEmu->emu_curcol;
  1330. // Do range checking for DEC emulation. This prevents the cursor
  1331. // from being displayed in the 81st position, which is a valid
  1332. // internal location, but is not a valid display column.
  1333. //
  1334. if (hhEmu->emu_curcol == hhEmu->emu_maxcol &&
  1335. (hhEmu->stUserSettings.nEmuId == EMU_VT100 ||
  1336. hhEmu->stUserSettings.nEmuId == EMU_VT100J))
  1337. {
  1338. iTempCol -= 1;
  1339. }
  1340. // If the row is a double wide character row, don't ever let the
  1341. // cursor land on an odd column number. If it's there now, back
  1342. // it up one.
  1343. //
  1344. if (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)])
  1345. {
  1346. if (iTempCol % 2 == 1)
  1347. {
  1348. iTempCol -= 1;
  1349. }
  1350. }
  1351. updateCursorPos(sessQueryUpdateHdl(hhEmu->hSession), iRow, iTempCol);
  1352. hhEmu->emu_imgrow = row_index(hhEmu, hhEmu->emu_currow);
  1353. return;
  1354. #endif
  1355. }
  1356. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1357. * emuDecClearScreen
  1358. *
  1359. * DESCRIPTION:
  1360. * Erases some or all of the virtual screen image.
  1361. *
  1362. * ARGUMENTS:
  1363. * select -- 0 to erase from cursor to end of screen
  1364. * -- 1 to erase from start of screen to cursor
  1365. * -- 2 to erase entire screen
  1366. *
  1367. * RETURNS:
  1368. * nothing
  1369. */
  1370. void emuDecClearScreen(const HHEMU hhEmu, const int nClearSelect)
  1371. {
  1372. const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
  1373. ECHAR aechBuf[10];
  1374. register int r;
  1375. int trow, tcol;
  1376. PSTATTR pstAttr;
  1377. BOOL fSave;
  1378. trow = hhEmu->emu_currow;
  1379. tcol = hhEmu->emu_curcol;
  1380. switch (nClearSelect)
  1381. {
  1382. /* cursor to end of screen */
  1383. case 0:
  1384. fSave = (hhEmu->emu_currow == 0 &&
  1385. hhEmu->emu_curcol == 0) ? TRUE : FALSE;
  1386. for (r = hhEmu->emu_currow + (fSave ? 0 : 1) ; r < MAX_EMUROWS; ++r)
  1387. {
  1388. if (fSave)
  1389. {
  1390. backscrlAdd(sessQueryBackscrlHdl(hhEmu->hSession),
  1391. hhEmu->emu_apText[row_index(hhEmu, r)],
  1392. hhEmu->emu_maxcol+1);
  1393. CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession),
  1394. CF_CAP_SCREENS,
  1395. hhEmu->emu_apText[row_index(hhEmu, r)],
  1396. emuRowLen(hhEmu, row_index(hhEmu, r)));
  1397. printEchoScreen(hhEmu->hPrintEcho,
  1398. hhEmu->emu_apText[row_index(hhEmu, r)],
  1399. emuRowLen(hhEmu, row_index(hhEmu, r)));
  1400. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\r\n"),
  1401. StrCharGetByteCount(TEXT("\r\n")));
  1402. printEchoScreen(hhEmu->hPrintEcho,
  1403. aechBuf,
  1404. sizeof(ECHAR) * 2);
  1405. }
  1406. clear_imgrow(hhEmu, r);
  1407. pstPRI->aiLineAttr[row_index(hhEmu, r)] = NO_LINE_ATTR;
  1408. }
  1409. // Clear the partial row now.
  1410. //
  1411. ECHAR_Fill(hhEmu->emu_apText[row_index(hhEmu, hhEmu->emu_currow)] +
  1412. hhEmu->emu_curcol,
  1413. EMU_BLANK_CHAR,
  1414. (size_t)(MAX_EMUCOLS - hhEmu->emu_curcol + 1));
  1415. if (hhEmu->emu_curcol <= hhEmu->emu_aiEnd[hhEmu->emu_imgrow])
  1416. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = hhEmu->emu_curcol - 1;
  1417. pstAttr = hhEmu->emu_apAttr[row_index(hhEmu, hhEmu->emu_currow)];
  1418. for (r = hhEmu->emu_curcol ; r < MAX_EMUCOLS ; ++r)
  1419. pstAttr[r] = hhEmu->emu_clearattr;
  1420. // Tell the video image what to do. Use the emuDispRgnScrollUp() call
  1421. // instead of RgnClear so edges of terminal get painted if
  1422. // clear attribute changes.
  1423. updateScroll(sessQueryUpdateHdl(hhEmu->hSession),
  1424. 0,
  1425. hhEmu->emu_maxrow,
  1426. hhEmu->emu_maxrow + 1,
  1427. hhEmu->emu_imgtop,
  1428. TRUE);
  1429. (*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, hhEmu->emu_curcol);
  1430. // Added a global to save the clear attribute at the time of
  1431. // notification. This is necessary since the message is posted
  1432. // and a race condition can develop.
  1433. hhEmu->emu_clearattr_sav = hhEmu->emu_clearattr;
  1434. NotifyClient(hhEmu->hSession, EVENT_EMU_CLRATTR, 0);
  1435. break;
  1436. /* start of screen to cursor */
  1437. case 1:
  1438. for (r = 0; r < hhEmu->emu_currow; ++r)
  1439. {
  1440. clear_imgrow(hhEmu, r);
  1441. pstPRI->aiLineAttr[row_index(hhEmu, r)] = NO_LINE_ATTR;
  1442. }
  1443. ECHAR_Fill(hhEmu->emu_apText[row_index(hhEmu, hhEmu->emu_currow)],
  1444. EMU_BLANK_CHAR,
  1445. (size_t)(hhEmu->emu_curcol + 1));
  1446. if (hhEmu->emu_curcol >= hhEmu->emu_aiEnd[hhEmu->emu_imgrow])
  1447. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = EMU_BLANK_LINE;
  1448. pstAttr = hhEmu->emu_apAttr[row_index(hhEmu, hhEmu->emu_currow)];
  1449. for (r = 0 ; r <= hhEmu->emu_curcol ; ++r)
  1450. pstAttr[r] = hhEmu->emu_clearattr;
  1451. (*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, hhEmu->emu_curcol);
  1452. updateLine(sessQueryUpdateHdl(hhEmu->hSession), 0, hhEmu->emu_currow);
  1453. break;
  1454. /* Entire screen */
  1455. case 2:
  1456. for (r = 0; r < MAX_EMUROWS; ++r)
  1457. {
  1458. backscrlAdd(sessQueryBackscrlHdl(hhEmu->hSession),
  1459. hhEmu->emu_apText[row_index(hhEmu, r)],
  1460. hhEmu->emu_maxcol+1);
  1461. CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession),
  1462. CF_CAP_SCREENS,
  1463. hhEmu->emu_apText[row_index(hhEmu, r)],
  1464. emuRowLen(hhEmu, row_index(hhEmu, r)));
  1465. printEchoScreen(hhEmu->hPrintEcho,
  1466. hhEmu->emu_apText[row_index(hhEmu, r)],
  1467. emuRowLen(hhEmu, row_index(hhEmu, r)));
  1468. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\r\n"),
  1469. StrCharGetByteCount(TEXT("\r\n")));
  1470. printEchoScreen(hhEmu->hPrintEcho,
  1471. aechBuf,
  1472. sizeof(ECHAR) * 2);
  1473. clear_imgrow(hhEmu, r);
  1474. pstPRI->aiLineAttr[r] = NO_LINE_ATTR;
  1475. }
  1476. updateScroll(sessQueryUpdateHdl(hhEmu->hSession),
  1477. 0,
  1478. hhEmu->emu_maxrow,
  1479. hhEmu->emu_maxrow + 1,
  1480. hhEmu->emu_imgtop,
  1481. TRUE);
  1482. // Save the clear attribute at the time of
  1483. // notification. This is necessary since the message is posted
  1484. // and a race condition can develop.
  1485. hhEmu->emu_clearattr_sav = hhEmu->emu_clearattr;
  1486. NotifyClient(hhEmu->hSession, EVENT_EMU_CLRATTR, 0);
  1487. break;
  1488. default:
  1489. commanderror(hhEmu);
  1490. }
  1491. (*hhEmu->emu_setcurpos)(hhEmu, trow, tcol);
  1492. }
  1493. /* end of vt100.c */