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
] =
63 /* Init num decimal separator control box */
65 InitNumDecimalSepCB(HWND hwndDlg
, LCID lcid
)
67 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
71 /* Limit text length */
72 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
77 /* Get current decimal separator */
81 MAX_SAMPLES_STR_SIZE
);
83 /* Clear all box content */
84 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
89 /* Create standard list of decimal separators */
90 for (nCBIndex
= 0; nCBIndex
< MAX_NUM_SEP_SAMPLES
; nCBIndex
++)
92 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
95 (LPARAM
)lpNumSepSamples
[nCBIndex
]);
98 /* Set current item to value from registry */
99 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
102 (LPARAM
)(LPCSTR
)szNumSep
);
104 /* if is not success, add new value to list and select them */
105 if (nRetCode
== CB_ERR
)
107 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
111 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
118 /* Init number of fractional symbols control box */
120 InitNumOfFracSymbCB(HWND hwndDlg
, LCID lcid
)
122 TCHAR szFracNum
[MAX_SAMPLES_STR_SIZE
];
123 TCHAR szFracCount
[MAX_SAMPLES_STR_SIZE
];
127 /* Get current number of fractional symbols */
131 MAX_SAMPLES_STR_SIZE
);
133 /* Clear all box content */
134 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
139 /* Create standard list of fractional symbols */
140 for (nCBIndex
= 0; nCBIndex
< MAX_FRAC_NUM_SAMPLES
; nCBIndex
++)
142 /* convert to wide char */
143 _itot(nCBIndex
, szFracCount
, DECIMAL_RADIX
);
145 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
148 (LPARAM
)szFracCount
);
151 /* Set current item to value from registry */
152 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
154 (WPARAM
)_ttoi(szFracNum
),
158 /* Init field separator control box */
160 InitNumFieldSepCB(HWND hwndDlg
, LCID lcid
)
162 TCHAR szFieldSep
[MAX_SAMPLES_STR_SIZE
];
166 /* Limit text length */
167 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
169 MAX_NUMBERSDIGITGRSYM
,
172 /* Get current field separator */
176 MAX_SAMPLES_STR_SIZE
);
178 /* Clear all box content */
179 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
184 /* Create standard list of field separators */
185 for (nCBIndex
= 0; nCBIndex
< MAX_FIELD_SEP_SAMPLES
; nCBIndex
++)
187 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
190 (LPARAM
)lpFieldSepSamples
[nCBIndex
]);
193 /* Set current item to value from registry */
194 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
199 /* if is not success, add new value to list and select them */
200 if (nRetCode
== CB_ERR
)
202 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
206 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
213 /* Init number of digits in field control box */
215 InitFieldDigNumCB(HWND hwndDlg
, LCID lcid
)
217 TCHAR szFieldDigNum
[MAX_SAMPLES_STR_SIZE
];
218 LPTSTR pszFieldDigNumSmpl
;
222 /* Get current field digits num */
226 MAX_SAMPLES_STR_SIZE
);
228 /* Clear all box content */
229 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
234 /* Create standard list of field digits num */
235 for (nCBIndex
= 0; nCBIndex
< MAX_FIELD_DIG_SAMPLES
; nCBIndex
++)
238 pszFieldDigNumSmpl
= InsSpacesFmt(SAMPLE_NUMBER
, lpFieldDigNumSamples
[nCBIndex
]);
239 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
242 (LPARAM
)pszFieldDigNumSmpl
);
243 free(pszFieldDigNumSmpl
);
246 pszFieldDigNumSmpl
= InsSpacesFmt(SAMPLE_NUMBER
, szFieldDigNum
);
247 /* Set current item to value from registry */
248 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
251 (LPARAM
)pszFieldDigNumSmpl
);
253 /* if is not success, add new value to list and select them */
254 if (nRetCode
== CB_ERR
)
256 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
259 (LPARAM
)pszFieldDigNumSmpl
);
260 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
263 (LPARAM
)pszFieldDigNumSmpl
);
266 free(pszFieldDigNumSmpl
);
269 /* Init negative sign control box */
271 InitNegSignCB(HWND hwndDlg
, LCID lcid
)
273 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
277 /* Limit text length */
278 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
283 /* Get current negative sign */
285 LOCALE_SNEGATIVESIGN
,
287 MAX_SAMPLES_STR_SIZE
);
289 /* Clear all box content */
290 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
295 /* Create standard list of signs */
296 for (nCBIndex
= 0; nCBIndex
< MAX_NEG_SIGN_SAMPLES
; nCBIndex
++)
298 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
301 (LPARAM
)lpNegSignSamples
[nCBIndex
]);
304 /* Set current item to value from registry */
305 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
310 /* if is not success, add new value to list and select them */
311 if (nRetCode
== CB_ERR
)
313 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
317 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
324 /* Init negative numbers format control box */
326 InitNegNumFmtCB(HWND hwndDlg
, LCID lcid
)
328 TCHAR szNegNumFmt
[MAX_SAMPLES_STR_SIZE
];
329 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
330 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
331 TCHAR szNewSample
[MAX_SAMPLES_STR_SIZE
];
336 /* Get current negative numbers format */
340 MAX_SAMPLES_STR_SIZE
);
342 /* Clear all box content */
343 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
348 /* Get current decimal separator */
352 MAX_SAMPLES_STR_SIZE
);
354 /* Get current negative sign */
356 LOCALE_SNEGATIVESIGN
,
358 MAX_SAMPLES_STR_SIZE
);
360 /* Create standard list of negative numbers formats */
361 for (nCBIndex
= 0; nCBIndex
< MAX_NEG_NUMBERS_SAMPLES
; nCBIndex
++)
363 /* Replace standard separator to setted */
364 pszResultStr
= ReplaceSubStr(lpNegNumFmtSamples
[nCBIndex
],
367 _tcscpy(szNewSample
, pszResultStr
);
369 /* Replace standard negative sign to setted */
370 pszResultStr
= ReplaceSubStr(szNewSample
,
373 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
376 (LPARAM
)pszResultStr
);
380 /* Set current item to value from registry */
381 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
383 (WPARAM
)_ttoi(szNegNumFmt
),
387 /* Init leading zeroes control box */
389 InitLeadingZeroesCB(HWND hwndDlg
, LCID lcid
)
391 TCHAR szLeadNumFmt
[MAX_SAMPLES_STR_SIZE
];
392 TCHAR szNumSep
[MAX_SAMPLES_STR_SIZE
];
397 /* Get current leading zeroes format */
401 MAX_SAMPLES_STR_SIZE
);
403 /* Clear all box content */
404 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
409 /* Get current decimal separator */
413 MAX_SAMPLES_STR_SIZE
);
415 /* Create list of standard leading zeroes formats */
416 for (nCBIndex
= 0; nCBIndex
< MAX_LEAD_ZEROES_SAMPLES
; nCBIndex
++)
418 pszResultStr
= ReplaceSubStr(lpLeadNumFmtSamples
[nCBIndex
],
421 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
424 (LPARAM
)pszResultStr
);
428 /* Set current item to value from registry */
429 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
431 (WPARAM
)_ttoi(szLeadNumFmt
),
436 InitListSepCB(HWND hwndDlg
,
439 TCHAR szListSep
[MAX_SAMPLES_STR_SIZE
];
443 /* Limit text length */
444 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
449 /* Get current list separator */
453 MAX_SAMPLES_STR_SIZE
);
455 /* Clear all box content */
456 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
461 /* Create standard list of signs */
462 for (nCBIndex
= 0; nCBIndex
< MAX_LIST_SEP_SAMPLES
; nCBIndex
++)
464 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
467 (LPARAM
)lpListSepSamples
[nCBIndex
]);
470 /* Set current item to value from registry */
471 nRetCode
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
476 /* if is not success, add new value to list and select them */
477 if (nRetCode
== CB_ERR
)
479 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
483 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
490 /* Init system of units control box */
492 InitUnitsSysCB(HWND hwndDlg
,
495 TCHAR szUnitsSys
[MAX_SAMPLES_STR_SIZE
];
496 TCHAR szUnitName
[128];
499 /* Get current system of units */
503 MAX_SAMPLES_STR_SIZE
);
505 /* Clear all box content */
506 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
511 /* Create list of standard system of units */
512 for (nCBIndex
= 0; nCBIndex
< MAX_UNITS_SYS_SAMPLES
; nCBIndex
++)
514 LoadString(hApplet
, IDS_METRIC
+ nCBIndex
, szUnitName
, 128);
516 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
522 /* Set current item to value from registry */
523 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
525 (WPARAM
)_ttoi(szUnitsSys
),
529 /* Update all numbers locale samples */
531 UpdateNumSamples(HWND hwndDlg
,
534 TCHAR OutBuffer
[MAX_FMT_SIZE
];
536 /* Get positive number format sample */
537 GetNumberFormat(lcid
,
544 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSPOSSAMPLE
),
549 /* Get positive number format sample */
550 GetNumberFormat(lcid
,
557 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNEGSAMPLE
),
563 /* Set num decimal separator */
565 SetNumDecimalSep(HWND hwndDlg
,
568 TCHAR szDecimalSep
[MAX_SAMPLES_STR_SIZE
];
570 /* Get setted decimal separator */
571 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERDSYMBOL
),
573 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
574 (LPARAM
)szDecimalSep
);
576 /* Save decimal separator */
577 SetLocaleInfo(lcid
, LOCALE_SDECIMAL
, szDecimalSep
);
582 /* Set number of fractional symbols */
584 SetFracSymNum(HWND hwndDlg
,
587 TCHAR szFracSymNum
[MAX_SAMPLES_STR_SIZE
];
590 /* Get setted number of fractional symbols */
591 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNDIGDEC
),
596 /* convert to wide char */
597 _itot(nCurrSel
, szFracSymNum
, DECIMAL_RADIX
);
599 /* Save number of fractional symbols */
600 SetLocaleInfo(lcid
, LOCALE_IDIGITS
, szFracSymNum
);
605 /* Set field separator */
607 SetNumFieldSep(HWND hwndDlg
,
610 TCHAR szFieldSep
[MAX_SAMPLES_STR_SIZE
];
612 /* Get setted field separator */
613 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDIGITGRSYM
),
615 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
618 /* Save field separator */
619 SetLocaleInfo(lcid
, LOCALE_STHOUSAND
, szFieldSep
);
624 /* Set number of digits in field */
626 SetFieldDigNum(HWND hwndDlg
,
629 TCHAR szFieldDigNum
[MAX_SAMPLES_STR_SIZE
];
631 /* Get setted number of digidts in field */
632 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSDGROUPING
),
634 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
635 (LPARAM
)szFieldDigNum
);
637 /* Save number of digits in field */
638 SetLocaleInfo(lcid
, LOCALE_SGROUPING
, szFieldDigNum
);
643 /* Set negative sign */
645 SetNumNegSign(HWND hwndDlg
,
648 TCHAR szNegSign
[MAX_SAMPLES_STR_SIZE
];
650 /* Get setted negative sign */
651 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNSIGNSYM
),
653 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
656 /* Save negative sign */
657 SetLocaleInfo(lcid
, LOCALE_SNEGATIVESIGN
, szNegSign
);
662 /* Set negative sum format */
664 SetNegSumFmt(HWND hwndDlg
,
667 TCHAR szNegSumFmt
[MAX_SAMPLES_STR_SIZE
];
670 /* Get setted negative sum format */
671 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSNNUMFORMAT
),
676 /* convert to wide char */
677 _itot(nCurrSel
, szNegSumFmt
,DECIMAL_RADIX
);
679 /* Save negative sum format */
680 SetLocaleInfo(lcid
, LOCALE_INEGNUMBER
, szNegSumFmt
);
685 /* Set leading zero */
687 SetNumLeadZero(HWND hwndDlg
,
690 TCHAR szLeadZero
[MAX_SAMPLES_STR_SIZE
];
693 /* Get setted leading zero format */
694 nCurrSel
= SendMessageW(GetDlgItem(hwndDlg
, IDC_NUMBERSDISPLEADZER
),
699 /* convert to wide char */
700 _itot(nCurrSel
, szLeadZero
, DECIMAL_RADIX
);
702 /* Save leading zero format */
703 SetLocaleInfo(lcid
, LOCALE_ILZERO
, szLeadZero
);
708 /* Set elements list separator */
710 SetNumListSep(HWND hwndDlg
,
713 TCHAR szListSep
[MAX_SAMPLES_STR_SIZE
];
715 /* Get setted list separator */
716 SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSLSEP
),
718 (WPARAM
)MAX_SAMPLES_STR_SIZE
,
721 /* Save list separator */
722 SetLocaleInfo(lcid
, LOCALE_SLIST
, szListSep
);
727 /* Set units system */
729 SetNumUnitsSys(HWND hwndDlg
,
732 TCHAR szUnitsSys
[MAX_SAMPLES_STR_SIZE
];
735 /* Get setted units system */
736 nCurrSel
= SendMessage(GetDlgItem(hwndDlg
, IDC_NUMBERSMEASSYS
),
741 /* convert to wide char */
742 _itot(nCurrSel
, szUnitsSys
, DECIMAL_RADIX
);
744 /* Save units system */
745 SetLocaleInfo(lcid
, LOCALE_IMEASURE
, szUnitsSys
);
750 /* Property page dialog callback */
752 NumbersPageProc(HWND hwndDlg
,
757 PGLOBALDATA pGlobalData
;
759 pGlobalData
= (PGLOBALDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
764 pGlobalData
= (PGLOBALDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
765 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
767 InitNumDecimalSepCB(hwndDlg
, pGlobalData
->lcid
);
768 InitNumOfFracSymbCB(hwndDlg
, pGlobalData
->lcid
);
769 InitNumFieldSepCB(hwndDlg
, pGlobalData
->lcid
);
770 InitFieldDigNumCB(hwndDlg
, pGlobalData
->lcid
);
771 InitNegSignCB(hwndDlg
, pGlobalData
->lcid
);
772 InitNegNumFmtCB(hwndDlg
, pGlobalData
->lcid
);
773 InitLeadingZeroesCB(hwndDlg
, pGlobalData
->lcid
);
774 InitListSepCB(hwndDlg
, pGlobalData
->lcid
);
775 InitUnitsSysCB(hwndDlg
, pGlobalData
->lcid
);
776 UpdateNumSamples(hwndDlg
, pGlobalData
->lcid
);
780 switch (LOWORD(wParam
))
782 case IDC_NUMBERDSYMBOL
:
783 case IDC_NUMBERSNDIGDEC
:
784 case IDC_NUMBERSDIGITGRSYM
:
785 case IDC_NUMBERSDGROUPING
:
786 case IDC_NUMBERSNSIGNSYM
:
787 case IDC_NUMBERSNNUMFORMAT
:
788 case IDC_NUMBERSDISPLEADZER
:
789 case IDC_NUMBERSLSEP
:
790 case IDC_NUMBERSMEASSYS
:
791 if (HIWORD(wParam
) == CBN_SELCHANGE
|| HIWORD(wParam
) == CBN_EDITCHANGE
)
793 /* Set "Apply" button enabled */
794 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
800 /* If push apply button */
801 if (((LPNMHDR
)lParam
)->code
== (UINT
)PSN_APPLY
)
803 if (!SetNumDecimalSep(hwndDlg
, pGlobalData
->lcid
))
806 if (!SetFracSymNum(hwndDlg
, pGlobalData
->lcid
))
809 if (!SetNumFieldSep(hwndDlg
, pGlobalData
->lcid
))
812 if (!SetFieldDigNum(hwndDlg
, pGlobalData
->lcid
))
815 if (!SetNumNegSign(hwndDlg
, pGlobalData
->lcid
))
818 if (!SetNegSumFmt(hwndDlg
, pGlobalData
->lcid
))
821 if (!SetNumLeadZero(hwndDlg
, pGlobalData
->lcid
))
824 if (!SetNumListSep(hwndDlg
, pGlobalData
->lcid
))
827 if (!SetNumUnitsSys(hwndDlg
, pGlobalData
->lcid
))
830 UpdateNumSamples(hwndDlg
, pGlobalData
->lcid
);