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