xref: /reactos/dll/cpl/intl/date.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  *  ReactOS
3*c2c66affSColin Finck  *  Copyright (C) 2004 ReactOS Team
4*c2c66affSColin Finck  *
5*c2c66affSColin Finck  *  This program is free software; you can redistribute it and/or modify
6*c2c66affSColin Finck  *  it under the terms of the GNU General Public License as published by
7*c2c66affSColin Finck  *  the Free Software Foundation; either version 2 of the License, or
8*c2c66affSColin Finck  *  (at your option) any later version.
9*c2c66affSColin Finck  *
10*c2c66affSColin Finck  *  This program is distributed in the hope that it will be useful,
11*c2c66affSColin Finck  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12*c2c66affSColin Finck  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*c2c66affSColin Finck  *  GNU General Public License for more details.
14*c2c66affSColin Finck  *
15*c2c66affSColin Finck  *  You should have received a copy of the GNU General Public License along
16*c2c66affSColin Finck  *  with this program; if not, write to the Free Software Foundation, Inc.,
17*c2c66affSColin Finck  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18*c2c66affSColin Finck  */
19*c2c66affSColin Finck /*
20*c2c66affSColin Finck  * PROJECT:         ReactOS International Control Panel
21*c2c66affSColin Finck  * FILE:            dll/cpl/intl/date.c
22*c2c66affSColin Finck  * PURPOSE:         Date property page
23*c2c66affSColin Finck  * PROGRAMMERS:     Eric Kohl
24*c2c66affSColin Finck  *                  Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
25*c2c66affSColin Finck  */
26*c2c66affSColin Finck 
27*c2c66affSColin Finck #include "intl.h"
28*c2c66affSColin Finck 
29*c2c66affSColin Finck /* GLOBALS ******************************************************************/
30*c2c66affSColin Finck 
31*c2c66affSColin Finck #define YEAR_STR_MAX_SIZE        5
32*c2c66affSColin Finck #define MAX_SHRT_DATE_SEPARATORS 3
33*c2c66affSColin Finck #define STD_DATE_SEP             L"."
34*c2c66affSColin Finck #define YEAR_DIFF                (99)
35*c2c66affSColin Finck #define MAX_YEAR                 (9999)
36*c2c66affSColin Finck 
37*c2c66affSColin Finck static HWND hwndEnum = NULL;
38*c2c66affSColin Finck 
39*c2c66affSColin Finck /* FUNCTIONS ****************************************************************/
40*c2c66affSColin Finck 
41*c2c66affSColin Finck /* If char is 'y' or 'M' or 'd' return TRUE, else FALSE */
42*c2c66affSColin Finck BOOL
isDateCompAl(WCHAR alpha)43*c2c66affSColin Finck isDateCompAl(WCHAR alpha)
44*c2c66affSColin Finck {
45*c2c66affSColin Finck     if ((alpha == L'y') || (alpha == L'M') || (alpha == L'd') || (alpha == L' '))
46*c2c66affSColin Finck         return TRUE;
47*c2c66affSColin Finck     else
48*c2c66affSColin Finck         return FALSE;
49*c2c66affSColin Finck }
50*c2c66affSColin Finck 
51*c2c66affSColin Finck /* Find first date separator in string */
52*c2c66affSColin Finck LPTSTR
FindDateSep(const WCHAR * szSourceStr)53*c2c66affSColin Finck FindDateSep(const WCHAR *szSourceStr)
54*c2c66affSColin Finck {
55*c2c66affSColin Finck     PWSTR pszFoundSep;
56*c2c66affSColin Finck     UINT nDateCompCount=0;
57*c2c66affSColin Finck     UINT nDateSepCount=0;
58*c2c66affSColin Finck 
59*c2c66affSColin Finck     pszFoundSep = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, MAX_SAMPLES_STR_SIZE * sizeof(WCHAR));
60*c2c66affSColin Finck     if (pszFoundSep == NULL)
61*c2c66affSColin Finck         return NULL;
62*c2c66affSColin Finck 
63*c2c66affSColin Finck     wcscpy(pszFoundSep,STD_DATE_SEP);
64*c2c66affSColin Finck 
65*c2c66affSColin Finck     while (nDateCompCount < wcslen(szSourceStr))
66*c2c66affSColin Finck     {
67*c2c66affSColin Finck         if (!isDateCompAl(szSourceStr[nDateCompCount]) && (szSourceStr[nDateCompCount] != L'\''))
68*c2c66affSColin Finck         {
69*c2c66affSColin Finck             while (!isDateCompAl(szSourceStr[nDateCompCount]) && (szSourceStr[nDateCompCount] != L'\''))
70*c2c66affSColin Finck             {
71*c2c66affSColin Finck                 pszFoundSep[nDateSepCount++] = szSourceStr[nDateCompCount];
72*c2c66affSColin Finck                 nDateCompCount++;
73*c2c66affSColin Finck             }
74*c2c66affSColin Finck 
75*c2c66affSColin Finck             pszFoundSep[nDateSepCount] = L'\0';
76*c2c66affSColin Finck             return pszFoundSep;
77*c2c66affSColin Finck         }
78*c2c66affSColin Finck 
79*c2c66affSColin Finck         nDateCompCount++;
80*c2c66affSColin Finck     }
81*c2c66affSColin Finck 
82*c2c66affSColin Finck     return pszFoundSep;
83*c2c66affSColin Finck }
84*c2c66affSColin Finck 
85*c2c66affSColin Finck /* Replace given template in source string with string to replace and return received string */
86*c2c66affSColin Finck 
87*c2c66affSColin Finck 
88*c2c66affSColin Finck /* Setted up short date separator to registry */
89*c2c66affSColin Finck static BOOL
SetShortDateSep(HWND hwndDlg,PWSTR pszShortDateSep)90*c2c66affSColin Finck SetShortDateSep(HWND hwndDlg, PWSTR pszShortDateSep)
91*c2c66affSColin Finck {
92*c2c66affSColin Finck     INT nSepStrSize;
93*c2c66affSColin Finck     INT nSepCount;
94*c2c66affSColin Finck 
95*c2c66affSColin Finck     /* Get separator */
96*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESEP_COMBO,
97*c2c66affSColin Finck                         WM_GETTEXT,
98*c2c66affSColin Finck                         (WPARAM)MAX_SAMPLES_STR_SIZE,
99*c2c66affSColin Finck                         (LPARAM)pszShortDateSep);
100*c2c66affSColin Finck 
101*c2c66affSColin Finck     /* Get separator string size */
102*c2c66affSColin Finck     nSepStrSize = wcslen(pszShortDateSep);
103*c2c66affSColin Finck 
104*c2c66affSColin Finck     /* Check date components */
105*c2c66affSColin Finck     for (nSepCount = 0; nSepCount < nSepStrSize; nSepCount++)
106*c2c66affSColin Finck     {
107*c2c66affSColin Finck         if (iswalnum(pszShortDateSep[nSepCount]) || (pszShortDateSep[nSepCount] == L'\''))
108*c2c66affSColin Finck         {
109*c2c66affSColin Finck             PrintErrorMsgBox(IDS_ERROR_SYMBOL_SEPARATE);
110*c2c66affSColin Finck             return FALSE;
111*c2c66affSColin Finck         }
112*c2c66affSColin Finck     }
113*c2c66affSColin Finck 
114*c2c66affSColin Finck     if (nSepStrSize == 0)
115*c2c66affSColin Finck     {
116*c2c66affSColin Finck         PrintErrorMsgBox(IDS_ERROR_SYMBOL_SEPARATE);
117*c2c66affSColin Finck         return FALSE;
118*c2c66affSColin Finck     }
119*c2c66affSColin Finck 
120*c2c66affSColin Finck     return TRUE;
121*c2c66affSColin Finck }
122*c2c66affSColin Finck 
123*c2c66affSColin Finck /* Setted up short date format to registry */
124*c2c66affSColin Finck static BOOL
SetShortDateFormat(HWND hwndDlg,PWSTR pszShortDateFmt)125*c2c66affSColin Finck SetShortDateFormat(HWND hwndDlg, PWSTR pszShortDateFmt)
126*c2c66affSColin Finck {
127*c2c66affSColin Finck     WCHAR szShortDateSep[MAX_SAMPLES_STR_SIZE];
128*c2c66affSColin Finck     WCHAR szFoundDateSep[MAX_SAMPLES_STR_SIZE];
129*c2c66affSColin Finck     PWSTR pszResultStr;
130*c2c66affSColin Finck     PWSTR pszFoundSep;
131*c2c66affSColin Finck     BOOL OpenApostFlg = FALSE;
132*c2c66affSColin Finck     INT nFmtStrSize;
133*c2c66affSColin Finck     INT nDateCompCount;
134*c2c66affSColin Finck 
135*c2c66affSColin Finck     /* Get format */
136*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SHRTDATEFMT_COMBO,
137*c2c66affSColin Finck                         WM_GETTEXT,
138*c2c66affSColin Finck                         (WPARAM)MAX_SAMPLES_STR_SIZE,
139*c2c66affSColin Finck                         (LPARAM)pszShortDateFmt);
140*c2c66affSColin Finck 
141*c2c66affSColin Finck     /* Get separator */
142*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESEP_COMBO,
143*c2c66affSColin Finck                         WM_GETTEXT,
144*c2c66affSColin Finck                         (WPARAM)MAX_SAMPLES_STR_SIZE,
145*c2c66affSColin Finck                         (LPARAM)szShortDateSep);
146*c2c66affSColin Finck 
147*c2c66affSColin Finck     /* Get format-string size */
148*c2c66affSColin Finck     nFmtStrSize = wcslen(pszShortDateFmt);
149*c2c66affSColin Finck 
150*c2c66affSColin Finck     /* Check date components */
151*c2c66affSColin Finck     for (nDateCompCount = 0; nDateCompCount < nFmtStrSize; nDateCompCount++)
152*c2c66affSColin Finck     {
153*c2c66affSColin Finck         if (pszShortDateFmt[nDateCompCount] == L'\'')
154*c2c66affSColin Finck         {
155*c2c66affSColin Finck             OpenApostFlg = !OpenApostFlg;
156*c2c66affSColin Finck         }
157*c2c66affSColin Finck 
158*c2c66affSColin Finck         if (iswalnum(pszShortDateFmt[nDateCompCount]) &&
159*c2c66affSColin Finck             !isDateCompAl(pszShortDateFmt[nDateCompCount]) &&
160*c2c66affSColin Finck             !OpenApostFlg)
161*c2c66affSColin Finck         {
162*c2c66affSColin Finck             PrintErrorMsgBox(IDS_ERROR_SYMBOL_FORMAT_SHORT);
163*c2c66affSColin Finck             return FALSE;
164*c2c66affSColin Finck         }
165*c2c66affSColin Finck     }
166*c2c66affSColin Finck 
167*c2c66affSColin Finck     if (OpenApostFlg || nFmtStrSize == 0)
168*c2c66affSColin Finck     {
169*c2c66affSColin Finck         PrintErrorMsgBox(IDS_ERROR_SYMBOL_FORMAT_SHORT);
170*c2c66affSColin Finck         return FALSE;
171*c2c66affSColin Finck     }
172*c2c66affSColin Finck 
173*c2c66affSColin Finck     pszFoundSep = FindDateSep(pszShortDateFmt);
174*c2c66affSColin Finck     if (pszFoundSep != NULL)
175*c2c66affSColin Finck     {
176*c2c66affSColin Finck         /* Substring replacement of separator */
177*c2c66affSColin Finck         wcscpy(szFoundDateSep, pszFoundSep);
178*c2c66affSColin Finck         pszResultStr = ReplaceSubStr(pszShortDateFmt, szShortDateSep, szFoundDateSep);
179*c2c66affSColin Finck         if (pszResultStr != NULL)
180*c2c66affSColin Finck         {
181*c2c66affSColin Finck             wcscpy(pszShortDateFmt, pszResultStr);
182*c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, pszResultStr);
183*c2c66affSColin Finck         }
184*c2c66affSColin Finck 
185*c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pszFoundSep);
186*c2c66affSColin Finck     }
187*c2c66affSColin Finck 
188*c2c66affSColin Finck     return TRUE;
189*c2c66affSColin Finck }
190*c2c66affSColin Finck 
191*c2c66affSColin Finck /* Setted up long date format to registry */
192*c2c66affSColin Finck static BOOL
SetLongDateFormat(HWND hwndDlg,PWSTR pszLongDateFmt)193*c2c66affSColin Finck SetLongDateFormat(HWND hwndDlg, PWSTR pszLongDateFmt)
194*c2c66affSColin Finck {
195*c2c66affSColin Finck     BOOL OpenApostFlg = FALSE;
196*c2c66affSColin Finck     INT nFmtStrSize;
197*c2c66affSColin Finck     INT nDateCompCount;
198*c2c66affSColin Finck 
199*c2c66affSColin Finck     /* Get format */
200*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_LONGDATEFMT_COMBO,
201*c2c66affSColin Finck                         WM_GETTEXT,
202*c2c66affSColin Finck                         (WPARAM)MAX_SAMPLES_STR_SIZE,
203*c2c66affSColin Finck                         (LPARAM)pszLongDateFmt);
204*c2c66affSColin Finck 
205*c2c66affSColin Finck     /* Get format string size */
206*c2c66affSColin Finck     nFmtStrSize = wcslen(pszLongDateFmt);
207*c2c66affSColin Finck 
208*c2c66affSColin Finck     /* Check date components */
209*c2c66affSColin Finck     for (nDateCompCount = 0; nDateCompCount < nFmtStrSize; nDateCompCount++)
210*c2c66affSColin Finck     {
211*c2c66affSColin Finck         if (pszLongDateFmt[nDateCompCount] == L'\'')
212*c2c66affSColin Finck         {
213*c2c66affSColin Finck             OpenApostFlg = !OpenApostFlg;
214*c2c66affSColin Finck         }
215*c2c66affSColin Finck 
216*c2c66affSColin Finck         if (iswalnum(pszLongDateFmt[nDateCompCount]) &&
217*c2c66affSColin Finck             !isDateCompAl(pszLongDateFmt[nDateCompCount]) &&
218*c2c66affSColin Finck             !OpenApostFlg)
219*c2c66affSColin Finck         {
220*c2c66affSColin Finck             PrintErrorMsgBox(IDS_ERROR_SYMBOL_FORMAT_LONG);
221*c2c66affSColin Finck             return FALSE;
222*c2c66affSColin Finck         }
223*c2c66affSColin Finck     }
224*c2c66affSColin Finck 
225*c2c66affSColin Finck     if (OpenApostFlg || nFmtStrSize == 0)
226*c2c66affSColin Finck     {
227*c2c66affSColin Finck         PrintErrorMsgBox(IDS_ERROR_SYMBOL_FORMAT_LONG);
228*c2c66affSColin Finck         return FALSE;
229*c2c66affSColin Finck     }
230*c2c66affSColin Finck 
231*c2c66affSColin Finck     return TRUE;
232*c2c66affSColin Finck }
233*c2c66affSColin Finck 
234*c2c66affSColin Finck /* Init short date separator control box */
235*c2c66affSColin Finck static VOID
InitShortDateSepSamples(HWND hwndDlg,PGLOBALDATA pGlobalData)236*c2c66affSColin Finck InitShortDateSepSamples(HWND hwndDlg, PGLOBALDATA pGlobalData)
237*c2c66affSColin Finck {
238*c2c66affSColin Finck     PWSTR ShortDateSepSamples[MAX_SHRT_DATE_SEPARATORS] =
239*c2c66affSColin Finck     {
240*c2c66affSColin Finck         L".",
241*c2c66affSColin Finck         L"/",
242*c2c66affSColin Finck         L"-"
243*c2c66affSColin Finck     };
244*c2c66affSColin Finck     INT nCBIndex;
245*c2c66affSColin Finck     INT nRetCode;
246*c2c66affSColin Finck 
247*c2c66affSColin Finck     /* Clear all box content */
248*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESEP_COMBO,
249*c2c66affSColin Finck                         CB_RESETCONTENT,
250*c2c66affSColin Finck                         (WPARAM)0,
251*c2c66affSColin Finck                         (LPARAM)0);
252*c2c66affSColin Finck 
253*c2c66affSColin Finck     /* Create standard list of separators */
254*c2c66affSColin Finck     for (nCBIndex = 0; nCBIndex < MAX_SHRT_DATE_SEPARATORS; nCBIndex++)
255*c2c66affSColin Finck     {
256*c2c66affSColin Finck         SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESEP_COMBO,
257*c2c66affSColin Finck                             CB_ADDSTRING,
258*c2c66affSColin Finck                             0,
259*c2c66affSColin Finck                             (LPARAM)ShortDateSepSamples[nCBIndex]);
260*c2c66affSColin Finck     }
261*c2c66affSColin Finck 
262*c2c66affSColin Finck     /* Set current item to value from registry */
263*c2c66affSColin Finck     nRetCode = SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESEP_COMBO,
264*c2c66affSColin Finck                                    CB_SELECTSTRING,
265*c2c66affSColin Finck                                    -1,
266*c2c66affSColin Finck                                    (LPARAM)pGlobalData->szDateSep);
267*c2c66affSColin Finck 
268*c2c66affSColin Finck     /* If it is not successful, add new value to list and select them */
269*c2c66affSColin Finck     if (nRetCode == CB_ERR)
270*c2c66affSColin Finck     {
271*c2c66affSColin Finck         SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESEP_COMBO,
272*c2c66affSColin Finck                             CB_ADDSTRING,
273*c2c66affSColin Finck                             0,
274*c2c66affSColin Finck                             (LPARAM)pGlobalData->szDateSep);
275*c2c66affSColin Finck         SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESEP_COMBO,
276*c2c66affSColin Finck                             CB_SELECTSTRING,
277*c2c66affSColin Finck                             -1,
278*c2c66affSColin Finck                             (LPARAM)pGlobalData->szDateSep);
279*c2c66affSColin Finck     }
280*c2c66affSColin Finck }
281*c2c66affSColin Finck 
282*c2c66affSColin Finck static BOOL CALLBACK
ShortDateFormatEnumProc(PWSTR lpTimeFormatString)283*c2c66affSColin Finck ShortDateFormatEnumProc(PWSTR lpTimeFormatString)
284*c2c66affSColin Finck {
285*c2c66affSColin Finck     SendMessageW(hwndEnum,
286*c2c66affSColin Finck                  CB_ADDSTRING,
287*c2c66affSColin Finck                  0,
288*c2c66affSColin Finck                  (LPARAM)lpTimeFormatString);
289*c2c66affSColin Finck 
290*c2c66affSColin Finck     return TRUE;
291*c2c66affSColin Finck }
292*c2c66affSColin Finck 
293*c2c66affSColin Finck /* Init short date control box */
294*c2c66affSColin Finck VOID
InitShortDateCB(HWND hwndDlg,PGLOBALDATA pGlobalData)295*c2c66affSColin Finck InitShortDateCB(HWND hwndDlg, PGLOBALDATA pGlobalData)
296*c2c66affSColin Finck {
297*c2c66affSColin Finck     INT nRetCode;
298*c2c66affSColin Finck 
299*c2c66affSColin Finck     /* Limit text lengths */
300*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SHRTDATEFMT_COMBO,
301*c2c66affSColin Finck                         CB_LIMITTEXT,
302*c2c66affSColin Finck                         MAX_SHORTDATEFORMAT,
303*c2c66affSColin Finck                         0);
304*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESEP_COMBO,
305*c2c66affSColin Finck                         CB_LIMITTEXT,
306*c2c66affSColin Finck                         MAX_DATESEPARATOR,
307*c2c66affSColin Finck                         0);
308*c2c66affSColin Finck 
309*c2c66affSColin Finck     /* Clear all box content */
310*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SHRTDATEFMT_COMBO,
311*c2c66affSColin Finck                         CB_RESETCONTENT,
312*c2c66affSColin Finck                         (WPARAM)0,
313*c2c66affSColin Finck                         (LPARAM)0);
314*c2c66affSColin Finck 
315*c2c66affSColin Finck     /* Enumerate short date formats */
316*c2c66affSColin Finck     hwndEnum = GetDlgItem(hwndDlg, IDC_SHRTDATEFMT_COMBO);
317*c2c66affSColin Finck     EnumDateFormatsW(ShortDateFormatEnumProc, pGlobalData->UserLCID, DATE_SHORTDATE);
318*c2c66affSColin Finck 
319*c2c66affSColin Finck     /* Set current item to value from registry */
320*c2c66affSColin Finck     nRetCode = SendDlgItemMessageW(hwndDlg, IDC_SHRTDATEFMT_COMBO,
321*c2c66affSColin Finck                                    CB_SELECTSTRING,
322*c2c66affSColin Finck                                    -1,
323*c2c66affSColin Finck                                    (LPARAM)pGlobalData->szShortDateFormat);
324*c2c66affSColin Finck 
325*c2c66affSColin Finck     /* If it is not successful, add new value to list and select them */
326*c2c66affSColin Finck     if (nRetCode == CB_ERR)
327*c2c66affSColin Finck     {
328*c2c66affSColin Finck         SendDlgItemMessageW(hwndDlg, IDC_SHRTDATEFMT_COMBO,
329*c2c66affSColin Finck                             CB_ADDSTRING,
330*c2c66affSColin Finck                             0,
331*c2c66affSColin Finck                             (LPARAM)pGlobalData->szShortDateFormat);
332*c2c66affSColin Finck         SendDlgItemMessageW(hwndDlg, IDC_SHRTDATEFMT_COMBO,
333*c2c66affSColin Finck                             CB_SELECTSTRING,
334*c2c66affSColin Finck                             -1,
335*c2c66affSColin Finck                             (LPARAM)pGlobalData->szShortDateFormat);
336*c2c66affSColin Finck     }
337*c2c66affSColin Finck }
338*c2c66affSColin Finck 
339*c2c66affSColin Finck /* Init long date control box */
340*c2c66affSColin Finck static VOID
InitLongDateCB(HWND hwndDlg,PGLOBALDATA pGlobalData)341*c2c66affSColin Finck InitLongDateCB(HWND hwndDlg, PGLOBALDATA pGlobalData)
342*c2c66affSColin Finck {
343*c2c66affSColin Finck     INT nRetCode;
344*c2c66affSColin Finck 
345*c2c66affSColin Finck     /* Limit text length */
346*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_LONGDATEFMT_COMBO,
347*c2c66affSColin Finck                         CB_LIMITTEXT,
348*c2c66affSColin Finck                         MAX_LONGDATEFORMAT,
349*c2c66affSColin Finck                         0);
350*c2c66affSColin Finck 
351*c2c66affSColin Finck     /* Clear all box content */
352*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_LONGDATEFMT_COMBO,
353*c2c66affSColin Finck                         CB_RESETCONTENT,
354*c2c66affSColin Finck                         (WPARAM)0,
355*c2c66affSColin Finck                         (LPARAM)0);
356*c2c66affSColin Finck 
357*c2c66affSColin Finck     /* Enumerate short long formats */
358*c2c66affSColin Finck     hwndEnum = GetDlgItem(hwndDlg, IDC_LONGDATEFMT_COMBO);
359*c2c66affSColin Finck     EnumDateFormatsW(ShortDateFormatEnumProc, pGlobalData->UserLCID, DATE_LONGDATE);
360*c2c66affSColin Finck 
361*c2c66affSColin Finck     /* Set current item to value from registry */
362*c2c66affSColin Finck     nRetCode = SendDlgItemMessageW(hwndDlg, IDC_LONGDATEFMT_COMBO,
363*c2c66affSColin Finck                                    CB_SELECTSTRING,
364*c2c66affSColin Finck                                    -1,
365*c2c66affSColin Finck                                    (LPARAM)pGlobalData->szLongDateFormat);
366*c2c66affSColin Finck 
367*c2c66affSColin Finck     /* If it is not successful, add new value to list and select them */
368*c2c66affSColin Finck     if (nRetCode == CB_ERR)
369*c2c66affSColin Finck     {
370*c2c66affSColin Finck         SendDlgItemMessageW(hwndDlg, IDC_LONGDATEFMT_COMBO,
371*c2c66affSColin Finck                             CB_ADDSTRING,
372*c2c66affSColin Finck                             0,
373*c2c66affSColin Finck                             (LPARAM)pGlobalData->szLongDateFormat);
374*c2c66affSColin Finck         SendDlgItemMessageW(hwndDlg, IDC_LONGDATEFMT_COMBO,
375*c2c66affSColin Finck                             CB_SELECTSTRING,
376*c2c66affSColin Finck                             -1,
377*c2c66affSColin Finck                             (LPARAM)pGlobalData->szLongDateFormat);
378*c2c66affSColin Finck     }
379*c2c66affSColin Finck }
380*c2c66affSColin Finck 
381*c2c66affSColin Finck /* Set up max date value to registry */
382*c2c66affSColin Finck static VOID
SetMaxDate(HWND hwndDlg,LCID lcid)383*c2c66affSColin Finck SetMaxDate(HWND hwndDlg, LCID lcid)
384*c2c66affSColin Finck {
385*c2c66affSColin Finck     WCHAR szMaxDateVal[YEAR_STR_MAX_SIZE];
386*c2c66affSColin Finck     HWND hWndYearSpin;
387*c2c66affSColin Finck     INT nSpinVal;
388*c2c66affSColin Finck 
389*c2c66affSColin Finck     hWndYearSpin = GetDlgItem(hwndDlg, IDC_SCR_MAX_YEAR);
390*c2c66affSColin Finck 
391*c2c66affSColin Finck     /* Get spin value */
392*c2c66affSColin Finck     nSpinVal = LOWORD(SendMessageW(hWndYearSpin,
393*c2c66affSColin Finck                                    UDM_GETPOS,
394*c2c66affSColin Finck                                    0,
395*c2c66affSColin Finck                                    0));
396*c2c66affSColin Finck 
397*c2c66affSColin Finck     /* convert to wide char */
398*c2c66affSColin Finck     _itow(nSpinVal, szMaxDateVal, DECIMAL_RADIX);
399*c2c66affSColin Finck 
400*c2c66affSColin Finck     /* Save max date value */
401*c2c66affSColin Finck     SetCalendarInfoW(lcid,
402*c2c66affSColin Finck                      CAL_GREGORIAN,
403*c2c66affSColin Finck                      48 , /* CAL_ITWODIGITYEARMAX */
404*c2c66affSColin Finck                      (PCWSTR)szMaxDateVal);
405*c2c66affSColin Finck }
406*c2c66affSColin Finck 
407*c2c66affSColin Finck /* Get max date value from registry set */
408*c2c66affSColin Finck static INT
GetMaxDate(LCID lcid)409*c2c66affSColin Finck GetMaxDate(LCID lcid)
410*c2c66affSColin Finck {
411*c2c66affSColin Finck     INT nMaxDateVal = 0;
412*c2c66affSColin Finck 
413*c2c66affSColin Finck     GetCalendarInfoW(lcid,
414*c2c66affSColin Finck                      CAL_GREGORIAN,
415*c2c66affSColin Finck                      CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
416*c2c66affSColin Finck                      NULL,
417*c2c66affSColin Finck                      0, /* ret type - number */
418*c2c66affSColin Finck                      (LPDWORD)&nMaxDateVal);
419*c2c66affSColin Finck 
420*c2c66affSColin Finck     return nMaxDateVal;
421*c2c66affSColin Finck }
422*c2c66affSColin Finck 
423*c2c66affSColin Finck /* Set's MIN data edit control value to MAX-99 */
424*c2c66affSColin Finck static VOID
SetMinDate(HWND hwndDlg)425*c2c66affSColin Finck SetMinDate(HWND hwndDlg)
426*c2c66affSColin Finck {
427*c2c66affSColin Finck     WCHAR OutBuffer[YEAR_STR_MAX_SIZE];
428*c2c66affSColin Finck     HWND hWndYearSpin;
429*c2c66affSColin Finck     INT nSpinVal;
430*c2c66affSColin Finck 
431*c2c66affSColin Finck     hWndYearSpin = GetDlgItem(hwndDlg, IDC_SCR_MAX_YEAR);
432*c2c66affSColin Finck 
433*c2c66affSColin Finck     /* Get spin value */
434*c2c66affSColin Finck     nSpinVal = LOWORD(SendMessageW(hWndYearSpin,
435*c2c66affSColin Finck                                    UDM_GETPOS,
436*c2c66affSColin Finck                                    0,
437*c2c66affSColin Finck                                    0));
438*c2c66affSColin Finck 
439*c2c66affSColin Finck     /* Set min year value */
440*c2c66affSColin Finck     wsprintf(OutBuffer, L"%d", (DWORD)nSpinVal - YEAR_DIFF);
441*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_FIRSTYEAR_EDIT,
442*c2c66affSColin Finck                         WM_SETTEXT,
443*c2c66affSColin Finck                         0,
444*c2c66affSColin Finck                         (LPARAM)OutBuffer);
445*c2c66affSColin Finck }
446*c2c66affSColin Finck 
447*c2c66affSColin Finck /* Init spin control */
448*c2c66affSColin Finck static VOID
InitMinMaxDateSpin(HWND hwndDlg,PGLOBALDATA pGlobalData)449*c2c66affSColin Finck InitMinMaxDateSpin(HWND hwndDlg, PGLOBALDATA pGlobalData)
450*c2c66affSColin Finck {
451*c2c66affSColin Finck     WCHAR OutBuffer[YEAR_STR_MAX_SIZE];
452*c2c66affSColin Finck     HWND hWndYearSpin;
453*c2c66affSColin Finck 
454*c2c66affSColin Finck     /* Limit text lengths */
455*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_FIRSTYEAR_EDIT,
456*c2c66affSColin Finck                         EM_LIMITTEXT,
457*c2c66affSColin Finck                         MAX_YEAR_EDIT,
458*c2c66affSColin Finck                         0);
459*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SECONDYEAR_EDIT,
460*c2c66affSColin Finck                         EM_LIMITTEXT,
461*c2c66affSColin Finck                         MAX_YEAR_EDIT,
462*c2c66affSColin Finck                         0);
463*c2c66affSColin Finck 
464*c2c66affSColin Finck     hWndYearSpin = GetDlgItem(hwndDlg, IDC_SCR_MAX_YEAR);
465*c2c66affSColin Finck 
466*c2c66affSColin Finck     /* Init max date value */
467*c2c66affSColin Finck     wsprintf(OutBuffer, L"%04d", (DWORD)GetMaxDate(pGlobalData->UserLCID));
468*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SECONDYEAR_EDIT,
469*c2c66affSColin Finck                         WM_SETTEXT,
470*c2c66affSColin Finck                         0,
471*c2c66affSColin Finck                         (LPARAM)OutBuffer);
472*c2c66affSColin Finck 
473*c2c66affSColin Finck     /* Init min date value */
474*c2c66affSColin Finck     wsprintf(OutBuffer, L"%04d", (DWORD)GetMaxDate(pGlobalData->UserLCID) - YEAR_DIFF);
475*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_FIRSTYEAR_EDIT,
476*c2c66affSColin Finck                         WM_SETTEXT,
477*c2c66affSColin Finck                         0,
478*c2c66affSColin Finck                         (LPARAM)OutBuffer);
479*c2c66affSColin Finck 
480*c2c66affSColin Finck     /* Init updown control */
481*c2c66affSColin Finck     /* Set bounds */
482*c2c66affSColin Finck     SendMessageW(hWndYearSpin,
483*c2c66affSColin Finck                  UDM_SETRANGE,
484*c2c66affSColin Finck                  0,
485*c2c66affSColin Finck                  MAKELONG(MAX_YEAR,YEAR_DIFF));
486*c2c66affSColin Finck 
487*c2c66affSColin Finck     /* Set current value */
488*c2c66affSColin Finck     SendMessageW(hWndYearSpin,
489*c2c66affSColin Finck                  UDM_SETPOS,
490*c2c66affSColin Finck                  0,
491*c2c66affSColin Finck                  MAKELONG(GetMaxDate(pGlobalData->UserLCID),0));
492*c2c66affSColin Finck }
493*c2c66affSColin Finck 
494*c2c66affSColin Finck /* Update all date locale samples */
495*c2c66affSColin Finck static VOID
UpdateDateLocaleSamples(HWND hwndDlg,PGLOBALDATA pGlobalData)496*c2c66affSColin Finck UpdateDateLocaleSamples(HWND hwndDlg,
497*c2c66affSColin Finck                         PGLOBALDATA pGlobalData)
498*c2c66affSColin Finck {
499*c2c66affSColin Finck     WCHAR OutBuffer[MAX_SAMPLES_STR_SIZE];
500*c2c66affSColin Finck 
501*c2c66affSColin Finck     /* Get short date format sample */
502*c2c66affSColin Finck     GetDateFormatW(pGlobalData->UserLCID, 0, NULL,
503*c2c66affSColin Finck                    pGlobalData->szShortDateFormat, OutBuffer,
504*c2c66affSColin Finck                    MAX_SAMPLES_STR_SIZE);
505*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_SHRTDATESAMPLE_EDIT, WM_SETTEXT,
506*c2c66affSColin Finck                         0, (LPARAM)OutBuffer);
507*c2c66affSColin Finck 
508*c2c66affSColin Finck     /* Get long date sample */
509*c2c66affSColin Finck     GetDateFormatW(pGlobalData->UserLCID, 0, NULL,
510*c2c66affSColin Finck                    pGlobalData->szLongDateFormat, OutBuffer,
511*c2c66affSColin Finck                    MAX_SAMPLES_STR_SIZE);
512*c2c66affSColin Finck     SendDlgItemMessageW(hwndDlg, IDC_LONGDATESAMPLE_EDIT,
513*c2c66affSColin Finck                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
514*c2c66affSColin Finck }
515*c2c66affSColin Finck 
516*c2c66affSColin Finck 
517*c2c66affSColin Finck static
518*c2c66affSColin Finck BOOL
GetDateSetting(HWND hwndDlg,PGLOBALDATA pGlobalData)519*c2c66affSColin Finck GetDateSetting(
520*c2c66affSColin Finck     HWND hwndDlg,
521*c2c66affSColin Finck     PGLOBALDATA pGlobalData)
522*c2c66affSColin Finck {
523*c2c66affSColin Finck     WCHAR szLongDateFormat[MAX_LONGDATEFORMAT];
524*c2c66affSColin Finck     WCHAR szShortDateFormat[MAX_SHORTDATEFORMAT];
525*c2c66affSColin Finck     WCHAR szDateSeparator[MAX_DATESEPARATOR];
526*c2c66affSColin Finck 
527*c2c66affSColin Finck     if (!SetLongDateFormat(hwndDlg, szLongDateFormat) ||
528*c2c66affSColin Finck         !SetShortDateFormat(hwndDlg, szShortDateFormat) ||
529*c2c66affSColin Finck         !SetShortDateSep(hwndDlg, szDateSeparator))
530*c2c66affSColin Finck     {
531*c2c66affSColin Finck         return FALSE;
532*c2c66affSColin Finck     }
533*c2c66affSColin Finck 
534*c2c66affSColin Finck     /* Store settings in global data */
535*c2c66affSColin Finck     wcscpy(pGlobalData->szLongDateFormat, szLongDateFormat);
536*c2c66affSColin Finck     wcscpy(pGlobalData->szShortDateFormat, szShortDateFormat);
537*c2c66affSColin Finck     wcscpy(pGlobalData->szDateSep, szDateSeparator);
538*c2c66affSColin Finck 
539*c2c66affSColin Finck     return TRUE;
540*c2c66affSColin Finck }
541*c2c66affSColin Finck 
542*c2c66affSColin Finck /* Property page dialog callback */
543*c2c66affSColin Finck INT_PTR CALLBACK
DatePageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)544*c2c66affSColin Finck DatePageProc(HWND hwndDlg,
545*c2c66affSColin Finck              UINT uMsg,
546*c2c66affSColin Finck              WPARAM wParam,
547*c2c66affSColin Finck              LPARAM lParam)
548*c2c66affSColin Finck {
549*c2c66affSColin Finck     PGLOBALDATA pGlobalData;
550*c2c66affSColin Finck 
551*c2c66affSColin Finck     pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
552*c2c66affSColin Finck 
553*c2c66affSColin Finck     switch (uMsg)
554*c2c66affSColin Finck     {
555*c2c66affSColin Finck         case WM_INITDIALOG:
556*c2c66affSColin Finck             pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam;
557*c2c66affSColin Finck             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
558*c2c66affSColin Finck 
559*c2c66affSColin Finck             InitMinMaxDateSpin(hwndDlg, pGlobalData);
560*c2c66affSColin Finck             UpdateDateLocaleSamples(hwndDlg, pGlobalData);
561*c2c66affSColin Finck             InitShortDateCB(hwndDlg, pGlobalData);
562*c2c66affSColin Finck             InitLongDateCB(hwndDlg, pGlobalData);
563*c2c66affSColin Finck             InitShortDateSepSamples(hwndDlg, pGlobalData);
564*c2c66affSColin Finck             /* TODO: Add other calendar types */
565*c2c66affSColin Finck             pGlobalData->bEnableYearNotification = TRUE;
566*c2c66affSColin Finck             break;
567*c2c66affSColin Finck 
568*c2c66affSColin Finck         case WM_COMMAND:
569*c2c66affSColin Finck             switch (LOWORD(wParam))
570*c2c66affSColin Finck             {
571*c2c66affSColin Finck                 case IDC_SECONDYEAR_EDIT:
572*c2c66affSColin Finck                     if (HIWORD(wParam) == EN_CHANGE &&
573*c2c66affSColin Finck                         pGlobalData != NULL &&
574*c2c66affSColin Finck                         pGlobalData->bEnableYearNotification == TRUE)
575*c2c66affSColin Finck                     {
576*c2c66affSColin Finck                         SetMinDate(hwndDlg);
577*c2c66affSColin Finck 
578*c2c66affSColin Finck                         /* Enable the Apply button */
579*c2c66affSColin Finck                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
580*c2c66affSColin Finck                     }
581*c2c66affSColin Finck                     break;
582*c2c66affSColin Finck 
583*c2c66affSColin Finck                 case IDC_CALTYPE_COMBO:
584*c2c66affSColin Finck                 case IDC_HIJCHRON_COMBO:
585*c2c66affSColin Finck                 case IDC_SHRTDATEFMT_COMBO:
586*c2c66affSColin Finck                 case IDC_LONGDATEFMT_COMBO:
587*c2c66affSColin Finck                 case IDC_SHRTDATESEP_COMBO:
588*c2c66affSColin Finck                     if (HIWORD(wParam) == CBN_SELCHANGE ||
589*c2c66affSColin Finck                         HIWORD(wParam) == CBN_EDITCHANGE)
590*c2c66affSColin Finck                     {
591*c2c66affSColin Finck                         /* Enable the Apply button */
592*c2c66affSColin Finck                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
593*c2c66affSColin Finck                     }
594*c2c66affSColin Finck                     break;
595*c2c66affSColin Finck             }
596*c2c66affSColin Finck             break;
597*c2c66affSColin Finck 
598*c2c66affSColin Finck         case WM_NOTIFY:
599*c2c66affSColin Finck             if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
600*c2c66affSColin Finck             {
601*c2c66affSColin Finck                 if (GetDateSetting(hwndDlg, pGlobalData))
602*c2c66affSColin Finck                 {
603*c2c66affSColin Finck                     pGlobalData->bUserLocaleChanged = TRUE;
604*c2c66affSColin Finck                     SetMaxDate(hwndDlg, pGlobalData->UserLCID);
605*c2c66affSColin Finck                     UpdateDateLocaleSamples(hwndDlg, pGlobalData);
606*c2c66affSColin Finck                 }
607*c2c66affSColin Finck             }
608*c2c66affSColin Finck             break;
609*c2c66affSColin Finck     }
610*c2c66affSColin Finck 
611*c2c66affSColin Finck     return FALSE;
612*c2c66affSColin Finck }
613*c2c66affSColin Finck 
614*c2c66affSColin Finck /* EOF */
615