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