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_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_clear(Elm_Theme *th)
+_elm_theme_file_item_add(Elm_Theme_Files *files, const char *item)
{
- const char *p;
- EINA_LIST_FREE(th->themes, p)
- eina_stringshare_del(p);
- EINA_LIST_FREE(th->overlay, p)
- eina_stringshare_del(p);
- EINA_LIST_FREE(th->extension, p)
- eina_stringshare_del(p);
+ Eina_Strbuf *buf = NULL;
+ Eina_File *f = NULL;
+ const char *home;
- ELM_SAFE_FREE(th->cache, eina_hash_free);
- ELM_SAFE_FREE(th->cache_data, eina_hash_free);
- ELM_SAFE_FREE(th->theme, eina_stringshare_del);
- if (th->ref_theme)
+ 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] == ':')))
{
- th->ref_theme->referrers =
- eina_list_remove(th->ref_theme->referrers, th);
- elm_theme_free(th->ref_theme);
- th->ref_theme = NULL;
+ 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 const char *
-_elm_theme_find_try(Elm_Theme *th, const char *f, const char *group)
+static void
+_elm_theme_file_item_del(Elm_Theme_Files *files, const char *str)
{
- const char *file;
+ Eina_List *l, *ll;
+ Eina_List *l2, *ll2;
+ const char *item;
+
+ str = eina_stringshare_add(str);
+ l2 = files->handles;
- if (edje_file_group_exists(f, group))
+ EINA_LIST_FOREACH_SAFE(files->items, l, ll, item)
{
- file = eina_stringshare_add(f);
- if (file)
+ ll2 = l2->next;
+
+ if (item == str)
{
- eina_hash_add(th->cache, group, file);
- return file;
+ 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;
}
- return NULL;
+
+ eina_stringshare_del(str);
}
-static const char *
-_elm_theme_theme_element_try(Elm_Theme *th, const char *home, const char *f, const char *group)
+static void
+_elm_theme_file_clean(Elm_Theme_Files *files)
{
- char buf[PATH_MAX];
- const char *file = NULL;
+ const char *item;
+ Eina_File *f;
- 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] == '/')))
+ EINA_LIST_FREE(files->items, item)
+ eina_stringshare_del(item);
+ EINA_LIST_FREE(files->handles, f)
+ eina_file_close(f);
+}
+
+static void
+_elm_theme_clear(Elm_Theme *th)
+{
+ _elm_theme_file_clean(&th->themes);
+ _elm_theme_file_clean(&th->overlay);
+ _elm_theme_file_clean(&th->extension);
+
+ ELM_SAFE_FREE(th->cache, eina_hash_free);
+ ELM_SAFE_FREE(th->cache_data, eina_hash_free);
+ ELM_SAFE_FREE(th->theme, eina_stringshare_del);
+ if (th->ref_theme)
{
- snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
- return _elm_theme_find_try(th, buf, group);
+ th->ref_theme->referrers =
+ eina_list_remove(th->ref_theme->referrers, th);
+ elm_theme_free(th->ref_theme);
+ th->ref_theme = NULL;
}
- 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 *
+static Eina_File *
_elm_theme_group_file_find(Elm_Theme *th, const char *group)
{
const Eina_List *l;
- const char *f;
- static const char *home = NULL;
- const char *file = eina_hash_find(th->cache, group);
+ Eina_File *file = eina_hash_find(th->cache, group);
if (file) return file;
- if (!home)
- {
- home = getenv("HOME");
- if (!home) home = "";
- }
- EINA_LIST_FOREACH(th->overlay, l, f)
+
+ EINA_LIST_FOREACH(th->overlay.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;
}
- 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;
}
- 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 (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group);
}
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;
const char *t;
- data = edje_file_data_get(f, key);
+ data = edje_mmap_data_get(f, key);
t = eina_stringshare_add(data);
free(data);
if (t)
}
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 *
_elm_theme_data_find(Elm_Theme *th, const char *key)
{
const Eina_List *l;
- const char *f;
- static const char *home = NULL;
- const char *data = eina_hash_find(th->cache_data, key);
+ const Eina_File *f;
+ const char *data = eina_hash_find(th->cache_data, key);
if (data) return data;
- if (!home)
- {
- home = getenv("HOME");
- if (!home) home = "";
- }
- EINA_LIST_FOREACH(th->overlay, l, f)
+
+ EINA_LIST_FOREACH(th->overlay.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;
}
- 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;
}
- 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 (th->ref_theme) return _elm_theme_data_find(th->ref_theme, key);
Eina_Bool
_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];
if ((!clas) || (!group) || (!style)) return EINA_FALSE;
file = _elm_theme_group_file_find(th, buf2);
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
{
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)));
}
}
snprintf(buf2, sizeof(buf2), "elm/%s/%s/default", clas, group);
file = _elm_theme_group_file_find(th, buf2);
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",
- 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;
}
const char *group,
const char *style)
{
- const char *file;
+ Eina_File *file;
char buf2[1024];
int w, h;
file = _elm_theme_group_file_find(th, buf2);
if (file)
{
- elm_image_file_set(o, file, buf2);
+ elm_image_mmap_set(o, file, buf2);
elm_image_object_size_get(o, &w, &h);
if (w > 0) return EINA_TRUE;
}
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);
return w > 0;
_elm_theme_parse(Elm_Theme *th, const char *theme)
{
Eina_List *names = NULL;
+ Eina_File *f;
const char *p, *pe;
if (!th) th = &(theme_default);
if (p) names = eina_list_append(names, p);
}
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);
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;
}
Elm_Theme *th = calloc(1, sizeof(Elm_Theme));
if (!th) return NULL;
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);
return th;
}
}
}
-EAPI void
-elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst)
+static void
+elm_theme_files_copy(Elm_Theme_Files *dst, Elm_Theme_Files *src)
{
const Eina_List *l;
- const char *f;
+ 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
+elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst)
+{
if (!th) th = &(theme_default);
if (!thdst) thdst = &(theme_default);
_elm_theme_clear(thdst);
eina_list_append(thdst->ref_theme->referrers, thdst);
thdst->ref_theme->ref++;
}
- EINA_LIST_FOREACH(th->overlay, l, f)
- {
- const char *s = eina_stringshare_add(f);
- 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);
- }
+ elm_theme_files_copy(&thdst->overlay, &th->overlay);
+ elm_theme_files_copy(&thdst->themes, &th->themes);
+ elm_theme_files_copy(&thdst->extension, &th->extension);
+
if (th->theme) thdst->theme = eina_stringshare_add(th->theme);
elm_theme_flush(thdst);
}
EAPI void
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 (f) th->overlay = eina_list_prepend(th->overlay, f);
+ _elm_theme_file_item_add(&th->overlay, item);
elm_theme_flush(th);
}
EAPI void
elm_theme_overlay_del(Elm_Theme *th, const char *item)
{
- const Eina_List *l;
- const char *f, *s;
-
+ if (!item) return ;
if (!th) th = &(theme_default);
- s = eina_stringshare_add(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_file_item_del(&th->overlay, item);
elm_theme_flush(th);
}
elm_theme_overlay_list_get(const Elm_Theme *th)
{
if (!th) th = &(theme_default);
- return th->overlay;
+ return th->overlay.items;
}
EAPI void
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 (f) th->extension = eina_list_append(th->extension, f);
+ _elm_theme_file_item_add(&th->extension, item);
elm_theme_flush(th);
}
EAPI void
elm_theme_extension_del(Elm_Theme *th, const char *item)
{
- const Eina_List *l;
- const char *f, *s;
-
+ if (!item) return ;
if (!th) th = &(theme_default);
- s = eina_stringshare_add(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_file_item_del(&th->extension, item);
elm_theme_flush(th);
}
elm_theme_extension_list_get(const Elm_Theme *th)
{
if (!th) th = &(theme_default);
- return th->extension;
+ return th->extension.items;
}
EAPI void
const char *f;
buf = eina_strbuf_new();
- EINA_LIST_FOREACH(th->themes, l, f)
+ EINA_LIST_FOREACH(th->themes.items, l, f)
{
while (*f)
{
elm_theme_list_get(const Elm_Theme *th)
{
if (!th) th = &(theme_default);
- return th->themes;
+ return th->themes.items;
}
EAPI char *
{
if (!th) th = &(theme_default);
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);
th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
_elm_win_rescale(th, EINA_TRUE);
{
EINA_SAFETY_ON_NULL_RETURN_VAL(group, NULL);
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 *
-_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] == '/')) ||
- ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
- ((isalpha(f[0])) && (f[1] == ':')))
+ EINA_LIST_FOREACH(handles, l, f)
{
- list = eina_list_append(list, eina_stringshare_add(f));
- }
- else if (((f[0] == '~') && (f[1] == '/')))
- {
- snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
- list = eina_list_append(list, eina_stringshare_add(buf));
- }
- else
- {
- snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
- list = eina_list_append(list, eina_stringshare_add(buf));
- snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
- list = eina_list_append(list, eina_stringshare_add(buf));
+ coll = edje_mmap_collection_list(f);
+ EINA_LIST_FOREACH(coll, ll, c)
+ {
+ // if base == start of collection str
+ if (!strncmp(c, base, len))
+ {
+ // check if already in list
+ EINA_LIST_FOREACH(list, in, c2)
+ if (c == c2)
+ 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;
}
EAPI Eina_List *
elm_theme_group_base_list(Elm_Theme *th, const char *base)
{
- Eina_List *list = NULL, *files = NULL, *coll, *l;
+ Eina_List *list;
int len;
- Eina_Stringshare *c, *c2, *f;
- static const char *home = NULL;
+
EINA_SAFETY_ON_NULL_RETURN_VAL(base, NULL);
if (!th) th = &(theme_default);
// XXX: look results up in a hash for speed
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
- EINA_LIST_FREE(files, f)
- {
- coll = edje_file_collection_list(f);
- EINA_LIST_FREE(coll, c)
- {
- if (!strncmp(c, base, len)) // if base == start of collection str
- {
- 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);
- }
- }
+ list = _elm_theme_file_group_base_list(NULL, th->overlay.handles,
+ base, len);
+ list = _elm_theme_file_group_base_list(list, th->themes.handles,
+ base, len);
+ list = _elm_theme_file_group_base_list(list, th->extension.handles,
+ base, len);
+
// sort the list nicely at the end
list = eina_list_sort(list, 0, EINA_COMPARE_CB(strcmp));
// XXX: store results in hash for fast lookup...