enlightenment/src/modules/conf_intl/e_int_config_intl.c

1487 lines
42 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "e.h"
typedef struct _E_Intl_Pair E_Intl_Pair;
typedef struct _E_Intl_Langauge_Node E_Intl_Language_Node;
typedef struct _E_Intl_Region_Node E_Intl_Region_Node;
static void *_create_data (E_Config_Dialog *cfd);
static void _free_data (E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
static int _advanced_apply_data (E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
static Evas_Object *_advanced_create_widgets (E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
static int _basic_apply_data (E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
static Evas_Object *_basic_create_widgets (E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
static void _ilist_basic_language_cb_change (void *data, Evas_Object *obj);
static void _ilist_language_cb_change (void *data, Evas_Object *obj);
static void _ilist_region_cb_change (void *data, Evas_Object *obj);
static void _ilist_codeset_cb_change (void *data, Evas_Object *obj);
static void _ilist_modifier_cb_change (void *data, Evas_Object *obj);
static int _lang_list_sort (const void *data1, const void *data2);
static void _lang_list_load (void *data);
static int _region_list_sort (const void *data1, const void *data2);
static void _region_list_load (void *data);
static int _basic_lang_list_sort (const void *data1, const void *data2);
/* Fill the clear lists, fill with language, select */
/* Update lanague */
static void _cfdata_language_go (const char *lang, const char *region, const char *codeset, const char *modifier, E_Config_Dialog_Data *cfdata);
static Eina_Bool _lang_hash_cb (const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata);
static Eina_Bool _region_hash_cb (const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata);
static Eina_Bool _language_hash_free_cb (const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__);
static Eina_Bool _region_hash_free_cb (const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__);
static void _intl_current_locale_setup (E_Config_Dialog_Data *cfdata);
static const char *_intl_charset_upper_get (const char *charset);
struct _E_Intl_Pair
{
const char *locale_key;
const char *locale_translation;
};
/* We need to store a map of languages -> Countries -> Extra
*
* Extra:
* Each region has its own Encodings
* Each region has its own Modifiers
*/
struct _E_Intl_Langauge_Node
{
const char *lang_code; /* en */
const char *lang_name; /* English (trans in ilist) */
int lang_available; /* defined in e translation */
Eina_Hash *region_hash; /* US->utf8 */
};
struct _E_Intl_Region_Node
{
const char *region_code; /* US */
const char *region_name; /* United States */
Eina_List *available_codesets;
Eina_List *available_modifiers;
};
struct _E_Config_Dialog_Data
{
E_Config_Dialog *cfd;
Evas *evas;
/* Current data */
char *cur_language;
char *cur_blang;
char *cur_lang;
char *cur_reg;
char *cur_cs;
char *cur_mod;
int lang_dirty;
Eina_Hash *locale_hash;
Eina_List *lang_list;
Eina_List *region_list;
Eina_List *blang_list;
struct
{
Evas_Object *blang_list;
Evas_Object *lang_list;
Evas_Object *reg_list;
Evas_Object *cs_list;
Evas_Object *mod_list;
Evas_Object *locale_entry;
}
gui;
};
const E_Intl_Pair basic_language_predefined_pairs[ ] = {
{"bg_BG.UTF-8", "Български"},
{"ca_ES.UTF-8", "Català"},
{"zh_CN.UTF-8", "Chinese (Simplified)"},
{"zh_TW.UTF-8", "Chinese (Traditional)"},
{"cs_CZ.UTF-8", "Čeština"},
{"da_DK.UTF-8", "Dansk"},
{"nl_NL.UTF-8", "Nederlands"},
{"en_US.UTF-8", "English"},
{"fi_FI.UTF-8", "Suomi"},
{"fr_FR.UTF-8", "Français"},
{"de_DE.UTF-8", "Deutsch"},
{"hu_HU.UTF-8", "Magyar"},
{"it_IT.UTF-8", "Italiano"},
{"ja_JP.UTF-8", "日本語"},
{"ko_KR.UTF-8", "한국어"},
{"nb_NO.UTF-8", "Norsk Bokmål"},
{"pl_PL.UTF-8", "Polski"},
{"pt_BR.UTF-8", "Português"},
{"ru_RU.UTF-8", "Русский"},
{"sk_SK.UTF-8", "Slovenčina"},
{"sl_SI.UTF-8", "Slovenščina"},
{"es_AR.UTF-8", "Español"},
{"sv_SE.UTF-8", "Svenska"},
{"el_GR.UTF-8", "Ελληνικά"},
{ NULL, NULL }
};
const E_Intl_Pair language_predefined_pairs[ ] = {
{"aa", "Qafár af"},
{"af", "Afrikaans"},
{"ak", "Akan"},
{"am", "አማርኛ"},
{"an", "Aragonés"},
{"ar", "ةيبرعلا"},
{"as", "অসমীয়া"},
{"az", "Azərbaycan dili"},
{"be", "Беларуская мова"},
{"bg", "Български"},
{"bn", "বাংলা"},
{"br", "Brezhoneg"},
{"bs", "Bosanski"},
{"byn", "ብሊና"},
{"ca", "Català"},
{"cch", "Atsam"},
{"cs", "Čeština"},
{"cy", "Cymraeg"},
{"da", "Dansk"},
{"de", "Deutsch"},
{"dv", "ދިވެހި"},
{"dz", "Dzongkha"},
{"ee", "Eʋegbe"},
{"el", "Ελληνικά"},
{"en", "English"},
{"eo", "Esperanto"},
{"es", "Español"},
{"et", "Eesti keel"},
{"eu", "Euskara"},
{"fa", "یسراف"},
{"fi", "Suomi"},
{"fo", "Føroyskt"},
{"fr", "Français"},
{"fur", "Furlan"},
{"ga", "Gaeilge"},
{"gaa", ""},
{"gez", "ግዕዝ"},
{"gl", "Galego"},
{"gu", "Gujarati"},
{"gv", "Yn Ghaelg"},
{"ha", "Hausa"},
{"haw", "ʻŌlelo Hawaiʻi"},
{"he", "תירבע"},
{"hi", "Hindi"},
{"hr", "Hrvatski"},
{"hu", "Magyar"},
{"hy", "Հայերեն"},
{"ia", "Interlingua"},
{"id", "Indonesian"},
{"ig", "Igbo"},
{"is", "Íslenska"},
{"it", "Italiano"},
{"iu", "ᐃᓄᒃᑎᑐᑦ"},
{"iw", "תירבע"},
{"ja", "日本語"},
{"ka", "ქართული"},
{"kaj", "Jju"},
{"kam", "Kikamba"},
{"kcg", "Tyap"},
{"kfo", "Koro"},
{"kk", "Qazaq"},
{"kl", "Kalaallisut"},
{"km", "Khmer"},
{"kn", "ಕನ್ನಡ"},
{"ko", "한국어"},
{"kok", "Konkani"},
{"ku", "یدروك"},
{"kw", "Kernowek"},
{"ky", "Кыргыз тили"},
{"ln", "Lingála"},
{"lo", "ພາສາລາວ"},
{"lt", "Lietuvių kalba"},
{"lv", "Latviešu"},
{"mi", "Te Reo Māori"},
{"mk", "Македонски"},
{"ml", "മലയാളം"},
{"mn", "Монгол"},
{"mr", "मराठी"},
{"ms", "Bahasa Melayu"},
{"mt", "Malti"},
{"nb", "Norsk Bokmål"},
{"ne", "नेपाली"},
{"nl", "Nederlands"},
{"nn", "Norsk Nynorsk"},
{"no", "Norsk"},
{"nr", "isiNdebele"},
{"nso", "Sesotho sa Leboa"},
{"ny", "Chicheŵa"},
{"oc", "Occitan"},
{"om", "Oromo"},
{"or", "ଓଡ଼ିଆ"},
{"pa", "ਪੰਜਾਬੀ"},
{"pl", "Polski"},
{"ps", "وتښپ"},
{"pt", "Português"},
{"ro", "Română"},
{"ru", "Русский"},
{"rw", "Kinyarwanda"},
{"sa", "संस्कृतम्"},
{"se", "Davvisápmi"},
{"sh", "Srpskohrvatski/Српскохрватски"},
{"sid", "Sidámo 'Afó"},
{"sk", "Slovenčina"},
{"sl", "Slovenščina"},
{"so", "af Soomaali"},
{"sq", "Shqip"},
{"sr", "Српски"},
{"ss", "Swati"},
{"st", "Southern Sotho"},
{"sv", "Svenska"},
{"sw", "Swahili"},
{"syr", "Syriac"},
{"ta", "தமிழ்"},
{"te", "తెలుగు"},
{"tg", "Тоҷикӣ"},
{"th", "ภาษาไทย"},
{"ti", "ትግርኛ"},
{"tig", "ቲግሬ"},
{"tl", "Tagalog"},
{"tn", "Setswana"},
{"tr", "Türkçe"},
{"ts", "Tsonga"},
{"tt", "Татарча"},
{"uk", "Українська мова"},
{"ur", "ودراُ"},
{"uz", "Ozbek"},
{"ve", "Venda"},
{"vi", "Tiếng Việt"},
{"wa", "Walon"},
{"wal", "Walamo"},
{"xh", "Xhosa"},
{"yi", "שידיִי"},
{"yo", "èdèe Yorùbá"},
{"zh", "汉语/漢語"},
{"zu", "Zulu"},
{ NULL, NULL}
};
const E_Intl_Pair region_predefined_pairs[ ] = {
{ "AF", "Afghanistan"},
{ "AX", "Åland"},
{ "AL", "Shqipëria"},
{ "DZ", "Algeria"},
{ "AS", "Amerika Sāmoa"},
{ "AD", "Andorra"},
{ "AO", "Angola"},
{ "AI", "Anguilla"},
{ "AQ", "Antarctica"},
{ "AG", "Antigua and Barbuda"},
{ "AR", "Argentina"},
{ "AM", "Հայաստան"},
{ "AW", "Aruba"},
{ "AU", "Australia"},
{ "AT", "Österreich"},
{ "AZ", "Azərbaycan"},
{ "BS", "Bahamas"},
{ "BH", "Bahrain"},
{ "BD", "বাংলাদেশ"},
{ "BB", "Barbados"},
{ "BY", "Беларусь"},
{ "BE", "Belgium"},
{ "BZ", "Belize"},
{ "BJ", "Bénin"},
{ "BM", "Bermuda"},
{ "BT", "Bhutan"},
{ "BO", "Bolivia"},
{ "BA", "Bosnia and Herzegovina"},
{ "BW", "Botswana"},
{ "BV", "Bouvetøya"},
{ "BR", "Brazil"},
{ "IO", "British Indian Ocean Territory"},
{ "BN", "Brunei Darussalam"},
{ "BG", "България"},
{ "BF", "Burkina Faso"},
{ "BI", "Burundi"},
{ "KH", "Cambodia"},
{ "CM", "Cameroon"},
{ "CA", "Canada"},
{ "CV", "Cape Verde"},
{ "KY", "Cayman Islands"},
{ "CF", "Central African Republic"},
{ "TD", "Chad"},
{ "CL", "Chile"},
{ "CN", "中國"},
{ "CX", "Christmas Island"},
{ "CC", "Cocos (keeling) Islands"},
{ "CO", "Colombia"},
{ "KM", "Comoros"},
{ "CG", "Congo"},
{ "CD", "Congo"},
{ "CK", "Cook Islands"},
{ "CR", "Costa Rica"},
{ "CI", "Cote d'Ivoire"},
{ "HR", "Hrvatska"},
{ "CU", "Cuba"},
{ "CY", "Cyprus"},
{ "CZ", "Česká republika"},
{ "DK", "Danmark"},
{ "DJ", "Djibouti"},
{ "DM", "Dominica"},
{ "DO", "República Dominicana"},
{ "EC", "Ecuador"},
{ "EG", "Egypt"},
{ "SV", "El Salvador"},
{ "GQ", "Equatorial Guinea"},
{ "ER", "Eritrea"},
{ "EE", "Eesti"},
{ "ET", "Ethiopia"},
{ "FK", "Falkland Islands (malvinas)"},
{ "FO", "Faroe Islands"},
{ "FJ", "Fiji"},
{ "FI", "Finland"},
{ "FR", "France"},
{ "GF", "French Guiana"},
{ "PF", "French Polynesia"},
{ "TF", "French Southern Territories"},
{ "GA", "Gabon"},
{ "GM", "Gambia"},
{ "GE", "Georgia"},
{ "DE", "Deutschland"},
{ "GH", "Ghana"},
{ "GI", "Gibraltar"},
{ "GR", "Greece"},
{ "GL", "Greenland"},
{ "GD", "Grenada"},
{ "GP", "Guadeloupe"},
{ "GU", "Guam"},
{ "GT", "Guatemala"},
{ "GG", "Guernsey"},
{ "GN", "Guinea"},
{ "GW", "Guinea-Bissau"},
{ "GY", "Guyana"},
{ "HT", "Haiti"},
{ "HM", "Heard Island and Mcdonald Islands"},
{ "VA", "Holy See (Vatican City State)"},
{ "HN", "Honduras"},
{ "HK", "Hong Kong"},
{ "HU", "Magyarország"},
{ "IS", "Iceland"},
{ "IN", "India"},
{ "ID", "Indonesia"},
{ "IR", "Iran"},
{ "IQ", "Iraq"},
{ "IE", "Éire"},
{ "IM", "Isle Of Man"},
{ "IL", "Israel"},
{ "IT", "Italia"},
{ "JM", "Jamaica"},
{ "JP", "日本"},
{ "JE", "Jersey"},
{ "JO", "Jordan"},
{ "KZ", "Kazakhstan"},
{ "KE", "Kenya"},
{ "KI", "Kiribati"},
{ "KP", "Korea"},
{ "KR", "Korea"},
{ "KW", "Kuwait"},
{ "KG", "Kyrgyzstan"},
{ "LA", "Lao People's Democratic Republic"},
{ "LV", "Latvija"},
{ "LB", "Lebanon"},
{ "LS", "Lesotho"},
{ "LR", "Liberia"},
{ "LY", "Libyan Arab Jamahiriya"},
{ "LI", "Liechtenstein"},
{ "LT", "Lietuva"},
{ "LU", "Lëtzebuerg"},
{ "MO", "Macao"},
{ "MK", "Македонија"},
{ "MG", "Madagascar"},
{ "MW", "Malawi"},
{ "MY", "Malaysia"},
{ "MV", "Maldives"},
{ "ML", "Mali"},
{ "MT", "Malta"},
{ "MH", "Marshall Islands"},
{ "MQ", "Martinique"},
{ "MR", "Mauritania"},
{ "MU", "Mauritius"},
{ "YT", "Mayotte"},
{ "MX", "Mexico"},
{ "FM", "Micronesia"},
{ "MD", "Moldova"},
{ "MC", "Monaco"},
{ "MN", "Mongolia"},
{ "MS", "Montserrat"},
{ "MA", "Morocco"},
{ "MZ", "Mozambique"},
{ "MM", "Myanmar"},
{ "NA", "Namibia"},
{ "NR", "Nauru"},
{ "NP", "Nepal"},
{ "NL", "Nederland"},
{ "AN", "Netherlands Antilles"},
{ "NC", "New Caledonia"},
{ "NZ", "New Zealand"},
{ "NI", "Nicaragua"},
{ "NE", "Niger"},
{ "NG", "Nigeria"},
{ "NU", "Niue"},
{ "NF", "Norfolk Island"},
{ "MP", "Northern Mariana Islands"},
{ "NO", "Norge"},
{ "OM", "Oman"},
{ "PK", "Pakistan"},
{ "PW", "Palau"},
{ "PS", "Palestinian Territory"},
{ "PA", "Panama"},
{ "PG", "Papua New Guinea"},
{ "PY", "Paraguay"},
{ "PE", "Peru"},
{ "PH", "Philippines"},
{ "PN", "Pitcairn"},
{ "PL", "Poland"},
{ "PT", "Portugal"},
{ "PR", "Puerto Rico"},
{ "QA", "Qatar"},
{ "RE", "Reunion"},
{ "RO", "Romania"},
{ "RU", "Russian Federation"},
{ "RW", "Rwanda"},
{ "SH", "Saint Helena"},
{ "KN", "Saint Kitts and Nevis"},
{ "LC", "Saint Lucia"},
{ "PM", "Saint Pierre and Miquelon"},
{ "VC", "Saint Vincent and the Grenadines"},
{ "WS", "Samoa"},
{ "SM", "San Marino"},
{ "ST", "Sao Tome and Principe"},
{ "SA", "Saudi Arabia"},
{ "SN", "Senegal"},
{ "CS", "Serbia and Montenegro"},
{ "SC", "Seychelles"},
{ "SL", "Sierra Leone"},
{ "SG", "Singapore"},
{ "SK", "Slovakia"},
{ "SI", "Slovenia"},
{ "SB", "Solomon Islands"},
{ "SO", "Somalia"},
{ "ZA", "South Africa"},
{ "GS", "South Georgia and the South Sandwich Islands"},
{ "ES", "Spain"},
{ "LK", "Sri Lanka"},
{ "SD", "Sudan"},
{ "SR", "Suriname"},
{ "SJ", "Svalbard and Jan Mayen"},
{ "SZ", "Swaziland"},
{ "SE", "Sweden"},
{ "CH", "Switzerland"},
{ "SY", "Syrian Arab Republic"},
{ "TW", "Taiwan"},
{ "TJ", "Tajikistan"},
{ "TZ", "Tanzania"},
{ "TH", "Thailand"},
{ "TL", "Timor-Leste"},
{ "TG", "Togo"},
{ "TK", "Tokelau"},
{ "TO", "Tonga"},
{ "TT", "Trinidad and Tobago"},
{ "TN", "Tunisia"},
{ "TR", "Turkey"},
{ "TM", "Turkmenistan"},
{ "TC", "Turks and Caicos Islands"},
{ "TV", "Tuvalu"},
{ "UG", "Uganda"},
{ "UA", "Ukraine"},
{ "AE", "United Arab Emirates"},
{ "GB", "United Kingdom"},
{ "US", "United States"},
{ "UM", "United States Minor Outlying Islands"},
{ "UY", "Uruguay"},
{ "UZ", "Uzbekistan"},
{ "VU", "Vanuatu"},
{ "VE", "Venezuela"},
{ "VN", "Viet Nam"},
{ "VG", "Virgin Islands"},
{ "VI", "Virgin Islands"},
{ "WF", "Wallis and Futuna"},
{ "EH", "Western Sahara"},
{ "YE", "Yemen"},
{ "ZM", "Zambia"},
{ "ZW", "Zimbabwe"},
{ NULL, NULL}
};
/* This comes from
$ man charsets
* and
$ locale -a | grep -v @ | grep "\." | cut -d . -f 2 | sort -u
*
* On some machines is complains if codesets don't look like this
* On linux its not really a problem but BSD has issues. So we neet to
* make sure that locale -a output gets converted to upper-case form in
* all situations just to be safe.
*/
const E_Intl_Pair charset_predefined_pairs[ ] = {
/* These are in locale -a but not in charsets */
{"cp1255", "CP1255"},
{"euc", "EUC"},
{"georgianps", "GEORGIAN-PS"},
{"iso885914", "ISO-8859-14"},
{"koi8t", "KOI8-T"},
{"tcvn", "TCVN"},
{"ujis", "UJIS"},
/* These are from charsets man page */
{"big5", "BIG5"},
{"big5hkscs", "BIG5-HKSCS"},
{"cp1251", "CP1251"},
{"eucjp", "EUC-JP"},
{"euckr", "EUC-KR"},
{"euctw", "EUC-TW"},
{"gb18030", "GB18030"},
{"gb2312", "GB2312"},
{"gbk", "GBK"},
{"iso88591", "ISO-8859-1"},
{"iso885913", "ISO-8859-13"},
{"iso885915", "ISO-8859-15"},
{"iso88592", "ISO-8859-2"},
{"iso88593", "ISO-8859-3"},
{"iso88595", "ISO-8859-5"},
{"iso88596", "ISO-8859-6"},
{"iso88597", "ISO-8859-7"},
{"iso88598", "ISO-8859-8"},
{"iso88599", "ISO-8859-9"},
{"koi8r", "KOI8-R"},
{"koi8u", "KOI8-U"},
{"tis620", "TIS-620"},
{"utf8", "UTF-8"},
{ NULL, NULL }
};
EAPI E_Config_Dialog *
e_int_config_intl(E_Container *con, const char *params __UNUSED__)
{
E_Config_Dialog *cfd;
E_Config_Dialog_View *v;
if (e_config_dialog_find("E", "_config_intl_dialog")) return NULL;
v = E_NEW(E_Config_Dialog_View, 1);
v->create_cfdata = _create_data;
v->free_cfdata = _free_data;
v->advanced.create_widgets = _advanced_create_widgets;
v->advanced.apply_cfdata = _advanced_apply_data;
v->basic.create_widgets = _basic_create_widgets;
v->basic.apply_cfdata = _basic_apply_data;
cfd = e_config_dialog_new(con,
_("Language Settings"),
"E", "_config_intl_dialog",
"enlightenment/intl", 0, v, NULL);
return cfd;
}
/* Build hash tables used for locale navigation. The locale information is
* gathered using the locale -a command.
*
* Below the following terms are used:
* ll - Locale Language Code (Example en)
* RR - Locale Region code (Example US)
* enc - Locale Encoding (Example UTF-8)
* mod - Locale Modifier (Example EURO)
*/
static void
_fill_data(E_Config_Dialog_Data *cfdata)
{
Eina_List *e_lang_list;
FILE *output;
e_lang_list = e_intl_language_list();
/* Get list of all locales and start making map */
output = popen("locale -a", "r");
if ( output )
{
char line[32];
while (fscanf(output, "%[^\n]\n", line) == 1)
{
E_Locale_Parts *locale_parts;
locale_parts = e_intl_locale_parts_get(line);
if (locale_parts)
{
char *basic_language;
basic_language = e_intl_locale_parts_combine(locale_parts, E_INTL_LOC_LANG | E_INTL_LOC_REGION);
if (basic_language)
{
int i;
i = 0;
while (basic_language_predefined_pairs[i].locale_key)
{
/* if basic language is supported by E and System*/
if (!strncmp(basic_language_predefined_pairs[i].locale_key,
basic_language, strlen(basic_language)))
{
if (!eina_list_data_find(cfdata->blang_list, &basic_language_predefined_pairs[i]))
cfdata->blang_list = eina_list_append(cfdata->blang_list, &basic_language_predefined_pairs[i]);
break;
}
i++;
}
}
E_FREE(basic_language);
/* If the language is a valid ll_RR[.enc[@mod]] locale add it to the hash */
if (locale_parts->lang)
{
E_Intl_Language_Node *lang_node;
E_Intl_Region_Node *region_node;
/* Add the language to the new locale properties to the hash */
/* First check if the LANGUAGE exists in there already */
lang_node = eina_hash_find(cfdata->locale_hash, locale_parts->lang);
if (lang_node == NULL)
{
Eina_List *next;
int i;
/* create new node */
lang_node = E_NEW(E_Intl_Language_Node, 1);
lang_node->lang_code = eina_stringshare_add(locale_parts->lang);
/* Check if the language list exists */
/* Linear Search */
for (next = e_lang_list; next; next = next->next)
{
char *e_lang;
e_lang = next->data;
if (!strncmp(e_lang, locale_parts->lang, 2) || !strcmp("en", locale_parts->lang))
{
lang_node->lang_available = 1;
break;
}
}
/* Search for translation */
/* Linear Search */
i = 0;
while (language_predefined_pairs[i].locale_key)
{
if (!strcmp(language_predefined_pairs[i].locale_key, locale_parts->lang))
{
lang_node->lang_name = _(language_predefined_pairs[i].locale_translation);
break;
}
i++;
}
if (!cfdata->locale_hash)
cfdata->locale_hash = eina_hash_string_superfast_new(NULL);
eina_hash_add(cfdata->locale_hash, locale_parts->lang, lang_node);
}
/* We now have the current language hash node, lets see if there is
region data that needs to be added.
*/
if (locale_parts->region)
{
region_node = eina_hash_find(lang_node->region_hash, locale_parts->region);
if (region_node == NULL)
{
int i;
/* create new node */
region_node = E_NEW(E_Intl_Region_Node, 1);
region_node->region_code = eina_stringshare_add(locale_parts->region);
/* Get the region translation */
/* Linear Search */
i = 0;
while (region_predefined_pairs[i].locale_key)
{
if (!strcmp(region_predefined_pairs[i].locale_key, locale_parts->region))
{
region_node->region_name = _(region_predefined_pairs[i].locale_translation);
break;
}
i++;
}
if (!lang_node->region_hash)
lang_node->region_hash = eina_hash_string_superfast_new(NULL);
eina_hash_add(lang_node->region_hash, locale_parts->region, region_node);
}
/* We now have the current region hash node */
/* Add codeset to the region hash node if it exists */
if (locale_parts->codeset)
{
const char * cs;
const char * cs_trans;
cs_trans = _intl_charset_upper_get(locale_parts->codeset);
if (cs_trans == NULL)
cs = eina_stringshare_add(locale_parts->codeset);
else
cs = eina_stringshare_add(cs_trans);
/* Exclusive */
/* Linear Search */
if (!eina_list_data_find(region_node->available_codesets, cs))
region_node->available_codesets = eina_list_append(region_node->available_codesets, cs);
}
/* Add modifier to the region hash node if it exists */
if (locale_parts->modifier)
{
const char *mod;
mod = eina_stringshare_add(locale_parts->modifier);
/* Find only works here because we are using stringshare*/
/* Exclusive */
/* Linear Search */
if (!eina_list_data_find(region_node->available_modifiers, mod))
region_node->available_modifiers = eina_list_append(region_node->available_modifiers, mod);
}
}
}
e_intl_locale_parts_free(locale_parts);
}
}
/* Sort basic languages */
cfdata->blang_list = eina_list_sort(cfdata->blang_list,
eina_list_count(cfdata->blang_list),
_basic_lang_list_sort);
while (e_lang_list)
{
free(e_lang_list->data);
e_lang_list = eina_list_remove_list(e_lang_list, e_lang_list);
}
pclose(output);
}
/* Make sure we know the currently configured locale */
if (e_config->language)
cfdata->cur_language = strdup(e_config->language);
return;
}
static void *
_create_data(E_Config_Dialog *cfd)
{
E_Config_Dialog_Data *cfdata;
cfdata = E_NEW(E_Config_Dialog_Data, 1);
cfdata->cfd = cfd;
_fill_data(cfdata);
return cfdata;
}
static void
_free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
{
E_FREE(cfdata->cur_language);
E_FREE(cfdata->cur_blang);
E_FREE(cfdata->cur_lang);
E_FREE(cfdata->cur_reg);
E_FREE(cfdata->cur_cs);
E_FREE(cfdata->cur_mod);
eina_hash_foreach(cfdata->locale_hash, _language_hash_free_cb, NULL);
eina_hash_free(cfdata->locale_hash);
cfdata->lang_list = eina_list_free(cfdata->lang_list);
cfdata->region_list = eina_list_free(cfdata->region_list);
cfdata->blang_list = eina_list_free(cfdata->blang_list);
E_FREE(cfdata);
}
static Eina_Bool
_language_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
{
E_Intl_Language_Node *node;
node = data;
if (node->lang_code) eina_stringshare_del(node->lang_code);
eina_hash_foreach(node->region_hash, _region_hash_free_cb, NULL);
eina_hash_free(node->region_hash);
free(node);
return 1;
}
static Eina_Bool
_region_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
{
E_Intl_Region_Node *node;
node = data;
if (node->region_code) eina_stringshare_del(node->region_code);
while (node->available_codesets)
{
const char *str;
str = node->available_codesets->data;
if (str) eina_stringshare_del(str);
node->available_codesets =
eina_list_remove_list(node->available_codesets, node->available_codesets);
}
while (node->available_modifiers)
{
const char *str;
str = node->available_modifiers->data;
if (str) eina_stringshare_del(str);
node->available_modifiers =
eina_list_remove_list(node->available_modifiers, node->available_modifiers);
}
free(node);
return 1;
}
static int
_basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
{
if (cfdata->cur_language)
{
if (e_config->language) eina_stringshare_del(e_config->language);
e_config->language = eina_stringshare_add(cfdata->cur_language);
e_intl_language_set(e_config->language);
}
e_config_save_queue();
return 1;
}
static int
_advanced_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
{
if (cfdata->cur_language)
{
if (e_config->language) eina_stringshare_del(e_config->language);
e_config->language = eina_stringshare_add(cfdata->cur_language);
e_intl_language_set(e_config->language);
}
e_config_save_queue();
return 1;
}
static Evas_Object *
_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
{
Evas_Object *o, *of, *ob;
char *cur_sig_loc;
Eina_List *next;
int i = 0;
cfdata->evas = evas;
o = e_widget_table_add(evas, 0);
of = e_widget_framelist_add(evas, _("Language Selector"), 0);
ob = e_widget_ilist_add(evas, 16, 16, &(cfdata->cur_blang));
e_widget_min_size_set(ob, 175, 175);
e_widget_on_change_hook_set(ob, _ilist_basic_language_cb_change, cfdata);
cfdata->gui.blang_list = ob;
e_widget_framelist_object_append(of, ob);
e_widget_table_object_append(o, of, 0, 0, 1, 1, 1, 1, 1, 1);
/* Load languages */
evas_event_freeze(evas_object_evas_get(ob));
edje_freeze();
e_widget_ilist_freeze(ob);
if (cfdata->cur_language)
{
E_Locale_Parts *locale_parts;
locale_parts = e_intl_locale_parts_get(cfdata->cur_language);
if (locale_parts)
{
cur_sig_loc = e_intl_locale_parts_combine(locale_parts,
E_INTL_LOC_LANG | E_INTL_LOC_REGION);
e_intl_locale_parts_free(locale_parts);
}
else
cur_sig_loc = NULL;
}
else
cur_sig_loc = NULL;
for (next = cfdata->blang_list; next; next = next->next)
{
E_Intl_Pair *pair;
const char *key;
const char *trans;
pair = next->data;
key = pair->locale_key;
trans = _(pair->locale_translation);
e_widget_ilist_append(cfdata->gui.blang_list, NULL, trans, NULL, NULL, key);
if (cur_sig_loc && !strncmp(key, cur_sig_loc, strlen(cur_sig_loc)))
e_widget_ilist_selected_set(cfdata->gui.blang_list, i);
i++;
}
E_FREE(cur_sig_loc);
e_widget_ilist_go(ob);
e_widget_ilist_thaw(ob);
edje_thaw();
evas_event_thaw(evas_object_evas_get(ob));
of = e_widget_frametable_add(evas, _("Locale Selected"), 0);
ob = e_widget_label_add(evas, _("Locale"));
e_widget_frametable_object_append(of, ob, 0, 0, 1, 1, 1, 0, 1, 0);
ob = e_widget_entry_add(evas, &(cfdata->cur_language), NULL, NULL, NULL);
cfdata->gui.locale_entry = ob;
e_widget_disabled_set(cfdata->gui.locale_entry, 1);
e_widget_min_size_set(cfdata->gui.locale_entry, 100, 25);
e_widget_frametable_object_append(of, cfdata->gui.locale_entry,
0, 1, 1, 1, 1, 1, 1, 0);
e_widget_table_object_append(o, of, 0, 1, 1, 1, 1, 0, 1, 0);
e_dialog_resizable_set(cfd->dia, 1);
return o;
}
static Evas_Object *
_advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
{
Evas_Object *o, *of, *ob;
const char *lang, *reg, *cs, *mod;
cfdata->evas = evas;
_intl_current_locale_setup(cfdata);
o = e_widget_table_add(evas, 0);
of = e_widget_framelist_add(evas, _("Language Selector"), 1);
/* Language List */
ob = e_widget_ilist_add(evas, 16, 16, &(cfdata->cur_lang));
cfdata->gui.lang_list = ob;
/* If lang_list already loaded just use it */
if (cfdata->lang_list == NULL)
eina_hash_foreach(cfdata->locale_hash, _lang_hash_cb, cfdata);
if (cfdata->lang_list)
{
cfdata->lang_list =
eina_list_sort(cfdata->lang_list, eina_list_count(cfdata->lang_list),
_lang_list_sort);
_lang_list_load(cfdata);
}
e_widget_ilist_go(ob);
e_widget_min_size_set(ob, 140, 200);
e_widget_framelist_object_append(of, ob);
e_widget_ilist_selected_set(ob, e_widget_ilist_selected_get(ob));
/* Region List */
ob = e_widget_ilist_add(evas, 0, 0, &(cfdata->cur_reg));
cfdata->gui.reg_list = ob;
e_widget_ilist_go(ob);
e_widget_min_size_set(ob, 100, 100);
e_widget_framelist_object_append(of, ob);
e_widget_ilist_selected_set(ob, e_widget_ilist_selected_get(ob));
/* Codeset List */
ob = e_widget_ilist_add(evas, 0, 0, &(cfdata->cur_cs));
cfdata->gui.cs_list = ob;
e_widget_ilist_go(ob);
e_widget_min_size_set(ob, 100, 100);
e_widget_framelist_object_append(of, ob);
/* Modified List */
ob = e_widget_ilist_add(evas, 0, 0, &(cfdata->cur_mod));
cfdata->gui.mod_list = ob;
e_widget_ilist_go(ob);
e_widget_min_size_set(ob, 100, 100);
e_widget_framelist_object_append(of, ob);
e_widget_table_object_append(o, of, 0, 0, 1, 1, 1, 1, 1, 1);
/* Locale selector */
of = e_widget_frametable_add(evas, _("Locale Selected"), 0);
ob = e_widget_label_add(evas, _("Locale"));
e_widget_frametable_object_append(of, ob, 0, 0, 1, 1, 1, 0, 1, 0);
ob = e_widget_entry_add(evas, &(cfdata->cur_language), NULL, NULL, NULL);
cfdata->gui.locale_entry = ob;
e_widget_disabled_set(cfdata->gui.locale_entry, 1);
e_widget_min_size_set(cfdata->gui.locale_entry, 100, 25);
e_widget_frametable_object_append(of, cfdata->gui.locale_entry,
0, 1, 1, 1, 1, 1, 1, 0);
e_widget_table_object_append(o, of, 0, 1, 1, 1, 1, 0, 1, 0);
/* all these cur_* values are not guaranteed to be const so we need to
* copy them.
*/
lang = NULL;
reg = NULL;
cs = NULL;
mod = NULL;
if (cfdata->cur_lang) lang = eina_stringshare_add(cfdata->cur_lang);
if (cfdata->cur_reg) reg = eina_stringshare_add(cfdata->cur_reg);
if (cfdata->cur_cs) cs = eina_stringshare_add(cfdata->cur_cs);
if (cfdata->cur_mod) mod = eina_stringshare_add(cfdata->cur_mod);
_cfdata_language_go(lang, reg, cs, mod, cfdata);
if (lang) eina_stringshare_del(lang);
if (reg) eina_stringshare_del(reg);
if (cs) eina_stringshare_del(cs);
if (mod) eina_stringshare_del(mod);
e_widget_on_change_hook_set(cfdata->gui.lang_list, _ilist_language_cb_change, cfdata);
e_widget_on_change_hook_set(cfdata->gui.reg_list, _ilist_region_cb_change, cfdata);
e_widget_on_change_hook_set(cfdata->gui.cs_list, _ilist_codeset_cb_change, cfdata);
e_widget_on_change_hook_set(cfdata->gui.mod_list, _ilist_modifier_cb_change, cfdata);
e_dialog_resizable_set(cfd->dia, 1);
return o;
}
static void
_ilist_basic_language_cb_change(void *data, Evas_Object *obj)
{
E_Config_Dialog_Data * cfdata;
cfdata = data;
e_widget_entry_text_set(cfdata->gui.locale_entry, cfdata->cur_blang);
}
static void
_ilist_language_cb_change(void *data, Evas_Object *obj)
{
E_Config_Dialog_Data * cfdata;
cfdata = data;
_cfdata_language_go(cfdata->cur_lang, NULL, NULL, NULL, cfdata);
e_widget_entry_text_set(cfdata->gui.locale_entry, cfdata->cur_lang);
E_FREE(cfdata->cur_cs);
E_FREE(cfdata->cur_mod);
}
static void
_ilist_region_cb_change(void *data, Evas_Object *obj)
{
E_Config_Dialog_Data * cfdata;
char locale[32];
cfdata = data;
_cfdata_language_go(cfdata->cur_lang, cfdata->cur_reg, NULL, NULL, cfdata);
sprintf(locale, "%s_%s", cfdata->cur_lang, cfdata->cur_reg);
e_widget_entry_text_set(cfdata->gui.locale_entry, locale);
E_FREE(cfdata->cur_cs);
E_FREE(cfdata->cur_mod);
}
static void
_ilist_codeset_cb_change(void *data, Evas_Object *obj)
{
E_Config_Dialog_Data * cfdata;
char locale[32];
cfdata = data;
if (cfdata->cur_mod)
sprintf(locale, "%s_%s.%s@%s", cfdata->cur_lang, cfdata->cur_reg, cfdata->cur_cs, cfdata->cur_mod);
else
sprintf(locale, "%s_%s.%s", cfdata->cur_lang, cfdata->cur_reg, cfdata->cur_cs);
e_widget_entry_text_set(cfdata->gui.locale_entry, locale);
}
static void
_ilist_modifier_cb_change(void *data, Evas_Object *obj)
{
E_Config_Dialog_Data * cfdata;
char locale[32];
cfdata = data;
if (cfdata->cur_cs)
sprintf(locale, "%s_%s.%s@%s", cfdata->cur_lang, cfdata->cur_reg, cfdata->cur_cs, cfdata->cur_mod);
else
sprintf(locale, "%s_%s@%s", cfdata->cur_lang, cfdata->cur_reg, cfdata->cur_mod);
e_widget_entry_text_set(cfdata->gui.locale_entry, locale);
}
static void
_cfdata_language_go(const char *lang, const char *region, const char *codeset, const char *modifier, E_Config_Dialog_Data *cfdata)
{
E_Intl_Language_Node *lang_node;
int lang_update;
int region_update;
/* Check what changed */
lang_update = 0;
region_update = 0;
evas_event_freeze(evas_object_evas_get(cfdata->gui.cs_list));
evas_event_freeze(evas_object_evas_get(cfdata->gui.mod_list));
edje_freeze();
e_widget_ilist_freeze(cfdata->gui.cs_list);
e_widget_ilist_freeze(cfdata->gui.mod_list);
if (cfdata->lang_dirty || (lang && !region))
{
lang_update = 1;
region_update = 1;
e_widget_ilist_clear(cfdata->gui.cs_list);
e_widget_ilist_clear(cfdata->gui.mod_list);
}
if (lang && region)
{
region_update = 1;
e_widget_ilist_clear(cfdata->gui.cs_list);
e_widget_ilist_clear(cfdata->gui.mod_list);
}
cfdata->lang_dirty = 0;
if (lang)
{
lang_node = eina_hash_find(cfdata->locale_hash, lang);
if (lang_node)
{
if (lang_update)
{
e_widget_ilist_clear(cfdata->gui.reg_list);
cfdata->region_list = eina_list_free(cfdata->region_list);
eina_hash_foreach(lang_node->region_hash,
_region_hash_cb, cfdata);
cfdata->region_list =
eina_list_sort(cfdata->region_list,
eina_list_count(cfdata->region_list),
_region_list_sort);
_region_list_load(cfdata);
}
if (region && region_update)
{
E_Intl_Region_Node *reg_node;
reg_node = eina_hash_find(lang_node->region_hash, region);
if (reg_node)
{
Eina_List *next;
for (next = reg_node->available_codesets; next; next = next->next)
{
const char * cs;
cs = next->data;
e_widget_ilist_append(cfdata->gui.cs_list, NULL, cs, NULL, NULL, cs);
if (codeset && !strcmp(cs, codeset))
{
int count;
count = e_widget_ilist_count(cfdata->gui.cs_list);
e_widget_ilist_selected_set(cfdata->gui.cs_list, count - 1);
}
}
for (next = reg_node->available_modifiers; next; next = next->next)
{
const char * mod;
mod = next->data;
e_widget_ilist_append(cfdata->gui.mod_list, NULL, mod, NULL, NULL, mod);
if (modifier && !strcmp(mod, modifier))
{
int count;
count = e_widget_ilist_count(cfdata->gui.mod_list);
e_widget_ilist_selected_set(cfdata->gui.mod_list, count - 1);
}
}
}
e_widget_ilist_go(cfdata->gui.cs_list);
e_widget_ilist_go(cfdata->gui.mod_list);
}
}
}
e_widget_ilist_thaw(cfdata->gui.cs_list);
e_widget_ilist_thaw(cfdata->gui.mod_list);
edje_thaw();
evas_event_thaw(evas_object_evas_get(cfdata->gui.cs_list));
evas_event_thaw(evas_object_evas_get(cfdata->gui.mod_list));
e_widget_ilist_go(cfdata->gui.reg_list);
}
static Eina_Bool
_lang_hash_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata)
{
E_Config_Dialog_Data *cfdata;
E_Intl_Language_Node *lang_node;
cfdata = fdata;
lang_node = data;
cfdata->lang_list = eina_list_append(cfdata->lang_list, lang_node);
return 1;
}
static Eina_Bool
_region_hash_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata)
{
E_Config_Dialog_Data *cfdata;
E_Intl_Region_Node *reg_node;
cfdata = fdata;
reg_node = data;
cfdata->region_list = eina_list_append(cfdata->region_list, reg_node);
return 1;
}
void
_intl_current_locale_setup(E_Config_Dialog_Data *cfdata)
{
E_FREE(cfdata->cur_lang);
E_FREE(cfdata->cur_reg);
E_FREE(cfdata->cur_cs);
E_FREE(cfdata->cur_mod);
cfdata->cur_lang = NULL;
cfdata->cur_reg = NULL;
cfdata->cur_cs = NULL;
cfdata->cur_mod = NULL;
if (cfdata->cur_language)
{
E_Locale_Parts *locale_parts;
locale_parts = e_intl_locale_parts_get(cfdata->cur_language);
if (locale_parts)
{
if (locale_parts->lang)
cfdata->cur_lang = strdup(locale_parts->lang);
if (locale_parts->region)
cfdata->cur_reg = strdup(locale_parts->region);
if (locale_parts->codeset)
{
const char *cs_trans;
cs_trans = _intl_charset_upper_get(locale_parts->codeset);
if (cs_trans == NULL)
cfdata->cur_cs = strdup(locale_parts->codeset);
else
cfdata->cur_cs = strdup(cs_trans);
}
if (locale_parts->modifier)
cfdata->cur_mod = strdup(locale_parts->modifier);
}
e_intl_locale_parts_free(locale_parts);
}
cfdata->lang_dirty = 1;
}
static int
_lang_list_sort(const void *data1, const void *data2)
{
const E_Intl_Language_Node *ln1, *ln2;
const char *trans1;
const char *trans2;
if (!data1) return 1;
if (!data2) return -1;
ln1 = data1;
ln2 = data2;
if (!ln1->lang_name) return 1;
trans1 = ln1->lang_name;
if (!ln2->lang_name) return -1;
trans2 = ln2->lang_name;
return (strcmp(trans1, trans2));
}
static void
_lang_list_load(void *data)
{
E_Config_Dialog_Data *cfdata;
Eina_List *l;
if (!data) return;
cfdata = data;
if (!cfdata->lang_list) return;
evas_event_freeze(evas_object_evas_get(cfdata->gui.lang_list));
edje_freeze();
e_widget_ilist_freeze(cfdata->gui.lang_list);
for (l = cfdata->lang_list; l; l = l->next)
{
E_Intl_Language_Node *ln;
const char *trans;
ln = l->data;
if (!ln) continue;
if (ln->lang_name)
trans = ln->lang_name;
else
trans = ln->lang_code;
if (ln->lang_available)
{
Evas_Object *ic;
ic = e_icon_add(cfdata->evas);
e_util_icon_theme_set(ic, "dialog-ok-apply");
e_widget_ilist_append(cfdata->gui.lang_list, ic, trans, NULL, NULL, ln->lang_code);
}
else
e_widget_ilist_append(cfdata->gui.lang_list, NULL, trans, NULL, NULL, ln->lang_code);
if (cfdata->cur_lang && !strcmp(cfdata->cur_lang, ln->lang_code))
{
int count;
count = e_widget_ilist_count(cfdata->gui.lang_list);
e_widget_ilist_selected_set(cfdata->gui.lang_list, count - 1);
}
}
e_widget_ilist_thaw(cfdata->gui.lang_list);
edje_thaw();
evas_event_thaw(evas_object_evas_get(cfdata->gui.lang_list));
}
static int
_region_list_sort(const void *data1, const void *data2)
{
const E_Intl_Region_Node *rn1, *rn2;
const char *trans1;
const char *trans2;
if (!data1) return 1;
if (!data2) return -1;
rn1 = data1;
rn2 = data2;
if (!rn1->region_name) return 1;
trans1 = rn1->region_name;
if (!rn2->region_name) return -1;
trans2 = rn2->region_name;
return (strcmp(trans1, trans2));
}
static void
_region_list_load(void *data)
{
E_Config_Dialog_Data *cfdata;
Eina_List *l;
if (!data) return;
cfdata = data;
if (!cfdata->region_list) return;
evas_event_freeze(evas_object_evas_get(cfdata->gui.reg_list));
edje_freeze();
e_widget_ilist_freeze(cfdata->gui.reg_list);
for (l = cfdata->region_list; l; l = l->next)
{
E_Intl_Region_Node *rn;
const char *trans;
rn = l->data;
if (!rn) continue;
if (rn->region_name)
trans = rn->region_name;
else
trans = rn->region_code;
e_widget_ilist_append(cfdata->gui.reg_list, NULL, trans, NULL, NULL, rn->region_code);
if (cfdata->cur_reg && !strcmp(cfdata->cur_reg, rn->region_code))
{
int count;
count = e_widget_ilist_count(cfdata->gui.reg_list);
e_widget_ilist_selected_set(cfdata->gui.reg_list, count - 1);
}
}
e_widget_ilist_thaw(cfdata->gui.reg_list);
edje_thaw();
evas_event_thaw(evas_object_evas_get(cfdata->gui.reg_list));
}
static int
_basic_lang_list_sort(const void *data1, const void *data2)
{
const E_Intl_Pair *ln1, *ln2;
const char *trans1;
const char *trans2;
if (!data1) return 1;
if (!data2) return -1;
ln1 = data1;
ln2 = data2;
if (!ln1->locale_translation) return 1;
trans1 = ln1->locale_translation;
if (!ln2->locale_translation) return -1;
trans2 = ln2->locale_translation;
return (strcmp(trans1, trans2));
}
const char *
_intl_charset_upper_get(const char *charset)
{
int i;
i = 0;
while (charset_predefined_pairs[i].locale_key)
{
if (!strcmp(charset_predefined_pairs[i].locale_key, charset))
{
return charset_predefined_pairs[i].locale_translation;
}
i++;
}
return NULL;
}