- 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 * PROJECT: ReactOS system libraries
* FILE: lib/msvcrt/conio/kbhit.c * FILE: lib/msvcrt/conio/kbhit.c
* PURPOSE: Checks for keyboard hits * PURPOSE: Checks for keyboard hits
* PROGRAMER: Ariadne * PROGRAMERS: Ariadne, Russell
* UPDATE HISTORY: * UPDATE HISTORY:
* 28/12/98: Created * 28/12/98: Created
* 27/9/08: An almost 100% working version of _kbhit()
*/ */
#include <precomp.h> #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) int _kbhit(void)
{ {
//INPUT_RECORD InputRecord; PINPUT_RECORD InputRecord = NULL;
DWORD NumberRead=0; DWORD NumberRead = 0;
if (char_avail) DWORD EventsRead = 0;
return(1); DWORD RecordIndex = 0;
else { DWORD BufferIndex = 0;
//FIXME PeekConsoleInput might do DeviceIo HANDLE StdInputHandle = 0;
//PeekConsoleInput((HANDLE)stdin->_file,&InputRecord,1,&NumberRead); DWORD ConsoleInputMode = 0;
return NumberRead;
/* 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;
} }