3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: subsys/csrss/win32csr/guiconsole.c
6 * PURPOSE: Implementation of gui-mode consoles
9 /* INCLUDES ******************************************************************/
15 /* Not defined in any header file */
16 extern VOID WINAPI
PrivateCsrssManualGuiCheck(LONG Check
);
18 /* GLOBALS *******************************************************************/
20 typedef struct GUI_CONSOLE_DATA_TAG
28 CRITICAL_SECTION Lock
;
32 HMODULE ConsoleLibrary
;
34 WCHAR FontName
[LF_FACESIZE
];
41 DWORD NumberOfHistoryBuffers
;
42 DWORD HistoryBufferSize
;
46 COLORREF ScreenBackground
;
47 COLORREF PopupBackground
;
50 WCHAR szProcessName
[MAX_PATH
];
51 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
56 #define PM_CREATE_CONSOLE (WM_APP + 1)
57 #define PM_DESTROY_CONSOLE (WM_APP + 2)
59 #define CURSOR_BLINK_TIME 500
60 #define DEFAULT_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
62 static BOOL ConsInitialized
= FALSE
;
63 static HWND NotifyWnd
;
65 typedef struct _GUICONSOLE_MENUITEM
68 const struct _GUICONSOLE_MENUITEM
*SubMenu
;
70 } GUICONSOLE_MENUITEM
, *PGUICONSOLE_MENUITEM
;
72 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems
[] =
74 { IDS_MARK
, NULL
, ID_SYSTEM_EDIT_MARK
},
75 { IDS_COPY
, NULL
, ID_SYSTEM_EDIT_COPY
},
76 { IDS_PASTE
, NULL
, ID_SYSTEM_EDIT_PASTE
},
77 { IDS_SELECTALL
, NULL
, ID_SYSTEM_EDIT_SELECTALL
},
78 { IDS_SCROLL
, NULL
, ID_SYSTEM_EDIT_SCROLL
},
79 { IDS_FIND
, NULL
, ID_SYSTEM_EDIT_FIND
},
81 { 0, NULL
, 0 } /* End of list */
84 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems
[] =
86 { (UINT
)-1, NULL
, 0 }, /* Separator */
87 { IDS_EDIT
, GuiConsoleEditMenuItems
, 0 },
88 { IDS_DEFAULTS
, NULL
, ID_SYSTEM_DEFAULTS
},
89 { IDS_PROPERTIES
, NULL
, ID_SYSTEM_PROPERTIES
},
91 { 0, NULL
, 0 } /* End of list */
94 static const COLORREF s_Colors
[] =
114 #define GuiConsoleRGBFromAttribute(GuiData, Attribute) ((GuiData)->Colors[(Attribute) & 0xF])
116 /* FUNCTIONS *****************************************************************/
119 GuiConsoleAppendMenuItems(HMENU hMenu
,
120 const GUICONSOLE_MENUITEM
*Items
)
123 WCHAR szMenuString
[255];
125 HINSTANCE hInst
= GetModuleHandleW(L
"win32csr");
129 if (Items
[i
].uID
!= (UINT
)-1)
131 if (LoadStringW(hInst
,
134 sizeof(szMenuString
) / sizeof(szMenuString
[0])) > 0)
136 if (Items
[i
].SubMenu
!= NULL
)
138 hSubMenu
= CreatePopupMenu();
139 if (hSubMenu
!= NULL
)
141 GuiConsoleAppendMenuItems(hSubMenu
,
144 if (!AppendMenuW(hMenu
,
145 MF_STRING
| MF_POPUP
,
149 DestroyMenu(hSubMenu
);
170 }while(!(Items
[i
].uID
== 0 && Items
[i
].SubMenu
== NULL
&& Items
[i
].wCmdID
== 0));
174 GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console
)
177 hMenu
= GetSystemMenu(Console
->hWindow
,
181 GuiConsoleAppendMenuItems(hMenu
,
182 GuiConsoleMainMenuItems
);
183 DrawMenuBar(Console
->hWindow
);
188 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
190 *Console
= (PCSRSS_CONSOLE
) GetWindowLongPtrW(hWnd
, GWL_USERDATA
);
191 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
195 GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId
, PHANDLE hProcHandle
, PHKEY hResult
, REGSAM samDesired
)
197 HANDLE hProcessToken
= NULL
;
202 UNICODE_STRING SidName
;
206 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
| READ_CONTROL
, FALSE
, ProcessId
);
209 DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
213 if (!OpenProcessToken(hProcess
, TOKEN_QUERY
, &hProcessToken
))
215 DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
216 CloseHandle(hProcess
);
220 if (!GetTokenInformation(hProcessToken
, TokenUser
, (PVOID
)Buffer
, sizeof(Buffer
), &Length
))
222 DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
223 CloseHandle(hProcess
);
224 CloseHandle(hProcessToken
);
228 TokUser
= ((PTOKEN_USER
)Buffer
)->User
.Sid
;
229 if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName
, TokUser
, TRUE
)))
231 DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
235 res
= RegOpenKeyExW(HKEY_USERS
, SidName
.Buffer
, 0, samDesired
, hResult
);
236 RtlFreeUnicodeString(&SidName
);
238 CloseHandle(hProcessToken
);
240 *hProcHandle
= hProcess
;
242 CloseHandle(hProcess
);
244 if (res
!= ERROR_SUCCESS
)
251 GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData
, DWORD ProcessId
, PHKEY hSubKey
, REGSAM samDesired
, BOOL bCreate
)
253 WCHAR szProcessName
[MAX_PATH
];
254 WCHAR szBuffer
[MAX_PATH
];
255 UINT fLength
, wLength
;
256 DWORD dwBitmask
, dwLength
;
257 WCHAR CurDrive
[] = { 'A',':', 0 };
263 * console properties are stored under
266 * There are 3 ways to store console properties
268 * 1. use console title as subkey name
271 * 2. use application name as subkey name
273 * 3. use unexpanded path to console application.
274 * i.e. %SystemRoot%_system32_cmd.exe
277 DPRINT("GuiConsoleOpenUserSettings entered\n");
279 if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId
, &hProcess
, &hKey
, samDesired
))
281 DPRINT("GuiConsoleOpenUserRegistryPathPerProcessId failed\n");
285 /* FIXME we do not getting the process name so no menu will be loading, why ?*/
286 fLength
= GetProcessImageFileNameW(hProcess
, szProcessName
, sizeof(GuiData
->szProcessName
) / sizeof(WCHAR
));
287 CloseHandle(hProcess
);
289 //DPRINT1("szProcessName3 : %S\n",szProcessName);
293 DPRINT("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(),hProcess
);
297 * try the process name as path
300 ptr
= wcsrchr(szProcessName
, L
'\\');
301 wcscpy(GuiData
->szProcessName
, ptr
);
303 swprintf(szBuffer
, L
"Console%s",ptr
);
304 DPRINT("#1 Path : %S\n", szBuffer
);
308 if (RegCreateKeyW(hKey
, szBuffer
, hSubKey
) == ERROR_SUCCESS
)
317 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
324 * try the "Shortcut to processname" as path
325 * FIXME: detect wheter the process was started as a shortcut
328 swprintf(szBuffer
, L
"Console\\Shortcut to %S", ptr
);
329 DPRINT("#2 Path : %S\n", szBuffer
);
330 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
332 swprintf(GuiData
->szProcessName
, L
"Shortcut to %S", ptr
);
338 * if the path contains \\Device\\HarddiskVolume1\... remove it
341 if (szProcessName
[0] == L
'\\')
343 dwBitmask
= GetLogicalDrives();
348 dwLength
= QueryDosDeviceW(CurDrive
, szBuffer
, MAX_PATH
);
351 if (!memcmp(szBuffer
, szProcessName
, (dwLength
-2)*sizeof(WCHAR
)))
353 wcscpy(szProcessName
, CurDrive
);
354 RtlMoveMemory(&szProcessName
[2], &szProcessName
[dwLength
-1], fLength
- dwLength
-1);
359 dwBitmask
= (dwBitmask
>> 1);
365 * last attempt: check whether the file is under %SystemRoot%
366 * and use path like Console\%SystemRoot%_dir_dir2_file.exe
369 wLength
= GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
372 if (!wcsncmp(szProcessName
, szBuffer
, wLength
))
374 /* replace slashes by underscores */
375 while((ptr
= wcschr(szProcessName
, L
'\\')))
378 swprintf(szBuffer
, L
"Console\\%%SystemRoot%%%S", &szProcessName
[wLength
]);
379 DPRINT("#3 Path : %S\n", szBuffer
);
380 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
382 swprintf(GuiData
->szProcessName
, L
"%%SystemRoot%%%S", &szProcessName
[wLength
]);
393 GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
)
396 PCSRSS_PROCESS_DATA ProcessData
;
398 if (Console
->ProcessList
.Flink
== &Console
->ProcessList
)
400 DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
403 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
404 if (!GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
| KEY_WRITE
, TRUE
))
409 if (Console
->ActiveBuffer
->CursorInfo
.dwSize
<= 1)
411 RegDeleteKeyW(hKey
, L
"CursorSize");
415 RegSetValueExW(hKey
, L
"CursorSize", 0, REG_DWORD
, (const BYTE
*)&Console
->ActiveBuffer
->CursorInfo
.dwSize
, sizeof(DWORD
));
418 if (GuiData
->NumberOfHistoryBuffers
== 5)
420 RegDeleteKeyW(hKey
, L
"NumberOfHistoryBuffers");
424 RegSetValueExW(hKey
, L
"NumberOfHistoryBuffers", 0, REG_DWORD
, (const BYTE
*)&GuiData
->NumberOfHistoryBuffers
, sizeof(DWORD
));
427 if (GuiData
->HistoryBufferSize
== 50)
429 RegDeleteKeyW(hKey
, L
"HistoryBufferSize");
433 RegSetValueExW(hKey
, L
"HistoryBufferSize", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryBufferSize
, sizeof(DWORD
));
436 if (GuiData
->FullScreen
== FALSE
)
438 RegDeleteKeyW(hKey
, L
"FullScreen");
442 RegSetValueExW(hKey
, L
"FullScreen", 0, REG_DWORD
, (const BYTE
*)&GuiData
->FullScreen
, sizeof(DWORD
));
445 if ( GuiData
->QuickEdit
== FALSE
)
447 RegDeleteKeyW(hKey
, L
"QuickEdit");
451 RegSetValueExW(hKey
, L
"QuickEdit", 0, REG_DWORD
, (const BYTE
*)&GuiData
->QuickEdit
, sizeof(DWORD
));
454 if (GuiData
->InsertMode
== TRUE
)
456 RegDeleteKeyW(hKey
, L
"InsertMode");
460 RegSetValueExW(hKey
, L
"InsertMode", 0, REG_DWORD
, (const BYTE
*)&GuiData
->InsertMode
, sizeof(DWORD
));
463 if (GuiData
->HistoryNoDup
== FALSE
)
465 RegDeleteKeyW(hKey
, L
"HistoryNoDup");
469 RegSetValueExW(hKey
, L
"HistoryNoDup", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryNoDup
, sizeof(DWORD
));
472 if (GuiData
->ScreenText
== RGB(192, 192, 192))
475 * MS uses console attributes instead of real color
477 RegDeleteKeyW(hKey
, L
"ScreenText");
481 RegSetValueExW(hKey
, L
"ScreenText", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenText
, sizeof(COLORREF
));
484 if (GuiData
->ScreenBackground
== RGB(0, 0, 0))
486 RegDeleteKeyW(hKey
, L
"ScreenBackground");
490 RegSetValueExW(hKey
, L
"ScreenBackground", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenBackground
, sizeof(COLORREF
));
497 GuiConsoleReadUserSettings(HKEY hKey
, PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
499 DWORD dwNumSubKeys
= 0;
504 WCHAR szValueName
[MAX_PATH
];
505 WCHAR szValue
[LF_FACESIZE
] = L
"\0";
508 if (RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
510 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
514 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
516 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
518 dwValue
= sizeof(Value
);
519 dwValueName
= MAX_PATH
;
521 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
523 if (dwType
== REG_SZ
)
526 * retry in case of string value
528 dwValue
= sizeof(szValue
);
529 dwValueName
= LF_FACESIZE
;
530 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
536 if (!wcscmp(szValueName
, L
"CursorSize"))
540 Buffer
->CursorInfo
.dwSize
= Value
;
542 else if (Value
== 0x64)
544 Buffer
->CursorInfo
.dwSize
= Value
;
547 else if (!wcscmp(szValueName
, L
"ScreenText"))
549 GuiData
->ScreenText
= Value
;
551 else if (!wcscmp(szValueName
, L
"ScreenBackground"))
553 GuiData
->ScreenBackground
= Value
;
555 else if (!wcscmp(szValueName
, L
"FaceName"))
557 wcscpy(GuiData
->FontName
, szValue
);
559 else if (!wcscmp(szValueName
, L
"FontSize"))
561 GuiData
->FontSize
= Value
;
563 else if (!wcscmp(szValueName
, L
"FontWeight"))
565 GuiData
->FontWeight
= Value
;
567 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
569 GuiData
->HistoryNoDup
= Value
;
571 else if (!wcscmp(szValueName
, L
"WindowSize"))
573 Console
->Size
.X
= LOWORD(Value
);
574 Console
->Size
.Y
= HIWORD(Value
);
576 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
580 Buffer
->MaxX
= LOWORD(Value
);
581 Buffer
->MaxY
= HIWORD(Value
);
584 else if (!wcscmp(szValueName
, L
"FullScreen"))
586 GuiData
->FullScreen
= Value
;
588 else if (!wcscmp(szValueName
, L
"QuickEdit"))
590 GuiData
->QuickEdit
= Value
;
592 else if (!wcscmp(szValueName
, L
"InsertMode"))
594 GuiData
->InsertMode
= Value
;
599 GuiConsoleUseDefaults(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
602 * init guidata with default properties
605 wcscpy(GuiData
->FontName
, L
"DejaVu Sans Mono");
606 GuiData
->FontSize
= 0x0008000C; // font is 8x12
607 GuiData
->FontWeight
= FW_NORMAL
;
608 GuiData
->HistoryNoDup
= FALSE
;
609 GuiData
->FullScreen
= FALSE
;
610 GuiData
->QuickEdit
= FALSE
;
611 GuiData
->InsertMode
= TRUE
;
612 GuiData
->HistoryBufferSize
= 50;
613 GuiData
->NumberOfHistoryBuffers
= 5;
614 GuiData
->ScreenText
= RGB(192, 192, 192);
615 GuiData
->ScreenBackground
= RGB(0, 0, 0);
616 GuiData
->PopupText
= RGB(128, 0, 128);
617 GuiData
->PopupBackground
= RGB(255, 255, 255);
618 GuiData
->WindowPosition
= UINT_MAX
;
619 GuiData
->UseRasterFonts
= TRUE
;
620 memcpy(GuiData
->Colors
, s_Colors
, sizeof(s_Colors
));
622 Console
->Size
.X
= 80;
623 Console
->Size
.Y
= 25;
629 Buffer
->CursorInfo
.bVisible
= TRUE
;
630 Buffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
636 GuiConsoleInitScrollbar(PCSRSS_CONSOLE Console
, HWND hwnd
)
639 PGUI_CONSOLE_DATA GuiData
= Console
->PrivateData
;
641 DWORD Width
= Console
->Size
.X
* GuiData
->CharWidth
+ 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
642 DWORD Height
= Console
->Size
.Y
* GuiData
->CharHeight
+ 2 * GetSystemMetrics(SM_CYFIXEDFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
644 /* set scrollbar sizes */
645 sInfo
.cbSize
= sizeof(SCROLLINFO
);
646 sInfo
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
648 if (Console
->ActiveBuffer
->MaxY
> Console
->Size
.Y
)
650 sInfo
.nMax
= Console
->ActiveBuffer
->MaxY
- 1;
651 sInfo
.nPage
= Console
->Size
.Y
;
652 sInfo
.nPos
= Console
->ActiveBuffer
->ShowY
;
653 SetScrollInfo(hwnd
, SB_VERT
, &sInfo
, TRUE
);
654 Width
+= GetSystemMetrics(SM_CXVSCROLL
);
655 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
659 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
662 if (Console
->ActiveBuffer
->MaxX
> Console
->Size
.X
)
664 sInfo
.nMax
= Console
->ActiveBuffer
->MaxX
- 1;
665 sInfo
.nPage
= Console
->Size
.X
;
666 sInfo
.nPos
= Console
->ActiveBuffer
->ShowX
;
667 SetScrollInfo(hwnd
, SB_HORZ
, &sInfo
, TRUE
);
668 Height
+= GetSystemMetrics(SM_CYHSCROLL
);
669 ShowScrollBar(hwnd
, SB_HORZ
, TRUE
);
673 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
676 SetWindowPos(hwnd
, NULL
, 0, 0, Width
, Height
,
677 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
681 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
683 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
684 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Console
->PrivateData
;
689 PCSRSS_PROCESS_DATA ProcessData
;
692 Console
->hWindow
= hWnd
;
696 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
700 GuiConsoleUseDefaults(Console
, GuiData
, Console
->ActiveBuffer
);
701 if (Console
->ProcessList
.Flink
!= &Console
->ProcessList
)
703 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
704 if (GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
, FALSE
))
706 GuiConsoleReadUserSettings(hKey
, Console
, GuiData
, Console
->ActiveBuffer
);
711 InitializeCriticalSection(&GuiData
->Lock
);
713 GuiData
->LineBuffer
= (PWCHAR
)HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
714 Console
->Size
.X
* sizeof(WCHAR
));
716 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->FontSize
),
717 0, //HIWORD(GuiData->FontSize),
725 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
726 NONANTIALIASED_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
728 if (NULL
== GuiData
->Font
)
730 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
731 DeleteCriticalSection(&GuiData
->Lock
);
732 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
738 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
739 DeleteObject(GuiData
->Font
);
740 DeleteCriticalSection(&GuiData
->Lock
);
741 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
744 OldFont
= SelectObject(Dc
, GuiData
->Font
);
747 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
749 DeleteObject(GuiData
->Font
);
750 DeleteCriticalSection(&GuiData
->Lock
);
751 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
754 if (! GetTextMetricsW(Dc
, &Metrics
))
756 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
757 SelectObject(Dc
, OldFont
);
759 DeleteObject(GuiData
->Font
);
760 DeleteCriticalSection(&GuiData
->Lock
);
761 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
764 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
765 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
767 /* Measure real char width more precisely if possible. */
768 if (GetTextExtentPoint32W(Dc
, L
"R", 1, &CharSize
))
769 GuiData
->CharWidth
= CharSize
.cx
;
771 SelectObject(Dc
, OldFont
);
774 GuiData
->CursorBlinkOn
= TRUE
;
775 GuiData
->ForceCursorOff
= FALSE
;
777 GuiData
->Selection
.left
= -1;
778 DPRINT("Console %p GuiData %p\n", Console
, GuiData
);
779 Console
->PrivateData
= GuiData
;
780 SetWindowLongPtrW(hWnd
, GWL_USERDATA
, (DWORD_PTR
) Console
);
782 SetTimer(hWnd
, 1, CURSOR_BLINK_TIME
, NULL
);
783 GuiConsoleCreateSysMenu(Console
);
784 GuiConsoleInitScrollbar(Console
, hWnd
);
785 SetEvent(GuiData
->hGuiInitEvent
);
787 return (BOOL
) DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
) Create
);
791 GuiConsoleUpdateSelection(HWND hWnd
, PRECT rc
, PGUI_CONSOLE_DATA GuiData
)
793 RECT oldRect
= GuiData
->Selection
;
797 RECT changeRect
= *rc
;
799 GuiData
->Selection
= *rc
;
801 changeRect
.left
*= GuiData
->CharWidth
;
802 changeRect
.top
*= GuiData
->CharHeight
;
803 changeRect
.right
*= GuiData
->CharWidth
;
804 changeRect
.bottom
*= GuiData
->CharHeight
;
806 if(rc
->left
!= oldRect
.left
||
807 rc
->top
!= oldRect
.top
||
808 rc
->right
!= oldRect
.right
||
809 rc
->bottom
!= oldRect
.bottom
)
811 if(oldRect
.left
!= -1)
815 oldRect
.left
*= GuiData
->CharWidth
;
816 oldRect
.top
*= GuiData
->CharHeight
;
817 oldRect
.right
*= GuiData
->CharWidth
;
818 oldRect
.bottom
*= GuiData
->CharHeight
;
820 /* calculate the region that needs to be updated */
821 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
823 if((rgn2
= CreateRectRgnIndirect(&changeRect
)))
825 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
827 InvalidateRgn(hWnd
, rgn1
, FALSE
);
837 InvalidateRect(hWnd
, &changeRect
, FALSE
);
841 else if(oldRect
.left
!= -1)
843 /* clear the selection */
844 GuiData
->Selection
.left
= -1;
845 oldRect
.left
*= GuiData
->CharWidth
;
846 oldRect
.top
*= GuiData
->CharHeight
;
847 oldRect
.right
*= GuiData
->CharWidth
;
848 oldRect
.bottom
*= GuiData
->CharHeight
;
849 InvalidateRect(hWnd
, &oldRect
, FALSE
);
855 GuiConsolePaint(PCSRSS_CONSOLE Console
,
856 PGUI_CONSOLE_DATA GuiData
,
860 PCSRSS_SCREEN_BUFFER Buff
;
861 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
862 ULONG Line
, Char
, Start
;
865 BYTE LastAttribute
, Attribute
;
866 ULONG CursorX
, CursorY
, CursorHeight
;
867 HBRUSH CursorBrush
, OldBrush
;
870 Buff
= Console
->ActiveBuffer
;
872 EnterCriticalSection(&Buff
->Header
.Lock
);
874 TopLine
= rc
->top
/ GuiData
->CharHeight
+ Buff
->ShowY
;
875 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1 + Buff
->ShowY
;
876 LeftChar
= rc
->left
/ GuiData
->CharWidth
+ Buff
->ShowX
;
877 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1 + Buff
->ShowX
;
878 LastAttribute
= ConioCoordToPointer(Buff
, LeftChar
, TopLine
)[1];
880 SetTextColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, LastAttribute
));
881 SetBkColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, LastAttribute
>> 4));
883 if (BottomLine
>= Buff
->MaxY
) BottomLine
= Buff
->MaxY
- 1;
884 if (RightChar
>= Buff
->MaxX
) RightChar
= Buff
->MaxX
- 1;
886 OldFont
= SelectObject(hDC
,
889 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
891 From
= ConioCoordToPointer(Buff
, LeftChar
, Line
);
893 To
= GuiData
->LineBuffer
;
895 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
897 if (*(From
+ 1) != LastAttribute
)
900 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
901 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
905 To
= GuiData
->LineBuffer
;
906 Attribute
= *(From
+ 1);
907 if (Attribute
!= LastAttribute
)
909 SetTextColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, Attribute
));
910 SetBkColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, Attribute
>> 4));
911 LastAttribute
= Attribute
;
915 MultiByteToWideChar(Console
->OutputCodePage
,
926 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
927 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
929 RightChar
- Start
+ 1);
932 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
&&
933 !GuiData
->ForceCursorOff
)
935 CursorX
= Buff
->CurrentX
;
936 CursorY
= Buff
->CurrentY
;
937 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
938 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
940 CursorHeight
= (GuiData
->CharHeight
* Buff
->CursorInfo
.dwSize
) / 100;
941 if (CursorHeight
< 1)
945 From
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
) + 1;
947 if (*From
!= DEFAULT_ATTRIB
)
949 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(GuiData
, *From
));
953 CursorBrush
= CreateSolidBrush(GuiData
->ScreenText
);
956 OldBrush
= SelectObject(hDC
,
959 (CursorX
- Buff
->ShowX
) * GuiData
->CharWidth
,
960 (CursorY
- Buff
->ShowY
) * GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
966 DeleteObject(CursorBrush
);
970 LeaveCriticalSection(&Buff
->Header
.Lock
);
977 GuiConsoleHandlePaint(HWND hWnd
, HDC hDCPaint
)
981 PCSRSS_CONSOLE Console
;
982 PGUI_CONSOLE_DATA GuiData
;
984 hDC
= BeginPaint(hWnd
, &ps
);
986 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
987 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
989 GuiConsoleGetDataPointers(hWnd
,
992 if (Console
!= NULL
&& GuiData
!= NULL
&&
993 Console
->ActiveBuffer
!= NULL
)
995 if (Console
->ActiveBuffer
->Buffer
!= NULL
)
997 EnterCriticalSection(&GuiData
->Lock
);
999 GuiConsolePaint(Console
,
1004 if (GuiData
->Selection
.left
!= -1)
1006 RECT rc
= GuiData
->Selection
;
1008 rc
.left
*= GuiData
->CharWidth
;
1009 rc
.top
*= GuiData
->CharHeight
;
1010 rc
.right
*= GuiData
->CharWidth
;
1011 rc
.bottom
*= GuiData
->CharHeight
;
1013 /* invert the selection */
1014 if (IntersectRect(&rc
,
1027 LeaveCriticalSection(&GuiData
->Lock
);
1032 EndPaint(hWnd
, &ps
);
1035 static VOID FASTCALL
1036 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1038 PCSRSS_CONSOLE Console
;
1039 PGUI_CONSOLE_DATA GuiData
;
1042 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1043 Message
.hwnd
= hWnd
;
1044 Message
.message
= msg
;
1045 Message
.wParam
= wParam
;
1046 Message
.lParam
= lParam
;
1048 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
1050 /* clear the selection */
1051 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
1054 ConioProcessKey(&Message
, Console
, FALSE
);
1057 static VOID FASTCALL
1058 GuiIntDrawRegion(PCSRSS_SCREEN_BUFFER Buff
, PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, RECT
*Region
)
1062 RegionRect
.left
= (Region
->left
- Buff
->ShowX
) * GuiData
->CharWidth
;
1063 RegionRect
.top
= (Region
->top
- Buff
->ShowY
) * GuiData
->CharHeight
;
1064 RegionRect
.right
= (Region
->right
+ 1 - Buff
->ShowX
) * GuiData
->CharWidth
;
1065 RegionRect
.bottom
= (Region
->bottom
+ 1 - Buff
->ShowY
) * GuiData
->CharHeight
;
1067 InvalidateRect(Wnd
, &RegionRect
, FALSE
);
1071 GuiDrawRegion(PCSRSS_CONSOLE Console
, RECT
*Region
)
1073 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1075 if (NULL
!= Console
->hWindow
&& NULL
!= GuiData
)
1077 GuiIntDrawRegion(Console
->ActiveBuffer
, GuiData
, Console
->hWindow
, Region
);
1081 static VOID FASTCALL
1082 GuiInvalidateCell(PCSRSS_SCREEN_BUFFER Buff
, PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, UINT x
, UINT y
)
1089 CellRect
.bottom
= y
;
1091 GuiIntDrawRegion(Buff
, GuiData
, Wnd
, &CellRect
);
1095 GuiWriteStream(PCSRSS_CONSOLE Console
, RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
1096 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
1098 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1099 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1100 LONG CursorEndX
, CursorEndY
;
1103 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
1108 if (0 != ScrolledLines
)
1110 ScrollRect
.left
= 0;
1112 ScrollRect
.right
= Console
->Size
.X
* GuiData
->CharWidth
;
1113 ScrollRect
.bottom
= Region
->top
* GuiData
->CharHeight
;
1115 if (GuiData
->Selection
.left
!= -1)
1117 /* scroll the selection */
1118 if (GuiData
->Selection
.top
> ScrolledLines
)
1120 GuiData
->Selection
.top
-= ScrolledLines
;
1121 GuiData
->Selection
.bottom
-= ScrolledLines
;
1123 else if (GuiData
->Selection
.bottom
< ScrolledLines
)
1125 GuiData
->Selection
.left
= -1;
1129 GuiData
->Selection
.top
= 0;
1130 GuiData
->Selection
.bottom
-= ScrolledLines
;
1134 ScrollWindowEx(Console
->hWindow
,
1136 -(ScrolledLines
* GuiData
->CharHeight
),
1144 GuiIntDrawRegion(Buff
, GuiData
, Console
->hWindow
, Region
);
1146 if (CursorStartX
< Region
->left
|| Region
->right
< CursorStartX
1147 || CursorStartY
< Region
->top
|| Region
->bottom
< CursorStartY
)
1149 GuiInvalidateCell(Buff
, GuiData
, Console
->hWindow
, CursorStartX
, CursorStartY
);
1152 CursorEndX
= Buff
->CurrentX
;
1153 CursorEndY
= Buff
->CurrentY
;
1154 if ((CursorEndX
< Region
->left
|| Region
->right
< CursorEndX
1155 || CursorEndY
< Region
->top
|| Region
->bottom
< CursorEndY
)
1156 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
1158 GuiInvalidateCell(Buff
, GuiData
, Console
->hWindow
, CursorEndX
, CursorEndY
);
1163 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1167 if (Console
->ActiveBuffer
== Buff
)
1169 UpdateRect
.left
= Buff
->CurrentX
;
1170 UpdateRect
.top
= Buff
->CurrentY
;
1171 UpdateRect
.right
= UpdateRect
.left
;
1172 UpdateRect
.bottom
= UpdateRect
.top
;
1173 ConioDrawRegion(Console
, &UpdateRect
);
1180 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
1184 if (Console
->ActiveBuffer
== Buff
)
1186 /* Redraw char at old position (removes cursor) */
1187 UpdateRect
.left
= OldCursorX
;
1188 UpdateRect
.top
= OldCursorY
;
1189 UpdateRect
.right
= OldCursorX
;
1190 UpdateRect
.bottom
= OldCursorY
;
1191 ConioDrawRegion(Console
, &UpdateRect
);
1192 /* Redraw char at new position (shows cursor) */
1193 UpdateRect
.left
= Buff
->CurrentX
;
1194 UpdateRect
.top
= Buff
->CurrentY
;
1195 UpdateRect
.right
= UpdateRect
.left
;
1196 UpdateRect
.bottom
= UpdateRect
.top
;
1197 ConioDrawRegion(Console
, &UpdateRect
);
1204 GuiUpdateScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1206 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1208 if (Console
->ActiveBuffer
== Buff
)
1210 GuiData
->ScreenText
= GuiConsoleRGBFromAttribute(GuiData
, Buff
->DefaultAttrib
);
1211 GuiData
->ScreenBackground
= GuiConsoleRGBFromAttribute(GuiData
, Buff
->DefaultAttrib
>> 4);
1217 static VOID FASTCALL
1218 GuiConsoleHandleTimer(HWND hWnd
)
1220 PCSRSS_CONSOLE Console
;
1221 PGUI_CONSOLE_DATA GuiData
;
1224 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1225 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
1227 CursorRect
.left
= Console
->ActiveBuffer
->CurrentX
;
1228 CursorRect
.top
= Console
->ActiveBuffer
->CurrentY
;
1229 CursorRect
.right
= CursorRect
.left
;
1230 CursorRect
.bottom
= CursorRect
.top
;
1231 GuiDrawRegion(Console
, &CursorRect
);
1234 static VOID FASTCALL
1235 GuiConsoleHandleClose(HWND hWnd
)
1237 PCSRSS_CONSOLE Console
;
1238 PGUI_CONSOLE_DATA GuiData
;
1239 PLIST_ENTRY current_entry
;
1240 PCSRSS_PROCESS_DATA current
;
1242 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1244 EnterCriticalSection(&Console
->Header
.Lock
);
1246 current_entry
= Console
->ProcessList
.Flink
;
1247 while (current_entry
!= &Console
->ProcessList
)
1249 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1250 current_entry
= current_entry
->Flink
;
1252 /* FIXME: Windows will wait up to 5 seconds for the thread to exit.
1253 * We shouldn't wait here, though, since the console lock is entered.
1254 * A copy of the thread list probably needs to be made. */
1255 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
1258 LeaveCriticalSection(&Console
->Header
.Lock
);
1261 static VOID FASTCALL
1262 GuiConsoleHandleNcDestroy(HWND hWnd
)
1264 PCSRSS_CONSOLE Console
;
1265 PGUI_CONSOLE_DATA GuiData
;
1268 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1270 Console
->PrivateData
= NULL
;
1271 DeleteCriticalSection(&GuiData
->Lock
);
1272 GetSystemMenu(hWnd
, TRUE
);
1273 if (GuiData
->ConsoleLibrary
)
1274 FreeLibrary(GuiData
->ConsoleLibrary
);
1276 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
1279 static VOID FASTCALL
1280 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
1282 PCSRSS_CONSOLE Console
;
1283 PGUI_CONSOLE_DATA GuiData
;
1287 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1288 if (Console
== NULL
|| GuiData
== NULL
) return;
1290 pt
= MAKEPOINTS(lParam
);
1292 rc
.left
= pt
.x
/ GuiData
->CharWidth
;
1293 rc
.top
= pt
.y
/ GuiData
->CharHeight
;
1294 rc
.right
= rc
.left
+ 1;
1295 rc
.bottom
= rc
.top
+ 1;
1297 GuiData
->SelectionStart
.x
= rc
.left
;
1298 GuiData
->SelectionStart
.y
= rc
.top
;
1302 GuiData
->MouseDown
= TRUE
;
1304 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1307 static VOID FASTCALL
1308 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
1310 PCSRSS_CONSOLE Console
;
1311 PGUI_CONSOLE_DATA GuiData
;
1315 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1316 if (Console
== NULL
|| GuiData
== NULL
) return;
1317 if (GuiData
->Selection
.left
== -1 || !GuiData
->MouseDown
) return;
1319 pt
= MAKEPOINTS(lParam
);
1321 rc
.left
= GuiData
->SelectionStart
.x
;
1322 rc
.top
= GuiData
->SelectionStart
.y
;
1323 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
1324 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
1326 /* exchange left/top with right/bottom if required */
1327 if(rc
.left
>= rc
.right
)
1331 rc
.left
= max(rc
.right
- 1, 0);
1334 if(rc
.top
>= rc
.bottom
)
1338 rc
.top
= max(rc
.bottom
- 1, 0);
1339 rc
.bottom
= tmp
+ 1;
1342 GuiData
->MouseDown
= FALSE
;
1344 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1349 static VOID FASTCALL
1350 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1352 PCSRSS_CONSOLE Console
;
1353 PGUI_CONSOLE_DATA GuiData
;
1357 if (!(wParam
& MK_LBUTTON
)) return;
1359 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1360 if (Console
== NULL
|| GuiData
== NULL
|| !GuiData
->MouseDown
) return;
1362 pt
= MAKEPOINTS(lParam
);
1364 rc
.left
= GuiData
->SelectionStart
.x
;
1365 rc
.top
= GuiData
->SelectionStart
.y
;
1366 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
1367 if (Console
->Size
.X
< rc
.right
)
1369 rc
.right
= Console
->Size
.X
;
1371 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
1372 if (Console
->Size
.Y
< rc
.bottom
)
1374 rc
.bottom
= Console
->Size
.Y
;
1377 /* exchange left/top with right/bottom if required */
1378 if(rc
.left
>= rc
.right
)
1382 rc
.left
= max(rc
.right
- 1, 0);
1385 if(rc
.top
>= rc
.bottom
)
1389 rc
.top
= max(rc
.bottom
- 1, 0);
1390 rc
.bottom
= tmp
+ 1;
1393 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
1396 static VOID FASTCALL
1397 GuiConsoleRightMouseDown(HWND hWnd
)
1399 PCSRSS_CONSOLE Console
;
1400 PGUI_CONSOLE_DATA GuiData
;
1402 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1403 if (Console
== NULL
|| GuiData
== NULL
) return;
1405 if (GuiData
->Selection
.left
== -1)
1407 /* FIXME - paste text from clipboard */
1411 /* FIXME - copy selection to clipboard */
1413 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
1420 GuiConsoleShowConsoleProperties(HWND hWnd
, BOOL Defaults
, PGUI_CONSOLE_DATA GuiData
)
1422 PCSRSS_CONSOLE Console
;
1423 APPLET_PROC CPLFunc
;
1424 TCHAR szBuffer
[MAX_PATH
];
1425 ConsoleInfo SharedInfo
;
1427 DPRINT("GuiConsoleShowConsoleProperties entered\n");
1429 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1431 if (GuiData
== NULL
)
1433 DPRINT("GuiConsoleGetDataPointers failed\n");
1437 if (GuiData
->ConsoleLibrary
== NULL
)
1439 GetWindowsDirectory(szBuffer
,MAX_PATH
);
1440 _tcscat(szBuffer
, _T("\\system32\\console.dll"));
1441 GuiData
->ConsoleLibrary
= LoadLibrary(szBuffer
);
1443 if (GuiData
->ConsoleLibrary
== NULL
)
1445 DPRINT1("failed to load console.dll");
1450 CPLFunc
= (APPLET_PROC
) GetProcAddress(GuiData
->ConsoleLibrary
, _T("CPlApplet"));
1453 DPRINT("Error: Console.dll misses CPlApplet export\n");
1458 SharedInfo
.InsertMode
= GuiData
->InsertMode
;
1459 SharedInfo
.HistoryBufferSize
= GuiData
->HistoryBufferSize
;
1460 SharedInfo
.NumberOfHistoryBuffers
= GuiData
->NumberOfHistoryBuffers
;
1461 SharedInfo
.ScreenText
= GuiData
->ScreenText
;
1462 SharedInfo
.ScreenBackground
= GuiData
->ScreenBackground
;
1463 SharedInfo
.PopupText
= GuiData
->PopupText
;
1464 SharedInfo
.PopupBackground
= GuiData
->PopupBackground
;
1465 SharedInfo
.WindowSize
= (DWORD
)MAKELONG(Console
->Size
.X
, Console
->Size
.Y
);
1466 SharedInfo
.WindowPosition
= GuiData
->WindowPosition
;
1467 SharedInfo
.ScreenBuffer
= (DWORD
)MAKELONG(Console
->ActiveBuffer
->MaxX
, Console
->ActiveBuffer
->MaxY
);
1468 SharedInfo
.UseRasterFonts
= GuiData
->UseRasterFonts
;
1469 SharedInfo
.FontSize
= (DWORD
)GuiData
->FontSize
;
1470 SharedInfo
.FontWeight
= GuiData
->FontWeight
;
1471 SharedInfo
.CursorSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1472 SharedInfo
.HistoryNoDup
= GuiData
->HistoryNoDup
;
1473 SharedInfo
.FullScreen
= GuiData
->FullScreen
;
1474 SharedInfo
.QuickEdit
= GuiData
->QuickEdit
;
1475 memcpy(&SharedInfo
.Colors
[0], GuiData
->Colors
, sizeof(s_Colors
));
1477 if (!CPLFunc(hWnd
, CPL_INIT
, 0, 0))
1479 DPRINT("Error: failed to initialize console.dll\n");
1483 if (CPLFunc(hWnd
, CPL_GETCOUNT
, 0, 0) != 1)
1485 DPRINT("Error: console.dll returned unexpected CPL count\n");
1489 CPLFunc(hWnd
, CPL_DBLCLK
, (LPARAM
)&SharedInfo
, Defaults
);
1491 static LRESULT FASTCALL
1492 GuiConsoleHandleSysMenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
, PGUI_CONSOLE_DATA GuiData
)
1498 case ID_SYSTEM_EDIT_MARK
:
1499 case ID_SYSTEM_EDIT_COPY
:
1500 case ID_SYSTEM_EDIT_PASTE
:
1501 case ID_SYSTEM_EDIT_SELECTALL
:
1502 case ID_SYSTEM_EDIT_SCROLL
:
1503 case ID_SYSTEM_EDIT_FIND
:
1506 case ID_SYSTEM_DEFAULTS
:
1507 GuiConsoleShowConsoleProperties(hWnd
, TRUE
, GuiData
);
1510 case ID_SYSTEM_PROPERTIES
:
1511 GuiConsoleShowConsoleProperties(hWnd
, FALSE
, GuiData
);
1515 Ret
= DefWindowProcW(hWnd
, WM_SYSCOMMAND
, wParam
, lParam
);
1521 static VOID FASTCALL
1522 GuiConsoleResize(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1524 PCSRSS_CONSOLE Console
;
1525 PGUI_CONSOLE_DATA GuiData
;
1527 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1528 if (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
)
1530 DPRINT1("GuiConsoleResize X %d Y %d\n", LOWORD(lParam
), HIWORD(lParam
));
1535 GuiConsoleHandleScrollbarMenu()
1539 hMenu
= CreatePopupMenu();
1542 DPRINT("CreatePopupMenu failed\n");
1545 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1546 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1547 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1548 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1549 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1550 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1551 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1552 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1553 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1554 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1558 static VOID FASTCALL
1559 GuiApplyUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PConsoleInfo pConInfo
)
1562 PCSRSS_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
1563 BOOL SizeChanged
= FALSE
;
1565 EnterCriticalSection(&ActiveBuffer
->Header
.Lock
);
1567 /* apply text / background color */
1568 GuiData
->ScreenText
= pConInfo
->ScreenText
;
1569 GuiData
->ScreenBackground
= pConInfo
->ScreenBackground
;
1571 /* apply cursor size */
1572 ActiveBuffer
->CursorInfo
.dwSize
= min(max(pConInfo
->CursorSize
, 1), 100);
1574 windx
= LOWORD(pConInfo
->ScreenBuffer
);
1575 windy
= HIWORD(pConInfo
->ScreenBuffer
);
1577 if (windx
!= ActiveBuffer
->MaxX
|| windy
!= ActiveBuffer
->MaxY
)
1579 BYTE
* Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, windx
* windy
* 2);
1591 value
= MAKEWORD(' ', ActiveBuffer
->DefaultAttrib
);
1593 DPRINT("MaxX %d MaxY %d windx %d windy %d value %04x DefaultAttrib %d\n",ActiveBuffer
->MaxX
, ActiveBuffer
->MaxY
, windx
, windy
, value
, ActiveBuffer
->DefaultAttrib
);
1594 OldBuffer
= ActiveBuffer
->Buffer
;
1596 for (CurrentY
= 0; CurrentY
< min(ActiveBuffer
->MaxY
, windy
); CurrentY
++)
1598 OldPtr
= ConioCoordToPointer(ActiveBuffer
, 0, CurrentY
);
1599 if (windx
<= ActiveBuffer
->MaxX
)
1602 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, windx
* 2);
1603 Offset
+= (windx
* 2);
1608 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, ActiveBuffer
->MaxX
* 2);
1609 Offset
+= (ActiveBuffer
->MaxX
* 2);
1611 diff
= windx
- ActiveBuffer
->MaxX
;
1612 /* zero new part of it */
1614 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
);
1616 for (i
= 0; i
< diff
; i
++)
1618 Buffer
[Offset
++] = ' ';
1619 Buffer
[Offset
++] = ActiveBuffer
->DefaultAttrib
;
1625 if (windy
> ActiveBuffer
->MaxY
)
1627 diff
= windy
- ActiveBuffer
->MaxY
;
1629 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
* windx
);
1631 for (i
= 0; i
< diff
* windx
; i
++)
1633 Buffer
[Offset
++] = ' ';
1634 Buffer
[Offset
++] = ActiveBuffer
->DefaultAttrib
;
1639 (void)InterlockedExchangePointer((PVOID
volatile *)&ActiveBuffer
->Buffer
, Buffer
);
1640 HeapFree(Win32CsrApiHeap
, 0, OldBuffer
);
1641 ActiveBuffer
->MaxX
= windx
;
1642 ActiveBuffer
->MaxY
= windy
;
1643 ActiveBuffer
->VirtualY
= 0;
1648 LeaveCriticalSection(&ActiveBuffer
->Header
.Lock
);
1653 windx
= LOWORD(pConInfo
->WindowSize
);
1654 windy
= HIWORD(pConInfo
->WindowSize
);
1656 if (windx
> Console
->Size
.X
)
1658 PWCHAR LineBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, windx
* sizeof(WCHAR
));
1661 HeapFree(Win32CsrApiHeap
, 0, GuiData
->LineBuffer
);
1662 GuiData
->LineBuffer
= LineBuffer
;
1666 LeaveCriticalSection(&ActiveBuffer
->Header
.Lock
);
1672 if (windx
!= Console
->Size
.X
|| windy
!= Console
->Size
.Y
)
1675 Console
->Size
.X
= windx
;
1676 Console
->Size
.Y
= windy
;
1682 GuiConsoleInitScrollbar(Console
, pConInfo
->hConsoleWindow
);
1685 LeaveCriticalSection(&ActiveBuffer
->Header
.Lock
);
1686 InvalidateRect(pConInfo
->hConsoleWindow
, NULL
, TRUE
);
1691 GuiConsoleHandleScroll(HWND hwnd
, UINT uMsg
, WPARAM wParam
)
1693 PCSRSS_CONSOLE Console
;
1694 PCSRSS_SCREEN_BUFFER Buff
;
1695 PGUI_CONSOLE_DATA GuiData
;
1698 int old_pos
, Maximum
;
1701 GuiConsoleGetDataPointers(hwnd
, &Console
, &GuiData
);
1702 if (Console
== NULL
|| GuiData
== NULL
)
1704 Buff
= Console
->ActiveBuffer
;
1706 if (uMsg
== WM_HSCROLL
)
1709 Maximum
= Buff
->MaxX
- Console
->Size
.X
;
1710 pShowXY
= &Buff
->ShowX
;
1715 Maximum
= Buff
->MaxY
- Console
->Size
.Y
;
1716 pShowXY
= &Buff
->ShowY
;
1719 /* set scrollbar sizes */
1720 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1721 sInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_PAGE
| SIF_TRACKPOS
;
1723 if (!GetScrollInfo(hwnd
, fnBar
, &sInfo
))
1728 old_pos
= sInfo
.nPos
;
1730 switch(LOWORD(wParam
))
1741 sInfo
.nPos
-= sInfo
.nPage
;
1745 sInfo
.nPos
+= sInfo
.nPage
;
1749 sInfo
.nPos
= sInfo
.nTrackPos
;
1753 sInfo
.nPos
= sInfo
.nMin
;
1757 sInfo
.nPos
= sInfo
.nMax
;
1764 sInfo
.nPos
= max(sInfo
.nPos
, 0);
1765 sInfo
.nPos
= min(sInfo
.nPos
, Maximum
);
1767 if (old_pos
!= sInfo
.nPos
)
1769 USHORT OldX
= Buff
->ShowX
;
1770 USHORT OldY
= Buff
->ShowY
;
1771 *pShowXY
= sInfo
.nPos
;
1773 ScrollWindowEx(hwnd
,
1774 (OldX
- Buff
->ShowX
) * GuiData
->CharWidth
,
1775 (OldY
- Buff
->ShowY
) * GuiData
->CharHeight
,
1782 sInfo
.fMask
= SIF_POS
;
1783 SetScrollInfo(hwnd
, fnBar
, &sInfo
, TRUE
);
1790 static LRESULT CALLBACK
1791 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1794 PGUI_CONSOLE_DATA GuiData
= NULL
;
1795 PCSRSS_CONSOLE Console
= NULL
;
1797 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1802 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
1805 GuiConsoleHandlePaint(hWnd
, (HDC
)wParam
);
1812 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
1815 GuiConsoleHandleTimer(hWnd
);
1818 GuiConsoleHandleClose(hWnd
);
1821 GuiConsoleHandleNcDestroy(hWnd
);
1823 case WM_LBUTTONDOWN
:
1824 GuiConsoleLeftMouseDown(hWnd
, lParam
);
1827 GuiConsoleLeftMouseUp(hWnd
, lParam
);
1829 case WM_RBUTTONDOWN
:
1830 GuiConsoleRightMouseDown(hWnd
);
1833 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
1836 Result
= GuiConsoleHandleSysMenuCommand(hWnd
, wParam
, lParam
, GuiData
);
1840 Result
= GuiConsoleHandleScroll(hWnd
, msg
, wParam
);
1843 GuiConsoleResize(hWnd
, wParam
, lParam
);
1845 case PM_APPLY_CONSOLE_INFO
:
1846 GuiApplyUserSettings(Console
, GuiData
, (PConsoleInfo
)wParam
);
1849 GuiConsoleWriteUserSettings(Console
, GuiData
);
1853 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1860 static LRESULT CALLBACK
1861 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1866 PWCHAR Buffer
, Title
;
1867 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
1874 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
1876 case PM_CREATE_CONSOLE
:
1877 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
1878 Console
->Title
.Length
+ sizeof(WCHAR
));
1881 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
1882 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
1889 NewWindow
= CreateWindowW(L
"ConsoleWindowClass",
1891 WS_OVERLAPPED
| WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_HSCROLL
| WS_VSCROLL
, //WS_OVERLAPPEDWINDOW
1898 (HINSTANCE
) GetModuleHandleW(NULL
),
1902 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1904 if (NULL
!= NewWindow
)
1906 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
1907 ShowWindow(NewWindow
, SW_SHOW
);
1909 return (LRESULT
) NewWindow
;
1910 case PM_DESTROY_CONSOLE
:
1911 /* Window creation is done using a PostMessage(), so it's possible that the
1912 * window that we want to destroy doesn't exist yet. So first empty the message
1914 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
1916 TranslateMessage(&Msg
);
1917 DispatchMessageW(&Msg
);
1919 DestroyWindow(Console
->hWindow
);
1920 Console
->hWindow
= NULL
;
1921 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
1923 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
1924 if (0 == WindowCount
)
1927 DestroyWindow(hWnd
);
1928 PrivateCsrssManualGuiCheck(-1);
1933 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1938 GuiConsoleGuiThread(PVOID Data
)
1941 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
1943 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
1945 WS_OVERLAPPEDWINDOW
,
1952 (HINSTANCE
) GetModuleHandleW(NULL
),
1954 if (NULL
== NotifyWnd
)
1956 PrivateCsrssManualGuiCheck(-1);
1957 SetEvent(*GraphicsStartupEvent
);
1961 SetEvent(*GraphicsStartupEvent
);
1963 while(GetMessageW(&msg
, NULL
, 0, 0))
1965 TranslateMessage(&msg
);
1966 DispatchMessageW(&msg
);
1972 static BOOL FASTCALL
1977 if (NULL
== NotifyWnd
)
1979 PrivateCsrssManualGuiCheck(+1);
1982 wc
.cbSize
= sizeof(WNDCLASSEXW
);
1983 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
1984 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
1986 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
1989 wc
.hbrBackground
= NULL
;
1990 wc
.lpszMenuName
= NULL
;
1994 if (RegisterClassExW(&wc
) == 0)
1996 DPRINT1("Failed to register notify wndproc\n");
2000 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2001 wc
.lpszClassName
= L
"ConsoleWindowClass";
2002 wc
.lpfnWndProc
= GuiConsoleWndProc
;
2004 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
2005 wc
.hIcon
= LoadIconW(GetModuleHandleW(L
"win32csr"), MAKEINTRESOURCEW(1));
2006 wc
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
) IDC_ARROW
);
2007 wc
.hbrBackground
= CreateSolidBrush(RGB(0,0,0));
2008 wc
.lpszMenuName
= NULL
;
2011 wc
.hIconSm
= LoadImageW(GetModuleHandleW(L
"win32csr"), MAKEINTRESOURCEW(1), IMAGE_ICON
,
2012 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
2014 if (RegisterClassExW(&wc
) == 0)
2016 DPRINT1("Failed to register console wndproc\n");
2024 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
2026 Buffer
->DefaultAttrib
= DEFAULT_ATTRIB
;
2030 GuiChangeTitle(PCSRSS_CONSOLE Console
)
2032 PWCHAR Buffer
, Title
;
2034 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
2035 Console
->Title
.Length
+ sizeof(WCHAR
));
2038 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
2039 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
2047 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
) Title
);
2051 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
2058 GuiChangeIcon(PCSRSS_CONSOLE Console
, HICON hWindowIcon
)
2060 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)hWindowIcon
);
2061 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)hWindowIcon
);
2067 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
2069 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
) Console
);
2072 static CSRSS_CONSOLE_VTBL GuiVtbl
=
2074 GuiInitScreenBuffer
,
2079 GuiUpdateScreenInfo
,
2086 GuiInitConsole(PCSRSS_CONSOLE Console
)
2088 HANDLE GraphicsStartupEvent
;
2089 HANDLE ThreadHandle
;
2090 PGUI_CONSOLE_DATA GuiData
;
2092 if (! ConsInitialized
)
2094 ConsInitialized
= TRUE
;
2097 ConsInitialized
= FALSE
;
2098 return STATUS_UNSUCCESSFUL
;
2102 Console
->Vtbl
= &GuiVtbl
;
2103 if (NULL
== NotifyWnd
)
2105 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2106 if (NULL
== GraphicsStartupEvent
)
2108 return STATUS_UNSUCCESSFUL
;
2111 ThreadHandle
= CreateThread(NULL
,
2113 GuiConsoleGuiThread
,
2114 (PVOID
) &GraphicsStartupEvent
,
2117 if (NULL
== ThreadHandle
)
2119 NtClose(GraphicsStartupEvent
);
2120 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
2121 return STATUS_UNSUCCESSFUL
;
2123 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
2124 CloseHandle(ThreadHandle
);
2126 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
2127 CloseHandle(GraphicsStartupEvent
);
2129 if (NULL
== NotifyWnd
)
2131 DPRINT1("Win32Csr: Failed to create notification window.\n");
2132 return STATUS_UNSUCCESSFUL
;
2135 GuiData
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
2136 sizeof(GUI_CONSOLE_DATA
));
2139 DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
2140 return STATUS_UNSUCCESSFUL
;
2143 Console
->PrivateData
= (PVOID
) GuiData
;
2145 * we need to wait untill the GUI has been fully initialized
2146 * to retrieve custom settings i.e. WindowSize etc..
2147 * Ideally we could use SendNotifyMessage for this but its not
2151 GuiData
->hGuiInitEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2152 /* create console */
2153 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, 0, (LPARAM
) Console
);
2155 /* wait untill initialization has finished */
2156 WaitForSingleObject(GuiData
->hGuiInitEvent
, INFINITE
);
2157 DPRINT1("received event Console %p GuiData %p X %d Y %d\n", Console
, Console
->PrivateData
, Console
->Size
.X
, Console
->Size
.Y
);
2158 CloseHandle(GuiData
->hGuiInitEvent
);
2159 GuiData
->hGuiInitEvent
= NULL
;
2161 return STATUS_SUCCESS
;