[ROSTESTS]
[reactos.git] / reactos / lib / sdk / crt / conio / kbhit.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/msvcrt/conio/kbhit.c
5 * PURPOSE: Checks for keyboard hits
6 * PROGRAMERS: Ariadne, Russell
7 * UPDATE HISTORY:
8 * 28/12/98: Created
9 * 27/9/08: An almost 100% working version of _kbhit()
10 */
11
12 #include <precomp.h>
13
14 static CRITICAL_SECTION CriticalSection;
15 volatile BOOL CriticalSectionInitialized=FALSE;
16
17 /*
18 * FIXME Initial keyboard char not detected on first punch
19 *
20 * @implemented
21 */
22
23 int _kbhit(void)
24 {
25 PINPUT_RECORD InputRecord = NULL;
26 DWORD NumberRead = 0;
27 DWORD EventsRead = 0;
28 DWORD RecordIndex = 0;
29 DWORD BufferIndex = 0;
30 HANDLE StdInputHandle = 0;
31 DWORD ConsoleInputMode = 0;
32
33 /* Attempt some thread safety */
34 if (!CriticalSectionInitialized)
35 {
36 InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400);
37 CriticalSectionInitialized = TRUE;
38 }
39
40 EnterCriticalSection(&CriticalSection);
41
42 if (char_avail)
43 {
44 LeaveCriticalSection(&CriticalSection);
45 return 1;
46 }
47
48 StdInputHandle = GetStdHandle(STD_INPUT_HANDLE);
49
50 /* Turn off processed input so we get key modifiers as well */
51 GetConsoleMode(StdInputHandle, &ConsoleInputMode);
52
53 SetConsoleMode(StdInputHandle, ConsoleInputMode & ~ENABLE_PROCESSED_INPUT);
54
55 /* Start the process */
56 if (!GetNumberOfConsoleInputEvents(StdInputHandle, &EventsRead))
57 {
58 LeaveCriticalSection(&CriticalSection);
59 return 0;
60 }
61
62 if (!EventsRead)
63 {
64 LeaveCriticalSection(&CriticalSection);
65 return 0;
66 }
67
68 if (!(InputRecord = (PINPUT_RECORD)malloc(EventsRead * sizeof(INPUT_RECORD))))
69 {
70 LeaveCriticalSection(&CriticalSection);
71 return 0;
72 }
73
74 if (!ReadConsoleInput(StdInputHandle, InputRecord, EventsRead, &NumberRead))
75 {
76 free(InputRecord);
77 LeaveCriticalSection(&CriticalSection);
78 return 0;
79 }
80
81 for (RecordIndex = 0; RecordIndex < NumberRead; RecordIndex++)
82 {
83 if (InputRecord[RecordIndex].EventType == KEY_EVENT &&
84 InputRecord[RecordIndex].Event.KeyEvent.bKeyDown)
85 {
86 BufferIndex = 1;
87 break;
88 }
89 }
90
91 free(InputRecord);
92
93 /* Restore console input mode */
94 SetConsoleMode(StdInputHandle, ConsoleInputMode);
95
96 LeaveCriticalSection(&CriticalSection);
97
98 return BufferIndex;
99 }
100
101