aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llfindlocale.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:50 -0500
committerJacek Antonelli2008-08-15 23:45:50 -0500
commit2a4dea528f670b9bb1f77ef27a8a1dd16603d114 (patch)
tree95c68e362703c9099d571ecbdc6142b1cda1e005 /linden/indra/llcommon/llfindlocale.cpp
parentSecond Life viewer sources 1.20.6 (diff)
downloadmeta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.zip
meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.gz
meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.bz2
meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.xz
Second Life viewer sources 1.20.7
Diffstat (limited to 'linden/indra/llcommon/llfindlocale.cpp')
-rw-r--r--linden/indra/llcommon/llfindlocale.cpp525
1 files changed, 525 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llfindlocale.cpp b/linden/indra/llcommon/llfindlocale.cpp
new file mode 100644
index 0000000..47da974
--- /dev/null
+++ b/linden/indra/llcommon/llfindlocale.cpp
@@ -0,0 +1,525 @@
1/**
2 * @file llfindlocale.cpp
3 * @brief Detect system language setting
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 2008, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32/* Yes, this was originally C code. */
33
34#include "linden_common.h"
35
36#include <stdlib.h>
37#include <string.h>
38#include <ctype.h>
39
40#ifdef WIN32
41#include <windows.h>
42#include <winnt.h>
43#endif
44
45#include "llfindlocale.h"
46
47static int
48is_lcchar(const int c) {
49 return isalnum(c);
50}
51
52static void
53lang_country_variant_from_envstring(const char *str,
54 char **lang,
55 char **country,
56 char **variant) {
57 int end = 0;
58 int start;
59
60 /* get lang, if any */
61 start = end;
62 while (is_lcchar(str[end])) {
63 ++end;
64 }
65 if (start != end) {
66 int i;
67 int len = end - start;
68 char *s = (char*)malloc(len + 1);
69 for (i=0; i<len; ++i) {
70 s[i] = tolower(str[start + i]);
71 }
72 s[i] = '\0';
73 *lang = s;
74 } else {
75 *lang = NULL;
76 }
77
78 if (str[end] && str[end]!=':') { /* not at end of str */
79 ++end;
80 }
81
82 /* get country, if any */
83 start = end;
84 while (is_lcchar(str[end])) {
85 ++end;
86 }
87 if (start != end) {
88 int i;
89 int len = end - start;
90 char *s = (char*)malloc(len + 1);
91 for (i=0; i<len; ++i) {
92 s[i] = toupper(str[start + i]);
93 }
94 s[i] = '\0';
95 *country = s;
96 } else {
97 *country = NULL;
98 }
99
100 if (str[end] && str[end]!=':') { /* not at end of str */
101 ++end;
102 }
103
104 /* get variant, if any */
105 start = end;
106 while (str[end] && str[end]!=':') {
107 ++end;
108 }
109 if (start != end) {
110 int i;
111 int len = end - start;
112 char *s = (char*)malloc(len + 1);
113 for (i=0; i<len; ++i) {
114 s[i] = str[start + i];
115 }
116 s[i] = '\0';
117 *variant = s;
118 } else {
119 *variant = NULL;
120 }
121}
122
123
124static int
125accumulate_locstring(const char *str, FL_Locale *l) {
126 char *lang = NULL;
127 char *country = NULL;
128 char *variant = NULL;
129 if (str) {
130 lang_country_variant_from_envstring(str, &lang, &country, &variant);
131 if (lang) {
132 l->lang = lang;
133 l->country = country;
134 l->variant = variant;
135 return 1;
136 }
137 }
138 free(lang); free(country); free(variant);
139 return 0;
140}
141
142
143static int
144accumulate_env(const char *name, FL_Locale *l) {
145 char *env;
146 char *lang = NULL;
147 char *country = NULL;
148 char *variant = NULL;
149 env = getenv(name);
150 if (env) {
151 return accumulate_locstring(env, l);
152 }
153 free(lang); free(country); free(variant);
154 return 0;
155}
156
157
158static void
159canonise_fl(FL_Locale *l) {
160 /* this function fixes some common locale-specifying mistakes */
161 /* en_UK -> en_GB */
162 if (l->lang && 0 == strcmp(l->lang, "en")) {
163 if (l->country && 0 == strcmp(l->country, "UK")) {
164 free((void*)l->country);
165 l->country = strdup("GB");
166 }
167 }
168 /* ja_JA -> ja_JP */
169 if (l->lang && 0 == strcmp(l->lang, "ja")) {
170 if (l->country && 0 == strcmp(l->country, "JA")) {
171 free((void*)l->country);
172 l->country = strdup("JP");
173 }
174 }
175}
176
177
178#ifdef WIN32
179#include <stdio.h>
180#define ML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##pn##_##sn)
181#define MLN(pn) MAKELANGID(LANG_##pn, SUBLANG_DEFAULT)
182#define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn)
183typedef struct {
184 LANGID id;
185 char* code;
186} IDToCode;
187static const IDToCode both_to_code[] = {
188 {ML(ENGLISH,US), "en_US.ISO_8859-1"},
189 {ML(ENGLISH,CAN), "en_CA"}, /* english / canadian */
190 {ML(ENGLISH,UK), "en_GB"},
191 {ML(ENGLISH,EIRE), "en_IE"},
192 {ML(ENGLISH,AUS), "en_AU"},
193 {MLN(GERMAN), "de_DE"},
194 {MLN(SPANISH), "es_ES"},
195 {ML(SPANISH,MEXICAN), "es_MX"},
196 {MLN(FRENCH), "fr_FR"},
197 {ML(FRENCH,CANADIAN), "fr_CA"},
198 {ML(FRENCH,BELGIAN), "fr_BE"}, /* ? */
199 {ML(DUTCH,BELGIAN), "nl_BE"}, /* ? */
200 {ML(PORTUGUESE,BRAZILIAN), "pt_BR"},
201 {MLN(PORTUGUESE), "pt_PT"},
202 {MLN(SWEDISH), "sv_SE"},
203 {ML(CHINESE,HONGKONG), "zh_HK"},
204 /* these are machine-generated and not yet verified */
205 {RML(AFRIKAANS,DEFAULT), "af_ZA"},
206 {RML(ALBANIAN,DEFAULT), "sq_AL"},
207 {RML(ARABIC,ARABIC_ALGERIA), "ar_DZ"},
208 {RML(ARABIC,ARABIC_BAHRAIN), "ar_BH"},
209 {RML(ARABIC,ARABIC_EGYPT), "ar_EG"},
210 {RML(ARABIC,ARABIC_IRAQ), "ar_IQ"},
211 {RML(ARABIC,ARABIC_JORDAN), "ar_JO"},
212 {RML(ARABIC,ARABIC_KUWAIT), "ar_KW"},
213 {RML(ARABIC,ARABIC_LEBANON), "ar_LB"},
214 {RML(ARABIC,ARABIC_LIBYA), "ar_LY"},
215 {RML(ARABIC,ARABIC_MOROCCO), "ar_MA"},
216 {RML(ARABIC,ARABIC_OMAN), "ar_OM"},
217 {RML(ARABIC,ARABIC_QATAR), "ar_QA"},
218 {RML(ARABIC,ARABIC_SAUDI_ARABIA), "ar_SA"},
219 {RML(ARABIC,ARABIC_SYRIA), "ar_SY"},
220 {RML(ARABIC,ARABIC_TUNISIA), "ar_TN"},
221 {RML(ARABIC,ARABIC_UAE), "ar_AE"},
222 {RML(ARABIC,ARABIC_YEMEN), "ar_YE"},
223 {RML(ARMENIAN,DEFAULT), "hy_AM"},
224 {RML(AZERI,AZERI_CYRILLIC), "az_AZ"},
225 {RML(AZERI,AZERI_LATIN), "az_AZ"},
226 {RML(BASQUE,DEFAULT), "eu_ES"},
227 {RML(BELARUSIAN,DEFAULT), "be_BY"},
228/*{RML(BRETON,DEFAULT), "br_FR"},*/
229 {RML(BULGARIAN,DEFAULT), "bg_BG"},
230 {RML(CATALAN,DEFAULT), "ca_ES"},
231 {RML(CHINESE,CHINESE_HONGKONG), "zh_HK"},
232 {RML(CHINESE,CHINESE_MACAU), "zh_MO"},
233 {RML(CHINESE,CHINESE_SIMPLIFIED), "zh_CN"},
234 {RML(CHINESE,CHINESE_SINGAPORE), "zh_SG"},
235 {RML(CHINESE,CHINESE_TRADITIONAL), "zh_TW"},
236/*{RML(CORNISH,DEFAULT), "kw_GB"},*/
237 {RML(CZECH,DEFAULT), "cs_CZ"},
238 {RML(DANISH,DEFAULT), "da_DK"},
239 {RML(DUTCH,DUTCH), "nl_NL"},
240 {RML(DUTCH,DUTCH_BELGIAN), "nl_BE"},
241/*{RML(DUTCH,DUTCH_SURINAM), "nl_SR"},*/
242 {RML(ENGLISH,ENGLISH_AUS), "en_AU"},
243 {RML(ENGLISH,ENGLISH_BELIZE), "en_BZ"},
244 {RML(ENGLISH,ENGLISH_CAN), "en_CA"},
245 {RML(ENGLISH,ENGLISH_CARIBBEAN), "en_CB"},
246 {RML(ENGLISH,ENGLISH_EIRE), "en_IE"},
247 {RML(ENGLISH,ENGLISH_JAMAICA), "en_JM"},
248 {RML(ENGLISH,ENGLISH_NZ), "en_NZ"},
249 {RML(ENGLISH,ENGLISH_PHILIPPINES), "en_PH"},
250 {RML(ENGLISH,ENGLISH_SOUTH_AFRICA), "en_ZA"},
251 {RML(ENGLISH,ENGLISH_TRINIDAD), "en_TT"},
252 {RML(ENGLISH,ENGLISH_UK), "en_GB"},
253 {RML(ENGLISH,ENGLISH_US), "en_US"},
254 {RML(ENGLISH,ENGLISH_ZIMBABWE), "en_ZW"},
255/*{RML(ESPERANTO,DEFAULT), "eo_"},*/
256 {RML(ESTONIAN,DEFAULT), "et_EE"},
257 {RML(FAEROESE,DEFAULT), "fo_FO"},
258 {RML(FARSI,DEFAULT), "fa_IR"},
259 {RML(FINNISH,DEFAULT), "fi_FI"},
260 {RML(FRENCH,FRENCH), "fr_FR"},
261 {RML(FRENCH,FRENCH_BELGIAN), "fr_BE"},
262 {RML(FRENCH,FRENCH_CANADIAN), "fr_CA"},
263 {RML(FRENCH,FRENCH_LUXEMBOURG), "fr_LU"},
264 {RML(FRENCH,FRENCH_MONACO), "fr_MC"},
265 {RML(FRENCH,FRENCH_SWISS), "fr_CH"},
266/*{RML(GAELIC,GAELIC), "ga_IE"},*/
267/*{RML(GAELIC,GAELIC_MANX), "gv_GB"},*/
268/*{RML(GAELIC,GAELIC_SCOTTISH), "gd_GB"},*/
269/*{RML(GALICIAN,DEFAULT), "gl_ES"},*/
270 {RML(GEORGIAN,DEFAULT), "ka_GE"},
271 {RML(GERMAN,GERMAN), "de_DE"},
272 {RML(GERMAN,GERMAN_AUSTRIAN), "de_AT"},
273 {RML(GERMAN,GERMAN_LIECHTENSTEIN), "de_LI"},
274 {RML(GERMAN,GERMAN_LUXEMBOURG), "de_LU"},
275 {RML(GERMAN,GERMAN_SWISS), "de_CH"},
276 {RML(GREEK,DEFAULT), "el_GR"},
277 {RML(GUJARATI,DEFAULT), "gu_IN"},
278 {RML(HEBREW,DEFAULT), "he_IL"},
279 {RML(HINDI,DEFAULT), "hi_IN"},
280 {RML(HUNGARIAN,DEFAULT), "hu_HU"},
281 {RML(ICELANDIC,DEFAULT), "is_IS"},
282 {RML(INDONESIAN,DEFAULT), "id_ID"},
283 {RML(ITALIAN,ITALIAN), "it_IT"},
284 {RML(ITALIAN,ITALIAN_SWISS), "it_CH"},
285 {RML(JAPANESE,DEFAULT), "ja_JP"},
286 {RML(KANNADA,DEFAULT), "kn_IN"},
287 {RML(KAZAK,DEFAULT), "kk_KZ"},
288 {RML(KONKANI,DEFAULT), "kok_IN"},
289 {RML(KOREAN,KOREAN), "ko_KR"},
290/*{RML(KYRGYZ,DEFAULT), "ky_KG"},*/
291 {RML(LATVIAN,DEFAULT), "lv_LV"},
292 {RML(LITHUANIAN,LITHUANIAN), "lt_LT"},
293 {RML(MACEDONIAN,DEFAULT), "mk_MK"},
294 {RML(MALAY,MALAY_BRUNEI_DARUSSALAM), "ms_BN"},
295 {RML(MALAY,MALAY_MALAYSIA), "ms_MY"},
296 {RML(MARATHI,DEFAULT), "mr_IN"},
297/*{RML(MONGOLIAN,DEFAULT), "mn_MN"},*/
298 {RML(NORWEGIAN,NORWEGIAN_BOKMAL), "nb_NO"},
299 {RML(NORWEGIAN,NORWEGIAN_NYNORSK), "nn_NO"},
300 {RML(POLISH,DEFAULT), "pl_PL"},
301 {RML(PORTUGUESE,PORTUGUESE), "pt_PT"},
302 {RML(PORTUGUESE,PORTUGUESE_BRAZILIAN), "pt_BR"},
303 {RML(PUNJABI,DEFAULT), "pa_IN"},
304 {RML(ROMANIAN,DEFAULT), "ro_RO"},
305 {RML(RUSSIAN,DEFAULT), "ru_RU"},
306 {RML(SANSKRIT,DEFAULT), "sa_IN"},
307 {RML(SERBIAN,DEFAULT), "hr_HR"},
308 {RML(SERBIAN,SERBIAN_CYRILLIC), "sr_SP"},
309 {RML(SERBIAN,SERBIAN_LATIN), "sr_SP"},
310 {RML(SLOVAK,DEFAULT), "sk_SK"},
311 {RML(SLOVENIAN,DEFAULT), "sl_SI"},
312 {RML(SPANISH,SPANISH), "es_ES"},
313 {RML(SPANISH,SPANISH_ARGENTINA), "es_AR"},
314 {RML(SPANISH,SPANISH_BOLIVIA), "es_BO"},
315 {RML(SPANISH,SPANISH_CHILE), "es_CL"},
316 {RML(SPANISH,SPANISH_COLOMBIA), "es_CO"},
317 {RML(SPANISH,SPANISH_COSTA_RICA), "es_CR"},
318 {RML(SPANISH,SPANISH_DOMINICAN_REPUBLIC), "es_DO"},
319 {RML(SPANISH,SPANISH_ECUADOR), "es_EC"},
320 {RML(SPANISH,SPANISH_EL_SALVADOR), "es_SV"},
321 {RML(SPANISH,SPANISH_GUATEMALA), "es_GT"},
322 {RML(SPANISH,SPANISH_HONDURAS), "es_HN"},
323 {RML(SPANISH,SPANISH_MEXICAN), "es_MX"},
324 {RML(SPANISH,SPANISH_MODERN), "es_ES"},
325 {RML(SPANISH,SPANISH_NICARAGUA), "es_NI"},
326 {RML(SPANISH,SPANISH_PANAMA), "es_PA"},
327 {RML(SPANISH,SPANISH_PARAGUAY), "es_PY"},
328 {RML(SPANISH,SPANISH_PERU), "es_PE"},
329 {RML(SPANISH,SPANISH_PUERTO_RICO), "es_PR"},
330 {RML(SPANISH,SPANISH_URUGUAY), "es_UY"},
331 {RML(SPANISH,SPANISH_VENEZUELA), "es_VE"},
332 {RML(SWAHILI,DEFAULT), "sw_KE"},
333 {RML(SWEDISH,SWEDISH), "sv_SE"},
334 {RML(SWEDISH,SWEDISH_FINLAND), "sv_FI"},
335/*{RML(SYRIAC,DEFAULT), "syr_SY"},*/
336 {RML(TAMIL,DEFAULT), "ta_IN"},
337 {RML(TATAR,DEFAULT), "tt_TA"},
338 {RML(TELUGU,DEFAULT), "te_IN"},
339 {RML(THAI,DEFAULT), "th_TH"},
340 {RML(TURKISH,DEFAULT), "tr_TR"},
341 {RML(UKRAINIAN,DEFAULT), "uk_UA"},
342 {RML(URDU,URDU_PAKISTAN), "ur_PK"},
343 {RML(UZBEK,UZBEK_CYRILLIC), "uz_UZ"},
344 {RML(UZBEK,UZBEK_LATIN), "uz_UZ"},
345 {RML(VIETNAMESE,DEFAULT), "vi_VN"},
346/*{RML(WALON,DEFAULT), "wa_BE"},*/
347/*{RML(WELSH,DEFAULT), "cy_GB"},*/
348};
349static const IDToCode primary_to_code[] = {
350 {LANG_AFRIKAANS, "af"},
351 {LANG_ARABIC, "ar"},
352 {LANG_AZERI, "az"},
353 {LANG_BULGARIAN, "bg"},
354/*{LANG_BRETON, "br"},*/
355 {LANG_BELARUSIAN, "by"},
356 {LANG_CATALAN, "ca"},
357 {LANG_CZECH, "cs"},
358/*{LANG_WELSH, "cy"},*/
359 {LANG_DANISH, "da"},
360 {LANG_GERMAN, "de"},
361 {LANG_GREEK, "el"},
362 {LANG_ENGLISH, "en"},
363/*{LANG_ESPERANTO, "eo"},*/
364 {LANG_SPANISH, "es"},
365 {LANG_ESTONIAN, "et"},
366 {LANG_BASQUE, "eu"},
367 {LANG_FARSI, "fa"},
368 {LANG_FINNISH, "fi"},
369 {LANG_FAEROESE, "fo"},
370 {LANG_FRENCH, "fr"},
371/*{LANG_GAELIC, "ga"},*/
372/*{LANG_GALICIAN, "gl"},*/
373 {LANG_GUJARATI, "gu"},
374 {LANG_HEBREW, "he"},
375 {LANG_HINDI, "hi"},
376 {LANG_SERBIAN, "hr"},
377 {LANG_HUNGARIAN, "hu"},
378 {LANG_ARMENIAN, "hy"},
379 {LANG_INDONESIAN, "id"},
380 {LANG_ITALIAN, "it"},
381 {LANG_JAPANESE, "ja"},
382 {LANG_GEORGIAN, "ka"},
383 {LANG_KAZAK, "kk"},
384 {LANG_KANNADA, "kn"},
385 {LANG_KOREAN, "ko"},
386/*{LANG_KYRGYZ, "ky"},*/
387 {LANG_LITHUANIAN, "lt"},
388 {LANG_LATVIAN, "lv"},
389 {LANG_MACEDONIAN, "mk"},
390/*{LANG_MONGOLIAN, "mn"},*/
391 {LANG_MARATHI, "mr"},
392 {LANG_MALAY, "ms"},
393 {LANG_NORWEGIAN, "nb"},
394 {LANG_DUTCH, "nl"},
395 {LANG_NORWEGIAN, "nn"},
396 {LANG_NORWEGIAN, "no"},/* unofficial? */
397 {LANG_PUNJABI, "pa"},
398 {LANG_POLISH, "pl"},
399 {LANG_PORTUGUESE, "pt"},
400 {LANG_ROMANIAN, "ro"},
401 {LANG_RUSSIAN, "ru"},
402 {LANG_SLOVAK, "sk"},
403 {LANG_SLOVENIAN, "sl"},
404 {LANG_ALBANIAN, "sq"},
405 {LANG_SERBIAN, "sr"},
406 {LANG_SWEDISH, "sv"},
407 {LANG_SWAHILI, "sw"},
408 {LANG_TAMIL, "ta"},
409 {LANG_THAI, "th"},
410 {LANG_TURKISH, "tr"},
411 {LANG_TATAR, "tt"},
412 {LANG_UKRAINIAN, "uk"},
413 {LANG_URDU, "ur"},
414 {LANG_UZBEK, "uz"},
415 {LANG_VIETNAMESE, "vi"},
416/*{LANG_WALON, "wa"},*/
417 {LANG_CHINESE, "zh"},
418};
419static int num_primary_to_code =
420 sizeof(primary_to_code) / sizeof(*primary_to_code);
421static int num_both_to_code =
422 sizeof(both_to_code) / sizeof(*both_to_code);
423
424static const int
425lcid_to_fl(LCID lcid,
426 FL_Locale *rtn) {
427 LANGID langid = LANGIDFROMLCID(lcid);
428 LANGID primary_lang = PRIMARYLANGID(langid);
429 /*LANGID sub_lang = SUBLANGID(langid);*/
430 int i;
431 /* try to find an exact primary/sublanguage combo that we know about */
432 for (i=0; i<num_both_to_code; ++i) {
433 if (both_to_code[i].id == langid) {
434 accumulate_locstring(both_to_code[i].code, rtn);
435 return 1;
436 }
437 }
438 /* fallback to just checking the primary language id */
439 for (i=0; i<num_primary_to_code; ++i) {
440 if (primary_to_code[i].id == primary_lang) {
441 accumulate_locstring(primary_to_code[i].code, rtn);
442 return 1;
443 }
444 }
445 return 0;
446}
447#endif
448
449
450FL_Success
451FL_FindLocale(FL_Locale **locale, FL_Domain domain) {
452 FL_Success success = FL_FAILED;
453 FL_Locale *rtn = (FL_Locale*)malloc(sizeof(FL_Locale));
454 rtn->lang = NULL;
455 rtn->country = NULL;
456 rtn->variant = NULL;
457
458#ifdef WIN32
459 /* win32 >= mswindows95 */
460 {
461 LCID lcid = GetThreadLocale();
462 if (lcid_to_fl(lcid, rtn)) {
463 success = FL_CONFIDENT;
464 }
465 if (success == FL_FAILED) {
466 /* assume US English on mswindows systems unless we know otherwise */
467 if (accumulate_locstring("en_US.ISO_8859-1", rtn)) {
468 success = FL_DEFAULT_GUESS;
469 }
470 }
471 }
472#else
473 /* assume unixoid */
474 {
475 /* examples: */
476 /* sv_SE.ISO_8859-1 */
477 /* fr_FR.ISO8859-1 */
478 /* no_NO_NB */
479 /* no_NO_NY */
480 /* no_NO */
481 /* de_DE */
482 /* try the various vars in decreasing order of authority */
483 if (accumulate_env("LC_ALL", rtn) ||
484 accumulate_env("LC_MESSAGES", rtn) ||
485 accumulate_env("LANG", rtn) ||
486 accumulate_env("LANGUAGE", rtn)) {
487 success = FL_CONFIDENT;
488 }
489 if (success == FL_FAILED) {
490 /* assume US English on unixoid systems unless we know otherwise */
491 if (accumulate_locstring("en_US.ISO_8859-1", rtn)) {
492 success = FL_DEFAULT_GUESS;
493 }
494 }
495 }
496#endif
497
498 if (success != FL_FAILED) {
499 canonise_fl(rtn);
500 }
501
502 *locale = rtn;
503 return success;
504}
505
506
507void
508FL_FreeLocale(FL_Locale **locale) {
509 if (locale) {
510 FL_Locale *l = *locale;
511 if (l) {
512 if (l->lang) {
513 free((void*)l->lang);
514 }
515 if (l->country) {
516 free((void*)l->country);
517 }
518 if (l->variant) {
519 free((void*)l->variant);
520 }
521 free(l);
522 *locale = NULL;
523 }
524 }
525}