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: lib/cpl/intl/numbers.c
23 * PURPOSE: Numbers property page
24 * PROGRAMMER: Eric Kohl
35 #define SAMPLE_NUMBER _T("123456789")
36 #define SAMPLE_NEG_NUMBER _T("-123456789")
37 #define MAX_NUM_SEP_SAMPLES 2
38 #define MAX_FRAC_NUM_SAMPLES 10
39 #define MAX_FIELD_SEP_SAMPLES 1
40 #define MAX_FIELD_DIG_SAMPLES 3
41 #define MAX_NEG_SIGN_SAMPLES 1
42 #define MAX_NEG_NUMBERS_SAMPLES 5
43 #define MAX_LEAD_ZEROES_SAMPLES 2
44 #define MAX_LIST_SEP_SAMPLES 1
45 #define MAX_UNITS_SYS_SAMPLES 2
47 static LPTSTR lpNumSepSamples
[MAX_NUM_SEP_SAMPLES
] =
49 static LPTSTR lpFieldSepSamples
[MAX_FIELD_SEP_SAMPLES
] =
51 static LPTSTR lpFieldDigNumSamples
[MAX_FIELD_DIG_SAMPLES
] =
52 {_T("0;0"), _T("3;0"), _T("3;2;0")};
53 static LPTSTR lpNegSignSamples
[MAX_NEG_SIGN_SAMPLES
] =
55 static LPTSTR lpNegNumFmtSamples
[MAX_NEG_NUMBERS_SAMPLES
] =
56 {_T("(1,1)"), _T("-1,1"), _T("- 1,1"), _T("1,1-"), _T("1,1 -")};
57 static LPTSTR lpLeadNumFmtSamples
[MAX_LEAD_ZEROES_SAMPLES
] =
58 {_T(",7"), _T("0,7")};
59 static LPTSTR lpListSepSamples
[MAX_LIST_SEP_SAMPLES
] =
61 static LPTSTR lpUnitsSysSamples
[MAX_UNITS_SYS_SAMPLES
] =
62 {_T("Metric"), _T("Imperial")};
65 /* Init num decimal separator control box */
67 InitNumDecimalSepCB(HWND hwndDlg
, LCID lcid
)
69 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
73 /* Limit text length */
74 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
79 /* Get current decimal separator */
83 MAX_SAMPLES_STR_SIZE
);
85 /* Clear all box content */
86 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
91 /* Create standard list of decimal separators */
92 for (nCBIndex
= 0; nCBIndex
< MAX_NUM_SEP_SAMPLES
; nCBIndex
++)
94 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
97 (LPARAM
)lpNumSepSamples
[nCBIndex
]);
100 /* Set current item to value from registry */
101 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
104 (LPARAM
)(LPCSTR
)szNumSep
);
106 /* if is not success, add new value to list and select them */
107 if (nRetCode
== CB_ERR
)
109 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
113 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
120 /* Init number of fractional symbols control box */
122 InitNumOfFracSymbCB(HWND hwndDlg
, LCID lcid
)
124 TCHAR szFracNum
[MAX_SAMPLES_STR_SIZE
];
125 TCHAR szFracCount
[MAX_SAMPLES_STR_SIZE
];
129 /* Get current number of fractional symbols */
133 MAX_SAMPLES_STR_SIZE
);
135 /* Clear all box content */
136 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
141 /* Create standard list of fractional symbols */
142 for (nCBIndex
= 0; nCBIndex
< MAX_FRAC_NUM_SAMPLES
; nCBIndex
++)
144 /* convert to wide char */
145 _itot(nCBIndex
, szFracCount
, DECIMAL_RADIX
);
147 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
150 (LPARAM
)szFracCount
);
153 /* Set current item to value from registry */
154 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
156 (WPARAM
)_ttoi(szFracNum
),
160 /* Init field separator control box */
162 InitNumFieldSepCB(HWND hwndDlg
, LCID lcid
)
164 TCHAR szFieldSep
[MAX_SAMPLES_STR_SIZE
];
168 /* Limit text length */
169 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
171 MAX_NUMBERSDIGITGRSYM
,
174 /* Get current field separator */
178 MAX_SAMPLES_STR_SIZE
);
180 /* Clear all box content */
181 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
186 /* Create standard list of field separators */
187 for (nCBIndex
= 0; nCBIndex
< MAX_FIELD_SEP_SAMPLES
; nCBIndex
++)
189 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
192 (LPARAM
)lpFieldSepSamples
[nCBIndex
]);
195 /* Set current item to value from registry */
196 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
201 /* if is not success, add new value to list and select them */
202 if (nRetCode
== CB_ERR
)
204 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
208 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
215 /* Init number of digits in field control box */
217 InitFieldDigNumCB(HWND hwndDlg
, LCID lcid
)
219 TCHAR szFieldDigNum
[MAX_SAMPLES_STR_SIZE
];
220 LPTSTR pszFieldDigNumSmpl
;
224 /* Get current field digits num */
228 MAX_SAMPLES_STR_SIZE
);
230 /* Clear all box content */
231 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
236 /* Create standard list of field digits num */
237 for (nCBIndex
= 0; nCBIndex
< MAX_FIELD_DIG_SAMPLES
; nCBIndex
++)
240 pszFieldDigNumSmpl
= InsSpacesFmt(SAMPLE_NUMBER
, lpFieldDigNumSamples
[nCBIndex
]);
241 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
244 (LPARAM
)pszFieldDigNumSmpl
);
245 free(pszFieldDigNumSmpl
);
248 pszFieldDigNumSmpl
= InsSpacesFmt(SAMPLE_NUMBER
, szFieldDigNum
);
249 /* Set current item to value from registry */
250 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
253 (LPARAM
)pszFieldDigNumSmpl
);
255 /* if is not success, add new value to list and select them */
256 if (nRetCode
== CB_ERR
)
258 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
261 (LPARAM
)pszFieldDigNumSmpl
);
262 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
265 (LPARAM
)pszFieldDigNumSmpl
);
268 free(pszFieldDigNumSmpl
);
271 /* Init negative sign control box */
273 InitNegSignCB(HWND hwndDlg
, LCID lcid
)
275 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
279 /* Limit text length */
280 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
285 /* Get current negative sign */
287 LOCALE_SNEGATIVESIGN
,
289 MAX_SAMPLES_STR_SIZE
);
291 /* Clear all box content */
292 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
297 /* Create standard list of signs */
298 for (nCBIndex
= 0; nCBIndex
< MAX_NEG_SIGN_SAMPLES
; nCBIndex
++)
300 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
303 (LPARAM
)lpNegSignSamples
[nCBIndex
]);
306 /* Set current item to value from registry */
307 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
312 /* if is not success, add new value to list and select them */
313 if (nRetCode
== CB_ERR
)
315 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
319 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
326 /* Init negative numbers format control box */
328 InitNegNumFmtCB(HWND hwndDlg
, LCID lcid
)
330 TCHAR szNegNumFmt
[MAX_SAMPLES_STR_SIZE
];
331 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
332 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
333 TCHAR szNewSample
[MAX_SAMPLES_STR_SIZE
];
338 /* Get current negative numbers format */
342 MAX_SAMPLES_STR_SIZE
);
344 /* Clear all box content */
345 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
350 /* Get current decimal separator */
354 MAX_SAMPLES_STR_SIZE
);
356 /* Get current negative sign */
358 LOCALE_SNEGATIVESIGN
,
360 MAX_SAMPLES_STR_SIZE
);
362 /* Create standard list of negative numbers formats */
363 for (nCBIndex
= 0; nCBIndex
< MAX_NEG_NUMBERS_SAMPLES
; nCBIndex
++)
365 /* Replace standard separator to setted */
366 pszResultStr
= ReplaceSubStr(lpNegNumFmtSamples
[nCBIndex
],
369 _tcscpy(szNewSample
, pszResultStr
);
371 /* Replace standard negative sign to setted */
372 pszResultStr
= ReplaceSubStr(szNewSample
,
375 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
378 (LPARAM
)pszResultStr
);
382 /* Set current item to value from registry */
383 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
385 (WPARAM
)_ttoi(szNegNumFmt
),
389 /* Init leading zeroes control box */
391 InitLeadingZeroesCB(HWND hwndDlg
, LCID lcid
)
393 TCHAR szLeadNumFmt
[MAX_SAMPLES_STR_SIZE
];
394 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
399 /* Get current leading zeroes format */
403 MAX_SAMPLES_STR_SIZE
);
405 /* Clear all box content */
406 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
411 /* Get current decimal separator */
415 MAX_SAMPLES_STR_SIZE
);
417 /* Create list of standard leading zeroes formats */
418 for (nCBIndex
= 0; nCBIndex
< MAX_LEAD_ZEROES_SAMPLES
; nCBIndex
++)
420 pszResultStr
= ReplaceSubStr(lpLeadNumFmtSamples
[nCBIndex
],
423 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
426 (LPARAM
)pszResultStr
);
430 /* Set current item to value from registry */
431 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
433 (WPARAM
)_ttoi(szLeadNumFmt
),
438 InitListSepCB(HWND hwndDlg
,
441 TCHAR szListSep
[MAX_SAMPLES_STR_SIZE
];
445 /* Limit text length */
446 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
451 /* Get current list separator */
455 MAX_SAMPLES_STR_SIZE
);
457 /* Clear all box content */
458 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
463 /* Create standard list of signs */
464 for (nCBIndex
= 0; nCBIndex
< MAX_LIST_SEP_SAMPLES
; nCBIndex
++)
466 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
469 (LPARAM
)lpListSepSamples
[nCBIndex
]);
472 /* Set current item to value from registry */
473 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
478 /* if is not success, add new value to list and select them */
479 if (nRetCode
== CB_ERR
)
481 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
485 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
492 /* Init system of units control box */
494 InitUnitsSysCB(HWND hwndDlg
,
497 TCHAR szUnitsSys
[MAX_SAMPLES_STR_SIZE
];
500 /* Get current system of units */
504 MAX_SAMPLES_STR_SIZE
);
506 /* Clear all box content */
507 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
512 /* Create list of standard system of units */
513 for (nCBIndex
= 0; nCBIndex
< MAX_UNITS_SYS_SAMPLES
; nCBIndex
++)
515 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
518 (LPARAM
)lpUnitsSysSamples
[nCBIndex
]);
521 /* Set current item to value from registry */
522 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
524 (WPARAM
)_ttoi(szUnitsSys
),
528 /* Update all numbers locale samples */
530 UpdateNumSamples(HWND hwndDlg
,
533 TCHAR OutBuffer
[MAX_FMT_SIZE
];
535 /* Get positive number format sample */
536 GetNumberFormat(lcid
,
543 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSPOSSAMPLE
),
548 /* Get positive number format sample */
549 GetNumberFormat(lcid
,
556 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNEGSAMPLE
),
562 /* Set num decimal separator */
564 SetNumDecimalSep(HWND hwndDlg
,
567 TCHAR szDecimalSep
[MAX_SAMPLES_STR_SIZE
];
569 /* Get setted decimal separator */
570 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
572 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
573 (LPARAM
)szDecimalSep
);
575 /* Save decimal separator */
576 SetLocaleInfo(lcid
, LOCALE_SDECIMAL
, szDecimalSep
);
581 /* Set number of fractional symbols */
583 SetFracSymNum(HWND hwndDlg
,
586 TCHAR szFracSymNum
[MAX_SAMPLES_STR_SIZE
];
589 /* Get setted number of fractional symbols */
590 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
595 /* convert to wide char */
596 _itot(nCurrSel
, szFracSymNum
, DECIMAL_RADIX
);
598 /* Save number of fractional symbols */
599 SetLocaleInfo(lcid
, LOCALE_IDIGITS
, szFracSymNum
);
604 /* Set field separator */
606 SetNumFieldSep(HWND hwndDlg
,
609 TCHAR szFieldSep
[MAX_SAMPLES_STR_SIZE
];
611 /* Get setted field separator */
612 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
614 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
617 /* Save field separator */
618 SetLocaleInfo(lcid
, LOCALE_STHOUSAND
, szFieldSep
);
623 /* Set number of digits in field */
625 SetFieldDigNum(HWND hwndDlg
,
628 TCHAR szFieldDigNum
[MAX_SAMPLES_STR_SIZE
];
630 /* Get setted number of digidts in field */
631 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
633 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
634 (LPARAM
)szFieldDigNum
);
636 /* Save number of digits in field */
637 SetLocaleInfo(lcid
, LOCALE_SGROUPING
, szFieldDigNum
);
642 /* Set negative sign */
644 SetNumNegSign(HWND hwndDlg
,
647 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
649 /* Get setted negative sign */
650 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
652 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
655 /* Save negative sign */
656 SetLocaleInfo(lcid
, LOCALE_SNEGATIVESIGN
, szNegSign
);
661 /* Set negative sum format */
663 SetNegSumFmt(HWND hwndDlg
,
666 TCHAR szNegSumFmt
[MAX_SAMPLES_STR_SIZE
];
669 /* Get setted negative sum format */
670 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
675 /* convert to wide char */
676 _itot(nCurrSel
, szNegSumFmt
,DECIMAL_RADIX
);
678 /* Save negative sum format */
679 SetLocaleInfo(lcid
, LOCALE_INEGNUMBER
, szNegSumFmt
);
684 /* Set leading zero */
686 SetNumLeadZero(HWND hwndDlg
,
689 TCHAR szLeadZero
[MAX_SAMPLES_STR_SIZE
];
692 /* Get setted leading zero format */
693 nCurrSel
= SendMessageW(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
698 /* convert to wide char */
699 _itot(nCurrSel
, szLeadZero
, DECIMAL_RADIX
);
701 /* Save leading zero format */
702 SetLocaleInfo(lcid
, LOCALE_ILZERO
, szLeadZero
);
707 /* Set elements list separator */
709 SetNumListSep(HWND hwndDlg
,
712 TCHAR szListSep
[MAX_SAMPLES_STR_SIZE
];
714 /* Get setted list separator */
715 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
717 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
720 /* Save list separator */
721 SetLocaleInfo(lcid
, LOCALE_SLIST
, szListSep
);
726 /* Set units system */
728 SetNumUnitsSys(HWND hwndDlg
,
731 TCHAR szUnitsSys
[MAX_SAMPLES_STR_SIZE
];
734 /* Get setted units system */
735 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
740 /* convert to wide char */
741 _itot(nCurrSel
, szUnitsSys
, DECIMAL_RADIX
);
743 /* Save units system */
744 SetLocaleInfo(lcid
, LOCALE_IMEASURE
, szUnitsSys
);
749 /* Property page dialog callback */
751 NumbersPageProc(HWND hwndDlg
,
756 PGLOBALDATA pGlobalData
;
758 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
763 pGlobalData
= (PGLOBALDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
764 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
766 InitNumDecimalSepCB(hwndDlg
, pGlobalData
->lcid
);
767 InitNumOfFracSymbCB(hwndDlg
, pGlobalData
->lcid
);
768 InitNumFieldSepCB(hwndDlg
, pGlobalData
->lcid
);
769 InitFieldDigNumCB(hwndDlg
, pGlobalData
->lcid
);
770 InitNegSignCB(hwndDlg
, pGlobalData
->lcid
);
771 InitNegNumFmtCB(hwndDlg
, pGlobalData
->lcid
);
772 InitLeadingZeroesCB(hwndDlg
, pGlobalData
->lcid
);
773 InitListSepCB(hwndDlg
, pGlobalData
->lcid
);
774 InitUnitsSysCB(hwndDlg
, pGlobalData
->lcid
);
775 UpdateNumSamples(hwndDlg
, pGlobalData
->lcid
);
779 switch (LOWORD(wParam
))
781 case IDC_NUMBERDSYMBOL
:
782 case IDC_NUMBERSNDIGDEC
:
783 case IDC_NUMBERSDIGITGRSYM
:
784 case IDC_NUMBERSDGROUPING
:
785 case IDC_NUMBERSNSIGNSYM
:
786 case IDC_NUMBERSNNUMFORMAT
:
787 case IDC_NUMBERSDISPLEADZER
:
788 case IDC_NUMBERSLSEP
:
789 case IDC_NUMBERSMEASSYS
:
790 if (HIWORD(wParam
) == CBN_SELCHANGE
|| HIWORD(wParam
) == CBN_EDITCHANGE
)
792 /* Set "Apply" button enabled */
793 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
799 /* If push apply button */
800 if (((LPNMHDR
)lParam
)->code
== (UINT
)PSN_APPLY
)
802 if (!SetNumDecimalSep(hwndDlg
, pGlobalData
->lcid
))
805 if (!SetFracSymNum(hwndDlg
, pGlobalData
->lcid
))
808 if (!SetNumFieldSep(hwndDlg
, pGlobalData
->lcid
))
811 if (!SetFieldDigNum(hwndDlg
, pGlobalData
->lcid
))
814 if (!SetNumNegSign(hwndDlg
, pGlobalData
->lcid
))
817 if (!SetNegSumFmt(hwndDlg
, pGlobalData
->lcid
))
820 if (!SetNumLeadZero(hwndDlg
, pGlobalData
->lcid
))
823 if (!SetNumListSep(hwndDlg
, pGlobalData
->lcid
))
826 if (!SetNumUnitsSys(hwndDlg
, pGlobalData
->lcid
))
829 UpdateNumSamples(hwndDlg
, pGlobalData
->lcid
);