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 MessageBoxW(hwnd, L"Unable to install a new language for programs don't support unicode!", 320 NULL, MB_ICONERROR | MB_OK); 321 } 322 323 SetupCloseInfFile(hFontInf); 324 } 325 326 327 static 328 VOID 329 SaveFontLinkingSettings( 330 HWND hwnd, 331 PGLOBALDATA pGlobalData) 332 { 333 /* TODO */ 334 } 335 336 337 static 338 VOID 339 SaveSystemSettings( 340 PGLOBALDATA pGlobalData) 341 { 342 WCHAR ACPPage[9]; 343 WCHAR OEMPage[9]; 344 HKEY langKey; 345 DWORD ret; 346 WCHAR value[5]; 347 DWORD valuesize; 348 349 ret = GetLocaleInfoW(MAKELCID(pGlobalData->SystemLCID, SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, OEMPage, sizeof(OEMPage)/sizeof(WCHAR)); 350 if (ret == 0) 351 { 352 PrintErrorMsgBox(IDS_ERROR_OEM_CODE_PAGE); 353 return; 354 } 355 356 ret = GetLocaleInfoW(MAKELCID(pGlobalData->SystemLCID, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, ACPPage, sizeof(ACPPage)/sizeof(WCHAR)); 357 if (ret == 0) 358 { 359 PrintErrorMsgBox(IDS_ERROR_ANSI_CODE_PAGE); 360 return; 361 } 362 363 /* Set codepages */ 364 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage", &langKey); 365 if (ret != ERROR_SUCCESS) 366 { 367 PrintErrorMsgBox(IDS_ERROR_NLS_CODE_REG); 368 return; 369 } 370 371 RegSetValueExW(langKey, L"OEMCP", 0, REG_SZ, (BYTE *)OEMPage, (wcslen(OEMPage) +1 ) * sizeof(WCHAR)); 372 RegSetValueExW(langKey, L"ACP", 0, REG_SZ, (BYTE *)ACPPage, (wcslen(ACPPage) +1 ) * sizeof(WCHAR)); 373 374 RegCloseKey(langKey); 375 376 377 wsprintf(value, L"%04hX", LANGIDFROMLCID(pGlobalData->SystemLCID)); 378 valuesize = (wcslen(value) + 1) * sizeof(WCHAR); 379 380 /* Set language */ 381 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language", &langKey); 382 if (ret != ERROR_SUCCESS) 383 { 384 PrintErrorMsgBox(IDS_ERROR_NLS_KEY_REG); 385 return; 386 } 387 388 RegSetValueExW(langKey, L"Default", 0, REG_SZ, (BYTE *)value, valuesize); 389 RegCloseKey(langKey); 390 } 391 392 393 LRESULT 394 ListViewCustomDraw( 395 LPARAM lParam) 396 { 397 LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam; 398 399 switch (lplvcd->nmcd.dwDrawStage) 400 { 401 case CDDS_PREPAINT: 402 return CDRF_NOTIFYITEMDRAW; 403 404 case CDDS_ITEMPREPAINT: 405 if (((PCPAGE)lplvcd->nmcd.lItemlParam)->Flags & CODEPAGE_NOT_REMOVEABLE) 406 { 407 lplvcd->clrText = GetSysColor(COLOR_GRAYTEXT); 408 } 409 else 410 { 411 lplvcd->clrText = GetSysColor(COLOR_WINDOWTEXT); 412 } 413 lplvcd->clrTextBk = GetSysColor(COLOR_WINDOW); 414 return CDRF_NEWFONT; 415 } 416 417 return CDRF_DODEFAULT; 418 } 419 420 421 /* Property page dialog callback */ 422 INT_PTR CALLBACK 423 AdvancedPageProc(HWND hwndDlg, 424 UINT uMsg, 425 WPARAM wParam, 426 LPARAM lParam) 427 { 428 PGLOBALDATA pGlobalData; 429 430 pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 431 432 switch (uMsg) 433 { 434 case WM_INITDIALOG: 435 pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam; 436 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData); 437 438 InitLanguagesList(hwndDlg, pGlobalData); 439 InitCodePagesList(hwndDlg); 440 break; 441 442 case WM_COMMAND: 443 switch (LOWORD(wParam)) 444 { 445 case IDC_LANGUAGE_COMBO: 446 if (HIWORD(wParam) == CBN_SELCHANGE) 447 { 448 LCID lcid; 449 INT iIndex; 450 451 iIndex = SendMessage(hLangList, CB_GETCURSEL, 0, 0); 452 if (iIndex == CB_ERR) 453 break; 454 455 lcid = SendMessage(hLangList, CB_GETITEMDATA, iIndex, 0); 456 if (lcid == (LCID)CB_ERR) 457 break; 458 459 pGlobalData->SystemLCID = lcid; 460 461 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 462 } 463 break; 464 465 case IDC_APPLY_CUR_USER_DEF_PROFILE: 466 if (HIWORD(wParam) == BN_CLICKED) 467 { 468 if (SendDlgItemMessageW(hwndDlg, IDC_APPLY_CUR_USER_DEF_PROFILE, BM_GETCHECK, 0, 0)) 469 { 470 ResourceMessageBox(hwndDlg, 471 MB_OK | MB_ICONWARNING, 472 IDS_APPLY_DEFAULT_TITLE, 473 IDS_APPLY_DEFAULT_TEXT); 474 pGlobalData->bApplyToDefaultUser = TRUE; 475 } 476 else 477 { 478 pGlobalData->bApplyToDefaultUser = FALSE; 479 } 480 481 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 482 } 483 break; 484 } 485 break; 486 487 case WM_NOTIFY: 488 if (((LPNMHDR)lParam)->code == PSN_APPLY) 489 { 490 PropSheet_UnChanged(GetParent(hwndDlg), hwndDlg); 491 492 SaveSystemSettings(pGlobalData); 493 SaveFontSubstitutionSettings(hwndDlg, pGlobalData); 494 SaveFontLinkingSettings(hwndDlg, pGlobalData); 495 } 496 else if (((LPNMHDR)lParam)->idFrom == IDC_CONV_TABLES && 497 ((LPNMHDR)lParam)->code == NM_CUSTOMDRAW) 498 { 499 SetWindowLong(hwndDlg, 500 DWL_MSGRESULT, 501 (LONG)ListViewCustomDraw(lParam)); 502 return TRUE; 503 } 504 break; 505 } 506 507 return FALSE; 508 } 509 510 /* EOF */ 511