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:
Hermès Bélusca-Maïto 2014-08-29 19:54:10 +00:00
parent 742f7ebd4b
commit e3e54a09b3
8 changed files with 531 additions and 345 deletions

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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,

View file

@ -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 */

View file

@ -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 */

View file

@ -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) \

View file

@ -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);
}
}
}