[WIN32SS][WINSRV] Fullwidth character handling Part 2 (#2240)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Sun, 12 Jan 2020 13:04:57 +0000 (22:04 +0900)
committerGitHub <noreply@github.com>
Sun, 12 Jan 2020 13:04:57 +0000 (22:04 +0900)
Follow-up of #2231. Also fix FillConsoleOutputAttribute, WriteConsoleOutputCharacterW and WriteConsoleOutputAttribute functions.
CORE-12451

win32ss/user/winsrv/consrv/condrv/text.c
win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
win32ss/user/winsrv/consrv/frontends/gui/guiterm.h
win32ss/user/winsrv/consrv/frontends/gui/text.c
win32ss/user/winsrv/consrv/frontends/terminal.c

index de0c740..92a6f4d 100644 (file)
@@ -14,6 +14,8 @@
 #define NDEBUG
 #include <debug.h>
 
+#define COMMON_LEAD_TRAIL (COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE)
+
 /* GLOBALS ********************************************************************/
 
 /*
@@ -512,8 +514,7 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console,
                 WideCharToMultiByte(Console->OutputCodePage, 0, &Ptr->Char.UnicodeChar, 1,
                                     &CurCharInfo->Char.AsciiChar, 1, NULL, NULL);
             }
-            CurCharInfo->Attributes =
-                (Ptr->Attributes & ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE));
+            CurCharInfo->Attributes = (Ptr->Attributes & ~COMMON_LEAD_TRAIL);
             ++Ptr;
             ++CurCharInfo;
         }
@@ -734,7 +735,7 @@ IntReadConsoleOutputStringAscii(IN PCONSOLE Console,
     SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
     ULONG i;
     PCHAR_INFO Ptr;
-    BOOL bCJK = Console->IsCJK;
+    BOOLEAN bCJK = Console->IsCJK;
 
     for (i = 0; i < NumCodesToRead; ++i)
     {
@@ -791,7 +792,7 @@ IntReadConsoleOutputStringUnicode(IN PCONSOLE Console,
     SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
     ULONG i, nNumChars = 0;
     PCHAR_INFO Ptr;
-    BOOL bCJK = Console->IsCJK;
+    BOOLEAN bCJK = Console->IsCJK;
 
     for (i = 0; i < NumCodesToRead; ++i, ++nNumChars)
     {
@@ -932,138 +933,236 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console,
     }
 }
 
-NTSTATUS NTAPI
-ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
-                               IN PTEXTMODE_SCREEN_BUFFER Buffer,
-                               IN CODE_TYPE CodeType,
-                               IN PVOID StringBuffer,
-                               IN ULONG NumCodesToWrite,
-                               IN PCOORD WriteCoord,
-                               // OUT PCOORD EndCoord,
-                               OUT PULONG NumCodesWritten OPTIONAL)
+static NTSTATUS
+IntWriteConsoleOutputStringUnicode(
+    IN PCONSOLE Console,
+    IN PTEXTMODE_SCREEN_BUFFER Buffer,
+    IN PVOID StringBuffer,
+    IN ULONG NumCodesToWrite,
+    IN PCOORD WriteCoord,
+    OUT PULONG NumCodesWritten OPTIONAL)
 {
     NTSTATUS Status = STATUS_SUCCESS;
-    PVOID WriteBuffer = NULL;
-    PWCHAR tmpString = NULL;
-    ULONG X, Y, Length; // , Written = 0;
-    ULONG CodeSize;
+    PWCHAR WriteBuffer = StringBuffer;
+    ULONG i, X, Y, Length;
     PCHAR_INFO Ptr;
+    BOOLEAN bCJK = Console->IsCJK;
 
-    if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */)
-    {
-        return STATUS_INVALID_PARAMETER;
-    }
+    if (!StringBuffer)
+        goto Cleanup;
 
-    /* Validity checks */
-    ASSERT(Console == Buffer->Header.Console);
-    ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0));
-
-    //
-    // FIXME: Make overflow checks on WriteCoord !!!!!!
-    //
-
-    if (NumCodesWritten) *NumCodesWritten = 0;
+    X = WriteCoord->X;
+    Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
+    Length = NumCodesToWrite;
 
-    switch (CodeType)
+    for (i = 0; i < Length; ++i)
     {
-        case CODE_ASCII:
-            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
-            break;
-
-        case CODE_UNICODE:
-            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
-            break;
-
-        case CODE_ATTRIBUTE:
-            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
-            break;
+        Ptr = ConioCoordToPointer(Buffer, X, Y);
 
-        default:
-            return STATUS_INVALID_PARAMETER;
-    }
+        Ptr->Char.UnicodeChar = *WriteBuffer;
+        ++WriteBuffer;
 
