3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: subsys/csrss/win32csr/guiconsole.c
6 * PURPOSE: Implementation of gui-mode consoles
9 /* INCLUDES ******************************************************************/
15 /* Not defined in any header file */
16 extern VOID WINAPI
PrivateCsrssManualGuiCheck(LONG Check
);
18 /* GLOBALS *******************************************************************/
20 typedef struct GUI_CONSOLE_DATA_TAG
27 CRITICAL_SECTION Lock
;
31 HMODULE ConsoleLibrary
;
33 WCHAR FontName
[LF_FACESIZE
];
40 DWORD NumberOfHistoryBuffers
;
41 DWORD HistoryBufferSize
;
45 COLORREF ScreenBackground
;
46 COLORREF PopupBackground
;
49 WCHAR szProcessName
[MAX_PATH
];
52 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
57 #define PM_CREATE_CONSOLE (WM_APP + 1)
58 #define PM_DESTROY_CONSOLE (WM_APP + 2)
60 #define CURSOR_BLINK_TIME 500
61 #define DEFAULT_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
63 static BOOL ConsInitialized
= FALSE
;
64 static HWND NotifyWnd
;
66 typedef struct _GUICONSOLE_MENUITEM
69 const struct _GUICONSOLE_MENUITEM
*SubMenu
;
71 } GUICONSOLE_MENUITEM
, *PGUICONSOLE_MENUITEM
;
73 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems
[] =
75 { IDS_MARK
, NULL
, ID_SYSTEM_EDIT_MARK
},
76 { IDS_COPY
, NULL
, ID_SYSTEM_EDIT_COPY
},
77 { IDS_PASTE
, NULL
, ID_SYSTEM_EDIT_PASTE
},
78 { IDS_SELECTALL
, NULL
, ID_SYSTEM_EDIT_SELECTALL
},
79 { IDS_SCROLL
, NULL
, ID_SYSTEM_EDIT_SCROLL
},
80 { IDS_FIND
, NULL
, ID_SYSTEM_EDIT_FIND
},
82 { 0, NULL
, 0 } /* End of list */
85 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems
[] =
87 { (UINT
)-1, NULL
, 0 }, /* Separator */
88 { IDS_EDIT
, GuiConsoleEditMenuItems
, 0 },
89 { IDS_DEFAULTS
, NULL
, ID_SYSTEM_DEFAULTS
},
90 { IDS_PROPERTIES
, NULL
, ID_SYSTEM_PROPERTIES
},
92 { 0, NULL
, 0 } /* End of list */
95 static const COLORREF s_Colors
[] =
115 #define GuiConsoleRGBFromAttribute(GuiData, Attribute) ((GuiData)->Colors[(Attribute) & 0xF])
117 /* FUNCTIONS *****************************************************************/
120 GuiConsoleAppendMenuItems(HMENU hMenu
,
121 const GUICONSOLE_MENUITEM
*Items
)
124 WCHAR szMenuString
[255];
126 HINSTANCE hInst
= GetModuleHandleW(L
"win32csr");
130 if (Items
[i
].uID
!= (UINT
)-1)
132 if (LoadStringW(hInst
,
135 sizeof(szMenuString
) / sizeof(szMenuString
[0])) > 0)
137 if (Items
[i
].SubMenu
!= NULL
)
139 hSubMenu
= CreatePopupMenu();
140 if (hSubMenu
!= NULL
)
142 GuiConsoleAppendMenuItems(hSubMenu
,
145 if (!AppendMenuW(hMenu
,
146 MF_STRING
| MF_POPUP
,
150 DestroyMenu(hSubMenu
);
171 }while(!(Items
[i
].uID
== 0 && Items
[i
].SubMenu
== NULL
&& Items
[i
].wCmdID
== 0));
175 GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console
)
178 hMenu
= GetSystemMenu(Console
->hWindow
,
182 GuiConsoleAppendMenuItems(hMenu
,
183 GuiConsoleMainMenuItems
);
184 DrawMenuBar(Console
->hWindow
);
189 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
191 *Console
= (PCSRSS_CONSOLE
) GetWindowLongPtrW(hWnd
, GWL_USERDATA
);
192 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
196 GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId
, PHANDLE hProcHandle
, PHKEY hResult
, REGSAM samDesired
)
198 HANDLE hProcessToken
= NULL
;
203 UNICODE_STRING SidName
;
207 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
| READ_CONTROL
, FALSE
, ProcessId
);
210 DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
214 if (!OpenProcessToken(hProcess
, TOKEN_QUERY
, &hProcessToken
))
216 DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
217 CloseHandle(hProcess
);
221 if (!GetTokenInformation(hProcessToken
, TokenUser
, (PVOID
)Buffer
, sizeof(Buffer
), &Length
))
223 DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
224 CloseHandle(hProcess
);
225 CloseHandle(hProcessToken
);
229 TokUser
= ((PTOKEN_USER
)Buffer
)->User
.Sid
;
230 if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName
, TokUser
, TRUE
)))
232 DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
236 res
= RegOpenKeyExW(HKEY_USERS
, SidName
.Buffer
, 0, samDesired
, hResult
);
237 RtlFreeUnicodeString(&SidName
);
239 CloseHandle(hProcessToken
);
241 *hProcHandle
= hProcess
;
243 CloseHandle(hProcess
);
245 if (res
!= ERROR_SUCCESS
)
252 GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData
, DWORD ProcessId
, PHKEY hSubKey
, REGSAM samDesired
, BOOL bCreate
)
254 WCHAR szProcessName
[MAX_PATH
];
255 WCHAR szBuffer
[MAX_PATH
];
256 UINT fLength
, wLength
;
257 DWORD dwBitmask
, dwLength
;
258 WCHAR CurDrive
[] = { 'A',':', 0 };
264 * console properties are stored under
267 * There are 3 ways to store console properties
269 * 1. use console title as subkey name
272 * 2. use application name as subkey name
274 * 3. use unexpanded path to console application.
275 * i.e. %SystemRoot%_system32_cmd.exe
278 DPRINT("GuiConsoleOpenUserSettings entered\n");
280 if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId
, &hProcess
, &hKey
, samDesired
))
282 DPRINT("GuiConsoleOpenUserRegistryPathPerProcessId failed\n");
286 /* FIXME we do not getting the process name so no menu will be loading, why ?*/
287 fLength
= GetProcessImageFileNameW(hProcess
, szProcessName
, sizeof(GuiData
->szProcessName
) / sizeof(WCHAR
));
288 CloseHandle(hProcess
);
290 //DPRINT1("szProcessName3 : %S\n",szProcessName);
294 DPRINT("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(),hProcess
);
298 * try the process name as path
301 ptr
= wcsrchr(szProcessName
, L
'\\');
302 wcscpy(GuiData
->szProcessName
, ptr
);
304 swprintf(szBuffer
, L
"Console%s",ptr
);
305 DPRINT("#1 Path : %S\n", szBuffer
);
309 if (RegCreateKeyW(hKey
, szBuffer
, hSubKey
) == ERROR_SUCCESS
)
318 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
325 * try the "Shortcut to processname" as path
326 * FIXME: detect wheter the process was started as a shortcut
329 swprintf(szBuffer
, L
"Console\\Shortcut to %S", ptr
);
330 DPRINT("#2 Path : %S\n", szBuffer
);
331 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
333 swprintf(GuiData
->szProcessName
, L
"Shortcut to %S", ptr
);
339 * if the path contains \\Device\\HarddiskVolume1\... remove it
342 if (szProcessName
[0] == L
'\\')
344 dwBitmask
= GetLogicalDrives();
349 dwLength
= QueryDosDeviceW(CurDrive
, szBuffer
, MAX_PATH
);
352 if (!memcmp(szBuffer
, szProcessName
, (dwLength
-2)*sizeof(WCHAR
)))
354 wcscpy(szProcessName
, CurDrive
);
355 RtlMoveMemory(&szProcessName
[2], &szProcessName
[dwLength
-1], fLength
- dwLength
-1);
360 dwBitmask
= (dwBitmask
>> 1);
366 * last attempt: check whether the file is under %SystemRoot%
367 * and use path like Console\%SystemRoot%_dir_dir2_file.exe
370 wLength
= GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
373 if (!wcsncmp(szProcessName
, szBuffer
, wLength
))
375 /* replace slashes by underscores */
376 while((ptr
= wcschr(szProcessName
, L
'\\')))
379 swprintf(szBuffer
, L
"Console\\%%SystemRoot%%%S", &szProcessName
[wLength
]);
380 DPRINT("#3 Path : %S\n", szBuffer
);
381 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
383 swprintf(GuiData
->szProcessName
, L
"%%SystemRoot%%%S", &szProcessName
[wLength
]);
394 GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
)
397 PCSRSS_PROCESS_DATA ProcessData
;
399 if (Console
->ProcessList
.Flink
== &Console
->ProcessList
)
401 DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
404 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
405 if (!GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
| KEY_WRITE
, TRUE
))
410 if (Console
->ActiveBuffer
->CursorInfo
.dwSize
<= 1)
412 RegDeleteKeyW(hKey
, L
"CursorSize");
416 RegSetValueExW(hKey
, L
"CursorSize", 0, REG_DWORD
, (const BYTE
*)&Console
->ActiveBuffer
->CursorInfo
.dwSize
, sizeof(DWORD
));
419 if (GuiData
->NumberOfHistoryBuffers
== 5)
421 RegDeleteKeyW(hKey
, L
"NumberOfHistoryBuffers");
425 RegSetValueExW(hKey
, L
"NumberOfHistoryBuffers", 0, REG_DWORD
, (const BYTE
*)&GuiData
->NumberOfHistoryBuffers
, sizeof(DWORD
));
428 if (GuiData
->HistoryBufferSize
== 50)
430 RegDeleteKeyW(hKey
, L
"HistoryBufferSize");
434 RegSetValueExW(hKey
, L
"HistoryBufferSize", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryBufferSize
, sizeof(DWORD
));
437 if (GuiData
->FullScreen
== FALSE
)
439 RegDeleteKeyW(hKey
, L
"FullScreen");
443 RegSetValueExW(hKey
, L
"FullScreen", 0, REG_DWORD
, (const BYTE
*)&GuiData
->FullScreen
, sizeof(DWORD
));
446 if ( GuiData
->QuickEdit
== FALSE
)
448 RegDeleteKeyW(hKey
, L
"QuickEdit");
452 RegSetValueExW(hKey
, L
"QuickEdit", 0, REG_DWORD
, (const BYTE
*)&GuiData
->QuickEdit
, sizeof(DWORD
));
455 if (GuiData
->InsertMode
== TRUE
)
457 RegDeleteKeyW(hKey
, L
"InsertMode");
461 RegSetValueExW(hKey
, L
"InsertMode", 0, REG_DWORD
, (const BYTE
*)&GuiData
->InsertMode
, sizeof(DWORD
));
464 if (GuiData
->HistoryNoDup
== FALSE
)
466 RegDeleteKeyW(hKey
, L
"HistoryNoDup");
470 RegSetValueExW(hKey
, L
"HistoryNoDup", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryNoDup
, sizeof(DWORD
));
473 if (GuiData
->ScreenText
== RGB(192, 192, 192))
476 * MS uses console attributes instead of real color
478 RegDeleteKeyW(hKey
, L
"ScreenText");
482 RegSetValueExW(hKey
, L
"ScreenText", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenText
, sizeof(COLORREF
));
485 if (GuiData
->ScreenBackground
== RGB(0, 0, 0))
487 RegDeleteKeyW(hKey
, L
"ScreenBackground");
491 RegSetValueExW(hKey
, L
"ScreenBackground", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenBackground
, sizeof(COLORREF
));
498 GuiConsoleReadUserSettings(HKEY hKey
, PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
500 DWORD dwNumSubKeys
= 0;
505 WCHAR szValueName
[MAX_PATH
];
506 WCHAR szValue
[LF_FACESIZE
] = L
"\0";
509 if (RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
511 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
515 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
517 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
519 dwValue
= sizeof(Value
);
520 dwValueName
= MAX_PATH
;
522 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
524 if (dwType
== REG_SZ
)
527 * retry in case of string value
529 dwValue
= sizeof(szValue
);
530 dwValueName
= LF_FACESIZE
;
531 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
537 if (!wcscmp(szValueName
, L
"CursorSize"))
541 Buffer
->CursorInfo
.dwSize
= Value
;
543 else if (Value
== 0x64)
545 Buffer
->CursorInfo
.dwSize
= Value
;
548 else if (!wcscmp(szValueName
, L
"ScreenText"))
550 GuiData
->ScreenText
= Value
;
552 else if (!wcscmp(szValueName
, L
"ScreenBackground"))
554 GuiData
->ScreenBackground
= Value
;
556 else if (!wcscmp(szValueName
, L
"FaceName"))
558 wcscpy(GuiData
->FontName
, szValue
);
560 else if (!wcscmp(szValueName
, L
"FontSize"))
562 GuiData
->FontSize
= Value
;
564 else if (!wcscmp(szValueName
, L
"FontWeight"))
566 GuiData
->FontWeight
= Value
;
568 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
570 GuiData
->HistoryNoDup
= Value
;
572 else if (!wcscmp(szValueName
, L
"WindowSize"))
574 Console
->Size
.X
= LOWORD(Value
);
575 Console
->Size
.Y
= HIWORD(Value
);
577 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
581 Buffer
->MaxX
= LOWORD(Value
);
582 Buffer
->MaxY
= HIWORD(Value
);
585 else if (!wcscmp(szValueName
, L
"FullScreen"))
587 GuiData
->FullScreen
= Value
;
589 else if (!wcscmp(szValueName
, L
"QuickEdit"))
591 GuiData
->QuickEdit
= Value
;
593 else if (!wcscmp(szValueName
, L
"InsertMode"))
595 GuiData
->InsertMode
= Value
;
600 GuiConsoleUseDefaults(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
603 * init guidata with default properties
606 wcscpy(GuiData
->FontName
, L
"DejaVu Sans Mono");
607 GuiData
->FontSize
= 0x0008000C; // font is 8x12
608 GuiData
->FontWeight
= FW_NORMAL
;
609 GuiData
->HistoryNoDup
= FALSE
;
610 GuiData
->FullScreen
= FALSE
;
611 GuiData
->QuickEdit
= FALSE
;
612 GuiData
->InsertMode
= TRUE
;
613 GuiData
->HistoryBufferSize
= 50;
614 GuiData
->NumberOfHistoryBuffers
= 5;
615 GuiData
->ScreenText
= RGB(192, 192, 192);
616 GuiData
->ScreenBackground
= RGB(0, 0, 0);
617 GuiData
->PopupText
= RGB(128, 0, 128);
618 GuiData
->PopupBackground
= RGB(255, 255, 255);
619 GuiData
->WindowPosition
= UINT_MAX
;
620 GuiData
->UseRasterFonts
= TRUE
;
621 memcpy(GuiData
->Colors
, s_Colors
, sizeof(s_Colors
));
623 Console
->Size
.X
= 80;
624 Console
->Size
.Y
= 25;
630 Buffer
->CursorInfo
.bVisible
= TRUE
;
631 Buffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
637 GuiConsoleInitScrollbar(PCSRSS_CONSOLE Console
, HWND hwnd
)
640 PGUI_CONSOLE_DATA GuiData
= Console
->PrivateData
;
642 DWORD Width
= Console
->Size
.X
* GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
643 DWORD Height
= Console
->Size
.Y
* GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
645 /* set scrollbar sizes */
646 sInfo
.cbSize
= sizeof(SCROLLINFO
);
647 sInfo
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
649 if (Console
->ActiveBuffer
->MaxY
> Console
->Size
.Y
)
651 sInfo
.nMax
= Console
->ActiveBuffer
->MaxY
- 1;
652 sInfo
.nPage
= Console
->Size
.Y
;
653 sInfo
.nPos
= Console
->ActiveBuffer
->ShowY
;
654 SetScrollInfo(hwnd
, SB_VERT
, &sInfo
, TRUE
);
655 Width
+= GetSystemMetrics(SM_CXVSCROLL
);
656 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
660 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
663 if (Console
->ActiveBuffer
->MaxX
> Console
->Size
.X
)
665 sInfo
.nMax
= Console
->ActiveBuffer
->MaxX
- 1;
666 sInfo
.nPage
= Console
->Size
.X
;
667 sInfo
.nPos
= Console
->ActiveBuffer
->ShowX
;
668 SetScrollInfo(hwnd
, SB_HORZ
, &sInfo
, TRUE
);
669 Height
+= GetSystemMetrics(SM_CYHSCROLL
);
670 ShowScrollBar(hwnd
, SB_HORZ
, TRUE
);
675 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
678 SetWindowPos(hwnd
, NULL
, 0, 0, Width
, Height
,
679 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
683 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
685 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
686 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Console
->PrivateData
;
691 PCSRSS_PROCESS_DATA ProcessData
;
694 Console
->hWindow
= hWnd
;
698 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
702 GuiConsoleUseDefaults(Console
, GuiData
, Console
->ActiveBuffer
);
703 if (Console
->ProcessList
.Flink
!= &Console
->ProcessList
)
705 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
706 if (GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
, FALSE
))
708 GuiConsoleReadUserSettings(hKey
, Console
, GuiData
, Console
->ActiveBuffer
);
713 InitializeCriticalSection(&GuiData
->Lock
);
715 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->FontSize
),
716 0, //HIWORD(GuiData->FontSize),
724 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
725 NONANTIALIASED_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
727 if (NULL
== GuiData
->Font
)
729 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
730 DeleteCriticalSection(&GuiData
->Lock
);
731 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
737 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
738 DeleteObject(GuiData
->Font
);
739 DeleteCriticalSection(&GuiData
->Lock
);
740 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
743 OldFont
= SelectObject(Dc
, GuiData
->Font
);
746 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
748 DeleteObject(GuiData
->Font
);
749 DeleteCriticalSection(&GuiData
->Lock
);
750 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
753 if (! GetTextMetricsW(Dc
, &Metrics
))
755 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
756 SelectObject(Dc
, OldFont
);
758 DeleteObject(GuiData
->Font
);
759 DeleteCriticalSection(&GuiData
->Lock
);
760 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
763 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
764 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
766 /* Measure real char width more precisely if possible. */
767 if (GetTextExtentPoint32W(Dc
, L
"R", 1, &CharSize
))
768 GuiData
->CharWidth
= CharSize
.cx
;
770 SelectObject(Dc
, OldFont
);
773 GuiData
->CursorBlinkOn
= TRUE
;
774 GuiData
->ForceCursorOff
= FALSE
;
776 GuiData
->Selection
.left
= -1;
777 DPRINT("Console %p GuiData %p\n", Console
, GuiData
);
778 Console
->PrivateData
= GuiData
;
779 SetWindowLongPtrW(hWnd
, GWL_USERDATA
, (DWORD_PTR
) Console
);
781 SetTimer(hWnd
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
782 GuiConsoleCreateSysMenu(Console
);
784 GuiData
->WindowSizeLock
= TRUE
;
785 GuiConsoleInitScrollbar(Console
, hWnd
);
786 GuiData
->WindowSizeLock
= FALSE
;
788 SetEvent(GuiData
->hGuiInitEvent
);
790 return (BOOL
) DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
) Create
);
794 GuiConsoleUpdateSelection(HWND hWnd
, PRECT rc
, PGUI_CONSOLE_DATA GuiData
)
796 RECT oldRect
= GuiData
->Selection
;
800 RECT changeRect
= *rc
;
802 GuiData
->Selection
= *rc
;
804 changeRect
.left
*= GuiData
->CharWidth
;
805 changeRect
.top
*= GuiData
->CharHeight
;
806 changeRect
.right
*= GuiData
->CharWidth
;
807 changeRect
.bottom
*= GuiData
->CharHeight
;
809 if(rc
->left
!= oldRect
.left
||
810 rc
->top
!= oldRect
.top
||
811 rc
->right
!= oldRect
.right
||
812 rc
->bottom
!= oldRect
.bottom
)
814 if(oldRect
.left
!= -1)
818 oldRect
.left
*= GuiData
->CharWidth
;
819 oldRect
.top
*= GuiData
->CharHeight
;
820 oldRect
.right
*= GuiData
->CharWidth
;
821 oldRect
.bottom
*= GuiData
->CharHeight
;
823 /* calculate the region that needs to be updated */
824 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
826 if((rgn2
= CreateRectRgnIndirect(&changeRect
)))
828 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
830 InvalidateRgn(hWnd
, rgn1
, FALSE
);
840 InvalidateRect(hWnd
, &changeRect
, FALSE
);
844 else if(oldRect
.left
!= -1)
846 /* clear the selection */
847 GuiData
->Selection
.left
= -1;
848 oldRect
.left
*= GuiData
->CharWidth
;
849 oldRect
.top
*= GuiData
->CharHeight
;
850 oldRect
.right
*= GuiData
->CharWidth
;
851 oldRect
.bottom
*= GuiData
->CharHeight
;
852 InvalidateRect(hWnd
, &oldRect
, FALSE
);
858 GuiConsolePaint(PCSRSS_CONSOLE Console
,
859 PGUI_CONSOLE_DATA GuiData
,
863 PCSRSS_SCREEN_BUFFER Buff
;
864 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
865 ULONG Line
, Char
, Start
;
868 BYTE LastAttribute
, Attribute
;
869 ULONG CursorX
, CursorY
, CursorHeight
;
870 HBRUSH CursorBrush
, OldBrush
;
873 Buff
= Console
->ActiveBuffer
;
875 EnterCriticalSection(&Buff
->Header
.Lock
);
877 TopLine
= rc
->top
/ GuiData
->CharHeight
+ Buff
->ShowY
;
878 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1 + Buff
->ShowY
;
879 LeftChar
= rc
->left
/ GuiData
->CharWidth
+ Buff
->ShowX
;
880 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1 + Buff
->ShowX
;
881 LastAttribute
= ConioCoordToPointer(Buff
, LeftChar
, TopLine
)[1];
883 SetTextColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, LastAttribute
));
884 SetBkColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, LastAttribute
>> 4));
886 if (BottomLine
>= Buff
->MaxY
) BottomLine
= Buff
->MaxY
- 1;
887 if (RightChar
>= Buff
->MaxX
) RightChar
= Buff
->MaxX
- 1;
889 OldFont
= SelectObject(hDC
,
892 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
894 WCHAR LineBuffer
[80];
895 From
= ConioCoordToPointer(Buff
, LeftChar
, Line
);
899 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
901 if (*(From
+ 1) != LastAttribute
|| (Char
- Start
== sizeof(LineBuffer
) / sizeof(WCHAR
)))
904 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
905 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
910 Attribute
= *(From
+ 1);
911 if (Attribute
!= LastAttribute
)
913 SetTextColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, Attribute
));
914 SetBkColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, Attribute
>> 4));
915 LastAttribute
= Attribute
;
919 MultiByteToWideChar(Console
->OutputCodePage
,
930 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
931 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
933 RightChar
- Start
+ 1);
936 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
&&
937 !GuiData
->ForceCursorOff
)
939 CursorX
= Buff
->CurrentX
;
940 CursorY
= Buff
->CurrentY
;
941 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
942 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
944 CursorHeight
= (GuiData
->CharHeight
* Buff
->CursorInfo
.dwSize
) / 100;
945 if (CursorHeight
< 1)
949 From
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
) + 1;
951 if (*From
!= DEFAULT_ATTRIB
)
953 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(GuiData
, *From
));
957 CursorBrush
= CreateSolidBrush(GuiData
->ScreenText
);
960 OldBrush
= SelectObject(hDC
,
963 (CursorX
- Buff
->ShowX
) * GuiData
->CharWidth
,
964 (CursorY
- Buff
->ShowY
) * GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
970 DeleteObject(CursorBrush
);
974 LeaveCriticalSection(&Buff
->Header
.Lock
);
981 GuiConsoleHandlePaint(HWND hWnd
, HDC hDCPaint
)
985 PCSRSS_CONSOLE Console
;
986 PGUI_CONSOLE_DATA GuiData
;
988 hDC
= BeginPaint(hWnd
, &ps
);
990 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
991 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
993 GuiConsoleGetDataPointers(hWnd
,
996 if (Console
!= NULL
&& GuiData
!= NULL
&&
997 Console
->ActiveBuffer
!= NULL
)
999 if (Console
->ActiveBuffer
->Buffer
!= NULL
)
1001 EnterCriticalSection(&GuiData
->Lock
);
1003 GuiConsolePaint(Console
,
1008 if (GuiData
->Selection
.left
!= -1)
1010 RECT rc
= GuiData
->Selection
;
1012 rc
.left
*= GuiData
->CharWidth
;
1013 rc
.top
*= GuiData
->CharHeight
;
1014 rc
.right
*= GuiData
->CharWidth
;
1015 rc
.bottom
*= GuiData
->CharHeight
;
1017 /* invert the selection */
1018 if (IntersectRect(&rc
,
1031 LeaveCriticalSection(&GuiData
->Lock
);
1036 EndPaint(hWnd
, &ps
);
1039 static VOID FASTCALL
1040 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1042 PCSRSS_CONSOLE Console
;
1043 PGUI_CONSOLE_DATA GuiData
;
1046 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1047 Message
.hwnd
= hWnd
;
1048 Message
.message
= msg
;
1049 Message
.wParam
= wParam
;
1050 Message
.lParam
= lParam
;
1052 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
1054 /* clear the selection */
1055 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
1058 ConioProcessKey(&Message
, Console
, FALSE
);
1061 static VOID FASTCALL
1062 GuiIntDrawRegion(PCSRSS_SCREEN_BUFFER Buff
, PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, RECT
*Region
)
1066 RegionRect
.left
= (Region
->left
- Buff
->ShowX
) * GuiData
->CharWidth
;
1067 RegionRect
.top
= (Region
->top
- Buff
->ShowY
) * GuiData
->CharHeight
;
1068 RegionRect
.right
= (Region
->right
+ 1 - Buff
->ShowX
) * GuiData
->CharWidth
;
1069 RegionRect
.bottom
= (Region
->bottom
+ 1 - Buff
->ShowY
) * GuiData
->CharHeight
;
1071 InvalidateRect(Wnd
, &RegionRect
, FALSE
);
1075 GuiDrawRegion(PCSRSS_CONSOLE Console
, RECT
*Region
)
1077 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1079 if (NULL
!= Console
->hWindow
&& NULL
!= GuiData
)
1081 GuiIntDrawRegion(Console
->ActiveBuffer
, GuiData
, Console
->hWindow
, Region
);
1085 static VOID FASTCALL
1086 GuiInvalidateCell(PCSRSS_SCREEN_BUFFER Buff
, PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, UINT x
, UINT y
)
1093 CellRect
.bottom
= y
;
1095 GuiIntDrawRegion(Buff
, GuiData
, Wnd
, &CellRect
);
1099 GuiWriteStream(PCSRSS_CONSOLE Console
, RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
1100 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
1102 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1103 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1104 LONG CursorEndX
, CursorEndY
;
1107 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
1112 if (0 != ScrolledLines
)
1114 ScrollRect
.left
= 0;
1116 ScrollRect
.right
= Console
->Size
.X
* GuiData
->CharWidth
;
1117 ScrollRect
.bottom
= Region
->top
* GuiData
->CharHeight
;
1119 if (GuiData
->Selection
.left
!= -1)
1121 /* scroll the selection */
1122 if (GuiData
->Selection
.top
> ScrolledLines
)
1124 GuiData
->Selection
.top
-= ScrolledLines
;
1125 GuiData
->Selection
.bottom
-= ScrolledLines
;
1127 else if (GuiData
->Selection
.bottom
< ScrolledLines
)
1129 GuiData
->Selection
.left
= -1;
1133 GuiData
->Selection
.top
= 0;
1134 GuiData
->Selection
.bottom
-= ScrolledLines
;
1138 ScrollWindowEx(Console
->hWindow
,
1140 -(ScrolledLines
* GuiData
->CharHeight
),
1148 GuiIntDrawRegion(Buff
, GuiData
, Console
->hWindow
, Region
);
1150 if (CursorStartX
< Region
->left
|| Region
->right
< CursorStartX
1151 || CursorStartY
< Region
->top
|| Region
->bottom
< CursorStartY
)
1153 GuiInvalidateCell(Buff
, GuiData
, Console
->hWindow
, CursorStartX
, CursorStartY
);
1156 CursorEndX
= Buff
->CurrentX
;
1157 CursorEndY
= Buff
->CurrentY
;
1158 if ((CursorEndX
< Region
->left
|| Region
->right
< CursorEndX
1159 || CursorEndY
< Region
->top
|| Region
->bottom
< CursorEndY
)
1160 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
1162 GuiInvalidateCell(Buff
, GuiData
, Console
->hWindow
, CursorEndX
, CursorEndY
);
1165 // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
1166 // repaint the window without having it just freeze up and stay on the screen permanently.
1167 GuiData
->CursorBlinkOn
= TRUE
;
1168 SetTimer(Console
->hWindow
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
1172 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1176 if (Console
->ActiveBuffer
== Buff
)
1178 UpdateRect
.left
= Buff
->CurrentX
;
1179 UpdateRect
.top
= Buff
->CurrentY
;
1180 UpdateRect
.right
= UpdateRect
.left
;
1181 UpdateRect
.bottom
= UpdateRect
.top
;
1182 ConioDrawRegion(Console
, &UpdateRect
);
1189 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
1193 if (Console
->ActiveBuffer
== Buff
)
1195 /* Redraw char at old position (removes cursor) */
1196 UpdateRect
.left
= OldCursorX
;
1197 UpdateRect
.top
= OldCursorY
;
1198 UpdateRect
.right
= OldCursorX
;
1199 UpdateRect
.bottom
= OldCursorY
;
1200 ConioDrawRegion(Console
, &UpdateRect
);
1201 /* Redraw char at new position (shows cursor) */
1202 UpdateRect
.left
= Buff
->CurrentX
;
1203 UpdateRect
.top
= Buff
->CurrentY
;
1204 UpdateRect
.right
= UpdateRect
.left
;
1205 UpdateRect
.bottom
= UpdateRect
.top
;
1206 ConioDrawRegion(Console
, &UpdateRect
);
1213 GuiUpdateScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1215 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1217 if (Console
->ActiveBuffer
== Buff
)
1219 GuiData
->ScreenText
= GuiConsoleRGBFromAttribute(GuiData
, Buff
->DefaultAttrib
);
1220 GuiData
->ScreenBackground
= GuiConsoleRGBFromAttribute(GuiData
, Buff
->DefaultAttrib
>> 4);
1226 static VOID FASTCALL
1227 GuiConsoleHandleTimer(HWND hWnd
)
1229 PCSRSS_CONSOLE Console
;
1230 PGUI_CONSOLE_DATA GuiData
;
1231 PCSRSS_SCREEN_BUFFER Buff
;
1234 SetTimer(hWnd
, CONGUI_UPDATE_TIMER
, CURSOR_BLINK_TIME
, NULL
);
1236 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1238 Buff
= Console
->ActiveBuffer
;
1239 CursorRect
.left
= Buff
->CurrentX
;
1240 CursorRect
.top
= Buff
->CurrentY
;
1241 CursorRect
.right
= CursorRect
.left
;
1242 CursorRect
.bottom
= CursorRect
.top
;
1243 GuiDrawRegion(Console
, &CursorRect
);
1244 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
1246 if((GuiData
->OldCursor
.x
!= Buff
->CurrentX
) || (GuiData
->OldCursor
.y
!= Buff
->CurrentY
))
1249 int OldScrollX
= -1, OldScrollY
= -1;
1250 int NewScrollX
= -1, NewScrollY
= -1;
1252 xScroll
.cbSize
= sizeof(SCROLLINFO
);
1253 xScroll
.fMask
= SIF_POS
;
1254 // Capture the original position of the scroll bars and save them.
1255 if(GetScrollInfo(hWnd
, SB_HORZ
, &xScroll
))OldScrollX
= xScroll
.nPos
;
1256 if(GetScrollInfo(hWnd
, SB_VERT
, &xScroll
))OldScrollY
= xScroll
.nPos
;
1258 // If we successfully got the info for the horizontal scrollbar
1261 if((Buff
->CurrentX
< Buff
->ShowX
)||(Buff
->CurrentX
>= (Buff
->ShowX
+ Console
->Size
.X
)))
1263 // Handle the horizontal scroll bar
1264 if(Buff
->CurrentX
>= Console
->Size
.X
) NewScrollX
= Buff
->CurrentX
- Console
->Size
.X
+ 1;
1265 else NewScrollX
= 0;
1269 NewScrollX
= OldScrollX
;
1272 // If we successfully got the info for the vertical scrollbar
1275 if((Buff
->CurrentY
< Buff
->ShowY
) || (Buff
->CurrentY
>= (Buff
->ShowY
+ Console
->Size
.Y
)))
1277 // Handle the vertical scroll bar
1278 if(Buff
->CurrentY
>= Console
->Size
.Y
) NewScrollY
= Buff
->CurrentY
- Console
->Size
.Y
+ 1;
1279 else NewScrollY
= 0;
1283 NewScrollY
= OldScrollY
;
1287 // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
1288 // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
1289 // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
1290 // and their associated scrollbar is left alone.
1291 if((OldScrollX
!= NewScrollX
) || (OldScrollY
!= NewScrollY
))
1293 Buff
->ShowX
= NewScrollX
;
1294 Buff
->ShowY
= NewScrollY
;
1295 ScrollWindowEx(hWnd
,
1296 (OldScrollX
- NewScrollX
) * GuiData
->CharWidth
,
1297 (OldScrollY
- NewScrollY
) * GuiData
->CharHeight
,
1305 xScroll
.nPos
= NewScrollX
;
1306 SetScrollInfo(hWnd
, SB_HORZ
, &xScroll
, TRUE
);
1310 xScroll
.nPos
= NewScrollY
;
1311 SetScrollInfo(hWnd
, SB_VERT
, &xScroll
, TRUE
);
1314 GuiData
->OldCursor
.x
= Buff
->CurrentX
;
1315 GuiData
->OldCursor
.y
= Buff
->CurrentY
;
1320 static VOID FASTCALL
1321 GuiConsoleHandleClose(HWND hWnd
)
1323 PCSRSS_CONSOLE Console
;
1324 PGUI_CONSOLE_DATA GuiData
;
1325 PLIST_ENTRY current_entry
;
1326 PCSRSS_PROCESS_DATA current
;
1328 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1330 EnterCriticalSection(&Console
->Header
.Lock
);
1332 current_entry
= Console
->ProcessList
.Flink
;
1333 while (current_entry
!= &Console
->ProcessList
)
1335 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1336 current_entry
= current_entry
->Flink
;
1338 /* FIXME: Windows will wait up to 5 seconds for the thread to exit.
1339 * We shouldn't wait here, though, since the console lock is entered.
1340 * A copy of the thread list probably needs to be made. */
1341 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
1344 LeaveCriticalSection(&Console
->Header
.Lock
);
1347 static VOID FASTCALL
1348 GuiConsoleHandleNcDestroy(HWND hWnd
)
1350 PCSRSS_CONSOLE Console
;
1351 PGUI_CONSOLE_DATA GuiData
;
1354 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1356 Console
->PrivateData
= NULL
;
1357 DeleteCriticalSection(&GuiData
->Lock
);
1358 GetSystemMenu(hWnd
, TRUE
);
1359 if (GuiData
->ConsoleLibrary
)
1360 FreeLibrary(GuiData
->ConsoleLibrary
);
1362 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
1365 static VOID FASTCALL
1366 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
1368 PCSRSS_CONSOLE Console
;
1369 PGUI_CONSOLE_DATA GuiData
;
1373 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1374 if (Console
== NULL
|| GuiData
== NULL
) return;
1376 pt
= MAKEPOINTS(lParam
);
1378 rc
.left
= pt
.x
/ GuiData
->CharWidth
;
1379 rc
.top
= pt
.y
/ GuiData
->CharHeight
;
1380 rc
.right
= rc
.left
+ 1;
1381 rc
.bottom
= rc
.top
+ 1;
1383 GuiData
->SelectionStart
.x
= rc
.left
;
1384 GuiData
->SelectionStart
.y
= rc
.top
;
1388 GuiData
->MouseDown
= TRUE
;
1390 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1393 static VOID FASTCALL
1394 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
1396 PCSRSS_CONSOLE Console
;
1397 PGUI_CONSOLE_DATA GuiData
;
1401 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1402 if (Console
== NULL
|| GuiData
== NULL
) return;
1403 if (GuiData
->Selection
.left
== -1 || !GuiData
->MouseDown
) return;
1405 pt
= MAKEPOINTS(lParam
);
1407 rc
.left
= GuiData
->SelectionStart
.x
;
1408 rc
.top
= GuiData
->SelectionStart
.y
;
1409 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
1410 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
1412 /* exchange left/top with right/bottom if required */
1413 if(rc
.left
>= rc
.right
)
1417 rc
.left
= max(rc
.right
- 1, 0);
1420 if(rc
.top
>= rc
.bottom
)
1424 rc
.top
= max(rc
.bottom
- 1, 0);
1425 rc
.bottom
= tmp
+ 1;
1428 GuiData
->MouseDown
= FALSE
;
1430 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1435 static VOID FASTCALL
1436 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1438 PCSRSS_CONSOLE Console
;
1439 PGUI_CONSOLE_DATA GuiData
;
1443 if (!(wParam
& MK_LBUTTON
)) return;
1445 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1446 if (Console
== NULL
|| GuiData
== NULL
|| !GuiData
->MouseDown
) return;
1448 pt
= MAKEPOINTS(lParam
);
1450 rc
.left
= GuiData
->SelectionStart
.x
;
1451 rc
.top
= GuiData
->SelectionStart
.y
;
1452 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
1453 if (Console
->Size
.X
< rc
.right
)
1455 rc
.right
= Console
->Size
.X
;
1457 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
1458 if (Console
->Size
.Y
< rc
.bottom
)
1460 rc
.bottom
= Console
->Size
.Y
;
1463 /* exchange left/top with right/bottom if required */
1464 if(rc
.left
>= rc
.right
)
1468 rc
.left
= max(rc
.right
- 1, 0);
1471 if(rc
.top
>= rc
.bottom
)
1475 rc
.top
= max(rc
.bottom
- 1, 0);
1476 rc
.bottom
= tmp
+ 1;
1479 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1482 static VOID FASTCALL
1483 GuiConsoleRightMouseDown(HWND hWnd
)
1485 PCSRSS_CONSOLE Console
;
1486 PGUI_CONSOLE_DATA GuiData
;
1488 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1489 if (Console
== NULL
|| GuiData
== NULL
) return;
1491 if (GuiData
->Selection
.left
== -1)
1493 /* FIXME - paste text from clipboard */
1497 /* FIXME - copy selection to clipboard */
1499 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
1506 GuiConsoleShowConsoleProperties(HWND hWnd
, BOOL Defaults
, PGUI_CONSOLE_DATA GuiData
)
1508 PCSRSS_CONSOLE Console
;
1509 APPLET_PROC CPLFunc
;
1510 TCHAR szBuffer
[MAX_PATH
];
1511 ConsoleInfo SharedInfo
;
1513 DPRINT("GuiConsoleShowConsoleProperties entered\n");
1515 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1517 if (GuiData
== NULL
)
1519 DPRINT("GuiConsoleGetDataPointers failed\n");
1523 if (GuiData
->ConsoleLibrary
== NULL
)
1525 GetWindowsDirectory(szBuffer
,MAX_PATH
);
1526 _tcscat(szBuffer
, _T("\\system32\\console.dll"));
1527 GuiData
->ConsoleLibrary
= LoadLibrary(szBuffer
);
1529 if (GuiData
->ConsoleLibrary
== NULL
)
1531 DPRINT1("failed to load console.dll");
1536 CPLFunc
= (APPLET_PROC
) GetProcAddress(GuiData
->ConsoleLibrary
, _T("CPlApplet"));
1539 DPRINT("Error: Console.dll misses CPlApplet export\n");
1544 SharedInfo
.InsertMode
= GuiData
->InsertMode
;
1545 SharedInfo
.HistoryBufferSize
= GuiData
->HistoryBufferSize
;
1546 SharedInfo
.NumberOfHistoryBuffers
= GuiData
->NumberOfHistoryBuffers
;
1547 SharedInfo
.ScreenText
= GuiData
->ScreenText
;
1548 SharedInfo
.ScreenBackground
= GuiData
->ScreenBackground
;
1549 SharedInfo
.PopupText
= GuiData
->PopupText
;
1550 SharedInfo
.PopupBackground
= GuiData
->PopupBackground
;
1551 SharedInfo
.WindowSize
= (DWORD
)MAKELONG(Console
->Size
.X
, Console
->Size
.Y
);
1552 SharedInfo
.WindowPosition
= GuiData
->WindowPosition
;
1553 SharedInfo
.ScreenBuffer
= (DWORD
)MAKELONG(Console
->ActiveBuffer
->MaxX
, Console
->ActiveBuffer
->MaxY
);
1554 SharedInfo
.UseRasterFonts
= GuiData
->UseRasterFonts
;
1555 SharedInfo
.FontSize
= (DWORD
)GuiData
->FontSize
;
1556 SharedInfo
.FontWeight
= GuiData
->FontWeight
;
1557 SharedInfo
.CursorSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1558 SharedInfo
.HistoryNoDup
= GuiData
->HistoryNoDup
;
1559 SharedInfo
.FullScreen
= GuiData
->FullScreen
;
1560 SharedInfo
.QuickEdit
= GuiData
->QuickEdit
;
1561 memcpy(&SharedInfo
.Colors
[0], GuiData
->Colors
, sizeof(s_Colors
));
1563 if (!CPLFunc(hWnd
, CPL_INIT
, 0, 0))
1565 DPRINT("Error: failed to initialize console.dll\n");
1569 if (CPLFunc(hWnd
, CPL_GETCOUNT
, 0, 0) != 1)
1571 DPRINT("Error: console.dll returned unexpected CPL count\n");
1575 CPLFunc(hWnd
, CPL_DBLCLK
, (LPARAM
)&SharedInfo
, Defaults
);
1577 static LRESULT FASTCALL
1578 GuiConsoleHandleSysMenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
, PGUI_CONSOLE_DATA GuiData
)
1584 case ID_SYSTEM_EDIT_MARK
:
1585 case ID_SYSTEM_EDIT_COPY
:
1586 case ID_SYSTEM_EDIT_PASTE
:
1587 case ID_SYSTEM_EDIT_SELECTALL
:
1588 case ID_SYSTEM_EDIT_SCROLL
:
1589 case ID_SYSTEM_EDIT_FIND
:
1592 case ID_SYSTEM_DEFAULTS
:
1593 GuiConsoleShowConsoleProperties(hWnd
, TRUE
, GuiData
);
1596 case ID_SYSTEM_PROPERTIES
:
1597 GuiConsoleShowConsoleProperties(hWnd
, FALSE
, GuiData
);
1601 Ret
= DefWindowProcW(hWnd
, WM_SYSCOMMAND
, wParam
, lParam
);
1607 static VOID FASTCALL
1608 GuiConsoleGetMinMaxInfo(HWND hWnd
, PMINMAXINFO minMaxInfo
)
1610 PCSRSS_CONSOLE Console
;
1611 PGUI_CONSOLE_DATA GuiData
;
1612 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1613 if((Console
== NULL
)|| (GuiData
== NULL
)) return;
1615 DWORD windx
= CONGUI_MIN_WIDTH
* GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1616 DWORD windy
= CONGUI_MIN_HEIGHT
* GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1618 minMaxInfo
->ptMinTrackSize
.x
= windx
;
1619 minMaxInfo
->ptMinTrackSize
.y
= windy
;
1621 windx
= (Console
->ActiveBuffer
->MaxX
) * GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1622 windy
= (Console
->ActiveBuffer
->MaxY
) * GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1624 if(Console
->Size
.X
< Console
->ActiveBuffer
->MaxX
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1625 if(Console
->Size
.Y
< Console
->ActiveBuffer
->MaxY
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1627 minMaxInfo
->ptMaxTrackSize
.x
= windx
;
1628 minMaxInfo
->ptMaxTrackSize
.y
= windy
;
1630 static VOID FASTCALL
1631 GuiConsoleResize(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1633 PCSRSS_CONSOLE Console
;
1634 PGUI_CONSOLE_DATA GuiData
;
1635 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1636 if((Console
== NULL
) || (GuiData
== NULL
)) return;
1638 if ((GuiData
->WindowSizeLock
== FALSE
) && (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
))
1640 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1642 GuiData
->WindowSizeLock
= TRUE
;
1644 DWORD windx
= LOWORD(lParam
);
1645 DWORD windy
= HIWORD(lParam
);
1647 // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
1648 if(Console
->Size
.X
< Buff
->MaxX
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1649 if(Console
->Size
.Y
< Buff
->MaxY
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1651 DWORD charx
= windx
/ GuiData
->CharWidth
;
1652 DWORD chary
= windy
/ GuiData
->CharHeight
;
1654 // Character alignment (round size up or down)
1655 if((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1656 if((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1658 // Compensate for added scroll bars in new window
1659 if(charx
< Buff
->MaxX
)windy
-= GetSystemMetrics(SM_CYHSCROLL
); // new window will have a horizontal scroll bar
1660 if(chary
< Buff
->MaxY
)windx
-= GetSystemMetrics(SM_CXVSCROLL
); // new window will have a vertical scroll bar
1662 charx
= windx
/ GuiData
->CharWidth
;
1663 chary
= windy
/ GuiData
->CharHeight
;
1665 // Character alignment (round size up or down)
1666 if((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1667 if((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1670 if((charx
!= Console
->Size
.X
) || (chary
!= Console
->Size
.Y
))
1672 Console
->Size
.X
= (charx
<= Buff
->MaxX
) ? charx
: Buff
->MaxX
;
1673 Console
->Size
.Y
= (chary
<= Buff
->MaxY
) ? chary
: Buff
->MaxY
;
1676 GuiConsoleInitScrollbar(Console
, hWnd
);
1678 // Adjust the start of the visible area if we are attempting to show nonexistent areas
1679 if((Buff
->MaxX
- Buff
->ShowX
) < Console
->Size
.X
) Buff
->ShowX
= Buff
->MaxX
- Console
->Size
.X
;
1680 if((Buff
->MaxY
- Buff
->ShowY
) < Console
->Size
.Y
) Buff
->ShowY
= Buff
->MaxY
- Console
->Size
.Y
;
1681 InvalidateRect(hWnd
, NULL
, TRUE
);
1683 GuiData
->WindowSizeLock
= FALSE
;
1688 GuiConsoleHandleScrollbarMenu()
1692 hMenu
= CreatePopupMenu();
1695 DPRINT("CreatePopupMenu failed\n");
1698 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1699 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1700 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1701 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1702 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1703 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1704 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1705 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1706 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1707 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1711 static NTSTATUS WINAPI
1712 GuiResizeBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER ScreenBuffer
, COORD Size
)
1720 USHORT value
= MAKEWORD(' ', ScreenBuffer
->DefaultAttrib
);
1725 /* Buffer size is not allowed to be smaller than window size */
1726 if (Size
.X
< Console
->Size
.X
|| Size
.Y
< Console
->Size
.Y
)
1727 return STATUS_INVALID_PARAMETER
;
1729 if (Size
.X
== ScreenBuffer
->MaxX
&& Size
.Y
== ScreenBuffer
->MaxY
)
1730 return STATUS_SUCCESS
;
1732 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Size
.X
* Size
.Y
* 2);
1734 return STATUS_NO_MEMORY
;
1736 DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer
->MaxX
, ScreenBuffer
->MaxY
, Size
.X
, Size
.Y
);
1737 OldBuffer
= ScreenBuffer
->Buffer
;
1739 for (CurrentY
= 0; CurrentY
< ScreenBuffer
->MaxY
&& CurrentY
< Size
.Y
; CurrentY
++)
1741 OldPtr
= ConioCoordToPointer(ScreenBuffer
, 0, CurrentY
);
1742 if (Size
.X
<= ScreenBuffer
->MaxX
)
1745 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, Size
.X
* 2);
1746 Offset
+= (Size
.X
* 2);
1751 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, ScreenBuffer
->MaxX
* 2);
1752 Offset
+= (ScreenBuffer
->MaxX
* 2);
1754 diff
= Size
.X
- ScreenBuffer
->MaxX
;
1755 /* zero new part of it */
1757 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
);
1759 for (i
= 0; i
< diff
; i
++)
1761 Buffer
[Offset
++] = ' ';
1762 Buffer
[Offset
++] = ScreenBuffer
->DefaultAttrib
;
1768 if (Size
.Y
> ScreenBuffer
->MaxY
)
1770 diff
= Size
.X
* (Size
.Y
- ScreenBuffer
->MaxY
);
1772 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
);
1774 for (i
= 0; i
< diff
; i
++)
1776 Buffer
[Offset
++] = ' ';
1777 Buffer
[Offset
++] = ScreenBuffer
->DefaultAttrib
;
1782 (void)InterlockedExchangePointer((PVOID
volatile *)&ScreenBuffer
->Buffer
, Buffer
);
1783 HeapFree(Win32CsrApiHeap
, 0, OldBuffer
);
1784 ScreenBuffer
->MaxX
= Size
.X
;
1785 ScreenBuffer
->MaxY
= Size
.Y
;
1786 ScreenBuffer
->VirtualY
= 0;
1788 /* Ensure cursor and window are within buffer */
1789 if (ScreenBuffer
->CurrentX
>= Size
.X
)
1790 ScreenBuffer
->CurrentX
= Size
.X
- 1;
1791 if (ScreenBuffer
->CurrentY
>= Size
.Y
)
1792 ScreenBuffer
->CurrentY
= Size
.Y
- 1;
1793 if (ScreenBuffer
->ShowX
> Size
.X
- Console
->Size
.X
)
1794 ScreenBuffer
->ShowX
= Size
.X
- Console
->Size
.X
;
1795 if (ScreenBuffer
->ShowY
> Size
.Y
- Console
->Size
.Y
)
1796 ScreenBuffer
->ShowY
= Size
.Y
- Console
->Size
.Y
;
1798 /* TODO: Should update scrollbar, but can't use anything that
1799 * calls SendMessage or it could cause deadlock */
1801 return STATUS_SUCCESS
;
1804 static VOID FASTCALL
1805 GuiApplyUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PConsoleInfo pConInfo
)
1808 PCSRSS_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
1810 BOOL SizeChanged
= FALSE
;
1812 EnterCriticalSection(&ActiveBuffer
->Header
.Lock
);
1814 /* apply text / background color */
1815 GuiData
->ScreenText
= pConInfo
->ScreenText
;
1816 GuiData
->ScreenBackground
= pConInfo
->ScreenBackground
;
1818 /* apply cursor size */
1819 ActiveBuffer
->CursorInfo
.dwSize
= min(max(pConInfo
->CursorSize
, 1), 100);
1821 windx
= LOWORD(pConInfo
->WindowSize
);
1822 windy
= HIWORD(pConInfo
->WindowSize
);
1824 if (windx
!= Console
->Size
.X
|| windy
!= Console
->Size
.Y
)
1827 Console
->Size
.X
= windx
;
1828 Console
->Size
.Y
= windy
;
1832 BufSize
.X
= LOWORD(pConInfo
->ScreenBuffer
);
1833 BufSize
.Y
= HIWORD(pConInfo
->ScreenBuffer
);
1834 if (BufSize
.X
!= ActiveBuffer
->MaxX
|| BufSize
.Y
!= ActiveBuffer
->MaxY
)
1836 if (NT_SUCCESS(GuiResizeBuffer(Console
, ActiveBuffer
, BufSize
)))
1842 GuiData
->WindowSizeLock
= TRUE
;
1843 GuiConsoleInitScrollbar(Console
, pConInfo
->hConsoleWindow
);
1844 GuiData
->WindowSizeLock
= FALSE
;
1847 LeaveCriticalSection(&ActiveBuffer
->Header
.Lock
);
1848 InvalidateRect(pConInfo
->hConsoleWindow
, NULL
, TRUE
);
1853 GuiConsoleHandleScroll(HWND hwnd
, UINT uMsg
, WPARAM wParam
)
1855 PCSRSS_CONSOLE Console
;
1856 PCSRSS_SCREEN_BUFFER Buff
;
1857 PGUI_CONSOLE_DATA GuiData
;
1860 int old_pos
, Maximum
;
1863 GuiConsoleGetDataPointers(hwnd
, &Console
, &GuiData
);
1864 if (Console
== NULL
|| GuiData
== NULL
)
1866 Buff
= Console
->ActiveBuffer
;
1868 if (uMsg
== WM_HSCROLL
)
1871 Maximum
= Buff
->MaxX
- Console
->Size
.X
;
1872 pShowXY
= &Buff
->ShowX
;
1877 Maximum
= Buff
->MaxY
- Console
->Size
.Y
;
1878 pShowXY
= &Buff
->ShowY
;
1881 /* set scrollbar sizes */
1882 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1883 sInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_PAGE
| SIF_TRACKPOS
;
1885 if (!GetScrollInfo(hwnd
, fnBar
, &sInfo
))
1890 old_pos
= sInfo
.nPos
;
1892 switch(LOWORD(wParam
))
1903 sInfo
.nPos
-= sInfo
.nPage
;
1907 sInfo
.nPos
+= sInfo
.nPage
;
1911 sInfo
.nPos
= sInfo
.nTrackPos
;
1915 sInfo
.nPos
= sInfo
.nMin
;
1919 sInfo
.nPos
= sInfo
.nMax
;
1926 sInfo
.nPos
= max(sInfo
.nPos
, 0);
1927 sInfo
.nPos
= min(sInfo
.nPos
, Maximum
);
1929 if (old_pos
!= sInfo
.nPos
)
1931 USHORT OldX
= Buff
->ShowX
;
1932 USHORT OldY
= Buff
->ShowY
;
1933 *pShowXY
= sInfo
.nPos
;
1935 ScrollWindowEx(hwnd
,
1936 (OldX
- Buff
->ShowX
) * GuiData
->CharWidth
,
1937 (OldY
- Buff
->ShowY
) * GuiData
->CharHeight
,
1944 sInfo
.fMask
= SIF_POS
;
1945 SetScrollInfo(hwnd
, fnBar
, &sInfo
, TRUE
);
1952 static LRESULT CALLBACK
1953 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1956 PGUI_CONSOLE_DATA GuiData
= NULL
;
1957 PCSRSS_CONSOLE Console
= NULL
;
1959 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1964 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
1967 GuiConsoleHandlePaint(hWnd
, (HDC
)wParam
);
1974 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
1977 GuiConsoleHandleTimer(hWnd
);
1980 GuiConsoleHandleClose(hWnd
);
1983 GuiConsoleHandleNcDestroy(hWnd
);
1985 case WM_LBUTTONDOWN
:
1986 GuiConsoleLeftMouseDown(hWnd
, lParam
);
1989 GuiConsoleLeftMouseUp(hWnd
, lParam
);
1991 case WM_RBUTTONDOWN
:
1992 GuiConsoleRightMouseDown(hWnd
);
1995 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
1998 Result
= GuiConsoleHandleSysMenuCommand(hWnd
, wParam
, lParam
, GuiData
);
2002 Result
= GuiConsoleHandleScroll(hWnd
, msg
, wParam
);
2004 case WM_GETMINMAXINFO
:
2005 GuiConsoleGetMinMaxInfo(hWnd
, (PMINMAXINFO
)lParam
);
2008 GuiConsoleResize(hWnd
, wParam
, lParam
);
2010 case PM_APPLY_CONSOLE_INFO
:
2011 GuiApplyUserSettings(Console
, GuiData
, (PConsoleInfo
)wParam
);
2014 GuiConsoleWriteUserSettings(Console
, GuiData
);
2018 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
2025 static LRESULT CALLBACK
2026 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2031 PWCHAR Buffer
, Title
;
2032 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
2039 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
2041 case PM_CREATE_CONSOLE
:
2042 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
2043 Console
->Title
.Length
+ sizeof(WCHAR
));
2046 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
2047 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
2054 NewWindow
= CreateWindowExW(WS_EX_CLIENTEDGE
,
2055 L
"ConsoleWindowClass",
2057 WS_OVERLAPPEDWINDOW
| WS_HSCROLL
| WS_VSCROLL
,
2064 (HINSTANCE
) GetModuleHandleW(NULL
),
2068 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
2070 if (NULL
!= NewWindow
)
2072 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
2073 ShowWindow(NewWindow
, SW_SHOW
);
2075 return (LRESULT
) NewWindow
;
2076 case PM_DESTROY_CONSOLE
:
2077 /* Window creation is done using a PostMessage(), so it's possible that the
2078 * window that we want to destroy doesn't exist yet. So first empty the message
2080 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
2082 TranslateMessage(&Msg
);
2083 DispatchMessageW(&Msg
);
2085 DestroyWindow(Console
->hWindow
);
2086 Console
->hWindow
= NULL
;
2087 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
2089 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
2090 if (0 == WindowCount
)
2093 DestroyWindow(hWnd
);
2094 PrivateCsrssManualGuiCheck(-1);
2099 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
2104 GuiConsoleGuiThread(PVOID Data
)
2107 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
2109 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
2111 WS_OVERLAPPEDWINDOW
,
2118 (HINSTANCE
) GetModuleHandleW(NULL
),
2120 if (NULL
== NotifyWnd
)
2122 PrivateCsrssManualGuiCheck(-1);
2123 SetEvent(*GraphicsStartupEvent
);
2127 SetEvent(*GraphicsStartupEvent
);
2129 while(GetMessageW(&msg
, NULL
, 0, 0))
2131 TranslateMessage(&msg
);
2132 DispatchMessageW(&msg
);
2138 static BOOL FASTCALL
2143 if (NULL
== NotifyWnd
)
2145 PrivateCsrssManualGuiCheck(+1);
2148 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2149 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
2150 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
2152 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
2155 wc
.hbrBackground
= NULL
;
2156 wc
.lpszMenuName
= NULL
;
2160 if (RegisterClassExW(&wc
) == 0)
2162 DPRINT1("Failed to register notify wndproc\n");
2166 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2167 wc
.lpszClassName
= L
"ConsoleWindowClass";
2168 wc
.lpfnWndProc
= GuiConsoleWndProc
;
2170 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
2171 wc
.hIcon
= LoadIconW(GetModuleHandleW(L
"win32csr"), MAKEINTRESOURCEW(1));
2172 wc
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
) IDC_ARROW
);
2173 wc
.hbrBackground
= CreateSolidBrush(RGB(0,0,0));
2174 wc
.lpszMenuName
= NULL
;
2177 wc
.hIconSm
= LoadImageW(GetModuleHandleW(L
"win32csr"), MAKEINTRESOURCEW(1), IMAGE_ICON
,
2178 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
2180 if (RegisterClassExW(&wc
) == 0)
2182 DPRINT1("Failed to register console wndproc\n");
2190 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
2192 Buffer
->DefaultAttrib
= DEFAULT_ATTRIB
;
2196 GuiChangeTitle(PCSRSS_CONSOLE Console
)
2198 PWCHAR Buffer
, Title
;
2200 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
2201 Console
->Title
.Length
+ sizeof(WCHAR
));
2204 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
2205 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
2213 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
) Title
);
2217 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
2224 GuiChangeIcon(PCSRSS_CONSOLE Console
, HICON hWindowIcon
)
2226 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)hWindowIcon
);
2227 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)hWindowIcon
);
2233 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
2235 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
) Console
);
2238 static CSRSS_CONSOLE_VTBL GuiVtbl
=
2240 GuiInitScreenBuffer
,
2245 GuiUpdateScreenInfo
,
2253 GuiInitConsole(PCSRSS_CONSOLE Console
)
2255 HANDLE GraphicsStartupEvent
;
2256 HANDLE ThreadHandle
;
2257 PGUI_CONSOLE_DATA GuiData
;
2259 if (! ConsInitialized
)
2261 ConsInitialized
= TRUE
;
2264 ConsInitialized
= FALSE
;
2265 return STATUS_UNSUCCESSFUL
;
2269 Console
->Vtbl
= &GuiVtbl
;
2270 if (NULL
== NotifyWnd
)
2272 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2273 if (NULL
== GraphicsStartupEvent
)
2275 return STATUS_UNSUCCESSFUL
;
2278 ThreadHandle
= CreateThread(NULL
,
2280 GuiConsoleGuiThread
,
2281 (PVOID
) &GraphicsStartupEvent
,
2284 if (NULL
== ThreadHandle
)
2286 NtClose(GraphicsStartupEvent
);
2287 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
2288 return STATUS_UNSUCCESSFUL
;
2290 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
2291 CloseHandle(ThreadHandle
);
2293 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
2294 CloseHandle(GraphicsStartupEvent
);
2296 if (NULL
== NotifyWnd
)
2298 DPRINT1("Win32Csr: Failed to create notification window.\n");
2299 return STATUS_UNSUCCESSFUL
;
2302 GuiData
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
2303 sizeof(GUI_CONSOLE_DATA
));
2306 DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
2307 return STATUS_UNSUCCESSFUL
;
2310 Console
->PrivateData
= (PVOID
) GuiData
;
2312 * we need to wait untill the GUI has been fully initialized
2313 * to retrieve custom settings i.e. WindowSize etc..
2314 * Ideally we could use SendNotifyMessage for this but its not
2318 GuiData
->hGuiInitEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2319 /* create console */
2320 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, 0, (LPARAM
) Console
);
2322 /* wait untill initialization has finished */
2323 WaitForSingleObject(GuiData
->hGuiInitEvent
, INFINITE
);
2324 DPRINT1("received event Console %p GuiData %p X %d Y %d\n", Console
, Console
->PrivateData
, Console
->Size
.X
, Console
->Size
.Y
);
2325 CloseHandle(GuiData
->hGuiInitEvent
);
2326 GuiData
->hGuiInitEvent
= NULL
;
2328 return STATUS_SUCCESS
;