Fix some compilation warnings with MSVC.
[KERNEL32-CONSRV]
- Implement console graphics screen buffers, as described in http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/ .
The idea is that the console server creates a memory shared section to be shared with the client console application (it increases performance). A mutex is used to "say" to the console server that he can repaint the screen. The function InvalidateConsoleDIBits is implemented too. The definition of the structure CONSOLE_GRAPHICS_BUFFER_INFO comes directly from the site.
- CreateConsoleScreenBuffer was modified to be able to create such buffers.
This is needed for a working NTVDM-like application.
[CONSRV]
- Rework the console buffer structures so that text-mode buffers and graphics-mode buffers can "inherit" from an "abstract" structure, CONSOLE_SCREEN_BUFFER. Add few helper functions for manipulating them.
- Reorganize the output code in "graphics.c" and "text.c" files to separate text-mode only code from graphics-mode only code, both in the console server and in the GUI front-end.
Other fixes:
- Fix mouse handling (left and right clicks when one goes away from the "Selection" mode); do not handle mouse signal when we reactivate the GUI front-end window by a click.
- Fix GetLargestConsoleWindowSize API in console server side. Now pressing Alt+F9 in Far Manager to "change" the "video" mode works correctly.
Finally:
- Start to implement a (fake, i.e. not using directly a VGA driver) console fullscreen mode. Currently Alt-Enter key presses call a stub which just alternates DPRINTing between "switch to fullscreen mode" and "switch to windowed mode".
Images here:
- Example of an application (a 16-bit emulator by Mysoft) which uses the console graphics screen-buffer functionality: http://img577.imageshack.us/img577/1693/mysoftemulatorargon.png
- A potpourri of console applications which use graphics screen-buffers: http://img571.imageshack.us/img571/6526/consoledelirium.png
Enjoy :)
svn path=/trunk/; revision=59099
pConInfo->ci.HistoryBufferSize = 50;
pConInfo->ci.NumberOfHistoryBuffers = 4;
pConInfo->ci.HistoryNoDup = FALSE;
- pConInfo->ci.FullScreen = FALSE;
pConInfo->ci.QuickEdit = FALSE;
pConInfo->ci.InsertMode = TRUE;
// pConInfo->ci.InputBufferSize;
GuiInfo->FontWeight = FW_DONTCARE;
GuiInfo->UseRasterFonts = TRUE;
+ GuiInfo->FullScreen = FALSE;
+ GuiInfo->ShowWindow = SW_SHOWNORMAL;
GuiInfo->AutoPosition = TRUE;
GuiInfo->WindowOrigin.x = 0;
GuiInfo->WindowOrigin.y = 0;
sheight = wheight;
}
}
- swidth = max(swidth, 1);
- sheight = max(sheight, 1);
+ swidth = min(max(swidth , 1), 0xFFFF);
+ sheight = min(max(sheight, 1), 0xFFFF);
if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
{
}
}
- pConInfo->ci.ScreenBufferSize.X = swidth;
- pConInfo->ci.ScreenBufferSize.Y = sheight;
- pConInfo->ci.ConsoleSize.X = wwidth;
- pConInfo->ci.ConsoleSize.Y = wheight;
+ pConInfo->ci.ScreenBufferSize.X = (SHORT)swidth;
+ pConInfo->ci.ScreenBufferSize.Y = (SHORT)sheight;
+ pConInfo->ci.ConsoleSize.X = (SHORT)wwidth;
+ pConInfo->ci.ConsoleSize.Y = (SHORT)wheight;
GuiInfo->WindowOrigin.x = left;
GuiInfo->WindowOrigin.y = top;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
DWORD sheight, swidth;
DWORD left, top;
- wwidth = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, NULL, FALSE);
+ wwidth = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, NULL, FALSE);
wheight = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, NULL, FALSE);
- swidth = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
+ swidth = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
sheight = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
- left = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, FALSE);
- top = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP, NULL, FALSE);
+ left = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, FALSE);
+ top = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP, NULL, FALSE);
- swidth = max(swidth, 1);
- sheight = max(sheight, 1);
+ swidth = min(max(swidth , 1), 0xFFFF);
+ sheight = min(max(sheight, 1), 0xFFFF);
/* Automatically adjust window size when screen buffer decreases */
if (wwidth > swidth)
wheight = sheight;
}
- pConInfo->ci.ScreenBufferSize.X = swidth;
- pConInfo->ci.ScreenBufferSize.Y = sheight;
- pConInfo->ci.ConsoleSize.X = wwidth;
- pConInfo->ci.ConsoleSize.Y = wheight;
+ pConInfo->ci.ScreenBufferSize.X = (SHORT)swidth;
+ pConInfo->ci.ScreenBufferSize.Y = (SHORT)sheight;
+ pConInfo->ci.ConsoleSize.X = (SHORT)wwidth;
+ pConInfo->ci.ConsoleSize.Y = (SHORT)wheight;
GuiInfo->WindowOrigin.x = left;
GuiInfo->WindowOrigin.y = top;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
LPARAM lParam)
{
PCONSOLE_PROPS pConInfo;
+ PGUI_CONSOLE_INFO GuiInfo;
LRESULT lResult;
HWND hDlgCtrl;
LPPSHNOTIFY lppsn;
case WM_COMMAND:
{
if (!pConInfo) break;
+ GuiInfo = pConInfo->TerminalInfo.TermInfo;
switch (LOWORD(wParam))
{
}
case IDC_RADIO_DISPLAY_WINDOW:
{
- pConInfo->ci.FullScreen = FALSE;
+ GuiInfo->FullScreen = FALSE;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
}
case IDC_RADIO_DISPLAY_FULL:
{
- pConInfo->ci.FullScreen = TRUE;
+ GuiInfo->FullScreen = TRUE;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
}
void
UpdateDialogElements(HWND hwndDlg, PCONSOLE_PROPS pConInfo)
{
+ PGUI_CONSOLE_INFO GuiInfo = pConInfo->TerminalInfo.TermInfo;
HWND hDlgCtrl;
TCHAR szBuffer[MAX_PATH];
SendMessage(hDlgCtrl, BM_SETCHECK, (LPARAM)BST_UNCHECKED, 0);
/* Update full/window screen */
- if (pConInfo->ci.FullScreen)
+ if (GuiInfo->FullScreen)
{
hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_DISPLAY_FULL);
SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
/*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
+ * @note See http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/
*/
-DWORD
+BOOL
WINAPI
-InvalidateConsoleDIBits(DWORD Unknown0,
- DWORD Unknown1)
+InvalidateConsoleDIBits(IN HANDLE hConsoleOutput,
+ IN PSMALL_RECT lpRect)
{
- DPRINT1("InvalidateConsoleDIBits(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return 0;
+ NTSTATUS Status;
+ CONSOLE_API_MESSAGE ApiMessage;
+ PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest = &ApiMessage.Data.InvalidateDIBitsRequest;
+
+ if (lpRect == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ InvalidateDIBitsRequest->OutputHandle = hConsoleOutput;
+ InvalidateDIBitsRequest->Region = *lpRect;
+
+ Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ NULL,
+ CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepInvalidateBitMapRect),
+ sizeof(CONSOLE_INVALIDATEDIBITS));
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ return FALSE;
+ }
+
+ return TRUE;
}
}
SetWindowInfoRequest->OutputHandle = hConsoleOutput;
- SetWindowInfoRequest->Absolute = bAbsolute;
- SetWindowInfoRequest->WindowRect = *lpConsoleWindow;
+ SetWindowInfoRequest->Absolute = bAbsolute;
+ SetWindowInfoRequest->WindowRect = *lpConsoleWindow;
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
{
NTSTATUS Status;
CONSOLE_API_MESSAGE ApiMessage;
+ PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &ApiMessage.Data.CreateScreenBufferRequest;
+ PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+ PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo = /*(PCONSOLE_GRAPHICS_BUFFER_INFO)*/lpScreenBufferData;
if ( (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE)) ||
(dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE)) ||
- (dwFlags != CONSOLE_TEXTMODE_BUFFER) )
+ (dwFlags != CONSOLE_TEXTMODE_BUFFER && dwFlags != CONSOLE_GRAPHICS_BUFFER) )
{
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
- ApiMessage.Data.CreateScreenBufferRequest.Access = dwDesiredAccess;
- ApiMessage.Data.CreateScreenBufferRequest.ShareMode = dwShareMode;
- ApiMessage.Data.CreateScreenBufferRequest.Inheritable =
+ CreateScreenBufferRequest->ScreenBufferType = dwFlags;
+ CreateScreenBufferRequest->Access = dwDesiredAccess;
+ CreateScreenBufferRequest->ShareMode = dwShareMode;
+ CreateScreenBufferRequest->Inheritable =
(lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE);
+ if (dwFlags == CONSOLE_GRAPHICS_BUFFER)
+ {
+ if (CreateScreenBufferRequest->Inheritable || GraphicsBufferInfo == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ CreateScreenBufferRequest->GraphicsBufferInfo = *GraphicsBufferInfo;
+
+ CaptureBuffer = CsrAllocateCaptureBuffer(1, GraphicsBufferInfo->dwBitMapInfoLength);
+ if (CaptureBuffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ (PVOID)GraphicsBufferInfo->lpBitMapInfo,
+ GraphicsBufferInfo->dwBitMapInfoLength,
+ (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo);
+ }
+
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
- NULL,
+ CaptureBuffer,
CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCreateScreenBuffer),
sizeof(CONSOLE_CREATESCREENBUFFER));
+
+ if (CaptureBuffer)
+ CsrFreeCaptureBuffer(CaptureBuffer);
+
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return INVALID_HANDLE_VALUE;
}
- return ApiMessage.Data.CreateScreenBufferRequest.OutputHandle;
+ if (dwFlags == CONSOLE_GRAPHICS_BUFFER && GraphicsBufferInfo)
+ {
+ GraphicsBufferInfo->hMutex = CreateScreenBufferRequest->GraphicsBufferInfo.hMutex ;
+ GraphicsBufferInfo->lpBitMap = CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap;
+ }
+
+ return CreateScreenBufferRequest->OutputHandle;
}
/* Initialize strings for conversion */
RtlInitUnicodeString(&BufferU, Buffer);
BufferA.Length = 0;
- BufferA.MaximumLength = nBufferLength;
+ BufferA.MaximumLength = (USHORT)nBufferLength;
BufferA.Buffer = lpBuffer;
/* Convert unicode name to ansi, copying as much chars as fit */
Size = MultiByteToWideChar(CP_ACP, 0, String, Size, RequestString->Buffer, Size * sizeof(WCHAR))
* sizeof(WCHAR);
}
- RequestString->Length = RequestString->MaximumLength = Size;
+ RequestString->Length = RequestString->MaximumLength = (USHORT)Size;
}
#define PROFILE_USER 0x10000000
#define PROFILE_KERNEL 0x20000000
#define PROFILE_SERVER 0x40000000
-#define CONSOLE_TEXTMODE_BUFFER 1
#define CREATE_NEW 1
#define CREATE_ALWAYS 2
#define OPEN_EXISTING 3
/*
* Console display modes
*/
+// These codes are answered by GetConsoleDisplayMode
+#define CONSOLE_WINDOWED 0
#define CONSOLE_FULLSCREEN 1
-#define CONSOLE_FULLSCREEN_HARDWARE 2
#if (_WIN32_WINNT >= 0x0600)
#define CONSOLE_OVERSTRIKE 1
#endif
+#define CONSOLE_FULLSCREEN_HARDWARE 2
+// These codes should be given to SetConsoleDisplayMode
#define CONSOLE_FULLSCREEN_MODE 1
#define CONSOLE_WINDOWED_MODE 2
#define COMMON_LVB_REVERSE_VIDEO 0x4000
#define COMMON_LVB_UNDERSCORE 0x8000
+/*
+ * Screen buffer types
+ */
+#define CONSOLE_TEXTMODE_BUFFER 1
+#define CONSOLE_GRAPHICS_BUFFER 2 /* Undocumented, see http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/ */
+
/*
* Control handler codes
*/
} Char;
WORD Attributes;
} CHAR_INFO,*PCHAR_INFO;
+
typedef struct _SMALL_RECT {
SHORT Left;
SHORT Top;
SHORT Right;
SHORT Bottom;
} SMALL_RECT,*PSMALL_RECT;
+
typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
} CONSOLE_CURSOR_INFO,*PCONSOLE_CURSOR_INFO;
+
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD;
+
typedef struct _CONSOLE_SELECTION_INFO {
DWORD dwFlags;
COORD dwSelectionAnchor;
SMALL_RECT srSelection;
} CONSOLE_SELECTION_INFO, *PCONSOLE_SELECTION_INFO;
+
typedef struct _CONSOLE_FONT_INFO {
DWORD nFont;
COORD dwFontSize;
} CONSOLE_FONT_INFO, *PCONSOLE_FONT_INFO;
+
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;
COORD dwCursorPosition;
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO,*PCONSOLE_SCREEN_BUFFER_INFO;
+
+/* Undocumented, see http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/ */
+#if defined(_WINGDI_) && !defined(NOGDI)
+typedef struct _CONSOLE_GRAPHICS_BUFFER_INFO {
+ DWORD dwBitMapInfoLength;
+ LPBITMAPINFO lpBitMapInfo;
+ DWORD dwUsage; // DIB_PAL_COLORS or DIB_RGB_COLORS
+ HANDLE hMutex;
+ PVOID lpBitMap;
+} CONSOLE_GRAPHICS_BUFFER_INFO, *PCONSOLE_GRAPHICS_BUFFER_INFO;
+#endif
+
typedef BOOL(CALLBACK *PHANDLER_ROUTINE)(_In_ DWORD);
+
typedef struct _KEY_EVENT_RECORD {
BOOL bKeyDown;
WORD wRepeatCount;
}
#ifdef __GNUC__
/* gcc's alignment is not what win32 expects */
- PACKED
+PACKED
#endif
KEY_EVENT_RECORD;
+
typedef struct _MOUSE_EVENT_RECORD {
COORD dwMousePosition;
DWORD dwButtonState;
DWORD dwControlKeyState;
DWORD dwEventFlags;
} MOUSE_EVENT_RECORD;
-typedef struct _WINDOW_BUFFER_SIZE_RECORD { COORD dwSize; } WINDOW_BUFFER_SIZE_RECORD;
-typedef struct _MENU_EVENT_RECORD { UINT dwCommandId; } MENU_EVENT_RECORD,*PMENU_EVENT_RECORD;
+
+typedef struct _WINDOW_BUFFER_SIZE_RECORD { COORD dwSize; } WINDOW_BUFFER_SIZE_RECORD;
+typedef struct _MENU_EVENT_RECORD { UINT dwCommandId; } MENU_EVENT_RECORD,*PMENU_EVENT_RECORD;
typedef struct _FOCUS_EVENT_RECORD { BOOL bSetFocus; } FOCUS_EVENT_RECORD;
+
typedef struct _INPUT_RECORD {
WORD EventType;
union {
UINT WINAPI GetConsoleOutputCP(VOID);
BOOL WINAPI GetConsoleScreenBufferInfo(_In_ HANDLE, _Out_ PCONSOLE_SCREEN_BUFFER_INFO);
+/* Undocumented, see http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/ */
+BOOL WINAPI InvalidateConsoleDIBits(_In_ HANDLE, _In_ PSMALL_RECT);
+
DWORD
WINAPI
GetConsoleTitleA(
COORD WINAPI GetLargestConsoleWindowSize(_In_ HANDLE);
BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE,PDWORD);
BOOL WINAPI GetNumberOfConsoleMouseButtons(_Out_ PDWORD);
+
BOOL WINAPI PeekConsoleInputA(HANDLE,PINPUT_RECORD,DWORD,PDWORD);
BOOL
ConsolepGetTitle,
ConsolepSetTitle,
ConsolepCreateScreenBuffer,
- // ConsolepInvalidateBitMapRect,
+ ConsolepInvalidateBitMapRect,
// ConsolepVDMOperation,
// ConsolepSetCursor,
// ConsolepShowCursor,
DWORD ConsoleMode;
} CONSOLE_GETSETCONSOLEMODE, *PCONSOLE_GETSETCONSOLEMODE;
-
-#define CONSOLE_WINDOWED 0 /* Internal console hardware state */
typedef struct
{
// HANDLE OutputHandle;
typedef struct
{
- HANDLE OutputHandle; /* Handle to newly created screen buffer */
+ HANDLE OutputHandle; /* Handle to newly created screen buffer */
+ DWORD ScreenBufferType; /* Type of the screen buffer: CONSOLE_TEXTMODE_BUFFER or CONSOLE_GRAPHICS_BUFFER */
+ /*
+ * If we are creating a graphics screen buffer,
+ * this structure holds the initialization information.
+ */
+ CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo;
DWORD Access;
DWORD ShareMode;
- BOOL Inheritable;
+ BOOL Inheritable;
} CONSOLE_CREATESCREENBUFFER, *PCONSOLE_CREATESCREENBUFFER;
typedef struct
HANDLE OutputHandle; /* Handle to screen buffer to switch to */
} CONSOLE_SETACTIVESCREENBUFFER, *PCONSOLE_SETACTIVESCREENBUFFER;
+typedef struct
+{
+ HANDLE OutputHandle;
+ SMALL_RECT Region;
+} CONSOLE_INVALIDATEDIBITS, *PCONSOLE_INVALIDATEDIBITS;
+
typedef struct
{
DWORD Length;
CONSOLE_GETSETHWSTATE HardwareStateRequest;
/* Console window */
+ CONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest;
CONSOLE_GETSETCONSOLETITLE TitleRequest;
CONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest;
CONSOLE_SETWINDOWINFO SetWindowInfoRequest;
alias.c
coninput.c
conoutput.c
+ graphics.c
+ text.c
console.c
handle.c
init.c
lineinput.c
settings.c
- consrv.rc
frontends/gui/guiterm.c
frontends/gui/guisettings.c
+ frontends/gui/graphics.c
+ frontends/gui/text.c
frontends/tui/tuiterm.c
${CMAKE_CURRENT_BINARY_DIR}/consrv.def)
-add_library(consrv SHARED ${SOURCE})
+add_library(consrv SHARED
+ ${SOURCE}
+ consrv.rc)
+
+#
+# Explicitely enable MS extensions to be able to use unnamed (anonymous) nested structs.
+#
+# FIXME: http://www.cmake.org/Bug/view.php?id=12998
+if(MSVC)
+ ## NOTE: No need to specify it as we use MSVC :)
+ #add_target_compile_flags(consrv "/Ze")
+ ##set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "/Ze")
+else()
+ add_target_compile_flags(consrv "-fms-extensions")
+ #set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-fms-extensions")
+endif()
target_link_libraries(consrv win32ksys ${PSEH_LIB} uuid) # win32ksys because of NtUser...()
CSR_API(SrvGetConsoleNumberOfInputEvents);
/* conoutput.c */
+CSR_API(SrvInvalidateBitMapRect);
CSR_API(SrvReadConsoleOutput);
CSR_API(SrvWriteConsole);
CSR_API(SrvWriteConsoleOutput);
if (Console->InputBuffer.Mode & ENABLE_LINE_INPUT &&
(vk == VK_PAUSE || (vk == 'S' &&
(cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &&
- !(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))))
+ !(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))))
{
ConioPause(Console, PAUSED_FROM_KEYBOARD);
return STATUS_SUCCESS;
/* add event to the queue */
ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput));
- if (ConInRec == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ if (ConInRec == NULL) return STATUS_INSUFFICIENT_RESOURCES;
+
ConInRec->InputEvent = *InputEvent;
InsertTailList(&Console->InputBuffer.InputEvents, &ConInRec->ListEntry);
* or translated keys may be involved. */
static UINT LastVirtualKey = 0;
DWORD ShiftState;
- UINT RepeatCount;
WCHAR UnicodeChar;
UINT VirtualKeyCode;
UINT VirtualScanCode;
return;
}
- RepeatCount = 1;
- VirtualScanCode = (msg->lParam >> 16) & 0xff;
+ VirtualScanCode = HIWORD(msg->lParam) & 0xFF;
Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
Chars,
2,
0,
- 0);
+ NULL);
UnicodeChar = (1 == RetChars ? Chars[0] : 0);
}
er.EventType = KEY_EVENT;
er.Event.KeyEvent.bKeyDown = Down;
- er.Event.KeyEvent.wRepeatCount = RepeatCount;
- er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
- er.Event.KeyEvent.dwControlKeyState = ShiftState;
+ er.Event.KeyEvent.wRepeatCount = 1;
er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
+ er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
+ er.Event.KeyEvent.dwControlKeyState = ShiftState;
if (ConioProcessKeyCallback(Console,
msg,
/* Macros used to call functions in the FRONTEND_VTBL virtual table */
+#define ConioCleanupConsole(Console) \
+ (Console)->TermIFace.Vtbl->CleanupConsole(Console)
#define ConioDrawRegion(Console, Region) \
(Console)->TermIFace.Vtbl->DrawRegion((Console), (Region))
#define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \
(Console)->TermIFace.Vtbl->SetCursorInfo((Console), (Buff))
#define ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY) \
(Console)->TermIFace.Vtbl->SetScreenInfo((Console), (Buff), (OldCursorX), (OldCursorY))
-#define ConioUpdateScreenInfo(Console, Buff) \
- (Console)->TermIFace.Vtbl->UpdateScreenInfo((Console), (Buff))
-#define ConioIsBufferResizeSupported(Console) \
- (Console)->TermIFace.Vtbl->IsBufferResizeSupported(Console)
-#define ConioChangeTitle(Console) \
- (Console)->TermIFace.Vtbl->ChangeTitle(Console)
-#define ConioCleanupConsole(Console) \
- (Console)->TermIFace.Vtbl->CleanupConsole(Console)
-#define ConioChangeIcon(Console, hWindowIcon) \
- (Console)->TermIFace.Vtbl->ChangeIcon((Console), (hWindowIcon))
-// #define ConioResizeBuffer(Console, Buff, Size) (Console)->TermIFace.Vtbl->ResizeBuffer((Console), (Buff), (Size))
#define ConioResizeTerminal(Console) \
(Console)->TermIFace.Vtbl->ResizeTerminal(Console)
#define ConioProcessKeyCallback(Console, Msg, KeyStateMenu, ShiftState, VirtualKeyCode, Down) \
(Console)->TermIFace.Vtbl->ProcessKeyCallback((Console), (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down))
-#define ConioGetLargestConsoleWindowSize(Console, pSize) \
- (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize((Console), (pSize))
-#define ConioGetConsoleWindowHandle(Console) \
- (Console)->TermIFace.Vtbl->GetConsoleWindowHandle(Console)
#define ConioRefreshInternalInfo(Console) \
(Console)->TermIFace.Vtbl->RefreshInternalInfo(Console)
+#define ConioChangeTitle(Console) \
+ (Console)->TermIFace.Vtbl->ChangeTitle(Console)
+#define ConioChangeIcon(Console, hWindowIcon) \
+ (Console)->TermIFace.Vtbl->ChangeIcon((Console), (hWindowIcon))
+#define ConioGetConsoleWindowHandle(Console) \
+ (Console)->TermIFace.Vtbl->GetConsoleWindowHandle(Console)
+#define ConioGetLargestConsoleWindowSize(Console, pSize) \
+ (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize((Console), (pSize))
+#define ConioGetDisplayMode(Console) \
+ (Console)->TermIFace.Vtbl->GetDisplayMode(Console)
+#define ConioSetDisplayMode(Console, NewMode) \
+ (Console)->TermIFace.Vtbl->SetDisplayMode((Console), (NewMode))
+
/* EOF */
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/conoutput.c
- * PURPOSE: Console Output functions
+ * PURPOSE: General Console Output Functions
* PROGRAMMERS: Jeffrey Morlan
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#define NDEBUG
#include <debug.h>
-/*
-// Define wmemset(...)
-#include <wchar.h>
-#define HAVE_WMEMSET
-*/
-
-
-/* GLOBALS ********************************************************************/
-
-#define TAB_WIDTH 8
-
-#define ConioInitRect(Rect, top, left, bottom, right) \
-do { \
- ((Rect)->Top) = top; \
- ((Rect)->Left) = left; \
- ((Rect)->Bottom) = bottom; \
- ((Rect)->Right) = right; \
-} while (0)
-
-#define ConioIsRectEmpty(Rect) \
- (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
-
-#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 **********************************************************/
-PBYTE FASTCALL
-ConioCoordToPointer(PCONSOLE_SCREEN_BUFFER Buff, ULONG X, ULONG Y)
-{
- return &Buff->Buffer[2 * (((Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y) * Buff->ScreenBufferSize.X + X)];
-}
-
-static VOID FASTCALL
-ClearLineBuffer(PCONSOLE_SCREEN_BUFFER Buff)
-{
- PBYTE Ptr = ConioCoordToPointer(Buff, 0, Buff->CursorPosition.Y);
- SHORT Pos;
-
- for (Pos = 0; Pos < Buff->ScreenBufferSize.X; Pos++)
- {
- /* Fill the cell */
- *Ptr++ = ' ';
- *Ptr++ = (BYTE)Buff->ScreenDefaultAttrib;
- }
-}
-
-NTSTATUS FASTCALL
-ConSrvCreateScreenBuffer(IN OUT PCONSOLE Console,
- OUT PCONSOLE_SCREEN_BUFFER* Buffer,
- IN COORD ScreenBufferSize,
- IN USHORT ScreenAttrib,
- IN USHORT PopupAttrib,
- IN ULONG DisplayMode,
- IN BOOLEAN IsCursorVisible,
- IN ULONG CursorSize)
+NTSTATUS
+TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN PTEXTMODE_BUFFER_INFO TextModeInfo);
+NTSTATUS
+GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN PGRAPHICS_BUFFER_INFO GraphicsInfo);
+
+VOID
+TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
+VOID
+GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
+
+
+NTSTATUS
+CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN SIZE_T Size)
{
- if (Console == NULL || Buffer == NULL)
+ if (Buffer == NULL || Console == NULL)
return STATUS_INVALID_PARAMETER;
- *Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(CONSOLE_SCREEN_BUFFER));
- if (NULL == *Buffer)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ *Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, max(sizeof(CONSOLE_SCREEN_BUFFER), Size));
+ if (*Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES;
+ /* Initialize the header with the default type */
ConSrvInitObject(&(*Buffer)->Header, SCREEN_BUFFER, Console);
- (*Buffer)->ScreenBufferSize = ScreenBufferSize;
-
- (*Buffer)->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, (*Buffer)->ScreenBufferSize.X * (*Buffer)->ScreenBufferSize.Y * 2);
- if (NULL == (*Buffer)->Buffer)
- {
- ConsoleFreeHeap(*Buffer);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- (*Buffer)->ShowX = 0;
- (*Buffer)->ShowY = 0;
- (*Buffer)->VirtualY = 0;
-
- (*Buffer)->CursorBlinkOn = (*Buffer)->ForceCursorOff = FALSE;
- (*Buffer)->CursorInfo.bVisible = (IsCursorVisible && (CursorSize != 0));
- (*Buffer)->CursorInfo.dwSize = min(max(CursorSize, 0), 100);
-
- (*Buffer)->ScreenDefaultAttrib = ScreenAttrib;
- (*Buffer)->PopupDefaultAttrib = PopupAttrib;
- /* initialize buffer to be empty with default attributes */
- for ((*Buffer)->CursorPosition.Y = 0 ; (*Buffer)->CursorPosition.Y < (*Buffer)->ScreenBufferSize.Y; (*Buffer)->CursorPosition.Y++)
- {
- ClearLineBuffer(*Buffer);
- }
- (*Buffer)->CursorPosition.X = 0;
- (*Buffer)->CursorPosition.Y = 0;
-
- (*Buffer)->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
- (*Buffer)->DisplayMode = DisplayMode;
-
- InsertHeadList(&Console->BufferList, &(*Buffer)->ListEntry);
+ (*Buffer)->Vtbl = NULL;
return STATUS_SUCCESS;
}
-static VOID FASTCALL
-ConioNextLine(PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* UpdateRect, UINT *ScrolledLines)
+VOID
+CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
{
- /* If we hit bottom, slide the viewable screen */
- if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y)
- {
- Buff->CursorPosition.Y--;
- if (++Buff->VirtualY == Buff->ScreenBufferSize.Y)
- {
- Buff->VirtualY = 0;
- }
- (*ScrolledLines)++;
- ClearLineBuffer(Buff);
- if (UpdateRect->Top != 0)
- {
- UpdateRect->Top--;
- }
- }
- UpdateRect->Left = 0;
- UpdateRect->Right = Buff->ScreenBufferSize.X - 1;
- UpdateRect->Bottom = Buff->CursorPosition.Y;
+ if (Buffer->Header.Type == TEXTMODE_BUFFER)
+ TEXTMODE_BUFFER_Destroy(Buffer);
+ else if (Buffer->Header.Type == GRAPHICS_BUFFER)
+ GRAPHICS_BUFFER_Destroy(Buffer);
+ else if (Buffer->Header.Type == SCREEN_BUFFER)
+ ConsoleFreeHeap(Buffer);
+ // else
+ // do_nothing;
}
NTSTATUS FASTCALL
-ConioWriteConsole(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff,
- CHAR *Buffer, DWORD Length, BOOL Attrib)
-{
- UINT i;
- PBYTE Ptr;
- SMALL_RECT UpdateRect;
- SHORT CursorStartX, CursorStartY;
- UINT ScrolledLines;
-
- CursorStartX = Buff->CursorPosition.X;
- CursorStartY = Buff->CursorPosition.Y;
- UpdateRect.Left = Buff->ScreenBufferSize.X;
- UpdateRect.Top = Buff->CursorPosition.Y;
- UpdateRect.Right = -1;
- UpdateRect.Bottom = Buff->CursorPosition.Y;
- ScrolledLines = 0;
-
- for (i = 0; i < Length; i++)
- {
- /*
- * If we are in processed mode, interpret special characters and
- * display them correctly. Otherwise, just put them into the buffer.
- */
- if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
- {
- /* --- CR --- */
- if (Buffer[i] == '\r')
- {
- Buff->CursorPosition.X = 0;
- UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
- UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
- continue;
- }
- /* --- LF --- */
- else if (Buffer[i] == '\n')
- {
- Buff->CursorPosition.X = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- continue;
- }
- /* --- BS --- */
- else if (Buffer[i] == '\b')
- {
- /* 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)
- {
- /* slide virtual position up */
- Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1;
- Buff->CursorPosition.Y--;
- UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y);
- }
- else
- {
- Buff->CursorPosition.X--;
- }
- Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
- Ptr[0] = ' ';
- Ptr[1] = (BYTE)Buff->ScreenDefaultAttrib;
- UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
- UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
- }
- continue;
- }
- /* --- TAB --- */
- else if (Buffer[i] == '\t')
- {
- UINT EndX;
-
- UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
- EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1);
- EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X);
- Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
- while (Buff->CursorPosition.X < EndX)
- {
- *Ptr++ = ' ';
- *Ptr++ = (BYTE)Buff->ScreenDefaultAttrib;
- Buff->CursorPosition.X++;
- }
- UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1);
- if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
- {
- if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
- {
- Buff->CursorPosition.X = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- }
- else
- {
- Buff->CursorPosition.X--;
- }
- }
- continue;
- }
- // /* --- BEL ---*/
- // else if (Buffer[i] == '\a')
- // {
- // // FIXME: This MUST BE moved to the terminal emulator frontend!!
- // DPRINT1("Bell\n");
- // // SendNotifyMessage(Console->hWindow, PM_CONSOLE_BEEP, 0, 0);
- // continue;
- // }
- }
- 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[0] = Buffer[i];
- if (Attrib)
- {
- Ptr[1] = (BYTE)Buff->ScreenDefaultAttrib;
- }
- Buff->CursorPosition.X++;
- if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
- {
- if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
- {
- Buff->CursorPosition.X = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- }
- else
- {
- Buff->CursorPosition.X = CursorStartX;
- }
- }
- }
-
- if (!ConioIsRectEmpty(&UpdateRect) && Buff == Console->ActiveBuffer)
- {
- ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
- ScrolledLines, Buffer, Length);
- }
-
- return STATUS_SUCCESS;
-}
-
-__inline BOOLEAN ConioGetIntersection(
- SMALL_RECT* Intersection,
- SMALL_RECT* Rect1,
- SMALL_RECT* Rect2)
+ConSrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN ULONG BufferType,
+ IN PVOID ScreenBufferInfo)
{
- if (ConioIsRectEmpty(Rect1) ||
- (ConioIsRectEmpty(Rect2)) ||
- (Rect1->Top > Rect2->Bottom) ||
- (Rect1->Left > Rect2->Right) ||
- (Rect1->Bottom < Rect2->Top) ||
- (Rect1->Right < Rect2->Left))
- {
- /* The rectangles do not intersect */
- ConioInitRect(Intersection, 0, -1, 0, -1);
- return FALSE;
- }
-
- ConioInitRect(Intersection,
- max(Rect1->Top, Rect2->Top),
- max(Rect1->Left, Rect2->Left),
- min(Rect1->Bottom, Rect2->Bottom),
- min(Rect1->Right, Rect2->Right));
-
- return TRUE;
-}
-
-__inline BOOLEAN ConioGetUnion(
- SMALL_RECT* Union,
- SMALL_RECT* Rect1,
- SMALL_RECT* Rect2)
-{
- if (ConioIsRectEmpty(Rect1))
- {
- if (ConioIsRectEmpty(Rect2))
- {
- ConioInitRect(Union, 0, -1, 0, -1);
- return FALSE;
- }
- else
- {
- *Union = *Rect2;
- }
- }
- else if (ConioIsRectEmpty(Rect2))
- {
- *Union = *Rect1;
- }
- else
- {
- ConioInitRect(Union,
- min(Rect1->Top, Rect2->Top),
- min(Rect1->Left, Rect2->Left),
- max(Rect1->Bottom, Rect2->Bottom),
- max(Rect1->Right, Rect2->Right));
- }
-
- return TRUE;
-}
+ NTSTATUS Status = STATUS_SUCCESS;
-/*
- * Move from one rectangle to another. We must be careful about the order that
- * this is done, to avoid overwriting parts of the source before they are moved.
- */
-static VOID FASTCALL
-ConioMoveRegion(PCONSOLE_SCREEN_BUFFER ScreenBuffer,
- SMALL_RECT* SrcRegion,
- SMALL_RECT* DstRegion,
- SMALL_RECT* ClipRegion,
- WORD Fill)
-{
- int Width = ConioRectWidth(SrcRegion);
- int Height = ConioRectHeight(SrcRegion);
- int SX, SY;
- int DX, DY;
- int XDelta, YDelta;
- int i, j;
-
- SY = SrcRegion->Top;
- DY = DstRegion->Top;
- YDelta = 1;
- if (SY < DY)
+ if ( Console == NULL || Buffer == NULL ||
+ (BufferType != CONSOLE_TEXTMODE_BUFFER && BufferType != CONSOLE_GRAPHICS_BUFFER) )
{
- /* Moving down: work from bottom up */
- SY = SrcRegion->Bottom;
- DY = DstRegion->Bottom;
- YDelta = -1;
- }
- for (i = 0; i < Height; i++)
- {
- PWORD SRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, SY);
- PWORD DRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, DY);
-
- SX = SrcRegion->Left;
- DX = DstRegion->Left;
- XDelta = 1;
- if (SX < DX)
- {
- /* Moving right: work from right to left */
- SX = SrcRegion->Right;
- DX = DstRegion->Right;
- XDelta = -1;
- }
- for (j = 0; j < Width; j++)
- {
- WORD Cell = SRow[SX];
- if (SX >= ClipRegion->Left && SX <= ClipRegion->Right
- && SY >= ClipRegion->Top && SY <= ClipRegion->Bottom)
- {
- SRow[SX] = Fill;
- }
- if (DX >= ClipRegion->Left && DX <= ClipRegion->Right
- && DY >= ClipRegion->Top && DY <= ClipRegion->Bottom)
- {
- DRow[DX] = Cell;
- }
- SX += XDelta;
- DX += XDelta;
- }
- SY += YDelta;
- DY += YDelta;
- }
-}
-
-NTSTATUS FASTCALL
-ConioResizeBuffer(PCONSOLE Console,
- PCONSOLE_SCREEN_BUFFER ScreenBuffer,
- COORD Size)
-{
- BYTE * Buffer;
- DWORD Offset = 0;
- BYTE * OldPtr;
- USHORT CurrentY;
- BYTE * OldBuffer;
-#ifdef HAVE_WMEMSET
- USHORT value = MAKEWORD(' ', ScreenBuffer->ScreenDefaultAttrib);
-#else
- DWORD i;
-#endif
- DWORD diff;
-
- /* Buffer size is not allowed to be smaller than window size */
- if (Size.X < Console->ConsoleSize.X || Size.Y < Console->ConsoleSize.Y)
return STATUS_INVALID_PARAMETER;
-
- if (Size.X == ScreenBuffer->ScreenBufferSize.X && Size.Y == ScreenBuffer->ScreenBufferSize.Y)
- {
- // FIXME: Trigger a buffer resize event ??
- return STATUS_SUCCESS;
}
- if (!ConioIsBufferResizeSupported(Console)) return STATUS_NOT_SUPPORTED;
-
- Buffer = ConsoleAllocHeap(0, Size.X * Size.Y * 2);
- if (!Buffer) return STATUS_NO_MEMORY;
-
- DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->ScreenBufferSize.X, ScreenBuffer->ScreenBufferSize.Y, Size.X, Size.Y);
- OldBuffer = ScreenBuffer->Buffer;
-
- for (CurrentY = 0; CurrentY < ScreenBuffer->ScreenBufferSize.Y && CurrentY < Size.Y; CurrentY++)
+ if (BufferType == CONSOLE_TEXTMODE_BUFFER)
{
- OldPtr = ConioCoordToPointer(ScreenBuffer, 0, CurrentY);
- if (Size.X <= ScreenBuffer->ScreenBufferSize.X)
- {
- /* reduce size */
- RtlCopyMemory(&Buffer[Offset], OldPtr, Size.X * 2);
- Offset += (Size.X * 2);
- }
- else
- {
- /* enlarge size */
- RtlCopyMemory(&Buffer[Offset], OldPtr, ScreenBuffer->ScreenBufferSize.X * 2);
- Offset += (ScreenBuffer->ScreenBufferSize.X * 2);
-
- diff = Size.X - ScreenBuffer->ScreenBufferSize.X;
- /* zero new part of it */
-#ifdef HAVE_WMEMSET
- wmemset((PWCHAR)&Buffer[Offset], value, diff);
-#else
- for (i = 0; i < diff; i++)
- {
- Buffer[Offset++] = ' ';
- Buffer[Offset++] = (BYTE)ScreenBuffer->ScreenDefaultAttrib;
- }
-#endif
- }
+ Status = TEXTMODE_BUFFER_Initialize(Buffer,
+ Console,
+ (PTEXTMODE_BUFFER_INFO)ScreenBufferInfo);
}
-
- if (Size.Y > ScreenBuffer->ScreenBufferSize.Y)
+ else if (BufferType == CONSOLE_GRAPHICS_BUFFER)
{
- diff = Size.X * (Size.Y - ScreenBuffer->ScreenBufferSize.Y);
-#ifdef HAVE_WMEMSET
- wmemset((PWCHAR)&Buffer[Offset], value, diff);
-#else
- for (i = 0; i < diff; i++)
- {
- Buffer[Offset++] = ' ';
- Buffer[Offset++] = (BYTE)ScreenBuffer->ScreenDefaultAttrib;
- }
-#endif
+ Status = GRAPHICS_BUFFER_Initialize(Buffer,
+ Console,
+ (PGRAPHICS_BUFFER_INFO)ScreenBufferInfo);
}
-
- (void)InterlockedExchangePointer((PVOID volatile*)&ScreenBuffer->Buffer, Buffer);
- ConsoleFreeHeap(OldBuffer);
- ScreenBuffer->ScreenBufferSize = Size;
- ScreenBuffer->VirtualY = 0;
-
- /* Ensure cursor and window are within buffer */
- if (ScreenBuffer->CursorPosition.X >= Size.X)
- ScreenBuffer->CursorPosition.X = Size.X - 1;
- if (ScreenBuffer->CursorPosition.Y >= Size.Y)
- ScreenBuffer->CursorPosition.Y = Size.Y - 1;
- if (ScreenBuffer->ShowX > Size.X - Console->ConsoleSize.X)
- ScreenBuffer->ShowX = Size.X - Console->ConsoleSize.X;
- if (ScreenBuffer->ShowY > Size.Y - Console->ConsoleSize.Y)
- ScreenBuffer->ShowY = Size.Y - Console->ConsoleSize.Y;
-
- /*
- * Trigger a buffer resize event
- */
- if (Console->InputBuffer.Mode & ENABLE_WINDOW_INPUT)
+ else
{
- INPUT_RECORD er;
-
- er.EventType = WINDOW_BUFFER_SIZE_EVENT;
- er.Event.WindowBufferSizeEvent.dwSize = ScreenBuffer->ScreenBufferSize;
-
- ConioProcessInputEvent(Console, &er);
+ /* Never ever go there!! */
+ ASSERT(FALSE);
}
- /* TODO: Should update scrollbar, but can't use anything that
- * calls SendMessage or it could cause deadlock --> Use PostMessage */
- // TODO: Tell the terminal to resize its scrollbars.
+ /* Insert the newly created screen buffer into the list, if succeeded */
+ if (NT_SUCCESS(Status)) InsertHeadList(&Console->BufferList, &(*Buffer)->ListEntry);
- return STATUS_SUCCESS;
+ return Status;
}
VOID WINAPI
ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
{
PCONSOLE Console = Buffer->Header.Console;
+ PCONSOLE_SCREEN_BUFFER NewBuffer;
RemoveEntryList(&Buffer->ListEntry);
if (Buffer == Console->ActiveBuffer)
{
- /* Deleted active buffer; switch to most recently created */
+ /* Delete active buffer; switch to most recently created */
Console->ActiveBuffer = NULL;
if (!IsListEmpty(&Console->BufferList))
{
- Console->ActiveBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CONSOLE_SCREEN_BUFFER, ListEntry);
- ConioDrawConsole(Console);
+ NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink,
+ CONSOLE_SCREEN_BUFFER,
+ ListEntry);
+ ConioSetActiveScreenBuffer(NewBuffer);
}
}
- ConsoleFreeHeap(Buffer->Buffer);
- ConsoleFreeHeap(Buffer);
+ CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
}
VOID FASTCALL
ConioDrawConsole(PCONSOLE Console)
{
SMALL_RECT Region;
+ PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
- ConioInitRect(&Region, 0, 0, Console->ConsoleSize.Y - 1, Console->ConsoleSize.X - 1);
- ConioDrawRegion(Console, &Region);
-}
-
-static VOID FASTCALL
-ConioComputeUpdateRect(PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* UpdateRect, PCOORD Start, UINT Length)
-{
- if (Buff->ScreenBufferSize.X <= Start->X + Length)
+ if (ActiveBuffer)
{
- UpdateRect->Left = 0;
+ ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1);
+ ConioDrawRegion(Console, &Region);
}
- else
- {
- UpdateRect->Left = Start->X;
- }
- if (Buff->ScreenBufferSize.X <= Start->X + Length)
- {
- UpdateRect->Right = Buff->ScreenBufferSize.X - 1;
- }
- else
- {
- UpdateRect->Right = Start->X + Length - 1;
- }
- UpdateRect->Top = Start->Y;
- UpdateRect->Bottom = Start->Y + (Start->X + Length - 1) / Buff->ScreenBufferSize.X;
- if (Buff->ScreenBufferSize.Y <= UpdateRect->Bottom)
- {
- UpdateRect->Bottom = Buff->ScreenBufferSize.Y - 1;
- }
-}
-
-DWORD FASTCALL
-ConioEffectiveCursorSize(PCONSOLE Console, DWORD Scale)
-{
- DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100;
- /* If line input in progress, perhaps adjust for insert toggle */
- if (Console->LineBuffer && !Console->LineComplete && Console->LineInsertToggle)
- return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2);
- return Size;
-}
-
-static NTSTATUS
-DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
- IN PCSR_THREAD ClientThread,
- IN BOOL CreateWaitBlock OPTIONAL);
-
-// Wait function CSR_WAIT_FUNCTION
-static BOOLEAN
-WriteConsoleThread(IN PLIST_ENTRY WaitList,
- IN PCSR_THREAD WaitThread,
- IN PCSR_API_MESSAGE WaitApiMessage,
- IN PVOID WaitContext,
- IN PVOID WaitArgument1,
- IN PVOID WaitArgument2,
- IN ULONG WaitFlags)
-{
- NTSTATUS Status;
-
- DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
-
- /*
- * If we are notified of the process termination via a call
- * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
- * CsrDestroyThread, just return.
- */
- if (WaitFlags & CsrProcessTerminating)
- {
- Status = STATUS_THREAD_IS_TERMINATING;
- goto Quit;
- }
-
- Status = DoWriteConsole(WaitApiMessage,
- WaitThread,
- FALSE);
-
-Quit:
- if (Status != STATUS_PENDING)
- {
- WaitApiMessage->Status = Status;
- }
-
- return (Status == STATUS_PENDING ? FALSE : TRUE);
}
-static NTSTATUS
-DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
- IN PCSR_THREAD ClientThread,
- IN BOOL CreateWaitBlock OPTIONAL)
+VOID FASTCALL
+ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
{
- NTSTATUS Status = STATUS_SUCCESS;
- PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
- PCHAR Buffer;
- DWORD Written = 0;
- ULONG Length;
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->OutputHandle, &Buff, GENERIC_WRITE, FALSE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
- if (Console->PauseFlags && Console->UnpauseEvent != NULL)
- {
- if (CreateWaitBlock)
- {
- if (!CsrCreateWait(&Console->WriteWaitQueue,
- WriteConsoleThread,
- ClientThread,
- ApiMessage,
- NULL,
- NULL))
- {
- /* Fail */
- ConSrvReleaseScreenBuffer(Buff, FALSE);
- return STATUS_NO_MEMORY;
- }
- }
-
- /* Wait until we un-pause the console */
- Status = STATUS_PENDING;
- }
- else
- {
- if (WriteConsoleRequest->Unicode)
- {
- Length = WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- NULL, 0, NULL, NULL);
- Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
- if (Buffer)
- {
- WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- Buffer, Length, NULL, NULL);
- }
- else
- {
- Status = STATUS_NO_MEMORY;
- }
- }
- else
- {
- Buffer = (PCHAR)WriteConsoleRequest->Buffer;
- }
-
- if (Buffer)
- {
- if (NT_SUCCESS(Status))
- {
- Status = ConioWriteConsole(Console, Buff, Buffer,
- WriteConsoleRequest->NrCharactersToWrite, TRUE);
- if (NT_SUCCESS(Status))
- {
- Written = WriteConsoleRequest->NrCharactersToWrite;
- }
- }
- if (WriteConsoleRequest->Unicode)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
- }
- }
-
- WriteConsoleRequest->NrCharactersWritten = Written;
- }
-
- ConSrvReleaseScreenBuffer(Buff, FALSE);
- return Status;
+ PCONSOLE Console = Buffer->Header.Console;
+ Console->ActiveBuffer = Buffer;
+ ConioResizeTerminal(Console);
+ // ConioDrawConsole(Console);
}
/* PUBLIC SERVER APIS *********************************************************/
-CSR_API(SrvReadConsoleOutput)
-{
- PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest;
- PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
- PCHAR_INFO CharInfo;
- PCHAR_INFO CurCharInfo;
- PCONSOLE_SCREEN_BUFFER Buff;
- SHORT SizeX, SizeY;
- NTSTATUS Status;
- COORD BufferSize;
- COORD BufferCoord;
- SMALL_RECT ReadRegion;
- SMALL_RECT ScreenRect;
- DWORD i;
- PBYTE Ptr;
- LONG X, Y;
- UINT CodePage;
-
- DPRINT("SrvReadConsoleOutput\n");
-
- CharInfo = ReadOutputRequest->CharInfo;
- ReadRegion = ReadOutputRequest->ReadRegion;
- BufferSize = ReadOutputRequest->BufferSize;
- BufferCoord = ReadOutputRequest->BufferCoord;
-
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&ReadOutputRequest->CharInfo,
- BufferSize.X * BufferSize.Y,
- sizeof(CHAR_INFO)))
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = ConSrvGetScreenBuffer(ProcessData, ReadOutputRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- /* FIXME: Is this correct? */
- CodePage = ProcessData->Console->OutputCodePage;
-
- SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
- SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion));
- ReadRegion.Bottom = ReadRegion.Top + SizeY;
- ReadRegion.Right = ReadRegion.Left + SizeX;
-
- ConioInitRect(&ScreenRect, 0, 0, Buff->ScreenBufferSize.Y, Buff->ScreenBufferSize.X);
- if (!ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
- {
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
- }
-
- for (i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y)
- {
- CurCharInfo = CharInfo + (i * BufferSize.X);
-
- Ptr = ConioCoordToPointer(Buff, ReadRegion.Left, Y);
- for (X = ReadRegion.Left; X < ReadRegion.Right; ++X)
- {
- if (ReadOutputRequest->Unicode)
- {
- // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
- MultiByteToWideChar(CodePage, 0,
- (PCHAR)Ptr++, 1,
- &CurCharInfo->Char.UnicodeChar, 1);
- }
- else
- {
- CurCharInfo->Char.AsciiChar = *Ptr++;
- }
- CurCharInfo->Attributes = *Ptr++;
- ++CurCharInfo;
- }
- }
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
-
- ReadOutputRequest->ReadRegion.Right = ReadRegion.Left + SizeX - 1;
- ReadOutputRequest->ReadRegion.Bottom = ReadRegion.Top + SizeY - 1;
- ReadOutputRequest->ReadRegion.Left = ReadRegion.Left;
- ReadOutputRequest->ReadRegion.Top = ReadRegion.Top;
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvWriteConsole)
+CSR_API(SrvInvalidateBitMapRect)
{
NTSTATUS Status;
- PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
-
- DPRINT("SrvWriteConsole\n");
-
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID)&WriteConsoleRequest->Buffer,
- WriteConsoleRequest->BufferSize,
- sizeof(BYTE)))
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = DoWriteConsole(ApiMessage,
- CsrGetClientThread(),
- TRUE);
-
- if (Status == STATUS_PENDING)
- *ReplyCode = CsrReplyPending;
-
- return Status;
-}
-
-CSR_API(SrvWriteConsoleOutput)
-{
- PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest;
- PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
- SHORT i, X, Y, SizeX, SizeY;
+ PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.InvalidateDIBitsRequest;
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER Buff;
- SMALL_RECT ScreenBuffer;
- CHAR_INFO* CurCharInfo;
- SMALL_RECT WriteRegion;
- CHAR_INFO* CharInfo;
- COORD BufferCoord;
- COORD BufferSize;
- NTSTATUS Status;
- PBYTE Ptr;
-
- DPRINT("SrvWriteConsoleOutput\n");
- BufferSize = WriteOutputRequest->BufferSize;
- BufferCoord = WriteOutputRequest->BufferCoord;
- CharInfo = WriteOutputRequest->CharInfo;
-
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&WriteOutputRequest->CharInfo,
- BufferSize.X * BufferSize.Y,
- sizeof(CHAR_INFO)))
- {
- return STATUS_INVALID_PARAMETER;
- }
+ DPRINT("SrvInvalidateBitMapRect\n");
- Status = ConSrvGetScreenBuffer(ProcessData,
- WriteOutputRequest->OutputHandle,
- &Buff,
- GENERIC_WRITE,
- TRUE);
+ Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), InvalidateDIBitsRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console;
- WriteRegion = WriteOutputRequest->WriteRegion;
-
- SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion));
- SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion));
- WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
- WriteRegion.Right = WriteRegion.Left + SizeX - 1;
-
- /* Make sure WriteRegion is inside the screen buffer */
- ConioInitRect(&ScreenBuffer, 0, 0, Buff->ScreenBufferSize.Y - 1, Buff->ScreenBufferSize.X - 1);
- if (!ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
- {
- ConSrvReleaseScreenBuffer(Buff, TRUE);
-
- /* It is okay to have a WriteRegion completely outside the screen buffer.
- No data is written then. */
- return STATUS_SUCCESS;
- }
-
- for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++)
- {
- CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
- Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y);
- for (X = WriteRegion.Left; X <= WriteRegion.Right; X++)
- {
- CHAR AsciiChar;
- if (WriteOutputRequest->Unicode)
- {
- ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
- }
- else
- {
- AsciiChar = CurCharInfo->Char.AsciiChar;
- }
- *Ptr++ = AsciiChar;
- *Ptr++ = (BYTE)CurCharInfo->Attributes;
- CurCharInfo++;
- }
- }
-
- ConioDrawRegion(Console, &WriteRegion);
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
-
- WriteOutputRequest->WriteRegion.Right = WriteRegion.Left + SizeX - 1;
- WriteOutputRequest->WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
- WriteOutputRequest->WriteRegion.Left = WriteRegion.Left;
- WriteOutputRequest->WriteRegion.Top = WriteRegion.Top;
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvReadConsoleOutputString)
-{
- NTSTATUS Status;
- PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputCodeRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
- USHORT CodeType;
- SHORT Xpos, Ypos;
- PVOID ReadBuffer;
- DWORD i;
- ULONG CodeSize;
- BYTE Code;
-
- DPRINT("SrvReadConsoleOutputString\n");
-
- CodeType = ReadOutputCodeRequest->CodeType;
- switch (CodeType)
- {
- case CODE_ASCII:
- CodeSize = sizeof(CHAR);
- break;
-
- case CODE_UNICODE:
- CodeSize = sizeof(WCHAR);
- break;
-
- case CODE_ATTRIBUTE:
- CodeSize = sizeof(WORD);
- break;
-
- default:
- return STATUS_INVALID_PARAMETER;
- }
-
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&ReadOutputCodeRequest->pCode.pCode,
- ReadOutputCodeRequest->NumCodesToRead,
- CodeSize))
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadOutputCodeRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- ReadBuffer = ReadOutputCodeRequest->pCode.pCode;
- Xpos = ReadOutputCodeRequest->ReadCoord.X;
- Ypos = (ReadOutputCodeRequest->ReadCoord.Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y;
-
- /*
- * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
- *
- * If the number of attributes (resp. characters) to be read from extends
- * beyond the end of the specified screen buffer row, attributes (resp.
- * characters) are read from the next row. If the number of attributes
- * (resp. characters) to be read from extends beyond the end of the console
- * screen buffer, attributes (resp. characters) up to the end of the console
- * screen buffer are read.
- *
- * TODO: Do NOT loop up to NumCodesToRead, but stop before
- * if we are going to overflow...
- */
- for (i = 0; i < min(ReadOutputCodeRequest->NumCodesToRead, Buff->ScreenBufferSize.X * Buff->ScreenBufferSize.Y * 2); ++i)
- {
- Code = Buff->Buffer[2 * (Xpos + Ypos * Buff->ScreenBufferSize.X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
-
- switch (CodeType)
- {
- case CODE_UNICODE:
- ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)ReadBuffer, (PCHAR)&Code);
- break;
-
- case CODE_ASCII:
- *(PCHAR)ReadBuffer = (CHAR)Code;
- break;
-
- case CODE_ATTRIBUTE:
- *(PWORD)ReadBuffer = (WORD)Code;
- break;
- }
- ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
-
- Xpos++;
-
- if (Xpos == Buff->ScreenBufferSize.X)
- {
- Xpos = 0;
- Ypos++;
-
- if (Ypos == Buff->ScreenBufferSize.Y)
- {
- Ypos = 0;
- }
- }
- }
-
- // switch (CodeType)
- // {
- // case CODE_UNICODE:
- // *(PWCHAR)ReadBuffer = 0;
- // break;
-
- // case CODE_ASCII:
- // *(PCHAR)ReadBuffer = 0;
- // break;
-
- // case CODE_ATTRIBUTE:
- // *(PWORD)ReadBuffer = 0;
- // break;
- // }
-
- ReadOutputCodeRequest->EndCoord.X = Xpos;
- ReadOutputCodeRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->ScreenBufferSize.Y) % Buff->ScreenBufferSize.Y;
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
-
- ReadOutputCodeRequest->CodesRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadOutputCodeRequest->pCode.pCode) / CodeSize;
- // <= ReadOutputCodeRequest->NumCodesToRead
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvWriteConsoleOutputString)
-{
- NTSTATUS Status;
- PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputCodeRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
- USHORT CodeType;
- PBYTE Buffer; // PUCHAR
- PCHAR String, tmpString = NULL;
- DWORD X, Y, Length; // , Written = 0;
- ULONG CodeSize;
- SMALL_RECT UpdateRect;
-
- DPRINT("SrvWriteConsoleOutputString\n");
-
- CodeType = WriteOutputCodeRequest->CodeType;
- switch (CodeType)
- {
- case CODE_ASCII:
- CodeSize = sizeof(CHAR);
- break;
-
- case CODE_UNICODE:
- CodeSize = sizeof(WCHAR);
- break;
-
- case CODE_ATTRIBUTE:
- CodeSize = sizeof(WORD);
- break;
-
- default:
- return STATUS_INVALID_PARAMETER;
- }
-
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&WriteOutputCodeRequest->pCode.pCode,
- WriteOutputCodeRequest->Length,
- CodeSize))
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- WriteOutputCodeRequest->OutputHandle,
- &Buff,
- GENERIC_WRITE,
- TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- switch (CodeType)
- {
- case CODE_UNICODE:
- {
- Length = WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteOutputCodeRequest->pCode.UnicodeChar,
- WriteOutputCodeRequest->Length,
- NULL, 0, NULL, NULL);
- 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;
- }
-
- case CODE_ASCII:
- String = (PCHAR)WriteOutputCodeRequest->pCode.AsciiChar;
- break;
-
- case CODE_ATTRIBUTE:
- default:
- // *(ReadBuffer++) = Code;
- String = (PCHAR)WriteOutputCodeRequest->pCode.Attribute;
- break;
- }
-
- if (String && NT_SUCCESS(Status))
- {
- 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--)
- {
- *Buffer = *String++;
- // ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
- String = (PCHAR)((ULONG_PTR)String + CodeSize);
- // Written++;
- Buffer += 2;
- if (++X == Buff->ScreenBufferSize.X)
- {
- if (++Y == Buff->ScreenBufferSize.Y)
- {
- Y = 0;
- Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
- }
- X = 0;
- }
- }
-
- if (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 (tmpString)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString);
- }
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
-
- // WriteOutputCodeRequest->NrCharactersWritten = Written;
- return Status;
-}
-
-CSR_API(SrvFillConsoleOutput)
-{
- NTSTATUS Status;
- PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
- DWORD X, Y, Length; // , Written = 0;
- USHORT CodeType;
- BYTE Code;
- PBYTE Buffer;
- SMALL_RECT UpdateRect;
-
- DPRINT("SrvFillConsoleOutput\n");
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), FillOutputRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- CodeType = FillOutputRequest->CodeType;
-
- X = FillOutputRequest->Coord.X;
- Y = (FillOutputRequest->Coord.Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y;
- Length = FillOutputRequest->Length;
- Buffer = &Buff->Buffer[2 * (Y * Buff->ScreenBufferSize.X + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
-
- 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--)
- {
- *Buffer = Code;
- Buffer += 2;
- // Written++;
- if (++X == Buff->ScreenBufferSize.X)
- {
- if (++Y == Buff->ScreenBufferSize.Y)
- {
- Y = 0;
- Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
- }
- X = 0;
- }
- }
-
+ /* If the output buffer is the current one, redraw the correct portion of the screen */
if (Buff == Console->ActiveBuffer)
- {
- ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputRequest->Coord,
- FillOutputRequest->Length);
- ConioDrawRegion(Console, &UpdateRect);
- }
+ ConioDrawRegion(Console, &InvalidateDIBitsRequest->Region);
ConSrvReleaseScreenBuffer(Buff, TRUE);
-/*
- Length = FillOutputRequest->Length;
- FillOutputRequest->NrCharactersWritten = Length;
-*/
return STATUS_SUCCESS;
}
DPRINT("SrvGetConsoleCursorInfo\n");
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
if (!NT_SUCCESS(Status)) return Status;
CursorInfoRequest->Info.bVisible = Buff->CursorInfo.bVisible;
- CursorInfoRequest->Info.dwSize = Buff->CursorInfo.dwSize;
+ CursorInfoRequest->Info.dwSize = Buff->CursorInfo.dwSize;
ConSrvReleaseScreenBuffer(Buff, TRUE);
return STATUS_SUCCESS;
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER Buff;
DWORD Size;
- BOOL Visible;
+ BOOL Visible, Success = TRUE;
DPRINT("SrvSetConsoleCursorInfo\n");
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console;
- Size = CursorInfoRequest->Info.dwSize;
+ Size = CursorInfoRequest->Info.dwSize;
Visible = CursorInfoRequest->Info.bVisible;
- if (Size < 1)
- {
- Size = 1;
- }
- if (100 < Size)
- {
- Size = 100;
- }
+ if (Size < 1) Size = 1;
+ if (100 < Size) Size = 100;
- if ( (Size != Buff->CursorInfo.dwSize) ||
- (Visible && ! Buff->CursorInfo.bVisible) ||
- (! Visible && Buff->CursorInfo.bVisible) )
+ if ( (Size != Buff->CursorInfo.dwSize) ||
+ (Visible && !Buff->CursorInfo.bVisible) ||
+ (!Visible && Buff->CursorInfo.bVisible) )
{
- Buff->CursorInfo.dwSize = Size;
+ Buff->CursorInfo.dwSize = Size;
Buff->CursorInfo.bVisible = Visible;
- if (!ConioSetCursorInfo(Console, Buff))
- {
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_UNSUCCESSFUL;
- }
+ Success = ConioSetCursorInfo(Console, Buff);
}
ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
+ return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}
CSR_API(SrvSetConsoleCursorPosition)
{
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorPositionRequest;
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER Buff;
DPRINT("SrvSetConsoleCursorPosition\n");
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetCursorPositionRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetCursorPositionRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console;
if ( NewCursorX < 0 || NewCursorX >= Buff->ScreenBufferSize.X ||
NewCursorY < 0 || NewCursorY >= Buff->ScreenBufferSize.Y )
{
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_INVALID_PARAMETER;
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quit;
}
OldCursorX = Buff->CursorPosition.X;
OldCursorY = Buff->CursorPosition.Y;
{
if (!ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
{
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_UNSUCCESSFUL;
- }
- }
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleTextAttribute)
-{
- NTSTATUS Status;
- PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetTextAttribRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
-
- DPRINT("SrvSetConsoleTextAttribute\n");
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetTextAttribRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- Buff->ScreenDefaultAttrib = SetTextAttribRequest->Attrib;
- if (Buff == Console->ActiveBuffer)
- {
- if (!ConioUpdateScreenInfo(Console, Buff))
- {
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_UNSUCCESSFUL;
+ Status = STATUS_UNSUCCESSFUL;
+ goto Quit;
}
}
+Quit:
ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
+ return Status;
}
CSR_API(SrvCreateConsoleScreenBuffer)
{
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER Buff;
- COORD ScreenBufferSize = {80, 25};
- USHORT ScreenAttrib = DEFAULT_SCREEN_ATTRIB;
- USHORT PopupAttrib = DEFAULT_POPUP_ATTRIB;
- ULONG DisplayMode = CONSOLE_WINDOWED_MODE;
- BOOLEAN IsCursorVisible = TRUE;
- ULONG CursorSize = CSR_DEFAULT_CURSOR_SIZE;
+ PVOID ScreenBufferInfo = NULL;
+ TEXTMODE_BUFFER_INFO TextModeInfo = {{80, 25},
+ DEFAULT_SCREEN_ATTRIB,
+ DEFAULT_POPUP_ATTRIB ,
+ TRUE,
+ CSR_DEFAULT_CURSOR_SIZE};
+ GRAPHICS_BUFFER_INFO GraphicsInfo;
+ GraphicsInfo.Info = CreateScreenBufferRequest->GraphicsBufferInfo; // HACK for MSVC
DPRINT("SrvCreateConsoleScreenBuffer\n");
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- /*
- if (Console->ActiveBuffer)
+ if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_TEXTMODE_BUFFER)
{
- ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
- if (ScreenBufferSize.X == 0) ScreenBufferSize.X = 80;
- if (ScreenBufferSize.Y == 0) ScreenBufferSize.Y = 25;
+ ScreenBufferInfo = &TextModeInfo;
- ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib;
- PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib;
+ /*
+ if (Console->ActiveBuffer)
+ {
+ TextModeInfo.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
+ if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 80;
+ if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 25;
- IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
- CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
- }
- */
+ TextModeInfo.ScreenAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.ScreenDefaultAttrib;
+ TextModeInfo.PopupAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.PopupDefaultAttrib;
- // This is Windows' behaviour
- {
- ScreenBufferSize = Console->ConsoleSize; // Use the current console size
- if (ScreenBufferSize.X == 0) ScreenBufferSize.X = 1;
- if (ScreenBufferSize.Y == 0) ScreenBufferSize.Y = 1;
+ TextModeInfo.IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
+ TextModeInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
+ }
+ */
- if (Console->ActiveBuffer)
+ /*
+ * This is Windows' behaviour
+ */
+
+ /* Use the current console size. Regularize it if needed. */
+ TextModeInfo.ScreenBufferSize = Console->ConsoleSize;
+ if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 1;
+ if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 1;
+
+ /* If we have an active screen buffer, use its attributes as the new ones */
+ if (Console->ActiveBuffer && GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
{
- ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib;
- PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib;
- DisplayMode = Console->ActiveBuffer->DisplayMode;
+ PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)Console->ActiveBuffer;
+
+ TextModeInfo.ScreenAttrib = Buffer->ScreenDefaultAttrib;
+ TextModeInfo.PopupAttrib = Buffer->PopupDefaultAttrib;
- IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
- CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
+ TextModeInfo.IsCursorVisible = Buffer->CursorInfo.bVisible;
+ TextModeInfo.CursorSize = Buffer->CursorInfo.dwSize;
}
}
-
- Status = ConSrvCreateScreenBuffer(Console,
- &Buff,
- ScreenBufferSize,
- ScreenAttrib,
- PopupAttrib,
- DisplayMode,
- IsCursorVisible,
- CursorSize);
- if (NT_SUCCESS(Status))
+ else if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER)
{
- RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+ /* Get infos from the graphics buffer information structure */
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo,
+ 1,
+ CreateScreenBufferRequest->GraphicsBufferInfo.dwBitMapInfoLength))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quit;
+ }
+
+ ScreenBufferInfo = &GraphicsInfo;
- /* Insert the new handle inside the process handles table */
- Status = ConSrvInsertObject(ProcessData,
- &CreateScreenBufferRequest->OutputHandle,
- &Buff->Header,
- CreateScreenBufferRequest->Access,
- CreateScreenBufferRequest->Inheritable,
- CreateScreenBufferRequest->ShareMode);
+ /* Initialize shared variables */
+ CreateScreenBufferRequest->GraphicsBufferInfo.hMutex = GraphicsInfo.Info.hMutex = INVALID_HANDLE_VALUE;
+ CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap = GraphicsInfo.Info.lpBitMap = NULL;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ /* A graphics screen buffer is never inheritable */
+ CreateScreenBufferRequest->Inheritable = FALSE;
}
- ConSrvReleaseConsole(Console, TRUE);
- return Status;
-}
+ Status = ConSrvCreateScreenBuffer(&Buff,
+ Console,
+ CreateScreenBufferRequest->ScreenBufferType,
+ ScreenBufferInfo);
+ if (!NT_SUCCESS(Status)) goto Quit;
-CSR_API(SrvGetConsoleScreenBufferInfo)
-{
- NTSTATUS Status;
- PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
- PCONSOLE_SCREEN_BUFFER_INFO pInfo = &ScreenBufferInfoRequest->Info;
+ /* Insert the new handle inside the process handles table */
+ RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- DPRINT("SrvGetConsoleScreenBufferInfo\n");
+ Status = ConSrvInsertObject(ProcessData,
+ &CreateScreenBufferRequest->OutputHandle,
+ &Buff->Header,
+ CreateScreenBufferRequest->Access,
+ CreateScreenBufferRequest->Inheritable,
+ CreateScreenBufferRequest->ShareMode);
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ScreenBufferInfoRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- Console = Buff->Header.Console;
+ if (!NT_SUCCESS(Status)) goto Quit;
- pInfo->dwSize = Buff->ScreenBufferSize;
- pInfo->dwCursorPosition = Buff->CursorPosition;
- pInfo->wAttributes = Buff->ScreenDefaultAttrib;
- pInfo->srWindow.Left = Buff->ShowX;
- pInfo->srWindow.Right = Buff->ShowX + Console->ConsoleSize.X - 1;
- pInfo->srWindow.Top = Buff->ShowY;
- pInfo->srWindow.Bottom = Buff->ShowY + Console->ConsoleSize.Y - 1;
- pInfo->dwMaximumWindowSize = Buff->ScreenBufferSize;
+ if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER)
+ {
+ PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)Buff;
+ /*
+ * Initialize the graphics buffer information structure
+ * and give it back to the client.
+ */
+ CreateScreenBufferRequest->GraphicsBufferInfo.hMutex = Buffer->ClientMutex;
+ CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap = Buffer->ClientBitMap;
+ }
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
+Quit:
+ ConSrvReleaseConsole(Console, TRUE);
+ return Status;
}
CSR_API(SrvSetConsoleActiveScreenBuffer)
Console = Buff->Header.Console;
- if (Buff == Console->ActiveBuffer)
- {
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
- }
+ if (Buff == Console->ActiveBuffer) goto Quit;
/* If old buffer has no handles, it's now unreferenced */
if (Console->ActiveBuffer->Header.HandleCount == 0)
}
/* Tie console to new buffer */
- Console->ActiveBuffer = Buff;
-
- /* Redraw the console */
- ConioDrawConsole(Console);
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvScrollConsoleScreenBuffer)
-{
- PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScrollScreenBufferRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
- SMALL_RECT ScreenBuffer;
- SMALL_RECT SrcRegion;
- SMALL_RECT DstRegion;
- SMALL_RECT UpdateRegion;
- SMALL_RECT ScrollRectangle;
- SMALL_RECT ClipRectangle;
- NTSTATUS Status;
- HANDLE OutputHandle;
- BOOLEAN UseClipRectangle;
- COORD DestinationOrigin;
- CHAR_INFO Fill;
- CHAR FillChar;
-
- DPRINT("SrvScrollConsoleScreenBuffer\n");
-
- OutputHandle = ScrollScreenBufferRequest->OutputHandle;
- UseClipRectangle = ScrollScreenBufferRequest->UseClipRectangle;
- DestinationOrigin = ScrollScreenBufferRequest->DestinationOrigin;
- Fill = ScrollScreenBufferRequest->Fill;
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), OutputHandle, &Buff, GENERIC_WRITE, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- ScrollRectangle = ScrollScreenBufferRequest->ScrollRectangle;
-
- /* Make sure source rectangle is inside the screen buffer */
- ConioInitRect(&ScreenBuffer, 0, 0, Buff->ScreenBufferSize.Y - 1, Buff->ScreenBufferSize.X - 1);
- if (!ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle))
- {
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
- }
-
- /* If the source was clipped on the left or top, adjust the destination accordingly */
- if (ScrollRectangle.Left < 0)
- {
- DestinationOrigin.X -= ScrollRectangle.Left;
- }
- if (ScrollRectangle.Top < 0)
- {
- DestinationOrigin.Y -= ScrollRectangle.Top;
- }
-
- if (UseClipRectangle)
- {
- ClipRectangle = ScrollScreenBufferRequest->ClipRectangle;
- if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer))
- {
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
- }
- }
- else
- {
- ClipRectangle = ScreenBuffer;
- }
-
- ConioInitRect(&DstRegion,
- DestinationOrigin.Y,
- DestinationOrigin.X,
- DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1,
- DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1);
-
- if (ScrollScreenBufferRequest->Unicode)
- ConsoleUnicodeCharToAnsiChar(Console, &FillChar, &Fill.Char.UnicodeChar);
- else
- FillChar = Fill.Char.AsciiChar;
-
- ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, Fill.Attributes << 8 | (BYTE)FillChar);
-
- if (Buff == Console->ActiveBuffer)
- {
- ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion);
- if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &ClipRectangle))
- {
- /* Draw update region */
- ConioDrawRegion(Console, &UpdateRegion);
- }
- }
+ ConioSetActiveScreenBuffer(Buff);
+Quit:
ConSrvReleaseScreenBuffer(Buff, TRUE);
return STATUS_SUCCESS;
}
-CSR_API(SrvSetConsoleScreenBufferSize)
-{
- NTSTATUS Status;
- PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferSizeRequest;
- PCONSOLE_SCREEN_BUFFER Buff;
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetScreenBufferSizeRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Status = ConioResizeBuffer(Buff->Header.Console, Buff, SetScreenBufferSizeRequest->Size);
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return Status;
-}
-
/* EOF */
#pragma once
+#define ConSrvGetTextModeBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
+ ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
+ (Access), (LockConsole), TEXTMODE_BUFFER)
+#define ConSrvGetTextModeBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
+ ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
+ (Access), (LockConsole), TEXTMODE_BUFFER)
+
+#define ConSrvGetGraphicsBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
+ ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
+ (Access), (LockConsole), GRAPHICS_BUFFER)
+#define ConSrvGetGraphicsBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
+ ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
+ (Access), (LockConsole), GRAPHICS_BUFFER)
+
#define ConSrvGetScreenBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
(Access), (LockConsole), SCREEN_BUFFER)
#define ConSrvGetScreenBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
(Access), (LockConsole), SCREEN_BUFFER)
+
#define ConSrvReleaseScreenBuffer(Buff, IsConsoleLocked) \
ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked))
-NTSTATUS FASTCALL ConSrvCreateScreenBuffer(IN OUT PCONSOLE Console,
- OUT PCONSOLE_SCREEN_BUFFER* Buffer,
- IN COORD ScreenBufferSize,
- IN USHORT ScreenAttrib,
- IN USHORT PopupAttrib,
- IN ULONG DisplayMode,
- IN BOOLEAN IsCursorVisible,
- IN ULONG CursorSize);
+NTSTATUS FASTCALL ConSrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN ULONG BufferType,
+ IN PVOID ScreenBufferInfo);
VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
+VOID FASTCALL ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
/* EOF */
{
NTSTATUS Status;
SECURITY_ATTRIBUTES SecurityAttributes;
- CONSOLE_INFO ConsoleInfo;
SIZE_T Length = 0;
DWORD ProcessId = HandleToUlong(ConsoleLeaderProcess->ClientId.UniqueProcess);
+ CONSOLE_INFO ConsoleInfo;
+ TEXTMODE_BUFFER_INFO ScreenBufferInfo;
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER NewBuffer;
BOOL GuiMode;
ConsoleInfo.ConsoleSize.X = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cx;
ConsoleInfo.ConsoleSize.Y = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cy;
}
- /*
- if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
- {
- ConsoleInfo.FullScreen = TRUE;
- }
- */
}
+ /*
+ * Fix the screen buffer size if needed. The rule is:
+ * ScreenBufferSize >= ConsoleSize
+ */
+ if (ConsoleInfo.ScreenBufferSize.X < ConsoleInfo.ConsoleSize.X)
+ ConsoleInfo.ScreenBufferSize.X = ConsoleInfo.ConsoleSize.X;
+ if (ConsoleInfo.ScreenBufferSize.Y < ConsoleInfo.ConsoleSize.Y)
+ ConsoleInfo.ScreenBufferSize.Y = ConsoleInfo.ConsoleSize.Y;
+
/*
* Initialize the console
*/
memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors));
Console->ConsoleSize = ConsoleInfo.ConsoleSize;
+ Console->FixedSize = FALSE; // Value by default; is reseted by the front-ends if needed.
/*
* Initialize the input buffer
Console->CodePage = GetOEMCP();
Console->OutputCodePage = GetOEMCP();
- /* Initialize a new screen buffer with default settings */
+ /* Initialize a new text-mode screen buffer with default settings */
+ ScreenBufferInfo.ScreenBufferSize = ConsoleInfo.ScreenBufferSize;
+ ScreenBufferInfo.ScreenAttrib = ConsoleInfo.ScreenAttrib;
+ ScreenBufferInfo.PopupAttrib = ConsoleInfo.PopupAttrib;
+ ScreenBufferInfo.IsCursorVisible = TRUE;
+ ScreenBufferInfo.CursorSize = ConsoleInfo.CursorSize;
+
InitializeListHead(&Console->BufferList);
- Status = ConSrvCreateScreenBuffer(Console,
- &NewBuffer,
- ConsoleInfo.ScreenBufferSize,
- ConsoleInfo.ScreenAttrib,
- ConsoleInfo.PopupAttrib,
- (ConsoleInfo.FullScreen ? CONSOLE_FULLSCREEN_MODE
- : CONSOLE_WINDOWED_MODE),
- TRUE,
- ConsoleInfo.CursorSize);
+ Status = ConSrvCreateScreenBuffer(&NewBuffer,
+ Console,
+ CONSOLE_TEXTMODE_BUFFER,
+ &ScreenBufferInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("ConSrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
InitializeListHead(&Console->WriteWaitQueue);
Console->PauseFlags = 0;
Console->UnpauseEvent = NULL;
- // HardwareState
/*
* Initialize the alias and history buffers
ConsoleModeRequest->ConsoleMode = ConsoleMode;
}
- else if (SCREEN_BUFFER == Object->Type)
+ else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
{
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
ConsoleModeRequest->ConsoleMode = Buffer->Mode;
}
InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
}
- else if (SCREEN_BUFFER == Object->Type)
+ else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
{
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
* ConsoleHwState has the correct size to be compatible
* with NT's, but values are not.
*/
+#if 0
static NTSTATUS FASTCALL
SetConsoleHardwareState(PCONSOLE Console, ULONG ConsoleHwState)
{
return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
}
+#endif
CSR_API(SrvGetConsoleHardwareState)
{
+#if 0
NTSTATUS Status;
PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
PCONSOLE_SCREEN_BUFFER Buff;
PCONSOLE Console;
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
HardwareStateRequest->OutputHandle,
&Buff,
GENERIC_READ,
ConSrvReleaseScreenBuffer(Buff, TRUE);
return Status;
+#else
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+#endif
}
CSR_API(SrvSetConsoleHardwareState)
{
+#if 0
NTSTATUS Status;
PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
PCONSOLE_SCREEN_BUFFER Buff;
PCONSOLE Console;
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
HardwareStateRequest->OutputHandle,
&Buff,
GENERIC_WRITE,
ConSrvReleaseScreenBuffer(Buff, TRUE);
return Status;
+#else
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+#endif
}
CSR_API(SrvGetConsoleDisplayMode)
NTSTATUS Status;
PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
PCONSOLE Console;
- ULONG DisplayMode = 0;
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
&Console, TRUE);
return Status;
}
- if (Console->ActiveBuffer->DisplayMode & CONSOLE_FULLSCREEN_MODE)
- DisplayMode |= CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN
- else if (Console->ActiveBuffer->DisplayMode & CONSOLE_WINDOWED_MODE)
- DisplayMode |= CONSOLE_WINDOWED;
-
- GetDisplayModeRequest->DisplayMode = DisplayMode;
- Status = STATUS_SUCCESS;
+ GetDisplayModeRequest->DisplayMode = ConioGetDisplayMode(Console);
ConSrvReleaseConsole(Console, TRUE);
- return Status;
+ return STATUS_SUCCESS;
}
CSR_API(SrvSetConsoleDisplayMode)
{
NTSTATUS Status;
PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
+ PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER Buff;
Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
return Status;
}
- if (SetDisplayModeRequest->DisplayMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
+ Console = Buff->Header.Console;
+
+ if (ConioSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode))
{
- Status = STATUS_INVALID_PARAMETER;
+ SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
+ Status = STATUS_SUCCESS;
}
else
{
- Buff->DisplayMode = SetDisplayModeRequest->DisplayMode;
- // TODO: Change the display mode
- SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
-
- Status = STATUS_SUCCESS;
+ Status = STATUS_INVALID_PARAMETER;
}
ConSrvReleaseScreenBuffer(Buff, TRUE);
PCONSOLE_SCREEN_BUFFER Buff;
PCONSOLE Console;
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
GetLargestWindowSizeRequest->OutputHandle,
&Buff,
GENERIC_READ,
CSR_API(SrvSetConsoleWindowInfo)
{
-#if 0
NTSTATUS Status;
-#endif
PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetWindowInfoRequest;
-#if 0
PCONSOLE_SCREEN_BUFFER Buff;
- PCONSOLE Console;
-#endif
SMALL_RECT WindowRect = SetWindowInfoRequest->WindowRect;
-#if 0
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- SetWindowInfoRequest->OutputHandle,
- &Buff,
- GENERIC_READ,
- TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ DPRINT("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
+ SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
+ WindowRect.Left, WindowRect.Top, WindowRect.Right, WindowRect.Bottom);
- Console = Buff->Header.Console;
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ SetWindowInfoRequest->OutputHandle,
+ &Buff,
+ GENERIC_READ,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
if (SetWindowInfoRequest->Absolute == FALSE)
{
/* Relative positions given. Transform them to absolute ones */
- WindowRect.Left += Buff->ShowX;
- WindowRect.Top += Buff->ShowY;
- WindowRect.Right += Buff->ShowX + Console->ConsoleSize.X - 1;
- WindowRect.Bottom += Buff->ShowY + Console->ConsoleSize.Y - 1;
+ WindowRect.Left += Buff->ViewOrigin.X;
+ WindowRect.Top += Buff->ViewOrigin.Y;
+ WindowRect.Right += Buff->ViewOrigin.X + Buff->ViewSize.X - 1;
+ WindowRect.Bottom += Buff->ViewOrigin.Y + Buff->ViewSize.Y - 1;
}
- if ( (WindowRect.Left < 0) || (WindowRect.Top < 0) ||
- (WindowRect.Right > ScreenBufferSize.X) ||
- (WindowRect.Bottom > ScreenBufferSize.Y) ||
- (WindowRect.Right <= WindowRect.Left) ||
+ /* See MSDN documentation on SetConsoleWindowInfo about the performed checks */
+ if ( (WindowRect.Left < 0) || (WindowRect.Top < 0) ||
+ (WindowRect.Right >= Buff->ScreenBufferSize.X) ||
+ (WindowRect.Bottom >= Buff->ScreenBufferSize.Y) ||
+ (WindowRect.Right <= WindowRect.Left) ||
(WindowRect.Bottom <= WindowRect.Top) )
{
ConSrvReleaseScreenBuffer(Buff, TRUE);
return STATUS_INVALID_PARAMETER;
}
- Buff->ShowX = WindowRect.Left;
- Buff->ShowY = WindowRect.Top;
-
- // These two lines are frontend-specific.
- Console->ConsoleSize.X = WindowRect.Right - WindowRect.Left + 1;
- Console->ConsoleSize.Y = WindowRect.Bottom - WindowRect.Top + 1;
+ Buff->ViewOrigin.X = WindowRect.Left;
+ Buff->ViewOrigin.Y = WindowRect.Top;
- // ConioGetLargestConsoleWindowSize(Console, &GetLargestWindowSizeRequest->Size);
+ Buff->ViewSize.X = WindowRect.Right - WindowRect.Left + 1;
+ Buff->ViewSize.Y = WindowRect.Bottom - WindowRect.Top + 1;
ConSrvReleaseScreenBuffer(Buff, TRUE);
return STATUS_SUCCESS;
-#else
- DPRINT1("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) UNIMPLEMENTED\n",
- SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
- WindowRect.Left, WindowRect.Top, WindowRect.Right, WindowRect.Bottom);
- return STATUS_NOT_IMPLEMENTED;
-#endif
}
CSR_API(SrvGetConsoleWindow)
#include <wincon.h>
#include <winuser.h>
#define NTOS_MODE_USER
+#include <ndk/exfuncs.h>
#include <ndk/iofuncs.h>
#include <ndk/mmfuncs.h>
#include <ndk/obfuncs.h>
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Console Server DLL
+ * FILE: win32ss/user/consrv/frontends/gui/graphics.c
+ * PURPOSE: GUI Terminal Front-End - Support for graphics-mode screen-buffers
+ * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "include/settings.h"
+#include "guisettings.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* FUNCTIONS ******************************************************************/
+
+VOID
+GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer)
+{
+ /*
+ * This function supposes that the system clipboard was opened.
+ */
+
+ // PCONSOLE Console = Buffer->Header.Console;
+
+ UNIMPLEMENTED;
+}
+
+VOID
+GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer)
+{
+ /*
+ * This function supposes that the system clipboard was opened.
+ */
+
+ // PCONSOLE Console = Buffer->Header.Console;
+
+ UNIMPLEMENTED;
+}
+
+VOID
+GuiPaintGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
+ PGUI_CONSOLE_DATA GuiData,
+ HDC hDC,
+ PRECT rc)
+{
+ if (Buffer->BitMap == NULL) return;
+
+ /* Grab the mutex */
+ NtWaitForSingleObject(Buffer->Mutex, FALSE, NULL);
+
+ /*
+ * The seventh parameter (YSrc) of SetDIBitsToDevice always designates
+ * the Y-coordinate of the "lower-left corner" of the image, be the DIB
+ * in bottom-up or top-down mode.
+ */
+ SetDIBitsToDevice(hDC,
+ /* Coordinates / size of the repainted rectangle, in the view's frame */
+ rc->left,
+ rc->top,
+ rc->right - rc->left,
+ rc->bottom - rc->top,
+ /* Coordinates / size of the corresponding image portion, in the graphics screen-buffer's frame */
+ Buffer->ViewOrigin.X + rc->left,
+ Buffer->ViewOrigin.Y + rc->top,
+ 0,
+ Buffer->ScreenBufferSize.Y, // == Buffer->BitMapInfo->bmiHeader.biHeight
+ Buffer->BitMap,
+ Buffer->BitMapInfo,
+ Buffer->BitMapUsage);
+
+ /* Release the mutex */
+ NtReleaseMutant(Buffer->Mutex, NULL);
+}
+
+/* EOF */
TermInfo->FontWeight = Value;
RetVal = TRUE;
}
+ else if (!wcscmp(szValueName, L"FullScreen"))
+ {
+ TermInfo->FullScreen = Value;
+ RetVal = TRUE;
+ }
else if (!wcscmp(szValueName, L"WindowPosition"))
{
TermInfo->AutoPosition = FALSE;
SetConsoleSetting(L"FontSize", REG_DWORD, sizeof(DWORD), &TermInfo->FontSize, 0);
SetConsoleSetting(L"FontWeight", REG_DWORD, sizeof(DWORD), &TermInfo->FontWeight, FW_DONTCARE);
+ Storage = TermInfo->FullScreen;
+ SetConsoleSetting(L"FullScreen", REG_DWORD, sizeof(DWORD), &Storage, FALSE);
+
if (TermInfo->AutoPosition == FALSE)
{
Storage = MAKELONG(TermInfo->WindowOrigin.x, TermInfo->WindowOrigin.y);
wcsncpy(TermInfo->FaceName, L"Fixedsys", LF_FACESIZE); // HACK: !!
// TermInfo->FaceName[0] = L'\0';
TermInfo->FontFamily = FF_DONTCARE;
- TermInfo->FontSize = 0;
+ TermInfo->FontSize = 0;
TermInfo->FontWeight = FW_DONTCARE;
TermInfo->UseRasterFonts = TRUE;
+ TermInfo->FullScreen = FALSE;
TermInfo->ShowWindow = SW_SHOWNORMAL;
TermInfo->AutoPosition = TRUE;
TermInfo->WindowOrigin.x = 0;
{
NTSTATUS Status;
PCONSOLE Console = GuiData->Console;
+ PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
PCONSOLE_PROCESS_DATA ProcessData;
HANDLE hSection = NULL, hClientSection = NULL;
LARGE_INTEGER SectionSize;
pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize;
pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup;
- pSharedInfo->ci.FullScreen = !!(Console->ActiveBuffer->DisplayMode & CONSOLE_FULLSCREEN_MODE);
pSharedInfo->ci.QuickEdit = Console->QuickEdit;
pSharedInfo->ci.InsertMode = Console->InsertMode;
pSharedInfo->ci.InputBufferSize = 0;
- pSharedInfo->ci.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
- pSharedInfo->ci.ConsoleSize = Console->ConsoleSize;
+ pSharedInfo->ci.ScreenBufferSize = ActiveBuffer->ScreenBufferSize;
+ pSharedInfo->ci.ConsoleSize = ActiveBuffer->ViewSize;
pSharedInfo->ci.CursorBlinkOn;
pSharedInfo->ci.ForceCursorOff;
- pSharedInfo->ci.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
- pSharedInfo->ci.ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib;
- pSharedInfo->ci.PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib;
+ pSharedInfo->ci.CursorSize = ActiveBuffer->CursorInfo.dwSize;
+ if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
+ {
+ PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
+
+ pSharedInfo->ci.ScreenAttrib = Buffer->ScreenDefaultAttrib;
+ pSharedInfo->ci.PopupAttrib = Buffer->PopupDefaultAttrib;
+ }
+ else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
+ {
+ // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer;
+ DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n");
+
+ // FIXME: Gather defaults from the registry ?
+ pSharedInfo->ci.ScreenAttrib = DEFAULT_SCREEN_ATTRIB;
+ pSharedInfo->ci.PopupAttrib = DEFAULT_POPUP_ATTRIB ;
+ }
pSharedInfo->ci.CodePage;
/* GUI Information */
wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE);
GuiInfo->FaceName[Length] = L'\0';
GuiInfo->FontFamily = GuiData->GuiInfo.FontFamily;
- GuiInfo->FontSize = GuiData->GuiInfo.FontSize;
+ GuiInfo->FontSize = GuiData->GuiInfo.FontSize;
GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight;
GuiInfo->UseRasterFonts = GuiData->GuiInfo.UseRasterFonts;
+ GuiInfo->FullScreen = GuiData->GuiInfo.FullScreen;
/// GuiInfo->WindowPosition = GuiData->GuiInfo.WindowPosition;
GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin;
else
{
Length = 0;
+ // FIXME: Load the default parameters from the registry.
}
/* Null-terminate the title */
GuiConsoleMoveWindow(GuiData);
InvalidateRect(GuiData->hWindow, NULL, TRUE);
+
+ /*
+ * Apply full-screen mode.
+ */
+ GuiData->GuiInfo.FullScreen = GuiInfo->FullScreen;
+ // TODO: Apply it really
}
/*
DWORD FontWeight;
BOOL UseRasterFonts;
+ BOOL FullScreen; /* Whether the console is displayed in full-screen or windowed mode */
+// ULONG HardwareState; /* _GDI_MANAGED, _DIRECT */
+
WORD ShowWindow;
BOOL AutoPosition;
POINT WindowOrigin;
HWND hWindow; /* Handle to the console's window */
HICON hIcon; /* Handle to the console's icon (big) */
HICON hIconSm; /* Handle to the console's icon (small) */
- // COLORREF Colors[16];
+ BOOL IgnoreNextMouseSignal; /* Used in cases where we don't want to treat a mouse signal */
+// COLORREF Colors[16];
- // PVOID ScreenBuffer; /* Hardware screen buffer */
+// PVOID ScreenBuffer; /* Hardware screen buffer */
HFONT Font;
UINT CharWidth;
#endif
#define PM_CREATE_CONSOLE (WM_APP + 1)
#define PM_DESTROY_CONSOLE (WM_APP + 2)
-#define PM_CONSOLE_BEEP (WM_APP + 3)
-#define PM_CONSOLE_SET_TITLE (WM_APP + 4)
+#define PM_RESIZE_TERMINAL (WM_APP + 3)
+#define PM_CONSOLE_BEEP (WM_APP + 4)
+#define PM_CONSOLE_SET_TITLE (WM_APP + 5)
/* Not defined in any header file */
{
LRESULT Ret = TRUE;
PCONSOLE Console = GuiData->Console;
+ PCONSOLE_SCREEN_BUFFER ActiveBuffer;
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
Ret = FALSE;
goto Quit;
}
+ ActiveBuffer = Console->ActiveBuffer;
switch (wParam)
{
{
Console->Selection.dwSelectionAnchor.X = 0;
Console->Selection.dwSelectionAnchor.Y = 0;
- Console->dwSelectionCursor.X = Console->ConsoleSize.X - 1;
- Console->dwSelectionCursor.Y = Console->ConsoleSize.Y - 1;
+ Console->dwSelectionCursor.X = ActiveBuffer->ViewSize.X - 1;
+ Console->dwSelectionCursor.Y = ActiveBuffer->ViewSize.Y - 1;
GuiConsoleUpdateSelection(Console, &Console->dwSelectionCursor);
break;
}
GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData)
{
PCONSOLE Console = GuiData->Console;
+ PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
SCROLLINFO sInfo;
- DWORD Width = Console->ConsoleSize.X * GuiData->CharWidth +
- 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
- DWORD Height = Console->ConsoleSize.Y * GuiData->CharHeight +
- 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
+ DWORD Width, Height;
+ UINT WidthUnit, HeightUnit;
+
+ if (GetType(Buff) == TEXTMODE_BUFFER)
+ {
+ WidthUnit = GuiData->CharWidth ;
+ HeightUnit = GuiData->CharHeight;
+ }
+ else /* if (GetType(Buff) == GRAPHICS_BUFFER) */
+ {
+ WidthUnit = 1;
+ HeightUnit = 1;
+ }
+
+ Width = Buff->ViewSize.X * WidthUnit +
+ 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
+ Height = Buff->ViewSize.Y * HeightUnit +
+ 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
/* Set scrollbar sizes */
sInfo.cbSize = sizeof(SCROLLINFO);
sInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
sInfo.nMin = 0;
- if (Console->ActiveBuffer->ScreenBufferSize.Y > Console->ConsoleSize.Y)
+ if (Buff->ScreenBufferSize.Y > Buff->ViewSize.Y)
{
- sInfo.nMax = Console->ActiveBuffer->ScreenBufferSize.Y - 1;
- sInfo.nPage = Console->ConsoleSize.Y;
- sInfo.nPos = Console->ActiveBuffer->ShowY;
+ sInfo.nMax = Buff->ScreenBufferSize.Y - 1;
+ sInfo.nPage = Buff->ViewSize.Y;
+ sInfo.nPos = Buff->ViewOrigin.Y;
SetScrollInfo(GuiData->hWindow, SB_VERT, &sInfo, TRUE);
Width += GetSystemMetrics(SM_CXVSCROLL);
ShowScrollBar(GuiData->hWindow, SB_VERT, TRUE);
ShowScrollBar(GuiData->hWindow, SB_VERT, FALSE);
}
- if (Console->ActiveBuffer->ScreenBufferSize.X > Console->ConsoleSize.X)
+ if (Buff->ScreenBufferSize.X > Buff->ViewSize.X)
{
- sInfo.nMax = Console->ActiveBuffer->ScreenBufferSize.X - 1;
- sInfo.nPage = Console->ConsoleSize.X;
- sInfo.nPos = Console->ActiveBuffer->ShowX;
+ sInfo.nMax = Buff->ScreenBufferSize.X - 1;
+ sInfo.nPage = Buff->ViewSize.X;
+ sInfo.nPos = Buff->ViewOrigin.X;
SetScrollInfo(GuiData->hWindow, SB_HORZ, &sInfo, TRUE);
Height += GetSystemMetrics(SM_CYHSCROLL);
ShowScrollBar(GuiData->hWindow, SB_HORZ, TRUE);
/* Resize the window */
SetWindowPos(GuiData->hWindow, NULL, 0, 0, Width, Height,
- SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+ SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS);
+ // NOTE: The SWP_NOCOPYBITS flag can be replaced by a subsequent call
+ // to: InvalidateRect(GuiData->hWindow, NULL, TRUE);
+}
+
+static VOID
+GuiConsoleSwitchFullScreen(PGUI_CONSOLE_DATA GuiData)
+{
+ PCONSOLE Console = GuiData->Console;
+ // DEVMODE dmScreenSettings;
+
+ if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+
+ /* Switch to full-screen or to windowed mode */
+ GuiData->GuiInfo.FullScreen = !GuiData->GuiInfo.FullScreen;
+ DPRINT1("GuiConsoleSwitchFullScreen - Switch to %s ...\n",
+ (GuiData->GuiInfo.FullScreen ? "full-screen" : "windowed mode"));
+
+ // TODO: Change window appearance.
+ // See:
+ // http://stackoverflow.com/questions/2382464/win32-full-screen-and-hiding-taskbar
+ // http://stackoverflow.com/questions/3549148/fullscreen-management-with-winapi
+ // http://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx
+ // http://stackoverflow.com/questions/1400654/how-do-i-put-my-opengl-app-into-fullscreen-mode
+ // http://nehe.gamedev.net/tutorial/creating_an_opengl_window_win32/13001/
+#if 0
+ if (GuiData->GuiInfo.FullScreen)
+ {
+ memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
+ dmScreenSettings.dmSize = sizeof(dmScreenSettings);
+ dmScreenSettings.dmDisplayFixedOutput = DMDFO_CENTER; // DMDFO_STRETCH // DMDFO_DEFAULT
+ dmScreenSettings.dmPelsWidth = 640; // Console->ActiveBuffer->ViewSize.X * GuiData->CharWidth;
+ dmScreenSettings.dmPelsHeight = 480; // Console->ActiveBuffer->ViewSize.Y * GuiData->CharHeight;
+ dmScreenSettings.dmBitsPerPel = 32;
+ dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+ ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
+ }
+ else
+ {
+ }
+#endif
+
+ LeaveCriticalSection(&Console->Lock);
}
static BOOL
{
PCONSOLE Console = GuiData->Console;
PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+ UINT WidthUnit, HeightUnit;
+
+ if (GetType(Buffer) == TEXTMODE_BUFFER)
+ {
+ WidthUnit = GuiData->CharWidth ;
+ HeightUnit = GuiData->CharHeight;
+ }
+ else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
+ {
+ WidthUnit = 1;
+ HeightUnit = 1;
+ }
- Rect->left = (SmallRect->Left - Buffer->ShowX) * GuiData->CharWidth;
- Rect->top = (SmallRect->Top - Buffer->ShowY) * GuiData->CharHeight;
- Rect->right = (SmallRect->Right + 1 - Buffer->ShowX) * GuiData->CharWidth;
- Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ShowY) * GuiData->CharHeight;
+ Rect->left = (SmallRect->Left - Buffer->ViewOrigin.X) * WidthUnit ;
+ Rect->top = (SmallRect->Top - Buffer->ViewOrigin.Y) * HeightUnit;
+ Rect->right = (SmallRect->Right + 1 - Buffer->ViewOrigin.X) * WidthUnit ;
+ Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ViewOrigin.Y) * HeightUnit;
}
static VOID
}
}
-static VOID
-GuiConsolePaint(PCONSOLE Console,
- PGUI_CONSOLE_DATA GuiData,
- HDC hDC,
- PRECT rc)
-{
- PCONSOLE_SCREEN_BUFFER Buff;
- ULONG TopLine, BottomLine, LeftChar, RightChar;
- ULONG Line, Char, Start;
- PBYTE From;
- PWCHAR To;
- BYTE LastAttribute, Attribute;
- ULONG CursorX, CursorY, CursorHeight;
- HBRUSH CursorBrush, OldBrush;
- HFONT OldFont;
-
- Buff = Console->ActiveBuffer;
-
- TopLine = rc->top / GuiData->CharHeight + Buff->ShowY;
- BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buff->ShowY;
- LeftChar = rc->left / GuiData->CharWidth + Buff->ShowX;
- RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1 + Buff->ShowX;
- LastAttribute = ConioCoordToPointer(Buff, LeftChar, TopLine)[1];
-
- SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
- SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
-
- if (BottomLine >= Buff->ScreenBufferSize.Y) BottomLine = Buff->ScreenBufferSize.Y - 1;
- if (RightChar >= Buff->ScreenBufferSize.X) RightChar = Buff->ScreenBufferSize.X - 1;
-
- OldFont = SelectObject(hDC, GuiData->Font);
-
- for (Line = TopLine; Line <= BottomLine; Line++)
- {
- WCHAR LineBuffer[80];
- From = ConioCoordToPointer(Buff, LeftChar, Line);
- Start = LeftChar;
- To = LineBuffer;
-
- for (Char = LeftChar; Char <= RightChar; Char++)
- {
- if (*(From + 1) != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
- {
- TextOutW(hDC,
- (Start - Buff->ShowX) * GuiData->CharWidth,
- (Line - Buff->ShowY) * GuiData->CharHeight,
- LineBuffer,
- Char - Start);
- Start = Char;
- To = LineBuffer;
- Attribute = *(From + 1);
- if (Attribute != LastAttribute)
- {
- SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
- SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(Attribute)));
- LastAttribute = Attribute;
- }
- }
-
- MultiByteToWideChar(Console->OutputCodePage,
- 0, (PCHAR)From, 1, To, 1);
- To++;
- From += 2;
- }
-
- TextOutW(hDC,
- (Start - Buff->ShowX) * GuiData->CharWidth,
- (Line - Buff->ShowY) * GuiData->CharHeight,
- LineBuffer,
- RightChar - Start + 1);
- }
- if (Buff->CursorInfo.bVisible &&
- Buff->CursorBlinkOn &&
- !Buff->ForceCursorOff)
- {
- CursorX = Buff->CursorPosition.X;
- CursorY = Buff->CursorPosition.Y;
- if (LeftChar <= CursorX && CursorX <= RightChar &&
- TopLine <= CursorY && CursorY <= BottomLine)
- {
- CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
- From = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y) + 1;
-
- if (*From != DEFAULT_SCREEN_ATTRIB)
- {
- CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, *From));
- }
- else
- {
- CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, Buff->ScreenDefaultAttrib));
- }
-
- OldBrush = SelectObject(hDC, CursorBrush);
- PatBlt(hDC,
- (CursorX - Buff->ShowX) * GuiData->CharWidth,
- (CursorY - Buff->ShowY) * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
- GuiData->CharWidth,
- CursorHeight,
- PATCOPY);
- SelectObject(hDC, OldBrush);
- DeleteObject(CursorBrush);
- }
- }
-
- SelectObject(hDC, OldFont);
-}
+VOID
+GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
+ PGUI_CONSOLE_DATA GuiData,
+ HDC hDC,
+ PRECT rc);
+VOID
+GuiPaintGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
+ PGUI_CONSOLE_DATA GuiData,
+ HDC hDC,
+ PRECT rc);
static VOID
GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData)
{
BOOL Success = TRUE;
PCONSOLE Console = GuiData->Console;
+ PCONSOLE_SCREEN_BUFFER ActiveBuffer;
HDC hDC;
PAINTSTRUCT ps;
Success = FALSE;
goto Quit;
}
-
- if (Console->ActiveBuffer == NULL ||
- Console->ActiveBuffer->Buffer == NULL)
- {
- goto Quit;
- }
+ ActiveBuffer = Console->ActiveBuffer;
hDC = BeginPaint(GuiData->hWindow, &ps);
if (hDC != NULL &&
- ps.rcPaint.left < ps.rcPaint.right &&
- ps.rcPaint.top < ps.rcPaint.bottom)
+ ps.rcPaint.left < ps.rcPaint.right &&
+ ps.rcPaint.top < ps.rcPaint.bottom)
{
EnterCriticalSection(&GuiData->Lock);
- GuiConsolePaint(Console,
- GuiData,
- hDC,
- &ps.rcPaint);
+ if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
+ {
+ GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
+ GuiData, hDC, &ps.rcPaint);
+ }
+ else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
+ {
+ GuiPaintGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)ActiveBuffer,
+ GuiData, hDC, &ps.rcPaint);
+ }
if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
SmallRectToRect(GuiData, &rc, &Console->Selection.srSelection);
/* invert the selection */
- if (IntersectRect(&rc,
- &ps.rcPaint,
- &rc))
+ if (IntersectRect(&rc, &ps.rcPaint, &rc))
{
PatBlt(hDC,
rc.left,
GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
{
PCONSOLE Console = GuiData->Console;
+ PCONSOLE_SCREEN_BUFFER ActiveBuffer;
MSG Message;
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+ ActiveBuffer = Console->ActiveBuffer;
+
if ( (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
- ((Console->Selection.dwFlags & CONSOLE_MOUSE_SELECTION) == 0) &&
- (Console->ActiveBuffer) )
+ ((Console->Selection.dwFlags & CONSOLE_MOUSE_SELECTION) == 0) )
{
BOOL Interpreted = FALSE;
case VK_RIGHT:
{
Interpreted = TRUE;
- if (Console->dwSelectionCursor.X < Console->ActiveBuffer->ScreenBufferSize.X - 1)
+ if (Console->dwSelectionCursor.X < ActiveBuffer->ScreenBufferSize.X - 1)
Console->dwSelectionCursor.X++;
break;
case VK_DOWN:
{
Interpreted = TRUE;
- if (Console->dwSelectionCursor.Y < Console->ActiveBuffer->ScreenBufferSize.Y - 1)
+ if (Console->dwSelectionCursor.Y < ActiveBuffer->ScreenBufferSize.Y - 1)
Console->dwSelectionCursor.Y++;
break;
case VK_END:
{
Interpreted = TRUE;
- Console->dwSelectionCursor.Y = Console->ActiveBuffer->ScreenBufferSize.Y - 1;
+ Console->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
break;
}
case VK_PRIOR:
{
Interpreted = TRUE;
- Console->dwSelectionCursor.Y -= Console->ConsoleSize.Y;
+ Console->dwSelectionCursor.Y -= ActiveBuffer->ViewSize.Y;
if (Console->dwSelectionCursor.Y < 0)
Console->dwSelectionCursor.Y = 0;
case VK_NEXT:
{
Interpreted = TRUE;
- Console->dwSelectionCursor.Y += Console->ConsoleSize.Y;
- if (Console->dwSelectionCursor.Y >= Console->ActiveBuffer->ScreenBufferSize.Y)
- Console->dwSelectionCursor.Y = Console->ActiveBuffer->ScreenBufferSize.Y - 1;
+ Console->dwSelectionCursor.Y += ActiveBuffer->ViewSize.Y;
+ if (Console->dwSelectionCursor.Y >= ActiveBuffer->ScreenBufferSize.Y)
+ Console->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
break;
}
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
Buff = Console->ActiveBuffer;
- GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
- Buff->CursorBlinkOn = !Buff->CursorBlinkOn;
- if ((GuiData->OldCursor.x != Buff->CursorPosition.X) || (GuiData->OldCursor.y != Buff->CursorPosition.Y))
+ if (GetType(Buff) == TEXTMODE_BUFFER)
{
- SCROLLINFO xScroll;
- int OldScrollX = -1, OldScrollY = -1;
- int NewScrollX = -1, NewScrollY = -1;
-
- xScroll.cbSize = sizeof(SCROLLINFO);
- xScroll.fMask = SIF_POS;
- // Capture the original position of the scroll bars and save them.
- if (GetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll))OldScrollX = xScroll.nPos;
- if (GetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll))OldScrollY = xScroll.nPos;
+ GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+ Buff->CursorBlinkOn = !Buff->CursorBlinkOn;
- // If we successfully got the info for the horizontal scrollbar
- if (OldScrollX >= 0)
- {
- if ((Buff->CursorPosition.X < Buff->ShowX)||(Buff->CursorPosition.X >= (Buff->ShowX + Console->ConsoleSize.X)))
- {
- // Handle the horizontal scroll bar
- if (Buff->CursorPosition.X >= Console->ConsoleSize.X) NewScrollX = Buff->CursorPosition.X - Console->ConsoleSize.X + 1;
- else NewScrollX = 0;
- }
- else
- {
- NewScrollX = OldScrollX;
- }
- }
- // If we successfully got the info for the vertical scrollbar
- if (OldScrollY >= 0)
+ if ((GuiData->OldCursor.x != Buff->CursorPosition.X) || (GuiData->OldCursor.y != Buff->CursorPosition.Y))
{
- if ((Buff->CursorPosition.Y < Buff->ShowY) || (Buff->CursorPosition.Y >= (Buff->ShowY + Console->ConsoleSize.Y)))
+ SCROLLINFO xScroll;
+ int OldScrollX = -1, OldScrollY = -1;
+ int NewScrollX = -1, NewScrollY = -1;
+
+ xScroll.cbSize = sizeof(SCROLLINFO);
+ xScroll.fMask = SIF_POS;
+ // Capture the original position of the scroll bars and save them.
+ if (GetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll)) OldScrollX = xScroll.nPos;
+ if (GetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll)) OldScrollY = xScroll.nPos;
+
+ // If we successfully got the info for the horizontal scrollbar
+ if (OldScrollX >= 0)
{
- // Handle the vertical scroll bar
- if (Buff->CursorPosition.Y >= Console->ConsoleSize.Y) NewScrollY = Buff->CursorPosition.Y - Console->ConsoleSize.Y + 1;
- else NewScrollY = 0;
+ if ((Buff->CursorPosition.X < Buff->ViewOrigin.X) || (Buff->CursorPosition.X >= (Buff->ViewOrigin.X + Buff->ViewSize.X)))
+ {
+ // Handle the horizontal scroll bar
+ if (Buff->CursorPosition.X >= Buff->ViewSize.X) NewScrollX = Buff->CursorPosition.X - Buff->ViewSize.X + 1;
+ else NewScrollX = 0;
+ }
+ else
+ {
+ NewScrollX = OldScrollX;
+ }
}
- else
+ // If we successfully got the info for the vertical scrollbar
+ if (OldScrollY >= 0)
{
- NewScrollY = OldScrollY;
+ if ((Buff->CursorPosition.Y < Buff->ViewOrigin.Y) || (Buff->CursorPosition.Y >= (Buff->ViewOrigin.Y + Buff->ViewSize.Y)))
+ {
+ // Handle the vertical scroll bar
+ if (Buff->CursorPosition.Y >= Buff->ViewSize.Y) NewScrollY = Buff->CursorPosition.Y - Buff->ViewSize.Y + 1;
+ else NewScrollY = 0;
+ }
+ else
+ {
+ NewScrollY = OldScrollY;
+ }
}
- }
- // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
- // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
- // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
- // and their associated scrollbar is left alone.
- if ((OldScrollX != NewScrollX) || (OldScrollY != NewScrollY))
- {
- Buff->ShowX = NewScrollX;
- Buff->ShowY = NewScrollY;
- ScrollWindowEx(GuiData->hWindow,
- (OldScrollX - NewScrollX) * GuiData->CharWidth,
- (OldScrollY - NewScrollY) * GuiData->CharHeight,
- NULL,
- NULL,
- NULL,
- NULL,
- SW_INVALIDATE);
- if (NewScrollX >= 0)
- {
- xScroll.nPos = NewScrollX;
- SetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll, TRUE);
- }
- if (NewScrollY >= 0)
+ // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
+ // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
+ // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
+ // and their associated scrollbar is left alone.
+ if ((OldScrollX != NewScrollX) || (OldScrollY != NewScrollY))
{
- xScroll.nPos = NewScrollY;
- SetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll, TRUE);
+ Buff->ViewOrigin.X = NewScrollX;
+ Buff->ViewOrigin.Y = NewScrollY;
+ ScrollWindowEx(GuiData->hWindow,
+ (OldScrollX - NewScrollX) * GuiData->CharWidth,
+ (OldScrollY - NewScrollY) * GuiData->CharHeight,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ SW_INVALIDATE);
+ if (NewScrollX >= 0)
+ {
+ xScroll.nPos = NewScrollX;
+ SetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll, TRUE);
+ }
+ if (NewScrollY >= 0)
+ {
+ xScroll.nPos = NewScrollY;
+ SetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll, TRUE);
+ }
+ UpdateWindow(GuiData->hWindow);
+ GuiData->OldCursor.x = Buff->CursorPosition.X;
+ GuiData->OldCursor.y = Buff->CursorPosition.Y;
}
- UpdateWindow(GuiData->hWindow);
- GuiData->OldCursor.x = Buff->CursorPosition.X;
- GuiData->OldCursor.y = Buff->CursorPosition.Y;
}
}
+ else /* if (GetType(Buff) == GRAPHICS_BUFFER) */
+ {
+ }
LeaveCriticalSection(&Console->Lock);
}
PCONSOLE Console = GuiData->Console;
PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
COORD Coord;
+ UINT WidthUnit, HeightUnit;
- Coord.X = Buffer->ShowX + ((SHORT)LOWORD(lParam) / (int)GuiData->CharWidth);
- Coord.Y = Buffer->ShowY + ((SHORT)HIWORD(lParam) / (int)GuiData->CharHeight);
+ if (GetType(Buffer) == TEXTMODE_BUFFER)
+ {
+ WidthUnit = GuiData->CharWidth ;
+ HeightUnit = GuiData->CharHeight;
+ }
+ else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
+ {
+ WidthUnit = 1;
+ HeightUnit = 1;
+ }
+
+ Coord.X = Buffer->ViewOrigin.X + ((SHORT)LOWORD(lParam) / (int)WidthUnit );
+ Coord.Y = Buffer->ViewOrigin.Y + ((SHORT)HIWORD(lParam) / (int)HeightUnit);
/* Clip coordinate to ensure it's inside buffer */
if (Coord.X < 0)
BOOL Err = FALSE;
PCONSOLE Console = GuiData->Console;
+ if (GuiData->IgnoreNextMouseSignal)
+ {
+ if (msg != WM_LBUTTONDOWN &&
+ msg != WM_MBUTTONDOWN &&
+ msg != WM_RBUTTONDOWN)
+ {
+ /*
+ * If this mouse signal is not a button-down action,
+ * then it is the last signal being ignored.
+ */
+ GuiData->IgnoreNextMouseSignal = FALSE;
+ }
+ else
+ {
+ /*
+ * This mouse signal is a button-down action.
+ * Ignore it and perform default action.
+ */
+ Err = TRUE;
+ }
+ goto Quit;
+ }
+
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
Err = TRUE;
break;
}
+ case WM_LBUTTONDBLCLK:
+ {
+ DPRINT1("Handle left-double-click for selecting a word\n");
+ break;
+ }
+
case WM_RBUTTONDOWN:
+ case WM_RBUTTONDBLCLK:
{
if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
{
SetWindowText(GuiData->hWindow, Console->Title.Buffer);
}
+ GuiData->IgnoreNextMouseSignal = TRUE;
break;
}
return 0;
}
+VOID GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer);
+VOID GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer);
+
static VOID
GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
{
- PCONSOLE Console = GuiData->Console;
-
if (OpenClipboard(GuiData->hWindow) == TRUE)
{
- HANDLE hData;
- PBYTE ptr;
- LPSTR data, dstPos;
- ULONG selWidth, selHeight;
- ULONG xPos, yPos, size;
-
- selWidth = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
- selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
- DPRINT("Selection is (%d|%d) to (%d|%d)\n",
- Console->Selection.srSelection.Left,
- Console->Selection.srSelection.Top,
- Console->Selection.srSelection.Right,
- Console->Selection.srSelection.Bottom);
-
- /* Basic size for one line and termination */
- size = selWidth + 1;
- if (selHeight > 0)
- {
- /* Multiple line selections have to get \r\n appended */
- size += ((selWidth + 2) * (selHeight - 1));
- }
+ PCONSOLE Console = GuiData->Console;
+ PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
- /* Allocate memory, it will be passed to the system and may not be freed here */
- hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
- if (hData == NULL)
- {
- CloseClipboard();
- return;
- }
- data = GlobalLock(hData);
- if (data == NULL)
+ if (GetType(Buffer) == TEXTMODE_BUFFER)
{
- CloseClipboard();
- return;
+ GuiCopyFromTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer);
}
-
- DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
- dstPos = data;
-
- for (yPos = 0; yPos < selHeight; yPos++)
+ else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
{
- ptr = ConioCoordToPointer(Console->ActiveBuffer,
- Console->Selection.srSelection.Left,
- yPos + Console->Selection.srSelection.Top);
- /* Copy only the characters, leave attributes alone */
- for (xPos = 0; xPos < selWidth; xPos++)
- {
- dstPos[xPos] = ptr[xPos * 2];
- }
- dstPos += selWidth;
- if (yPos != (selHeight - 1))
- {
- strcat(data, "\r\n");
- dstPos += 2;
- }
+ GuiCopyFromGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer);
}
- DPRINT("Setting data <%s> to clipboard\n", data);
- GlobalUnlock(hData);
-
- EmptyClipboard();
- SetClipboardData(CF_TEXT, hData);
CloseClipboard();
}
}
+VOID GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer);
+VOID GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer);
+
static VOID
GuiConsolePaste(PGUI_CONSOLE_DATA GuiData)
{
- PCONSOLE Console = GuiData->Console;
-
if (OpenClipboard(GuiData->hWindow) == TRUE)
{
- HANDLE hData;
- LPSTR str;
- size_t len;
+ PCONSOLE Console = GuiData->Console;
+ PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
- hData = GetClipboardData(CF_TEXT);
- if (hData == NULL)
+ if (GetType(Buffer) == TEXTMODE_BUFFER)
{
- CloseClipboard();
- return;
+ GuiPasteToTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer);
}
-
- str = GlobalLock(hData);
- if (str == NULL)
+ else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
{
- CloseClipboard();
- return;
+ GuiPasteToGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer);
}
- DPRINT("Got data <%s> from clipboard\n", str);
- len = strlen(str);
-
- // TODO: Push the text into the input buffer.
- ConioWriteConsole(Console, Console->ActiveBuffer, str, len, TRUE);
- GlobalUnlock(hData);
CloseClipboard();
}
}
GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData, PMINMAXINFO minMaxInfo)
{
PCONSOLE Console = GuiData->Console;
+ PCONSOLE_SCREEN_BUFFER ActiveBuffer;
DWORD windx, windy;
+ UINT WidthUnit, HeightUnit;
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
- windx = CONGUI_MIN_WIDTH * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
- windy = CONGUI_MIN_HEIGHT * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
+ ActiveBuffer = Console->ActiveBuffer;
+
+ if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
+ {
+ WidthUnit = GuiData->CharWidth ;
+ HeightUnit = GuiData->CharHeight;
+ }
+ else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
+ {
+ WidthUnit = 1;
+ HeightUnit = 1;
+ }
+
+ windx = CONGUI_MIN_WIDTH * WidthUnit + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
+ windy = CONGUI_MIN_HEIGHT * HeightUnit + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
minMaxInfo->ptMinTrackSize.x = windx;
minMaxInfo->ptMinTrackSize.y = windy;
- windx = (Console->ActiveBuffer->ScreenBufferSize.X) * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
- windy = (Console->ActiveBuffer->ScreenBufferSize.Y) * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
+ windx = (ActiveBuffer->ScreenBufferSize.X) * WidthUnit + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
+ windy = (ActiveBuffer->ScreenBufferSize.Y) * HeightUnit + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
- if (Console->ConsoleSize.X < Console->ActiveBuffer->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL); // window currently has a horizontal scrollbar
- if (Console->ConsoleSize.Y < Console->ActiveBuffer->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL); // window currently has a vertical scrollbar
+ if (ActiveBuffer->ViewSize.X < ActiveBuffer->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL); // window currently has a horizontal scrollbar
+ if (ActiveBuffer->ViewSize.Y < ActiveBuffer->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL); // window currently has a vertical scrollbar
minMaxInfo->ptMaxTrackSize.x = windx;
minMaxInfo->ptMaxTrackSize.y = windy;
{
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
DWORD windx, windy, charx, chary;
+ UINT WidthUnit, HeightUnit;
+
+ if (GetType(Buff) == TEXTMODE_BUFFER)
+ {
+ WidthUnit = GuiData->CharWidth ;
+ HeightUnit = GuiData->CharHeight;
+ }
+ else /* if (GetType(Buff) == GRAPHICS_BUFFER) */
+ {
+ WidthUnit = 1;
+ HeightUnit = 1;
+ }
GuiData->WindowSizeLock = TRUE;
windy = HIWORD(lParam);
// Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
- if (Console->ConsoleSize.X < Buff->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL); // window currently has a horizontal scrollbar
- if (Console->ConsoleSize.Y < Buff->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL); // window currently has a vertical scrollbar
+ if (Buff->ViewSize.X < Buff->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL); // window currently has a horizontal scrollbar
+ if (Buff->ViewSize.Y < Buff->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL); // window currently has a vertical scrollbar
- charx = windx / GuiData->CharWidth;
- chary = windy / GuiData->CharHeight;
+ charx = windx / (int)WidthUnit ;
+ chary = windy / (int)HeightUnit;
// Character alignment (round size up or down)
- if ((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx;
- if ((windy % GuiData->CharHeight) >= (GuiData->CharHeight / 2)) ++chary;
+ if ((windx % WidthUnit ) >= (WidthUnit / 2)) ++charx;
+ if ((windy % HeightUnit) >= (HeightUnit / 2)) ++chary;
// Compensate for added scroll bars in new window
- if (charx < Buff->ScreenBufferSize.X)windy -= GetSystemMetrics(SM_CYHSCROLL); // new window will have a horizontal scroll bar
- if (chary < Buff->ScreenBufferSize.Y)windx -= GetSystemMetrics(SM_CXVSCROLL); // new window will have a vertical scroll bar
+ if (charx < Buff->ScreenBufferSize.X) windy -= GetSystemMetrics(SM_CYHSCROLL); // new window will have a horizontal scroll bar
+ if (chary < Buff->ScreenBufferSize.Y) windx -= GetSystemMetrics(SM_CXVSCROLL); // new window will have a vertical scroll bar
- charx = windx / GuiData->CharWidth;
- chary = windy / GuiData->CharHeight;
+ charx = windx / (int)WidthUnit ;
+ chary = windy / (int)HeightUnit;
// Character alignment (round size up or down)
- if ((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx;
- if ((windy % GuiData->CharHeight) >= (GuiData->CharHeight / 2)) ++chary;
+ if ((windx % WidthUnit ) >= (WidthUnit / 2)) ++charx;
+ if ((windy % HeightUnit) >= (HeightUnit / 2)) ++chary;
// Resize window
- if ((charx != Console->ConsoleSize.X) || (chary != Console->ConsoleSize.Y))
+ if ((charx != Buff->ViewSize.X) || (chary != Buff->ViewSize.Y))
{
- Console->ConsoleSize.X = (charx <= Buff->ScreenBufferSize.X) ? charx : Buff->ScreenBufferSize.X;
- Console->ConsoleSize.Y = (chary <= Buff->ScreenBufferSize.Y) ? chary : Buff->ScreenBufferSize.Y;
+ Buff->ViewSize.X = (charx <= Buff->ScreenBufferSize.X) ? charx : Buff->ScreenBufferSize.X;
+ Buff->ViewSize.Y = (chary <= Buff->ScreenBufferSize.Y) ? chary : Buff->ScreenBufferSize.Y;
}
GuiConsoleResizeWindow(GuiData);
// Adjust the start of the visible area if we are attempting to show nonexistent areas
- if ((Buff->ScreenBufferSize.X - Buff->ShowX) < Console->ConsoleSize.X) Buff->ShowX = Buff->ScreenBufferSize.X - Console->ConsoleSize.X;
- if ((Buff->ScreenBufferSize.Y - Buff->ShowY) < Console->ConsoleSize.Y) Buff->ShowY = Buff->ScreenBufferSize.Y - Console->ConsoleSize.Y;
+ if ((Buff->ScreenBufferSize.X - Buff->ViewOrigin.X) < Buff->ViewSize.X) Buff->ViewOrigin.X = Buff->ScreenBufferSize.X - Buff->ViewSize.X;
+ if ((Buff->ScreenBufferSize.Y - Buff->ViewOrigin.Y) < Buff->ViewSize.Y) Buff->ViewOrigin.Y = Buff->ScreenBufferSize.Y - Buff->ViewSize.Y;
InvalidateRect(GuiData->hWindow, NULL, TRUE);
GuiData->WindowSizeLock = FALSE;
SCROLLINFO sInfo;
int fnBar;
int old_pos, Maximum;
- PUSHORT pShowXY;
+ PSHORT pShowXY;
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
if (uMsg == WM_HSCROLL)
{
fnBar = SB_HORZ;
- Maximum = Buff->ScreenBufferSize.X - Console->ConsoleSize.X;
- pShowXY = &Buff->ShowX;
+ Maximum = Buff->ScreenBufferSize.X - Buff->ViewSize.X;
+ pShowXY = &Buff->ViewOrigin.X;
}
else
{
fnBar = SB_VERT;
- Maximum = Buff->ScreenBufferSize.Y - Console->ConsoleSize.Y;
- pShowXY = &Buff->ShowY;
+ Maximum = Buff->ScreenBufferSize.Y - Buff->ViewSize.Y;
+ pShowXY = &Buff->ViewOrigin.Y;
}
/* set scrollbar sizes */
if (old_pos != sInfo.nPos)
{
- USHORT OldX = Buff->ShowX;
- USHORT OldY = Buff->ShowY;
+ USHORT OldX = Buff->ViewOrigin.X;
+ USHORT OldY = Buff->ViewOrigin.Y;
+ UINT WidthUnit, HeightUnit;
+
*pShowXY = sInfo.nPos;
+ if (GetType(Buff) == TEXTMODE_BUFFER)
+ {
+ WidthUnit = GuiData->CharWidth ;
+ HeightUnit = GuiData->CharHeight;
+ }
+ else /* if (GetType(Buff) == GRAPHICS_BUFFER) */
+ {
+ WidthUnit = 1;
+ HeightUnit = 1;
+ }
+
ScrollWindowEx(GuiData->hWindow,
- (OldX - Buff->ShowX) * GuiData->CharWidth,
- (OldY - Buff->ShowY) * GuiData->CharHeight,
+ (OldX - Buff->ViewOrigin.X) * WidthUnit ,
+ (OldY - Buff->ViewOrigin.Y) * HeightUnit,
NULL,
NULL,
NULL,
/* We have a console, start message dispatching */
switch (msg)
{
+ case WM_ACTIVATE:
+ {
+ if (LOWORD(wParam) == WA_CLICKACTIVE) GuiData->IgnoreNextMouseSignal = TRUE;
+ break;
+ }
+
case WM_CLOSE:
GuiConsoleHandleClose(GuiData);
break;
case WM_SYSKEYUP:
case WM_CHAR:
{
+ /* Detect Alt-Enter presses and switch back and forth to fullscreen mode */
+ if (msg == WM_SYSKEYDOWN && (HIWORD(lParam) & KF_ALTDOWN) && wParam == VK_RETURN)
+ {
+ /* Switch only at first Alt-Enter press, and ignore subsequent key repetitions */
+ if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT) GuiConsoleSwitchFullScreen(GuiData);
+ break;
+ }
+
GuiConsoleHandleKey(GuiData, msg, wParam, lParam);
break;
}
break;
}
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ {
+ Result = GuiConsoleHandleScroll(GuiData, msg, wParam);
+ break;
+ }
+
case WM_NCRBUTTONDOWN:
{
- DPRINT("WM_NCRBUTTONDOWN\n");
+ DPRINT1("WM_NCRBUTTONDOWN\n");
/*
* HACK: !! Because, when we deal with WM_RBUTTON* and we do not
* call after that DefWindowProc, on ReactOS, right-clicks on the
* and line 1135 too.
*/
if (DefWindowProcW(hWnd, WM_NCHITTEST, 0, lParam) == HTCAPTION)
- return DefWindowProcW(hWnd, WM_CONTEXTMENU, wParam, lParam);
- else
- goto Default;
+ {
+ /* Call DefWindowProcW with the WM_CONTEXTMENU message */
+ msg = WM_CONTEXTMENU;
+ }
+ goto Default;
}
// case WM_NCRBUTTONUP:
// DPRINT1("WM_NCRBUTTONUP\n");
break;
}
- case WM_HSCROLL:
- case WM_VSCROLL:
- {
- Result = GuiConsoleHandleScroll(GuiData, msg, wParam);
- break;
- }
-
case WM_SETFOCUS:
case WM_KILLFOCUS:
{
er.Event.FocusEvent.bSetFocus = (msg == WM_SETFOCUS);
ConioProcessInputEvent(Console, &er);
+ if (msg == WM_SETFOCUS)
+ DPRINT1("TODO: Create console caret\n");
+ else // if (msg == WM_KILLFOCUS)
+ DPRINT1("TODO: Destroy console caret\n");
+
LeaveCriticalSection(&Console->Lock);
}
break;
GuiConsoleResize(GuiData, wParam, lParam);
break;
+ case PM_RESIZE_TERMINAL:
+ {
+ /* Resize the window to the user's values */
+ GuiData->WindowSizeLock = TRUE;
+ GuiConsoleResizeWindow(GuiData);
+ GuiData->WindowSizeLock = FALSE;
+ break;
+ }
+
case PM_APPLY_CONSOLE_INFO:
{
Console = GuiData->Console; // Not NULL because checked in GuiGetGuiData.
wc.hIcon = ghDefaultIcon;
wc.hIconSm = ghDefaultIconSm;
wc.hCursor = ghDefaultCursor;
- wc.hbrBackground = CreateSolidBrush(RGB(0,0,0)); // FIXME: Use defaults from registry.
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // The color of a terminal when it is switch off.
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = GWLP_CONSOLEWND_ALLOC;
DPRINT("Quit GuiCleanupConsole\n");
}
+static VOID WINAPI
+GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
+{
+ PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ RECT RegionRect;
+
+ SmallRectToRect(GuiData, &RegionRect, Region);
+ /* Do not erase the background: it speeds up redrawing and reduce flickering */
+ InvalidateRect(GuiData->hWindow, &RegionRect, FALSE);
+}
+
static VOID WINAPI
GuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
UINT ScrolledLines, CHAR *Buffer, UINT Length)
SHORT CursorEndX, CursorEndY;
RECT ScrollRect;
- if (NULL == GuiData || NULL == GuiData->hWindow)
- {
- return;
- }
+ if (NULL == GuiData || NULL == GuiData->hWindow) return;
+ if (GetType(Buff) != TEXTMODE_BUFFER) return;
if (0 != ScrolledLines)
{
ScrollRect.left = 0;
ScrollRect.top = 0;
- ScrollRect.right = Console->ConsoleSize.X * GuiData->CharWidth;
+ ScrollRect.right = Buff->ViewSize.X * GuiData->CharWidth;
ScrollRect.bottom = Region->Top * GuiData->CharHeight;
ScrollWindowEx(GuiData->hWindow,
SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
}
-static VOID WINAPI
-GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
-{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
- RECT RegionRect;
-
- SmallRectToRect(GuiData, &RegionRect, Region);
- InvalidateRect(GuiData->hWindow, &RegionRect, FALSE);
-}
-
static BOOL WINAPI
GuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
{
{
if (Console->ActiveBuffer == Buff)
{
- /* Redraw char at old position (removes cursor) */
+ /* Redraw char at old position (remove cursor) */
GuiInvalidateCell(Console, OldCursorX, OldCursorY);
- /* Redraw char at new position (shows cursor) */
+ /* Redraw char at new position (show cursor) */
GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
}
return TRUE;
}
-static BOOL WINAPI
-GuiUpdateScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
-{
- return TRUE;
-}
-
-static BOOL WINAPI
-GuiIsBufferResizeSupported(PCONSOLE Console)
-{
- return TRUE;
-}
-
static VOID WINAPI
GuiResizeTerminal(PCONSOLE Console)
{
PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
/* Resize the window to the user's values */
- GuiData->WindowSizeLock = TRUE;
- GuiConsoleResizeWindow(GuiData);
- GuiData->WindowSizeLock = FALSE;
+ // GuiData->WindowSizeLock = TRUE;
+ // GuiConsoleResizeWindow(GuiData);
+ // GuiData->WindowSizeLock = FALSE;
+ // NOTE: This code ^^ causes deadlocks...
+
+ PostMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
}
static BOOL WINAPI
GuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize)
{
PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
- HWND hDesktop;
- RECT desktop;
+ RECT WorkArea;
LONG width, height;
+ UINT WidthUnit, HeightUnit;
if (!pSize) return;
- /*
- * This is one solution. Surely better solutions exist :
- * http://stackoverflow.com/questions/4631292/how-detect-current-screen-resolution
- * http://www.clearevo.com/blog/programming/2011/08/30/windows_c_c++_-_get_monitor_display_screen_size_in_pixels.html
- */
- hDesktop = GetDesktopWindow();
- if (!hDesktop) return;
+ if (!SystemParametersInfoW(SPI_GETWORKAREA, 0, &WorkArea, 0))
+ {
+ DPRINT1("SystemParametersInfoW failed - What to do ??\n");
+ return;
+ }
- GetWindowRect(hDesktop, &desktop);
+ if (Console->ActiveBuffer)
+ {
+ if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
+ {
+ WidthUnit = GuiData->CharWidth ;
+ HeightUnit = GuiData->CharHeight;
+ }
+ else /* if (GetType(Console->ActiveBuffer) == GRAPHICS_BUFFER) */
+ {
+ WidthUnit = 1;
+ HeightUnit = 1;
+ }
+ }
+ else
+ {
+ /* Default: text mode */
+ WidthUnit = GuiData->CharWidth ;
+ HeightUnit = GuiData->CharHeight;
+ }
- width = desktop.right;
- height = desktop.bottom;
+ width = WorkArea.right;
+ height = WorkArea.bottom;
width -= (2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)));
height -= (2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION));
if (width < 0) width = 0;
if (height < 0) height = 0;
- pSize->X = (SHORT)(width / GuiData->CharWidth );
- pSize->Y = (SHORT)(height / GuiData->CharHeight);
+ pSize->X = (SHORT)(width / (int)WidthUnit ) /* HACK */ + 2;
+ pSize->Y = (SHORT)(height / (int)HeightUnit) /* HACK */ + 1;
+}
+
+static ULONG WINAPI
+GuiGetDisplayMode(PCONSOLE Console)
+{
+ PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ ULONG DisplayMode = 0;
+
+ if (GuiData->GuiInfo.FullScreen)
+ DisplayMode |= CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN
+ else
+ DisplayMode |= CONSOLE_WINDOWED;
+
+ return DisplayMode;
+}
+
+static BOOL WINAPI
+GuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
+{
+ PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+
+ if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
+ return FALSE;
+
+ GuiData->GuiInfo.FullScreen = (NewMode & CONSOLE_FULLSCREEN_MODE);
+ // TODO: Change the display mode
+ return TRUE;
}
static FRONTEND_VTBL GuiVtbl =
{
GuiCleanupConsole,
- GuiWriteStream,
GuiDrawRegion,
+ GuiWriteStream,
GuiSetCursorInfo,
GuiSetScreenInfo,
- GuiUpdateScreenInfo,
- GuiIsBufferResizeSupported,
GuiResizeTerminal,
GuiProcessKeyCallback,
GuiRefreshInternalInfo,
GuiChangeTitle,
GuiChangeIcon,
GuiGetConsoleWindowHandle,
- GuiGetLargestConsoleWindowSize
+ GuiGetLargestConsoleWindowSize,
+ GuiGetDisplayMode,
+ GuiSetDisplayMode,
};
NTSTATUS FASTCALL
GuiData->Console = Console;
GuiData->hWindow = NULL;
+ /* The console can be resized */
+ Console->FixedSize = FALSE;
+
InitializeCriticalSection(&GuiData->Lock);
TermInfo.AutoPosition = FALSE;
TermInfo.WindowOrigin = ConsoleStartInfo->ConsoleWindowOrigin;
}
- /*
if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
{
- ConsoleInfo.FullScreen = TRUE;
+ TermInfo.FullScreen = TRUE;
}
- */
}
GuiData->GuiInfo.FontSize = TermInfo.FontSize;
GuiData->GuiInfo.FontWeight = TermInfo.FontWeight;
GuiData->GuiInfo.UseRasterFonts = TermInfo.UseRasterFonts;
+ GuiData->GuiInfo.FullScreen = TermInfo.FullScreen;
GuiData->GuiInfo.ShowWindow = TermInfo.ShowWindow;
GuiData->GuiInfo.AutoPosition = TermInfo.AutoPosition;
GuiData->GuiInfo.WindowOrigin = TermInfo.WindowOrigin;
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Console Server DLL
+ * FILE: win32ss/user/consrv/frontends/gui/text.c
+ * PURPOSE: GUI Terminal Front-End - Support for text-mode screen-buffers
+ * PROGRAMMERS: Gé van Geldorp
+ * Johannes Anderwald
+ * Jeffrey Morlan
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "include/settings.h"
+#include "guisettings.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* GLOBALS ********************************************************************/
+
+/* Copied from consrv/text.c */
+#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
+ MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
+
+
+/* FUNCTIONS ******************************************************************/
+
+VOID
+GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
+{
+ /*
+ * This function supposes that the system clipboard was opened.
+ */
+
+ PCONSOLE Console = Buffer->Header.Console;
+
+ HANDLE hData;
+ PBYTE ptr;
+ LPWSTR data, dstPos;
+ ULONG selWidth, selHeight;
+ ULONG xPos, yPos, size;
+
+ selWidth = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
+ selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
+ DPRINT("Selection is (%d|%d) to (%d|%d)\n",
+ Console->Selection.srSelection.Left,
+ Console->Selection.srSelection.Top,
+ Console->Selection.srSelection.Right,
+ Console->Selection.srSelection.Bottom);
+
+ /* Basic size for one line and termination */
+ size = selWidth + 1;
+ if (selHeight > 0)
+ {
+ /* Multiple line selections have to get \r\n appended */
+ size += ((selWidth + 2) * (selHeight - 1));
+ }
+ size *= sizeof(WCHAR);
+
+ /* Allocate memory, it will be passed to the system and may not be freed here */
+ hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
+ if (hData == NULL) return;
+
+ data = GlobalLock(hData);
+ if (data == NULL) return;
+
+ DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
+ dstPos = data;
+
+ for (yPos = 0; yPos < selHeight; yPos++)
+ {
+ ptr = ConioCoordToPointer(Buffer,
+ Console->Selection.srSelection.Left,
+ yPos + Console->Selection.srSelection.Top);
+ /* Copy only the characters, leave attributes alone */
+ for (xPos = 0; xPos < selWidth; xPos++)
+ {
+ ConsoleAnsiCharToUnicodeChar(Console, &dstPos[xPos], (LPCSTR)&ptr[xPos * 2]);
+ }
+ dstPos += selWidth;
+ if (yPos != (selHeight - 1))
+ {
+ wcscat(data, L"\r\n");
+ dstPos += 2;
+ }
+ }
+
+ DPRINT("Setting data <%S> to clipboard\n", data);
+ GlobalUnlock(hData);
+
+ EmptyClipboard();
+ SetClipboardData(CF_UNICODETEXT, hData);
+}
+
+VOID
+GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
+{
+ /*
+ * This function supposes that the system clipboard was opened.
+ */
+
+ PCONSOLE Console = Buffer->Header.Console;
+
+ HANDLE hData;
+ LPWSTR str;
+ WCHAR CurChar = 0;
+
+ SHORT VkKey; // MAKEWORD(low = vkey_code, high = shift_state);
+ INPUT_RECORD er;
+
+ hData = GetClipboardData(CF_UNICODETEXT);
+ if (hData == NULL) return;
+
+ str = GlobalLock(hData);
+ if (str == NULL) return;
+
+ DPRINT("Got data <%S> from clipboard\n", str);
+
+ er.EventType = KEY_EVENT;
+ er.Event.KeyEvent.wRepeatCount = 1;
+ while (*str)
+ {
+ /* \r or \n characters. Go to the line only if we get "\r\n" sequence. */
+ if (CurChar == L'\r' && *str == L'\n')
+ {
+ str++;
+ continue;
+ }
+ CurChar = *str++;
+
+ /* Get the key code (+ shift state) corresponding to the character */
+ VkKey = VkKeyScanW(CurChar);
+ if (VkKey == 0xFFFF)
+ {
+ DPRINT1("VkKeyScanW failed - Should simulate the key...\n");
+ continue;
+ }
+
+ /* Pressing some control keys */
+
+ /* Pressing the character key, with the control keys maintained pressed */
+ er.Event.KeyEvent.bKeyDown = TRUE;
+ er.Event.KeyEvent.wVirtualKeyCode = LOBYTE(VkKey);
+ er.Event.KeyEvent.wVirtualScanCode = MapVirtualKeyW(LOBYTE(VkKey), MAPVK_VK_TO_CHAR);
+ er.Event.KeyEvent.uChar.UnicodeChar = CurChar;
+ er.Event.KeyEvent.dwControlKeyState = 0;
+ if (HIBYTE(VkKey) & 1)
+ er.Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
+ if (HIBYTE(VkKey) & 2)
+ er.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; // RIGHT_CTRL_PRESSED;
+ if (HIBYTE(VkKey) & 4)
+ er.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; // RIGHT_ALT_PRESSED;
+
+ ConioProcessInputEvent(Console, &er);
+
+ /* Up all the character and control keys */
+ er.Event.KeyEvent.bKeyDown = FALSE;
+ ConioProcessInputEvent(Console, &er);
+ }
+
+ GlobalUnlock(hData);
+}
+
+VOID
+GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
+ PGUI_CONSOLE_DATA GuiData,
+ HDC hDC,
+ PRECT rc)
+{
+ PCONSOLE Console = Buffer->Header.Console;
+ // ASSERT(Console == GuiData->Console);
+
+ ULONG TopLine, BottomLine, LeftChar, RightChar;
+ ULONG Line, Char, Start;
+ PBYTE From;
+ PWCHAR To;
+ BYTE LastAttribute, Attribute;
+ ULONG CursorX, CursorY, CursorHeight;
+ HBRUSH CursorBrush, OldBrush;
+ HFONT OldFont;
+
+ if (Buffer->Buffer == NULL) return;
+
+ TopLine = rc->top / GuiData->CharHeight + Buffer->ViewOrigin.Y;
+ BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buffer->ViewOrigin.Y;
+ LeftChar = rc->left / GuiData->CharWidth + Buffer->ViewOrigin.X;
+ RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1 + Buffer->ViewOrigin.X;
+ LastAttribute = ConioCoordToPointer(Buffer, LeftChar, TopLine)[1];
+
+ SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
+ SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
+
+ if (BottomLine >= Buffer->ScreenBufferSize.Y) BottomLine = Buffer->ScreenBufferSize.Y - 1;
+ if (RightChar >= Buffer->ScreenBufferSize.X) RightChar = Buffer->ScreenBufferSize.X - 1;
+
+ OldFont = SelectObject(hDC, GuiData->Font);
+
+ for (Line = TopLine; Line <= BottomLine; Line++)
+ {
+ WCHAR LineBuffer[80];
+ From = ConioCoordToPointer(Buffer, LeftChar, Line);
+ Start = LeftChar;
+ To = LineBuffer;
+
+ for (Char = LeftChar; Char <= RightChar; Char++)
+ {
+ if (*(From + 1) != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
+ {
+ TextOutW(hDC,
+ (Start - Buffer->ViewOrigin.X) * GuiData->CharWidth,
+ (Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
+ LineBuffer,
+ Char - Start);
+ Start = Char;
+ To = LineBuffer;
+ Attribute = *(From + 1);
+ if (Attribute != LastAttribute)
+ {
+ SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
+ SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(Attribute)));
+ LastAttribute = Attribute;
+ }
+ }
+
+ MultiByteToWideChar(Console->OutputCodePage,
+ 0, (PCHAR)From, 1, To, 1);
+ To++;
+ From += 2;
+ }
+
+ TextOutW(hDC,
+ (Start - Buffer->ViewOrigin.X) * GuiData->CharWidth,
+ (Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
+ LineBuffer,
+ RightChar - Start + 1);
+ }
+
+ /*
+ * Draw the caret
+ */
+ if (Buffer->CursorInfo.bVisible &&
+ Buffer->CursorBlinkOn &&
+ !Buffer->ForceCursorOff)
+ {
+ CursorX = Buffer->CursorPosition.X;
+ CursorY = Buffer->CursorPosition.Y;
+ if (LeftChar <= CursorX && CursorX <= RightChar &&
+ TopLine <= CursorY && CursorY <= BottomLine)
+ {
+ CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
+ From = ConioCoordToPointer(Buffer, Buffer->CursorPosition.X, Buffer->CursorPosition.Y) + 1;
+
+ if (*From != DEFAULT_SCREEN_ATTRIB)
+ {
+ CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, *From));
+ }
+ else
+ {
+ CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, Buffer->ScreenDefaultAttrib));
+ }
+
+ OldBrush = SelectObject(hDC, CursorBrush);
+ PatBlt(hDC,
+ (CursorX - Buffer->ViewOrigin.X) * GuiData->CharWidth,
+ (CursorY - Buffer->ViewOrigin.Y) * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
+ GuiData->CharWidth,
+ CursorHeight,
+ PATCOPY);
+ SelectObject(hDC, OldBrush);
+ DeleteObject(CursorBrush);
+ }
+ }
+
+ SelectObject(hDC, OldFont);
+}
+
+/* EOF */
}
static VOID FASTCALL
-TuiCopyRect(char *Dest, PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
+TuiCopyRect(char *Dest, PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
{
UINT SrcDelta, DestDelta;
LONG i;
ConsoleFreeHeap(TuiData);
}
-static VOID WINAPI
-TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
- UINT ScrolledLines, CHAR *Buffer, UINT Length)
-{
- DWORD BytesWritten;
- PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
-
- if (ActiveConsole->Console->ActiveBuffer != Buff) return;
-
- if (!WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL))
- {
- DPRINT1("Error writing to BlueScreen\n");
- }
-}
-
static VOID WINAPI
TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
{
PCONSOLE_DRAW ConsoleDraw;
UINT ConsoleDrawSize;
- if (ActiveConsole->Console != Console) return;
+ if (ActiveConsole->Console != Console || GetType(Buff) != TEXTMODE_BUFFER) return;
ConsoleDrawSize = sizeof(CONSOLE_DRAW) +
(ConioRectWidth(Region) * ConioRectHeight(Region)) * 2;
ConsoleDraw->CursorX = Buff->CursorPosition.X;
ConsoleDraw->CursorY = Buff->CursorPosition.Y;
- TuiCopyRect((char *) (ConsoleDraw + 1), Buff, Region);
+ TuiCopyRect((char*)(ConsoleDraw + 1), (PTEXTMODE_SCREEN_BUFFER)Buff, Region);
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW,
NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL))
ConsoleFreeHeap(ConsoleDraw);
}
+static VOID WINAPI
+TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
+ UINT ScrolledLines, CHAR *Buffer, UINT Length)
+{
+ DWORD BytesWritten;
+ PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+
+ if (ActiveConsole->Console->ActiveBuffer != Buff) return;
+
+ if (!WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL))
+ {
+ DPRINT1("Error writing to BlueScreen\n");
+ }
+}
+
static BOOL WINAPI
TuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
{
DWORD BytesReturned;
if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE;
+ if (GetType(Buff) != TEXTMODE_BUFFER) return FALSE;
Info.dwCursorPosition = Buff->CursorPosition;
- Info.wAttributes = Buff->ScreenDefaultAttrib;
+ Info.wAttributes = ((PTEXTMODE_SCREEN_BUFFER)Buff)->ScreenDefaultAttrib;
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
&Info, sizeof(CONSOLE_SCREEN_BUFFER_INFO), NULL, 0,
return TRUE;
}
-static BOOL WINAPI
-TuiUpdateScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
-{
- return TRUE;
-}
-
-static BOOL WINAPI
-TuiIsBufferResizeSupported(PCONSOLE Console)
-{
- return (Console && Console->State == CONSOLE_INITIALIZING ? TRUE : FALSE);
-}
-
static VOID WINAPI
TuiResizeTerminal(PCONSOLE Console)
{
*pSize = PhysicalConsoleSize;
}
+static ULONG WINAPI
+TuiGetDisplayMode(PCONSOLE Console)
+{
+ return CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN;
+}
+
+static BOOL WINAPI
+TuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
+{
+ // if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
+ // return FALSE;
+ return TRUE;
+}
+
static FRONTEND_VTBL TuiVtbl =
{
TuiCleanupConsole,
- TuiWriteStream,
TuiDrawRegion,
+ TuiWriteStream,
TuiSetCursorInfo,
TuiSetScreenInfo,
- TuiUpdateScreenInfo,
- TuiIsBufferResizeSupported,
TuiResizeTerminal,
TuiProcessKeyCallback,
TuiRefreshInternalInfo,
TuiChangeTitle,
TuiChangeIcon,
TuiGetConsoleWindowHandle,
- TuiGetLargestConsoleWindowSize
+ TuiGetLargestConsoleWindowSize,
+ TuiGetDisplayMode,
+ TuiSetDisplayMode,
};
NTSTATUS FASTCALL
if (Console == NULL || ConsoleInfo == NULL)
return STATUS_INVALID_PARAMETER;
+ if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
+ return STATUS_INVALID_PARAMETER;
+
/* Initialize the TUI terminal emulator */
if (!TuiInit(Console->CodePage)) return STATUS_UNSUCCESSFUL;
* the console size when we display it with the hardware.
*/
Console->ConsoleSize = PhysicalConsoleSize;
- ConioResizeBuffer(Console, Console->ActiveBuffer, PhysicalConsoleSize);
- Console->ActiveBuffer->DisplayMode |= CONSOLE_FULLSCREEN_MODE;
+ ConioResizeBuffer(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), PhysicalConsoleSize);
+
+ /* The console cannot be resized anymore */
+ Console->FixedSize = TRUE; // MUST be placed AFTER the call to ConioResizeBuffer !!
// ConioResizeTerminal(Console);
/*
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Console Server DLL
+ * FILE: win32ss/user/consrv/graphics.c
+ * PURPOSE: Console Output Functions for graphics-mode screen-buffers
+ * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *
+ * NOTE: See http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/
+ * for more information.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "conoutput.h"
+#include "handle.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+CONSOLE_IO_OBJECT_TYPE
+GRAPHICS_BUFFER_GetType(PCONSOLE_SCREEN_BUFFER This)
+{
+ // return This->Header.Type;
+ return GRAPHICS_BUFFER;
+}
+
+static CONSOLE_SCREEN_BUFFER_VTBL GraphicsVtbl =
+{
+ GRAPHICS_BUFFER_GetType,
+};
+
+
+NTSTATUS
+CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN SIZE_T Size);
+VOID
+CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
+
+
+NTSTATUS
+GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN PGRAPHICS_BUFFER_INFO GraphicsInfo)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PGRAPHICS_SCREEN_BUFFER NewBuffer = NULL;
+
+ LARGE_INTEGER SectionSize;
+ ULONG ViewSize = 0;
+ HANDLE ProcessHandle;
+
+ if (Buffer == NULL || Console == NULL || GraphicsInfo == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ *Buffer = NULL;
+
+ Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer,
+ Console,
+ sizeof(GRAPHICS_SCREEN_BUFFER));
+ if (!NT_SUCCESS(Status)) return Status;
+ NewBuffer->Header.Type = GRAPHICS_BUFFER;
+ NewBuffer->Vtbl = &GraphicsVtbl;
+
+ /*
+ * Remember the handle to the process so that we can close or unmap
+ * correctly the allocated resources when the client releases the
+ * screen buffer.
+ */
+ ProcessHandle = CsrGetClientThread()->Process->ProcessHandle;
+ NewBuffer->ClientProcess = ProcessHandle;
+
+ /* Get infos from the graphics buffer information structure */
+ NewBuffer->BitMapInfoLength = GraphicsInfo->Info.dwBitMapInfoLength;
+
+ NewBuffer->BitMapInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, NewBuffer->BitMapInfoLength);
+ if (NewBuffer->BitMapInfo == NULL)
+ {
+ CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Adjust the bitmap height if needed (bottom-top vs. top-bottom). Use always bottom-up. */
+ if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight > 0)
+ GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight = -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
+
+ /* We do not use anything else than uncompressed bitmaps */
+ if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB)
+ {
+ DPRINT1("biCompression == %d != BI_RGB, correct that!\n", GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression);
+ GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB;
+ }
+
+ RtlCopyMemory(NewBuffer->BitMapInfo,
+ GraphicsInfo->Info.lpBitMapInfo,
+ GraphicsInfo->Info.dwBitMapInfoLength);
+
+ NewBuffer->BitMapUsage = GraphicsInfo->Info.dwUsage;
+
+ /* Set the screen buffer size. Fight against overflows. */
+ if ( GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth <= 0xFFFF &&
+ -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight <= 0xFFFF )
+ {
+ /* Be careful about the sign of biHeight */
+ NewBuffer->ScreenBufferSize.X = (SHORT)GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth ;
+ NewBuffer->ScreenBufferSize.Y = (SHORT)-GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
+
+ NewBuffer->OldViewSize = NewBuffer->ViewSize =
+ NewBuffer->OldScreenBufferSize = NewBuffer->ScreenBufferSize;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ ConsoleFreeHeap(NewBuffer->BitMapInfo);
+ CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
+ goto Quit;
+ }
+
+ /*
+ * Create a mutex to synchronize bitmap memory access
+ * between ourselves and the client.
+ */
+ Status = NtCreateMutant(&NewBuffer->Mutex, MUTANT_ALL_ACCESS, NULL, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtCreateMutant() failed: %lu\n", Status);
+ ConsoleFreeHeap(NewBuffer->BitMapInfo);
+ CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
+ goto Quit;
+ }
+
+ /*
+ * Duplicate the Mutex for the client. We must keep a trace of it
+ * so that we can close it when the client releases the screen buffer.
+ */
+ Status = NtDuplicateObject(NtCurrentProcess(),
+ NewBuffer->Mutex,
+ ProcessHandle,
+ &NewBuffer->ClientMutex,
+ 0, 0, DUPLICATE_SAME_ACCESS);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
+ NtClose(NewBuffer->Mutex);
+ ConsoleFreeHeap(NewBuffer->BitMapInfo);
+ CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
+ goto Quit;
+ }
+
+ /*
+ * Create a memory section for the bitmap area, to share with the client.
+ */
+ SectionSize.QuadPart = NewBuffer->BitMapInfo->bmiHeader.biSizeImage;
+ Status = NtCreateSection(&NewBuffer->hSection,
+ SECTION_ALL_ACCESS,
+ NULL,
+ &SectionSize,
+ PAGE_READWRITE,
+ SEC_COMMIT,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status);
+ NtClose(NewBuffer->ClientMutex);
+ NtClose(NewBuffer->Mutex);
+ ConsoleFreeHeap(NewBuffer->BitMapInfo);
+ CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
+ goto Quit;
+ }
+
+ /*
+ * Create a view for our needs.
+ */
+ ViewSize = 0;
+ NewBuffer->BitMap = NULL;
+ Status = NtMapViewOfSection(NewBuffer->hSection,
+ NtCurrentProcess(),
+ (PVOID*)&NewBuffer->BitMap,
+ 0,
+ 0,
+ NULL,
+ &ViewSize,
+ ViewUnmap,
+ 0,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
+ NtClose(NewBuffer->hSection);
+ NtClose(NewBuffer->ClientMutex);
+ NtClose(NewBuffer->Mutex);
+ ConsoleFreeHeap(NewBuffer->BitMapInfo);
+ CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
+ goto Quit;
+ }
+
+ /*
+ * Create a view for the client. We must keep a trace of it so that
+ * we can unmap it when the client releases the screen buffer.
+ */
+ ViewSize = 0;
+ NewBuffer->ClientBitMap = NULL;
+ Status = NtMapViewOfSection(NewBuffer->hSection,
+ ProcessHandle,
+ (PVOID*)&NewBuffer->ClientBitMap,
+ 0,
+ 0,
+ NULL,
+ &ViewSize,
+ ViewUnmap,
+ 0,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
+ NtUnmapViewOfSection(NtCurrentProcess(), NewBuffer->BitMap);
+ NtClose(NewBuffer->hSection);
+ NtClose(NewBuffer->ClientMutex);
+ NtClose(NewBuffer->Mutex);
+ ConsoleFreeHeap(NewBuffer->BitMapInfo);
+ CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
+ goto Quit;
+ }
+
+ NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0;
+ NewBuffer->VirtualY = 0;
+
+ NewBuffer->CursorBlinkOn = FALSE;
+ NewBuffer->ForceCursorOff = TRUE;
+ NewBuffer->CursorInfo.bVisible = FALSE;
+ NewBuffer->CursorInfo.dwSize = 0;
+ NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0;
+
+ NewBuffer->Mode = 0;
+
+ *Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer;
+ Status = STATUS_SUCCESS;
+
+Quit:
+ return Status;
+}
+
+VOID
+GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
+{
+ PGRAPHICS_SCREEN_BUFFER Buff = (PGRAPHICS_SCREEN_BUFFER)Buffer;
+
+ /*
+ * IMPORTANT !! Reinitialize the type so that we don't enter a recursive
+ * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy.
+ */
+ Buffer->Header.Type = SCREEN_BUFFER;
+
+ /*
+ * Uninitialize the graphics screen buffer
+ * in the reverse way we initialized it.
+ */
+ NtUnmapViewOfSection(Buff->ClientProcess, Buff->ClientBitMap);
+ NtUnmapViewOfSection(NtCurrentProcess(), Buff->BitMap);
+ NtClose(Buff->hSection);
+ NtClose(Buff->ClientMutex);
+ NtClose(Buff->Mutex);
+ ConsoleFreeHeap(Buff->BitMapInfo);
+
+ CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
+}
+
+/* EOF */
/* If the last handle to a screen buffer is closed, delete it... */
if (AdjustHandleCounts(Entry, -1) == 0)
{
- if (Object->Type == SCREEN_BUFFER)
+ if (Object->Type == TEXTMODE_BUFFER || Object->Type == GRAPHICS_BUFFER)
{
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
/* ...unless it's the only buffer left. Windows allows deletion
{
DPRINT("Closing the input buffer\n");
}
+ else
+ {
+ DPRINT1("Invalid object type %d\n", Object->Type);
+ }
}
/// LOCK /// LeaveCriticalSection(&Console->Lock);
if ( HandleEntry == NULL ||
ObjectEntry == NULL ||
(HandleEntry->Access & Access) == 0 ||
- (Type != 0 && ObjectEntry->Type != Type) )
+ /*(Type != 0 && ObjectEntry->Type != Type)*/
+ (Type != 0 && (ObjectEntry->Type & Type) == 0) )
{
- DPRINT1("ConSrvGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle, Type, Access);
+ DPRINT1("ConSrvGetObject returning invalid handle (%x) of type %lu with access %lu ; wanted type %lu with access %lu\n", Handle, ObjectEntry->Type, HandleEntry->Access, Type, Access);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
/* Object type magic numbers */
typedef enum _CONSOLE_IO_OBJECT_TYPE
{
- INPUT_BUFFER = 0x01, // --> Input-type handles
- SCREEN_BUFFER = 0x02 // --> Output-type handles
+// ANY_TYPE_BUFFER = 0x00, // --> Match any types of IO handles
+ TEXTMODE_BUFFER = 0x01, // --> Output-type handles for text SBs
+ GRAPHICS_BUFFER = 0x02, // --> Output-type handles for graphics SBs
+ SCREEN_BUFFER = 0x03, // --> Any SB type
+ INPUT_BUFFER = 0x04 // --> Input-type handles
} CONSOLE_IO_OBJECT_TYPE;
typedef struct _CONSOLE_IO_OBJECT
LONG HandleCount;
} CONSOLE_IO_OBJECT, *PCONSOLE_IO_OBJECT;
+
+/******************************************************************************\
+|* *|
+|* Abstract "class" for screen-buffers, be they text-mode or graphics *|
+|* *|
+\******************************************************************************/
+
+/*
+ * See conoutput.c for the implementation
+ */
+
+typedef struct _CONSOLE_SCREEN_BUFFER CONSOLE_SCREEN_BUFFER,
+ *PCONSOLE_SCREEN_BUFFER;
+
+typedef struct _CONSOLE_SCREEN_BUFFER_VTBL
+{
+ CONSOLE_IO_OBJECT_TYPE (*GetType)(PCONSOLE_SCREEN_BUFFER This);
+} CONSOLE_SCREEN_BUFFER_VTBL, *PCONSOLE_SCREEN_BUFFER_VTBL;
+
+#define GetType(This) (This)->Vtbl->GetType(This)
+
+struct _CONSOLE_SCREEN_BUFFER
+{
+ CONSOLE_IO_OBJECT Header; /* Object header - MUST BE IN FIRST PLACE */
+ PCONSOLE_SCREEN_BUFFER_VTBL Vtbl; /* Virtual table */
+
+ LIST_ENTRY ListEntry; /* Entry in console's list of buffers */
+
+ COORD ScreenBufferSize; /* Size of this screen buffer. (Rows, Columns) for text-mode and (Width, Height) for graphics */
+ COORD ViewSize; /* Associated "view" (i.e. console) size */
+
+ COORD OldScreenBufferSize; /* Old size of this screen buffer */
+ COORD OldViewSize; /* Old associated view size */
+
+ COORD ViewOrigin; /* Beginning offset for the actual display area */
+
+/***** Put that VV in TEXTMODE_SCREEN_BUFFER ?? *****/
+ USHORT VirtualY; /* Top row of buffer being displayed, reported to callers */
+
+ COORD CursorPosition; /* Current cursor position */
+ BOOLEAN CursorBlinkOn;
+ BOOLEAN ForceCursorOff;
+// ULONG CursorSize;
+ CONSOLE_CURSOR_INFO CursorInfo; // FIXME: Keep this member or not ??
+/*********************************************/
+
+// WORD ScreenDefaultAttrib; /* Default screen char attribute */
+// WORD PopupDefaultAttrib; /* Default popup char attribute */
+ USHORT Mode; /* Output buffer modes */
+};
+
+
+
+/******************************************************************************\
+|* *|
+|* Text-mode and graphics-mode screen-buffer "classes" *|
+|* *|
+\******************************************************************************/
+
+/*
+ * See text.c for the implementation
+ */
+
/************************************************************************
* Screen buffer structure represents the win32 screen buffer object. *
* Internally, the portion of the buffer being shown CAN loop past the *
* internally, I just wrap back to the top of the buffer. *
************************************************************************/
-typedef struct _CONSOLE_SCREEN_BUFFER
+typedef struct _TEXTMODE_BUFFER_INFO
{
- CONSOLE_IO_OBJECT Header; /* Object header */
- LIST_ENTRY ListEntry; /* Entry in console's list of buffers */
+ COORD ScreenBufferSize;
+ USHORT ScreenAttrib;
+ USHORT PopupAttrib;
+ BOOLEAN IsCursorVisible;
+ ULONG CursorSize;
+} TEXTMODE_BUFFER_INFO, *PTEXTMODE_BUFFER_INFO;
+
+typedef struct _TEXTMODE_SCREEN_BUFFER
+{
+ CONSOLE_SCREEN_BUFFER; /* Screen buffer base class - MUST BE IN FIRST PLACE */
BYTE *Buffer; /* CHAR_INFO */ /* Pointer to screen buffer */
- COORD ScreenBufferSize; /* Size of this screen buffer */
- COORD CursorPosition; /* Current cursor position */
+ WORD ScreenDefaultAttrib; /* Default screen char attribute */
+ WORD PopupDefaultAttrib; /* Default popup char attribute */
+} TEXTMODE_SCREEN_BUFFER, *PTEXTMODE_SCREEN_BUFFER;
- USHORT ShowX, ShowY; /* Beginning offset for the actual display area */
- USHORT VirtualY; /* Top row of buffer being displayed, reported to callers */
- BOOLEAN CursorBlinkOn;
- BOOLEAN ForceCursorOff;
- // ULONG CursorSize;
- CONSOLE_CURSOR_INFO CursorInfo; // FIXME: Keep this member or not ??
+/*
+ * See graphics.c for the implementation
+ */
+
+typedef struct _GRAPHICS_BUFFER_INFO
+{
+ CONSOLE_GRAPHICS_BUFFER_INFO Info;
+} GRAPHICS_BUFFER_INFO, *PGRAPHICS_BUFFER_INFO;
+
+typedef struct _GRAPHICS_SCREEN_BUFFER
+{
+ CONSOLE_SCREEN_BUFFER; /* Screen buffer base class - MUST BE IN FIRST PLACE */
+
+ ULONG BitMapInfoLength; /* Real size of the structure pointed by BitMapInfo */
+ LPBITMAPINFO BitMapInfo; /* Information on the bitmap buffer */
+ ULONG BitMapUsage; /* See the uUsage parameter of GetDIBits */
+ HANDLE hSection; /* Handle to the memory shared section for the bitmap buffer */
+ PVOID BitMap; /* Our bitmap buffer */
+ PVOID ClientBitMap; /* A copy of the client view of our bitmap buffer */
+ HANDLE Mutex; /* Our mutex, used to synchronize read / writes to the bitmap buffer */
+ HANDLE ClientMutex; /* A copy of the client handle to our mutex */
+ HANDLE ClientProcess; /* Handle to the client process who opened the buffer, to unmap the view */
+} GRAPHICS_SCREEN_BUFFER, *PGRAPHICS_SCREEN_BUFFER;
+
- WORD ScreenDefaultAttrib; /* Default screen char attribute */
- WORD PopupDefaultAttrib; /* Default popup char attribute */
- USHORT Mode;
- ULONG DisplayMode;
-} CONSOLE_SCREEN_BUFFER, *PCONSOLE_SCREEN_BUFFER;
typedef struct _CONSOLE_INPUT_BUFFER
{
- CONSOLE_IO_OBJECT Header; /* Object header */
+ CONSOLE_IO_OBJECT Header; /* Object header - MUST BE IN FIRST PLACE */
- ULONG InputBufferSize; /* Size of this input buffer */
- LIST_ENTRY InputEvents; /* List head for input event queue */
- HANDLE ActiveEvent; /* Event set when an input event is added in its queue */
- LIST_ENTRY ReadWaitQueue; /* List head for the queue of read wait blocks */
+ ULONG InputBufferSize; /* Size of this input buffer */
+ LIST_ENTRY InputEvents; /* List head for input event queue */
+ HANDLE ActiveEvent; /* Event set when an input event is added in its queue */
+ LIST_ENTRY ReadWaitQueue; /* List head for the queue of read wait blocks */
- USHORT Mode; /* Console Input Buffer mode flags */
+ USHORT Mode; /* Input buffer modes */
} CONSOLE_INPUT_BUFFER, *PCONSOLE_INPUT_BUFFER;
typedef struct _FRONTEND_VTBL
/*
* Internal interface (functions called by the console server only)
*/
+ // BOOL (WINAPI *Init)();
VOID (WINAPI *CleanupConsole)(struct _CONSOLE* Console);
+ /* Interface used for both text-mode and graphics screen buffers */
+ VOID (WINAPI *DrawRegion)(struct _CONSOLE* Console,
+ SMALL_RECT* Region);
+ /* Interface used only for text-mode screen buffers */
VOID (WINAPI *WriteStream)(struct _CONSOLE* Console,
SMALL_RECT* Block,
SHORT CursorStartX,
UINT ScrolledLines,
CHAR *Buffer,
UINT Length);
- VOID (WINAPI *DrawRegion)(struct _CONSOLE* Console,
- SMALL_RECT* Region);
BOOL (WINAPI *SetCursorInfo)(struct _CONSOLE* Console,
PCONSOLE_SCREEN_BUFFER ScreenBuffer);
BOOL (WINAPI *SetScreenInfo)(struct _CONSOLE* Console,
PCONSOLE_SCREEN_BUFFER ScreenBuffer,
SHORT OldCursorX,
SHORT OldCursorY);
- BOOL (WINAPI *UpdateScreenInfo)(struct _CONSOLE* Console,
- PCONSOLE_SCREEN_BUFFER ScreenBuffer);
- BOOL (WINAPI *IsBufferResizeSupported)(struct _CONSOLE* Console);
VOID (WINAPI *ResizeTerminal)(struct _CONSOLE* Console);
BOOL (WINAPI *ProcessKeyCallback)(struct _CONSOLE* Console,
MSG* msg,
HWND (WINAPI *GetConsoleWindowHandle)(struct _CONSOLE* Console);
VOID (WINAPI *GetLargestConsoleWindowSize)(struct _CONSOLE* Console,
PCOORD pSize);
-
+ ULONG (WINAPI *GetDisplayMode)(struct _CONSOLE* Console);
+ BOOL (WINAPI *SetDisplayMode)(struct _CONSOLE* Console,
+ ULONG NewMode);
+
+#if 0 // Possible future front-end interface
+ BOOL (WINAPI *GetFrontEndProperty)(struct _CONSOLE* Console,
+ ULONG Flag,
+ PVOID Info,
+ ULONG Size);
+ BOOL (WINAPI *SetFrontEndProperty)(struct _CONSOLE* Console,
+ ULONG Flag,
+ PVOID Info /*,
+ ULONG Size */);
+#endif
} FRONTEND_VTBL, *PFRONTEND_VTBL;
typedef struct _FRONTEND_IFACE
FRONTEND_IFACE TermIFace; /* Frontend-specific interface */
/**************************** Input buffer and data ***************************/
- CONSOLE_INPUT_BUFFER InputBuffer; /* Input buffer of the console */
+ CONSOLE_INPUT_BUFFER InputBuffer; /* Input buffer of the console */
+ /** Put those things in TEXTMODE_SCREEN_BUFFER ?? **/
PWCHAR LineBuffer; /* Current line being input, in line buffered mode */
WORD LineMaxSize; /* Maximum size of line in characters (including CR+LF) */
WORD LineSize; /* Current size of line */
BOOLEAN LineUpPressed;
BOOLEAN LineInsertToggle; /* Replace character over cursor instead of inserting */
ULONG LineWakeupMask; /* Bitmap of which control characters will end line input */
+ /***************************************************/
BOOLEAN QuickEdit;
BOOLEAN InsertMode;
HANDLE UnpauseEvent;
LIST_ENTRY WriteWaitQueue; /* List head for the queue of write wait blocks */
- ULONG HardwareState; /* _GDI_MANAGED, _DIRECT */
-
/**************************** Aliases and Histories ***************************/
struct _ALIAS_HEADER *Aliases;
LIST_ENTRY HistoryBuffers;
BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */
/****************************** Other properties ******************************/
- UNICODE_STRING OriginalTitle; /* Original title of console, the one when the console leader is launched. Always NULL-terminated */
+ UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */
UNICODE_STRING Title; /* Title of console. Always NULL-terminated */
-/* SIZE */ COORD ConsoleSize; /* The size of the console */
+ COORD ConsoleSize; /* The current size of the console, for text-mode only */
+ BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
+
COLORREF Colors[16]; /* Colour palette */
} CONSOLE, *PCONSOLE;
PINPUT_RECORD InputEvent);
/* conoutput.c */
+#define ConioInitRect(Rect, top, left, bottom, right) \
+do { \
+ ((Rect)->Top) = top; \
+ ((Rect)->Left) = left; \
+ ((Rect)->Bottom) = bottom; \
+ ((Rect)->Right) = right; \
+} while (0)
+#define ConioIsRectEmpty(Rect) \
+ (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
#define ConioRectHeight(Rect) \
(((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1)
#define ConioRectWidth(Rect) \
(((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
-PBYTE FASTCALL ConioCoordToPointer(PCONSOLE_SCREEN_BUFFER Buf,
- ULONG X,
- ULONG Y);
+PBYTE ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y);
VOID FASTCALL ConioDrawConsole(PCONSOLE Console);
-NTSTATUS FASTCALL ConioResizeBuffer(PCONSOLE Console,
- PCONSOLE_SCREEN_BUFFER ScreenBuffer,
- COORD Size);
-NTSTATUS FASTCALL ConioWriteConsole(PCONSOLE Console,
- PCONSOLE_SCREEN_BUFFER Buff,
- CHAR *Buffer,
- DWORD Length,
- BOOL Attrib);
+NTSTATUS ConioResizeBuffer(PCONSOLE Console,
+ PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
+ COORD Size);
+NTSTATUS ConioWriteConsole(PCONSOLE Console,
+ PTEXTMODE_SCREEN_BUFFER Buff,
+ CHAR *Buffer,
+ DWORD Length,
+ BOOL Attrib);
DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console,
DWORD Scale);
ULONG NumberOfHistoryBuffers;
BOOLEAN HistoryNoDup;
-/* BOOLEAN */ ULONG FullScreen; /* Give the type of console: GUI (windowed) or TUI (fullscreen) */
BOOLEAN QuickEdit;
BOOLEAN InsertMode;
- ULONG InputBufferSize;
- COORD ScreenBufferSize;
-/* SIZE */ COORD ConsoleSize; /* The size of the console */
+ ULONG InputBufferSize;
+ COORD ScreenBufferSize;
+ COORD ConsoleSize; /* The size of the console */
BOOLEAN CursorBlinkOn;
BOOLEAN ForceCursorOff;
BOOLEAN AppliedConfig;
DWORD ActiveStaticControl;
- CONSOLE_INFO ci; /* Console-specific informations */
+ CONSOLE_INFO ci; /* Console-specific informations */
TERMINAL_INFO TerminalInfo; /* Frontend-specific parameters */
} CONSOLE_PROPS, *PCONSOLE_PROPS;
SrvGetConsoleTitle,
SrvSetConsoleTitle,
SrvCreateConsoleScreenBuffer,
- // SrvInvalidateBitMapRect,
+ SrvInvalidateBitMapRect,
// SrvVDMConsoleOperation,
// SrvSetConsoleCursor,
// SrvShowConsoleCursor,
FALSE, // SrvGetConsoleTitle,
FALSE, // SrvSetConsoleTitle,
FALSE, // SrvCreateConsoleScreenBuffer,
- // FALSE, // SrvInvalidateBitMapRect,
+ FALSE, // SrvInvalidateBitMapRect,
// FALSE, // SrvVDMConsoleOperation,
// FALSE, // SrvSetConsoleCursor,
// FALSE, // SrvShowConsoleCursor,
"GetConsoleTitle",
"SetConsoleTitle",
"CreateConsoleScreenBuffer",
- // "InvalidateBitMapRect",
+ "InvalidateBitMapRect",
// "VDMConsoleOperation",
// "SetConsoleCursor",
// "ShowConsoleCursor",
/* Couldn't find the buffer, create a new one */
Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName.Length);
- if (!Hist)
- return NULL;
+ if (!Hist) return NULL;
Hist->MaxEntries = Console->HistoryBufferSize;
Hist->NumEntries = 0;
Hist->Entries = ConsoleAllocHeap(0, Hist->MaxEntries * sizeof(UNICODE_STRING));
static VOID
LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Insertion)
{
+ PTEXTMODE_SCREEN_BUFFER ActiveBuffer;
UINT Pos = Console->LinePos;
UINT NewSize = Console->LineSize - NumToDelete + NumToInsert;
UINT i;
+ if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER) return;
+ ActiveBuffer = (PTEXTMODE_SCREEN_BUFFER)Console->ActiveBuffer;
+
/* Make sure there's always enough room for ending \r\n */
if (NewSize + 2 > Console->LineMaxSize)
return;
WideCharToMultiByte(Console->OutputCodePage, 0,
&Console->LineBuffer[i], 1,
&AsciiChar, 1, NULL, NULL);
- ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
+ ConioWriteConsole(Console, ActiveBuffer, &AsciiChar, 1, TRUE);
}
for (; i < Console->LineSize; i++)
{
- ConioWriteConsole(Console, Console->ActiveBuffer, " ", 1, TRUE);
+ ConioWriteConsole(Console, ActiveBuffer, " ", 1, TRUE);
}
Console->LinePos = i;
}
LineInputSetPos(Console, Console->LineSize);
Console->LineBuffer[Console->LineSize++] = L'\r';
if (Console->InputBuffer.Mode & ENABLE_ECHO_INPUT)
- ConioWriteConsole(Console, Console->ActiveBuffer, "\r", 1, TRUE);
+ {
+ if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
+ {
+ ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), "\r", 1, TRUE);
+ }
+ }
/* Add \n if processed input. There should usually be room for it,
* but an exception to the rule exists: the buffer could have been
{
Console->LineBuffer[Console->LineSize++] = L'\n';
if (Console->InputBuffer.Mode & ENABLE_ECHO_INPUT)
- ConioWriteConsole(Console, Console->ActiveBuffer, "\n", 1, TRUE);
+ {
+ if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
+ {
+ ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), "\n", 1, TRUE);
+ }
+ }
}
Console->LineComplete = TRUE;
Console->LinePos = 0;
ConsoleInfo->HistoryNoDup = (BOOLEAN)Value;
RetVal = TRUE;
}
- else if (!wcscmp(szValueName, L"FullScreen"))
- {
- ConsoleInfo->FullScreen = Value;
- RetVal = TRUE;
- }
else if (!wcscmp(szValueName, L"QuickEdit"))
{
ConsoleInfo->QuickEdit = (BOOLEAN)Value;
Storage = ConsoleInfo->HistoryNoDup;
SetConsoleSetting(L"HistoryNoDup", REG_DWORD, sizeof(DWORD), &Storage, FALSE);
- Storage = ConsoleInfo->FullScreen;
- SetConsoleSetting(L"FullScreen", REG_DWORD, sizeof(DWORD), &Storage, FALSE);
-
Storage = ConsoleInfo->QuickEdit;
SetConsoleSetting(L"QuickEdit", REG_DWORD, sizeof(DWORD), &Storage, FALSE);
ConsoleInfo->NumberOfHistoryBuffers = 4;
ConsoleInfo->HistoryNoDup = FALSE;
- ConsoleInfo->FullScreen = FALSE;
ConsoleInfo->QuickEdit = FALSE;
ConsoleInfo->InsertMode = TRUE;
// ConsoleInfo->InputBufferSize;
+
+ // Rule: ScreenBufferSize >= ConsoleSize
ConsoleInfo->ScreenBufferSize.X = 80;
ConsoleInfo->ScreenBufferSize.Y = 300;
ConsoleInfo->ConsoleSize.X = 80;
IN PCONSOLE_INFO ConsoleInfo)
{
PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
- COORD BufSize;
- BOOL SizeChanged = FALSE;
-
- /*
- * Apply full-screen mode.
- */
- if (ConsoleInfo->FullScreen)
- Console->ActiveBuffer->DisplayMode |= CONSOLE_FULLSCREEN_MODE;
- else
- Console->ActiveBuffer->DisplayMode &= ~CONSOLE_FULLSCREEN_MODE;
- // TODO: Apply it really
/*
* Apply terminal-edition settings:
* Apply foreground and background colors for both screen and popup
* and copy the new palette.
*/
- ActiveBuffer->ScreenDefaultAttrib = ConsoleInfo->ScreenAttrib;
- ActiveBuffer->PopupDefaultAttrib = ConsoleInfo->PopupAttrib;
- memcpy(Console->Colors, ConsoleInfo->Colors, sizeof(s_Colors)); // FIXME: Possible buffer overflow if s_colors is bigger than pConInfo->Colors.
+ if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
+ {
+ PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
+
+ Buffer->ScreenDefaultAttrib = ConsoleInfo->ScreenAttrib;
+ Buffer->PopupDefaultAttrib = ConsoleInfo->PopupAttrib;
+ }
+ else // if (Console->ActiveBuffer->Header.Type == GRAPHICS_BUFFER)
+ {
+ }
+
+ // FIXME: Possible buffer overflow if s_colors is bigger than pConInfo->Colors.
+ memcpy(Console->Colors, ConsoleInfo->Colors, sizeof(s_Colors));
// TODO: Really update the screen attributes as FillConsoleOutputAttribute does.
ActiveBuffer->CursorInfo.bVisible = (ConsoleInfo->CursorSize != 0);
ActiveBuffer->CursorInfo.dwSize = min(max(ConsoleInfo->CursorSize, 0), 100);
- /* Resize the console */
- if (ConsoleInfo->ConsoleSize.X != Console->ConsoleSize.X ||
- ConsoleInfo->ConsoleSize.Y != Console->ConsoleSize.Y)
+ if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
{
- Console->ConsoleSize = ConsoleInfo->ConsoleSize;
- SizeChanged = TRUE;
- }
+ PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
+ COORD BufSize;
- /* Resize its active screen-buffer */
- BufSize = ConsoleInfo->ScreenBufferSize;
- if (BufSize.X != ActiveBuffer->ScreenBufferSize.X ||
- BufSize.Y != ActiveBuffer->ScreenBufferSize.Y)
- {
- if (NT_SUCCESS(ConioResizeBuffer(Console, ActiveBuffer, BufSize)))
- SizeChanged = TRUE;
+ /* Resize its active screen-buffer */
+ BufSize = ConsoleInfo->ScreenBufferSize;
+
+ if (Console->FixedSize)
+ {
+ /*
+ * The console is in fixed-size mode, so we cannot resize anything
+ * at the moment. However, keep those settings somewhere so that
+ * we can try to set them up when we will be allowed to do so.
+ */
+ if (ConsoleInfo->ConsoleSize.X != Buffer->OldViewSize.X ||
+ ConsoleInfo->ConsoleSize.Y != Buffer->OldViewSize.Y)
+ {
+ Buffer->OldViewSize = ConsoleInfo->ConsoleSize;
+ }
+
+ /* Buffer size is not allowed to be smaller than the view size */
+ if (BufSize.X >= Buffer->OldViewSize.X && BufSize.Y >= Buffer->OldViewSize.Y)
+ {
+ if (BufSize.X != Buffer->OldScreenBufferSize.X ||
+ BufSize.Y != Buffer->OldScreenBufferSize.Y)
+ {
+ /*
+ * The console is in fixed-size mode, so we cannot resize anything
+ * at the moment. However, keep those settings somewhere so that
+ * we can try to set them up when we will be allowed to do so.
+ */
+ Buffer->OldScreenBufferSize = BufSize;
+ }
+ }
+ }
+ else
+ {
+ BOOL SizeChanged = FALSE;
+
+ /* Resize the console */
+ if (ConsoleInfo->ConsoleSize.X != Buffer->ViewSize.X ||
+ ConsoleInfo->ConsoleSize.Y != Buffer->ViewSize.Y)
+ {
+ Buffer->ViewSize = ConsoleInfo->ConsoleSize;
+ SizeChanged = TRUE;
+ }
+
+ /* Resize the screen-buffer */
+ if (BufSize.X != Buffer->ScreenBufferSize.X ||
+ BufSize.Y != Buffer->ScreenBufferSize.Y)
+ {
+ if (NT_SUCCESS(ConioResizeBuffer(Console, Buffer, BufSize)))
+ SizeChanged = TRUE;
+ }
+
+ if (SizeChanged) ConioResizeTerminal(Console);
+ }
}
+ else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
+ {
+ PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer;
- if (SizeChanged) ConioResizeTerminal(Console);
+ /*
+ * In any case we do NOT modify the size of the graphics screen-buffer.
+ * We just allow resizing the view only if the new size is smaller
+ * than the older one.
+ */
+
+ if (Console->FixedSize)
+ {
+ /*
+ * The console is in fixed-size mode, so we cannot resize anything
+ * at the moment. However, keep those settings somewhere so that
+ * we can try to set them up when we will be allowed to do so.
+ */
+ if (ConsoleInfo->ConsoleSize.X <= Buffer->ViewSize.X ||
+ ConsoleInfo->ConsoleSize.Y <= Buffer->ViewSize.Y)
+ {
+ Buffer->OldViewSize = ConsoleInfo->ConsoleSize;
+ }
+ }
+ else
+ {
+ /* Resize the view if its size is bigger than the specified size */
+ if (ConsoleInfo->ConsoleSize.X <= Buffer->ViewSize.X ||
+ ConsoleInfo->ConsoleSize.Y <= Buffer->ViewSize.Y)
+ {
+ Buffer->ViewSize = ConsoleInfo->ConsoleSize;
+ // SizeChanged = TRUE;
+ }
+ }
+ }
}
/* EOF */
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Console Server DLL
+ * FILE: win32ss/user/consrv/text.c
+ * PURPOSE: Console Output Functions for text-mode screen-buffers
+ * PROGRAMMERS: Jeffrey Morlan
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "conoutput.h"
+#include "handle.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/*
+// Define wmemset(...)
+#include <wchar.h>
+#define HAVE_WMEMSET
+*/
+
+
+/* GLOBALS ********************************************************************/
+
+#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 **********************************************************/
+
+CONSOLE_IO_OBJECT_TYPE
+TEXTMODE_BUFFER_GetType(PCONSOLE_SCREEN_BUFFER This)
+{
+ // return This->Header.Type;
+ return TEXTMODE_BUFFER;
+}
+
+static CONSOLE_SCREEN_BUFFER_VTBL TextVtbl =
+{
+ TEXTMODE_BUFFER_GetType,
+};
+
+
+static VOID FASTCALL
+ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff);
+
+
+NTSTATUS
+CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN SIZE_T Size);
+VOID
+CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
+
+
+NTSTATUS
+TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
+ IN OUT PCONSOLE Console,
+ IN PTEXTMODE_BUFFER_INFO TextModeInfo)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PTEXTMODE_SCREEN_BUFFER NewBuffer = NULL;
+
+ if (Console == NULL || Buffer == NULL || TextModeInfo == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ *Buffer = NULL;
+
+ Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer,
+ Console,
+ sizeof(TEXTMODE_SCREEN_BUFFER));
+ if (!NT_SUCCESS(Status)) return Status;
+ NewBuffer->Header.Type = TEXTMODE_BUFFER;
+ NewBuffer->Vtbl = &TextVtbl;
+
+ NewBuffer->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
+ 2 * TextModeInfo->ScreenBufferSize.X
+ * TextModeInfo->ScreenBufferSize.Y);
+ if (NewBuffer->Buffer == NULL)
+ {
+ CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ NewBuffer->ScreenBufferSize = NewBuffer->OldScreenBufferSize
+ = TextModeInfo->ScreenBufferSize;
+ NewBuffer->ViewSize = NewBuffer->OldViewSize
+ = Console->ConsoleSize;
+
+ NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0;
+ NewBuffer->VirtualY = 0;
+
+ NewBuffer->CursorBlinkOn = NewBuffer->ForceCursorOff = FALSE;
+ NewBuffer->CursorInfo.bVisible = (TextModeInfo->IsCursorVisible && (TextModeInfo->CursorSize != 0));
+ NewBuffer->CursorInfo.dwSize = min(max(TextModeInfo->CursorSize, 0), 100);
+
+ NewBuffer->ScreenDefaultAttrib = TextModeInfo->ScreenAttrib;
+ NewBuffer->PopupDefaultAttrib = TextModeInfo->PopupAttrib;
+
+ /* Initialize buffer to be empty with default attributes */
+ for (NewBuffer->CursorPosition.Y = 0 ; NewBuffer->CursorPosition.Y < NewBuffer->ScreenBufferSize.Y; NewBuffer->CursorPosition.Y++)
+ {
+ ClearLineBuffer(NewBuffer);
+ }
+ NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0;
+
+ NewBuffer->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
+
+ *Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer;
+ return STATUS_SUCCESS;
+}
+
+VOID
+TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
+{
+ PTEXTMODE_SCREEN_BUFFER Buff = (PTEXTMODE_SCREEN_BUFFER)Buffer;
+
+ /*
+ * IMPORTANT !! Reinitialize the type so that we don't enter a recursive
+ * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy.
+ */
+ Buffer->Header.Type = SCREEN_BUFFER;
+
+ ConsoleFreeHeap(Buff->Buffer);
+
+ CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
+}
+
+
+PBYTE
+ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y)
+{
+ return &Buff->Buffer[2 * (((Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y) * Buff->ScreenBufferSize.X + X)];
+}
+
+static VOID FASTCALL
+ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff)
+{
+ PBYTE Ptr = ConioCoordToPointer(Buff, 0, Buff->CursorPosition.Y);
+ SHORT Pos;
+
+ for (Pos = 0; Pos < Buff->ScreenBufferSize.X; Pos++)
+ {
+ /* Fill the cell */
+ *Ptr++ = ' ';
+ *Ptr++ = (BYTE)Buff->ScreenDefaultAttrib;
+ }
+}
+
+static __inline BOOLEAN ConioGetIntersection(
+ SMALL_RECT* Intersection,
+ SMALL_RECT* Rect1,
+ SMALL_RECT* Rect2)
+{
+ if ( ConioIsRectEmpty(Rect1) ||
+ ConioIsRectEmpty(Rect2) ||
+ (Rect1->Top > Rect2->Bottom) ||
+ (Rect1->Left > Rect2->Right) ||
+ (Rect1->Bottom < Rect2->Top) ||
+ (Rect1->Right < Rect2->Left) )
+ {
+ /* The rectangles do not intersect */
+ ConioInitRect(Intersection, 0, -1, 0, -1);
+ return FALSE;
+ }
+
+ ConioInitRect(Intersection,
+ max(Rect1->Top, Rect2->Top),
+ max(Rect1->Left, Rect2->Left),
+ min(Rect1->Bottom, Rect2->Bottom),
+ min(Rect1->Right, Rect2->Right));
+
+ return TRUE;
+}
+
+static __inline BOOLEAN ConioGetUnion(
+ SMALL_RECT* Union,
+ SMALL_RECT* Rect1,
+ SMALL_RECT* Rect2)
+{
+ if (ConioIsRectEmpty(Rect1))
+ {
+ if (ConioIsRectEmpty(Rect2))
+ {
+ ConioInitRect(Union, 0, -1, 0, -1);
+ return FALSE;
+ }
+ else
+ {
+ *Union = *Rect2;
+ }
+ }
+ else if (ConioIsRectEmpty(Rect2))
+ {
+ *Union = *Rect1;
+ }
+ else
+ {
+ ConioInitRect(Union,
+ min(Rect1->Top, Rect2->Top),
+ min(Rect1->Left, Rect2->Left),
+ max(Rect1->Bottom, Rect2->Bottom),
+ max(Rect1->Right, Rect2->Right));
+ }
+
+ return TRUE;
+}
+
+static VOID FASTCALL
+ConioComputeUpdateRect(PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* UpdateRect, PCOORD Start, UINT Length)
+{
+ if (Buff->ScreenBufferSize.X <= Start->X + Length)
+ {
+ UpdateRect->Left = 0;
+ }
+ else
+ {
+ UpdateRect->Left = Start->X;
+ }
+ if (Buff->ScreenBufferSize.X <= Start->X + Length)
+ {
+ UpdateRect->Right = Buff->ScreenBufferSize.X - 1;
+ }
+ else
+ {
+ UpdateRect->Right = Start->X + Length - 1;
+ }
+ UpdateRect->Top = Start->Y;
+ UpdateRect->Bottom = Start->Y + (Start->X + Length - 1) / Buff->ScreenBufferSize.X;
+ if (Buff->ScreenBufferSize.Y <= UpdateRect->Bottom)
+ {
+ UpdateRect->Bottom = Buff->ScreenBufferSize.Y - 1;
+ }
+}
+
+/*
+ * Move from one rectangle to another. We must be careful about the order that
+ * this is done, to avoid overwriting parts of the source before they are moved.
+ */
+static VOID FASTCALL
+ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
+ SMALL_RECT* SrcRegion,
+ SMALL_RECT* DstRegion,
+ SMALL_RECT* ClipRegion,
+ WORD Fill)
+{
+ int Width = ConioRectWidth(SrcRegion);
+ int Height = ConioRectHeight(SrcRegion);
+ int SX, SY;
+ int DX, DY;
+ int XDelta, YDelta;
+ int i, j;
+
+ SY = SrcRegion->Top;
+ DY = DstRegion->Top;
+ YDelta = 1;
+ if (SY < DY)
+ {
+ /* Moving down: work from bottom up */
+ SY = SrcRegion->Bottom;
+ DY = DstRegion->Bottom;
+ YDelta = -1;
+ }
+ for (i = 0; i < Height; i++)
+ {
+ PWORD SRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, SY);
+ PWORD DRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, DY);
+
+ SX = SrcRegion->Left;
+ DX = DstRegion->Left;
+ XDelta = 1;
+ if (SX < DX)
+ {
+ /* Moving right: work from right to left */
+ SX = SrcRegion->Right;
+ DX = DstRegion->Right;
+ XDelta = -1;
+ }
+ for (j = 0; j < Width; j++)
+ {
+ WORD Cell = SRow[SX];
+ if (SX >= ClipRegion->Left && SX <= ClipRegion->Right
+ && SY >= ClipRegion->Top && SY <= ClipRegion->Bottom)
+ {
+ SRow[SX] = Fill;
+ }
+ if (DX >= ClipRegion->Left && DX <= ClipRegion->Right
+ && DY >= ClipRegion->Top && DY <= ClipRegion->Bottom)
+ {
+ DRow[DX] = Cell;
+ }
+ SX += XDelta;
+ DX += XDelta;
+ }
+ SY += YDelta;
+ DY += YDelta;
+ }
+}
+
+DWORD FASTCALL
+ConioEffectiveCursorSize(PCONSOLE Console, DWORD Scale)
+{
+ DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100;
+ /* If line input in progress, perhaps adjust for insert toggle */
+ if (Console->LineBuffer && !Console->LineComplete && Console->LineInsertToggle)
+ return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2);
+ return Size;
+}
+
+NTSTATUS
+ConioResizeBuffer(PCONSOLE Console,
+ PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
+ COORD Size)
+{
+ BYTE * Buffer;
+ DWORD Offset = 0;
+ BYTE * OldPtr;
+ USHORT CurrentY;
+ BYTE * OldBuffer;
+#ifdef HAVE_WMEMSET
+ USHORT value = MAKEWORD(' ', ScreenBuffer->ScreenDefaultAttrib);
+#else
+ DWORD i;
+#endif
+ DWORD diff;
+
+ /* Buffer size is not allowed to be smaller than the view size */
+ if (Size.X < ScreenBuffer->ViewSize.X || Size.Y < ScreenBuffer->ViewSize.Y)
+ return STATUS_INVALID_PARAMETER;
+
+ if (Size.X == ScreenBuffer->ScreenBufferSize.X && Size.Y == ScreenBuffer->ScreenBufferSize.Y)
+ {
+ // FIXME: Trigger a buffer resize event ??
+ return STATUS_SUCCESS;
+ }
+
+ if (Console->FixedSize)
+ {
+ /*
+ * The console is in fixed-size mode, so we cannot resize anything
+ * at the moment. However, keep those settings somewhere so that
+ * we can try to set them up when we will be allowed to do so.
+ */
+ ScreenBuffer->OldScreenBufferSize = Size;
+ return STATUS_NOT_SUPPORTED; // STATUS_SUCCESS
+ }
+
+ Buffer = ConsoleAllocHeap(0, Size.X * Size.Y * 2);
+ if (!Buffer) return STATUS_NO_MEMORY;
+
+ DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->ScreenBufferSize.X, ScreenBuffer->ScreenBufferSize.Y, Size.X, Size.Y);
+ OldBuffer = ScreenBuffer->Buffer;
+
+ for (CurrentY = 0; CurrentY < ScreenBuffer->ScreenBufferSize.Y && CurrentY < Size.Y; CurrentY++)
+ {
+ OldPtr = ConioCoordToPointer(ScreenBuffer, 0, CurrentY);
+ if (Size.X <= ScreenBuffer->ScreenBufferSize.X)
+ {
+ /* reduce size */
+ RtlCopyMemory(&Buffer[Offset], OldPtr, Size.X * 2);
+ Offset += (Size.X * 2);
+ }
+ else
+ {
+ /* enlarge size */
+ RtlCopyMemory(&Buffer[Offset], OldPtr, ScreenBuffer->ScreenBufferSize.X * 2);
+ Offset += (ScreenBuffer->ScreenBufferSize.X * 2);
+
+ diff = Size.X - ScreenBuffer->ScreenBufferSize.X;
+ /* zero new part of it */
+#ifdef HAVE_WMEMSET
+ wmemset((PWCHAR)&Buffer[Offset], value, diff);
+#else
+ for (i = 0; i < diff; i++)
+ {
+ Buffer[Offset++] = ' ';
+ Buffer[Offset++] = (BYTE)ScreenBuffer->ScreenDefaultAttrib;
+ }
+#endif
+ }
+ }
+
+ if (Size.Y > ScreenBuffer->ScreenBufferSize.Y)
+ {
+ diff = Size.X * (Size.Y - ScreenBuffer->ScreenBufferSize.Y);
+#ifdef HAVE_WMEMSET
+ wmemset((PWCHAR)&Buffer[Offset], value, diff);
+#else
+ for (i = 0; i < diff; i++)
+ {
+ Buffer[Offset++] = ' ';
+ Buffer[Offset++] = (BYTE)ScreenBuffer->ScreenDefaultAttrib;
+ }
+#endif
+ }
+
+ (void)InterlockedExchangePointer((PVOID volatile*)&ScreenBuffer->Buffer, Buffer);
+ ConsoleFreeHeap(OldBuffer);
+ ScreenBuffer->ScreenBufferSize = ScreenBuffer->OldScreenBufferSize = Size;
+ ScreenBuffer->VirtualY = 0;
+
+ /* Ensure cursor and window are within buffer */
+ if (ScreenBuffer->CursorPosition.X >= Size.X)
+ ScreenBuffer->CursorPosition.X = Size.X - 1;
+ if (ScreenBuffer->CursorPosition.Y >= Size.Y)
+ ScreenBuffer->CursorPosition.Y = Size.Y - 1;
+ if (ScreenBuffer->ViewOrigin.X > Size.X - ScreenBuffer->ViewSize.X)
+ ScreenBuffer->ViewOrigin.X = Size.X - ScreenBuffer->ViewSize.X;
+ if (ScreenBuffer->ViewOrigin.Y > Size.Y - ScreenBuffer->ViewSize.Y)
+ ScreenBuffer->ViewOrigin.Y = Size.Y - ScreenBuffer->ViewSize.Y;
+
+ /*
+ * Trigger a buffer resize event
+ */
+ if (Console->InputBuffer.Mode & ENABLE_WINDOW_INPUT)
+ {
+ INPUT_RECORD er;
+
+ er.EventType = WINDOW_BUFFER_SIZE_EVENT;
+ er.Event.WindowBufferSizeEvent.dwSize = ScreenBuffer->ScreenBufferSize;
+
+ ConioProcessInputEvent(Console, &er);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static VOID FASTCALL
+ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* UpdateRect, UINT *ScrolledLines)
+{
+ /* If we hit bottom, slide the viewable screen */
+ if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y)
+ {
+ Buff->CursorPosition.Y--;
+ if (++Buff->VirtualY == Buff->ScreenBufferSize.Y)
+ {
+ Buff->VirtualY = 0;
+ }
+ (*ScrolledLines)++;
+ ClearLineBuffer(Buff);
+ if (UpdateRect->Top != 0)
+ {
+ UpdateRect->Top--;
+ }
+ }
+ UpdateRect->Left = 0;
+ UpdateRect->Right = Buff->ScreenBufferSize.X - 1;
+ UpdateRect->Bottom = Buff->CursorPosition.Y;
+}
+
+NTSTATUS
+ConioWriteConsole(PCONSOLE Console,
+ PTEXTMODE_SCREEN_BUFFER Buff,
+ CHAR *Buffer,
+ DWORD Length,
+ BOOL Attrib)
+{
+ UINT i;
+ PBYTE Ptr;
+ SMALL_RECT UpdateRect;
+ SHORT CursorStartX, CursorStartY;
+ UINT ScrolledLines;
+
+ CursorStartX = Buff->CursorPosition.X;
+ CursorStartY = Buff->CursorPosition.Y;
+ UpdateRect.Left = Buff->ScreenBufferSize.X;
+ UpdateRect.Top = Buff->CursorPosition.Y;
+ UpdateRect.Right = -1;
+ UpdateRect.Bottom = Buff->CursorPosition.Y;
+ ScrolledLines = 0;
+
+ for (i = 0; i < Length; i++)
+ {
+ /*
+ * If we are in processed mode, interpret special characters and
+ * display them correctly. Otherwise, just put them into the buffer.
+ */
+ if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
+ {
+ /* --- CR --- */
+ if (Buffer[i] == '\r')
+ {
+ Buff->CursorPosition.X = 0;
+ UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
+ UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
+ continue;
+ }
+ /* --- LF --- */
+ else if (Buffer[i] == '\n')
+ {
+ Buff->CursorPosition.X = 0;
+ ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
+ continue;
+ }
+ /* --- BS --- */
+ else if (Buffer[i] == '\b')
+ {
+ /* 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)
+ {
+ /* slide virtual position up */
+ Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1;
+ Buff->CursorPosition.Y--;
+ UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y);
+ }
+ else
+ {
+ Buff->CursorPosition.X--;
+ }
+ Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+ Ptr[0] = ' ';
+ Ptr[1] = (BYTE)Buff->ScreenDefaultAttrib;
+ UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
+ UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
+ }
+ continue;
+ }
+ /* --- TAB --- */
+ else if (Buffer[i] == '\t')
+ {
+ UINT EndX;
+
+ UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
+ EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1);
+ EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X);
+ Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+ while (Buff->CursorPosition.X < EndX)
+ {
+ *Ptr++ = ' ';
+ *Ptr++ = (BYTE)Buff->ScreenDefaultAttrib;
+ Buff->CursorPosition.X++;
+ }
+ UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1);
+ if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
+ {
+ if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
+ {
+ Buff->CursorPosition.X = 0;
+ ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
+ }
+ else
+ {
+ Buff->CursorPosition.X--;
+ }
+ }
+ continue;
+ }
+ // /* --- BEL ---*/
+ // else if (Buffer[i] == '\a')
+ // {
+ // // FIXME: This MUST BE moved to the terminal emulator frontend!!
+ // DPRINT1("Bell\n");
+ // // SendNotifyMessage(Console->hWindow, PM_CONSOLE_BEEP, 0, 0);
+ // continue;
+ // }
+ }
+ 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[0] = Buffer[i];
+ if (Attrib)
+ {
+ Ptr[1] = (BYTE)Buff->ScreenDefaultAttrib;
+ }
+ Buff->CursorPosition.X++;
+ if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
+ {
+ if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
+ {
+ Buff->CursorPosition.X = 0;
+ ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
+ }
+ else
+ {
+ Buff->CursorPosition.X = CursorStartX;
+ }
+ }
+ }
+
+ if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
+ {
+ ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
+ ScrolledLines, Buffer, Length);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
+ IN PCSR_THREAD ClientThread,
+ IN BOOL CreateWaitBlock OPTIONAL);
+
+// Wait function CSR_WAIT_FUNCTION
+static BOOLEAN
+WriteConsoleThread(IN PLIST_ENTRY WaitList,
+ IN PCSR_THREAD WaitThread,
+ IN PCSR_API_MESSAGE WaitApiMessage,
+ IN PVOID WaitContext,
+ IN PVOID WaitArgument1,
+ IN PVOID WaitArgument2,
+ IN ULONG WaitFlags)
+{
+ NTSTATUS Status;
+
+ DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
+
+ /*
+ * If we are notified of the process termination via a call
+ * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
+ * CsrDestroyThread, just return.
+ */
+ if (WaitFlags & CsrProcessTerminating)
+ {
+ Status = STATUS_THREAD_IS_TERMINATING;
+ goto Quit;
+ }
+
+ Status = DoWriteConsole(WaitApiMessage,
+ WaitThread,
+ FALSE);
+
+Quit:
+ if (Status != STATUS_PENDING)
+ {
+ WaitApiMessage->Status = Status;
+ }
+
+ return (Status == STATUS_PENDING ? FALSE : TRUE);
+}
+
+static NTSTATUS
+DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
+ IN PCSR_THREAD ClientThread,
+ IN BOOL CreateWaitBlock OPTIONAL)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
+ PCONSOLE Console;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+ PCHAR Buffer;
+ DWORD Written = 0;
+ ULONG Length;
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->OutputHandle, &Buff, GENERIC_WRITE, FALSE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
+ if (Console->PauseFlags && Console->UnpauseEvent != NULL)
+ {
+ if (CreateWaitBlock)
+ {
+ if (!CsrCreateWait(&Console->WriteWaitQueue,
+ WriteConsoleThread,
+ ClientThread,
+ ApiMessage,
+ NULL,
+ NULL))
+ {
+ /* Fail */
+ ConSrvReleaseScreenBuffer(Buff, FALSE);
+ return STATUS_NO_MEMORY;
+ }
+ }
+
+ /* Wait until we un-pause the console */
+ Status = STATUS_PENDING;
+ }
+ else
+ {
+ if (WriteConsoleRequest->Unicode)
+ {
+ Length = WideCharToMultiByte(Console->OutputCodePage, 0,
+ (PWCHAR)WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NrCharactersToWrite,
+ NULL, 0, NULL, NULL);
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
+ if (Buffer)
+ {
+ WideCharToMultiByte(Console->OutputCodePage, 0,
+ (PWCHAR)WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NrCharactersToWrite,
+ Buffer, Length, NULL, NULL);
+ }
+ else
+ {
+ Status = STATUS_NO_MEMORY;
+ }
+ }
+ else
+ {
+ Buffer = (PCHAR)WriteConsoleRequest->Buffer;
+ }
+
+ if (Buffer)
+ {
+ if (NT_SUCCESS(Status))
+ {
+ Status = ConioWriteConsole(Console, Buff, Buffer,
+ WriteConsoleRequest->NrCharactersToWrite, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ Written = WriteConsoleRequest->NrCharactersToWrite;
+ }
+ }
+
+ if (WriteConsoleRequest->Unicode)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+ }
+
+ WriteConsoleRequest->NrCharactersWritten = Written;
+ }
+
+ ConSrvReleaseScreenBuffer(Buff, FALSE);
+ return Status;
+}
+
+
+/* PUBLIC SERVER APIS *********************************************************/
+
+CSR_API(SrvReadConsoleOutput)
+{
+ PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ PCHAR_INFO CharInfo;
+ PCHAR_INFO CurCharInfo;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+ SHORT SizeX, SizeY;
+ NTSTATUS Status;
+ COORD BufferSize;
+ COORD BufferCoord;
+ SMALL_RECT ReadRegion;
+ SMALL_RECT ScreenRect;
+ DWORD i;
+ PBYTE Ptr;
+ LONG X, Y;
+ UINT CodePage;
+
+ DPRINT("SrvReadConsoleOutput\n");
+
+ CharInfo = ReadOutputRequest->CharInfo;
+ ReadRegion = ReadOutputRequest->ReadRegion;
+ BufferSize = ReadOutputRequest->BufferSize;
+ BufferCoord = ReadOutputRequest->BufferCoord;
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&ReadOutputRequest->CharInfo,
+ BufferSize.X * BufferSize.Y,
+ sizeof(CHAR_INFO)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = ConSrvGetTextModeBuffer(ProcessData, ReadOutputRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* FIXME: Is this correct? */
+ CodePage = ProcessData->Console->OutputCodePage;
+
+ SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
+ SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion));
+ ReadRegion.Bottom = ReadRegion.Top + SizeY;
+ ReadRegion.Right = ReadRegion.Left + SizeX;
+
+ ConioInitRect(&ScreenRect, 0, 0, Buff->ScreenBufferSize.Y, Buff->ScreenBufferSize.X);
+ if (!ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
+ {
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+ }
+
+ for (i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y)
+ {
+ CurCharInfo = CharInfo + (i * BufferSize.X);
+
+ Ptr = ConioCoordToPointer(Buff, ReadRegion.Left, Y);
+ for (X = ReadRegion.Left; X < ReadRegion.Right; ++X)
+ {
+ if (ReadOutputRequest->Unicode)
+ {
+ // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
+ MultiByteToWideChar(CodePage, 0,
+ (PCHAR)Ptr++, 1,
+ &CurCharInfo->Char.UnicodeChar, 1);
+ }
+ else
+ {
+ CurCharInfo->Char.AsciiChar = *Ptr++;
+ }
+ CurCharInfo->Attributes = *Ptr++;
+ ++CurCharInfo;
+ }
+ }
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+
+ ReadOutputRequest->ReadRegion.Right = ReadRegion.Left + SizeX - 1;
+ ReadOutputRequest->ReadRegion.Bottom = ReadRegion.Top + SizeY - 1;
+ ReadOutputRequest->ReadRegion.Left = ReadRegion.Left;
+ ReadOutputRequest->ReadRegion.Top = ReadRegion.Top;
+
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvWriteConsoleOutput)
+{
+ PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ SHORT i, X, Y, SizeX, SizeY;
+ PCONSOLE Console;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+ SMALL_RECT ScreenBuffer;
+ CHAR_INFO* CurCharInfo;
+ SMALL_RECT WriteRegion;
+ CHAR_INFO* CharInfo;
+ COORD BufferCoord;
+ COORD BufferSize;
+ NTSTATUS Status;
+ PBYTE Ptr;
+
+ DPRINT("SrvWriteConsoleOutput\n");
+
+ BufferSize = WriteOutputRequest->BufferSize;
+ BufferCoord = WriteOutputRequest->BufferCoord;
+ CharInfo = WriteOutputRequest->CharInfo;
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&WriteOutputRequest->CharInfo,
+ BufferSize.X * BufferSize.Y,
+ sizeof(CHAR_INFO)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = ConSrvGetTextModeBuffer(ProcessData,
+ WriteOutputRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ WriteRegion = WriteOutputRequest->WriteRegion;
+
+ SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion));
+ SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion));
+ WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
+ WriteRegion.Right = WriteRegion.Left + SizeX - 1;
+
+ /* Make sure WriteRegion is inside the screen buffer */
+ ConioInitRect(&ScreenBuffer, 0, 0, Buff->ScreenBufferSize.Y - 1, Buff->ScreenBufferSize.X - 1);
+ if (!ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
+ {
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+
+ /* It is okay to have a WriteRegion completely outside the screen buffer.
+ No data is written then. */
+ return STATUS_SUCCESS;
+ }
+
+ for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++)
+ {
+ CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
+ Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y);
+ for (X = WriteRegion.Left; X <= WriteRegion.Right; X++)
+ {
+ CHAR AsciiChar;
+ if (WriteOutputRequest->Unicode)
+ {
+ ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
+ }
+ else
+ {
+ AsciiChar = CurCharInfo->Char.AsciiChar;
+ }
+ *Ptr++ = AsciiChar;
+ *Ptr++ = (BYTE)CurCharInfo->Attributes;
+ CurCharInfo++;
+ }
+ }
+
+ ConioDrawRegion(Console, &WriteRegion);
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+
+ WriteOutputRequest->WriteRegion.Right = WriteRegion.Left + SizeX - 1;
+ WriteOutputRequest->WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
+ WriteOutputRequest->WriteRegion.Left = WriteRegion.Left;
+ WriteOutputRequest->WriteRegion.Top = WriteRegion.Top;
+
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvWriteConsole)
+{
+ NTSTATUS Status;
+ PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
+
+ DPRINT("SrvWriteConsole\n");
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID)&WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->BufferSize,
+ sizeof(BYTE)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = DoWriteConsole(ApiMessage,
+ CsrGetClientThread(),
+ TRUE);
+
+ if (Status == STATUS_PENDING)
+ *ReplyCode = CsrReplyPending;
+
+ return Status;
+}
+
+CSR_API(SrvReadConsoleOutputString)
+{
+ NTSTATUS Status;
+ PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputCodeRequest;
+ PCONSOLE Console;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+ USHORT CodeType;
+ SHORT Xpos, Ypos;
+ PVOID ReadBuffer;
+ DWORD i;
+ ULONG CodeSize;
+ BYTE Code;
+
+ DPRINT("SrvReadConsoleOutputString\n");
+
+ CodeType = ReadOutputCodeRequest->CodeType;
+ switch (CodeType)
+ {
+ case CODE_ASCII:
+ CodeSize = sizeof(CHAR);
+ break;
+
+ case CODE_UNICODE:
+ CodeSize = sizeof(WCHAR);
+ break;
+
+ case CODE_ATTRIBUTE:
+ CodeSize = sizeof(WORD);
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&ReadOutputCodeRequest->pCode.pCode,
+ ReadOutputCodeRequest->NumCodesToRead,
+ CodeSize))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadOutputCodeRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ ReadBuffer = ReadOutputCodeRequest->pCode.pCode;
+ Xpos = ReadOutputCodeRequest->ReadCoord.X;
+ Ypos = (ReadOutputCodeRequest->ReadCoord.Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y;
+
+ /*
+ * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
+ *
+ * If the number of attributes (resp. characters) to be read from extends
+ * beyond the end of the specified screen buffer row, attributes (resp.
+ * characters) are read from the next row. If the number of attributes
+ * (resp. characters) to be read from extends beyond the end of the console
+ * screen buffer, attributes (resp. characters) up to the end of the console
+ * screen buffer are read.
+ *
+ * TODO: Do NOT loop up to NumCodesToRead, but stop before
+ * if we are going to overflow...
+ */
+ for (i = 0; i < min(ReadOutputCodeRequest->NumCodesToRead, Buff->ScreenBufferSize.X * Buff->ScreenBufferSize.Y * 2); ++i)
+ {
+ Code = Buff->Buffer[2 * (Xpos + Ypos * Buff->ScreenBufferSize.X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
+
+ switch (CodeType)
+ {
+ case CODE_UNICODE:
+ ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)ReadBuffer, (PCHAR)&Code);
+ break;
+
+ case CODE_ASCII:
+ *(PCHAR)ReadBuffer = (CHAR)Code;
+ break;
+
+ case CODE_ATTRIBUTE:
+ *(PWORD)ReadBuffer = (WORD)Code;
+ break;
+ }
+ ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
+
+ Xpos++;
+
+ if (Xpos == Buff->ScreenBufferSize.X)
+ {
+ Xpos = 0;
+ Ypos++;
+
+ if (Ypos == Buff->ScreenBufferSize.Y)
+ {
+ Ypos = 0;
+ }
+ }
+ }
+
+ // switch (CodeType)
+ // {
+ // case CODE_UNICODE:
+ // *(PWCHAR)ReadBuffer = 0;
+ // break;
+
+ // case CODE_ASCII:
+ // *(PCHAR)ReadBuffer = 0;
+ // break;
+
+ // case CODE_ATTRIBUTE:
+ // *(PWORD)ReadBuffer = 0;
+ // break;
+ // }
+
+ ReadOutputCodeRequest->EndCoord.X = Xpos;
+ ReadOutputCodeRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->ScreenBufferSize.Y) % Buff->ScreenBufferSize.Y;
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+
+ ReadOutputCodeRequest->CodesRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadOutputCodeRequest->pCode.pCode) / CodeSize;
+ // <= ReadOutputCodeRequest->NumCodesToRead
+
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvWriteConsoleOutputString)
+{
+ NTSTATUS Status;
+ PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputCodeRequest;
+ PCONSOLE Console;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+ USHORT CodeType;
+ PBYTE Buffer; // PUCHAR
+ PCHAR String, tmpString = NULL;
+ DWORD X, Y, Length; // , Written = 0;
+ ULONG CodeSize;
+ SMALL_RECT UpdateRect;
+
+ DPRINT("SrvWriteConsoleOutputString\n");
+
+ CodeType = WriteOutputCodeRequest->CodeType;
+ switch (CodeType)
+ {
+ case CODE_ASCII:
+ CodeSize = sizeof(CHAR);
+ break;
+
+ case CODE_UNICODE:
+ CodeSize = sizeof(WCHAR);
+ break;
+
+ case CODE_ATTRIBUTE:
+ CodeSize = sizeof(WORD);
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&WriteOutputCodeRequest->pCode.pCode,
+ WriteOutputCodeRequest->Length,
+ CodeSize))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ WriteOutputCodeRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ switch (CodeType)
+ {
+ case CODE_UNICODE:
+ {
+ Length = WideCharToMultiByte(Console->OutputCodePage, 0,
+ (PWCHAR)WriteOutputCodeRequest->pCode.UnicodeChar,
+ WriteOutputCodeRequest->Length,
+ NULL, 0, NULL, NULL);
+ 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;
+ }
+
+ case CODE_ASCII:
+ String = (PCHAR)WriteOutputCodeRequest->pCode.AsciiChar;
+ break;
+
+ case CODE_ATTRIBUTE:
+ default:
+ // *(ReadBuffer++) = Code;
+ String = (PCHAR)WriteOutputCodeRequest->pCode.Attribute;
+ break;
+ }
+
+ if (String && NT_SUCCESS(Status))
+ {
+ 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--)
+ {
+ *Buffer = *String++;
+ // ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
+ String = (PCHAR)((ULONG_PTR)String + CodeSize);
+ // Written++;
+ Buffer += 2;
+ if (++X == Buff->ScreenBufferSize.X)
+ {
+ if (++Y == Buff->ScreenBufferSize.Y)
+ {
+ 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 (tmpString)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString);
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+
+ // WriteOutputCodeRequest->NrCharactersWritten = Written;
+ return Status;
+}
+
+CSR_API(SrvFillConsoleOutput)
+{
+ NTSTATUS Status;
+ PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
+ PCONSOLE Console;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+ DWORD X, Y, Length; // , Written = 0;
+ USHORT CodeType;
+ BYTE Code;
+ PBYTE Buffer;
+ SMALL_RECT UpdateRect;
+
+ DPRINT("SrvFillConsoleOutput\n");
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), FillOutputRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ CodeType = FillOutputRequest->CodeType;
+
+ X = FillOutputRequest->Coord.X;
+ Y = (FillOutputRequest->Coord.Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y;
+ Length = FillOutputRequest->Length;
+ Buffer = &Buff->Buffer[2 * (Y * Buff->ScreenBufferSize.X + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
+
+ 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--)
+ {
+ *Buffer = Code;
+ Buffer += 2;
+ // Written++;
+ if (++X == Buff->ScreenBufferSize.X)
+ {
+ if (++Y == Buff->ScreenBufferSize.Y)
+ {
+ Y = 0;
+ Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
+ }
+ X = 0;
+ }
+ }
+
+ if ((PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
+ {
+ ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputRequest->Coord,
+ FillOutputRequest->Length);
+ ConioDrawRegion(Console, &UpdateRect);
+ }
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+/*
+ Length = FillOutputRequest->Length;
+ FillOutputRequest->NrCharactersWritten = Length;
+*/
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvGetConsoleScreenBufferInfo)
+{
+ NTSTATUS Status;
+ PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest;
+ // PCONSOLE Console;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+ PCONSOLE_SCREEN_BUFFER_INFO pInfo = &ScreenBufferInfoRequest->Info;
+
+ DPRINT("SrvGetConsoleScreenBufferInfo\n");
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ScreenBufferInfoRequest->OutputHandle, &Buff, GENERIC_READ, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ // Console = Buff->Header.Console;
+
+ pInfo->dwSize = Buff->ScreenBufferSize;
+ pInfo->dwCursorPosition = Buff->CursorPosition;
+ pInfo->wAttributes = Buff->ScreenDefaultAttrib;
+ pInfo->srWindow.Left = Buff->ViewOrigin.X;
+ pInfo->srWindow.Top = Buff->ViewOrigin.Y;
+ pInfo->srWindow.Right = Buff->ViewOrigin.X + Buff->ViewSize.X - 1;
+ pInfo->srWindow.Bottom = Buff->ViewOrigin.Y + Buff->ViewSize.Y - 1;
+ pInfo->dwMaximumWindowSize = Buff->ScreenBufferSize; // TODO: Refine the computation
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleTextAttribute)
+{
+ NTSTATUS Status;
+ PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetTextAttribRequest;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+
+ DPRINT("SrvSetConsoleTextAttribute\n");
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetTextAttribRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Buff->ScreenDefaultAttrib = SetTextAttribRequest->Attrib;
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleScreenBufferSize)
+{
+ NTSTATUS Status;
+ PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferSizeRequest;
+ PCONSOLE Console;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetScreenBufferSizeRequest->OutputHandle, &Buff, GENERIC_WRITE, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ Status = ConioResizeBuffer(Console, Buff, SetScreenBufferSizeRequest->Size);
+ if (NT_SUCCESS(Status)) ConioResizeTerminal(Console);
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return Status;
+}
+
+CSR_API(SrvScrollConsoleScreenBuffer)
+{
+ PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScrollScreenBufferRequest;
+ PCONSOLE Console;
+ PTEXTMODE_SCREEN_BUFFER Buff;
+ SMALL_RECT ScreenBuffer;
+ SMALL_RECT SrcRegion;
+ SMALL_RECT DstRegion;
+ SMALL_RECT UpdateRegion;
+ SMALL_RECT ScrollRectangle;
+ SMALL_RECT ClipRectangle;
+ NTSTATUS Status;
+ HANDLE OutputHandle;
+ BOOLEAN UseClipRectangle;
+ COORD DestinationOrigin;
+ CHAR_INFO Fill;
+ CHAR FillChar;
+
+ DPRINT("SrvScrollConsoleScreenBuffer\n");
+
+ OutputHandle = ScrollScreenBufferRequest->OutputHandle;
+ UseClipRectangle = ScrollScreenBufferRequest->UseClipRectangle;
+ DestinationOrigin = ScrollScreenBufferRequest->DestinationOrigin;
+ Fill = ScrollScreenBufferRequest->Fill;
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), OutputHandle, &Buff, GENERIC_WRITE, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ ScrollRectangle = ScrollScreenBufferRequest->ScrollRectangle;
+
+ /* Make sure source rectangle is inside the screen buffer */
+ ConioInitRect(&ScreenBuffer, 0, 0, Buff->ScreenBufferSize.Y - 1, Buff->ScreenBufferSize.X - 1);
+ if (!ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle))
+ {
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+ }
+
+ /* If the source was clipped on the left or top, adjust the destination accordingly */
+ if (ScrollRectangle.Left < 0)
+ {
+ DestinationOrigin.X -= ScrollRectangle.Left;
+ }
+ if (ScrollRectangle.Top < 0)
+ {
+ DestinationOrigin.Y -= ScrollRectangle.Top;
+ }
+
+ if (UseClipRectangle)
+ {
+ ClipRectangle = ScrollScreenBufferRequest->ClipRectangle;
+ if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer))
+ {
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ ClipRectangle = ScreenBuffer;
+ }
+
+ ConioInitRect(&DstRegion,
+ DestinationOrigin.Y,
+ DestinationOrigin.X,
+ DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1,
+ DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1);
+
+ if (ScrollScreenBufferRequest->Unicode)
+ ConsoleUnicodeCharToAnsiChar(Console, &FillChar, &Fill.Char.UnicodeChar);
+ else
+ FillChar = Fill.Char.AsciiChar;
+
+ ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, Fill.Attributes << 8 | (BYTE)FillChar);
+
+ if ((PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
+ {
+ ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion);
+ if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &ClipRectangle))
+ {
+ /* Draw update region */
+ ConioDrawRegion(Console, &UpdateRegion);
+ }
+ }
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+}
+
+/* EOF */