#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include "Ecore_Config.h" #include "ecore_config_private.h" #include "ecore_config_ipc.h" #include "ecore_config_util.h" int _ecore_config_log_dom = -1; int DEBUG = 0; EAPI Ecore_Config_Server *__ecore_config_server_global = NULL; EAPI Ecore_Config_Server *__ecore_config_server_local = NULL; EAPI Ecore_Config_Bundle *__ecore_config_bundle_local = NULL; EAPI char *__ecore_config_app_name = NULL; int __ecore_config_system_init = 0; static int _ecore_config_system_init_no_load(void); static int _ecore_config_system_load(void); static inline void *__ecore_argb_to_long(int a, int r, int g, int b, long *v); static inline void *__ecore_argbstr_to_long(const char *argb, long *v); static const char *_ecore_config_type[] = { "undefined", "integer", "float", "string", "colour", "theme", "boolean", "structure" }; /** * @defgroup Ecore_Config_Property_Group Ecore Config Property Functions * * Functions that retrieve or set the attributes relating to a property. */ /** * Removes the given property from the local configuration and destroys it. * @param e Property to destroy. * @return @c NULL * @ingroup Ecore_Config_Property_Group */ EAPI Ecore_Config_Prop * ecore_config_dst(Ecore_Config_Prop * e) { Ecore_Config_Bundle *t; Ecore_Config_Prop *p, *c; Ecore_Config_Listener_List *l; p = NULL; t = __ecore_config_bundle_local; c = t->data; if (!e || !e->key) return NULL; if (t) { if (t->data == e) t->data = e->next; else { do { p = c; c = c->next; } while (c && (c != e)); if (c) /* remove from list if even in there */ p->next = c->next; } } while (e->listeners) { l = e->listeners; e->listeners = e->listeners->next; free(l); } if (e->key) free(e->key); if (e->ptr && ((e->type == ECORE_CONFIG_STR) || (e->type == ECORE_CONFIG_THM))) free(e->ptr); memset(e, 0, sizeof(Ecore_Config_Prop)); free(e); return NULL; } /** * @defgroup Ecore_Config_Get_Group Configuration Retrieve Functions * * Functions that retrieve configuration values, based on type. */ /** * Returns the property with the given key. * @param key The unique name of the wanted property. * @return The property that corresponds to the given key. @c NULL if the * key could not be found. * @ingroup Ecore_Config_Get_Group */ EAPI Ecore_Config_Prop * ecore_config_get(const char *key) { Ecore_Config_Bundle *t; Ecore_Config_Prop *e; t = __ecore_config_bundle_local; if (!t || !key) return NULL; e = t->data; while (e) { if (!strcmp(key, e->key)) return e; e = e->next; } return NULL; } /** * Returns the type of the property. * @param e Property to get the type of. * @returns The type of the property. If the property is invalid, then the * string "not found" is returned. * @ingroup Ecore_Config_Property_Group */ EAPI const char * ecore_config_type_get(const Ecore_Config_Prop * e) { if (e) { return _ecore_config_type[e->type]; } return "not found"; } /** * Returns the specified property as a string. * @param key The property key. * @return The string value of the property. The function returns @c NULL if * the property is not a string or is not set. * @ingroup Ecore_Config_Get_Group */ EAPI char * ecore_config_string_get(const char *key) { return _ecore_config_string_get( ecore_config_get(key) ); } char * _ecore_config_string_get(Ecore_Config_Prop *e) { return (e && (e->type == ECORE_CONFIG_STR) && e->ptr) ? strdup(e->ptr) : NULL; } /** * Returns the specified property as an integer. * @param key The property key. * @return The value of the property. The function returns -1 if the * property is not an integer or is not set. * @ingroup Ecore_Config_Get_Group */ EAPI int ecore_config_boolean_get(const char *key) { return _ecore_config_boolean_get( ecore_config_get(key) ); } int _ecore_config_boolean_get(Ecore_Config_Prop *e) { return (e && ((e->type == ECORE_CONFIG_INT) || (e->type == ECORE_CONFIG_BLN))) ? (e->val != 0) : -1; } /** * Returns the specified property as a long integer. * @param key The property key. * @return The integer value of the property. The function returns 0 if the * property is not an integer or is not set. * @ingroup Ecore_Config_Get_Group */ EAPI long ecore_config_int_get(const char *key) { return _ecore_config_int_get( ecore_config_get(key) ); } long _ecore_config_int_get(Ecore_Config_Prop *e) { return (e && ((e->type == ECORE_CONFIG_INT) || (e->type == ECORE_CONFIG_RGB))) ? e->val : 0L; } /** * Returns the specified property as a float. * @param key The property key. * @return The float value of the property. The function returns 0.0 if the * property is not a float or is not set. * @ingroup Ecore_Config_Get_Group */ EAPI float ecore_config_float_get(const char *key) { return _ecore_config_float_get( ecore_config_get(key) ); } float _ecore_config_float_get(Ecore_Config_Prop *e) { return (e && (e->type == ECORE_CONFIG_FLT)) ? ((float)e->val / ECORE_CONFIG_FLOAT_PRECISION) : 0.0; } /** * Finds the alpha, red, green and blue values of a color property. * @param key The property key. * @param a A pointer to an integer to store the alpha value into. * @param r A pointer to an integer to store the red value into. * @param g A pointer to an integer to store the green value into. * @param b A pointer to an integer to store the blue value into. * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_FAIL * otherwise. * @ingroup Ecore_Config_Get_Group */ EAPI int ecore_config_argb_get(const char *key, int *a, int *r, int *g, int *b) { return _ecore_config_argb_get( ecore_config_get(key), a, r, g, b); } int _ecore_config_argb_get(Ecore_Config_Prop *e, int *a, int *r, int *g, int *b) { if (e && ((e->type == ECORE_CONFIG_RGB))) { if(a) *a = (e->val >> 24) & 0xff; if(r) *r = (e->val >> 16) & 0xff; if(g) *g = (e->val >> 8) & 0xff; if(b) *b = e->val & 0xff; return ECORE_CONFIG_ERR_SUCC; } return ECORE_CONFIG_ERR_FAIL; } /** * Returns a color property as a long * @param key The property key. * @return ARGB data as long * @ingroup Ecore_Config_Get_Group */ EAPI long ecore_config_argbint_get(const char *key) { return _ecore_config_argbint_get( ecore_config_get(key) ); } long _ecore_config_argbint_get(Ecore_Config_Prop *e) { if (e && ((e->type == ECORE_CONFIG_RGB))) { return e->val; } return 0L; } /** * Returns a color property as a string of hexadecimal characters. * @param key The property key. * @return A string of hexadecimal characters in the format #aarrggbb. * @ingroup Ecore_Config_Get_Group */ EAPI char * ecore_config_argbstr_get(const char *key) { return _ecore_config_argbstr_get( ecore_config_get(key) ); } char * _ecore_config_argbstr_get(Ecore_Config_Prop *e) { char *r; r = NULL; esprintf(&r, "#%08x", _ecore_config_int_get(e)); return r; } /** * Returns a theme property. * @param key The property key. * @return The name of the theme the property refers to. The function returns * @c NULL if the property is not a theme or is not set. * @ingroup Ecore_Config_Get_Group */ EAPI char * ecore_config_theme_get(const char *key) { return _ecore_config_theme_get( ecore_config_get(key) ); } char * _ecore_config_theme_get(Ecore_Config_Prop *e) { return (e && (e->type == ECORE_CONFIG_THM)) ? strdup(e->ptr) : NULL; } /** * Retrieves the key as a string. * @param key The property key. * @return Returns a character array in the form of 'key:type=value'. @c NULL * is returned if the property does not exist. * @ingroup Ecore_Config_Get_Group */ EAPI char * ecore_config_as_string_get(const char *key) { Ecore_Config_Prop *e; char *val; char *r; val = NULL; r = NULL; if (!(e = ecore_config_get(key))) ERR("no such property, \"%s\"...", key); else { switch (e->type) { case ECORE_CONFIG_NIL: val = strdup(""); break; case ECORE_CONFIG_INT: esprintf(&val, "%ld", _ecore_config_int_get(e)); break; case ECORE_CONFIG_BLN: esprintf(&val, "%ld", _ecore_config_boolean_get(e)); break; case ECORE_CONFIG_FLT: esprintf(&val, "%lf", _ecore_config_float_get(e)); break; case ECORE_CONFIG_STR: esprintf(&val, "\"%s\"", _ecore_config_string_get(e)); break; case ECORE_CONFIG_RGB: esprintf(&val, "#%08x", _ecore_config_int_get(e)); break; case ECORE_CONFIG_THM: esprintf(&val, "\"%s\"", _ecore_config_theme_get(e)); break; case ECORE_CONFIG_SCT: break; default: esprintf(&r, "%s:unknown_type", key); break; } if (val) { esprintf(&r, "%s:%s=%s", key, _ecore_config_type[e->type], val); free(val); } } return r; } EAPI int ecore_config_bound(Ecore_Config_Prop * e) { int ret; long v; ret = ECORE_CONFIG_ERR_SUCC; if (!e) return ECORE_CONFIG_ERR_FAIL; if (e->flags & ECORE_CONFIG_FLAG_BOUNDS) { if ((e->val < e->lo)) { WRN("ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...", e->key, e->val, e->lo); e->val = e->lo; } else if ((e->val > e->hi)) { WRN("ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...", e->key, e->val, e->hi); e->val = e->hi; } else ret = ECORE_CONFIG_ERR_IGNORED; } else ret = ECORE_CONFIG_ERR_IGNORED; if (e->step) { v = ((int)(e->val / e->step)) * e->step; if (v != e->val) { if (e->type == ECORE_CONFIG_FLT) WRN("ecore_config_bound(\"%s\"): float value %f not a multiple of %f, adjusted to %f...", e->key, ((double)e->val) / ECORE_CONFIG_FLOAT_PRECISION, ((double)e->step) / ECORE_CONFIG_FLOAT_PRECISION, ((double)v) / ECORE_CONFIG_FLOAT_PRECISION); else WRN("ecore_config_bound(\"%s\"): integer value %ld not a multiple of %ld, adjusted to %ld...", e->key, e->val, e->step, v); ret = ECORE_CONFIG_ERR_SUCC; e->val = v; } } return ret; } /** * Tries to guess the type of a property. * * This function first checks to see if the property exists. If it does, then * the type of the stored property is returned. Otherwise, the function tries * to guess the type of the property based on @p val. * * @param key The property key. * @param val The value in string form. * @return The type of the property determined by the function. Note that if * val is @c NULL, @c ECORE_CONFIG_NIL will be returned. */ EAPI int ecore_config_type_guess(const char *key, const char *val) { Ecore_Config_Prop *p; char *l; l = NULL; if (key && (p = ecore_config_get(key)) && p->type != ECORE_CONFIG_NIL) return p->type; if (!val) return ECORE_CONFIG_NIL; if (val[0] == '#') return ECORE_CONFIG_RGB; strtol(val, &l, 10); if (*l) { float f; if (sscanf(val, "%f%*s", &f) != 1) return ECORE_CONFIG_STR; return ECORE_CONFIG_FLT; } return ECORE_CONFIG_INT; } static int ecore_config_typed_val(Ecore_Config_Prop * e, const void *val, int type) { if (!e) return ECORE_CONFIG_ERR_NODATA; if (!(val) && (type != ECORE_CONFIG_NIL && type != ECORE_CONFIG_SCT)) e->ptr = NULL; else { if (type == ECORE_CONFIG_INT || type == ECORE_CONFIG_BLN) { e->val = (long) *((int *)val); e->type = type; } else if (type == ECORE_CONFIG_STR || type == ECORE_CONFIG_THM) { if (!(e->ptr = strdup(val))) return ECORE_CONFIG_ERR_OOM; if (e->type == ECORE_CONFIG_NIL) e->type = type; } else if (type == ECORE_CONFIG_RGB) { __ecore_argbstr_to_long((char *)val, &e->val); e->type = ECORE_CONFIG_RGB; } else if (type == ECORE_CONFIG_FLT) { e->val = (long) ((*((float *)val)) * ECORE_CONFIG_FLOAT_PRECISION); e->type = ECORE_CONFIG_FLT; } else if (type == ECORE_CONFIG_SCT) { e->type = ECORE_CONFIG_SCT; } else { e->type = ECORE_CONFIG_NIL; } ecore_config_bound(e); e->flags |= ECORE_CONFIG_FLAG_MODIFIED; e->flags &= ~ECORE_CONFIG_FLAG_CMDLN; return ECORE_CONFIG_ERR_SUCC; } return ECORE_CONFIG_ERR_IGNORED; } static int ecore_config_typed_add(const char *key, const void *val, int type) { int error = ECORE_CONFIG_ERR_SUCC; Ecore_Config_Prop *e = NULL; Ecore_Config_Bundle *t; t = __ecore_config_bundle_local; if (!key) return ECORE_CONFIG_ERR_NODATA; if (!(e = calloc(1, sizeof(Ecore_Config_Prop)))) { return ECORE_CONFIG_ERR_OOM; } else if (!(e->key = strdup(key))) { error = ECORE_CONFIG_ERR_OOM; } else if ((error = ecore_config_typed_val(e, val, type)) == ECORE_CONFIG_ERR_SUCC) { if (t) { e->next = t->data; t->data = e; } return ECORE_CONFIG_ERR_SUCC; } if(e->key) free(e->key); if(e) free(e); if (error == ECORE_CONFIG_ERR_SUCC) error = ECORE_CONFIG_ERR_FAIL; return error; } static int ecore_config_add(const char *key, const char *val) { int type; type = ecore_config_type_guess(key, val); return ecore_config_typed_add(key, val, type); } /** * Sets the description field of the indicated property. * @param key The property key. * @param desc Description string. * @note The description string is copied for the property's use. You can * free @p desc once this function is called. * @ingroup Ecore_Config_Property_Group */ EAPI int ecore_config_describe(const char *key, const char *desc) { Ecore_Config_Prop *e; if (!(e = ecore_config_get(key))) return ECORE_CONFIG_ERR_NODATA; e->description = strdup(desc); return ECORE_CONFIG_ERR_SUCC; } /** * Set the short option character of a property. * @param key The property key. * @param short_opt Character used to indicate the value of a property * given on the command line. * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_NODATA * is returned if the property does not exist. * @ingroup Ecore_Config_Property_Group */ EAPI int ecore_config_short_opt_set(const char *key, char short_opt) { Ecore_Config_Prop *e; if (!(e = ecore_config_get(key))) return ECORE_CONFIG_ERR_NODATA; e->short_opt = short_opt; return ECORE_CONFIG_ERR_SUCC; } /** * Set the long option string of the property. * @param key The property key. * @param long_opt String used to indicate the value of a property given * on the command line. * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_NODATA * is returned if the property does not exist. * @ingroup Ecore_Config_Property_Group */ EAPI int ecore_config_long_opt_set(const char *key, const char *long_opt) { Ecore_Config_Prop *e; if (!(e = ecore_config_get(key))) return ECORE_CONFIG_ERR_NODATA; if (e->long_opt) free(e->long_opt); if (long_opt) e->long_opt = strdup(long_opt); return ECORE_CONFIG_ERR_SUCC; } static void _ecore_config_listener_fire(Ecore_Config_Prop *prop) { Ecore_Config_Listener_List *l; for (l = prop->listeners; l; l = l->next) l->listener(prop->key, prop->type, l->tag, l->data); /* fire change listeners for the generic struct container etc */ if (prop->parent) _ecore_config_listener_fire(prop->parent); } /** * Sets the indicated property to the given value and type. * @param key The property key. * @param val A pointer to the value to set the property to. * @param type The type of the property. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Property_Group */ EAPI int ecore_config_typed_set(const char *key, const void *val, int type) { Ecore_Config_Prop *e; int ret; if (!key) return ECORE_CONFIG_ERR_NODATA; /* if (!t) { * global prop * e=ecore_config_get(key); if (e) for(l=e->listeners;l;l=l->next) l->listener(e->key,e->type,l->tag,l->data,t); return ECORE_CONFIG_ERR_SUCC; } */ if (!(e = ecore_config_get(key))) return ecore_config_typed_add(key, val, type); if ((ret = ecore_config_typed_val(e, val, type)) == ECORE_CONFIG_ERR_SUCC) { _ecore_config_listener_fire(e); } else { ERR("ecore_config_typed_set(\"%s\"): ecore_config_typed_val() failed: %d", key, ret); } return ret; } /** * @defgroup Ecore_Config_Set_Group Ecore Config Setters * * Functions that set the value of a property. */ /** * Sets the indicated property to the value indicated by @a val. * @param key The property key. * @param val String representation of value to set. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_set(const char *key, const char *val) { int type; int tmpi; float tmpf; long tmpl; type = ecore_config_type_guess(key, val); if (type == ECORE_CONFIG_INT || type == ECORE_CONFIG_BLN) { tmpi = atoi(val); return ecore_config_typed_set(key, &tmpi, type); } else if (type == ECORE_CONFIG_FLT) { tmpf = atof(val); return ecore_config_typed_set(key, &tmpf, type); } else if (type == ECORE_CONFIG_RGB) { __ecore_argbstr_to_long(val, &tmpl); return ecore_config_typed_set(key, &tmpl, type); } else return ecore_config_typed_set(key, val, type); } /** * Sets the indicated property to the value given in the string. * @param key The property key. * @param val String representation of the value. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_as_string_set(const char *key, const char *val) { return ecore_config_set(key, val); } /** * Sets the indicated property to the given boolean. * @param key The property key. * @param val Boolean integer to set the property to. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_boolean_set(const char *key, int val) { val = val ? 1 : 0; return ecore_config_typed_set(key, &val, ECORE_CONFIG_BLN); } /** * Sets the indicated property to the given integer. * @param key The property key. * @param val Integer to set the property to. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_int_set(const char *key, int val) { return ecore_config_typed_set(key, &val, ECORE_CONFIG_INT); } /** * Sets the indicated property to the given string. * @param key The property key. * @param val String to set the property to. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_string_set(const char *key, const char *val) { return ecore_config_typed_set(key, val, ECORE_CONFIG_STR); } /** * Sets the indicated property to the given float value. * @param key The property key. * @param val Float to set the property to. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_float_set(const char *key, float val) { return ecore_config_typed_set(key, &val, ECORE_CONFIG_FLT); } /** * Sets the indicated property to a color value. * @param key The property key * @param a integer 0..255 * @param r integer 0..255 * @param g integer 0..255 * @param b integer 0..255 * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_argb_set(const char *key, int a, int r, int g, int b) { long v = 0; return ecore_config_typed_set(key, __ecore_argb_to_long(a,r,g,b, &v), ECORE_CONFIG_RGB); } /** * Sets the indicated property to a color value. * @param key The property key * @param argb ARGB data as long * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_argbint_set(const char *key, long argb) { return ecore_config_typed_set(key, &argb, ECORE_CONFIG_RGB); } /** * Sets the indicated property to a color value. * @param key The property key * @param val Color value in ARGB format. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_argbstr_set(const char *key, const char *val) { long v = 0; return ecore_config_typed_set(key, __ecore_argbstr_to_long(val, &v), ECORE_CONFIG_RGB); } /** * Sets the indicated property to a theme name. * @param key The property key. * @param val String giving the name of the theme. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_theme_set(const char *key, const char *val) { return ecore_config_typed_set(key, val, ECORE_CONFIG_THM); } /** * Sets the theme preview group of an indicated property. * @param key The property key. * @param group The group name. * @return @c ECORE_CONFIG_ERR_SUCC on success. * @ingroup Ecore_Config_Set_Group */ EAPI int ecore_config_theme_preview_group_set(const char *key, const char *group) { int ret; Ecore_Config_Prop *e; ret = ECORE_CONFIG_ERR_SUCC; if (!(e = ecore_config_get(key))) { /* prop doesn't exist yet */ if ((ret = ecore_config_typed_add(key, "", ECORE_CONFIG_THM)) != ECORE_CONFIG_ERR_SUCC) /* try to add it */ return ret; /* ...failed */ if (!(e = ecore_config_get(key))) /* get handle */ return ECORE_CONFIG_ERR_FAIL; } if (e->data) free(e->data); e->data = strdup(group); return ret; } EAPI int ecore_config_typed_default(const char *key, const void *val, int type) { int ret; Ecore_Config_Prop *e; ret = ECORE_CONFIG_ERR_SUCC; if (!(e = ecore_config_get(key))) { /* prop doesn't exist yet */ if ((ret = ecore_config_typed_add(key, val, type)) != ECORE_CONFIG_ERR_SUCC) /* try to add it */ return ret; /* ...failed */ if (!(e = ecore_config_get(key))) /* get handle */ return ECORE_CONFIG_ERR_FAIL; e->flags = e->flags & ~ECORE_CONFIG_FLAG_MODIFIED; } else if (!(e->flags & ECORE_CONFIG_FLAG_MODIFIED) && !(e->flags & ECORE_CONFIG_FLAG_SYSTEM)) { ecore_config_typed_set(key, val, type); if (!(e = ecore_config_get(key))) /* get handle */ return ECORE_CONFIG_ERR_FAIL; e->flags = e->flags & ~ECORE_CONFIG_FLAG_MODIFIED; } return ret; } /** * @defgroup Ecore_Config_Default_Group Ecore Config Defaults * * Functions that are used to set the default values of properties. */ /** * Sets the indicated property if it has not already been set or loaded. * @param key The property key. * @param val Default value of the key. * @param lo Lowest valid value for the key. * @param hi Highest valid value for the key. * @param step Used by integer and float values. * @return @c ECORE_CONFIG_ERR_SUCC if there are no errors. * @note The @p lo, @p hi and @p step parameters are only used when storing * integer and float properties. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_default(const char *key, const char *val, float lo, float hi, float step) { int ret, type; Ecore_Config_Prop *e; type = ecore_config_type_guess(key, val); ret = ecore_config_typed_default(key, val, type); e = ecore_config_get(key); if (e) { if (type == ECORE_CONFIG_INT) { e->step = step; e->flags |= ECORE_CONFIG_FLAG_BOUNDS; e->lo = lo; e->hi = hi; ecore_config_bound(e); } else if (type == ECORE_CONFIG_FLT) { e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION); e->flags |= ECORE_CONFIG_FLAG_BOUNDS; e->lo = (int)(lo * ECORE_CONFIG_FLOAT_PRECISION); e->hi = (int)(hi * ECORE_CONFIG_FLOAT_PRECISION); ecore_config_bound(e); } } return ret; } /** * Sets the indicated property to the given boolean if the property has not yet * been set. * @param key The property key. * @param val Boolean Integer to set the value to. * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_boolean_default(const char *key, int val) { val = val ? 1 : 0; return ecore_config_typed_default(key, &val, ECORE_CONFIG_BLN); } /** * Sets the indicated property to the given integer if the property has not yet * been set. * @param key The property key. * @param val Integer to set the value to. * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_int_default(const char *key, int val) { return ecore_config_typed_default(key, &val, ECORE_CONFIG_INT); } /** * Sets the indicated property to the given integer if the property has not yet * been set. * * The bounds and step values are set regardless. * * @param key The property key. * @param val Integer to set the property to. * @param low Lowest valid integer value for the property. * @param high Highest valid integer value for the property. * @param step Increment value for the property. * @return @c ECORE_CONFIG_ERR_SUCC if there were no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_int_default_bound(const char *key, int val, int low, int high, int step) { Ecore_Config_Prop *e; int ret; ret = ecore_config_typed_default(key, &val, ECORE_CONFIG_INT); e = ecore_config_get(key); if (e) { e->step = step; e->flags |= ECORE_CONFIG_FLAG_BOUNDS; e->lo = low; e->hi = high; ecore_config_bound(e); } return ret; } /** * Sets the indicated property to the given string if the property has not yet * been set. * @param key The property key. * @param val String to set the property to. * @return @c ECORE_CONFIG_ERR_SUCC if there were no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_string_default(const char *key, const char *val) { return ecore_config_typed_default(key, val, ECORE_CONFIG_STR); } /** * Sets the indicated property to the given float if the property has not yet * been set. * @param key The property key. * @param val Float to set the property to. * @return @c ECORE_CONFIG_ERR_SUCC if there were no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_float_default(const char *key, float val) { return ecore_config_typed_default(key, &val, ECORE_CONFIG_FLT); } /** * Sets the indicated property to the given float if the property has not yet * been set. * * The bounds and step values are set regardless. * * @param key The property key. * @param val Float to set the property to. * @param low Lowest valid integer value for the property. * @param high Highest valid float value for the property. * @param step Increment value for the property. * @return @c ECORE_CONFIG_ERR_SUCC if there were no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_float_default_bound(const char *key, float val, float low, float high, float step) { Ecore_Config_Prop *e; int ret; ret = ecore_config_typed_default(key, &val, ECORE_CONFIG_FLT); e = ecore_config_get(key); if (e) { e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION); e->flags |= ECORE_CONFIG_FLAG_BOUNDS; e->lo = (int)(low * ECORE_CONFIG_FLOAT_PRECISION); e->hi = (int)(high * ECORE_CONFIG_FLOAT_PRECISION); ecore_config_bound(e); } return ret; } /** * Sets the indicated property to a color value if the property has not yet * been set. * @param key The property key. * @param a integer 0..255 * @param r integer 0..255 * @param g integer 0..255 * @param b integer 0..255 * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_argb_default(const char *key, int a, int r, int g, int b) { long v = 0; return ecore_config_typed_default(key, __ecore_argb_to_long(a,r,g,b, &v), ECORE_CONFIG_RGB); } /** * Sets the indicated property to a color value if the property has not yet * been set. * @param key The property key. * @param argb ARGB data as long * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_argbint_default(const char *key, long argb) { return ecore_config_typed_default(key, &argb, ECORE_CONFIG_RGB); } /** * Sets the indicated property to a color value if the property has not yet * been set. * @param key The property key. * @param val Color value in ARGB format. * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_argbstr_default(const char *key, const char *val) { long v = 0; return ecore_config_typed_default(key, __ecore_argbstr_to_long(val, &v), ECORE_CONFIG_RGB); } /** * Sets the indicated property to a theme name if the property has not yet * been set. * @param key The property key. * @param val String giving the name of the theme. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Default_Group */ EAPI int ecore_config_theme_default(const char *key, const char *val) { return ecore_config_typed_default(key, val, ECORE_CONFIG_THM); } /** * @defgroup Ecore_Config_Struct_Group Ecore Config Structures * * Functions that are used to create structures of properties. */ /** * Sets the indicated property to a structure if the property has not yet * been set. * @param key The property key. * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Struct_Group */ EAPI int ecore_config_struct_create(const char *key) { WRN("you are using ecore_config structures. These are very young"); WRN(" and not complete - you have been warned"); return ecore_config_typed_default(key, NULL, ECORE_CONFIG_SCT); } static int _ecore_config_struct_append(Ecore_Config_Prop *sct, Ecore_Config_Prop *add) { Eina_List *l; if (!sct || !add || sct->type != ECORE_CONFIG_SCT) return ECORE_CONFIG_ERR_IGNORED; l = sct->data; sct->data = eina_list_append(l, add); add->parent = sct; return ECORE_CONFIG_ERR_SUCC; } static int _ecore_config_struct_typed_add(const char *key, const char *name, const void *val, int type) { char *subkey; int ret; subkey = malloc((strlen(key) + strlen(name) + 2) * sizeof(char)); strcpy(subkey, key); strcat(subkey, "."); strcat(subkey, name); ecore_config_typed_default(subkey, val, type); ret = _ecore_config_struct_append(ecore_config_get(key), ecore_config_get(subkey)); free(subkey); return ret; } /** * Add an int property to the named structure. The property is set if it has not * yet been set. * @param key The key of the structure to add to. * @param name The name of the item to add - this will be appended to the key * @param val the int to default to * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Struct_Group */ EAPI int ecore_config_struct_int_add(const char *key, const char *name, int val) { return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_INT); } /** * Add a float property to the named structure. The property is set if it has * not yet been set. * @param key The key of the structure to add to. * @param name The name of the item to add - this will be appended to the key * @param val The float to default to * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Struct_Group */ EAPI int ecore_config_struct_float_add(const char *key, const char *name, float val) { return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_FLT); } /** * Add a string property to the named structure. The property is set if it has * not yet been set. * @param key The key of the structure to add to. * @param name The name of the item to add - this will be appended to the key * @param val The string to default to * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Struct_Group */ EAPI int ecore_config_struct_string_add(const char *key, const char *name, const char* val) { return _ecore_config_struct_typed_add(key, name, val, ECORE_CONFIG_STR); } /** * Add an argb property to the named structure. The property is set if it has * not yet been set. * @param key The key of the structure to add to. * @param name The name of the item to add - this will be appended to the key * @param a The alpha to default to * @param r The red to default to * @param g The green to default to * @param b The blue to default to * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Struct_Group */ EAPI int ecore_config_struct_argb_add(const char *key, const char *name, int a, int r, int g, int b) { long argb; __ecore_argb_to_long(a, r, g, b, &argb); return _ecore_config_struct_typed_add(key, name, &argb, ECORE_CONFIG_RGB); } /** * Add a theme property to the named structure. The property is set if it has * not yet been set. * @param key The key of the structure to add to. * @param name The name of the item to add - this will be appended to the key * @param val The theme name to default to * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Struct_Group */ EAPI int ecore_config_struct_theme_add(const char *key, const char *name, const char* val) { return _ecore_config_struct_typed_add(key, name, val, ECORE_CONFIG_THM); } /** * Add a boolean property to the named structure. The property is set if it has * not yet been set. * @param key The key of the structure to add to. * @param name The name of the item to add - this will be appended to the key * @param val The boolean to default to * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. * @ingroup Ecore_Config_Struct_Group */ EAPI int ecore_config_struct_boolean_add(const char *key, const char *name, int val) { val = val ? 1 : 0; return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_BLN); } /** * Get the contents of a defined structure property and load it into the passed * C struct * @param key The name of the structure property to look up. * @param data The struct to write into. * @return @c ECORE_CONFIG_ERR_SUCC if the structure is written successfully. * @ingroup Ecore_Config_Struct_Group */ EAPI int ecore_config_struct_get(const char *key, void *data) { Ecore_Config_Prop *e, *f; Eina_List *l; unsigned char *ptr; long argb; e = ecore_config_get(key); if (!e) return ECORE_CONFIG_ERR_NODATA; l = e->data; ptr = data; while (l) { f = (Ecore_Config_Prop *) l->data; switch (f->type) { case ECORE_CONFIG_INT: *((int *) ptr) = _ecore_config_int_get(f); ptr += sizeof(int); break; case ECORE_CONFIG_BLN: *((int *) ptr) = _ecore_config_boolean_get(f); ptr += sizeof(int); break; case ECORE_CONFIG_FLT: *((float *) ptr) = _ecore_config_float_get(f); ptr += sizeof(float); break; case ECORE_CONFIG_STR: case ECORE_CONFIG_THM: *((char **) ptr) = _ecore_config_string_get(f); ptr += sizeof(char *); break; case ECORE_CONFIG_RGB: argb = _ecore_config_argbint_get(f); *((int *) ptr) = (argb >> 24) & 0xff; ptr += sizeof(int); *((int *) ptr) = (argb >> 16) & 0xff; ptr += sizeof(int); *((int *) ptr) = (argb >> 8) & 0xff; ptr += sizeof(int); *((int *) ptr) = argb & 0xff; ptr += sizeof(int); break; default: WRN("ARGH - STRUCT coding not implemented yet"); } l = eina_list_next(l); } return ECORE_CONFIG_ERR_SUCC; } /** * @defgroup Ecore_Config_Listeners_Group Ecore Config Listeners * * Functions that set and unset property listener callbacks. */ /** * Adds a callback function to the list of functions called when a property * changes. * @param name Name of the callback. * @param key The key of the property to listen to. * @param listener Listener callback function. * @param tag Tag to pass to @p listener when it is called. * @param data Data to pass to @p listener when it is called. * @return @c ECORE_CONFIG_ERR_SUCC if successful in setting up the callback. * @ingroup Ecore_Config_Listeners_Group */ EAPI int ecore_config_listen(const char *name, const char *key, Ecore_Config_Listener listener, int tag, void *data) { Ecore_Config_Prop *e; Ecore_Config_Listener_List *l; if (!key) return ECORE_CONFIG_ERR_NODATA; if (!(e = ecore_config_get(key))) { int ret = ecore_config_add(key, ""); if (ret != ECORE_CONFIG_ERR_SUCC) { ERR("ecore_config_listen: ecore_config_add(\"%s\") failed: %d", key, ret); return ret; } if (!(e = ecore_config_get(key))) { ERR("ecore_config_listen: list of properties corrupted!?"); return ECORE_CONFIG_ERR_FAIL; } } for (l = e->listeners; l; l = l->next) if (!strcmp(l->name, name) || (l->listener == listener)) { ERR("ecore_config_listen: %s is already listening for changes of %s...", name, key); return ECORE_CONFIG_ERR_IGNORED; } if (!(l = malloc(sizeof(Ecore_Config_Listener_List)))) return ECORE_CONFIG_ERR_OOM; ERR("registering listener \"%s\" for \"%s\" (%d)...", name, key, e->type); memset(l, 0, sizeof(Ecore_Config_Listener_List)); l->listener = listener; l->name = name; l->data = data; l->tag = tag; l->next = e->listeners; e->listeners = l; if (e->type != ECORE_CONFIG_NIL) /* call right on creation if prop exists and has val */ listener(key, e->type, tag, data); return ECORE_CONFIG_ERR_SUCC; } /** * Removes a listener callback. * @param name Name of the callback to remove. * @param key The property key the callback is listening to. * @param listener The callback function to remove. * @return @c ECORE_CONFIG_ERR_SUCC if successful in removing the callback. * If no callback matches the given parameters, then * @c ECORE_CONFIG_ERR_NOTFOUND is returned. If @c NULL is passed * for the key pointer, @c ECORE_CONFIG_ERR_NODATA is returned. * @ingroup Ecore_Config_Listeners_Group */ EAPI int ecore_config_deaf(const char *name, const char *key, Ecore_Config_Listener listener) { Ecore_Config_Prop *e; Ecore_Config_Listener_List *l, *p; int ret; ret = ECORE_CONFIG_ERR_NOTFOUND; if (!key) return ECORE_CONFIG_ERR_NODATA; if (!(e = ecore_config_get(key))) return ECORE_CONFIG_ERR_NOTFOUND; for (p = NULL, l = e->listeners; l; p = l) { Ecore_Config_Listener_List *nl; nl = l->next; if ((name && !strcmp(l->name, name)) || (l->listener == listener)) { ret = ECORE_CONFIG_ERR_SUCC; if (!p) e->listeners = e->listeners->next; else p->next = l->next; memset(l, 0, sizeof(Ecore_Config_Listener)); free(l); } l = nl; } return ret; } /** * Locates the first configuration bundle on the given server. * @param srv The configuration server. * @return Pointer to the first configuration bundle. */ EAPI Ecore_Config_Bundle * ecore_config_bundle_1st_get(Ecore_Config_Server * srv) { /* anchor: global, but read-only */ return srv->bundles; } /** * Locates the configuration bundle after the given one. * @param ns The configuration bundle. * @return The next configuration bundle. */ EAPI Ecore_Config_Bundle * ecore_config_bundle_next_get(Ecore_Config_Bundle * ns) { return ns ? ns->next : NULL; } /** * Locates a configuration bundle on a configuration server based on its serial * number. * @param srv The configuration server. * @param serial Serial number. * @return The configuration bundle with the given serial number. */ EAPI Ecore_Config_Bundle * ecore_config_bundle_by_serial_get(Ecore_Config_Server * srv, long serial) { Ecore_Config_Bundle *eb; eb = srv->bundles; if (serial < 0) return NULL; else if (serial == 0) { Ecore_Config_Bundle *r = eb; return r; } while (eb) { if (eb->serial == serial) return eb; eb = eb->next; } return NULL; } /** * Gets the Ecore_Config_Bundle with the given identifier from the given * server. * @param srv The configuration server. * @param label The bundle's identifier string. * @return The bundle with the given identifier string, or @c NULL if it * could not be found. */ EAPI Ecore_Config_Bundle * ecore_config_bundle_by_label_get(Ecore_Config_Server * srv, const char *label) { Ecore_Config_Bundle *ns; ns = srv->bundles; while (ns) { if (ns->identifier && !strcmp(ns->identifier, label)) return ns; ns = ns->next; } return NULL; } /** * Retrieves the bundle's serial number. * @param ns The configuration bundle. * @return The bundle's identifier string, or -1 if ns is @c NULL. */ EAPI long ecore_config_bundle_serial_get(Ecore_Config_Bundle * ns) { return ns ? ns->serial : -1; } /** * Retrieves the bundle's identifier. * @param ns The configuration bundle. * @return The bundle's identifer string. */ EAPI char * ecore_config_bundle_label_get(Ecore_Config_Bundle * ns) { return ns ? ns->identifier : NULL; } /** * Creates a new Ecore_Config_Bundle. * @param srv Config server. * @param identifier Identifier string for the new bundle. * @return A pointer to a new Ecore_Config_Bundle. @c NULL is returned if the * structure couldn't be allocated. */ EAPI Ecore_Config_Bundle * ecore_config_bundle_new(Ecore_Config_Server * srv, const char *identifier) { Ecore_Config_Bundle *t; static long ss; ss = 0; /* bundle unique serial */ if ((t = malloc(sizeof(Ecore_Config_Bundle)))) { memset(t, 0, sizeof(Ecore_Config_Bundle)); t->identifier = (char *)identifier; t->serial = ++ss; t->owner = srv->name; t->next = srv->bundles; srv->bundles = t; } return t; } static Ecore_Config_Server * do_init(const char *name) { return _ecore_config_ipc_init(name); } static Ecore_Config_Server * ecore_config_init_local(const char *name) { char *p; char *buf; if ((p = getenv("HOME"))) { /* debug-only ### FIXME */ if (!(buf = malloc(PATH_MAX * sizeof(char)))) return NULL; snprintf(buf, PATH_MAX, "%s/.ecore/%s/.global", p, name); unlink(buf); free(buf); } return do_init(name); } static Ecore_Config_Server * ecore_config_init_global(const char *name) { char *p; int global; char *buf; if ((p = getenv("HOME"))) { /* debug-only ### FIXME */ if (!(buf = malloc(PATH_MAX * sizeof(char)))) return NULL; snprintf(buf, PATH_MAX, "%s/.ecore/%s/.global", p, name); global = creat(buf, S_IRWXU); if (global >= 0) close(global); free(buf); } return do_init(name); } /** * @defgroup Ecore_Config_App_Lib_Group Ecore Config App Library Functions * * Functions that are used to start up and shutdown the Enlightened * Property Library when used directly by an application. */ /** * Initializes the Enlightened Property Library. * * Either this function or @ref ecore_config_system_init must be run * before any other function in the Enlightened Property Library, even * if you have run @ref ecore_init . The name given is used to * determine the default configuration to load. * * @param name Application name * @return @c ECORE_CONFIG_ERR_SUCC if the library is successfully set up. * @c ECORE_CONFIG_ERR_FAIL otherwise. * @ingroup Ecore_Config_App_Lib_Group */ EAPI int ecore_config_init(const char *name) { char *path; Ecore_Config_Prop *list; _ecore_config_log_dom = eina_log_domain_register ("ecore_config", ECORE_CONFIG_DEFAULT_LOG_COLOR); if(_ecore_config_log_dom < 0) { EINA_LOG_ERR("Impossible to create a log domain for the Ecore config module."); return -1; } _ecore_config_system_init_no_load(); __ecore_config_app_name = strdup(name); __ecore_config_server_local = ecore_config_init_local(name); if (!__ecore_config_server_local) return ECORE_CONFIG_ERR_FAIL; list = __ecore_config_bundle_local->data; free( __ecore_config_bundle_local ); __ecore_config_bundle_local = ecore_config_bundle_new(__ecore_config_server_local, "config"); __ecore_config_bundle_local->data = list; path = ecore_config_theme_default_path_get(); ecore_config_string_default("/e/themes/search_path", path); if (path) free(path); list = ecore_config_get("/e/themes/search_path"); if (list) { list->flags |= ECORE_CONFIG_FLAG_SYSTEM; list->flags &= ~ECORE_CONFIG_FLAG_MODIFIED; } return _ecore_config_system_load(); } /** * Frees memory and shuts down the library for an application. * @return @c ECORE_CONFIG_ERR_IGNORED . * @ingroup Ecore_Config_App_Lib_Group */ EAPI int ecore_config_shutdown(void) { return ecore_config_system_shutdown(); } /** * @defgroup Ecore_Config_Lib_Lib_Group Ecore Config Library Functions * * Functions that are used to start up and shutdown the Enlightened * Property Library when used directly by an application. */ /** * Initializes the Enlightened Property Library. * * This function is meant to be run from other programming libraries. * It should not be called from applications. * * This function (or @ref ecore_config_init ) * must be run before any other function in the * Enlightened Property Library, even if you have run @ref ecore_init . * * @return @c ECORE_CONFIG_ERR_SUCC if the library is successfully set up. * @c ECORE_CONFIG_ERR_FAIL otherwise. * @ingroup Ecore_Config_Lib_Lib_Group */ EAPI int ecore_config_system_init(void) { _ecore_config_system_init_no_load(); return _ecore_config_system_load(); } static int _ecore_config_system_init_no_load(void) { char *p; __ecore_config_system_init++; if (__ecore_config_system_init > 1) return ECORE_CONFIG_ERR_IGNORED; DEBUG = -1; if ((p = getenv("ECORE_CONFIG_DEBUG")) && p[0] != 0) { DEBUG = atoi(p); } __ecore_config_server_global = ecore_config_init_global(ECORE_CONFIG_GLOBAL_ID); if (!__ecore_config_server_global) return ECORE_CONFIG_ERR_FAIL; __ecore_config_bundle_local = ecore_config_bundle_new(__ecore_config_server_global, "system"); /* set up a simple default path */ ecore_config_string_default("/e/themes/search_path", PACKAGE_DATA_DIR "../ewl/themes"); return ECORE_CONFIG_ERR_SUCC; } static int _ecore_config_system_load(void) { char *buf, *p; Ecore_Config_Prop *sys; if (__ecore_config_system_init != 1) return ECORE_CONFIG_ERR_FAIL; if ((p = getenv("HOME"))) { /* debug-only ### FIXME */ if ((buf = malloc(PATH_MAX * sizeof(char)))) { snprintf(buf, PATH_MAX, "%s/.e/config.eet", p); if (ecore_config_file_load(buf) != 0) { /* even if this file (system.eet) doesn't exist we can * continue without it as it isn't striclty necessary. */ ecore_config_file_load(PACKAGE_DATA_DIR "/system.eet"); } sys = __ecore_config_bundle_local->data; while (sys) { /* unmark it modified - modification will mean it has been overridden */ sys->flags &= ~ECORE_CONFIG_FLAG_MODIFIED; /* mark as system so that examine can hide them */ sys->flags |= ECORE_CONFIG_FLAG_SYSTEM; sys = sys->next; } } free(buf); } return ECORE_CONFIG_ERR_SUCC; } /** * Frees memory and shuts down the library for other programming libraries. * @return @c ECORE_CONFIG_ERR_IGNORED * @ingroup Ecore_Config_Lib_Lib_Group */ EAPI int ecore_config_system_shutdown(void) { int ret; __ecore_config_system_init--; if (__ecore_config_system_init > 0) return ECORE_CONFIG_ERR_IGNORED; ret = _ecore_config_ipc_exit(); if (__ecore_config_app_name) free(__ecore_config_app_name); while(__ecore_config_bundle_local->data) ecore_config_dst(__ecore_config_bundle_local->data); free(__ecore_config_bundle_local); free(__ecore_config_server_local); free(__ecore_config_server_global); eina_log_domain_unregister(_ecore_config_log_dom); _ecore_config_log_dom = -1; return ret; } static inline void * __ecore_argb_to_long(int a, int r, int g, int b, long *v) { *v = ((a << 24) & 0xff000000 ) | ((r << 16) & 0xff0000 ) | ((g << 8) & 0xff00 ) | ( b & 0xff ); return v; } static inline void * __ecore_argbstr_to_long(const char *argb, long *v) { char *l = NULL; // convert hexadecimal string #..., #0x..., 0x..., ... to long if(*argb == '#') argb++; *v = (long)strtoul( argb, &l, 16); if(*l) { ERR("ecore_config_val: value \"%s\" not a valid hexadecimal RGB value?", argb); return NULL; } return v; }