svn update: 48958 (latest:48959)
[framework/uifw/ecore.git] / src / lib / ecore_config / ecore_config_extra.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 <stdio.h>
11 #include <stdlib.h>
12
13 #include <sys/types.h>
14 #include <sys/stat.h>
15
16 #include "Ecore_Config.h"
17 #include "Ecore.h"
18 #include "ecore_config_private.h"
19 typedef struct __Ecore_Config_Arg_Callback _Ecore_Config_Arg_Callback;
20 struct __Ecore_Config_Arg_Callback
21 {
22    char           short_opt;
23    char          *long_opt;
24    char          *description;
25    void          *data;
26    void         (*func)(char *val, void *data);
27    Ecore_Config_Type type;
28    _Ecore_Config_Arg_Callback *next;
29 };
30
31 char               *__ecore_config_app_description;
32 _Ecore_Config_Arg_Callback *_ecore_config_arg_callbacks;
33
34 /* shorthand prop setup code to make client apps a little smaller ;) */
35
36 /**
37  * Creates a new property, if it does not already exist, and sets its
38  * attributes to those given.
39  *
40  * The type of the property is guessed from the key and the value
41  * given.
42  *
43  * @param   key       The property key.
44  * @param   val       Pointer to default value of key.
45  * @param   short_opt Short option used to set the property from command
46  *                    line.
47  * @param   long_opt  Long option used to set the property from command line.
48  * @param   desc      String description of property.
49  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
50  * @ingroup Ecore_Config_Create_Group
51  */
52 int
53 ecore_config_create(const char *key, void *val, char short_opt, char *long_opt,
54                     char *desc)
55 {
56    int                 type = ecore_config_type_guess(key, val);
57
58    return ecore_config_typed_create(key, val, type, short_opt, long_opt, desc);
59 }
60
61 /**
62  * Creates a new property, if it does not already exist, and sets its
63  * attributes to those given.
64  * @param   key       The property key.
65  * @param   val       Pointer to default value of key.
66  * @param   type      Type of the property.
67  * @param   short_opt Short option used to set the property from
68  *                    command line.
69  * @param   long_opt  Long option used to set the property from command line.
70  * @param   desc      String description of property.
71  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
72  * @ingroup Ecore_Config_Create_Group
73  */
74 int
75 ecore_config_typed_create(const char *key, void *val, int type, char short_opt,
76                           char *long_opt, char *desc)
77 {
78    int                 ret;
79
80    if ((ret =
81         ecore_config_typed_default(key, val, type)) != ECORE_CONFIG_ERR_SUCC)
82       return ret;
83    if ((ret =
84         ecore_config_short_opt_set(key, short_opt)) != ECORE_CONFIG_ERR_SUCC)
85       return ret;
86    if ((ret =
87         ecore_config_long_opt_set(key, long_opt)) != ECORE_CONFIG_ERR_SUCC)
88       return ret;
89    ret = ecore_config_describe(key, desc);
90    return ret;
91 }
92
93 /**
94  * Creates a new boolean property, if it does not already exist, and sets its
95  * attributes to those given.
96  * @param   key       The property key.
97  * @param   val       Default boolean value of key.
98  * @param   short_opt Short option used to set the property from command
99  *                    line.
100  * @param   long_opt  Long option used to set the property from command line.
101  * @param   desc      String description of property.
102  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
103  * @ingroup Ecore_Config_Create_Group
104  */
105 int
106 ecore_config_boolean_create(const char *key, int val, char short_opt,
107                         char *long_opt, char *desc)
108 {
109    return
110       ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_BLN, short_opt, long_opt,
111                                 desc);
112 }
113
114 /**
115  * Creates a new integer property, if it does not already exist, and sets its
116  * attributes to those given.
117  * @param   key       The property key.
118  * @param   val       Default integer value of key.
119  * @param   short_opt Short option used to set the property from command
120  *                    line.
121  * @param   long_opt  Long option used to set the property from command line.
122  * @param   desc      String description of property.
123  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
124  * @ingroup Ecore_Config_Create_Group
125  */
126 int
127 ecore_config_int_create(const char *key, int val, char short_opt,
128                         char *long_opt, char *desc)
129 {
130    return
131       ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_INT, short_opt, long_opt,
132                                 desc);
133 }
134
135 /**
136  * Creates a new integer property, if it does not already exist, and sets its
137  * attributes to those given.
138  * @param   key       The property key.
139  * @param   val       Default integer value of key.
140  * @param   low       Lowest valid integer value for the property.
141  * @param   high      Highest valid integer value for the property.
142  * @param   step      Increment value for the property.
143  * @param   short_opt Short option used to set the property from command
144  *                    line.
145  * @param   long_opt  Long option used to set the property from command line.
146  * @param   desc      String description of property.
147  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
148  * @ingroup Ecore_Config_Create_Group
149  */
150 int
151 ecore_config_int_create_bound(const char *key, int val, int low, int high,
152                               int step, char short_opt, char *long_opt,
153                               char *desc)
154 {
155    Ecore_Config_Prop  *e;
156    int                 ret;
157
158    ret =
159       ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_INT, short_opt, long_opt,
160                                 desc);
161    if (ret != ECORE_CONFIG_ERR_SUCC)
162       return ret;
163    e = ecore_config_get(key);
164    if (e)
165      {
166         e->step = step;
167         e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
168         e->lo = low;
169         e->hi = high;
170         ecore_config_bound(e);
171      }
172    return ret;
173 }
174
175 /**
176  * Creates a new string property, if it does not already exist, and sets its
177  * attributes to those given.
178  * @param   key       The property key.
179  * @param   val       Default value of key.
180  * @param   short_opt Short option used to set the property from command
181  *                    line.
182  * @param   long_opt  Long option used to set the property from command line.
183  * @param   desc      String description of property.
184  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
185  * @ingroup Ecore_Config_Create_Group
186  */
187 int
188 ecore_config_string_create(const char *key, char *val, char short_opt,
189                            char *long_opt, char *desc)
190 {
191    return
192       ecore_config_typed_create(key, (void *)val, ECORE_CONFIG_STR, short_opt, long_opt,
193                                 desc);
194 }
195
196 /**
197  * Creates a new float property, if it does not already exist, and sets its
198  * attributes to those given.
199  * @param   key       The property key.
200  * @param   val       Default float value of key.
201  * @param   short_opt Short option used to set the property from command
202  *                    line.
203  * @param   long_opt  Long option used to set the property from command line.
204  * @param   desc      String description of property.
205  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
206  * @ingroup Ecore_Config_Create_Group
207  */
208 int
209 ecore_config_float_create(const char *key, float val, char short_opt,
210                           char *long_opt, char *desc)
211 {
212    return
213       ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_FLT, short_opt, long_opt,
214                                 desc);
215 }
216
217 /**
218  * Creates a new float property, if it does not already exist, and sets its
219  * attributes to those given.
220  * @param   key       The property key.
221  * @param   val       Default float value of key.
222  * @param   low       Lowest valid float value for the property.
223  * @param   high      Highest valid float value for the property.
224  * @param   step      Increment value for the property.
225  * @param   short_opt Short option used to set the property from command
226  *                    line.
227  * @param   long_opt  Long option used to set the property from command line.
228  * @param   desc      String description of property.
229  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
230  * @ingroup Ecore_Config_Create_Group
231  */
232 int
233 ecore_config_float_create_bound(const char *key, float val, float low,
234                                 float high, float step, char short_opt,
235                                 char *long_opt, char *desc)
236 {
237    Ecore_Config_Prop  *e;
238    int                 ret;
239
240    ret =
241       ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_FLT, short_opt, long_opt,
242                                 desc);
243    e = ecore_config_get(key);
244    if (e)
245      {
246         e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION);
247         e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
248         e->lo = (int)(low * ECORE_CONFIG_FLOAT_PRECISION);
249         e->hi = (int)(high * ECORE_CONFIG_FLOAT_PRECISION);
250         ecore_config_bound(e);
251      }
252    return ret;
253 }
254
255 /**
256  * Creates a new color property, if it does not already exist, and sets its
257  * attributes to those given.
258  * @param   key       The property key.
259  * @param   val       Default color value of key, as a hexadecimal string.
260  * @param   short_opt Short option used to set the property from command
261  *                    line.
262  * @param   long_opt  Long option used to set the property from command line.
263  * @param   desc      String description of property.
264  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
265  * @ingroup Ecore_Config_Create_Group
266  */
267 int
268 ecore_config_argb_create(const char *key, char *val, char short_opt,
269                         char *long_opt, char *desc)
270 {
271    return
272       ecore_config_typed_create(key, (void *)val, ECORE_CONFIG_RGB, short_opt, long_opt,
273                                 desc);
274 }
275
276 /**
277  * Creates a new theme property, if it does not already exist, and sets its
278  * attributes to those given.
279  * @param   key       The property key.
280  * @param   val       Default theme name for the property.
281  * @param   short_opt Short option used to set the property from command
282  *                    line.
283  * @param   long_opt  Long option used to set the property from command line.
284  * @param   desc      String description of property.
285  * @return  @c ECORE_CONFIG_ERR_SUCC on success.
286  * @ingroup Ecore_Config_Create_Group
287  */
288 int
289 ecore_config_theme_create(const char *key, char *val, char short_opt,
290                           char *long_opt, char *desc)
291 {
292    return
293       ecore_config_typed_create(key, (void *)val, ECORE_CONFIG_THM, short_opt, long_opt,
294                                 desc);
295 }
296
297 /* this should only be built if evas is present */
298
299 /**
300  * Calls evas_font_path_append on @p evas for each of the font names stored
301  * in the property "/e/font/path".
302  * @param  evas Evas object to append the font names to.
303  * @return @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_NODATA
304  *         is returned if the property has not been set.
305  */
306 int
307 ecore_config_evas_font_path_apply(Evas * evas)
308 {
309    char               *font_path, *font_path_tmp, *ptr, *end;
310
311    font_path = ecore_config_string_get("/e/font/path");
312
313    if (!font_path)
314       return ECORE_CONFIG_ERR_NODATA;
315    ptr = font_path;
316    end = font_path + strlen(font_path);
317    font_path_tmp = font_path;
318    while (ptr && ptr < end)
319      {
320         while (*ptr != '|' && ptr < end)
321            ptr++;
322         if (ptr < end)
323            *ptr = '\0';
324
325         evas_font_path_append(evas, font_path_tmp);
326         ptr++;
327         font_path_tmp = ptr;
328      }
329
330    free(font_path);
331
332    return ECORE_CONFIG_ERR_SUCC;
333 }
334
335 /**
336  * Retrieves the default theme search path.
337  *
338  * @return The default theme search path.
339  */
340 char               *
341 ecore_config_theme_default_path_get(void)
342 {
343    char               *path, *home;
344    int                 len;
345
346    home = getenv("HOME");
347    len = strlen(PACKAGE_DATA_DIR "/../") + strlen(__ecore_config_app_name) +
348             strlen("/themes/") + 1;
349    if (home)
350       len += strlen(home) + strlen("/.e/apps/") +
351                 strlen(__ecore_config_app_name) +
352                 strlen("/themes/|"); /* no \0, as that is above */
353
354    if (!(path = malloc(len)))
355       return NULL;
356
357    *path = '\0';
358    if (home)
359      {
360         strcat(path, home);
361         strcat(path, "/.e/apps/");
362         strcat(path, __ecore_config_app_name);
363         strcat(path, "/themes/|");
364      }
365    strcat(path, PACKAGE_DATA_DIR "/../");
366    strcat(path, __ecore_config_app_name);
367    strcat(path, "/themes/");
368
369    return path;
370 }
371
372 /**
373  * Retrieves the search path used to find themes.
374  *
375  * The search path is stored in the property "/e/themes/search_path".  If
376  * the property has not been set, the default path used is
377  * "/usr/local/share/<app_name>/themes|~/.e/apps/<app_name>/themes".
378  * See @ref ecore_config_theme_default_path_get for more information about
379  * the default path.
380  *
381  * @return The search path.  @c NULL is returned if there is no memory left.
382  */
383 char               *
384 ecore_config_theme_search_path_get(void)
385 {
386    char               *search_path;
387    search_path = ecore_config_string_get("/e/themes/search_path");
388
389    /* this should no longer be the case, as it is defaulted in init */
390    if (!search_path)
391      {
392         search_path = ecore_config_theme_default_path_get();
393         if (search_path)
394           {
395              ecore_config_string_default("/e/themes/search_path", search_path);
396              free(search_path);
397           }
398      }
399    return search_path;
400 }
401
402 /**
403  * Adds the given path to the search path used to find themes.
404  *
405  * If the search path is successfully, the new search path will be saved
406  * into the property "/e/themes/search_path".  Therefore, this function
407  * should be called @b after @ref ecore_config_load to allow a user to
408  * override the default search path.
409  *
410  * @param  path The given 
411  * @return @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_FAIL
412  *         will be returned if @p path already exists in the search path.
413  *         @c ECORE_CONFIG_ERR_FAIL is returned if @p path is @c NULL.
414  */
415 int
416 ecore_config_theme_search_path_append(const char *path)
417 {
418    char               *search_path, *loc, *new_search_path;
419    int                 len, search_len;
420    Ecore_Config_Prop  *prop;
421
422    if (!path)
423      return ECORE_CONFIG_ERR_NODATA;
424    search_path = ecore_config_theme_search_path_get();
425
426    loc = strstr(search_path, path);
427    len = strlen(path);
428    search_len = strlen(search_path);
429    
430    if (loc == NULL || (loc != search_path && *(loc - 1) != '|') || 
431        (loc != (search_path + search_len - len) && *(loc + len - 1) != '|'))
432      {
433         new_search_path = malloc(search_len + len + 2); /* 2 = \0 + | */
434         strcpy(new_search_path, search_path);
435         strncat(new_search_path, "|", 1);
436         strncat(new_search_path, path, len);
437
438         ecore_config_string_set("/e/themes/search_path", new_search_path);
439         prop = ecore_config_get("/e/themes/search_path");
440         if (prop)
441           prop->flags &= ~ECORE_CONFIG_FLAG_MODIFIED;
442
443         free(new_search_path);
444
445         return ECORE_CONFIG_ERR_SUCC;
446      }
447    return ECORE_CONFIG_ERR_FAIL;
448 }
449
450 /**
451  * Retrieve a theme file's full path.
452  *
453  * The search path for theme files is given by @ref
454  * ecore_config_theme_search_path_get .
455  *
456  * @param  name The name of the theme.
457  * @return A full path to the theme on success.  @c NULL will be returned
458  *         if @p name is @c NULL or no theme matching the given name could
459  *         be found.
460  */
461 char               *
462 ecore_config_theme_with_path_from_name_get(char *name)
463 {
464    char               *search_path, *search_path_tmp, *ptr, *end, *file;
465    struct stat         st;
466
467    if (!name)
468       return NULL; /* no theme specified (nor a default) */
469
470    search_path = ecore_config_theme_search_path_get();
471    ptr = search_path;
472    end = search_path + strlen(search_path);
473    search_path_tmp = search_path;
474    while (ptr && ptr < end)
475      {
476         while (*ptr != '|' && ptr < end)
477            ptr++;
478         if (ptr < end)
479            *ptr = '\0';
480
481         file = malloc(strlen(search_path_tmp) + strlen(name) + 6);
482            /* 6 = / + .edj + \0 */
483
484         snprintf(file, strlen(search_path_tmp) + strlen(name) + 6, 
485                       "%s/%s.edj", search_path_tmp, name);
486         
487         if (stat(file, &st) == 0)
488           {
489               free(search_path);
490               return file;
491           }
492         free(file);
493         ptr++;
494         search_path_tmp = ptr;
495      }
496
497    free(search_path);
498
499    return NULL; /* we could not find the theme with that name in search path */
500 }
501
502 /**
503  * Retrieves the full path to the theme file of the theme stored in the
504  * given property.
505  *
506  * The search path for themes is given by @ref
507  * ecore_config_theme_search_path_get .
508  *
509  * @param  key The given property.
510  * @return A full path to the theme on success, or @c NULL on failure.
511  *         This function will fail if no key is specified or not theme
512  *         matching that given by the property @p key could be found.
513  */
514 char               *
515 ecore_config_theme_with_path_get(const char *key)
516 {
517    return
518       ecore_config_theme_with_path_from_name_get(ecore_config_theme_get(key));
519 }
520
521 static const char  *_ecore_config_short_types[] =
522    { "      ", "<int> ", "<flt> ", "<str> ", "<rgb> ", "<str> ", "<bool>" };
523
524 /**
525  * Prints the property list of the local configuration bundle to output.
526  */
527 void
528 ecore_config_args_display(void)
529 {
530    Ecore_Config_Prop  *props;
531    _Ecore_Config_Arg_Callback *callbacks;
532
533    if (__ecore_config_app_description)
534       ERR("%s\n\n", __ecore_config_app_description);
535    ERR("Supported Options:");
536    ERR(" -h, --help\t       Print this text");
537    if (!__ecore_config_bundle_local)
538       return;
539    props = __ecore_config_bundle_local->data;
540    while (props)
541      {
542         /* if it is a system prop, or cannot be set on command line hide it */
543         if (props->flags & ECORE_CONFIG_FLAG_SYSTEM || (!props->short_opt && !props->long_opt))
544           {
545              props = props->next;
546              continue;
547           }
548         INF(" %c%c%c --%s\t%s %s", props->short_opt ? '-' : ' ',
549                props->short_opt ? props->short_opt : ' ',
550                props->short_opt ? ',' : ' ',
551                props->long_opt ? props->long_opt : props->key,
552                _ecore_config_short_types[props->type],
553                props->description ? props->description :
554                "(no description available)");
555
556         props = props->next;
557      }
558    callbacks = _ecore_config_arg_callbacks;
559    while (callbacks)
560      {
561         INF(" %c%c%c --%s\t%s %s", callbacks->short_opt ? '-' : ' ',
562                callbacks->short_opt ? callbacks->short_opt : ' ',
563                callbacks->short_opt ? ',' : ' ',
564                callbacks->long_opt ? callbacks->long_opt : "",
565                _ecore_config_short_types[callbacks->type],
566                callbacks->description ? callbacks->description :
567                "(no description available)");
568
569         callbacks = callbacks->next;
570      }
571 }
572
573 static int
574 ecore_config_parse_set(Ecore_Config_Prop * prop, char *arg, char *opt,
575                        char opt2)
576 {
577    if (!arg)
578      {
579         if (opt)
580            ERR("Missing expected argument for option --%s", opt);
581         else
582            ERR("Missing expected argument for option -%c", opt2);
583         return ECORE_CONFIG_PARSE_EXIT;
584      }
585    else
586      {
587         ecore_config_set(prop->key, arg);
588         prop->flags |= ECORE_CONFIG_FLAG_CMDLN;
589      }   
590    return ECORE_CONFIG_PARSE_CONTINUE;
591 }
592
593 static void
594 ecore_config_args_callback_add(char short_opt, char *long_opt, char *desc,
595                                void (*func)(char *val, void *data),
596                                void *data, Ecore_Config_Type type) {
597    _Ecore_Config_Arg_Callback *new_cb;
598
599    new_cb = malloc(sizeof(_Ecore_Config_Arg_Callback));
600    new_cb->short_opt = short_opt;
601    if (long_opt)
602       new_cb->long_opt = strdup(long_opt);
603    if (desc)
604       new_cb->description = strdup(desc);
605    new_cb->data = data;
606    new_cb->func = func;
607    new_cb->type = type;
608
609    new_cb->next = _ecore_config_arg_callbacks;
610    _ecore_config_arg_callbacks = new_cb;
611 }
612
613 void
614 ecore_config_args_callback_str_add(char short_opt, char *long_opt, char *desc,
615                                    void (*func)(char *val, void *data),
616                                    void *data) {
617    ecore_config_args_callback_add(short_opt, long_opt, desc, func, data, ECORE_CONFIG_STR);
618 }
619
620 void
621 ecore_config_args_callback_noarg_add(char short_opt, char *long_opt, char *desc,
622                                      void (*func)(char *val, void *data),
623                                      void *data) {
624    ecore_config_args_callback_add(short_opt, long_opt, desc, func, data, ECORE_CONFIG_NIL);
625 }
626
627 /**
628  * Parse the arguments set by @ref ecore_app_args_set and set properties
629  * accordingly.
630  *
631  * @return @c ECORE_CONFIG_PARSE_CONTINUE if successful.
632  *         @c ECORE_CONFIG_PARSE_EXIT is returned if an unrecognised option
633  *         is found.  @c ECORE_CONFIG_PARSE_HELP is returned if help was
634  *         displayed.
635  */
636 int
637 ecore_config_args_parse(void)
638 {
639    int                 argc;
640    char              **argv;
641    int                 nextarg, next_short_opt, found, ret;
642    char               *arg;
643    char               *long_opt, short_opt;
644    Ecore_Config_Prop  *prop;
645    _Ecore_Config_Arg_Callback *callback;
646
647    ecore_app_args_get(&argc, &argv);
648    nextarg = 1;
649    while (nextarg < argc)
650      {
651         arg = argv[nextarg];
652
653         if (*arg != '-')
654           {
655              ERR("Unexpected attribute \"%s\"", arg);
656              nextarg++;
657              continue;
658           }
659
660         next_short_opt = 1;
661         short_opt = *(arg + next_short_opt);
662
663         if (short_opt == '-')
664           {
665              long_opt = arg + 2;
666
667              if (!strcmp(long_opt, "help"))
668                {
669                   ecore_config_args_display();
670                   return ECORE_CONFIG_PARSE_HELP;
671                }
672
673              found = 0;
674              prop = __ecore_config_bundle_local->data;
675              while (prop)
676                {
677                   if ((prop->long_opt && !strcmp(long_opt, prop->long_opt))
678                       || !strcmp(long_opt, prop->key))
679                     {
680                        found = 1;
681                        if ((ret =
682                             ecore_config_parse_set(prop, argv[++nextarg],
683                                                    long_opt,
684                                                    '\0')) !=
685                            ECORE_CONFIG_PARSE_CONTINUE)
686                           return ret;
687                        break;
688                     }
689                   prop = prop->next;
690                }
691              if (!found)
692                {
693                   callback = _ecore_config_arg_callbacks;
694                   while (callback)
695                     {
696                        if ((callback->long_opt && 
697                             !strcmp(long_opt, callback->long_opt)))
698                          {
699                             found = 1;
700                             if (callback->type == ECORE_CONFIG_NIL)
701                               {
702                                  callback->func(NULL, callback->data);
703                               }
704                             else 
705                               {
706                                  if (!argv[++nextarg])
707                                    {
708                                       ERR("Missing expected argument for option --%s", long_opt);
709                                       return ECORE_CONFIG_PARSE_EXIT;
710                                    }
711                                    callback->func(argv[nextarg], callback->data);
712                               }
713                             break;
714                          }
715                        callback = callback->next;
716                     }
717                }
718              if (!found)
719                {
720                   ERR("Unrecognised option \"%s\"", long_opt);
721                   ERR("Try using -h or --help for more information.\n");
722                   return ECORE_CONFIG_PARSE_EXIT;
723                }
724           }
725         else
726           {
727              while (short_opt)
728                {
729                   if (short_opt == 'h')
730                     {
731                        ecore_config_args_display();
732                        return ECORE_CONFIG_PARSE_HELP;
733                     }
734                   else
735                     {
736                        found = 0;
737                        prop = __ecore_config_bundle_local->data;
738                        while (prop)
739                          {
740                             if (short_opt == prop->short_opt)
741                               {
742                                  found = 1;
743                                  if ((ret =
744                                       ecore_config_parse_set(prop,
745                                                              argv[++nextarg],
746                                                              NULL,
747                                                              short_opt)) !=
748                                      ECORE_CONFIG_PARSE_CONTINUE)
749                                     return ret;
750                                  break;
751                               }
752                             prop = prop->next;
753                          }
754
755                        if (!found)
756                          {
757                             callback = _ecore_config_arg_callbacks;
758                             while (callback)
759                               {
760                                  if (short_opt == callback->short_opt)
761                                    {
762                                       found = 1;
763                                       if (callback->type == ECORE_CONFIG_NIL)
764                                         {
765                                            callback->func(NULL, callback->data);
766                                         }
767                                       else
768                                         {
769                                            if (!argv[++nextarg])
770                                              {
771                                                 ERR("Missing expected argument for option -%c", short_opt);
772                                                 return ECORE_CONFIG_PARSE_EXIT;
773                                              }
774                                            callback->func(argv[nextarg], callback->data);
775                                         }
776                                       break;
777                                    }
778                                  callback = callback->next;
779                               }
780                          }
781                        if (!found)
782                          {
783                             ERR("Unrecognised option '%c'", short_opt);
784                             ERR("Try using -h or --help for more information.\n");
785                             return ECORE_CONFIG_PARSE_EXIT;
786                          }
787                     }
788                   short_opt = *(arg + ++next_short_opt);
789                }
790           }
791         nextarg++;
792      }
793
794    return ECORE_CONFIG_PARSE_CONTINUE;
795 }
796
797 /**
798  * Sets the description string used by @ref ecore_config_args_display .
799  * @param description Description of application.
800  */
801 void
802 ecore_config_app_describe(char *description)
803 {
804    if (__ecore_config_app_description)
805       free(__ecore_config_app_description);
806    __ecore_config_app_description = strdup(description);
807 }