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