clean up PYConfig.h/cc
[platform/upstream/ibus-libpinyin.git] / src / PYPConfig.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 "PYPConfig.h"
22
23 #include <pinyin.h>
24 #include "PYBus.h"
25 #include "PYLibPinyin.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 |
54         CHEWING_INCOMPLETE|
55         PINYIN_CORRECT_ALL|
56         0;
57
58 std::unique_ptr<LibPinyinPinyinConfig> LibPinyinPinyinConfig::m_instance;
59 std::unique_ptr<LibPinyinBopomofoConfig> LibPinyinBopomofoConfig::m_instance;
60
61 LibPinyinConfig::LibPinyinConfig (Bus & bus, const std::string & name)
62     : Config (bus, name)
63 {
64     initDefaultValues ();
65     g_signal_connect (get<IBusConfig> (),
66                       "value-changed",
67                       G_CALLBACK (valueChangedCallback),
68                       this);
69 }
70
71 LibPinyinConfig::~LibPinyinConfig (void)
72 {
73 }
74
75 void
76 LibPinyinConfig::initDefaultValues (void)
77 {
78     m_option = PINYIN_DEFAULT_OPTION;
79     m_option_mask = PINYIN_INCOMPLETE | CHEWING_INCOMPLETE | PINYIN_CORRECT_ALL;
80
81     m_orientation = IBUS_ORIENTATION_HORIZONTAL;
82     m_page_size = 5;
83     m_shift_select_candidate = FALSE;
84     m_minus_equal_page = TRUE;
85     m_comma_period_page = TRUE;
86     m_auto_commit = FALSE;
87
88     m_double_pinyin = FALSE;
89     m_double_pinyin_schema = 0;
90     m_double_pinyin_show_raw = FALSE;
91
92     m_init_chinese = TRUE;
93     m_init_full = FALSE;
94     m_init_full_punct = TRUE;
95     m_init_simp_chinese = TRUE;
96     m_special_phrases = TRUE;
97 }
98
99 static const struct {
100     const gchar * const name;
101     guint option;
102 } options [] = {
103     { "IncompletePinyin",       PINYIN_INCOMPLETE|CHEWING_INCOMPLETE},
104     /* fuzzy pinyin */
105     { "FuzzyPinyin_C_CH",       PINYIN_AMB_C_CH      },
106     { "FuzzyPinyin_Z_ZH",       PINYIN_AMB_Z_ZH      },
107     { "FuzzyPinyin_S_SH",       PINYIN_AMB_S_SH      },
108     { "FuzzyPinyin_L_N",        PINYIN_AMB_L_N       },
109     { "FuzzyPinyin_F_H",        PINYIN_AMB_F_H       },
110     { "FuzzyPinyin_L_R",        PINYIN_AMB_L_R       },
111     { "FuzzyPinyin_G_K",        PINYIN_AMB_G_K       },
112     { "FuzzyPinyin_AN_ANG",     PINYIN_AMB_AN_ANG    },
113     { "FuzzyPinyin_EN_ENG",     PINYIN_AMB_EN_ENG    },
114     { "FuzzyPinyin_IN_ING",     PINYIN_AMB_IN_ING    },
115 };
116
117 void
118 LibPinyinConfig::readDefaultValues (void)
119 {
120 #if defined(HAVE_IBUS_CONFIG_GET_VALUES)
121     /* read all values together */
122     initDefaultValues ();
123     GVariant *values =
124             ibus_config_get_values (get<IBusConfig> (), m_section.c_str ());
125     g_return_if_fail (values != NULL);
126
127     GVariantIter iter;
128     gchar *name;
129     GVariant *value;
130     g_variant_iter_init (&iter, values);
131     while (g_variant_iter_next (&iter, "{sv}", &name, &value)) {
132         valueChanged (m_section, name, value);
133         g_free (name);
134         g_variant_unref (value);
135     }
136     g_variant_unref (values);
137 #else
138     /* others */
139     m_orientation = read (CONFIG_ORIENTATION, 0);
140     if (m_orientation != IBUS_ORIENTATION_VERTICAL &&
141         m_orientation != IBUS_ORIENTATION_HORIZONTAL) {
142         m_orientation = IBUS_ORIENTATION_HORIZONTAL;
143         g_warn_if_reached ();
144     }
145     m_page_size = read (CONFIG_PAGE_SIZE, 5);
146     if (m_page_size > 10) {
147         m_page_size = 5;
148         g_warn_if_reached ();
149     }
150
151     /* fuzzy pinyin */
152     if (read (CONFIG_FUZZY_PINYIN, false))
153         m_option_mask |= PINYIN_AMB_ALL;
154     else
155         m_option_mask &= ~PINYIN_AMB_ALL;
156
157     /* read values */
158     for (guint i = 0; i < G_N_ELEMENTS (options); i++) {
159         if (read (options[i].name,
160                   (options[i].option & PINYIN_DEFAULT_OPTION) != 0)) {
161             m_option |= options[i].option;
162         }
163         else {
164             m_option &= ~options[i].option;
165         }
166     }
167 #endif
168 }
169
170
171 static inline bool
172 normalizeGVariant (GVariant *value, bool defval)
173 {
174     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
175         return defval;
176     return g_variant_get_boolean (value);
177 }
178
179 static inline gint
180 normalizeGVariant (GVariant *value, gint defval)
181 {
182     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_INT32)
183         return defval;
184     return g_variant_get_int32 (value);
185 }
186
187 static inline std::string
188 normalizeGVariant (GVariant *value, const std::string &defval)
189 {
190     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_STRING)
191         return defval;
192     return g_variant_get_string (value, NULL);
193 }
194
195 gboolean
196 LibPinyinConfig::valueChanged (const std::string &section,
197                                const std::string &name,
198                                GVariant          *value)
199 {
200     if (m_section != section)
201         return FALSE;
202
203     /* lookup table page size */
204     if (CONFIG_ORIENTATION == name) {
205         m_orientation = normalizeGVariant (value, IBUS_ORIENTATION_HORIZONTAL);
206         if (m_orientation != IBUS_ORIENTATION_VERTICAL &&
207             m_orientation != IBUS_ORIENTATION_HORIZONTAL) {
208             m_orientation = IBUS_ORIENTATION_HORIZONTAL;
209             g_warn_if_reached ();
210         }
211     }
212     else if (CONFIG_PAGE_SIZE == name) {
213         m_page_size = normalizeGVariant (value, 5);
214         if (m_page_size > 10) {
215             m_page_size = 5;
216             g_warn_if_reached ();
217         }
218     }
219     /* fuzzy pinyin */
220     else if (CONFIG_FUZZY_PINYIN == name) {
221         if (normalizeGVariant (value, false))
222             m_option_mask |= PINYIN_AMB_ALL;
223         else
224             m_option_mask &= ~PINYIN_AMB_ALL;
225     }
226     else {
227         for (guint i = 0; i < G_N_ELEMENTS (options); i++) {
228             if (G_LIKELY (options[i].name != name))
229                 continue;
230             if (normalizeGVariant (value,
231                     (options[i].option & PINYIN_DEFAULT_OPTION) != 0))
232                 m_option |= options[i].option;
233             else
234                 m_option &= ~options[i].option;
235             return TRUE;
236         }
237         return FALSE;
238     }
239     return TRUE;
240 }
241
242 void
243 LibPinyinConfig::valueChangedCallback (IBusConfig  *config,
244                                        const gchar *section,
245                                        const gchar *name,
246                                        GVariant    *value,
247                                        LibPinyinConfig *self)
248 {
249     self->valueChanged (section, name, value);
250     if (self->m_section != section)
251         return;
252 #ifdef IBUS_BUILD_LIBPINYIN
253     if (self->m_section == "engine/Pinyin")
254         LibPinyinBackEnd::instance ().setPinyinOptions (self);
255     if (self->m_section == "engine/Bopomofo")
256         LibPinyinBackEnd::instance ().setChewingOptions (self);
257 #endif
258 }
259
260 static const struct {
261     const gchar * const name;
262     guint option;
263 } pinyin_options [] = {
264     /* correct */
265     { "CorrectPinyin_GN_NG",    PINYIN_CORRECT_GN_NG    },
266     { "CorrectPinyin_GN_NG",    PINYIN_CORRECT_GN_NG    },
267     { "CorrectPinyin_MG_NG",    PINYIN_CORRECT_MG_NG    },
268     { "CorrectPinyin_IOU_IU",   PINYIN_CORRECT_IOU_IU   },
269     { "CorrectPinyin_UEI_UI",   PINYIN_CORRECT_UEI_UI   },
270     { "CorrectPinyin_UEN_UN",   PINYIN_CORRECT_UEN_UN   },
271     { "CorrectPinyin_UE_VE",    PINYIN_CORRECT_UE_VE    },
272     { "CorrectPinyin_V_U",      PINYIN_CORRECT_V_U      },
273     { "CorrectPinyin_VE_UE",    PINYIN_CORRECT_V_U      },
274     { "CorrectPinyin_ON_ONG",   PINYIN_CORRECT_ON_ONG   },
275 };
276
277 LibPinyinPinyinConfig::LibPinyinPinyinConfig (Bus & bus)
278     : LibPinyinConfig (bus, "Pinyin")
279 {
280 }
281
282 void
283 LibPinyinPinyinConfig::init (Bus & bus)
284 {
285     if (m_instance.get () == NULL) {
286         m_instance.reset (new LibPinyinPinyinConfig (bus));
287         m_instance->readDefaultValues ();
288     }
289 }
290
291 void
292 LibPinyinPinyinConfig::readDefaultValues (void)
293 {
294     LibPinyinConfig::readDefaultValues ();
295 #if !defined(HAVE_IBUS_CONFIG_GET_VALUES)
296     /* double pinyin */
297     m_double_pinyin = read (CONFIG_DOUBLE_PINYIN, false);
298     m_double_pinyin_schema = read (CONFIG_DOUBLE_PINYIN_SCHEMA, 0);
299     if (m_double_pinyin_schema > DOUBLE_PINYIN_LAST) {
300         m_double_pinyin_schema = 0;
301         g_warn_if_reached ();
302     }
303     m_double_pinyin_show_raw = read (CONFIG_DOUBLE_PINYIN_SHOW_RAW, false);
304
305     /* init states */
306     m_init_chinese = read (CONFIG_INIT_CHINESE, true);
307     m_init_full = read (CONFIG_INIT_FULL, false);
308     m_init_full_punct = read (CONFIG_INIT_FULL_PUNCT, true);
309     m_init_simp_chinese = read (CONFIG_INIT_SIMP_CHINESE, true);
310
311     m_special_phrases = read (CONFIG_SPECIAL_PHRASES, true);
312
313     /* other */
314     m_shift_select_candidate = read (CONFIG_SHIFT_SELECT_CANDIDATE, false);
315     m_minus_equal_page = read (CONFIG_MINUS_EQUAL_PAGE, true);
316     m_comma_period_page = read (CONFIG_COMMA_PERIOD_PAGE, true);
317     m_auto_commit = read (CONFIG_AUTO_COMMIT, false);
318
319     /* correct pinyin */
320     if (read (CONFIG_CORRECT_PINYIN, true))
321         m_option_mask |= PINYIN_CORRECT_ALL;
322     else
323         m_option_mask &= ~PINYIN_CORRECT_ALL;
324
325     /* read values */
326     for (guint i = 0; i < G_N_ELEMENTS (pinyin_options); i++) {
327         if (read (pinyin_options[i].name,
328                 (pinyin_options[i].option & PINYIN_DEFAULT_OPTION) != 0))
329             m_option |= pinyin_options[i].option;
330         else
331             m_option &= ~pinyin_options[i].option;
332     }
333 #endif
334 }
335
336 gboolean
337 LibPinyinPinyinConfig::valueChanged (const std::string &section,
338                                      const std::string &name,
339                                      GVariant          *value)
340 {
341     if (m_section != section)
342         return FALSE;
343
344     if (LibPinyinConfig::valueChanged (section, name, value))
345         return TRUE;
346
347     /* double pinyin */
348     if (CONFIG_DOUBLE_PINYIN == name)
349         m_double_pinyin = normalizeGVariant (value, false);
350     else if (CONFIG_DOUBLE_PINYIN_SCHEMA == name) {
351         m_double_pinyin_schema = normalizeGVariant (value, 0);
352 #if 0
353         if (m_double_pinyin_schema > DOUBLE_PINYIN_LAST) {
354             m_double_pinyin_schema = 0;
355             g_warn_if_reached ();
356         }
357 #endif
358     }
359     else if (CONFIG_DOUBLE_PINYIN_SHOW_RAW == name)
360         m_double_pinyin_show_raw = normalizeGVariant (value, false);
361     /* init states */
362     else if (CONFIG_INIT_CHINESE == name)
363         m_init_chinese = normalizeGVariant (value, true);
364     else if (CONFIG_INIT_FULL == name)
365         m_init_full = normalizeGVariant (value, true);
366     else if (CONFIG_INIT_FULL_PUNCT == name)
367         m_init_full_punct = normalizeGVariant (value, true);
368     else if (CONFIG_INIT_SIMP_CHINESE == name)
369         m_init_simp_chinese = normalizeGVariant (value, true);
370     else if (CONFIG_SPECIAL_PHRASES == name)
371         m_special_phrases = normalizeGVariant (value, true);
372     /* others */
373     else if (CONFIG_SHIFT_SELECT_CANDIDATE == name)
374         m_shift_select_candidate = normalizeGVariant (value, false);
375     else if (CONFIG_MINUS_EQUAL_PAGE == name)
376         m_minus_equal_page = normalizeGVariant (value, true);
377     else if (CONFIG_COMMA_PERIOD_PAGE == name)
378         m_comma_period_page = normalizeGVariant (value, true);
379     else if (CONFIG_AUTO_COMMIT == name)
380         m_auto_commit = normalizeGVariant (value, false);
381     /* correct pinyin */
382     else if (CONFIG_CORRECT_PINYIN == name) {
383         if (normalizeGVariant (value, true))
384             m_option_mask |= PINYIN_CORRECT_ALL;
385         else
386             m_option_mask &= ~PINYIN_CORRECT_ALL;
387     }
388     else {
389         for (guint i = 0; i < G_N_ELEMENTS (pinyin_options); i++) {
390             if (G_LIKELY (pinyin_options[i].name != name))
391                 continue;
392             if (normalizeGVariant (value,
393                     (pinyin_options[i].option & PINYIN_DEFAULT_OPTION) != 0))
394                 m_option |= pinyin_options[i].option;
395             else
396                 m_option &= ~pinyin_options[i].option;
397             return TRUE;
398         }
399         return FALSE;
400     }
401     return TRUE;
402 }
403
404 LibPinyinBopomofoConfig::LibPinyinBopomofoConfig (Bus & bus)
405     : LibPinyinConfig (bus, "Bopomofo")
406 {
407 }
408
409 void
410 LibPinyinBopomofoConfig::init (Bus & bus)
411 {
412     if (m_instance.get () == NULL) {
413         m_instance.reset (new LibPinyinBopomofoConfig (bus));
414         m_instance->readDefaultValues ();
415     }
416 }
417
418 void
419 LibPinyinBopomofoConfig::readDefaultValues (void)
420 {
421     LibPinyinConfig::readDefaultValues ();
422 #if !defined(HAVE_IBUS_CONFIG_GET_VALUES)
423     /* init states */
424     m_init_chinese = read (CONFIG_INIT_CHINESE, true);
425     m_init_full = read (CONFIG_INIT_FULL, false);
426     m_init_full_punct = read (CONFIG_INIT_FULL_PUNCT, true);
427     m_init_simp_chinese = read (CONFIG_INIT_SIMP_CHINESE, false);
428
429     m_special_phrases = read (CONFIG_SPECIAL_PHRASES, false);
430
431     m_bopomofo_keyboard_mapping = read (CONFIG_BOPOMOFO_KEYBOARD_MAPPING, 0);
432
433     m_select_keys = read (CONFIG_SELECT_KEYS, 0);
434     if (m_select_keys >= 9) m_select_keys = 0;
435     m_guide_key = read (CONFIG_GUIDE_KEY, true);
436     m_auxiliary_select_key_f = read (CONFIG_AUXILIARY_SELECT_KEY_F, true);
437     m_auxiliary_select_key_kp = read (CONFIG_AUXILIARY_SELECT_KEY_KP, true);
438     m_enter_key = read (CONFIG_ENTER_KEY, true);
439 #endif
440 }
441
442 gboolean
443 LibPinyinBopomofoConfig::valueChanged (const std::string &section,
444                                        const std::string &name,
445                                        GVariant          *value)
446 {
447     if (m_section != section)
448         return FALSE;
449
450     if (LibPinyinConfig::valueChanged (section, name, value))
451         return TRUE;
452
453     /* init states */
454     if (CONFIG_INIT_CHINESE == name)
455         m_init_chinese = normalizeGVariant (value, true);
456     else if (CONFIG_INIT_FULL == name)
457         m_init_full = normalizeGVariant (value, true);
458     else if (CONFIG_INIT_FULL_PUNCT == name)
459         m_init_full_punct = normalizeGVariant (value, true);
460     else if (CONFIG_INIT_SIMP_CHINESE == name)
461         m_init_simp_chinese = normalizeGVariant (value, false);
462     else if (CONFIG_SPECIAL_PHRASES == name)
463         m_special_phrases = normalizeGVariant (value, false);
464     else if (CONFIG_BOPOMOFO_KEYBOARD_MAPPING == name)
465         m_bopomofo_keyboard_mapping = normalizeGVariant (value, 0);
466     else if (CONFIG_SELECT_KEYS == name) {
467         m_select_keys = normalizeGVariant (value, 0);
468         if (m_select_keys >= 9) m_select_keys = 0;
469     }
470     else if (CONFIG_GUIDE_KEY == name)
471         m_guide_key = normalizeGVariant (value, true);
472     else if (CONFIG_AUXILIARY_SELECT_KEY_F == name)
473         m_auxiliary_select_key_f = normalizeGVariant (value, true);
474     else if (CONFIG_AUXILIARY_SELECT_KEY_KP == name)
475         m_auxiliary_select_key_kp = normalizeGVariant (value, true);
476     else if (CONFIG_ENTER_KEY == name)
477         m_enter_key = normalizeGVariant (value, true);
478     else
479         return FALSE;
480     return TRUE;
481
482 }
483
484 };