Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / conf_intl / e_int_config_intl.c
1 #include "e.h"
2
3 typedef struct _E_Intl_Pair          E_Intl_Pair;
4 typedef struct _E_Intl_Langauge_Node E_Intl_Language_Node;
5 typedef struct _E_Intl_Region_Node   E_Intl_Region_Node;
6
7 static void        *_create_data(E_Config_Dialog *cfd);
8 static void         _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
9 static int          _advanced_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
10 static Evas_Object *_advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
11 static int          _basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
12 static Evas_Object *_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
13
14 static void         _ilist_basic_language_cb_change(void *data, Evas_Object *obj);
15 static void         _ilist_language_cb_change(void *data, Evas_Object *obj);
16 static void         _ilist_region_cb_change(void *data, Evas_Object *obj);
17 static void         _ilist_codeset_cb_change(void *data, Evas_Object *obj);
18 static void         _ilist_modifier_cb_change(void *data, Evas_Object *obj);
19 static int          _lang_list_sort(const void *data1, const void *data2);
20 static void         _lang_list_load(void *data);
21 static int          _region_list_sort(const void *data1, const void *data2);
22 static void         _region_list_load(void *data);
23 static int          _basic_lang_list_sort(const void *data1, const void *data2);
24
25 /* Fill the clear lists, fill with language, select */
26 /* Update lanague */
27 static void         _cfdata_language_go(const char *lang, const char *region, const char *codeset, const char *modifier, E_Config_Dialog_Data *cfdata);
28 static Eina_Bool    _lang_hash_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata);
29 static Eina_Bool    _region_hash_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata);
30 static Eina_Bool    _language_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__);
31 static Eina_Bool    _region_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__);
32 static void         _intl_current_locale_setup(E_Config_Dialog_Data *cfdata);
33 static const char  *_intl_charset_upper_get(const char *charset);
34
35 struct _E_Intl_Pair
36 {
37    const char *locale_key;
38    const char *locale_icon;
39    const char *locale_translation;
40 };
41
42 /* We need to store a map of languages -> Countries -> Extra
43  *
44  * Extra:
45  * Each region has its own Encodings
46  * Each region has its own Modifiers
47  */
48
49 struct _E_Intl_Langauge_Node
50 {
51    const char *lang_code; /* en */
52    const char *lang_name; /* English (trans in ilist) */
53    const char *lang_icon;
54    int         lang_available; /* defined in e translation */
55    Eina_Hash  *region_hash; /* US->utf8 */
56 };
57
58 struct _E_Intl_Region_Node
59 {
60    const char *region_code; /* US */
61    const char *region_name; /* United States */
62    const char *region_icon;
63    Eina_List  *available_codesets;
64    Eina_List  *available_modifiers;
65 };
66
67 struct _E_Config_Dialog_Data
68 {
69    E_Config_Dialog *cfd;
70    Evas            *evas;
71
72    /* Current data */
73    char            *cur_language;
74
75    const char      *cur_blang;
76
77    const char      *cur_lang;
78    const char      *cur_reg;
79    const char      *cur_cs;
80    const char      *cur_mod;
81
82    int              lang_dirty;
83
84    Eina_Hash       *locale_hash;
85    Eina_List       *lang_list;
86    Eina_List       *region_list;
87    Eina_List       *blang_list;
88
89    struct
90    {
91       Evas_Object *blang_list;
92
93       Evas_Object *lang_list;
94       Evas_Object *reg_list;
95       Evas_Object *cs_list;
96       Evas_Object *mod_list;
97
98       Evas_Object *locale_entry;
99    }
100    gui;
101 };
102
103 const E_Intl_Pair basic_language_predefined_pairs[] = {
104    {"ar_AE.UTF-8", "ara_flag.png", "العربية"},
105    {"bg_BG.UTF-8", "bg_flag.png", "Български"},
106    {"ca_ES.UTF-8", "cat_flag.png", "Català"},
107    {"cs_CZ.UTF-8", "cz_flag.png", "Čeština"},
108    {"da_DK.UTF-8", "dk_flag.png", "Dansk"},
109    {"de_DE.UTF-8", "de_flag.png", "Deutsch"},
110    {"en_US.UTF-8", "us_flag.png", "English"},
111    {"en_GB.UTF-8", "gb_flag.png", "British English"},
112    {"el_GR.UTF-8", "gr_flag.png", "Ελληνικά"},
113    {"eo.UTF-8", "epo_flag.png", "Esperanto"},
114    {"es_AR.UTF-8", "ar_flag.png", "Español"},
115    {"et_ET.UTF-8", "ee_flag.png", "Eesti keel"},
116    {"fi_FI.UTF-8", "fi_flag.png", "Suomi"},
117    {"fo_FO.UTF-8", "fo_flag.png", "Føroyskt"},
118    {"fr_CH.UTF-8", "ch_flag.png", "Français (Suisse)"},
119    {"fr_FR.UTF-8", "fr_flag.png", "Français"},
120    {"he_HE.UTF-8", "il_flag.png", "עברית"},
121    {"hr_HR.UTF-8", "hr_flag.png", "Hrvatski"},
122    {"hu_HU.UTF-8", "hu_flag.png", "Magyar"},
123    {"it_IT.UTF-8", "it_flag.png", "Italiano"},
124    {"ja_JP.UTF-8", "jp_flag.png", "日本語"},
125    {"km_KM.UTF-8", "kh_flag.png", "ភាសាខ្មែរ"},
126    {"ko_KR.UTF-8", "kr_flag.png", "한국어"},
127    {"ku.UTF-8", "ku_flag.png", "یدروك"},
128    {"lt_LT.UTF-8", "lt_flag.png", "Lietuvių kalba"},
129    {"ms_MY.UTF-8", "my_flag.png", "Bahasa Melayu"},
130    {"nb_NO.UTF-8", "no_flag.png", "Norsk Bokmål"},
131    {"nl_NL.UTF-8", "nl_flag.png", "Nederlands"},
132    {"pl_PL.UTF-8", "pl_flag.png", "Polski"},
133    {"pt_BR.UTF-8", "br_flag.png", "Português"},
134    {"ru_RU.UTF-8", "ru_flag.png", "Русский"},
135    {"sk_SK.UTF-8", "sk_flag.png", "Slovenčina"},
136    {"sl_SI.UTF-8", "si_flag.png", "Slovenščina"},
137    {"sv_SE.UTF-8", "se_flag.png", "Svenska"},
138    {"tr_TR.UTF-8", "tr_flag.png", "Türkçe"},
139    {"uk_UK.UTF-8", "ua_flag.png", "Українська мова"},
140    {"zh_CN.UTF-8", "cn_flag.png", "中文 (繁体)"},
141    {"zh_TW.UTF-8", "tw_flag.png", "中文 (繁體)"},
142    { NULL, NULL, NULL }
143 };
144
145 const E_Intl_Pair language_predefined_pairs[] = {
146    {"aa", NULL, "Qafár af"},
147    {"af", NULL, "Afrikaans"},
148    {"ak", NULL, "Akan"},
149    {"am", NULL, "አማርኛ"},
150    {"an", NULL, "Aragonés"},
151    {"ar", NULL, "ةيبرعلا"},
152    {"as", NULL, "অসমীয়া"},
153    {"az", NULL, "Azərbaycan dili"},
154    {"be", NULL, "Беларуская мова"},
155    {"bg", NULL, "Български"},
156    {"bn", NULL, "বাংলা"},
157    {"br", NULL, "Brezhoneg"},
158    {"bs", NULL, "Bosanski"},
159    {"byn", NULL, "ብሊና"},
160    {"ca", NULL, "Català"},
161    {"cch", NULL, "Atsam"},
162    {"cs", NULL, "Čeština"},
163    {"cy", NULL, "Cymraeg"},
164    {"da", NULL, "Dansk"},
165    {"de", NULL, "Deutsch"},
166    {"dv", NULL, "ދިވެހި"},
167    {"dz", NULL, "Dzongkha"},
168    {"ee", NULL, "Eʋegbe"},
169    {"el", NULL, "Ελληνικά"},
170    {"en", NULL, "English"},
171    {"eo", NULL, "Esperanto"},
172    {"es", NULL, "Español"},
173    {"et", NULL, "Eesti keel"},
174    {"eu", NULL, "Euskara"},
175    {"fa", NULL, "یسراف"},
176    {"fi", NULL, "Suomi"},
177    {"fo", NULL, "Føroyskt"},
178    {"fr", NULL, "Français"},
179    {"fur", NULL, "Furlan"},
180    {"ga", NULL, "Gaeilge"},
181    {"gaa", NULL, "Gã"},
182    {"gez", NULL, "ግዕዝ"},
183    {"gl", NULL, "Galego"},
184    {"gu", NULL, "Gujarati"},
185    {"gv", NULL, "Yn Ghaelg"},
186    {"ha", NULL, "Hausa"},
187    {"haw", NULL, "ʻŌlelo Hawaiʻi"},
188    {"he", NULL, "עברית"},
189    {"hi", NULL, "Hindi"},
190    {"hr", NULL, "Hrvatski"},
191    {"hu", NULL, "Magyar"},
192    {"hy", NULL, "Հայերեն"},
193    {"ia", NULL, "Interlingua"},
194    {"id", NULL, "Indonesian"},
195    {"ig", NULL, "Igbo"},
196    {"is", NULL, "Íslenska"},
197    {"it", NULL, "Italiano"},
198    {"iu", NULL, "ᐃᓄᒃᑎᑐᑦ"},
199    {"iw", NULL, "עברית"},
200    {"ja", NULL, "日本語"},
201    {"ka", NULL, "ქართული"},
202    {"kaj", NULL, "Jju"},
203    {"kam", NULL, "Kikamba"},
204    {"kcg", NULL, "Tyap"},
205    {"kfo", NULL, "Koro"},
206    {"kk", NULL, "Qazaq"},
207    {"kl", NULL, "Kalaallisut"},
208    {"km", NULL, "ភាសាខ្មែរ"},
209    {"kn", NULL, "ಕನ್ನಡ"},
210    {"ko", NULL, "한국어"},
211    {"kok", NULL, "Konkani"},
212    {"ku", NULL, "یدروك"},
213    {"kw", NULL, "Kernowek"},
214    {"ky", NULL, "Кыргыз тили"},
215    {"ln", NULL, "Lingála"},
216    {"lo", NULL, "ພາສາລາວ"},
217    {"lt", NULL, "Lietuvių kalba"},
218    {"lv", NULL, "Latviešu"},
219    {"mi", NULL, "Te Reo Māori"},
220    {"mk", NULL, "Македонски"},
221    {"ml", NULL, "മലയാളം"},
222    {"mn", NULL, "Монгол"},
223    {"mr", NULL, "मराठी"},
224    {"ms", NULL, "Bahasa Melayu"},
225    {"mt", NULL, "Malti"},
226    {"nb", NULL, "Norsk Bokmål"},
227    {"ne", NULL, "नेपाली"},
228    {"nl", NULL, "Nederlands"},
229    {"nn", NULL, "Norsk Nynorsk"},
230    {"no", NULL, "Norsk"},
231    {"nr", NULL, "isiNdebele"},
232    {"nso", NULL, "Sesotho sa Leboa"},
233    {"ny", NULL, "Chicheŵa"},
234    {"oc", NULL, "Occitan"},
235    {"om", NULL, "Oromo"},
236    {"or", NULL, "ଓଡ଼ିଆ"},
237    {"pa", NULL, "ਪੰਜਾਬੀ"},
238    {"pl", NULL, "Polski"},
239    {"ps", NULL, "وتښپ"},
240    {"pt", NULL, "Português"},
241    {"ro", NULL, "Română"},
242    {"ru", NULL, "Русский"},
243    {"rw", NULL, "Kinyarwanda"},
244    {"sa", NULL, "संस्कृतम्"},
245    {"se", NULL, "Davvisápmi"},
246    {"sh", NULL, "Srpskohrvatski/Српскохрватски"},
247    {"sid", NULL, "Sidámo 'Afó"},
248    {"sk", NULL, "Slovenčina"},
249    {"sl", NULL, "Slovenščina"},
250    {"so", NULL, "af Soomaali"},
251    {"sq", NULL, "Shqip"},
252    {"sr", NULL, "Српски"},
253    {"ss", NULL, "Swati"},
254    {"st", NULL, "Southern Sotho"},
255    {"sv", NULL, "Svenska"},
256    {"sw", NULL, "Swahili"},
257    {"syr", NULL, "Syriac"},
258    {"ta", NULL, "தமிழ்"},
259    {"te", NULL, "తెలుగు"},
260    {"tg", NULL, "Тоҷикӣ"},
261    {"th", NULL, "ภาษาไทย"},
262    {"ti", NULL, "ትግርኛ"},
263    {"tig", NULL, "ቲግሬ"},
264    {"tl", NULL, "Tagalog"},
265    {"tn", NULL, "Setswana"},
266    {"tr", NULL, "Türkçe"},
267    {"ts", NULL, "Tsonga"},
268    {"tt", NULL, "Татарча"},
269    {"uk", NULL, "Українська мова"},
270    {"ur", NULL, "ودراُ"},
271    {"uz", NULL, "O‘zbek"},
272    {"ve", NULL, "Venda"},
273    {"vi", NULL, "Tiếng Việt"},
274    {"wa", NULL, "Walon"},
275    {"wal", NULL, "Walamo"},
276    {"xh", NULL, "Xhosa"},
277    {"yi", NULL, "שידיִי"},
278    {"yo", NULL, "èdèe Yorùbá"},
279    {"zh", NULL, "汉语/漢語"},
280    {"zu", NULL, "Zulu"},
281    { NULL, NULL, NULL}
282 };
283
284 const E_Intl_Pair region_predefined_pairs[] = {
285    { "AF", "af_flag.png", "Afghanistan"},
286    { "AX", NULL, "Åland"},
287    { "AL", "al_flag.png", "Shqipëria"},
288    { "DZ", NULL, "Algeria"},
289    { "AS", NULL, "Amerika Sāmoa"},
290    { "AD", "ad_flag.png", "Andorra"},
291    { "AO", NULL, "Angola"},
292    { "AI", NULL, "Anguilla"},
293    { "AQ", NULL, "Antarctica"},
294    { "AG", NULL, "Antigua and Barbuda"},
295    { "AR", "ar_flag.png", "Argentina"},
296    { "AM", "am_flag.png", "Հայաստան"},
297    { "AW", NULL, "Aruba"},
298    { "AU", NULL, "Australia"},
299    { "AT", "at_flag.png", "Österreich"},
300    { "AZ", "az_flag.png", "Azərbaycan"},
301    { "BS", NULL, "Bahamas"},
302    { "BH", NULL, "Bahrain"},
303    { "BD", "bd_flag.png", "বাংলাদেশ"},
304    { "BB", NULL, "Barbados"},
305    { "BY", "by_flag.png", "Беларусь"},
306    { "BE", "be_flag.png", "Belgium"},
307    { "BZ", NULL, "Belize"},
308    { "BJ", NULL, "Bénin"},
309    { "BM", NULL, "Bermuda"},
310    { "BT", "bt_flag.png", "Bhutan"},
311    { "BO", NULL, "Bolivia"},
312    { "BA", "ba_flag.png", "Bosnia and Herzegovina"},
313    { "BW", "bw_flag.png", "Botswana"},
314    { "BV", NULL, "Bouvetøya"},
315    { "BR", "br_flag.png", "Brazil"},
316    { "IO", NULL, "British Indian Ocean Territory"},
317    { "BN", NULL, "Brunei Darussalam"},
318    { "BG", "bg_flag.png", "България"},
319    { "BF", NULL, "Burkina Faso"},
320    { "BI", NULL, "Burundi"},
321    { "KH", "kh_flag.png", "Cambodia"},
322    { "CM", "cm_flag.png", "Cameroon"},
323    { "CA", "ca_flag.png", "Canada"},
324    { "CV", NULL, "Cape Verde"},
325    { "KY", NULL, "Cayman Islands"},
326    { "CF", NULL, "Central African Republic"},
327    { "TD", NULL, "Chad"},
328    { "CL", NULL, "Chile"},
329    { "CN", "cn_flag.png", "中國"},
330    { "CX", NULL, "Christmas Island"},
331    { "CC", NULL, "Cocos (keeling) Islands"},
332    { "CO", NULL, "Colombia"},
333    { "KM", NULL, "Comoros"},
334    { "CG", NULL, "Congo"},
335    { "CD", "cd_flag.png", "Congo"},
336    { "CK", NULL, "Cook Islands"},
337    { "CR", NULL, "Costa Rica"},
338    { "CI", NULL, "Cote d'Ivoire"},
339    { "HR", "hr_flag.png", "Hrvatska"},
340    { "CU", NULL, "Cuba"},
341    { "CY", NULL, "Cyprus"},
342    { "CZ", "cz_flag.png", "Česká republika"},
343    { "DK", "dk_flag.png", "Danmark"},
344    { "DJ", NULL, "Djibouti"},
345    { "DM", NULL, "Dominica"},
346    { "DO", NULL, "República Dominicana"},
347    { "EC", NULL, "Ecuador"},
348    { "EG", NULL, "Egypt"},
349    { "SV", NULL, "El Salvador"},
350    { "GQ", NULL, "Equatorial Guinea"},
351    { "ER", NULL, "Eritrea"},
352    { "EE", "ee_flag.png", "Eesti"},
353    { "ET", "et_flag.png", "Ethiopia"},
354    { "FK", NULL, "Falkland Islands (malvinas)"},
355    { "FO", "fo_flag.png", "Faroe Islands"},
356    { "FJ", NULL, "Fiji"},
357    { "FI", "fi_flag.png", "Finland"},
358    { "FR", "fr_flag.png", "France"},
359    { "GF", NULL, "French Guiana"},
360    { "PF", NULL, "French Polynesia"},
361    { "TF", NULL, "French Southern Territories"},
362    { "GA", NULL, "Gabon"},
363    { "GM", NULL, "Gambia"},
364    { "GE", "ge_flag.png", "Georgia"},
365    { "DE", "de_flag.png", "Deutschland"},
366    { "GH", "gh_flag.png", "Ghana"},
367    { "GI", NULL, "Gibraltar"},
368    { "GR", "gr_flag.png", "Greece"},
369    { "GL", NULL, "Greenland"},
370    { "GD", NULL, "Grenada"},
371    { "GP", NULL, "Guadeloupe"},
372    { "GU", NULL, "Guam"},
373    { "GT", NULL, "Guatemala"},
374    { "GG", NULL, "Guernsey"},
375    { "GN", "gn_flag.png", "Guinea"},
376    { "GW", NULL, "Guinea-Bissau"},
377    { "GY", NULL, "Guyana"},
378    { "HT", NULL, "Haiti"},
379    { "HM", NULL, "Heard Island and Mcdonald Islands"},
380    { "VA", NULL, "Holy See (Vatican City State)"},
381    { "HN", NULL, "Honduras"},
382    { "HK", NULL, "Hong Kong"},
383    { "HU", "hu_flag.png", "Magyarország"},
384    { "IS", "is_flag.png", "Iceland"},
385    { "IN", "in_flag.png", "India"},
386    { "ID", NULL, "Indonesia"},
387    { "IR", "ir_flag.png", "Iran"},
388    { "IQ", "iq_flag.png", "Iraq"},
389    { "IE", "ie_flag.png", "Éire"},
390    { "IM", NULL, "Isle Of Man"},
391    { "IL", "il_flag.png", "Israel"},
392    { "IT", "it_flag.png", "Italia"},
393    { "JM", NULL, "Jamaica"},
394    { "JP", "jp_flag.png", "日本"},
395    { "JE", NULL, "Jersey"},
396    { "JO", NULL, "Jordan"},
397    { "KZ", "kz_flag.png", "Kazakhstan"},
398    { "KE", "ke_flag.png", "Kenya"},
399    { "KI", NULL, "Kiribati"},
400    { "KP", NULL, "Korea"},
401    { "KR", "kr_flag.png", "Korea"},
402    { "KW", NULL, "Kuwait"},
403    { "KG", "kg_flag.png", "Kyrgyzstan"},
404    { "LA", "la_flag.png", "Lao People's Democratic Republic"},
405    { "LV", "lv_flag.png", "Latvija"},
406    { "LB", NULL, "Lebanon"},
407    { "LS", NULL, "Lesotho"},
408    { "LR", NULL, "Liberia"},
409    { "LY", NULL, "Libyan Arab Jamahiriya"},
410    { "LI", NULL, "Liechtenstein"},
411    { "LT", "lt_flag.png", "Lietuva"},
412    { "LU", NULL, "Lëtzebuerg"},
413    { "MO", NULL, "Macao"},
414    { "MK", "mk_flag.png", "Македонија"},
415    { "MG", NULL, "Madagascar"},
416    { "MW", NULL, "Malawi"},
417    { "MY", "my_flag.png", "Malaysia"},
418    { "MV", "mv_flag.png", "Maldives"},
419    { "ML", "ml_flag.png", "Mali"},
420    { "MT", "mt_flag.png", "Malta"},
421    { "MH", NULL, "Marshall Islands"},
422    { "MQ", NULL, "Martinique"},
423    { "MR", NULL, "Mauritania"},
424    { "MU", NULL, "Mauritius"},
425    { "YT", NULL, "Mayotte"},
426    { "MX", NULL, "Mexico"},
427    { "FM", NULL, "Micronesia"},
428    { "MD", NULL, "Moldova"},
429    { "MC", NULL, "Monaco"},
430    { "MN", "mn_flag.png", "Mongolia"},
431    { "ME", NULL, "Montenegro"},
432    { "MS", NULL, "Montserrat"},
433    { "MA", "ma_flag.png", "Morocco"},
434    { "MZ", NULL, "Mozambique"},
435    { "MM", "mm_flag.png", "Myanmar"},
436    { "NA", NULL, "Namibia"},
437    { "NR", NULL, "Nauru"},
438    { "NP", "np_flag.png", "Nepal"},
439    { "NL", "nl_flag.png", "Nederland"},
440    { "AN", NULL, "Netherlands Antilles"},
441    { "NC", NULL, "New Caledonia"},
442    { "NZ", NULL, "New Zealand"},
443    { "NI", NULL, "Nicaragua"},
444    { "NE", NULL, "Niger"},
445    { "NG", "ng_flag.png", "Nigeria"},
446    { "NU", NULL, "Niue"},
447    { "NF", NULL, "Norfolk Island"},
448    { "MP", NULL, "Northern Mariana Islands"},
449    { "NO", "no_flag.png", "Norge"},
450    { "OM", NULL, "Oman"},
451    { "PK", "pk_flag.png", "Pakistan"},
452    { "PW", NULL, "Palau"},
453    { "PS", NULL, "Palestinian Territory"},
454    { "PA", NULL, "Panama"},
455    { "PG", NULL, "Papua New Guinea"},
456    { "PY", NULL, "Paraguay"},
457    { "PE", NULL, "Peru"},
458    { "PH", "ph_flag.png", "Philippines"},
459    { "PN", NULL, "Pitcairn"},
460    { "PL", "pl_flag.png", "Poland"},
461    { "PT", "pt_flag.png", "Portugal"},
462    { "PR", NULL, "Puerto Rico"},
463    { "QA", NULL, "Qatar"},
464    { "RE", NULL, "Reunion"},
465    { "RO", "ro_flag.png", "Romania"},
466    { "RU", "ru_flag.png", "Russian Federation"},
467    { "RW", NULL, "Rwanda"},
468    { "SH", NULL, "Saint Helena"},
469    { "KN", NULL, "Saint Kitts and Nevis"},
470    { "LC", NULL, "Saint Lucia"},
471    { "PM", NULL, "Saint Pierre and Miquelon"},
472    { "VC", NULL, "Saint Vincent and the Grenadines"},
473    { "WS", NULL, "Samoa"},
474    { "SM", NULL, "San Marino"},
475    { "ST", NULL, "Sao Tome and Principe"},
476    { "SA", NULL, "Saudi Arabia"},
477    { "SN", "sn_flag.png", "Senegal"},
478    { "RS", "rs_flag.png", "Serbia"},
479    { "SC", NULL, "Seychelles"},
480    { "SL", NULL, "Sierra Leone"},
481    { "SG", NULL, "Singapore"},
482    { "SK", "sk_flag.png", "Slovakia"},
483    { "SI", "si_flag.png", "Slovenia"},
484    { "SB", NULL, "Solomon Islands"},
485    { "SO", NULL, "Somalia"},
486    { "ZA", "za_flag.png", "South Africa"},
487    { "GS", NULL, "South Georgia and the South Sandwich Islands"},
488    { "ES", "es_flag.png", "Spain"},
489    { "LK", "lk_flag.png", "Sri Lanka"},
490    { "SD", NULL, "Sudan"},
491    { "SR", NULL, "Suriname"},
492    { "SJ", NULL, "Svalbard and Jan Mayen"},
493    { "SZ", NULL, "Swaziland"},
494    { "SE", "se_flag.png", "Sweden"},
495    { "CH", "ch_flag.png", "Switzerland"},
496    { "SY", "sy_flag.png", "Syrian Arab Republic"},
497    { "TW", "tw_flag.png", "Taiwan"},
498    { "TJ", "tj_flag.png", "Tajikistan"},
499    { "TZ", "tz_flag.png", "Tanzania"},
500    { "TH", "th_flag.png", "Thailand"},
501    { "TL", NULL, "Timor-Leste"},
502    { "TG", NULL, "Togo"},
503    { "TK", NULL, "Tokelau"},
504    { "TO", NULL, "Tonga"},
505    { "TT", NULL, "Trinidad and Tobago"},
506    { "TN", NULL, "Tunisia"},
507    { "TR", "tr_flag.png", "Turkey"},
508    { "TM", "tm_flag.png", "Turkmenistan"},
509    { "TC", NULL, "Turks and Caicos Islands"},
510    { "TV", NULL, "Tuvalu"},
511    { "UG", NULL, "Uganda"},
512    { "UA", "ua_flag.png", "Ukraine"},
513    { "AE", NULL, "United Arab Emirates"},
514    { "GB", "gb_flag.png", "United Kingdom"},
515    { "US", "us_flag.png", "United States"},
516    { "UM", NULL, "United States Minor Outlying Islands"},
517    { "UY", NULL, "Uruguay"},
518    { "UZ", "uz_flag.png", "Uzbekistan"},
519    { "VU", NULL, "Vanuatu"},
520    { "VE", NULL, "Venezuela"},
521    { "VN", "vn_flag.png", "Viet Nam"},
522    { "VG", NULL, "Virgin Islands"},
523    { "VI", NULL, "Virgin Islands"},
524    { "WF", NULL, "Wallis and Futuna"},
525    { "EH", NULL, "Western Sahara"},
526    { "YE", NULL, "Yemen"},
527    { "ZM", NULL, "Zambia"},
528    { "ZW", NULL, "Zimbabwe"},
529    { NULL, NULL, NULL}
530 };
531
532 /* This comes from
533    $ man charsets
534  * and
535    $ locale -a | grep -v @ | grep "\." | cut -d . -f 2 | sort -u
536  *
537  * On some machines is complains if codesets don't look like this
538  * On linux its not really a problem but BSD has issues. So we neet to
539  * make sure that locale -a output gets converted to upper-case form in
540  * all situations just to be safe.
541  */
542 const E_Intl_Pair charset_predefined_pairs[] = {
543    /* These are in locale -a but not in charsets */
544    {"cp1255", NULL, "CP1255"},
545    {"euc", NULL, "EUC"},
546    {"georgianps", NULL, "GEORGIAN-PS"},
547    {"iso885914", NULL, "ISO-8859-14"},
548    {"koi8t", NULL, "KOI8-T"},
549    {"tcvn", NULL, "TCVN"},
550    {"ujis", NULL, "UJIS"},
551
552    /* These are from charsets man page */
553    {"big5", NULL, "BIG5"},
554    {"big5hkscs", NULL, "BIG5-HKSCS"},
555    {"cp1251", NULL, "CP1251"},
556    {"eucjp", NULL, "EUC-JP"},
557    {"euckr", NULL, "EUC-KR"},
558    {"euctw", NULL, "EUC-TW"},
559    {"gb18030", NULL, "GB18030"},
560    {"gb2312", NULL, "GB2312"},
561    {"gbk", NULL, "GBK"},
562    {"iso88591", NULL, "ISO-8859-1"},
563    {"iso885913", NULL, "ISO-8859-13"},
564    {"iso885915", NULL, "ISO-8859-15"},
565    {"iso88592", NULL, "ISO-8859-2"},
566    {"iso88593", NULL, "ISO-8859-3"},
567    {"iso88595", NULL, "ISO-8859-5"},
568    {"iso88596", NULL, "ISO-8859-6"},
569    {"iso88597", NULL, "ISO-8859-7"},
570    {"iso88598", NULL, "ISO-8859-8"},
571    {"iso88599", NULL, "ISO-8859-9"},
572    {"koi8r", NULL, "KOI8-R"},
573    {"koi8u", NULL, "KOI8-U"},
574    {"tis620", NULL, "TIS-620"},
575    {"utf8", NULL, "UTF-8"},
576    { NULL, NULL, NULL }
577 };
578
579 E_Config_Dialog *
580 e_int_config_intl(E_Container *con, const char *params __UNUSED__)
581 {
582    E_Config_Dialog *cfd;
583    E_Config_Dialog_View *v;
584
585    if (e_config_dialog_find("E", "language/language_settings")) return NULL;
586    v = E_NEW(E_Config_Dialog_View, 1);
587
588    v->create_cfdata = _create_data;
589    v->free_cfdata = _free_data;
590    v->advanced.create_widgets = _advanced_create_widgets;
591    v->advanced.apply_cfdata = _advanced_apply_data;
592    v->basic.create_widgets = _basic_create_widgets;
593    v->basic.apply_cfdata = _basic_apply_data;
594
595    cfd = e_config_dialog_new(con,
596                              _("Language Settings"),
597                              "E", "language/language_settings",
598                              "preferences-desktop-locale", 0, v, NULL);
599    return cfd;
600 }
601
602 /* Build hash tables used for locale navigation. The locale information is
603  * gathered using the locale -a command.
604  *
605  * Below the following terms are used:
606  * ll - Locale Language Code (Example en)
607  * RR - Locale Region code (Example US)
608  * enc - Locale Encoding (Example UTF-8)
609  * mod - Locale Modifier (Example EURO)
610  */
611 static void
612 _fill_data(E_Config_Dialog_Data *cfdata)
613 {
614    Eina_List *e_lang_list;
615    FILE *output;
616
617    e_lang_list = e_intl_language_list();
618
619    /* Get list of all locales and start making map */
620 #ifdef __OpenBSD__
621    output = popen("ls /usr/share/locale", "r");
622 #else
623    output = popen("locale -a", "r");
624 #endif
625    if ( output )
626      {
627         char line[32];
628         while (fscanf(output, "%[^\n]\n", line) == 1)
629           {
630              E_Locale_Parts *locale_parts;
631
632              locale_parts = e_intl_locale_parts_get(line);
633
634              if (locale_parts)
635                {
636                   char *basic_language;
637
638                   basic_language = e_intl_locale_parts_combine(locale_parts, E_INTL_LOC_LANG | E_INTL_LOC_REGION);
639                   if (basic_language)
640                     {
641                        int i;
642
643                        i = 0;
644                        while (basic_language_predefined_pairs[i].locale_key)
645                          {
646                             /* if basic language is supported by E and System*/
647                             if (!strncmp(basic_language_predefined_pairs[i].locale_key,
648                                          basic_language, strlen(basic_language)))
649                               {
650                                  if (!eina_list_data_find(cfdata->blang_list, &basic_language_predefined_pairs[i]))
651                                    cfdata->blang_list = eina_list_append(cfdata->blang_list, &basic_language_predefined_pairs[i]);
652                                  break;
653                               }
654                             i++;
655                          }
656                     }
657                   E_FREE(basic_language);
658
659                   /* If the language is a valid ll_RR[.enc[@mod]] locale add it to the hash */
660                   if (locale_parts->lang)
661                     {
662                        E_Intl_Language_Node *lang_node;
663                        E_Intl_Region_Node *region_node;
664
665                        /* Add the language to the new locale properties to the hash */
666                        /* First check if the LANGUAGE exists in there already */
667
668                        lang_node = eina_hash_find(cfdata->locale_hash, locale_parts->lang);
669                        if (!lang_node)
670                          {
671                             Eina_List *next;
672                             int i;
673
674                             /* create new node */
675                             lang_node = E_NEW(E_Intl_Language_Node, 1);
676
677                             lang_node->lang_code = eina_stringshare_add(locale_parts->lang);
678
679                             /* Check if the language list exists */
680                             /* Linear Search */
681                             for (next = e_lang_list; next; next = next->next)
682                               {
683                                  char *e_lang;
684
685                                  e_lang = next->data;
686                                  if (!strncmp(e_lang, locale_parts->lang, 2) || !strcmp("en", locale_parts->lang))
687                                    {
688                                       lang_node->lang_available = 1;
689                                       break;
690                                    }
691                               }
692
693                             /* Search for translation */
694                             /* Linear Search */
695                             i = 0;
696                             while (language_predefined_pairs[i].locale_key)
697                               {
698                                  if (!strcmp(language_predefined_pairs[i].locale_key, locale_parts->lang))
699                                    {
700                                       lang_node->lang_name = _(language_predefined_pairs[i].locale_translation);
701                                       lang_node->lang_icon = language_predefined_pairs[i].locale_icon;
702                                       break;
703                                    }
704                                  i++;
705                               }
706
707                             if (!cfdata->locale_hash)
708                               cfdata->locale_hash = eina_hash_string_superfast_new(NULL);
709                             eina_hash_add(cfdata->locale_hash, locale_parts->lang, lang_node);
710                          }
711
712                        /* We now have the current language hash node, lets see if there is
713                           region data that needs to be added.
714                         */
715
716                        if (locale_parts->region)
717                          {
718                             region_node = eina_hash_find(lang_node->region_hash, locale_parts->region);
719
720                             if (!region_node)
721                               {
722                                  int i;
723
724                                  /* create new node */
725                                  region_node = E_NEW(E_Intl_Region_Node, 1);
726                                  region_node->region_code = eina_stringshare_add(locale_parts->region);
727
728                                  /* Get the region translation */
729                                  /* Linear Search */
730                                  i = 0;
731                                  while (region_predefined_pairs[i].locale_key)
732                                    {
733                                       if (!strcmp(region_predefined_pairs[i].locale_key, locale_parts->region))
734                                         {
735                                            region_node->region_name = _(region_predefined_pairs[i].locale_translation);
736                                            region_node->region_icon = region_predefined_pairs[i].locale_icon;
737                                            break;
738                                         }
739                                       i++;
740                                    }
741                                  if (!lang_node->region_hash)
742                                    lang_node->region_hash = eina_hash_string_superfast_new(NULL);
743                                  eina_hash_add(lang_node->region_hash, locale_parts->region, region_node);
744                               }
745
746                             /* We now have the current region hash node */
747                             /* Add codeset to the region hash node if it exists */
748                             if (locale_parts->codeset)
749                               {
750                                  const char *cs = NULL;
751                                  const char *cs_trans;
752
753                                  cs_trans = _intl_charset_upper_get(locale_parts->codeset);
754                                  if (!cs_trans)
755                                    cs = eina_stringshare_add(locale_parts->codeset);
756                                  else
757                                    cs = eina_stringshare_add(cs_trans);
758
759                                  /* Exclusive */
760                                  /* Linear Search */
761                                  if (!eina_list_data_find(region_node->available_codesets, cs))
762                                    region_node->available_codesets = eina_list_append(region_node->available_codesets, cs);
763                                  else eina_stringshare_del(cs);
764                               }
765
766                             /* Add modifier to the region hash node if it exists */
767                             if (locale_parts->modifier)
768                               {
769                                  const char *mod;
770
771                                  mod = eina_stringshare_add(locale_parts->modifier);
772                                  /* Find only works here because we are using stringshare*/
773
774                                  /* Exclusive */
775                                  /* Linear Search */
776                                  if (!eina_list_data_find(region_node->available_modifiers, mod))
777                                    region_node->available_modifiers = eina_list_append(region_node->available_modifiers, mod);
778                               }
779                          }
780                     }
781                   e_intl_locale_parts_free(locale_parts);
782                }
783           }
784
785         /* Sort basic languages */
786         cfdata->blang_list = eina_list_sort(cfdata->blang_list,
787                                             eina_list_count(cfdata->blang_list),
788                                             _basic_lang_list_sort);
789
790         while (e_lang_list)
791           {
792              free(e_lang_list->data);
793              e_lang_list = eina_list_remove_list(e_lang_list, e_lang_list);
794           }
795         pclose(output);
796      }
797
798    /* Make sure we know the currently configured locale */
799    if (e_config->language)
800      cfdata->cur_language = strdup(e_config->language);
801
802    return;
803 }
804
805 static void *
806 _create_data(E_Config_Dialog *cfd)
807 {
808    E_Config_Dialog_Data *cfdata;
809
810    cfdata = E_NEW(E_Config_Dialog_Data, 1);
811    cfdata->cfd = cfd;
812    _fill_data(cfdata);
813    return cfdata;
814 }
815
816 static void
817 _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
818 {
819    E_FREE(cfdata->cur_language);
820
821    eina_stringshare_del(cfdata->cur_blang);
822    eina_stringshare_del(cfdata->cur_lang);
823    eina_stringshare_del(cfdata->cur_reg);
824    eina_stringshare_del(cfdata->cur_cs);
825    eina_stringshare_del(cfdata->cur_mod);
826
827    eina_hash_foreach(cfdata->locale_hash, _language_hash_free_cb, NULL);
828    eina_hash_free(cfdata->locale_hash);
829
830    cfdata->lang_list = eina_list_free(cfdata->lang_list);
831    cfdata->region_list = eina_list_free(cfdata->region_list);
832    cfdata->blang_list = eina_list_free(cfdata->blang_list);
833
834    E_FREE(cfdata);
835 }
836
837 static Eina_Bool
838 _language_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
839 {
840    E_Intl_Language_Node *node;
841
842    node = data;
843    if (node->lang_code) eina_stringshare_del(node->lang_code);
844    eina_hash_foreach(node->region_hash, _region_hash_free_cb, NULL);
845    eina_hash_free(node->region_hash);
846    free(node);
847
848    return 1;
849 }
850
851 static Eina_Bool
852 _region_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
853 {
854    E_Intl_Region_Node *node;
855
856    node = data;
857    if (node->region_code) eina_stringshare_del(node->region_code);
858    while (node->available_codesets)
859      {
860         const char *str;
861
862         str = node->available_codesets->data;
863         if (str) eina_stringshare_del(str);
864         node->available_codesets =
865           eina_list_remove_list(node->available_codesets, node->available_codesets);
866      }
867
868    while (node->available_modifiers)
869      {
870         const char *str;
871
872         str = node->available_modifiers->data;
873         if (str) eina_stringshare_del(str);
874         node->available_modifiers =
875           eina_list_remove_list(node->available_modifiers, node->available_modifiers);
876      }
877
878    free(node);
879    return 1;
880 }
881
882 static void
883 _lc_check_del(void *data __UNUSED__)
884 {
885    E_Action *a;
886    a = e_action_find("restart");
887    if ((a) && (a->func.go)) a->func.go(NULL, NULL);
888 }
889
890 static void
891 _lc_check(void)
892 {
893    char buf[8192];
894    char buf2[512];
895    E_Dialog *dia;
896
897    buf2[0] = 0;
898
899    if (getenv("LC_CTYPE")) strcat(buf2, "<br>LC_CTYPE");
900    if (getenv("LC_NUMERIC")) strcat(buf2, "<br>LC_NUMERIC");
901    if (getenv("LC_TIME")) strcat(buf2, "<br>LC_TIME");
902    if (getenv("LC_COLLATE")) strcat(buf2, "<br>LC_COLLATE");
903    if (getenv("LC_MONETARY")) strcat(buf2, "<br>LC_MONETARY");
904    if (getenv("LC_MESSAGES")) strcat(buf2, "<br>LC_MESSAGES");
905    if (getenv("LC_ALL")) strcat(buf2, "<br>LC_ALL");
906
907    if (!buf2[0]) return;
908
909    snprintf(buf, sizeof(buf), _("You have some extra locale environment<br>"
910                                  "variables set that may interfere with<br>"
911                                  "correct display of your chosen language.<br>"
912                                  "If you don't want these affected, use the<br>"
913                                  "Environment variable settings to unset them.<br>"
914                                  "The variables that may affect you are<br>"
915                                  "as follows:<br>"
916                                  "%s"), buf2);
917    dia = e_util_dialog_internal(_("Possible Locale problems"), buf);
918    e_object_free_attach_func_set(E_OBJECT(dia), _lc_check_del);
919 }
920
921 static int
922 _basic_apply_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
923 {
924    if (cfdata->cur_language)
925      {
926         if (e_config->language) eina_stringshare_del(e_config->language);
927         e_config->language = NULL;
928         if ((cfdata->cur_language) && (cfdata->cur_language[0]))
929           e_config->language = eina_stringshare_add(cfdata->cur_language);
930         e_intl_language_set(e_config->language);
931         _lc_check();
932      }
933
934    e_config_save_queue();
935    return 1;
936 }
937
938 static int
939 _advanced_apply_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
940 {
941    if (cfdata->cur_language)
942      {
943         if (e_config->language) eina_stringshare_del(e_config->language);
944         e_config->language = NULL;
945         if ((cfdata->cur_language) && (cfdata->cur_language[0]))
946           e_config->language = eina_stringshare_add(cfdata->cur_language);
947         e_intl_language_set(e_config->language);
948         _lc_check();
949      }
950
951    e_config_save_queue();
952    return 1;
953 }
954
955 static Evas_Object *
956 _basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
957 {
958    Evas_Object *o, *of, *ob, *ic;
959    char *cur_sig_loc;
960    Eina_List *next;
961    int i = 0;
962    char buf[PATH_MAX];
963
964    cfdata->evas = evas;
965    o = e_widget_table_add(evas, 0);
966    of = e_widget_framelist_add(evas, _("Language Selector"), 0);
967    ob = e_widget_ilist_add(evas, 16, 16, &(cfdata->cur_blang));
968    e_widget_size_min_set(ob, 100, 80);
969    e_widget_on_change_hook_set(ob, _ilist_basic_language_cb_change, cfdata);
970    cfdata->gui.blang_list = ob;
971    e_widget_framelist_object_append(of, ob);
972    e_widget_table_object_append(o, of, 0, 0, 1, 1, 1, 1, 1, 1);
973
974    /* Load languages */
975    evas_event_freeze(evas_object_evas_get(ob));
976    edje_freeze();
977    e_widget_ilist_freeze(ob);
978    if (cfdata->cur_language)
979      {
980         E_Locale_Parts *locale_parts;
981         locale_parts = e_intl_locale_parts_get(cfdata->cur_language);
982         if (locale_parts)
983           {
984              cur_sig_loc = e_intl_locale_parts_combine(locale_parts,
985                                                        E_INTL_LOC_LANG | E_INTL_LOC_REGION);
986
987              e_intl_locale_parts_free(locale_parts);
988           }
989         else
990           cur_sig_loc = NULL;
991      }
992    else
993      cur_sig_loc = NULL;
994
995    e_prefix_data_snprintf(buf, sizeof(buf), "data/flags/%s", "lang-system.png");
996    ic = e_util_icon_add(buf, evas);
997    e_widget_ilist_append(cfdata->gui.blang_list, ic, _("System Default"), NULL, NULL, "");
998    if ((!cur_sig_loc) || (!cfdata->cur_language))
999      e_widget_ilist_selected_set(cfdata->gui.blang_list, i);
1000    i++;
1001
1002    for (next = cfdata->blang_list; next; next = next->next)
1003      {
1004         E_Intl_Pair *pair;
1005         const char *key;
1006         const char *trans;
1007
1008         pair = next->data;
1009         key = pair->locale_key;
1010         trans = _(pair->locale_translation);
1011         if (pair->locale_icon)
1012           {
1013              e_prefix_data_snprintf(buf, sizeof(buf), "data/flags/%s", pair->locale_icon);
1014              ic = e_util_icon_add(buf, evas);
1015           }
1016         else
1017           ic = NULL;
1018         e_widget_ilist_append(cfdata->gui.blang_list, ic, trans, NULL, NULL, key);
1019         if ((cur_sig_loc) &&
1020             (!strncmp(key, cur_sig_loc, strlen(cur_sig_loc))))
1021           e_widget_ilist_selected_set(cfdata->gui.blang_list, i);
1022
1023         i++;
1024      }
1025    E_FREE(cur_sig_loc);
1026    e_widget_ilist_go(ob);
1027    e_widget_ilist_thaw(ob);
1028    edje_thaw();
1029    evas_event_thaw(evas_object_evas_get(ob));
1030
1031    of = e_widget_frametable_add(evas, _("Locale Selected"), 0);
1032    ob = e_widget_label_add(evas, _("Locale"));
1033    e_widget_frametable_object_append(of, ob, 0, 0, 1, 1, 1, 0, 1, 0);
1034    ob = e_widget_entry_add(evas, &(cfdata->cur_language), NULL, NULL, NULL);
1035    cfdata->gui.locale_entry = ob;
1036    e_widget_disabled_set(cfdata->gui.locale_entry, 1);
1037    e_widget_size_min_set(cfdata->gui.locale_entry, 100, 25);
1038    e_widget_frametable_object_append(of, cfdata->gui.locale_entry,
1039                                      1, 0, 1, 1, 1, 1, 1, 0);
1040    e_widget_table_object_append(o, of, 0, 1, 1, 1, 1, 0, 1, 0);
1041
1042    e_dialog_resizable_set(cfd->dia, 1);
1043    return o;
1044 }
1045
1046 static Evas_Object *
1047 _advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
1048 {
1049    Evas_Object *o, *of, *ob;
1050    const char *lang, *reg, *cs, *mod;
1051
1052    cfdata->evas = evas;
1053
1054    _intl_current_locale_setup(cfdata);
1055
1056    o = e_widget_table_add(evas, 0);
1057
1058    of = e_widget_framelist_add(evas, _("Language Selector"), 1);
1059
1060    /* Language List */
1061    ob = e_widget_ilist_add(evas, 16, 16, &(cfdata->cur_lang));
1062    cfdata->gui.lang_list = ob;
1063
1064    /* If lang_list already loaded just use it */
1065    if (!cfdata->lang_list)
1066      eina_hash_foreach(cfdata->locale_hash, _lang_hash_cb, cfdata);
1067
1068    if (cfdata->lang_list)
1069      {
1070         cfdata->lang_list =
1071           eina_list_sort(cfdata->lang_list, eina_list_count(cfdata->lang_list),
1072                          _lang_list_sort);
1073         _lang_list_load(cfdata);
1074      }
1075
1076    e_widget_ilist_go(ob);
1077    e_widget_size_min_set(ob, 140, 200);
1078    e_widget_framelist_object_append(of, ob);
1079    e_widget_ilist_selected_set(ob, e_widget_ilist_selected_get(ob));
1080
1081    /* Region List */
1082    ob = e_widget_ilist_add(evas, 0, 0, &(cfdata->cur_reg));
1083    cfdata->gui.reg_list = ob;
1084
1085    e_widget_ilist_go(ob);
1086    e_widget_size_min_set(ob, 100, 100);
1087    e_widget_framelist_object_append(of, ob);
1088    e_widget_ilist_selected_set(ob, e_widget_ilist_selected_get(ob));
1089
1090    /* Codeset List */
1091    ob = e_widget_ilist_add(evas, 0, 0, &(cfdata->cur_cs));
1092    cfdata->gui.cs_list = ob;
1093
1094    e_widget_ilist_go(ob);
1095    e_widget_size_min_set(ob, 100, 100);
1096    e_widget_framelist_object_append(of, ob);
1097
1098    /* Modified List */
1099    ob = e_widget_ilist_add(evas, 0, 0, &(cfdata->cur_mod));
1100    cfdata->gui.mod_list = ob;
1101
1102    e_widget_ilist_go(ob);
1103    e_widget_size_min_set(ob, 100, 100);
1104    e_widget_framelist_object_append(of, ob);
1105
1106    e_widget_table_object_append(o, of, 0, 0, 1, 1, 1, 1, 1, 1);
1107
1108    /* Locale selector */
1109    of = e_widget_frametable_add(evas, _("Locale Selected"), 0);
1110    ob = e_widget_label_add(evas, _("Locale"));
1111    e_widget_frametable_object_append(of, ob, 0, 0, 1, 1, 1, 0, 1, 0);
1112    ob = e_widget_entry_add(evas, &(cfdata->cur_language), NULL, NULL, NULL);
1113    cfdata->gui.locale_entry = ob;
1114    e_widget_disabled_set(cfdata->gui.locale_entry, 1);
1115    e_widget_size_min_set(cfdata->gui.locale_entry, 100, 25);
1116    e_widget_frametable_object_append(of, cfdata->gui.locale_entry,
1117                                      0, 1, 1, 1, 1, 1, 1, 0);
1118    e_widget_table_object_append(o, of, 0, 1, 1, 1, 1, 0, 1, 0);
1119
1120    /* all these cur_* values are not guaranteed to be const so we need to
1121     * copy them.
1122     */
1123    lang = eina_stringshare_ref(cfdata->cur_lang);
1124    reg = eina_stringshare_ref(cfdata->cur_reg);
1125    cs = eina_stringshare_ref(cfdata->cur_cs);
1126    mod = eina_stringshare_ref(cfdata->cur_mod);
1127
1128    _cfdata_language_go(lang, reg, cs, mod, cfdata);
1129
1130    eina_stringshare_del(lang);
1131    eina_stringshare_del(reg);
1132    eina_stringshare_del(cs);
1133    eina_stringshare_del(mod);
1134
1135    e_widget_on_change_hook_set(cfdata->gui.lang_list, _ilist_language_cb_change, cfdata);
1136    e_widget_on_change_hook_set(cfdata->gui.reg_list, _ilist_region_cb_change, cfdata);
1137    e_widget_on_change_hook_set(cfdata->gui.cs_list, _ilist_codeset_cb_change, cfdata);
1138    e_widget_on_change_hook_set(cfdata->gui.mod_list, _ilist_modifier_cb_change, cfdata);
1139
1140    e_dialog_resizable_set(cfd->dia, 1);
1141    return o;
1142 }
1143
1144 static void
1145 _ilist_basic_language_cb_change(void *data, Evas_Object *obj __UNUSED__)
1146 {
1147    E_Config_Dialog_Data *cfdata;
1148
1149    cfdata = data;
1150    e_widget_entry_text_set(cfdata->gui.locale_entry, cfdata->cur_blang);
1151 }
1152
1153 static void
1154 _ilist_language_cb_change(void *data, Evas_Object *obj __UNUSED__)
1155 {
1156    E_Config_Dialog_Data *cfdata;
1157
1158    cfdata = data;
1159    _cfdata_language_go(cfdata->cur_lang, NULL, NULL, NULL, cfdata);
1160    e_widget_entry_text_set(cfdata->gui.locale_entry, cfdata->cur_lang);
1161    eina_stringshare_del(cfdata->cur_cs);
1162    eina_stringshare_del(cfdata->cur_mod);
1163    cfdata->cur_cs = NULL;
1164    cfdata->cur_mod = NULL;
1165 }
1166
1167 static void
1168 _ilist_region_cb_change(void *data, Evas_Object *obj __UNUSED__)
1169 {
1170    E_Config_Dialog_Data *cfdata;
1171    char locale[32];
1172
1173    cfdata = data;
1174
1175    _cfdata_language_go(cfdata->cur_lang, cfdata->cur_reg, NULL, NULL, cfdata);
1176
1177    if ((cfdata->cur_lang) && (cfdata->cur_lang[0]))
1178      {
1179         sprintf(locale, "%s_%s", cfdata->cur_lang, cfdata->cur_reg);
1180         e_widget_entry_text_set(cfdata->gui.locale_entry, locale);
1181      }
1182    else
1183      e_widget_entry_text_set(cfdata->gui.locale_entry, "");
1184    eina_stringshare_del(cfdata->cur_cs);
1185    eina_stringshare_del(cfdata->cur_mod);
1186    cfdata->cur_cs = NULL;
1187    cfdata->cur_mod = NULL;
1188 }
1189
1190 static void
1191 _ilist_codeset_cb_change(void *data, Evas_Object *obj __UNUSED__)
1192 {
1193    E_Config_Dialog_Data *cfdata;
1194    char locale[32];
1195
1196    cfdata = data;
1197
1198    if ((cfdata->cur_lang) && (cfdata->cur_lang[0]))
1199      {
1200         if (cfdata->cur_mod)
1201           sprintf(locale, "%s_%s.%s@%s", cfdata->cur_lang, cfdata->cur_reg, cfdata->cur_cs, cfdata->cur_mod);
1202         else
1203           sprintf(locale, "%s_%s.%s", cfdata->cur_lang, cfdata->cur_reg, cfdata->cur_cs);
1204         e_widget_entry_text_set(cfdata->gui.locale_entry, locale);
1205      }
1206    else
1207      e_widget_entry_text_set(cfdata->gui.locale_entry, "");
1208 }
1209
1210 static void
1211 _ilist_modifier_cb_change(void *data, Evas_Object *obj __UNUSED__)
1212 {
1213    E_Config_Dialog_Data *cfdata;
1214    char locale[32];
1215
1216    cfdata = data;
1217
1218    if ((cfdata->cur_lang) && (cfdata->cur_lang[0]))
1219      {
1220         if (cfdata->cur_cs)
1221           sprintf(locale, "%s_%s.%s@%s", cfdata->cur_lang, cfdata->cur_reg, cfdata->cur_cs, cfdata->cur_mod);
1222         else
1223           sprintf(locale, "%s_%s@%s", cfdata->cur_lang, cfdata->cur_reg, cfdata->cur_mod);
1224         e_widget_entry_text_set(cfdata->gui.locale_entry, locale);
1225      }
1226    else
1227      e_widget_entry_text_set(cfdata->gui.locale_entry, "");
1228 }
1229
1230 static void
1231 _cfdata_language_go(const char *lang, const char *region, const char *codeset, const char *modifier, E_Config_Dialog_Data *cfdata)
1232 {
1233    E_Intl_Language_Node *lang_node;
1234    int lang_update;
1235    int region_update;
1236
1237    /* Check what changed */
1238    lang_update = 0;
1239    region_update = 0;
1240
1241    evas_event_freeze(evas_object_evas_get(cfdata->gui.cs_list));
1242    evas_event_freeze(evas_object_evas_get(cfdata->gui.mod_list));
1243    edje_freeze();
1244    e_widget_ilist_freeze(cfdata->gui.cs_list);
1245    e_widget_ilist_freeze(cfdata->gui.mod_list);
1246
1247    if ((!lang) || (!lang[0]))
1248      {
1249         e_widget_ilist_clear(cfdata->gui.reg_list);
1250         e_widget_ilist_clear(cfdata->gui.cs_list);
1251         e_widget_ilist_clear(cfdata->gui.mod_list);
1252      }
1253    if (cfdata->lang_dirty || (lang && !region))
1254      {
1255         lang_update = 1;
1256         region_update = 1;
1257         e_widget_ilist_clear(cfdata->gui.cs_list);
1258         e_widget_ilist_clear(cfdata->gui.mod_list);
1259      }
1260    if (lang && region)
1261      {
1262         region_update = 1;
1263         e_widget_ilist_clear(cfdata->gui.cs_list);
1264         e_widget_ilist_clear(cfdata->gui.mod_list);
1265      }
1266
1267    cfdata->lang_dirty = 0;
1268
1269    if (lang)
1270      {
1271         lang_node = eina_hash_find(cfdata->locale_hash, lang);
1272
1273         if (lang_node)
1274           {
1275              if (lang_update)
1276                {
1277                   e_widget_ilist_clear(cfdata->gui.reg_list);
1278                   cfdata->region_list = eina_list_free(cfdata->region_list);
1279                   eina_hash_foreach(lang_node->region_hash,
1280                                     _region_hash_cb, cfdata);
1281                   cfdata->region_list =
1282                     eina_list_sort(cfdata->region_list,
1283                                    eina_list_count(cfdata->region_list),
1284                                    _region_list_sort);
1285                   _region_list_load(cfdata);
1286                }
1287
1288              if (region && region_update)
1289                {
1290                   E_Intl_Region_Node *reg_node;
1291
1292                   reg_node = eina_hash_find(lang_node->region_hash, region);
1293                   if (reg_node)
1294                     {
1295                        Eina_List *next;
1296
1297                        for (next = reg_node->available_codesets; next; next = next->next)
1298                          {
1299                             const char *cs;
1300
1301                             cs = next->data;
1302                             e_widget_ilist_append(cfdata->gui.cs_list, NULL, cs, NULL, NULL, cs);
1303                             if (codeset && !strcmp(cs, codeset))
1304                               {
1305                                  int count;
1306
1307                                  count = e_widget_ilist_count(cfdata->gui.cs_list);
1308                                  e_widget_ilist_selected_set(cfdata->gui.cs_list, count - 1);
1309                               }
1310                          }
1311
1312                        for (next = reg_node->available_modifiers; next; next = next->next)
1313                          {
1314                             const char *mod;
1315
1316                             mod = next->data;
1317                             e_widget_ilist_append(cfdata->gui.mod_list, NULL, mod, NULL, NULL, mod);
1318                             if (modifier && !strcmp(mod, modifier))
1319                               {
1320                                  int count;
1321
1322                                  count = e_widget_ilist_count(cfdata->gui.mod_list);
1323                                  e_widget_ilist_selected_set(cfdata->gui.mod_list, count - 1);
1324                               }
1325                          }
1326                     }
1327                   e_widget_ilist_go(cfdata->gui.cs_list);
1328                   e_widget_ilist_go(cfdata->gui.mod_list);
1329                }
1330           }
1331      }
1332    e_widget_ilist_thaw(cfdata->gui.cs_list);
1333    e_widget_ilist_thaw(cfdata->gui.mod_list);
1334    edje_thaw();
1335    evas_event_thaw(evas_object_evas_get(cfdata->gui.cs_list));
1336    evas_event_thaw(evas_object_evas_get(cfdata->gui.mod_list));
1337
1338    e_widget_ilist_go(cfdata->gui.reg_list);
1339 }
1340
1341 static Eina_Bool
1342 _lang_hash_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata)
1343 {
1344    E_Config_Dialog_Data *cfdata;
1345    E_Intl_Language_Node *lang_node;
1346
1347    cfdata = fdata;
1348    lang_node = data;
1349
1350    cfdata->lang_list = eina_list_append(cfdata->lang_list, lang_node);
1351    return 1;
1352 }
1353
1354 static Eina_Bool
1355 _region_hash_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata)
1356 {
1357    E_Config_Dialog_Data *cfdata;
1358    E_Intl_Region_Node *reg_node;
1359
1360    cfdata = fdata;
1361    reg_node = data;
1362
1363    cfdata->region_list = eina_list_append(cfdata->region_list, reg_node);
1364    return 1;
1365 }
1366
1367 void
1368 _intl_current_locale_setup(E_Config_Dialog_Data *cfdata)
1369 {
1370    eina_stringshare_del(cfdata->cur_lang);
1371    eina_stringshare_del(cfdata->cur_reg);
1372    eina_stringshare_del(cfdata->cur_cs);
1373    eina_stringshare_del(cfdata->cur_mod);
1374
1375    cfdata->cur_lang = NULL;
1376    cfdata->cur_reg = NULL;
1377    cfdata->cur_cs = NULL;
1378    cfdata->cur_mod = NULL;
1379
1380    if (cfdata->cur_language)
1381      {
1382         E_Locale_Parts *locale_parts;
1383
1384         locale_parts = e_intl_locale_parts_get(cfdata->cur_language);
1385         if (locale_parts)
1386           {
1387              cfdata->cur_lang = eina_stringshare_add(locale_parts->lang);
1388              cfdata->cur_reg = eina_stringshare_add(locale_parts->region);
1389              if (locale_parts->codeset)
1390                {
1391                   const char *cs_trans;
1392
1393                   cs_trans = _intl_charset_upper_get(locale_parts->codeset);
1394                   if (!cs_trans)
1395                     cfdata->cur_cs = eina_stringshare_add(locale_parts->codeset);
1396                   else
1397                     cfdata->cur_cs = eina_stringshare_add(cs_trans);
1398                }
1399              cfdata->cur_mod = eina_stringshare_add(locale_parts->modifier);
1400           }
1401         e_intl_locale_parts_free(locale_parts);
1402      }
1403    cfdata->lang_dirty = 1;
1404 }
1405
1406 static int
1407 _lang_list_sort(const void *data1, const void *data2)
1408 {
1409    const E_Intl_Language_Node *ln1, *ln2;
1410    const char *trans1;
1411    const char *trans2;
1412
1413    if (!data1) return 1;
1414    if (!data2) return -1;
1415
1416    ln1 = data1;
1417    ln2 = data2;
1418
1419    if (!ln1->lang_name) return 1;
1420    trans1 = ln1->lang_name;
1421
1422    if (!ln2->lang_name) return -1;
1423    trans2 = ln2->lang_name;
1424
1425    return strcmp(trans1, trans2);
1426 }
1427
1428 static void
1429 _lang_list_load(void *data)
1430 {
1431    E_Config_Dialog_Data *cfdata;
1432    Eina_List *l;
1433    Evas_Object *ic;
1434    char buf[PATH_MAX];
1435
1436    if (!data) return;
1437
1438    cfdata = data;
1439    if (!cfdata->lang_list) return;
1440
1441    evas_event_freeze(evas_object_evas_get(cfdata->gui.lang_list));
1442    edje_freeze();
1443    e_widget_ilist_freeze(cfdata->gui.lang_list);
1444
1445    e_prefix_data_snprintf(buf, sizeof(buf), "data/flags/%s", "lang-system.png");
1446    ic = e_util_icon_add(buf, cfdata->evas);
1447    e_widget_ilist_append(cfdata->gui.lang_list, ic, _("System Default"), NULL, NULL, "");
1448    for (l = cfdata->lang_list; l; l = l->next)
1449      {
1450         E_Intl_Language_Node *ln;
1451         const char *trans;
1452
1453         ln = l->data;
1454         if (!ln) continue;
1455         if (ln->lang_name)
1456           trans = ln->lang_name;
1457         else
1458           trans = ln->lang_code;
1459
1460         if (ln->lang_available)
1461           {
1462              ic = e_icon_add(cfdata->evas);
1463              e_util_icon_theme_set(ic, "dialog-ok-apply");
1464           }
1465         else
1466           ic = NULL;
1467
1468         e_widget_ilist_append(cfdata->gui.lang_list, ic, trans, NULL, NULL, ln->lang_code);
1469
1470         if (cfdata->cur_lang && !strcmp(cfdata->cur_lang, ln->lang_code))
1471           {
1472              int count;
1473
1474              count = e_widget_ilist_count(cfdata->gui.lang_list);
1475              e_widget_ilist_selected_set(cfdata->gui.lang_list, count - 1);
1476           }
1477      }
1478    e_widget_ilist_thaw(cfdata->gui.lang_list);
1479    edje_thaw();
1480    evas_event_thaw(evas_object_evas_get(cfdata->gui.lang_list));
1481 }
1482
1483 static int
1484 _region_list_sort(const void *data1, const void *data2)
1485 {
1486    const E_Intl_Region_Node *rn1, *rn2;
1487    const char *trans1;
1488    const char *trans2;
1489
1490    if (!data1) return 1;
1491    if (!data2) return -1;
1492
1493    rn1 = data1;
1494    rn2 = data2;
1495
1496    if (!rn1->region_name) return 1;
1497    trans1 = rn1->region_name;
1498
1499    if (!rn2->region_name) return -1;
1500    trans2 = rn2->region_name;
1501
1502    return strcmp(trans1, trans2);
1503 }
1504
1505 static void
1506 _region_list_load(void *data)
1507 {
1508    E_Config_Dialog_Data *cfdata;
1509    Eina_List *l;
1510    Evas_Object *ic;
1511    char buf[PATH_MAX];
1512
1513    if (!data) return;
1514
1515    cfdata = data;
1516    if (!cfdata->region_list) return;
1517
1518    evas_event_freeze(evas_object_evas_get(cfdata->gui.reg_list));
1519    edje_freeze();
1520    e_widget_ilist_freeze(cfdata->gui.reg_list);
1521
1522    for (l = cfdata->region_list; l; l = l->next)
1523      {
1524         E_Intl_Region_Node *rn;
1525         const char *trans;
1526
1527         rn = l->data;
1528         if (!rn) continue;
1529         if (rn->region_name)
1530           trans = rn->region_name;
1531         else
1532           trans = rn->region_code;
1533
1534         if (rn->region_icon)
1535           {
1536              e_prefix_data_snprintf(buf, sizeof(buf), "data/flags/%s", rn->region_icon);
1537              ic = e_util_icon_add(buf, cfdata->evas);
1538           }
1539         else
1540           ic = NULL;
1541         e_widget_ilist_append(cfdata->gui.reg_list, ic, trans, NULL, NULL, rn->region_code);
1542
1543         if (cfdata->cur_reg && !strcmp(cfdata->cur_reg, rn->region_code))
1544           {
1545              int count;
1546
1547              count = e_widget_ilist_count(cfdata->gui.reg_list);
1548              e_widget_ilist_selected_set(cfdata->gui.reg_list, count - 1);
1549           }
1550      }
1551    e_widget_ilist_thaw(cfdata->gui.reg_list);
1552    edje_thaw();
1553    evas_event_thaw(evas_object_evas_get(cfdata->gui.reg_list));
1554 }
1555
1556 static int
1557 _basic_lang_list_sort(const void *data1, const void *data2)
1558 {
1559    const E_Intl_Pair *ln1, *ln2;
1560    const char *trans1;
1561    const char *trans2;
1562
1563    if (!data1) return 1;
1564    if (!data2) return -1;
1565
1566    ln1 = data1;
1567    ln2 = data2;
1568
1569    if (!ln1->locale_translation) return 1;
1570    trans1 = ln1->locale_translation;
1571
1572    if (!ln2->locale_translation) return -1;
1573    trans2 = ln2->locale_translation;
1574
1575    return strcmp(trans1, trans2);
1576 }
1577
1578 const char *
1579 _intl_charset_upper_get(const char *charset)
1580 {
1581    int i;
1582
1583    i = 0;
1584    while (charset_predefined_pairs[i].locale_key)
1585      {
1586         if (!strcmp(charset_predefined_pairs[i].locale_key, charset))
1587           {
1588              return charset_predefined_pairs[i].locale_translation;
1589           }
1590         i++;
1591      }
1592    return NULL;
1593 }
1594