#include #include #include #include /* locale names mostly copied from XFree86 */ static const char * const iso8859_2locales[] = { "croatian", "cs", "cs_CS", "cs_CZ","cz", "cz_CZ", "czech", "hr", "hr_HR", "hu", "hu_HU", "hungarian", "pl", "pl_PL", "polish", "ro", "ro_RO", "rumanian", "serbocroatian", "sh", "sh_SP", "sh_YU", "sk", "sk_SK", "sl", "sl_CS", "sl_SI", "slovak", "slovene", "sr_SP", 0 }; static const char * const iso8859_3locales[] = { "eo", 0 }; static const char * const iso8859_4locales[] = { "ee", "ee_EE", 0 }; static const char * const iso8859_5locales[] = { "mk", "mk_MK", "sp", "sp_YU", 0 }; static const char * const cp_1251locales[] = { "be", "be_BY", "bg", "bg_BG", "bulgarian", 0 }; static const char * const pt_154locales[] = { "ba_RU", "ky", "ky_KG", "kk", "kk_KZ", 0 }; static const char * const iso8859_6locales[] = { "ar_AA", "ar_SA", "arabic", 0 }; static const char * const iso8859_7locales[] = { "el", "el_GR", "greek", 0 }; static const char * const iso8859_8locales[] = { "hebrew", "he", "he_IL", "iw", "iw_IL", 0 }; static const char * const iso8859_9locales[] = { "tr", "tr_TR", "turkish", 0 }; static const char * const iso8859_13locales[] = { "lt", "lt_LT", "lv", "lv_LV", 0 }; static const char * const iso8859_15locales[] = { "et", "et_EE", // Euro countries "br_FR", "ca_ES", "de", "de_AT", "de_BE", "de_DE", "de_LU", "en_IE", "es", "es_ES", "eu_ES", "fi", "fi_FI", "finnish", "fr", "fr_FR", "fr_BE", "fr_LU", "french", "ga_IE", "gl_ES", "it", "it_IT", "oc_FR", "nl", "nl_BE", "nl_NL", "pt", "pt_PT", "sv_FI", "wa_BE", 0 }; static const char * const koi8_ulocales[] = { "uk", "uk_UA", "ru_UA", "ukrainian", 0 }; static const char * const tis_620locales[] = { "th", "th_TH", "thai", 0 }; // static const char * const tcvnlocales[] = { // "vi", "vi_VN", 0 }; static bool try_locale_list(const char * const locale[], const char * lang) { int i; for(i=0; locale[i] && *locale[i] && strcmp(locale[i], lang); i++) ; return locale[i] != 0; } char* save_strdup(const char* src) { if (src) return strdup(src); return 0; } int checkForCodec(const char* codec) { printf("checkForCodec: %s\n", codec); return 0; } int codecForName(const char* name) { printf("codecForName: %s\n", name); return 0; } int main() { int localeMapper = 0; // Very poorly defined and followed standards causes lots of code // to try to get all the cases... // Try to determine locale codeset from locale name assigned to // LC_CTYPE category. // First part is getting that locale name. First try setlocale() which // definitely knows it, but since we cannot fully trust it, get ready // to fall back to environment variables. char * ctype = save_strdup(setlocale(LC_CTYPE, 0)); // Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG // environment variables. char * lang = save_strdup(getenv("LC_ALL")); if (!lang || lang[0] == 0 || strcmp(lang, "C") == 0) { if (lang) delete[](lang); lang = save_strdup(getenv("LC_CTYPE")); } if (!lang || lang[0] == 0 || strcmp(lang, "C") == 0) { if (lang) delete[](lang); lang = save_strdup(getenv("LANG")); } // Now try these in order: // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15) // 2. CODESET from lang if it contains a .CODESET part // 3. ctype (maybe the locale is named "ISO-8859-1" or something) // 4. locale (ditto) // 5. check for "@euro" // 6. guess locale from ctype unless ctype is "C" // 7. guess locale from lang // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15) char * codeset = ctype ? strchr(ctype, '.') : 0; if (codeset && *codeset == '.') localeMapper = checkForCodec(codeset + 1); // 2. CODESET from lang if it contains a .CODESET part codeset = lang ? strchr(lang, '.') : 0; if (!localeMapper && codeset && *codeset == '.') localeMapper = checkForCodec(codeset + 1); // 3. ctype (maybe the locale is named "ISO-8859-1" or something) if (!localeMapper && ctype && *ctype != 0 && strcmp (ctype, "C") != 0) localeMapper = checkForCodec(ctype); // 4. locale (ditto) if (!localeMapper && lang && *lang != 0) localeMapper = checkForCodec(lang); // 5. "@euro" if (!localeMapper && ctype && strstr(ctype, "@euro") || lang && strstr(lang, "@euro")) localeMapper = checkForCodec("ISO 8859-15"); // 6. guess locale from ctype unless ctype is "C" // 7. guess locale from lang char * try_by_name = ctype; if (ctype && *ctype != 0 && strcmp (ctype, "C") != 0) try_by_name = lang; // Now do the guessing. if (lang && *lang && !localeMapper && try_by_name && *try_by_name) { if (try_locale_list(iso8859_15locales, lang)) localeMapper = codecForName("ISO 8859-15"); else if (try_locale_list(iso8859_2locales, lang)) localeMapper = codecForName("ISO 8859-2"); else if (try_locale_list(iso8859_3locales, lang)) localeMapper = codecForName("ISO 8859-3"); else if (try_locale_list(iso8859_4locales, lang)) localeMapper = codecForName("ISO 8859-4"); else if (try_locale_list(iso8859_5locales, lang)) localeMapper = codecForName("ISO 8859-5"); else if (try_locale_list(iso8859_6locales, lang)) localeMapper = codecForName("ISO 8859-6"); else if (try_locale_list(iso8859_7locales, lang)) localeMapper = codecForName("ISO 8859-7"); else if (try_locale_list(iso8859_8locales, lang)) localeMapper = codecForName("ISO 8859-8-I"); else if (try_locale_list(iso8859_9locales, lang)) localeMapper = codecForName("ISO 8859-9"); else if (try_locale_list(iso8859_13locales, lang)) localeMapper = codecForName("ISO 8859-13"); else if (try_locale_list(tis_620locales, lang)) localeMapper = codecForName("ISO 8859-11"); else if (try_locale_list(koi8_ulocales, lang)) localeMapper = codecForName("KOI8-U"); else if (try_locale_list(cp_1251locales, lang)) localeMapper = codecForName("CP 1251"); else if (try_locale_list(pt_154locales, lang)) localeMapper = codecForName("PT 154"); /* else if (try_locale_list(probably_koi8_rlocales, lang)) localeMapper = ru_RU_hack(lang);*/ } delete[](ctype); delete[](lang); // If everything failed, we default to 8859-1 // We could perhaps default to 8859-15. if (!localeMapper) localeMapper = codecForName("ISO 8859-1"); return 0; }