[CPL][INPUT] Fix bullet (#2124)
[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 DrawFrameControl(hdc, &rect, DFC_MENU, DFCS_MENUBULLET);
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 HIMAGELIST hOldImagelist = ListView_SetImageList(hwndInputList, hLayoutImageList, LVSIL_SMALL);
230 ImageList_Destroy(hOldImagelist);
231 }
232
233 UpdateInputListView(hwndInputList);
234 }
235
236 SetControlsState(hwndDlg, FALSE);
237 }
238
239
240 static VOID
241 OnDestroySettingsPage(HWND hwndDlg)
242 {
243 LayoutList_Destroy();
244 LocaleList_Destroy();
245 InputList_Destroy();
246 }
247
248
249 VOID
250 OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam)
251 {
252 switch (LOWORD(wParam))
253 {
254 case IDC_ADD_BUTTON:
255 {
256 if (DialogBoxW(hApplet,
257 MAKEINTRESOURCEW(IDD_ADD),
258 hwndDlg,
259 AddDialogProc) == IDOK)
260 {
261 UpdateInputListView(GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST));
262 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
263 }
264 }
265 break;
266
267 case IDC_REMOVE_BUTTON:
268 {
269 HWND hwndList;
270
271 hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST);
272
273 if (hwndList != NULL)
274 {
275 LVITEM item = { 0 };
276
277 item.mask = LVIF_PARAM;
278 item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
279
280 if (ListView_GetItem(hwndList, &item) != FALSE)
281 {
282 InputList_Remove((INPUT_LIST_NODE*) item.lParam);
283 UpdateInputListView(hwndList);
284 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
285 }
286 }
287 }
288 break;
289
290 case IDC_PROP_BUTTON:
291 {
292 HWND hwndList;
293
294 hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST);
295
296 if (hwndList != NULL)
297 {
298 LVITEM item = { 0 };
299
300 item.mask = LVIF_PARAM;
301 item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
302
303 if (ListView_GetItem(hwndList, &item) != FALSE)
304 {
305 if (DialogBoxParamW(hApplet,
306 MAKEINTRESOURCEW(IDD_INPUT_LANG_PROP),
307 hwndDlg,
308 EditDialogProc,
309 item.lParam) == IDOK)
310 {
311 UpdateInputListView(hwndList);
312 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
313 }
314 }
315 }
316 }
317 break;
318
319 case IDC_SET_DEFAULT:
320 {
321 HWND hwndList;
322
323 hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST);
324
325 if (hwndList != NULL)
326 {
327 LVITEM item = { 0 };
328
329 item.mask = LVIF_PARAM;
330 item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
331
332 if (ListView_GetItem(hwndList, &item) != FALSE)
333 {
334 InputList_SetDefault((INPUT_LIST_NODE*) item.lParam);
335 UpdateInputListView(hwndList);
336 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
337 }
338 }
339 }
340 break;
341
342 case IDC_KEY_SET_BTN:
343 {
344 DialogBoxW(hApplet,
345 MAKEINTRESOURCEW(IDD_KEYSETTINGS),
346 hwndDlg,
347 KeySettingsDialogProc);
348 }
349 break;
350 }
351 }
352
353 BOOL EnableProcessPrivileges(LPCWSTR lpPrivilegeName, BOOL bEnable)
354 {
355 HANDLE hToken;
356 LUID luid;
357 TOKEN_PRIVILEGES tokenPrivileges;
358 BOOL Ret;
359
360 Ret = OpenProcessToken(GetCurrentProcess(),
361 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
362 &hToken);
363 if (!Ret)
364 return Ret; // failure
365
366 Ret = LookupPrivilegeValueW(NULL, lpPrivilegeName, &luid);
367 if (Ret)
368 {
369 tokenPrivileges.PrivilegeCount = 1;
370 tokenPrivileges.Privileges[0].Luid = luid;
371 tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
372
373 Ret = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, 0, 0);
374 }
375
376 CloseHandle(hToken);
377 return Ret;
378 }
379
380 static VOID
381 OnNotifySettingsPage(HWND hwndDlg, LPARAM lParam)
382 {
383 LPNMHDR header;
384
385 header = (LPNMHDR)lParam;
386
387 switch (header->code)
388 {
389 case NM_CLICK:
390 {
391 if (header->idFrom == IDC_KEYLAYOUT_LIST)
392 {
393 INT iSelected = ListView_GetNextItem(header->hwndFrom, -1, LVNI_SELECTED);
394
395 if (iSelected != -1)
396 {
397 LVITEM item = { 0 };
398
399 SetControlsState(hwndDlg, TRUE);
400
401 item.mask = LVIF_PARAM;
402 item.iItem = iSelected;
403
404 if (ListView_GetItem(header->hwndFrom, &item) != FALSE)
405 {
406 INPUT_LIST_NODE *pInput;
407
408 pInput = (INPUT_LIST_NODE*) item.lParam;
409
410 if (pInput != NULL && pInput->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT)
411 {
412 EnableWindow(GetDlgItem(hwndDlg, IDC_SET_DEFAULT), FALSE);
413 }
414 }
415 }
416 else
417 {
418 SetControlsState(hwndDlg, FALSE);
419 }
420 }
421 }
422 break;
423
424 case PSN_APPLY:
425 {
426 /* Write Input Methods list to registry */
427 if (InputList_Process())
428 {
429 /* Needs reboot */
430 WCHAR szNeedsReboot[128], szLanguage[64];
431 LoadStringW(hApplet, IDS_REBOOT_NOW, szNeedsReboot, _countof(szNeedsReboot));
432 LoadStringW(hApplet, IDS_LANGUAGE, szLanguage, _countof(szLanguage));
433
434 if (MessageBoxW(hwndDlg, szNeedsReboot, szLanguage,
435 MB_ICONINFORMATION | MB_YESNOCANCEL) == IDYES)
436 {
437 EnableProcessPrivileges(SE_SHUTDOWN_NAME, TRUE);
438 ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0);
439 }
440 }
441 }
442 break;
443 }
444 }
445
446
447 INT_PTR CALLBACK
448 SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
449 {
450 switch (uMsg)
451 {
452 case WM_INITDIALOG:
453 OnInitSettingsPage(hwndDlg);
454 break;
455
456 case WM_DESTROY:
457 OnDestroySettingsPage(hwndDlg);
458 break;
459
460 case WM_COMMAND:
461 OnCommandSettingsPage(hwndDlg, wParam);
462 break;
463
464 case WM_NOTIFY:
465 OnNotifySettingsPage(hwndDlg, lParam);
466 break;
467 }
468
469 return FALSE;
470 }