2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: frontends/terminal.c
5 * PURPOSE: ConSrv terminal.
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
13 // #include "frontends/gui/guiterm.h"
14 #ifdef TUITERM_COMPILE
15 #include "frontends/tui/tuiterm.h"
25 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
27 /* GLOBALS ********************************************************************/
31 * "The lpMultiByteStr and lpWideCharStr pointers must not be the same.
32 * If they are the same, the function fails, and GetLastError returns
33 * ERROR_INVALID_PARAMETER."
35 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
36 ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \
37 WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
39 #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
40 ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \
41 MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1)
43 typedef struct ConsoleInput_t
46 INPUT_RECORD InputEvent
;
50 /* PRIVATE FUNCTIONS **********************************************************/
55 ConioInputEventToAnsi(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
57 if (InputEvent
->EventType
== KEY_EVENT
)
59 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
60 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
61 ConsoleInputUnicodeCharToAnsiChar(Console
,
62 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
68 ConioInputEventToUnicode(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
70 if (InputEvent
->EventType
== KEY_EVENT
)
72 CHAR AsciiChar
= InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
;
73 InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
= 0;
74 ConsoleInputAnsiCharToUnicodeChar(Console
,
75 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
,
82 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
91 /* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/
94 #ifdef TUITERM_COMPILE
96 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
97 IN OUT PCONSOLE_INFO ConsoleInfo
,
98 IN OUT PVOID ExtraConsoleInfo
,
101 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
);
105 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
106 IN OUT PCONSOLE_INFO ConsoleInfo
,
107 IN OUT PVOID ExtraConsoleInfo
,
110 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
);
114 NTSTATUS (NTAPI
*FRONTEND_LOAD
)(IN OUT PFRONTEND FrontEnd
,
115 IN OUT PCONSOLE_INFO ConsoleInfo
,
116 IN OUT PVOID ExtraConsoleInfo
,
120 NTSTATUS (NTAPI
*FRONTEND_UNLOAD
)(IN OUT PFRONTEND FrontEnd
);
123 * If we are not in GUI-mode, start the text-mode terminal emulator.
124 * If we fail, try to start the GUI-mode terminal emulator.
126 * Try to open the GUI-mode terminal emulator. Two cases are possible:
127 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
128 * failed and we start GUI-mode terminal emulator.
129 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
130 * succeeded BUT we failed at starting text-mode terminal emulator.
131 * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
132 * terminal emulator (Win32k will automatically switch to graphical mode,
133 * therefore no additional code is needed).
137 * NOTE: Each entry of the table should be retrieved when loading a front-end
138 * (examples of the CSR servers which register some data for CSRSS).
142 CHAR FrontEndName
[80];
143 FRONTEND_LOAD FrontEndLoad
;
144 FRONTEND_UNLOAD FrontEndUnload
;
145 } FrontEndLoadingMethods
[] =
147 #ifdef TUITERM_COMPILE
148 {"TUI", TuiLoadFrontEnd
, TuiUnloadFrontEnd
},
150 {"GUI", GuiLoadFrontEnd
, GuiUnloadFrontEnd
},
152 // {"Not found", 0, NULL}
156 ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
157 IN OUT PCONSOLE_INFO ConsoleInfo
,
158 IN OUT PVOID ExtraConsoleInfo
,
161 NTSTATUS Status
= STATUS_SUCCESS
;
165 * Choose an adequate terminal front-end to load, and load it
167 for (i
= 0; i
< sizeof(FrontEndLoadingMethods
) / sizeof(FrontEndLoadingMethods
[0]); ++i
)
169 DPRINT("CONSRV: Trying to load %s frontend...\n",
170 FrontEndLoadingMethods
[i
].FrontEndName
);
171 Status
= FrontEndLoadingMethods
[i
].FrontEndLoad(FrontEnd
,
175 if (NT_SUCCESS(Status
))
177 /* Save the unload callback */
178 FrontEnd
->UnloadFrontEnd
= FrontEndLoadingMethods
[i
].FrontEndUnload
;
180 DPRINT("CONSRV: %s frontend loaded successfully\n",
181 FrontEndLoadingMethods
[i
].FrontEndName
);
186 DPRINT1("CONSRV: Loading %s frontend failed, Status = 0x%08lx , continuing...\n",
187 FrontEndLoadingMethods
[i
].FrontEndName
, Status
);
195 ConSrvUnloadFrontEnd(IN PFRONTEND FrontEnd
)
197 if (FrontEnd
== NULL
) return STATUS_INVALID_PARAMETER
;
198 // return FrontEnd->Vtbl->UnloadFrontEnd(FrontEnd);
199 return FrontEnd
->UnloadFrontEnd(FrontEnd
);
203 static TERMINAL_VTBL ConSrvTermVtbl
;
206 ConSrvInitTerminal(IN OUT PTERMINAL Terminal
,
207 IN OUT PCONSOLE_INFO ConsoleInfo
,
208 IN OUT PVOID ExtraConsoleInfo
,
214 /* Load a suitable frontend for the ConSrv terminal */
215 FrontEnd
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, sizeof(*FrontEnd
));
216 if (!FrontEnd
) return STATUS_NO_MEMORY
;
218 Status
= ConSrvLoadFrontEnd(FrontEnd
,
222 if (!NT_SUCCESS(Status
))
224 DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status
);
225 ConsoleFreeHeap(FrontEnd
);
228 DPRINT("CONSRV: Frontend initialized\n");
230 /* Initialize the ConSrv terminal */
231 Terminal
->Vtbl
= &ConSrvTermVtbl
;
232 // Terminal->Console will be initialized by ConDrvRegisterTerminal
233 Terminal
->Context
= FrontEnd
; /* We store the frontend pointer in the terminal private context */
235 return STATUS_SUCCESS
;
239 ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal
)
241 NTSTATUS Status
= STATUS_SUCCESS
;
242 PFRONTEND FrontEnd
= Terminal
->Context
;
244 /* Reset the ConSrv terminal */
245 Terminal
->Context
= NULL
;
246 Terminal
->Vtbl
= NULL
;
248 /* Unload the frontend */
249 if (FrontEnd
!= NULL
)
251 Status
= ConSrvUnloadFrontEnd(FrontEnd
);
252 ConsoleFreeHeap(FrontEnd
);
259 /* CONSRV TERMINAL INTERFACE **************************************************/
261 static NTSTATUS NTAPI
262 ConSrvTermInitTerminal(IN OUT PTERMINAL This
,
266 PFRONTEND FrontEnd
= This
->Context
;
268 /* Initialize the console pointer for our frontend */
269 FrontEnd
->Console
= Console
;
271 /** HACK HACK!! Copy FrontEnd into the console!! **/
272 DPRINT1("Using FrontEndIFace HACK(1), should be removed after proper implementation!\n");
273 Console
->FrontEndIFace
= *FrontEnd
;
275 Status
= FrontEnd
->Vtbl
->InitFrontEnd(FrontEnd
, FrontEnd
->Console
);
276 if (!NT_SUCCESS(Status
))
277 DPRINT1("InitFrontEnd failed, Status = 0x%08lx\n", Status
);
279 /** HACK HACK!! Be sure FrontEndIFace is correctly updated in the console!! **/
280 DPRINT("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n");
281 Console
->FrontEndIFace
= *FrontEnd
;
287 ConSrvTermDeinitTerminal(IN OUT PTERMINAL This
)
289 PFRONTEND FrontEnd
= This
->Context
;
290 FrontEnd
->Vtbl
->DeinitFrontEnd(FrontEnd
);
295 /************ Line discipline ***************/
297 static NTSTATUS NTAPI
298 ConSrvTermReadStream(IN OUT PTERMINAL This
,
302 IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl
,
303 IN PVOID Parameter OPTIONAL
,
304 IN ULONG NumCharsToRead
,
305 OUT PULONG NumCharsRead OPTIONAL
)
307 PFRONTEND FrontEnd
= This
->Context
;
308 PCONSRV_CONSOLE Console
= FrontEnd
->Console
;
309 PCONSOLE_INPUT_BUFFER InputBuffer
= &Console
->InputBuffer
;
310 PUNICODE_STRING ExeName
= Parameter
;
312 // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait.
313 NTSTATUS Status
= STATUS_PENDING
;
315 PLIST_ENTRY CurrentEntry
;
319 /* Validity checks */
320 // ASSERT(Console == InputBuffer->Header.Console);
321 ASSERT((Buffer
!= NULL
) || (Buffer
== NULL
&& NumCharsToRead
== 0));
323 /* We haven't read anything (yet) */
324 i
= ReadControl
->nInitialChars
;
326 if (InputBuffer
->Mode
& ENABLE_LINE_INPUT
)
328 /* COOKED mode, call the line discipline */
330 if (Console
->LineBuffer
== NULL
)
332 /* Starting a new line */
333 Console
->LineMaxSize
= max(256, NumCharsToRead
);
335 Console
->LineBuffer
= ConsoleAllocHeap(0, Console
->LineMaxSize
* sizeof(WCHAR
));
336 if (Console
->LineBuffer
== NULL
) return STATUS_NO_MEMORY
;
338 Console
->LinePos
= Console
->LineSize
= ReadControl
->nInitialChars
;
339 Console
->LineComplete
= Console
->LineUpPressed
= FALSE
;
340 Console
->LineInsertToggle
= Console
->InsertMode
;
341 Console
->LineWakeupMask
= ReadControl
->dwCtrlWakeupMask
;
344 * Pre-filling the buffer is only allowed in the Unicode API,
345 * so we don't need to worry about ANSI <-> Unicode conversion.
347 memcpy(Console
->LineBuffer
, Buffer
, Console
->LineSize
* sizeof(WCHAR
));
348 if (Console
->LineSize
== Console
->LineMaxSize
)
350 Console
->LineComplete
= TRUE
;
351 Console
->LinePos
= 0;
355 /* If we don't have a complete line yet, process the pending input */
356 while (!Console
->LineComplete
&& !IsListEmpty(&InputBuffer
->InputEvents
))
358 /* Remove input event from queue */
359 CurrentEntry
= RemoveHeadList(&InputBuffer
->InputEvents
);
360 if (IsListEmpty(&InputBuffer
->InputEvents
))
362 ResetEvent(InputBuffer
->ActiveEvent
);
364 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
366 /* Only pay attention to key down */
367 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
368 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
370 LineInputKeyDown(Console
, ExeName
,
371 &Input
->InputEvent
.Event
.KeyEvent
);
372 ReadControl
->dwControlKeyState
= Input
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
;
374 ConsoleFreeHeap(Input
);
377 /* Check if we have a complete line to read from */
378 if (Console
->LineComplete
)
380 while (i
< NumCharsToRead
&& Console
->LinePos
!= Console
->LineSize
)
382 WCHAR Char
= Console
->LineBuffer
[Console
->LinePos
++];
386 ((PWCHAR
)Buffer
)[i
] = Char
;
390 ConsoleInputUnicodeCharToAnsiChar(Console
, &((PCHAR
)Buffer
)[i
], &Char
);
395 if (Console
->LinePos
== Console
->LineSize
)
397 /* Entire line has been read */
398 ConsoleFreeHeap(Console
->LineBuffer
);
399 Console
->LineBuffer
= NULL
;
402 Status
= STATUS_SUCCESS
;
409 /* Character input */
410 while (i
< NumCharsToRead
&& !IsListEmpty(&InputBuffer
->InputEvents
))
412 /* Remove input event from queue */
413 CurrentEntry
= RemoveHeadList(&InputBuffer
->InputEvents
);
414 if (IsListEmpty(&InputBuffer
->InputEvents
))
416 ResetEvent(InputBuffer
->ActiveEvent
);
418 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
420 /* Only pay attention to valid characters, on key down */
421 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
422 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
423 Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
!= L
'\0')
425 WCHAR Char
= Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
;
429 ((PWCHAR
)Buffer
)[i
] = Char
;
433 ConsoleInputUnicodeCharToAnsiChar(Console
, &((PCHAR
)Buffer
)[i
], &Char
);
437 /* Did read something */
438 Status
= STATUS_SUCCESS
;
440 ConsoleFreeHeap(Input
);
444 // FIXME: Only set if Status == STATUS_SUCCESS ???
445 if (NumCharsRead
) *NumCharsRead
= i
;
453 /* GLOBALS ********************************************************************/
459 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff
);
462 ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff
, PSMALL_RECT UpdateRect
, PUINT ScrolledLines
)
464 /* If we hit bottom, slide the viewable screen */
465 if (++Buff
->CursorPosition
.Y
== Buff
->ScreenBufferSize
.Y
)
467 Buff
->CursorPosition
.Y
--;
468 if (++Buff
->VirtualY
== Buff
->ScreenBufferSize
.Y
)
473 ClearLineBuffer(Buff
);
474 if (UpdateRect
->Top
!= 0)
479 UpdateRect
->Left
= 0;
480 UpdateRect
->Right
= Buff
->ScreenBufferSize
.X
- 1;
481 UpdateRect
->Bottom
= Buff
->CursorPosition
.Y
;
485 ConioWriteConsole(PFRONTEND FrontEnd
,
486 PTEXTMODE_SCREEN_BUFFER Buff
,
491 PCONSRV_CONSOLE Console
= FrontEnd
->Console
;
495 SMALL_RECT UpdateRect
;
496 SHORT CursorStartX
, CursorStartY
;
499 CursorStartX
= Buff
->CursorPosition
.X
;
500 CursorStartY
= Buff
->CursorPosition
.Y
;
501 UpdateRect
.Left
= Buff
->ScreenBufferSize
.X
;
502 UpdateRect
.Top
= Buff
->CursorPosition
.Y
;
503 UpdateRect
.Right
= -1;
504 UpdateRect
.Bottom
= Buff
->CursorPosition
.Y
;
507 for (i
= 0; i
< Length
; i
++)
510 * If we are in processed mode, interpret special characters and
511 * display them correctly. Otherwise, just put them into the buffer.
513 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
516 if (Buffer
[i
] == L
'\r')
518 Buff
->CursorPosition
.X
= 0;
519 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
520 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
524 else if (Buffer
[i
] == L
'\n')
526 Buff
->CursorPosition
.X
= 0;
527 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
531 else if (Buffer
[i
] == L
'\b')
533 /* Only handle BS if we're not on the first pos of the first line */
534 if (0 != Buff
->CursorPosition
.X
|| 0 != Buff
->CursorPosition
.Y
)
536 if (0 == Buff
->CursorPosition
.X
)
538 /* slide virtual position up */
539 Buff
->CursorPosition
.X
= Buff
->ScreenBufferSize
.X
- 1;
540 Buff
->CursorPosition
.Y
--;
541 UpdateRect
.Top
= min(UpdateRect
.Top
, Buff
->CursorPosition
.Y
);
545 Buff
->CursorPosition
.X
--;
547 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
548 Ptr
->Char
.UnicodeChar
= L
' ';
549 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
550 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
551 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
556 else if (Buffer
[i
] == L
'\t')
560 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
561 EndX
= (Buff
->CursorPosition
.X
+ TAB_WIDTH
) & ~(TAB_WIDTH
- 1);
562 EndX
= min(EndX
, (UINT
)Buff
->ScreenBufferSize
.X
);
563 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
564 while (Buff
->CursorPosition
.X
< EndX
)
566 Ptr
->Char
.UnicodeChar
= L
' ';
567 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
569 Buff
->CursorPosition
.X
++;
571 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
- 1);
572 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
574 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
576 Buff
->CursorPosition
.X
= 0;
577 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
581 Buff
->CursorPosition
.X
--;
587 else if (Buffer
[i
] == L
'\a')
589 FrontEnd
->Vtbl
->RingBell(FrontEnd
);
593 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
594 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
596 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
597 Ptr
->Char
.UnicodeChar
= Buffer
[i
];
598 if (Attrib
) Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
600 Buff
->CursorPosition
.X
++;
601 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
603 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
605 Buff
->CursorPosition
.X
= 0;
606 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
610 Buff
->CursorPosition
.X
= CursorStartX
;
615 if (!ConioIsRectEmpty(&UpdateRect
) && (PCONSOLE_SCREEN_BUFFER
)Buff
== Console
->ActiveBuffer
)
617 // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
618 // ScrolledLines, Buffer, Length);
619 FrontEnd
->Vtbl
->WriteStream(FrontEnd
,
628 return STATUS_SUCCESS
;
633 static NTSTATUS NTAPI
634 ConSrvTermWriteStream(IN OUT PTERMINAL This
,
635 PTEXTMODE_SCREEN_BUFFER Buff
,
640 PFRONTEND FrontEnd
= This
->Context
;
641 return ConioWriteConsole(FrontEnd
,
648 /************ Line discipline ***************/
653 ConioDrawConsole(PCONSRV_CONSOLE Console
)
656 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
658 if (!ActiveBuffer
) return;
660 ConioInitRect(&Region
, 0, 0,
661 ActiveBuffer
->ViewSize
.Y
- 1,
662 ActiveBuffer
->ViewSize
.X
- 1);
663 TermDrawRegion(Console
, &Region
);
664 // Console->FrontEndIFace.Vtbl->DrawRegion(&Console->FrontEndIFace, &Region);
668 ConSrvTermDrawRegion(IN OUT PTERMINAL This
,
671 PFRONTEND FrontEnd
= This
->Context
;
672 FrontEnd
->Vtbl
->DrawRegion(FrontEnd
, Region
);
676 ConSrvTermSetCursorInfo(IN OUT PTERMINAL This
,
677 PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
679 PFRONTEND FrontEnd
= This
->Context
;
680 return FrontEnd
->Vtbl
->SetCursorInfo(FrontEnd
, ScreenBuffer
);
684 ConSrvTermSetScreenInfo(IN OUT PTERMINAL This
,
685 PCONSOLE_SCREEN_BUFFER ScreenBuffer
,
689 PFRONTEND FrontEnd
= This
->Context
;
690 return FrontEnd
->Vtbl
->SetScreenInfo(FrontEnd
,
697 ConSrvTermResizeTerminal(IN OUT PTERMINAL This
)
699 PFRONTEND FrontEnd
= This
->Context
;
700 FrontEnd
->Vtbl
->ResizeTerminal(FrontEnd
);
704 ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This
)
706 PFRONTEND FrontEnd
= This
->Context
;
707 FrontEnd
->Vtbl
->SetActiveScreenBuffer(FrontEnd
);
711 ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This
,
712 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
714 PFRONTEND FrontEnd
= This
->Context
;
715 FrontEnd
->Vtbl
->ReleaseScreenBuffer(FrontEnd
, ScreenBuffer
);
719 ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This
,
722 PFRONTEND FrontEnd
= This
->Context
;
723 FrontEnd
->Vtbl
->GetLargestConsoleWindowSize(FrontEnd
, pSize
);
727 ConSrvTermSetPalette(IN OUT PTERMINAL This
,
728 HPALETTE PaletteHandle
,
731 PFRONTEND FrontEnd
= This
->Context
;
732 return FrontEnd
->Vtbl
->SetPalette(FrontEnd
, PaletteHandle
, PaletteUsage
);
736 ConSrvTermShowMouseCursor(IN OUT PTERMINAL This
,
739 PFRONTEND FrontEnd
= This
->Context
;
740 return FrontEnd
->Vtbl
->ShowMouseCursor(FrontEnd
, Show
);
743 static TERMINAL_VTBL ConSrvTermVtbl
=
745 ConSrvTermInitTerminal
,
746 ConSrvTermDeinitTerminal
,
748 ConSrvTermReadStream
,
749 ConSrvTermWriteStream
,
751 ConSrvTermDrawRegion
,
752 ConSrvTermSetCursorInfo
,
753 ConSrvTermSetScreenInfo
,
754 ConSrvTermResizeTerminal
,
755 ConSrvTermSetActiveScreenBuffer
,
756 ConSrvTermReleaseScreenBuffer
,
757 ConSrvTermGetLargestConsoleWindowSize
,
758 ConSrvTermSetPalette
,
759 ConSrvTermShowMouseCursor
,
764 ResetFrontEnd(IN PCONSOLE Console
)
766 if (!Console
) return;
768 /* Reinitialize the frontend interface */
769 RtlZeroMemory(&Console
->FrontEndIFace
, sizeof(Console
->FrontEndIFace
));
770 Console
->FrontEndIFace
.Vtbl
= &ConSrvTermVtbl
;