2 #include "e_mod_parse.h"
4 Eina_List *layouts = NULL;
5 Eina_List *models = NULL;
6 Eina_List *optgroups = NULL;
8 static const char *rules_file = NULL;
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",
26 for (; lstfiles[i]; i++)
28 FILE *f = fopen(lstfiles[i], "r");
32 rules_file = lstfiles[i];
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;
49 if (!rules_file) return 0;
54 f = fopen(rules_file, "r");
57 /* move on to next line, the first one is useless */
58 if (!fgets(buf, sizeof(buf), f)) goto err;
60 /* let X decide on this one, also serves as
61 * "fallback on global" for layout combinations
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);
68 /* read models here */
71 if (fgets(buf, sizeof(buf), f))
77 n = strchr(buf, '\n');
80 /* means end of section */
82 /* get rid of initial 2 spaces here */
86 model = E_NEW(E_XKB_Model, 1);
87 model->name = eina_stringshare_add(strtok(tmp, " "));
91 p += strlen(model->name);
92 while (p[0] == ' ') ++p;
94 model->description = eina_stringshare_add(p);
96 models = eina_list_append(models, model);
103 if (!fgets(buf, sizeof(buf), f)) goto err;
105 /* read layouts here */
108 if (fgets(buf, sizeof(buf), f))
114 n = strchr(buf, '\n');
122 layout = E_NEW(E_XKB_Layout, 1);
123 layout->name = eina_stringshare_add(strtok(tmp, " "));
127 p += strlen(layout->name);
128 while (p[0] == ' ') ++p;
130 variant = E_NEW(E_XKB_Variant, 1);
131 variant->name = eina_stringshare_add("basic");
132 variant->description = eina_stringshare_add("Default layout variant");
134 layout->description = eina_stringshare_add(p);
135 layout->variants = eina_list_append(layout->variants, variant);
137 layouts = eina_list_append(layouts, layout);
144 if (!fgets(buf, sizeof(buf), f)) goto err;
146 /* read variants here */
149 if (fgets(buf, sizeof(buf), f))
156 n = strchr(buf, '\n');
164 variant = E_NEW(E_XKB_Variant, 1);
165 variant->name = eina_stringshare_add(strtok(tmp, " "));
167 tok = strtok(NULL, " ");
168 *strchr(tok, ':') = '\0';
170 layout = eina_list_search_unsorted(layouts, layout_sort_by_name_cb, tok);
171 layout->variants = eina_list_append(layout->variants, variant);
173 p += strlen(variant->name);
174 while (p[0] == ' ') ++p;
180 variant->description = eina_stringshare_add(p);
187 if (!fgets(buf, sizeof(buf), f)) goto err;
189 /* read options here */
192 if (fgets(buf, sizeof(buf), f))
199 n = strchr(buf, '\n');
206 name = strtok(tmp, " ");
209 while (p[0] == ' ') ++p;
211 /* skip "grp" options for switching kbd layouts */
212 //if (strncmp(name, "grp", 3))
214 if (!strchr(name, ':'))
216 group = E_NEW(E_XKB_Option_Group, 1);
218 /* A hack to get it to parse right if
219 * the group name contains a space
224 while (p[0] == ' ') ++p;
227 group->description = eina_stringshare_add(p);
229 optgroups = eina_list_append(optgroups, group);
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,
252 eina_list_sort(layouts, eina_list_count(layouts), layout_sort_cb);
259 E_XKB_Option_Group *og;
265 EINA_LIST_FREE(layouts, la)
267 eina_stringshare_del(la->name);
268 eina_stringshare_del(la->description);
270 EINA_LIST_FREE(la->variants, v)
272 eina_stringshare_del(v->name);
273 eina_stringshare_del(v->description);
281 EINA_LIST_FREE(models, m)
283 eina_stringshare_del(m->name);
284 eina_stringshare_del(m->description);
289 EINA_LIST_FREE(optgroups, og)
291 eina_stringshare_del(og->description);
293 EINA_LIST_FREE(og->options, o)
295 eina_stringshare_del(o->name);
296 eina_stringshare_del(o->description);
310 layout_sort_cb(const void *data1, const void *data2)
312 const E_XKB_Layout *l1, *l2;
314 if (!(l1 = data1)) return 1;
315 if (!l1->name) return 1;
316 if (!(l2 = data2)) return -1;
317 if (!l2->name) return -1;
319 return strcmp(l1->name, l2->name);
323 layout_sort_by_name_cb(const void *data1, const void *data2)
325 const E_XKB_Layout *l1 = NULL;
326 const char *l2 = NULL;
328 if (!(l1 = data1)) return 1;
329 if (!l1->name) return 1;
330 if (!(l2 = data2)) return -1;
332 return strcmp(l1->name, l2);