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 L"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
= wcstoul(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 LoadStringW(hApplet
, IDS_SPAIN
, lang
, 255);
115 GetLocaleInfoW(lcid
, LOCALE_SLANGUAGE
, lang
, sizeof(lang
)/sizeof(WCHAR
));
118 if (bNoShow
== FALSE
)
120 index
= SendMessageW(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 EnumSystemLocalesW(LocalesEnumProc
, LCID_SUPPORTED
);
205 /* Select current locale */
206 /* or should it be System and not user? */
207 GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_SLANGUAGE
, langSel
, sizeof(langSel
)/sizeof(WCHAR
));
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
);
301 pGlobalData
->pLocaleArray
= NULL
;
307 PGLOBALDATA pGlobalData
,
312 pGlobalData
->lcid
= lcid
;
314 for (i
= 0; i
< pGlobalData
->dwLocaleCount
; i
++)
316 if (pGlobalData
->pLocaleArray
[i
])
318 HeapFree(GetProcessHeap(), 0, pGlobalData
->pLocaleArray
[i
]);
319 pGlobalData
->pLocaleArray
[i
] = NULL
;
322 dwSize
= GetLocaleInfo(lcid
,
323 LocaleKeyData
[i
].lcType
| LOCALE_NOUSEROVERRIDE
,
328 pGlobalData
->pLocaleArray
[i
] = HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(WCHAR
));
329 if (pGlobalData
->pLocaleArray
[i
])
332 LocaleKeyData
[i
].lcType
| LOCALE_NOUSEROVERRIDE
,
333 pGlobalData
->pLocaleArray
[i
],
341 /* Sets new locale */
344 PGLOBALDATA pGlobalData
)
352 wsprintf(value
, L
"%08x", (DWORD
)pGlobalData
->lcid
);
353 valuesize
= (wcslen(value
) + 1) * sizeof(WCHAR
);
355 if (pGlobalData
->bApplyToDefaultUser
)
357 ret
= RegOpenKeyExW(HKEY_USERS
,
358 L
".DEFAULT\\Control Panel\\International",
362 if (ret
!= ERROR_SUCCESS
)
364 PrintErrorMsgBox(IDS_ERROR_DEF_INT_KEY_REG
);
368 ret
= RegSetValueExW(localeKey
, L
"Locale", 0, REG_SZ
, (PBYTE
)value
, valuesize
);
369 if (ret
!= ERROR_SUCCESS
)
371 RegCloseKey(localeKey
);
372 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
376 for (i
= 0; i
< pGlobalData
->dwLocaleCount
; i
++)
378 RegSetValueExW(localeKey
,
379 LocaleKeyData
[i
].pKeyName
,
382 (PBYTE
)pGlobalData
->pLocaleArray
[i
],
383 (wcslen(pGlobalData
->pLocaleArray
[i
]) + 1) * sizeof(WCHAR
));
386 /* Flush and close the locale key */
387 RegFlushKey(localeKey
);
388 RegCloseKey(localeKey
);
391 ret
= RegOpenKeyExW(HKEY_CURRENT_USER
, L
"Control Panel\\International",
392 0, KEY_READ
| KEY_WRITE
, &localeKey
);
393 if (ret
!= ERROR_SUCCESS
)
395 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
399 ret
= RegSetValueExW(localeKey
, L
"Locale", 0, REG_SZ
, (PBYTE
)value
, valuesize
);
400 if (ret
!= ERROR_SUCCESS
)
402 RegCloseKey(localeKey
);
403 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
407 for (i
= 0; i
< pGlobalData
->dwLocaleCount
; i
++)
409 RegSetValueExW(localeKey
,
410 LocaleKeyData
[i
].pKeyName
,
413 (PBYTE
)pGlobalData
->pLocaleArray
[i
],
414 (wcslen(pGlobalData
->pLocaleArray
[i
]) + 1) * sizeof(WCHAR
));
417 /* Flush and close the locale key */
418 RegFlushKey(localeKey
);
419 RegCloseKey(localeKey
);
421 /* Set the new locale for the current process */
422 NtSetDefaultLocale(TRUE
, pGlobalData
->lcid
);
426 /* Location enumerate procedure */
429 LocationsEnumProc(GEOID gId
)
431 WCHAR loc
[MAX_STR_SIZE
];
434 if (GetGeoInfoW(gId
, GEO_FRIENDLYNAME
, loc
, MAX_STR_SIZE
, LANG_SYSTEM_DEFAULT
) == 0)
437 index
= (INT
)SendMessageW(hGeoList
,
442 SendMessageW(hGeoList
,
450 /* Enumerate all system locations identifiers */
453 CreateLocationsList(HWND hWnd
)
456 WCHAR loc
[MAX_STR_SIZE
];
460 EnumSystemGeoID(GEOCLASS_NATION
, 0, LocationsEnumProc
);
462 /* Select current location */
463 userGeoID
= GetUserGeoID(GEOCLASS_NATION
);
464 GetGeoInfoW(userGeoID
,
468 LANG_SYSTEM_DEFAULT
);
470 SendMessageW(hGeoList
,
480 PGLOBALDATA pGlobalData
)
487 wsprintf(value
, L
"%lu", (DWORD
)pGlobalData
->geoid
);
488 valuesize
= (wcslen(value
) + 1) * sizeof(WCHAR
);
490 if (pGlobalData
->bApplyToDefaultUser
)
492 ret
= RegOpenKeyExW(HKEY_USERS
,
493 L
".DEFAULT\\Control Panel\\International\\Geo",
497 if (ret
!= ERROR_SUCCESS
)
499 PrintErrorMsgBox(IDS_ERROR_DEF_INT_KEY_REG
);
503 ret
= RegSetValueExW(hGeoKey
,
510 RegFlushKey(hGeoKey
);
511 RegCloseKey(hGeoKey
);
513 if (ret
!= ERROR_SUCCESS
)
515 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
520 ret
= RegOpenKeyExW(HKEY_CURRENT_USER
,
521 L
"Control Panel\\International\\Geo",
525 if (ret
!= ERROR_SUCCESS
)
527 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
531 ret
= RegSetValueExW(hGeoKey
,
538 RegFlushKey(hGeoKey
);
539 RegCloseKey(hGeoKey
);
541 if (ret
!= ERROR_SUCCESS
)
543 PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG
);
549 VerifyUnattendLCID(HWND hwndDlg
)
551 LRESULT lCount
, lIndex
, lResult
;
553 lCount
= SendMessage(hList
, CB_GETCOUNT
, (WPARAM
)0, (LPARAM
)0);
554 if (lCount
== CB_ERR
)
559 for (lIndex
= 0; lIndex
< lCount
; lIndex
++)
561 lResult
= SendMessage(hList
, CB_GETITEMDATA
, (WPARAM
)lIndex
, (LPARAM
)0);
562 if (lResult
== CB_ERR
)
567 if (lResult
== (LRESULT
)UnattendLCID
)
569 SendMessage(hList
, CB_SETCURSEL
, (WPARAM
)lIndex
, (LPARAM
)0);
570 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
579 /* Property page dialog callback */
581 GeneralPageProc(HWND hwndDlg
,
586 PGLOBALDATA pGlobalData
;
588 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
593 pGlobalData
= (PGLOBALDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
594 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
598 LoadCurrentLocale(pGlobalData
);
600 CreateLanguagesList(GetDlgItem(hwndDlg
, IDC_LANGUAGELIST
));
601 UpdateLocaleSample(hwndDlg
, pGlobalData
);
602 pGlobalData
->geoid
= CreateLocationsList(GetDlgItem(hwndDlg
, IDC_LOCATION_COMBO
));
603 if (IsUnattendedSetupEnabled
)
605 if (VerifyUnattendLCID(hwndDlg
))
607 SetNewLocale(pGlobalData
, UnattendLCID
);
608 SaveCurrentLocale(pGlobalData
);
613 DPRINT1("VerifyUnattendLCID failed\n");
621 switch (LOWORD(wParam
))
623 case IDC_LANGUAGELIST
:
624 if (HIWORD(wParam
) == CBN_SELCHANGE
)
629 iCurSel
= SendMessage(hList
,
633 if (iCurSel
== CB_ERR
)
636 NewLcid
= SendMessage(hList
,
640 if (NewLcid
== (LCID
)CB_ERR
)
643 SetNewLocale(pGlobalData
, NewLcid
);
644 UpdateLocaleSample(hwndDlg
, pGlobalData
);
645 pGlobalData
->fUserLocaleChanged
= TRUE
;
647 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
651 case IDC_LOCATION_COMBO
:
652 if (HIWORD(wParam
) == CBN_SELCHANGE
)
657 iCurSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_LOCATION_COMBO
),
661 if (iCurSel
== CB_ERR
)
664 NewGeoID
= SendMessage(GetDlgItem(hwndDlg
, IDC_LOCATION_COMBO
),
668 if (NewGeoID
== (GEOID
)CB_ERR
)
671 pGlobalData
->geoid
= NewGeoID
;
672 pGlobalData
->fGeoIdChanged
= TRUE
;
674 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
678 case IDC_SETUP_BUTTON
:
679 SetupApplet(GetParent(hwndDlg
), pGlobalData
);
686 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
688 if (lpnm
->code
== (UINT
)PSN_APPLY
)
691 PropSheet_UnChanged(GetParent(hwndDlg
), hwndDlg
);
694 if (pGlobalData
->fUserLocaleChanged
== TRUE
)
696 SaveCurrentLocale(pGlobalData
);
697 pGlobalData
->fUserLocaleChanged
= FALSE
;
701 if (pGlobalData
->fGeoIdChanged
== TRUE
)
703 SaveGeoID(pGlobalData
);
704 pGlobalData
->fGeoIdChanged
= FALSE
;
707 AddNewKbLayoutsByLcid(pGlobalData
->lcid
);
715 FreeCurrentLocale(pGlobalData
);