Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / wrapper / xim / settings.c
1 /*
2  * Copyright (c) 2010 Mike Qin <mikeandmore@gmail.com>
3  *
4  * The contents of this file are subject to the terms of either the GNU Lesser
5  * General Public License Version 2.1 only ("LGPL") or the Common Development and
6  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
7  * file except in compliance with the License. You can obtain a copy of the CDDL at
8  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
9  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
10  * specific language governing permissions and limitations under the License. When
11  * distributing the software, include this License Header Notice in each file and
12  * include the full text of the License in the License file as well as the
13  * following notice:
14  *
15  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
16  * (CDDL)
17  * For Covered Software in this distribution, this License shall be governed by the
18  * laws of the State of California (excluding conflict-of-law provisions).
19  * Any litigation relating to this License shall be subject to the jurisdiction of
20  * the Federal Courts of the Northern District of California and the state courts
21  * of the State of California, with venue lying in Santa Clara County, California.
22  *
23  * Contributor(s):
24  *
25  * If you wish your version of this file to be governed by only the CDDL or only
26  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
27  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
28  * license." If you don't indicate a single choice of license, a recipient has the
29  * option to distribute your version of this file under either the CDDL or the LGPL
30  * Version 2.1, or to extend the choice of license to its licensees as provided
31  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
32  * Version 2 license, then the option applies only if the new code is made subject
33  * to such option by the copyright holder.
34  */
35
36 #include <X11/X.h>
37 #include <X11/Xproto.h>
38 #include <X11/Xlib.h>
39 #include <X11/keysym.h>
40 #include <X11/Xutil.h>
41 #include <sys/stat.h>
42
43 #include "common.h"
44 #include "xmisc.h"
45 #include "settings.h"
46
47 typedef void (*serialize_func_t)(char* str, void* data);
48
49 static const char* setting_names[] = {
50     "trigger_key",
51     "eng_key",
52     "icbar_pos",
53     "preedit_opacity",
54     "preedit_color",
55     "preedit_font",
56     "preedit_font_color",
57     "shuangpin",
58     "shuangpin_scheme",
59     "candidates_size",
60     "page_minus_plus",
61     "page_comma_period",
62     "page_paren",
63     "fuzzy_inner_segmentation",
64     "fuzzy_segmentation",
65     "cancel_on_backspace",
66     "smart_punct",
67     "skin_name",
68     "hide_icbar",
69     NULL
70 };
71
72 static void*  setting_data[MAX_KEY];
73 static size_t setting_size[MAX_KEY];
74
75 static serialize_func_t setting_enc[MAX_KEY];
76 static serialize_func_t setting_dec[MAX_KEY];
77
78 static void
79 __varchar_enc(char* str, void* data)
80 {
81     strncpy(str, data, 128);
82 }
83
84 static void
85 __varchar_dec(char* str, void* data)
86 {
87     strncpy(data, str, 128);
88 }
89
90 static void
91 __double_enc(char* str, void* data)
92 {
93     double* ptr = data;
94     snprintf(str, 256, "%.2lf", *ptr);
95 }
96
97 static void
98 __double_dec(char* str, void* data)
99 {
100     double* ptr = data;
101     sscanf(str, "%lf", ptr);
102 }
103
104 static void
105 __int_enc(char* str, void* data)
106 {
107     int* ptr = data;
108     snprintf(str, 256, "%d", *ptr);
109 }
110
111 static void
112 __int_dec(char* str, void* data)
113 {
114     int* ptr = data;
115     sscanf(str, "%d", ptr);
116 }
117
118 static void
119 __position_enc(char* str, void* data)
120 {
121     position_t* pos = data;
122     snprintf(str, 256, "%d,%d", pos->x, pos->y);
123 }
124
125 static void
126 __position_dec(char* str, void* data)
127 {
128     position_t* pos = data;
129     sscanf(str, "%d,%d", &pos->x, &pos->y);
130 }
131
132 static const int kmap_keysym[] =
133 {
134     XK_Shift_L, XK_Shift_R, XK_Control_L,
135     XK_Control_R, XK_Meta_L, XK_Meta_R,
136     XK_space,
137 };
138
139 static const char* kmap_text[] =
140 {
141     "Shift_L", "Shift_R", "Control_L",
142     "Control_R", "Meta_L", "Meta_R", "space",
143 };
144
145 const int nkmap = 7;
146
147 static void
148 __hotkey_enc(char* str, void* data)
149 {
150     hotkey_t* hk = data;
151     if (hk->modifiers & ControlMask) {
152         strncat(str, "Control+", 255);
153     }
154     if (hk->modifiers & ShiftMask) {
155         strncat(str, "Shift+", 255);
156     }
157
158     char keyname[256];
159     memset(keyname, 0, sizeof(char) * 256);
160     int i;
161     for (i = 0; i < nkmap + 1; i++) {
162         if (i == nkmap) {
163             keyname[0] = hk->keysym - 0x0020;
164             break;
165         } else if (hk->keysym == kmap_keysym[i]) {
166             strncpy(keyname, kmap_text[i], 255);
167             break;
168         }
169     }
170
171     strncat(str, keyname, 255);
172 }
173
174 static void
175 __hotkey_dec(char* str, void* data)
176 {
177     hotkey_t* hk = data;
178     hk->keysym = 0;
179     hk->modifiers = 0;
180
181     char* last_ptr = str;
182     char text[256];
183     while (1) {
184         char* ptr = strchr(last_ptr, '+');
185         memset(text, 0, sizeof(char) * 256);
186         if (ptr == NULL)
187             strcpy(text, last_ptr);
188         else
189             strncpy(text, last_ptr, (ptr - last_ptr) * sizeof(char));
190
191         if (ptr == NULL) {
192             int i;
193             for (i = 0; i < nkmap + 1; i++) {
194                 if (i == nkmap) {
195                     hk->keysym = text[0] + 0x0020;
196                     break;
197                 } else if (strcmp(text, kmap_text[i]) == 0) {
198                     hk->keysym = kmap_keysym[i];
199                     break;
200                 }
201             }
202             break;
203         } else {
204             if (strcmp(text, "Control") == 0)
205                 hk->modifiers |= ControlMask;
206             if (strcmp(text, "Shift") == 0)
207                 hk->modifiers |= ShiftMask;
208         }
209         last_ptr = ptr + 1;
210     }
211 }
212
213 static void
214 __init_default_values()
215 {
216     hotkey_t hk;
217     position_t pos;
218     double d;
219     varchar str;
220     int i;
221
222     /* trigger key */
223     hk.modifiers = ControlMask;
224     hk.keysym = XK_space;
225     settings_set(TRIGGER_KEY, &hk);
226
227     /* eng key */
228     hk.modifiers = 0;
229     hk.keysym = XK_Shift_L;
230     settings_set(ENG_KEY, &hk);
231
232     get_screen_size(&(pos.x), &(pos.y));
233     pos.x -= 200;
234     pos.y -= 70;
235
236     settings_set(ICBAR_POS, &pos);
237
238     /* preedit opacity */
239     settings_set_double(PREEDIT_OPACITY, 1.0);
240
241     settings_set_string(PREEDIT_COLOR, "#FFFFB3");
242     settings_set_string(PREEDIT_FONT, "Sans 10");
243     settings_set_string(PREEDIT_FONT_COLOR, "#000000");
244
245     settings_set_int(SHUANGPIN, 0);
246     settings_set_string(SHUANGPIN_SCHEME, "MS2003");
247
248     settings_set_int(CANDIDATES_SIZE, 10);
249
250     /* page up and down trigger */
251     settings_set_int(PAGE_MINUS_PLUS, 1);
252     settings_set_int(PAGE_COMMA_PERIOD, 0);
253     settings_set_int(PAGE_PAREN, 0);
254
255     /* fuzzy segmentation */
256     settings_set_int(FUZZY_SEGMENTATION, 0);
257     settings_set_int(FUZZY_INNER_SEGMENTATION, 0);
258
259     /* cancel on backspace */
260     settings_set_int(CANCEL_ON_BACKSPACE, 1);
261
262     /* smart punctuation */
263     settings_set_int(SMART_PUNCT, 0);
264
265     /* skin support */
266     settings_set_string(SKIN_NAME, "classic");
267
268     /* whether hide icbar */
269     settings_set_int(HIDE_ICBAR, 0);
270 }
271
272 #define REGISTER(k, type, efunc, dfunc)               \
273     do {                                        \
274         setting_data[k] = malloc(sizeof(type)); \
275         setting_size[k] = sizeof(type);         \
276         setting_enc[k] = efunc;                 \
277         setting_dec[k] = dfunc;                 \
278     } while(0)                                  \
279
280 void
281 settings_init()
282 {
283     memset(setting_data, 0, sizeof(void*) * MAX_KEY);
284
285     REGISTER(TRIGGER_KEY, hotkey_t, __hotkey_enc, __hotkey_dec);
286     REGISTER(ENG_KEY, hotkey_t, __hotkey_enc, __hotkey_dec);
287     REGISTER(ICBAR_POS, position_t, __position_enc, __position_dec);
288     REGISTER(PREEDIT_OPACITY, double, __double_enc, __double_dec);
289     REGISTER(PREEDIT_COLOR, varchar, __varchar_enc, __varchar_dec);
290     REGISTER(PREEDIT_FONT, varchar, __varchar_enc, __varchar_dec);
291     REGISTER(PREEDIT_FONT_COLOR, varchar, __varchar_enc, __varchar_dec);
292     REGISTER(SHUANGPIN, int, __int_enc, __int_dec);
293     REGISTER(SHUANGPIN_SCHEME, varchar, __varchar_enc, __varchar_dec);
294     REGISTER(CANDIDATES_SIZE, int, __int_enc, __int_dec);
295     REGISTER(PAGE_MINUS_PLUS, int, __int_enc, __int_dec);
296     REGISTER(PAGE_COMMA_PERIOD, int, __int_enc, __int_dec);
297     REGISTER(PAGE_PAREN, int, __int_enc, __int_dec);
298     REGISTER(FUZZY_SEGMENTATION, int, __int_enc, __int_dec);
299     REGISTER(FUZZY_INNER_SEGMENTATION, int, __int_enc, __int_dec);
300     REGISTER(CANCEL_ON_BACKSPACE, int, __int_enc, __int_dec);
301     REGISTER(SMART_PUNCT, int, __int_enc, __int_dec);
302     REGISTER(SKIN_NAME, varchar, __varchar_enc, __varchar_dec);
303     REGISTER(HIDE_ICBAR, int, __int_enc, __int_dec);
304
305     __init_default_values();
306 }
307
308 void
309 settings_destroy()
310 {
311     int i = 0;
312     while (setting_names[i] != NULL) {
313         if (setting_data[i] != NULL)
314             free(setting_data[i]);
315         i++;
316     }
317 }
318
319 #define SETTING_FILE ".sunpinyin/xim_config"
320 #define DEFAULT_SETTING_FILE SUNPINYIN_XIM_SETTING_DIR"/xim_config_default"
321
322 void
323 settings_load()
324 {
325     char path[256];
326     char line[256];
327     snprintf(path, 256, "%s/%s", getenv("HOME"), SETTING_FILE);
328     FILE *fp = fopen(path, "r");
329     if (fp == NULL) {
330         char config_dir[256];
331         snprintf(config_dir, 256, "%s/.sunpinyin", getenv("HOME"));
332         mkdir(config_dir, S_IRWXU);
333         settings_save();
334         if ((fp = fopen(path, "r")) == NULL)
335             return;
336     }
337     while (1) {
338         memset(line, 0, sizeof(char) * 256);
339         if (fgets(line, 256, fp) == NULL)
340             break;
341         if (line[0] == 0)
342             break;
343
344         /* strip the last \n */
345         line[strlen(line) - 1] = 0;
346
347         /* bypass the comment */
348         if (line[0] == '#')
349             continue;
350
351         char* ptr = strchr(line, '=');
352         int i = 0;
353         while (setting_names[i] != NULL) {
354             if (strncmp(line, setting_names[i], ptr - line) == 0) {
355                 serialize_func_t func = setting_dec[i];
356                 func(ptr + 1, setting_data[i]);
357             }
358             i++;
359         }
360     }
361     fclose(fp);
362 }
363
364 void
365 settings_save()
366 {
367     char path[256];
368     char line[256];
369     snprintf(path, 256, "%s/%s", getenv("HOME"), SETTING_FILE);
370     FILE *fp = fopen(path, "w");
371     if (fp == NULL) {
372         LOG("settings can't be saved");
373         return;
374     }
375     int i = 0;
376     while (setting_names[i] != NULL) {
377         memset(line, 0, sizeof(char) * 256);
378         serialize_func_t func = setting_enc[i];
379         func(line, setting_data[i]);
380         fprintf(fp, "%s=%s\n", setting_names[i], line);
381         i++;
382     }
383     fclose(fp);
384 }
385
386 int settings_get_int(setting_key_t key)
387 {
388     int ret = 0;
389     settings_get(key, &ret);
390     return ret;
391 }
392
393 double settings_get_double(setting_key_t key)
394 {
395     double ret = 0;
396     settings_get(key, &ret);
397     return ret;
398 }
399
400 void
401 settings_get(setting_key_t key, void* data)
402 {
403     if (setting_data[key] == NULL) {
404         LOG("invalid setting key %d to get", key);
405         return;
406     }
407     memcpy(data, setting_data[key], setting_size[key]);
408 }
409
410 void
411 settings_set_int(setting_key_t key, int value)
412 {
413     settings_set(key, &value);
414 }
415
416 void
417 settings_set_double(setting_key_t key, double value)
418 {
419     settings_set(key, &value);
420 }
421
422 void
423 settings_set_string(setting_key_t key, const char* str)
424 {
425     varchar vchar;
426     strncpy(vchar, str, sizeof(varchar));
427     settings_set(key, vchar);
428 }
429
430 void
431 settings_set(setting_key_t key, void* data)
432 {
433     if (setting_data[key] == NULL) {
434         LOG("invalid setting key %d to set", key);
435         return;
436     }
437     memcpy(setting_data[key], data, setting_size[key]);
438 }