2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/guiconsole.c
5 * PURPOSE: Implementation of gui-mode consoles
9 /* INCLUDES ******************************************************************/
12 #include "guiconsole.h"
15 /* Public Win32K Headers */
21 /* Not defined in any header file */
22 // extern VOID WINAPI PrivateCsrssManualGuiCheck(LONG Check);
23 // From win32ss/user/win32csr/dllmain.c
26 PrivateCsrssManualGuiCheck(LONG Check
)
28 NtUserCallOneParam(Check
, ONEPARAM_ROUTINE_CSRSS_GUICHECK
);
31 /* GLOBALS *******************************************************************/
33 typedef struct GUI_CONSOLE_DATA_TAG
40 CRITICAL_SECTION Lock
;
41 HMODULE ConsoleLibrary
;
43 WCHAR FontName
[LF_FACESIZE
];
52 COLORREF ScreenBackground
;
53 COLORREF PopupBackground
;
56 WCHAR szProcessName
[MAX_PATH
];
59 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
64 #define PM_CREATE_CONSOLE (WM_APP + 1)
65 #define PM_DESTROY_CONSOLE (WM_APP + 2)
67 #define CURSOR_BLINK_TIME 500
68 #define DEFAULT_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
70 static BOOL ConsInitialized
= FALSE
;
71 static HWND NotifyWnd
;
73 typedef struct _GUICONSOLE_MENUITEM
76 const struct _GUICONSOLE_MENUITEM
*SubMenu
;
78 } GUICONSOLE_MENUITEM
, *PGUICONSOLE_MENUITEM
;
80 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems
[] =
82 { IDS_MARK
, NULL
, ID_SYSTEM_EDIT_MARK
},
83 { IDS_COPY
, NULL
, ID_SYSTEM_EDIT_COPY
},
84 { IDS_PASTE
, NULL
, ID_SYSTEM_EDIT_PASTE
},
85 { IDS_SELECTALL
, NULL
, ID_SYSTEM_EDIT_SELECTALL
},
86 { IDS_SCROLL
, NULL
, ID_SYSTEM_EDIT_SCROLL
},
87 { IDS_FIND
, NULL
, ID_SYSTEM_EDIT_FIND
},
89 { 0, NULL
, 0 } /* End of list */
92 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems
[] =
94 { (UINT
)-1, NULL
, 0 }, /* Separator */
95 { IDS_EDIT
, GuiConsoleEditMenuItems
, 0 },
96 { IDS_DEFAULTS
, NULL
, ID_SYSTEM_DEFAULTS
},
97 { IDS_PROPERTIES
, NULL
, ID_SYSTEM_PROPERTIES
},
99 { 0, NULL
, 0 } /* End of list */
102 static const COLORREF s_Colors
[] =
122 #define GuiConsoleRGBFromAttribute(GuiData, Attribute) ((GuiData)->Colors[(Attribute) & 0xF])
124 /* FUNCTIONS *****************************************************************/
127 GuiConsoleAppendMenuItems(HMENU hMenu
,
128 const GUICONSOLE_MENUITEM
*Items
)
131 WCHAR szMenuString
[255];
136 if (Items
[i
].uID
!= (UINT
)-1)
138 if (LoadStringW(ConSrvDllInstance
,
141 sizeof(szMenuString
) / sizeof(szMenuString
[0])) > 0)
143 if (Items
[i
].SubMenu
!= NULL
)
145 hSubMenu
= CreatePopupMenu();
146 if (hSubMenu
!= NULL
)
148 GuiConsoleAppendMenuItems(hSubMenu
,
151 if (!AppendMenuW(hMenu
,
152 MF_STRING
| MF_POPUP
,
156 DestroyMenu(hSubMenu
);
177 } while(!(Items
[i
].uID
== 0 && Items
[i
].SubMenu
== NULL
&& Items
[i
].wCmdID
== 0));
181 GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console
)
184 hMenu
= GetSystemMenu(Console
->hWindow
,
188 GuiConsoleAppendMenuItems(hMenu
,
189 GuiConsoleMainMenuItems
);
190 DrawMenuBar(Console
->hWindow
);
195 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
197 *Console
= (PCSRSS_CONSOLE
) GetWindowLongPtrW(hWnd
, GWL_USERDATA
);
198 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
202 GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId
, PHANDLE hProcHandle
, PHKEY hResult
, REGSAM samDesired
)
204 HANDLE hProcessToken
= NULL
;
209 UNICODE_STRING SidName
;
213 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
| READ_CONTROL
, FALSE
, ProcessId
);
216 DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
220 if (!OpenProcessToken(hProcess
, TOKEN_QUERY
, &hProcessToken
))
222 DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
223 CloseHandle(hProcess
);
227 if (!GetTokenInformation(hProcessToken
, TokenUser
, (PVOID
)Buffer
, sizeof(Buffer
), &Length
))
229 DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
230 CloseHandle(hProcessToken
);
231 CloseHandle(hProcess
);
235 TokUser
= ((PTOKEN_USER
)Buffer
)->User
.Sid
;
236 if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName
, TokUser
, TRUE
)))
238 DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
239 CloseHandle(hProcessToken
);
240 CloseHandle(hProcess
);
244 res
= RegOpenKeyExW(HKEY_USERS
, SidName
.Buffer
, 0, samDesired
, hResult
);
245 RtlFreeUnicodeString(&SidName
);
247 CloseHandle(hProcessToken
);
248 if (res
!= ERROR_SUCCESS
)
250 CloseHandle(hProcess
);
255 *hProcHandle
= hProcess
;
257 CloseHandle(hProcess
);
263 GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData
, DWORD ProcessId
, PHKEY hSubKey
, REGSAM samDesired
, BOOL bCreate
)
265 WCHAR szProcessName
[MAX_PATH
];
266 WCHAR szBuffer
[MAX_PATH
];
267 UINT fLength
, wLength
;
268 DWORD dwBitmask
, dwLength
;
269 WCHAR CurDrive
[] = { 'A',':', 0 };
275 * console properties are stored under
278 * There are 3 ways to store console properties
280 * 1. use console title as subkey name
283 * 2. use application name as subkey name
285 * 3. use unexpanded path to console application.
286 * i.e. %SystemRoot%_system32_cmd.exe
289 DPRINT("GuiConsoleOpenUserSettings entered\n");
291 if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId
, &hProcess
, &hKey
, samDesired
))
293 DPRINT("GuiConsoleOpenUserRegistryPathPerProcessId failed\n");
297 /* FIXME we do not getting the process name so no menu will be loading, why ?*/
298 fLength
= GetProcessImageFileNameW(hProcess
, szProcessName
, sizeof(GuiData
->szProcessName
) / sizeof(WCHAR
));
299 CloseHandle(hProcess
);
301 //DPRINT1("szProcessName3 : %S\n",szProcessName);
305 DPRINT("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(), ProcessId
);
309 * try the process name as path
312 ptr
= wcsrchr(szProcessName
, L
'\\');
313 wcscpy(GuiData
->szProcessName
, ptr
);
315 swprintf(szBuffer
, L
"Console%s",ptr
);
316 DPRINT("#1 Path : %S\n", szBuffer
);
320 if (RegCreateKeyW(hKey
, szBuffer
, hSubKey
) == ERROR_SUCCESS
)
329 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
336 * try the "Shortcut to processname" as path
337 * FIXME: detect wheter the process was started as a shortcut
340 swprintf(szBuffer
, L
"Console\\Shortcut to %S", ptr
);
341 DPRINT("#2 Path : %S\n", szBuffer
);
342 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
344 swprintf(GuiData
->szProcessName
, L
"Shortcut to %S", ptr
);
350 * if the path contains \\Device\\HarddiskVolume1\... remove it
353 if (szProcessName
[0] == L
'\\')
355 dwBitmask
= GetLogicalDrives();
360 dwLength
= QueryDosDeviceW(CurDrive
, szBuffer
, MAX_PATH
);
363 if (!memcmp(szBuffer
, szProcessName
, (dwLength
-2)*sizeof(WCHAR
)))
365 wcscpy(szProcessName
, CurDrive
);
366 RtlMoveMemory(&szProcessName
[2], &szProcessName
[dwLength
-1], fLength
- dwLength
-1);
371 dwBitmask
= (dwBitmask
>> 1);
377 * last attempt: check whether the file is under %SystemRoot%
378 * and use path like Console\%SystemRoot%_dir_dir2_file.exe
381 wLength
= GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
384 if (!wcsncmp(szProcessName
, szBuffer
, wLength
))
386 /* replace slashes by underscores */
387 while((ptr
= wcschr(szProcessName
, L
'\\')))
390 swprintf(szBuffer
, L
"Console\\%%SystemRoot%%%S", &szProcessName
[wLength
]);
391 DPRINT("#3 Path : %S\n", szBuffer
);
392 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
394 swprintf(GuiData
->szProcessName
, L
"%%SystemRoot%%%S", &szProcessName
[wLength
]);
405 GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
)
408 PCONSOLE_PROCESS_DATA ProcessData
;
410 if (Console
->ProcessList
.Flink
== &Console
->ProcessList
)
412 DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
416 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
417 if (!GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->Process
->ClientId
.UniqueProcess
), &hKey
, KEY_READ
| KEY_WRITE
, TRUE
))
422 if (Console
->ActiveBuffer
->CursorInfo
.dwSize
<= 1)
424 RegDeleteKeyW(hKey
, L
"CursorSize");
428 RegSetValueExW(hKey
, L
"CursorSize", 0, REG_DWORD
, (const BYTE
*)&Console
->ActiveBuffer
->CursorInfo
.dwSize
, sizeof(DWORD
));
431 if (Console
->NumberOfHistoryBuffers
== 5)
433 RegDeleteKeyW(hKey
, L
"NumberOfHistoryBuffers");
437 RegSetValueExW(hKey
, L
"NumberOfHistoryBuffers", 0, REG_DWORD
, (const BYTE
*)&Console
->NumberOfHistoryBuffers
, sizeof(DWORD
));
440 if (Console
->HistoryBufferSize
== 50)
442 RegDeleteKeyW(hKey
, L
"HistoryBufferSize");
446 RegSetValueExW(hKey
, L
"HistoryBufferSize", 0, REG_DWORD
, (const BYTE
*)&Console
->HistoryBufferSize
, sizeof(DWORD
));
449 if (GuiData
->FullScreen
== FALSE
)
451 RegDeleteKeyW(hKey
, L
"FullScreen");
455 RegSetValueExW(hKey
, L
"FullScreen", 0, REG_DWORD
, (const BYTE
*)&GuiData
->FullScreen
, sizeof(DWORD
));
458 if (GuiData
->QuickEdit
== FALSE
)
460 RegDeleteKeyW(hKey
, L
"QuickEdit");
464 RegSetValueExW(hKey
, L
"QuickEdit", 0, REG_DWORD
, (const BYTE
*)&GuiData
->QuickEdit
, sizeof(DWORD
));
467 if (GuiData
->InsertMode
== TRUE
)
469 RegDeleteKeyW(hKey
, L
"InsertMode");
473 RegSetValueExW(hKey
, L
"InsertMode", 0, REG_DWORD
, (const BYTE
*)&GuiData
->InsertMode
, sizeof(DWORD
));
476 if (Console
->HistoryNoDup
== FALSE
)
478 RegDeleteKeyW(hKey
, L
"HistoryNoDup");
482 DWORD Temp
= Console
->HistoryNoDup
;
483 RegSetValueExW(hKey
, L
"HistoryNoDup", 0, REG_DWORD
, (const BYTE
*)&Temp
, sizeof(DWORD
));
486 if (GuiData
->ScreenText
== RGB(192, 192, 192))
489 * MS uses console attributes instead of real color
491 RegDeleteKeyW(hKey
, L
"ScreenText");
495 RegSetValueExW(hKey
, L
"ScreenText", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenText
, sizeof(COLORREF
));
498 if (GuiData
->ScreenBackground
== RGB(0, 0, 0))
500 RegDeleteKeyW(hKey
, L
"ScreenBackground");
504 RegSetValueExW(hKey
, L
"ScreenBackground", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenBackground
, sizeof(COLORREF
));
511 GuiConsoleReadUserSettings(HKEY hKey
, PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
513 DWORD dwNumSubKeys
= 0;
518 WCHAR szValueName
[MAX_PATH
];
519 WCHAR szValue
[LF_FACESIZE
] = L
"\0";
522 if (RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
524 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
528 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
530 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
532 dwValue
= sizeof(Value
);
533 dwValueName
= MAX_PATH
;
535 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
537 if (dwType
== REG_SZ
)
540 * retry in case of string value
542 dwValue
= sizeof(szValue
);
543 dwValueName
= LF_FACESIZE
;
544 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
550 if (!wcscmp(szValueName
, L
"CursorSize"))
554 Buffer
->CursorInfo
.dwSize
= Value
;
556 else if (Value
== 0x64)
558 Buffer
->CursorInfo
.dwSize
= Value
;
561 else if (!wcscmp(szValueName
, L
"ScreenText"))
563 GuiData
->ScreenText
= Value
;
565 else if (!wcscmp(szValueName
, L
"ScreenBackground"))
567 GuiData
->ScreenBackground
= Value
;
569 else if (!wcscmp(szValueName
, L
"FaceName"))
571 wcscpy(GuiData
->FontName
, szValue
);
573 else if (!wcscmp(szValueName
, L
"FontSize"))
575 GuiData
->FontSize
= Value
;
577 else if (!wcscmp(szValueName
, L
"FontWeight"))
579 GuiData
->FontWeight
= Value
;
581 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
583 Console
->HistoryNoDup
= Value
;
585 else if (!wcscmp(szValueName
, L
"WindowSize"))
587 Console
->Size
.X
= LOWORD(Value
);
588 Console
->Size
.Y
= HIWORD(Value
);
590 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
594 Buffer
->MaxX
= LOWORD(Value
);
595 Buffer
->MaxY
= HIWORD(Value
);
598 else if (!wcscmp(szValueName
, L
"FullScreen"))
600 GuiData
->FullScreen
= Value
;
602 else if (!wcscmp(szValueName
, L
"QuickEdit"))
604 GuiData
->QuickEdit
= Value
;
606 else if (!wcscmp(szValueName
, L
"InsertMode"))
608 GuiData
->InsertMode
= Value
;
613 GuiConsoleUseDefaults(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
616 * init guidata with default properties
619 wcscpy(GuiData
->FontName
, L
"DejaVu Sans Mono");
620 GuiData
->FontSize
= 0x0008000C; // font is 8x12
621 GuiData
->FontWeight
= FW_NORMAL
;
622 GuiData
->FullScreen
= FALSE
;
623 GuiData
->QuickEdit
= FALSE
;
624 GuiData
->InsertMode
= TRUE
;
625 GuiData
->ScreenText
= RGB(192, 192, 192);
626 GuiData
->ScreenBackground
= RGB(0, 0, 0);
627 GuiData
->PopupText
= RGB(128, 0, 128);
628 GuiData
->PopupBackground
= RGB(255, 255, 255);
629 GuiData
->WindowPosition
= UINT_MAX
;
630 GuiData
->UseRasterFonts
= TRUE
;
631 memcpy(GuiData
->Colors
, s_Colors
, sizeof(s_Colors
));
633 Console
->HistoryBufferSize
= 50;
634 Console
->NumberOfHistoryBuffers
= 5;
635 Console
->HistoryNoDup
= FALSE
;
636 Console
->Size
.X
= 80;
637 Console
->Size
.Y
= 25;
643 Buffer
->CursorInfo
.bVisible
= TRUE
;
644 Buffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
650 GuiConsoleInitScrollbar(PCSRSS_CONSOLE Console
, HWND hwnd
)
653 PGUI_CONSOLE_DATA GuiData
= Console
->PrivateData
;
655 DWORD Width
= Console
->Size
.X
* GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
656 DWORD Height
= Console
->Size
.Y
* GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
658 /* set scrollbar sizes */
659 sInfo
.cbSize
= sizeof(SCROLLINFO
);
660 sInfo
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
662 if (Console
->ActiveBuffer
->MaxY
> Console
->Size
.Y
)
664 sInfo
.nMax
= Console
->ActiveBuffer
->MaxY
- 1;
665 sInfo
.nPage
= Console
->Size
.Y
;
666 sInfo
.nPos
= Console
->ActiveBuffer
->ShowY
;
667 SetScrollInfo(hwnd
, SB_VERT
, &sInfo
, TRUE
);
668 Width
+= GetSystemMetrics(SM_CXVSCROLL
);
669 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
673 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
676 if (Console
->ActiveBuffer
->MaxX
> Console
->Size
.X
)
678 sInfo
.nMax
= Console
->ActiveBuffer
->MaxX
- 1;
679 sInfo
.nPage
= Console
->Size
.X
;
680 sInfo
.nPos
= Console
->ActiveBuffer
->ShowX
;
681 SetScrollInfo(hwnd
, SB_HORZ
, &sInfo
, TRUE
);
682 Height
+= GetSystemMetrics(SM_CYHSCROLL
);
683 ShowScrollBar(hwnd
, SB_HORZ
, TRUE
);
688 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
691 SetWindowPos(hwnd
, NULL
, 0, 0, Width
, Height
,
692 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
696 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
698 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
699 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Console
->PrivateData
;
704 PCONSOLE_PROCESS_DATA ProcessData
;
707 Console
->hWindow
= hWnd
;
711 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
715 GuiConsoleUseDefaults(Console
, GuiData
, Console
->ActiveBuffer
);
716 if (Console
->ProcessList
.Flink
!= &Console
->ProcessList
)
718 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
719 if (GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->Process
->ClientId
.UniqueProcess
), &hKey
, KEY_READ
, FALSE
))
721 GuiConsoleReadUserSettings(hKey
, Console
, GuiData
, Console
->ActiveBuffer
);
726 InitializeCriticalSection(&GuiData
->Lock
);
728 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->FontSize
),
729 0, //HIWORD(GuiData->FontSize),
737 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
738 NONANTIALIASED_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
740 if (NULL
== GuiData
->Font
)
742 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
743 DeleteCriticalSection(&GuiData
->Lock
);
744 HeapFree(ConSrvHeap
, 0, GuiData
);
750 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
751 DeleteObject(GuiData
->Font
);
752 DeleteCriticalSection(&GuiData
->Lock
);
753 HeapFree(ConSrvHeap
, 0, GuiData
);
756 OldFont
= SelectObject(Dc
, GuiData
->Font
);
759 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
761 DeleteObject(GuiData
->Font
);
762 DeleteCriticalSection(&GuiData
->Lock
);
763 HeapFree(ConSrvHeap
, 0, GuiData
);
766 if (! GetTextMetricsW(Dc
, &Metrics
))
768 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
769 SelectObject(Dc
, OldFont
);
771 DeleteObject(GuiData
->Font
);
772 DeleteCriticalSection(&GuiData
->Lock
);
773 HeapFree(ConSrvHeap
, 0, GuiData
);
776 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
777 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
779 /* Measure real char width more precisely if possible. */
780 if (GetTextExtentPoint32W(Dc
, L
"R", 1, &CharSize
))
781 GuiData
->CharWidth
= CharSize
.cx
;
783 SelectObject(Dc
, OldFont
);
786 GuiData
->CursorBlinkOn
= TRUE
;
787 GuiData
->ForceCursorOff
= FALSE
;
789 DPRINT("Console %p GuiData %p\n", Console
, GuiData
);
790 Console
->PrivateData
= GuiData
;
791 SetWindowLongPtrW(hWnd
, GWL_USERDATA
, (DWORD_PTR
) Console
);
793 SetTimer(hWnd
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
794 GuiConsoleCreateSysMenu(Console
);
796 GuiData
->WindowSizeLock
= TRUE
;
797 GuiConsoleInitScrollbar(Console
, hWnd
);
798 GuiData
->WindowSizeLock
= FALSE
;
800 SetEvent(GuiData
->hGuiInitEvent
);
802 return (BOOL
)DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
)Create
);
806 SmallRectToRect(PCSRSS_CONSOLE Console
, PRECT Rect
, PSMALL_RECT SmallRect
)
808 PCSRSS_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
809 PGUI_CONSOLE_DATA GuiData
= Console
->PrivateData
;
810 Rect
->left
= (SmallRect
->Left
- Buffer
->ShowX
) * GuiData
->CharWidth
;
811 Rect
->top
= (SmallRect
->Top
- Buffer
->ShowY
) * GuiData
->CharHeight
;
812 Rect
->right
= (SmallRect
->Right
+ 1 - Buffer
->ShowX
) * GuiData
->CharWidth
;
813 Rect
->bottom
= (SmallRect
->Bottom
+ 1 - Buffer
->ShowY
) * GuiData
->CharHeight
;
817 GuiConsoleUpdateSelection(PCSRSS_CONSOLE Console
, PCOORD coord
)
819 RECT oldRect
, newRect
;
820 HWND hWnd
= Console
->hWindow
;
822 SmallRectToRect(Console
, &oldRect
, &Console
->Selection
.srSelection
);
827 /* exchange left/top with right/bottom if required */
828 rc
.Left
= min(Console
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
829 rc
.Top
= min(Console
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
830 rc
.Right
= max(Console
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
831 rc
.Bottom
= max(Console
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
833 SmallRectToRect(Console
, &newRect
, &rc
);
835 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
837 if (memcmp(&rc
, &Console
->Selection
.srSelection
, sizeof(SMALL_RECT
)) != 0)
841 /* calculate the region that needs to be updated */
842 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
844 if((rgn2
= CreateRectRgnIndirect(&newRect
)))
846 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
848 InvalidateRgn(hWnd
, rgn1
, FALSE
);
859 InvalidateRect(hWnd
, &newRect
, FALSE
);
861 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_NOT_EMPTY
;
862 Console
->Selection
.srSelection
= rc
;
863 ConioPause(Console
, PAUSED_FROM_SELECTION
);
867 /* clear the selection */
868 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
870 InvalidateRect(hWnd
, &oldRect
, FALSE
);
872 Console
->Selection
.dwFlags
= CONSOLE_NO_SELECTION
;
873 ConioUnpause(Console
, PAUSED_FROM_SELECTION
);
879 GuiConsolePaint(PCSRSS_CONSOLE Console
,
880 PGUI_CONSOLE_DATA GuiData
,
884 PCSRSS_SCREEN_BUFFER Buff
;
885 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
886 ULONG Line
, Char
, Start
;
889 BYTE LastAttribute
, Attribute
;
890 ULONG CursorX
, CursorY
, CursorHeight
;
891 HBRUSH CursorBrush
, OldBrush
;
894 Buff
= Console
->ActiveBuffer
;
896 EnterCriticalSection(&Buff
->Header
.Console
->Lock
);
898 TopLine
= rc
->top
/ GuiData
->CharHeight
+ Buff
->ShowY
;
899 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1 + Buff
->ShowY
;
900 LeftChar
= rc
->left
/ GuiData
->CharWidth
+ Buff
->ShowX
;
901 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1 + Buff
->ShowX
;
902 LastAttribute
= ConioCoordToPointer(Buff
, LeftChar
, TopLine
)[1];
904 SetTextColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, LastAttribute
));
905 SetBkColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, LastAttribute
>> 4));
907 if (BottomLine
>= Buff
->MaxY
) BottomLine
= Buff
->MaxY
- 1;
908 if (RightChar
>= Buff
->MaxX
) RightChar
= Buff
->MaxX
- 1;
910 OldFont
= SelectObject(hDC
,
913 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
915 WCHAR LineBuffer
[80];
916 From
= ConioCoordToPointer(Buff
, LeftChar
, Line
);
920 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
922 if (*(From
+ 1) != LastAttribute
|| (Char
- Start
== sizeof(LineBuffer
) / sizeof(WCHAR
)))
925 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
926 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
931 Attribute
= *(From
+ 1);
932 if (Attribute
!= LastAttribute
)
934 SetTextColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, Attribute
));
935 SetBkColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, Attribute
>> 4));
936 LastAttribute
= Attribute
;
940 MultiByteToWideChar(Console
->OutputCodePage
,
951 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
952 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
954 RightChar
- Start
+ 1);
957 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
&&
958 !GuiData
->ForceCursorOff
)
960 CursorX
= Buff
->CurrentX
;
961 CursorY
= Buff
->CurrentY
;
962 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
963 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
965 CursorHeight
= ConioEffectiveCursorSize(Console
, GuiData
->CharHeight
);
966 From
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
) + 1;
968 if (*From
!= DEFAULT_ATTRIB
)
970 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(GuiData
, *From
));
974 CursorBrush
= CreateSolidBrush(GuiData
->ScreenText
);
977 OldBrush
= SelectObject(hDC
,
980 (CursorX
- Buff
->ShowX
) * GuiData
->CharWidth
,
981 (CursorY
- Buff
->ShowY
) * GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
987 DeleteObject(CursorBrush
);
991 LeaveCriticalSection(&Buff
->Header
.Console
->Lock
);
998 GuiConsoleHandlePaint(HWND hWnd
, HDC hDCPaint
)
1002 PCSRSS_CONSOLE Console
;
1003 PGUI_CONSOLE_DATA GuiData
;
1005 hDC
= BeginPaint(hWnd
, &ps
);
1007 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
1008 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
1010 GuiConsoleGetDataPointers(hWnd
,
1013 if (Console
!= NULL
&& GuiData
!= NULL
&&
1014 Console
->ActiveBuffer
!= NULL
)
1016 if (Console
->ActiveBuffer
->Buffer
!= NULL
)
1018 EnterCriticalSection(&GuiData
->Lock
);
1020 GuiConsolePaint(Console
,
1025 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
1028 SmallRectToRect(Console
, &rc
, &Console
->Selection
.srSelection
);
1030 /* invert the selection */
1031 if (IntersectRect(&rc
,
1044 LeaveCriticalSection(&GuiData
->Lock
);
1049 EndPaint(hWnd
, &ps
);
1053 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1055 PCSRSS_CONSOLE Console
;
1056 PGUI_CONSOLE_DATA GuiData
;
1059 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1060 Message
.hwnd
= hWnd
;
1061 Message
.message
= msg
;
1062 Message
.wParam
= wParam
;
1063 Message
.lParam
= lParam
;
1065 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
1067 /* clear the selection */
1068 GuiConsoleUpdateSelection(Console
, NULL
);
1071 ConioProcessKey(&Message
, Console
, FALSE
);
1075 GuiDrawRegion(PCSRSS_CONSOLE Console
, SMALL_RECT
*Region
)
1078 SmallRectToRect(Console
, &RegionRect
, Region
);
1079 InvalidateRect(Console
->hWindow
, &RegionRect
, FALSE
);
1083 GuiInvalidateCell(PCSRSS_CONSOLE Console
, UINT x
, UINT y
)
1085 SMALL_RECT CellRect
= { x
, y
, x
, y
};
1086 GuiDrawRegion(Console
, &CellRect
);
1090 GuiWriteStream(PCSRSS_CONSOLE Console
, SMALL_RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
1091 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
1093 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1094 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1095 LONG CursorEndX
, CursorEndY
;
1098 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
1103 if (0 != ScrolledLines
)
1105 ScrollRect
.left
= 0;
1107 ScrollRect
.right
= Console
->Size
.X
* GuiData
->CharWidth
;
1108 ScrollRect
.bottom
= Region
->Top
* GuiData
->CharHeight
;
1110 ScrollWindowEx(Console
->hWindow
,
1112 -(ScrolledLines
* GuiData
->CharHeight
),
1120 GuiDrawRegion(Console
, Region
);
1122 if (CursorStartX
< Region
->Left
|| Region
->Right
< CursorStartX
1123 || CursorStartY
< Region
->Top
|| Region
->Bottom
< CursorStartY
)
1125 GuiInvalidateCell(Console
, CursorStartX
, CursorStartY
);
1128 CursorEndX
= Buff
->CurrentX
;
1129 CursorEndY
= Buff
->CurrentY
;
1130 if ((CursorEndX
< Region
->Left
|| Region
->Right
< CursorEndX
1131 || CursorEndY
< Region
->Top
|| Region
->Bottom
< CursorEndY
)
1132 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
1134 GuiInvalidateCell(Console
, CursorEndX
, CursorEndY
);
1137 // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
1138 // repaint the window without having it just freeze up and stay on the screen permanently.
1139 GuiData
->CursorBlinkOn
= TRUE
;
1140 SetTimer(Console
->hWindow
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
1144 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1146 if (Console
->ActiveBuffer
== Buff
)
1148 GuiInvalidateCell(Console
, Buff
->CurrentX
, Buff
->CurrentY
);
1155 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
1157 if (Console
->ActiveBuffer
== Buff
)
1159 /* Redraw char at old position (removes cursor) */
1160 GuiInvalidateCell(Console
, OldCursorX
, OldCursorY
);
1161 /* Redraw char at new position (shows cursor) */
1162 GuiInvalidateCell(Console
, Buff
->CurrentX
, Buff
->CurrentY
);
1169 GuiUpdateScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1171 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1173 if (Console
->ActiveBuffer
== Buff
)
1175 GuiData
->ScreenText
= GuiConsoleRGBFromAttribute(GuiData
, Buff
->DefaultAttrib
);
1176 GuiData
->ScreenBackground
= GuiConsoleRGBFromAttribute(GuiData
, Buff
->DefaultAttrib
>> 4);
1183 GuiConsoleHandleTimer(HWND hWnd
)
1185 PCSRSS_CONSOLE Console
;
1186 PGUI_CONSOLE_DATA GuiData
;
1187 PCSRSS_SCREEN_BUFFER Buff
;
1189 SetTimer(hWnd
, CONGUI_UPDATE_TIMER
, CURSOR_BLINK_TIME
, NULL
);
1191 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1193 Buff
= Console
->ActiveBuffer
;
1194 GuiInvalidateCell(Console
, Buff
->CurrentX
, Buff
->CurrentY
);
1195 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
1197 if((GuiData
->OldCursor
.x
!= Buff
->CurrentX
) || (GuiData
->OldCursor
.y
!= Buff
->CurrentY
))
1200 int OldScrollX
= -1, OldScrollY
= -1;
1201 int NewScrollX
= -1, NewScrollY
= -1;
1203 xScroll
.cbSize
= sizeof(SCROLLINFO
);
1204 xScroll
.fMask
= SIF_POS
;
1205 // Capture the original position of the scroll bars and save them.
1206 if(GetScrollInfo(hWnd
, SB_HORZ
, &xScroll
))OldScrollX
= xScroll
.nPos
;
1207 if(GetScrollInfo(hWnd
, SB_VERT
, &xScroll
))OldScrollY
= xScroll
.nPos
;
1209 // If we successfully got the info for the horizontal scrollbar
1212 if((Buff
->CurrentX
< Buff
->ShowX
)||(Buff
->CurrentX
>= (Buff
->ShowX
+ Console
->Size
.X
)))
1214 // Handle the horizontal scroll bar
1215 if(Buff
->CurrentX
>= Console
->Size
.X
) NewScrollX
= Buff
->CurrentX
- Console
->Size
.X
+ 1;
1216 else NewScrollX
= 0;
1220 NewScrollX
= OldScrollX
;
1223 // If we successfully got the info for the vertical scrollbar
1226 if((Buff
->CurrentY
< Buff
->ShowY
) || (Buff
->CurrentY
>= (Buff
->ShowY
+ Console
->Size
.Y
)))
1228 // Handle the vertical scroll bar
1229 if(Buff
->CurrentY
>= Console
->Size
.Y
) NewScrollY
= Buff
->CurrentY
- Console
->Size
.Y
+ 1;
1230 else NewScrollY
= 0;
1234 NewScrollY
= OldScrollY
;
1238 // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
1239 // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
1240 // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
1241 // and their associated scrollbar is left alone.
1242 if((OldScrollX
!= NewScrollX
) || (OldScrollY
!= NewScrollY
))
1244 Buff
->ShowX
= NewScrollX
;
1245 Buff
->ShowY
= NewScrollY
;
1246 ScrollWindowEx(hWnd
,
1247 (OldScrollX
- NewScrollX
) * GuiData
->CharWidth
,
1248 (OldScrollY
- NewScrollY
) * GuiData
->CharHeight
,
1256 xScroll
.nPos
= NewScrollX
;
1257 SetScrollInfo(hWnd
, SB_HORZ
, &xScroll
, TRUE
);
1261 xScroll
.nPos
= NewScrollY
;
1262 SetScrollInfo(hWnd
, SB_VERT
, &xScroll
, TRUE
);
1265 GuiData
->OldCursor
.x
= Buff
->CurrentX
;
1266 GuiData
->OldCursor
.y
= Buff
->CurrentY
;
1272 GuiConsoleHandleClose(HWND hWnd
)
1274 PCSRSS_CONSOLE Console
;
1275 PGUI_CONSOLE_DATA GuiData
;
1276 PLIST_ENTRY current_entry
;
1277 PCONSOLE_PROCESS_DATA current
;
1279 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1281 EnterCriticalSection(&Console
->Lock
);
1283 current_entry
= Console
->ProcessList
.Flink
;
1284 while (current_entry
!= &Console
->ProcessList
)
1286 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
1287 current_entry
= current_entry
->Flink
;
1289 /* FIXME: Windows will wait up to 5 seconds for the thread to exit.
1290 * We shouldn't wait here, though, since the console lock is entered.
1291 * A copy of the thread list probably needs to be made. */
1292 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
1295 LeaveCriticalSection(&Console
->Lock
);
1299 GuiConsoleHandleNcDestroy(HWND hWnd
)
1301 PCSRSS_CONSOLE Console
;
1302 PGUI_CONSOLE_DATA GuiData
;
1305 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1307 Console
->PrivateData
= NULL
;
1308 DeleteCriticalSection(&GuiData
->Lock
);
1309 GetSystemMenu(hWnd
, TRUE
);
1310 if (GuiData
->ConsoleLibrary
)
1311 FreeLibrary(GuiData
->ConsoleLibrary
);
1313 HeapFree(ConSrvHeap
, 0, GuiData
);
1317 PointToCoord(PCSRSS_CONSOLE Console
, LPARAM lParam
)
1319 PCSRSS_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
1320 PGUI_CONSOLE_DATA GuiData
= Console
->PrivateData
;
1322 Coord
.X
= Buffer
->ShowX
+ ((short)LOWORD(lParam
) / (int)GuiData
->CharWidth
);
1323 Coord
.Y
= Buffer
->ShowY
+ ((short)HIWORD(lParam
) / (int)GuiData
->CharHeight
);
1325 /* Clip coordinate to ensure it's inside buffer */
1326 if (Coord
.X
< 0) Coord
.X
= 0;
1327 else if (Coord
.X
>= Buffer
->MaxX
) Coord
.X
= Buffer
->MaxX
- 1;
1328 if (Coord
.Y
< 0) Coord
.Y
= 0;
1329 else if (Coord
.Y
>= Buffer
->MaxY
) Coord
.Y
= Buffer
->MaxY
- 1;
1334 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
1336 PCSRSS_CONSOLE Console
;
1337 PGUI_CONSOLE_DATA GuiData
;
1339 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1340 if (Console
== NULL
|| GuiData
== NULL
) return;
1342 Console
->Selection
.dwSelectionAnchor
= PointToCoord(Console
, lParam
);
1346 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_IN_PROGRESS
| CONSOLE_MOUSE_SELECTION
| CONSOLE_MOUSE_DOWN
;
1348 GuiConsoleUpdateSelection(Console
, &Console
->Selection
.dwSelectionAnchor
);
1352 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
1354 PCSRSS_CONSOLE Console
;
1355 PGUI_CONSOLE_DATA GuiData
;
1358 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1359 if (Console
== NULL
|| GuiData
== NULL
) return;
1360 if (!(Console
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) return;
1362 c
= PointToCoord(Console
, lParam
);
1364 Console
->Selection
.dwFlags
&= ~CONSOLE_MOUSE_DOWN
;
1366 GuiConsoleUpdateSelection(Console
, &c
);
1372 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1374 PCSRSS_CONSOLE Console
;
1375 PGUI_CONSOLE_DATA GuiData
;
1378 if (!(wParam
& MK_LBUTTON
)) return;
1380 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1381 if (Console
== NULL
|| GuiData
== NULL
) return;
1382 if (!(Console
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) return;
1384 c
= PointToCoord(Console
, lParam
); /* TODO: Scroll buffer to bring c into view */
1386 GuiConsoleUpdateSelection(Console
, &c
);
1390 GuiConsoleCopy(HWND hWnd
, PCSRSS_CONSOLE Console
)
1392 if (OpenClipboard(hWnd
) == TRUE
)
1397 ULONG selWidth
, selHeight
;
1398 ULONG xPos
, yPos
, size
;
1400 selWidth
= Console
->Selection
.srSelection
.Right
- Console
->Selection
.srSelection
.Left
+ 1;
1401 selHeight
= Console
->Selection
.srSelection
.Bottom
- Console
->Selection
.srSelection
.Top
+ 1;
1402 DPRINT("Selection is (%d|%d) to (%d|%d)\n",
1403 Console
->Selection
.srSelection
.Left
,
1404 Console
->Selection
.srSelection
.Top
,
1405 Console
->Selection
.srSelection
.Right
,
1406 Console
->Selection
.srSelection
.Bottom
);
1408 /* Basic size for one line and termination */
1409 size
= selWidth
+ 1;
1412 /* Multiple line selections have to get \r\n appended */
1413 size
+= ((selWidth
+ 2) * (selHeight
- 1));
1416 /* Allocate memory, it will be passed to the system and may not be freed here */
1417 hData
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
1423 data
= GlobalLock(hData
);
1430 DPRINT("Copying %dx%d selection\n", selWidth
, selHeight
);
1433 for (yPos
= 0; yPos
< selHeight
; yPos
++)
1435 ptr
= ConioCoordToPointer(Console
->ActiveBuffer
,
1436 Console
->Selection
.srSelection
.Left
,
1437 yPos
+ Console
->Selection
.srSelection
.Top
);
1438 /* Copy only the characters, leave attributes alone */
1439 for (xPos
= 0; xPos
< selWidth
; xPos
++)
1441 dstPos
[xPos
] = ptr
[xPos
* 2];
1444 if (yPos
!= (selHeight
- 1))
1446 strcat(data
, "\r\n");
1451 DPRINT("Setting data <%s> to clipboard\n", data
);
1452 GlobalUnlock(hData
);
1455 SetClipboardData(CF_TEXT
, hData
);
1461 GuiConsolePaste(HWND hWnd
, PCSRSS_CONSOLE Console
)
1463 if (OpenClipboard(hWnd
) == TRUE
)
1469 hData
= GetClipboardData(CF_TEXT
);
1476 str
= GlobalLock(hData
);
1482 DPRINT("Got data <%s> from clipboard\n", str
);
1485 ConioWriteConsole(Console
, Console
->ActiveBuffer
, str
, len
, TRUE
);
1487 GlobalUnlock(hData
);
1493 GuiConsoleRightMouseDown(HWND hWnd
)
1495 PCSRSS_CONSOLE Console
;
1496 PGUI_CONSOLE_DATA GuiData
;
1498 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1499 if (Console
== NULL
|| GuiData
== NULL
) return;
1501 if (!(Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
))
1503 GuiConsolePaste(hWnd
, Console
);
1507 GuiConsoleCopy(hWnd
, Console
);
1509 /* Clear the selection */
1510 GuiConsoleUpdateSelection(Console
, NULL
);
1517 GuiConsoleShowConsoleProperties(HWND hWnd
, BOOL Defaults
, PGUI_CONSOLE_DATA GuiData
)
1519 PCSRSS_CONSOLE Console
;
1520 APPLET_PROC CPLFunc
;
1521 TCHAR szBuffer
[MAX_PATH
];
1522 ConsoleInfo SharedInfo
;
1524 DPRINT("GuiConsoleShowConsoleProperties entered\n");
1526 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1528 if (GuiData
== NULL
)
1530 DPRINT("GuiConsoleGetDataPointers failed\n");
1534 if (GuiData
->ConsoleLibrary
== NULL
)
1536 GetWindowsDirectory(szBuffer
,MAX_PATH
);
1537 _tcscat(szBuffer
, _T("\\system32\\console.dll"));
1538 GuiData
->ConsoleLibrary
= LoadLibrary(szBuffer
);
1540 if (GuiData
->ConsoleLibrary
== NULL
)
1542 DPRINT1("failed to load console.dll");
1547 CPLFunc
= (APPLET_PROC
) GetProcAddress(GuiData
->ConsoleLibrary
, _T("CPlApplet"));
1550 DPRINT("Error: Console.dll misses CPlApplet export\n");
1555 SharedInfo
.InsertMode
= GuiData
->InsertMode
;
1556 SharedInfo
.HistoryBufferSize
= Console
->HistoryBufferSize
;
1557 SharedInfo
.NumberOfHistoryBuffers
= Console
->NumberOfHistoryBuffers
;
1558 SharedInfo
.ScreenText
= GuiData
->ScreenText
;
1559 SharedInfo
.ScreenBackground
= GuiData
->ScreenBackground
;
1560 SharedInfo
.PopupText
= GuiData
->PopupText
;
1561 SharedInfo
.PopupBackground
= GuiData
->PopupBackground
;
1562 SharedInfo
.WindowSize
= (DWORD
)MAKELONG(Console
->Size
.X
, Console
->Size
.Y
);
1563 SharedInfo
.WindowPosition
= GuiData
->WindowPosition
;
1564 SharedInfo
.ScreenBuffer
= (DWORD
)MAKELONG(Console
->ActiveBuffer
->MaxX
, Console
->ActiveBuffer
->MaxY
);
1565 SharedInfo
.UseRasterFonts
= GuiData
->UseRasterFonts
;
1566 SharedInfo
.FontSize
= (DWORD
)GuiData
->FontSize
;
1567 SharedInfo
.FontWeight
= GuiData
->FontWeight
;
1568 SharedInfo
.CursorSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1569 SharedInfo
.HistoryNoDup
= Console
->HistoryNoDup
;
1570 SharedInfo
.FullScreen
= GuiData
->FullScreen
;
1571 SharedInfo
.QuickEdit
= GuiData
->QuickEdit
;
1572 memcpy(&SharedInfo
.Colors
[0], GuiData
->Colors
, sizeof(s_Colors
));
1574 if (!CPLFunc(hWnd
, CPL_INIT
, 0, 0))
1576 DPRINT("Error: failed to initialize console.dll\n");
1580 if (CPLFunc(hWnd
, CPL_GETCOUNT
, 0, 0) != 1)
1582 DPRINT("Error: console.dll returned unexpected CPL count\n");
1586 CPLFunc(hWnd
, CPL_DBLCLK
, (LPARAM
)&SharedInfo
, Defaults
);
1589 GuiConsoleHandleSysMenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1592 PCSRSS_CONSOLE Console
;
1593 PGUI_CONSOLE_DATA GuiData
;
1594 COORD bottomRight
= { 0, 0 };
1596 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1600 case ID_SYSTEM_EDIT_MARK
:
1601 DPRINT1("Marking not handled yet\n");
1604 case ID_SYSTEM_EDIT_COPY
:
1605 GuiConsoleCopy(hWnd
, Console
);
1608 case ID_SYSTEM_EDIT_PASTE
:
1609 GuiConsolePaste(hWnd
, Console
);
1612 case ID_SYSTEM_EDIT_SELECTALL
:
1613 bottomRight
.X
= Console
->Size
.X
- 1;
1614 bottomRight
.Y
= Console
->Size
.Y
- 1;
1615 GuiConsoleUpdateSelection(Console
, &bottomRight
);
1618 case ID_SYSTEM_EDIT_SCROLL
:
1619 DPRINT1("Scrolling is not handled yet\n");
1622 case ID_SYSTEM_EDIT_FIND
:
1623 DPRINT1("Finding is not handled yet\n");
1626 case ID_SYSTEM_DEFAULTS
:
1627 GuiConsoleShowConsoleProperties(hWnd
, TRUE
, GuiData
);
1630 case ID_SYSTEM_PROPERTIES
:
1631 GuiConsoleShowConsoleProperties(hWnd
, FALSE
, GuiData
);
1635 Ret
= DefWindowProcW(hWnd
, WM_SYSCOMMAND
, wParam
, lParam
);
1642 GuiConsoleGetMinMaxInfo(HWND hWnd
, PMINMAXINFO minMaxInfo
)
1644 PCSRSS_CONSOLE Console
;
1645 PGUI_CONSOLE_DATA GuiData
;
1648 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1649 if((Console
== NULL
)|| (GuiData
== NULL
)) return;
1651 windx
= CONGUI_MIN_WIDTH
* GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1652 windy
= CONGUI_MIN_HEIGHT
* GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1654 minMaxInfo
->ptMinTrackSize
.x
= windx
;
1655 minMaxInfo
->ptMinTrackSize
.y
= windy
;
1657 windx
= (Console
->ActiveBuffer
->MaxX
) * GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1658 windy
= (Console
->ActiveBuffer
->MaxY
) * GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1660 if(Console
->Size
.X
< Console
->ActiveBuffer
->MaxX
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1661 if(Console
->Size
.Y
< Console
->ActiveBuffer
->MaxY
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1663 minMaxInfo
->ptMaxTrackSize
.x
= windx
;
1664 minMaxInfo
->ptMaxTrackSize
.y
= windy
;
1667 GuiConsoleResize(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1669 PCSRSS_CONSOLE Console
;
1670 PGUI_CONSOLE_DATA GuiData
;
1671 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1672 if((Console
== NULL
) || (GuiData
== NULL
)) return;
1674 if ((GuiData
->WindowSizeLock
== FALSE
) && (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
))
1676 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1677 DWORD windx
, windy
, charx
, chary
;
1679 GuiData
->WindowSizeLock
= TRUE
;
1681 windx
= LOWORD(lParam
);
1682 windy
= HIWORD(lParam
);
1684 // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
1685 if(Console
->Size
.X
< Buff
->MaxX
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1686 if(Console
->Size
.Y
< Buff
->MaxY
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1688 charx
= windx
/ GuiData
->CharWidth
;
1689 chary
= windy
/ GuiData
->CharHeight
;
1691 // Character alignment (round size up or down)
1692 if((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1693 if((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1695 // Compensate for added scroll bars in new window
1696 if(charx
< Buff
->MaxX
)windy
-= GetSystemMetrics(SM_CYHSCROLL
); // new window will have a horizontal scroll bar
1697 if(chary
< Buff
->MaxY
)windx
-= GetSystemMetrics(SM_CXVSCROLL
); // new window will have a vertical scroll bar
1699 charx
= windx
/ GuiData
->CharWidth
;
1700 chary
= windy
/ GuiData
->CharHeight
;
1702 // Character alignment (round size up or down)
1703 if((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1704 if((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1707 if((charx
!= Console
->Size
.X
) || (chary
!= Console
->Size
.Y
))
1709 Console
->Size
.X
= (charx
<= Buff
->MaxX
) ? charx
: Buff
->MaxX
;
1710 Console
->Size
.Y
= (chary
<= Buff
->MaxY
) ? chary
: Buff
->MaxY
;
1713 GuiConsoleInitScrollbar(Console
, hWnd
);
1715 // Adjust the start of the visible area if we are attempting to show nonexistent areas
1716 if((Buff
->MaxX
- Buff
->ShowX
) < Console
->Size
.X
) Buff
->ShowX
= Buff
->MaxX
- Console
->Size
.X
;
1717 if((Buff
->MaxY
- Buff
->ShowY
) < Console
->Size
.Y
) Buff
->ShowY
= Buff
->MaxY
- Console
->Size
.Y
;
1718 InvalidateRect(hWnd
, NULL
, TRUE
);
1720 GuiData
->WindowSizeLock
= FALSE
;
1726 GuiConsoleHandleScrollbarMenu(VOID
)
1730 hMenu
= CreatePopupMenu();
1733 DPRINT("CreatePopupMenu failed\n");
1736 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1737 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1738 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1739 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1740 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1741 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1742 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1743 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1744 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1745 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1749 static NTSTATUS WINAPI
1750 GuiResizeBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER ScreenBuffer
, COORD Size
)
1758 USHORT value
= MAKEWORD(' ', ScreenBuffer
->DefaultAttrib
);
1763 /* Buffer size is not allowed to be smaller than window size */
1764 if (Size
.X
< Console
->Size
.X
|| Size
.Y
< Console
->Size
.Y
)
1765 return STATUS_INVALID_PARAMETER
;
1767 if (Size
.X
== ScreenBuffer
->MaxX
&& Size
.Y
== ScreenBuffer
->MaxY
)
1768 return STATUS_SUCCESS
;
1770 Buffer
= HeapAlloc(ConSrvHeap
, 0, Size
.X
* Size
.Y
* 2);
1772 return STATUS_NO_MEMORY
;
1774 DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer
->MaxX
, ScreenBuffer
->MaxY
, Size
.X
, Size
.Y
);
1775 OldBuffer
= ScreenBuffer
->Buffer
;
1777 for (CurrentY
= 0; CurrentY
< ScreenBuffer
->MaxY
&& CurrentY
< Size
.Y
; CurrentY
++)
1779 OldPtr
= ConioCoordToPointer(ScreenBuffer
, 0, CurrentY
);
1780 if (Size
.X
<= ScreenBuffer
->MaxX
)
1783 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, Size
.X
* 2);
1784 Offset
+= (Size
.X
* 2);
1789 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, ScreenBuffer
->MaxX
* 2);
1790 Offset
+= (ScreenBuffer
->MaxX
* 2);
1792 diff
= Size
.X
- ScreenBuffer
->MaxX
;
1793 /* zero new part of it */
1795 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
);
1797 for (i
= 0; i
< diff
; i
++)
1799 Buffer
[Offset
++] = ' ';
1800 Buffer
[Offset
++] = ScreenBuffer
->DefaultAttrib
;
1806 if (Size
.Y
> ScreenBuffer
->MaxY
)
1808 diff
= Size
.X
* (Size
.Y
- ScreenBuffer
->MaxY
);
1810 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
);
1812 for (i
= 0; i
< diff
; i
++)
1814 Buffer
[Offset
++] = ' ';
1815 Buffer
[Offset
++] = ScreenBuffer
->DefaultAttrib
;
1820 (void)InterlockedExchangePointer((PVOID
volatile *)&ScreenBuffer
->Buffer
, Buffer
);
1821 HeapFree(ConSrvHeap
, 0, OldBuffer
);
1822 ScreenBuffer
->MaxX
= Size
.X
;
1823 ScreenBuffer
->MaxY
= Size
.Y
;
1824 ScreenBuffer
->VirtualY
= 0;
1826 /* Ensure cursor and window are within buffer */
1827 if (ScreenBuffer
->CurrentX
>= Size
.X
)
1828 ScreenBuffer
->CurrentX
= Size
.X
- 1;
1829 if (ScreenBuffer
->CurrentY
>= Size
.Y
)
1830 ScreenBuffer
->CurrentY
= Size
.Y
- 1;
1831 if (ScreenBuffer
->ShowX
> Size
.X
- Console
->Size
.X
)
1832 ScreenBuffer
->ShowX
= Size
.X
- Console
->Size
.X
;
1833 if (ScreenBuffer
->ShowY
> Size
.Y
- Console
->Size
.Y
)
1834 ScreenBuffer
->ShowY
= Size
.Y
- Console
->Size
.Y
;
1836 /* TODO: Should update scrollbar, but can't use anything that
1837 * calls SendMessage or it could cause deadlock */
1839 return STATUS_SUCCESS
;
1843 GuiApplyUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PConsoleInfo pConInfo
)
1846 PCSRSS_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
1848 BOOL SizeChanged
= FALSE
;
1850 EnterCriticalSection(&Console
->Lock
);
1852 /* apply text / background color */
1853 GuiData
->ScreenText
= pConInfo
->ScreenText
;
1854 GuiData
->ScreenBackground
= pConInfo
->ScreenBackground
;
1856 /* apply cursor size */
1857 ActiveBuffer
->CursorInfo
.dwSize
= min(max(pConInfo
->CursorSize
, 1), 100);
1859 windx
= LOWORD(pConInfo
->WindowSize
);
1860 windy
= HIWORD(pConInfo
->WindowSize
);
1862 if (windx
!= Console
->Size
.X
|| windy
!= Console
->Size
.Y
)
1865 Console
->Size
.X
= windx
;
1866 Console
->Size
.Y
= windy
;
1870 BufSize
.X
= LOWORD(pConInfo
->ScreenBuffer
);
1871 BufSize
.Y
= HIWORD(pConInfo
->ScreenBuffer
);
1872 if (BufSize
.X
!= ActiveBuffer
->MaxX
|| BufSize
.Y
!= ActiveBuffer
->MaxY
)
1874 if (NT_SUCCESS(GuiResizeBuffer(Console
, ActiveBuffer
, BufSize
)))
1880 GuiData
->WindowSizeLock
= TRUE
;
1881 GuiConsoleInitScrollbar(Console
, pConInfo
->hConsoleWindow
);
1882 GuiData
->WindowSizeLock
= FALSE
;
1885 LeaveCriticalSection(&Console
->Lock
);
1886 InvalidateRect(pConInfo
->hConsoleWindow
, NULL
, TRUE
);
1891 GuiConsoleHandleScroll(HWND hwnd
, UINT uMsg
, WPARAM wParam
)
1893 PCSRSS_CONSOLE Console
;
1894 PCSRSS_SCREEN_BUFFER Buff
;
1895 PGUI_CONSOLE_DATA GuiData
;
1898 int old_pos
, Maximum
;
1901 GuiConsoleGetDataPointers(hwnd
, &Console
, &GuiData
);
1902 if (Console
== NULL
|| GuiData
== NULL
)
1904 Buff
= Console
->ActiveBuffer
;
1906 if (uMsg
== WM_HSCROLL
)
1909 Maximum
= Buff
->MaxX
- Console
->Size
.X
;
1910 pShowXY
= &Buff
->ShowX
;
1915 Maximum
= Buff
->MaxY
- Console
->Size
.Y
;
1916 pShowXY
= &Buff
->ShowY
;
1919 /* set scrollbar sizes */
1920 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1921 sInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_PAGE
| SIF_TRACKPOS
;
1923 if (!GetScrollInfo(hwnd
, fnBar
, &sInfo
))
1928 old_pos
= sInfo
.nPos
;
1930 switch(LOWORD(wParam
))
1941 sInfo
.nPos
-= sInfo
.nPage
;
1945 sInfo
.nPos
+= sInfo
.nPage
;
1949 sInfo
.nPos
= sInfo
.nTrackPos
;
1950 ConioPause(Console
, PAUSED_FROM_SCROLLBAR
);
1953 case SB_THUMBPOSITION
:
1954 ConioUnpause(Console
, PAUSED_FROM_SCROLLBAR
);
1958 sInfo
.nPos
= sInfo
.nMin
;
1962 sInfo
.nPos
= sInfo
.nMax
;
1969 sInfo
.nPos
= max(sInfo
.nPos
, 0);
1970 sInfo
.nPos
= min(sInfo
.nPos
, Maximum
);
1972 if (old_pos
!= sInfo
.nPos
)
1974 USHORT OldX
= Buff
->ShowX
;
1975 USHORT OldY
= Buff
->ShowY
;
1976 *pShowXY
= sInfo
.nPos
;
1978 ScrollWindowEx(hwnd
,
1979 (OldX
- Buff
->ShowX
) * GuiData
->CharWidth
,
1980 (OldY
- Buff
->ShowY
) * GuiData
->CharHeight
,
1987 sInfo
.fMask
= SIF_POS
;
1988 SetScrollInfo(hwnd
, fnBar
, &sInfo
, TRUE
);
1995 static LRESULT CALLBACK
1996 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1999 PGUI_CONSOLE_DATA GuiData
= NULL
;
2000 PCSRSS_CONSOLE Console
= NULL
;
2002 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
2007 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
2010 GuiConsoleHandlePaint(hWnd
, (HDC
)wParam
);
2017 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
2020 GuiConsoleHandleTimer(hWnd
);
2023 GuiConsoleHandleClose(hWnd
);
2026 GuiConsoleHandleNcDestroy(hWnd
);
2028 case WM_LBUTTONDOWN
:
2029 GuiConsoleLeftMouseDown(hWnd
, lParam
);
2032 GuiConsoleLeftMouseUp(hWnd
, lParam
);
2034 case WM_RBUTTONDOWN
:
2035 GuiConsoleRightMouseDown(hWnd
);
2038 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
2041 Result
= GuiConsoleHandleSysMenuCommand(hWnd
, wParam
, lParam
);
2045 Result
= GuiConsoleHandleScroll(hWnd
, msg
, wParam
);
2047 case WM_GETMINMAXINFO
:
2048 GuiConsoleGetMinMaxInfo(hWnd
, (PMINMAXINFO
)lParam
);
2051 GuiConsoleResize(hWnd
, wParam
, lParam
);
2053 case PM_APPLY_CONSOLE_INFO
:
2054 GuiApplyUserSettings(Console
, GuiData
, (PConsoleInfo
)wParam
);
2057 GuiConsoleWriteUserSettings(Console
, GuiData
);
2061 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
2068 static LRESULT CALLBACK
2069 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2074 PWCHAR Buffer
, Title
;
2075 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
2082 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
2084 case PM_CREATE_CONSOLE
:
2085 Buffer
= HeapAlloc(ConSrvHeap
, 0,
2086 Console
->Title
.Length
+ sizeof(WCHAR
));
2089 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
2090 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
2097 NewWindow
= CreateWindowExW(WS_EX_CLIENTEDGE
,
2098 L
"ConsoleWindowClass",
2100 WS_OVERLAPPEDWINDOW
| WS_HSCROLL
| WS_VSCROLL
,
2107 (HINSTANCE
) GetModuleHandleW(NULL
),
2111 HeapFree(ConSrvHeap
, 0, Buffer
);
2113 if (NULL
!= NewWindow
)
2115 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
2116 ShowWindow(NewWindow
, (int)wParam
);
2118 return (LRESULT
) NewWindow
;
2119 case PM_DESTROY_CONSOLE
:
2120 /* Window creation is done using a PostMessage(), so it's possible that the
2121 * window that we want to destroy doesn't exist yet. So first empty the message
2123 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
2125 TranslateMessage(&Msg
);
2126 DispatchMessageW(&Msg
);
2128 DestroyWindow(Console
->hWindow
);
2129 Console
->hWindow
= NULL
;
2130 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
2132 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
2133 if (0 == WindowCount
)
2136 DestroyWindow(hWnd
);
2137 PrivateCsrssManualGuiCheck(-1);
2142 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
2147 GuiConsoleGuiThread(PVOID Data
)
2150 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
2152 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
2154 WS_OVERLAPPEDWINDOW
,
2161 (HINSTANCE
) GetModuleHandleW(NULL
),
2163 if (NULL
== NotifyWnd
)
2165 PrivateCsrssManualGuiCheck(-1);
2166 SetEvent(*GraphicsStartupEvent
);
2170 SetEvent(*GraphicsStartupEvent
);
2172 while(GetMessageW(&msg
, NULL
, 0, 0))
2174 TranslateMessage(&msg
);
2175 DispatchMessageW(&msg
);
2186 if (NULL
== NotifyWnd
)
2188 PrivateCsrssManualGuiCheck(+1);
2191 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2192 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
2193 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
2195 wc
.hInstance
= (HINSTANCE
)GetModuleHandleW(NULL
);
2198 wc
.hbrBackground
= NULL
;
2199 wc
.lpszMenuName
= NULL
;
2203 if (RegisterClassExW(&wc
) == 0)
2205 DPRINT1("Failed to register notify wndproc\n");
2209 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2210 wc
.lpszClassName
= L
"ConsoleWindowClass";
2211 wc
.lpfnWndProc
= GuiConsoleWndProc
;
2213 wc
.hInstance
= (HINSTANCE
)GetModuleHandleW(NULL
);
2214 wc
.hIcon
= LoadIconW(ConSrvDllInstance
, MAKEINTRESOURCEW(1));
2215 wc
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
) IDC_ARROW
);
2216 wc
.hbrBackground
= CreateSolidBrush(RGB(0,0,0));
2217 wc
.lpszMenuName
= NULL
;
2220 wc
.hIconSm
= LoadImageW(ConSrvDllInstance
, MAKEINTRESOURCEW(1), IMAGE_ICON
,
2221 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
2223 if (RegisterClassExW(&wc
) == 0)
2225 DPRINT1("Failed to register console wndproc\n");
2233 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
2235 Buffer
->DefaultAttrib
= DEFAULT_ATTRIB
;
2239 GuiChangeTitle(PCSRSS_CONSOLE Console
)
2241 PWCHAR Buffer
, Title
;
2243 Buffer
= HeapAlloc(ConSrvHeap
, 0,
2244 Console
->Title
.Length
+ sizeof(WCHAR
));
2247 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
2248 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
2256 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
)Title
);
2260 HeapFree(ConSrvHeap
, 0, Buffer
);
2267 GuiChangeIcon(PCSRSS_CONSOLE Console
, HICON hWindowIcon
)
2269 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)hWindowIcon
);
2270 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)hWindowIcon
);
2276 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
2278 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
)Console
);
2281 static CSRSS_CONSOLE_VTBL GuiVtbl
=
2283 GuiInitScreenBuffer
,
2288 GuiUpdateScreenInfo
,
2296 GuiInitConsole(PCSRSS_CONSOLE Console
, int ShowCmd
)
2298 HANDLE GraphicsStartupEvent
;
2299 HANDLE ThreadHandle
;
2300 PGUI_CONSOLE_DATA GuiData
;
2302 if (! ConsInitialized
)
2304 ConsInitialized
= TRUE
;
2307 ConsInitialized
= FALSE
;
2308 return STATUS_UNSUCCESSFUL
;
2312 Console
->Vtbl
= &GuiVtbl
;
2313 if (NULL
== NotifyWnd
)
2315 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2316 if (NULL
== GraphicsStartupEvent
)
2318 return STATUS_UNSUCCESSFUL
;
2321 ThreadHandle
= CreateThread(NULL
,
2323 GuiConsoleGuiThread
,
2324 (PVOID
) &GraphicsStartupEvent
,
2327 if (NULL
== ThreadHandle
)
2329 CloseHandle(GraphicsStartupEvent
);
2330 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
2331 return STATUS_UNSUCCESSFUL
;
2333 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
2334 CloseHandle(ThreadHandle
);
2336 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
2337 CloseHandle(GraphicsStartupEvent
);
2339 if (NULL
== NotifyWnd
)
2341 DPRINT1("Win32Csr: Failed to create notification window.\n");
2342 return STATUS_UNSUCCESSFUL
;
2345 GuiData
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
,
2346 sizeof(GUI_CONSOLE_DATA
));
2349 DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
2350 return STATUS_UNSUCCESSFUL
;
2353 Console
->PrivateData
= (PVOID
) GuiData
;
2355 * we need to wait untill the GUI has been fully initialized
2356 * to retrieve custom settings i.e. WindowSize etc..
2357 * Ideally we could use SendNotifyMessage for this but its not
2361 GuiData
->hGuiInitEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2362 /* create console */
2363 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, ShowCmd
, (LPARAM
)Console
);
2365 /* wait untill initialization has finished */
2366 WaitForSingleObject(GuiData
->hGuiInitEvent
, INFINITE
);
2367 DPRINT("received event Console %p GuiData %p X %d Y %d\n", Console
, Console
->PrivateData
, Console
->Size
.X
, Console
->Size
.Y
);
2368 CloseHandle(GuiData
->hGuiInitEvent
);
2369 GuiData
->hGuiInitEvent
= NULL
;
2371 return STATUS_SUCCESS
;