https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fa42794a3a51367823755…
commit fa42794a3a5136782375598b6636b61a95ae7317
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Jan 7 15:26:58 2020 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Jan 7 15:26:58 2020 +0900
[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 +++++++++++++++------
win32ss/user/winsrv/consrv/frontends/gui/conwnd.c | 2 +-
win32ss/user/winsrv/consrv/frontends/gui/guiterm.h | 2 +-
win32ss/user/winsrv/consrv/frontends/gui/text.c | 2 +-
win32ss/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(a)sfr.fr)
+ * Katayama Hirofumi MZ (katayama.hirofumi.mz(a)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;
}
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 <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