[CONSRV]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 29 Aug 2014 19:54:10 +0000 (19:54 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 29 Aug 2014 19:54:10 +0000 (19:54 +0000)
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
win32ss/user/winsrv/consrv/condrv/dummyterm.c
win32ss/user/winsrv/consrv/condrv/text.c
win32ss/user/winsrv/consrv/frontends/terminal.c
win32ss/user/winsrv/consrv/include/conio.h
win32ss/user/winsrv/consrv/include/conio_winsrv.h
win32ss/user/winsrv/consrv/include/term.h
win32ss/user/winsrv/consrv/lineinput.c

index 4c883ee..ab43adc 100644 (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
index 3b38329..a9f6cf6 100644 (file)
@@ -31,17 +31,51 @@ DummyDrawRegion(IN OUT PTERMINAL This,
 {
 }
 
-static VOID NTAPI
+
+
+/************ 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,
-                 SMALL_RECT* Region,
-                 SHORT CursorStartX,
-                 SHORT CursorStartY,
-                 UINT ScrolledLines,
+                 PTEXTMODE_SCREEN_BUFFER Buff,
                  PWCHAR Buffer,
-                 UINT Length)
+                 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,
index 6b8dbdc..921df4d 100644 (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;
index b2ba1a9..de95241 100644 (file)
 #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
+
+
+/************ 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;
+    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,
-                 SMALL_RECT* Region,
-                 SHORT CursorStartX,
-                 SHORT CursorStartY,
-                 UINT ScrolledLines,
-                 PWCHAR Buffer,
-                 UINT Length)
+                      PTEXTMODE_SCREEN_BUFFER Buff,
+                      PWCHAR Buffer,
+                      DWORD Length,
+                      BOOL Attrib)
 {
     PFRONTEND FrontEnd = This->Data;
-    FrontEnd->Vtbl->WriteStream(FrontEnd,
-                                Region,
-                                CursorStartX,
-                                CursorStartY,
-                                ScrolledLines,
-                                Buffer,
-                                Length);
+    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,
index e9c1fb7..ee925bd 100644 (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 */
index a3e8285..73604ba 100644 (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 */
index 037f6e8..1671ca7 100644 (file)
 
 #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) \
index e9fe3ce..6bd830f 100644 (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);
                 }
             }
         }