- Use a Unicode screen-buffer for the console.
- Fix some pointers miscalculations in Read/Write console output routines, which lead to character display problems sometimes.
CORE-7277 #resolve #comment Should be fixed in revision r59212. Thanks for your report :)

svn path=/trunk/; revision=59212
This commit is contained in:
Hermès Bélusca-Maïto 2013-06-14 01:10:43 +00:00
parent 3ada1fe593
commit d224604eef
7 changed files with 323 additions and 266 deletions

View file

@ -99,7 +99,7 @@ ConioProcessInputEvent(PCONSOLE Console,
} }
} }
/* add event to the queue */ /* Add event to the queue */
ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput)); ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput));
if (ConInRec == NULL) return STATUS_INSUFFICIENT_RESOURCES; if (ConInRec == NULL) return STATUS_INSUFFICIENT_RESOURCES;

View file

@ -744,8 +744,6 @@ GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM l
{ {
PCONSOLE Console = GuiData->Console; PCONSOLE Console = GuiData->Console;
PCONSOLE_SCREEN_BUFFER ActiveBuffer; PCONSOLE_SCREEN_BUFFER ActiveBuffer;
MSG Message;
WORD VirtualKeyCode = LOWORD(wParam);
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return; if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
@ -753,6 +751,8 @@ GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM l
if (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) if (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS)
{ {
WORD VirtualKeyCode = LOWORD(wParam);
if (msg != WM_KEYDOWN) goto Quit; if (msg != WM_KEYDOWN) goto Quit;
if (VirtualKeyCode == VK_RETURN) if (VirtualKeyCode == VK_RETURN)
@ -767,12 +767,13 @@ GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM l
/* Cancel selection if ESC or Ctrl-C are pressed */ /* Cancel selection if ESC or Ctrl-C are pressed */
GuiConsoleUpdateSelection(Console, NULL); GuiConsoleUpdateSelection(Console, NULL);
SetWindowText(GuiData->hWindow, Console->Title.Buffer); SetWindowText(GuiData->hWindow, Console->Title.Buffer);
goto Quit; goto Quit;
} }
if ((Console->Selection.dwFlags & CONSOLE_MOUSE_SELECTION) == 0) if ((Console->Selection.dwFlags & CONSOLE_MOUSE_SELECTION) == 0)
{ {
/* Selection mode with keyboard */ /* Keyboard selection mode */
BOOL Interpreted = FALSE; BOOL Interpreted = FALSE;
BOOL MajPressed = (GetKeyState(VK_SHIFT) & 0x8000); BOOL MajPressed = (GetKeyState(VK_SHIFT) & 0x8000);
@ -865,20 +866,30 @@ GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM l
/* Emit an error beep sound */ /* Emit an error beep sound */
SendNotifyMessage(GuiData->hWindow, PM_CONSOLE_BEEP, 0, 0); SendNotifyMessage(GuiData->hWindow, PM_CONSOLE_BEEP, 0, 0);
} }
goto Quit;
} }
else else
{ {
/* Selection mode with mouse, clear the selection if needed */ /* Mouse selection mode */
if (!IsSystemKey(VirtualKeyCode)) if (!IsSystemKey(VirtualKeyCode))
{ {
/* Clear the selection and send the key into the input buffer */
GuiConsoleUpdateSelection(Console, NULL); GuiConsoleUpdateSelection(Console, NULL);
SetWindowText(GuiData->hWindow, Console->Title.Buffer); SetWindowText(GuiData->hWindow, Console->Title.Buffer);
} }
else
{
goto Quit;
}
} }
} }
if ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0) if ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0)
{ {
MSG Message;
Message.hwnd = GuiData->hWindow; Message.hwnd = GuiData->hWindow;
Message.message = msg; Message.message = msg;
Message.wParam = wParam; Message.wParam = wParam;
@ -2247,7 +2258,7 @@ GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
static VOID WINAPI static VOID WINAPI
GuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY, GuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
UINT ScrolledLines, CHAR *Buffer, UINT Length) UINT ScrolledLines, PWCHAR Buffer, UINT Length)
{ {
PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data; PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer; PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;

View file

@ -20,13 +20,6 @@
#include <debug.h> #include <debug.h>
/* GLOBALS ********************************************************************/
/* Copied from consrv/text.c */
#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
VOID VOID
@ -45,7 +38,7 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
BOOL InlineCopyMode = (GetKeyState(VK_SHIFT) & 0x8000); BOOL InlineCopyMode = (GetKeyState(VK_SHIFT) & 0x8000);
HANDLE hData; HANDLE hData;
PBYTE ptr; PCHAR_INFO ptr;
LPWSTR data, dstPos; LPWSTR data, dstPos;
ULONG selWidth, selHeight; ULONG selWidth, selHeight;
ULONG xPos, yPos, size; ULONG xPos, yPos, size;
@ -90,7 +83,7 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
/* Copy only the characters, leave attributes alone */ /* Copy only the characters, leave attributes alone */
for (xPos = 0; xPos < selWidth; xPos++) for (xPos = 0; xPos < selWidth; xPos++)
{ {
ConsoleAnsiCharToUnicodeChar(Console, &dstPos[xPos], (LPCSTR)&ptr[xPos * 2]); dstPos[xPos] = ptr[xPos].Char.UnicodeChar;
} }
dstPos += selWidth; dstPos += selWidth;
@ -192,9 +185,9 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
ULONG TopLine, BottomLine, LeftChar, RightChar; ULONG TopLine, BottomLine, LeftChar, RightChar;
ULONG Line, Char, Start; ULONG Line, Char, Start;
PBYTE From; PCHAR_INFO From;
PWCHAR To; PWCHAR To;
BYTE LastAttribute, Attribute; WORD LastAttribute, Attribute;
ULONG CursorX, CursorY, CursorHeight; ULONG CursorX, CursorY, CursorHeight;
HBRUSH CursorBrush, OldBrush; HBRUSH CursorBrush, OldBrush;
HFONT OldFont; HFONT OldFont;
@ -205,35 +198,40 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buffer->ViewOrigin.Y; BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buffer->ViewOrigin.Y;
LeftChar = rc->left / GuiData->CharWidth + Buffer->ViewOrigin.X; LeftChar = rc->left / GuiData->CharWidth + Buffer->ViewOrigin.X;
RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1 + Buffer->ViewOrigin.X; RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1 + Buffer->ViewOrigin.X;
LastAttribute = ConioCoordToPointer(Buffer, LeftChar, TopLine)[1];
LastAttribute = ConioCoordToPointer(Buffer, LeftChar, TopLine)->Attributes;
SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute))); SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute))); SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
if (BottomLine >= Buffer->ScreenBufferSize.Y) BottomLine = Buffer->ScreenBufferSize.Y - 1; if (BottomLine >= Buffer->ScreenBufferSize.Y) BottomLine = Buffer->ScreenBufferSize.Y - 1;
if (RightChar >= Buffer->ScreenBufferSize.X) RightChar = Buffer->ScreenBufferSize.X - 1; if (RightChar >= Buffer->ScreenBufferSize.X) RightChar = Buffer->ScreenBufferSize.X - 1;
OldFont = SelectObject(hDC, GuiData->Font); OldFont = SelectObject(hDC, GuiData->Font);
for (Line = TopLine; Line <= BottomLine; Line++) for (Line = TopLine; Line <= BottomLine; Line++)
{ {
WCHAR LineBuffer[80]; WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed
From = ConioCoordToPointer(Buffer, LeftChar, Line); From = ConioCoordToPointer(Buffer, LeftChar, Line); // Get the first code of the line
Start = LeftChar; Start = LeftChar;
To = LineBuffer; To = LineBuffer;
for (Char = LeftChar; Char <= RightChar; Char++) for (Char = LeftChar; Char <= RightChar; Char++)
{ {
if (*(From + 1) != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR))) /*
* 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(hDC, TextOutW(hDC,
(Start - Buffer->ViewOrigin.X) * GuiData->CharWidth, (Start - Buffer->ViewOrigin.X) * GuiData->CharWidth ,
(Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight, (Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
LineBuffer, LineBuffer,
Char - Start); Char - Start);
Start = Char; Start = Char;
To = LineBuffer; To = LineBuffer;
Attribute = *(From + 1); Attribute = From->Attributes;
if (Attribute != LastAttribute) if (Attribute != LastAttribute)
{ {
SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(Attribute))); SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
@ -242,15 +240,12 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
} }
} }
MultiByteToWideChar(Console->OutputCodePage, *(To++) = (From++)->Char.UnicodeChar;
0, (PCHAR)From, 1, To, 1);
To++;
From += 2;
} }
TextOutW(hDC, TextOutW(hDC,
(Start - Buffer->ViewOrigin.X) * GuiData->CharWidth, (Start - Buffer->ViewOrigin.X) * GuiData->CharWidth ,
(Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight, (Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
LineBuffer, LineBuffer,
RightChar - Start + 1); RightChar - Start + 1);
} }
@ -268,11 +263,11 @@ GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
TopLine <= CursorY && CursorY <= BottomLine) TopLine <= CursorY && CursorY <= BottomLine)
{ {
CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight); CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
From = ConioCoordToPointer(Buffer, Buffer->CursorPosition.X, Buffer->CursorPosition.Y) + 1; Attribute = ConioCoordToPointer(Buffer, Buffer->CursorPosition.X, Buffer->CursorPosition.Y)->Attributes;
if (*From != DEFAULT_SCREEN_ATTRIB) if (Attribute != DEFAULT_SCREEN_ATTRIB)
{ {
CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, *From)); CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, Attribute));
} }
else else
{ {

View file

@ -230,23 +230,25 @@ TuiSwapConsole(INT Next)
} }
static VOID FASTCALL static VOID FASTCALL
TuiCopyRect(char *Dest, PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* Region) TuiCopyRect(PCHAR Dest, PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
{ {
UINT SrcDelta, DestDelta; UINT SrcDelta, DestDelta;
LONG i; LONG i;
PBYTE Src, SrcEnd; PCHAR_INFO Src, SrcEnd;
Src = ConioCoordToPointer(Buff, Region->Left, Region->Top); Src = ConioCoordToPointer(Buff, Region->Left, Region->Top);
SrcDelta = Buff->ScreenBufferSize.X * 2; SrcDelta = Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
SrcEnd = Buff->Buffer + Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * 2; SrcEnd = Buff->Buffer + Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
DestDelta = ConioRectWidth(Region) * 2; DestDelta = ConioRectWidth(Region) * 2 /* 2 == sizeof(CHAR) + sizeof(BYTE) */;
for (i = Region->Top; i <= Region->Bottom; i++) for (i = Region->Top; i <= Region->Bottom; i++)
{ {
memcpy(Dest, Src, DestDelta); ConsoleUnicodeCharToAnsiChar(Buff->Header.Console, (PCHAR)Dest, &Src->Char.UnicodeChar);
*(PBYTE)(Dest + 1) = (BYTE)Src->Attributes;
Src += SrcDelta; Src += SrcDelta;
if (SrcEnd <= Src) if (SrcEnd <= Src)
{ {
Src -= Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * 2; Src -= Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
} }
Dest += DestDelta; Dest += DestDelta;
} }
@ -501,7 +503,7 @@ TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
ConsoleDraw->CursorX = Buff->CursorPosition.X; ConsoleDraw->CursorX = Buff->CursorPosition.X;
ConsoleDraw->CursorY = Buff->CursorPosition.Y; ConsoleDraw->CursorY = Buff->CursorPosition.Y;
TuiCopyRect((char*)(ConsoleDraw + 1), (PTEXTMODE_SCREEN_BUFFER)Buff, Region); TuiCopyRect((PCHAR)(ConsoleDraw + 1), (PTEXTMODE_SCREEN_BUFFER)Buff, Region);
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW, if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW,
NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL)) NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL))
@ -516,17 +518,31 @@ TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
static VOID WINAPI static VOID WINAPI
TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY, TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
UINT ScrolledLines, CHAR *Buffer, UINT Length) UINT ScrolledLines, PWCHAR Buffer, UINT Length)
{ {
DWORD BytesWritten;
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer; PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
PCHAR NewBuffer;
ULONG NewLength;
DWORD BytesWritten;
if (ActiveConsole->Console->ActiveBuffer != Buff) return; if (ActiveConsole->Console->ActiveBuffer != Buff) return;
if (!WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL)) NewLength = WideCharToMultiByte(Console->OutputCodePage, 0,
Buffer, Length,
NULL, 0, NULL, NULL);
NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewLength * sizeof(CHAR));
if (!NewBuffer) return;
WideCharToMultiByte(Console->OutputCodePage, 0,
Buffer, Length,
NewBuffer, NewLength, NULL, NULL);
if (!WriteFile(ConsoleDeviceHandle, NewBuffer, NewLength * sizeof(CHAR), &BytesWritten, NULL))
{ {
DPRINT1("Error writing to BlueScreen\n"); DPRINT1("Error writing to BlueScreen\n");
} }
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
} }
static BOOL WINAPI static BOOL WINAPI

