[WIN32SS][WINSRV] Fullwidth character handling Part 2 (#2240)

Follow-up of #2231. Also fix FillConsoleOutputAttribute, WriteConsoleOutputCharacterW and WriteConsoleOutputAttribute functions.
CORE-12451
This commit is contained in:
Katayama Hirofumi MZ 2020-01-12 22:04:57 +09:00 committed by GitHub
parent dbe1d36e5b
commit b41299470b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 323 additions and 184 deletions

View file

@ -14,6 +14,8 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#define COMMON_LEAD_TRAIL (COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE)
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
/* /*
@ -512,8 +514,7 @@ 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 = CurCharInfo->Attributes = (Ptr->Attributes & ~COMMON_LEAD_TRAIL);
(Ptr->Attributes & ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE));
++Ptr; ++Ptr;
++CurCharInfo; ++CurCharInfo;
} }
@ -734,7 +735,7 @@ IntReadConsoleOutputStringAscii(IN PCONSOLE Console,
SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
ULONG i; ULONG i;
PCHAR_INFO Ptr; PCHAR_INFO Ptr;
BOOL bCJK = Console->IsCJK; BOOLEAN bCJK = Console->IsCJK;
for (i = 0; i < NumCodesToRead; ++i) for (i = 0; i < NumCodesToRead; ++i)
{ {
@ -791,7 +792,7 @@ IntReadConsoleOutputStringUnicode(IN PCONSOLE Console,
SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; SHORT Ypos = (ReadCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
ULONG i, nNumChars = 0; ULONG i, nNumChars = 0;
PCHAR_INFO Ptr; PCHAR_INFO Ptr;
BOOL bCJK = Console->IsCJK; BOOLEAN bCJK = Console->IsCJK;
for (i = 0; i < NumCodesToRead; ++i, ++nNumChars) for (i = 0; i < NumCodesToRead; ++i, ++nNumChars)
{ {
@ -932,22 +933,195 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console,
} }
} }
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;
PWCHAR WriteBuffer = StringBuffer;
ULONG i, X, Y, Length;
PCHAR_INFO Ptr;
BOOLEAN bCJK = Console->IsCJK;
if (!StringBuffer)
goto Cleanup;
X = WriteCoord->X;
Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
Length = NumCodesToWrite;
for (i = 0; i < Length; ++i)
{
Ptr = ConioCoordToPointer(Buffer, X, Y);
Ptr->Char.UnicodeChar = *WriteBuffer;
++WriteBuffer;
++X;
if (X == Buffer->ScreenBufferSize.X)
{
X = 0;
++Y;
if (Y == Buffer->ScreenBufferSize.Y)
{
Y = 0;
}
}
/* For Chinese, Japanese and Korean */
if (bCJK && Ptr->Char.UnicodeChar >= 0x80 &&
mk_wcwidth_cjk(Ptr->Char.UnicodeChar) == 2)
{
/* 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);
}
/* 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;
}
}
}
}
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)
{
if (NumCodesWritten)
*NumCodesWritten = NumCodesToWrite;
return STATUS_SUCCESS;
}
/* 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;
for (i = 0; i < Length; ++i)
{
Ptr = ConioCoordToPointer(Buffer, X, Y);
Ptr->Attributes = (*WriteBuffer & ~COMMON_LEAD_TRAIL);
++WriteBuffer;
++X;
if (X == Buffer->ScreenBufferSize.X)
{
X = 0;
++Y;
if (Y == Buffer->ScreenBufferSize.Y)
{
Y = 0;
}
}
}
Cleanup:
if (NumCodesWritten)
*NumCodesWritten = NumCodesToWrite;
return Status;
}
NTSTATUS NTAPI NTSTATUS NTAPI
ConDrvWriteConsoleOutputString(IN PCONSOLE Console, ConDrvWriteConsoleOutputString(
IN PCONSOLE Console,
IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PTEXTMODE_SCREEN_BUFFER Buffer,
IN CODE_TYPE CodeType, IN CODE_TYPE CodeType,
IN PVOID StringBuffer, IN PVOID StringBuffer,
IN ULONG NumCodesToWrite, IN ULONG NumCodesToWrite,
IN PCOORD WriteCoord, IN PCOORD WriteCoord,
// OUT PCOORD EndCoord,
OUT PULONG NumCodesWritten OPTIONAL) OUT PULONG NumCodesWritten OPTIONAL)
{ {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status;
PVOID WriteBuffer = NULL; SMALL_RECT UpdateRect;
PWCHAR tmpString = NULL;
ULONG X, Y, Length; // , Written = 0;
ULONG CodeSize;
PCHAR_INFO Ptr;
if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */) if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */)
{ {
@ -958,112 +1132,37 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
ASSERT(Console == Buffer->Header.Console); ASSERT(Console == Buffer->Header.Console);
ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0)); ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0));
// if (NumCodesWritten)
// FIXME: Make overflow checks on WriteCoord !!!!!! *NumCodesWritten = 0;
//
if (NumCodesWritten) *NumCodesWritten = 0;
switch (CodeType) switch (CodeType)
{ {
case CODE_ASCII: case CODE_ASCII:
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); Status = IntWriteConsoleOutputStringAscii(
Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
break; break;
case CODE_UNICODE: case CODE_UNICODE:
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); Status = IntWriteConsoleOutputStringUnicode(
Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
break; break;
case CODE_ATTRIBUTE: case CODE_ATTRIBUTE:
CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); Status = IntWriteConsoleOutputStringAttribute(
Console, Buffer, StringBuffer, NumCodesToWrite, WriteCoord, NumCodesWritten);
break; break;
default: default:
return STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
}
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)
{
MultiByteToWideChar(Console->OutputCodePage, 0,
(PCHAR)StringBuffer,
NumCodesToWrite,
(PWCHAR)WriteBuffer, Length);
}
else
{
Status = STATUS_NO_MEMORY;
}
// 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);
}
else
{
/* For CODE_UNICODE or CODE_ATTRIBUTE, we are already OK */
WriteBuffer = StringBuffer;
}
if (WriteBuffer == NULL || !NT_SUCCESS(Status)) goto Cleanup;
X = WriteCoord->X;
Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
Length = NumCodesToWrite;
while (Length--)
{
Ptr = ConioCoordToPointer(Buffer, X, Y);
switch (CodeType)
{
case CODE_ASCII:
case CODE_UNICODE:
Ptr->Char.UnicodeChar = *(PWCHAR)WriteBuffer;
break; break;
case CODE_ATTRIBUTE:
Ptr->Attributes = *(PWORD)WriteBuffer;
break;
}
WriteBuffer = (PVOID)((ULONG_PTR)WriteBuffer + CodeSize);
// ++Ptr;
// Written++;
if (++X == Buffer->ScreenBufferSize.X)
{
X = 0;
if (++Y == Buffer->ScreenBufferSize.Y)
{
Y = 0;
}
}
} }
if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
{ {
SMALL_RECT UpdateRect;
ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite); ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite);
TermDrawRegion(Console, &UpdateRect); 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; return Status;
} }
@ -1078,7 +1177,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
{ {
ULONG X, Y, i; ULONG X, Y, i;
PCHAR_INFO Ptr; PCHAR_INFO Ptr;
BOOL bLead, bFullwidth; BOOLEAN bLead, bFullwidth;
if (Console == NULL || Buffer == NULL || WriteCoord == NULL) if (Console == NULL || Buffer == NULL || WriteCoord == NULL)
{ {
@ -1133,7 +1232,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
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); Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
if (bFullwidth) if (bFullwidth)
{ {
if (bLead) if (bLead)
@ -1144,18 +1243,17 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
break; break;
case CODE_ATTRIBUTE: case CODE_ATTRIBUTE:
Ptr->Attributes &= ~0xFF; Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
Ptr->Attributes |= (Code.Attribute & 0xFF); Ptr->Attributes |= (Code.Attribute & ~COMMON_LEAD_TRAIL);
break; break;
} }
// ++Ptr;
// Written++; ++X;
if (++X == Buffer->ScreenBufferSize.X) if (X == Buffer->ScreenBufferSize.X)
{ {
X = 0; X = 0;
++Y;
if (++Y == Buffer->ScreenBufferSize.Y) if (Y == Buffer->ScreenBufferSize.Y)
{ {
Y = 0; Y = 0;
} }
@ -1170,7 +1268,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
{ {
Ptr = ConioCoordToPointer(Buffer, X - 1, Y); Ptr = ConioCoordToPointer(Buffer, X - 1, Y);
Ptr->Char.UnicodeChar = L' '; Ptr->Char.UnicodeChar = L' ';
Ptr->Attributes &= ~(COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE); Ptr->Attributes &= ~COMMON_LEAD_TRAIL;
} }
} }

View file

@ -990,19 +990,10 @@ OnPaint(PGUI_CONSOLE_DATA GuiData)
/* Compose the current screen-buffer on-memory */ /* Compose the current screen-buffer on-memory */
if (GetType(ActiveBuffer) == TEXTMODE_BUFFER) 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, GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
GuiData, &ps.rcPaint, &rcPaint); GuiData, &ps.rcPaint, &rcPaint);
} }
}
else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */ else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
{ {
GuiPaintGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)ActiveBuffer, GuiPaintGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)ActiveBuffer,

