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 ******************************************************************/
16 /* Not defined in any header file */
17 extern VOID STDCALL
PrivateCsrssManualGuiCheck(LONG Check
);
19 /* GLOBALS *******************************************************************/
21 typedef struct GUI_CONSOLE_DATA_TAG
29 CRITICAL_SECTION Lock
;
33 HMODULE ConsoleLibrary
;
37 WCHAR FontName
[LF_FACESIZE
];
44 DWORD NumberOfHistoryBuffers
;
45 DWORD HistoryBufferSize
;
47 DWORD ScreenBufferSize
;
50 COLORREF ScreenBackground
;
51 COLORREF PopupBackground
;
54 WCHAR szProcessName
[MAX_PATH
];
55 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
60 #define PM_CREATE_CONSOLE (WM_APP + 1)
61 #define PM_DESTROY_CONSOLE (WM_APP + 2)
63 #define CURSOR_BLINK_TIME 500
64 #define DEFAULT_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
66 static BOOL ConsInitialized
= FALSE
;
67 static HWND NotifyWnd
;
69 typedef struct _GUICONSOLE_MENUITEM
72 const struct _GUICONSOLE_MENUITEM
*SubMenu
;
74 } GUICONSOLE_MENUITEM
, *PGUICONSOLE_MENUITEM
;
76 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems
[] =
78 { IDS_MARK
, NULL
, ID_SYSTEM_EDIT_MARK
},
79 { IDS_COPY
, NULL
, ID_SYSTEM_EDIT_COPY
},
80 { IDS_PASTE
, NULL
, ID_SYSTEM_EDIT_PASTE
},
81 { IDS_SELECTALL
, NULL
, ID_SYSTEM_EDIT_SELECTALL
},
82 { IDS_SCROLL
, NULL
, ID_SYSTEM_EDIT_SCROLL
},
83 { IDS_FIND
, NULL
, ID_SYSTEM_EDIT_FIND
},
85 { 0, NULL
, 0 } /* End of list */
88 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems
[] =
90 { (UINT
)-1, NULL
, 0 }, /* Separator */
91 { IDS_EDIT
, GuiConsoleEditMenuItems
, 0 },
92 { IDS_DEFAULTS
, NULL
, ID_SYSTEM_DEFAULTS
},
93 { IDS_PROPERTIES
, NULL
, ID_SYSTEM_PROPERTIES
},
95 { 0, NULL
, 0 } /* End of list */
98 static const COLORREF s_Colors
[] =
118 /* FUNCTIONS *****************************************************************/
121 GuiConsoleAppendMenuItems(HMENU hMenu
,
122 const GUICONSOLE_MENUITEM
*Items
)
125 WCHAR szMenuString
[255];
128 for (i
= 0; Items
[i
].uID
!= 0; i
++)
130 if (Items
[i
].uID
!= (UINT
)-1)
132 if (LoadStringW(Win32CsrDllHandle
,
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
);
151 DPRINT1("DestroyMenu \n");
175 GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console
)
179 hMenu
= GetSystemMenu(Console
->hWindow
,
183 DPRINT1("adding menu\n");
184 GuiConsoleAppendMenuItems(hMenu
,
185 GuiConsoleMainMenuItems
);
189 DPRINT1("This should never happen, GetSystemMenu == NULL \n");
194 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
196 *Console
= (PCSRSS_CONSOLE
) GetWindowLongPtrW(hWnd
, GWL_USERDATA
);
197 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
201 GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId
, PHANDLE hProcHandle
, PHKEY hResult
, REGSAM samDesired
)
203 HANDLE hProcessToken
= NULL
;
208 UNICODE_STRING SidName
;
212 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
| READ_CONTROL
, FALSE
, ProcessId
);
215 DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
219 if (!OpenProcessToken(hProcess
, TOKEN_QUERY
, &hProcessToken
))
221 DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
222 CloseHandle(hProcess
);
226 if (!GetTokenInformation(hProcessToken
, TokenUser
, (PVOID
)Buffer
, sizeof(Buffer
), &Length
))
228 DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
229 CloseHandle(hProcess
);
230 CloseHandle(hProcessToken
);
234 TokUser
= ((PTOKEN_USER
)Buffer
)->User
.Sid
;
235 if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName
, TokUser
, TRUE
)))
237 DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
241 res
= RegOpenKeyExW(HKEY_USERS
, SidName
.Buffer
, 0, samDesired
, hResult
);
242 RtlFreeUnicodeString(&SidName
);
244 CloseHandle(hProcessToken
);
245 CloseHandle(hProcess
);
248 // *hProcHandle = hProcess;
250 // CloseHandle(hProcess);
252 if (res
!= ERROR_SUCCESS
)
259 GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData
, DWORD ProcessId
, PHKEY hSubKey
, REGSAM samDesired
, BOOL bCreate
)
261 WCHAR szProcessName
[MAX_PATH
];
262 WCHAR szBuffer
[MAX_PATH
];
263 UINT fLength
, wLength
;
264 DWORD dwBitmask
, dwLength
;
265 WCHAR CurDrive
[] = { 'A',':', 0 };
271 * console properties are stored under
274 * There are 3 ways to store console properties
276 * 1. use console title as subkey name
279 * 2. use application name as subkey name
281 * 3. use unexpanded path to console application.
282 * i.e. %SystemRoot%_system32_cmd.exe
285 DPRINT("GuiConsoleOpenUserSettings entered\n");
287 DPRINT1("ProcessId %d\n",ProcessId
);
289 if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId
, &hProcess
, &hKey
, samDesired
))
291 DPRINT1("GuiConsoleOpenUserRegistryPathPerProcessId failed\n");
295 hProcess
= OpenProcess( PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, ProcessId
);
298 /* FIXME we do not getting the process name so no menu will be loading, why ?*/
299 fLength
= GetProcessImageFileNameW(hProcess
, szProcessName
, sizeof(GuiData
->szProcessName
) / sizeof(WCHAR
));
300 CloseHandle(hProcess
);
302 DPRINT1("szProcessName3 : %S\n",szProcessName
);
306 DPRINT1("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(),hProcess
);
310 * try the process name as path
313 ptr
= wcsrchr(szProcessName
, L
'\\');
314 wcscpy(GuiData
->szProcessName
, ptr
);
316 swprintf(szBuffer
, L
"Console%s",ptr
);
317 DPRINT("#1 Path : %S\n", szBuffer
);
321 if (RegCreateKeyW(hKey
, szBuffer
, hSubKey
) == ERROR_SUCCESS
)
330 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
337 * try the "Shortcut to processname" as path
338 * FIXME: detect wheter the process was started as a shortcut
341 swprintf(szBuffer
, L
"Console\\Shortcut to %S", ptr
);
342 DPRINT("#2 Path : %S\n", szBuffer
);
343 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
345 swprintf(GuiData
->szProcessName
, L
"Shortcut to %S", ptr
);
351 * if the path contains \\Device\\HarddiskVolume1\... remove it
354 if (szProcessName
[0] == L
'\\')
356 dwBitmask
= GetLogicalDrives();
361 dwLength
= QueryDosDeviceW(CurDrive
, szBuffer
, MAX_PATH
);
364 if (!memcmp(szBuffer
, szProcessName
, (dwLength
-2)*sizeof(WCHAR
)))
366 wcscpy(szProcessName
, CurDrive
);
367 RtlMoveMemory(&szProcessName
[2], &szProcessName
[dwLength
-1], fLength
- dwLength
-1);
372 dwBitmask
= (dwBitmask
>> 1);
378 * last attempt: check whether the file is under %SystemRoot%
379 * and use path like Console\%SystemRoot%_dir_dir2_file.exe
382 wLength
= GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
385 if (!wcsncmp(szProcessName
, szBuffer
, wLength
))
387 /* replace slashes by underscores */
388 while((ptr
= wcschr(szProcessName
, L
'\\')))
391 swprintf(szBuffer
, L
"Console\\\%SystemRoot\%%S", &szProcessName
[wLength
]);
392 DPRINT("#3 Path : %S\n", szBuffer
);
393 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
395 swprintf(GuiData
->szProcessName
, L
"\%SystemRoot\%%S", &szProcessName
[wLength
]);
406 GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
)
409 PCSRSS_PROCESS_DATA ProcessData
;
411 if (Console
->ProcessList
.Flink
== &Console
->ProcessList
)
413 DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
416 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
417 if (!GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &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 (GuiData
->NumberOfHistoryBuffers
== 5)
433 RegDeleteKeyW(hKey
, L
"NumberOfHistoryBuffers");
437 RegSetValueExW(hKey
, L
"NumberOfHistoryBuffers", 0, REG_DWORD
, (const BYTE
*)&GuiData
->NumberOfHistoryBuffers
, sizeof(DWORD
));
440 if (GuiData
->HistoryBufferSize
== 50)
442 RegDeleteKeyW(hKey
, L
"HistoryBufferSize");
446 RegSetValueExW(hKey
, L
"HistoryBufferSize", 0, REG_DWORD
, (const BYTE
*)&GuiData
->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 (GuiData
->HistoryNoDup
== FALSE
)
478 RegDeleteKeyW(hKey
, L
"HistoryNoDup");
482 RegSetValueExW(hKey
, L
"HistoryNoDup", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryNoDup
, sizeof(DWORD
));
485 if (GuiData
->ScreenText
== RGB(192, 192, 192))
488 * MS uses console attributes instead of real color
490 RegDeleteKeyW(hKey
, L
"ScreenText");
494 RegSetValueExW(hKey
, L
"ScreenText", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenText
, sizeof(COLORREF
));
497 if (GuiData
->ScreenBackground
== RGB(0, 0, 0))
499 RegDeleteKeyW(hKey
, L
"ScreenBackground");
503 RegSetValueExW(hKey
, L
"ScreenBackground", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenBackground
, sizeof(COLORREF
));
510 GuiConsoleReadUserSettings(HKEY hKey
, PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
512 DWORD dwNumSubKeys
= 0;
517 WCHAR szValueName
[MAX_PATH
];
518 WCHAR szValue
[MAX_PATH
];
521 if (RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
523 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
527 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
529 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
531 dwValue
= sizeof(Value
);
532 dwValueName
= MAX_PATH
;
534 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
536 if (dwType
== REG_SZ
)
539 * retry in case of string value
541 dwValue
= sizeof(szValue
);
542 dwValueName
= MAX_PATH
;
543 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
549 if (!wcscmp(szValueName
, L
"CursorSize"))
553 Buffer
->CursorInfo
.dwSize
= Value
;
555 else if (Value
== 0x64)
557 Buffer
->CursorInfo
.dwSize
= Value
;
560 else if (!wcscmp(szValueName
, L
"ScreenText"))
562 GuiData
->ScreenText
= Value
;
564 else if (!wcscmp(szValueName
, L
"ScreenBackground"))
566 GuiData
->ScreenBackground
= Value
;
568 else if (!wcscmp(szValueName
, L
"FaceName"))
570 wcscpy(GuiData
->FontName
, szValue
);
572 else if (!wcscmp(szValueName
, L
"FontSize"))
574 GuiData
->FontSize
= Value
;
576 else if (!wcscmp(szValueName
, L
"FontWeight"))
578 GuiData
->FontWeight
= Value
;
580 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
582 GuiData
->HistoryNoDup
= Value
;
584 else if (!wcscmp(szValueName
, L
"WindowSize"))
586 Console
->Size
.X
= LOWORD(Value
);
587 Console
->Size
.Y
= HIWORD(Value
);
589 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
593 Buffer
->MaxX
= LOWORD(Value
);
594 Buffer
->MaxY
= HIWORD(Value
);
597 else if (!wcscmp(szValueName
, L
"FullScreen"))
599 GuiData
->FullScreen
= Value
;
601 else if (!wcscmp(szValueName
, L
"QuickEdit"))
603 GuiData
->QuickEdit
= Value
;
605 else if (!wcscmp(szValueName
, L
"InsertMode"))
607 GuiData
->InsertMode
= Value
;
612 GuiConsoleUseDefaults(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
615 * init guidata with default properties
618 wcscpy(GuiData
->FontName
, L
"DejaVu Sans Mono");
619 GuiData
->FontSize
= 0x0008000C; // font is 8x12
620 GuiData
->FontWeight
= FW_NORMAL
;
621 GuiData
->HistoryNoDup
= FALSE
;
622 GuiData
->FullScreen
= FALSE
;
623 GuiData
->QuickEdit
= FALSE
;
624 GuiData
->InsertMode
= TRUE
;
625 GuiData
->HistoryBufferSize
= 50;
626 GuiData
->NumberOfHistoryBuffers
= 5;
627 GuiData
->ScreenText
= RGB(192, 192, 192);
628 GuiData
->ScreenBackground
= RGB(0, 0, 0);
629 GuiData
->PopupText
= RGB(128, 0, 128);
630 GuiData
->PopupBackground
= RGB(255, 255, 255);
631 GuiData
->WindowPosition
= UINT_MAX
;
632 GuiData
->ScreenBufferSize
= MAKELONG(80, 300); //FIXME
633 GuiData
->UseRasterFonts
= TRUE
;
634 memcpy(GuiData
->Colors
, s_Colors
, sizeof(s_Colors
));
636 Console
->Size
.X
= 80;
637 Console
->Size
.Y
= 25;
643 Buffer
->CursorInfo
.bVisible
= TRUE
;
644 Buffer
->CursorInfo
.dwSize
= 5;
651 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
654 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
655 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Console
->PrivateData
;
659 PCSRSS_PROCESS_DATA ProcessData
;
662 Console
->hWindow
= hWnd
;
666 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
670 GuiConsoleUseDefaults(Console
, GuiData
, Console
->ActiveBuffer
);
671 if (Console
->ProcessList
.Flink
!= &Console
->ProcessList
)
673 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
674 DPRINT1("PtrToUlong(ProcessData->ProcessId) == %d",PtrToUlong(ProcessData
->ProcessId
));
676 if (GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
, FALSE
))
678 GuiConsoleReadUserSettings(hKey
, Console
, GuiData
, Console
->ActiveBuffer
);
683 InitializeCriticalSection(&GuiData
->Lock
);
685 GuiData
->LineBuffer
= (PWCHAR
)HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
686 Console
->Size
.X
* sizeof(WCHAR
));
688 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->FontSize
),
689 0, //HIWORD(GuiData->FontSize),
697 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
698 NONANTIALIASED_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
700 if (NULL
== GuiData
->Font
)
702 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
703 DeleteCriticalSection(&GuiData
->Lock
);
704 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
710 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
711 DeleteObject(GuiData
->Font
);
712 DeleteCriticalSection(&GuiData
->Lock
);
713 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
716 OldFont
= SelectObject(Dc
, GuiData
->Font
);
719 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
721 DeleteObject(GuiData
->Font
);
722 DeleteCriticalSection(&GuiData
->Lock
);
723 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
726 if (! GetTextMetricsW(Dc
, &Metrics
))
728 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
729 SelectObject(Dc
, OldFont
);
731 DeleteObject(GuiData
->Font
);
732 DeleteCriticalSection(&GuiData
->Lock
);
733 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
736 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
737 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
738 SelectObject(Dc
, OldFont
);
741 GuiData
->CursorBlinkOn
= TRUE
;
742 GuiData
->ForceCursorOff
= FALSE
;
744 GuiData
->Selection
.left
= -1;
745 DPRINT("Console %p GuiData %p\n", Console
, GuiData
);
746 Console
->PrivateData
= GuiData
;
747 SetWindowLongPtrW(hWnd
, GWL_USERDATA
, (DWORD_PTR
) Console
);
749 GetWindowRect(hWnd
, &Rect
);
750 Rect
.right
= Rect
.left
+ Console
->Size
.X
* GuiData
->CharWidth
+
751 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
752 Rect
.bottom
= Rect
.top
+ Console
->Size
.Y
* GuiData
->CharHeight
+
753 2 * GetSystemMetrics(SM_CYFIXEDFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
754 MoveWindow(hWnd
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
755 Rect
.bottom
- Rect
.top
, FALSE
);
757 SetTimer(hWnd
, 1, CURSOR_BLINK_TIME
, NULL
);
758 GuiConsoleCreateSysMenu(Console
);
759 SetEvent(GuiData
->hGuiInitEvent
);
761 return (BOOL
) DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
) Create
);
764 static COLORREF FASTCALL
765 GuiConsoleRGBFromAttribute(BYTE Attribute
)
767 int Red
= (Attribute
& 0x04 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
768 int Green
= (Attribute
& 0x02 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
769 int Blue
= (Attribute
& 0x01 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
771 return RGB(Red
, Green
, Blue
);
775 GuiConsoleSetTextColors(HDC Dc
, BYTE Attribute
, PCSRSS_SCREEN_BUFFER Buff
, COLORREF TextColor
, COLORREF BkColor
)
777 if (Attribute
!= Buff
->DefaultAttrib
)
779 SetTextColor(Dc
, GuiConsoleRGBFromAttribute(Attribute
& 0x0f));
780 SetBkColor(Dc
, GuiConsoleRGBFromAttribute((Attribute
& 0xf0) >> 4));
784 SetTextColor(Dc
, TextColor
);
785 SetBkColor(Dc
, BkColor
);
790 GuiConsoleGetLogicalCursorPos(PCSRSS_SCREEN_BUFFER Buff
, ULONG
*CursorX
, ULONG
*CursorY
)
792 *CursorX
= Buff
->CurrentX
;
793 if (Buff
->CurrentY
< Buff
->ShowY
)
795 *CursorY
= Buff
->MaxY
- Buff
->ShowY
+ Buff
->CurrentY
;
799 *CursorY
= Buff
->CurrentY
- Buff
->ShowY
;
805 GuiConsoleUpdateSelection(HWND hWnd
, PRECT rc
, PGUI_CONSOLE_DATA GuiData
)
807 RECT oldRect
= GuiData
->Selection
;
811 RECT changeRect
= *rc
;
813 GuiData
->Selection
= *rc
;
815 changeRect
.left
*= GuiData
->CharWidth
;
816 changeRect
.top
*= GuiData
->CharHeight
;
817 changeRect
.right
*= GuiData
->CharWidth
;
818 changeRect
.bottom
*= GuiData
->CharHeight
;
820 if(rc
->left
!= oldRect
.left
||
821 rc
->top
!= oldRect
.top
||
822 rc
->right
!= oldRect
.right
||
823 rc
->bottom
!= oldRect
.bottom
)
825 if(oldRect
.left
!= -1)
829 oldRect
.left
*= GuiData
->CharWidth
;
830 oldRect
.top
*= GuiData
->CharHeight
;
831 oldRect
.right
*= GuiData
->CharWidth
;
832 oldRect
.bottom
*= GuiData
->CharHeight
;
834 /* calculate the region that needs to be updated */
835 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
837 if((rgn2
= CreateRectRgnIndirect(&changeRect
)))
839 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
841 InvalidateRgn(hWnd
, rgn1
, FALSE
);
851 InvalidateRect(hWnd
, &changeRect
, FALSE
);
855 else if(oldRect
.left
!= -1)
857 /* clear the selection */
858 GuiData
->Selection
.left
= -1;
859 oldRect
.left
*= GuiData
->CharWidth
;
860 oldRect
.top
*= GuiData
->CharHeight
;
861 oldRect
.right
*= GuiData
->CharWidth
;
862 oldRect
.bottom
*= GuiData
->CharHeight
;
863 InvalidateRect(hWnd
, &oldRect
, FALSE
);
869 GuiConsolePaint(PCSRSS_CONSOLE Console
,
870 PGUI_CONSOLE_DATA GuiData
,
874 PCSRSS_SCREEN_BUFFER Buff
;
875 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
876 ULONG Line
, Char
, Start
;
879 BYTE LastAttribute
, Attribute
;
880 ULONG CursorX
, CursorY
, CursorHeight
;
881 HBRUSH CursorBrush
, OldBrush
, BackgroundBrush
;
884 Buff
= Console
->ActiveBuffer
;
886 TopLine
= rc
->top
/ GuiData
->CharHeight
;
887 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1;
888 LeftChar
= rc
->left
/ GuiData
->CharWidth
;
889 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1;
890 LastAttribute
= Buff
->Buffer
[(TopLine
* Buff
->MaxX
+ LeftChar
) * 2 + 1];
892 GuiConsoleSetTextColors(hDC
,
896 GuiData
->ScreenBackground
);
898 EnterCriticalSection(&Buff
->Header
.Lock
);
900 OldFont
= SelectObject(hDC
,
903 BackgroundBrush
= CreateSolidBrush(GuiData
->ScreenBackground
);
904 FillRect(hDC
, rc
, BackgroundBrush
);
905 DeleteObject(BackgroundBrush
);
907 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
909 if (Line
+ Buff
->ShowY
< Buff
->MaxY
)
911 From
= Buff
->Buffer
+ ((Line
+ Buff
->ShowY
) * Buff
->MaxX
+ LeftChar
) * 2;
915 From
= Buff
->Buffer
+
916 ((Line
- (Buff
->MaxY
- Buff
->ShowY
)) * Buff
->MaxX
+ LeftChar
) * 2;
919 To
= GuiData
->LineBuffer
;
921 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
923 if (*(From
+ 1) != LastAttribute
)
926 Start
* GuiData
->CharWidth
,
927 Line
* GuiData
->CharHeight
,
931 To
= GuiData
->LineBuffer
;
932 Attribute
= *(From
+ 1);
933 if (Attribute
!= LastAttribute
)
935 GuiConsoleSetTextColors(hDC
,
939 GuiData
->ScreenBackground
);
940 LastAttribute
= Attribute
;
944 MultiByteToWideChar(Console
->OutputCodePage
,
955 Start
* GuiData
->CharWidth
,
956 Line
* GuiData
->CharHeight
,
958 RightChar
- Start
+ 1);
961 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
&&
962 !GuiData
->ForceCursorOff
)
964 GuiConsoleGetLogicalCursorPos(Buff
,
967 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
968 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
970 CursorHeight
= (GuiData
->CharHeight
* Buff
->CursorInfo
.dwSize
) / 100;
971 if (CursorHeight
< 1)
975 From
= Buff
->Buffer
+ (Buff
->CurrentY
* Buff
->MaxX
+ Buff
->CurrentX
) * 2 + 1;
977 if (*From
!= DEFAULT_ATTRIB
)
979 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(*From
));
983 CursorBrush
= CreateSolidBrush(GuiData
->ScreenText
);
986 OldBrush
= SelectObject(hDC
,
989 CursorX
* GuiData
->CharWidth
,
990 CursorY
* GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
996 DeleteObject(CursorBrush
);
1000 LeaveCriticalSection(&Buff
->Header
.Lock
);
1006 static VOID FASTCALL
1007 GuiConsoleHandlePaint(HWND hWnd
, HDC hDCPaint
)
1011 PCSRSS_CONSOLE Console
;
1012 PGUI_CONSOLE_DATA GuiData
;
1014 hDC
= BeginPaint(hWnd
, &ps
);
1016 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
1017 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
1019 GuiConsoleGetDataPointers(hWnd
,
1022 if (Console
!= NULL
&& GuiData
!= NULL
&&
1023 Console
->ActiveBuffer
!= NULL
)
1025 if (Console
->ActiveBuffer
->Buffer
!= NULL
)
1027 EnterCriticalSection(&GuiData
->Lock
);
1029 GuiConsolePaint(Console
,
1034 if (GuiData
->Selection
.left
!= -1)
1036 RECT rc
= GuiData
->Selection
;
1038 rc
.left
*= GuiData
->CharWidth
;
1039 rc
.top
*= GuiData
->CharHeight
;
1040 rc
.right
*= GuiData
->CharWidth
;
1041 rc
.bottom
*= GuiData
->CharHeight
;
1043 /* invert the selection */
1044 if (IntersectRect(&rc
,
1057 LeaveCriticalSection(&GuiData
->Lock
);
1061 EndPaint(hWnd
, &ps
);
1065 static VOID FASTCALL
1066 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1068 PCSRSS_CONSOLE Console
;
1069 PGUI_CONSOLE_DATA GuiData
;
1072 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1073 Message
.hwnd
= hWnd
;
1074 Message
.message
= msg
;
1075 Message
.wParam
= wParam
;
1076 Message
.lParam
= lParam
;
1078 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
1080 /* clear the selection */
1081 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
1084 ConioProcessKey(&Message
, Console
, FALSE
);
1087 static VOID FASTCALL
1088 GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, RECT
*Region
)
1092 RegionRect
.left
= Region
->left
* GuiData
->CharWidth
;
1093 RegionRect
.top
= Region
->top
* GuiData
->CharHeight
;
1094 RegionRect
.right
= (Region
->right
+ 1) * GuiData
->CharWidth
;
1095 RegionRect
.bottom
= (Region
->bottom
+ 1) * GuiData
->CharHeight
;
1097 InvalidateRect(Wnd
, &RegionRect
, FALSE
);
1101 GuiDrawRegion(PCSRSS_CONSOLE Console
, RECT
*Region
)
1103 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1105 if (NULL
!= Console
->hWindow
&& NULL
!= GuiData
)
1107 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
1111 static VOID FASTCALL
1112 GuiInvalidateCell(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, UINT x
, UINT y
)
1119 CellRect
.bottom
= y
;
1121 GuiIntDrawRegion(GuiData
, Wnd
, &CellRect
);
1125 GuiWriteStream(PCSRSS_CONSOLE Console
, RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
1126 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
1128 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1129 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1130 LONG CursorEndX
, CursorEndY
;
1133 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
1138 if (0 != ScrolledLines
)
1140 ScrollRect
.left
= 0;
1142 ScrollRect
.right
= Console
->Size
.X
* GuiData
->CharWidth
;
1143 ScrollRect
.bottom
= Region
->top
* GuiData
->CharHeight
;
1145 if (GuiData
->Selection
.left
!= -1)
1147 /* scroll the selection */
1148 if (GuiData
->Selection
.top
> ScrolledLines
)
1150 GuiData
->Selection
.top
-= ScrolledLines
;
1151 GuiData
->Selection
.bottom
-= ScrolledLines
;
1153 else if (GuiData
->Selection
.bottom
< ScrolledLines
)
1155 GuiData
->Selection
.left
= -1;
1159 GuiData
->Selection
.top
= 0;
1160 GuiData
->Selection
.bottom
-= ScrolledLines
;
1164 ScrollWindowEx(Console
->hWindow
,
1166 -(ScrolledLines
* GuiData
->CharHeight
),
1174 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
1176 if (CursorStartX
< Region
->left
|| Region
->right
< CursorStartX
1177 || CursorStartY
< Region
->top
|| Region
->bottom
< CursorStartY
)
1179 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorStartX
, CursorStartY
);
1182 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
1183 &CursorEndX
, &CursorEndY
);
1184 if ((CursorEndX
< Region
->left
|| Region
->right
< CursorEndX
1185 || CursorEndY
< Region
->top
|| Region
->bottom
< CursorEndY
)
1186 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
1188 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorEndX
, CursorEndY
);
1193 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1197 if (Console
->ActiveBuffer
== Buff
)
1199 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
1200 &UpdateRect
.left
, &UpdateRect
.top
);
1201 UpdateRect
.right
= UpdateRect
.left
;
1202 UpdateRect
.bottom
= UpdateRect
.top
;
1203 ConioDrawRegion(Console
, &UpdateRect
);
1210 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
1214 if (Console
->ActiveBuffer
== Buff
)
1216 /* Redraw char at old position (removes cursor) */
1217 UpdateRect
.left
= OldCursorX
;
1218 UpdateRect
.top
= OldCursorY
;
1219 UpdateRect
.right
= OldCursorX
;
1220 UpdateRect
.bottom
= OldCursorY
;
1221 ConioDrawRegion(Console
, &UpdateRect
);
1222 /* Redraw char at new position (shows cursor) */
1223 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
1224 &(UpdateRect
.left
), &(UpdateRect
.top
));
1225 UpdateRect
.right
= UpdateRect
.left
;
1226 UpdateRect
.bottom
= UpdateRect
.top
;
1227 ConioDrawRegion(Console
, &UpdateRect
);
1233 static VOID FASTCALL
1234 GuiConsoleHandleTimer(HWND hWnd
)
1236 PCSRSS_CONSOLE Console
;
1237 PGUI_CONSOLE_DATA GuiData
;
1239 ULONG CursorX
, CursorY
;
1241 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1242 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
1244 GuiConsoleGetLogicalCursorPos(Console
->ActiveBuffer
, &CursorX
, &CursorY
);
1245 CursorRect
.left
= CursorX
;
1246 CursorRect
.top
= CursorY
;
1247 CursorRect
.right
= CursorX
;
1248 CursorRect
.bottom
= CursorY
;
1249 GuiDrawRegion(Console
, &CursorRect
);
1252 static VOID FASTCALL
1253 GuiConsoleHandleClose(HWND hWnd
)
1255 PCSRSS_CONSOLE Console
;
1256 PGUI_CONSOLE_DATA GuiData
;
1257 PLIST_ENTRY current_entry
;
1258 PCSRSS_PROCESS_DATA current
;
1260 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1262 EnterCriticalSection(&Console
->Header
.Lock
);
1264 current_entry
= Console
->ProcessList
.Flink
;
1265 while (current_entry
!= &Console
->ProcessList
)
1267 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1268 current_entry
= current_entry
->Flink
;
1270 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
1273 LeaveCriticalSection(&Console
->Header
.Lock
);
1276 static VOID FASTCALL
1277 GuiConsoleHandleNcDestroy(HWND hWnd
)
1279 PCSRSS_CONSOLE Console
;
1280 PGUI_CONSOLE_DATA GuiData
;
1284 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1286 Console
->PrivateData
= NULL
;
1287 DeleteCriticalSection(&GuiData
->Lock
);
1289 menu
= GetSystemMenu(hWnd
, TRUE
);
1292 DPRINT1("This should never happen, GetSystemMenu == NULL \n");
1295 if (GuiData
->ConsoleLibrary
)
1296 FreeLibrary(GuiData
->ConsoleLibrary
);
1298 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
1301 static VOID FASTCALL
1302 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
1304 PCSRSS_CONSOLE Console
;
1305 PGUI_CONSOLE_DATA GuiData
;
1309 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1310 if (Console
== NULL
|| GuiData
== NULL
) return;
1312 pt
= MAKEPOINTS(lParam
);
1314 rc
.left
= pt
.x
/ GuiData
->CharWidth
;
1315 rc
.top
= pt
.y
/ GuiData
->CharHeight
;
1316 rc
.right
= rc
.left
+ 1;
1317 rc
.bottom
= rc
.top
+ 1;
1319 GuiData
->SelectionStart
.x
= rc
.left
;
1320 GuiData
->SelectionStart
.y
= rc
.top
;
1324 GuiData
->MouseDown
= TRUE
;
1326 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1329 static VOID FASTCALL
1330 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
1332 PCSRSS_CONSOLE Console
;
1333 PGUI_CONSOLE_DATA GuiData
;
1337 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1338 if (Console
== NULL
|| GuiData
== NULL
) return;
1339 if (GuiData
->Selection
.left
== -1 || !GuiData
->MouseDown
) return;
1341 pt
= MAKEPOINTS(lParam
);
1343 rc
.left
= GuiData
->SelectionStart
.x
;
1344 rc
.top
= GuiData
->SelectionStart
.y
;
1345 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
1346 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
1348 /* exchange left/top with right/bottom if required */
1349 if(rc
.left
>= rc
.right
)
1353 rc
.left
= max(rc
.right
- 1, 0);
1356 if(rc
.top
>= rc
.bottom
)
1360 rc
.top
= max(rc
.bottom
- 1, 0);
1361 rc
.bottom
= tmp
+ 1;
1364 GuiData
->MouseDown
= FALSE
;
1366 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1371 static VOID FASTCALL
1372 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1374 PCSRSS_CONSOLE Console
;
1375 PGUI_CONSOLE_DATA GuiData
;
1379 if (!(wParam
& MK_LBUTTON
)) return;
1381 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1382 if (Console
== NULL
|| GuiData
== NULL
|| !GuiData
->MouseDown
) return;
1384 pt
= MAKEPOINTS(lParam
);
1386 rc
.left
= GuiData
->SelectionStart
.x
;
1387 rc
.top
= GuiData
->SelectionStart
.y
;
1388 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
1389 if (Console
->Size
.X
< rc
.right
)
1391 rc
.right
= Console
->Size
.X
;
1393 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
1394 if (Console
->Size
.Y
< rc
.bottom
)
1396 rc
.bottom
= Console
->Size
.Y
;
1399 /* exchange left/top with right/bottom if required */
1400 if(rc
.left
>= rc
.right
)
1404 rc
.left
= max(rc
.right
- 1, 0);
1407 if(rc
.top
>= rc
.bottom
)
1411 rc
.top
= max(rc
.bottom
- 1, 0);
1412 rc
.bottom
= tmp
+ 1;
1415 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1418 static VOID FASTCALL
1419 GuiConsoleRightMouseDown(HWND hWnd
)
1421 PCSRSS_CONSOLE Console
;
1422 PGUI_CONSOLE_DATA GuiData
;
1424 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1425 if (Console
== NULL
|| GuiData
== NULL
) return;
1427 if (GuiData
->Selection
.left
== -1)
1429 /* FIXME - paste text from clipboard */
1433 /* FIXME - copy selection to clipboard */
1435 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
1442 GuiConsoleShowConsoleProperties(HWND hWnd
, BOOL Defaults
, PGUI_CONSOLE_DATA GuiData
)
1444 PCSRSS_CONSOLE Console
;
1445 APPLET_PROC CPLFunc
;
1446 TCHAR szBuffer
[MAX_PATH
];
1447 ConsoleInfo SharedInfo
;
1449 DPRINT("GuiConsoleShowConsoleProperties entered\n");
1451 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1453 if (GuiData
== NULL
)
1455 DPRINT("GuiConsoleGetDataPointers failed\n");
1459 if (GuiData
->ConsoleLibrary
== NULL
)
1461 GetWindowsDirectory(szBuffer
,MAX_PATH
);
1462 _tcscat(szBuffer
, _T("\\system32\\console.dll"));
1463 GuiData
->ConsoleLibrary
= LoadLibrary(szBuffer
);
1465 if (GuiData
->ConsoleLibrary
== NULL
)
1467 DPRINT1("failed to load console.dll");
1472 CPLFunc
= (APPLET_PROC
) GetProcAddress(GuiData
->ConsoleLibrary
, _T("CPlApplet"));
1475 DPRINT("Error: Console.dll misses CPlApplet export\n");
1480 SharedInfo
.InsertMode
= GuiData
->InsertMode
;
1481 SharedInfo
.HistoryBufferSize
= GuiData
->HistoryBufferSize
;
1482 SharedInfo
.NumberOfHistoryBuffers
= GuiData
->NumberOfHistoryBuffers
;
1483 SharedInfo
.ScreenText
= GuiData
->ScreenText
;
1484 SharedInfo
.ScreenBackground
= GuiData
->ScreenBackground
;
1485 SharedInfo
.PopupText
= GuiData
->PopupText
;
1486 SharedInfo
.PopupBackground
= GuiData
->PopupBackground
;
1487 SharedInfo
.WindowSize
= (DWORD
)MAKELONG(Console
->Size
.X
, Console
->Size
.Y
);
1488 SharedInfo
.WindowPosition
= GuiData
->WindowPosition
;
1489 SharedInfo
.ScreenBuffer
= GuiData
->ScreenBufferSize
;
1490 SharedInfo
.UseRasterFonts
= GuiData
->UseRasterFonts
;
1491 SharedInfo
.FontSize
= (DWORD
)GuiData
->FontSize
;
1492 SharedInfo
.FontWeight
= GuiData
->FontWeight
;
1493 SharedInfo
.CursorSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1494 SharedInfo
.HistoryNoDup
= GuiData
->HistoryNoDup
;
1495 SharedInfo
.FullScreen
= GuiData
->FullScreen
;
1496 SharedInfo
.QuickEdit
= GuiData
->QuickEdit
;
1497 memcpy(&SharedInfo
.Colors
[0], GuiData
->Colors
, sizeof(s_Colors
));
1499 if (!CPLFunc(hWnd
, CPL_INIT
, 0, 0))
1501 DPRINT("Error: failed to initialize console.dll\n");
1505 if (CPLFunc(hWnd
, CPL_GETCOUNT
, 0, 0) != 1)
1507 DPRINT("Error: console.dll returned unexpected CPL count\n");
1511 CPLFunc(hWnd
, CPL_DBLCLK
, (LPARAM
)&SharedInfo
, Defaults
);
1513 static LRESULT FASTCALL
1514 GuiConsoleHandleSysMenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
, PGUI_CONSOLE_DATA GuiData
)
1520 case ID_SYSTEM_EDIT_MARK
:
1521 case ID_SYSTEM_EDIT_COPY
:
1522 case ID_SYSTEM_EDIT_PASTE
:
1523 case ID_SYSTEM_EDIT_SELECTALL
:
1524 case ID_SYSTEM_EDIT_SCROLL
:
1525 case ID_SYSTEM_EDIT_FIND
:
1528 case ID_SYSTEM_DEFAULTS
:
1529 GuiConsoleShowConsoleProperties(hWnd
, TRUE
, GuiData
);
1532 case ID_SYSTEM_PROPERTIES
:
1533 GuiConsoleShowConsoleProperties(hWnd
, FALSE
, GuiData
);
1537 Ret
= DefWindowProcW(hWnd
, WM_SYSCOMMAND
, wParam
, lParam
);
1543 static VOID FASTCALL
1544 GuiConsoleResize(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1546 PCSRSS_CONSOLE Console
;
1547 PGUI_CONSOLE_DATA GuiData
;
1549 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1550 if (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
)
1552 DPRINT1("GuiConsoleResize X %d Y %d\n", LOWORD(lParam
), HIWORD(lParam
));
1557 GuiConsoleCreateScrollBar(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, HWND NewWindow
)
1564 hMenu
= CreatePopupMenu();
1567 DPRINT("CreatePopupMenu failed\n");
1571 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1572 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1573 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1574 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1575 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1576 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1577 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1578 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1579 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1580 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1582 hVScrollBar
= CreateWindowExW(0L,
1585 WS_CHILD
| WS_VSCROLL
,
1592 GetModuleHandleW(NULL
),
1598 /* set scrollbar sizes */
1599 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1600 sInfo
.fMask
= SIF_RANGE
| SIF_POS
;
1602 sInfo
.nMax
= Console
->ActiveBuffer
->MaxY
;
1604 SetScrollInfo(hVScrollBar
, SB_CTL
, &sInfo
, TRUE
);
1605 ShowScrollBar(NewWindow
, SB_CTL
, TRUE
);
1606 GuiData
->hVScrollBar
= hVScrollBar
;
1609 if (Console
->ActiveBuffer
->MaxX
> Console
->Size
.X
)
1611 hHScrollBar
= CreateWindowExW(0L,
1614 WS_CHILD
| WS_HSCROLL
,
1621 GetModuleHandleW(NULL
),
1625 sInfo
.nMax
= Console
->ActiveBuffer
->MaxX
;
1626 SetScrollInfo(hHScrollBar
, SB_CTL
, &sInfo
, TRUE
);
1627 GuiData
->hHScrollBar
= hHScrollBar
;
1632 static VOID FASTCALL
1633 GuiApplyUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PConsoleInfo pConInfo
)
1638 /* apply text / background color */
1639 GuiData
->ScreenText
= pConInfo
->ScreenText
;
1640 GuiData
->ScreenBackground
= pConInfo
->ScreenBackground
;
1642 /* apply cursor size */
1643 Console
->ActiveBuffer
->CursorInfo
.dwSize
= max(min(pConInfo
->CursorSize
, 1), 100);
1645 windx
= LOWORD(pConInfo
->ScreenBuffer
);
1646 windy
= HIWORD(pConInfo
->ScreenBuffer
);
1648 if (windx
!= Console
->ActiveBuffer
->MaxX
|| windy
!= Console
->ActiveBuffer
->MaxY
)
1652 // resize screen buffer
1655 // Console->ActiveBuffer->MaxX = windx;
1656 // Console->ActiveBuffer->MaxY = windy;
1659 windx
= LOWORD(pConInfo
->WindowSize
);
1660 windy
= HIWORD(pConInfo
->WindowSize
);
1662 if (windx
!= Console
->Size
.X
|| windy
!= Console
->Size
.Y
)
1665 Console
->Size
.X
= windx
;
1666 Console
->Size
.Y
= windy
;
1668 GetWindowRect(pConInfo
->hConsoleWindow
, &rect
);
1670 rect
.right
= rect
.left
+ Console
->Size
.X
* GuiData
->CharWidth
+ 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
1671 rect
.bottom
= rect
.top
+ Console
->Size
.Y
* GuiData
->CharHeight
+ 2 * GetSystemMetrics(SM_CYFIXEDFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
1673 MoveWindow(pConInfo
->hConsoleWindow
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, FALSE
);
1675 if (Console
->Size
.X
< Console
->ActiveBuffer
->MaxX
)
1677 /* show scrollbar when window becomes smaller than active screen buffer */
1678 //ShowScrollBar(GuiData->hHScrollBar, SB_CTL, TRUE);
1682 /* hide scrollbar */
1683 //ShowScrollBar(GuiData->hHScrollBar, SB_CTL, FALSE);
1686 /* repaint window */
1687 InvalidateRect(pConInfo
->hConsoleWindow
, NULL
, TRUE
);
1690 static LRESULT CALLBACK
1691 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1694 PGUI_CONSOLE_DATA GuiData
= NULL
;
1695 PCSRSS_CONSOLE Console
= NULL
;
1697 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1702 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
1705 GuiConsoleHandlePaint(hWnd
, (HDC
)wParam
);
1712 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
1715 GuiConsoleHandleTimer(hWnd
);
1718 GuiConsoleHandleClose(hWnd
);
1721 GuiConsoleHandleNcDestroy(hWnd
);
1723 case WM_LBUTTONDOWN
:
1724 GuiConsoleLeftMouseDown(hWnd
, lParam
);
1727 GuiConsoleLeftMouseUp(hWnd
, lParam
);
1729 case WM_RBUTTONDOWN
:
1730 GuiConsoleRightMouseDown(hWnd
);
1733 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
1736 Result
= GuiConsoleHandleSysMenuCommand(hWnd
, wParam
, lParam
, GuiData
);
1739 GuiConsoleResize(hWnd
, wParam
, lParam
);
1741 case PM_APPLY_CONSOLE_INFO
:
1742 GuiApplyUserSettings(Console
, GuiData
, (PConsoleInfo
)wParam
);
1745 GuiConsoleWriteUserSettings(Console
, GuiData
);
1749 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1756 static LRESULT CALLBACK
1757 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1762 PWCHAR Buffer
, Title
;
1763 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
1770 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
1772 case PM_CREATE_CONSOLE
:
1773 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
1774 Console
->Title
.Length
+ sizeof(WCHAR
));
1777 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
1778 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
1785 NewWindow
= CreateWindowW(L
"ConsoleWindowClass",
1787 WS_OVERLAPPED
| WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
, //WS_OVERLAPPEDWINDOW
1794 (HINSTANCE
) GetModuleHandleW(NULL
),
1798 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1800 if (NULL
!= NewWindow
)
1802 // scrollbar support
1803 //GuiConsoleCreateScrollBar(Console, (PGUI_CONSOLE_DATA)Console->PrivateData, NewWindow);
1804 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
1805 ShowWindow(NewWindow
, SW_SHOW
);
1807 return (LRESULT
) NewWindow
;
1808 case PM_DESTROY_CONSOLE
:
1809 /* Window creation is done using a PostMessage(), so it's possible that the
1810 * window that we want to destroy doesn't exist yet. So first empty the message
1812 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
1814 TranslateMessage(&Msg
);
1815 DispatchMessageW(&Msg
);
1817 DestroyWindow(Console
->hWindow
);
1818 Console
->hWindow
= NULL
;
1819 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
1821 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
1822 if (0 == WindowCount
)
1825 DestroyWindow(hWnd
);
1826 PrivateCsrssManualGuiCheck(-1);
1831 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1835 static DWORD STDCALL
1836 GuiConsoleGuiThread(PVOID Data
)
1839 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
1841 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
1843 WS_OVERLAPPEDWINDOW
,
1850 (HINSTANCE
) GetModuleHandleW(NULL
),
1852 if (NULL
== NotifyWnd
)
1854 PrivateCsrssManualGuiCheck(-1);
1855 SetEvent(*GraphicsStartupEvent
);
1859 SetEvent(*GraphicsStartupEvent
);
1861 while(GetMessageW(&msg
, NULL
, 0, 0))
1863 TranslateMessage(&msg
);
1864 DispatchMessageW(&msg
);
1870 static BOOL FASTCALL
1875 if (NULL
== NotifyWnd
)
1877 PrivateCsrssManualGuiCheck(+1);
1880 wc
.cbSize
= sizeof(WNDCLASSEXW
);
1881 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
1882 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
1884 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
1887 wc
.hbrBackground
= NULL
;
1888 wc
.lpszMenuName
= NULL
;
1892 if (RegisterClassExW(&wc
) == 0)
1894 DPRINT1("Failed to register notify wndproc\n");
1898 wc
.cbSize
= sizeof(WNDCLASSEXW
);
1899 wc
.lpszClassName
= L
"ConsoleWindowClass";
1900 wc
.lpfnWndProc
= GuiConsoleWndProc
;
1902 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
1903 wc
.hIcon
= LoadIconW(Win32CsrDllHandle
, MAKEINTRESOURCEW(1));
1904 wc
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
) IDC_ARROW
);
1905 wc
.hbrBackground
= NULL
;
1906 wc
.lpszMenuName
= NULL
;
1909 wc
.hIconSm
= LoadImageW(Win32CsrDllHandle
, MAKEINTRESOURCEW(1), IMAGE_ICON
,
1910 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
1912 if (RegisterClassExW(&wc
) == 0)
1914 DPRINT1("Failed to register console wndproc\n");
1922 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
1924 Buffer
->DefaultAttrib
= DEFAULT_ATTRIB
;
1928 GuiChangeTitle(PCSRSS_CONSOLE Console
)
1930 PWCHAR Buffer
, Title
;
1932 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
1933 Console
->Title
.Length
+ sizeof(WCHAR
));
1936 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
1937 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
1945 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
) Title
);
1949 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1956 GuiChangeIcon(PCSRSS_CONSOLE Console
)
1958 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)Console
->hWindowIcon
);
1959 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)Console
->hWindowIcon
);
1965 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
1967 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
) Console
);
1970 static CSRSS_CONSOLE_VTBL GuiVtbl
=
1972 GuiInitScreenBuffer
,
1983 GuiInitConsole(PCSRSS_CONSOLE Console
)
1985 HANDLE GraphicsStartupEvent
;
1986 HANDLE ThreadHandle
;
1987 PGUI_CONSOLE_DATA GuiData
;
1989 if (! ConsInitialized
)
1991 ConsInitialized
= TRUE
;
1994 ConsInitialized
= FALSE
;
1995 return STATUS_UNSUCCESSFUL
;
1999 Console
->Vtbl
= &GuiVtbl
;
2000 if (NULL
== NotifyWnd
)
2002 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2003 if (NULL
== GraphicsStartupEvent
)
2005 return STATUS_UNSUCCESSFUL
;
2008 ThreadHandle
= CreateThread(NULL
,
2010 GuiConsoleGuiThread
,
2011 (PVOID
) &GraphicsStartupEvent
,
2014 if (NULL
== ThreadHandle
)
2016 NtClose(GraphicsStartupEvent
);
2017 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
2018 return STATUS_UNSUCCESSFUL
;
2020 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
2021 CloseHandle(ThreadHandle
);
2023 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
2024 CloseHandle(GraphicsStartupEvent
);
2026 if (NULL
== NotifyWnd
)
2028 DPRINT1("Win32Csr: Failed to create notification window.\n");
2029 return STATUS_UNSUCCESSFUL
;
2032 GuiData
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
2033 sizeof(GUI_CONSOLE_DATA
));
2036 DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
2037 return STATUS_UNSUCCESSFUL
;
2040 Console
->PrivateData
= (PVOID
) GuiData
;
2042 * we need to wait untill the GUI has been fully initialized
2043 * to retrieve custom settings i.e. WindowSize etc..
2044 * Ideally we could use SendNotifyMessage for this but its not
2048 GuiData
->hGuiInitEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2049 /* create console */
2050 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, 0, (LPARAM
) Console
);
2052 /* wait untill initialization has finished */
2053 WaitForSingleObject(GuiData
->hGuiInitEvent
, INFINITE
);
2054 DPRINT1("received event Console %p GuiData %p X %d Y %d\n", Console
, Console
->PrivateData
, Console
->Size
.X
, Console
->Size
.Y
);
2055 CloseHandle(GuiData
->hGuiInitEvent
);
2056 GuiData
->hGuiInitEvent
= NULL
;
2058 return STATUS_SUCCESS
;