enlightenment/src/bin/e_intl.c

1067 lines
26 KiB
C

/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "e.h"
static Ecore_Exe *_e_intl_input_method_exec = NULL;
static Ecore_Event_Handler *_e_intl_exit_handler = NULL;
static char *_e_intl_orig_lc_messages = NULL;
static char *_e_intl_orig_language = NULL;
static char *_e_intl_orig_lc_all = NULL;
static char *_e_intl_orig_lang = NULL;
static char *_e_intl_language = NULL;
static char *_e_intl_language_alias = NULL;
static char *_e_intl_orig_xmodifiers = NULL;
static char *_e_intl_orig_qt_im_module = NULL;
static char *_e_intl_orig_gtk_im_module = NULL;
static const char *_e_intl_imc_personal_path = NULL;
static const char *_e_intl_imc_system_path = NULL;
#define E_EXE_STOP(EXE) if (EXE != NULL) { ecore_exe_terminate(EXE); ecore_exe_free(EXE); EXE = NULL; }
#define E_EXE_IS_VALID(EXE) (!((EXE == NULL) || (EXE[0] == 0)))
/* All locale parts */
#define E_INTL_LOC_ALL E_INTL_LOC_LANG | \
E_INTL_LOC_REGION | \
E_INTL_LOC_CODESET | \
E_INTL_LOC_MODIFIER
/* Locale parts wich are significant when Validating */
#define E_INTL_LOC_SIGNIFICANT E_INTL_LOC_LANG | \
E_INTL_LOC_REGION | \
E_INTL_LOC_CODESET
/* Language Setting and Listing */
static char *_e_intl_language_path_find(char *language);
static Evas_List *_e_intl_language_dir_scan(const char *dir);
static int _e_intl_language_list_find(Evas_List *language_list, char *language);
/* Locale Validation and Discovery */
static Evas_Hash *_e_intl_locale_alias_hash_get(void);
static char *_e_intl_locale_alias_get(const char *language);
static Evas_List *_e_intl_locale_system_locales_get(void);
static Evas_List *_e_intl_locale_search_order_get(const char *locale);
static int _e_intl_locale_validate(const char *locale);
static void _e_intl_locale_hash_free(Evas_Hash *language_hash);
static Evas_Bool _e_intl_locale_hash_free_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata);
/* Input Method Configuration and Management */
static int _e_intl_cb_exit(void *data, int type, void *event);
static Evas_List *_e_intl_imc_dir_scan(const char *dir);
EAPI int
e_intl_init(void)
{
char *s;
e_intl_data_init();
if ((s = getenv("LC_MESSAGES"))) _e_intl_orig_lc_messages = strdup(s);
if ((s = getenv("LANGUAGE"))) _e_intl_orig_language = strdup(s);
if ((s = getenv("LC_ALL"))) _e_intl_orig_lc_all = strdup(s);
if ((s = getenv("LANG"))) _e_intl_orig_lang = strdup(s);
if ((s = getenv("GTK_IM_MODULE"))) _e_intl_orig_gtk_im_module = strdup(s);
if ((s = getenv("QT_IM_MODULE"))) _e_intl_orig_qt_im_module = strdup(s);
if ((s = getenv("XMODIFIERS"))) _e_intl_orig_xmodifiers = strdup(s);
return 1;
}
EAPI int
e_intl_shutdown(void)
{
E_FREE(_e_intl_language);
E_FREE(_e_intl_orig_lc_messages);
E_FREE(_e_intl_orig_language);
E_FREE(_e_intl_orig_lc_all);
E_FREE(_e_intl_orig_lang);
E_FREE(_e_intl_orig_gtk_im_module);
E_FREE(_e_intl_orig_qt_im_module);
E_FREE(_e_intl_orig_xmodifiers);
if (_e_intl_imc_personal_path)
evas_stringshare_del(_e_intl_imc_personal_path);
if (_e_intl_imc_system_path)
evas_stringshare_del(_e_intl_imc_system_path);
e_intl_data_shutdown();
return 1;
}
/* Setup configuration settings and start services */
EAPI int
e_intl_post_init(void)
{
if ((e_config->language) && (e_config->language[0] != 0))
e_intl_language_set(e_config->language);
else
e_intl_language_set(NULL);
if ((e_config->input_method) && (e_config->input_method[0] != 0))
e_intl_input_method_set(e_config->input_method);
_e_intl_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
_e_intl_cb_exit, NULL);
return 1;
}
EAPI int
e_intl_post_shutdown(void)
{
if (_e_intl_exit_handler)
{
ecore_event_handler_del(_e_intl_exit_handler);
_e_intl_exit_handler = NULL;
}
e_intl_input_method_set(NULL);
e_intl_language_set(NULL);
E_FREE(_e_intl_language_alias);
E_EXE_STOP(_e_intl_input_method_exec);
return 1;
}
/*
* TODO
* - Add error dialogs explaining any errors while setting the locale
* * Locale aliases need to be configured
* * Locale is invalid
* * Message files are not found for this locale, then we have (en_US, POSIX, C)
* - Add support of compound locales i.e. (en_US;zh_CN;C) ==Defer==
* - Add Configuration for to-be-set environment variables
*/
EAPI void
e_intl_language_set(const char *lang)
{
int set_envars;
set_envars = 1;
/* NULL lang means set everything back to the original environment
* defaults
*/
if (!lang)
{
e_util_env_set("LC_MESSAGES", _e_intl_orig_lc_messages);
e_util_env_set("LANGUAGE", _e_intl_orig_language);
e_util_env_set("LC_ALL", _e_intl_orig_lc_all);
e_util_env_set("LANG", _e_intl_orig_lang);
lang = getenv("LC_MESSAGES");
if (!lang) lang = getenv("LANGUAGE");
if (!lang) lang = getenv("LC_ALL");
if (!lang) lang = getenv("LANG");
set_envars = 0;
}
E_FREE(_e_intl_language_alias);
_e_intl_language_alias = _e_intl_locale_alias_get(lang);
E_FREE(_e_intl_language);
if (lang)
_e_intl_language = strdup(lang);
else
_e_intl_language = NULL;
if ((!_e_intl_locale_validate(_e_intl_language_alias)) &&
(strcmp(_e_intl_language_alias, "C")))
{
fprintf(stderr, "The locale '%s' cannot be found on your "
"system. Please install this locale or try "
"something else.", _e_intl_language_alias);
}
else
{
/* Only set env vars is a non NULL locale was passed */
if (set_envars)
{
e_util_env_set("LANGUAGE", _e_intl_language);
e_util_env_set("LANG", _e_intl_language);
e_util_env_set("LC_ALL", _e_intl_language);
e_util_env_set("LC_MESSAGES", _e_intl_language);
}
setlocale(LC_ALL, _e_intl_language);
if (_e_intl_language)
{
char *locale_path;
locale_path = _e_intl_language_path_find(_e_intl_language_alias);
if (locale_path == NULL)
{
E_Locale_Parts *locale_parts;
locale_parts = e_intl_locale_parts_get(_e_intl_language_alias);
/* If locale is C or some form of en don't report an error */
if ((locale_parts == NULL) &&
(strcmp(_e_intl_language_alias, "C")))
{
fprintf(stderr,
"An error occurred setting your locale. \n\n"
"The locale you have chosen '%s' appears to \n"
"be an alias, however, it can not be resloved.\n"
"Please make sure you have a 'locale.alias' \n"
"file in your 'messages' path which can resolve\n"
"this alias.\n\n"
"Enlightenment will not be translated.\n",
_e_intl_language_alias);
}
else if ((locale_parts) && (locale_parts->lang) &&
(strcmp(locale_parts->lang, "en")))
{
fprintf(stderr,
"An error occurred setting your locale. \n\n"
"The translation files for the locale you \n"
"have chosen (%s) cannot be found in your \n"
"'messages' path. \n\n"
"Enlightenment will not be translated.\n",
_e_intl_language_alias);
}
e_intl_locale_parts_free(locale_parts);
}
else
{
bindtextdomain(PACKAGE, locale_path);
textdomain(PACKAGE);
bind_textdomain_codeset(PACKAGE, "UTF-8");
free(locale_path);
}
}
}
}
EAPI const char *
e_intl_language_get(void)
{
return _e_intl_language;
}
EAPI const char *
e_intl_language_alias_get(void)
{
return _e_intl_language_alias;
}
EAPI Evas_List *
e_intl_language_list(void)
{
Evas_List *next;
Evas_List *dir_list;
Evas_List *all_languages;
all_languages = NULL;
dir_list = e_path_dir_list_get(path_messages);
for (next = dir_list ; next ; next = next->next)
{
E_Path_Dir *epd;
Evas_List *dir_languages;
epd = next->data;
dir_languages = _e_intl_language_dir_scan(epd->dir);
while (dir_languages)
{
char *language;
language = dir_languages->data;
dir_languages = evas_list_remove_list(dir_languages, dir_languages);
if ((_e_intl_language_list_find(all_languages, language)) ||
((strlen(language) > 2) && (!_e_intl_locale_validate(language))))
{
free(language);
}
else
all_languages = evas_list_append(all_languages, language);
}
}
e_path_dir_list_free(dir_list);
return all_languages;
}
static int
_e_intl_language_list_find(Evas_List *language_list, char *language)
{
Evas_List *l;
if (!language_list) return 0;
if (!language) return 0;
for (l = language_list; l; l = l->next)
{
char *lang;
lang = l->data;
if (!strcmp(lang, language)) return 1;
}
return 0;
}
EAPI void
e_intl_input_method_set(const char *imc_path)
{
if (!imc_path)
{
E_EXE_STOP(_e_intl_input_method_exec);
e_util_env_set("GTK_IM_MODULE", _e_intl_orig_gtk_im_module);
e_util_env_set("QT_IM_MODULE", _e_intl_orig_qt_im_module);
e_util_env_set("XMODIFIERS", _e_intl_orig_xmodifiers);
}
if (imc_path)
{
Eet_File *imc_ef;
E_Input_Method_Config *imc;
imc_ef = eet_open(imc_path, EET_FILE_MODE_READ);
if (imc_ef)
{
imc = e_intl_input_method_config_read(imc_ef);
eet_close(imc_ef);
if (imc)
{
e_util_env_set("GTK_IM_MODULE", imc->gtk_im_module);
e_util_env_set("QT_IM_MODULE", imc->qt_im_module);
e_util_env_set("XMODIFIERS", imc->xmodifiers);
E_EXE_STOP(_e_intl_input_method_exec);
if (E_EXE_IS_VALID(imc->e_im_exec))
{
e_util_library_path_strip();
_e_intl_input_method_exec = ecore_exe_run(imc->e_im_exec, NULL);
e_util_library_path_restore();
ecore_exe_tag_set(_e_intl_input_method_exec,"E/im_exec");
if ((!_e_intl_input_method_exec) ||
(!ecore_exe_pid_get(_e_intl_input_method_exec)))
e_util_dialog_show(_("Input Method Error"),
_( "Error starting the input method executable<br><br>"
"please make sure that your input<br>"
"method configuration is correct and<br>"
"that your configuration's<br>"
"executable is in your PATH<br>"));
}
e_intl_input_method_config_free(imc);
}
}
}
}
EAPI Evas_List *
e_intl_input_method_list(void)
{
Evas_List *input_methods;
Evas_List *im_list;
Evas_List *l;
char *imc_path;
im_list = NULL;
/* Personal Path */
input_methods = _e_intl_imc_dir_scan(e_intl_imc_personal_path_get());
for (l = input_methods; l; l = l->next)
{
imc_path = l->data;
im_list = evas_list_append(im_list, imc_path);
}
while (input_methods)
input_methods = evas_list_remove_list(input_methods, input_methods);
/* System Path */
input_methods = _e_intl_imc_dir_scan(e_intl_imc_system_path_get());
for (l = input_methods; l; l = l->next)
{
imc_path = l->data;
im_list = evas_list_append(im_list, imc_path);
}
while (input_methods)
input_methods = evas_list_remove_list(input_methods, input_methods);
return im_list;
}
const char *
e_intl_imc_personal_path_get(void)
{
if (_e_intl_imc_personal_path == NULL)
{
char buf[4096];
snprintf(buf, sizeof(buf), "%s/.e/e/input_methods", e_user_homedir_get());
_e_intl_imc_personal_path = evas_stringshare_add(buf);
}
return _e_intl_imc_personal_path;
}
const char *
e_intl_imc_system_path_get(void)
{
if (_e_intl_imc_system_path == NULL)
{
char buf[4096];
snprintf(buf, sizeof(buf), "%s/data/input_methods", e_prefix_data_get());
_e_intl_imc_system_path = evas_stringshare_add(buf);
}
return _e_intl_imc_system_path;
}
static int
_e_intl_cb_exit(void *data, int type, void *event)
{
Ecore_Exe_Event_Del *ev;
ev = event;
if (!ev->exe) return 1;
if (!(ecore_exe_tag_get(ev->exe) &&
(!strcmp(ecore_exe_tag_get(ev->exe), "E/im_exec")))) return 1;
_e_intl_input_method_exec = NULL;
return 1;
}
static void
_e_intl_locale_hash_free(Evas_Hash *locale_hash)
{
if (!locale_hash) return;
evas_hash_foreach(locale_hash, _e_intl_locale_hash_free_cb, NULL);
evas_hash_free(locale_hash);
}
static Evas_Bool
_e_intl_locale_hash_free_cb(const Evas_Hash *hash __UNUSED__, const char *key __UNUSED__, void *data, void *fdata __UNUSED__)
{
free(data);
return 1;
}
/*
* get the directory associated with the language. Language Must be valid alias
* i.e. Already validated and already de-aliased.
*
* NULL means:
* 1) The user does not have an enlightenment translation for this locale
* 2) The user does not have their locale.aliases configured correctly
*
* @return NULL if not found.
*/
static char *
_e_intl_language_path_find(char *language)
{
char *directory;
Evas_List *dir_list;
Evas_List *search_list;
Evas_List *next_dir;
Evas_List *next_search;
int found;
search_list = _e_intl_locale_search_order_get(language);
if (search_list == NULL) return NULL;
directory = NULL;
found = 0;
dir_list = e_path_dir_list_get(path_messages);
/* For each directory in the path */
for (next_dir = dir_list; next_dir && !found; next_dir = next_dir->next)
{
E_Path_Dir *epd;
epd = next_dir->data;
/* Match canonicalized locale against each possible search */
for (next_search = search_list; next_search && !found; next_search = next_search->next)
{
char *search_locale;
char message_path[PATH_MAX];
search_locale = next_search->data;
snprintf(message_path, sizeof(message_path), "%s/%s/LC_MESSAGES/%s.mo", epd->dir, search_locale, PACKAGE);
if ((ecore_file_exists(message_path)) && (!ecore_file_is_dir(message_path)))
{
directory = strdup(epd->dir);
found = 1;
}
}
}
e_path_dir_list_free(dir_list);
while (search_list)
{
char *data;
data = search_list->data;
free(data);
search_list = evas_list_remove_list(search_list, search_list);
}
return directory;
}
static Evas_List *
_e_intl_language_dir_scan(const char *dir)
{
Evas_List *languages;
Ecore_List *files;
char *file;
languages = NULL;
files = ecore_file_ls(dir);
if (!files) return NULL;
ecore_list_first_goto(files);
if (files)
{
while ((file = ecore_list_next(files)))
{
char file_path[PATH_MAX];
snprintf(file_path, sizeof(file_path),"%s/%s/LC_MESSAGES/%s.mo",
dir, file, PACKAGE);
if (ecore_file_exists(file_path) && !ecore_file_is_dir(file_path))
languages = evas_list_append(languages, strdup(file));
}
ecore_list_destroy(files);
}
return languages;
}
/* get the alias for a locale
*
* return pointer to allocated alias string. never returns NULL
* String will be the same if its a valid locale already or there
* is no alias.
*/
static char *
_e_intl_locale_alias_get(const char *language)
{
Evas_Hash *alias_hash;
char *alias;
char *lower_language;
int i;
if ((language == NULL) || (!strncmp(language, "POSIX", strlen("POSIX"))))
return strdup("C");
alias_hash = _e_intl_locale_alias_hash_get();
if (alias_hash == NULL) /* No alias file available */
return strdup(language);
lower_language = malloc(strlen(language) + 1);
for (i = 0; i < strlen(language); i++)
lower_language[i] = tolower(language[i]);
lower_language[i] = 0;
alias = evas_hash_find(alias_hash, lower_language);
free(lower_language);
if (alias)
alias = strdup(alias);
else
alias = strdup(language);
_e_intl_locale_hash_free(alias_hash);
return alias;
}
static Evas_Hash *
_e_intl_locale_alias_hash_get(void)
{
Evas_List *next;
Evas_List *dir_list;
Evas_Hash *alias_hash;
dir_list = e_path_dir_list_get(path_messages);
alias_hash = NULL;
for (next = dir_list; next; next = next->next)
{
char buf[4096];
E_Path_Dir *epd;
FILE *f;
epd = next->data;
snprintf(buf, sizeof(buf), "%s/locale.alias", epd->dir);
f = fopen(buf, "r");
if (f)
{
char alias[4096], locale[4096];
/* read locale alias lines */
while (fscanf(f, "%4090s %[^\n]\n", alias, locale) == 2)
{
/* skip comments */
if ((alias[0] == '!') || (alias[0] == '#'))
continue;
/* skip dupes */
if (evas_hash_find(alias_hash, alias))
continue;
alias_hash = evas_hash_add(alias_hash, alias, strdup(locale));
}
fclose (f);
}
}
e_path_dir_list_free(dir_list);
return alias_hash;
}
/* return parts of the locale that are requested in the mask
* return null if the locale looks to be invalid (Does not have
* ll_DD)
*
* the returned string needs to be freed
*/
/*
* Not canonic, just gets the parts
*/
EAPI E_Locale_Parts *
e_intl_locale_parts_get(const char *locale)
{
/* Parse Results */
E_Locale_Parts *locale_parts;
char language[4];
char territory[4];
char codeset[32];
char modifier[32];
/* Parse State */
int state = 0; /* start out looking for the language */
int locale_idx;
int tmp_idx = 0;
/* Parse Loop - Seperators are _ . @ */
for (locale_idx = 0; locale_idx < strlen(locale); locale_idx++)
{
char locale_char;
locale_char = locale[locale_idx];
/* we have finished scanning the locale string */
if (!locale_char)
break;
/* scan this character based on the current start */
switch (state)
{
case 0: /* Gathering Language */
if (tmp_idx == 2 && locale_char == '_')
{
state++;
language[tmp_idx] = 0;
tmp_idx = 0;
}
else if ((tmp_idx < 2) && (islower(locale_char)))
language[tmp_idx++] = locale_char;
else
return NULL;
break;
case 1: /* Gathering Territory */
if (tmp_idx == 2 && locale_char == '.')
{
state++;
territory[tmp_idx] = 0;
tmp_idx = 0;
}
else if ((tmp_idx == 2) && (locale_char == '@'))
{
state += 2;
territory[tmp_idx] = 0;
codeset[0] = 0;
tmp_idx = 0;
}
else if ((tmp_idx < 2) && isupper(locale_char))
territory[tmp_idx++] = locale_char;
else
return NULL;
break;
case 2: /* Gathering Codeset */
if (locale_char == '@')
{
state++;
codeset[tmp_idx] = 0;
tmp_idx = 0;
}
else if (tmp_idx < 32)
codeset[tmp_idx++] = locale_char;
else
return NULL;
break;
case 3: /* Gathering modifier */
if (tmp_idx < 32)
modifier[tmp_idx++] = locale_char;
else
return NULL;
break;
default:
break;
}
}
/* set end-of-string \0 */
/* There are no breaks here on purpose */
switch (state)
{
case 0:
language[tmp_idx] = 0;
tmp_idx = 0;
case 1:
territory[tmp_idx] = 0;
tmp_idx = 0;
case 2:
codeset[tmp_idx] = 0;
tmp_idx = 0;
case 3:
modifier[tmp_idx] = 0;
default:
break;
}
locale_parts = E_NEW(E_Locale_Parts, 1);
/* Put the parts of the string together */
if (language[0] != 0)
{
locale_parts->mask |= E_INTL_LOC_LANG;
locale_parts->lang = evas_stringshare_add(language);
}
if (territory[0] != 0)
{
locale_parts->mask |= E_INTL_LOC_REGION;
locale_parts->region = evas_stringshare_add(territory);
}
if (codeset[0] != 0)
{
locale_parts->mask |= E_INTL_LOC_CODESET;
locale_parts->codeset = evas_stringshare_add(codeset);
}
if (modifier[0] != 0)
{
locale_parts->mask |= E_INTL_LOC_MODIFIER;
locale_parts->modifier = evas_stringshare_add(modifier);
}
return locale_parts;
}
EAPI void
e_intl_locale_parts_free(E_Locale_Parts *locale_parts)
{
if (locale_parts != NULL)
{
if (locale_parts->lang) evas_stringshare_del(locale_parts->lang);
if (locale_parts->region) evas_stringshare_del(locale_parts->region);
if (locale_parts->codeset) evas_stringshare_del(locale_parts->codeset);
if (locale_parts->modifier) evas_stringshare_del(locale_parts->modifier);
E_FREE(locale_parts);
}
}
EAPI char *
e_intl_locale_parts_combine(E_Locale_Parts *locale_parts, int mask)
{
int locale_size;
char *locale;
if (!locale_parts) return NULL;
if ((mask & locale_parts->mask) != mask) return NULL;
/* Construct the clean locale string */
locale_size = 0;
/* determine the size */
if (mask & E_INTL_LOC_LANG)
locale_size = strlen(locale_parts->lang) + 1;
if (mask & E_INTL_LOC_REGION)
locale_size += strlen(locale_parts->region) + 1;
if (mask & E_INTL_LOC_CODESET)
locale_size += strlen(locale_parts->codeset) + 1;
if (mask & E_INTL_LOC_MODIFIER)
locale_size += strlen(locale_parts->modifier) + 1;
/* Allocate memory */
locale = (char *) malloc(locale_size);
locale[0] = 0;
if (mask & E_INTL_LOC_LANG)
strcat(locale, locale_parts->lang);
if (mask & E_INTL_LOC_REGION)
{
if (locale[0] != 0) strcat(locale, "_");
strcat(locale, locale_parts->region);
}
if (mask & E_INTL_LOC_CODESET)
{
if (locale[0] != 0) strcat(locale, ".");
strcat(locale, locale_parts->codeset);
}
if (mask & E_INTL_LOC_MODIFIER)
{
if (locale[0] != 0) strcat(locale, "@");
strcat(locale, locale_parts->modifier);
}
return locale;
}
EAPI char *
e_intl_locale_charset_canonic_get(const char *charset)
{
char charset_canonic[32];
char c;
int i, i_tmp;
i = 0;
i_tmp = 0;
while ((c = charset[i++]) != 0)
{
if (isalnum(c))
charset_canonic[i_tmp++] = tolower(c);
}
charset_canonic[i_tmp] = 0;
if (!strcmp(charset, charset_canonic))
return NULL;
return strdup(charset_canonic);
}
static Evas_List *
_e_intl_locale_system_locales_get(void)
{
Evas_List *locales;
FILE *output;
locales = NULL;
output = popen("locale -a", "r");
if (output)
{
char line[32];
while (fscanf(output, "%[^\n]\n", line) == 1)
locales = evas_list_append(locales, strdup(line));
pclose(output);
}
return locales;
}
/*
* must be an un aliased locale;
*/
static int
_e_intl_locale_validate(const char *locale)
{
Evas_List *all_locales;
E_Locale_Parts *locale_parts;
char *locale_lr;
char *locale_cs_canonic;
int found;
found = 0;
locale_parts = e_intl_locale_parts_get(locale);
/* Gather the search information */
locale_lr =
e_intl_locale_parts_combine(locale_parts,
E_INTL_LOC_LANG | E_INTL_LOC_REGION);
if (locale_lr == NULL)
{
/* Not valid locale, maybe its an alias */
locale_lr = strdup(locale);
locale_cs_canonic = NULL;
}
else
{
if (locale_parts && locale_parts->codeset)
locale_cs_canonic = e_intl_locale_charset_canonic_get(locale_parts->codeset);
else
locale_cs_canonic = NULL;
}
/* Get list of all available locales and aliases */
all_locales = _e_intl_locale_system_locales_get();
/* Match locale with one from the list */
while (all_locales)
{
char *locale_next;
locale_next = all_locales->data;
if (found == 0)
{
E_Locale_Parts *locale_parts_next;
char * locale_lr_next;
locale_parts_next = e_intl_locale_parts_get(locale_next);
locale_lr_next = e_intl_locale_parts_combine(locale_parts_next,
E_INTL_LOC_LANG | E_INTL_LOC_REGION);
if ((locale_parts) && (locale_lr_next) &&
(!strcmp(locale_lr, locale_lr_next)))
{
/* Matched lang/region part, now if CS matches */
if ((locale_parts->codeset == NULL) && (locale_parts_next->codeset == NULL))
{
/* Lang/Region parts match and no charsets,
* we have a match
*/
found = 1;
}
else if (locale_parts->codeset && locale_parts_next->codeset)
{
if (!strcmp(locale_parts->codeset, locale_parts_next->codeset))
{
/* Lang/Region and charsets match */
found = 1;
}
else if (locale_cs_canonic)
{
char *locale_cs_canonic_next;
/* try to match charsets in canonic form */
locale_cs_canonic_next =
e_intl_locale_charset_canonic_get(locale_parts_next->codeset);
if (locale_cs_canonic_next)
{
if (!strcmp(locale_cs_canonic, locale_cs_canonic_next))
{
/* Lang/Resion and charsets in canonic
* form match
*/
found = 1;
}
free(locale_cs_canonic_next);
}
else
{
if (!strcmp(locale_cs_canonic, locale_parts_next->codeset))
{
/* Lang/Resion and charsets in canonic
* form match
*/
found = 1;
}
}
}
}
}
else
{
/* Its an alias */
if (!strcmp(locale_lr, locale_next)) found = 1;
}
e_intl_locale_parts_free(locale_parts_next);
E_FREE(locale_lr_next);
}
all_locales = evas_list_remove_list(all_locales, all_locales);
free(locale_next);
}
e_intl_locale_parts_free(locale_parts);
free(locale_lr);
E_FREE(locale_cs_canonic);
return found;
}
/*
* arg local must be an already validated and unaliased locale
* returns the locale search order e.g.
* en_US.UTF-8 ->
* Mask (b) Locale (en_US.UTF-8)
* Mask (a) Locale (en_US)
* Mask (9) Locale (en.UTF-8)
* Mask (8) Locale (en)
*/
static Evas_List *
_e_intl_locale_search_order_get(const char *locale)
{
Evas_List *search_list;
E_Locale_Parts *locale_parts;
char *masked_locale;
int mask;
locale_parts = e_intl_locale_parts_get(locale);
if (locale_parts == NULL) return NULL;
search_list = NULL;
for (mask = E_INTL_LOC_ALL; mask >= E_INTL_LOC_LANG; mask--)
{
if ((mask & locale_parts->mask) == mask)
{
/* Only append if the mask we need is available */
masked_locale = e_intl_locale_parts_combine(locale_parts, mask);
search_list = evas_list_append(search_list, masked_locale);
}
}
e_intl_locale_parts_free(locale_parts);
return search_list;
}
static Evas_List *
_e_intl_imc_dir_scan(const char *dir)
{
Evas_List *imcs;
Ecore_List *files;
char *file;
imcs = NULL;
files = ecore_file_ls(dir);
if (!files) return NULL;
ecore_list_first_goto(files);
if (files)
{
while ((file = ecore_list_next(files)))
{
if (strstr(file, ".imc") != NULL)
{
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "%s/%s", dir, file);
imcs = evas_list_append(imcs, strdup(buf));
}
}
ecore_list_destroy(files);
}
return imcs;
}