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