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
));
60 _tcscpy(pszFoundSep
,STD_DATE_SEP
);
62 while (nDateCompCount
< _tcslen(szSourceStr
))
64 if (!isDateCompAl(szSourceStr
[nDateCompCount
]) && (szSourceStr
[nDateCompCount
] != _T('\'')))
66 while (!isDateCompAl(szSourceStr
[nDateCompCount
]) && (szSourceStr
[nDateCompCount
] != _T('\'')))
68 pszFoundSep
[nDateSepCount
++] = szSourceStr
[nDateCompCount
];
72 pszFoundSep
[nDateSepCount
] = _T('\0');
82 /* Replace given template in source string with string to replace and return recieved string */
85 /* Setted up short date separator to registry */
87 SetShortDateSep(HWND hwndDlg
, LCID lcid
)
89 TCHAR szShortDateSep
[MAX_SAMPLES_STR_SIZE
];
93 /* Get setted separator */
94 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
96 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
97 (LPARAM
)szShortDateSep
);
99 /* Get setted separator string size */
100 nSepStrSize
= _tcslen(szShortDateSep
);
102 /* Check date components */
103 for (nSepCount
= 0; nSepCount
< nSepStrSize
; nSepCount
++)
105 if (_istalnum(szShortDateSep
[nSepCount
]) || (szShortDateSep
[nSepCount
] == _T('\'')))
108 _T("Entered short date separator contain incorrect symbol"),
109 _T("Error"), MB_OK
| MB_ICONERROR
);
114 /* Save date separator */
115 SetLocaleInfo(lcid
, LOCALE_SDATE
, szShortDateSep
);
120 /* Setted up short date format to registry */
122 SetShortDateFormat(HWND hwndDlg
, LCID lcid
)
124 TCHAR szShortDateFmt
[MAX_SAMPLES_STR_SIZE
];
125 TCHAR szShortDateSep
[MAX_SAMPLES_STR_SIZE
];
126 TCHAR szFindedDateSep
[MAX_SAMPLES_STR_SIZE
];
128 BOOL OpenApostFlg
= FALSE
;
132 /* Get setted format */
133 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
135 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
136 (LPARAM
)szShortDateFmt
);
138 /* Get setted separator */
139 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
141 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
142 (LPARAM
)szShortDateSep
);
144 /* Get setted format-string size */
145 nFmtStrSize
= _tcslen(szShortDateFmt
);
147 /* Check date components */
148 for (nDateCompCount
= 0; nDateCompCount
< nFmtStrSize
; nDateCompCount
++)
150 if (szShortDateFmt
[nDateCompCount
] == _T('\''))
152 OpenApostFlg
= !OpenApostFlg
;
155 if (_istalnum(szShortDateFmt
[nDateCompCount
]) &&
156 !isDateCompAl(szShortDateFmt
[nDateCompCount
]) &&
160 _T("Entered short date format contain incorrect symbol"),
161 _T("Error"), MB_OK
| MB_ICONERROR
);
170 _T("Entered short date format contain incorrect symbol"),
171 _T("Error"), MB_OK
| MB_ICONERROR
);
175 /* Substring replacement of separator */
176 _tcscpy(szFindedDateSep
, FindDateSep(szShortDateFmt
));
177 pszResultStr
= ReplaceSubStr(szShortDateFmt
, szShortDateSep
, szFindedDateSep
);
178 _tcscpy(szShortDateFmt
, pszResultStr
);
181 /* Save short date format */
182 SetLocaleInfo(lcid
, LOCALE_SSHORTDATE
, szShortDateFmt
);
187 /* Setted up long date format to registry */
189 SetLongDateFormat(HWND hwndDlg
, LCID lcid
)
191 TCHAR szLongDateFmt
[MAX_SAMPLES_STR_SIZE
];
192 BOOL OpenApostFlg
= FALSE
;
196 /* Get setted format */
197 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
199 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
200 (LPARAM
)szLongDateFmt
);
202 /* Get setted format string size */
203 nFmtStrSize
= _tcslen(szLongDateFmt
);
205 /* Check date components */
206 for (nDateCompCount
= 0; nDateCompCount
< nFmtStrSize
; nDateCompCount
++)
208 if (szLongDateFmt
[nDateCompCount
] == _T('\''))
210 OpenApostFlg
= !OpenApostFlg
;
213 if (_istalnum(szLongDateFmt
[nDateCompCount
]) &&
214 !isDateCompAl(szLongDateFmt
[nDateCompCount
]) &&
218 _T("Entered long date format contain incorrect symbol"),
219 _T("Error"), MB_OK
| MB_ICONERROR
);
228 _T("Entered long date format contain incorrect symbol"),
229 _T("Error"), MB_OK
| MB_ICONERROR
);
233 /* Save short date format */
234 SetLocaleInfo(lcid
, LOCALE_SLONGDATE
, szLongDateFmt
);
239 /* Init short date separator control box */
241 InitShortDateSepSamples(HWND hwndDlg
, LCID lcid
)
243 LPTSTR ShortDateSepSamples
[MAX_SHRT_DATE_SEPARATORS
] =
249 TCHAR szShortDateSep
[MAX_SAMPLES_STR_SIZE
];
253 /* Get current short date separator */
257 MAX_SAMPLES_STR_SIZE
);
259 /* Clear all box content */
260 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
265 /* Create standard list of separators */
266 for (nCBIndex
= 0; nCBIndex
< MAX_SHRT_DATE_SEPARATORS
; nCBIndex
++)
268 SendMessageW(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
271 (LPARAM
)ShortDateSepSamples
[nCBIndex
]);
274 /* Set current item to value from registry */
275 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
278 (LPARAM
)szShortDateSep
);
280 /* If it is not successful, add new value to list and select them */
281 if (nRetCode
== CB_ERR
)
283 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
286 (LPARAM
)szShortDateSep
);
287 SendMessageW(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
290 (LPARAM
)szShortDateSep
);
295 ShortDateFormatEnumProc(LPTSTR lpTimeFormatString
)
297 SendMessage(hwndEnum
,
300 (LPARAM
)lpTimeFormatString
);
305 /* Init short date control box */
307 InitShortDateCB(HWND hwndDlg
, LCID lcid
)
309 TCHAR szShortDateFmt
[MAX_SAMPLES_STR_SIZE
];
312 /* Limit text lengths */
313 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
317 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
322 /* Get current short date format */
326 MAX_SAMPLES_STR_SIZE
);
328 /* Clear all box content */
329 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
334 /* Enumerate short date formats */
335 hwndEnum
= GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
);
336 EnumDateFormats(ShortDateFormatEnumProc
, lcid
, DATE_SHORTDATE
);
338 /* Set current item to value from registry */
339 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
342 (LPARAM
)szShortDateFmt
);
344 /* If it is not successful, add new value to list and select them */
345 if (nRetCode
== CB_ERR
)
347 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
350 (LPARAM
)szShortDateFmt
);
351 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
354 (LPARAM
)szShortDateFmt
);
358 /* Init long date control box */
360 InitLongDateCB(HWND hwndDlg
, LCID lcid
)
362 TCHAR szLongDateFmt
[MAX_SAMPLES_STR_SIZE
];
365 /* Limit text length */
366 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
371 /* Get current long date format */
375 MAX_SAMPLES_STR_SIZE
);
377 /* Clear all box content */
378 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
383 /* Enumerate short long formats */
384 hwndEnum
= GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
);
385 EnumDateFormats(ShortDateFormatEnumProc
, lcid
, DATE_LONGDATE
);
387 /* Set current item to value from registry */
388 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
391 (LPARAM
)szLongDateFmt
);
393 /* If it is not successful, add new value to list and select them */
394 if (nRetCode
== CB_ERR
)
396 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
399 (LPARAM
)szLongDateFmt
);
400 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
403 (LPARAM
)szLongDateFmt
);
407 /* Set up max date value to registry */
409 SetMaxDate(HWND hwndDlg
, LCID lcid
)
411 TCHAR szMaxDateVal
[YEAR_STR_MAX_SIZE
];
415 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
418 nSpinVal
=LOWORD(SendMessage(hWndYearSpin
,
423 /* convert to wide char */
424 _itot(nSpinVal
, szMaxDateVal
, DECIMAL_RADIX
);
426 /* Save max date value */
427 SetCalendarInfo(lcid
,
429 48 , /* CAL_ITWODIGITYEARMAX */
430 (LPCTSTR
)szMaxDateVal
);
433 /* Get max date value from registry set */
435 GetMaxDate(LCID lcid
)
439 GetCalendarInfo(lcid
,
441 CAL_ITWODIGITYEARMAX
| CAL_RETURN_NUMBER
,
443 0, /* ret type - number */
444 (LPDWORD
)&nMaxDateVal
);
449 /* Set's MIN data edit control value to MAX-99 */
451 SetMinData(HWND hwndDlg
)
453 TCHAR OutBuffer
[YEAR_STR_MAX_SIZE
];
457 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
460 nSpinVal
= LOWORD(SendMessage(hWndYearSpin
,
465 /* Set min year value */
466 wsprintf(OutBuffer
, _T("%d"), (DWORD
)nSpinVal
- YEAR_DIFF
);
467 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
473 /* Init spin control */
475 InitMinMaxDateSpin(HWND hwndDlg
, LCID lcid
)
477 TCHAR OutBuffer
[YEAR_STR_MAX_SIZE
];
480 /* Limit text lengths */
481 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
485 SendMessage(GetDlgItem(hwndDlg
, IDC_SECONDYEAR_EDIT
),
490 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
492 /* Init max date value */
493 wsprintf(OutBuffer
, _T("%04d"), (DWORD
)GetMaxDate(lcid
));
494 SendMessage(GetDlgItem(hwndDlg
, IDC_SECONDYEAR_EDIT
),
499 /* Init min date value */
500 wsprintf(OutBuffer
, _T("%04d"), (DWORD
)GetMaxDate(lcid
) - YEAR_DIFF
);
501 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
506 /* Init updown control */
508 SendMessage(hWndYearSpin
,
511 MAKELONG(MAX_YEAR
,YEAR_DIFF
));
513 /* Set current value */
514 SendMessage(hWndYearSpin
,
517 MAKELONG(GetMaxDate(lcid
),0));
520 /* Update all date locale samples */
522 UpdateDateLocaleSamples(HWND hwndDlg
,
525 TCHAR OutBuffer
[MAX_SAMPLES_STR_SIZE
];
527 /* Get short date format sample */
528 GetDateFormat(lcidLocale
, DATE_SHORTDATE
, NULL
, NULL
, OutBuffer
,
529 MAX_SAMPLES_STR_SIZE
);
530 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESAMPLE_EDIT
), WM_SETTEXT
,
531 0, (LPARAM
)OutBuffer
);
533 /* Get long date sample */
534 GetDateFormat(lcidLocale
, DATE_LONGDATE
, NULL
, NULL
, OutBuffer
,
535 MAX_SAMPLES_STR_SIZE
);
536 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATESAMPLE_EDIT
),
537 WM_SETTEXT
, 0, (LPARAM
)OutBuffer
);
540 /* Property page dialog callback */
542 DatePageProc(HWND hwndDlg
,
547 PGLOBALDATA pGlobalData
;
549 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
554 pGlobalData
= (PGLOBALDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
555 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
557 InitMinMaxDateSpin(hwndDlg
, pGlobalData
->lcid
);
558 UpdateDateLocaleSamples(hwndDlg
, pGlobalData
->lcid
);
559 InitShortDateCB(hwndDlg
, pGlobalData
->lcid
);
560 InitLongDateCB(hwndDlg
, pGlobalData
->lcid
);
561 InitShortDateSepSamples(hwndDlg
, pGlobalData
->lcid
);
562 /* TODO: Add other calendar types */
567 switch (LOWORD(wParam
))
569 case IDC_SECONDYEAR_EDIT
:
571 if(HIWORD(wParam
)==EN_CHANGE
)
576 case IDC_SCR_MAX_YEAR
:
578 /* Set "Apply" button enabled */
580 //PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
583 case IDC_CALTYPE_COMBO
:
584 case IDC_HIJCHRON_COMBO
:
585 case IDC_SHRTDATEFMT_COMBO
:
586 case IDC_SHRTDATESEP_COMBO
:
587 case IDC_LONGDATEFMT_COMBO
:
589 if (HIWORD(wParam
) == CBN_SELCHANGE
|| HIWORD(wParam
) == CBN_EDITCHANGE
)
591 /* Set "Apply" button enabled */
592 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
601 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
602 /* If push apply button */
603 if (lpnm
->code
== (UINT
)PSN_APPLY
)
605 SetMaxDate(hwndDlg
, pGlobalData
->lcid
);
606 if(!SetShortDateSep(hwndDlg
, pGlobalData
->lcid
)) break;
607 if(!SetShortDateFormat(hwndDlg
, pGlobalData
->lcid
)) break;
608 if(!SetLongDateFormat(hwndDlg
, pGlobalData
->lcid
)) break;
609 InitShortDateCB(hwndDlg
, pGlobalData
->lcid
);
612 UpdateDateLocaleSamples(hwndDlg
, pGlobalData
->lcid
);