-    if (CodeType == CODE_ASCII)
-    {
-        /* Convert the ASCII string into Unicode before writing it to the console */
-        Length = MultiByteToWideChar(Console->OutputCodePage, 0,
-                                     (PCHAR)StringBuffer,
-                                     NumCodesToWrite,
-                                     NULL, 0);
-        tmpString = WriteBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
-        if (WriteBuffer)
+        ++X;
+        if (X == Buffer->ScreenBufferSize.X)
         {
-            MultiByteToWideChar(Console->OutputCodePage, 0,
-                                (PCHAR)StringBuffer,
-                                NumCodesToWrite,
-                                (PWCHAR)WriteBuffer, Length);
+            X = 0;
+            ++Y;
+            if (Y == Buffer->ScreenBufferSize.Y)
+            {
+                Y = 0;
+            }
         }
-        else
+
+        /* For Chinese, Japanese and Korean */
+        if (bCJK && Ptr->Char.UnicodeChar >= 0x80 &&
+            mk_wcwidth_cjk(Ptr->Char.UnicodeChar) == 2)
         {
-            Status = STATUS_NO_MEMORY;
-        }
+            /* A full-width character cannot cross a line boundary */
+            if (X == Buffer->ScreenBufferSize.X - 1)
+            {
+                /* go to next line */
+                X = 0;
+                ++Y;
+                if (Y == Buffer->ScreenBufferSize.Y)
+                {
+                    Y = 0;
+                }
+                Ptr = ConioCoordToPointer(Buffer, X, Y);
+            }
 
-        // FIXME: Quick fix: fix the CodeType and CodeSize since the
-        // ASCII string was converted into UNICODE.
-        // A proper fix needs to be written.
-        CodeType = CODE_UNICODE;
-        CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
+            /* the leading byte */
+            Ptr->Attributes = Buffer->ScreenDefaultAttrib;
+            Ptr->Attributes |= COMMON_LVB_LEADING_BYTE;
+            ++i;
+
+            /* the trailing byte */
+            Ptr = ConioCoordToPointer(Buffer, X, Y);
+            Ptr->Attributes = Buffer->ScreenDefaultAttrib;
+            Ptr->Attributes |= COMMON_LVB_TRAILING_BYTE;
+
+            ++X;
+            if (X == Buffer->ScreenBufferSize.X)
+            {
+                X = 0;
+                ++Y;
+                if (Y == Buffer->ScreenBufferSize.Y)
+                {
+                    Y = 0;
+                }
+            }
+        }
     }
-    else
+
+Cleanup:
+    if (NumCodesWritten)
+        *NumCodesWritten = NumCodesToWrite;
+    return Status;
+}
+
+static NTSTATUS
+IntWriteConsoleOutputStringAscii(
+    IN PCONSOLE Console,
+    IN PTEXTMODE_SCREEN_BUFFER Buffer,
+    IN PVOID StringBuffer,
+    IN ULONG NumCodesToWrite,
+    IN PCOORD WriteCoord,
+    OUT PULONG NumCodesWritten OPTIONAL)
+{
+    NTSTATUS Status;
+    PWCHAR tmpString;
+    ULONG Length;
+
+    if (!StringBuffer)
     {
-        /* For CODE_UNICODE or CODE_ATTRIBUTE, we are already OK */
-        WriteBuffer = StringBuffer;
+        if (NumCodesWritten)
+            *NumCodesWritten = NumCodesToWrite;
+
+        return STATUS_SUCCESS;
     }
 
-    if (WriteBuffer == NULL || !NT_SUCCESS(Status)) goto Cleanup;
+    /* Convert the ASCII string into Unicode before writing it to the console */
+    Length = MultiByteToWideChar(Console->OutputCodePage, 0,
+                                 StringBuffer,
+                                 NumCodesToWrite,
+                                 NULL, 0);
+    tmpString = ConsoleAllocHeap(0, Length * sizeof(WCHAR));
+    if (!tmpString)
+        return STATUS_NO_MEMORY;
+
+    MultiByteToWideChar(Console->OutputCodePage, 0,
+                        StringBuffer,
+                        NumCodesToWrite,
+                        tmpString, Length);
+
+    Status = IntWriteConsoleOutputStringUnicode(Console,
+                                                Buffer,
+                                                tmpString,
+                                                Length,
+                                                WriteCoord,
+                                                NumCodesWritten);
+    ConsoleFreeHeap(tmpString);
+    return Status;
+}
+
+static NTSTATUS
+IntWriteConsoleOutputStringAttribute(
+    IN PCONSOLE Console,
+    IN PTEXTMODE_SCREEN_BUFFER Buffer,
+    IN PVOID StringBuffer,
+    IN ULONG NumCodesToWrite,
+    IN PCOORD WriteCoord,
+    OUT PULONG NumCodesWritten OPTIONAL)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PWORD WriteBuffer = StringBuffer;
+    ULONG i, X, Y, Length;
+    PCHAR_INFO Ptr;
+
+    if (!StringBuffer)
+        goto Cleanup;
 
     X = WriteCoord->X;
     Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
     Length = NumCodesToWrite;
 
