efl/legacy/ecore/src/lib/ecore_config/ecore_config.c

1607 lines
40 KiB
C

#include "Ecore_Config.h"
#include "config.h"
#include "ecore_config_private.h"
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <util.h>
int DEBUG = 0;
Ecore_Config_Server *__ecore_config_server_global = NULL;
Ecore_Config_Server *__ecore_config_server_local = NULL;
Ecore_Config_Bundle *__ecore_config_bundle_local = NULL;
char *__ecore_config_app_name = NULL;
int __ecore_config_system_init = 0;
Ecore_Config_Server *_ecore_config_ipc_init(char *name);
int _ecore_config_ipc_exit(void);
static int _ecore_config_system_init_no_load(void);
static int _ecore_config_system_load(void);
static char *_ecore_config_type[] =
{ "undefined", "integer", "float", "string", "colour", "theme", "boolean" };
/**
* @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
*/
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;
c = e;
t = __ecore_config_bundle_local;
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 == PT_STR))
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
*/
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
*/
const char *
ecore_config_type_get(const Ecore_Config_Prop * e)
{
if (e)
{
return _ecore_config_type[e->type];
}
return "not found";
}
/**
* Obtains the data pointed to by the specified property.
* @param key The property key.
* @return Data pointer used by the property.
* @ingroup Ecore_Config_Get_Group
*/
void *
ecore_config_data_get(const char *key)
{
Ecore_Config_Prop *e;
e = ecore_config_get(key);
return (e ? ((e->type == PT_STR) ? ((void *)&e->ptr) : ((void *)&e->val))
: NULL);
}
/**
* 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
*/
char *
ecore_config_string_get(const char *key)
{
Ecore_Config_Prop *e;
e = ecore_config_get(key);
return (e && (e->type == PT_STR)) ? 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
*/
int
ecore_config_boolean_get(const char *key)
{
Ecore_Config_Prop *e;
e = ecore_config_get(key);
return (e && ((e->type == PT_INT) || (e->type == PT_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
*/
long
ecore_config_int_get(const char *key)
{
Ecore_Config_Prop *e;
e = ecore_config_get(key);
return (e && ((e->type == PT_INT) || (e->type == PT_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
*/
float
ecore_config_float_get(const char *key)
{
Ecore_Config_Prop *e;
e = ecore_config_get(key);
return (e
&& (e->type ==
PT_FLT)) ? ((float)e->val / ECORE_CONFIG_FLOAT_PRECISION) : 0.0;
}
/**
* Finds the red, green and blue values of a color property.
* @param key The property key.
* @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
* @deprecated
*/
int
ecore_config_rgb_get(const char *key, int *r, int *g, int *b)
{
int alpha;
return ecore_config_argb_get(key, &alpha, r, g, b);
}
/**
* 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
*/
int
ecore_config_argb_get(const char *key, int *a, int *r, int *g, int *b)
{
Ecore_Config_Prop *e;
e = ecore_config_get(key);
if (e && ((e->type == PT_RGB)))
{
*a = (e->val >> 24) & 0xff;
*r = (e->val >> 16) & 0xff;
*g = (e->val >> 8) & 0xff;
*b = e->val & 0xff;
return ECORE_CONFIG_ERR_SUCC;
}
return ECORE_CONFIG_ERR_FAIL;
}
/**
* Returns a color property as a string of hexadecimal characters.
* @param key The property key.
* @return A string of hexadecimal characters in the format #rrggbb.
* @ingroup Ecore_Config_Get_Group
* @deprecated
*/
char *
ecore_config_rgbstr_get(const char *key)
{
char *argb, *rgb;
argb = ecore_config_argbstr_get(key);
rgb = argb + 2;
*rgb = '#';
return rgb;
}
/**
* 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
*/
char *
ecore_config_argbstr_get(const char *key)
{
char *r;
r = NULL;
esprintf(&r, "#%08x", ecore_config_int_get(key));
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
*/
char *
ecore_config_theme_get(const char *key)
{
Ecore_Config_Prop *e;
e = ecore_config_get(key);
return (e && (e->type == PT_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
*/
char *
ecore_config_as_string_get(const char *key)
{
Ecore_Config_Prop *e;
char *r;
r = NULL;
if (!(e = ecore_config_get(key)))
E(0, "no such property, \"%s\"...\n", key);
else
{
const char *type = ecore_config_type_get(e);
switch (e->type)
{
case PT_NIL:
esprintf(&r, "%s:%s=<nil>", key, type);
break;
case PT_INT:
esprintf(&r, "%s:%s=%ld", key, type, ecore_config_int_get(key));
break;
case PT_BLN:
esprintf(&r, "%s:%s=%ld", key, type, ecore_config_boolean_get(key));
break;
case PT_FLT:
esprintf(&r, "%s:%s=%lf", key, type, ecore_config_float_get(key));
break;
case PT_STR:
esprintf(&r, "%s:%s=\"%s\"", key, type,
ecore_config_string_get(key));
break;
case PT_RGB:
esprintf(&r, "%s:%s=#%08x", key, type, ecore_config_int_get(key));
break;
case PT_THM:
esprintf(&r, "%s:%s=\"%s\"", key, type,
ecore_config_theme_get(key));
break;
default:
esprintf(&r, "%s:unknown_type", key);
break;
}
}
return r;
}
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 & PF_BOUNDS)
{
if ((e->val < e->lo))
{
E(0,
"ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...\n",
e->key, e->val, e->lo);
e->val = e->lo;
}
else if ((e->val > e->hi))
{
E(0,
"ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...\n",
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 == PT_FLT)
E(0,
"ecore_config_bound(\"%s\"): float value %f not a multiple of %f, adjusted to %f...\n",
e->key, ((double)e->val) / ECORE_CONFIG_FLOAT_PRECISION,
((double)e->step) / ECORE_CONFIG_FLOAT_PRECISION,
((double)v) / ECORE_CONFIG_FLOAT_PRECISION);
else
E(0,
"ecore_config_bound(\"%s\"): integer value %ld not a multiple of %ld, adjusted to %ld...\n",
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 PT_NIL will be returned.
*/
int
ecore_config_type_guess(const char *key, char *val)
{
Ecore_Config_Prop *p;
char *l;
long v;
l = NULL;
if ((p = ecore_config_get(key)) && p->type != PT_NIL)
return p->type;
if (!val)
return PT_NIL;
if (val[0] == '#')
return PT_RGB;
v = strtol(val, &l, 10);
if (*l)
{
float f;
if (sscanf(val, "%f%*s", &f) != 1)
return PT_STR;
return PT_FLT;
}
return PT_INT;
}
static int
ecore_config_typed_val(Ecore_Config_Prop * e, void *val, int type)
{
char *l;
long v;
int *i;
float *f;
l = NULL;
v = 0;
if (!(val))
e->ptr = NULL;
else
{
if (type == PT_INT)
{
i = (int *)val;
e->val = (long)*i;
e->type = PT_INT;
}
else if (type == PT_BLN )
{
i = (int *)val;
e->val = (long)*i;
e->type = PT_BLN;
}
else if (type == PT_STR || type == PT_THM)
{
if (!(e->ptr = strdup(val)))
return ECORE_CONFIG_ERR_OOM;
if (e->type == PT_NIL)
e->type = type;
}
else if (type == PT_RGB)
{
if (((char *)val)[0] == '#')
{
if ((v = strtol(&((char *)val)[1], &l, 16)) < 0)
{
v = 0;
E(0,
"ecore_config_val: key \"%s\" -- hexadecimal value less than zero, bound to zero...\n",
(char *)val);
l = (char *)val;
}
}
else
{
E(0,
"ecore_config_val: key \"%s\" -- value \"%s\" not a valid hexadecimal RGB value?\n",
e->key, (char *)val);
return ECORE_CONFIG_ERR_FAIL;
}
if (*l)
E(0,
"ecore_config_val: key \"%s\" -- value \"%s\" not a valid hexadecimal RGB value?\n",
e->key, (char *)val);
else
{
e->val = v;
e->type = PT_RGB;
}
}
else if (type == PT_FLT)
{
f = (float *)val;
e->val = (long)((*f) * ECORE_CONFIG_FLOAT_PRECISION);
e->type = PT_FLT;
}
else
e->type = PT_NIL;
ecore_config_bound(e);
e->flags |= PF_MODIFIED;
return ECORE_CONFIG_ERR_SUCC;
}
return ECORE_CONFIG_ERR_IGNORED;
}
static int
ecore_config_typed_add(const char *key, void *val, int type)
{
Ecore_Config_Prop *e;
Ecore_Config_Bundle *t;
t = __ecore_config_bundle_local;
if (!key)
return ECORE_CONFIG_ERR_NODATA;
if (!(e = malloc(sizeof(Ecore_Config_Prop))))
goto ret;
memset(e, 0, sizeof(Ecore_Config_Prop));
if (!(e->key = strdup(key)))
goto ret_free_nte;
if (!val)
e->type = PT_NIL;
else if (ecore_config_typed_val(e, val, type) == ECORE_CONFIG_ERR_OOM)
goto ret_free_key;
e->next = t ? t->data : NULL;
if (t)
t->data = e;
return ECORE_CONFIG_ERR_SUCC;
ret_free_key:
free(e->key);
ret_free_nte:
free(e);
ret:
return ECORE_CONFIG_ERR_OOM;
}
static int
ecore_config_add(const char *key, 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
*/
int
ecore_config_describe(const char *key, 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
*/
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
*/
int
ecore_config_long_opt_set(const char *key, 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);
e->long_opt = strdup(long_opt);
return ECORE_CONFIG_ERR_SUCC;
}
/**
* 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
*/
int
ecore_config_typed_set(const char *key, void *val, int type)
{
Ecore_Config_Prop *e;
Ecore_Config_Listener_List *l;
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)
{
for (l = e->listeners; l; l = l->next)
l->listener(e->key, e->type, l->tag, l->data);
}
else
{
E(0,
"ecore_config_typed_set(\"%s\"): ecore_config_typed_val() failed: %d\n",
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
*/
int
ecore_config_set(const char *key, char *val)
{
int type;
int tmpi;
float tmpf;
type = ecore_config_type_guess(key, val);
if (type == PT_INT || type == PT_BLN)
{
tmpi = atoi(val);
return ecore_config_typed_set(key, (void *)&tmpi, type);
}
else if (type == PT_FLT)
{
tmpf = atof(val);
return ecore_config_typed_set(key, (void *)&tmpf, type);
}
else
return ecore_config_typed_set(key, (void *)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
*/
int
ecore_config_as_string_set(const char *key, 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
*/
int
ecore_config_boolean_set(const char *key, int val)
{
val = val ? 1 : 0;
return ecore_config_typed_set(key, (void *)&val, PT_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
*/
int
ecore_config_int_set(const char *key, int val)
{
return ecore_config_typed_set(key, (void *)&val, PT_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
*/
int
ecore_config_string_set(const char *key, char *val)
{
return ecore_config_typed_set(key, (void *)val, PT_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
*/
int
ecore_config_float_set(const char *key, float val)
{
return ecore_config_typed_set(key, (void *)&val, PT_FLT);
}
char *
ecore_config_rgb_to_argb(char *rgb)
{
char *argb;
argb = malloc(strlen(rgb) + 2);
strncpy(argb, "#ff", 3);
strncat(argb, rgb+1, strlen(rgb - 1));
return argb;
}
/**
* Sets the indicated property to a color value.
* @param key The property key
* @param val Color value in RGB format.
* @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
* @ingroup Ecore_Config_Set_Group
* @deprecated
*/
int
ecore_config_rgb_set(const char *key, char *val)
{
char *argb;
int ret;
argb = ecore_config_rgb_to_argb(val);
ret = ecore_config_argb_set(key, argb);
free(argb);
return ret;
}
/**
* 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
*/
int
ecore_config_argb_set(const char *key, char *val)
{
return ecore_config_typed_set(key, (void *)val, PT_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
*/
int
ecore_config_theme_set(const char *key, char *val)
{
return ecore_config_typed_set(key, (void *)val, PT_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
*/
int
ecore_config_theme_preview_group_set(const char *key, 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, "", PT_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;
}
int
ecore_config_typed_default(const char *key, 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 & ~PF_MODIFIED;
}
else if (!(e->flags & PF_MODIFIED) && !(e->flags & PF_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 & ~PF_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
*/
int
ecore_config_default(const char *key, 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 == PT_INT)
{
e->step = step;
e->flags |= PF_BOUNDS;
e->lo = lo;
e->hi = hi;
ecore_config_bound(e);
}
else if (type == PT_FLT)
{
e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION);
e->flags |= PF_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
*/
int
ecore_config_boolean_default(const char *key, int val)
{
val = val ? 1 : 0;
return ecore_config_typed_default(key, (void *)&val, PT_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
*/
int
ecore_config_int_default(const char *key, int val)
{
return ecore_config_typed_default(key, (void *)&val, PT_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
*/
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, (void *)&val, PT_INT);
e = ecore_config_get(key);
if (e)
{
e->step = step;
e->flags |= PF_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
*/
int
ecore_config_string_default(const char *key, char *val)
{
return ecore_config_typed_default(key, (void *)val, PT_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
*/
int
ecore_config_float_default(const char *key, float val)
{
return ecore_config_typed_default(key, (void *)&val, PT_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
*/
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, (void *)&val, PT_FLT);
e = ecore_config_get(key);
if (e)
{
e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION);
e->flags |= PF_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 val Color value in RGB format.
* @return @c ECORE_CONFIG_ERR_SUCC if there are no problems.
* @ingroup Ecore_Config_Default_Group
* @deprecated
*/
int
ecore_config_rgb_default(const char *key, char *val)
{
char *argb;
int ret;
argb = ecore_config_rgb_to_argb(val);
ret = ecore_config_argb_default(key, argb);
free(argb);
return ret;
}
/**
* 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
*/
int
ecore_config_argb_default(const char *key, char *val)
{
return ecore_config_typed_default(key, (void *)val, PT_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
*/
int
ecore_config_theme_default(const char *key, char *val)
{
return ecore_config_typed_default(key, (void *)val, PT_THM);
}
/**
* @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
*/
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)
{
E(0, "ecore_config_listen: ecore_config_add(\"%s\") failed: %d\n",
key, ret);
return ret;
}
if (!(e = ecore_config_get(key)))
{
E(0, "ecore_config_listen: list of properties corrupted!?\n");
return ECORE_CONFIG_ERR_FAIL;
}
}
for (l = e->listeners; l; l = l->next)
if (!strcmp(l->name, name) || (l->listener == listener))
{
E(1,
"ecore_config_listen: %s is already listening for changes of %s...\n",
name, key);
return ECORE_CONFIG_ERR_IGNORED;
}
if (!(l = malloc(sizeof(Ecore_Config_Listener_List))))
return ECORE_CONFIG_ERR_OOM;
E(1, "registering listener \"%s\" for \"%s\" (%d)...\n", 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 != PT_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
*/
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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;
}
Ecore_Config_Server *
do_init(char *name)
{
return _ecore_config_ipc_init(name);
}
Ecore_Config_Server *
ecore_config_init_local(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);
}
Ecore_Config_Server *
ecore_config_init_global(char *name)
{
char *p;
int global;
char *buf;
global = 0;
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)
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
*/
int
ecore_config_init(char *name)
{
char *path;
Ecore_Config_Prop *list;
_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;
/* FIXME should free __ecore_config_bundle_local */
list = __ecore_config_bundle_local->data;
__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();
if (path)
{
ecore_config_string_default("/e/themes/search_path", path);
free(path);
}
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
*/
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
*/
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")) && strlen(p) > 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;
if ((p = getenv("HOME")))
{ /* debug-only ### FIXME */
if ((buf = malloc(PATH_MAX * sizeof(char))))
{
snprintf(buf, PATH_MAX, "%s/.e/config.db", p);
if (ecore_config_file_load(buf) != 0)
if (ecore_config_file_load(PACKAGE_DATA_DIR "/system.db") != 0)
return ECORE_CONFIG_ERR_NOFILE;
sys = __ecore_config_bundle_local->data;
while (sys)
{
/* unmark it modified - modification will mean it has been overridden */
sys->flags &= ~PF_MODIFIED;
/* mark as system so that examine can hide them */
sys->flags |= PF_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
*/
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);
free(__ecore_config_bundle_local);
free(__ecore_config_server_local);
free(__ecore_config_server_global);
return ret;
}