diff --git a/reactos/subsystems/win32/csrss/win32csr/coninput.c b/reactos/subsystems/win32/csrss/win32csr/coninput.c
index 95955890217..51777ddac90 100644
--- a/reactos/subsystems/win32/csrss/win32csr/coninput.c
+++ b/reactos/subsystems/win32/csrss/win32csr/coninput.c
@@ -22,25 +22,143 @@
/* FUNCTIONS *****************************************************************/
+static VOID
+ConioLineInputSetPos(PCSRSS_CONSOLE Console, UINT Pos)
+{
+ if (Pos != Console->LinePos && Console->Mode & ENABLE_ECHO_INPUT)
+ {
+ PCSRSS_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+ UINT OldCursorX = Buffer->CurrentX;
+ UINT OldCursorY = Buffer->CurrentY;
+ INT XY = OldCursorY * Buffer->MaxX + OldCursorX;
+
+ XY += (Pos - Console->LinePos);
+ if (XY < 0)
+ XY = 0;
+ else if (XY >= Buffer->MaxY * Buffer->MaxX)
+ XY = Buffer->MaxY * Buffer->MaxX - 1;
+
+ Buffer->CurrentX = XY % Buffer->MaxX;
+ Buffer->CurrentY = XY / Buffer->MaxX;
+ ConioSetScreenInfo(Console, Buffer, OldCursorX, OldCursorY);
+ }
+
+ Console->LinePos = Pos;
+}
+
+static VOID
+ConioLineInputEdit(PCSRSS_CONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Insertion)
+{
+ UINT Pos = Console->LinePos;
+ UINT NewSize = Console->LineSize - NumToDelete + NumToInsert;
+ INT i;
+
+ /* Make sure there's always enough room for ending \r\n */
+ if (NewSize + 2 > Console->LineMaxSize)
+ return;
+
+ memmove(&Console->LineBuffer[Pos + NumToInsert],
+ &Console->LineBuffer[Pos + NumToDelete],
+ (Console->LineSize - (Pos + NumToDelete)) * sizeof(WCHAR));
+ memcpy(&Console->LineBuffer[Pos], Insertion, NumToInsert * sizeof(WCHAR));
+
+ if (Console->Mode & ENABLE_ECHO_INPUT)
+ {
+ for (i = Pos; i < NewSize; i++)
+ {
+ CHAR AsciiChar;
+ WideCharToMultiByte(Console->OutputCodePage, 0,
+ &Console->LineBuffer[i], 1,
+ &AsciiChar, 1, NULL, NULL);
+ ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
+ }
+ for (; i < Console->LineSize; i++)
+ {
+ ConioWriteConsole(Console, Console->ActiveBuffer, " ", 1, TRUE);
+ }
+ Console->LinePos = i;
+ }
+
+ Console->LineSize = NewSize;
+ ConioLineInputSetPos(Console, Pos + NumToInsert);
+}
+
static VOID
ConioLineInputKeyDown(PCSRSS_CONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
{
+ UINT Pos = Console->LinePos;
+ switch (KeyEvent->wVirtualKeyCode)
+ {
+ case VK_ESCAPE:
+ /* Clear entire line */
+ ConioLineInputSetPos(Console, 0);
+ ConioLineInputEdit(Console, Console->LineSize, 0, NULL);
+ return;
+ case VK_HOME:
+ /* Move to start of line. With ctrl, erase everything left of cursor */
+ ConioLineInputSetPos(Console, 0);
+ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
+ ConioLineInputEdit(Console, Pos, 0, NULL);
+ return;
+ case VK_END:
+ /* Move to end of line. With ctrl, erase everything right of cursor */
+ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
+ ConioLineInputEdit(Console, Console->LineSize - Pos, 0, NULL);
+ else
+ ConioLineInputSetPos(Console, Console->LineSize);
+ return;
+ case VK_LEFT:
+ /* Move left. With ctrl, move to beginning of previous word */
+ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
+ {
+ while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--;
+ while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--;
+ }
+ else
+ {
+ Pos -= (Pos > 0);
+ }
+ ConioLineInputSetPos(Console, Pos);
+ return;
+ case VK_RIGHT:
+ /* Move right. With ctrl, move to beginning of next word */
+ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
+ {
+ while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++;
+ while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++;
+ }
+ else
+ {
+ Pos += (Pos < Console->LineSize);
+ }
+ ConioLineInputSetPos(Console, Pos);
+ return;
+ case VK_DELETE:
+ /* Remove character to right of cursor */
+ if (Pos != Console->LineSize)
+ ConioLineInputEdit(Console, 1, 0, NULL);
+ return;
+ case VK_F6:
+ /* Insert a ^Z character */
+ KeyEvent->uChar.UnicodeChar = 26;
+ break;
+ }
+
if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->Mode & ENABLE_PROCESSED_INPUT)
{
- /* backspace handling - if we are in charge of echoing it then we handle it here
- * otherwise we treat it like a normal char.
- */
- if (Console->LineSize > 0)
+ /* backspace handling - if processed input enabled then we handle it here
+ * otherwise we treat it like a normal char. */
+ if (Pos > 0)
{
- Console->LineSize--;
- if (Console->Mode & ENABLE_ECHO_INPUT)
- ConioWriteConsole(Console, Console->ActiveBuffer, "\b", 1, TRUE);
+ ConioLineInputSetPos(Console, Pos - 1);
+ ConioLineInputEdit(Console, 1, 0, NULL);
}
}
else if (KeyEvent->uChar.UnicodeChar == L'\r')
{
HistoryAddEntry(Console);
+ ConioLineInputSetPos(Console, Console->LineSize);
Console->LineBuffer[Console->LineSize++] = L'\r';
if (Console->Mode & ENABLE_ECHO_INPUT)
ConioWriteConsole(Console, Console->ActiveBuffer, "\r", 1, TRUE);
@@ -55,19 +173,8 @@ ConioLineInputKeyDown(PCSRSS_CONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
}
else if (KeyEvent->uChar.UnicodeChar != L'\0')
{
- if (Console->LineSize + 2 < Console->LineMaxSize)
- {
- Console->LineBuffer[Console->LineSize++] = KeyEvent->uChar.UnicodeChar;
- /* echo to screen if enabled */
- if (Console->Mode & ENABLE_ECHO_INPUT)
- {
- CHAR AsciiChar;
- WideCharToMultiByte(Console->OutputCodePage, 0,
- &KeyEvent->uChar.UnicodeChar, 1,
- &AsciiChar, 1, NULL, NULL);
- ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
- }
- }
+ /* Normal character */
+ ConioLineInputEdit(Console, 0, 1, &KeyEvent->uChar.UnicodeChar);
}
}
diff --git a/reactos/subsystems/win32/csrss/win32csr/win32csr.rbuild b/reactos/subsystems/win32/csrss/win32csr/win32csr.rbuild
index 3cf0931c0fb..96e3be51b2f 100644
--- a/reactos/subsystems/win32/csrss/win32csr/win32csr.rbuild
+++ b/reactos/subsystems/win32/csrss/win32csr/win32csr.rbuild
@@ -26,7 +26,7 @@
guiconsole.c
handle.c
harderror.c
- history.c
+ history.c
tuiconsole.c
appswitch.c
win32csr.rc