clean db
[platform/upstream/ibus-libpinyin.git] / src / PYConfig.cc
1 /* vim:set et ts=4 sts=4:
2  *
3  * ibus-pinyin - The Chinese PinYin engine for IBus
4  *
5  * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 #include "PYConfig.h"
22
23 #include "PYTypes.h"
24 #include "PYBus.h"
25
26 namespace PY {
27
28 const gchar * const CONFIG_CORRECT_PINYIN            = "CorrectPinyin";
29 const gchar * const CONFIG_FUZZY_PINYIN              = "FuzzyPinyin";
30 const gchar * const CONFIG_ORIENTATION               = "LookupTableOrientation";
31 const gchar * const CONFIG_PAGE_SIZE                 = "LookupTablePageSize";
32 const gchar * const CONFIG_SHIFT_SELECT_CANDIDATE    = "ShiftSelectCandidate";
33 const gchar * const CONFIG_MINUS_EQUAL_PAGE          = "MinusEqualPage";
34 const gchar * const CONFIG_COMMA_PERIOD_PAGE         = "CommaPeriodPage";
35 const gchar * const CONFIG_AUTO_COMMIT               = "AutoCommit";
36 const gchar * const CONFIG_DOUBLE_PINYIN             = "DoublePinyin";
37 const gchar * const CONFIG_DOUBLE_PINYIN_SCHEMA      = "DoublePinyinSchema";
38 const gchar * const CONFIG_DOUBLE_PINYIN_SHOW_RAW    = "DoublePinyinShowRaw";
39 const gchar * const CONFIG_INIT_CHINESE              = "InitChinese";
40 const gchar * const CONFIG_INIT_FULL                 = "InitFull";
41 const gchar * const CONFIG_INIT_FULL_PUNCT           = "InitFullPunct";
42 const gchar * const CONFIG_INIT_SIMP_CHINESE         = "InitSimplifiedChinese";
43 const gchar * const CONFIG_SPECIAL_PHRASES           = "SpecialPhrases";
44 const gchar * const CONFIG_BOPOMOFO_KEYBOARD_MAPPING = "BopomofoKeyboardMapping";
45 const gchar * const CONFIG_SELECT_KEYS               = "SelectKeys";
46 const gchar * const CONFIG_GUIDE_KEY                 = "GuideKey";
47 const gchar * const CONFIG_AUXILIARY_SELECT_KEY_F    = "AuxiliarySelectKey_F";
48 const gchar * const CONFIG_AUXILIARY_SELECT_KEY_KP   = "AuxiliarySelectKey_KP";
49 const gchar * const CONFIG_ENTER_KEY                 = "EnterKey";
50
51 const guint PINYIN_DEFAULT_OPTION =
52         PINYIN_INCOMPLETE_PINYIN |
53         PINYIN_FUZZY_C_CH |
54         // PINYIN_FUZZY_CH_C |
55         PINYIN_FUZZY_Z_ZH |
56         // PINYIN_FUZZY_ZH_Z |
57         PINYIN_FUZZY_S_SH |
58         // PINYIN_FUZZY_SH_S |
59         PINYIN_FUZZY_L_N |
60         // PINYIN_FUZZY_N_L |
61         PINYIN_FUZZY_F_H |
62         // PINYIN_FUZZY_H_F |
63         // PINYIN_FUZZY_L_R |
64         // PINYIN_FUZZY_R_L |
65         PINYIN_FUZZY_K_G |
66         PINYIN_FUZZY_G_K |
67         PINYIN_FUZZY_AN_ANG |
68         PINYIN_FUZZY_ANG_AN |
69         PINYIN_FUZZY_EN_ENG |
70         PINYIN_FUZZY_ENG_EN |
71         PINYIN_FUZZY_IN_ING |
72         PINYIN_FUZZY_ING_IN |
73         // PINYIN_FUZZY_IAN_IANG |
74         // PINYIN_FUZZY_IANG_IAN |
75         // PINYIN_FUZZY_UAN_UANG |
76         // PINYIN_FUZZY_UANG_UAN |
77         0;
78
79
80 Config::Config (Bus & bus, const std::string & name)
81     : Object (ibus_bus_get_config (bus)),
82       m_section ("engine/" + name)
83 {
84     initDefaultValues ();
85     g_signal_connect (get<IBusConfig> (),
86                       "value-changed",
87                       G_CALLBACK (valueChangedCallback),
88                       this);
89 }
90
91 Config::~Config (void)
92 {
93 }
94
95 void
96 Config::initDefaultValues (void)
97 {
98     m_option = PINYIN_DEFAULT_OPTION;
99     m_option_mask = PINYIN_INCOMPLETE_PINYIN | PINYIN_CORRECT_ALL;
100
101     m_orientation = IBUS_ORIENTATION_HORIZONTAL;
102     m_page_size = 5;
103     m_shift_select_candidate = FALSE;
104     m_minus_equal_page = TRUE;
105     m_comma_period_page = TRUE;
106     m_auto_commit = FALSE;
107
108     m_double_pinyin = FALSE;
109     m_double_pinyin_schema = 0;
110     m_double_pinyin_show_raw = FALSE;
111
112     m_init_chinese = TRUE;
113     m_init_full = FALSE;
114     m_init_full_punct = TRUE;
115     m_init_simp_chinese = TRUE;
116     m_special_phrases = TRUE;
117 }
118
119 static const struct {
120     const gchar * const name;
121     guint option;
122 } options [] = {
123     { "IncompletePinyin",       PINYIN_INCOMPLETE_PINYIN},
124     /* fuzzy pinyin */
125     { "FuzzyPinyin_C_CH",       PINYIN_FUZZY_C_CH      },
126     { "FuzzyPinyin_CH_C",       PINYIN_FUZZY_CH_C      },
127     { "FuzzyPinyin_Z_ZH",       PINYIN_FUZZY_Z_ZH      },
128     { "FuzzyPinyin_ZH_Z",       PINYIN_FUZZY_ZH_Z      },
129     { "FuzzyPinyin_S_SH",       PINYIN_FUZZY_S_SH      },
130     { "FuzzyPinyin_SH_S",       PINYIN_FUZZY_SH_S      },
131     { "FuzzyPinyin_L_N",        PINYIN_FUZZY_L_N       },
132     { "FuzzyPinyin_N_L",        PINYIN_FUZZY_N_L       },
133     { "FuzzyPinyin_F_H",        PINYIN_FUZZY_F_H       },
134     { "FuzzyPinyin_H_F",        PINYIN_FUZZY_H_F       },
135     { "FuzzyPinyin_L_R",        PINYIN_FUZZY_L_R       },
136     { "FuzzyPinyin_R_L",        PINYIN_FUZZY_R_L       },
137     { "FuzzyPinyin_K_G",        PINYIN_FUZZY_K_G       },
138     { "FuzzyPinyin_G_K",        PINYIN_FUZZY_G_K       },
139     { "FuzzyPinyin_AN_ANG",     PINYIN_FUZZY_AN_ANG    },
140     { "FuzzyPinyin_ANG_AN",     PINYIN_FUZZY_ANG_AN    },
141     { "FuzzyPinyin_EN_ENG",     PINYIN_FUZZY_EN_ENG    },
142     { "FuzzyPinyin_ENG_EN",     PINYIN_FUZZY_ENG_EN    },
143     { "FuzzyPinyin_IN_ING",     PINYIN_FUZZY_IN_ING    },
144     { "FuzzyPinyin_ING_IN",     PINYIN_FUZZY_ING_IN    },
145 #if 0
146     { "FuzzyPinyin_IAN_IANG",   PINYIN_FUZZY_IAN_IANG  },
147     { "FuzzyPinyin_IANG_IAN",   PINYIN_FUZZY_IANG_IAN  },
148     { "FuzzyPinyin_UAN_UANG",   PINYIN_FUZZY_UAN_UANG  },
149     { "FuzzyPinyin_UANG_UAN",   PINYIN_FUZZY_UANG_UAN  },
150 #endif
151 };
152
153 void
154 Config::readDefaultValues (void)
155 {
156 #if defined(HAVE_IBUS_CONFIG_GET_VALUES)
157     /* read all values together */
158     initDefaultValues ();
159     GVariant *values =
160             ibus_config_get_values (get<IBusConfig> (), m_section.c_str ());
161     g_return_if_fail (values != NULL);
162
163     GVariantIter iter;
164     gchar *name;
165     GVariant *value;
166     g_variant_iter_init (&iter, values);
167     while (g_variant_iter_next (&iter, "{sv}", &name, &value)) {
168         valueChanged (m_section, name, value);
169         g_free (name);
170         g_variant_unref (value);
171     }
172     g_variant_unref (values);
173 #else
174     /* others */
175     m_orientation = read (CONFIG_ORIENTATION, 0);
176     if (m_orientation != IBUS_ORIENTATION_VERTICAL &&
177         m_orientation != IBUS_ORIENTATION_HORIZONTAL) {
178         m_orientation = IBUS_ORIENTATION_HORIZONTAL;
179         g_warn_if_reached ();
180     }
181     m_page_size = read (CONFIG_PAGE_SIZE, 5);
182     if (m_page_size > 10) {
183         m_page_size = 5;
184         g_warn_if_reached ();
185     }
186
187     /* fuzzy pinyin */
188     if (read (CONFIG_FUZZY_PINYIN, false))
189         m_option_mask |= PINYIN_FUZZY_ALL;
190     else
191         m_option_mask &= ~PINYIN_FUZZY_ALL;
192
193     /* read values */
194     for (guint i = 0; i < G_N_ELEMENTS (options); i++) {
195         if (read (options[i].name,
196                   (options[i].option & PINYIN_DEFAULT_OPTION) != 0)) {
197             m_option |= options[i].option;
198         }
199         else {
200             m_option &= ~options[i].option;
201         }
202     }
203 #endif
204 }
205
206 inline bool
207 Config::read (const gchar * name,
208               bool          defval)
209 {
210     GVariant *value = NULL;
211     if ((value = ibus_config_get_value (get<IBusConfig> (), m_section.c_str (), name)) != NULL) {
212         if (g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN)
213             return g_variant_get_boolean (value);
214     }
215
216     // write default value to config
217     value = g_variant_new ("b", defval);
218     ibus_config_set_value (get<IBusConfig> (), m_section.c_str (), name, value);
219
220     return defval;
221 }
222
223 inline gint
224 Config::read (const gchar * name,
225               gint          defval)
226 {
227     GVariant *value = NULL;
228     if ((value = ibus_config_get_value (get<IBusConfig> (), m_section.c_str (), name)) != NULL) {
229         if (g_variant_classify (value) == G_VARIANT_CLASS_INT32)
230             return g_variant_get_int32 (value);
231     }
232
233     // write default value to config
234     value = g_variant_new ("i", defval);
235     ibus_config_set_value (get<IBusConfig> (), m_section.c_str (), name, value);
236
237     return defval;
238 }
239
240 inline std::string
241 Config::read (const gchar * name,
242               const gchar * defval)
243 {
244     GVariant *value = NULL;
245     if ((value = ibus_config_get_value (get<IBusConfig> (), m_section.c_str (), name)) != NULL) {
246         if (g_variant_classify (value) == G_VARIANT_CLASS_STRING)
247             return g_variant_get_string (value, NULL);
248     }
249
250     // write default value to config
251     value = g_variant_new ("s", defval);
252     ibus_config_set_value (get<IBusConfig> (), m_section.c_str (), name, value);
253
254     return defval;
255 }
256
257 static inline bool
258 normalizeGVariant (GVariant *value, bool defval)
259 {
260     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
261         return defval;
262     return g_variant_get_boolean (value);
263 }
264
265 static inline gint
266 normalizeGVariant (GVariant *value, gint defval)
267 {
268     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_INT32)
269         return defval;
270     return g_variant_get_int32 (value);
271 }
272
273 static inline std::string
274 normalizeGVariant (GVariant *value, const std::string &defval)
275 {
276     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_STRING)
277         return defval;
278     return g_variant_get_string (value, NULL);
279 }
280
281 gboolean
282 Config::valueChanged (const std::string &section,
283                       const std::string &name,
284                       GVariant          *value)
285 {
286     if (m_section != section)
287         return FALSE;
288
289     /* lookup table page size */
290     if (CONFIG_ORIENTATION == name) {
291         m_orientation = normalizeGVariant (value, IBUS_ORIENTATION_HORIZONTAL);
292         if (m_orientation != IBUS_ORIENTATION_VERTICAL &&
293             m_orientation != IBUS_ORIENTATION_HORIZONTAL) {
294             m_orientation = IBUS_ORIENTATION_HORIZONTAL;
295             g_warn_if_reached ();
296         }
297     }
298     else if (CONFIG_PAGE_SIZE == name) {
299         m_page_size = normalizeGVariant (value, 5);
300         if (m_page_size > 10) {
301             m_page_size = 5;
302             g_warn_if_reached ();
303         }
304     }
305     /* fuzzy pinyin */
306     else if (CONFIG_FUZZY_PINYIN == name) {
307         if (normalizeGVariant (value, false))
308             m_option_mask |= PINYIN_FUZZY_ALL;
309         else
310             m_option_mask &= ~PINYIN_FUZZY_ALL;
311     }
312     else {
313         for (guint i = 0; i < G_N_ELEMENTS (options); i++) {
314             if (G_LIKELY (options[i].name != name))
315                 continue;
316             if (normalizeGVariant (value,
317                     (options[i].option & PINYIN_DEFAULT_OPTION) != 0))
318                 m_option |= options[i].option;
319             else
320                 m_option &= ~options[i].option;
321             return TRUE;
322         }
323         return FALSE;
324     }
325     return TRUE;
326 }
327
328 void
329 Config::valueChangedCallback (IBusConfig  *config,
330                               const gchar *section,
331                               const gchar *name,
332                               GVariant    *value,
333                               Config      *self)
334 {
335     self->valueChanged (section, name, value);
336 }
337
338 };