2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Driver DLL
4 * FILE: win32ss/user/winsrv/consrv/condrv/text.c
5 * PURPOSE: Console Output Functions for text-mode screen-buffers
6 * PROGRAMMERS: Jeffrey Morlan
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *******************************************************************/
17 /* GLOBALS ********************************************************************/
21 /* PRIVATE FUNCTIONS **********************************************************/
23 CONSOLE_IO_OBJECT_TYPE
24 TEXTMODE_BUFFER_GetType(PCONSOLE_SCREEN_BUFFER This
)
26 // return This->Header.Type;
27 return TEXTMODE_BUFFER
;
30 static CONSOLE_SCREEN_BUFFER_VTBL TextVtbl
=
32 TEXTMODE_BUFFER_GetType
,
37 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff
);
41 CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
42 IN OUT PCONSOLE Console
,
45 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
);
49 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
50 IN OUT PCONSOLE Console
,
51 IN PTEXTMODE_BUFFER_INFO TextModeInfo
)
53 NTSTATUS Status
= STATUS_SUCCESS
;
54 PTEXTMODE_SCREEN_BUFFER NewBuffer
= NULL
;
56 if (Console
== NULL
|| Buffer
== NULL
|| TextModeInfo
== NULL
)
57 return STATUS_INVALID_PARAMETER
;
61 Status
= CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER
*)&NewBuffer
,
63 sizeof(TEXTMODE_SCREEN_BUFFER
));
64 if (!NT_SUCCESS(Status
)) return Status
;
65 NewBuffer
->Header
.Type
= TEXTMODE_BUFFER
;
66 NewBuffer
->Vtbl
= &TextVtbl
;
68 NewBuffer
->Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
69 TextModeInfo
->ScreenBufferSize
.X
*
70 TextModeInfo
->ScreenBufferSize
.Y
*
72 if (NewBuffer
->Buffer
== NULL
)
74 CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER
)NewBuffer
);
75 return STATUS_INSUFFICIENT_RESOURCES
;
78 NewBuffer
->ScreenBufferSize
= NewBuffer
->OldScreenBufferSize
79 = TextModeInfo
->ScreenBufferSize
;
80 NewBuffer
->ViewSize
= NewBuffer
->OldViewSize
81 = Console
->ConsoleSize
;
83 NewBuffer
->ViewOrigin
.X
= NewBuffer
->ViewOrigin
.Y
= 0;
84 NewBuffer
->VirtualY
= 0;
86 NewBuffer
->CursorBlinkOn
= NewBuffer
->ForceCursorOff
= FALSE
;
87 NewBuffer
->CursorInfo
.bVisible
= (TextModeInfo
->IsCursorVisible
&& (TextModeInfo
->CursorSize
!= 0));
88 NewBuffer
->CursorInfo
.dwSize
= min(max(TextModeInfo
->CursorSize
, 0), 100);
90 NewBuffer
->ScreenDefaultAttrib
= TextModeInfo
->ScreenAttrib
;
91 NewBuffer
->PopupDefaultAttrib
= TextModeInfo
->PopupAttrib
;
93 /* Initialize buffer to be empty with default attributes */
94 for (NewBuffer
->CursorPosition
.Y
= 0 ; NewBuffer
->CursorPosition
.Y
< NewBuffer
->ScreenBufferSize
.Y
; NewBuffer
->CursorPosition
.Y
++)
96 ClearLineBuffer(NewBuffer
);
98 NewBuffer
->CursorPosition
.X
= NewBuffer
->CursorPosition
.Y
= 0;
100 NewBuffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
102 *Buffer
= (PCONSOLE_SCREEN_BUFFER
)NewBuffer
;
103 return STATUS_SUCCESS
;
107 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
)
109 PTEXTMODE_SCREEN_BUFFER Buff
= (PTEXTMODE_SCREEN_BUFFER
)Buffer
;
112 * IMPORTANT !! Reinitialize the type so that we don't enter a recursive
113 * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy.
115 Buffer
->Header
.Type
= SCREEN_BUFFER
;
117 ConsoleFreeHeap(Buff
->Buffer
);
119 CONSOLE_SCREEN_BUFFER_Destroy(Buffer
);
124 ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
126 return &Buff
->Buffer
[((Y
+ Buff
->VirtualY
) % Buff
->ScreenBufferSize
.Y
) * Buff
->ScreenBufferSize
.X
+ X
];
130 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff
)
132 PCHAR_INFO Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CursorPosition
.Y
);
135 for (Pos
= 0; Pos
< Buff
->ScreenBufferSize
.X
; Pos
++, Ptr
++)
138 Ptr
->Char
.UnicodeChar
= L
' ';
139 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
143 static __inline BOOLEAN
144 ConioGetIntersection(OUT PSMALL_RECT Intersection
,
145 IN PSMALL_RECT Rect1
,
146 IN PSMALL_RECT Rect2
)
148 if ( ConioIsRectEmpty(Rect1
) ||
149 ConioIsRectEmpty(Rect2
) ||
150 (Rect1
->Top
> Rect2
->Bottom
) ||
151 (Rect1
->Left
> Rect2
->Right
) ||
152 (Rect1
->Bottom
< Rect2
->Top
) ||
153 (Rect1
->Right
< Rect2
->Left
) )
155 /* The rectangles do not intersect */
156 ConioInitRect(Intersection
, 0, -1, 0, -1);
160 ConioInitRect(Intersection
,
161 max(Rect1
->Top
, Rect2
->Top
),
162 max(Rect1
->Left
, Rect2
->Left
),
163 min(Rect1
->Bottom
, Rect2
->Bottom
),
164 min(Rect1
->Right
, Rect2
->Right
));
169 static __inline BOOLEAN
170 ConioGetUnion(OUT PSMALL_RECT Union
,
171 IN PSMALL_RECT Rect1
,
172 IN PSMALL_RECT Rect2
)
174 if (ConioIsRectEmpty(Rect1
))
176 if (ConioIsRectEmpty(Rect2
))
178 ConioInitRect(Union
, 0, -1, 0, -1);
186 else if (ConioIsRectEmpty(Rect2
))
193 min(Rect1
->Top
, Rect2
->Top
),
194 min(Rect1
->Left
, Rect2
->Left
),
195 max(Rect1
->Bottom
, Rect2
->Bottom
),
196 max(Rect1
->Right
, Rect2
->Right
));
203 ConioComputeUpdateRect(IN PTEXTMODE_SCREEN_BUFFER Buff
,
204 IN OUT PSMALL_RECT UpdateRect
,
208 if (Buff
->ScreenBufferSize
.X
<= Start
->X
+ Length
)
210 UpdateRect
->Left
= 0;
214 UpdateRect
->Left
= Start
->X
;
216 if (Buff
->ScreenBufferSize
.X
<= Start
->X
+ Length
)
218 UpdateRect
->Right
= Buff
->ScreenBufferSize
.X
- 1;
222 UpdateRect
->Right
= Start
->X
+ Length
- 1;
224 UpdateRect
->Top
= Start
->Y
;
225 UpdateRect
->Bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->ScreenBufferSize
.X
;
226 if (Buff
->ScreenBufferSize
.Y
<= UpdateRect
->Bottom
)
228 UpdateRect
->Bottom
= Buff
->ScreenBufferSize
.Y
- 1;
233 * Move from one rectangle to another. We must be careful about the order that
234 * this is done, to avoid overwriting parts of the source before they are moved.
237 ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
238 PSMALL_RECT SrcRegion
,
239 PSMALL_RECT DstRegion
,
240 PSMALL_RECT ClipRegion
,
243 int Width
= ConioRectWidth(SrcRegion
);
244 int Height
= ConioRectHeight(SrcRegion
);
255 /* Moving down: work from bottom up */
256 SY
= SrcRegion
->Bottom
;
257 DY
= DstRegion
->Bottom
;
260 for (i
= 0; i
< Height
; i
++)
262 PCHAR_INFO SRow
= ConioCoordToPointer(ScreenBuffer
, 0, SY
);
263 PCHAR_INFO DRow
= ConioCoordToPointer(ScreenBuffer
, 0, DY
);
265 SX
= SrcRegion
->Left
;
266 DX
= DstRegion
->Left
;
270 /* Moving right: work from right to left */
271 SX
= SrcRegion
->Right
;
272 DX
= DstRegion
->Right
;
275 for (j
= 0; j
< Width
; j
++)
277 CHAR_INFO Cell
= SRow
[SX
];
278 if (SX
>= ClipRegion
->Left
&& SX
<= ClipRegion
->Right
&&
279 SY
>= ClipRegion
->Top
&& SY
<= ClipRegion
->Bottom
)
283 if (DX
>= ClipRegion
->Left
&& DX
<= ClipRegion
->Right
&&
284 DY
>= ClipRegion
->Top
&& DY
<= ClipRegion
->Bottom
)
297 ConioEffectiveCursorSize(PCONSOLE Console
, DWORD Scale
)
299 DWORD Size
= (Console
->ActiveBuffer
->CursorInfo
.dwSize
* Scale
+ 99) / 100;
300 /* If line input in progress, perhaps adjust for insert toggle */
301 if (Console
->LineBuffer
&& !Console
->LineComplete
&& (Console
->InsertMode
? !Console
->LineInsertToggle
: Console
->LineInsertToggle
))
302 return (Size
* 2 <= Scale
) ? (Size
* 2) : (Size
/ 2);
307 ConioResizeBuffer(PCONSOLE Console
,
308 PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
314 WORD CurrentAttribute
;
316 PCHAR_INFO OldBuffer
;
320 /* Buffer size is not allowed to be smaller than the view size */
321 if (Size
.X
< ScreenBuffer
->ViewSize
.X
|| Size
.Y
< ScreenBuffer
->ViewSize
.Y
)
322 return STATUS_INVALID_PARAMETER
;
324 if (Size
.X
== ScreenBuffer
->ScreenBufferSize
.X
&& Size
.Y
== ScreenBuffer
->ScreenBufferSize
.Y
)
326 // FIXME: Trigger a buffer resize event ??
327 return STATUS_SUCCESS
;
330 if (Console
->FixedSize
)
333 * The console is in fixed-size mode, so we cannot resize anything
334 * at the moment. However, keep those settings somewhere so that
335 * we can try to set them up when we will be allowed to do so.
337 ScreenBuffer
->OldScreenBufferSize
= Size
;
338 return STATUS_NOT_SUPPORTED
; // STATUS_SUCCESS
341 Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Size
.X
* Size
.Y
* sizeof(CHAR_INFO
));
342 if (!Buffer
) return STATUS_NO_MEMORY
;
344 DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer
->ScreenBufferSize
.X
, ScreenBuffer
->ScreenBufferSize
.Y
, Size
.X
, Size
.Y
);
345 OldBuffer
= ScreenBuffer
->Buffer
;
347 for (CurrentY
= 0; CurrentY
< ScreenBuffer
->ScreenBufferSize
.Y
&& CurrentY
< Size
.Y
; CurrentY
++)
349 ptr
= ConioCoordToPointer(ScreenBuffer
, 0, CurrentY
);
350 if (Size
.X
<= ScreenBuffer
->ScreenBufferSize
.X
)
353 RtlCopyMemory(Buffer
+ Offset
, ptr
, Size
.X
* sizeof(CHAR_INFO
));
359 RtlCopyMemory(Buffer
+ Offset
, ptr
, ScreenBuffer
->ScreenBufferSize
.X
* sizeof(CHAR_INFO
));
360 Offset
+= ScreenBuffer
->ScreenBufferSize
.X
;
362 /* The attribute to be used is the one of the last cell of the current line */
363 CurrentAttribute
= ConioCoordToPointer(ScreenBuffer
,
364 ScreenBuffer
->ScreenBufferSize
.X
- 1,
365 CurrentY
)->Attributes
;
367 diff
= Size
.X
- ScreenBuffer
->ScreenBufferSize
.X
;
369 /* Zero-out the new part of the buffer */
370 for (i
= 0; i
< diff
; i
++)
372 ptr
= Buffer
+ Offset
;
373 ptr
->Char
.UnicodeChar
= L
' ';
374 ptr
->Attributes
= CurrentAttribute
;
380 if (Size
.Y
> ScreenBuffer
->ScreenBufferSize
.Y
)
382 diff
= Size
.X
* (Size
.Y
- ScreenBuffer
->ScreenBufferSize
.Y
);
384 /* Zero-out the new part of the buffer */
385 for (i
= 0; i
< diff
; i
++)
387 ptr
= Buffer
+ Offset
;
388 ptr
->Char
.UnicodeChar
= L
' ';
389 ptr
->Attributes
= ScreenBuffer
->ScreenDefaultAttrib
;
394 (void)InterlockedExchangePointer((PVOID
volatile*)&ScreenBuffer
->Buffer
, Buffer
);
395 ConsoleFreeHeap(OldBuffer
);
396 ScreenBuffer
->ScreenBufferSize
= ScreenBuffer
->OldScreenBufferSize
= Size
;
397 ScreenBuffer
->VirtualY
= 0;
399 /* Ensure cursor and window are within buffer */
400 if (ScreenBuffer
->CursorPosition
.X
>= Size
.X
)
401 ScreenBuffer
->CursorPosition
.X
= Size
.X
- 1;
402 if (ScreenBuffer
->CursorPosition
.Y
>= Size
.Y
)
403 ScreenBuffer
->CursorPosition
.Y
= Size
.Y
- 1;
404 if (ScreenBuffer
->ViewOrigin
.X
> Size
.X
- ScreenBuffer
->ViewSize
.X
)
405 ScreenBuffer
->ViewOrigin
.X
= Size
.X
- ScreenBuffer
->ViewSize
.X
;
406 if (ScreenBuffer
->ViewOrigin
.Y
> Size
.Y
- ScreenBuffer
->ViewSize
.Y
)
407 ScreenBuffer
->ViewOrigin
.Y
= Size
.Y
- ScreenBuffer
->ViewSize
.Y
;
410 * Trigger a buffer resize event
412 if (Console
->InputBuffer
.Mode
& ENABLE_WINDOW_INPUT
)
416 er
.EventType
= WINDOW_BUFFER_SIZE_EVENT
;
417 er
.Event
.WindowBufferSizeEvent
.dwSize
= ScreenBuffer
->ScreenBufferSize
;
419 ConioProcessInputEvent(Console
, &er
);
422 return STATUS_SUCCESS
;
426 ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff
, PSMALL_RECT UpdateRect
, PUINT ScrolledLines
)
428 /* If we hit bottom, slide the viewable screen */
429 if (++Buff
->CursorPosition
.Y
== Buff
->ScreenBufferSize
.Y
)
431 Buff
->CursorPosition
.Y
--;
432 if (++Buff
->VirtualY
== Buff
->ScreenBufferSize
.Y
)
437 ClearLineBuffer(Buff
);
438 if (UpdateRect
->Top
!= 0)
443 UpdateRect
->Left
= 0;
444 UpdateRect
->Right
= Buff
->ScreenBufferSize
.X
- 1;
445 UpdateRect
->Bottom
= Buff
->CursorPosition
.Y
;
449 ConioWriteConsole(PCONSOLE Console
,
450 PTEXTMODE_SCREEN_BUFFER Buff
,
457 SMALL_RECT UpdateRect
;
458 SHORT CursorStartX
, CursorStartY
;
461 CursorStartX
= Buff
->CursorPosition
.X
;
462 CursorStartY
= Buff
->CursorPosition
.Y
;
463 UpdateRect
.Left
= Buff
->ScreenBufferSize
.X
;
464 UpdateRect
.Top
= Buff
->CursorPosition
.Y
;
465 UpdateRect
.Right
= -1;
466 UpdateRect
.Bottom
= Buff
->CursorPosition
.Y
;
469 for (i
= 0; i
< Length
; i
++)
472 * If we are in processed mode, interpret special characters and
473 * display them correctly. Otherwise, just put them into the buffer.
475 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
478 if (Buffer
[i
] == L
'\r')
480 Buff
->CursorPosition
.X
= 0;
481 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
482 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
486 else if (Buffer
[i
] == L
'\n')
488 Buff
->CursorPosition
.X
= 0;
489 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
493 else if (Buffer
[i
] == L
'\b')
495 /* Only handle BS if we're not on the first pos of the first line */
496 if (0 != Buff
->CursorPosition
.X
|| 0 != Buff
->CursorPosition
.Y
)
498 if (0 == Buff
->CursorPosition
.X
)
500 /* slide virtual position up */
501 Buff
->CursorPosition
.X
= Buff
->ScreenBufferSize
.X
- 1;
502 Buff
->CursorPosition
.Y
--;
503 UpdateRect
.Top
= min(UpdateRect
.Top
, Buff
->CursorPosition
.Y
);
507 Buff
->CursorPosition
.X
--;
509 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
510 Ptr
->Char
.UnicodeChar
= L
' ';
511 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
512 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
513 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
518 else if (Buffer
[i
] == L
'\t')
522 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
523 EndX
= (Buff
->CursorPosition
.X
+ TAB_WIDTH
) & ~(TAB_WIDTH
- 1);
524 EndX
= min(EndX
, (UINT
)Buff
->ScreenBufferSize
.X
);
525 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
526 while (Buff
->CursorPosition
.X
< EndX
)
528 Ptr
->Char
.UnicodeChar
= L
' ';
529 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
531 Buff
->CursorPosition
.X
++;
533 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
- 1);
534 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
536 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
538 Buff
->CursorPosition
.X
= 0;
539 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
543 Buff
->CursorPosition
.X
--;
549 // else if (Buffer[i] == L'\a')
551 // // FIXME: This MUST BE moved to the terminal emulator frontend!!
552 // DPRINT1("Bell\n");
553 // // SendNotifyMessage(Console->hWindow, PM_CONSOLE_BEEP, 0, 0);
557 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
558 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
560 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
561 Ptr
->Char
.UnicodeChar
= Buffer
[i
];
562 if (Attrib
) Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
564 Buff
->CursorPosition
.X
++;
565 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
567 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
569 Buff
->CursorPosition
.X
= 0;
570 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
574 Buff
->CursorPosition
.X
= CursorStartX
;
579 if (!ConioIsRectEmpty(&UpdateRect
) && (PCONSOLE_SCREEN_BUFFER
)Buff
== Console
->ActiveBuffer
)
581 TermWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
,
582 ScrolledLines
, Buffer
, Length
);
585 return STATUS_SUCCESS
;
589 ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console
,
590 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
591 IN USHORT NewScreenAttrib
,
592 IN USHORT NewPopupAttrib
)
598 ULONG NumCodesToWrite
;
599 USHORT OldScreenAttrib
;
601 if (Console
== NULL
|| Buffer
== NULL
)
603 return STATUS_INVALID_PARAMETER
;
607 ASSERT(Console
== Buffer
->Header
.Console
);
609 NumCodesToWrite
= Buffer
->ScreenBufferSize
.X
* Buffer
->ScreenBufferSize
.Y
;
610 OldScreenAttrib
= Buffer
->ScreenDefaultAttrib
;
613 Y
= (TopLeft
.Y
+ Buffer
->VirtualY
) % Buffer
->ScreenBufferSize
.Y
;
614 Length
= NumCodesToWrite
;
616 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
617 // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
621 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
622 Ptr
= &Buffer
->Buffer
[X
+ Y
* Buffer
->ScreenBufferSize
.X
];
625 * Change the current colors only if they are the old ones.
628 /* Foreground color */
629 if ((Ptr
->Attributes
& 0x0F) == (OldScreenAttrib
& 0x0F))
630 Ptr
->Attributes
= (Ptr
->Attributes
& 0xFFF0) | (NewScreenAttrib
& 0x0F);
632 /* Background color */
633 if ((Ptr
->Attributes
& 0xF0) == (OldScreenAttrib
& 0xF0))
634 Ptr
->Attributes
= (Ptr
->Attributes
& 0xFF0F) | (NewScreenAttrib
& 0xF0);
638 if (++X
== Buffer
->ScreenBufferSize
.X
)
642 if (++Y
== Buffer
->ScreenBufferSize
.Y
)
649 /* Save foreground and background colors for both screen and popup */
650 Buffer
->ScreenDefaultAttrib
= (NewScreenAttrib
& 0x00FF);
651 Buffer
->PopupDefaultAttrib
= (NewPopupAttrib
& 0x00FF);
653 /* Refresh the display if needed */
654 if ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
)
656 SMALL_RECT UpdateRect
;
657 ConioComputeUpdateRect(Buffer
, &UpdateRect
, &TopLeft
, NumCodesToWrite
);
658 TermDrawRegion(Console
, &UpdateRect
);
661 return STATUS_SUCCESS
;
665 /* PUBLIC DRIVER APIS *********************************************************/
668 ConDrvReadConsoleOutput(IN PCONSOLE Console
,
669 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
671 OUT PCHAR_INFO CharInfo
/*Buffer*/,
672 IN PCOORD BufferSize
,
673 IN PCOORD BufferCoord
,
674 IN OUT PSMALL_RECT ReadRegion
)
676 PCHAR_INFO CurCharInfo
;
678 SMALL_RECT CapturedReadRegion
;
679 SMALL_RECT ScreenRect
;
685 if (Console
== NULL
|| Buffer
== NULL
|| CharInfo
== NULL
||
686 BufferSize
== NULL
|| BufferCoord
== NULL
|| ReadRegion
== NULL
)
688 return STATUS_INVALID_PARAMETER
;
692 ASSERT(Console
== Buffer
->Header
.Console
);
694 CapturedReadRegion
= *ReadRegion
;
696 /* FIXME: Is this correct? */
697 CodePage
= Console
->OutputCodePage
;
699 SizeX
= min(BufferSize
->X
- BufferCoord
->X
, ConioRectWidth(&CapturedReadRegion
));
700 SizeY
= min(BufferSize
->Y
- BufferCoord
->Y
, ConioRectHeight(&CapturedReadRegion
));
701 CapturedReadRegion
.Right
= CapturedReadRegion
.Left
+ SizeX
;
702 CapturedReadRegion
.Bottom
= CapturedReadRegion
.Top
+ SizeY
;
704 ConioInitRect(&ScreenRect
, 0, 0, Buffer
->ScreenBufferSize
.Y
, Buffer
->ScreenBufferSize
.X
);
705 if (!ConioGetIntersection(&CapturedReadRegion
, &ScreenRect
, &CapturedReadRegion
))
707 return STATUS_SUCCESS
;
710 for (i
= 0, Y
= CapturedReadRegion
.Top
; Y
< CapturedReadRegion
.Bottom
; ++i
, ++Y
)
712 CurCharInfo
= CharInfo
+ (i
* BufferSize
->X
);
714 Ptr
= ConioCoordToPointer(Buffer
, CapturedReadRegion
.Left
, Y
);
715 for (X
= CapturedReadRegion
.Left
; X
< CapturedReadRegion
.Right
; ++X
)
719 CurCharInfo
->Char
.UnicodeChar
= Ptr
->Char
.UnicodeChar
;
723 // ConsoleUnicodeCharToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar);
724 WideCharToMultiByte(CodePage
, 0, &Ptr
->Char
.UnicodeChar
, 1,
725 &CurCharInfo
->Char
.AsciiChar
, 1, NULL
, NULL
);
727 CurCharInfo
->Attributes
= Ptr
->Attributes
;
733 ReadRegion
->Left
= CapturedReadRegion
.Left
;
734 ReadRegion
->Top
= CapturedReadRegion
.Top
;
735 ReadRegion
->Right
= CapturedReadRegion
.Left
+ SizeX
- 1;
736 ReadRegion
->Bottom
= CapturedReadRegion
.Top
+ SizeY
- 1;
738 return STATUS_SUCCESS
;
742 ConDrvWriteConsoleOutput(IN PCONSOLE Console
,
743 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
745 IN PCHAR_INFO CharInfo
/*Buffer*/,
746 IN PCOORD BufferSize
,
747 IN PCOORD BufferCoord
,
748 IN OUT PSMALL_RECT WriteRegion
)
750 SHORT i
, X
, Y
, SizeX
, SizeY
;
751 SMALL_RECT ScreenBuffer
;
752 PCHAR_INFO CurCharInfo
;
753 SMALL_RECT CapturedWriteRegion
;
756 if (Console
== NULL
|| Buffer
== NULL
|| CharInfo
== NULL
||
757 BufferSize
== NULL
|| BufferCoord
== NULL
|| WriteRegion
== NULL
)
759 return STATUS_INVALID_PARAMETER
;
763 ASSERT(Console
== Buffer
->Header
.Console
);
765 CapturedWriteRegion
= *WriteRegion
;
767 SizeX
= min(BufferSize
->X
- BufferCoord
->X
, ConioRectWidth(&CapturedWriteRegion
));
768 SizeY
= min(BufferSize
->Y
- BufferCoord
->Y
, ConioRectHeight(&CapturedWriteRegion
));
769 CapturedWriteRegion
.Right
= CapturedWriteRegion
.Left
+ SizeX
- 1;
770 CapturedWriteRegion
.Bottom
= CapturedWriteRegion
.Top
+ SizeY
- 1;
772 /* Make sure WriteRegion is inside the screen buffer */
773 ConioInitRect(&ScreenBuffer
, 0, 0, Buffer
->ScreenBufferSize
.Y
- 1, Buffer
->ScreenBufferSize
.X
- 1);
774 if (!ConioGetIntersection(&CapturedWriteRegion
, &ScreenBuffer
, &CapturedWriteRegion
))
777 * It is okay to have a WriteRegion completely outside
778 * the screen buffer. No data is written then.
780 return STATUS_SUCCESS
;
783 for (i
= 0, Y
= CapturedWriteRegion
.Top
; Y
<= CapturedWriteRegion
.Bottom
; i
++, Y
++)
785 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
->Y
) * BufferSize
->X
+ BufferCoord
->X
;
787 Ptr
= ConioCoordToPointer(Buffer
, CapturedWriteRegion
.Left
, Y
);
788 for (X
= CapturedWriteRegion
.Left
; X
<= CapturedWriteRegion
.Right
; X
++)
792 Ptr
->Char
.UnicodeChar
= CurCharInfo
->Char
.UnicodeChar
;
796 ConsoleAnsiCharToUnicodeChar(Console
, &Ptr
->Char
.UnicodeChar
, &CurCharInfo
->Char
.AsciiChar
);
798 Ptr
->Attributes
= CurCharInfo
->Attributes
;
804 TermDrawRegion(Console
, &CapturedWriteRegion
);
806 WriteRegion
->Left
= CapturedWriteRegion
.Left
;
807 WriteRegion
->Top
= CapturedWriteRegion
.Top
;
808 WriteRegion
->Right
= CapturedWriteRegion
.Left
+ SizeX
- 1;
809 WriteRegion
->Bottom
= CapturedWriteRegion
.Top
+ SizeY
- 1;
811 return STATUS_SUCCESS
;
815 ConDrvWriteConsole(IN PCONSOLE Console
,
816 IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
818 IN PVOID StringBuffer
,
819 IN ULONG NumCharsToWrite
,
820 OUT PULONG NumCharsWritten OPTIONAL
)
822 NTSTATUS Status
= STATUS_SUCCESS
;
823 PWCHAR Buffer
= NULL
;
827 if (Console
== NULL
|| ScreenBuffer
== NULL
/* || StringBuffer == NULL */)
828 return STATUS_INVALID_PARAMETER
;
830 /* Validity checks */
831 ASSERT(Console
== ScreenBuffer
->Header
.Console
);
832 ASSERT((StringBuffer
!= NULL
) || (StringBuffer
== NULL
&& NumCharsToWrite
== 0));
834 // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
835 if (Console
->PauseFlags
&& Console
->UnpauseEvent
!= NULL
)
837 return STATUS_PENDING
;
842 Buffer
= StringBuffer
;
846 Length
= MultiByteToWideChar(Console
->OutputCodePage
, 0,
850 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
* sizeof(WCHAR
));
853 MultiByteToWideChar(Console
->OutputCodePage
, 0,
856 (PWCHAR
)Buffer
, Length
);
860 Status
= STATUS_NO_MEMORY
;
866 if (NT_SUCCESS(Status
))
868 Status
= ConioWriteConsole(Console
,
873 if (NT_SUCCESS(Status
))
875 Written
= NumCharsToWrite
;
879 if (!Unicode
) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
882 if (NumCharsWritten
) *NumCharsWritten
= Written
;
888 ConDrvReadConsoleOutputString(IN PCONSOLE Console
,
889 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
890 IN CODE_TYPE CodeType
,
891 OUT PVOID StringBuffer
,
892 IN ULONG NumCodesToRead
,
894 // OUT PCOORD EndCoord,
895 OUT PULONG NumCodesRead OPTIONAL
)
903 if (Console
== NULL
|| Buffer
== NULL
|| ReadCoord
== NULL
/* || EndCoord == NULL */)
905 return STATUS_INVALID_PARAMETER
;
908 /* Validity checks */
909 ASSERT(Console
== Buffer
->Header
.Console
);
910 ASSERT((StringBuffer
!= NULL
) || (StringBuffer
== NULL
&& NumCodesToRead
== 0));
912 if (NumCodesRead
) *NumCodesRead
= 0;
917 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
921 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
925 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
929 return STATUS_INVALID_PARAMETER
;
932 ReadBuffer
= StringBuffer
;
934 Ypos
= (ReadCoord
->Y
+ Buffer
->VirtualY
) % Buffer
->ScreenBufferSize
.Y
;
937 * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
939 * If the number of attributes (resp. characters) to be read from extends
940 * beyond the end of the specified screen buffer row, attributes (resp.
941 * characters) are read from the next row. If the number of attributes
942 * (resp. characters) to be read from extends beyond the end of the console
943 * screen buffer, attributes (resp. characters) up to the end of the console
944 * screen buffer are read.
946 * TODO: Do NOT loop up to NumCodesToRead, but stop before
947 * if we are going to overflow...
949 // Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); // Doesn't work
950 for (i
= 0; i
< min(NumCodesToRead
, Buffer
->ScreenBufferSize
.X
* Buffer
->ScreenBufferSize
.Y
); ++i
)
952 // Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); // Doesn't work either
953 Ptr
= &Buffer
->Buffer
[Xpos
+ Ypos
* Buffer
->ScreenBufferSize
.X
];
958 ConsoleUnicodeCharToAnsiChar(Console
, (PCHAR
)ReadBuffer
, &Ptr
->Char
.UnicodeChar
);
962 *(PWCHAR
)ReadBuffer
= Ptr
->Char
.UnicodeChar
;
966 *(PWORD
)ReadBuffer
= Ptr
->Attributes
;
969 ReadBuffer
= (PVOID
)((ULONG_PTR
)ReadBuffer
+ CodeSize
);
974 if (Xpos
== Buffer
->ScreenBufferSize
.X
)
979 if (Ypos
== Buffer
->ScreenBufferSize
.Y
)
986 // EndCoord->X = Xpos;
987 // EndCoord->Y = (Ypos - Buffer->VirtualY + Buffer->ScreenBufferSize.Y) % Buffer->ScreenBufferSize.Y;
990 *NumCodesRead
= (ULONG
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)StringBuffer
) / CodeSize
;
993 return STATUS_SUCCESS
;
997 ConDrvWriteConsoleOutputString(IN PCONSOLE Console
,
998 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
999 IN CODE_TYPE CodeType
,
1000 IN PVOID StringBuffer
,
1001 IN ULONG NumCodesToWrite
,
1002 IN PCOORD WriteCoord
,
1003 // OUT PCOORD EndCoord,
1004 OUT PULONG NumCodesWritten OPTIONAL
)
1006 NTSTATUS Status
= STATUS_SUCCESS
;
1007 PVOID WriteBuffer
= NULL
;
1008 PWCHAR tmpString
= NULL
;
1009 DWORD X
, Y
, Length
; // , Written = 0;
1013 if (Console
== NULL
|| Buffer
== NULL
|| WriteCoord
== NULL
/* || EndCoord == NULL */)
1015 return STATUS_INVALID_PARAMETER
;
1018 /* Validity checks */
1019 ASSERT(Console
== Buffer
->Header
.Console
);
1020 ASSERT((StringBuffer
!= NULL
) || (StringBuffer
== NULL
&& NumCodesToWrite
== 0));
1022 if (NumCodesWritten
) *NumCodesWritten
= 0;
1027 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
1031 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
1034 case CODE_ATTRIBUTE
:
1035 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
1039 return STATUS_INVALID_PARAMETER
;
1042 if (CodeType
== CODE_ASCII
)
1044 /* Convert the ASCII string into Unicode before writing it to the console */
1045 Length
= MultiByteToWideChar(Console
->OutputCodePage
, 0,
1046 (PCHAR
)StringBuffer
,
1049 tmpString
= WriteBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
* sizeof(WCHAR
));
1052 MultiByteToWideChar(Console
->OutputCodePage
, 0,
1053 (PCHAR
)StringBuffer
,
1055 (PWCHAR
)WriteBuffer
, Length
);
1059 Status
= STATUS_NO_MEMORY
;
1064 /* For CODE_UNICODE or CODE_ATTRIBUTE, we are already OK */
1065 WriteBuffer
= StringBuffer
;
1068 if (WriteBuffer
== NULL
|| !NT_SUCCESS(Status
)) goto Cleanup
;
1071 Y
= (WriteCoord
->Y
+ Buffer
->VirtualY
) % Buffer
->ScreenBufferSize
.Y
;
1072 Length
= NumCodesToWrite
;
1073 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
1074 // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
1078 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
1079 Ptr
= &Buffer
->Buffer
[X
+ Y
* Buffer
->ScreenBufferSize
.X
];
1085 Ptr
->Char
.UnicodeChar
= *(PWCHAR
)WriteBuffer
;
1088 case CODE_ATTRIBUTE
:
1089 Ptr
->Attributes
= *(PWORD
)WriteBuffer
;
1092 WriteBuffer
= (PVOID
)((ULONG_PTR
)WriteBuffer
+ CodeSize
);
1096 if (++X
== Buffer
->ScreenBufferSize
.X
)
1100 if (++Y
== Buffer
->ScreenBufferSize
.Y
)
1107 if ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
)
1109 SMALL_RECT UpdateRect
;
1110 ConioComputeUpdateRect(Buffer
, &UpdateRect
, WriteCoord
, NumCodesToWrite
);
1111 TermDrawRegion(Console
, &UpdateRect
);
1115 // EndCoord->Y = (Y + Buffer->ScreenBufferSize.Y - Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
1118 if (tmpString
) RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString
);
1120 if (NumCodesWritten
) *NumCodesWritten
= NumCodesToWrite
; // Written;
1125 ConDrvFillConsoleOutput(IN PCONSOLE Console
,
1126 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1127 IN CODE_TYPE CodeType
,
1128 IN CODE_ELEMENT Code
,
1129 IN ULONG NumCodesToWrite
,
1130 IN PCOORD WriteCoord
,
1131 OUT PULONG NumCodesWritten OPTIONAL
)
1133 DWORD X
, Y
, Length
; // , Written = 0;
1136 if (Console
== NULL
|| Buffer
== NULL
|| WriteCoord
== NULL
)
1138 return STATUS_INVALID_PARAMETER
;
1141 /* Validity check */
1142 ASSERT(Console
== Buffer
->Header
.Console
);
1144 if (NumCodesWritten
) *NumCodesWritten
= 0;
1146 if (CodeType
== CODE_ASCII
)
1148 /* Conversion from the ASCII char to the UNICODE char */
1150 ConsoleAnsiCharToUnicodeChar(Console
, &tmp
.UnicodeChar
, &Code
.AsciiChar
);
1155 Y
= (WriteCoord
->Y
+ Buffer
->VirtualY
) % Buffer
->ScreenBufferSize
.Y
;
1156 Length
= NumCodesToWrite
;
1157 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
1158 // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
1162 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
1163 Ptr
= &Buffer
->Buffer
[X
+ Y
* Buffer
->ScreenBufferSize
.X
];
1169 Ptr
->Char
.UnicodeChar
= Code
.UnicodeChar
;
1172 case CODE_ATTRIBUTE
:
1173 Ptr
->Attributes
= Code
.Attribute
;
1179 if (++X
== Buffer
->ScreenBufferSize
.X
)
1183 if (++Y
== Buffer
->ScreenBufferSize
.Y
)
1190 if ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
)
1192 SMALL_RECT UpdateRect
;
1193 ConioComputeUpdateRect(Buffer
, &UpdateRect
, WriteCoord
, NumCodesToWrite
);
1194 TermDrawRegion(Console
, &UpdateRect
);
1197 if (NumCodesWritten
) *NumCodesWritten
= NumCodesToWrite
; // Written;
1198 return STATUS_SUCCESS
;
1202 ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console
,
1203 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1204 OUT PCOORD ScreenBufferSize
,
1205 OUT PCOORD CursorPosition
,
1206 OUT PCOORD ViewOrigin
,
1207 OUT PCOORD ViewSize
,
1208 OUT PCOORD MaximumViewSize
,
1209 OUT PWORD Attributes
)
1211 if (Console
== NULL
|| Buffer
== NULL
|| ScreenBufferSize
== NULL
||
1212 CursorPosition
== NULL
|| ViewOrigin
== NULL
|| ViewSize
== NULL
||
1213 MaximumViewSize
== NULL
|| Attributes
== NULL
)
1215 return STATUS_INVALID_PARAMETER
;
1218 /* Validity check */
1219 ASSERT(Console
== Buffer
->Header
.Console
);
1221 *ScreenBufferSize
= Buffer
->ScreenBufferSize
;
1222 *CursorPosition
= Buffer
->CursorPosition
;
1223 *ViewOrigin
= Buffer
->ViewOrigin
;
1224 *ViewSize
= Buffer
->ViewSize
;
1225 *Attributes
= Buffer
->ScreenDefaultAttrib
;
1227 // FIXME: Refine the computation
1228 *MaximumViewSize
= Buffer
->ScreenBufferSize
;
1230 return STATUS_SUCCESS
;
1234 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console
,
1235 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1238 if (Console
== NULL
|| Buffer
== NULL
)
1239 return STATUS_INVALID_PARAMETER
;
1241 /* Validity check */
1242 ASSERT(Console
== Buffer
->Header
.Console
);
1244 Buffer
->ScreenDefaultAttrib
= Attributes
;
1245 return STATUS_SUCCESS
;
1249 ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console
,
1250 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1255 if (Console
== NULL
|| Buffer
== NULL
|| Size
== NULL
)
1256 return STATUS_INVALID_PARAMETER
;
1258 /* Validity check */
1259 ASSERT(Console
== Buffer
->Header
.Console
);
1261 Status
= ConioResizeBuffer(Console
, Buffer
, *Size
);
1262 if (NT_SUCCESS(Status
)) TermResizeTerminal(Console
);
1268 ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console
,
1269 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1271 IN PSMALL_RECT ScrollRectangle
,
1272 IN BOOLEAN UseClipRectangle
,
1273 IN PSMALL_RECT ClipRectangle OPTIONAL
,
1274 IN PCOORD DestinationOrigin
,
1275 IN CHAR_INFO FillChar
)
1277 COORD CapturedDestinationOrigin
;
1278 SMALL_RECT ScreenBuffer
;
1279 SMALL_RECT SrcRegion
;
1280 SMALL_RECT DstRegion
;
1281 SMALL_RECT UpdateRegion
;
1282 SMALL_RECT CapturedClipRectangle
;
1284 if (Console
== NULL
|| Buffer
== NULL
|| ScrollRectangle
== NULL
||
1285 (UseClipRectangle
? ClipRectangle
== NULL
: FALSE
) || DestinationOrigin
== NULL
)
1287 return STATUS_INVALID_PARAMETER
;
1290 /* Validity check */
1291 ASSERT(Console
== Buffer
->Header
.Console
);
1293 CapturedDestinationOrigin
= *DestinationOrigin
;
1295 /* Make sure the source rectangle is inside the screen buffer */
1296 ConioInitRect(&ScreenBuffer
, 0, 0, Buffer
->ScreenBufferSize
.Y
- 1, Buffer
->ScreenBufferSize
.X
- 1);
1297 if (!ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, ScrollRectangle
))
1299 return STATUS_SUCCESS
;
1302 /* If the source was clipped on the left or top, adjust the destination accordingly */
1303 if (ScrollRectangle
->Left
< 0)
1305 CapturedDestinationOrigin
.X
-= ScrollRectangle
->Left
;
1307 if (ScrollRectangle
->Top
< 0)
1309 CapturedDestinationOrigin
.Y
-= ScrollRectangle
->Top
;
1312 if (UseClipRectangle
)
1314 CapturedClipRectangle
= *ClipRectangle
;
1315 if (!ConioGetIntersection(&CapturedClipRectangle
, &CapturedClipRectangle
, &ScreenBuffer
))
1317 return STATUS_SUCCESS
;
1322 CapturedClipRectangle
= ScreenBuffer
;
1325 ConioInitRect(&DstRegion
,
1326 CapturedDestinationOrigin
.Y
,
1327 CapturedDestinationOrigin
.X
,
1328 CapturedDestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1329 CapturedDestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1334 ConsoleAnsiCharToUnicodeChar(Console
, &tmp
, &FillChar
.Char
.AsciiChar
);
1335 FillChar
.Char
.UnicodeChar
= tmp
;
1338 ConioMoveRegion(Buffer
, &SrcRegion
, &DstRegion
, &CapturedClipRectangle
, FillChar
);
1340 if ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
)
1342 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1343 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &CapturedClipRectangle
))
1345 /* Draw update region */
1346 TermDrawRegion(Console
, &UpdateRegion
);
1350 return STATUS_SUCCESS
;
1354 ConDrvSetConsoleWindowInfo(IN PCONSOLE Console
,
1355 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1356 IN BOOLEAN Absolute
,
1357 IN PSMALL_RECT WindowRect
)
1359 SMALL_RECT CapturedWindowRect
;
1361 if (Console
== NULL
|| Buffer
== NULL
|| WindowRect
== NULL
)
1362 return STATUS_INVALID_PARAMETER
;
1364 /* Validity check */
1365 ASSERT(Console
== Buffer
->Header
.Console
);
1367 CapturedWindowRect
= *WindowRect
;
1369 if (Absolute
== FALSE
)
1371 /* Relative positions given. Transform them to absolute ones */
1372 CapturedWindowRect
.Left
+= Buffer
->ViewOrigin
.X
;
1373 CapturedWindowRect
.Top
+= Buffer
->ViewOrigin
.Y
;
1374 CapturedWindowRect
.Right
+= Buffer
->ViewOrigin
.X
+ Buffer
->ViewSize
.X
- 1;
1375 CapturedWindowRect
.Bottom
+= Buffer
->ViewOrigin
.Y
+ Buffer
->ViewSize
.Y
- 1;
1378 /* See MSDN documentation on SetConsoleWindowInfo about the performed checks */
1379 if ( (CapturedWindowRect
.Left
< 0) || (CapturedWindowRect
.Top
< 0) ||
1380 (CapturedWindowRect
.Right
>= Buffer
->ScreenBufferSize
.X
) ||
1381 (CapturedWindowRect
.Bottom
>= Buffer
->ScreenBufferSize
.Y
) ||
1382 (CapturedWindowRect
.Right
<= CapturedWindowRect
.Left
) ||
1383 (CapturedWindowRect
.Bottom
<= CapturedWindowRect
.Top
) )
1385 return STATUS_INVALID_PARAMETER
;
1388 Buffer
->ViewOrigin
.X
= CapturedWindowRect
.Left
;
1389 Buffer
->ViewOrigin
.Y
= CapturedWindowRect
.Top
;
1391 Buffer
->ViewSize
.X
= CapturedWindowRect
.Right
- CapturedWindowRect
.Left
+ 1;
1392 Buffer
->ViewSize
.Y
= CapturedWindowRect
.Bottom
- CapturedWindowRect
.Top
+ 1;
1394 // TermResizeTerminal(Console);
1396 return STATUS_SUCCESS
;