2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: frontends/gui/conwnd.c
5 * PURPOSE: GUI Console Window Class
6 * PROGRAMMERS: Gé van Geldorp
9 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
12 /* INCLUDES *******************************************************************/
25 /* GLOBALS ********************************************************************/
27 // #define PM_CREATE_CONSOLE (WM_APP + 1)
28 // #define PM_DESTROY_CONSOLE (WM_APP + 2)
31 #define CONGUI_MIN_WIDTH 10
32 #define CONGUI_MIN_HEIGHT 10
33 #define CONGUI_UPDATE_TIME 0
34 #define CONGUI_UPDATE_TIMER 1
36 #define CURSOR_BLINK_TIME 500
39 /**************************************************************\
40 \** Define the Console Leader Process for the console window **/
41 #define GWLP_CONWND_ALLOC (2 * sizeof(LONG_PTR))
42 #define GWLP_CONSOLE_LEADER_PID 0
43 #define GWLP_CONSOLE_LEADER_TID 4
46 SetConWndConsoleLeaderCID(IN PGUI_CONSOLE_DATA GuiData
)
48 PCONSOLE_PROCESS_DATA ProcessData
;
49 CLIENT_ID ConsoleLeaderCID
;
51 ProcessData
= ConDrvGetConsoleLeaderProcess(GuiData
->Console
);
52 ConsoleLeaderCID
= ProcessData
->Process
->ClientId
;
53 SetWindowLongPtrW(GuiData
->hWindow
, GWLP_CONSOLE_LEADER_PID
,
54 (LONG_PTR
)(ConsoleLeaderCID
.UniqueProcess
));
55 SetWindowLongPtrW(GuiData
->hWindow
, GWLP_CONSOLE_LEADER_TID
,
56 (LONG_PTR
)(ConsoleLeaderCID
.UniqueThread
));
58 /**************************************************************/
60 HICON ghDefaultIcon
= NULL
;
61 HICON ghDefaultIconSm
= NULL
;
62 HCURSOR ghDefaultCursor
= NULL
;
64 typedef struct _GUICONSOLE_MENUITEM
67 const struct _GUICONSOLE_MENUITEM
*SubMenu
;
69 } GUICONSOLE_MENUITEM
, *PGUICONSOLE_MENUITEM
;
71 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems
[] =
73 { IDS_MARK
, NULL
, ID_SYSTEM_EDIT_MARK
},
74 { IDS_COPY
, NULL
, ID_SYSTEM_EDIT_COPY
},
75 { IDS_PASTE
, NULL
, ID_SYSTEM_EDIT_PASTE
},
76 { IDS_SELECTALL
, NULL
, ID_SYSTEM_EDIT_SELECTALL
},
77 { IDS_SCROLL
, NULL
, ID_SYSTEM_EDIT_SCROLL
},
78 { IDS_FIND
, NULL
, ID_SYSTEM_EDIT_FIND
},
80 { 0, NULL
, 0 } /* End of list */
83 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems
[] =
85 { IDS_EDIT
, GuiConsoleEditMenuItems
, 0 },
86 { IDS_DEFAULTS
, NULL
, ID_SYSTEM_DEFAULTS
},
87 { IDS_PROPERTIES
, NULL
, ID_SYSTEM_PROPERTIES
},
89 { 0, NULL
, 0 } /* End of list */
93 * Default 16-color palette for foreground and background
94 * (corresponding flags in comments).
96 const COLORREF s_Colors
[16] =
98 RGB(0, 0, 0), // (Black)
99 RGB(0, 0, 128), // BLUE
100 RGB(0, 128, 0), // GREEN
101 RGB(0, 128, 128), // BLUE | GREEN
102 RGB(128, 0, 0), // RED
103 RGB(128, 0, 128), // BLUE | RED
104 RGB(128, 128, 0), // GREEN | RED
105 RGB(192, 192, 192), // BLUE | GREEN | RED
107 RGB(128, 128, 128), // (Grey) INTENSITY
108 RGB(0, 0, 255), // BLUE | INTENSITY
109 RGB(0, 255, 0), // GREEN | INTENSITY
110 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
111 RGB(255, 0, 0), // RED | INTENSITY
112 RGB(255, 0, 255), // BLUE | RED | INTENSITY
113 RGB(255, 255, 0), // GREEN | RED | INTENSITY
114 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
117 /* FUNCTIONS ******************************************************************/
119 static LRESULT CALLBACK
120 ConWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
);
123 RegisterConWndClass(IN HINSTANCE hInstance
)
125 WNDCLASSEXW WndClass
;
128 ghDefaultIcon
= LoadImageW(hInstance
,
129 MAKEINTRESOURCEW(IDI_TERMINAL
),
131 GetSystemMetrics(SM_CXICON
),
132 GetSystemMetrics(SM_CYICON
),
134 ghDefaultIconSm
= LoadImageW(hInstance
,
135 MAKEINTRESOURCEW(IDI_TERMINAL
),
137 GetSystemMetrics(SM_CXSMICON
),
138 GetSystemMetrics(SM_CYSMICON
),
140 ghDefaultCursor
= LoadCursorW(NULL
, IDC_ARROW
);
142 WndClass
.cbSize
= sizeof(WNDCLASSEXW
);
143 WndClass
.lpszClassName
= GUI_CONWND_CLASS
;
144 WndClass
.lpfnWndProc
= ConWndProc
;
145 WndClass
.style
= CS_DBLCLKS
/* | CS_HREDRAW | CS_VREDRAW */;
146 WndClass
.hInstance
= hInstance
;
147 WndClass
.hIcon
= ghDefaultIcon
;
148 WndClass
.hIconSm
= ghDefaultIconSm
;
149 WndClass
.hCursor
= ghDefaultCursor
;
150 WndClass
.hbrBackground
= (HBRUSH
)GetStockObject(BLACK_BRUSH
); // The color of a terminal when it is switched off.
151 WndClass
.lpszMenuName
= NULL
;
152 WndClass
.cbClsExtra
= 0;
153 WndClass
.cbWndExtra
= GWLP_CONWND_ALLOC
;
155 WndClassAtom
= RegisterClassExW(&WndClass
);
156 if (WndClassAtom
== 0)
158 DPRINT1("Failed to register GUI console class\n");
162 NtUserConsoleControl(GuiConsoleWndClassAtom
, &WndClassAtom
, sizeof(ATOM
));
165 return (WndClassAtom
!= 0);
169 UnRegisterConWndClass(HINSTANCE hInstance
)
171 return !!UnregisterClassW(GUI_CONWND_CLASS
, hInstance
);
177 GetScreenBufferSizeUnits(IN PCONSOLE_SCREEN_BUFFER Buffer
,
178 IN PGUI_CONSOLE_DATA GuiData
,
180 OUT PUINT HeightUnit
)
182 if (Buffer
== NULL
|| GuiData
== NULL
||
183 WidthUnit
== NULL
|| HeightUnit
== NULL
)
188 if (GetType(Buffer
) == TEXTMODE_BUFFER
)
190 *WidthUnit
= GuiData
->CharWidth
;
191 *HeightUnit
= GuiData
->CharHeight
;
193 else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
201 AppendMenuItems(HMENU hMenu
,
202 const GUICONSOLE_MENUITEM
*Items
)
205 WCHAR szMenuString
[255];
210 if (Items
[i
].uID
!= (UINT
)-1)
212 if (LoadStringW(ConSrvDllInstance
,
215 sizeof(szMenuString
) / sizeof(szMenuString
[0])) > 0)
217 if (Items
[i
].SubMenu
!= NULL
)
219 hSubMenu
= CreatePopupMenu();
220 if (hSubMenu
!= NULL
)
222 AppendMenuItems(hSubMenu
, Items
[i
].SubMenu
);
224 if (!AppendMenuW(hMenu
,
225 MF_STRING
| MF_POPUP
,
229 DestroyMenu(hSubMenu
);
250 } while (!(Items
[i
].uID
== 0 && Items
[i
].SubMenu
== NULL
&& Items
[i
].wCmdID
== 0));
254 CreateSysMenu(HWND hWnd
)
256 HMENU hMenu
= GetSystemMenu(hWnd
, FALSE
);
259 AppendMenuItems(hMenu
, GuiConsoleMainMenuItems
);
265 SendMenuEvent(PCONSOLE Console
, UINT CmdId
)
269 DPRINT1("Menu item ID: %d\n", CmdId
);
271 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
273 er
.EventType
= MENU_EVENT
;
274 er
.Event
.MenuEvent
.dwCommandId
= CmdId
;
275 ConioProcessInputEvent(Console
, &er
);
277 LeaveCriticalSection(&Console
->Lock
);
281 Copy(PGUI_CONSOLE_DATA GuiData
);
283 Paste(PGUI_CONSOLE_DATA GuiData
);
285 UpdateSelection(PGUI_CONSOLE_DATA GuiData
, PCOORD coord
);
288 Mark(PGUI_CONSOLE_DATA GuiData
)
290 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= GuiData
->ActiveBuffer
;
292 /* Clear the old selection */
293 // UpdateSelection(GuiData, NULL);
294 GuiData
->Selection
.dwFlags
= CONSOLE_NO_SELECTION
;
296 /* Restart a new selection */
297 GuiData
->dwSelectionCursor
.X
= ActiveBuffer
->ViewOrigin
.X
;
298 GuiData
->dwSelectionCursor
.Y
= ActiveBuffer
->ViewOrigin
.Y
;
299 GuiData
->Selection
.dwSelectionAnchor
= GuiData
->dwSelectionCursor
;
300 UpdateSelection(GuiData
, &GuiData
->Selection
.dwSelectionAnchor
);
304 SelectAll(PGUI_CONSOLE_DATA GuiData
)
306 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= GuiData
->ActiveBuffer
;
308 /* Clear the old selection */
309 // UpdateSelection(GuiData, NULL);
310 GuiData
->Selection
.dwFlags
= CONSOLE_NO_SELECTION
;
313 * The selection area extends to the whole screen buffer's width.
315 GuiData
->Selection
.dwSelectionAnchor
.X
= 0;
316 GuiData
->Selection
.dwSelectionAnchor
.Y
= 0;
317 GuiData
->dwSelectionCursor
.X
= ActiveBuffer
->ScreenBufferSize
.X
- 1;
320 * Determine whether the selection must extend to just some part
321 * (for text-mode screen buffers) or to all of the screen buffer's
322 * height (for graphics ones).
324 if (GetType(ActiveBuffer
) == TEXTMODE_BUFFER
)
327 * We select all the characters from the first line
328 * to the line where the cursor is positioned.
330 GuiData
->dwSelectionCursor
.Y
= ActiveBuffer
->CursorPosition
.Y
;
332 else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
335 * We select all the screen buffer area.
337 GuiData
->dwSelectionCursor
.Y
= ActiveBuffer
->ScreenBufferSize
.Y
- 1;
340 /* Restart a new selection */
341 GuiData
->Selection
.dwFlags
|= CONSOLE_MOUSE_SELECTION
;
342 UpdateSelection(GuiData
, &GuiData
->dwSelectionCursor
);
346 OnCommand(PGUI_CONSOLE_DATA GuiData
, WPARAM wParam
, LPARAM lParam
)
349 PCONSOLE Console
= GuiData
->Console
;
352 * In case the selected menu item belongs to the user-reserved menu id range,
353 * send to him a menu event and return directly. The user must handle those
354 * reserved menu commands...
356 if (GuiData
->CmdIdLow
<= (UINT
)wParam
&& (UINT
)wParam
<= GuiData
->CmdIdHigh
)
358 SendMenuEvent(Console
, (UINT
)wParam
);
362 /* ... otherwise, perform actions. */
365 case ID_SYSTEM_EDIT_MARK
:
369 case ID_SYSTEM_EDIT_COPY
:
373 case ID_SYSTEM_EDIT_PASTE
:
377 case ID_SYSTEM_EDIT_SELECTALL
:
381 case ID_SYSTEM_EDIT_SCROLL
:
382 DPRINT1("Scrolling is not handled yet\n");
385 case ID_SYSTEM_EDIT_FIND
:
386 DPRINT1("Finding is not handled yet\n");
389 case ID_SYSTEM_DEFAULTS
:
390 GuiConsoleShowConsoleProperties(GuiData
, TRUE
);
393 case ID_SYSTEM_PROPERTIES
:
394 GuiConsoleShowConsoleProperties(GuiData
, FALSE
);
404 Ret
= DefWindowProcW(GuiData
->hWindow
, WM_SYSCOMMAND
, wParam
, lParam
);
409 static PGUI_CONSOLE_DATA
410 GuiGetGuiData(HWND hWnd
)
412 /* This function ensures that the console pointer is not NULL */
413 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
414 return ( ((GuiData
== NULL
) || (GuiData
->hWindow
== hWnd
&& GuiData
->Console
!= NULL
)) ? GuiData
: NULL
);
418 ResizeConWnd(PGUI_CONSOLE_DATA GuiData
, DWORD WidthUnit
, DWORD HeightUnit
)
420 PCONSOLE_SCREEN_BUFFER Buff
= GuiData
->ActiveBuffer
;
425 Width
= Buff
->ViewSize
.X
* WidthUnit
+
426 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
427 Height
= Buff
->ViewSize
.Y
* HeightUnit
+
428 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
430 /* Set scrollbar sizes */
431 sInfo
.cbSize
= sizeof(SCROLLINFO
);
432 sInfo
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
434 if (Buff
->ScreenBufferSize
.Y
> Buff
->ViewSize
.Y
)
436 sInfo
.nMax
= Buff
->ScreenBufferSize
.Y
- 1;
437 sInfo
.nPage
= Buff
->ViewSize
.Y
;
438 sInfo
.nPos
= Buff
->ViewOrigin
.Y
;
439 SetScrollInfo(GuiData
->hWindow
, SB_VERT
, &sInfo
, TRUE
);
440 Width
+= GetSystemMetrics(SM_CXVSCROLL
);
441 ShowScrollBar(GuiData
->hWindow
, SB_VERT
, TRUE
);
445 ShowScrollBar(GuiData
->hWindow
, SB_VERT
, FALSE
);
448 if (Buff
->ScreenBufferSize
.X
> Buff
->ViewSize
.X
)
450 sInfo
.nMax
= Buff
->ScreenBufferSize
.X
- 1;
451 sInfo
.nPage
= Buff
->ViewSize
.X
;
452 sInfo
.nPos
= Buff
->ViewOrigin
.X
;
453 SetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &sInfo
, TRUE
);
454 Height
+= GetSystemMetrics(SM_CYHSCROLL
);
455 ShowScrollBar(GuiData
->hWindow
, SB_HORZ
, TRUE
);
459 ShowScrollBar(GuiData
->hWindow
, SB_HORZ
, FALSE
);
462 /* Resize the window */
463 SetWindowPos(GuiData
->hWindow
, NULL
, 0, 0, Width
, Height
,
464 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
);
465 // NOTE: The SWP_NOCOPYBITS flag can be replaced by a subsequent call
466 // to: InvalidateRect(GuiData->hWindow, NULL, TRUE);
470 OnNcCreate(HWND hWnd
, LPCREATESTRUCTW Create
)
472 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Create
->lpCreateParams
;
481 DPRINT1("GuiConsoleNcCreate: No GUI data\n");
485 Console
= GuiData
->Console
;
487 GuiData
->hWindow
= hWnd
;
489 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->GuiInfo
.FontSize
),
490 0, // HIWORD(GuiData->GuiInfo.FontSize),
493 GuiData
->GuiInfo
.FontWeight
,
500 NONANTIALIASED_QUALITY
,
501 FIXED_PITCH
| GuiData
->GuiInfo
.FontFamily
/* FF_DONTCARE */,
502 GuiData
->GuiInfo
.FaceName
);
504 if (NULL
== GuiData
->Font
)
506 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
507 GuiData
->hWindow
= NULL
;
508 SetEvent(GuiData
->hGuiInitEvent
);
511 hDC
= GetDC(GuiData
->hWindow
);
514 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
515 DeleteObject(GuiData
->Font
);
516 GuiData
->hWindow
= NULL
;
517 SetEvent(GuiData
->hGuiInitEvent
);
520 OldFont
= SelectObject(hDC
, GuiData
->Font
);
523 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
524 ReleaseDC(GuiData
->hWindow
, hDC
);
525 DeleteObject(GuiData
->Font
);
526 GuiData
->hWindow
= NULL
;
527 SetEvent(GuiData
->hGuiInitEvent
);
530 if (!GetTextMetricsW(hDC
, &Metrics
))
532 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
533 SelectObject(hDC
, OldFont
);
534 ReleaseDC(GuiData
->hWindow
, hDC
);
535 DeleteObject(GuiData
->Font
);
536 GuiData
->hWindow
= NULL
;
537 SetEvent(GuiData
->hGuiInitEvent
);
540 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
541 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
543 /* Measure real char width more precisely if possible. */
544 if (GetTextExtentPoint32W(hDC
, L
"R", 1, &CharSize
))
545 GuiData
->CharWidth
= CharSize
.cx
;
547 SelectObject(hDC
, OldFont
);
549 ReleaseDC(GuiData
->hWindow
, hDC
);
551 /* Initialize the terminal framebuffer */
552 GuiData
->hMemDC
= CreateCompatibleDC(NULL
);
553 GuiData
->hBitmap
= NULL
;
554 GuiData
->hSysPalette
= NULL
; /* Original system palette */
556 /* Update the icons of the window */
557 if (GuiData
->hIcon
!= ghDefaultIcon
)
559 DefWindowProcW(GuiData
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)GuiData
->hIcon
);
560 DefWindowProcW(GuiData
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)GuiData
->hIconSm
);
563 // FIXME: Keep these instructions here ? ///////////////////////////////////
564 Console
->ActiveBuffer
->CursorBlinkOn
= TRUE
;
565 Console
->ActiveBuffer
->ForceCursorOff
= FALSE
;
566 ////////////////////////////////////////////////////////////////////////////
568 SetWindowLongPtrW(GuiData
->hWindow
, GWLP_USERDATA
, (DWORD_PTR
)GuiData
);
570 SetTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
571 CreateSysMenu(GuiData
->hWindow
);
573 DPRINT("OnNcCreate - setting start event\n");
574 SetEvent(GuiData
->hGuiInitEvent
);
576 return (BOOL
)DefWindowProcW(GuiData
->hWindow
, WM_NCCREATE
, 0, (LPARAM
)Create
);
581 EnterFullScreen(PGUI_CONSOLE_DATA GuiData
);
583 LeaveFullScreen(PGUI_CONSOLE_DATA GuiData
);
585 SwitchFullScreen(PGUI_CONSOLE_DATA GuiData
, BOOL FullScreen
);
587 GuiConsoleSwitchFullScreen(PGUI_CONSOLE_DATA GuiData
);
590 OnActivate(PGUI_CONSOLE_DATA GuiData
, WPARAM wParam
)
592 PCONSOLE Console
= GuiData
->Console
;
593 WORD ActivationState
= LOWORD(wParam
);
595 DPRINT1("WM_ACTIVATE - ActivationState = %d\n");
597 if ( ActivationState
== WA_ACTIVE
||
598 ActivationState
== WA_CLICKACTIVE
)
600 if (GuiData
->GuiInfo
.FullScreen
)
602 EnterFullScreen(GuiData
);
603 // // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
604 // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
607 else // if (ActivationState == WA_INACTIVE)
609 if (GuiData
->GuiInfo
.FullScreen
)
611 SendMessageW(GuiData
->hWindow
, WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
612 LeaveFullScreen(GuiData
);
613 // // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
614 // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
619 * When we are in QuickEdit mode, ignore the next mouse signal
620 * when we are going to be enabled again via the mouse, in order
621 * to prevent e.g. an erroneous right-click from the user which
622 * would have as an effect to paste some unwanted text...
624 if (Console
->QuickEdit
&& (ActivationState
== WA_CLICKACTIVE
))
625 GuiData
->IgnoreNextMouseSignal
= TRUE
;
629 OnFocus(PGUI_CONSOLE_DATA GuiData
, BOOL SetFocus
)
631 PCONSOLE Console
= GuiData
->Console
;
634 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
636 er
.EventType
= FOCUS_EVENT
;
637 er
.Event
.FocusEvent
.bSetFocus
= SetFocus
;
638 ConioProcessInputEvent(Console
, &er
);
640 LeaveCriticalSection(&Console
->Lock
);
643 DPRINT1("TODO: Create console caret\n");
645 DPRINT1("TODO: Destroy console caret\n");
649 SmallRectToRect(PGUI_CONSOLE_DATA GuiData
, PRECT Rect
, PSMALL_RECT SmallRect
)
651 PCONSOLE_SCREEN_BUFFER Buffer
= GuiData
->ActiveBuffer
;
652 UINT WidthUnit
, HeightUnit
;
654 GetScreenBufferSizeUnits(Buffer
, GuiData
, &WidthUnit
, &HeightUnit
);
656 Rect
->left
= (SmallRect
->Left
- Buffer
->ViewOrigin
.X
) * WidthUnit
;
657 Rect
->top
= (SmallRect
->Top
- Buffer
->ViewOrigin
.Y
) * HeightUnit
;
658 Rect
->right
= (SmallRect
->Right
+ 1 - Buffer
->ViewOrigin
.X
) * WidthUnit
;
659 Rect
->bottom
= (SmallRect
->Bottom
+ 1 - Buffer
->ViewOrigin
.Y
) * HeightUnit
;
663 UpdateSelection(PGUI_CONSOLE_DATA GuiData
, PCOORD coord
)
665 PCONSOLE Console
= GuiData
->Console
;
668 SmallRectToRect(GuiData
, &oldRect
, &GuiData
->Selection
.srSelection
);
675 /* Exchange left/top with right/bottom if required */
676 rc
.Left
= min(GuiData
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
677 rc
.Top
= min(GuiData
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
678 rc
.Right
= max(GuiData
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
679 rc
.Bottom
= max(GuiData
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
681 SmallRectToRect(GuiData
, &newRect
, &rc
);
683 if (GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
685 if (memcmp(&rc
, &GuiData
->Selection
.srSelection
, sizeof(SMALL_RECT
)) != 0)
689 /* Calculate the region that needs to be updated */
690 if ((rgn1
= CreateRectRgnIndirect(&oldRect
)))
692 if ((rgn2
= CreateRectRgnIndirect(&newRect
)))
694 if (CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
696 InvalidateRgn(GuiData
->hWindow
, rgn1
, FALSE
);
706 InvalidateRect(GuiData
->hWindow
, &newRect
, FALSE
);
709 GuiData
->Selection
.dwFlags
|= CONSOLE_SELECTION_NOT_EMPTY
;
710 GuiData
->Selection
.srSelection
= rc
;
711 GuiData
->dwSelectionCursor
= *coord
;
713 if ((GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_IN_PROGRESS
) == 0)
715 LPWSTR SelectionType
, WindowTitle
= NULL
;
718 /* Clear the old selection */
719 if (GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
721 InvalidateRect(GuiData
->hWindow
, &oldRect
, FALSE
);
724 if (GuiData
->Selection
.dwFlags
& CONSOLE_MOUSE_SELECTION
)
726 SelectionType
= L
"Selection - ";
730 SelectionType
= L
"Mark - ";
733 Length
= Console
->Title
.Length
+ wcslen(SelectionType
) + 1;
734 WindowTitle
= ConsoleAllocHeap(0, Length
* sizeof(WCHAR
));
735 wcscpy(WindowTitle
, SelectionType
);
736 wcscat(WindowTitle
, Console
->Title
.Buffer
);
737 SetWindowText(GuiData
->hWindow
, WindowTitle
);
738 ConsoleFreeHeap(WindowTitle
);
740 GuiData
->Selection
.dwFlags
|= CONSOLE_SELECTION_IN_PROGRESS
;
741 ConioPause(Console
, PAUSED_FROM_SELECTION
);
746 /* Clear the selection */
747 if (GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
749 InvalidateRect(GuiData
->hWindow
, &oldRect
, FALSE
);
752 GuiData
->Selection
.dwFlags
= CONSOLE_NO_SELECTION
;
753 ConioUnpause(Console
, PAUSED_FROM_SELECTION
);
755 SetWindowText(GuiData
->hWindow
, Console
->Title
.Buffer
);
761 GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer
,
762 PGUI_CONSOLE_DATA GuiData
,
764 PRECT rcFramebuffer
);
766 GuiPaintGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer
,
767 PGUI_CONSOLE_DATA GuiData
,
769 PRECT rcFramebuffer
);
772 OnPaint(PGUI_CONSOLE_DATA GuiData
)
774 PCONSOLE_SCREEN_BUFFER ActiveBuffer
;
778 ActiveBuffer
= GuiData
->ActiveBuffer
;
780 BeginPaint(GuiData
->hWindow
, &ps
);
781 if (ps
.hdc
!= NULL
&&
782 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
783 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
785 EnterCriticalSection(&GuiData
->Lock
);
787 /* Compose the current screen-buffer on-memory */
788 if (GetType(ActiveBuffer
) == TEXTMODE_BUFFER
)
790 GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER
)ActiveBuffer
,
791 GuiData
, &ps
.rcPaint
, &rcPaint
);
793 else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
795 GuiPaintGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER
)ActiveBuffer
,
796 GuiData
, &ps
.rcPaint
, &rcPaint
);
799 /* Send it to screen */
803 rcPaint
.right
- rcPaint
.left
,
804 rcPaint
.bottom
- rcPaint
.top
,
810 if (GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
812 SmallRectToRect(GuiData
, &rcPaint
, &GuiData
->Selection
.srSelection
);
814 /* Invert the selection */
815 if (IntersectRect(&rcPaint
, &ps
.rcPaint
, &rcPaint
))
817 InvertRect(ps
.hdc
, &rcPaint
);
821 LeaveCriticalSection(&GuiData
->Lock
);
823 EndPaint(GuiData
->hWindow
, &ps
);
829 OnPaletteChanged(PGUI_CONSOLE_DATA GuiData
)
831 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= GuiData
->ActiveBuffer
;
833 // See WM_PALETTECHANGED message
834 // if ((HWND)wParam == hWnd) break;
836 // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
837 if (ActiveBuffer
->PaletteHandle
)
839 DPRINT("WM_PALETTECHANGED changing palette\n");
841 /* Specify the use of the system palette for the framebuffer */
842 SetSystemPaletteUse(GuiData
->hMemDC
, ActiveBuffer
->PaletteUsage
);
844 /* Realize the (logical) palette */
845 RealizePalette(GuiData
->hMemDC
);
850 IsSystemKey(WORD VirtualKeyCode
)
852 switch (VirtualKeyCode
)
854 /* From MSDN, "Virtual-Key Codes" */
873 OnKey(PGUI_CONSOLE_DATA GuiData
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
875 PCONSOLE Console
= GuiData
->Console
;
876 PCONSOLE_SCREEN_BUFFER ActiveBuffer
;
878 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
880 ActiveBuffer
= GuiData
->ActiveBuffer
;
882 if (GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_IN_PROGRESS
)
884 WORD VirtualKeyCode
= LOWORD(wParam
);
886 if (msg
!= WM_KEYDOWN
) goto Quit
;
888 if (VirtualKeyCode
== VK_RETURN
)
890 /* Copy (and clear) selection if ENTER is pressed */
894 else if ( VirtualKeyCode
== VK_ESCAPE
||
895 (VirtualKeyCode
== 'C' && GetKeyState(VK_CONTROL
) & 0x8000) )
897 /* Cancel selection if ESC or Ctrl-C are pressed */
898 UpdateSelection(GuiData
, NULL
);
902 if ((GuiData
->Selection
.dwFlags
& CONSOLE_MOUSE_SELECTION
) == 0)
904 /* Keyboard selection mode */
905 BOOL Interpreted
= FALSE
;
906 BOOL MajPressed
= (GetKeyState(VK_SHIFT
) & 0x8000);
908 switch (VirtualKeyCode
)
913 if (GuiData
->dwSelectionCursor
.X
> 0)
914 GuiData
->dwSelectionCursor
.X
--;
922 if (GuiData
->dwSelectionCursor
.X
< ActiveBuffer
->ScreenBufferSize
.X
- 1)
923 GuiData
->dwSelectionCursor
.X
++;
931 if (GuiData
->dwSelectionCursor
.Y
> 0)
932 GuiData
->dwSelectionCursor
.Y
--;
940 if (GuiData
->dwSelectionCursor
.Y
< ActiveBuffer
->ScreenBufferSize
.Y
- 1)
941 GuiData
->dwSelectionCursor
.Y
++;
949 GuiData
->dwSelectionCursor
.X
= 0;
950 GuiData
->dwSelectionCursor
.Y
= 0;
957 GuiData
->dwSelectionCursor
.Y
= ActiveBuffer
->ScreenBufferSize
.Y
- 1;
964 GuiData
->dwSelectionCursor
.Y
-= ActiveBuffer
->ViewSize
.Y
;
965 if (GuiData
->dwSelectionCursor
.Y
< 0)
966 GuiData
->dwSelectionCursor
.Y
= 0;
974 GuiData
->dwSelectionCursor
.Y
+= ActiveBuffer
->ViewSize
.Y
;
975 if (GuiData
->dwSelectionCursor
.Y
>= ActiveBuffer
->ScreenBufferSize
.Y
)
976 GuiData
->dwSelectionCursor
.Y
= ActiveBuffer
->ScreenBufferSize
.Y
- 1;
988 GuiData
->Selection
.dwSelectionAnchor
= GuiData
->dwSelectionCursor
;
990 UpdateSelection(GuiData
, &GuiData
->dwSelectionCursor
);
992 else if (!IsSystemKey(VirtualKeyCode
))
994 /* Emit an error beep sound */
995 SendNotifyMessage(GuiData
->hWindow
, PM_CONSOLE_BEEP
, 0, 0);
1002 /* Mouse selection mode */
1004 if (!IsSystemKey(VirtualKeyCode
))
1006 /* Clear the selection and send the key into the input buffer */
1007 UpdateSelection(GuiData
, NULL
);
1016 if ((GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_IN_PROGRESS
) == 0)
1020 Message
.hwnd
= GuiData
->hWindow
;
1021 Message
.message
= msg
;
1022 Message
.wParam
= wParam
;
1023 Message
.lParam
= lParam
;
1025 ConioProcessKey(Console
, &Message
);
1029 LeaveCriticalSection(&Console
->Lock
);
1033 // FIXME: Remove after fixing OnTimer
1035 InvalidateCell(PGUI_CONSOLE_DATA GuiData
,
1039 OnTimer(PGUI_CONSOLE_DATA GuiData
)
1041 PCONSOLE Console
= GuiData
->Console
;
1042 PCONSOLE_SCREEN_BUFFER Buff
;
1044 SetTimer(GuiData
->hWindow
, CONGUI_UPDATE_TIMER
, CURSOR_BLINK_TIME
, NULL
);
1046 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
1048 Buff
= GuiData
->ActiveBuffer
;
1050 if (GetType(Buff
) == TEXTMODE_BUFFER
)
1052 InvalidateCell(GuiData
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
1053 Buff
->CursorBlinkOn
= !Buff
->CursorBlinkOn
;
1055 if ((GuiData
->OldCursor
.x
!= Buff
->CursorPosition
.X
) ||
1056 (GuiData
->OldCursor
.y
!= Buff
->CursorPosition
.Y
))
1059 int OldScrollX
= -1, OldScrollY
= -1;
1060 int NewScrollX
= -1, NewScrollY
= -1;
1062 xScroll
.cbSize
= sizeof(SCROLLINFO
);
1063 xScroll
.fMask
= SIF_POS
;
1064 // Capture the original position of the scroll bars and save them.
1065 if (GetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &xScroll
)) OldScrollX
= xScroll
.nPos
;
1066 if (GetScrollInfo(GuiData
->hWindow
, SB_VERT
, &xScroll
)) OldScrollY
= xScroll
.nPos
;
1068 // If we successfully got the info for the horizontal scrollbar
1069 if (OldScrollX
>= 0)
1071 if ((Buff
->CursorPosition
.X
< Buff
->ViewOrigin
.X
) ||
1072 (Buff
->CursorPosition
.X
>= (Buff
->ViewOrigin
.X
+ Buff
->ViewSize
.X
)))
1074 // Handle the horizontal scroll bar
1075 if (Buff
->CursorPosition
.X
>= Buff
->ViewSize
.X
)
1076 NewScrollX
= Buff
->CursorPosition
.X
- Buff
->ViewSize
.X
+ 1;
1082 NewScrollX
= OldScrollX
;
1085 // If we successfully got the info for the vertical scrollbar
1086 if (OldScrollY
>= 0)
1088 if ((Buff
->CursorPosition
.Y
< Buff
->ViewOrigin
.Y
) ||
1089 (Buff
->CursorPosition
.Y
>= (Buff
->ViewOrigin
.Y
+ Buff
->ViewSize
.Y
)))
1091 // Handle the vertical scroll bar
1092 if (Buff
->CursorPosition
.Y
>= Buff
->ViewSize
.Y
)
1093 NewScrollY
= Buff
->CursorPosition
.Y
- Buff
->ViewSize
.Y
+ 1;
1099 NewScrollY
= OldScrollY
;
1103 // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
1104 // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
1105 // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
1106 // and their associated scrollbar is left alone.
1107 if ((OldScrollX
!= NewScrollX
) || (OldScrollY
!= NewScrollY
))
1109 Buff
->ViewOrigin
.X
= NewScrollX
;
1110 Buff
->ViewOrigin
.Y
= NewScrollY
;
1111 ScrollWindowEx(GuiData
->hWindow
,
1112 (OldScrollX
- NewScrollX
) * GuiData
->CharWidth
,
1113 (OldScrollY
- NewScrollY
) * GuiData
->CharHeight
,
1119 if (NewScrollX
>= 0)
1121 xScroll
.nPos
= NewScrollX
;
1122 SetScrollInfo(GuiData
->hWindow
, SB_HORZ
, &xScroll
, TRUE
);
1124 if (NewScrollY
>= 0)
1126 xScroll
.nPos
= NewScrollY
;
1127 SetScrollInfo(GuiData
->hWindow
, SB_VERT
, &xScroll
, TRUE
);
1129 UpdateWindow(GuiData
->hWindow
);
1130 // InvalidateRect(GuiData->hWindow, NULL, FALSE);
1131 GuiData
->OldCursor
.x
= Buff
->CursorPosition
.X
;
1132 GuiData
->OldCursor
.y
= Buff
->CursorPosition
.Y
;
1136 else /* if (GetType(Buff) == GRAPHICS_BUFFER) */
1140 LeaveCriticalSection(&Console
->Lock
);
1144 OnClose(PGUI_CONSOLE_DATA GuiData
)
1146 PCONSOLE Console
= GuiData
->Console
;
1148 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
))
1151 // TODO: Prompt for termination ? (Warn the user about possible apps running in this console)
1154 * FIXME: Windows will wait up to 5 seconds for the thread to exit.
1155 * We shouldn't wait here, though, since the console lock is entered.
1156 * A copy of the thread list probably needs to be made.
1158 ConDrvConsoleProcessCtrlEvent(Console
, 0, CTRL_CLOSE_EVENT
);
1160 LeaveCriticalSection(&Console
->Lock
);
1165 OnNcDestroy(HWND hWnd
)
1167 PGUI_CONSOLE_DATA GuiData
= GuiGetGuiData(hWnd
);
1169 KillTimer(hWnd
, CONGUI_UPDATE_TIMER
);
1170 GetSystemMenu(hWnd
, TRUE
);
1174 /* Free the terminal framebuffer */
1175 if (GuiData
->hMemDC
) DeleteDC(GuiData
->hMemDC
);
1176 if (GuiData
->hBitmap
) DeleteObject(GuiData
->hBitmap
);
1177 // if (GuiData->hSysPalette) DeleteObject(GuiData->hSysPalette);
1178 if (GuiData
->Font
) DeleteObject(GuiData
->Font
);
1181 /* Free the GuiData registration */
1182 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (DWORD_PTR
)NULL
);
1184 return DefWindowProcW(hWnd
, WM_NCDESTROY
, 0, 0);
1188 PointToCoord(PGUI_CONSOLE_DATA GuiData
, LPARAM lParam
)
1190 PCONSOLE_SCREEN_BUFFER Buffer
= GuiData
->ActiveBuffer
;
1192 UINT WidthUnit
, HeightUnit
;
1194 GetScreenBufferSizeUnits(Buffer
, GuiData
, &WidthUnit
, &HeightUnit
);
1196 Coord
.X
= Buffer
->ViewOrigin
.X
+ ((SHORT
)LOWORD(lParam
) / (int)WidthUnit
);
1197 Coord
.Y
= Buffer
->ViewOrigin
.Y
+ ((SHORT
)HIWORD(lParam
) / (int)HeightUnit
);
1199 /* Clip coordinate to ensure it's inside buffer */
1202 else if (Coord
.X
>= Buffer
->ScreenBufferSize
.X
)
1203 Coord
.X
= Buffer
->ScreenBufferSize
.X
- 1;
1207 else if (Coord
.Y
>= Buffer
->ScreenBufferSize
.Y
)
1208 Coord
.Y
= Buffer
->ScreenBufferSize
.Y
- 1;
1214 OnMouse(PGUI_CONSOLE_DATA GuiData
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1217 PCONSOLE Console
= GuiData
->Console
;
1219 if (GuiData
->IgnoreNextMouseSignal
)
1221 if (msg
!= WM_LBUTTONDOWN
&&
1222 msg
!= WM_MBUTTONDOWN
&&
1223 msg
!= WM_RBUTTONDOWN
&&
1224 msg
!= WM_MOUSEMOVE
)
1227 * If this mouse signal is not a button-down action or a move,
1228 * then it is the last signal being ignored.
1230 GuiData
->IgnoreNextMouseSignal
= FALSE
;
1235 * This mouse signal is a button-down action or a move.
1236 * Ignore it and perform default action.
1243 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
))
1249 if ( (GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_IN_PROGRESS
) ||
1250 (Console
->QuickEdit
) )
1254 case WM_LBUTTONDOWN
:
1256 /* Clear the old selection */
1257 // UpdateSelection(GuiData, NULL);
1258 GuiData
->Selection
.dwFlags
= CONSOLE_NO_SELECTION
;
1260 /* Restart a new selection */
1261 GuiData
->Selection
.dwSelectionAnchor
= PointToCoord(GuiData
, lParam
);
1262 SetCapture(GuiData
->hWindow
);
1263 GuiData
->Selection
.dwFlags
|= CONSOLE_MOUSE_SELECTION
| CONSOLE_MOUSE_DOWN
;
1264 UpdateSelection(GuiData
, &GuiData
->Selection
.dwSelectionAnchor
);
1273 if (!(GuiData
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) break;
1275 // c = PointToCoord(GuiData, lParam);
1276 GuiData
->Selection
.dwFlags
&= ~CONSOLE_MOUSE_DOWN
;
1277 // UpdateSelection(GuiData, &c);
1283 case WM_LBUTTONDBLCLK
:
1285 PCONSOLE_SCREEN_BUFFER Buffer
= GuiData
->ActiveBuffer
;
1287 if (GetType(Buffer
) == TEXTMODE_BUFFER
)
1289 #ifdef IS_WHITESPACE
1290 #undef IS_WHITESPACE
1292 #define IS_WHITESPACE(c) \
1293 ((c) == L'\0' || (c) == L' ' || (c) == L'\t' || (c) == L'\r' || (c) == L'\n')
1295 PTEXTMODE_SCREEN_BUFFER TextBuffer
= (PTEXTMODE_SCREEN_BUFFER
)Buffer
;
1297 PCHAR_INFO ptrL
, ptrR
;
1299 /* Starting point */
1300 cL
= cR
= PointToCoord(GuiData
, lParam
);
1301 ptrL
= ptrR
= ConioCoordToPointer(TextBuffer
, cL
.X
, cL
.Y
);
1303 /* Enlarge the selection by checking for whitespace */
1304 while ((0 < cL
.X
) && !IS_WHITESPACE(ptrL
->Char
.UnicodeChar
)
1305 && !IS_WHITESPACE((ptrL
-1)->Char
.UnicodeChar
))
1310 while ((cR
.X
< TextBuffer
->ScreenBufferSize
.X
- 1) &&
1311 !IS_WHITESPACE(ptrR
->Char
.UnicodeChar
) &&
1312 !IS_WHITESPACE((ptrR
+1)->Char
.UnicodeChar
))
1319 * Update the selection started with the single
1320 * left-click that preceded this double-click.
1322 GuiData
->Selection
.dwSelectionAnchor
= cL
;
1323 GuiData
->dwSelectionCursor
= cR
;
1325 GuiData
->Selection
.dwFlags
|= CONSOLE_MOUSE_SELECTION
| CONSOLE_MOUSE_DOWN
;
1326 UpdateSelection(GuiData
, &GuiData
->dwSelectionCursor
);
1328 /* Ignore the next mouse move signal */
1329 GuiData
->IgnoreNextMouseSignal
= TRUE
;
1335 case WM_RBUTTONDOWN
:
1336 case WM_RBUTTONDBLCLK
:
1338 if (!(GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
))
1347 /* Ignore the next mouse move signal */
1348 GuiData
->IgnoreNextMouseSignal
= TRUE
;
1356 if (!(wParam
& MK_LBUTTON
)) break;
1357 if (!(GuiData
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) break;
1359 c
= PointToCoord(GuiData
, lParam
); /* TODO: Scroll buffer to bring c into view */
1360 UpdateSelection(GuiData
, &c
);
1366 Err
= FALSE
; // TRUE;
1370 else if (Console
->InputBuffer
.Mode
& ENABLE_MOUSE_INPUT
)
1373 WORD wKeyState
= GET_KEYSTATE_WPARAM(wParam
);
1374 DWORD dwButtonState
= 0;
1375 DWORD dwControlKeyState
= 0;
1376 DWORD dwEventFlags
= 0;
1380 case WM_LBUTTONDOWN
:
1381 SetCapture(GuiData
->hWindow
);
1382 dwButtonState
= FROM_LEFT_1ST_BUTTON_PRESSED
;
1386 case WM_MBUTTONDOWN
:
1387 SetCapture(GuiData
->hWindow
);
1388 dwButtonState
= FROM_LEFT_2ND_BUTTON_PRESSED
;
1392 case WM_RBUTTONDOWN
:
1393 SetCapture(GuiData
->hWindow
);
1394 dwButtonState
= RIGHTMOST_BUTTON_PRESSED
;
1416 case WM_LBUTTONDBLCLK
:
1417 dwButtonState
= FROM_LEFT_1ST_BUTTON_PRESSED
;
1418 dwEventFlags
= DOUBLE_CLICK
;
1421 case WM_MBUTTONDBLCLK
:
1422 dwButtonState
= FROM_LEFT_2ND_BUTTON_PRESSED
;
1423 dwEventFlags
= DOUBLE_CLICK
;
1426 case WM_RBUTTONDBLCLK
:
1427 dwButtonState
= RIGHTMOST_BUTTON_PRESSED
;
1428 dwEventFlags
= DOUBLE_CLICK
;
1433 dwEventFlags
= MOUSE_MOVED
;
1437 dwButtonState
= GET_WHEEL_DELTA_WPARAM(wParam
) << 16;
1438 dwEventFlags
= MOUSE_WHEELED
;
1441 case WM_MOUSEHWHEEL
:
1442 dwButtonState
= GET_WHEEL_DELTA_WPARAM(wParam
) << 16;
1443 dwEventFlags
= MOUSE_HWHEELED
;
1453 if (wKeyState
& MK_LBUTTON
)
1454 dwButtonState
|= FROM_LEFT_1ST_BUTTON_PRESSED
;
1455 if (wKeyState
& MK_MBUTTON
)
1456 dwButtonState
|= FROM_LEFT_2ND_BUTTON_PRESSED
;
1457 if (wKeyState
& MK_RBUTTON
)
1458 dwButtonState
|= RIGHTMOST_BUTTON_PRESSED
;
1460 if (GetKeyState(VK_RMENU
) & 0x8000)
1461 dwControlKeyState
|= RIGHT_ALT_PRESSED
;
1462 if (GetKeyState(VK_LMENU
) & 0x8000)
1463 dwControlKeyState
|= LEFT_ALT_PRESSED
;
1464 if (GetKeyState(VK_RCONTROL
) & 0x8000)
1465 dwControlKeyState
|= RIGHT_CTRL_PRESSED
;
1466 if (GetKeyState(VK_LCONTROL
) & 0x8000)
1467 dwControlKeyState
|= LEFT_CTRL_PRESSED
;
1468 if (GetKeyState(VK_SHIFT
) & 0x8000)
1469 dwControlKeyState
|= SHIFT_PRESSED
;
1470 if (GetKeyState(VK_NUMLOCK
) & 0x0001)
1471 dwControlKeyState
|= NUMLOCK_ON
;
1472 if (GetKeyState(VK_SCROLL
) & 0x0001)
1473 dwControlKeyState
|= SCROLLLOCK_ON
;
1474 if (GetKeyState(VK_CAPITAL
) & 0x0001)
1475 dwControlKeyState
|= CAPSLOCK_ON
;
1476 /* See WM_CHAR MSDN documentation for instance */
1477 if (lParam
& 0x01000000)
1478 dwControlKeyState
|= ENHANCED_KEY
;
1480 er
.EventType
= MOUSE_EVENT
;
1481 er
.Event
.MouseEvent
.dwMousePosition
= PointToCoord(GuiData
, lParam
);
1482 er
.Event
.MouseEvent
.dwButtonState
= dwButtonState
;
1483 er
.Event
.MouseEvent
.dwControlKeyState
= dwControlKeyState
;
1484 er
.Event
.MouseEvent
.dwEventFlags
= dwEventFlags
;
1486 ConioProcessInputEvent(Console
, &er
);
1494 LeaveCriticalSection(&Console
->Lock
);
1498 return DefWindowProcW(GuiData
->hWindow
, msg
, wParam
, lParam
);
1504 GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer
,
1505 PGUI_CONSOLE_DATA GuiData
);
1507 GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer
,
1508 PGUI_CONSOLE_DATA GuiData
);
1511 Copy(PGUI_CONSOLE_DATA GuiData
)
1513 if (OpenClipboard(GuiData
->hWindow
) == TRUE
)
1515 PCONSOLE_SCREEN_BUFFER Buffer
= GuiData
->ActiveBuffer
;
1517 if (GetType(Buffer
) == TEXTMODE_BUFFER
)
1519 GuiCopyFromTextModeBuffer((PTEXTMODE_SCREEN_BUFFER
)Buffer
, GuiData
);
1521 else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
1523 GuiCopyFromGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER
)Buffer
, GuiData
);
1529 /* Clear the selection */
1530 UpdateSelection(GuiData
, NULL
);
1534 GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer
,
1535 PGUI_CONSOLE_DATA GuiData
);
1537 GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer
,
1538 PGUI_CONSOLE_DATA GuiData
);
1541 Paste(PGUI_CONSOLE_DATA GuiData
)
1543 if (OpenClipboard(GuiData
->hWindow
) == TRUE
)
1545 PCONSOLE_SCREEN_BUFFER Buffer
= GuiData
->ActiveBuffer
;
1547 if (GetType(Buffer
) == TEXTMODE_BUFFER
)
1549 GuiPasteToTextModeBuffer((PTEXTMODE_SCREEN_BUFFER
)Buffer
, GuiData
);
1551 else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
1553 GuiPasteToGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER
)Buffer
, GuiData
);
1561 OnGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData
, PMINMAXINFO minMaxInfo
)
1563 PCONSOLE Console
= GuiData
->Console
;
1564 PCONSOLE_SCREEN_BUFFER ActiveBuffer
;
1566 UINT WidthUnit
, HeightUnit
;
1568 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
1570 ActiveBuffer
= GuiData
->ActiveBuffer
;
1572 GetScreenBufferSizeUnits(ActiveBuffer
, GuiData
, &WidthUnit
, &HeightUnit
);
1574 windx
= CONGUI_MIN_WIDTH
* WidthUnit
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1575 windy
= CONGUI_MIN_HEIGHT
* HeightUnit
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1577 minMaxInfo
->ptMinTrackSize
.x
= windx
;
1578 minMaxInfo
->ptMinTrackSize
.y
= windy
;
1580 windx
= (ActiveBuffer
->ScreenBufferSize
.X
) * WidthUnit
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1581 windy
= (ActiveBuffer
->ScreenBufferSize
.Y
) * HeightUnit
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1583 if (ActiveBuffer
->ViewSize
.X
< ActiveBuffer
->ScreenBufferSize
.X
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1584 if (ActiveBuffer
->ViewSize
.Y
< ActiveBuffer
->ScreenBufferSize
.Y
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1586 minMaxInfo
->ptMaxTrackSize
.x
= windx
;
1587 minMaxInfo
->ptMaxTrackSize
.y
= windy
;
1589 LeaveCriticalSection(&Console
->Lock
);
1593 OnSize(PGUI_CONSOLE_DATA GuiData
, WPARAM wParam
, LPARAM lParam
)
1595 PCONSOLE Console
= GuiData
->Console
;
1597 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
1599 if ((GuiData
->WindowSizeLock
== FALSE
) &&
1600 (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
))
1602 PCONSOLE_SCREEN_BUFFER Buff
= GuiData
->ActiveBuffer
;
1603 DWORD windx
, windy
, charx
, chary
;
1604 UINT WidthUnit
, HeightUnit
;
1606 GetScreenBufferSizeUnits(Buff
, GuiData
, &WidthUnit
, &HeightUnit
);
1608 GuiData
->WindowSizeLock
= TRUE
;
1610 windx
= LOWORD(lParam
);
1611 windy
= HIWORD(lParam
);
1613 // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
1614 if (Buff
->ViewSize
.X
< Buff
->ScreenBufferSize
.X
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1615 if (Buff
->ViewSize
.Y
< Buff
->ScreenBufferSize
.Y
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1617 charx
= windx
/ (int)WidthUnit
;
1618 chary
= windy
/ (int)HeightUnit
;
1620 // Character alignment (round size up or down)
1621 if ((windx
% WidthUnit
) >= (WidthUnit
/ 2)) ++charx
;
1622 if ((windy
% HeightUnit
) >= (HeightUnit
/ 2)) ++chary
;
1624 // Compensate for added scroll bars in new window
1625 if (charx
< Buff
->ScreenBufferSize
.X
) windy
-= GetSystemMetrics(SM_CYHSCROLL
); // new window will have a horizontal scroll bar
1626 if (chary
< Buff
->ScreenBufferSize
.Y
) windx
-= GetSystemMetrics(SM_CXVSCROLL
); // new window will have a vertical scroll bar
1628 charx
= windx
/ (int)WidthUnit
;
1629 chary
= windy
/ (int)HeightUnit
;
1631 // Character alignment (round size up or down)
1632 if ((windx
% WidthUnit
) >= (WidthUnit
/ 2)) ++charx
;
1633 if ((windy
% HeightUnit
) >= (HeightUnit
/ 2)) ++chary
;
1636 if ((charx
!= Buff
->ViewSize
.X
) || (chary
!= Buff
->ViewSize
.Y
))
1638 Buff
->ViewSize
.X
= (charx
<= Buff
->ScreenBufferSize
.X
) ? charx
: Buff
->ScreenBufferSize
.X
;
1639 Buff
->ViewSize
.Y
= (chary
<= Buff
->ScreenBufferSize
.Y
) ? chary
: Buff
->ScreenBufferSize
.Y
;
1642 ResizeConWnd(GuiData
, WidthUnit
, HeightUnit
);
1644 // Adjust the start of the visible area if we are attempting to show nonexistent areas
1645 if ((Buff
->ScreenBufferSize
.X
- Buff
->ViewOrigin
.X
) < Buff
->ViewSize
.X
) Buff
->ViewOrigin
.X
= Buff
->ScreenBufferSize
.X
- Buff
->ViewSize
.X
;
1646 if ((Buff
->ScreenBufferSize
.Y
- Buff
->ViewOrigin
.Y
) < Buff
->ViewSize
.Y
) Buff
->ViewOrigin
.Y
= Buff
->ScreenBufferSize
.Y
- Buff
->ViewSize
.Y
;
1647 InvalidateRect(GuiData
->hWindow
, NULL
, TRUE
);
1649 GuiData
->WindowSizeLock
= FALSE
;
1652 LeaveCriticalSection(&Console
->Lock
);
1656 OnMove(PGUI_CONSOLE_DATA GuiData
)
1660 // TODO: Simplify the code.
1661 // See: GuiConsoleNotifyWndProc() PM_CREATE_CONSOLE.
1663 /* Retrieve our real position */
1664 GetWindowRect(GuiData
->hWindow
, &rcWnd
);
1665 GuiData
->GuiInfo
.WindowOrigin
.x
= rcWnd
.left
;
1666 GuiData
->GuiInfo
.WindowOrigin
.y
= rcWnd
.top
;
1670 // HACK: This functionality is standard for general scrollbars. Don't add it by hand.
1674 GuiConsoleHandleScrollbarMenu(VOID)
1678 hMenu = CreatePopupMenu();
1681 DPRINT("CreatePopupMenu failed\n");
1685 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1686 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1687 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1688 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1689 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1690 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1691 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1692 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1693 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1694 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1699 OnScroll(PGUI_CONSOLE_DATA GuiData
, UINT uMsg
, WPARAM wParam
)
1701 PCONSOLE Console
= GuiData
->Console
;
1702 PCONSOLE_SCREEN_BUFFER Buff
;
1705 int old_pos
, Maximum
;
1708 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return 0;
1710 Buff
= GuiData
->ActiveBuffer
;
1712 if (uMsg
== WM_HSCROLL
)
1715 Maximum
= Buff
->ScreenBufferSize
.X
- Buff
->ViewSize
.X
;
1716 pShowXY
= &Buff
->ViewOrigin
.X
;
1721 Maximum
= Buff
->ScreenBufferSize
.Y
- Buff
->ViewSize
.Y
;
1722 pShowXY
= &Buff
->ViewOrigin
.Y
;
1725 /* set scrollbar sizes */
1726 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1727 sInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_PAGE
| SIF_TRACKPOS
;
1729 if (!GetScrollInfo(GuiData
->hWindow
, fnBar
, &sInfo
)) goto Quit
;
1731 old_pos
= sInfo
.nPos
;
1733 switch (LOWORD(wParam
))
1744 sInfo
.nPos
-= sInfo
.nPage
;
1748 sInfo
.nPos
+= sInfo
.nPage
;
1752 sInfo
.nPos
= sInfo
.nTrackPos
;
1753 ConioPause(Console
, PAUSED_FROM_SCROLLBAR
);
1756 case SB_THUMBPOSITION
:
1757 ConioUnpause(Console
, PAUSED_FROM_SCROLLBAR
);
1761 sInfo
.nPos
= sInfo
.nMin
;
1765 sInfo
.nPos
= sInfo
.nMax
;
1772 sInfo
.nPos
= max(sInfo
.nPos
, 0);
1773 sInfo
.nPos
= min(sInfo
.nPos
, Maximum
);
1775 if (old_pos
!= sInfo
.nPos
)
1777 USHORT OldX
= Buff
->ViewOrigin
.X
;
1778 USHORT OldY
= Buff
->ViewOrigin
.Y
;
1779 UINT WidthUnit
, HeightUnit
;
1781 *pShowXY
= sInfo
.nPos
;
1783 GetScreenBufferSizeUnits(Buff
, GuiData
, &WidthUnit
, &HeightUnit
);
1785 ScrollWindowEx(GuiData
->hWindow
,
1786 (OldX
- Buff
->ViewOrigin
.X
) * WidthUnit
,
1787 (OldY
- Buff
->ViewOrigin
.Y
) * HeightUnit
,
1794 sInfo
.fMask
= SIF_POS
;
1795 SetScrollInfo(GuiData
->hWindow
, fnBar
, &sInfo
, TRUE
);
1797 UpdateWindow(GuiData
->hWindow
);
1798 // InvalidateRect(GuiData->hWindow, NULL, FALSE);
1802 LeaveCriticalSection(&Console
->Lock
);
1807 static LRESULT CALLBACK
1808 ConWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1811 PGUI_CONSOLE_DATA GuiData
= NULL
;
1812 PCONSOLE Console
= NULL
;
1815 * - If it's the first time we create a window for the terminal,
1816 * just initialize it and return.
1818 * - If we are destroying the window, just do it and return.
1820 if (msg
== WM_NCCREATE
)
1822 return (LRESULT
)OnNcCreate(hWnd
, (LPCREATESTRUCTW
)lParam
);
1824 else if (msg
== WM_NCDESTROY
)
1826 return OnNcDestroy(hWnd
);
1830 * Now the terminal window is initialized.
1831 * Get the terminal data via the window's data.
1832 * If there is no data, just go away.
1834 GuiData
= GuiGetGuiData(hWnd
);
1835 if (GuiData
== NULL
) return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1837 // TEMPORARY HACK until all of the functions can deal with a NULL GuiData->ActiveBuffer ...
1838 if (GuiData
->ActiveBuffer
== NULL
) return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1841 * Just retrieve a pointer to the console in case somebody needs it.
1842 * It is not NULL because it was checked in GuiGetGuiData.
1843 * Each helper function which needs the console has to validate and lock it.
1845 Console
= GuiData
->Console
;
1847 /* We have a console, start message dispatching */
1851 OnActivate(GuiData
, wParam
);
1855 if (OnClose(GuiData
)) goto Default
;
1866 case WM_PALETTECHANGED
:
1868 DPRINT("WM_PALETTECHANGED called\n");
1871 * Protects against infinite loops:
1872 * "... A window that receives this message must not realize
1873 * its palette, unless it determines that wParam does not contain
1874 * its own window handle." (WM_PALETTECHANGED description - MSDN)
1876 * This message is sent to all windows, including the one that
1877 * changed the system palette and caused this message to be sent.
1878 * The wParam of this message contains the handle of the window
1879 * that caused the system palette to change. To avoid an infinite
1880 * loop, care must be taken to check that the wParam of this message
1881 * does not match the window's handle.
1883 if ((HWND
)wParam
== hWnd
) break;
1885 DPRINT("WM_PALETTECHANGED ok\n");
1886 OnPaletteChanged(GuiData
);
1887 DPRINT("WM_PALETTECHANGED quit\n");
1898 case WM_SYSDEADCHAR
:
1900 /* Detect Alt-Enter presses and switch back and forth to fullscreen mode */
1901 if (msg
== WM_SYSKEYDOWN
&& (HIWORD(lParam
) & KF_ALTDOWN
) && wParam
== VK_RETURN
)
1903 /* Switch only at first Alt-Enter press, and ignore subsequent key repetitions */
1904 if ((HIWORD(lParam
) & (KF_UP
| KF_REPEAT
)) != KF_REPEAT
)
1905 GuiConsoleSwitchFullScreen(GuiData
);
1910 OnKey(GuiData
, msg
, wParam
, lParam
);
1917 * The message was sent because we are manually triggering a change.
1918 * Check whether the mouse is indeed present on this console window
1919 * and take appropriate decisions.
1921 if (wParam
== -1 && lParam
== -1)
1926 /* Get the placement of the mouse */
1927 GetCursorPos(&mouseCoords
);
1929 /* On which window is placed the mouse ? */
1930 hWndHit
= WindowFromPoint(mouseCoords
);
1932 /* It's our window. Perform the hit-test to be used later on. */
1933 if (hWndHit
== hWnd
)
1935 wParam
= (WPARAM
)hWnd
;
1936 lParam
= DefWindowProcW(hWndHit
, WM_NCHITTEST
, 0,
1937 MAKELPARAM(mouseCoords
.x
, mouseCoords
.y
));
1941 /* Set the mouse cursor only when we are in the client area */
1942 if ((HWND
)wParam
== hWnd
&& LOWORD(lParam
) == HTCLIENT
)
1944 if (GuiData
->MouseCursorRefCount
>= 0)
1946 /* Show the cursor */
1947 SetCursor(GuiData
->hCursor
);
1951 /* Hide the cursor if the reference count is negative */
1962 case WM_LBUTTONDOWN
:
1963 case WM_MBUTTONDOWN
:
1964 case WM_RBUTTONDOWN
:
1968 case WM_LBUTTONDBLCLK
:
1969 case WM_MBUTTONDBLCLK
:
1970 case WM_RBUTTONDBLCLK
:
1973 case WM_MOUSEHWHEEL
:
1975 Result
= OnMouse(GuiData
, msg
, wParam
, lParam
);
1982 Result
= OnScroll(GuiData
, msg
, wParam
);
1986 case WM_CONTEXTMENU
:
1988 if (DefWindowProcW(hWnd
/*GuiData->hWindow*/, WM_NCHITTEST
, 0, lParam
) == HTCLIENT
)
1990 HMENU hMenu
= CreatePopupMenu();
1993 AppendMenuItems(hMenu
, GuiConsoleEditMenuItems
);
1994 TrackPopupMenuEx(hMenu
,
1996 GET_X_LPARAM(lParam
),
1997 GET_Y_LPARAM(lParam
),
2012 HMENU hMenu
= (HMENU
)wParam
;
2015 /* Enable or disable the Close menu item */
2016 EnableMenuItem(hMenu
, SC_CLOSE
, MF_BYCOMMAND
|
2017 (GuiData
->IsCloseButtonEnabled
? MF_ENABLED
: MF_GRAYED
));
2019 /* Enable or disable the Copy and Paste items */
2020 EnableMenuItem(hMenu
, ID_SYSTEM_EDIT_COPY
, MF_BYCOMMAND
|
2021 ((GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_IN_PROGRESS
) &&
2022 (GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
) ? MF_ENABLED
: MF_GRAYED
));
2023 // FIXME: Following whether the active screen buffer is text-mode
2024 // or graphics-mode, search for CF_UNICODETEXT or CF_BITMAP formats.
2025 EnableMenuItem(hMenu
, ID_SYSTEM_EDIT_PASTE
, MF_BYCOMMAND
|
2026 (!(GuiData
->Selection
.dwFlags
& CONSOLE_SELECTION_IN_PROGRESS
) &&
2027 IsClipboardFormatAvailable(CF_UNICODETEXT
) ? MF_ENABLED
: MF_GRAYED
));
2030 SendMenuEvent(Console
, WM_INITMENU
);
2036 if (HIWORD(wParam
) == 0xFFFF) // Allow all the menu flags
2038 SendMenuEvent(Console
, WM_MENUSELECT
);
2046 Result
= OnCommand(GuiData
, wParam
, lParam
);
2052 OnFocus(GuiData
, (msg
== WM_SETFOCUS
));
2055 case WM_GETMINMAXINFO
:
2056 OnGetMinMaxInfo(GuiData
, (PMINMAXINFO
)lParam
);
2063 #if 0 // This code is here to prepare & control dynamic console SB resizing.
2066 PRECT dragRect
= (PRECT
)lParam
;
2070 DPRINT1("WMSZ_LEFT\n");
2073 DPRINT1("WMSZ_RIGHT\n");
2076 DPRINT1("WMSZ_TOP\n");
2079 DPRINT1("WMSZ_TOPLEFT\n");
2082 DPRINT1("WMSZ_TOPRIGHT\n");
2085 DPRINT1("WMSZ_BOTTOM\n");
2087 case WMSZ_BOTTOMLEFT
:
2088 DPRINT1("WMSZ_BOTTOMLEFT\n");
2090 case WMSZ_BOTTOMRIGHT
:
2091 DPRINT1("WMSZ_BOTTOMRIGHT\n");
2094 DPRINT1("wParam = %d\n", wParam
);
2097 DPRINT1("dragRect = {.left = %d ; .top = %d ; .right = %d ; .bottom = %d}\n",
2098 dragRect
->left
, dragRect
->top
, dragRect
->right
, dragRect
->bottom
);
2104 OnSize(GuiData
, wParam
, lParam
);
2107 case PM_RESIZE_TERMINAL
:
2109 PCONSOLE_SCREEN_BUFFER Buff
= GuiData
->ActiveBuffer
;
2113 DWORD Width
, Height
;
2114 UINT WidthUnit
, HeightUnit
;
2116 GetScreenBufferSizeUnits(Buff
, GuiData
, &WidthUnit
, &HeightUnit
);
2118 Width
= Buff
->ScreenBufferSize
.X
* WidthUnit
;
2119 Height
= Buff
->ScreenBufferSize
.Y
* HeightUnit
;
2121 /* Recreate the framebuffer */
2122 hDC
= GetDC(GuiData
->hWindow
);
2123 hnew
= CreateCompatibleBitmap(hDC
, Width
, Height
);
2124 ReleaseDC(GuiData
->hWindow
, hDC
);
2125 hold
= SelectObject(GuiData
->hMemDC
, hnew
);
2126 if (GuiData
->hBitmap
)
2128 if (hold
== GuiData
->hBitmap
) DeleteObject(GuiData
->hBitmap
);
2130 GuiData
->hBitmap
= hnew
;
2132 /* Resize the window to the user's values */
2133 GuiData
->WindowSizeLock
= TRUE
;
2134 ResizeConWnd(GuiData
, WidthUnit
, HeightUnit
);
2135 GuiData
->WindowSizeLock
= FALSE
;
2139 case PM_APPLY_CONSOLE_INFO
:
2141 GuiApplyUserSettings(GuiData
, (HANDLE
)wParam
, (BOOL
)lParam
);
2145 case PM_CONSOLE_BEEP
:
2146 DPRINT1("Beep !!\n");
2150 // case PM_CONSOLE_SET_TITLE:
2151 // SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
2155 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);