* Sync up to trunk head (r64959).
[reactos.git] / dll / cpl / console / console.c
1 /*
2 * PROJECT: ReactOS Console Configuration DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/console/console.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 #include "console.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #define NUM_APPLETS 1
16
17 LONG APIENTRY InitApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam);
18 INT_PTR CALLBACK OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
19 INT_PTR CALLBACK FontProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
20 INT_PTR CALLBACK LayoutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
21 INT_PTR CALLBACK ColorsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
22
23 HINSTANCE hApplet = 0;
24
25 /* Applets */
26 APPLET Applets[NUM_APPLETS] =
27 {
28 {IDC_CPLICON, IDS_CPLNAME, IDS_CPLDESCRIPTION, InitApplet}
29 };
30
31 /*
32 * Default 16-color palette for foreground and background
33 * (corresponding flags in comments).
34 */
35 const COLORREF s_Colors[16] =
36 {
37 RGB(0, 0, 0), // (Black)
38 RGB(0, 0, 128), // BLUE
39 RGB(0, 128, 0), // GREEN
40 RGB(0, 128, 128), // BLUE | GREEN
41 RGB(128, 0, 0), // RED
42 RGB(128, 0, 128), // BLUE | RED
43 RGB(128, 128, 0), // GREEN | RED
44 RGB(192, 192, 192), // BLUE | GREEN | RED
45
46 RGB(128, 128, 128), // (Grey) INTENSITY
47 RGB(0, 0, 255), // BLUE | INTENSITY
48 RGB(0, 255, 0), // GREEN | INTENSITY
49 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
50 RGB(255, 0, 0), // RED | INTENSITY
51 RGB(255, 0, 255), // BLUE | RED | INTENSITY
52 RGB(255, 255, 0), // GREEN | RED | INTENSITY
53 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
54 };
55 /* Default attributes */
56 #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
57 #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \
58 BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
59 /* Cursor size */
60 #define CSR_DEFAULT_CURSOR_SIZE 25
61
62 static VOID
63 InitPropSheetPage(PROPSHEETPAGEW *psp,
64 WORD idDlg,
65 DLGPROC DlgProc,
66 LPARAM lParam)
67 {
68 ZeroMemory(psp, sizeof(PROPSHEETPAGEW));
69 psp->dwSize = sizeof(PROPSHEETPAGEW);
70 psp->dwFlags = PSP_DEFAULT;
71 psp->hInstance = hApplet;
72 psp->pszTemplate = MAKEINTRESOURCEW(idDlg);
73 psp->pfnDlgProc = DlgProc;
74 psp->lParam = lParam;
75 }
76
77 PCONSOLE_PROPS
78 AllocConsoleInfo()
79 {
80 /* Adapted for holding GUI terminal information */
81 return HeapAlloc(GetProcessHeap(),
82 HEAP_ZERO_MEMORY,
83 sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
84 }
85
86 VOID
87 InitConsoleDefaults(PCONSOLE_PROPS pConInfo)
88 {
89 PGUI_CONSOLE_INFO GuiInfo = NULL;
90
91 /* FIXME: Get also the defaults from the registry */
92
93 /* Initialize the default properties */
94 pConInfo->ci.HistoryBufferSize = 50;
95 pConInfo->ci.NumberOfHistoryBuffers = 4;
96 pConInfo->ci.HistoryNoDup = FALSE;
97 pConInfo->ci.QuickEdit = FALSE;
98 pConInfo->ci.InsertMode = TRUE;
99 // pConInfo->ci.InputBufferSize;
100 pConInfo->ci.ScreenBufferSize.X = 80;
101 pConInfo->ci.ScreenBufferSize.Y = 300;
102 pConInfo->ci.ConsoleSize.X = 80;
103 pConInfo->ci.ConsoleSize.Y = 25;
104 pConInfo->ci.CursorBlinkOn = TRUE;
105 pConInfo->ci.ForceCursorOff = FALSE;
106 pConInfo->ci.CursorSize = CSR_DEFAULT_CURSOR_SIZE;
107 pConInfo->ci.ScreenAttrib = DEFAULT_SCREEN_ATTRIB;
108 pConInfo->ci.PopupAttrib = DEFAULT_POPUP_ATTRIB;
109 pConInfo->ci.CodePage = 0;
110 pConInfo->ci.ConsoleTitle[0] = L'\0';
111
112 /* Adapted for holding GUI terminal information */
113 pConInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
114 GuiInfo = pConInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pConInfo + 1);
115 wcsncpy(GuiInfo->FaceName, L"VGA", LF_FACESIZE); // HACK: !!
116 // GuiInfo->FaceName[0] = L'\0';
117 GuiInfo->FontFamily = FF_DONTCARE;
118 GuiInfo->FontSize.X = 0;
119 GuiInfo->FontSize.Y = 0;
120 GuiInfo->FontWeight = FW_NORMAL; // HACK: !!
121 // GuiInfo->FontWeight = FW_DONTCARE;
122
123 GuiInfo->FullScreen = FALSE;
124 GuiInfo->ShowWindow = SW_SHOWNORMAL;
125 GuiInfo->AutoPosition = TRUE;
126 GuiInfo->WindowOrigin.x = 0;
127 GuiInfo->WindowOrigin.y = 0;
128
129 memcpy(pConInfo->ci.Colors, s_Colors, sizeof(s_Colors));
130 }
131
132 INT_PTR
133 CALLBACK
134 ApplyProc(HWND hwndDlg,
135 UINT uMsg,
136 WPARAM wParam,
137 LPARAM lParam)
138 {
139 UNREFERENCED_PARAMETER(lParam);
140
141 switch (uMsg)
142 {
143 case WM_INITDIALOG:
144 {
145 CheckDlgButton(hwndDlg, IDC_RADIO_APPLY_CURRENT, BST_CHECKED);
146 return TRUE;
147 }
148 case WM_COMMAND:
149 {
150 if (LOWORD(wParam) == IDOK)
151 {
152 if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_APPLY_CURRENT) == BST_CHECKED)
153 EndDialog(hwndDlg, IDC_RADIO_APPLY_CURRENT);
154 else
155 EndDialog(hwndDlg, IDC_RADIO_APPLY_ALL);
156 }
157 else if (LOWORD(wParam) == IDCANCEL)
158 {
159 EndDialog(hwndDlg, IDCANCEL);
160 }
161 break;
162 }
163 default:
164 break;
165 }
166
167 return FALSE;
168 }
169
170 BOOL
171 ApplyConsoleInfo(HWND hwndDlg,
172 PCONSOLE_PROPS pConInfo)
173 {
174 BOOL SetParams = FALSE;
175 BOOL SaveParams = FALSE;
176
177 /*
178 * If we are setting the default parameters, just save them,
179 * otherwise display the save-confirmation dialog.
180 */
181 if (pConInfo->ShowDefaultParams)
182 {
183 SetParams = TRUE;
184 SaveParams = TRUE;
185 }
186 else
187 {
188 INT_PTR res = DialogBoxW(hApplet, MAKEINTRESOURCEW(IDD_APPLYOPTIONS), hwndDlg, ApplyProc);
189
190 SetParams = (res != IDCANCEL);
191 SaveParams = (res == IDC_RADIO_APPLY_ALL);
192
193 if (SetParams == FALSE)
194 {
195 /* Don't destroy when user presses cancel */
196 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
197 // return TRUE;
198 }
199 }
200
201 if (SetParams)
202 {
203 HANDLE hSection;
204 PCONSOLE_PROPS pSharedInfo;
205
206 /*
207 * Create a memory section to share with the server, and map it.
208 */
209 /* Holds data for console.dll + console info + terminal-specific info */
210 hSection = CreateFileMappingW(INVALID_HANDLE_VALUE,
211 NULL,
212 PAGE_READWRITE,
213 0,
214 sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO),
215 NULL);
216 if (!hSection)
217 {
218 DPRINT1("Error when creating file mapping, error = %d\n", GetLastError());
219 return FALSE;
220 }
221
222 pSharedInfo = MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS, 0, 0, 0);
223 if (!pSharedInfo)
224 {
225 DPRINT1("Error when mapping view of file, error = %d\n", GetLastError());
226 CloseHandle(hSection);
227 return FALSE;
228 }
229
230 /* We are applying the chosen configuration */
231 pConInfo->AppliedConfig = TRUE;
232
233 /*
234 * Copy the console information into the section and
235 * offsetize the address of terminal-specific information.
236 * Do not perform the offsetization in pConInfo as it is
237 * likely to be reused later on. Instead, do it in pSharedInfo
238 * after having copied all the data.
239 */
240 RtlCopyMemory(pSharedInfo, pConInfo, sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
241 pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pConInfo->TerminalInfo.TermInfo - (ULONG_PTR)pConInfo);
242
243 /* Unmap it */
244 UnmapViewOfFile(pSharedInfo);
245
246 /* Signal to the console server that it can apply the new configuration */
247 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
248 SendMessage(pConInfo->hConsoleWindow,
249 PM_APPLY_CONSOLE_INFO,
250 (WPARAM)hSection,
251 (LPARAM)SaveParams);
252
253 /* Close the section and return */
254 CloseHandle(hSection);
255 }
256
257 return TRUE;
258 }
259
260 /* First Applet */
261 LONG APIENTRY
262 InitApplet(HWND hWnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
263 {
264 HANDLE hSection = (HANDLE)wParam;
265 PCONSOLE_PROPS pSharedInfo = NULL;
266 PCONSOLE_PROPS pConInfo;
267 WCHAR szTitle[MAX_PATH + 1];
268 PROPSHEETPAGEW psp[4];
269 PROPSHEETHEADERW psh;
270 INT i = 0;
271
272 UNREFERENCED_PARAMETER(uMsg);
273
274 /*
275 * CONSOLE.DLL shares information with CONSRV with wParam:
276 * wParam is a handle to a shared section holding a CONSOLE_PROPS struct.
277 *
278 * NOTE: lParam is not used.
279 */
280
281 /* Allocate a local buffer to hold console information */
282 pConInfo = AllocConsoleInfo();
283 if (!pConInfo) return 0;
284
285 /* Check whether we were launched from the terminal... */
286 if (hSection != NULL)
287 {
288 /* ... yes, map the shared section */
289 pSharedInfo = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
290 if (pSharedInfo == NULL)
291 {
292 /* Cleanup */
293 HeapFree(GetProcessHeap(), 0, pConInfo);
294
295 /* Close the section */
296 CloseHandle(hSection);
297
298 return 0;
299 }
300
301 /* Find the console window and whether we set the default parameters */
302 pConInfo->hConsoleWindow = pSharedInfo->hConsoleWindow;
303 pConInfo->ShowDefaultParams = pSharedInfo->ShowDefaultParams;
304 }
305 else
306 {
307 /* ... no, we were launched as a CPL. Display the default settings. */
308 pConInfo->ShowDefaultParams = TRUE;
309 }
310
311 if (pConInfo->ShowDefaultParams)
312 {
313 /* Use defaults */
314 InitConsoleDefaults(pConInfo);
315 }
316 else if (hSection && pSharedInfo)
317 {
318 /*
319 * Copy the shared data into our allocated buffer, and
320 * de-offsetize the address of terminal-specific information.
321 */
322
323 /* Check that we are really going to modify GUI terminal information */
324 // FIXME: Do something clever, for example copy the UI-independent part
325 // and init the UI-dependent part to some default values...
326 ASSERT(pSharedInfo->TerminalInfo.Size == sizeof(GUI_CONSOLE_INFO));
327 ASSERT(pSharedInfo->TerminalInfo.TermInfo);
328
329 RtlCopyMemory(pConInfo, pSharedInfo, sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
330 pConInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)pConInfo->TerminalInfo.TermInfo);
331 }
332
333 if (hSection && pSharedInfo)
334 {
335 /* Close the section */
336 UnmapViewOfFile(pSharedInfo);
337 CloseHandle(hSection);
338 }
339
340 /* Initialize the property sheet structure */
341 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
342 psh.dwSize = sizeof(PROPSHEETHEADERW);
343 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | /* PSH_USEHICON */ PSH_USEICONID | PSH_NOAPPLYNOW;
344
345 if (pConInfo->ci.ConsoleTitle[0] != L'\0')
346 {
347 wcsncpy(szTitle, L"\"", MAX_PATH);
348 wcsncat(szTitle, pConInfo->ci.ConsoleTitle, MAX_PATH - wcslen(szTitle));
349 wcsncat(szTitle, L"\"", MAX_PATH - wcslen(szTitle));
350 }
351 else
352 {
353 wcscpy(szTitle, L"ReactOS Console");
354 }
355 psh.pszCaption = szTitle;
356
357 psh.hwndParent = pConInfo->hConsoleWindow;
358 psh.hInstance = hApplet;
359 // psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCEW(IDC_CPLICON));
360 psh.pszIcon = MAKEINTRESOURCEW(IDC_CPLICON);
361 psh.nPages = 4;
362 psh.nStartPage = 0;
363 psh.ppsp = psp;
364
365 InitPropSheetPage(&psp[i++], IDD_PROPPAGEOPTIONS, (DLGPROC) OptionsProc, (LPARAM)pConInfo);
366 InitPropSheetPage(&psp[i++], IDD_PROPPAGEFONT , (DLGPROC) FontProc , (LPARAM)pConInfo);
367 InitPropSheetPage(&psp[i++], IDD_PROPPAGELAYOUT , (DLGPROC) LayoutProc , (LPARAM)pConInfo);
368 InitPropSheetPage(&psp[i++], IDD_PROPPAGECOLORS , (DLGPROC) ColorsProc , (LPARAM)pConInfo);
369
370 return (PropertySheetW(&psh) != -1);
371 }
372
373 /* Control Panel Callback */
374 LONG CALLBACK
375 CPlApplet(HWND hwndCPl,
376 UINT uMsg,
377 LPARAM lParam1,
378 LPARAM lParam2)
379 {
380 switch (uMsg)
381 {
382 case CPL_INIT:
383 return TRUE;
384
385 case CPL_EXIT:
386 // TODO: Free allocated memory
387 break;
388
389 case CPL_GETCOUNT:
390 return NUM_APPLETS;
391
392 case CPL_INQUIRE:
393 {
394 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
395 CPlInfo->idIcon = Applets[0].idIcon;
396 CPlInfo->idName = Applets[0].idName;
397 CPlInfo->idInfo = Applets[0].idDescription;
398 break;
399 }
400
401 case CPL_DBLCLK:
402 InitApplet(hwndCPl, uMsg, lParam1, lParam2);
403 break;
404 }
405
406 return FALSE;
407 }
408
409
410 INT
411 WINAPI
412 DllMain(HINSTANCE hinstDLL,
413 DWORD dwReason,
414 LPVOID lpvReserved)
415 {
416 UNREFERENCED_PARAMETER(lpvReserved);
417
418 switch (dwReason)
419 {
420 case DLL_PROCESS_ATTACH:
421 case DLL_THREAD_ATTACH:
422 hApplet = hinstDLL;
423 break;
424 }
425
426 return TRUE;
427 }