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.

742 lines
25 KiB

  1. /***
  2. *getch.c - contains _getch(), _getche(), _ungetch() and kbhit for Win32
  3. *
  4. * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Defines the "direct console" functions listed above.
  8. *
  9. * NOTE: The real-mode DOS versions of these functions read from
  10. * standard input and are therefore redirected when standard input
  11. * is redirected. However, these versions ALWAYS read from the console,
  12. * even when standard input is redirected.
  13. *
  14. *Revision History:
  15. * 06-08-89 PHG Module created, based on asm version
  16. * 03-12-90 GJF Made calling type _CALLTYPE1, added #include
  17. * <cruntime.h> and fixed the copyright. Also, cleaned
  18. * up the formatting a bit.
  19. * 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits
  20. * 07-24-90 SBM Removed '32' from API names
  21. * 10-03-90 GJF New-style function declarators.
  22. * 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
  23. * 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
  24. * 01-16-91 GJF ANSI naming.
  25. * 01-25-91 SRW Get/SetConsoleMode parameters changed (_WIN32_)
  26. * 02-18-91 SRW Get/SetConsoleMode required read/write access (_WIN32_)
  27. * 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_)
  28. * 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
  29. * 07-26-91 GJF Took out init. stuff and cleaned up the error
  30. * handling [_WIN32_].
  31. * 12-11-92 GJF Initialize character buffer to 0 (int ch = 0;) and
  32. * use ReadConsole instead of ReadFile.
  33. * 03-20-93 GJF Completely rewritten, Cruiser support purged, _kbhit
  34. * (also rewritten) and _ungetch also merged in.
  35. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  36. * Change GetExtendedKeyCode to _getextendedkeycode
  37. * 05-10-93 GJF Fixed bug in _kbhit, pointer passed to free no
  38. * longer pointed to the allocated block.
  39. * 01-28-94 CFW Let's also look at the RIGHT_CTRL_PRESSED.
  40. * 09-06-94 CFW Replace MTHREAD with _MT.
  41. * 12-03-94 SKS Clean up OS/2 references
  42. * 01-13-95 GJF getche() should not echo a pushback character.
  43. * 01-10-95 CFW Debug CRT allocs.
  44. * 06-23-95 GJF Use _alloca instead of malloc/free. Also, make we
  45. * really need the event buffer before allocating it.
  46. * 10-05-95 SKS Remove two // commented-out lines
  47. * 12-08-95 SKS _coninph is now initialized on demand.
  48. * 02-07-98 GJF Changes for Win64: _coninph is now an intptr_t.
  49. * 12-10-99 GB Added support for recovery from stack overflow around
  50. * _alloca().
  51. * 04-25-00 GB exposed getextendedkeycode for use by _getwch()
  52. * 03-13-01 PML Fix heap leak if _alloca fails (vs7#224864)
  53. * 04-29-02 GB Added try-finally arounds lock-unlock.
  54. *
  55. *******************************************************************************/
  56. #include <cruntime.h>
  57. #include <oscalls.h>
  58. #include <conio.h>
  59. #include <internal.h>
  60. #include <mtdll.h>
  61. #include <stdio.h>
  62. #include <stdlib.h>
  63. #include <dbgint.h>
  64. #include <malloc.h>
  65. typedef struct {
  66. unsigned char LeadChar;
  67. unsigned char SecondChar;
  68. } CharPair;
  69. typedef struct {
  70. unsigned short ScanCode;
  71. CharPair RegChars;
  72. CharPair ShiftChars;
  73. CharPair CtrlChars;
  74. CharPair AltChars;
  75. } EnhKeyVals;
  76. typedef struct {
  77. CharPair RegChars;
  78. CharPair ShiftChars;
  79. CharPair CtrlChars;
  80. CharPair AltChars;
  81. } NormKeyVals;
  82. /*
  83. * Table of key values for enhanced keys
  84. */
  85. const static EnhKeyVals EnhancedKeys[] = {
  86. { 28, { 13, 0 }, { 13, 0 }, { 10, 0 }, { 0, 166 } },
  87. { 53, { 47, 0 }, { 63, 0 }, { 0, 149 }, { 0, 164 } },
  88. { 71, { 224, 71 }, { 224, 71 }, { 224, 119 }, { 0, 151 } },
  89. { 72, { 224, 72 }, { 224, 72 }, { 224, 141 }, { 0, 152 } },
  90. { 73, { 224, 73 }, { 224, 73 }, { 224, 134 }, { 0, 153 } },
  91. { 75, { 224, 75 }, { 224, 75 }, { 224, 115 }, { 0, 155 } },
  92. { 77, { 224, 77 }, { 224, 77 }, { 224, 116 }, { 0, 157 } },
  93. { 79, { 224, 79 }, { 224, 79 }, { 224, 117 }, { 0, 159 } },
  94. { 80, { 224, 80 }, { 224, 80 }, { 224, 145 }, { 0, 160 } },
  95. { 81, { 224, 81 }, { 224, 81 }, { 224, 118 }, { 0, 161 } },
  96. { 82, { 224, 82 }, { 224, 82 }, { 224, 146 }, { 0, 162 } },
  97. { 83, { 224, 83 }, { 224, 83 }, { 224, 147 }, { 0, 163 } }
  98. };
  99. /*
  100. * macro for the number of elements of in EnhancedKeys[]
  101. */
  102. #define NUM_EKA_ELTS ( sizeof( EnhancedKeys ) / sizeof( EnhKeyVals ) )
  103. /*
  104. * Table of key values for normal keys. Note that the table is padded so
  105. * that the key scan code serves as an index into the table.
  106. */
  107. const static NormKeyVals NormalKeys[] = {
  108. /* padding */
  109. { /* 0 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  110. { /* 1 */ { 27, 0 }, { 27, 0 }, { 27, 0 }, { 0, 1 } },
  111. { /* 2 */ { 49, 0 }, { 33, 0 }, { 0, 0 }, { 0, 120 } },
  112. { /* 3 */ { 50, 0 }, { 64, 0 }, { 0, 3 }, { 0, 121 } },
  113. { /* 4 */ { 51, 0 }, { 35, 0 }, { 0, 0 }, { 0, 122 } },
  114. { /* 5 */ { 52, 0 }, { 36, 0 }, { 0, 0 }, { 0, 123 } },
  115. { /* 6 */ { 53, 0 }, { 37, 0 }, { 0, 0 }, { 0, 124 } },
  116. { /* 7 */ { 54, 0 }, { 94, 0 }, { 30, 0 }, { 0, 125 } },
  117. { /* 8 */ { 55, 0 }, { 38, 0 }, { 0, 0 }, { 0, 126 } },
  118. { /* 9 */ { 56, 0 }, { 42, 0 }, { 0, 0 }, { 0, 127 } },
  119. { /* 10 */ { 57, 0 }, { 40, 0 }, { 0, 0 }, { 0, 128 } },
  120. { /* 11 */ { 48, 0 }, { 41, 0 }, { 0, 0 }, { 0, 129 } },
  121. { /* 12 */ { 45, 0 }, { 95, 0 }, { 31, 0 }, { 0, 130 } },
  122. { /* 13 */ { 61, 0 }, { 43, 0 }, { 0, 0 }, { 0, 131 } },
  123. { /* 14 */ { 8, 0 }, { 8, 0 }, { 127, 0 }, { 0, 14 } },
  124. { /* 15 */ { 9, 0 }, { 0, 15 }, { 0, 148 }, { 0, 15 } },
  125. { /* 16 */ { 113, 0 }, { 81, 0 }, { 17, 0 }, { 0, 16 } },
  126. { /* 17 */ { 119, 0 }, { 87, 0 }, { 23, 0 }, { 0, 17 } },
  127. { /* 18 */ { 101, 0 }, { 69, 0 }, { 5, 0 }, { 0, 18 } },
  128. { /* 19 */ { 114, 0 }, { 82, 0 }, { 18, 0 }, { 0, 19 } },
  129. { /* 20 */ { 116, 0 }, { 84, 0 }, { 20, 0 }, { 0, 20 } },
  130. { /* 21 */ { 121, 0 }, { 89, 0 }, { 25, 0 }, { 0, 21 } },
  131. { /* 22 */ { 117, 0 }, { 85, 0 }, { 21, 0 }, { 0, 22 } },
  132. { /* 23 */ { 105, 0 }, { 73, 0 }, { 9, 0 }, { 0, 23 } },
  133. { /* 24 */ { 111, 0 }, { 79, 0 }, { 15, 0 }, { 0, 24 } },
  134. { /* 25 */ { 112, 0 }, { 80, 0 }, { 16, 0 }, { 0, 25 } },
  135. { /* 26 */ { 91, 0 }, { 123, 0 }, { 27, 0 }, { 0, 26 } },
  136. { /* 27 */ { 93, 0 }, { 125, 0 }, { 29, 0 }, { 0, 27 } },
  137. { /* 28 */ { 13, 0 }, { 13, 0 }, { 10, 0 }, { 0, 28 } },
  138. /* padding */
  139. { /* 29 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  140. { /* 30 */ { 97, 0 }, { 65, 0 }, { 1, 0 }, { 0, 30 } },
  141. { /* 31 */ { 115, 0 }, { 83, 0 }, { 19, 0 }, { 0, 31 } },
  142. { /* 32 */ { 100, 0 }, { 68, 0 }, { 4, 0 }, { 0, 32 } },
  143. { /* 33 */ { 102, 0 }, { 70, 0 }, { 6, 0 }, { 0, 33 } },
  144. { /* 34 */ { 103, 0 }, { 71, 0 }, { 7, 0 }, { 0, 34 } },
  145. { /* 35 */ { 104, 0 }, { 72, 0 }, { 8, 0 }, { 0, 35 } },
  146. { /* 36 */ { 106, 0 }, { 74, 0 }, { 10, 0 }, { 0, 36 } },
  147. { /* 37 */ { 107, 0 }, { 75, 0 }, { 11, 0 }, { 0, 37 } },
  148. { /* 38 */ { 108, 0 }, { 76, 0 }, { 12, 0 }, { 0, 38 } },
  149. { /* 39 */ { 59, 0 }, { 58, 0 }, { 0, 0 }, { 0, 39 } },
  150. { /* 40 */ { 39, 0 }, { 34, 0 }, { 0, 0 }, { 0, 40 } },
  151. { /* 41 */ { 96, 0 }, { 126, 0 }, { 0, 0 }, { 0, 41 } },
  152. /* padding */
  153. { /* 42 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  154. { /* 43 */ { 92, 0 }, { 124, 0 }, { 28, 0 }, { 0, 0 } },
  155. { /* 44 */ { 122, 0 }, { 90, 0 }, { 26, 0 }, { 0, 44 } },
  156. { /* 45 */ { 120, 0 }, { 88, 0 }, { 24, 0 }, { 0, 45 } },
  157. { /* 46 */ { 99, 0 }, { 67, 0 }, { 3, 0 }, { 0, 46 } },
  158. { /* 47 */ { 118, 0 }, { 86, 0 }, { 22, 0 }, { 0, 47 } },
  159. { /* 48 */ { 98, 0 }, { 66, 0 }, { 2, 0 }, { 0, 48 } },
  160. { /* 49 */ { 110, 0 }, { 78, 0 }, { 14, 0 }, { 0, 49 } },
  161. { /* 50 */ { 109, 0 }, { 77, 0 }, { 13, 0 }, { 0, 50 } },
  162. { /* 51 */ { 44, 0 }, { 60, 0 }, { 0, 0 }, { 0, 51 } },
  163. { /* 52 */ { 46, 0 }, { 62, 0 }, { 0, 0 }, { 0, 52 } },
  164. { /* 53 */ { 47, 0 }, { 63, 0 }, { 0, 0 }, { 0, 53 } },
  165. /* padding */
  166. { /* 54 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  167. { /* 55 */ { 42, 0 }, { 0, 0 }, { 114, 0 }, { 0, 0 } },
  168. /* padding */
  169. { /* 56 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  170. { /* 57 */ { 32, 0 }, { 32, 0 }, { 32, 0 }, { 32, 0 } },
  171. /* padding */
  172. { /* 58 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  173. { /* 59 */ { 0, 59 }, { 0, 84 }, { 0, 94 }, { 0, 104 } },
  174. { /* 60 */ { 0, 60 }, { 0, 85 }, { 0, 95 }, { 0, 105 } },
  175. { /* 61 */ { 0, 61 }, { 0, 86 }, { 0, 96 }, { 0, 106 } },
  176. { /* 62 */ { 0, 62 }, { 0, 87 }, { 0, 97 }, { 0, 107 } },
  177. { /* 63 */ { 0, 63 }, { 0, 88 }, { 0, 98 }, { 0, 108 } },
  178. { /* 64 */ { 0, 64 }, { 0, 89 }, { 0, 99 }, { 0, 109 } },
  179. { /* 65 */ { 0, 65 }, { 0, 90 }, { 0, 100 }, { 0, 110 } },
  180. { /* 66 */ { 0, 66 }, { 0, 91 }, { 0, 101 }, { 0, 111 } },
  181. { /* 67 */ { 0, 67 }, { 0, 92 }, { 0, 102 }, { 0, 112 } },
  182. { /* 68 */ { 0, 68 }, { 0, 93 }, { 0, 103 }, { 0, 113 } },
  183. /* padding */
  184. { /* 69 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  185. { /* 70 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  186. { /* 71 */ { 0, 71 }, { 55, 0 }, { 0, 119 }, { 0, 0 } },
  187. { /* 72 */ { 0, 72 }, { 56, 0 }, { 0, 141 }, { 0, 0 } },
  188. { /* 73 */ { 0, 73 }, { 57, 0 }, { 0, 132 }, { 0, 0 } },
  189. { /* 74 */ { 0, 0 }, { 45, 0 }, { 0, 0 }, { 0, 0 } },
  190. { /* 75 */ { 0, 75 }, { 52, 0 }, { 0, 115 }, { 0, 0 } },
  191. { /* 76 */ { 0, 0 }, { 53, 0 }, { 0, 0 }, { 0, 0 } },
  192. { /* 77 */ { 0, 77 }, { 54, 0 }, { 0, 116 }, { 0, 0 } },
  193. { /* 78 */ { 0, 0 }, { 43, 0 }, { 0, 0 }, { 0, 0 } },
  194. { /* 79 */ { 0, 79 }, { 49, 0 }, { 0, 117 }, { 0, 0 } },
  195. { /* 80 */ { 0, 80 }, { 50, 0 }, { 0, 145 }, { 0, 0 } },
  196. { /* 81 */ { 0, 81 }, { 51, 0 }, { 0, 118 }, { 0, 0 } },
  197. { /* 82 */ { 0, 82 }, { 48, 0 }, { 0, 146 }, { 0, 0 } },
  198. { /* 83 */ { 0, 83 }, { 46, 0 }, { 0, 147 }, { 0, 0 } },
  199. /* padding */
  200. { /* 84 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  201. { /* 85 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  202. { /* 86 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  203. { /* 87 */ { 224, 133 }, { 224, 135 }, { 224, 137 }, { 224, 139 } },
  204. { /* 88 */ { 224, 134 }, { 224, 136 }, { 224, 138 }, { 224, 140 } }
  205. };
  206. /*
  207. * This is the one character push-back buffer used by _getch(), _getche()
  208. * and _ungetch().
  209. */
  210. static int chbuf = EOF;
  211. /*
  212. * Declaration for console handle
  213. */
  214. extern intptr_t _coninpfh;
  215. /*
  216. * Function that looks up the extended key code for a given event.
  217. */
  218. const CharPair * __cdecl _getextendedkeycode(KEY_EVENT_RECORD *);
  219. /***
  220. *int _getch(), _getche() - read one char. from console (without and with echo)
  221. *
  222. *Purpose:
  223. * If the "_ungetch()" push-back buffer is not empty (empty==-1) Then
  224. * Mark it empty (-1) and RETURN the value that was in it
  225. * Read a character using ReadConsole in RAW mode
  226. * Return the Character Code
  227. * _getche(): Same as _getch() except that the character value returned
  228. * is echoed (via "_putch()")
  229. *
  230. *Entry:
  231. * None, reads from console.
  232. *
  233. *Exit:
  234. * If an error is returned from the API
  235. * Then EOF
  236. * Otherwise
  237. * next byte from console
  238. * Static variable "chbuf" may be altered
  239. *
  240. *Exceptions:
  241. *
  242. *******************************************************************************/
  243. #ifdef _MT
  244. int __cdecl _getch (
  245. void
  246. )
  247. {
  248. int ch;
  249. _mlock(_CONIO_LOCK); /* secure the console lock */
  250. __TRY
  251. ch = _getch_lk(); /* input the character */
  252. __FINALLY
  253. _munlock(_CONIO_LOCK); /* release the console lock */
  254. __END_TRY_FINALLY
  255. return ch;
  256. }
  257. int __cdecl _getche (
  258. void
  259. )
  260. {
  261. int ch;
  262. _mlock(_CONIO_LOCK); /* secure the console lock */
  263. __TRY
  264. ch = _getche_lk(); /* input and echo the character */
  265. __FINALLY
  266. _munlock(_CONIO_LOCK); /* unlock the console */
  267. __END_TRY_FINALLY
  268. return ch;
  269. }
  270. #endif /* _MT */
  271. #ifdef _MT
  272. int __cdecl _getch_lk (
  273. #else
  274. int __cdecl _getch (
  275. #endif
  276. void
  277. )
  278. {
  279. INPUT_RECORD ConInpRec;
  280. DWORD NumRead;
  281. const CharPair *pCP;
  282. int ch = 0; /* single character buffer */
  283. DWORD oldstate;
  284. /*
  285. * check pushback buffer (chbuf) a for character
  286. */
  287. if ( chbuf != EOF ) {
  288. /*
  289. * something there, clear buffer and return the character.
  290. */
  291. ch = (unsigned char)(chbuf & 0xFF);
  292. chbuf = EOF;
  293. return ch;
  294. }
  295. if (_coninpfh == -1)
  296. return EOF;
  297. /*
  298. * _coninpfh, the handle to the console input, is created the first
  299. * time that either _getch() or _cgets() or _kbhit() is called.
  300. */
  301. if ( _coninpfh == -2 )
  302. __initconin();
  303. /*
  304. * Switch to raw mode (no line input, no echo input)
  305. */
  306. GetConsoleMode( (HANDLE)_coninpfh, &oldstate );
  307. SetConsoleMode( (HANDLE)_coninpfh, 0L );
  308. for ( ; ; ) {
  309. /*
  310. * Get a console input event.
  311. */
  312. if ( !ReadConsoleInput( (HANDLE)_coninpfh,
  313. &ConInpRec,
  314. 1L,
  315. &NumRead )
  316. || (NumRead == 0L) )
  317. {
  318. ch = EOF;
  319. break;
  320. }
  321. /*
  322. * Look for, and decipher, key events.
  323. */
  324. if ( (ConInpRec.EventType == KEY_EVENT) &&
  325. ConInpRec.Event.KeyEvent.bKeyDown ) {
  326. /*
  327. * Easy case: if uChar.AsciiChar is non-zero, just stuff it
  328. * into ch and quit.
  329. */
  330. if ( ch = (unsigned char)ConInpRec.Event.KeyEvent.uChar.AsciiChar )
  331. break;
  332. /*
  333. * Hard case: either an extended code or an event which should
  334. * not be recognized. let _getextendedkeycode() do the work...
  335. */
  336. if ( pCP = _getextendedkeycode( &(ConInpRec.Event.KeyEvent) ) ) {
  337. ch = pCP->LeadChar;
  338. chbuf = pCP->SecondChar;
  339. break;
  340. }
  341. }
  342. }
  343. /*
  344. * Restore previous console mode.
  345. */
  346. SetConsoleMode( (HANDLE)_coninpfh, oldstate );
  347. return ch;
  348. }
  349. /*
  350. * getche is just getch followed by a putch if no error occurred
  351. */
  352. #ifdef _MT
  353. int __cdecl _getche_lk (
  354. #else
  355. int __cdecl _getche (
  356. #endif
  357. void
  358. )
  359. {
  360. int ch; /* character read */
  361. /*
  362. * check pushback buffer (chbuf) a for character. if found, return
  363. * it without echoing.
  364. */
  365. if ( chbuf != EOF ) {
  366. /*
  367. * something there, clear buffer and return the character.
  368. */
  369. ch = (unsigned char)(chbuf & 0xFF);
  370. chbuf = EOF;
  371. return ch;
  372. }
  373. ch = _getch_lk(); /* read character */
  374. if (ch != EOF) {
  375. if (_putch_lk(ch) != EOF) {
  376. return ch; /* if no error, return char */
  377. }
  378. }
  379. return EOF; /* get or put failed, return EOF */
  380. }
  381. /***
  382. *int _kbhit() - return flag if a keystroke is already waiting to be read
  383. *
  384. *Purpose:
  385. * If the "_ungetch()" push-back buffer is not empty (empty==-1) Then
  386. * Return TRUE
  387. * Otherwise get the Keyboard Status (via DOSQUERYFHSTATE)
  388. *
  389. *Entry:
  390. * None, tests console.
  391. *
  392. *Exit:
  393. * returns 0 if no key waiting
  394. * = !0 if key waiting
  395. *
  396. *Exceptions:
  397. *
  398. *******************************************************************************/
  399. #ifdef _MT
  400. int __cdecl _kbhit_lk(void);
  401. int __cdecl _kbhit (
  402. void
  403. )
  404. {
  405. int retval;
  406. _mlock(_CONIO_LOCK); /* secure the console lock */
  407. __TRY
  408. retval = _kbhit_lk(); /* determine if a key is waiting */
  409. __FINALLY
  410. _munlock(_CONIO_LOCK); /* release the console lock */
  411. __END_TRY_FINALLY
  412. return retval;
  413. }
  414. int __cdecl _kbhit_lk (
  415. #else
  416. int __cdecl _kbhit (
  417. #endif
  418. void
  419. )
  420. {
  421. PINPUT_RECORD pIRBuf;
  422. DWORD NumPending;
  423. DWORD NumPeeked;
  424. int malloc_flag = 0;
  425. int ret = FALSE;
  426. /*
  427. * if a character has been pushed back, return TRUE
  428. */
  429. if ( chbuf != -1 )
  430. return TRUE;
  431. /*
  432. * _coninpfh, the handle to the console input, is created the first
  433. * time that either _getch() or _cgets() or _kbhit() is called.
  434. */
  435. if ( _coninpfh == -2 )
  436. __initconin();
  437. /*
  438. * Peek all pending console events
  439. */
  440. if ( (_coninpfh == -1) ||
  441. !GetNumberOfConsoleInputEvents((HANDLE)_coninpfh, &NumPending) ||
  442. (NumPending == 0))
  443. {
  444. return FALSE;
  445. }
  446. __try {
  447. pIRBuf = (PINPUT_RECORD)_alloca( NumPending * sizeof(INPUT_RECORD));
  448. }
  449. __except (EXCEPTION_EXECUTE_HANDLER) {
  450. _resetstkoflw();
  451. pIRBuf = NULL;
  452. }
  453. if ( pIRBuf == NULL )
  454. {
  455. pIRBuf = (PINPUT_RECORD)_malloc_crt( NumPending *
  456. sizeof(INPUT_RECORD));
  457. if ( pIRBuf == NULL )
  458. return FALSE;
  459. malloc_flag = 1;
  460. }
  461. if ( PeekConsoleInput( (HANDLE)_coninpfh,
  462. pIRBuf,
  463. NumPending,
  464. &NumPeeked ) &&
  465. (NumPeeked != 0L) &&
  466. (NumPeeked <= NumPending) )
  467. {
  468. /*
  469. * Scan all of the peeked events to determine if any is a key event
  470. * which should be recognized.
  471. */
  472. for ( ; NumPeeked > 0 ; NumPeeked--, pIRBuf++ ) {
  473. if ( (pIRBuf->EventType == KEY_EVENT) &&
  474. (pIRBuf->Event.KeyEvent.bKeyDown) &&
  475. ( pIRBuf->Event.KeyEvent.uChar.AsciiChar ||
  476. _getextendedkeycode( &(pIRBuf->Event.KeyEvent) ) ) )
  477. {
  478. /*
  479. * Key event corresponding to an ASCII character or an
  480. * extended code. In either case, success!
  481. */
  482. ret = TRUE;
  483. }
  484. }
  485. }
  486. if ( malloc_flag )
  487. _free_crt( pIRBuf );
  488. return ret;
  489. }
  490. /***
  491. *int _ungetch(c) - push back one character for "_getch()" or "_getche()"
  492. *
  493. *Purpose:
  494. * If the Push-back buffer "chbuf" is -1 Then
  495. * Set "chbuf" to the argument and return the argument
  496. * Else
  497. * Return EOF to indicate an error
  498. *
  499. *Entry:
  500. * int c - Character to be pushed back
  501. *
  502. *Exit:
  503. * If successful
  504. * returns character that was pushed back
  505. * Else if error
  506. * returns EOF
  507. *
  508. *Exceptions:
  509. *
  510. *******************************************************************************/
  511. #ifdef _MT
  512. int __cdecl _ungetch (
  513. int c
  514. )
  515. {
  516. int retval;
  517. _mlock(_CONIO_LOCK); /* lock the console */
  518. __TRY
  519. retval = _ungetch_lk(c); /* pushback character */
  520. __FINALLY
  521. _munlock(_CONIO_LOCK); /* unlock the console */
  522. __END_TRY_FINALLY
  523. return retval;
  524. }
  525. int __cdecl _ungetch_lk (
  526. #else
  527. int __cdecl _ungetch (
  528. #endif
  529. int c
  530. )
  531. {
  532. /*
  533. * Fail if the char is EOF or the pushback buffer is non-empty
  534. */
  535. if ( (c == EOF) || (chbuf != EOF) )
  536. return EOF;
  537. chbuf = (c & 0xFF);
  538. return chbuf;
  539. }
  540. /***
  541. * static CharPair * _getextendedkeycode(pKE) - return extended code (if any)
  542. * for key event.
  543. *
  544. *Purpose:
  545. * Core function for _getch (and getche) and essential to _kbhit. This
  546. * is the function that determines whether or not a key event NOT
  547. * accompanied by an ASCII character has an extended code and returns
  548. * that code.
  549. *
  550. *Entry:
  551. * None, tests console.
  552. *
  553. *Exit:
  554. * if successful, returns a pointer to a CharPair value holding the lead
  555. * and second characters of the extended code.
  556. *
  557. * if unsuccesful, returns NULL
  558. *
  559. *Exceptions:
  560. *
  561. *******************************************************************************/
  562. const CharPair * __cdecl _getextendedkeycode (
  563. KEY_EVENT_RECORD *pKE
  564. )
  565. {
  566. DWORD CKS; /* hold dwControlKeyState value */
  567. const CharPair *pCP; /* pointer to CharPair containing extended
  568. code */
  569. int i;
  570. if ( (CKS = pKE->dwControlKeyState) & ENHANCED_KEY ) {
  571. /*
  572. * Find the appropriate entry in EnhancedKeys[]
  573. */
  574. for ( pCP = NULL, i = 0 ; i < NUM_EKA_ELTS ; i++ ) {
  575. if ( EnhancedKeys[i].ScanCode == pKE->wVirtualScanCode ) {
  576. if ( CKS & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) )
  577. pCP = &(EnhancedKeys[i].AltChars);
  578. else if ( CKS & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) )
  579. pCP = &(EnhancedKeys[i].CtrlChars);
  580. else if ( CKS & SHIFT_PRESSED)
  581. pCP = &(EnhancedKeys[i].ShiftChars);
  582. else
  583. pCP = &(EnhancedKeys[i].RegChars);
  584. break;
  585. }
  586. }
  587. }
  588. else {
  589. /*
  590. * Regular key or a keyboard event which shouldn't be recognized.
  591. * Determine which by getting the proper field of the proper
  592. * entry in NormalKeys[], and examining the extended code.
  593. */
  594. if ( CKS & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) )
  595. pCP = &(NormalKeys[pKE->wVirtualScanCode].AltChars);
  596. else if ( CKS & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) )
  597. pCP = &(NormalKeys[pKE->wVirtualScanCode].CtrlChars);
  598. else if ( CKS & SHIFT_PRESSED)
  599. pCP = &(NormalKeys[pKE->wVirtualScanCode].ShiftChars);
  600. else
  601. pCP = &(NormalKeys[pKE->wVirtualScanCode].RegChars);
  602. if ( ((pCP->LeadChar != 0) && (pCP->LeadChar != 224)) ||
  603. (pCP->SecondChar == 0) )
  604. /*
  605. * Must be a keyboard event which should not be recognized
  606. * (e.g., shift key was pressed)
  607. */
  608. pCP = NULL;
  609. }
  610. return(pCP);
  611. }