xref: /reactos/dll/cpl/console/console.c (revision 57d6853c)
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@student.tugraz.at)
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.FullScreen = FALSE;
97     pConInfo->ci.QuickEdit = FALSE;
98     pConInfo->ci.InsertMode = TRUE;
99     // pConInfo->ci.InputBufferSize;
100     pConInfo->ci.ScreenBufferSize = (COORD){80, 300};
101     pConInfo->ci.ConsoleSize      = (COORD){80, 25 };
102     pConInfo->ci.CursorBlinkOn = TRUE;
103     pConInfo->ci.ForceCursorOff = FALSE;
104     pConInfo->ci.CursorSize = CSR_DEFAULT_CURSOR_SIZE;
105     pConInfo->ci.ScreenAttrib = DEFAULT_SCREEN_ATTRIB;
106     pConInfo->ci.PopupAttrib  = DEFAULT_POPUP_ATTRIB;
107     pConInfo->ci.CodePage = 0;
108     pConInfo->ci.ConsoleTitle[0] = L'\0';
109 
110     /* Adapted for holding GUI terminal information */
111     pConInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
112     GuiInfo = pConInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pConInfo + 1);
113     wcsncpy(GuiInfo->FaceName, L"Fixedsys", LF_FACESIZE); // HACK: !!
114     // GuiInfo->FaceName[0] = L'\0';
115     GuiInfo->FontFamily = FF_DONTCARE;
116     GuiInfo->FontSize = 0;
117     GuiInfo->FontWeight = FW_DONTCARE;
118     GuiInfo->UseRasterFonts = TRUE;
119 
120     GuiInfo->AutoPosition = TRUE;
121     GuiInfo->WindowOrigin = (POINT){0, 0};
122 
123     memcpy(pConInfo->ci.Colors, s_Colors, sizeof(s_Colors));
124 }
125 
126 INT_PTR
127 CALLBACK
128 ApplyProc(HWND hwndDlg,
129           UINT uMsg,
130           WPARAM wParam,
131           LPARAM lParam)
132 {
133     HWND hDlgCtrl;
134 
135     UNREFERENCED_PARAMETER(lParam);
136 
137     switch (uMsg)
138     {
139         case WM_INITDIALOG:
140         {
141             hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_APPLY_CURRENT);
142             SendMessage(hDlgCtrl, BM_SETCHECK, BST_CHECKED, 0);
143             return TRUE;
144         }
145         case WM_COMMAND:
146         {
147             if (LOWORD(wParam) == IDOK)
148             {
149                 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_APPLY_CURRENT);
150                 if (SendMessage(hDlgCtrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
151                     EndDialog(hwndDlg, IDC_RADIO_APPLY_CURRENT);
152                 else
153                     EndDialog(hwndDlg, IDC_RADIO_APPLY_ALL);
154             }
155             else if (LOWORD(wParam) == IDCANCEL)
156             {
157                 EndDialog(hwndDlg, IDCANCEL);
158             }
159             break;
160         }
161         default:
162             break;
163     }
164 
165     return FALSE;
166 }
167 
168 BOOL
169 ApplyConsoleInfo(HWND hwndDlg,
170                  PCONSOLE_PROPS pConInfo)
171 {
172     BOOL SetParams  = FALSE;
173     BOOL SaveParams = FALSE;
174 
175     /*
176      * If we are setting the default parameters, just save them,
177      * otherwise display the save-confirmation dialog.
178      */
179     if (pConInfo->ShowDefaultParams)
180     {
181         SetParams  = TRUE;
182         SaveParams = TRUE;
183     }
184     else
185     {
186         INT_PTR res = DialogBox(hApplet, MAKEINTRESOURCE(IDD_APPLYOPTIONS), hwndDlg, ApplyProc);
187 
188         SetParams  = (res != IDCANCEL);
189         SaveParams = (res == IDC_RADIO_APPLY_ALL);
190 
191         if (SetParams == FALSE)
192         {
193             /* Don't destroy when user presses cancel */
194             SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
195             // return TRUE;
196         }
197     }
198 
199     if (SetParams)
200     {
201         HANDLE hSection;
202         PCONSOLE_PROPS pSharedInfo;
203 
204         /*
205          * Create a memory section to share with the server, and map it.
206          */
207         /* Holds data for console.dll + console info + terminal-specific info */
208         hSection = CreateFileMapping(INVALID_HANDLE_VALUE,
209                                      NULL,
210                                      PAGE_READWRITE,
211                                      0,
212                                      sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO),
213                                      NULL);
214         if (!hSection)
215         {
216             DPRINT1("Error when creating file mapping, error = %d\n", GetLastError());
217             return FALSE;
218         }
219 
220         pSharedInfo = MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS, 0, 0, 0);
221         if (!pSharedInfo)
222         {
223             DPRINT1("Error when mapping view of file, error = %d\n", GetLastError());
224             CloseHandle(hSection);
225             return FALSE;
226         }
227 
228         /* We are applying the chosen configuration */
229         pConInfo->AppliedConfig = TRUE;
230 
231         /*
232          * Copy the console information into the section and
233          * offsetize the address of terminal-specific information.
234          * Do not perform the offsetization in pConInfo as it is
235          * likely to be reused later on. Instead, do it in pSharedInfo
236          * after having copied all the data.
237          */
238         RtlCopyMemory(pSharedInfo, pConInfo, sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
239         pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pConInfo->TerminalInfo.TermInfo - (ULONG_PTR)pConInfo);
240 
241         /* Unmap it */
242         UnmapViewOfFile(pSharedInfo);
243 
244         /* Signal to the console server that it can apply the new configuration */
245         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
246         SendMessage(pConInfo->hConsoleWindow,
247                     PM_APPLY_CONSOLE_INFO,
248                     (WPARAM)hSection,
249                     (LPARAM)SaveParams);
250 
251         /* Close the section and return */
252         CloseHandle(hSection);
253     }
254 
255     return TRUE;
256 }
257 
258 /* First Applet */
259 LONG APIENTRY
260 InitApplet(HWND hWnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
261 {
262     HANDLE hSection = (HANDLE)wParam;
263     BOOL GuiTermInfo = FALSE;
264     PCONSOLE_PROPS pSharedInfo;
265     PCONSOLE_PROPS pConInfo;
266     WCHAR szTitle[MAX_PATH + 1];
267     PROPSHEETPAGE psp[4];
268     PROPSHEETHEADER psh;
269     INT i = 0;
270 
271     UNREFERENCED_PARAMETER(uMsg);
272 
273     /*
274      * CONSOLE.DLL shares information with CONSRV with wParam:
275      * wParam is a handle to a shared section holding a CONSOLE_PROPS struct.
276      *
277      * NOTE: lParam is not used.
278      */
279 
280     /* Allocate a local buffer to hold console information */
281     pConInfo = AllocConsoleInfo();
282     if (!pConInfo) return 0;
283 
284     /* Map the shared section */
285     pSharedInfo = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
286     if (pSharedInfo == NULL)
287     {
288         HeapFree(GetProcessHeap(), 0, pConInfo);
289         return 0;
290     }
291 
292     /* Find the console window and whether we must use default parameters */
293     pConInfo->hConsoleWindow    = pSharedInfo->hConsoleWindow;
294     pConInfo->ShowDefaultParams = pSharedInfo->ShowDefaultParams;
295 
296     /* Check that we are going to modify GUI terminal information */
297     GuiTermInfo = ( pSharedInfo->TerminalInfo.Size == sizeof(GUI_CONSOLE_INFO) &&
298                     pSharedInfo->TerminalInfo.TermInfo != 0 );
299 
300     if (pConInfo->ShowDefaultParams || !GuiTermInfo)
301     {
302         /* Use defaults */
303         InitConsoleDefaults(pConInfo);
304     }
305     else
306     {
307         /*
308          * Copy the shared data into our allocated buffer, and
309          * de-offsetize the address of terminal-specific information.
310          */
311         RtlCopyMemory(pConInfo, pSharedInfo, sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
312         pConInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)pConInfo->TerminalInfo.TermInfo);
313     }
314 
315     /* Close the section */
316     UnmapViewOfFile(pSharedInfo);
317     CloseHandle(hSection);
318 
319     /* Initialize the property sheet structure */
320     ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
321     psh.dwSize = sizeof(PROPSHEETHEADER);
322     psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | /* PSH_USEHICON */ PSH_USEICONID | PSH_NOAPPLYNOW;
323 
324     if (pConInfo->ci.ConsoleTitle[0] != L'\0')
325     {
326         wcsncpy(szTitle, L"\"", sizeof(szTitle) / sizeof(szTitle[0]));
327         wcsncat(szTitle, pConInfo->ci.ConsoleTitle, sizeof(szTitle) / sizeof(szTitle[0]));
328         wcsncat(szTitle, L"\"", sizeof(szTitle) / sizeof(szTitle[0]));
329     }
330     else
331     {
332         wcscpy(szTitle, L"ReactOS Console");
333     }
334     psh.pszCaption = szTitle;
335 
336     psh.hwndParent = pConInfo->hConsoleWindow;
337     psh.hInstance = hApplet;
338     // psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON));
339     psh.pszIcon = MAKEINTRESOURCE(IDC_CPLICON);
340     psh.nPages = 4;
341     psh.nStartPage = 0;
342     psh.ppsp = psp;
343 
344     InitPropSheetPage(&psp[i++], IDD_PROPPAGEOPTIONS, (DLGPROC) OptionsProc, (LPARAM)pConInfo);
345     InitPropSheetPage(&psp[i++], IDD_PROPPAGEFONT, (DLGPROC) FontProc, (LPARAM)pConInfo);
346     InitPropSheetPage(&psp[i++], IDD_PROPPAGELAYOUT, (DLGPROC) LayoutProc, (LPARAM)pConInfo);
347     InitPropSheetPage(&psp[i++], IDD_PROPPAGECOLORS, (DLGPROC) ColorsProc, (LPARAM)pConInfo);
348 
349     return (PropertySheet(&psh) != -1);
350 }
351 
352 /* Control Panel Callback */
353 LONG CALLBACK
354 CPlApplet(HWND hwndCPl,
355           UINT uMsg,
356           LPARAM lParam1,
357           LPARAM lParam2)
358 {
359     switch (uMsg)
360     {
361         case CPL_INIT:
362             return TRUE;
363 
364         case CPL_EXIT:
365             // TODO: Free allocated memory
366             break;
367 
368         case CPL_GETCOUNT:
369             return NUM_APPLETS;
370 
371         case CPL_INQUIRE:
372         {
373             CPLINFO *CPlInfo = (CPLINFO*)lParam2;
374             CPlInfo->idIcon = Applets[0].idIcon;
375             CPlInfo->idName = Applets[0].idName;
376             CPlInfo->idInfo = Applets[0].idDescription;
377             break;
378         }
379 
380         case CPL_DBLCLK:
381             InitApplet(hwndCPl, uMsg, lParam1, lParam2);
382             break;
383     }
384 
385     return FALSE;
386 }
387 
388 
389 INT
390 WINAPI
391 DllMain(HINSTANCE hinstDLL,
392         DWORD     dwReason,
393         LPVOID    lpvReserved)
394 {
395     UNREFERENCED_PARAMETER(lpvReserved);
396 
397     switch (dwReason)
398     {
399         case DLL_PROCESS_ATTACH:
400         case DLL_THREAD_ATTACH:
401             hApplet = hinstDLL;
402             break;
403     }
404 
405     return TRUE;
406 }
407