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