- Update to r53061
[reactos.git] / dll / cpl / intl / currency.c
1 /*
2 * ReactOS
3 * Copyright (C) 2004 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS International Control Panel
22 * FILE: lib/cpl/intl/currency.c
23 * PURPOSE: Currency property page
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include "intl.h"
28
29 #define POSITIVE_EXAMPLE _T("123456789.00")
30 #define NEGATIVE_EXAMPLE _T("-123456789.00")
31 #define MAX_FIELD_DIG_SAMPLES 3
32
33
34 static VOID
35 UpdateExamples(HWND hwndDlg, PGLOBALDATA pGlobalData)
36 {
37 TCHAR szBuffer[MAX_FMT_SIZE];
38
39 /* positive example */
40 GetCurrencyFormat(pGlobalData->lcid, 0,
41 POSITIVE_EXAMPLE,
42 NULL, szBuffer, MAX_FMT_SIZE);
43
44 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSSAMPLE), WM_SETTEXT, 0, (LPARAM)szBuffer);
45
46 /* negative example */
47 GetCurrencyFormat(pGlobalData->lcid, 0,
48 NEGATIVE_EXAMPLE,
49 NULL, szBuffer, MAX_FMT_SIZE);
50
51 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGSAMPLE), WM_SETTEXT, 0, (LPARAM)szBuffer);
52 }
53
54
55 static VOID
56 InitCurrencySymbols(HWND hwndDlg, PGLOBALDATA pGlobalData)
57 {
58 TCHAR szBuffer[MAX_FMT_SIZE];
59
60 /* Limit text length */
61 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYSYMBOL),
62 CB_LIMITTEXT,
63 MAX_CURRENCYSYMBOL,
64 0);
65
66 /* Set currency symbols */
67 GetLocaleInfo(pGlobalData->lcid,
68 LOCALE_SCURRENCY,
69 szBuffer, MAX_FMT_SIZE);
70
71 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYSYMBOL),
72 CB_ADDSTRING,
73 0,
74 (LPARAM)szBuffer);
75
76 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYSYMBOL),
77 CB_SETCURSEL,
78 0, /* index */
79 0);
80 }
81
82
83 static VOID
84 InitCurrencyPositiveFormats(HWND hwndDlg, PGLOBALDATA pGlobalData)
85 {
86 TCHAR szDecimalSep[MAX_FMT_SIZE];
87 TCHAR szThousandSep[MAX_FMT_SIZE];
88 TCHAR szCurrencySymbol[MAX_FMT_SIZE];
89 TCHAR szBuffer[MAX_FMT_SIZE];
90 CURRENCYFMT cyFmt;
91 INT nPositiveOrder = 0;
92 INT ret;
93 INT i;
94
95
96 /* Get positive format */
97 ret = GetLocaleInfo(pGlobalData->lcid,
98 LOCALE_ICURRENCY,
99 szBuffer, MAX_FMT_SIZE);
100 if (ret != 0)
101 {
102 nPositiveOrder = _ttoi(szBuffer);
103 }
104
105 /* Get number of fractional digits */
106 ret = GetLocaleInfo(pGlobalData->lcid,
107 LOCALE_ICURRDIGITS,
108 szBuffer, MAX_FMT_SIZE);
109 if (ret != 0)
110 {
111 cyFmt.NumDigits = _ttoi(szBuffer);
112 }
113 else
114 {
115 cyFmt.NumDigits = 0;
116 }
117
118 /* Get decimal separator */
119 ret = GetLocaleInfo(pGlobalData->lcid,
120 LOCALE_SMONDECIMALSEP,
121 szDecimalSep, MAX_FMT_SIZE);
122
123 /* Get group separator */
124 ret = GetLocaleInfo(pGlobalData->lcid,
125 LOCALE_SMONTHOUSANDSEP,
126 szThousandSep, MAX_FMT_SIZE);
127
128 /* Get currency symbol */
129 ret = GetLocaleInfo(pGlobalData->lcid,
130 LOCALE_SCURRENCY,
131 szCurrencySymbol, MAX_FMT_SIZE);
132
133 /* positive currency values */
134 cyFmt.LeadingZero = 0;
135 cyFmt.Grouping = 3;
136 cyFmt.lpDecimalSep = szDecimalSep;
137 cyFmt.lpThousandSep = szThousandSep;
138 cyFmt.lpCurrencySymbol = szCurrencySymbol;
139 cyFmt.NegativeOrder = 0;
140
141 for (i = 0; i < 4; i++)
142 {
143 cyFmt.PositiveOrder = i;
144 GetCurrencyFormat(pGlobalData->lcid, 0,
145 _T("1.1"),
146 &cyFmt, szBuffer, MAX_FMT_SIZE);
147
148 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSVALUE),
149 CB_INSERTSTRING,
150 -1,
151 (LPARAM)szBuffer);
152 }
153
154 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSVALUE),
155 CB_SETCURSEL,
156 nPositiveOrder,
157 0);
158 }
159
160
161 static VOID
162 InitCurrencyNegativeFormats(HWND hwndDlg, PGLOBALDATA pGlobalData)
163 {
164 TCHAR szDecimalSep[MAX_FMT_SIZE];
165 TCHAR szThousandSep[MAX_FMT_SIZE];
166 TCHAR szCurrencySymbol[MAX_FMT_SIZE];
167 TCHAR szBuffer[MAX_FMT_SIZE];
168 CURRENCYFMT cyFmt;
169 INT nNegativeOrder = 0;
170 INT ret;
171 int i;
172
173 /* Get negative format */
174 ret = GetLocaleInfo(pGlobalData->lcid,
175 LOCALE_INEGCURR,
176 szBuffer, MAX_FMT_SIZE);
177 if (ret != 0)
178 {
179 nNegativeOrder = _ttoi(szBuffer);
180 }
181
182 /* Get number of fractional digits */
183 ret = GetLocaleInfo(pGlobalData->lcid,
184 LOCALE_ICURRDIGITS,
185 szBuffer, MAX_FMT_SIZE);
186 if (ret != 0)
187 {
188 cyFmt.NumDigits = _ttoi(szBuffer);
189 }
190 else
191 {
192 cyFmt.NumDigits = 0;
193 }
194
195 /* Get decimal separator */
196 ret = GetLocaleInfo(pGlobalData->lcid,
197 LOCALE_SMONDECIMALSEP,
198 szDecimalSep, MAX_FMT_SIZE);
199
200 /* Get group separator */
201 ret = GetLocaleInfo(pGlobalData->lcid,
202 LOCALE_SMONTHOUSANDSEP,
203 szThousandSep, MAX_FMT_SIZE);
204
205 /* Get currency symbol */
206 ret = GetLocaleInfo(pGlobalData->lcid,
207 LOCALE_SCURRENCY,
208 szCurrencySymbol, MAX_FMT_SIZE);
209
210 /* negative currency values */
211 cyFmt.LeadingZero = 0;
212 cyFmt.Grouping = 3;
213 cyFmt.lpDecimalSep = szDecimalSep;
214 cyFmt.lpThousandSep = szThousandSep;
215 cyFmt.lpCurrencySymbol = szCurrencySymbol;
216 cyFmt.PositiveOrder = 0;
217
218 for (i = 0; i < 16; i++)
219 {
220 cyFmt.NegativeOrder = i;
221 GetCurrencyFormat(pGlobalData->lcid, 0,
222 _T("-1.1"),
223 &cyFmt, szBuffer, MAX_FMT_SIZE);
224
225 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGVALUE),
226 CB_INSERTSTRING,
227 -1,
228 (LPARAM)szBuffer);
229 }
230
231 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGVALUE),
232 CB_SETCURSEL,
233 nNegativeOrder,
234 0);
235 }
236
237
238 static VOID
239 InitCurrencyDecimalSeparators(HWND hwndDlg, PGLOBALDATA pGlobalData)
240 {
241 TCHAR szBuffer[MAX_FMT_SIZE];
242
243 /* Limit text length */
244 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP),
245 CB_LIMITTEXT,
246 MAX_CURRENCYDECSEP,
247 0);
248
249 /* Get decimal separator */
250 GetLocaleInfo(pGlobalData->lcid,
251 LOCALE_SMONDECIMALSEP,
252 szBuffer, MAX_FMT_SIZE);
253
254 /* decimal separator */
255 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP),
256 CB_ADDSTRING,
257 0,
258 (LPARAM)szBuffer);
259
260 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP),
261 CB_SETCURSEL,
262 0, /* index */
263 0);
264 }
265
266
267 /* Initialize the number of fractional digits */
268 static VOID
269 InitCurrencyNumFracDigits(HWND hwndDlg, PGLOBALDATA pGlobalData)
270 {
271 TCHAR szBuffer[MAX_FMT_SIZE];
272 int ret;
273 int i;
274
275 /* Create standard list of fractional symbols */
276 for (i = 0; i < 10; i++)
277 {
278 szBuffer[0] = _T('0') + i;
279 szBuffer[1] = 0;
280 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
281 CB_ADDSTRING,
282 0,
283 (LPARAM)szBuffer);
284 }
285
286 /* Get number of fractional digits */
287 ret = GetLocaleInfo(pGlobalData->lcid,
288 LOCALE_ICURRDIGITS,
289 szBuffer, MAX_FMT_SIZE);
290 if (ret != 0)
291 {
292 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
293 CB_SETCURSEL,
294 _ttoi(szBuffer),
295 0);
296 }
297 else
298 {
299 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
300 CB_SETCURSEL,
301 0,
302 0);
303 }
304 }
305
306
307 /* Initialize the list of group separators */
308 static VOID
309 InitCurrencyGroupSeparators(HWND hwndDlg, PGLOBALDATA pGlobalData)
310 {
311 TCHAR szBuffer[MAX_FMT_SIZE];
312
313 /* Limit text length */
314 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP),
315 CB_LIMITTEXT,
316 MAX_CURRENCYGRPSEP,
317 0);
318
319 /* Get group separator */
320 GetLocaleInfo(pGlobalData->lcid,
321 LOCALE_SMONTHOUSANDSEP,
322 szBuffer, MAX_FMT_SIZE);
323
324 /* digit group separator */
325 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP),
326 CB_ADDSTRING,
327 0,
328 (LPARAM)szBuffer);
329
330 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP),
331 CB_SETCURSEL,
332 0, /* index */
333 0);
334 }
335
336
337 static VOID
338 InitDigitGroupCB(HWND hwndDlg, PGLOBALDATA pGlobalData)
339 {
340 TCHAR szThousandSep[MAX_FMT_SIZE];
341 TCHAR szGrouping[MAX_FMT_SIZE];
342 TCHAR szBuffer[MAX_FMT_SIZE];
343 CURRENCYFMT cyFmt;
344 INT ret;
345 INT i;
346
347 /* Get group separator */
348 ret = GetLocaleInfo(pGlobalData->lcid,
349 LOCALE_SMONTHOUSANDSEP,
350 szThousandSep, MAX_FMT_SIZE);
351
352 /* Get grouping */
353 ret = GetLocaleInfo(pGlobalData->lcid,
354 LOCALE_SMONGROUPING,
355 szGrouping, MAX_FMT_SIZE);
356
357 /* digit grouping */
358 cyFmt.NumDigits = 0;
359 cyFmt.LeadingZero = 0;
360 cyFmt.lpDecimalSep = _T("");
361 cyFmt.lpThousandSep = szThousandSep;
362 cyFmt.PositiveOrder = 0;
363 cyFmt.NegativeOrder = 0;
364 cyFmt.lpCurrencySymbol = _T("");
365 cyFmt.Grouping = 0;
366 GetCurrencyFormat(pGlobalData->lcid, 0,
367 _T("123456789"),
368 &cyFmt, szBuffer, MAX_FMT_SIZE);
369 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
370 CB_INSERTSTRING,
371 -1,
372 (LPARAM)szBuffer);
373
374 cyFmt.Grouping = 3;
375 GetCurrencyFormat(pGlobalData->lcid, 0,
376 _T("123456789"),
377 &cyFmt, szBuffer, MAX_FMT_SIZE);
378 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
379 CB_INSERTSTRING,
380 -1,
381 (LPARAM)szBuffer);
382
383 cyFmt.Grouping = 32;
384 GetCurrencyFormat(pGlobalData->lcid, 0,
385 _T("123456789"),
386 &cyFmt, szBuffer, MAX_FMT_SIZE);
387 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
388 CB_INSERTSTRING,
389 -1,
390 (LPARAM)szBuffer);
391
392 i = 0;
393 if (szGrouping[0] == _T('3'))
394 {
395 if ((szGrouping[1] == _T(';')) &&
396 (szGrouping[2] == _T('2')))
397 i = 2;
398 else
399 i = 1;
400 }
401
402 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
403 CB_SETCURSEL,
404 i, /* index */
405 0);
406 }
407
408
409 /* Set number of digits in field */
410 static BOOL
411 SetCurrencyDigNum(HWND hwndDlg, LCID lcid)
412 {
413 LPTSTR szFieldDigNumSamples[MAX_FIELD_DIG_SAMPLES]=
414 {
415 _T("0;0"),
416 _T("3;0"),
417 _T("3;2;0")
418 };
419
420 int nCurrSel;
421
422 /* Get setted number of digits in field */
423 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
424 CB_GETCURSEL,
425 (WPARAM)0,
426 (LPARAM)0);
427
428 /* Save number of digits in field */
429 if (nCurrSel != CB_ERR)
430 SetLocaleInfo(lcid, LOCALE_SMONGROUPING, szFieldDigNumSamples[nCurrSel]);
431
432 return TRUE;
433 }
434
435 /* Set currency field separator */
436 static BOOL
437 SetCurrencyFieldSep(HWND hwndDlg, LCID lcid)
438 {
439 TCHAR szCurrencyFieldSep[MAX_SAMPLES_STR_SIZE];
440
441 /* Get setted currency field separator */
442 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP),
443 WM_GETTEXT,
444 (WPARAM)MAX_SAMPLES_STR_SIZE,
445 (LPARAM)szCurrencyFieldSep);
446
447 /* Save currency field separator */
448 SetLocaleInfo(lcid, LOCALE_SMONTHOUSANDSEP, szCurrencyFieldSep);
449
450 return TRUE;
451 }
452
453 /* Set number of fractional symbols */
454 static BOOL
455 SetCurrencyFracSymNum(HWND hwndDlg, LCID lcid)
456 {
457 TCHAR szCurrencyFracSymNum[MAX_SAMPLES_STR_SIZE];
458 INT nCurrSel;
459
460 /* Get setted number of fractional symbols */
461 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
462 CB_GETCURSEL,
463 (WPARAM)0,
464 (LPARAM)0);
465
466 /* convert to wide char */
467 _itot(nCurrSel, szCurrencyFracSymNum, DECIMAL_RADIX);
468
469 /* Save number of fractional symbols */
470 SetLocaleInfo(lcid, LOCALE_ICURRDIGITS, szCurrencyFracSymNum);
471
472 return TRUE;
473 }
474
475 /* Set currency separator */
476 static BOOL
477 SetCurrencySep(HWND hwndDlg, LCID lcid)
478 {
479 TCHAR szCurrencySep[MAX_SAMPLES_STR_SIZE];
480
481 /* Get setted currency decimal separator */
482 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP),
483 WM_GETTEXT,
484 (WPARAM)MAX_SAMPLES_STR_SIZE,
485 (LPARAM)szCurrencySep);
486
487 /* TODO: Add check for correctly input */
488
489 /* Save currency separator */
490 SetLocaleInfo(lcid, LOCALE_SMONDECIMALSEP, szCurrencySep);
491
492 return TRUE;
493 }
494
495 /* Set negative currency sum format */
496 static BOOL
497 SetNegCurrencySumFmt(HWND hwndDlg, LCID lcid)
498 {
499 TCHAR szNegCurrencySumFmt[MAX_SAMPLES_STR_SIZE];
500 INT nCurrSel;
501
502 /* Get setted currency unit */
503 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGVALUE),
504 CB_GETCURSEL,
505 (WPARAM)0,
506 (LPARAM)0);
507
508 /* convert to wide char */
509 _itot(nCurrSel, szNegCurrencySumFmt, DECIMAL_RADIX);
510
511 /* Save currency sum format */
512 SetLocaleInfo(lcid, LOCALE_INEGCURR, szNegCurrencySumFmt);
513
514 return TRUE;
515 }
516
517 /* Set positive currency sum format */
518 static BOOL
519 SetPosCurrencySumFmt(HWND hwndDlg, LCID lcid)
520 {
521 TCHAR szPosCurrencySumFmt[MAX_SAMPLES_STR_SIZE];
522 INT nCurrSel;
523
524 /* Get setted currency unit */
525 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSVALUE),
526 CB_GETCURSEL,
527 (WPARAM)0,
528 (LPARAM)0);
529
530 /* convert to wide char */
531 _itot(nCurrSel, szPosCurrencySumFmt, DECIMAL_RADIX);
532
533 /* Save currency sum format */
534 SetLocaleInfo(lcid, LOCALE_ICURRENCY, szPosCurrencySumFmt);
535
536 return TRUE;
537 }
538
539 /* Set currency unit */
540 static BOOL
541 SetCurrencyUnit(HWND hwndDlg, LCID lcid)
542 {
543 TCHAR szCurrencyUnit[MAX_SAMPLES_STR_SIZE];
544
545 /* Get setted currency unit */
546 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYSYMBOL),
547 WM_GETTEXT,
548 (WPARAM)MAX_SAMPLES_STR_SIZE,
549 (LPARAM)(LPCSTR)szCurrencyUnit);
550
551 /* Save currency unit */
552 SetLocaleInfo(lcid, LOCALE_SCURRENCY, szCurrencyUnit);
553
554 return TRUE;
555 }
556
557 /* Property page dialog callback */
558 INT_PTR CALLBACK
559 CurrencyPageProc(HWND hwndDlg,
560 UINT uMsg,
561 WPARAM wParam,
562 LPARAM lParam)
563 {
564 PGLOBALDATA pGlobalData;
565
566 pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
567
568 switch (uMsg)
569 {
570 case WM_INITDIALOG:
571 pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam;
572 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
573
574 InitCurrencySymbols(hwndDlg, pGlobalData);
575 InitCurrencyPositiveFormats(hwndDlg, pGlobalData);
576 InitCurrencyNegativeFormats(hwndDlg, pGlobalData);
577 InitCurrencyDecimalSeparators(hwndDlg, pGlobalData);
578 InitCurrencyNumFracDigits(hwndDlg, pGlobalData);
579 InitCurrencyGroupSeparators(hwndDlg, pGlobalData);
580 InitDigitGroupCB(hwndDlg, pGlobalData);
581 UpdateExamples(hwndDlg, pGlobalData);
582 break;
583
584 case WM_COMMAND:
585 switch (LOWORD(wParam))
586 {
587 case IDC_CURRENCYSYMBOL:
588 case IDC_CURRENCYPOSVALUE:
589 case IDC_CURRENCYNEGVALUE:
590 case IDC_CURRENCYDECSEP:
591 case IDC_CURRENCYDECNUM:
592 case IDC_CURRENCYGRPSEP:
593 case IDC_CURRENCYGRPNUM:
594 if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE)
595 {
596 /* Set "Apply" button enabled */
597 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
598 }
599 }
600 break;
601
602 case WM_NOTIFY:
603 {
604 LPNMHDR lpnm = (LPNMHDR)lParam;
605 /* If push apply button */
606 if (lpnm->code == (UINT)PSN_APPLY)
607 {
608 if (!SetCurrencyDigNum(hwndDlg, pGlobalData->lcid))
609 break;
610
611 if (!SetCurrencyUnit(hwndDlg, pGlobalData->lcid))
612 break;
613
614 if (!SetPosCurrencySumFmt(hwndDlg, pGlobalData->lcid))
615 break;
616
617 if (!SetNegCurrencySumFmt(hwndDlg, pGlobalData->lcid))
618 break;
619
620 if (!SetCurrencySep(hwndDlg, pGlobalData->lcid))
621 break;
622
623 if (!SetCurrencyFracSymNum(hwndDlg, pGlobalData->lcid))
624 break;
625
626 if (!SetCurrencyFieldSep(hwndDlg, pGlobalData->lcid))
627 break;
628
629 UpdateExamples(hwndDlg, pGlobalData);
630 }
631 }
632 break;
633 }
634
635 return FALSE;
636 }
637
638 /* EOF */