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
29 #define SAMPLE_NUMBER _T("123456789")
30 #define SAMPLE_NEG_NUMBER _T("-123456789")
31 #define MAX_NUM_SEP_SAMPLES 2
32 #define MAX_FRAC_NUM_SAMPLES 10
33 #define MAX_FIELD_SEP_SAMPLES 1
34 #define MAX_FIELD_DIG_SAMPLES 3
35 #define MAX_NEG_SIGN_SAMPLES 1
36 #define MAX_NEG_NUMBERS_SAMPLES 5
37 #define MAX_LEAD_ZEROES_SAMPLES 2
38 #define MAX_LIST_SEP_SAMPLES 1
39 #define MAX_UNITS_SYS_SAMPLES 2
41 static LPTSTR lpNumSepSamples
[MAX_NUM_SEP_SAMPLES
] =
43 static LPTSTR lpFieldSepSamples
[MAX_FIELD_SEP_SAMPLES
] =
45 static LPTSTR lpFieldDigNumSamples
[MAX_FIELD_DIG_SAMPLES
] =
46 {_T("0;0"), _T("3;0"), _T("3;2;0")};
47 static LPTSTR lpNegSignSamples
[MAX_NEG_SIGN_SAMPLES
] =
49 static LPTSTR lpNegNumFmtSamples
[MAX_NEG_NUMBERS_SAMPLES
] =
50 {_T("(1,1)"), _T("-1,1"), _T("- 1,1"), _T("1,1-"), _T("1,1 -")};
51 static LPTSTR lpLeadNumFmtSamples
[MAX_LEAD_ZEROES_SAMPLES
] =
52 {_T(",7"), _T("0,7")};
53 static LPTSTR lpListSepSamples
[MAX_LIST_SEP_SAMPLES
] =
57 /* Init num decimal separator control box */
59 InitNumDecimalSepCB(HWND hwndDlg
, LCID lcid
)
61 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
65 /* Limit text length */
66 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
71 /* Get current decimal separator */
75 MAX_SAMPLES_STR_SIZE
);
77 /* Clear all box content */
78 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
83 /* Create standard list of decimal separators */
84 for (nCBIndex
= 0; nCBIndex
< MAX_NUM_SEP_SAMPLES
; nCBIndex
++)
86 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
89 (LPARAM
)lpNumSepSamples
[nCBIndex
]);
92 /* Set current item to value from registry */
93 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
96 (LPARAM
)(LPCSTR
)szNumSep
);
98 /* if is not success, add new value to list and select them */
99 if (nRetCode
== CB_ERR
)
101 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
105 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
112 /* Init number of fractional symbols control box */
114 InitNumOfFracSymbCB(HWND hwndDlg
, LCID lcid
)
116 TCHAR szFracNum
[MAX_SAMPLES_STR_SIZE
];
117 TCHAR szFracCount
[MAX_SAMPLES_STR_SIZE
];
121 /* Get current number of fractional symbols */
125 MAX_SAMPLES_STR_SIZE
);
127 /* Clear all box content */
128 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
133 /* Create standard list of fractional symbols */
134 for (nCBIndex
= 0; nCBIndex
< MAX_FRAC_NUM_SAMPLES
; nCBIndex
++)
136 /* convert to wide char */
137 _itot(nCBIndex
, szFracCount
, DECIMAL_RADIX
);
139 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
142 (LPARAM
)szFracCount
);
145 /* Set current item to value from registry */
146 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
148 (WPARAM
)_ttoi(szFracNum
),
152 /* Init field separator control box */
154 InitNumFieldSepCB(HWND hwndDlg
, LCID lcid
)
156 TCHAR szFieldSep
[MAX_SAMPLES_STR_SIZE
];
160 /* Limit text length */
161 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
163 MAX_NUMBERSDIGITGRSYM
,
166 /* Get current field separator */
170 MAX_SAMPLES_STR_SIZE
);
172 /* Clear all box content */
173 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
178 /* Create standard list of field separators */
179 for (nCBIndex
= 0; nCBIndex
< MAX_FIELD_SEP_SAMPLES
; nCBIndex
++)
181 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
184 (LPARAM
)lpFieldSepSamples
[nCBIndex
]);
187 /* Set current item to value from registry */
188 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
193 /* if is not success, add new value to list and select them */
194 if (nRetCode
== CB_ERR
)
196 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
200 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
207 /* Init number of digits in field control box */
209 InitFieldDigNumCB(HWND hwndDlg
, LCID lcid
)
211 TCHAR szFieldDigNum
[MAX_SAMPLES_STR_SIZE
];
212 LPTSTR pszFieldDigNumSmpl
;
216 /* Get current field digits num */
220 MAX_SAMPLES_STR_SIZE
);
222 /* Clear all box content */
223 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
228 /* Create standard list of field digits num */
229 for (nCBIndex
= 0; nCBIndex
< MAX_FIELD_DIG_SAMPLES
; nCBIndex
++)
232 pszFieldDigNumSmpl
= InsSpacesFmt(SAMPLE_NUMBER
, lpFieldDigNumSamples
[nCBIndex
]);
233 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
236 (LPARAM
)pszFieldDigNumSmpl
);
237 free(pszFieldDigNumSmpl
);
240 pszFieldDigNumSmpl
= InsSpacesFmt(SAMPLE_NUMBER
, szFieldDigNum
);
241 /* Set current item to value from registry */
242 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
245 (LPARAM
)pszFieldDigNumSmpl
);
247 /* if is not success, add new value to list and select them */
248 if (nRetCode
== CB_ERR
)
250 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
253 (LPARAM
)pszFieldDigNumSmpl
);
254 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
257 (LPARAM
)pszFieldDigNumSmpl
);
260 free(pszFieldDigNumSmpl
);
263 /* Init negative sign control box */
265 InitNegSignCB(HWND hwndDlg
, LCID lcid
)
267 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
271 /* Limit text length */
272 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
277 /* Get current negative sign */
279 LOCALE_SNEGATIVESIGN
,
281 MAX_SAMPLES_STR_SIZE
);
283 /* Clear all box content */
284 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
289 /* Create standard list of signs */
290 for (nCBIndex
= 0; nCBIndex
< MAX_NEG_SIGN_SAMPLES
; nCBIndex
++)
292 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
295 (LPARAM
)lpNegSignSamples
[nCBIndex
]);
298 /* Set current item to value from registry */
299 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
304 /* if is not success, add new value to list and select them */
305 if (nRetCode
== CB_ERR
)
307 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
311 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
318 /* Init negative numbers format control box */
320 InitNegNumFmtCB(HWND hwndDlg
, LCID lcid
)
322 TCHAR szNegNumFmt
[MAX_SAMPLES_STR_SIZE
];
323 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
324 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
325 TCHAR szNewSample
[MAX_SAMPLES_STR_SIZE
];
330 /* Get current negative numbers format */
334 MAX_SAMPLES_STR_SIZE
);
336 /* Clear all box content */
337 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
342 /* Get current decimal separator */
346 MAX_SAMPLES_STR_SIZE
);
348 /* Get current negative sign */
350 LOCALE_SNEGATIVESIGN
,
352 MAX_SAMPLES_STR_SIZE
);
354 /* Create standard list of negative numbers formats */
355 for (nCBIndex
= 0; nCBIndex
< MAX_NEG_NUMBERS_SAMPLES
; nCBIndex
++)
357 /* Replace standard separator to setted */
358 pszResultStr
= ReplaceSubStr(lpNegNumFmtSamples
[nCBIndex
],
361 _tcscpy(szNewSample
, pszResultStr
);
363 /* Replace standard negative sign to setted */
364 pszResultStr
= ReplaceSubStr(szNewSample
,
367 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
370 (LPARAM
)pszResultStr
);
374 /* Set current item to value from registry */
375 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
377 (WPARAM
)_ttoi(szNegNumFmt
),
381 /* Init leading zeroes control box */
383 InitLeadingZeroesCB(HWND hwndDlg
, LCID lcid
)
385 TCHAR szLeadNumFmt
[MAX_SAMPLES_STR_SIZE
];
386 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
391 /* Get current leading zeroes format */
395 MAX_SAMPLES_STR_SIZE
);
397 /* Clear all box content */
398 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
403 /* Get current decimal separator */
407 MAX_SAMPLES_STR_SIZE
);
409 /* Create list of standard leading zeroes formats */
410 for (nCBIndex
= 0; nCBIndex
< MAX_LEAD_ZEROES_SAMPLES
; nCBIndex
++)
412 pszResultStr
= ReplaceSubStr(lpLeadNumFmtSamples
[nCBIndex
],
415 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
418 (LPARAM
)pszResultStr
);
422 /* Set current item to value from registry */
423 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
425 (WPARAM
)_ttoi(szLeadNumFmt
),
430 InitListSepCB(HWND hwndDlg
,
433 TCHAR szListSep
[MAX_SAMPLES_STR_SIZE
];
437 /* Limit text length */
438 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
443 /* Get current list separator */
447 MAX_SAMPLES_STR_SIZE
);
449 /* Clear all box content */
450 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
455 /* Create standard list of signs */
456 for (nCBIndex
= 0; nCBIndex
< MAX_LIST_SEP_SAMPLES
; nCBIndex
++)
458 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
461 (LPARAM
)lpListSepSamples
[nCBIndex
]);
464 /* Set current item to value from registry */
465 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
470 /* if is not success, add new value to list and select them */
471 if (nRetCode
== CB_ERR
)
473 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
477 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
484 /* Init system of units control box */
486 InitUnitsSysCB(HWND hwndDlg
,
489 TCHAR szUnitsSys
[MAX_SAMPLES_STR_SIZE
];
490 TCHAR szUnitName
[128];
493 /* Get current system of units */
497 MAX_SAMPLES_STR_SIZE
);
499 /* Clear all box content */
500 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
505 /* Create list of standard system of units */
506 for (nCBIndex
= 0; nCBIndex
< MAX_UNITS_SYS_SAMPLES
; nCBIndex
++)
508 LoadString(hApplet
, IDS_METRIC
+ nCBIndex
, szUnitName
, 128);
510 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
516 /* Set current item to value from registry */
517 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
519 (WPARAM
)_ttoi(szUnitsSys
),
523 /* Update all numbers locale samples */
525 UpdateNumSamples(HWND hwndDlg
,
528 TCHAR OutBuffer
[MAX_FMT_SIZE
];
530 /* Get positive number format sample */
531 GetNumberFormat(lcid
,
538 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSPOSSAMPLE
),
543 /* Get positive number format sample */
544 GetNumberFormat(lcid
,
551 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNEGSAMPLE
),
557 /* Set num decimal separator */
559 SetNumDecimalSep(HWND hwndDlg
,
562 TCHAR szDecimalSep
[MAX_SAMPLES_STR_SIZE
];
564 /* Get setted decimal separator */
565 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
567 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
568 (LPARAM
)szDecimalSep
);
570 /* Save decimal separator */
571 SetLocaleInfo(lcid
, LOCALE_SDECIMAL
, szDecimalSep
);
576 /* Set number of fractional symbols */
578 SetFracSymNum(HWND hwndDlg
,
581 TCHAR szFracSymNum
[MAX_SAMPLES_STR_SIZE
];
584 /* Get setted number of fractional symbols */
585 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
590 /* convert to wide char */
591 _itot(nCurrSel
, szFracSymNum
, DECIMAL_RADIX
);
593 /* Save number of fractional symbols */
594 SetLocaleInfo(lcid
, LOCALE_IDIGITS
, szFracSymNum
);
599 /* Set field separator */
601 SetNumFieldSep(HWND hwndDlg
,
604 TCHAR szFieldSep
[MAX_SAMPLES_STR_SIZE
];
606 /* Get setted field separator */
607 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
609 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
612 /* Save field separator */
613 SetLocaleInfo(lcid
, LOCALE_STHOUSAND
, szFieldSep
);
618 /* Set number of digits in field */
620 SetFieldDigNum(HWND hwndDlg
,
623 TCHAR szFieldDigNum
[MAX_SAMPLES_STR_SIZE
];
625 /* Get setted number of digidts in field */
626 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
628 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
629 (LPARAM
)szFieldDigNum
);
631 /* Save number of digits in field */
632 SetLocaleInfo(lcid
, LOCALE_SGROUPING
, szFieldDigNum
);
637 /* Set negative sign */
639 SetNumNegSign(HWND hwndDlg
,
642 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
644 /* Get setted negative sign */
645 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
647 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
650 /* Save negative sign */
651 SetLocaleInfo(lcid
, LOCALE_SNEGATIVESIGN
, szNegSign
);
656 /* Set negative sum format */
658 SetNegSumFmt(HWND hwndDlg
,
661 TCHAR szNegSumFmt
[MAX_SAMPLES_STR_SIZE
];
664 /* Get setted negative sum format */
665 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
670 /* convert to wide char */
671 _itot(nCurrSel
, szNegSumFmt
,DECIMAL_RADIX
);
673 /* Save negative sum format */
674 SetLocaleInfo(lcid
, LOCALE_INEGNUMBER
, szNegSumFmt
);
679 /* Set leading zero */
681 SetNumLeadZero(HWND hwndDlg
,
684 TCHAR szLeadZero
[MAX_SAMPLES_STR_SIZE
];
687 /* Get setted leading zero format */
688 nCurrSel
= SendMessageW(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
693 /* convert to wide char */
694 _itot(nCurrSel
, szLeadZero
, DECIMAL_RADIX
);
696 /* Save leading zero format */
697 SetLocaleInfo(lcid
, LOCALE_ILZERO
, szLeadZero
);
702 /* Set elements list separator */
704 SetNumListSep(HWND hwndDlg
,
707 TCHAR szListSep
[MAX_SAMPLES_STR_SIZE
];
709 /* Get setted list separator */
710 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
712 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
715 /* Save list separator */
716 SetLocaleInfo(lcid
, LOCALE_SLIST
, szListSep
);
721 /* Set units system */
723 SetNumUnitsSys(HWND hwndDlg
,
726 TCHAR szUnitsSys
[MAX_SAMPLES_STR_SIZE
];
729 /* Get setted units system */
730 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
735 /* convert to wide char */
736 _itot(nCurrSel
, szUnitsSys
, DECIMAL_RADIX
);
738 /* Save units system */
739 SetLocaleInfo(lcid
, LOCALE_IMEASURE
, szUnitsSys
);
744 /* Property page dialog callback */
746 NumbersPageProc(HWND hwndDlg
,
751 PGLOBALDATA pGlobalData
;
753 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
758 pGlobalData
= (PGLOBALDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
759 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
761 InitNumDecimalSepCB(hwndDlg
, pGlobalData
->lcid
);
762 InitNumOfFracSymbCB(hwndDlg
, pGlobalData
->lcid
);
763 InitNumFieldSepCB(hwndDlg
, pGlobalData
->lcid
);
764 InitFieldDigNumCB(hwndDlg
, pGlobalData
->lcid
);
765 InitNegSignCB(hwndDlg
, pGlobalData
->lcid
);
766 InitNegNumFmtCB(hwndDlg
, pGlobalData
->lcid
);
767 InitLeadingZeroesCB(hwndDlg
, pGlobalData
->lcid
);
768 InitListSepCB(hwndDlg
, pGlobalData
->lcid
);
769 InitUnitsSysCB(hwndDlg
, pGlobalData
->lcid
);
770 UpdateNumSamples(hwndDlg
, pGlobalData
->lcid
);
774 switch (LOWORD(wParam
))
776 case IDC_NUMBERDSYMBOL
:
777 case IDC_NUMBERSNDIGDEC
:
778 case IDC_NUMBERSDIGITGRSYM
:
779 case IDC_NUMBERSDGROUPING
:
780 case IDC_NUMBERSNSIGNSYM
:
781 case IDC_NUMBERSNNUMFORMAT
:
782 case IDC_NUMBERSDISPLEADZER
:
783 case IDC_NUMBERSLSEP
:
784 case IDC_NUMBERSMEASSYS
:
785 if (HIWORD(wParam
) == CBN_SELCHANGE
|| HIWORD(wParam
) == CBN_EDITCHANGE
)
787 /* Set "Apply" button enabled */
788 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
794 /* If push apply button */
795 if (((LPNMHDR
)lParam
)->code
== (UINT
)PSN_APPLY
)
797 if (!SetNumDecimalSep(hwndDlg
, pGlobalData
->lcid
))
800 if (!SetFracSymNum(hwndDlg
, pGlobalData
->lcid
))
803 if (!SetNumFieldSep(hwndDlg
, pGlobalData
->lcid
))
806 if (!SetFieldDigNum(hwndDlg
, pGlobalData
->lcid
))
809 if (!SetNumNegSign(hwndDlg
, pGlobalData
->lcid
))
812 if (!SetNegSumFmt(hwndDlg
, pGlobalData
->lcid
))
815 if (!SetNumLeadZero(hwndDlg
, pGlobalData
->lcid
))
818 if (!SetNumListSep(hwndDlg
, pGlobalData
->lcid
))
821 if (!SetNumUnitsSys(hwndDlg
, pGlobalData
->lcid
))
824 UpdateNumSamples(hwndDlg
, pGlobalData
->lcid
);