diff options
Diffstat (limited to '')
-rw-r--r-- | private/utils/ulib/src/keyboard.cxx | 920 |
1 files changed, 920 insertions, 0 deletions
diff --git a/private/utils/ulib/src/keyboard.cxx b/private/utils/ulib/src/keyboard.cxx new file mode 100644 index 000000000..fca87c2e9 --- /dev/null +++ b/private/utils/ulib/src/keyboard.cxx @@ -0,0 +1,920 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + keyboard.cxx + +Abstract: + + This module contains the definitions of the member functions + of KEYBOARD class. + +Author: + + Jaime Sasson (jaimes) 24-Mar-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "stream.hxx" +#include "bufstrm.hxx" +#include "keyboard.hxx" + + +BOOL KEYBOARD::_FlagBreak; + + +#define CTRL_Z 0x1a + +DEFINE_EXPORTED_CONSTRUCTOR ( KEYBOARD, BUFFER_STREAM, ULIB_EXPORT ); + + +DEFINE_EXPORTED_CAST_MEMBER_FUNCTION( KEYBOARD, ULIB_EXPORT ); + + +KEYBOARD::~KEYBOARD ( + ) + +/*++ + +Routine Description: + + Destroy a KEYBOARD (close a keyboard handle). + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + SetConsoleMode( _KeyboardHandle, _PreviousMode ); + CloseHandle( _KeyboardHandle ); +} + + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::Initialize( + BOOLEAN LineMode, + BOOLEAN EchoMode + ) + +/*++ + +Routine Description: + + Initializes a KEYBOARD class. + +Arguments: + + LineMode - Indicates if the keyboard is to be set in line mode. + + EchoMode - Indicates if the keyboard is to be set in the echo mode + (characters are echoed to the current active screen) + +Return Value: + + BOOLEAN - Indicates if the initialization succeeded. + +--*/ + +{ + ULONG KeyboardMode; + + _KeyboardHandle = CreateFile( (LPWSTR)L"CONIN$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL ); + if( _KeyboardHandle ==INVALID_HANDLE_VALUE ) { + return( FALSE ); + } + if( !GetConsoleMode( _KeyboardHandle, &_PreviousMode ) ) { + return( FALSE ); + } + KeyboardMode = _PreviousMode; + if( LineMode ) { + KeyboardMode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; + } else { + KeyboardMode &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); + } + if( EchoMode ) { + KeyboardMode |= ENABLE_ECHO_INPUT; + } else { + KeyboardMode &= ~ENABLE_ECHO_INPUT; + } + if( !SetConsoleMode( _KeyboardHandle, KeyboardMode ) ) { + return( FALSE ); + } + _FlagCtrlZ = FALSE; + return( BUFFER_STREAM::Initialize( 256 ) ); +} + + +BOOL +KEYBOARD::BreakHandler ( + IN ULONG CtrlType + ) + +/*++ + +Routine Description: + + Handles Break events. Sets up the static data so that it can be + queried later on. + +Arguments: + + CtrlType - Supplies the type of Ctrl + +Return Value: + + none + +--*/ + +{ + UNREFERENCED_PARAMETER( CtrlType ); + + _FlagBreak = TRUE; + return TRUE; +} + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::GotABreak ( + ) + +/*++ + +Routine Description: + + Determines if a Break event (e.g Ctrl-C) was caught and handled. + + The static data that contains the Break information is set to a + "FALSE" state. Note that this means that if there is no Break + between two consecutive calls to this method, then the second + one will always return FALSE. + +Arguments: + + None. + +Return Value: + + BOOLEAN - TRUE if a Break event happened, FALSE otherwise. + +--*/ + +{ + BOOLEAN GotBreak = _FlagBreak; + + _FlagBreak = FALSE; + + return GotBreak; + +} + +ULIB_EXPORT +BOOLEAN +KEYBOARD::EnableBreakHandling( + ) + +/*++ + +Routine Description: + + Enables Break events handling (E.g. Ctrl-C). + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + _FlagBreak = FALSE; + + return SetConsoleCtrlHandler( KEYBOARD::BreakHandler, TRUE ); + +} + +ULIB_EXPORT +BOOLEAN +KEYBOARD::EnableLineMode( + ) + +/*++ + +Routine Description: + + Set the keyboard in line mode. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + ULONG Mode; + + if( !GetConsoleMode( _KeyboardHandle, &Mode ) ) { + return( FALSE ); + } + + Mode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT; + return( SetConsoleMode( _KeyboardHandle, Mode ) ); +} + + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::DisableBreakHandling( + ) + +/*++ + +Routine Description: + + Disables Break event handling (E.g. Ctrl-C). + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + _FlagBreak = FALSE; + + return SetConsoleCtrlHandler( KEYBOARD::BreakHandler, FALSE ); + +} + +ULIB_EXPORT +BOOLEAN +KEYBOARD::DisableLineMode( + ) + +/*++ + +Routine Description: + + Set the keyboard in character mode. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + ULONG Mode; + + // unreferenced parameters + (void)(this); + + if( !GetConsoleMode( _KeyboardHandle, &Mode ) ) { + return( FALSE ); + } + Mode &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT); + return( SetConsoleMode( _KeyboardHandle, Mode ) ); +} + + + + +BOOLEAN +KEYBOARD::IsLineModeEnabled( + ) CONST + +/*++ + +Routine Description: + + Finds out if the keyboard is in line mode. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the keyboard is in line mode + +--*/ + +{ + ULONG Mode; + + // unreferenced parameters + (void)(this); + + GetConsoleMode( _KeyboardHandle, &Mode ); + return( ( Mode & ENABLE_LINE_INPUT ) != 0 ); +} + + + +BOOLEAN +KEYBOARD::EnableEchoMode( + ) + +/*++ + +Routine Description: + + Set the keyboard in echo mode. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + ULONG Mode; + + if( !GetConsoleMode( _KeyboardHandle, &Mode ) ) { + return( FALSE ); + } + Mode |= ENABLE_ECHO_INPUT; + return( SetConsoleMode( _KeyboardHandle, Mode ) ); +} + + + +BOOLEAN +KEYBOARD::DisableEchoMode( + ) + +/*++ + +Routine Description: + + Does not echo characters read from keyboard. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + ULONG Mode; + + if( !GetConsoleMode( _KeyboardHandle, &Mode ) ) { + return( FALSE ); + } + Mode &= ~ENABLE_ECHO_INPUT; + return( SetConsoleMode( _KeyboardHandle, Mode ) ); +} + + + +BOOLEAN +KEYBOARD::IsEchoModeEnabled( + ) CONST + +/*++ + +Routine Description: + + Finds out if characters read from keyboard echoed to the screen. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the keyboard is in echo mode + +--*/ + +{ + ULONG Mode; + + GetConsoleMode( _KeyboardHandle, &Mode ); + return( ( Mode | ENABLE_ECHO_INPUT ) != 0 ); +} + + + +BOOLEAN +KEYBOARD::CheckForAsciiKey( + IN PINPUT_RECORD InputRecord, + IN ULONG NumberOfInputRecords + ) CONST + +/*++ + +Routine Description: + + Examines an array of input records in order to find out if at least + one ascii key was pressed. + +Arguments: + + InputRecord - Pointer to an array of INPUT_RECORDS. + + NumberOfInputRecords - Number of elements in the array + + +Return Value: + + BOOLEAN - Indicates if the input buffer contains at least one + ASCII key. + + +--*/ + +{ + BOOLEAN Result; + + // unreferenced parameters + (void)(this); + + Result = FALSE; + while( !Result && NumberOfInputRecords ) { + if( ( InputRecord->EventType == KEY_EVENT ) && + ( InputRecord->Event ).KeyEvent.bKeyDown && + +#if defined DBCS +// MSKK KazuM Sep,24,1993 + ( ( InputRecord->Event ).KeyEvent.uChar.UnicodeChar > 0 ) && + ( ( InputRecord->Event >.KeyEvent.uChar.UnicodeChar <= 0x7e ) ) { +#else + ( ( InputRecord->Event ).KeyEvent.uChar.AsciiChar > 0 ) && + ( ( InputRecord->Event ).KeyEvent.uChar.AsciiChar <= 0x7e ) ) { +#endif + + Result = TRUE; + } else { + NumberOfInputRecords--; + InputRecord++; + } + } + return( Result ); +} + + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::IsKeyAvailable( + OUT PBOOLEAN Available + ) CONST + +/*++ + +Routine Description: + + Determines if there is at least one key to be read. + +Arguments: + + Available - Pointer to the variable that will contain the result of + the query (if there is a key in the keyboard buffer). + +Return Value: + + BOOLEAN - A boolean value that indicates if the operation succeeded + If this value is FALSE, the contets of 'Available' has no + meaning (the calls to the APIs failed). + + +--*/ + + +{ + BOOLEAN Result; + ULONG NumberOfInputEvents; + PINPUT_RECORD Event; + ULONG NumberOfEventsRead; + + // + // Keys read, but not yet consumed, are kept are in a buffer. + // So, we have to check first if there is at least one key + // in this buffer. + // + if( BUFFER_STREAM::QueryBytesInBuffer() != 0 ) { + *Available = TRUE; + return( TRUE ); + } + // + // If there was no key previously read, we have to check the + // keyboard buffer for key events. + // + Result = FALSE; + if ( GetNumberOfConsoleInputEvents( _KeyboardHandle, + &NumberOfInputEvents ) ) { + + if( NumberOfInputEvents == 0 ) { + *Available = FALSE; + Result = TRUE; + } else { + Event = ( PINPUT_RECORD ) MALLOC( ( size_t )( sizeof( INPUT_RECORD ) * NumberOfInputEvents ) ); + if( PeekConsoleInput( _KeyboardHandle, + Event, + NumberOfInputEvents, + &NumberOfEventsRead ) && + NumberOfEventsRead != 0 ) { + + *Available = CheckForAsciiKey( Event, NumberOfInputEvents ); + Result = TRUE; + } + FREE( Event ); + } + + } + return( Result ); +} + + + + +BOOLEAN +KEYBOARD::FillBuffer( + OUT PBYTE Buffer, + IN ULONG BufferSize, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Fills a buffer with data read from the keyboard. + +Arguments: + + Buffer - Points to the buffer where the data will be put. + + BufferSize - Indicates total number of bytes to read from the stream. + + BytesRead - Points to the variable that will contain the number of + bytes read. + +Return Value: + + BOOLEAN - Indicates if the read operation succeeded. + + +--*/ + + +{ + BOOLEAN Result; + ULONG Count; + + + Result = ReadFile( _KeyboardHandle, + Buffer, + BufferSize, + BytesRead, + NULL ); + if( !Result ) { + return( Result ); + } + if (*BytesRead == 0) { + _FlagCtrlZ = TRUE; + } else if ( IsLineModeEnabled() ) { + Count = *BytesRead; + while( Count > 0 ) { + if( *Buffer != CTRL_Z ) { + Count--; + Buffer++; + } else { + *Buffer = 0; + *BytesRead -= Count; + _FlagCtrlZ = TRUE; + Count = 0; // To get out of while() loop + } + } + } + BUFFER_STREAM::SetStreamTypeANSI(); + return( Result ); +} + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::Flush( + ) + +/*++ + +Routine Description: + + Discards all keys in the buffer in BUFFER_STREAM, and flushes the + console input buffer. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + BUFFER_STREAM::FlushBuffer(); + return( FlushConsoleInputBuffer( _KeyboardHandle ) ); +} + + + +BOOLEAN +KEYBOARD::EndOfFile( + ) CONST + +/*++ + +Routine Description: + + Indicates if end-of-file has occurred when the keyboard was read. + End-of-file for a keyboard means that the keyboard was in line + mode and a Ctrl-Z was read from the keyboard. + +Arguments: + + None. + +Return Value: + + BOOLEAN - returns TRUE if the keyboard is in the line mode and a + CTRL-Z was read. Returns FALSE otherwise. + +--*/ + +{ + BOOLEAN CtrlZ; + BOOLEAN MoreKeys; + PBOOLEAN Pointer; + + CtrlZ = _FlagCtrlZ; + if( CtrlZ ) { + if( IsKeyAvailable( &MoreKeys ) ) { + // + // Enables client to read again from the keyboard + // + // This method is CONST and shouldn't modify + // _FlagCtrlZ, but here is the place to do it. + // I cannot define the method as non-const because it was + // defined as CONST in the base class + // + Pointer = &(((PKEYBOARD) this)->_FlagCtrlZ); + *Pointer = !MoreKeys; + } + } + return( CtrlZ ); +} + +STREAMACCESS +KEYBOARD::QueryAccess( + ) CONST + +/*++ + +Routine Description: + + Informs the caller about the access to the keyboard. + +Arguments: + + None. + +Return Value: + + STREAMACCESS - Returns READ_ACCESS always. + +--*/ + +{ + // unreferenced parameters + (void)(this); + + return( READ_ACCESS ); +} + + + + +ULONG +KEYBOARD::QueryDelay( + ) CONST + +/*++ + +Routine Description: + + Obtains the delay value of the keyboard. + +Arguments: + + None. + +Return Value: + + ULONG - The delay value. + +--*/ + +{ + INT Delay; + + SystemParametersInfo( SPI_GETKEYBOARDDELAY, 0, &Delay, 0 ); + + return Delay; +} + +HANDLE +KEYBOARD::QueryHandle( + ) CONST + +/*++ + +Routine Description: + + Returns to the caller the keyboard handle. + +Arguments: + + None. + +Return Value: + + HANDLE - Returns the keyboard handle. + +--*/ + +{ + return( _KeyboardHandle ); +} + + +ULONG +KEYBOARD::QuerySpeed( + ) CONST + +/*++ + +Routine Description: + + Obtains the speed rate of the keyboard. + +Arguments: + + None. + +Return Value: + + ULONG - The speed value. + +--*/ + +{ + WORD Speed; + + SystemParametersInfo( SPI_GETKEYBOARDSPEED, 0, &Speed, 0 ); + + return Speed; + +} + + +BOOLEAN +KEYBOARD::SetDelay( + IN ULONG Delay + ) CONST + +/*++ + +Routine Description: + + Sets the delay value of the keyboard. + +Arguments: + + Delay - Supplies the delay value + +Return Value: + + BOOLEAN - TRUE if delay set, FALSE otherwise + +--*/ + +{ + + // return SystemParametersInfo( SPI_SETKEYBOARDDELAY, (UINT)Delay, NULL, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE ); + return TRUE; + +} + + +BOOLEAN +KEYBOARD::SetSpeed ( + IN ULONG Speed + ) CONST + +/*++ + +Routine Description: + + Sets the speed rate of the keyboard. + +Arguments: + + Speed - Supplies the speed value + +Return Value: + + BOOLEAN - TRUE if speed set, FALSE otherwise + +--*/ + +{ + + // return SystemParametersInfo( SPI_SETKEYBOARDSPEED, (UINT)Speed, NULL, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE ); + return TRUE; + +} + +ULIB_EXPORT +CONST +PBOOL +KEYBOARD::GetPFlagBreak ( + VOID + ) CONST + +/*++ + +Routine Description: + + Returns pointer to _FlagBreak. Used by xcopy to pass pointer to _FlagBreak + as the lpCancel flag to CopyFileEx. When the user hits a Ctrl-C, this flag + becomes TRUE and CopyFileEx will stop copying the current file. + +Arguments: + + none + +Return Value: + + Pointer to _Flagbreak +--*/ + +{ + return (&_FlagBreak); +} |