GnuCash fec5643+
Loading...
Searching...
No Matches
gnc-locale-utils.c
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
33static void
34gnc_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
43static LPCWSTR
44get_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.
57static wchar_t*
58get_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
77static void
78gnc_lconv_set_utf8 (char **p_value, char *default_value)
79{
80 char *value = *p_value;
81 *p_value = NULL;
82
83 if ((value == NULL) || (value[0] == 0))
84 value = default_value;
85
86 *p_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
87
88 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 *p_value = default_value;
93 }
94}
95
96#endif
97static void
98gnc_lconv_set_char (char *p_value, char default_value)
99{
100 if ((p_value != NULL) && (*p_value == CHAR_MAX))
101 *p_value = default_value;
102}
103
104struct lconv *
105gnc_localeconv (void)
106{
107 static struct lconv lc;
108 static gboolean lc_set = FALSE;
109
110 if (lc_set)
111 return &lc;
112
113 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 gnc_lconv_set_utf8(&lc.decimal_point, ".");
137 gnc_lconv_set_utf8(&lc.thousands_sep, ",");
138 gnc_lconv_set_utf8(&lc.grouping, "\003");
139 gnc_lconv_set_utf8(&lc.int_curr_symbol, "USD ");
140 gnc_lconv_set_utf8(&lc.currency_symbol, "$");
141 gnc_lconv_set_utf8(&lc.mon_decimal_point, ".");
142 gnc_lconv_set_utf8(&lc.mon_thousands_sep, ",");
143 gnc_lconv_set_utf8(&lc.mon_grouping, "\003");
144 gnc_lconv_set_utf8(&lc.negative_sign, "-");
145 gnc_lconv_set_utf8(&lc.positive_sign, "");
146#endif
147 gnc_lconv_set_char(&lc.frac_digits, 2);
148 gnc_lconv_set_char(&lc.int_frac_digits, 2);
149 gnc_lconv_set_char(&lc.p_cs_precedes, 1);
150 gnc_lconv_set_char(&lc.p_sep_by_space, 0);
151 gnc_lconv_set_char(&lc.n_cs_precedes, 1);
152 gnc_lconv_set_char(&lc.n_sep_by_space, 0);
153 gnc_lconv_set_char(&lc.p_sign_posn, 1);
154 gnc_lconv_set_char(&lc.n_sign_posn, 1);
155
156 lc_set = TRUE;
157
158 return &lc;
159}
160
161const char *
162gnc_locale_default_iso_currency_code (void)
163{
164 static char *code = NULL;
165 struct lconv *lc;
166
167 if (code)
168 return code;
169
170 lc = gnc_localeconv ();
171
172 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 g_strstrip (code);
179
180 return code;
181}
182
183/* Return the number of decimal places for this locale. */
184int
185gnc_locale_decimal_places (void)
186{
187 static gboolean got_it = FALSE;
188 static int places;
189 struct lconv *lc;
190
191 if (got_it)
192 return places;
193
194 lc = gnc_localeconv();
195 places = lc->frac_digits;
196
197 /* frac_digits is already initialized by gnc_localeconv, hopefully
198 * to a reasonable default. */
199 got_it = TRUE;
200
201 return places;
202}
203
204gchar *gnc_locale_name (void)
205{
206# ifdef G_OS_WIN32
207 return g_win32_getlocale();
208# else /* !G_OS_WIN32 */
209 return g_strdup (setlocale(LC_MONETARY, NULL));
210# endif /* G_OS_WIN32 */
211
212}