-    while (Length--)
+    for (i = 0; i < Length; ++i)
     {
         Ptr = ConioCoordToPointer(Buffer, X, Y);
 
-        switch (CodeType)
-        {
-            case CODE_ASCII:
-            case CODE_UNICODE:
-                Ptr->Char.UnicodeChar = *(PWCHAR)WriteBuffer;
-                break;
-
-            case CODE_ATTRIBUTE:
-                Ptr->Attributes = *(PWORD)WriteBuffer;
-                break;
-        }
-        WriteBuffer = (PVOID)((ULONG_PTR)WriteBuffer + CodeSize);
-        // ++Ptr;
+        Ptr->Attributes = (*WriteBuffer & ~COMMON_LEAD_TRAIL);
+        ++WriteBuffer;
 
-        // Written++;
-        if (++X == Buffer->ScreenBufferSize.X)
+        ++X;
+        if (X == Buffer->ScreenBufferSize.X)
         {
             X = 0;
-
-            if (++Y == Buffer->ScreenBufferSize.Y)
+            ++Y;
+            if (Y == Buffer->ScreenBufferSize.Y)
             {
                 Y = 0;
             }
         }
     }
 
+Cleanup:
+    if (NumCodesWritten)
+        *NumCodesWritten = NumCodesToWrite;
+    return Status;
+}
+
+NTSTATUS NTAPI
+ConDrvWriteConsoleOutputString(
+    IN PCONSOLE Console,
+    IN PTEXTMODE_SCREEN_BUFFER Buffer,
+    IN CODE_TYPE CodeType,
+    IN PVOID StringBuffer,
+    IN ULONG NumCodesToWrite,
+    IN PCOORD WriteCoord,
+    OUT PULONG NumCodesWritten OPTIONAL)
+{
+    NTSTATUS Status;
+    SMALL_RECT UpdateRect;
+
+    if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Validity checks */
+    ASSERT(Console == Buffer->Header.Console);
+    ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0));
+
+    if (NumCodesWritten)
+        *NumCodesWritten = 0;
+
+    switch (CodeType)
+    {
+        case CODE_ASCII:
+            Status = IntWriteConsoleOutputStringAscii(
+                Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
+            break;
+
+        case CODE_UNICODE:
+            Status = IntWriteConsoleOutputStringUnicode(
+                Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
+            break;
+
+        case CODE_ATTRIBUTE:
+            Status = IntWriteConsoleOutputStringAttribute(
+                Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
+            break;
+
+        default:
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+    }
+
     if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
     {
-        SMALL_RECT UpdateRect;
         ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite);
         TermDrawRegion(Console, &UpdateRect);
     }
 
-    // EndCoord->X = X;
-    // EndCoord->Y = (Y + Buffer->ScreenBufferSize.Y - Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
-
-Cleanup:
-    if (tmpString) RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString);
-
-    if (NumCodesWritten) *NumCodesWritten = NumCodesToWrite; // Written;
     return Status;
 }
 
@@ -1078,7 +1177,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
 {
     ULONG X, Y, i;
     PCHAR_INFO Ptr;
-    BOOL bLead, bFullwidth;
+    BOOLEAN bLead, bFullwidth;
 
     if (Console == NULL || Buffer == NULL || WriteCoord == NULL)
     {
@@ -1133,7 +1232,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
             case CODE_ASCII:
             case CODE_UNICODE:
                 Ptr->Char.UnicodeChar = Code.UnicodeChar;
-                Ptr->Attributes &= ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE);
+                Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
                 if (bFullwidth)
                 {
                     if (bLead)
@@ -1144,18 +1243,17 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
                 break;
 
             case CODE_ATTRIBUTE:
-                Ptr->Attributes &= ~0xFF;
-                Ptr->Attributes |= (Code.Attribute & 0xFF);
+                Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
+                Ptr->Attributes |= (Code.Attribute & ~COMMON_LEAD_TRAIL);
                 break;
         }
-        // ++Ptr;
 
-        // Written++;
-        if (++X == Buffer->ScreenBufferSize.X)
+        ++X;
+        if (X == Buffer->ScreenBufferSize.X)
         {
             X = 0;
-
-            if (++Y == Buffer->ScreenBufferSize.Y)
+            ++Y;
+            if (Y == Buffer->ScreenBufferSize.Y)
             {
                 Y = 0;
             }
@@ -1170,7 +1268,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
         {
             Ptr = ConioCoordToPointer(Buffer, X - 1, Y);
             Ptr->Char.UnicodeChar = L' ';
-            Ptr->Attributes &= ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE);
+            Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
         }
     }
 
