/*++ Copyright (c) 1994-2000, Microsoft Corporation All rights reserved. Module Name: numdlg.c Abstract: This module implements the number property sheet for the Regional Options applet. Revision History: --*/ // // Include Files. // #include "intl.h" #include #include #include "intlhlp.h" #include "maxvals.h" #define STRSAFE_LIB #include // // Constant Declarations. // #define MAX_DIGIT_SUBST 2 #define CHAR_MAX_DIGIT_SUBST TEXT('2') #define EUROPEAN_DIGITS TEXT("0123456789") #define LPK_EUROPEAN_DIGITS TEXT("\x206f\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039") #define LANGUAGE_GROUPS_KEY TEXT("System\\CurrentControlSet\\Control\\Nls\\Language Groups") // // Global Variables. // static TCHAR sz_iNegNumber[MAX_INEGNUMBER + 1]; static TCHAR sz_iMeasure[MAX_IMEASURE + 1]; static TCHAR sz_NumShape[MAX_IDIGITSUBSTITUTION + 1]; static TCHAR sz_sDecimal[MAX_SDECIMAL + 1]; static TCHAR sz_sGrouping[MAX_SGROUPING + 1]; static TCHAR sz_sList[MAX_SLIST + 1]; static TCHAR sz_sNativeDigits[MAX_FORMAT + 1]; static TCHAR sz_sNegativeSign[MAX_SNEGSIGN + 1]; static TCHAR sz_sPositiveSign[MAX_SPOSSIGN + 1]; static TCHAR sz_sThousand[MAX_STHOUSAND + 1]; static TCHAR sz_iDigits[MAX_IDIGITS + 1]; static TCHAR sz_iLZero[MAX_ILZERO + 1]; // // Native Digits tables. // #define MAX_LANG_GROUPS 16 #define MAX_DIGITS_PER_LG 2 static const int c_szDigitsPerLangGroup[MAX_LANG_GROUPS][MAX_DIGITS_PER_LG] = { 0, 0, // 0 = (invalid) 0, 0, // 1 = Western Europe (added by code, see Number_SetValues(..)) 0, 0, // 2 = Central Europe 0, 0, // 3 = Baltic 0, 0, // 4 = Greek 0, 0, // 5 = Cyrillic 0, 0, // 6 = Turkish 0, 0, // 7 = Japanese 0, 0, // 8 = Korean 0, 0, // 9 = Traditional Chinese 0, 0, // 10 = Simplified Chinese 12, 0, // 11 = Thai 0, 0, // 12 = Hebrew 1, 2, // 13 = Arabic 0, 0, // 14 = Vietnamese 3, 8 // 15 = Indian (NT5 supports only Devenagari and Tamil (i.e. fonts and kbd)) }; static const LPTSTR c_szNativeDigits[15] = { TEXT("0123456789"), // European TEXT("\x0660\x0661\x0662\x0663\x0664\x0665\x0666\x0667\x0668\x0669"), // Arabic-Indic TEXT("\x06f0\x06f1\x06f2\x06f3\x06f4\x06f5\x06f6\x06f7\x06f8\x06f9"), // Extended Arabic-Indic TEXT("\x0966\x0967\x0968\x0969\x096a\x096b\x096c\x096d\x096e\x096f"), // Devanagari TEXT("\x09e6\x09e7\x09e8\x09e9\x09ea\x09eb\x09ec\x09ed\x09ee\x09ef"), // Bengali TEXT("\x0a66\x0a67\x0a68\x0a69\x0a6a\x0a6b\x0a6c\x0a6d\x0a6e\x0a6f"), // Gurmukhi TEXT("\x0ae6\x0ae7\x0ae8\x0ae9\x0aea\x0aeb\x0aec\x0aed\x0aee\x0aef"), // Gujarati TEXT("\x0b66\x0b67\x0b68\x0b69\x0b6a\x0b6b\x0b6c\x0b6d\x0b6e\x0b6f"), // Oriya TEXT("\x0030\x0be7\x0be8\x0be9\x0bea\x0beb\x0bec\x0bed\x0bee\x0bef"), // Tamil TEXT("\x0c66\x0c67\x0c68\x0c69\x0c6a\x0c6b\x0c6c\x0c6d\x0c6e\x0c6f"), // Telugu TEXT("\x0ce6\x0ce7\x0ce8\x0ce9\x0cea\x0ceb\x0cec\x0ced\x0cee\x0cef"), // Kannada TEXT("\x0d66\x0d67\x0d68\x0d69\x0d6a\x0d6b\x0d6c\x0d6d\x0d6e\x0d6f"), // Malayalam TEXT("\x0e50\x0e51\x0e52\x0e53\x0e54\x0e55\x0e56\x0e57\x0e58\x0e59"), // Thai TEXT("\x0ed0\x0ed1\x0ed2\x0ed3\x0ed4\x0ed5\x0ed6\x0ed7\x0ed8\x0ed9"), // Lao TEXT("\x0f20\x0f21\x0f22\x0f23\x0f24\x0f25\x0f26\x0f27\x0f28\x0f29") // Tibetan }; // // Context Help Ids. // static int aNumberHelpIds[] = { IDC_SAMPLELBL3, IDH_COMM_GROUPBOX, IDC_SAMPLELBL1, IDH_INTL_NUM_POSVALUE, IDC_SAMPLE1, IDH_INTL_NUM_POSVALUE, IDC_SAMPLELBL2, IDH_INTL_NUM_NEGVALUE, IDC_SAMPLE2, IDH_INTL_NUM_NEGVALUE, IDC_SAMPLELBL1A, IDH_INTL_NUM_POSVALUE_ARABIC, IDC_SAMPLE1A, IDH_INTL_NUM_POSVALUE_ARABIC, IDC_SAMPLELBL2A, IDH_INTL_NUM_NEGVALUE_ARABIC, IDC_SAMPLE2A, IDH_INTL_NUM_NEGVALUE_ARABIC, IDC_DECIMAL_SYMBOL, IDH_INTL_NUM_DECSYMBOL, IDC_NUM_DECIMAL_DIGITS, IDH_INTL_NUM_DIGITSAFTRDEC, IDC_DIGIT_GROUP_SYMBOL, IDH_INTL_NUM_DIGITGRPSYMBOL, IDC_NUM_DIGITS_GROUP, IDH_INTL_NUM_DIGITSINGRP, IDC_NEG_SIGN, IDH_INTL_NUM_NEGSIGNSYMBOL, IDC_NEG_NUM_FORMAT, IDH_INTL_NUM_NEGNUMFORMAT, IDC_SEPARATOR, IDH_INTL_NUM_LISTSEPARATOR, IDC_DISPLAY_LEAD_0, IDH_INTL_NUM_DISPLEADZEROS, IDC_MEASURE_SYS, IDH_INTL_NUM_MEASUREMNTSYS, IDC_NATIVE_DIGITS_TEXT, IDH_INTL_NUM_NATIVE_DIGITS, IDC_NATIVE_DIGITS, IDH_INTL_NUM_NATIVE_DIGITS, IDC_DIGIT_SUBST_TEXT, IDH_INTL_NUM_DIGIT_SUBST, IDC_DIGIT_SUBST, IDH_INTL_NUM_DIGIT_SUBST, 0, 0 }; //////////////////////////////////////////////////////////////////////////// // // Number_IsEuropeanDigits // //////////////////////////////////////////////////////////////////////////// BOOL Number_IsEuropeanDigits( TCHAR *pNum) { int Ctr; int Length = lstrlen(pNum); for (Ctr = 0; Ctr < Length; Ctr++) { if (!((pNum[Ctr] >= TEXT('0')) && (pNum[Ctr] <= TEXT('9')))) { return (FALSE); } } // // Return success. // return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Number_GetDigitSubstitution // //////////////////////////////////////////////////////////////////////////// int Number_GetDigitSubstitution() { TCHAR szBuf[10]; int cch; // // Get the digit substitution. // if ((cch = GetLocaleInfo(UserLocaleID, LOCALE_IDIGITSUBSTITUTION, szBuf, 10)) && (cch == 2) && ((szBuf[0] >= CHAR_ZERO) && (szBuf[0] <= CHAR_MAX_DIGIT_SUBST))) { return (szBuf[0] - CHAR_ZERO); } return (0); } //////////////////////////////////////////////////////////////////////////// // // Number_DisplaySample // // Update the Number sample. Format the number based on the user's // current locale settings. Display either a positive value or a // negative value based on the Positive/Negative radio buttons. // //////////////////////////////////////////////////////////////////////////// void Number_DisplaySample( HWND hDlg) { TCHAR szBuf[MAX_SAMPLE_SIZE]; int nCharCount; // // Show or hide the Arabic info based on the current user locale id. // ShowWindow(GetDlgItem(hDlg, IDC_SAMPLELBL1A), bShowArabic ? SW_SHOW : SW_HIDE); ShowWindow(GetDlgItem(hDlg, IDC_SAMPLE1A), bShowArabic ? SW_SHOW : SW_HIDE); ShowWindow(GetDlgItem(hDlg, IDC_SAMPLELBL2A), bShowArabic ? SW_SHOW : SW_HIDE); ShowWindow(GetDlgItem(hDlg, IDC_SAMPLE2A), bShowArabic ? SW_SHOW : SW_HIDE); // // Get the string representing the number format for the positive sample // number and, if the the value is valid, display it. Perform the same // operations for the negative sample. // nCharCount = GetNumberFormat( UserLocaleID, 0, szSample_Number, NULL, szBuf, MAX_SAMPLE_SIZE ); if (nCharCount) { SetDlgItemText(hDlg, IDC_SAMPLE1, szBuf); if (bShowArabic) { SetDlgItemText(hDlg, IDC_SAMPLE1A, szBuf); SetDlgItemRTL(hDlg, IDC_SAMPLE1A); } } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } nCharCount = GetNumberFormat( UserLocaleID, 0, szNegSample_Number, NULL, szBuf, MAX_SAMPLE_SIZE ); if (nCharCount) { SetDlgItemText(hDlg, IDC_SAMPLE2, szBuf); if (bShowArabic) { SetDlgItemText(hDlg, IDC_SAMPLE2A, szBuf); SetDlgItemRTL(hDlg, IDC_SAMPLE2A); } } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } } //////////////////////////////////////////////////////////////////////////// // // Number_SaveValues // // Save values in the case that we need to restore them. // //////////////////////////////////////////////////////////////////////////// void Number_SaveValues() { // // Save registry values. // if (!GetLocaleInfo( UserLocaleID, LOCALE_INEGNUMBER, sz_iNegNumber, MAX_INEGNUMBER + 1 )) { //_tcscpy(sz_iNegNumber, TEXT("1")); if(FAILED(StringCchCopy(sz_iNegNumber, MAX_INEGNUMBER+1, TEXT("1")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_IMEASURE, sz_iMeasure, MAX_IMEASURE + 1 )) { //_tcscpy(sz_iMeasure, TEXT("1")); if(FAILED(StringCchCopy(sz_iMeasure, MAX_IMEASURE+1, TEXT("1")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_IDIGITSUBSTITUTION, sz_NumShape, MAX_IDIGITSUBSTITUTION + 1 )) { //_tcscpy(sz_NumShape, TEXT("1")); if(FAILED(StringCchCopy(sz_NumShape, MAX_IDIGITSUBSTITUTION+1, TEXT("1")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SDECIMAL, sz_sDecimal, MAX_SDECIMAL + 1 )) { //_tcscpy(sz_sDecimal, TEXT(".")); if(FAILED(StringCchCopy(sz_sDecimal, MAX_SDECIMAL+1, TEXT(".")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SGROUPING, sz_sGrouping, MAX_SGROUPING + 1 )) { //_tcscpy(sz_sGrouping, TEXT("3;0")); if(FAILED(StringCchCopy(sz_sGrouping, MAX_SGROUPING+1, TEXT("3;0")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SLIST, sz_sList, MAX_SLIST + 1 )) { //_tcscpy(sz_sList, TEXT(",")); if(FAILED(StringCchCopy(sz_sList, MAX_SLIST+1, TEXT(",")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SNATIVEDIGITS, sz_sNativeDigits, MAX_FORMAT + 1 )) { //_tcscpy(sz_sNativeDigits, TEXT("0123456789")); if(FAILED(StringCchCopy(sz_sNativeDigits, MAX_FORMAT+1, TEXT("0123456789")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SNEGATIVESIGN, sz_sNegativeSign, MAX_SNEGSIGN + 1 )) { //_tcscpy(sz_sNegativeSign, TEXT("-")); if(FAILED(StringCchCopy(sz_sNegativeSign, MAX_SNEGSIGN+1, TEXT("-")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SPOSITIVESIGN, sz_sPositiveSign, MAX_SPOSSIGN + 1 )) { //_tcscpy(sz_sPositiveSign, TEXT("")); if(FAILED(StringCchCopy(sz_sPositiveSign, MAX_SPOSSIGN+1, TEXT("")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_STHOUSAND, sz_sThousand, MAX_STHOUSAND + 1 )) { //_tcscpy(sz_sThousand, TEXT(",")); if(FAILED(StringCchCopy(sz_sThousand, MAX_STHOUSAND+1, TEXT(",")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_IDIGITS, sz_iDigits, MAX_IDIGITS + 1 )) { //_tcscpy(sz_iDigits, TEXT("2")); if(FAILED(StringCchCopy(sz_iDigits, MAX_IDIGITS+1, TEXT("2")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_ILZERO, sz_iLZero, MAX_ILZERO + 1 )) { //_tcscpy(sz_iLZero, TEXT("2")); if(FAILED(StringCchCopy(sz_iLZero, MAX_ILZERO+1, TEXT("2")))) { // This should be impossible, but we need to avoid PREfast complaints. } } } //////////////////////////////////////////////////////////////////////////// // // Number_RestoreValues // //////////////////////////////////////////////////////////////////////////// void Number_RestoreValues() { if (g_dwCustChange & Process_Num) { SetLocaleInfo(UserLocaleID, LOCALE_INEGNUMBER, sz_iNegNumber); SetLocaleInfo(UserLocaleID, LOCALE_IMEASURE, sz_iMeasure); SetLocaleInfo(UserLocaleID, LOCALE_IDIGITSUBSTITUTION, sz_NumShape); SetLocaleInfo(UserLocaleID, LOCALE_SDECIMAL, sz_sDecimal); SetLocaleInfo(UserLocaleID, LOCALE_SGROUPING, sz_sGrouping); SetLocaleInfo(UserLocaleID, LOCALE_SLIST, sz_sList); SetLocaleInfo(UserLocaleID, LOCALE_SNATIVEDIGITS, sz_sNativeDigits); SetLocaleInfo(UserLocaleID, LOCALE_SNEGATIVESIGN, sz_sNegativeSign); SetLocaleInfo(UserLocaleID, LOCALE_SPOSITIVESIGN, sz_sPositiveSign); SetLocaleInfo(UserLocaleID, LOCALE_STHOUSAND, sz_sThousand); SetLocaleInfo(UserLocaleID, LOCALE_IDIGITS, sz_iDigits); SetLocaleInfo(UserLocaleID, LOCALE_ILZERO, sz_iLZero); } } //////////////////////////////////////////////////////////////////////////// // // Number_ClearValues // // Reset each of the list boxes in the number property sheet page. // //////////////////////////////////////////////////////////////////////////// void Number_ClearValues( HWND hDlg) { ComboBox_ResetContent(GetDlgItem(hDlg, IDC_DECIMAL_SYMBOL)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_NEG_SIGN)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_SEPARATOR)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_DIGIT_GROUP_SYMBOL)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_NUM_DECIMAL_DIGITS)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_NUM_DIGITS_GROUP)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_DISPLAY_LEAD_0)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_NEG_NUM_FORMAT)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_MEASURE_SYS)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_NATIVE_DIGITS)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_DIGIT_SUBST)); } //////////////////////////////////////////////////////////////////////////// // // Number_SetValues // // Initialize all of the controls in the number property sheet page. // //////////////////////////////////////////////////////////////////////////// void Number_SetValues( HWND hDlg) { HWND hCtrl1, hCtrl2; HKEY hKey; int Index, Ctr1, Ctr2; DWORD cbData; TCHAR szBuf[SIZE_128]; const nMax_Array_Fill = (cInt_Str >= 10 ? 10 : cInt_Str); NUMBERFMT nfmt; TCHAR szThousandSep[SIZE_128]; TCHAR szEmpty[] = TEXT(""); TCHAR szSample[] = TEXT("123456789"); BOOL bShow; // // ---------------------------------------------------------------------- // Initialize the dropdown box for the current locale setting for: // Decimal Symbol // Positive Sign // Negative Sign // List Separator // Grouping Symbol // ---------------------------------------------------------------------- // DropDown_Use_Locale_Values(hDlg, LOCALE_SDECIMAL, IDC_DECIMAL_SYMBOL); DropDown_Use_Locale_Values(hDlg, LOCALE_SNEGATIVESIGN, IDC_NEG_SIGN); DropDown_Use_Locale_Values(hDlg, LOCALE_SLIST, IDC_SEPARATOR); DropDown_Use_Locale_Values(hDlg, LOCALE_STHOUSAND, IDC_DIGIT_GROUP_SYMBOL); // // ---------------------------------------------------------------------- // Fill in the Number of Digits after Decimal Symbol drop down list // with the values of 0 through 10. Get the user locale value and // make it the current selection. If GetLocaleInfo fails, simply // select the first item in the list. // ---------------------------------------------------------------------- // hCtrl1 = GetDlgItem(hDlg, IDC_NUM_DECIMAL_DIGITS); hCtrl2 = GetDlgItem(hDlg, IDC_NUM_DIGITS_GROUP); for (Index = 0; Index < nMax_Array_Fill; Index++) { ComboBox_InsertString(hCtrl1, -1, aInt_Str[Index]); } if (GetLocaleInfo(UserLocaleID, LOCALE_IDIGITS, szBuf, SIZE_128)) { ComboBox_SelectString(hCtrl1, -1, szBuf); } else { ComboBox_SetCurSel(hCtrl1, 0); } // // ---------------------------------------------------------------------- // Fill in the Number of Digits in "Thousands" Grouping's drop down // list with the appropriate options. Get the user locale value and // make it the current selection. If GetLocaleInfo fails, simply // select the first item in the list. // ---------------------------------------------------------------------- // nfmt.NumDigits = 0; // no decimal in sample string nfmt.LeadingZero = 0; // no decimal in sample string nfmt.lpDecimalSep = szEmpty; // no decimal in sample string nfmt.NegativeOrder = 0; // not a negative value nfmt.lpThousandSep = szThousandSep; GetLocaleInfo(UserLocaleID, LOCALE_STHOUSAND, szThousandSep, SIZE_128); nfmt.Grouping = 0; GetNumberFormat(UserLocaleID, 0, szSample, &nfmt, szBuf, SIZE_128); ComboBox_InsertString(hCtrl2, -1, szBuf); nfmt.Grouping = 3; GetNumberFormat(UserLocaleID, 0, szSample, &nfmt, szBuf, SIZE_128); ComboBox_InsertString(hCtrl2, -1, szBuf); nfmt.Grouping = 32; GetNumberFormat(UserLocaleID, 0, szSample, &nfmt, szBuf, SIZE_128); ComboBox_InsertString(hCtrl2, -1, szBuf); if (GetLocaleInfo(UserLocaleID, LOCALE_SGROUPING, szBuf, SIZE_128) && (szBuf[0])) { // // Since only the values 0, 3;0, and 3;2;0 are allowed, simply // ignore the ";#"s for subsequent groupings. // Index = 0; if (szBuf[0] == TEXT('3')) { if ((szBuf[1] == CHAR_SEMICOLON) && (szBuf[2] == TEXT('2'))) { Index = 2; } else { Index = 1; } } else { // // We used to allow the user to set #;0, where # is a value from // 0 - 9. If it's 0, then fall through so that Index is 0. // if ((szBuf[0] > CHAR_ZERO) && (szBuf[0] <= CHAR_NINE) && ((szBuf[1] == 0) || (lstrcmp(szBuf + 1, TEXT(";0")) == 0))) { nfmt.Grouping = szBuf[0] - CHAR_ZERO; if (GetNumberFormat(UserLocaleID, 0, szSample, &nfmt, szBuf, SIZE_128)) { Index = ComboBox_InsertString(hCtrl2, -1, szBuf); if (Index >= 0) { ComboBox_SetItemData( hCtrl2, Index, (LPARAM)((DWORD)nfmt.Grouping) ); } else { Index = 0; } } } } ComboBox_SetCurSel(hCtrl2, Index); } else { ComboBox_SetCurSel(hCtrl2, 0); } // // ---------------------------------------------------------------------- // Initialize and Lock function. If it succeeds, call enum function to // enumerate all possible values for the list box via a call to EnumProc. // EnumProc will call Set_List_Values for each of the string values it // receives. When the enumeration of values is complete, call // Set_List_Values to clear the dialog item specific data and to clear // the lock on the function. Perform this set of operations for: // Display Leading Zeros, Negative Number Format, and Measurement Systems. // ---------------------------------------------------------------------- // if (Set_List_Values(hDlg, IDC_DISPLAY_LEAD_0, 0)) { EnumLeadingZeros(EnumProcEx, UserLocaleID, 0); Set_List_Values(0, IDC_DISPLAY_LEAD_0, 0); if (GetLocaleInfo(UserLocaleID, LOCALE_ILZERO, szBuf, SIZE_128)) { ComboBox_SetCurSel( GetDlgItem(hDlg, IDC_DISPLAY_LEAD_0), Intl_StrToLong(szBuf) ); } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } } if (Set_List_Values(hDlg, IDC_NEG_NUM_FORMAT, 0)) { EnumNegNumFmt(EnumProcEx, UserLocaleID, 0); Set_List_Values(0, IDC_NEG_NUM_FORMAT, 0); if (GetLocaleInfo(UserLocaleID, LOCALE_INEGNUMBER, szBuf, SIZE_128)) { ComboBox_SetCurSel( GetDlgItem(hDlg, IDC_NEG_NUM_FORMAT), Intl_StrToLong(szBuf) ); } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } } if (Set_List_Values(hDlg, IDC_MEASURE_SYS, 0)) { EnumMeasureSystem(EnumProc, UserLocaleID, 0); Set_List_Values(0, IDC_MEASURE_SYS, 0); if (GetLocaleInfo(UserLocaleID, LOCALE_IMEASURE, szBuf, SIZE_128)) { ComboBox_SetCurSel( GetDlgItem(hDlg, IDC_MEASURE_SYS), Intl_StrToLong(szBuf) ); } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } } // // ---------------------------------------------------------------------- // Fill in the "Native Digits" dropdown and set the current selection. // Only show this combo box if there is more than one entry in the list. // ---------------------------------------------------------------------- // hCtrl1 = GetDlgItem(hDlg, IDC_NATIVE_DIGITS); ComboBox_AddString( hCtrl1, bLPKInstalled ? LPK_EUROPEAN_DIGITS : EUROPEAN_DIGITS ); ComboBox_SetCurSel(hCtrl1, 0); // // Go through the language groups to see which ones have extra native // digits options. // // Entry 0 in c_szNativeDigits is the European option. If any entries // in c_szDigitsPerLangGroup are 0 (European), then ignore them as the // European option is always enabled. // if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, LANGUAGE_GROUPS_KEY, 0L, KEY_READ, &hKey ) == ERROR_SUCCESS) { for (Ctr1 = 1; Ctr1 < MAX_LANG_GROUPS; Ctr1++) { // // This assumes that if the first entry of // c_szDigitsPerLangGroup is 0, then all other entries are 0. // if (c_szDigitsPerLangGroup[Ctr1][0] != 0) { // // See if the language group is installed. // cbData = 0; //wsprintf(szBuf, TEXT("%x"), Ctr1); if(SUCCEEDED(StringCchPrintf(szBuf, ARRAYSIZE(szBuf), TEXT("%x"), Ctr1))) { RegQueryValueEx(hKey, szBuf, NULL, NULL, NULL, &cbData); if (cbData > sizeof(TCHAR)) { // // Installed, so add the native digit options to // the combo box. // for (Ctr2 = 0; Ctr2 < MAX_DIGITS_PER_LG; Ctr2++) { if ((Index = c_szDigitsPerLangGroup[Ctr1][Ctr2]) != 0) { if (ComboBox_FindStringExact( hCtrl1, -1, c_szNativeDigits[Index] ) == CB_ERR) { ComboBox_AddString( hCtrl1, c_szNativeDigits[Index] ); } } } } } } } RegCloseKey(hKey); } // // Add the current user's Native Digits option if it's not already // in the combo box. // if (GetLocaleInfo( UserLocaleID, LOCALE_SNATIVEDIGITS, szBuf, SIZE_128 ) && (!Number_IsEuropeanDigits(szBuf))) { if ((Index = ComboBox_FindStringExact(hCtrl1, -1, szBuf)) == CB_ERR) { Index = ComboBox_AddString(hCtrl1, szBuf); } if (Index != CB_ERR) { ComboBox_SetCurSel(hCtrl1, Index); } } // // Add the default Native Digits option for the user's chosen locale // if it's not already in the combo box. // if (GetLocaleInfo( UserLocaleID, LOCALE_SNATIVEDIGITS | LOCALE_NOUSEROVERRIDE, szBuf, SIZE_128 ) && (!Number_IsEuropeanDigits(szBuf))) { if (ComboBox_FindStringExact(hCtrl1, -1, szBuf) == CB_ERR) { ComboBox_AddString(hCtrl1, szBuf); } } // // Disable the control if there is only 1 entry in the list. // bShow = ComboBox_GetCount(hCtrl1) > 1; EnableWindow(GetDlgItem(hDlg, IDC_NATIVE_DIGITS_TEXT), bShow); EnableWindow(GetDlgItem(hDlg, IDC_NATIVE_DIGITS), bShow); ShowWindow(GetDlgItem(hDlg, IDC_NATIVE_DIGITS_TEXT), bShow ? SW_SHOW : SW_HIDE); ShowWindow(GetDlgItem(hDlg, IDC_NATIVE_DIGITS), bShow ? SW_SHOW : SW_HIDE); // // ---------------------------------------------------------------------- // Fill in the "Digit Substitution" dropdown and set the current // selection. Only show this combo box if a language pack is installed. // ---------------------------------------------------------------------- // hCtrl1 = GetDlgItem(hDlg, IDC_DIGIT_SUBST); for (Index = 0; Index <= MAX_DIGIT_SUBST; Index++) { LoadString(hInstance, IDS_DIGIT_SUBST_CONTEXT + Index, szBuf, SIZE_128); ComboBox_InsertString(hCtrl1, Index, szBuf); } ComboBox_SetCurSel( hCtrl1, Number_GetDigitSubstitution() ); EnableWindow(GetDlgItem(hDlg, IDC_DIGIT_SUBST_TEXT), bLPKInstalled); EnableWindow(hCtrl1, bLPKInstalled); ShowWindow(GetDlgItem(hDlg, IDC_DIGIT_SUBST_TEXT), bLPKInstalled ? SW_SHOW : SW_HIDE); ShowWindow(hCtrl1, bLPKInstalled ? SW_SHOW : SW_HIDE); // // ---------------------------------------------------------------------- // Display the current sample that represents all of the locale settings. // ---------------------------------------------------------------------- // Number_DisplaySample(hDlg); } //////////////////////////////////////////////////////////////////////////// // // Number_ApplySettings // // For every control that has changed (that affects the Locale settings), // call Set_Locale_Values to update the user locale information. // Notify the parent of changes and reset the change flag stored in the // property sheet page structure appropriately. Redisplay the number // sample if bRedisplay is TRUE. // //////////////////////////////////////////////////////////////////////////// BOOL Number_ApplySettings( HWND hDlg, BOOL bRedisplay) { LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER)); LPARAM Changes = lpPropSheet->lParam; if (Changes & NC_DSymbol) { if (!Set_Locale_Values( hDlg, LOCALE_SDECIMAL, IDC_DECIMAL_SYMBOL, TEXT("sDecimal"), FALSE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_NSign) { if (!Set_Locale_Values( hDlg, LOCALE_SNEGATIVESIGN, IDC_NEG_SIGN, 0, FALSE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_SList) { if (!Set_Locale_Values( hDlg, LOCALE_SLIST, IDC_SEPARATOR, TEXT("sList"), FALSE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_SThousand) { if (!Set_Locale_Values( hDlg, LOCALE_STHOUSAND, IDC_DIGIT_GROUP_SYMBOL, TEXT("sThousand"), FALSE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_IDigits) { if (!Set_Locale_Values( hDlg, LOCALE_IDIGITS, IDC_NUM_DECIMAL_DIGITS, TEXT("iDigits"), TRUE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_DGroup) { if (!Set_Locale_Values( hDlg, LOCALE_SGROUPING, IDC_NUM_DIGITS_GROUP, 0, TRUE, 0, TEXT(";0"), NULL )) { return (FALSE); } } if (Changes & NC_LZero) { if (!Set_Locale_Values( hDlg, LOCALE_ILZERO, IDC_DISPLAY_LEAD_0, TEXT("iLzero"), TRUE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_NegFmt) { if (!Set_Locale_Values( hDlg, LOCALE_INEGNUMBER, IDC_NEG_NUM_FORMAT, 0, TRUE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_Measure) { if (!Set_Locale_Values( hDlg, LOCALE_IMEASURE, IDC_MEASURE_SYS, TEXT("iMeasure"), TRUE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_NativeDigits) { if (!Set_Locale_Values( hDlg, LOCALE_SNATIVEDIGITS, IDC_NATIVE_DIGITS, TEXT("sNativeDigits"), FALSE, 0, 0, NULL )) { return (FALSE); } } if (Changes & NC_DigitSubst) { if (!Set_Locale_Values( hDlg, LOCALE_IDIGITSUBSTITUTION, IDC_DIGIT_SUBST, TEXT("NumShape"), TRUE, 0, 0, NULL )) { return (FALSE); } } PropSheet_UnChanged(GetParent(hDlg), hDlg); lpPropSheet->lParam = NC_EverChg; // // Display the current sample that represents all of the locale settings. // if (bRedisplay) { Number_ClearValues(hDlg); Number_SetValues(hDlg); } // // Changes made in the second level. // if (Changes) { g_dwCustChange |= Process_Num; } // // Return success. // return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Number_ValidatePPS // // Validate each of the combo boxes whose values are constrained. // If any of the input fails, notify the user and then return FALSE // to indicate validation failure. // //////////////////////////////////////////////////////////////////////////// BOOL Number_ValidatePPS( HWND hDlg, LPARAM Changes) { // // If nothing has changed, return TRUE immediately. // if (Changes <= NC_EverChg) { return (TRUE); } // // If the decimal symbol has changed, ensure that there are no digits // contained in the new symbol. // if (Changes & NC_DSymbol && Item_Has_Digits(hDlg, IDC_DECIMAL_SYMBOL, FALSE)) { No_Numerals_Error(hDlg, IDC_DECIMAL_SYMBOL, IDS_LOCALE_DECIMAL_SYM); return (FALSE); } // // If the negative sign symbol has changed, ensure that there are no // digits contained in the new symbol. // if (Changes & NC_NSign && Item_Has_Digits(hDlg, IDC_NEG_SIGN, TRUE)) { No_Numerals_Error(hDlg, IDC_NEG_SIGN, IDS_LOCALE_NEG_SIGN); return (FALSE); } // // If the thousands grouping symbol has changed, ensure that there // are no digits contained in the new symbol. // if (Changes & NC_SThousand && Item_Has_Digits(hDlg, IDC_DIGIT_GROUP_SYMBOL, FALSE)) { No_Numerals_Error(hDlg, IDC_DIGIT_GROUP_SYMBOL, IDS_LOCALE_GROUP_SYM); return (FALSE); } // // Return success. // return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Number_InitPropSheet // // The extra long value for the property sheet page is used as a set of // state or change flags for each of the list boxes in the property sheet. // Initialize this value to 0. Call Number_SetValues with the property // sheet handle to initialize all of the property sheet controls. // Constrain the size of certain ComboBox text sizes. // //////////////////////////////////////////////////////////////////////////// void Number_InitPropSheet( HWND hDlg, LPARAM lParam) { // // The lParam holds a pointer to the property sheet page, save it for // later reference. // SetWindowLongPtr(hDlg, DWLP_USER, lParam); Number_SetValues(hDlg); ComboBox_LimitText(GetDlgItem(hDlg, IDC_NEG_SIGN), MAX_SNEGSIGN); ComboBox_LimitText(GetDlgItem(hDlg, IDC_DECIMAL_SYMBOL), MAX_SDECIMAL); ComboBox_LimitText(GetDlgItem(hDlg, IDC_DIGIT_GROUP_SYMBOL), MAX_STHOUSAND); ComboBox_LimitText(GetDlgItem(hDlg, IDC_SEPARATOR), MAX_SLIST); } //////////////////////////////////////////////////////////////////////////// // // NumberDlgProc // // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK NumberDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { NMHDR *lpnm; LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER)); switch (message) { case ( WM_NOTIFY ) : { lpnm = (NMHDR *)lParam; switch (lpnm->code) { case ( PSN_SETACTIVE ) : { // // If there has been a change in the regional Locale // setting, clear all of the current info in the // property sheet, get the new values, and update the // appropriate registry values. // if (Verified_Regional_Chg & Process_Num) { Verified_Regional_Chg &= ~Process_Num; Number_ClearValues(hDlg); Number_SetValues(hDlg); lpPropSheet->lParam = 0; } break; } case ( PSN_KILLACTIVE ) : { // // Validate the entries on the property page. // SetWindowLongPtr( hDlg, DWLP_MSGRESULT, !Number_ValidatePPS( hDlg, lpPropSheet->lParam ) ); break; } case ( PSN_APPLY ) : { // // Apply the settings. // if (Number_ApplySettings(hDlg, TRUE)) { SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); // // Zero out the NC_EverChg bit. // lpPropSheet->lParam = 0; } else { SetWindowLongPtr( hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE ); } break; } default : { return (FALSE); } } break; } case ( WM_INITDIALOG ) : { Number_InitPropSheet(hDlg, lParam); Number_SaveValues(); break; } case ( WM_DESTROY ) : { break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aNumberHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aNumberHelpIds ); break; } case ( WM_COMMAND ) : { switch (LOWORD(wParam)) { case ( IDC_DECIMAL_SYMBOL ) : { if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE) { lpPropSheet->lParam |= NC_DSymbol; } break; } case ( IDC_NEG_SIGN ) : { if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE) { lpPropSheet->lParam |= NC_NSign; } break; } case ( IDC_SEPARATOR ) : { if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE) { lpPropSheet->lParam |= NC_SList; } break; } case ( IDC_DIGIT_GROUP_SYMBOL ) : { if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE) { lpPropSheet->lParam |= NC_SThousand; } break; } case ( IDC_NUM_DECIMAL_DIGITS ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= NC_IDigits; } break; } case ( IDC_NUM_DIGITS_GROUP ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= NC_DGroup; } break; } case ( IDC_DISPLAY_LEAD_0 ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= NC_LZero; } break; } case ( IDC_NEG_NUM_FORMAT ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= NC_NegFmt; } break; } case ( IDC_MEASURE_SYS ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= NC_Measure; } break; } case ( IDC_NATIVE_DIGITS ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= NC_NativeDigits; } break; } case ( IDC_DIGIT_SUBST ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= NC_DigitSubst; } break; } } // // Turn on ApplyNow button. // if (lpPropSheet->lParam > NC_EverChg) { PropSheet_Changed(GetParent(hDlg), hDlg); } break; } default : { return (FALSE); } } // // Return success. // return (TRUE); }