2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/frontends/terminal.c
5 * PURPOSE: ConSrv terminal.
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
12 #include "concfg/font.h"
14 // #include "frontends/gui/guiterm.h"
15 #ifdef TUITERM_COMPILE
16 #include "frontends/tui/tuiterm.h"
26 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
28 /* GLOBALS ********************************************************************/
32 * "The lpMultiByteStr and lpWideCharStr pointers must not be the same.
33 * If they are the same, the function fails, and GetLastError returns
34 * ERROR_INVALID_PARAMETER."
36 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
38 ASSERT((ULONG_PTR)(dChar) != (ULONG_PTR)(sWChar)); \
39 WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL); \
42 #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
44 ASSERT((ULONG_PTR)(dWChar) != (ULONG_PTR)(sChar)); \
45 MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1); \
48 /* PRIVATE FUNCTIONS **********************************************************/
53 ConioInputEventToAnsi(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
55 if (InputEvent
->EventType
== KEY_EVENT
)
57 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
58 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
59 ConsoleInputUnicodeCharToAnsiChar(Console
,
60 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
66 ConioInputEventToUnicode(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
68 if (InputEvent
->EventType
== KEY_EVENT
)
70 CHAR AsciiChar
= InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
;
71 InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
= 0;
72 ConsoleInputAnsiCharToUnicodeChar(Console
,
73 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
,
80 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
89 /* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/
92 #ifdef TUITERM_COMPILE
94 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
95 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
96 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
97 IN HANDLE ConsoleLeaderProcessHandle
);
99 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
);
103 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
104 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
105 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
106 IN HANDLE ConsoleLeaderProcessHandle
);
108 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
);
112 NTSTATUS (NTAPI
*FRONTEND_LOAD
)(IN OUT PFRONTEND FrontEnd
,
113 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
114 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
115 IN HANDLE ConsoleLeaderProcessHandle
);
118 NTSTATUS (NTAPI
*FRONTEND_UNLOAD
)(IN OUT PFRONTEND FrontEnd
);
121 * If we are not in GUI-mode, start the text-mode terminal emulator.
122 * If we fail, try to start the GUI-mode terminal emulator.
124 * Try to open the GUI-mode terminal emulator. Two cases are possible:
125 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
126 * failed and we start GUI-mode terminal emulator.
127 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
128 * succeeded BUT we failed at starting text-mode terminal emulator.
129 * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
130 * terminal emulator (Win32k will automatically switch to graphical mode,
131 * therefore no additional code is needed).
135 * NOTE: Each entry of the table should be retrieved when loading a front-end
136 * (examples of the CSR servers which register some data for CSRSS).
140 CHAR FrontEndName
[80];
141 FRONTEND_LOAD FrontEndLoad
;
142 FRONTEND_UNLOAD FrontEndUnload
;
143 } FrontEndLoadingMethods
[] =
145 #ifdef TUITERM_COMPILE
146 {"TUI", TuiLoadFrontEnd
, TuiUnloadFrontEnd
},
148 {"GUI", GuiLoadFrontEnd
, GuiUnloadFrontEnd
},
150 // {"Not found", 0, NULL}
154 ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
155 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
156 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
157 IN HANDLE ConsoleLeaderProcessHandle
)
159 NTSTATUS Status
= STATUS_SUCCESS
;
163 * Choose an adequate terminal front-end to load, and load it
165 for (i
= 0; i
< ARRAYSIZE(FrontEndLoadingMethods
); ++i
)
167 DPRINT("CONSRV: Trying to load %s frontend...\n",
168 FrontEndLoadingMethods
[i
].FrontEndName
);
169 Status
= FrontEndLoadingMethods
[i
].FrontEndLoad(FrontEnd
,
172 ConsoleLeaderProcessHandle
);
173 if (NT_SUCCESS(Status
))
175 /* Save the unload callback */
176 FrontEnd
->UnloadFrontEnd
= FrontEndLoadingMethods
[i
].FrontEndUnload
;
178 DPRINT("CONSRV: %s frontend loaded successfully\n",
179 FrontEndLoadingMethods
[i
].FrontEndName
);
184 DPRINT1("CONSRV: Loading %s frontend failed, Status = 0x%08lx , continuing...\n",
185 FrontEndLoadingMethods
[i
].FrontEndName
, Status
);
193 ConSrvUnloadFrontEnd(IN PFRONTEND FrontEnd
)
195 if (FrontEnd
== NULL
) return STATUS_INVALID_PARAMETER
;
196 // return FrontEnd->Vtbl->UnloadFrontEnd(FrontEnd);
197 return FrontEnd
->UnloadFrontEnd(FrontEnd
);
201 static TERMINAL_VTBL ConSrvTermVtbl
;
204 ConSrvInitTerminal(IN OUT PTERMINAL Terminal
,
205 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
206 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
207 IN HANDLE ConsoleLeaderProcessHandle
)
212 /* Load a suitable frontend for the ConSrv terminal */
213 FrontEnd
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, sizeof(*FrontEnd
));
214 if (!FrontEnd
) return STATUS_NO_MEMORY
;
216 Status
= ConSrvLoadFrontEnd(FrontEnd
,
219 ConsoleLeaderProcessHandle
);
220 if (!NT_SUCCESS(Status
))
222 DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status
);
223 ConsoleFreeHeap(FrontEnd
);
226 DPRINT("CONSRV: Frontend initialized\n");
228 /* Initialize the ConSrv terminal */
229 Terminal
->Vtbl
= &ConSrvTermVtbl
;
230 // Terminal->Console will be initialized by ConDrvAttachTerminal
231 Terminal
->Context
= FrontEnd
; /* We store the frontend pointer in the terminal private context */
233 return STATUS_SUCCESS
;
237 ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal
)
239 NTSTATUS Status
= STATUS_SUCCESS
;
240 PFRONTEND FrontEnd
= Terminal
->Context
;
242 /* Reset the ConSrv terminal */
243 Terminal
->Context
= NULL
;
244 Terminal
->Vtbl
= NULL
;
246 /* Unload the frontend */
247 if (FrontEnd
!= NULL
)
249 Status
= ConSrvUnloadFrontEnd(FrontEnd
);
250 ConsoleFreeHeap(FrontEnd
);
257 /* CONSRV TERMINAL INTERFACE **************************************************/
259 static NTSTATUS NTAPI
260 ConSrvTermInitTerminal(IN OUT PTERMINAL This
,
264 PFRONTEND FrontEnd
= This
->Context
;
266 /* Initialize the console pointer for our frontend */
267 FrontEnd
->Console
= Console
;
269 /** HACK HACK!! Copy FrontEnd into the console!! **/
270 DPRINT("Using FrontEndIFace HACK(1), should be removed after proper implementation!\n");
271 Console
->FrontEndIFace
= *FrontEnd
;
273 Status
= FrontEnd
->Vtbl
->InitFrontEnd(FrontEnd
, FrontEnd
->Console
);
274 if (!NT_SUCCESS(Status
))
275 DPRINT1("InitFrontEnd failed, Status = 0x%08lx\n", Status
);
277 /** HACK HACK!! Be sure FrontEndIFace is correctly updated in the console!! **/
278 DPRINT("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n");
279 Console
->FrontEndIFace
= *FrontEnd
;
285 ConSrvTermDeinitTerminal(IN OUT PTERMINAL This
)
287 PFRONTEND FrontEnd
= This
->Context
;
288 FrontEnd
->Vtbl
->DeinitFrontEnd(FrontEnd
);
293 /************ Line discipline ***************/
295 static NTSTATUS NTAPI
296 ConSrvTermReadStream(IN OUT PTERMINAL This
,
300 IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl
,
301 IN PVOID Parameter OPTIONAL
,
302 IN ULONG NumCharsToRead
,
303 OUT PULONG NumCharsRead OPTIONAL
)
305 PFRONTEND FrontEnd
= This
->Context
;
306 PCONSRV_CONSOLE Console
= FrontEnd
->Console
;
307 PCONSOLE_INPUT_BUFFER InputBuffer
= &Console
->InputBuffer
;
308 PUNICODE_STRING ExeName
= Parameter
;
310 // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait.
311 NTSTATUS Status
= STATUS_PENDING
;
313 PLIST_ENTRY CurrentEntry
;
317 /* Validity checks */
318 // ASSERT(Console == InputBuffer->Header.Console);
319 ASSERT((Buffer
!= NULL
) || (Buffer
== NULL
&& NumCharsToRead
== 0));
321 /* We haven't read anything (yet) */
323 if (InputBuffer
->Mode
& ENABLE_LINE_INPUT
)
325 /* COOKED mode, call the line discipline */
327 if (Console
->LineBuffer
== NULL
)
329 /* Start a new line */
330 Console
->LineMaxSize
= max(256, NumCharsToRead
);
333 * Fixup ReadControl->nInitialChars in case the number of initial
334 * characters is bigger than the number of characters to be read.
335 * It will always be, lesser than or equal to Console->LineMaxSize.
337 ReadControl
->nInitialChars
= min(ReadControl
->nInitialChars
, NumCharsToRead
);
339 Console
->LineBuffer
= ConsoleAllocHeap(0, Console
->LineMaxSize
* sizeof(WCHAR
));
340 if (Console
->LineBuffer
== NULL
) return STATUS_NO_MEMORY
;
342 Console
->LinePos
= Console
->LineSize
= ReadControl
->nInitialChars
;
343 Console
->LineComplete
= Console
->LineUpPressed
= FALSE
;
344 Console
->LineInsertToggle
= Console
->InsertMode
;
345 Console
->LineWakeupMask
= ReadControl
->dwCtrlWakeupMask
;
348 * Pre-fill the buffer with the nInitialChars from the user buffer.
349 * Since pre-filling is only allowed in Unicode, we don't need to
350 * worry about ANSI <-> Unicode conversion.
352 memcpy(Console
->LineBuffer
, Buffer
, Console
->LineSize
* sizeof(WCHAR
));
353 if (Console
->LineSize
>= Console
->LineMaxSize
)
355 Console
->LineComplete
= TRUE
;
356 Console
->LinePos
= 0;
360 /* If we don't have a complete line yet, process the pending input */
361 while (!Console
->LineComplete
&& !IsListEmpty(&InputBuffer
->InputEvents
))
363 /* Remove an input event from the queue */
364 CurrentEntry
= RemoveHeadList(&InputBuffer
->InputEvents
);
365 if (IsListEmpty(&InputBuffer
->InputEvents
))
367 ResetEvent(InputBuffer
->ActiveEvent
);
369 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
371 /* Only pay attention to key down */
372 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
373 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
375 LineInputKeyDown(Console
, ExeName
,
376 &Input
->InputEvent
.Event
.KeyEvent
);
377 ReadControl
->dwControlKeyState
= Input
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
;
379 ConsoleFreeHeap(Input
);
382 /* Check if we have a complete line to read from */
383 if (Console
->LineComplete
)
386 * Console->LinePos keeps the next position of the character to read
387 * in the line buffer across the different calls of the function,
388 * so that the line buffer can be read by chunks after all the input
392 while (i
< NumCharsToRead
&& Console
->LinePos
< Console
->LineSize
)
394 WCHAR Char
= Console
->LineBuffer
[Console
->LinePos
++];
398 ((PWCHAR
)Buffer
)[i
] = Char
;
402 ConsoleInputUnicodeCharToAnsiChar(Console
, &((PCHAR
)Buffer
)[i
], &Char
);
407 if (Console
->LinePos
>= Console
->LineSize
)
409 /* The entire line has been read */
410 ConsoleFreeHeap(Console
->LineBuffer
);
411 Console
->LineBuffer
= NULL
;
412 Console
->LinePos
= Console
->LineMaxSize
= Console
->LineSize
= 0;
413 // Console->LineComplete = Console->LineUpPressed = FALSE;
414 Console
->LineComplete
= FALSE
;
417 Status
= STATUS_SUCCESS
;
424 /* Character input */
425 while (i
< NumCharsToRead
&& !IsListEmpty(&InputBuffer
->InputEvents
))
427 /* Remove an input event from the queue */
428 CurrentEntry
= RemoveHeadList(&InputBuffer
->InputEvents
);
429 if (IsListEmpty(&InputBuffer
->InputEvents
))
431 ResetEvent(InputBuffer
->ActiveEvent
);
433 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
435 /* Only pay attention to valid characters, on key down */
436 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
437 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
438 Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
!= L
'\0')
440 WCHAR Char
= Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
;
444 ((PWCHAR
)Buffer
)[i
] = Char
;
448 ConsoleInputUnicodeCharToAnsiChar(Console
, &((PCHAR
)Buffer
)[i
], &Char
);
452 /* Did read something */
453 Status
= STATUS_SUCCESS
;
455 ConsoleFreeHeap(Input
);
459 // FIXME: Only set if Status == STATUS_SUCCESS ???
460 if (NumCharsRead
) *NumCharsRead
= i
;
468 /* GLOBALS ********************************************************************/
474 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff
);
477 ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff
, PSMALL_RECT UpdateRect
, PUINT ScrolledLines
)
479 /* If we hit bottom, slide the viewable screen */
480 if (++Buff
->CursorPosition
.Y
== Buff
->ScreenBufferSize
.Y
)
482 Buff
->CursorPosition
.Y
--;
483 if (++Buff
->VirtualY
== Buff
->ScreenBufferSize
.Y
)
488 ClearLineBuffer(Buff
);
489 if (UpdateRect
->Top
!= 0)
494 UpdateRect
->Left
= 0;
495 UpdateRect
->Right
= Buff
->ScreenBufferSize
.X
- 1;
496 UpdateRect
->Bottom
= Buff
->CursorPosition
.Y
;
500 ConioWriteConsole(PFRONTEND FrontEnd
,
501 PTEXTMODE_SCREEN_BUFFER Buff
,
506 PCONSRV_CONSOLE Console
= FrontEnd
->Console
;
510 SMALL_RECT UpdateRect
;
511 SHORT CursorStartX
, CursorStartY
;
513 BOOL bCJK
= Console
->IsCJK
;
515 CursorStartX
= Buff
->CursorPosition
.X
;
516 CursorStartY
= Buff
->CursorPosition
.Y
;
517 UpdateRect
.Left
= Buff
->ScreenBufferSize
.X
;
518 UpdateRect
.Top
= Buff
->CursorPosition
.Y
;
519 UpdateRect
.Right
= -1;
520 UpdateRect
.Bottom
= Buff
->CursorPosition
.Y
;
523 for (i
= 0; i
< Length
; i
++)
526 * If we are in processed mode, interpret special characters and
527 * display them correctly. Otherwise, just put them into the buffer.
529 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
532 if (Buffer
[i
] == L
'\r')
534 Buff
->CursorPosition
.X
= 0;
535 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
536 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
540 else if (Buffer
[i
] == L
'\n')
542 Buff
->CursorPosition
.X
= 0;
543 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
547 else if (Buffer
[i
] == L
'\b')
549 /* Only handle BS if we're not on the first pos of the first line */
550 if (0 != Buff
->CursorPosition
.X
|| 0 != Buff
->CursorPosition
.Y
)
552 if (0 == Buff
->CursorPosition
.X
)
554 /* slide virtual position up */
555 Buff
->CursorPosition
.X
= Buff
->ScreenBufferSize
.X
- 1;
556 Buff
->CursorPosition
.Y
--;
557 UpdateRect
.Top
= min(UpdateRect
.Top
, Buff
->CursorPosition
.Y
);
561 Buff
->CursorPosition
.X
--;
563 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
564 Ptr
->Char
.UnicodeChar
= L
' ';
566 if (Ptr
->Attributes
& COMMON_LVB_TRAILING_BYTE
)
568 /* Delete a full-width character */
569 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
570 if (Buff
->CursorPosition
.X
> 0)
571 Buff
->CursorPosition
.X
--;
572 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
573 Ptr
->Char
.UnicodeChar
= L
' ';
576 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
577 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
578 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
583 else if (Buffer
[i
] == L
'\t')
587 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
588 EndX
= (Buff
->CursorPosition
.X
+ TAB_WIDTH
) & ~(TAB_WIDTH
- 1);
589 EndX
= min(EndX
, (UINT
)Buff
->ScreenBufferSize
.X
);
590 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
591 while ((UINT
)Buff
->CursorPosition
.X
< EndX
)
593 Ptr
->Char
.UnicodeChar
= L
' ';
594 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
596 Buff
->CursorPosition
.X
++;
598 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
- 1);
599 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
601 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
603 Buff
->CursorPosition
.X
= 0;
604 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
608 Buff
->CursorPosition
.X
--;
614 else if (Buffer
[i
] == L
'\a')
616 FrontEnd
->Vtbl
->RingBell(FrontEnd
);
620 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
621 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
623 /* For Chinese, Japanese and Korean */
624 if (bCJK
&& Buffer
[i
] >= 0x80 && mk_wcwidth_cjk(Buffer
[i
]) == 2)
626 /* Buffer[i] is a fullwidth character */
628 if (Buff
->CursorPosition
.X
> 0)
630 /* Kill the previous leading byte */
631 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
- 1, Buff
->CursorPosition
.Y
);
632 if (Ptr
->Attributes
& COMMON_LVB_LEADING_BYTE
)
634 Ptr
->Char
.UnicodeChar
= L
' ';
636 Ptr
->Attributes
&= ~COMMON_LVB_LEADING_BYTE
;
640 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
- 1)
643 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
645 Buff
->CursorPosition
.X
= 0;
646 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
650 Buff
->CursorPosition
.X
= CursorStartX
;
655 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
656 Ptr
->Char
.UnicodeChar
= Buffer
[i
];
658 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
| COMMON_LVB_LEADING_BYTE
;
661 Buff
->CursorPosition
.X
++;
662 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
664 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
| COMMON_LVB_TRAILING_BYTE
;
668 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
669 Ptr
->Char
.UnicodeChar
= Buffer
[i
];
671 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
674 Buff
->CursorPosition
.X
++;
675 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
677 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
679 Buff
->CursorPosition
.X
= 0;
680 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
684 Buff
->CursorPosition
.X
= CursorStartX
;
689 if (bCJK
&& Buff
->CursorPosition
.X
> 0)
691 /* Delete trailing */
692 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
693 if (Ptr
->Attributes
& COMMON_LVB_TRAILING_BYTE
)
695 Ptr
->Char
.UnicodeChar
= L
' ';
697 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
701 if (!ConioIsRectEmpty(&UpdateRect
) && (PCONSOLE_SCREEN_BUFFER
)Buff
== Console
->ActiveBuffer
)
703 // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
704 // ScrolledLines, Buffer, Length);
705 FrontEnd
->Vtbl
->WriteStream(FrontEnd
,
714 return STATUS_SUCCESS
;
719 static NTSTATUS NTAPI
720 ConSrvTermWriteStream(IN OUT PTERMINAL This
,
721 PTEXTMODE_SCREEN_BUFFER Buff
,
726 PFRONTEND FrontEnd
= This
->Context
;
727 return ConioWriteConsole(FrontEnd
,
734 /************ Line discipline ***************/
739 ConioDrawConsole(PCONSRV_CONSOLE Console
)
742 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
744 if (!ActiveBuffer
) return;
746 ConioInitRect(&Region
, 0, 0,
747 ActiveBuffer
->ViewSize
.Y
- 1,
748 ActiveBuffer
->ViewSize
.X
- 1);
749 TermDrawRegion(Console
, &Region
);
750 // Console->FrontEndIFace.Vtbl->DrawRegion(&Console->FrontEndIFace, &Region);
754 ConSrvTermDrawRegion(IN OUT PTERMINAL This
,
757 PFRONTEND FrontEnd
= This
->Context
;
758 FrontEnd
->Vtbl
->DrawRegion(FrontEnd
, Region
);
762 ConSrvTermSetCursorInfo(IN OUT PTERMINAL This
,
763 PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
765 PFRONTEND FrontEnd
= This
->Context
;
766 return FrontEnd
->Vtbl
->SetCursorInfo(FrontEnd
, ScreenBuffer
);
770 ConSrvTermSetScreenInfo(IN OUT PTERMINAL This
,
771 PCONSOLE_SCREEN_BUFFER ScreenBuffer
,
775 PFRONTEND FrontEnd
= This
->Context
;
776 return FrontEnd
->Vtbl
->SetScreenInfo(FrontEnd
,
783 ConSrvTermResizeTerminal(IN OUT PTERMINAL This
)
785 PFRONTEND FrontEnd
= This
->Context
;
786 FrontEnd
->Vtbl
->ResizeTerminal(FrontEnd
);
790 ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This
)
792 PFRONTEND FrontEnd
= This
->Context
;
793 FrontEnd
->Vtbl
->SetActiveScreenBuffer(FrontEnd
);
797 ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This
,
798 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
800 PFRONTEND FrontEnd
= This
->Context
;
801 FrontEnd
->Vtbl
->ReleaseScreenBuffer(FrontEnd
, ScreenBuffer
);
805 ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This
,
808 PFRONTEND FrontEnd
= This
->Context
;
809 FrontEnd
->Vtbl
->GetLargestConsoleWindowSize(FrontEnd
, pSize
);
813 ConSrvTermSetPalette(IN OUT PTERMINAL This
,
814 HPALETTE PaletteHandle
,
817 PFRONTEND FrontEnd
= This
->Context
;
818 return FrontEnd
->Vtbl
->SetPalette(FrontEnd
, PaletteHandle
, PaletteUsage
);
822 ConSrvTermShowMouseCursor(IN OUT PTERMINAL This
,
825 PFRONTEND FrontEnd
= This
->Context
;
826 return FrontEnd
->Vtbl
->ShowMouseCursor(FrontEnd
, Show
);
829 static TERMINAL_VTBL ConSrvTermVtbl
=
831 ConSrvTermInitTerminal
,
832 ConSrvTermDeinitTerminal
,
834 ConSrvTermReadStream
,
835 ConSrvTermWriteStream
,
837 ConSrvTermDrawRegion
,
838 ConSrvTermSetCursorInfo
,
839 ConSrvTermSetScreenInfo
,
840 ConSrvTermResizeTerminal
,
841 ConSrvTermSetActiveScreenBuffer
,
842 ConSrvTermReleaseScreenBuffer
,
843 ConSrvTermGetLargestConsoleWindowSize
,
844 ConSrvTermSetPalette
,
845 ConSrvTermShowMouseCursor
,
850 ResetFrontEnd(IN PCONSOLE Console
)
852 if (!Console
) return;
854 /* Reinitialize the frontend interface */
855 RtlZeroMemory(&Console
->FrontEndIFace
, sizeof(Console
->FrontEndIFace
));
856 Console
->FrontEndIFace
.Vtbl
= &ConSrvTermVtbl
;