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];
127 HINSTANCE hInst
= GetModuleHandleW(L
"win32csr");
131 if (Items
[i
].uID
!= (UINT
)-1)
133 if (LoadStringW(hInst
,
136 sizeof(szMenuString
) / sizeof(szMenuString
[0])) > 0)
138 if (Items
[i
].SubMenu
!= NULL
)
140 hSubMenu
= CreatePopupMenu();
141 if (hSubMenu
!= NULL
)
143 GuiConsoleAppendMenuItems(hSubMenu
,
146 if (!AppendMenuW(hMenu
,
147 MF_STRING
| MF_POPUP
,
151 DestroyMenu(hSubMenu
);
172 }while(!(Items
[i
].uID
== 0 && Items
[i
].SubMenu
== NULL
&& Items
[i
].wCmdID
== 0));
176 GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console
)
179 hMenu
= GetSystemMenu(Console
->hWindow
,
183 GuiConsoleAppendMenuItems(hMenu
,
184 GuiConsoleMainMenuItems
);
185 DrawMenuBar(Console
->hWindow
);
190 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
192 *Console
= (PCSRSS_CONSOLE
) GetWindowLongPtrW(hWnd
, GWL_USERDATA
);
193 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
197 GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId
, PHANDLE hProcHandle
, PHKEY hResult
, REGSAM samDesired
)
199 HANDLE hProcessToken
= NULL
;
204 UNICODE_STRING SidName
;
208 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
| READ_CONTROL
, FALSE
, ProcessId
);
211 DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
215 if (!OpenProcessToken(hProcess
, TOKEN_QUERY
, &hProcessToken
))
217 DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
218 CloseHandle(hProcess
);
222 if (!GetTokenInformation(hProcessToken
, TokenUser
, (PVOID
)Buffer
, sizeof(Buffer
), &Length
))
224 DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
225 CloseHandle(hProcess
);
226 CloseHandle(hProcessToken
);
230 TokUser
= ((PTOKEN_USER
)Buffer
)->User
.Sid
;
231 if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName
, TokUser
, TRUE
)))
233 DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
237 res
= RegOpenKeyExW(HKEY_USERS
, SidName
.Buffer
, 0, samDesired
, hResult
);
238 RtlFreeUnicodeString(&SidName
);
240 CloseHandle(hProcessToken
);
242 *hProcHandle
= hProcess
;
244 CloseHandle(hProcess
);
246 if (res
!= ERROR_SUCCESS
)
253 GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData
, DWORD ProcessId
, PHKEY hSubKey
, REGSAM samDesired
, BOOL bCreate
)
255 WCHAR szProcessName
[MAX_PATH
];
256 WCHAR szBuffer
[MAX_PATH
];
257 UINT fLength
, wLength
;
258 DWORD dwBitmask
, dwLength
;
259 WCHAR CurDrive
[] = { 'A',':', 0 };
265 * console properties are stored under
268 * There are 3 ways to store console properties
270 * 1. use console title as subkey name
273 * 2. use application name as subkey name
275 * 3. use unexpanded path to console application.
276 * i.e. %SystemRoot%_system32_cmd.exe
279 DPRINT("GuiConsoleOpenUserSettings entered\n");
281 if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId
, &hProcess
, &hKey
, samDesired
))
283 DPRINT("GuiConsoleOpenUserRegistryPathPerProcessId failed\n");
287 /* FIXME we do not getting the process name so no menu will be loading, why ?*/
288 fLength
= GetProcessImageFileNameW(hProcess
, szProcessName
, sizeof(GuiData
->szProcessName
) / sizeof(WCHAR
));
289 CloseHandle(hProcess
);
291 //DPRINT1("szProcessName3 : %S\n",szProcessName);
295 DPRINT("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(),hProcess
);
299 * try the process name as path
302 ptr
= wcsrchr(szProcessName
, L
'\\');
303 wcscpy(GuiData
->szProcessName
, ptr
);
305 swprintf(szBuffer
, L
"Console%s",ptr
);
306 DPRINT("#1 Path : %S\n", szBuffer
);
310 if (RegCreateKeyW(hKey
, szBuffer
, hSubKey
) == ERROR_SUCCESS
)
319 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
326 * try the "Shortcut to processname" as path
327 * FIXME: detect wheter the process was started as a shortcut
330 swprintf(szBuffer
, L
"Console\\Shortcut to %S", ptr
);
331 DPRINT("#2 Path : %S\n", szBuffer
);
332 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
334 swprintf(GuiData
->szProcessName
, L
"Shortcut to %S", ptr
);
340 * if the path contains \\Device\\HarddiskVolume1\... remove it
343 if (szProcessName
[0] == L
'\\')
345 dwBitmask
= GetLogicalDrives();
350 dwLength
= QueryDosDeviceW(CurDrive
, szBuffer
, MAX_PATH
);
353 if (!memcmp(szBuffer
, szProcessName
, (dwLength
-2)*sizeof(WCHAR
)))
355 wcscpy(szProcessName
, CurDrive
);
356 RtlMoveMemory(&szProcessName
[2], &szProcessName
[dwLength
-1], fLength
- dwLength
-1);
361 dwBitmask
= (dwBitmask
>> 1);
367 * last attempt: check whether the file is under %SystemRoot%
368 * and use path like Console\%SystemRoot%_dir_dir2_file.exe
371 wLength
= GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
374 if (!wcsncmp(szProcessName
, szBuffer
, wLength
))
376 /* replace slashes by underscores */
377 while((ptr
= wcschr(szProcessName
, L
'\\')))
380 swprintf(szBuffer
, L
"Console\\\%SystemRoot\%%S", &szProcessName
[wLength
]);
381 DPRINT("#3 Path : %S\n", szBuffer
);
382 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
384 swprintf(GuiData
->szProcessName
, L
"\%SystemRoot\%%S", &szProcessName
[wLength
]);
395 GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
)
398 PCSRSS_PROCESS_DATA ProcessData
;
400 if (Console
->ProcessList
.Flink
== &Console
->ProcessList
)
402 DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
405 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
406 if (!GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
| KEY_WRITE
, TRUE
))
411 if (Console
->ActiveBuffer
->CursorInfo
.dwSize
<= 1)
413 RegDeleteKeyW(hKey
, L
"CursorSize");
417 RegSetValueExW(hKey
, L
"CursorSize", 0, REG_DWORD
, (const BYTE
*)&Console
->ActiveBuffer
->CursorInfo
.dwSize
, sizeof(DWORD
));
420 if (GuiData
->NumberOfHistoryBuffers
== 5)
422 RegDeleteKeyW(hKey
, L
"NumberOfHistoryBuffers");
426 RegSetValueExW(hKey
, L
"NumberOfHistoryBuffers", 0, REG_DWORD
, (const BYTE
*)&GuiData
->NumberOfHistoryBuffers
, sizeof(DWORD
));
429 if (GuiData
->HistoryBufferSize
== 50)
431 RegDeleteKeyW(hKey
, L
"HistoryBufferSize");
435 RegSetValueExW(hKey
, L
"HistoryBufferSize", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryBufferSize
, sizeof(DWORD
));
438 if (GuiData
->FullScreen
== FALSE
)
440 RegDeleteKeyW(hKey
, L
"FullScreen");
444 RegSetValueExW(hKey
, L
"FullScreen", 0, REG_DWORD
, (const BYTE
*)&GuiData
->FullScreen
, sizeof(DWORD
));
447 if ( GuiData
->QuickEdit
== FALSE
)
449 RegDeleteKeyW(hKey
, L
"QuickEdit");
453 RegSetValueExW(hKey
, L
"QuickEdit", 0, REG_DWORD
, (const BYTE
*)&GuiData
->QuickEdit
, sizeof(DWORD
));
456 if (GuiData
->InsertMode
== TRUE
)
458 RegDeleteKeyW(hKey
, L
"InsertMode");
462 RegSetValueExW(hKey
, L
"InsertMode", 0, REG_DWORD
, (const BYTE
*)&GuiData
->InsertMode
, sizeof(DWORD
));
465 if (GuiData
->HistoryNoDup
== FALSE
)
467 RegDeleteKeyW(hKey
, L
"HistoryNoDup");
471 RegSetValueExW(hKey
, L
"HistoryNoDup", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryNoDup
, sizeof(DWORD
));
474 if (GuiData
->ScreenText
== RGB(192, 192, 192))
477 * MS uses console attributes instead of real color
479 RegDeleteKeyW(hKey
, L
"ScreenText");
483 RegSetValueExW(hKey
, L
"ScreenText", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenText
, sizeof(COLORREF
));
486 if (GuiData
->ScreenBackground
== RGB(0, 0, 0))
488 RegDeleteKeyW(hKey
, L
"ScreenBackground");
492 RegSetValueExW(hKey
, L
"ScreenBackground", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenBackground
, sizeof(COLORREF
));
499 GuiConsoleReadUserSettings(HKEY hKey
, PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
501 DWORD dwNumSubKeys
= 0;
506 WCHAR szValueName
[MAX_PATH
];
507 WCHAR szValue
[MAX_PATH
];
510 if (RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
512 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
516 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
518 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
520 dwValue
= sizeof(Value
);
521 dwValueName
= MAX_PATH
;
523 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
525 if (dwType
== REG_SZ
)
528 * retry in case of string value
530 dwValue
= sizeof(szValue
);
531 dwValueName
= MAX_PATH
;
532 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
538 if (!wcscmp(szValueName
, L
"CursorSize"))
542 Buffer
->CursorInfo
.dwSize
= Value
;
544 else if (Value
== 0x64)
546 Buffer
->CursorInfo
.dwSize
= Value
;
549 else if (!wcscmp(szValueName
, L
"ScreenText"))
551 GuiData
->ScreenText
= Value
;
553 else if (!wcscmp(szValueName
, L
"ScreenBackground"))
555 GuiData
->ScreenBackground
= Value
;
557 else if (!wcscmp(szValueName
, L
"FaceName"))
559 wcscpy(GuiData
->FontName
, szValue
);
561 else if (!wcscmp(szValueName
, L
"FontSize"))
563 GuiData
->FontSize
= Value
;
565 else if (!wcscmp(szValueName
, L
"FontWeight"))
567 GuiData
->FontWeight
= Value
;
569 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
571 GuiData
->HistoryNoDup
= Value
;
573 else if (!wcscmp(szValueName
, L
"WindowSize"))
575 Console
->Size
.X
= LOWORD(Value
);
576 Console
->Size
.Y
= HIWORD(Value
);
578 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
582 Buffer
->MaxX
= LOWORD(Value
);
583 Buffer
->MaxY
= HIWORD(Value
);
586 else if (!wcscmp(szValueName
, L
"FullScreen"))
588 GuiData
->FullScreen
= Value
;
590 else if (!wcscmp(szValueName
, L
"QuickEdit"))
592 GuiData
->QuickEdit
= Value
;
594 else if (!wcscmp(szValueName
, L
"InsertMode"))
596 GuiData
->InsertMode
= Value
;
601 GuiConsoleUseDefaults(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
604 * init guidata with default properties
607 wcscpy(GuiData
->FontName
, L
"DejaVu Sans Mono");
608 GuiData
->FontSize
= 0x0008000C; // font is 8x12
609 GuiData
->FontWeight
= FW_NORMAL
;
610 GuiData
->HistoryNoDup
= FALSE
;
611 GuiData
->FullScreen
= FALSE
;
612 GuiData
->QuickEdit
= FALSE
;
613 GuiData
->InsertMode
= TRUE
;
614 GuiData
->HistoryBufferSize
= 50;
615 GuiData
->NumberOfHistoryBuffers
= 5;
616 GuiData
->ScreenText
= RGB(192, 192, 192);
617 GuiData
->ScreenBackground
= RGB(0, 0, 0);
618 GuiData
->PopupText
= RGB(128, 0, 128);
619 GuiData
->PopupBackground
= RGB(255, 255, 255);
620 GuiData
->WindowPosition
= UINT_MAX
;
621 GuiData
->ScreenBufferSize
= MAKELONG(80, 300); //FIXME
622 GuiData
->UseRasterFonts
= TRUE
;
623 memcpy(GuiData
->Colors
, s_Colors
, sizeof(s_Colors
));
625 Console
->Size
.X
= 80;
626 Console
->Size
.Y
= 25;
632 Buffer
->CursorInfo
.bVisible
= TRUE
;
633 Buffer
->CursorInfo
.dwSize
= 5;
639 GuiConsoleInitScrollbar(PCSRSS_CONSOLE Console
, HWND hwnd
)
643 /* set scrollbar sizes */
644 sInfo
.cbSize
= sizeof(SCROLLINFO
);
645 sInfo
.fMask
= SIF_RANGE
| SIF_POS
;
647 sInfo
.nMax
= Console
->ActiveBuffer
->MaxY
;
649 SetScrollInfo(hwnd
, SB_HORZ
, &sInfo
, TRUE
);
650 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
652 if (Console
->ActiveBuffer
->MaxX
> Console
->Size
.X
)
654 sInfo
.cbSize
= sizeof(SCROLLINFO
);
655 sInfo
.fMask
= SIF_RANGE
| SIF_POS
;
658 sInfo
.nMax
= Console
->ActiveBuffer
->MaxX
;
659 SetScrollInfo(hwnd
, SB_HORZ
, &sInfo
, TRUE
);
663 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
668 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
671 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
672 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Console
->PrivateData
;
676 PCSRSS_PROCESS_DATA ProcessData
;
679 Console
->hWindow
= hWnd
;
683 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
687 GuiConsoleUseDefaults(Console
, GuiData
, Console
->ActiveBuffer
);
688 if (Console
->ProcessList
.Flink
!= &Console
->ProcessList
)
690 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
691 if (GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
, FALSE
))
693 GuiConsoleReadUserSettings(hKey
, Console
, GuiData
, Console
->ActiveBuffer
);
698 InitializeCriticalSection(&GuiData
->Lock
);
700 GuiData
->LineBuffer
= (PWCHAR
)HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
701 Console
->Size
.X
* sizeof(WCHAR
));
703 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->FontSize
),
704 0, //HIWORD(GuiData->FontSize),
712 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
713 NONANTIALIASED_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
715 if (NULL
== GuiData
->Font
)
717 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
718 DeleteCriticalSection(&GuiData
->Lock
);
719 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
725 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
726 DeleteObject(GuiData
->Font
);
727 DeleteCriticalSection(&GuiData
->Lock
);
728 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
731 OldFont
= SelectObject(Dc
, GuiData
->Font
);
734 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
736 DeleteObject(GuiData
->Font
);
737 DeleteCriticalSection(&GuiData
->Lock
);
738 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
741 if (! GetTextMetricsW(Dc
, &Metrics
))
743 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
744 SelectObject(Dc
, OldFont
);
746 DeleteObject(GuiData
->Font
);
747 DeleteCriticalSection(&GuiData
->Lock
);
748 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
751 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
752 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
753 SelectObject(Dc
, OldFont
);
756 GuiData
->CursorBlinkOn
= TRUE
;
757 GuiData
->ForceCursorOff
= FALSE
;
759 GuiData
->Selection
.left
= -1;
760 DPRINT("Console %p GuiData %p\n", Console
, GuiData
);
761 Console
->PrivateData
= GuiData
;
762 SetWindowLongPtrW(hWnd
, GWL_USERDATA
, (DWORD_PTR
) Console
);
764 GetWindowRect(hWnd
, &Rect
);
765 Rect
.right
= Rect
.left
+ Console
->Size
.X
* GuiData
->CharWidth
+
766 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
767 Rect
.bottom
= Rect
.top
+ Console
->Size
.Y
* GuiData
->CharHeight
+
768 2 * GetSystemMetrics(SM_CYFIXEDFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
769 MoveWindow(hWnd
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
770 Rect
.bottom
- Rect
.top
, FALSE
);
772 SetTimer(hWnd
, 1, CURSOR_BLINK_TIME
, NULL
);
773 GuiConsoleCreateSysMenu(Console
);
774 GuiConsoleInitScrollbar(Console
, hWnd
);
775 SetEvent(GuiData
->hGuiInitEvent
);
777 return (BOOL
) DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
) Create
);
780 static COLORREF FASTCALL
781 GuiConsoleRGBFromAttribute(BYTE Attribute
)
783 int Red
= (Attribute
& 0x04 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
784 int Green
= (Attribute
& 0x02 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
785 int Blue
= (Attribute
& 0x01 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
787 return RGB(Red
, Green
, Blue
);
791 GuiConsoleSetTextColors(HDC Dc
, BYTE Attribute
, PCSRSS_SCREEN_BUFFER Buff
, COLORREF TextColor
, COLORREF BkColor
)
793 if (Attribute
!= Buff
->DefaultAttrib
)
795 SetTextColor(Dc
, GuiConsoleRGBFromAttribute(Attribute
& 0x0f));
796 SetBkColor(Dc
, GuiConsoleRGBFromAttribute((Attribute
& 0xf0) >> 4));
800 SetTextColor(Dc
, TextColor
);
801 SetBkColor(Dc
, BkColor
);
806 GuiConsoleGetLogicalCursorPos(PCSRSS_SCREEN_BUFFER Buff
, ULONG
*CursorX
, ULONG
*CursorY
)
808 *CursorX
= Buff
->CurrentX
;
809 if (Buff
->CurrentY
< Buff
->ShowY
)
811 *CursorY
= Buff
->MaxY
- Buff
->ShowY
+ Buff
->CurrentY
;
815 *CursorY
= Buff
->CurrentY
- Buff
->ShowY
;
821 GuiConsoleUpdateSelection(HWND hWnd
, PRECT rc
, PGUI_CONSOLE_DATA GuiData
)
823 RECT oldRect
= GuiData
->Selection
;
827 RECT changeRect
= *rc
;
829 GuiData
->Selection
= *rc
;
831 changeRect
.left
*= GuiData
->CharWidth
;
832 changeRect
.top
*= GuiData
->CharHeight
;
833 changeRect
.right
*= GuiData
->CharWidth
;
834 changeRect
.bottom
*= GuiData
->CharHeight
;
836 if(rc
->left
!= oldRect
.left
||
837 rc
->top
!= oldRect
.top
||
838 rc
->right
!= oldRect
.right
||
839 rc
->bottom
!= oldRect
.bottom
)
841 if(oldRect
.left
!= -1)
845 oldRect
.left
*= GuiData
->CharWidth
;
846 oldRect
.top
*= GuiData
->CharHeight
;
847 oldRect
.right
*= GuiData
->CharWidth
;
848 oldRect
.bottom
*= GuiData
->CharHeight
;
850 /* calculate the region that needs to be updated */
851 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
853 if((rgn2
= CreateRectRgnIndirect(&changeRect
)))
855 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
857 InvalidateRgn(hWnd
, rgn1
, FALSE
);
867 InvalidateRect(hWnd
, &changeRect
, FALSE
);
871 else if(oldRect
.left
!= -1)
873 /* clear the selection */
874 GuiData
->Selection
.left
= -1;
875 oldRect
.left
*= GuiData
->CharWidth
;
876 oldRect
.top
*= GuiData
->CharHeight
;
877 oldRect
.right
*= GuiData
->CharWidth
;
878 oldRect
.bottom
*= GuiData
->CharHeight
;
879 InvalidateRect(hWnd
, &oldRect
, FALSE
);
885 GuiConsolePaint(PCSRSS_CONSOLE Console
,
886 PGUI_CONSOLE_DATA GuiData
,
890 PCSRSS_SCREEN_BUFFER Buff
;
891 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
892 ULONG Line
, Char
, Start
;
895 BYTE LastAttribute
, Attribute
;
896 ULONG CursorX
, CursorY
, CursorHeight
;
897 HBRUSH CursorBrush
, OldBrush
, BackgroundBrush
;
900 Buff
= Console
->ActiveBuffer
;
902 TopLine
= rc
->top
/ GuiData
->CharHeight
;
903 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1;
904 LeftChar
= rc
->left
/ GuiData
->CharWidth
;
905 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1;
906 LastAttribute
= Buff
->Buffer
[(TopLine
* Buff
->MaxX
+ LeftChar
) * 2 + 1];
908 GuiConsoleSetTextColors(hDC
,
912 GuiData
->ScreenBackground
);
914 EnterCriticalSection(&Buff
->Header
.Lock
);
916 OldFont
= SelectObject(hDC
,
919 BackgroundBrush
= CreateSolidBrush(GuiData
->ScreenBackground
);
920 FillRect(hDC
, rc
, BackgroundBrush
);
921 DeleteObject(BackgroundBrush
);
923 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
925 if (Line
+ Buff
->ShowY
< Buff
->MaxY
)
927 From
= Buff
->Buffer
+ ((Line
+ Buff
->ShowY
) * Buff
->MaxX
+ LeftChar
) * 2;
931 From
= Buff
->Buffer
+
932 ((Line
- (Buff
->MaxY
- Buff
->ShowY
)) * Buff
->MaxX
+ LeftChar
) * 2;
935 To
= GuiData
->LineBuffer
;
937 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
939 if (*(From
+ 1) != LastAttribute
)
942 Start
* GuiData
->CharWidth
,
943 Line
* GuiData
->CharHeight
,
947 To
= GuiData
->LineBuffer
;
948 Attribute
= *(From
+ 1);
949 if (Attribute
!= LastAttribute
)
951 GuiConsoleSetTextColors(hDC
,
955 GuiData
->ScreenBackground
);
956 LastAttribute
= Attribute
;
960 MultiByteToWideChar(Console
->OutputCodePage
,
971 Start
* GuiData
->CharWidth
,
972 Line
* GuiData
->CharHeight
,
974 RightChar
- Start
+ 1);
977 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
&&
978 !GuiData
->ForceCursorOff
)
980 GuiConsoleGetLogicalCursorPos(Buff
,
983 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
984 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
986 CursorHeight
= (GuiData
->CharHeight
* Buff
->CursorInfo
.dwSize
) / 100;
987 if (CursorHeight
< 1)
991 From
= Buff
->Buffer
+ (Buff
->CurrentY
* Buff
->MaxX
+ Buff
->CurrentX
) * 2 + 1;
993 if (*From
!= DEFAULT_ATTRIB
)
995 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(*From
));
999 CursorBrush
= CreateSolidBrush(GuiData
->ScreenText
);
1002 OldBrush
= SelectObject(hDC
,
1005 CursorX
* GuiData
->CharWidth
,
1006 CursorY
* GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
1012 DeleteObject(CursorBrush
);
1016 LeaveCriticalSection(&Buff
->Header
.Lock
);
1022 static VOID FASTCALL
1023 GuiConsoleHandlePaint(HWND hWnd
, HDC hDCPaint
)
1027 PCSRSS_CONSOLE Console
;
1028 PGUI_CONSOLE_DATA GuiData
;
1030 hDC
= BeginPaint(hWnd
, &ps
);
1032 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
1033 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
1035 GuiConsoleGetDataPointers(hWnd
,
1038 if (Console
!= NULL
&& GuiData
!= NULL
&&
1039 Console
->ActiveBuffer
!= NULL
)
1041 if (Console
->ActiveBuffer
->Buffer
!= NULL
)
1043 EnterCriticalSection(&GuiData
->Lock
);
1045 GuiConsolePaint(Console
,
1050 if (GuiData
->Selection
.left
!= -1)
1052 RECT rc
= GuiData
->Selection
;
1054 rc
.left
*= GuiData
->CharWidth
;
1055 rc
.top
*= GuiData
->CharHeight
;
1056 rc
.right
*= GuiData
->CharWidth
;
1057 rc
.bottom
*= GuiData
->CharHeight
;
1059 /* invert the selection */
1060 if (IntersectRect(&rc
,
1073 LeaveCriticalSection(&GuiData
->Lock
);
1077 EndPaint(hWnd
, &ps
);
1081 static VOID FASTCALL
1082 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1084 PCSRSS_CONSOLE Console
;
1085 PGUI_CONSOLE_DATA GuiData
;
1088 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1089 Message
.hwnd
= hWnd
;
1090 Message
.message
= msg
;
1091 Message
.wParam
= wParam
;
1092 Message
.lParam
= lParam
;
1094 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
1096 /* clear the selection */
1097 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
1100 ConioProcessKey(&Message
, Console
, FALSE
);
1103 static VOID FASTCALL
1104 GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, RECT
*Region
)
1108 RegionRect
.left
= Region
->left
* GuiData
->CharWidth
;
1109 RegionRect
.top
= Region
->top
* GuiData
->CharHeight
;
1110 RegionRect
.right
= (Region
->right
+ 1) * GuiData
->CharWidth
;
1111 RegionRect
.bottom
= (Region
->bottom
+ 1) * GuiData
->CharHeight
;
1113 InvalidateRect(Wnd
, &RegionRect
, FALSE
);
1117 GuiDrawRegion(PCSRSS_CONSOLE Console
, RECT
*Region
)
1119 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1121 if (NULL
!= Console
->hWindow
&& NULL
!= GuiData
)
1123 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
1127 static VOID FASTCALL
1128 GuiInvalidateCell(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, UINT x
, UINT y
)
1135 CellRect
.bottom
= y
;
1137 GuiIntDrawRegion(GuiData
, Wnd
, &CellRect
);
1141 GuiWriteStream(PCSRSS_CONSOLE Console
, RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
1142 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
1144 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1145 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1146 LONG CursorEndX
, CursorEndY
;
1149 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
1154 if (0 != ScrolledLines
)
1156 ScrollRect
.left
= 0;
1158 ScrollRect
.right
= Console
->Size
.X
* GuiData
->CharWidth
;
1159 ScrollRect
.bottom
= Region
->top
* GuiData
->CharHeight
;
1161 if (GuiData
->Selection
.left
!= -1)
1163 /* scroll the selection */
1164 if (GuiData
->Selection
.top
> ScrolledLines
)
1166 GuiData
->Selection
.top
-= ScrolledLines
;
1167 GuiData
->Selection
.bottom
-= ScrolledLines
;
1169 else if (GuiData
->Selection
.bottom
< ScrolledLines
)
1171 GuiData
->Selection
.left
= -1;
1175 GuiData
->Selection
.top
= 0;
1176 GuiData
->Selection
.bottom
-= ScrolledLines
;
1180 ScrollWindowEx(Console
->hWindow
,
1182 -(ScrolledLines
* GuiData
->CharHeight
),
1190 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
1192 if (CursorStartX
< Region
->left
|| Region
->right
< CursorStartX
1193 || CursorStartY
< Region
->top
|| Region
->bottom
< CursorStartY
)
1195 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorStartX
, CursorStartY
);
1198 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
1199 &CursorEndX
, &CursorEndY
);
1200 if ((CursorEndX
< Region
->left
|| Region
->right
< CursorEndX
1201 || CursorEndY
< Region
->top
|| Region
->bottom
< CursorEndY
)
1202 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
1204 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorEndX
, CursorEndY
);
1209 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1213 if (Console
->ActiveBuffer
== Buff
)
1215 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
1216 &UpdateRect
.left
, &UpdateRect
.top
);
1217 UpdateRect
.right
= UpdateRect
.left
;
1218 UpdateRect
.bottom
= UpdateRect
.top
;
1219 ConioDrawRegion(Console
, &UpdateRect
);
1226 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
1230 if (Console
->ActiveBuffer
== Buff
)
1232 /* Redraw char at old position (removes cursor) */
1233 UpdateRect
.left
= OldCursorX
;
1234 UpdateRect
.top
= OldCursorY
;
1235 UpdateRect
.right
= OldCursorX
;
1236 UpdateRect
.bottom
= OldCursorY
;
1237 ConioDrawRegion(Console
, &UpdateRect
);
1238 /* Redraw char at new position (shows cursor) */
1239 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
1240 &(UpdateRect
.left
), &(UpdateRect
.top
));
1241 UpdateRect
.right
= UpdateRect
.left
;
1242 UpdateRect
.bottom
= UpdateRect
.top
;
1243 ConioDrawRegion(Console
, &UpdateRect
);
1249 static VOID FASTCALL
1250 GuiConsoleHandleTimer(HWND hWnd
)
1252 PCSRSS_CONSOLE Console
;
1253 PGUI_CONSOLE_DATA GuiData
;
1255 ULONG CursorX
, CursorY
;
1257 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1258 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
1260 GuiConsoleGetLogicalCursorPos(Console
->ActiveBuffer
, &CursorX
, &CursorY
);
1261 CursorRect
.left
= CursorX
;
1262 CursorRect
.top
= CursorY
;
1263 CursorRect
.right
= CursorX
;
1264 CursorRect
.bottom
= CursorY
;
1265 GuiDrawRegion(Console
, &CursorRect
);
1268 static VOID FASTCALL
1269 GuiConsoleHandleClose(HWND hWnd
)
1271 PCSRSS_CONSOLE Console
;
1272 PGUI_CONSOLE_DATA GuiData
;
1273 PLIST_ENTRY current_entry
;
1274 PCSRSS_PROCESS_DATA current
;
1276 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1278 EnterCriticalSection(&Console
->Header
.Lock
);
1280 current_entry
= Console
->ProcessList
.Flink
;
1281 while (current_entry
!= &Console
->ProcessList
)
1283 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1284 current_entry
= current_entry
->Flink
;
1286 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
1289 LeaveCriticalSection(&Console
->Header
.Lock
);
1292 static VOID FASTCALL
1293 GuiConsoleHandleNcDestroy(HWND hWnd
)
1295 PCSRSS_CONSOLE Console
;
1296 PGUI_CONSOLE_DATA GuiData
;
1299 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1301 Console
->PrivateData
= NULL
;
1302 DeleteCriticalSection(&GuiData
->Lock
);
1303 GetSystemMenu(hWnd
, TRUE
);
1304 if (GuiData
->ConsoleLibrary
)
1305 FreeLibrary(GuiData
->ConsoleLibrary
);
1307 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
1310 static VOID FASTCALL
1311 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
1313 PCSRSS_CONSOLE Console
;
1314 PGUI_CONSOLE_DATA GuiData
;
1318 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1319 if (Console
== NULL
|| GuiData
== NULL
) return;
1321 pt
= MAKEPOINTS(lParam
);
1323 rc
.left
= pt
.x
/ GuiData
->CharWidth
;
1324 rc
.top
= pt
.y
/ GuiData
->CharHeight
;
1325 rc
.right
= rc
.left
+ 1;
1326 rc
.bottom
= rc
.top
+ 1;
1328 GuiData
->SelectionStart
.x
= rc
.left
;
1329 GuiData
->SelectionStart
.y
= rc
.top
;
1333 GuiData
->MouseDown
= TRUE
;
1335 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1338 static VOID FASTCALL
1339 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
1341 PCSRSS_CONSOLE Console
;
1342 PGUI_CONSOLE_DATA GuiData
;
1346 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1347 if (Console
== NULL
|| GuiData
== NULL
) return;
1348 if (GuiData
->Selection
.left
== -1 || !GuiData
->MouseDown
) return;
1350 pt
= MAKEPOINTS(lParam
);
1352 rc
.left
= GuiData
->SelectionStart
.x
;
1353 rc
.top
= GuiData
->SelectionStart
.y
;
1354 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
1355 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
1357 /* exchange left/top with right/bottom if required */
1358 if(rc
.left
>= rc
.right
)
1362 rc
.left
= max(rc
.right
- 1, 0);
1365 if(rc
.top
>= rc
.bottom
)
1369 rc
.top
= max(rc
.bottom
- 1, 0);
1370 rc
.bottom
= tmp
+ 1;
1373 GuiData
->MouseDown
= FALSE
;
1375 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1380 static VOID FASTCALL
1381 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1383 PCSRSS_CONSOLE Console
;
1384 PGUI_CONSOLE_DATA GuiData
;
1388 if (!(wParam
& MK_LBUTTON
)) return;
1390 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1391 if (Console
== NULL
|| GuiData
== NULL
|| !GuiData
->MouseDown
) return;
1393 pt
= MAKEPOINTS(lParam
);
1395 rc
.left
= GuiData
->SelectionStart
.x
;
1396 rc
.top
= GuiData
->SelectionStart
.y
;
1397 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
1398 if (Console
->Size
.X
< rc
.right
)
1400 rc
.right
= Console
->Size
.X
;
1402 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
1403 if (Console
->Size
.Y
< rc
.bottom
)
1405 rc
.bottom
= Console
->Size
.Y
;
1408 /* exchange left/top with right/bottom if required */
1409 if(rc
.left
>= rc
.right
)
1413 rc
.left
= max(rc
.right
- 1, 0);
1416 if(rc
.top
>= rc
.bottom
)
1420 rc
.top
= max(rc
.bottom
- 1, 0);
1421 rc
.bottom
= tmp
+ 1;
1424 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1427 static VOID FASTCALL
1428 GuiConsoleRightMouseDown(HWND hWnd
)
1430 PCSRSS_CONSOLE Console
;
1431 PGUI_CONSOLE_DATA GuiData
;
1433 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1434 if (Console
== NULL
|| GuiData
== NULL
) return;
1436 if (GuiData
->Selection
.left
== -1)
1438 /* FIXME - paste text from clipboard */
1442 /* FIXME - copy selection to clipboard */
1444 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
1451 GuiConsoleShowConsoleProperties(HWND hWnd
, BOOL Defaults
, PGUI_CONSOLE_DATA GuiData
)
1453 PCSRSS_CONSOLE Console
;
1454 APPLET_PROC CPLFunc
;
1455 TCHAR szBuffer
[MAX_PATH
];
1456 ConsoleInfo SharedInfo
;
1458 DPRINT("GuiConsoleShowConsoleProperties entered\n");
1460 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1462 if (GuiData
== NULL
)
1464 DPRINT("GuiConsoleGetDataPointers failed\n");
1468 if (GuiData
->ConsoleLibrary
== NULL
)
1470 GetWindowsDirectory(szBuffer
,MAX_PATH
);
1471 _tcscat(szBuffer
, _T("\\system32\\console.dll"));
1472 GuiData
->ConsoleLibrary
= LoadLibrary(szBuffer
);
1474 if (GuiData
->ConsoleLibrary
== NULL
)
1476 DPRINT1("failed to load console.dll");
1481 CPLFunc
= (APPLET_PROC
) GetProcAddress(GuiData
->ConsoleLibrary
, _T("CPlApplet"));
1484 DPRINT("Error: Console.dll misses CPlApplet export\n");
1489 SharedInfo
.InsertMode
= GuiData
->InsertMode
;
1490 SharedInfo
.HistoryBufferSize
= GuiData
->HistoryBufferSize
;
1491 SharedInfo
.NumberOfHistoryBuffers
= GuiData
->NumberOfHistoryBuffers
;
1492 SharedInfo
.ScreenText
= GuiData
->ScreenText
;
1493 SharedInfo
.ScreenBackground
= GuiData
->ScreenBackground
;
1494 SharedInfo
.PopupText
= GuiData
->PopupText
;
1495 SharedInfo
.PopupBackground
= GuiData
->PopupBackground
;
1496 SharedInfo
.WindowSize
= (DWORD
)MAKELONG(Console
->Size
.X
, Console
->Size
.Y
);
1497 SharedInfo
.WindowPosition
= GuiData
->WindowPosition
;
1498 SharedInfo
.ScreenBuffer
= GuiData
->ScreenBufferSize
;
1499 SharedInfo
.UseRasterFonts
= GuiData
->UseRasterFonts
;
1500 SharedInfo
.FontSize
= (DWORD
)GuiData
->FontSize
;
1501 SharedInfo
.FontWeight
= GuiData
->FontWeight
;
1502 SharedInfo
.CursorSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1503 SharedInfo
.HistoryNoDup
= GuiData
->HistoryNoDup
;
1504 SharedInfo
.FullScreen
= GuiData
->FullScreen
;
1505 SharedInfo
.QuickEdit
= GuiData
->QuickEdit
;
1506 memcpy(&SharedInfo
.Colors
[0], GuiData
->Colors
, sizeof(s_Colors
));
1508 if (!CPLFunc(hWnd
, CPL_INIT
, 0, 0))
1510 DPRINT("Error: failed to initialize console.dll\n");
1514 if (CPLFunc(hWnd
, CPL_GETCOUNT
, 0, 0) != 1)
1516 DPRINT("Error: console.dll returned unexpected CPL count\n");
1520 CPLFunc(hWnd
, CPL_DBLCLK
, (LPARAM
)&SharedInfo
, Defaults
);
1522 static LRESULT FASTCALL
1523 GuiConsoleHandleSysMenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
, PGUI_CONSOLE_DATA GuiData
)
1529 case ID_SYSTEM_EDIT_MARK
:
1530 case ID_SYSTEM_EDIT_COPY
:
1531 case ID_SYSTEM_EDIT_PASTE
:
1532 case ID_SYSTEM_EDIT_SELECTALL
:
1533 case ID_SYSTEM_EDIT_SCROLL
:
1534 case ID_SYSTEM_EDIT_FIND
:
1537 case ID_SYSTEM_DEFAULTS
:
1538 GuiConsoleShowConsoleProperties(hWnd
, TRUE
, GuiData
);
1541 case ID_SYSTEM_PROPERTIES
:
1542 GuiConsoleShowConsoleProperties(hWnd
, FALSE
, GuiData
);
1546 Ret
= DefWindowProcW(hWnd
, WM_SYSCOMMAND
, wParam
, lParam
);
1552 static VOID FASTCALL
1553 GuiConsoleResize(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1555 PCSRSS_CONSOLE Console
;
1556 PGUI_CONSOLE_DATA GuiData
;
1558 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1559 if (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
)
1561 DPRINT1("GuiConsoleResize X %d Y %d\n", LOWORD(lParam
), HIWORD(lParam
));
1566 GuiConsoleHandleScrollbarMenu()
1570 hMenu
= CreatePopupMenu();
1573 DPRINT("CreatePopupMenu failed\n");
1576 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1577 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1578 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1579 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1580 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1581 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1582 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1583 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1584 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1585 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1589 static VOID FASTCALL
1590 GuiApplyUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PConsoleInfo pConInfo
)
1594 PCSRSS_SCREEN_BUFFER ActiveBuffer
;
1595 PCSRSS_PROCESS_DATA ProcessData
= NULL
;
1597 if (Console
->ProcessList
.Flink
!= &Console
->ProcessList
)
1599 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1600 ConioLockScreenBuffer(ProcessData
, Console
->hActiveBuffer
, (Object_t
**)&ActiveBuffer
);
1603 /* apply text / background color */
1604 GuiData
->ScreenText
= pConInfo
->ScreenText
;
1605 GuiData
->ScreenBackground
= pConInfo
->ScreenBackground
;
1607 /* apply cursor size */
1608 Console
->ActiveBuffer
->CursorInfo
.dwSize
= max(min(pConInfo
->CursorSize
, 1), 100);
1610 windx
= LOWORD(pConInfo
->ScreenBuffer
);
1611 windy
= HIWORD(pConInfo
->ScreenBuffer
);
1613 if (windx
!= ActiveBuffer
->MaxX
|| windy
!= ActiveBuffer
->MaxY
)
1615 BYTE
* Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, windx
* windy
* 2);
1620 DWORD BufferOffset
= 0;
1627 value
= MAKEWORD(' ', ActiveBuffer
->DefaultAttrib
);
1629 DPRINT("MaxX %d MaxY %d windx %d windy %d value %04x DefaultAttrib %d\n",ActiveBuffer
->MaxX
, ActiveBuffer
->MaxY
, windx
, windy
, value
, ActiveBuffer
->DefaultAttrib
);
1630 OldBuffer
= ActiveBuffer
->Buffer
;
1632 for (CurrentY
= 0; CurrentY
< min(ActiveBuffer
->MaxY
, windy
); CurrentY
++)
1634 if (windx
<= ActiveBuffer
->MaxX
)
1637 RtlCopyMemory(&Buffer
[Offset
], &OldBuffer
[BufferOffset
], windx
* 2);
1638 Offset
+= (windx
* 2);
1639 BufferOffset
+= (ActiveBuffer
->MaxX
* 2);
1644 RtlCopyMemory(&Buffer
[Offset
], &OldBuffer
[BufferOffset
], ActiveBuffer
->MaxX
* 2);
1645 Offset
+= (ActiveBuffer
->MaxX
* 2);
1647 diff
= windx
- ActiveBuffer
->MaxX
;
1648 /* zero new part of it */
1650 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
);
1652 for (i
= 0; i
< diff
* 2; i
++)
1654 Buffer
[Offset
* 2] = ' ';
1655 Buffer
[Offset
* 2 + 1] = ActiveBuffer
->DefaultAttrib
;
1658 Offset
+= (diff
* 2);
1659 BufferOffset
+= (Console
->ActiveBuffer
->MaxX
* 2);
1663 if (windy
> Console
->ActiveBuffer
->MaxY
)
1665 diff
= windy
- Console
->ActiveBuffer
->MaxX
;
1667 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
* windx
);
1669 for (i
= 0; i
< diff
* 2; i
++)
1671 Buffer
[Offset
* 2] = ' ';
1672 Buffer
[Offset
* 2 + 1] = ActiveBuffer
->DefaultAttrib
;
1677 (void)InterlockedExchangePointer((PVOID
volatile *)&Console
->ActiveBuffer
->Buffer
, Buffer
);
1678 HeapFree(Win32CsrApiHeap
, 0, OldBuffer
);
1679 Console
->ActiveBuffer
->MaxX
= windx
;
1680 Console
->ActiveBuffer
->MaxY
= windy
;
1681 InvalidateRect(pConInfo
->hConsoleWindow
, NULL
, TRUE
);
1687 ConioUnlockScreenBuffer(ActiveBuffer
);
1693 windx
= LOWORD(pConInfo
->WindowSize
);
1694 windy
= HIWORD(pConInfo
->WindowSize
);
1696 if (windx
> Console
->Size
.X
)
1698 PWCHAR LineBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, windx
* sizeof(WCHAR
));
1701 HeapFree(Win32CsrApiHeap
, 0, GuiData
->LineBuffer
);
1702 GuiData
->LineBuffer
= LineBuffer
;
1708 ConioUnlockScreenBuffer(ActiveBuffer
);
1715 if (windx
!= Console
->Size
.X
|| windy
!= Console
->Size
.Y
)
1718 Console
->Size
.X
= windx
;
1719 Console
->Size
.Y
= windy
;
1721 GetWindowRect(pConInfo
->hConsoleWindow
, &rect
);
1723 rect
.right
= rect
.left
+ Console
->Size
.X
* GuiData
->CharWidth
+ 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
1724 rect
.bottom
= rect
.top
+ Console
->Size
.Y
* GuiData
->CharHeight
+ 2 * GetSystemMetrics(SM_CYFIXEDFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
1726 MoveWindow(pConInfo
->hConsoleWindow
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, FALSE
);
1728 if (Console
->Size
.X
< Console
->ActiveBuffer
->MaxX
)
1730 /* show scrollbar when window becomes smaller than active screen buffer */
1731 ShowScrollBar(pConInfo
->hConsoleWindow
, SB_CTL
, TRUE
);
1735 /* hide scrollbar */
1736 ShowScrollBar(pConInfo
->hConsoleWindow
, SB_CTL
, FALSE
);
1741 ConioUnlockScreenBuffer(ActiveBuffer
);
1743 InvalidateRect(pConInfo
->hConsoleWindow
, NULL
, TRUE
);
1748 GuiConsoleHandleScroll(HWND hwnd
, UINT uMsg
, WPARAM wParam
, PGUI_CONSOLE_DATA GuiData
)
1753 /* set scrollbar sizes */
1754 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1755 sInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_PAGE
| SIF_TRACKPOS
;
1757 if (!GetScrollInfo(hwnd
,
1758 (uMsg
== WM_HSCROLL
? SB_HORZ
: SB_VERT
),
1764 old_pos
= sInfo
.nPos
;
1766 switch(LOWORD(wParam
))
1777 sInfo
.nPos
-= sInfo
.nPage
;
1781 sInfo
.nPos
+= sInfo
.nPage
;
1785 sInfo
.nPage
= sInfo
.nTrackPos
;
1789 sInfo
.nPos
= sInfo
.nMin
;
1793 sInfo
.nPos
= sInfo
.nMax
;
1800 sInfo
.fMask
= SIF_POS
;
1801 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1804 (uMsg
== WM_HSCROLL
? SB_HORZ
: SB_VERT
),
1808 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1809 sInfo
.fMask
= SIF_POS
;
1811 if (!GetScrollInfo(hwnd
,
1812 (uMsg
== WM_HSCROLL
? SB_HORZ
: SB_VERT
),
1818 if (old_pos
!= sInfo
.nPos
)
1821 /// fixme scroll window
1824 ScrollWindowEx(hwnd
,
1826 GuiData
->CharHeight
* (old_pos
- sInfo
.nPos
),
1838 static LRESULT CALLBACK
1839 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1842 PGUI_CONSOLE_DATA GuiData
= NULL
;
1843 PCSRSS_CONSOLE Console
= NULL
;
1845 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1850 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
1853 GuiConsoleHandlePaint(hWnd
, (HDC
)wParam
);
1860 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
1863 GuiConsoleHandleTimer(hWnd
);
1866 GuiConsoleHandleClose(hWnd
);
1869 GuiConsoleHandleNcDestroy(hWnd
);
1871 case WM_LBUTTONDOWN
:
1872 GuiConsoleLeftMouseDown(hWnd
, lParam
);
1875 GuiConsoleLeftMouseUp(hWnd
, lParam
);
1877 case WM_RBUTTONDOWN
:
1878 GuiConsoleRightMouseDown(hWnd
);
1881 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
1884 Result
= GuiConsoleHandleSysMenuCommand(hWnd
, wParam
, lParam
, GuiData
);
1888 Result
= GuiConsoleHandleScroll(hWnd
, msg
, wParam
, GuiData
);
1891 GuiConsoleResize(hWnd
, wParam
, lParam
);
1893 case PM_APPLY_CONSOLE_INFO
:
1894 GuiApplyUserSettings(Console
, GuiData
, (PConsoleInfo
)wParam
);
1897 GuiConsoleWriteUserSettings(Console
, GuiData
);
1901 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1908 static LRESULT CALLBACK
1909 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1914 PWCHAR Buffer
, Title
;
1915 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
1922 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
1924 case PM_CREATE_CONSOLE
:
1925 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
1926 Console
->Title
.Length
+ sizeof(WCHAR
));
1929 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
1930 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
1937 NewWindow
= CreateWindowW(L
"ConsoleWindowClass",
1939 WS_OVERLAPPED
| WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_HSCROLL
| WS_VSCROLL
, //WS_OVERLAPPEDWINDOW
1946 (HINSTANCE
) GetModuleHandleW(NULL
),
1950 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1952 if (NULL
!= NewWindow
)
1954 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
1955 ShowWindow(NewWindow
, SW_SHOW
);
1957 return (LRESULT
) NewWindow
;
1958 case PM_DESTROY_CONSOLE
:
1959 /* Window creation is done using a PostMessage(), so it's possible that the
1960 * window that we want to destroy doesn't exist yet. So first empty the message
1962 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
1964 TranslateMessage(&Msg
);
1965 DispatchMessageW(&Msg
);
1967 DestroyWindow(Console
->hWindow
);
1968 Console
->hWindow
= NULL
;
1969 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
1971 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
1972 if (0 == WindowCount
)
1975 DestroyWindow(hWnd
);
1976 PrivateCsrssManualGuiCheck(-1);
1981 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1985 static DWORD STDCALL
1986 GuiConsoleGuiThread(PVOID Data
)
1989 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
1991 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
1993 WS_OVERLAPPEDWINDOW
,
2000 (HINSTANCE
) GetModuleHandleW(NULL
),
2002 if (NULL
== NotifyWnd
)
2004 PrivateCsrssManualGuiCheck(-1);
2005 SetEvent(*GraphicsStartupEvent
);
2009 SetEvent(*GraphicsStartupEvent
);
2011 while(GetMessageW(&msg
, NULL
, 0, 0))
2013 TranslateMessage(&msg
);
2014 DispatchMessageW(&msg
);
2020 static BOOL FASTCALL
2025 if (NULL
== NotifyWnd
)
2027 PrivateCsrssManualGuiCheck(+1);
2030 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2031 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
2032 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
2034 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
2037 wc
.hbrBackground
= NULL
;
2038 wc
.lpszMenuName
= NULL
;
2042 if (RegisterClassExW(&wc
) == 0)
2044 DPRINT1("Failed to register notify wndproc\n");
2048 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2049 wc
.lpszClassName
= L
"ConsoleWindowClass";
2050 wc
.lpfnWndProc
= GuiConsoleWndProc
;
2052 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
2053 wc
.hIcon
= LoadIconW(GetModuleHandleW(L
"win32csr"), MAKEINTRESOURCEW(1));
2054 wc
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
) IDC_ARROW
);
2055 wc
.hbrBackground
= NULL
;
2056 wc
.lpszMenuName
= NULL
;
2059 wc
.hIconSm
= LoadImageW(GetModuleHandleW(L
"win32csr"), MAKEINTRESOURCEW(1), IMAGE_ICON
,
2060 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
2062 if (RegisterClassExW(&wc
) == 0)
2064 DPRINT1("Failed to register console wndproc\n");
2072 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
2074 Buffer
->DefaultAttrib
= DEFAULT_ATTRIB
;
2078 GuiChangeTitle(PCSRSS_CONSOLE Console
)
2080 PWCHAR Buffer
, Title
;
2082 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
2083 Console
->Title
.Length
+ sizeof(WCHAR
));
2086 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
2087 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
2095 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
) Title
);
2099 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
2106 GuiChangeIcon(PCSRSS_CONSOLE Console
)
2108 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)Console
->hWindowIcon
);
2109 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)Console
->hWindowIcon
);
2115 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
2117 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
) Console
);
2120 static CSRSS_CONSOLE_VTBL GuiVtbl
=
2122 GuiInitScreenBuffer
,
2133 GuiInitConsole(PCSRSS_CONSOLE Console
)
2135 HANDLE GraphicsStartupEvent
;
2136 HANDLE ThreadHandle
;
2137 PGUI_CONSOLE_DATA GuiData
;
2139 if (! ConsInitialized
)
2141 ConsInitialized
= TRUE
;
2144 ConsInitialized
= FALSE
;
2145 return STATUS_UNSUCCESSFUL
;
2149 Console
->Vtbl
= &GuiVtbl
;
2150 if (NULL
== NotifyWnd
)
2152 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2153 if (NULL
== GraphicsStartupEvent
)
2155 return STATUS_UNSUCCESSFUL
;
2158 ThreadHandle
= CreateThread(NULL
,
2160 GuiConsoleGuiThread
,
2161 (PVOID
) &GraphicsStartupEvent
,
2164 if (NULL
== ThreadHandle
)
2166 NtClose(GraphicsStartupEvent
);
2167 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
2168 return STATUS_UNSUCCESSFUL
;
2170 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
2171 CloseHandle(ThreadHandle
);
2173 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
2174 CloseHandle(GraphicsStartupEvent
);
2176 if (NULL
== NotifyWnd
)
2178 DPRINT1("Win32Csr: Failed to create notification window.\n");
2179 return STATUS_UNSUCCESSFUL
;
2182 GuiData
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
2183 sizeof(GUI_CONSOLE_DATA
));
2186 DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
2187 return STATUS_UNSUCCESSFUL
;
2190 Console
->PrivateData
= (PVOID
) GuiData
;
2192 * we need to wait untill the GUI has been fully initialized
2193 * to retrieve custom settings i.e. WindowSize etc..
2194 * Ideally we could use SendNotifyMessage for this but its not
2198 GuiData
->hGuiInitEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2199 /* create console */
2200 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, 0, (LPARAM
) Console
);
2202 /* wait untill initialization has finished */
2203 WaitForSingleObject(GuiData
->hGuiInitEvent
, INFINITE
);
2204 DPRINT1("received event Console %p GuiData %p X %d Y %d\n", Console
, Console
->PrivateData
, Console
->Size
.X
, Console
->Size
.Y
);
2205 CloseHandle(GuiData
->hGuiInitEvent
);
2206 GuiData
->hGuiInitEvent
= NULL
;
2208 return STATUS_SUCCESS
;