elm genlist: Fixed genlist crash issue when huge amount of items are expanded/contrac...
[framework/uifw/elementary.git] / src / lib / elm_font.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 Elm_Font_Properties *
13 _elm_font_properties_get(Eina_Hash **font_hash,
14                          const char *font)
15 {
16    Elm_Font_Properties *efp = NULL;
17    char *s1;
18
19    s1 = strchr(font, ':');
20    if (s1)
21      {
22         char *s2, *name, *style;
23         int len;
24
25         len = s1 - font;
26         name = calloc(sizeof(char), len + 1);
27         if (!name) return NULL;
28         strncpy(name, font, len);
29
30         /* get subname (should be english)  */
31         s2 = strchr(name, ',');
32         if (s2)
33           {
34              len = s2 - name;
35              name = realloc(name, sizeof(char) * len + 1);
36              if (name)
37                {
38                   memset(name, 0, sizeof(char) * len + 1);
39                   strncpy(name, font, len);
40                }
41           }
42
43         if (!strncmp(s1, ELM_FONT_TOKEN_STYLE, strlen(ELM_FONT_TOKEN_STYLE)))
44           {
45              style = s1 + strlen(ELM_FONT_TOKEN_STYLE);
46
47              if (font_hash) efp = eina_hash_find(*font_hash, name);
48              if (!efp)
49                {
50                   efp = calloc(1, sizeof(Elm_Font_Properties));
51                   if (efp)
52                     {
53                        efp->name = eina_stringshare_add(name);
54                        if ((font_hash && !*font_hash))
55                          {
56                             *font_hash = eina_hash_string_superfast_new(NULL);
57                             eina_hash_add(*font_hash, name, efp);
58                          }
59                     }
60                }
61              s2 = strchr(style, ',');
62              if (s2)
63                {
64                   char *style_old;
65
66                   len = s2 - style;
67                   style_old = style;
68                   style = calloc(sizeof(char), len + 1);
69                   if (style)
70                     {
71                        strncpy(style, style_old, len);
72                        efp->styles = eina_list_append(efp->styles,
73                                                    eina_stringshare_add(style));
74                        free(style);
75                     }
76                }
77              else
78                efp->styles = eina_list_append(efp->styles,
79                                               eina_stringshare_add(style));
80           }
81         free(name);
82      }
83    else
84      {
85         if (font_hash) efp = eina_hash_find(*font_hash, font);
86         if (!efp)
87           {
88              efp = calloc(1, sizeof(Elm_Font_Properties));
89              if (efp)
90                {
91                   efp->name = eina_stringshare_add(font);
92                   if (font_hash && !*font_hash)
93                     {
94                        *font_hash = eina_hash_string_superfast_new(NULL);
95                        eina_hash_add(*font_hash, font, efp);
96                     }
97                }
98           }
99      }
100    return efp;
101 }
102
103 Eina_Hash *
104 _elm_font_available_hash_add(Eina_Hash  *font_hash,
105                              const char *full_name)
106 {
107    _elm_font_properties_get(&font_hash, full_name);
108    return font_hash;
109 }
110
111 static void
112 _elm_font_properties_free(Elm_Font_Properties *efp)
113 {
114    const char *str;
115
116    EINA_LIST_FREE(efp->styles, str)
117      if (str) eina_stringshare_del(str);
118
119    if (efp->name) eina_stringshare_del(efp->name);
120    free(efp);
121 }
122
123 static Eina_Bool
124 _font_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
125 {
126    Elm_Font_Properties *efp;
127
128    efp = data;
129    _elm_font_properties_free(efp);
130    return EINA_TRUE;
131 }
132
133 void
134 _elm_font_available_hash_del(Eina_Hash *hash)
135 {
136    if (!hash) return;
137
138    eina_hash_foreach(hash, _font_hash_free_cb, NULL);
139    eina_hash_free(hash);
140 }
141
142 EAPI Elm_Font_Properties *
143 elm_font_properties_get(const char *font)
144 {
145    EINA_SAFETY_ON_NULL_RETURN_VAL(font, NULL);
146    return _elm_font_properties_get(NULL, font);
147 }
148
149 EAPI void
150 elm_font_properties_free(Elm_Font_Properties *efp)
151 {
152    const char *str;
153
154    EINA_SAFETY_ON_NULL_RETURN(efp);
155    EINA_LIST_FREE(efp->styles, str)
156      if (str) eina_stringshare_del(str);
157    if (efp->name) eina_stringshare_del(efp->name);
158    free(efp);
159 }
160
161 EAPI char *
162 elm_font_fontconfig_name_get(const char *name,
163                              const char *style)
164 {
165    char buf[256];
166
167    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
168    if (!style || style[0] == 0) return (char *) eina_stringshare_add(name);
169    snprintf(buf, 256, "%s" ELM_FONT_TOKEN_STYLE "%s", name, style);
170    return (char *) eina_stringshare_add(buf);
171 }
172
173 EAPI void
174 elm_font_fontconfig_name_free(char *name)
175 {
176    eina_stringshare_del(name);
177 }
178
179 EAPI Eina_Hash *
180 elm_font_available_hash_add(Eina_List *list)
181 {
182    Eina_Hash *font_hash;
183    Eina_List *l;
184    void *key;
185
186    font_hash = NULL;
187
188    /* populate with default font families */
189    //FIXME: Need to check whether fonts are being added multiple times.
190    font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Regular");
191    font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Bold");
192    font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Oblique");
193    font_hash = _elm_font_available_hash_add(font_hash,
194                                             "Sans:style=Bold Oblique");
195
196    font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Regular");
197    font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Bold");
198    font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Oblique");
199    font_hash = _elm_font_available_hash_add(font_hash,
200                                             "Serif:style=Bold Oblique");
201
202    font_hash = _elm_font_available_hash_add(font_hash,
203                                             "Monospace:style=Regular");
204    font_hash = _elm_font_available_hash_add(font_hash,
205                                             "Monospace:style=Bold");
206    font_hash = _elm_font_available_hash_add(font_hash,
207                                             "Monospace:style=Oblique");
208    font_hash = _elm_font_available_hash_add(font_hash,
209                                             "Monospace:style=Bold Oblique");
210
211    EINA_LIST_FOREACH(list, l, key)
212      if (key) _elm_font_available_hash_add(font_hash, key);
213
214    return font_hash;
215 }
216
217 EAPI void
218 elm_font_available_hash_del(Eina_Hash *hash)
219 {
220    _elm_font_available_hash_del(hash);
221 }