3 * Copyright (C) 2004, 2005 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * PROJECT: ReactOS International Control Panel
21 * FILE: dll/cpl/intl/generalp.c
22 * PURPOSE: General property page
23 * PROGRAMMER: Eric Kohl
32 #define SAMPLE_NUMBER _T("123456789")
39 } LOCALE_KEY_DATA
, *PLOCALE_KEY_DATA
;
42 HWND hLocaleList
, hGeoList
;
45 LOCALE_KEY_DATA LocaleKeyData
[] =
47 {LOCALE_ICALENDARTYPE
, L
"iCalendarType"},
48 {LOCALE_ICOUNTRY
, L
"iCountry"},
49 {LOCALE_ICURRDIGITS
, L
"iCurrDigits"},
50 {LOCALE_ICURRENCY
, L
"iCurrency"},
51 {LOCALE_IDATE
, L
"iDate"},
52 {LOCALE_IDIGITS
, L
"iDigits"},
53 {LOCALE_IFIRSTDAYOFWEEK
, L
"iFirstDayOfWeek"},
54 {LOCALE_IFIRSTWEEKOFYEAR
, L
"iFirstWeekOfYear"},
55 {LOCALE_ILZERO
, L
"iLZero"},
56 {LOCALE_IMEASURE
, L
"iMeasure"},
57 {LOCALE_INEGCURR
, L
"iNegCurr"},
58 {LOCALE_INEGNUMBER
, L
"iNegNumber"},
59 {LOCALE_ITIME
, L
"iTime"},
60 {LOCALE_ITIMEMARKPOSN
, L
"iTimePrefix"},
61 {LOCALE_ITLZERO
, L
"iTLZero"},
62 {LOCALE_IDIGITSUBSTITUTION
, L
"NumShape"},
63 {LOCALE_S1159
, L
"s1159"},
64 {LOCALE_S2359
, L
"s2359"},
65 {LOCALE_SCOUNTRY
, L
"sCountry"},
66 {LOCALE_SCURRENCY
, L
"sCurrency"},
67 {LOCALE_SDATE
, L
"sDate"},
68 {LOCALE_SDECIMAL
, L
"sDecimal"},
69 {LOCALE_SGROUPING
, L
"sGrouping"},
70 {LOCALE_SABBREVLANGNAME
, L
"sLanguage"},
71 {LOCALE_SLIST
, L
"sList"},
72 {LOCALE_SLONGDATE
, L
"sLongDate"},
73 {LOCALE_SMONDECIMALSEP
, L
"sMonDecimalSep"},
74 {LOCALE_SMONGROUPING
, L
"sMonGrouping"},
75 {LOCALE_SMONTHOUSANDSEP
, L
"sMonThousandSep"},
76 {LOCALE_SNATIVEDIGITS
, L
"sNativeDigits"},
77 {LOCALE_SNEGATIVESIGN
, L
"sNegativeSign"},
78 {LOCALE_SPOSITIVESIGN
, L
"sPositiveSign"},
79 {LOCALE_SSHORTDATE
, L
"sShortDate"},
80 {LOCALE_STHOUSAND
, L
"sThousand"},
81 {LOCALE_STIME
, L
"sTime"},
82 {LOCALE_STIMEFORMAT
, L
"sTimeFormat"}
87 LocalesEnumProc(LPTSTR lpLocale
)
94 lcid
= _tcstoul(lpLocale
, NULL
, 16);
96 /* Display only languages with installed support */
97 if (!IsValidLocale(lcid
, LCID_INSTALLED
))
100 if (lcid
== MAKELCID(MAKELANGID(LANG_SPANISH
, SUBLANG_SPANISH
), SORT_DEFAULT
) ||
101 lcid
== MAKELCID(MAKELANGID(LANG_SPANISH
, SUBLANG_SPANISH_MODERN
), SORT_DEFAULT
))
105 LoadString(hApplet
, IDS_SPAIN
, lang
, 255);
115 GetLocaleInfo(lcid
, LOCALE_SLANGUAGE
, lang
, sizeof(lang
)/sizeof(TCHAR
));
118 if (bNoShow
== FALSE
)
120 index
= SendMessage(hList
,
140 DWORD dwDataCount
, i
;
142 dwDataCount
= sizeof(LocaleKeyData
) / sizeof(LOCALE_KEY_DATA
);
143 for (i
= 0; i
< dwDataCount
; i
++)
145 if (LocaleKeyData
[i
].lcType
== lcType
)
146 return pLocaleArray
[i
];
153 /* Update all locale samples */
158 PGLOBALDATA pGlobalData
)
160 WCHAR OutBuffer
[MAX_SAMPLES_STR_SIZE
];
162 /* Get number format sample */
163 GetNumberFormatW(pGlobalData
->lcid
, NO_FLAG
, SAMPLE_NUMBER
, NULL
,
164 OutBuffer
, MAX_SAMPLES_STR_SIZE
);
165 SendDlgItemMessageW(hwndDlg
, IDC_NUMSAMPLE_EDIT
,
166 WM_SETTEXT
, 0, (LPARAM
)OutBuffer
);
167 ZeroMemory(OutBuffer
, MAX_SAMPLES_STR_SIZE
* sizeof(WCHAR
));
169 /* Get monetary format sample */
170 GetCurrencyFormatW(pGlobalData
->lcid
, NO_FLAG
, SAMPLE_NUMBER
, NULL
,
171 OutBuffer
, MAX_SAMPLES_STR_SIZE
);
172 SendDlgItemMessageW(hwndDlg
, IDC_MONEYSAMPLE_EDIT
,
173 WM_SETTEXT
, 0, (LPARAM
)OutBuffer
);
174 ZeroMemory(OutBuffer
, MAX_SAMPLES_STR_SIZE
* sizeof(WCHAR
));
176 /* Get time format sample */
177 GetTimeFormatW(pGlobalData
->lcid
, NO_FLAG
, NULL
, NULL
,
178 OutBuffer
, MAX_SAMPLES_STR_SIZE
);
179 SendDlgItemMessageW(hwndDlg
, IDC_TIMESAMPLE_EDIT
,
180 WM_SETTEXT
, 0, (LPARAM
)OutBuffer
);
181 ZeroMemory(OutBuffer
, MAX_SAMPLES_STR_SIZE
* sizeof(WCHAR
));
183 /* Get short date format sample */
184 GetDateFormatW(pGlobalData
->lcid
, DATE_SHORTDATE
, NULL
, NULL
,
185 OutBuffer
, MAX_SAMPLES_STR_SIZE
);
186 SendDlgItemMessageW(hwndDlg
, IDC_SHORTTIMESAMPLE_EDIT
,
187 WM_SETTEXT
, 0, (LPARAM
)OutBuffer
);
189 /* Get long date sample */
190 GetDateFormatW(pGlobalData
->lcid
, DATE_LONGDATE
, NULL
, NULL
,
191 OutBuffer
, MAX_SAMPLES_STR_SIZE
);
192 SendDlgItemMessageW(hwndDlg
, IDC_FULLTIMESAMPLE_EDIT
,
193 WM_SETTEXT
, 0, (LPARAM
)OutBuffer
);
197 CreateLanguagesList(HWND hwnd
)
203 EnumSystemLocales(LocalesEnumProc
, LCID_SUPPORTED
);
205 /* Select current locale */
206 /* or should it be System and not user? */
207 GetLocaleInfo(GetUserDefaultLCID(), LOCALE_SLANGUAGE
, langSel
, sizeof(langSel
)/sizeof(TCHAR
));
218 PGLOBALDATA pGlobalData
)
227 ret
= RegOpenKeyExW(HKEY_CURRENT_USER
,
228 L
"Control Panel\\International",
232 if (ret
!= ERROR_SUCCESS
)
234 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
238 pGlobalData
->dwLocaleCount
= sizeof(LocaleKeyData
) / sizeof(LOCALE_KEY_DATA
);
240 pGlobalData
->pLocaleArray
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
241 pGlobalData
->dwLocaleCount
* sizeof(PWSTR
));
242 if (pGlobalData
->pLocaleArray
== NULL
)
244 RegCloseKey(hLocaleKey
);
248 dwSize
= 9 * sizeof(WCHAR
);
249 RegQueryValueExW(hLocaleKey
,
255 pGlobalData
->lcid
= (LCID
)wcstoul(szValue
, &ptr
, 16);
257 for (i
= 0; i
< pGlobalData
->dwLocaleCount
; i
++)
259 RegQueryValueExW(hLocaleKey
,
260 LocaleKeyData
[i
].pKeyName
,
267 pGlobalData
->pLocaleArray
[i
] = HeapAlloc(GetProcessHeap(), 0, dwSize
);
268 if (pGlobalData
->pLocaleArray
[i
])
270 RegQueryValueExW(hLocaleKey
,
271 LocaleKeyData
[i
].pKeyName
,
274 (LPVOID
)pGlobalData
->pLocaleArray
[i
],
280 RegCloseKey(hLocaleKey
);
288 PGLOBALDATA pGlobalData
)
292 if (pGlobalData
== NULL
|| pGlobalData
->pLocaleArray
== NULL
)
295 for (i
= 0; i
< pGlobalData
->dwLocaleCount
; i
++)
297 if (pGlobalData
->pLocaleArray
[i
])
298 HeapFree(GetProcessHeap(), 0, pGlobalData
->pLocaleArray
[i
]);
300 HeapFree(GetProcessHeap(), 0, pGlobalData
->pLocaleArray
);
306 PGLOBALDATA pGlobalData
,
311 pGlobalData
->lcid
= lcid
;
313 for (i
= 0; i
< pGlobalData
->dwLocaleCount
; i
++)
315 if (pGlobalData
->pLocaleArray
[i
])
317 HeapFree(GetProcessHeap(), 0, pGlobalData
->pLocaleArray
[i
]);
318 pGlobalData
->pLocaleArray
[i
] = NULL
;
321 dwSize
= GetLocaleInfo(lcid
,
322 LocaleKeyData
[i
].lcType
| LOCALE_NOUSEROVERRIDE
,
327 pGlobalData
->pLocaleArray
[i
] = HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(WCHAR
));
328 if (pGlobalData
->pLocaleArray
[i
])
331 LocaleKeyData
[i
].lcType
| LOCALE_NOUSEROVERRIDE
,
332 pGlobalData
->pLocaleArray
[i
],
340 /* Sets new locale */
343 PGLOBALDATA pGlobalData
)
345 // HKCU\\Control Panel\\International\\Locale = 0409 (type=0)
346 // HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","Default",0x00000000,"0409" (type=0)
347 // HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","InstallLanguage",0x00000000,"0409" (type=0)
357 ret
= GetLocaleInfo(MAKELCID(lcid
, SORT_DEFAULT
), LOCALE_IDEFAULTCODEPAGE
, OEMPage
, sizeof(OEMPage
)/sizeof(TCHAR
));
360 PrintErrorMsgBox(IDS_ERROR_OEM_CODE_PAGE
);
364 ret
= GetLocaleInfo(MAKELCID(lcid
, SORT_DEFAULT
), LOCALE_IDEFAULTANSICODEPAGE
, ACPPage
, sizeof(ACPPage
)/sizeof(TCHAR
));
367 PrintErrorMsgBox(IDS_ERROR_ANSI_CODE_PAGE
);
372 ret
= RegOpenKeyExW(HKEY_CURRENT_USER
, L
"Control Panel\\International",
373 0, KEY_READ
| KEY_WRITE
, &localeKey
);
374 if (ret
!= ERROR_SUCCESS
)
376 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
380 wsprintf(value
, L
"%08x", (DWORD
)pGlobalData
->lcid
);
381 valuesize
= (wcslen(value
) + 1) * sizeof(WCHAR
);
383 ret
= RegSetValueExW(localeKey
, L
"Locale", 0, REG_SZ
, (PBYTE
)value
, valuesize
);
384 if (ret
!= ERROR_SUCCESS
)
386 RegCloseKey(localeKey
);
387 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
391 for (i
= 0; i
< pGlobalData
->dwLocaleCount
; i
++)
393 RegSetValueExW(localeKey
,
394 LocaleKeyData
[i
].pKeyName
,
397 (PBYTE
)pGlobalData
->pLocaleArray
[i
],
398 (wcslen(pGlobalData
->pLocaleArray
[i
]) + 1) * sizeof(WCHAR
));
401 /* Flush and close the locale key */
402 RegFlushKey(localeKey
);
403 RegCloseKey(localeKey
);
405 /* Set the new locale for the current process */
406 NtSetDefaultLocale(TRUE
, pGlobalData
->lcid
);
409 ret
= RegOpenKey(HKEY_USERS
, _T(".DEFAULT\\Control Panel\\International"), &localeKey
);
410 if (ret
!= ERROR_SUCCESS
)
412 PrintErrorMsgBox(IDS_ERROR_DEF_INT_KEY_REG
);
416 wsprintf(value
, _T("%08X"), (DWORD
)lcid
);
417 valuesize
= (_tcslen(value
) + 1) * sizeof(TCHAR
);
419 RegSetValueEx(localeKey
, _T("Locale"), 0, REG_SZ
, (BYTE
*)value
, valuesize
);
420 RegCloseKey(localeKey
);
423 ret
= RegOpenKey(HKEY_LOCAL_MACHINE
, _T("SYSTEM\\CurrentControlSet\\Control\\NLS\\Language"), &langKey
);
424 if (ret
!= ERROR_SUCCESS
)
426 PrintErrorMsgBox(IDS_ERROR_NLS_KEY_REG
);
430 RegSetValueEx(langKey
, _T("Default"), 0, REG_SZ
, (BYTE
*)value
, valuesize
);
431 RegSetValueEx(langKey
, _T("InstallLanguage"), 0, REG_SZ
, (BYTE
*)value
, valuesize
);
433 RegCloseKey(langKey
);
437 ret
= RegOpenKey(HKEY_LOCAL_MACHINE
, _T("SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage"), &langKey
);
438 if (ret
!= ERROR_SUCCESS
)
440 PrintErrorMsgBox(IDS_ERROR_NLS_CODE_REG
);
444 RegSetValueExW(langKey
, _T("OEMCP"), 0, REG_SZ
, (BYTE
*)OEMPage
, (_tcslen(OEMPage
) +1 ) * sizeof(TCHAR
));
445 RegSetValueExW(langKey
, _T("ACP"), 0, REG_SZ
, (BYTE
*)ACPPage
, (_tcslen(ACPPage
) +1 ) * sizeof(TCHAR
));
447 RegCloseKey(langKey
);
451 /* Location enumerate procedure */
454 LocationsEnumProc(GEOID gId
)
456 TCHAR loc
[MAX_STR_SIZE
];
459 if (GetGeoInfo(gId
, GEO_FRIENDLYNAME
, loc
, MAX_STR_SIZE
, LANG_SYSTEM_DEFAULT
) == 0)
462 index
= (INT
)SendMessage(hGeoList
,
467 SendMessage(hGeoList
,
475 /* Enumerate all system locations identifiers */
478 CreateLocationsList(HWND hWnd
)
481 TCHAR loc
[MAX_STR_SIZE
];
485 EnumSystemGeoID(GEOCLASS_NATION
, 0, LocationsEnumProc
);
487 /* Select current location */
488 userGeoID
= GetUserGeoID(GEOCLASS_NATION
);
489 GetGeoInfo(userGeoID
,
493 LANG_SYSTEM_DEFAULT
);
495 SendMessage(hGeoList
,
504 VerifyUnattendLCID(HWND hwndDlg
)
506 LRESULT lCount
, lIndex
, lResult
;
508 lCount
= SendMessage(hList
, CB_GETCOUNT
, (WPARAM
)0, (LPARAM
)0);
509 if (lCount
== CB_ERR
)
514 for (lIndex
= 0; lIndex
< lCount
; lIndex
++)
516 lResult
= SendMessage(hList
, CB_GETITEMDATA
, (WPARAM
)lIndex
, (LPARAM
)0);
517 if (lResult
== CB_ERR
)
522 if (lResult
== (LRESULT
)UnattendLCID
)
524 SendMessage(hList
, CB_SETCURSEL
, (WPARAM
)lIndex
, (LPARAM
)0);
525 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
534 /* Property page dialog callback */
536 GeneralPageProc(HWND hwndDlg
,
541 PGLOBALDATA pGlobalData
;
543 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
548 pGlobalData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(GLOBALDATA
));
549 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
553 LoadCurrentLocale(pGlobalData
);
555 CreateLanguagesList(GetDlgItem(hwndDlg
, IDC_LANGUAGELIST
));
556 UpdateLocaleSample(hwndDlg
, pGlobalData
);
557 pGlobalData
->geoid
= CreateLocationsList(GetDlgItem(hwndDlg
, IDC_LOCATION_COMBO
));
558 if (IsUnattendedSetupEnabled
)
560 if (VerifyUnattendLCID(hwndDlg
))
562 SetNewLocale(pGlobalData
, UnattendLCID
);
563 SaveCurrentLocale(pGlobalData
);
568 DPRINT1("VerifyUnattendLCID failed\n");
576 switch (LOWORD(wParam
))
578 case IDC_LANGUAGELIST
:
579 if (HIWORD(wParam
) == CBN_SELCHANGE
)
584 iCurSel
= SendMessage(hList
,
588 if (iCurSel
== CB_ERR
)
591 NewLcid
= SendMessage(hList
,
595 if (NewLcid
== (LCID
)CB_ERR
)
598 SetNewLocale(pGlobalData
, NewLcid
);
599 UpdateLocaleSample(hwndDlg
, pGlobalData
);
600 pGlobalData
->fUserLocaleChanged
= TRUE
;
602 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
606 case IDC_LOCATION_COMBO
:
607 if (HIWORD(wParam
) == CBN_SELCHANGE
)
612 iCurSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_LOCATION_COMBO
),
616 if (iCurSel
== CB_ERR
)
619 NewGeoID
= SendMessage(GetDlgItem(hwndDlg
, IDC_LOCATION_COMBO
),
623 if (NewGeoID
== (GEOID
)CB_ERR
)
626 pGlobalData
->geoid
= NewGeoID
;
627 pGlobalData
->fGeoIdChanged
= TRUE
;
629 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
633 case IDC_SETUP_BUTTON
:
634 SetupApplet(GetParent(hwndDlg
), pGlobalData
);
641 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
643 if (lpnm
->code
== (UINT
)PSN_APPLY
)
646 PropSheet_UnChanged(GetParent(hwndDlg
), hwndDlg
);
649 if (pGlobalData
->fUserLocaleChanged
== TRUE
)
651 SaveCurrentLocale(pGlobalData
);
652 pGlobalData
->fUserLocaleChanged
= FALSE
;
656 if (pGlobalData
->fGeoIdChanged
== TRUE
)
658 SetUserGeoID(pGlobalData
->geoid
);
659 pGlobalData
->fGeoIdChanged
= FALSE
;
662 AddNewKbLayoutsByLcid(pGlobalData
->lcid
);
663 SetNonUnicodeLang(hwndDlg
, pGlobalData
->lcid
);
671 FreeCurrentLocale(pGlobalData
);
672 HeapFree(GetProcessHeap(), 0, pGlobalData
);