[WIN32CSR] Implement some basic line editing capability

svn path=/trunk/; revision=47584
This commit is contained in:
Jeffrey Morlan 2010-06-05 06:10:53 +00:00
parent f4f8ee78d1
commit 7da6d0a6e2
2 changed files with 128 additions and 21 deletions

View file

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

View file

@ -26,7 +26,7 @@
<file>guiconsole.c</file>
<file>handle.c</file>
<file>harderror.c</file>
<file>history.c</file>
<file>history.c</file>
<file>tuiconsole.c</file>
<file>appswitch.c</file>
<file>win32csr.rc</file>