View file

@ -126,12 +126,12 @@ typedef struct _TEXTMODE_BUFFER_INFO
typedef struct _TEXTMODE_SCREEN_BUFFER typedef struct _TEXTMODE_SCREEN_BUFFER
{ {
CONSOLE_SCREEN_BUFFER; /* Screen buffer base class - MUST BE IN FIRST PLACE */ CONSOLE_SCREEN_BUFFER; /* Screen buffer base class - MUST BE IN FIRST PLACE */
BYTE *Buffer; /* CHAR_INFO */ /* Pointer to screen buffer */ PCHAR_INFO Buffer; /* Pointer to UNICODE screen buffer (Buffer->Char.UnicodeChar only is valid, not Char.AsciiChar) */
WORD ScreenDefaultAttrib; /* Default screen char attribute */ WORD ScreenDefaultAttrib; /* Default screen char attribute */
WORD PopupDefaultAttrib; /* Default popup char attribute */ WORD PopupDefaultAttrib; /* Default popup char attribute */
} TEXTMODE_SCREEN_BUFFER, *PTEXTMODE_SCREEN_BUFFER; } TEXTMODE_SCREEN_BUFFER, *PTEXTMODE_SCREEN_BUFFER;
@ -189,7 +189,7 @@ typedef struct _FRONTEND_VTBL
SHORT CursorStartX, SHORT CursorStartX,
SHORT CursorStartY, SHORT CursorStartY,
UINT ScrolledLines, UINT ScrolledLines,
CHAR *Buffer, PWCHAR Buffer,
UINT Length); UINT Length);
BOOL (WINAPI *SetCursorInfo)(struct _CONSOLE* Console, BOOL (WINAPI *SetCursorInfo)(struct _CONSOLE* Console,
PCONSOLE_SCREEN_BUFFER ScreenBuffer); PCONSOLE_SCREEN_BUFFER ScreenBuffer);
@ -286,7 +286,6 @@ typedef struct _CONSOLE
BOOLEAN QuickEdit; BOOLEAN QuickEdit;
BOOLEAN InsertMode; BOOLEAN InsertMode;
UINT CodePage; UINT CodePage;
UINT OutputCodePage;
CONSOLE_SELECTION_INFO Selection; /* Contains information about the selection */ CONSOLE_SELECTION_INFO Selection; /* Contains information about the selection */
COORD dwSelectionCursor; /* Selection cursor position, most of the time different from Selection.dwSelectionAnchor */ COORD dwSelectionCursor; /* Selection cursor position, most of the time different from Selection.dwSelectionAnchor */
@ -297,6 +296,7 @@ typedef struct _CONSOLE
BYTE PauseFlags; BYTE PauseFlags;
HANDLE UnpauseEvent; HANDLE UnpauseEvent;
LIST_ENTRY WriteWaitQueue; /* List head for the queue of write wait blocks */ LIST_ENTRY WriteWaitQueue; /* List head for the queue of write wait blocks */
UINT OutputCodePage;
/**************************** Aliases and Histories ***************************/ /**************************** Aliases and Histories ***************************/
struct _ALIAS_HEADER *Aliases; struct _ALIAS_HEADER *Aliases;
@ -348,14 +348,20 @@ do { \
#define ConioRectWidth(Rect) \ #define ConioRectWidth(Rect) \
(((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1) (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
PBYTE ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y); #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
PCHAR_INFO ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y);
VOID FASTCALL ConioDrawConsole(PCONSOLE Console); VOID FASTCALL ConioDrawConsole(PCONSOLE Console);
NTSTATUS ConioResizeBuffer(PCONSOLE Console, NTSTATUS ConioResizeBuffer(PCONSOLE Console,
PTEXTMODE_SCREEN_BUFFER ScreenBuffer, PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
COORD Size); COORD Size);
NTSTATUS ConioWriteConsole(PCONSOLE Console, NTSTATUS ConioWriteConsole(PCONSOLE Console,
PTEXTMODE_SCREEN_BUFFER Buff, PTEXTMODE_SCREEN_BUFFER Buff,
CHAR *Buffer, PWCHAR Buffer,
DWORD Length, DWORD Length,
BOOL Attrib); BOOL Attrib);
DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console, DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console,

View file

@ -214,15 +214,11 @@ LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Inser
{ {
for (i = Pos; i < NewSize; i++) for (i = Pos; i < NewSize; i++)
{ {
CHAR AsciiChar; ConioWriteConsole(Console, ActiveBuffer, &Console->LineBuffer[i], 1, TRUE);
WideCharToMultiByte(Console->OutputCodePage, 0,
&Console->LineBuffer[i], 1,
&AsciiChar, 1, NULL, NULL);
ConioWriteConsole(Console, ActiveBuffer, &AsciiChar, 1, TRUE);
} }
for (; i < Console->LineSize; i++) for (; i < Console->LineSize; i++)
{ {
ConioWriteConsole(Console, ActiveBuffer, " ", 1, TRUE); ConioWriteConsole(Console, ActiveBuffer, L" ", 1, TRUE);
} }
Console->LinePos = i; Console->LinePos = i;
} }
@ -413,7 +409,7 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
{ {
if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
{ {
ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), "\r", 1, TRUE); ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\r", 1, TRUE);
} }
} }
@ -428,7 +424,7 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
{ {
if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
{ {
ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), "\n", 1, TRUE); ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\n", 1, TRUE);
} }
} }
} }

