[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:
Katayama Hirofumi MZ 2020-01-07 15:26:58 +09:00 committed by GitHub
parent b00a1f3e76
commit fa42794a3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 305 additions and 112 deletions

View File

@ -6,18 +6,18 @@
* PROGRAMMERS: van Geldorp * PROGRAMMERS: 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;
} }

View File

@ -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)

View File

@ -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);
} }

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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