1 #include "intl.h" 2 #include <wingdi.h> 3 4 #include <debug.h> 5 6 typedef struct CPStruct 7 { 8 UINT CodePage; 9 DWORD Flags; 10 WCHAR Name[MAX_PATH]; 11 struct CPStruct *NextItem; 12 } CPAGE, *PCPAGE; 13 14 #define CODEPAGE_INSTALLED 0x00000001 15 #define CODEPAGE_NOT_REMOVEABLE 0x00000002 16 #define CODEPAGE_INSTALL 0x00000004 17 #define CODEPAGE_REMOVE 0x00000008 18 19 static PCPAGE PCPage = NULL; 20 static BOOL bSpain = FALSE; 21 static HWND hLangList; 22 23 static BOOL 24 GetSupportedCP( 25 HINF hInf) 26 { 27 WCHAR szSection[MAX_PATH]; 28 INFCONTEXT Context, Context2; 29 PCPAGE pCodePage; 30 CPINFOEX cpInfEx; 31 UINT uiCodePage; 32 33 if (!SetupFindFirstLine(hInf, 34 L"CodePages", 35 NULL, 36 &Context)) 37 return FALSE; 38 39 for (;;) 40 { 41 if (SetupGetIntField(&Context, 0, (PINT)&uiCodePage)) 42 { 43 pCodePage = HeapAlloc(GetProcessHeap(), 0, sizeof(CPAGE)); 44 if (pCodePage == NULL) 45 return FALSE; 46 47 pCodePage->CodePage = uiCodePage; 48 pCodePage->Flags = 0; 49 (pCodePage->Name)[0] = UNICODE_NULL; 50 51 if (GetCPInfoExW(uiCodePage, 0, &cpInfEx)) 52 { 53 wcscpy(pCodePage->Name, cpInfEx.CodePageName); 54 } 55 else 56 { 57 SetupGetStringFieldW(&Context, 1, pCodePage->Name, MAX_PATH, NULL); 58 } 59 60 if (wcslen(pCodePage->Name) != 0) 61 { 62 pCodePage->NextItem = PCPage; 63 PCPage = pCodePage; 64 65 wsprintf(szSection, L"CODEPAGE_REMOVE_%d", uiCodePage); 66 67 if ((uiCodePage == GetACP()) || 68 (uiCodePage == GetOEMCP()) || 69 (!SetupFindFirstLineW(hInf, szSection, L"AddReg", &Context2))) 70 { 71 pCodePage->Flags |= CODEPAGE_NOT_REMOVEABLE; 72 } 73 } 74 else 75 { 76 HeapFree(GetProcessHeap(), 0, pCodePage); 77 } 78 } 79 80 if (!SetupFindNextLine(&Context, &Context)) 81 break; 82 } 83 84 return TRUE; 85 } 86 87 static BOOL CALLBACK 88 InstalledCPProc(PWSTR lpStr) 89 { 90 PCPAGE lpCP; 91 UINT uiCP; 92 93 lpCP = PCPage; 94 uiCP = _wtol(lpStr); 95 96 for (;;) 97 { 98 if (!lpCP) 99 break; 100 101 if (lpCP->CodePage == uiCP) 102 { 103 lpCP->Flags |= CODEPAGE_INSTALLED; 104 break; 105 } 106 107 lpCP = lpCP->NextItem; 108 } 109 110 return TRUE; 111 } 112 113 static VOID 114 InitCodePagesList(HWND hwndDlg) 115 { 116 PCPAGE pCodePage; 117 INT ItemIndex; 118 HWND hList; 119 LV_COLUMN column; 120 LV_ITEM item; 121 RECT ListRect; 122 HINF hIntlInf; 123 124 hIntlInf = SetupOpenInfFileW(L"intl.inf", NULL, INF_STYLE_WIN4, NULL); 125 if (hIntlInf == INVALID_HANDLE_VALUE) 126 return; 127 128 if (!SetupOpenAppendInfFile(NULL, hIntlInf, NULL)) 129 { 130 SetupCloseInfFile(hIntlInf); 131 hIntlInf = NULL; 132 return; 133 } 134 135 if (!GetSupportedCP(hIntlInf)) 136 return; 137 138 SetupCloseInfFile(hIntlInf); 139 140 if (!EnumSystemCodePagesW(InstalledCPProc, CP_INSTALLED)) 141 { 142 /* Hack: EnumSystemCodePages returns FALSE on successful completion! */ 143 /* return; */ 144 } 145 146 hList = GetDlgItem(hwndDlg, IDC_CONV_TABLES); 147 148 ZeroMemory(&column, sizeof(LV_COLUMN)); 149 column.mask = LVCF_FMT | LVCF_WIDTH; 150 column.fmt = LVCFMT_LEFT; 151 GetClientRect(hList, &ListRect); 152 column.cx = ListRect.right - GetSystemMetrics(SM_CYHSCROLL); 153 ListView_InsertColumn(hList, 0, &column); 154 155 (VOID) ListView_SetExtendedListViewStyle(hList, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT); 156 157 pCodePage = PCPage; 158 159 for (;;) 160 { 161 if (pCodePage == NULL) 162 break; 163 164 ZeroMemory(&item, sizeof(LV_ITEM)); 165 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; 166 item.state = 0; 167 item.stateMask = LVIS_STATEIMAGEMASK; 168 item.pszText = pCodePage->Name; 169 item.lParam = (LPARAM)pCodePage; 170 171 ItemIndex = ListView_InsertItem(hList, &item); 172 if (ItemIndex != -1) 173 { 174 if (pCodePage->Flags & CODEPAGE_INSTALLED) 175 { 176 ListView_SetItemState(hList, ItemIndex, 177 INDEXTOSTATEIMAGEMASK(LVIS_SELECTED), 178 LVIS_STATEIMAGEMASK); 179 } 180 else 181 { 182 ListView_SetItemState(hList, ItemIndex, 183 INDEXTOSTATEIMAGEMASK(LVIS_FOCUSED), 184 LVIS_STATEIMAGEMASK); 185 } 186 } 187 188 pCodePage = pCodePage->NextItem; 189 } 190 } 191 192 static BOOL CALLBACK 193 LocalesEnumProc(PWSTR lpLocale) 194 { 195 LCID lcid; 196 WCHAR lang[255]; 197 INT index; 198 BOOL bNoShow = FALSE; 199 200 lcid = wcstoul(lpLocale, NULL, 16); 201 202 if (lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) || 203 lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT)) 204 { 205 if (bSpain == FALSE) 206 { 207 LoadStringW(hApplet, IDS_SPAIN, lang, 255); 208 bSpain = TRUE; 209 } 210 else 211 { 212 bNoShow = TRUE; 213 } 214 } 215 else 216 { 217 GetLocaleInfoW(lcid, LOCALE_SLANGUAGE, lang, sizeof(lang)/sizeof(WCHAR)); 218 } 219 220 if (bNoShow == FALSE) 221 { 222 index = SendMessageW(hLangList, 223 CB_ADDSTRING, 224 0, 225 (LPARAM)lang); 226 227 SendMessageW(hLangList, 228 CB_SETITEMDATA, 229 index, 230 (LPARAM)lcid); 231 } 232 233 return TRUE; 234 } 235 236 static VOID 237 InitLanguagesList( 238 HWND hwndDlg, 239 PGLOBALDATA pGlobalData) 240 { 241 WCHAR langSel[255]; 242 243 hLangList = GetDlgItem(hwndDlg, IDC_LANGUAGE_COMBO); 244 245 bSpain = FALSE; 246 EnumSystemLocalesW(LocalesEnumProc, LCID_SUPPORTED); 247 248 /* Select current locale */ 249 GetLocaleInfoW(pGlobalData->SystemLCID, LOCALE_SLANGUAGE, langSel, sizeof(langSel)/sizeof(WCHAR)); 250 251 SendMessageW(hLangList, CB_SELECTSTRING, -1, (LPARAM)langSel); 252 } 253 254 static VOID 255 GetCurrentDPI(LPTSTR szDPI) 256 { 257 DWORD dwType, dwSize, dwDPI, dwDefDPI = 0x00000060; // Default 96 DPI 258 HKEY hKey; 259 260 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontDPI", 0, NULL, 261 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) != ERROR_SUCCESS) 262 { 263 wcscpy(szDPI, L"96"); 264 return; 265 } 266 267 dwType = REG_DWORD; 268 dwSize = sizeof(DWORD); 269 270 if (RegQueryValueExW(hKey, L"LogPixels", NULL, &dwType, (LPBYTE)&dwDPI, &dwSize) != ERROR_SUCCESS) 271 { 272 if (RegSetValueExW(hKey, L"LogPixels", 0, REG_DWORD, (LPBYTE)&dwDefDPI, sizeof(DWORD)) == ERROR_SUCCESS) 273 { 274 wcscpy(szDPI, L"96"); 275 RegCloseKey(hKey); 276 return; 277 } 278 } 279 else 280 { 281 wsprintf(szDPI, L"%d", dwDPI); 282 } 283 284 RegCloseKey(hKey); 285 } 286 287 static 288 VOID 289 SaveFontSubstitutionSettings( 290 HWND hwnd, 291 PGLOBALDATA pGlobalData) 292 { 293 WCHAR szDefCP[5 + 1], szSection[MAX_PATH], szDPI[3 + 1]; 294 HINF hFontInf; 295 UINT Count; 296 297 GetLocaleInfoW(MAKELCID(pGlobalData->SystemLCID, SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, szDefCP, sizeof(szDefCP) / sizeof(WCHAR)); 298 GetCurrentDPI(szDPI); 299 300 wsprintf(szSection, L"Font.CP%s.%s", szDefCP, szDPI); 301 302 hFontInf = SetupOpenInfFileW(L"font.inf", NULL, INF_STYLE_WIN4, NULL); 303 if (hFontInf == INVALID_HANDLE_VALUE) 304 return; 305 306 if (!SetupOpenAppendInfFile(NULL, hFontInf, NULL)) 307 { 308 SetupCloseInfFile(hFontInf); 309 return; 310 } 311 312 Count = (UINT)SetupGetLineCount(hFontInf, szSection); 313 if (Count <= 0) 314 return; 315 316 if (!SetupInstallFromInfSectionW(hwnd, hFontInf, szSection, SPINST_REGISTRY & ~SPINST_FILES, 317 NULL, NULL, 0, NULL, NULL, NULL, NULL)) 318 { 319 PrintErrorMsgBox(IDS_ERROR_UNICODE); 320 } 321 322 SetupCloseInfFile(hFontInf); 323 } 324 325 326 static 327 VOID 328 SaveFontLinkingSettings( 329 HWND hwnd, 330 PGLOBALDATA pGlobalData) 331 { 332 /* TODO */ 333 } 334 335 336 static 337 VOID 338 SaveSystemSettings( 339 PGLOBALDATA pGlobalData) 340 { 341 WCHAR ACPPage[9]; 342 WCHAR OEMPage[9]; 343 HKEY langKey; 344 DWORD ret; 345 WCHAR value[5]; 346 DWORD valuesize; 347 348 ret = GetLocaleInfoW(MAKELCID(pGlobalData->SystemLCID, SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, OEMPage, sizeof(OEMPage)/sizeof(WCHAR)); 349 if (ret == 0) 350 { 351 PrintErrorMsgBox(IDS_ERROR_OEM_CODE_PAGE); 352 return; 353 } 354 355 ret = GetLocaleInfoW(MAKELCID(pGlobalData->SystemLCID, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, ACPPage, sizeof(ACPPage)/sizeof(WCHAR)); 356 if (ret == 0) 357 { 358 PrintErrorMsgBox(IDS_ERROR_ANSI_CODE_PAGE); 359 return; 360 } 361 362 /* Set codepages */ 363 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage", &langKey); 364 if (ret != ERROR_SUCCESS) 365 { 366 PrintErrorMsgBox(IDS_ERROR_NLS_CODE_REG); 367 return; 368 } 369 370 RegSetValueExW(langKey, L"OEMCP", 0, REG_SZ, (BYTE *)OEMPage, (wcslen(OEMPage) +1 ) * sizeof(WCHAR)); 371 RegSetValueExW(langKey, L"ACP", 0, REG_SZ, (BYTE *)ACPPage, (wcslen(ACPPage) +1 ) * sizeof(WCHAR)); 372 373 RegCloseKey(langKey); 374 375 376 wsprintf(value, L"%04hX", LANGIDFROMLCID(pGlobalData->SystemLCID)); 377 valuesize = (wcslen(value) + 1) * sizeof(WCHAR); 378 379 /* Set language */ 380 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language", &langKey); 381 if (ret != ERROR_SUCCESS) 382 { 383 PrintErrorMsgBox(IDS_ERROR_NLS_KEY_REG); 384 return; 385 } 386 387 RegSetValueExW(langKey, L"Default", 0, REG_SZ, (BYTE *)value, valuesize); 388 RegCloseKey(langKey); 389 } 390 391 392 LRESULT 393 ListViewCustomDraw( 394 LPARAM lParam) 395 { 396 LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam; 397 398 switch (lplvcd->nmcd.dwDrawStage) 399 { 400 case CDDS_PREPAINT: 401 return CDRF_NOTIFYITEMDRAW; 402 403 case CDDS_ITEMPREPAINT: 404 if (((PCPAGE)lplvcd->nmcd.lItemlParam)->Flags & CODEPAGE_NOT_REMOVEABLE) 405 { 406 lplvcd->clrText = GetSysColor(COLOR_GRAYTEXT); 407 } 408 else 409 { 410 lplvcd->clrText = GetSysColor(COLOR_WINDOWTEXT); 411 } 412 lplvcd->clrTextBk = GetSysColor(COLOR_WINDOW); 413 return CDRF_NEWFONT; 414 } 415 416 return CDRF_DODEFAULT; 417 } 418 419 420 /* Property page dialog callback */ 421 INT_PTR CALLBACK 422 AdvancedPageProc(HWND hwndDlg, 423 UINT uMsg, 424 WPARAM wParam, 425 LPARAM lParam) 426 { 427 PGLOBALDATA pGlobalData; 428 429 pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 430 431 switch (uMsg) 432 { 433 case WM_INITDIALOG: 434 pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam; 435 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData); 436 437 InitLanguagesList(hwndDlg, pGlobalData); 438 InitCodePagesList(hwndDlg); 439 break; 440 441 case WM_COMMAND: 442 switch (LOWORD(wParam)) 443 { 444 case IDC_LANGUAGE_COMBO: 445 if (HIWORD(wParam) == CBN_SELCHANGE) 446 { 447 LCID lcid; 448 INT iIndex; 449 450 iIndex = SendMessage(hLangList, CB_GETCURSEL, 0, 0); 451 if (iIndex == CB_ERR) 452 break; 453 454 lcid = SendMessage(hLangList, CB_GETITEMDATA, iIndex, 0); 455 if (lcid == (LCID)CB_ERR) 456 break; 457 458 pGlobalData->SystemLCID = lcid; 459 460 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 461 } 462 break; 463 464 case IDC_APPLY_CUR_USER_DEF_PROFILE: 465 if (HIWORD(wParam) == BN_CLICKED) 466 { 467 if (SendDlgItemMessageW(hwndDlg, IDC_APPLY_CUR_USER_DEF_PROFILE, BM_GETCHECK, 0, 0)) 468 { 469 ResourceMessageBox(hwndDlg, 470 MB_OK | MB_ICONWARNING, 471 IDS_APPLY_DEFAULT_TITLE, 472 IDS_APPLY_DEFAULT_TEXT); 473 pGlobalData->bApplyToDefaultUser = TRUE; 474 } 475 else 476 { 477 pGlobalData->bApplyToDefaultUser = FALSE; 478 } 479 480 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 481 } 482 break; 483 } 484 break; 485 486 case WM_NOTIFY: 487 if (((LPNMHDR)lParam)->code == PSN_APPLY) 488 { 489 PropSheet_UnChanged(GetParent(hwndDlg), hwndDlg); 490 491 SaveSystemSettings(pGlobalData); 492 SaveFontSubstitutionSettings(hwndDlg, pGlobalData); 493 SaveFontLinkingSettings(hwndDlg, pGlobalData); 494 } 495 else if (((LPNMHDR)lParam)->idFrom == IDC_CONV_TABLES && 496 ((LPNMHDR)lParam)->code == NM_CUSTOMDRAW) 497 { 498 SetWindowLongPtr(hwndDlg, 499 DWLP_MSGRESULT, 500 (LONG_PTR)ListViewCustomDraw(lParam)); 501 return TRUE; 502 } 503 break; 504 } 505 506 return FALSE; 507 } 508 509 /* EOF */ 510