d6b0be120f1779216f0a8f102451bacd6adee0d9
[framework/uifw/ecore.git] / src / lib / ecore_imf / ecore_imf_module.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include <limits.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8
9 #include "config.h"
10
11 #include "ecore_imf_private.h"
12
13 static void _ecore_imf_module_load_all(void);
14 static void _ecore_imf_module_append(Ecore_Plugin *plugin, const Ecore_IMF_Context_Info *info, Ecore_IMF_Context *(*imf_module_create)(void));
15 static void _ecore_imf_module_free(Ecore_IMF_Module *module);
16 static int _ecore_imf_modules_exists(const char *ctx_id);
17
18 static Ecore_Path_Group *ecore_imf_modules_path = NULL;
19 static Ecore_Hash *modules = NULL;
20
21 void
22 ecore_imf_module_init(void)
23 {
24    char pathname[PATH_MAX];
25    const char *homedir;
26
27    ecore_imf_modules_path = ecore_path_group_new();
28    snprintf(pathname, sizeof(pathname), "%s/ecore/immodules/",
29             PACKAGE_LIB_DIR);
30    ecore_path_group_add(ecore_imf_modules_path, pathname);
31
32    homedir = getenv("HOME");
33    if (homedir)
34      {
35         snprintf(pathname, sizeof(pathname), "%s/.ecore/immodules/",
36                  homedir);
37         ecore_path_group_add(ecore_imf_modules_path, pathname);
38      }
39
40    modules = NULL;
41    _ecore_imf_module_load_all();
42 }
43
44 void
45 ecore_imf_module_shutdown(void)
46 {
47    if (modules)
48      {
49         ecore_hash_destroy(modules);
50         modules = NULL;
51      }
52
53    ecore_path_group_del(ecore_imf_modules_path);
54    ecore_imf_modules_path = NULL;
55 }
56
57 Ecore_List *
58 ecore_imf_module_available_get(void)
59 {
60    Ecore_List *values;
61    unsigned int i = 0;
62
63    if (!modules) return NULL;
64
65    /* ecore_hash_values() */
66    values = ecore_list_new();
67    while (i < ecore_prime_table[modules->size])
68      {
69         if (modules->buckets[i])
70           {
71              Ecore_Hash_Node *node;
72
73              for (node = modules->buckets[i]; node; node = node->next)
74                ecore_list_append(values, node->value);
75           }
76         i++;
77      }
78    ecore_list_first_goto(values);
79
80    return values;
81 }
82
83 Ecore_IMF_Module *
84 ecore_imf_module_get(const char *ctx_id)
85 {
86    if (!modules) return NULL;
87    return ecore_hash_get(modules, ctx_id);
88 }
89
90 Ecore_IMF_Context *
91 ecore_imf_module_context_create(const char *ctx_id)
92 {
93    Ecore_IMF_Module *module;
94    Ecore_IMF_Context *ctx = NULL;
95
96    if (!modules) return NULL;
97    module = ecore_hash_get(modules, ctx_id);
98    if (module)
99      {
100         ctx = module->create();
101         if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
102           {
103              ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
104                               "ecore_imf_module_context_create");
105              return NULL;
106           }
107         ctx->module = module;
108      }
109    return ctx;
110 }
111
112 Ecore_List *
113 ecore_imf_module_context_ids_get(void)
114 {
115    if (!modules) return NULL;
116    return ecore_hash_keys(modules);
117 }
118
119 Ecore_List *
120 ecore_imf_module_context_ids_by_canvas_type_get(const char *canvas_type)
121 {
122    Ecore_List *values;
123    unsigned int i = 0;
124
125    if (!modules) return NULL;
126
127    if (!canvas_type)
128      return ecore_imf_module_context_ids_get();
129
130    values = ecore_list_new();
131    while (i < ecore_prime_table[modules->size])
132      {
133         if (modules->buckets[i])
134           {
135              Ecore_Hash_Node *node;
136
137              for (node = modules->buckets[i]; node; node = node->next)
138                {
139                   Ecore_IMF_Module *module = node->value;
140                   if (strcmp(module->info->canvas_type, canvas_type) == 0)
141                     ecore_list_append(values, (void *) module->info->id);
142                }
143           }
144         i++;
145      }
146    ecore_list_first_goto(values);
147
148    return values;
149 }
150
151 static void
152 _ecore_imf_module_load_all(void)
153 {
154    Ecore_List *avail;
155    char *filename;
156    Ecore_Plugin *plugin;
157    const Ecore_IMF_Context_Info *info = NULL;
158    int (*imf_module_init)(const Ecore_IMF_Context_Info **info);
159    Ecore_IMF_Context *(*imf_module_create)(void);
160
161    avail = ecore_plugin_available_get(ecore_imf_modules_path);
162    if (!avail) return;
163
164    ecore_list_first_goto(avail);
165    while ((filename = ecore_list_next(avail)))
166      {
167         plugin = ecore_plugin_load(ecore_imf_modules_path, filename, NULL);
168         if (!plugin)
169           {
170              fprintf(stderr, "** ecore_imf: Error loading input method plugin %s!\n",
171                      filename);
172              continue;
173           }
174
175         imf_module_init = ecore_plugin_symbol_get(plugin, "imf_module_init");
176         if (!imf_module_init || !imf_module_init(&info) || !info)
177           {
178              fprintf(stderr, "** ecore_imf: Error initializing input method plugin %s! "
179                              "'imf_module_init' is missing or failed to run!",
180                      filename);
181              ecore_plugin_unload(plugin);
182              continue;
183           }
184
185         if (_ecore_imf_modules_exists(info->id))
186           {
187              fprintf(stderr, "** ecore_imf: Error loading input method plugin %s! "
188                              "Plugin with id='%s' already exists!",
189                      filename, info->id);
190              ecore_plugin_unload(plugin);
191              continue;
192           }
193
194         imf_module_create = ecore_plugin_symbol_get(plugin, "imf_module_create");
195         if (!imf_module_create)
196           {
197              fprintf(stderr, "** ecore_imf: Error setting up input method plugin %s! "
198                              "'imf_module_create' is missing!",
199                      filename);
200              ecore_plugin_unload(plugin);
201              continue;
202           }
203
204         _ecore_imf_module_append(plugin, info, imf_module_create);
205      }
206
207    ecore_list_destroy(avail);
208 }
209
210 static void
211 _ecore_imf_module_append(Ecore_Plugin *plugin,
212                         const Ecore_IMF_Context_Info *info,
213                         Ecore_IMF_Context *(*imf_module_create)(void))
214 {
215    Ecore_IMF_Module *module;
216
217    if (!modules)
218      {
219         modules = ecore_hash_new(ecore_str_hash, ecore_str_compare);
220         ecore_hash_free_key_cb_set(modules, free);
221         ecore_hash_free_value_cb_set(modules, (Ecore_Free_Cb) _ecore_imf_module_free);
222      }
223
224    module = malloc(sizeof(Ecore_IMF_Module));
225    module->plugin = plugin;
226    module->info = info;
227    /* cache imf_module_create as it may be used several times */
228    module->create = imf_module_create;
229
230    ecore_hash_set(modules, strdup(info->id), module);
231 }
232
233 static void
234 _ecore_imf_module_free(Ecore_IMF_Module *module)
235 {
236    int (*imf_module_exit)(void);
237
238    imf_module_exit = ecore_plugin_symbol_get(module->plugin, "imf_module_exit");
239    if (imf_module_exit) imf_module_exit();
240    ecore_plugin_unload(module->plugin);
241    free(module);
242 }
243
244 static int
245 _ecore_imf_modules_exists(const char *ctx_id)
246 {
247    if (!modules) return 0;
248    return (ecore_hash_get(modules, ctx_id) != NULL);
249 }