#define NDEBUG
#include <debug.h>
+#define COMMON_LEAD_TRAIL (COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE)
+
/* GLOBALS ********************************************************************/
-#define TAB_WIDTH 8
+/*
+ * From MSDN:
+ * "The lpMultiByteStr and lpWideCharStr pointers must not be the same.
+ * If they are the same, the function fails, and GetLastError returns
+ * ERROR_INVALID_PARAMETER."
+ */
+#define ConsoleOutputUnicodeToAnsiChar(Console, dChar, sWChar) \
+ ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \
+ WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
+
+#define ConsoleOutputAnsiToUnicodeChar(Console, dWChar, sChar) \
+ ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \
+ MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
/* PRIVATE FUNCTIONS **********************************************************/
};
-static VOID
+/*static*/ VOID
ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff);
NTSTATUS
CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
- IN OUT PCONSOLE Console,
+ IN PCONSOLE Console,
IN PCONSOLE_SCREEN_BUFFER_VTBL Vtbl,
IN SIZE_T Size);
VOID
NTSTATUS
TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
- IN OUT PCONSOLE Console,
+ IN PCONSOLE Console,
+ IN HANDLE ProcessHandle,
IN PTEXTMODE_BUFFER_INFO TextModeInfo)
{
NTSTATUS Status = STATUS_SUCCESS;
PTEXTMODE_SCREEN_BUFFER NewBuffer = NULL;
+ UNREFERENCED_PARAMETER(ProcessHandle);
+
if (Console == NULL || Buffer == NULL || TextModeInfo == NULL)
return STATUS_INVALID_PARAMETER;
return &Buff->Buffer[((Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y) * Buff->ScreenBufferSize.X + X];
}
-static VOID
+/*static*/ VOID
ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff)
{
PCHAR_INFO Ptr = ConioCoordToPointer(Buff, 0, Buff->CursorPosition.Y);
IN PCOORD Start,
IN UINT Length)
{
- if (Buff->ScreenBufferSize.X <= Start->X + Length)
- {
- UpdateRect->Left = 0;
- }
- else
- {
- UpdateRect->Left = Start->X;
- }
- if (Buff->ScreenBufferSize.X <= Start->X + Length)
+ if ((UINT)Buff->ScreenBufferSize.X <= Start->X + Length)
{
+ UpdateRect->Left = 0;
UpdateRect->Right = Buff->ScreenBufferSize.X - 1;
}
else
{
+ UpdateRect->Left = Start->X;
UpdateRect->Right = Start->X + Length - 1;
}
UpdateRect->Top = Start->Y;
}
}
+// FIXME!
+NTSTATUS NTAPI
+ConDrvWriteConsoleInput(IN PCONSOLE Console,
+ IN PCONSOLE_INPUT_BUFFER InputBuffer,
+ IN BOOLEAN AppendToEnd,
+ IN PINPUT_RECORD InputRecord,
+ IN ULONG NumEventsToWrite,
+ OUT PULONG NumEventsWritten OPTIONAL);
+
NTSTATUS
ConioResizeBuffer(PCONSOLE Console,
PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size.X * Size.Y * sizeof(CHAR_INFO));
if (!Buffer) return STATUS_NO_MEMORY;
- DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->ScreenBufferSize.X, ScreenBuffer->ScreenBufferSize.Y, Size.X, Size.Y);
+ DPRINT("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->ScreenBufferSize.X, ScreenBuffer->ScreenBufferSize.Y, Size.X, Size.Y);
OldBuffer = ScreenBuffer->Buffer;
for (CurrentY = 0; CurrentY < ScreenBuffer->ScreenBufferSize.Y && CurrentY < Size.Y; CurrentY++)
*/
if (Console->InputBuffer.Mode & ENABLE_WINDOW_INPUT)
{
+ ULONG NumEventsWritten;
INPUT_RECORD er;
er.EventType = WINDOW_BUFFER_SIZE_EVENT;
er.Event.WindowBufferSizeEvent.dwSize = ScreenBuffer->ScreenBufferSize;
- ConioProcessInputEvent(Console, &er);
- }
-
- return STATUS_SUCCESS;
-}
-
-static VOID
-ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT ScrolledLines)
-{
- /* If we hit bottom, slide the viewable screen */
- if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y)
- {
- Buff->CursorPosition.Y--;
- if (++Buff->VirtualY == Buff->ScreenBufferSize.Y)
- {
- Buff->VirtualY = 0;
- }
- (*ScrolledLines)++;
- ClearLineBuffer(Buff);
- if (UpdateRect->Top != 0)
- {
- UpdateRect->Top--;
- }
- }
- UpdateRect->Left = 0;
- UpdateRect->Right = Buff->ScreenBufferSize.X - 1;
- UpdateRect->Bottom = Buff->CursorPosition.Y;
-}
-
-NTSTATUS
-ConioWriteConsole(PCONSOLE Console,
- PTEXTMODE_SCREEN_BUFFER Buff,
- PWCHAR Buffer,
- DWORD Length,
- BOOL Attrib)
-{
- UINT i;
- PCHAR_INFO Ptr;
- SMALL_RECT UpdateRect;
- SHORT CursorStartX, CursorStartY;
- UINT ScrolledLines;
-
- CursorStartX = Buff->CursorPosition.X;
- CursorStartY = Buff->CursorPosition.Y;
- UpdateRect.Left = Buff->ScreenBufferSize.X;
- UpdateRect.Top = Buff->CursorPosition.Y;
- UpdateRect.Right = -1;
- UpdateRect.Bottom = Buff->CursorPosition.Y;
- ScrolledLines = 0;
-
- for (i = 0; i < Length; i++)
- {
- /*
- * If we are in processed mode, interpret special characters and
- * display them correctly. Otherwise, just put them into the buffer.
- */
- if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
- {
- /* --- CR --- */
- if (Buffer[i] == L'\r')
- {
- Buff->CursorPosition.X = 0;
- UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
- UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
- continue;
- }
- /* --- LF --- */
- else if (Buffer[i] == L'\n')
- {
- Buff->CursorPosition.X = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- continue;
- }
- /* --- BS --- */
- else if (Buffer[i] == L'\b')
- {
- /* Only handle BS if we're not on the first pos of the first line */
- if (0 != Buff->CursorPosition.X || 0 != Buff->CursorPosition.Y)
- {
- if (0 == Buff->CursorPosition.X)
- {
- /* slide virtual position up */
- Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1;
- Buff->CursorPosition.Y--;
- UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y);
- }
- else
- {
- Buff->CursorPosition.X--;
- }
- Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
- Ptr->Char.UnicodeChar = L' ';
- Ptr->Attributes = Buff->ScreenDefaultAttrib;
- UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
- UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
- }
- continue;
- }
- /* --- TAB --- */
- else if (Buffer[i] == L'\t')
- {
- UINT EndX;
-
- UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
- EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1);
- EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X);
- Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
- while (Buff->CursorPosition.X < EndX)
- {
- Ptr->Char.UnicodeChar = L' ';
- Ptr->Attributes = Buff->ScreenDefaultAttrib;
- ++Ptr;
- Buff->CursorPosition.X++;
- }
- UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1);
- if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
- {
- if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
- {
- Buff->CursorPosition.X = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- }
- else
- {
- Buff->CursorPosition.X--;
- }
- }
- continue;
- }
- // /* --- BEL ---*/
- // else if (Buffer[i] == L'\a')
- // {
- // // FIXME: This MUST BE moved to the terminal emulator frontend!!
- // DPRINT1("Bell\n");
- // // SendNotifyMessage(Console->hWindow, PM_CONSOLE_BEEP, 0, 0);
- // continue;
- // }
- }
- UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
- UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
-
- Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
- Ptr->Char.UnicodeChar = Buffer[i];
- if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib;
-
- Buff->CursorPosition.X++;
- if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
- {
- if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
- {
- Buff->CursorPosition.X = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- }
- else
- {
- Buff->CursorPosition.X = CursorStartX;
- }
- }
- }
-
- if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
- {
- TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
- ScrolledLines, Buffer, Length);
+ // ConioProcessInputEvent(Console, &er);
+ ConDrvWriteConsoleInput(Console,
+ &Console->InputBuffer,
+ TRUE,
+ &er,
+ 1,
+ &NumEventsWritten);
}
return STATUS_SUCCESS;
IN USHORT NewScreenAttrib,
IN USHORT NewPopupAttrib)
{
- DWORD X, Y, Length;
+ ULONG X, Y, Length;
PCHAR_INFO Ptr;
COORD TopLeft = {0};
ULONG NumCodesToWrite;
- USHORT OldScreenAttrib;
+ USHORT OldScreenAttrib, OldPopupAttrib;
if (Console == NULL || Buffer == NULL)
{
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];
+ Ptr = ConioCoordToPointer(Buffer, X, Y);
/*
* 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;
/* Make sure ReadRegion is inside the screen buffer */
ConioInitRect(&ScreenBuffer, 0, 0,
- Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1);
+ Buffer->ScreenBufferSize.Y - 1,
+ Buffer->ScreenBufferSize.X - 1);
if (!ConioGetIntersection(&CapturedReadRegion, &ScreenBuffer, &CapturedReadRegion))
{
/*
}
else
{
- // ConsoleUnicodeCharToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar);
+ // 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;
+ CurCharInfo->Attributes = (Ptr->Attributes & ~COMMON_LEAD_TRAIL);
++Ptr;
++CurCharInfo;
}
/* Make sure WriteRegion is inside the screen buffer */
ConioInitRect(&ScreenBuffer, 0, 0,
- Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1);
+ Buffer->ScreenBufferSize.Y - 1,
+ Buffer->ScreenBufferSize.X - 1);
if (!ConioGetIntersection(&CapturedWriteRegion, &ScreenBuffer, &CapturedWriteRegion))
{
/*
}
else
{
- ConsoleAnsiCharToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char.AsciiChar);
+ ConsoleOutputAnsiToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char.AsciiChar);
}
Ptr->Attributes = CurCharInfo->Attributes;
++Ptr;
/*
* NOTE: This function is strongly inspired by ConDrvWriteConsoleOutput...
+ * FIXME: This function MUST be moved into consrv/conoutput.c because only
+ * consrv knows how to manipulate VDM screenbuffers.
*/
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)
+ IN PSMALL_RECT WriteRegion)
{
SHORT X, Y;
SMALL_RECT ScreenBuffer;
/* Make sure WriteRegion is inside the screen buffer */
ConioInitRect(&ScreenBuffer, 0, 0,
- Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1);
+ Buffer->ScreenBufferSize.Y - 1,
+ Buffer->ScreenBufferSize.X - 1);
if (!ConioGetIntersection(&CapturedWriteRegion, &ScreenBuffer, &CapturedWriteRegion))
{
/*
Ptr = ConioCoordToPointer(Buffer, CapturedWriteRegion.Left, Y);
for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; ++X)
{
- ConsoleAnsiCharToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char);
+ ConsoleOutputAnsiToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char);
Ptr->Attributes = CurCharInfo->Attributes;
++Ptr;
++CurCharInfo;
}
}
- if (DrawRegion) TermDrawRegion(Console, &CapturedWriteRegion);
-
- *WriteRegion = CapturedWriteRegion;
-
return STATUS_SUCCESS;
}
/* Stop here if the console is paused */
if (Console->UnpauseEvent != NULL) return STATUS_PENDING;
+ /* Convert the string to UNICODE */
if (Unicode)
{
Buffer = StringBuffer;
}
}
+ /* Send it */
if (Buffer)
{
if (NT_SUCCESS(Status))
{
- Status = ConioWriteConsole(Console,
- ScreenBuffer,
- Buffer,
- NumCharsToWrite,
- TRUE);
+ Status = TermWriteStream(Console,
+ ScreenBuffer,
+ Buffer,
+ NumCharsToWrite,
+ TRUE);
if (NT_SUCCESS(Status))
{
Written = NumCharsToWrite;
return Status;
}
-NTSTATUS NTAPI
-ConDrvReadConsoleOutputString(IN PCONSOLE Console,
- IN PTEXTMODE_SCREEN_BUFFER Buffer,
- IN CODE_TYPE CodeType,
- OUT PVOID StringBuffer,
- IN ULONG NumCodesToRead,
- IN PCOORD ReadCoord,
- // OUT PCOORD EndCoord,
- OUT PULONG NumCodesRead OPTIONAL)
+NTSTATUS FASTCALL
+IntReadConsoleOutputStringAscii(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ OUT PVOID StringBuffer,
+ IN ULONG NumCodesToRead,
+ IN PCOORD ReadCoord,
+ OUT PULONG NumCodesRead OPTIONAL)
{
- SHORT Xpos, Ypos;
- PVOID ReadBuffer;
+ ULONG CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
+ LPBYTE ReadBuffer = StringBuffer;
+ SHORT Xpos = ReadCoord->X;
+ SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
ULONG i;
- ULONG CodeSize;
PCHAR_INFO Ptr;
+ BOOLEAN bCJK = Console->IsCJK;
- if (Console == NULL || Buffer == NULL || ReadCoord == NULL /* || EndCoord == NULL */)
+ for (i = 0; i < NumCodesToRead; ++i)
{
- return STATUS_INVALID_PARAMETER;
+ Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos);
+
+ ConsoleOutputUnicodeToAnsiChar(Console, (PCHAR)ReadBuffer, &Ptr->Char.UnicodeChar);
+ ReadBuffer += CodeSize;
+
+ Xpos++;
+ if (Xpos == Buffer->ScreenBufferSize.X)
+ {
+ Xpos = 0;
+ Ypos++;
+ if (Ypos == Buffer->ScreenBufferSize.Y)
+ {
+ Ypos = 0;
+ }
+ }
+
+ /* For Chinese, Japanese and Korean */
+ if (bCJK && (Ptr->Attributes & COMMON_LVB_LEADING_BYTE))
+ {
+ Xpos++;
+ if (Xpos == Buffer->ScreenBufferSize.X)
+ {
+ Xpos = 0;
+ Ypos++;
+ if (Ypos == Buffer->ScreenBufferSize.Y)
+ {
+ Ypos = 0;
+ }
+ }
+ ++i;
+ }
}
- /* Validity checks */
- ASSERT(Console == Buffer->Header.Console);
- ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0));
+ if (NumCodesRead)
+ *NumCodesRead = i;
- if (NumCodesRead) *NumCodesRead = 0;
+ return STATUS_SUCCESS;
+}
- switch (CodeType)
+NTSTATUS FASTCALL
+IntReadConsoleOutputStringUnicode(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ OUT PVOID StringBuffer,
+ IN ULONG NumCodesToRead,
+ IN PCOORD ReadCoord,
+ OUT PULONG NumCodesRead OPTIONAL)
+{
+ ULONG CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
+ LPBYTE ReadBuffer = StringBuffer;
+ SHORT Xpos = ReadCoord->X;
+ SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
+ ULONG i, nNumChars = 0;
+ PCHAR_INFO Ptr;
+ BOOLEAN bCJK = Console->IsCJK;
+
+ for (i = 0; i < NumCodesToRead; ++i, ++nNumChars)
{
- case CODE_ASCII:
- CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
- break;
+ Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos);
- case CODE_UNICODE:
- CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
- break;
+ *(PWCHAR)ReadBuffer = Ptr->Char.UnicodeChar;
+ ReadBuffer += CodeSize;
- case CODE_ATTRIBUTE:
- CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
- break;
+ Xpos++;
+ if (Xpos == Buffer->ScreenBufferSize.X)
+ {
+ Xpos = 0;
+ Ypos++;
+ if (Ypos == Buffer->ScreenBufferSize.Y)
+ {
+ Ypos = 0;
+ }
+ }
- default:
- return STATUS_INVALID_PARAMETER;
+ /* For Chinese, Japanese and Korean */
+ if (bCJK && (Ptr->Attributes & COMMON_LVB_LEADING_BYTE))
+ {
+ Xpos++;
+ if (Xpos == Buffer->ScreenBufferSize.X)
+ {
+ Xpos = 0;
+ Ypos++;
+ if (Ypos == Buffer->ScreenBufferSize.Y)
+ {
+ Ypos = 0;
+ }
+ }
+ ++i;
+ }
}
- ReadBuffer = StringBuffer;
- Xpos = ReadCoord->X;
- Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
+ if (NumCodesRead)
+ *NumCodesRead = nNumChars;
- /*
- * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
- *
- * If the number of attributes (resp. characters) to be read from extends
- * beyond the end of the specified screen buffer row, attributes (resp.
- * characters) are read from the next row. If the number of attributes
- * (resp. characters) to be read from extends beyond the end of the console
- * screen buffer, attributes (resp. characters) up to the end of the console
- * screen buffer are read.
- *
- * TODO: Do NOT loop up to NumCodesToRead, but stop before
- * if we are going to overflow...
- */
- // Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); // Doesn't work
- for (i = 0; i < min(NumCodesToRead, Buffer->ScreenBufferSize.X * Buffer->ScreenBufferSize.Y); ++i)
- {
- // Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); // Doesn't work either
- Ptr = &Buffer->Buffer[Xpos + Ypos * Buffer->ScreenBufferSize.X];
+ return STATUS_SUCCESS;
+}
- switch (CodeType)
- {
- case CODE_ASCII:
- ConsoleUnicodeCharToAnsiChar(Console, (PCHAR)ReadBuffer, &Ptr->Char.UnicodeChar);
- break;
+NTSTATUS FASTCALL
+IntReadConsoleOutputStringAttributes(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ OUT PVOID StringBuffer,
+ IN ULONG NumCodesToRead,
+ IN PCOORD ReadCoord,
+ OUT PULONG NumCodesRead OPTIONAL)
+{
+ ULONG CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
+ LPBYTE ReadBuffer = StringBuffer;
+ SHORT Xpos = ReadCoord->X;
+ SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
+ ULONG i;
+ PCHAR_INFO Ptr;
- case CODE_UNICODE:
- *(PWCHAR)ReadBuffer = Ptr->Char.UnicodeChar;
- break;
+ for (i = 0; i < NumCodesToRead; ++i)
+ {
+ Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos);
- case CODE_ATTRIBUTE:
- *(PWORD)ReadBuffer = Ptr->Attributes;
- break;
- }
- ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
- // ++Ptr;
+ *(PWORD)ReadBuffer = Ptr->Attributes;
+ ReadBuffer += CodeSize;
Xpos++;
-
if (Xpos == Buffer->ScreenBufferSize.X)
{
Xpos = 0;
Ypos++;
-
if (Ypos == Buffer->ScreenBufferSize.Y)
{
Ypos = 0;
}
}
- // EndCoord->X = Xpos;
- // EndCoord->Y = (Ypos - Buffer->VirtualY + Buffer->ScreenBufferSize.Y) % Buffer->ScreenBufferSize.Y;
+ if (Xpos > 0 && Console->IsCJK)
+ {
+ ReadBuffer -= CodeSize;
+ *(PWORD)ReadBuffer &= ~COMMON_LVB_LEADING_BYTE;
+ }
if (NumCodesRead)
- *NumCodesRead = (ULONG)((ULONG_PTR)ReadBuffer - (ULONG_PTR)StringBuffer) / CodeSize;
- // <= NumCodesToRead
+ *NumCodesRead = NumCodesToRead;
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)
+ConDrvReadConsoleOutputString(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ IN CODE_TYPE CodeType,
+ OUT PVOID StringBuffer,
+ IN ULONG NumCodesToRead,
+ IN PCOORD ReadCoord,
+ OUT PULONG NumCodesRead OPTIONAL)
{
- NTSTATUS Status = STATUS_SUCCESS;
- PVOID WriteBuffer = NULL;
- PWCHAR tmpString = NULL;
- DWORD X, Y, Length; // , Written = 0;
- ULONG CodeSize;
- PCHAR_INFO Ptr;
-
- if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */)
+ if (Console == NULL || Buffer == NULL || ReadCoord == NULL /* || EndCoord == NULL */)
{
return STATUS_INVALID_PARAMETER;
}
/* Validity checks */
ASSERT(Console == Buffer->Header.Console);
- ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0));
+ ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0));
- if (NumCodesWritten) *NumCodesWritten = 0;
+ if (NumCodesRead)
+ *NumCodesRead = 0;
switch (CodeType)
{
case CODE_ASCII:
- CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
- break;
+ return IntReadConsoleOutputStringAscii(Console,
+ Buffer,
+ StringBuffer,
+ NumCodesToRead,
+ ReadCoord,
+ NumCodesRead);
case CODE_UNICODE:
- CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
- break;
+ return IntReadConsoleOutputStringUnicode(Console,
+ Buffer,
+ StringBuffer,
+ NumCodesToRead,
+ ReadCoord,
+ NumCodesRead);
case CODE_ATTRIBUTE:
- CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
- break;
+ return IntReadConsoleOutputStringAttributes(Console,
+ Buffer,
+ StringBuffer,
+ NumCodesToRead,
+ ReadCoord,
+ NumCodesRead);
default:
return STATUS_INVALID_PARAMETER;
}
+}
- if (CodeType == CODE_ASCII)
+static NTSTATUS
+IntWriteConsoleOutputStringUnicode(
+ IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ IN PVOID StringBuffer,
+ IN ULONG NumCodesToWrite,
+ IN PCOORD WriteCoord,
+ OUT PULONG NumCodesWritten OPTIONAL)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PWCHAR WriteBuffer = StringBuffer;
+ ULONG i, X, Y, Length;
+ PCHAR_INFO Ptr;
+ BOOLEAN bCJK = Console->IsCJK;
+
+ if (!StringBuffer)
+ goto Cleanup;
+
+ X = WriteCoord->X;
+ Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
+ Length = NumCodesToWrite;
+
+ for (i = 0; i < Length; ++i)
{
- /* 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)
+ Ptr = ConioCoordToPointer(Buffer, X, Y);
+
+ Ptr->Char.UnicodeChar = *WriteBuffer;
+ ++WriteBuffer;
+
+ ++X;
+ if (X == Buffer->ScreenBufferSize.X)
{
- MultiByteToWideChar(Console->OutputCodePage, 0,
- (PCHAR)StringBuffer,
- NumCodesToWrite,
- (PWCHAR)WriteBuffer, Length);
+ X = 0;
+ ++Y;
+ if (Y == Buffer->ScreenBufferSize.Y)
+ {
+ Y = 0;
+ }
}
- else
+
+ /* For Chinese, Japanese and Korean */
+ if (bCJK && Ptr->Char.UnicodeChar >= 0x80 &&
+ mk_wcwidth_cjk(Ptr->Char.UnicodeChar) == 2)
{
- Status = STATUS_NO_MEMORY;
- }
+ /* A full-width character cannot cross a line boundary */
+ if (X == Buffer->ScreenBufferSize.X - 1)
+ {
+ /* go to next line */
+ X = 0;
+ ++Y;
+ if (Y == Buffer->ScreenBufferSize.Y)
+ {
+ Y = 0;
+ }
+ Ptr = ConioCoordToPointer(Buffer, X, Y);
+ }
- // 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);
+ /* the leading byte */
+ Ptr->Attributes = Buffer->ScreenDefaultAttrib;
+ Ptr->Attributes |= COMMON_LVB_LEADING_BYTE;
+ ++i;
+
+ /* the trailing byte */
+ Ptr = ConioCoordToPointer(Buffer, X, Y);
+ Ptr->Attributes = Buffer->ScreenDefaultAttrib;
+ Ptr->Attributes |= COMMON_LVB_TRAILING_BYTE;
+
+ ++X;
+ if (X == Buffer->ScreenBufferSize.X)
+ {
+ X = 0;
+ ++Y;
+ if (Y == Buffer->ScreenBufferSize.Y)
+ {
+ Y = 0;
+ }
+ }
+ }
}
- else
+
+Cleanup:
+ if (NumCodesWritten)
+ *NumCodesWritten = NumCodesToWrite;
+ return Status;
+}
+
+static NTSTATUS
+IntWriteConsoleOutputStringAscii(
+ IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ IN PVOID StringBuffer,
+ IN ULONG NumCodesToWrite,
+ IN PCOORD WriteCoord,
+ OUT PULONG NumCodesWritten OPTIONAL)
+{
+ NTSTATUS Status;
+ PWCHAR tmpString;
+ ULONG Length;
+
+ if (!StringBuffer)
{
- /* For CODE_UNICODE or CODE_ATTRIBUTE, we are already OK */
- WriteBuffer = StringBuffer;
+ if (NumCodesWritten)
+ *NumCodesWritten = NumCodesToWrite;
+
+ return STATUS_SUCCESS;
}
- if (WriteBuffer == NULL || !NT_SUCCESS(Status)) goto Cleanup;
+ /* Convert the ASCII string into Unicode before writing it to the console */
+ Length = MultiByteToWideChar(Console->OutputCodePage, 0,
+ StringBuffer,
+ NumCodesToWrite,
+ NULL, 0);
+ tmpString = ConsoleAllocHeap(0, Length * sizeof(WCHAR));
+ if (!tmpString)
+ return STATUS_NO_MEMORY;
+
+ MultiByteToWideChar(Console->OutputCodePage, 0,
+ StringBuffer,
+ NumCodesToWrite,
+ tmpString, Length);
+
+ Status = IntWriteConsoleOutputStringUnicode(Console,
+ Buffer,
+ tmpString,
+ Length,
+ WriteCoord,
+ NumCodesWritten);
+ ConsoleFreeHeap(tmpString);
+ return Status;
+}
+
+static NTSTATUS
+IntWriteConsoleOutputStringAttribute(
+ IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ IN PVOID StringBuffer,
+ IN ULONG NumCodesToWrite,
+ IN PCOORD WriteCoord,
+ OUT PULONG NumCodesWritten OPTIONAL)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PWORD WriteBuffer = StringBuffer;
+ ULONG i, X, Y, Length;
+ PCHAR_INFO Ptr;
+
+ if (!StringBuffer)
+ 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--)
+ for (i = 0; i < Length; ++i)
{
- // 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;
+ Ptr = ConioCoordToPointer(Buffer, X, Y);
- case CODE_ATTRIBUTE:
- Ptr->Attributes = *(PWORD)WriteBuffer;
- break;
- }
- WriteBuffer = (PVOID)((ULONG_PTR)WriteBuffer + CodeSize);
- // ++Ptr;
+ Ptr->Attributes = (*WriteBuffer & ~COMMON_LEAD_TRAIL);
+ ++WriteBuffer;
- // Written++;
- if (++X == Buffer->ScreenBufferSize.X)
+ ++X;
+ if (X == Buffer->ScreenBufferSize.X)
{
X = 0;
-
- if (++Y == Buffer->ScreenBufferSize.Y)
+ ++Y;
+ if (Y == Buffer->ScreenBufferSize.Y)
{
Y = 0;
}
}
}
+Cleanup:
+ if (NumCodesWritten)
+ *NumCodesWritten = NumCodesToWrite;
+ return Status;
+}
+
+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 PULONG NumCodesWritten OPTIONAL)
+{
+ NTSTATUS Status;
+ SMALL_RECT UpdateRect;
+
+ 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));
+
+ if (NumCodesWritten)
+ *NumCodesWritten = 0;
+
+ switch (CodeType)
+ {
+ case CODE_ASCII:
+ Status = IntWriteConsoleOutputStringAscii(
+ Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
+ break;
+
+ case CODE_UNICODE:
+ Status = IntWriteConsoleOutputStringUnicode(
+ Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
+ break;
+
+ case CODE_ATTRIBUTE:
+ Status = IntWriteConsoleOutputStringAttribute(
+ Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
+ break;
+
+ default:
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
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;
}
IN PCOORD WriteCoord,
OUT PULONG NumCodesWritten OPTIONAL)
{
- DWORD X, Y, Length; // , Written = 0;
+ ULONG X, Y, i;
PCHAR_INFO Ptr;
+ BOOLEAN bLead, bFullwidth;
if (Console == NULL || Buffer == NULL || WriteCoord == NULL)
{
/* 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;
- ConsoleAnsiCharToUnicodeChar(Console, &tmp.UnicodeChar, &Code.AsciiChar);
+ 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--)
+ /* For Chinese, Japanese and Korean */
+ bLead = TRUE;
+ bFullwidth = FALSE;
+ if (Console->IsCJK)
+ {
+ bFullwidth = (mk_wcwidth_cjk(Code.UnicodeChar) == 2);
+ if (X > 0)
+ {
+ Ptr = ConioCoordToPointer(Buffer, X - 1, Y);
+ if (Ptr->Attributes & COMMON_LVB_LEADING_BYTE)
+ {
+ Ptr->Char.UnicodeChar = L' ';
+ Ptr->Attributes &= ~COMMON_LVB_LEADING_BYTE;
+ }
+ }
+ }
+
+ for (i = 0; i < NumCodesToWrite; ++i)
{
- // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
- Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X];
+ Ptr = ConioCoordToPointer(Buffer, X, Y);
switch (CodeType)
{
case CODE_ASCII:
case CODE_UNICODE:
Ptr->Char.UnicodeChar = Code.UnicodeChar;
+ Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
+ if (bFullwidth)
+ {
+ if (bLead)
+ Ptr->Attributes |= COMMON_LVB_LEADING_BYTE;
+ else
+ Ptr->Attributes |= COMMON_LVB_TRAILING_BYTE;
+ }
break;
case CODE_ATTRIBUTE:
- Ptr->Attributes = Code.Attribute;
+ Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
+ Ptr->Attributes |= (Code.Attribute & ~COMMON_LEAD_TRAIL);
break;
}
- // ++Ptr;
- // Written++;
- if (++X == Buffer->ScreenBufferSize.X)
+ ++X;
+ if (X == Buffer->ScreenBufferSize.X)
{
X = 0;
-
- if (++Y == Buffer->ScreenBufferSize.Y)
+ ++Y;
+ if (Y == Buffer->ScreenBufferSize.Y)
{
Y = 0;
}
}
+
+ bLead = !bLead;
+ }
+
+ if ((NumCodesToWrite & 1) & bFullwidth)
+ {
+ if (X + Y * Buffer->ScreenBufferSize.X > 0)
+ {
+ Ptr = ConioCoordToPointer(Buffer, X - 1, Y);
+ Ptr->Char.UnicodeChar = L' ';
+ Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
+ }
}
if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
OUT PCOORD MaximumViewSize,
OUT PWORD Attributes)
{
+ COORD LargestWindowSize;
+
if (Console == NULL || Buffer == NULL || ScreenBufferSize == NULL ||
CursorPosition == NULL || ViewOrigin == NULL || ViewSize == NULL ||
MaximumViewSize == NULL || Attributes == NULL)
*ViewSize = Buffer->ViewSize;
*Attributes = Buffer->ScreenDefaultAttrib;
- // FIXME: Refine the computation
- *MaximumViewSize = Buffer->ScreenBufferSize;
+ /*
+ * Retrieve the largest possible console window size, taking
+ * into account the size of the console screen buffer.
+ */
+ TermGetLargestConsoleWindowSize(Console, &LargestWindowSize);
+ LargestWindowSize.X = min(LargestWindowSize.X, Buffer->ScreenBufferSize.X);
+ LargestWindowSize.Y = min(LargestWindowSize.Y, Buffer->ScreenBufferSize.Y);
+ *MaximumViewSize = LargestWindowSize;
return STATUS_SUCCESS;
}
/* Make sure the source rectangle is inside the screen buffer */
ConioInitRect(&ScreenBuffer, 0, 0,
- Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1);
+ Buffer->ScreenBufferSize.Y - 1,
+ Buffer->ScreenBufferSize.X - 1);
if (!ConioGetIntersection(&SrcRegion, &ScreenBuffer, ScrollRectangle))
{
return STATUS_SUCCESS;
if (!Unicode)
{
WCHAR tmp;
- ConsoleAnsiCharToUnicodeChar(Console, &tmp, &FillChar.Char.AsciiChar);
+ ConsoleOutputAnsiToUnicodeChar(Console, &tmp, &FillChar.Char.AsciiChar);
FillChar.Char.UnicodeChar = tmp;
}
IN PSMALL_RECT WindowRect)
{
SMALL_RECT CapturedWindowRect;
+ COORD LargestWindowSize;
if (Console == NULL || Buffer == NULL || WindowRect == NULL)
return STATUS_INVALID_PARAMETER;
CapturedWindowRect = *WindowRect;
- if (Absolute == FALSE)
+ if (!Absolute)
{
- /* Relative positions given. Transform them to absolute ones */
+ /* Relative positions are given, transform them to absolute ones */
CapturedWindowRect.Left += Buffer->ViewOrigin.X;
CapturedWindowRect.Top += Buffer->ViewOrigin.Y;
CapturedWindowRect.Right += Buffer->ViewOrigin.X + Buffer->ViewSize.X - 1;
CapturedWindowRect.Bottom += Buffer->ViewOrigin.Y + Buffer->ViewSize.Y - 1;
}
- /* See MSDN documentation on SetConsoleWindowInfo about the performed checks */
- if ( (CapturedWindowRect.Left < 0) || (CapturedWindowRect.Top < 0) ||
- (CapturedWindowRect.Right >= Buffer->ScreenBufferSize.X) ||
- (CapturedWindowRect.Bottom >= Buffer->ScreenBufferSize.Y) ||
- (CapturedWindowRect.Right <= CapturedWindowRect.Left) ||
- (CapturedWindowRect.Bottom <= CapturedWindowRect.Top) )
+ /*
+ * The MSDN documentation on SetConsoleWindowInfo is partially wrong about
+ * the performed checks this API performs. While it is correct that the
+ * 'Right'/'Bottom' members cannot be strictly smaller than the 'Left'/'Top'
+ * members, they can be equal.
+ * Also, if the 'Left' or 'Top' members are negative, this is automatically
+ * corrected for, and the window rectangle coordinates are shifted accordingly.
+ */
+ if ((CapturedWindowRect.Right < CapturedWindowRect.Left) ||
+ (CapturedWindowRect.Bottom < CapturedWindowRect.Top))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /*
+ * Forbid window sizes larger than the largest allowed console window size,
+ * taking into account the size of the console screen buffer.
+ */
+ TermGetLargestConsoleWindowSize(Console, &LargestWindowSize);
+ LargestWindowSize.X = min(LargestWindowSize.X, Buffer->ScreenBufferSize.X);
+ LargestWindowSize.Y = min(LargestWindowSize.Y, Buffer->ScreenBufferSize.Y);
+ if ((CapturedWindowRect.Right - CapturedWindowRect.Left + 1 > LargestWindowSize.X) ||
+ (CapturedWindowRect.Bottom - CapturedWindowRect.Top + 1 > LargestWindowSize.Y))
{
return STATUS_INVALID_PARAMETER;
}
+ /* Shift the window rectangle coordinates if 'Left' or 'Top' are negative */
+ if (CapturedWindowRect.Left < 0)
+ {
+ CapturedWindowRect.Right -= CapturedWindowRect.Left;
+ CapturedWindowRect.Left = 0;
+ }
+ if (CapturedWindowRect.Top < 0)
+ {
+ CapturedWindowRect.Bottom -= CapturedWindowRect.Top;
+ CapturedWindowRect.Top = 0;
+ }
+
+ /* Clip the window rectangle to the screen buffer */
+ CapturedWindowRect.Right = min(CapturedWindowRect.Right , Buffer->ScreenBufferSize.X);
+ CapturedWindowRect.Bottom = min(CapturedWindowRect.Bottom, Buffer->ScreenBufferSize.Y);
+
Buffer->ViewOrigin.X = CapturedWindowRect.Left;
Buffer->ViewOrigin.Y = CapturedWindowRect.Top;
Buffer->ViewSize.X = CapturedWindowRect.Right - CapturedWindowRect.Left + 1;
Buffer->ViewSize.Y = CapturedWindowRect.Bottom - CapturedWindowRect.Top + 1;
- // TermResizeTerminal(Console);
+ TermResizeTerminal(Console);
return STATUS_SUCCESS;
}