xref: /reactos/dll/cpl/intl/currency.c (revision b09b5584)
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  * PROGRAMMERS:     Eric Kohl
24  *                  Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
25  */
26 
27 #include "intl.h"
28 
29 #define POSITIVE_EXAMPLE   L"123456789.00"
30 #define NEGATIVE_EXAMPLE   L"-123456789.00"
31 
32 
33 static VOID
34 UpdateExamples(HWND hwndDlg, PGLOBALDATA pGlobalData)
35 {
36     WCHAR szBuffer[MAX_FMT_SIZE];
37     CURRENCYFMTW CurrencyFormat;
38 
39     CurrencyFormat.NumDigits = pGlobalData->nCurrDigits;
40     CurrencyFormat.LeadingZero = pGlobalData->nNumLeadingZero;
41     CurrencyFormat.Grouping = GroupingFormats[pGlobalData->nCurrGrouping].nInteger;
42     CurrencyFormat.lpDecimalSep = pGlobalData->szCurrDecimalSep;
43     CurrencyFormat.lpThousandSep = pGlobalData->szCurrThousandSep;
44     CurrencyFormat.NegativeOrder = pGlobalData->nCurrNegFormat;
45     CurrencyFormat.PositiveOrder = pGlobalData->nCurrPosFormat;
46     CurrencyFormat.lpCurrencySymbol = pGlobalData->szCurrSymbol;
47 
48     /* Positive example */
49     GetCurrencyFormatW(pGlobalData->UserLCID, 0,
50                        POSITIVE_EXAMPLE,
51                        &CurrencyFormat, szBuffer, MAX_FMT_SIZE);
52 
53     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYPOSSAMPLE, WM_SETTEXT, 0, (LPARAM)szBuffer);
54 
55     /* Negative example */
56     GetCurrencyFormatW(pGlobalData->UserLCID, 0,
57                        NEGATIVE_EXAMPLE,
58                        &CurrencyFormat, szBuffer, MAX_FMT_SIZE);
59 
60     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYNEGSAMPLE, WM_SETTEXT, 0, (LPARAM)szBuffer);
61 }
62 
63 
64 static VOID
65 InitCurrencySymbols(HWND hwndDlg, PGLOBALDATA pGlobalData)
66 {
67     /* Limit text length */
68     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYSYMBOL,
69                         CB_LIMITTEXT,
70                         MAX_CURRSYMBOL - 1,
71                         0);
72 
73     /* Set currency symbols */
74     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYSYMBOL,
75                         CB_ADDSTRING,
76                         0,
77                         (LPARAM)pGlobalData->szCurrSymbol);
78 
79     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYSYMBOL,
80                         CB_SETCURSEL,
81                         0, /* Index */
82                         0);
83 }
84 
85 
86 static VOID
87 InitCurrencyPositiveFormats(HWND hwndDlg, PGLOBALDATA pGlobalData)
88 {
89     WCHAR szBuffer[MAX_FMT_SIZE];
90     CURRENCYFMTW cyFmt;
91     INT i;
92 
93     /* positive currency values */
94     cyFmt.NumDigits = pGlobalData->nCurrDigits;
95     cyFmt.LeadingZero = 0;
96     cyFmt.Grouping = 3;
97     cyFmt.lpDecimalSep = pGlobalData->szCurrDecimalSep;
98     cyFmt.lpThousandSep = pGlobalData->szCurrThousandSep;
99     cyFmt.lpCurrencySymbol = pGlobalData->szCurrSymbol;
100     cyFmt.NegativeOrder = 0;
101 
102     for (i = 0; i < 4; i++)
103     {
104         cyFmt.PositiveOrder = i;
105         GetCurrencyFormatW(pGlobalData->UserLCID, 0,
106                            L"1.1",
107                            &cyFmt, szBuffer, MAX_FMT_SIZE);
108 
109         SendDlgItemMessageW(hwndDlg, IDC_CURRENCYPOSVALUE,
110                             CB_INSERTSTRING,
111                             -1,
112                             (LPARAM)szBuffer);
113     }
114 
115     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYPOSVALUE,
116                         CB_SETCURSEL,
117                         pGlobalData->nCurrPosFormat,
118                         0);
119 }
120 
121 
122 static VOID
123 InitCurrencyNegativeFormats(HWND hwndDlg, PGLOBALDATA pGlobalData)
124 {
125     WCHAR szBuffer[MAX_FMT_SIZE];
126     CURRENCYFMTW cyFmt;
127     int i;
128 
129     /* negative currency values */
130     cyFmt.NumDigits = pGlobalData->nCurrDigits;
131     cyFmt.LeadingZero = 0;
132     cyFmt.Grouping = 3;
133     cyFmt.lpDecimalSep = pGlobalData->szCurrDecimalSep;
134     cyFmt.lpThousandSep = pGlobalData->szCurrThousandSep;
135     cyFmt.lpCurrencySymbol = pGlobalData->szCurrSymbol;
136     cyFmt.PositiveOrder = 0;
137 
138     for (i = 0; i < 16; i++)
139     {
140         cyFmt.NegativeOrder = i;
141         GetCurrencyFormatW(pGlobalData->UserLCID, 0,
142                            L"-1.1",
143                            &cyFmt, szBuffer, MAX_FMT_SIZE);
144 
145         SendDlgItemMessageW(hwndDlg, IDC_CURRENCYNEGVALUE,
146                             CB_INSERTSTRING,
147                             -1,
148                             (LPARAM)szBuffer);
149     }
150 
151     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYNEGVALUE,
152                         CB_SETCURSEL,
153                         pGlobalData->nCurrNegFormat,
154                         0);
155 }
156 
157 
158 static VOID
159 InitCurrencyDecimalSeparators(HWND hwndDlg, PGLOBALDATA pGlobalData)
160 {
161     /* Limit text length */
162     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYDECSEP,
163                         CB_LIMITTEXT,
164                         MAX_CURRDECIMALSEP - 1,
165                         0);
166 
167     /* Decimal separator */
168     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYDECSEP,
169                         CB_ADDSTRING,
170                         0,
171                         (LPARAM)pGlobalData->szCurrDecimalSep);
172 
173     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYDECSEP,
174                         CB_SETCURSEL,
175                         0, /* Index */
176                         0);
177 }
178 
179 
180 /* Initialize the number of fractional digits */
181 static VOID
182 InitCurrencyNumFracDigits(HWND hwndDlg, PGLOBALDATA pGlobalData)
183 {
184     WCHAR szBuffer[MAX_FMT_SIZE];
185     int i;
186 
187     /* Create standard list of fractional symbols */
188     for (i = 0; i < 10; i++)
189     {
190         szBuffer[0] = L'0' + i;
191         szBuffer[1] = 0;
192         SendDlgItemMessageW(hwndDlg, IDC_CURRENCYDECNUM,
193                             CB_ADDSTRING,
194                             0,
195                             (LPARAM)szBuffer);
196     }
197 
198     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYDECNUM,
199                         CB_SETCURSEL,
200                         pGlobalData->nCurrDigits,
201                         0);
202 }
203 
204 
205 /* Initialize the list of group separators */
206 static VOID
207 InitCurrencyGroupSeparators(HWND hwndDlg, PGLOBALDATA pGlobalData)
208 {
209     /* Limit text length */
210     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYGRPSEP,
211                         CB_LIMITTEXT,
212                         MAX_CURRTHOUSANDSEP - 1,
213                         0);
214 
215     /* Digit group separator */
216     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYGRPSEP,
217                         CB_ADDSTRING,
218                         0,
219                         (LPARAM)pGlobalData->szCurrThousandSep);
220 
221     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYGRPSEP,
222                         CB_SETCURSEL,
223                         0, /* Index */
224                         0);
225 }
226 
227 
228 static VOID
229 InitDigitGroupCB(HWND hwndDlg, PGLOBALDATA pGlobalData)
230 {
231     WCHAR szBuffer[MAX_FMT_SIZE];
232     CURRENCYFMTW cyFmt;
233     INT i;
234 
235     /* Digit grouping */
236     cyFmt.NumDigits = 0;
237     cyFmt.LeadingZero = 0;
238     cyFmt.lpDecimalSep = L"";
239     cyFmt.lpThousandSep = pGlobalData->szCurrThousandSep;
240     cyFmt.PositiveOrder = 0;
241     cyFmt.NegativeOrder = 0;
242     cyFmt.lpCurrencySymbol = L"";
243 
244     for (i = 0 ; i < MAX_GROUPINGFORMATS ; i++)
245     {
246        cyFmt.Grouping = GroupingFormats[i].nInteger;
247 
248        GetCurrencyFormatW(pGlobalData->UserLCID, 0,
249                           L"123456789",
250                           &cyFmt, szBuffer, MAX_FMT_SIZE);
251        SendDlgItemMessageW(hwndDlg, IDC_CURRENCYGRPNUM,
252                            CB_INSERTSTRING,
253                            -1,
254                            (LPARAM)szBuffer);
255     }
256 
257     SendDlgItemMessageW(hwndDlg, IDC_CURRENCYGRPNUM,
258                         CB_SETCURSEL,
259                         pGlobalData->nCurrGrouping,
260                         0);
261 }
262 
263 
264 static
265 BOOL
266 GetCurrencySetting(
267      HWND hwndDlg,
268      PGLOBALDATA pGlobalData)
269 {
270     WCHAR szCurrSymbol[MAX_CURRSYMBOL];
271     WCHAR szCurrDecimalSep[MAX_CURRDECIMALSEP];
272     WCHAR szCurrThousandSep[MAX_CURRTHOUSANDSEP];
273     INT nCurrPosFormat;
274     INT nCurrNegFormat;
275     INT nCurrDigits;
276     INT nCurrGrouping;
277 
278     /* Currency symbol */
279     GetSelectedComboBoxText(hwndDlg,
280                             IDC_CURRENCYSYMBOL,
281                             szCurrSymbol,
282                             MAX_CURRSYMBOL);
283 
284     if (szCurrSymbol[0] == L'\0')
285     {
286         /* TODO: Show error message */
287 
288         return FALSE;
289     }
290 
291     /* Positive Amount */
292     GetSelectedComboBoxIndex(hwndDlg,
293                              IDC_CURRENCYPOSVALUE,
294                              &nCurrPosFormat);
295 
296     /* Negative Amount */
297     GetSelectedComboBoxIndex(hwndDlg,
298                              IDC_CURRENCYNEGVALUE,
299                              &nCurrNegFormat);
300 
301     /* Decimal separator */
302     GetSelectedComboBoxText(hwndDlg,
303                             IDC_CURRENCYDECSEP,
304                             szCurrDecimalSep,
305                             MAX_CURRDECIMALSEP);
306 
307     if (szCurrDecimalSep[0] == L'\0')
308     {
309         /* TODO: Show error message */
310 
311         return FALSE;
312     }
313 
314     /* Number of fractional digits */
315     GetSelectedComboBoxIndex(hwndDlg,
316                              IDC_CURRENCYDECNUM,
317                              &nCurrDigits);
318 
319     /* Grouping symbol */
320     GetSelectedComboBoxText(hwndDlg,
321                             IDC_CURRENCYGRPSEP,
322                             szCurrThousandSep,
323                             MAX_CURRTHOUSANDSEP);
324 
325     if (szCurrThousandSep[0] == L'\0')
326     {
327         /* TODO: Show error message */
328 
329         return FALSE;
330     }
331 
332     /* Digit grouping */
333     GetSelectedComboBoxIndex(hwndDlg,
334                              IDC_CURRENCYGRPNUM,
335                              &nCurrGrouping);
336 
337     /* Store settings in global data */
338     wcscpy(pGlobalData->szCurrSymbol, szCurrSymbol);
339     pGlobalData->nCurrGrouping = nCurrGrouping;
340     wcscpy(pGlobalData->szCurrDecimalSep, szCurrDecimalSep);
341     wcscpy(pGlobalData->szCurrThousandSep, szCurrThousandSep);
342     pGlobalData->nCurrPosFormat = nCurrPosFormat;
343     pGlobalData->nCurrNegFormat = nCurrNegFormat;
344     pGlobalData->nCurrDigits = nCurrDigits;
345 
346     return TRUE;
347 }
348 
349 /* Property page dialog callback */
350 INT_PTR CALLBACK
351 CurrencyPageProc(HWND hwndDlg,
352                  UINT uMsg,
353                  WPARAM wParam,
354                  LPARAM lParam)
355 {
356     PGLOBALDATA pGlobalData;
357 
358     pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
359 
360     switch (uMsg)
361     {
362         case WM_INITDIALOG:
363             pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam;
364             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
365 
366             InitCurrencySymbols(hwndDlg, pGlobalData);
367             InitCurrencyPositiveFormats(hwndDlg, pGlobalData);
368             InitCurrencyNegativeFormats(hwndDlg, pGlobalData);
369             InitCurrencyDecimalSeparators(hwndDlg, pGlobalData);
370             InitCurrencyNumFracDigits(hwndDlg, pGlobalData);
371             InitCurrencyGroupSeparators(hwndDlg, pGlobalData);
372             InitDigitGroupCB(hwndDlg, pGlobalData);
373             UpdateExamples(hwndDlg, pGlobalData);
374             break;
375 
376         case WM_COMMAND:
377             switch (LOWORD(wParam))
378             {
379                 case IDC_CURRENCYSYMBOL:
380                 case IDC_CURRENCYPOSVALUE:
381                 case IDC_CURRENCYNEGVALUE:
382                 case IDC_CURRENCYDECSEP:
383                 case IDC_CURRENCYDECNUM:
384                 case IDC_CURRENCYGRPSEP:
385                 case IDC_CURRENCYGRPNUM:
386                     if (HIWORD(wParam) == CBN_SELCHANGE ||
387                         HIWORD(wParam) == CBN_EDITCHANGE)
388                     {
389                         /* Enable the Apply button */
390                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
391                     }
392             }
393             break;
394 
395         case WM_NOTIFY:
396             if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
397             {
398                 if (GetCurrencySetting(hwndDlg, pGlobalData))
399                 {
400                     pGlobalData->bUserLocaleChanged = TRUE;
401                     UpdateExamples(hwndDlg, pGlobalData);
402                 }
403             }
404             break;
405     }
406     return FALSE;
407 }
408 
409 /* EOF */
410