index eda0e82..633317c 100644 (file)
@@ -991,17 +991,8 @@ OnPaint(PGUI_CONSOLE_DATA GuiData)
         /* Compose the current screen-buffer on-memory */
         if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
         {
-            if (IsCJKCodePage(ActiveBuffer->Header.Console->OutputCodePage))
-            {
-                /* For Chinese, Japanese and Korean */
-                GuiPaintTextModeBufferCJK((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
-                                          GuiData, &ps.rcPaint, &rcPaint);
-            }
-            else
-            {
-                GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
-                                       GuiData, &ps.rcPaint, &rcPaint);
-            }
+            GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
+                                   GuiData, &ps.rcPaint, &rcPaint);
         }
         else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
         {
index 2e4a6df..4ed6c1e 100644 (file)
@@ -121,11 +121,4 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
                        PRECT rcView,
                        PRECT rcFramebuffer);
 
-/* For Chinese, Japanese and Korean */
-VOID
-GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
-                          PGUI_CONSOLE_DATA GuiData,
-                          PRECT rcView,
-                          PRECT rcFramebuffer);
-
 /* EOF */
index 8b12645..1751dfe 100644 (file)
@@ -405,54 +405,88 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
     NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
     OldFont = SelectObject(GuiData->hMemDC, NewFont);
 
-    for (Line = TopLine; Line <= BottomLine; Line++)
+    if (Console->IsCJK)
     {
-        WCHAR LineBuffer[80];   // Buffer containing a part or all the line to be displayed
-        From  = ConioCoordToPointer(Buffer, LeftColumn, Line);  // Get the first code of the line
-        Start = LeftColumn;
-        To    = LineBuffer;
-
-        for (Char = LeftColumn; Char <= RightColumn; Char++)
+        for (Line = TopLine; Line <= BottomLine; Line++)
         {
-            /*
-             * We flush the buffer if the new attribute is different
-             * from the current one, or if the buffer is full.
-             */
-            if (From->Attributes != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
+            for (Char = LeftColumn; Char <= RightColumn; Char++)
             {
-                TextOutW(GuiData->hMemDC,
-                         Start * GuiData->CharWidth,
-                         Line  * GuiData->CharHeight,
-                         LineBuffer,
-                         Char - Start);
-                Start = Char;
-                To    = LineBuffer;
+                From = ConioCoordToPointer(Buffer, Char, Line);
                 Attribute = From->Attributes;
-                if (Attribute != LastAttribute)
+                SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
+                SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(Attribute)));
+
+                /* Change underline state if needed */
+                if (!!(Attribute & COMMON_LVB_UNDERSCORE) != IsUnderline)
                 {
-                    LastAttribute = Attribute;
-                    SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
-                    SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
+                    IsUnderline = !!(Attribute & COMMON_LVB_UNDERSCORE);
+
+                    /* Select the new font */
+                    NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
+                    SelectObject(GuiData->hMemDC, NewFont);
+                }
+
+                if (Attribute & COMMON_LVB_TRAILING_BYTE)
+                    continue;
+
+                TextOutW(GuiData->hMemDC,
+                         Char * GuiData->CharWidth,
+                         Line * GuiData->CharHeight,
+                         &From->Char.UnicodeChar, 1);
+            }
+        }
+    }
+    else
+    {
+        for (Line = TopLine; Line <= BottomLine; Line++)
+        {
+            WCHAR LineBuffer[80];   // Buffer containing a part or all the line to be displayed
+            From  = ConioCoordToPointer(Buffer, LeftColumn, Line);  // Get the first code of the line
+            Start = LeftColumn;
+            To    = LineBuffer;
 
-                    /* Change underline state if needed */
-                    if (!!(LastAttribute & COMMON_LVB_UNDERSCORE) != IsUnderline)
+            for (Char = LeftColumn; Char <= RightColumn; Char++)
+            {
+                /*
+                 * We flush the buffer if the new attribute is different
+                 * from the current one, or if the buffer is full.
+                 */
+                if (From->Attributes != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
+                {
+                    TextOutW(GuiData->hMemDC,
+                             Start * GuiData->CharWidth,
+                             Line  * GuiData->CharHeight,
+                             LineBuffer,
+                             Char - Start);
+                    Start = Char;
+                    To    = LineBuffer;
+                    Attribute = From->Attributes;
+                    if (Attribute != LastAttribute)
                     {
-                        IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE);
-                        /* Select the new font */
-                        NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
-                        /* OldFont = */ SelectObject(GuiData->hMemDC, NewFont);
+                        LastAttribute = Attribute;
+                        SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
+                        SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
+
+                        /* Change underline state if needed */
+                        if (!!(LastAttribute & COMMON_LVB_UNDERSCORE) != IsUnderline)
+                        {
+                            IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE);
+                            /* Select the new font */
+                            NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
+                            SelectObject(GuiData->hMemDC, NewFont);
+                        }
                     }
                 }
+
+                *(To++) = (From++)->Char.UnicodeChar;
             }
 
-            *(To++) = (From++)->Char.UnicodeChar;
+            TextOutW(GuiData->hMemDC,
+                     Start * GuiData->CharWidth,
+                     Line  * GuiData->CharHeight,
+                     LineBuffer,
+                     RightColumn - Start + 1);
         }
