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.

1245 lines
28 KiB

  1. /* File: D:\WACKER7\emu\emu.c (Created: 08-Dec-1993)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 11 $
  7. * $Date: 7/08/02 6:32p $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <tdll\stdtyp.h>
  12. #include <tdll\tdll.h>
  13. #include <tdll\assert.h>
  14. #include <tdll\mc.h>
  15. #include <tdll\com.h>
  16. #include <tdll\cloop.h>
  17. #include <tdll\capture.h>
  18. #include <tdll\session.h>
  19. #include <tdll\load_res.h>
  20. #include <tdll\globals.h>
  21. #include <tdll\print.h>
  22. #include <tdll\statusbr.h>
  23. #include <tdll\htchar.h>
  24. #include <search.h>
  25. #include <tdll\update.h>
  26. #include <term\res.h>
  27. #include "emu.h"
  28. #include "emu.hh"
  29. #include "emuid.h"
  30. #if defined(INCL_VTUTF8)
  31. extern BOOL DoUTF8;
  32. #endif
  33. static int FFstrlen(const BYTE *);
  34. int _cdecl KeyCmp(const void *, const void *);
  35. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  36. * FUNCTION:
  37. * char_pn
  38. *
  39. * DESCRIPTION:
  40. *
  41. * ARGUMENTS:
  42. *
  43. * RETURNS:
  44. *
  45. */
  46. void char_pn(const HHEMU hhEmu) /* interpret a character as a numeric param */
  47. {
  48. if (hhEmu->emu_code < ETEXT(' '))
  49. hhEmu->emu_code = ETEXT(' ');
  50. hhEmu->selector[hhEmu->selector_cnt] =
  51. hhEmu->num_param[hhEmu->num_param_cnt] = hhEmu->emu_code - ETEXT(' ') + 1;
  52. hhEmu->num_param[++hhEmu->num_param_cnt] = 0;
  53. hhEmu->selector[++hhEmu->selector_cnt] = 0;
  54. }
  55. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  56. * FUNCTION:
  57. * commanderror
  58. *
  59. * DESCRIPTION:
  60. *
  61. * ARGUMENTS:
  62. *
  63. * RETURNS:
  64. *
  65. */
  66. void commanderror(const HHEMU hhEmu)
  67. {
  68. hhEmu->state = 0;
  69. ANSI_Pn_Clr(hhEmu);
  70. }
  71. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  72. * FUNCTION:
  73. * emuAutoDetectLoad
  74. *
  75. * DESCRIPTION:
  76. * if auto dection is on, loads the given emulator ID and sets auto
  77. * detection off.
  78. *
  79. * ARGUMENTS:
  80. * hhEmu - private emulator handle
  81. * EmuID - id of emulator to load
  82. *
  83. * RETURNS:
  84. * void
  85. *
  86. */
  87. void emuAutoDetectLoad(const HHEMU hhEmu, const int nEmuID)
  88. {
  89. if (hhEmu->stUserSettings.nEmuId != EMU_AUTO)
  90. return;
  91. if (hhEmu->stUserSettings.nEmuId != nEmuID)
  92. {
  93. emuLock((HEMU)hhEmu);
  94. hhEmu->stUserSettings.nAutoAttempts = 0;
  95. #ifdef INCL_USER_DEFINED_BACKSPACE_AND_TELNET_TERMINAL_ID
  96. // Load the default telnet terminal id for this emulator. - cab:11/18/96
  97. //
  98. emuQueryDefaultTelnetId(nEmuID, hhEmu->stUserSettings.acTelnetId,
  99. EMU_MAX_TELNETID);
  100. #endif
  101. emuUnlock((HEMU)hhEmu);
  102. emuLoad((HEMU)hhEmu, nEmuID);
  103. }
  104. return;
  105. }
  106. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  107. * FUNCTION:
  108. * emuStdGraphic
  109. *
  110. * DESCRIPTION:
  111. * This function is called to display the normal range of characters
  112. * for the emulators. It handles insertion modes, end of line wrapping,
  113. * and cursor positioning.
  114. *
  115. * ARGUMENTS:
  116. *
  117. * RETURNS:
  118. *
  119. */
  120. void emuStdGraphic(const HHEMU hhEmu)
  121. {
  122. ECHAR ccode;
  123. ECHAR echBuf[10];
  124. int iCharsToMove;
  125. int iRow = hhEmu->emu_currow;
  126. int iCol = hhEmu->emu_curcol;
  127. ECHAR *tp = hhEmu->emu_apText[hhEmu->emu_imgrow];
  128. PSTATTR ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
  129. ccode = hhEmu->emu_code;
  130. // Is the emulator in insert mode?
  131. //
  132. if (hhEmu->mode_IRM == SET)
  133. {
  134. iCharsToMove = hhEmu->emu_aiEnd[hhEmu->emu_imgrow] - iCol;
  135. if (iCharsToMove + iCol >= hhEmu->emu_maxcol)
  136. iCharsToMove -= 1;
  137. if (iCharsToMove > 0)
  138. {
  139. memmove(&tp[iCol+1], &tp[iCol], (unsigned)iCharsToMove * sizeof(ECHAR));
  140. memmove(&ap[iCol+1], &ap[iCol], (unsigned)iCharsToMove * sizeof(ECHAR));
  141. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] =
  142. min(hhEmu->emu_aiEnd[hhEmu->emu_imgrow] + 1,
  143. hhEmu->emu_maxcol - 1);
  144. }
  145. }
  146. // Our competetor's are eating the NULL's. DOS ANSI doesn't.
  147. // For now we'll try it their way... - mrw
  148. //
  149. if (ccode == (ECHAR)0)
  150. return;
  151. // Place the character and the current attribute into the image.
  152. //
  153. if ((hhEmu->stUserSettings.nEmuId == EMU_VT100) &&
  154. ccode < sizeof(hhEmu->dspchar))
  155. ccode = hhEmu->dspchar[ccode];
  156. tp[iCol] = ccode;
  157. ap[iCol] = hhEmu->emu_charattr;
  158. #if !defined(CHAR_NARROW)
  159. if ((hhEmu->stUserSettings.nEmuId == EMU_AUTO) ||
  160. (hhEmu->stUserSettings.nEmuId == EMU_ANSIW))
  161. {
  162. // Process Double Byte Characters
  163. //
  164. if (QueryCLoopMBCSState(sessQueryCLoopHdl(hhEmu->hSession)))
  165. {
  166. if (isDBCSChar(ccode))
  167. {
  168. int iColPrev = iCol;
  169. ap[iCol].wilf = 1;
  170. ap[iCol].wirt = 0;
  171. // Update the end of row index if necessary.
  172. //
  173. if (iCol > hhEmu->emu_aiEnd[hhEmu->emu_imgrow])
  174. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = iCol;
  175. // Update the image.
  176. //
  177. updateChar(sessQueryUpdateHdl(hhEmu->hSession),
  178. iRow,
  179. iCol,
  180. hhEmu->mode_IRM ?
  181. hhEmu->emu_maxcol :
  182. hhEmu->emu_aiEnd[hhEmu->emu_imgrow]);
  183. iCol = min(iCol+1, hhEmu->emu_maxcol);
  184. tp[iCol] = ccode;
  185. ap[iCol] = ap[iColPrev];
  186. ap[iCol].wilf = 0;
  187. ap[iCol].wirt = 1;
  188. }
  189. }
  190. #if 0
  191. //mpt:1-23-98 handles the case when an incoming character
  192. // (single or double byte) overwrites the first half of
  193. // a double byte character
  194. if ( iCol < hhEmu->emu_maxcol )
  195. {
  196. //if we orphaned a right half of a dbcs char
  197. if (hhEmu->emu_apAttr[iRow][iCol + 1].wirt == TRUE)
  198. {
  199. //slide characters and attribs to left
  200. iCharsToMove = hhEmu->emu_aiEnd[hhEmu->emu_imgrow] - iCol + 1;
  201. if (iCol + 2 < hhEmu->emu_maxcol && iCharsToMove > 0)
  202. {
  203. memmove(&tp[iCol + 1],
  204. &tp[iCol + 2],
  205. (unsigned)iCharsToMove * sizeof(ECHAR));
  206. memmove(&ap[iCol + 1],
  207. &ap[iCol + 2],
  208. (unsigned)iCharsToMove * sizeof(ECHAR));
  209. }
  210. //move end of row since we removed a character
  211. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] -= 1;
  212. //update the image
  213. updateChar(sessQueryUpdateHdl(hhEmu->hSession),
  214. hhEmu->emu_imgrow,
  215. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] + 1,
  216. hhEmu->mode_IRM ?
  217. hhEmu->emu_maxcol :
  218. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] + 1);
  219. }
  220. }
  221. #endif
  222. }
  223. #endif //CHAR_NARROW
  224. // Update the end of row index if necessary.
  225. //
  226. if (iCol > hhEmu->emu_aiEnd[hhEmu->emu_imgrow])
  227. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = iCol;
  228. // Update the image.
  229. //
  230. updateChar(sessQueryUpdateHdl(hhEmu->hSession),
  231. iRow,
  232. iCol,
  233. hhEmu->mode_IRM ?
  234. hhEmu->emu_maxcol :
  235. hhEmu->emu_aiEnd[hhEmu->emu_imgrow]);
  236. // Move the position of the cursor ahead of the last character
  237. // displayed, checking for end of line wrap.
  238. //
  239. iCol++;
  240. if (iCol > hhEmu->emu_maxcol)
  241. {
  242. if (hhEmu->mode_AWM)
  243. {
  244. // This code was added, but not enabled because we did not
  245. // want to introduce this without proper testing. If line
  246. // wrap on capture to printer not working is reported as a
  247. // bug, enable this code.
  248. #if 0
  249. printEchoChar(hhEmu->hPrintEcho, ETEXT('\r'));
  250. printEchoChar(hhEmu->hPrintEcho, ETEXT('\n'));
  251. #endif
  252. printEchoString(hhEmu->hPrintEcho, tp, emuRowLen(hhEmu, iRow));
  253. CnvrtMBCStoECHAR(echBuf, sizeof(echBuf), TEXT("\r\n"),
  254. StrCharGetByteCount(TEXT("\r\n")));
  255. printEchoString(hhEmu->hPrintEcho,
  256. echBuf,
  257. sizeof(ECHAR) * 2);
  258. CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession),
  259. CF_CAP_LINES,
  260. tp,
  261. emuRowLen(hhEmu, iRow));
  262. if (iRow == hhEmu->bottom_margin)
  263. (*hhEmu->emu_scroll)(hhEmu, 1, TRUE);
  264. else
  265. iRow += 1;
  266. iCol = 0;
  267. }
  268. else
  269. {
  270. iCol = hhEmu->emu_maxcol;
  271. }
  272. }
  273. // Finally, set the cursor position. This wil reset emu_currow
  274. // and emu_curcol.
  275. //
  276. (*hhEmu->emu_setcurpos)(hhEmu, iRow, iCol);
  277. return;
  278. }
  279. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  280. * emu_cleartabs
  281. *
  282. * DESCRIPTION:
  283. * Clears one or all tab stops.
  284. *
  285. * ARGUMENTS:
  286. * selector -- 0 clears tab at current cursor position
  287. * -- 3 clears all tabs in current line
  288. *
  289. * RETURNS:
  290. * nothing
  291. */
  292. void emu_cleartabs(const HHEMU hhEmu, int selecter)
  293. {
  294. int col;
  295. switch (selecter)
  296. {
  297. case 0:
  298. hhEmu->tab_stop[hhEmu->emu_curcol] = FALSE;
  299. break;
  300. case 3:
  301. for (col = 0; col <= hhEmu->emu_maxcol; ++col)
  302. hhEmu->tab_stop[col] = FALSE;
  303. break;
  304. default:
  305. commanderror(hhEmu);
  306. break;
  307. }
  308. return;
  309. }
  310. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  311. * emuSendKeyString
  312. *
  313. * DESCRIPTION:
  314. * Sends the specified string.
  315. *
  316. * ARGUMENTS:
  317. * hhEmu - The internal emulator handle.
  318. * nIndex - Position of key in keytable array.
  319. * pstKeyTbl - Address of key strings table.
  320. *
  321. * RETURNS:
  322. * nothing
  323. */
  324. void emuSendKeyString(const HHEMU hhEmu,
  325. const nIndex,
  326. const PSTKEYTABLE pstKeyTbl)
  327. {
  328. ECHAR str[80];
  329. PSTKEY pstKey;
  330. TCHAR *pszTemp;
  331. memset(str, ETEXT('\0'), sizeof(str));
  332. assert(nIndex >= 0 && nIndex < pstKeyTbl->iMaxKeys);
  333. pstKey = pstKeyTbl->pstKeys + nIndex;
  334. pszTemp = pstKey->fPointer ? pstKey->u.pachKeyStr : pstKey->u.achKeyStr;
  335. CnvrtMBCStoECHAR(str, sizeof(str), pszTemp,
  336. StrCharGetByteCount(pszTemp));
  337. emuSendString(hhEmu, str, pstKey->uLen);
  338. }
  339. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  340. * emuSendString
  341. *
  342. * DESCRIPTION:
  343. * Sends the specified string.
  344. *
  345. * ARGUMENTS:
  346. * str -- address of string
  347. * strlen -- length of string
  348. *
  349. * RETURNS:
  350. * nothing
  351. */
  352. void emuSendString(const HHEMU hhEmu, ECHAR *str, int nLen)
  353. {
  354. TCHAR *pchMBCS = NULL;
  355. TCHAR *pchTemp = NULL;
  356. unsigned long ulSize = 0;
  357. unsigned int i = 0;
  358. unsigned long ulDestSize = nLen + 1;
  359. // This probably allocates way to many bytes, but if the incomming
  360. // string is all MBC's we are safe.
  361. pchMBCS = malloc((unsigned long)ulDestSize * sizeof(TCHAR));
  362. if (pchMBCS == NULL)
  363. {
  364. assert(FALSE);
  365. return;
  366. }
  367. TCHAR_Fill(pchMBCS, TEXT('\0'), nLen + 1);
  368. #if defined(INCL_VTUTF8)
  369. if (!DoUTF8)
  370. {
  371. ulSize = (unsigned long)CnvrtECHARtoMBCS(pchMBCS, (unsigned long)ulDestSize * sizeof(TCHAR),
  372. str, (unsigned long)nLen * sizeof(ECHAR));
  373. }
  374. else
  375. {
  376. while (nLen > (int)ulSize)
  377. {
  378. pchMBCS[ulSize++] = (str[ulSize] & 0x00FF);
  379. }
  380. }
  381. #else
  382. ulSize = (unsigned long)CnvrtECHARtoMBCS(pchMBCS, (unsigned long)ulDestSize * sizeof(TCHAR),
  383. str, (unsigned long)nLen * sizeof(ECHAR));
  384. #endif
  385. //
  386. // Make sure the string is NULL terminated. REV: 07/23/2001
  387. //
  388. pchMBCS[ulDestSize - 1] = TEXT('\0');
  389. pchTemp = pchMBCS;
  390. ulSize = StrCharGetStrLength(pchTemp);
  391. #if 0 //DEADWOOD:jkh, 12/12/1996
  392. // Some systems mistake something like ESC 0 D if the codes
  393. // are sent in separate packets. This now sends such sequences
  394. // in a single socket write which should usually put them in
  395. // the same packet (though it doesn't guarantee to do so.
  396. // Loop through the # of bytes in the string
  397. for (i = 0 ; i < ulSize ; ++i)
  398. CLoopCharOut(sessQueryCLoopHdl(hhEmu->hSession), *pchTemp++);
  399. #endif
  400. CLoopBufrOut(sessQueryCLoopHdl(hhEmu->hSession), pchTemp, ulSize);
  401. free(pchMBCS);
  402. pchMBCS = NULL;
  403. return;
  404. }
  405. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  406. * emu_reverse_image
  407. *
  408. * DESCRIPTION:
  409. * Reverses the foreground and background colors for the entire virtual
  410. * image.
  411. *
  412. * ARGUMENTS:
  413. * none
  414. *
  415. * RETURNS:
  416. * nothing
  417. */
  418. void emu_reverse_image(const HHEMU hhEmu)
  419. {
  420. int nRow, nCol;
  421. STATTR stOldAttr;
  422. PSTATTR pstAttr;
  423. // Set reverse screen mode for both clear and character attributes.
  424. //
  425. hhEmu->attrState[CSCLEAR_STATE].revvid =
  426. !hhEmu->attrState[CSCLEAR_STATE].revvid;
  427. hhEmu->emu_clearattr_sav =
  428. hhEmu->emu_clearattr = hhEmu->attrState[CSCLEAR_STATE];
  429. hhEmu->attrState[CS_STATE].revvid =
  430. !hhEmu->attrState[CS_STATE].revvid;
  431. hhEmu->emu_charattr = hhEmu->attrState[CS_STATE];
  432. for (nRow = 0; nRow < (hhEmu->emu_maxrow+1); nRow++)
  433. {
  434. pstAttr = hhEmu->emu_apAttr[nRow];
  435. for (nCol = 0 ; nCol <= hhEmu->emu_maxcol ; ++nCol, ++pstAttr)
  436. {
  437. stOldAttr = *pstAttr;
  438. pstAttr->txtclr = stOldAttr.bkclr;
  439. pstAttr->bkclr = stOldAttr.txtclr;
  440. }
  441. }
  442. updateLine(sessQueryUpdateHdl(hhEmu->hSession), 0, hhEmu->emu_maxrow);
  443. NotifyClient(hhEmu->hSession, EVENT_EMU_CLRATTR, 0);
  444. return;
  445. }
  446. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  447. * emu_is25lines
  448. *
  449. * DESCRIPTION:
  450. * Tells the calling function if the emulator is using the 25th line.
  451. *
  452. * ARGUMENTS:
  453. * none
  454. *
  455. * RETURNS:
  456. * TRUE if the emulator is using the 25th line
  457. */
  458. int emu_is25lines(const HHEMU hhEmu)
  459. {
  460. return (hhEmu->mode_25enab ? TRUE : FALSE);
  461. }
  462. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  463. * emu_kbdlocked
  464. *
  465. * DESCRIPTION:
  466. * Replacement kbdin that ignores all keys passed to it.
  467. *
  468. * ARGUMENTS:
  469. * key -- key to process
  470. *
  471. * RETURNS:
  472. * nothing
  473. */
  474. /* ARGSUSED */
  475. int emu_kbdlocked(const HHEMU hhEmu, int key, const int fTest)
  476. {
  477. return -1;
  478. }
  479. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  480. * FUNCTION:
  481. * nothing
  482. *
  483. * DESCRIPTION:
  484. *
  485. * ARGUMENTS:
  486. *
  487. * RETURNS:
  488. *
  489. */
  490. /* ARGSUSED */
  491. void nothing(const HHEMU hhEmu)
  492. {
  493. return;
  494. }
  495. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  496. * FUNCTION:
  497. * emuKbdKeyLookup
  498. *
  499. * DESCRIPTION:
  500. * Main keyboard translation routine for all emulators. Note, this
  501. * routine will not lookup keys unless the iUseTermKeys flag is set.
  502. *
  503. * ARGUMENTS:
  504. * UINT key - lower byte is char or virtual key, upper byte has flags
  505. *
  506. * RETURNS:
  507. * Index if translated, else minus one.
  508. *
  509. */
  510. int emuKbdKeyLookup(const HHEMU hhEmu,
  511. const int uKey,
  512. const PSTKEYTABLE pstKeyTbl)
  513. {
  514. PSTKEY pstKey;
  515. if (hhEmu->stUserSettings.nTermKeys == EMU_KEYS_ACCEL)
  516. return -1;
  517. pstKey = bsearch(&uKey,
  518. pstKeyTbl->pstKeys,
  519. (unsigned)pstKeyTbl->iMaxKeys,
  520. sizeof(KEY), KeyCmp);
  521. if (pstKey)
  522. return (int)(pstKey - pstKeyTbl->pstKeys);
  523. return -1;
  524. }
  525. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  526. * FUNCTION:
  527. * emuKeyTableLoad
  528. *
  529. * DESCRIPTION:
  530. *
  531. * ARGUMENTS:
  532. *
  533. * RETURNS:
  534. *
  535. */
  536. /* ARGSUSED */
  537. int emuKeyTableLoad(const HHEMU hhEmu,
  538. const KEYTBLSTORAGE pstKeySource[],
  539. const int nNumKeys,
  540. PSTKEYTABLE const pstKeyTbl)
  541. {
  542. int l;
  543. int nLoop = 0;
  544. PSTKEY pstKeys;
  545. if (nNumKeys == 0)
  546. return FALSE;
  547. emuKeyTableFree(pstKeyTbl); // free previous instance
  548. if ((pstKeyTbl->pstKeys = malloc((unsigned)(nNumKeys * (int)sizeof(KEY))))
  549. == 0)
  550. {
  551. assert(0);
  552. return FALSE;
  553. }
  554. memset(pstKeyTbl->pstKeys, 0, (unsigned)(nNumKeys * (int)sizeof(KEY)));
  555. if (pstKeyTbl->pstKeys)
  556. {
  557. for (pstKeys = pstKeyTbl->pstKeys; nLoop < nNumKeys ; pstKeys++, nLoop++)
  558. {
  559. pstKeys->key = pstKeySource[nLoop].KeyCode;
  560. l = FFstrlen(pstKeySource[nLoop].achKeyStr);
  561. if ( l <= (int)sizeof(LPTSTR) )
  562. {
  563. pstKeys->fPointer = FALSE;
  564. // Because of the goofy resource compiler, it was
  565. // necessary to define a "\xff" in the resource data,
  566. // when what we really wanted was a "\x00\xff". So,
  567. // now we determine when this case occurs, and load the
  568. // \x00 value manually. Note that there is an additional
  569. // test for this below when determining the length of the
  570. // the data.
  571. //
  572. if (l != 0)
  573. {
  574. MemCopy(pstKeys->u.achKeyStr, pstKeySource[nLoop].achKeyStr, (unsigned)l);
  575. }
  576. else
  577. {
  578. pstKeys->u.achKeyStr[0] = '\x00';
  579. }
  580. }
  581. else
  582. {
  583. pstKeys->fPointer = TRUE;
  584. pstKeys->u.pachKeyStr = malloc((unsigned)(l+1));
  585. if (!pstKeys->u.pachKeyStr)
  586. {
  587. emuKeyTableFree(pstKeyTbl);
  588. break;
  589. }
  590. MemCopy(pstKeys->u.pachKeyStr, pstKeySource[nLoop].achKeyStr, (unsigned)l);
  591. }
  592. // Here's the special case test, again.
  593. //
  594. if (l !=0 )
  595. pstKeys->uLen = (int)l;
  596. else
  597. pstKeys->uLen = 1;
  598. pstKeyTbl->iMaxKeys += 1;
  599. }
  600. }
  601. if (pstKeyTbl->iMaxKeys)
  602. {
  603. qsort(pstKeyTbl->pstKeys,
  604. (unsigned)pstKeyTbl->iMaxKeys,
  605. sizeof(KEY),
  606. KeyCmp);
  607. }
  608. return (int)pstKeyTbl->iMaxKeys;
  609. }
  610. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  611. * FUNCTION:
  612. * emuKeyTableFree
  613. *
  614. * DESCRIPTION:
  615. *
  616. * ARGUMENTS:
  617. *
  618. * RETURNS:
  619. *
  620. */
  621. void emuKeyTableFree(PSTKEYTABLE const pstKeyTbl)
  622. {
  623. int i;
  624. for (i = 0 ; i < pstKeyTbl->iMaxKeys ; i++)
  625. {
  626. if (pstKeyTbl->pstKeys[i].fPointer)
  627. {
  628. free(pstKeyTbl->pstKeys[i].u.pachKeyStr);
  629. pstKeyTbl->pstKeys[i].u.pachKeyStr = NULL;
  630. }
  631. }
  632. pstKeyTbl->iMaxKeys = 0;
  633. if (pstKeyTbl->pstKeys)
  634. {
  635. free(pstKeyTbl->pstKeys);
  636. pstKeyTbl->pstKeys = (KEY *)0;
  637. }
  638. return;
  639. }
  640. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  641. * FUNCTION:
  642. * FFstrlen
  643. *
  644. * DESCRIPTION:
  645. * Local version of strlen that uses '\ff' as a string terminator
  646. *
  647. * ARGUMENTS:
  648. * CHAR FAR *s - '\ff' terminated string.
  649. *
  650. * RETURNS:
  651. * length
  652. *
  653. */
  654. static int FFstrlen(const BYTE *s)
  655. {
  656. int i = 0;
  657. while (*s++ != 0xFF)
  658. i += 1;
  659. return i;
  660. }
  661. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  662. * KeyCmp
  663. *
  664. * DESCRIPTION: Compare function for qsort.
  665. *
  666. * ARGUMENTS:
  667. *
  668. * RETURNS:
  669. *
  670. */
  671. int _cdecl KeyCmp(PSTKEY pstKey1, PSTKEY pstKey2)
  672. {
  673. if (pstKey1->key > pstKey2->key)
  674. return 1;
  675. if (pstKey1->key < pstKey2->key)
  676. return -1;
  677. return 0;
  678. }
  679. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  680. * emuInstallStateTable
  681. *
  682. * DESCRIPTION:
  683. *
  684. * ARGUMENTS:
  685. *
  686. * RETURNS:
  687. *
  688. */
  689. void emuInstallStateTable(const HHEMU hhEmu, struct trans_entry const *e, int size)
  690. {
  691. struct state_entry *state_pntr = 0;
  692. int nStateCnt = 0;
  693. int nTransCnt = 0;
  694. while (size--)
  695. {
  696. if (e->next_state == NEW_STATE) /* start a new state */
  697. {
  698. assert(nStateCnt < MAX_STATE);
  699. hhEmu->state_tbl[nStateCnt].first_trans = &hhEmu->trans_tbl[nTransCnt];
  700. state_pntr = &hhEmu->state_tbl[nStateCnt++];
  701. state_pntr->number_trans = 0;
  702. }
  703. else /* add a transition */
  704. {
  705. assert(nTransCnt < MAX_TRANSITION);
  706. assert(state_pntr);
  707. if (state_pntr)
  708. {
  709. ++state_pntr->number_trans;
  710. }
  711. hhEmu->trans_tbl[nTransCnt++] = *e;
  712. }
  713. ++e;
  714. }
  715. }
  716. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  717. * FUNCTION:
  718. * emuCreateTextAttrBufs
  719. *
  720. * DESCRIPTION:
  721. * This one took a while to decipher but here is the bottom line.
  722. * emu_maxrow and emu_maxcol refer to the last row and column from
  723. * offset 0 (ZERO)! The emulator image has 2 (two) more columns for the
  724. * the stuff unknown to me at the present time. This function wants
  725. * the total number of rows and columns, so emu_maxrow = 23 means the
  726. * the argument nRows is 24.
  727. *
  728. * ARGUMENTS:
  729. *
  730. * RETURNS:
  731. *
  732. */
  733. int emuCreateTextAttrBufs(const HEMU hEmu, const size_t nRows, size_t nCols)
  734. {
  735. const HHEMU hhEmu = (HHEMU)hEmu;
  736. register size_t i, ndx;
  737. PSTATTR pstAttr;
  738. if (hhEmu == NULL)
  739. {
  740. return FALSE;
  741. }
  742. if (hhEmu->emu_apText && hhEmu->emu_apAttr && hhEmu->emu_aiEnd)
  743. return (TRUE);
  744. else
  745. emuDestroyTextAttrBufs(hEmu);
  746. nCols += 2; // Emulators need two extra columns.
  747. // Allocate the text buffer.
  748. //
  749. if ((hhEmu->emu_apText = (ECHAR **)calloc(nRows, sizeof(ECHAR *))) == 0)
  750. {
  751. assert(FALSE);
  752. return FALSE;
  753. }
  754. for (i = 0 ; i < nRows ; ++i)
  755. {
  756. if ((hhEmu->emu_apText[i] = (ECHAR *)calloc(nCols, sizeof(ECHAR))) == 0)
  757. {
  758. assert(FALSE);
  759. emuDestroyTextAttrBufs(hEmu);
  760. return FALSE;
  761. }
  762. ECHAR_Fill(hhEmu->emu_apText[i], EMU_BLANK_CHAR, nCols);
  763. }
  764. // Allocate the array to hold the rightmost character column number
  765. // for each row.
  766. //
  767. if ((hhEmu->emu_aiEnd = (int *)calloc(nRows, sizeof(int))) == 0)
  768. {
  769. assert(FALSE);
  770. emuDestroyTextAttrBufs(hEmu);
  771. return FALSE;
  772. }
  773. for (ndx = 0; ndx < nRows; ++ndx)
  774. hhEmu->emu_aiEnd[ndx] = EMU_BLANK_LINE;
  775. // Allocate the attribute buffer.
  776. //
  777. if ((hhEmu->emu_apAttr = (PSTATTR *)calloc(nRows, sizeof(LPTSTR))) == 0)
  778. {
  779. assert(FALSE);
  780. emuDestroyTextAttrBufs(hEmu);
  781. return FALSE;
  782. }
  783. for (i = 0 ; i < nRows ; ++i)
  784. {
  785. if ((hhEmu->emu_apAttr[i] = calloc(nCols, sizeof(STATTR))) == 0)
  786. {
  787. assert(FALSE);
  788. emuDestroyTextAttrBufs(hEmu);
  789. return FALSE;
  790. }
  791. for (ndx = 0, pstAttr = hhEmu->emu_apAttr[i] ; ndx < nCols ; ++ndx)
  792. pstAttr[ndx] = hhEmu->emu_clearattr;
  793. }
  794. return TRUE;
  795. }
  796. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  797. * FUNCTION:
  798. * emuDestroyTextAttrBufs
  799. *
  800. * DESCRIPTION:
  801. * Destroys any allocated buffers for text and attributes.
  802. *
  803. * ARGUMENTS:
  804. * void
  805. *
  806. * RETURNS:
  807. * void
  808. *
  809. */
  810. void emuDestroyTextAttrBufs(const HEMU hEmu)
  811. {
  812. const HHEMU hhEmu = (HHEMU)hEmu;
  813. register int i;
  814. if (hEmu == NULL || hhEmu == NULL)
  815. {
  816. return;
  817. }
  818. if (hhEmu->emu_apText)
  819. {
  820. //
  821. // Fixed memory leak hhEmu->emu_maxrow != MAX_EMUROWS
  822. // MAX_EMUROWS was what was allocated. REV: 12/20/2000
  823. //
  824. for (i = 0 ; i < MAX_EMUROWS ; ++i)
  825. {
  826. if (hhEmu->emu_apText[i])
  827. {
  828. free(hhEmu->emu_apText[i]);
  829. hhEmu->emu_apText[i] = NULL;
  830. }
  831. if (hhEmu->emu_apAttr[i])
  832. {
  833. free(hhEmu->emu_apAttr[i]);
  834. hhEmu->emu_apAttr[i] = NULL;
  835. }
  836. }
  837. free(hhEmu->emu_apText);
  838. hhEmu->emu_apText = 0;
  839. free(hhEmu->emu_apAttr);
  840. hhEmu->emu_apAttr = 0;
  841. }
  842. if (hhEmu->emu_aiEnd)
  843. {
  844. free(hhEmu->emu_aiEnd);
  845. hhEmu->emu_aiEnd = 0;
  846. }
  847. if (hhEmu->emu_apAttr)
  848. {
  849. for (i = 0 ; i <= hhEmu->emu_maxrow ; ++i)
  850. {
  851. if (hhEmu->emu_apAttr[i])
  852. {
  853. free(hhEmu->emu_apAttr[i]);
  854. hhEmu->emu_apAttr[i] = NULL;
  855. }
  856. }
  857. free(hhEmu->emu_apAttr);
  858. hhEmu->emu_apAttr = 0;
  859. }
  860. return;
  861. }
  862. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  863. * FUNCTION:
  864. * emuCreateNameTable
  865. *
  866. * DESCRIPTION:
  867. * Loads the Emulator Names into a table
  868. *
  869. * ARGUMENTS:
  870. * HHEMU hhEmu - Emulator Handle
  871. *
  872. * RETURNS:
  873. * Success/Failure
  874. *
  875. */
  876. int emuCreateNameTable(const HHEMU hhEmu)
  877. {
  878. int iLen, idx, iRet;
  879. TCHAR achText[256];
  880. iRet = TRUE;
  881. emuLock((HEMU)hhEmu);
  882. if (hhEmu->pstNameTable)
  883. {
  884. free(hhEmu->pstNameTable);
  885. hhEmu->pstNameTable = NULL;
  886. }
  887. if ((hhEmu->pstNameTable = malloc(sizeof(STEMUNAMETABLE) * NBR_EMULATORS)) == 0)
  888. {
  889. assert(FALSE);
  890. iRet = FALSE;
  891. goto LoadExit;
  892. }
  893. // Load the emulator name table. It simply contains the name and id of
  894. // all of the supported emulators.
  895. //
  896. // EMU_AUTO
  897. //
  898. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_AUTO, achText, sizeof(achText) / sizeof(TCHAR));
  899. if (iLen >= EMU_MAX_NAMELEN)
  900. {
  901. assert(FALSE);
  902. iRet = FALSE;
  903. goto LoadExit;
  904. }
  905. idx = 0;
  906. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  907. hhEmu->pstNameTable[idx].nEmuId = EMU_AUTO;
  908. // EMU_ANSI
  909. //
  910. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_ANSI, achText, sizeof(achText) / sizeof(TCHAR));
  911. if (iLen >= EMU_MAX_NAMELEN)
  912. {
  913. assert(FALSE);
  914. iRet = FALSE;
  915. goto LoadExit;
  916. }
  917. idx++;
  918. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  919. hhEmu->pstNameTable[idx].nEmuId = EMU_ANSI;
  920. // EMU_ANSIW
  921. //
  922. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_ANSIW, achText, sizeof(achText) / sizeof(TCHAR));
  923. if (iLen >= EMU_MAX_NAMELEN)
  924. {
  925. assert(FALSE);
  926. iRet = FALSE;
  927. goto LoadExit;
  928. }
  929. idx++;
  930. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  931. hhEmu->pstNameTable[idx].nEmuId = EMU_ANSIW;
  932. // EMU_MIMI
  933. //
  934. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_MINI, achText, sizeof(achText) / sizeof(TCHAR));
  935. if (iLen >= EMU_MAX_NAMELEN)
  936. {
  937. assert(FALSE);
  938. iRet = FALSE;
  939. goto LoadExit;
  940. }
  941. idx++;
  942. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  943. hhEmu->pstNameTable[idx].nEmuId = EMU_MINI;
  944. // EMU_VIEW
  945. //
  946. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VIEW, achText, sizeof(achText) / sizeof(TCHAR));
  947. if (iLen >= EMU_MAX_NAMELEN)
  948. {
  949. assert(FALSE);
  950. iRet = FALSE;
  951. goto LoadExit;
  952. }
  953. idx++;
  954. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  955. hhEmu->pstNameTable[idx].nEmuId = EMU_VIEW;
  956. // EMU_TTY
  957. //
  958. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_TTY, achText, sizeof(achText) / sizeof(TCHAR));
  959. if (iLen >= EMU_MAX_NAMELEN)
  960. {
  961. assert(FALSE);
  962. iRet = FALSE;
  963. goto LoadExit;
  964. }
  965. idx++;
  966. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  967. hhEmu->pstNameTable[idx].nEmuId = EMU_TTY;
  968. // EMU_VT100
  969. //
  970. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT100, achText, sizeof(achText) / sizeof(TCHAR));
  971. if (iLen >= EMU_MAX_NAMELEN)
  972. {
  973. assert(FALSE);
  974. iRet = FALSE;
  975. goto LoadExit;
  976. }
  977. idx++;
  978. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  979. hhEmu->pstNameTable[idx].nEmuId = EMU_VT100;
  980. // EMU_VT52
  981. //
  982. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT52, achText, sizeof(achText) / sizeof(TCHAR));
  983. if (iLen >= EMU_MAX_NAMELEN)
  984. {
  985. assert(FALSE);
  986. iRet = FALSE;
  987. goto LoadExit;
  988. }
  989. idx++;
  990. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  991. hhEmu->pstNameTable[idx].nEmuId = EMU_VT52;
  992. // EMU_VT100J
  993. //
  994. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT100J, achText, sizeof(achText) / sizeof(TCHAR));
  995. if (iLen >= EMU_MAX_NAMELEN)
  996. {
  997. assert(FALSE);
  998. iRet = FALSE;
  999. goto LoadExit;
  1000. }
  1001. idx++;
  1002. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  1003. hhEmu->pstNameTable[idx].nEmuId = EMU_VT100J;
  1004. #if defined(INCL_VT220)
  1005. // EMU_VT220
  1006. //
  1007. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT220, achText, sizeof(achText) / sizeof(TCHAR));
  1008. if (iLen >= EMU_MAX_NAMELEN)
  1009. {
  1010. assert(FALSE);
  1011. iRet = FALSE;
  1012. goto LoadExit;
  1013. }
  1014. idx++;
  1015. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  1016. hhEmu->pstNameTable[idx].nEmuId = EMU_VT220;
  1017. #endif
  1018. #if defined(INCL_VT320)
  1019. // EMU_VT320
  1020. //
  1021. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT320, achText, sizeof(achText) / sizeof(TCHAR));
  1022. if (iLen >= EMU_MAX_NAMELEN)
  1023. {
  1024. assert(FALSE);
  1025. iRet = FALSE;
  1026. goto LoadExit;
  1027. }
  1028. idx++;
  1029. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  1030. hhEmu->pstNameTable[idx].nEmuId = EMU_VT320;
  1031. #endif
  1032. #if defined(INCL_VT100PLUS)
  1033. // EMU_VT100+
  1034. //
  1035. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT100PLUS, achText, sizeof(achText) / sizeof(TCHAR));
  1036. if (iLen >= EMU_MAX_NAMELEN)
  1037. {
  1038. assert(FALSE);
  1039. iRet = FALSE;
  1040. goto LoadExit;
  1041. }
  1042. idx++;
  1043. StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  1044. hhEmu->pstNameTable[idx].nEmuId = EMU_VTUTF8;
  1045. #endif
  1046. #if defined(INCL_VTUTF8)
  1047. // EMU_VTUTF8
  1048. //
  1049. iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VTUTF8, achText, sizeof(achText) / sizeof(TCHAR));
  1050. if (iLen >= EMU_MAX_NAMELEN)
  1051. {
  1052. assert(FALSE);
  1053. iRet = FALSE;
  1054. goto LoadExit;
  1055. }
  1056. idx++;
  1057. StrCharCopyN (hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN);
  1058. hhEmu->pstNameTable[idx].nEmuId = EMU_VTUTF8;
  1059. #endif
  1060. LoadExit:
  1061. emuUnlock((HEMU)hhEmu);
  1062. return(iRet);
  1063. }
  1064. /* end of emu.c */