2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/frontends/gui/guiterm.c
5 * PURPOSE: GUI Terminal Front-End
6 * PROGRAMMERS: Gé van Geldorp
9 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
12 /* INCLUDES *******************************************************************/
15 #include "include/conio.h"
16 #include "include/console.h"
17 #include "include/settings.h"
19 #include "guisettings.h"
27 /* GUI Console Window Class name */
28 #define GUI_CONSOLE_WINDOW_CLASS L"ConsoleWindowClass"
33 #define PM_CREATE_CONSOLE (WM_APP + 1)
34 #define PM_DESTROY_CONSOLE (WM_APP + 2)
35 #define PM_CONSOLE_BEEP (WM_APP + 3)
36 #define PM_CONSOLE_SET_TITLE (WM_APP + 4)
39 /* Not defined in any header file */
40 // extern VOID WINAPI PrivateCsrssManualGuiCheck(LONG Check);
41 // From win32ss/user/win32csr/dllmain.c
44 PrivateCsrssManualGuiCheck(LONG Check
)
46 NtUserCallOneParam(Check
, ONEPARAM_ROUTINE_CSRSS_GUICHECK
);
49 /* GLOBALS ********************************************************************/
51 /**************************************************************\
52 \** Define the Console Leader Process for the console window **/
53 #define GWLP_CONSOLEWND_ALLOC (2 * sizeof(LONG_PTR))
54 #define GWLP_CONSOLE_LEADER_PID 0
55 #define GWLP_CONSOLE_LEADER_TID 4
57 #define SetConsoleWndConsoleLeaderCID(GuiData) \
59 PCONSOLE_PROCESS_DATA ProcessData; \
60 CLIENT_ID ConsoleLeaderCID; \
61 ProcessData = CONTAINING_RECORD((GuiData)->Console->ProcessList.Blink, \
62 CONSOLE_PROCESS_DATA, \
64 ConsoleLeaderCID = ProcessData->Process->ClientId; \
65 SetWindowLongPtrW((GuiData)->hWindow, GWLP_CONSOLE_LEADER_PID, (LONG_PTR)(ConsoleLeaderCID.UniqueProcess)); \
66 SetWindowLongPtrW((GuiData)->hWindow, GWLP_CONSOLE_LEADER_TID, (LONG_PTR)(ConsoleLeaderCID.UniqueThread )); \
68 /**************************************************************/
70 static BOOL ConsInitialized
= FALSE
;
71 static HICON ghDefaultIcon
= NULL
;
72 static HICON ghDefaultIconSm
= NULL
;
73 static HCURSOR ghDefaultCursor
= NULL
;
74 static HWND NotifyWnd
= NULL
;
76 typedef struct _GUICONSOLE_MENUITEM
79 const struct _GUICONSOLE_MENUITEM
*SubMenu
;
81 } GUICONSOLE_MENUITEM
, *PGUICONSOLE_MENUITEM
;
83 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems
[] =
85 { IDS_MARK
, NULL
, ID_SYSTEM_EDIT_MARK
},
86 { IDS_COPY
, NULL
, ID_SYSTEM_EDIT_COPY
},
87 { IDS_PASTE
, NULL
, ID_SYSTEM_EDIT_PASTE
},
88 { IDS_SELECTALL
, NULL
, ID_SYSTEM_EDIT_SELECTALL
},
89 { IDS_SCROLL
, NULL
, ID_SYSTEM_EDIT_SCROLL
},
90 { IDS_FIND
, NULL
, ID_SYSTEM_EDIT_FIND
},
92 { 0, NULL
, 0 } /* End of list */
95 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems
[] =
97 { IDS_EDIT
, GuiConsoleEditMenuItems
, 0 },
98 { IDS_DEFAULTS
, NULL
, ID_SYSTEM_DEFAULTS
},
99 { IDS_PROPERTIES
, NULL
, ID_SYSTEM_PROPERTIES
},
101 { 0, NULL
, 0 } /* End of list */
105 * Default 16-color palette for foreground and background
106 * (corresponding flags in comments).
108 const COLORREF s_Colors
[16] =
110 RGB(0, 0, 0), // (Black)
111 RGB(0, 0, 128), // BLUE
112 RGB(0, 128, 0), // GREEN
113 RGB(0, 128, 128), // BLUE | GREEN
114 RGB(128, 0, 0), // RED
115 RGB(128, 0, 128), // BLUE | RED
116 RGB(128, 128, 0), // GREEN | RED
117 RGB(192, 192, 192), // BLUE | GREEN | RED
119 RGB(128, 128, 128), // (Grey) INTENSITY
120 RGB(0, 0, 255), // BLUE | INTENSITY
121 RGB(0, 255, 0), // GREEN | INTENSITY
122 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
123 RGB(255, 0, 0), // RED | INTENSITY
124 RGB(255, 0, 255), // BLUE | RED | INTENSITY
125 RGB(255, 255, 0), // GREEN | RED | INTENSITY
126 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
129 /* FUNCTIONS ******************************************************************/
132 GuiConsoleAppendMenuItems(HMENU hMenu
,
133 const GUICONSOLE_MENUITEM
*Items
)
136 WCHAR szMenuString
[255];
141 if (Items
[i
].uID
!= (UINT
)-1)
143 if (LoadStringW(ConSrvDllInstance
,
146 sizeof(szMenuString
) / sizeof(szMenuString
[0])) > 0)
148 if (Items
[i
].SubMenu
!= NULL
)
150 hSubMenu
= CreatePopupMenu();
151 if (hSubMenu
!= NULL
)
153 GuiConsoleAppendMenuItems(hSubMenu
,
156 if (!AppendMenuW(hMenu
,
157 MF_STRING
| MF_POPUP
,
161 DestroyMenu(hSubMenu
);
182 } while (!(Items
[i
].uID
== 0 && Items
[i
].SubMenu
== NULL
&& Items
[i
].wCmdID
== 0));
186 GuiConsoleCreateSysMenu(HWND hWnd
)
189 hMenu
= GetSystemMenu(hWnd
, FALSE
);
192 GuiConsoleAppendMenuItems(hMenu
, GuiConsoleMainMenuItems
);
199 GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData
);
201 GuiConsolePaste(PGUI_CONSOLE_DATA GuiData
);
203 GuiConsoleUpdateSelection(PCONSOLE Console
, PCOORD coord
);
205 GuiDrawRegion(PCONSOLE Console
, SMALL_RECT
* Region
);
207 GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData
);
211 GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData
, WPARAM wParam
, LPARAM lParam
)
214 PCONSOLE Console
= GuiData
->Console
;
216 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
))
224 case ID_SYSTEM_EDIT_MARK
:
226 LPWSTR WindowTitle
= NULL
;
229 Console
->dwSelectionCursor
.X
= 0;
230 Console
->dwSelectionCursor
.Y
= 0;
231 Console
->Selection
.dwSelectionAnchor
= Console
->dwSelectionCursor
;
232 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_IN_PROGRESS
;
233 GuiConsoleUpdateSelection(Console
, &Console
->Selection
.dwSelectionAnchor
);
235 Length
= Console
->Title
.Length
+ sizeof(L
"Mark - ")/sizeof(WCHAR
) + 1;
236 WindowTitle
= RtlAllocateHeap(ConSrvHeap
, 0, Length
* sizeof(WCHAR
));
237 wcscpy(WindowTitle
, L
"Mark - ");
238 wcscat(WindowTitle
, Console
->Title
.Buffer
);
239 SetWindowText(GuiData
->hWindow
, WindowTitle
);
240 RtlFreeHeap(ConSrvHeap
, 0, WindowTitle
);
245 case ID_SYSTEM_EDIT_COPY
:
246 GuiConsoleCopy(GuiData
);
249 case ID_SYSTEM_EDIT_PASTE
:
250 GuiConsolePaste(GuiData
);
253 case ID_SYSTEM_EDIT_SELECTALL
:
255 Console
->Selection
.dwSelectionAnchor
.X
= 0;
256 Console
->Selection
.dwSelectionAnchor
.Y
= 0;
257 Console
->dwSelectionCursor
.X
= Console
->ConsoleSize
.X
- 1;
258 Console
->dwSelectionCursor
.Y
= Console
->ConsoleSize
.Y
- 1;
259 GuiConsoleUpdateSelection(Console
, &Console
->dwSelectionCursor
);
263 case ID_SYSTEM_EDIT_SCROLL
:
264 DPRINT1("Scrolling is not handled yet\n");
267 case ID_SYSTEM_EDIT_FIND
:
268 DPRINT1("Finding is not handled yet\n");
271 case ID_SYSTEM_DEFAULTS
:
272 GuiConsoleShowConsoleProperties(GuiData
, TRUE
);
275 case ID_SYSTEM_PROPERTIES
:
276 GuiConsoleShowConsoleProperties(GuiData
, FALSE
);
284 LeaveCriticalSection(&Console
->Lock
);
288 Ret
= DefWindowProcW(GuiData
->hWindow
, WM_SYSCOMMAND
, wParam
, lParam
);
293 static PGUI_CONSOLE_DATA
294 GuiGetGuiData(HWND hWnd
)
296 /* This function ensures that the console pointer is not NULL */
297 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
298 return ( ((GuiData
== NULL
) || (GuiData
->hWindow
== hWnd
&& GuiData
->Console
!= NULL
)) ? GuiData
: NULL
);
302 GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData
)
304 /* Move the window if needed (not positioned by the system) */
305 if (!GuiData
->GuiInfo
.AutoPosition
)
307 SetWindowPos(GuiData
->hWindow
,
309 GuiData
->GuiInfo
.WindowOrigin
.x
,
310 GuiData
->GuiInfo
.WindowOrigin
.y
,
313 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
318 GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData
)
320 PCONSOLE Console
= GuiData
->Console
;
323 DWORD Width
= Console
->ConsoleSize
.X
* GuiData
->CharWidth
+
324 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
325 DWORD Height
= Console
->ConsoleSize
.Y
* GuiData
->CharHeight
+
326 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
328 /* Set scrollbar sizes */
329 sInfo
.cbSize
= sizeof(SCROLLINFO
);
330 sInfo
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
332 if (Console
->ActiveBuffer
->ScreenBufferSize
.Y
> Console
->ConsoleSize
.Y
)
334 sInfo
.nMax
= Console
->ActiveBuffer
->ScreenBufferSize
.Y
- 1;
335 sInfo
.nPage
= Console
->ConsoleSize
.Y
;
336 sInfo
.nPos
= Console
->ActiveBuffer
->ShowY
;
337 SetScrollInfo(GuiData
->hWindow
, SB_VERT
, &sInfo
, TRUE
);
338 Width
+= GetSystemMetrics(SM_CXVSCROLL
);
339 ShowScrollBar(GuiData
->hWindow
, SB_VERT
, TRUE
);
343 ShowScrollBar(GuiData
->hWindow
, SB_VERT
, FALSE
);
346 if (Console
->ActiveBuffer
->ScreenBufferSize
.X
> Console
->ConsoleSize
.X
)
348 sInfo
.nMax
= Console
->ActiveBuffer
->ScreenBufferSize
.X
- 1;
349 sInfo
.nPage
= Console
->ConsoleSize
.X
;
350 sInfo
.nPos
= Console
->ActiveBuffer
->ShowX
;
351 SetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &sInfo
, TRUE
);
352 Height
+= GetSystemMetrics(SM_CYHSCROLL
);
353 ShowScrollBar(GuiData
->hWindow
, SB_HORZ
, TRUE
);
357 ShowScrollBar(GuiData
->hWindow
, SB_HORZ
, FALSE
);
360 /* Resize the window */
361 SetWindowPos(GuiData
->hWindow
, NULL
, 0, 0, Width
, Height
,
362 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
366 GuiConsoleHandleNcCreate(HWND hWnd
, LPCREATESTRUCTW Create
)
368 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Create
->lpCreateParams
;
375 DPRINT("GuiConsoleHandleNcCreate\n");
379 DPRINT1("GuiConsoleNcCreate: No GUI data\n");
383 Console
= GuiData
->Console
;
385 GuiData
->hWindow
= hWnd
;
387 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->GuiInfo
.FontSize
),
388 0, // HIWORD(GuiData->GuiInfo.FontSize),
391 GuiData
->GuiInfo
.FontWeight
,
398 NONANTIALIASED_QUALITY
,
399 FIXED_PITCH
| GuiData
->GuiInfo
.FontFamily
/* FF_DONTCARE */,
400 GuiData
->GuiInfo
.FaceName
);
402 if (NULL
== GuiData
->Font
)
404 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
405 GuiData
->hWindow
= NULL
;
406 SetEvent(GuiData
->hGuiInitEvent
);
409 Dc
= GetDC(GuiData
->hWindow
);
412 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
413 DeleteObject(GuiData
->Font
);
414 GuiData
->hWindow
= NULL
;
415 SetEvent(GuiData
->hGuiInitEvent
);
418 OldFont
= SelectObject(Dc
, GuiData
->Font
);
421 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
422 ReleaseDC(GuiData
->hWindow
, Dc
);
423 DeleteObject(GuiData
->Font
);
424 GuiData
->hWindow
= NULL
;
425 SetEvent(GuiData
->hGuiInitEvent
);
428 if (!GetTextMetricsW(Dc
, &Metrics
))
430 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
431 SelectObject(Dc
, OldFont
);
432 ReleaseDC(GuiData
->hWindow
, Dc
);
433 DeleteObject(GuiData
->Font
);
434 GuiData
->hWindow
= NULL
;
435 SetEvent(GuiData
->hGuiInitEvent
);
438 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
439 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
441 /* Measure real char width more precisely if possible. */
442 if (GetTextExtentPoint32W(Dc
, L
"R", 1, &CharSize
))
443 GuiData
->CharWidth
= CharSize
.cx
;
445 SelectObject(Dc
, OldFont
);
447 ReleaseDC(GuiData
->hWindow
, Dc
);
449 // FIXME: Keep these instructions here ? ///////////////////////////////////
450 Console
->ActiveBuffer
->CursorBlinkOn
= TRUE
;
451 Console
->ActiveBuffer
->ForceCursorOff
= FALSE
;
452 ////////////////////////////////////////////////////////////////////////////
454 SetWindowLongPtrW(GuiData
->hWindow
, GWLP_USERDATA
, (DWORD_PTR
)GuiData
);
456 SetTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
457 GuiConsoleCreateSysMenu(GuiData
->hWindow
);
459 DPRINT("GuiConsoleHandleNcCreate - setting start event\n");
460 SetEvent(GuiData
->hGuiInitEvent
);
462 return (BOOL
)DefWindowProcW(GuiData
->hWindow
, WM_NCCREATE
, 0, (LPARAM
)Create
);
466 SmallRectToRect(PGUI_CONSOLE_DATA GuiData
, PRECT Rect
, PSMALL_RECT SmallRect
)
468 PCONSOLE Console
= GuiData
->Console
;
469 PCONSOLE_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
471 Rect
->left
= (SmallRect
->Left
- Buffer
->ShowX
) * GuiData
->CharWidth
;
472 Rect
->top
= (SmallRect
->Top
- Buffer
->ShowY
) * GuiData
->CharHeight
;
473 Rect
->right
= (SmallRect
->Right
+ 1 - Buffer
->ShowX
) * GuiData
->CharWidth
;
474 Rect
->bottom
= (SmallRect
->Bottom
+ 1 - Buffer
->ShowY
) * GuiData
->CharHeight
;
478 GuiConsoleUpdateSelection(PCONSOLE Console
, PCOORD coord
)
480 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
481 RECT oldRect
, newRect
;
483 SmallRectToRect(GuiData
, &oldRect
, &Console
->Selection
.srSelection
);
488 /* exchange left/top with right/bottom if required */
489 rc
.Left
= min(Console
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
490 rc
.Top
= min(Console
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
491 rc
.Right
= max(Console
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
492 rc
.Bottom
= max(Console
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
494 SmallRectToRect(GuiData
, &newRect
, &rc
);
496 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
498 if (memcmp(&rc
, &Console
->Selection
.srSelection
, sizeof(SMALL_RECT
)) != 0)
502 /* calculate the region that needs to be updated */
503 if ((rgn1
= CreateRectRgnIndirect(&oldRect
)))
505 if ((rgn2
= CreateRectRgnIndirect(&newRect
)))
507 if (CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
509 InvalidateRgn(GuiData
->hWindow
, rgn1
, FALSE
);
519 InvalidateRect(GuiData
->hWindow
, &newRect
, FALSE
);
521 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_NOT_EMPTY
;
522 Console
->Selection
.srSelection
= rc
;
523 Console
->dwSelectionCursor
= *coord
;
524 ConioPause(Console
, PAUSED_FROM_SELECTION
);
528 /* clear the selection */
529 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
531 InvalidateRect(GuiData
->hWindow
, &oldRect
, FALSE
);
533 Console
->Selection
.dwFlags
= CONSOLE_NO_SELECTION
;
534 ConioUnpause(Console
, PAUSED_FROM_SELECTION
);
539 GuiConsolePaint(PCONSOLE Console
,
540 PGUI_CONSOLE_DATA GuiData
,
544 PCONSOLE_SCREEN_BUFFER Buff
;
545 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
546 ULONG Line
, Char
, Start
;
549 BYTE LastAttribute
, Attribute
;
550 ULONG CursorX
, CursorY
, CursorHeight
;
551 HBRUSH CursorBrush
, OldBrush
;
554 Buff
= Console
->ActiveBuffer
;
556 TopLine
= rc
->top
/ GuiData
->CharHeight
+ Buff
->ShowY
;
557 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1 + Buff
->ShowY
;
558 LeftChar
= rc
->left
/ GuiData
->CharWidth
+ Buff
->ShowX
;
559 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1 + Buff
->ShowX
;
560 LastAttribute
= ConioCoordToPointer(Buff
, LeftChar
, TopLine
)[1];
562 SetTextColor(hDC
, RGBFromAttrib(Console
, TextAttribFromAttrib(LastAttribute
)));
563 SetBkColor(hDC
, RGBFromAttrib(Console
, BkgdAttribFromAttrib(LastAttribute
)));
565 if (BottomLine
>= Buff
->ScreenBufferSize
.Y
) BottomLine
= Buff
->ScreenBufferSize
.Y
- 1;
566 if (RightChar
>= Buff
->ScreenBufferSize
.X
) RightChar
= Buff
->ScreenBufferSize
.X
- 1;
568 OldFont
= SelectObject(hDC
, GuiData
->Font
);
570 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
572 WCHAR LineBuffer
[80];
573 From
= ConioCoordToPointer(Buff
, LeftChar
, Line
);
577 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
579 if (*(From
+ 1) != LastAttribute
|| (Char
- Start
== sizeof(LineBuffer
) / sizeof(WCHAR
)))
582 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
583 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
588 Attribute
= *(From
+ 1);
589 if (Attribute
!= LastAttribute
)
591 SetTextColor(hDC
, RGBFromAttrib(Console
, TextAttribFromAttrib(Attribute
)));
592 SetBkColor(hDC
, RGBFromAttrib(Console
, BkgdAttribFromAttrib(Attribute
)));
593 LastAttribute
= Attribute
;
597 MultiByteToWideChar(Console
->OutputCodePage
,
608 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
609 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
611 RightChar
- Start
+ 1);
614 if (Buff
->CursorInfo
.bVisible
&& Buff
->CursorBlinkOn
&&
615 !Buff
->ForceCursorOff
)
617 CursorX
= Buff
->CursorPosition
.X
;
618 CursorY
= Buff
->CursorPosition
.Y
;
619 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
620 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
622 CursorHeight
= ConioEffectiveCursorSize(Console
, GuiData
->CharHeight
);
623 From
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
) + 1;
625 if (*From
!= DEFAULT_SCREEN_ATTRIB
)
627 CursorBrush
= CreateSolidBrush(RGBFromAttrib(Console
, *From
));
631 CursorBrush
= CreateSolidBrush(RGBFromAttrib(Console
, Buff
->ScreenDefaultAttrib
));
634 OldBrush
= SelectObject(hDC
, CursorBrush
);
636 (CursorX
- Buff
->ShowX
) * GuiData
->CharWidth
,
637 (CursorY
- Buff
->ShowY
) * GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
641 SelectObject(hDC
, OldBrush
);
642 DeleteObject(CursorBrush
);
646 SelectObject(hDC
, OldFont
);
650 GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData
)
653 PCONSOLE Console
= GuiData
->Console
;
657 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
))
663 if (Console
->ActiveBuffer
== NULL
||
664 Console
->ActiveBuffer
->Buffer
== NULL
)
669 hDC
= BeginPaint(GuiData
->hWindow
, &ps
);
671 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
672 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
674 EnterCriticalSection(&GuiData
->Lock
);
676 GuiConsolePaint(Console
,
681 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
684 SmallRectToRect(GuiData
, &rc
, &Console
->Selection
.srSelection
);
686 /* invert the selection */
687 if (IntersectRect(&rc
,
700 LeaveCriticalSection(&GuiData
->Lock
);
702 EndPaint(GuiData
->hWindow
, &ps
);
706 LeaveCriticalSection(&Console
->Lock
);
708 DefWindowProcW(GuiData
->hWindow
, WM_PAINT
, 0, 0);
714 GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
716 PCONSOLE Console
= GuiData
->Console
;
719 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
721 if ( (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_IN_PROGRESS
) &&
722 ((Console
->Selection
.dwFlags
& CONSOLE_MOUSE_SELECTION
) == 0) &&
723 (Console
->ActiveBuffer
) )
725 BOOL Interpreted
= FALSE
;
727 /* Selection with keyboard */
728 if (msg
== WM_KEYDOWN
)
730 BOOL MajPressed
= (GetKeyState(VK_SHIFT
) & 0x8000);
737 if (Console
->dwSelectionCursor
.X
> 0)
738 Console
->dwSelectionCursor
.X
--;
746 if (Console
->dwSelectionCursor
.X
< Console
->ActiveBuffer
->ScreenBufferSize
.X
- 1)
747 Console
->dwSelectionCursor
.X
++;
755 if (Console
->dwSelectionCursor
.Y
> 0)
756 Console
->dwSelectionCursor
.Y
--;
764 if (Console
->dwSelectionCursor
.Y
< Console
->ActiveBuffer
->ScreenBufferSize
.Y
- 1)
765 Console
->dwSelectionCursor
.Y
++;
773 Console
->dwSelectionCursor
.X
= 0;
774 Console
->dwSelectionCursor
.Y
= 0;
781 Console
->dwSelectionCursor
.Y
= Console
->ActiveBuffer
->ScreenBufferSize
.Y
- 1;
788 Console
->dwSelectionCursor
.Y
-= Console
->ConsoleSize
.Y
;
789 if (Console
->dwSelectionCursor
.Y
< 0)
790 Console
->dwSelectionCursor
.Y
= 0;
798 Console
->dwSelectionCursor
.Y
+= Console
->ConsoleSize
.Y
;
799 if (Console
->dwSelectionCursor
.Y
>= Console
->ActiveBuffer
->ScreenBufferSize
.Y
)
800 Console
->dwSelectionCursor
.Y
= Console
->ActiveBuffer
->ScreenBufferSize
.Y
- 1;
812 Console
->Selection
.dwSelectionAnchor
= Console
->dwSelectionCursor
;
814 GuiConsoleUpdateSelection(Console
, &Console
->dwSelectionCursor
);
820 Message
.hwnd
= GuiData
->hWindow
;
821 Message
.message
= msg
;
822 Message
.wParam
= wParam
;
823 Message
.lParam
= lParam
;
825 if (msg
== WM_KEYDOWN
)
827 /* If we are in selection mode (with mouse), clear the selection */
828 GuiConsoleUpdateSelection(Console
, NULL
);
829 SetWindowText(GuiData
->hWindow
, Console
->Title
.Buffer
);
832 ConioProcessKey(Console
, &Message
);
835 LeaveCriticalSection(&Console
->Lock
);
839 GuiInvalidateCell(PCONSOLE Console
, UINT x
, UINT y
)
841 SMALL_RECT CellRect
= { x
, y
, x
, y
};
842 GuiDrawRegion(Console
, &CellRect
);
846 GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData
)
848 PCONSOLE Console
= GuiData
->Console
;
849 PCONSOLE_SCREEN_BUFFER Buff
;
851 SetTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
, CURSOR_BLINK_TIME
, NULL
);
853 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
855 Buff
= Console
->ActiveBuffer
;
856 GuiInvalidateCell(Console
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
857 Buff
->CursorBlinkOn
= !Buff
->CursorBlinkOn
;
859 if ((GuiData
->OldCursor
.x
!= Buff
->CursorPosition
.X
) || (GuiData
->OldCursor
.y
!= Buff
->CursorPosition
.Y
))
862 int OldScrollX
= -1, OldScrollY
= -1;
863 int NewScrollX
= -1, NewScrollY
= -1;
865 xScroll
.cbSize
= sizeof(SCROLLINFO
);
866 xScroll
.fMask
= SIF_POS
;
867 // Capture the original position of the scroll bars and save them.
868 if (GetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &xScroll
))OldScrollX
= xScroll
.nPos
;
869 if (GetScrollInfo(GuiData
->hWindow
, SB_VERT
, &xScroll
))OldScrollY
= xScroll
.nPos
;
871 // If we successfully got the info for the horizontal scrollbar
874 if ((Buff
->CursorPosition
.X
< Buff
->ShowX
)||(Buff
->CursorPosition
.X
>= (Buff
->ShowX
+ Console
->ConsoleSize
.X
)))
876 // Handle the horizontal scroll bar
877 if (Buff
->CursorPosition
.X
>= Console
->ConsoleSize
.X
) NewScrollX
= Buff
->CursorPosition
.X
- Console
->ConsoleSize
.X
+ 1;
882 NewScrollX
= OldScrollX
;
885 // If we successfully got the info for the vertical scrollbar
888 if ((Buff
->CursorPosition
.Y
< Buff
->ShowY
) || (Buff
->CursorPosition
.Y
>= (Buff
->ShowY
+ Console
->ConsoleSize
.Y
)))
890 // Handle the vertical scroll bar
891 if (Buff
->CursorPosition
.Y
>= Console
->ConsoleSize
.Y
) NewScrollY
= Buff
->CursorPosition
.Y
- Console
->ConsoleSize
.Y
+ 1;
896 NewScrollY
= OldScrollY
;
900 // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
901 // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
902 // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
903 // and their associated scrollbar is left alone.
904 if ((OldScrollX
!= NewScrollX
) || (OldScrollY
!= NewScrollY
))
906 Buff
->ShowX
= NewScrollX
;
907 Buff
->ShowY
= NewScrollY
;
908 ScrollWindowEx(GuiData
->hWindow
,
909 (OldScrollX
- NewScrollX
) * GuiData
->CharWidth
,
910 (OldScrollY
- NewScrollY
) * GuiData
->CharHeight
,
918 xScroll
.nPos
= NewScrollX
;
919 SetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &xScroll
, TRUE
);
923 xScroll
.nPos
= NewScrollY
;
924 SetScrollInfo(GuiData
->hWindow
, SB_VERT
, &xScroll
, TRUE
);
926 UpdateWindow(GuiData
->hWindow
);
927 GuiData
->OldCursor
.x
= Buff
->CursorPosition
.X
;
928 GuiData
->OldCursor
.y
= Buff
->CursorPosition
.Y
;
932 LeaveCriticalSection(&Console
->Lock
);
936 GuiConsoleHandleClose(PGUI_CONSOLE_DATA GuiData
)
938 PCONSOLE Console
= GuiData
->Console
;
939 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
942 * FIXME: Windows will wait up to 5 seconds for the thread to exit.
943 * We shouldn't wait here, though, since the console lock is entered.
944 * A copy of the thread list probably needs to be made.
946 ConSrvConsoleProcessCtrlEvent(Console
, 0, CTRL_CLOSE_EVENT
);
948 LeaveCriticalSection(&Console
->Lock
);
952 GuiConsoleHandleNcDestroy(HWND hWnd
)
954 // PGUI_CONSOLE_DATA GuiData;
956 KillTimer(hWnd
, CONGUI_UPDATE_TIMER
);
957 GetSystemMenu(hWnd
, TRUE
);
959 /* Free the GuiData registration */
960 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (DWORD_PTR
)NULL
);
961 // GuiData->hWindow = NULL;
964 return DefWindowProcW(hWnd
, WM_NCDESTROY
, 0, 0);
968 PointToCoord(PGUI_CONSOLE_DATA GuiData
, LPARAM lParam
)
970 PCONSOLE Console
= GuiData
->Console
;
971 PCONSOLE_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
974 Coord
.X
= Buffer
->ShowX
+ ((short)LOWORD(lParam
) / (int)GuiData
->CharWidth
);
975 Coord
.Y
= Buffer
->ShowY
+ ((short)HIWORD(lParam
) / (int)GuiData
->CharHeight
);
977 /* Clip coordinate to ensure it's inside buffer */
980 else if (Coord
.X
>= Buffer
->ScreenBufferSize
.X
)
981 Coord
.X
= Buffer
->ScreenBufferSize
.X
- 1;
985 else if (Coord
.Y
>= Buffer
->ScreenBufferSize
.Y
)
986 Coord
.Y
= Buffer
->ScreenBufferSize
.Y
- 1;
992 GuiConsoleHandleMouse(PGUI_CONSOLE_DATA GuiData
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
995 PCONSOLE Console
= GuiData
->Console
;
997 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
))
1003 if ( (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_IN_PROGRESS
) ||
1004 (Console
->QuickEdit
) )
1008 case WM_LBUTTONDOWN
:
1010 LPWSTR WindowTitle
= NULL
;
1013 Console
->Selection
.dwSelectionAnchor
= PointToCoord(GuiData
, lParam
);
1014 SetCapture(GuiData
->hWindow
);
1015 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_IN_PROGRESS
| CONSOLE_MOUSE_SELECTION
| CONSOLE_MOUSE_DOWN
;
1016 GuiConsoleUpdateSelection(Console
, &Console
->Selection
.dwSelectionAnchor
);
1018 Length
= Console
->Title
.Length
+ sizeof(L
"Selection - ")/sizeof(WCHAR
) + 1;
1019 WindowTitle
= RtlAllocateHeap(ConSrvHeap
, 0, Length
* sizeof(WCHAR
));
1020 wcscpy(WindowTitle
, L
"Selection - ");
1021 wcscat(WindowTitle
, Console
->Title
.Buffer
);
1022 SetWindowText(GuiData
->hWindow
, WindowTitle
);
1023 RtlFreeHeap(ConSrvHeap
, 0, WindowTitle
);
1032 if (!(Console
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) break;
1034 c
= PointToCoord(GuiData
, lParam
);
1035 Console
->Selection
.dwFlags
&= ~CONSOLE_MOUSE_DOWN
;
1036 GuiConsoleUpdateSelection(Console
, &c
);
1042 case WM_RBUTTONDOWN
:
1044 if (!(Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
))
1046 GuiConsolePaste(GuiData
);
1050 GuiConsoleCopy(GuiData
);
1052 /* Clear the selection */
1053 GuiConsoleUpdateSelection(Console
, NULL
);
1054 SetWindowText(GuiData
->hWindow
, Console
->Title
.Buffer
);
1064 if (!(wParam
& MK_LBUTTON
)) break;
1065 if (!(Console
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) break;
1067 c
= PointToCoord(GuiData
, lParam
); /* TODO: Scroll buffer to bring c into view */
1068 GuiConsoleUpdateSelection(Console
, &c
);
1078 else if (Console
->InputBuffer
.Mode
& ENABLE_MOUSE_INPUT
)
1081 WORD wKeyState
= GET_KEYSTATE_WPARAM(wParam
);
1082 DWORD dwButtonState
= 0;
1083 DWORD dwControlKeyState
= 0;
1084 DWORD dwEventFlags
= 0;
1088 case WM_LBUTTONDOWN
:
1089 SetCapture(GuiData
->hWindow
);
1090 dwButtonState
= FROM_LEFT_1ST_BUTTON_PRESSED
;
1094 case WM_MBUTTONDOWN
:
1095 SetCapture(GuiData
->hWindow
);
1096 dwButtonState
= FROM_LEFT_2ND_BUTTON_PRESSED
;
1100 case WM_RBUTTONDOWN
:
1101 SetCapture(GuiData
->hWindow
);
1102 dwButtonState
= RIGHTMOST_BUTTON_PRESSED
;
1124 case WM_LBUTTONDBLCLK
:
1125 dwButtonState
= FROM_LEFT_1ST_BUTTON_PRESSED
;
1126 dwEventFlags
= DOUBLE_CLICK
;
1129 case WM_MBUTTONDBLCLK
:
1130 dwButtonState
= FROM_LEFT_2ND_BUTTON_PRESSED
;
1131 dwEventFlags
= DOUBLE_CLICK
;
1134 case WM_RBUTTONDBLCLK
:
1135 dwButtonState
= RIGHTMOST_BUTTON_PRESSED
;
1136 dwEventFlags
= DOUBLE_CLICK
;
1141 dwEventFlags
= MOUSE_MOVED
;
1145 dwButtonState
= GET_WHEEL_DELTA_WPARAM(wParam
) << 16;
1146 dwEventFlags
= MOUSE_WHEELED
;
1149 case WM_MOUSEHWHEEL
:
1150 dwButtonState
= GET_WHEEL_DELTA_WPARAM(wParam
) << 16;
1151 dwEventFlags
= MOUSE_HWHEELED
;
1161 if (wKeyState
& MK_LBUTTON
)
1162 dwButtonState
|= FROM_LEFT_1ST_BUTTON_PRESSED
;
1163 if (wKeyState
& MK_MBUTTON
)
1164 dwButtonState
|= FROM_LEFT_2ND_BUTTON_PRESSED
;
1165 if (wKeyState
& MK_RBUTTON
)
1166 dwButtonState
|= RIGHTMOST_BUTTON_PRESSED
;
1168 if (GetKeyState(VK_RMENU
) & 0x8000)
1169 dwControlKeyState
|= RIGHT_ALT_PRESSED
;
1170 if (GetKeyState(VK_LMENU
) & 0x8000)
1171 dwControlKeyState
|= LEFT_ALT_PRESSED
;
1172 if (GetKeyState(VK_RCONTROL
) & 0x8000)
1173 dwControlKeyState
|= RIGHT_CTRL_PRESSED
;
1174 if (GetKeyState(VK_LCONTROL
) & 0x8000)
1175 dwControlKeyState
|= LEFT_CTRL_PRESSED
;
1176 if (GetKeyState(VK_SHIFT
) & 0x8000)
1177 dwControlKeyState
|= SHIFT_PRESSED
;
1178 if (GetKeyState(VK_NUMLOCK
) & 0x0001)
1179 dwControlKeyState
|= NUMLOCK_ON
;
1180 if (GetKeyState(VK_SCROLL
) & 0x0001)
1181 dwControlKeyState
|= SCROLLLOCK_ON
;
1182 if (GetKeyState(VK_CAPITAL
) & 0x0001)
1183 dwControlKeyState
|= CAPSLOCK_ON
;
1184 /* See WM_CHAR MSDN documentation for instance */
1185 if (lParam
& 0x01000000)
1186 dwControlKeyState
|= ENHANCED_KEY
;
1188 er
.EventType
= MOUSE_EVENT
;
1189 er
.Event
.MouseEvent
.dwMousePosition
= PointToCoord(GuiData
, lParam
);
1190 er
.Event
.MouseEvent
.dwButtonState
= dwButtonState
;
1191 er
.Event
.MouseEvent
.dwControlKeyState
= dwControlKeyState
;
1192 er
.Event
.MouseEvent
.dwEventFlags
= dwEventFlags
;
1194 ConioProcessInputEvent(Console
, &er
);
1202 LeaveCriticalSection(&Console
->Lock
);
1206 return DefWindowProcW(GuiData
->hWindow
, msg
, wParam
, lParam
);
1212 GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData
)
1214 PCONSOLE Console
= GuiData
->Console
;
1216 if (OpenClipboard(GuiData
->hWindow
) == TRUE
)
1221 ULONG selWidth
, selHeight
;
1222 ULONG xPos
, yPos
, size
;
1224 selWidth
= Console
->Selection
.srSelection
.Right
- Console
->Selection
.srSelection
.Left
+ 1;
1225 selHeight
= Console
->Selection
.srSelection
.Bottom
- Console
->Selection
.srSelection
.Top
+ 1;
1226 DPRINT("Selection is (%d|%d) to (%d|%d)\n",
1227 Console
->Selection
.srSelection
.Left
,
1228 Console
->Selection
.srSelection
.Top
,
1229 Console
->Selection
.srSelection
.Right
,
1230 Console
->Selection
.srSelection
.Bottom
);
1232 /* Basic size for one line and termination */
1233 size
= selWidth
+ 1;
1236 /* Multiple line selections have to get \r\n appended */
1237 size
+= ((selWidth
+ 2) * (selHeight
- 1));
1240 /* Allocate memory, it will be passed to the system and may not be freed here */
1241 hData
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
1247 data
= GlobalLock(hData
);
1254 DPRINT("Copying %dx%d selection\n", selWidth
, selHeight
);
1257 for (yPos
= 0; yPos
< selHeight
; yPos
++)
1259 ptr
= ConioCoordToPointer(Console
->ActiveBuffer
,
1260 Console
->Selection
.srSelection
.Left
,
1261 yPos
+ Console
->Selection
.srSelection
.Top
);
1262 /* Copy only the characters, leave attributes alone */
1263 for (xPos
= 0; xPos
< selWidth
; xPos
++)
1265 dstPos
[xPos
] = ptr
[xPos
* 2];
1268 if (yPos
!= (selHeight
- 1))
1270 strcat(data
, "\r\n");
1275 DPRINT("Setting data <%s> to clipboard\n", data
);
1276 GlobalUnlock(hData
);
1279 SetClipboardData(CF_TEXT
, hData
);
1285 GuiConsolePaste(PGUI_CONSOLE_DATA GuiData
)
1287 PCONSOLE Console
= GuiData
->Console
;
1289 if (OpenClipboard(GuiData
->hWindow
) == TRUE
)
1295 hData
= GetClipboardData(CF_TEXT
);
1302 str
= GlobalLock(hData
);
1308 DPRINT("Got data <%s> from clipboard\n", str
);
1311 // TODO: Push the text into the input buffer.
1312 ConioWriteConsole(Console
, Console
->ActiveBuffer
, str
, len
, TRUE
);
1314 GlobalUnlock(hData
);
1320 GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData
, PMINMAXINFO minMaxInfo
)
1322 PCONSOLE Console
= GuiData
->Console
;
1325 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
1327 windx
= CONGUI_MIN_WIDTH
* GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1328 windy
= CONGUI_MIN_HEIGHT
* GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1330 minMaxInfo
->ptMinTrackSize
.x
= windx
;
1331 minMaxInfo
->ptMinTrackSize
.y
= windy
;
1333 windx
= (Console
->ActiveBuffer
->ScreenBufferSize
.X
) * GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1334 windy
= (Console
->ActiveBuffer
->ScreenBufferSize
.Y
) * GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1336 if (Console
->ConsoleSize
.X
< Console
->ActiveBuffer
->ScreenBufferSize
.X
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1337 if (Console
->ConsoleSize
.Y
< Console
->ActiveBuffer
->ScreenBufferSize
.Y
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1339 minMaxInfo
->ptMaxTrackSize
.x
= windx
;
1340 minMaxInfo
->ptMaxTrackSize
.y
= windy
;
1342 LeaveCriticalSection(&Console
->Lock
);
1346 GuiConsoleResize(PGUI_CONSOLE_DATA GuiData
, WPARAM wParam
, LPARAM lParam
)
1348 PCONSOLE Console
= GuiData
->Console
;
1350 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
1352 if ((GuiData
->WindowSizeLock
== FALSE
) &&
1353 (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
))
1355 PCONSOLE_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1356 DWORD windx
, windy
, charx
, chary
;
1358 GuiData
->WindowSizeLock
= TRUE
;
1360 windx
= LOWORD(lParam
);
1361 windy
= HIWORD(lParam
);
1363 // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
1364 if (Console
->ConsoleSize
.X
< Buff
->ScreenBufferSize
.X
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1365 if (Console
->ConsoleSize
.Y
< Buff
->ScreenBufferSize
.Y
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1367 charx
= windx
/ GuiData
->CharWidth
;
1368 chary
= windy
/ GuiData
->CharHeight
;
1370 // Character alignment (round size up or down)
1371 if ((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1372 if ((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1374 // Compensate for added scroll bars in new window
1375 if (charx
< Buff
->ScreenBufferSize
.X
)windy
-= GetSystemMetrics(SM_CYHSCROLL
); // new window will have a horizontal scroll bar
1376 if (chary
< Buff
->ScreenBufferSize
.Y
)windx
-= GetSystemMetrics(SM_CXVSCROLL
); // new window will have a vertical scroll bar
1378 charx
= windx
/ GuiData
->CharWidth
;
1379 chary
= windy
/ GuiData
->CharHeight
;
1381 // Character alignment (round size up or down)
1382 if ((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1383 if ((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1386 if ((charx
!= Console
->ConsoleSize
.X
) || (chary
!= Console
->ConsoleSize
.Y
))
1388 Console
->ConsoleSize
.X
= (charx
<= Buff
->ScreenBufferSize
.X
) ? charx
: Buff
->ScreenBufferSize
.X
;
1389 Console
->ConsoleSize
.Y
= (chary
<= Buff
->ScreenBufferSize
.Y
) ? chary
: Buff
->ScreenBufferSize
.Y
;
1392 GuiConsoleResizeWindow(GuiData
);
1394 // Adjust the start of the visible area if we are attempting to show nonexistent areas
1395 if ((Buff
->ScreenBufferSize
.X
- Buff
->ShowX
) < Console
->ConsoleSize
.X
) Buff
->ShowX
= Buff
->ScreenBufferSize
.X
- Console
->ConsoleSize
.X
;
1396 if ((Buff
->ScreenBufferSize
.Y
- Buff
->ShowY
) < Console
->ConsoleSize
.Y
) Buff
->ShowY
= Buff
->ScreenBufferSize
.Y
- Console
->ConsoleSize
.Y
;
1397 InvalidateRect(GuiData
->hWindow
, NULL
, TRUE
);
1399 GuiData
->WindowSizeLock
= FALSE
;
1402 LeaveCriticalSection(&Console
->Lock
);
1406 // HACK: This functionality is standard for general scrollbars. Don't add it by hand.
1410 GuiConsoleHandleScrollbarMenu(VOID)
1414 hMenu = CreatePopupMenu();
1417 DPRINT("CreatePopupMenu failed\n");
1421 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1422 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1423 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1424 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1425 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1426 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1427 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1428 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1429 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1430 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1435 GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData
, UINT uMsg
, WPARAM wParam
)
1437 PCONSOLE Console
= GuiData
->Console
;
1438 PCONSOLE_SCREEN_BUFFER Buff
;
1441 int old_pos
, Maximum
;
1444 if (!ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return 0;
1446 Buff
= Console
->ActiveBuffer
;
1448 if (uMsg
== WM_HSCROLL
)
1451 Maximum
= Buff
->ScreenBufferSize
.X
- Console
->ConsoleSize
.X
;
1452 pShowXY
= &Buff
->ShowX
;
1457 Maximum
= Buff
->ScreenBufferSize
.Y
- Console
->ConsoleSize
.Y
;
1458 pShowXY
= &Buff
->ShowY
;
1461 /* set scrollbar sizes */
1462 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1463 sInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_PAGE
| SIF_TRACKPOS
;
1465 if (!GetScrollInfo(GuiData
->hWindow
, fnBar
, &sInfo
)) goto Quit
;
1467 old_pos
= sInfo
.nPos
;
1469 switch (LOWORD(wParam
))
1480 sInfo
.nPos
-= sInfo
.nPage
;
1484 sInfo
.nPos
+= sInfo
.nPage
;
1488 sInfo
.nPos
= sInfo
.nTrackPos
;
1489 ConioPause(Console
, PAUSED_FROM_SCROLLBAR
);
1492 case SB_THUMBPOSITION
:
1493 ConioUnpause(Console
, PAUSED_FROM_SCROLLBAR
);
1497 sInfo
.nPos
= sInfo
.nMin
;
1501 sInfo
.nPos
= sInfo
.nMax
;
1508 sInfo
.nPos
= max(sInfo
.nPos
, 0);
1509 sInfo
.nPos
= min(sInfo
.nPos
, Maximum
);
1511 if (old_pos
!= sInfo
.nPos
)
1513 USHORT OldX
= Buff
->ShowX
;
1514 USHORT OldY
= Buff
->ShowY
;
1515 *pShowXY
= sInfo
.nPos
;
1517 ScrollWindowEx(GuiData
->hWindow
,
1518 (OldX
- Buff
->ShowX
) * GuiData
->CharWidth
,
1519 (OldY
- Buff
->ShowY
) * GuiData
->CharHeight
,
1526 sInfo
.fMask
= SIF_POS
;
1527 SetScrollInfo(GuiData
->hWindow
, fnBar
, &sInfo
, TRUE
);
1529 UpdateWindow(GuiData
->hWindow
);
1533 LeaveCriticalSection(&Console
->Lock
);
1537 static LRESULT CALLBACK
1538 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1541 PGUI_CONSOLE_DATA GuiData
= NULL
;
1542 PCONSOLE Console
= NULL
;
1545 * - If it's the first time we create a window for the terminal,
1546 * just initialize it and return.
1548 * - If we are destroying the window, just do it and return.
1550 if (msg
== WM_NCCREATE
)
1552 return (LRESULT
)GuiConsoleHandleNcCreate(hWnd
, (LPCREATESTRUCTW
)lParam
);
1554 else if (msg
== WM_NCDESTROY
)
1556 return GuiConsoleHandleNcDestroy(hWnd
);
1560 * Now the terminal window is initialized.
1561 * Get the terminal data via the window's data.
1562 * If there is no data, just go away.
1564 GuiData
= GuiGetGuiData(hWnd
);
1565 if (GuiData
== NULL
) return 0;
1568 * Each helper function which needs the console
1569 * has to validate and lock it.
1572 /* We have a console, start message dispatching */
1576 GuiConsoleHandleClose(GuiData
);
1580 GuiConsoleHandlePaint(GuiData
);
1589 GuiConsoleHandleKey(GuiData
, msg
, wParam
, lParam
);
1594 GuiConsoleHandleTimer(GuiData
);
1597 case WM_LBUTTONDOWN
:
1598 case WM_MBUTTONDOWN
:
1599 case WM_RBUTTONDOWN
:
1603 case WM_LBUTTONDBLCLK
:
1604 case WM_MBUTTONDBLCLK
:
1605 case WM_RBUTTONDBLCLK
:
1608 case WM_MOUSEHWHEEL
:
1610 Result
= GuiConsoleHandleMouse(GuiData
, msg
, wParam
, lParam
);
1614 case WM_NCRBUTTONDOWN
:
1616 DPRINT("WM_NCRBUTTONDOWN\n");
1618 * HACK: !! Because, when we deal with WM_RBUTTON* and we do not
1619 * call after that DefWindowProc, on ReactOS, right-clicks on the
1620 * (non-client) application title-bar does not display the system
1621 * menu and does not trigger a WM_NCRBUTTONUP message too.
1622 * See: http://git.reactos.org/?p=reactos.git;a=blob;f=reactos/win32ss/user/user32/windows/defwnd.c;hb=HEAD#l1103
1623 * and line 1135 too.
1625 if (DefWindowProcW(hWnd
, WM_NCHITTEST
, 0, lParam
) == HTCAPTION
)
1626 return DefWindowProcW(hWnd
, WM_CONTEXTMENU
, wParam
, lParam
);
1630 // case WM_NCRBUTTONUP:
1631 // DPRINT1("WM_NCRBUTTONUP\n");
1634 case WM_CONTEXTMENU
:
1636 if (DefWindowProcW(hWnd
/*GuiData->hWindow*/, WM_NCHITTEST
, 0, lParam
) == HTCLIENT
)
1638 HMENU hMenu
= CreatePopupMenu();
1641 GuiConsoleAppendMenuItems(hMenu
, GuiConsoleEditMenuItems
);
1642 TrackPopupMenuEx(hMenu
,
1644 GET_X_LPARAM(lParam
),
1645 GET_Y_LPARAM(lParam
),
1661 Result
= GuiConsoleHandleSysMenuCommand(GuiData
, wParam
, lParam
);
1668 Result
= GuiConsoleHandleScroll(GuiData
, msg
, wParam
);
1675 Console
= GuiData
->Console
; // Not NULL because checked in GuiGetGuiData.
1676 if (ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
))
1679 er
.EventType
= FOCUS_EVENT
;
1680 er
.Event
.FocusEvent
.bSetFocus
= (msg
== WM_SETFOCUS
);
1681 ConioProcessInputEvent(Console
, &er
);
1683 LeaveCriticalSection(&Console
->Lock
);
1688 case WM_GETMINMAXINFO
:
1689 GuiConsoleGetMinMaxInfo(GuiData
, (PMINMAXINFO
)lParam
);
1693 GuiConsoleResize(GuiData
, wParam
, lParam
);
1696 case PM_APPLY_CONSOLE_INFO
:
1698 Console
= GuiData
->Console
; // Not NULL because checked in GuiGetGuiData.
1699 if (ConSrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
))
1701 GuiApplyUserSettings(GuiData
, (HANDLE
)wParam
, (BOOL
)lParam
);
1702 LeaveCriticalSection(&Console
->Lock
);
1707 case PM_CONSOLE_BEEP
:
1708 DPRINT1("Beep !!\n");
1712 // case PM_CONSOLE_SET_TITLE:
1713 // SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
1717 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1726 /******************************************************************************
1727 * GUI Terminal Initialization *
1728 ******************************************************************************/
1730 static LRESULT CALLBACK
1731 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1741 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
1745 case PM_CREATE_CONSOLE
:
1747 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)lParam
;
1748 PCONSOLE Console
= GuiData
->Console
;
1750 NewWindow
= CreateWindowExW(WS_EX_CLIENTEDGE
,
1751 GUI_CONSOLE_WINDOW_CLASS
,
1752 Console
->Title
.Buffer
,
1753 WS_OVERLAPPEDWINDOW
| WS_HSCROLL
| WS_VSCROLL
,
1762 if (NULL
!= NewWindow
)
1764 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
1766 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
1768 DPRINT("Set icons via PM_CREATE_CONSOLE\n");
1769 if (GuiData
->hIcon
== NULL
)
1771 DPRINT("Not really /o\\...\n");
1772 GuiData
->hIcon
= ghDefaultIcon
;
1773 GuiData
->hIconSm
= ghDefaultIconSm
;
1775 else if (GuiData
->hIcon
!= ghDefaultIcon
)
1777 DPRINT("Yes \\o/\n");
1778 SendMessageW(GuiData
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)GuiData
->hIcon
);
1779 SendMessageW(GuiData
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)GuiData
->hIconSm
);
1782 /* Move and resize the window to the user's values */
1783 /* CAN WE DEADLOCK ?? */
1784 GuiConsoleMoveWindow(GuiData
);
1785 GuiData
->WindowSizeLock
= TRUE
;
1786 GuiConsoleResizeWindow(GuiData
);
1787 GuiData
->WindowSizeLock
= FALSE
;
1789 // ShowWindow(NewWindow, (int)wParam);
1790 ShowWindowAsync(NewWindow
, (int)wParam
);
1791 DPRINT("Window showed\n");
1794 return (LRESULT
)NewWindow
;
1797 case PM_DESTROY_CONSOLE
:
1799 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)lParam
;
1802 * Window creation is done using a PostMessage(), so it's possible
1803 * that the window that we want to destroy doesn't exist yet.
1804 * So first empty the message queue.
1807 while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
1809 TranslateMessage(&Msg);
1810 DispatchMessageW(&Msg);
1812 while (PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
)) ;
1814 if (GuiData
->hWindow
!= NULL
) /* && DestroyWindow(GuiData->hWindow) */
1816 DestroyWindow(GuiData
->hWindow
);
1818 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
1820 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
1821 if (0 == WindowCount
)
1824 DestroyWindow(hWnd
);
1825 DPRINT("CONSRV: Going to quit the Gui Thread!!\n");
1834 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1839 GuiConsoleGuiThread(PVOID Data
)
1842 PHANDLE GraphicsStartupEvent
= (PHANDLE
)Data
;
1845 * This thread dispatches all the console notifications to the notify window.
1846 * It is common for all the console windows.
1849 PrivateCsrssManualGuiCheck(+1);
1851 NotifyWnd
= CreateWindowW(L
"ConSrvCreateNotify",
1853 WS_OVERLAPPEDWINDOW
,
1862 if (NULL
== NotifyWnd
)
1864 PrivateCsrssManualGuiCheck(-1);
1865 SetEvent(*GraphicsStartupEvent
);
1869 SetEvent(*GraphicsStartupEvent
);
1871 while (GetMessageW(&msg
, NULL
, 0, 0))
1873 TranslateMessage(&msg
);
1874 DispatchMessageW(&msg
);
1877 DPRINT("CONSRV: Quit the Gui Thread!!\n");
1878 PrivateCsrssManualGuiCheck(-1);
1887 ATOM ConsoleClassAtom
;
1889 /* Exit if we were already initialized */
1890 // if (ConsInitialized) return TRUE;
1893 * Initialize and register the different window classes, if needed.
1895 if (!ConsInitialized
)
1897 /* Initialize the notification window class */
1898 wc
.cbSize
= sizeof(WNDCLASSEXW
);
1899 wc
.lpszClassName
= L
"ConSrvCreateNotify";
1900 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
1902 wc
.hInstance
= ConSrvDllInstance
;
1906 wc
.hbrBackground
= NULL
;
1907 wc
.lpszMenuName
= NULL
;
1910 if (RegisterClassExW(&wc
) == 0)
1912 DPRINT1("Failed to register GUI notify wndproc\n");
1916 /* Initialize the console window class */
1917 ghDefaultIcon
= LoadImageW(ConSrvDllInstance
,
1918 MAKEINTRESOURCEW(IDI_TERMINAL
),
1920 GetSystemMetrics(SM_CXICON
),
1921 GetSystemMetrics(SM_CYICON
),
1923 ghDefaultIconSm
= LoadImageW(ConSrvDllInstance
,
1924 MAKEINTRESOURCEW(IDI_TERMINAL
),
1926 GetSystemMetrics(SM_CXSMICON
),
1927 GetSystemMetrics(SM_CYSMICON
),
1929 ghDefaultCursor
= LoadCursorW(NULL
, IDC_ARROW
);
1930 wc
.cbSize
= sizeof(WNDCLASSEXW
);
1931 wc
.lpszClassName
= GUI_CONSOLE_WINDOW_CLASS
;
1932 wc
.lpfnWndProc
= GuiConsoleWndProc
;
1933 wc
.style
= CS_DBLCLKS
/* | CS_HREDRAW | CS_VREDRAW */;
1934 wc
.hInstance
= ConSrvDllInstance
;
1935 wc
.hIcon
= ghDefaultIcon
;
1936 wc
.hIconSm
= ghDefaultIconSm
;
1937 wc
.hCursor
= ghDefaultCursor
;
1938 wc
.hbrBackground
= CreateSolidBrush(RGB(0,0,0)); // FIXME: Use defaults from registry.
1939 wc
.lpszMenuName
= NULL
;
1941 wc
.cbWndExtra
= GWLP_CONSOLEWND_ALLOC
;
1943 ConsoleClassAtom
= RegisterClassExW(&wc
);
1944 if (ConsoleClassAtom
== 0)
1946 DPRINT1("Failed to register GUI console wndproc\n");
1951 NtUserConsoleControl(GuiConsoleWndClassAtom
, &ConsoleClassAtom
, sizeof(ATOM
));
1954 ConsInitialized
= TRUE
;
1958 * Set-up the notification window
1960 if (NULL
== NotifyWnd
)
1962 HANDLE ThreadHandle
;
1963 HANDLE GraphicsStartupEvent
;
1965 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1966 if (NULL
== GraphicsStartupEvent
) return FALSE
;
1968 ThreadHandle
= CreateThread(NULL
,
1970 GuiConsoleGuiThread
,
1971 (PVOID
)&GraphicsStartupEvent
,
1974 if (NULL
== ThreadHandle
)
1976 CloseHandle(GraphicsStartupEvent
);
1977 DPRINT1("CONSRV: Failed to create graphics console thread. Expect problems\n");
1980 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
1981 CloseHandle(ThreadHandle
);
1983 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
1984 CloseHandle(GraphicsStartupEvent
);
1986 if (NULL
== NotifyWnd
)
1988 DPRINT1("CONSRV: Failed to create notification window.\n");
1993 // ConsInitialized = TRUE;
2000 /******************************************************************************
2001 * GUI Console Driver *
2002 ******************************************************************************/
2005 GuiCleanupConsole(PCONSOLE Console
)
2007 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2009 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
)GuiData
);
2011 DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n",
2012 GuiData
->hIcon
, ghDefaultIcon
, GuiData
->hIconSm
, ghDefaultIconSm
);
2013 if (GuiData
->hIcon
!= NULL
&& GuiData
->hIcon
!= ghDefaultIcon
)
2015 DPRINT("Destroy hIcon\n");
2016 DestroyIcon(GuiData
->hIcon
);
2018 if (GuiData
->hIconSm
!= NULL
&& GuiData
->hIconSm
!= ghDefaultIconSm
)
2020 DPRINT("Destroy hIconSm\n");
2021 DestroyIcon(GuiData
->hIconSm
);
2024 Console
->TermIFace
.Data
= NULL
;
2025 DeleteCriticalSection(&GuiData
->Lock
);
2026 RtlFreeHeap(ConSrvHeap
, 0, GuiData
);
2028 DPRINT("Quit GuiCleanupConsole\n");
2032 GuiWriteStream(PCONSOLE Console
, SMALL_RECT
* Region
, LONG CursorStartX
, LONG CursorStartY
,
2033 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
2035 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2036 PCONSOLE_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
2037 LONG CursorEndX
, CursorEndY
;
2040 if (NULL
== GuiData
|| NULL
== GuiData
->hWindow
)
2045 if (0 != ScrolledLines
)
2047 ScrollRect
.left
= 0;
2049 ScrollRect
.right
= Console
->ConsoleSize
.X
* GuiData
->CharWidth
;
2050 ScrollRect
.bottom
= Region
->Top
* GuiData
->CharHeight
;
2052 ScrollWindowEx(GuiData
->hWindow
,
2054 -(int)(ScrolledLines
* GuiData
->CharHeight
),
2062 GuiDrawRegion(Console
, Region
);
2064 if (CursorStartX
< Region
->Left
|| Region
->Right
< CursorStartX
2065 || CursorStartY
< Region
->Top
|| Region
->Bottom
< CursorStartY
)
2067 GuiInvalidateCell(Console
, CursorStartX
, CursorStartY
);
2070 CursorEndX
= Buff
->CursorPosition
.X
;
2071 CursorEndY
= Buff
->CursorPosition
.Y
;
2072 if ((CursorEndX
< Region
->Left
|| Region
->Right
< CursorEndX
2073 || CursorEndY
< Region
->Top
|| Region
->Bottom
< CursorEndY
)
2074 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
2076 GuiInvalidateCell(Console
, CursorEndX
, CursorEndY
);
2079 // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
2080 // repaint the window without having it just freeze up and stay on the screen permanently.
2081 Buff
->CursorBlinkOn
= TRUE
;
2082 SetTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
2086 GuiDrawRegion(PCONSOLE Console
, SMALL_RECT
* Region
)
2088 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2091 SmallRectToRect(GuiData
, &RegionRect
, Region
);
2092 InvalidateRect(GuiData
->hWindow
, &RegionRect
, FALSE
);
2096 GuiSetCursorInfo(PCONSOLE Console
, PCONSOLE_SCREEN_BUFFER Buff
)
2098 if (Console
->ActiveBuffer
== Buff
)
2100 GuiInvalidateCell(Console
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
2107 GuiSetScreenInfo(PCONSOLE Console
, PCONSOLE_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
2109 if (Console
->ActiveBuffer
== Buff
)
2111 /* Redraw char at old position (removes cursor) */
2112 GuiInvalidateCell(Console
, OldCursorX
, OldCursorY
);
2113 /* Redraw char at new position (shows cursor) */
2114 GuiInvalidateCell(Console
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
2121 GuiUpdateScreenInfo(PCONSOLE Console
, PCONSOLE_SCREEN_BUFFER Buff
)
2127 GuiIsBufferResizeSupported(PCONSOLE Console
)
2133 GuiResizeTerminal(PCONSOLE Console
)
2135 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2137 /* Resize the window to the user's values */
2138 GuiData
->WindowSizeLock
= TRUE
;
2139 GuiConsoleResizeWindow(GuiData
);
2140 GuiData
->WindowSizeLock
= FALSE
;
2144 GuiProcessKeyCallback(PCONSOLE Console
, MSG
* msg
, BYTE KeyStateMenu
, DWORD ShiftState
, UINT VirtualKeyCode
, BOOL Down
)
2146 if ((ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
) || KeyStateMenu
& 0x80) &&
2147 (VirtualKeyCode
== VK_ESCAPE
|| VirtualKeyCode
== VK_TAB
|| VirtualKeyCode
== VK_SPACE
))
2149 DefWindowProcW(msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2157 GuiRefreshInternalInfo(PCONSOLE Console
)
2159 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2161 /* Update the console leader information held by the window */
2162 SetConsoleWndConsoleLeaderCID(GuiData
);
2166 GuiChangeTitle(PCONSOLE Console
)
2168 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2169 // PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0);
2170 SetWindowText(GuiData
->hWindow
, Console
->Title
.Buffer
);
2174 GuiChangeIcon(PCONSOLE Console
, HICON hWindowIcon
)
2176 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2177 HICON hIcon
, hIconSm
;
2179 if (hWindowIcon
== NULL
)
2181 hIcon
= ghDefaultIcon
;
2182 hIconSm
= ghDefaultIconSm
;
2186 hIcon
= CopyIcon(hWindowIcon
);
2187 hIconSm
= CopyIcon(hWindowIcon
);
2195 if (hIcon
!= GuiData
->hIcon
)
2197 if (GuiData
->hIcon
!= NULL
&& GuiData
->hIcon
!= ghDefaultIcon
)
2199 DestroyIcon(GuiData
->hIcon
);
2201 if (GuiData
->hIconSm
!= NULL
&& GuiData
->hIconSm
!= ghDefaultIconSm
)
2203 DestroyIcon(GuiData
->hIconSm
);
2206 GuiData
->hIcon
= hIcon
;
2207 GuiData
->hIconSm
= hIconSm
;
2209 DPRINT("Set icons in GuiChangeIcon\n");
2210 PostMessageW(GuiData
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)GuiData
->hIcon
);
2211 PostMessageW(GuiData
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)GuiData
->hIconSm
);
2218 GuiGetConsoleWindowHandle(PCONSOLE Console
)
2220 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2221 return GuiData
->hWindow
;
2225 GuiGetLargestConsoleWindowSize(PCONSOLE Console
, PCOORD pSize
)
2227 PGUI_CONSOLE_DATA GuiData
= Console
->TermIFace
.Data
;
2235 * This is one solution. Surely better solutions exist :
2236 * http://stackoverflow.com/questions/4631292/how-detect-current-screen-resolution
2237 * http://www.clearevo.com/blog/programming/2011/08/30/windows_c_c++_-_get_monitor_display_screen_size_in_pixels.html
2239 hDesktop
= GetDesktopWindow();
2240 if (!hDesktop
) return;
2242 GetWindowRect(hDesktop
, &desktop
);
2244 width
= desktop
.right
;
2245 height
= desktop
.bottom
;
2247 width
-= (2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
)));
2248 height
-= (2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
));
2250 if (width
< 0) width
= 0;
2251 if (height
< 0) height
= 0;
2253 pSize
->X
= (SHORT
)(width
/ GuiData
->CharWidth
);
2254 pSize
->Y
= (SHORT
)(height
/ GuiData
->CharHeight
);
2257 static FRONTEND_VTBL GuiVtbl
=
2264 GuiUpdateScreenInfo
,
2265 GuiIsBufferResizeSupported
,
2267 GuiProcessKeyCallback
,
2268 GuiRefreshInternalInfo
,
2271 GuiGetConsoleWindowHandle
,
2272 GuiGetLargestConsoleWindowSize
2276 GuiInitConsole(PCONSOLE Console
,
2277 /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo
,
2278 PCONSOLE_INFO ConsoleInfo
,
2283 PGUI_CONSOLE_DATA GuiData
;
2284 GUI_CONSOLE_INFO TermInfo
;
2287 if (Console
== NULL
|| ConsoleInfo
== NULL
)
2288 return STATUS_INVALID_PARAMETER
;
2290 /* Initialize the GUI terminal emulator */
2291 if (!GuiInit()) return STATUS_UNSUCCESSFUL
;
2293 /* Initialize the console */
2294 Console
->TermIFace
.Vtbl
= &GuiVtbl
;
2296 GuiData
= RtlAllocateHeap(ConSrvHeap
, HEAP_ZERO_MEMORY
,
2297 sizeof(GUI_CONSOLE_DATA
));
2300 DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
2301 return STATUS_UNSUCCESSFUL
;
2303 Console
->TermIFace
.Data
= (PVOID
)GuiData
;
2304 GuiData
->Console
= Console
;
2305 GuiData
->hWindow
= NULL
;
2307 InitializeCriticalSection(&GuiData
->Lock
);
2311 * Load the terminal settings
2314 /***********************************************
2315 * Adapted from ConSrvInitConsole in console.c *
2316 ***********************************************/
2318 /* 1. Load the default settings */
2319 GuiConsoleGetDefaultSettings(&TermInfo
, ProcessId
);
2321 /* 2. Load the remaining console settings via the registry. */
2322 if ((ConsoleStartInfo
->dwStartupFlags
& STARTF_TITLEISLINKNAME
) == 0)
2324 /* Load the terminal infos from the registry. */
2325 GuiConsoleReadUserSettings(&TermInfo
, ConsoleInfo
->ConsoleTitle
, ProcessId
);
2328 * Now, update them with the properties the user might gave to us
2329 * via the STARTUPINFO structure before calling CreateProcess
2330 * (and which was transmitted via the ConsoleStartInfo structure).
2331 * We therefore overwrite the values read in the registry.
2333 if (ConsoleStartInfo
->dwStartupFlags
& STARTF_USESHOWWINDOW
)
2335 TermInfo
.ShowWindow
= ConsoleStartInfo
->ShowWindow
;
2337 if (ConsoleStartInfo
->dwStartupFlags
& STARTF_USEPOSITION
)
2339 TermInfo
.AutoPosition
= FALSE
;
2340 TermInfo
.WindowOrigin
= ConsoleStartInfo
->ConsoleWindowOrigin
;
2343 if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
2345 ConsoleInfo.FullScreen = TRUE;
2352 * Set up the GUI data
2355 Length
= min(wcslen(TermInfo
.FaceName
) + 1, LF_FACESIZE
); // wcsnlen
2356 wcsncpy(GuiData
->GuiInfo
.FaceName
, TermInfo
.FaceName
, LF_FACESIZE
);
2357 GuiData
->GuiInfo
.FaceName
[Length
] = L
'\0';
2358 GuiData
->GuiInfo
.FontFamily
= TermInfo
.FontFamily
;
2359 GuiData
->GuiInfo
.FontSize
= TermInfo
.FontSize
;
2360 GuiData
->GuiInfo
.FontWeight
= TermInfo
.FontWeight
;
2361 GuiData
->GuiInfo
.UseRasterFonts
= TermInfo
.UseRasterFonts
;
2362 GuiData
->GuiInfo
.ShowWindow
= TermInfo
.ShowWindow
;
2363 GuiData
->GuiInfo
.AutoPosition
= TermInfo
.AutoPosition
;
2364 GuiData
->GuiInfo
.WindowOrigin
= TermInfo
.WindowOrigin
;
2366 /* Initialize the icon handles to their default values */
2367 GuiData
->hIcon
= ghDefaultIcon
;
2368 GuiData
->hIconSm
= ghDefaultIconSm
;
2370 /* Get the associated icon, if any */
2371 if (IconPath
== NULL
|| *IconPath
== L
'\0')
2373 IconPath
= ConsoleStartInfo
->AppPath
;
2376 DPRINT("IconPath = %S ; IconIndex = %lu\n", (IconPath
? IconPath
: L
"n/a"), IconIndex
);
2379 HICON hIcon
= NULL
, hIconSm
= NULL
;
2380 PrivateExtractIconExW(IconPath
,
2385 DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon
, hIconSm
);
2388 DPRINT("Effectively set the icons\n");
2389 GuiData
->hIcon
= hIcon
;
2390 GuiData
->hIconSm
= hIconSm
;
2395 * We need to wait until the GUI has been fully initialized
2396 * to retrieve custom settings i.e. WindowSize etc...
2397 * Ideally we could use SendNotifyMessage for this but its not
2400 GuiData
->hGuiInitEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2402 /* Create the terminal window */
2403 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, GuiData
->GuiInfo
.ShowWindow
, (LPARAM
)GuiData
);
2405 /* Wait until initialization has finished */
2406 WaitForSingleObject(GuiData
->hGuiInitEvent
, INFINITE
);
2407 DPRINT("OK we created the console window\n");
2408 CloseHandle(GuiData
->hGuiInitEvent
);
2409 GuiData
->hGuiInitEvent
= NULL
;
2411 /* Check whether we really succeeded in initializing the terminal window */
2412 if (GuiData
->hWindow
== NULL
)
2414 DPRINT("GuiInitConsole - We failed at creating a new terminal window\n");
2415 // ConioCleanupConsole(Console);
2416 GuiCleanupConsole(Console
);
2417 return STATUS_UNSUCCESSFUL
;
2420 return STATUS_SUCCESS
;