input: Overwrite font substitutes settings on lang change
[reactos.git] / dll / cpl / input / settings_page.c
1 /*
2 * PROJECT: input.dll
3 * FILE: dll/cpl/input/settings_page.c
4 * PURPOSE: input.dll
5 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
6 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7 */
8
9 #include "input.h"
10 #include "layout_list.h"
11 #include "locale_list.h"
12 #include "input_list.h"
13
14
15 static HICON
16 CreateLayoutIcon(LPWSTR szLayout, BOOL bIsDefault)
17 {
18 INT width = GetSystemMetrics(SM_CXSMICON) * 2;
19 INT height = GetSystemMetrics(SM_CYSMICON);
20 HDC hdc;
21 HDC hdcsrc;
22 HBITMAP hBitmap;
23 HICON hIcon = NULL;
24
25 hdcsrc = GetDC(NULL);
26 hdc = CreateCompatibleDC(hdcsrc);
27 hBitmap = CreateCompatibleBitmap(hdcsrc, width, height);
28
29 ReleaseDC(NULL, hdcsrc);
30
31 if (hdc && hBitmap)
32 {
33 HBITMAP hBmpNew;
34
35 hBmpNew = CreateBitmap(width, height, 1, 1, NULL);
36 if (hBmpNew)
37 {
38 LOGFONTW lf;
39
40 if (SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
41 {
42 ICONINFO IconInfo;
43 HFONT hFont;
44
45 hFont = CreateFontIndirectW(&lf);
46
47 if (hFont != NULL)
48 {
49 HBITMAP hBmpOld;
50
51 hBmpOld = SelectObject(hdc, hBitmap);
52
53 if (hBmpOld != NULL)
54 {
55 RECT rect;
56
57 SetRect(&rect, 0, 0, width / 2, height);
58
59 if (bIsDefault != FALSE)
60 {
61 SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
62 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
63
64 ExtTextOutW(hdc, rect.left, rect.top, ETO_OPAQUE, &rect, L"", 0, NULL);
65
66 SelectObject(hdc, hFont);
67 DrawTextW(hdc, L"\x2022", 1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
68 }
69 else
70 {
71 FillRect(hdc, &rect, GetSysColorBrush(COLOR_WINDOW));
72 }
73
74 SetRect(&rect, width / 2, 0, width, height);
75
76 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
77 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
78
79 ExtTextOutW(hdc, rect.left, rect.top, ETO_OPAQUE, &rect, L"", 0, NULL);
80
81 SelectObject(hdc, hFont);
82 DrawTextW(hdc, szLayout, 2, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
83
84 SelectObject(hdc, hBmpNew);
85
86 PatBlt(hdc, 0, 0, width, height, BLACKNESS);
87
88 SelectObject(hdc, hBmpOld);
89
90 IconInfo.hbmColor = hBitmap;
91 IconInfo.hbmMask = hBmpNew;
92 IconInfo.fIcon = TRUE;
93
94 hIcon = CreateIconIndirect(&IconInfo);
95
96 DeleteObject(hBmpOld);
97 }
98
99 DeleteObject(hFont);
100 }
101 }
102
103 DeleteObject(hBmpNew);
104 }
105 }
106
107 DeleteDC(hdc);
108 DeleteObject(hBitmap);
109
110 return hIcon;
111 }
112
113
114 static VOID
115 SetControlsState(HWND hwndDlg, BOOL bIsEnabled)
116 {
117 EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE_BUTTON), bIsEnabled);
118 EnableWindow(GetDlgItem(hwndDlg, IDC_PROP_BUTTON), bIsEnabled);
119 EnableWindow(GetDlgItem(hwndDlg, IDC_SET_DEFAULT), bIsEnabled);
120 }
121
122
123 static VOID
124 AddToInputListView(HWND hwndList, INPUT_LIST_NODE *pInputNode)
125 {
126 INT ItemIndex = -1;
127 INT ImageIndex = -1;
128 LV_ITEM item;
129 HIMAGELIST hImageList;
130
131 hImageList = ListView_GetImageList(hwndList, LVSIL_SMALL);
132
133 if (hImageList != NULL)
134 {
135 HICON hLayoutIcon;
136
137 hLayoutIcon = CreateLayoutIcon(pInputNode->pszIndicator,
138 (pInputNode->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT));
139
140 if (hLayoutIcon != NULL)
141 {
142 ImageIndex = ImageList_AddIcon(hImageList, hLayoutIcon);
143 DestroyIcon(hLayoutIcon);
144 }
145 }
146
147 ZeroMemory(&item, sizeof(item));
148
149 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
150 item.pszText = pInputNode->pLocale->pszName;
151 item.iItem = ListView_GetItemCount(hwndList) + 1;
152 item.lParam = (LPARAM)pInputNode;
153 item.iImage = ImageIndex;
154
155 ItemIndex = ListView_InsertItem(hwndList, &item);
156
157 ListView_SetItemText(hwndList, ItemIndex, 1, pInputNode->pLayout->pszName);
158 }
159
160
161 static VOID
162 UpdateInputListView(HWND hwndList)
163 {
164 INPUT_LIST_NODE *pCurrentInputNode;
165 HIMAGELIST hImageList;
166
167 hImageList = ListView_GetImageList(hwndList, LVSIL_SMALL);
168 if (hImageList != NULL)
169 {
170 ImageList_RemoveAll(hImageList);
171 }
172
173 ListView_DeleteAllItems(hwndList);
174
175 for (pCurrentInputNode = InputList_GetFirst();
176 pCurrentInputNode != NULL;
177 pCurrentInputNode = pCurrentInputNode->pNext)
178 {
179 if (!(pCurrentInputNode->wFlags & INPUT_LIST_NODE_FLAG_DELETED))
180 {
181 AddToInputListView(hwndList, pCurrentInputNode);
182 }
183 }
184 }
185
186
187 static VOID
188 OnInitSettingsPage(HWND hwndDlg)
189 {
190 HWND hwndInputList;
191
192 LayoutList_Create();
193 LocaleList_Create();
194 InputList_Create();
195
196 hwndInputList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST);
197
198 if (hwndInputList != NULL)
199 {
200 WCHAR szBuffer[MAX_STR_LEN];
201 HIMAGELIST hLayoutImageList;
202 LV_COLUMN column;
203
204 ListView_SetExtendedListViewStyle(hwndInputList, LVS_EX_FULLROWSELECT);
205
206 ZeroMemory(&column, sizeof(column));
207
208 column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
209
210 LoadStringW(hApplet, IDS_LANGUAGE, szBuffer, ARRAYSIZE(szBuffer));
211 column.fmt = LVCFMT_LEFT;
212 column.iSubItem = 0;
213 column.pszText = szBuffer;
214 column.cx = 175;
215 ListView_InsertColumn(hwndInputList, 0, &column);
216
217 LoadStringW(hApplet, IDS_LAYOUT, szBuffer, ARRAYSIZE(szBuffer));
218 column.fmt = LVCFMT_RIGHT;
219 column.cx = 155;
220 column.iSubItem = 1;
221 column.pszText = szBuffer;
222 ListView_InsertColumn(hwndInputList, 1, &column);
223
224 hLayoutImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON) * 2,
225 GetSystemMetrics(SM_CYSMICON),
226 ILC_COLOR8 | ILC_MASK, 0, 0);
227 if (hLayoutImageList != NULL)
228 {
229 ListView_SetImageList(hwndInputList, hLayoutImageList, LVSIL_SMALL);
230 }
231
232 UpdateInputListView(hwndInputList);
233 }
234
235 SetControlsState(hwndDlg, FALSE);
236 }
237
238
239 static VOID
240 OnDestroySettingsPage(HWND hwndDlg)
241 {
242 HIMAGELIST hImageList;
243
244 LayoutList_Destroy();
245 LocaleList_Destroy();
246 InputList_Destroy();
247
248 hImageList = ListView_GetImageList(GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST),
249 LVSIL_SMALL);
250 if (hImageList != NULL)
251 {
252 ImageList_Destroy(hImageList);
253 }
254 }
255
256
257 VOID
258 OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam)
259 {
260 switch (LOWORD(wParam))
261 {
262 case IDC_ADD_BUTTON:
263 {
264 if (DialogBoxW(hApplet,
265 MAKEINTRESOURCEW(IDD_ADD),
266 hwndDlg,
267 AddDialogProc) == IDOK)
268 {
269 UpdateInputListView(GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST));
270 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
271 }
272 }
273 break;
274
275 case IDC_REMOVE_BUTTON:
276 {
277 HWND hwndList;
278
279 hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST);
280
281 if (hwndList != NULL)
282 {
283 LVITEM item = { 0 };
284
285 item.mask = LVIF_PARAM;
286 item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
287
288 if (ListView_GetItem(hwndList, &item) != FALSE)
289 {
290 InputList_Remove((INPUT_LIST_NODE*) item.lParam);
291 UpdateInputListView(hwndList);
292 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
293 }
294 }
295 }
296 break;
297
298 case IDC_PROP_BUTTON:
299 {
300 HWND hwndList;
301
302 hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST);
303
304 if (hwndList != NULL)
305 {
306 LVITEM item = { 0 };
307
308 item.mask = LVIF_PARAM;
309 item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
310
311 if (ListView_GetItem(hwndList, &item) != FALSE)
312 {
313 if (DialogBoxParamW(hApplet,
314 MAKEINTRESOURCEW(IDD_INPUT_LANG_PROP),
315 hwndDlg,
316 EditDialogProc,
317 item.lParam) == IDOK)
318 {
319 UpdateInputListView(hwndList);
320 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
321 }
322 }
323 }
324 }
325 break;
326
327 case IDC_SET_DEFAULT:
328 {
329 HWND hwndList;
330
331 hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST);
332
333 if (hwndList != NULL)
334 {
335 LVITEM item = { 0 };
336
337 item.mask = LVIF_PARAM;
338 item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
339
340 if (ListView_GetItem(hwndList, &item) != FALSE)
341 {
342 InputList_SetDefault((INPUT_LIST_NODE*) item.lParam);
343 UpdateInputListView(hwndList);
344 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
345 }
346 }
347 }
348 break;
349
350 case IDC_KEY_SET_BTN:
351 {
352 DialogBoxW(hApplet,
353 MAKEINTRESOURCEW(IDD_KEYSETTINGS),
354 hwndDlg,
355 KeySettingsDialogProc);
356 }
357 break;
358 }
359 }
360
361 BOOL EnableProcessPrivileges(LPCWSTR lpPrivilegeName, BOOL bEnable)
362 {
363 HANDLE hToken;
364 LUID luid;
365 TOKEN_PRIVILEGES tokenPrivileges;
366 BOOL Ret;
367
368 Ret = OpenProcessToken(GetCurrentProcess(),
369 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
370 &hToken);
371 if (!Ret)
372 return Ret; // failure
373
374 Ret = LookupPrivilegeValueW(NULL, lpPrivilegeName, &luid);
375 if (Ret)
376 {
377 tokenPrivileges.PrivilegeCount = 1;
378 tokenPrivileges.Privileges[0].Luid = luid;
379 tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
380
381 Ret = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, 0, 0);
382 }
383
384 CloseHandle(hToken);
385 return Ret;
386 }
387
388 static VOID
389 OnNotifySettingsPage(HWND hwndDlg, LPARAM lParam)
390 {
391 LPNMHDR header;
392
393 header = (LPNMHDR)lParam;
394
395 switch (header->code)
396 {
397 case NM_CLICK:
398 {
399 if (header->idFrom == IDC_KEYLAYOUT_LIST)
400 {
401 INT iSelected = ListView_GetNextItem(header->hwndFrom, -1, LVNI_SELECTED);
402
403 if (iSelected != -1)
404 {
405 LVITEM item = { 0 };
406
407 SetControlsState(hwndDlg, TRUE);
408
409 item.mask = LVIF_PARAM;
410 item.iItem = iSelected;
411
412 if (ListView_GetItem(header->hwndFrom, &item) != FALSE)
413 {
414 INPUT_LIST_NODE *pInput;
415
416 pInput = (INPUT_LIST_NODE*) item.lParam;
417
418 if (pInput != NULL && pInput->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT)
419 {
420 EnableWindow(GetDlgItem(hwndDlg, IDC_SET_DEFAULT), FALSE);
421 }
422 }
423 }
424 else
425 {
426 SetControlsState(hwndDlg, FALSE);
427 }
428 }
429 }
430 break;
431
432 case PSN_APPLY:
433 {
434 /* Write Input Methods list to registry */
435 if (InputList_Process())
436 {
437 /* Needs reboot */
438 WCHAR szNeedsReboot[128], szLanguage[64];
439 LoadStringW(hApplet, IDS_REBOOT_NOW, szNeedsReboot, _countof(szNeedsReboot));
440 LoadStringW(hApplet, IDS_LANGUAGE, szLanguage, _countof(szLanguage));
441
442 if (MessageBoxW(hwndDlg, szNeedsReboot, szLanguage,
443 MB_ICONINFORMATION | MB_YESNOCANCEL) == IDYES)
444 {
445 EnableProcessPrivileges(SE_SHUTDOWN_NAME, TRUE);
446 ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0);
447 }
448 }
449 }
450 break;
451 }
452 }
453
454
455 INT_PTR CALLBACK
456 SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
457 {
458 switch (uMsg)
459 {
460 case WM_INITDIALOG:
461 OnInitSettingsPage(hwndDlg);
462 break;
463
464 case WM_DESTROY:
465 OnDestroySettingsPage(hwndDlg);
466 break;
467
468 case WM_COMMAND:
469 OnCommandSettingsPage(hwndDlg, wParam);
470 break;
471
472 case WM_NOTIFY:
473 OnNotifySettingsPage(hwndDlg, lParam);
474 break;
475 }
476
477 return FALSE;
478 }