-
-        TextOutW(GuiData->hMemDC,
-                 Start * GuiData->CharWidth,
-                 Line  * GuiData->CharHeight,
-                 LineBuffer,
-                 RightColumn - Start + 1);
     }
 
     /* Restore the old font */
@@ -479,12 +513,35 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
             CursorBrush = CreateSolidBrush(PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
             OldBrush    = SelectObject(GuiData->hMemDC, CursorBrush);
 
-            PatBlt(GuiData->hMemDC,
-                   CursorX * GuiData->CharWidth,
-                   CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
-                   GuiData->CharWidth,
-                   CursorHeight,
-                   PATCOPY);
+            if (Attribute & COMMON_LVB_LEADING_BYTE)
+            {
+                /* The caret is on the leading byte */
+                PatBlt(GuiData->hMemDC,
+                       CursorX * GuiData->CharWidth,
+                       CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
+                       GuiData->CharWidth * 2,
+                       CursorHeight,
+                       PATCOPY);
+            }
+            else if (Attribute & COMMON_LVB_TRAILING_BYTE)
+            {
+                /* The caret is on the trailing byte */
+                PatBlt(GuiData->hMemDC,
+                       (CursorX - 1) * GuiData->CharWidth,
+                       CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
+                       GuiData->CharWidth * 2,
+                       CursorHeight,
+                       PATCOPY);
+            }
+            else
+            {
+                PatBlt(GuiData->hMemDC,
+                       CursorX * GuiData->CharWidth,
+                       CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
+                       GuiData->CharWidth,
+                       CursorHeight,
+                       PATCOPY);
+            }
 
             SelectObject(GuiData->hMemDC, OldBrush);
             DeleteObject(CursorBrush);
@@ -494,15 +551,4 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
     LeaveCriticalSection(&Console->Lock);
 }
 
-/* For Chinese, Japanese and Korean */
-VOID
-GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
-                          PGUI_CONSOLE_DATA GuiData,
-                          PRECT rcView,
-                          PRECT rcFramebuffer)
-{
-    /* FIXME */
-    GuiPaintTextModeBuffer(Buffer, GuiData, rcView, rcFramebuffer);
-}
-
 /* EOF */
index 6603d84..bae13a8 100644 (file)
@@ -558,6 +558,17 @@ ConioWriteConsole(PFRONTEND FrontEnd,
                     }
                     Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
                     Ptr->Char.UnicodeChar = L' ';
+
+                    if (Ptr->Attributes & COMMON_LVB_TRAILING_BYTE)
+                    {
+                        /* Delete a full-width character */
+                        Ptr->Attributes  = Buff->ScreenDefaultAttrib;
+                        if (Buff->CursorPosition.X > 0)
+                            Buff->CursorPosition.X--;
+                        Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+                        Ptr->Char.UnicodeChar = L' ';
+                    }
+
                     Ptr->Attributes  = Buff->ScreenDefaultAttrib;
                     UpdateRect.Left  = min(UpdateRect.Left, Buff->CursorPosition.X);
                     UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);