enlightenment/src/bin/e_intl.c

474 lines
13 KiB
C

/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "e.h"
#include "config.h"
/* TODO List:
*
* * add more language names to the language name list list in e_intl_language_name_get()
* * as we get translations add languages to the simplified lang list (C and en are currently the same, ja is a test translation - incomplete)
*/
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 Evas_List *_e_intl_languages = 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 char *_e_intl_input_method = NULL;
static Eet_Data_Descriptor *_e_intl_input_method_config_edd = NULL;
#define ADD_LANG(lang) _e_intl_languages = evas_list_append(_e_intl_languages, lang)
#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) || (strlen(EXE) == 0)))
static int _e_intl_cb_exit(void *data, int type, void *event);
static Evas_List *_e_intl_imc_path_scan(E_Path *path);
static Evas_List *_e_intl_imc_dir_scan(char *dir);
static E_Input_Method_Config *_e_intl_imc_find(Evas_List *imc_list, char *name);
int
e_intl_init(void)
{
char *s;
E_Input_Method_Config *imc;
if (_e_intl_languages) return 1;
/* supporeted languages - as we get translations - add them here
*
* if you add a language:
*
* NOTE: add a language NAME for this in e_intl_language_name_get() if
* there isn't one yet (use the english name - then we will add
* translations of the language names to the .po file)
* NOTE: add a translation logic list to take all possible ways to address
* a language locale and convert it to a simplified one that is in
* the list here below. languages can often have multiple ways of
* being addressed (same language spoken in multiple countries or
* many variants of the language). this translation allows all the
* variants to be used and mapped to a simple "single" name for that
* language. if the differences in variants are large (eg simplified
* vs. traditional chinese) we may refer to them as separate languages
* entirely.
*/
/* FIXME: remove this - hunt locale dirs (a user one in ~/.e/e/ too for
* user installed locale support
*/
ADD_LANG("");
ADD_LANG("en_US.UTF-8");
ADD_LANG("ja_JP.UTF-8");
ADD_LANG("fr_FR.UTF-8");
ADD_LANG("es_AR.UTF-8");
ADD_LANG("pt_BR.UTF-8");
ADD_LANG("fi_FI.UTF-8");
ADD_LANG("ru_RU.UTF-8");
ADD_LANG("bg_BG.UTF-8");
ADD_LANG("de_DE.UTF-8");
ADD_LANG("pl_PL.UTF-8");
ADD_LANG("zh_CN.UTF-8");
ADD_LANG("hu_HU.UTF-8");
ADD_LANG("sl_SI.UTF-8");
ADD_LANG("it_IT.UTF-8");
ADD_LANG("cs_CZ.UTF-8");
ADD_LANG("da_DK.UTF-8");
ADD_LANG("sk_SK.UTF-8");
ADD_LANG("sv_SV.UTF-8");
ADD_LANG("nb_NO.UTF-8");
_e_intl_input_method_config_edd = E_CONFIG_DD_NEW("input_method_config", E_Input_Method_Config);
E_CONFIG_VAL(_e_intl_input_method_config_edd, E_Input_Method_Config, version, INT);
E_CONFIG_VAL(_e_intl_input_method_config_edd, E_Input_Method_Config, e_im_name, STR);
E_CONFIG_VAL(_e_intl_input_method_config_edd, E_Input_Method_Config, gtk_im_module, STR);
E_CONFIG_VAL(_e_intl_input_method_config_edd, E_Input_Method_Config, qt_im_module, STR);
E_CONFIG_VAL(_e_intl_input_method_config_edd, E_Input_Method_Config, xmodifiers, STR);
E_CONFIG_VAL(_e_intl_input_method_config_edd, E_Input_Method_Config, e_im_exec, STR);
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;
}
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);
evas_list_free(_e_intl_languages);
E_CONFIG_DD_FREE(_e_intl_input_method_config_edd);
return 1;
}
/* Setup configuration settings and start services */
int
e_intl_post_init(void)
{
if ((e_config->language) && (strlen(e_config->language) > 0))
e_intl_language_set(e_config->language);
if ((e_config->input_method) && (strlen(e_config->input_method) > 0))
e_intl_input_method_set(e_config->input_method);
_e_intl_exit_handler = ecore_event_handler_add(ECORE_EVENT_EXE_EXIT, _e_intl_cb_exit, NULL);
}
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_EXE_STOP(_e_intl_input_method_exec);
}
static Evas_List *
_e_intl_imc_path_scan(E_Path *path)
{
Evas_List *next;
Evas_List *dir_list;
Evas_List *all_imcs;
if (!path) return NULL;
all_imcs = NULL;
dir_list = e_path_dir_list_get(path);
for (next = dir_list ; next ; next = next->next)
{
E_Path_Dir *epd;
Evas_List *dir_imcs;
epd = next->data;
dir_imcs = _e_intl_imc_dir_scan(epd->dir);
while (dir_imcs)
{
E_Input_Method_Config *imc;
imc = dir_imcs->data;
dir_imcs = evas_list_remove_list(dir_imcs, dir_imcs);
if (_e_intl_imc_find(all_imcs, imc->e_im_name))
{
e_intl_input_method_config_free(imc);
}
else
{
all_imcs = evas_list_append(all_imcs, imc);
}
}
}
e_path_dir_list_free(dir_list);
return all_imcs;
}
static Evas_List *
_e_intl_imc_dir_scan(char *dir)
{
Evas_List *imcs;
Ecore_List *files;
char *file;
imcs = NULL;
files = ecore_file_ls(dir);
if (!files) return NULL;
ecore_list_goto_first(files);
if (files)
{
while ((file = ecore_list_next(files)))
{
E_Input_Method_Config *imc;
Eet_File *imc_file;
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "%s/%s", dir, file);
imc_file = eet_open(buf, EET_FILE_MODE_READ);
if (imc_file)
{
imc = e_intl_input_method_config_read (imc_file);
if (imc)
{
imcs = evas_list_append(imcs, imc);
}
}
}
ecore_list_destroy(files);
}
return imcs;
}
static E_Input_Method_Config *
_e_intl_imc_find(Evas_List *imc_list, char * name)
{
Evas_List *l;
if (!imc_list) return NULL;
if (!name) return NULL;
for (l = imc_list; l; l = l->next)
{
E_Input_Method_Config *imc;
imc = l->data;
if (!strcmp(imc->e_im_name, name)) return imc;
}
return NULL;
}
void
e_intl_language_set(const char *lang)
{
/* 1 list ~/.e/e/locale contents */
/* 2 list e_preifx_locale_get() contents */
/* FIXME: determine if in user or system locale dir */
if (_e_intl_language) free(_e_intl_language);
/* NULL lang means set everything back to the original environemtn 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);
}
if (!lang) lang = getenv("LC_MESSAGES");
if (!lang) lang = getenv("LANGUAGE");
if (!lang) lang = getenv("LC_ALL");
if (!lang) lang = getenv("LANG");
if (lang)
{
_e_intl_language = strdup(lang);
e_util_env_set("LANGUAGE", _e_intl_language);
if (getenv("LANG")) e_util_env_set("LANG", _e_intl_language);
if (getenv("LC_ALL")) e_util_env_set("LC_ALL", _e_intl_language);
if (getenv("LC_MESSAGES")) e_util_env_set("LC_MESSAGES", _e_intl_language);
}
else
{
_e_intl_language = NULL;
}
if (setlocale(LC_ALL, _e_intl_language) == NULL)
{
perror("setlocale() :");
if (_e_intl_language)
printf("An error occured when trying to use the locale: %s\nDetails:\n",
_e_intl_language);
else
printf("An error occured trying to use the default locale\n");
}
bindtextdomain(PACKAGE, e_prefix_locale_get());
textdomain(PACKAGE);
// XSetLocaleModifiers("");
bind_textdomain_codeset(PACKAGE, "UTF-8");
}
const char *
e_intl_language_get(void)
{
return _e_intl_language;
}
const Evas_List *
e_intl_language_list(void)
{
/* FIXME: hunt dirs for locales */
return _e_intl_languages;
}
void
e_intl_input_method_set(const char *method)
{
if (_e_intl_input_method) free(_e_intl_input_method);
if (!method)
{
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 (method)
{
Evas_List * input_methods;
E_Input_Method_Config *imc;
input_methods = _e_intl_imc_path_scan(path_input_methods);
_e_intl_input_method = strdup(method);
imc = _e_intl_imc_find (input_methods, _e_intl_input_method);
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_intl_input_method_exec = ecore_exe_run(imc->e_im_exec, NULL);
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_error_dialog_show(_("Input Method Error"),
_( "Error starting the input method "
"executable\n\n"
"please make sure that your input\n"
"method configuration is correct and\n"
"that your configuration's\n"
"executable is in your PATH\n"));
}
}
/* Need to free up the directory listing */
while (input_methods)
{
E_Input_Method_Config *imc;
imc = input_methods->data;
input_methods = evas_list_remove_list(input_methods,input_methods);
e_intl_input_method_config_free (imc);
}
}
else
{
_e_intl_input_method = NULL;
}
}
const char *
e_intl_input_method_get(void)
{
return _e_intl_input_method;
}
Evas_List *
e_intl_input_method_list(void)
{
Evas_List *input_methods;
Evas_List *im_list;
Evas_List *l;
E_Input_Method_Config *imc;
im_list = NULL;
input_methods = _e_intl_imc_path_scan(path_input_methods);
for (l = input_methods; l; l = l->next)
{
imc = l->data;
im_list = evas_list_append(im_list, strdup(imc->e_im_name));
}
/* Need to free up the directory listing */
while (input_methods)
{
E_Input_Method_Config *imc;
imc = input_methods->data;
input_methods = evas_list_remove_list(input_methods, input_methods);
e_intl_input_method_config_free (imc);
}
return im_list;
}
/* Get the input method configuration from the file */
E_Input_Method_Config *
e_intl_input_method_config_read (Eet_File * imc_file)
{
E_Input_Method_Config *imc;
imc = NULL;
if (imc_file)
{
imc = (E_Input_Method_Config *) eet_data_read(imc_file, _e_intl_input_method_config_edd, "imc");
}
return imc;
}
/* Write the input method configuration to the file */
int
e_intl_input_method_config_write (Eet_File * imc_file, E_Input_Method_Config * imc)
{
int ok = 0;
if (imc_file)
{
ok = eet_data_write(imc_file, _e_intl_input_method_config_edd, "imc", imc, 0);
}
return ok;
}
void
e_intl_input_method_config_free (E_Input_Method_Config *imc)
{
if (imc != NULL)
{
E_FREE(imc->e_im_name);
E_FREE(imc->gtk_im_module);
E_FREE(imc->qt_im_module);
E_FREE(imc->xmodifiers);
E_FREE(imc->e_im_exec);
E_FREE(imc);
}
}
static int
_e_intl_cb_exit(void *data, int type, void *event)
{
Ecore_Event_Exe_Exit *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;
}