/* * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 */ #include "e.h" /* local subsystem functions */ typedef struct _E_Theme_Result E_Theme_Result; struct _E_Theme_Result { const char *file; const char *cache; Evas_Hash *quickfind; }; static Evas_Bool _e_theme_mappings_free_cb(Evas_Hash *hash, const char *key, void *data, void *fdata); static Evas_Bool _e_theme_mappings_quickfind_free_cb(Evas_Hash *hash, const char *key, void *data, void *fdata); static void _e_theme_category_register(const char *category); static Evas_List *_e_theme_collection_item_register(Evas_List *list, const char *name); static Evas_List *_e_theme_collection_items_find(const char *base, const char *collname); /* local subsystem globals */ static Evas_Hash *mappings = NULL; static Evas_Hash *group_cache = NULL; static Evas_List *categories = NULL; static Evas_List *transitions = NULL; static Evas_List *borders = NULL; static Evas_List *shelfs = NULL; /* externally accessible functions */ EAPI int e_theme_init(void) { Evas_List *l; /* this is a fallback that is ALWAYS there - if all fails things will */ /* always fall back to the default theme. the rest after this are config */ /* values users can set */ e_theme_file_set("base", "default.edj"); for (l = e_config->themes; l; l = l->next) { E_Config_Theme *et; char buf[256]; et = l->data; snprintf(buf, sizeof(buf), "base/%s", et->category); e_theme_file_set(buf, et->file); } /* Find transitions */ transitions = _e_theme_collection_items_find("base/theme/transitions", "e/transitions"); borders = _e_theme_collection_items_find("base/theme/borders", "e/widgets/border"); shelfs = _e_theme_collection_items_find("base/theme/shelf", "e/shelf"); return 1; } /* * this is used to sewt the theme for a CATEGORY of e17. "base" is always set * to the default theme - because if a selected theme for lest say base/theme * does not provide theme elements it can default back to the default theme. * * the idea is you can actually set a different theme for different parts of * the desktop... :) * * other possible categories... * e_theme_file_set("base/theme/about", "default.edj"); * e_theme_file_set("base/theme/borders", "default.edj"); * e_theme_file_set("base/theme/background", "default.edj"); * e_theme_file_set("base/theme/configure", "default.edj"); * e_theme_file_set("base/theme/dialog", "default.edj"); * e_theme_file_set("base/theme/menus", "default.edj"); * e_theme_file_set("base/theme/error", "default.edj"); * e_theme_file_set("base/theme/gadman", "default.edj"); * e_theme_file_set("base/theme/dnd", "default.edj"); * e_theme_file_set("base/theme/icons", "default.edj"); * e_theme_file_set("base/theme/pointer", "default.edj"); * e_theme_file_set("base/theme/transitions", "default.edj"); * e_theme_file_set("base/theme/widgets", "default.edj"); * e_theme_file_set("base/theme/winlist", "default.edj"); * e_theme_file_set("base/theme/modules", "default.edj"); * e_theme_file_set("base/theme/modules/pager", "default.edj"); * e_theme_file_set("base/theme/modules/ibar", "default.edj"); * e_theme_file_set("base/theme/modules/ibox", "default.edj"); * e_theme_file_set("base/theme/modules/clock", "default.edj"); * e_theme_file_set("base/theme/modules/battery", "default.edj"); * e_theme_file_set("base/theme/modules/cpufreq", "default.edj"); * e_theme_file_set("base/theme/modules/start", "default.edj"); * e_theme_file_set("base/theme/modules/temperature", "default.edj"); */ EAPI int e_theme_shutdown(void) { if (mappings) { evas_hash_foreach(mappings, _e_theme_mappings_free_cb, NULL); evas_hash_free(mappings); mappings = NULL; } if (group_cache) { evas_hash_free(group_cache); group_cache = NULL; } while (categories) { evas_stringshare_del(categories->data); categories = evas_list_remove_list(categories, categories); } while (transitions) { evas_stringshare_del(transitions->data); transitions = evas_list_remove_list(transitions, transitions); } while (borders) { evas_stringshare_del(borders->data); borders = evas_list_remove_list(borders, borders); } while (shelfs) { evas_stringshare_del(shelfs->data); shelfs = evas_list_remove_list(shelfs, shelfs); } return 1; } EAPI int e_theme_edje_object_set(Evas_Object *o, const char *category, const char *group) { E_Theme_Result *res; char buf[256]; char *p; /* find category -> edje mapping */ _e_theme_category_register(category); res = evas_hash_find(mappings, category); if (res) { const char *str; /* if found check cached path */ str = res->cache; if (!str) { /* no cached path */ str = res->file; /* if its not an absolute path find it */ if (str[0] != '/') str = e_path_find(path_themes, str); /* save cached value */ if (str) res->cache = str; } if (str) { void *tres; int ok; snprintf(buf, sizeof(buf), "%s/::/%s", str, group); tres = evas_hash_find(group_cache, buf); if (!tres) { ok = edje_object_file_set(o, str, group); /* save in the group cache hash */ if (ok) group_cache = evas_hash_add(group_cache, buf, res); else group_cache = evas_hash_add(group_cache, buf, (void *)1); } else if (tres == (void *)1) ok = 0; else ok = 1; if (ok) { if (tres) edje_object_file_set(o, str, group); return 1; } } } /* no mapping or set failed - fall back */ strncpy(buf, category, sizeof(buf) - 1); buf[sizeof(buf) - 1] = 0; /* shorten string up to and not including last / char */ p = strrchr(buf, '/'); if (p) *p = 0; /* no / anymore - we are already as far back as we can go */ else return 0; /* try this category */ return e_theme_edje_object_set(o, buf, group); } EAPI const char * e_theme_edje_file_get(const char *category, const char *group) { E_Theme_Result *res; char buf[4096]; const char *q; char *p; /* find category -> edje mapping */ _e_theme_category_register(category); res = evas_hash_find(mappings, category); if (res) { const char *str; /* if found check cached path */ str = res->cache; if (!str) { /* no cached path */ str = res->file; /* if its not an absolute path find it */ if (str[0] != '/') str = e_path_find(path_themes, str); /* save cached value */ if (str) res->cache = str; } if (str) { void *tres; Evas_List *coll, *l; int ok; snprintf(buf, sizeof(buf), "%s/::/%s", str, group); tres = evas_hash_find(group_cache, buf); if (!tres) { /* if the group exists - return */ if (!res->quickfind) { /* great a quick find hash of all group entires */ coll = edje_file_collection_list(str); for (l = coll; l; l = l->next) { q = evas_stringshare_add(l->data); res->quickfind = evas_hash_direct_add(res->quickfind, q, q); } if (coll) edje_file_collection_list_free(coll); } /* save in the group cache hash */ if (evas_hash_find(res->quickfind, group)) { group_cache = evas_hash_add(group_cache, buf, res); ok = 1; } else { group_cache = evas_hash_add(group_cache, buf, (void *)1); ok = 0; } } else if (tres == (void *)1) /* special pointer "1" == not there */ ok = 0; else ok = 1; if (ok) return str; } } /* no mapping or set failed - fall back */ strncpy(buf, category, sizeof(buf) - 1); buf[sizeof(buf) - 1] = 0; /* shorten string up to and not including last / char */ p = strrchr(buf, '/'); if (p) *p = 0; /* no / anymore - we are already as far back as we can go */ else return ""; /* try this category */ return e_theme_edje_file_get(buf, group); } EAPI void e_theme_file_set(const char *category, const char *file) { E_Theme_Result *res; if (group_cache) { evas_hash_free(group_cache); group_cache = NULL; } _e_theme_category_register(category); res = evas_hash_find(mappings, category); if (res) { mappings = evas_hash_del(mappings, category, res); if (res->file) { e_filereg_deregister(res->file); evas_stringshare_del(res->file); } if (res->cache) evas_stringshare_del(res->cache); free(res); } res = calloc(1, sizeof(E_Theme_Result)); res->file = evas_stringshare_add(file); e_filereg_register(res->file); mappings = evas_hash_add(mappings, category, res); } EAPI int e_theme_config_set(const char *category, const char *file) { E_Config_Theme *ect; Evas_List *next; /* Don't accept unused categories */ #if 0 if (!e_theme_category_find(category)) return 0; #endif /* search for the category */ for (next = e_config->themes; next; next = next->next) { ect = evas_list_data(next); if (!strcmp(ect->category, category)) { if (ect->file) evas_stringshare_del(ect->file); ect->file = evas_stringshare_add(file); return 1; } } /* the text class doesnt exist */ ect = E_NEW(E_Config_Theme, 1); ect->category = evas_stringshare_add(category); ect->file = evas_stringshare_add(file); e_config->themes = evas_list_append(e_config->themes, ect); return 1; } /* * returns a pointer to the data, return null if nothing if found. */ EAPI E_Config_Theme * e_theme_config_get(const char *category) { E_Config_Theme *ect = NULL; Evas_List *next; /* search for the category */ for (next = e_config->themes; next; next = next->next) { ect = evas_list_data(next); if (!strcmp(ect->category, category)) { return ect; } } return NULL; } EAPI int e_theme_config_remove(const char *category) { E_Config_Theme *ect; Evas_List *next; /* search for the category */ for (next = e_config->themes; next; next = next->next) { ect = evas_list_data(next); if (!strcmp(ect->category, category)) { e_config->themes = evas_list_remove_list( e_config->themes, next); if (ect->category) evas_stringshare_del(ect->category); if (ect->file) evas_stringshare_del(ect->file); free(ect); return 1; } } return 1; } EAPI Evas_List * e_theme_config_list(void) { return e_config->themes; } EAPI int e_theme_category_find(const char *category) { Evas_List *l; for (l = categories; l; l = l->next) { if (!strcmp(category, l->data)) return 1; } return 0; } EAPI Evas_List * e_theme_category_list(void) { return categories; } EAPI int e_theme_transition_find(const char *transition) { Evas_List *l; for (l = transitions; l; l = l->next) { if (!strcmp(transition, l->data)) return 1; } return 0; } EAPI Evas_List * e_theme_transition_list(void) { return transitions; } EAPI int e_theme_border_find(const char *border) { Evas_List *l; for (l = borders; l; l = l->next) { if (!strcmp(border, l->data)) return 1; } return 0; } EAPI Evas_List * e_theme_border_list(void) { return borders; } EAPI int e_theme_shelf_find(const char *shelf) { Evas_List *l; for (l = shelfs; l; l = l->next) { if (!strcmp(shelf, l->data)) return 1; } return 0; } EAPI Evas_List * e_theme_shelf_list(void) { return shelfs; } /* local subsystem functions */ static Evas_Bool _e_theme_mappings_free_cb(Evas_Hash *hash, const char *key, void *data, void *fdata) { E_Theme_Result *res; res = data; if (res->file) evas_stringshare_del(res->file); if (res->cache) evas_stringshare_del(res->cache); if (res->quickfind) { evas_hash_foreach(res->quickfind, _e_theme_mappings_quickfind_free_cb, NULL); evas_hash_free(res->quickfind); } free(res); return 1; } static Evas_Bool _e_theme_mappings_quickfind_free_cb(Evas_Hash *hash, const char *key, void *data, void *fdata) { evas_stringshare_del(key); return 1; } static void _e_theme_category_register(const char *category) { Evas_List *l; for (l = categories; l; l = l->next) { if (!strcmp(category, l->data)) return; } categories = evas_list_append(categories, evas_stringshare_add(category)); } static Evas_List * _e_theme_collection_item_register(Evas_List *list, const char *name) { Evas_List *l; for (l = list; l; l = l->next) { if (!strcmp(name, l->data)) return list; } list = evas_list_append(list, evas_stringshare_add(name)); return list; } static Evas_List * _e_theme_collection_items_find(const char *base, const char *collname) { Evas_List *list = NULL; E_Theme_Result *res; char *category, *p, *p2; int collname_len; collname_len = strlen(collname); category = alloca(strlen(base) + 1); strcpy(category, base); do { res = evas_hash_find(mappings, category); if (res) { const char *str; /* if found check cached path */ str = res->cache; if (!str) { /* no cached path */ str = res->file; /* if its not an absolute path find it */ if (str[0] != '/') str = e_path_find(path_themes, str); /* save cached value */ if (str) res->cache = str; } if (str) { Evas_List *coll, *l; coll = edje_file_collection_list(str); if (coll) { for (l = coll; l; l = l->next) { if (!strncmp(l->data, collname, collname_len)) { char *trans; trans = strdup(l->data); p = trans + collname_len + 1; if (*p) { p2 = strchr(p, '/'); if (p2) *p2 = 0; list = _e_theme_collection_item_register(list, p); } free(trans); } } edje_file_collection_list_free(coll); } } } p = strrchr(category, '/'); if (p) *p = 0; } while (p); return list; }