Branch data Line data Source code
1 : : /********************************************************************\
2 : : * gnc-locale-utils.c -- locale functions *
3 : : * Copyright (C) 2000 Dave Peticolas <dave@krondo.com> *
4 : : * *
5 : : * This program is free software; you can redistribute it and/or *
6 : : * modify it under the terms of the GNU General Public License as *
7 : : * published by the Free Software Foundation; either version 2 of *
8 : : * the License, or (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, contact: *
17 : : * *
18 : : * Free Software Foundation Voice: +1-617-542-5942 *
19 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
20 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
21 : : \********************************************************************/
22 : :
23 : : #include <config.h>
24 : :
25 : : #include "gnc-locale-utils.h"
26 : :
27 : : #include <glib.h>
28 : : #include <glib/gi18n.h>
29 : :
30 : : #ifdef G_OS_WIN32
31 : : #include <windows.h>
32 : :
33 : : static void
34 : : gnc_lconv_set_utf8 (char **p_value, wchar_t *w_value, const char *default_value)
35 : : {
36 : : g_return_if_fail (p_value != NULL);
37 : : if (w_value && *w_value)
38 : : *p_value = g_utf16_to_utf8 (w_value, -1, NULL, NULL, NULL);
39 : : else
40 : : *p_value = g_strdup (default_value);
41 : : }
42 : :
43 : : static LPCWSTR
44 : : get_locale_name ()
45 : : {
46 : : char* locale = setlocale(LC_MONETARY, NULL);
47 : : int len = 0;
48 : : len = strchr (locale, '.') - locale;
49 : : locale[2] = '-';
50 : : wchar_t *wlocale = g_utf8_to_utf16 (locale, len, NULL, NULL, NULL);
51 : : if (IsValidLocaleName(wlocale))
52 : : return wlocale;
53 : : return LOCALE_NAME_USER_DEFAULT;
54 : : }
55 : :
56 : : #define BUFSIZE 10 //Max size used by LOCALE_SGROUPING.
57 : : static wchar_t*
58 : : get_lconv_wide_val (LCTYPE lctype)
59 : : {
60 : : static wchar_t buffer[BUFSIZE];
61 : : LPCWSTR locale = get_locale_name ();
62 : : memset (buffer, 0, BUFSIZE * sizeof(wchar_t));
63 : : int count = GetLocaleInfoEx (locale, lctype, buffer, BUFSIZE);
64 : : if (!count)
65 : : {
66 : : g_error("GetLocaleInfo failed for %ld, %ld", lctype, GetLastError());
67 : : return NULL;
68 : : }
69 : : if (lctype == LOCALE_SGROUPING || lctype == LOCALE_SMONGROUPING)
70 : : {
71 : : buffer[0] &= 0x0f; // The standard localeconv is a single uint8
72 : : buffer[1] = '\0';
73 : : }
74 : : return buffer;
75 : : }
76 : : #else
77 : : static void
78 : 340 : gnc_lconv_set_utf8 (char **p_value, char *default_value)
79 : : {
80 : 340 : char *value = *p_value;
81 : 340 : *p_value = NULL;
82 : :
83 : 340 : if ((value == NULL) || (value[0] == 0))
84 : 306 : value = default_value;
85 : :
86 : 340 : *p_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
87 : :
88 : 340 : if (*p_value == NULL)
89 : : {
90 : : // The g_locale_to_utf8 conversion failed. FIXME: Should we rather
91 : : // use an empty string instead of the default_value? Not sure.
92 : 0 : *p_value = default_value;
93 : : }
94 : 340 : }
95 : :
96 : : #endif
97 : : static void
98 : 272 : gnc_lconv_set_char (char *p_value, char default_value)
99 : : {
100 : 272 : if ((p_value != NULL) && (*p_value == CHAR_MAX))
101 : 272 : *p_value = default_value;
102 : 272 : }
103 : :
104 : : struct lconv *
105 : 35347 : gnc_localeconv (void)
106 : : {
107 : : static struct lconv lc;
108 : : static gboolean lc_set = FALSE;
109 : :
110 : 35347 : if (lc_set)
111 : 35313 : return &lc;
112 : :
113 : 34 : lc = *localeconv();
114 : : #ifdef G_OS_WIN32
115 : : gnc_lconv_set_utf8(&lc.decimal_point,
116 : : get_lconv_wide_val (LOCALE_SDECIMAL), ".");
117 : : gnc_lconv_set_utf8(&lc.thousands_sep,
118 : : get_lconv_wide_val (LOCALE_STHOUSAND),",");
119 : : gnc_lconv_set_utf8(&lc.grouping,
120 : : get_lconv_wide_val (LOCALE_SGROUPING), "\003");
121 : : gnc_lconv_set_utf8(&lc.int_curr_symbol,
122 : : get_lconv_wide_val (LOCALE_SINTLSYMBOL), "USD ");
123 : : gnc_lconv_set_utf8(&lc.currency_symbol,
124 : : get_lconv_wide_val (LOCALE_SCURRENCY), "$");
125 : : gnc_lconv_set_utf8(&lc.mon_decimal_point,
126 : : get_lconv_wide_val (LOCALE_SMONDECIMALSEP), ".");
127 : : gnc_lconv_set_utf8(&lc.mon_thousands_sep,
128 : : get_lconv_wide_val (LOCALE_SMONTHOUSANDSEP), ",");
129 : : gnc_lconv_set_utf8(&lc.mon_grouping,
130 : : get_lconv_wide_val (LOCALE_SMONGROUPING), "\003");
131 : : gnc_lconv_set_utf8(&lc.negative_sign,
132 : : get_lconv_wide_val (LOCALE_SNEGATIVESIGN), "-");
133 : : gnc_lconv_set_utf8(&lc.positive_sign,
134 : : get_lconv_wide_val (LOCALE_SPOSITIVESIGN), "");
135 : : #else
136 : 34 : gnc_lconv_set_utf8(&lc.decimal_point, ".");
137 : 34 : gnc_lconv_set_utf8(&lc.thousands_sep, ",");
138 : 34 : gnc_lconv_set_utf8(&lc.grouping, "\003");
139 : 34 : gnc_lconv_set_utf8(&lc.int_curr_symbol, "USD ");
140 : 34 : gnc_lconv_set_utf8(&lc.currency_symbol, "$");
141 : 34 : gnc_lconv_set_utf8(&lc.mon_decimal_point, ".");
142 : 34 : gnc_lconv_set_utf8(&lc.mon_thousands_sep, ",");
143 : 34 : gnc_lconv_set_utf8(&lc.mon_grouping, "\003");
144 : 34 : gnc_lconv_set_utf8(&lc.negative_sign, "-");
145 : 34 : gnc_lconv_set_utf8(&lc.positive_sign, "");
146 : : #endif
147 : 34 : gnc_lconv_set_char(&lc.frac_digits, 2);
148 : 34 : gnc_lconv_set_char(&lc.int_frac_digits, 2);
149 : 34 : gnc_lconv_set_char(&lc.p_cs_precedes, 1);
150 : 34 : gnc_lconv_set_char(&lc.p_sep_by_space, 0);
151 : 34 : gnc_lconv_set_char(&lc.n_cs_precedes, 1);
152 : 34 : gnc_lconv_set_char(&lc.n_sep_by_space, 0);
153 : 34 : gnc_lconv_set_char(&lc.p_sign_posn, 1);
154 : 34 : gnc_lconv_set_char(&lc.n_sign_posn, 1);
155 : :
156 : 34 : lc_set = TRUE;
157 : :
158 : 34 : return &lc;
159 : : }
160 : :
161 : : const char *
162 : 1533 : gnc_locale_default_iso_currency_code (void)
163 : : {
164 : : static char *code = NULL;
165 : : struct lconv *lc;
166 : :
167 : 1533 : if (code)
168 : 1505 : return code;
169 : :
170 : 28 : lc = gnc_localeconv ();
171 : :
172 : 28 : code = g_strdup (lc->int_curr_symbol);
173 : :
174 : : /* The int_curr_symbol includes a space at the end! Note: you
175 : : * can't just change "USD " to "USD" in gnc_localeconv, because
176 : : * that is only used if int_curr_symbol was not defined in the
177 : : * current locale. If it was, it will have the space! */
178 : 28 : g_strstrip (code);
179 : :
180 : 28 : return code;
181 : : }
182 : :
183 : : /* Return the number of decimal places for this locale. */
184 : : int
185 : 0 : gnc_locale_decimal_places (void)
186 : : {
187 : : static gboolean got_it = FALSE;
188 : : static int places;
189 : : struct lconv *lc;
190 : :
191 : 0 : if (got_it)
192 : 0 : return places;
193 : :
194 : 0 : lc = gnc_localeconv();
195 : 0 : places = lc->frac_digits;
196 : :
197 : : /* frac_digits is already initialized by gnc_localeconv, hopefully
198 : : * to a reasonable default. */
199 : 0 : got_it = TRUE;
200 : :
201 : 0 : return places;
202 : : }
203 : :
204 : 2853 : gchar *gnc_locale_name (void)
205 : : {
206 : : # ifdef G_OS_WIN32
207 : : return g_win32_getlocale();
208 : : # else /* !G_OS_WIN32 */
209 : 5706 : return g_strdup (setlocale(LC_MONETARY, NULL));
210 : : # endif /* G_OS_WIN32 */
211 : :
212 : : }
|