View file

@ -121,11 +121,4 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
PRECT rcView, PRECT rcView,
PRECT rcFramebuffer); PRECT rcFramebuffer);
/* For Chinese, Japanese and Korean */
VOID
GuiPaintTextModeBufferCJK(PTEXTMODE_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData,
PRECT rcView,
PRECT rcFramebuffer);
/* EOF */ /* EOF */

View file

@ -405,6 +405,39 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL]; NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
OldFont = SelectObject(GuiData->hMemDC, NewFont); OldFont = SelectObject(GuiData->hMemDC, NewFont);
if (Console->IsCJK)
{
for (Line = TopLine; Line <= BottomLine; Line++)
{
for (Char = LeftColumn; Char <= RightColumn; Char++)
{
From = ConioCoordToPointer(Buffer, Char, Line);
Attribute = From->Attributes;
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)
{
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++) for (Line = TopLine; Line <= BottomLine; Line++)
{ {
WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed
@ -440,7 +473,7 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE); IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE);
/* Select the new font */ /* Select the new font */
NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL]; NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
/* OldFont = */ SelectObject(GuiData->hMemDC, NewFont); SelectObject(GuiData->hMemDC, NewFont);
} }
} }
} }
@ -454,6 +487,7 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
LineBuffer, LineBuffer,
RightColumn - Start + 1); RightColumn - Start + 1);
} }
}
/* Restore the old font */ /* Restore the old font */
SelectObject(GuiData->hMemDC, OldFont); SelectObject(GuiData->hMemDC, OldFont);
@ -479,12 +513,35 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
CursorBrush = CreateSolidBrush(PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute))); CursorBrush = CreateSolidBrush(PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
OldBrush = SelectObject(GuiData->hMemDC, CursorBrush); OldBrush = SelectObject(GuiData->hMemDC, CursorBrush);
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, PatBlt(GuiData->hMemDC,
CursorX * GuiData->CharWidth, CursorX * GuiData->CharWidth,
CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight), CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
GuiData->CharWidth, GuiData->CharWidth,
CursorHeight, CursorHeight,
PATCOPY); PATCOPY);
}
SelectObject(GuiData->hMemDC, OldBrush); SelectObject(GuiData->hMemDC, OldBrush);
DeleteObject(CursorBrush); DeleteObject(CursorBrush);
@ -494,15 +551,4 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
LeaveCriticalSection(&Console->Lock); 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 */ /* EOF */

View file

@ -558,6 +558,17 @@ ConioWriteConsole(PFRONTEND FrontEnd,
} }
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
Ptr->Char.UnicodeChar = L' '; 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; Ptr->Attributes = Buff->ScreenDefaultAttrib;
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);