/*++ Copyright (c) 1994-2000, Microsoft Corporation All rights reserved. Module Name: datedlg.c Abstract: This module implements the date property sheet for the Regional Options applet. Revision History: --*/ // // Include Files. // #include "intl.h" #include #include #include #include "intlhlp.h" #include "maxvals.h" #include "winnlsp.h" #define STRSAFE_LIB #include // // Context Help Ids. // static int aDateHelpIds[] = { IDC_GROUPBOX1, IDH_COMM_GROUPBOX, IDC_GROUPBOX2, IDH_COMM_GROUPBOX, IDC_GROUPBOX3, IDH_COMM_GROUPBOX, IDC_SAMPLE1, IDH_INTL_DATE_SHORTSAMPLE, IDC_SAMPLELBL1, IDH_INTL_DATE_SHORTSAMPLE, IDC_SAMPLE1A, IDH_INTL_DATE_SHORTSAMPLE_ARABIC, IDC_SAMPLELBL1A, IDH_INTL_DATE_SHORTSAMPLE_ARABIC, IDC_SHORT_DATE_STYLE, IDH_INTL_DATE_SHORTSTYLE, IDC_SEPARATOR, IDH_INTL_DATE_SEPARATOR, IDC_SAMPLE2, IDH_INTL_DATE_LONGSAMPLE, IDC_SAMPLELBL2, IDH_INTL_DATE_LONGSAMPLE, IDC_SAMPLE2A, IDH_INTL_DATE_LONGSAMPLE_ARABIC, IDC_SAMPLELBL2A, IDH_INTL_DATE_LONGSAMPLE_ARABIC, IDC_LONG_DATE_STYLE, IDH_INTL_DATE_LONGSTYLE, IDC_CALENDAR_TYPE_TEXT, IDH_INTL_DATE_CALENDARTYPE, IDC_CALENDAR_TYPE, IDH_INTL_DATE_CALENDARTYPE, IDC_TWO_DIGIT_YEAR_LOW, IDH_INTL_DATE_TWO_DIGIT_YEAR, IDC_TWO_DIGIT_YEAR_HIGH, IDH_INTL_DATE_TWO_DIGIT_YEAR, IDC_TWO_DIGIT_YEAR_ARROW, IDH_INTL_DATE_TWO_DIGIT_YEAR, IDC_ADD_HIJRI_DATE, IDH_INTL_DATE_ADD_HIJRI_DATE, IDC_ADD_HIJRI_DATE_TEXT, IDH_INTL_DATE_ADD_HIJRI_DATE, 0, 0 }; // // Global Variables. // TCHAR szNLS_LongDate[SIZE_128]; TCHAR szNLS_ShortDate[SIZE_128]; static TCHAR sz_iCalendarType[MAX_ICALTYPE + 1]; static TCHAR sz_sDate[MAX_SDATE + 1]; static TCHAR sz_sLongDate[MAX_SLONGDATE + 1]; static TCHAR sz_sShortDate[MAX_FORMAT + 1]; static const TCHAR c_szInternational[] = TEXT("Control Panel\\International"); static const TCHAR c_szAddHijriDate[] = TEXT("AddHijriDate"); static const TCHAR c_szAddHijriDateTemp[] = TEXT("AddHijriDateTemp"); static const PTSTR c_szAddHijriDateValues[] = { TEXT("AddHijriDate-2"), TEXT("AddHijriDate"), TEXT(""), TEXT("AddHijriDate+1"), TEXT("AddHijriDate+2") }; static const TCHAR c_szTwoDigitYearKey[] = TEXT("Software\\Policies\\Microsoft\\Control Panel\\International\\Calendars\\TwoDigitYearMax"); // // Function Prototypes. // void Date_InitializeHijriDateComboBox( HWND hDlg); //////////////////////////////////////////////////////////////////////////// // // Date_EnumerateDates // // Enumerates the appropriate dates for the chosen calendar. // //////////////////////////////////////////////////////////////////////////// void Date_EnumerateDates( HWND hDlg, DWORD dwDateFlag) { DWORD dwLocaleFlag; int nItemId; DWORD dwIndex; DWORD dwCalNum = 0; TCHAR szBuf[SIZE_128]; HWND hCtrlDate; HWND hCtrlCal = GetDlgItem(hDlg, IDC_CALENDAR_TYPE); // // Initialize variables according to the dwDateFlag parameter. // if (dwDateFlag == CAL_SSHORTDATE) { dwLocaleFlag = LOCALE_SSHORTDATE; nItemId = IDC_SHORT_DATE_STYLE; } else // CAL_SLONGDATE { dwLocaleFlag = LOCALE_SLONGDATE; nItemId = IDC_LONG_DATE_STYLE; } hCtrlDate = GetDlgItem(hDlg, nItemId); // // Initialize to reset the contents for the appropriate combo box. // if (!Set_List_Values(hDlg, nItemId, 0)) { return; } // // Reset the contents of the combo box. // ComboBox_ResetContent(hCtrlDate); // // Get the currently selected calendar id. // dwIndex = ComboBox_GetCurSel(hCtrlCal); if (dwIndex != CB_ERR) { dwCalNum = (DWORD)ComboBox_GetItemData(hCtrlCal, dwIndex); } // // Enumerate the dates for the currently selected calendar. // EnumCalendarInfo(EnumProc, UserLocaleID, dwCalNum, dwDateFlag); dwIndex = ComboBox_GetCount(hCtrlCal); if ((dwIndex == 0) || (dwIndex == CB_ERR)) { EnumCalendarInfo(EnumProc, UserLocaleID, CAL_GREGORIAN, dwDateFlag); } // // Add (if necesary) and select the current user setting in the // combo box. // dwIndex = 0; if (GetLocaleInfo(UserLocaleID, dwLocaleFlag, szBuf, SIZE_128)) { if ((dwIndex = ComboBox_FindStringExact(hCtrlDate, -1, szBuf)) == CB_ERR) { // // Need to add this entry to the combo box. // Set_List_Values(0, 0, szBuf); if ((dwIndex = ComboBox_FindStringExact(hCtrlDate, -1, szBuf)) == CB_ERR) { dwIndex = 0; } } } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } Set_List_Values(0, nItemId, 0); Localize_Combobox_Styles(hDlg, nItemId, dwLocaleFlag); ComboBox_SetCurSel(hCtrlDate, dwIndex); } //////////////////////////////////////////////////////////////////////////// // // Date_GetTwoDigitYearRangeFromPolicy // // Read the two digit year from the Policy registry. // //////////////////////////////////////////////////////////////////////////// BOOL Date_GetTwoDigitYearRangeFromPolicy( CALID CalId) { HKEY hKey; BYTE buf[MAX_PATH]; TCHAR szCalId[MAX_PATH]; DWORD dwResultLen = sizeof(buf), dwType; BOOL bRet = FALSE; // // Convert CalendarId to a string. // //wsprintf(szCalId, TEXT("%d"), CalId); if(FAILED(StringCchPrintf(szCalId, ARRAYSIZE(szCalId), TEXT("%d"), CalId))) { return(FALSE); } if (RegOpenKey( HKEY_CURRENT_USER, c_szTwoDigitYearKey, &hKey ) == ERROR_SUCCESS) { if ((RegQueryValueEx( hKey, szCalId, NULL, &dwType, &buf[0], &dwResultLen ) == ERROR_SUCCESS) && (dwType == REG_SZ) && (dwResultLen > 2)) { bRet = TRUE; } RegCloseKey(hKey); } // // Return the result. // return (bRet); } //////////////////////////////////////////////////////////////////////////// // // Date_GetTwoDigitYearRange // // Fills in the two digit year range controls. // //////////////////////////////////////////////////////////////////////////// void Date_GetTwoDigitYearRange( HWND hDlg, CALID CalId) { HWND hwndYearHigh = GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_HIGH); HWND hwndScroll = GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_ARROW); DWORD YearHigh, YearHighDefault; // // Enable the high range control. // EnableWindow(hwndYearHigh, TRUE); EnableWindow(hwndScroll, TRUE); // // Get the default two digit year upper boundary. // if (!GetCalendarInfo( LOCALE_USER_DEFAULT, CalId, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER | CAL_NOUSEROVERRIDE, NULL, 0, &YearHighDefault )) { YearHighDefault = 0; } // // Disable the two digit year upper boundary control if it is // enforced by a policy or if the default value is 99 or less. // if ((Date_GetTwoDigitYearRangeFromPolicy(CalId)) || (YearHighDefault <= 99)) { // // Disable the two digit year max controls. // EnableWindow(hwndScroll, FALSE); EnableWindow(hwndYearHigh, FALSE); } // // Get the two digit year upper boundary. If the default is less // than or equal to 99, then use the default value and ignore the // registry. This is done for calendars like the Japanese Era // calendar where it doesn't make sense to have a sliding window. // if (YearHighDefault <= 99) { YearHigh = YearHighDefault; } else if (!GetCalendarInfo( LOCALE_USER_DEFAULT, CalId, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER, NULL, 0, &YearHigh ) || (YearHigh < 99) || (YearHigh > 9999)) { YearHigh = (YearHighDefault >= 99) ? YearHighDefault : 2029; } // // Set the range on the controls. // SendMessage(hwndScroll, UDM_SETRANGE, 0, MAKELPARAM(9999, 99)); SendMessage(hwndScroll, UDM_SETBUDDY, (WPARAM)hwndYearHigh, 0L); // // Set the values of the controls. // SetDlgItemInt(hDlg, IDC_TWO_DIGIT_YEAR_LOW, (UINT)(YearHigh - 99), FALSE); SendMessage(hwndScroll, UDM_SETPOS, 0, MAKELONG((short)YearHigh, 0)); } //////////////////////////////////////////////////////////////////////////// // // Date_SetTwoDigitYearMax // // Sets the two digit year max value in the registry. // //////////////////////////////////////////////////////////////////////////// BOOL Date_SetTwoDigitYearMax( HWND hDlg, CALID CalId) { TCHAR szYear[SIZE_64]; // // Get the max year. // szYear[0] = 0; if (GetWindowText( GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_HIGH), szYear, SIZE_64 ) != 0) { // // Set the two digit year upper boundary. // return (SetCalendarInfo( LOCALE_USER_DEFAULT, CalId, CAL_ITWODIGITYEARMAX, szYear )); } // // Return success. // return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Date_ChangeYear // // Changes the lower bound based on the upper bound value. // //////////////////////////////////////////////////////////////////////////// void Date_ChangeYear( HWND hDlg) { DWORD YearHigh; BOOL bSuccess; // // Get the two digit year upper boundary. // YearHigh = GetDlgItemInt(hDlg, IDC_TWO_DIGIT_YEAR_HIGH, &bSuccess, FALSE); if ((!bSuccess) || (YearHigh < 99) || (YearHigh > 9999)) { // // Invalid value, so set the lower control to 0. // SetDlgItemInt(hDlg, IDC_TWO_DIGIT_YEAR_LOW, 0, FALSE); } else { // // Set the value of the lower control. // SetDlgItemInt(hDlg, IDC_TWO_DIGIT_YEAR_LOW, (UINT)(YearHigh - 99), FALSE); } } //////////////////////////////////////////////////////////////////////////// // // Date_DisplaySample // // Updates the date samples. It formats the date based on the user's // current locale settings. // //////////////////////////////////////////////////////////////////////////// void Date_DisplaySample( HWND hDlg) { TCHAR szBuf[MAX_SAMPLE_SIZE]; BOOL bNoError = TRUE; if (!bShowArabic) { // If user locale is not Arabic, make sure that the control for date samples are: // * LTR reading orders for non-Hebrew locales // * RTL reading orders for Hebrew locales. SetControlReadingOrder(bHebrewUI, GetDlgItem(hDlg, IDC_SAMPLE1)); SetControlReadingOrder(bHebrewUI, GetDlgItem(hDlg, IDC_SAMPLE2)); } // In Hebrew locale, we want to format the short date for left-to-right reading order. // If we make it right-to-left reading order, the Gregorian short date will display // in a complete different display order. // The left-to-right reading order won't affect the Hebrew short date display. if (GetDateFormat( UserLocaleID, (bHebrewUI ? DATE_LTRREADING : (bShowRtL ? DATE_LTRREADING : 0)) | DATE_SHORTDATE, NULL, NULL, szBuf, MAX_SAMPLE_SIZE )) { SetDlgItemText(hDlg, IDC_SAMPLE1, szBuf); } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); bNoError = FALSE; } // // 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); if (bShowArabic) { if (GetDateFormat( UserLocaleID, DATE_RTLREADING | DATE_SHORTDATE, NULL, NULL, szBuf, MAX_SAMPLE_SIZE )) { SetDlgItemText(hDlg, IDC_SAMPLE1A, szBuf); SetDlgItemRTL(hDlg, IDC_SAMPLE1A); } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); bNoError = FALSE; } } if (GetDateFormat( UserLocaleID, (bHebrewUI ? DATE_RTLREADING : (bShowRtL ? DATE_LTRREADING : 0)) | DATE_LONGDATE, NULL, NULL, szBuf, MAX_SAMPLE_SIZE )) { SetDlgItemText(hDlg, IDC_SAMPLE2, szBuf); } else if (bNoError) { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } // // Show or hide the Right to left info based on the current user locale id. // ShowWindow(GetDlgItem(hDlg, IDC_SAMPLELBL2A), bShowArabic ? SW_SHOW : SW_HIDE); ShowWindow(GetDlgItem(hDlg, IDC_SAMPLE2A), bShowArabic ? SW_SHOW : SW_HIDE); if (bShowArabic) { if (GetDateFormat( UserLocaleID, DATE_RTLREADING | DATE_LONGDATE, NULL, NULL, szBuf, MAX_SAMPLE_SIZE )) { SetDlgItemText(hDlg, IDC_SAMPLE2A, szBuf); SetDlgItemRTL(hDlg, IDC_SAMPLE2A); } else if (bNoError) { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } } } //////////////////////////////////////////////////////////////////////////// // // Date_ClearValues // // Reset each of the list boxes in the date property sheet page. // //////////////////////////////////////////////////////////////////////////// void Date_ClearValues( HWND hDlg) { ComboBox_ResetContent(GetDlgItem(hDlg, IDC_SHORT_DATE_STYLE)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_LONG_DATE_STYLE)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_SEPARATOR)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_CALENDAR_TYPE)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_LOW)); ComboBox_ResetContent(GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_HIGH)); } //////////////////////////////////////////////////////////////////////////// // // Date_EnableHijriComboBox // // Enables/Disables Show/Hides the Hijri date advance combo where necessary // //////////////////////////////////////////////////////////////////////////// void Date_EnableHijriComboBox( HWND hDlg, BOOL Status) { HWND hAddHijriDateCB = GetDlgItem(hDlg, IDC_ADD_HIJRI_DATE); HWND hAddHijriDateText = GetDlgItem(hDlg, IDC_ADD_HIJRI_DATE_TEXT); INT iCount; // // If the combo box is empty, then disable it. // iCount = (INT)SendMessage(hAddHijriDateCB, CB_GETCOUNT, 0L, 0L); if ((iCount == CB_ERR) || (iCount <= 0L)) { Status = FALSE; } EnableWindow(hAddHijriDateCB, Status); ShowWindow(hAddHijriDateCB, Status ? SW_SHOW : SW_HIDE ); EnableWindow(hAddHijriDateText, Status); ShowWindow(hAddHijriDateText, Status ? SW_SHOW : SW_HIDE); } //////////////////////////////////////////////////////////////////////////// // // Date_SaveValues // // Save values in the case that we need to restore them. // //////////////////////////////////////////////////////////////////////////// void Date_SaveValues() { // // Save registry values. // if (!GetLocaleInfo( UserLocaleID, LOCALE_ICALENDARTYPE, sz_iCalendarType, MAX_ICALTYPE + 1 )) { //_tcscpy(sz_iCalendarType, TEXT("1")); if(FAILED(StringCchCopy(sz_iCalendarType, MAX_ICALTYPE+1, TEXT("1")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SDATE, sz_sDate, MAX_SDATE + 1 )) { //_tcscpy(sz_sDate, TEXT("/")); if(FAILED(StringCchCopy(sz_sDate, MAX_SDATE+1, TEXT("/")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SLONGDATE, sz_sLongDate, MAX_SLONGDATE + 1 )) { //_tcscpy(sz_sLongDate, TEXT("dddd, MMMM dd, yyyy")); if(FAILED(StringCchCopy(sz_sLongDate, MAX_SLONGDATE+1, TEXT("dddd, MMMM dd, yyyy")))) { // This should be impossible, but we need to avoid PREfast complaints. } } if (!GetLocaleInfo( UserLocaleID, LOCALE_SSHORTDATE, sz_sShortDate, MAX_SSHORTDATE + 1 )) { //_tcscpy(sz_sShortDate, TEXT("M/d/yyyy")); if(FAILED(StringCchCopy(sz_sShortDate, MAX_SSHORTDATE+1, TEXT("M/d/yyyy")))) { // This should be impossible, but we need to avoid PREfast complaints. } } } //////////////////////////////////////////////////////////////////////////// // // Date_RestoreValues // //////////////////////////////////////////////////////////////////////////// void Date_RestoreValues() { if (g_dwCustChange & Process_Date) { SetLocaleInfo(UserLocaleID, LOCALE_ICALENDARTYPE, sz_iCalendarType); SetLocaleInfo(UserLocaleID, LOCALE_SDATE, sz_sDate); SetLocaleInfo(UserLocaleID, LOCALE_SLONGDATE, sz_sLongDate); SetLocaleInfo(UserLocaleID, LOCALE_SSHORTDATE, sz_sShortDate); } } //////////////////////////////////////////////////////////////////////////// // // Date_SetValues // // Initialize all of the controls in the date property sheet page. // //////////////////////////////////////////////////////////////////////////// void Date_SetValues( HWND hDlg) { TCHAR szBuf[SIZE_128]; int i, nItem; HWND hCtrl; LONG CalId; // // Initialize the dropdown box for the current locale setting for the // date separator. // DropDown_Use_Locale_Values(hDlg, LOCALE_SDATE, IDC_SEPARATOR); // // 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: // Calendar Type, Short Date Sytle, and Long Date Style. // if (Set_List_Values(hDlg, IDC_CALENDAR_TYPE, 0)) { hCtrl = GetDlgItem(hDlg, IDC_CALENDAR_TYPE); EnumCalendarInfo(EnumProc, UserLocaleID, ENUM_ALL_CALENDARS, CAL_SCALNAME); Set_List_Values(0, IDC_CALENDAR_TYPE, 0); EnumCalendarInfo(EnumProc, UserLocaleID, ENUM_ALL_CALENDARS, CAL_ICALINTVALUE); Set_List_Values(0, IDC_CALENDAR_TYPE, 0); if (GetLocaleInfo(UserLocaleID, LOCALE_ICALENDARTYPE, szBuf, SIZE_128)) { TCHAR szBufTmp[SIZE_128] = {0}; int iTmp = 0; LONG CalIdTmp; if( GetLocaleInfo( UserLocaleID, LOCALE_ICALENDARTYPE | LOCALE_NOUSEROVERRIDE, szBufTmp, SIZE_128)) { // // Convert the id to a number. // CalId = Intl_StrToLong(szBuf); CalIdTmp = Intl_StrToLong(szBufTmp); // // Search for calendars // nItem = ComboBox_GetCount(hCtrl); for (i = 0; i < nItem; i++) { if (ComboBox_GetItemData(hCtrl, i) == CalId) { break; } if (ComboBox_GetItemData(hCtrl, i) == CalIdTmp) { iTmp = i; } } // // Look if we find something. // if (i < nItem) { ComboBox_SetCurSel(hCtrl, i); } else { CalId = CalIdTmp; ComboBox_SetCurSel(hCtrl, iTmp); // Zero or something else. } // // Enable/disable the Add Hijri date check box. // Date_InitializeHijriDateComboBox(hDlg); Date_EnableHijriComboBox(hDlg, (CalId == CAL_HIJRI)); // // Set the two digit year range. // Date_GetTwoDigitYearRange(hDlg, (CALID)CalId); // // Subtract 1 from calendar value because calendars are one // based, not zero based like all other locale values. // } } else { MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION); } // // If more than one selection, enable dropdown box. // Otherwise, disable it. // if (ComboBox_GetCount(hCtrl) > 1) { EnableWindow(GetDlgItem(hDlg, IDC_CALENDAR_TYPE_TEXT), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_CALENDAR_TYPE), TRUE); ShowWindow(GetDlgItem(hDlg, IDC_CALENDAR_TYPE_TEXT), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDC_CALENDAR_TYPE), SW_SHOW); } else { EnableWindow(GetDlgItem(hDlg, IDC_CALENDAR_TYPE_TEXT), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_CALENDAR_TYPE), FALSE); ShowWindow(GetDlgItem(hDlg, IDC_CALENDAR_TYPE_TEXT), SW_HIDE); ShowWindow(GetDlgItem(hDlg, IDC_CALENDAR_TYPE), SW_HIDE); } } Date_EnumerateDates(hDlg, CAL_SSHORTDATE); Date_EnumerateDates(hDlg, CAL_SLONGDATE); // // Display the current sample that represents all of the locale settings. // Date_DisplaySample(hDlg); } //////////////////////////////////////////////////////////////////////////// // // Date_SetHijriDate // // Saves the Hijri date advance amount to the registry. // //////////////////////////////////////////////////////////////////////////// void Date_SetHijriDate( HWND hHijriComboBox) { HKEY hKey; INT iIndex; // // Get the string index to set. // iIndex = (INT)SendMessage(hHijriComboBox, CB_GETCURSEL, 0L, 0L); if (iIndex == CB_ERR) { return; } iIndex = (INT)SendMessage(hHijriComboBox, CB_GETITEMDATA, (WPARAM)iIndex, 0L); if (iIndex != CB_ERR) { if (RegOpenKeyEx( HKEY_CURRENT_USER, c_szInternational, 0, KEY_READ | KEY_WRITE, &hKey ) == ERROR_SUCCESS) { RegSetValueEx( hKey, c_szAddHijriDate, 0, REG_SZ, (LPBYTE)c_szAddHijriDateValues[iIndex], (lstrlen(c_szAddHijriDateValues[iIndex]) + 1) * sizeof(TCHAR) ); RegCloseKey(hKey); } } } //////////////////////////////////////////////////////////////////////////// // // Date_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 date sample if // bRedisplay is TRUE. // //////////////////////////////////////////////////////////////////////////// BOOL Date_ApplySettings( HWND hDlg, BOOL bRedisplay) { TCHAR szBuf[SIZE_128]; CALID CalId = 0; LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER)); LPARAM Changes = lpPropSheet->lParam; HWND hwndYearHigh = GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_HIGH); if (Changes & DC_ShortFmt) { // // szNLS_ShortDate is set in Date_ValidatePPS. // if (!Set_Locale_Values( hDlg, LOCALE_SSHORTDATE, IDC_SHORT_DATE_STYLE, TEXT("sShortDate"), FALSE, 0, 0, szNLS_ShortDate )) { return (FALSE); } // // If the date separator field has also been changed by the user, // then don't update now. It will be updated below. // if (!(Changes & DC_SDate)) { // // Since the short date style changed, reset date separator // list box. // ComboBox_ResetContent(GetDlgItem(hDlg, IDC_SEPARATOR)); DropDown_Use_Locale_Values(hDlg, LOCALE_SDATE, IDC_SEPARATOR); if (!Set_Locale_Values( hDlg, LOCALE_SDATE, IDC_SEPARATOR, TEXT("sDate"), FALSE, 0, 0, NULL )) { return (FALSE); } } } if (Changes & DC_LongFmt) { // // szNLS_LongDate is set in Date_ValidatePPS. // if (!Set_Locale_Values( hDlg, LOCALE_SLONGDATE, IDC_LONG_DATE_STYLE, TEXT("sLongDate"), FALSE, 0, 0, szNLS_LongDate )) { return (FALSE); } } if (Changes & DC_SDate) { if (!Set_Locale_Values( hDlg, LOCALE_SDATE, IDC_SEPARATOR, TEXT("sDate"), FALSE, 0, 0, NULL )) { return (FALSE); } // // Since the date separator changed, reset the short date style // list box. // Date_EnumerateDates(hDlg, CAL_SSHORTDATE); } if (Changes & DC_Calendar) { if (!Set_Locale_Values( hDlg, LOCALE_ICALENDARTYPE, IDC_CALENDAR_TYPE, 0, TRUE, 1, 0, NULL )) { return (FALSE); } if (GetLocaleInfo(UserLocaleID, LOCALE_ICALENDARTYPE, szBuf, SIZE_128)) { CalId = Intl_StrToLong(szBuf); Date_InitializeHijriDateComboBox(hDlg); Date_EnableHijriComboBox(hDlg, (CalId == CAL_HIJRI)); } } if (Changes & DC_Arabic_Calendar) { Date_SetHijriDate( GetDlgItem(hDlg, IDC_ADD_HIJRI_DATE) ); } if (Changes & DC_TwoDigitYearMax) { if (CalId == 0) { HWND hCtrl = GetDlgItem(hDlg, IDC_CALENDAR_TYPE); int index; if ((index = ComboBox_GetCurSel(hCtrl)) == CB_ERR) { if (GetLocaleInfo( UserLocaleID, LOCALE_ICALENDARTYPE | LOCALE_NOUSEROVERRIDE, szBuf, SIZE_128)) { CalId = Intl_StrToLong(szBuf); } else { return (FALSE); } } else { CalId = (CALID)ComboBox_GetItemData(hCtrl, index); } } if (!Date_SetTwoDigitYearMax(hDlg, CalId)) { // // Make sure that the API failed due to a reason other than // the upper year two digit max is <= 99. This can easily // be checked by seeing if the control is enabled or not. // if (IsWindowEnabled(hwndYearHigh)) { return (FALSE); } } } PropSheet_UnChanged(GetParent(hDlg), hDlg); lpPropSheet->lParam = DC_EverChg; // // Display the current sample that represents all of the locale settings. // if (bRedisplay) { Date_DisplaySample(hDlg); } // // Changes made in the second level. // if (Changes) { g_dwCustChange |= Process_Date; } // // Return success. // return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Date_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 Date_ValidatePPS( HWND hDlg, LPARAM Changes) { // // If nothing has changed, return TRUE immediately. // if (Changes <= DC_EverChg) { return (TRUE); } // // If the date separator has changed, ensure that there are no digits // and no invalid characters contained in the new separator. // if (Changes & DC_SDate && Item_Has_Digits_Or_Invalid_Chars( hDlg, IDC_SEPARATOR, FALSE, szInvalidSDate )) { No_Numerals_Error(hDlg, IDC_SEPARATOR, IDS_LOCALE_DATE_SEP); return (FALSE); } // // If the short date style has changed, ensure that there are only // characters in this set " dHhMmsty,-./:;\", the separator string, // and text enclosed in single quotes. // if (Changes & DC_ShortFmt) { if (NLSize_Style( hDlg, IDC_SHORT_DATE_STYLE, szNLS_ShortDate, LOCALE_SSHORTDATE ) || Item_Check_Invalid_Chars( hDlg, szNLS_ShortDate, szSDateChars, IDC_SEPARATOR, FALSE, szSDCaseSwap, IDC_SHORT_DATE_STYLE )) { Invalid_Chars_Error(hDlg, IDC_SHORT_DATE_STYLE, IDS_LOCALE_SDATE); return (FALSE); } } // // If the long date style has changed, ensure that there are only // characters in this set " dgHhMmsty,-./:;\", the separator string, // and text enclosed in single quotes. // if (Changes & DC_LongFmt) { if (NLSize_Style( hDlg, IDC_LONG_DATE_STYLE, szNLS_LongDate, LOCALE_SLONGDATE ) || Item_Check_Invalid_Chars( hDlg, szNLS_LongDate, szLDateChars, IDC_SEPARATOR, FALSE, szLDCaseSwap, IDC_LONG_DATE_STYLE )) { Invalid_Chars_Error(hDlg, IDC_LONG_DATE_STYLE, IDS_LOCALE_LDATE); return (FALSE); } } // // If the two digit year has changed, make sure the value is between // 99 and 9999 (if the window is still enabled). // if (Changes & DC_TwoDigitYearMax) { DWORD YearHigh; BOOL bSuccess; if (IsWindowEnabled(GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_HIGH))) { YearHigh = GetDlgItemInt( hDlg, IDC_TWO_DIGIT_YEAR_HIGH, &bSuccess, FALSE ); if ((!bSuccess) || (YearHigh < 99) || (YearHigh > 9999)) { TCHAR szBuf[SIZE_128]; LoadString(hInstance, IDS_LOCALE_YEAR_ERROR, szBuf, SIZE_128); MessageBox(hDlg, szBuf, NULL, MB_OK | MB_ICONINFORMATION); SetFocus(GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_HIGH)); return (FALSE); } } } // // Return success. // return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Date_InitializeHijriDateComboBox // // Initialize the HijriDate advance combo box. // //////////////////////////////////////////////////////////////////////////// void Date_InitializeHijriDateComboBox( HWND hDlg) { HWND hHijriDate = GetDlgItem(hDlg, IDC_ADD_HIJRI_DATE); HKEY hKey; TCHAR szBuf[128]; TCHAR szCurrentValue[16]; // Max size ever needed should be 15 characters including the NULL INT iIndex; DWORD dwCtr, dwNumEntries, DataLen; // // Clear contents. // SendMessage( hHijriDate, CB_RESETCONTENT, 0L, 0L); if (RegOpenKeyEx( HKEY_CURRENT_USER, c_szInternational, 0, KEY_READ | KEY_WRITE, &hKey ) == ERROR_SUCCESS) { // // Read the default/current value. // // Use the byte count, the API expects that even for Unicode strings DataLen = sizeof(szCurrentValue); if (RegQueryValueEx( hKey, c_szAddHijriDate, NULL, NULL, (LPBYTE)szCurrentValue, &DataLen ) != ERROR_SUCCESS) { szCurrentValue[0] = TEXT('\0'); } dwNumEntries = (ARRAYSIZE(c_szAddHijriDateValues)); for (dwCtr = 0; dwCtr < dwNumEntries; dwCtr++) { // // Fill the combo box. // if (RegSetValueEx( hKey, c_szAddHijriDateTemp, 0, REG_SZ, (LPBYTE)c_szAddHijriDateValues[dwCtr], (lstrlen(c_szAddHijriDateValues[dwCtr]) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS) { // // 0x80000000 is a private flag to make GetDateFormat read // the HijriDate setting from the temp reg value. // if (GetDateFormat( MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), DATE_ADDHIJRIDATETEMP | DATE_LONGDATE | DATE_RTLREADING, NULL, NULL, szBuf, ARRAYSIZE(szBuf))) { iIndex = (INT)SendMessage(hHijriDate, CB_ADDSTRING, 0L, (LPARAM)szBuf); if (iIndex != CB_ERR) { SendMessage(hHijriDate, CB_SETITEMDATA, iIndex, (LPARAM)dwCtr); if (!lstrcmp(szCurrentValue, c_szAddHijriDateValues[dwCtr])) { SendMessage(hHijriDate, CB_SETCURSEL, iIndex, 0L); } } } } } // // Delete the value after we're done. // RegDeleteValue(hKey, c_szAddHijriDateTemp); RegCloseKey(hKey); } } //////////////////////////////////////////////////////////////////////////// // // Date_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 Date_SetValues with the property // sheet handle and the value TRUE (to indicate that the Positive Value // button should also be initialized) to initialize all of the property // sheet controls. // //////////////////////////////////////////////////////////////////////////// void Date_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); // // Set the values. // Date_SetValues(hDlg); szNLS_ShortDate[0] = szNLS_LongDate[0] = 0; ComboBox_LimitText(GetDlgItem(hDlg, IDC_SEPARATOR), MAX_SDATE); ComboBox_LimitText(GetDlgItem(hDlg, IDC_SHORT_DATE_STYLE), MAX_FORMAT); ComboBox_LimitText(GetDlgItem(hDlg, IDC_LONG_DATE_STYLE), MAX_FORMAT); Edit_LimitText(GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_LOW), MAX_YEAR); Edit_LimitText(GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_HIGH), MAX_YEAR); // // Set the Add Hijri Date combo box appropriately. // if (bShowArabic) { Date_InitializeHijriDateComboBox(hDlg); } // // Make sure the Apply button is off. // PropSheet_UnChanged(GetParent(hDlg), hDlg); if (lParam) { ((LPPROPSHEETPAGE)lParam)->lParam = DC_EverChg; } } //////////////////////////////////////////////////////////////////////////// // // DateDlgProc // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK DateDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { NMHDR *lpnm; LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER)); DWORD dwIndex; HWND hCtrl; switch (message) { case ( WM_INITDIALOG ) : { Date_InitPropSheet(hDlg, lParam); Date_SaveValues(); break; } case ( WM_DESTROY ) : { break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aDateHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aDateHelpIds ); break; } case ( WM_COMMAND ) : { if (!lpPropSheet) { break; } switch ( LOWORD(wParam) ) { case ( IDC_SHORT_DATE_STYLE ) : { if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE) { lpPropSheet->lParam |= DC_ShortFmt; } break; } case ( IDC_LONG_DATE_STYLE ) : { if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE) { lpPropSheet->lParam |= DC_LongFmt; } break; } case ( IDC_SEPARATOR ) : { if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE) { lpPropSheet->lParam |= DC_SDate; } break; } case ( IDC_CALENDAR_TYPE ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= DC_Calendar; hCtrl = GetDlgItem(hDlg, IDC_CALENDAR_TYPE); dwIndex = ComboBox_GetCurSel(hCtrl); if (dwIndex != CB_ERR) { dwIndex = (DWORD)ComboBox_GetItemData(hCtrl, dwIndex); Date_InitializeHijriDateComboBox(hDlg); Date_EnableHijriComboBox(hDlg, (dwIndex == CAL_HIJRI) ); Date_GetTwoDigitYearRange(hDlg, (CALID)dwIndex); } Date_EnumerateDates(hDlg, CAL_SSHORTDATE); Date_EnumerateDates(hDlg, CAL_SLONGDATE); } break; } case ( IDC_ADD_HIJRI_DATE ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { lpPropSheet->lParam |= DC_Arabic_Calendar; } break; } case ( IDC_TWO_DIGIT_YEAR_HIGH ) : { if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { Date_ChangeYear(hDlg); lpPropSheet->lParam |= DC_TwoDigitYearMax; } break; } } // // Turn on ApplyNow button. // if (lpPropSheet->lParam > DC_EverChg) { PropSheet_Changed(GetParent(hDlg), hDlg); } break; } 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_Date) { Verified_Regional_Chg &= ~Process_Date; Date_ClearValues(hDlg); Date_SetValues(hDlg); lpPropSheet->lParam = 0; } break; } case ( PSN_KILLACTIVE ) : { // // Validate the entries on the property page. // SetWindowLongPtr( hDlg, DWLP_MSGRESULT, !Date_ValidatePPS( hDlg, lpPropSheet->lParam ) ); break; } case ( PSN_APPLY ) : { // // Apply the settings. // if (Date_ApplySettings(hDlg, TRUE)) { SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); // // Zero out the DC_EverChg bit. // lpPropSheet->lParam = 0; } else { SetWindowLongPtr( hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE ); } break; } default : { return (FALSE); } } break; } case ( WM_VSCROLL ) : { if ((GET_WM_VSCROLL_CODE(wParam, lParam) == SB_ENDSCROLL) && ((HWND)SendMessage( GET_WM_VSCROLL_HWND(wParam, lParam), UDM_GETBUDDY, 0, 0L ) == GetDlgItem(hDlg, IDC_TWO_DIGIT_YEAR_HIGH))) { DWORD YearHigh; // // Get the high year. // YearHigh = (DWORD)SendDlgItemMessage( hDlg, IDC_TWO_DIGIT_YEAR_ARROW, UDM_GETPOS, 0, 0L ); // // Set the low year based on the high year. // SetDlgItemInt( hDlg, IDC_TWO_DIGIT_YEAR_LOW, (UINT)(YearHigh - 99), FALSE ); // // Mark it as changed. // lpPropSheet->lParam |= DC_TwoDigitYearMax; // // Turn on ApplyNow button. // PropSheet_Changed(GetParent(hDlg), hDlg); } break; } default : { return (FALSE); } } // // Return success. // return (TRUE); }