mirror of
https://github.com/reactos/reactos.git
synced 2024-11-27 13:33:32 +08:00
[WIN32SS][WINSRV] Fullwidth character handling for Asian console (#2231)
Far-East Asian language (Chinese, Japanese and Korean; CJK) needs special handling in console. Especially a fullwidth character (mk_wcwidth_cjk(ch) == 2) needs a double width space. A fullwidth character on the console window is treated as a pair of a leading byte and a trailing byte (COMMON_LVB_LEADING_BYTE and COMMON_LVB_TRAILING_BYTE). CORE-12451
This commit is contained in:
parent
b00a1f3e76
commit
fa42794a3a
@ -6,18 +6,18 @@
|
|||||||
* PROGRAMMERS: Gé van Geldorp
|
* PROGRAMMERS: Gé van Geldorp
|
||||||
* Jeffrey Morlan
|
* Jeffrey Morlan
|
||||||
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
||||||
|
* Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *******************************************************************/
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
#include <consrv.h>
|
#include <consrv.h>
|
||||||
|
|
||||||
#include <coninput.h>
|
#include <coninput.h>
|
||||||
|
#include "../../concfg/font.h"
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
|
||||||
/* GLOBALS ********************************************************************/
|
/* GLOBALS ********************************************************************/
|
||||||
|
|
||||||
static ULONG CurrentConsoleID = 0;
|
static ULONG CurrentConsoleID = 0;
|
||||||
@ -220,6 +220,8 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole,
|
|||||||
if (IsValidCodePage(ConsoleInfo->CodePage))
|
if (IsValidCodePage(ConsoleInfo->CodePage))
|
||||||
Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
|
Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
|
||||||
|
|
||||||
|
Console->IsCJK = IsCJKCodePage(Console->OutputCodePage);
|
||||||
|
|
||||||
/* Initialize a new text-mode screen buffer with default settings */
|
/* Initialize a new text-mode screen buffer with default settings */
|
||||||
ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
|
ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
|
||||||
ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
|
ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
|
||||||
@ -531,9 +533,14 @@ ConDrvSetConsoleCP(IN PCONSOLE Console,
|
|||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (OutputCP)
|
if (OutputCP)
|
||||||
|
{
|
||||||
Console->OutputCodePage = CodePage;
|
Console->OutputCodePage = CodePage;
|
||||||
|
Console->IsCJK = IsCJKCodePage(CodePage);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Console->InputCodePage = CodePage;
|
Console->InputCodePage = CodePage;
|
||||||
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -408,13 +408,9 @@ ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console,
|
|||||||
Y = (TopLeft.Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
Y = (TopLeft.Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
||||||
Length = NumCodesToWrite;
|
Length = NumCodesToWrite;
|
||||||
|
|
||||||
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
|
|
||||||
// Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
|
|
||||||
|
|
||||||
while (Length--)
|
while (Length--)
|
||||||
{
|
{
|
||||||
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
|
Ptr = ConioCoordToPointer(Buffer, X, Y);
|
||||||
Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change the current colors only if they are the old ones.
|
* Change the current colors only if they are the old ones.
|
||||||
@ -516,7 +512,8 @@ 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 = Ptr->Attributes;
|
CurCharInfo->Attributes =
|
||||||
|
(Ptr->Attributes & ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE));
|
||||||
++Ptr;
|
++Ptr;
|
||||||
++CurCharInfo;
|
++CurCharInfo;
|
||||||
}
|
}
|
||||||
@ -723,6 +720,166 @@ ConDrvWriteConsole(IN PCONSOLE Console,
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FASTCALL
|
||||||
|
IntReadConsoleOutputStringAscii(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, AsciiChar);
|
||||||
|
LPBYTE ReadBuffer = StringBuffer;
|
||||||
|
SHORT Xpos = ReadCoord->X;
|
||||||
|
SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
||||||
|
ULONG i;
|
||||||
|
PCHAR_INFO Ptr;
|
||||||
|
BOOL bCJK = Console->IsCJK;
|
||||||
|
|
||||||
|
for (i = 0; i < NumCodesToRead; ++i)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumCodesRead)
|
||||||
|
*NumCodesRead = i;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
BOOL bCJK = Console->IsCJK;
|
||||||
|
|
||||||
|
for (i = 0; i < NumCodesToRead; ++i, ++nNumChars)
|
||||||
|
{
|
||||||
|
Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos);
|
||||||
|
|
||||||
|
*(PWCHAR)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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumCodesRead)
|
||||||
|
*NumCodesRead = nNumChars;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
for (i = 0; i < NumCodesToRead; ++i)
|
||||||
|
{
|
||||||
|
Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos);
|
||||||
|
|
||||||
|
*(PWORD)ReadBuffer = Ptr->Attributes;
|
||||||
|
ReadBuffer += CodeSize;
|
||||||
|
|
||||||
|
Xpos++;
|
||||||
|
if (Xpos == Buffer->ScreenBufferSize.X)
|
||||||
|
{
|
||||||
|
Xpos = 0;
|
||||||
|
Ypos++;
|
||||||
|
if (Ypos == Buffer->ScreenBufferSize.Y)
|
||||||
|
{
|
||||||
|
Ypos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Xpos > 0 && Console->IsCJK)
|
||||||
|
{
|
||||||
|
ReadBuffer -= CodeSize;
|
||||||
|
*(PWORD)ReadBuffer &= ~COMMON_LVB_LEADING_BYTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumCodesRead)
|
||||||
|
*NumCodesRead = NumCodesToRead;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
||||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
@ -730,15 +887,8 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
|||||||
OUT PVOID StringBuffer,
|
OUT PVOID StringBuffer,
|
||||||
IN ULONG NumCodesToRead,
|
IN ULONG NumCodesToRead,
|
||||||
IN PCOORD ReadCoord,
|
IN PCOORD ReadCoord,
|
||||||
// OUT PCOORD EndCoord,
|
|
||||||
OUT PULONG NumCodesRead OPTIONAL)
|
OUT PULONG NumCodesRead OPTIONAL)
|
||||||
{
|
{
|
||||||
SHORT Xpos, Ypos;
|
|
||||||
PVOID ReadBuffer;
|
|
||||||
ULONG i;
|
|
||||||
ULONG CodeSize;
|
|
||||||
PCHAR_INFO Ptr;
|
|
||||||
|
|
||||||
if (Console == NULL || Buffer == NULL || ReadCoord == NULL /* || EndCoord == NULL */)
|
if (Console == NULL || Buffer == NULL || ReadCoord == NULL /* || EndCoord == NULL */)
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
@ -748,92 +898,38 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
|||||||
ASSERT(Console == Buffer->Header.Console);
|
ASSERT(Console == Buffer->Header.Console);
|
||||||
ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0));
|
ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0));
|
||||||
|
|
||||||
//
|
if (NumCodesRead)
|
||||||
// FIXME: Make overflow checks on ReadCoord !!!!!!
|
*NumCodesRead = 0;
|
||||||
//
|
|
||||||
|
|
||||||
if (NumCodesRead) *NumCodesRead = 0;
|
|
||||||
|
|
||||||
switch (CodeType)
|
switch (CodeType)
|
||||||
{
|
{
|
||||||
case CODE_ASCII:
|
case CODE_ASCII:
|
||||||
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
|
return IntReadConsoleOutputStringAscii(Console,
|
||||||
break;
|
Buffer,
|
||||||
|
StringBuffer,
|
||||||
|
NumCodesToRead,
|
||||||
|
ReadCoord,
|
||||||
|
NumCodesRead);
|
||||||
|
|
||||||
case CODE_UNICODE:
|
case CODE_UNICODE:
|
||||||
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
|
return IntReadConsoleOutputStringUnicode(Console,
|
||||||
break;
|
Buffer,
|
||||||
|
StringBuffer,
|
||||||
|
NumCodesToRead,
|
||||||
|
ReadCoord,
|
||||||
|
NumCodesRead);
|
||||||
|
|
||||||
case CODE_ATTRIBUTE:
|
case CODE_ATTRIBUTE:
|
||||||
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
|
return IntReadConsoleOutputStringAttributes(Console,
|
||||||
break;
|
Buffer,
|
||||||
|
StringBuffer,
|
||||||
|
NumCodesToRead,
|
||||||
|
ReadCoord,
|
||||||
|
NumCodesRead);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadBuffer = StringBuffer;
|
|
||||||
Xpos = ReadCoord->X;
|
|
||||||
Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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, (ULONG)Buffer->ScreenBufferSize.X * Buffer->ScreenBufferSize.Y); ++i)
|
|
||||||
{
|
|
||||||
// Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); // Doesn't work either
|
|
||||||
Ptr = &Buffer->Buffer[Xpos + Ypos * Buffer->ScreenBufferSize.X];
|
|
||||||
|
|
||||||
switch (CodeType)
|
|
||||||
{
|
|
||||||
case CODE_ASCII:
|
|
||||||
ConsoleOutputUnicodeToAnsiChar(Console, (PCHAR)ReadBuffer, &Ptr->Char.UnicodeChar);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CODE_UNICODE:
|
|
||||||
*(PWCHAR)ReadBuffer = Ptr->Char.UnicodeChar;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CODE_ATTRIBUTE:
|
|
||||||
*(PWORD)ReadBuffer = Ptr->Attributes;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
|
|
||||||
// ++Ptr;
|
|
||||||
|
|
||||||
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 (NumCodesRead)
|
|
||||||
*NumCodesRead = (ULONG)((ULONG_PTR)ReadBuffer - (ULONG_PTR)StringBuffer) / CodeSize;
|
|
||||||
// <= NumCodesToRead
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
@ -923,13 +1019,10 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
|
|||||||
X = WriteCoord->X;
|
X = WriteCoord->X;
|
||||||
Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
||||||
Length = NumCodesToWrite;
|
Length = NumCodesToWrite;
|
||||||
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
|
|
||||||
// Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
|
|
||||||
|
|
||||||
while (Length--)
|
while (Length--)
|
||||||
{
|
{
|
||||||
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
|
Ptr = ConioCoordToPointer(Buffer, X, Y);
|
||||||
Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X];
|
|
||||||
|
|
||||||
switch (CodeType)
|
switch (CodeType)
|
||||||
{
|
{
|
||||||
@ -983,8 +1076,9 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
|||||||
IN PCOORD WriteCoord,
|
IN PCOORD WriteCoord,
|
||||||
OUT PULONG NumCodesWritten OPTIONAL)
|
OUT PULONG NumCodesWritten OPTIONAL)
|
||||||
{
|
{
|
||||||
ULONG X, Y, Length; // , Written = 0;
|
ULONG X, Y, i;
|
||||||
PCHAR_INFO Ptr;
|
PCHAR_INFO Ptr;
|
||||||
|
BOOL bLead, bFullwidth;
|
||||||
|
|
||||||
if (Console == NULL || Buffer == NULL || WriteCoord == NULL)
|
if (Console == NULL || Buffer == NULL || WriteCoord == NULL)
|
||||||
{
|
{
|
||||||
@ -1010,24 +1104,48 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
|||||||
|
|
||||||
X = WriteCoord->X;
|
X = WriteCoord->X;
|
||||||
Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
|
||||||
Length = NumCodesToWrite;
|
|
||||||
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
|
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
|
||||||
// Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May 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)
|
||||||
{
|
{
|
||||||
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
|
bFullwidth = (mk_wcwidth_cjk(Code.UnicodeChar) == 2);
|
||||||
Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X];
|
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);
|
||||||
|
|
||||||
switch (CodeType)
|
switch (CodeType)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
if (bFullwidth)
|
||||||
|
{
|
||||||
|
if (bLead)
|
||||||
|
Ptr->Attributes |= COMMON_LVB_LEADING_BYTE;
|
||||||
|
else
|
||||||
|
Ptr->Attributes |= COMMON_LVB_TRAILING_BYTE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CODE_ATTRIBUTE:
|
case CODE_ATTRIBUTE:
|
||||||
Ptr->Attributes = Code.Attribute;
|
Ptr->Attributes &= ~0xFF;
|
||||||
|
Ptr->Attributes |= (Code.Attribute & 0xFF);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// ++Ptr;
|
// ++Ptr;
|
||||||
@ -1042,6 +1160,18 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
|||||||
Y = 0;
|
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_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
|
if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
|
||||||
|
@ -993,7 +993,7 @@ OnPaint(PGUI_CONSOLE_DATA GuiData)
|
|||||||
{
|
{
|
||||||
if (IsCJKCodePage(ActiveBuffer->Header.Console->OutputCodePage))
|
if (IsCJKCodePage(ActiveBuffer->Header.Console->OutputCodePage))
|
||||||
{
|
{
|
||||||
/* For Chinese, Japanese and Korean: */
|
/* For Chinese, Japanese and Korean */
|
||||||
GuiPaintTextModeBufferCJK((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
|
GuiPaintTextModeBufferCJK((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
|
||||||
GuiData, &ps.rcPaint, &rcPaint);
|
GuiData, &ps.rcPaint, &rcPaint);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
|||||||
PRECT rcView,
|
PRECT rcView,
|
||||||
PRECT rcFramebuffer);
|
PRECT rcFramebuffer);
|
||||||
|
|
||||||
/* For Chinese, Japanese and Korean: */
|
/* For Chinese, Japanese and Korean */
|
||||||
VOID
|
VOID
|
||||||
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
|
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
PGUI_CONSOLE_DATA GuiData,
|
PGUI_CONSOLE_DATA GuiData,
|
||||||
|
@ -494,7 +494,7 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
|||||||
LeaveCriticalSection(&Console->Lock);
|
LeaveCriticalSection(&Console->Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For Chinese, Japanese and Korean: */
|
/* For Chinese, Japanese and Korean */
|
||||||
VOID
|
VOID
|
||||||
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
|
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||||
PGUI_CONSOLE_DATA GuiData,
|
PGUI_CONSOLE_DATA GuiData,
|
||||||
|
@ -492,8 +492,6 @@ ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT Scroll
|
|||||||
UpdateRect->Bottom = Buff->CursorPosition.Y;
|
UpdateRect->Bottom = Buff->CursorPosition.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mk_wcwidth_cjk(wchar_t ucs);
|
|
||||||
|
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
ConioWriteConsole(PFRONTEND FrontEnd,
|
ConioWriteConsole(PFRONTEND FrontEnd,
|
||||||
PTEXTMODE_SCREEN_BUFFER Buff,
|
PTEXTMODE_SCREEN_BUFFER Buff,
|
||||||
@ -508,7 +506,7 @@ ConioWriteConsole(PFRONTEND FrontEnd,
|
|||||||
SMALL_RECT UpdateRect;
|
SMALL_RECT UpdateRect;
|
||||||
SHORT CursorStartX, CursorStartY;
|
SHORT CursorStartX, CursorStartY;
|
||||||
UINT ScrolledLines;
|
UINT ScrolledLines;
|
||||||
BOOL bCJK = IsCJKCodePage(Console->OutputCodePage);
|
BOOL bCJK = Console->IsCJK;
|
||||||
|
|
||||||
CursorStartX = Buff->CursorPosition.X;
|
CursorStartX = Buff->CursorPosition.X;
|
||||||
CursorStartY = Buff->CursorPosition.Y;
|
CursorStartY = Buff->CursorPosition.Y;
|
||||||
@ -607,16 +605,56 @@ ConioWriteConsole(PFRONTEND FrontEnd,
|
|||||||
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);
|
||||||
|
|
||||||
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
/* For Chinese, Japanese and Korean */
|
||||||
|
|
||||||
if (bCJK && Buffer[i] >= 0x80 && mk_wcwidth_cjk(Buffer[i]) == 2)
|
if (bCJK && Buffer[i] >= 0x80 && mk_wcwidth_cjk(Buffer[i]) == 2)
|
||||||
{
|
{
|
||||||
/* Buffer[i] is a fullwidth character */
|
/* Buffer[i] is a fullwidth character */
|
||||||
/* FIXME */
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr->Char.UnicodeChar = Buffer[i];
|
if (Buff->CursorPosition.X > 0)
|
||||||
if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib;
|
{
|
||||||
|
/* Kill the previous leading byte */
|
||||||
|
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X - 1, Buff->CursorPosition.Y);
|
||||||
|
if (Ptr->Attributes & COMMON_LVB_LEADING_BYTE)
|
||||||
|
{
|
||||||
|
Ptr->Char.UnicodeChar = L' ';
|
||||||
|
if (Attrib)
|
||||||
|
Ptr->Attributes &= ~COMMON_LVB_LEADING_BYTE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X - 1)
|
||||||
|
{
|
||||||
|
/* New line */
|
||||||
|
if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
|
||||||
|
{
|
||||||
|
Buff->CursorPosition.X = 0;
|
||||||
|
ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Buff->CursorPosition.X = CursorStartX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set leading */
|
||||||
|
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
||||||
|
Ptr->Char.UnicodeChar = Buffer[i];
|
||||||
|
if (Attrib)
|
||||||
|
Ptr->Attributes = Buff->ScreenDefaultAttrib | COMMON_LVB_LEADING_BYTE;
|
||||||
|
|
||||||
|
/* Set trailing */
|
||||||
|
Buff->CursorPosition.X++;
|
||||||
|
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
||||||
|
if (Attrib)
|
||||||
|
Ptr->Attributes = Buff->ScreenDefaultAttrib | COMMON_LVB_TRAILING_BYTE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
||||||
|
Ptr->Char.UnicodeChar = Buffer[i];
|
||||||
|
if (Attrib)
|
||||||
|
Ptr->Attributes = Buff->ScreenDefaultAttrib;
|
||||||
|
}
|
||||||
|
|
||||||
Buff->CursorPosition.X++;
|
Buff->CursorPosition.X++;
|
||||||
if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
|
if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
|
||||||
@ -633,6 +671,18 @@ ConioWriteConsole(PFRONTEND FrontEnd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bCJK && Buff->CursorPosition.X > 0)
|
||||||
|
{
|
||||||
|
/* Delete trailing */
|
||||||
|
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
||||||
|
if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
|
||||||
|
{
|
||||||
|
Ptr->Char.UnicodeChar = L' ';
|
||||||
|
if (Attrib)
|
||||||
|
Ptr->Attributes = Buff->ScreenDefaultAttrib;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
|
if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
|
||||||
{
|
{
|
||||||
// TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
|
// TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
|
||||||
|
@ -345,7 +345,7 @@ typedef struct _CONSOLE
|
|||||||
/****************************** Other properties ******************************/
|
/****************************** Other properties ******************************/
|
||||||
COORD ConsoleSize; /* The current size of the console, for text-mode only */
|
COORD ConsoleSize; /* The current size of the console, for text-mode only */
|
||||||
BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
|
BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
|
||||||
|
BOOLEAN IsCJK; /* TRUE if Chinese, Japanese or Korean (CJK) */
|
||||||
} CONSOLE; // , *PCONSOLE;
|
} CONSOLE; // , *PCONSOLE;
|
||||||
|
|
||||||
/* console.c */
|
/* console.c */
|
||||||
@ -369,4 +369,7 @@ NTSTATUS ConioResizeBuffer(PCONSOLE /*PCONSRV_CONSOLE*/ Console,
|
|||||||
PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
|
PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
|
||||||
COORD Size);
|
COORD Size);
|
||||||
|
|
||||||
|
/* wcwidth.c */
|
||||||
|
int mk_wcwidth_cjk(wchar_t ucs);
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
/* INCLUDES *******************************************************************/
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
#include "consrv.h"
|
#include "consrv.h"
|
||||||
|
#include "../concfg/font.h"
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@ -59,6 +60,8 @@ ConSrvApplyUserSettings(IN PCONSOLE Console,
|
|||||||
Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
|
Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
|
||||||
// ConDrvSetConsoleCP(Console, ConsoleInfo->CodePage, TRUE); // Output
|
// ConDrvSetConsoleCP(Console, ConsoleInfo->CodePage, TRUE); // Output
|
||||||
// ConDrvSetConsoleCP(Console, ConsoleInfo->CodePage, FALSE); // Input
|
// ConDrvSetConsoleCP(Console, ConsoleInfo->CodePage, FALSE); // Input
|
||||||
|
|
||||||
|
Console->IsCJK = IsCJKCodePage(Console->OutputCodePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Check ConsoleInfo->WindowSize with respect to
|
// FIXME: Check ConsoleInfo->WindowSize with respect to
|
||||||
|
Loading…
Reference in New Issue
Block a user