1 #include "e.h"
2 
3 E_API E_Path * path_data = NULL;
4 E_API E_Path * path_images = NULL;
5 E_API E_Path * path_fonts = NULL;
6 E_API E_Path * path_icons = NULL;
7 E_API E_Path * path_modules = NULL;
8 E_API E_Path * path_backgrounds = NULL;
9 E_API E_Path * path_messages = NULL;
10 
11 /* local subsystem functions */
12 static Eina_Bool    _e_util_cb_delayed_del(void *data);
13 static Eina_Bool    _e_util_wakeup_cb(void *data);
14 
15 static Evas_Object *_e_util_icon_add(const char *path, Evas *evas, int size);
16 
17 static void         _e_util_cb_delayed_cancel(void *data, void *obj);
18 
19 /* local subsystem globals */
20 static Ecore_Timer *_e_util_dummy_timer = NULL;
21 
22 /* externally accessible functions */
23 E_API void
e_util_wakeup(void)24 e_util_wakeup(void)
25 {
26    if (_e_util_dummy_timer) return;
27    _e_util_dummy_timer = ecore_timer_loop_add(0.0, _e_util_wakeup_cb, NULL);
28 }
29 
30 E_API void
e_util_env_set(const char * var,const char * val)31 e_util_env_set(const char *var, const char *val)
32 {
33    if (val)
34      {
35 #ifdef HAVE_SETENV
36         setenv(var, val, 1);
37 #else
38         char buf[8192];
39 
40         snprintf(buf, sizeof(buf), "%s=%s", var, val);
41         putenv(strdup(buf));
42 #endif
43      }
44    else
45      {
46 #ifdef HAVE_UNSETENV
47         unsetenv(var);
48 #else
49         if (getenv(var)) putenv(var);
50 #endif
51      }
52 }
53 
54 E_API int
e_util_glob_match(const char * str,const char * pattern)55 e_util_glob_match(const char *str, const char *pattern)
56 {
57    if ((!str) || (!pattern)) return 0;
58    if (pattern[0] == 0)
59      {
60         if (str[0] == 0) return 1;
61         return 0;
62      }
63    if (str == pattern) return 1;
64    if (!strcmp(pattern, "*")) return 1;
65    if (!fnmatch(pattern, str, 0)) return 1;
66    return 0;
67 }
68 
69 E_API int
e_util_glob_case_match(const char * str,const char * pattern)70 e_util_glob_case_match(const char *str, const char *pattern)
71 {
72    const char *p;
73    char *tstr, *tglob, *tp;
74 
75    if (str == pattern) return 1;
76    if (pattern[0] == 0)
77      {
78         if (str[0] == 0) return 1;
79         return 0;
80      }
81    if (!strcmp(pattern, "*")) return 1;
82    tstr = alloca(strlen(str) + 1);
83    for (tp = tstr, p = str; *p != 0; p++, tp++)
84      *tp = tolower(*p);
85    *tp = 0;
86    tglob = alloca(strlen(pattern) + 1);
87    for (tp = tglob, p = pattern; *p != 0; p++, tp++)
88      *tp = tolower(*p);
89    *tp = 0;
90    if (!fnmatch(tglob, tstr, 0)) return 1;
91    return 0;
92 }
93 
94 E_API int
e_util_strcmp(const char * s1,const char * s2)95 e_util_strcmp(const char *s1, const char *s2)
96 {
97    if ((s1) && (s2))
98      {
99         if (s1 == s2) return 0;
100         return strcmp(s1, s2);
101      }
102    return 0x7fffffff;
103 }
104 
105 E_API int
e_util_strcasecmp(const char * s1,const char * s2)106 e_util_strcasecmp(const char *s1, const char *s2)
107 {
108    if ((!s1) && (!s2)) return 0;
109    if (!s1) return -1;
110    if (!s2) return 1;
111    return strcasecmp(s1, s2);
112 }
113 
114 E_API int
e_util_both_str_empty(const char * s1,const char * s2)115 e_util_both_str_empty(const char *s1, const char *s2)
116 {
117    int empty = 0;
118 
119    if ((!s1) && (!s2)) return 1;
120    if ((!s1) || ((s1) && (s1[0] == 0))) empty++;
121    if ((!s2) || ((s2) && (s2[0] == 0))) empty++;
122    if (empty == 2) return 1;
123    return 0;
124 }
125 
126 E_API int
e_util_immortal_check(void)127 e_util_immortal_check(void)
128 {
129    Eina_List *wins;
130 
131    wins = e_clients_immortal_list();
132    if (wins)
133      {
134         e_util_dialog_show(_("Cannot exit - immortal windows."),
135                            _("Some windows are left still around with the Lifespan lock enabled. This means<ps/>"
136                              "that Enlightenment will not allow itself to exit until these windows have<ps/>"
137                              "been closed or have the lifespan lock removed.<ps/>"));
138         /* FIXME: should really display a list of these lifespan locked */
139         /* windows in a dialog and let the user disable their locks in */
140         /* this dialog */
141         eina_list_free(wins);
142         return 1;
143      }
144    return 0;
145 }
146 
147 E_API int
e_util_edje_icon_check(const char * name)148 e_util_edje_icon_check(const char *name)
149 {
150    const char *file;
151    char buf[4096];
152 
153    if ((!name) || (!name[0])) return 0;
154    snprintf(buf, sizeof(buf), "e/icons/%s", name);
155    file = e_theme_edje_file_get("base/theme/icons", buf);
156    if (file[0]) return 1;
157    return 0;
158 }
159 
160 /* WARNING This function is deprecated,. must be made static.
161  * You should use e_util_icon_theme_set instead
162  */
163 E_API int
e_util_edje_icon_set(Evas_Object * obj,const char * name)164 e_util_edje_icon_set(Evas_Object *obj, const char *name)
165 {
166    const char *file;
167    char buf[4096];
168 
169    if ((!name) || (!name[0])) return 0;
170    snprintf(buf, sizeof(buf), "e/icons/%s", name);
171    file = e_theme_edje_file_get("base/theme/icons", buf);
172    if (file[0])
173      {
174         edje_object_file_set(obj, file, buf);
175         return 1;
176      }
177    return 0;
178 }
179 
180 static int
_e_util_icon_theme_set(Evas_Object * obj,const char * icon,Eina_Bool fallback)181 _e_util_icon_theme_set(Evas_Object *obj, const char *icon, Eina_Bool fallback)
182 {
183    const char *file;
184    char buf[4096];
185 
186    if ((!icon) || (!icon[0])) return 0;
187    snprintf(buf, sizeof(buf), "e/icons/%s", icon);
188 
189    if (fallback)
190      file = e_theme_edje_icon_fallback_file_get(buf);
191    else
192      file = e_theme_edje_file_get("base/theme/icons", buf);
193 
194    if (file[0])
195      {
196         e_icon_file_edje_set(obj, file, buf);
197         return 1;
198      }
199 
200    return 0;
201 }
202 
203 static int
_e_util_icon_fdo_set(Evas_Object * obj,const char * icon)204 _e_util_icon_fdo_set(Evas_Object *obj, const char *icon)
205 {
206    const char *path = NULL;
207    unsigned int size;
208 
209    if ((!icon) || (!icon[0])) return 0;
210    size = e_icon_scale_size_get(obj);
211    if (size < 16) size = 16;
212    size = e_util_icon_size_normalize(size * e_scale);
213 
214    path = efreet_icon_path_find(e_config->icon_theme, icon, size);
215    if (!path) return 0;
216 
217    e_icon_file_set(obj, path);
218    return 1;
219 }
220 
221 /* use e_icon_size_scale_set(obj, size) to set the preferred icon size */
222 E_API int
e_util_icon_theme_set(Evas_Object * obj,const char * icon)223 e_util_icon_theme_set(Evas_Object *obj, const char *icon)
224 {
225    if (icon && (icon[0] == '/'))
226      {
227         e_icon_file_set(obj, icon);
228         return 1;
229      }
230    if (e_config->icon_theme_overrides)
231      {
232         if (_e_util_icon_fdo_set(obj, icon))
233           return 1;
234         if (_e_util_icon_theme_set(obj, icon, EINA_FALSE))
235           return 1;
236         return _e_util_icon_theme_set(obj, icon, EINA_TRUE);
237      }
238    else
239      {
240         if (_e_util_icon_theme_set(obj, icon, EINA_FALSE))
241           return 1;
242         if (_e_util_icon_fdo_set(obj, icon))
243           return 1;
244         return _e_util_icon_theme_set(obj, icon, EINA_TRUE);
245      }
246 }
247 
248 int
_e_util_menu_item_edje_icon_set(E_Menu_Item * mi,const char * name,Eina_Bool fallback)249 _e_util_menu_item_edje_icon_set(E_Menu_Item *mi, const char *name, Eina_Bool fallback)
250 {
251    const char *file;
252    char buf[4096];
253 
254    if ((!name) || (!name[0])) return 0;
255 
256    if ((!fallback) && (name[0] == '/') && ecore_file_exists(name))
257      {
258         e_menu_item_icon_edje_set(mi, name, "icon");
259         return 1;
260      }
261    snprintf(buf, sizeof(buf), "e/icons/%s", name);
262 
263    if (fallback)
264      file = e_theme_edje_icon_fallback_file_get(buf);
265    else
266      file = e_theme_edje_file_get("base/theme/icons", buf);
267 
268    if (file[0])
269      {
270         e_menu_item_icon_edje_set(mi, file, buf);
271         return 1;
272      }
273    return 0;
274 }
275 
276 E_API unsigned int
e_util_icon_size_normalize(unsigned int desired)277 e_util_icon_size_normalize(unsigned int desired)
278 {
279    const unsigned int *itr, known_sizes[] =
280    {
281       16, 22, 24, 32, 36, 48, 64, 72, 96, 128, 192, 256, 0
282    };
283 
284    for (itr = known_sizes; *itr > 0; itr++)
285      if (*itr >= desired)
286        return *itr;
287 
288    return 256; /* largest know size? */
289 }
290 
291 static int
_e_util_menu_item_fdo_icon_set(E_Menu_Item * mi,const char * icon)292 _e_util_menu_item_fdo_icon_set(E_Menu_Item *mi, const char *icon)
293 {
294    const char *path = NULL;
295    unsigned int size;
296 
297    if ((!icon) || (!icon[0])) return 0;
298    size = e_util_icon_size_normalize(96 * e_scale);
299    path = efreet_icon_path_find(e_config->icon_theme, icon, size);
300    if (!path) return 0;
301    e_menu_item_icon_file_set(mi, path);
302    return 1;
303 }
304 
305 E_API int
e_util_menu_item_theme_icon_set(E_Menu_Item * mi,const char * icon)306 e_util_menu_item_theme_icon_set(E_Menu_Item *mi, const char *icon)
307 {
308    if (e_config->icon_theme_overrides)
309      {
310         if (_e_util_menu_item_fdo_icon_set(mi, icon))
311           return 1;
312         if (_e_util_menu_item_edje_icon_set(mi, icon, EINA_FALSE))
313           return 1;
314         return _e_util_menu_item_edje_icon_set(mi, icon, EINA_TRUE);
315      }
316    else
317      {
318         if (_e_util_menu_item_edje_icon_set(mi, icon, EINA_FALSE))
319           return 1;
320         if (_e_util_menu_item_fdo_icon_set(mi, icon))
321           return 1;
322         return _e_util_menu_item_edje_icon_set(mi, icon, EINA_TRUE);
323      }
324 }
325 
326 E_API const char *
e_util_mime_icon_get(const char * mime,unsigned int size)327 e_util_mime_icon_get(const char *mime, unsigned int size)
328 {
329    char buf[1024];
330    const char *file = NULL;
331 
332    if (e_config->icon_theme_overrides)
333      file = efreet_mime_type_icon_get(mime, e_config->icon_theme, e_util_icon_size_normalize(size));
334    if (file) return file;
335 
336    if (snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", mime) >= (int)sizeof(buf))
337      return NULL;
338 
339    file = e_theme_edje_file_get("base/theme/icons", buf);
340    if (file && file[0]) return file;
341    return efreet_mime_type_icon_get(mime, e_config->icon_theme, e_util_icon_size_normalize(size));
342 }
343 
344 E_API E_Client *
e_util_desk_client_above(E_Client * ec)345 e_util_desk_client_above(E_Client *ec)
346 {
347    E_Client *ec2;
348 
349    E_OBJECT_CHECK_RETURN(ec, NULL);
350    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, NULL);
351 
352    for (ec2 = e_client_above_get(ec); ec2; ec2 = e_client_above_get(ec2))
353      {
354         if ((ec2->desk == ec->desk) || (ec2->sticky)) return ec2;
355      }
356    return NULL;
357 }
358 
359 E_API E_Client *
e_util_desk_client_below(E_Client * ec)360 e_util_desk_client_below(E_Client *ec)
361 {
362    E_Client *ec2;
363 
364    E_OBJECT_CHECK_RETURN(ec, NULL);
365    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, NULL);
366 
367    for (ec2 = e_client_below_get(ec); ec2; ec2 = e_client_below_get(ec2))
368      {
369         if ((ec2->desk == ec->desk) || (ec2->sticky)) return ec2;
370      }
371    return NULL;
372 }
373 
374 E_API int
e_util_edje_collection_exists(const char * file,const char * coll)375 e_util_edje_collection_exists(const char *file, const char *coll)
376 {
377    Eina_List *clist;
378    Eina_Stringshare *str;
379    Eina_Bool ret = EINA_FALSE;
380 
381    clist = edje_file_collection_list(file);
382    EINA_LIST_FREE(clist, str)
383      {
384         if ((!ret) && (!strcmp(coll, str)))
385           ret = EINA_TRUE;
386         eina_stringshare_del(str);
387      }
388    return ret;
389 }
390 
391 E_API E_Dialog *
e_util_dialog_internal(const char * title,const char * txt)392 e_util_dialog_internal(const char *title, const char *txt)
393 {
394    E_Dialog *dia;
395 
396    dia = e_dialog_new(NULL, "E", "_error_dialog");
397    if (!dia) return NULL;
398    e_dialog_title_set(dia, title);
399    e_dialog_text_set(dia, txt);
400    e_dialog_icon_set(dia, "dialog-error", 64);
401    e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
402    e_dialog_button_focus_num(dia, 0);
403    elm_win_center(dia->win, 1, 1);
404    e_dialog_show(dia);
405    return dia;
406 }
407 
408 E_API const char *
e_util_filename_escape(const char * filename)409 e_util_filename_escape(const char *filename)
410 {
411    const char *p;
412    char *q;
413    static char buf[PATH_MAX];
414 
415    if (!filename) return NULL;
416    p = filename;
417    q = buf;
418    while (*p)
419      {
420         if ((q - buf) > 4090) return NULL;
421         if (
422           (*p == ' ') || (*p == '\t') || (*p == '\n') ||
423           (*p == '\\') || (*p == '\'') || (*p == '\"') ||
424           (*p == ';') || (*p == '!') || (*p == '#') ||
425           (*p == '$') || (*p == '%') || (*p == '&') ||
426           (*p == '*') || (*p == '(') || (*p == ')') ||
427           (*p == '[') || (*p == ']') || (*p == '{') ||
428           (*p == '}') || (*p == '|') || (*p == '<') ||
429           (*p == '>') || (*p == '?')
430           )
431           {
432              *q = '\\';
433              q++;
434           }
435         *q = *p;
436         q++;
437         p++;
438      }
439    *q = 0;
440    return buf;
441 }
442 
443 
444 E_API char *
e_util_shell_env_path_eval(const char * path)445 e_util_shell_env_path_eval(const char *path)
446 {
447    /* evaluate things like:
448     * $HOME/bling -> /home/user/bling
449     * $HOME/bin/$HOSTNAME/blah -> /home/user/bin/localhost/blah
450     * etc. etc.
451     */
452    const char *p, *v2, *v1 = NULL;
453    char buf[PATH_MAX], *pd, *s, *vp;
454    char *v = NULL;
455    int esc = 0, invar = 0;
456 
457    for (p = path, pd = buf; (pd < (buf + sizeof(buf) - 1)); p++)
458      {
459         if (invar)
460           {
461              if (!((isalnum(*p)) || (*p == '_')))
462                {
463                   v2 = p;
464                   invar = 0;
465                   if ((v2 - v1) > 1)
466                     {
467                        s = alloca(v2 - v1);
468                        strncpy(s, v1 + 1, v2 - v1 - 1);
469                        s[v2 - v1 - 1] = 0;
470                        if (strncmp(s, "XDG", 3))
471                          v = getenv(s);
472                        else
473                          {
474                             if (!strcmp(s, "XDG_CONFIG_HOME"))
475                               v = (char *)efreet_config_home_get();
476                             else if (!strcmp(s, "XDG_CACHE_HOME"))
477                               v = (char *)efreet_cache_home_get();
478                             else if (!strcmp(s, "XDG_DATA_HOME"))
479                               v = (char *)efreet_data_home_get();
480                             else if (!strcmp(s, "XDG_DESKTOP_DIR"))
481                               v = (char *)efreet_desktop_dir_get();
482                             else if (!strcmp(s, "XDG_DOWNLOAD_DIR"))
483                               v = (char *)efreet_download_dir_get();
484                             else if (!strcmp(s, "XDG_TEMPLATES_DIR"))
485                               v = (char *)efreet_templates_dir_get();
486                             else if (!strcmp(s, "XDG_PUBLICSHARE_DIR"))
487                               v = (char *)efreet_public_share_dir_get();
488                             else if (!strcmp(s, "XDG_DOCUMENTS_DIR"))
489                               v = (char *)efreet_documents_dir_get();
490                             else if (!strcmp(s, "XDG_MUSIC_DIR"))
491                               v = (char *)efreet_music_dir_get();
492                             else if (!strcmp(s, "XDG_PICTURES_DIR"))
493                               v = (char *)efreet_pictures_dir_get();
494                             else if (!strcmp(s, "XDG_VIDEOS_DIR"))
495                               v = (char *)efreet_videos_dir_get();
496                             else if (!strcmp(s, "XDG_RUNTIME_DIR"))
497                               v = (char *)efreet_runtime_dir_get();
498                          }
499 
500                        if (v)
501                          {
502                             vp = v;
503                             while ((*vp) && (pd < (buf + sizeof(buf) - 1)))
504                               {
505                                  *pd = *vp;
506                                  vp++;
507                                  pd++;
508                               }
509                          }
510                     }
511                   if (pd < (buf + sizeof(buf) - 1))
512                     {
513                        *pd = *p;
514                        pd++;
515                     }
516                }
517           }
518         else
519           {
520              if (esc)
521                {
522                   *pd = *p;
523                   pd++;
524                }
525              else
526                {
527                   if (*p == '\\') esc = 1;
528                   else if (*p == '$')
529                     {
530                        invar = 1;
531                        v1 = p;
532                     }
533                   else
534                     {
535                        *pd = *p;
536                        pd++;
537                     }
538                }
539           }
540         if (*p == 0) break;
541      }
542    *pd = 0;
543    return strdup(buf);
544 }
545 
546 E_API char *
e_util_size_string_get(off_t size)547 e_util_size_string_get(off_t size)
548 {
549    double dsize;
550    char buf[256];
551 
552    dsize = (double)size;
553    if (dsize < 1024.0) snprintf(buf, sizeof(buf), _("%'.0f bytes"), dsize);
554    else
555      {
556         dsize /= 1024.0;
557         if (dsize < 1024) snprintf(buf, sizeof(buf), _("%'.0f KiB"), dsize);
558         else
559           {
560              dsize /= 1024.0;
561              if (dsize < 1024) snprintf(buf, sizeof(buf), _("%'.1f MiB"), dsize);
562              else
563                {
564                   dsize /= 1024.0;
565                   if (dsize < 1024) snprintf(buf, sizeof(buf), _("%'.1f GiB"), dsize);
566                   else
567                     {
568                        dsize /= 1024.0;
569                        snprintf(buf, sizeof(buf), _("%'.1f TiB"), dsize);
570                     }
571                }
572           }
573      }
574    return strdup(buf);
575 }
576 
577 E_API char *
e_util_file_time_get(time_t ftime)578 e_util_file_time_get(time_t ftime)
579 {
580    time_t diff, ltime;
581    char buf[256];
582    char *s = NULL;
583    long test;
584    ltime = time(NULL);
585    diff = ltime - ftime;
586    buf[0] = 0;
587    if (ftime > ltime)
588      snprintf(buf, sizeof(buf), _("In the future"));
589    else
590      {
591         if (diff <= 60)
592           snprintf(buf, sizeof(buf), _("In the last minute"));
593         else if (diff >= 31526000)
594           {
595              test = diff / 31526000;
596              snprintf(buf, sizeof(buf), P_("Last year", "%li Years ago", test), test);
597           }
598         else if (diff >= 2592000)
599           {
600              test = diff / 2592000;
601              snprintf(buf, sizeof(buf), P_("Last month", "%li Months ago", test), test);
602           }
603         else if (diff >= 604800)
604           {
605              test = diff / 604800;
606              snprintf(buf, sizeof(buf), P_("Last week", "%li Weeks ago", test), test);
607           }
608         else if (diff >= 86400)
609           {
610              test = diff / 86400;
611              snprintf(buf, sizeof(buf), P_("Yesterday", "%li Days ago", test), test);
612           }
613         else if (diff >= 3600)
614           {
615              test = diff / 3600;
616              snprintf(buf, sizeof(buf), P_("An hour ago", "%li Hours ago", test), test);
617           }
618         else if (diff > 60)
619           {
620              test = diff / 60;
621              snprintf(buf, sizeof(buf), P_("A minute ago", "%li Minutes ago", test), test);
622           }
623      }
624 
625    if (buf[0])
626      s = strdup(buf);
627    else
628      s = strdup(_("Unknown"));
629    return s;
630 }
631 
632 E_API Evas_Object *
e_util_icon_add(const char * path,Evas * evas)633 e_util_icon_add(const char *path, Evas *evas)
634 {
635    return _e_util_icon_add(path, evas, 64);
636 }
637 
638 E_API Evas_Object *
e_util_desktop_icon_add(Efreet_Desktop * desktop,unsigned int size,Evas * evas)639 e_util_desktop_icon_add(Efreet_Desktop *desktop, unsigned int size, Evas *evas)
640 {
641    if ((!desktop) || (!desktop->icon)) return NULL;
642    return e_util_icon_theme_icon_add(desktop->icon, size, evas);
643 }
644 
645 E_API Evas_Object *
e_util_icon_theme_icon_add(const char * icon_name,unsigned int size,Evas * evas)646 e_util_icon_theme_icon_add(const char *icon_name, unsigned int size, Evas *evas)
647 {
648    if (!icon_name) return NULL;
649    if (icon_name[0] == '/') return _e_util_icon_add(icon_name, evas, size);
650    else
651      {
652         Evas_Object *obj;
653         const char *path;
654 
655         path = efreet_icon_path_find(e_config->icon_theme, icon_name, size);
656         if (path)
657           {
658              obj = _e_util_icon_add(path, evas, size);
659              return obj;
660           }
661      }
662    return NULL;
663 }
664 
665 E_API void
e_util_desktop_menu_item_icon_add(Efreet_Desktop * desktop,unsigned int size,E_Menu_Item * mi)666 e_util_desktop_menu_item_icon_add(Efreet_Desktop *desktop, unsigned int size, E_Menu_Item *mi)
667 {
668    const char *path = NULL;
669 
670    if ((!desktop) || (!desktop->icon)) return;
671 
672    if (desktop->icon[0] == '/') path = desktop->icon;
673    else path = efreet_icon_path_find(e_config->icon_theme, desktop->icon, size);
674 
675    if (path)
676      {
677         const char *ext;
678 
679         ext = strrchr(path, '.');
680         if (ext)
681           {
682              if (strcmp(ext, ".edj") == 0)
683                e_menu_item_icon_edje_set(mi, path, "icon");
684              else
685                e_menu_item_icon_file_set(mi, path);
686           }
687         else
688           e_menu_item_icon_file_set(mi, path);
689      }
690 }
691 
692 E_API int
e_util_dir_check(const char * dir)693 e_util_dir_check(const char *dir)
694 {
695    if (!ecore_file_exists(dir))
696      {
697         if (!ecore_file_mkpath(dir))
698           {
699              e_util_dialog_show(_("Error creating directory"), _("Failed to create directory: %s .<ps/>Check that you have correct permissions set."), dir);
700              return 0;
701           }
702      }
703    else
704      {
705         if (!ecore_file_is_dir(dir))
706           {
707              e_util_dialog_show(_("Error creating directory"), _("Failed to create directory: %s .<ps/>A file of that name already exists."), dir);
708              return 0;
709           }
710      }
711    return 1;
712 }
713 
714 static Eina_Array *_delay_del_array = NULL;
715 static Ecore_Idle_Enterer *_delay_del_idler = NULL;
716 
717 static Eina_Bool
_e_util_cb_delayed_del(void * data EINA_UNUSED)718 _e_util_cb_delayed_del(void *data EINA_UNUSED)
719 {
720    while (_delay_del_array)
721      {
722         Eina_Array *arr = _delay_del_array;
723         Eina_Iterator *itr = eina_array_iterator_new(arr);
724         void *ptr;
725 
726         _delay_del_array = NULL;
727         while (eina_iterator_next(itr, &ptr))
728           {
729              if (ptr) e_object_del(E_OBJECT(ptr));
730           }
731         eina_array_free(arr);
732      }
733    _delay_del_idler = NULL;
734    return ECORE_CALLBACK_CANCEL;
735 }
736 
737 static void
_e_util_cb_delayed_cancel(void * data,void * obj EINA_UNUSED)738 _e_util_cb_delayed_cancel(void *data, void *obj EINA_UNUSED)
739 {
740    unsigned long c = (unsigned long)data;
741    if (_delay_del_array) eina_array_data_set(_delay_del_array, c, NULL);
742 }
743 
744 E_API void
e_util_defer_object_del(E_Object * obj)745 e_util_defer_object_del(E_Object *obj)
746 {
747    if (stopping)
748      e_object_del(obj);
749    else
750      {
751         if (!_delay_del_array)
752           {
753              _delay_del_array = eina_array_new(8);
754              if (!_delay_del_idler)
755                _delay_del_idler = ecore_idle_enterer_before_add
756                  (_e_util_cb_delayed_del, NULL);
757           }
758         if (_delay_del_array)
759           {
760              if (eina_array_push(_delay_del_array, obj))
761                {
762                   unsigned long c = eina_array_count_get(_delay_del_array);
763                   e_object_delfn_add(obj, _e_util_cb_delayed_cancel, (void *)c);
764                }
765           }
766      }
767 }
768 
769 E_API const char *
e_util_winid_str_get(Ecore_X_Window win)770 e_util_winid_str_get(Ecore_X_Window win)
771 {
772    const char *vals = "qWeRtYuIoP5-$&<~";
773    static char id[9];
774    unsigned int val;
775 
776    val = (unsigned int)win;
777    id[0] = vals[(val >> 28) & 0xf];
778    id[1] = vals[(val >> 24) & 0xf];
779    id[2] = vals[(val >> 20) & 0xf];
780    id[3] = vals[(val >> 16) & 0xf];
781    id[4] = vals[(val >> 12) & 0xf];
782    id[5] = vals[(val >> 8) & 0xf];
783    id[6] = vals[(val >> 4) & 0xf];
784    id[7] = vals[(val) & 0xf];
785    id[8] = 0;
786    return id;
787 }
788 
789 static int
_win_auto_size_calc(int max,int min)790 _win_auto_size_calc(int max, int min)
791 {
792    const float *itr, scales[] = {0.25, 0.3, 0.5, 0.75, 0.8, 0.9, 0.95, -1};
793 
794    for (itr = scales; *itr > 0; itr++)
795      {
796         int value = *itr * max;
797         if (value > min) /* not >=, try a bit larger */
798           {
799              if (min > 10)
800                value = E_CLAMP(value, min, min * 1.5);
801              return value;
802           }
803      }
804 
805    return min;
806 }
807 
808 E_API void
e_util_win_auto_resize_fill(Evas_Object * win)809 e_util_win_auto_resize_fill(Evas_Object *win)
810 {
811    E_Zone *zone = NULL;
812    E_Client *ec;
813 
814    ec = e_win_client_get(win);
815    if (ec)
816      zone = ec->zone;
817    if (!zone)
818      zone = e_zone_current_get();
819 
820    if (zone)
821      {
822         int w, h, mw, mh;
823 
824         e_zone_useful_geometry_get(zone, NULL, NULL, &w, &h);
825 
826         evas_object_size_hint_min_get(win, &mw, &mh);
827         w = _win_auto_size_calc(w, mw);
828         h = _win_auto_size_calc(h, mh);
829         evas_object_resize(win, w, h);
830      }
831 }
832 
833 /* local subsystem functions */
834 
835 static Evas_Object *
_e_util_icon_add(const char * path,Evas * evas,int size)836 _e_util_icon_add(const char *path, Evas *evas, int size)
837 {
838    Evas_Object *o = NULL;
839    const char *ext;
840 
841    if (!path) return NULL;
842    if (!ecore_file_exists(path)) return NULL;
843 
844    o = e_icon_add(evas);
845    e_icon_scale_size_set(o, size);
846    e_icon_preload_set(o, 1);
847    ext = strrchr(path, '.');
848    if (ext)
849      {
850         if (!strcmp(ext, ".edj"))
851           e_icon_file_edje_set(o, path, "icon");
852         else
853           e_icon_file_set(o, path);
854      }
855    else
856      e_icon_file_set(o, path);
857    e_icon_fill_inside_set(o, 1);
858 
859    return o;
860 }
861 
862 static Eina_Bool
_e_util_wakeup_cb(void * data EINA_UNUSED)863 _e_util_wakeup_cb(void *data EINA_UNUSED)
864 {
865    _e_util_dummy_timer = NULL;
866    return ECORE_CALLBACK_CANCEL;
867 }
868 
869 static Eina_Bool
_e_util_conf_timer_old(void * data)870 _e_util_conf_timer_old(void *data)
871 {
872    char *module_name = data;
873    char buf[4096];
874    char *msg = _("Configuration data needed upgrading. Your old configuration<ps/>"
875                  "has been wiped and a new set of defaults initialized. This<ps/>"
876                  "will happen regularly during development, so don't report a<ps/>"
877                  "bug. This means the module needs new configuration<ps/>"
878                  "data by default for usable functionality that your old<ps/>"
879                  "configuration lacked. This new set of defaults will fix<ps/>"
880                  "that by adding it in. You can re-configure things now to your<ps/>"
881                  "liking. Sorry for the hiccup in your configuration.<ps/>");
882 
883    snprintf(buf, sizeof(buf), N_("%s Configuration Updated"), module_name);
884    e_util_dialog_internal(buf, msg);
885    E_FREE(module_name);
886 
887    return ECORE_CALLBACK_CANCEL;
888 }
889 
890 static Eina_Bool
_e_util_conf_timer_new(void * data)891 _e_util_conf_timer_new(void *data)
892 {
893    char *module_name = data;
894    char buf[4096];
895    char *msg =
896      _("Your module configuration is NEWER "
897        "than the module version. This is "
898        "very<ps/>strange. This should not happen unless"
899        " you downgraded<ps/>the module or "
900        "copied the configuration from a place where"
901        "<ps/>a newer version of the module "
902        "was running. This is bad and<ps/>as a "
903        "precaution your configuration has been now "
904        "restored to<ps/>defaults. Sorry for the "
905        "inconvenience.<ps/>");
906 
907    snprintf(buf, sizeof(buf), _("%s Configuration Updated"), module_name);
908    e_util_dialog_internal(buf, msg);
909    E_FREE(module_name);
910 
911    return ECORE_CALLBACK_CANCEL;
912 }
913 
914 E_API Eina_Bool
e_util_module_config_check(const char * module_name,int loaded,int current)915 e_util_module_config_check(const char *module_name, int loaded, int current)
916 {
917    if (loaded > current)
918      {
919         ecore_timer_loop_add(1.0, _e_util_conf_timer_new, strdup(module_name));
920         return EINA_FALSE;
921      }
922    loaded -= loaded % 1000000, current -= current % 1000000;
923    if (loaded < current)
924      {
925         ecore_timer_loop_add(1.0, _e_util_conf_timer_old, strdup(module_name));
926         return EINA_FALSE;
927      }
928 
929    return EINA_TRUE;
930 }
931 
932 /**
933  * Checks whenever the current manager/comp/zone have fullscreen windows.
934  */
935 E_API Eina_Bool
e_util_fullscreen_current_any(void)936 e_util_fullscreen_current_any(void)
937 {
938    E_Zone *zone = e_zone_current_get();
939    E_Desk *desk;
940 
941    if ((zone) && (zone->fullscreen > 0)) return EINA_TRUE;
942    desk = e_desk_current_get(zone);
943    if ((desk) && (desk->fullscreen_clients)) return EINA_TRUE;
944    return EINA_FALSE;
945 }
946 
947 /**
948  * Checks whenever any manager/comp/zone have fullscreen windows.
949  */
950 E_API Eina_Bool
e_util_fullscreen_any(void)951 e_util_fullscreen_any(void)
952 {
953    E_Zone *zone;
954    const Eina_List *lz;
955    E_Desk *desk;
956    int x, y;
957 
958    EINA_LIST_FOREACH(e_comp->zones, lz, zone)
959      {
960         if (zone->fullscreen > 0) return EINA_TRUE;
961 
962         for (x = 0; x < zone->desk_x_count; x++)
963           for (y = 0; y < zone->desk_y_count; y++)
964             {
965                desk = e_desk_at_xy_get(zone, x, y);
966                if ((desk) && (desk->fullscreen_clients))
967                  return EINA_TRUE;
968             }
969      }
970    return EINA_FALSE;
971 }
972 
973 E_API const char *
e_util_time_str_get(long int seconds)974 e_util_time_str_get(long int seconds)
975 {
976    static char buf[1024];
977    long int test;
978 
979    if (seconds < 0)
980      snprintf(buf, sizeof(buf), _("Never"));
981    else
982      {
983         if (seconds <= 60)
984           snprintf(buf, sizeof(buf), P_("A second", "%li Seconds", seconds), seconds);
985         else if (seconds >= 31526000)
986           {
987              test = seconds / 31526000;
988              snprintf(buf, sizeof(buf), P_("One year", "%li Years", test), test);
989           }
990         else if (seconds >= 2592000)
991           {
992              test = seconds / 2592000;
993              snprintf(buf, sizeof(buf), P_("One month", "%li Months", test), test);
994           }
995         else if (seconds >= 604800)
996           {
997              test = seconds / 604800;
998              snprintf(buf, sizeof(buf), P_("One week", "%li Weeks", test), test);
999           }
1000         else if (seconds >= 86400)
1001           {
1002              test = seconds / 86400;
1003              snprintf(buf, sizeof(buf), P_("One day", "%li Days", test), test);
1004           }
1005         else if (seconds >= 3600)
1006           {
1007              test = seconds / 3600;
1008              snprintf(buf, sizeof(buf), P_("An hour", "%li Hours", test), test);
1009           }
1010         else if (seconds > 60)
1011           {
1012              test = seconds / 60;
1013              snprintf(buf, sizeof(buf), P_("A minute", "%li Minutes", test), test);
1014           }
1015      }
1016    return buf;
1017 }
1018 
1019 static void
_e_util_size_debug_free(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1020 _e_util_size_debug_free(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1021 {
1022    int x, y, w, h;
1023    const char *name;
1024 
1025    evas_object_geometry_get(obj, &x, &y, &w, &h);
1026    name = evas_object_name_get(obj);
1027    fprintf(stderr, "FREE %s %d OBJ[%s%s%p]: (%d,%d) - %dx%d\n", evas_object_visible_get(obj) ? "VIS" : "HID", evas_object_layer_get(obj), name ?: "", name ? "|" : "", obj, x, y, w, h);
1028 }
1029 
1030 static void
_e_util_size_debug_del(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1031 _e_util_size_debug_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1032 {
1033    int x, y, w, h;
1034    const char *name;
1035 
1036    evas_object_geometry_get(obj, &x, &y, &w, &h);
1037    name = evas_object_name_get(obj);
1038    fprintf(stderr, "DEL %s %d OBJ[%s%s%p]: (%d,%d) - %dx%d\n", evas_object_visible_get(obj) ? "VIS" : "HID", evas_object_layer_get(obj), name ?: "", name ? "|" : "", obj, x, y, w, h);
1039 }
1040 
1041 static void
_e_util_size_debug_stack(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1042 _e_util_size_debug_stack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1043 {
1044    int x, y, w, h;
1045    const char *name;
1046 
1047    evas_object_geometry_get(obj, &x, &y, &w, &h);
1048    name = evas_object_name_get(obj);
1049    fprintf(stderr, "RESTACK %s %d OBJ[%s%s%p]: (%d,%d) - %dx%d\n", evas_object_visible_get(obj) ? "VIS" : "HID", evas_object_layer_get(obj), name ?: "", name ? "|" : "", obj, x, y, w, h);
1050 }
1051 
1052 E_API void
e_util_size_debug(Evas_Object * obj)1053 e_util_size_debug(Evas_Object *obj)
1054 {
1055    int x, y, w, h;
1056    const char *name;
1057 
1058    evas_object_geometry_get(obj, &x, &y, &w, &h);
1059    name = evas_object_name_get(obj);
1060    fprintf(stderr, "%s %d OBJ[%s%s%p]: (%d,%d) - %dx%d\n", evas_object_visible_get(obj) ? "VIS" : "HID", evas_object_layer_get(obj), name ?: evas_object_type_get(obj), "|", obj, x, y, w, h);
1061 }
1062 
1063 static void
_e_util_size_debug(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1064 _e_util_size_debug(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1065 {
1066    e_util_size_debug(obj);
1067 }
1068 
1069 E_API void
e_util_size_debug_set(Evas_Object * obj,Eina_Bool enable)1070 e_util_size_debug_set(Evas_Object *obj, Eina_Bool enable)
1071 {
1072    if (enable)
1073      {
1074         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
1075                                        _e_util_size_debug, NULL);
1076         evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
1077                                        _e_util_size_debug, NULL);
1078         evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW,
1079                                        _e_util_size_debug, NULL);
1080         evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
1081                                        _e_util_size_debug, NULL);
1082         evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK,
1083                                        _e_util_size_debug_stack, NULL);
1084         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1085                                        _e_util_size_debug_del, NULL);
1086         evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE,
1087                                        _e_util_size_debug_free, NULL);
1088      }
1089    else
1090      {
1091         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
1092                                             _e_util_size_debug, NULL);
1093         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
1094                                             _e_util_size_debug, NULL);
1095         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_SHOW,
1096                                        _e_util_size_debug, NULL);
1097         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE,
1098                                        _e_util_size_debug, NULL);
1099         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
1100                                        _e_util_size_debug_del, NULL);
1101         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE,
1102                                        _e_util_size_debug_free, NULL);
1103      }
1104 }
1105 
1106 E_API void
e_util_string_list_free(Eina_List * l)1107 e_util_string_list_free(Eina_List *l)
1108 {
1109    char *s;
1110 
1111    EINA_LIST_FREE(l, s)
1112      free(s);
1113 }
1114 
1115 static Efreet_Desktop *
_e_util_default_terminal_get(const char * defaults_list)1116 _e_util_default_terminal_get(const char *defaults_list)
1117 {
1118    Efreet_Desktop *tdesktop = NULL;
1119    Efreet_Ini *ini;
1120    const char *s;
1121 
1122    ini = efreet_ini_new(defaults_list);
1123    if ((ini) && (ini->data) &&
1124        (efreet_ini_section_set(ini, "Default Applications")) &&
1125        (ini->section))
1126      {
1127         s = efreet_ini_string_get(ini, "x-scheme-handler/terminal");
1128         if (s) tdesktop = efreet_util_desktop_file_id_find(s);
1129      }
1130    if (ini) efreet_ini_free(ini);
1131    return tdesktop;
1132 }
1133 
1134 E_API Efreet_Desktop *
e_util_terminal_desktop_get(void)1135 e_util_terminal_desktop_get(void)
1136 {
1137    const char *terms[] =
1138    {
1139       "terminology.desktop",
1140       "rxvt.desktop",
1141       "gnome-terminal.desktop",
1142       "konsole.desktop",
1143       NULL
1144    };
1145    const char *s;
1146    char buf[PATH_MAX];
1147    Efreet_Desktop *tdesktop = NULL, *td;
1148    Eina_List *l;
1149    int i;
1150 
1151    s = efreet_data_home_get();
1152    if (s)
1153      {
1154         snprintf(buf, sizeof(buf), "%s/mimeapps.list",
1155                  efreet_config_home_get());
1156         tdesktop = _e_util_default_terminal_get(buf);
1157      }
1158    if (tdesktop) return tdesktop;
1159    EINA_LIST_FOREACH(efreet_data_dirs_get(), l, s)
1160      {
1161         snprintf(buf, sizeof(buf), "%s/applications/defaults.list", s);
1162         tdesktop = _e_util_default_terminal_get(buf);
1163         if (tdesktop) return tdesktop;
1164      }
1165 
1166    for (i = 0; terms[i]; i++)
1167      {
1168         tdesktop = efreet_util_desktop_file_id_find(terms[i]);
1169         if (tdesktop) return tdesktop;
1170      }
1171    if (!tdesktop)
1172      {
1173         l = efreet_util_desktop_category_list("TerminalEmulator");
1174         if (l)
1175           {
1176              // just take first one since above list doesn't work.
1177              tdesktop = l->data;
1178              EINA_LIST_FREE(l, td)
1179                {
1180                   // free/unref the desktops we are not going to use
1181                   if (td != tdesktop) efreet_desktop_free(td);
1182                }
1183           }
1184      }
1185    return tdesktop;
1186 }
1187 
1188 E_API E_Config_Binding_Key *
e_util_binding_match(const Eina_List * bindlist,Ecore_Event_Key * ev,unsigned int * num,const E_Config_Binding_Key * skip)1189 e_util_binding_match(const Eina_List *bindlist, Ecore_Event_Key *ev, unsigned int *num, const E_Config_Binding_Key *skip)
1190 {
1191    E_Config_Binding_Key *bi;
1192    const Eina_List *l;
1193    unsigned int mod = E_BINDING_MODIFIER_NONE;
1194 
1195    if (num) *num = 0;
1196 
1197    if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
1198      mod |= E_BINDING_MODIFIER_SHIFT;
1199    if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
1200      mod |= E_BINDING_MODIFIER_CTRL;
1201    if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
1202      mod |= E_BINDING_MODIFIER_ALT;
1203    if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
1204      mod |= E_BINDING_MODIFIER_WIN;
1205    /* see comment in e_bindings on numlock
1206       if (ev->modifiers & ECORE_X_LOCK_NUM)
1207       mod |= ECORE_X_LOCK_NUM;
1208     */
1209    EINA_LIST_FOREACH(bindlist ? : e_bindings->key_bindings, l, bi)
1210      {
1211         if (bi != skip)
1212           {
1213              if ((bi->modifiers == mod) && eina_streq(bi->key, ev->key))
1214                return bi;
1215           }
1216         if (num) (*num)++;
1217      }
1218    if (num) *num = 0;
1219    return NULL;
1220 }
1221 
1222 E_API void
e_util_gadcon_orient_icon_set(E_Gadcon_Orient orient,Evas_Object * obj)1223 e_util_gadcon_orient_icon_set(E_Gadcon_Orient orient, Evas_Object *obj)
1224 {
1225    switch (orient)
1226      {
1227       case E_GADCON_ORIENT_LEFT:
1228         e_util_icon_theme_set(obj, "preferences-position-left");
1229         break;
1230 
1231       case E_GADCON_ORIENT_RIGHT:
1232         e_util_icon_theme_set(obj, "preferences-position-right");
1233         break;
1234 
1235       case E_GADCON_ORIENT_TOP:
1236         e_util_icon_theme_set(obj, "preferences-position-top");
1237         break;
1238 
1239       case E_GADCON_ORIENT_BOTTOM:
1240         e_util_icon_theme_set(obj, "preferences-position-bottom");
1241         break;
1242 
1243       case E_GADCON_ORIENT_CORNER_TL:
1244         e_util_icon_theme_set(obj, "preferences-position-top-left");
1245         break;
1246 
1247       case E_GADCON_ORIENT_CORNER_TR:
1248         e_util_icon_theme_set(obj, "preferences-position-top-right");
1249         break;
1250 
1251       case E_GADCON_ORIENT_CORNER_BL:
1252         e_util_icon_theme_set(obj, "preferences-position-bottom-left");
1253         break;
1254 
1255       case E_GADCON_ORIENT_CORNER_BR:
1256         e_util_icon_theme_set(obj, "preferences-position-bottom-right");
1257         break;
1258 
1259       case E_GADCON_ORIENT_CORNER_LT:
1260         e_util_icon_theme_set(obj, "preferences-position-left-top");
1261         break;
1262 
1263       case E_GADCON_ORIENT_CORNER_RT:
1264         e_util_icon_theme_set(obj, "preferences-position-right-top");
1265         break;
1266 
1267       case E_GADCON_ORIENT_CORNER_LB:
1268         e_util_icon_theme_set(obj, "preferences-position-left-bottom");
1269         break;
1270 
1271       case E_GADCON_ORIENT_CORNER_RB:
1272         e_util_icon_theme_set(obj, "preferences-position-right-bottom");
1273         break;
1274 
1275       default:
1276         e_util_icon_theme_set(obj, "enlightenment");
1277         break;
1278      }
1279 }
1280 
1281 E_API void
e_util_gadcon_orient_menu_item_icon_set(E_Gadcon_Orient orient,E_Menu_Item * mi)1282 e_util_gadcon_orient_menu_item_icon_set(E_Gadcon_Orient orient, E_Menu_Item *mi)
1283 {
1284    switch (orient)
1285      {
1286       case E_GADCON_ORIENT_LEFT:
1287         e_util_menu_item_theme_icon_set(mi, "preferences-position-left");
1288         break;
1289 
1290       case E_GADCON_ORIENT_RIGHT:
1291         e_util_menu_item_theme_icon_set(mi, "preferences-position-right");
1292         break;
1293 
1294       case E_GADCON_ORIENT_TOP:
1295         e_util_menu_item_theme_icon_set(mi, "preferences-position-top");
1296         break;
1297 
1298       case E_GADCON_ORIENT_BOTTOM:
1299         e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom");
1300         break;
1301 
1302       case E_GADCON_ORIENT_CORNER_TL:
1303         e_util_menu_item_theme_icon_set(mi, "preferences-position-top-left");
1304         break;
1305 
1306       case E_GADCON_ORIENT_CORNER_TR:
1307         e_util_menu_item_theme_icon_set(mi, "preferences-position-top-right");
1308         break;
1309 
1310       case E_GADCON_ORIENT_CORNER_BL:
1311         e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom-left");
1312         break;
1313 
1314       case E_GADCON_ORIENT_CORNER_BR:
1315         e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom-right");
1316         break;
1317 
1318       case E_GADCON_ORIENT_CORNER_LT:
1319         e_util_menu_item_theme_icon_set(mi, "preferences-position-left-top");
1320         break;
1321 
1322       case E_GADCON_ORIENT_CORNER_RT:
1323         e_util_menu_item_theme_icon_set(mi, "preferences-position-right-top");
1324         break;
1325 
1326       case E_GADCON_ORIENT_CORNER_LB:
1327         e_util_menu_item_theme_icon_set(mi, "preferences-position-left-bottom");
1328         break;
1329 
1330       case E_GADCON_ORIENT_CORNER_RB:
1331         e_util_menu_item_theme_icon_set(mi, "preferences-position-right-bottom");
1332         break;
1333 
1334       default:
1335         e_util_menu_item_theme_icon_set(mi, "enlightenment");
1336         break;
1337      }
1338 }
1339 
1340 E_API char *
e_util_string_append_char(char * str,size_t * size,size_t * len,char c)1341 e_util_string_append_char(char *str, size_t *size, size_t *len, char c)
1342 {
1343    if (!str)
1344      {
1345         str = malloc(4096);
1346         if (!str) return NULL;
1347         str[0] = 0;
1348         *size = 4096;
1349         *len = 0;
1350      }
1351 
1352    if (*len >= *size - 1)
1353      {
1354         char *str2;
1355 
1356         *size += 1024;
1357         str2 = realloc(str, *size);
1358         if (!str2)
1359           {
1360              *size = 0;
1361              free(str);
1362              return NULL;
1363           }
1364         str = str2;
1365      }
1366 
1367    str[(*len)++] = c;
1368    str[*len] = 0;
1369 
1370    return str;
1371 }
1372 
1373 E_API char *
e_util_string_append_quoted(char * str,size_t * size,size_t * len,const char * src)1374 e_util_string_append_quoted(char *str, size_t *size, size_t *len, const char *src)
1375 {
1376    str = e_util_string_append_char(str, size, len, '\'');
1377    if (!str) return NULL;
1378 
1379    while (*src)
1380      {
1381         if (*src == '\'')
1382           {
1383              str = e_util_string_append_char(str, size, len, '\'');
1384              if (!str) return NULL;
1385              str = e_util_string_append_char(str, size, len, '\\');
1386              if (!str) return NULL;
1387              str = e_util_string_append_char(str, size, len, '\'');
1388              if (!str) return NULL;
1389              str = e_util_string_append_char(str, size, len, '\'');
1390              if (!str) return NULL;
1391           }
1392         else
1393           {
1394              str = e_util_string_append_char(str, size, len, *src);
1395              if (!str) return NULL;
1396           }
1397 
1398         src++;
1399      }
1400 
1401    str = e_util_string_append_char(str, size, len, '\'');
1402    if (!str) return NULL;
1403 
1404    return str;
1405 }
1406 
1407 E_API void
e_util_evas_objects_above_print(Evas_Object * o)1408 e_util_evas_objects_above_print(Evas_Object *o)
1409 {
1410    Evas_Object *a, *oo;
1411 
1412    EINA_SAFETY_ON_NULL_RETURN(o);
1413    a = o;
1414    while ((a = evas_object_above_get(a)))
1415      {
1416         const Eina_List *l, *ll;
1417 
1418         l = evas_object_clipees_get(a);
1419         if (l)
1420           {
1421              fprintf(stderr, "[%p] - %s(%s) %s :: CLIPPEES: ", a, evas_object_type_get(a), evas_object_name_get(a), evas_object_visible_get(a) ? "VISIBLE" : "HIDDEN");
1422              EINA_LIST_FOREACH(l, ll, oo)
1423                fprintf(stderr, "[%p] - %s(%s) %s", oo, evas_object_type_get(oo), evas_object_name_get(oo), ll->next ? "| " : "");
1424           }
1425         else
1426           fprintf(stderr, "[%p] - %s(%s) %s\n", a, evas_object_type_get(a), evas_object_name_get(a), evas_object_visible_get(a) ? "VISIBLE" : "HIDDEN");
1427      }
1428 }
1429 
1430 E_API void
e_util_evas_objects_above_print_smart(Evas_Object * o)1431 e_util_evas_objects_above_print_smart(Evas_Object *o)
1432 {
1433    Evas_Object *a, *oo;
1434 
1435    EINA_SAFETY_ON_NULL_RETURN(o);
1436    a = o;
1437    while ((a = evas_object_above_get(a)))
1438      {
1439         const Eina_List *l, *ll;
1440 
1441         l = evas_object_clipees_get(a);
1442         if (l)
1443           {
1444              fprintf(stderr, "[%p] - %s(%s) %s :: CLIPPEES: ", a, evas_object_type_get(a), evas_object_name_get(a), evas_object_visible_get(a) ? "VISIBLE" : "HIDDEN");
1445              EINA_LIST_FOREACH(l, ll, oo)
1446                fprintf(stderr, "[%p] - %s(%s) %s", oo, evas_object_type_get(oo), evas_object_name_get(oo), ll->next ? "| " : "");
1447              fprintf(stderr, "\n");
1448           }
1449         else if (evas_object_smart_data_get(a))
1450           {
1451              fprintf(stderr, "[%p] - %s(%s) %s :: SMART MEMBERS: ", a, evas_object_type_get(a), evas_object_name_get(a), evas_object_visible_get(a) ? "VISIBLE" : "HIDDEN");
1452              EINA_LIST_FOREACH(evas_object_smart_members_get(a), l, oo)
1453                fprintf(stderr, "[%p] - %s(%s) %s", oo, evas_object_type_get(oo), evas_object_name_get(oo), l->next ? "| " : "");
1454              fprintf(stderr, "\n");
1455           }
1456         else
1457           fprintf(stderr, "[%p] - %s(%s) %s\n", a, evas_object_type_get(a), evas_object_name_get(a), evas_object_visible_get(a) ? "VISIBLE" : "HIDDEN");
1458      }
1459 }
1460 
1461 #if   defined(HAVE_MEMSET_S)
1462 #elif defined(HAVE_EXPLICIT_BZERO)
1463 #elif defined(HAVE_EXPLICIT_MEMSET)
1464 #else
1465 void *(* const volatile __memset_ptr)(void *, int, size_t) = memset;
1466 #endif
1467 
1468 E_API void
e_util_memclear(void * s,size_t n)1469 e_util_memclear(void *s, size_t n)
1470 {
1471    if (n == 0) return;
1472 #if   defined(HAVE_MEMSET_S)
1473    memset_s(s, n, 0, n);
1474 #elif defined(HAVE_EXPLICIT_BZERO)
1475    explicit_bzero(s, n);
1476 #elif defined(HAVE_EXPLICIT_MEMSET)
1477    explicit_memset(s, 0, n);
1478 #else
1479    __memset_ptr(s, 0, n);
1480    __asm__ __volatile__("": :"r"(s) : "memory");
1481 #endif
1482 }
1483 
1484 E_API Ecore_Exe *
e_util_open(const char * exe,void * data)1485 e_util_open(const char *exe, void *data)
1486 {
1487    char *sb;
1488    size_t size = 65536, len;
1489    Ecore_Exe *ret;
1490 
1491    sb = malloc(size);
1492    snprintf(sb, size, "%s/enlightenment_open ", e_prefix_bin_get());
1493    len = strlen(sb);
1494    sb = e_util_string_append_quoted(sb, &size, &len, exe);
1495    ret = e_util_exe_safe_run(sb, data);
1496    free(sb);
1497    return ret;
1498 }
1499 
1500 E_API Ecore_Exe *
e_util_exe_safe_run(const char * cmd,void * data)1501 e_util_exe_safe_run(const char *cmd, void *data)
1502 {
1503    Ecore_Exe_Flags flags = ECORE_EXE_NONE;
1504 
1505 #if (ECORE_VERSION_MAJOR >= 1) && (ECORE_VERSION_MINOR >= 21)
1506    flags |= ECORE_EXE_ISOLATE_IO;
1507 #else
1508    flags |= 1024; // isolate_io is bit 10 .... it will be ignored if
1509                   // efl doesn't do it, so harmless
1510 #endif
1511    return ecore_exe_pipe_run(cmd, flags, data);
1512 }
1513 
1514 static Eina_Bool
str_matches_one(const char * instr,const char ** strset)1515 str_matches_one(const char *instr, const char **strset)
1516 {
1517    int i;
1518 
1519    if ((!instr) || (!strset)) return EINA_FALSE;
1520    for (i = 0; strset[i]; i++)
1521      {
1522         if (!strcmp(strset[i], instr)) return EINA_TRUE;
1523      }
1524    return EINA_FALSE;
1525 }
1526 
1527 E_API E_Util_Action
e_util_key_geometry_action_get(const char * key,int * x,int * y,int dx,int dy)1528 e_util_key_geometry_action_get(const char *key, int *x, int *y, int dx, int dy)
1529 {
1530    const char *k_up[]    = { "Up",     "KP_Up",     "k", "K", "w", "W", NULL };
1531    const char *k_down[]  = { "Down",   "KP_Down",   "j", "J", "s", "S", NULL };
1532    const char *k_left[]  = { "Left",   "KP_Left",   "h", "H", "a", "A", NULL };
1533    const char *k_right[] = { "Right",  "KP_Right",  "l", "L", "d", "D", NULL };
1534    const char *k_done[]  = { "Return", "KP_Enter",  "space",  NULL };
1535    const char *k_abort[] = { "Escape", "BackSpace", "Delete", "x", "X", NULL };
1536 
1537    if      (str_matches_one(key, k_up))    *y -= dy;
1538    else if (str_matches_one(key, k_down))  *y += dy;
1539    else if (str_matches_one(key, k_left))  *x -= dx;
1540    else if (str_matches_one(key, k_right)) *x += dx;
1541    else if (str_matches_one(key, k_done))  return E_UTIL_ACTION_DONE;
1542    else if (str_matches_one(key, k_abort)) return E_UTIL_ACTION_ABORT;
1543    else return E_UTIL_ACTION_NONE;
1544 
1545    return E_UTIL_ACTION_DO;
1546 }
1547