summaryrefslogtreecommitdiffstats
path: root/src/PYPPinyinEngine.cc
diff options
context:
space:
mode:
authorPeng Wu <alexepico@gmail.com>2011-09-28 17:09:11 +0800
committerPeng Wu <alexepico@gmail.com>2011-12-22 12:23:13 +0800
commit1de241261875c35144a0a732849e057bc9bcc962 (patch)
tree54627edfe784329ef900b503c30f73acec749ac1 /src/PYPPinyinEngine.cc
parent3497f64da0b6b6e7ffb85769b05e49f04221b08f (diff)
downloadibus-libpinyin-1de241261875c35144a0a732849e057bc9bcc962.tar.gz
ibus-libpinyin-1de241261875c35144a0a732849e057bc9bcc962.tar.xz
ibus-libpinyin-1de241261875c35144a0a732849e057bc9bcc962.zip
add libpinyin pinyin engine
Diffstat (limited to 'src/PYPPinyinEngine.cc')
-rw-r--r--src/PYPPinyinEngine.cc325
1 files changed, 325 insertions, 0 deletions
diff --git a/src/PYPPinyinEngine.cc b/src/PYPPinyinEngine.cc
new file mode 100644
index 0000000..2877702
--- /dev/null
+++ b/src/PYPPinyinEngine.cc
@@ -0,0 +1,325 @@
+/* vim:set et ts=4 sts=4:
+ *
+ * ibus-pinyin - The Chinese PinYin engine for IBus
+ *
+ * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (c) 2011 Peng Wu <alexepico@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "PYPPinyinEngine.h"
+#include <string>
+#include "PYConfig.h"
+#include "PYPunctEditor.h"
+#include "PYRawEditor.h"
+#ifdef IBUS_BUILD_LUA_EXTENSION
+#include "PYExtEditor.h"
+#endif
+#ifdef IBUS_BUILD_ENGLISH_INPUT_MODE
+#include "PYEnglishEditor.h"
+#endif
+#include "PYPFullPinyinEditor.h"
+#include "PYPDoublePinyinEditor.h"
+#include "PYFallbackEditor.h"
+
+using namespace PY;
+
+/* constructor */
+LibPinyinPinyinEngine::LibPinyinPinyinEngine (IBusEngine *engine)
+ : Engine (engine),
+ m_props (PinyinConfig::instance ()),
+ m_prev_pressed_key (IBUS_VoidSymbol),
+ m_input_mode (MODE_INIT),
+ m_fallback_editor (new FallbackEditor (m_props, PinyinConfig::instance ()))
+{
+ gint i;
+
+ if (PinyinConfig::instance ().doublePinyin ())
+ m_editors[MODE_INIT].reset
+ (new LibPinyinDoublePinyinEditor (m_props, PinyinConfig::instance ()));
+ else
+ m_editors[MODE_INIT].reset
+ (new LibPinyinFullPinyinEditor (m_props, PinyinConfig::instance ()));
+
+ m_editors[MODE_PUNCT].reset
+ (new PunctEditor (m_props, PinyinConfig::instance ()));
+ m_editors[MODE_RAW].reset
+ (new RawEditor (m_props, PinyinConfig::instance ()));
+
+#ifdef IBUS_BUILD_LUA_EXTENSION
+ m_editors[MODE_EXTENSION].reset (new ExtEditor (m_props, PinyinConfig::instance ()));
+#else
+ m_editors[MODE_EXTENSION].reset (new Editor (m_props, PinyinConfig::instance ()));
+#endif
+#ifdef IBUS_BUILD_ENGLISH_INPUT_MODE
+ m_editors[MODE_ENGLISH].reset (new EnglishEditor (m_props, PinyinConfig::instance ()));
+#else
+ m_editors[MODE_ENGLISH].reset (new Editor (m_props, PinyinConfig::instance ()));
+#endif
+
+ m_props.signalUpdateProperty ().connect
+ (std::bind (&LibPinyinPinyinEngine::updateProperty, this, _1));
+
+ for (i = MODE_INIT; i < MODE_LAST; i++) {
+ connectEditorSignals (m_editors[i]);
+ }
+
+ connectEditorSignals (m_fallback_editor);
+}
+
+/* destructor */
+LibPinyinPinyinEngine::~LibPinyinPinyinEngine (void)
+{
+}
+
+gboolean
+LibPinyinPinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modifiers)
+{
+ gboolean retval = FALSE;
+
+ /* check Shift + Release hotkey,
+ * and then ignore other Release key event */
+ if (modifiers & IBUS_RELEASE_MASK) {
+ /* press and release keyval are same,
+ * and no other key event between the press and release key event */
+ if (m_prev_pressed_key == keyval){
+ if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R) {
+ if (!m_editors[MODE_INIT]->text ().empty ())
+ m_editors[MODE_INIT]->reset ();
+ m_props.toggleModeChinese ();
+ return TRUE;
+ }
+ }
+
+ if (m_input_mode == MODE_INIT &&
+ m_editors[MODE_INIT]->text ().empty ()) {
+ /* If it is in init mode, and no any previous input text,
+ * we will let client applications to handle release key event */
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+ }
+
+ /* Toggle simp/trad Chinese Mode when hotkey Ctrl + Shift + F pressed */
+ if (keyval == IBUS_F && scmshm_test (modifiers, (IBUS_SHIFT_MASK | IBUS_CONTROL_MASK))) {
+ m_props.toggleModeSimp ();
+ m_prev_pressed_key = IBUS_F;
+ return TRUE;
+ }
+
+ if (m_props.modeChinese ()) {
+ if (m_input_mode == MODE_INIT &&
+ (cmshm_filter (modifiers) == 0)) {
+ const String & text = m_editors[MODE_INIT]->text ();
+ if (text.empty ()) {
+ switch (keyval) {
+ case IBUS_grave:
+ m_input_mode = MODE_PUNCT;
+ break;
+#ifdef IBUS_BUILD_LUA_EXTENSION
+ case IBUS_i:
+ // do not enable lua extension when use double pinyin.
+ if (PinyinConfig::instance ().doublePinyin ())
+ break;
+ m_input_mode = MODE_EXTENSION;
+ break;
+#endif
+#ifdef IBUS_BUILD_ENGLISH_INPUT_MODE
+ case IBUS_v:
+ // do not enable english mode when use double pinyin.
+ if (PinyinConfig::instance ().doublePinyin ())
+ break;
+ m_input_mode = MODE_ENGLISH;
+ break;
+#endif
+ }
+ } else {
+ if (m_prev_pressed_key != IBUS_period) {
+ if ((keyval == IBUS_at || keyval == IBUS_colon)) {
+ m_input_mode = MODE_RAW;
+ m_editors[MODE_RAW]->setText (text, text.length ());
+ m_editors[MODE_INIT]->reset ();
+ }
+ }
+ else {
+ if ((keyval >= IBUS_a && keyval <= IBUS_z) ||
+ (keyval >= IBUS_A && keyval <= IBUS_Z)) {
+ String tmp = text;
+ tmp += ".";
+ m_input_mode = MODE_RAW;
+ m_editors[MODE_RAW]->setText (tmp, tmp.length ());
+ m_editors[MODE_INIT]->reset ();
+ }
+ }
+ }
+ }
+ retval = m_editors[m_input_mode]->processKeyEvent (keyval, keycode, modifiers);
+ if (G_UNLIKELY (retval &&
+ m_input_mode != MODE_INIT &&
+ m_editors[m_input_mode]->text ().empty ()))
+ m_input_mode = MODE_INIT;
+ }
+
+ if (G_UNLIKELY (!retval))
+ retval = m_fallback_editor->processKeyEvent (keyval, keycode, modifiers);
+
+ /* store ignored key event by editors */
+ m_prev_pressed_key = retval ? IBUS_VoidSymbol : keyval;
+
+ return retval;
+}
+
+void
+LibPinyinPinyinEngine::focusIn (void)
+{
+ /* TODO: check memory leak here,
+ * or switch full/double pinyin when pinyin config is changed.*/
+ if (PinyinConfig::instance ().doublePinyin ()) {
+ if (dynamic_cast <LibPinyinDoublePinyinEditor *> (m_editors[MODE_INIT].get ()) == NULL) {
+ m_editors[MODE_INIT].reset (new LibPinyinDoublePinyinEditor (m_props, PinyinConfig::instance ()));
+ connectEditorSignals (m_editors[MODE_INIT]);
+ }
+ }
+ else {
+ if (dynamic_cast <LibPinyinFullPinyinEditor *> (m_editors[MODE_INIT].get ()) == NULL) {
+ m_editors[MODE_INIT].reset (new LibPinyinFullPinyinEditor (m_props, PinyinConfig::instance ()));
+ connectEditorSignals (m_editors[MODE_INIT]);
+ }
+ }
+ registerProperties (m_props.properties ());
+}
+
+void
+LibPinyinPinyinEngine::focusOut (void)
+{
+ reset ();
+}
+
+void
+LibPinyinPinyinEngine::reset (void)
+{
+ m_prev_pressed_key = IBUS_VoidSymbol;
+ m_input_mode = MODE_INIT;
+ for (gint i = 0; i < MODE_LAST; i++) {
+ m_editors[i]->reset ();
+ }
+ m_fallback_editor->reset ();
+}
+
+void
+LibPinyinPinyinEngine::enable (void)
+{
+ m_props.reset ();
+}
+
+void
+LibPinyinPinyinEngine::disable (void)
+{
+}
+
+void
+LibPinyinPinyinEngine::pageUp (void)
+{
+ m_editors[m_input_mode]->pageUp ();
+}
+
+void
+LibPinyinPinyinEngine::pageDown (void)
+{
+ m_editors[m_input_mode]->pageDown ();
+}
+
+void
+LibPinyinPinyinEngine::cursorUp (void)
+{
+ m_editors[m_input_mode]->cursorUp ();
+}
+
+void
+LibPinyinPinyinEngine::cursorDown (void)
+{
+ m_editors[m_input_mode]->cursorDown ();
+}
+
+inline void
+LibPinyinPinyinEngine::showSetupDialog (void)
+{
+ /* TODO: to be implemented */
+ g_assert (FALSE);
+}
+
+gboolean
+LibPinyinPinyinEngine::propertyActivate (const char *prop_name, guint prop_state)
+{
+ const static String setup ("setup");
+ if (m_props.propertyActivate (prop_name, prop_state)) {
+ return TRUE;
+ }
+ else if (setup == prop_name) {
+ showSetupDialog ();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+LibPinyinPinyinEngine::candidateClicked (guint index, guint button, guint state)
+{
+ m_editors[m_input_mode]->candidateClicked (index, button, state);
+}
+
+void
+LibPinyinPinyinEngine::commitText (Text & text)
+{
+ Engine::commitText (text);
+ if (m_input_mode != MODE_INIT)
+ m_input_mode = MODE_INIT;
+ if (text.text ())
+ static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (*text.text ());
+ else
+ static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (0);
+}
+
+void
+LibPinyinPinyinEngine::connectEditorSignals (EditorPtr editor)
+{
+ editor->signalCommitText ().connect (
+ std::bind (&LibPinyinPinyinEngine::commitText, this, _1));
+
+ editor->signalUpdatePreeditText ().connect (
+ std::bind (&LibPinyinPinyinEngine::updatePreeditText, this, _1, _2, _3));
+ editor->signalShowPreeditText ().connect (
+ std::bind (&LibPinyinPinyinEngine::showPreeditText, this));
+ editor->signalHidePreeditText ().connect (
+ std::bind (&LibPinyinPinyinEngine::hidePreeditText, this));
+
+ editor->signalUpdateAuxiliaryText ().connect (
+ std::bind (&LibPinyinPinyinEngine::updateAuxiliaryText, this, _1, _2));
+ editor->signalShowAuxiliaryText ().connect (
+ std::bind (&LibPinyinPinyinEngine::showAuxiliaryText, this));
+ editor->signalHideAuxiliaryText ().connect (
+ std::bind (&LibPinyinPinyinEngine::hideAuxiliaryText, this));
+
+ editor->signalUpdateLookupTable ().connect (
+ std::bind (&LibPinyinPinyinEngine::updateLookupTable, this, _1, _2));
+ editor->signalUpdateLookupTableFast ().connect (
+ std::bind (&LibPinyinPinyinEngine::updateLookupTableFast, this, _1, _2));
+ editor->signalShowLookupTable ().connect (
+ std::bind (&LibPinyinPinyinEngine::showLookupTable, this));
+ editor->signalHideLookupTable ().connect (
+ std::bind (&LibPinyinPinyinEngine::hideLookupTable, this));
+}