No issues found
1 /*
2 * Copyright (C) 2010 Nokia <ivan.frade@nokia.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #include <locale.h>
23 #include <string.h>
24
25 #include <glib.h>
26
27 #include "tracker-locale.h"
28
29 #ifdef HAVE_MEEGOTOUCH
30 #include "tracker-locale-gconfdbus.h"
31 #endif /* HAVE_MEEGOTOUCH */
32
33 /* Current locales in use. They will be stored in heap and available throughout
34 * the whole program execution, so will be reported as still reachable by Valgrind.
35 */
36 static gchar *current_locales[TRACKER_LOCALE_LAST];
37
38 static const gchar *locale_names[TRACKER_LOCALE_LAST] = {
39 "TRACKER_LOCALE_LANGUAGE",
40 "TRACKER_LOCALE_TIME",
41 "TRACKER_LOCALE_COLLATE",
42 "TRACKER_LOCALE_NUMERIC",
43 "TRACKER_LOCALE_MONETARY"
44 };
45
46 /* Already initialized? */
47 static gboolean initialized;
48
49 #if GLIB_CHECK_VERSION (2,31,0)
50 static GRecMutex locales_mutex;
51 #else
52 static GStaticRecMutex locales_mutex = G_STATIC_REC_MUTEX_INIT;
53 #endif
54
55 const gchar*
56 tracker_locale_get_name (guint i)
57 {
58 g_return_val_if_fail (i < TRACKER_LOCALE_LAST, NULL);
59 return locale_names[i];
60 }
61
62 void
63 tracker_locale_set (TrackerLocaleID id,
64 const gchar *value)
65 {
66 #if GLIB_CHECK_VERSION (2,31,0)
67 g_rec_mutex_lock (&locales_mutex);
68 #else
69 g_static_rec_mutex_lock (&locales_mutex);
70 #endif
71
72 if (current_locales[id]) {
73 g_debug ("Locale '%s' was changed from '%s' to '%s'",
74 locale_names[id],
75 current_locales[id],
76 value);
77 g_free (current_locales[id]);
78 } else {
79 g_debug ("Locale '%s' was set to '%s'",
80 locale_names[id],
81 value);
82 }
83
84 /* Store the new one */
85 current_locales[id] = g_strdup (value);
86
87 /* And also set the new one in the corresponding envvar */
88 switch (id) {
89 case TRACKER_LOCALE_LANGUAGE:
90 g_setenv ("LANG", value, TRUE);
91 break;
92 case TRACKER_LOCALE_TIME:
93 setlocale (LC_TIME, value);
94 break;
95 case TRACKER_LOCALE_COLLATE:
96 setlocale (LC_COLLATE, value);
97 break;
98 case TRACKER_LOCALE_NUMERIC:
99 setlocale (LC_NUMERIC, value);
100 break;
101 case TRACKER_LOCALE_MONETARY:
102 setlocale (LC_MONETARY, value);
103 break;
104 case TRACKER_LOCALE_LAST:
105 /* Make compiler happy */
106 g_warn_if_reached ();
107 break;
108 }
109
110 #if GLIB_CHECK_VERSION (2,31,0)
111 g_rec_mutex_unlock (&locales_mutex);
112 #else
113 g_static_rec_mutex_unlock (&locales_mutex);
114 #endif
115 }
116
117 void
118 tracker_locale_shutdown (void)
119 {
120 #ifdef HAVE_MEEGOTOUCH
121 tracker_locale_gconfdbus_shutdown ();
122 #endif /* HAVE_MEEGOTOUCH */
123 }
124
125 void
126 tracker_locale_init (void)
127 {
128 guint i;
129
130 #ifdef HAVE_MEEGOTOUCH
131 tracker_locale_gconfdbus_init ();
132 #endif /* HAVE_MEEGOTOUCH */
133
134 /* Initialize those not retrieved from gconf, or if not in meegotouch */
135 for (i = 0; i < TRACKER_LOCALE_LAST; i++) {
136 if (!current_locales[i]) {
137 const gchar *env_locale = NULL;
138
139 switch (i) {
140 case TRACKER_LOCALE_LANGUAGE:
141 env_locale = g_getenv ("LANG");
142 break;
143 case TRACKER_LOCALE_TIME:
144 env_locale = setlocale (LC_TIME, NULL);
145 break;
146 case TRACKER_LOCALE_COLLATE:
147 env_locale = setlocale (LC_COLLATE, NULL);
148 break;
149 case TRACKER_LOCALE_NUMERIC:
150 env_locale = setlocale (LC_NUMERIC, NULL);
151 break;
152 case TRACKER_LOCALE_MONETARY:
153 env_locale = setlocale (LC_MONETARY, NULL);
154 break;
155 case TRACKER_LOCALE_LAST:
156 /* Make compiler happy. The for loop avoids
157 * this from happening. */
158 break;
159 }
160
161 if (!env_locale) {
162 g_warning ("Locale '%d' is not set, defaulting to C locale", i);
163 tracker_locale_set (i, "C");
164 } else {
165 tracker_locale_set (i, env_locale);
166 }
167 }
168 }
169
170 /* So we're initialized */
171 initialized = TRUE;
172 }
173
174 gchar *
175 tracker_locale_get (TrackerLocaleID id)
176 {
177 gchar *locale;
178
179 g_return_val_if_fail (initialized, NULL);
180
181 #if GLIB_CHECK_VERSION (2,31,0)
182 g_rec_mutex_lock (&locales_mutex);
183 #else
184 g_static_rec_mutex_lock (&locales_mutex);
185 #endif
186
187 /* Always return a duplicated string, as the locale may change at any
188 * moment */
189 locale = g_strdup (current_locales[id]);
190
191 #if GLIB_CHECK_VERSION (2,31,0)
192 g_rec_mutex_unlock (&locales_mutex);
193 #else
194 g_static_rec_mutex_unlock (&locales_mutex);
195 #endif
196
197 return locale;
198 }
199
200 gpointer
201 tracker_locale_notify_add (TrackerLocaleID id,
202 TrackerLocaleNotifyFunc func,
203 gpointer user_data,
204 GFreeFunc destroy_notify)
205 {
206 #ifdef HAVE_MEEGOTOUCH
207 return tracker_locale_gconfdbus_notify_add (id, func, user_data, destroy_notify);
208 #else
209 /* If not using gconf locales, this is a no-op... */
210 return NULL;
211 #endif /* HAVE_MEEGOTOUCH */
212 }
213
214 void
215 tracker_locale_notify_remove (gpointer notification_id)
216 {
217 #ifdef HAVE_MEEGOTOUCH
218 return tracker_locale_gconfdbus_notify_remove (notification_id);
219 #else
220 /* If not using gconf locales, this is a no-op... */
221 #endif /* HAVE_MEEGOTOUCH */
222 }