Imported Upstream version 1.7.1
[platform/upstream/edje.git] / src / lib / edje_module.c
1 #include "edje_private.h"
2
3 Eina_Hash *_registered_modules = NULL;
4 Eina_List *_modules_paths = NULL;
5
6 Eina_List *_modules_found = NULL;
7
8 #if defined(__CEGCC__) || defined(__MINGW32CE__)
9 # define EDJE_MODULE_NAME "edje_%s.dll"
10 # define EDJE_EXTRA_MODULE_NAME 1
11 #elif _WIN32
12 # define EDJE_MODULE_NAME "module.dll"
13 #else
14 # define EDJE_MODULE_NAME "module.so"
15 #endif
16
17 EAPI Eina_Bool
18 edje_module_load(const char *module)
19 {
20    if (_edje_module_handle_load(module)) return EINA_TRUE;
21    return EINA_FALSE;
22 }
23
24 Eina_Module *
25 _edje_module_handle_load(const char *module)
26 {
27    const char *path;
28    Eina_List *l;
29    Eina_Module *em = NULL;
30
31    EINA_SAFETY_ON_NULL_RETURN_VAL(module, NULL);
32
33    em =  (Eina_Module *)eina_hash_find(_registered_modules, module);
34    if (em) return em;
35
36    EINA_LIST_FOREACH(_modules_paths, l, path)
37      {
38         char tmp[PATH_MAX];
39
40         snprintf(tmp, sizeof (tmp), "%s/%s/%s/" EDJE_MODULE_NAME, path, module, MODULE_ARCH
41 #ifdef EDJE_EXTRA_MODULE_NAME
42                  , module
43 #endif
44                 );
45         em = eina_module_new(tmp);
46         if (!em) continue;
47
48         if (!eina_module_load(em))
49           {
50              eina_module_free(em);
51              continue;
52           }
53         if (eina_hash_add(_registered_modules, module, em))
54           return em;
55      }
56
57    return NULL;
58 }
59
60 void
61 _edje_module_init(void)
62 {
63    char *paths[4] = { NULL, NULL, NULL, NULL };
64    unsigned int i;
65    unsigned int j;
66
67    _registered_modules = eina_hash_string_small_new(EINA_FREE_CB(eina_module_free));
68
69    /* 1. ~/.edje/modules/ */
70    paths[0] = eina_module_environment_path_get("HOME", "/.edje/modules");
71    /* 2. $(EDJE_MODULE_DIR)/edje/modules/ */
72    paths[1] = eina_module_environment_path_get("EDJE_MODULES_DIR", "/edje/modules");
73    /* 3. libedje.so/../edje/modules/ */
74    paths[2] = eina_module_symbol_path_get(_edje_module_init, "/edje/modules");
75    /* 4. PREFIX/edje/modules/ */
76 #ifndef _MSC_VER
77    paths[3] = strdup(PACKAGE_LIB_DIR "/edje/modules");
78 #endif
79
80    for (j = 0; j < ((sizeof (paths) / sizeof (char*)) - 1); ++j)
81      for (i = j + 1; i < sizeof (paths) / sizeof (char*); ++i)
82        if (paths[i] && paths[j] && !strcmp(paths[i], paths[j]))
83          {
84             free(paths[i]);
85             paths[i] = NULL;
86          }
87
88    for (i = 0; i < sizeof (paths) / sizeof (char*); ++i)
89      if (paths[i])
90        _modules_paths = eina_list_append(_modules_paths, paths[i]);
91 }
92
93 void
94 _edje_module_shutdown(void)
95 {
96    char *path;
97
98    if (_registered_modules)
99      {
100        eina_hash_free(_registered_modules);
101        _registered_modules = NULL;
102      }
103
104    EINA_LIST_FREE(_modules_paths, path)
105      free(path);
106
107    EINA_LIST_FREE(_modules_found, path)
108      eina_stringshare_del(path);
109 }
110
111 EAPI const Eina_List *
112 edje_available_modules_get(void)
113 {
114    Eina_File_Direct_Info *info;
115    Eina_Iterator *it;
116    Eina_List *l;
117    const char *path;
118    Eina_List *result = NULL;
119
120    /* FIXME: Stat each possible dir and check if they did change, before starting a huge round of readdir/stat */
121    if (_modules_found)
122      {
123         EINA_LIST_FREE(_modules_found, path)
124           eina_stringshare_del(path);
125      }
126
127    EINA_LIST_FOREACH(_modules_paths, l, path)
128      {
129         it = eina_file_direct_ls(path);
130
131         if (it)
132           {
133              EINA_ITERATOR_FOREACH(it, info)
134                {
135                   char tmp[PATH_MAX];
136
137                   snprintf(tmp, sizeof (tmp), "%s/%s/" EDJE_MODULE_NAME, info->path, MODULE_ARCH
138 #ifdef EDJE_EXTRA_MODULE_NAME
139                            , info->path + info->name_start
140 #endif
141                            );
142
143                   if (ecore_file_exists(tmp))
144                     result = eina_list_append(result, eina_stringshare_add(info->path + info->name_start));
145                }
146
147              eina_iterator_free(it);
148           }
149      }
150
151    _modules_found = result;
152
153    return result;
154 }