mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 23:45:42 +00:00
[USETUP] Implement a basic console 'input queue' and implement PeekConsoleInput() and CONSOLE_ConInKeyPeek() around it.
This commit is contained in:
parent
fc2b4bc7ea
commit
6241a16f41
3 changed files with 178 additions and 22 deletions
|
@ -34,6 +34,13 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
/* DATA **********************************************************************/
|
||||||
|
|
||||||
|
static BOOLEAN InputQueueEmpty;
|
||||||
|
static BOOLEAN WaitForInput;
|
||||||
|
static KEYBOARD_INPUT_DATA InputDataQueue; // Only one element!
|
||||||
|
static IO_STATUS_BLOCK InputIosb;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
|
@ -76,6 +83,10 @@ AllocConsole(VOID)
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
/* Reset the queue state */
|
||||||
|
InputQueueEmpty = TRUE;
|
||||||
|
WaitForInput = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +104,10 @@ BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
FreeConsole(VOID)
|
FreeConsole(VOID)
|
||||||
{
|
{
|
||||||
|
/* Reset the queue state */
|
||||||
|
InputQueueEmpty = TRUE;
|
||||||
|
WaitForInput = FALSE;
|
||||||
|
|
||||||
if (StdInput != INVALID_HANDLE_VALUE)
|
if (StdInput != INVALID_HANDLE_VALUE)
|
||||||
NtClose(StdInput);
|
NtClose(StdInput);
|
||||||
|
|
||||||
|
@ -154,11 +169,20 @@ WINAPI
|
||||||
FlushConsoleInputBuffer(
|
FlushConsoleInputBuffer(
|
||||||
IN HANDLE hConsoleInput)
|
IN HANDLE hConsoleInput)
|
||||||
{
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
LARGE_INTEGER Offset, Timeout;
|
LARGE_INTEGER Offset, Timeout;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
KEYBOARD_INPUT_DATA InputData;
|
KEYBOARD_INPUT_DATA InputData;
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
|
/* Cancel any pending read */
|
||||||
|
if (WaitForInput)
|
||||||
|
NtCancelIoFile(hConsoleInput, &IoStatusBlock);
|
||||||
|
|
||||||
|
/* Reset the queue state */
|
||||||
|
InputQueueEmpty = TRUE;
|
||||||
|
WaitForInput = FALSE;
|
||||||
|
|
||||||
|
/* Flush the keyboard buffer */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Offset.QuadPart = 0;
|
Offset.QuadPart = 0;
|
||||||
|
@ -168,7 +192,7 @@ FlushConsoleInputBuffer(
|
||||||
NULL,
|
NULL,
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
&InputData,
|
&InputData,
|
||||||
sizeof(KEYBOARD_INPUT_DATA),
|
sizeof(InputData),
|
||||||
&Offset,
|
&Offset,
|
||||||
NULL);
|
NULL);
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING)
|
||||||
|
@ -186,6 +210,81 @@ FlushConsoleInputBuffer(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WINAPI
|
||||||
|
PeekConsoleInput(
|
||||||
|
IN HANDLE hConsoleInput,
|
||||||
|
OUT PINPUT_RECORD lpBuffer,
|
||||||
|
IN DWORD nLength,
|
||||||
|
OUT LPDWORD lpNumberOfEventsRead)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
LARGE_INTEGER Offset, Timeout;
|
||||||
|
KEYBOARD_INPUT_DATA InputData;
|
||||||
|
|
||||||
|
if (InputQueueEmpty)
|
||||||
|
{
|
||||||
|
/* Read the keyboard for an event, without waiting */
|
||||||
|
if (!WaitForInput)
|
||||||
|
{
|
||||||
|
Offset.QuadPart = 0;
|
||||||
|
Status = NtReadFile(hConsoleInput,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&InputIosb,
|
||||||
|
&InputDataQueue,
|
||||||
|
sizeof(InputDataQueue),
|
||||||
|
&Offset,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return FALSE;
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
/* No input yet, we will have to wait next time */
|
||||||
|
*lpNumberOfEventsRead = 0;
|
||||||
|
WaitForInput = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We already tried to read from the keyboard and are
|
||||||
|
* waiting for data, check whether something showed up.
|
||||||
|
*/
|
||||||
|
Timeout.QuadPart = -100; // Wait just a little bit.
|
||||||
|
Status = NtWaitForSingleObject(hConsoleInput, FALSE, &Timeout);
|
||||||
|
if (Status == STATUS_TIMEOUT)
|
||||||
|
{
|
||||||
|
/* Nothing yet, continue waiting next time */
|
||||||
|
*lpNumberOfEventsRead = 0;
|
||||||
|
WaitForInput = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
WaitForInput = FALSE;
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We got something in the queue */
|
||||||
|
InputQueueEmpty = FALSE;
|
||||||
|
WaitForInput = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch from the queue but keep it inside */
|
||||||
|
InputData = InputDataQueue;
|
||||||
|
|
||||||
|
lpBuffer->EventType = KEY_EVENT;
|
||||||
|
Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*lpNumberOfEventsRead = 1;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
ReadConsoleInput(
|
ReadConsoleInput(
|
||||||
|
@ -194,28 +293,53 @@ ReadConsoleInput(
|
||||||
IN DWORD nLength,
|
IN DWORD nLength,
|
||||||
OUT LPDWORD lpNumberOfEventsRead)
|
OUT LPDWORD lpNumberOfEventsRead)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER Offset;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
KEYBOARD_INPUT_DATA InputData;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
KEYBOARD_INPUT_DATA InputData;
|
||||||
|
|
||||||
Offset.QuadPart = 0;
|
if (InputQueueEmpty)
|
||||||
Status = NtReadFile(hConsoleInput,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&IoStatusBlock,
|
|
||||||
&InputData,
|
|
||||||
sizeof(KEYBOARD_INPUT_DATA),
|
|
||||||
&Offset,
|
|
||||||
NULL);
|
|
||||||
if (Status == STATUS_PENDING)
|
|
||||||
{
|
{
|
||||||
Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL);
|
/* Read the keyboard and wait for an event, skipping the queue */
|
||||||
Status = IoStatusBlock.Status;
|
if (!WaitForInput)
|
||||||
|
{
|
||||||
|
Offset.QuadPart = 0;
|
||||||
|
Status = NtReadFile(hConsoleInput,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&InputIosb,
|
||||||
|
&InputDataQueue,
|
||||||
|
sizeof(InputDataQueue),
|
||||||
|
&Offset,
|
||||||
|
NULL);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
/* Block and wait for input */
|
||||||
|
WaitForInput = TRUE;
|
||||||
|
Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL);
|
||||||
|
WaitForInput = FALSE;
|
||||||
|
Status = InputIosb.Status;
|
||||||
|
}
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We already tried to read from the keyboard and are
|
||||||
|
* waiting for data, block and wait for input.
|
||||||
|
*/
|
||||||
|
Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL);
|
||||||
|
WaitForInput = FALSE;
|
||||||
|
Status = InputIosb.Status;
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return FALSE;
|
/* Fetch from the queue and empty it */
|
||||||
|
InputData = InputDataQueue;
|
||||||
|
InputQueueEmpty = TRUE;
|
||||||
|
|
||||||
lpBuffer->EventType = KEY_EVENT;
|
lpBuffer->EventType = KEY_EVENT;
|
||||||
Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent);
|
Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent);
|
||||||
|
|
|
@ -66,11 +66,39 @@ CONSOLE_ConInKey(
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
|
/* Wait for a key press */
|
||||||
ReadConsoleInput(StdInput, Buffer, 1, &Read);
|
ReadConsoleInput(StdInput, Buffer, 1, &Read);
|
||||||
|
|
||||||
if ((Buffer->EventType == KEY_EVENT)
|
if ((Buffer->EventType == KEY_EVENT) &&
|
||||||
&& (Buffer->Event.KeyEvent.bKeyDown != FALSE))
|
(Buffer->Event.KeyEvent.bKeyDown != FALSE))
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
CONSOLE_ConInKeyPeek(
|
||||||
|
OUT PINPUT_RECORD Buffer)
|
||||||
|
{
|
||||||
|
DWORD Read = 0;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
/* Try to get a key press without blocking */
|
||||||
|
if (!PeekConsoleInput(StdInput, Buffer, 1, &Read))
|
||||||
|
return FALSE;
|
||||||
|
if (Read == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Consume it */
|
||||||
|
ReadConsoleInput(StdInput, Buffer, 1, &Read);
|
||||||
|
|
||||||
|
if ((Buffer->EventType == KEY_EVENT) &&
|
||||||
|
(Buffer->Event.KeyEvent.bKeyDown != FALSE))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,10 @@ VOID
|
||||||
CONSOLE_ConInKey(
|
CONSOLE_ConInKey(
|
||||||
OUT PINPUT_RECORD Buffer);
|
OUT PINPUT_RECORD Buffer);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
CONSOLE_ConInKeyPeek(
|
||||||
|
OUT PINPUT_RECORD Buffer);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CONSOLE_ConOutChar(
|
CONSOLE_ConOutChar(
|
||||||
IN CHAR c);
|
IN CHAR c);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue