mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 21:11:54 +00:00
[WIN32SS][WINSRV] Fullwidth character handling Part 2 (#2240)
Follow-up of #2231. Also fix FillConsoleOutputAttribute, WriteConsoleOutputCharacterW and WriteConsoleOutputAttribute functions. CORE-12451
This commit is contained in:
parent
dbe1d36e5b
commit
b41299470b
5 changed files with 323 additions and 184 deletions
|
@ -14,6 +14,8 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
#define COMMON_LEAD_TRAIL (COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE)
|
||||||
|
|
||||||
/* GLOBALS ********************************************************************/
|
/* GLOBALS ********************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -512,8 +514,7 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console,
|
||||||
WideCharToMultiByte(Console->OutputCodePage, 0, &Ptr->Char.UnicodeChar, 1,
|
WideCharToMultiByte(Console->OutputCodePage, 0, &Ptr->Char.UnicodeChar, 1,
|
||||||
&CurCharInfo->Char.AsciiChar, 1, NULL, NULL);
|
&CurCharInfo->Char.AsciiChar, 1, NULL, NULL);
|
||||||
}
|
}
|
||||||
CurCharInfo->Attributes =
|
CurCharInfo->Attributes = (Ptr->Attributes & ~COMMON_LEAD_TRAIL);
|
||||||
(Ptr->Attributes & ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE));
|
|
||||||
++Ptr;
|
++Ptr;
|
||||||
++CurCharInfo;
|
++CurCharInfo;
|
||||||
}
|
}
|
||||||
|
@ -734,7 +735,7 @@ IntReadConsoleOutputStringAscii(IN PCONSOLE Console,
|
||||||
SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
PCHAR_INFO Ptr;
|
PCHAR_INFO Ptr;
|
||||||
BOOL bCJK = Console->IsCJK;
|
BOOLEAN bCJK = Console->IsCJK;
|
||||||
|
|
||||||
for (i = 0; i < NumCodesToRead; ++i)
|
for (i = 0; i < NumCodesToRead; ++i)
|
||||||
{
|
{
|
||||||
|
@ -791,7 +792,7 @@ IntReadConsoleOutputStringUnicode(IN PCONSOLE Console,
|
||||||
SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
||||||
ULONG i, nNumChars = 0;
|
ULONG i, nNumChars = 0;
|
||||||
PCHAR_INFO Ptr;
|
PCHAR_INFO Ptr;
|
||||||
BOOL bCJK = Console->IsCJK;
|
BOOLEAN bCJK = Console->IsCJK;
|
||||||
|
|
||||||
for (i = 0; i < NumCodesToRead; ++i, ++nNumChars)
|
for (i = 0; i < NumCodesToRead; ++i, ++nNumChars)
|
||||||
{
|
{
|
||||||
|
@ -932,22 +933,195 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Ptr = ConioCoordToPointer(Buffer, X, Y);
|
||||||
|
|
||||||
|
Ptr->Char.UnicodeChar = *WriteBuffer;
|
||||||
|
++WriteBuffer;
|
||||||
|
|
||||||
|
++X;
|
||||||
|
if (X == Buffer->ScreenBufferSize.X)
|
||||||
|
{
|
||||||
|
X = 0;
|
||||||
|
++Y;
|
||||||
|
if (Y == Buffer->ScreenBufferSize.Y)
|
||||||
|
{
|
||||||
|
Y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For Chinese, Japanese and Korean */
|
||||||
|
if (bCJK && Ptr->Char.UnicodeChar >= 0x80 &&
|
||||||
|
mk_wcwidth_cjk(Ptr->Char.UnicodeChar) == 2)
|
||||||
|
{
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (NumCodesWritten)
|
||||||
|
*NumCodesWritten = NumCodesToWrite;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
for (i = 0; i < Length; ++i)
|
||||||
|
{
|
||||||
|
Ptr = ConioCoordToPointer(Buffer, X, Y);
|
||||||
|
|
||||||
|
Ptr->Attributes = (*WriteBuffer & ~COMMON_LEAD_TRAIL);
|
||||||
|
++WriteBuffer;
|
||||||
|
|
||||||
|
++X;
|
||||||
|
if (X == Buffer->ScreenBufferSize.X)
|
||||||
|
{
|
||||||
|
X = 0;
|
||||||
|
++Y;
|
||||||
|
if (Y == Buffer->ScreenBufferSize.Y)
|
||||||
|
{
|
||||||
|
Y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
if (NumCodesWritten)
|
||||||
|
*NumCodesWritten = NumCodesToWrite;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
|
ConDrvWriteConsoleOutputString(
|
||||||
|
IN PCONSOLE Console,
|
||||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
IN CODE_TYPE CodeType,
|
IN CODE_TYPE CodeType,
|
||||||
IN PVOID StringBuffer,
|
IN PVOID StringBuffer,
|
||||||
IN ULONG NumCodesToWrite,
|
IN ULONG NumCodesToWrite,
|
||||||
IN PCOORD WriteCoord,
|
IN PCOORD WriteCoord,
|
||||||
// OUT PCOORD EndCoord,
|
|
||||||
OUT PULONG NumCodesWritten OPTIONAL)
|
OUT PULONG NumCodesWritten OPTIONAL)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status;
|
||||||
PVOID WriteBuffer = NULL;
|
SMALL_RECT UpdateRect;
|
||||||
PWCHAR tmpString = NULL;
|
|
||||||
ULONG X, Y, Length; // , Written = 0;
|
|
||||||
ULONG CodeSize;
|
|
||||||
PCHAR_INFO Ptr;
|
|
||||||
|
|
||||||
if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */)
|
if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */)
|
||||||
{
|
{
|
||||||
|
@ -958,112 +1132,37 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
|
||||||
ASSERT(Console == Buffer->Header.Console);
|
ASSERT(Console == Buffer->Header.Console);
|
||||||
ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0));
|
ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0));
|
||||||
|
|
||||||
//
|
if (NumCodesWritten)
|
||||||
// FIXME: Make overflow checks on WriteCoord !!!!!!
|
*NumCodesWritten = 0;
|
||||||
//
|
|
||||||
|
|
||||||
if (NumCodesWritten) *NumCodesWritten = 0;
|
|
||||||
|
|
||||||
switch (CodeType)
|
switch (CodeType)
|
||||||
{
|
{
|
||||||
case CODE_ASCII:
|
case CODE_ASCII:
|
||||||
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
|
Status = IntWriteConsoleOutputStringAscii(
|
||||||
|
Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CODE_UNICODE:
|
case CODE_UNICODE:
|
||||||
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
|
Status = IntWriteConsoleOutputStringUnicode(
|
||||||
|
Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CODE_ATTRIBUTE:
|
case CODE_ATTRIBUTE:
|
||||||
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
|
Status = IntWriteConsoleOutputStringAttribute(
|
||||||
|
Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return STATUS_INVALID_PARAMETER;
|
Status = 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;
|
|
||||||
|
|
||||||
while (Length--)
|
|
||||||
{
|
|
||||||
Ptr = ConioCoordToPointer(Buffer, X, Y);
|
|
||||||
|
|
||||||
switch (CodeType)
|
|
||||||
{
|
|
||||||
case CODE_ASCII:
|
|
||||||
case CODE_UNICODE:
|
|
||||||
Ptr->Char.UnicodeChar = *(PWCHAR)WriteBuffer;
|
|
||||||
break;
|
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)
|
if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
|
||||||
{
|
{
|
||||||
SMALL_RECT UpdateRect;
|
|
||||||
ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite);
|
ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite);
|
||||||
TermDrawRegion(Console, &UpdateRect);
|
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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1078,7 +1177,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
||||||
{
|
{
|
||||||
ULONG X, Y, i;
|
ULONG X, Y, i;
|
||||||
PCHAR_INFO Ptr;
|
PCHAR_INFO Ptr;
|
||||||
BOOL bLead, bFullwidth;
|
BOOLEAN bLead, bFullwidth;
|
||||||
|
|
||||||
if (Console == NULL || Buffer == NULL || WriteCoord == NULL)
|
if (Console == NULL || Buffer == NULL || WriteCoord == NULL)
|
||||||
{
|
{
|
||||||
|
@ -1133,7 +1232,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
||||||
case CODE_ASCII:
|
case CODE_ASCII:
|
||||||
case CODE_UNICODE:
|
case CODE_UNICODE:
|
||||||
Ptr->Char.UnicodeChar = Code.UnicodeChar;
|
Ptr->Char.UnicodeChar = Code.UnicodeChar;
|
||||||
Ptr->Attributes &= ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE);
|
Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
|
||||||
if (bFullwidth)
|
if (bFullwidth)
|
||||||
{
|
{
|
||||||
if (bLead)
|
if (bLead)
|
||||||
|
@ -1144,18 +1243,17 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CODE_ATTRIBUTE:
|
case CODE_ATTRIBUTE:
|
||||||
Ptr->Attributes &= ~0xFF;
|
Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
|
||||||
Ptr->Attributes |= (Code.Attribute & 0xFF);
|
Ptr->Attributes |= (Code.Attribute & ~COMMON_LEAD_TRAIL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// ++Ptr;
|
|
||||||
|
|
||||||
// Written++;
|
++X;
|
||||||
if (++X == Buffer->ScreenBufferSize.X)
|
if (X == Buffer->ScreenBufferSize.X)
|
||||||
{
|
{
|
||||||
X = 0;
|
X = 0;
|
||||||
|
++Y;
|
||||||
if (++Y == Buffer->ScreenBufferSize.Y)
|
if (Y == Buffer->ScreenBufferSize.Y)
|
||||||
{
|
{
|
||||||
Y = 0;
|
Y = 0;
|
||||||
}
|
}
|
||||||
|
@ -1170,7 +1268,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
||||||
{
|
{
|
||||||
Ptr = ConioCoordToPointer(Buffer, X - 1, Y);
|
Ptr = ConioCoordToPointer(Buffer, X - 1, Y);
|
||||||
Ptr->Char.UnicodeChar = L' ';
|
Ptr->Char.UnicodeChar = L' ';
|
||||||
Ptr->Attributes &= ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE);
|
Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -990,19 +990,10 @@ OnPaint(PGUI_CONSOLE_DATA GuiData)
|
||||||
|
|
||||||
/* Compose the current screen-buffer on-memory */
|
/* Compose the current screen-buffer on-memory */
|
||||||
if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
|
if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
|
||||||
{
|
|
||||||
if (IsCJKCodePage(ActiveBuffer->Header.Console->OutputCodePage))
|
|
||||||
{
|
|
||||||
/* For Chinese, Japanese and Korean */
|
|
||||||
GuiPaintTextModeBufferCJK((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
|
|
||||||
GuiData, &ps.rcPaint, &rcPaint);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
|
GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
|
||||||
GuiData, &ps.rcPaint, &rcPaint);
|
GuiData, &ps.rcPaint, &rcPaint);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
|
else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
|
||||||
{
|
{
|
||||||
GuiPaintGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)ActiveBuffer,
|
GuiPaintGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)ActiveBuffer,
|
||||||
|
|
|
@ -121,11 +121,4 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
PRECT rcView,
|
PRECT rcView,
|
||||||
PRECT rcFramebuffer);
|
PRECT rcFramebuffer);
|
||||||
|
|
||||||
/* For Chinese, Japanese and Korean */
|
|
||||||
VOID
|
|
||||||
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
|
|
||||||
PGUI_CONSOLE_DATA GuiData,
|
|
||||||
PRECT rcView,
|
|
||||||
PRECT rcFramebuffer);
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -405,6 +405,39 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
|
NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
|
||||||
OldFont = SelectObject(GuiData->hMemDC, NewFont);
|
OldFont = SelectObject(GuiData->hMemDC, NewFont);
|
||||||
|
|
||||||
|
if (Console->IsCJK)
|
||||||
|
{
|
||||||
|
for (Line = TopLine; Line <= BottomLine; Line++)
|
||||||
|
{
|
||||||
|
for (Char = LeftColumn; Char <= RightColumn; Char++)
|
||||||
|
{
|
||||||
|
From = ConioCoordToPointer(Buffer, Char, Line);
|
||||||
|
Attribute = From->Attributes;
|
||||||
|
SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
|
||||||
|
SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(Attribute)));
|
||||||
|
|
||||||
|
/* Change underline state if needed */
|
||||||
|
if (!!(Attribute & COMMON_LVB_UNDERSCORE) != IsUnderline)
|
||||||
|
{
|
||||||
|
IsUnderline = !!(Attribute & COMMON_LVB_UNDERSCORE);
|
||||||
|
|
||||||
|
/* Select the new font */
|
||||||
|
NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
|
||||||
|
SelectObject(GuiData->hMemDC, NewFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Attribute & COMMON_LVB_TRAILING_BYTE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TextOutW(GuiData->hMemDC,
|
||||||
|
Char * GuiData->CharWidth,
|
||||||
|
Line * GuiData->CharHeight,
|
||||||
|
&From->Char.UnicodeChar, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for (Line = TopLine; Line <= BottomLine; Line++)
|
for (Line = TopLine; Line <= BottomLine; Line++)
|
||||||
{
|
{
|
||||||
WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed
|
WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed
|
||||||
|
@ -440,7 +473,7 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE);
|
IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE);
|
||||||
/* Select the new font */
|
/* Select the new font */
|
||||||
NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
|
NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
|
||||||
/* OldFont = */ SelectObject(GuiData->hMemDC, NewFont);
|
SelectObject(GuiData->hMemDC, NewFont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,6 +487,7 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
LineBuffer,
|
LineBuffer,
|
||||||
RightColumn - Start + 1);
|
RightColumn - Start + 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Restore the old font */
|
/* Restore the old font */
|
||||||
SelectObject(GuiData->hMemDC, OldFont);
|
SelectObject(GuiData->hMemDC, OldFont);
|
||||||
|
@ -479,12 +513,35 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
CursorBrush = CreateSolidBrush(PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
|
CursorBrush = CreateSolidBrush(PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
|
||||||
OldBrush = SelectObject(GuiData->hMemDC, CursorBrush);
|
OldBrush = SelectObject(GuiData->hMemDC, CursorBrush);
|
||||||
|
|
||||||
|
if (Attribute & COMMON_LVB_LEADING_BYTE)
|
||||||
|
{
|
||||||
|
/* The caret is on the leading byte */
|
||||||
|
PatBlt(GuiData->hMemDC,
|
||||||
|
CursorX * GuiData->CharWidth,
|
||||||
|
CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
|
||||||
|
GuiData->CharWidth * 2,
|
||||||
|
CursorHeight,
|
||||||
|
PATCOPY);
|
||||||
|
}
|
||||||
|
else if (Attribute & COMMON_LVB_TRAILING_BYTE)
|
||||||
|
{
|
||||||
|
/* The caret is on the trailing byte */
|
||||||
|
PatBlt(GuiData->hMemDC,
|
||||||
|
(CursorX - 1) * GuiData->CharWidth,
|
||||||
|
CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
|
||||||
|
GuiData->CharWidth * 2,
|
||||||
|
CursorHeight,
|
||||||
|
PATCOPY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
PatBlt(GuiData->hMemDC,
|
PatBlt(GuiData->hMemDC,
|
||||||
CursorX * GuiData->CharWidth,
|
CursorX * GuiData->CharWidth,
|
||||||
CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
|
CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
|
||||||
GuiData->CharWidth,
|
GuiData->CharWidth,
|
||||||
CursorHeight,
|
CursorHeight,
|
||||||
PATCOPY);
|
PATCOPY);
|
||||||
|
}
|
||||||
|
|
||||||
SelectObject(GuiData->hMemDC, OldBrush);
|
SelectObject(GuiData->hMemDC, OldBrush);
|
||||||
DeleteObject(CursorBrush);
|
DeleteObject(CursorBrush);
|
||||||
|
@ -494,15 +551,4 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
LeaveCriticalSection(&Console->Lock);
|
LeaveCriticalSection(&Console->Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For Chinese, Japanese and Korean */
|
|
||||||
VOID
|
|
||||||
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
|
|
||||||
PGUI_CONSOLE_DATA GuiData,
|
|
||||||
PRECT rcView,
|
|
||||||
PRECT rcFramebuffer)
|
|
||||||
{
|
|
||||||
/* FIXME */
|
|
||||||
GuiPaintTextModeBuffer(Buffer, GuiData, rcView, rcFramebuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -558,6 +558,17 @@ ConioWriteConsole(PFRONTEND FrontEnd,
|
||||||
}
|
}
|
||||||
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
||||||
Ptr->Char.UnicodeChar = L' ';
|
Ptr->Char.UnicodeChar = L' ';
|
||||||
|
|
||||||
|
if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
|
||||||
|
{
|
||||||
|
/* Delete a full-width character */
|
||||||
|
Ptr->Attributes = Buff->ScreenDefaultAttrib;
|
||||||
|
if (Buff->CursorPosition.X > 0)
|
||||||
|
Buff->CursorPosition.X--;
|
||||||
|
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
||||||
|
Ptr->Char.UnicodeChar = L' ';
|
||||||
|
}
|
||||||
|
|
||||||
Ptr->Attributes = Buff->ScreenDefaultAttrib;
|
Ptr->Attributes = Buff->ScreenDefaultAttrib;
|
||||||
UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
|
UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
|
||||||
UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
|
UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue