ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

lineinput.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS CSRSS
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            subsystems/win32/csrss/win32csr/lineinput.c
00005  * PURPOSE:         Console line input functions
00006  * PROGRAMMERS:     Jeffrey Morlan
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #define NDEBUG
00012 #include "w32csr.h"
00013 #include <debug.h>
00014 
00015 typedef struct tagHISTORY_BUFFER
00016 {
00017     LIST_ENTRY ListEntry;
00018     WORD Position;
00019     WORD MaxEntries;
00020     WORD NumEntries;
00021     PUNICODE_STRING Entries;
00022     UNICODE_STRING ExeName;
00023 } HISTORY_BUFFER, *PHISTORY_BUFFER;
00024 
00025 /* FUNCTIONS *****************************************************************/
00026 
00027 static PHISTORY_BUFFER
00028 HistoryCurrentBuffer(PCSRSS_CONSOLE Console)
00029 {
00030     /* TODO: use actual EXE name sent from process that called ReadConsole */
00031     UNICODE_STRING ExeName = { 14, 14, L"cmd.exe" };
00032     PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
00033     PHISTORY_BUFFER Hist;
00034 
00035     for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
00036     {
00037         Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
00038         if (RtlEqualUnicodeString(&ExeName, &Hist->ExeName, FALSE))
00039             return Hist;
00040     }
00041 
00042     /* Couldn't find the buffer, create a new one */
00043     Hist = HeapAlloc(Win32CsrApiHeap, 0, sizeof(HISTORY_BUFFER) + ExeName.Length);
00044     if (!Hist)
00045         return NULL;
00046     Hist->MaxEntries = Console->HistoryBufferSize;
00047     Hist->NumEntries = 0;
00048     Hist->Entries = HeapAlloc(Win32CsrApiHeap, 0, Hist->MaxEntries * sizeof(UNICODE_STRING));
00049     if (!Hist->Entries)
00050     {
00051         HeapFree(Win32CsrApiHeap, 0, Hist);
00052         return NULL;
00053     }
00054     Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName.Length;
00055     Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
00056     memcpy(Hist->ExeName.Buffer, ExeName.Buffer, ExeName.Length);
00057     InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
00058     return Hist;
00059 }
00060 
00061 static VOID
00062 HistoryAddEntry(PCSRSS_CONSOLE Console)
00063 {
00064     UNICODE_STRING NewEntry;
00065     PHISTORY_BUFFER Hist;
00066     INT i;
00067 
00068     NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR);
00069     NewEntry.Buffer = Console->LineBuffer;
00070 
00071     if (!(Hist = HistoryCurrentBuffer(Console)))
00072         return;
00073 
00074     /* Don't add blank or duplicate entries */
00075     if (NewEntry.Length == 0 || Hist->MaxEntries == 0 ||
00076         (Hist->NumEntries > 0 &&
00077          RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], &NewEntry, FALSE)))
00078     {
00079         return;
00080     }
00081 
00082     if (Console->HistoryNoDup)
00083     {
00084         /* Check if this line has been entered before */
00085         for (i = Hist->NumEntries - 1; i >= 0; i--)
00086         {
00087             if (RtlEqualUnicodeString(&Hist->Entries[i], &NewEntry, FALSE))
00088             {
00089                 /* Just rotate the list to bring this entry to the end */
00090                 NewEntry = Hist->Entries[i];
00091                 memmove(&Hist->Entries[i], &Hist->Entries[i + 1],
00092                         (Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING));
00093                 Hist->Entries[Hist->NumEntries - 1] = NewEntry;
00094                 Hist->Position = Hist->NumEntries - 1;
00095                 return;
00096             }
00097         }
00098     }
00099 
00100     if (Hist->NumEntries == Hist->MaxEntries)
00101     {
00102         /* List is full, remove oldest entry */
00103         RtlFreeUnicodeString(&Hist->Entries[0]);
00104         memmove(&Hist->Entries[0], &Hist->Entries[1],
00105                 --Hist->NumEntries * sizeof(UNICODE_STRING));
00106     }
00107 
00108     if (NT_SUCCESS(RtlDuplicateUnicodeString(0, &NewEntry, &Hist->Entries[Hist->NumEntries])))
00109         Hist->NumEntries++;
00110     Hist->Position = Hist->NumEntries - 1;
00111 }
00112 
00113 static VOID
00114 HistoryGetCurrentEntry(PCSRSS_CONSOLE Console, PUNICODE_STRING Entry)
00115 {
00116     PHISTORY_BUFFER Hist;
00117     if (!(Hist = HistoryCurrentBuffer(Console)) || Hist->NumEntries == 0)
00118         Entry->Length = 0;
00119     else
00120         *Entry = Hist->Entries[Hist->Position];
00121 }
00122 
00123 static PHISTORY_BUFFER
00124 HistoryFindBuffer(PCSRSS_CONSOLE Console, PUNICODE_STRING ExeName)
00125 {
00126     PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
00127     while (Entry != &Console->HistoryBuffers)
00128     {
00129         /* For the history APIs, the caller is allowed to give only part of the name */
00130         PHISTORY_BUFFER Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
00131         if (RtlPrefixUnicodeString(ExeName, &Hist->ExeName, TRUE))
00132             return Hist;
00133         Entry = Entry->Flink;
00134     }
00135     return NULL;
00136 }
00137 
00138 VOID FASTCALL
00139 HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
00140 {
00141     if (!Hist)
00142         return;
00143     while (Hist->NumEntries != 0)
00144         RtlFreeUnicodeString(&Hist->Entries[--Hist->NumEntries]);
00145     HeapFree(Win32CsrApiHeap, 0, Hist->Entries);
00146     RemoveEntryList(&Hist->ListEntry);
00147     HeapFree(Win32CsrApiHeap, 0, Hist);
00148 }
00149 
00150 CSR_API(CsrGetCommandHistoryLength)
00151 {
00152     PCSRSS_CONSOLE Console;
00153     NTSTATUS Status;
00154     PHISTORY_BUFFER Hist;
00155     ULONG Length = 0;
00156     INT i;
00157 
00158     if (!Win32CsrValidateBuffer(ProcessData,
00159                                 Request->Data.GetCommandHistoryLength.ExeName.Buffer,
00160                                 Request->Data.GetCommandHistoryLength.ExeName.Length, 1))
00161     {
00162         return STATUS_ACCESS_VIOLATION;
00163     }
00164 
00165     Status = ConioConsoleFromProcessData(ProcessData, &Console);
00166     if (NT_SUCCESS(Status))
00167     {
00168         Hist = HistoryFindBuffer(Console, &Request->Data.GetCommandHistory.ExeName);
00169         if (Hist)
00170         {
00171             for (i = 0; i < Hist->NumEntries; i++)
00172                 Length += Hist->Entries[i].Length + sizeof(WCHAR);
00173         }
00174         Request->Data.GetCommandHistoryLength.Length = Length;
00175         ConioUnlockConsole(Console);
00176     }
00177     return Status;
00178 }
00179 
00180 CSR_API(CsrGetCommandHistory)
00181 {
00182     PCSRSS_CONSOLE Console;
00183     NTSTATUS Status;
00184     PHISTORY_BUFFER Hist;
00185     PBYTE Buffer = (PBYTE)Request->Data.GetCommandHistory.History;
00186     ULONG BufferSize = Request->Data.GetCommandHistory.Length;
00187     INT i;
00188 
00189     if (!Win32CsrValidateBuffer(ProcessData, Buffer, BufferSize, 1) ||
00190         !Win32CsrValidateBuffer(ProcessData,
00191                                 Request->Data.GetCommandHistory.ExeName.Buffer,
00192                                 Request->Data.GetCommandHistory.ExeName.Length, 1))
00193     {
00194         return STATUS_ACCESS_VIOLATION;
00195     }
00196 
00197     Status = ConioConsoleFromProcessData(ProcessData, &Console);
00198     if (NT_SUCCESS(Status))
00199     {
00200         Hist = HistoryFindBuffer(Console, &Request->Data.GetCommandHistory.ExeName);
00201         if (Hist)
00202         {
00203             for (i = 0; i < Hist->NumEntries; i++)
00204             {
00205                 if (BufferSize < (Hist->Entries[i].Length + sizeof(WCHAR)))
00206                 {
00207                     Status = STATUS_BUFFER_OVERFLOW;
00208                     break;
00209                 }
00210                 memcpy(Buffer, Hist->Entries[i].Buffer, Hist->Entries[i].Length);
00211                 Buffer += Hist->Entries[i].Length;
00212                 *(PWCHAR)Buffer = L'\0';
00213                 Buffer += sizeof(WCHAR);
00214             }
00215         }
00216         Request->Data.GetCommandHistory.Length = Buffer - (PBYTE)Request->Data.GetCommandHistory.History;
00217         ConioUnlockConsole(Console);
00218     }
00219     return Status;
00220 }
00221 
00222 CSR_API(CsrExpungeCommandHistory)
00223 {
00224     PCSRSS_CONSOLE Console;
00225     PHISTORY_BUFFER Hist;
00226     NTSTATUS Status;
00227 
00228     if (!Win32CsrValidateBuffer(ProcessData,
00229                                 Request->Data.ExpungeCommandHistory.ExeName.Buffer,
00230                                 Request->Data.ExpungeCommandHistory.ExeName.Length, 1))
00231     {
00232         return STATUS_ACCESS_VIOLATION;
00233     }
00234 
00235     Status = ConioConsoleFromProcessData(ProcessData, &Console);
00236     if (NT_SUCCESS(Status))
00237     {
00238         Hist = HistoryFindBuffer(Console, &Request->Data.ExpungeCommandHistory.ExeName);
00239         HistoryDeleteBuffer(Hist);
00240         ConioUnlockConsole(Console);
00241     }
00242     return Status;
00243 }
00244 
00245 CSR_API(CsrSetHistoryNumberCommands)
00246 {
00247     PCSRSS_CONSOLE Console;
00248     PHISTORY_BUFFER Hist;
00249     NTSTATUS Status;
00250     WORD MaxEntries = Request->Data.SetHistoryNumberCommands.NumCommands;
00251     PUNICODE_STRING OldEntryList, NewEntryList;
00252 
00253     if (!Win32CsrValidateBuffer(ProcessData,
00254                                 Request->Data.SetHistoryNumberCommands.ExeName.Buffer,
00255                                 Request->Data.SetHistoryNumberCommands.ExeName.Length, 1))
00256     {
00257         return STATUS_ACCESS_VIOLATION;
00258     }
00259 
00260     Status = ConioConsoleFromProcessData(ProcessData, &Console);
00261     if (NT_SUCCESS(Status))
00262     {
00263         Hist = HistoryFindBuffer(Console, &Request->Data.SetHistoryNumberCommands.ExeName);
00264         if (Hist)
00265         {
00266             OldEntryList = Hist->Entries;
00267             NewEntryList = HeapAlloc(Win32CsrApiHeap, 0,
00268                                      MaxEntries * sizeof(UNICODE_STRING));
00269             if (!NewEntryList)
00270             {
00271                 Status = STATUS_NO_MEMORY;
00272             }
00273             else
00274             {
00275                 /* If necessary, shrink by removing oldest entries */
00276                 for (; Hist->NumEntries > MaxEntries; Hist->NumEntries--)
00277                 {
00278                     RtlFreeUnicodeString(Hist->Entries++);
00279                     Hist->Position += (Hist->Position == 0);
00280                 }
00281 
00282                 Hist->MaxEntries = MaxEntries;
00283                 Hist->Entries = memcpy(NewEntryList, Hist->Entries,
00284                                        Hist->NumEntries * sizeof(UNICODE_STRING));
00285                 HeapFree(Win32CsrApiHeap, 0, OldEntryList);
00286             }
00287         }
00288         ConioUnlockConsole(Console);
00289     }
00290     return Status;
00291 }
00292 
00293 CSR_API(CsrGetHistoryInfo)
00294 {
00295     PCSRSS_CONSOLE Console;
00296     NTSTATUS Status = ConioConsoleFromProcessData(ProcessData, &Console);
00297     if (NT_SUCCESS(Status))
00298     {
00299         Request->Data.SetHistoryInfo.HistoryBufferSize      = Console->HistoryBufferSize;
00300         Request->Data.SetHistoryInfo.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
00301         Request->Data.SetHistoryInfo.dwFlags                = Console->HistoryNoDup;
00302         ConioUnlockConsole(Console);
00303     }
00304     return Status;
00305 }
00306 
00307 CSR_API(CsrSetHistoryInfo)
00308 {
00309     PCSRSS_CONSOLE Console;
00310     NTSTATUS Status = ConioConsoleFromProcessData(ProcessData, &Console);
00311     if (NT_SUCCESS(Status))
00312     {
00313         Console->HistoryBufferSize      = (WORD)Request->Data.SetHistoryInfo.HistoryBufferSize;
00314         Console->NumberOfHistoryBuffers = (WORD)Request->Data.SetHistoryInfo.NumberOfHistoryBuffers;
00315         Console->HistoryNoDup           = Request->Data.SetHistoryInfo.dwFlags & HISTORY_NO_DUP_FLAG;
00316         ConioUnlockConsole(Console);
00317     }
00318     return Status;
00319 }
00320 
00321 static VOID
00322 LineInputSetPos(PCSRSS_CONSOLE Console, UINT Pos)
00323 {
00324     if (Pos != Console->LinePos && Console->Mode & ENABLE_ECHO_INPUT)
00325     {
00326         PCSRSS_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
00327         UINT OldCursorX = Buffer->CurrentX;
00328         UINT OldCursorY = Buffer->CurrentY;
00329         INT XY = OldCursorY * Buffer->MaxX + OldCursorX;
00330 
00331         XY += (Pos - Console->LinePos);
00332         if (XY < 0)
00333             XY = 0;
00334         else if (XY >= Buffer->MaxY * Buffer->MaxX)
00335             XY = Buffer->MaxY * Buffer->MaxX - 1;
00336 
00337         Buffer->CurrentX = XY % Buffer->MaxX;
00338         Buffer->CurrentY = XY / Buffer->MaxX;
00339         ConioSetScreenInfo(Console, Buffer, OldCursorX, OldCursorY);
00340     }
00341 
00342     Console->LinePos = Pos;
00343 }
00344 
00345 static VOID
00346 LineInputEdit(PCSRSS_CONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Insertion)
00347 {
00348     UINT Pos = Console->LinePos;
00349     UINT NewSize = Console->LineSize - NumToDelete + NumToInsert;
00350     INT i;
00351 
00352     /* Make sure there's always enough room for ending \r\n */
00353     if (NewSize + 2 > Console->LineMaxSize)
00354         return;
00355 
00356     memmove(&Console->LineBuffer[Pos + NumToInsert],
00357             &Console->LineBuffer[Pos + NumToDelete],
00358             (Console->LineSize - (Pos + NumToDelete)) * sizeof(WCHAR));
00359     memcpy(&Console->LineBuffer[Pos], Insertion, NumToInsert * sizeof(WCHAR));
00360 
00361     if (Console->Mode & ENABLE_ECHO_INPUT)
00362     {
00363         for (i = Pos; i < NewSize; i++)
00364         {
00365             CHAR AsciiChar;
00366             WideCharToMultiByte(Console->OutputCodePage, 0,
00367                                 &Console->LineBuffer[i], 1,
00368                                 &AsciiChar, 1, NULL, NULL);
00369             ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
00370         }
00371         for (; i < Console->LineSize; i++)
00372         {
00373             ConioWriteConsole(Console, Console->ActiveBuffer, " ", 1, TRUE);
00374         }
00375         Console->LinePos = i;
00376     }
00377 
00378     Console->LineSize = NewSize;
00379     LineInputSetPos(Console, Pos + NumToInsert);
00380 }
00381 
00382 static VOID
00383 LineInputRecallHistory(PCSRSS_CONSOLE Console, INT Offset)
00384 {
00385     PHISTORY_BUFFER Hist;
00386 
00387     if (!(Hist = HistoryCurrentBuffer(Console)) || Hist->NumEntries == 0)
00388         return;
00389 
00390     Offset += Hist->Position;
00391     Offset = max(Offset, 0);
00392     Offset = min(Offset, Hist->NumEntries - 1);
00393     Hist->Position = Offset;
00394 
00395     LineInputSetPos(Console, 0);
00396     LineInputEdit(Console, Console->LineSize,
00397                   Hist->Entries[Offset].Length / sizeof(WCHAR),
00398                   Hist->Entries[Offset].Buffer);
00399 }
00400 
00401 VOID FASTCALL
00402 LineInputKeyDown(PCSRSS_CONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
00403 {
00404     UINT Pos = Console->LinePos;
00405     PHISTORY_BUFFER Hist;
00406     UNICODE_STRING Entry;
00407     INT HistPos;
00408 
00409     switch (KeyEvent->wVirtualKeyCode)
00410     {
00411     case VK_ESCAPE:
00412         /* Clear entire line */
00413         LineInputSetPos(Console, 0);
00414         LineInputEdit(Console, Console->LineSize, 0, NULL);
00415         return;
00416     case VK_HOME:
00417         /* Move to start of line. With ctrl, erase everything left of cursor */
00418         LineInputSetPos(Console, 0);
00419         if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
00420             LineInputEdit(Console, Pos, 0, NULL);
00421         return;
00422     case VK_END:
00423         /* Move to end of line. With ctrl, erase everything right of cursor */
00424         if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
00425             LineInputEdit(Console, Console->LineSize - Pos, 0, NULL);
00426         else
00427             LineInputSetPos(Console, Console->LineSize);
00428         return;
00429     case VK_LEFT:
00430         /* Move left. With ctrl, move to beginning of previous word */
00431         if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
00432         {
00433             while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--;
00434             while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--;
00435         }
00436         else
00437         {
00438             Pos -= (Pos > 0);
00439         }
00440         LineInputSetPos(Console, Pos);
00441         return;
00442     case VK_RIGHT:
00443     case VK_F1:
00444         /* Move right. With ctrl, move to beginning of next word */
00445         if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
00446         {
00447             while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++;
00448             while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++;
00449             LineInputSetPos(Console, Pos);
00450             return;
00451         }
00452         else
00453         {
00454             /* Recall one character (but don't overwrite current line) */
00455             HistoryGetCurrentEntry(Console, &Entry);
00456             if (Pos < Console->LineSize)
00457                 LineInputSetPos(Console, Pos + 1);
00458             else if (Pos * sizeof(WCHAR) < Entry.Length)
00459                 LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]);
00460         }
00461         return;
00462     case VK_INSERT:
00463         /* Toggle between insert and overstrike */
00464         Console->LineInsertToggle = !Console->LineInsertToggle;
00465         ConioSetCursorInfo(Console, Console->ActiveBuffer);
00466         return;
00467     case VK_DELETE:
00468         /* Remove character to right of cursor */
00469         if (Pos != Console->LineSize)
00470             LineInputEdit(Console, 1, 0, NULL);
00471         return;
00472     case VK_PRIOR:
00473         /* Recall first history entry */
00474         LineInputRecallHistory(Console, -((WORD)-1));
00475         return;
00476     case VK_NEXT:
00477         /* Recall last history entry */
00478         LineInputRecallHistory(Console, +((WORD)-1));
00479         return;
00480     case VK_UP:
00481     case VK_F5:
00482         /* Recall previous history entry. On first time, actually recall the
00483          * current (usually last) entry; on subsequent times go back. */
00484         LineInputRecallHistory(Console, Console->LineUpPressed ? -1 : 0);
00485         Console->LineUpPressed = TRUE;
00486         return;
00487     case VK_DOWN:
00488         /* Recall next history entry */
00489         LineInputRecallHistory(Console, +1);
00490         return;
00491     case VK_F3:
00492         /* Recall remainder of current history entry */
00493         HistoryGetCurrentEntry(Console, &Entry);
00494         if (Pos * sizeof(WCHAR) < Entry.Length)
00495         {
00496             UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos);
00497             UINT DeleteSize = min(Console->LineSize - Pos, InsertSize);
00498             LineInputEdit(Console, DeleteSize, InsertSize, &Entry.Buffer[Pos]);
00499         }
00500         return;
00501     case VK_F6:
00502         /* Insert a ^Z character */
00503         KeyEvent->uChar.UnicodeChar = 26;
00504         break;
00505     case VK_F7:
00506         if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
00507             HistoryDeleteBuffer(HistoryCurrentBuffer(Console));
00508         return;
00509     case VK_F8:
00510         /* Search for history entries starting with input. */
00511         if (!(Hist = HistoryCurrentBuffer(Console)) || Hist->NumEntries == 0)
00512             return;
00513 
00514         /* Like Up/F5, on first time start from current (usually last) entry,
00515          * but on subsequent times start at previous entry. */
00516         if (Console->LineUpPressed)
00517             Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1;
00518         Console->LineUpPressed = TRUE;
00519 
00520         Entry.Length = Console->LinePos * sizeof(WCHAR);
00521         Entry.Buffer = Console->LineBuffer;
00522 
00523         /* Keep going backwards, even wrapping around to the end,
00524          * until we get back to starting point */
00525         HistPos = Hist->Position;
00526         do
00527         {
00528             if (RtlPrefixUnicodeString(&Entry, &Hist->Entries[HistPos], FALSE))
00529             {
00530                 Hist->Position = HistPos;
00531                 LineInputEdit(Console, Console->LineSize - Pos,
00532                               Hist->Entries[HistPos].Length / sizeof(WCHAR) - Pos,
00533                               &Hist->Entries[HistPos].Buffer[Pos]);
00534                 /* Cursor stays where it was */
00535                 LineInputSetPos(Console, Pos);
00536                 return;
00537             }
00538             if (--HistPos < 0) HistPos += Hist->NumEntries;
00539         } while (HistPos != Hist->Position);
00540         return;
00541     }
00542 
00543     if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->Mode & ENABLE_PROCESSED_INPUT)
00544     {
00545         /* backspace handling - if processed input enabled then we handle it here
00546          * otherwise we treat it like a normal char. */
00547         if (Pos > 0)
00548         {
00549             LineInputSetPos(Console, Pos - 1);
00550             LineInputEdit(Console, 1, 0, NULL);
00551         }
00552     }
00553     else if (KeyEvent->uChar.UnicodeChar == L'\r')
00554     {
00555         HistoryAddEntry(Console);
00556 
00557         /* TODO: Expand aliases */
00558 
00559         LineInputSetPos(Console, Console->LineSize);
00560         Console->LineBuffer[Console->LineSize++] = L'\r';
00561         if (Console->Mode & ENABLE_ECHO_INPUT)
00562             ConioWriteConsole(Console, Console->ActiveBuffer, "\r", 1, TRUE);
00563 
00564         /* Add \n if processed input. There should usually be room for it,
00565          * but an exception to the rule exists: the buffer could have been 
00566          * pre-filled with LineMaxSize - 1 characters. */
00567         if (Console->Mode & ENABLE_PROCESSED_INPUT &&
00568             Console->LineSize < Console->LineMaxSize)
00569         {
00570             Console->LineBuffer[Console->LineSize++] = L'\n';
00571             if (Console->Mode & ENABLE_ECHO_INPUT)
00572                 ConioWriteConsole(Console, Console->ActiveBuffer, "\n", 1, TRUE);
00573         }
00574         Console->LineComplete = TRUE;
00575         Console->LinePos = 0;
00576     }
00577     else if (KeyEvent->uChar.UnicodeChar != L'\0')
00578     {
00579         if (KeyEvent->uChar.UnicodeChar < 0x20 &&
00580             Console->LineWakeupMask & (1 << KeyEvent->uChar.UnicodeChar))
00581         {
00582             /* Control key client wants to handle itself (e.g. for tab completion) */
00583             Console->LineBuffer[Console->LineSize++] = L' ';
00584             Console->LineBuffer[Console->LinePos] = KeyEvent->uChar.UnicodeChar;
00585             Console->LineComplete = TRUE;
00586             Console->LinePos = 0;
00587         }
00588         else
00589         {
00590             /* Normal character */
00591             BOOL Overstrike = Console->LineInsertToggle && Console->LinePos != Console->LineSize;
00592             LineInputEdit(Console, Overstrike, 1, &KeyEvent->uChar.UnicodeChar);
00593         }
00594     }
00595 }
00596 
00597 /* EOF */

Generated on Sun May 27 2012 04:38:45 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.