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