llfindlocale.cpp 15 KB

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