Add a task to copy configuration files to user's HOME dir from data dir for multi...
[platform/core/uifw/e17.git] / src / modules / xkbswitch / e_mod_parse.c
1 #include "e.h"
2 #include "e_mod_parse.h"
3
4 Eina_List *layouts = NULL;
5 Eina_List *models = NULL;
6 Eina_List *optgroups = NULL;
7
8 static const char *rules_file = NULL;
9
10 void
11 find_rules(void)
12 {
13    int i = 0;
14    const char *lstfiles[] = {
15       "/usr/share/X11/xkb/rules/xorg.lst",
16       "/usr/share/X11/xkb/rules/xfree86.lst",
17       "/usr/local/share/X11/xkb/rules/xorg.lst",
18       "/usr/local/share/X11/xkb/rules/xfree86.lst",
19       "/usr/X11R6/lib/X11/xkb/rules/xorg.lst",
20       "/usr/X11R6/lib/X11/xkb/rules/xfree86.lst",
21       "/usr/local/X11R6/lib/X11/xkb/rules/xorg.lst",
22       "/usr/local/X11R6/lib/X11/xkb/rules/xfree86.lst",
23       NULL
24    };
25
26    for (; lstfiles[i]; i++)
27      {
28         FILE *f = fopen(lstfiles[i], "r");
29         if (f)
30           {
31              fclose(f);
32              rules_file = lstfiles[i];
33              break;
34           }
35      }
36 }
37
38 int
39 parse_rules(void)
40 {
41    char buf[4096];
42    E_XKB_Model *model = NULL;
43    E_XKB_Layout *layout = NULL;
44    E_XKB_Option *option = NULL;
45    E_XKB_Variant *variant = NULL;
46    E_XKB_Option_Group *group = NULL;
47    FILE *f;
48
49    if (!rules_file) return 0;
50
51    layouts = NULL;
52    models = NULL;
53
54    f = fopen(rules_file, "r");
55    if (!f) return 0;
56
57    /* move on to next line, the first one is useless */
58    if (!fgets(buf, sizeof(buf), f)) goto err;
59
60    /* let X decide on this one, also serves as
61     * "fallback on global" for layout combinations
62     */
63    model = E_NEW(E_XKB_Model, 1);
64    model->name = eina_stringshare_add("default");
65    model->description = eina_stringshare_add("Automatic");
66    models = eina_list_append(models, model);
67
68    /* read models here */
69    for (;;)
70      {
71         if (fgets(buf, sizeof(buf), f))
72           {
73              char *n;
74              char *p;
75              char *tmp;
76
77              n = strchr(buf, '\n');
78              if (n) *n = '\0';
79
80              /* means end of section */
81              if (!buf[0]) break;
82              /* get rid of initial 2 spaces here */
83              p   = buf + 2;
84              tmp = strdup(p);
85
86              model = E_NEW(E_XKB_Model, 1);
87              model->name = eina_stringshare_add(strtok(tmp, " "));
88
89              free(tmp);
90
91              p += strlen(model->name);
92              while (p[0] == ' ') ++p;
93
94              model->description = eina_stringshare_add(p);
95
96              models = eina_list_append(models, model);
97           }
98         else
99           break;
100      }
101
102    /* move on again */
103    if (!fgets(buf, sizeof(buf), f)) goto err;
104
105    /* read layouts here */
106    for (;;)
107      {
108         if (fgets(buf, sizeof(buf), f))
109           {
110              char *n;
111              char *p;
112              char *tmp;
113
114              n = strchr(buf, '\n');
115              if   (n) *n = '\0';
116
117              if (!buf[0]) break;
118
119              p   = buf + 2;
120              tmp = strdup(p);
121
122              layout = E_NEW(E_XKB_Layout, 1);
123              layout->name = eina_stringshare_add(strtok(tmp, " "));
124
125              free(tmp);
126
127              p += strlen(layout->name);
128              while (p[0] == ' ') ++p;
129
130              variant = E_NEW(E_XKB_Variant, 1);
131              variant->name = eina_stringshare_add("basic");
132              variant->description = eina_stringshare_add("Default layout variant");
133
134              layout->description = eina_stringshare_add(p);
135              layout->variants = eina_list_append(layout->variants, variant);
136
137              layouts = eina_list_append(layouts, layout);
138           }
139         else
140           break;
141      }
142
143    /* move on again */
144    if (!fgets(buf, sizeof(buf), f)) goto err;
145
146    /* read variants here */
147    for (;;)
148      {
149         if (fgets(buf, sizeof(buf), f))
150           {
151              char *n;
152              char *p;
153              char *tmp;
154              char   *tok;
155
156              n = strchr(buf, '\n');
157              if   (n) *n = '\0';
158
159              if (!buf[0]) break;
160
161              p   = buf + 2;
162              tmp = strdup(p);
163
164              variant = E_NEW(E_XKB_Variant, 1);
165              variant->name = eina_stringshare_add(strtok(tmp, " "));
166
167              tok = strtok(NULL, " ");
168              *strchr(tok, ':') = '\0';
169
170              layout = eina_list_search_unsorted(layouts, layout_sort_by_name_cb, tok);
171              layout->variants = eina_list_append(layout->variants, variant);
172
173              p += strlen(variant->name);
174              while (p[0] == ' ') ++p;
175              p += strlen(tok);
176              p += 2;
177
178              free(tmp);
179
180              variant->description = eina_stringshare_add(p);
181           }
182         else
183           break;
184      }
185
186    /* move on again */
187    if (!fgets(buf, sizeof(buf), f)) goto err;
188
189    /* read options here */
190    for (;;)
191      {
192         if (fgets(buf, sizeof(buf), f))
193           {
194              char *n;
195              char *p;
196              char *tmp;
197              char *name;
198
199              n = strchr(buf, '\n');
200              if   (n) *n = '\0';
201
202              if (!buf[0]) break;
203
204              p   = buf + 2;
205              tmp  = strdup(p);
206              name = strtok(tmp, " ");
207
208              p += strlen(name);
209              while (p[0] == ' ') ++p;
210
211              /* skip "grp" options for switching kbd layouts */
212              //if (strncmp(name, "grp", 3))
213                {
214                   if (!strchr(name, ':'))
215                     {
216                        group = E_NEW(E_XKB_Option_Group, 1);
217
218                        /* A hack to get it to parse right if
219                         * the group name contains a space
220                         */
221                        if (strstr(p, "  "))
222                          {
223                             p = strstr(p, "  ");
224                             while (p[0] == ' ') ++p;
225                          }
226
227                        group->description = eina_stringshare_add(p);
228
229                        optgroups = eina_list_append(optgroups, group);
230                     }
231                   else if (group)
232                     {
233                        option = E_NEW(E_XKB_Option, 1);
234                        option->name = eina_stringshare_add(name);
235                        option->description = eina_stringshare_add(p);
236                        group->options = eina_list_append(group->options,
237                                                          option);
238                     }
239                }
240
241              free(tmp);
242           }
243         else
244           break;
245      }
246
247 err:
248    fclose(f);
249
250    /* Sort layouts */
251    layouts =
252      eina_list_sort(layouts, eina_list_count(layouts), layout_sort_cb);
253    return 1;
254 }
255
256 void
257 clear_rules(void)
258 {
259    E_XKB_Option_Group *og;
260    E_XKB_Variant      *v;
261    E_XKB_Option       *o;
262    E_XKB_Layout       *la;
263    E_XKB_Model        *m;
264
265    EINA_LIST_FREE(layouts, la)
266      {
267         eina_stringshare_del(la->name);
268         eina_stringshare_del(la->description);
269
270         EINA_LIST_FREE(la->variants, v)
271           {
272              eina_stringshare_del(v->name);
273              eina_stringshare_del(v->description);
274
275              E_FREE(v);
276           }
277
278         E_FREE(la);
279      }
280
281    EINA_LIST_FREE(models, m)
282      {
283         eina_stringshare_del(m->name);
284         eina_stringshare_del(m->description);
285
286         E_FREE(m);
287      }
288
289    EINA_LIST_FREE(optgroups, og)
290      {
291         eina_stringshare_del(og->description);
292
293         EINA_LIST_FREE(og->options, o)
294           {
295              eina_stringshare_del(o->name);
296              eina_stringshare_del(o->description);
297
298              E_FREE(o);
299           }
300
301         E_FREE(og);
302      }
303
304    optgroups = NULL;
305    layouts = NULL;
306    models = NULL;
307 }
308
309 int
310 layout_sort_cb(const void *data1, const void *data2)
311 {
312    const E_XKB_Layout *l1, *l2;
313
314    if (!(l1 = data1)) return 1;
315    if (!l1->name) return 1;
316    if (!(l2 = data2)) return -1;
317    if (!l2->name) return -1;
318
319    return strcmp(l1->name, l2->name);
320 }
321
322 int
323 layout_sort_by_name_cb(const void *data1, const void *data2)
324 {
325    const E_XKB_Layout *l1 = NULL;
326    const char *l2 = NULL;
327
328    if (!(l1 = data1)) return 1;
329    if (!l1->name) return 1;
330    if (!(l2 = data2)) return -1;
331
332    return strcmp(l1->name, l2);
333 }