static __inline BOOLEAN ConioGetUnion(OUT PSMALL_RECT Union, IN PSMALL_RECT Rect1, IN PSMALL_RECT Rect2) { if (ConioIsRectEmpty(Rect1)) { if (ConioIsRectEmpty(Rect2)) { ConioInitRect(Union, 0, -1, 0, -1); return FALSE; } else { *Union = *Rect2; } } else if (ConioIsRectEmpty(Rect2)) { *Union = *Rect1; } else { ConioInitRect(Union, min(Rect1->Top , Rect2->Top ), min(Rect1->Left , Rect2->Left ), max(Rect1->Bottom, Rect2->Bottom), max(Rect1->Right , Rect2->Right )); } return TRUE; }
static __inline BOOLEAN ConioGetIntersection(OUT PSMALL_RECT Intersection, IN PSMALL_RECT Rect1, IN PSMALL_RECT Rect2) { if ( ConioIsRectEmpty(Rect1) || ConioIsRectEmpty(Rect2) || (Rect1->Top > Rect2->Bottom) || (Rect1->Left > Rect2->Right) || (Rect1->Bottom < Rect2->Top) || (Rect1->Right < Rect2->Left) ) { /* The rectangles do not intersect */ ConioInitRect(Intersection, 0, -1, 0, -1); return FALSE; } ConioInitRect(Intersection, max(Rect1->Top , Rect2->Top ), max(Rect1->Left , Rect2->Left ), min(Rect1->Bottom, Rect2->Bottom), min(Rect1->Right , Rect2->Right )); return TRUE; }
/* * NOTE: This function is strongly inspired by ConDrvWriteConsoleOutput... */ NTSTATUS NTAPI ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PCHAR_CELL CharInfo/*Buffer*/, IN COORD CharInfoSize, IN OUT PSMALL_RECT WriteRegion, IN BOOLEAN DrawRegion) { SHORT X, Y; SMALL_RECT ScreenBuffer; PCHAR_CELL CurCharInfo; SMALL_RECT CapturedWriteRegion; PCHAR_INFO Ptr; if (Console == NULL || Buffer == NULL || CharInfo == NULL || WriteRegion == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); CapturedWriteRegion = *WriteRegion; /* Make sure WriteRegion is inside the screen buffer */ ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&CapturedWriteRegion, &ScreenBuffer, &CapturedWriteRegion)) { /* * It is okay to have a WriteRegion completely outside * the screen buffer. No data is written then. */ return STATUS_SUCCESS; } // CurCharInfo = CharInfo; for (Y = CapturedWriteRegion.Top; Y <= CapturedWriteRegion.Bottom; ++Y) { /**/CurCharInfo = CharInfo + Y * CharInfoSize.X + CapturedWriteRegion.Left;/**/ Ptr = ConioCoordToPointer(Buffer, CapturedWriteRegion.Left, Y); for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; ++X) { ConsoleOutputAnsiToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char); Ptr->Attributes = CurCharInfo->Attributes; ++Ptr; ++CurCharInfo; } } if (DrawRegion) TermDrawRegion(Console, &CapturedWriteRegion); *WriteRegion = CapturedWriteRegion; return STATUS_SUCCESS; }
VOID FASTCALL ConioDrawConsole(PCONSOLE Console) { SMALL_RECT Region; PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer; if (ActiveBuffer) { ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1); ConioDrawRegion(Console, &Region); } }
VOID ConioDrawConsole(PCONSRV_CONSOLE Console) { SMALL_RECT Region; PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer; if (!ActiveBuffer) return; ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1); TermDrawRegion(Console, &Region); // Console->FrontEndIFace.Vtbl->DrawRegion(&Console->FrontEndIFace, &Region); }
NTSTATUS NTAPI ConDrvReadConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, OUT PCHAR_INFO CharInfo/*Buffer*/, IN OUT PSMALL_RECT ReadRegion) { SHORT X, Y; SMALL_RECT ScreenBuffer; PCHAR_INFO CurCharInfo; SMALL_RECT CapturedReadRegion; PCHAR_INFO Ptr; if (Console == NULL || Buffer == NULL || CharInfo == NULL || ReadRegion == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); CapturedReadRegion = *ReadRegion; /* Make sure ReadRegion is inside the screen buffer */ ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&CapturedReadRegion, &ScreenBuffer, &CapturedReadRegion)) { /* * It is okay to have a ReadRegion completely outside * the screen buffer. No data is read then. */ return STATUS_SUCCESS; } CurCharInfo = CharInfo; for (Y = CapturedReadRegion.Top; Y <= CapturedReadRegion.Bottom; ++Y) { Ptr = ConioCoordToPointer(Buffer, CapturedReadRegion.Left, Y); for (X = CapturedReadRegion.Left; X <= CapturedReadRegion.Right; ++X) { if (Unicode) { CurCharInfo->Char.UnicodeChar = Ptr->Char.UnicodeChar; } else { // ConsoleOutputUnicodeToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar); WideCharToMultiByte(Console->OutputCodePage, 0, &Ptr->Char.UnicodeChar, 1, &CurCharInfo->Char.AsciiChar, 1, NULL, NULL); } CurCharInfo->Attributes = Ptr->Attributes; ++Ptr; ++CurCharInfo; } } *ReadRegion = CapturedReadRegion; return STATUS_SUCCESS; }
NTSTATUS NTAPI ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PSMALL_RECT ScrollRectangle, IN BOOLEAN UseClipRectangle, IN PSMALL_RECT ClipRectangle OPTIONAL, IN PCOORD DestinationOrigin, IN CHAR_INFO FillChar) { COORD CapturedDestinationOrigin; SMALL_RECT ScreenBuffer; SMALL_RECT SrcRegion; SMALL_RECT DstRegion; SMALL_RECT UpdateRegion; SMALL_RECT CapturedClipRectangle; if (Console == NULL || Buffer == NULL || ScrollRectangle == NULL || (UseClipRectangle ? ClipRectangle == NULL : FALSE) || DestinationOrigin == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); CapturedDestinationOrigin = *DestinationOrigin; /* Make sure the source rectangle is inside the screen buffer */ ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&SrcRegion, &ScreenBuffer, ScrollRectangle)) { return STATUS_SUCCESS; } /* If the source was clipped on the left or top, adjust the destination accordingly */ if (ScrollRectangle->Left < 0) { CapturedDestinationOrigin.X -= ScrollRectangle->Left; } if (ScrollRectangle->Top < 0) { CapturedDestinationOrigin.Y -= ScrollRectangle->Top; } if (UseClipRectangle) { CapturedClipRectangle = *ClipRectangle; if (!ConioGetIntersection(&CapturedClipRectangle, &CapturedClipRectangle, &ScreenBuffer)) { return STATUS_SUCCESS; } } else { CapturedClipRectangle = ScreenBuffer; } ConioInitRect(&DstRegion, CapturedDestinationOrigin.Y, CapturedDestinationOrigin.X, CapturedDestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1, CapturedDestinationOrigin.X + ConioRectWidth(&SrcRegion ) - 1); if (!Unicode) { WCHAR tmp; ConsoleOutputAnsiToUnicodeChar(Console, &tmp, &FillChar.Char.AsciiChar); FillChar.Char.UnicodeChar = tmp; } ConioMoveRegion(Buffer, &SrcRegion, &DstRegion, &CapturedClipRectangle, FillChar); if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) { ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion); if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &CapturedClipRectangle)) { /* Draw update region */ TermDrawRegion(Console, &UpdateRegion); } } return STATUS_SUCCESS; }
NTSTATUS NTAPI ConDrvWriteConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PCHAR_INFO CharInfo/*Buffer*/, IN PCOORD BufferSize, IN PCOORD BufferCoord, IN OUT PSMALL_RECT WriteRegion) { SHORT i, X, Y, SizeX, SizeY; SMALL_RECT ScreenBuffer; PCHAR_INFO CurCharInfo; SMALL_RECT CapturedWriteRegion; PCHAR_INFO Ptr; if (Console == NULL || Buffer == NULL || CharInfo == NULL || BufferSize == NULL || BufferCoord == NULL || WriteRegion == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); CapturedWriteRegion = *WriteRegion; SizeX = min(BufferSize->X - BufferCoord->X, ConioRectWidth(&CapturedWriteRegion)); SizeY = min(BufferSize->Y - BufferCoord->Y, ConioRectHeight(&CapturedWriteRegion)); CapturedWriteRegion.Right = CapturedWriteRegion.Left + SizeX - 1; CapturedWriteRegion.Bottom = CapturedWriteRegion.Top + SizeY - 1; /* Make sure WriteRegion is inside the screen buffer */ ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&CapturedWriteRegion, &ScreenBuffer, &CapturedWriteRegion)) { /* * It is okay to have a WriteRegion completely outside * the screen buffer. No data is written then. */ return STATUS_SUCCESS; } for (i = 0, Y = CapturedWriteRegion.Top; Y <= CapturedWriteRegion.Bottom; i++, Y++) { CurCharInfo = CharInfo + (i + BufferCoord->Y) * BufferSize->X + BufferCoord->X; Ptr = ConioCoordToPointer(Buffer, CapturedWriteRegion.Left, Y); for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; X++) { if (Unicode) { Ptr->Char.UnicodeChar = CurCharInfo->Char.UnicodeChar; } else { ConsoleAnsiCharToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char.AsciiChar); } Ptr->Attributes = CurCharInfo->Attributes; ++Ptr; ++CurCharInfo; } } ConioDrawRegion(Console, &CapturedWriteRegion); WriteRegion->Left = CapturedWriteRegion.Left; WriteRegion->Top = CapturedWriteRegion.Top ; WriteRegion->Right = CapturedWriteRegion.Left + SizeX - 1; WriteRegion->Bottom = CapturedWriteRegion.Top + SizeY - 1; return STATUS_SUCCESS; }
NTSTATUS NTAPI ConDrvReadConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, OUT PCHAR_INFO CharInfo/*Buffer*/, IN PCOORD BufferSize, IN PCOORD BufferCoord, IN OUT PSMALL_RECT ReadRegion) { PCHAR_INFO CurCharInfo; SHORT SizeX, SizeY; SMALL_RECT CapturedReadRegion; SMALL_RECT ScreenRect; DWORD i; PCHAR_INFO Ptr; LONG X, Y; UINT CodePage; if (Console == NULL || Buffer == NULL || CharInfo == NULL || BufferSize == NULL || BufferCoord == NULL || ReadRegion == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); CapturedReadRegion = *ReadRegion; /* FIXME: Is this correct? */ CodePage = Console->OutputCodePage; SizeX = min(BufferSize->X - BufferCoord->X, ConioRectWidth(&CapturedReadRegion)); SizeY = min(BufferSize->Y - BufferCoord->Y, ConioRectHeight(&CapturedReadRegion)); CapturedReadRegion.Right = CapturedReadRegion.Left + SizeX; CapturedReadRegion.Bottom = CapturedReadRegion.Top + SizeY; ConioInitRect(&ScreenRect, 0, 0, Buffer->ScreenBufferSize.Y, Buffer->ScreenBufferSize.X); if (!ConioGetIntersection(&CapturedReadRegion, &ScreenRect, &CapturedReadRegion)) { return STATUS_SUCCESS; } for (i = 0, Y = CapturedReadRegion.Top; Y < CapturedReadRegion.Bottom; ++i, ++Y) { CurCharInfo = CharInfo + (i * BufferSize->X); Ptr = ConioCoordToPointer(Buffer, CapturedReadRegion.Left, Y); for (X = CapturedReadRegion.Left; X < CapturedReadRegion.Right; ++X) { if (Unicode) { CurCharInfo->Char.UnicodeChar = Ptr->Char.UnicodeChar; } else { // ConsoleUnicodeCharToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar); WideCharToMultiByte(CodePage, 0, &Ptr->Char.UnicodeChar, 1, &CurCharInfo->Char.AsciiChar, 1, NULL, NULL); } CurCharInfo->Attributes = Ptr->Attributes; ++Ptr; ++CurCharInfo; } } ReadRegion->Left = CapturedReadRegion.Left; ReadRegion->Top = CapturedReadRegion.Top ; ReadRegion->Right = CapturedReadRegion.Left + SizeX - 1; ReadRegion->Bottom = CapturedReadRegion.Top + SizeY - 1; return STATUS_SUCCESS; }