elm_theme: use Eina_File all over the place in an attempt to reduce race condition.

This commit is contained in:
Cedric Bail 2013-11-04 12:17:58 +09:00
parent 1f442e4a8e
commit eaeda2ecdd
2 changed files with 238 additions and 224 deletions

View File

@ -75,6 +75,7 @@
#endif #endif
#define N_(string) (string) #define N_(string) (string)
typedef struct _Elm_Theme_Files Elm_Theme_Files;
typedef struct _Edje_Signal_Data Edje_Signal_Data; typedef struct _Edje_Signal_Data Edje_Signal_Data;
typedef struct _Elm_Config Elm_Config; typedef struct _Elm_Config Elm_Config;
typedef struct _Elm_Module Elm_Module; typedef struct _Elm_Module Elm_Module;
@ -89,11 +90,22 @@ struct _Edje_Signal_Data
void *data; void *data;
}; };
struct _Elm_Theme_Files
{
/*
* We are conserving a list of path even if that's duplicated
* because we expose those directly to the outside world :'(
*/
Eina_List *items;
Eina_List *handles;
};
struct _Elm_Theme struct _Elm_Theme
{ {
Eina_List *overlay; Elm_Theme_Files overlay;
Eina_List *themes; Elm_Theme_Files themes;
Eina_List *extension; Elm_Theme_Files extension;
Eina_Hash *cache; Eina_Hash *cache;
Eina_Hash *cache_data; Eina_Hash *cache_data;
Elm_Theme *ref_theme; Elm_Theme *ref_theme;

View File

@ -8,21 +8,129 @@
static Elm_Theme theme_default = static Elm_Theme theme_default =
{ {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1 { NULL, NULL }, { NULL, NULL }, { NULL, NULL },
NULL, NULL, NULL, NULL, NULL, 1
}; };
static Eina_List *themes = NULL; static Eina_List *themes = NULL;
static Eina_File *
_elm_theme_find_try(Elm_Theme *th, Eina_File *f, const char *group)
{
if (edje_mmap_group_exists(f, group))
{
eina_hash_add(th->cache, group, eina_file_dup(f));
return f;
}
return NULL;
}
static inline void
_elm_theme_item_finalize(Elm_Theme_Files *files,
const char *item,
Eina_File *f)
{
if (!f) return ;
files->items = eina_list_append(files->items,
eina_stringshare_add(item));
files->handles = eina_list_append(files->handles, f);
}
static void
_elm_theme_file_item_add(Elm_Theme_Files *files, const char *item)
{
Eina_Strbuf *buf = NULL;
Eina_File *f = NULL;
const char *home;
home = getenv("HOME") ? getenv("HOME") : "";
buf = eina_strbuf_new();
if ((item[0] == '/') ||
((item[0] == '.') && (item[1] == '/')) ||
((item[0] == '.') && (item[1] == '.') && (item[2] == '/')) ||
((isalpha(item[0])) && (item[1] == ':')))
{
f = eina_file_open(item, EINA_FALSE);
if (!f) goto on_error;
}
else if (((item[0] == '~') && (item[1] == '/')))
{
eina_strbuf_append_printf(buf, "%s/%s", home, item + 2);
f = eina_file_open(eina_strbuf_string_get(buf), EINA_FALSE);
if (!f) goto on_error;
}
else
{
eina_strbuf_append_printf(buf,
"%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj",
home, item);
f = eina_file_open(eina_strbuf_string_get(buf), EINA_FALSE);
_elm_theme_item_finalize(files, item, f);
eina_strbuf_reset(buf);
eina_strbuf_append_printf(buf,
"%s/themes/%s.edj",
_elm_data_dir, item);
f = eina_file_open(eina_strbuf_string_get(buf), EINA_FALSE);
/* Finalize will be done by the common one */
}
_elm_theme_item_finalize(files, item, f);
on_error:
if (buf) eina_strbuf_free(buf);
}
static void
_elm_theme_file_item_del(Elm_Theme_Files *files, const char *str)
{
Eina_List *l, *ll;
Eina_List *l2, *ll2;
const char *item;
str = eina_stringshare_add(str);
l2 = files->handles;
EINA_LIST_FOREACH_SAFE(files->items, l, ll, item)
{
ll2 = l2->next;
if (item == str)
{
eina_file_close(eina_list_data_get(l2));
eina_stringshare_del(item);
files->handles = eina_list_remove_list(files->handles, l2);
files->items = eina_list_remove_list(files->items, l);
}
l2 = ll2;
}
eina_stringshare_del(str);
}
static void
_elm_theme_file_clean(Elm_Theme_Files *files)
{
const char *item;
Eina_File *f;
EINA_LIST_FREE(files->items, item)
eina_stringshare_del(item);
EINA_LIST_FREE(files->handles, f)
eina_file_close(f);
}
static void static void
_elm_theme_clear(Elm_Theme *th) _elm_theme_clear(Elm_Theme *th)
{ {
const char *p; _elm_theme_file_clean(&th->themes);
EINA_LIST_FREE(th->themes, p) _elm_theme_file_clean(&th->overlay);
eina_stringshare_del(p); _elm_theme_file_clean(&th->extension);
EINA_LIST_FREE(th->overlay, p)
eina_stringshare_del(p);
EINA_LIST_FREE(th->extension, p)
eina_stringshare_del(p);
ELM_SAFE_FREE(th->cache, eina_hash_free); ELM_SAFE_FREE(th->cache, eina_hash_free);
ELM_SAFE_FREE(th->cache_data, eina_hash_free); ELM_SAFE_FREE(th->cache_data, eina_hash_free);
@ -36,73 +144,27 @@ _elm_theme_clear(Elm_Theme *th)
} }
} }
static const char * static Eina_File *
_elm_theme_find_try(Elm_Theme *th, const char *f, const char *group)
{
const char *file;
if (edje_file_group_exists(f, group))
{
file = eina_stringshare_add(f);
if (file)
{
eina_hash_add(th->cache, group, file);
return file;
}
}
return NULL;
}
static const char *
_elm_theme_theme_element_try(Elm_Theme *th, const char *home, const char *f, const char *group)
{
char buf[PATH_MAX];
const char *file = NULL;
if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
((isalpha(f[0])) && (f[1] == ':')))
return _elm_theme_find_try(th, f, group);
else if (((f[0] == '~') && (f[1] == '/')))
{
snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
return _elm_theme_find_try(th, buf, group);
}
snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
file = _elm_theme_find_try(th, buf, group);
if (file) return file;
snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
file = _elm_theme_find_try(th, buf, group);
return file;
}
static const char *
_elm_theme_group_file_find(Elm_Theme *th, const char *group) _elm_theme_group_file_find(Elm_Theme *th, const char *group)
{ {
const Eina_List *l; const Eina_List *l;
const char *f; Eina_File *file = eina_hash_find(th->cache, group);
static const char *home = NULL;
const char *file = eina_hash_find(th->cache, group);
if (file) return file; if (file) return file;
if (!home)
EINA_LIST_FOREACH(th->overlay.handles, l, file)
{ {
home = getenv("HOME"); file = _elm_theme_find_try(th, file, group);
if (!home) home = "";
}
EINA_LIST_FOREACH(th->overlay, l, f)
{
file = _elm_theme_theme_element_try(th, home, f, group);
if (file) return file; if (file) return file;
} }
EINA_LIST_FOREACH(th->themes, l, f) EINA_LIST_FOREACH(th->themes.handles, l, file)
{ {
file = _elm_theme_theme_element_try(th, home, f, group); file = _elm_theme_find_try(th, file, group);
if (file) return file; if (file) return file;
} }
EINA_LIST_FOREACH(th->extension, l, f) EINA_LIST_FOREACH(th->extension.handles, l, file)
{ {
file = _elm_theme_theme_element_try(th, home, f, group); file = _elm_theme_find_try(th, file, group);
if (file) return file; if (file) return file;
} }
if (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group); if (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group);
@ -110,12 +172,12 @@ _elm_theme_group_file_find(Elm_Theme *th, const char *group)
} }
static const char * static const char *
_elm_theme_find_data_try(Elm_Theme *th, const char *f, const char *key) _elm_theme_find_data_try(Elm_Theme *th, const Eina_File *f, const char *key)
{ {
char *data; char *data;
const char *t; const char *t;
data = edje_file_data_get(f, key); data = edje_mmap_data_get(f, key);
t = eina_stringshare_add(data); t = eina_stringshare_add(data);
free(data); free(data);
if (t) if (t)
@ -126,56 +188,28 @@ _elm_theme_find_data_try(Elm_Theme *th, const char *f, const char *key)
return NULL; return NULL;
} }
static const char *
_elm_theme_theme_data_try(Elm_Theme *th, const char *home, const char *f, const char *key)
{
char buf[PATH_MAX];
const char *data = NULL;
if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
((isalpha(f[0])) && (f[1] == ':')))
return _elm_theme_find_data_try(th, f, key);
else if (((f[0] == '~') && (f[1] == '/')))
{
snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
return _elm_theme_find_try(th, buf, key);
}
snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
data = _elm_theme_find_data_try(th, buf, key);
if (data) return data;
snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
data = _elm_theme_find_data_try(th, buf, key);
return data;
}
static const char * static const char *
_elm_theme_data_find(Elm_Theme *th, const char *key) _elm_theme_data_find(Elm_Theme *th, const char *key)
{ {
const Eina_List *l; const Eina_List *l;
const char *f; const Eina_File *f;
static const char *home = NULL;
const char *data = eina_hash_find(th->cache_data, key);
const char *data = eina_hash_find(th->cache_data, key);
if (data) return data; if (data) return data;
if (!home)
EINA_LIST_FOREACH(th->overlay.handles, l, f)
{ {
home = getenv("HOME"); data = _elm_theme_find_data_try(th, f, key);
if (!home) home = "";
}
EINA_LIST_FOREACH(th->overlay, l, f)
{
data = _elm_theme_theme_data_try(th, home, f, key);
if (data) return data; if (data) return data;
} }
EINA_LIST_FOREACH(th->themes, l, f) EINA_LIST_FOREACH(th->themes.handles, l, f)
{ {
data = _elm_theme_theme_data_try(th, home, f, key); data = _elm_theme_find_data_try(th, f, key);
if (data) return data; if (data) return data;
} }
EINA_LIST_FOREACH(th->extension, l, f) EINA_LIST_FOREACH(th->extension.handles, l, f)
{ {
data = _elm_theme_theme_data_try(th, home, f, key); data = _elm_theme_find_data_try(th, f, key);
if (data) return data; if (data) return data;
} }
if (th->ref_theme) return _elm_theme_data_find(th->ref_theme, key); if (th->ref_theme) return _elm_theme_data_find(th->ref_theme, key);
@ -252,7 +286,7 @@ _elm_theme_object_icon_set(Evas_Object *o,
Eina_Bool Eina_Bool
_elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *group, const char *style) _elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *group, const char *style)
{ {
const char *file; Eina_File *file;
char buf2[1024]; char buf2[1024];
if ((!clas) || (!group) || (!style)) return EINA_FALSE; if ((!clas) || (!group) || (!style)) return EINA_FALSE;
@ -262,11 +296,13 @@ _elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *grou
file = _elm_theme_group_file_find(th, buf2); file = _elm_theme_group_file_find(th, buf2);
if (file) if (file)
{ {
if (edje_object_file_set(o, file, buf2)) return EINA_TRUE; if (edje_object_mmap_set(o, file, buf2)) return EINA_TRUE;
else else
{ {
DBG("could not set theme group '%s' from file '%s': %s", DBG("could not set theme group '%s' from file '%s': %s",
buf2, file, edje_load_error_str(edje_object_load_error_get(o))); buf2,
eina_file_filename_get(file),
edje_load_error_str(edje_object_load_error_get(o)));
} }
} }
@ -274,9 +310,11 @@ _elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *grou
snprintf(buf2, sizeof(buf2), "elm/%s/%s/default", clas, group); snprintf(buf2, sizeof(buf2), "elm/%s/%s/default", clas, group);
file = _elm_theme_group_file_find(th, buf2); file = _elm_theme_group_file_find(th, buf2);
if (!file) return EINA_FALSE; if (!file) return EINA_FALSE;
if (edje_object_file_set(o, file, buf2)) return EINA_TRUE; if (edje_object_mmap_set(o, file, buf2)) return EINA_TRUE;
DBG("could not set theme group '%s' from file '%s': %s", DBG("could not set theme group '%s' from file '%s': %s",
buf2, file, edje_load_error_str(edje_object_load_error_get(o))); buf2,
eina_file_filename_get(file),
edje_load_error_str(edje_object_load_error_get(o)));
return EINA_FALSE; return EINA_FALSE;
} }
@ -287,7 +325,7 @@ _elm_theme_icon_set(Elm_Theme *th,
const char *group, const char *group,
const char *style) const char *style)
{ {
const char *file; Eina_File *file;
char buf2[1024]; char buf2[1024];
int w, h; int w, h;
@ -296,7 +334,7 @@ _elm_theme_icon_set(Elm_Theme *th,
file = _elm_theme_group_file_find(th, buf2); file = _elm_theme_group_file_find(th, buf2);
if (file) if (file)
{ {
elm_image_file_set(o, file, buf2); elm_image_mmap_set(o, file, buf2);
elm_image_object_size_get(o, &w, &h); elm_image_object_size_get(o, &w, &h);
if (w > 0) return EINA_TRUE; if (w > 0) return EINA_TRUE;
} }
@ -305,7 +343,7 @@ _elm_theme_icon_set(Elm_Theme *th,
if (!file) return EINA_FALSE; if (!file) return EINA_FALSE;
elm_image_file_set(o, file, buf2); elm_image_mmap_set(o, file, buf2);
elm_image_object_size_get(o, &w, &h); elm_image_object_size_get(o, &w, &h);
return w > 0; return w > 0;
@ -315,6 +353,7 @@ Eina_Bool
_elm_theme_parse(Elm_Theme *th, const char *theme) _elm_theme_parse(Elm_Theme *th, const char *theme)
{ {
Eina_List *names = NULL; Eina_List *names = NULL;
Eina_File *f;
const char *p, *pe; const char *p, *pe;
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
@ -363,13 +402,15 @@ _elm_theme_parse(Elm_Theme *th, const char *theme)
if (p) names = eina_list_append(names, p); if (p) names = eina_list_append(names, p);
} }
if (th->cache) eina_hash_free(th->cache); if (th->cache) eina_hash_free(th->cache);
th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del)); th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_file_close));
if (th->cache_data) eina_hash_free(th->cache_data); if (th->cache_data) eina_hash_free(th->cache_data);
th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del)); th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
EINA_LIST_FREE(th->themes, p) eina_stringshare_del(p); EINA_LIST_FREE(th->themes.items, p) eina_stringshare_del(p);
EINA_LIST_FREE(th->themes.handles, f) eina_file_close(f);
th->themes = names; EINA_LIST_FREE(names, p)
_elm_theme_file_item_add(&th->themes, p);
return EINA_TRUE; return EINA_TRUE;
} }
@ -391,7 +432,7 @@ elm_theme_new(void)
Elm_Theme *th = calloc(1, sizeof(Elm_Theme)); Elm_Theme *th = calloc(1, sizeof(Elm_Theme));
if (!th) return NULL; if (!th) return NULL;
th->ref = 1; th->ref = 1;
th->themes = eina_list_append(th->themes, eina_stringshare_add("default")); _elm_theme_file_item_add(&th->themes, "default");
themes = eina_list_append(themes, th); themes = eina_list_append(themes, th);
return th; return th;
} }
@ -409,12 +450,24 @@ elm_theme_free(Elm_Theme *th)
} }
} }
static void
elm_theme_files_copy(Elm_Theme_Files *dst, Elm_Theme_Files *src)
{
const Eina_List *l;
const Eina_File *f;
const char *item;
EINA_LIST_FOREACH(src->items, l, item)
dst->items = eina_list_append(dst->items,
eina_stringshare_ref(item));
EINA_LIST_FOREACH(src->handles, l, f)
dst->handles = eina_list_append(dst->handles,
eina_file_dup(f));
}
EAPI void EAPI void
elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst) elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst)
{ {
const Eina_List *l;
const char *f;
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
if (!thdst) thdst = &(theme_default); if (!thdst) thdst = &(theme_default);
_elm_theme_clear(thdst); _elm_theme_clear(thdst);
@ -425,21 +478,10 @@ elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst)
eina_list_append(thdst->ref_theme->referrers, thdst); eina_list_append(thdst->ref_theme->referrers, thdst);
thdst->ref_theme->ref++; thdst->ref_theme->ref++;
} }
EINA_LIST_FOREACH(th->overlay, l, f) elm_theme_files_copy(&thdst->overlay, &th->overlay);
{ elm_theme_files_copy(&thdst->themes, &th->themes);
const char *s = eina_stringshare_add(f); elm_theme_files_copy(&thdst->extension, &th->extension);
if (s) thdst->overlay = eina_list_append(thdst->overlay, s);
}
EINA_LIST_FOREACH(th->themes, l, f)
{
const char *s = eina_stringshare_add(f);
if (s) thdst->themes = eina_list_append(thdst->themes, s);
}
EINA_LIST_FOREACH(th->extension, l, f)
{
const char *s = eina_stringshare_add(f);
if (s) thdst->extension = eina_list_append(thdst->extension, s);
}
if (th->theme) thdst->theme = eina_stringshare_add(th->theme); if (th->theme) thdst->theme = eina_stringshare_add(th->theme);
elm_theme_flush(thdst); elm_theme_flush(thdst);
} }
@ -476,29 +518,18 @@ elm_theme_default_get(void)
EAPI void EAPI void
elm_theme_overlay_add(Elm_Theme *th, const char *item) elm_theme_overlay_add(Elm_Theme *th, const char *item)
{ {
const char *f = eina_stringshare_add(item); if (!item) return;
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
if (f) th->overlay = eina_list_prepend(th->overlay, f); _elm_theme_file_item_add(&th->overlay, item);
elm_theme_flush(th); elm_theme_flush(th);
} }
EAPI void EAPI void
elm_theme_overlay_del(Elm_Theme *th, const char *item) elm_theme_overlay_del(Elm_Theme *th, const char *item)
{ {
const Eina_List *l; if (!item) return ;
const char *f, *s;
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
s = eina_stringshare_add(item); _elm_theme_file_item_del(&th->overlay, item);
EINA_LIST_FOREACH(th->overlay, l, f)
if (f == s)
{
eina_stringshare_del(f);
th->overlay = eina_list_remove_list(th->overlay, (Eina_List *)l);
break;
}
eina_stringshare_del(s);
elm_theme_flush(th); elm_theme_flush(th);
} }
@ -506,35 +537,24 @@ EAPI const Eina_List *
elm_theme_overlay_list_get(const Elm_Theme *th) elm_theme_overlay_list_get(const Elm_Theme *th)
{ {
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
return th->overlay; return th->overlay.items;
} }
EAPI void EAPI void
elm_theme_extension_add(Elm_Theme *th, const char *item) elm_theme_extension_add(Elm_Theme *th, const char *item)
{ {
const char *f = eina_stringshare_add(item); if (!item) return ;
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
if (f) th->extension = eina_list_append(th->extension, f); _elm_theme_file_item_add(&th->extension, item);
elm_theme_flush(th); elm_theme_flush(th);
} }
EAPI void EAPI void
elm_theme_extension_del(Elm_Theme *th, const char *item) elm_theme_extension_del(Elm_Theme *th, const char *item)
{ {
const Eina_List *l; if (!item) return ;
const char *f, *s;
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
s = eina_stringshare_add(item); _elm_theme_file_item_del(&th->extension, item);
EINA_LIST_FOREACH(th->extension, l, f)
if (f == s)
{
eina_stringshare_del(f);
th->extension = eina_list_remove_list(th->extension, (Eina_List *)l);
break;
}
eina_stringshare_del(s);
elm_theme_flush(th); elm_theme_flush(th);
} }
@ -542,7 +562,7 @@ EAPI const Eina_List *
elm_theme_extension_list_get(const Elm_Theme *th) elm_theme_extension_list_get(const Elm_Theme *th)
{ {
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
return th->extension; return th->extension.items;
} }
EAPI void EAPI void
@ -567,7 +587,7 @@ elm_theme_get(Elm_Theme *th)
const char *f; const char *f;
buf = eina_strbuf_new(); buf = eina_strbuf_new();
EINA_LIST_FOREACH(th->themes, l, f) EINA_LIST_FOREACH(th->themes.items, l, f)
{ {
while (*f) while (*f)
{ {
@ -589,7 +609,7 @@ EAPI const Eina_List *
elm_theme_list_get(const Elm_Theme *th) elm_theme_list_get(const Elm_Theme *th)
{ {
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
return th->themes; return th->themes.items;
} }
EAPI char * EAPI char *
@ -646,7 +666,7 @@ elm_theme_flush(Elm_Theme *th)
{ {
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
if (th->cache) eina_hash_free(th->cache); if (th->cache) eina_hash_free(th->cache);
th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del)); th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_file_close));
if (th->cache_data) eina_hash_free(th->cache_data); if (th->cache_data) eina_hash_free(th->cache_data);
th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del)); th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
_elm_win_rescale(th, EINA_TRUE); _elm_win_rescale(th, EINA_TRUE);
@ -773,80 +793,62 @@ elm_theme_group_path_find(Elm_Theme *th, const char *group)
{ {
EINA_SAFETY_ON_NULL_RETURN_VAL(group, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(group, NULL);
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
return _elm_theme_group_file_find(th, group); return eina_file_filename_get(_elm_theme_group_file_find(th, group));
} }
static Eina_List * static Eina_List *
_file_find_append(Eina_List *list, const char *home, const char *f) _elm_theme_file_group_base_list(Eina_List *list,
Eina_List *handles,
const char *base, int len)
{ {
char buf[PATH_MAX]; Eina_Stringshare *c, *c2;
Eina_List *coll;
Eina_List *in, *l, *ll;
Eina_File *f;
if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) || EINA_LIST_FOREACH(handles, l, f)
((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
((isalpha(f[0])) && (f[1] == ':')))
{ {
list = eina_list_append(list, eina_stringshare_add(f)); coll = edje_mmap_collection_list(f);
} EINA_LIST_FOREACH(coll, ll, c)
else if (((f[0] == '~') && (f[1] == '/')))
{ {
snprintf(buf, sizeof(buf), "%s/%s", home, f + 2); // if base == start of collection str
list = eina_list_append(list, eina_stringshare_add(buf)); if (!strncmp(c, base, len))
}
else
{ {
snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f); // check if already in list
list = eina_list_append(list, eina_stringshare_add(buf)); EINA_LIST_FOREACH(list, in, c2)
snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f); if (c == c2)
list = eina_list_append(list, eina_stringshare_add(buf)); break;
// if not already in list append shared str to list
if (!in)
list = eina_list_append(list, eina_stringshare_ref(c));
} }
}
edje_mmap_collection_list_free(coll);
}
return list; return list;
} }
EAPI Eina_List * EAPI Eina_List *
elm_theme_group_base_list(Elm_Theme *th, const char *base) elm_theme_group_base_list(Elm_Theme *th, const char *base)
{ {
Eina_List *list = NULL, *files = NULL, *coll, *l; Eina_List *list;
int len; int len;
Eina_Stringshare *c, *c2, *f;
static const char *home = NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(base, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(base, NULL);
if (!th) th = &(theme_default); if (!th) th = &(theme_default);
// XXX: look results up in a hash for speed // XXX: look results up in a hash for speed
len = strlen(base); len = strlen(base);
if (!home) // get homedir once only
{
home = getenv("HOME");
if (!home) home = "";
}
// go through overlay, themes and extensions in that order and build list
EINA_LIST_FOREACH(th->overlay, l, f)
files = _file_find_append(files, home, f);
EINA_LIST_FOREACH(th->themes, l, f)
files = _file_find_append(files, home, f);
EINA_LIST_FOREACH(th->extension, l, f)
files = _file_find_append(files, home, f);
// go through all possible theme files and find collections that match // go through all possible theme files and find collections that match
EINA_LIST_FREE(files, f) list = _elm_theme_file_group_base_list(NULL, th->overlay.handles,
{ base, len);
coll = edje_file_collection_list(f); list = _elm_theme_file_group_base_list(list, th->themes.handles,
EINA_LIST_FREE(coll, c) base, len);
{ list = _elm_theme_file_group_base_list(list, th->extension.handles,
if (!strncmp(c, base, len)) // if base == start of collection str base, len);
{
EINA_LIST_FOREACH(list, l, c2) // check if already in list
{
if (!strcmp(c, c2)) break;
}
if (!l) // if not already in list append shared str to list
{
c2 = eina_stringshare_add(c);
list = eina_list_append(list, c2);
}
}
eina_stringshare_del(c);
}
}
// sort the list nicely at the end // sort the list nicely at the end
list = eina_list_sort(list, 0, EINA_COMPARE_CB(strcmp)); list = eina_list_sort(list, 0, EINA_COMPARE_CB(strcmp));
// XXX: store results in hash for fast lookup... // XXX: store results in hash for fast lookup...