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.

1975 lines
52 KiB

  1. /* File: D:\wacker\emu\minitel.c (Created: 05-Mar-1994)
  2. *
  3. * Copyright 1994, 1998 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 12 $
  7. * $Date: 7/12/02 1:25p $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <time.h>
  12. #include <tdll\stdtyp.h>
  13. #include <tdll\tdll.h>
  14. #include <tdll\session.h>
  15. #include <tdll\cloop.h>
  16. #include <tdll\print.h>
  17. #include <tdll\capture.h>
  18. #include <tdll\assert.h>
  19. #include <tdll\mc.h>
  20. #include <tdll\update.h>
  21. #include <tdll\chars.h>
  22. #include <tdll\cnct.h>
  23. #include <tdll\term.h>
  24. #include <tdll\backscrl.h>
  25. #include <tdll\htchar.h>
  26. #include <term\res.h>
  27. #include <tapi.h>
  28. #include <cncttapi\cncttapi.hh>
  29. #include "emu.h"
  30. #include "emu.hh"
  31. #include "emuid.h"
  32. #include "minitel.hh"
  33. #include "keytbls.h"
  34. #if defined(INCL_MINITEL)
  35. static void emuMinitelRedisplayLine(const HHEMU hhEmu,
  36. const int row,
  37. const int col);
  38. static int minitel_kbdin(const HHEMU hhEmu, int key, const int fTest);
  39. static ECHAR minitelMapMosaics(const HHEMU hhEmu, ECHAR ch);
  40. static void minitelFullScrnReveal(const HHEMU hhEmu);
  41. static void minitelFullScrnConceal(const HHEMU hhEmu);
  42. static void minitelSS2(const HHEMU hhEmu);
  43. static void minitelSS2Part2(const HHEMU hhEmu);
  44. static void minitelInsMode(const HHEMU hhEmu);
  45. static void minitelPRO1(const HHEMU hhEmu);
  46. static void minitelPRO2Part1(const HHEMU hhEmu);
  47. static void minitelPRO2Part2(const HHEMU hhEmu);
  48. static void minitelStatusReply(const HHEMU hhEmu);
  49. /*
  50. Here begins the famed and fabled Minitel emulator. Abandon all hope
  51. all ye who..., well you get the idea. The Minitel emulator uses a
  52. combination of character attributes and field attributes. See the
  53. book "minitel 1B" for description of field attributes. Page numbers
  54. referenced in this code refer to the before mentioned book. - mrw
  55. */
  56. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  57. * FUNCTION:
  58. * emuMinitelInit
  59. *
  60. * DESCRIPTION:
  61. * Startup routine for the minitel emulator.
  62. *
  63. * ARGUMENTS:
  64. * hhEmu - private emulator handle.
  65. *
  66. * RETURNS:
  67. * void
  68. *
  69. */
  70. void emuMinitelInit(const HHEMU hhEmu)
  71. {
  72. int i;
  73. LOGFONT lf;
  74. HWND hwndTerm;
  75. PSTMTPRIVATE pstPRI;
  76. static struct trans_entry const minitel_tbl[] =
  77. {
  78. {NEW_STATE, 0, 0, 0}, // 0
  79. {0, ETEXT('\x00'), ETEXT('\x01'), nothing},
  80. {0, ETEXT('\x20'), ETEXT('\x7F'), minitelGraphic},
  81. {1, ETEXT('\x1B'), ETEXT('\x1B'), nothing},
  82. {0, ETEXT('\x07'), ETEXT('\x07'), emu_bell},
  83. {0, ETEXT('\b'), ETEXT('\b'), minitelBackspace},
  84. {0, ETEXT('\t'), ETEXT('\t'), minitelHorzTab},
  85. {0, ETEXT('\n'), ETEXT('\n'), minitelLinefeed},
  86. {0, ETEXT('\x0B'), ETEXT('\x0B'), minitelVerticalTab},
  87. {0, ETEXT('\x0C'), ETEXT('\x0C'), minitelFormFeed},
  88. {0, ETEXT('\r'), ETEXT('\r'), carriagereturn},
  89. {0, ETEXT('\x0E'), ETEXT('\x0F'), minitelCharSet}, // change char set
  90. {0, ETEXT('\x11'), ETEXT('\x11'), minitelCursorOn}, // cursor on
  91. {5, ETEXT('\x12'), ETEXT('\x12'), nothing}, // repeat
  92. {12,ETEXT('\x13'), ETEXT('\x13'), nothing}, // SEP
  93. {0, ETEXT('\x14'), ETEXT('\x14'), minitelCursorOff},// cursor off
  94. {20,ETEXT('\x16'), ETEXT('\x16'), nothing}, // SS2 (undocumented)
  95. {0, ETEXT('\x18'), ETEXT('\x18'), minitelCancel}, // cancel
  96. {20,ETEXT('\x19'), ETEXT('\x19'), nothing}, // SS2
  97. {0, ETEXT('\x1C'), ETEXT('\x1C'), nothing}, // really is nothing.
  98. {13,ETEXT('\x1D'), ETEXT('\x1D'), nothing}, // SS3,X ingnored, p99, 1.2.7
  99. {0, ETEXT('\x1E'), ETEXT('\x1E'), minitelRecordSeparator},
  100. {3, ETEXT('\x1F'), ETEXT('\x1F'), nothing}, // Unit Seperator
  101. //{0, ETEXT('\x7F'), ETEXT('\x7F'), minitelDel},
  102. {NEW_STATE, 0, 0, 0}, // 1 - seen ESC
  103. {1, ETEXT('\x00'), ETEXT('\x00'), nothing},
  104. {0, ETEXT('\x01'), ETEXT('\x1F'), minitelResync},
  105. {18,ETEXT('\x23'), ETEXT('\x23'), nothing},
  106. {14,ETEXT('\x25'), ETEXT('\x25'), nothing},
  107. {13,ETEXT('\x35'), ETEXT('\x37'), nothing}, // eat ESC,35-37,X sequences
  108. {6, ETEXT('\x39'), ETEXT('\x39'), nothing}, // PROT1, p134
  109. {7, ETEXT('\x3A'), ETEXT('\x3A'), nothing}, // PROT2, p134
  110. {8, ETEXT('\x3B'), ETEXT('\x3B'), nothing}, // PROT3, p134
  111. {2, ETEXT('\x5B'), ETEXT('\x5B'), ANSI_Pn_Clr},
  112. {0, ETEXT('\x40'), ETEXT('\x49'), emuMinitelCharAttr}, // forground color, flashing
  113. {0, ETEXT('\x4C'), ETEXT('\x4F'), emuMinitelCharAttr}, // char width & height
  114. {0, ETEXT('\x50'), ETEXT('\x5A'), emuMinitelFieldAttr},// background, underlining
  115. {0, ETEXT('\x5F'), ETEXT('\x5F'), emuMinitelFieldAttr},// reveal display
  116. {0, ETEXT('\x5C'), ETEXT('\x5D'), emuMinitelCharAttr}, // inverse
  117. {0, ETEXT('\x61'), ETEXT('\x61'), minitelCursorReport},
  118. {22,ETEXT('\x20'), ETEXT('\x2F'), nothing}, // p.99 ISO 2022
  119. {NEW_STATE, 0, 0, 0}, // 2 - seen ESC [
  120. {2, ETEXT('\x00'), ETEXT('\x00'), nothing},
  121. {2, ETEXT('\x30'), ETEXT('\x39'), ANSI_Pn},
  122. {2, ETEXT('\x3B'), ETEXT('\x3B'), ANSI_Pn_End},
  123. {2, ETEXT('\x3A'), ETEXT('\x3F'), ANSI_Pn},
  124. {0, ETEXT('\x40'), ETEXT('\x40'), minitelInsChars},
  125. {0, ETEXT('\x41'), ETEXT('\x41'), minitelCursorUp},
  126. {0, ETEXT('\x42'), ETEXT('\x42'), ANSI_CUD},
  127. {0, ETEXT('\x43'), ETEXT('\x43'), ANSI_CUF},
  128. {0, ETEXT('\x44'), ETEXT('\x44'), ANSI_CUB},
  129. {0, ETEXT('\x48'), ETEXT('\x48'), minitelCursorDirect},
  130. {0, ETEXT('\x4A'), ETEXT('\x4A'), minitelClrScrn},
  131. {0, ETEXT('\x4B'), ETEXT('\x4B'), minitelClrLn},
  132. {0, ETEXT('\x4C'), ETEXT('\x4C'), minitelInsRows},
  133. {0, ETEXT('\x4D'), ETEXT('\x4D'), minitelDelRows},
  134. {0, ETEXT('\x50'), ETEXT('\x50'), minitelDelChars},
  135. {0, ETEXT('\x68'), ETEXT('\x69'), minitelInsMode},
  136. {0, ETEXT('\x7A'), ETEXT('\x7B'), nothing}, //* p144 12.2
  137. {0, ETEXT('\x7D'), ETEXT('\x7D'), nothing}, //* p144 12.2
  138. {0, ETEXT('\x7F'), ETEXT('\x7F'), minitelResetTerminal}, //* p145, 13.2
  139. {NEW_STATE, 0, 0, 0}, // 3 - unit separtor character position
  140. {3, ETEXT('\x00'), ETEXT('\x00'), nothing},
  141. {4, ETEXT('\x01'), ETEXT('\xFF'), minitelUSRow},
  142. {NEW_STATE, 0, 0, 0}, // 4 - end of unit separtor character position
  143. {4, ETEXT('\x00'), ETEXT('\x00'), nothing},
  144. {0, ETEXT('\x01'), ETEXT('\xFF'), minitelUSCol},
  145. {NEW_STATE, 0, 0, 0}, // 5 - number of repeats
  146. {5, ETEXT('\x00'), ETEXT('\x00'), nothing},
  147. {0, ETEXT('\x40'), ETEXT('\x7F'), minitelRepeat},
  148. {0, ETEXT('\x00'), ETEXT('\xFF'), minitelResync},
  149. {NEW_STATE, 0, 0, 0}, // 6 - Protocol 1 sequence (PRO1,X)
  150. {6, ETEXT('\x00'), ETEXT('\x00'), nothing},
  151. {0, ETEXT('\x01'), ETEXT('\xFF'), minitelPRO1},
  152. {NEW_STATE, 0, 0, 0}, // 7 - Protocol 2 sequence (PRO2,X,Y)
  153. {7, ETEXT('\x00'), ETEXT('\x00'), nothing},
  154. {8, ETEXT('\x01'), ETEXT('\xFF'), minitelPRO2Part1},
  155. {NEW_STATE, 0, 0, 0}, // 8 - Protocol 2 sequence (PRO2,X,Y)
  156. {8, ETEXT('\x00'), ETEXT('\x00'), nothing},
  157. {0, ETEXT('\x01'), ETEXT('\xFF'), minitelPRO2Part2},
  158. {NEW_STATE, 0, 0, 0}, // 9 - Protocol 3 sequence (PRO3,X,Y,Z)
  159. {9, ETEXT('\x00'), ETEXT('\x00'), nothing},
  160. {10,ETEXT('\x01'), ETEXT('\xFF'), nothing},
  161. {NEW_STATE, 0, 0, 0}, // 10 - Protocol 3 sequence (PRO3,X,Y,Z)
  162. {10,ETEXT('\x00'), ETEXT('\x00'), nothing},
  163. {11,ETEXT('\x01'), ETEXT('\xFF'), nothing},
  164. {NEW_STATE, 0, 0, 0}, // 11 - Protocol 3 sequence (PRO3,X,Y,Z)
  165. {11,ETEXT('\x00'), ETEXT('\x00'), nothing},
  166. {0, ETEXT('\x01'), ETEXT('\xFF'), nothing},
  167. {NEW_STATE, 0, 0, 0}, // 12 - SEP
  168. {12,ETEXT('\x00'), ETEXT('\x00'), nothing},
  169. {0, ETEXT('\x01'), ETEXT('\xFF'), nothing},
  170. {NEW_STATE, 0, 0, 0}, // 13 - ESC,35-39,X sequences eaten, p99, 1.2.7
  171. {13,ETEXT('\x00'), ETEXT('\x00'), nothing},
  172. {0, ETEXT('\x01'), ETEXT('\xFF'), nothing},
  173. {NEW_STATE, 0, 0, 0}, // 14 - screen transparency mode
  174. {15,ETEXT('\x1B'), ETEXT('\x1B'), nothing},
  175. {14,ETEXT('\x00'), ETEXT('\xFF'), nothing},
  176. {23,ETEXT('\x20'), ETEXT('\x2F'), nothing}, // could be ISO 2022
  177. {NEW_STATE, 0, 0, 0}, // 15 - screen transparency mode continued, seen ESC
  178. {16,ETEXT('\x25'), ETEXT('\x25'), nothing},
  179. {17,ETEXT('\x2F'), ETEXT('\x2F'), nothing},
  180. {15,ETEXT('\x00'), ETEXT('\x00'), nothing},
  181. {14,ETEXT('\x00'), ETEXT('\xFF'), nothing},
  182. {NEW_STATE, 0, 0, 0}, // 16 - screen transparency mode continued, seen ESC \x25
  183. {0, ETEXT('\x40'), ETEXT('\x40'), nothing},
  184. {16,ETEXT('\x00'), ETEXT('\x00'), nothing},
  185. {14,ETEXT('\x00'), ETEXT('\xFF'), nothing},
  186. {NEW_STATE, 0, 0, 0}, // 17 - screen transparency mode continued, seen ESC \x2F
  187. {0, ETEXT('\x3F'), ETEXT('\x3F'), nothing},
  188. {17,ETEXT('\x00'), ETEXT('\x00'), nothing},
  189. {14,ETEXT('\x00'), ETEXT('\xFF'), nothing},
  190. {NEW_STATE, 0, 0, 0}, // 18 - Full screen reveal/hide, seen ESC \x23
  191. {18,ETEXT('\x00'), ETEXT('\x00'), nothing},
  192. {19,ETEXT('\x20'), ETEXT('\x20'), nothing},
  193. {23,ETEXT('\x20'), ETEXT('\x2F'), nothing}, // could be ISO 2022
  194. {NEW_STATE, 0, 0, 0}, // 19 - Full screen reveal/hide, seen ESC \x23 \x20
  195. {19,ETEXT('\x00'), ETEXT('\x00'), nothing},
  196. {0, ETEXT('\x58'), ETEXT('\x58'), minitelFullScrnConceal},
  197. {0, ETEXT('\x5F'), ETEXT('\x5F'), minitelFullScrnReveal},
  198. {NEW_STATE, 0, 0, 0}, // 20 - SS2
  199. {20,ETEXT('\x00'), ETEXT('\x00'), nothing},
  200. {0, ETEXT('\x00'), ETEXT('\x1F'), minitelResync},
  201. {21,ETEXT('\x20'), ETEXT('\x7F'), minitelSS2}, // valid SS2
  202. {NEW_STATE, 0, 0, 0}, // 21 - SS2 part 2
  203. {21,ETEXT('\x00'), ETEXT('\x00'), nothing},
  204. {0, ETEXT('\x20'), ETEXT('\x7F'), minitelSS2Part2}, // valid SS2
  205. {NEW_STATE, 0, 0, 0}, // 22 - p.99 ISO 2022
  206. {23,ETEXT('\x20'), ETEXT('\x2F'), nothing},
  207. {0, ETEXT('\x00'), ETEXT('\x1F'), minitelResync},
  208. {NEW_STATE, 0, 0, 0}, // 23 - p.99 ISO 2022
  209. {24,ETEXT('\x20'), ETEXT('\x2F'), nothing},
  210. {0, ETEXT('\x00'), ETEXT('\x1F'), minitelResync},
  211. {NEW_STATE, 0, 0, 0}, // 24 - p.99 ISO 2022
  212. {25, ETEXT('\x30'), ETEXT('\x3F'), nothing}, // page 107.
  213. {0, ETEXT('\x30'), ETEXT('\x7E'), nothing}, // final character
  214. {0, ETEXT('\x00'), ETEXT('\x1F'), minitelResync},
  215. {NEW_STATE, 0, 0, 0}, // 25 - p.99 ISO 2022
  216. {0, ETEXT('\x0D'), ETEXT('\x0D'), nothing}, // page 107. eat CR
  217. {0, ETEXT('\x00'), ETEXT('\x7F'), minitelResync},
  218. };
  219. if (hhEmu == 0)
  220. {
  221. assert(0);
  222. return;
  223. }
  224. emuInstallStateTable(hhEmu, minitel_tbl, DIM(minitel_tbl));
  225. // Allocate and initialize private data for Minitel emulator.
  226. //
  227. if (hhEmu->pvPrivate != 0)
  228. {
  229. free(hhEmu->pvPrivate);
  230. hhEmu->pvPrivate = 0;
  231. }
  232. hhEmu->pvPrivate = malloc(sizeof(MTPRIVATE));
  233. if (hhEmu->pvPrivate == 0)
  234. {
  235. assert(FALSE);
  236. return;
  237. }
  238. pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  239. memset(pstPRI, 0, sizeof(MTPRIVATE));
  240. pstPRI->minitel_last_char = ETEXT(' ');
  241. /* load key array */
  242. emuKeyTableLoad(hhEmu, Minitel_KeyTable,
  243. sizeof(Minitel_KeyTable)/sizeof(KEYTBLSTORAGE),
  244. &hhEmu->stEmuKeyTbl);
  245. /* --- Allocate attribute buffer for Minitel junk --- */
  246. pstPRI->apstMT = malloc(MAX_EMUROWS * sizeof(PSTMINITEL));
  247. if (pstPRI->apstMT == 0)
  248. {
  249. assert(FALSE);
  250. return;
  251. }
  252. memset(pstPRI->apstMT, 0, MAX_EMUROWS * sizeof(PSTMINITEL));
  253. for (i = 0 ; i < MAX_EMUROWS ; ++i)
  254. {
  255. pstPRI->apstMT[i] = malloc(MAX_EMUCOLS * sizeof(STMINITEL));
  256. if (pstPRI->apstMT[i] == 0)
  257. {
  258. assert(FALSE);
  259. return;
  260. }
  261. memset(pstPRI->apstMT[i], 0, MAX_EMUCOLS * sizeof(STMINITEL));
  262. }
  263. /* --- Setup defaults --- */
  264. hhEmu->emu_maxrow = 24; // 25 line emulator
  265. hhEmu->emu_maxcol = 39; // start in 40 column mode
  266. hhEmu->top_margin = 1; // access to row 0 is restricted.
  267. hhEmu->bottom_margin = hhEmu->emu_maxrow; // this has to equal emu_maxrow which changed
  268. hhEmu->emu_kbdin = minitel_kbdin;
  269. hhEmu->emu_graphic = minitelGraphic;
  270. hhEmu->emu_deinstall = emuMinitelDeinstall;
  271. hhEmu->emu_ntfy = minitelNtfy;
  272. hhEmu->emuHomeHostCursor = minitelHomeHostCursor;
  273. #ifdef INCL_TERMINAL_SIZE_AND_COLORS
  274. hhEmu->emu_setscrsize = emuMinitelSetScrSize;
  275. #endif
  276. hhEmu->emu_highchar = (TCHAR)0xFF;
  277. if (hhEmu->emu_currow == 0)
  278. (*hhEmu->emu_setcurpos)(hhEmu, 1, hhEmu->emu_curcol - 1);
  279. // Also, set font to Arial Alternative
  280. //
  281. memset(&lf, 0, sizeof(LOGFONT));
  282. hwndTerm = sessQueryHwndTerminal(hhEmu->hSession);
  283. termGetLogFont(hwndTerm, &lf);
  284. if (StrCharCmpi(lf.lfFaceName, "Arial Alternative") != 0)
  285. {
  286. StrCharCopyN(lf.lfFaceName, "Arial Alternative", LF_FACESIZE);
  287. lf.lfWeight = FW_DONTCARE;
  288. lf.lfItalic = FALSE;
  289. lf.lfUnderline = FALSE;
  290. lf.lfStrikeOut = FALSE;
  291. lf.lfCharSet = DEFAULT_CHARSET;
  292. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  293. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  294. lf.lfQuality = DEFAULT_QUALITY;
  295. lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
  296. termSetLogFont(hwndTerm, &lf);
  297. }
  298. // Backscroll not supported in minitel
  299. //
  300. backscrlSetUNumLines(sessQueryBackscrlHdl(hhEmu->hSession), 0);
  301. // Initialize colors for the Minitel.
  302. //
  303. std_setcolors(hhEmu, VC_BRT_WHITE, VC_BLACK);
  304. // Set terminal to power-up state
  305. //
  306. minitelResetTerminal(hhEmu);
  307. // Turn backscroll off for Minitel
  308. //
  309. backscrlSetShowFlag(sessQueryBackscrlHdl(hhEmu->hSession), FALSE);
  310. // Enable Minitel toolbar buttons
  311. //
  312. PostMessage(sessQueryHwnd(hhEmu->hSession), WM_SESS_SHOW_SIDEBAR, 0, 0);
  313. return;
  314. }
  315. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  316. * FUNCTION:
  317. * emuMinitelDeinstall
  318. *
  319. * DESCRIPTION:
  320. * Frees the extra attribute buffer needed to manage serial attributes.
  321. *
  322. * ARGUMENTS:
  323. * hhEmu - private emulator handle.
  324. *
  325. * RETURNS:
  326. * void
  327. *
  328. */
  329. void emuMinitelDeinstall(const HHEMU hhEmu)
  330. {
  331. int i;
  332. PSTMTPRIVATE pstPRI;
  333. assert(hhEmu);
  334. pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  335. if (pstPRI)
  336. {
  337. if (pstPRI->apstMT)
  338. {
  339. for (i = 0 ; i < MAX_EMUROWS ; ++i)
  340. {
  341. if (pstPRI->apstMT[i])
  342. {
  343. free(pstPRI->apstMT[i]);
  344. pstPRI->apstMT[i] = NULL;
  345. }
  346. }
  347. free(pstPRI->apstMT);
  348. pstPRI->apstMT = 0;
  349. }
  350. free(hhEmu->pvPrivate);
  351. hhEmu->pvPrivate = 0;
  352. }
  353. // Hide Minitel toolbar buttons
  354. //
  355. ShowWindow(sessQuerySidebarHwnd(hhEmu->hSession), SW_HIDE);
  356. //
  357. // Make sure to free the key table that was created when the emulator
  358. // was loaded, otherwise there is a memory leak. REV: 05/09/2001
  359. //
  360. emuKeyTableFree(&hhEmu->stEmuKeyTbl);
  361. return;
  362. }
  363. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  364. * FUNCTION:
  365. * minitelReset
  366. *
  367. * DESCRIPTION:
  368. * Sets emulator to an initial state. Used for record and unit
  369. * separators.
  370. *
  371. * ARGUMENTS:
  372. * hhEmu - private emulator handle.
  373. *
  374. * RETURNS:
  375. * void
  376. *
  377. */
  378. void minitelReset(const HHEMU hhEmu)
  379. {
  380. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  381. pstPRI->minitelG1Active = FALSE;
  382. memset(&hhEmu->emu_charattr, 0, sizeof(hhEmu->emu_charattr));
  383. hhEmu->emu_charattr.txtclr = VC_BRT_WHITE;
  384. hhEmu->emu_charattr.bkclr = VC_BLACK;
  385. pstPRI->apstMT[hhEmu->emu_imgrow][hhEmu->emu_curcol].isattr = 0;
  386. memset(&pstPRI->stLatentAttr, 0, sizeof(pstPRI->stLatentAttr));
  387. pstPRI->stLatentAttr.fBkClr = TRUE;
  388. hhEmu->attrState[CS_STATE] =
  389. hhEmu->attrState[CSCLEAR_STATE] = hhEmu->emu_charattr;
  390. hhEmu->emu_clearattr = hhEmu->emu_charattr;
  391. minitelNtfy(hhEmu, 0);
  392. return;
  393. }
  394. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  395. * FUNCTION:
  396. * minitelGraphic
  397. *
  398. * DESCRIPTION:
  399. * Handles displayable characters.
  400. *
  401. * ARGUMENTS:
  402. * hhEmu - private emulator handle.
  403. *
  404. * RETURNS:
  405. * void
  406. *
  407. */
  408. void minitelGraphic(const HHEMU hhEmu)
  409. {
  410. ECHAR ccode;
  411. ECHAR aechBuf[10];
  412. int r;
  413. int row = hhEmu->emu_currow;
  414. int col = hhEmu->emu_curcol;
  415. BOOL fRedisplay = FALSE;
  416. BOOL fDblHi;
  417. STATTR stAttr;
  418. ECHAR *tp = hhEmu->emu_apText[hhEmu->emu_imgrow];
  419. const PSTATTR ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
  420. const HUPDATE hUpdate = sessQueryUpdateHdl(hhEmu->hSession);
  421. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  422. ccode = hhEmu->emu_code;
  423. if (ccode == 0)
  424. return;
  425. pstPRI->minitel_last_char = ccode;
  426. if (hhEmu->mode_IRM == SET)
  427. {
  428. if (col < hhEmu->emu_maxcol)
  429. {
  430. memmove(&tp[col+1], &tp[col],
  431. (unsigned)(hhEmu->emu_maxcol-col) * sizeof(ECHAR));
  432. memmove(&ap[col+1], &ap[col],
  433. (unsigned)(hhEmu->emu_maxcol-col) * sizeof(STATTR));
  434. memmove(&pstPRI->apstMT[hhEmu->emu_imgrow][col+1],
  435. &pstPRI->apstMT[hhEmu->emu_imgrow][col],
  436. (unsigned)(hhEmu->emu_maxcol-col) * sizeof(STMINITEL));
  437. }
  438. }
  439. /* --- check if we are overwriting an attribute space --- */
  440. if (pstPRI->apstMT[hhEmu->emu_imgrow][col].isattr)
  441. {
  442. pstPRI->apstMT[hhEmu->emu_imgrow][col].isattr = FALSE;
  443. fRedisplay = TRUE;
  444. }
  445. /* --- If we receive a space and have latent attributes, validate --- */
  446. if (ccode == ETEXT('\x20') && pstPRI->stLatentAttr.fModified
  447. && pstPRI->minitelG1Active == FALSE)
  448. {
  449. r = hhEmu->emu_imgrow;
  450. // Color
  451. //
  452. pstPRI->apstMT[r][col].fbkclr = pstPRI->stLatentAttr.fBkClr;
  453. pstPRI->apstMT[r][col].bkclr = pstPRI->stLatentAttr.bkclr;
  454. // Conceal
  455. //
  456. pstPRI->apstMT[r][col].conceal = pstPRI->stLatentAttr.conceal;
  457. // Underline
  458. //
  459. pstPRI->apstMT[r][col].undrln = pstPRI->stLatentAttr.undrln;
  460. pstPRI->apstMT[hhEmu->emu_imgrow][col].isattr = TRUE;
  461. // This is truely wierd. We don't reset the fBkclr, fConceal, or
  462. // fUndrln fields, only the fModified flag. Thus if any serial
  463. // attributes are set, all latent values get updated. The only
  464. // guy who appears to be able to turn off an attribute is the
  465. // mosaic character which validates the background color and sets
  466. // the fBkClr flag to false. I can't think of a reason why it
  467. // should work this way. - mrw
  468. //
  469. pstPRI->stLatentAttr.fModified = FALSE;
  470. fRedisplay = TRUE;
  471. }
  472. /* --- If we switched to G1, map char to location in new font --- */
  473. if (pstPRI->minitelG1Active)
  474. ccode = minitelMapMosaics(hhEmu, ccode);
  475. pstPRI->apstMT[hhEmu->emu_imgrow][col].ismosaic =
  476. (unsigned)pstPRI->minitelG1Active;
  477. /* --- If we switched to semigraphic mode, validate the background --- */
  478. if (pstPRI->minitelG1Active)
  479. {
  480. // Guess what? Latent background color is always adopted for mosaics.
  481. // This is a major undocumented find. Basicly, mosaics
  482. // (semigraphics) always use the latent background color regardless
  483. // of the validation state.
  484. //
  485. ap[col].bkclr = pstPRI->stLatentAttr.bkclr;
  486. fRedisplay = TRUE;
  487. // Something tricky here. Reception of a mosaic validates the
  488. // background color. Validate means adopt the color. It also
  489. // means that if we shift back to the alpha (G0 char set) and
  490. // recieve a space, we DON'T validate the background color a
  491. // second time. So we keep a seperate flag for the background
  492. // color validation. - mrw
  493. //
  494. pstPRI->stLatentAttr.fBkClr = FALSE;
  495. }
  496. /* --- Normal character processing --- */
  497. tp[col] = ccode;
  498. // Update the end of row index if necessary.
  499. //
  500. if (col > hhEmu->emu_aiEnd[hhEmu->emu_imgrow])
  501. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = col;
  502. /* --- Find out this characters current attributes and adjust --- */
  503. stAttr = GetAttr(hhEmu, row, col);
  504. ap[col] = hhEmu->emu_charattr;
  505. ap[col].bkclr = stAttr.bkclr;
  506. ap[col].blank = stAttr.blank;
  507. ap[col].undrln = stAttr.undrln;
  508. if (pstPRI->minitelG1Active)
  509. ap[col].symbol = 1;
  510. // Documented: 0x7F (mosaic or alpha) always maps to 0x5F in the G1
  511. // character set (solid block).
  512. //
  513. if (tp[col] == ETEXT('\x7F'))
  514. {
  515. tp[col] = ETEXT('\x5F');
  516. ap[col].symbol = 1;
  517. }
  518. /* --- Double high stuff --- */
  519. if (hhEmu->emu_charattr.dblhilo)
  520. {
  521. if (row >= 2)
  522. {
  523. r = row_index(hhEmu, row-1);
  524. hhEmu->emu_apText[r][col] = ccode;
  525. hhEmu->emu_apAttr[r][col] = ap[col];
  526. hhEmu->emu_apAttr[r][col].dblhilo = 0;
  527. hhEmu->emu_apAttr[r][col].dblhihi = 1;
  528. pstPRI->apstMT[r][col] = pstPRI->apstMT[hhEmu->emu_imgrow][col];
  529. updateChar(hUpdate, row-1, col, col);
  530. }
  531. }
  532. /* --- Double wide stuff --- */
  533. if (hhEmu->emu_charattr.dblwilf)
  534. {
  535. if (row > 0 && col < hhEmu->emu_maxcol)
  536. {
  537. tp[col+1] = ccode;
  538. ap[col+1] = ap[col];
  539. ap[col+1].dblwilf = 0;
  540. ap[col+1].dblwirt = 1;
  541. // Major league bug.
  542. //
  543. pstPRI->apstMT[hhEmu->emu_imgrow][col+1] =
  544. pstPRI->apstMT[hhEmu->emu_imgrow][col];
  545. }
  546. if (hhEmu->emu_charattr.dblhilo)
  547. {
  548. r = row_index(hhEmu, row-1);
  549. hhEmu->emu_apText[r][col+1] = ccode;
  550. hhEmu->emu_apAttr[r][col+1] = ap[col];
  551. hhEmu->emu_apAttr[r][col+1].dblwilf = 0;
  552. hhEmu->emu_apAttr[r][col+1].dblwirt = 1;
  553. hhEmu->emu_apAttr[r][col+1].dblhilo = 0;
  554. hhEmu->emu_apAttr[r][col+1].dblhihi = 1;
  555. pstPRI->apstMT[r][col+1] = pstPRI->apstMT[hhEmu->emu_imgrow][col];
  556. }
  557. }
  558. /* --- Need to use old row and column --- */
  559. if (fRedisplay)
  560. emuMinitelRedisplayLine(hhEmu, row, col);
  561. /* --- Need to bump the column guy an extra notch if double wide --- */
  562. if (hhEmu->emu_charattr.dblwilf)
  563. {
  564. col += 1;
  565. hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = col;
  566. }
  567. updateChar(hUpdate, row, hhEmu->emu_curcol, col);
  568. /* --- bump column position, check for wrap, etc. --- */
  569. if (++col > hhEmu->emu_maxcol)
  570. {
  571. // Escape code 0x18 is referred to as cancel in the minitel doco.
  572. // It fills from the cursor pos to the end of the row with blanks.
  573. // Note: Also, it does not force wrap in anyway since
  574. // the cursor position is not updated. That's why we have to
  575. // check here. - mrw:5/3/95
  576. //
  577. if (pstPRI->fInCancel || row == 0)
  578. {
  579. col = hhEmu->emu_maxcol;
  580. return;
  581. }
  582. printEchoString(hhEmu->hPrintEcho, tp,
  583. emuRowLen(hhEmu, hhEmu->emu_imgrow));
  584. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\r\n"),
  585. StrCharGetByteCount(TEXT("\r\n")));
  586. printEchoString(hhEmu->hPrintEcho, aechBuf, sizeof(ECHAR) * 2);
  587. CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession), CF_CAP_LINES,
  588. tp, emuRowLen(hhEmu, hhEmu->emu_imgrow));
  589. // Wrap around accounts for double high
  590. //
  591. fDblHi = (BOOL)hhEmu->emu_charattr.dblhilo;
  592. if (row == hhEmu->bottom_margin)
  593. {
  594. if (pstPRI->fScrollMode)
  595. minitel_scrollup(hhEmu, fDblHi ? 2 : 1);
  596. else
  597. row = fDblHi ? 2 : 1;
  598. }
  599. else if (row != 0)
  600. {
  601. row += fDblHi ? 2 : 1;
  602. if (row > hhEmu->emu_maxrow)
  603. row = 2;
  604. }
  605. col = 0;
  606. }
  607. // Finally, set the cursor position. This will reset emu_currow
  608. // and emu_curcol.
  609. //
  610. (*hhEmu->emu_setcurpos)(hhEmu, row, col);
  611. return;
  612. }
  613. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  614. * FUNCTION:
  615. * emuMinitelRedisplayLine
  616. *
  617. * DESCRIPTION:
  618. * The trick to field attributes is when you encounter one, you need to
  619. * update the rest of the line that follows since changing or overwriting
  620. * an attribute space affects stuff to the right.
  621. *
  622. * ARGUMENTS:
  623. * hhEmu - private emulator handle.
  624. * int row - row to redisplay
  625. * int col - start column
  626. *
  627. * RETURNS:
  628. * void
  629. *
  630. */
  631. static void emuMinitelRedisplayLine(const HHEMU hhEmu,
  632. const int row,
  633. const int col)
  634. {
  635. int i = row_index(hhEmu, row);
  636. int fDblHi = FALSE;
  637. const ECHAR *tp = hhEmu->emu_apText[i];
  638. const PSTATTR ap = hhEmu->emu_apAttr[i];
  639. const PSTATTR apl = hhEmu->emu_apAttr[row_index(hhEmu, row-1)];
  640. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  641. const PSTMINITEL pstMT = pstPRI->apstMT[i];
  642. for (i = col ; i <= hhEmu->emu_maxcol ; ++i)
  643. {
  644. ap[i] = GetAttr(hhEmu, row, i);
  645. // Here's a wierd one. Attribute spaces (as opposed to plain spaces)
  646. // validate but do not display the underline attribute. I suspect
  647. // something similar with seperated mosaics. - mrw
  648. if (tp[i] == ETEXT('\x20') && pstMT[i].isattr)
  649. ap[i].undrln = 0;
  650. // If we're redisplaying a row that has a double hi character,
  651. // then we have to redisplay the upper-half as well.
  652. if (ap[i].dblhilo)
  653. {
  654. fDblHi = TRUE;
  655. apl[i] = GetAttr(hhEmu, row-1, i);
  656. }
  657. }
  658. if (fDblHi)
  659. {
  660. updateChar(sessQueryUpdateHdl(hhEmu->hSession),
  661. row-1, col, hhEmu->emu_maxcol);
  662. }
  663. updateChar(sessQueryUpdateHdl(hhEmu->hSession),
  664. row, col, hhEmu->emu_maxcol);
  665. return;
  666. }
  667. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  668. * FUNCTION:
  669. * GetAttr
  670. *
  671. * DESCRIPTION:
  672. * Walks the current row and builds a composite attribute based on
  673. * the encountered attribute spaces.
  674. *
  675. * ARGUMENTS:
  676. * hhEmu - private emulator handle.
  677. * iRow - logical row
  678. * iCol - logical col
  679. *
  680. * RETURNS:
  681. * composite attribute.
  682. *
  683. */
  684. STATTR GetAttr(const HHEMU hhEmu, const int iRow, const int iCol)
  685. {
  686. int i;
  687. STATTR stAttr;
  688. const int r = row_index(hhEmu, iRow);
  689. const PSTATTR ap = hhEmu->emu_apAttr[r];
  690. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  691. const PSTMINITEL pstMT = pstPRI->apstMT[r];
  692. stAttr = hhEmu->emu_apAttr[r][iCol];
  693. stAttr.bkclr = 0;
  694. stAttr.undrln = 0;
  695. stAttr.blank = 0;
  696. for (i = 0 ; i <= iCol ; ++i)
  697. {
  698. // Mosaics validate the background color. Do it first however,
  699. // because an attribute space can change it to something else.
  700. if (pstMT[i].ismosaic)
  701. stAttr.bkclr = ap[i].bkclr;
  702. if (pstMT[i].isattr)
  703. {
  704. if (pstMT[i].fbkclr)
  705. stAttr.bkclr = pstMT[i].bkclr;
  706. stAttr.undrln = pstMT[i].undrln;
  707. stAttr.blank = pstMT[i].conceal;
  708. }
  709. // Mosaics always cancel underlining.
  710. //
  711. if (pstMT[i].ismosaic)
  712. stAttr.undrln = 0;
  713. }
  714. return stAttr;
  715. }
  716. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  717. * FUNCTION:
  718. * emuMinitelCharAttr
  719. *
  720. * DESCRIPTION:
  721. * Modifies the current character attribute. Does not affect field
  722. * attributes.
  723. *
  724. * mrw - 11/1/94: Went to high intensity colors to more closely match
  725. * the minitel colors.
  726. *
  727. * ARGUMENTS:
  728. * hhEmu - private emulator handle.
  729. *
  730. * RETURNS:
  731. * void
  732. *
  733. */
  734. void emuMinitelCharAttr(const HHEMU hhEmu)
  735. {
  736. STATTR stAttr = hhEmu->attrState[CS_STATE];
  737. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  738. switch (hhEmu->emu_code)
  739. {
  740. case ETEXT('\x40'): stAttr.txtclr = 0; break;
  741. case ETEXT('\x41'): stAttr.txtclr = 12; /*4*/ break;
  742. case ETEXT('\x42'): stAttr.txtclr = 10; /*2*/ break;
  743. case ETEXT('\x43'): stAttr.txtclr = 14; /*6*/ break;
  744. case ETEXT('\x44'): stAttr.txtclr = 9; /*1*/ break;
  745. case ETEXT('\x45'): stAttr.txtclr = 13; /*5*/ break;
  746. case ETEXT('\x46'): stAttr.txtclr = 11; /*3*/ break;
  747. case ETEXT('\x47'): stAttr.txtclr = 15; break;
  748. case ETEXT('\x48'): stAttr.blink = 1; break;
  749. case ETEXT('\x49'): stAttr.blink = 0; break;
  750. case ETEXT('\x4C'): // normal size
  751. if (pstPRI->minitelG1Active)
  752. return;
  753. stAttr.dblhilo = 0;
  754. stAttr.dblwilf = 0;
  755. break;
  756. case ETEXT('\x4D'): // double height
  757. if (pstPRI->minitelG1Active || hhEmu->emu_currow <= 1)
  758. return;
  759. stAttr.dblhilo= 1;
  760. stAttr.dblwilf = 0;
  761. break;
  762. case ETEXT('\x4E'): // double width
  763. if (pstPRI->minitelG1Active || hhEmu->emu_currow < 1)
  764. return;
  765. stAttr.dblhilo = 0;
  766. stAttr.dblwilf = 1;
  767. break;
  768. case ETEXT('\x4F'): // double size
  769. if (pstPRI->minitelG1Active || hhEmu->emu_currow <= 1)
  770. return;
  771. stAttr.dblhilo = 1;
  772. stAttr.dblwilf = 1;
  773. break;
  774. case ETEXT(ETEXT('\x5C')): // normal polarity
  775. if (pstPRI->minitelG1Active)
  776. return;
  777. stAttr.revvid = 0;
  778. break;
  779. case ETEXT(ETEXT('\x5D')): // reverse polarity
  780. if (pstPRI->minitelG1Active)
  781. return;
  782. stAttr.revvid = 1;
  783. break;
  784. default:
  785. break;
  786. }
  787. /* --- commit changes --- */
  788. hhEmu->emu_charattr =
  789. hhEmu->attrState[CS_STATE] =
  790. hhEmu->attrState[CSCLEAR_STATE] = stAttr;
  791. hhEmu->attrState[CSCLEAR_STATE].revvid = 0;
  792. hhEmu->attrState[CSCLEAR_STATE].undrln = 0;
  793. hhEmu->emu_clearattr = hhEmu->attrState[CSCLEAR_STATE];
  794. return;
  795. }
  796. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  797. * FUNCTION:
  798. * emuMinitelFieldAttr
  799. *
  800. * DESCRIPTION:
  801. * Dreaded field attributes. Actually, this routine updates what is
  802. * called a Latent Attribute. The attributes only become effective
  803. * when a space is recieved.
  804. *
  805. * mrw - 11/1/94: Went to high intensity colors to more closely match
  806. * the minitel colors.
  807. *
  808. * ARGUMENTS:
  809. * hhEmu - private emulator handle.
  810. *
  811. * RETURNS:
  812. * void
  813. *
  814. */
  815. void emuMinitelFieldAttr(const HHEMU hhEmu)
  816. {
  817. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  818. LATENTATTR * const pstLA = &pstPRI->stLatentAttr;
  819. switch (hhEmu->emu_code)
  820. {
  821. case ETEXT('\x50'): pstLA->bkclr = 0; break;
  822. case ETEXT('\x51'): pstLA->bkclr = 12; break;
  823. case ETEXT('\x52'): pstLA->bkclr = 10; break;
  824. case ETEXT('\x53'): pstLA->bkclr = 14; break;
  825. case ETEXT('\x54'): pstLA->bkclr = 9; break;
  826. case ETEXT('\x55'): pstLA->bkclr = 13; break;
  827. case ETEXT('\x56'): pstLA->bkclr = 11; break;
  828. case ETEXT('\x57'): pstLA->bkclr = 15; break;
  829. case ETEXT('\x58'): pstLA->conceal=1; break;
  830. case ETEXT('\x5F'): pstLA->conceal=0; break;
  831. case ETEXT('\x59'): // separated mosaics off
  832. if (pstPRI->minitelG1Active)
  833. {
  834. pstPRI->minitelUseSeparatedMosaics = 0;
  835. return;
  836. }
  837. else
  838. {
  839. pstPRI->stLatentAttr.undrln = 0;
  840. }
  841. break;
  842. case ETEXT('\x5A'): // separated mosaics on
  843. if (pstPRI->minitelG1Active)
  844. {
  845. pstPRI->minitelUseSeparatedMosaics = 1;
  846. return;
  847. }
  848. else
  849. {
  850. pstPRI->stLatentAttr.undrln = 1;
  851. }
  852. break;
  853. default:
  854. return;
  855. }
  856. // Undocumented: setting any field attribute invalidates the
  857. // latent color context.
  858. //
  859. pstPRI->stLatentAttr.fBkClr = TRUE;
  860. pstPRI->stLatentAttr.fModified = TRUE;
  861. return;
  862. }
  863. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  864. * minitel_kbdin
  865. *
  866. * DESCRIPTION:
  867. * Processes keys for the minitel emulator.
  868. *
  869. * ARGUMENTS:
  870. * hhEmu - private emulator handle.
  871. * key - key to process
  872. *
  873. * RETURNS:
  874. * nothing
  875. */
  876. static int minitel_kbdin(const HHEMU hhEmu, int key, const int fTest)
  877. {
  878. int index;
  879. TCHAR c;
  880. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  881. if ((index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl)) != -1)
  882. {
  883. if (!fTest)
  884. {
  885. emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl);
  886. // This completes the code sent by emuSendKeyString(), page 124
  887. //
  888. if (key == (VK_RIGHT | VIRTUAL_KEY | SHIFT_KEY) ||
  889. key == (VK_RIGHT | VIRTUAL_KEY | SHIFT_KEY | EXTENDED_KEY))
  890. {
  891. c = (pstPRI->minitelSecondDep) ? TEXT('\x6c') : TEXT('\x68');
  892. CLoopCharOut(sessQueryCLoopHdl(hhEmu->hSession), c);
  893. }
  894. // Check for disconnect key. If hit twice consecutively,
  895. // it posts a disconnect to the modem guy.
  896. //
  897. if (key == (VK_F9 | VIRTUAL_KEY))
  898. {
  899. pstPRI->F9 += 1;
  900. if (pstPRI->F9 == 2)
  901. {
  902. PostMessage(sessQueryHwnd(hhEmu->hSession),
  903. WM_DISCONNECT, 0, 0);
  904. pstPRI->F9 = 0;
  905. }
  906. }
  907. }
  908. }
  909. else
  910. {
  911. // reset F9 counter, must have two consecutive to disconnect
  912. //
  913. pstPRI->F9 = 0;
  914. index = std_kbdin(hhEmu, key, fTest);
  915. }
  916. return index;
  917. }
  918. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  919. * FUNCTION:
  920. * minitelCharSet
  921. *
  922. * DESCRIPTION:
  923. * We don't really switch character sets here. Since minitel uses
  924. * 7 bit ASCII, we can user the half of the ASCII table for the
  925. * contigous and seperated mosaics that comprise the G1 char set.
  926. * Other rule here is that switching the the G1 character set
  927. * validates the background color on reception of the first mosaic.
  928. * One thing I haven't figured out yet is when a field attribute is
  929. * validated, does the latent attribute get reset or retain the last color?
  930. *
  931. * ARGUMENTS:
  932. * hhEmu - private emulator handle.
  933. *
  934. * RETURNS:
  935. * void
  936. *
  937. */
  938. void minitelCharSet(const HHEMU hhEmu)
  939. {
  940. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  941. pstPRI->stLatentAttr.undrln = 0;
  942. if (hhEmu->emu_code == ETEXT(0x0E)) // switch to G1
  943. {
  944. pstPRI->minitelG1Active = TRUE;
  945. pstPRI->minitelUseSeparatedMosaics = FALSE;
  946. }
  947. else
  948. {
  949. pstPRI->minitelG1Active = FALSE;
  950. }
  951. // underline, size and polarity attributes permanently canceled.
  952. //
  953. hhEmu->emu_charattr.undrln = 0;
  954. hhEmu->emu_charattr.dblhihi = 0;
  955. hhEmu->emu_charattr.dblhilo = 0;
  956. hhEmu->emu_charattr.dblwilf = 0;
  957. hhEmu->emu_charattr.dblwirt = 0;
  958. hhEmu->emu_charattr.revvid = 0;
  959. hhEmu->emu_charattr.symbol = 0;
  960. hhEmu->attrState[CS_STATE] =
  961. hhEmu->attrState[CSCLEAR_STATE] = hhEmu->emu_charattr;
  962. hhEmu->emu_clearattr = hhEmu->emu_charattr;
  963. return;
  964. }
  965. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  966. * FUNCTION:
  967. * minitelResetTerminal
  968. *
  969. * DESCRIPTION:
  970. * Response to a 1B 39 7F sequence. Puts terminal in power-up state.
  971. *
  972. * ARGUMENTS:
  973. * hhEmu - private emulator handle.
  974. *
  975. * RETURNS:
  976. * void
  977. *
  978. */
  979. void minitelResetTerminal(const HHEMU hhEmu)
  980. {
  981. minitelClearScreen(hhEmu, 0); // clear screen
  982. (*hhEmu->emu_setcurpos)(hhEmu, 0, 0);
  983. minitelClearLine(hhEmu, 0); // clear line 0
  984. (*hhEmu->emu_setcurpos)(hhEmu, 1, 0);
  985. minitelReset(hhEmu); // reset attributes
  986. ((PSTMTPRIVATE)hhEmu->pvPrivate)->fScrollMode = 0;
  987. EmuStdSetCursorType(hhEmu, EMU_CURSOR_NONE);
  988. minitelNtfy(hhEmu, 0);
  989. return;
  990. }
  991. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  992. * FUNCTION:
  993. * minitelCursorOn
  994. *
  995. * DESCRIPTION:
  996. * Turns minitel cursor on.
  997. *
  998. * ARGUMENTS:
  999. * hhEmu - private emulator handle.
  1000. *
  1001. * RETURNS:
  1002. * void
  1003. *
  1004. */
  1005. void minitelCursorOn(const HHEMU hhEmu)
  1006. {
  1007. EmuStdSetCursorType(hhEmu, EMU_CURSOR_BLOCK);
  1008. return;
  1009. }
  1010. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1011. * FUNCTION:
  1012. * minitelCursorOff
  1013. *
  1014. * DESCRIPTION:
  1015. * Turns minitel cursor off
  1016. *
  1017. * ARGUMENTS:
  1018. * hhEmu - private emulator handle.
  1019. *
  1020. * RETURNS:
  1021. * void
  1022. *
  1023. */
  1024. void minitelCursorOff(const HHEMU hhEmu)
  1025. {
  1026. #if defined(NDEBUG)
  1027. EmuStdSetCursorType(hhEmu, EMU_CURSOR_NONE);
  1028. #else
  1029. EmuStdSetCursorType(hhEmu, EMU_CURSOR_BLOCK);
  1030. #endif
  1031. return;
  1032. }
  1033. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1034. * FUNCTION:
  1035. * mintelMapMosaics
  1036. *
  1037. * DESCRIPTION:
  1038. * Maps regular character to a mosaic char for our font only.
  1039. *
  1040. * ARGUMENTS:
  1041. * hhEmu - private emulator handle.
  1042. * ch - character to convert
  1043. *
  1044. * RETURNS:
  1045. * converted or original character.
  1046. *
  1047. */
  1048. static ECHAR minitelMapMosaics(const HHEMU hhEmu, ECHAR ch)
  1049. {
  1050. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  1051. if (ch >= ETEXT('\x21') && ch <= ETEXT('\x3F'))
  1052. ch += ETEXT('\x1F');
  1053. // Another weird undocumented affect. Columns 4 and 5 (except 5F)
  1054. // map to columns 6 and 7 (page 101)
  1055. //
  1056. else if (ch >= ETEXT('\x40') && ch <= ETEXT('\x5E'))
  1057. ch += ETEXT('\x20');
  1058. else if (ch >= ETEXT('\x60') && ch <= ETEXT('\x7E'))
  1059. ch += 0;
  1060. if (pstPRI->minitelUseSeparatedMosaics && ch >= ETEXT('\x21') &&
  1061. ch <= ETEXT('\x7F'))
  1062. {
  1063. ch += ETEXT('\x40');
  1064. }
  1065. return ch;
  1066. }
  1067. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1068. * FUNCTION:
  1069. * minitelCursorReport
  1070. *
  1071. * DESCRIPTION:
  1072. * Return the current cursor location as US row col.
  1073. *
  1074. * ARGUMENTS:
  1075. * hhEmu - private emulator handle.
  1076. *
  1077. * RETURNS:
  1078. * void
  1079. *
  1080. */
  1081. void minitelCursorReport(const HHEMU hhEmu)
  1082. {
  1083. TCHAR ach[40];
  1084. ECHAR aech[40];
  1085. wsprintf(ach, TEXT("US%c%c"), hhEmu->emu_currow, hhEmu->emu_curcol);
  1086. CnvrtMBCStoECHAR(aech, sizeof(aech), ach,
  1087. StrCharGetByteCount(ach) + sizeof(TCHAR));
  1088. emuSendString(hhEmu, aech, StrCharGetEcharByteCount(aech));
  1089. return;
  1090. }
  1091. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1092. * FUNCTION:
  1093. * minitelFullScrnConceal
  1094. *
  1095. * DESCRIPTION:
  1096. * Just sets the blank bits on all the attributes.
  1097. *
  1098. * ARGUMENTS:
  1099. * hhEmu - private emulator handle.
  1100. *
  1101. * RETURNS:
  1102. * void
  1103. *
  1104. */
  1105. static void minitelFullScrnConceal(const HHEMU hhEmu)
  1106. {
  1107. int i, j;
  1108. PSTATTR ap;
  1109. for (i = 1 ; i <= hhEmu->emu_maxrow ; ++i)
  1110. {
  1111. ap = hhEmu->emu_apAttr[row_index(hhEmu, i)];
  1112. for (j = 0 ; j <= hhEmu->emu_maxcol ; ++j, ++ap)
  1113. ap->blank = 1;
  1114. updateLine(sessQueryUpdateHdl(hhEmu->hSession),
  1115. 1, hhEmu->emu_maxrow);
  1116. }
  1117. return;
  1118. }
  1119. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1120. * FUNCTION:
  1121. * minitelFullScrnReveal
  1122. *
  1123. * DESCRIPTION:
  1124. * Just sets the blank bits on all the attributes.
  1125. *
  1126. * ARGUMENTS:
  1127. * hhEmu - private emulator handle.
  1128. *
  1129. * RETURNS:
  1130. * void
  1131. *
  1132. */
  1133. static void minitelFullScrnReveal(const HHEMU hhEmu)
  1134. {
  1135. int i, j;
  1136. PSTATTR ap;
  1137. for (i = 1 ; i <= hhEmu->emu_maxrow ; ++i)
  1138. {
  1139. ap = hhEmu->emu_apAttr[row_index(hhEmu, i)];
  1140. for (j = 0 ; j <= hhEmu->emu_maxcol ; ++j, ++ap)
  1141. ap->blank = 0;
  1142. }
  1143. updateLine(sessQueryUpdateHdl(hhEmu->hSession), 1, hhEmu->emu_maxrow);
  1144. return;
  1145. }
  1146. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1147. * FUNCTION:
  1148. * minitelResync
  1149. *
  1150. * DESCRIPTION:
  1151. * Certain codes will cause the emulator to resynchronize, (goto state
  1152. * zero) and play the character thru.
  1153. *
  1154. * ARGUMENTS:
  1155. * hhEmu - private emulator handle.
  1156. *
  1157. * RETURNS:
  1158. * void
  1159. *
  1160. */
  1161. void minitelResync(const HHEMU hhEmu)
  1162. {
  1163. hhEmu->state = 0;
  1164. #if defined(EXTENDED_FEATURES)
  1165. (void)(*hhEmu->emu_datain)(hhEmu, hhEmu->emu_code);
  1166. #else
  1167. (void)(*hhEmu->emu_datain)((HEMU)hhEmu, hhEmu->emu_code);
  1168. #endif
  1169. return;
  1170. }
  1171. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1172. * FUNCTION:
  1173. * minitelSS2
  1174. *
  1175. * DESCRIPTION:
  1176. * SS2 is an alternate character set. It only has about 15 symbols so
  1177. * we just map them here to ones in our current minitel font.
  1178. *
  1179. * ARGUMENTS:
  1180. * hhEmu - private emulator handle.
  1181. *
  1182. * RETURNS:
  1183. * void
  1184. *
  1185. */
  1186. static void minitelSS2(const HHEMU hhEmu)
  1187. {
  1188. const int row = hhEmu->emu_currow;
  1189. const int col = hhEmu->emu_curcol;
  1190. BOOL fNoAdvance = FALSE;
  1191. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  1192. /* --- SS2 codes are ignored in semigraphic mode --- */
  1193. if (pstPRI->minitelG1Active)
  1194. {
  1195. hhEmu->state = 0;
  1196. return;
  1197. }
  1198. /* --- Map the character --- */
  1199. switch (hhEmu->emu_code)
  1200. {
  1201. case ETEXT('\x23'): hhEmu->emu_code = ETEXT('\xA3'); break; // british pound
  1202. case ETEXT('\x24'): hhEmu->emu_code = ETEXT('\x24'); break; // Dollar sign
  1203. case ETEXT('\x26'): hhEmu->emu_code = ETEXT('\x23'); break; // pound sign
  1204. case ETEXT('\x27'): hhEmu->emu_code = ETEXT('\xA7'); break; // integral
  1205. case ETEXT('\x2C'): hhEmu->emu_code = ETEXT('\xC3'); break; // left arrow
  1206. case ETEXT('\x2D'): hhEmu->emu_code = ETEXT('\xC0'); break; // up arrow
  1207. case ETEXT('\x2E'): hhEmu->emu_code = ETEXT('\xC4'); break; // right arrow
  1208. case ETEXT('\x2F'): hhEmu->emu_code = ETEXT('\xC5'); break; // down arrow
  1209. case ETEXT('\x30'): hhEmu->emu_code = ETEXT('\xB0'); break; // degree
  1210. case ETEXT('\x31'): hhEmu->emu_code = ETEXT('\xB1'); break; // plus-minus
  1211. case ETEXT('\x38'): hhEmu->emu_code = ETEXT('\xF7'); break; // divide
  1212. case ETEXT('\x3C'): hhEmu->emu_code = ETEXT('\xBC'); break; // 1/4
  1213. case ETEXT('\x3D'): hhEmu->emu_code = ETEXT('\xBD'); break; // 1/2
  1214. case ETEXT('\x3E'): hhEmu->emu_code = ETEXT('\xBE'); break; // 3/4
  1215. case ETEXT('\x41'): hhEmu->emu_code = ETEXT('\x60'); fNoAdvance = TRUE; break;
  1216. case ETEXT('\x42'): hhEmu->emu_code = ETEXT('\xB4'); fNoAdvance = TRUE; break;
  1217. case ETEXT('\x43'): hhEmu->emu_code = ETEXT('\x5E'); fNoAdvance = TRUE; break;
  1218. case ETEXT('\x48'): hhEmu->emu_code = ETEXT('\xA8'); fNoAdvance = TRUE; break;
  1219. case ETEXT('\x4A'): hhEmu->emu_code = ETEXT('\xB8'); fNoAdvance = TRUE; break;
  1220. case ETEXT('\x4B'): hhEmu->emu_code = ETEXT('\xB8'); fNoAdvance = TRUE; break;
  1221. case ETEXT('\x6A'): hhEmu->emu_code = ETEXT('\x8C'); break;
  1222. case ETEXT('\x7A'): hhEmu->emu_code = ETEXT('\x9C'); break;
  1223. case ETEXT('\x7B'): hhEmu->emu_code = ETEXT('\xDF'); break;
  1224. default: hhEmu->emu_code = ETEXT('\x5F'); break;
  1225. }
  1226. minitelGraphic(hhEmu);
  1227. if (fNoAdvance)
  1228. {
  1229. (*hhEmu->emu_setcurpos)(hhEmu, row, col); // don't advance cursor
  1230. }
  1231. else
  1232. {
  1233. // If we don't advance the cursor, we're done with this SS2
  1234. // sequence and reset the state to 0 - mrw, 2/3/95
  1235. //
  1236. hhEmu->state = 0;
  1237. }
  1238. return;
  1239. }
  1240. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1241. * FUNCTION:
  1242. * minitelSS2Part2
  1243. *
  1244. * DESCRIPTION:
  1245. * The second half a an SS2 code is the vowel portion for the accents
  1246. * page 90.
  1247. *
  1248. * ARGUMENTS:
  1249. * hhEmu - private emulator handle.
  1250. *
  1251. * RETURNS:
  1252. * void
  1253. *
  1254. */
  1255. static void minitelSS2Part2(const HHEMU hhEmu)
  1256. {
  1257. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  1258. switch (hhEmu->emu_code)
  1259. {
  1260. case ETEXT('a'):
  1261. switch (pstPRI->minitel_last_char)
  1262. {
  1263. case ETEXT('\x60'): hhEmu->emu_code = ETEXT('\xE0'); break;
  1264. case ETEXT('\x5E'): hhEmu->emu_code = ETEXT('\xE2'); break;
  1265. case ETEXT('\xA8'): hhEmu->emu_code = ETEXT('\xE4'); break;
  1266. default: break;
  1267. }
  1268. break;
  1269. case ETEXT('e'):
  1270. switch (pstPRI->minitel_last_char)
  1271. {
  1272. case ETEXT('\x60'): hhEmu->emu_code = ETEXT('\xE8'); break;
  1273. case ETEXT('\xB4'): hhEmu->emu_code = ETEXT('\xE9'); break;
  1274. case ETEXT('\x5E'): hhEmu->emu_code = ETEXT('\xEA'); break;
  1275. case ETEXT('\xA8'): hhEmu->emu_code = ETEXT('\xEB'); break;
  1276. default: break;
  1277. }
  1278. break;
  1279. case ETEXT('i'):
  1280. switch (pstPRI->minitel_last_char)
  1281. {
  1282. case ETEXT('\x5E'): hhEmu->emu_code = ETEXT('\xEE'); break;
  1283. case ETEXT('\xA8'): hhEmu->emu_code = ETEXT('\xEF'); break;
  1284. default: break;
  1285. }
  1286. break;
  1287. case ETEXT('o'):
  1288. switch (pstPRI->minitel_last_char)
  1289. {
  1290. case ETEXT('\x5E'): hhEmu->emu_code = ETEXT('\xF4'); break;
  1291. case ETEXT('\xA8'): hhEmu->emu_code = ETEXT('\xF6'); break;
  1292. default: break;
  1293. }
  1294. break;
  1295. case ETEXT('u'):
  1296. switch (pstPRI->minitel_last_char)
  1297. {
  1298. case ETEXT('\x60'): hhEmu->emu_code = ETEXT('\xF9'); break;
  1299. case ETEXT('\x5E'): hhEmu->emu_code = ETEXT('\xFB'); break;
  1300. case ETEXT('\xA8'): hhEmu->emu_code = ETEXT('\xFC'); break;
  1301. default: break;
  1302. }
  1303. break;
  1304. case ETEXT('c'):
  1305. switch (pstPRI->minitel_last_char)
  1306. {
  1307. case ETEXT('\xB8'): hhEmu->emu_code = ETEXT('\xE7'); break;
  1308. default: break;
  1309. }
  1310. break;
  1311. default:
  1312. // Docs say if we're not one of the above chars, then overwrite
  1313. // position with current char.
  1314. break;
  1315. }
  1316. minitelGraphic(hhEmu);
  1317. return;
  1318. }
  1319. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1320. * FUNCTION:
  1321. * minitelInsMode
  1322. *
  1323. * DESCRIPTION:
  1324. * Sets or Resets the insert mode depending on received code.
  1325. *
  1326. * ARGUMENTS:
  1327. * hhEmu - private emulator handle.
  1328. *
  1329. * RETURNS:
  1330. * void
  1331. *
  1332. */
  1333. static void minitelInsMode(const HHEMU hhEmu)
  1334. {
  1335. hhEmu->mode_IRM = (hhEmu->emu_code == ETEXT('\x68')) ? SET : RESET;
  1336. return;
  1337. }
  1338. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1339. * FUNCTION:
  1340. * minitelNtfy
  1341. *
  1342. * DESCRIPTION:
  1343. * Paints an inverted F or C when connection/disconnection notifications
  1344. * come in.
  1345. *
  1346. * ARGUMENTS:
  1347. * hhEmuPass - change this to hhEmu when reentrancy done.
  1348. * nNtfyCode - why it was called, (we don't use)
  1349. *
  1350. * RETURNS:
  1351. * void
  1352. *
  1353. */
  1354. void minitelNtfy(const HHEMU hhEmu, const int nNtfyCode)
  1355. {
  1356. const int r = row_index(hhEmu, 0);
  1357. const int c = hhEmu->emu_maxcol - 1;
  1358. ECHAR chr;
  1359. BOOL fFlash = FALSE;
  1360. switch (cnctQueryStatus(sessQueryCnctHdl(hhEmu->hSession)))
  1361. {
  1362. case CNCT_STATUS_FALSE:
  1363. default:
  1364. chr = ETEXT('F');
  1365. break;
  1366. case CNCT_STATUS_TRUE:
  1367. chr = ETEXT('C');
  1368. break;
  1369. case CNCT_STATUS_CONNECTING:
  1370. chr = ETEXT('C');
  1371. fFlash = TRUE;
  1372. break;
  1373. }
  1374. hhEmu->emu_apText[r][c] = chr;
  1375. hhEmu->emu_apAttr[r][c].revvid = 1;
  1376. hhEmu->emu_apAttr[r][c].blink = (unsigned)fFlash;
  1377. hhEmu->emu_apAttr[r][c].symbol = 0; // mrw-5/5/95
  1378. hhEmu->emu_aiEnd[r] = c;
  1379. updateChar(sessQueryUpdateHdl(hhEmu->hSession), 0, c, c);
  1380. NotifyClient(hhEmu->hSession, EVENT_TERM_UPDATE, 0);
  1381. return;
  1382. }
  1383. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1384. * FUNCTION:
  1385. * minitelPRO1
  1386. *
  1387. * DESCRIPTION:
  1388. * Handles PRO1 sequences (ESC,39,X).
  1389. *
  1390. * ARGUMENTS:
  1391. * hhEmu - private emulator handle
  1392. *
  1393. * RETURNS:
  1394. * void
  1395. *
  1396. */
  1397. static void minitelPRO1(const HHEMU hhEmu)
  1398. {
  1399. ECHAR aechBuf[35];
  1400. static const TCHAR achID[] = TEXT("\x01\x43r0\x04");
  1401. switch (hhEmu->emu_code)
  1402. {
  1403. case ETEXT('\x7B'): // ENQROM (page 139)
  1404. // See pages 21 & 22. Basicly we send back an indentification
  1405. // sequence delimited by SOH and EOT
  1406. //
  1407. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), achID,
  1408. StrCharGetByteCount(achID));
  1409. CLoopSend(sessQueryCLoopHdl(hhEmu->hSession), aechBuf, 5, 0);
  1410. break;
  1411. case ETEXT('\x67'): // Disconnect (page 139)
  1412. PostMessage(sessQueryHwnd(hhEmu->hSession), WM_DISCONNECT, 0, 0);
  1413. break;
  1414. case ETEXT('\x72'):
  1415. minitelStatusReply(hhEmu);
  1416. break;
  1417. default:
  1418. break;
  1419. }
  1420. return;
  1421. }
  1422. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1423. * FUNCTION:
  1424. * minitelPRO2Part1
  1425. *
  1426. * DESCRIPTION:
  1427. * Handles first half of a PRO2 sequence.
  1428. *
  1429. * ARGUMENTS:
  1430. * hhEmu - private emulator handle.
  1431. *
  1432. * RETURNS:
  1433. * void
  1434. *
  1435. */
  1436. static void minitelPRO2Part1(const HHEMU hhEmu)
  1437. {
  1438. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  1439. pstPRI->minitel_PRO1 = hhEmu->emu_code;
  1440. return;
  1441. }
  1442. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1443. * FUNCTION:
  1444. * minitelPRO2Part2
  1445. *
  1446. * DESCRIPTION:
  1447. * Handles the second half of a PRO2 sequence.
  1448. *
  1449. * ARGUMENTS:
  1450. * hhEmu - private emulator handle
  1451. *
  1452. * RETURNS:
  1453. * void
  1454. *
  1455. */
  1456. static void minitelPRO2Part2(const HHEMU hhEmu)
  1457. {
  1458. int fUpperCase;
  1459. BYTE abKey[256];
  1460. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  1461. switch (hhEmu->emu_code)
  1462. {
  1463. case ETEXT('\x43'): // scrolling
  1464. if (pstPRI->minitel_PRO1 == ETEXT('\x69'))
  1465. {
  1466. pstPRI->fScrollMode = TRUE;
  1467. }
  1468. if (pstPRI->minitel_PRO1 == ETEXT('\x6A'))
  1469. {
  1470. pstPRI->fScrollMode = FALSE;
  1471. }
  1472. minitelStatusReply(hhEmu);
  1473. break;
  1474. case ETEXT('\x44'): // error correction procedure (not implemented)
  1475. break;
  1476. case ETEXT('\x45'): // keyboard upper/lower case
  1477. if (pstPRI->minitel_PRO1 == ETEXT('\x69'))
  1478. {
  1479. fUpperCase = FALSE;
  1480. }
  1481. else if (pstPRI->minitel_PRO1 == ETEXT('\x6A'))
  1482. {
  1483. fUpperCase = TRUE;
  1484. }
  1485. else
  1486. {
  1487. break;
  1488. }
  1489. if (GetKeyboardState(abKey))
  1490. {
  1491. if (fUpperCase)
  1492. {
  1493. abKey[VK_CAPITAL] |= 0x01;
  1494. }
  1495. else
  1496. {
  1497. abKey[VK_CAPITAL] &= 0xfe;
  1498. }
  1499. SetKeyboardState(abKey);
  1500. }
  1501. #if TODO // TODO:REV 3/1/2002 Set the CapLock key state when GetKeyboardState fails.
  1502. else
  1503. {
  1504. SHORT lCapitalKeyState = GetKeyState(VK_CAPITAL);
  1505. if (fUpperCase)
  1506. {
  1507. lCapitalKeyState |= 0x01;
  1508. }
  1509. else
  1510. {
  1511. lCapitalKeyState &= 0xfe;
  1512. }
  1513. if (lCapitalKeyState)
  1514. {
  1515. INPUT lInput;
  1516. lInput.ki =
  1517. SendInput(1, lInput, sizeof(INPUT));
  1518. }
  1519. }
  1520. #endif // TODO:REV 3/1/2002
  1521. minitelStatusReply(hhEmu);
  1522. break;
  1523. default:
  1524. break;
  1525. }
  1526. return;
  1527. }
  1528. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1529. * FUNCTION:
  1530. * minitelStatusReply
  1531. *
  1532. * DESCRIPTION:
  1533. * Acknowledgement sequence for some PRO2 sequences and status requests.
  1534. *
  1535. * ARGUMENTS:
  1536. * hhEmu - private emulator handle.
  1537. *
  1538. * RETURNS:
  1539. * void
  1540. *
  1541. * AUTHOR: Mike Ward, 08-May-1995
  1542. */
  1543. static void minitelStatusReply(const HHEMU hhEmu)
  1544. {
  1545. ECHAR ach[10];
  1546. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  1547. // The PRO2 sequences \x43 and \x45 all return and acknowledgement
  1548. // of the form PRO2,\x73,status byte. The format of the status byte
  1549. // is defined in page 143, section 11.2.
  1550. //
  1551. // strcpy(ach, "\x1b\x3A\x73");
  1552. CnvrtMBCStoECHAR(ach, sizeof(ach), TEXT("\x1b\x3A\x73"),
  1553. StrCharGetByteCount(TEXT("\x1b\x3A\x73")));
  1554. ach[3] = ETEXT('\x40'); // bit 7 is always 1.
  1555. ach[3] |= pstPRI->fScrollMode ? ETEXT('\x02') : ETEXT('\x00');
  1556. ach[3] |=(GetKeyState(VK_CAPITAL) > 0) ? ETEXT('\x00') : ETEXT('\x08');
  1557. ach[4] = ETEXT('\0');
  1558. CLoopSend(sessQueryCLoopHdl(hhEmu->hSession), ach, 4, 0);
  1559. return;
  1560. }
  1561. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1562. * FUNCTION:
  1563. * emuMinitelSendKey
  1564. *
  1565. * DESCRIPTION:
  1566. * Used by the toolbar to emit the correct minitel sequence for the
  1567. * specified button.
  1568. *
  1569. * ARGUMENTS:
  1570. * hEmu - public emulator handle.
  1571. * iCmd - command string to send.
  1572. *
  1573. * RETURNS:
  1574. * void
  1575. *
  1576. * AUTHOR: Mike Ward, 10-Mar-1995
  1577. */
  1578. void emuMinitelSendKey(const HEMU hEmu, const int iCmd)
  1579. {
  1580. TCHAR *pach;
  1581. ECHAR aechBuf[20];
  1582. const HHEMU hhEmu = (HHEMU)hEmu;
  1583. const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
  1584. HCNCT hCnct = NULL;
  1585. BOOL bSendKey = TRUE;
  1586. int iRet = 0;
  1587. switch (iCmd)
  1588. {
  1589. case IDM_MINITEL_INDEX: pach = TEXT("\x13") TEXT("F"); break;
  1590. case IDM_MINITEL_CANCEL: pach = TEXT("\x13") TEXT("E"); break;
  1591. case IDM_MINITEL_PREVIOUS: pach = TEXT("\x13") TEXT("B"); break;
  1592. case IDM_MINITEL_REPEAT: pach = TEXT("\x13") TEXT("C"); break;
  1593. case IDM_MINITEL_GUIDE: pach = TEXT("\x13") TEXT("D"); break;
  1594. case IDM_MINITEL_CORRECT: pach = TEXT("\x13") TEXT("G"); break;
  1595. case IDM_MINITEL_NEXT: pach = TEXT("\x13") TEXT("H"); break;
  1596. case IDM_MINITEL_SEND: pach = TEXT("\x13") TEXT("A"); break;
  1597. case IDM_MINITEL_CONFIN:
  1598. pach = TEXT("\x13") TEXT("I");
  1599. pstPRI->F9 += 1;
  1600. break;
  1601. default:
  1602. assert(0);
  1603. return;
  1604. }
  1605. //
  1606. // Attempt to make a connection if we are currently disconnected, and
  1607. // we are supposed to initiate a connection.
  1608. //
  1609. hCnct = sessQueryCnctHdl(hhEmu->hSession);
  1610. iRet = cnctQueryStatus(hCnct);
  1611. if (iCmd == IDM_MINITEL_CONFIN)
  1612. {
  1613. if (iRet != CNCT_STATUS_TRUE && iRet != CNCT_STATUS_CONNECTING &&
  1614. iRet != CNCT_STATUS_DISCONNECTING)
  1615. {
  1616. if (SendMessageTimeout(sessQueryHwnd(hhEmu->hSession), WM_COMMAND,
  1617. IDM_ACTIONS_DIAL, 0,
  1618. SMTO_ABORTIFHUNG, 1000, NULL) == 0)
  1619. {
  1620. DWORD dwSendKey = GetLastError();
  1621. bSendKey = FALSE;
  1622. }
  1623. else
  1624. {
  1625. hCnct = sessQueryCnctHdl(hhEmu->hSession);
  1626. if (!hCnct)
  1627. {
  1628. bSendKey = FALSE;
  1629. }
  1630. else
  1631. {
  1632. iRet = cnctQueryStatus(hCnct);
  1633. if (iRet != CNCT_STATUS_TRUE)
  1634. {
  1635. bSendKey = FALSE;
  1636. }
  1637. }
  1638. }
  1639. }
  1640. else if(iRet != CNCT_STATUS_DISCONNECTING)
  1641. {
  1642. PostMessage(sessQueryHwnd(hhEmu->hSession), WM_DISCONNECT, 0, 0);
  1643. pstPRI->F9 = 0;
  1644. bSendKey = FALSE;
  1645. }
  1646. }
  1647. else if (iRet != CNCT_STATUS_TRUE)
  1648. {
  1649. bSendKey = FALSE;
  1650. }
  1651. if (bSendKey == TRUE)
  1652. {
  1653. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), pach,
  1654. StrCharGetByteCount(pach) + sizeof(TCHAR));
  1655. emuSendString((HHEMU)hEmu, aechBuf, StrCharGetEcharByteCount(aechBuf));
  1656. }
  1657. return;
  1658. }
  1659. #ifdef INCL_TERMINAL_SIZE_AND_COLORS
  1660. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1661. * FUNCTION:
  1662. * emuMinitelSetScrSize
  1663. *
  1664. * DESCRIPTION:
  1665. * Replaces std_setscrsize which was added to allow user settable screen
  1666. * sizes. However, the Minitel doesn't allow this.
  1667. *
  1668. * ARGUMENTS:
  1669. * hhEmu - The internal emulator handle.
  1670. *
  1671. * RETURNS:
  1672. * void
  1673. *
  1674. * AUTHOR: Bob Everett - 1 Sep 1998
  1675. */
  1676. void emuMinitelSetScrSize(const HHEMU hhEmu)
  1677. {
  1678. }
  1679. #endif
  1680. #endif // INCL_MINITEL