From e3e54a09b3b5ab65f6e9e4b171e60c61b2688e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Fri, 29 Aug 2014 19:54:10 +0000 Subject: [PATCH] [CONSRV] Commit my work that I've done during my trip from Albi back to Paris (part 2/2): Remove terminal-specific line discipline code from CONDRV back to CONSRV. svn path=/branches/condrv_restructure/; revision=63979 --- win32ss/user/winsrv/consrv/condrv/coninput.c | 135 +----- win32ss/user/winsrv/consrv/condrv/dummyterm.c | 53 ++- win32ss/user/winsrv/consrv/condrv/text.c | 181 +------ .../user/winsrv/consrv/frontends/terminal.c | 444 +++++++++++++++++- win32ss/user/winsrv/consrv/include/conio.h | 36 +- .../user/winsrv/consrv/include/conio_winsrv.h | 5 - win32ss/user/winsrv/consrv/include/term.h | 14 +- win32ss/user/winsrv/consrv/lineinput.c | 8 +- 8 files changed, 531 insertions(+), 345 deletions(-) diff --git a/win32ss/user/winsrv/consrv/condrv/coninput.c b/win32ss/user/winsrv/consrv/condrv/coninput.c index 4c883eec8e6..ab43adcd470 100644 --- a/win32ss/user/winsrv/consrv/condrv/coninput.c +++ b/win32ss/user/winsrv/consrv/condrv/coninput.c @@ -302,10 +302,7 @@ ConDrvReadConsole(IN PCONSOLE Console, OUT PULONG NumCharsRead OPTIONAL) { // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait. - NTSTATUS Status = STATUS_PENDING; - PLIST_ENTRY CurrentEntry; - ConsoleInput *Input; - ULONG i; + // NTSTATUS Status; = STATUS_PENDING; if (Console == NULL || InputBuffer == NULL || /* Buffer == NULL || */ ReadControl == NULL || ReadControl->nLength != sizeof(CONSOLE_READCONSOLE_CONTROL)) @@ -317,128 +314,14 @@ ConDrvReadConsole(IN PCONSOLE Console, ASSERT(Console == InputBuffer->Header.Console); ASSERT((Buffer != NULL) || (Buffer == NULL && NumCharsToRead == 0)); - /* We haven't read anything (yet) */ - - i = ReadControl->nInitialChars; - - if (InputBuffer->Mode & ENABLE_LINE_INPUT) - { - if (Console->LineBuffer == NULL) - { - /* Starting a new line */ - Console->LineMaxSize = max(256, NumCharsToRead); - - Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR)); - if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY; - - Console->LinePos = Console->LineSize = ReadControl->nInitialChars; - Console->LineComplete = Console->LineUpPressed = FALSE; - Console->LineInsertToggle = Console->InsertMode; - Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask; - - /* - * Pre-filling the buffer is only allowed in the Unicode API, - * so we don't need to worry about ANSI <-> Unicode conversion. - */ - memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR)); - if (Console->LineSize == Console->LineMaxSize) - { - Console->LineComplete = TRUE; - Console->LinePos = 0; - } - } - - /* If we don't have a complete line yet, process the pending input */ - while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents)) - { - /* Remove input event from queue */ - CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); - if (IsListEmpty(&InputBuffer->InputEvents)) - { - ResetEvent(InputBuffer->ActiveEvent); - } - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - - /* Only pay attention to key down */ - if (Input->InputEvent.EventType == KEY_EVENT && - Input->InputEvent.Event.KeyEvent.bKeyDown) - { - LineInputKeyDown(Console, ExeName, - &Input->InputEvent.Event.KeyEvent); - ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; - } - ConsoleFreeHeap(Input); - } - - /* Check if we have a complete line to read from */ - if (Console->LineComplete) - { - while (i < NumCharsToRead && Console->LinePos != Console->LineSize) - { - WCHAR Char = Console->LineBuffer[Console->LinePos++]; - - if (Unicode) - { - ((PWCHAR)Buffer)[i] = Char; - } - else - { - ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); - } - ++i; - } - - if (Console->LinePos == Console->LineSize) - { - /* Entire line has been read */ - ConsoleFreeHeap(Console->LineBuffer); - Console->LineBuffer = NULL; - } - - Status = STATUS_SUCCESS; - } - } - else - { - /* Character input */ - while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents)) - { - /* Remove input event from queue */ - CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); - if (IsListEmpty(&InputBuffer->InputEvents)) - { - ResetEvent(InputBuffer->ActiveEvent); - } - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - - /* Only pay attention to valid ASCII chars, on key down */ - if (Input->InputEvent.EventType == KEY_EVENT && - Input->InputEvent.Event.KeyEvent.bKeyDown && - Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0') - { - WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar; - - if (Unicode) - { - ((PWCHAR)Buffer)[i] = Char; - } - else - { - ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); - } - ++i; - - /* Did read something */ - Status = STATUS_SUCCESS; - } - ConsoleFreeHeap(Input); - } - } - - // FIXME: Only set if Status == STATUS_SUCCESS ??? - if (NumCharsRead) *NumCharsRead = i; - - return Status; + /* Call the line-discipline */ + return TermReadStream(Console, + ExeName, + Unicode, + Buffer, + ReadControl, + NumCharsToRead, + NumCharsRead); } NTSTATUS NTAPI diff --git a/win32ss/user/winsrv/consrv/condrv/dummyterm.c b/win32ss/user/winsrv/consrv/condrv/dummyterm.c index 3b38329cfcd..a9f6cf63b6d 100644 --- a/win32ss/user/winsrv/consrv/condrv/dummyterm.c +++ b/win32ss/user/winsrv/consrv/condrv/dummyterm.c @@ -31,17 +31,51 @@ DummyDrawRegion(IN OUT PTERMINAL This, { } -static VOID NTAPI -DummyWriteStream(IN OUT PTERMINAL This, - SMALL_RECT* Region, - SHORT CursorStartX, - SHORT CursorStartY, - UINT ScrolledLines, - PWCHAR Buffer, - UINT Length) + + +/************ Line discipline ***************/ + +static NTSTATUS NTAPI +DummyReadStream(IN OUT PTERMINAL This, + /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/ + IN BOOLEAN Unicode, + /**PWCHAR Buffer,**/ + OUT PVOID Buffer, + IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, + IN ULONG NumCharsToRead, + OUT PULONG NumCharsRead OPTIONAL) { + /* + * We were called because the console was in cooked mode. + * There is nothing to read, wait until a real terminal + * is plugged into the console. + */ + return STATUS_PENDING; } +static NTSTATUS NTAPI +DummyWriteStream(IN OUT PTERMINAL This, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib) +{ + /* + * We were called because the console was in cooked mode. + * There is nothing to write, wait until a real terminal + * is plugged into the console. + */ + + // /* Stop here if the console is paused */ + // if (Console->UnpauseEvent != NULL) return STATUS_PENDING; + + return STATUS_PENDING; +} + +/************ Line discipline ***************/ + + + static BOOL NTAPI DummySetCursorInfo(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer) @@ -114,7 +148,10 @@ static TERMINAL_VTBL DummyVtbl = DummyInitTerminal, DummyDeinitTerminal, DummyDrawRegion, + + DummyReadStream, DummyWriteStream, + DummySetCursorInfo, DummySetScreenInfo, DummyResizeTerminal, diff --git a/win32ss/user/winsrv/consrv/condrv/text.c b/win32ss/user/winsrv/consrv/condrv/text.c index 6b8dbdcbc8a..921df4da2fe 100644 --- a/win32ss/user/winsrv/consrv/condrv/text.c +++ b/win32ss/user/winsrv/consrv/condrv/text.c @@ -16,8 +16,6 @@ /* GLOBALS ********************************************************************/ -#define TAB_WIDTH 8 - /* PRIVATE FUNCTIONS **********************************************************/ CONSOLE_IO_OBJECT_TYPE @@ -33,7 +31,7 @@ static CONSOLE_SCREEN_BUFFER_VTBL TextVtbl = }; -static VOID +/*static*/ VOID ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff); @@ -127,7 +125,7 @@ ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y) return &Buff->Buffer[((Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y) * Buff->ScreenBufferSize.X + X]; } -static VOID +/*static*/ VOID ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff) { PCHAR_INFO Ptr = ConioCoordToPointer(Buff, 0, Buff->CursorPosition.Y); @@ -354,169 +352,6 @@ ConioResizeBuffer(PCONSOLE Console, return STATUS_SUCCESS; } -static VOID -ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT ScrolledLines) -{ - /* If we hit bottom, slide the viewable screen */ - if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y) - { - Buff->CursorPosition.Y--; - if (++Buff->VirtualY == Buff->ScreenBufferSize.Y) - { - Buff->VirtualY = 0; - } - (*ScrolledLines)++; - ClearLineBuffer(Buff); - if (UpdateRect->Top != 0) - { - UpdateRect->Top--; - } - } - UpdateRect->Left = 0; - UpdateRect->Right = Buff->ScreenBufferSize.X - 1; - UpdateRect->Bottom = Buff->CursorPosition.Y; -} - -NTSTATUS -ConioWriteConsole(PCONSOLE Console, - PTEXTMODE_SCREEN_BUFFER Buff, - PWCHAR Buffer, - DWORD Length, - BOOL Attrib) -{ - UINT i; - PCHAR_INFO Ptr; - SMALL_RECT UpdateRect; - SHORT CursorStartX, CursorStartY; - UINT ScrolledLines; - - CursorStartX = Buff->CursorPosition.X; - CursorStartY = Buff->CursorPosition.Y; - UpdateRect.Left = Buff->ScreenBufferSize.X; - UpdateRect.Top = Buff->CursorPosition.Y; - UpdateRect.Right = -1; - UpdateRect.Bottom = Buff->CursorPosition.Y; - ScrolledLines = 0; - - for (i = 0; i < Length; i++) - { - /* - * If we are in processed mode, interpret special characters and - * display them correctly. Otherwise, just put them into the buffer. - */ - if (Buff->Mode & ENABLE_PROCESSED_OUTPUT) - { - /* --- CR --- */ - if (Buffer[i] == L'\r') - { - Buff->CursorPosition.X = 0; - UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); - UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); - continue; - } - /* --- LF --- */ - else if (Buffer[i] == L'\n') - { - Buff->CursorPosition.X = 0; - ConioNextLine(Buff, &UpdateRect, &ScrolledLines); - continue; - } - /* --- BS --- */ - else if (Buffer[i] == L'\b') - { - /* Only handle BS if we're not on the first pos of the first line */ - if (0 != Buff->CursorPosition.X || 0 != Buff->CursorPosition.Y) - { - if (0 == Buff->CursorPosition.X) - { - /* slide virtual position up */ - Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1; - Buff->CursorPosition.Y--; - UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y); - } - else - { - Buff->CursorPosition.X--; - } - Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); - Ptr->Char.UnicodeChar = L' '; - Ptr->Attributes = Buff->ScreenDefaultAttrib; - UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); - UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); - } - continue; - } - /* --- TAB --- */ - else if (Buffer[i] == L'\t') - { - UINT EndX; - - UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); - EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1); - EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X); - Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); - while (Buff->CursorPosition.X < EndX) - { - Ptr->Char.UnicodeChar = L' '; - Ptr->Attributes = Buff->ScreenDefaultAttrib; - ++Ptr; - Buff->CursorPosition.X++; - } - UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1); - if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) - { - if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) - { - Buff->CursorPosition.X = 0; - ConioNextLine(Buff, &UpdateRect, &ScrolledLines); - } - else - { - Buff->CursorPosition.X--; - } - } - continue; - } - // /* --- BEL ---*/ - // else if (Buffer[i] == L'\a') - // { - // // FIXME: This MUST BE moved to the terminal emulator frontend!! - // DPRINT1("Bell\n"); - // // SendNotifyMessage(Console->hWindow, PM_CONSOLE_BEEP, 0, 0); - // continue; - // } - } - UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); - UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); - - Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); - Ptr->Char.UnicodeChar = Buffer[i]; - if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib; - - Buff->CursorPosition.X++; - if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) - { - if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) - { - Buff->CursorPosition.X = 0; - ConioNextLine(Buff, &UpdateRect, &ScrolledLines); - } - else - { - Buff->CursorPosition.X = CursorStartX; - } - } - } - - if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer) - { - TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, - ScrolledLines, Buffer, Length); - } - - return STATUS_SUCCESS; -} - NTSTATUS NTAPI ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, @@ -807,6 +642,7 @@ ConDrvWriteConsole(IN PCONSOLE Console, /* Stop here if the console is paused */ if (Console->UnpauseEvent != NULL) return STATUS_PENDING; + /* Convert the string to UNICODE */ if (Unicode) { Buffer = StringBuffer; @@ -831,15 +667,16 @@ ConDrvWriteConsole(IN PCONSOLE Console, } } + /* Send it */ if (Buffer) { if (NT_SUCCESS(Status)) { - Status = ConioWriteConsole(Console, - ScreenBuffer, - Buffer, - NumCharsToWrite, - TRUE); + Status = TermWriteStream(Console, + ScreenBuffer, + Buffer, + NumCharsToWrite, + TRUE); if (NT_SUCCESS(Status)) { Written = NumCharsToWrite; diff --git a/win32ss/user/winsrv/consrv/frontends/terminal.c b/win32ss/user/winsrv/consrv/frontends/terminal.c index b2ba1a95885..de952410dac 100644 --- a/win32ss/user/winsrv/consrv/frontends/terminal.c +++ b/win32ss/user/winsrv/consrv/frontends/terminal.c @@ -18,6 +18,76 @@ #define NDEBUG #include + + + + +/********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/ + +/* GLOBALS ********************************************************************/ + +/* + * From MSDN: + * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. + * If they are the same, the function fails, and GetLastError returns + * ERROR_INVALID_PARAMETER." + */ +#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \ + ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ + WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) + +#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \ + ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ + MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1) + +typedef struct ConsoleInput_t +{ + LIST_ENTRY ListEntry; + INPUT_RECORD InputEvent; +} ConsoleInput; + + +/* PRIVATE FUNCTIONS **********************************************************/ + +#if 0 + +static VOID +ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent) +{ + if (InputEvent->EventType == KEY_EVENT) + { + WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar; + InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0; + ConsoleInputUnicodeCharToAnsiChar(Console, + &InputEvent->Event.KeyEvent.uChar.AsciiChar, + &UnicodeChar); + } +} + +static VOID +ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent) +{ + if (InputEvent->EventType == KEY_EVENT) + { + CHAR AsciiChar = InputEvent->Event.KeyEvent.uChar.AsciiChar; + InputEvent->Event.KeyEvent.uChar.AsciiChar = 0; + ConsoleInputAnsiCharToUnicodeChar(Console, + &InputEvent->Event.KeyEvent.uChar.UnicodeChar, + &AsciiChar); + } +} + +#endif + +/********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/ + + + + + + + + /* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/ /***************/ @@ -226,25 +296,366 @@ ConSrvTermDrawRegion(IN OUT PTERMINAL This, FrontEnd->Vtbl->DrawRegion(FrontEnd, Region); } -static VOID NTAPI -ConSrvTermWriteStream(IN OUT PTERMINAL This, - SMALL_RECT* Region, - SHORT CursorStartX, - SHORT CursorStartY, - UINT ScrolledLines, - PWCHAR Buffer, - UINT Length) + + +/************ Line discipline ***************/ + +static NTSTATUS NTAPI +ConSrvTermReadStream(IN OUT PTERMINAL This, + /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/ + IN BOOLEAN Unicode, + /**PWCHAR Buffer,**/ + OUT PVOID Buffer, + IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, + IN ULONG NumCharsToRead, + OUT PULONG NumCharsRead OPTIONAL) { PFRONTEND FrontEnd = This->Data; - FrontEnd->Vtbl->WriteStream(FrontEnd, - Region, - CursorStartX, - CursorStartY, - ScrolledLines, - Buffer, - Length); + PCONSRV_CONSOLE Console = FrontEnd->Console; + PCONSOLE_INPUT_BUFFER InputBuffer = &Console->InputBuffer; + + // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait. + NTSTATUS Status = STATUS_PENDING; + + PLIST_ENTRY CurrentEntry; + ConsoleInput *Input; + ULONG i; + + /* Validity checks */ + // ASSERT(Console == InputBuffer->Header.Console); + ASSERT((Buffer != NULL) || (Buffer == NULL && NumCharsToRead == 0)); + + /* We haven't read anything (yet) */ + i = ReadControl->nInitialChars; + + if (InputBuffer->Mode & ENABLE_LINE_INPUT) + { + /* COOKED mode, call the line discipline */ + + if (Console->LineBuffer == NULL) + { + /* Starting a new line */ + Console->LineMaxSize = max(256, NumCharsToRead); + + Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR)); + if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY; + + Console->LinePos = Console->LineSize = ReadControl->nInitialChars; + Console->LineComplete = Console->LineUpPressed = FALSE; + Console->LineInsertToggle = Console->InsertMode; + Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask; + + /* + * Pre-filling the buffer is only allowed in the Unicode API, + * so we don't need to worry about ANSI <-> Unicode conversion. + */ + memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR)); + if (Console->LineSize == Console->LineMaxSize) + { + Console->LineComplete = TRUE; + Console->LinePos = 0; + } + } + + /* If we don't have a complete line yet, process the pending input */ + while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents)) + { + /* Remove input event from queue */ + CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); + if (IsListEmpty(&InputBuffer->InputEvents)) + { + ResetEvent(InputBuffer->ActiveEvent); + } + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + + /* Only pay attention to key down */ + if (Input->InputEvent.EventType == KEY_EVENT && + Input->InputEvent.Event.KeyEvent.bKeyDown) + { + LineInputKeyDown(Console, ExeName, + &Input->InputEvent.Event.KeyEvent); + ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; + } + ConsoleFreeHeap(Input); + } + + /* Check if we have a complete line to read from */ + if (Console->LineComplete) + { + while (i < NumCharsToRead && Console->LinePos != Console->LineSize) + { + WCHAR Char = Console->LineBuffer[Console->LinePos++]; + + if (Unicode) + { + ((PWCHAR)Buffer)[i] = Char; + } + else + { + ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); + } + ++i; + } + + if (Console->LinePos == Console->LineSize) + { + /* Entire line has been read */ + ConsoleFreeHeap(Console->LineBuffer); + Console->LineBuffer = NULL; + } + + Status = STATUS_SUCCESS; + } + } + else + { + /* RAW mode */ + + /* Character input */ + while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents)) + { + /* Remove input event from queue */ + CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); + if (IsListEmpty(&InputBuffer->InputEvents)) + { + ResetEvent(InputBuffer->ActiveEvent); + } + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + + /* Only pay attention to valid characters, on key down */ + if (Input->InputEvent.EventType == KEY_EVENT && + Input->InputEvent.Event.KeyEvent.bKeyDown && + Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0') + { + WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar; + + if (Unicode) + { + ((PWCHAR)Buffer)[i] = Char; + } + else + { + ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); + } + ++i; + + /* Did read something */ + Status = STATUS_SUCCESS; + } + ConsoleFreeHeap(Input); + } + } + + // FIXME: Only set if Status == STATUS_SUCCESS ??? + if (NumCharsRead) *NumCharsRead = i; + + return Status; } + + + +/* GLOBALS ********************************************************************/ + +#define TAB_WIDTH 8 + +// See condrv/text.c +/*static*/ VOID +ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff); + +static VOID +ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT ScrolledLines) +{ + /* If we hit bottom, slide the viewable screen */ + if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y) + { + Buff->CursorPosition.Y--; + if (++Buff->VirtualY == Buff->ScreenBufferSize.Y) + { + Buff->VirtualY = 0; + } + (*ScrolledLines)++; + ClearLineBuffer(Buff); + if (UpdateRect->Top != 0) + { + UpdateRect->Top--; + } + } + UpdateRect->Left = 0; + UpdateRect->Right = Buff->ScreenBufferSize.X - 1; + UpdateRect->Bottom = Buff->CursorPosition.Y; +} + +static NTSTATUS +ConioWriteConsole(PFRONTEND FrontEnd, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib) +{ + PCONSRV_CONSOLE Console = FrontEnd->Console; + + UINT i; + PCHAR_INFO Ptr; + SMALL_RECT UpdateRect; + SHORT CursorStartX, CursorStartY; + UINT ScrolledLines; + + CursorStartX = Buff->CursorPosition.X; + CursorStartY = Buff->CursorPosition.Y; + UpdateRect.Left = Buff->ScreenBufferSize.X; + UpdateRect.Top = Buff->CursorPosition.Y; + UpdateRect.Right = -1; + UpdateRect.Bottom = Buff->CursorPosition.Y; + ScrolledLines = 0; + + for (i = 0; i < Length; i++) + { + /* + * If we are in processed mode, interpret special characters and + * display them correctly. Otherwise, just put them into the buffer. + */ + if (Buff->Mode & ENABLE_PROCESSED_OUTPUT) + { + /* --- CR --- */ + if (Buffer[i] == L'\r') + { + Buff->CursorPosition.X = 0; + UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); + UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); + continue; + } + /* --- LF --- */ + else if (Buffer[i] == L'\n') + { + Buff->CursorPosition.X = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + continue; + } + /* --- BS --- */ + else if (Buffer[i] == L'\b') + { + /* Only handle BS if we're not on the first pos of the first line */ + if (0 != Buff->CursorPosition.X || 0 != Buff->CursorPosition.Y) + { + if (0 == Buff->CursorPosition.X) + { + /* slide virtual position up */ + Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1; + Buff->CursorPosition.Y--; + UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y); + } + else + { + Buff->CursorPosition.X--; + } + Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); + Ptr->Char.UnicodeChar = L' '; + Ptr->Attributes = Buff->ScreenDefaultAttrib; + UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); + UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); + } + continue; + } + /* --- TAB --- */ + else if (Buffer[i] == L'\t') + { + UINT EndX; + + UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); + EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1); + EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X); + Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); + while (Buff->CursorPosition.X < EndX) + { + Ptr->Char.UnicodeChar = L' '; + Ptr->Attributes = Buff->ScreenDefaultAttrib; + ++Ptr; + Buff->CursorPosition.X++; + } + UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1); + if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) + { + if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) + { + Buff->CursorPosition.X = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + } + else + { + Buff->CursorPosition.X--; + } + } + continue; + } + // /* --- BEL ---*/ + // else if (Buffer[i] == L'\a') + // { + // // FIXME: This MUST BE moved to the terminal emulator frontend!! + // DPRINT1("Bell\n"); + // // SendNotifyMessage(Console->hWindow, PM_CONSOLE_BEEP, 0, 0); + // continue; + // } + } + UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); + UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); + + Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); + Ptr->Char.UnicodeChar = Buffer[i]; + if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib; + + Buff->CursorPosition.X++; + if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) + { + if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) + { + Buff->CursorPosition.X = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + } + else + { + Buff->CursorPosition.X = CursorStartX; + } + } + } + + if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer) + { + // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, + // ScrolledLines, Buffer, Length); + FrontEnd->Vtbl->WriteStream(FrontEnd, + &UpdateRect, + CursorStartX, + CursorStartY, + ScrolledLines, + Buffer, + Length); + } + + return STATUS_SUCCESS; +} + + + +static NTSTATUS NTAPI +ConSrvTermWriteStream(IN OUT PTERMINAL This, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib) +{ + PFRONTEND FrontEnd = This->Data; + return ConioWriteConsole(FrontEnd, + Buff, + Buffer, + Length, + Attrib); +} + +/************ Line discipline ***************/ + + + static BOOL NTAPI ConSrvTermSetCursorInfo(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer) @@ -335,7 +746,10 @@ static TERMINAL_VTBL ConSrvTermVtbl = ConSrvTermInitTerminal, ConSrvTermDeinitTerminal, ConSrvTermDrawRegion, + + ConSrvTermReadStream, ConSrvTermWriteStream, + ConSrvTermSetCursorInfo, ConSrvTermSetScreenInfo, ConSrvTermResizeTerminal, diff --git a/win32ss/user/winsrv/consrv/include/conio.h b/win32ss/user/winsrv/consrv/include/conio.h index e9c1fb7cf80..ee925bd0543 100644 --- a/win32ss/user/winsrv/consrv/include/conio.h +++ b/win32ss/user/winsrv/consrv/include/conio.h @@ -197,14 +197,31 @@ typedef struct _TERMINAL_VTBL /* Interface used for both text-mode and graphics screen buffers */ VOID (NTAPI *DrawRegion)(IN OUT PTERMINAL This, SMALL_RECT* Region); + + + +/************ Line discipline ***************/ + /* Interface used only for text-mode screen buffers */ - VOID (NTAPI *WriteStream)(IN OUT PTERMINAL This, - SMALL_RECT* Region, - SHORT CursorStartX, - SHORT CursorStartY, - UINT ScrolledLines, - PWCHAR Buffer, - UINT Length); + + NTSTATUS (NTAPI *ReadStream)(IN OUT PTERMINAL This, + /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/ + IN BOOLEAN Unicode, + /**PWCHAR Buffer,**/ + OUT PVOID Buffer, + IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, + IN ULONG NumCharsToRead, + OUT PULONG NumCharsRead OPTIONAL); + NTSTATUS (NTAPI *WriteStream)(IN OUT PTERMINAL This, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib); + +/************ Line discipline ***************/ + + + BOOL (NTAPI *SetCursorInfo)(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer); BOOL (NTAPI *SetScreenInfo)(IN OUT PTERMINAL This, @@ -341,10 +358,5 @@ VOID ConioDrawConsole(PCONSOLE Console); NTSTATUS ConioResizeBuffer(PCONSOLE Console, PTEXTMODE_SCREEN_BUFFER ScreenBuffer, COORD Size); -NTSTATUS ConioWriteConsole(PCONSOLE Console, - PTEXTMODE_SCREEN_BUFFER Buff, - PWCHAR Buffer, - DWORD Length, - BOOL Attrib); /* EOF */ diff --git a/win32ss/user/winsrv/consrv/include/conio_winsrv.h b/win32ss/user/winsrv/consrv/include/conio_winsrv.h index a3e82852235..73604ba38b2 100644 --- a/win32ss/user/winsrv/consrv/include/conio_winsrv.h +++ b/win32ss/user/winsrv/consrv/include/conio_winsrv.h @@ -222,10 +222,5 @@ VOID ConioDrawConsole(PCONSRV_CONSOLE Console); NTSTATUS ConioResizeBuffer(PCONSRV_CONSOLE Console, PTEXTMODE_SCREEN_BUFFER ScreenBuffer, COORD Size); -NTSTATUS ConioWriteConsole(PCONSRV_CONSOLE Console, - PTEXTMODE_SCREEN_BUFFER Buff, - PWCHAR Buffer, - DWORD Length, - BOOL Attrib); /* EOF */ diff --git a/win32ss/user/winsrv/consrv/include/term.h b/win32ss/user/winsrv/consrv/include/term.h index 037f6e8c314..1671ca7d0f9 100644 --- a/win32ss/user/winsrv/consrv/include/term.h +++ b/win32ss/user/winsrv/consrv/include/term.h @@ -12,9 +12,17 @@ #define TermDrawRegion(Console, Region) \ (Console)->TermIFace.Vtbl->DrawRegion(&(Console)->TermIFace, (Region)) -#define TermWriteStream(Console, Region, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \ - (Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (Region), (CurStartX), (CurStartY), \ - (ScrolledLines), (Buffer), (Length)) + + +#define TermReadStream(Console, ExeName, /**/ Unicode, /**/ Buffer, ReadControl, NumCharsToRead, NumCharsRead) \ + (Console)->TermIFace.Vtbl->ReadStream(&(Console)->TermIFace, (ExeName), /**/ (Unicode), /**/ \ + (Buffer), (ReadControl), (NumCharsToRead), (NumCharsRead)) + +#define TermWriteStream(Console, ScreenBuffer, Buffer, Length, Attrib) \ + (Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (ScreenBuffer), (Buffer), \ + (Length), (Attrib)) + + #define TermSetCursorInfo(Console, ScreenBuffer) \ (Console)->TermIFace.Vtbl->SetCursorInfo(&(Console)->TermIFace, (ScreenBuffer)) #define TermSetScreenInfo(Console, ScreenBuffer, OldCursorX, OldCursorY) \ diff --git a/win32ss/user/winsrv/consrv/lineinput.c b/win32ss/user/winsrv/consrv/lineinput.c index e9fe3cef977..6bd830fbfcc 100644 --- a/win32ss/user/winsrv/consrv/lineinput.c +++ b/win32ss/user/winsrv/consrv/lineinput.c @@ -108,11 +108,11 @@ LineInputEdit(PCONSRV_CONSOLE Console, { for (i = Pos; i < NewSize; i++) { - ConioWriteConsole(Console, ActiveBuffer, &Console->LineBuffer[i], 1, TRUE); + TermWriteStream(Console, ActiveBuffer, &Console->LineBuffer[i], 1, TRUE); } for (; i < Console->LineSize; i++) { - ConioWriteConsole(Console, ActiveBuffer, L" ", 1, TRUE); + TermWriteStream(Console, ActiveBuffer, L" ", 1, TRUE); } Console->LinePos = i; } @@ -361,7 +361,7 @@ LineInputKeyDown(PCONSRV_CONSOLE Console, { if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) { - ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\r", 1, TRUE); + TermWriteStream(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\r", 1, TRUE); } } @@ -378,7 +378,7 @@ LineInputKeyDown(PCONSRV_CONSOLE Console, { if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) { - ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\n", 1, TRUE); + TermWriteStream(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\n", 1, TRUE); } } }