xref: /reactos/dll/cpl/input/settings_page.c (revision ac43fd2b)
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             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 }
471