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