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.
21 * PROJECT: ReactOS International Control Panel
22 * FILE: dll/cpl/intl/date.c
23 * PURPOSE: Date property page
24 * PROGRAMMER: Eric Kohl
29 /* GLOBALS ******************************************************************/
31 #define YEAR_STR_MAX_SIZE 5
32 #define MAX_SHRT_DATE_SEPARATORS 3
33 #define STD_DATE_SEP _T(".")
34 #define YEAR_DIFF (99)
35 #define MAX_YEAR (9999)
37 static HWND hwndEnum
= NULL
;
39 /* FUNCTIONS ****************************************************************/
41 /* If char is 'y' or 'M' or 'd' return TRUE, else FALSE */
43 isDateCompAl(TCHAR alpha
)
45 if ((alpha
== _T('y')) || (alpha
== _T('M')) || (alpha
== _T('d')) || (alpha
== _T(' ')))
51 /* Find first date separator in string */
53 FindDateSep(const TCHAR
*szSourceStr
)
56 UINT nDateCompCount
=0;
59 pszFoundSep
= (LPTSTR
)malloc(MAX_SAMPLES_STR_SIZE
* sizeof(TCHAR
));
61 _tcscpy(pszFoundSep
,STD_DATE_SEP
);
63 while (nDateCompCount
< _tcslen(szSourceStr
))
65 if (!isDateCompAl(szSourceStr
[nDateCompCount
]) && (szSourceStr
[nDateCompCount
] != _T('\'')))
67 while (!isDateCompAl(szSourceStr
[nDateCompCount
]) && (szSourceStr
[nDateCompCount
] != _T('\'')))
69 pszFoundSep
[nDateSepCount
++] = szSourceStr
[nDateCompCount
];
73 pszFoundSep
[nDateSepCount
] = _T('\0');
83 /* Replace given template in source string with string to replace and return recieved string */
86 /* Setted up short date separator to registry */
88 SetShortDateSep(HWND hwndDlg
, LCID lcid
)
90 TCHAR szShortDateSep
[MAX_SAMPLES_STR_SIZE
];
94 /* Get setted separator */
95 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
97 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
98 (LPARAM
)szShortDateSep
);
100 /* Get setted separator string size */
101 nSepStrSize
= _tcslen(szShortDateSep
);
103 /* Check date components */
104 for (nSepCount
= 0; nSepCount
< nSepStrSize
; nSepCount
++)
106 if (_istalnum(szShortDateSep
[nSepCount
]) || (szShortDateSep
[nSepCount
] == _T('\'')))
109 _T("Entered short date separator contain incorrect symbol"),
110 _T("Error"), MB_OK
| MB_ICONERROR
);
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 szFindedDateSep
[MAX_SAMPLES_STR_SIZE
];
129 BOOL OpenApostFlg
= FALSE
;
133 /* Get setted format */
134 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
136 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
137 (LPARAM
)szShortDateFmt
);
139 /* Get setted separator */
140 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
142 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
143 (LPARAM
)szShortDateSep
);
145 /* Get setted format-string size */
146 nFmtStrSize
= _tcslen(szShortDateFmt
);
148 /* Check date components */
149 for (nDateCompCount
= 0; nDateCompCount
< nFmtStrSize
; nDateCompCount
++)
151 if (szShortDateFmt
[nDateCompCount
] == _T('\''))
153 OpenApostFlg
= !OpenApostFlg
;
156 if (_istalnum(szShortDateFmt
[nDateCompCount
]) &&
157 !isDateCompAl(szShortDateFmt
[nDateCompCount
]) &&
161 _T("Entered short date format contain incorrect symbol"),
162 _T("Error"), MB_OK
| MB_ICONERROR
);
171 _T("Entered short date format contain incorrect symbol"),
172 _T("Error"), MB_OK
| MB_ICONERROR
);
176 /* Substring replacement of separator */
177 _tcscpy(szFindedDateSep
, FindDateSep(szShortDateFmt
));
178 pszResultStr
= ReplaceSubStr(szShortDateFmt
, szShortDateSep
, szFindedDateSep
);
179 _tcscpy(szShortDateFmt
, pszResultStr
);
182 /* Save short date format */
183 SetLocaleInfo(lcid
, LOCALE_SSHORTDATE
, szShortDateFmt
);
188 /* Setted up long date format to registry */
190 SetLongDateFormat(HWND hwndDlg
, LCID lcid
)
192 TCHAR szLongDateFmt
[MAX_SAMPLES_STR_SIZE
];
193 BOOL OpenApostFlg
= FALSE
;
197 /* Get setted format */
198 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
200 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
201 (LPARAM
)szLongDateFmt
);
203 /* Get setted format string size */
204 nFmtStrSize
= _tcslen(szLongDateFmt
);
206 /* Check date components */
207 for (nDateCompCount
= 0; nDateCompCount
< nFmtStrSize
; nDateCompCount
++)
209 if (szLongDateFmt
[nDateCompCount
] == _T('\''))
211 OpenApostFlg
= !OpenApostFlg
;
214 if (_istalnum(szLongDateFmt
[nDateCompCount
]) &&
215 !isDateCompAl(szLongDateFmt
[nDateCompCount
]) &&
219 _T("Entered long date format contain incorrect symbol"),
220 _T("Error"), MB_OK
| MB_ICONERROR
);
229 _T("Entered long date format contain incorrect symbol"),
230 _T("Error"), MB_OK
| MB_ICONERROR
);
234 /* Save short date format */
235 SetLocaleInfo(lcid
, LOCALE_SLONGDATE
, szLongDateFmt
);
240 /* Init short date separator control box */
242 InitShortDateSepSamples(HWND hwndDlg
, LCID lcid
)
244 LPTSTR ShortDateSepSamples
[MAX_SHRT_DATE_SEPARATORS
] =
250 TCHAR szShortDateSep
[MAX_SAMPLES_STR_SIZE
];
254 /* Get current short date separator */
258 MAX_SAMPLES_STR_SIZE
);
260 /* Clear all box content */
261 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
266 /* Create standard list of separators */
267 for (nCBIndex
= 0; nCBIndex
< MAX_SHRT_DATE_SEPARATORS
; nCBIndex
++)
269 SendMessageW(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
272 (LPARAM
)ShortDateSepSamples
[nCBIndex
]);
275 /* Set current item to value from registry */
276 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
279 (LPARAM
)szShortDateSep
);
281 /* If it is not successful, add new value to list and select them */
282 if (nRetCode
== CB_ERR
)
284 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
287 (LPARAM
)szShortDateSep
);
288 SendMessageW(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
291 (LPARAM
)szShortDateSep
);
296 ShortDateFormatEnumProc(LPTSTR lpTimeFormatString
)
298 SendMessage(hwndEnum
,
301 (LPARAM
)lpTimeFormatString
);
306 /* Init short date control box */
308 InitShortDateCB(HWND hwndDlg
, LCID lcid
)
310 TCHAR szShortDateFmt
[MAX_SAMPLES_STR_SIZE
];
313 /* Limit text lengths */
314 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
318 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESEP_COMBO
),
323 /* Get current short date format */
327 MAX_SAMPLES_STR_SIZE
);
329 /* Clear all box content */
330 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
335 /* Enumerate short date formats */
336 hwndEnum
= GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
);
337 EnumDateFormats(ShortDateFormatEnumProc
, lcid
, DATE_SHORTDATE
);
339 /* Set current item to value from registry */
340 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
343 (LPARAM
)szShortDateFmt
);
345 /* If it is not successful, add new value to list and select them */
346 if (nRetCode
== CB_ERR
)
348 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
351 (LPARAM
)szShortDateFmt
);
352 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATEFMT_COMBO
),
355 (LPARAM
)szShortDateFmt
);
359 /* Init long date control box */
361 InitLongDateCB(HWND hwndDlg
, LCID lcid
)
363 TCHAR szLongDateFmt
[MAX_SAMPLES_STR_SIZE
];
366 /* Limit text length */
367 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
372 /* Get current long date format */
376 MAX_SAMPLES_STR_SIZE
);
378 /* Clear all box content */
379 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
384 /* Enumerate short long formats */
385 hwndEnum
= GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
);
386 EnumDateFormats(ShortDateFormatEnumProc
, lcid
, DATE_LONGDATE
);
388 /* Set current item to value from registry */
389 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
392 (LPARAM
)szLongDateFmt
);
394 /* If it is not successful, add new value to list and select them */
395 if (nRetCode
== CB_ERR
)
397 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
400 (LPARAM
)szLongDateFmt
);
401 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATEFMT_COMBO
),
404 (LPARAM
)szLongDateFmt
);
408 /* Set up max date value to registry */
410 SetMaxDate(HWND hwndDlg
, LCID lcid
)
412 TCHAR szMaxDateVal
[YEAR_STR_MAX_SIZE
];
416 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
419 nSpinVal
=LOWORD(SendMessage(hWndYearSpin
,
424 /* convert to wide char */
425 _itot(nSpinVal
, szMaxDateVal
, DECIMAL_RADIX
);
427 /* Save max date value */
428 SetCalendarInfo(lcid
,
430 48 , /* CAL_ITWODIGITYEARMAX */
431 (LPCTSTR
)szMaxDateVal
);
434 /* Get max date value from registry set */
436 GetMaxDate(LCID lcid
)
440 GetCalendarInfo(lcid
,
442 CAL_ITWODIGITYEARMAX
| CAL_RETURN_NUMBER
,
444 0, /* ret type - number */
445 (LPDWORD
)&nMaxDateVal
);
450 /* Set's MIN data edit control value to MAX-99 */
452 SetMinData(HWND hwndDlg
)
454 TCHAR OutBuffer
[YEAR_STR_MAX_SIZE
];
458 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
461 nSpinVal
= LOWORD(SendMessage(hWndYearSpin
,
466 /* Set min year value */
467 wsprintf(OutBuffer
, _T("%d"), (DWORD
)nSpinVal
- YEAR_DIFF
);
468 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
474 /* Init spin control */
476 InitMinMaxDateSpin(HWND hwndDlg
, LCID lcid
)
478 TCHAR OutBuffer
[YEAR_STR_MAX_SIZE
];
481 /* Limit text lengths */
482 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
486 SendMessage(GetDlgItem(hwndDlg
, IDC_SECONDYEAR_EDIT
),
491 hWndYearSpin
= GetDlgItem(hwndDlg
, IDC_SCR_MAX_YEAR
);
493 /* Init max date value */
494 wsprintf(OutBuffer
, _T("%04d"), (DWORD
)GetMaxDate(lcid
));
495 SendMessage(GetDlgItem(hwndDlg
, IDC_SECONDYEAR_EDIT
),
500 /* Init min date value */
501 wsprintf(OutBuffer
, _T("%04d"), (DWORD
)GetMaxDate(lcid
) - YEAR_DIFF
);
502 SendMessage(GetDlgItem(hwndDlg
, IDC_FIRSTYEAR_EDIT
),
507 /* Init updown control */
509 SendMessage(hWndYearSpin
,
512 MAKELONG(MAX_YEAR
,YEAR_DIFF
));
514 /* Set current value */
515 SendMessage(hWndYearSpin
,
518 MAKELONG(GetMaxDate(lcid
),0));
521 /* Update all date locale samples */
523 UpdateDateLocaleSamples(HWND hwndDlg
,
526 TCHAR OutBuffer
[MAX_SAMPLES_STR_SIZE
];
528 /* Get short date format sample */
529 GetDateFormat(lcidLocale
, DATE_SHORTDATE
, NULL
, NULL
, OutBuffer
,
530 MAX_SAMPLES_STR_SIZE
);
531 SendMessage(GetDlgItem(hwndDlg
, IDC_SHRTDATESAMPLE_EDIT
), WM_SETTEXT
,
532 0, (LPARAM
)OutBuffer
);
534 /* Get long date sample */
535 GetDateFormat(lcidLocale
, DATE_LONGDATE
, NULL
, NULL
, OutBuffer
,
536 MAX_SAMPLES_STR_SIZE
);
537 SendMessage(GetDlgItem(hwndDlg
, IDC_LONGDATESAMPLE_EDIT
),
538 WM_SETTEXT
, 0, (LPARAM
)OutBuffer
);
541 /* Property page dialog callback */
543 DatePageProc(HWND hwndDlg
,
548 PGLOBALDATA pGlobalData
;
550 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
555 pGlobalData
= (PGLOBALDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
556 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
558 InitMinMaxDateSpin(hwndDlg
, pGlobalData
->lcid
);
559 UpdateDateLocaleSamples(hwndDlg
, pGlobalData
->lcid
);
560 InitShortDateCB(hwndDlg
, pGlobalData
->lcid
);
561 InitLongDateCB(hwndDlg
, pGlobalData
->lcid
);
562 InitShortDateSepSamples(hwndDlg
, pGlobalData
->lcid
);
563 /* TODO: Add other calendar types */
568 switch (LOWORD(wParam
))
570 case IDC_SECONDYEAR_EDIT
:
572 if(HIWORD(wParam
)==EN_CHANGE
)
577 case IDC_SCR_MAX_YEAR
:
579 /* Set "Apply" button enabled */
581 //PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
584 case IDC_CALTYPE_COMBO
:
585 case IDC_HIJCHRON_COMBO
:
586 case IDC_SHRTDATEFMT_COMBO
:
587 case IDC_SHRTDATESEP_COMBO
:
588 case IDC_LONGDATEFMT_COMBO
:
590 if (HIWORD(wParam
) == CBN_SELCHANGE
|| HIWORD(wParam
) == CBN_EDITCHANGE
)
592 /* Set "Apply" button enabled */
593 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
602 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
603 /* If push apply button */
604 if (lpnm
->code
== (UINT
)PSN_APPLY
)
606 SetMaxDate(hwndDlg
, pGlobalData
->lcid
);
607 if(!SetShortDateSep(hwndDlg
, pGlobalData
->lcid
)) break;
608 if(!SetShortDateFormat(hwndDlg
, pGlobalData
->lcid
)) break;
609 if(!SetLongDateFormat(hwndDlg
, pGlobalData
->lcid
)) break;
610 InitShortDateCB(hwndDlg
, pGlobalData
->lcid
);
613 UpdateDateLocaleSamples(hwndDlg
, pGlobalData
->lcid
);