From fa42794a3a5136782375598b6636b61a95ae7317 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Tue, 7 Jan 2020 15:26:58 +0900 Subject: [PATCH] [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 --- win32ss/user/winsrv/consrv/condrv/console.c | 11 +- win32ss/user/winsrv/consrv/condrv/text.c | 310 +++++++++++++----- .../user/winsrv/consrv/frontends/gui/conwnd.c | 2 +- .../winsrv/consrv/frontends/gui/guiterm.h | 2 +- .../user/winsrv/consrv/frontends/gui/text.c | 2 +- .../user/winsrv/consrv/frontends/terminal.c | 68 +++- win32ss/user/winsrv/consrv/include/conio.h | 5 +- win32ss/user/winsrv/consrv/settings.c | 3 + 8 files changed, 298 insertions(+), 105 deletions(-) diff --git a/win32ss/user/winsrv/consrv/condrv/console.c b/win32ss/user/winsrv/consrv/condrv/console.c index d088f317eb4..f888b755c2c 100644 --- a/win32ss/user/winsrv/consrv/condrv/console.c +++ b/win32ss/user/winsrv/consrv/condrv/console.c @@ -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 - #include +#include "../../concfg/font.h" #define NDEBUG #include - /* 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; } diff --git a/win32ss/user/winsrv/consrv/condrv/text.c b/win32ss/user/winsrv/consrv/condrv/text.c index 5b4d415b297..de0c740e58f 100644 --- a/win32ss/user/winsrv/consrv/condrv/text.c +++ b/win32ss/user/winsrv/consrv/condrv/text.c @@ -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,102 +720,147 @@ ConDrvWriteConsole(IN PCONSOLE Console, return Status; } -NTSTATUS NTAPI -ConDrvReadConsoleOutputString(IN PCONSOLE Console, - IN PTEXTMODE_SCREEN_BUFFER Buffer, - IN CODE_TYPE CodeType, - OUT PVOID StringBuffer, - IN ULONG NumCodesToRead, - IN PCOORD ReadCoord, - // OUT PCOORD EndCoord, - OUT PULONG NumCodesRead OPTIONAL) +NTSTATUS FASTCALL +IntReadConsoleOutputStringAscii(IN PCONSOLE Console, + IN PTEXTMODE_SCREEN_BUFFER Buffer, + OUT PVOID StringBuffer, + IN ULONG NumCodesToRead, + IN PCOORD ReadCoord, + OUT PULONG NumCodesRead OPTIONAL) { - SHORT Xpos, Ypos; - PVOID ReadBuffer; + ULONG CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); + LPBYTE ReadBuffer = StringBuffer; + SHORT Xpos = ReadCoord->X; + SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; ULONG i; - ULONG CodeSize; PCHAR_INFO Ptr; + BOOL bCJK = Console->IsCJK; - if (Console == NULL || Buffer == NULL || ReadCoord == NULL /* || EndCoord == NULL */) + for (i = 0; i < NumCodesToRead; ++i) { - return STATUS_INVALID_PARAMETER; + Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); + + ConsoleOutputUnicodeToAnsiChar(Console, (PCHAR)ReadBuffer, &Ptr->Char.UnicodeChar); + ReadBuffer += CodeSize; + + Xpos++; + if (Xpos == Buffer->ScreenBufferSize.X) + { + Xpos = 0; + Ypos++; + if (Ypos == Buffer->ScreenBufferSize.Y) + { + Ypos = 0; + } + } + + /* For Chinese, Japanese and Korean */ + if (bCJK && (Ptr->Attributes & COMMON_LVB_LEADING_BYTE)) + { + Xpos++; + if (Xpos == Buffer->ScreenBufferSize.X) + { + Xpos = 0; + Ypos++; + if (Ypos == Buffer->ScreenBufferSize.Y) + { + Ypos = 0; + } + } + ++i; + } } - /* Validity checks */ - ASSERT(Console == Buffer->Header.Console); - ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0)); + if (NumCodesRead) + *NumCodesRead = i; - // - // FIXME: Make overflow checks on ReadCoord !!!!!! - // + return STATUS_SUCCESS; +} - if (NumCodesRead) *NumCodesRead = 0; +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; - switch (CodeType) + for (i = 0; i < NumCodesToRead; ++i, ++nNumChars) { - case CODE_ASCII: - CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); - break; + Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); - case CODE_UNICODE: - CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); - break; + *(PWCHAR)ReadBuffer = Ptr->Char.UnicodeChar; + ReadBuffer += CodeSize; - case CODE_ATTRIBUTE: - CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); - break; + Xpos++; + if (Xpos == Buffer->ScreenBufferSize.X) + { + Xpos = 0; + Ypos++; + if (Ypos == Buffer->ScreenBufferSize.Y) + { + Ypos = 0; + } + } - default: - return STATUS_INVALID_PARAMETER; + /* For Chinese, Japanese and Korean */ + if (bCJK && (Ptr->Attributes & COMMON_LVB_LEADING_BYTE)) + { + Xpos++; + if (Xpos == Buffer->ScreenBufferSize.X) + { + Xpos = 0; + Ypos++; + if (Ypos == Buffer->ScreenBufferSize.Y) + { + Ypos = 0; + } + } + ++i; + } } - ReadBuffer = StringBuffer; - Xpos = ReadCoord->X; - Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; + if (NumCodesRead) + *NumCodesRead = nNumChars; - /* - * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) : - * - * If the number of attributes (resp. characters) to be read from extends - * beyond the end of the specified screen buffer row, attributes (resp. - * characters) are read from the next row. If the number of attributes - * (resp. characters) to be read from extends beyond the end of the console - * screen buffer, attributes (resp. characters) up to the end of the console - * screen buffer are read. - * - * TODO: Do NOT loop up to NumCodesToRead, but stop before - * if we are going to overflow... - */ - // Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); // Doesn't work - for (i = 0; i < min(NumCodesToRead, (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]; + return STATUS_SUCCESS; +} - switch (CodeType) - { - case CODE_ASCII: - ConsoleOutputUnicodeToAnsiChar(Console, (PCHAR)ReadBuffer, &Ptr->Char.UnicodeChar); - break; +NTSTATUS FASTCALL +IntReadConsoleOutputStringAttributes(IN PCONSOLE Console, + IN PTEXTMODE_SCREEN_BUFFER Buffer, + OUT PVOID StringBuffer, + IN ULONG NumCodesToRead, + IN PCOORD ReadCoord, + OUT PULONG NumCodesRead OPTIONAL) +{ + ULONG CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); + LPBYTE ReadBuffer = StringBuffer; + SHORT Xpos = ReadCoord->X; + SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; + ULONG i; + PCHAR_INFO Ptr; - case CODE_UNICODE: - *(PWCHAR)ReadBuffer = Ptr->Char.UnicodeChar; - break; + for (i = 0; i < NumCodesToRead; ++i) + { + Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); - case CODE_ATTRIBUTE: - *(PWORD)ReadBuffer = Ptr->Attributes; - break; - } - ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize); - // ++Ptr; + *(PWORD)ReadBuffer = Ptr->Attributes; + ReadBuffer += CodeSize; Xpos++; - if (Xpos == Buffer->ScreenBufferSize.X) { Xpos = 0; Ypos++; - if (Ypos == Buffer->ScreenBufferSize.Y) { Ypos = 0; @@ -826,16 +868,70 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console, } } - // EndCoord->X = Xpos; - // EndCoord->Y = (Ypos - Buffer->VirtualY + Buffer->ScreenBufferSize.Y) % Buffer->ScreenBufferSize.Y; + if (Xpos > 0 && Console->IsCJK) + { + ReadBuffer -= CodeSize; + *(PWORD)ReadBuffer &= ~COMMON_LVB_LEADING_BYTE; + } if (NumCodesRead) - *NumCodesRead = (ULONG)((ULONG_PTR)ReadBuffer - (ULONG_PTR)StringBuffer) / CodeSize; - // <= NumCodesToRead + *NumCodesRead = NumCodesToRead; return STATUS_SUCCESS; } +NTSTATUS NTAPI +ConDrvReadConsoleOutputString(IN PCONSOLE Console, + IN PTEXTMODE_SCREEN_BUFFER Buffer, + IN CODE_TYPE CodeType, + OUT PVOID StringBuffer, + IN ULONG NumCodesToRead, + IN PCOORD ReadCoord, + OUT PULONG NumCodesRead OPTIONAL) +{ + if (Console == NULL || Buffer == NULL || ReadCoord == NULL /* || EndCoord == NULL */) + { + return STATUS_INVALID_PARAMETER; + } + + /* Validity checks */ + ASSERT(Console == Buffer->Header.Console); + ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0)); + + if (NumCodesRead) + *NumCodesRead = 0; + + switch (CodeType) + { + case CODE_ASCII: + return IntReadConsoleOutputStringAscii(Console, + Buffer, + StringBuffer, + NumCodesToRead, + ReadCoord, + NumCodesRead); + + case CODE_UNICODE: + return IntReadConsoleOutputStringUnicode(Console, + Buffer, + StringBuffer, + NumCodesToRead, + ReadCoord, + NumCodesRead); + + case CODE_ATTRIBUTE: + return IntReadConsoleOutputStringAttributes(Console, + Buffer, + StringBuffer, + NumCodesToRead, + ReadCoord, + NumCodesRead); + + default: + return STATUS_INVALID_PARAMETER; + } +} + NTSTATUS NTAPI ConDrvWriteConsoleOutputString(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, @@ -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) diff --git a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c index b7859201a3a..eda0e822861 100644 --- a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c +++ b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c @@ -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); } diff --git a/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h b/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h index bd28b2b98d1..2e4a6dfd90f 100644 --- a/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h +++ b/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h @@ -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, diff --git a/win32ss/user/winsrv/consrv/frontends/gui/text.c b/win32ss/user/winsrv/consrv/frontends/gui/text.c index 2b62c3dd377..8b12645df77 100644 --- a/win32ss/user/winsrv/consrv/frontends/gui/text.c +++ b/win32ss/user/winsrv/consrv/frontends/gui/text.c @@ -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, diff --git a/win32ss/user/winsrv/consrv/frontends/terminal.c b/win32ss/user/winsrv/consrv/frontends/terminal.c index c4ca197a6dd..6603d844050 100644 --- a/win32ss/user/winsrv/consrv/frontends/terminal.c +++ b/win32ss/user/winsrv/consrv/frontends/terminal.c @@ -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, diff --git a/win32ss/user/winsrv/consrv/include/conio.h b/win32ss/user/winsrv/consrv/include/conio.h index 3e7f96dd096..ad1b226020d 100644 --- a/win32ss/user/winsrv/consrv/include/conio.h +++ b/win32ss/user/winsrv/consrv/include/conio.h @@ -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 */ diff --git a/win32ss/user/winsrv/consrv/settings.c b/win32ss/user/winsrv/consrv/settings.c index 1cfd4d37971..879c152d4d1 100644 --- a/win32ss/user/winsrv/consrv/settings.c +++ b/win32ss/user/winsrv/consrv/settings.c @@ -10,6 +10,7 @@ /* INCLUDES *******************************************************************/ #include "consrv.h" +#include "../concfg/font.h" #define NDEBUG #include @@ -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 -- 2.17.1