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) \
37 ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \
38 WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
40 #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
41 ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \
42 MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1)
44 /* PRIVATE FUNCTIONS **********************************************************/
49 ConioInputEventToAnsi(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
51 if (InputEvent
->EventType
== KEY_EVENT
)
53 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
54 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
55 ConsoleInputUnicodeCharToAnsiChar(Console
,
56 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
62 ConioInputEventToUnicode(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
64 if (InputEvent
->EventType
== KEY_EVENT
)
66 CHAR AsciiChar
= InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
;
67 InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
= 0;
68 ConsoleInputAnsiCharToUnicodeChar(Console
,
69 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
,
76 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
85 /* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/
88 #ifdef TUITERM_COMPILE
90 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
91 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
92 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
93 IN HANDLE ConsoleLeaderProcessHandle
);
95 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
);
99 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
100 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
101 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
102 IN HANDLE ConsoleLeaderProcessHandle
);
104 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
);
108 NTSTATUS (NTAPI
*FRONTEND_LOAD
)(IN OUT PFRONTEND FrontEnd
,
109 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
110 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
111 IN HANDLE ConsoleLeaderProcessHandle
);
114 NTSTATUS (NTAPI
*FRONTEND_UNLOAD
)(IN OUT PFRONTEND FrontEnd
);
117 * If we are not in GUI-mode, start the text-mode terminal emulator.
118 * If we fail, try to start the GUI-mode terminal emulator.
120 * Try to open the GUI-mode terminal emulator. Two cases are possible:
121 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
122 * failed and we start GUI-mode terminal emulator.
123 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
124 * succeeded BUT we failed at starting text-mode terminal emulator.
125 * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
126 * terminal emulator (Win32k will automatically switch to graphical mode,
127 * therefore no additional code is needed).
131 * NOTE: Each entry of the table should be retrieved when loading a front-end
132 * (examples of the CSR servers which register some data for CSRSS).
136 CHAR FrontEndName
[80];
137 FRONTEND_LOAD FrontEndLoad
;
138 FRONTEND_UNLOAD FrontEndUnload
;
139 } FrontEndLoadingMethods
[] =
141 #ifdef TUITERM_COMPILE
142 {"TUI", TuiLoadFrontEnd
, TuiUnloadFrontEnd
},
144 {"GUI", GuiLoadFrontEnd
, GuiUnloadFrontEnd
},
146 // {"Not found", 0, NULL}
150 ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
151 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
152 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
153 IN HANDLE ConsoleLeaderProcessHandle
)
155 NTSTATUS Status
= STATUS_SUCCESS
;
159 * Choose an adequate terminal front-end to load, and load it
161 for (i
= 0; i
< ARRAYSIZE(FrontEndLoadingMethods
); ++i
)
163 DPRINT("CONSRV: Trying to load %s frontend...\n",
164 FrontEndLoadingMethods
[i
].FrontEndName
);
165 Status
= FrontEndLoadingMethods
[i
].FrontEndLoad(FrontEnd
,
168 ConsoleLeaderProcessHandle
);
169 if (NT_SUCCESS(Status
))
171 /* Save the unload callback */
172 FrontEnd
->UnloadFrontEnd
= FrontEndLoadingMethods
[i
].FrontEndUnload
;
174 DPRINT("CONSRV: %s frontend loaded successfully\n",
175 FrontEndLoadingMethods
[i
].FrontEndName
);
180 DPRINT1("CONSRV: Loading %s frontend failed, Status = 0x%08lx , continuing...\n",
181 FrontEndLoadingMethods
[i
].FrontEndName
, Status
);
189 ConSrvUnloadFrontEnd(IN PFRONTEND FrontEnd
)
191 if (FrontEnd
== NULL
) return STATUS_INVALID_PARAMETER
;
192 // return FrontEnd->Vtbl->UnloadFrontEnd(FrontEnd);
193 return FrontEnd
->UnloadFrontEnd(FrontEnd
);
197 static TERMINAL_VTBL ConSrvTermVtbl
;
200 ConSrvInitTerminal(IN OUT PTERMINAL Terminal
,
201 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
202 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
203 IN HANDLE ConsoleLeaderProcessHandle
)
208 /* Load a suitable frontend for the ConSrv terminal */
209 FrontEnd
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, sizeof(*FrontEnd
));
210 if (!FrontEnd
) return STATUS_NO_MEMORY
;
212 Status
= ConSrvLoadFrontEnd(FrontEnd
,
215 ConsoleLeaderProcessHandle
);
216 if (!NT_SUCCESS(Status
))
218 DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status
);
219 ConsoleFreeHeap(FrontEnd
);
222 DPRINT("CONSRV: Frontend initialized\n");
224 /* Initialize the ConSrv terminal */
225 Terminal
->Vtbl
= &ConSrvTermVtbl
;
226 // Terminal->Console will be initialized by ConDrvAttachTerminal
227 Terminal
->Context
= FrontEnd
; /* We store the frontend pointer in the terminal private context */
229 return STATUS_SUCCESS
;
233 ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal
)
235 NTSTATUS Status
= STATUS_SUCCESS
;
236 PFRONTEND FrontEnd
= Terminal
->Context
;
238 /* Reset the ConSrv terminal */
239 Terminal
->Context
= NULL
;
240 Terminal
->Vtbl
= NULL
;
242 /* Unload the frontend */
243 if (FrontEnd
!= NULL
)
245 Status
= ConSrvUnloadFrontEnd(FrontEnd
);
246 ConsoleFreeHeap(FrontEnd
);
253 /* CONSRV TERMINAL INTERFACE **************************************************/
255 static NTSTATUS NTAPI
256 ConSrvTermInitTerminal(IN OUT PTERMINAL This
,
260 PFRONTEND FrontEnd
= This
->Context
;
262 /* Initialize the console pointer for our frontend */
263 FrontEnd
->Console
= Console
;
265 /** HACK HACK!! Copy FrontEnd into the console!! **/
266 DPRINT("Using FrontEndIFace HACK(1), should be removed after proper implementation!\n");
267 Console
->FrontEndIFace
= *FrontEnd
;
269 Status
= FrontEnd
->Vtbl
->InitFrontEnd(FrontEnd
, FrontEnd
->Console
);
270 if (!NT_SUCCESS(Status
))
271 DPRINT1("InitFrontEnd failed, Status = 0x%08lx\n", Status
);
273 /** HACK HACK!! Be sure FrontEndIFace is correctly updated in the console!! **/
274 DPRINT("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n");
275 Console
->FrontEndIFace
= *FrontEnd
;
281 ConSrvTermDeinitTerminal(IN OUT PTERMINAL This
)
283 PFRONTEND FrontEnd
= This
->Context
;
284 FrontEnd
->Vtbl
->DeinitFrontEnd(FrontEnd
);
289 /************ Line discipline ***************/
291 static NTSTATUS NTAPI
292 ConSrvTermReadStream(IN OUT PTERMINAL This
,
296 IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl
,
297 IN PVOID Parameter OPTIONAL
,
298 IN ULONG NumCharsToRead
,
299 OUT PULONG NumCharsRead OPTIONAL
)
301 PFRONTEND FrontEnd
= This
->Context
;
302 PCONSRV_CONSOLE Console
= FrontEnd
->Console
;
303 PCONSOLE_INPUT_BUFFER InputBuffer
= &Console
->InputBuffer
;
304 PUNICODE_STRING ExeName
= Parameter
;
306 // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait.
307 NTSTATUS Status
= STATUS_PENDING
;
309 PLIST_ENTRY CurrentEntry
;
313 /* Validity checks */
314 // ASSERT(Console == InputBuffer->Header.Console);
315 ASSERT((Buffer
!= NULL
) || (Buffer
== NULL
&& NumCharsToRead
== 0));
317 /* We haven't read anything (yet) */
319 if (InputBuffer
->Mode
& ENABLE_LINE_INPUT
)
321 /* COOKED mode, call the line discipline */
323 if (Console
->LineBuffer
== NULL
)
325 /* Start a new line */
326 Console
->LineMaxSize
= max(256, NumCharsToRead
);
329 * Fixup ReadControl->nInitialChars in case the number of initial
330 * characters is bigger than the number of characters to be read.
331 * It will always be, lesser than or equal to Console->LineMaxSize.
333 ReadControl
->nInitialChars
= min(ReadControl
->nInitialChars
, 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-fill the buffer with the nInitialChars from the user buffer.
345 * Since pre-filling is only allowed in Unicode, we don't need to
346 * worry about ANSI <-> Unicode conversion.
348 memcpy(Console
->LineBuffer
, Buffer
, Console
->LineSize
* sizeof(WCHAR
));
349 if (Console
->LineSize
>= Console
->LineMaxSize
)
351 Console
->LineComplete
= TRUE
;
352 Console
->LinePos
= 0;
356 /* If we don't have a complete line yet, process the pending input */
357 while (!Console
->LineComplete
&& !IsListEmpty(&InputBuffer
->InputEvents
))
359 /* Remove an input event from the queue */
360 CurrentEntry
= RemoveHeadList(&InputBuffer
->InputEvents
);
361 if (IsListEmpty(&InputBuffer
->InputEvents
))
363 ResetEvent(InputBuffer
->ActiveEvent
);
365 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
367 /* Only pay attention to key down */
368 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
369 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
371 LineInputKeyDown(Console
, ExeName
,
372 &Input
->InputEvent
.Event
.KeyEvent
);
373 ReadControl
->dwControlKeyState
= Input
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
;
375 ConsoleFreeHeap(Input
);
378 /* Check if we have a complete line to read from */
379 if (Console
->LineComplete
)
382 * Console->LinePos keeps the next position of the character to read
383 * in the line buffer across the different calls of the function,
384 * so that the line buffer can be read by chunks after all the input
388 while (i
< NumCharsToRead
&& Console
->LinePos
< Console
->LineSize
)
390 WCHAR Char
= Console
->LineBuffer
[Console
->LinePos
++];
394 ((PWCHAR
)Buffer
)[i
] = Char
;
398 ConsoleInputUnicodeCharToAnsiChar(Console
, &((PCHAR
)Buffer
)[i
], &Char
);
403 if (Console
->LinePos
>= Console
->LineSize
)
405 /* The entire line has been read */
406 ConsoleFreeHeap(Console
->LineBuffer
);
407 Console
->LineBuffer
= NULL
;
408 Console
->LinePos
= Console
->LineMaxSize
= Console
->LineSize
= 0;
409 // Console->LineComplete = Console->LineUpPressed = FALSE;
410 Console
->LineComplete
= FALSE
;
413 Status
= STATUS_SUCCESS
;
420 /* Character input */
421 while (i
< NumCharsToRead
&& !IsListEmpty(&InputBuffer
->InputEvents
))
423 /* Remove an input event from the queue */
424 CurrentEntry
= RemoveHeadList(&InputBuffer
->InputEvents
);
425 if (IsListEmpty(&InputBuffer
->InputEvents
))
427 ResetEvent(InputBuffer
->ActiveEvent
);
429 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
431 /* Only pay attention to valid characters, on key down */
432 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
433 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
434 Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
!= L
'\0')
436 WCHAR Char
= Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
;
440 ((PWCHAR
)Buffer
)[i
] = Char
;
444 ConsoleInputUnicodeCharToAnsiChar(Console
, &((PCHAR
)Buffer
)[i
], &Char
);
448 /* Did read something */
449 Status
= STATUS_SUCCESS
;
451 ConsoleFreeHeap(Input
);
455 // FIXME: Only set if Status == STATUS_SUCCESS ???
456 if (NumCharsRead
) *NumCharsRead
= i
;
464 /* GLOBALS ********************************************************************/
470 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff
);
473 ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff
, PSMALL_RECT UpdateRect
, PUINT ScrolledLines
)
475 /* If we hit bottom, slide the viewable screen */
476 if (++Buff
->CursorPosition
.Y
== Buff
->ScreenBufferSize
.Y
)
478 Buff
->CursorPosition
.Y
--;
479 if (++Buff
->VirtualY
== Buff
->ScreenBufferSize
.Y
)
484 ClearLineBuffer(Buff
);
485 if (UpdateRect
->Top
!= 0)
490 UpdateRect
->Left
= 0;
491 UpdateRect
->Right
= Buff
->ScreenBufferSize
.X
- 1;
492 UpdateRect
->Bottom
= Buff
->CursorPosition
.Y
;
496 ConioWriteConsole(PFRONTEND FrontEnd
,
497 PTEXTMODE_SCREEN_BUFFER Buff
,
502 PCONSRV_CONSOLE Console
= FrontEnd
->Console
;
506 SMALL_RECT UpdateRect
;
507 SHORT CursorStartX
, CursorStartY
;
509 BOOL bCJK
= Console
->IsCJK
;
511 CursorStartX
= Buff
->CursorPosition
.X
;
512 CursorStartY
= Buff
->CursorPosition
.Y
;
513 UpdateRect
.Left
= Buff
->ScreenBufferSize
.X
;
514 UpdateRect
.Top
= Buff
->CursorPosition
.Y
;
515 UpdateRect
.Right
= -1;
516 UpdateRect
.Bottom
= Buff
->CursorPosition
.Y
;
519 for (i
= 0; i
< Length
; i
++)
522 * If we are in processed mode, interpret special characters and
523 * display them correctly. Otherwise, just put them into the buffer.
525 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
528 if (Buffer
[i
] == L
'\r')
530 Buff
->CursorPosition
.X
= 0;
531 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
532 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
536 else if (Buffer
[i
] == L
'\n')
538 Buff
->CursorPosition
.X
= 0;
539 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
543 else if (Buffer
[i
] == L
'\b')
545 /* Only handle BS if we're not on the first pos of the first line */
546 if (0 != Buff
->CursorPosition
.X
|| 0 != Buff
->CursorPosition
.Y
)
548 if (0 == Buff
->CursorPosition
.X
)
550 /* slide virtual position up */
551 Buff
->CursorPosition
.X
= Buff
->ScreenBufferSize
.X
- 1;
552 Buff
->CursorPosition
.Y
--;
553 UpdateRect
.Top
= min(UpdateRect
.Top
, Buff
->CursorPosition
.Y
);
557 Buff
->CursorPosition
.X
--;
559 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
560 Ptr
->Char
.UnicodeChar
= L
' ';
562 if (Ptr
->Attributes
& COMMON_LVB_TRAILING_BYTE
)
564 /* Delete a full-width character */
565 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
566 if (Buff
->CursorPosition
.X
> 0)
567 Buff
->CursorPosition
.X
--;
568 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
569 Ptr
->Char
.UnicodeChar
= L
' ';
572 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
573 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
574 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
579 else if (Buffer
[i
] == L
'\t')
583 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
584 EndX
= (Buff
->CursorPosition
.X
+ TAB_WIDTH
) & ~(TAB_WIDTH
- 1);
585 EndX
= min(EndX
, (UINT
)Buff
->ScreenBufferSize
.X
);
586 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
587 while ((UINT
)Buff
->CursorPosition
.X
< EndX
)
589 Ptr
->Char
.UnicodeChar
= L
' ';
590 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
592 Buff
->CursorPosition
.X
++;
594 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
- 1);
595 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
597 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
599 Buff
->CursorPosition
.X
= 0;
600 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
604 Buff
->CursorPosition
.X
--;
610 else if (Buffer
[i
] == L
'\a')
612 FrontEnd
->Vtbl
->RingBell(FrontEnd
);
616 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
617 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
619 /* For Chinese, Japanese and Korean */
620 if (bCJK
&& Buffer
[i
] >= 0x80 && mk_wcwidth_cjk(Buffer
[i
]) == 2)
622 /* Buffer[i] is a fullwidth character */
624 if (Buff
->CursorPosition
.X
> 0)
626 /* Kill the previous leading byte */
627 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
- 1, Buff
->CursorPosition
.Y
);
628 if (Ptr
->Attributes
& COMMON_LVB_LEADING_BYTE
)
630 Ptr
->Char
.UnicodeChar
= L
' ';
632 Ptr
->Attributes
&= ~COMMON_LVB_LEADING_BYTE
;
636 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
- 1)
639 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
641 Buff
->CursorPosition
.X
= 0;
642 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
646 Buff
->CursorPosition
.X
= CursorStartX
;
651 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
652 Ptr
->Char
.UnicodeChar
= Buffer
[i
];
654 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
| COMMON_LVB_LEADING_BYTE
;
657 Buff
->CursorPosition
.X
++;
658 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
660 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
| COMMON_LVB_TRAILING_BYTE
;
664 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
665 Ptr
->Char
.UnicodeChar
= Buffer
[i
];
667 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
670 Buff
->CursorPosition
.X
++;
671 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
673 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
675 Buff
->CursorPosition
.X
= 0;
676 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
680 Buff
->CursorPosition
.X
= CursorStartX
;
685 if (bCJK
&& Buff
->CursorPosition
.X
> 0)
687 /* Delete trailing */
688 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
689 if (Ptr
->Attributes
& COMMON_LVB_TRAILING_BYTE
)
691 Ptr
->Char
.UnicodeChar
= L
' ';
693 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
697 if (!ConioIsRectEmpty(&UpdateRect
) && (PCONSOLE_SCREEN_BUFFER
)Buff
== Console
->ActiveBuffer
)
699 // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
700 // ScrolledLines, Buffer, Length);
701 FrontEnd
->Vtbl
->WriteStream(FrontEnd
,
710 return STATUS_SUCCESS
;
715 static NTSTATUS NTAPI
716 ConSrvTermWriteStream(IN OUT PTERMINAL This
,
717 PTEXTMODE_SCREEN_BUFFER Buff
,
722 PFRONTEND FrontEnd
= This
->Context
;
723 return ConioWriteConsole(FrontEnd
,
730 /************ Line discipline ***************/
735 ConioDrawConsole(PCONSRV_CONSOLE Console
)
738 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
740 if (!ActiveBuffer
) return;
742 ConioInitRect(&Region
, 0, 0,
743 ActiveBuffer
->ViewSize
.Y
- 1,
744 ActiveBuffer
->ViewSize
.X
- 1);
745 TermDrawRegion(Console
, &Region
);
746 // Console->FrontEndIFace.Vtbl->DrawRegion(&Console->FrontEndIFace, &Region);
750 ConSrvTermDrawRegion(IN OUT PTERMINAL This
,
753 PFRONTEND FrontEnd
= This
->Context
;
754 FrontEnd
->Vtbl
->DrawRegion(FrontEnd
, Region
);
758 ConSrvTermSetCursorInfo(IN OUT PTERMINAL This
,
759 PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
761 PFRONTEND FrontEnd
= This
->Context
;
762 return FrontEnd
->Vtbl
->SetCursorInfo(FrontEnd
, ScreenBuffer
);
766 ConSrvTermSetScreenInfo(IN OUT PTERMINAL This
,
767 PCONSOLE_SCREEN_BUFFER ScreenBuffer
,
771 PFRONTEND FrontEnd
= This
->Context
;
772 return FrontEnd
->Vtbl
->SetScreenInfo(FrontEnd
,
779 ConSrvTermResizeTerminal(IN OUT PTERMINAL This
)
781 PFRONTEND FrontEnd
= This
->Context
;
782 FrontEnd
->Vtbl
->ResizeTerminal(FrontEnd
);
786 ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This
)
788 PFRONTEND FrontEnd
= This
->Context
;
789 FrontEnd
->Vtbl
->SetActiveScreenBuffer(FrontEnd
);
793 ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This
,
794 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
796 PFRONTEND FrontEnd
= This
->Context
;
797 FrontEnd
->Vtbl
->ReleaseScreenBuffer(FrontEnd
, ScreenBuffer
);
801 ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This
,
804 PFRONTEND FrontEnd
= This
->Context
;
805 FrontEnd
->Vtbl
->GetLargestConsoleWindowSize(FrontEnd
, pSize
);
809 ConSrvTermSetPalette(IN OUT PTERMINAL This
,
810 HPALETTE PaletteHandle
,
813 PFRONTEND FrontEnd
= This
->Context
;
814 return FrontEnd
->Vtbl
->SetPalette(FrontEnd
, PaletteHandle
, PaletteUsage
);
818 ConSrvTermShowMouseCursor(IN OUT PTERMINAL This
,
821 PFRONTEND FrontEnd
= This
->Context
;
822 return FrontEnd
->Vtbl
->ShowMouseCursor(FrontEnd
, Show
);
825 static TERMINAL_VTBL ConSrvTermVtbl
=
827 ConSrvTermInitTerminal
,
828 ConSrvTermDeinitTerminal
,
830 ConSrvTermReadStream
,
831 ConSrvTermWriteStream
,
833 ConSrvTermDrawRegion
,
834 ConSrvTermSetCursorInfo
,
835 ConSrvTermSetScreenInfo
,
836 ConSrvTermResizeTerminal
,
837 ConSrvTermSetActiveScreenBuffer
,
838 ConSrvTermReleaseScreenBuffer
,
839 ConSrvTermGetLargestConsoleWindowSize
,
840 ConSrvTermSetPalette
,
841 ConSrvTermShowMouseCursor
,
846 ResetFrontEnd(IN PCONSOLE Console
)
848 if (!Console
) return;
850 /* Reinitialize the frontend interface */
851 RtlZeroMemory(&Console
->FrontEndIFace
, sizeof(Console
->FrontEndIFace
));
852 Console
->FrontEndIFace
.Vtbl
= &ConSrvTermVtbl
;