ReactOS 0.4.15-dev-7889-g76290a6
terminal.c
Go to the documentation of this file.
1/*
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)
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <consrv.h>
12#include "concfg/font.h"
13
14// #include "frontends/gui/guiterm.h"
15#ifdef TUITERM_COMPILE
17#endif
18
19#define NDEBUG
20#include <debug.h>
21
22
23
24
25
26/********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
27
28/* GLOBALS ********************************************************************/
29
30/*
31 * From MSDN:
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."
35 */
36#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
37do { \
38 ASSERT((ULONG_PTR)(dChar) != (ULONG_PTR)(sWChar)); \
39 WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL); \
40} while (0)
41
42#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
43do { \
44 ASSERT((ULONG_PTR)(dWChar) != (ULONG_PTR)(sChar)); \
45 MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1); \
46} while (0)
47
48/* PRIVATE FUNCTIONS **********************************************************/
49
50#if 0
51
52static VOID
54{
55 if (InputEvent->EventType == KEY_EVENT)
56 {
57 WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
58 InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
60 &InputEvent->Event.KeyEvent.uChar.AsciiChar,
61 &UnicodeChar);
62 }
63}
64
65static VOID
67{
68 if (InputEvent->EventType == KEY_EVENT)
69 {
70 CHAR AsciiChar = InputEvent->Event.KeyEvent.uChar.AsciiChar;
71 InputEvent->Event.KeyEvent.uChar.AsciiChar = 0;
73 &InputEvent->Event.KeyEvent.uChar.UnicodeChar,
74 &AsciiChar);
75 }
76}
77
78#endif
79
80/********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
81
82
83
84
85
86
87
88
89/* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/
90
91/***************/
92#ifdef TUITERM_COMPILE
94TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
96 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
97 IN HANDLE ConsoleLeaderProcessHandle);
99TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
100#endif
101
105 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
106 IN HANDLE ConsoleLeaderProcessHandle);
109/***************/
110
111typedef
114 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
115 IN HANDLE ConsoleLeaderProcessHandle);
116
117typedef
119
120/*
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.
123 *
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).
132 */
133
134/*
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).
137 */
138static struct
139{
144{
145#ifdef TUITERM_COMPILE
146 {"TUI", TuiLoadFrontEnd, TuiUnloadFrontEnd},
147#endif
149
150// {"Not found", 0, NULL}
152
153static NTSTATUS
156 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
157 IN HANDLE ConsoleLeaderProcessHandle)
158{
160 ULONG i;
161
162 /*
163 * Choose an adequate terminal front-end to load, and load it
164 */
165 for (i = 0; i < ARRAYSIZE(FrontEndLoadingMethods); ++i)
166 {
167 DPRINT("CONSRV: Trying to load %s frontend...\n",
169 Status = FrontEndLoadingMethods[i].FrontEndLoad(FrontEnd,
171 ConsoleInitInfo,
172 ConsoleLeaderProcessHandle);
173 if (NT_SUCCESS(Status))
174 {
175 /* Save the unload callback */
176 FrontEnd->UnloadFrontEnd = FrontEndLoadingMethods[i].FrontEndUnload;
177
178 DPRINT("CONSRV: %s frontend loaded successfully\n",
180 break;
181 }
182 else
183 {
184 DPRINT1("CONSRV: Loading %s frontend failed, Status = 0x%08lx , continuing...\n",
186 }
187 }
188
189 return Status;
190}
191
192static NTSTATUS
194{
195 if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
196 // return FrontEnd->Vtbl->UnloadFrontEnd(FrontEnd);
197 return FrontEnd->UnloadFrontEnd(FrontEnd);
198}
199
200// See after...
202
206 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
207 IN HANDLE ConsoleLeaderProcessHandle)
208{
210 PFRONTEND FrontEnd;
211
212 /* Load a suitable frontend for the ConSrv terminal */
213 FrontEnd = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*FrontEnd));
214 if (!FrontEnd) return STATUS_NO_MEMORY;
215
216 Status = ConSrvLoadFrontEnd(FrontEnd,
218 ConsoleInitInfo,
219 ConsoleLeaderProcessHandle);
220 if (!NT_SUCCESS(Status))
221 {
222 DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
223 ConsoleFreeHeap(FrontEnd);
224 return Status;
225 }
226 DPRINT("CONSRV: Frontend initialized\n");
227
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 */
232
233 return STATUS_SUCCESS;
234}
235
238{
240 PFRONTEND FrontEnd = Terminal->Context;
241
242 /* Reset the ConSrv terminal */
243 Terminal->Context = NULL;
244 Terminal->Vtbl = NULL;
245
246 /* Unload the frontend */
247 if (FrontEnd != NULL)
248 {
249 Status = ConSrvUnloadFrontEnd(FrontEnd);
250 ConsoleFreeHeap(FrontEnd);
251 }
252
253 return Status;
254}
255
256
257/* CONSRV TERMINAL INTERFACE **************************************************/
258
259static NTSTATUS NTAPI
262{
264 PFRONTEND FrontEnd = This->Context;
265 PCONSRV_CONSOLE ConSrvConsole = (PCONSRV_CONSOLE)Console;
266
267 /* Initialize the console pointer for our frontend */
268 FrontEnd->Console = ConSrvConsole;
269
271 DPRINT("Using FrontEndIFace HACK(1), should be removed after proper implementation!\n");
272 ConSrvConsole->FrontEndIFace = *FrontEnd;
273
274 Status = FrontEnd->Vtbl->InitFrontEnd(FrontEnd, ConSrvConsole);
275 if (!NT_SUCCESS(Status))
276 DPRINT1("InitFrontEnd failed, Status = 0x%08lx\n", Status);
277
279 DPRINT("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n");
280 ConSrvConsole->FrontEndIFace = *FrontEnd;
281
282 return Status;
283}
284
285static VOID NTAPI
287{
288 PFRONTEND FrontEnd = This->Context;
289 FrontEnd->Vtbl->DeinitFrontEnd(FrontEnd);
290}
291
292
293
294/************ Line discipline ***************/
295
296static NTSTATUS NTAPI
298 IN BOOLEAN Unicode,
303 IN ULONG NumCharsToRead,
304 OUT PULONG NumCharsRead OPTIONAL)
305{
306 PFRONTEND FrontEnd = This->Context;
307 PCONSRV_CONSOLE Console = FrontEnd->Console;
309 PUNICODE_STRING ExeName = Parameter;
310
311 // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait.
313
314 PLIST_ENTRY CurrentEntry;
316 ULONG i = 0;
317
318 /* Validity checks */
319 // ASSERT(Console == InputBuffer->Header.Console);
320 ASSERT((Buffer != NULL) || (Buffer == NULL && NumCharsToRead == 0));
321
322 /* We haven't read anything (yet) */
323
324 if (InputBuffer->Mode & ENABLE_LINE_INPUT)
325 {
326 /* COOKED mode, call the line discipline */
327
328 if (Console->LineBuffer == NULL)
329 {
330 /* Start a new line */
331 Console->LineMaxSize = max(256, NumCharsToRead);
332
333 /*
334 * Fixup ReadControl->nInitialChars in case the number of initial
335 * characters is bigger than the number of characters to be read.
336 * It will always be, lesser than or equal to Console->LineMaxSize.
337 */
338 ReadControl->nInitialChars = min(ReadControl->nInitialChars, NumCharsToRead);
339
340 Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR));
341 if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY;
342
343 Console->LinePos = Console->LineSize = ReadControl->nInitialChars;
344 Console->LineComplete = Console->LineUpPressed = FALSE;
345 Console->LineInsertToggle = Console->InsertMode;
346 Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask;
347
348 /*
349 * Pre-fill the buffer with the nInitialChars from the user buffer.
350 * Since pre-filling is only allowed in Unicode, we don't need to
351 * worry about ANSI <-> Unicode conversion.
352 */
353 memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR));
354 if (Console->LineSize >= Console->LineMaxSize)
355 {
356 Console->LineComplete = TRUE;
357 Console->LinePos = 0;
358 }
359 }
360
361 /* If we don't have a complete line yet, process the pending input */
362 while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents))
363 {
364 /* Remove an input event from the queue */
365 _InterlockedDecrement((PLONG)&InputBuffer->NumberOfEvents);
366 CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
367 if (IsListEmpty(&InputBuffer->InputEvents))
368 {
369 NtClearEvent(InputBuffer->ActiveEvent);
370 }
371 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
372
373 /* Only pay attention to key down */
374 if (Input->InputEvent.EventType == KEY_EVENT &&
375 Input->InputEvent.Event.KeyEvent.bKeyDown)
376 {
377 LineInputKeyDown(Console, ExeName,
378 &Input->InputEvent.Event.KeyEvent);
379 ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
380 }
382 }
383
384 /* Check if we have a complete line to read from */
385 if (Console->LineComplete)
386 {
387 /*
388 * Console->LinePos keeps the next position of the character to read
389 * in the line buffer across the different calls of the function,
390 * so that the line buffer can be read by chunks after all the input
391 * has been buffered.
392 */
393
394 while (i < NumCharsToRead && Console->LinePos < Console->LineSize)
395 {
396 WCHAR Char = Console->LineBuffer[Console->LinePos++];
397
398 if (Unicode)
399 {
400 ((PWCHAR)Buffer)[i] = Char;
401 }
402 else
403 {
405 }
406 ++i;
407 }
408
409 if (Console->LinePos >= Console->LineSize)
410 {
411 /* The entire line has been read */
412 ConsoleFreeHeap(Console->LineBuffer);
413 Console->LineBuffer = NULL;
414 Console->LinePos = Console->LineMaxSize = Console->LineSize = 0;
415 // Console->LineComplete = Console->LineUpPressed = FALSE;
416 Console->LineComplete = FALSE;
417 }
418
420 }
421 }
422 else
423 {
424 /* RAW mode */
425
426 /* Character input */
427 while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents))
428 {
429 /* Remove an input event from the queue */
430 _InterlockedDecrement((PLONG)&InputBuffer->NumberOfEvents);
431 CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
432 if (IsListEmpty(&InputBuffer->InputEvents))
433 {
434 NtClearEvent(InputBuffer->ActiveEvent);
435 }
436 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
437
438 /* Only pay attention to valid characters, on key down */
439 if (Input->InputEvent.EventType == KEY_EVENT &&
440 Input->InputEvent.Event.KeyEvent.bKeyDown &&
441 Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0')
442 {
443 WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar;
444
445 if (Unicode)
446 {
447 ((PWCHAR)Buffer)[i] = Char;
448 }
449 else
450 {
452 }
453 ++i;
454
455 /* Did read something */
457 }
459 }
460 }
461
462 // FIXME: Only set if Status == STATUS_SUCCESS ???
463 if (NumCharsRead) *NumCharsRead = i;
464
465 return Status;
466}
467
468
469
470
471/* GLOBALS ********************************************************************/
472
473#define TAB_WIDTH 8
474
475// See condrv/text.c
476/*static*/ VOID
478
479static VOID
481{
482 /* If we hit bottom, slide the viewable screen */
483 if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y)
484 {
485 Buff->CursorPosition.Y--;
486 if (++Buff->VirtualY == Buff->ScreenBufferSize.Y)
487 {
488 Buff->VirtualY = 0;
489 }
490 (*ScrolledLines)++;
491 ClearLineBuffer(Buff);
492 if (UpdateRect->Top != 0)
493 {
494 UpdateRect->Top--;
495 }
496 }
497 UpdateRect->Left = 0;
498 UpdateRect->Right = Buff->ScreenBufferSize.X - 1;
499 UpdateRect->Bottom = Buff->CursorPosition.Y;
500}
501
502static NTSTATUS
507 BOOL Attrib)
508{
509 PCONSRV_CONSOLE Console = FrontEnd->Console;
510
511 UINT i;
514 SHORT CursorStartX, CursorStartY;
515 UINT ScrolledLines;
516 BOOLEAN bFullwidth;
517 BOOLEAN bCJK = Console->IsCJK;
518
519 /* If nothing to write, bail out now */
520 if (Length == 0)
521 return STATUS_SUCCESS;
522
523 CursorStartX = Buff->CursorPosition.X;
524 CursorStartY = Buff->CursorPosition.Y;
525 UpdateRect.Left = Buff->ScreenBufferSize.X;
526 UpdateRect.Top = Buff->CursorPosition.Y;
527 UpdateRect.Right = -1;
528 UpdateRect.Bottom = Buff->CursorPosition.Y;
529 ScrolledLines = 0;
530
531 for (i = 0; i < Length; i++)
532 {
533 /*
534 * If we are in processed mode, interpret special characters and
535 * display them correctly. Otherwise, just put them into the buffer.
536 */
537 if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
538 {
539 /* --- CR --- */
540 if (Buffer[i] == L'\r')
541 {
542 Buff->CursorPosition.X = 0;
543 CursorStartX = Buff->CursorPosition.X;
544 UpdateRect.Left = min(UpdateRect.Left , Buff->CursorPosition.X);
545 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
546 continue;
547 }
548 /* --- LF --- */
549 else if (Buffer[i] == L'\n')
550 {
551 Buff->CursorPosition.X = 0; // TODO: Make this behaviour optional!
552 CursorStartX = Buff->CursorPosition.X;
553 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
554 continue;
555 }
556 /* --- BS --- */
557 else if (Buffer[i] == L'\b')
558 {
559 /* Only handle BS if we are not on the first position of the first line */
560 if (Buff->CursorPosition.X == 0 && Buff->CursorPosition.Y == 0)
561 continue;
562
563 if (Buff->CursorPosition.X == 0)
564 {
565 /* Slide virtual position up */
566 Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1;
567 Buff->CursorPosition.Y--;
568 // TODO? : Update CursorStartY = Buff->CursorPosition.Y;
569 UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y);
570 }
571 else
572 {
573 Buff->CursorPosition.X--;
574 }
575 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
576
577 if (Ptr->Attributes & COMMON_LVB_LEADING_BYTE)
578 {
579 /*
580 * The cursor just moved on the leading byte of the same
581 * current character. We should go one position before to
582 * go to the actual previous character to erase.
583 */
584
585 /* Only handle BS if we are not on the first position of the first line */
586 if (Buff->CursorPosition.X == 0 && Buff->CursorPosition.Y == 0)
587 continue;
588
589 if (Buff->CursorPosition.X == 0)
590 {
591 /* Slide virtual position up */
592 Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1;
593 Buff->CursorPosition.Y--;
594 // TODO? : Update CursorStartY = Buff->CursorPosition.Y;
595 UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y);
596 }
597 else
598 {
599 Buff->CursorPosition.X--;
600 }
601 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
602 }
603
604 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
605 {
606 /* The cursor is on the trailing byte of a full-width character */
607
608 /* Delete its trailing byte... */
609 Ptr->Char.UnicodeChar = L' ';
610 if (Attrib)
611 Ptr->Attributes = Buff->ScreenDefaultAttrib;
612 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
613
614 if (Buff->CursorPosition.X > 0)
615 Buff->CursorPosition.X--;
616 /* ... and now its leading byte */
617 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
618 }
619
620 Ptr->Char.UnicodeChar = L' ';
621 if (Attrib)
622 Ptr->Attributes = Buff->ScreenDefaultAttrib;
623 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
624
625 UpdateRect.Left = min(UpdateRect.Left , Buff->CursorPosition.X);
626 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
627 continue;
628 }
629 /* --- TAB --- */
630 else if (Buffer[i] == L'\t')
631 {
632 UINT EndX;
633
634 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
635
636 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
637 {
638 /*
639 * The cursor is on the trailing byte of a full-width character.
640 * Go back one position to be on its leading byte.
641 */
642 if (Buff->CursorPosition.X > 0)
643 Buff->CursorPosition.X--;
644 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
645 }
646
647 UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
648
649 EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1);
650 EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X);
651
652 while ((UINT)Buff->CursorPosition.X < EndX)
653 {
654 Ptr->Char.UnicodeChar = L' ';
655 if (Attrib)
656 Ptr->Attributes = Buff->ScreenDefaultAttrib;
657 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
658
659 ++Ptr;
660 Buff->CursorPosition.X++;
661 }
662 if (Buff->CursorPosition.X < Buff->ScreenBufferSize.X)
663 {
664 /* If the following cell is the trailing byte of a full-width character, reset it */
665 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
666 {
667 Ptr->Char.UnicodeChar = L' ';
668 if (Attrib)
669 Ptr->Attributes = Buff->ScreenDefaultAttrib;
670 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
671 }
672 }
673 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
674
675 if (Buff->CursorPosition.X >= Buff->ScreenBufferSize.X)
676 {
677 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
678 {
679 /* Wrapping mode: Go to next line */
680 Buff->CursorPosition.X = 0;
681 CursorStartX = Buff->CursorPosition.X;
682 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
683 }
684 else
685 {
686 /* The cursor wraps back to its starting position on the same line */
687 Buff->CursorPosition.X = CursorStartX;
688 }
689 }
690 continue;
691 }
692 /* --- BEL ---*/
693 else if (Buffer[i] == L'\a')
694 {
695 FrontEnd->Vtbl->RingBell(FrontEnd);
696 continue;
697 }
698 }
699 UpdateRect.Left = min(UpdateRect.Left , Buff->CursorPosition.X);
700 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
701
702 /* For Chinese, Japanese and Korean */
703 bFullwidth = (bCJK && IS_FULL_WIDTH(Buffer[i]));
704
705 /* Check whether we can insert the full-width character */
706 if (bFullwidth)
707 {
708 /* It spans two cells and should all fit on the current line */
709 if (Buff->CursorPosition.X >= Buff->ScreenBufferSize.X - 1)
710 {
711 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
712 {
713 /* Wrapping mode: Go to next line */
714 Buff->CursorPosition.X = 0;
715 CursorStartX = Buff->CursorPosition.X;
716 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
717 }
718 else
719 {
720 /* The cursor wraps back to its starting position on the same line */
721 Buff->CursorPosition.X = CursorStartX;
722 }
723 }
724
725 /*
726 * Now be sure we can fit the full-width character.
727 * If the screenbuffer is one cell wide we cannot display
728 * the full-width character, so just skip it.
729 */
730 if (Buff->CursorPosition.X >= Buff->ScreenBufferSize.X - 1)
731 {
732 DPRINT1("Cannot display full-width character! CursorPosition.X = %d, ScreenBufferSize.X = %d\n",
733 Buff->CursorPosition.X, Buff->ScreenBufferSize.X);
734 continue;
735 }
736 }
737
738 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
739
740 /*
741 * Check whether we are overwriting part of a full-width character,
742 * in which case we need to invalidate it.
743 */
744 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
745 {
746 /*
747 * The cursor is on the trailing byte of a full-width character.
748 * Go back one position to kill the previous leading byte.
749 */
750 if (Buff->CursorPosition.X > 0)
751 {
752 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X - 1, Buff->CursorPosition.Y);
753 Ptr->Char.UnicodeChar = L' ';
754 if (Attrib)
755 Ptr->Attributes = Buff->ScreenDefaultAttrib;
756 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
757 }
758 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
759 }
760
761 /* Insert the character */
762 if (bFullwidth)
763 {
764 ASSERT(Buff->CursorPosition.X < Buff->ScreenBufferSize.X - 1);
765
766 /* Set the leading byte */
767 Ptr->Char.UnicodeChar = Buffer[i];
768 if (Attrib)
769 Ptr->Attributes = Buff->ScreenDefaultAttrib;
770 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
771 Ptr->Attributes |= COMMON_LVB_LEADING_BYTE;
772
773 /* Set the trailing byte */
774 Buff->CursorPosition.X++;
775 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
776 // Ptr->Char.UnicodeChar = Buffer[i]; // L' ';
777 if (Attrib)
778 Ptr->Attributes = Buff->ScreenDefaultAttrib;
779 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
780 Ptr->Attributes |= COMMON_LVB_TRAILING_BYTE;
781 }
782 else
783 {
784 Ptr->Char.UnicodeChar = Buffer[i];
785 if (Attrib)
786 Ptr->Attributes = Buff->ScreenDefaultAttrib;
787 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
788 }
789
790 ++Ptr;
791 Buff->CursorPosition.X++;
792
793 if (Buff->CursorPosition.X < Buff->ScreenBufferSize.X)
794 {
795 /* If the following cell is the trailing byte of a full-width character, reset it */
796 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
797 {
798 Ptr->Char.UnicodeChar = L' ';
799 if (Attrib)
800 Ptr->Attributes = Buff->ScreenDefaultAttrib;
801 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
802 }
803 }
804
805 if (Buff->CursorPosition.X >= Buff->ScreenBufferSize.X)
806 {
807 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
808 {
809 /* Wrapping mode: Go to next line */
810 Buff->CursorPosition.X = 0;
811 CursorStartX = Buff->CursorPosition.X;
812 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
813 }
814 else
815 {
816 /* The cursor wraps back to its starting position on the same line */
817 Buff->CursorPosition.X = CursorStartX;
818 }
819 }
820 }
821
822 if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
823 {
824 // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
825 // ScrolledLines, Buffer, Length);
826 FrontEnd->Vtbl->WriteStream(FrontEnd,
827 &UpdateRect,
828 CursorStartX,
829 CursorStartY,
830 ScrolledLines,
831 Buffer,
832 Length);
833 }
834
835 return STATUS_SUCCESS;
836}
837
838
839
840static NTSTATUS NTAPI
845 BOOL Attrib)
846{
847 PFRONTEND FrontEnd = This->Context;
848 return ConioWriteConsole(FrontEnd,
849 Buff,
850 Buffer,
851 Length,
852 Attrib);
853}
854
855/************ Line discipline ***************/
856
857
858
859VOID
861{
863 PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
864
865 if (!ActiveBuffer) return;
866
867 ConioInitRect(&Region, 0, 0,
868 ActiveBuffer->ViewSize.Y - 1,
869 ActiveBuffer->ViewSize.X - 1);
871 // Console->FrontEndIFace.Vtbl->DrawRegion(&Console->FrontEndIFace, &Region);
872}
873
874static VOID NTAPI
877{
878 PFRONTEND FrontEnd = This->Context;
879 FrontEnd->Vtbl->DrawRegion(FrontEnd, Region);
880}
881
882static BOOL NTAPI
885{
886 PFRONTEND FrontEnd = This->Context;
887 return FrontEnd->Vtbl->SetCursorInfo(FrontEnd, ScreenBuffer);
888}
889
890static BOOL NTAPI
893 SHORT OldCursorX,
894 SHORT OldCursorY)
895{
896 PFRONTEND FrontEnd = This->Context;
897 return FrontEnd->Vtbl->SetScreenInfo(FrontEnd,
899 OldCursorX,
900 OldCursorY);
901}
902
903static VOID NTAPI
905{
906 PFRONTEND FrontEnd = This->Context;
907 FrontEnd->Vtbl->ResizeTerminal(FrontEnd);
908}
909
910static VOID NTAPI
912{
913 PFRONTEND FrontEnd = This->Context;
914 FrontEnd->Vtbl->SetActiveScreenBuffer(FrontEnd);
915}
916
917static VOID NTAPI
920{
921 PFRONTEND FrontEnd = This->Context;
922 FrontEnd->Vtbl->ReleaseScreenBuffer(FrontEnd, ScreenBuffer);
923}
924
925static VOID NTAPI
927 PCOORD pSize)
928{
929 PFRONTEND FrontEnd = This->Context;
930 FrontEnd->Vtbl->GetLargestConsoleWindowSize(FrontEnd, pSize);
931}
932
933static BOOL NTAPI
935 HPALETTE PaletteHandle,
936 UINT PaletteUsage)
937{
938 PFRONTEND FrontEnd = This->Context;
939 return FrontEnd->Vtbl->SetPalette(FrontEnd, PaletteHandle, PaletteUsage);
940}
941
942static BOOL NTAPI
944 UINT CodePage)
945{
946 PFRONTEND FrontEnd = This->Context;
947 return FrontEnd->Vtbl->SetCodePage(FrontEnd, CodePage);
948}
949
950static INT NTAPI
952 BOOL Show)
953{
954 PFRONTEND FrontEnd = This->Context;
955 return FrontEnd->Vtbl->ShowMouseCursor(FrontEnd, Show);
956}
957
959{
962
965
976};
977
978#if 0
979VOID
980ResetFrontEnd(IN PCONSOLE Console)
981{
982 PCONSRV_CONSOLE ConSrvConsole = (PCONSRV_CONSOLE)Console;
983 if (!Console) return;
984
985 /* Reinitialize the frontend interface */
986 RtlZeroMemory(&ConSrvConsole->FrontEndIFace, sizeof(ConSrvConsole->FrontEndIFace));
987 ConSrvConsole->FrontEndIFace.Vtbl = &ConSrvTermVtbl;
988}
989#endif
990
991/* EOF */
unsigned char BOOLEAN
CConsole Console
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define IS_FULL_WIDTH(wch)
Definition: console.c:337
#define ENABLE_WRAP_AT_EOL_OUTPUT
Definition: blue.h:54
#define ENABLE_PROCESSED_OUTPUT
Definition: blue.h:53
Definition: bufpool.h:45
static VOID ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent)
Definition: coninput.c:74
static VOID ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
Definition: coninput.c:61
struct _CONSRV_CONSOLE * PCONSRV_CONSOLE
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define NTSTATUS
Definition: precomp.h:21
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
long __cdecl _InterlockedDecrement(_Interlocked_operand_ long volatile *_Addend)
VOID LineInputKeyDown(PCONSRV_CONSOLE Console, PUNICODE_STRING ExeName, KEY_EVENT_RECORD *KeyEvent)
Definition: lineinput.c:147
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
unsigned int * PUINT
Definition: ndis.h:50
unsigned int UINT
Definition: ndis.h:50
HANDLE ScreenBuffer
Definition: notevil.c:37
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTATUS NTAPI NtClearEvent(IN HANDLE EventHandle)
Definition: event.c:65
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define L(x)
Definition: ntvdm.h:50
short SHORT
Definition: pedump.c:59
@ Input
Definition: arc.h:84
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
FRONTEND FrontEndIFace
Definition: conio_winsrv.h:130
Definition: bl.h:1338
ULONG Y
Definition: bl.h:1340
ULONG X
Definition: bl.h:1339
PFRONTEND_VTBL Vtbl
Definition: conio_winsrv.h:100
struct _CONSRV_CONSOLE * Console
Definition: conio_winsrv.h:103
PVOID Context
Definition: conio_winsrv.h:104
union _INPUT_RECORD::@3292 Event
WORD EventType
Definition: wincon.h:273
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:275
union _KEY_EVENT_RECORD::@3291 uChar
WCHAR UnicodeChar
Definition: wincon.h:245
Definition: typedefs.h:120
USHORT ScreenDefaultAttrib
Definition: conio.h:131
static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
Definition: video.c:47
#define max(a, b)
Definition: svc.c:63
static HPALETTE PaletteHandle
Definition: svga.c:215
#define TermDrawRegion(Console, Region)
Definition: term.h:22
NTSTATUS(NTAPI * FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd)
Definition: terminal.c:118
static NTSTATUS ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd, IN OUT PCONSOLE_STATE_INFO ConsoleInfo, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN HANDLE ConsoleLeaderProcessHandle)
Definition: terminal.c:154
#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar)
Definition: terminal.c:36
CHAR FrontEndName[80]
Definition: terminal.c:140
static INT NTAPI ConSrvTermShowMouseCursor(IN OUT PTERMINAL This, BOOL Show)
Definition: terminal.c:951
static TERMINAL_VTBL ConSrvTermVtbl
Definition: terminal.c:201
VOID ConioDrawConsole(PCONSRV_CONSOLE Console)
Definition: terminal.c:860
static BOOL NTAPI ConSrvTermSetScreenInfo(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer, SHORT OldCursorX, SHORT OldCursorY)
Definition: terminal.c:891
static VOID NTAPI ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This, PCOORD pSize)
Definition: terminal.c:926
static NTSTATUS ConSrvUnloadFrontEnd(IN PFRONTEND FrontEnd)
Definition: terminal.c:193
static NTSTATUS NTAPI ConSrvTermWriteStream(IN OUT PTERMINAL This, PTEXTMODE_SCREEN_BUFFER Buff, PWCHAR Buffer, DWORD Length, BOOL Attrib)
Definition: terminal.c:841
static VOID NTAPI ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This)
Definition: terminal.c:911
#define TAB_WIDTH
Definition: terminal.c:473
NTSTATUS NTAPI GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, IN OUT PCONSOLE_STATE_INFO ConsoleInfo, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN HANDLE ConsoleLeaderProcessHandle)
Definition: guiterm.c:1208
static VOID NTAPI ConSrvTermDeinitTerminal(IN OUT PTERMINAL This)
Definition: terminal.c:286
static NTSTATUS ConioWriteConsole(PFRONTEND FrontEnd, PTEXTMODE_SCREEN_BUFFER Buff, PWCHAR Buffer, DWORD Length, BOOL Attrib)
Definition: terminal.c:503
static BOOL NTAPI ConSrvTermSetPalette(IN OUT PTERMINAL This, HPALETTE PaletteHandle, UINT PaletteUsage)
Definition: terminal.c:934
NTSTATUS(NTAPI * FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd, IN OUT PCONSOLE_STATE_INFO ConsoleInfo, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN HANDLE ConsoleLeaderProcessHandle)
Definition: terminal.c:112
static struct @5136 FrontEndLoadingMethods[]
#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar)
Definition: terminal.c:42
NTSTATUS NTAPI GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
Definition: guiterm.c:1338
FRONTEND_LOAD FrontEndLoad
Definition: terminal.c:141
static VOID NTAPI ConSrvTermDrawRegion(IN OUT PTERMINAL This, SMALL_RECT *Region)
Definition: terminal.c:875
FRONTEND_UNLOAD FrontEndUnload
Definition: terminal.c:142
static VOID NTAPI ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This, IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
Definition: terminal.c:918
static BOOL NTAPI ConSrvTermSetCursorInfo(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer)
Definition: terminal.c:883
static BOOL NTAPI ConSrvTermSetCodePage(IN OUT PTERMINAL This, UINT CodePage)
Definition: terminal.c:943
static NTSTATUS NTAPI ConSrvTermInitTerminal(IN OUT PTERMINAL This, IN PCONSOLE Console)
Definition: terminal.c:260
NTSTATUS NTAPI ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal)
Definition: terminal.c:237
NTSTATUS NTAPI ConSrvInitTerminal(IN OUT PTERMINAL Terminal, IN OUT PCONSOLE_STATE_INFO ConsoleInfo, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN HANDLE ConsoleLeaderProcessHandle)
Definition: terminal.c:204
static NTSTATUS NTAPI ConSrvTermReadStream(IN OUT PTERMINAL This, IN BOOLEAN Unicode, OUT PVOID Buffer, IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, IN PVOID Parameter OPTIONAL, IN ULONG NumCharsToRead, OUT PULONG NumCharsRead OPTIONAL)
Definition: terminal.c:297
VOID ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff)
Definition: text.c:151
static VOID ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT ScrolledLines)
Definition: terminal.c:480
static VOID NTAPI ConSrvTermResizeTerminal(IN OUT PTERMINAL This)
Definition: terminal.c:904
static int UpdateRect(TreeListData *pData, unsigned uItem, unsigned uSub)
Definition: treelist.c:1529
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
PCHAR_INFO ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y)
Definition: text.c:143
#define ConsoleAllocHeap(Flags, Size)
Definition: heap.h:14
#define ConsoleFreeHeap(HeapBase)
Definition: heap.h:15
#define ConioInitRect(Rect, top, left, bottom, right)
Definition: rect.h:20
#define ConioIsRectEmpty(Rect)
Definition: rect.h:28
#define COMMON_LVB_TRAILING_BYTE
Definition: wincon.h:49
#define KEY_EVENT
Definition: wincon.h:128
#define ENABLE_LINE_INPUT
Definition: wincon.h:79
#define COMMON_LVB_LEADING_BYTE
Definition: wincon.h:48
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175