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