- An "almost working" kbhit implementation by Russel. The code is rather crappy, feel free to improve it.

Some notes:
1) Forgive my sloppy coding skills (all those LeaveCriticalSections, use of malloc/free), a lot of it was written in a rush to get something going. 2) For some reason, the first char entered isn't detected (on windows and reactos)
3) The thread safety code is questionable, I haven't tested this, but windows does use critical sections for it.
4) Compared to the windows way of doing it, it is probably wrong.
5) Maybe other things as well.

But it does work (at least when I tested it on windows and reactos) compared to the previous implementation of it which did not at all.
See issue #3747 for more details.

svn path=/trunk/; revision=38019
This commit is contained in:
Aleksey Bragin 2008-12-11 16:44:07 +00:00
parent 9507d41bad
commit e30784ec7b

View file

@ -3,28 +3,99 @@
* PROJECT: ReactOS system libraries
* FILE: lib/msvcrt/conio/kbhit.c
* PURPOSE: Checks for keyboard hits
* PROGRAMER: Ariadne
* PROGRAMERS: Ariadne, Russell
* UPDATE HISTORY:
* 28/12/98: Created
* 27/9/08: An almost 100% working version of _kbhit()
*/
#include <precomp.h>
static CRITICAL_SECTION CriticalSection;
volatile BOOL CriticalSectionInitialized=FALSE;
/*
* FIXME PeekConsoleInput returns more than keyboard hits
* FIXME Initial keyboard char not detected on first punch
*
* @unimplemented
* @implemented
*/
int _kbhit(void)
{
//INPUT_RECORD InputRecord;
DWORD NumberRead=0;
if (char_avail)
return(1);
else {
//FIXME PeekConsoleInput might do DeviceIo
//PeekConsoleInput((HANDLE)stdin->_file,&InputRecord,1,&NumberRead);
return NumberRead;
PINPUT_RECORD InputRecord = NULL;
DWORD NumberRead = 0;
DWORD EventsRead = 0;
DWORD RecordIndex = 0;
DWORD BufferIndex = 0;
HANDLE StdInputHandle = 0;
DWORD ConsoleInputMode = 0;
/* Attempt some thread safety */
if (!CriticalSectionInitialized)
{
InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400);
CriticalSectionInitialized = TRUE;
}
return 0;
EnterCriticalSection(&CriticalSection);
if (char_avail)
{
LeaveCriticalSection(&CriticalSection);
return 1;
}
StdInputHandle = GetStdHandle(STD_INPUT_HANDLE);
/* Turn off processed input so we get key modifiers as well */
GetConsoleMode(StdInputHandle, &ConsoleInputMode);
SetConsoleMode(StdInputHandle, ConsoleInputMode & ~ENABLE_PROCESSED_INPUT);
/* Start the process */
if (!GetNumberOfConsoleInputEvents(StdInputHandle, &EventsRead))
{
LeaveCriticalSection(&CriticalSection);
return 0;
}
if (!EventsRead)
{
LeaveCriticalSection(&CriticalSection);
return 0;
}
if (!(InputRecord = (PINPUT_RECORD)malloc(EventsRead * sizeof(INPUT_RECORD))))
{
LeaveCriticalSection(&CriticalSection);
return 0;
}
if (!ReadConsoleInput(StdInputHandle, InputRecord, EventsRead, &NumberRead))
{
free(InputRecord);
LeaveCriticalSection(&CriticalSection);
return 0;
}
for (RecordIndex = 0; RecordIndex < NumberRead; RecordIndex++)
{
if (InputRecord[RecordIndex].EventType == KEY_EVENT &&
InputRecord[RecordIndex].Event.KeyEvent.bKeyDown)
{
BufferIndex = 1;
break;
}
}
free(InputRecord);
/* Restore console input mode */
SetConsoleMode(StdInputHandle, ConsoleInputMode);
LeaveCriticalSection(&CriticalSection);
return BufferIndex;
}