GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-locale-utils.c
1 /********************************************************************\
2  * gnc-locale-utils.c -- locale functions *
3  * Copyright (C) 2000 Dave Peticolas <[email protected]> *
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 [email protected] *
21 \********************************************************************/
22 
23 #include "config.h"
24 
25 #include "gnc-locale-utils.h"
26 
27 #include <glib.h>
28 #include <glib/gi18n.h>
29 #include <stdlib.h> /* for mbstowcs() */
30 
31 static void
32 gnc_lconv_set_utf8 (char **p_value, char *default_value)
33 {
34  char *value = *p_value;
35  *p_value = NULL;
36 
37  if ((value == NULL) || (value[0] == 0))
38  value = default_value;
39 
40 #ifdef G_OS_WIN32
41  {
42  /* get number of resulting wide characters */
43  size_t count = mbstowcs (NULL, value, 0);
44  if (count > 0)
45  {
46  /* malloc and convert */
47  wchar_t *wvalue = g_malloc ((count + 1) * sizeof(wchar_t));
48  count = mbstowcs (wvalue, value, count + 1);
49  if (count > 0)
50  {
51  *p_value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
52  }
53  g_free (wvalue);
54  }
55  }
56 #else /* !G_OS_WIN32 */
57  *p_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
58 #endif
59 
60  if (*p_value == NULL)
61  {
62  // The g_locale_to_utf8 conversion failed. FIXME: Should we rather
63  // use an empty string instead of the default_value? Not sure.
64  *p_value = default_value;
65  }
66 }
67 
68 static void
69 gnc_lconv_set_char (char *p_value, char default_value)
70 {
71  if ((p_value != NULL) && (*p_value == CHAR_MAX))
72  *p_value = default_value;
73 }
74 
75 struct lconv *
76 gnc_localeconv (void)
77 {
78  static struct lconv lc;
79  static gboolean lc_set = FALSE;
80 
81  if (lc_set)
82  return &lc;
83 
84  lc = *localeconv();
85 
86  gnc_lconv_set_utf8(&lc.decimal_point, ".");
87  gnc_lconv_set_utf8(&lc.thousands_sep, ",");
88  gnc_lconv_set_utf8(&lc.grouping, "\003");
89  gnc_lconv_set_utf8(&lc.int_curr_symbol, "USD ");
90  gnc_lconv_set_utf8(&lc.currency_symbol, "$");
91  gnc_lconv_set_utf8(&lc.mon_decimal_point, ".");
92  gnc_lconv_set_utf8(&lc.mon_thousands_sep, ",");
93  gnc_lconv_set_utf8(&lc.mon_grouping, "\003");
94  gnc_lconv_set_utf8(&lc.negative_sign, "-");
95  gnc_lconv_set_utf8(&lc.positive_sign, "");
96 
97  gnc_lconv_set_char(&lc.frac_digits, 2);
98  gnc_lconv_set_char(&lc.int_frac_digits, 2);
99  gnc_lconv_set_char(&lc.p_cs_precedes, 1);
100  gnc_lconv_set_char(&lc.p_sep_by_space, 0);
101  gnc_lconv_set_char(&lc.n_cs_precedes, 1);
102  gnc_lconv_set_char(&lc.n_sep_by_space, 0);
103  gnc_lconv_set_char(&lc.p_sign_posn, 1);
104  gnc_lconv_set_char(&lc.n_sign_posn, 1);
105 
106  lc_set = TRUE;
107 
108  return &lc;
109 }
110 
111 const char *
112 gnc_locale_default_iso_currency_code (void)
113 {
114  static char *code = NULL;
115  struct lconv *lc;
116 
117  if (code)
118  return code;
119 
120  lc = gnc_localeconv ();
121 
122  code = g_strdup (lc->int_curr_symbol);
123 
124  /* The int_curr_symbol includes a space at the end! Note: you
125  * can't just change "USD " to "USD" in gnc_localeconv, because
126  * that is only used if int_curr_symbol was not defined in the
127  * current locale. If it was, it will have the space! */
128  g_strstrip (code);
129 
130  return code;
131 }
132 
133 /* Return the number of decimal places for this locale. */
134 int
135 gnc_locale_decimal_places (void)
136 {
137  static gboolean got_it = FALSE;
138  static int places;
139  struct lconv *lc;
140 
141  if (got_it)
142  return places;
143 
144  lc = gnc_localeconv();
145  places = lc->frac_digits;
146 
147  /* frac_digits is already initialized by gnc_localeconv, hopefully
148  * to a reasonable default. */
149  got_it = TRUE;
150 
151  return places;
152 }
153 
154 
155 static GList *locale_stack = NULL;
156 
157 void
158 gnc_push_locale (int category, const char *locale)
159 {
160  char *saved_locale;
161 
162  g_return_if_fail (locale != NULL);
163 
164 # ifdef G_OS_WIN32
165  /* On win32, setlocale() doesn't say anything useful. Use
166  glib's function instead. */
167  saved_locale = g_win32_getlocale();
168 # else
169  saved_locale = g_strdup(setlocale(category, NULL) ?
170  setlocale(category, NULL) : "C");
171 #endif
172  locale_stack = g_list_prepend (locale_stack, saved_locale);
173  setlocale (category, locale);
174 }
175 
176 void
177 gnc_pop_locale (int category)
178 {
179  char *saved_locale;
180  GList *node;
181 
182  g_return_if_fail (locale_stack != NULL);
183 
184  node = locale_stack;
185  saved_locale = node->data;
186 
187  setlocale (category, saved_locale);
188 
189  locale_stack = g_list_remove_link (locale_stack, node);
190  g_list_free_1 (node);
191  g_free (saved_locale);
192 }