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