1 /* vim:set et ts=4 sts=4:
3 * ibus-pinyin - The Chinese PinYin engine for IBus
5 * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
6 * Copyright (c) 2011 Peng Wu <alexepico@gmail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "PYPPinyinEngine.h"
25 #include "PYPConfig.h"
26 #include "PYPunctEditor.h"
27 #include "PYRawEditor.h"
28 #ifdef IBUS_BUILD_LUA_EXTENSION
29 #include "PYExtEditor.h"
31 #ifdef IBUS_BUILD_ENGLISH_INPUT_MODE
32 #include "PYEnglishEditor.h"
34 #include "PYPFullPinyinEditor.h"
35 #include "PYPDoublePinyinEditor.h"
36 #include "PYFallbackEditor.h"
41 LibPinyinPinyinEngine::LibPinyinPinyinEngine (IBusEngine *engine)
43 m_props (LibPinyinPinyinConfig::instance ()),
44 m_prev_pressed_key (IBUS_VoidSymbol),
45 m_input_mode (MODE_INIT),
46 m_fallback_editor (new FallbackEditor (m_props, LibPinyinPinyinConfig::instance ()))
50 m_double_pinyin = LibPinyinPinyinConfig::instance ().doublePinyin ();
53 m_editors[MODE_INIT].reset
54 (new LibPinyinDoublePinyinEditor (m_props, LibPinyinPinyinConfig::instance ()));
56 m_editors[MODE_INIT].reset
57 (new LibPinyinFullPinyinEditor (m_props, LibPinyinPinyinConfig::instance ()));
59 m_editors[MODE_PUNCT].reset
60 (new PunctEditor (m_props, LibPinyinPinyinConfig::instance ()));
61 m_editors[MODE_RAW].reset
62 (new RawEditor (m_props, LibPinyinPinyinConfig::instance ()));
64 #ifdef IBUS_BUILD_LUA_EXTENSION
65 m_editors[MODE_EXTENSION].reset (new ExtEditor (m_props, LibPinyinPinyinConfig::instance ()));
67 m_editors[MODE_EXTENSION].reset (new Editor (m_props, LibPinyinPinyinConfig::instance ()));
69 #ifdef IBUS_BUILD_ENGLISH_INPUT_MODE
70 m_editors[MODE_ENGLISH].reset (new EnglishEditor (m_props, LibPinyinPinyinConfig::instance ()));
72 m_editors[MODE_ENGLISH].reset (new Editor (m_props, LibPinyinPinyinConfig::instance ()));
75 m_props.signalUpdateProperty ().connect
76 (std::bind (&LibPinyinPinyinEngine::updateProperty, this, _1));
78 for (i = MODE_INIT; i < MODE_LAST; i++) {
79 connectEditorSignals (m_editors[i]);
82 connectEditorSignals (m_fallback_editor);
86 LibPinyinPinyinEngine::~LibPinyinPinyinEngine (void)
91 LibPinyinPinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modifiers)
93 gboolean retval = FALSE;
95 /* check Shift + Release hotkey,
96 * and then ignore other Release key event */
97 if (modifiers & IBUS_RELEASE_MASK) {
98 /* press and release keyval are same,
99 * and no other key event between the press and release key event */
100 if (m_prev_pressed_key == keyval){
101 if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R) {
102 if (!m_editors[MODE_INIT]->text ().empty ())
103 m_editors[MODE_INIT]->reset ();
104 m_props.toggleModeChinese ();
109 if (m_input_mode == MODE_INIT &&
110 m_editors[MODE_INIT]->text ().empty ()) {
111 /* If it is in init mode, and no any previous input text,
112 * we will let client applications to handle release key event */
120 /* Toggle simp/trad Chinese Mode when hotkey Ctrl + Shift + F pressed */
121 if (keyval == IBUS_F && scmshm_test (modifiers, (IBUS_SHIFT_MASK | IBUS_CONTROL_MASK))) {
122 m_props.toggleModeSimp ();
123 m_prev_pressed_key = IBUS_F;
127 if (m_props.modeChinese ()) {
128 if (m_input_mode == MODE_INIT &&
129 (cmshm_filter (modifiers) == 0)) {
130 const String & text = m_editors[MODE_INIT]->text ();
134 m_input_mode = MODE_PUNCT;
136 #ifdef IBUS_BUILD_LUA_EXTENSION
138 // do not enable lua extension when use double pinyin.
139 if (LibPinyinPinyinConfig::instance ().doublePinyin ())
141 m_input_mode = MODE_EXTENSION;
144 #ifdef IBUS_BUILD_ENGLISH_INPUT_MODE
146 // do not enable english mode when use double pinyin.
147 if (LibPinyinPinyinConfig::instance ().doublePinyin ())
149 m_input_mode = MODE_ENGLISH;
157 retval = m_editors[m_input_mode]->processKeyEvent (keyval, keycode, modifiers);
158 if (G_UNLIKELY (retval &&
159 m_input_mode != MODE_INIT &&
160 m_editors[m_input_mode]->text ().empty ()))
161 m_input_mode = MODE_INIT;
164 if (G_UNLIKELY (!retval))
165 retval = m_fallback_editor->processKeyEvent (keyval, keycode, modifiers);
167 /* store ignored key event by editors */
168 m_prev_pressed_key = retval ? IBUS_VoidSymbol : keyval;
174 LibPinyinPinyinEngine::focusIn (void)
176 /* TODO: check memory leak here,
177 * or switch full/double pinyin when pinyin config is changed.*/
178 if (LibPinyinPinyinConfig::instance ().doublePinyin ()) {
179 if (!m_double_pinyin) {
180 m_editors[MODE_INIT].reset (new LibPinyinDoublePinyinEditor (m_props, LibPinyinPinyinConfig::instance ()));
181 connectEditorSignals (m_editors[MODE_INIT]);
183 m_double_pinyin = TRUE;
186 if (m_double_pinyin) {
187 m_editors[MODE_INIT].reset (new LibPinyinFullPinyinEditor (m_props, LibPinyinPinyinConfig::instance ()));
188 connectEditorSignals (m_editors[MODE_INIT]);
190 m_double_pinyin = FALSE;
193 registerProperties (m_props.properties ());
197 LibPinyinPinyinEngine::focusOut (void)
203 LibPinyinPinyinEngine::reset (void)
205 m_prev_pressed_key = IBUS_VoidSymbol;
206 m_input_mode = MODE_INIT;
207 for (gint i = 0; i < MODE_LAST; i++) {
208 m_editors[i]->reset ();
210 m_fallback_editor->reset ();
214 LibPinyinPinyinEngine::enable (void)
220 LibPinyinPinyinEngine::disable (void)
225 LibPinyinPinyinEngine::pageUp (void)
227 m_editors[m_input_mode]->pageUp ();
231 LibPinyinPinyinEngine::pageDown (void)
233 m_editors[m_input_mode]->pageDown ();
237 LibPinyinPinyinEngine::cursorUp (void)
239 m_editors[m_input_mode]->cursorUp ();
243 LibPinyinPinyinEngine::cursorDown (void)
245 m_editors[m_input_mode]->cursorDown ();
249 LibPinyinPinyinEngine::showSetupDialog (void)
251 g_spawn_command_line_async
252 (LIBEXECDIR"/ibus-setup-libpinyin pinyin", NULL);
256 LibPinyinPinyinEngine::propertyActivate (const char *prop_name, guint prop_state)
258 const static String setup ("setup");
259 if (m_props.propertyActivate (prop_name, prop_state)) {
262 else if (setup == prop_name) {
270 LibPinyinPinyinEngine::candidateClicked (guint index, guint button, guint state)
272 m_editors[m_input_mode]->candidateClicked (index, button, state);
276 LibPinyinPinyinEngine::commitText (Text & text)
278 Engine::commitText (text);
279 if (m_input_mode != MODE_INIT)
280 m_input_mode = MODE_INIT;
282 /* handle "<num>+.<num>+" here */
284 static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (*text.text ());
286 static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (0);
291 LibPinyinPinyinEngine::connectEditorSignals (EditorPtr editor)
293 editor->signalCommitText ().connect (
294 std::bind (&LibPinyinPinyinEngine::commitText, this, _1));
296 editor->signalUpdatePreeditText ().connect (
297 std::bind (&LibPinyinPinyinEngine::updatePreeditText, this, _1, _2, _3));
298 editor->signalShowPreeditText ().connect (
299 std::bind (&LibPinyinPinyinEngine::showPreeditText, this));
300 editor->signalHidePreeditText ().connect (
301 std::bind (&LibPinyinPinyinEngine::hidePreeditText, this));
303 editor->signalUpdateAuxiliaryText ().connect (
304 std::bind (&LibPinyinPinyinEngine::updateAuxiliaryText, this, _1, _2));
305 editor->signalShowAuxiliaryText ().connect (
306 std::bind (&LibPinyinPinyinEngine::showAuxiliaryText, this));
307 editor->signalHideAuxiliaryText ().connect (
308 std::bind (&LibPinyinPinyinEngine::hideAuxiliaryText, this));
310 editor->signalUpdateLookupTable ().connect (
311 std::bind (&LibPinyinPinyinEngine::updateLookupTable, this, _1, _2));
312 editor->signalUpdateLookupTableFast ().connect (
313 std::bind (&LibPinyinPinyinEngine::updateLookupTableFast, this, _1, _2));
314 editor->signalShowLookupTable ().connect (
315 std::bind (&LibPinyinPinyinEngine::showLookupTable, this));
316 editor->signalHideLookupTable ().connect (
317 std::bind (&LibPinyinPinyinEngine::hideLookupTable, this));