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