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