3 * Copyright (C) 2004 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/date.c
22 * PURPOSE: Date property page
23 * PROGRAMMER: Eric Kohl
28 /* GLOBALS ******************************************************************/
30 #define YEAR_STR_MAX_SIZE 5
31 #define MAX_SHRT_DATE_SEPARATORS 3
32 #define STD_DATE_SEP _T(".")
33 #define YEAR_DIFF (99)
34 #define MAX_YEAR (9999)
36 static HWND hwndEnum
= NULL
;
38 /* FUNCTIONS ****************************************************************/
40 /* If char is 'y' or 'M' or 'd' return TRUE, else FALSE */
42 isDateCompAl(TCHAR alpha
)
44 if ((alpha
== _T('y')) || (alpha
== _T('M')) || (alpha
== _T('d')) || (alpha
== _T(' ')))
50 /* Find first date separator in string */
52 FindDateSep(const TCHAR
*szSourceStr
)
55 UINT nDateCompCount
=0;
58 pszFoundSep
= (LPTSTR
)malloc(MAX_SAMPLES_STR_SIZE
* sizeof(TCHAR
));
63 _tcscpy(pszFoundSep
,STD_DATE_SEP
);
65 while (nDateCompCount
< _tcslen(szSourceStr
))
67 if (!isDateCompAl(szSourceStr
[nDateCompCount
]) && (szSourceStr
[nDateCompCount
] != _T('\'')))
69 while (!isDateCompAl(szSourceStr
[nDateCompCount
]) && (szSourceStr
[nDateCompCount
] != _T('\'')))
71 pszFoundSep
[nDateSepCount
++] = szSourceStr
[nDateCompCount
];
75 pszFoundSep
[nDateSepCount
] = _T('\0');
85 /* Replace given template in source string with string to replace and return received string */
88 /* Setted up short date separator to registry */
90 SetShortDateSep(HWND hwndDlg
, LCID lcid
)
92 TCHAR szShortDateSep
[MAX_SAMPLES_STR_SIZE
];
96 /* Get setted separator */
97 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
99 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
100 (LPARAM
)szShortDateSep
);
102 /* Get setted separator string size */
103 nSepStrSize
= _tcslen(szShortDateSep
);
105 /* Check date components */
106 for (nSepCount
= 0; nSepCount
< nSepStrSize
; nSepCount
++)
108 if (_istalnum(szShortDateSep
[nSepCount
]) || (szShortDateSep
[nSepCount
] == _T('\'')))
110 PrintErrorMsgBox(IDS_ERROR_SYMBOL_SEPARATE
);
115 /* Save date separator */
116 SetLocaleInfo(lcid
, LOCALE_SDATE
, szShortDateSep
);
121 /* Setted up short date format to registry */
123 SetShortDateFormat(HWND hwndDlg
, LCID lcid
)
125 TCHAR szShortDateFmt
[MAX_SAMPLES_STR_SIZE
];
126 TCHAR szShortDateSep
[MAX_SAMPLES_STR_SIZE
];
127 TCHAR szFoundDateSep
[MAX_SAMPLES_STR_SIZE
];
130 BOOL OpenApostFlg
= FALSE
;
134 /* Get setted format */
135 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
137 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
138 (LPARAM
)szShortDateFmt
);
140 /* Get setted separator */
141 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
143 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
144 (LPARAM
)szShortDateSep
);
146 /* Get setted format-string size */
147 nFmtStrSize
= _tcslen(szShortDateFmt
);
149 /* Check date components */
150 for (nDateCompCount
= 0; nDateCompCount
< nFmtStrSize
; nDateCompCount
++)
152 if (szShortDateFmt
[nDateCompCount
] == _T('\''))
154 OpenApostFlg
= !OpenApostFlg
;
157 if (_istalnum(szShortDateFmt
[nDateCompCount
]) &&
158 !isDateCompAl(szShortDateFmt
[nDateCompCount
]) &&
161 PrintErrorMsgBox(IDS_ERROR_SYMBOL_FORMAT_SHORT
);
169 PrintErrorMsgBox(IDS_ERROR_SYMBOL_FORMAT_SHORT
);
173 pszFoundSep
= FindDateSep(szShortDateFmt
);
175 /* Substring replacement of separator */
176 _tcscpy(szFoundDateSep
, pszFoundSep
);
177 pszResultStr
= ReplaceSubStr(szShortDateFmt
, szShortDateSep
, szFoundDateSep
);
178 _tcscpy(szShortDateFmt
, pszResultStr
);
184 /* Save short date format */
185 SetLocaleInfo(lcid
, LOCALE_SSHORTDATE
, szShortDateFmt
);
190 /* Setted up long date format to registry */
192 SetLongDateFormat(HWND hwndDlg
, LCID lcid
)
194 TCHAR szLongDateFmt
[MAX_SAMPLES_STR_SIZE
];
195 BOOL OpenApostFlg
= FALSE
;
199 /* Get setted format */
200 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
202 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
203 (LPARAM
)szLongDateFmt
);
205 /* Get setted format string size */
206 nFmtStrSize
= _tcslen(szLongDateFmt
);
208 /* Check date components */
209 for (nDateCompCount
= 0; nDateCompCount
< nFmtStrSize
; nDateCompCount
++)
211 if (szLongDateFmt
[nDateCompCount
] == _T('\''))
213 OpenApostFlg
= !OpenApostFlg
;
216 if (_istalnum(szLongDateFmt
[nDateCompCount
]) &&
217 !isDateCompAl(szLongDateFmt
[nDateCompCount
]) &&
220 PrintErrorMsgBox(IDS_ERROR_SYMBOL_FORMAT_LONG
);
228 PrintErrorMsgBox(IDS_ERROR_SYMBOL_FORMAT_LONG
);
232 /* Save short date format */
233 SetLocaleInfo(lcid
, LOCALE_SLONGDATE
, szLongDateFmt
);
238 /* Init short date separator control box */
240 InitShortDateSepSamples(HWND hwndDlg
, LCID lcid
)
242 LPTSTR ShortDateSepSamples
[MAX_SHRT_DATE_SEPARATORS
] =
248 TCHAR szShortDateSep
[MAX_SAMPLES_STR_SIZE
];
252 /* Get current short date separator */
256 MAX_SAMPLES_STR_SIZE
);
258 /* Clear all box content */
259 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
264 /* Create standard list of separators */
265 for (nCBIndex
= 0; nCBIndex
< MAX_SHRT_DATE_SEPARATORS
; nCBIndex
++)
267 SendMessageW(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
270 (LPARAM
)ShortDateSepSamples
[nCBIndex
]);
273 /* Set current item to value from registry */
274 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
277 (LPARAM
)szShortDateSep
);
279 /* If it is not successful, add new value to list and select them */
280 if (nRetCode
== CB_ERR
)
282 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
285 (LPARAM
)szShortDateSep
);
286 SendMessageW(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
289 (LPARAM
)szShortDateSep
);
294 ShortDateFormatEnumProc(LPTSTR lpTimeFormatString
)
296 SendMessage(hwndEnum
,
299 (LPARAM
)lpTimeFormatString
);
304 /* Init short date control box */
306 InitShortDateCB(HWND hwndDlg
, LCID lcid
)
308 TCHAR szShortDateFmt
[MAX_SAMPLES_STR_SIZE
];
311 /* Limit text lengths */
312 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
316 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
321 /* Get current short date format */
325 MAX_SAMPLES_STR_SIZE
);
327 /* Clear all box content */
328 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
333 /* Enumerate short date formats */
334 hwndEnum
= GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
);
335 EnumDateFormats(ShortDateFormatEnumProc
, lcid
, DATE_SHORTDATE
);
337 /* Set current item to value from registry */
338 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
341 (LPARAM
)szShortDateFmt
);
343 /* If it is not successful, add new value to list and select them */
344 if (nRetCode
== CB_ERR
)
346 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
349 (LPARAM
)szShortDateFmt
);
350 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
353 (LPARAM
)szShortDateFmt
);
357 /* Init long date control box */
359 InitLongDateCB(HWND hwndDlg
, LCID lcid
)
361 TCHAR szLongDateFmt
[MAX_SAMPLES_STR_SIZE
];
364 /* Limit text length */
365 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
370 /* Get current long date format */
374 MAX_SAMPLES_STR_SIZE
);
376 /* Clear all box content */
377 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
382 /* Enumerate short long formats */
383 hwndEnum
= GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
);
384 EnumDateFormats(ShortDateFormatEnumProc
, lcid
, DATE_LONGDATE
);
386 /* Set current item to value from registry */
387 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
390 (LPARAM
)szLongDateFmt
);
392 /* If it is not successful, add new value to list and select them */
393 if (nRetCode
== CB_ERR
)
395 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
398 (LPARAM
)szLongDateFmt
);
399 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
402 (LPARAM
)szLongDateFmt
);
406 /* Set up max date value to registry */
408 SetMaxDate(HWND hwndDlg
, LCID lcid
)
410 TCHAR szMaxDateVal
[YEAR_STR_MAX_SIZE
];
414 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
417 nSpinVal
=LOWORD(SendMessage(hWndYearSpin
,
422 /* convert to wide char */
423 _itot(nSpinVal
, szMaxDateVal
, DECIMAL_RADIX
);
425 /* Save max date value */
426 SetCalendarInfo(lcid
,
428 48 , /* CAL_ITWODIGITYEARMAX */
429 (LPCTSTR
)szMaxDateVal
);
432 /* Get max date value from registry set */
434 GetMaxDate(LCID lcid
)
438 GetCalendarInfo(lcid
,
440 CAL_ITWODIGITYEARMAX
| CAL_RETURN_NUMBER
,
442 0, /* ret type - number */
443 (LPDWORD
)&nMaxDateVal
);
448 /* Set's MIN data edit control value to MAX-99 */
450 SetMinData(HWND hwndDlg
)
452 TCHAR OutBuffer
[YEAR_STR_MAX_SIZE
];
456 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
459 nSpinVal
= LOWORD(SendMessage(hWndYearSpin
,
464 /* Set min year value */
465 wsprintf(OutBuffer
, _T("%d"), (DWORD
)nSpinVal
- YEAR_DIFF
);
466 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
472 /* Init spin control */
474 InitMinMaxDateSpin(HWND hwndDlg
, LCID lcid
)
476 TCHAR OutBuffer
[YEAR_STR_MAX_SIZE
];
479 /* Limit text lengths */
480 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
484 SendMessage(GetDlgItem(hwndDlg
, IDC_SECONDYEAR_EDIT
),
489 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
491 /* Init max date value */
492 wsprintf(OutBuffer
, _T("%04d"), (DWORD
)GetMaxDate(lcid
));
493 SendMessage(GetDlgItem(hwndDlg
, IDC_SECONDYEAR_EDIT
),
498 /* Init min date value */
499 wsprintf(OutBuffer
, _T("%04d"), (DWORD
)GetMaxDate(lcid
) - YEAR_DIFF
);
500 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
505 /* Init updown control */
507 SendMessage(hWndYearSpin
,
510 MAKELONG(MAX_YEAR
,YEAR_DIFF
));
512 /* Set current value */
513 SendMessage(hWndYearSpin
,
516 MAKELONG(GetMaxDate(lcid
),0));
519 /* Update all date locale samples */
521 UpdateDateLocaleSamples(HWND hwndDlg
,
524 TCHAR OutBuffer
[MAX_SAMPLES_STR_SIZE
];
526 /* Get short date format sample */
527 GetDateFormat(lcidLocale
, DATE_SHORTDATE
, NULL
, NULL
, OutBuffer
,
528 MAX_SAMPLES_STR_SIZE
);
529 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESAMPLE_EDIT
), WM_SETTEXT
,
530 0, (LPARAM
)OutBuffer
);
532 /* Get long date sample */
533 GetDateFormat(lcidLocale
, DATE_LONGDATE
, NULL
, NULL
, OutBuffer
,
534 MAX_SAMPLES_STR_SIZE
);
535 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATESAMPLE_EDIT
),
536 WM_SETTEXT
, 0, (LPARAM
)OutBuffer
);
539 /* Property page dialog callback */
541 DatePageProc(HWND hwndDlg
,
546 PGLOBALDATA pGlobalData
;
548 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
553 pGlobalData
= (PGLOBALDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
554 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
556 InitMinMaxDateSpin(hwndDlg
, pGlobalData
->lcid
);
557 UpdateDateLocaleSamples(hwndDlg
, pGlobalData
->lcid
);
558 InitShortDateCB(hwndDlg
, pGlobalData
->lcid
);
559 InitLongDateCB(hwndDlg
, pGlobalData
->lcid
);
560 InitShortDateSepSamples(hwndDlg
, pGlobalData
->lcid
);
561 /* TODO: Add other calendar types */
566 switch (LOWORD(wParam
))
568 case IDC_SECONDYEAR_EDIT
:
570 if(HIWORD(wParam
)==EN_CHANGE
)
575 case IDC_SCR_MAX_YEAR
:
577 /* Set "Apply" button enabled */
579 //PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
582 case IDC_CALTYPE_COMBO
:
583 case IDC_HIJCHRON_COMBO
:
584 case IDC_SHRTDATEFMT_COMBO
:
585 case IDC_SHRTDATESEP_COMBO
:
586 case IDC_LONGDATEFMT_COMBO
:
588 if (HIWORD(wParam
) == CBN_SELCHANGE
|| HIWORD(wParam
) == CBN_EDITCHANGE
)
590 /* Set "Apply" button enabled */
591 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
600 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
601 /* If push apply button */
602 if (lpnm
->code
== (UINT
)PSN_APPLY
)
604 SetMaxDate(hwndDlg
, pGlobalData
->lcid
);
605 if(!SetShortDateSep(hwndDlg
, pGlobalData
->lcid
)) break;
606 if(!SetShortDateFormat(hwndDlg
, pGlobalData
->lcid
)) break;
607 if(!SetLongDateFormat(hwndDlg
, pGlobalData
->lcid
)) break;
608 InitShortDateCB(hwndDlg
, pGlobalData
->lcid
);
611 UpdateDateLocaleSamples(hwndDlg
, pGlobalData
->lcid
);