View file

@ -29,12 +29,6 @@
#define TAB_WIDTH 8 #define TAB_WIDTH 8
#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
@ -84,8 +78,9 @@ TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
NewBuffer->Vtbl = &TextVtbl; NewBuffer->Vtbl = &TextVtbl;
NewBuffer->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, NewBuffer->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
2 * TextModeInfo->ScreenBufferSize.X TextModeInfo->ScreenBufferSize.X *
* TextModeInfo->ScreenBufferSize.Y); TextModeInfo->ScreenBufferSize.Y *
sizeof(CHAR_INFO));
if (NewBuffer->Buffer == NULL) if (NewBuffer->Buffer == NULL)
{ {
CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
@ -137,23 +132,23 @@ TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
} }
PBYTE PCHAR_INFO
ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y) ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y)
{ {
return &Buff->Buffer[2 * (((Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y) * Buff->ScreenBufferSize.X + X)]; return &Buff->Buffer[((Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y) * Buff->ScreenBufferSize.X + X];
} }
static VOID FASTCALL static VOID FASTCALL
ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff) ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff)
{ {
PBYTE Ptr = ConioCoordToPointer(Buff, 0, Buff->CursorPosition.Y); PCHAR_INFO Ptr = ConioCoordToPointer(Buff, 0, Buff->CursorPosition.Y);
SHORT Pos; SHORT Pos;
for (Pos = 0; Pos < Buff->ScreenBufferSize.X; Pos++) for (Pos = 0; Pos < Buff->ScreenBufferSize.X; Pos++, Ptr++)
{ {
/* Fill the cell */ /* Fill the cell */
*Ptr++ = ' '; Ptr->Char.UnicodeChar = L' ';
*Ptr++ = (BYTE)Buff->ScreenDefaultAttrib; Ptr->Attributes = Buff->ScreenDefaultAttrib;
} }
} }
@ -252,9 +247,9 @@ ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
SMALL_RECT* SrcRegion, SMALL_RECT* SrcRegion,
SMALL_RECT* DstRegion, SMALL_RECT* DstRegion,
SMALL_RECT* ClipRegion, SMALL_RECT* ClipRegion,
WORD Fill) CHAR_INFO FillChar)
{ {
int Width = ConioRectWidth(SrcRegion); int Width = ConioRectWidth(SrcRegion);
int Height = ConioRectHeight(SrcRegion); int Height = ConioRectHeight(SrcRegion);
int SX, SY; int SX, SY;
int DX, DY; int DX, DY;
@ -273,8 +268,8 @@ ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
} }
for (i = 0; i < Height; i++) for (i = 0; i < Height; i++)
{ {
PWORD SRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, SY); PCHAR_INFO SRow = ConioCoordToPointer(ScreenBuffer, 0, SY);
PWORD DRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, DY); PCHAR_INFO DRow = ConioCoordToPointer(ScreenBuffer, 0, DY);
SX = SrcRegion->Left; SX = SrcRegion->Left;
DX = DstRegion->Left; DX = DstRegion->Left;
@ -288,14 +283,14 @@ ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
} }
for (j = 0; j < Width; j++) for (j = 0; j < Width; j++)
{ {
WORD Cell = SRow[SX]; CHAR_INFO Cell = SRow[SX];
if (SX >= ClipRegion->Left && SX <= ClipRegion->Right if (SX >= ClipRegion->Left && SX <= ClipRegion->Right &&
&& SY >= ClipRegion->Top && SY <= ClipRegion->Bottom) SY >= ClipRegion->Top && SY <= ClipRegion->Bottom)
{ {
SRow[SX] = Fill; SRow[SX] = FillChar;
} }
if (DX >= ClipRegion->Left && DX <= ClipRegion->Right if (DX >= ClipRegion->Left && DX <= ClipRegion->Right &&
&& DY >= ClipRegion->Top && DY <= ClipRegion->Bottom) DY >= ClipRegion->Top && DY <= ClipRegion->Bottom)
{ {
DRow[DX] = Cell; DRow[DX] = Cell;
} }
@ -322,11 +317,11 @@ ConioResizeBuffer(PCONSOLE Console,
PTEXTMODE_SCREEN_BUFFER ScreenBuffer, PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
COORD Size) COORD Size)
{ {
BYTE * Buffer; PCHAR_INFO Buffer;
DWORD Offset = 0; DWORD Offset = 0;
BYTE * OldPtr; PCHAR_INFO ptr;
USHORT CurrentY; USHORT CurrentY;
BYTE * OldBuffer; PCHAR_INFO OldBuffer;
#ifdef HAVE_WMEMSET #ifdef HAVE_WMEMSET
USHORT value = MAKEWORD(' ', ScreenBuffer->ScreenDefaultAttrib); USHORT value = MAKEWORD(' ', ScreenBuffer->ScreenDefaultAttrib);
#else #else
@ -355,7 +350,7 @@ ConioResizeBuffer(PCONSOLE Console,
return STATUS_NOT_SUPPORTED; // STATUS_SUCCESS return STATUS_NOT_SUPPORTED; // STATUS_SUCCESS
} }
Buffer = ConsoleAllocHeap(0, Size.X * Size.Y * 2); Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size.X * Size.Y * sizeof(CHAR_INFO));
if (!Buffer) return STATUS_NO_MEMORY; if (!Buffer) return STATUS_NO_MEMORY;
DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->ScreenBufferSize.X, ScreenBuffer->ScreenBufferSize.Y, Size.X, Size.Y); DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->ScreenBufferSize.X, ScreenBuffer->ScreenBufferSize.Y, Size.X, Size.Y);
@ -363,28 +358,30 @@ ConioResizeBuffer(PCONSOLE Console,
for (CurrentY = 0; CurrentY < ScreenBuffer->ScreenBufferSize.Y && CurrentY < Size.Y; CurrentY++) for (CurrentY = 0; CurrentY < ScreenBuffer->ScreenBufferSize.Y && CurrentY < Size.Y; CurrentY++)
{ {
OldPtr = ConioCoordToPointer(ScreenBuffer, 0, CurrentY); ptr = ConioCoordToPointer(ScreenBuffer, 0, CurrentY);
if (Size.X <= ScreenBuffer->ScreenBufferSize.X) if (Size.X <= ScreenBuffer->ScreenBufferSize.X)
{ {
/* reduce size */ /* Reduce size */
RtlCopyMemory(&Buffer[Offset], OldPtr, Size.X * 2); RtlCopyMemory(Buffer + Offset, ptr, Size.X * sizeof(CHAR_INFO));
Offset += (Size.X * 2); Offset += Size.X;
} }
else else
{ {
/* enlarge size */ /* Enlarge size */
RtlCopyMemory(&Buffer[Offset], OldPtr, ScreenBuffer->ScreenBufferSize.X * 2); RtlCopyMemory(Buffer + Offset, ptr, ScreenBuffer->ScreenBufferSize.X * sizeof(CHAR_INFO));
Offset += (ScreenBuffer->ScreenBufferSize.X * 2); Offset += ScreenBuffer->ScreenBufferSize.X;
diff = Size.X - ScreenBuffer->ScreenBufferSize.X; diff = Size.X - ScreenBuffer->ScreenBufferSize.X;
/* zero new part of it */ /* Zero new part of it */
#ifdef HAVE_WMEMSET #ifdef HAVE_WMEMSET
wmemset((PWCHAR)&Buffer[Offset], value, diff); wmemset((PWCHAR)&Buffer[Offset], value, diff);
#else #else
for (i = 0; i < diff; i++) for (i = 0; i < diff; i++)
{ {
Buffer[Offset++] = ' '; ptr = Buffer + Offset;
Buffer[Offset++] = (BYTE)ScreenBuffer->ScreenDefaultAttrib; ptr->Char.UnicodeChar = L' ';
ptr->Attributes = ScreenBuffer->ScreenDefaultAttrib;
++Offset;
} }
#endif #endif
} }
@ -398,8 +395,10 @@ ConioResizeBuffer(PCONSOLE Console,
#else #else
for (i = 0; i < diff; i++) for (i = 0; i < diff; i++)
{ {
Buffer[Offset++] = ' '; ptr = Buffer + Offset;
Buffer[Offset++] = (BYTE)ScreenBuffer->ScreenDefaultAttrib; ptr->Char.UnicodeChar = L' ';
ptr->Attributes = ScreenBuffer->ScreenDefaultAttrib;
++Offset;
} }
#endif #endif
} }
@ -461,12 +460,12 @@ ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* UpdateRect, UINT *Scroll
NTSTATUS NTSTATUS
ConioWriteConsole(PCONSOLE Console, ConioWriteConsole(PCONSOLE Console,
PTEXTMODE_SCREEN_BUFFER Buff, PTEXTMODE_SCREEN_BUFFER Buff,
CHAR *Buffer, PWCHAR Buffer,
DWORD Length, DWORD Length,
BOOL Attrib) BOOL Attrib)
{ {
UINT i; UINT i;
PBYTE Ptr; PCHAR_INFO Ptr;
SMALL_RECT UpdateRect; SMALL_RECT UpdateRect;
SHORT CursorStartX, CursorStartY; SHORT CursorStartX, CursorStartY;
UINT ScrolledLines; UINT ScrolledLines;
@ -488,7 +487,7 @@ ConioWriteConsole(PCONSOLE Console,
if (Buff->Mode & ENABLE_PROCESSED_OUTPUT) if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
{ {
/* --- CR --- */ /* --- CR --- */
if (Buffer[i] == '\r') if (Buffer[i] == L'\r')
{ {
Buff->CursorPosition.X = 0; Buff->CursorPosition.X = 0;
UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
@ -496,14 +495,14 @@ ConioWriteConsole(PCONSOLE Console,
continue; continue;
} }
/* --- LF --- */ /* --- LF --- */
else if (Buffer[i] == '\n') else if (Buffer[i] == L'\n')
{ {
Buff->CursorPosition.X = 0; Buff->CursorPosition.X = 0;
ConioNextLine(Buff, &UpdateRect, &ScrolledLines); ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
continue; continue;
} }
/* --- BS --- */ /* --- BS --- */
else if (Buffer[i] == '\b') else if (Buffer[i] == L'\b')
{ {
/* Only handle BS if we're not on the first pos of the first line */ /* Only handle BS if we're not on the first pos of the first line */
if (0 != Buff->CursorPosition.X || 0 != Buff->CursorPosition.Y) if (0 != Buff->CursorPosition.X || 0 != Buff->CursorPosition.Y)
@ -520,15 +519,15 @@ ConioWriteConsole(PCONSOLE Console,
Buff->CursorPosition.X--; Buff->CursorPosition.X--;
} }
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
Ptr[0] = ' '; Ptr->Char.UnicodeChar = L' ';
Ptr[1] = (BYTE)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);
} }
continue; continue;
} }
/* --- TAB --- */ /* --- TAB --- */
else if (Buffer[i] == '\t') else if (Buffer[i] == L'\t')
{ {
UINT EndX; UINT EndX;
@ -538,8 +537,9 @@ ConioWriteConsole(PCONSOLE Console,
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
while (Buff->CursorPosition.X < EndX) while (Buff->CursorPosition.X < EndX)
{ {
*Ptr++ = ' '; Ptr->Char.UnicodeChar = L' ';
*Ptr++ = (BYTE)Buff->ScreenDefaultAttrib; Ptr->Attributes = Buff->ScreenDefaultAttrib;
++Ptr;
Buff->CursorPosition.X++; Buff->CursorPosition.X++;
} }
UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1); UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1);
@ -558,7 +558,7 @@ ConioWriteConsole(PCONSOLE Console,
continue; continue;
} }
// /* --- BEL ---*/ // /* --- BEL ---*/
// else if (Buffer[i] == '\a') // else if (Buffer[i] == L'\a')
// { // {
// // FIXME: This MUST BE moved to the terminal emulator frontend!! // // FIXME: This MUST BE moved to the terminal emulator frontend!!
// DPRINT1("Bell\n"); // DPRINT1("Bell\n");
@ -566,14 +566,13 @@ ConioWriteConsole(PCONSOLE Console,
// continue; // continue;
// } // }
} }
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);
Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
Ptr[0] = Buffer[i]; Ptr->Char.UnicodeChar = Buffer[i];
if (Attrib) if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib;
{
Ptr[1] = (BYTE)Buff->ScreenDefaultAttrib;
}
Buff->CursorPosition.X++; Buff->CursorPosition.X++;
if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
{ {
@ -650,7 +649,7 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest; PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
PCONSOLE Console; PCONSOLE Console;
PTEXTMODE_SCREEN_BUFFER Buff; PTEXTMODE_SCREEN_BUFFER Buff;
PCHAR Buffer; PVOID Buffer;
DWORD Written = 0; DWORD Written = 0;
ULONG Length; ULONG Length;
@ -684,41 +683,44 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
{ {
if (WriteConsoleRequest->Unicode) if (WriteConsoleRequest->Unicode)
{ {
Length = WideCharToMultiByte(Console->OutputCodePage, 0, Buffer = WriteConsoleRequest->Buffer;
(PWCHAR)WriteConsoleRequest->Buffer, }
else
{
Length = MultiByteToWideChar(Console->OutputCodePage, 0,
(PCHAR)WriteConsoleRequest->Buffer,
WriteConsoleRequest->NrCharactersToWrite, WriteConsoleRequest->NrCharactersToWrite,
NULL, 0, NULL, NULL); NULL, 0);
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length); Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
if (Buffer) if (Buffer)
{ {
WideCharToMultiByte(Console->OutputCodePage, 0, MultiByteToWideChar(Console->OutputCodePage, 0,
(PWCHAR)WriteConsoleRequest->Buffer, (PCHAR)WriteConsoleRequest->Buffer,
WriteConsoleRequest->NrCharactersToWrite, WriteConsoleRequest->NrCharactersToWrite,
Buffer, Length, NULL, NULL); (PWCHAR)Buffer, Length);
} }
else else
{ {
Status = STATUS_NO_MEMORY; Status = STATUS_NO_MEMORY;
} }
} }
else
{
Buffer = (PCHAR)WriteConsoleRequest->Buffer;
}
if (Buffer) if (Buffer)
{ {
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Status = ConioWriteConsole(Console, Buff, Buffer, Status = ConioWriteConsole(Console,
WriteConsoleRequest->NrCharactersToWrite, TRUE); Buff,
Buffer,
WriteConsoleRequest->NrCharactersToWrite,
TRUE);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Written = WriteConsoleRequest->NrCharactersToWrite; Written = WriteConsoleRequest->NrCharactersToWrite;
} }
} }
if (WriteConsoleRequest->Unicode) if (!WriteConsoleRequest->Unicode)
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
} }
@ -746,7 +748,7 @@ CSR_API(SrvReadConsoleOutput)
SMALL_RECT ReadRegion; SMALL_RECT ReadRegion;
SMALL_RECT ScreenRect; SMALL_RECT ScreenRect;
DWORD i; DWORD i;
PBYTE Ptr; PCHAR_INFO Ptr;
LONG X, Y; LONG X, Y;
UINT CodePage; UINT CodePage;
@ -792,16 +794,16 @@ CSR_API(SrvReadConsoleOutput)
{ {
if (ReadOutputRequest->Unicode) if (ReadOutputRequest->Unicode)
{ {
// ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar); CurCharInfo->Char.UnicodeChar = Ptr->Char.UnicodeChar;
MultiByteToWideChar(CodePage, 0,
(PCHAR)Ptr++, 1,
&CurCharInfo->Char.UnicodeChar, 1);
} }
else else
{ {
CurCharInfo->Char.AsciiChar = *Ptr++; // ConsoleUnicodeCharToAnsiChar(ProcessData->Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar);
WideCharToMultiByte(CodePage, 0, &Ptr->Char.UnicodeChar, 1,
&CurCharInfo->Char.AsciiChar, 1, NULL, NULL);
} }
CurCharInfo->Attributes = *Ptr++; CurCharInfo->Attributes = Ptr->Attributes;
++Ptr;
++CurCharInfo; ++CurCharInfo;
} }
} }
@ -824,13 +826,13 @@ CSR_API(SrvWriteConsoleOutput)
PCONSOLE Console; PCONSOLE Console;
PTEXTMODE_SCREEN_BUFFER Buff; PTEXTMODE_SCREEN_BUFFER Buff;
SMALL_RECT ScreenBuffer; SMALL_RECT ScreenBuffer;
CHAR_INFO* CurCharInfo; PCHAR_INFO CurCharInfo;
SMALL_RECT WriteRegion; SMALL_RECT WriteRegion;
CHAR_INFO* CharInfo; PCHAR_INFO CharInfo;
COORD BufferCoord; COORD BufferCoord;
COORD BufferSize; COORD BufferSize;
NTSTATUS Status; NTSTATUS Status;
PBYTE Ptr; PCHAR_INFO Ptr;
DPRINT("SrvWriteConsoleOutput\n"); DPRINT("SrvWriteConsoleOutput\n");
@ -847,10 +849,10 @@ CSR_API(SrvWriteConsoleOutput)
} }
Status = ConSrvGetTextModeBuffer(ProcessData, Status = ConSrvGetTextModeBuffer(ProcessData,
WriteOutputRequest->OutputHandle, WriteOutputRequest->OutputHandle,
&Buff, &Buff,
GENERIC_WRITE, GENERIC_WRITE,
TRUE); TRUE);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console; Console = Buff->Header.Console;
@ -876,21 +878,21 @@ CSR_API(SrvWriteConsoleOutput)
for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++) for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++)
{ {
CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X; CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y); Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y);
for (X = WriteRegion.Left; X <= WriteRegion.Right; X++) for (X = WriteRegion.Left; X <= WriteRegion.Right; X++)
{ {
CHAR AsciiChar;
if (WriteOutputRequest->Unicode) if (WriteOutputRequest->Unicode)
{ {
ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar); Ptr->Char.UnicodeChar = CurCharInfo->Char.UnicodeChar;
} }
else else
{ {
AsciiChar = CurCharInfo->Char.AsciiChar; ConsoleAnsiCharToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char.AsciiChar);
} }
*Ptr++ = AsciiChar; Ptr->Attributes = CurCharInfo->Attributes;
*Ptr++ = (BYTE)CurCharInfo->Attributes; ++Ptr;
CurCharInfo++; ++CurCharInfo;
} }
} }
@ -942,7 +944,7 @@ CSR_API(SrvReadConsoleOutputString)
PVOID ReadBuffer; PVOID ReadBuffer;
DWORD i; DWORD i;
ULONG CodeSize; ULONG CodeSize;
BYTE Code; PCHAR_INFO Ptr;
DPRINT("SrvReadConsoleOutputString\n"); DPRINT("SrvReadConsoleOutputString\n");
@ -973,7 +975,11 @@ CSR_API(SrvReadConsoleOutputString)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadOutputCodeRequest->OutputHandle, &Buff, GENERIC_READ, TRUE); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
ReadOutputCodeRequest->OutputHandle,
&Buff,
GENERIC_READ,
TRUE);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console; Console = Buff->Header.Console;
@ -995,25 +1001,28 @@ CSR_API(SrvReadConsoleOutputString)
* TODO: Do NOT loop up to NumCodesToRead, but stop before * TODO: Do NOT loop up to NumCodesToRead, but stop before
* if we are going to overflow... * if we are going to overflow...
*/ */
for (i = 0; i < min(ReadOutputCodeRequest->NumCodesToRead, Buff->ScreenBufferSize.X * Buff->ScreenBufferSize.Y * 2); ++i) // Ptr = ConioCoordToPointer(Buff, Xpos, Ypos); // Doesn't work
for (i = 0; i < min(ReadOutputCodeRequest->NumCodesToRead, Buff->ScreenBufferSize.X * Buff->ScreenBufferSize.Y); ++i)
{ {
Code = Buff->Buffer[2 * (Xpos + Ypos * Buff->ScreenBufferSize.X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)]; // Ptr = ConioCoordToPointer(Buff, Xpos, Ypos); // Doesn't work either
Ptr = &Buff->Buffer[Xpos + Ypos * Buff->ScreenBufferSize.X];
switch (CodeType) switch (CodeType)
{ {
case CODE_UNICODE: case CODE_ASCII:
ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)ReadBuffer, (PCHAR)&Code); ConsoleUnicodeCharToAnsiChar(Console, (PCHAR)ReadBuffer, &Ptr->Char.UnicodeChar);
break; break;
case CODE_ASCII: case CODE_UNICODE:
*(PCHAR)ReadBuffer = (CHAR)Code; *(PWCHAR)ReadBuffer = Ptr->Char.UnicodeChar;
break; break;
case CODE_ATTRIBUTE: case CODE_ATTRIBUTE:
*(PWORD)ReadBuffer = (WORD)Code; *(PWORD)ReadBuffer = Ptr->Attributes;
break; break;
} }
ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize); ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
// ++Ptr;
Xpos++; Xpos++;
@ -1062,11 +1071,12 @@ CSR_API(SrvWriteConsoleOutputString)
PCONSOLE Console; PCONSOLE Console;
PTEXTMODE_SCREEN_BUFFER Buff; PTEXTMODE_SCREEN_BUFFER Buff;
USHORT CodeType; USHORT CodeType;
PBYTE Buffer; // PUCHAR PVOID ReadBuffer = NULL;
PCHAR String, tmpString = NULL; PWCHAR tmpString = NULL;
DWORD X, Y, Length; // , Written = 0; DWORD X, Y, Length; // , Written = 0;
ULONG CodeSize; ULONG CodeSize;
SMALL_RECT UpdateRect; SMALL_RECT UpdateRect;
PCHAR_INFO Ptr;
DPRINT("SrvWriteConsoleOutputString\n"); DPRINT("SrvWriteConsoleOutputString\n");
@ -1098,85 +1108,90 @@ CSR_API(SrvWriteConsoleOutputString)
} }
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
WriteOutputCodeRequest->OutputHandle, WriteOutputCodeRequest->OutputHandle,
&Buff, &Buff,
GENERIC_WRITE, GENERIC_WRITE,
TRUE); TRUE);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console; Console = Buff->Header.Console;
switch (CodeType) if (CodeType == CODE_ASCII)
{ {
case CODE_UNICODE: /* Convert the ASCII string into Unicode before writing it to the console */
Length = MultiByteToWideChar(Console->OutputCodePage, 0,
WriteOutputCodeRequest->pCode.AsciiChar,
WriteOutputCodeRequest->Length,
NULL, 0);
tmpString = ReadBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
if (ReadBuffer)
{ {
Length = WideCharToMultiByte(Console->OutputCodePage, 0, MultiByteToWideChar(Console->OutputCodePage, 0,
(PWCHAR)WriteOutputCodeRequest->pCode.UnicodeChar, WriteOutputCodeRequest->pCode.AsciiChar,
WriteOutputCodeRequest->Length, WriteOutputCodeRequest->Length,
NULL, 0, NULL, NULL); (PWCHAR)ReadBuffer, Length);
tmpString = String = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
if (String)
{
WideCharToMultiByte(Console->OutputCodePage, 0,
(PWCHAR)WriteOutputCodeRequest->pCode.UnicodeChar,
WriteOutputCodeRequest->Length,
String, Length, NULL, NULL);
}
else
{
Status = STATUS_NO_MEMORY;
}
break;
} }
else
case CODE_ASCII: {
String = (PCHAR)WriteOutputCodeRequest->pCode.AsciiChar; Status = STATUS_NO_MEMORY;
break; }
}
case CODE_ATTRIBUTE: else
default: {
// *(ReadBuffer++) = Code; /* For CODE_UNICODE or CODE_ATTRIBUTE, we are already OK */
String = (PCHAR)WriteOutputCodeRequest->pCode.Attribute; ReadBuffer = WriteOutputCodeRequest->pCode.pCode;
break;
} }
if (String && NT_SUCCESS(Status)) if (ReadBuffer == NULL || !NT_SUCCESS(Status)) goto Cleanup;
{
X = WriteOutputCodeRequest->Coord.X;
Y = (WriteOutputCodeRequest->Coord.Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y;
Length = WriteOutputCodeRequest->Length;
Buffer = &Buff->Buffer[2 * (Y * Buff->ScreenBufferSize.X + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
while (Length--) X = WriteOutputCodeRequest->Coord.X;
Y = (WriteOutputCodeRequest->Coord.Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y;
Length = WriteOutputCodeRequest->Length;
// Ptr = ConioCoordToPointer(Buff, X, Y); // Doesn't work
// Ptr = &Buff->Buffer[X + Y * Buff->ScreenBufferSize.X]; // May work
while (Length--)
{
// Ptr = ConioCoordToPointer(Buff, X, Y); // Doesn't work either
Ptr = &Buff->Buffer[X + Y * Buff->ScreenBufferSize.X];
switch (CodeType)
{ {
*Buffer = *String++; case CODE_ASCII:
// ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize); case CODE_UNICODE:
String = (PCHAR)((ULONG_PTR)String + CodeSize); Ptr->Char.UnicodeChar = *(PWCHAR)ReadBuffer;
// Written++; break;
Buffer += 2;
if (++X == Buff->ScreenBufferSize.X) case CODE_ATTRIBUTE:
Ptr->Attributes = *(PWORD)ReadBuffer;
break;
}
ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
// ++Ptr;
// Written++;
if (++X == Buff->ScreenBufferSize.X)
{
X = 0;
if (++Y == Buff->ScreenBufferSize.Y)
{ {
if (++Y == Buff->ScreenBufferSize.Y) Y = 0;
{
Y = 0;
Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
}
X = 0;
} }
} }
if ((PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
{
ConioComputeUpdateRect(Buff, &UpdateRect, &WriteOutputCodeRequest->Coord,
WriteOutputCodeRequest->Length);
ConioDrawRegion(Console, &UpdateRect);
}
// WriteOutputCodeRequest->EndCoord.X = X;
// WriteOutputCodeRequest->EndCoord.Y = (Y + Buff->ScreenBufferSize.Y - Buff->VirtualY) % Buff->ScreenBufferSize.Y;
} }
if ((PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
{
ConioComputeUpdateRect(Buff, &UpdateRect, &WriteOutputCodeRequest->Coord,
WriteOutputCodeRequest->Length);
ConioDrawRegion(Console, &UpdateRect);
}
// WriteOutputCodeRequest->EndCoord.X = X;
// WriteOutputCodeRequest->EndCoord.Y = (Y + Buff->ScreenBufferSize.Y - Buff->VirtualY) % Buff->ScreenBufferSize.Y;
Cleanup:
if (tmpString) if (tmpString)
RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString); RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString);
@ -1194,56 +1209,77 @@ CSR_API(SrvFillConsoleOutput)
PTEXTMODE_SCREEN_BUFFER Buff; PTEXTMODE_SCREEN_BUFFER Buff;
DWORD X, Y, Length; // , Written = 0; DWORD X, Y, Length; // , Written = 0;
USHORT CodeType; USHORT CodeType;
BYTE Code; PVOID Code = NULL;
PBYTE Buffer; PCHAR_INFO Ptr;
SMALL_RECT UpdateRect; SMALL_RECT UpdateRect;
DPRINT("SrvFillConsoleOutput\n"); DPRINT("SrvFillConsoleOutput\n");
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), FillOutputRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE); CodeType = FillOutputRequest->CodeType;
if ( (CodeType != CODE_ASCII ) &&
(CodeType != CODE_UNICODE ) &&
(CodeType != CODE_ATTRIBUTE) )
{
return STATUS_INVALID_PARAMETER;
}
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
FillOutputRequest->OutputHandle,
&Buff,
GENERIC_WRITE,
TRUE);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console; Console = Buff->Header.Console;
CodeType = FillOutputRequest->CodeType; switch (CodeType)
{
case CODE_ASCII:
/* On-place conversion from the ASCII char to the UNICODE char */
ConsoleAnsiCharToUnicodeChar(Console, &FillOutputRequest->Code.UnicodeChar, &FillOutputRequest->Code.AsciiChar);
/* Fall through */
case CODE_UNICODE:
Code = &FillOutputRequest->Code.UnicodeChar;
break;
case CODE_ATTRIBUTE:
Code = &FillOutputRequest->Code.Attribute;
break;
}
X = FillOutputRequest->Coord.X; X = FillOutputRequest->Coord.X;
Y = (FillOutputRequest->Coord.Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y; Y = (FillOutputRequest->Coord.Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y;
Length = FillOutputRequest->Length; Length = FillOutputRequest->Length;
Buffer = &Buff->Buffer[2 * (Y * Buff->ScreenBufferSize.X + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)]; // Ptr = ConioCoordToPointer(Buff, X, Y); // Doesn't work
// Ptr = &Buff->Buffer[X + Y * Buff->ScreenBufferSize.X]; // May work
switch (CodeType)
{
case CODE_ASCII:
Code = (BYTE)FillOutputRequest->Code.AsciiChar;
break;
case CODE_UNICODE:
ConsoleUnicodeCharToAnsiChar(Console, (PCHAR)&Code, &FillOutputRequest->Code.UnicodeChar);
break;
case CODE_ATTRIBUTE:
Code = (BYTE)FillOutputRequest->Code.Attribute;
break;
default:
ConSrvReleaseScreenBuffer(Buff, TRUE);
return STATUS_INVALID_PARAMETER;
}
while (Length--) while (Length--)
{ {
*Buffer = Code; // Ptr = ConioCoordToPointer(Buff, X, Y); // Doesn't work either
Buffer += 2; Ptr = &Buff->Buffer[X + Y * Buff->ScreenBufferSize.X];
switch (CodeType)
{
case CODE_ASCII:
case CODE_UNICODE:
Ptr->Char.UnicodeChar = *(PWCHAR)Code;
break;
case CODE_ATTRIBUTE:
Ptr->Attributes = *(PWORD)Code;
break;
}
// ++Ptr;
// Written++; // Written++;
if (++X == Buff->ScreenBufferSize.X) if (++X == Buff->ScreenBufferSize.X)
{ {
X = 0;
if (++Y == Buff->ScreenBufferSize.Y) if (++Y == Buff->ScreenBufferSize.Y)
{ {
Y = 0; Y = 0;
Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
} }
X = 0;
} }
} }
@ -1341,15 +1377,14 @@ CSR_API(SrvScrollConsoleScreenBuffer)
HANDLE OutputHandle; HANDLE OutputHandle;
BOOLEAN UseClipRectangle; BOOLEAN UseClipRectangle;
COORD DestinationOrigin; COORD DestinationOrigin;
CHAR_INFO Fill; CHAR_INFO FillChar;
CHAR FillChar;
DPRINT("SrvScrollConsoleScreenBuffer\n"); DPRINT("SrvScrollConsoleScreenBuffer\n");
OutputHandle = ScrollScreenBufferRequest->OutputHandle; OutputHandle = ScrollScreenBufferRequest->OutputHandle;
UseClipRectangle = ScrollScreenBufferRequest->UseClipRectangle; UseClipRectangle = ScrollScreenBufferRequest->UseClipRectangle;
DestinationOrigin = ScrollScreenBufferRequest->DestinationOrigin; DestinationOrigin = ScrollScreenBufferRequest->DestinationOrigin;
Fill = ScrollScreenBufferRequest->Fill; FillChar = ScrollScreenBufferRequest->Fill;
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), OutputHandle, &Buff, GENERIC_WRITE, TRUE); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), OutputHandle, &Buff, GENERIC_WRITE, TRUE);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
@ -1396,12 +1431,10 @@ CSR_API(SrvScrollConsoleScreenBuffer)
DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1, DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1,
DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1); DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1);
if (ScrollScreenBufferRequest->Unicode) if (!ScrollScreenBufferRequest->Unicode)
ConsoleUnicodeCharToAnsiChar(Console, &FillChar, &Fill.Char.UnicodeChar); ConsoleAnsiCharToUnicodeChar(Console, &FillChar.Char.UnicodeChar, &FillChar.Char.AsciiChar);
else
FillChar = Fill.Char.AsciiChar;
ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, Fill.Attributes << 8 | (BYTE)FillChar); ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, FillChar);
if ((PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer) if ((PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
{ {