0fddc82b5abb7e57620f713478c3f523bd8e5e61
[reactos.git] / dll / cpl / intl / advanced.c
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 */