f092f414570811e320e14bbf9b26ad89608c769f
[framework/uifw/e17.git] / src / modules / conf_theme / e_int_config_fonts.c
1 #include "e.h"
2
3 typedef struct _E_Font_Size_Data E_Font_Size_Data;
4 typedef struct _E_Text_Class_Pair E_Text_Class_Pair;
5 typedef struct _CFText_Class CFText_Class;
6
7 static void *_create_data(E_Config_Dialog *cfd);
8 static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
9 static int _basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
10 static Evas_Object *_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
11 static int _advanced_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
12 static Evas_Object *_advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
13
14 static void _basic_font_cb_change(void *data, Evas_Object *obj);
15 static void _basic_enable_cb_change(void *data, Evas_Object *obj);
16 static void _basic_init_data_fill(E_Config_Dialog_Data *cfdata);
17
18 static void _adv_class_cb_change(void *data, Evas_Object *obj);
19 static void _adv_enabled_font_cb_change(void *data, Evas_Object *obj);
20 static void _adv_enabled_fallback_cb_change(void *data, Evas_Object *obj);
21 static void _adv_font_cb_change(void *data, Evas_Object *obj);
22 static void _adv_style_cb_change(void *data, Evas_Object *obj);
23 static void _size_cb_change(void *data);
24
25 static int  _sort_fonts(const void *data1, const void *data2);
26 static void _font_list_load(E_Config_Dialog_Data *cfdata, const char *cur_font);
27 static void _size_list_load(E_Config_Dialog_Data *cfdata, Eina_List *size_list, Evas_Font_Size cur_size, int clear);
28 static void _class_list_load(E_Config_Dialog_Data *cfdata);
29 static void _font_preview_update(E_Config_Dialog_Data *cfdata);
30
31 static Eina_Bool _font_hash_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata);
32
33 struct _E_Font_Size_Data
34 {
35    E_Config_Dialog_Data *cfdata;
36    const char           *size_str;
37    Evas_Font_Size        size;
38 };
39
40 struct _E_Text_Class_Pair
41 {
42    const char *class_name;
43    const char *class_description;
44 };
45
46 struct _CFText_Class
47 {
48    const char     *class_name;
49    const char     *class_description;
50    const char     *font;
51    const char     *style;
52    Evas_Font_Size  size;
53    unsigned char   enabled : 1;
54 };
55
56 const E_Text_Class_Pair text_class_predefined_names[ ] = {
57      {  NULL,             N_("Core")},
58      { "title_bar",       N_("Title Bar")},
59      { "menu_item",       N_("Menu Item")},
60      { "menu_title",      N_("Menu Title")},
61      { "tb_plain",        N_("Textblock Plain")},
62      { "tb_light",        N_("Textblock Light")},
63      { "tb_big",          N_("Textblock Big")},
64      { "move_text",       N_("Move Text")},
65      { "resize_text",     N_("Resize Text")},
66      { "winlist_title",   N_("Winlist Title")},
67      { "configure",       N_("Settings Heading")},
68      { "about_title",     N_("About Title")},
69      { "about_version",   N_("About Version")},
70      { "button_text",     N_("About Text")},
71      { "desklock_title",  N_("Desklock Title")},
72      { "desklock_passwd", N_("Desklock Password")},
73      { "dialog_error",    N_("Dialog Error")},
74      { "exebuf_command",  N_("Exebuf Command")},
75      { "init_title",      N_("Splash Title")},
76      { "init_text",       N_("Splash Text")},
77      { "init_version",    N_("Splash Version")},
78
79      {  NULL,             N_("Widgets")},
80      { "entry",           N_("Entry")},
81      { "frame",           N_("Frame")},
82      { "label",           N_("Label")},
83      { "button",          N_("Buttons")},
84      { "slider",          N_("Slider")},
85      { "radio_button",    N_("Radio Buttons")},
86      { "check_button",    N_("Check Buttons")},
87      { "tlist",           N_("Text List Item")},
88      { "ilist_item",      N_("List Item")},
89      { "ilist_header",    N_("List Header")},
90
91      {  NULL,             N_("Filemanager")},
92      { "fileman_typebuf", N_("Typebuf")},
93      { "fileman_icon",    N_("Icon")},
94      { "desktop_icon",    N_("Desktop Icon")},
95
96      {  NULL,             N_("Modules")},
97      { "module_small",    N_("Small")},
98      { "module_normal",   N_("Normal")},
99      { "module_large",    N_("Large")},
100      { "module_small_s",  N_("Small Styled")},
101      { "module_normal_s", N_("Normal Styled")},
102      { "module_large_s",  N_("Large Styled")},
103
104      { NULL, NULL}
105 };
106
107 struct _E_Config_Dialog_Data
108 {
109    E_Config_Dialog *cfd;
110    Evas *evas;
111
112    /* Text Classes */
113    Eina_List    *text_classes;
114
115    /* Font Data */
116    Eina_Hash    *font_hash;
117    Eina_List    *font_list;
118    Eina_List    *font_px_list;
119    Eina_List    *font_scale_list;
120
121    /* Current data */
122    const char   *cur_font;
123    const char   *cur_style;
124    double        cur_size;
125    int           cur_enabled;
126    int           cur_index;
127
128    /* Font Fallbacks */
129    int           cur_fallbacks_enabled;
130
131    /* Font Hinting */
132    int           hinting;
133
134    struct
135      {
136         /* Font Classes */
137         Evas_Object *class_list;
138         Evas_Object *font_list;
139         Evas_Object *style_list;
140         Evas_Object *size_list;
141         Evas_Object *enabled;
142         Evas_Object *preview;
143
144         /* Font Fallbacks */
145         Evas_Object *fallback_list; /* Selecting a list entry starts edit*/
146      } gui;
147 };
148
149 E_Config_Dialog *
150 e_int_config_fonts(E_Container *con, const char *params __UNUSED__)
151 {
152    E_Config_Dialog *cfd;
153    E_Config_Dialog_View *v;
154
155    if (e_config_dialog_find("E", "appearance/fonts")) return NULL;
156    v = E_NEW(E_Config_Dialog_View, 1);
157
158    v->create_cfdata = _create_data;
159    v->free_cfdata = _free_data;
160    v->basic.create_widgets = _basic_create_widgets;
161    v->basic.apply_cfdata = _basic_apply_data;
162    v->advanced.create_widgets = _advanced_create_widgets;
163    v->advanced.apply_cfdata = _advanced_apply_data;
164
165    cfd = e_config_dialog_new(con, _("Font Settings"),
166                              "E", "appearance/fonts",
167                              "preferences-desktop-font", 0, v, NULL);
168    return cfd;
169 }
170
171 static void
172 _fill_data(E_Config_Dialog_Data *cfdata)
173 {
174    Eina_List *font_list;
175    Eina_List *next;
176    E_Font_Default *efd;
177    E_Font_Size_Data *size_data;
178    CFText_Class *tc;
179    int i;
180
181    font_list = e_font_default_list();
182
183    /* Fill out the font list */
184    for (i = 0; text_class_predefined_names[i].class_description; i++ )
185      {
186         tc = E_NEW(CFText_Class, 1);
187         tc->class_name = text_class_predefined_names[i].class_name;
188         tc->class_description =
189           _(text_class_predefined_names[i].class_description);
190         tc->font = NULL;
191         tc->size = 0;
192         tc->enabled = 0;
193
194         if (text_class_predefined_names[i].class_name)
195           {
196              /* Search manually because we dont want to fallback */
197              for (next = font_list; next ; next = next->next)
198                {
199                   efd = next->data;
200
201                   if (!strcmp(tc->class_name, efd->text_class))
202                     {
203                        if (efd->font)
204                          {
205                             E_Font_Properties *efp;
206
207                             efp = e_font_fontconfig_name_parse(efd->font);
208                             if (efp->name)
209                               tc->font = eina_stringshare_add(efp->name);
210                             if (efp->styles)
211                               tc->style = eina_stringshare_add(efp->styles->data);
212                             e_font_properties_free(efp);
213                          }
214                        tc->size = efd->size;
215                        tc->enabled = 1;
216                     }
217                }
218
219              if (!tc->enabled)
220                {
221                   /* search with default fallbacks */
222                   efd = e_font_default_get(tc->class_name);
223                   if (efd)
224                     {
225                        if (efd->font)
226                          {
227                             E_Font_Properties *efp;
228
229                             efp = e_font_fontconfig_name_parse(efd->font);
230                             if (efp->name)
231                               tc->font = eina_stringshare_add(efp->name);
232                             if (efp->styles)
233                               tc->style = eina_stringshare_add(efp->styles->data);
234                             e_font_properties_free(efp);
235                          }
236                        tc->size = efd->size;
237                     }
238                }
239           }
240
241         /* Append the class */
242         cfdata->text_classes = eina_list_append(cfdata->text_classes, tc);
243      }
244
245    /* Fill Hinting */
246    cfdata->hinting = e_config->font_hinting;
247
248    size_data = E_NEW(E_Font_Size_Data, 1);
249    size_data->cfdata = cfdata;
250    size_data->size_str = eina_stringshare_add(_("Tiny"));
251    size_data->size = -50;
252    cfdata->font_scale_list = eina_list_append(cfdata->font_scale_list, size_data);
253
254    size_data = E_NEW(E_Font_Size_Data, 1);
255    size_data->cfdata = cfdata;
256    size_data->size_str = eina_stringshare_add(_("Small"));
257    size_data->size = -80;
258    cfdata->font_scale_list = eina_list_append(cfdata->font_scale_list, size_data);
259
260    size_data = E_NEW(E_Font_Size_Data, 1);
261    size_data->cfdata = cfdata;
262    size_data->size_str = eina_stringshare_add(_("Normal"));
263    size_data->size = -100;
264    cfdata->font_scale_list = eina_list_append(cfdata->font_scale_list, size_data);
265
266    size_data = E_NEW(E_Font_Size_Data, 1);
267    size_data->cfdata = cfdata;
268    size_data->size_str = eina_stringshare_add(_("Big"));
269    size_data->size = -150;
270    cfdata->font_scale_list = eina_list_append(cfdata->font_scale_list, size_data);
271
272    size_data = E_NEW(E_Font_Size_Data, 1);
273    size_data->cfdata = cfdata;
274    size_data->size_str = eina_stringshare_add(_("Really Big"));
275    size_data->size = -190;
276    cfdata->font_scale_list = eina_list_append(cfdata->font_scale_list, size_data);
277
278    size_data = E_NEW(E_Font_Size_Data, 1);
279    size_data->cfdata = cfdata;
280    size_data->size_str = eina_stringshare_add(_("Huge"));
281    size_data->size = -250;
282    cfdata->font_scale_list = eina_list_append(cfdata->font_scale_list, size_data);
283
284    for (i = 5; i < 21; i++)
285      {
286         char str[16];
287
288         str[0] = 0;
289         snprintf(str, sizeof(str), _("%d pixels"), i);
290
291         size_data = E_NEW(E_Font_Size_Data, 1);
292         size_data->cfdata = cfdata;
293         size_data->size_str = eina_stringshare_add(str);
294         size_data->size = i;
295         cfdata->font_px_list = eina_list_append(cfdata->font_px_list, size_data);
296      }
297 }
298
299 static void *
300 _create_data(E_Config_Dialog *cfd)
301 {
302    E_Config_Dialog_Data *cfdata;
303
304    cfdata = E_NEW(E_Config_Dialog_Data, 1);
305    cfdata->cfd = cfd;
306    _fill_data(cfdata);
307    return cfdata;
308 }
309
310 static void
311 _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
312 {
313    E_Font_Size_Data *size_data;
314    CFText_Class *tc;
315
316    e_font_available_hash_free(cfdata->font_hash);
317    cfdata->font_list =eina_list_free(cfdata->font_list);
318
319    EINA_LIST_FREE(cfdata->text_classes, tc)
320      {
321         eina_stringshare_del(tc->font);
322         eina_stringshare_del(tc->style);
323         E_FREE(tc);
324      }
325
326    EINA_LIST_FREE(cfdata->font_scale_list, size_data)
327      {
328         eina_stringshare_del(size_data->size_str);
329         E_FREE(size_data);
330      }
331
332    EINA_LIST_FREE(cfdata->font_px_list, size_data)
333      {
334         eina_stringshare_del(size_data->size_str);
335         E_FREE(size_data);
336      }
337
338    eina_stringshare_del(cfdata->cur_font);
339    eina_stringshare_del(cfdata->cur_style);
340    E_FREE(cfdata);
341 }
342
343 static int
344 _basic_apply_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
345 {
346    CFText_Class *tc;
347    Eina_List *next;
348    int i;
349
350    if (cfdata->cur_enabled && !cfdata->cur_font)
351      return 0;
352
353    for (i = 0; text_class_predefined_names[i].class_description; i++ )
354      {
355         if (!text_class_predefined_names[i].class_name) continue;
356
357         if (cfdata->cur_enabled)
358           {
359              const char *class_name;
360              const char *font_name;
361
362              class_name = text_class_predefined_names[i].class_name;
363              font_name =
364                e_font_fontconfig_name_get(cfdata->cur_font, cfdata->cur_style);
365              e_font_default_set(class_name, font_name, cfdata->cur_size);
366
367              if (i == 1)
368                e_font_default_set("e_basic_font", font_name, cfdata->cur_size);
369
370              eina_stringshare_del(font_name);
371           }
372         else
373           {
374              e_font_default_remove(text_class_predefined_names[i].class_name);
375              if (i == 1)
376                e_font_default_remove("e_basic_font");
377           }
378      }
379
380    e_font_apply();
381    e_config_save_queue();
382
383    /* Apply to advanced */
384    EINA_LIST_FOREACH(cfdata->text_classes, next, tc)
385      {
386         tc->size = cfdata->cur_size;
387
388         eina_stringshare_del(tc->font);
389         tc->font = eina_stringshare_ref(cfdata->cur_font);
390
391         eina_stringshare_del(tc->style);
392         tc->style = eina_stringshare_ref(cfdata->cur_style);
393         tc->enabled = cfdata->cur_enabled;
394      }
395
396    return 1;
397 }
398
399 static Eina_Bool
400 _font_hash_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata)
401 {
402    E_Config_Dialog_Data *cfdata;
403    E_Font_Properties *efp;
404
405    cfdata = fdata;
406    efp = data;
407    cfdata->font_list = eina_list_append(cfdata->font_list, efp->name);
408
409    return EINA_TRUE;
410 }
411
412 static Evas_Object *
413 _basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
414 {
415    Evas_Object *ot, *ob, *of;
416
417    cfdata->cur_index = -1;
418    cfdata->evas = evas;
419
420    ot = e_widget_table_add(evas, 0);
421
422    cfdata->gui.class_list = NULL;
423
424    ob = e_widget_check_add(evas, _("Enable Custom Font Classes"),
425                            &(cfdata->cur_enabled));
426    cfdata->gui.enabled = ob;
427    e_widget_on_change_hook_set(ob, _basic_enable_cb_change, cfdata);
428    e_widget_disabled_set(ob, 0);
429    e_widget_table_object_append(ot, ob, 0, 0, 1, 1, 1, 0, 1, 0);
430
431    of = e_widget_framelist_add(evas, _("Fonts"), 1);
432    ob = e_widget_ilist_add(evas, 16, 16, &(cfdata->cur_font));
433    cfdata->gui.font_list = ob;
434    e_widget_on_change_hook_set(ob, _basic_font_cb_change, cfdata);
435    e_widget_ilist_go(ob);
436    e_widget_framelist_object_append(of, ob);
437    e_widget_table_object_append(ot, of, 0, 1, 1, 1, 1, 1, 1, 1);
438
439    of = e_widget_framelist_add(evas, _("Size"), 1);
440    ob = e_widget_ilist_add(evas, 16, 16, NULL);
441    cfdata->gui.size_list = ob;
442    e_widget_ilist_go(ob);
443    e_widget_size_min_set(ob, 100, 200);
444    e_widget_framelist_object_append(of, ob);
445    e_widget_table_object_append(ot, of, 1, 1, 1, 1, 1, 1, 1, 1);
446
447    ob =
448      e_widget_font_preview_add(evas, _("Basic preview text: 123: 我的天空!"));
449    cfdata->gui.preview = ob;
450    e_widget_table_object_append(ot, ob, 0, 2, 2, 1, 1, 0, 1, 0);
451
452    _basic_init_data_fill(cfdata);
453
454    e_dialog_resizable_set(cfd->dia, 1);
455    return ot;
456 }
457
458 static void
459 _basic_font_cb_change(void *data, Evas_Object *obj __UNUSED__)
460 {
461    E_Config_Dialog_Data *cfdata;
462
463    cfdata = data;
464    if (!cfdata) return;
465    _font_preview_update(cfdata);
466 }
467
468 static void
469 _basic_enable_cb_change(void *data, Evas_Object *obj __UNUSED__)
470 {
471    E_Config_Dialog_Data *cfdata;
472
473    cfdata = data;
474    if (!cfdata) return;
475
476    e_widget_disabled_set(cfdata->gui.font_list, !cfdata->cur_enabled);
477    e_widget_disabled_set(cfdata->gui.size_list, !cfdata->cur_enabled);
478
479    if (!cfdata->cur_enabled)
480      {
481         e_widget_ilist_unselect(cfdata->gui.font_list);
482         e_widget_ilist_unselect(cfdata->gui.size_list);
483      }
484 }
485
486 /* fill the basic dialog with initial data and select it */
487 static void
488 _basic_init_data_fill(E_Config_Dialog_Data *cfdata)
489 {
490    Evas_Object *ob;
491    E_Font_Default *efd;
492    const char *init_font;
493    Evas_Font_Size init_size;
494
495    init_font = NULL;
496    init_size = -100;
497
498    /* Get initial basic basic */
499    efd = e_font_default_get("e_basic_font");
500    if (efd)
501      {
502         if (efd->font)
503           {
504              E_Font_Properties *efp;
505
506              efp = e_font_fontconfig_name_parse(efd->font);
507              init_font = eina_stringshare_add(efp->name);
508              e_font_properties_free(efp);
509           }
510         init_size = efd->size;
511      }
512
513    /* Check based on efd */
514    ob = cfdata->gui.enabled;
515    if (!efd)
516      e_widget_check_checked_set(ob, 0);
517    else if (!strcmp(efd->text_class, "default"))
518      e_widget_check_checked_set(ob, 0);
519    else
520      e_widget_check_checked_set(ob, 1);
521
522    /* Populate font list (Select current font) */
523    _font_list_load(cfdata, init_font);
524
525    /* Populate size list (Select current font) */
526    _size_list_load(cfdata, cfdata->font_scale_list, init_size, 1);
527 }
528
529 static int
530 _advanced_apply_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
531 {
532    int i;
533    Eina_List *next;
534    CFText_Class *tc;
535
536    /* Save current data */
537    if (cfdata->cur_index >= 0)
538      {
539         tc = eina_list_nth(cfdata->text_classes, cfdata->cur_index);
540         tc->enabled = cfdata->cur_enabled;
541         tc->size = cfdata->cur_size;
542         if (cfdata->cur_font)
543           tc->font = eina_stringshare_ref(cfdata->cur_font);
544         if (cfdata->cur_style)
545           tc->style = eina_stringshare_ref(cfdata->cur_style);
546      }
547
548    EINA_LIST_FOREACH(cfdata->text_classes, next, tc)
549      {
550         if (!tc->class_name) continue;
551         if (tc->enabled && tc->font)
552           {
553              const char *name;
554
555              name = e_font_fontconfig_name_get(tc->font, tc->style);
556              e_font_default_set(tc->class_name, name, tc->size);
557              eina_stringshare_del(name);
558           }
559         else
560           e_font_default_remove(tc->class_name);
561      }
562
563    /* Fallbacks configure */
564    e_font_fallback_clear();
565
566    if (cfdata->cur_fallbacks_enabled)
567      {
568         for (i = 0; i < e_widget_config_list_count(cfdata->gui.fallback_list); i++)
569           {
570              const char *fallback;
571
572              fallback =
573                e_widget_config_list_nth_get(cfdata->gui.fallback_list, i);
574              if ((fallback) && (fallback[0]))
575                e_font_fallback_append(fallback);
576           }
577      }
578    e_font_apply();
579
580    /* Apply Hinting */
581    e_config->font_hinting = cfdata->hinting;
582    e_config_save_queue();
583    e_canvas_rehint();
584    return 1;
585 }
586
587 static Evas_Object *
588 _advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
589 {
590    Evas_Object *ot, *ob, *of, *otb;
591    E_Radio_Group *rg;
592    Eina_List *next = NULL;
593    int option_enable;
594
595    cfdata->cur_index = -1;
596    cfdata->evas = evas;
597
598    otb = e_widget_toolbook_add(evas, 48 * e_scale, 48 * e_scale);
599
600    ot = e_widget_table_add(evas, 0);
601    of = e_widget_frametable_add(evas, _("Font Classes"), 0);
602    ob = e_widget_ilist_add(evas, 16, 16, NULL);
603    cfdata->gui.class_list = ob;
604    _class_list_load(cfdata);
605    e_widget_ilist_multi_select_set(ob, 1);
606    e_widget_size_min_set(ob, 110, 220);
607    e_widget_on_change_hook_set(ob, _adv_class_cb_change, cfdata);
608    e_widget_frametable_object_append(of, ob, 0, 0, 1, 1, 1, 1, 1, 1);
609    ob = e_widget_check_add(evas, _("Enable Font Class"), &(cfdata->cur_enabled));
610    cfdata->gui.enabled = ob;
611    e_widget_on_change_hook_set(ob, _adv_enabled_font_cb_change, cfdata);
612    e_widget_disabled_set(ob, 1);
613    e_widget_frametable_object_append(of, ob, 0, 1, 1, 1, 1, 0, 1, 0);
614    e_widget_table_object_append(ot, of, 0, 0, 1, 2, 1, 1, 1, 1);
615
616    of = e_widget_framelist_add(evas, _("Font"), 1);
617    ob = e_widget_ilist_add(evas, 16, 16, &(cfdata->cur_font));
618    cfdata->gui.font_list = ob;
619    e_widget_on_change_hook_set(ob, _adv_font_cb_change, cfdata);
620    _font_list_load(cfdata, NULL);
621    e_widget_size_min_set(ob, 110, 220);
622    e_widget_framelist_object_append(of, ob);
623    e_widget_table_object_append(ot, of, 1, 0, 1, 2, 1, 1, 1, 1);
624
625    of = e_widget_framelist_add(evas, _("Style"), 1);
626    ob = e_widget_ilist_add(evas, 16, 16, &(cfdata->cur_style));
627    cfdata->gui.style_list = ob;
628    e_widget_on_change_hook_set(ob, _adv_style_cb_change, cfdata);
629    e_widget_ilist_go(ob);
630    e_widget_size_min_set(ob, 110, 50);
631    e_widget_framelist_object_append(of, ob);
632    e_widget_table_object_append(ot, of, 2, 0, 1, 1, 1, 1, 1, 1);
633
634    of = e_widget_framelist_add(evas, _("Size"), 1);
635    ob = e_widget_ilist_add(evas, 16, 16, NULL);
636    cfdata->gui.size_list = ob;
637    e_widget_ilist_go(ob);
638    e_widget_size_min_set(ob, 110, 50);
639    e_widget_framelist_object_append(of, ob);
640    e_widget_table_object_append(ot, of, 2, 1, 1, 1, 1, 1, 1, 1);
641
642    ob = e_widget_font_preview_add(evas, _("Advanced Preview Text.. 我真的会写中文"));
643    cfdata->gui.preview = ob;
644    e_widget_table_object_append(ot, ob, 0, 2, 3, 1, 1, 0, 1, 0);
645
646    e_widget_toolbook_page_append(otb, NULL, _("General Settings"),
647                                  ot, 1, 1, 1, 1, 0.5, 0.0);
648
649    ot = e_widget_table_add(evas, 0);
650    of = e_widget_frametable_add(evas, _("Hinting"), 0);
651    rg = e_widget_radio_group_new(&(cfdata->hinting));
652    option_enable = evas_font_hinting_can_hint(evas, EVAS_FONT_HINTING_BYTECODE);
653    ob = e_widget_radio_add(evas, _("Bytecode"), 0, rg);
654    e_widget_disabled_set(ob, !option_enable);
655    e_widget_frametable_object_append(of, ob, 0, 0, 1, 1, 1, 0, 1, 0);
656    option_enable = evas_font_hinting_can_hint(evas, EVAS_FONT_HINTING_AUTO);
657    ob = e_widget_radio_add(evas, _("Automatic"), 1, rg);
658    e_widget_disabled_set(ob, !option_enable);
659    e_widget_frametable_object_append(of, ob, 0, 1, 1, 1, 1, 0, 1, 0);
660    option_enable = evas_font_hinting_can_hint(evas, EVAS_FONT_HINTING_NONE);
661    ob = e_widget_radio_add(evas, _("None"), 2, rg);
662    e_widget_disabled_set(ob, !option_enable);
663    e_widget_frametable_object_append(of, ob, 0, 2, 1, 1, 1, 0, 1, 0);
664    e_widget_table_object_append(ot, of, 0, 0, 1, 1, 1, 1, 1, 0);
665
666    of = e_widget_framelist_add(evas, _("Font Fallbacks"), 0);
667    ob = e_widget_config_list_add(evas, e_widget_entry_add, _("Fallback Name"), 2);
668    cfdata->gui.fallback_list = ob;
669    option_enable = 0;
670    for (next = e_font_fallback_list(); next; next = next->next)
671      {
672         E_Font_Fallback *eff;
673
674         eff = next->data;
675         e_widget_config_list_append(ob, eff->name);
676         option_enable = 1;
677      }
678    if (next) eina_list_free(next);
679    ob = e_widget_check_add(evas, _("Enable Fallbacks"), &(cfdata->cur_fallbacks_enabled));
680    e_widget_config_list_object_append(cfdata->gui.fallback_list, ob,
681                                       0, 0, 2, 1, 1, 0, 1, 0);
682    e_widget_on_change_hook_set(ob, _adv_enabled_fallback_cb_change, cfdata);
683    e_widget_check_checked_set(ob, option_enable);
684    e_widget_change(ob);
685    e_widget_framelist_object_append(of, cfdata->gui.fallback_list);
686    e_widget_table_object_append(ot, of, 1, 0, 1, 1, 1, 1, 1, 0);
687
688    e_widget_toolbook_page_append(otb, NULL, _("Hinting / Fallbacks"),
689                                  ot, 1, 0, 1, 0, 0.5, 0.0);
690
691    e_widget_toolbook_page_show(otb, 0);
692    e_dialog_resizable_set(cfd->dia, 1);
693    return otb;
694 }
695
696 /* Private Font Class Functions */
697 static void
698 _class_list_load(E_Config_Dialog_Data *cfdata)
699 {
700    Evas *evas;
701    Eina_List *next;
702
703    if (!cfdata->gui.class_list) return;
704    evas = evas_object_evas_get(cfdata->gui.class_list);
705    evas_event_freeze(evas);
706    edje_freeze();
707    e_widget_ilist_freeze(cfdata->gui.class_list);
708    e_widget_ilist_clear(cfdata->gui.class_list);
709
710    /* Fill in Class Ilist */
711    for (next = cfdata->text_classes; next; next = next->next)
712      {
713         CFText_Class *tc;
714         Evas_Object *ic;
715
716         tc = next->data;
717         if (tc)
718           {
719              if (tc->class_name)
720                {
721                   if (tc->enabled)
722                     {
723                        ic = e_icon_add(evas);
724                        e_util_icon_theme_set(ic, "dialog-ok-apply");
725                     }
726                   else
727                     ic = NULL;
728                   e_widget_ilist_append(cfdata->gui.class_list, ic, tc->class_description, NULL, NULL, NULL);
729                }
730              else
731                e_widget_ilist_header_append(cfdata->gui.class_list, NULL, tc->class_description);
732           }
733      }
734    e_widget_ilist_go(cfdata->gui.class_list);
735    e_widget_ilist_thaw(cfdata->gui.class_list);
736    edje_thaw();
737    evas_event_thaw(evas);
738 }
739
740 /* Called whenever class list selection changes */
741 static void
742 _adv_class_cb_change(void *data, Evas_Object *obj __UNUSED__)
743 {
744    int indx;
745    E_Config_Dialog_Data *cfdata;
746    CFText_Class *tc;
747
748    if (!(cfdata = data)) return;
749
750    /* Save Current */
751    if (cfdata->cur_index >= 0)
752      {
753         tc = eina_list_nth(cfdata->text_classes, cfdata->cur_index);
754         tc->enabled = cfdata->cur_enabled;
755         tc->size = cfdata->cur_size;
756
757         eina_stringshare_del(tc->font);
758         tc->font = eina_stringshare_ref(cfdata->cur_font);
759
760         eina_stringshare_del(tc->style);
761         tc->style = eina_stringshare_ref(cfdata->cur_style);
762
763         if (cfdata->gui.style_list)
764           e_widget_ilist_unselect(cfdata->gui.style_list);
765         if (cfdata->gui.size_list)
766           e_widget_ilist_unselect(cfdata->gui.size_list);
767      }
768
769    /* If no class is selected unselect all and return */
770    indx = e_widget_ilist_selected_get(cfdata->gui.class_list);
771    if (indx < 0)
772      {
773         e_widget_disabled_set(cfdata->gui.enabled, 1);
774         e_widget_disabled_set(cfdata->gui.font_list, 1);
775         e_widget_disabled_set(cfdata->gui.size_list, 1);
776         e_widget_check_checked_set(cfdata->gui.enabled, 0);
777         if (cfdata->gui.font_list)
778           e_widget_ilist_unselect(cfdata->gui.font_list);
779         return;
780      }
781
782    tc = eina_list_nth(cfdata->text_classes, indx);
783    cfdata->cur_index = indx;
784
785    e_widget_disabled_set(cfdata->gui.enabled, 0);
786    e_widget_disabled_set(cfdata->gui.font_list, !tc->enabled);
787    e_widget_disabled_set(cfdata->gui.size_list, !tc->enabled);
788    e_widget_check_checked_set(cfdata->gui.enabled, tc->enabled);
789
790    if (cfdata->gui.font_list)
791      {
792         /* Select the configured font */
793         for (indx = 0; indx < e_widget_ilist_count(cfdata->gui.font_list); indx++)
794           {
795              const char *f;
796
797              f = e_widget_ilist_nth_label_get(cfdata->gui.font_list, indx);
798              if (tc->font && !strcasecmp(f, tc->font))
799                {
800                   e_widget_ilist_selected_set(cfdata->gui.font_list, indx);
801                   break;
802                }
803           }
804      }
805 }
806
807 static void
808 _adv_enabled_font_cb_change(void *data, Evas_Object *obj __UNUSED__)
809 {
810    E_Config_Dialog_Data *cfdata;
811    Eina_List *l;
812    int n;
813
814    if (!(cfdata = data)) return;
815    e_widget_disabled_set(cfdata->gui.font_list, !cfdata->cur_enabled);
816    e_widget_disabled_set(cfdata->gui.style_list, !cfdata->cur_enabled);
817    e_widget_disabled_set(cfdata->gui.size_list, !cfdata->cur_enabled);
818
819    /* Search class list fot selected and enable Icon */
820    for (n = 0, l = e_widget_ilist_items_get(cfdata->gui.class_list); l; l = l->next, n++)
821      {
822         E_Ilist_Item *i;
823         Evas_Object *icon = NULL;
824         CFText_Class *tc;
825
826         if (!(i = l->data)) continue;
827         if (!i->selected) continue;
828
829         tc = eina_list_nth(cfdata->text_classes, n);
830         tc->enabled = cfdata->cur_enabled;
831         tc->size = cfdata->cur_size;
832         eina_stringshare_del(tc->font);
833         if (cfdata->cur_font)
834           tc->font = eina_stringshare_ref(cfdata->cur_font);
835         if (cfdata->cur_enabled)
836           {
837              icon = e_icon_add(cfdata->evas);
838              e_util_icon_theme_set(icon, "enlightenment");
839           }
840         e_widget_ilist_nth_icon_set(cfdata->gui.class_list, n, icon);
841      }
842 }
843
844 static void
845 _size_cb_change(void *data)
846 {
847    E_Config_Dialog_Data *cfdata;
848    E_Font_Size_Data *size_data;
849    Eina_List *l;
850    int n;
851
852    size_data = data;
853    if (!(cfdata = size_data->cfdata)) return;
854
855    cfdata->cur_size = size_data->size;
856
857    _font_preview_update(cfdata);
858
859    if (!cfdata->gui.class_list) return;
860
861    for (n = 0, l = e_widget_ilist_items_get(cfdata->gui.class_list); l; l = l->next, n++)
862      {
863         E_Ilist_Item *i;
864         CFText_Class *tc;
865
866         if (!(i = l->data)) continue;
867         if (!i->selected) continue;
868
869         tc = eina_list_nth(cfdata->text_classes, n);
870         tc->size = cfdata->cur_size;
871      }
872 }
873
874 static void
875 _adv_font_cb_change(void *data, Evas_Object *obj __UNUSED__)
876 {
877    E_Config_Dialog_Data *cfdata;
878    CFText_Class *tc;
879    Eina_List *l;
880    int n;
881
882    tc = NULL;
883    if (!(cfdata = data)) return;
884
885    /* Set up the new font name for each selected class */
886    for (n = 0, l = e_widget_ilist_items_get(cfdata->gui.class_list); l; l = l->next, n++)
887      {
888         E_Ilist_Item *i;
889
890         if (!(i = l->data)) continue;
891         if (!i->selected) continue;
892
893         tc = eina_list_nth(cfdata->text_classes, n);
894         if (tc->font) eina_stringshare_del(tc->font);
895         if (cfdata->cur_font)
896           tc->font = eina_stringshare_ref(cfdata->cur_font);
897      }
898
899    /* Load the style list */
900    if (cfdata->cur_font)
901      {
902         E_Font_Properties *efp;
903         Eina_List *next;
904
905         efp = eina_hash_find(cfdata->font_hash, cfdata->cur_font);
906         evas_event_freeze(evas_object_evas_get(cfdata->gui.style_list));
907         edje_freeze();
908         e_widget_ilist_freeze(cfdata->gui.style_list);
909         e_widget_ilist_clear(cfdata->gui.style_list);
910
911         for (next = efp->styles; next; next = next->next)
912           {
913              const char *style;
914
915              style = next->data;
916              e_widget_ilist_append(cfdata->gui.style_list, NULL, style,
917                                    NULL, NULL, style);
918           }
919
920         e_widget_ilist_go(cfdata->gui.style_list);
921         e_widget_ilist_thaw(cfdata->gui.style_list);
922         edje_thaw();
923         evas_event_thaw(evas_object_evas_get(cfdata->gui.style_list));
924      }
925
926    /* select configured style from list */
927    if ((tc) && (tc->style))
928      {
929         for (n = 0; n < e_widget_ilist_count(cfdata->gui.style_list); n++)
930           {
931              const char *f;
932
933              f = e_widget_ilist_nth_label_get(cfdata->gui.style_list, n);
934              if ((!f) || (!tc->style)) continue;
935              if (!strcasecmp(f, tc->style))
936                {
937                   e_widget_ilist_selected_set(cfdata->gui.style_list, n);
938                   break;
939                }
940           }
941      }
942
943    /* load and select size list */
944    if (tc)
945      {
946         cfdata->cur_size = tc->size;
947         _size_list_load(cfdata, cfdata->font_scale_list, tc->size, 1);
948         _size_list_load(cfdata, cfdata->font_px_list, tc->size, 0);
949      }
950
951    _font_preview_update(cfdata);
952 }
953
954 static void
955 _size_list_load(E_Config_Dialog_Data *cfdata, Eina_List *size_list, Evas_Font_Size cur_size, int clear)
956 {
957    Eina_List *next;
958    Evas_Object *ob;
959    Evas *evas;
960    int n;
961
962    ob = cfdata->gui.size_list;
963    evas = evas_object_evas_get(ob);
964
965    evas_event_freeze(evas);
966    edje_freeze();
967    e_widget_ilist_freeze(ob);
968    if (clear) e_widget_ilist_clear(ob);
969
970    for (next = size_list; next; next = next->next)
971      {
972         E_Font_Size_Data *size_data;
973
974         size_data = next->data;
975         e_widget_ilist_append(ob, NULL, size_data->size_str, _size_cb_change,
976                               size_data, NULL);
977      }
978
979    e_widget_ilist_go(ob);
980    e_widget_ilist_thaw(ob);
981    edje_thaw();
982    evas_event_thaw(evas);
983
984    for (n = 0; n < e_widget_ilist_count(ob); n++)
985      {
986        E_Font_Size_Data *size_data;
987
988        if (!(size_data = e_widget_ilist_nth_data_get(ob, n))) continue;
989        if (cur_size == size_data->size)
990           {
991              e_widget_ilist_selected_set(ob, n);
992              break;
993           }
994      }
995 }
996
997 static void
998 _font_list_load(E_Config_Dialog_Data *cfdata, const char *cur_font)
999 {
1000    int n;
1001    Eina_List *next;
1002    Evas_Object *ob;
1003    Evas *evas;
1004    Evas_Coord w;
1005
1006    ob = cfdata->gui.font_list;
1007    evas = evas_object_evas_get(ob);
1008
1009    evas_event_freeze(evas);
1010    edje_freeze();
1011    e_widget_ilist_freeze(ob);
1012
1013    /* Load Hash a single time */
1014    if (!cfdata->font_hash)
1015      {
1016         Eina_List *fonts;
1017
1018         fonts = evas_font_available_list(evas);
1019         cfdata->font_hash = e_font_available_list_parse(fonts);
1020         eina_hash_foreach(cfdata->font_hash, _font_hash_cb, cfdata);
1021         if (cfdata->font_list)
1022           {
1023              cfdata->font_list =
1024                eina_list_sort(cfdata->font_list,
1025                               eina_list_count(cfdata->font_list),
1026                               _sort_fonts);
1027           }
1028         evas_font_available_list_free(evas, fonts);
1029      }
1030
1031    /* Load the list */
1032    if (cfdata->font_list)
1033      {
1034         Eina_List *next;
1035
1036         for (next = cfdata->font_list; next; next = next->next)
1037           {
1038              const char *f;
1039
1040              f = next->data;
1041              e_widget_ilist_append(ob, NULL, f, NULL, NULL, f);
1042           }
1043      }
1044
1045    e_widget_ilist_go(ob);
1046    e_widget_size_min_get(ob, &w, NULL);
1047    e_widget_size_min_set(ob, w, 250);
1048    e_widget_ilist_thaw(ob);
1049    edje_thaw();
1050    evas_event_thaw(evas);
1051
1052    if (!cur_font) return;
1053
1054    /* Select Current Font */
1055    n = 0;
1056    for (next = cfdata->font_list; next; next = next->next)
1057      {
1058         const char *f;
1059
1060         f = next->data;
1061         if (!strcasecmp(f, cur_font))
1062           {
1063              e_widget_ilist_selected_set(ob, n);
1064              break;
1065           }
1066         n++;
1067      }
1068 }
1069
1070 static void
1071 _adv_style_cb_change(void *data, Evas_Object *obj __UNUSED__)
1072 {
1073    E_Config_Dialog_Data *cfdata;
1074    Eina_List *l;
1075    int n;
1076
1077    if (!(cfdata = data)) return;
1078
1079    /* Setup the new style name */
1080    for (n = 0, l = e_widget_ilist_items_get(cfdata->gui.class_list); l; l = l->next, n++)
1081      {
1082         E_Ilist_Item *i;
1083         CFText_Class *tc;
1084
1085         if (!(i = l->data)) continue;
1086         if (!i->selected) continue;
1087
1088         tc = eina_list_nth(cfdata->text_classes, n);
1089         eina_stringshare_del(tc->style);
1090         tc->style = eina_stringshare_ref(cfdata->cur_style);
1091      }
1092
1093    _font_preview_update(cfdata);
1094 }
1095
1096 /* Private Font Fallback Functions */
1097 static void
1098 _adv_enabled_fallback_cb_change(void *data, Evas_Object *obj __UNUSED__)
1099 {
1100    E_Config_Dialog_Data *cfdata;
1101
1102    if (!(cfdata = data)) return;
1103    e_widget_disabled_set(cfdata->gui.fallback_list,
1104                          !cfdata->cur_fallbacks_enabled);
1105 }
1106
1107 static int
1108 _sort_fonts(const void *data1, const void *data2)
1109 {
1110    if (!data1) return 1;
1111    if (!data2) return -1;
1112    return e_util_strcmp(data1, data2);
1113 }
1114
1115 static void
1116 _font_preview_update(E_Config_Dialog_Data *cfdata)
1117 {
1118    /* update preview */
1119    if (cfdata->cur_font)
1120      {
1121         const char *name;
1122
1123         name = e_font_fontconfig_name_get(cfdata->cur_font, cfdata->cur_style);
1124         e_widget_font_preview_font_set(cfdata->gui.preview, name,
1125                                        cfdata->cur_size);
1126         eina_stringshare_del(name);
1127      }
1128 }