Use the currently selected locale id instead of LOCALE_USER_DEFAULT to display and...
[reactos.git] / reactos / 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 <windows.h>
28 #include <commctrl.h>
29 #include <cpl.h>
30 #include <tchar.h>
31
32 #include "intl.h"
33 #include "resource.h"
34
35 #define POSITIVE_EXAMPLE _T("123456789.00")
36 #define NEGATIVE_EXAMPLE _T("-123456789.00")
37 #define MAX_FIELD_DIG_SAMPLES 3
38
39
40 static VOID
41 UpdateExamples(HWND hwndDlg, PGLOBALDATA pGlobalData)
42 {
43 TCHAR szBuffer[MAX_FMT_SIZE];
44
45 /* positive example */
46 GetCurrencyFormat(pGlobalData->lcid, 0,
47 POSITIVE_EXAMPLE,
48 NULL, szBuffer, MAX_FMT_SIZE);
49
50 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSSAMPLE), WM_SETTEXT, 0, (LPARAM)szBuffer);
51
52 /* negative example */
53 GetCurrencyFormat(pGlobalData->lcid, 0,
54 NEGATIVE_EXAMPLE,
55 NULL, szBuffer, MAX_FMT_SIZE);
56
57 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGSAMPLE), WM_SETTEXT, 0, (LPARAM)szBuffer);
58 }
59
60
61 static VOID
62 InitCurrencySymbols(HWND hwndDlg, PGLOBALDATA pGlobalData)
63 {
64 TCHAR szBuffer[MAX_FMT_SIZE];
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 /* Get decimal separator */
244 GetLocaleInfo(pGlobalData->lcid,
245 LOCALE_SMONDECIMALSEP,
246 szBuffer, MAX_FMT_SIZE);
247
248 /* decimal separator */
249 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP),
250 CB_ADDSTRING,
251 0,
252 (LPARAM)szBuffer);
253
254 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP),
255 CB_SETCURSEL,
256 0, /* index */
257 0);
258 }
259
260
261 /* Initialize the number of fractional digits */
262 static VOID
263 InitCurrencyNumFracDigits(HWND hwndDlg, PGLOBALDATA pGlobalData)
264 {
265 TCHAR szBuffer[MAX_FMT_SIZE];
266 int ret;
267 int i;
268
269 /* */
270 for (i = 0; i < 10; i++)
271 {
272 szBuffer[0] = _T('0') + i;
273 szBuffer[1] = 0;
274 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
275 CB_ADDSTRING,
276 0,
277 (LPARAM)szBuffer);
278 }
279
280 /* Get number of fractional digits */
281 ret = GetLocaleInfo(pGlobalData->lcid,
282 LOCALE_ICURRDIGITS,
283 szBuffer, MAX_FMT_SIZE);
284 if (ret != 0)
285 {
286 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
287 CB_SETCURSEL,
288 _ttoi(szBuffer),
289 0);
290 }
291 else
292 {
293 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
294 CB_SETCURSEL,
295 0,
296 0);
297 }
298 }
299
300
301 /* Initialize the list of group separators */
302 static VOID
303 InitCurrencyGroupSeparators(HWND hwndDlg, PGLOBALDATA pGlobalData)
304 {
305 TCHAR szBuffer[MAX_FMT_SIZE];
306
307 /* Get group separator */
308 GetLocaleInfo(pGlobalData->lcid,
309 LOCALE_SMONTHOUSANDSEP,
310 szBuffer, MAX_FMT_SIZE);
311
312 /* digit group separator */
313 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP),
314 CB_ADDSTRING,
315 0,
316 (LPARAM)szBuffer);
317
318 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP),
319 CB_SETCURSEL,
320 0, /* index */
321 0);
322 }
323
324
325 static VOID
326 InitDigitGroupCB(HWND hwndDlg, PGLOBALDATA pGlobalData)
327 {
328 TCHAR szThousandSep[MAX_FMT_SIZE];
329 TCHAR szGrouping[MAX_FMT_SIZE];
330 TCHAR szBuffer[MAX_FMT_SIZE];
331 CURRENCYFMT cyFmt;
332 INT ret;
333 INT i;
334
335 /* Get group separator */
336 ret = GetLocaleInfo(pGlobalData->lcid,
337 LOCALE_SMONTHOUSANDSEP,
338 szThousandSep, MAX_FMT_SIZE);
339
340 /* Get grouping */
341 ret = GetLocaleInfo(pGlobalData->lcid,
342 LOCALE_SMONGROUPING,
343 szGrouping, MAX_FMT_SIZE);
344
345 /* digit grouping */
346 cyFmt.NumDigits = 0;
347 cyFmt.LeadingZero = 0;
348 cyFmt.lpDecimalSep = _T("");
349 cyFmt.lpThousandSep = szThousandSep;
350 cyFmt.NegativeOrder = 0;
351 cyFmt.lpCurrencySymbol = _T("");
352 cyFmt.Grouping = 0;
353 GetCurrencyFormat(pGlobalData->lcid, 0,
354 _T("123456789"),
355 &cyFmt, szBuffer, MAX_FMT_SIZE);
356 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
357 CB_INSERTSTRING,
358 -1,
359 (LPARAM)szBuffer);
360
361 cyFmt.Grouping = 3;
362 GetCurrencyFormat(pGlobalData->lcid, 0,
363 _T("123456789"),
364 &cyFmt, szBuffer, MAX_FMT_SIZE);
365 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
366 CB_INSERTSTRING,
367 -1,
368 (LPARAM)szBuffer);
369
370 cyFmt.Grouping = 32;
371 GetCurrencyFormat(pGlobalData->lcid, 0,
372 _T("123456789"),
373 &cyFmt, szBuffer, MAX_FMT_SIZE);
374 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
375 CB_INSERTSTRING,
376 -1,
377 (LPARAM)szBuffer);
378
379 i = 0;
380 if (szGrouping[0] == _T('3'))
381 {
382 if ((szGrouping[1] == _T(';')) &&
383 (szGrouping[2] == _T('2')))
384 i = 2;
385 else
386 i = 1;
387 }
388
389 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
390 CB_SETCURSEL,
391 i, /* index */
392 0);
393 }
394
395
396 /* Set number of digidts in field */
397 static BOOL
398 SetCurrencyDigNum(HWND hwndDlg, LCID lcid)
399 {
400 LPTSTR szFieldDigNumSamples[MAX_FIELD_DIG_SAMPLES]=
401 {
402 _T("0;0"),
403 _T("3;0"),
404 _T("3;2;0")
405 };
406
407 int nCurrSel;
408
409 /* Get setted number of digidts in field */
410 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPNUM),
411 CB_GETCURSEL,
412 (WPARAM)0,
413 (LPARAM)0);
414
415 /* Save number of digidts in field */
416 SetLocaleInfo(lcid, LOCALE_SMONGROUPING, szFieldDigNumSamples[nCurrSel]);
417
418 return TRUE;
419 }
420
421 /* Set currency field separator */
422 static BOOL
423 SetCurrencyFieldSep(HWND hwndDlg, LCID lcid)
424 {
425 TCHAR szCurrencyFieldSep[MAX_SAMPLES_STR_SIZE];
426
427 /* Get setted currency field separator */
428 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYGRPSEP),
429 WM_GETTEXT,
430 (WPARAM)MAX_SAMPLES_STR_SIZE,
431 (LPARAM)szCurrencyFieldSep);
432
433 /* Save currency field separator */
434 SetLocaleInfo(lcid, LOCALE_SMONTHOUSANDSEP, szCurrencyFieldSep);
435
436 return TRUE;
437 }
438
439 /* Set number of fractional symbols */
440 static BOOL
441 SetCurrencyFracSymNum(HWND hwndDlg, LCID lcid)
442 {
443 TCHAR szCurrencyFracSymNum[MAX_SAMPLES_STR_SIZE];
444 INT nCurrSel;
445
446 /* Get setted number of fractional symbols */
447 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECNUM),
448 CB_GETCURSEL,
449 (WPARAM)0,
450 (LPARAM)0);
451
452 /* convert to wide char */
453 _itot(nCurrSel, szCurrencyFracSymNum, DECIMAL_RADIX);
454
455 /* Save number of fractional symbols */
456 SetLocaleInfo(lcid, LOCALE_ICURRDIGITS, szCurrencyFracSymNum);
457
458 return TRUE;
459 }
460
461 /* Set currency separator */
462 static BOOL
463 SetCurrencySep(HWND hwndDlg, LCID lcid)
464 {
465 TCHAR szCurrencySep[MAX_SAMPLES_STR_SIZE];
466
467 /* Get setted currency decimal separator */
468 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYDECSEP),
469 WM_GETTEXT,
470 (WPARAM)MAX_SAMPLES_STR_SIZE,
471 (LPARAM)szCurrencySep);
472
473 /* TODO: Add check for correctly input */
474
475 /* Save currency separator */
476 SetLocaleInfo(lcid, LOCALE_SMONDECIMALSEP, szCurrencySep);
477
478 return TRUE;
479 }
480
481 /* Set negative currency sum format */
482 static BOOL
483 SetNegCurrencySumFmt(HWND hwndDlg, LCID lcid)
484 {
485 TCHAR szNegCurrencySumFmt[MAX_SAMPLES_STR_SIZE];
486 INT nCurrSel;
487
488 /* Get setted currency unit */
489 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYNEGVALUE),
490 CB_GETCURSEL,
491 (WPARAM)0,
492 (LPARAM)0);
493
494 /* convert to wide char */
495 _itot(nCurrSel, szNegCurrencySumFmt, DECIMAL_RADIX);
496
497 /* Save currency sum format */
498 SetLocaleInfo(lcid, LOCALE_INEGCURR, szNegCurrencySumFmt);
499
500 return TRUE;
501 }
502
503 /* Set positive currency sum format */
504 static BOOL
505 SetPosCurrencySumFmt(HWND hwndDlg, LCID lcid)
506 {
507 TCHAR szPosCurrencySumFmt[MAX_SAMPLES_STR_SIZE];
508 INT nCurrSel;
509
510 /* Get setted currency unit */
511 nCurrSel = SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYPOSVALUE),
512 CB_GETCURSEL,
513 (WPARAM)0,
514 (LPARAM)0);
515
516 /* convert to wide char */
517 _itot(nCurrSel, szPosCurrencySumFmt, DECIMAL_RADIX);
518
519 /* Save currency sum format */
520 SetLocaleInfo(lcid, LOCALE_ICURRENCY, szPosCurrencySumFmt);
521
522 return TRUE;
523 }
524
525 /* Set currency unit */
526 static BOOL
527 SetCurrencyUnit(HWND hwndDlg, LCID lcid)
528 {
529 TCHAR szCurrencyUnit[MAX_SAMPLES_STR_SIZE];
530
531 /* Get setted currency unit */
532 SendMessage(GetDlgItem(hwndDlg, IDC_CURRENCYSYMBOL),
533 WM_GETTEXT,
534 (WPARAM)MAX_SAMPLES_STR_SIZE,
535 (LPARAM)(LPCSTR)szCurrencyUnit);
536
537 /* Save currency unit */
538 SetLocaleInfo(lcid, LOCALE_SCURRENCY, szCurrencyUnit);
539
540 return TRUE;
541 }
542
543 /* Property page dialog callback */
544 INT_PTR CALLBACK
545 CurrencyPageProc(HWND hwndDlg,
546 UINT uMsg,
547 WPARAM wParam,
548 LPARAM lParam)
549 {
550 PGLOBALDATA pGlobalData;
551
552 pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
553
554 switch (uMsg)
555 {
556 case WM_INITDIALOG:
557 pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam;
558 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
559
560 InitCurrencySymbols(hwndDlg, pGlobalData);
561 InitCurrencyPositiveFormats(hwndDlg, pGlobalData);
562 InitCurrencyNegativeFormats(hwndDlg, pGlobalData);
563 InitCurrencyDecimalSeparators(hwndDlg, pGlobalData);
564 InitCurrencyNumFracDigits(hwndDlg, pGlobalData);
565 InitCurrencyGroupSeparators(hwndDlg, pGlobalData);
566 InitDigitGroupCB(hwndDlg, pGlobalData);
567 UpdateExamples(hwndDlg, pGlobalData);
568 break;
569
570 case WM_COMMAND:
571 switch (LOWORD(wParam))
572 {
573 case IDC_CURRENCYSYMBOL:
574 case IDC_CURRENCYPOSVALUE:
575 case IDC_CURRENCYNEGVALUE:
576 case IDC_CURRENCYDECSEP:
577 case IDC_CURRENCYDECNUM:
578 case IDC_CURRENCYGRPSEP:
579 case IDC_CURRENCYGRPNUM:
580 if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE)
581 {
582 /* Set "Apply" button enabled */
583 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
584 }
585 }
586 break;
587
588 case WM_NOTIFY:
589 {
590 LPNMHDR lpnm = (LPNMHDR)lParam;
591 /* If push apply button */
592 if (lpnm->code == (UINT)PSN_APPLY)
593 {
594 if (!SetCurrencyDigNum(hwndDlg, pGlobalData->lcid))
595 break;
596
597 if (!SetCurrencyUnit(hwndDlg, pGlobalData->lcid))
598 break;
599
600 if (!SetPosCurrencySumFmt(hwndDlg, pGlobalData->lcid))
601 break;
602
603 if (!SetNegCurrencySumFmt(hwndDlg, pGlobalData->lcid))
604 break;
605
606 if (!SetCurrencySep(hwndDlg, pGlobalData->lcid))
607 break;
608
609 if (!SetCurrencyFracSymNum(hwndDlg, pGlobalData->lcid))
610 break;
611
612 if (!SetCurrencyFieldSep(hwndDlg, pGlobalData->lcid))
613 break;
614
615 UpdateExamples(hwndDlg, pGlobalData);
616 }
617 }
618 break;
619 }
620
621 return FALSE;
622 }
623
624 /* EOF */