clean db
[platform/upstream/ibus-libpinyin.git] / src / PYPBopomofoEngine.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  * Copyright (c) 2010 BYVoid <byvoid1@gmail.com>
7  * Copyright (c) 2011 Peng Wu <alexepico@gmail.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 #include "PYPBopomofoEngine.h"
24 #include <string>
25 #include "PYPunctEditor.h"
26 #include "PYPBopomofoEditor.h"
27 #include "PYFallbackEditor.h"
28 #include "PYConfig.h"
29 #include "PYPConfig.h"
30
31 using namespace PY;
32
33 /* constructor */
34 LibPinyinBopomofoEngine::LibPinyinBopomofoEngine (IBusEngine *engine)
35     : Engine (engine),
36       m_props (LibPinyinBopomofoConfig::instance ()),
37       m_prev_pressed_key (IBUS_VoidSymbol),
38       m_input_mode (MODE_INIT),
39       m_fallback_editor (new FallbackEditor (m_props, LibPinyinBopomofoConfig::instance()))
40 {
41     gint i;
42
43     /* create editors */
44     m_editors[MODE_INIT].reset (new LibPinyinBopomofoEditor (m_props, LibPinyinBopomofoConfig::instance ()));
45     m_editors[MODE_PUNCT].reset (new PunctEditor (m_props, LibPinyinBopomofoConfig::instance ()));
46
47     m_props.signalUpdateProperty ().connect
48         (std::bind (&LibPinyinBopomofoEngine::updateProperty, this, _1));
49
50     for (i = MODE_INIT; i < MODE_LAST; i++) {
51         connectEditorSignals (m_editors[i]);
52     }
53
54     connectEditorSignals (m_fallback_editor);
55 }
56
57 /* destructor */
58 LibPinyinBopomofoEngine::~LibPinyinBopomofoEngine (void)
59 {
60 }
61
62 gboolean
63 LibPinyinBopomofoEngine::processKeyEvent (guint keyval, guint keycode, guint modifiers)
64 {
65     gboolean retval = FALSE;
66
67     /* check Shift + Release hotkey,
68      * and then ignore other Release key event */
69     if (modifiers & IBUS_RELEASE_MASK) {
70         /* press and release keyval are same,
71          * and no other key event between the press and release key event */
72         if (m_prev_pressed_key == keyval) {
73             if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R) {
74                 if (!m_editors[MODE_INIT]->text ().empty ())
75                     m_editors[MODE_INIT]->reset ();
76                 m_props.toggleModeChinese ();
77                 return TRUE;
78             }
79         }
80
81         if (m_input_mode == MODE_INIT &&
82             m_editors[MODE_INIT]->text ().empty ()) {
83             /* If it is init mode, and no any previous input text,
84              * we will let client applications to handle release key event */
85             return FALSE;
86         } else {
87             return TRUE;
88         }
89     }
90
91     /* Toggle simp/trad Chinese Mode when hotkey Ctrl + Shift + F pressed */
92     if (keyval == IBUS_F && scmshm_test (modifiers, (IBUS_SHIFT_MASK | IBUS_CONTROL_MASK))) {
93         m_props.toggleModeSimp();
94         m_prev_pressed_key = IBUS_F;
95         return TRUE;
96     }
97
98     if (m_props.modeChinese ()) {
99         if (G_UNLIKELY (m_input_mode == MODE_INIT &&
100                         m_editors[MODE_INIT]->text ().empty () &&
101                         cmshm_filter (modifiers) == 0 &&
102                         keyval == IBUS_grave)){
103             /* if BopomofoEditor is empty and get a grave key,
104              * switch current editor to PunctEditor */
105             m_input_mode = MODE_PUNCT;
106         }
107
108         retval = m_editors[m_input_mode]->processKeyEvent (keyval, keycode, modifiers);
109         if (G_UNLIKELY (retval &&
110                         m_input_mode != MODE_INIT &&
111                         m_editors[m_input_mode]->text ().empty ()))
112             m_input_mode = MODE_INIT;
113     }
114
115     if (G_UNLIKELY (!retval))
116         retval = m_fallback_editor->processKeyEvent (keyval, keycode, modifiers);
117
118     /* store ignored key event by editors */
119     m_prev_pressed_key = retval ? IBUS_VoidSymbol : keyval;
120
121     return retval;
122 }
123
124 void
125 LibPinyinBopomofoEngine::focusIn (void)
126 {
127     registerProperties (m_props.properties ());
128 }
129
130 void
131 LibPinyinBopomofoEngine::focusOut (void)
132 {
133     reset ();
134 }
135
136 void
137 LibPinyinBopomofoEngine::reset (void)
138 {
139     m_prev_pressed_key = IBUS_VoidSymbol;
140     m_input_mode = MODE_INIT;
141     for (gint i = 0; i < MODE_LAST; i++) {
142         m_editors[i]->reset ();
143     }
144     m_fallback_editor->reset ();
145 }
146
147 void
148 LibPinyinBopomofoEngine::enable (void)
149 {
150     m_props.reset ();
151 }
152
153 void
154 LibPinyinBopomofoEngine::disable (void)
155 {
156 }
157
158 void
159 LibPinyinBopomofoEngine::pageUp (void)
160 {
161     m_editors[m_input_mode]->pageUp ();
162 }
163
164 void
165 LibPinyinBopomofoEngine::pageDown (void)
166 {
167     m_editors[m_input_mode]->pageDown ();
168 }
169
170 void
171 LibPinyinBopomofoEngine::cursorUp (void)
172 {
173     m_editors[m_input_mode]->cursorUp ();
174 }
175
176 void
177 LibPinyinBopomofoEngine::cursorDown (void)
178 {
179     m_editors[m_input_mode]->cursorDown ();
180 }
181
182 inline void
183 LibPinyinBopomofoEngine::showSetupDialog (void)
184 {
185     g_spawn_command_line_async
186         (LIBEXECDIR"/ibus-setup-libpinyin bopomofo", NULL);
187 }
188
189 gboolean
190 LibPinyinBopomofoEngine::propertyActivate (const gchar *prop_name,
191                                            guint prop_state)
192 {
193     const static std::string setup ("setup");
194     if (m_props.propertyActivate (prop_name, prop_state)) {
195         return TRUE;
196     }
197     else if (setup == prop_name) {
198         showSetupDialog ();
199         return TRUE;
200     }
201     return FALSE;
202 }
203
204 void
205 LibPinyinBopomofoEngine::candidateClicked (guint index,
206                                            guint button,
207                                            guint state)
208 {
209     m_editors[m_input_mode]->candidateClicked (index, button, state);
210 }
211
212 void
213 LibPinyinBopomofoEngine::commitText (Text & text)
214 {
215     Engine::commitText (text);
216     if (m_input_mode != MODE_INIT)
217         m_input_mode = MODE_INIT;
218 #if 1
219     /* handle "<num>+.<num>+" here */
220     if (text.text ())
221         static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (*text.text ());
222     else
223         static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (0);
224 #endif
225 }
226
227 void
228 LibPinyinBopomofoEngine::connectEditorSignals (EditorPtr editor)
229 {
230     editor->signalCommitText ().connect (
231         std::bind (&LibPinyinBopomofoEngine::commitText, this, _1));
232
233     editor->signalUpdatePreeditText ().connect (
234         std::bind (&LibPinyinBopomofoEngine::updatePreeditText, this, _1, _2, _3));
235     editor->signalShowPreeditText ().connect (
236         std::bind (&LibPinyinBopomofoEngine::showPreeditText, this));
237     editor->signalHidePreeditText ().connect (
238         std::bind (&LibPinyinBopomofoEngine::hidePreeditText, this));
239
240     editor->signalUpdateAuxiliaryText ().connect (
241         std::bind (&LibPinyinBopomofoEngine::updateAuxiliaryText, this, _1, _2));
242     editor->signalShowAuxiliaryText ().connect (
243         std::bind (&LibPinyinBopomofoEngine::showAuxiliaryText, this));
244     editor->signalHideAuxiliaryText ().connect (
245         std::bind (&LibPinyinBopomofoEngine::hideAuxiliaryText, this));
246
247     editor->signalUpdateLookupTable ().connect (
248         std::bind (&LibPinyinBopomofoEngine::updateLookupTable, this, _1, _2));
249     editor->signalUpdateLookupTableFast ().connect (
250         std::bind (&LibPinyinBopomofoEngine::updateLookupTableFast, this, _1, _2));
251     editor->signalShowLookupTable ().connect (
252         std::bind (&LibPinyinBopomofoEngine::showLookupTable, this));
253     editor->signalHideLookupTable ().connect (
254         std::bind (&LibPinyinBopomofoEngine::hideLookupTable, this));
255 }
256
257