efl/src/lib/ecore_imf/ecore_imf_module.c

337 lines
8.2 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <Ecore.h>
#include <ecore_private.h>
#include "Ecore_IMF.h"
#include "ecore_imf_private.h"
#include "../../static_libs/buildsystem/buildsystem.h"
static void _ecore_imf_module_free(Ecore_IMF_Module *module);
static int _ecore_imf_modules_exists(const char *ctx_id);
typedef struct _Ecore_IMF_Selector
{
const char *toselect;
void *selected;
} Ecore_IMF_Selector;
static Eina_Hash *modules = NULL;
static Eina_Array *module_list = NULL;
static Eina_Prefix *pfx = NULL;
void
ecore_imf_module_init(void)
{
const char *built_modules[] = {
#ifdef BUILD_ECORE_IMF_XIM
"xim",
#endif
#ifdef BUILD_ECORE_IMF_IBUS
"ibus",
#endif
#ifdef BUILD_ECORE_IMF_SCIM
"scim",
#endif
#ifdef BUILD_ECORE_IMF_WAYLAND
"wayland",
#endif
NULL
};
const char *env;
char buf[PATH_MAX] = "";
pfx = eina_prefix_new(NULL, ecore_imf_init,
"ECORE_IMF", "ecore_imf", "checkme",
PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
#ifdef NEED_RUN_IN_TREE
#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
if (getuid() == geteuid())
#endif
{
if (getenv("EFL_RUN_IN_TREE"))
{
struct stat st;
snprintf(buf, sizeof(buf), "%s/src/modules/ecore_imf",
PACKAGE_BUILD_DIR);
if (stat(buf, &st) == 0)
{
const char **itr;
const char **modules_load;
const char *modules_one[2] = { NULL, NULL };
modules_load = built_modules;
env = getenv("ECORE_IMF_MODULE");
if ((env) && (env[0]))
{
modules_one[0] = env;
modules_load = modules_one;
}
for (itr = modules_load; *itr != NULL; itr++)
{
bs_mod_dir_get(buf, sizeof(buf), "ecore_imf", *itr);
module_list = eina_module_list_get
(module_list, buf, EINA_FALSE, NULL, NULL);
}
if (module_list) eina_module_list_load(module_list);
return;
}
}
}
#endif
env = getenv("ECORE_IMF_MODULE");
#ifdef BUILD_ECORE_IMF_WAYLAND
// if not set and we are sure we're on wayland....
if ((!env) && (getenv("WAYLAND_DISPLAY")) && (!getenv("DISPLAY")))
env = "wayland";
#endif
#ifdef BUILD_ECORE_IMF_XIM
if ((!env) && (!getenv("WAYLAND_DISPLAY")) && (getenv("DISPLAY")))
env = "xim";
#endif
if ((env) && (env[0]))
{
const char **itr;
Eina_Bool ok = EINA_FALSE;
for (itr = built_modules; *itr != NULL; itr++)
{
if (!strcmp(env, *itr))
{
ok = EINA_TRUE;
break;
}
}
if (ok)
{
Eina_Module *m;
snprintf(buf, sizeof(buf),
"%s/ecore_imf/modules/%s/%s/module" SHARED_LIB_SUFFIX,
eina_prefix_lib_get(pfx), env, MODULE_ARCH);
m = eina_module_new(buf);
if (m)
{
module_list = eina_array_new(1);
if (module_list) eina_array_push(module_list, m);
else eina_module_free(m);
}
}
}
else
{
Eina_Module *m;
const char **itr;
for (itr = built_modules; *itr != NULL; itr++)
{
snprintf(buf, sizeof(buf),
"%s/ecore_imf/modules/%s/%s/module" SHARED_LIB_SUFFIX,
eina_prefix_lib_get(pfx), *itr, MODULE_ARCH);
m = eina_module_new(buf);
if (m)
{
module_list = eina_array_new(1);
if (module_list)
{
eina_array_push(module_list, m);
break;
}
else
eina_module_free(m);
}
}
}
if (module_list) eina_module_list_load(module_list);
}
void
ecore_imf_module_shutdown(void)
{
if (modules)
{
eina_hash_free(modules);
modules = NULL;
}
if (module_list)
{
eina_module_list_free(module_list);
eina_array_free(module_list);
module_list = NULL;
}
eina_prefix_free(pfx);
pfx = NULL;
}
static Eina_Bool
_hash_module_available_get(const Eina_Hash *hash EINA_UNUSED, int *data, void *list)
{
*(Eina_List**)list = eina_list_append(*(Eina_List**)list, data);
return EINA_TRUE;
}
Eina_List *
ecore_imf_module_available_get(void)
{
Eina_List *values = NULL;
Eina_Iterator *it = NULL;
if (!modules) return NULL;
it = eina_hash_iterator_data_new(modules);
if (!it)
return NULL;
eina_iterator_foreach(it, EINA_EACH_CB(_hash_module_available_get), &values);
eina_iterator_free(it);
return values;
}
Ecore_IMF_Module *
ecore_imf_module_get(const char *ctx_id)
{
if (!modules) return NULL;
return eina_hash_find(modules, ctx_id);
}
Ecore_IMF_Context *
ecore_imf_module_context_create(const char *ctx_id)
{
Ecore_IMF_Module *module;
Ecore_IMF_Context *ctx = NULL;
if (!modules) return NULL;
module = eina_hash_find(modules, ctx_id);
if (module)
{
if (!(ctx = module->create())) return NULL;
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_module_context_create");
return NULL;
}
ctx->module = module;
}
return ctx;
}
static Eina_Bool
_hash_ids_get(const Eina_Hash *hash EINA_UNUSED, const char *key, void *list)
{
*(Eina_List**)list = eina_list_append(*(Eina_List**)list, key);
return EINA_TRUE;
}
Eina_List *
ecore_imf_module_context_ids_get(void)
{
Eina_List *l = NULL;
Eina_Iterator *it = NULL;
if (!modules) return NULL;
it = eina_hash_iterator_key_new(modules);
if (!it)
return NULL;
eina_iterator_foreach(it, EINA_EACH_CB(_hash_ids_get), &l);
eina_iterator_free(it);
return l;
}
static Eina_Bool
_hash_ids_by_canvas_type_get(const Eina_Hash *hash EINA_UNUSED, void *data, void *fdata)
{
Ecore_IMF_Module *module = data;
Ecore_IMF_Selector *selector = fdata;
if (!strcmp(module->info->canvas_type, selector->toselect))
selector->selected = eina_list_append(selector->selected, (void *)module->info->id);
return EINA_TRUE;
}
Eina_List *
ecore_imf_module_context_ids_by_canvas_type_get(const char *canvas_type)
{
Ecore_IMF_Selector selector;
Eina_List *values = NULL;
Eina_Iterator *it = NULL;
if (!modules) return NULL;
if (!canvas_type)
return ecore_imf_module_context_ids_get();
it = eina_hash_iterator_data_new(modules);
if (!it)
return NULL;
selector.toselect = canvas_type;
selector.selected = values;
eina_iterator_foreach(it, EINA_EACH_CB(_hash_ids_by_canvas_type_get), &selector);
eina_iterator_free(it);
return values;
}
EAPI void
ecore_imf_module_register(const Ecore_IMF_Context_Info *info,
Ecore_IMF_Context *(*imf_module_create)(void),
Ecore_IMF_Context *(*imf_module_exit)(void))
{
Ecore_IMF_Module *module;
if (!info || _ecore_imf_modules_exists(info->id)) return;
if (!modules)
modules = eina_hash_string_superfast_new(EINA_FREE_CB(_ecore_imf_module_free));
module = malloc(sizeof(Ecore_IMF_Module));
EINA_SAFETY_ON_NULL_RETURN(module);
module->info = info;
/* cache imf_module_create as it may be used several times */
module->create = imf_module_create;
module->exit = imf_module_exit;
eina_hash_add(modules, info->id, module);
}
static void
_ecore_imf_module_free(Ecore_IMF_Module *module)
{
if (module->exit) module->exit();
free(module);
}
static int
_ecore_imf_modules_exists(const char *ctx_id)
{
if (!modules) return 0;
if (!ctx_id) return 0;
if (eina_hash_find(modules, ctx_id))
return 1;
return 0;
}