275eefd20143ca96d541f621043c02464a2bb648
[framework/uifw/ecore.git] / src / lib / ecore_config / ecore_config.c
1 #include <string.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #include <sys/param.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <limits.h>
11 #include <unistd.h>
12
13 #include "Ecore_Config.h"
14 #include "config.h"
15 #include "ecore_config_private.h"
16 #include "ecore_config_ipc.h"
17
18 #include "ecore_config_util.h"
19
20 int                  DEBUG = 0;
21 EAPI Ecore_Config_Server *__ecore_config_server_global = NULL;
22 EAPI Ecore_Config_Server *__ecore_config_server_local = NULL;
23 EAPI Ecore_Config_Bundle *__ecore_config_bundle_local = NULL;
24 EAPI char                *__ecore_config_app_name = NULL;
25 int                  __ecore_config_system_init = 0;
26
27 static int           _ecore_config_system_init_no_load(void);
28 static int           _ecore_config_system_load(void);
29
30 static inline void  *__ecore_argb_to_long(int a, int r, int g, int b, long *v);
31 static inline void  *__ecore_argbstr_to_long(const char *argb, long *v);
32
33 static const char  *_ecore_config_type[] =
34    { "undefined", "integer", "float", "string", "colour", "theme", "boolean", "structure" };
35
36 /**
37  * @defgroup Ecore_Config_Property_Group Ecore Config Property Functions
38  *
39  * Functions that retrieve or set the attributes relating to a property.
40  */
41
42 /**
43  * Removes the given property from the local configuration and destroys it.
44  * @param   e Property to destroy.
45  * @return  @c NULL
46  * @ingroup Ecore_Config_Property_Group
47  */
48 EAPI Ecore_Config_Prop  *
49 ecore_config_dst(Ecore_Config_Prop * e)
50 {
51    Ecore_Config_Bundle *t;
52    Ecore_Config_Prop  *p, *c;
53    Ecore_Config_Listener_List *l;
54
55    p = NULL;
56    c = e;
57    t = __ecore_config_bundle_local;
58
59    if (!e || !e->key)
60       return NULL;
61    if (t)
62      {
63         if (t->data == e)
64            t->data = e->next;
65         else
66           {
67              do
68                {
69                   p = c;
70                   c = c->next;
71                }
72              while (c && (c != e));
73              if (c)             /* remove from list if even in there */
74                 p->next = c->next;
75           }
76      }
77
78    while (e->listeners)
79      {
80         l = e->listeners;
81         e->listeners = e->listeners->next;
82         free(l);
83      }
84
85    if (e->key)
86       free(e->key);
87    if (e->ptr && ((e->type == ECORE_CONFIG_STR) || (e->type == ECORE_CONFIG_THM)))
88       free(e->ptr);
89
90    memset(e, 0, sizeof(Ecore_Config_Prop));
91    free(e);
92
93    return NULL;
94 }
95
96 /**
97  * @defgroup Ecore_Config_Get_Group Configuration Retrieve Functions
98  *
99  * Functions that retrieve configuration values, based on type.
100  */
101
102 /**
103  * Returns the property with the given key.
104  * @param   key The unique name of the wanted property.
105  * @return  The property that corresponds to the given key.  @c NULL if the
106  *          key could not be found.
107  * @ingroup Ecore_Config_Get_Group
108  */
109 EAPI Ecore_Config_Prop  *
110 ecore_config_get(const char *key)
111 {
112    Ecore_Config_Bundle *t;
113    Ecore_Config_Prop  *e;
114
115    t = __ecore_config_bundle_local;
116    if (!t || !key)
117       return NULL;
118    e = t->data;
119    while (e)
120      {
121         if (!strcmp(key, e->key))
122            return e;
123         e = e->next;
124      }
125    return NULL;
126 }
127
128 /**
129  * Returns the type of the property.
130  * @param   e Property to get the type of.
131  * @returns The type of the property.  If the property is invalid, then the
132  *          string "not found" is returned.
133  * @ingroup Ecore_Config_Property_Group
134  */
135 EAPI const char         *
136 ecore_config_type_get(const Ecore_Config_Prop * e)
137 {
138    if (e)
139      {
140         return _ecore_config_type[e->type];
141      }
142    return "not found";
143 }
144
145 /**
146  * Returns the specified property as a string.
147  * @param   key The property key.
148  * @return  The string value of the property.  The function returns @c NULL if
149  *          the property is not a string or is not set.
150  * @ingroup Ecore_Config_Get_Group
151  */
152 EAPI char               *
153 ecore_config_string_get(const char *key)
154 {
155    return _ecore_config_string_get( ecore_config_get(key) );
156 }
157
158 char               *
159 _ecore_config_string_get(Ecore_Config_Prop *e)
160 {
161    return (e && (e->type == ECORE_CONFIG_STR) && e->ptr) ? strdup(e->ptr) : NULL;
162 }
163
164 /**
165  * Returns the specified property as an integer.
166  * @param   key The property key.
167  * @return  The value of the property.  The function returns -1 if the
168  *          property is not an integer or is not set.
169  * @ingroup Ecore_Config_Get_Group
170  */
171 EAPI int
172 ecore_config_boolean_get(const char *key)
173 {
174    return _ecore_config_boolean_get( ecore_config_get(key) );
175 }
176
177 int
178 _ecore_config_boolean_get(Ecore_Config_Prop *e)
179 {
180    return (e && ((e->type == ECORE_CONFIG_INT) || (e->type == ECORE_CONFIG_BLN))) ? (e->val != 0) : -1;
181 }
182
183 /**
184  * Returns the specified property as a long integer.
185  * @param   key The property key.
186  * @return  The integer value of the property.  The function returns 0 if the
187  *          property is not an integer or is not set.
188  * @ingroup Ecore_Config_Get_Group
189  */
190 EAPI long
191 ecore_config_int_get(const char *key)
192 {
193    return _ecore_config_int_get( ecore_config_get(key) );
194 }
195
196 long
197 _ecore_config_int_get(Ecore_Config_Prop *e)
198 {
199    return (e && ((e->type == ECORE_CONFIG_INT) || (e->type == ECORE_CONFIG_RGB))) ? e->val : 0L;
200 }
201
202 /**
203  * Returns the specified property as a float.
204  * @param   key The property key.
205  * @return  The float value of the property.  The function returns 0.0 if the 
206  *          property is not a float or is not set.
207  * @ingroup Ecore_Config_Get_Group
208  */
209 EAPI float
210 ecore_config_float_get(const char *key)
211 {
212    return _ecore_config_float_get( ecore_config_get(key) );
213 }
214
215 float
216 _ecore_config_float_get(Ecore_Config_Prop *e)
217 {
218    return (e && (e->type == ECORE_CONFIG_FLT)) ? ((float)e->val / ECORE_CONFIG_FLOAT_PRECISION) : 0.0;
219 }
220
221 /**
222  * Finds the alpha, red, green and blue values of a color property.
223  * @param   key The property key.
224  * @param   a   A pointer to an integer to store the alpha value into.
225  * @param   r   A pointer to an integer to store the red value into.
226  * @param   g   A pointer to an integer to store the green value into.
227  * @param   b   A pointer to an integer to store the blue value into.
228  * @return  @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_FAIL
229  *          otherwise.
230  * @ingroup Ecore_Config_Get_Group
231  */
232 EAPI int
233 ecore_config_argb_get(const char *key, int *a, int *r, int *g, int *b)
234 {
235    return _ecore_config_argb_get( ecore_config_get(key), a, r, g, b);
236 }
237
238 int
239 _ecore_config_argb_get(Ecore_Config_Prop *e, int *a, int *r, int *g, int *b)
240 {
241    if (e && ((e->type == ECORE_CONFIG_RGB)))
242      {
243         if(a) *a = (e->val >> 24) & 0xff;
244         if(r) *r = (e->val >> 16) & 0xff;
245         if(g) *g = (e->val >>  8) & 0xff;
246         if(b) *b =  e->val        & 0xff;
247         return ECORE_CONFIG_ERR_SUCC;
248      }
249    return ECORE_CONFIG_ERR_FAIL;
250 }
251
252 /**
253  * Returns a color property as a long
254  * @param   key The property key.
255  * @return  ARGB data as long
256  * @ingroup Ecore_Config_Get_Group
257  */
258 EAPI long
259 ecore_config_argbint_get(const char *key)
260 {
261    return _ecore_config_argbint_get( ecore_config_get(key) );
262 }
263
264 long
265 _ecore_config_argbint_get(Ecore_Config_Prop *e)
266 {
267    if (e && ((e->type == ECORE_CONFIG_RGB)))
268      {
269         return e->val;
270      }
271    return 0L;
272 }
273
274 /**
275  * Returns a color property as a string of hexadecimal characters.
276  * @param   key The property key.
277  * @return  A string of hexadecimal characters in the format #aarrggbb.
278  * @ingroup Ecore_Config_Get_Group
279  */
280 EAPI char               *
281 ecore_config_argbstr_get(const char *key)
282 {
283    return _ecore_config_argbstr_get( ecore_config_get(key) );
284 }
285
286 char               *
287 _ecore_config_argbstr_get(Ecore_Config_Prop *e)
288 {
289    char               *r;
290
291    r = NULL;
292    esprintf(&r, "#%08x", _ecore_config_int_get(e));
293    return r;
294 }
295
296 /**
297  * Returns a theme property.
298  * @param   key The property key.
299  * @return  The name of the theme the property refers to.  The function returns
300  *          @c NULL if the property is not a theme or is not set.
301  * @ingroup Ecore_Config_Get_Group
302  */
303 EAPI char               *
304 ecore_config_theme_get(const char *key)
305 {
306    return _ecore_config_theme_get( ecore_config_get(key) );
307 }
308
309 char               *
310 _ecore_config_theme_get(Ecore_Config_Prop *e)
311 {
312    return (e && (e->type == ECORE_CONFIG_THM)) ? strdup(e->ptr) : NULL;
313 }
314
315 /**
316  * Retrieves the key as a string.
317  * @param   key The property key.
318  * @return  Returns a character array in the form of 'key:type=value'.  @c NULL
319  *          is returned if the property does not exist.
320  * @ingroup Ecore_Config_Get_Group
321  */
322 EAPI char               *
323 ecore_config_as_string_get(const char *key)
324 {
325    Ecore_Config_Prop  *e;
326    char               *val;
327    char               *r;
328
329    val = NULL;
330    r = NULL;
331    if (!(e = ecore_config_get(key)))
332       E(0, "no such property, \"%s\"...\n", key);
333    else
334      {
335         switch (e->type)
336            {
337              case ECORE_CONFIG_NIL:
338                 val = strdup("<nil>");
339                 break;
340              case ECORE_CONFIG_INT:
341                 esprintf(&val, "%ld",    _ecore_config_int_get(e));
342                 break;
343              case ECORE_CONFIG_BLN:
344                 esprintf(&val, "%ld",    _ecore_config_boolean_get(e));
345                 break;
346              case ECORE_CONFIG_FLT:
347                 esprintf(&val, "%lf",    _ecore_config_float_get(e));
348                 break;
349              case ECORE_CONFIG_STR:
350                 esprintf(&val, "\"%s\"", _ecore_config_string_get(e));
351                 break;
352              case ECORE_CONFIG_RGB:
353                 esprintf(&val, "#%08x",  _ecore_config_int_get(e));
354                 break;
355              case ECORE_CONFIG_THM:
356                 esprintf(&val, "\"%s\"", _ecore_config_theme_get(e));
357                 break;
358              case ECORE_CONFIG_SCT:
359                 break;
360              default:
361                 esprintf(&r, "%s:unknown_type", key);
362                 break;
363            }
364         if (val)
365            {
366              esprintf(&r, "%s:%s=%s", key, _ecore_config_type[e->type], val);
367              free(val);
368            }
369      }
370    return r;
371 }
372
373 EAPI int
374 ecore_config_bound(Ecore_Config_Prop * e)
375 {
376    int                 ret;
377    long                v;
378
379    ret = ECORE_CONFIG_ERR_SUCC;
380
381    if (!e)
382       return ECORE_CONFIG_ERR_FAIL;
383    if (e->flags & ECORE_CONFIG_FLAG_BOUNDS)
384      {
385         if ((e->val < e->lo))
386           {
387              E(0,
388                "ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...\n",
389                e->key, e->val, e->lo);
390              e->val = e->lo;
391           }
392         else if ((e->val > e->hi))
393           {
394              E(0,
395                "ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...\n",
396                e->key, e->val, e->hi);
397              e->val = e->hi;
398           }
399         else
400            ret = ECORE_CONFIG_ERR_IGNORED;
401      }
402    else
403       ret = ECORE_CONFIG_ERR_IGNORED;
404
405    if (e->step)
406      {
407         v = ((int)(e->val / e->step)) * e->step;
408         if (v != e->val)
409           {
410              if (e->type == ECORE_CONFIG_FLT)
411                 E(0,
412                   "ecore_config_bound(\"%s\"): float value %f not a multiple of %f, adjusted to %f...\n",
413                   e->key, ((double)e->val) / ECORE_CONFIG_FLOAT_PRECISION,
414                   ((double)e->step) / ECORE_CONFIG_FLOAT_PRECISION,
415                   ((double)v) / ECORE_CONFIG_FLOAT_PRECISION);
416              else
417                 E(0,
418                   "ecore_config_bound(\"%s\"): integer value %ld not a multiple of %ld, adjusted to %ld...\n",
419                   e->key, e->val, e->step, v);
420              ret = ECORE_CONFIG_ERR_SUCC;
421              e->val = v;
422           }
423      }
424
425    return ret;
426 }
427
428 /**
429  * Tries to guess the type of a property.
430  *
431  * This function first checks to see if the property exists.  If it does, then
432  * the type of the stored property is returned.  Otherwise, the function tries
433  * to guess the type of the property based on @p val.
434  *
435  * @param  key The property key.
436  * @param  val The value in string form.
437  * @return The type of the property determined by the function.  Note that if
438  *         val is @c NULL, @c ECORE_CONFIG_NIL will be returned.
439  */
440 EAPI int
441 ecore_config_type_guess(const char *key, const char *val)
442 {
443    Ecore_Config_Prop  *p;
444    char               *l;
445    long                v;
446
447    l = NULL;
448
449    if (key && (p = ecore_config_get(key)) && p->type != ECORE_CONFIG_NIL)
450       return p->type;
451
452    if (!val)
453       return ECORE_CONFIG_NIL;
454    if (val[0] == '#')
455       return ECORE_CONFIG_RGB;
456    v = strtol(val, &l, 10);
457    if (*l)
458      {
459         float               f;
460
461         if (sscanf(val, "%f%*s", &f) != 1)
462            return ECORE_CONFIG_STR;
463         return ECORE_CONFIG_FLT;
464      }
465    return ECORE_CONFIG_INT;
466 }
467
468 static int
469 ecore_config_typed_val(Ecore_Config_Prop * e, const void *val, int type)
470 {
471
472    if (!e)
473      return ECORE_CONFIG_ERR_NODATA;
474
475    if (!(val) && (type != ECORE_CONFIG_NIL && type != ECORE_CONFIG_SCT))
476       e->ptr = NULL;
477    else
478      {
479         if (type == ECORE_CONFIG_INT || type == ECORE_CONFIG_BLN)
480           {
481              e->val = (long) *((int *)val);
482              e->type = type;
483           }
484         else if (type == ECORE_CONFIG_STR || type == ECORE_CONFIG_THM)
485           {
486              if (!(e->ptr = strdup(val)))
487                 return ECORE_CONFIG_ERR_OOM;
488              if (e->type == ECORE_CONFIG_NIL)
489                 e->type = type;
490           }
491         else if (type == ECORE_CONFIG_RGB)
492           {
493              __ecore_argbstr_to_long((char *)val, &e->val);
494              e->type = ECORE_CONFIG_RGB;
495           }
496         else if (type == ECORE_CONFIG_FLT)
497           {
498              e->val = (long) ((*((float *)val)) * ECORE_CONFIG_FLOAT_PRECISION);
499              e->type = ECORE_CONFIG_FLT;
500           }
501         else if (type == ECORE_CONFIG_SCT)
502           {
503              e->type = ECORE_CONFIG_SCT;
504           }
505         else
506           {
507            e->type = ECORE_CONFIG_NIL;
508           }
509
510         ecore_config_bound(e);
511         e->flags |= ECORE_CONFIG_FLAG_MODIFIED;
512         e->flags &= ~ECORE_CONFIG_FLAG_CMDLN;
513         return ECORE_CONFIG_ERR_SUCC;
514      }
515    return ECORE_CONFIG_ERR_IGNORED;
516 }
517
518 static int
519 ecore_config_typed_add(const char *key, const void *val, int type)
520 {
521    int error = ECORE_CONFIG_ERR_SUCC;
522    Ecore_Config_Prop  *e = NULL;
523    Ecore_Config_Bundle *t;
524
525    t = __ecore_config_bundle_local;
526    if (!key)
527       return ECORE_CONFIG_ERR_NODATA;
528
529    if (!(e = calloc(1, sizeof(Ecore_Config_Prop))))
530      {
531         error = ECORE_CONFIG_ERR_OOM;
532      }
533    else if (!(e->key = strdup(key)))
534      {
535         error = ECORE_CONFIG_ERR_OOM;
536      }
537    else if ((error = ecore_config_typed_val(e, val, type)) == ECORE_CONFIG_ERR_SUCC)
538      {
539         if (t)
540            {
541              e->next = t->data;
542              t->data = e;
543            }
544         return ECORE_CONFIG_ERR_SUCC;
545      }
546
547    if(e->key)
548      free(e->key);
549    if(e)
550      free(e);
551
552    if (error == ECORE_CONFIG_ERR_SUCC)
553       error = ECORE_CONFIG_ERR_FAIL;
554
555    return error;
556 }
557
558 static int
559 ecore_config_add(const char *key, const char *val)
560 {
561    int                 type;
562
563    type = ecore_config_type_guess(key, val);
564    return ecore_config_typed_add(key, val, type);
565 }
566
567 /**
568  * Sets the description field of the indicated property.
569  * @param   key  The property key.
570  * @param   desc Description string.
571  * @note    The description string is copied for the property's use.  You can
572  *          free @p desc once this function is called.
573  * @ingroup Ecore_Config_Property_Group
574  */
575 EAPI int
576 ecore_config_describe(const char *key, const char *desc)
577 {
578    Ecore_Config_Prop  *e;
579
580    if (!(e = ecore_config_get(key)))
581       return ECORE_CONFIG_ERR_NODATA;
582    e->description = strdup(desc);
583    return ECORE_CONFIG_ERR_SUCC;
584 }
585
586 /**
587  * Set the short option character of a property.
588  * @param   key       The property key.
589  * @param   short_opt Character used to indicate the value of a property
590  *                    given on the command line.
591  * @return  @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_NODATA
592  *          is returned if the property does not exist.
593  * @ingroup Ecore_Config_Property_Group
594  */
595 EAPI int
596 ecore_config_short_opt_set(const char *key, char short_opt)
597 {
598    Ecore_Config_Prop  *e;
599
600    if (!(e = ecore_config_get(key)))
601       return ECORE_CONFIG_ERR_NODATA;
602    e->short_opt = short_opt;
603    return ECORE_CONFIG_ERR_SUCC;
604 }
605
606 /**
607  * Set the long option string of the property.
608  * @param   key      The property key.
609  * @param   long_opt String used to indicate the value of a property given
610  *                   on the command line.
611  * @return  @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_NODATA
612  *          is returned if the property does not exist.
613  * @ingroup Ecore_Config_Property_Group
614  */
615 EAPI int
616 ecore_config_long_opt_set(const char *key, const char *long_opt)
617 {
618    Ecore_Config_Prop  *e;
619
620    if (!(e = ecore_config_get(key)))
621       return ECORE_CONFIG_ERR_NODATA;
622    if (e->long_opt)
623       free(e->long_opt);
624    if (long_opt)
625       e->long_opt = strdup(long_opt);
626    return ECORE_CONFIG_ERR_SUCC;
627 }
628
629 static void
630 _ecore_config_listener_fire(Ecore_Config_Prop *prop)
631 {
632    Ecore_Config_Listener_List *l;
633    for (l = prop->listeners; l; l = l->next)
634      l->listener(prop->key, prop->type, l->tag, l->data);
635
636    /* fire change listeners for the generic struct container etc */
637    if (prop->parent)
638      _ecore_config_listener_fire(prop->parent);
639 }
640
641 /**
642  * Sets the indicated property to the given value and type.
643  * @param   key  The property key.
644  * @param   val  A pointer to the value to set the property to.
645  * @param   type The type of the property.
646  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
647  * @ingroup Ecore_Config_Property_Group
648  */
649 EAPI int
650 ecore_config_typed_set(const char *key, const void *val, int type)
651 {
652    Ecore_Config_Prop  *e;
653    int                 ret;
654
655    if (!key)
656       return ECORE_CONFIG_ERR_NODATA;
657 /*  if (!t) { * global prop *
658     e=ecore_config_get(key);
659     if (e)
660       for(l=e->listeners;l;l=l->next)
661         l->listener(e->key,e->type,l->tag,l->data,t);
662     return ECORE_CONFIG_ERR_SUCC;
663   }
664 */
665    if (!(e = ecore_config_get(key)))
666       return ecore_config_typed_add(key, val, type);
667
668    if ((ret = ecore_config_typed_val(e, val, type)) == ECORE_CONFIG_ERR_SUCC)
669      {
670        _ecore_config_listener_fire(e);
671      }
672    else
673      {
674         E(0,
675           "ecore_config_typed_set(\"%s\"): ecore_config_typed_val() failed: %d\n",
676           key, ret);
677      }
678
679    return ret;
680 }
681
682 /**
683  * @defgroup Ecore_Config_Set_Group Ecore Config Setters
684  *
685  * Functions that set the value of a property.
686  */
687
688 /**
689  * Sets the indicated property to the value indicated by @a val.
690  * @param   key The property key.
691  * @param   val String representation of value to set.
692  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
693  * @ingroup Ecore_Config_Set_Group
694  */
695 EAPI int
696 ecore_config_set(const char *key, const char *val)
697 {
698    int                 type;
699    int                 tmpi;
700    float               tmpf;
701    long                tmpl;
702
703    type = ecore_config_type_guess(key, val);
704    if (type == ECORE_CONFIG_INT || type == ECORE_CONFIG_BLN)
705      {
706         tmpi = atoi(val);
707         return ecore_config_typed_set(key, &tmpi, type);
708      }
709    else if (type == ECORE_CONFIG_FLT)
710      {
711         tmpf = atof(val);
712         return ecore_config_typed_set(key, &tmpf, type);
713      }
714    else if (type == ECORE_CONFIG_RGB)
715      {
716         __ecore_argbstr_to_long(val, &tmpl);
717         return ecore_config_typed_set(key, &tmpl, type);
718      }
719    else
720       return ecore_config_typed_set(key, val, type);
721 }
722
723 /**
724  * Sets the indicated property to the value given in the string.
725  * @param   key The property key.
726  * @param   val String representation of the value.
727  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
728  * @ingroup Ecore_Config_Set_Group
729  */
730 EAPI int
731 ecore_config_as_string_set(const char *key, const char *val)
732 {
733    return ecore_config_set(key, val);
734 }
735
736 /**
737  * Sets the indicated property to the given boolean.
738  * @param   key The property key.
739  * @param   val Boolean integer to set the property to.
740  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
741  * @ingroup Ecore_Config_Set_Group
742  */
743 EAPI int
744 ecore_config_boolean_set(const char *key, int val)
745 {
746    val = val ? 1 : 0;
747    return ecore_config_typed_set(key, &val, ECORE_CONFIG_BLN);
748 }
749
750 /**
751  * Sets the indicated property to the given integer.
752  * @param   key The property key.
753  * @param   val Integer to set the property to.
754  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
755  * @ingroup Ecore_Config_Set_Group
756  */
757 EAPI int
758 ecore_config_int_set(const char *key, int val)
759 {
760    return ecore_config_typed_set(key, &val, ECORE_CONFIG_INT);
761 }
762
763 /**
764  * Sets the indicated property to the given string.
765  * @param   key The property key.
766  * @param   val String to set the property to.
767  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
768  * @ingroup Ecore_Config_Set_Group
769  */
770 EAPI int
771 ecore_config_string_set(const char *key, const char *val)
772 {
773    return ecore_config_typed_set(key, val, ECORE_CONFIG_STR);
774 }
775
776 /**
777  * Sets the indicated property to the given float value.
778  * @param   key The property key.
779  * @param   val Float to set the property to.
780  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
781  * @ingroup Ecore_Config_Set_Group
782  */
783 EAPI int
784 ecore_config_float_set(const char *key, float val)
785 {
786    return ecore_config_typed_set(key, &val, ECORE_CONFIG_FLT);
787 }
788
789 /**
790  * Sets the indicated property to a color value.
791  * @param   key The property key
792  * @param   a integer 0..255
793  * @param   r integer 0..255
794  * @param   g integer 0..255
795  * @param   b integer 0..255
796  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
797  * @ingroup Ecore_Config_Set_Group
798  */
799 EAPI int
800 ecore_config_argb_set(const char *key, int a, int r, int g, int b)
801 {
802    long v = 0;
803    return ecore_config_typed_set(key, __ecore_argb_to_long(a,r,g,b, &v), ECORE_CONFIG_RGB);
804 }
805
806 /**
807  * Sets the indicated property to a color value.
808  * @param   key The property key
809  * @param   argb ARGB data as long
810  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
811  * @ingroup Ecore_Config_Set_Group
812  */
813 EAPI int
814 ecore_config_argbint_set(const char *key, long argb)
815 {
816    return ecore_config_typed_set(key, &argb, ECORE_CONFIG_RGB);
817 }
818
819 /**
820  * Sets the indicated property to a color value.
821  * @param   key The property key
822  * @param   val Color value in ARGB format.
823  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
824  * @ingroup Ecore_Config_Set_Group
825  */
826 EAPI int
827 ecore_config_argbstr_set(const char *key, const char *val)
828 {
829    long v = 0;
830    return ecore_config_typed_set(key, __ecore_argbstr_to_long(val, &v), ECORE_CONFIG_RGB);
831 }
832
833 /**
834  * Sets the indicated property to a theme name.
835  * @param   key The property key.
836  * @param   val String giving the name of the theme.
837  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
838  * @ingroup Ecore_Config_Set_Group
839  */
840 EAPI int
841 ecore_config_theme_set(const char *key, const char *val)
842 {
843    return ecore_config_typed_set(key, val, ECORE_CONFIG_THM);
844 }
845
846 /**
847  * Sets the theme preview group of an indicated property.
848  * @param   key   The property key.
849  * @param   group The group name.
850  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
851  * @ingroup Ecore_Config_Set_Group
852  */
853 EAPI int
854 ecore_config_theme_preview_group_set(const char *key, const char *group)
855 {
856    int                 ret;
857    Ecore_Config_Prop  *e;
858
859    ret = ECORE_CONFIG_ERR_SUCC;
860    if (!(e = ecore_config_get(key)))
861      {                          /* prop doesn't exist yet */
862         if ((ret = ecore_config_typed_add(key, "", ECORE_CONFIG_THM)) != ECORE_CONFIG_ERR_SUCC) /* try to add it */
863            return ret;          /* ...failed */
864         if (!(e = ecore_config_get(key)))       /* get handle */
865            return ECORE_CONFIG_ERR_FAIL;
866      }
867    if (e->data)
868       free(e->data);
869    e->data = strdup(group);
870
871    return ret;
872 }
873
874 EAPI int
875 ecore_config_typed_default(const char *key, const void *val, int type)
876 {
877    int                 ret;
878    Ecore_Config_Prop  *e;
879
880    ret = ECORE_CONFIG_ERR_SUCC;
881
882    if (!(e = ecore_config_get(key)))
883      {                          /* prop doesn't exist yet */
884         if ((ret = ecore_config_typed_add(key, val, type)) != ECORE_CONFIG_ERR_SUCC)    /* try to add it */
885            return ret;          /* ...failed */
886         if (!(e = ecore_config_get(key)))       /* get handle */
887            return ECORE_CONFIG_ERR_FAIL;
888         e->flags = e->flags & ~ECORE_CONFIG_FLAG_MODIFIED;
889      }
890    else if (!(e->flags & ECORE_CONFIG_FLAG_MODIFIED) && !(e->flags & ECORE_CONFIG_FLAG_SYSTEM))
891      {
892         ecore_config_typed_set(key, val, type);
893         if (!(e = ecore_config_get(key)))       /* get handle */
894            return ECORE_CONFIG_ERR_FAIL;
895         e->flags = e->flags & ~ECORE_CONFIG_FLAG_MODIFIED;
896      }
897    return ret;
898 }
899
900 /**
901  * @defgroup Ecore_Config_Default_Group Ecore Config Defaults
902  *
903  * Functions that are used to set the default values of properties.
904  */
905
906 /**
907  * Sets the indicated property if it has not already been set or loaded.
908  * @param   key  The property key.
909  * @param   val  Default value of the key.
910  * @param   lo   Lowest valid value for the key.
911  * @param   hi   Highest valid value for the key.
912  * @param   step Used by integer and float values.
913  * @return  @c ECORE_CONFIG_ERR_SUCC if there are no errors.
914  * @note    The @p lo, @p hi and @p step parameters are only used when storing
915  *          integer and float properties.
916  * @ingroup Ecore_Config_Default_Group
917  */
918 EAPI int
919 ecore_config_default(const char *key, const char *val, float lo, float hi, float step)
920 {
921    int                 ret, type;
922    Ecore_Config_Prop  *e;
923
924    type = ecore_config_type_guess(key, val);
925    ret = ecore_config_typed_default(key, val, type);
926    e = ecore_config_get(key);
927    if (e)
928      {
929         if (type == ECORE_CONFIG_INT)
930           {
931              e->step = step;
932              e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
933              e->lo = lo;
934              e->hi = hi;
935              ecore_config_bound(e);
936           }
937         else if (type == ECORE_CONFIG_FLT)
938           {
939              e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION);
940              e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
941              e->lo = (int)(lo * ECORE_CONFIG_FLOAT_PRECISION);
942              e->hi = (int)(hi * ECORE_CONFIG_FLOAT_PRECISION);
943              ecore_config_bound(e);
944           }
945      }
946
947    return ret;
948 }
949
950 /**
951  * Sets the indicated property to the given boolean if the property has not yet
952  * been set.
953  * @param   key The property key.
954  * @param   val Boolean Integer to set the value to.
955  * @return  @c ECORE_CONFIG_ERR_SUCC if there are no problems.
956  * @ingroup Ecore_Config_Default_Group
957  */
958 EAPI int
959 ecore_config_boolean_default(const char *key, int val)
960 {
961    val = val ? 1 : 0;
962    return ecore_config_typed_default(key, &val, ECORE_CONFIG_BLN);
963 }
964
965 /**
966  * Sets the indicated property to the given integer if the property has not yet
967  * been set.
968  * @param   key The property key.
969  * @param   val Integer to set the value to.
970  * @return  @c ECORE_CONFIG_ERR_SUCC if there are no problems.
971  * @ingroup Ecore_Config_Default_Group
972  */
973 EAPI int
974 ecore_config_int_default(const char *key, int val)
975 {
976    return ecore_config_typed_default(key, &val, ECORE_CONFIG_INT);
977 }
978
979 /**
980  * Sets the indicated property to the given integer if the property has not yet
981  * been set.
982  *
983  * The bounds and step values are set regardless.
984  *
985  * @param   key  The property key.
986  * @param   val  Integer to set the property to.
987  * @param   low  Lowest valid integer value for the property.
988  * @param   high Highest valid integer value for the property.
989  * @param   step Increment value for the property.
990  * @return  @c ECORE_CONFIG_ERR_SUCC if there were no problems.
991  * @ingroup Ecore_Config_Default_Group
992  */
993 EAPI int
994 ecore_config_int_default_bound(const char *key, int val, int low, int high,
995                                int step)
996 {
997    Ecore_Config_Prop  *e;
998    int                 ret;
999
1000    ret = ecore_config_typed_default(key, &val, ECORE_CONFIG_INT);
1001    e = ecore_config_get(key);
1002    if (e)
1003      {
1004         e->step = step;
1005         e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
1006         e->lo = low;
1007         e->hi = high;
1008         ecore_config_bound(e);
1009      }
1010
1011    return ret;
1012 }
1013
1014 /**
1015  * Sets the indicated property to the given string if the property has not yet
1016  * been set.
1017  * @param   key The property key.
1018  * @param   val String to set the property to.
1019  * @return  @c ECORE_CONFIG_ERR_SUCC if there were no problems.
1020  * @ingroup Ecore_Config_Default_Group
1021  */
1022 EAPI int
1023 ecore_config_string_default(const char *key, const char *val)
1024 {
1025    return ecore_config_typed_default(key, val, ECORE_CONFIG_STR);
1026 }
1027
1028 /**
1029  * Sets the indicated property to the given float if the property has not yet
1030  * been set.
1031  * @param   key The property key.
1032  * @param   val Float to set the property to.
1033  * @return  @c ECORE_CONFIG_ERR_SUCC if there were no problems.
1034  * @ingroup Ecore_Config_Default_Group
1035  */
1036 EAPI int
1037 ecore_config_float_default(const char *key, float val)
1038 {
1039    return ecore_config_typed_default(key, &val, ECORE_CONFIG_FLT);
1040 }
1041
1042 /**
1043  * Sets the indicated property to the given float if the property has not yet
1044  * been set.
1045  *
1046  * The bounds and step values are set regardless.
1047  *
1048  * @param   key  The property key.
1049  * @param   val  Float to set the property to.
1050  * @param   low  Lowest valid integer value for the property.
1051  * @param   high Highest valid float value for the property.
1052  * @param   step Increment value for the property.
1053  * @return  @c ECORE_CONFIG_ERR_SUCC if there were no problems.
1054  * @ingroup Ecore_Config_Default_Group
1055  */
1056 EAPI int
1057 ecore_config_float_default_bound(const char *key, float val, float low,
1058                                  float high, float step)
1059 {
1060    Ecore_Config_Prop  *e;
1061    int                 ret;
1062
1063    ret = ecore_config_typed_default(key, &val, ECORE_CONFIG_FLT);
1064    e = ecore_config_get(key);
1065    if (e)
1066      {
1067         e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION);
1068         e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
1069         e->lo = (int)(low * ECORE_CONFIG_FLOAT_PRECISION);
1070         e->hi = (int)(high * ECORE_CONFIG_FLOAT_PRECISION);
1071         ecore_config_bound(e);
1072      }
1073
1074    return ret;
1075 }
1076
1077 /**
1078  * Sets the indicated property to a color value if the property has not yet
1079  * been set.
1080  * @param  key The property key.
1081  * @param  a integer 0..255
1082  * @param  r integer 0..255
1083  * @param  g integer 0..255
1084  * @param  b integer 0..255
1085  * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems.
1086  * @ingroup Ecore_Config_Default_Group
1087  */
1088 EAPI int
1089 ecore_config_argb_default(const char *key, int a, int r, int g, int b)
1090 {
1091    long v = 0;
1092    return ecore_config_typed_default(key, __ecore_argb_to_long(a,r,g,b, &v), ECORE_CONFIG_RGB);
1093 }
1094
1095 /**
1096  * Sets the indicated property to a color value if the property has not yet
1097  * been set.
1098  * @param  key The property key.
1099  * @param  argb ARGB data as long
1100  * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems.
1101  * @ingroup Ecore_Config_Default_Group
1102  */
1103 EAPI int
1104 ecore_config_argbint_default(const char *key, long argb)
1105 {
1106    return ecore_config_typed_default(key, &argb, ECORE_CONFIG_RGB);
1107 }
1108
1109 /**
1110  * Sets the indicated property to a color value if the property has not yet
1111  * been set.
1112  * @param  key The property key.
1113  * @param  val Color value in ARGB format.
1114  * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems.
1115  * @ingroup Ecore_Config_Default_Group
1116  */
1117 EAPI int
1118 ecore_config_argbstr_default(const char *key, const char *val)
1119 {
1120    long v = 0;
1121    return ecore_config_typed_default(key, __ecore_argbstr_to_long(val, &v), ECORE_CONFIG_RGB);
1122 }
1123
1124 /**
1125  * Sets the indicated property to a theme name if the property has not yet
1126  * been set.
1127  * @param   key The property key.
1128  * @param   val String giving the name of the theme.
1129  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
1130  * @ingroup Ecore_Config_Default_Group
1131  */
1132 EAPI int
1133 ecore_config_theme_default(const char *key, const char *val)
1134 {
1135    return ecore_config_typed_default(key, val, ECORE_CONFIG_THM);
1136 }
1137
1138 /**
1139  * @defgroup Ecore_Config_Struct_Group Ecore Config Structures
1140  *
1141  * Functions that are used to create structures of properties.
1142  */
1143
1144 /**
1145  * Sets the indicated property to a structure if the property has not yet
1146  * been set.
1147  * @param   key The property key.
1148  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
1149  * @ingroup Ecore_Config_Struct_Group
1150  */
1151 EAPI int
1152 ecore_config_struct_create(const char *key)
1153 {
1154    printf("WARNING: you are using ecore_config structures. These are very young");
1155    printf(" and not complete - you have been warned");
1156
1157    return ecore_config_typed_default(key, NULL, ECORE_CONFIG_SCT);
1158 }
1159
1160 static int
1161 _ecore_config_struct_append(Ecore_Config_Prop *sct, Ecore_Config_Prop *add)
1162 {
1163    Evas_List *l;
1164
1165    if (!sct || !add || sct->type != ECORE_CONFIG_SCT)
1166      return ECORE_CONFIG_ERR_IGNORED;
1167
1168    l = sct->data;
1169    sct->data = evas_list_append(l, add);
1170    add->parent = sct;
1171
1172    return ECORE_CONFIG_ERR_SUCC;
1173 }
1174
1175 static int
1176 _ecore_config_struct_typed_add(const char *key, const char *name, const void *val,
1177     int type)
1178 {
1179    char *subkey;
1180    int ret;
1181
1182    subkey = malloc((strlen(key) + strlen(name) + 2) * sizeof(char));
1183    strcpy(subkey, key);
1184    strcat(subkey, ".");
1185    strcat(subkey, name);
1186
1187    ecore_config_typed_default(subkey, val, type);
1188    ret = _ecore_config_struct_append(ecore_config_get(key),
1189                                      ecore_config_get(subkey));
1190    free(subkey);
1191    return ret;   
1192 }
1193
1194 /**
1195  * Add an int property to the named structure. The property is set if it has not
1196  * yet been set.
1197  * @param   key The key of the structure to add to.
1198  * @param   name The name of the item to add - this will be appended to the key
1199  * @param   val the int to default to
1200  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
1201  * @ingroup Ecore_Config_Struct_Group
1202  */
1203 EAPI int
1204 ecore_config_struct_int_add(const char *key, const char *name, int val)
1205 {
1206    return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_INT);
1207 }
1208
1209 /**
1210  * Add a float property to the named structure. The property is set if it has
1211  * not yet been set.
1212  * @param   key The key of the structure to add to.
1213  * @param   name The name of the item to add - this will be appended to the key
1214  * @param   val The float to default to
1215  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
1216  * @ingroup Ecore_Config_Struct_Group
1217  */
1218 EAPI int
1219 ecore_config_struct_float_add(const char *key, const char *name, float val)
1220 {
1221    return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_FLT);
1222 }
1223
1224 /**
1225  * Add a string property to the named structure. The property is set if it has
1226  * not yet been set.
1227  * @param   key The key of the structure to add to.
1228  * @param   name The name of the item to add - this will be appended to the key
1229  * @param   val The string to default to
1230  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
1231  * @ingroup Ecore_Config_Struct_Group
1232  */
1233 EAPI int
1234 ecore_config_struct_string_add(const char *key, const char *name, const char* val)
1235 {
1236    return _ecore_config_struct_typed_add(key, name, val, ECORE_CONFIG_STR);
1237 }
1238
1239 /**
1240  * Add an argb property to the named structure. The property is set if it has
1241  * not yet been set.
1242  * @param   key The key of the structure to add to.
1243  * @param   name The name of the item to add - this will be appended to the key
1244  * @param   a The alpha to default to
1245  * @param   r The red to default to
1246  * @param   g The green to default to
1247  * @param   b The blue to default to
1248  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
1249  * @ingroup Ecore_Config_Struct_Group
1250  */
1251 EAPI int
1252 ecore_config_struct_argb_add(const char *key, const char *name, int a, int r,
1253                              int g, int b)
1254 {
1255    long argb;
1256   
1257    __ecore_argb_to_long(a, r, g, b, &argb);
1258    return _ecore_config_struct_typed_add(key, name, &argb, ECORE_CONFIG_RGB);
1259 }
1260
1261 /**
1262  * Add a theme property to the named structure. The property is set if it has
1263  * not yet been set.
1264  * @param   key The key of the structure to add to.
1265  * @param   name The name of the item to add - this will be appended to the key
1266  * @param   val The theme name to default to
1267  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
1268  * @ingroup Ecore_Config_Struct_Group
1269  */
1270 EAPI int
1271 ecore_config_struct_theme_add(const char *key, const char *name, const char* val)
1272 {
1273    return _ecore_config_struct_typed_add(key, name, val, ECORE_CONFIG_THM);
1274 }
1275
1276 /**
1277  * Add a boolean property to the named structure. The property is set if it has
1278  * not yet been set.
1279  * @param   key The key of the structure to add to.
1280  * @param   name The name of the item to add - this will be appended to the key
1281  * @param   val The boolean to default to
1282  * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
1283  * @ingroup Ecore_Config_Struct_Group
1284  */
1285 EAPI int
1286 ecore_config_struct_boolean_add(const char *key, const char *name, int val)
1287 {
1288    val = val ? 1 : 0;
1289    return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_BLN);
1290 }
1291
1292 /**
1293  * Get the contents of a defined structure property and load it into the passed
1294  * C struct
1295  * @param   key The name of the structure property to look up.
1296  * @param   data The struct to write into.
1297  * @return  @c ECORE_CONFIG_ERR_SUCC if the structure is written successfully.
1298  * @ingroup Ecore_Config_Struct_Group
1299  */
1300 EAPI int
1301 ecore_config_struct_get(const char *key, void *data)
1302 {
1303    Ecore_Config_Prop *e, *f;
1304    Evas_List *l;
1305    unsigned char *ptr;
1306    long argb;
1307
1308    e = ecore_config_get(key);
1309    if (!e)
1310      return ECORE_CONFIG_ERR_NODATA;
1311
1312    l = e->data;
1313    ptr = data;
1314    while (l)
1315      {
1316         f = (Ecore_Config_Prop *) l->data;
1317         switch (f->type)
1318           {
1319              case ECORE_CONFIG_INT:
1320                *((int *) ptr) = _ecore_config_int_get(f);
1321                ptr += sizeof(int);
1322              break;
1323              case ECORE_CONFIG_BLN:
1324                *((int *) ptr) = _ecore_config_boolean_get(f);
1325                ptr += sizeof(int);
1326              break;
1327              case ECORE_CONFIG_FLT:
1328                *((float *) ptr) = _ecore_config_float_get(f);
1329                ptr += sizeof(float);
1330              break;
1331              case ECORE_CONFIG_STR:
1332              case ECORE_CONFIG_THM:
1333                *((char **) ptr) = _ecore_config_string_get(f);
1334                ptr += sizeof(char *);
1335              break;
1336              case ECORE_CONFIG_RGB:
1337                argb = _ecore_config_argbint_get(f);
1338                *((int *) ptr) = (argb >> 24) & 0xff;
1339                ptr += sizeof(int);
1340                *((int *) ptr) = (argb >> 16) & 0xff;
1341                ptr += sizeof(int);
1342                *((int *) ptr) = (argb >> 8) & 0xff;
1343                ptr += sizeof(int);
1344                *((int *) ptr) = argb & 0xff;
1345                ptr += sizeof(int);
1346              break;
1347              default:
1348                printf("ARGH - STRUCT coding not implemented yet\n");
1349           }
1350         l = evas_list_next(l);
1351      }
1352    return ECORE_CONFIG_ERR_SUCC;
1353 }
1354
1355 /**
1356  * @defgroup Ecore_Config_Listeners_Group Ecore Config Listeners
1357  *
1358  * Functions that set and unset property listener callbacks.
1359  */
1360
1361 /**
1362  * Adds a callback function to the list of functions called when a property
1363  * changes.
1364  * @param   name     Name of the callback.
1365  * @param   key      The key of the property to listen to.
1366  * @param   listener Listener callback function.
1367  * @param   tag      Tag to pass to @p listener when it is called.
1368  * @param   data     Data to pass to @p listener when it is called.
1369  * @return  @c ECORE_CONFIG_ERR_SUCC if successful in setting up the callback.
1370  * @ingroup Ecore_Config_Listeners_Group
1371  */
1372 EAPI int
1373 ecore_config_listen(const char *name, const char *key,
1374                     Ecore_Config_Listener listener, int tag, void *data)
1375 {
1376    Ecore_Config_Prop  *e;
1377    Ecore_Config_Listener_List *l;
1378
1379    if (!key)
1380       return ECORE_CONFIG_ERR_NODATA;
1381
1382    if (!(e = ecore_config_get(key)))
1383      {
1384         int                 ret = ecore_config_add(key, "");
1385
1386         if (ret != ECORE_CONFIG_ERR_SUCC)
1387           {
1388              E(0, "ecore_config_listen: ecore_config_add(\"%s\") failed: %d\n",
1389                key, ret);
1390              return ret;
1391           }
1392         if (!(e = ecore_config_get(key)))
1393           {
1394              E(0, "ecore_config_listen: list of properties corrupted!?\n");
1395              return ECORE_CONFIG_ERR_FAIL;
1396           }
1397      }
1398
1399    for (l = e->listeners; l; l = l->next)
1400       if (!strcmp(l->name, name) || (l->listener == listener))
1401         {
1402            E(1,
1403              "ecore_config_listen: %s is already listening for changes of %s...\n",
1404              name, key);
1405            return ECORE_CONFIG_ERR_IGNORED;
1406         }
1407
1408    if (!(l = malloc(sizeof(Ecore_Config_Listener_List))))
1409       return ECORE_CONFIG_ERR_OOM;
1410
1411    E(1, "registering listener \"%s\" for \"%s\" (%d)...\n", name, key, e->type);
1412
1413    memset(l, 0, sizeof(Ecore_Config_Listener_List));
1414
1415    l->listener = listener;
1416    l->name = name;
1417    l->data = data;
1418    l->tag = tag;
1419    l->next = e->listeners;
1420    e->listeners = l;
1421
1422    if (e->type != ECORE_CONFIG_NIL)     /* call right on creation if prop exists and has val */
1423       listener(key, e->type, tag, data);
1424
1425    return ECORE_CONFIG_ERR_SUCC;
1426 }
1427
1428 /**
1429  * Removes a listener callback.
1430  * @param  name     Name of the callback to remove.
1431  * @param  key      The property key the callback is listening to.
1432  * @param  listener The callback function to remove.
1433  * @return @c ECORE_CONFIG_ERR_SUCC if successful in removing the callback.
1434  *         If no callback matches the given parameters, then
1435  *         @c ECORE_CONFIG_ERR_NOTFOUND is returned.  If @c NULL is passed
1436  *         for the key pointer, @c ECORE_CONFIG_ERR_NODATA is returned.
1437  * @ingroup Ecore_Config_Listeners_Group
1438  */
1439 EAPI int
1440 ecore_config_deaf(const char *name, const char *key,
1441                   Ecore_Config_Listener listener)
1442 {
1443    Ecore_Config_Prop  *e;
1444    Ecore_Config_Listener_List *l, *p;
1445    int                 ret;
1446
1447    ret = ECORE_CONFIG_ERR_NOTFOUND;
1448
1449    if (!key)
1450       return ECORE_CONFIG_ERR_NODATA;
1451
1452    if (!(e = ecore_config_get(key)))
1453       return ECORE_CONFIG_ERR_NOTFOUND;
1454
1455    for (p = NULL, l = e->listeners; l; p = l)
1456      {
1457         Ecore_Config_Listener_List *nl;
1458         
1459         nl = l->next;
1460         if ((name && !strcmp(l->name, name)) || (l->listener == listener))
1461           {
1462              ret = ECORE_CONFIG_ERR_SUCC;
1463              if (!p)
1464                 e->listeners = e->listeners->next;
1465              else
1466                 p->next = l->next;
1467              memset(l, 0, sizeof(Ecore_Config_Listener));
1468              free(l);
1469           }
1470         l = nl;
1471      }
1472
1473    return ret;
1474 }
1475
1476 /**
1477  * Locates the first configuration bundle on the given server.
1478  * @param  srv The configuration server.
1479  * @return Pointer to the first configuration bundle.
1480  */
1481 EAPI Ecore_Config_Bundle *
1482 ecore_config_bundle_1st_get(Ecore_Config_Server * srv)
1483 {                               /* anchor: global, but read-only */
1484    return srv->bundles;
1485 }
1486
1487 /**
1488  * Locates the configuration bundle after the given one.
1489  * @param  ns  The configuration bundle.
1490  * @return The next configuration bundle.
1491  */
1492 EAPI Ecore_Config_Bundle *
1493 ecore_config_bundle_next_get(Ecore_Config_Bundle * ns)
1494 {
1495    return ns ? ns->next : NULL;
1496 }
1497
1498 /**
1499  * Locates a configuration bundle on a configuration server based on its serial
1500  * number.
1501  * @param  srv    The configuration server.
1502  * @param  serial Serial number.
1503  * @return The configuration bundle with the given serial number.
1504  */
1505 EAPI Ecore_Config_Bundle *
1506 ecore_config_bundle_by_serial_get(Ecore_Config_Server * srv, long serial)
1507 {
1508    Ecore_Config_Bundle *eb;
1509
1510    eb = srv->bundles;
1511
1512    if (serial < 0)
1513       return NULL;
1514    else if (serial == 0)
1515      {
1516         Ecore_Config_Bundle *r = eb;
1517
1518         return r;
1519      }
1520
1521    while (eb)
1522      {
1523         if (eb->serial == serial)
1524            return eb;
1525         eb = eb->next;
1526      }
1527    return NULL;
1528 }
1529
1530 /**
1531  * Gets the Ecore_Config_Bundle with the given identifier from the given
1532  * server.
1533  * @param  srv   The configuration server.
1534  * @param  label The bundle's identifier string.
1535  * @return The bundle with the given identifier string, or @c NULL if it
1536  *         could not be found.
1537  */
1538 EAPI Ecore_Config_Bundle *
1539 ecore_config_bundle_by_label_get(Ecore_Config_Server * srv, const char *label)
1540 {
1541    Ecore_Config_Bundle *ns;
1542
1543    ns = srv->bundles;
1544
1545    while (ns)
1546      {
1547         if (ns->identifier && !strcmp(ns->identifier, label))
1548            return ns;
1549         ns = ns->next;
1550      }
1551    return NULL;
1552 }
1553
1554 /**
1555  * Retrieves the bundle's serial number.
1556  * @param  ns The configuration bundle.
1557  * @return The bundle's identifier string, or -1 if ns is @c NULL.
1558  */
1559 EAPI long
1560 ecore_config_bundle_serial_get(Ecore_Config_Bundle * ns)
1561 {
1562    return ns ? ns->serial : -1;
1563 }
1564
1565 /**
1566  * Retrieves the bundle's identifier.
1567  * @param  ns The configuration bundle.
1568  * @return The bundle's identifer string.
1569  */
1570 EAPI char               *
1571 ecore_config_bundle_label_get(Ecore_Config_Bundle * ns)
1572 {
1573    return ns ? ns->identifier : NULL;
1574 }
1575
1576 /**
1577  * Creates a new Ecore_Config_Bundle.
1578  * @param  srv        Config server.
1579  * @param  identifier Identifier string for the new bundle.
1580  * @return A pointer to a new Ecore_Config_Bundle.  @c NULL is returned if the
1581  *         structure couldn't be allocated.
1582  */
1583 EAPI Ecore_Config_Bundle *
1584 ecore_config_bundle_new(Ecore_Config_Server * srv, const char *identifier)
1585 {
1586    Ecore_Config_Bundle *t;
1587    static long         ss;
1588
1589    ss = 0;                      /* bundle unique serial */
1590
1591    if ((t = malloc(sizeof(Ecore_Config_Bundle))))
1592      {
1593         memset(t, 0, sizeof(Ecore_Config_Bundle));
1594
1595         t->identifier = (char *)identifier;
1596         t->serial = ++ss;
1597         t->owner = srv->name;
1598         t->next = srv->bundles;
1599         srv->bundles = t;
1600      }
1601    return t;
1602 }
1603
1604 static Ecore_Config_Server *
1605 do_init(const char *name)
1606 {
1607    return _ecore_config_ipc_init(name);
1608 }
1609
1610 static Ecore_Config_Server *
1611 ecore_config_init_local(const char *name)
1612 {
1613    char               *p;
1614    char               *buf;
1615
1616    if ((p = getenv("HOME")))
1617      {                          /* debug-only ### FIXME */
1618         if (!(buf = malloc(PATH_MAX * sizeof(char))))
1619            return NULL;
1620         snprintf(buf, PATH_MAX, "%s/.ecore/%s/.global", p, name);
1621         unlink(buf);
1622
1623         free(buf);
1624      }
1625
1626    return do_init(name);
1627 }
1628
1629 static Ecore_Config_Server *
1630 ecore_config_init_global(const char *name)
1631 {
1632    char               *p;
1633    int global;
1634    char               *buf;
1635    global = 0;
1636
1637    if ((p = getenv("HOME")))
1638      {                          /* debug-only ### FIXME */
1639         if (!(buf = malloc(PATH_MAX * sizeof(char))))
1640            return NULL;
1641         snprintf(buf, PATH_MAX, "%s/.ecore/%s/.global", p, name);
1642         global = creat(buf, S_IRWXU);
1643
1644         if (global)
1645            close(global);
1646
1647         free(buf);
1648      }
1649
1650    return do_init(name);
1651 }
1652
1653 /**
1654  * @defgroup Ecore_Config_App_Lib_Group Ecore Config App Library Functions
1655  *
1656  * Functions that are used to start up and shutdown the Enlightened
1657  * Property Library when used directly by an application.
1658  */
1659
1660 /**
1661  * Initializes the Enlightened Property Library.
1662  *
1663  * Either this function or @ref ecore_config_system_init must be run
1664  * before any other function in the Enlightened Property Library, even
1665  * if you have run @ref ecore_init .  The name given is used to
1666  * determine the default configuration to load.
1667  *
1668  * @param  name Application name
1669  * @return @c ECORE_CONFIG_ERR_SUCC if the library is successfully set up.
1670  *         @c ECORE_CONFIG_ERR_FAIL otherwise.
1671  * @ingroup Ecore_Config_App_Lib_Group
1672  */
1673 EAPI int
1674 ecore_config_init(const char *name)
1675 {
1676    char                *path;
1677    Ecore_Config_Prop   *list;
1678    _ecore_config_system_init_no_load();
1679
1680    __ecore_config_app_name = strdup(name);
1681    __ecore_config_server_local = ecore_config_init_local(name);
1682    if (!__ecore_config_server_local)
1683       return ECORE_CONFIG_ERR_FAIL;
1684
1685    list = __ecore_config_bundle_local->data;
1686    free( __ecore_config_bundle_local );
1687    __ecore_config_bundle_local =
1688       ecore_config_bundle_new(__ecore_config_server_local, "config");
1689    __ecore_config_bundle_local->data = list;
1690
1691    path = ecore_config_theme_default_path_get();
1692    ecore_config_string_default("/e/themes/search_path", path);
1693    if (path)
1694       free(path);
1695
1696    list = ecore_config_get("/e/themes/search_path");
1697    if (list)
1698      {
1699         list->flags |= ECORE_CONFIG_FLAG_SYSTEM;
1700         list->flags &= ~ECORE_CONFIG_FLAG_MODIFIED;
1701      }
1702
1703    return _ecore_config_system_load();
1704 }
1705
1706 /**
1707  * Frees memory and shuts down the library for an application.
1708  * @return @c ECORE_CONFIG_ERR_IGNORED .
1709  * @ingroup Ecore_Config_App_Lib_Group
1710  */
1711 EAPI int
1712 ecore_config_shutdown(void)
1713 {
1714    return ecore_config_system_shutdown();
1715 }
1716
1717 /**
1718  * @defgroup Ecore_Config_Lib_Lib_Group Ecore Config Library Functions
1719  *
1720  * Functions that are used to start up and shutdown the Enlightened
1721  * Property Library when used directly by an application.
1722  */
1723
1724 /**
1725  * Initializes the Enlightened Property Library.
1726  *
1727  * This function is meant to be run from other programming libraries.
1728  * It should not be called from applications.
1729  *
1730  * This function (or @ref ecore_config_init )
1731  * must be run before any other function in the
1732  * Enlightened Property Library, even if you have run @ref ecore_init .
1733  *
1734  * @return @c ECORE_CONFIG_ERR_SUCC if the library is successfully set up.
1735  *         @c ECORE_CONFIG_ERR_FAIL otherwise.
1736  * @ingroup Ecore_Config_Lib_Lib_Group
1737  */
1738 EAPI int
1739 ecore_config_system_init(void)
1740 {
1741    _ecore_config_system_init_no_load();
1742    return _ecore_config_system_load();
1743 }
1744
1745 static            int
1746 _ecore_config_system_init_no_load(void)
1747 {
1748    char               *p;
1749
1750    __ecore_config_system_init++;
1751    if (__ecore_config_system_init > 1)
1752       return ECORE_CONFIG_ERR_IGNORED;
1753
1754    DEBUG = -1;
1755    if ((p = getenv("ECORE_CONFIG_DEBUG")) && p[0] != 0)
1756      {
1757         DEBUG = atoi(p);
1758      }
1759
1760    __ecore_config_server_global =
1761       ecore_config_init_global(ECORE_CONFIG_GLOBAL_ID);
1762    if (!__ecore_config_server_global)
1763         return ECORE_CONFIG_ERR_FAIL;
1764
1765    __ecore_config_bundle_local =
1766       ecore_config_bundle_new(__ecore_config_server_global, "system");
1767
1768    /* set up a simple default path */
1769    ecore_config_string_default("/e/themes/search_path", PACKAGE_DATA_DIR "../ewl/themes");
1770    
1771    return ECORE_CONFIG_ERR_SUCC;
1772 }
1773
1774
1775 static             int
1776 _ecore_config_system_load(void)
1777 {
1778    char               *buf, *p;
1779    Ecore_Config_Prop  *sys;
1780
1781    if (__ecore_config_system_init != 1)
1782         return ECORE_CONFIG_ERR_FAIL;
1783
1784    if ((p = getenv("HOME")))
1785      {                          /* debug-only ### FIXME */
1786         if ((buf = malloc(PATH_MAX * sizeof(char))))
1787           {
1788              snprintf(buf, PATH_MAX, "%s/.e/config.eet", p);
1789              if (ecore_config_file_load(buf) != 0) {
1790                 /* even if this file (system.eet) dosen't exist we can 
1791                  * continue without it as it isn't striclty necessary.
1792                 */
1793                 ecore_config_file_load(PACKAGE_DATA_DIR "/system.eet");
1794              }
1795              sys = __ecore_config_bundle_local->data;
1796              while (sys)
1797                {
1798                   /* unmark it modified - modification will mean it has been overridden */
1799                   sys->flags &= ~ECORE_CONFIG_FLAG_MODIFIED;
1800                   /* mark as system so that examine can hide them */
1801                   sys->flags |= ECORE_CONFIG_FLAG_SYSTEM;
1802                   sys = sys->next;
1803                }
1804           }
1805         free(buf);
1806      }
1807
1808    return ECORE_CONFIG_ERR_SUCC;
1809 }
1810
1811
1812 /**
1813  * Frees memory and shuts down the library for other programming libraries.
1814  * @return @c ECORE_CONFIG_ERR_IGNORED
1815  * @ingroup Ecore_Config_Lib_Lib_Group
1816  */
1817 EAPI int
1818 ecore_config_system_shutdown(void)
1819 {
1820    int                 ret;
1821
1822    __ecore_config_system_init--;
1823    if (__ecore_config_system_init > 0)
1824       return ECORE_CONFIG_ERR_IGNORED;
1825
1826    ret = _ecore_config_ipc_exit();
1827    if (__ecore_config_app_name)
1828       free(__ecore_config_app_name);
1829    while(__ecore_config_bundle_local->data)
1830      ecore_config_dst(__ecore_config_bundle_local->data);
1831    free(__ecore_config_bundle_local);
1832    free(__ecore_config_server_local);
1833    free(__ecore_config_server_global);
1834    return ret;
1835 }
1836
1837 static inline void *
1838 __ecore_argb_to_long(int a, int r, int g, int b, long *v)
1839 {
1840    *v = ((a << 24) & 0xff000000 )
1841       | ((r << 16) &   0xff0000 )
1842       | ((g <<  8) &     0xff00 )
1843       | ( b        &       0xff );
1844
1845    return v;
1846 }
1847
1848 static inline void *
1849 __ecore_argbstr_to_long(const char *argb, long *v)
1850 {
1851    char *l = NULL;
1852
1853    // convert hexadecimal string #..., #0x..., 0x..., ... to long
1854    if(*argb == '#')
1855      argb++;
1856    *v = (long)strtoul( argb, &l, 16);
1857
1858    if(*l)
1859      {
1860         E(0, "ecore_config_val: value \"%s\" not a valid hexadecimal RGB value?\n", argb);
1861         return NULL;
1862      }
1863
1864    return v;
1865 }
1866