mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4046 lines
106 KiB
4046 lines
106 KiB
/*++
|
|
|
|
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);
|
|
}
|
|
|