/* * 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 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 ConDrvInvalidateBitMapRect(IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER Buffer, IN PSMALL_RECT Region) { if (Console == NULL || Buffer == NULL || Region == NULL) return STATUS_INVALID_PARAMETER; /* Validity check */ ASSERT(Console == Buffer->Header.Console); /* If the output buffer is the current one, redraw the correct portion of the screen */ if (Buffer == Console->ActiveBuffer) TermDrawRegion(Console, Region); return STATUS_SUCCESS; }
NTSTATUS NTAPI ConDrvFillConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, IN CODE_ELEMENT Code, IN ULONG NumCodesToWrite, IN PCOORD WriteCoord, OUT PULONG NumCodesWritten OPTIONAL) { ULONG X, Y, Length; // , Written = 0; PCHAR_INFO Ptr; if (Console == NULL || Buffer == NULL || WriteCoord == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); // // FIXME: Make overflow checks on WriteCoord !!!!!! // if (NumCodesWritten) *NumCodesWritten = 0; if (CodeType == CODE_ASCII) { /* Conversion from the ASCII char to the UNICODE char */ CODE_ELEMENT tmp; ConsoleOutputAnsiToUnicodeChar(Console, &tmp.UnicodeChar, &Code.AsciiChar); Code = tmp; } X = WriteCoord->X; Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; Length = NumCodesToWrite; // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work while (Length--) { // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; switch (CodeType) { case CODE_ASCII: case CODE_UNICODE: Ptr->Char.UnicodeChar = Code.UnicodeChar; break; case CODE_ATTRIBUTE: Ptr->Attributes = Code.Attribute; break; } // ++Ptr; // Written++; if (++X == Buffer->ScreenBufferSize.X) { X = 0; if (++Y == Buffer->ScreenBufferSize.Y) { Y = 0; } } } if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) { SMALL_RECT UpdateRect; ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite); TermDrawRegion(Console, &UpdateRect); } if (NumCodesWritten) *NumCodesWritten = NumCodesToWrite; // Written; return STATUS_SUCCESS; }
NTSTATUS NTAPI ConDrvWriteConsoleOutputString(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, IN PVOID StringBuffer, IN ULONG NumCodesToWrite, IN PCOORD WriteCoord, // OUT PCOORD EndCoord, OUT PULONG NumCodesWritten OPTIONAL) { NTSTATUS Status = STATUS_SUCCESS; PVOID WriteBuffer = NULL; PWCHAR tmpString = NULL; ULONG X, Y, Length; // , Written = 0; ULONG CodeSize; PCHAR_INFO Ptr; if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */) { return STATUS_INVALID_PARAMETER; } /* Validity checks */ ASSERT(Console == Buffer->Header.Console); ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0)); // // FIXME: Make overflow checks on WriteCoord !!!!!! // if (NumCodesWritten) *NumCodesWritten = 0; switch (CodeType) { case CODE_ASCII: CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); break; case CODE_UNICODE: CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); break; case CODE_ATTRIBUTE: CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); break; default: return STATUS_INVALID_PARAMETER; } if (CodeType == CODE_ASCII) { /* Convert the ASCII string into Unicode before writing it to the console */ Length = MultiByteToWideChar(Console->OutputCodePage, 0, (PCHAR)StringBuffer, NumCodesToWrite, NULL, 0); tmpString = WriteBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR)); if (WriteBuffer) { MultiByteToWideChar(Console->OutputCodePage, 0, (PCHAR)StringBuffer, NumCodesToWrite, (PWCHAR)WriteBuffer, Length); } else { Status = STATUS_NO_MEMORY; } // FIXME: Quick fix: fix the CodeType and CodeSize since the // ASCII string was converted into UNICODE. // A proper fix needs to be written. CodeType = CODE_UNICODE; CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); } else { /* For CODE_UNICODE or CODE_ATTRIBUTE, we are already OK */ WriteBuffer = StringBuffer; } if (WriteBuffer == NULL || !NT_SUCCESS(Status)) goto Cleanup; X = WriteCoord->X; Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; Length = NumCodesToWrite; // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work while (Length--) { // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; switch (CodeType) { case CODE_ASCII: case CODE_UNICODE: Ptr->Char.UnicodeChar = *(PWCHAR)WriteBuffer; break; case CODE_ATTRIBUTE: Ptr->Attributes = *(PWORD)WriteBuffer; break; } WriteBuffer = (PVOID)((ULONG_PTR)WriteBuffer + CodeSize); // ++Ptr; // Written++; if (++X == Buffer->ScreenBufferSize.X) { X = 0; if (++Y == Buffer->ScreenBufferSize.Y) { Y = 0; } } } if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) { SMALL_RECT UpdateRect; ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite); TermDrawRegion(Console, &UpdateRect); } // EndCoord->X = X; // EndCoord->Y = (Y + Buffer->ScreenBufferSize.Y - Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; Cleanup: if (tmpString) RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString); if (NumCodesWritten) *NumCodesWritten = NumCodesToWrite; // Written; return Status; }
NTSTATUS NTAPI ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN USHORT NewScreenAttrib, IN USHORT NewPopupAttrib) { ULONG X, Y, Length; PCHAR_INFO Ptr; COORD TopLeft = {0}; ULONG NumCodesToWrite; USHORT OldScreenAttrib, OldPopupAttrib; if (Console == NULL || Buffer == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); NumCodesToWrite = Buffer->ScreenBufferSize.X * Buffer->ScreenBufferSize.Y; OldScreenAttrib = Buffer->ScreenDefaultAttrib; OldPopupAttrib = Buffer->PopupDefaultAttrib; X = TopLeft.X; Y = (TopLeft.Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; Length = NumCodesToWrite; // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work while (Length--) { // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; /* * Change the current colors only if they are the old ones. */ /* Foreground color */ if ((Ptr->Attributes & 0x0F) == (OldScreenAttrib & 0x0F)) Ptr->Attributes = (Ptr->Attributes & 0xFFF0) | (NewScreenAttrib & 0x0F); if ((Ptr->Attributes & 0x0F) == (OldPopupAttrib & 0x0F)) Ptr->Attributes = (Ptr->Attributes & 0xFFF0) | (NewPopupAttrib & 0x0F); /* Background color */ if ((Ptr->Attributes & 0xF0) == (OldScreenAttrib & 0xF0)) Ptr->Attributes = (Ptr->Attributes & 0xFF0F) | (NewScreenAttrib & 0xF0); if ((Ptr->Attributes & 0xF0) == (OldPopupAttrib & 0xF0)) Ptr->Attributes = (Ptr->Attributes & 0xFF0F) | (NewPopupAttrib & 0xF0); // ++Ptr; if (++X == Buffer->ScreenBufferSize.X) { X = 0; if (++Y == Buffer->ScreenBufferSize.Y) { Y = 0; } } } /* Save foreground and background colors for both screen and popup */ Buffer->ScreenDefaultAttrib = (NewScreenAttrib & 0x00FF); Buffer->PopupDefaultAttrib = (NewPopupAttrib & 0x00FF); /* Refresh the display if needed */ if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) { SMALL_RECT UpdateRect; ConioComputeUpdateRect(Buffer, &UpdateRect, &TopLeft, NumCodesToWrite); TermDrawRegion(Console, &UpdateRect); } 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; }