Synchronize with trunk r58457.
[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: dll/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 i;
345
346 /* Get group separator */
347 GetLocaleInfo(pGlobalData->lcid,
348 LOCALE_SMONTHOUSANDSEP,
349 szThousandSep, MAX_FMT_SIZE);
350
351 /* Get grouping */
352 GetLocaleInfo(pGlobalData->lcid,
353 LOCALE_SMONGROUPING,
354 szGrouping, MAX_FMT_SIZE);
355
356 /* Digit grouping */
357 cyFmt.NumDigits = 0;
358 cyFmt.LeadingZero = 0;
359 cyFmt.lpDecimalSep = _T("");
360 cyFmt.lpThousandSep = szThousandSep;
361 cyFmt.PositiveOrder = 0;
362 cyFmt.NegativeOrder = 0;
363 cyFmt.lpCurrencySymbol = _T("");
364 cyFmt.Grouping = 0;
365 GetCurrencyFormat(pGlobalData->lcid, 0,
366 _T("123456789"),
367 &cyFmt, szBuffer, MAX_FMT_SIZE);
368 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
369 CB_INSERTSTRING,
370 -1,
371 (LPARAM)szBuffer);
372
373 cyFmt.Grouping = 3;
374 GetCurrencyFormat(pGlobalData->lcid, 0,
375 _T("123456789"),
376 &cyFmt, szBuffer, MAX_FMT_SIZE);
377 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
378 CB_INSERTSTRING,
379 -1,
380 (LPARAM)szBuffer);
381
382 cyFmt.Grouping = 32;
383 GetCurrencyFormat(pGlobalData->lcid, 0,
384 _T("123456789"),
385 &cyFmt, szBuffer, MAX_FMT_SIZE);
386 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
387 CB_INSERTSTRING,
388 -1,
389 (LPARAM)szBuffer);
390
391 i = 0;
392 if (szGrouping[0] == _T('3'))
393 {
394 if ((szGrouping[1] == _T(';')) &&
395 (szGrouping[2] == _T('2')))
396 i = 2;
397 else
398 i = 1;
399 }
400
401 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
402 CB_SETCURSEL,
403 i, /* Index */
404 0);
405 }
406
407
408 /* Set number of digits in field */
409 static BOOL
410 SetCurrencyDigNum(HWND hwndDlg, LCID lcid)
411 {
412 LPTSTR szFieldDigNumSamples[MAX_FIELD_DIG_SAMPLES]=
413 {
414 _T("0;0"),
415 _T("3;0"),
416 _T("3;2;0")
417 };
418
419 int nCurrSel;
420
421 /* Get setted number of digits in field */
422 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
423 CB_GETCURSEL,
424 (WPARAM)0,
425 (LPARAM)0);
426
427 /* Save number of digits in field */
428 if (nCurrSel != CB_ERR)
429 SetLocaleInfo(lcid, LOCALE_SMONGROUPING, szFieldDigNumSamples[nCurrSel]);
430
431 return TRUE;
432 }
433
434 /* Set currency field separator */
435 static BOOL
436 SetCurrencyFieldSep(HWND hwndDlg, LCID lcid)
437 {
438 TCHAR szCurrencyFieldSep[MAX_SAMPLES_STR_SIZE];
439
440 /* Get setted currency field separator */
441 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP),
442 WM_GETTEXT,
443 (WPARAM)MAX_SAMPLES_STR_SIZE,
444 (LPARAM)szCurrencyFieldSep);
445
446 /* Save currency field separator */
447 SetLocaleInfo(lcid, LOCALE_SMONTHOUSANDSEP, szCurrencyFieldSep);
448
449 return TRUE;
450 }
451
452 /* Set number of fractional symbols */
453 static BOOL
454 SetCurrencyFracSymNum(HWND hwndDlg, LCID lcid)
455 {
456 TCHAR szCurrencyFracSymNum[MAX_SAMPLES_STR_SIZE];
457 INT nCurrSel;
458
459 /* Get setted number of fractional symbols */
460 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
461 CB_GETCURSEL,
462 (WPARAM)0,
463 (LPARAM)0);
464
465 /* Convert to wide char */
466 _itot(nCurrSel, szCurrencyFracSymNum, DECIMAL_RADIX);
467
468 /* Save number of fractional symbols */
469 SetLocaleInfo(lcid, LOCALE_ICURRDIGITS, szCurrencyFracSymNum);
470
471 return TRUE;
472 }
473
474 /* Set currency separator */
475 static BOOL
476 SetCurrencySep(HWND hwndDlg, LCID lcid)
477 {
478 TCHAR szCurrencySep[MAX_SAMPLES_STR_SIZE];
479
480 /* Get setted currency decimal separator */
481 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP),
482 WM_GETTEXT,
483 (WPARAM)MAX_SAMPLES_STR_SIZE,
484 (LPARAM)szCurrencySep);
485
486 /* TODO: Add check for correctly input */
487
488 /* Save currency separator */
489 SetLocaleInfo(lcid, LOCALE_SMONDECIMALSEP, szCurrencySep);
490
491 return TRUE;
492 }
493
494 /* Set negative currency sum format */
495 static BOOL
496 SetNegCurrencySumFmt(HWND hwndDlg, LCID lcid)
497 {
498 TCHAR szNegCurrencySumFmt[MAX_SAMPLES_STR_SIZE];
499 INT nCurrSel;
500
501 /* Get setted currency unit */
502 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGVALUE),
503 CB_GETCURSEL,
504 (WPARAM)0,
505 (LPARAM)0);
506
507 /* Convert to wide char */
508 _itot(nCurrSel, szNegCurrencySumFmt, DECIMAL_RADIX);
509
510 /* Save currency sum format */
511 SetLocaleInfo(lcid, LOCALE_INEGCURR, szNegCurrencySumFmt);
512
513 return TRUE;
514 }
515
516 /* Set positive currency sum format */
517 static BOOL
518 SetPosCurrencySumFmt(HWND hwndDlg, LCID lcid)
519 {
520 TCHAR szPosCurrencySumFmt[MAX_SAMPLES_STR_SIZE];
521 INT nCurrSel;
522
523 /* Get setted currency unit */
524 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSVALUE),
525 CB_GETCURSEL,
526 (WPARAM)0,
527 (LPARAM)0);
528
529 /* Convert to wide char */
530 _itot(nCurrSel, szPosCurrencySumFmt, DECIMAL_RADIX);
531
532 /* Save currency sum format */
533 SetLocaleInfo(lcid, LOCALE_ICURRENCY, szPosCurrencySumFmt);
534
535 return TRUE;
536 }
537
538 /* Set currency unit */
539 static BOOL
540 SetCurrencyUnit(HWND hwndDlg, LCID lcid)
541 {
542 TCHAR szCurrencyUnit[MAX_SAMPLES_STR_SIZE];
543
544 /* Get setted currency unit */
545 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYSYMBOL),
546 WM_GETTEXT,
547 (WPARAM)MAX_SAMPLES_STR_SIZE,
548 (LPARAM)(LPCSTR)szCurrencyUnit);
549
550 /* Save currency unit */
551 SetLocaleInfo(lcid, LOCALE_SCURRENCY, szCurrencyUnit);
552
553 return TRUE;
554 }
555
556 /* Property page dialog callback */
557 INT_PTR CALLBACK
558 CurrencyPageProc(HWND hwndDlg,
559 UINT uMsg,
560 WPARAM wParam,
561 LPARAM lParam)
562 {
563 PGLOBALDATA pGlobalData;
564
565 pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
566
567 switch (uMsg)
568 {
569 case WM_INITDIALOG:
570 pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam;
571 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
572
573 InitCurrencySymbols(hwndDlg, pGlobalData);
574 InitCurrencyPositiveFormats(hwndDlg, pGlobalData);
575 InitCurrencyNegativeFormats(hwndDlg, pGlobalData);
576 InitCurrencyDecimalSeparators(hwndDlg, pGlobalData);
577 InitCurrencyNumFracDigits(hwndDlg, pGlobalData);
578 InitCurrencyGroupSeparators(hwndDlg, pGlobalData);
579 InitDigitGroupCB(hwndDlg, pGlobalData);
580 UpdateExamples(hwndDlg, pGlobalData);
581 break;
582
583 case WM_COMMAND:
584 switch (LOWORD(wParam))
585 {
586 case IDC_CURRENCYSYMBOL:
587 case IDC_CURRENCYPOSVALUE:
588 case IDC_CURRENCYNEGVALUE:
589 case IDC_CURRENCYDECSEP:
590 case IDC_CURRENCYDECNUM:
591 case IDC_CURRENCYGRPSEP:
592 case IDC_CURRENCYGRPNUM:
593 if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE)
594 {
595 /* Set "Apply" button enabled */
596 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
597 }
598 }
599 break;
600
601 case WM_NOTIFY:
602 {
603 LPNMHDR lpnm = (LPNMHDR)lParam;
604 /* If push apply button */
605 if (lpnm->code == (UINT)PSN_APPLY)
606 {
607 if (!SetCurrencyDigNum(hwndDlg, pGlobalData->lcid))
608 break;
609
610 if (!SetCurrencyUnit(hwndDlg, pGlobalData->lcid))
611 break;
612
613 if (!SetPosCurrencySumFmt(hwndDlg, pGlobalData->lcid))
614 break;
615
616 if (!SetNegCurrencySumFmt(hwndDlg, pGlobalData->lcid))
617 break;
618
619 if (!SetCurrencySep(hwndDlg, pGlobalData->lcid))
620 break;
621
622 if (!SetCurrencyFracSymNum(hwndDlg, pGlobalData->lcid))
623 break;
624
625 if (!SetCurrencyFieldSep(hwndDlg, pGlobalData->lcid))
626 break;
627
628 UpdateExamples(hwndDlg, pGlobalData);
629 }
630 }
631 break;
632 }
633 return FALSE;
634 }
635
636 /* EOF */