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