[WIN32SS][WINSRV] Fullwidth character handling Part 2 (#2240)
[reactos.git] / win32ss / user / winsrv / consrv / frontends / terminal.c
index 0ab20d8..bae13a8 100644 (file)
@@ -9,6 +9,7 @@
 /* INCLUDES *******************************************************************/
 
 #include <consrv.h>
+#include "concfg/font.h"
 
 // #include "frontends/gui/guiterm.h"
 #ifdef TUITERM_COMPILE
@@ -505,6 +506,7 @@ ConioWriteConsole(PFRONTEND FrontEnd,
     SMALL_RECT UpdateRect;
     SHORT CursorStartX, CursorStartY;
     UINT ScrolledLines;
+    BOOL bCJK = Console->IsCJK;
 
     CursorStartX = Buff->CursorPosition.X;
     CursorStartY = Buff->CursorPosition.Y;
@@ -556,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);
@@ -603,9 +616,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);
-        Ptr->Char.UnicodeChar = Buffer[i];
-        if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib;
+        /* For Chinese, Japanese and Korean */
+        if (bCJK && Buffer[i] >= 0x80 && mk_wcwidth_cjk(Buffer[i]) == 2)
+        {
+            /* Buffer[i] is a fullwidth character */
+
+            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)
@@ -622,6 +682,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,