mirror of
https://github.com/reactos/reactos.git
synced 2024-11-27 05:23:33 +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
|
||||
* Jeffrey Morlan
|
||||
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
||||
* Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <consrv.h>
|
||||
|
||||
#include <coninput.h>
|
||||
#include "../../concfg/font.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
static ULONG CurrentConsoleID = 0;
|
||||
@ -220,6 +220,8 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole,
|
||||
if (IsValidCodePage(ConsoleInfo->CodePage))
|
||||
Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
|
||||
|
||||
Console->IsCJK = IsCJKCodePage(Console->OutputCodePage);
|
||||
|
||||
/* Initialize a new text-mode screen buffer with default settings */
|
||||
ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
|
||||
ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
|
||||
@ -531,9 +533,14 @@ ConDrvSetConsoleCP(IN PCONSOLE Console,
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (OutputCP)
|
||||
{
|
||||
Console->OutputCodePage = CodePage;
|
||||
Console->IsCJK = IsCJKCodePage(CodePage);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console->InputCodePage = CodePage;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -408,13 +408,9 @@ ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console,
|
||||
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.
|
||||
@ -516,7 +512,8 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console,
|
||||
WideCharToMultiByte(Console->OutputCodePage, 0, &Ptr->Char.UnicodeChar, 1,
|
||||
&CurCharInfo->Char.AsciiChar, 1, NULL, NULL);
|
||||
}
|
||||
CurCharInfo->Attributes = Ptr->Attributes;
|
||||
CurCharInfo->Attributes =
|
||||
(Ptr->Attributes & ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE));
|
||||
++Ptr;
|
||||
++CurCharInfo;
|
||||
}
|
||||
@ -723,6 +720,166 @@ ConDrvWriteConsole(IN PCONSOLE Console,
|
||||
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
|
||||
ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
@ -730,15 +887,8 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
||||
OUT PVOID StringBuffer,
|
||||
IN ULONG NumCodesToRead,
|
||||
IN PCOORD ReadCoord,
|
||||
// OUT PCOORD EndCoord,
|
||||
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 */)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
@ -748,92 +898,38 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console,
|
||||
ASSERT(Console == Buffer->Header.Console);
|
||||
ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0));
|
||||
|
||||
//
|
||||
// FIXME: Make overflow checks on ReadCoord !!!!!!
|
||||
//
|
||||
|
||||
if (NumCodesRead) *NumCodesRead = 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;
|
||||
}
|
||||
|
||||
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
|
||||
@ -923,13 +1019,10 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
|
||||
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];
|
||||
Ptr = ConioCoordToPointer(Buffer, X, Y);
|
||||
|
||||
switch (CodeType)
|
||||
{
|
||||
@ -983,8 +1076,9 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
||||
IN PCOORD WriteCoord,
|
||||
OUT PULONG NumCodesWritten OPTIONAL)
|
||||
{
|
||||
ULONG X, Y, Length; // , Written = 0;
|
||||
ULONG X, Y, i;
|
||||
PCHAR_INFO Ptr;
|
||||
BOOL bLead, bFullwidth;
|
||||
|
||||
if (Console == NULL || Buffer == NULL || WriteCoord == NULL)
|
||||
{
|
||||
@ -1010,24 +1104,48 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
||||
|
||||
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)
|
||||
{
|
||||
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
|
||||
Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X];
|
||||
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);
|
||||
|
||||
switch (CodeType)
|
||||
{
|
||||
case CODE_ASCII:
|
||||
case CODE_UNICODE:
|
||||
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;
|
||||
|
||||
case CODE_ATTRIBUTE:
|
||||
Ptr->Attributes = Code.Attribute;
|
||||
Ptr->Attributes &= ~0xFF;
|
||||
Ptr->Attributes |= (Code.Attribute & 0xFF);
|
||||
break;
|
||||
}
|
||||
// ++Ptr;
|
||||
@ -1042,6 +1160,18 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
|
||||
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)
|
||||
|
@ -993,7 +993,7 @@ OnPaint(PGUI_CONSOLE_DATA GuiData)
|
||||
{
|
||||
if (IsCJKCodePage(ActiveBuffer->Header.Console->OutputCodePage))
|
||||
{
|
||||
/* For Chinese, Japanese and Korean: */
|
||||
/* For Chinese, Japanese and Korean */
|
||||
GuiPaintTextModeBufferCJK((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
|
||||
GuiData, &ps.rcPaint, &rcPaint);
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
PRECT rcView,
|
||||
PRECT rcFramebuffer);
|
||||
|
||||
/* For Chinese, Japanese and Korean: */
|
||||
/* For Chinese, Japanese and Korean */
|
||||
VOID
|
||||
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
PGUI_CONSOLE_DATA GuiData,
|
||||
|
@ -494,7 +494,7 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
}
|
||||
|
||||
/* For Chinese, Japanese and Korean: */
|
||||
/* For Chinese, Japanese and Korean */
|
||||
VOID
|
||||
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
|
||||
PGUI_CONSOLE_DATA GuiData,
|
||||
|
@ -492,8 +492,6 @@ ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT Scroll
|
||||
UpdateRect->Bottom = Buff->CursorPosition.Y;
|
||||
}
|
||||
|
||||
int mk_wcwidth_cjk(wchar_t ucs);
|
||||
|
||||
static NTSTATUS
|
||||
ConioWriteConsole(PFRONTEND FrontEnd,
|
||||
PTEXTMODE_SCREEN_BUFFER Buff,
|
||||
@ -508,7 +506,7 @@ ConioWriteConsole(PFRONTEND FrontEnd,
|
||||
SMALL_RECT UpdateRect;
|
||||
SHORT CursorStartX, CursorStartY;
|
||||
UINT ScrolledLines;
|
||||
BOOL bCJK = IsCJKCodePage(Console->OutputCodePage);
|
||||
BOOL bCJK = Console->IsCJK;
|
||||
|
||||
CursorStartX = Buff->CursorPosition.X;
|
||||
CursorStartY = Buff->CursorPosition.Y;
|
||||
@ -607,16 +605,56 @@ ConioWriteConsole(PFRONTEND FrontEnd,
|
||||
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);
|
||||
|
||||
/* For Chinese, Japanese and Korean */
|
||||
if (bCJK && Buffer[i] >= 0x80 && mk_wcwidth_cjk(Buffer[i]) == 2)
|
||||
{
|
||||
/* Buffer[i] is a fullwidth character */
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
Ptr->Char.UnicodeChar = Buffer[i];
|
||||
if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib;
|
||||
if (Buff->CursorPosition.X > 0)
|
||||
{
|
||||
/* 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++;
|
||||
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)
|
||||
{
|
||||
// TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
|
||||
|
@ -345,7 +345,7 @@ typedef struct _CONSOLE
|
||||
/****************************** Other properties ******************************/
|
||||
COORD ConsoleSize; /* The current size of the console, for text-mode only */
|
||||
BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
|
||||
|
||||
BOOLEAN IsCJK; /* TRUE if Chinese, Japanese or Korean (CJK) */
|
||||
} CONSOLE; // , *PCONSOLE;
|
||||
|
||||
/* console.c */
|
||||
@ -369,4 +369,7 @@ NTSTATUS ConioResizeBuffer(PCONSOLE /*PCONSRV_CONSOLE*/ Console,
|
||||
PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
|
||||
COORD Size);
|
||||
|
||||
/* wcwidth.c */
|
||||
int mk_wcwidth_cjk(wchar_t ucs);
|
||||
|
||||
/* EOF */
|
||||
|
@ -10,6 +10,7 @@
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "consrv.h"
|
||||
#include "../concfg/font.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
@ -59,6 +60,8 @@ ConSrvApplyUserSettings(IN PCONSOLE Console,
|
||||
Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
|
||||
// ConDrvSetConsoleCP(Console, ConsoleInfo->CodePage, TRUE); // Output
|
||||
// ConDrvSetConsoleCP(Console, ConsoleInfo->CodePage, FALSE); // Input
|
||||
|
||||
Console->IsCJK = IsCJKCodePage(Console->OutputCodePage);
|
||||
}
|
||||
|
||||
// FIXME: Check ConsoleInfo->WindowSize with respect to
|
||||
|
Loading…
Reference in New Issue
Block a user