Fix signatures of wkb_ibus_config_eet public functions
[profile/ivi/weekeyboard.git] / src / wkb-ibus-config-eet.c
1 /*
2  * Copyright © 2013 Intel Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <strings.h>
23
24 #include <Eina.h>
25 #include <Eet.h>
26 #include <Eldbus.h>
27
28 #include "wkb-ibus-config-eet.h"
29 #include "wkb-ibus-config-key.h"
30
31 /*
32  * Base struct for all config types
33  */
34 struct _config_section
35 {
36    const char *id;
37    Eina_List *keys;
38    Eina_List *subsections;
39
40    void (*set_defaults)(struct _config_section *);
41 };
42
43 static void
44 _config_section_free(struct _config_section *base)
45 {
46    struct wkb_config_key *key;
47    struct _config_section *sub;
48
49    eina_stringshare_del(base->id);
50
51    EINA_LIST_FREE(base->keys, key)
52       wkb_config_key_free(key);
53
54    eina_list_free(base->keys);
55
56    EINA_LIST_FREE(base->subsections, sub)
57       _config_section_free(sub);
58
59    eina_list_free(base->subsections);
60
61    free(base);
62 }
63
64 static void
65 _config_section_set_defaults(struct _config_section *base)
66 {
67    Eina_List *node;
68    struct _config_section *sub;
69
70    EINA_LIST_FOREACH(base->subsections, node, sub)
71       _config_section_set_defaults(sub);
72
73    if (!base->set_defaults)
74       return;
75
76    base->set_defaults(base);
77 }
78
79 static struct _config_section *
80 _config_section_find(struct _config_section *base, const char *section)
81 {
82    Eina_List *node;
83    struct _config_section *ret = NULL, *sub;
84
85    if (!section)
86       return NULL;
87
88    printf("Requested section '%s'\n", section);
89    if (!strncasecmp(section, base->id, strlen(base->id)))
90       return base;
91
92    EINA_LIST_FOREACH(base->subsections, node, sub)
93       if ((ret = _config_section_find(sub, section)))
94          break;
95
96    return ret;
97 }
98
99 static struct wkb_config_key *
100 _config_section_find_key(struct _config_section *base, const char *section, const char *name)
101 {
102    struct wkb_config_key *ret = NULL, *key;
103    struct _config_section *sec;
104    const char *key_id;
105    Eina_List *node;
106
107    if (!(sec = _config_section_find(base, section)))
108      {
109         printf("Config section with id '%s' not found\n", section);
110         goto end;
111      }
112
113    printf("Requested key '%s'\n", name);
114    EINA_LIST_FOREACH(base->keys, node, key)
115      {
116         key_id = wkb_config_key_id(key);
117         if (!strncasecmp(name, key_id, strlen(key_id)))
118           {
119              ret = key;
120              break;
121           }
122      }
123
124 end:
125    return ret;
126 }
127
128 #define _config_section_init(_section, _id) \
129    do { \
130         _section->set_defaults = _config_ ## _id ## _set_defaults; \
131         if (parent) \
132           { \
133              _section->id = eina_stringshare_printf("%s/" #_id, parent->id); \
134              parent->subsections = eina_list_append(parent->subsections, _section); \
135           } \
136         else \
137           { \
138              _section->id = eina_stringshare_add("/" #_id); \
139           } \
140    } while (0)
141
142 #define _config_section_add_key(_section, _section_id, _key_type, _field) \
143    do { \
144         struct _config_ ## _section_id *__conf = (struct _config_ ## _section_id *) _section; \
145         struct wkb_config_key *__key = wkb_config_key_ ## _key_type(#_field, &__conf->_field); \
146         _section->keys = eina_list_append(_section->keys, __key); \
147    } while (0)
148
149 #define _config_section_add_key_int(_section, _section_id, _field) \
150     _config_section_add_key(_section, _section_id, int, _field)
151
152 #define _config_section_add_key_bool(_section, _section_id, _field) \
153     _config_section_add_key(_section, _section_id, bool, _field)
154
155 #define _config_section_add_key_string(_section, _section_id, _field) \
156     _config_section_add_key(_section, _section_id, string, _field)
157
158 #define _config_section_add_key_string_list(_section, _section_id, _field) \
159     _config_section_add_key(_section, _section_id, string_list, _field)
160
161 /*
162  * Helpers
163  */
164 static Eina_List *
165 _config_string_list_new(const char **strs)
166 {
167    Eina_List *list = NULL;
168    const char *str;
169
170    for (str = *strs; str != NULL; str = *++strs)
171       list = eina_list_append(list, eina_stringshare_add(str));
172
173    return list;
174 }
175
176 static char *
177 _config_string_sanitize(const char *str)
178 {
179    char *s, *sane = strdup(str);
180
181    for (s = sane; *s; s++)
182      {
183         if (*s == '-')
184            *s = '_';
185         else if (*s >= 'A' && *s <= 'Z')
186            *s += ('a' - 'A');
187      }
188
189    return sane;
190 }
191
192 /*
193  * <schema path="/desktop/ibus/general/hotkey/" id="org.freedesktop.ibus.general.hotkey">
194  *   <key type="as" name="trigger">
195  *     <default>[ 'Control+space', 'Zenkaku_Hankaku', 'Alt+Kanji', 'Alt+grave', 'Hangul', 'Alt+Release+Alt_R' ]</default>
196  *     <summary>Trigger shortcut keys</summary>
197  *     <description>The shortcut keys for turning input method on or off</description>
198  *   </key>
199  *   <key type="as" name="triggers">
200  *     <default>[ '&lt;Super&gt;space' ]</default>
201  *     <summary>Trigger shortcut keys for gtk_accelerator_parse</summary>
202  *     <description>The shortcut keys for turning input method on or off</description>
203  *   </key>
204  *   <key type="as" name="enable-unconditional">
205  *     <default>[]</default>
206  *     <summary>Enable shortcut keys</summary>
207  *     <description>The shortcut keys for turning input method on</description>
208  *   </key>
209  *   <key type="as" name="disable-unconditional">
210  *     <default>[]</default>
211  *     <summary>Disable shortcut keys</summary>
212  *     <description>The shortcut keys for turning input method off</description>
213  *   </key>
214  *   <key type="as" name="next-engine">
215  *     <default>[ 'Alt+Shift_L' ]</default>
216  *     <summary>Next engine shortcut keys</summary>
217  *     <description>The shortcut keys for switching to the next input method in the list</description>
218  *   </key>
219  *   <key type="as" name="next-engine-in-menu">
220  *     <default>[ 'Alt+Shift_L' ]</default>
221  *     <summary>Next engine shortcut keys</summary>
222  *     <description>The shortcut keys for switching to the next input method in the list</description>
223  *   </key>
224  *   <key type="as" name="prev-engine">
225  *     <default>[]</default>
226  *     <summary>Prev engine shortcut keys</summary>
227  *     <description>The shortcut keys for switching to the previous input method</description>
228  *   </key>
229  *   <key type="as" name="previous-engine">
230  *     <default>[]</default>
231  *     <summary>Prev engine shortcut keys</summary>
232  *     <description>The shortcut keys for switching to the previous input method</description>
233  *   </key>
234  * </schema>
235  */
236 struct _config_hotkey
237 {
238    struct _config_section base;
239
240    Eina_List *trigger;
241    Eina_List *triggers;
242    Eina_List *enable_unconditional;
243    Eina_List *disable_unconditional;
244    Eina_List *next_engine;
245    Eina_List *next_engine_in_menu;
246    Eina_List *prev_engine;
247    Eina_List *previous_engine;
248 };
249
250 static Eet_Data_Descriptor *
251 _config_hotkey_edd_new(void)
252 {
253    Eet_Data_Descriptor *edd;
254    Eet_Data_Descriptor_Class eddc;
255
256    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_hotkey);
257    edd = eet_data_descriptor_stream_new(&eddc);
258
259    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "trigger", trigger);
260    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "triggers", triggers);
261    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "enable-unconditional", enable_unconditional);
262    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "disable-unconditional", disable_unconditional);
263    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "next-engine", next_engine);
264    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "next-engine-in-menu", next_engine_in_menu);
265    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "prev-engine", prev_engine);
266    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "previous-engine", previous_engine);
267
268    return edd;
269 }
270
271 static void
272 _config_hotkey_set_defaults(struct _config_section *base)
273 {
274    struct _config_hotkey *hotkey = (struct _config_hotkey *) base;
275
276    const char *trigger[] = { "Control+space", "Zenkaku_Hankaku", "Alt+Kanji", "Alt+grave", "Hangul", "Alt+Release+Alt_R", NULL };
277    const char *triggers[] = { "<Super>space", NULL };
278    const char *enable_unconditional[] = { NULL };
279    const char *disable_unconditional[] = { NULL };
280    const char *next_engine[] = { NULL };
281    const char *next_engine_in_menu[] = { NULL };
282    const char *prev_engine[] = { NULL };
283    const char *previous_engine[] = { NULL };
284
285    hotkey->trigger = _config_string_list_new(trigger);
286    hotkey->triggers = _config_string_list_new(triggers);
287    hotkey->enable_unconditional = _config_string_list_new(enable_unconditional);
288    hotkey->disable_unconditional = _config_string_list_new(disable_unconditional);
289    hotkey->next_engine = _config_string_list_new(next_engine);
290    hotkey->next_engine_in_menu = _config_string_list_new(next_engine_in_menu);
291    hotkey->prev_engine = _config_string_list_new(prev_engine);
292    hotkey->previous_engine = _config_string_list_new(previous_engine);
293 }
294
295 static void
296 _config_hotkey_section_init(struct _config_section *base, struct _config_section *parent)
297 {
298    _config_section_init(base, hotkey);
299    _config_section_add_key_string_list(base, hotkey, trigger);
300    _config_section_add_key_string_list(base, hotkey, triggers);
301    _config_section_add_key_string_list(base, hotkey, enable_unconditional);
302    _config_section_add_key_string_list(base, hotkey, disable_unconditional);
303    _config_section_add_key_string_list(base, hotkey, next_engine);
304    _config_section_add_key_string_list(base, hotkey, next_engine_in_menu);
305    _config_section_add_key_string_list(base, hotkey, prev_engine);
306    _config_section_add_key_string_list(base, hotkey, previous_engine);
307 }
308
309 static struct _config_section *
310 _config_hotkey_new(struct _config_section *parent)
311 {
312    struct _config_hotkey *conf = calloc(1, sizeof(*conf));
313    struct _config_section *hotkey = (struct _config_section *) conf;
314
315    _config_hotkey_section_init(hotkey, parent);
316    return hotkey;
317 }
318
319 /*
320  * <schema path="/desktop/ibus/general/" id="org.freedesktop.ibus.general">
321  *    <key type="as" name="preload-engines">
322  *      <default>[]</default>
323  *      <summary>Preload engines</summary>
324  *      <description>Preload engines during ibus starts up</description>
325  *    </key>
326  *    <key type="as" name="engines-order">
327  *      <default>[]</default>
328  *      <summary>Engines order</summary>
329  *      <description>Saved engines order in input method list</description>
330  *    </key>
331  *    <key type="i" name="switcher-delay-time">
332  *      <default>400</default>
333  *      <summary>Popup delay milliseconds for IME switcher window</summary>
334  *      <description>Set popup delay milliseconds to show IME switcher window. The default is 400. 0 = Show the window immediately. 0 &lt; Delay milliseconds. 0 &gt; Do not show the
335  *    </key>
336  *    <key type="s" name="version">
337  *      <default>''</default>
338  *      <summary>Saved version number</summary>
339  *      <description>The saved version number will be used to check the difference between the version of the previous installed ibus and one of the current ibus.</description>
340  *    </key>
341  *    <key type="b" name="use-system-keyboard-layout">
342  *      <default>false</default>
343  *      <summary>Use system keyboard layout</summary>
344  *      <description>Use system keyboard (XKB) layout</description>
345  *    </key>
346  *    <key type="b" name="embed-preedit-text">
347  *      <default>true</default>
348  *      <summary>Embed Preedit Text</summary>
349  *      <description>Embed Preedit Text in Application Window</description>
350  *    </key>
351  *    <key type="b" name="use-global-engine">
352  *      <default>false</default>
353  *      <summary>Use global input method</summary>
354  *     <description>Share the same input method among all applications</description>
355  *    </key>
356  *    <key type="b" name="enable-by-default">
357  *      <default>false</default>
358  *      <summary>Enable input method by default</summary>
359  *      <description>Enable input method by default when the application gets input focus</description>
360  *    </key>
361  *    <key type="as" name="dconf-preserve-name-prefixes">
362  *      <default>[ '/desktop/ibus/engine/pinyin', '/desktop/ibus/engine/bopomofo', '/desktop/ibus/engine/hangul' ]</default>
363  *      <summary>DConf preserve name prefixes</summary>
364  *      <description>Prefixes of DConf keys to stop name conversion</description>
365  *    </key>
366  *    <child schema="org.freedesktop.ibus.general.hotkey" name="hotkey"/>
367  * </schema>
368  */
369 struct _config_general
370 {
371    struct _config_section base;
372
373    struct _config_section *hotkey;
374
375    Eina_List *preload_engines;
376    Eina_List *engines_order;
377    Eina_List *dconf_preserve_name_prefixes;
378
379    const char *version;
380
381    int switcher_delay_time;
382
383    Eina_Bool use_system_keyboard_layout;
384    Eina_Bool embed_preedit_text;
385    Eina_Bool use_global_engine;
386    Eina_Bool enable_by_default;
387 };
388
389 static Eet_Data_Descriptor *
390 _config_general_edd_new(Eet_Data_Descriptor *hotkey_edd)
391 {
392    Eet_Data_Descriptor *edd;
393    Eet_Data_Descriptor_Class eddc;
394
395    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_general);
396    edd = eet_data_descriptor_stream_new(&eddc);
397
398    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_general, "preload-engines", preload_engines);
399    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_general, "engines-order", engines_order);
400    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "switcher-delay-time", switcher_delay_time, EET_T_INT);
401    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "version", version, EET_T_STRING);
402    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "use-system-keyboard-layout", use_system_keyboard_layout, EET_T_UCHAR);
403    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "embed-preedit-text", embed_preedit_text, EET_T_UCHAR);
404    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "use-global-engine", use_global_engine, EET_T_UCHAR);
405    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "enable-by-default", enable_by_default, EET_T_UCHAR);
406    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_general, "dconf-preserve-name-prefixes", dconf_preserve_name_prefixes);
407    EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_general, "hotkey", hotkey, hotkey_edd);
408
409    return edd;
410 }
411
412 static void
413 _config_general_set_defaults(struct _config_section *base)
414 {
415    struct _config_general *general = (struct _config_general *) base;
416
417    const char *preload_engines[] = { NULL };
418    const char *engines_order[] = { NULL };
419    const char *dconf_preserve_name_prefixes[] = { "/desktop/ibus/engine/pinyin", "/desktop/ibus/engine/bopomofo", "/desktop/ibus/engine/hangul", NULL };
420
421    general->preload_engines = _config_string_list_new(preload_engines);
422    general->engines_order = _config_string_list_new(engines_order);
423    general->switcher_delay_time = 400;
424    general->version = eina_stringshare_add("");
425    general->use_system_keyboard_layout = EINA_FALSE;
426    general->embed_preedit_text = EINA_TRUE;
427    general->use_global_engine = EINA_FALSE;
428    general->enable_by_default = EINA_FALSE;
429    general->dconf_preserve_name_prefixes = _config_string_list_new(dconf_preserve_name_prefixes);
430 }
431
432 static void
433 _config_general_section_init(struct _config_section *base, struct _config_section *parent)
434 {
435    struct _config_general *conf = (struct _config_general *) base;
436
437    _config_section_init(base, general);
438    _config_section_add_key_string_list(base, general, preload_engines);
439    _config_section_add_key_string_list(base, general, engines_order);
440    _config_section_add_key_int(base, general, switcher_delay_time);
441    _config_section_add_key_string(base, general, version);
442    _config_section_add_key_bool(base, general, use_system_keyboard_layout);
443    _config_section_add_key_bool(base, general, embed_preedit_text);
444    _config_section_add_key_bool(base, general, use_global_engine);
445    _config_section_add_key_bool(base, general, enable_by_default);
446    _config_section_add_key_string_list(base, general, dconf_preserve_name_prefixes);
447
448    if (conf->hotkey)
449       _config_hotkey_section_init(conf->hotkey, base);
450 }
451
452 static struct _config_section *
453 _config_general_new(struct _config_section *parent)
454 {
455    struct _config_general *conf = calloc(1, sizeof(*conf));
456    struct _config_section *general = (struct _config_section *) conf;
457
458    _config_general_section_init(general, parent);
459    conf->hotkey = _config_hotkey_new(general);
460    return general;
461 }
462
463 /*
464  * <schema path="/desktop/ibus/panel/" id="org.freedesktop.ibus.panel">
465  *    <key type="i" name="show">
466  *      <default>0</default>
467  *      <summary>Auto hide</summary>
468  *      <description>The behavior of language panel. 0 = Embedded in menu, 1 = Auto hide, 2 = Always show</description>
469  *    </key>
470  *    <key type="i" name="x">
471  *      <default>-1</default>
472  *      <summary>Language panel position</summary>
473  *    </key>
474  *    <key type="i" name="y">
475  *      <default>-1</default>
476  *      <summary>Language panel position</summary>
477  *    </key>
478  *    <key type="i" name="lookup-table-orientation">
479  *      <default>1</default>
480  *      <summary>Orientation of lookup table</summary>
481  *      <description>Orientation of lookup table. 0 = Horizontal, 1 = Vertical</description>
482  *    </key>
483  *    <key type="b" name="show-icon-on-systray">
484  *      <default>true</default>
485  *      <summary>Show icon on system tray</summary>
486  *      <description>Show icon on system tray</description>
487  *    </key>
488  *    <key type="b" name="show-im-name">
489  *      <default>false</default>
490  *      <summary>Show input method name</summary>
491  *      <description>Show input method name on language bar</description>
492  *    </key>
493  *    <key type="b" name="use-custom-font">
494  *      <default>false</default>
495  *      <summary>Use custom font</summary>
496  *      <description>Use custom font name for language panel</description>
497  *    </key>
498  *    <key type="s" name="custom-font">
499  *      <default>'Sans 10'</default>
500  *      <summary>Custom font</summary>
501  *      <description>Custom font name for language panel</description>
502  *    </key>
503  * </schema>
504  */
505 struct _config_panel
506 {
507    struct _config_section base;
508
509    const char *custom_font;
510    int show;
511    int x;
512    int y;
513    int lookup_table_orientation;
514    Eina_Bool show_icon_in_systray;
515    Eina_Bool show_im_name;
516    Eina_Bool use_custom_font;
517 };
518
519 static Eet_Data_Descriptor *
520 _config_panel_edd_new(void)
521 {
522    Eet_Data_Descriptor *edd;
523    Eet_Data_Descriptor_Class eddc;
524
525    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_panel);
526    edd = eet_data_descriptor_stream_new(&eddc);
527
528    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "show", show, EET_T_INT);
529    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "x", x, EET_T_INT);
530    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "y", y, EET_T_INT);
531    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "lookup-table-orientation", lookup_table_orientation, EET_T_INT);
532    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "show-icon-in-systray", show_icon_in_systray, EET_T_UCHAR);
533    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "show-im-name", show_im_name, EET_T_UCHAR);
534    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "use-custom-font", use_custom_font, EET_T_UCHAR);
535    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "custom-font", custom_font, EET_T_STRING);
536
537    return edd;
538 }
539
540 static void
541 _config_panel_set_defaults(struct _config_section *base)
542 {
543    struct _config_panel *panel = (struct _config_panel *) base;
544
545    panel->show = 0;
546    panel->x = -1;
547    panel->y = -1;
548    panel->lookup_table_orientation = 1;
549    panel->show_icon_in_systray = EINA_TRUE;
550    panel->show_im_name = EINA_FALSE;
551    panel->use_custom_font = EINA_FALSE;
552    panel->custom_font = eina_stringshare_add("Sans 10");
553 }
554
555 static void
556 _config_panel_section_init(struct _config_section *base, struct _config_section *parent)
557 {
558    _config_section_init(base, panel);
559    _config_section_add_key_int(base, panel, show);
560    _config_section_add_key_int(base, panel, x);
561    _config_section_add_key_int(base, panel, y);
562    _config_section_add_key_int(base, panel, lookup_table_orientation);
563    _config_section_add_key_bool(base, panel, show_icon_in_systray);
564    _config_section_add_key_bool(base, panel, show_im_name);
565    _config_section_add_key_bool(base, panel, use_custom_font);
566    _config_section_add_key_string(base, panel, custom_font);
567 }
568
569 static struct _config_section *
570 _config_panel_new(struct _config_section *parent)
571 {
572    struct _config_panel *conf = calloc(1, sizeof(*conf));
573    struct _config_section *panel = (struct _config_section *) conf;
574
575    _config_panel_section_init(panel, parent);
576    return panel;
577 }
578
579 /*
580  * NO SCHEMA AVAILABLE. BASED ON THE SOURCE CODE
581  */
582 struct _config_hangul
583 {
584    struct _config_section base;
585
586    const char *hangul_keyboard;
587    Eina_List *hanja_keys;
588    Eina_Bool word_commit;
589    Eina_Bool auto_reorder;
590 };
591
592 static Eet_Data_Descriptor *
593 _config_hangul_edd_new(void)
594 {
595    Eet_Data_Descriptor *edd;
596    Eet_Data_Descriptor_Class eddc;
597
598    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_hangul);
599    edd = eet_data_descriptor_stream_new(&eddc);
600
601    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_hangul, "HangulKeyboard", hangul_keyboard, EET_T_STRING);
602    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hangul, "HanjaKeys", hanja_keys);
603    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_hangul, "WordCommit", word_commit, EET_T_UCHAR);
604    EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_hangul, "AutoReorder", auto_reorder, EET_T_UCHAR);
605
606    return edd;
607 }
608
609 static void
610 _config_hangul_set_defaults(struct _config_section *base)
611 {
612    struct _config_hangul *hangul = (struct _config_hangul *) base;
613    const char *hanja_keys[] = { "Hangul_Hanja", "F9", NULL };
614
615    hangul->hangul_keyboard = eina_stringshare_add("2");
616    hangul->hanja_keys = _config_string_list_new(hanja_keys);
617    hangul->word_commit = EINA_FALSE;
618    hangul->auto_reorder = EINA_TRUE;
619 }
620
621 static void
622 _config_hangul_section_init(struct _config_section *base, struct _config_section *parent)
623 {
624    _config_section_init(base, hangul);
625    _config_section_add_key_string(base, hangul, hangul_keyboard);
626    _config_section_add_key_string_list(base, hangul, hanja_keys);
627    _config_section_add_key_bool(base, hangul, word_commit);
628    _config_section_add_key_bool(base, hangul, auto_reorder);
629 }
630
631 static struct _config_section *
632 _config_hangul_new(struct _config_section *parent)
633 {
634    struct _config_hangul *conf = calloc(1, sizeof(*conf));
635    struct _config_section *hangul = (struct _config_section *) conf;
636
637    _config_hangul_section_init(hangul, parent);
638    return hangul;
639 }
640
641 /*
642  * NO SCHEMA AVAILABLE. BASED ON THE SOURCE CODE
643  */
644 struct _config_engine
645 {
646    struct _config_section base;
647
648    struct _config_section *hangul;
649 };
650
651 static Eet_Data_Descriptor *
652 _config_engine_edd_new(Eet_Data_Descriptor *hangul_edd)
653 {
654    Eet_Data_Descriptor *edd;
655    Eet_Data_Descriptor_Class eddc;
656
657    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_engine);
658    edd = eet_data_descriptor_stream_new(&eddc);
659
660    EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_engine, "Hangul", hangul, hangul_edd);
661
662    return edd;
663 }
664
665 static void
666 _config_engine_set_defaults(struct _config_section *base)
667 {
668 }
669
670 static void
671 _config_engine_section_init(struct _config_section *base, struct _config_section *parent)
672 {
673    struct _config_engine *conf= (struct _config_engine *) base;
674
675    _config_section_init(base, engine);
676
677    if (conf->hangul)
678       _config_hangul_section_init(conf->hangul, base);
679 }
680
681 static struct _config_section *
682 _config_engine_new(struct _config_section *parent)
683 {
684    struct _config_engine *conf = calloc(1, sizeof(*conf));
685    struct _config_section *engine = (struct _config_section *) conf;
686
687    _config_engine_section_init(engine, parent);
688    conf->hangul = _config_hangul_new(engine);
689    return engine;
690 }
691
692 /*
693  * <schema path="/desktop/ibus/" id="org.freedesktop.ibus">
694  *    <child schema="org.freedesktop.ibus.general" name="general"/>
695  *    <child schema="org.freedesktop.ibus.panel" name="panel"/>
696  * </schema>
697  */
698 struct _config_ibus
699 {
700    struct _config_section base;
701
702    struct _config_section *general;
703    struct _config_section *panel;
704    struct _config_section *engine;
705 };
706
707 static Eet_Data_Descriptor *
708 _config_ibus_edd_new(Eet_Data_Descriptor *general_edd, Eet_Data_Descriptor *panel_edd, Eet_Data_Descriptor *engine_edd)
709 {
710    Eet_Data_Descriptor *edd;
711    Eet_Data_Descriptor_Class eddc;
712
713    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_ibus);
714    edd = eet_data_descriptor_stream_new(&eddc);
715
716    EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_ibus, "general", general, general_edd);
717    EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_ibus, "panel", panel, panel_edd);
718    EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_ibus, "engine", engine, engine_edd);
719
720    return edd;
721 }
722
723 static void
724 _config_ibus_set_defaults(struct _config_section *base)
725 {
726 }
727
728 static void
729 _config_ibus_section_init(struct _config_section *base, struct _config_section *parent)
730 {
731    struct _config_ibus *conf= (struct _config_ibus *) base;
732
733    _config_section_init(base, ibus);
734
735    if (conf->general)
736       _config_general_section_init(conf->general, base);
737
738    if (conf->panel)
739       _config_panel_section_init(conf->panel, base);
740
741    if (conf->engine)
742       _config_engine_section_init(conf->engine, base);
743 }
744
745 static struct _config_section *
746 _config_ibus_new(void)
747 {
748    struct _config_ibus *conf = calloc(1, sizeof(*conf));
749    struct _config_section *ibus = (struct _config_section *) conf;
750
751    _config_ibus_section_init(ibus, NULL);
752    conf->general = _config_general_new(ibus);
753    conf->panel = _config_panel_new(ibus);
754    conf->engine = _config_engine_new(ibus);
755    return ibus;
756 }
757
758 /*
759  * MAIN
760  */
761 struct wkb_ibus_config_eet
762 {
763    const char *path;
764    struct _config_section *ibus_config;
765
766    Eet_Data_Descriptor *hotkey_edd;
767    Eet_Data_Descriptor *general_edd;
768    Eet_Data_Descriptor *panel_edd;
769    Eet_Data_Descriptor *hangul_edd;
770    Eet_Data_Descriptor *engine_edd;
771    Eet_Data_Descriptor *ibus_edd;
772 };
773
774 Eina_Bool
775 wkb_ibus_config_eet_set_value(struct wkb_ibus_config_eet *config_eet, const char *section, const char *name, Eldbus_Message_Iter *value)
776 {
777    Eina_Bool ret = EINA_FALSE;
778    struct wkb_config_key *key;
779
780    if (!(key = _config_section_find_key(config_eet->ibus_config, section, name)))
781      {
782         printf("Config key with id '%s' not found\n", name);
783         goto end;
784      }
785
786    ret = wkb_config_key_set(key, value);
787
788 end:
789    return ret;
790 }
791
792 Eina_Bool
793 wkb_ibus_config_eet_get_value(struct wkb_ibus_config_eet *config_eet, const char *section, const char *name, Eldbus_Message_Iter *reply)
794 {
795    Eina_Bool ret = EINA_FALSE;
796    struct wkb_config_key *key;
797
798    if (!(key = _config_section_find_key(config_eet->ibus_config, section, name)))
799      {
800         printf("Config key with id '%s' not found\n", name);
801         goto end;
802      }
803
804    ret = wkb_config_key_get(key, reply);
805
806 end:
807    return ret;
808 }
809
810 Eina_Bool
811 wkb_ibus_config_eet_get_values(struct wkb_ibus_config_eet *config_eet, const char *section, Eldbus_Message_Iter *reply)
812 {
813    Eina_Bool ret = EINA_FALSE;
814    struct _config_section *sec;
815    struct wkb_config_key *key;
816
817    if (!(sec = _config_section_find(config_eet->ibus_config, section)))
818      {
819         printf("Config section with id '%s' not found\n", section);
820         goto end;
821      }
822
823 end:
824    return ret;
825 }
826
827 void
828 wkb_ibus_config_eet_set_defaults(struct wkb_ibus_config_eet *config_eet)
829 {
830    if (config_eet->ibus_config)
831       _config_section_free(config_eet->ibus_config);
832
833    config_eet->ibus_config = _config_ibus_new();
834    _config_section_set_defaults(config_eet->ibus_config);
835 }
836
837 static struct wkb_ibus_config_eet *
838 _config_eet_init(const char *path)
839 {
840    struct wkb_ibus_config_eet *eet = calloc(1, sizeof(*eet));
841    eet->path = eina_stringshare_add(path);
842
843    eet->hotkey_edd = _config_hotkey_edd_new();
844    eet->general_edd = _config_general_edd_new(eet->hotkey_edd);
845    eet->panel_edd = _config_panel_edd_new();
846    eet->hangul_edd = _config_hangul_edd_new();
847    eet->engine_edd = _config_engine_edd_new(eet->hangul_edd);
848    eet->ibus_edd = _config_ibus_edd_new(eet->general_edd, eet->panel_edd, eet->engine_edd);
849
850    return eet;
851 }
852
853 static Eina_Bool
854 _config_eet_exists(const char *path)
855 {
856    struct stat buf;
857    return stat(path, &buf) == 0;
858 }
859
860 struct wkb_ibus_config_eet *
861 wkb_ibus_config_eet_new(const char *path)
862 {
863    struct wkb_ibus_config_eet *eet = _config_eet_init(path);
864    Eet_File *ef = NULL;
865    Eet_File_Mode mode = EET_FILE_MODE_READ_WRITE;
866
867    if (_config_eet_exists(path))
868       mode = EET_FILE_MODE_READ;
869
870    if (!(ef = eet_open(path, mode)))
871      {
872         printf("Error opening eet file '%s' for %s\n", path, mode == EET_FILE_MODE_READ ? "read" : "write");
873         wkb_ibus_config_eet_free(eet);
874         return NULL;
875      }
876
877    if (mode == EET_FILE_MODE_READ)
878      {
879         eet->ibus_config = eet_data_read(ef, eet->ibus_edd, "ibus");
880         _config_ibus_section_init(eet->ibus_config, NULL);
881         goto end;
882      }
883
884    wkb_ibus_config_eet_set_defaults(eet);
885    if (!eet_data_write(ef, eet->ibus_edd, "ibus", eet->ibus_config, EINA_TRUE))
886      {
887         printf("Error creating eet file '%s'\n", path);
888         wkb_ibus_config_eet_free(eet);
889         eet = NULL;
890      }
891
892 end:
893    eet_close(ef);
894    return eet;
895 }
896
897 void
898 wkb_ibus_config_eet_free(struct wkb_ibus_config_eet *config_eet)
899 {
900    _config_section_free(config_eet->ibus_config);
901    eina_stringshare_del(config_eet->path);
902
903    eet_data_descriptor_free(config_eet->hotkey_edd);
904    eet_data_descriptor_free(config_eet->general_edd);
905    eet_data_descriptor_free(config_eet->panel_edd);
906    eet_data_descriptor_free(config_eet->hangul_edd);
907    eet_data_descriptor_free(config_eet->engine_edd);
908    eet_data_descriptor_free(config_eet->ibus_edd);
909
910    free(config_eet);
911 }