2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/guiconsole.c
5 * PURPOSE: GUI terminal emulator
9 /* INCLUDES *******************************************************************/
13 #include "guiconsole.h"
19 // Define wmemset(...)
24 /* GUI Console Window Class name */
25 #define GUI_CONSOLE_WINDOW_CLASS L"ConsoleWindowClass"
30 #define PM_CREATE_CONSOLE (WM_APP + 1)
31 #define PM_DESTROY_CONSOLE (WM_APP + 2)
32 #define PM_CONSOLE_BEEP (WM_APP + 3)
33 #define PM_CONSOLE_SET_TITLE (WM_APP + 4)
36 /* Not defined in any header file */
37 // extern VOID WINAPI PrivateCsrssManualGuiCheck(LONG Check);
38 // From win32ss/user/win32csr/dllmain.c
41 PrivateCsrssManualGuiCheck(LONG Check
)
43 NtUserCallOneParam(Check
, ONEPARAM_ROUTINE_CSRSS_GUICHECK
);
46 /* GLOBALS ********************************************************************/
48 typedef struct _GUI_CONSOLE_DATA
50 CRITICAL_SECTION Lock
;
55 HWND hWindow
; /* Handle to the console's window */
56 HICON hIcon
; /* Handle to the console's icon (big) */
57 HICON hIconSm
; /* Handle to the console's icon (small) */
58 // COLORREF Colors[16];
64 PCONSOLE Console
; /* Pointer to the owned console */
65 GUI_CONSOLE_INFO GuiInfo
; /* GUI terminal settings */
66 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
68 static BOOL ConsInitialized
= FALSE
;
69 static HICON ghDefaultIcon
= NULL
;
70 static HICON ghDefaultIconSm
= NULL
;
71 static HCURSOR ghDefaultCursor
= NULL
;
72 static HWND NotifyWnd
= NULL
;
74 typedef struct _GUICONSOLE_MENUITEM
77 const struct _GUICONSOLE_MENUITEM
*SubMenu
;
79 } GUICONSOLE_MENUITEM
, *PGUICONSOLE_MENUITEM
;
81 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems
[] =
83 { IDS_MARK
, NULL
, ID_SYSTEM_EDIT_MARK
},
84 { IDS_COPY
, NULL
, ID_SYSTEM_EDIT_COPY
},
85 { IDS_PASTE
, NULL
, ID_SYSTEM_EDIT_PASTE
},
86 { IDS_SELECTALL
, NULL
, ID_SYSTEM_EDIT_SELECTALL
},
87 { IDS_SCROLL
, NULL
, ID_SYSTEM_EDIT_SCROLL
},
88 { IDS_FIND
, NULL
, ID_SYSTEM_EDIT_FIND
},
90 { 0, NULL
, 0 } /* End of list */
93 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems
[] =
95 { IDS_EDIT
, GuiConsoleEditMenuItems
, 0 },
96 { IDS_DEFAULTS
, NULL
, ID_SYSTEM_DEFAULTS
},
97 { IDS_PROPERTIES
, NULL
, ID_SYSTEM_PROPERTIES
},
99 { 0, NULL
, 0 } /* End of list */
103 * Default 16-color palette for foreground and background
104 * (corresponding flags in comments).
106 const COLORREF s_Colors
[16] =
108 RGB(0, 0, 0), // (Black)
109 RGB(0, 0, 128), // BLUE
110 RGB(0, 128, 0), // GREEN
111 RGB(0, 128, 128), // BLUE | GREEN
112 RGB(128, 0, 0), // RED
113 RGB(128, 0, 128), // BLUE | RED
114 RGB(128, 128, 0), // GREEN | RED
115 RGB(192, 192, 192), // BLUE | GREEN | RED
117 RGB(128, 128, 128), // (Grey) INTENSITY
118 RGB(0, 0, 255), // BLUE | INTENSITY
119 RGB(0, 255, 0), // GREEN | INTENSITY
120 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
121 RGB(255, 0, 0), // RED | INTENSITY
122 RGB(255, 0, 255), // BLUE | RED | INTENSITY
123 RGB(255, 255, 0), // GREEN | RED | INTENSITY
124 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
127 /* FUNCTIONS ******************************************************************/
130 GuiConsoleAppendMenuItems(HMENU hMenu
,
131 const GUICONSOLE_MENUITEM
*Items
)
134 WCHAR szMenuString
[255];
139 if (Items
[i
].uID
!= (UINT
)-1)
141 if (LoadStringW(ConSrvDllInstance
,
144 sizeof(szMenuString
) / sizeof(szMenuString
[0])) > 0)
146 if (Items
[i
].SubMenu
!= NULL
)
148 hSubMenu
= CreatePopupMenu();
149 if (hSubMenu
!= NULL
)
151 GuiConsoleAppendMenuItems(hSubMenu
,
154 if (!AppendMenuW(hMenu
,
155 MF_STRING
| MF_POPUP
,
159 DestroyMenu(hSubMenu
);
180 } while(!(Items
[i
].uID
== 0 && Items
[i
].SubMenu
== NULL
&& Items
[i
].wCmdID
== 0));
184 GuiConsoleCreateSysMenu(HWND hWnd
)
187 hMenu
= GetSystemMenu(hWnd
, FALSE
);
190 GuiConsoleAppendMenuItems(hMenu
, GuiConsoleMainMenuItems
);
197 GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData
);
199 GuiConsolePaste(PGUI_CONSOLE_DATA GuiData
);
201 GuiConsoleUpdateSelection(PCONSOLE Console
, PCOORD coord
);
203 GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData
, BOOL Defaults
);
205 GuiDrawRegion(PCONSOLE Console
, SMALL_RECT
* Region
);
206 static NTSTATUS WINAPI
207 GuiResizeBuffer(PCONSOLE Console
, PCONSOLE_SCREEN_BUFFER ScreenBuffer
, COORD Size
);
209 GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData
);
211 GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData
);
215 GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData
, WPARAM wParam
, LPARAM lParam
)
221 case ID_SYSTEM_EDIT_MARK
:
222 DPRINT1("Marking not handled yet\n");
225 case ID_SYSTEM_EDIT_COPY
:
226 GuiConsoleCopy(GuiData
);
229 case ID_SYSTEM_EDIT_PASTE
:
230 GuiConsolePaste(GuiData
);
233 case ID_SYSTEM_EDIT_SELECTALL
:
235 PCONSOLE Console
= GuiData
->Console
;
236 COORD bottomRight
= { 0, 0 };
238 bottomRight
.X
= Console
->Size
.X
- 1;
239 bottomRight
.Y
= Console
->Size
.Y
- 1;
240 GuiConsoleUpdateSelection(Console
, &bottomRight
);
244 case ID_SYSTEM_EDIT_SCROLL
:
245 DPRINT1("Scrolling is not handled yet\n");
248 case ID_SYSTEM_EDIT_FIND
:
249 DPRINT1("Finding is not handled yet\n");
252 case ID_SYSTEM_DEFAULTS
:
253 GuiConsoleShowConsoleProperties(GuiData
, TRUE
);
256 case ID_SYSTEM_PROPERTIES
:
257 GuiConsoleShowConsoleProperties(GuiData
, FALSE
);
261 Ret
= DefWindowProcW(GuiData
->hWindow
, WM_SYSCOMMAND
, wParam
, lParam
);
268 GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData
, BOOL Defaults
)
271 PCONSOLE Console
= GuiData
->Console
;
272 PCONSOLE_PROCESS_DATA ProcessData
;
273 HANDLE hSection
= NULL
, hClientSection
= NULL
;
274 LARGE_INTEGER SectionSize
;
277 PCONSOLE_PROPS pSharedInfo
= NULL
;
279 DPRINT("GuiConsoleShowConsoleProperties entered\n");
281 /* Create a memory section to share with the applet, and map it */
282 SectionSize
.QuadPart
= sizeof(CONSOLE_PROPS
);
283 Status
= NtCreateSection(&hSection
,
290 if (!NT_SUCCESS(Status
))
292 DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status
);
296 Status
= NtMapViewOfSection(hSection
,
298 (PVOID
*)&pSharedInfo
,
306 if (!NT_SUCCESS(Status
))
308 DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status
);
314 * Setup the shared console properties structure.
317 pSharedInfo
->hConsoleWindow
= GuiData
->hWindow
;
318 pSharedInfo
->ShowDefaultParams
= Defaults
;
319 /* Console information */
320 pSharedInfo
->ci
.HistoryBufferSize
= Console
->HistoryBufferSize
;
321 pSharedInfo
->ci
.NumberOfHistoryBuffers
= Console
->NumberOfHistoryBuffers
;
322 pSharedInfo
->ci
.HistoryNoDup
= Console
->HistoryNoDup
;
323 pSharedInfo
->ci
.FullScreen
= Console
->FullScreen
;
324 pSharedInfo
->ci
.QuickEdit
= Console
->QuickEdit
;
325 pSharedInfo
->ci
.InsertMode
= Console
->InsertMode
;
326 pSharedInfo
->ci
.InputBufferSize
= 0;
327 pSharedInfo
->ci
.ScreenBufferSize
= Console
->ActiveBuffer
->ScreenBufferSize
;
328 pSharedInfo
->ci
.ConsoleSize
= Console
->Size
;
329 pSharedInfo
->ci
.CursorBlinkOn
;
330 pSharedInfo
->ci
.ForceCursorOff
;
331 pSharedInfo
->ci
.CursorSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
332 pSharedInfo
->ci
.ScreenAttrib
= Console
->ActiveBuffer
->ScreenDefaultAttrib
;
333 pSharedInfo
->ci
.PopupAttrib
= Console
->ActiveBuffer
->PopupDefaultAttrib
;
334 pSharedInfo
->ci
.CodePage
;
335 /* GUI Information */
336 wcsncpy(pSharedInfo
->ci
.u
.GuiInfo
.FaceName
, GuiData
->GuiInfo
.FaceName
, LF_FACESIZE
);
337 pSharedInfo
->ci
.u
.GuiInfo
.FontSize
= (DWORD
)GuiData
->GuiInfo
.FontSize
;
338 pSharedInfo
->ci
.u
.GuiInfo
.FontWeight
= GuiData
->GuiInfo
.FontWeight
;
339 pSharedInfo
->ci
.u
.GuiInfo
.UseRasterFonts
= GuiData
->GuiInfo
.UseRasterFonts
;
340 /// pSharedInfo->ci.u.GuiInfo.WindowPosition = GuiData->GuiInfo.WindowPosition;
341 pSharedInfo
->ci
.u
.GuiInfo
.AutoPosition
= GuiData
->GuiInfo
.AutoPosition
;
342 pSharedInfo
->ci
.u
.GuiInfo
.WindowOrigin
= GuiData
->GuiInfo
.WindowOrigin
;
344 memcpy(pSharedInfo
->ci
.Colors
, Console
->Colors
, sizeof(s_Colors
)); // FIXME: Possible buffer overflow if s_colors is bigger than pSharedInfo->Colors.
345 /* Title of the console, original one corresponding to the one set by the console leader */
346 Length
= min(sizeof(pSharedInfo
->ci
.ConsoleTitle
) / sizeof(pSharedInfo
->ci
.ConsoleTitle
[0]) - 1,
347 Console
->OriginalTitle
.Length
/ sizeof(WCHAR
));
348 wcsncpy(pSharedInfo
->ci
.ConsoleTitle
, Console
->OriginalTitle
.Buffer
, Length
);
349 pSharedInfo
->ci
.ConsoleTitle
[Length
] = L
'\0';
352 NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo
);
354 /* Get the console leader process, our client */
355 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Blink
,
356 CONSOLE_PROCESS_DATA
,
359 /* Duplicate the section handle for the client */
360 Status
= NtDuplicateObject(NtCurrentProcess(),
362 ProcessData
->Process
->ProcessHandle
,
364 0, 0, DUPLICATE_SAME_ACCESS
);
365 if (!NT_SUCCESS(Status
))
367 DPRINT1("Error: Impossible to duplicate section handle for client ; Status = %lu\n", Status
);
372 /* Start the properties dialog */
373 if (ProcessData
->PropDispatcher
)
377 Thread
= CreateRemoteThread(ProcessData
->Process
->ProcessHandle
, NULL
, 0,
378 ProcessData
->PropDispatcher
,
379 (PVOID
)hClientSection
, 0, NULL
);
382 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
386 DPRINT1("We succeeded at creating ProcessData->PropDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData
->Process
->ClientId
.UniqueProcess
, ProcessData
->Process
);
387 /// WaitForSingleObject(Thread, INFINITE);
391 /* We have finished, close the section handle */
397 GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData
,
398 HANDLE hClientSection
,
402 PCONSOLE Console
= GuiData
->Console
;
403 PCONSOLE_PROCESS_DATA ProcessData
;
404 HANDLE hSection
= NULL
;
406 PCONSOLE_PROPS pConInfo
= NULL
;
407 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
409 BOOL SizeChanged
= FALSE
;
411 /// LOCK /// EnterCriticalSection(&Console->Lock);
413 /* Get the console leader process, our client */
414 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Blink
,
415 CONSOLE_PROCESS_DATA
,
418 /* Duplicate the section handle for ourselves */
419 Status
= NtDuplicateObject(ProcessData
->Process
->ProcessHandle
,
423 0, 0, DUPLICATE_SAME_ACCESS
);
424 if (!NT_SUCCESS(Status
))
426 DPRINT1("Error when mapping client handle, Status = %lu\n", Status
);
430 /* Get a view of the shared section */
431 Status
= NtMapViewOfSection(hSection
,
441 if (!NT_SUCCESS(Status
))
443 DPRINT1("Error when mapping view of file, Status = %lu\n", Status
);
448 /* Check that the section is well-sized */
449 if (ViewSize
< sizeof(CONSOLE_PROPS
))
451 DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS)\n");
452 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo
);
457 // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
460 * Apply foreground and background colors for both screen and popup.
461 * Copy the new palette.
462 * TODO: Really update the screen attributes as FillConsoleOutputAttribute does.
464 ActiveBuffer
->ScreenDefaultAttrib
= pConInfo
->ci
.ScreenAttrib
;
465 ActiveBuffer
->PopupDefaultAttrib
= pConInfo
->ci
.PopupAttrib
;
466 memcpy(Console
->Colors
, pConInfo
->ci
.Colors
, sizeof(s_Colors
)); // FIXME: Possible buffer overflow if s_colors is bigger than pConInfo->Colors.
468 /* Apply cursor size */
469 ActiveBuffer
->CursorInfo
.bVisible
= (pConInfo
->ci
.CursorSize
!= 0);
470 ActiveBuffer
->CursorInfo
.dwSize
= min(max(pConInfo
->ci
.CursorSize
, 0), 100);
472 if (pConInfo
->ci
.ConsoleSize
.X
!= Console
->Size
.X
||
473 pConInfo
->ci
.ConsoleSize
.Y
!= Console
->Size
.Y
)
476 Console
->Size
= pConInfo
->ci
.ConsoleSize
;
480 BufSize
= pConInfo
->ci
.ScreenBufferSize
;
481 if (BufSize
.X
!= ActiveBuffer
->ScreenBufferSize
.X
|| BufSize
.Y
!= ActiveBuffer
->ScreenBufferSize
.Y
)
483 if (NT_SUCCESS(GuiResizeBuffer(Console
, ActiveBuffer
, BufSize
)))
487 /* Move the window to the user's values */
488 GuiData
->GuiInfo
.AutoPosition
= pConInfo
->ci
.u
.GuiInfo
.AutoPosition
;
489 GuiData
->GuiInfo
.WindowOrigin
= pConInfo
->ci
.u
.GuiInfo
.WindowOrigin
;
490 GuiConsoleMoveWindow(GuiData
);
494 /* Resize the window to the user's values */
495 GuiData
->WindowSizeLock
= TRUE
;
496 GuiConsoleResizeWindow(GuiData
);
497 GuiData
->WindowSizeLock
= FALSE
;
500 /// LOCK /// LeaveCriticalSection(&Console->Lock);
501 InvalidateRect(pConInfo
->hConsoleWindow
, NULL
, TRUE
);
503 /* Save settings if needed */
504 // FIXME: Do it in the console properties applet ??
507 DWORD ProcessId
= HandleToUlong(ProcessData
->Process
->ClientId
.UniqueProcess
);
508 ConSrvWriteUserSettings(&pConInfo
->ci
, ProcessId
);
511 /* Finally, close the section */
512 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo
);
516 static PGUI_CONSOLE_DATA
517 GuiGetGuiData(HWND hWnd
)
519 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
520 return ( ((GuiData
== NULL
) || (GuiData
->hWindow
== hWnd
&& GuiData
->Console
!= NULL
)) ? GuiData
: NULL
);
524 GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData
)
526 /* Move the window if needed (not positioned by the system) */
527 if (!GuiData
->GuiInfo
.AutoPosition
)
529 SetWindowPos(GuiData
->hWindow
,
531 GuiData
->GuiInfo
.WindowOrigin
.x
,
532 GuiData
->GuiInfo
.WindowOrigin
.y
,
535 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
540 GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData
)
542 PCONSOLE Console
= GuiData
->Console
;
545 DWORD Width
= Console
->Size
.X
* GuiData
->CharWidth
+
546 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
547 DWORD Height
= Console
->Size
.Y
* GuiData
->CharHeight
+
548 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
550 /* Set scrollbar sizes */
551 sInfo
.cbSize
= sizeof(SCROLLINFO
);
552 sInfo
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
554 if (Console
->ActiveBuffer
->ScreenBufferSize
.Y
> Console
->Size
.Y
)
556 sInfo
.nMax
= Console
->ActiveBuffer
->ScreenBufferSize
.Y
- 1;
557 sInfo
.nPage
= Console
->Size
.Y
;
558 sInfo
.nPos
= Console
->ActiveBuffer
->ShowY
;
559 SetScrollInfo(GuiData
->hWindow
, SB_VERT
, &sInfo
, TRUE
);
560 Width
+= GetSystemMetrics(SM_CXVSCROLL
);
561 ShowScrollBar(GuiData
->hWindow
, SB_VERT
, TRUE
);
565 ShowScrollBar(GuiData
->hWindow
, SB_VERT
, FALSE
);
568 if (Console
->ActiveBuffer
->ScreenBufferSize
.X
> Console
->Size
.X
)
570 sInfo
.nMax
= Console
->ActiveBuffer
->ScreenBufferSize
.X
- 1;
571 sInfo
.nPage
= Console
->Size
.X
;
572 sInfo
.nPos
= Console
->ActiveBuffer
->ShowX
;
573 SetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &sInfo
, TRUE
);
574 Height
+= GetSystemMetrics(SM_CYHSCROLL
);
575 ShowScrollBar(GuiData
->hWindow
, SB_HORZ
, TRUE
);
579 ShowScrollBar(GuiData
->hWindow
, SB_HORZ
, FALSE
);
582 /* Resize the window */
583 SetWindowPos(GuiData
->hWindow
, NULL
, 0, 0, Width
, Height
,
584 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
588 GuiConsoleHandleNcCreate(HWND hWnd
, LPCREATESTRUCTW Create
)
590 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Create
->lpCreateParams
;
599 DPRINT1("GuiConsoleNcCreate: No GUI data\n");
603 Console
= GuiData
->Console
;
605 GuiData
->hWindow
= hWnd
;
607 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->GuiInfo
.FontSize
),
608 0, // HIWORD(GuiData->GuiInfo.FontSize),
611 GuiData
->GuiInfo
.FontWeight
,
618 NONANTIALIASED_QUALITY
,
619 FIXED_PITCH
| GuiData
->GuiInfo
.FontFamily
/* FF_DONTCARE */,
620 GuiData
->GuiInfo
.FaceName
);
622 if (NULL
== GuiData
->Font
)
624 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
625 GuiData
->hWindow
= NULL
;
626 SetEvent(GuiData
->hGuiInitEvent
);
629 Dc
= GetDC(GuiData
->hWindow
);
632 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
633 DeleteObject(GuiData
->Font
);
634 GuiData
->hWindow
= NULL
;
635 SetEvent(GuiData
->hGuiInitEvent
);
638 OldFont
= SelectObject(Dc
, GuiData
->Font
);
641 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
642 ReleaseDC(GuiData
->hWindow
, Dc
);
643 DeleteObject(GuiData
->Font
);
644 GuiData
->hWindow
= NULL
;
645 SetEvent(GuiData
->hGuiInitEvent
);
648 if (!GetTextMetricsW(Dc
, &Metrics
))
650 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
651 SelectObject(Dc
, OldFont
);
652 ReleaseDC(GuiData
->hWindow
, Dc
);
653 DeleteObject(GuiData
->Font
);
654 GuiData
->hWindow
= NULL
;
655 SetEvent(GuiData
->hGuiInitEvent
);
658 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
659 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
661 /* Measure real char width more precisely if possible. */
662 if (GetTextExtentPoint32W(Dc
, L
"R", 1, &CharSize
))
663 GuiData
->CharWidth
= CharSize
.cx
;
665 SelectObject(Dc
, OldFont
);
667 ReleaseDC(GuiData
->hWindow
, Dc
);
669 // FIXME: Keep these instructions here ? ///////////////////////////////////
670 Console
->ActiveBuffer
->CursorBlinkOn
= TRUE
;
671 Console
->ActiveBuffer
->ForceCursorOff
= FALSE
;
672 ////////////////////////////////////////////////////////////////////////////
674 SetWindowLongPtrW(GuiData
->hWindow
, GWLP_USERDATA
, (DWORD_PTR
)GuiData
);
676 SetTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
677 GuiConsoleCreateSysMenu(GuiData
->hWindow
);
679 /* Move and resize the window to the user's values */
680 GuiConsoleMoveWindow(GuiData
);
681 GuiData
->WindowSizeLock
= TRUE
;
682 GuiConsoleResizeWindow(GuiData
);
683 GuiData
->WindowSizeLock
= FALSE
;
685 SetEvent(GuiData
->hGuiInitEvent
);
687 return (BOOL
)DefWindowProcW(GuiData
->hWindow
, WM_NCCREATE
, 0, (LPARAM
)Create
);
691 SmallRectToRect(PGUI_CONSOLE_DATA GuiData
, PRECT Rect
, PSMALL_RECT SmallRect
)
693 PCONSOLE Console
= GuiData
->Console
;
694 PCONSOLE_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
696 Rect
->left
= (SmallRect
->Left
- Buffer
->ShowX
) * GuiData
->CharWidth
;
697 Rect
->top
= (SmallRect
->Top
- Buffer
->ShowY
) * GuiData
->CharHeight
;
698 Rect
->right
= (SmallRect
->Right
+ 1 - Buffer
->ShowX
) * GuiData
->CharWidth
;
699 Rect
->bottom
= (SmallRect
->Bottom
+ 1 - Buffer
->ShowY
) * GuiData
->CharHeight
;
703 GuiConsoleUpdateSelection(PCONSOLE Console
, PCOORD coord
)
705 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
706 RECT oldRect
, newRect
;
708 SmallRectToRect(GuiData
, &oldRect
, &Console
->Selection
.srSelection
);
713 /* exchange left/top with right/bottom if required */
714 rc
.Left
= min(Console
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
715 rc
.Top
= min(Console
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
716 rc
.Right
= max(Console
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
717 rc
.Bottom
= max(Console
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
719 SmallRectToRect(GuiData
, &newRect
, &rc
);
721 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
723 if (memcmp(&rc
, &Console
->Selection
.srSelection
, sizeof(SMALL_RECT
)) != 0)
727 /* calculate the region that needs to be updated */
728 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
730 if((rgn2
= CreateRectRgnIndirect(&newRect
)))
732 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
734 InvalidateRgn(GuiData
->hWindow
, rgn1
, FALSE
);
745 InvalidateRect(GuiData
->hWindow
, &newRect
, FALSE
);
747 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_NOT_EMPTY
;
748 Console
->Selection
.srSelection
= rc
;
749 ConioPause(Console
, PAUSED_FROM_SELECTION
);
753 /* clear the selection */
754 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
756 InvalidateRect(GuiData
->hWindow
, &oldRect
, FALSE
);
758 Console
->Selection
.dwFlags
= CONSOLE_NO_SELECTION
;
759 ConioUnpause(Console
, PAUSED_FROM_SELECTION
);
764 GuiConsolePaint(PCONSOLE Console
,
765 PGUI_CONSOLE_DATA GuiData
,
769 PCONSOLE_SCREEN_BUFFER Buff
;
770 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
771 ULONG Line
, Char
, Start
;
774 BYTE LastAttribute
, Attribute
;
775 ULONG CursorX
, CursorY
, CursorHeight
;
776 HBRUSH CursorBrush
, OldBrush
;
779 Buff
= Console
->ActiveBuffer
;
781 /// LOCK /// EnterCriticalSection(&Buff->Header.Console->Lock);
783 TopLine
= rc
->top
/ GuiData
->CharHeight
+ Buff
->ShowY
;
784 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1 + Buff
->ShowY
;
785 LeftChar
= rc
->left
/ GuiData
->CharWidth
+ Buff
->ShowX
;
786 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1 + Buff
->ShowX
;
787 LastAttribute
= ConioCoordToPointer(Buff
, LeftChar
, TopLine
)[1];
789 SetTextColor(hDC
, RGBFromAttrib(Console
, TextAttribFromAttrib(LastAttribute
)));
790 SetBkColor(hDC
, RGBFromAttrib(Console
, BkgdAttribFromAttrib(LastAttribute
)));
792 if (BottomLine
>= Buff
->ScreenBufferSize
.Y
) BottomLine
= Buff
->ScreenBufferSize
.Y
- 1;
793 if (RightChar
>= Buff
->ScreenBufferSize
.X
) RightChar
= Buff
->ScreenBufferSize
.X
- 1;
795 OldFont
= SelectObject(hDC
, GuiData
->Font
);
797 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
799 WCHAR LineBuffer
[80];
800 From
= ConioCoordToPointer(Buff
, LeftChar
, Line
);
804 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
806 if (*(From
+ 1) != LastAttribute
|| (Char
- Start
== sizeof(LineBuffer
) / sizeof(WCHAR
)))
809 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
810 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
815 Attribute
= *(From
+ 1);
816 if (Attribute
!= LastAttribute
)
818 SetTextColor(hDC
, RGBFromAttrib(Console
, TextAttribFromAttrib(Attribute
)));
819 SetBkColor(hDC
, RGBFromAttrib(Console
, BkgdAttribFromAttrib(Attribute
)));
820 LastAttribute
= Attribute
;
824 MultiByteToWideChar(Console
->OutputCodePage
,
835 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
836 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
838 RightChar
- Start
+ 1);
841 if (Buff
->CursorInfo
.bVisible
&& Buff
->CursorBlinkOn
&&
842 !Buff
->ForceCursorOff
)
844 CursorX
= Buff
->CursorPosition
.X
;
845 CursorY
= Buff
->CursorPosition
.Y
;
846 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
847 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
849 CursorHeight
= ConioEffectiveCursorSize(Console
, GuiData
->CharHeight
);
850 From
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
) + 1;
852 if (*From
!= DEFAULT_SCREEN_ATTRIB
)
854 CursorBrush
= CreateSolidBrush(RGBFromAttrib(Console
, *From
));
858 CursorBrush
= CreateSolidBrush(RGBFromAttrib(Console
, Buff
->ScreenDefaultAttrib
));
861 OldBrush
= SelectObject(hDC
, CursorBrush
);
863 (CursorX
- Buff
->ShowX
) * GuiData
->CharWidth
,
864 (CursorY
- Buff
->ShowY
) * GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
868 SelectObject(hDC
, OldBrush
);
869 DeleteObject(CursorBrush
);
873 /// LOCK /// LeaveCriticalSection(&Buff->Header.Console->Lock);
875 SelectObject(hDC
, OldFont
);
879 GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData
, HDC hDCPaint
)
881 PCONSOLE Console
= GuiData
->Console
;
885 if (Console
->ActiveBuffer
== NULL
) return;
887 hDC
= BeginPaint(GuiData
->hWindow
, &ps
);
889 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
890 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
892 if (Console
->ActiveBuffer
->Buffer
!= NULL
)
894 EnterCriticalSection(&GuiData
->Lock
);
896 GuiConsolePaint(Console
,
901 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
904 SmallRectToRect(GuiData
, &rc
, &Console
->Selection
.srSelection
);
906 /* invert the selection */
907 if (IntersectRect(&rc
,
920 LeaveCriticalSection(&GuiData
->Lock
);
923 EndPaint(GuiData
->hWindow
, &ps
);
927 GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
929 PCONSOLE Console
= GuiData
->Console
;
932 Message
.hwnd
= GuiData
->hWindow
;
933 Message
.message
= msg
;
934 Message
.wParam
= wParam
;
935 Message
.lParam
= lParam
;
937 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
939 /* clear the selection */
940 GuiConsoleUpdateSelection(Console
, NULL
);
943 ConioProcessKey(Console
, &Message
);
947 GuiInvalidateCell(PCONSOLE Console
, UINT x
, UINT y
)
949 SMALL_RECT CellRect
= { x
, y
, x
, y
};
950 GuiDrawRegion(Console
, &CellRect
);
954 GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData
)
956 PCONSOLE Console
= GuiData
->Console
;
957 PCONSOLE_SCREEN_BUFFER Buff
;
959 SetTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
, CURSOR_BLINK_TIME
, NULL
);
961 Buff
= Console
->ActiveBuffer
;
962 GuiInvalidateCell(Console
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
963 Buff
->CursorBlinkOn
= !Buff
->CursorBlinkOn
;
965 if((GuiData
->OldCursor
.x
!= Buff
->CursorPosition
.X
) || (GuiData
->OldCursor
.y
!= Buff
->CursorPosition
.Y
))
968 int OldScrollX
= -1, OldScrollY
= -1;
969 int NewScrollX
= -1, NewScrollY
= -1;
971 xScroll
.cbSize
= sizeof(SCROLLINFO
);
972 xScroll
.fMask
= SIF_POS
;
973 // Capture the original position of the scroll bars and save them.
974 if(GetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &xScroll
))OldScrollX
= xScroll
.nPos
;
975 if(GetScrollInfo(GuiData
->hWindow
, SB_VERT
, &xScroll
))OldScrollY
= xScroll
.nPos
;
977 // If we successfully got the info for the horizontal scrollbar
980 if((Buff
->CursorPosition
.X
< Buff
->ShowX
)||(Buff
->CursorPosition
.X
>= (Buff
->ShowX
+ Console
->Size
.X
)))
982 // Handle the horizontal scroll bar
983 if(Buff
->CursorPosition
.X
>= Console
->Size
.X
) NewScrollX
= Buff
->CursorPosition
.X
- Console
->Size
.X
+ 1;
988 NewScrollX
= OldScrollX
;
991 // If we successfully got the info for the vertical scrollbar
994 if((Buff
->CursorPosition
.Y
< Buff
->ShowY
) || (Buff
->CursorPosition
.Y
>= (Buff
->ShowY
+ Console
->Size
.Y
)))
996 // Handle the vertical scroll bar
997 if(Buff
->CursorPosition
.Y
>= Console
->Size
.Y
) NewScrollY
= Buff
->CursorPosition
.Y
- Console
->Size
.Y
+ 1;
1002 NewScrollY
= OldScrollY
;
1006 // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
1007 // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
1008 // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
1009 // and their associated scrollbar is left alone.
1010 if((OldScrollX
!= NewScrollX
) || (OldScrollY
!= NewScrollY
))
1012 Buff
->ShowX
= NewScrollX
;
1013 Buff
->ShowY
= NewScrollY
;
1014 ScrollWindowEx(GuiData
->hWindow
,
1015 (OldScrollX
- NewScrollX
) * GuiData
->CharWidth
,
1016 (OldScrollY
- NewScrollY
) * GuiData
->CharHeight
,
1024 xScroll
.nPos
= NewScrollX
;
1025 SetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &xScroll
, TRUE
);
1029 xScroll
.nPos
= NewScrollY
;
1030 SetScrollInfo(GuiData
->hWindow
, SB_VERT
, &xScroll
, TRUE
);
1032 UpdateWindow(GuiData
->hWindow
);
1033 GuiData
->OldCursor
.x
= Buff
->CursorPosition
.X
;
1034 GuiData
->OldCursor
.y
= Buff
->CursorPosition
.Y
;
1040 GuiConsoleHandleClose(PGUI_CONSOLE_DATA GuiData
)
1042 PCONSOLE Console
= GuiData
->Console
;
1043 PLIST_ENTRY current_entry
;
1044 PCONSOLE_PROCESS_DATA current
;
1046 /// LOCK /// EnterCriticalSection(&Console->Lock);
1049 * Loop through the process list, from the most recent process
1050 * (the active one) to the oldest one (the first created,
1051 * i.e. the console leader process), and for each, send a
1052 * CTRL-CLOSE event (new processes are inserted at the head
1053 * of the console process list).
1055 current_entry
= Console
->ProcessList
.Flink
;
1056 while (current_entry
!= &Console
->ProcessList
)
1058 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
1059 current_entry
= current_entry
->Flink
;
1061 /* FIXME: Windows will wait up to 5 seconds for the thread to exit.
1062 * We shouldn't wait here, though, since the console lock is entered.
1063 * A copy of the thread list probably needs to be made. */
1064 ConSrvConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
1067 /// LOCK /// LeaveCriticalSection(&Console->Lock);
1071 GuiConsoleHandleNcDestroy(PGUI_CONSOLE_DATA GuiData
)
1073 KillTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
);
1074 GetSystemMenu(GuiData
->hWindow
, TRUE
);
1076 SetWindowLongPtrW(GuiData
->hWindow
, GWLP_USERDATA
, (DWORD_PTR
)NULL
);
1077 GuiData
->hWindow
= NULL
;
1081 PointToCoord(PGUI_CONSOLE_DATA GuiData
, LPARAM lParam
)
1083 PCONSOLE Console
= GuiData
->Console
;
1084 PCONSOLE_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
1087 Coord
.X
= Buffer
->ShowX
+ ((short)LOWORD(lParam
) / (int)GuiData
->CharWidth
);
1088 Coord
.Y
= Buffer
->ShowY
+ ((short)HIWORD(lParam
) / (int)GuiData
->CharHeight
);
1090 /* Clip coordinate to ensure it's inside buffer */
1093 else if (Coord
.X
>= Buffer
->ScreenBufferSize
.X
)
1094 Coord
.X
= Buffer
->ScreenBufferSize
.X
- 1;
1098 else if (Coord
.Y
>= Buffer
->ScreenBufferSize
.Y
)
1099 Coord
.Y
= Buffer
->ScreenBufferSize
.Y
- 1;
1105 GuiConsoleLeftMouseDown(PGUI_CONSOLE_DATA GuiData
, LPARAM lParam
)
1107 PCONSOLE Console
= GuiData
->Console
;
1109 Console
->Selection
.dwSelectionAnchor
= PointToCoord(GuiData
, lParam
);
1110 SetCapture(GuiData
->hWindow
);
1111 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_IN_PROGRESS
| CONSOLE_MOUSE_SELECTION
| CONSOLE_MOUSE_DOWN
;
1112 GuiConsoleUpdateSelection(Console
, &Console
->Selection
.dwSelectionAnchor
);
1116 GuiConsoleLeftMouseUp(PGUI_CONSOLE_DATA GuiData
, LPARAM lParam
)
1118 PCONSOLE Console
= GuiData
->Console
;
1121 if (!(Console
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) return;
1123 c
= PointToCoord(GuiData
, lParam
);
1124 Console
->Selection
.dwFlags
&= ~CONSOLE_MOUSE_DOWN
;
1125 GuiConsoleUpdateSelection(Console
, &c
);
1130 GuiConsoleMouseMove(PGUI_CONSOLE_DATA GuiData
, WPARAM wParam
, LPARAM lParam
)
1132 PCONSOLE Console
= GuiData
->Console
;
1135 if (!(wParam
& MK_LBUTTON
)) return;
1137 if (!(Console
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) return;
1139 c
= PointToCoord(GuiData
, lParam
); /* TODO: Scroll buffer to bring c into view */
1140 GuiConsoleUpdateSelection(Console
, &c
);
1144 GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData
)
1146 PCONSOLE Console
= GuiData
->Console
;
1148 if (OpenClipboard(GuiData
->hWindow
) == TRUE
)
1153 ULONG selWidth
, selHeight
;
1154 ULONG xPos
, yPos
, size
;
1156 selWidth
= Console
->Selection
.srSelection
.Right
- Console
->Selection
.srSelection
.Left
+ 1;
1157 selHeight
= Console
->Selection
.srSelection
.Bottom
- Console
->Selection
.srSelection
.Top
+ 1;
1158 DPRINT("Selection is (%d|%d) to (%d|%d)\n",
1159 Console
->Selection
.srSelection
.Left
,
1160 Console
->Selection
.srSelection
.Top
,
1161 Console
->Selection
.srSelection
.Right
,
1162 Console
->Selection
.srSelection
.Bottom
);
1164 /* Basic size for one line and termination */
1165 size
= selWidth
+ 1;
1168 /* Multiple line selections have to get \r\n appended */
1169 size
+= ((selWidth
+ 2) * (selHeight
- 1));
1172 /* Allocate memory, it will be passed to the system and may not be freed here */
1173 hData
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
1179 data
= GlobalLock(hData
);
1186 DPRINT("Copying %dx%d selection\n", selWidth
, selHeight
);
1189 for (yPos
= 0; yPos
< selHeight
; yPos
++)
1191 ptr
= ConioCoordToPointer(Console
->ActiveBuffer
,
1192 Console
->Selection
.srSelection
.Left
,
1193 yPos
+ Console
->Selection
.srSelection
.Top
);
1194 /* Copy only the characters, leave attributes alone */
1195 for (xPos
= 0; xPos
< selWidth
; xPos
++)
1197 dstPos
[xPos
] = ptr
[xPos
* 2];
1200 if (yPos
!= (selHeight
- 1))
1202 strcat(data
, "\r\n");
1207 DPRINT("Setting data <%s> to clipboard\n", data
);
1208 GlobalUnlock(hData
);
1211 SetClipboardData(CF_TEXT
, hData
);
1217 GuiConsolePaste(PGUI_CONSOLE_DATA GuiData
)
1219 PCONSOLE Console
= GuiData
->Console
;
1221 if (OpenClipboard(GuiData
->hWindow
) == TRUE
)
1227 hData
= GetClipboardData(CF_TEXT
);
1234 str
= GlobalLock(hData
);
1240 DPRINT("Got data <%s> from clipboard\n", str
);
1243 // TODO: Push the text into the input buffer.
1244 ConioWriteConsole(Console
, Console
->ActiveBuffer
, str
, len
, TRUE
);
1246 GlobalUnlock(hData
);
1252 GuiConsoleRightMouseDown(PGUI_CONSOLE_DATA GuiData
)
1254 PCONSOLE Console
= GuiData
->Console
;
1256 if (!(Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
))
1258 GuiConsolePaste(GuiData
);
1262 GuiConsoleCopy(GuiData
);
1264 /* Clear the selection */
1265 GuiConsoleUpdateSelection(Console
, NULL
);
1270 GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData
, PMINMAXINFO minMaxInfo
)
1272 PCONSOLE Console
= GuiData
->Console
;
1275 windx
= CONGUI_MIN_WIDTH
* GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1276 windy
= CONGUI_MIN_HEIGHT
* GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1278 minMaxInfo
->ptMinTrackSize
.x
= windx
;
1279 minMaxInfo
->ptMinTrackSize
.y
= windy
;
1281 windx
= (Console
->ActiveBuffer
->ScreenBufferSize
.X
) * GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1282 windy
= (Console
->ActiveBuffer
->ScreenBufferSize
.Y
) * GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1284 if(Console
->Size
.X
< Console
->ActiveBuffer
->ScreenBufferSize
.X
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1285 if(Console
->Size
.Y
< Console
->ActiveBuffer
->ScreenBufferSize
.Y
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1287 minMaxInfo
->ptMaxTrackSize
.x
= windx
;
1288 minMaxInfo
->ptMaxTrackSize
.y
= windy
;
1292 GuiConsoleResize(PGUI_CONSOLE_DATA GuiData
, WPARAM wParam
, LPARAM lParam
)
1294 PCONSOLE Console
= GuiData
->Console
;
1296 if ((GuiData
->WindowSizeLock
== FALSE
) &&
1297 (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
))
1299 PCONSOLE_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1300 DWORD windx
, windy
, charx
, chary
;
1302 GuiData
->WindowSizeLock
= TRUE
;
1304 windx
= LOWORD(lParam
);
1305 windy
= HIWORD(lParam
);
1307 // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
1308 if(Console
->Size
.X
< Buff
->ScreenBufferSize
.X
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1309 if(Console
->Size
.Y
< Buff
->ScreenBufferSize
.Y
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1311 charx
= windx
/ GuiData
->CharWidth
;
1312 chary
= windy
/ GuiData
->CharHeight
;
1314 // Character alignment (round size up or down)
1315 if((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1316 if((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1318 // Compensate for added scroll bars in new window
1319 if(charx
< Buff
->ScreenBufferSize
.X
)windy
-= GetSystemMetrics(SM_CYHSCROLL
); // new window will have a horizontal scroll bar
1320 if(chary
< Buff
->ScreenBufferSize
.Y
)windx
-= GetSystemMetrics(SM_CXVSCROLL
); // new window will have a vertical scroll bar
1322 charx
= windx
/ GuiData
->CharWidth
;
1323 chary
= windy
/ GuiData
->CharHeight
;
1325 // Character alignment (round size up or down)
1326 if((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1327 if((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1330 if((charx
!= Console
->Size
.X
) || (chary
!= Console
->Size
.Y
))
1332 Console
->Size
.X
= (charx
<= Buff
->ScreenBufferSize
.X
) ? charx
: Buff
->ScreenBufferSize
.X
;
1333 Console
->Size
.Y
= (chary
<= Buff
->ScreenBufferSize
.Y
) ? chary
: Buff
->ScreenBufferSize
.Y
;
1336 GuiConsoleResizeWindow(GuiData
);
1338 // Adjust the start of the visible area if we are attempting to show nonexistent areas
1339 if((Buff
->ScreenBufferSize
.X
- Buff
->ShowX
) < Console
->Size
.X
) Buff
->ShowX
= Buff
->ScreenBufferSize
.X
- Console
->Size
.X
;
1340 if((Buff
->ScreenBufferSize
.Y
- Buff
->ShowY
) < Console
->Size
.Y
) Buff
->ShowY
= Buff
->ScreenBufferSize
.Y
- Console
->Size
.Y
;
1341 InvalidateRect(GuiData
->hWindow
, NULL
, TRUE
);
1343 GuiData
->WindowSizeLock
= FALSE
;
1348 // HACK: This functionality is standard for general scrollbars. Don't add it by hand.
1352 GuiConsoleHandleScrollbarMenu(VOID)
1356 hMenu = CreatePopupMenu();
1359 DPRINT("CreatePopupMenu failed\n");
1363 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1364 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1365 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1366 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1367 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1368 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1369 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1370 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1371 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1372 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1378 GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData
, UINT uMsg
, WPARAM wParam
)
1380 PCONSOLE Console
= GuiData
->Console
;
1381 PCONSOLE_SCREEN_BUFFER Buff
;
1384 int old_pos
, Maximum
;
1387 if (GuiData
== NULL
) return FALSE
;
1389 Buff
= Console
->ActiveBuffer
;
1391 if (uMsg
== WM_HSCROLL
)
1394 Maximum
= Buff
->ScreenBufferSize
.X
- Console
->Size
.X
;
1395 pShowXY
= &Buff
->ShowX
;
1400 Maximum
= Buff
->ScreenBufferSize
.Y
- Console
->Size
.Y
;
1401 pShowXY
= &Buff
->ShowY
;
1404 /* set scrollbar sizes */
1405 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1406 sInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_PAGE
| SIF_TRACKPOS
;
1408 if (!GetScrollInfo(GuiData
->hWindow
, fnBar
, &sInfo
))
1413 old_pos
= sInfo
.nPos
;
1415 switch (LOWORD(wParam
))
1426 sInfo
.nPos
-= sInfo
.nPage
;
1430 sInfo
.nPos
+= sInfo
.nPage
;
1434 sInfo
.nPos
= sInfo
.nTrackPos
;
1435 ConioPause(Console
, PAUSED_FROM_SCROLLBAR
);
1438 case SB_THUMBPOSITION
:
1439 ConioUnpause(Console
, PAUSED_FROM_SCROLLBAR
);
1443 sInfo
.nPos
= sInfo
.nMin
;
1447 sInfo
.nPos
= sInfo
.nMax
;
1454 sInfo
.nPos
= max(sInfo
.nPos
, 0);
1455 sInfo
.nPos
= min(sInfo
.nPos
, Maximum
);
1457 if (old_pos
!= sInfo
.nPos
)
1459 USHORT OldX
= Buff
->ShowX
;
1460 USHORT OldY
= Buff
->ShowY
;
1461 *pShowXY
= sInfo
.nPos
;
1463 ScrollWindowEx(GuiData
->hWindow
,
1464 (OldX
- Buff
->ShowX
) * GuiData
->CharWidth
,
1465 (OldY
- Buff
->ShowY
) * GuiData
->CharHeight
,
1472 sInfo
.fMask
= SIF_POS
;
1473 SetScrollInfo(GuiData
->hWindow
, fnBar
, &sInfo
, TRUE
);
1475 UpdateWindow(GuiData
->hWindow
);
1481 static LRESULT CALLBACK
1482 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1485 PGUI_CONSOLE_DATA GuiData
= NULL
;
1488 * If it's the first time we create a window
1489 * for the terminal, just initialize it.
1491 if (msg
== WM_NCCREATE
)
1493 return (LRESULT
)GuiConsoleHandleNcCreate(hWnd
, (LPCREATESTRUCTW
)lParam
);
1497 * Now the terminal window is initialized.
1498 * Get the terminal data via the window's data.
1499 * If there is no data, just go away.
1501 GuiData
= GuiGetGuiData(hWnd
);
1502 if (GuiData
== NULL
) return 0;
1504 // TODO: If the console is about to be destroyed, leave the loop.
1506 /* Lock the console */
1507 EnterCriticalSection(&GuiData
->Console
->Lock
);
1509 /* We have a console, start message dispatching. */
1513 GuiConsoleHandleClose(GuiData
);
1517 GuiConsoleHandleNcDestroy(GuiData
);
1521 GuiConsoleHandlePaint(GuiData
, (HDC
)wParam
);
1529 GuiConsoleHandleKey(GuiData
, msg
, wParam
, lParam
);
1533 GuiConsoleHandleTimer(GuiData
);
1536 case WM_LBUTTONDOWN
:
1537 GuiConsoleLeftMouseDown(GuiData
, lParam
);
1541 GuiConsoleLeftMouseUp(GuiData
, lParam
);
1544 case WM_RBUTTONDOWN
:
1545 GuiConsoleRightMouseDown(GuiData
);
1549 GuiConsoleMouseMove(GuiData
, wParam
, lParam
);
1553 Result
= GuiConsoleHandleSysMenuCommand(GuiData
, wParam
, lParam
);
1558 Result
= GuiConsoleHandleScroll(GuiData
, msg
, wParam
);
1561 case WM_GETMINMAXINFO
:
1562 GuiConsoleGetMinMaxInfo(GuiData
, (PMINMAXINFO
)lParam
);
1566 GuiConsoleResize(GuiData
, wParam
, lParam
);
1569 case PM_APPLY_CONSOLE_INFO
:
1570 GuiApplyUserSettings(GuiData
, (HANDLE
)wParam
, (BOOL
)lParam
);
1573 case PM_CONSOLE_BEEP
:
1574 DPRINT1("Beep !!\n");
1578 case PM_CONSOLE_SET_TITLE
:
1579 SetWindowText(GuiData
->hWindow
, GuiData
->Console
->Title
.Buffer
);
1583 Result
= DefWindowProcW(GuiData
->hWindow
, msg
, wParam
, lParam
);
1587 /* Unlock the console */
1588 LeaveCriticalSection(&GuiData
->Console
->Lock
);
1595 /******************************************************************************
1596 * GUI Terminal Initialization *
1597 ******************************************************************************/
1599 static LRESULT CALLBACK
1600 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1605 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)lParam
;
1606 PCONSOLE Console
= GuiData
->Console
;
1612 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
1616 case PM_CREATE_CONSOLE
:
1618 NewWindow
= CreateWindowExW(WS_EX_CLIENTEDGE
,
1619 GUI_CONSOLE_WINDOW_CLASS
,
1620 Console
->Title
.Buffer
,
1621 WS_OVERLAPPEDWINDOW
| WS_HSCROLL
| WS_VSCROLL
,
1630 if (NULL
!= NewWindow
)
1632 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
1634 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
1636 // SetConsoleWndConsoleLeaderCID(Console);
1638 DPRINT1("Set icons via PM_CREATE_CONSOLE\n");
1639 if (GuiData
->hIcon
== NULL
)
1641 DPRINT1("Not really /o\\...\n");
1642 GuiData
->hIcon
= ghDefaultIcon
;
1643 GuiData
->hIconSm
= ghDefaultIconSm
;
1645 else if (GuiData
->hIcon
!= ghDefaultIcon
)
1647 DPRINT1("Yes \\o/\n");
1648 SendMessageW(GuiData
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)GuiData
->hIcon
);
1649 SendMessageW(GuiData
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)GuiData
->hIconSm
);
1652 ShowWindow(NewWindow
, (int)wParam
);
1655 return (LRESULT
)NewWindow
;
1658 case PM_DESTROY_CONSOLE
:
1661 * Window creation is done using a PostMessage(), so it's possible
1662 * that the window that we want to destroy doesn't exist yet.
1663 * So first empty the message queue.
1665 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
1667 TranslateMessage(&Msg
);
1668 DispatchMessageW(&Msg
);
1671 if (GuiData
->hWindow
!= NULL
) /* && DestroyWindow(GuiData->hWindow) */
1673 DestroyWindow(GuiData
->hWindow
);
1675 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
1677 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
1678 if (0 == WindowCount
)
1681 DestroyWindow(hWnd
);
1682 DPRINT1("CONSRV: Going to quit the Gui Thread!!\n");
1691 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1696 GuiConsoleGuiThread(PVOID Data
)
1699 PHANDLE GraphicsStartupEvent
= (PHANDLE
)Data
;
1702 * This thread dispatches all the console notifications to the notify window.
1703 * It is common for all the console windows.
1706 PrivateCsrssManualGuiCheck(+1);
1708 NotifyWnd
= CreateWindowW(L
"ConSrvCreateNotify",
1710 WS_OVERLAPPEDWINDOW
,
1719 if (NULL
== NotifyWnd
)
1721 PrivateCsrssManualGuiCheck(-1);
1722 SetEvent(*GraphicsStartupEvent
);
1726 SetEvent(*GraphicsStartupEvent
);
1728 while(GetMessageW(&msg
, NULL
, 0, 0))
1730 TranslateMessage(&msg
);
1731 DispatchMessageW(&msg
);
1734 DPRINT1("CONSRV: Quit the Gui Thread!!\n");
1735 PrivateCsrssManualGuiCheck(-1);
1744 ATOM ConsoleClassAtom
;
1746 /* Exit if we were already initialized */
1747 // if (ConsInitialized) return TRUE;
1750 * Initialize and register the different window classes, if needed.
1752 if (!ConsInitialized
)
1754 /* Initialize the notification window class */
1755 wc
.cbSize
= sizeof(WNDCLASSEXW
);
1756 wc
.lpszClassName
= L
"ConSrvCreateNotify";
1757 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
1759 wc
.hInstance
= ConSrvDllInstance
;
1763 wc
.hbrBackground
= NULL
;
1764 wc
.lpszMenuName
= NULL
;
1767 if (RegisterClassExW(&wc
) == 0)
1769 DPRINT1("Failed to register GUI notify wndproc\n");
1773 /* Initialize the console window class */
1774 ghDefaultIcon
= LoadImageW(ConSrvDllInstance
, MAKEINTRESOURCEW(IDI_CONSOLE
), IMAGE_ICON
,
1775 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
),
1777 ghDefaultIconSm
= LoadImageW(ConSrvDllInstance
, MAKEINTRESOURCEW(IDI_CONSOLE
), IMAGE_ICON
,
1778 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
1780 ghDefaultCursor
= LoadCursorW(NULL
, IDC_ARROW
);
1781 wc
.cbSize
= sizeof(WNDCLASSEXW
);
1782 wc
.lpszClassName
= GUI_CONSOLE_WINDOW_CLASS
;
1783 wc
.lpfnWndProc
= GuiConsoleWndProc
;
1785 wc
.hInstance
= ConSrvDllInstance
;
1786 wc
.hIcon
= ghDefaultIcon
;
1787 wc
.hIconSm
= ghDefaultIconSm
;
1788 wc
.hCursor
= ghDefaultCursor
;
1789 wc
.hbrBackground
= CreateSolidBrush(RGB(0,0,0)); // FIXME: Use defaults from registry.
1790 wc
.lpszMenuName
= NULL
;
1792 wc
.cbWndExtra
= GWLP_CONSOLEWND_ALLOC
;
1794 ConsoleClassAtom
= RegisterClassExW(&wc
);
1795 if (ConsoleClassAtom
== 0)
1797 DPRINT1("Failed to register GUI console wndproc\n");
1802 NtUserConsoleControl(GuiConsoleWndClassAtom
, &ConsoleClassAtom
, sizeof(ATOM
));
1805 ConsInitialized
= TRUE
;
1809 * Set-up the notification window
1811 if (NULL
== NotifyWnd
)
1813 HANDLE ThreadHandle
;
1814 HANDLE GraphicsStartupEvent
;
1816 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1817 if (NULL
== GraphicsStartupEvent
) return FALSE
;
1819 ThreadHandle
= CreateThread(NULL
,
1821 GuiConsoleGuiThread
,
1822 (PVOID
)&GraphicsStartupEvent
,
1825 if (NULL
== ThreadHandle
)
1827 CloseHandle(GraphicsStartupEvent
);
1828 DPRINT1("CONSRV: Failed to create graphics console thread. Expect problems\n");
1831 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
1832 CloseHandle(ThreadHandle
);
1834 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
1835 CloseHandle(GraphicsStartupEvent
);
1837 if (NULL
== NotifyWnd
)
1839 DPRINT1("CONSRV: Failed to create notification window.\n");
1844 // ConsInitialized = TRUE;
1851 /******************************************************************************
1852 * GUI Console Driver *
1853 ******************************************************************************/
1856 GuiCleanupConsole(PCONSOLE Console
)
1858 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
1860 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
)GuiData
);
1862 DPRINT1("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n",
1863 GuiData
->hIcon
, ghDefaultIcon
, GuiData
->hIconSm
, ghDefaultIconSm
);
1864 if (GuiData
->hIcon
!= NULL
&& GuiData
->hIcon
!= ghDefaultIcon
)
1866 DPRINT1("Destroy hIcon\n");
1867 DestroyIcon(GuiData
->hIcon
);
1869 if (GuiData
->hIconSm
!= NULL
&& GuiData
->hIconSm
!= ghDefaultIconSm
)
1871 DPRINT1("Destroy hIconSm\n");
1872 DestroyIcon(GuiData
->hIconSm
);
1875 Console
->TermIFace
.Data
= NULL
;
1876 DeleteCriticalSection(&GuiData
->Lock
);
1877 RtlFreeHeap(ConSrvHeap
, 0, GuiData
);
1881 GuiWriteStream(PCONSOLE Console
, SMALL_RECT
* Region
, LONG CursorStartX
, LONG CursorStartY
,
1882 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
1884 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
1885 PCONSOLE_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1886 LONG CursorEndX
, CursorEndY
;
1889 if (NULL
== GuiData
|| NULL
== GuiData
->hWindow
)
1894 if (0 != ScrolledLines
)
1896 ScrollRect
.left
= 0;
1898 ScrollRect
.right
= Console
->Size
.X
* GuiData
->CharWidth
;
1899 ScrollRect
.bottom
= Region
->Top
* GuiData
->CharHeight
;
1901 ScrollWindowEx(GuiData
->hWindow
,
1903 -(ScrolledLines
* GuiData
->CharHeight
),
1911 GuiDrawRegion(Console
, Region
);
1913 if (CursorStartX
< Region
->Left
|| Region
->Right
< CursorStartX
1914 || CursorStartY
< Region
->Top
|| Region
->Bottom
< CursorStartY
)
1916 GuiInvalidateCell(Console
, CursorStartX
, CursorStartY
);
1919 CursorEndX
= Buff
->CursorPosition
.X
;
1920 CursorEndY
= Buff
->CursorPosition
.Y
;
1921 if ((CursorEndX
< Region
->Left
|| Region
->Right
< CursorEndX
1922 || CursorEndY
< Region
->Top
|| Region
->Bottom
< CursorEndY
)
1923 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
1925 GuiInvalidateCell(Console
, CursorEndX
, CursorEndY
);
1928 // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
1929 // repaint the window without having it just freeze up and stay on the screen permanently.
1930 Buff
->CursorBlinkOn
= TRUE
;
1931 SetTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
1935 GuiDrawRegion(PCONSOLE Console
, SMALL_RECT
* Region
)
1937 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
1940 SmallRectToRect(GuiData
, &RegionRect
, Region
);
1941 InvalidateRect(GuiData
->hWindow
, &RegionRect
, FALSE
);
1945 GuiSetCursorInfo(PCONSOLE Console
, PCONSOLE_SCREEN_BUFFER Buff
)
1947 if (Console
->ActiveBuffer
== Buff
)
1949 GuiInvalidateCell(Console
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
1956 GuiSetScreenInfo(PCONSOLE Console
, PCONSOLE_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
1958 if (Console
->ActiveBuffer
== Buff
)
1960 /* Redraw char at old position (removes cursor) */
1961 GuiInvalidateCell(Console
, OldCursorX
, OldCursorY
);
1962 /* Redraw char at new position (shows cursor) */
1963 GuiInvalidateCell(Console
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
1970 GuiUpdateScreenInfo(PCONSOLE Console
, PCONSOLE_SCREEN_BUFFER Buff
)
1975 static NTSTATUS WINAPI
1976 GuiResizeBuffer(PCONSOLE Console
, PCONSOLE_SCREEN_BUFFER ScreenBuffer
, COORD Size
)
1984 USHORT value
= MAKEWORD(' ', ScreenBuffer
->ScreenDefaultAttrib
);
1990 /* Buffer size is not allowed to be smaller than window size */
1991 if (Size
.X
< Console
->Size
.X
|| Size
.Y
< Console
->Size
.Y
)
1992 return STATUS_INVALID_PARAMETER
;
1994 if (Size
.X
== ScreenBuffer
->ScreenBufferSize
.X
&& Size
.Y
== ScreenBuffer
->ScreenBufferSize
.Y
)
1995 return STATUS_SUCCESS
;
1997 Buffer
= RtlAllocateHeap(ConSrvHeap
, 0, Size
.X
* Size
.Y
* 2);
1999 return STATUS_NO_MEMORY
;
2001 DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer
->ScreenBufferSize
.X
, ScreenBuffer
->ScreenBufferSize
.Y
, Size
.X
, Size
.Y
);
2002 OldBuffer
= ScreenBuffer
->Buffer
;
2004 for (CurrentY
= 0; CurrentY
< ScreenBuffer
->ScreenBufferSize
.Y
&& CurrentY
< Size
.Y
; CurrentY
++)
2006 OldPtr
= ConioCoordToPointer(ScreenBuffer
, 0, CurrentY
);
2007 if (Size
.X
<= ScreenBuffer
->ScreenBufferSize
.X
)
2010 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, Size
.X
* 2);
2011 Offset
+= (Size
.X
* 2);
2016 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, ScreenBuffer
->ScreenBufferSize
.X
* 2);
2017 Offset
+= (ScreenBuffer
->ScreenBufferSize
.X
* 2);
2019 diff
= Size
.X
- ScreenBuffer
->ScreenBufferSize
.X
;
2020 /* zero new part of it */
2022 wmemset((PWCHAR
)&Buffer
[Offset
], value
, diff
);
2024 for (i
= 0; i
< diff
; i
++)
2026 Buffer
[Offset
++] = ' ';
2027 Buffer
[Offset
++] = ScreenBuffer
->ScreenDefaultAttrib
;
2033 if (Size
.Y
> ScreenBuffer
->ScreenBufferSize
.Y
)
2035 diff
= Size
.X
* (Size
.Y
- ScreenBuffer
->ScreenBufferSize
.Y
);
2037 wmemset((PWCHAR
)&Buffer
[Offset
], value
, diff
);
2039 for (i
= 0; i
< diff
; i
++)
2041 Buffer
[Offset
++] = ' ';
2042 Buffer
[Offset
++] = ScreenBuffer
->ScreenDefaultAttrib
;
2047 (void)InterlockedExchangePointer((PVOID
volatile*)&ScreenBuffer
->Buffer
, Buffer
);
2048 RtlFreeHeap(ConSrvHeap
, 0, OldBuffer
);
2049 ScreenBuffer
->ScreenBufferSize
= Size
;
2050 ScreenBuffer
->VirtualY
= 0;
2052 /* Ensure cursor and window are within buffer */
2053 if (ScreenBuffer
->CursorPosition
.X
>= Size
.X
)
2054 ScreenBuffer
->CursorPosition
.X
= Size
.X
- 1;
2055 if (ScreenBuffer
->CursorPosition
.Y
>= Size
.Y
)
2056 ScreenBuffer
->CursorPosition
.Y
= Size
.Y
- 1;
2057 if (ScreenBuffer
->ShowX
> Size
.X
- Console
->Size
.X
)
2058 ScreenBuffer
->ShowX
= Size
.X
- Console
->Size
.X
;
2059 if (ScreenBuffer
->ShowY
> Size
.Y
- Console
->Size
.Y
)
2060 ScreenBuffer
->ShowY
= Size
.Y
- Console
->Size
.Y
;
2062 /* TODO: Should update scrollbar, but can't use anything that
2063 * calls SendMessage or it could cause deadlock --> Use PostMessage */
2064 // TODO: Tell the terminal to resize its scrollbars.
2066 return STATUS_SUCCESS
;
2070 GuiProcessKeyCallback(PCONSOLE Console
, MSG
* msg
, BYTE KeyStateMenu
, DWORD ShiftState
, UINT VirtualKeyCode
, BOOL Down
)
2072 if ((ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
) || KeyStateMenu
& 0x80) &&
2073 (VirtualKeyCode
== VK_ESCAPE
|| VirtualKeyCode
== VK_TAB
|| VirtualKeyCode
== VK_SPACE
))
2075 DefWindowProcW(msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2083 GuiChangeTitle(PCONSOLE Console
)
2085 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2086 PostMessageW(GuiData
->hWindow
, PM_CONSOLE_SET_TITLE
, 0, 0);
2090 GuiChangeIcon(PCONSOLE Console
, HICON hWindowIcon
)
2092 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2093 HICON hIcon
, hIconSm
;
2095 if (hWindowIcon
== NULL
)
2097 hIcon
= ghDefaultIcon
;
2098 hIconSm
= ghDefaultIconSm
;
2102 hIcon
= CopyIcon(hWindowIcon
);
2103 hIconSm
= CopyIcon(hWindowIcon
);
2111 if (hIcon
!= GuiData
->hIcon
)
2113 if (GuiData
->hIcon
!= NULL
&& GuiData
->hIcon
!= ghDefaultIcon
)
2115 DestroyIcon(GuiData
->hIcon
);
2117 if (GuiData
->hIconSm
!= NULL
&& GuiData
->hIconSm
!= ghDefaultIconSm
)
2119 DestroyIcon(GuiData
->hIconSm
);
2122 GuiData
->hIcon
= hIcon
;
2123 GuiData
->hIconSm
= hIconSm
;
2125 DPRINT1("Set icons in GuiChangeIcon\n");
2126 PostMessageW(GuiData
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)GuiData
->hIcon
);
2127 PostMessageW(GuiData
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)GuiData
->hIconSm
);
2134 GuiGetConsoleWindowHandle(PCONSOLE Console
)
2136 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2137 return GuiData
->hWindow
;
2140 static TERMINAL_VTBL GuiVtbl
=
2147 GuiUpdateScreenInfo
,
2149 GuiProcessKeyCallback
,
2152 GuiGetConsoleWindowHandle
2156 GuiInitConsole(PCONSOLE Console
,
2158 PCONSOLE_INFO ConsoleInfo
,
2162 PGUI_CONSOLE_DATA GuiData
;
2164 if (Console
== NULL
|| ConsoleInfo
== NULL
)
2165 return STATUS_INVALID_PARAMETER
;
2167 /* Initialize the GUI terminal emulator */
2168 if (!GuiInit()) return STATUS_UNSUCCESSFUL
;
2170 /* Initialize the console */
2171 Console
->TermIFace
.Vtbl
= &GuiVtbl
;
2173 GuiData
= RtlAllocateHeap(ConSrvHeap
, HEAP_ZERO_MEMORY
,
2174 sizeof(GUI_CONSOLE_DATA
));
2177 DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
2178 return STATUS_UNSUCCESSFUL
;
2180 Console
->TermIFace
.Data
= (PVOID
)GuiData
;
2181 GuiData
->Console
= Console
;
2182 GuiData
->hWindow
= NULL
;
2184 InitializeCriticalSection(&GuiData
->Lock
);
2186 /* Set up the GUI data */
2187 wcsncpy(GuiData
->GuiInfo
.FaceName
, ConsoleInfo
->u
.GuiInfo
.FaceName
, LF_FACESIZE
);
2188 GuiData
->GuiInfo
.FontFamily
= ConsoleInfo
->u
.GuiInfo
.FontFamily
;
2189 GuiData
->GuiInfo
.FontSize
= ConsoleInfo
->u
.GuiInfo
.FontSize
;
2190 GuiData
->GuiInfo
.FontWeight
= ConsoleInfo
->u
.GuiInfo
.FontWeight
;
2191 GuiData
->GuiInfo
.UseRasterFonts
= ConsoleInfo
->u
.GuiInfo
.UseRasterFonts
;
2192 GuiData
->GuiInfo
.ShowWindow
= ConsoleInfo
->u
.GuiInfo
.ShowWindow
;
2193 GuiData
->GuiInfo
.AutoPosition
= ConsoleInfo
->u
.GuiInfo
.AutoPosition
;
2194 GuiData
->GuiInfo
.WindowOrigin
= ConsoleInfo
->u
.GuiInfo
.WindowOrigin
;
2196 /* Initialize the icon handles to their default values */
2197 GuiData
->hIcon
= ghDefaultIcon
;
2198 GuiData
->hIconSm
= ghDefaultIconSm
;
2200 /* Get the associated icon, if any */
2201 if (IconPath
== NULL
|| *IconPath
== L
'\0')
2206 DPRINT1("IconPath = %S ; IconIndex = %lu\n", (IconPath
? IconPath
: L
"n/a"), IconIndex
);
2209 HICON hIcon
= NULL
, hIconSm
= NULL
;
2210 PrivateExtractIconExW(IconPath
,
2215 DPRINT1("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon
, hIconSm
);
2218 DPRINT1("Effectively set the icons\n");
2219 GuiData
->hIcon
= hIcon
;
2220 GuiData
->hIconSm
= hIconSm
;
2225 * We need to wait until the GUI has been fully initialized
2226 * to retrieve custom settings i.e. WindowSize etc...
2227 * Ideally we could use SendNotifyMessage for this but its not
2230 GuiData
->hGuiInitEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2232 /* Create the terminal window */
2233 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, GuiData
->GuiInfo
.ShowWindow
, (LPARAM
)GuiData
);
2235 /* Wait until initialization has finished */
2236 WaitForSingleObject(GuiData
->hGuiInitEvent
, INFINITE
);
2237 CloseHandle(GuiData
->hGuiInitEvent
);
2238 GuiData
->hGuiInitEvent
= NULL
;
2240 /* Check whether we really succeeded in initializing the terminal window */
2241 if (GuiData
->hWindow
== NULL
)
2243 DPRINT1("GuiInitConsole - We failed at creating a new terminal window\n");
2244 // ConioCleanupConsole(Console);
2245 GuiCleanupConsole(Console
);
2246 return STATUS_UNSUCCESSFUL
;
2249 return STATUS_SUCCESS
;