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/numbers.c
22 * PURPOSE: Numbers property page
23 * PROGRAMMER: Eric Kohl
28 #define SAMPLE_NUMBER L"123456789"
29 #define SAMPLE_NEG_NUMBER L"-123456789"
30 #define MAX_NUM_SEP_SAMPLES 2
31 #define MAX_FRAC_NUM_SAMPLES 10
32 #define MAX_FIELD_SEP_SAMPLES 1
33 #define MAX_FIELD_DIG_SAMPLES 3
34 #define MAX_NEG_SIGN_SAMPLES 1
35 #define MAX_NEG_NUMBERS_SAMPLES 5
36 #define MAX_LEAD_ZEROES_SAMPLES 2
37 #define MAX_LIST_SEP_SAMPLES 1
38 #define MAX_UNITS_SYS_SAMPLES 2
40 static PWSTR lpNumSepSamples
[MAX_NUM_SEP_SAMPLES
] =
42 static PWSTR lpFieldSepSamples
[MAX_FIELD_SEP_SAMPLES
] =
44 static PWSTR lpFieldDigNumSamples
[MAX_FIELD_DIG_SAMPLES
] =
45 {L
"0;0", L
"3;0", L
"3;2;0"};
46 static PWSTR lpNegSignSamples
[MAX_NEG_SIGN_SAMPLES
] =
48 static PWSTR lpNegNumFmtSamples
[MAX_NEG_NUMBERS_SAMPLES
] =
49 {L
"(1,1)", L
"-1,1", L
"- 1,1", L
"1,1-", L
"1,1 -"};
50 static PWSTR lpLeadNumFmtSamples
[MAX_LEAD_ZEROES_SAMPLES
] =
52 static PWSTR lpListSepSamples
[MAX_LIST_SEP_SAMPLES
] =
56 /* Init num decimal separator control box */
58 InitNumDecimalSepCB(HWND hwndDlg
, PGLOBALDATA pGlobalData
)
63 /* Limit text length */
64 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERDSYMBOL
,
66 MAX_NUMDECIMALSEP
- 1,
69 /* Clear all box content */
70 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERDSYMBOL
,
75 /* Create standard list of decimal separators */
76 for (nCBIndex
= 0; nCBIndex
< MAX_NUM_SEP_SAMPLES
; nCBIndex
++)
78 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERDSYMBOL
,
81 (LPARAM
)lpNumSepSamples
[nCBIndex
]);
84 /* Set current item to value from registry */
85 nRetCode
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERDSYMBOL
,
88 (LPARAM
)pGlobalData
->szNumDecimalSep
);
90 /* If it is not successful, add new values to list and select them */
91 if (nRetCode
== CB_ERR
)
93 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERDSYMBOL
,
96 (LPARAM
)pGlobalData
->szNumDecimalSep
);
97 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERDSYMBOL
,
100 (LPARAM
)pGlobalData
->szNumDecimalSep
);
104 /* Init number of fractional symbols control box */
106 InitNumOfFracSymbCB(HWND hwndDlg
, PGLOBALDATA pGlobalData
)
108 WCHAR szFracCount
[MAX_SAMPLES_STR_SIZE
];
111 /* Clear all box content */
112 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNDIGDEC
,
117 /* Create standard list of fractional symbols */
118 for (nCBIndex
= 0; nCBIndex
< MAX_FRAC_NUM_SAMPLES
; nCBIndex
++)
120 /* Convert to wide char */
121 _itow(nCBIndex
, szFracCount
, DECIMAL_RADIX
);
123 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNDIGDEC
,
126 (LPARAM
)szFracCount
);
129 /* Set current item to value from registry */
130 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNDIGDEC
,
132 (WPARAM
)pGlobalData
->nNumDigits
,
136 /* Init field separator control box */
138 InitNumFieldSepCB(HWND hwndDlg
, PGLOBALDATA pGlobalData
)
143 /* Limit text length */
144 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDIGITGRSYM
,
146 MAX_NUMTHOUSANDSEP
- 1,
149 /* Clear all box content */
150 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDIGITGRSYM
,
155 /* Create standard list of field separators */
156 for (nCBIndex
= 0; nCBIndex
< MAX_FIELD_SEP_SAMPLES
; nCBIndex
++)
158 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDIGITGRSYM
,
161 (LPARAM
)lpFieldSepSamples
[nCBIndex
]);
164 /* Set current item to value from registry */
165 nRetCode
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDIGITGRSYM
,
168 (LPARAM
)pGlobalData
->szNumThousandSep
);
170 /* If it is not success, add new values to list and select them */
171 if (nRetCode
== CB_ERR
)
173 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDIGITGRSYM
,
176 (LPARAM
)pGlobalData
->szNumThousandSep
);
177 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDIGITGRSYM
,
180 (LPARAM
)pGlobalData
->szNumThousandSep
);
184 /* Init number of digits in field control box */
186 InitFieldDigNumCB(HWND hwndDlg
, PGLOBALDATA pGlobalData
)
188 PWSTR pszFieldDigNumSmpl
;
191 /* Clear all box content */
192 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDGROUPING
,
197 /* Create standard list of field digits num */
198 for (nCBIndex
= 0; nCBIndex
< MAX_FIELD_DIG_SAMPLES
; nCBIndex
++)
200 pszFieldDigNumSmpl
= InsSpacesFmt(SAMPLE_NUMBER
, lpFieldDigNumSamples
[nCBIndex
]);
201 if (pszFieldDigNumSmpl
!= NULL
)
203 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDGROUPING
,
206 (LPARAM
)pszFieldDigNumSmpl
);
207 HeapFree(GetProcessHeap(), 0, pszFieldDigNumSmpl
);
211 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDGROUPING
,
213 (WPARAM
)pGlobalData
->nNumGrouping
,
217 /* Init negative sign control box */
219 InitNegSignCB(HWND hwndDlg
, PGLOBALDATA pGlobalData
)
224 /* Limit text length */
225 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNSIGNSYM
,
227 MAX_NUMNEGATIVESIGN
- 1,
230 /* Clear all box content */
231 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNSIGNSYM
,
236 /* Create standard list of signs */
237 for (nCBIndex
= 0; nCBIndex
< MAX_NEG_SIGN_SAMPLES
; nCBIndex
++)
239 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNSIGNSYM
,
242 (LPARAM
)lpNegSignSamples
[nCBIndex
]);
245 /* Set current item to value from registry */
246 nRetCode
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNSIGNSYM
,
249 (LPARAM
)pGlobalData
->szNumNegativeSign
);
251 /* If it is not successful, add new values to list and select them */
252 if (nRetCode
== CB_ERR
)
254 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNSIGNSYM
,
257 (LPARAM
)pGlobalData
->szNumNegativeSign
);
258 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNSIGNSYM
,
261 (LPARAM
)pGlobalData
->szNumNegativeSign
);
265 /* Init negative numbers format control box */
267 InitNegNumFmtCB(HWND hwndDlg
, PGLOBALDATA pGlobalData
)
269 WCHAR szNewSample
[MAX_SAMPLES_STR_SIZE
];
273 /* Clear all box content */
274 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNNUMFORMAT
,
279 /* Create standard list of negative numbers formats */
280 for (nCBIndex
= 0; nCBIndex
< MAX_NEG_NUMBERS_SAMPLES
; nCBIndex
++)
282 /* Replace standard separator to setted */
283 pszResultStr
= ReplaceSubStr(lpNegNumFmtSamples
[nCBIndex
],
284 pGlobalData
->szNumDecimalSep
,
286 if (pszResultStr
!= NULL
)
288 wcscpy(szNewSample
, pszResultStr
);
289 HeapFree(GetProcessHeap(), 0, pszResultStr
);
292 /* Replace standard negative sign to setted */
293 pszResultStr
= ReplaceSubStr(szNewSample
,
294 pGlobalData
->szNumNegativeSign
,
296 if (pszResultStr
!= NULL
)
298 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNNUMFORMAT
,
301 (LPARAM
)pszResultStr
);
302 HeapFree(GetProcessHeap(), 0, pszResultStr
);
306 /* Set current item to value from registry */
307 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNNUMFORMAT
,
309 (WPARAM
)pGlobalData
->nNumNegFormat
,
313 /* Init leading zeroes control box */
315 InitLeadingZeroesCB(HWND hwndDlg
, PGLOBALDATA pGlobalData
)
320 /* Clear all box content */
321 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDISPLEADZER
,
326 /* Create list of standard leading zeroes formats */
327 for (nCBIndex
= 0; nCBIndex
< MAX_LEAD_ZEROES_SAMPLES
; nCBIndex
++)
329 pszResultStr
= ReplaceSubStr(lpLeadNumFmtSamples
[nCBIndex
],
330 pGlobalData
->szNumDecimalSep
,
332 if (pszResultStr
!= NULL
)
334 SendDlgItemMessage(hwndDlg
, IDC_NUMBERSDISPLEADZER
,
337 (LPARAM
)pszResultStr
);
338 HeapFree(GetProcessHeap(), 0, pszResultStr
);
342 /* Set current item to value from registry */
343 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDISPLEADZER
,
345 (WPARAM
)pGlobalData
->nNumLeadingZero
,
350 InitListSepCB(HWND hwndDlg
,
351 PGLOBALDATA pGlobalData
)
356 /* Limit text length */
357 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSLSEP
,
362 /* Clear all box content */
363 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSLSEP
,
368 /* Create standard list of signs */
369 for (nCBIndex
= 0; nCBIndex
< MAX_LIST_SEP_SAMPLES
; nCBIndex
++)
371 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSLSEP
,
374 (LPARAM
)lpListSepSamples
[nCBIndex
]);
377 /* Set current item to value from registry */
378 nRetCode
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSLSEP
,
381 (LPARAM
)pGlobalData
->szNumListSep
);
383 /* If it is not successful, add new values to list and select them */
384 if (nRetCode
== CB_ERR
)
386 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSLSEP
,
389 (LPARAM
)pGlobalData
->szNumListSep
);
390 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSLSEP
,
393 (LPARAM
)pGlobalData
->szNumListSep
);
397 /* Init system of units control box */
399 InitUnitsSysCB(HWND hwndDlg
,
400 PGLOBALDATA pGlobalData
)
402 WCHAR szUnitName
[128];
405 /* Clear all box content */
406 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSMEASSYS
,
411 /* Create list of standard system of units */
412 for (nCBIndex
= 0; nCBIndex
< MAX_UNITS_SYS_SAMPLES
; nCBIndex
++)
414 LoadStringW(hApplet
, IDS_METRIC
+ nCBIndex
, szUnitName
, 128);
416 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSMEASSYS
,
422 /* Set current item to value from registry */
423 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSMEASSYS
,
425 (WPARAM
)pGlobalData
->nNumMeasure
,
429 /* Update all numbers locale samples */
431 UpdateNumSamples(HWND hwndDlg
,
432 PGLOBALDATA pGlobalData
)
434 WCHAR OutBuffer
[MAX_FMT_SIZE
];
435 NUMBERFMT NumberFormat
;
437 NumberFormat
.NumDigits
= pGlobalData
->nNumDigits
;
438 NumberFormat
.LeadingZero
= pGlobalData
->nNumLeadingZero
;
439 NumberFormat
.Grouping
= GroupingFormats
[pGlobalData
->nNumGrouping
].nInteger
;
440 NumberFormat
.lpDecimalSep
= pGlobalData
->szNumDecimalSep
;
441 NumberFormat
.lpThousandSep
= pGlobalData
->szNumThousandSep
;
442 NumberFormat
.NegativeOrder
= pGlobalData
->nNumNegFormat
;
444 /* Get positive number format sample */
445 GetNumberFormatW(pGlobalData
->UserLCID
,
452 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSPOSSAMPLE
,
457 /* Get positive number format sample */
458 GetNumberFormatW(pGlobalData
->UserLCID
,
465 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNEGSAMPLE
,
471 /* Set num decimal separator */
473 SetNumDecimalSep(HWND hwndDlg
,
474 PGLOBALDATA pGlobalData
)
476 /* Get setted decimal separator */
477 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERDSYMBOL
,
479 (WPARAM
)MAX_NUMDECIMALSEP
,
480 (LPARAM
)pGlobalData
->szNumDecimalSep
);
485 /* Set number of fractional symbols */
487 SetFracSymNum(HWND hwndDlg
,
488 PGLOBALDATA pGlobalData
)
492 /* Get setted number of fractional symbols */
493 nCurrSel
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNDIGDEC
,
497 if (nCurrSel
== CB_ERR
)
500 pGlobalData
->nNumDigits
= nCurrSel
;
505 /* Set field separator */
507 SetNumFieldSep(HWND hwndDlg
,
508 PGLOBALDATA pGlobalData
)
510 /* Get thousand separator */
511 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDIGITGRSYM
,
513 (WPARAM
)MAX_NUMTHOUSANDSEP
,
514 (LPARAM
)pGlobalData
->szNumThousandSep
);
519 /* Set number of digits in field */
521 SetFieldDigNum(HWND hwndDlg
,
522 PGLOBALDATA pGlobalData
)
526 /* Get setted negative sum format */
527 nCurrSel
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDGROUPING
,
531 if (nCurrSel
== CB_ERR
)
534 pGlobalData
->nNumGrouping
= nCurrSel
;
539 /* Set negative sign */
541 SetNumNegSign(HWND hwndDlg
,
542 PGLOBALDATA pGlobalData
)
544 /* Get setted negative sign */
545 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNSIGNSYM
,
547 (WPARAM
)MAX_NUMNEGATIVESIGN
,
548 (LPARAM
)pGlobalData
->szNumNegativeSign
);
553 /* Set negative sum format */
555 SetNegSumFmt(HWND hwndDlg
,
556 PGLOBALDATA pGlobalData
)
560 /* Get setted negative sum format */
561 nCurrSel
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSNNUMFORMAT
,
565 if (nCurrSel
== CB_ERR
)
568 pGlobalData
->nNumNegFormat
= nCurrSel
;
573 /* Set leading zero */
575 SetNumLeadZero(HWND hwndDlg
,
576 PGLOBALDATA pGlobalData
)
580 /* Get setted leading zero format */
581 nCurrSel
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSDISPLEADZER
,
585 if (nCurrSel
== CB_ERR
)
588 pGlobalData
->nNumLeadingZero
= nCurrSel
;
593 /* Set elements list separator */
595 SetNumListSep(HWND hwndDlg
,
596 PGLOBALDATA pGlobalData
)
598 /* Get setted list separator */
599 SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSLSEP
,
601 (WPARAM
)MAX_NUMLISTSEP
,
602 (LPARAM
)pGlobalData
->szNumListSep
);
607 /* Set units system */
609 SetNumUnitsSys(HWND hwndDlg
,
610 PGLOBALDATA pGlobalData
)
614 /* Get setted units system */
615 nCurrSel
= SendDlgItemMessageW(hwndDlg
, IDC_NUMBERSMEASSYS
,
619 if (nCurrSel
== CB_ERR
)
622 pGlobalData
->nNumMeasure
= nCurrSel
;
627 /* Property page dialog callback */
629 NumbersPageProc(HWND hwndDlg
,
634 PGLOBALDATA pGlobalData
;
636 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
641 pGlobalData
= (PGLOBALDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
642 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
644 InitNumDecimalSepCB(hwndDlg
, pGlobalData
);
645 InitNumOfFracSymbCB(hwndDlg
, pGlobalData
);
646 InitNumFieldSepCB(hwndDlg
, pGlobalData
);
647 InitFieldDigNumCB(hwndDlg
, pGlobalData
);
648 InitNegSignCB(hwndDlg
, pGlobalData
);
649 InitNegNumFmtCB(hwndDlg
, pGlobalData
);
650 InitLeadingZeroesCB(hwndDlg
, pGlobalData
);
651 InitListSepCB(hwndDlg
, pGlobalData
);
652 InitUnitsSysCB(hwndDlg
, pGlobalData
);
653 UpdateNumSamples(hwndDlg
, pGlobalData
);
657 switch (LOWORD(wParam
))
659 case IDC_NUMBERDSYMBOL
:
660 case IDC_NUMBERSNDIGDEC
:
661 case IDC_NUMBERSDIGITGRSYM
:
662 case IDC_NUMBERSDGROUPING
:
663 case IDC_NUMBERSNSIGNSYM
:
664 case IDC_NUMBERSNNUMFORMAT
:
665 case IDC_NUMBERSDISPLEADZER
:
666 case IDC_NUMBERSLSEP
:
667 case IDC_NUMBERSMEASSYS
:
668 if (HIWORD(wParam
) == CBN_SELCHANGE
|| HIWORD(wParam
) == CBN_EDITCHANGE
)
670 /* Set "Apply" button enabled */
671 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
677 /* If push apply button */
678 if (((LPNMHDR
)lParam
)->code
== (UINT
)PSN_APPLY
)
680 if (!SetNumDecimalSep(hwndDlg
, pGlobalData
))
683 if (!SetFracSymNum(hwndDlg
, pGlobalData
))
686 if (!SetNumFieldSep(hwndDlg
, pGlobalData
))
689 if (!SetFieldDigNum(hwndDlg
, pGlobalData
))
692 if (!SetNumNegSign(hwndDlg
, pGlobalData
))
695 if (!SetNegSumFmt(hwndDlg
, pGlobalData
))
698 if (!SetNumLeadZero(hwndDlg
, pGlobalData
))
701 if (!SetNumListSep(hwndDlg
, pGlobalData
))
704 if (!SetNumUnitsSys(hwndDlg
, pGlobalData
))
707 pGlobalData
->bUserLocaleChanged
= TRUE
;
709 UpdateNumSamples(hwndDlg
, pGlobalData
);