mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:36:23 +00:00
[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
This commit is contained in:
parent
742f7ebd4b
commit
e3e54a09b3
8 changed files with 531 additions and 345 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -18,6 +18,76 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/********** 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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue