b5128b948918300c49e8175262cb30466c40ce38
[framework/uifw/e17.git] / src / bin / e_utils.c
1 #include "e.h"
2
3 EAPI E_Path *path_data = NULL;
4 EAPI E_Path *path_images = NULL;
5 EAPI E_Path *path_fonts = NULL;
6 EAPI E_Path *path_themes = NULL;
7 EAPI E_Path *path_icons = NULL;
8 EAPI E_Path *path_modules = NULL;
9 EAPI E_Path *path_backgrounds = NULL;
10 EAPI E_Path *path_messages = NULL;
11
12 typedef struct _E_Util_Fake_Mouse_Up_Info E_Util_Fake_Mouse_Up_Info;
13 typedef struct _E_Util_Image_Import_Settings E_Util_Image_Import_Settings;
14
15 struct _E_Util_Fake_Mouse_Up_Info
16 {
17    Evas *evas;
18    int button;
19 };
20
21 struct _E_Util_Image_Import_Settings
22 {
23    E_Dialog *dia;
24    struct
25      {
26         void (*func)(void *data, const char *path, Eina_Bool ok, Eina_Bool external, int quality, E_Image_Import_Mode mode);
27         void *data;
28      } cb;
29    const char *path;
30    int quality;
31    int external;
32    int mode;
33    Eina_Bool ok;
34 };
35
36 struct _E_Util_Image_Import_Handle
37 {
38    Ecore_Exe *exe;
39    Ecore_Event_Handler *handler;
40    struct
41      {
42         void (*func)(void *data, Eina_Bool ok, const char *image_path, const char *edje_path);
43         void *data;
44      } cb;
45    struct
46      {
47         const char *image, *edje, *temp;
48      } path;
49 };
50
51 /* local subsystem functions */
52 static Eina_Bool _e_util_cb_delayed_del(void *data);
53 static Eina_Bool _e_util_wakeup_cb(void *data);
54
55 static void _e_util_image_import_settings_do(void *data, E_Dialog *dia);
56 static void _e_util_image_import_settings_del(void *obj);
57
58 static Eina_Bool _e_util_image_import_exit(void *data, int type __UNUSED__, void *event);
59 static void _e_util_image_import_handle_free(E_Util_Image_Import_Handle *handle);
60 static Evas_Object *_e_util_icon_add(const char *path, Evas *evas, int size);
61
62 /* local subsystem globals */
63 static Ecore_Timer *_e_util_dummy_timer = NULL;
64
65 /* externally accessible functions */
66 EAPI void
67 e_util_wakeup(void)
68 {
69    if (_e_util_dummy_timer) return;
70    _e_util_dummy_timer = ecore_timer_add(0.0, _e_util_wakeup_cb, NULL);
71 }
72
73 EAPI void
74 e_util_env_set(const char *var, const char *val)
75 {
76    if (val)
77      {
78 #ifdef HAVE_SETENV
79         setenv(var, val, 1);
80 #else
81         char buf[8192];
82
83         snprintf(buf, sizeof(buf), "%s=%s", var, val);
84         if (getenv(var))
85           putenv(buf);
86         else
87           putenv(strdup(buf));
88 #endif
89      }
90    else
91      {
92 #ifdef HAVE_UNSETENV
93         unsetenv(var);
94 #else
95         if (getenv(var)) putenv(var);
96 #endif
97      }
98 }
99
100 EAPI E_Zone *
101 e_util_zone_current_get(E_Manager *man)
102 {
103    E_Container *con;
104
105    E_OBJECT_CHECK_RETURN(man, NULL);
106    E_OBJECT_TYPE_CHECK_RETURN(man, E_MANAGER_TYPE, NULL);
107    con = e_container_current_get(man);
108    if (con)
109      {
110         E_Zone *zone;
111
112         zone = e_zone_current_get(con);
113         return zone;
114      }
115    return NULL;
116 }
117
118 EAPI int
119 e_util_glob_match(const char *str, const char *glob)
120 {
121    if ((!str) || (!glob)) return 0;
122    if (glob[0] == 0)
123      {
124         if (str[0] == 0) return 1;
125         return 0;
126      }
127    if (!strcmp(glob, "*")) return 1;
128    if (!fnmatch(glob, str, 0)) return 1;
129    return 0;
130 }
131
132 EAPI int
133 e_util_glob_case_match(const char *str, const char *glob)
134 {
135    const char *p;
136    char *tstr, *tglob, *tp;
137
138    if (glob[0] == 0)
139      {
140         if (str[0] == 0) return 1;
141         return 0;
142      }
143    if (!strcmp(glob, "*")) return 1;
144    tstr = alloca(strlen(str) + 1);
145    for (tp = tstr, p = str; *p != 0; p++, tp++) *tp = tolower(*p);
146    *tp = 0;
147    tglob = alloca(strlen(glob) + 1);
148    for (tp = tglob, p = glob; *p != 0; p++, tp++) *tp = tolower(*p);
149    *tp = 0;
150    if (!fnmatch(tglob, tstr, 0)) return 1;
151    return 0;
152 }
153
154 EAPI E_Container *
155 e_util_container_number_get(int num)
156 {
157    Eina_List *l;
158    E_Manager *man;
159
160    EINA_LIST_FOREACH(e_manager_list(), l, man)
161      {
162         E_Container *con;
163
164         con = e_container_number_get(man, num);
165         if (con) return con;
166      }
167    return NULL;
168 }
169
170 EAPI E_Zone *
171 e_util_container_zone_number_get(int con_num, int zone_num)
172 {
173    E_Container *con;
174
175    con = e_util_container_number_get(con_num);
176    if (!con) return NULL;
177    return e_container_zone_number_get(con, zone_num);
178 }
179
180 EAPI E_Zone *
181 e_util_container_zone_id_get(int con_num, int id)
182 {
183    E_Container *con;
184
185    con = e_util_container_number_get(con_num);
186    if (!con) return NULL;
187    return e_container_zone_id_get(con, id);
188 }
189
190 EAPI int
191 e_util_head_exec(int head, const char *cmd)
192 {
193    char *penv_display;
194    char *p1, *p2;
195    char buf[PATH_MAX], buf2[32];
196    int ok = 0;
197    Ecore_Exe *exe;
198
199    penv_display = getenv("DISPLAY");
200    if (!penv_display) return 0;
201    penv_display = strdup(penv_display);
202    /* set env vars */
203    p1 = strrchr(penv_display, ':');
204    p2 = strrchr(penv_display, '.');
205    if ((p1) && (p2) && (p2 > p1)) /* "blah:x.y" */
206      {
207         /* yes it could overflow... but who will overflow DISPLAY eh? why? to
208          * "exploit" your own applications running as you?
209          */
210         strcpy(buf, penv_display);
211         buf[p2 - penv_display + 1] = 0;
212         snprintf(buf2, sizeof(buf2), "%i", head);
213         strcat(buf, buf2);
214      }
215    else if (p1) /* "blah:x */
216      {
217         strcpy(buf, penv_display);
218         snprintf(buf2, sizeof(buf2), ".%i", head);
219         strcat(buf, buf2);
220      }
221    else
222      strcpy(buf, penv_display);
223
224    ok = 1;
225    e_util_library_path_strip();
226    exe = ecore_exe_run(cmd, NULL);
227    e_util_library_path_restore();
228    if (!exe)
229      {
230         e_util_dialog_show(_("Run Error"),
231                            _("Enlightenment was unable to fork a child process:<br>"
232                              "<br>"
233                              "%s<br>"),
234                            cmd);
235         ok = 0;
236      }
237
238    /* reset env vars */
239    if (penv_display)
240      {
241         e_util_env_set("DISPLAY", penv_display);
242         free(penv_display);
243      }
244    return ok;
245 }
246
247 EAPI int
248 e_util_strcmp(const char *s1, const char *s2)
249 {
250    if ((s1) && (s2))
251      return strcmp(s1, s2);
252    return 0x7fffffff;
253 }
254
255 EAPI int
256 e_util_both_str_empty(const char *s1, const char *s2)
257 {
258    int empty = 0;
259
260    if ((!s1) && (!s2)) return 1;
261    if ((!s1) || ((s1) && (s1[0] == 0))) empty++;
262    if ((!s2) || ((s2) && (s2[0] == 0))) empty++;
263    if (empty == 2) return 1;
264    return 0;
265 }
266
267 EAPI int
268 e_util_immortal_check(void)
269 {
270    Eina_List *wins;
271
272    wins = e_border_immortal_windows_get();
273    if (wins)
274      {
275         e_util_dialog_show(_("Cannot exit - immortal windows."),
276                            _("Some windows are left still around with the Lifespan lock enabled. This means<br>"
277                              "that Enlightenment will not allow itself to exit until these windows have<br>"
278                              "been closed or have the lifespan lock removed.<br>"));
279         /* FIXME: should really display a list of these lifespan locked */
280         /* windows in a dialog and let the user disable their locks in */
281         /* this dialog */
282         eina_list_free(wins);
283         return 1;
284      }
285    return 0;
286 }
287
288 EAPI int
289 e_util_edje_icon_list_check(const char *list)
290 {
291    char *buf;
292    const char *p;
293    const char *c;
294
295    if ((!list) || (!list[0])) return 0;
296    buf = alloca(strlen(list) + 1);
297    p = list;
298    while (p)
299      {
300         c = strchr(p, ',');
301         if (c)
302           {
303              strncpy(buf, p, c - p);
304              buf[c - p] = 0;
305              if (e_util_edje_icon_check(buf)) return 1;
306              p = c + 1;
307              if (!*p) return 0;
308           }
309         else
310           {
311              strcpy(buf, p);
312              if (e_util_edje_icon_check(buf)) return 1;
313              return 0;
314           }
315      }
316    return 0;
317 }
318
319 EAPI int
320 e_util_edje_icon_list_set(Evas_Object *obj, const char *list)
321 {
322    char *buf;
323    const char *p;
324    const char *c;
325
326    if ((!list) || (!list[0])) return 0;
327    buf = alloca(strlen(list) + 1);
328    p = list;
329    while (p)
330      {
331         c = strchr(p, ',');
332         if (c)
333           {
334              strncpy(buf, p, c - p);
335              buf[c - p] = 0;
336              if (e_util_edje_icon_set(obj, buf)) return 1;
337              p = c + 1;
338              if (!*p) return 0;
339           }
340         else
341           {
342              strcpy(buf, p);
343              if (e_util_edje_icon_set(obj, buf)) return 1;
344              return 0;
345           }
346      }
347    return 0;
348 }
349
350 EAPI int
351 e_util_menu_item_edje_icon_list_set(E_Menu_Item *mi, const char *list)
352 {
353    char *buf;
354    const char *p;
355    char *c;
356
357    if ((!list) || (!list[0])) return 0;
358    buf = alloca(strlen(list) + 1);
359    p = list;
360    while (p)
361      {
362         c = strchr(p, ',');
363         if (c)
364           {
365              strncpy(buf, p, c - p);
366              buf[c - p] = 0;
367              if (e_util_menu_item_theme_icon_set(mi, buf)) return 1;
368              p = c + 1;
369              if (!*p) return 0;
370           }
371         else
372           {
373              strcpy(buf, p);
374              if (e_util_menu_item_theme_icon_set(mi, buf)) return 1;
375              return 0;
376           }
377      }
378    return 0;
379 }
380
381 EAPI int
382 e_util_edje_icon_check(const char *name)
383 {
384    const char *file;
385    char buf[PATH_MAX];
386
387    if ((!name) || (!name[0])) return 0;
388    snprintf(buf, sizeof(buf), "e/icons/%s", name);
389    file = e_theme_edje_file_get("base/theme/icons", buf);
390    if (file[0]) return 1;
391    return 0;
392 }
393
394
395 /* WARNING This function is deprecated,. must be made static.
396  * You should use e_util_icon_theme_set instead
397  */
398 EAPI int
399 e_util_edje_icon_set(Evas_Object *obj, const char *name)
400 {
401    const char *file;
402    char buf[PATH_MAX];
403
404    if ((!name) || (!name[0])) return 0;
405    snprintf(buf, sizeof(buf), "e/icons/%s", name);
406    file = e_theme_edje_file_get("base/theme/icons", buf);
407    if (file[0])
408      {
409         edje_object_file_set(obj, file, buf);
410         return 1;
411      }
412    return 0;
413 }
414
415 static int
416 _e_util_icon_theme_set(Evas_Object *obj, const char *icon, Eina_Bool fallback)
417 {
418    const char *file;
419    char buf[PATH_MAX];
420
421    if ((!icon) || (!icon[0])) return 0;
422    snprintf(buf, sizeof(buf), "e/icons/%s", icon);
423
424    if (fallback)
425      file = e_theme_edje_icon_fallback_file_get(buf);
426    else
427      file = e_theme_edje_file_get("base/theme/icons", buf);
428
429    if (file[0])
430      {
431         e_icon_file_edje_set(obj, file, buf);
432         return 1;
433      }
434
435    return 0;
436 }
437
438 static int
439 _e_util_icon_fdo_set(Evas_Object *obj, const char *icon)
440 {
441    const char *path = NULL;
442    unsigned int size;
443    
444    if ((!icon) || (!icon[0])) return 0;
445    size = e_icon_scale_size_get(obj);
446    if (size < 16) size = 16;
447    size = e_util_icon_size_normalize(size * e_scale);
448
449    path = efreet_icon_path_find(e_config->icon_theme, icon, size);
450    if (!path) return 0;
451
452    e_icon_file_set(obj, path);
453    return 1;
454 }
455
456 /* use e_icon_size_scale_set(obj, size) to set the preferred icon size */
457 EAPI int
458 e_util_icon_theme_set(Evas_Object *obj, const char *icon)
459 {
460    if (e_config->icon_theme_overrides)
461      {
462         if (_e_util_icon_fdo_set(obj, icon))
463           return 1;
464         if (_e_util_icon_theme_set(obj, icon, EINA_FALSE))
465           return 1;
466         return _e_util_icon_theme_set(obj, icon, EINA_TRUE);
467      }
468    else
469      {
470         if (_e_util_icon_theme_set(obj, icon, EINA_FALSE))
471           return 1;
472         if (_e_util_icon_fdo_set(obj, icon))
473           return 1;
474         return _e_util_icon_theme_set(obj, icon, EINA_TRUE);
475      }
476 }
477
478 int
479 _e_util_menu_item_edje_icon_set(E_Menu_Item *mi, const char *name, Eina_Bool fallback)
480 {
481    const char *file;
482    char buf[PATH_MAX];
483
484    if ((!name) || (!name[0])) return 0;
485
486    if ((!fallback) && (name[0]=='/') && ecore_file_exists(name))
487      {
488         e_menu_item_icon_edje_set(mi, name, "icon");
489         return 1;
490      }
491    snprintf(buf, sizeof(buf), "e/icons/%s", name);
492
493    if (fallback)
494      file = e_theme_edje_icon_fallback_file_get(buf);
495    else
496      file = e_theme_edje_file_get("base/theme/icons", buf);
497
498    if (file[0])
499      {
500         e_menu_item_icon_edje_set(mi, file, buf);
501         return 1;
502      }
503    return 0;
504 }
505
506 EAPI unsigned int
507 e_util_icon_size_normalize(unsigned int desired)
508 {
509    const unsigned int *itr, known_sizes[] =
510      {
511         16, 22, 24, 32, 36, 48, 64, 72, 96, 128, 192, 256, -1
512      };
513
514    for (itr = known_sizes; *itr > 0; itr++)
515      if (*itr >= desired)
516        return *itr;
517
518    return 256; /* largest know size? */
519 }
520
521 static int
522 _e_util_menu_item_fdo_icon_set(E_Menu_Item *mi, const char *icon)
523 {
524    const char *path = NULL;
525    unsigned int size;
526
527    if ((!icon) || (!icon[0])) return 0;
528    size = e_util_icon_size_normalize(24 * e_scale);
529    path = efreet_icon_path_find(e_config->icon_theme, icon, size);
530    if (!path) return 0;
531    e_menu_item_icon_file_set(mi, path);
532    return 1;
533 }
534
535 EAPI int
536 e_util_menu_item_theme_icon_set(E_Menu_Item *mi, const char *icon)
537 {
538    if (e_config->icon_theme_overrides)
539      {
540         if (_e_util_menu_item_fdo_icon_set(mi, icon))
541           return 1;
542         if (_e_util_menu_item_edje_icon_set(mi, icon, EINA_FALSE))
543           return 1;
544         return _e_util_menu_item_edje_icon_set(mi, icon, EINA_TRUE);
545      }
546    else
547      {
548         if (_e_util_menu_item_edje_icon_set(mi, icon, EINA_FALSE))
549           return 1;
550         if (_e_util_menu_item_fdo_icon_set(mi, icon))
551           return 1;
552         return _e_util_menu_item_edje_icon_set(mi, icon, EINA_TRUE);
553      }
554 }
555
556 EAPI E_Container *
557 e_util_container_window_find(Ecore_X_Window win)
558 {
559    Eina_List *l, *ll;
560    E_Manager *man;
561    E_Container *con;
562
563    EINA_LIST_FOREACH(e_manager_list(), l, man)
564      {
565         EINA_LIST_FOREACH(man->containers, ll, con)
566           {
567              if ((con->win == win) || (con->bg_win == win) ||
568                  (con->event_win == win))
569                return con;
570           }
571      }
572    return NULL;
573 }
574
575 EAPI E_Zone *
576 e_util_zone_window_find(Ecore_X_Window win)
577 {
578    Eina_List *l, *ll, *lll;
579    E_Manager *man;
580    E_Container *con;
581    E_Zone *zone;
582
583    EINA_LIST_FOREACH(e_manager_list(), l, man)
584      EINA_LIST_FOREACH(man->containers, ll, con)
585        EINA_LIST_FOREACH(con->zones, lll, zone)
586          if (zone->black_win == win) return zone;
587
588    return NULL;
589 }
590
591 EAPI E_Border *
592 e_util_desk_border_above(E_Border *bd)
593 {
594    E_Border *bd2, *above = NULL;
595    Eina_List *l;
596    int pos, i;
597
598    E_OBJECT_CHECK_RETURN(bd, NULL);
599    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
600
601    if (bd->layer == 0) pos = 0;
602    else if ((bd->layer > 0) && (bd->layer <= 50)) pos = 1;
603    else if ((bd->layer > 50) && (bd->layer <= 100)) pos = 2;
604    else if ((bd->layer > 100) && (bd->layer <= 150)) pos = 3;
605    else if ((bd->layer > 150) && (bd->layer <= 200)) pos = 4;
606    else pos = 5;
607
608    EINA_LIST_FOREACH(eina_list_data_find_list(bd->zone->container->layers[pos].clients, bd), l, bd2)
609      {
610         if(!eina_list_next(l) || above) break;
611         above = eina_list_data_get(eina_list_next(l));
612         if ((above->desk != bd->desk) && (!above->sticky))
613           above = NULL;
614      }
615    if (!above)
616      {
617         /* Need to check the layers above */
618         for (i = pos + 1; (i < 7) && (!above); i++)
619           {
620              EINA_LIST_FOREACH(bd->zone->container->layers[i].clients, l, bd2)
621                {
622                   if (above) break;
623                   above = bd2;
624                   if ((above->desk != bd->desk) && (!above->sticky))
625                     above = NULL;
626                }
627           }
628      }
629    return above;
630 }
631
632 EAPI E_Border *
633 e_util_desk_border_below(E_Border *bd)
634 {
635    E_Border *below = NULL, *bd2;
636    Eina_List *l;
637    int pos, i;
638
639    E_OBJECT_CHECK_RETURN(bd, NULL);
640    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
641
642    if (bd->layer == 0) pos = 0;
643    else if ((bd->layer > 0) && (bd->layer <= 50)) pos = 1;
644    else if ((bd->layer > 50) && (bd->layer <= 100)) pos = 2;
645    else if ((bd->layer > 100) && (bd->layer <= 150)) pos = 3;
646    else if ((bd->layer > 150) && (bd->layer <= 200)) pos = 4;
647    else pos = 5;
648
649    for (l = eina_list_data_find_list(bd->zone->container->layers[pos].clients, bd); l; l = l->prev)
650      {
651         if (!eina_list_prev(l) || below) break;
652         below = eina_list_data_get(eina_list_prev(l));
653         if ((below->desk != bd->desk) && (!below->sticky))
654           below = NULL;
655      }
656    if (!below)
657      {
658         /* Need to check the layers below */
659         for (i = pos - 1; (i >= 0) && (!below); i--)
660           {
661              if (bd->zone->container->layers[i].clients)
662                {
663                   l = eina_list_data_find_list(bd->zone->container->layers[pos].clients, bd);
664                   for (; l && !below; l = l->prev)
665                     {
666                        bd2 = l->data;
667                        below = bd2;
668                        if ((below->desk != bd->desk) && (!below->sticky))
669                          below = NULL;
670                     }
671                }
672           }
673      }
674
675    return below;
676 }
677
678 EAPI int
679 e_util_edje_collection_exists(const char *file, const char *coll)
680 {
681    Eina_List *clist, *l;
682    char *str;
683
684    clist = edje_file_collection_list(file);
685    EINA_LIST_FOREACH(clist, l, str)
686      {
687         if (!strcmp(coll, str))
688           {
689              edje_file_collection_list_free(clist);
690              return 1;
691           }
692      }
693    edje_file_collection_list_free(clist);
694    return 0;
695 }
696
697 EAPI void
698 e_util_dialog_internal(const char *title, const char *txt)
699 {
700    E_Dialog *dia;
701
702    dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_error_dialog");
703    if (!dia) return;
704    e_dialog_title_set(dia, title);
705    e_dialog_text_set(dia, txt);
706    e_dialog_icon_set(dia, "dialog-error", 64);
707    e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
708    e_dialog_button_focus_num(dia, 0);
709    e_win_centered_set(dia->win, 1);
710    e_dialog_show(dia);
711 }
712
713 EAPI const char *
714 e_util_filename_escape(const char *filename)
715 {
716    const char *p;
717    char *q;
718    static char buf[PATH_MAX];
719
720    if (!filename) return NULL;
721    p = filename;
722    q = buf;
723    while (*p)
724      {
725         if ((q - buf) > 4090) return NULL;
726         if (
727             (*p == ' ') || (*p == '\t') || (*p == '\n') ||
728             (*p == '\\') || (*p == '\'') || (*p == '\"') ||
729             (*p == ';') || (*p == '!') || (*p == '#') ||
730             (*p == '$') || (*p == '%') || (*p == '&') ||
731             (*p == '*') || (*p == '(') || (*p == ')') ||
732             (*p == '[') || (*p == ']') || (*p == '{') ||
733             (*p == '}') || (*p == '|') || (*p == '<') ||
734             (*p == '>') || (*p == '?')
735             )
736           {
737              *q = '\\';
738              q++;
739           }
740         *q = *p;
741         q++;
742         p++;
743      }
744    *q = 0;
745    return buf;
746 }
747
748 EAPI int
749 e_util_icon_save(Ecore_X_Icon *icon, const char *filename)
750 {
751    Ecore_Evas *ee;
752    Evas *evas;
753    Evas_Object *im;
754    int ret;
755
756    ee = ecore_evas_buffer_new(icon->width, icon->height);
757    if (!ee) return 0;
758    evas = ecore_evas_get(ee);
759    evas_image_cache_set(evas, 0);
760    evas_font_cache_set(evas, 0);
761
762    im = evas_object_image_add(evas);
763    if (!im)
764      {
765         ecore_evas_free(ee);
766         return 0;
767      }
768    evas_object_move(im, 0, 0);
769    evas_object_resize(im, icon->width, icon->height);
770    evas_object_image_size_set(im, icon->width, icon->height);
771    evas_object_image_data_copy_set(im, icon->data);
772    evas_object_image_alpha_set(im, 1);
773    evas_object_show(im);
774    ret = evas_object_image_save(im, filename, NULL, NULL);
775    evas_object_del(im);
776    ecore_evas_free(ee);
777    return ret;
778 }
779
780 EAPI char *
781 e_util_shell_env_path_eval(const char *path)
782 {
783    /* evaluate things like:
784     * $HOME/bling -> /home/user/bling
785     * $HOME/bin/$HOSTNAME/blah -> /home/user/bin/localhost/blah
786     * etc. etc.
787     */
788    const char *p, *v2, *v1 = NULL;
789    char buf[PATH_MAX], *pd, *s, *vp;
790    char *v = NULL;
791    int esc = 0, invar = 0;
792
793    for (p = path, pd = buf; (pd < (buf + sizeof(buf) - 1)); p++)
794      {
795         if (invar)
796           {
797              if (!((isalnum(*p)) || (*p == '_')))
798                {
799                   v2 = p;
800                   invar = 0;
801                   if ((v2 - v1) > 1)
802                     {
803                        s = alloca(v2 - v1);
804                        strncpy(s, v1 + 1, v2 - v1 - 1);
805                        s[v2 - v1 - 1] = 0;
806                        if (strncmp(s, "XDG", 3))
807                          v = getenv(s);
808                        else
809                          {
810                             if (!strcmp(s, "XDG_CONFIG_HOME"))
811                               v = (char *)efreet_config_home_get();
812                             else if (!strcmp(s, "XDG_CACHE_HOME"))
813                               v = (char *)efreet_cache_home_get();
814                             else if (!strcmp(s, "XDG_DATA_HOME"))
815                               v = (char *)efreet_data_home_get();
816                          }
817
818                        if (v)
819                          {
820                             vp = v;
821                             while ((*vp) && (pd < (buf + sizeof(buf) - 1)))
822                               {
823                                  *pd = *vp;
824                                  vp++;
825                                  pd++;
826                               }
827                          }
828                     }
829                   if (pd < (buf + sizeof(buf) - 1))
830                     {
831                        *pd = *p;
832                        pd++;
833                     }
834                }
835           }
836         else
837           {
838              if (esc)
839                {
840                   *pd = *p;
841                   pd++;
842                }
843              else
844                {
845                   if (*p == '\\') esc = 1;
846                   else if (*p == '$')
847                     {
848                        invar = 1;
849                        v1 = p;
850                     }
851                   else
852                     {
853                        *pd = *p;
854                        pd++;
855                     }
856                }
857           }
858         if (*p == 0) break;
859      }
860    *pd = 0;
861    return strdup(buf);
862 }
863
864 EAPI char *
865 e_util_size_string_get(off_t size)
866 {
867    double dsize;
868    char buf[256];
869
870    dsize = (double)size;
871    if (dsize < 1024.0) snprintf(buf, sizeof(buf), _("%'.0f Bytes"), dsize);
872    else
873      {
874         dsize /= 1024.0;
875         if (dsize < 1024) snprintf(buf, sizeof(buf), _("%'.0f KB"), dsize);
876         else
877           {
878              dsize /= 1024.0;
879              if (dsize < 1024) snprintf(buf, sizeof(buf), _("%'.0f MB"), dsize);
880              else
881                {
882                   dsize /= 1024.0;
883                   snprintf(buf, sizeof(buf), _("%'.1f GB"), dsize);
884                }
885           }
886      }
887    return strdup(buf);
888 }
889
890 EAPI char *
891 e_util_file_time_get(time_t ftime)
892 {
893    time_t diff;
894    time_t ltime;
895    char buf[256];
896    char *s = NULL;
897
898    ltime = time(NULL);
899    diff = ltime - ftime;
900    buf[0] = 0;
901    if (ftime > ltime)
902      snprintf(buf, sizeof(buf), _("In the Future"));
903    else
904      {
905         if (diff <= 60)
906           snprintf(buf, sizeof(buf), _("In the last Minute"));
907         else if (diff >= 31526000)
908           snprintf(buf, sizeof(buf), _("%li Years ago"), (diff / 31526000));
909         else if (diff >= 2592000)
910           snprintf(buf, sizeof(buf), _("%li Months ago"), (diff / 2592000));
911         else if (diff >= 604800)
912           snprintf(buf, sizeof(buf), _("%li Weeks ago"), (diff / 604800));
913         else if (diff >= 86400)
914           snprintf(buf, sizeof(buf), _("%li Days ago"), (diff / 86400));
915         else if (diff >= 3600)
916           snprintf(buf, sizeof(buf), _("%li Hours ago"), (diff / 3600));
917         else if (diff > 60)
918           snprintf(buf, sizeof(buf), _("%li Minutes ago"), (diff / 60));
919      }
920
921    if (buf[0])
922      s = strdup(buf);
923    else
924      s = strdup(_("Unknown"));
925    return s;
926 }
927
928 static char *prev_ld_library_path = NULL;
929 static char *prev_path = NULL;
930
931 EAPI void
932 e_util_library_path_strip(void)
933 {
934    char *p, *p2;
935
936    p = getenv("LD_LIBRARY_PATH");
937    E_FREE(prev_ld_library_path);
938    if (p)
939      {
940         prev_ld_library_path = strdup(p);
941         p2 = strchr(p, ':');
942         if (p2) p2++;
943         e_util_env_set("LD_LIBRARY_PATH", p2);
944      }
945    p = getenv("PATH");
946    E_FREE(prev_path);
947    if (p)
948      {
949         prev_path = strdup(p);
950         p2 = strchr(p, ':');
951         if (p2) p2++;
952         e_util_env_set("PATH", p2);
953      }
954 }
955
956 EAPI void
957 e_util_library_path_restore(void)
958 {
959    if (prev_ld_library_path)
960      {
961         e_util_env_set("LD_LIBRARY_PATH", prev_ld_library_path);
962         E_FREE(prev_ld_library_path);
963      }
964    if (prev_path)
965      {
966         e_util_env_set("PATH", prev_path);
967         E_FREE(prev_path);
968      }
969 }
970
971 EAPI Evas_Object *
972 e_util_icon_add(const char *path, Evas *evas)
973 {
974    return _e_util_icon_add(path, evas, 64); 
975 }
976
977 EAPI Evas_Object *
978 e_util_desktop_icon_add(Efreet_Desktop *desktop, unsigned int size, Evas *evas)
979 {
980    if ((!desktop) || (!desktop->icon)) return NULL;
981    return e_util_icon_theme_icon_add(desktop->icon, size, evas);
982 }
983
984 EAPI Evas_Object *
985 e_util_icon_theme_icon_add(const char *icon_name, unsigned int size, Evas *evas)
986 {
987    if (!icon_name) return NULL;
988    if (icon_name[0] == '/') return _e_util_icon_add(icon_name, evas, size);
989    else
990      {
991         Evas_Object *obj;
992         const char *path;
993
994         path = efreet_icon_path_find(e_config->icon_theme, icon_name, size);
995         if (path)
996           {
997              obj = _e_util_icon_add(path, evas, size);
998              return obj;
999           }
1000      }
1001    return NULL;
1002 }
1003
1004 EAPI void
1005 e_util_desktop_menu_item_icon_add(Efreet_Desktop *desktop, unsigned int size, E_Menu_Item *mi)
1006 {
1007    const char *path = NULL;
1008
1009    if ((!desktop) || (!desktop->icon)) return;
1010
1011    if (desktop->icon[0] == '/') path = desktop->icon;
1012    else path = efreet_icon_path_find(e_config->icon_theme, desktop->icon, size);
1013
1014    if (path)
1015      {
1016         const char *ext;
1017
1018         ext = strrchr(path, '.');
1019         if (ext)
1020           {
1021              if (strcmp(ext, ".edj") == 0)
1022                e_menu_item_icon_edje_set(mi, path, "icon");
1023              else
1024                e_menu_item_icon_file_set(mi, path);
1025           }
1026         else
1027           e_menu_item_icon_file_set(mi, path);
1028      }
1029 }
1030
1031 EAPI int
1032 e_util_dir_check(const char *dir)
1033 {
1034    if (!ecore_file_exists(dir))
1035      {
1036         if (!ecore_file_mkpath(dir))
1037           {
1038              e_util_dialog_show("Error creating directory", "Failed to create directory: %s .<br>Check that you have correct permissions set.", dir);
1039              return 0;
1040           }
1041      }
1042    else
1043      {
1044         if (!ecore_file_is_dir(dir))
1045           {
1046              e_util_dialog_show("Error creating directory", "Failed to create directory: %s .<br>A file of that name already exists.", dir);
1047              return 0;
1048           }
1049      }
1050    return 1;
1051 }
1052
1053 EAPI void
1054 e_util_defer_object_del(E_Object *obj)
1055 {
1056    if (stopping)
1057      e_object_del(obj);
1058    else
1059      ecore_idle_enterer_before_add(_e_util_cb_delayed_del, obj);
1060 }
1061
1062 EAPI const char *
1063 e_util_winid_str_get(Ecore_X_Window win)
1064 {
1065    const char *vals = "qWeRtYuIoP5-$&<~";
1066    static char id[9];
1067    unsigned int val;
1068
1069    val = (unsigned int)win;
1070    id[0] = vals[(val >> 28) & 0xf];
1071    id[1] = vals[(val >> 24) & 0xf];
1072    id[2] = vals[(val >> 20) & 0xf];
1073    id[3] = vals[(val >> 16) & 0xf];
1074    id[4] = vals[(val >> 12) & 0xf];
1075    id[5] = vals[(val >>  8) & 0xf];
1076    id[6] = vals[(val >>  4) & 0xf];
1077    id[7] = vals[(val      ) & 0xf];
1078    id[8] = 0;
1079    return id;
1080 }
1081
1082 static int
1083 _win_auto_size_calc(int max, int min)
1084 {
1085    const float *itr, scales[] = {0.25, 0.3, 0.5, 0.75, 0.8, 0.9, 0.95, -1};
1086
1087    for (itr = scales; *itr > 0; itr++)
1088      {
1089         int value = *itr * max;
1090         if (value > min) /* not >=, try a bit larger */
1091           return value;
1092      }
1093
1094    return min;
1095 }
1096
1097 EAPI void
1098 e_util_win_auto_resize_fill(E_Win *win)
1099 {
1100    E_Zone *zone = NULL;
1101
1102    if (win->border)
1103      zone = win->border->zone;
1104    if ((!zone) && (win->container))
1105      zone = e_util_zone_current_get(win->container->manager);
1106
1107    if (zone)
1108      {
1109         int w, h;
1110
1111         e_zone_useful_geometry_get(zone, NULL, NULL, &w, &h);
1112
1113         w = _win_auto_size_calc(w, win->min_w);
1114         h = _win_auto_size_calc(h, win->min_h);
1115         e_win_resize(win, w, h);
1116      }
1117 }
1118
1119 /**
1120  * Creates a new dialog to query image import settings, report results.
1121  *
1122  * @param path may be used to display live preview (not used so far).
1123  * @param cb function to call before exit. Last parameter is mode of
1124  *        image filling.
1125  * @param data extra data to give to @a cb as first argument.
1126  *
1127  * @return newly allocated window on success, @c NULL on failure. If
1128  *         @c NULL is returned, then callback is never called!
1129  */
1130 EAPI E_Dialog *
1131 e_util_image_import_settings_new(const char *path, void (*cb)(void *data, const char *path, Eina_Bool ok, Eina_Bool external, int quality, E_Image_Import_Mode mode), const void *data)
1132 {
1133    Evas *evas;
1134    E_Util_Image_Import_Settings *ctxt;
1135    Evas_Object *vlist, *frame, *radio, *check, *slider;
1136    E_Radio_Group *rg;
1137    Evas_Coord w, h;
1138
1139    if (!path) return NULL;
1140    if (!cb) return NULL;
1141
1142    ctxt = E_NEW(E_Util_Image_Import_Settings, 1);
1143    if (!ctxt) return NULL;
1144
1145    ctxt->dia = e_dialog_new(NULL, "E", "_image_import_settings");
1146    if (!ctxt->dia)
1147      {
1148         E_FREE(ctxt);
1149         return NULL;
1150      }
1151
1152    ctxt->dia->data = ctxt;
1153
1154    e_object_del_attach_func_set
1155      (E_OBJECT(ctxt->dia), _e_util_image_import_settings_del);
1156    e_dialog_title_set(ctxt->dia, _("Image Import Settings"));
1157    e_dialog_border_icon_set(ctxt->dia, "dialog-ask");
1158
1159    e_dialog_button_add
1160      (ctxt->dia, _("Import"), NULL, _e_util_image_import_settings_do, ctxt);
1161    e_dialog_button_add
1162      (ctxt->dia, _("Cancel"), NULL, NULL, ctxt);
1163    e_dialog_button_focus_num(ctxt->dia, 0);
1164
1165    ctxt->cb.func = cb;
1166    ctxt->cb.data = (void *)data;
1167    ctxt->path = eina_stringshare_add(path);
1168    ctxt->quality = 90;
1169    ctxt->ok = EINA_FALSE;
1170    ctxt->external = EINA_FALSE;
1171    ctxt->mode = E_IMAGE_IMPORT_STRETCH;
1172
1173    evas = e_win_evas_get(ctxt->dia->win);
1174
1175    vlist = e_widget_list_add(evas, 0, 0);
1176
1177    frame = e_widget_frametable_add(evas, _("Fill and Stretch Options"), 1);
1178    rg = e_widget_radio_group_new(&ctxt->mode);
1179
1180 #define RD(lbl, icon, val, col, row)                                    \
1181    radio = e_widget_radio_icon_add                                      \
1182      (evas, lbl, "enlightenment/wallpaper_"icon, 24, 24, val, rg);      \
1183    e_widget_frametable_object_append(frame, radio, col, row, 1, 1, 1, 1, 0, 0)
1184
1185    RD(_("Stretch"), "stretch", E_IMAGE_IMPORT_STRETCH, 0, 0);
1186    RD(_("Center"), "center", E_IMAGE_IMPORT_CENTER, 1, 0);
1187    RD(_("Title"), "tile", E_IMAGE_IMPORT_TILE, 2, 0);
1188    RD(_("Within"), "scale_aspect_in", E_IMAGE_IMPORT_SCALE_ASPECT_IN, 3, 0);
1189    RD(_("Fill"), "scale_aspect_out", E_IMAGE_IMPORT_SCALE_ASPECT_OUT, 4, 0);
1190 #undef RD
1191
1192    e_widget_list_object_append(vlist, frame, 1, 1, 0.5);
1193
1194    frame = e_widget_frametable_add(evas, _("File Quality"), 0);
1195
1196    check = e_widget_check_add(evas, _("Use original file"), &ctxt->external);
1197    e_widget_frametable_object_append(frame, check, 0, 0, 1, 1, 1, 0, 1, 0);
1198
1199    slider = e_widget_slider_add
1200      (evas, 1, 0, _("%3.0f%%"), 0.0, 100.0, 1.0, 0, NULL, &ctxt->quality, 150);
1201    e_widget_frametable_object_append(frame, slider, 0, 1, 1, 1, 1, 0, 1, 0);
1202
1203    e_widget_list_object_append(vlist, frame, 1, 1, 0.5);
1204
1205    e_widget_size_min_get(vlist, &w, &h);
1206    w += 50;
1207    e_dialog_content_set(ctxt->dia, vlist, w, h);
1208
1209    e_win_centered_set(ctxt->dia->win, 1);
1210
1211    return ctxt->dia;
1212 }
1213
1214 /**
1215  * Request given image to be imported as an edje file.
1216  *
1217  * This is useful to convert images to icons and background.
1218  *
1219  * @param image_path path to source image to use.
1220  * @param edje_path path to destination edje to generate.
1221  * @param external if @c EINA_TRUE, then it will not embed image into edje,
1222  *        but reference the original @a image_path.
1223  * @param quality quality value from 0-100.
1224  * @param mode how to resize image with edje.
1225  * @param cb function to callback when process finishes.
1226  * @param data extra context to give to callback.
1227  *
1228  * @return handle so one can cancel the operation. This handle will be
1229  *         invalid after @a cb is called!
1230  */
1231 EAPI E_Util_Image_Import_Handle *
1232 e_util_image_import(const char *image_path, const char *edje_path, const char *edje_group, Eina_Bool external, int quality, E_Image_Import_Mode mode, void (*cb)(void *data, Eina_Bool ok, const char *image_path, const char *edje_path), const void *data)
1233 {
1234    static const char *tmpdir = NULL;
1235    E_Util_Image_Import_Handle *handle;
1236    Ecore_Evas *ee;
1237    Evas_Object *img;
1238    int fd, w, h;
1239    const char *escaped_file;
1240    char cmd[PATH_MAX * 2], tmpn[PATH_MAX];
1241    FILE *f;
1242
1243    if (!image_path) return NULL;
1244    if (!edje_path) return NULL;
1245    if (!edje_group) return NULL;
1246    if (!cb) return NULL;
1247    ee = ecore_evas_buffer_new(1, 1);
1248    img = evas_object_image_add(ecore_evas_get(ee));
1249    evas_object_image_file_set(img, image_path, NULL);
1250    if (evas_object_image_load_error_get(img) != EVAS_LOAD_ERROR_NONE)
1251      {
1252         ecore_evas_free(ee);
1253         printf("Error loading image '%s'\n", image_path);
1254         return NULL;
1255      }
1256    evas_object_image_size_get(img, &w, &h);
1257    ecore_evas_free(ee);
1258
1259    if (!tmpdir)
1260      {
1261         tmpdir = getenv("TMPDIR");
1262         if (!tmpdir) tmpdir = "/tmp";
1263      }
1264    snprintf(tmpn, sizeof(tmpn), "%s/e_util_image_import-XXXXXX", tmpdir);
1265    fd = mkstemp(tmpn);
1266    if (fd < 0)
1267      {
1268         printf("Error Creating tmp file: %s\n", strerror(errno));
1269         return NULL;
1270      }
1271
1272    f = fdopen(fd, "wb");
1273    if (!f)
1274      {
1275         printf("Cannot open %s for writing\n", tmpn);
1276         close(fd);
1277         return NULL;
1278      }
1279
1280    escaped_file = e_util_filename_escape(image_path); // watch out ret buffer!
1281
1282    fprintf(f, "images.image: \"%s\" ", escaped_file);
1283    if (external)
1284      fputs("USER", f);
1285    else if (quality >= 100)
1286      fputs("COMP", f);
1287    else
1288      fprintf(f, "LOSSY %d", (quality > 1) ? quality : 90);
1289
1290    fprintf(f,
1291            ";\n"
1292            "collections {\n"
1293            "   group {\n"
1294            "      name: \"%s\";\n"
1295            "      data.item: \"style\" \"%d\";\n"
1296            "      max: %d %d;\n"
1297            "      parts {\n",
1298            edje_group, mode, w, h);
1299
1300    if ((mode == E_IMAGE_IMPORT_CENTER) ||
1301        (mode == E_IMAGE_IMPORT_SCALE_ASPECT_IN))
1302      {
1303         fputs("         part {\n"
1304               "            type: RECT;\n"
1305               "            name: \"col\";\n"
1306               "            mouse_events: 0;\n"
1307               "            description {\n"
1308               "               state: \"default\" 0.0;\n"
1309               "               color: 255 255 255 255;\n"
1310               "            }\n"
1311               "         }\n",
1312               f);
1313      }
1314
1315    fprintf(f,
1316            "         part {\n"
1317            "            type: IMAGE;\n"
1318            "            name: \"image\";\n"
1319            "            mouse_events: 0;\n"
1320            "            description {\n"
1321            "               state: \"default\" 0.0;\n"
1322            "               image {\n"
1323            "                  normal: \"%s\";\n"
1324            "                  scale_hint: STATIC;\n"
1325            "               }\n",
1326            escaped_file);
1327
1328    if (mode == E_IMAGE_IMPORT_TILE)
1329      {
1330         fprintf(f,
1331                 "               fill {\n"
1332                 "                  size {\n"
1333                 "                     relative: 0.0 0.0;\n"
1334                 "                     offset: %d %d;\n"
1335                 "                  }\n"
1336                 "               }\n",
1337                 w, h);
1338      }
1339    else if (mode == E_IMAGE_IMPORT_CENTER)
1340      {
1341         fprintf(f,
1342                 "               min: %d %d;\n"
1343                 "               max: %d %d;\n",
1344                 w, h, w, h);
1345
1346      }
1347    else if ((mode == E_IMAGE_IMPORT_SCALE_ASPECT_IN) ||
1348             (mode == E_IMAGE_IMPORT_SCALE_ASPECT_OUT))
1349      {
1350         const char *locale = e_intl_language_get();
1351         double aspect = (double)w / (double)h;
1352         setlocale(LC_NUMERIC, "C");
1353         fprintf(f,
1354                 "               aspect: %1.9f %1.9f;\n"
1355                 "               aspect_preference: %s;\n",
1356                 aspect, aspect,
1357                 (mode == E_IMAGE_IMPORT_SCALE_ASPECT_IN) ? "BOTH" : "NONE");
1358         setlocale(LC_NUMERIC, locale);
1359      }
1360
1361    fputs("            }\n" // description
1362          "         }\n"    // part
1363          "      }\n"       // parts
1364          "   }\n"          // group
1365          "}\n",            // collections
1366          f);
1367
1368    fclose(f); // fd gets closed here
1369
1370    snprintf(cmd, sizeof(cmd), "edje_cc %s %s",
1371             tmpn, e_util_filename_escape(edje_path));
1372
1373    handle = E_NEW(E_Util_Image_Import_Handle, 1);
1374    if (!handle)
1375      {
1376         unlink(tmpn);
1377         return NULL;
1378      }
1379
1380    handle->cb.func = cb;
1381    handle->cb.data = (void *)data;
1382    handle->path.image = eina_stringshare_add(image_path);
1383    handle->path.edje = eina_stringshare_add(edje_path);
1384    handle->path.temp = eina_stringshare_add(tmpn);
1385    handle->handler = ecore_event_handler_add
1386      (ECORE_EXE_EVENT_DEL, _e_util_image_import_exit, handle);
1387    handle->exe = ecore_exe_run(cmd, NULL);
1388    if (!handle->exe)
1389      {
1390         _e_util_image_import_handle_free(handle);
1391         return NULL;
1392      }
1393
1394    return handle;
1395 }
1396
1397 EAPI void
1398 e_util_image_import_cancel(E_Util_Image_Import_Handle *handle)
1399 {
1400    if (!handle) return;
1401    ecore_exe_kill(handle->exe);
1402 }
1403
1404 EAPI int
1405 e_util_container_desk_count_get(E_Container *con)
1406 {
1407    Eina_List *zl;
1408    E_Zone *zone;
1409    int count = 0;
1410
1411    E_OBJECT_CHECK_RETURN(con, 0);
1412    E_OBJECT_TYPE_CHECK_RETURN(con, E_CONTAINER_TYPE, 0);
1413    EINA_LIST_FOREACH(con->zones, zl, zone)
1414      {
1415         int x, y;
1416         int cx = 0, cy = 0;
1417
1418         e_zone_desk_count_get(zone, &cx, &cy);
1419         for (x = 0; x < cx; x++)
1420           {
1421              for (y = 0; y < cy; y++)
1422                count += 1;
1423           }
1424      }
1425    return count;
1426 }
1427
1428 /* local subsystem functions */
1429
1430 static Evas_Object *
1431 _e_util_icon_add(const char *path, Evas *evas, int size)
1432 {
1433    Evas_Object *o = NULL;
1434    const char *ext;
1435
1436    if (!path) return NULL;
1437    if (!ecore_file_exists(path)) return NULL;
1438
1439    o = e_icon_add(evas);
1440    e_icon_scale_size_set(o, size); 
1441    e_icon_preload_set(o, 1);
1442    ext = strrchr(path, '.');
1443    if (ext)
1444      {
1445         if (!strcmp(ext, ".edj"))
1446           e_icon_file_edje_set(o, path, "icon");
1447         else
1448           e_icon_file_set(o, path);
1449      }
1450    else
1451      e_icon_file_set(o, path);
1452    e_icon_fill_inside_set(o, 1);
1453
1454    return o;
1455 }
1456
1457 static Eina_Bool
1458 _e_util_cb_delayed_del(void *data)
1459 {
1460    e_object_del(E_OBJECT(data));
1461    return ECORE_CALLBACK_CANCEL;
1462 }
1463
1464 static Eina_Bool
1465 _e_util_wakeup_cb(void *data __UNUSED__)
1466 {
1467    _e_util_dummy_timer = NULL;
1468    return ECORE_CALLBACK_CANCEL;
1469 }
1470
1471 static void
1472 _e_util_image_import_settings_do(void *data, E_Dialog *dia)
1473 {
1474    E_Util_Image_Import_Settings *ctxt = data;
1475
1476    ctxt->ok = EINA_TRUE;
1477    e_util_defer_object_del(E_OBJECT(dia));
1478 }
1479
1480 static void
1481 _e_util_image_import_settings_del(void *obj)
1482 {
1483    E_Dialog *dia = obj;
1484    E_Util_Image_Import_Settings *ctxt = dia->data;
1485
1486    ctxt->cb.func(ctxt->cb.data, ctxt->path,
1487                  ctxt->ok, ctxt->external, ctxt->quality, ctxt->mode);
1488
1489    eina_stringshare_del(ctxt->path);
1490    E_FREE(ctxt);
1491 }
1492
1493 static Eina_Bool
1494 _e_util_image_import_exit(void *data, int type __UNUSED__, void *event)
1495 {
1496    E_Util_Image_Import_Handle *handle = data;
1497    Ecore_Exe_Event_Del *ev = event;
1498    Eina_Bool ok;
1499
1500    if (ev->exe != handle->exe) return ECORE_CALLBACK_PASS_ON;
1501
1502    ok = (ev->exit_code == 0);
1503
1504    if (!ok) unlink(handle->path.edje);
1505    handle->cb.func(handle->cb.data, ok, handle->path.image, handle->path.edje);
1506
1507    _e_util_image_import_handle_free(handle);
1508
1509    return ECORE_CALLBACK_CANCEL;
1510 }
1511
1512 static void
1513 _e_util_image_import_handle_free(E_Util_Image_Import_Handle *handle)
1514 {
1515    unlink(handle->path.temp);
1516    eina_stringshare_del(handle->path.image);
1517    eina_stringshare_del(handle->path.edje);
1518    eina_stringshare_del(handle->path.temp);
1519    if (handle->handler) ecore_event_handler_del(handle->handler);
1520    E_FREE(handle);
1521 }
1522
1523 static Eina_Bool
1524 _e_util_conf_timer_old(void *data)
1525 {
1526    char *module_name = data;
1527    char buf[PATH_MAX];
1528    char *msg =
1529      _("Configuration data needed "
1530        "upgrading. Your old configuration<br> has been"
1531        " wiped and a new set of defaults initialized. "
1532        "This<br>will happen regularly during "
1533        "development, so don't report a<br>bug. "
1534        "This simply means the module needs "
1535        "new configuration<br>data by default for "
1536        "usable functionality that your old<br>"
1537        "configuration simply lacks. This new set of "
1538        "defaults will fix<br>that by adding it in. "
1539        "You can re-configure things now to your<br>"
1540        "liking. Sorry for the inconvenience.<br>");
1541
1542    snprintf(buf, sizeof(buf),N_("%s Configuration Updated"), module_name);
1543    e_util_dialog_internal(buf, msg);
1544    E_FREE(module_name);
1545
1546    return ECORE_CALLBACK_CANCEL;
1547 }
1548
1549 static Eina_Bool
1550 _e_util_conf_timer_new(void *data)
1551 {
1552    char *module_name = data;
1553    char buf[4096];
1554    char *msg =
1555      _("Your module configuration is NEWER "
1556        "than the module version. This is "
1557        "very<br>strange. This should not happen unless"
1558        " you downgraded<br>the module or "
1559        "copied the configuration from a place where"
1560        "<br>a newer version of the module "
1561        "was running. This is bad and<br>as a "
1562        "precaution your configuration has been now "
1563        "restored to<br>defaults. Sorry for the "
1564        "inconvenience.<br>");
1565
1566    snprintf(buf, sizeof(buf),N_("%s Configuration Updated"), module_name);
1567    e_util_dialog_internal(buf, msg);
1568    E_FREE(module_name);
1569
1570    return ECORE_CALLBACK_CANCEL;
1571 }
1572
1573 EAPI Eina_Bool
1574 e_util_module_config_check(const char *module_name, int loaded, int current)
1575 {
1576    if ((loaded >> 16) < (current >> 16))
1577      {
1578         ecore_timer_add(1.0, _e_util_conf_timer_old, strdup(module_name));
1579         return EINA_FALSE;
1580      }
1581    else if (loaded > current)
1582      {
1583         ecore_timer_add(1.0, _e_util_conf_timer_new, strdup(module_name));
1584         return EINA_FALSE;
1585      }
1586
1587    return EINA_TRUE;
1588 }
1589
1590 /**
1591  * Checks whenever the current manager/container/zone have fullscreen windows.
1592  */
1593 EAPI Eina_Bool
1594 e_util_fullscreen_curreny_any(void)
1595 {
1596    E_Manager *man = e_manager_current_get();
1597    E_Container *con = e_container_current_get(man);
1598    E_Zone *zone = e_zone_current_get(con);
1599    E_Desk *desk;
1600
1601    if ((zone) && (zone->fullscreen > 0)) return EINA_TRUE;
1602    desk = e_desk_current_get(zone);
1603    if ((desk) && (desk->fullscreen_borders > 0)) return EINA_TRUE;
1604    return EINA_FALSE;
1605 }
1606
1607 /**
1608  * Checks whenever any manager/container/zone have fullscreen windows.
1609  */
1610 EAPI Eina_Bool
1611 e_util_fullscreen_any(void)
1612 {
1613    E_Zone *zone;
1614    Eina_List *lm, *lc, *lz;
1615    E_Container *con;
1616    E_Manager *man;
1617    E_Desk *desk;
1618    int x, y;
1619
1620    EINA_LIST_FOREACH(e_manager_list(), lm, man)
1621      {
1622         EINA_LIST_FOREACH(man->containers, lc, con)
1623           {
1624              EINA_LIST_FOREACH(con->zones, lz, zone)
1625                {
1626                   if (zone->fullscreen > 0) return EINA_TRUE;
1627
1628                   for (x = 0; x < zone->desk_x_count; x++)
1629                     for (y = 0; y < zone->desk_y_count; y++)
1630                       {
1631                          desk = e_desk_at_xy_get(zone, x, y);
1632                          if ((desk) && (desk->fullscreen_borders > 0))
1633                            return EINA_TRUE;
1634                       }
1635                }
1636           }
1637      }
1638    return EINA_FALSE;
1639 }