diff options
Diffstat (limited to 'private/os2/os2ses/kbdrqust.c')
-rw-r--r-- | private/os2/os2ses/kbdrqust.c | 4046 |
1 files changed, 4046 insertions, 0 deletions
diff --git a/private/os2/os2ses/kbdrqust.c b/private/os2/os2ses/kbdrqust.c new file mode 100644 index 000000000..3c17e9332 --- /dev/null +++ b/private/os2/os2ses/kbdrqust.c @@ -0,0 +1,4046 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + kbdrqust.c + +Abstract: + + This module contains the Kbd requests thread and + the handler for Kbd requests. + +Author: + + Michael Jarus (mjarus) 23-Oct-1991 + +Environment: + + User Mode Only + +Revision History: + +--*/ + +#define WIN32_ONLY +#include "os2ses.h" +#include "trans.h" +#include "event.h" +#include "kbd.h" +#include "os2win.h" +#include <stdio.h> + +#define OS2_SCAN_INSERT_0 0x52 +#define OS2_SCAN_END_1 0x4F +#define OS2_SCAN_CTRL_END_1 0x75 +#define OS2_SCAN_DOWN_2 0x50 +#define OS2_SCAN_LEFT_4 0x4B +#define OS2_SCAN_CTRL_LEFT_4 0x73 +#define OS2_SCAN_RIGHT_6 0x4D +#define OS2_SCAN_CTRL_RIGHT_6 0x74 +#define OS2_SCAN_HOME_7 0x47 +#define OS2_SCAN_CTRL_HOME_7 0x77 +#define OS2_SCAN_UP_8 0x48 +#define OS2_SCAN_DEL 0x53 + +DWORD +Ow2GetOs2KbdEventIntoQueue(); + +DWORD +Ow2VioUpdateCurPos( + IN COORD CurPos + ); + +DWORD +Ow2VioReadCurPos( + ); + +DWORD +Ow2VioReadCurType(); + +VOID +KbdSetTable( + IN ULONG KbdCP + ); + +#if DBG +BYTE KbdEchoCharToConsoleStr[] = "KbdEchoCharToConsole"; +BYTE KbdEchoCharStr[] = "KbdEchoChar"; +BYTE KbdEchoStringToConsoleStr[] = "KbdEchoStringToConsole"; +BYTE KbdEchoAStringStr[] = "KbdEchoAString"; +BYTE KbdEchoBSAndFillSpacesStr[] = "KbdEchoBSAndFillSpaces"; +BYTE KbdEchoESCStr[] = "KbdEchoESC"; +BYTE KbdCueMoveToRightStr[] = "KbdCueMoveToRight"; +#endif + +#define KEYBOARD_NEW_MASK (USHORT)(KEYBOARD_2B_TURNAROUND | KEYBOARD_SHIFT_REPORT) +#define KEYBOARD_ECHO (USHORT)(KEYBOARD_ECHO_ON | KEYBOARD_ECHO_OFF) +#define KEYBOARD_INPUT (USHORT)(KEYBOARD_ASCII_MODE | KEYBOARD_BINARY_MODE) + +#define KEYBOARD_BINARY_SHIFT (KEYBOARD_BINARY_MODE | KEYBOARD_SHIFT_REPORT) +#define MODE_BINARY_SHIFT (SHIFT_REPORT_MODE | BINARY_MODE) + +#define KEYBOARD_SHIFT_ASCII_INPUT (USHORT)(KEYBOARD_ASCII_MODE | KEYBOARD_SHIFT_REPORT) +#define KEYBOARD_INPUT_RESERVED \ + ~( KEYBOARD_ECHO_ON | KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE | \ + KEYBOARD_ASCII_MODE | KEYBOARD_MODIFY_STATE | KEYBOARD_MODIFY_INTERIM | \ + KEYBOARD_MODIFY_TURNAROUND | KEYBOARD_2B_TURNAROUND | KEYBOARD_SHIFT_REPORT ) + +#define KbdBuffSize 256 +#define KBD_BUFFER_ADDRESS ((PUCHAR)KbdAddress) // used for ECHO to console +#define KBD_BUFFER_SIZE OS2_KBD_PORT_MSG_SIZE + +#define ALPHANUM_CHAR(BuffIndex) \ + ((((Char = LineInputBuff[BuffIndex].Char) >= '0') && \ + (Char <= '9')) || \ + ((Char >= 'a') && (Char <= 'z')) || \ + ((Char >= 'A') && (Char <= 'Z'))) \ + +#define GET_CURRENT_COORD (SesGrp->WinCoord) + +typedef struct _LINE_EDIT_KBD +{ + UCHAR Char; + SHORT X_Pos; // Used as X Coordinate for edit + // Used as offset for CUE +} LINE_EDIT_KBD; + +typedef enum +{ + CharMode, + AsciiMode, + BinaryMode +} KBDMODE; + +//CONSOLE_SCREEN_BUFFER_INFO KbdConsoleInfo; +KBDMODE KbdState; // state for HandleKeyboardInput +ULONG KbdWaitFlag; // flags for KbdCheckPackage and + // arg to GetKeyboardInput +/* (from event.h) + CharIn Peek String Read + ------ ---- ------ ---- + WAIT_MASK 0x01 User NOWAIT User WAIT (0 IO_WAIT, 1 IO_NOWAIT) + ENABLE_SHIFT_KEY 0x02 <if SHIFT report> + ENABLE_NON_ASCII_KEY 0x04 + + <if BINARY> + ENABLE_LN_EDITOR_KEY 0x08 <if ASCII (for KEYS OFF)> + ENABLE_KEYS_ON_KEY 0x10 <if ASCII and KEYS ON> + */ + +#define ENABLE_SHIFT_KEY 0x02 /* enable shift report keys (and break for them) */ + +/* + * for Command line editing + */ + +PUCHAR KbdCueBuffer = NULL; // 64K CUE buffer for KEYS ON + // This is a cyclic bufffer and all + // pointers are index of type USHORT. +BOOL KbdLineWasEdited; // TRUE if user edited the current line +USHORT KbdNextLinePointer; // where to put next input line +USHORT KbdCurrentLine; // index of current line in KbdCueBuffer +USHORT KbdIndexInLine; // index of current char in input line +BOOL KbdCueUpRowIsCurrent; // flag set after CR to indicate UP arrow + // returns the current line + +/* + * for GetOs2KbdRead + */ + +USHORT KbdBuffNextPtr; // when string typed was longer the size (ASCII read only) + // it points to the remain string +USHORT KbdBuffNextLen; // remaining bytes in the string + +/* + * for for HandleKeyboardInput.CharMode: + */ + +BOOL KbdPeekFlag; // called by CharIn (0) or Peek(1) + +/* + * for for HandleKeyboardInput.Ascii/BinaryMode: + */ + +USHORT KbdInputLength; // the current string length (num of chars + // already in input buffer for the user) +ULONG KbdMaxLength; // maximun input length (String.cb + // for StringIn, KbdBuffSize for Read) +USHORT KbdLength; // On enter: the requested length, + // On exit: the returned string length +USHORT KbdEndLength; // length of Turn Around string + +/* + * for for HandleKeyboardInput.AsciiMode: + */ + +LINE_EDIT_KBD LineInputBuff[KbdBuffSize]; // the current input buffer +UCHAR KbdLastBuff[KbdBuffSize]; // holds the previous "Buff" +USHORT KbdLastBuffPtr; // points to the char in KbdLastBuff to take (if F1) +USHORT LastStringLength; // length of the previous "Buff" +USHORT KbdEditFlag; // support EDIT line (F1 .. F4, ->, <-, Ins, Del) +USHORT KbdReadMode; // called by StringIn (0) or Read(1) +USHORT KbdFxWaitForChar; // waiting for char after F2(1) or F4(2) +BOOL KbdEchoFlag; // set if ECHO ON +BOOL KbdInsertOn; // INSERT key current state (1 - ON) +BOOL KbdEchoString; // copy string from last buffer (F2 and F3) +USHORT KbdTurnAroundChar; // turn around char to look for +BOOLEAN KbdTurnAroundCharTwo; // 2-byte turn around char (KEYBOARD_2B_TURNAROUND) +USHORT KbdDelIndex; +SHORT KbdFirstColumn; // first column for this input request +SHORT KbdStartOfLine; // first column on this line + +BOOLEAN KbdSetupTurnAroundCharTwo; // KbsSetStatus of KbdTurnAroundCharTwo: + // before new read KbdTurnAroundCharTwo + // is updated from this. + +#ifdef JAPAN +// MSKK May.07.1993 V-AkihiS +/* + * for KBDGetKbdType + */ +extern USHORT KbdType, KbdSubType; +extern BYTE OemId, OemSubType; +#endif + +/* + * internal functions + */ + +DWORD +GetOs2KbdKey( + IN BOOL PeekFlag, + IN USHORT WaitFlag, + OUT PKBDKEYINFO KeyInfo, + IN PVOID pMsg, + OUT PULONG pReply + ); + +DWORD +GetOs2KbdString( + IN USHORT WaitFlag, + IN OUT PKBDREQUEST PReq, + IN PVOID pMsg, + OUT PULONG pReply + ); + +DWORD +GetOs2KbdRead( + IN PULONG Length, + IN PVOID pMsg, + OUT PULONG pReply + ); + +VOID +KbdNewSetup( + IN PKBDINFO LastSetup + ); + +DWORD +GetOs2KbdStringRead( + IN USHORT WaitFlag, + IN USHORT EditFlag, + IN USHORT ReadMode, + IN ULONG MaxLength, + IN OUT PUSHORT Length, + IN PVOID pMsg, + OUT PULONG pReply + ); + +DWORD +HandleKeyboardInput( + IN PKEYEVENTINFO pKbd + ); + +DWORD +Ow2KbdSetStatus( + IN PKBDREQUEST PReq + ); + +BOOL +KbdKeyIsTurnAround( + IN UCHAR Char, + IN UCHAR Scan + ); + +/* + * Echo functions for KbdStringIn/Read (ASCII) + */ + +DWORD +KbdEchoNL( + IN ULONG Count + ); + +DWORD +KbdEchoESC( + IN ULONG Count, + IN ULONG HorzMove + ); + +DWORD +KbdEchoBSAndFillSpaces( + IN ULONG BSCount, + IN ULONG SpaceCount + ); + +DWORD +KbdEchoBeep( + IN ULONG Count + ); + +DWORD +KbdEchoChar( + IN UCHAR Char, + IN ULONG Count + ); + +DWORD +KbdEchoAString( + IN PUCHAR String, + IN ULONG Length + ); + +/* + * CUE functions + */ + +VOID +KbdCueEraseAndDisplayLine( + IN ULONG NewLineIndex + ); + +VOID +KbdCueMoveToRight( + IN ULONG StartIndex, + IN ULONG StringLength, + IN ULONG UpdateLVB + ); + +VOID +KbdCueMoveToLeft( + IN ULONG StartIndex, + IN ULONG MoveLength + ); + +VOID +KbdCueUpdateBufferOffset( + IN ULONG StartIndex, + IN ULONG StringLength, + IN ULONG StartOffset + ); + +VOID +KbdCueDeleteCharAndShift( + IN ULONG StartIndex, + IN ULONG NumChar + ); + +VOID +KbdCueHandleChar( + IN UCHAR Char, + IN ULONG Count + ); + +VOID +KbdCueSetCurTypeToHalf(); + +VOID +KbdCueSetCurTypeToQuater(); + + +DWORD +KbdInit(IN VOID) +{ + KBDINFO LastSetup; + + if (InitQueue(&KbdQueue)) + { + return(TRUE); + } + + KbdMonQueue = PhyKbdQueue = KbdQueue; + + KbdQueue->Setup.cb = sizeof(KBDINFO); + KbdQueue->Setup.fsMask = KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE; + KbdQueue->Setup.chTurnAround = 0x0D; /* default: <ENTER>/<CR> */ + KbdQueue->Setup.fsInterim = 0; + KbdQueue->Setup.fsState = 0; + KbdQueue->bNlsShift = 0; + KbdQueue->LastKeyFlag = FALSE; + + LastSetup.fsMask = KEYBOARD_BINARY_MODE; + KbdNewSetup(&LastSetup); + + KbdAddress = ((PCHAR)Os2SessionCtrlDataBaseAddress) + KBD_OFFSET; + + Ow2KbdXlateVars.OtherFlags = InterruptTime; + + return(FALSE); +} + + +DWORD +KbdInitAfterSesGrp(IN VOID) +{ + if (SesGrp->KeysOnFlag) + { + KbdCueBuffer = HeapAlloc(HandleHeap, 0, 64 * 1024); + if ( KbdCueBuffer == NULL ) + { +#if DBG + KdPrint(("OS2SES(KbdRequset): unable to allocate Cue buffer\n")); +#endif + return ERROR_KBD_NO_MORE_HANDLE; + } + } + return(FALSE); +} + + +BOOL +ServeKbdRequest(IN PKBDREQUEST PReq, + OUT PVOID PStatus, + IN PVOID pMsg, + OUT PULONG pReply) +{ + DWORD Rc; + KBDINFO LastSetup; + PKEY_EVENT_QUEUE TempKbdQueue; + KEYEVENTINFO In; + + Rc = 0; + TempKbdQueue = (PKEY_EVENT_QUEUE) PReq->hKbd; + +#if DBG + if (( PReq->Request != KBDNewFocus ) && + ( PReq->Request != KBDNewCountry ) && + ( PReq->Request != KBDOpen ) && + (KbdQueue != TempKbdQueue)) + { + KdPrint(("OS2SES(KbdRequest-%u): illegal handle\n", + PReq->Request)); + } +#endif + + switch (PReq->Request) + { + case KBDOpen: + if((Rc = InitQueue(&TempKbdQueue)) == NO_ERROR) + { + PReq->hKbd = TempKbdQueue; + } + break; + + case KBDClose: + if (( TempKbdQueue != PhyKbdQueue) && TempKbdQueue->Count ) + { + if ( !--TempKbdQueue->Count ) + { + HeapFree(HandleHeap, 0, + (LPSTR) TempKbdQueue->MonHdr.MemoryStartAddress); + } + } + break; + + case KBDDupLogHandle: + if (TempKbdQueue != PhyKbdQueue) + { + TempKbdQueue->Count++ ; + } + break; + + case KBDReadStdIn: + if (!hStdInConsoleType) + { +#if DBG + KdPrint(("OS2SES(KbdRequest-KbdReadStdIn): illegal request\n")); +#endif + Rc = ERROR_INVALID_HANDLE; + break; + } + // falls into KBDRead + + case KBDRead: + Rc = GetOs2KbdRead(&PReq->Length, + pMsg, + pReply); + break; + + + case KBDCharIn: + Rc = GetOs2KbdKey(0, /* CharIn/Peek flag */ + (USHORT)PReq->fWait, + &PReq->d.KeyInfo, + pMsg, + pReply); + break; + + case KBDStringIn: + Rc = GetOs2KbdString((USHORT)PReq->fWait, + PReq, + pMsg, + pReply); + break; + + case KBDPeek: + Rc = GetOs2KbdKey(1, /* CharIn/Peek flag */ + IO_NOWAIT, + &PReq->d.KeyInfo, + pMsg, + pReply); + break; + + case KBDFlushBuffer: + In.wRepeatCount = 0x7FFF; + while (TRUE) + { + KbdQueue->LastKeyFlag = FALSE; + KbdQueue->Out == KbdQueue->In; + + Rc = GetKeyboardInput( IO_NOWAIT, + &In, + pMsg, + pReply); + + if ( !Rc ) /* no char & NO_WAIT */ + break; + } + break; + + case KBDGetStatus: + if (PReq->d.KbdInfo.cb < 10 ) + { Rc = ERROR_KBD_INVALID_LENGTH; + break; + } + Ow2GetOs2KbdEventIntoQueue(); + PReq->d.KbdInfo = KbdQueue->Setup; +#ifdef DBCS +// MSKK May.18.1992 KazuM + GetNlsMode(&KbdQueue->Setup); +#endif + PReq->d.KbdInfo.fsState &= KBDINFO_STATE_MASK; + break; + + case KBDSetStatus: + Rc = Ow2KbdSetStatus(PReq); + break; + + case KBDFreeFocus: + LastSetup = KbdQueue->Setup; + KbdQueue = PhyKbdQueue; + NewKbdQueue(KbdQueue); + KbdNewSetup(&LastSetup); + break; + + case KBDNewFocus: + LastSetup = KbdQueue->Setup; + KbdQueue = TempKbdQueue; + NewKbdQueue(KbdQueue); + KbdNewSetup(&LastSetup); + break; + +// BUGBUG?? - do the following requests working on the current/last-focused +// logical keyboard, on the physical keyboard or on a logical +// keyboard passed as a parameter + + case KBDGetInputMode: + switch (KbdQueue->Setup.fsMask & KEYBOARD_BINARY_SHIFT) + { + case KEYBOARD_BINARY_SHIFT: + PReq->d.InputMode = MODE_BINARY_SHIFT; + break; + + case KEYBOARD_BINARY_MODE: + PReq->d.InputMode = BINARY_MODE; + break; + + default: + PReq->d.InputMode = ASCII_MODE; + break; + } + break; + + case KBDGetInterimFlag: +#ifdef DBCS +// MSKK May.18.1992 KazuM + GetNlsMode(&KbdQueue->Setup); +#endif + PReq->d.Interim = (UCHAR)(KbdQueue->Setup.fsInterim & + (CONVERSION_REQUEST | INTERIM_CHAR)); + break; + + case KBDGetKbdType: +#ifdef JAPAN +// MSKK May.07.1993 V-AkihiS + if (KbdType == KBD_TYPE_JAPAN && OemId == SUB_KBD_TYPE_MICROSOFT) + { + switch(OemSubType) + { + case MICROSOFT_KBD_101_TYPE: + PReq->d.KbdType[0] = 0x0001; + PReq->d.KbdType[1] = 0x0000; + PReq->d.KbdType[2] = 0x0000; + break; + case MICROSOFT_KBD_AX_TYPE: + PReq->d.KbdType[0] = 0x0010; + PReq->d.KbdType[1] = 0x0000; + PReq->d.KbdType[2] = 0x0001; + break; + case MICROSOFT_KBD_106_TYPE: + PReq->d.KbdType[0] = 0x0001; + PReq->d.KbdType[1] = 0x82B3; + PReq->d.KbdType[2] = 0x0032; + break; + case MICROSOFT_KBD_002_TYPE: + PReq->d.KbdType[0] = 0x0006; + PReq->d.KbdType[1] = 0x82B3; + PReq->d.KbdType[2] = 0x0032; + break; + default: + PReq->d.KbdType[0] = 0x0001; + PReq->d.KbdType[1] = 0x0000; + PReq->d.KbdType[2] = 0x0000; +#if DBG + KdPrint(("OS2SES(Kbd) This keyboard isn't supported yet.\n")); +#endif + } + } else + { + PReq->d.KbdType[0] = 0x0001; + PReq->d.KbdType[1] = 0x0000; + PReq->d.KbdType[2] = 0x0000; +#if DBG + KdPrint(("OS2SES(Kbd) This keyboard isn't supported yet.\n")); +#endif + } +#else + PReq->d.KbdType = 0x0001; // BUGBUG +#endif + break; + + case KBDGetHotKey: + // BUGBUG PReq->d.HotKey = + /* + + if ((*pParm != HOTKEY_MAX_COUNT) && + (*pParm != HOTKEY_CURRENT_COUNT)) + { + } +#define HOTKEY_MAX_COUNT 0x0000 +#define HOTKEY_CURRENT_COUNT 0x0001 + */ + + break; + + case KBDGetShiftState: +#ifdef DBCS +// MSKK Oct.20.1992 V-AkihiS + GetNlsMode(&KbdQueue->Setup); + PReq->d.Shift.fNLS = HIBYTE(KbdQueue->Setup.fsInterim); +#else + PReq->d.Shift.fNLS = KbdQueue->bNlsShift; +#endif + PReq->d.Shift.fsState = KbdQueue->Setup.fsState; + break; + + case KBDSetInputMode: + LastSetup = KbdQueue->Setup; + KbdQueue->Setup.fsMask = (USHORT) + ((KbdQueue->Setup.fsMask & ~(KEYBOARD_INPUT | KEYBOARD_SHIFT_REPORT)) | + ((PReq->d.InputMode & SHIFT_REPORT_MODE) ? KEYBOARD_SHIFT_REPORT : 0) | + ((PReq->d.InputMode & BINARY_MODE ) ? + KEYBOARD_BINARY_MODE : KEYBOARD_ASCII_MODE)); + KbdNewSetup(&LastSetup); + break; + + case KBDSetShiftState: + LastSetup = KbdQueue->Setup; + KbdQueue->Setup.fsState = PReq->d.Shift.fsState; + // BUGBUG : SHIFTSTATE.fbNLS PReq->d.Shift.fNLS +#ifdef DBCS +// MSKK Oct.20.1992 V-AkihiS + KbdQueue->Setup.fsInterim = MAKEWORD( + KbdQueue->Setup.fsInterim, + PReq->d.Shift.fNLS + ); + SetNlsMode(KbdQueue->Setup); +#endif + KbdNewSetup(&LastSetup); + break; + + case KBDSetTypamaticRate: + Rc = !SystemParametersInfo( + SPI_SETKEYBOARDDELAY, + PReq->d.RateDelay.usDelay, + NULL, + 0); + if (!Rc) + { + Rc = !SystemParametersInfo( + SPI_SETKEYBOARDSPEED, + PReq->d.RateDelay.usRate, + NULL, + 0 + ); + } + break; + + case KBDSetInTerimFlag: + LastSetup = KbdQueue->Setup; +#ifdef DBCS +// MSKK Mar.03.1993 V-AkihiS + KbdQueue->Setup.fsInterim = MAKEWORD( + PReq->d.Interim, + HIBYTE(KbdQueue->Setup.fsInterim) + ); + SetNlsMode(KbdQueue->Setup); +#else + KbdQueue->Setup.fsInterim = (USHORT)PReq->d.Interim; +#endif + KbdNewSetup(&LastSetup); + break; + + case KBDGetCp: + PReq->d.CodePage = SesGrp->KbdCP; + break; + + case KBDSetCp: + Rc = KbdNewCp(PReq->d.CodePage); + break; + + case KBDNewCountry: + SesGrp->KeyboardCountry = PReq->d.CodePage; //Hack - Not Really CodePage + KbdSetTable(SesGrp->KbdCP); + *pReply = 0; + + break; + + case KBDXlate: + /* + { + KBD_XLATE_VARS XlateVars; + KBD_MON_PACKAGE KeyInfo[3]; + PKBDTRANS pKbdXlate = &PReq->d.KbdTrans; + + RtlZeroMemory(&XlateVars, sizeof(KBD_XLATE_VARS)); + if (pKbdXlate->fsShift != 0) + { + // continue translation + + //? = pKbdXlate->fsShift; + } + + RtlZeroMemory(&Os2KeyInfo[0], 3 * sizeof(KBD_MON_PACKAGE)); + + //KeyInfo[0].MonitorFlag = pKbdXlate->...; + //KeyInfo[0].DeviceFlag = pKbdXlate->...; + KeyInfo[0].KeyInfo.chChar = pKbdXlate->chChar; + KeyInfo[0].KeyInfo.chScan = pKbdXlate->chScan; + KeyInfo[0].KeyInfo.fbStatus = pKbdXlate->fbStatus; + KeyInfo[0].KeyInfo.bNlsShift = pKbdXlate->bNlsShift; + KeyInfo[0].KeyInfo.fsState = pKbdXlate->fsState; + KeyInfo[0].KeyBoardFlag = pKbdXlate->fsDD; + + KeyInfo[0].KeyInfo.fbStatus = 0x40; + + //? XlateVars.XlateFlags |= SecPrefix; // Have seen E0 prefix + + Rc = Ow2KbdXlate( + pKbdXlate->chScan, // ScanCode, + &XlateVars, // pFlagArea, + &KeyInfo[0], // pMonitorPack, + Ow2KbdScanTable // pTransTable + ); + + //? which packet - KeyInfo[?] + pKbdXlate->chChar = KeyInfo[0].KeyInfo.chChar; + pKbdXlate->chScan = KeyInfo[0].KeyInfo.chScan; + pKbdXlate->fbStatus = KeyInfo[0].KeyInfo.fbStatus; + pKbdXlate->bNlsShift = KeyInfo[0].KeyInfo.bNlsShift; + pKbdXlate->fsState = KeyInfo[0].KeyInfo.fsState; + pKbdXlate->fsDD = KeyInfo[0].KeyBoardFlag; + //? pKbdXlate->fsXlate = ; + //? pKbdXlate->fsShift = ; + } + */ + case KBDSetCustXt: + /* from ??? */ + default: + Rc = (DWORD)-1L; //STATUS_INVALID_PARAMETER; +#if DBG + IF_OD2_DEBUG2( KBD, OS2_EXE ) + KdPrint(("OS2SES(KbdRequest): Unknown Kbd request = %X\n", PReq->Request)); +#endif + } + + if ( Rc == 1 ) + { + Rc = GetLastError(); + } + + *(PDWORD) PStatus = Rc; + return(TRUE); // Continue +} + + +DWORD +Ow2KbdSetStatus(IN PKBDREQUEST PReq) +{ + KBDINFO LastSetup, *pKbdSetup; + USHORT KbdMask, Mask; + + /* + * check legalty of parameters: + * + * 1. sizeof structure + * 2. reserved bits + * 3. mutuex bits (ECHO_ON & ECHO_OFF, ASCII & BINARY, ASCII & SHIFT) + */ + + LastSetup = KbdQueue->Setup; + if (PReq->d.KbdInfo.cb != 10 ) + { + return ERROR_KBD_INVALID_LENGTH; + } + + KbdMask = PReq->d.KbdInfo.fsMask; + pKbdSetup = &KbdQueue->Setup; + + if (KbdMask & KEYBOARD_INPUT_RESERVED) + { + return ERROR_KBD_INVALID_INPUT_MASK; + } + + if ((KbdMask & KEYBOARD_ECHO ) == KEYBOARD_ECHO) + { + return ERROR_KBD_INVALID_ECHO_MASK; + } + + if ((KbdMask & KEYBOARD_INPUT) == KEYBOARD_INPUT) + { + return ERROR_KBD_INVALID_INPUT_MASK; + } + + if ((KbdMask & KEYBOARD_SHIFT_ASCII_INPUT) == KEYBOARD_SHIFT_ASCII_INPUT) + { + return ERROR_KBD_INVALID_INPUT_MASK; + } + + /* + * check modified bits and set the flags according: + * + * 1. STATE - set fsState + * 2. INTERIM - set fsInterim + * 3. TURNAROUND - set chTurnAround + */ + +#ifdef DBCS +// MSKK Jul.1993 V-AKihiS + if (KbdMask & KEYBOARD_MODIFY_STATE) + { + pKbdSetup->fsState = PReq->d.KbdInfo.fsState; + pKbdSetup->fsInterim = MAKEWORD( + LOBYTE(pKbdSetup->fsInterim), + HIBYTE(PReq->d.KbdInfo.fsInterim) + ); + SetNlsMode(*pKbdSetup); + } + + if (KbdMask & KEYBOARD_MODIFY_INTERIM) + pKbdSetup->fsInterim = MAKEWORD( + LOBYTE(PReq->d.KbdInfo.fsInterim), + HIBYTE(pKbdSetup->fsInterim) + ); +#else + if (KbdMask & KEYBOARD_MODIFY_STATE) + pKbdSetup->fsState = PReq->d.KbdInfo.fsState; + + if (KbdMask & KEYBOARD_MODIFY_INTERIM) + pKbdSetup->fsInterim = PReq->d.KbdInfo.fsInterim; +#endif + + if (KbdMask & KEYBOARD_MODIFY_TURNAROUND) + pKbdSetup->chTurnAround = PReq->d.KbdInfo.chTurnAround; + + /* + * update mask: + * + * 1. update mask of new bits SHIFT_REPORT & 2B_TURNAROUND + * 2. if new mask includes new ECHO then update mask + * 3. if new mask includes new INPUT then update mask + */ + + Mask = KEYBOARD_NEW_MASK; + + if (KbdMask & KEYBOARD_ECHO) + { + Mask |= KEYBOARD_ECHO; + } + + if (KbdMask & KEYBOARD_INPUT) + { + Mask |= KEYBOARD_INPUT; + } + + pKbdSetup->fsMask = + (pKbdSetup->fsMask & ~Mask) | (KbdMask & Mask); + + KbdNewSetup(&LastSetup); + + return (0L); +} + + +DWORD +GetOs2KbdKey( IN BOOL PeekFlag, + IN USHORT WaitFlag, + OUT PKBDKEYINFO KeyInfo, + IN PVOID pMsg, + OUT PULONG pReply) +/*++ + +Routine Description: + + This routine get kbd char for KbdCharIn and KbdPeek + +Arguments: + + PeekFlag - TRUE if peek (0 - CharIn, 1 - Peek) + + WaitFlag - Wait if no input (IO_WAIT or IO_NOWAIT) + + KeyInfo - Where to return the key input record + + pMsg - Pointer to the LPC message + + pReply - Pointer to flag if return reply on LPC + +Return Value: + + +Note: + + If no event and IO_WAIT: save pMsg, put 0 into *pReply and + the reply is postponed. + +--*/ +{ + + DWORD Rc; + KEYEVENTINFO In; + + + RtlZeroMemory(KeyInfo, sizeof(KBDKEYINFO)); + KeyInfo->fsState = 1; + + if ( KbdQueue->Setup.fsMask & KEYBOARD_ASCII_MODE ) + { + KbdAsciiMode = 1; + } else + { + KbdAsciiMode = 0; + if ((KbdQueue->Setup.fsMask & KEYBOARD_BINARY_SHIFT) == KEYBOARD_BINARY_SHIFT) + { + WaitFlag |= ENABLE_SHIFT_KEY; + } + } + + WaitFlag |= ENABLE_NON_ASCII_KEY; + + KbdState = CharMode; + KbdWaitFlag = (ULONG)WaitFlag; + KbdPeekFlag = PeekFlag; + + for(;;) + { + if (KbdQueue->LastKeyFlag) + { + In = KbdQueue->LastKey; + KbdQueue->LastKeyFlag = FALSE; + } else + { + In.wRepeatCount = 0x7FFF; + Rc = GetKeyboardInput( KbdWaitFlag, + &In, + pMsg, + pReply); + + if ( !Rc ) /* no char & (NO_WAIT or postponed reply) */ + return(Rc); + } + + if (( HandleKeyboardInput( + &In + )) == NO_ERROR ) + { + *KeyInfo = In.KeyInfo[0].KeyInfo; + return(0L); + } + } +} + + +DWORD +GetOs2KbdString( IN USHORT WaitFlag, + //IN OUT KBDRW *Length, + IN OUT PKBDREQUEST PReq, + IN PVOID pMsg, + OUT PULONG pReply) +{ + + DWORD Rc; + USHORT EditFlag = 0; + STRINGINBUF String = PReq->d.String; + + KbdAsciiMode = (BOOL)(( KbdQueue->Setup.fsMask & KEYBOARD_ASCII_MODE ) ? 1 : 0); + + if ( String.cchIn && ( String.cchIn <= String.cb ) && + ( KbdLastBuff[String.cchIn] == '\r' )) + { + EditFlag = 1; + } + + String.cchIn = String.cb; + + Rc = GetOs2KbdStringRead( WaitFlag, + EditFlag, + 0, + (ULONG)String.cb, + &String.cchIn, + pMsg, + pReply); + if ( pReply ) + { + PReq->Length = (ULONG)KbdLength; + String.cchIn = KbdLength; + if ( String.cchIn != String.cb ) + PReq->Length++ ; // ASCII mode - copy the CR + } + + return(Rc); + +} + + +DWORD +GetOs2KbdRead(IN PULONG Length, + IN PVOID pMsg, + OUT PULONG pReply) +{ + DWORD Rc, i; + + KbdAsciiMode = (BOOL)(( KbdQueue->Setup.fsMask & KEYBOARD_ASCII_MODE ) ? 1 : 0); + + /* + * ignore previously-typed-but-not-returned character in binary mode + */ + + if ( !KbdAsciiMode || !KbdBuffNextLen) + { + + Rc = GetOs2KbdStringRead( IO_WAIT, + TRUE, + 1, + KbdBuffSize - 2, + (PUSHORT)Length, + pMsg, + pReply); + + return(Rc); + + } + + /* + * + * Copy from kbd buffer + * + */ + + if (*Length > (ULONG)KbdBuffNextLen) + *Length = KbdBuffNextLen; + + for (i = 0 ; i < *Length ; i++ ) + { + if ((KBD_BUFFER_ADDRESS[i] = KbdLastBuff[i + KbdBuffNextPtr]) == '\n') + { + *Length = i + 1; + break; + } + } + + KbdBuffNextLen -= *((PUSHORT)Length); + KbdBuffNextPtr += (USHORT)*Length; + + return(0L); +} + + +DWORD +GetOs2KbdStringRead(IN USHORT WaitFlag, + IN USHORT EditFlag, + IN USHORT ReadMode, + IN ULONG MaxLength, + IN OUT PUSHORT Length, + IN PVOID pMsg, + OUT PULONG pReply) +/*++ + +Routine Description: + + This routine get kbd string for KbdStringIn and Read("KBD$" or non-redirected + STD-IN). + +Arguments: + + WaitFlag - Wait if no input (IO_WAIT or IO_NOWAIT) + + EditFlag - TRUE if edit last line(0/1 according to cchIn - StringIn, 1 - Read) + + ReadMode - Called by StringIn (0) or Read(1) + + MaxLength - Maximun input length (String.cb for StringIn, KbdBuffSize + for Read) + + Length - On enter: the requested length, on exit: the returned string + length (String.cchIn for StringIn, Length field in LPC for Read) + + pMsg - Pointer to the LPC message + + pReply - Pointer to flag if return reply on LPC + +Return Value: + + +Note: + + If no event and IO_WAIT: save pMsg, put 0 into *pReply and + the reply is postponed. + +--*/ +{ + KEYEVENTINFO In; + DWORD Rc; + + KbdLastBuffPtr = KbdInputLength = KbdFxWaitForChar = KbdDelIndex = 0; + KbdIndexInLine = 0; + KbdInsertOn = KbdEchoString = KbdLineWasEdited = FALSE; + //KbdSecondTurnAround = KbdEndFlag = FALSE; + KbdLength = *Length; + + if ( KbdAsciiMode ) + { + /* + * ASCII mode + */ + + KbdWaitFlag = (ULONG)(WaitFlag | ENABLE_LN_EDITOR_KEY); + + /* + * + * Get Start Cursor-Position + * + */ + + // force SesGrp->WinCoord and CurType params to get updated + + Ow2VioReadCurPos(); + Ow2VioReadCurType(); + + if (SesGrp->KeysOnFlag) + { + KbdWaitFlag |= ENABLE_KEYS_ON_KEY; + KbdCueSetCurTypeToQuater(); + } + KbdMaxLength = MaxLength - 1; /* leave space for the TurnAround char at the end */ + KbdEndLength = 1; + KbdReadMode = ReadMode; + + KbdEchoFlag = (BOOL)(( KbdQueue->Setup.fsMask & KEYBOARD_ECHO_ON ) ? 1 : 0); + KbdTurnAroundChar = KbdQueue->Setup.chTurnAround; + KbdTurnAroundCharTwo = KbdSetupTurnAroundCharTwo; + + //if (KbdQueue->Setup.chTurnAround & 0x80) + if(KbdTurnAroundCharTwo) + { KbdMaxLength--; /* need another space for 2-byte-TurnAround */ + KbdEndLength++; + } + + KbdEditFlag = EditFlag; + + LineInputBuff[KbdInputLength].X_Pos = KbdStartOfLine = KbdFirstColumn = + GET_CURRENT_COORD.X; + + KbdState = AsciiMode; + + } else + { + KbdWaitFlag = (ULONG)(WaitFlag | ENABLE_NON_ASCII_KEY); + KbdState = BinaryMode; + } + + for(;;) + { + /* + * + * Restore saved Input Key if any + * + */ + + if (KbdQueue->LastKeyFlag) + { + In = KbdQueue->LastKey; + KbdQueue->LastKeyFlag = FALSE; + } else + { + /* + * + * Get Input Key if any + * + */ + + In.wRepeatCount = 0x7FFF; + Rc = GetKeyboardInput( KbdWaitFlag, + &In, + pMsg, + pReply); + + if ( !Rc ) /* no char & NO_WAIT */ + return(Rc); + } + + if (( HandleKeyboardInput( + &In + )) == NO_ERROR ) + { + *Length = KbdLength; + return(0L); + } + } +} + + +DWORD +HandleKeyboardInput(IN PKEYEVENTINFO pKbd) +{ + DWORD NumChar = 0; + UCHAR Char, Scan, *puchLastString; + USHORT i, usIndex, StringLengthToEcho, NumBeep = 0; + SHORT X_Pos, Offset; + + Scan = pKbd->KeyInfo[0].KeyInfo.chScan; + Char = pKbd->KeyInfo[0].KeyInfo.chChar; + +#if DBG + IF_OD2_DEBUG(KBD) + { + KdPrint(("HandleKeyboardInput: %s - Char %x, Scan %x, Status %x, State %x, Flag %x\n", + (KbdState == CharMode) ? "CharMode" : + (KbdState == AsciiMode) ? "AsciiMode" : "BinaryMode", + Char, Scan, pKbd->KeyInfo[0].KeyInfo.fbStatus, + pKbd->KeyInfo[0].KeyInfo.fsState, pKbd->KeyInfo[0].KeyboardFlag)); + } +#endif + switch (KbdState) + { + case CharMode: + if ( KbdPeekFlag || (pKbd->wRepeatCount > 1)) + { + KbdQueue->LastKey = *pKbd; + KbdQueue->LastKeyFlag = TRUE; + if (!KbdPeekFlag) + { + KbdQueue->LastKey.wRepeatCount--; + } + } + + return (NO_ERROR); + break; + + case AsciiMode: + + KbdQueue->LastKey = *pKbd; // prepare it in case we read only one copy of the char + KbdQueue->LastKey.wRepeatCount--; + + /* + * + * Handle CR (TurnAround Char) + * + * 1. put in buffer (if there is a room), beep otherwise + * 2. echo if echo_on + * 3. (READ only) add LF to CR (if there is a place) + * + */ + + if ( !KbdFxWaitForChar && KbdKeyIsTurnAround(Char, Scan) ) + { + if ( pKbd->wRepeatCount > 1 ) + { + KbdQueue->LastKeyFlag = TRUE; + } + + if (( KbdReadMode == 1 ) && KbdInputLength && + ( LineInputBuff[0].Char == 0x1A )) // ^Z + { + NumChar = KbdInputLength = 0; + } else + { + NumChar = KbdInputLength; + + /* + * Add the TurnAround char at the end of the buffer + */ + + LineInputBuff[KbdInputLength++].Char = Char; + + if (KbdTurnAroundCharTwo) + { + if ( KbdReadMode == 1 ) + { + LineInputBuff[KbdInputLength - 1].Char = '\r'; + Scan = '\n'; + } + LineInputBuff[KbdInputLength++].Char = Scan; + } else if (( KbdReadMode == 1 ) && ( Char == '\r' ) && + ( KbdInputLength <= (USHORT)KbdMaxLength )) + { + LineInputBuff[KbdInputLength++].Char = '\n'; + } + + } + + /* + * Echo the TurnAround char to console + */ + + if (KbdEchoFlag && !KbdTurnAroundCharTwo) + { + KbdEchoNL(1); + } + + /* + * + * Save string length and data in buffer for editing keys + * + */ + + for ( i = 0 ; i < KbdInputLength ; i++ ) + { + KbdLastBuff[i] = LineInputBuff[i].Char; + } + + if (KbdReadMode == 0) + { + KbdInputLength = (USHORT)NumChar; + } + LastStringLength = (USHORT)NumChar; // not include the TurnAround char + + /* + * + * Copy to application buffer + * + */ + + if ( KbdLength > KbdInputLength ) + KbdLength = KbdInputLength; + + RtlMoveMemory(KbdAddress, KbdLastBuff, KbdLength); + + if ( KbdReadMode == 0 ) + KBD_BUFFER_ADDRESS[KbdLength] = Char; // add the CR at the end + + /* + * + * Keep info for Read in case we don't return all the string + * + */ + + KbdBuffNextPtr = KbdLength; + KbdBuffNextLen = KbdInputLength - KbdLength; + + /* + * + * Copy string to CUE buffer if active + * + */ + + if ( SesGrp->KeysOnFlag ) + { + if( KbdLineWasEdited && NumChar ) + { + KbdCurrentLine = KbdNextLinePointer; + + for ( i = 0, usIndex = KbdNextLinePointer ; + i < NumChar ; i++, usIndex++ ) + { + KbdCueBuffer[usIndex] = KbdLastBuff[i]; + } + + KbdNextLinePointer = usIndex + 1; + + while (KbdCueBuffer[usIndex]) + { + // zero the end of the last string we copy the new + // one on (fill with NULL till start of next line) + + KbdCueBuffer[usIndex++] = 0; + } + } + + KbdCueUpRowIsCurrent = TRUE; + } + + return(0L); + } + + /* + * + * Check for Speciel Keys (PFx, enhanced ...) + * + */ + + if (( Char == 0 ) || ( Char == 0xE0 )) + { + if (SesGrp->KeysOnFlag) + { + if ( Scan == OS2_SCAN_RIGHT_6 ) // Right + { + if (( NumChar = KbdInputLength - KbdIndexInLine ) > + pKbd->wRepeatCount ) + { + NumChar = pKbd->wRepeatCount; + } + + KbdCueMoveToRight( + KbdIndexInLine, + (USHORT)NumChar, + FALSE + ); + + } else if ( Scan == OS2_SCAN_LEFT_4 ) // Left + { + NumChar = ( KbdIndexInLine < pKbd->wRepeatCount ) ? + KbdIndexInLine : pKbd->wRepeatCount; + + KbdCueMoveToLeft( + KbdIndexInLine, + (USHORT)NumChar + ); + + } else if ( Scan == OS2_SCAN_UP_8 ) // Up + { + /* + * Find previous command in the command queue + */ + + if (KbdCueBuffer[KbdCurrentLine]) // if anything at the CUE buffer + { + if (KbdCueUpRowIsCurrent) + { + pKbd->wRepeatCount--; + KbdCueUpRowIsCurrent = FALSE; + } + + usIndex = KbdCurrentLine; + for ( i = 0 ; i < pKbd->wRepeatCount ; i++ ) + { + usIndex--; + while (!KbdCueBuffer[--usIndex]); // skip all null + while (KbdCueBuffer[--usIndex]); // go to start of command + + usIndex++; + } + KbdCurrentLine = usIndex; + } else + { + usIndex = KbdCurrentLine; + } + + KbdCueEraseAndDisplayLine(usIndex); + } else if ( Scan == OS2_SCAN_DOWN_2 ) // Down + { + /* + * Find next command in the command queue + */ + + if (KbdCueBuffer[KbdCurrentLine]) // if anything at the CUE buffer + { + usIndex = KbdCurrentLine; + KbdCueUpRowIsCurrent = FALSE; + + for ( i = 0 ; i < pKbd->wRepeatCount ; i++ ) + { + while (KbdCueBuffer[++usIndex]); + while (!KbdCueBuffer[++usIndex]); + } + KbdCurrentLine = usIndex; + } else + { + usIndex = KbdCurrentLine; + } + + KbdCueEraseAndDisplayLine(usIndex); + } else if ( Scan == OS2_SCAN_HOME_7 ) // Home + { + KbdCueMoveToLeft( + KbdIndexInLine, + KbdIndexInLine + ); + } else if ( Scan == OS2_SCAN_END_1 ) // End + { + KbdCueMoveToRight( + KbdIndexInLine, + (USHORT)(KbdInputLength - KbdIndexInLine), + FALSE + ); + + } else if ( Scan == OS2_SCAN_CTRL_LEFT_4 ) // ^Left + { + USHORT PrevIndex = KbdIndexInLine; + + for ( i = 0; + (i < pKbd->wRepeatCount) && PrevIndex ; + i++ ) + { + /* for each char: + * go one char left + * skip all non-alphanumeric chars + * akip all alphanumeric chars + * while points to alpha, which is not the original + */ + + usIndex = PrevIndex - 1; + + while (usIndex && !ALPHANUM_CHAR(usIndex)) + { + usIndex--; + } + + while (usIndex && ALPHANUM_CHAR(usIndex)) + { + usIndex--; + } + + if (usIndex || !ALPHANUM_CHAR(usIndex)) + { + usIndex++; + } + + if (!ALPHANUM_CHAR(usIndex) || + (PrevIndex == usIndex)) + { + break; + } + + PrevIndex = usIndex; + } + if (NumChar = KbdIndexInLine - PrevIndex) + { + KbdCueMoveToLeft( + KbdIndexInLine, + (USHORT)NumChar + ); + } + } else if ( Scan == OS2_SCAN_CTRL_RIGHT_6 ) // ^Right + { + USHORT PrevIndex = KbdIndexInLine; + + for ( i = 0; + (i < pKbd->wRepeatCount) && (PrevIndex < KbdInputLength); + i++ ) + { + /* for each char: + * go one char right + * akip all alphanumeric chars + * skip all non-alphanumeric chars + * while points to alpha, which is not the original + */ + + usIndex = PrevIndex; + + while ((usIndex < KbdInputLength) && + ALPHANUM_CHAR(usIndex)) + { + usIndex++; + } + + while ((usIndex < KbdInputLength) && + !ALPHANUM_CHAR(usIndex)) + { + usIndex++; + } + + if ((usIndex >= KbdInputLength) || + !ALPHANUM_CHAR(usIndex)) + { + break; + } + + PrevIndex = usIndex; + } + if (NumChar = PrevIndex - KbdIndexInLine) + { + KbdCueMoveToRight( + KbdIndexInLine, + (USHORT)NumChar, + FALSE + ); + } + } else if ( Scan == OS2_SCAN_CTRL_END_1 ) // ^End + { + KbdLineWasEdited = TRUE; + KbdEchoBSAndFillSpaces(0, LineInputBuff[KbdInputLength].X_Pos - + LineInputBuff[KbdIndexInLine].X_Pos); + + KbdInputLength = KbdIndexInLine; + } else if ( Scan == OS2_SCAN_DEL ) // Del + { + KbdLineWasEdited = TRUE; + if (( NumChar = KbdInputLength - KbdIndexInLine ) > + pKbd->wRepeatCount ) + { + NumChar = pKbd->wRepeatCount; + } + + KbdCueDeleteCharAndShift( + KbdIndexInLine, + (USHORT)NumChar + ); + } else if ( Scan == OS2_SCAN_CTRL_HOME_7 ) // ^Home + { + if (NumChar = KbdIndexInLine) + { + KbdLineWasEdited = TRUE; + KbdCueMoveToLeft( + KbdIndexInLine, + (USHORT)NumChar + ); + + KbdCueDeleteCharAndShift( + KbdIndexInLine, + (USHORT)NumChar + ); + } + } else if ( Scan == OS2_SCAN_INSERT_0 ) // Ins + { + if ( pKbd->wRepeatCount % 2 ) + { + if( KbdInsertOn = ~KbdInsertOn ) + { + KbdCueSetCurTypeToHalf(); + } else + { + KbdCueSetCurTypeToQuater(); + } + } + } + + break; + } else + { + if ( KbdFxWaitForChar ) + { + KbdFxWaitForChar = 0; + if (--pKbd->wRepeatCount) + { + KbdQueue->LastKey.wRepeatCount--; + KbdQueue->LastKeyFlag = TRUE; + } else + { + break; + } + } + + if ( Scan == 0x40 ) + { + Char = 0x1A; // F6 => ^Z + } else if ( Scan == 0x41 ) + { + Char = 0x00; // F7 => ^@ + } else if (KbdEditFlag) + { + if (( Scan == 0x3B ) || // F1 + ( Scan == OS2_SCAN_RIGHT_6 )) // Right + { + KbdInsertOn = FALSE; + if ((USHORT)(KbdDelIndex + KbdLastBuffPtr) < LastStringLength) + { + Char = KbdLastBuff[KbdDelIndex + KbdLastBuffPtr]; // => previous char + } else + break; + + } else if ( Scan == 0x3C ) // F2 + { + KbdInsertOn = FALSE; + if (pKbd->wRepeatCount % 2) + { + KbdFxWaitForChar = 1; + } + break; + } else if ( Scan == 0x3D ) // F3 + { + KbdInsertOn = FALSE; + if ((USHORT)(KbdDelIndex + KbdLastBuffPtr) < LastStringLength) + { + StringLengthToEcho = LastStringLength - KbdDelIndex - KbdLastBuffPtr; + KbdEchoString = TRUE; + } else + break; + + } else if ( Scan == 0x3E ) // F4 + { + KbdInsertOn = FALSE; + if (pKbd->wRepeatCount % 2) + { + KbdFxWaitForChar = 2; + } + break; + } else if ( Scan == OS2_SCAN_DEL ) // Del + { + KbdDelIndex += pKbd->wRepeatCount; + if(KbdDelIndex > LastStringLength) + { + KbdDelIndex = LastStringLength; + } + break; + } else if ( Scan == OS2_SCAN_INSERT_0 ) // Ins + { + if (pKbd->wRepeatCount % 2) + { + KbdInsertOn = ~KbdInsertOn; + } + + break; + + } else if ( Scan == OS2_SCAN_LEFT_4 ) // Left + { + Char = '\b'; // => BS + KbdInsertOn = FALSE; + } else + break; + } else + break; + } + } + + /* + * + * Search for char in KbdLastBuff (for F2 & F4) + * + */ + + if (KbdFxWaitForChar) + { + if (pKbd->wRepeatCount > 1) + { + KbdQueue->LastKeyFlag = TRUE; + } + for ( i = KbdDelIndex + KbdLastBuffPtr ; + (i < LastStringLength) && (KbdLastBuff[i] != Char) ; i++ ); + if ((i == (USHORT)(KbdDelIndex + KbdLastBuffPtr)) || + (KbdLastBuff[i] != Char)) + { + KbdFxWaitForChar = 0; + break; + } + + StringLengthToEcho = i - (KbdDelIndex + KbdLastBuffPtr); + + if (KbdFxWaitForChar == 1) // F2 + { + KbdFxWaitForChar = 0; + KbdEchoString = TRUE; + } else // F4 + { + KbdDelIndex += i; + KbdFxWaitForChar = 0; + break; + } + } + + /* + * + * Echo string from KbdLastBuff (for F2 & F3) + * + * StringLengthToEcho - is the string length + */ + + if (KbdEchoString) + { + X_Pos = GET_CURRENT_COORD.X; + NumChar = 0; + + for ( i = KbdDelIndex + KbdLastBuffPtr, puchLastString = &KbdLastBuff[i] ; + StringLengthToEcho && (KbdInputLength < (USHORT)KbdMaxLength) ; StringLengthToEcho-- ) + { + Char = KbdLastBuff[i++]; + NumChar++ ; + + LineInputBuff[KbdInputLength++].Char = Char; + if (Char == '\t') // TAB + { + X_Pos += 8 - (X_Pos % 8); + } else if (Char < ' ') + { + X_Pos += 2; + } else + { + X_Pos++; + } + + if (X_Pos >= SesGrp->ScreenColNum) + { + X_Pos -= SesGrp->ScreenColNum; + KbdStartOfLine = 0; + } + + LineInputBuff[KbdInputLength].X_Pos = X_Pos; + } + + if (KbdEchoFlag && NumChar) + { + KbdEchoAString(puchLastString, NumChar); + } + + KbdLastBuffPtr += (USHORT)NumChar; + + if (StringLengthToEcho) + { + KbdEchoBeep(i); + } + + KbdEchoString = FALSE; + break; + } + + /* + * + * Handle BS + * + */ + + if (( Char == '\b' ) || ( Char == 0x7F )) + { + if (SesGrp->KeysOnFlag) + { + if ( NumChar = KbdIndexInLine ) + { + if ( NumChar > pKbd->wRepeatCount ) + { + NumChar = pKbd->wRepeatCount; + } + + KbdCueMoveToLeft( + KbdIndexInLine, + (USHORT)NumChar + ); + + KbdCueDeleteCharAndShift( + KbdIndexInLine, + (USHORT)NumChar + ); + + KbdLineWasEdited = TRUE; + } + + break; + } else + { + KbdInsertOn = FALSE; + + for ( i = 0 ; (i < pKbd->wRepeatCount) && KbdInputLength && + (LineInputBuff[KbdInputLength].X_Pos != KbdStartOfLine) ; i++ ) + { + if (KbdLastBuffPtr) + { + KbdLastBuffPtr--; + } else if (KbdDelIndex) + { + KbdDelIndex--; + } + + KbdInputLength--; + } + + NumChar = GET_CURRENT_COORD.X - LineInputBuff[KbdInputLength].X_Pos; + + if(KbdEchoFlag && NumChar) + { + KbdEchoBSAndFillSpaces(NumChar, NumChar); + } + + break; + } + } + + if (!SesGrp->KeysOnFlag) + { + /* + * + * Handle LF + * + */ + + if (Char == '\n') + { + if (KbdEchoFlag) + { + KbdEchoNL(pKbd->wRepeatCount); + } + + LineInputBuff[KbdInputLength].X_Pos = 0; + KbdStartOfLine = 0; + + break; + } + + /* + * + * Handle ^W + * + */ + + if (Char == 0x17) + { + USHORT PrevIndex = KbdIndexInLine; + + KbdInsertOn = FALSE; + + for ( i = 0; + (i < pKbd->wRepeatCount) && ( PrevIndex > KbdStartOfLine ) ; + i++ ) + { + /* for each char: + * go one char left + * skip all non-alphanumeric chars + * akip all alphanumeric chars + * while points to alpha, which is not the original + */ + + usIndex = PrevIndex - 1; + + while (( usIndex > KbdStartOfLine ) && + !ALPHANUM_CHAR(usIndex)) + { + usIndex--; + } + + while (( usIndex > KbdStartOfLine ) && + ALPHANUM_CHAR(usIndex)) + { + usIndex--; + } + + if (( usIndex > KbdStartOfLine ) || + !ALPHANUM_CHAR(usIndex)) + { + usIndex++; + } + + if (!ALPHANUM_CHAR(usIndex) || + (PrevIndex == usIndex)) + { + break; + } + + PrevIndex = usIndex; + } + + NumChar = LineInputBuff[KbdIndexInLine].X_Pos - + LineInputBuff[PrevIndex].X_Pos ; + + if(KbdEchoFlag && NumChar) + { + KbdEchoBSAndFillSpaces(NumChar, NumChar); + } + + KbdIndexInLine = KbdInputLength = PrevIndex; + //KbdLastBuffPtr = 0; + break; + } + } + + /* + * + * Handle ESC + * + */ + + if (Char == 0x1B) + { + // ^[ => Write '\'<NL> & Clear Buff + + KbdInsertOn = FALSE; + + KbdLastBuffPtr = KbdDelIndex = 0; + if (SesGrp->KeysOnFlag) + { + if (KbdCueBuffer[KbdCurrentLine]) + { + usIndex = KbdCurrentLine - 1; + } else + { + usIndex = KbdCurrentLine; + } + + KbdCueEraseAndDisplayLine(usIndex); // don't display anything + } else if (KbdEchoFlag) + { + KbdEchoESC(pKbd->wRepeatCount, KbdFirstColumn); + } + + KbdStartOfLine = LineInputBuff[0].X_Pos = KbdFirstColumn; + KbdInputLength = 0; + break; + } + + /* + * + * Handle ^F + * + */ + + if (Char == 0x6) + { + break; + } + + /* + * + * Handle char : + * + * 1. put in buffer (if there is a room), beep otherwise + * 2. save in buffer cursor position of next char + * 3. echo if echo_on + * + */ + + NumChar = 0; + + if (SesGrp->KeysOnFlag) + { + KbdCueHandleChar(Char, pKbd->wRepeatCount); + } else + { + X_Pos = GET_CURRENT_COORD.X; + + if (Char < ' ') + { + if (Char == '\t') // TAB + { + Offset = 8; + X_Pos &= ~7; + } else + { + Offset = 2; + } + } else + { + Offset = 1; + } + + for ( i = 0 ; (i < pKbd->wRepeatCount) && + (KbdInputLength < (USHORT)KbdMaxLength) ; i++ ) + { + if (!KbdInsertOn) + { + KbdLastBuffPtr++; + } + + LineInputBuff[KbdInputLength++].Char = Char; + X_Pos += Offset; + + if (X_Pos >= SesGrp->ScreenColNum) + { + X_Pos -= SesGrp->ScreenColNum; + KbdStartOfLine = 0; + } + LineInputBuff[KbdInputLength].X_Pos = X_Pos; + } + + if (KbdEchoFlag && i) + { + KbdEchoChar(Char, i); + } + + if (i < pKbd->wRepeatCount) + { + KbdEchoBeep(pKbd->wRepeatCount - i); + } + } + break; + + case BinaryMode: + /* + * + * Binary mode + * + */ + + /* + * + * Handle char : + * + * put in buffer (if a place exist) + * if enhanced - put also scan code + * + */ + + for ( i = 0 ; (i < pKbd->wRepeatCount) && (KbdInputLength < KbdLength); i++ ) + { + KBD_BUFFER_ADDRESS[KbdInputLength++] = Char; + + if ((Char == 0x0) && (KbdInputLength < KbdLength)) + { + KBD_BUFFER_ADDRESS[KbdInputLength++] = Scan; + } + } + + if ( KbdInputLength < KbdLength ) + { + break; + } else if ( i < pKbd->wRepeatCount ) + { + KbdQueue->LastKey = *pKbd; // prepare it in case we read only one copy of the char + KbdQueue->LastKey.wRepeatCount -= i; + KbdQueue->LastKeyFlag = TRUE; + } + + /* + * + * Copy to application buffer + * + */ + + if ( KbdLength > KbdInputLength ) + KbdLength = KbdInputLength; + + /* + * + * Keep info for Read in case we don't return all the string + * + */ + + KbdBuffNextPtr = KbdLength; + KbdBuffNextLen = KbdInputLength - KbdLength; + + /* + * + * No editing keys in binary mode + * + */ + + LastStringLength = 0; + + return(0L); + + default: + break; + } + +#if DBG + IF_OD2_DEBUG( KBD ) + { + if ( KbdState == AsciiMode ) + { + USHORT CurrentIdx; + CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; + + CurrentIdx = (SesGrp->KeysOnFlag) ? KbdIndexInLine : KbdInputLength; + + if (!GetConsoleScreenBufferInfo( + hConOut, + &ConsoleScreenBufferInfo + )) + { + ConsoleScreenBufferInfo.dwCursorPosition.X = + ConsoleScreenBufferInfo.dwCursorPosition.Y = 255; + KdPrint(("OS2SES(Ow2VioReadCurPos): Rc %lu\n", GetLastError())); + ASSERT( FALSE ); // should not happend + } + KdPrint(("HandleKeyboardInput: Len %u, CUE-Idx %u, Cur-Offset %u, Prev-Offset %u, Col %u, Pos %u:%u\n", + KbdInputLength, KbdIndexInLine, + LineInputBuff[CurrentIdx].X_Pos, + (CurrentIdx) ? LineInputBuff[CurrentIdx - 1].X_Pos : 255, + SesGrp->WinCoord.X, + ConsoleScreenBufferInfo.dwCursorPosition.Y, + ConsoleScreenBufferInfo.dwCursorPosition.X + )); + if (KbdEchoFlag) + { + ASSERT( ConsoleScreenBufferInfo.dwCursorPosition.X == SesGrp->WinCoord.X ); + ASSERT( ConsoleScreenBufferInfo.dwCursorPosition.Y == SesGrp->WinCoord.Y ); + ASSERT( (LineInputBuff[CurrentIdx].X_Pos % SesGrp->ScreenColNum) == + SesGrp->WinCoord.X ); + } + } + } +#endif + + return(1L); +} + + +DWORD +KbdHandlePackage(IN PKEY_EVENT_QUEUE NextKbdMon, + IN PKBD_MON_PACKAGE KbdPackage) +{ + KEYEVENTINFO In; + + if ( KbdCheckPackage( KbdPackage )) + { + return (0L); // ignore key + } + +#ifdef DBCS +// MSKK Jul.23.1992 KazuM + In.wRepeatCount = NextKbdMon->In->wRepeatCount; +#else + In.wRepeatCount = 1; +#endif + In.KeyInfo[0] = *KbdPackage; + + if ( HandleKeyboardInput( &In )) + { + return (0L); // not time to send reply yet + } + + NextKbdMon->MonHdr.WaitForEvent = FALSE; + +#if DBG + IF_OD2_DEBUG( KBD ) + { + KdPrint(("KbdHandlePackage: %s respond\n", + (KbdRequestSaveArea.Request == KBDCharIn) ? "KbdCharIn" : + (KbdRequestSaveArea.Request == KBDStringIn) ? "KbdStringIn" : + "KbdRead")); + } +#endif + if ( KbdRequestSaveArea.Request == KBDCharIn ) + { + KbdRequestSaveArea.d.KeyInfo = In.KeyInfo[0].KeyInfo; + + SendKbdReply((PVOID)NextKbdMon->MonHdr.MemoryStartAddress, + (PVOID)&KbdRequestSaveArea, + KbdAddress, + 0); + } else + { + KbdRequestSaveArea.Length = (ULONG)KbdLength; + + if ( KbdRequestSaveArea.Request == KBDStringIn ) + { + KbdRequestSaveArea.d.String.cchIn = KbdLength; + if ( KbdRequestSaveArea.d.String.cchIn != KbdRequestSaveArea.d.String.cb ) + KbdRequestSaveArea.Length++ ; // ASCII mode - copy the CR + } + + SendKbdReply ((PVOID)NextKbdMon->MonHdr.MemoryStartAddress, + (PVOID)&KbdRequestSaveArea, + KbdAddress, + 0); + } + + return (1L); +} + + +DWORD +KbdCheckPackage(IN PKBD_MON_PACKAGE KbdPackage) +{ + BOOL IgnoreKey = FALSE; + UCHAR Scan, Char; + + Char = KbdPackage->KeyInfo.chChar; + Scan = KbdPackage->KeyInfo.chScan; + + if (( Char == 0 ) && ( Scan == 0 )) + { + if(!( ENABLE_SHIFT_KEY & KbdWaitFlag )) + { + /* + * Ignore shift keys if { in ASCII mode or shift report off } + */ +#if DBG + IF_OD2_DEBUG(KBD) + { + KdPrint((" - ignore since shift report disable\n")); + } +#endif + IgnoreKey = TRUE; // ignore shift report + } else if(!( KbdPackage->KeyInfo.fbStatus & 1)) + { + /* + * Ignore non-shift keys + */ +#if DBG + IF_OD2_DEBUG(KBD) + { + KdPrint((" - ignore since non-shift key\n")); + } +#endif + IgnoreKey = TRUE; + } + } else if ( KbdPackage->KeyboardFlag & KBD_KEY_BREAK ) + { + /* + * Ignore Break if non-shift + */ + +#if DBG + IF_OD2_DEBUG( KBD ) + { + KdPrint(("KbdCheckPackage: ignore key release\n")); + } +#endif + IgnoreKey = TRUE; // ignore KEY_UP + } else if (( KbdWaitFlag & ENABLE_LN_EDITOR_KEY ) && + KbdKeyIsTurnAround(Char, Scan) ) + { + // don't ignore the turn around char in ASCII mode + + } else if ( !( KbdWaitFlag & ENABLE_NON_ASCII_KEY ) && + (( Char == 0 ) || ( Char == 0xE0 ))) + { + IgnoreKey = TRUE; // ignore NON_ASCII + + if ( KbdWaitFlag & ENABLE_KEYS_ON_KEY ) + { + if (( Scan == OS2_SCAN_HOME_7 ) || // Home + ( Scan == OS2_SCAN_CTRL_HOME_7 ) || // ^Home + ( Scan == OS2_SCAN_END_1 ) || // End + ( Scan == OS2_SCAN_CTRL_END_1 ) || // ^End + ( Scan == OS2_SCAN_LEFT_4 ) || // Left + ( Scan == OS2_SCAN_CTRL_LEFT_4 ) || // ^Left + ( Scan == OS2_SCAN_RIGHT_6 ) || // Right + ( Scan == OS2_SCAN_CTRL_RIGHT_6 ) || // ^Right + ( Scan == OS2_SCAN_UP_8 ) || // Up + ( Scan == OS2_SCAN_DOWN_2 ) || // Down + ( Scan == OS2_SCAN_DEL ) || // Del + ( Scan == OS2_SCAN_INSERT_0 )) // Ins + { + IgnoreKey = FALSE; // don't ignore CUE keys + } + } else if ( KbdWaitFlag & ENABLE_LN_EDITOR_KEY ) + { + if (( Scan == 0x3B ) || // F1 + ( Scan == 0x3C ) || // F2 + ( Scan == 0x3D ) || // F3 + ( Scan == 0x3E ) || // F4 + ( Scan == 0x40 ) || // F6 + ( Scan == 0x41 ) || // F7 + ( Scan == OS2_SCAN_LEFT_4 ) || // Left + ( Scan == OS2_SCAN_RIGHT_6 ) || // Right + ( Scan == OS2_SCAN_DEL ) || // Del + ( Scan == OS2_SCAN_INSERT_0 )) // Ins + { + IgnoreKey = FALSE; // don't ignore editing keys + } + } + + if (IgnoreKey) + { +#if DBG + IF_OD2_DEBUG( KBD ) + { + KdPrint(("KbdCheckPackage: ignore non-ASCII key\n")); + } +#endif + } + } else if ( KbdAsciiMode ) + { + /* + * + * Ignore speciel CTRL-Keys in ASCII mode + * + */ + + if (( Char == 0x03 ) || // ^C + ( Char == 0x10 ) || // ^P + // ^Q: in non-US kbd(AZARTY) ^Q is passed + // and ^A not (mjarus 7/5/93) + (( Scan == 0x10 ) && + ((KbdPackage->KeyInfo.fsState & (OS2_CONTROL | OS2_ALT)) == OS2_CONTROL)) || + ( Char == 0x13 )) // ^S + { +#if DBG + IF_OD2_DEBUG(KBD) + { + KdPrint((" - ignore Char %x in ASCII\n", + Char)); + } +#endif + IgnoreKey = TRUE; // ignore NON_ASCII + } + } + + return ( (DWORD)IgnoreKey ); +} + + +VOID +KbdNewSetup( + IN PKBDINFO LastSetup + ) +{ + PKBDINFO NewSetup = &KbdQueue->Setup; + USHORT Mask; + +// if (*LastSetup == *NewSetup) +// return; + + /* BUGBUG=> handle new setup */ + + SesGrp->ModeFlag = (USHORT)((NewSetup->fsMask & KEYBOARD_BINARY_MODE ) ? 1 : 0); + + Mask = NewSetup->fsMask & (KEYBOARD_BINARY_MODE | KEYBOARD_SHIFT_REPORT); + + Ow2KbdXlateVars.XInputMode = (Mask) ? + ((Mask & KEYBOARD_SHIFT_REPORT) ? (BINARY_MODE | SHIFT_REPORT_MODE) : + BINARY_MODE) : 0; + + if ((NewSetup->fsMask & KEYBOARD_ASCII_MODE ) && + (LastSetup->fsMask & KEYBOARD_BINARY_MODE )) + { + LastStringLength = 0; + KbdBuffNextPtr = 0; + KbdBuffNextLen = 0; + } + + KbdAsciiMode = (BOOL)(( NewSetup->fsMask & KEYBOARD_ASCII_MODE ) ? 1 : 0); + + if (NewSetup->fsMask & KEYBOARD_2B_TURNAROUND) + { + KbdSetupTurnAroundCharTwo = (BOOLEAN)TRUE; + } else + { + KbdSetupTurnAroundCharTwo = (BOOLEAN)FALSE; + } + + return; +} + + +VOID +KbdCueEraseAndDisplayLine( + IN ULONG NewLineIndex + ) +/*++ + +Routine Description: + + This routine erase the current input line and display new one. + +Arguments: + + NewLineIndex - pointer in CUE buffer for new line (or to NULL + if nothing to diaply). + +Return Value: + + +Note: + + ASCII CUE string mode. + + Used by UP-ARROW, DOWN-ARROW and ESC. + + 1. Erase the active command line being displayed and + 2. Display the new command in the command queue. + + Uses: + + - KbdInputLength - active command line length. + - KbdIndexInLine - current index in command line. + - LineInputBuff[0, KbdIndexInLine, KbdInputLength].X_Pos + - KbdCueBuffer[NewLineIndex..] + + Updates: + + - KbdInputLength - new line length. + - KbdIndexInLine - 0. + - LineInputBuff[0..KbdInputLength].Char and .X_Pos + - console display + - LVB + - SesGrp->WinCoord - by other routines. + + Calls: + + - KbdEchoBSAndFillSpaces + - KbdCueUpdateBufferOffset + - KbdCueMoveToRight + - KbdCueMoveToLeft + +--*/ +{ + /* + * Erase the active command line being displayed. + */ + + if ( KbdInputLength ) + { + KbdEchoBSAndFillSpaces( + LineInputBuff[KbdIndexInLine].X_Pos - LineInputBuff[0].X_Pos, + LineInputBuff[KbdInputLength].X_Pos - LineInputBuff[0].X_Pos + ); + + KbdIndexInLine = 0; + KbdInputLength = 0; + } + + /* + * Display the new command in the command queue + */ + + for ( KbdInputLength = 0 ; + LineInputBuff[KbdInputLength].Char = KbdCueBuffer[NewLineIndex + KbdInputLength] ; + KbdInputLength++ ); + + if (KbdInputLength) + { + KbdCueUpdateBufferOffset( + 0, + KbdInputLength, + LineInputBuff[0].X_Pos + ); + + KbdCueMoveToRight( + 0, + KbdInputLength, + TRUE + ); + + KbdCueMoveToLeft( + KbdInputLength, + KbdInputLength + ); + } +} + + +VOID +KbdCueMoveToRight( + IN ULONG StartIndex, + IN ULONG StringLength, + IN ULONG UpdateLVB + ) +/*++ + +Routine Description: + + This routine moves the console cursor position to the right + while sending the active command line to the console. + +Arguments: + + StartIndex - index in LineInputBuff[] (the active command line) to start + moving right from. + + StringLength - number of character to move right. + + UpdateLVB - flag if to set LVB also (for new info) + +Return Value: + + +Note: + + ASCII CUE string mode. + + Used by RIGHT-ARROW, END, ^RIGHT-ARROW, KbdCueEraseAndDisplayLine, + KbdCueDeleteCharAndShift and KbdCueHandleChar. + + 1. Send to console + 2. Update Coord + 3. Update LVB + 4. Update position + + Uses: + + - LineInputBuff[0..KbdInputLength].Char and .X_Pos + + Updates: + + - KbdInputLength - NO. + - KbdIndexInLine - add StringLength. + - LineInputBuff[0..KbdInputLength].Char and .X_Pos - NO + - console display + - LVB (if UpdateLVB) + - SesGrp->WinCoord - add StringLength. + + Calls: + + - Or2WinWriteConsoleA + - Ow2VioUpdateCurPos + - VioLVBScrollBuff + - VioLVBCopyStr + +--*/ +{ + UCHAR Char; + ULONG NumChar, NumBytes, NumWritten, NumLines = 0; + COORD OldCoord, Coord; + + OldCoord = Coord = GET_CURRENT_COORD; + + /* + * Copy to temp buffer + */ + + for ( NumBytes = 0, NumChar = 0 ; NumChar < StringLength ; NumChar++ ) + { + if ((Char = LineInputBuff[StartIndex + NumChar].Char) < ' ') + { + KBD_BUFFER_ADDRESS[NumBytes++] = '^'; + KBD_BUFFER_ADDRESS[NumBytes++] = (UCHAR)(Char + '@'); + } else + { + KBD_BUFFER_ADDRESS[NumBytes++] = Char; + } + } + + if (!NumBytes) + { + return ; + } + + if ( KbdEchoFlag ) + { + /* + * Send to console + */ + + if(!Or2WinWriteConsoleA( + #if DBG + KbdCueMoveToRightStr, + #endif + hConOut, + (LPSTR)KBD_BUFFER_ADDRESS, + NumBytes, + &NumWritten, + NULL + )) + { +#if DBG + ASSERT1("OS2SES(KbdCueMoveToRight): failed on WriteConsoleA", FALSE); +#endif + } + +#if DBG + if ( NumBytes != NumWritten ) + { + KdPrint(("OS2SES(KbdCueMoveToRight): partial data WriteConsoleA (%u from %u)\n", + NumWritten, NumBytes)); + ASSERT( FALSE ); + } +#endif + + /* + * Update Coord + */ + + Coord.X += (SHORT)NumWritten; + while ( Coord.X >= SesGrp->ScreenColNum ) + { + Coord.Y++; + Coord.X -= SesGrp->ScreenColNum; + } + + if ( Coord.Y >= SesGrp->ScreenRowNum ) + { + NumLines = Coord.Y - SesGrp->ScreenRowNum + 1; + Coord.Y = SesGrp->ScreenRowNum - 1; + } + + Ow2VioUpdateCurPos(Coord); + + /* + * Update LVB + */ + + if ( UpdateLVB ) + { + if ( NumLines && ( SesGrp->ScreenSize < 512 )) + { + ULONG NumChar1 = SesGrp->ScreenRowNum - OldCoord.X; + UCHAR *Ptr = &KBD_BUFFER_ADDRESS[0]; + + while ( NumWritten ) + { + VioLVBCopyStr( + Ptr, + OldCoord, + NumChar1 + ); + + VioLVBFillAtt( + SesGrp->AnsiCellAttr, + OldCoord, + NumChar1 + ); + + OldCoord.X = 0; + + if ( ++OldCoord.Y >= SesGrp->ScreenRowNum ) + { + OldCoord.Y--; + VioLVBScrollBuff(1); + NumLines--; + } + + NumWritten -= NumChar1; + + if (( NumChar1 = NumWritten ) > (ULONG)SesGrp->ScreenColNum ) + { + NumChar1 = SesGrp->ScreenColNum; + } + } + + ASSERT( NumLines == 0 ); + } else + { + if ( NumLines ) + { + OldCoord.Y -= (SHORT)NumLines; + VioLVBScrollBuff(NumLines); + } + + VioLVBCopyStr( + KBD_BUFFER_ADDRESS, + OldCoord, + NumWritten + ); + + VioLVBFillAtt( + SesGrp->AnsiCellAttr, + OldCoord, + NumWritten + ); + } + } + } + + /* + * Update position index + */ + + KbdIndexInLine += (USHORT)StringLength; +} + + +VOID +KbdCueMoveToLeft( + IN ULONG StartIndex, + IN ULONG MoveLength + ) +/*++ + +Routine Description: + + This routine moves the console cursor position to the left + using '\b'. + +Arguments: + + StartIndex - index in LineInputBuff[] (the active command line) to start + moving left from. + + MoveLength - number of character to move left. + +Return Value: + + +Note: + + ASCII CUE string mode. + + Used by LEFT-ARROW, HOME, ^LEFT-ARROW, ^HOME, BS, KbdCueEraseAndDisplayLine, + KbdCueDeleteCharAndShift and KbdCueHandleChar. + + 1. Send to console + 2. Update position + + Uses: + + - LineInputBuff[StartIndex - MoveLength,StartIndex].X_Pos + - LineInputBuff[StartIndex - MoveLength..StartIndex].Char + + Updates: + + - KbdInputLength - NO. + - KbdIndexInLine - sub MoveLength. + - LineInputBuff[0..KbdInputLength].Char and .X_Pos - NO + - console display - NO + - LVB - NO + - SesGrp->WinCoord - by other routines. + + Calls: + + - KbdEchoBSAndFillSpaces + +--*/ +{ + ULONG NumBytes; + + /* + * Calculate byte count + */ + + NumBytes = LineInputBuff[StartIndex].X_Pos - LineInputBuff[StartIndex - MoveLength].X_Pos; + + if (!NumBytes) + { + return ; + } + + if ( KbdEchoFlag ) + { + if ( SesGrp->ScreenSize < 512 ) + { + ULONG Row1, Row2; + + Row1 = LineInputBuff[StartIndex - MoveLength].X_Pos / SesGrp->ScreenColNum; + Row2 = LineInputBuff[KbdInputLength].X_Pos / SesGrp->ScreenColNum; + + if (( Row2 - Row1 + 1 ) > (ULONG)SesGrp->ScreenRowNum ) + { + NumBytes += LineInputBuff[StartIndex - MoveLength].X_Pos % SesGrp->ScreenColNum; + NumBytes -= (Row2 - Row1 + 1 - SesGrp->ScreenRowNum) * SesGrp->ScreenColNum; + } + } + + /* + * Send to console and update coord + */ + + KbdEchoBSAndFillSpaces(NumBytes, 0); + } + + /* + * Update position index + */ + + KbdIndexInLine -= (USHORT)MoveLength; +} + + +VOID +KbdCueUpdateBufferOffset( + IN ULONG StartIndex, + IN ULONG StringLength, + IN ULONG StartOffset + ) +/*++ + +Routine Description: + + This routine updates the offset in buffer for the active command line. + This is done from StartIndex for StringLength + 1 (to update the offset + of the next char according to the last char in string). The StartIndex + gets X_Pos of StartOffset and the following are updated according the + char type (char under 0x20 holds two columns for ^X). + +Arguments: + + StartIndex - index in LineInputBuff[] (the active command line) to start + updaing the X_Pos field from. + + StringLength - number of character to update X_Pos for. + + StartOffset - X_Pos for the first character. + +Return Value: + + +Note: + + ASCII CUE string mode. + + Used by KbdCueEraseAndDisplayLine, KbdCueDeleteCharAndShift and + KbdCueHandleChar. + + 1. Updates the X_Pos field in LineInputBuff[]. + + Uses: + + - KbdInputLength - active command line length. + - KbdIndexInLine - current index in command line. + - LineInputBuff[0, KbdIndexInLine, KbdInputLength].X_Pos + - KbdCueBuffer[NewLineIndex..] + +--*/ +{ + ULONG NumChar, Index, Offset; + + /* + * Update the offset in buffer. This is done for StringLength + 1 + * to update the offset of the next char according to the last char + * in string. + */ + + for ( Index = StartIndex, Offset = StartOffset, NumChar = 0 ; + NumChar <= StringLength ; NumChar++ ) + { + LineInputBuff[Index].X_Pos = (USHORT)Offset++; + + if ( LineInputBuff[Index++].Char < ' ' ) + { + Offset++; + } + } +} + + +VOID +KbdCueDeleteCharAndShift( + IN ULONG StartIndex, + IN ULONG NumChar + ) +/*++ + +Routine Description: + + This routine delete character and shift the remaining command line + input to the left. + +Arguments: + + StartIndex - index in LineInputBuff[] (the active command line) to start + deleting from. + + NumChar - number of character to delete. + +Return Value: + + +Note: + + ASCII CUE string mode. + + Used by DEL, ^HOME and BS. + + 1 Shift buffer info (Char field) + 2 Update X_Pos (Offset) field in the shifted area + 3 Send the shifted string to console and LVB + 4 Clear remaining line + 5 Return to the cursor position + + Uses: + + - LineInputBuff[].X_Pos and Char + + Updates: + + - KbdInputLength - sub NumChar. + - KbdIndexInLine - NO + - LineInputBuff[0..KbdInputLength].Char and .X_Pos + - console display + - LVB + - SesGrp->WinCoord - by other routines. + + Calls: + + - KbdCueUpdateBufferOffset + - KbdCueMoveToRight + - KbdEchoBSAndFillSpaces + - KbdCueMoveToLeft + +--*/ +{ + if (NumChar) + { + ULONG Offset = LineInputBuff[StartIndex].X_Pos; + ULONG Delta = LineInputBuff[StartIndex + NumChar].X_Pos - Offset; + ULONG NumShift = KbdInputLength - StartIndex - NumChar; + + if ( NumShift ) + { + /* + * Shift buffer info (Char field) + */ + + RtlMoveMemory( + &LineInputBuff[StartIndex].Char, + &LineInputBuff[StartIndex + NumChar].Char, + NumShift * sizeof(LINE_EDIT_KBD) + ); + + /* + * Update X_Pos (Offset) field in the shifted area + */ + + KbdCueUpdateBufferOffset( + StartIndex, + NumShift, + Offset + ); + + /* + * Send the shifted string to console and LVB + */ + + KbdCueMoveToRight( + StartIndex, + NumShift, + TRUE + ); + } + + /* + * Clear remaining line + */ + + KbdEchoBSAndFillSpaces(0, Delta); + + /* + * Return to the cursor position + */ + + KbdCueMoveToLeft( + StartIndex + NumShift, + NumShift + ); + + KbdInputLength -= (USHORT)NumChar; + } +} + + +VOID +KbdCueHandleChar( + IN UCHAR Char, + IN ULONG Count + ) +/*++ + +Routine Description: + + This routine handle new char at CUE mode. + +Arguments: + + Char - char to handle. + + NumChar - number of character. + +Return Value: + + +Note: + + ASCII CUE string mode. + + Used by CHAR. + + For INSERT: + 1 Shift buffer info (Char field) + 2 Fill new char + 3 Update X_Pos (Offset) field + 4 Send the new+old string to console and LVB + 5 Return to the cursor position + 6 Beep if no place + Else: + 1 Shift buffer info (Char field) + 2 Fill new char + 3 Update X_Pos (Offset) field + 4 Send the shifted string to console and LVB + 5 Clear remaining line + 6 Return to the cursor position + 7 Beep if no place + + Uses: + + - LineInputBuff[].X_Pos and Char + - KbdInsertOn + - KbdIndexInLine + - KbdMaxLength + - KbdInputLength + + Updates: + + - KbdInputLength + - KbdIndexInLine + - LineInputBuff[0..KbdInputLength].Char and .X_Pos + - console display + - LVB + - SesGrp->WinCoord - by other routines. + + Calls: + + - KbdCueUpdateBufferOffset + - KbdCueMoveToRight + - KbdCueMoveToLeft + - KbdEchoBSAndFillSpaces + - KbdEchoBeep + - RtlMoveMemory + +--*/ +{ + ULONG NumChar, NumBeep = 0, NumShift, UpdateRight, i; + ULONG LastOffset = LineInputBuff[KbdInputLength].X_Pos; + + if ( KbdInsertOn ) + { + if (( NumChar = KbdMaxLength - KbdInputLength ) > Count ) + { + NumChar = Count; + } else + { + NumBeep = Count - NumChar; + } + + /* + * Shift buffer info (Char field) to free space for new char + */ + + NumShift = KbdInputLength - KbdIndexInLine; + + RtlMoveMemory( + &LineInputBuff[KbdIndexInLine + NumChar].Char, + &LineInputBuff[KbdIndexInLine].Char, + NumShift * sizeof(LINE_EDIT_KBD) + ); + /* + * Fill new char + */ + + for ( i = 0 ; i < NumChar ; i++ ) + { + LineInputBuff[KbdIndexInLine + i].Char = Char; + } + + /* + * Update X_Pos (Offset) field in the shifted and new areas + */ + + KbdCueUpdateBufferOffset( + KbdIndexInLine, + NumChar + NumShift, + LineInputBuff[KbdIndexInLine].X_Pos + ); + + /* + * Send the shifted string to console and LVB + */ + + KbdCueMoveToRight( + KbdIndexInLine, + NumChar + NumShift, + TRUE + ); + + /* + * Return to the cursor position + */ + + KbdCueMoveToLeft( + KbdIndexInLine, + NumShift + ); + + KbdInputLength += (USHORT)NumChar; + } else + { + if (( NumChar = KbdMaxLength - KbdIndexInLine ) > Count ) + { + NumChar = Count; + } else + { + NumBeep = Count - NumChar; + } + + UpdateRight = max(NumChar, (ULONG)(KbdInputLength - KbdIndexInLine)); + + /* + * Fill new char + */ + + for ( i = 0 ; i < NumChar ; i++ ) + { + LineInputBuff[KbdIndexInLine + i].Char = Char; + } + + /* + * Update X_Pos (Offset) field in the old and new areas + */ + + KbdCueUpdateBufferOffset( + KbdIndexInLine, + UpdateRight, + LineInputBuff[KbdIndexInLine].X_Pos + ); + + /* + * Send the shifted string to console and LVB + */ + + KbdCueMoveToRight( + KbdIndexInLine, + UpdateRight, + TRUE + ); + + if ( LastOffset > (ULONG)LineInputBuff[KbdIndexInLine].X_Pos ) + { + /* + * Fill spaces at the EOL if needed + */ + + KbdEchoBSAndFillSpaces( + 0, + LastOffset - LineInputBuff[KbdIndexInLine].X_Pos + ); + } + + if ( UpdateRight != NumChar ) + { + /* + * Return to the cursor position + */ + + KbdCueMoveToLeft( + KbdIndexInLine, + UpdateRight - NumChar + ); + } + + if ( KbdIndexInLine > KbdInputLength ) + { + KbdInputLength = KbdIndexInLine; + } + } + + if ( NumBeep != Count ) + { + KbdLineWasEdited = TRUE; + } + + if ( NumBeep ) + { + KbdEchoBeep(NumBeep); + } +} + + +VOID +KbdCueSetCurTypeToHalf() +{ + VIOCURSORINFO CurType; + + //Ow2VioGetCurType((PVOID)&CurType); + //CurType = SesGrp->CursorInfo; + + //CurType.cEnd = SesGrp->CellVSize; + CurType.cEnd = SesGrp->CursorInfo.cEnd; + CurType.yStart = (CurType.cEnd + 1 ) / 2; + CurType.cx = 1; + CurType.attr = 0; + + Ow2VioSetCurType((PVOID)&CurType); +} + + +VOID +KbdCueSetCurTypeToQuater() +{ + VIOCURSORINFO CurType; + + //Ow2VioGetCurType((PVOID)&CurType); + //CurType = SesGrp->CursorInfo; + + //CurType.cEnd = SesGrp->CellVSize; + CurType.cEnd = SesGrp->CursorInfo.cEnd; + CurType.yStart = (CurType.cEnd + 1 ) * 3 / 4; + CurType.cx = 1; + CurType.attr = 0; + + Ow2VioSetCurType((PVOID)&CurType); +} + + +DWORD +KbdEchoCharToConsole( + IN UCHAR Char, + IN ULONG Count + ) +/*++ + +Routine Description: + + This routine write <Char> to console <Count> times. + +Arguments: + + Char - character to write. + + Count - number of times to write char + +Return Value: + + +Note: + + ASCII CUE/EDIT string mode. + + Used by KbdEchoNL, KbdEchoBSAndFillSpaces, KbdEchoBeep and KbdEchoChar. + + Calls: + + - Or2WinWriteConsoleA + +--*/ +{ + ULONG NumChar, NumWritten, MaxCount = Count; + + NumChar = (MaxCount > KBD_BUFFER_SIZE) ? KBD_BUFFER_SIZE : MaxCount; + memset(KBD_BUFFER_ADDRESS, Char, NumChar); + + while (MaxCount) + { + if(!Or2WinWriteConsoleA( + #if DBG + KbdEchoCharToConsoleStr, + #endif + hConOut, + (LPSTR)KBD_BUFFER_ADDRESS, + NumChar, + &NumWritten, + NULL)) + { +#if DBG + ASSERT1("OS2SES(KbdEchoCharToConsole): failed on WriteConsoleA", FALSE); +#endif + } + +#if DBG + if ( NumChar != NumWritten ) + { + KdPrint(("OS2SES(KbdEchoCharToConsole): partial data WriteConsoleA %u from %u\n", + NumWritten, NumChar)); + ASSERT( FALSE ); + } +#endif + + MaxCount -= NumChar; + NumChar = (MaxCount > KBD_BUFFER_SIZE) ? KBD_BUFFER_SIZE : MaxCount; + } + + return(NO_ERROR); +} + + +DWORD +KbdEchoNL( + IN ULONG Count + ) +/*++ + +Routine Description: + + This routine write NL to console <Count> times and update LVB. + +Arguments: + + Count - number of times to write char + +Return Value: + + +Note: + + ASCII CUE/EDIT string mode. + + Used by LF (EDIT only) and CR. + + Updates: + + - SesGrp->WinCoord + - LVB + + Calls: + + - KbdEchoCharToConsole + - VioLVBScrollBuff + +--*/ +{ + ULONG NumLines = 0; + COORD Coord = GET_CURRENT_COORD; + + Coord.X = 0; + Coord.Y += (SHORT)Count; + if ( Coord.Y >= SesGrp->ScreenRowNum ) + { + NumLines = Coord.Y - SesGrp->ScreenRowNum + 1; + Coord.Y = SesGrp->ScreenRowNum - 1; + } + + KbdEchoCharToConsole('\n', Count); + Ow2VioUpdateCurPos(Coord); + + if (NumLines) + { + VioLVBScrollBuff(NumLines); + } + + return(NO_ERROR); +} + + +DWORD +KbdEchoESC( + IN ULONG Count, + IN ULONG HorzMove + ) +/*++ + +Routine Description: + + This routine write <ESC> to console <Count> times with <HorzMove> + number of spaces on the next line. It also update LVB. + +Arguments: + + Count - number of times to write char + + HorzMove - number of spaces on the start of the new line. + +Return Value: + + +Note: + + ASCII EDIT string mode. + + Used by ESC. + + Updates: + + - SesGrp->WinCoord + - LVB + + Calls: + + - Or2WinWriteConsoleA + - VioLVBScrollBuff + +--*/ +{ + ULONG NumChar, NumWritten, MaxCount = Count, NumLines = 0, Length = HorzMove + 1; + COORD OldCoord, Coord; + + OldCoord = Coord = GET_CURRENT_COORD; + + KBD_BUFFER_ADDRESS[0] = '\\'; + KBD_BUFFER_ADDRESS[1] = '\n'; + memset(&KBD_BUFFER_ADDRESS[2], ' ', HorzMove); + KBD_BUFFER_ADDRESS[HorzMove + 2] = '\\'; + NumChar = HorzMove + 2; + + Coord.Y += (SHORT)Count; + Coord.X = (SHORT)HorzMove; + + if ( Coord.Y >= SesGrp->ScreenRowNum ) + { + NumLines = Coord.Y - SesGrp->ScreenRowNum + 1; + Coord.Y = SesGrp->ScreenRowNum - 1; + } + + while ( MaxCount ) + { + if(!Or2WinWriteConsoleA( + #if DBG + KbdEchoESCStr, + #endif + hConOut, + (LPSTR)KBD_BUFFER_ADDRESS, + NumChar, + &NumWritten, + NULL)) + { +#if DBG + ASSERT1("OS2SES(KbdEchoESC): failed on WriteConsoleA", FALSE); +#endif + //return (1); + } + +#if DBG + if ( NumChar != NumWritten ) + { + KdPrint(("OS2SES(KbdEchoESC): partial data WriteConsoleA %u from %u\n", + NumWritten, NumChar)); + ASSERT( FALSE ); + } +#endif + + MaxCount--; + } + + Ow2VioUpdateCurPos(Coord); + + VioLVBFillChar( +#ifdef DBCS +// MSKK Oct.14.1993 V-AkihiS + "\\", +#else + '\\', +#endif + OldCoord, + 1 + ); + + VioLVBFillAtt( + SesGrp->AnsiCellAttr, + OldCoord, + 1 + ); + + OldCoord.X = 0; + + for ( NumChar = 0 ; NumChar < Count ; NumChar++ ) + { + if ( ++OldCoord.Y >= SesGrp->ScreenRowNum ) + { + OldCoord.Y--; + VioLVBScrollBuff(1); + NumLines--; + } + + if ( NumChar == ( Count - 1 )) + { + Length--; // don't put the slash at the last line + } + + VioLVBCopyStr( + &KBD_BUFFER_ADDRESS[2], + OldCoord, + Length + ); + + VioLVBFillAtt( + SesGrp->AnsiCellAttr, + OldCoord, + Length + ); + } + + ASSERT( NumLines == 0 ); + return(NO_ERROR); +} + + +DWORD +KbdEchoBSAndFillSpaces( + IN ULONG BSCount, + IN ULONG SpaceCount + ) +/*++ + +Routine Description: + + This routine write BS ('\b') to console <BSCount> times and fill + <SpaceCount> times spaces in console and LVB. + +Arguments: + + BSCount - number of times to write \b char to console + + SpaceCount - number of times to fill space char to console and LVB + +Return Value: + + +Note: + + ASCII EDIT/CUE string mode. + + Used by ^END, BS (EDIT only), LF (EDIT only), KbdCueEraseAndDisplayLine, + KbdCueMoveToLeft, KbdCueDeleteCharAndShift and KbdCueHandleChar. + + Updates: + + - SesGrp->WinCoord (for BSCount only) + - LVB (for SpaceCount only) + + Calls: + + - KbdEchoCharToConsole + - Or2WinFillConsoleOutputCharacterA + - VioLVBFillChar + +--*/ +{ + ULONG NumFilled; + COORD OldCoord, Coord; + + if ( !KbdEchoFlag ) + { + return (0L); + } + + if (((long) BSCount < 0) || ((long) SpaceCount < 0)) { +#if DBG + DbgPrint("KbdEchoBSAndFillSpaces: BSCount %d or SpaceCount %d are negative\n", + (long)BSCount, (long)SpaceCount); +#endif + return ERROR_INVALID_PARAMETER; + } + + OldCoord = Coord = GET_CURRENT_COORD; + + Coord.X -= (SHORT)BSCount; + while ( Coord.X < 0 ) + { + if ( Coord.Y ) + { + Coord.Y--; + Coord.X += SesGrp->ScreenColNum; + } else + { + if ( SpaceCount ) + { + if ( SpaceCount > (ULONG)abs(Coord.X) ) + { + SpaceCount += (ULONG)Coord.X; + } else + { + SpaceCount = 0; + } + } + + BSCount += (ULONG)Coord.X; // sub the negative value + Coord.X = 0; + } + } + + KbdEchoCharToConsole('\b', BSCount); + Ow2VioUpdateCurPos(Coord); + + if ( SpaceCount ) + { + if (!Or2WinFillConsoleOutputCharacterA( + #if DBG + KbdEchoBSAndFillSpacesStr, + #endif + hConOut, + ' ', + SpaceCount, + Coord, + &NumFilled)) + { +#if DBG + ASSERT1("OS2SES(KbdEchoBSAndFillSpaces): failed on FillConsoleOutputCharacterA\n", FALSE); +#endif + } + +#if DBG + if ( NumFilled != SpaceCount ) + { + KdPrint(("OS2SES(KbdEchoBSAndFillSpaces): partial data %u from %u\n", + NumFilled, SpaceCount)); + ASSERT( FALSE ); + } +#endif + VioLVBFillChar( +#ifdef DBCS +// MSKK Oct.14.1993 V-AkihiS + " ", +#else + ' ', +#endif + Coord, + SpaceCount + ); + + VioLVBFillAtt( + SesGrp->AnsiCellAttr, + Coord, + SpaceCount + ); + } + return(NO_ERROR); +} + + +DWORD +KbdEchoBeep( + IN ULONG Count + ) +/*++ + +Routine Description: + + This routine send BEPP ('\07') to console <Count> times. + +Arguments: + + Count - number of times to write \g char to console + +Return Value: + + +Note: + + ASCII EDIT/CUE string mode. + + Used when no place in the active command line by KbdEchoString, + Char and KbdCueHandleChar. + + Calls: + + - KbdEchoCharToConsole + +--*/ +{ + KbdEchoCharToConsole('\07', Count); + return(NO_ERROR); +} + + +DWORD +KbdEchoChar( + IN UCHAR Char, + IN ULONG Count + ) +/*++ + +Routine Description: + + This routine echo <Char> to console <Count> times and update LVB. + +Arguments: + + Char - char to send to console + + Count - number of times to send char to console + +Return Value: + + +Note: + + ASCII EDIT string mode. + + Updates: + + - SesGrp->WinCoord + - LVB + + Calls: + + - KbdEchoCharToConsole + - VioLVBScrollBuff + +--*/ +{ + COORD OldCoord, Coord; + BOOL SendByLine = FALSE; + UCHAR FillChar; + ULONG Offset; + + OldCoord = Coord = GET_CURRENT_COORD; + if (( Char >= ' ' ) || ( Char == '\t' )) + { + KbdEchoCharToConsole(Char, Count); + + if ( Char == '\t' ) + { + Offset = 8 * Count - (Coord.X & 7); + FillChar = ' '; + } else + { + FillChar = Char; + Offset = Count; + } + + if ((ULONG)( Offset + 2 * SesGrp->ScreenColNum ) > SesGrp->ScreenSize ) + { + SendByLine = TRUE; + } else + { + Coord.X += (SHORT)Offset; + while ( Coord.X >= SesGrp->ScreenColNum ) + { + Coord.Y++; + Coord.X -= SesGrp->ScreenColNum; + } + + if ( Coord.Y >= SesGrp->ScreenRowNum ) + { + VioLVBScrollBuff(Coord.Y - SesGrp->ScreenRowNum + 1); + OldCoord.Y -= Coord.Y - SesGrp->ScreenRowNum + 1; + Coord.Y = SesGrp->ScreenRowNum - 1; + } + + Ow2VioUpdateCurPos(Coord); + + VioLVBFillChar( +#ifdef DBCS +// MSKK Oct.14.1993 V-AkihiS + &FillChar, +#else + FillChar, +#endif + OldCoord, + Offset + ); + + VioLVBFillAtt( + SesGrp->AnsiCellAttr, + OldCoord, + Offset + ); + } + } + + if ( SendByLine || (( Char < ' ' ) && ( Char != '\t' ))) + { + ULONG NumChar, NumWritten, MaxCount, Pattern; + + if ( SendByLine ) + { + Pattern = (ULONG)((FillChar << 24) | + (FillChar << 16) | + (FillChar << 8) | + (FillChar)); + + MaxCount = 0; + } else + { + MaxCount = Offset = 2 * Count; + FillChar = (UCHAR)(Char + '@'); + + Pattern = (ULONG)((FillChar << 24) | + ('^' << 16) | + (FillChar << 8) | + ('^')); + } + + NumChar = ( Offset > KBD_BUFFER_SIZE ) ? KBD_BUFFER_SIZE : Offset; + + RtlFillMemoryUlong( + KBD_BUFFER_ADDRESS, + (NumChar + 3) & ~3, + Pattern + ); + + while ( MaxCount ) + { + if(!Or2WinWriteConsoleA( + #if DBG + KbdEchoCharStr, + #endif + hConOut, + (LPSTR)KBD_BUFFER_ADDRESS, + NumChar, + &NumWritten, + NULL)) + { +#if DBG + ASSERT1("OS2SES(KbdEchoChar): failed on WriteConsoleA", FALSE); +#endif + //return (1); + } + +#if DBG + if ( NumChar != NumWritten ) + { + KdPrint(("OS2SES(KbdEchoChar): partial data WriteConsoleA %u from %u\n", + NumWritten, NumChar)); + ASSERT( FALSE ); + } +#endif + + MaxCount -= NumChar; + NumChar = ( MaxCount > KBD_BUFFER_SIZE ) ? KBD_BUFFER_SIZE : MaxCount; + } + + if (( NumChar = SesGrp->ScreenColNum - Coord.X ) > Offset ) + { + NumChar = Offset; + } + + while ( Offset ) + { + VioLVBCopyStr( + &KBD_BUFFER_ADDRESS[0], + Coord, + NumChar + ); + + + VioLVBFillAtt( + SesGrp->AnsiCellAttr, + Coord, + NumChar + ); + Coord.X += (SHORT)NumChar; + if ( Coord.X >= SesGrp->ScreenColNum ) + { + Coord.X -= SesGrp->ScreenColNum; + if ( ++Coord.Y >= SesGrp->ScreenRowNum ) + { + VioLVBScrollBuff(1); + Coord.Y--; + } + } + + Offset -= NumChar; + if (( NumChar = SesGrp->ScreenColNum - Coord.X ) > Offset ) + { + NumChar = Offset; + } + } + + Ow2VioUpdateCurPos(Coord); + } + + return(NO_ERROR); +} + + +DWORD +KbdEchoAString( + IN PUCHAR String, + IN ULONG Length + ) +/*++ + +Routine Description: + + This routine echo <String>, which size is <Lenght> to console and update LVB. + +Arguments: + + String - char string to send to console + + Length - string length + +Return Value: + + +Note: + + ASCII EDIT string mode. + + Updates: + + - SesGrp->WinCoord + - LVB + + Calls: + + - Or2WinWriteConsoleA + +--*/ +{ + ULONG NumWritten, NumChar, NumBytes, Num; + COORD OldCoord, Coord; + UCHAR Char; + + OldCoord = Coord = GET_CURRENT_COORD; + + for ( NumChar = 0, NumBytes = 0 ; NumChar < Length ; NumChar++ ) + { + Char = String[NumChar]; + if ( Char >= ' ' ) + { + KBD_BUFFER_ADDRESS[NumBytes++] = Char; + } else if ( Char = '\t' ) + { + Num = 8 - ((Coord.X + NumBytes) & 7); + memset(&KBD_BUFFER_ADDRESS[NumBytes], ' ', Num); + NumBytes += Num; + } else + { + KBD_BUFFER_ADDRESS[NumBytes++] = '^'; + KBD_BUFFER_ADDRESS[NumBytes++] = (UCHAR)(Char + '@'); + } + + if (((ULONG)( Coord.X + NumBytes ) >= (ULONG)SesGrp->ScreenColNum ) || + ( NumChar == ( Length - 1 ))) + { + if(!Or2WinWriteConsoleA( + #if DBG + KbdEchoAStringStr, + #endif + hConOut, + (LPSTR)KBD_BUFFER_ADDRESS, + NumBytes, + &NumWritten, + NULL)) + { +#if DBG + ASSERT1("OS2SES(KbdEchoAString): failed on WriteConsoleA", FALSE); +#endif + } + +#if DBG + if ( NumBytes != NumWritten ) + { + KdPrint(("OS2SES(KbdEchoAString): partial data WriteConsoleA %u from %u\n", + NumWritten, NumBytes)); + ASSERT( FALSE ); + } +#endif + OldCoord = Coord; + Coord.X += (SHORT)NumBytes; + if ( Coord.X >= SesGrp->ScreenColNum ) + { + Coord.Y++; + Coord.X -= SesGrp->ScreenColNum; + + if ( Coord.Y >= SesGrp->ScreenRowNum ) + { + Coord.Y = SesGrp->ScreenRowNum - 1; + OldCoord.Y--; + } + } + + Ow2VioUpdateCurPos(Coord); + + VioLVBCopyStr( + &KBD_BUFFER_ADDRESS[0], + OldCoord, + NumBytes + ); + + VioLVBFillAtt( + SesGrp->AnsiCellAttr, + OldCoord, + NumBytes + ); + NumBytes = 0; + } + } + return(NO_ERROR); +} + + +BOOL +KbdKeyIsTurnAround( + IN UCHAR Char, + IN UCHAR Scan + ) +{ + if ( KbdTurnAroundCharTwo ) + { + if ( Scan == (UCHAR)KbdTurnAroundChar ) + { + if ((( KbdReadMode == 0 ) && + (( Char == 0 ) || ( Char == 0xE0 ))) || + (( KbdReadMode == 1 ) && ( Char == HIBYTE(KbdTurnAroundChar) ))) + { + return(TRUE); + } + } + } else + { + if ( Char == (UCHAR)KbdTurnAroundChar ) + { + return(TRUE); + } + } + + return(FALSE); +} + |