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