In case a user sets min-value of the item, the toolbar shouldn't set the min-value...
[framework/uifw/elementary.git] / src / lib / elm_module.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /* what are moodules in elementary for? for modularising behavior and features
5  * so they can be plugged in and out where you dont want the core source to
6  * always behave like that or do it that way. plug it at runtime!
7  *
8  * they have module names (in config) and "slots" to plug that module into
9  * to server a purpose. eg you plug plugin "xx" into the "entry-copy-paste"
10  * slot so it would provide replacement copy & paste ui functionality and
11  * specific symbols
12  *
13  * config is something like:
14  *
15  * export ELM_MODULES="xx>slot1:yy>slot2"
16  *
17  * where a module named xx is plugged into slot1 & yy is plugged into slot2
18  *
19  * real examples:
20  *
21  * export ELM_MODULES="my_module>entry/api"
22  *
23  * this loads the module called "my_module" into the slot "entry/api" which
24  * is an api slot for entry modules to modify behavior and hook to
25  * creation/deletion of the entry as well as replace the longpress behavior.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "elementary_config.h"
30 #endif
31
32 static Eina_Hash *modules = NULL;
33 static Eina_Hash *modules_as = NULL;
34
35 void
36 _elm_module_init(void)
37 {
38    modules = eina_hash_string_small_new(NULL);
39    modules_as = eina_hash_string_small_new(NULL);
40 }
41
42 void
43 _elm_module_shutdown(void)
44 {
45    // FIXME: unload all modules
46    if (modules) eina_hash_free(modules);
47    modules = NULL;
48    if (modules_as) eina_hash_free(modules_as);
49    modules_as = NULL;
50 }
51
52 void
53 _elm_module_parse(const char *s)
54 {
55    const char *p, *pe;
56
57    p = s;
58    pe = p;
59    for (;;)
60      {
61         if ((*pe == ':') || (!*pe))
62           { // p -> pe == 'name:'
63              if (pe > p)
64                {
65                   char *n = malloc(pe - p + 1);
66                   if (n)
67                     {
68                        char *nn;
69
70                        strncpy(n, p, pe - p);
71                        n[pe - p] = 0;
72                        nn = strchr(n, '>');
73                        if (nn)
74                          {
75                             *nn = 0;
76                             nn++;
77                             _elm_module_add(n, nn);
78                          }
79                        free(n);
80                     }
81                }
82              if (!*pe) break;
83              p = pe + 1;
84              pe = p;
85           }
86         else
87           pe++;
88      }
89 }
90
91 Elm_Module *
92 _elm_module_find_as(const char *as)
93 {
94    Elm_Module *m;
95
96    m = eina_hash_find(modules_as, as);
97    if (!m) return NULL;
98
99    if (!_elm_module_load(m))
100      {
101         _elm_module_del(m);
102         return NULL;
103      }
104    return m;
105 }
106
107 Eina_Bool
108 _elm_module_load(Elm_Module *m)
109 {
110    const char *home;
111    char buf[PATH_MAX];
112
113    if (m->module) return EINA_TRUE;
114
115    home = getenv("HOME");
116    if (home)
117      {
118         snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s/%s/module" EFL_SHARED_EXTENSION, home, m->name, MODULE_ARCH);
119         m->module = eina_module_new(buf);
120         if (m->module && eina_module_load (m->module) == EINA_TRUE)
121           {
122              m->init_func = eina_module_symbol_get(m->module, "elm_modapi_init");
123              if (m->init_func)
124                {
125                   m->shutdown_func = eina_module_symbol_get(m->module, "elm_modapi_shutdown");
126                   m->so_path = eina_stringshare_add(buf);
127                   snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s/%s", home, m->name, MODULE_ARCH);
128                   m->bin_dir = eina_stringshare_add(buf);
129                   snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s", home, m->name);
130                   m->data_dir = eina_stringshare_add(buf);
131                }
132              else
133                {
134                   if (m->module)
135                     {
136                        eina_module_unload(m->module);
137                        eina_module_free(m->module);
138                        m->module = NULL;
139                     }
140                   return EINA_FALSE;
141                }
142           }
143         else if (m->module)
144           {
145             eina_module_free(m->module);
146             m->module = NULL;
147           }
148      }
149
150    if (!m->module)
151      {
152         snprintf(buf, sizeof(buf), "%s/elementary/modules/%s/%s/module" EFL_SHARED_EXTENSION, _elm_lib_dir, m->name, MODULE_ARCH);
153         m->module = eina_module_new(buf);
154         if (m->module && eina_module_load (m->module) == EINA_TRUE)
155           {
156              m->init_func = eina_module_symbol_get(m->module, "elm_modapi_init");
157              if (m->init_func)
158                {
159                   m->shutdown_func = eina_module_symbol_get(m->module, "elm_modapi_shutdown");
160                   m->so_path = eina_stringshare_add(buf);
161                   snprintf(buf, sizeof(buf), "%s/elementary/modules/%s/%s", _elm_lib_dir, m->name, MODULE_ARCH);
162                   m->bin_dir = eina_stringshare_add(buf);
163                   snprintf(buf, sizeof(buf), "%s/elementary/modules/%s", _elm_lib_dir, m->name);
164                   m->data_dir = eina_stringshare_add(buf);
165                }
166              else
167                {
168                   if (m->module)
169                     {
170                        eina_module_unload(m->module);
171                        eina_module_free(m->module);
172                        m->module = NULL;
173                     }
174                   return EINA_FALSE;
175                }
176           }
177      }
178    else if (m->module)
179      {
180        eina_module_free(m->module);
181        m->module = NULL;
182      }
183
184    if (!m->module) return EINA_FALSE;
185    return EINA_TRUE;
186 }
187
188 void
189 _elm_module_unload(Elm_Module *m)
190 {
191    eina_stringshare_del(m->so_path);
192    eina_stringshare_del(m->data_dir);
193    eina_stringshare_del(m->bin_dir);
194    if (m->api)
195      {
196         free(m->api);
197         m->api = NULL;
198      }
199    if (m->module)
200      {
201         if (m->shutdown_func) m->shutdown_func(m);
202         eina_module_unload(m->module);
203         eina_module_free(m->module);
204         m->module = NULL;
205      }
206    m->shutdown_func = NULL;
207    m->init_func = NULL;
208 }
209
210 Elm_Module *
211 _elm_module_add(const char *name, const char *as)
212 {
213    Elm_Module *m;
214
215    if (name[0] == '/') return NULL;
216
217    m = eina_hash_find(modules, name);
218    if (m)
219      {
220         m->references++;
221         return m;
222      }
223    m = calloc(1, sizeof(Elm_Module));
224    if (!m) return NULL;
225    m->version = 1;
226    m->name = eina_stringshare_add(name);
227    m->references = 1;
228    eina_hash_direct_add(modules, m->name, m);
229    m->as = eina_stringshare_add(as);
230    eina_hash_direct_add(modules_as, m->as, m);
231    return m;
232 }
233
234 void
235 _elm_module_del(Elm_Module *m)
236 {
237    m->references--;
238    if (m->references > 0) return;
239    _elm_module_unload(m);
240    eina_hash_del(modules, m->name, m);
241    eina_hash_del(modules_as, m->as, m);
242    eina_stringshare_del(m->name);
243    eina_stringshare_del(m->as);
244    free(m);
245 }
246
247 const void *
248 _elm_module_symbol_get(Elm_Module *m, const char *name)
249 {
250    return eina_module_symbol_get(m->module, name);
251 }