fixes compile
[platform/upstream/ibus-libpinyin.git] / src / PYPBopomofoEngine.cc
1 /* vim:set et ts=4 sts=4:
2  *
3  * ibus-libpinyin - Intelligent Pinyin engine based on libpinyin 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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 or Ctrl + 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         gboolean triggered = FALSE;
73
74         if (m_prev_pressed_key == keyval) {
75             if (LibPinyinBopomofoConfig::instance ().ctrlSwitch ()) {
76                 if (keyval == IBUS_Control_L || keyval == IBUS_Control_R)
77                     triggered = TRUE;
78             } else {
79                 if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R)
80                     triggered = TRUE;
81             }
82         }
83
84         if (triggered) {
85             if (!m_editors[MODE_INIT]->text ().empty ())
86                 m_editors[MODE_INIT]->reset ();
87             m_props.toggleModeChinese ();
88             return TRUE;
89         }
90
91         if (m_input_mode == MODE_INIT &&
92             m_editors[MODE_INIT]->text ().empty ()) {
93             /* If it is init mode, and no any previous input text,
94              * we will let client applications to handle release key event */
95             return FALSE;
96         } else {
97             return TRUE;
98         }
99     }
100
101     /* Toggle simp/trad Chinese Mode when hotkey Ctrl + Shift + F pressed */
102     if (keyval == IBUS_F && scmshm_test (modifiers, (IBUS_SHIFT_MASK | IBUS_CONTROL_MASK))) {
103         m_props.toggleModeSimp();
104         m_prev_pressed_key = IBUS_F;
105         return TRUE;
106     }
107
108     if (m_props.modeChinese ()) {
109         if (G_UNLIKELY (m_input_mode == MODE_INIT &&
110                         m_editors[MODE_INIT]->text ().empty () &&
111                         cmshm_filter (modifiers) == 0 &&
112                         keyval == IBUS_grave)){
113             /* if BopomofoEditor is empty and get a grave key,
114              * switch current editor to PunctEditor */
115             m_input_mode = MODE_PUNCT;
116         }
117
118         retval = m_editors[m_input_mode]->processKeyEvent (keyval, keycode, modifiers);
119         if (G_UNLIKELY (retval &&
120                         m_input_mode != MODE_INIT &&
121                         m_editors[m_input_mode]->text ().empty ()))
122             m_input_mode = MODE_INIT;
123     }
124
125     if (G_UNLIKELY (!retval))
126         retval = m_fallback_editor->processKeyEvent (keyval, keycode, modifiers);
127
128     /* store ignored key event by editors */
129     m_prev_pressed_key = retval ? IBUS_VoidSymbol : keyval;
130
131     return retval;
132 }
133
134 void
135 LibPinyinBopomofoEngine::focusIn (void)
136 {
137     registerProperties (m_props.properties ());
138 }
139
140 void
141 LibPinyinBopomofoEngine::focusOut (void)
142 {
143     reset ();
144 }
145
146 void
147 LibPinyinBopomofoEngine::reset (void)
148 {
149     m_prev_pressed_key = IBUS_VoidSymbol;
150     m_input_mode = MODE_INIT;
151     for (gint i = 0; i < MODE_LAST; i++) {
152         m_editors[i]->reset ();
153     }
154     m_fallback_editor->reset ();
155 }
156
157 void
158 LibPinyinBopomofoEngine::enable (void)
159 {
160     m_props.reset ();
161 }
162
163 void
164 LibPinyinBopomofoEngine::disable (void)
165 {
166 }
167
168 void
169 LibPinyinBopomofoEngine::pageUp (void)
170 {
171     m_editors[m_input_mode]->pageUp ();
172 }
173
174 void
175 LibPinyinBopomofoEngine::pageDown (void)
176 {
177     m_editors[m_input_mode]->pageDown ();
178 }
179
180 void
181 LibPinyinBopomofoEngine::cursorUp (void)
182 {
183     m_editors[m_input_mode]->cursorUp ();
184 }
185
186 void
187 LibPinyinBopomofoEngine::cursorDown (void)
188 {
189     m_editors[m_input_mode]->cursorDown ();
190 }
191
192 inline void
193 LibPinyinBopomofoEngine::showSetupDialog (void)
194 {
195     g_spawn_command_line_async
196         (LIBEXECDIR"/ibus-setup-libpinyin bopomofo", NULL);
197 }
198
199 gboolean
200 LibPinyinBopomofoEngine::propertyActivate (const gchar *prop_name,
201                                            guint prop_state)
202 {
203     const static std::string setup ("setup");
204     if (m_props.propertyActivate (prop_name, prop_state)) {
205         return TRUE;
206     }
207     else if (setup == prop_name) {
208         showSetupDialog ();
209         return TRUE;
210     }
211     return FALSE;
212 }
213
214 void
215 LibPinyinBopomofoEngine::candidateClicked (guint index,
216                                            guint button,
217                                            guint state)
218 {
219     m_editors[m_input_mode]->candidateClicked (index, button, state);
220 }
221
222 void
223 LibPinyinBopomofoEngine::commitText (Text & text)
224 {
225     Engine::commitText (text);
226     if (m_input_mode != MODE_INIT)
227         m_input_mode = MODE_INIT;
228 #if 1
229     /* handle "<num>+.<num>+" here */
230     if (text.text ())
231         static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (*text.text ());
232     else
233         static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (0);
234 #endif
235 }
236
237 void
238 LibPinyinBopomofoEngine::connectEditorSignals (EditorPtr editor)
239 {
240     editor->signalCommitText ().connect (
241         std::bind (&LibPinyinBopomofoEngine::commitText, this, _1));
242
243     editor->signalUpdatePreeditText ().connect (
244         std::bind (&LibPinyinBopomofoEngine::updatePreeditText, this, _1, _2, _3));
245     editor->signalShowPreeditText ().connect (
246         std::bind (&LibPinyinBopomofoEngine::showPreeditText, this));
247     editor->signalHidePreeditText ().connect (
248         std::bind (&LibPinyinBopomofoEngine::hidePreeditText, this));
249
250     editor->signalUpdateAuxiliaryText ().connect (
251         std::bind (&LibPinyinBopomofoEngine::updateAuxiliaryText, this, _1, _2));
252     editor->signalShowAuxiliaryText ().connect (
253         std::bind (&LibPinyinBopomofoEngine::showAuxiliaryText, this));
254     editor->signalHideAuxiliaryText ().connect (
255         std::bind (&LibPinyinBopomofoEngine::hideAuxiliaryText, this));
256
257     editor->signalUpdateLookupTable ().connect (
258         std::bind (&LibPinyinBopomofoEngine::updateLookupTable, this, _1, _2));
259     editor->signalUpdateLookupTableFast ().connect (
260         std::bind (&LibPinyinBopomofoEngine::updateLookupTableFast, this, _1, _2));
261     editor->signalShowLookupTable ().connect (
262         std::bind (&LibPinyinBopomofoEngine::showLookupTable, this));
263     editor->signalHideLookupTable ().connect (
264         std::bind (&LibPinyinBopomofoEngine::hideLookupTable, this));
265 }
266
267