fixed dia_image_rgb_data() for non-alpha images
[dia.git] / lib / intl.c
blob53e1b40857762b49262cd47724e7dce736e70b95
1 #include <config.h>
3 #include "intl.h"
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
9 #ifndef GNOME
10 /* taken from gnome-libs/libgnome/gnome-i18n.c ... */
11 /* FIXME: is this still necessary, or has gtk2.0 swallowed this ? */
13 static GHashTable *alias_table = NULL;
15 /*read an alias file for the locales*/
16 static void
17 read_aliases (char *file)
19 FILE *fp;
20 char buf[256];
22 if (!alias_table)
23 alias_table = g_hash_table_new (g_str_hash, g_str_equal);
24 fp = fopen (file,"r");
25 if (!fp)
26 return;
27 while (fgets (buf,256,fp)) {
28 char *p;
29 g_strstrip(buf);
30 if(buf[0]=='#' || buf[0]=='\0')
31 continue;
32 p = strtok(buf,"\t ");
33 if(!p) continue;
34 p = strtok(NULL,"\t ");
35 if(!p) continue;
36 g_hash_table_insert (alias_table, g_strdup(buf), g_strdup(p));
38 fclose (fp);
41 static void
42 free_alias_cb(gpointer key, gpointer value, gpointer user_data)
44 g_free(key);
45 g_free(value);
48 static void
49 free_alias_table(void)
51 if (!alias_table)
52 return;
53 g_hash_table_foreach(alias_table, free_alias_cb, NULL);
54 g_hash_table_destroy(alias_table);
55 alias_table = NULL;
58 /*return the un-aliased language as a newly allocated string*/
59 static char *
60 unalias_lang (char *lang)
62 char *p;
64 if(!alias_table) {
65 read_aliases ("/usr/share/locale/locale.alias");
66 read_aliases ("/usr/local/share/locale/locale.alias");
67 read_aliases ("/usr/lib/X11/locale/locale.alias");
68 read_aliases ("/usr/openwin/lib/locale/locale.alias");
70 while((p=g_hash_table_lookup(alias_table,lang)) && strcmp(p, lang))
71 lang = p;
72 return lang;
75 /* Mask for components of locale spec. The ordering here is from
76 * least significant to most significant
78 enum
80 COMPONENT_CODESET = 1 << 0,
81 COMPONENT_TERRITORY = 1 << 1,
82 COMPONENT_MODIFIER = 1 << 2
85 /* Break an X/Open style locale specification into components
87 static guint
88 explode_locale (const gchar *locale,
89 gchar **language,
90 gchar **territory,
91 gchar **codeset,
92 gchar **modifier)
94 const gchar *uscore_pos;
95 const gchar *at_pos;
96 const gchar *dot_pos;
98 guint mask = 0;
100 uscore_pos = strchr (locale, '_');
101 dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
102 at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
104 if (at_pos) {
105 mask |= COMPONENT_MODIFIER;
106 *modifier = g_strdup (at_pos);
107 } else
108 at_pos = locale + strlen (locale);
110 if (dot_pos) {
111 mask |= COMPONENT_CODESET;
112 *codeset = g_new (gchar, 1 + at_pos - dot_pos);
113 strncpy (*codeset, dot_pos, at_pos - dot_pos);
114 (*codeset)[at_pos - dot_pos] = '\0';
115 } else
116 dot_pos = at_pos;
118 if (uscore_pos) {
119 mask |= COMPONENT_TERRITORY;
120 *territory = g_new (gchar, 1 + dot_pos - uscore_pos);
121 strncpy (*territory, uscore_pos, dot_pos - uscore_pos);
122 (*territory)[dot_pos - uscore_pos] = '\0';
123 } else
124 uscore_pos = dot_pos;
126 *language = g_new (gchar, 1 + uscore_pos - locale);
127 strncpy (*language, locale, uscore_pos - locale);
128 (*language)[uscore_pos - locale] = '\0';
130 return mask;
134 * Compute all interesting variants for a given locale name -
135 * by stripping off different components of the value.
137 * For simplicity, we assume that the locale is in
138 * X/Open format: language[_territory][.codeset][@modifier]
140 * TODO: Extend this to handle the CEN format (see the GNUlibc docs)
141 * as well. We could just copy the code from glibc wholesale
142 * but it is big, ugly, and complicated, so I'm reluctant
143 * to do so when this should handle 99% of the time...
145 static GList *
146 compute_locale_variants (const gchar *locale)
148 GList *retval = NULL;
150 gchar *language;
151 gchar *territory;
152 gchar *codeset;
153 gchar *modifier;
155 guint mask;
156 guint i;
158 g_return_val_if_fail (locale != NULL, NULL);
160 mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
162 /* Iterate through all possible combinations, from least attractive
163 * to most attractive.
165 for (i=0; i<=mask; i++)
166 if ((i & ~mask) == 0)
168 gchar *val = g_strconcat(language,
169 (i & COMPONENT_TERRITORY) ? territory : "",
170 (i & COMPONENT_CODESET) ? codeset : "",
171 (i & COMPONENT_MODIFIER) ? modifier : "",
172 NULL);
173 retval = g_list_prepend (retval, val);
176 g_free (language);
177 if (mask & COMPONENT_CODESET)
178 g_free (codeset);
179 if (mask & COMPONENT_TERRITORY)
180 g_free (territory);
181 if (mask & COMPONENT_MODIFIER)
182 g_free (modifier);
184 return retval;
187 /* The following is (partly) taken from the gettext package.
188 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
190 static const gchar *
191 guess_category_value (const gchar *categoryname)
193 const gchar *retval;
195 /* The highest priority value is the `LANGUAGE' environment
196 variable. This is a GNU extension. */
197 retval = getenv ("LANGUAGE");
198 if (retval != NULL && retval[0] != '\0')
199 return retval;
201 /* `LANGUAGE' is not set. So we have to proceed with the POSIX
202 methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
203 systems this can be done by the `setlocale' function itself. */
205 /* Setting of LC_ALL overwrites all other. */
206 retval = getenv ("LC_ALL");
207 if (retval != NULL && retval[0] != '\0')
208 return retval;
210 /* Next comes the name of the desired category. */
211 retval = getenv (categoryname);
212 if (retval != NULL && retval[0] != '\0')
213 return retval;
215 /* Last possibility is the LANG environment variable. */
216 retval = getenv ("LANG");
217 if (retval != NULL && retval[0] != '\0')
218 return retval;
220 return NULL;
223 static GList *
224 get_language_list(const gchar *category_name)
226 GList *list = NULL;
227 gint c_locale_defined= FALSE;
229 const gchar *category_value;
230 gchar *category_memory, *orig_category_memory;
232 if (!category_name)
233 category_name= "LC_ALL";
235 category_value = guess_category_value (category_name);
236 if (! category_value)
237 category_value = "C";
238 orig_category_memory = category_memory =
239 g_malloc (strlen (category_value)+1);
241 while (category_value[0] != '\0') {
242 while (category_value[0] != '\0' && category_value[0] == ':')
243 ++category_value;
245 if (category_value[0] != '\0') {
246 char *cp= category_memory;
248 while (category_value[0] != '\0' && category_value[0] != ':')
249 *category_memory++= *category_value++;
251 category_memory[0]= '\0';
252 category_memory++;
254 cp = unalias_lang(cp);
256 if (strcmp (cp, "C") == 0)
257 c_locale_defined= TRUE;
259 list= g_list_concat (list, compute_locale_variants (cp));
263 g_free (orig_category_memory);
265 if (!c_locale_defined)
266 list= g_list_append (list, "C");
268 return list;
271 #endif
273 const GList *
274 intl_get_language_list(void)
276 static const GList *list = NULL;
278 if (!list) {
279 #ifdef GNOME
280 list = gnome_i18n_get_language_list("LC_MESSAGES");
281 #else
282 list = get_language_list("LC_MESSAGES");
283 free_alias_table();
284 #endif
286 return list;
289 /* low numbers are better */
291 intl_score_locale(const gchar *locale)
293 const GList *list = intl_get_language_list();
294 const GList *tmp;
295 int i;
297 /* NULL is same as C locale */
298 if (!locale)
299 return g_list_length((GList*)list) - 1;
300 for (tmp = list, i = 0; tmp; tmp = tmp->next, i++)
301 if (!strcmp((const char *)tmp->data, locale))
302 break;
303 if (!tmp) /* not found */
304 i = G_MAXINT;
305 return i;