elm elm_widget.c: Fixed build break. Thanks for the report Rajeev.
[framework/uifw/elementary.git] / src / lib / elm_config.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #ifdef HAVE_EVIL
6 # include <Evil.h>
7 #endif
8
9 #include <Elementary.h>
10 #include "elm_priv.h"
11
12 EAPI int ELM_EVENT_CONFIG_ALL_CHANGED = 0;
13
14 Elm_Config *_elm_config = NULL;
15 char *_elm_profile = NULL;
16 static Eet_Data_Descriptor *_config_edd = NULL;
17 static Eet_Data_Descriptor *_config_font_overlay_edd = NULL;
18 static Eet_Data_Descriptor *_config_color_edd = NULL;
19 static Eet_Data_Descriptor *_config_color_palette_edd = NULL;
20 const char *_elm_preferred_engine = NULL;
21
22 static Ecore_Poller *_elm_cache_flush_poller = NULL;
23
24 const char *_elm_engines[] = {
25    "software_x11",
26    "fb",
27    "directfb",
28    "software_16_x11",
29    "software_8_x11",
30    "xrender_x11",
31    "opengl_x11",
32    "software_gdi",
33    "software_16_wince_gdi",
34    "sdl",
35    "software_16_sdl",
36    "opengl_sdl",
37    "buffer",
38    "ews",
39    "opengl_cocoa",
40    "psl1ght",
41    "wayland_shm",
42    "wayland_egl",
43    NULL
44 };
45
46 /* whenever you want to add a new text class support into Elementary,
47    declare it both here and in the (default) theme */
48 static const Elm_Text_Class _elm_text_classes[] = {
49    {"button", "Button Labels"},
50    {"label", "Text Labels"},
51    {"entry", "Text Entries"},
52    {"title_bar", "Title Bar"},
53    {"list_item", "List Items"},
54    {"grid_item", "Grid Items"},
55    {"toolbar_item", "Toolbar Items"},
56    {"menu_item", "Menu Items"},
57    {NULL, NULL}
58 };
59
60 static void        _desc_init(void);
61 static void        _desc_shutdown(void);
62 static void        _profile_fetch_from_conf(void);
63 static void        _config_free(void);
64 static void        _config_apply(void);
65 static Elm_Config *_config_user_load(void);
66 static Elm_Config *_config_system_load(void);
67 static void        _config_load(void);
68 static void        _config_update(void);
69 static void        _env_get(void);
70 static size_t      _elm_data_dir_snprintf(char       *dst,
71                                           size_t      size,
72                                           const char *fmt, ...)
73                                           EINA_PRINTF(3, 4);
74 static size_t _elm_user_dir_snprintf(char       *dst,
75                                      size_t      size,
76                                      const char *fmt, ...)
77                                      EINA_PRINTF(3, 4);
78
79 #define ELM_CONFIG_VAL(edd, type, member, dtype) \
80   EET_DATA_DESCRIPTOR_ADD_BASIC(edd, type, #member, member, dtype)
81 #define ELM_CONFIG_LIST(edd, type, member, eddtype) \
82   EET_DATA_DESCRIPTOR_ADD_LIST(edd, type, #member, member, eddtype)
83
84 #ifdef HAVE_ELEMENTARY_X
85 static Ecore_Event_Handler *_prop_change_handler = NULL;
86 static Ecore_Timer *_prop_all_update_timer = NULL;
87 static Ecore_Timer *_prop_change_delay_timer = NULL;
88 static Ecore_X_Window _root_1st = 0;
89 #define ATOM_COUNT 2
90 static Ecore_X_Atom _atom[ATOM_COUNT];
91 static Ecore_X_Atom _atom_config = 0;
92 static const char *_atom_names[ATOM_COUNT] =
93 {
94    "ELM_PROFILE",
95    "ELM_CONFIG"
96 };
97 #define ATOM_E_PROFILE                              0
98 #define ATOM_E_CONFIG                               1
99
100 static Eina_Bool _prop_all_update_cb(void *data __UNUSED__);
101 static Eina_Bool _prop_config_get(void);
102 static void      _prop_config_set(void);
103 static Eina_Bool _prop_change(void *data  __UNUSED__,
104                               int ev_type __UNUSED__,
105                               void       *ev);
106
107 static Eina_Bool
108 _prop_all_update_cb(void *data __UNUSED__)
109 {
110    _prop_config_set();
111    ecore_x_window_prop_string_set(_root_1st, _atom[ATOM_E_PROFILE],
112                                   _elm_profile);
113    _prop_all_update_timer = NULL;
114    return EINA_FALSE;
115 }
116
117 static Eina_Bool
118 _prop_config_get(void)
119 {
120    int size = 0;
121    Ecore_X_Atom atom;
122    char buf[512];
123    unsigned char *data = NULL;
124    Elm_Config *config_data;
125
126    snprintf(buf, sizeof(buf), "ELM_CONFIG_%s", _elm_profile);
127    atom = ecore_x_atom_get(buf);
128    _atom_config = atom;
129    if (!ecore_x_window_prop_property_get(_root_1st,
130                                          atom, _atom[ATOM_E_CONFIG],
131                                          8, &data, &size))
132      {
133         if (!ecore_x_window_prop_property_get(_root_1st,
134                                               _atom[ATOM_E_CONFIG],
135                                               _atom[ATOM_E_CONFIG],
136                                               8, &data, &size))
137           return EINA_FALSE;
138         else
139           _atom_config = _atom[ATOM_E_CONFIG];
140      }
141    else
142      _atom_config = atom;
143    if (size < 1)
144      {
145         free(data);
146         return EINA_FALSE;
147      }
148    config_data = eet_data_descriptor_decode(_config_edd, data, size);
149    free(data);
150    if (!config_data) return EINA_FALSE;
151
152    /* What do we do on version mismatch when someone changes the
153     * config in the rootwindow? */
154    /* Most obvious case, new version and we are still linked to
155     * whatever was there before, we just ignore until user restarts us */
156    if (config_data->config_version > ELM_CONFIG_VERSION)
157      return EINA_TRUE;
158    /* What in the case the version is older? Do we even support those
159     * cases or we only check for equality above? */
160
161    _config_free();
162    _elm_config = config_data;
163    _config_apply();
164    _elm_config_font_overlay_apply();
165    _elm_rescale();
166    _elm_recache();
167    ecore_event_add(ELM_EVENT_CONFIG_ALL_CHANGED, NULL, NULL, NULL);
168    return EINA_TRUE;
169 }
170
171 static void
172 _prop_config_set(void)
173 {
174    unsigned char *config_data = NULL;
175    int size = 0;
176
177    config_data = eet_data_descriptor_encode(_config_edd, _elm_config, &size);
178    if (config_data)
179      {
180         Ecore_X_Atom atom;
181         char buf[512];
182
183         snprintf(buf, sizeof(buf), "ELM_CONFIG_%s", _elm_profile);
184         atom = ecore_x_atom_get(buf);
185         _atom_config = atom;
186
187         ecore_x_window_prop_property_set(_root_1st, _atom_config,
188                                          _atom[ATOM_E_CONFIG], 8,
189                                          config_data, size);
190         free(config_data);
191      }
192 }
193
194 static Eina_Bool
195 _prop_change_delay_cb(void *data __UNUSED__)
196 {
197    char *s;
198
199    s = ecore_x_window_prop_string_get(_root_1st, _atom[ATOM_E_PROFILE]);
200    if (s)
201      {
202         if (_elm_profile) free(_elm_profile);
203         _elm_profile = s;
204      }
205    _prop_config_get();
206    _prop_change_delay_timer = NULL;
207    return EINA_FALSE;
208 }
209
210 static Eina_Bool
211 _prop_change(void *data  __UNUSED__,
212              int ev_type __UNUSED__,
213              void       *ev)
214 {
215    Ecore_X_Event_Window_Property *event = ev;
216
217    if (event->win == _root_1st)
218      {
219         if (event->atom == _atom[ATOM_E_PROFILE])
220           {
221              if (_prop_change_delay_timer) ecore_timer_del(_prop_change_delay_timer);
222              _prop_change_delay_timer = ecore_timer_add(0.1, _prop_change_delay_cb, NULL);
223           }
224         else if (((_atom_config > 0) && (event->atom == _atom_config)) ||
225                  (event->atom == _atom[ATOM_E_CONFIG]))
226           {
227              if (_prop_change_delay_timer) ecore_timer_del(_prop_change_delay_timer);
228              _prop_change_delay_timer = ecore_timer_add(0.1, _prop_change_delay_cb, NULL);
229           }
230      }
231    return ECORE_CALLBACK_PASS_ON;
232 }
233
234 #endif
235
236 static void
237 _desc_init(void)
238 {
239    Eet_Data_Descriptor_Class eddc;
240
241    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Config);
242    eddc.func.str_direct_alloc = NULL;
243    eddc.func.str_direct_free = NULL;
244
245    _config_edd = eet_data_descriptor_file_new(&eddc);
246    if (!_config_edd)
247      {
248         printf("EEEK! eet_data_descriptor_file_new() failed\n");
249         return;
250      }
251
252    memset(&eddc, 0, sizeof(eddc)); /* just in case... */
253    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Font_Overlay);
254    eddc.func.str_direct_alloc = NULL;
255    eddc.func.str_direct_free = NULL;
256
257    _config_font_overlay_edd = eet_data_descriptor_stream_new(&eddc);
258    if (!_config_font_overlay_edd)
259      {
260         printf("EEEK! eet_data_descriptor_stream_new() failed\n");
261         eet_data_descriptor_free(_config_edd);
262         return;
263      }
264
265    memset(&eddc, 0, sizeof(eddc)); /* just in case... */
266    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Color_RGBA);
267    eddc.func.str_direct_alloc = NULL;
268    eddc.func.str_direct_free = NULL;
269
270    _config_color_edd = eet_data_descriptor_stream_new(&eddc);
271    if (!_config_color_edd)
272      {
273         printf("EEEK! eet_data_descriptor_stream_new() failed\n");
274         eet_data_descriptor_free(_config_edd);
275         return;
276      }
277
278    memset(&eddc, 0, sizeof(eddc)); /* just in case... */
279    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Custom_Palette);
280    eddc.func.str_direct_alloc = NULL;
281    eddc.func.str_direct_free = NULL;
282
283    _config_color_palette_edd = eet_data_descriptor_stream_new(&eddc);
284    if (!_config_color_palette_edd)
285      {
286         printf("EEEK! eet_data_descriptor_stream_new() failed\n");
287         eet_data_descriptor_free(_config_edd);
288         return;
289      }
290
291 #define T_INT    EET_T_INT
292 #define T_DOUBLE EET_T_DOUBLE
293 #define T_STRING EET_T_STRING
294 #define T_UCHAR  EET_T_UCHAR
295
296 #define T        Elm_Font_Overlay
297 #define D        _config_font_overlay_edd
298    ELM_CONFIG_VAL(D, T, text_class, EET_T_STRING);
299    ELM_CONFIG_VAL(D, T, font, EET_T_STRING);
300    ELM_CONFIG_VAL(D, T, size, EET_T_INT);
301 #undef T
302 #undef D
303
304 #define T Elm_Color_RGBA
305 #define D _config_color_edd
306    ELM_CONFIG_VAL(D, T, r, EET_T_UINT);
307    ELM_CONFIG_VAL(D, T, g, EET_T_UINT);
308    ELM_CONFIG_VAL(D, T, b, EET_T_UINT);
309    ELM_CONFIG_VAL(D, T, a, EET_T_UINT);
310 #undef T
311 #undef D
312
313 #define T Elm_Custom_Palette
314 #define D _config_color_palette_edd
315    ELM_CONFIG_VAL(D, T, palette_name, EET_T_STRING);
316    ELM_CONFIG_LIST(D, T, color_list, _config_color_edd);
317 #undef T
318 #undef D
319
320 #define T Elm_Config
321 #define D _config_edd
322    ELM_CONFIG_VAL(D, T, config_version, T_INT);
323    ELM_CONFIG_VAL(D, T, engine, T_STRING);
324    ELM_CONFIG_VAL(D, T, vsync, T_UCHAR);
325    ELM_CONFIG_VAL(D, T, thumbscroll_enable, T_UCHAR);
326    ELM_CONFIG_VAL(D, T, thumbscroll_threshold, T_INT);
327    ELM_CONFIG_VAL(D, T, thumbscroll_momentum_threshold, T_DOUBLE);
328    ELM_CONFIG_VAL(D, T, thumbscroll_friction, T_DOUBLE);
329    ELM_CONFIG_VAL(D, T, thumbscroll_bounce_friction, T_DOUBLE);
330    ELM_CONFIG_VAL(D, T, thumbscroll_border_friction, T_DOUBLE);
331    ELM_CONFIG_VAL(D, T, thumbscroll_sensitivity_friction, T_DOUBLE);
332    ELM_CONFIG_VAL(D, T, page_scroll_friction, T_DOUBLE);
333    ELM_CONFIG_VAL(D, T, bring_in_scroll_friction, T_DOUBLE);
334    ELM_CONFIG_VAL(D, T, zoom_friction, T_DOUBLE);
335    ELM_CONFIG_VAL(D, T, thumbscroll_bounce_enable, T_UCHAR);
336    ELM_CONFIG_VAL(D, T, scroll_smooth_amount, T_DOUBLE);
337    ELM_CONFIG_VAL(D, T, scroll_smooth_history_weight, T_DOUBLE);
338    ELM_CONFIG_VAL(D, T, scroll_smooth_future_time, T_DOUBLE);
339    ELM_CONFIG_VAL(D, T, scroll_smooth_time_window, T_DOUBLE);
340    ELM_CONFIG_VAL(D, T, scale, T_DOUBLE);
341    ELM_CONFIG_VAL(D, T, bgpixmap, T_INT);
342    ELM_CONFIG_VAL(D, T, compositing, T_INT);
343    /* EET_DATA_DESCRIPTOR_ADD_LIST(D, T, "font_dirs", font_dirs, sub_edd); */
344    ELM_CONFIG_LIST(D, T, font_overlays, _config_font_overlay_edd);
345    ELM_CONFIG_VAL(D, T, font_hinting, T_INT);
346    ELM_CONFIG_VAL(D, T, cache_flush_poll_interval, T_INT);
347    ELM_CONFIG_VAL(D, T, cache_flush_enable, T_UCHAR);
348    ELM_CONFIG_VAL(D, T, image_cache, T_INT);
349    ELM_CONFIG_VAL(D, T, font_cache, T_INT);
350    ELM_CONFIG_VAL(D, T, edje_cache, T_INT);
351    ELM_CONFIG_VAL(D, T, edje_collection_cache, T_INT);
352    ELM_CONFIG_VAL(D, T, finger_size, T_INT);
353    ELM_CONFIG_VAL(D, T, fps, T_DOUBLE);
354    ELM_CONFIG_VAL(D, T, theme, T_STRING);
355    ELM_CONFIG_VAL(D, T, modules, T_STRING);
356    ELM_CONFIG_VAL(D, T, tooltip_delay, T_DOUBLE);
357    ELM_CONFIG_VAL(D, T, cursor_engine_only, T_UCHAR);
358    ELM_CONFIG_VAL(D, T, focus_highlight_enable, T_UCHAR);
359    ELM_CONFIG_VAL(D, T, focus_highlight_animate, T_UCHAR);
360    ELM_CONFIG_VAL(D, T, toolbar_shrink_mode, T_INT);
361    ELM_CONFIG_VAL(D, T, fileselector_expand_enable, T_UCHAR);
362    ELM_CONFIG_VAL(D, T, inwin_dialogs_enable, T_UCHAR);
363    ELM_CONFIG_VAL(D, T, icon_size, T_INT);
364    ELM_CONFIG_VAL(D, T, longpress_timeout, T_DOUBLE);
365    ELM_CONFIG_VAL(D, T, effect_enable, T_UCHAR);
366    ELM_CONFIG_VAL(D, T, desktop_entry, T_UCHAR);
367    ELM_CONFIG_VAL(D, T, password_show_last, T_UCHAR);
368    ELM_CONFIG_VAL(D, T, password_show_last_timeout, T_DOUBLE);
369    ELM_CONFIG_VAL(D, T, glayer_zoom_finger_enable, T_UCHAR);
370    ELM_CONFIG_VAL(D, T, glayer_zoom_finger_factor, T_DOUBLE);
371    ELM_CONFIG_VAL(D, T, glayer_zoom_wheel_factor, T_DOUBLE);
372    ELM_CONFIG_VAL(D, T, glayer_zoom_distance_tolerance, T_DOUBLE);
373    ELM_CONFIG_VAL(D, T, glayer_rotate_finger_enable, T_UCHAR);
374    ELM_CONFIG_VAL(D, T, glayer_rotate_angular_tolerance, T_DOUBLE);
375    ELM_CONFIG_VAL(D, T, glayer_line_min_length, T_DOUBLE);
376    ELM_CONFIG_VAL(D, T, glayer_line_distance_tolerance, T_DOUBLE);
377    ELM_CONFIG_VAL(D, T, glayer_line_angular_tolerance, T_DOUBLE);
378    ELM_CONFIG_VAL(D, T, glayer_flick_time_limit_ms, T_INT);
379    ELM_CONFIG_VAL(D, T, glayer_long_tap_start_timeout, T_DOUBLE);
380    ELM_CONFIG_VAL(D, T, access_mode, T_INT);
381    ELM_CONFIG_VAL(D, T, glayer_continues_enable, T_UCHAR);
382    ELM_CONFIG_VAL(D, T, week_start, T_INT);
383    ELM_CONFIG_VAL(D, T, weekend_start, T_INT);
384    ELM_CONFIG_VAL(D, T, weekend_len, T_INT);
385    ELM_CONFIG_VAL(D, T, year_min, T_INT);
386    ELM_CONFIG_VAL(D, T, year_max, T_INT);
387    ELM_CONFIG_LIST(D, T, color_palette, _config_color_palette_edd);
388 #undef T
389 #undef D
390 #undef T_INT
391 #undef T_DOUBLE
392 #undef T_STRING
393 #undef T_UCHAR
394 }
395
396 static void
397 _desc_shutdown(void)
398 {
399    if (_config_edd)
400      {
401         eet_data_descriptor_free(_config_edd);
402         _config_edd = NULL;
403      }
404
405    if (_config_font_overlay_edd)
406      {
407         eet_data_descriptor_free(_config_font_overlay_edd);
408         _config_font_overlay_edd = NULL;
409      }
410
411    if (_config_color_edd)
412      {
413         eet_data_descriptor_free(_config_color_edd);
414         _config_color_edd = NULL;
415      }
416
417    if (_config_color_palette_edd)
418      {
419         eet_data_descriptor_free(_config_color_palette_edd);
420         _config_color_palette_edd = NULL;
421      }
422 }
423
424 static int
425 _sort_files_cb(const void *f1,
426                const void *f2)
427 {
428    return strcmp(f1, f2);
429 }
430
431 const char *
432 _elm_config_current_profile_get(void)
433 {
434    return _elm_profile;
435 }
436
437 static size_t
438 _elm_data_dir_snprintf(char       *dst,
439                        size_t      size,
440                        const char *fmt,
441                        ...)
442 {
443    size_t data_dir_len, off;
444    va_list ap;
445
446    data_dir_len = eina_strlcpy(dst, _elm_data_dir, size);
447
448    off = data_dir_len + 1;
449    if (off >= size)
450      goto end;
451
452    va_start(ap, fmt);
453    dst[data_dir_len] = '/';
454
455    off = off + vsnprintf(dst + off, size - off, fmt, ap);
456    va_end(ap);
457
458 end:
459    return off;
460 }
461
462 static size_t
463 _elm_user_dir_snprintf(char       *dst,
464                        size_t      size,
465                        const char *fmt,
466                        ...)
467 {
468    const char *home;
469    size_t user_dir_len, off;
470    va_list ap;
471
472 #ifdef _WIN32
473    home = evil_homedir_get();
474 #else
475    home = getenv("HOME");
476 #endif
477    if (!home)
478      home = "/";
479
480    user_dir_len = eina_str_join_len(dst, size, '/', home, strlen(home),
481                                     ELEMENTARY_BASE_DIR, sizeof(ELEMENTARY_BASE_DIR) - 1);
482
483    off = user_dir_len + 1;
484    if (off >= size)
485      goto end;
486
487    va_start(ap, fmt);
488    dst[user_dir_len] = '/';
489
490    off = off + vsnprintf(dst + off, size - off, fmt, ap);
491    va_end(ap);
492
493 end:
494    return off;
495 }
496
497 const char *
498 _elm_config_profile_dir_get(const char *prof,
499                             Eina_Bool   is_user)
500 {
501    char buf[PATH_MAX];
502
503    if (!is_user)
504      goto not_user;
505
506    _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s", prof);
507
508    if (ecore_file_is_dir(buf))
509      return strdup(buf);
510
511    return NULL;
512
513 not_user:
514    snprintf(buf, sizeof(buf), "%s/config/%s", _elm_data_dir, prof);
515
516    if (ecore_file_is_dir(buf))
517      return strdup(buf);
518
519    return NULL;
520 }
521
522 Eina_List *
523 _elm_config_font_overlays_list(void)
524 {
525    return _elm_config->font_overlays;
526 }
527
528 void
529 _elm_config_font_overlay_set(const char    *text_class,
530                              const char    *font,
531                              Evas_Font_Size size)
532 {
533    Elm_Font_Overlay *efd;
534    Eina_List *l;
535
536    EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
537      {
538         if (strcmp(efd->text_class, text_class))
539           continue;
540
541         if (efd->font) eina_stringshare_del(efd->font);
542         efd->font = eina_stringshare_add(font);
543         efd->size = size;
544         _elm_config->font_overlays =
545           eina_list_promote_list(_elm_config->font_overlays, l);
546         return;
547      }
548
549    /* the text class doesn't exist */
550    efd = calloc(1, sizeof(Elm_Font_Overlay));
551    efd->text_class = eina_stringshare_add(text_class);
552    efd->font = eina_stringshare_add(font);
553    efd->size = size;
554
555    _elm_config->font_overlays = eina_list_prepend(_elm_config->font_overlays,
556                                                   efd);
557 }
558
559 void
560 _elm_config_font_overlay_remove(const char *text_class)
561 {
562    Elm_Font_Overlay *efd;
563    Eina_List *l;
564
565    EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
566      {
567         if (strcmp(efd->text_class, text_class))
568           continue;
569
570         _elm_config->font_overlays =
571           eina_list_remove_list(_elm_config->font_overlays, l);
572         if (efd->text_class) eina_stringshare_del(efd->text_class);
573         if (efd->font) eina_stringshare_del(efd->font);
574         free(efd);
575
576         return;
577      }
578 }
579
580 void
581 _elm_config_font_overlay_apply(void)
582 {
583    Elm_Font_Overlay *efd;
584    Eina_List *l;
585    int i;
586
587    for (i = 0; _elm_text_classes[i].desc; i++)
588      edje_text_class_del(_elm_text_classes[i].name);
589
590    EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
591      edje_text_class_set(efd->text_class, efd->font, efd->size);
592 }
593
594 Eina_List *
595 _elm_config_text_classes_get(void)
596 {
597    Eina_List *ret = NULL;
598    int i;
599
600    for (i = 0; _elm_text_classes[i].desc; i++)
601      {
602         Elm_Text_Class *tc;
603         tc = malloc(sizeof(*tc));
604         if (!tc) continue;
605
606         *tc = _elm_text_classes[i];
607
608         ret = eina_list_append(ret, tc);
609      }
610
611    return ret;
612 }
613
614 void
615 _elm_config_text_classes_free(Eina_List *l)
616 {
617    Elm_Text_Class *tc;
618
619    EINA_LIST_FREE(l, tc)
620      free(tc);
621 }
622
623 Eina_List *
624 _elm_config_color_list_get(const char *palette_name)
625 {
626     Eina_List *plist;
627     Elm_Custom_Palette *cpalette;
628     EINA_LIST_FOREACH(_elm_config->color_palette, plist, cpalette)
629       {
630          if (strcmp(cpalette->palette_name, palette_name))
631            continue;
632          return cpalette->color_list;
633       }
634     return NULL;
635 }
636
637 void
638 _elm_config_color_set(const char *palette_name,
639                       int r,
640                       int g,
641                       int b,
642                       int a)
643 {
644    Eina_List *plist;
645    Elm_Custom_Palette *cpalette;
646    Elm_Color_RGBA *color;
647    EINA_LIST_FOREACH(_elm_config->color_palette, plist, cpalette)
648      {
649         if (strcmp(cpalette->palette_name, palette_name))
650           continue;
651
652         color = calloc(1, sizeof(Elm_Color_RGBA));
653         color->r = r;
654         color->g = g;
655         color->b = b;
656         color->a = a;
657         cpalette->color_list = eina_list_prepend(cpalette->color_list,
658                                                        color);
659      }
660 }
661
662 void
663 _elm_config_colors_free(const char *palette_name)
664 {
665    Eina_List *plist;
666    Elm_Custom_Palette *cpalette;
667    Elm_Color_RGBA *color;
668    EINA_LIST_FOREACH(_elm_config->color_palette, plist, cpalette)
669      {
670         if (strcmp(cpalette->palette_name, palette_name))
671           continue;
672
673         EINA_LIST_FREE(cpalette->color_list, color)
674           {
675              free(color);
676           }
677      }
678 }
679
680 Eina_List *
681 _elm_config_profiles_list(void)
682 {
683    Eina_File_Direct_Info *info;
684    Eina_List *flist = NULL;
685    Eina_Iterator *file_it;
686    char buf[PATH_MAX];
687    const char *dir;
688    size_t len;
689
690    len = _elm_user_dir_snprintf(buf, sizeof(buf), "config");
691
692    file_it = eina_file_stat_ls(buf);
693    if (!file_it)
694      goto sys;
695
696    buf[len] = '/';
697    len++;
698
699    len = sizeof(buf) - len;
700
701    EINA_ITERATOR_FOREACH(file_it, info)
702      {
703         if (info->name_length >= len)
704           continue;
705
706         if (info->type == EINA_FILE_DIR)
707           {
708              flist =
709                eina_list_sorted_insert(flist, _sort_files_cb,
710                                        eina_stringshare_add(info->path +
711                                                             info->name_start));
712           }
713      }
714
715    eina_iterator_free(file_it);
716
717 sys:
718    len = eina_str_join_len(buf, sizeof(buf), '/', _elm_data_dir,
719                            strlen(_elm_data_dir), "config",
720                            sizeof("config") - 1);
721
722    file_it = eina_file_direct_ls(buf);
723    if (!file_it)
724      goto list_free;
725
726    buf[len] = '/';
727    len++;
728
729    len = sizeof(buf) - len;
730    EINA_ITERATOR_FOREACH(file_it, info)
731      {
732         if (info->name_length >= len)
733           continue;
734
735         switch (info->type)
736           {
737            case EINA_FILE_DIR:
738            {
739               const Eina_List *l;
740               const char *tmp;
741
742               EINA_LIST_FOREACH(flist, l, tmp)
743                 if (!strcmp(info->path + info->name_start, tmp))
744                   break;
745
746               if (!l)
747                 flist =
748                   eina_list_sorted_insert(flist, _sort_files_cb,
749                                           eina_stringshare_add(info->path +
750                                                                info->name_start));
751            }
752            break;
753
754            default:
755              continue;
756           }
757      }
758    eina_iterator_free(file_it);
759    return flist;
760
761 list_free:
762    EINA_LIST_FREE(flist, dir)
763      eina_stringshare_del(dir);
764
765    return NULL;
766 }
767
768 static void
769 _profile_fetch_from_conf(void)
770 {
771    char buf[PATH_MAX], *p, *s;
772    Eet_File *ef = NULL;
773    int len = 0;
774
775    _elm_profile = strdup("default");
776
777    // if env var - use profile without question
778    s = getenv("ELM_PROFILE");
779    if (s)
780      {
781         free(_elm_profile);
782         _elm_profile = strdup(s);
783         return;
784      }
785
786    // user profile
787    _elm_user_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
788    ef = eet_open(buf, EET_FILE_MODE_READ);
789    if (ef)
790      {
791         p = eet_read(ef, "config", &len);
792         if (p)
793           {
794              free(_elm_profile);
795              _elm_profile = malloc(len + 1);
796              memcpy(_elm_profile, p, len);
797              _elm_profile[len] = 0;
798              free(p);
799           }
800         eet_close(ef);
801         if (!p) ef = NULL;
802      }
803    if (ef) return;
804
805    // system profile
806    _elm_data_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
807    ef = eet_open(buf, EET_FILE_MODE_READ);
808    if (ef)
809      {
810         p = eet_read(ef, "config", &len);
811         if (p)
812           {
813              free(_elm_profile);
814              _elm_profile = malloc(len + 1);
815              memcpy(_elm_profile, p, len);
816              _elm_profile[len] = 0;
817              free(p);
818           }
819         eet_close(ef);
820      }
821 }
822
823 static void
824 _config_free(void)
825 {
826    Elm_Font_Overlay *fo;
827    const char *fontdir;
828    Elm_Custom_Palette *palette;
829    Elm_Color_RGBA *color;
830
831    if (!_elm_config) return;
832    EINA_LIST_FREE(_elm_config->font_dirs, fontdir)
833      {
834         eina_stringshare_del(fontdir);
835      }
836    if (_elm_config->engine) eina_stringshare_del(_elm_config->engine);
837    EINA_LIST_FREE(_elm_config->font_overlays, fo)
838      {
839         if (fo->text_class) eina_stringshare_del(fo->text_class);
840         if (fo->font) eina_stringshare_del(fo->font);
841         free(fo);
842      }
843    EINA_LIST_FREE(_elm_config->color_palette, palette)
844      {
845         if (palette->palette_name) eina_stringshare_del(palette->palette_name);
846         EINA_LIST_FREE(palette->color_list, color) free(color);
847         free(palette);
848      }
849    if (_elm_config->theme) eina_stringshare_del(_elm_config->theme);
850    if (_elm_config->modules) eina_stringshare_del(_elm_config->modules);
851    free(_elm_config);
852    _elm_config = NULL;
853 }
854
855 static void
856 _config_apply(void)
857 {
858    _elm_theme_parse(NULL, _elm_config->theme);
859    ecore_animator_frametime_set(1.0 / _elm_config->fps);
860 }
861
862 static void
863 _config_sub_apply(void)
864 {
865    edje_frametime_set(1.0 / _elm_config->fps);
866    edje_scale_set(_elm_config->scale);
867    edje_password_show_last_set(_elm_config->password_show_last);
868    edje_password_show_last_timeout_set(_elm_config->password_show_last_timeout);
869    if (_elm_config->modules) _elm_module_parse(_elm_config->modules);
870 }
871
872 static Eina_Bool
873 _elm_cache_flush_cb(void *data __UNUSED__)
874 {
875    elm_cache_all_flush();
876    return ECORE_CALLBACK_RENEW;
877 }
878
879 /* kind of abusing this call right now -- shared between all of those
880  * properties -- but they are not meant to be called that periodically
881  * anyway */
882 void
883 _elm_recache(void)
884 {
885    Eina_List *l;
886    Evas_Object *win;
887
888    elm_cache_all_flush();
889
890    EINA_LIST_FOREACH(_elm_win_list, l, win)
891      {
892         Evas *e = evas_object_evas_get(win);
893         evas_image_cache_set(e, _elm_config->image_cache * 1024);
894         evas_font_cache_set(e, _elm_config->font_cache * 1024);
895      }
896    edje_file_cache_set(_elm_config->edje_cache);
897    edje_collection_cache_set(_elm_config->edje_collection_cache);
898
899    if (_elm_cache_flush_poller)
900      {
901         ecore_poller_del(_elm_cache_flush_poller);
902         _elm_cache_flush_poller = NULL;
903      }
904    if (_elm_config->cache_flush_enable)
905      {
906         if (_elm_config->cache_flush_poll_interval > 0)
907           {
908              _elm_cache_flush_poller =
909                 ecore_poller_add(ECORE_POLLER_CORE,
910                                  _elm_config->cache_flush_poll_interval,
911                                  _elm_cache_flush_cb, NULL);
912           }
913      }
914 }
915
916 static Elm_Config *
917 _config_user_load(void)
918 {
919    Elm_Config *cfg = NULL;
920    Eet_File *ef;
921    char buf[PATH_MAX];
922
923    _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s/base.cfg",
924                           _elm_profile);
925
926    ef = eet_open(buf, EET_FILE_MODE_READ);
927    if (ef)
928      {
929         cfg = eet_data_read(ef, _config_edd, "config");
930         eet_close(ef);
931      }
932    return cfg;
933 }
934
935 static Elm_Config *
936 _config_system_load(void)
937 {
938    Elm_Config *cfg = NULL;
939    Eet_File *ef;
940    char buf[PATH_MAX];
941
942    _elm_data_dir_snprintf(buf, sizeof(buf), "config/%s/base.cfg",
943                           _elm_profile);
944
945    ef = eet_open(buf, EET_FILE_MODE_READ);
946    if (ef)
947      {
948         cfg = eet_data_read(ef, _config_edd, "config");
949         eet_close(ef);
950      }
951    return cfg;
952 }
953
954 static void
955 _config_load(void)
956 {
957    _elm_config = _config_user_load();
958    if (_elm_config)
959      {
960         if (_elm_config->config_version < ELM_CONFIG_VERSION)
961           _config_update();
962         return;
963      }
964
965    /* no user config, fallback for system. No need to check version for
966     * this one, if it's not the right one, someone screwed up at the time
967     * of installing it */
968    _elm_config = _config_system_load();
969    if (_elm_config) return;
970    /* FIXME: config load could have failed because of a non-existent
971     * profile. Fallback to default before moving on */
972
973    // config load fail - defaults
974    // why are these here? well if they are, it means you can make a gui
975    // config recovery app i guess...
976    _elm_config = ELM_NEW(Elm_Config);
977    _elm_config->config_version = ELM_CONFIG_VERSION;
978    _elm_config->engine = eina_stringshare_add("software_x11");
979    _elm_config->vsync = 0;
980    _elm_config->thumbscroll_enable = EINA_TRUE;
981    _elm_config->thumbscroll_threshold = 24;
982    _elm_config->thumbscroll_momentum_threshold = 100.0;
983    _elm_config->thumbscroll_friction = 1.0;
984    _elm_config->thumbscroll_bounce_friction = 0.5;
985    _elm_config->thumbscroll_bounce_enable = EINA_TRUE;
986    _elm_config->page_scroll_friction = 0.5;
987    _elm_config->bring_in_scroll_friction = 0.5;
988    _elm_config->zoom_friction = 0.5;
989    _elm_config->thumbscroll_border_friction = 0.5;
990    _elm_config->thumbscroll_sensitivity_friction = 0.25; // magic number! just trial and error shows this makes it behave "nicer" and not run off at high speed all the time
991    _elm_config->scroll_smooth_amount = 1.0;
992    _elm_config->scroll_smooth_history_weight = 0.3;
993    _elm_config->scroll_smooth_future_time = 0.0;
994    _elm_config->scroll_smooth_time_window = 0.2;
995    _elm_config->scale = 1.0;
996    _elm_config->bgpixmap = 0;
997    _elm_config->compositing = 1;
998    _elm_config->font_hinting = 2;
999    _elm_config->cache_flush_poll_interval = 512;
1000    _elm_config->cache_flush_enable = EINA_TRUE;
1001    _elm_config->font_dirs = NULL;
1002    _elm_config->image_cache = 4096;
1003    _elm_config->font_cache = 512;
1004    _elm_config->edje_cache = 32;
1005    _elm_config->edje_collection_cache = 64;
1006    _elm_config->finger_size = 40;
1007    _elm_config->fps = 60.0;
1008    _elm_config->theme = eina_stringshare_add("default");
1009    _elm_config->modules = NULL;
1010    _elm_config->tooltip_delay = 1.0;
1011    _elm_config->cursor_engine_only = EINA_TRUE;
1012    _elm_config->focus_highlight_enable = EINA_FALSE;
1013    _elm_config->focus_highlight_animate = EINA_TRUE;
1014    _elm_config->toolbar_shrink_mode = 2;
1015    _elm_config->fileselector_expand_enable = EINA_FALSE;
1016    _elm_config->inwin_dialogs_enable = EINA_FALSE;
1017    _elm_config->icon_size = 32;
1018    _elm_config->longpress_timeout = 1.0;
1019    _elm_config->effect_enable = EINA_TRUE;
1020    _elm_config->desktop_entry = EINA_FALSE;
1021    _elm_config->is_mirrored = EINA_FALSE; /* Read sys value in env_get() */
1022    _elm_config->password_show_last = EINA_FALSE;
1023    _elm_config->password_show_last_timeout = 2.0;
1024    _elm_config->glayer_zoom_finger_enable = EINA_TRUE;
1025    _elm_config->glayer_zoom_finger_factor = 1.0;
1026    _elm_config->glayer_zoom_wheel_factor = 0.05;
1027    _elm_config->glayer_zoom_distance_tolerance = 1.0; /* 1 times elm_finger_size_get() */
1028    _elm_config->glayer_rotate_finger_enable = EINA_TRUE;
1029    _elm_config->glayer_rotate_angular_tolerance = 2.0; /* 2 DEG */
1030    _elm_config->glayer_line_min_length = 1.0;         /* 1 times elm_finger_size_get() */
1031    _elm_config->glayer_line_distance_tolerance = 3.0; /* 3 times elm_finger_size_get() */
1032    _elm_config->glayer_line_angular_tolerance = 20.0; /* 20 DEG */
1033    _elm_config->glayer_flick_time_limit_ms = 120;              /* ms to finish flick */
1034    _elm_config->glayer_long_tap_start_timeout = 1.2;   /* 1.2 second to start long-tap */
1035    _elm_config->glayer_continues_enable = EINA_TRUE;      /* Continue gestures default */
1036    _elm_config->week_start = 1; /* monday */
1037    _elm_config->weekend_start = 6; /* saturday */
1038    _elm_config->weekend_len = 2;
1039    _elm_config->year_min = 2;
1040    _elm_config->year_max = 137;
1041    _elm_config->color_palette = NULL;
1042 }
1043
1044 static const char *
1045 _elm_config_eet_close_error_get(Eet_File *ef,
1046                                 char     *file)
1047 {
1048    Eet_Error err;
1049    const char *erstr = NULL;
1050
1051    err = eet_close(ef);
1052    switch (err)
1053      {
1054       case EET_ERROR_WRITE_ERROR:
1055         erstr = "An error occurred while saving Elementary's "
1056                 "settings to disk. The error could not be "
1057                 "deterimined. The file where the error occurred was: "
1058                 "%s. This file has been deleted to avoid corrupt data.";
1059         break;
1060
1061       case EET_ERROR_WRITE_ERROR_FILE_TOO_BIG:
1062         erstr = "Elementary's settings files are too big "
1063                 "for the file system they are being saved to. "
1064                 "This error is very strange as the files should "
1065                 "be extremely small. Please check the settings "
1066                 "for your home directory. "
1067                 "The file where the error occurred was: %s ."
1068                 "This file has been deleted to avoid corrupt data.";
1069         break;
1070
1071       case EET_ERROR_WRITE_ERROR_IO_ERROR:
1072         erstr = "An output error occurred when writing the settings "
1073                 "files for Elementary. Your disk is having troubles "
1074                 "and possibly needs replacement. "
1075                 "The file where the error occurred was: %s ."
1076                 "This file has been deleted to avoid corrupt data.";
1077         break;
1078
1079       case EET_ERROR_WRITE_ERROR_OUT_OF_SPACE:
1080         erstr = "Elementary cannot write its settings file "
1081                 "because it ran out of space to write the file. "
1082                 "You have either run out of disk space or have "
1083                 "gone over your quota limit. "
1084                 "The file where the error occurred was: %s ."
1085                 "This file has been deleted to avoid corrupt data.";
1086         break;
1087
1088       case EET_ERROR_WRITE_ERROR_FILE_CLOSED:
1089         erstr = "Elementary unexpectedly had the settings file "
1090                 "it was writing closed on it. This is very unusual. "
1091                 "The file where the error occurred was: %s "
1092                 "This file has been deleted to avoid corrupt data.";
1093         break;
1094
1095       default:
1096         break;
1097      }
1098    if (erstr)
1099      {
1100         /* delete any partially-written file */
1101          ecore_file_unlink(file);
1102          return strdup(erstr);
1103      }
1104
1105    return NULL;
1106 }
1107
1108 static Eina_Bool
1109 _elm_config_profile_save(void)
1110 {
1111    char buf[4096], buf2[4096];
1112    int ok = 0, ret;
1113    const char *err;
1114    Eet_File *ef;
1115    size_t len;
1116
1117    len = _elm_user_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
1118    if (len + 1 >= sizeof(buf))
1119      return EINA_FALSE;
1120
1121    len = _elm_user_dir_snprintf(buf2, sizeof(buf2), "config/profile.cfg.tmp");
1122    if (len + 1 >= sizeof(buf2))
1123      return EINA_FALSE;
1124
1125    ef = eet_open(buf2, EET_FILE_MODE_WRITE);
1126    if (!ef)
1127      return EINA_FALSE;
1128
1129    ok = eet_write(ef, "config", _elm_profile, strlen(_elm_profile), 0);
1130    if (!ok)
1131      goto err;
1132
1133    err = _elm_config_eet_close_error_get(ef, buf2);
1134    if (err)
1135      {
1136         ERR("%s", err);
1137         free((void *)err);
1138         goto err;
1139      }
1140
1141    ret = ecore_file_mv(buf2, buf);
1142    if (!ret)
1143      {
1144         ERR("Error saving Elementary's configuration file");
1145         goto err;
1146      }
1147
1148    ecore_file_unlink(buf2);
1149    return EINA_TRUE;
1150
1151 err:
1152    ecore_file_unlink(buf2);
1153    return EINA_FALSE;
1154 }
1155
1156 Eina_Bool
1157 _elm_config_save(void)
1158 {
1159    char buf[4096], buf2[4096];
1160    int ok = 0, ret;
1161    const char *err;
1162    Eet_File *ef;
1163    size_t len;
1164
1165    len = _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s", _elm_profile);
1166    if (len + 1 >= sizeof(buf))
1167      return EINA_FALSE;
1168
1169    ok = ecore_file_mkpath(buf);
1170    if (!ok)
1171      {
1172         ERR("Problem accessing Elementary's user configuration directory: %s",
1173             buf);
1174         return EINA_FALSE;
1175      }
1176
1177    if (!_elm_config_profile_save())
1178      return EINA_FALSE;
1179
1180    buf[len] = '/';
1181    len++;
1182
1183    if (len + sizeof("base.cfg") >= sizeof(buf) - len)
1184      return EINA_FALSE;
1185
1186    memcpy(buf + len, "base.cfg", sizeof("base.cfg"));
1187    len += sizeof("base.cfg") - 1;
1188
1189    if (len + sizeof(".tmp") >= sizeof(buf))
1190      return EINA_FALSE;
1191
1192    memcpy(buf2, buf, len);
1193    memcpy(buf2 + len, ".tmp", sizeof(".tmp"));
1194
1195    ef = eet_open(buf2, EET_FILE_MODE_WRITE);
1196    if (!ef)
1197      return EINA_FALSE;
1198
1199    ok = eet_data_write(ef, _config_edd, "config", _elm_config, 1);
1200    if (!ok)
1201      goto err;
1202
1203    err = _elm_config_eet_close_error_get(ef, buf2);
1204    if (err)
1205      {
1206         ERR("%s", err);
1207         free((void *)err);
1208         goto err;
1209      }
1210
1211    ret = ecore_file_mv(buf2, buf);
1212    if (!ret)
1213      {
1214         ERR("Error saving Elementary's configuration file");
1215         goto err;
1216      }
1217
1218    ecore_file_unlink(buf2);
1219    return EINA_TRUE;
1220
1221 err:
1222    ecore_file_unlink(buf2);
1223    return EINA_FALSE;
1224 }
1225
1226 static void
1227 _config_update(void)
1228 {
1229    Elm_Config *tcfg;
1230
1231    tcfg = _config_system_load();
1232    if (!tcfg)
1233      {
1234         /* weird profile or something? We should probably fill
1235          * with hardcoded defaults, or get from default previx */
1236           return;
1237      }
1238 #define IFCFG(v)   if ((_elm_config->config_version & 0xffff) < (v)) {
1239 #define IFCFGELSE } else {
1240 #define IFCFGEND  }
1241 #define COPYVAL(x) do {_elm_config->x = tcfg->x; } while (0)
1242 #define COPYPTR(x) do {_elm_config->x = tcfg->x; tcfg->x = NULL; } while (0)
1243 #define COPYSTR(x) COPYPTR(x)
1244
1245      /* we also need to update for property changes in the root window
1246       * if needed, but that will be dependent on new properties added
1247       * with each version */
1248
1249      IFCFG(0x0003);
1250      COPYVAL(longpress_timeout);
1251      IFCFGEND;
1252
1253 #undef COPYSTR
1254 #undef COPYPTR
1255 #undef COPYVAL
1256 #undef IFCFGEND
1257 #undef IFCFGELSE
1258 #undef IFCFG
1259
1260      /* after updating user config, we must save */
1261 }
1262
1263 static void
1264 _env_get(void)
1265 {
1266    char *s;
1267    double friction;
1268
1269    s = getenv("ELM_ENGINE");
1270    if (s)
1271      {
1272         if ((!strcasecmp(s, "x11")) ||
1273             (!strcasecmp(s, "x")) ||
1274             (!strcasecmp(s, "software-x11")) ||
1275             (!strcasecmp(s, "software_x11")))
1276           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_X11);
1277         else if ((!strcasecmp(s, "opengl")) ||
1278                  (!strcasecmp(s, "gl")) ||
1279                  (!strcasecmp(s, "opengl-x11")) ||
1280                  (!strcasecmp(s, "opengl_x11")))
1281           eina_stringshare_replace(&_elm_config->engine, ELM_OPENGL_X11);
1282         else if ((!strcasecmp(s, "x11-8")) ||
1283                  (!strcasecmp(s, "x8")) ||
1284                  (!strcasecmp(s, "software-8-x11")) ||
1285                  (!strcasecmp(s, "software_8_x11")))
1286           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_8_X11);
1287         else if ((!strcasecmp(s, "x11-16")) ||
1288                  (!strcasecmp(s, "x16")) ||
1289                  (!strcasecmp(s, "software-16-x11")) ||
1290                  (!strcasecmp(s, "software_16_x11")))
1291           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_X11);
1292 /*
1293         else if ((!strcasecmp(s, "xrender")) ||
1294                  (!strcasecmp(s, "xr")) ||
1295                  (!strcasecmp(s, "xrender-x11")) ||
1296                  (!strcasecmp(s, "xrender_x11")))
1297           eina_stringshare_replace(&_elm_config->engine, ELM_XRENDER_X11);
1298  */
1299         else if ((!strcasecmp(s, "fb")) ||
1300                  (!strcasecmp(s, "software-fb")) ||
1301                  (!strcasecmp(s, "software_fb")))
1302           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_FB);
1303         else if ((!strcasecmp(s, "directfb")) ||
1304                  (!strcasecmp(s, "dfb")))
1305           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_DIRECTFB);
1306         else if ((!strcasecmp(s, "psl1ght")))
1307           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_PSL1GHT);
1308         else if ((!strcasecmp(s, "sdl")) ||
1309                  (!strcasecmp(s, "software-sdl")) ||
1310                  (!strcasecmp(s, "software_sdl")))
1311           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_SDL);
1312         else if ((!strcasecmp(s, "sdl-16")) ||
1313                  (!strcasecmp(s, "software-16-sdl")) ||
1314                  (!strcasecmp(s, "software_16_sdl")))
1315           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_SDL);
1316         else if ((!strcasecmp(s, "opengl-sdl")) ||
1317                  (!strcasecmp(s, "opengl_sdl")) ||
1318                  (!strcasecmp(s, "gl-sdl")) ||
1319                  (!strcasecmp(s, "gl_sdl")))
1320           eina_stringshare_replace(&_elm_config->engine, ELM_OPENGL_SDL);
1321         else if ((!strcasecmp(s, "opengl-cocoa")) ||
1322                  (!strcasecmp(s, "opengl_cocoa")) ||
1323                  (!strcasecmp(s, "gl-cocoa")) ||
1324                  (!strcasecmp(s, "gl_cocoa")))
1325           eina_stringshare_replace(&_elm_config->engine, ELM_OPENGL_COCOA);
1326         else if ((!strcasecmp(s, "gdi")) ||
1327                  (!strcasecmp(s, "software-gdi")) ||
1328                  (!strcasecmp(s, "software_gdi")))
1329           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_WIN32);
1330         else if ((!strcasecmp(s, "wince-gdi")) ||
1331                  (!strcasecmp(s, "software-16-wince-gdi")) ||
1332                  (!strcasecmp(s, "software_16_wince_gdi")))
1333           eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_WINCE);
1334         else if (!strcasecmp(s, "buffer"))
1335           eina_stringshare_replace(&_elm_config->engine, ELM_BUFFER);
1336         else if ((!strncmp(s, "shot:", 5)))
1337           eina_stringshare_replace(&_elm_config->engine, s);
1338         else if ((!strcasecmp(s, "ews")))
1339           eina_stringshare_replace(&_elm_config->engine, ELM_EWS);
1340         else if ((!strcasecmp(s, "wayland_shm")))
1341           eina_stringshare_replace(&_elm_config->engine, ELM_WAYLAND_SHM);
1342         else if ((!strcasecmp(s, "wayland_egl")))
1343           eina_stringshare_replace(&_elm_config->engine, ELM_WAYLAND_EGL);
1344         else
1345           ERR("Unknown engine '%s'.", s);
1346      }
1347
1348    s = getenv("ELM_VSYNC");
1349    if (s) _elm_config->vsync = !!atoi(s);
1350
1351    s = getenv("ELM_THUMBSCROLL_ENABLE");
1352    if (s) _elm_config->thumbscroll_enable = !!atoi(s);
1353    s = getenv("ELM_THUMBSCROLL_THRESHOLD");
1354    if (s) _elm_config->thumbscroll_threshold = atoi(s);
1355    // FIXME: floatformat locale issues here 1.0 vs 1,0 - should just be 1.0
1356    s = getenv("ELM_THUMBSCROLL_MOMENTUM_THRESHOLD");
1357    if (s) _elm_config->thumbscroll_momentum_threshold = atof(s);
1358    s = getenv("ELM_THUMBSCROLL_FRICTION");
1359    if (s) _elm_config->thumbscroll_friction = atof(s);
1360    s = getenv("ELM_THUMBSCROLL_BOUNCE_ENABLE");
1361    if (s) _elm_config->thumbscroll_bounce_enable = !!atoi(s);
1362    s = getenv("ELM_THUMBSCROLL_BOUNCE_FRICTION");
1363    if (s) _elm_config->thumbscroll_bounce_friction = atof(s);
1364    s = getenv("ELM_PAGE_SCROLL_FRICTION");
1365    if (s) _elm_config->page_scroll_friction = atof(s);
1366    s = getenv("ELM_BRING_IN_SCROLL_FRICTION");
1367    if (s) _elm_config->bring_in_scroll_friction = atof(s);
1368    s = getenv("ELM_ZOOM_FRICTION");
1369    if (s) _elm_config->zoom_friction = atof(s);
1370    s = getenv("ELM_THUMBSCROLL_BORDER_FRICTION");
1371    if (s)
1372      {
1373         friction = atof(s);
1374         if (friction < 0.0)
1375           friction = 0.0;
1376
1377         if (friction > 1.0)
1378           friction = 1.0;
1379
1380         _elm_config->thumbscroll_border_friction = friction;
1381      }
1382    s = getenv("ELM_THUMBSCROLL_SENSITIVITY_FRICTION");
1383    if (s)
1384      {
1385         friction = atof(s);
1386         if (friction < 0.1)
1387           friction = 0.1;
1388
1389         if (friction > 1.0)
1390           friction = 1.0;
1391
1392         _elm_config->thumbscroll_sensitivity_friction = friction;
1393      }
1394    s = getenv("ELM_SCROLL_SMOOTH_AMOUNT");
1395    if (s) _elm_config->scroll_smooth_amount = atof(s);
1396    s = getenv("ELM_SCROLL_SMOOTH_HISTORY_WEIGHT");
1397    if (s) _elm_config->scroll_smooth_history_weight = atof(s);
1398    s = getenv("ELM_SCROLL_SMOOTH_FUTURE_TIME");
1399    if (s) _elm_config->scroll_smooth_future_time = atof(s);
1400    s = getenv("ELM_SCROLL_SMOOTH_TIME_WINDOW");
1401    if (s) _elm_config->scroll_smooth_time_window = atof(s);
1402    s = getenv("ELM_THEME");
1403    if (s) eina_stringshare_replace(&_elm_config->theme, s);
1404
1405    s = getenv("ELM_FONT_HINTING");
1406    if (s)
1407      {
1408         if      (!strcasecmp(s, "none")) _elm_config->font_hinting = 0;
1409         else if (!strcasecmp(s, "auto"))
1410           _elm_config->font_hinting = 1;
1411         else if (!strcasecmp(s, "bytecode"))
1412           _elm_config->font_hinting = 2;
1413      }
1414
1415    s = getenv("ELM_FONT_PATH");
1416    if (s)
1417      {
1418         const char *p, *pp;
1419         char *buf2;
1420
1421         EINA_LIST_FREE(_elm_config->font_dirs, p)
1422           {
1423              eina_stringshare_del(p);
1424           }
1425
1426         buf2 = alloca(strlen(s) + 1);
1427         p = s;
1428         pp = p;
1429         for (;; )
1430           {
1431              if ((*p == ':') || (*p == 0))
1432                {
1433                   int len;
1434
1435                   len = p - pp;
1436                   strncpy(buf2, pp, len);
1437                   buf2[len] = 0;
1438                   _elm_config->font_dirs =
1439                     eina_list_append(_elm_config->font_dirs,
1440                                      eina_stringshare_add(buf2));
1441                   if (*p == 0) break;
1442                   p++;
1443                   pp = p;
1444                }
1445              else
1446                {
1447                   if (*p == 0) break;
1448                   p++;
1449                }
1450           }
1451      }
1452
1453    s = getenv("ELM_IMAGE_CACHE");
1454    if (s) _elm_config->image_cache = atoi(s);
1455
1456    s = getenv("ELM_FONT_CACHE");
1457    if (s) _elm_config->font_cache = atoi(s);
1458
1459    s = getenv("ELM_SCALE");
1460    if (s) _elm_config->scale = atof(s);
1461
1462    s = getenv("ELM_FINGER_SIZE");
1463    if (s) _elm_config->finger_size = atoi(s);
1464
1465    s = getenv("ELM_PASSWORD_SHOW_LAST");
1466    if (s) _elm_config->password_show_last = !!atoi(s);
1467
1468    s = getenv("ELM_PASSWORD_SHOW_LAST_TIMEOUT");
1469    if (s)
1470      {
1471         double pw_show_last_timeout = atof(s);
1472         if (pw_show_last_timeout >= 0.0)
1473           _elm_config->password_show_last_timeout = pw_show_last_timeout;
1474      }
1475
1476    s = getenv("ELM_FPS");
1477    if (s) _elm_config->fps = atof(s);
1478    if (_elm_config->fps < 1.0) _elm_config->fps = 1.0;
1479
1480    s = getenv("ELM_MODULES");
1481    if (s) eina_stringshare_replace(&_elm_config->modules, s);
1482
1483    /* Get RTL orientation from system */
1484    setlocale(LC_ALL, "");
1485    bindtextdomain(PACKAGE, LOCALE_DIR);
1486    _elm_config->is_mirrored = !strcmp(E_("default:LTR"), "default:RTL");
1487
1488    s = getenv("ELM_TOOLTIP_DELAY");
1489    if (s)
1490      {
1491         double delay = atof(s);
1492         if (delay >= 0.0)
1493           _elm_config->tooltip_delay = delay;
1494      }
1495
1496    s = getenv("ELM_CURSOR_ENGINE_ONLY");
1497    if (s) _elm_config->cursor_engine_only = !!atoi(s);
1498
1499    s = getenv("ELM_FOCUS_HIGHLIGHT_ENABLE");
1500    if (s) _elm_config->focus_highlight_enable = !!atoi(s);
1501
1502    s = getenv("ELM_FOCUS_HIGHLIGHT_ANIMATE");
1503    if (s) _elm_config->focus_highlight_animate = !!atoi(s);
1504
1505    s = getenv("ELM_TOOLBAR_SHRINK_MODE");
1506    if (s) _elm_config->toolbar_shrink_mode = atoi(s);
1507
1508    s = getenv("ELM_FILESELECTOR_EXPAND_ENABLE");
1509    if (s) _elm_config->fileselector_expand_enable = !!atoi(s);
1510
1511    s = getenv("ELM_INWIN_DIALOGS_ENABLE");
1512    if (s) _elm_config->inwin_dialogs_enable = !!atoi(s);
1513
1514    s = getenv("ELM_ICON_SIZE");
1515    if (s) _elm_config->icon_size = atoi(s);
1516
1517    s = getenv("ELM_LONGPRESS_TIMEOUT");
1518    if (s) _elm_config->longpress_timeout = atof(s);
1519    if (_elm_config->longpress_timeout < 0.0)
1520      _elm_config->longpress_timeout = 0.0;
1521
1522    s = getenv("ELM_EFFECT_ENABLE");
1523    if (s) _elm_config->effect_enable = !!atoi(s);
1524
1525    s = getenv("ELM_DESKTOP_ENTRY");
1526    if (s) _elm_config->desktop_entry = !!atoi(s);
1527    s = getenv("ELM_ACCESS_MODE");
1528    if (s) _elm_config->access_mode = ELM_ACCESS_MODE_ON;
1529 }
1530
1531 EAPI Eina_Bool
1532 elm_config_mirrored_get(void)
1533 {
1534    return _elm_config->is_mirrored;
1535 }
1536
1537 EAPI void
1538 elm_config_mirrored_set(Eina_Bool mirrored)
1539 {
1540    _elm_config->is_mirrored = mirrored;
1541    _elm_rescale();
1542 }
1543
1544 EAPI Eina_Bool
1545 elm_config_cursor_engine_only_get(void)
1546 {
1547    return _elm_config->cursor_engine_only;
1548 }
1549
1550 EAPI void
1551 elm_config_cursor_engine_only_set(Eina_Bool engine_only)
1552 {
1553    engine_only = !!engine_only;
1554    _elm_config->cursor_engine_only = engine_only;
1555 }
1556
1557 EAPI double
1558 elm_config_tooltip_delay_get(void)
1559 {
1560    return _elm_config->tooltip_delay;
1561 }
1562
1563 EAPI void
1564 elm_config_tooltip_delay_set(double delay)
1565 {
1566    if (delay < 0.0) return;
1567    _elm_config->tooltip_delay = delay;
1568 }
1569
1570 EAPI double
1571 elm_config_scale_get(void)
1572 {
1573    return _elm_config->scale;
1574 }
1575
1576 EAPI void
1577 elm_config_scale_set(double scale)
1578 {
1579    if (_elm_config->scale == scale) return;
1580    _elm_config->scale = scale;
1581    _elm_rescale();
1582 }
1583
1584 EAPI Eina_Bool
1585 elm_config_password_show_last_get(void)
1586 {
1587    return _elm_config->password_show_last;
1588 }
1589
1590 EAPI void
1591 elm_config_password_show_last_set(Eina_Bool password_show_last)
1592 {
1593    if (_elm_config->password_show_last == password_show_last) return;
1594    _elm_config->password_show_last = password_show_last;
1595    edje_password_show_last_set(_elm_config->password_show_last);
1596 }
1597
1598 EAPI double
1599 elm_config_password_show_last_timeout_get(void)
1600 {
1601    return _elm_config->password_show_last_timeout;
1602 }
1603
1604 EAPI void
1605 elm_config_password_show_last_timeout_set(double password_show_last_timeout)
1606 {
1607    if (_elm_config->password_show_last_timeout == password_show_last_timeout) return;
1608    _elm_config->password_show_last_timeout = password_show_last_timeout;
1609    edje_password_show_last_timeout_set(_elm_config->password_show_last_timeout);
1610 }
1611
1612 EAPI Eina_Bool
1613 elm_config_save(void)
1614 {
1615    return _elm_config_save();
1616 }
1617
1618 EAPI void
1619 elm_config_reload(void)
1620 {
1621    _elm_config_reload();
1622 }
1623
1624 EAPI const char *
1625 elm_config_profile_get(void)
1626 {
1627    return _elm_config_current_profile_get();
1628 }
1629
1630 EAPI const char *
1631 elm_config_profile_dir_get(const char *profile,
1632                     Eina_Bool   is_user)
1633 {
1634    return _elm_config_profile_dir_get(profile, is_user);
1635 }
1636
1637 EAPI void
1638 elm_config_profile_dir_free(const char *p_dir)
1639 {
1640    free((void *)p_dir);
1641 }
1642
1643 EAPI Eina_List *
1644 elm_config_profile_list_get(void)
1645 {
1646    return _elm_config_profiles_list();
1647 }
1648
1649 EAPI void
1650 elm_config_profile_list_free(Eina_List *l)
1651 {
1652    const char *dir;
1653
1654    EINA_LIST_FREE(l, dir)
1655      eina_stringshare_del(dir);
1656 }
1657
1658 EAPI void
1659 elm_config_profile_set(const char *profile)
1660 {
1661    EINA_SAFETY_ON_NULL_RETURN(profile);
1662    _elm_config_profile_set(profile);
1663 }
1664
1665 EAPI const char *
1666 elm_config_engine_get(void)
1667 {
1668    return _elm_config->engine;
1669 }
1670
1671 EAPI void
1672 elm_config_engine_set(const char *engine)
1673 {
1674    EINA_SAFETY_ON_NULL_RETURN(engine);
1675
1676    _elm_config_engine_set(engine);
1677 }
1678
1679 EAPI Eina_List *
1680 elm_config_text_classes_list_get(void)
1681 {
1682    return _elm_config_text_classes_get();
1683 }
1684
1685 EAPI void
1686 elm_config_text_classes_list_free(Eina_List *list)
1687 {
1688    _elm_config_text_classes_free(list);
1689 }
1690
1691 EAPI const Eina_List *
1692 elm_config_font_overlay_list_get(void)
1693 {
1694    return _elm_config_font_overlays_list();
1695 }
1696
1697 EAPI void
1698 elm_config_font_overlay_set(const char    *text_class,
1699                      const char    *font,
1700                      Evas_Font_Size size)
1701 {
1702    EINA_SAFETY_ON_NULL_RETURN(text_class);
1703    _elm_config_font_overlay_set(text_class, font, size);
1704 }
1705
1706 EAPI void
1707 elm_config_font_overlay_unset(const char *text_class)
1708 {
1709    EINA_SAFETY_ON_NULL_RETURN(text_class);
1710    _elm_config_font_overlay_remove(text_class);
1711 }
1712
1713 EAPI void
1714 elm_config_font_overlay_apply(void)
1715 {
1716    _elm_config_font_overlay_apply();
1717 }
1718
1719 EAPI Evas_Coord
1720 elm_config_finger_size_get(void)
1721 {
1722    return _elm_config->finger_size;
1723 }
1724
1725 EAPI void
1726 elm_config_finger_size_set(Evas_Coord size)
1727 {
1728    if (_elm_config->finger_size == size) return;
1729    _elm_config->finger_size = size;
1730    _elm_rescale();
1731 }
1732
1733 EAPI int
1734 elm_config_cache_flush_interval_get(void)
1735 {
1736    return _elm_config->cache_flush_poll_interval;
1737 }
1738
1739 EAPI void
1740 elm_config_cache_flush_interval_set(int size)
1741 {
1742    if (_elm_config->cache_flush_poll_interval == size) return;
1743    _elm_config->cache_flush_poll_interval = size;
1744
1745    _elm_recache();
1746 }
1747
1748 EAPI Eina_Bool
1749 elm_config_cache_flush_enabled_get(void)
1750 {
1751    return _elm_config->cache_flush_enable;
1752 }
1753
1754 EAPI void
1755 elm_config_cache_flush_enabled_set(Eina_Bool enabled)
1756 {
1757    enabled = !!enabled;
1758    if (_elm_config->cache_flush_enable == enabled) return;
1759    _elm_config->cache_flush_enable = enabled;
1760
1761    _elm_recache();
1762 }
1763
1764 EAPI int
1765 elm_config_cache_font_cache_size_get(void)
1766 {
1767    return _elm_config->font_cache;
1768 }
1769
1770 EAPI void
1771 elm_config_cache_font_cache_size_set(int size)
1772 {
1773    if (_elm_config->font_cache == size) return;
1774    _elm_config->font_cache = size;
1775
1776    _elm_recache();
1777 }
1778
1779 EAPI int
1780 elm_config_cache_image_cache_size_get(void)
1781 {
1782    return _elm_config->image_cache;
1783 }
1784
1785 EAPI void
1786 elm_config_cache_image_cache_size_set(int size)
1787 {
1788    if (_elm_config->image_cache == size) return;
1789    _elm_config->image_cache = size;
1790
1791    _elm_recache();
1792 }
1793
1794 EAPI int
1795 elm_config_cache_edje_file_cache_size_get()
1796 {
1797    return _elm_config->edje_cache;
1798 }
1799
1800 EAPI void
1801 elm_config_cache_edje_file_cache_size_set(int size)
1802 {
1803    if (_elm_config->edje_cache == size) return;
1804    _elm_config->edje_cache = size;
1805
1806    _elm_recache();
1807 }
1808
1809 EAPI int
1810 elm_config_cache_edje_collection_cache_size_get(void)
1811 {
1812    return _elm_config->edje_collection_cache;
1813 }
1814
1815 EAPI void
1816 elm_config_cache_edje_collection_cache_size_set(int size)
1817 {
1818    if (_elm_config->edje_collection_cache == size) return;
1819    _elm_config->edje_collection_cache = size;
1820
1821    _elm_recache();
1822 }
1823
1824 EAPI Eina_Bool
1825 elm_config_focus_highlight_enabled_get(void)
1826 {
1827    return _elm_config->focus_highlight_enable;
1828 }
1829
1830 EAPI void
1831 elm_config_focus_highlight_enabled_set(Eina_Bool enable)
1832 {
1833    _elm_config->focus_highlight_enable = !!enable;
1834 }
1835
1836 EAPI Eina_Bool
1837 elm_config_focus_highlight_animate_get(void)
1838 {
1839    return _elm_config->focus_highlight_animate;
1840 }
1841
1842 EAPI void
1843 elm_config_focus_highlight_animate_set(Eina_Bool animate)
1844 {
1845    _elm_config->focus_highlight_animate = !!animate;
1846 }
1847
1848 EAPI Eina_Bool
1849 elm_config_scroll_bounce_enabled_get(void)
1850 {
1851    return _elm_config->thumbscroll_bounce_enable;
1852 }
1853
1854 EAPI void
1855 elm_config_scroll_bounce_enabled_set(Eina_Bool enabled)
1856 {
1857    _elm_config->thumbscroll_bounce_enable = enabled;
1858 }
1859
1860 EAPI double
1861 elm_config_scroll_bounce_friction_get(void)
1862 {
1863    return _elm_config->thumbscroll_bounce_friction;
1864 }
1865
1866 EAPI void
1867 elm_config_scroll_bounce_friction_set(double friction)
1868 {
1869    _elm_config->thumbscroll_bounce_friction = friction;
1870 }
1871
1872 EAPI double
1873 elm_config_scroll_page_scroll_friction_get(void)
1874 {
1875    return _elm_config->page_scroll_friction;
1876 }
1877
1878 EAPI void
1879 elm_config_scroll_page_scroll_friction_set(double friction)
1880 {
1881    _elm_config->page_scroll_friction = friction;
1882 }
1883
1884 EAPI double
1885 elm_config_scroll_bring_in_scroll_friction_get(void)
1886 {
1887    return _elm_config->bring_in_scroll_friction;
1888 }
1889
1890 EAPI void
1891 elm_config_scroll_bring_in_scroll_friction_set(double friction)
1892 {
1893    _elm_config->bring_in_scroll_friction = friction;
1894 }
1895
1896 EAPI double
1897 elm_config_scroll_zoom_friction_get(void)
1898 {
1899    return _elm_config->zoom_friction;
1900 }
1901
1902 EAPI void
1903 elm_config_scroll_zoom_friction_set(double friction)
1904 {
1905    _elm_config->zoom_friction = friction;
1906 }
1907
1908 EAPI Eina_Bool
1909 elm_config_scroll_thumbscroll_enabled_get(void)
1910 {
1911    return _elm_config->thumbscroll_enable;
1912 }
1913
1914 EAPI void
1915 elm_config_scroll_thumbscroll_enabled_set(Eina_Bool enabled)
1916 {
1917    _elm_config->thumbscroll_enable = enabled;
1918 }
1919
1920 EAPI unsigned int
1921 elm_config_scroll_thumbscroll_threshold_get(void)
1922 {
1923    return _elm_config->thumbscroll_threshold;
1924 }
1925
1926 EAPI void
1927 elm_config_scroll_thumbscroll_threshold_set(unsigned int threshold)
1928 {
1929    _elm_config->thumbscroll_threshold = threshold;
1930 }
1931
1932 EAPI double
1933 elm_config_scroll_thumbscroll_momentum_threshold_get(void)
1934 {
1935    return _elm_config->thumbscroll_momentum_threshold;
1936 }
1937
1938 EAPI void
1939 elm_config_scroll_thumbscroll_momentum_threshold_set(double threshold)
1940 {
1941    _elm_config->thumbscroll_momentum_threshold = threshold;
1942 }
1943
1944 EAPI double
1945 elm_config_scroll_thumbscroll_friction_get(void)
1946 {
1947    return _elm_config->thumbscroll_friction;
1948 }
1949
1950 EAPI void
1951 elm_config_scroll_thumbscroll_friction_set(double friction)
1952 {
1953    _elm_config->thumbscroll_friction = friction;
1954 }
1955
1956 EAPI double
1957 elm_config_scroll_thumbscroll_border_friction_get(void)
1958 {
1959    return _elm_config->thumbscroll_border_friction;
1960 }
1961
1962 EAPI void
1963 elm_config_scroll_thumbscroll_border_friction_set(double friction)
1964 {
1965    if (friction < 0.0) friction = 0.0;
1966    if (friction > 1.0) friction = 1.0;
1967    _elm_config->thumbscroll_border_friction = friction;
1968 }
1969
1970 EAPI double
1971 elm_config_scroll_thumbscroll_sensitivity_friction_get(void)
1972 {
1973    return _elm_config->thumbscroll_sensitivity_friction;
1974 }
1975
1976 EAPI void
1977 elm_config_scroll_thumbscroll_sensitivity_friction_set(double friction)
1978 {
1979    if (friction < 0.1) friction = 0.1;
1980    if (friction > 1.0) friction = 1.0;
1981    _elm_config->thumbscroll_sensitivity_friction = friction;
1982 }
1983
1984 EAPI void
1985 elm_config_longpress_timeout_set(double longpress_timeout)
1986 {
1987    _elm_config->longpress_timeout = longpress_timeout;
1988 }
1989
1990 EAPI double
1991 elm_config_longpress_timeout_get(void)
1992 {
1993    return _elm_config->longpress_timeout;
1994 }
1995
1996 EAPI void
1997 elm_config_all_flush(void)
1998 {
1999 #ifdef HAVE_ELEMENTARY_X
2000    if (_prop_all_update_timer) ecore_timer_del(_prop_all_update_timer);
2001    _prop_all_update_timer = ecore_timer_add(0.1, _prop_all_update_cb, NULL);
2002 #endif
2003 }
2004
2005 static void
2006 _translation_init()
2007 {
2008 #ifdef ENABLE_NLS
2009    const char *cur_dom = textdomain(NULL);
2010    const char *trans_comment = gettext("");
2011    const char *msg_locale = setlocale(LC_MESSAGES, NULL);
2012
2013    /* Same concept as what glib does:
2014     * We shouldn't translate if there are no translations for the
2015     * application in the current locale + domain. (Unless locale is
2016     * en_/C where translating only parts of the interface make some
2017     * sense).
2018     */
2019    _elm_config->translate = !(strcmp (cur_dom, "messages") &&
2020          !*trans_comment && strncmp (msg_locale, "en_", 3) &&
2021          strcmp (msg_locale, "C"));
2022 #endif
2023 }
2024
2025 void
2026 _elm_config_init(void)
2027 {
2028    if (!ELM_EVENT_CONFIG_ALL_CHANGED)
2029       ELM_EVENT_CONFIG_ALL_CHANGED = ecore_event_type_new();
2030    _desc_init();
2031    _profile_fetch_from_conf();
2032    _config_load();
2033    _env_get();
2034    if (_elm_preferred_engine) eina_stringshare_del(_elm_preferred_engine);
2035    if (_elm_config->engine)
2036      _elm_preferred_engine = eina_stringshare_add(_elm_config->engine);
2037    else
2038      _elm_preferred_engine = NULL;
2039    _translation_init();
2040    _config_apply();
2041    _elm_config_font_overlay_apply();
2042    _elm_recache();
2043 }
2044
2045 void
2046 _elm_config_sub_shutdown(void)
2047 {
2048 #define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
2049    if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
2050        ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
2051        ENGINE_COMPARE(ELM_XRENDER_X11) ||
2052        ENGINE_COMPARE(ELM_OPENGL_X11) ||
2053        ENGINE_COMPARE(ELM_OPENGL_COCOA))
2054 #undef ENGINE_COMPARE
2055      {
2056 #ifdef HAVE_ELEMENTARY_X
2057         ecore_x_disconnect();
2058 #endif
2059      }
2060 }
2061
2062 void
2063 _elm_config_sub_init(void)
2064 {
2065 #define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
2066    if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
2067        ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
2068        ENGINE_COMPARE(ELM_XRENDER_X11) ||
2069        ENGINE_COMPARE(ELM_OPENGL_X11) ||
2070        ENGINE_COMPARE(ELM_OPENGL_COCOA))
2071 #undef ENGINE_COMPARE
2072      {
2073 #ifdef HAVE_ELEMENTARY_X
2074         if (!ecore_x_init(NULL))
2075           {
2076              ERR("Cannot connect to X11 display. check $DISPLAY variable");
2077              exit(1);
2078           }
2079         _root_1st = ecore_x_window_root_first_get();
2080
2081         if (!ecore_x_screen_is_composited(0))
2082           _elm_config->compositing = 0;
2083
2084         ecore_x_atoms_get(_atom_names, ATOM_COUNT, _atom);
2085         ecore_x_event_mask_set(_root_1st,
2086                                ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
2087         _prop_change_handler = ecore_event_handler_add
2088             (ECORE_X_EVENT_WINDOW_PROPERTY, _prop_change, NULL);
2089         if (!getenv("ELM_PROFILE"))
2090           {
2091              char *s;
2092
2093              s = ecore_x_window_prop_string_get(_root_1st,
2094                                                 _atom[ATOM_E_PROFILE]);
2095              if (s)
2096                {
2097                   int changed = 0;
2098
2099                   if (_elm_profile)
2100                     {
2101                        if (strcmp(_elm_profile, s)) changed = 1;
2102                        free(_elm_profile);
2103                     }
2104                   _elm_profile = s;
2105                   if (changed) _prop_config_get();
2106                }
2107           }
2108 #endif
2109      }
2110    _config_sub_apply();
2111 }
2112
2113 void
2114 _elm_config_reload(void)
2115 {
2116    _config_free();
2117    _config_load();
2118    _config_apply();
2119    _elm_config_font_overlay_apply();
2120    _elm_rescale();
2121    _elm_recache();
2122 }
2123
2124 void
2125 _elm_config_engine_set(const char *engine)
2126 {
2127    if (_elm_config->engine && strcmp(_elm_config->engine, engine))
2128      eina_stringshare_del(_elm_config->engine);
2129
2130    _elm_config->engine = eina_stringshare_add(engine);
2131 }
2132
2133 EAPI const char *
2134 elm_config_preferred_engine_get(void)
2135 {
2136    return _elm_preferred_engine;
2137 }
2138
2139 EAPI void
2140 elm_config_preferred_engine_set(const char *engine)
2141 {
2142    if (engine)
2143      eina_stringshare_replace(&(_elm_preferred_engine), engine);
2144    else
2145      {
2146         if (_elm_preferred_engine) eina_stringshare_del(_elm_preferred_engine);
2147         _elm_preferred_engine = eina_stringshare_add(_elm_config->engine);
2148      }
2149 }
2150
2151 void
2152 _elm_config_profile_set(const char *profile)
2153 {
2154    Eina_Bool changed = EINA_FALSE;
2155
2156    if (_elm_profile)
2157      {
2158         if (strcmp(_elm_profile, profile))
2159           changed = 1;
2160         free(_elm_profile);
2161      }
2162
2163    _elm_profile = strdup(profile);
2164
2165    if (changed)
2166      {
2167         _config_free();
2168         _config_load();
2169         _config_apply();
2170         _elm_config_font_overlay_apply();
2171         _elm_rescale();
2172         _elm_recache();
2173      }
2174 }
2175
2176 void
2177 _elm_config_shutdown(void)
2178 {
2179 #ifdef HAVE_ELEMENTARY_X
2180    if (_prop_all_update_timer)
2181      {
2182         ecore_timer_del(_prop_all_update_timer);
2183         _prop_all_update_timer = NULL;
2184         _prop_all_update_cb(NULL);
2185      }
2186    if (_prop_change_delay_timer) ecore_timer_del(_prop_change_delay_timer);
2187    _prop_change_delay_timer = NULL;
2188 #endif
2189
2190 #define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
2191    if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
2192        ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
2193        ENGINE_COMPARE(ELM_XRENDER_X11) ||
2194        ENGINE_COMPARE(ELM_OPENGL_X11))
2195 #undef ENGINE_COMPARE
2196      {
2197 #ifdef HAVE_ELEMENTARY_X
2198         ecore_event_handler_del(_prop_change_handler);
2199         _prop_change_handler = NULL;
2200 #endif
2201      }
2202    _config_free();
2203    if (_elm_preferred_engine)
2204      {
2205         eina_stringshare_del(_elm_preferred_engine);
2206         _elm_preferred_engine = NULL;
2207      }
2208    if (_elm_profile)
2209      {
2210         free(_elm_profile);
2211         _elm_profile = NULL;
2212      }
2213    _desc_shutdown();
2214 }
2215