[ACPPAGE] Make use of the PCH.
[reactos.git] / dll / cpl / console / options.c
1 /*
2 * PROJECT: ReactOS Console Configuration DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/console/options.c
5 * PURPOSE: Options dialog
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 MAX_VALUE_NAME 16383
16
17
18 static INT
19 List_GetCount(IN PLIST_CTL ListCtl)
20 {
21 return (INT)SendMessageW(ListCtl->hWndList, CB_GETCOUNT, 0, 0);
22 }
23
24 static ULONG_PTR
25 List_GetData(IN PLIST_CTL ListCtl, IN INT Index)
26 {
27 return (ULONG_PTR)SendMessageW(ListCtl->hWndList, CB_GETITEMDATA, (WPARAM)Index, 0);
28 }
29
30 static VOID
31 AddCodePage(
32 IN PLIST_CTL ListCtl,
33 IN UINT CodePage)
34 {
35 UINT iItem, iDupItem;
36 CPINFOEXW CPInfo;
37
38 /*
39 * Add only valid code pages, that is:
40 * - If the CodePage is one of the reserved (alias) values:
41 * CP_ACP == 0 ; CP_OEMCP == 1 ; CP_MACCP == 2 ; CP_THREAD_ACP == 3 ;
42 * or the deprecated CP_SYMBOL == 42 (see http://archives.miloush.net/michkap/archive/2005/11/08/490495.html)
43 * it is considered invalid.
44 * - If IsValidCodePage() fails because the code page is listed but
45 * not installed on the system, it is also considered invalid.
46 */
47 if (CodePage == CP_ACP || CodePage == CP_OEMCP || CodePage == CP_MACCP ||
48 CodePage == CP_THREAD_ACP || CodePage == CP_SYMBOL || !IsValidCodePage(CodePage))
49 {
50 return;
51 }
52
53 /* Retrieve the code page display name */
54 if (!GetCPInfoExW(CodePage, 0, &CPInfo))
55 {
56 /* We failed, just use the code page value as its name */
57 // _ultow(CodePage, CPInfo.CodePageName, 10);
58 StringCchPrintfW(CPInfo.CodePageName, ARRAYSIZE(CPInfo.CodePageName), L"%lu", CodePage);
59 }
60
61 /* Add the code page into the list, sorted by code page value. Avoid any duplicates. */
62 iDupItem = CB_ERR;
63 iItem = BisectListSortedByValue(ListCtl, CodePage, &iDupItem, TRUE);
64 if (iItem == CB_ERR)
65 iItem = 0;
66 if (iDupItem != CB_ERR)
67 return;
68 iItem = (UINT)SendMessageW(ListCtl->hWndList, CB_INSERTSTRING, iItem, (LPARAM)CPInfo.CodePageName);
69 if (iItem != CB_ERR && iItem != CB_ERRSPACE)
70 iItem = SendMessageW(ListCtl->hWndList, CB_SETITEMDATA, iItem, CodePage);
71 }
72
73 static VOID
74 BuildCodePageList(
75 IN HWND hDlg)
76 {
77 LIST_CTL ListCtl;
78 HKEY hKey;
79 DWORD dwIndex, dwSize, dwType;
80 UINT CodePage;
81 WCHAR szValueName[MAX_VALUE_NAME];
82
83 // #define REGSTR_PATH_CODEPAGE TEXT("System\\CurrentControlSet\\Control\\Nls\\CodePage")
84 /* Open the Nls\CodePage key */
85 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
86 L"System\\CurrentControlSet\\Control\\Nls\\CodePage",
87 0,
88 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
89 &hKey) != ERROR_SUCCESS)
90 {
91 return;
92 }
93
94 ListCtl.hWndList = GetDlgItem(hDlg, IDL_CODEPAGE);
95 ListCtl.GetCount = List_GetCount;
96 ListCtl.GetData = List_GetData;
97
98 /* Enumerate all the available code pages on the system */
99 dwSize = ARRAYSIZE(szValueName);
100 dwIndex = 0;
101 while (RegEnumValueW(hKey, dwIndex, szValueName, &dwSize,
102 NULL, &dwType, NULL, NULL) == ERROR_SUCCESS) // != ERROR_NO_MORE_ITEMS
103 {
104 /* Ignore these parameters, prepare for next iteration */
105 dwSize = ARRAYSIZE(szValueName);
106 ++dwIndex;
107
108 /* Check the value type validity */
109 if (dwType != REG_SZ)
110 continue;
111
112 /*
113 * Add the code page into the list.
114 * If _wtol fails and returns 0, the code page is considered invalid
115 * (and indeed this value corresponds to the CP_ACP alias too).
116 */
117 CodePage = (UINT)_wtol(szValueName);
118 if (CodePage == 0) continue;
119 AddCodePage(&ListCtl, CodePage);
120 }
121
122 RegCloseKey(hKey);
123
124 /* Add the special UTF-7 (CP_UTF7 65000) and UTF-8 (CP_UTF8 65001) code pages */
125 AddCodePage(&ListCtl, CP_UTF7);
126 AddCodePage(&ListCtl, CP_UTF8);
127
128 /* Find and select the current code page in the sorted list */
129 if (BisectListSortedByValue(&ListCtl, ConInfo->CodePage, &CodePage, FALSE) == CB_ERR ||
130 CodePage == CB_ERR)
131 {
132 /* Not found, select the first element */
133 CodePage = 0;
134 }
135 SendMessageW(ListCtl.hWndList, CB_SETCURSEL, (WPARAM)CodePage, 0);
136 }
137
138 static VOID
139 UpdateDialogElements(
140 IN HWND hDlg,
141 IN PCONSOLE_STATE_INFO pConInfo)
142 {
143 /* Update the cursor size */
144 if (pConInfo->CursorSize <= 25)
145 {
146 /* Small cursor */
147 CheckRadioButton(hDlg, IDC_RADIO_SMALL_CURSOR, IDC_RADIO_LARGE_CURSOR, IDC_RADIO_SMALL_CURSOR);
148 // CheckDlgButton(hDlg, IDC_RADIO_SMALL_CURSOR , BST_CHECKED);
149 // CheckDlgButton(hDlg, IDC_RADIO_MEDIUM_CURSOR, BST_UNCHECKED);
150 // CheckDlgButton(hDlg, IDC_RADIO_LARGE_CURSOR , BST_UNCHECKED);
151 }
152 else if (pConInfo->CursorSize <= 50)
153 {
154 /* Medium cursor */
155 CheckRadioButton(hDlg, IDC_RADIO_SMALL_CURSOR, IDC_RADIO_LARGE_CURSOR, IDC_RADIO_MEDIUM_CURSOR);
156 // CheckDlgButton(hDlg, IDC_RADIO_SMALL_CURSOR , BST_UNCHECKED);
157 // CheckDlgButton(hDlg, IDC_RADIO_MEDIUM_CURSOR, BST_CHECKED);
158 // CheckDlgButton(hDlg, IDC_RADIO_LARGE_CURSOR , BST_UNCHECKED);
159 }
160 else /* if (pConInfo->CursorSize <= 100) */
161 {
162 /* Large cursor */
163 CheckRadioButton(hDlg, IDC_RADIO_SMALL_CURSOR, IDC_RADIO_LARGE_CURSOR, IDC_RADIO_LARGE_CURSOR);
164 // CheckDlgButton(hDlg, IDC_RADIO_SMALL_CURSOR , BST_UNCHECKED);
165 // CheckDlgButton(hDlg, IDC_RADIO_MEDIUM_CURSOR, BST_UNCHECKED);
166 // CheckDlgButton(hDlg, IDC_RADIO_LARGE_CURSOR , BST_CHECKED);
167 }
168
169 /* Update the number of history buffers */
170 SendDlgItemMessageW(hDlg, IDC_UPDOWN_NUM_BUFFER, UDM_SETRANGE, 0, MAKELONG(999, 1));
171 SetDlgItemInt(hDlg, IDC_EDIT_NUM_BUFFER, pConInfo->NumberOfHistoryBuffers, FALSE);
172
173 /* Update the history buffer size */
174 SendDlgItemMessageW(hDlg, IDC_UPDOWN_BUFFER_SIZE, UDM_SETRANGE, 0, MAKELONG(999, 1));
175 SetDlgItemInt(hDlg, IDC_EDIT_BUFFER_SIZE, pConInfo->HistoryBufferSize, FALSE);
176
177 /* Update discard duplicates */
178 CheckDlgButton(hDlg, IDC_CHECK_DISCARD_DUPLICATES,
179 pConInfo->HistoryNoDup ? BST_CHECKED : BST_UNCHECKED);
180
181 /* Update full/window screen state */
182 if (pConInfo->FullScreen)
183 {
184 CheckRadioButton(hDlg, IDC_RADIO_DISPLAY_WINDOW, IDC_RADIO_DISPLAY_FULL, IDC_RADIO_DISPLAY_FULL);
185 // CheckDlgButton(hDlg, IDC_RADIO_DISPLAY_WINDOW, BST_UNCHECKED);
186 // CheckDlgButton(hDlg, IDC_RADIO_DISPLAY_FULL , BST_CHECKED);
187 }
188 else
189 {
190 CheckRadioButton(hDlg, IDC_RADIO_DISPLAY_WINDOW, IDC_RADIO_DISPLAY_FULL, IDC_RADIO_DISPLAY_WINDOW);
191 // CheckDlgButton(hDlg, IDC_RADIO_DISPLAY_WINDOW, BST_CHECKED);
192 // CheckDlgButton(hDlg, IDC_RADIO_DISPLAY_FULL , BST_UNCHECKED);
193 }
194
195 /* Update "Quick-edit" state */
196 CheckDlgButton(hDlg, IDC_CHECK_QUICK_EDIT,
197 pConInfo->QuickEdit ? BST_CHECKED : BST_UNCHECKED);
198
199 /* Update "Insert mode" state */
200 CheckDlgButton(hDlg, IDC_CHECK_INSERT_MODE,
201 pConInfo->InsertMode ? BST_CHECKED : BST_UNCHECKED);
202 }
203
204 INT_PTR
205 CALLBACK
206 OptionsProc(HWND hDlg,
207 UINT uMsg,
208 WPARAM wParam,
209 LPARAM lParam)
210 {
211 switch (uMsg)
212 {
213 case WM_INITDIALOG:
214 {
215 BuildCodePageList(hDlg);
216 UpdateDialogElements(hDlg, ConInfo);
217 return TRUE;
218 }
219
220 case WM_NOTIFY:
221 {
222 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam;
223
224 if (lppsn->hdr.code == UDN_DELTAPOS)
225 {
226 LPNMUPDOWN lpnmud = (LPNMUPDOWN)lParam;
227
228 if (lppsn->hdr.idFrom == IDC_UPDOWN_BUFFER_SIZE)
229 {
230 lpnmud->iPos = min(max(lpnmud->iPos + lpnmud->iDelta, 1), 999);
231 ConInfo->HistoryBufferSize = lpnmud->iPos;
232 PropSheet_Changed(GetParent(hDlg), hDlg);
233 }
234 else if (lppsn->hdr.idFrom == IDC_UPDOWN_NUM_BUFFER)
235 {
236 lpnmud->iPos = min(max(lpnmud->iPos + lpnmud->iDelta, 1), 999);
237 ConInfo->NumberOfHistoryBuffers = lpnmud->iPos;
238 PropSheet_Changed(GetParent(hDlg), hDlg);
239 }
240 }
241 else if (lppsn->hdr.code == PSN_APPLY)
242 {
243 ApplyConsoleInfo(hDlg);
244 return TRUE;
245 }
246 break;
247 }
248
249 case WM_COMMAND:
250 {
251 if (HIWORD(wParam) == BN_CLICKED)
252 {
253 switch (LOWORD(wParam))
254 {
255 case IDC_RADIO_SMALL_CURSOR:
256 {
257 ConInfo->CursorSize = 25;
258 PropSheet_Changed(GetParent(hDlg), hDlg);
259 break;
260 }
261 case IDC_RADIO_MEDIUM_CURSOR:
262 {
263 ConInfo->CursorSize = 50;
264 PropSheet_Changed(GetParent(hDlg), hDlg);
265 break;
266 }
267 case IDC_RADIO_LARGE_CURSOR:
268 {
269 ConInfo->CursorSize = 100;
270 PropSheet_Changed(GetParent(hDlg), hDlg);
271 break;
272 }
273 case IDC_RADIO_DISPLAY_WINDOW:
274 {
275 ConInfo->FullScreen = FALSE;
276 PropSheet_Changed(GetParent(hDlg), hDlg);
277 break;
278 }
279 case IDC_RADIO_DISPLAY_FULL:
280 {
281 ConInfo->FullScreen = TRUE;
282 PropSheet_Changed(GetParent(hDlg), hDlg);
283 break;
284 }
285 case IDC_CHECK_QUICK_EDIT:
286 {
287 ConInfo->QuickEdit = (IsDlgButtonChecked(hDlg, IDC_CHECK_QUICK_EDIT) == BST_CHECKED); // BST_UNCHECKED or BST_INDETERMINATE => FALSE
288 PropSheet_Changed(GetParent(hDlg), hDlg);
289 break;
290 }
291 case IDC_CHECK_INSERT_MODE:
292 {
293 ConInfo->InsertMode = (IsDlgButtonChecked(hDlg, IDC_CHECK_INSERT_MODE) == BST_CHECKED); // BST_UNCHECKED or BST_INDETERMINATE => FALSE
294 PropSheet_Changed(GetParent(hDlg), hDlg);
295 break;
296 }
297 case IDC_CHECK_DISCARD_DUPLICATES:
298 {
299 ConInfo->HistoryNoDup = (IsDlgButtonChecked(hDlg, IDC_CHECK_DISCARD_DUPLICATES) == BST_CHECKED); // BST_UNCHECKED or BST_INDETERMINATE => FALSE
300 PropSheet_Changed(GetParent(hDlg), hDlg);
301 break;
302 }
303 }
304 }
305 else
306 if (HIWORD(wParam) == EN_KILLFOCUS)
307 {
308 switch (LOWORD(wParam))
309 {
310 case IDC_EDIT_BUFFER_SIZE:
311 {
312 DWORD sizeBuff;
313
314 sizeBuff = GetDlgItemInt(hDlg, IDC_EDIT_BUFFER_SIZE, NULL, FALSE);
315 sizeBuff = min(max(sizeBuff, 1), 999);
316
317 ConInfo->HistoryBufferSize = sizeBuff;
318 PropSheet_Changed(GetParent(hDlg), hDlg);
319 break;
320 }
321 case IDC_EDIT_NUM_BUFFER:
322 {
323 DWORD numBuff;
324
325 numBuff = GetDlgItemInt(hDlg, IDC_EDIT_NUM_BUFFER, NULL, FALSE);
326 numBuff = min(max(numBuff, 1), 999);
327
328 ConInfo->NumberOfHistoryBuffers = numBuff;
329 PropSheet_Changed(GetParent(hDlg), hDlg);
330 break;
331 }
332 }
333 }
334 else
335 if ((HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_SELENDOK) &&
336 (LOWORD(wParam) == IDL_CODEPAGE))
337 {
338 HWND hWndList = GetDlgItem(hDlg, IDL_CODEPAGE);
339 INT iItem;
340 UINT CodePage;
341
342 iItem = (INT)SendMessageW(hWndList, CB_GETCURSEL, 0, 0);
343 if (iItem == CB_ERR)
344 break;
345
346 CodePage = (UINT)SendMessageW(hWndList, CB_GETITEMDATA, iItem, 0);
347 if (CodePage == CB_ERR)
348 break;
349
350 ConInfo->CodePage = CodePage;
351
352 /* Change the property sheet state only if the user validated */
353 if (HIWORD(wParam) == CBN_SELENDOK)
354 PropSheet_Changed(GetParent(hDlg), hDlg);
355 }
356
357 break;
358 }
359
360 default:
361 break;
362 }
363
364 return FALSE;
365 }