llfindlocale.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:15k
源码类别:

游戏引擎

开发平台:

C++ Builder

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