2 * Copyright (c) 2010 Mike Qin <mikeandmore@gmail.com>
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
15 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
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.
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.
37 #include <X11/Xproto.h>
39 #include <X11/keysym.h>
40 #include <X11/Xutil.h>
47 typedef void (*serialize_func_t)(char* str, void* data);
49 static const char* setting_names[] = {
63 "fuzzy_inner_segmentation",
65 "cancel_on_backspace",
72 static void* setting_data[MAX_KEY];
73 static size_t setting_size[MAX_KEY];
75 static serialize_func_t setting_enc[MAX_KEY];
76 static serialize_func_t setting_dec[MAX_KEY];
79 __varchar_enc(char* str, void* data)
81 strncpy(str, data, 128);
85 __varchar_dec(char* str, void* data)
87 strncpy(data, str, 128);
91 __double_enc(char* str, void* data)
94 snprintf(str, 256, "%.2lf", *ptr);
98 __double_dec(char* str, void* data)
101 sscanf(str, "%lf", ptr);
105 __int_enc(char* str, void* data)
108 snprintf(str, 256, "%d", *ptr);
112 __int_dec(char* str, void* data)
115 sscanf(str, "%d", ptr);
119 __position_enc(char* str, void* data)
121 position_t* pos = data;
122 snprintf(str, 256, "%d,%d", pos->x, pos->y);
126 __position_dec(char* str, void* data)
128 position_t* pos = data;
129 sscanf(str, "%d,%d", &pos->x, &pos->y);
132 static const int kmap_keysym[] =
134 XK_Shift_L, XK_Shift_R, XK_Control_L,
135 XK_Control_R, XK_Meta_L, XK_Meta_R,
139 static const char* kmap_text[] =
141 "Shift_L", "Shift_R", "Control_L",
142 "Control_R", "Meta_L", "Meta_R", "space",
148 __hotkey_enc(char* str, void* data)
151 if (hk->modifiers & ControlMask) {
152 strncat(str, "Control+", 255);
154 if (hk->modifiers & ShiftMask) {
155 strncat(str, "Shift+", 255);
159 memset(keyname, 0, sizeof(char) * 256);
161 for (i = 0; i < nkmap + 1; i++) {
163 keyname[0] = hk->keysym - 0x0020;
165 } else if (hk->keysym == kmap_keysym[i]) {
166 strncpy(keyname, kmap_text[i], 255);
171 strncat(str, keyname, 255);
175 __hotkey_dec(char* str, void* data)
181 char* last_ptr = str;
184 char* ptr = strchr(last_ptr, '+');
185 memset(text, 0, sizeof(char) * 256);
187 strcpy(text, last_ptr);
189 strncpy(text, last_ptr, (ptr - last_ptr) * sizeof(char));
193 for (i = 0; i < nkmap + 1; i++) {
195 hk->keysym = text[0] + 0x0020;
197 } else if (strcmp(text, kmap_text[i]) == 0) {
198 hk->keysym = kmap_keysym[i];
204 if (strcmp(text, "Control") == 0)
205 hk->modifiers |= ControlMask;
206 if (strcmp(text, "Shift") == 0)
207 hk->modifiers |= ShiftMask;
214 __init_default_values()
223 hk.modifiers = ControlMask;
224 hk.keysym = XK_space;
225 settings_set(TRIGGER_KEY, &hk);
229 hk.keysym = XK_Shift_L;
230 settings_set(ENG_KEY, &hk);
232 get_screen_size(&(pos.x), &(pos.y));
236 settings_set(ICBAR_POS, &pos);
238 /* preedit opacity */
239 settings_set_double(PREEDIT_OPACITY, 1.0);
241 settings_set_string(PREEDIT_COLOR, "#FFFFB3");
242 settings_set_string(PREEDIT_FONT, "Sans 10");
243 settings_set_string(PREEDIT_FONT_COLOR, "#000000");
245 settings_set_int(SHUANGPIN, 0);
246 settings_set_string(SHUANGPIN_SCHEME, "MS2003");
248 settings_set_int(CANDIDATES_SIZE, 10);
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);
255 /* fuzzy segmentation */
256 settings_set_int(FUZZY_SEGMENTATION, 0);
257 settings_set_int(FUZZY_INNER_SEGMENTATION, 0);
259 /* cancel on backspace */
260 settings_set_int(CANCEL_ON_BACKSPACE, 1);
262 /* smart punctuation */
263 settings_set_int(SMART_PUNCT, 0);
266 settings_set_string(SKIN_NAME, "classic");
268 /* whether hide icbar */
269 settings_set_int(HIDE_ICBAR, 0);
272 #define REGISTER(k, type, efunc, dfunc) \
274 setting_data[k] = malloc(sizeof(type)); \
275 setting_size[k] = sizeof(type); \
276 setting_enc[k] = efunc; \
277 setting_dec[k] = dfunc; \
283 memset(setting_data, 0, sizeof(void*) * MAX_KEY);
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);
305 __init_default_values();
312 while (setting_names[i] != NULL) {
313 if (setting_data[i] != NULL)
314 free(setting_data[i]);
319 #define SETTING_FILE ".sunpinyin/xim_config"
320 #define DEFAULT_SETTING_FILE SUNPINYIN_XIM_SETTING_DIR"/xim_config_default"
327 snprintf(path, 256, "%s/%s", getenv("HOME"), SETTING_FILE);
328 FILE *fp = fopen(path, "r");
330 char config_dir[256];
331 snprintf(config_dir, 256, "%s/.sunpinyin", getenv("HOME"));
332 mkdir(config_dir, S_IRWXU);
334 if ((fp = fopen(path, "r")) == NULL)
338 memset(line, 0, sizeof(char) * 256);
339 if (fgets(line, 256, fp) == NULL)
344 /* strip the last \n */
345 line[strlen(line) - 1] = 0;
347 /* bypass the comment */
351 char* ptr = strchr(line, '=');
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]);
369 snprintf(path, 256, "%s/%s", getenv("HOME"), SETTING_FILE);
370 FILE *fp = fopen(path, "w");
372 LOG("settings can't be saved");
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);
386 int settings_get_int(setting_key_t key)
389 settings_get(key, &ret);
393 double settings_get_double(setting_key_t key)
396 settings_get(key, &ret);
401 settings_get(setting_key_t key, void* data)
403 if (setting_data[key] == NULL) {
404 LOG("invalid setting key %d to get", key);
407 memcpy(data, setting_data[key], setting_size[key]);
411 settings_set_int(setting_key_t key, int value)
413 settings_set(key, &value);
417 settings_set_double(setting_key_t key, double value)
419 settings_set(key, &value);
423 settings_set_string(setting_key_t key, const char* str)
426 strncpy(vchar, str, sizeof(varchar));
427 settings_set(key, vchar);
431 settings_set(setting_key_t key, void* data)
433 if (setting_data[key] == NULL) {
434 LOG("invalid setting key %d to set", key);
437 memcpy(setting_data[key], data, setting_size[key]);