ReactOS 0.4.16-dev-2613-g9533ad7
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 INT OldX = Buff->CursorPosition.X;
560
561 /* Only handle BS if we are not on the first position of the first line */
562 if (Buff->CursorPosition.X == 0 && Buff->CursorPosition.Y == 0)
563 continue;
564
565 if (Buff->CursorPosition.X == 0)
566 {
567 /* Slide virtual position up */
568 Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1;
569 Buff->CursorPosition.Y--;
570 // TODO? : Update CursorStartY = Buff->CursorPosition.Y;
571 UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y);
572 }
573 else
574 {
575 Buff->CursorPosition.X--;
576 }
577 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
578
579 if (Ptr->Attributes & COMMON_LVB_LEADING_BYTE)
580 {
581 /*
582 * The cursor just moved on the leading byte of the same
583 * current character. We should go one position before to
584 * go to the actual previous character to erase.
585 */
586
587 /* Only handle BS if we are not on the first position of the first line */
588 if (Buff->CursorPosition.X == 0 && Buff->CursorPosition.Y == 0)
589 continue;
590
591 if (Buff->CursorPosition.X == 0)
592 {
593 /* Slide virtual position up */
594 Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1;
595 Buff->CursorPosition.Y--;
596 // TODO? : Update CursorStartY = Buff->CursorPosition.Y;
597 UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y);
598 }
599 else
600 {
601 Buff->CursorPosition.X--;
602 }
603 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
604 }
605
606 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
607 {
608 /* The cursor is on the trailing byte of a full-width character */
609
610 /* Delete its trailing byte... */
611 Ptr->Char.UnicodeChar = L' ';
612 if (Attrib)
613 Ptr->Attributes = Buff->ScreenDefaultAttrib;
614 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
615
616 if (Buff->CursorPosition.X > 0)
617 Buff->CursorPosition.X--;
618 /* ... and now its leading byte */
619 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
620 }
621
622 Ptr->Char.UnicodeChar = L' ';
623 if (Attrib)
624 Ptr->Attributes = Buff->ScreenDefaultAttrib;
625 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
626
627 UpdateRect.Left = min(min(UpdateRect.Left , Buff->CursorPosition.X), OldX);
628 UpdateRect.Right = max(max(UpdateRect.Right, Buff->CursorPosition.X), OldX);
629 continue;
630 }
631 /* --- TAB --- */
632 else if (Buffer[i] == L'\t')
633 {
634 UINT EndX;
635
636 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
637
638 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
639 {
640 /*
641 * The cursor is on the trailing byte of a full-width character.
642 * Go back one position to be on its leading byte.
643 */
644 if (Buff->CursorPosition.X > 0)
645 Buff->CursorPosition.X--;
646 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
647 }
648
649 UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
650
651 EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1);
652 EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X);
653
654 while ((UINT)Buff->CursorPosition.X < EndX)
655 {
656 Ptr->Char.UnicodeChar = L' ';
657 if (Attrib)
658 Ptr->Attributes = Buff->ScreenDefaultAttrib;
659 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
660
661 ++Ptr;
662 Buff->CursorPosition.X++;
663 }
664 if (Buff->CursorPosition.X < Buff->ScreenBufferSize.X)
665 {
666 /* If the following cell is the trailing byte of a full-width character, reset it */
667 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
668 {
669 Ptr->Char.UnicodeChar = L' ';
670 if (Attrib)
671 Ptr->Attributes = Buff->ScreenDefaultAttrib;
672 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
673 }
674 }
675 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
676
677 if (Buff->CursorPosition.X >= Buff->ScreenBufferSize.X)
678 {
679 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
680 {
681 /* Wrapping mode: Go to next line */
682 Buff->CursorPosition.X = 0;
683 CursorStartX = Buff->CursorPosition.X;
684 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
685 }
686 else
687 {
688 /* The cursor wraps back to its starting position on the same line */
689 Buff->CursorPosition.X = CursorStartX;
690 }
691 }
692 continue;
693 }
694 /* --- BEL ---*/
695 else if (Buffer[i] == L'\a')
696 {
697 FrontEnd->Vtbl->RingBell(FrontEnd);
698 continue;
699 }
700 }
701 UpdateRect.Left = min(UpdateRect.Left , Buff->CursorPosition.X);
702 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
703
704 /* For Chinese, Japanese and Korean */
705 bFullwidth = (bCJK && IS_FULL_WIDTH(Buffer[i]));
706
707 /* Check whether we can insert the full-width character */
708 if (bFullwidth)
709 {
710 /* It spans two cells and should all fit on the current line */
711 if (Buff->CursorPosition.X >= Buff->ScreenBufferSize.X - 1)
712 {
713 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
714 {
715 /* Wrapping mode: Go to next line */
716 Buff->CursorPosition.X = 0;
717 CursorStartX = Buff->CursorPosition.X;
718 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
719 }
720 else
721 {
722 /* The cursor wraps back to its starting position on the same line */
723 Buff->CursorPosition.X = CursorStartX;
724 }
725 }
726
727 /*
728 * Now be sure we can fit the full-width character.
729 * If the screenbuffer is one cell wide we cannot display
730 * the full-width character, so just skip it.
731 */
732 if (Buff->CursorPosition.X >= Buff->ScreenBufferSize.X - 1)
733 {
734 DPRINT1("Cannot display full-width character! CursorPosition.X = %d, ScreenBufferSize.X = %d\n",
735 Buff->CursorPosition.X, Buff->ScreenBufferSize.X);
736 continue;
737 }
738 }
739
740 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
741
742 /*
743 * Check whether we are overwriting part of a full-width character,
744 * in which case we need to invalidate it.
745 */
746 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
747 {
748 /*
749 * The cursor is on the trailing byte of a full-width character.
750 * Go back one position to kill the previous leading byte.
751 */
752 if (Buff->CursorPosition.X > 0)
753 {
754 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X - 1, Buff->CursorPosition.Y);
755 Ptr->Char.UnicodeChar = L' ';
756 if (Attrib)
757 Ptr->Attributes = Buff->ScreenDefaultAttrib;
758 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
759 }
760 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
761 }
762
763 /* Insert the character */
764 if (bFullwidth)
765 {
766 ASSERT(Buff->CursorPosition.X < Buff->ScreenBufferSize.X - 1);
767
768 /* Set the leading byte */
769 Ptr->Char.UnicodeChar = Buffer[i];
770 if (Attrib)
771 Ptr->Attributes = Buff->ScreenDefaultAttrib;
772 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
773 Ptr->Attributes |= COMMON_LVB_LEADING_BYTE;
774
775 /* Set the trailing byte */
776 Buff->CursorPosition.X++;
777 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
778 // Ptr->Char.UnicodeChar = Buffer[i]; // L' ';
779 if (Attrib)
780 Ptr->Attributes = Buff->ScreenDefaultAttrib;
781 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
782 Ptr->Attributes |= COMMON_LVB_TRAILING_BYTE;
783
784 UpdateRect.Right++;
785 }
786 else
787 {
788 Ptr->Char.UnicodeChar = Buffer[i];
789 if (Attrib)
790 Ptr->Attributes = Buff->ScreenDefaultAttrib;
791 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
792 }
793
794 ++Ptr;
795 Buff->CursorPosition.X++;
796
797 if (Buff->CursorPosition.X < Buff->ScreenBufferSize.X)
798 {
799 /* If the following cell is the trailing byte of a full-width character, reset it */
800 if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
801 {
802 Ptr->Char.UnicodeChar = L' ';
803 if (Attrib)
804 Ptr->Attributes = Buff->ScreenDefaultAttrib;
805 Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
806 }
807 }
808
809 if (Buff->CursorPosition.X >= Buff->ScreenBufferSize.X)
810 {
811 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
812 {
813 /* Wrapping mode: Go to next line */
814 Buff->CursorPosition.X = 0;
815 CursorStartX = Buff->CursorPosition.X;
816 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
817 }
818 else
819 {
820 /* The cursor wraps back to its starting position on the same line */
821 Buff->CursorPosition.X = CursorStartX;
822 }
823 }
824 }
825
826 if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
827 {
828 // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
829 // ScrolledLines, Buffer, Length);
830 FrontEnd->Vtbl->WriteStream(FrontEnd,
831 &UpdateRect,
832 CursorStartX,
833 CursorStartY,
834 ScrolledLines,
835 Buffer,
836 Length);
837 }
838
839 return STATUS_SUCCESS;
840}
841
842
843
844static NTSTATUS NTAPI
849 BOOL Attrib)
850{
851 PFRONTEND FrontEnd = This->Context;
852 return ConioWriteConsole(FrontEnd,
853 Buff,
854 Buffer,
855 Length,
856 Attrib);
857}
858
859/************ Line discipline ***************/
860
861
862
863VOID
865{
867 PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
868
869 if (!ActiveBuffer) return;
870
871 ConioInitRect(&Region, 0, 0,
872 ActiveBuffer->ViewSize.Y - 1,
873 ActiveBuffer->ViewSize.X - 1);
875 // Console->FrontEndIFace.Vtbl->DrawRegion(&Console->FrontEndIFace, &Region);
876}
877
878static VOID NTAPI
881{
882 PFRONTEND FrontEnd = This->Context;
883 FrontEnd->Vtbl->DrawRegion(FrontEnd, Region);
884}
885
886static BOOL NTAPI
889{
890 PFRONTEND FrontEnd = This->Context;
891 return FrontEnd->Vtbl->SetCursorInfo(FrontEnd, ScreenBuffer);
892}
893
894static BOOL NTAPI
897 SHORT OldCursorX,
898 SHORT OldCursorY)
899{
900 PFRONTEND FrontEnd = This->Context;
901 return FrontEnd->Vtbl->SetScreenInfo(FrontEnd,
903 OldCursorX,
904 OldCursorY);
905}
906
907static VOID NTAPI
909{
910 PFRONTEND FrontEnd = This->Context;
911 FrontEnd->Vtbl->ResizeTerminal(FrontEnd);
912}
913
914static VOID NTAPI
916{
917 PFRONTEND FrontEnd = This->Context;
918 FrontEnd->Vtbl->SetActiveScreenBuffer(FrontEnd);
919}
920
921static VOID NTAPI
924{
925 PFRONTEND FrontEnd = This->Context;
926 FrontEnd->Vtbl->ReleaseScreenBuffer(FrontEnd, ScreenBuffer);
927}
928
929static VOID NTAPI
931 PCOORD pSize)
932{
933 PFRONTEND FrontEnd = This->Context;
934 FrontEnd->Vtbl->GetLargestConsoleWindowSize(FrontEnd, pSize);
935}
936
937static BOOL NTAPI
939 HPALETTE PaletteHandle,
940 UINT PaletteUsage)
941{
942 PFRONTEND FrontEnd = This->Context;
943 return FrontEnd->Vtbl->SetPalette(FrontEnd, PaletteHandle, PaletteUsage);
944}
945
946static BOOL NTAPI
948 UINT CodePage)
949{
950 PFRONTEND FrontEnd = This->Context;
951 return FrontEnd->Vtbl->SetCodePage(FrontEnd, CodePage);
952}
953
954static INT NTAPI
956 BOOL Show)
957{
958 PFRONTEND FrontEnd = This->Context;
959 return FrontEnd->Vtbl->ShowMouseCursor(FrontEnd, Show);
960}
961
963{
966
969
980};
981
982#if 0
983VOID
984ResetFrontEnd(IN PCONSOLE Console)
985{
986 PCONSRV_CONSOLE ConSrvConsole = (PCONSRV_CONSOLE)Console;
987 if (!Console) return;
988
989 /* Reinitialize the frontend interface */
990 RtlZeroMemory(&ConSrvConsole->FrontEndIFace, sizeof(ConSrvConsole->FrontEndIFace));
991 ConSrvConsole->FrontEndIFace.Vtbl = &ConSrvTermVtbl;
992}
993#endif
994
995/* EOF */
CConsole Console
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define IS_FULL_WIDTH(wch)
Definition: console.c:333
#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 STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#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:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define NTSTATUS
Definition: precomp.h:19
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define L(x)
Definition: resources.c:13
#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
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
short WCHAR
Definition: pedump.c:58
short SHORT
Definition: pedump.c:59
char CHAR
Definition: pedump.c:57
@ Input
Definition: arc.h:93
long __cdecl _InterlockedDecrement(_Interlocked_operand_ long volatile *_Addend)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
FRONTEND FrontEndIFace
Definition: conio_winsrv.h:130
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::@3521 Event
WORD EventType
Definition: wincon.h:294
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:296
union _KEY_EVENT_RECORD::@3520 uChar
WCHAR UnicodeChar
Definition: wincon.h:266
Definition: typedefs.h:120
USHORT ScreenDefaultAttrib
Definition: conio.h:131
Definition: blue.h:25
SHORT Y
Definition: blue.h:27
SHORT X
Definition: blue.h:26
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 STATUS_PENDING
Definition: telnetd.h:14
#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:955
static TERMINAL_VTBL ConSrvTermVtbl
Definition: terminal.c:201
VOID ConioDrawConsole(PCONSRV_CONSOLE Console)
Definition: terminal.c:864
static BOOL NTAPI ConSrvTermSetScreenInfo(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer, SHORT OldCursorX, SHORT OldCursorY)
Definition: terminal.c:895
static VOID NTAPI ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This, PCOORD pSize)
Definition: terminal.c:930
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:845
static VOID NTAPI ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This)
Definition: terminal.c:915
#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 struct @5505 FrontEndLoadingMethods[]
static BOOL NTAPI ConSrvTermSetPalette(IN OUT PTERMINAL This, HPALETTE PaletteHandle, UINT PaletteUsage)
Definition: terminal.c:938
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
#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:879
FRONTEND_UNLOAD FrontEndUnload
Definition: terminal.c:142
static VOID NTAPI ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This, IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
Definition: terminal.c:922
static BOOL NTAPI ConSrvTermSetCursorInfo(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer)
Definition: terminal.c:887
static BOOL NTAPI ConSrvTermSetCodePage(IN OUT PTERMINAL This, UINT CodePage)
Definition: terminal.c:947
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:908
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:77
#define KEY_EVENT
Definition: wincon.h:156
#define ENABLE_LINE_INPUT
Definition: wincon.h:108
#define COMMON_LVB_LEADING_BYTE
Definition: wincon.h:76
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336