efreet: Improve language reset
[framework/uifw/efreet.git] / src / lib / efreet_base.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #undef alloca
6 #ifdef HAVE_ALLOCA_H
7 # include <alloca.h>
8 #elif defined __GNUC__
9 # define alloca __builtin_alloca
10 #elif defined _AIX
11 # define alloca __alloca
12 #elif defined _MSC_VER
13 # include <malloc.h>
14 # define alloca _alloca
15 #else
16 # include <stddef.h>
17 # ifdef  __cplusplus
18 extern "C"
19 # endif
20 void *alloca (size_t);
21 #endif
22
23 #include <unistd.h>
24
25 /* define macros and variable for using the eina logging system  */
26 #define EFREET_MODULE_LOG_DOM _efreet_base_log_dom
27 static int _efreet_base_log_dom = -1;
28
29 #include "Efreet.h"
30 #include "efreet_private.h"
31
32 static Efreet_Version _version = { VMAJ, VMIN, VMIC, VREV };
33 EAPI Efreet_Version *efreet_version = &_version;
34
35 #ifdef _WIN32
36 # define EFREET_PATH_SEP ';'
37 #else
38 # define EFREET_PATH_SEP ':'
39 #endif
40
41 static const char *efreet_home_dir = NULL;
42 static const char *xdg_data_home = NULL;
43 static const char *xdg_config_home = NULL;
44 static const char *xdg_cache_home = NULL;
45 static Eina_List  *xdg_data_dirs = NULL;
46 static Eina_List  *xdg_config_dirs = NULL;
47 static const char *xdg_desktop_dir = NULL;
48 static const char *hostname = NULL;
49
50 static const char *efreet_dir_get(const char *key, const char *fallback);
51 static Eina_List  *efreet_dirs_get(const char *key,
52                                         const char *fallback);
53
54 /**
55  * @internal
56  * @return Returns @c 1 on success or @c 0 on failure
57  * @brief Initializes the efreet base settings
58  */
59 int
60 efreet_base_init(void)
61 {
62     _efreet_base_log_dom = eina_log_domain_register
63       ("efreet_base", EFREET_DEFAULT_LOG_COLOR);
64     if (_efreet_base_log_dom < 0)
65     {
66         EINA_LOG_ERR("Efreet: Could not create a log domain for efreet_base.\n");
67         return 0;
68     }
69     return 1;
70 }
71
72 /**
73  * @internal
74  * @return Returns no value
75  * @brief Cleans up the efreet base settings system
76  */
77 void
78 efreet_base_shutdown(void)
79 {
80     IF_RELEASE(efreet_home_dir);
81     IF_RELEASE(xdg_desktop_dir);
82     IF_RELEASE(xdg_data_home);
83     IF_RELEASE(xdg_config_home);
84     IF_RELEASE(xdg_cache_home);
85
86     IF_FREE_LIST(xdg_data_dirs, eina_stringshare_del);
87     IF_FREE_LIST(xdg_config_dirs, eina_stringshare_del);
88
89     IF_RELEASE(hostname);
90
91     eina_log_domain_unregister(_efreet_base_log_dom);
92     _efreet_base_log_dom = -1;
93 }
94
95 /**
96  * @internal
97  * @return Returns the users home directory
98  * @brief Gets the users home directory and returns it.
99  */
100 const char *
101 efreet_home_dir_get(void)
102 {
103     if (efreet_home_dir) return efreet_home_dir;
104
105     efreet_home_dir = getenv("HOME");
106 #ifdef _WIN32
107     if (!efreet_home_dir || efreet_home_dir[0] == '\0')
108         efreet_home_dir = getenv("USERPROFILE");
109 #endif
110     if (!efreet_home_dir || efreet_home_dir[0] == '\0')
111         efreet_home_dir = "/tmp";
112
113     efreet_home_dir = eina_stringshare_add(efreet_home_dir);
114
115     return efreet_home_dir;
116 }
117
118 EAPI const char *
119 efreet_desktop_dir_get(void)
120 {
121     if (xdg_desktop_dir) return xdg_desktop_dir;
122     xdg_desktop_dir = efreet_dir_get("XDG_DESKTOP_DIR", _("/Desktop"));
123     return xdg_desktop_dir;
124 }
125
126 EAPI const char *
127 efreet_data_home_get(void)
128 {
129     if (xdg_data_home) return xdg_data_home;
130     xdg_data_home = efreet_dir_get("XDG_DATA_HOME", "/.local/share");
131     return xdg_data_home;
132 }
133
134 EAPI Eina_List *
135 efreet_data_dirs_get(void)
136 {
137 #ifdef _WIN32
138     char buf[4096];
139 #endif
140
141     if (xdg_data_dirs) return xdg_data_dirs;
142
143 #ifdef _WIN32
144     snprintf(buf, 4096, "%s\\Efl;" PACKAGE_DATA_DIR ";/usr/share;/usr/local/share", getenv("APPDATA"));
145     xdg_data_dirs = efreet_dirs_get("XDG_DATA_DIRS", buf);
146 #else
147     xdg_data_dirs = efreet_dirs_get("XDG_DATA_DIRS",
148                             PACKAGE_DATA_DIR ":/usr/share:/usr/local/share");
149 #endif
150     return xdg_data_dirs;
151 }
152
153 EAPI const char *
154 efreet_config_home_get(void)
155 {
156     if (xdg_config_home) return xdg_config_home;
157     xdg_config_home = efreet_dir_get("XDG_CONFIG_HOME", "/.config");
158     return xdg_config_home;
159 }
160
161 EAPI Eina_List *
162 efreet_config_dirs_get(void)
163 {
164     if (xdg_config_dirs) return xdg_config_dirs;
165     xdg_config_dirs = efreet_dirs_get("XDG_CONFIG_DIRS", "/etc/xdg");
166     return xdg_config_dirs;
167 }
168
169 EAPI const char *
170 efreet_cache_home_get(void)
171 {
172     if (xdg_cache_home) return xdg_cache_home;
173     xdg_cache_home = efreet_dir_get("XDG_CACHE_HOME", "/.cache");
174     return xdg_cache_home;
175 }
176
177 EAPI const char *
178 efreet_hostname_get(void)
179 {
180     char buf[256];
181
182     if (hostname) return hostname;
183     if (gethostname(buf, sizeof(buf)) < 0)
184         hostname = eina_stringshare_add("");
185     else
186         hostname = eina_stringshare_add(buf);
187     return hostname;
188 }
189
190 void
191 efreet_dirs_reset(void)
192 {
193     eina_stringshare_replace(&xdg_desktop_dir, NULL);
194 }
195
196 /**
197  * @internal
198  * @param key The environment key to lookup
199  * @param fallback The fallback value to use
200  * @return Returns the directory related to the given key or the fallback
201  * @brief This tries to determine the correct directory name given the
202  * environment key @a key and fallbacks @a fallback.
203  */
204 static const char *
205 efreet_dir_get(const char *key, const char *fallback)
206 {
207     char *dir;
208     const char *t;
209
210     dir = getenv(key);
211     if (!dir || dir[0] == '\0')
212     {
213         int len;
214         const char *user;
215
216         user = efreet_home_dir_get();
217         len = strlen(user) + strlen(fallback) + 1;
218         dir = malloc(len);
219         if (!dir) return NULL;
220         snprintf(dir, len, "%s%s", user, fallback);
221
222         t = eina_stringshare_add(dir);
223         FREE(dir);
224     }
225     else t = eina_stringshare_add(dir);
226
227     return t;
228 }
229
230 /**
231  * @internal
232  * @param key The environment key to lookup
233  * @param fallback The fallback value to use
234  * @return Returns a list of directories specified by the given key @a key
235  * or from the list of fallbacks in @a fallback.
236  * @brief Creates a list of directories as given in the environment key @a
237  * key or from the fallbacks in @a fallback
238  */
239 static Eina_List *
240 efreet_dirs_get(const char *key, const char *fallback)
241 {
242     Eina_List *dirs = NULL;
243     const char *path;
244     char *tmp, *s, *p;
245     char ts[PATH_MAX];
246     size_t len;
247
248     path = getenv(key);
249     if (!path || (path[0] == '\0')) path = fallback;
250
251     if (!path) return dirs;
252
253     len = strlen(path) + 1;
254     tmp = alloca(len);
255     memcpy(tmp, path, len);
256     s = tmp;
257     p = strchr(s, EFREET_PATH_SEP);
258     while (p)
259     {
260         *p = '\0';
261         if (!eina_list_search_unsorted(dirs, EINA_COMPARE_CB(strcmp), s))
262         {
263             // resolve path properly/fully to remove path//path2 to
264             // path/path2, path/./path2 to path/path2 etc.
265             if (realpath(s, ts))
266                 dirs = eina_list_append(dirs, (void *)eina_stringshare_add(ts));
267         }
268
269         s = ++p;
270         p = strchr(s, EFREET_PATH_SEP);
271     }
272     if (!eina_list_search_unsorted(dirs, EINA_COMPARE_CB(strcmp), s))
273     {
274         // resolve path properly/fully to remove path//path2 to
275         // path/path2, path/./path2 to path/path2 etc.
276         if (realpath(s, ts))
277             dirs = eina_list_append(dirs, (void *)eina_stringshare_add(ts));
278     }
279
280     return dirs;
281 }