[ibus-pinyin] add integration patch
Peng Wu
pwu at fedoraproject.org
Thu Oct 27 04:47:37 UTC 2011
commit 1cc5988ae82a47995b7baf96ce5502b33e1f30a4
Author: Peng Wu <alexepico at gmail.com>
Date: Thu Oct 27 12:47:21 2011 +0800
add integration patch
ibus-pinyin-libpinyin-integration.patch | 9524 +++++++++++++++++++++++++++++++
ibus-pinyin-xx-icon-symbol.patch | 24 +-
ibus-pinyin.spec | 7 +-
3 files changed, 9531 insertions(+), 24 deletions(-)
---
diff --git a/ibus-pinyin-libpinyin-integration.patch b/ibus-pinyin-libpinyin-integration.patch
new file mode 100644
index 0000000..d609be5
--- /dev/null
+++ b/ibus-pinyin-libpinyin-integration.patch
@@ -0,0 +1,9524 @@
+From 94bbc5c2f29f2d1e73c202dee9ca30b8ddc01c21 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 29 Aug 2011 14:14:46 +0800
+Subject: [PATCH 01/71] begin to integrate
+
+---
+ src/PYPinyinBaseEditor.h | 91 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 91 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPinyinBaseEditor.h
+
+diff --git a/src/PYPinyinBaseEditor.h b/src/PYPinyinBaseEditor.h
+new file mode 100644
+index 0000000..0bed00a
+--- /dev/null
++++ b/src/PYPinyinBaseEditor.h
+@@ -0,0 +1,91 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_PINYIN_BASE_EDITOR_H_
++#define __PY_PINYIN_BASE_EDITOR_H_
++
++#include <libpinyin.h>
++#include "PYLookupTable.h"
++#include "PYEditor.h"
++#include "PYPinyinParser.h"
++#include "PYSpecialPhraseTable.h"
++
++namespace PY {
++
++class PinyinBaseEditor : public Editor {
++public:
++ PinyinBaseEditor (PinyinProperties & props, Config & config);
++
++public:
++ /* virtual functions */
++ virtual void pageUp (void);
++ virtual void pageDown (void);
++ virtual void cursorUp (void);
++ virtual void cursorDown (void);
++ virtual void update (void);
++ virtual void reset (void);
++ virtual void candidateClicked (guint index, guint button, guint state);
++ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ virtual gboolean processSpace (guint keyval, guint keycode, guint modifiers);
++ virtual gboolean processFunctionKey (guint keyval, guint keycode, guint modifiers);
++ virtual void updateLookupTable ();
++ virtual void updateLookupTableFast ();
++ virtual gboolean fillLookupTableByPage ();
++
++protected:
++
++ gboolean updateSpecialPhrases ();
++ gboolean selectCandidate (guint i);
++ gboolean selectCandidateInPage (guint i);
++ gboolean resetCandidate (guint i);
++ gboolean resetCandidateInPage(guint i);
++
++ void commit (const gchar *str);
++
++ /* inline functions */
++
++ /* pure virtual functions */
++ virtual gboolean insert (gint ch) = 0;
++ virtual gboolean removeCharBefore (void) = 0;
++ virtual gboolean removeCharAfter (void) = 0;
++ virtual gboolean removeWordBefore (void) = 0;
++ virtual gboolean removeWordAfter (void) = 0;
++ virtual gboolean moveCursorLeft (void) = 0;
++ virtual gboolean moveCursorRight (void) = 0;
++ virtual gboolean moveCursorLeftByWord (void) = 0;
++ virtual gboolean moveCursorRightByWord (void) = 0;
++ virtual gboolean moveCursorToBegin (void) = 0;
++ virtual gboolean moveCursorToEnd (void) = 0;
++ virtual void commit (void) = 0;
++ virtual void updateAuxiliaryText (void) = 0;
++ virtual void updatePreeditText (void) = 0;
++
++ /* varibles */
++ PinyinArray m_pinyin;
++ guint m_pinyin_len;
++ LookupTable m_lookup_table;
++ /* libpinyin singleton here. */
++ std::vector<std::string> m_special_phrases;
++ std::string m_selected_special_phrase;
++};
++
++};
++
++#endif
+--
+1.7.6.4
+
+
+From 21ee5c23e325fd7b4816b38b9cc308e17e23c1a3 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Tue, 30 Aug 2011 18:24:02 +0800
+Subject: [PATCH 02/71] begin to write libpinyin backend singleton
+
+---
+ src/PYLibPinyin.h | 36 ++++++++++++++++++++++++++++++++++++
+ 1 files changed, 36 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYLibPinyin.h
+
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+new file mode 100644
+index 0000000..cfd8566
+--- /dev/null
++++ b/src/PYLibPinyin.h
+@@ -0,0 +1,36 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++
++#ifndef __PY_LIB_PINYIN_H_
++#define __PY_LIB_PINYIN_H_
++
++namespace PY {
++class LibPinyinBackEnd{
++public:
++ /* use static initializer in C++. */
++ static LibPinyinBackEnd & instance (void) { return *m_instance; }
++
++private:
++ static std::unique_ptr<LibPinyinBackEnd> m_instance;
++};
++};
++
++#endif
+--
+1.7.6.4
+
+
+From 71e25b32ed628a4692c43b48fa6a150884b05378 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 1 Sep 2011 11:24:02 +0800
+Subject: [PATCH 03/71] rename editor class
+
+---
+ src/PYLibPinyin.h | 5 +++++
+ src/PYPinyinBaseEditor.h | 11 ++++++-----
+ 2 files changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+index cfd8566..d3bc90c 100644
+--- a/src/PYLibPinyin.h
++++ b/src/PYLibPinyin.h
+@@ -22,6 +22,8 @@
+ #ifndef __PY_LIB_PINYIN_H_
+ #define __PY_LIB_PINYIN_H_
+
++typedef struct _pinyin_context_t pinyin_context_t;
++
+ namespace PY {
+ class LibPinyinBackEnd{
+ public:
+@@ -29,6 +31,9 @@ public:
+ static LibPinyinBackEnd & instance (void) { return *m_instance; }
+
+ private:
++ pinyin_context_t *m_pinyin_context; /* libpinyin context */
++
++private:
+ static std::unique_ptr<LibPinyinBackEnd> m_instance;
+ };
+ };
+diff --git a/src/PYPinyinBaseEditor.h b/src/PYPinyinBaseEditor.h
+index 0bed00a..ee200a1 100644
+--- a/src/PYPinyinBaseEditor.h
++++ b/src/PYPinyinBaseEditor.h
+@@ -18,8 +18,8 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#ifndef __PY_PINYIN_BASE_EDITOR_H_
+-#define __PY_PINYIN_BASE_EDITOR_H_
++#ifndef __PY_LIB_PINYIN_BASE_EDITOR_H_
++#define __PY_LIB_PINYIN_BASE_EDITOR_H_
+
+ #include <libpinyin.h>
+ #include "PYLookupTable.h"
+@@ -29,9 +29,9 @@
+
+ namespace PY {
+
+-class PinyinBaseEditor : public Editor {
++class LibPinyinBaseEditor : public Editor {
+ public:
+- PinyinBaseEditor (PinyinProperties & props, Config & config);
++ LibPinyinBaseEditor (PinyinProperties & props, Config & config);
+
+ public:
+ /* virtual functions */
+@@ -81,7 +81,8 @@ protected:
+ PinyinArray m_pinyin;
+ guint m_pinyin_len;
+ LookupTable m_lookup_table;
+- /* libpinyin singleton here. */
++
++ /* use LibPinyinBackEnd here. */
+ std::vector<std::string> m_special_phrases;
+ std::string m_selected_special_phrase;
+ };
+--
+1.7.6.4
+
+
+From b89b25c7c5522b25f4f8a023fea7bf73bb15db68 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 1 Sep 2011 13:02:24 +0800
+Subject: [PATCH 04/71] rename editor header
+
+---
+ src/PYLibPinyinBaseEditor.h | 92 +++++++++++++++++++++++++++++++++++++++++++
+ src/PYPinyinBaseEditor.h | 92 -------------------------------------------
+ 2 files changed, 92 insertions(+), 92 deletions(-)
+ create mode 100644 src/PYLibPinyinBaseEditor.h
+ delete mode 100644 src/PYPinyinBaseEditor.h
+
+diff --git a/src/PYLibPinyinBaseEditor.h b/src/PYLibPinyinBaseEditor.h
+new file mode 100644
+index 0000000..ee200a1
+--- /dev/null
++++ b/src/PYLibPinyinBaseEditor.h
+@@ -0,0 +1,92 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_BASE_EDITOR_H_
++#define __PY_LIB_PINYIN_BASE_EDITOR_H_
++
++#include <libpinyin.h>
++#include "PYLookupTable.h"
++#include "PYEditor.h"
++#include "PYPinyinParser.h"
++#include "PYSpecialPhraseTable.h"
++
++namespace PY {
++
++class LibPinyinBaseEditor : public Editor {
++public:
++ LibPinyinBaseEditor (PinyinProperties & props, Config & config);
++
++public:
++ /* virtual functions */
++ virtual void pageUp (void);
++ virtual void pageDown (void);
++ virtual void cursorUp (void);
++ virtual void cursorDown (void);
++ virtual void update (void);
++ virtual void reset (void);
++ virtual void candidateClicked (guint index, guint button, guint state);
++ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ virtual gboolean processSpace (guint keyval, guint keycode, guint modifiers);
++ virtual gboolean processFunctionKey (guint keyval, guint keycode, guint modifiers);
++ virtual void updateLookupTable ();
++ virtual void updateLookupTableFast ();
++ virtual gboolean fillLookupTableByPage ();
++
++protected:
++
++ gboolean updateSpecialPhrases ();
++ gboolean selectCandidate (guint i);
++ gboolean selectCandidateInPage (guint i);
++ gboolean resetCandidate (guint i);
++ gboolean resetCandidateInPage(guint i);
++
++ void commit (const gchar *str);
++
++ /* inline functions */
++
++ /* pure virtual functions */
++ virtual gboolean insert (gint ch) = 0;
++ virtual gboolean removeCharBefore (void) = 0;
++ virtual gboolean removeCharAfter (void) = 0;
++ virtual gboolean removeWordBefore (void) = 0;
++ virtual gboolean removeWordAfter (void) = 0;
++ virtual gboolean moveCursorLeft (void) = 0;
++ virtual gboolean moveCursorRight (void) = 0;
++ virtual gboolean moveCursorLeftByWord (void) = 0;
++ virtual gboolean moveCursorRightByWord (void) = 0;
++ virtual gboolean moveCursorToBegin (void) = 0;
++ virtual gboolean moveCursorToEnd (void) = 0;
++ virtual void commit (void) = 0;
++ virtual void updateAuxiliaryText (void) = 0;
++ virtual void updatePreeditText (void) = 0;
++
++ /* varibles */
++ PinyinArray m_pinyin;
++ guint m_pinyin_len;
++ LookupTable m_lookup_table;
++
++ /* use LibPinyinBackEnd here. */
++ std::vector<std::string> m_special_phrases;
++ std::string m_selected_special_phrase;
++};
++
++};
++
++#endif
+diff --git a/src/PYPinyinBaseEditor.h b/src/PYPinyinBaseEditor.h
+deleted file mode 100644
+index ee200a1..0000000
+--- a/src/PYPinyinBaseEditor.h
++++ /dev/null
+@@ -1,92 +0,0 @@
+-/* vim:set et ts=4 sts=4:
+- *
+- * ibus-pinyin - The Chinese PinYin engine for IBus
+- *
+- * Copyright (c) 2011 Peng Wu <alexepico at 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.
+- */
+-#ifndef __PY_LIB_PINYIN_BASE_EDITOR_H_
+-#define __PY_LIB_PINYIN_BASE_EDITOR_H_
+-
+-#include <libpinyin.h>
+-#include "PYLookupTable.h"
+-#include "PYEditor.h"
+-#include "PYPinyinParser.h"
+-#include "PYSpecialPhraseTable.h"
+-
+-namespace PY {
+-
+-class LibPinyinBaseEditor : public Editor {
+-public:
+- LibPinyinBaseEditor (PinyinProperties & props, Config & config);
+-
+-public:
+- /* virtual functions */
+- virtual void pageUp (void);
+- virtual void pageDown (void);
+- virtual void cursorUp (void);
+- virtual void cursorDown (void);
+- virtual void update (void);
+- virtual void reset (void);
+- virtual void candidateClicked (guint index, guint button, guint state);
+- virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+- virtual gboolean processSpace (guint keyval, guint keycode, guint modifiers);
+- virtual gboolean processFunctionKey (guint keyval, guint keycode, guint modifiers);
+- virtual void updateLookupTable ();
+- virtual void updateLookupTableFast ();
+- virtual gboolean fillLookupTableByPage ();
+-
+-protected:
+-
+- gboolean updateSpecialPhrases ();
+- gboolean selectCandidate (guint i);
+- gboolean selectCandidateInPage (guint i);
+- gboolean resetCandidate (guint i);
+- gboolean resetCandidateInPage(guint i);
+-
+- void commit (const gchar *str);
+-
+- /* inline functions */
+-
+- /* pure virtual functions */
+- virtual gboolean insert (gint ch) = 0;
+- virtual gboolean removeCharBefore (void) = 0;
+- virtual gboolean removeCharAfter (void) = 0;
+- virtual gboolean removeWordBefore (void) = 0;
+- virtual gboolean removeWordAfter (void) = 0;
+- virtual gboolean moveCursorLeft (void) = 0;
+- virtual gboolean moveCursorRight (void) = 0;
+- virtual gboolean moveCursorLeftByWord (void) = 0;
+- virtual gboolean moveCursorRightByWord (void) = 0;
+- virtual gboolean moveCursorToBegin (void) = 0;
+- virtual gboolean moveCursorToEnd (void) = 0;
+- virtual void commit (void) = 0;
+- virtual void updateAuxiliaryText (void) = 0;
+- virtual void updatePreeditText (void) = 0;
+-
+- /* varibles */
+- PinyinArray m_pinyin;
+- guint m_pinyin_len;
+- LookupTable m_lookup_table;
+-
+- /* use LibPinyinBackEnd here. */
+- std::vector<std::string> m_special_phrases;
+- std::string m_selected_special_phrase;
+-};
+-
+-};
+-
+-#endif
+--
+1.7.6.4
+
+
+From 9103387c14422521f7449806079bf411ab8f6fd3 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 1 Sep 2011 15:13:09 +0800
+Subject: [PATCH 05/71] begin to write libpinyin base editor
+
+---
+ src/PYLibPinyinBaseEditor.cc | 318 ++++++++++++++++++++++++++++++++++++++++++
+ src/PYLibPinyinBaseEditor.h | 2 -
+ 2 files changed, 318 insertions(+), 2 deletions(-)
+ create mode 100644 src/PYLibPinyinBaseEditor.cc
+
+diff --git a/src/PYLibPinyinBaseEditor.cc b/src/PYLibPinyinBaseEditor.cc
+new file mode 100644
+index 0000000..81ef1f2
+--- /dev/null
++++ b/src/PYLibPinyinBaseEditor.cc
+@@ -0,0 +1,318 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYLibPinyinBaseEditor.h"
++#include "PYConfig.h"
++#include "PYPinyinProperties.h"
++#include "PYSimpTradConverter.h"
++
++namespace PY {
++/* init static members */
++LibPinyinBaseEditor::LibPinyinBaseEditor (PinyinProperties &props,
++ Config &config):
++ Editor (props, config),
++ m_pinyin (MAX_PHRASE_LEN),
++ m_pinyin_len (0),
++ m_lookup_table (m_config.pageSize ())
++{
++}
++
++gboolean
++LibPinyinBaseEditor::processSpace (guint keyval, guint keycode,
++ guint modifiers)
++{
++ if (!m_text)
++ return FALSE;
++ if (cmshm_filter (modifiers) != 0)
++ return TRUE;
++ if (m_lookup_table.size () != 0) {
++ selectCandidate (m_lookup_table.cursorPos ());
++ } else {
++ commit ();
++ }
++ return TRUE;
++}
++
++gboolean
++LibPinyinBaseEditor::processFunctionKey (guint keyval, guint keycode, guint modifiers)
++{
++ if (m_text.empty ())
++ return FALSE;
++
++ /* ignore numlock */
++ modifiers = cmshm_filter (modifiers);
++
++ if (modifiers != 0 && modifiers != IBUS_CONTROL_MASK)
++ return TRUE;
++
++ /* process some cursor control keys */
++ if (modifiers == 0) { /* no modifiers. */
++ switch (keyval) {
++ case IBUS_Return:
++ case IBUS_KP_Enter:
++ commit ();
++ return TRUE;
++
++ case IBUS_BackSpace:
++ removeCharBefore ();
++ return TRUE;
++
++ case IBUS_Delete:
++ case IBUS_KP_Delete:
++ removeCharAfter ();
++ return TRUE;
++
++ case IBUS_Left:
++ case IBUS_KP_Left:
++ moveCursorLeft ();
++ return TRUE;
++
++ case IBUS_Right:
++ case IBUS_KP_Right:
++ moveCursorRight ();
++ return TRUE;
++
++ case IBUS_Home:
++ case IBUS_KP_Home:
++ moveCursorToBegin ();
++ return TRUE;
++
++ case IBUS_End:
++ case IBUS_KP_End:
++ moveCursorToEnd ();
++ return TRUE;
++
++ case IBUS_Up:
++ case IBUS_KP_Up:
++ cursorUp ();
++ return TRUE;
++
++ case IBUS_Down:
++ case IBUS_KP_Down:
++ cursorDown ();
++ return TRUE;
++
++ case IBUS_Page_Up:
++ case IBUS_KP_Page_Up:
++ pageUp ();
++ return TRUE;
++
++ case IBUS_Page_Down:
++ case IBUS_KP_Page_Down:
++ case IBUS_Tab:
++ pageDown ();
++ return TRUE;
++
++ case IBUS_Escape:
++ reset ();
++ return TRUE;
++ default:
++ return TRUE;
++ }
++ } else { /* ctrl key pressed. */
++ switch (keyval) {
++ case IBUS_BackSpace:
++ removeWordBefore ();
++ return TRUE;
++
++ case IBUS_Delete:
++ case IBUS_KP_Delete:
++ removeWordAfter ();
++ return TRUE;
++
++ case IBUS_Left:
++ case IBUS_KP_Left:
++ moveCursorLeftByWord ();
++ return TRUE;
++
++ case IBUS_Right:
++ case IBUS_KP_Right:
++ moveCursorToEnd ();
++ return TRUE;
++
++ default:
++ return TRUE;
++ }
++ }
++ return TRUE;
++}
++
++gboolean
++LibPinyinBaseEditor::processKeyEvent (guint keyval, guint keycode, guint modifiers)
++{
++ return FALSE;
++}
++
++gboolean
++LibPinyinBaseEditor::updateSpecialPhrases (void)
++{
++ guint size = m_special_phrases.size ();
++ m_special_phrases.clear ();
++
++ if (!m_config.specialPhrases ())
++ return FALSE;
++
++ if (!m_selected_special_phrase.empty ())
++ return FALSE;
++
++ /* TODO: change behavior to match the entire m_text,
++ * instead of partial of m_text.
++ */
++ g_assert(FALSE);
++}
++
++void
++LibPinyinBaseEditor::updateLookupTableFast (void)
++{
++ Editor::updateLookupTableFast (m_lookup_table, TRUE);
++}
++
++void
++LibPinyinBaseEditor::updateLookupTable (void)
++{
++ m_lookup_table.clear ();
++
++ fillLookupTableByPage ();
++ if (m_lookup_table.size()) {
++ Editor::updateLookupTable (m_lookup_table, TRUE);
++ } else {
++ hideLookupTable ();
++ }
++}
++
++gboolean
++LibPinyinBaseEditor::fillLookupTableByPage (void)
++{
++ if (!m_selected_special_phrase.empty ()) {
++ return FALSE;
++ }
++
++ guint filled_nr = m_lookup_table.size ();
++ guint page_size = m_lookup_table.pageSize ();
++
++ /* fill lookup table by libpinyin get candidates. */
++ g_assert(FALSE);
++}
++
++void
++LibPinyinBaseEditor::pageUp (void)
++{
++ if (G_LIKELY (m_lookup_table.pageUp ())) {
++ updateLookupTableFast ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++ }
++}
++
++void
++LibPinyinBaseEditor::pageDown (void)
++{
++ if (G_LIKELY((m_lookup_table.pageDown ()) ||
++ (fillLookupTableByPage () && m_lookup_table.pageDown()))) {
++ updateLookupTableFast ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++ }
++}
++
++void
++LibPinyinBaseEditor::cursorUp (void)
++{
++ if (G_LIKELY (m_lookup_table.cursorUp ())) {
++ updateLookupTableFast ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++ }
++}
++
++void
++LibPinyinBaseEditor::cursorDown (void)
++{
++ if (G_LIKELY ((m_lookup_table.cursorPos () == m_lookup_table.size() - 1) &&
++ (fillLookupTableByPage () == FALSE))) {
++ return;
++ }
++
++ if (G_LIKELY (m_lookup_table.cursorDown ())) {
++ updateLookupTableFast ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++ }
++}
++
++void
++LibPinyinBaseEditor::candidateClicked (guint index, guint button, guint state)
++{
++ selectCandidateInPage (index);
++}
++
++void
++LibPinyinBaseEditor::reset (void)
++{
++ m_pinyin.clear ();
++ m_pinyin_len = 0;
++ m_lookup_table.clear ();
++ m_special_phrases.clear ();
++ m_selected_special_phrase.clear ();
++
++ Editor::reset ();
++}
++
++void
++LibPinyinBaseEditor::update (void)
++{
++ updateLookupTable ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++}
++
++void
++LibPinyinBaseEditor::commit (const gchar *str)
++{
++ StaticText text(str);
++ commitText (text);
++}
++
++gboolean
++LibPinyinBaseEditor::selectCandidate (guint i)
++{
++ g_assert(FALSE);
++ if (i < m_special_phrases.size ()) {
++ /* select a special phrase */
++ m_selected_special_phrase = m_special_phrases[i];
++
++ /* refer to updateSpecialPhrases. */
++ }
++}
++
++gboolean
++LibPinyinBaseEditor::selectCandidateInPage (guint i)
++{
++ guint page_size = m_lookup_table.pageSize ();
++ guint cursor_pos = m_lookup_table.cursorPos ();
++
++ if (G_UNLIKELY (i >= page_size))
++ return FALSE;
++ i += (cursor_pos / page_size) * page_size;
++
++ return selectCandidate (i);
++}
++
++};
+diff --git a/src/PYLibPinyinBaseEditor.h b/src/PYLibPinyinBaseEditor.h
+index ee200a1..c7b0d2b 100644
+--- a/src/PYLibPinyinBaseEditor.h
++++ b/src/PYLibPinyinBaseEditor.h
+@@ -54,8 +54,6 @@ protected:
+ gboolean updateSpecialPhrases ();
+ gboolean selectCandidate (guint i);
+ gboolean selectCandidateInPage (guint i);
+- gboolean resetCandidate (guint i);
+- gboolean resetCandidateInPage(guint i);
+
+ void commit (const gchar *str);
+
+--
+1.7.6.4
+
+
+From 2f3696c5af718b4eeb6113dc0b68bd9525027ec2 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 1 Sep 2011 15:51:53 +0800
+Subject: [PATCH 06/71] fixes compile
+
+---
+ src/Makefile.am | 3 +++
+ src/PYLibPinyinBaseEditor.cc | 1 -
+ src/PYLibPinyinBaseEditor.h | 1 -
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 2ca6c1e..a104c75 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -64,6 +64,7 @@ ibus_engine_pinyin_c_sources = \
+ PYDynamicSpecialPhrase.cc \
+ PYSpecialPhrase.cc \
+ PYSpecialPhraseTable.cc \
++ PYLibPinyinBaseEditor.cc \
+ $(NULL)
+ ibus_engine_pinyin_h_sources = \
+ PYBopomofo.h \
+@@ -106,6 +107,8 @@ ibus_engine_pinyin_h_sources = \
+ PYTypes.h \
+ PYUtil.h \
+ PYEnglishEditor.h \
++ PYLibPinyin.h \
++ PYLibPinyinBaseEditor.h \
+ $(NULL)
+
+ if IBUS_BUILD_LUA_EXTENSION
+diff --git a/src/PYLibPinyinBaseEditor.cc b/src/PYLibPinyinBaseEditor.cc
+index 81ef1f2..74acba4 100644
+--- a/src/PYLibPinyinBaseEditor.cc
++++ b/src/PYLibPinyinBaseEditor.cc
+@@ -163,7 +163,6 @@ LibPinyinBaseEditor::processKeyEvent (guint keyval, guint keycode, guint modifie
+ gboolean
+ LibPinyinBaseEditor::updateSpecialPhrases (void)
+ {
+- guint size = m_special_phrases.size ();
+ m_special_phrases.clear ();
+
+ if (!m_config.specialPhrases ())
+diff --git a/src/PYLibPinyinBaseEditor.h b/src/PYLibPinyinBaseEditor.h
+index c7b0d2b..d682a7b 100644
+--- a/src/PYLibPinyinBaseEditor.h
++++ b/src/PYLibPinyinBaseEditor.h
+@@ -21,7 +21,6 @@
+ #ifndef __PY_LIB_PINYIN_BASE_EDITOR_H_
+ #define __PY_LIB_PINYIN_BASE_EDITOR_H_
+
+-#include <libpinyin.h>
+ #include "PYLookupTable.h"
+ #include "PYEditor.h"
+ #include "PYPinyinParser.h"
+--
+1.7.6.4
+
+
+From b6cc94ba4d65f1511aebb5b2da80c958cd882815 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 2 Sep 2011 10:34:06 +0800
+Subject: [PATCH 07/71] add special phrases handle in libpinyin base editor
+
+---
+ src/PYLibPinyinBaseEditor.cc | 27 +++++++++++++++++++++------
+ src/PYLibPinyinBaseEditor.h | 1 +
+ 2 files changed, 22 insertions(+), 6 deletions(-)
+
+diff --git a/src/PYLibPinyinBaseEditor.cc b/src/PYLibPinyinBaseEditor.cc
+index 74acba4..6fdd5ef 100644
+--- a/src/PYLibPinyinBaseEditor.cc
++++ b/src/PYLibPinyinBaseEditor.cc
+@@ -163,6 +163,7 @@ LibPinyinBaseEditor::processKeyEvent (guint keyval, guint keycode, guint modifie
+ gboolean
+ LibPinyinBaseEditor::updateSpecialPhrases (void)
+ {
++ guint size = m_special_phrases.size();
+ m_special_phrases.clear ();
+
+ if (!m_config.specialPhrases ())
+@@ -171,10 +172,13 @@ LibPinyinBaseEditor::updateSpecialPhrases (void)
+ if (!m_selected_special_phrase.empty ())
+ return FALSE;
+
+- /* TODO: change behavior to match the entire m_text,
+- * instead of partial of m_text.
++ /* Note: change behavior to match the entire m_text,
++ * instead of partial m_text.
+ */
+- g_assert(FALSE);
++ SpecialPhraseTable::instance ().lookup
++ (m_text, m_special_phrases);
++
++ return size != m_special_phrases.size() || size != 0;
+ }
+
+ void
+@@ -292,13 +296,24 @@ LibPinyinBaseEditor::commit (const gchar *str)
+ gboolean
+ LibPinyinBaseEditor::selectCandidate (guint i)
+ {
+- g_assert(FALSE);
++
+ if (i < m_special_phrases.size ()) {
+ /* select a special phrase */
+ m_selected_special_phrase = m_special_phrases[i];
+-
+- /* refer to updateSpecialPhrases. */
++ if (m_cursor == m_text.size()) {
++ m_buffer = m_selected_special_phrase;
++ reset ();
++ commit ((const gchar *)m_buffer);
++ } else {
++ updateSpecialPhrases ();
++ update ();
++ }
++ return TRUE;
+ }
++
++ i -= m_special_phrases.size ();
++ /* TODO: deal with normal candidates selection here by libpinyin. */
++ g_assert (FALSE);
+ }
+
+ gboolean
+diff --git a/src/PYLibPinyinBaseEditor.h b/src/PYLibPinyinBaseEditor.h
+index d682a7b..fa5755c 100644
+--- a/src/PYLibPinyinBaseEditor.h
++++ b/src/PYLibPinyinBaseEditor.h
+@@ -78,6 +78,7 @@ protected:
+ PinyinArray m_pinyin;
+ guint m_pinyin_len;
+ LookupTable m_lookup_table;
++ String m_buffer;
+
+ /* use LibPinyinBackEnd here. */
+ std::vector<std::string> m_special_phrases;
+--
+1.7.6.4
+
+
+From 61aafedfb9cf7718afebb4cb8a3eb82873bafa1d Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 2 Sep 2011 14:30:11 +0800
+Subject: [PATCH 08/71] begin to write concrete pinyin editors
+
+---
+ src/PYLibPinyinDoublePinyinEditor.h | 57 +++++++++++++++++++++++++++++++++
+ src/PYLibPinyinFullPinyinEditor.h | 59 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 116 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYLibPinyinDoublePinyinEditor.h
+ create mode 100644 src/PYLibPinyinFullPinyinEditor.h
+
+diff --git a/src/PYLibPinyinDoublePinyinEditor.h b/src/PYLibPinyinDoublePinyinEditor.h
+new file mode 100644
+index 0000000..5ed106f
+--- /dev/null
++++ b/src/PYLibPinyinDoublePinyinEditor.h
+@@ -0,0 +1,57 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_DOUBLE_PINYIN_EDITOR_H_
++#define __PY_LIB_PINYIN_DOUBLE_PINYIN_EDITOR_H_
++
++#include "PYLibPinyinBaseEditor.h"
++
++namespace PY {
++
++class LibPinyinDoublePinyinEditor : public LibPinyinBaseEditor {
++
++public:
++ LibPinyinDoublePinyinEditor (PinyinProperties & props, Config & config);
++
++ gboolean insert (gint ch);
++
++ gboolean removeCharBefore (void);
++ gboolean removeCharAfter (void);
++ gboolean removeWordBefore (void);
++ gboolean removeWordAfter (void);
++
++ gboolean moveCursorLeft (void);
++ gboolean moveCursorRight (void);
++ gboolean moveCursorLeftByWord (void);
++ gboolean moveCursorRightByWord (void);
++ gboolean moveCursorToBegin (void);
++ gboolean moveCursorToEnd (void);
++
++ /* override virtual functions */
++ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ void reset (void);
++
++protected:
++ /* TODO: to be implemented. */
++};
++
++};
++
++#endif
+diff --git a/src/PYLibPinyinFullPinyinEditor.h b/src/PYLibPinyinFullPinyinEditor.h
+new file mode 100644
+index 0000000..dcc1728
+--- /dev/null
++++ b/src/PYLibPinyinFullPinyinEditor.h
+@@ -0,0 +1,59 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_FULL_PINYIN_EDITOR_H
++#define __PY_LIB_PINYIN_FULL_PINYIN_EDITOR_H
++
++#include "PYLibPinyinBaseEditor.h"
++
++namespace PY {
++
++class LibPinyinFullPinyinEditor : public PinyinEditor {
++
++public:
++ LibPinyinFullPinyinEditor (PinyinProperties & props, Config & config);
++ ~LibPinyinFullPinyinEditor (void);
++
++public:
++ gboolean insert (gint ch);
++
++ gboolean removeCharBefore (void);
++ gboolean removeCharAfter (void);
++ gboolean removeWordBefore (void);
++ gboolean removeWordAfter (void);
++
++ gboolean moveCursorLeft (void);
++ gboolean moveCursorRight (void);
++ gboolean moveCursorLeftByWord (void);
++ gboolean moveCursorRightByWord (void);
++ gboolean moveCursorToBegin (void);
++ gboolean moveCursorToEnd (void);
++
++ /* virtual functions */
++ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ virtual void reset (void);
++
++protected:
++ /* TODO: to be implemented. */
++};
++
++};
++
++#endif
+--
+1.7.6.4
+
+
+From 56d08018ceb62e0dfaff14cc3456e7b1e65dc53b Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 2 Sep 2011 15:26:21 +0800
+Subject: [PATCH 09/71] rename files
+
+---
+ src/PYLibPinyinBaseEditor.cc | 332 -----------------------------------
+ src/PYLibPinyinBaseEditor.h | 90 ----------
+ src/PYLibPinyinDoublePinyinEditor.h | 57 ------
+ src/PYLibPinyinFullPinyinEditor.h | 59 ------
+ src/PYPDoublePinyinEditor.h | 57 ++++++
+ src/PYPFullPinyinEditor.h | 59 ++++++
+ src/PYPPhoneticEditor.cc | 332 +++++++++++++++++++++++++++++++++++
+ src/PYPPhoneticEditor.h | 90 ++++++++++
+ 8 files changed, 538 insertions(+), 538 deletions(-)
+ delete mode 100644 src/PYLibPinyinBaseEditor.cc
+ delete mode 100644 src/PYLibPinyinBaseEditor.h
+ delete mode 100644 src/PYLibPinyinDoublePinyinEditor.h
+ delete mode 100644 src/PYLibPinyinFullPinyinEditor.h
+ create mode 100644 src/PYPDoublePinyinEditor.h
+ create mode 100644 src/PYPFullPinyinEditor.h
+ create mode 100644 src/PYPPhoneticEditor.cc
+ create mode 100644 src/PYPPhoneticEditor.h
+
+diff --git a/src/PYLibPinyinBaseEditor.cc b/src/PYLibPinyinBaseEditor.cc
+deleted file mode 100644
+index 6fdd5ef..0000000
+--- a/src/PYLibPinyinBaseEditor.cc
++++ /dev/null
+@@ -1,332 +0,0 @@
+-/* vim:set et ts=4 sts=4:
+- *
+- * ibus-pinyin - The Chinese PinYin engine for IBus
+- *
+- * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYLibPinyinBaseEditor.h"
+-#include "PYConfig.h"
+-#include "PYPinyinProperties.h"
+-#include "PYSimpTradConverter.h"
+-
+-namespace PY {
+-/* init static members */
+-LibPinyinBaseEditor::LibPinyinBaseEditor (PinyinProperties &props,
+- Config &config):
+- Editor (props, config),
+- m_pinyin (MAX_PHRASE_LEN),
+- m_pinyin_len (0),
+- m_lookup_table (m_config.pageSize ())
+-{
+-}
+-
+-gboolean
+-LibPinyinBaseEditor::processSpace (guint keyval, guint keycode,
+- guint modifiers)
+-{
+- if (!m_text)
+- return FALSE;
+- if (cmshm_filter (modifiers) != 0)
+- return TRUE;
+- if (m_lookup_table.size () != 0) {
+- selectCandidate (m_lookup_table.cursorPos ());
+- } else {
+- commit ();
+- }
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBaseEditor::processFunctionKey (guint keyval, guint keycode, guint modifiers)
+-{
+- if (m_text.empty ())
+- return FALSE;
+-
+- /* ignore numlock */
+- modifiers = cmshm_filter (modifiers);
+-
+- if (modifiers != 0 && modifiers != IBUS_CONTROL_MASK)
+- return TRUE;
+-
+- /* process some cursor control keys */
+- if (modifiers == 0) { /* no modifiers. */
+- switch (keyval) {
+- case IBUS_Return:
+- case IBUS_KP_Enter:
+- commit ();
+- return TRUE;
+-
+- case IBUS_BackSpace:
+- removeCharBefore ();
+- return TRUE;
+-
+- case IBUS_Delete:
+- case IBUS_KP_Delete:
+- removeCharAfter ();
+- return TRUE;
+-
+- case IBUS_Left:
+- case IBUS_KP_Left:
+- moveCursorLeft ();
+- return TRUE;
+-
+- case IBUS_Right:
+- case IBUS_KP_Right:
+- moveCursorRight ();
+- return TRUE;
+-
+- case IBUS_Home:
+- case IBUS_KP_Home:
+- moveCursorToBegin ();
+- return TRUE;
+-
+- case IBUS_End:
+- case IBUS_KP_End:
+- moveCursorToEnd ();
+- return TRUE;
+-
+- case IBUS_Up:
+- case IBUS_KP_Up:
+- cursorUp ();
+- return TRUE;
+-
+- case IBUS_Down:
+- case IBUS_KP_Down:
+- cursorDown ();
+- return TRUE;
+-
+- case IBUS_Page_Up:
+- case IBUS_KP_Page_Up:
+- pageUp ();
+- return TRUE;
+-
+- case IBUS_Page_Down:
+- case IBUS_KP_Page_Down:
+- case IBUS_Tab:
+- pageDown ();
+- return TRUE;
+-
+- case IBUS_Escape:
+- reset ();
+- return TRUE;
+- default:
+- return TRUE;
+- }
+- } else { /* ctrl key pressed. */
+- switch (keyval) {
+- case IBUS_BackSpace:
+- removeWordBefore ();
+- return TRUE;
+-
+- case IBUS_Delete:
+- case IBUS_KP_Delete:
+- removeWordAfter ();
+- return TRUE;
+-
+- case IBUS_Left:
+- case IBUS_KP_Left:
+- moveCursorLeftByWord ();
+- return TRUE;
+-
+- case IBUS_Right:
+- case IBUS_KP_Right:
+- moveCursorToEnd ();
+- return TRUE;
+-
+- default:
+- return TRUE;
+- }
+- }
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBaseEditor::processKeyEvent (guint keyval, guint keycode, guint modifiers)
+-{
+- return FALSE;
+-}
+-
+-gboolean
+-LibPinyinBaseEditor::updateSpecialPhrases (void)
+-{
+- guint size = m_special_phrases.size();
+- m_special_phrases.clear ();
+-
+- if (!m_config.specialPhrases ())
+- return FALSE;
+-
+- if (!m_selected_special_phrase.empty ())
+- return FALSE;
+-
+- /* Note: change behavior to match the entire m_text,
+- * instead of partial m_text.
+- */
+- SpecialPhraseTable::instance ().lookup
+- (m_text, m_special_phrases);
+-
+- return size != m_special_phrases.size() || size != 0;
+-}
+-
+-void
+-LibPinyinBaseEditor::updateLookupTableFast (void)
+-{
+- Editor::updateLookupTableFast (m_lookup_table, TRUE);
+-}
+-
+-void
+-LibPinyinBaseEditor::updateLookupTable (void)
+-{
+- m_lookup_table.clear ();
+-
+- fillLookupTableByPage ();
+- if (m_lookup_table.size()) {
+- Editor::updateLookupTable (m_lookup_table, TRUE);
+- } else {
+- hideLookupTable ();
+- }
+-}
+-
+-gboolean
+-LibPinyinBaseEditor::fillLookupTableByPage (void)
+-{
+- if (!m_selected_special_phrase.empty ()) {
+- return FALSE;
+- }
+-
+- guint filled_nr = m_lookup_table.size ();
+- guint page_size = m_lookup_table.pageSize ();
+-
+- /* fill lookup table by libpinyin get candidates. */
+- g_assert(FALSE);
+-}
+-
+-void
+-LibPinyinBaseEditor::pageUp (void)
+-{
+- if (G_LIKELY (m_lookup_table.pageUp ())) {
+- updateLookupTableFast ();
+- updatePreeditText ();
+- updateAuxiliaryText ();
+- }
+-}
+-
+-void
+-LibPinyinBaseEditor::pageDown (void)
+-{
+- if (G_LIKELY((m_lookup_table.pageDown ()) ||
+- (fillLookupTableByPage () && m_lookup_table.pageDown()))) {
+- updateLookupTableFast ();
+- updatePreeditText ();
+- updateAuxiliaryText ();
+- }
+-}
+-
+-void
+-LibPinyinBaseEditor::cursorUp (void)
+-{
+- if (G_LIKELY (m_lookup_table.cursorUp ())) {
+- updateLookupTableFast ();
+- updatePreeditText ();
+- updateAuxiliaryText ();
+- }
+-}
+-
+-void
+-LibPinyinBaseEditor::cursorDown (void)
+-{
+- if (G_LIKELY ((m_lookup_table.cursorPos () == m_lookup_table.size() - 1) &&
+- (fillLookupTableByPage () == FALSE))) {
+- return;
+- }
+-
+- if (G_LIKELY (m_lookup_table.cursorDown ())) {
+- updateLookupTableFast ();
+- updatePreeditText ();
+- updateAuxiliaryText ();
+- }
+-}
+-
+-void
+-LibPinyinBaseEditor::candidateClicked (guint index, guint button, guint state)
+-{
+- selectCandidateInPage (index);
+-}
+-
+-void
+-LibPinyinBaseEditor::reset (void)
+-{
+- m_pinyin.clear ();
+- m_pinyin_len = 0;
+- m_lookup_table.clear ();
+- m_special_phrases.clear ();
+- m_selected_special_phrase.clear ();
+-
+- Editor::reset ();
+-}
+-
+-void
+-LibPinyinBaseEditor::update (void)
+-{
+- updateLookupTable ();
+- updatePreeditText ();
+- updateAuxiliaryText ();
+-}
+-
+-void
+-LibPinyinBaseEditor::commit (const gchar *str)
+-{
+- StaticText text(str);
+- commitText (text);
+-}
+-
+-gboolean
+-LibPinyinBaseEditor::selectCandidate (guint i)
+-{
+-
+- if (i < m_special_phrases.size ()) {
+- /* select a special phrase */
+- m_selected_special_phrase = m_special_phrases[i];
+- if (m_cursor == m_text.size()) {
+- m_buffer = m_selected_special_phrase;
+- reset ();
+- commit ((const gchar *)m_buffer);
+- } else {
+- updateSpecialPhrases ();
+- update ();
+- }
+- return TRUE;
+- }
+-
+- i -= m_special_phrases.size ();
+- /* TODO: deal with normal candidates selection here by libpinyin. */
+- g_assert (FALSE);
+-}
+-
+-gboolean
+-LibPinyinBaseEditor::selectCandidateInPage (guint i)
+-{
+- guint page_size = m_lookup_table.pageSize ();
+- guint cursor_pos = m_lookup_table.cursorPos ();
+-
+- if (G_UNLIKELY (i >= page_size))
+- return FALSE;
+- i += (cursor_pos / page_size) * page_size;
+-
+- return selectCandidate (i);
+-}
+-
+-};
+diff --git a/src/PYLibPinyinBaseEditor.h b/src/PYLibPinyinBaseEditor.h
+deleted file mode 100644
+index fa5755c..0000000
+--- a/src/PYLibPinyinBaseEditor.h
++++ /dev/null
+@@ -1,90 +0,0 @@
+-/* vim:set et ts=4 sts=4:
+- *
+- * ibus-pinyin - The Chinese PinYin engine for IBus
+- *
+- * Copyright (c) 2011 Peng Wu <alexepico at 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.
+- */
+-#ifndef __PY_LIB_PINYIN_BASE_EDITOR_H_
+-#define __PY_LIB_PINYIN_BASE_EDITOR_H_
+-
+-#include "PYLookupTable.h"
+-#include "PYEditor.h"
+-#include "PYPinyinParser.h"
+-#include "PYSpecialPhraseTable.h"
+-
+-namespace PY {
+-
+-class LibPinyinBaseEditor : public Editor {
+-public:
+- LibPinyinBaseEditor (PinyinProperties & props, Config & config);
+-
+-public:
+- /* virtual functions */
+- virtual void pageUp (void);
+- virtual void pageDown (void);
+- virtual void cursorUp (void);
+- virtual void cursorDown (void);
+- virtual void update (void);
+- virtual void reset (void);
+- virtual void candidateClicked (guint index, guint button, guint state);
+- virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+- virtual gboolean processSpace (guint keyval, guint keycode, guint modifiers);
+- virtual gboolean processFunctionKey (guint keyval, guint keycode, guint modifiers);
+- virtual void updateLookupTable ();
+- virtual void updateLookupTableFast ();
+- virtual gboolean fillLookupTableByPage ();
+-
+-protected:
+-
+- gboolean updateSpecialPhrases ();
+- gboolean selectCandidate (guint i);
+- gboolean selectCandidateInPage (guint i);
+-
+- void commit (const gchar *str);
+-
+- /* inline functions */
+-
+- /* pure virtual functions */
+- virtual gboolean insert (gint ch) = 0;
+- virtual gboolean removeCharBefore (void) = 0;
+- virtual gboolean removeCharAfter (void) = 0;
+- virtual gboolean removeWordBefore (void) = 0;
+- virtual gboolean removeWordAfter (void) = 0;
+- virtual gboolean moveCursorLeft (void) = 0;
+- virtual gboolean moveCursorRight (void) = 0;
+- virtual gboolean moveCursorLeftByWord (void) = 0;
+- virtual gboolean moveCursorRightByWord (void) = 0;
+- virtual gboolean moveCursorToBegin (void) = 0;
+- virtual gboolean moveCursorToEnd (void) = 0;
+- virtual void commit (void) = 0;
+- virtual void updateAuxiliaryText (void) = 0;
+- virtual void updatePreeditText (void) = 0;
+-
+- /* varibles */
+- PinyinArray m_pinyin;
+- guint m_pinyin_len;
+- LookupTable m_lookup_table;
+- String m_buffer;
+-
+- /* use LibPinyinBackEnd here. */
+- std::vector<std::string> m_special_phrases;
+- std::string m_selected_special_phrase;
+-};
+-
+-};
+-
+-#endif
+diff --git a/src/PYLibPinyinDoublePinyinEditor.h b/src/PYLibPinyinDoublePinyinEditor.h
+deleted file mode 100644
+index 5ed106f..0000000
+--- a/src/PYLibPinyinDoublePinyinEditor.h
++++ /dev/null
+@@ -1,57 +0,0 @@
+-/* vim:set et ts=4 sts=4:
+- *
+- * ibus-pinyin - The Chinese PinYin engine for IBus
+- *
+- * Copyright (c) 2011 Peng Wu <alexepico at 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.
+- */
+-#ifndef __PY_LIB_PINYIN_DOUBLE_PINYIN_EDITOR_H_
+-#define __PY_LIB_PINYIN_DOUBLE_PINYIN_EDITOR_H_
+-
+-#include "PYLibPinyinBaseEditor.h"
+-
+-namespace PY {
+-
+-class LibPinyinDoublePinyinEditor : public LibPinyinBaseEditor {
+-
+-public:
+- LibPinyinDoublePinyinEditor (PinyinProperties & props, Config & config);
+-
+- gboolean insert (gint ch);
+-
+- gboolean removeCharBefore (void);
+- gboolean removeCharAfter (void);
+- gboolean removeWordBefore (void);
+- gboolean removeWordAfter (void);
+-
+- gboolean moveCursorLeft (void);
+- gboolean moveCursorRight (void);
+- gboolean moveCursorLeftByWord (void);
+- gboolean moveCursorRightByWord (void);
+- gboolean moveCursorToBegin (void);
+- gboolean moveCursorToEnd (void);
+-
+- /* override virtual functions */
+- gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+- void reset (void);
+-
+-protected:
+- /* TODO: to be implemented. */
+-};
+-
+-};
+-
+-#endif
+diff --git a/src/PYLibPinyinFullPinyinEditor.h b/src/PYLibPinyinFullPinyinEditor.h
+deleted file mode 100644
+index dcc1728..0000000
+--- a/src/PYLibPinyinFullPinyinEditor.h
++++ /dev/null
+@@ -1,59 +0,0 @@
+-/* vim:set et ts=4 sts=4:
+- *
+- * ibus-pinyin - The Chinese PinYin engine for IBus
+- *
+- * Copyright (c) 2011 Peng Wu <alexepico at 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.
+- */
+-#ifndef __PY_LIB_PINYIN_FULL_PINYIN_EDITOR_H
+-#define __PY_LIB_PINYIN_FULL_PINYIN_EDITOR_H
+-
+-#include "PYLibPinyinBaseEditor.h"
+-
+-namespace PY {
+-
+-class LibPinyinFullPinyinEditor : public PinyinEditor {
+-
+-public:
+- LibPinyinFullPinyinEditor (PinyinProperties & props, Config & config);
+- ~LibPinyinFullPinyinEditor (void);
+-
+-public:
+- gboolean insert (gint ch);
+-
+- gboolean removeCharBefore (void);
+- gboolean removeCharAfter (void);
+- gboolean removeWordBefore (void);
+- gboolean removeWordAfter (void);
+-
+- gboolean moveCursorLeft (void);
+- gboolean moveCursorRight (void);
+- gboolean moveCursorLeftByWord (void);
+- gboolean moveCursorRightByWord (void);
+- gboolean moveCursorToBegin (void);
+- gboolean moveCursorToEnd (void);
+-
+- /* virtual functions */
+- virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+- virtual void reset (void);
+-
+-protected:
+- /* TODO: to be implemented. */
+-};
+-
+-};
+-
+-#endif
+diff --git a/src/PYPDoublePinyinEditor.h b/src/PYPDoublePinyinEditor.h
+new file mode 100644
+index 0000000..5ed106f
+--- /dev/null
++++ b/src/PYPDoublePinyinEditor.h
+@@ -0,0 +1,57 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_DOUBLE_PINYIN_EDITOR_H_
++#define __PY_LIB_PINYIN_DOUBLE_PINYIN_EDITOR_H_
++
++#include "PYLibPinyinBaseEditor.h"
++
++namespace PY {
++
++class LibPinyinDoublePinyinEditor : public LibPinyinBaseEditor {
++
++public:
++ LibPinyinDoublePinyinEditor (PinyinProperties & props, Config & config);
++
++ gboolean insert (gint ch);
++
++ gboolean removeCharBefore (void);
++ gboolean removeCharAfter (void);
++ gboolean removeWordBefore (void);
++ gboolean removeWordAfter (void);
++
++ gboolean moveCursorLeft (void);
++ gboolean moveCursorRight (void);
++ gboolean moveCursorLeftByWord (void);
++ gboolean moveCursorRightByWord (void);
++ gboolean moveCursorToBegin (void);
++ gboolean moveCursorToEnd (void);
++
++ /* override virtual functions */
++ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ void reset (void);
++
++protected:
++ /* TODO: to be implemented. */
++};
++
++};
++
++#endif
+diff --git a/src/PYPFullPinyinEditor.h b/src/PYPFullPinyinEditor.h
+new file mode 100644
+index 0000000..dcc1728
+--- /dev/null
++++ b/src/PYPFullPinyinEditor.h
+@@ -0,0 +1,59 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_FULL_PINYIN_EDITOR_H
++#define __PY_LIB_PINYIN_FULL_PINYIN_EDITOR_H
++
++#include "PYLibPinyinBaseEditor.h"
++
++namespace PY {
++
++class LibPinyinFullPinyinEditor : public PinyinEditor {
++
++public:
++ LibPinyinFullPinyinEditor (PinyinProperties & props, Config & config);
++ ~LibPinyinFullPinyinEditor (void);
++
++public:
++ gboolean insert (gint ch);
++
++ gboolean removeCharBefore (void);
++ gboolean removeCharAfter (void);
++ gboolean removeWordBefore (void);
++ gboolean removeWordAfter (void);
++
++ gboolean moveCursorLeft (void);
++ gboolean moveCursorRight (void);
++ gboolean moveCursorLeftByWord (void);
++ gboolean moveCursorRightByWord (void);
++ gboolean moveCursorToBegin (void);
++ gboolean moveCursorToEnd (void);
++
++ /* virtual functions */
++ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ virtual void reset (void);
++
++protected:
++ /* TODO: to be implemented. */
++};
++
++};
++
++#endif
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+new file mode 100644
+index 0000000..6fdd5ef
+--- /dev/null
++++ b/src/PYPPhoneticEditor.cc
+@@ -0,0 +1,332 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYLibPinyinBaseEditor.h"
++#include "PYConfig.h"
++#include "PYPinyinProperties.h"
++#include "PYSimpTradConverter.h"
++
++namespace PY {
++/* init static members */
++LibPinyinBaseEditor::LibPinyinBaseEditor (PinyinProperties &props,
++ Config &config):
++ Editor (props, config),
++ m_pinyin (MAX_PHRASE_LEN),
++ m_pinyin_len (0),
++ m_lookup_table (m_config.pageSize ())
++{
++}
++
++gboolean
++LibPinyinBaseEditor::processSpace (guint keyval, guint keycode,
++ guint modifiers)
++{
++ if (!m_text)
++ return FALSE;
++ if (cmshm_filter (modifiers) != 0)
++ return TRUE;
++ if (m_lookup_table.size () != 0) {
++ selectCandidate (m_lookup_table.cursorPos ());
++ } else {
++ commit ();
++ }
++ return TRUE;
++}
++
++gboolean
++LibPinyinBaseEditor::processFunctionKey (guint keyval, guint keycode, guint modifiers)
++{
++ if (m_text.empty ())
++ return FALSE;
++
++ /* ignore numlock */
++ modifiers = cmshm_filter (modifiers);
++
++ if (modifiers != 0 && modifiers != IBUS_CONTROL_MASK)
++ return TRUE;
++
++ /* process some cursor control keys */
++ if (modifiers == 0) { /* no modifiers. */
++ switch (keyval) {
++ case IBUS_Return:
++ case IBUS_KP_Enter:
++ commit ();
++ return TRUE;
++
++ case IBUS_BackSpace:
++ removeCharBefore ();
++ return TRUE;
++
++ case IBUS_Delete:
++ case IBUS_KP_Delete:
++ removeCharAfter ();
++ return TRUE;
++
++ case IBUS_Left:
++ case IBUS_KP_Left:
++ moveCursorLeft ();
++ return TRUE;
++
++ case IBUS_Right:
++ case IBUS_KP_Right:
++ moveCursorRight ();
++ return TRUE;
++
++ case IBUS_Home:
++ case IBUS_KP_Home:
++ moveCursorToBegin ();
++ return TRUE;
++
++ case IBUS_End:
++ case IBUS_KP_End:
++ moveCursorToEnd ();
++ return TRUE;
++
++ case IBUS_Up:
++ case IBUS_KP_Up:
++ cursorUp ();
++ return TRUE;
++
++ case IBUS_Down:
++ case IBUS_KP_Down:
++ cursorDown ();
++ return TRUE;
++
++ case IBUS_Page_Up:
++ case IBUS_KP_Page_Up:
++ pageUp ();
++ return TRUE;
++
++ case IBUS_Page_Down:
++ case IBUS_KP_Page_Down:
++ case IBUS_Tab:
++ pageDown ();
++ return TRUE;
++
++ case IBUS_Escape:
++ reset ();
++ return TRUE;
++ default:
++ return TRUE;
++ }
++ } else { /* ctrl key pressed. */
++ switch (keyval) {
++ case IBUS_BackSpace:
++ removeWordBefore ();
++ return TRUE;
++
++ case IBUS_Delete:
++ case IBUS_KP_Delete:
++ removeWordAfter ();
++ return TRUE;
++
++ case IBUS_Left:
++ case IBUS_KP_Left:
++ moveCursorLeftByWord ();
++ return TRUE;
++
++ case IBUS_Right:
++ case IBUS_KP_Right:
++ moveCursorToEnd ();
++ return TRUE;
++
++ default:
++ return TRUE;
++ }
++ }
++ return TRUE;
++}
++
++gboolean
++LibPinyinBaseEditor::processKeyEvent (guint keyval, guint keycode, guint modifiers)
++{
++ return FALSE;
++}
++
++gboolean
++LibPinyinBaseEditor::updateSpecialPhrases (void)
++{
++ guint size = m_special_phrases.size();
++ m_special_phrases.clear ();
++
++ if (!m_config.specialPhrases ())
++ return FALSE;
++
++ if (!m_selected_special_phrase.empty ())
++ return FALSE;
++
++ /* Note: change behavior to match the entire m_text,
++ * instead of partial m_text.
++ */
++ SpecialPhraseTable::instance ().lookup
++ (m_text, m_special_phrases);
++
++ return size != m_special_phrases.size() || size != 0;
++}
++
++void
++LibPinyinBaseEditor::updateLookupTableFast (void)
++{
++ Editor::updateLookupTableFast (m_lookup_table, TRUE);
++}
++
++void
++LibPinyinBaseEditor::updateLookupTable (void)
++{
++ m_lookup_table.clear ();
++
++ fillLookupTableByPage ();
++ if (m_lookup_table.size()) {
++ Editor::updateLookupTable (m_lookup_table, TRUE);
++ } else {
++ hideLookupTable ();
++ }
++}
++
++gboolean
++LibPinyinBaseEditor::fillLookupTableByPage (void)
++{
++ if (!m_selected_special_phrase.empty ()) {
++ return FALSE;
++ }
++
++ guint filled_nr = m_lookup_table.size ();
++ guint page_size = m_lookup_table.pageSize ();
++
++ /* fill lookup table by libpinyin get candidates. */
++ g_assert(FALSE);
++}
++
++void
++LibPinyinBaseEditor::pageUp (void)
++{
++ if (G_LIKELY (m_lookup_table.pageUp ())) {
++ updateLookupTableFast ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++ }
++}
++
++void
++LibPinyinBaseEditor::pageDown (void)
++{
++ if (G_LIKELY((m_lookup_table.pageDown ()) ||
++ (fillLookupTableByPage () && m_lookup_table.pageDown()))) {
++ updateLookupTableFast ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++ }
++}
++
++void
++LibPinyinBaseEditor::cursorUp (void)
++{
++ if (G_LIKELY (m_lookup_table.cursorUp ())) {
++ updateLookupTableFast ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++ }
++}
++
++void
++LibPinyinBaseEditor::cursorDown (void)
++{
++ if (G_LIKELY ((m_lookup_table.cursorPos () == m_lookup_table.size() - 1) &&
++ (fillLookupTableByPage () == FALSE))) {
++ return;
++ }
++
++ if (G_LIKELY (m_lookup_table.cursorDown ())) {
++ updateLookupTableFast ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++ }
++}
++
++void
++LibPinyinBaseEditor::candidateClicked (guint index, guint button, guint state)
++{
++ selectCandidateInPage (index);
++}
++
++void
++LibPinyinBaseEditor::reset (void)
++{
++ m_pinyin.clear ();
++ m_pinyin_len = 0;
++ m_lookup_table.clear ();
++ m_special_phrases.clear ();
++ m_selected_special_phrase.clear ();
++
++ Editor::reset ();
++}
++
++void
++LibPinyinBaseEditor::update (void)
++{
++ updateLookupTable ();
++ updatePreeditText ();
++ updateAuxiliaryText ();
++}
++
++void
++LibPinyinBaseEditor::commit (const gchar *str)
++{
++ StaticText text(str);
++ commitText (text);
++}
++
++gboolean
++LibPinyinBaseEditor::selectCandidate (guint i)
++{
++
++ if (i < m_special_phrases.size ()) {
++ /* select a special phrase */
++ m_selected_special_phrase = m_special_phrases[i];
++ if (m_cursor == m_text.size()) {
++ m_buffer = m_selected_special_phrase;
++ reset ();
++ commit ((const gchar *)m_buffer);
++ } else {
++ updateSpecialPhrases ();
++ update ();
++ }
++ return TRUE;
++ }
++
++ i -= m_special_phrases.size ();
++ /* TODO: deal with normal candidates selection here by libpinyin. */
++ g_assert (FALSE);
++}
++
++gboolean
++LibPinyinBaseEditor::selectCandidateInPage (guint i)
++{
++ guint page_size = m_lookup_table.pageSize ();
++ guint cursor_pos = m_lookup_table.cursorPos ();
++
++ if (G_UNLIKELY (i >= page_size))
++ return FALSE;
++ i += (cursor_pos / page_size) * page_size;
++
++ return selectCandidate (i);
++}
++
++};
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+new file mode 100644
+index 0000000..fa5755c
+--- /dev/null
++++ b/src/PYPPhoneticEditor.h
+@@ -0,0 +1,90 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_BASE_EDITOR_H_
++#define __PY_LIB_PINYIN_BASE_EDITOR_H_
++
++#include "PYLookupTable.h"
++#include "PYEditor.h"
++#include "PYPinyinParser.h"
++#include "PYSpecialPhraseTable.h"
++
++namespace PY {
++
++class LibPinyinBaseEditor : public Editor {
++public:
++ LibPinyinBaseEditor (PinyinProperties & props, Config & config);
++
++public:
++ /* virtual functions */
++ virtual void pageUp (void);
++ virtual void pageDown (void);
++ virtual void cursorUp (void);
++ virtual void cursorDown (void);
++ virtual void update (void);
++ virtual void reset (void);
++ virtual void candidateClicked (guint index, guint button, guint state);
++ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ virtual gboolean processSpace (guint keyval, guint keycode, guint modifiers);
++ virtual gboolean processFunctionKey (guint keyval, guint keycode, guint modifiers);
++ virtual void updateLookupTable ();
++ virtual void updateLookupTableFast ();
++ virtual gboolean fillLookupTableByPage ();
++
++protected:
++
++ gboolean updateSpecialPhrases ();
++ gboolean selectCandidate (guint i);
++ gboolean selectCandidateInPage (guint i);
++
++ void commit (const gchar *str);
++
++ /* inline functions */
++
++ /* pure virtual functions */
++ virtual gboolean insert (gint ch) = 0;
++ virtual gboolean removeCharBefore (void) = 0;
++ virtual gboolean removeCharAfter (void) = 0;
++ virtual gboolean removeWordBefore (void) = 0;
++ virtual gboolean removeWordAfter (void) = 0;
++ virtual gboolean moveCursorLeft (void) = 0;
++ virtual gboolean moveCursorRight (void) = 0;
++ virtual gboolean moveCursorLeftByWord (void) = 0;
++ virtual gboolean moveCursorRightByWord (void) = 0;
++ virtual gboolean moveCursorToBegin (void) = 0;
++ virtual gboolean moveCursorToEnd (void) = 0;
++ virtual void commit (void) = 0;
++ virtual void updateAuxiliaryText (void) = 0;
++ virtual void updatePreeditText (void) = 0;
++
++ /* varibles */
++ PinyinArray m_pinyin;
++ guint m_pinyin_len;
++ LookupTable m_lookup_table;
++ String m_buffer;
++
++ /* use LibPinyinBackEnd here. */
++ std::vector<std::string> m_special_phrases;
++ std::string m_selected_special_phrase;
++};
++
++};
++
++#endif
+--
+1.7.6.4
+
+
+From b8f7e09a3316035b2b497386885a41e52da7b664 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 2 Sep 2011 15:39:31 +0800
+Subject: [PATCH 10/71] add libpinyin pinyin editor header
+
+---
+ src/PYPPinyinEditor.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 56 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPPinyinEditor.h
+
+diff --git a/src/PYPPinyinEditor.h b/src/PYPPinyinEditor.h
+new file mode 100644
+index 0000000..4213395
+--- /dev/null
++++ b/src/PYPPinyinEditor.h
+@@ -0,0 +1,56 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_PINYIN_EDITOR_H_
++#define __PY_LIB_PINYIN_PINYIN_EDITOR_H_
++
++#include "PYPPhoneticEditor.h"
++
++namespace PY {
++
++class Config;
++
++#define MAX_PINYIN_LEN 64
++
++class SpecialPhraseTable;
++
++class LibPinyinPinyinEditor : public LibPinyinPhoneticEditor {
++public:
++ LibPinyinPinyinEditor (PinyinProperties & props, Config & config);
++
++protected:
++ gboolean processPinyin (guint keyval, guint keycode, guint modifiers);
++ gboolean processNumber (guint keyval, guint keycode, guint modifiers);
++ gboolean processPunct (guint keyval, guint keycode, guint modifiers);
++ gboolean processFunctionKey (guint keyval, guint keycode, guint modifiers);
++
++ void commit ();
++
++ void updateAuxiliaryText (void);
++ void updateLookupTable (void);
++ void updatePreeditText (void);
++
++ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++
++};
++
++};
++
++#endif
+--
+1.7.6.4
+
+
+From 0d7fdc1f9b71df881fa4353fc0f20a0839c0c78c Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 2 Sep 2011 15:49:13 +0800
+Subject: [PATCH 11/71] rename base editor
+
+---
+ src/Makefile.am | 6 +++-
+ src/PYPDoublePinyinEditor.h | 4 +-
+ src/PYPFullPinyinEditor.h | 4 +-
+ src/PYPPhoneticEditor.cc | 47 ++++++++++++++++++++++---------------------
+ src/PYPPhoneticEditor.h | 4 +-
+ src/PYPPinyinEditor.cc | 22 ++++++++++++++++++++
+ src/PYPPinyinEditor.h | 4 +-
+ 7 files changed, 58 insertions(+), 33 deletions(-)
+ create mode 100644 src/PYPPinyinEditor.cc
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index a104c75..ddebb04 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -64,7 +64,8 @@ ibus_engine_pinyin_c_sources = \
+ PYDynamicSpecialPhrase.cc \
+ PYSpecialPhrase.cc \
+ PYSpecialPhraseTable.cc \
+- PYLibPinyinBaseEditor.cc \
++ PYPPhoneticEditor.cc \
++ PYPPinyinEditor.cc \
+ $(NULL)
+ ibus_engine_pinyin_h_sources = \
+ PYBopomofo.h \
+@@ -108,7 +109,8 @@ ibus_engine_pinyin_h_sources = \
+ PYUtil.h \
+ PYEnglishEditor.h \
+ PYLibPinyin.h \
+- PYLibPinyinBaseEditor.h \
++ PYPPhoneticEditor.h \
++ PYPPinyinEditor.h \
+ $(NULL)
+
+ if IBUS_BUILD_LUA_EXTENSION
+diff --git a/src/PYPDoublePinyinEditor.h b/src/PYPDoublePinyinEditor.h
+index 5ed106f..35baa6f 100644
+--- a/src/PYPDoublePinyinEditor.h
++++ b/src/PYPDoublePinyinEditor.h
+@@ -21,11 +21,11 @@
+ #ifndef __PY_LIB_PINYIN_DOUBLE_PINYIN_EDITOR_H_
+ #define __PY_LIB_PINYIN_DOUBLE_PINYIN_EDITOR_H_
+
+-#include "PYLibPinyinBaseEditor.h"
++#include "PYPPinyinEditor.h"
+
+ namespace PY {
+
+-class LibPinyinDoublePinyinEditor : public LibPinyinBaseEditor {
++class LibPinyinDoublePinyinEditor : public LibPinyinPinyinEditor {
+
+ public:
+ LibPinyinDoublePinyinEditor (PinyinProperties & props, Config & config);
+diff --git a/src/PYPFullPinyinEditor.h b/src/PYPFullPinyinEditor.h
+index dcc1728..a6e74c4 100644
+--- a/src/PYPFullPinyinEditor.h
++++ b/src/PYPFullPinyinEditor.h
+@@ -21,11 +21,11 @@
+ #ifndef __PY_LIB_PINYIN_FULL_PINYIN_EDITOR_H
+ #define __PY_LIB_PINYIN_FULL_PINYIN_EDITOR_H
+
+-#include "PYLibPinyinBaseEditor.h"
++#include "PYPPinyinEditor.h"
+
+ namespace PY {
+
+-class LibPinyinFullPinyinEditor : public PinyinEditor {
++class LibPinyinFullPinyinEditor : public LibPinyinPinyinEditor {
+
+ public:
+ LibPinyinFullPinyinEditor (PinyinProperties & props, Config & config);
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index 6fdd5ef..ef9a02d 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -18,15 +18,16 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+-#include "PYLibPinyinBaseEditor.h"
++#include "PYPPhoneticEditor.h"
+ #include "PYConfig.h"
+ #include "PYPinyinProperties.h"
+ #include "PYSimpTradConverter.h"
+
+-namespace PY {
++using namespace PY;
++
+ /* init static members */
+-LibPinyinBaseEditor::LibPinyinBaseEditor (PinyinProperties &props,
+- Config &config):
++LibPinyinPhoneticEditor::LibPinyinPhoneticEditor (PinyinProperties &props,
++ Config &config):
+ Editor (props, config),
+ m_pinyin (MAX_PHRASE_LEN),
+ m_pinyin_len (0),
+@@ -35,8 +36,8 @@ LibPinyinBaseEditor::LibPinyinBaseEditor (PinyinProperties &props,
+ }
+
+ gboolean
+-LibPinyinBaseEditor::processSpace (guint keyval, guint keycode,
+- guint modifiers)
++LibPinyinPhoneticEditor::processSpace (guint keyval, guint keycode,
++ guint modifiers)
+ {
+ if (!m_text)
+ return FALSE;
+@@ -51,7 +52,7 @@ LibPinyinBaseEditor::processSpace (guint keyval, guint keycode,
+ }
+
+ gboolean
+-LibPinyinBaseEditor::processFunctionKey (guint keyval, guint keycode, guint modifiers)
++LibPinyinPhoneticEditor::processFunctionKey (guint keyval, guint keycode, guint modifiers)
+ {
+ if (m_text.empty ())
+ return FALSE;
+@@ -155,13 +156,13 @@ LibPinyinBaseEditor::processFunctionKey (guint keyval, guint keycode, guint modi
+ }
+
+ gboolean
+-LibPinyinBaseEditor::processKeyEvent (guint keyval, guint keycode, guint modifiers)
++LibPinyinPhoneticEditor::processKeyEvent (guint keyval, guint keycode, guint modifiers)
+ {
+ return FALSE;
+ }
+
+ gboolean
+-LibPinyinBaseEditor::updateSpecialPhrases (void)
++LibPinyinPhoneticEditor::updateSpecialPhrases (void)
+ {
+ guint size = m_special_phrases.size();
+ m_special_phrases.clear ();
+@@ -182,13 +183,13 @@ LibPinyinBaseEditor::updateSpecialPhrases (void)
+ }
+
+ void
+-LibPinyinBaseEditor::updateLookupTableFast (void)
++LibPinyinPhoneticEditor::updateLookupTableFast (void)
+ {
+ Editor::updateLookupTableFast (m_lookup_table, TRUE);
+ }
+
+ void
+-LibPinyinBaseEditor::updateLookupTable (void)
++LibPinyinPhoneticEditor::updateLookupTable (void)
+ {
+ m_lookup_table.clear ();
+
+@@ -201,7 +202,7 @@ LibPinyinBaseEditor::updateLookupTable (void)
+ }
+
+ gboolean
+-LibPinyinBaseEditor::fillLookupTableByPage (void)
++LibPinyinPhoneticEditor::fillLookupTableByPage (void)
+ {
+ if (!m_selected_special_phrase.empty ()) {
+ return FALSE;
+@@ -215,7 +216,7 @@ LibPinyinBaseEditor::fillLookupTableByPage (void)
+ }
+
+ void
+-LibPinyinBaseEditor::pageUp (void)
++LibPinyinPhoneticEditor::pageUp (void)
+ {
+ if (G_LIKELY (m_lookup_table.pageUp ())) {
+ updateLookupTableFast ();
+@@ -225,7 +226,7 @@ LibPinyinBaseEditor::pageUp (void)
+ }
+
+ void
+-LibPinyinBaseEditor::pageDown (void)
++LibPinyinPhoneticEditor::pageDown (void)
+ {
+ if (G_LIKELY((m_lookup_table.pageDown ()) ||
+ (fillLookupTableByPage () && m_lookup_table.pageDown()))) {
+@@ -236,7 +237,7 @@ LibPinyinBaseEditor::pageDown (void)
+ }
+
+ void
+-LibPinyinBaseEditor::cursorUp (void)
++LibPinyinPhoneticEditor::cursorUp (void)
+ {
+ if (G_LIKELY (m_lookup_table.cursorUp ())) {
+ updateLookupTableFast ();
+@@ -246,7 +247,7 @@ LibPinyinBaseEditor::cursorUp (void)
+ }
+
+ void
+-LibPinyinBaseEditor::cursorDown (void)
++LibPinyinPhoneticEditor::cursorDown (void)
+ {
+ if (G_LIKELY ((m_lookup_table.cursorPos () == m_lookup_table.size() - 1) &&
+ (fillLookupTableByPage () == FALSE))) {
+@@ -261,13 +262,13 @@ LibPinyinBaseEditor::cursorDown (void)
+ }
+
+ void
+-LibPinyinBaseEditor::candidateClicked (guint index, guint button, guint state)
++LibPinyinPhoneticEditor::candidateClicked (guint index, guint button, guint state)
+ {
+ selectCandidateInPage (index);
+ }
+
+ void
+-LibPinyinBaseEditor::reset (void)
++LibPinyinPhoneticEditor::reset (void)
+ {
+ m_pinyin.clear ();
+ m_pinyin_len = 0;
+@@ -279,7 +280,7 @@ LibPinyinBaseEditor::reset (void)
+ }
+
+ void
+-LibPinyinBaseEditor::update (void)
++LibPinyinPhoneticEditor::update (void)
+ {
+ updateLookupTable ();
+ updatePreeditText ();
+@@ -287,14 +288,14 @@ LibPinyinBaseEditor::update (void)
+ }
+
+ void
+-LibPinyinBaseEditor::commit (const gchar *str)
++LibPinyinPhoneticEditor::commit (const gchar *str)
+ {
+ StaticText text(str);
+ commitText (text);
+ }
+
+ gboolean
+-LibPinyinBaseEditor::selectCandidate (guint i)
++LibPinyinPhoneticEditor::selectCandidate (guint i)
+ {
+
+ if (i < m_special_phrases.size ()) {
+@@ -317,7 +318,7 @@ LibPinyinBaseEditor::selectCandidate (guint i)
+ }
+
+ gboolean
+-LibPinyinBaseEditor::selectCandidateInPage (guint i)
++LibPinyinPhoneticEditor::selectCandidateInPage (guint i)
+ {
+ guint page_size = m_lookup_table.pageSize ();
+ guint cursor_pos = m_lookup_table.cursorPos ();
+@@ -329,4 +330,4 @@ LibPinyinBaseEditor::selectCandidateInPage (guint i)
+ return selectCandidate (i);
+ }
+
+-};
++
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index fa5755c..3d64bc4 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -28,9 +28,9 @@
+
+ namespace PY {
+
+-class LibPinyinBaseEditor : public Editor {
++class LibPinyinPhoneticEditor : public Editor {
+ public:
+- LibPinyinBaseEditor (PinyinProperties & props, Config & config);
++ LibPinyinPhoneticEditor (PinyinProperties & props, Config & config);
+
+ public:
+ /* virtual functions */
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+new file mode 100644
+index 0000000..a259a99
+--- /dev/null
++++ b/src/PYPPinyinEditor.cc
+@@ -0,0 +1,22 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYPPinyinEditor.h"
+diff --git a/src/PYPPinyinEditor.h b/src/PYPPinyinEditor.h
+index 4213395..fd2b2ce 100644
+--- a/src/PYPPinyinEditor.h
++++ b/src/PYPPinyinEditor.h
+@@ -25,10 +25,10 @@
+
+ namespace PY {
+
+-class Config;
+-
+ #define MAX_PINYIN_LEN 64
+
++class Config;
++
+ class SpecialPhraseTable;
+
+ class LibPinyinPinyinEditor : public LibPinyinPhoneticEditor {
+--
+1.7.6.4
+
+
+From 21c05a2bf76d58a2928fd6e93c2e1f561129ee8f Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 2 Sep 2011 16:49:00 +0800
+Subject: [PATCH 12/71] begin to write pinyin editor
+
+---
+ src/PYPPinyinEditor.cc | 202 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 202 insertions(+), 0 deletions(-)
+
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index a259a99..a78544d 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -20,3 +20,205 @@
+ */
+
+ #include "PYPPinyinEditor.h"
++#include "PYConfig.h"
++#include "PYPinyinProperties.h"
++#include "PYSimpTradConverter.h"
++#include "PYHalfFullConverter.h"
++
++using namespace PY;
++
++/* init static members*/
++LibPinyinPinyinEditor::LibPinyinPinyinEditor (PinyinProperties & props,
++ Config & config)
++ : LibPinyinPhoneticEditor (props, config)
++{
++}
++
++
++/**
++ * process pinyin
++ */
++inline gboolean
++LibPinyinPinyinEditor::processPinyin (guint keyval, guint keycode,
++ guint modifiers)
++{
++ if (G_UNLIKELY (cmshm_filter (modifiers) != 0))
++ return m_text ? TRUE : FALSE;
++
++ return insert (keyval);
++}
++
++/**
++ * process numbers
++ */
++inline gboolean
++LibPinyinPinyinEditor::processNumber (guint keyval, guint keycode,
++ guint modifiers)
++{
++ guint i;
++
++ if (!m_text)
++ return FALSE;
++
++ switch (keyval) {
++ case IBUS_0:
++ case IBUS_KP_0:
++ i = 9;
++ break;
++ case IBUS_1 ... IBUS_9:
++ i = keyval - IBUS_1;
++ break;
++ case IBUS_KP_1 ... IBUS_KP_9:
++ i = keyval - IBUS_KP_1;
++ break;
++ default:
++ g_return_val_if_reached (FALSE);
++ }
++
++ if (modifiers == 0)
++ selectCandidateInPage (i);
++
++ return TRUE;
++}
++
++inline gboolean
++LibPinyinPinyinEditor::processPunct (guint keyval, guint keycode,
++ guint modifiers)
++{
++ if (m_text.empty ())
++ return FALSE;
++
++ if (cmshm_filter (modifiers) != 0)
++ return TRUE;
++
++ switch (keyval) {
++ case IBUS_apostrophe:
++ return insert (keyval);
++ case IBUS_comma:
++ if (m_config.commaPeriodPage ()) {
++ pageUp ();
++ return TRUE;
++ }
++ break;
++ case IBUS_minus:
++ if (m_config.minusEqualPage ()) {
++ pageUp ();
++ return TRUE;
++ }
++ break;
++ case IBUS_period:
++ if (m_config.commaPeriodPage ()) {
++ pageDown ();
++ return TRUE;
++ }
++ break;
++ case IBUS_equal:
++ if (m_config.minusEqualPage ()) {
++ pageDown ();
++ return TRUE;
++ }
++ break;
++ }
++
++ if (m_config.autoCommit ()) {
++ if (m_lookup_table.size ()) {
++ /* TODO: check here. */
++ selectCandidate (m_lookup_table.cursorPos ());
++ }
++ commit ();
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++inline gboolean
++LibPinyinPinyinEditor::processFunctionKey (guint keyval, guint keycode,
++ guint modifiers)
++{
++ if (m_text.empty ())
++ return FALSE;
++
++ /* ignore numlock */
++ modifiers = cmshm_filter (modifiers);
++
++ if (modifiers != 0 && modifiers != IBUS_CONTROL_MASK)
++ return TRUE;
++
++ /* process some cursor control keys */
++ if (modifiers == 0) { /* no modifiers. */
++ switch (keyval) {
++ case IBUS_Shift_L:
++ if (!m_config.shiftSelectCandidate ())
++ return FALSE;
++ selectCandidateInPage (1);
++ return TRUE;
++
++ case IBUS_Shift_R:
++ if (!m_config.shiftSelectCandidate ())
++ return FALSE;
++ selectCandidateInPage (2);
++ return TRUE;
++ }
++ }
++
++ return LibPinyinPhoneticEditor::processFunctionKey (keyval, keycode,
++ modifiers);
++}
++
++gboolean
++LibPinyinPinyinEditor::processKeyEvent (guint keyval, guint keycode,
++ guint modifiers)
++{
++ modifiers &= (IBUS_SHIFT_MASK |
++ IBUS_CONTROL_MASK |
++ IBUS_MOD1_MASK |
++ IBUS_SUPER_MASK |
++ IBUS_HYPER_MASK |
++ IBUS_META_MASK |
++ IBUS_LOCK_MASK);
++
++ switch (keyval) {
++ /* letters */
++ case IBUS_a ... IBUS_z:
++ return processPinyin (keyval, keycode, modifiers);
++ case IBUS_0 ... IBUS_9:
++ case IBUS_KP_0 ... IBUS_KP_9:
++ return processNumber (keyval, keycode, modifiers);
++ case IBUS_exclam ... IBUS_slash:
++ case IBUS_colon ... IBUS_at:
++ case IBUS_bracketleft ... IBUS_quoteleft:
++ case IBUS_braceleft ... IBUS_asciitilde:
++ return processPunct (keyval, keycode, modifiers);
++ case IBUS_space:
++ return processSpace (keyval, keycode, modifiers);
++ default:
++ return processFunctionKey (keyval, keycode, modifiers);
++ }
++}
++
++void
++LibPinyinPinyinEditor::commit ()
++{
++ g_assert (FALSE);
++}
++
++void
++LibPinyinPinyinEditor::updatePreeditText ()
++{
++ g_assert (FALSE);
++}
++
++void
++LibPinyinPinyinEditor::updateAuxiliaryText ()
++{
++ g_assert (FALSE);
++}
++
++void
++LibPinyinPinyinEditor::updateLookupTable ()
++{
++ m_lookup_table.setPageSize (m_config.pageSize ());
++ m_lookup_table.setOrientation (m_config.orientation ());
++ LibPinyinPhoneticEditor::updateLookupTable ();
++}
+--
+1.7.6.4
+
+
+From b79504595353a90d85b025ab6f3bb426787f26b3 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 5 Sep 2011 16:59:49 +0800
+Subject: [PATCH 13/71] begin to write bopomofo editor
+
+---
+ src/PYPBopomofoEditor.cc | 374 ++++++++++++++++++++++++++++++++++++++++++++++
+ src/PYPBopomofoEditor.h | 77 ++++++++++
+ 2 files changed, 451 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPBopomofoEditor.cc
+ create mode 100644 src/PYPBopomofoEditor.h
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+new file mode 100644
+index 0000000..75c8ddc
+--- /dev/null
++++ b/src/PYPBopomofoEditor.cc
+@@ -0,0 +1,374 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYPBopomofoEditor.h"
++#include "PYConfig.h"
++#include "PYPinyinProperties.h"
++#include "PYSimpTradConverter.h"
++
++namespace PY {
++#include "PYBopomofoKeyboard.h"
++};
++
++using namespace PY;
++
++const static gchar * bopomofo_select_keys[] = {
++ "1234567890",
++ "asdfghjkl;",
++ "1qaz2wsxed",
++ "asdfzxcvgb",
++ "1234qweras",
++ "aoeu;qjkix",
++ "aoeuhtnsid",
++ "aoeuidhtns",
++ "qweasdzxcr"
++};
++
++LibPinyinBopomofoEditor::LibPinyinBopomofoEditor
++(PinyinProperties & props, Config & config)
++ : LibPinyinPhoneticEditor (props, config),
++ m_select_mode (FALSE)
++{
++}
++
++LibPinyinBopomofoEditor::~LibPinyinBopomofoEditor (void)
++{
++}
++
++void
++LibPinyinBopomofoEditor::reset (void)
++{
++ m_select_mode = FALSE;
++ LibPinyinPhoneticEditor::reset ();
++}
++
++gboolean
++LibPinyinBopomofoEditor::insert (gint ch)
++{
++ /* is full */
++ if (G_UNLIKELY (m_text.length () >= MAX_PINYIN_LEN))
++ return TRUE;
++
++ m_text.insert (m_cursor++, ch);
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::removeCharBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor --;
++ m_text.erase (m_cursor, 1);
++ update();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::removeCharAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_text.erase (m_cursor, 1);
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::removeWordBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ guint cursor;
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_pinyin_len;
++ } else {
++ const Pinyin & p = *m_pinyin.back ();
++ cursor = m_cursor - p.len;
++ m_pinyin_len -= p.len;
++ m_pinyin.pop_back ();
++ }
++
++ m_text.erase (cursor, m_cursor - cursor);
++ m_cursor = cursor;
++ update();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::removeWordAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ /* TODO: remove one word instead of the sentence. */
++ m_text.erase (m_cursor, -1);
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::moveCursorLeft (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor --;
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::moveCursorRight (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_cursor ++;
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::moveCursorLeftByWord (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ m_cursor = m_pinyin_len;
++ return TRUE;
++ }
++
++ const Pinyin & p = *m_pinyin.back ();
++ m_cursor -= p.len;
++ m_pinyin_len -= p.len;
++ m_pinyin.pop_back ();
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::moveCursorRightByWord (void)
++{
++ return moveCursorToEnd ();
++}
++
++gboolean
++LibPinyinBopomofoEditor::moveCursorToBegin (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor = 0;
++ update();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::moveCursorToEnd (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_cursor = m_text.length ();
++ update();
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::processGuideKey (guint keyval, guint keycode,
++ guint modifiers)
++{
++ if (!m_config.guideKey ())
++ return FALSE;
++
++ if (G_UNLIKELY (cmshm_filter (modifiers) != 0))
++ return FALSE;
++
++ if (G_LIKELY (m_select_mode))
++ return FALSE;
++
++ if (G_UNLIKELY (keyval == IBUS_space)) {
++ m_select_mode = TRUE;
++ update ();
++ return TRUE;
++ }
++
++ return FALSE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::processAuxiliarySelectKey
++(guint keyval, guint keycode, guint modifiers)
++{
++ if (G_UNLIKELY (cmshm_filter (modifiers) != 0))
++ return FALSE;
++
++ guint i;
++
++ switch (keyval) {
++ case IBUS_KP_0:
++ i = 9;
++ if (!m_config.auxiliarySelectKeyKP ())
++ return FALSE;
++ break;
++ case IBUS_KP_1 ... IBUS_KP_9:
++ i = keyval - IBUS_KP_1;
++ if (!m_config.auxiliarySelectKeyKP ())
++ return FALSE;
++ break;
++ case IBUS_F1 ... IBUS_F10:
++ i = keyval - IBUS_F1;
++ if (!m_config.auxiliarySelectKeyF ())
++ return FALSE;
++ break;
++ default:
++ return FALSE;
++ }
++
++ m_select_mode = TRUE;
++ selectCandidateInPage (i);
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::processSelectKey (guint keyval, guint keycode,
++ guint modifiers)
++{
++ if (G_UNLIKELY (!m_text))
++ return FALSE;
++
++ if (G_LIKELY (!m_select_mode && ((modifiers & IBUS_MOD1_MASK) == 0)))
++ return FALSE;
++
++ const gchar * pos = NULL;
++ const gchar * keys = bopomofo_select_keys[m_config.selectKeys ()];
++ for ( const gchar * p = keys; *p != NULL; ++p ) {
++ if ( *p == keyval )
++ pos = p;
++ }
++
++ if (pos == NULL)
++ return FALSE;
++
++ m_select_mode = TRUE;
++
++ guint i = pos - keys;
++ selectCandidateInPage (i);
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::processBopomofo (guint keyval, guint keycode,
++ guint modifiers)
++{
++ if (G_UNLIKELY (cmshm_filter (modifiers) != 0))
++ return m_text ? TRUE : FALSE;
++
++ if (keyvalToBopomofo (keyval) == BOPOMOFO_ZERO)
++ return FALSE;
++
++ m_select_mode = FALSE;
++
++ return insert (keyval);
++}
++
++gboolean
++LibPinyinBopomofoEditor::processKeyEvent (guint keyval, guint keycode,
++ guint modifiers)
++{
++ modifiers &= (IBUS_SHIFT_MASK |
++ IBUS_CONTROL_MASK |
++ IBUS_MOD1_MASK |
++ IBUS_SUPER_MASK |
++ IBUS_HYPER_MASK |
++ IBUS_META_MASK |
++ IBUS_LOCK_MASK);
++
++ if (G_UNLIKELY (processGuideKey (keyval, keycode, modifiers)))
++ return TRUE;
++ if (G_UNLIKELY (processSelectKey (keyval, keycode, modifiers)))
++ return TRUE;
++ if (G_UNLIKELY (processAuxiliarySelectKey (keyval, keycode,
++ modifiers)))
++ return TRUE;
++ if (G_LIKELY (processBopomofo (keyval, keycode, modifiers)))
++ return TRUE;
++
++ switch (keyval) {
++ case IBUS_space:
++ m_select_mode = TRUE;
++ return processSpace (keyval, keycode, modifiers);
++
++ case IBUS_Up: case IBUS_KP_Up:
++ case IBUS_Down: case IBUS_KP_Down:
++ case IBUS_Page_Up: case IBUS_KP_Page_Up:
++ case IBUS_Page_Down: case IBUS_KP_Page_Down:
++ case IBUS_Tab:
++ m_select_mode = TRUE;
++ return LibPinyinPhoneticEditor::processFunctionKey
++ (keyval, keycode, modifiers);
++
++ case IBUS_BackSpace:
++ case IBUS_Delete: case IBUS_KP_Delete:
++ case IBUS_Left: case IBUS_KP_Left:
++ case IBUS_Right: case IBUS_KP_Right:
++ case IBUS_Home: case IBUS_KP_Home:
++ case IBUS_End: case IBUS_KP_End:
++ m_select_mode = FALSE;
++ return LibPinyinPhoneticEditor::processFunctionKey
++ (keyval, keycode, modifiers);
++
++ default:
++ return LibPinyinPhoneticEditor::processFunctionKey
++ (keyval, keycode, modifiers);
++ }
++ return FALSE;
++}
++
++gint
++LibPinyinBopomofoEditor::keyvalToBopomofo(gint ch)
++{
++ const gint keyboard = m_config.bopomofoKeyboardMapping ();
++ const guint8 & keys[41][2] = bopomofo_keyboard[keyboard];
++ gint len = G_N_ELEMENTS (bopomofo_keyboard[keyboard]);
++
++ for ( size_t i = 0; i < len; ++i ) {
++ if ( keys[i][0] == ch )
++ return keys[i][1];
++ }
++
++ return BOPOMOFO_ZERO;
++}
+diff --git a/src/PYPBopomofoEditor.h b/src/PYPBopomofoEditor.h
+new file mode 100644
+index 0000000..bcbf85d
+--- /dev/null
++++ b/src/PYPBopomofoEditor.h
+@@ -0,0 +1,77 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_BOPOMOFO_EDITOR_H_
++#define __PY_LIB_PINYIN_BOPOMOFO_EDITOR_H_
++
++#include "PYPPhoneticEditor.h"
++
++namespace PY {
++
++class Config;
++
++#define MAX_PINYIN_LEN 64
++
++class LibPinyinBopomofoEditor : public LibPinyinPhoneticEditor {
++
++public:
++ LibPinyinBopomofoEditor (PinyinProperties & props, Config & config);
++ ~LibPinyinBopomofoEditor (void);
++
++protected:
++ String bopomofo;
++ gboolean m_select_mode;
++
++ gboolean processGuideKey (guint keyval, guint keycode, guint modifiers);
++ gboolean processAuxiliarySelectKey (guint keyval, guint keycode,
++ guint modifiers);
++ gboolean processSelectKey (guint keyval, guint keycode, guint modifiers);
++ gboolean processBopomofo (guint keyval, guint keycode, guint modifiers);
++ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++
++ void updateAuxiliaryText ();
++ void updateLookupTable ();
++ void updatePreeditText ();
++
++ void update ();
++ void commit ();
++ void reset ();
++
++ gboolean insert (gint ch);
++ gint keyvalToBopomofo (gint ch);
++
++ gboolean removeCharBefore (void);
++ gboolean removeCharAfter (void);
++ gboolean removeWordBefore (void);
++ gboolean removeWordAfter (void);
++
++ gboolean moveCursorLeft (void);
++ gboolean moveCursorRight (void);
++ gboolean moveCursorLeftByWord (void);
++ gboolean moveCursorRightByWord (void);
++ gboolean moveCursorToBegin (void);
++ gboolean moveCursorToEnd (void);
++
++};
++
++};
++
++
++#endif
+--
+1.7.6.4
+
+
+From 5a59f456bb40ea381a8f39858a0a8d3f8e43b074 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 5 Sep 2011 17:13:31 +0800
+Subject: [PATCH 14/71] fixes compile
+
+---
+ src/Makefile.am | 2 ++
+ src/PYPBopomofoEditor.cc | 9 ++++-----
+ src/PYPBopomofoEditor.h | 2 ++
+ 3 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index ddebb04..3065410 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -66,6 +66,7 @@ ibus_engine_pinyin_c_sources = \
+ PYSpecialPhraseTable.cc \
+ PYPPhoneticEditor.cc \
+ PYPPinyinEditor.cc \
++ PYPBopomofoEditor.cc \
+ $(NULL)
+ ibus_engine_pinyin_h_sources = \
+ PYBopomofo.h \
+@@ -111,6 +112,7 @@ ibus_engine_pinyin_h_sources = \
+ PYLibPinyin.h \
+ PYPPhoneticEditor.h \
+ PYPPinyinEditor.h \
++ PYPBopomofoEditor.h \
+ $(NULL)
+
+ if IBUS_BUILD_LUA_EXTENSION
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 75c8ddc..cb64abd 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -274,7 +274,7 @@ LibPinyinBopomofoEditor::processSelectKey (guint keyval, guint keycode,
+
+ const gchar * pos = NULL;
+ const gchar * keys = bopomofo_select_keys[m_config.selectKeys ()];
+- for ( const gchar * p = keys; *p != NULL; ++p ) {
++ for ( const gchar * p = keys; *p; ++p ) {
+ if ( *p == keyval )
+ pos = p;
+ }
+@@ -362,12 +362,11 @@ gint
+ LibPinyinBopomofoEditor::keyvalToBopomofo(gint ch)
+ {
+ const gint keyboard = m_config.bopomofoKeyboardMapping ();
+- const guint8 & keys[41][2] = bopomofo_keyboard[keyboard];
+ gint len = G_N_ELEMENTS (bopomofo_keyboard[keyboard]);
+
+- for ( size_t i = 0; i < len; ++i ) {
+- if ( keys[i][0] == ch )
+- return keys[i][1];
++ for ( gint i = 0; i < len; ++i ) {
++ if ( bopomofo_keyboard[keyboard][i][0] == ch )
++ return bopomofo_keyboard[keyboard][i][1];
+ }
+
+ return BOPOMOFO_ZERO;
+diff --git a/src/PYPBopomofoEditor.h b/src/PYPBopomofoEditor.h
+index bcbf85d..f78375f 100644
+--- a/src/PYPBopomofoEditor.h
++++ b/src/PYPBopomofoEditor.h
+@@ -46,12 +46,14 @@ protected:
+ gboolean processBopomofo (guint keyval, guint keycode, guint modifiers);
+ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+
++#if 0
+ void updateAuxiliaryText ();
+ void updateLookupTable ();
+ void updatePreeditText ();
+
+ void update ();
+ void commit ();
++#endif
+ void reset ();
+
+ gboolean insert (gint ch);
+--
+1.7.6.4
+
+
+From 2c724244d80e4d79385be7e0f5744b286c5b30a1 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 8 Sep 2011 15:13:17 +0800
+Subject: [PATCH 15/71] add libpinyin deps
+
+---
+ configure.ac | 5 +++++
+ src/Makefile.am | 2 ++
+ src/PYPPhoneticEditor.h | 4 ++++
+ 3 files changed, 11 insertions(+), 0 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 6afc180..1e3394d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -62,6 +62,11 @@ PKG_CHECK_MODULES(SQLITE, [
+ ])
+ AC_PATH_PROG(SQLITE3, sqlite3)
+
++# check libpinyin
++PKG_CHECK_MODULES(LIBPINYIN, [
++ libpinyin >= 0.2.0
++])
++
+ # check uuid
+ AC_CHECK_FUNCS([uuid_create], [], [
+ PKG_CHECK_MODULES(LIBUUID, uuid, [
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 3065410..fd12e0b 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -134,6 +134,7 @@ ibus_engine_pinyin_SOURCES = \
+ ibus_engine_pinyin_CXXFLAGS = \
+ @IBUS_CFLAGS@ \
+ @SQLITE_CFLAGS@ \
++ @LIBPINYIN_CFLAGS@ \
+ @OPENCC_CFLAGS@ \
+ -DGETTEXT_PACKAGE=\"@GETTEXT_PACKAGE@\" \
+ -DPKGDATADIR=\"$(pkgdatadir)\" \
+@@ -153,6 +154,7 @@ endif
+ ibus_engine_pinyin_LDADD = \
+ @IBUS_LIBS@ \
+ @SQLITE_LIBS@ \
++ @LIBPINYIN_LIBS@ \
+ @OPENCC_LIBS@ \
+ $(NULL)
+
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index 3d64bc4..f222557 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -21,6 +21,7 @@
+ #ifndef __PY_LIB_PINYIN_BASE_EDITOR_H_
+ #define __PY_LIB_PINYIN_BASE_EDITOR_H_
+
++#include <pinyin.h>
+ #include "PYLookupTable.h"
+ #include "PYEditor.h"
+ #include "PYPinyinParser.h"
+@@ -81,6 +82,9 @@ protected:
+ String m_buffer;
+
+ /* use LibPinyinBackEnd here. */
++ CandidateConstraints m_constraints;
++ MatchResults m_match_results;
++
+ std::vector<std::string> m_special_phrases;
+ std::string m_selected_special_phrase;
+ };
+--
+1.7.6.4
+
+
+From aa80dfa352b8657202c895062283d9e930735b14 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 8 Sep 2011 18:02:51 +0800
+Subject: [PATCH 16/71] begin to write libpinyin backend
+
+---
+ src/Makefile.am | 1 +
+ src/PYLibPinyin.cc | 39 +++++++++++++++++++++++++++++++++++++++
+ src/PYLibPinyin.h | 8 +++++++-
+ 3 files changed, 47 insertions(+), 1 deletions(-)
+ create mode 100644 src/PYLibPinyin.cc
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index fd12e0b..d70b36b 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -64,6 +64,7 @@ ibus_engine_pinyin_c_sources = \
+ PYDynamicSpecialPhrase.cc \
+ PYSpecialPhrase.cc \
+ PYSpecialPhraseTable.cc \
++ PYLibPinyin.cc \
+ PYPPhoneticEditor.cc \
+ PYPPinyinEditor.cc \
+ PYPBopomofoEditor.cc \
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+new file mode 100644
+index 0000000..55ffb8b
+--- /dev/null
++++ b/src/PYLibPinyin.cc
+@@ -0,0 +1,39 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYLibPinyin.h"
++
++using namespace PY;
++
++std::unique_ptr<LibPinyinBackEnd> LibPinyinBackEnd::m_instance;
++
++static LibPinyinBackEnd libpinyin_backend;
++
++LibPinyinBackEnd::LibPinyinBackEnd(){
++ g_assert (NULL == m_instance.get ());
++ m_pinyin_context = pinyin_init("/usr/share/libpinyin/data", "../data");
++ m_instance.reset(this);
++}
++
++LibPinyinBackEnd::~LibPinyinBackEnd(){
++ pinyin_fini(m_pinyin_context);
++ m_instance = NULL;
++}
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+index d3bc90c..c07b435 100644
+--- a/src/PYLibPinyin.h
++++ b/src/PYLibPinyin.h
+@@ -22,11 +22,17 @@
+ #ifndef __PY_LIB_PINYIN_H_
+ #define __PY_LIB_PINYIN_H_
+
+-typedef struct _pinyin_context_t pinyin_context_t;
++#include <memory>
++#include <pinyin.h>
+
+ namespace PY {
++
+ class LibPinyinBackEnd{
++
+ public:
++ LibPinyinBackEnd();
++ ~LibPinyinBackEnd();
++
+ /* use static initializer in C++. */
+ static LibPinyinBackEnd & instance (void) { return *m_instance; }
+
+--
+1.7.6.4
+
+
+From 1f6ff1c6791cf266fcff9ac2808f85d902ee4b5f Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 14 Sep 2011 17:49:47 +0800
+Subject: [PATCH 17/71] add set options to libpinyin back end
+
+---
+ src/PYLibPinyin.cc | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/PYLibPinyin.h | 5 +++++
+ 2 files changed, 56 insertions(+), 0 deletions(-)
+
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+index 55ffb8b..36eaba3 100644
+--- a/src/PYLibPinyin.cc
++++ b/src/PYLibPinyin.cc
+@@ -20,6 +20,8 @@
+ */
+
+ #include "PYLibPinyin.h"
++#include "PYTypes.h"
++#include "PYConfig.h"
+
+ using namespace PY;
+
+@@ -37,3 +39,52 @@ LibPinyinBackEnd::~LibPinyinBackEnd(){
+ pinyin_fini(m_pinyin_context);
+ m_instance = NULL;
+ }
++
++/* Here are the fuzzy pinyin options conversion table. */
++static const struct {
++ guint ibus_pinyin_option;
++ PinyinAmbiguity libpinyin_option;
++} fuzzy_options [] = {
++ /* fuzzy pinyin */
++ { PINYIN_FUZZY_C_CH, PINYIN_AmbCiChi },
++ { PINYIN_FUZZY_CH_C, PINYIN_AmbChiCi },
++ { PINYIN_FUZZY_Z_ZH, PINYIN_AmbZiZhi },
++ { PINYIN_FUZZY_ZH_Z, PINYIN_AmbZhiZi },
++ { PINYIN_FUZZY_S_SH, PINYIN_AmbSiShi },
++ { PINYIN_FUZZY_SH_S, PINYIN_AmbShiSi },
++ { PINYIN_FUZZY_L_N, PINYIN_AmbLeNe },
++ { PINYIN_FUZZY_N_L, PINYIN_AmbNeLe },
++ { PINYIN_FUZZY_F_H, PINYIN_AmbFoHe },
++ { PINYIN_FUZZY_H_F, PINYIN_AmbHeFo },
++ { PINYIN_FUZZY_L_R, PINYIN_AmbLeRi },
++ { PINYIN_FUZZY_R_L, PINYIN_AmbRiLe },
++ { PINYIN_FUZZY_K_G, PINYIN_AmbKeGe },
++ { PINYIN_FUZZY_G_K, PINYIN_AmbGeKe },
++ { PINYIN_FUZZY_AN_ANG, PINYIN_AmbAnAng },
++ { PINYIN_FUZZY_ANG_AN, PINYIN_AmbAngAn },
++ { PINYIN_FUZZY_EN_ENG, PINYIN_AmbEnEng },
++ { PINYIN_FUZZY_ENG_EN, PINYIN_AmbEngEn },
++ { PINYIN_FUZZY_IN_ING, PINYIN_AmbInIng },
++ { PINYIN_FUZZY_ING_IN, PINYIN_AmbIngIn }
++};
++
++gboolean
++LibPinyinBackEnd::setPinyinOptions (Config * config)
++{
++ guint option = config->option ();
++ PinyinCustomSettings custom;
++
++ custom.set_use_incomplete (option & PINYIN_INCOMPLETE_PINYIN);
++ custom.set_use_ambiguities (PINYIN_AmbAny, false);
++
++ /* copy values */
++ for (guint i = 0; i < G_N_ELEMENTS (fuzzy_options); i++) {
++ if ( option & fuzzy_options[i].ibus_pinyin_option )
++ custom.set_use_ambiguities
++ (fuzzy_options[i].libpinyin_option, true);
++ }
++
++ pinyin_set_options(m_pinyin_context, &custom);
++
++ return TRUE;
++}
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+index c07b435..83aa1fc 100644
+--- a/src/PYLibPinyin.h
++++ b/src/PYLibPinyin.h
+@@ -27,12 +27,16 @@
+
+ namespace PY {
+
++class Config;
++
+ class LibPinyinBackEnd{
+
+ public:
+ LibPinyinBackEnd();
+ ~LibPinyinBackEnd();
+
++ gboolean setPinyinOptions(Config *config);
++
+ /* use static initializer in C++. */
+ static LibPinyinBackEnd & instance (void) { return *m_instance; }
+
+@@ -42,6 +46,7 @@ private:
+ private:
+ static std::unique_ptr<LibPinyinBackEnd> m_instance;
+ };
++
+ };
+
+ #endif
+--
+1.7.6.4
+
+
+From 7bb6c26be96489e919736eb719abafcf11796e15 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 15 Sep 2011 15:19:49 +0800
+Subject: [PATCH 18/71] remove special phrase
+
+---
+ src/PYPPhoneticEditor.cc | 41 -----------------------------------------
+ src/PYPPhoneticEditor.h | 7 +------
+ 2 files changed, 1 insertions(+), 47 deletions(-)
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index ef9a02d..fc4aee2 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -161,27 +161,6 @@ LibPinyinPhoneticEditor::processKeyEvent (guint keyval, guint keycode, guint mod
+ return FALSE;
+ }
+
+-gboolean
+-LibPinyinPhoneticEditor::updateSpecialPhrases (void)
+-{
+- guint size = m_special_phrases.size();
+- m_special_phrases.clear ();
+-
+- if (!m_config.specialPhrases ())
+- return FALSE;
+-
+- if (!m_selected_special_phrase.empty ())
+- return FALSE;
+-
+- /* Note: change behavior to match the entire m_text,
+- * instead of partial m_text.
+- */
+- SpecialPhraseTable::instance ().lookup
+- (m_text, m_special_phrases);
+-
+- return size != m_special_phrases.size() || size != 0;
+-}
+-
+ void
+ LibPinyinPhoneticEditor::updateLookupTableFast (void)
+ {
+@@ -204,9 +183,6 @@ LibPinyinPhoneticEditor::updateLookupTable (void)
+ gboolean
+ LibPinyinPhoneticEditor::fillLookupTableByPage (void)
+ {
+- if (!m_selected_special_phrase.empty ()) {
+- return FALSE;
+- }
+
+ guint filled_nr = m_lookup_table.size ();
+ guint page_size = m_lookup_table.pageSize ();
+@@ -273,8 +249,6 @@ LibPinyinPhoneticEditor::reset (void)
+ m_pinyin.clear ();
+ m_pinyin_len = 0;
+ m_lookup_table.clear ();
+- m_special_phrases.clear ();
+- m_selected_special_phrase.clear ();
+
+ Editor::reset ();
+ }
+@@ -298,21 +272,6 @@ gboolean
+ LibPinyinPhoneticEditor::selectCandidate (guint i)
+ {
+
+- if (i < m_special_phrases.size ()) {
+- /* select a special phrase */
+- m_selected_special_phrase = m_special_phrases[i];
+- if (m_cursor == m_text.size()) {
+- m_buffer = m_selected_special_phrase;
+- reset ();
+- commit ((const gchar *)m_buffer);
+- } else {
+- updateSpecialPhrases ();
+- update ();
+- }
+- return TRUE;
+- }
+-
+- i -= m_special_phrases.size ();
+ /* TODO: deal with normal candidates selection here by libpinyin. */
+ g_assert (FALSE);
+ }
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index f222557..f7a3704 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -51,7 +51,6 @@ public:
+
+ protected:
+
+- gboolean updateSpecialPhrases ();
+ gboolean selectCandidate (guint i);
+ gboolean selectCandidateInPage (guint i);
+
+@@ -82,11 +81,7 @@ protected:
+ String m_buffer;
+
+ /* use LibPinyinBackEnd here. */
+- CandidateConstraints m_constraints;
+- MatchResults m_match_results;
+-
+- std::vector<std::string> m_special_phrases;
+- std::string m_selected_special_phrase;
++ pinyin_instance_t *m_instance;
+ };
+
+ };
+--
+1.7.6.4
+
+
+From c9a83029d574da3de06bc8d3b3766919acd68c5c Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 16 Sep 2011 15:43:35 +0800
+Subject: [PATCH 19/71] refactor libpinyin phonetic editor
+
+---
+ src/PYPPhoneticEditor.cc | 59 +++++++++++++++++++++++++++++++++++++++------
+ src/PYPPhoneticEditor.h | 6 +++-
+ 2 files changed, 55 insertions(+), 10 deletions(-)
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index fc4aee2..86ee42b 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -29,8 +29,8 @@ using namespace PY;
+ LibPinyinPhoneticEditor::LibPinyinPhoneticEditor (PinyinProperties &props,
+ Config &config):
+ Editor (props, config),
+- m_pinyin (MAX_PHRASE_LEN),
+- m_pinyin_len (0),
++ m_pinyins (MAX_PHRASE_LEN),
++ m_pinyin_cursor (0),
+ m_lookup_table (m_config.pageSize ())
+ {
+ }
+@@ -188,7 +188,34 @@ LibPinyinPhoneticEditor::fillLookupTableByPage (void)
+ guint page_size = m_lookup_table.pageSize ();
+
+ /* fill lookup table by libpinyin get candidates. */
+- g_assert(FALSE);
++ guint need_nr = MIN (page_size, m_candidates->len - filled_nr);
++ g_assert (need_nr >=0);
++ if (need_nr == 0)
++ return FALSE;
++
++ for (guint i = filled_nr; i < filled_nr + need_nr; i++) {
++ if (G_LIKELY (m_props.modeSimp ())) { /* Simplified Chinese */
++ phrase_token_t *token = &g_array_index
++ (m_candidates, phrase_token_t, i);
++ char *word = NULL;
++ pinyin_translate_token(m_instance, *token, &word);
++ Text text (word);
++ m_lookup_table.appendCandidate(text);
++ g_free(word);
++ } else { /* Traditional Chinese */
++ m_buffer.truncate (0);
++ phrase_token_t *token = &g_array_index
++ (m_candidates, phrase_token_t, i);
++ char *word = NULL;
++ pinyin_translate_token(m_instance, *token, &word);
++ SimpTradConverter::simpToTrad (word, m_buffer);
++ Text text (m_buffer);
++ m_lookup_table.appendCandidate (text);
++ g_free(word);
++ }
++ }
++
++ return TRUE;
+ }
+
+ void
+@@ -246,8 +273,8 @@ LibPinyinPhoneticEditor::candidateClicked (guint index, guint button, guint stat
+ void
+ LibPinyinPhoneticEditor::reset (void)
+ {
+- m_pinyin.clear ();
+- m_pinyin_len = 0;
++ m_pinyins.clear ();
++ m_pinyin_cursor = 0;
+ m_lookup_table.clear ();
+
+ Editor::reset ();
+@@ -268,12 +295,28 @@ LibPinyinPhoneticEditor::commit (const gchar *str)
+ commitText (text);
+ }
+
++void
++LibPinyinPhoneticEditor::updatePinyinCursor ()
++{
++ /* Translate cursor position to pinyin position. */
++ m_pinyin_cursor = MIN (m_pinyin_cursor, m_pinyins.size ());
++ PinyinArray::const_iterator iter = m_pinyins.begin ();
++ for ( ; iter != m_pinyins.end (); ++iter) {
++ guint end = iter->begin + iter->len;
++ if ( iter->begin <= m_cursor && m_cursor < end )
++ m_pinyin_cursor = iter - m_pinyins.begin ();
++ }
++ m_pinyin_cursor = MAX (m_pinyin_cursor, 0);
++}
++
+ gboolean
+ LibPinyinPhoneticEditor::selectCandidate (guint i)
+ {
+-
+- /* TODO: deal with normal candidates selection here by libpinyin. */
+- g_assert (FALSE);
++ /* Prolog: assume updatePinyinCursor is called before. */
++ /* NOTE: deal with normal candidates selection here by libpinyin. */
++ phrase_token_t *token = &g_array_index (m_candidates, phrase_token_t, i);
++ pinyin_choose_candidate(m_instance, m_pinyin_cursor, *token);
++ return TRUE;
+ }
+
+ gboolean
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index f7a3704..a3b03ff 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -55,6 +55,7 @@ protected:
+ gboolean selectCandidateInPage (guint i);
+
+ void commit (const gchar *str);
++ void updatePinyinCursor ();
+
+ /* inline functions */
+
+@@ -75,13 +76,14 @@ protected:
+ virtual void updatePreeditText (void) = 0;
+
+ /* varibles */
+- PinyinArray m_pinyin;
+- guint m_pinyin_len;
++ PinyinArray m_pinyins;
++ guint m_pinyin_cursor;
+ LookupTable m_lookup_table;
+ String m_buffer;
+
+ /* use LibPinyinBackEnd here. */
+ pinyin_instance_t *m_instance;
++ TokenVector m_candidates;
+ };
+
+ };
+--
+1.7.6.4
+
+
+From 0afa90502dac19f65253c3bd6d6dd6b97f403ec7 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 16 Sep 2011 15:51:12 +0800
+Subject: [PATCH 20/71] clean up libpinyin bopomofo editor
+
+---
+ src/PYPBopomofoEditor.cc | 39 +++++++++++++--------------------------
+ 1 files changed, 13 insertions(+), 26 deletions(-)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index cb64abd..35c9ed2 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -103,19 +103,8 @@ LibPinyinBopomofoEditor::removeWordBefore (void)
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+- guint cursor;
+- if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
+- cursor = m_pinyin_len;
+- } else {
+- const Pinyin & p = *m_pinyin.back ();
+- cursor = m_cursor - p.len;
+- m_pinyin_len -= p.len;
+- m_pinyin.pop_back ();
+- }
+-
+- m_text.erase (cursor, m_cursor - cursor);
+- m_cursor = cursor;
+- update();
++ /* TODO: to be implemented. */
++ g_assert(FALSE);
+
+ return TRUE;
+ }
+@@ -127,8 +116,8 @@ LibPinyinBopomofoEditor::removeWordAfter (void)
+ return FALSE;
+
+ /* TODO: remove one word instead of the sentence. */
+- m_text.erase (m_cursor, -1);
+- update ();
++ g_assert(FALSE);
++
+ return TRUE;
+ }
+
+@@ -162,16 +151,8 @@ LibPinyinBopomofoEditor::moveCursorLeftByWord (void)
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+- if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
+- m_cursor = m_pinyin_len;
+- return TRUE;
+- }
+-
+- const Pinyin & p = *m_pinyin.back ();
+- m_cursor -= p.len;
+- m_pinyin_len -= p.len;
+- m_pinyin.pop_back ();
+- update ();
++ /* TODO: to be implemented. */
++ g_assert(FALSE);
+
+ return TRUE;
+ }
+@@ -179,7 +160,13 @@ LibPinyinBopomofoEditor::moveCursorLeftByWord (void)
+ gboolean
+ LibPinyinBopomofoEditor::moveCursorRightByWord (void)
+ {
+- return moveCursorToEnd ();
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ /* TODO: to be implemented. */
++ g_assert(FALSE);
++
++ return TRUE;
+ }
+
+ gboolean
+--
+1.7.6.4
+
+
+From 5d0466f732e7520851edb8145c348b29c8bea252 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 16 Sep 2011 17:31:56 +0800
+Subject: [PATCH 21/71] add m_pinyin_len back
+
+---
+ src/PYPPhoneticEditor.cc | 20 +++++++++++---------
+ src/PYPPhoneticEditor.h | 4 ++--
+ 2 files changed, 13 insertions(+), 11 deletions(-)
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index 86ee42b..a26ce85 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -30,7 +30,7 @@ LibPinyinPhoneticEditor::LibPinyinPhoneticEditor (PinyinProperties &props,
+ Config &config):
+ Editor (props, config),
+ m_pinyins (MAX_PHRASE_LEN),
+- m_pinyin_cursor (0),
++ m_pinyin_len (0),
+ m_lookup_table (m_config.pageSize ())
+ {
+ }
+@@ -274,7 +274,7 @@ void
+ LibPinyinPhoneticEditor::reset (void)
+ {
+ m_pinyins.clear ();
+- m_pinyin_cursor = 0;
++ m_pinyin_len = 0;
+ m_lookup_table.clear ();
+
+ Editor::reset ();
+@@ -295,27 +295,29 @@ LibPinyinPhoneticEditor::commit (const gchar *str)
+ commitText (text);
+ }
+
+-void
+-LibPinyinPhoneticEditor::updatePinyinCursor ()
++guint
++LibPinyinPhoneticEditor::getPinyinCursor ()
+ {
+ /* Translate cursor position to pinyin position. */
+- m_pinyin_cursor = MIN (m_pinyin_cursor, m_pinyins.size ());
++ guint pinyin_cursor = m_pinyins.size ();
+ PinyinArray::const_iterator iter = m_pinyins.begin ();
+ for ( ; iter != m_pinyins.end (); ++iter) {
+ guint end = iter->begin + iter->len;
+ if ( iter->begin <= m_cursor && m_cursor < end )
+- m_pinyin_cursor = iter - m_pinyins.begin ();
++ pinyin_cursor = iter - m_pinyins.begin ();
+ }
+- m_pinyin_cursor = MAX (m_pinyin_cursor, 0);
++ g_assert (pinyin_cursor >= 0);
++ return pinyin_cursor;
+ }
+
+ gboolean
+ LibPinyinPhoneticEditor::selectCandidate (guint i)
+ {
+- /* Prolog: assume updatePinyinCursor is called before. */
++ guint pinyin_cursor = getPinyinCursor ();
++
+ /* NOTE: deal with normal candidates selection here by libpinyin. */
+ phrase_token_t *token = &g_array_index (m_candidates, phrase_token_t, i);
+- pinyin_choose_candidate(m_instance, m_pinyin_cursor, *token);
++ pinyin_choose_candidate(m_instance, pinyin_cursor, *token);
+ return TRUE;
+ }
+
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index a3b03ff..32a5245 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -55,7 +55,7 @@ protected:
+ gboolean selectCandidateInPage (guint i);
+
+ void commit (const gchar *str);
+- void updatePinyinCursor ();
++ guint getPinyinCursor ();
+
+ /* inline functions */
+
+@@ -77,7 +77,7 @@ protected:
+
+ /* varibles */
+ PinyinArray m_pinyins;
+- guint m_pinyin_cursor;
++ guint m_pinyin_len;
+ LookupTable m_lookup_table;
+ String m_buffer;
+
+--
+1.7.6.4
+
+
+From 325056f0f43e86da5621ac04d5261faaabe5041c Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 19 Sep 2011 16:10:48 +0800
+Subject: [PATCH 22/71] write pinyin editor in progress
+
+---
+ src/PYPPhoneticEditor.h | 2 +-
+ src/PYPPinyinEditor.cc | 79 +++++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 77 insertions(+), 4 deletions(-)
+
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index 32a5245..428f17b 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -25,7 +25,7 @@
+ #include "PYLookupTable.h"
+ #include "PYEditor.h"
+ #include "PYPinyinParser.h"
+-#include "PYSpecialPhraseTable.h"
++
+
+ namespace PY {
+
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index a78544d..a435b82 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -200,19 +200,92 @@ LibPinyinPinyinEditor::processKeyEvent (guint keyval, guint keycode,
+ void
+ LibPinyinPinyinEditor::commit ()
+ {
+- g_assert (FALSE);
++
++ if (G_UNLIKELY (m_buffer.empty ()))
++ return;
++
++ m_buffer.clear ();
++
++ /* sentence candidate */
++ char *tmp = NULL;
++ pinyin_get_sentence(m_instance, &tmp);
++ m_buffer << tmp;
++ g_free (tmp);
++ tmp = NULL;
++
++ /* text after pinyin */
++ const gchar *p = m_text.c_str() + m_pinyin_len;
++ if (G_UNLIKELY (m_props.modeFull ())) {
++ while (*p != '\0') {
++ m_buffer.appendUnichar (HalfFullConverter::toFull (*p++));
++ }
++ } else {
++ m_buffer << p;
++ }
++
++ pinyin_train(m_instance);
++ LibPinyinPhoneticEditor::commit ((const gchar *)m_buffer);
++ reset();
+ }
+
+ void
+ LibPinyinPinyinEditor::updatePreeditText ()
+ {
+- g_assert (FALSE);
++ /* preedit text = guessed sentence + un-parsed pinyin text */
++ if (G_UNLIKELY (m_text.empty ())) {
++ hidePreeditText ();
++ return;
++ }
++
++ m_buffer.clear ();
++ char *tmp = NULL;
++ pinyin_get_sentence(m_instance, &tmp);
++ if (m_props.modeSimp ()) {
++ m_buffer<<tmp;
++ } else {
++ SimpTradConverter::simpToTrad (tmp, m_buffer);
++ }
++ g_free (tmp);
++ tmp = NULL;
++
++ /* append rest text */
++ const gchar *p = m_text.c_str () + m_pinyin_len;
++ m_buffer << p;
++
++ StaticText preedit_text (m_buffer);
++ /* underline */
++ preedit_text.appendAttribute (IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, -1);
++
++ guint pinyin_cursor = getPinyinCursor ();
++ Editor::updatePreeditText (preedit_text, pinyin_cursor, TRUE);
+ }
+
+ void
+ LibPinyinPinyinEditor::updateAuxiliaryText ()
+ {
+- g_assert (FALSE);
++ if (G_UNLIKELY (m_text.empty ())) {
++ hideAuxiliaryText ();
++ return;
++ }
++
++ m_buffer.clear ();
++
++ /* Note: cursor handling is defered to full/double pinyin editors. */
++ guint pinyin_cursor = getPinyinCursor ();
++ for (guint i = 0; i < m_pinyins.size (); ++i) {
++ if (G_LIKELY (i))
++ m_buffer << ' ';
++ const Pinyin *pinyin = m_pinyins[i];
++ m_buffer << pinyin->sheng
++ << pinyin->yun;
++ }
++
++ /* append rest text */
++ const gchar * p = m_text.c_str() + m_pinyin_len;
++ m_buffer << p;
++
++ StaticText aux_text (m_buffer);
++ Editor::updateAuxiliaryText (aux_text, TRUE);
+ }
+
+ void
+--
+1.7.6.4
+
+
+From 6cee400f75eeb9d977cb3bb64df8dc282ab31aa7 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 19 Sep 2011 16:26:42 +0800
+Subject: [PATCH 23/71] begin to write libpinyin full pinyin editor
+
+---
+ src/Makefile.am | 1 +
+ src/PYPFullPinyinEditor.cc | 64 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 65 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPFullPinyinEditor.cc
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index d70b36b..aeaaf89 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -67,6 +67,7 @@ ibus_engine_pinyin_c_sources = \
+ PYLibPinyin.cc \
+ PYPPhoneticEditor.cc \
+ PYPPinyinEditor.cc \
++ PYPFullPinyinEditor.cc \
+ PYPBopomofoEditor.cc \
+ $(NULL)
+ ibus_engine_pinyin_h_sources = \
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+new file mode 100644
+index 0000000..9712d97
+--- /dev/null
++++ b/src/PYPFullPinyinEditor.cc
+@@ -0,0 +1,64 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYPFullPinyinEditor.h"
++#include "PYConfig.h"
++
++using namespace PY;
++
++LibPinyinFullPinyinEditor::LibPinyinFullPinyinEditor
++(PinyinProperties & props, Config & config)
++ : LibPinyinPinyinEditor (props, config)
++{
++}
++
++LibPinyinFullPinyinEditor::~LibPinyinFullPinyinEditor (void)
++{
++}
++
++void
++LibPinyinFullPinyinEditor::reset (void)
++{
++ LibPinyinPinyinEditor::reset ();
++}
++
++gboolean
++LibPinyinFullPinyinEditor::insert (gint ch)
++{
++ /* is full */
++ if (G_UNLIKELY (m_text.length () >= MAX_PINYIN_LEN))
++ return TRUE;
++
++ m_text.insert (m_cursor++, ch);
++
++ updatePinyin ();
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::processKeyEvent (guint keyval,
++ guint keycode,
++ guint modifiers)
++{
++ return LibPinyinPinyinEditor::processKeyEvent (keyval, keycode, modifiers);
++}
++
+--
+1.7.6.4
+
+
+From b50a6e074f608f640afb074231ed643240bf26b3 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Tue, 20 Sep 2011 13:52:05 +0800
+Subject: [PATCH 24/71] write update pinyin
+
+---
+ src/PYPFullPinyinEditor.cc | 31 +++++++++++++++++++++++++++++++
+ src/PYPFullPinyinEditor.h | 2 ++
+ 2 files changed, 33 insertions(+), 0 deletions(-)
+
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 9712d97..5194ef8 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -62,3 +62,34 @@ LibPinyinFullPinyinEditor::processKeyEvent (guint keyval,
+ return LibPinyinPinyinEditor::processKeyEvent (keyval, keycode, modifiers);
+ }
+
++void
++LibPinyinFullPinyinEditor::updatePinyin (void)
++{
++ if (G_UNLIKELY (m_text.empty ())) {
++ m_pinyins.clear ();
++ m_pinyin_len = 0;
++ return;
++ }
++
++ m_pinyin_len = PinyinParser::parse (m_text, // text
++ m_text.length (), // text length
++ m_config.option (), // option
++ m_pinyins, // result
++ MAX_PHRASE_LEN); // max result length
++
++ /* propagate to libpinyin */
++ g_array_set_size (m_instance->m_pinyin_keys, 0);
++ g_array_set_size (m_instance->m_pinyin_poses, 0);
++
++ PinyinKey key; PinyinKeyPos pos;
++ PinyinArray::const_iterator iter = m_pinyins.begin ();
++ for ( ; iter != m_pinyins.end (); ++iter ) {
++ PinyinSegment py = *iter;
++ pinyin_parse_full_pinyin (m_instance, py.pinyin->text, &key);
++ pos.set_pos (py.begin); pos.set_length (py.len);
++ g_array_append_val(m_instance->m_pinyin_keys, key);
++ g_array_append_val(m_instance->m_pinyin_poses, pos);
++ }
++
++ pinyin_guess_sentence(m_instance);
++}
+diff --git a/src/PYPFullPinyinEditor.h b/src/PYPFullPinyinEditor.h
+index a6e74c4..afb52d5 100644
+--- a/src/PYPFullPinyinEditor.h
++++ b/src/PYPFullPinyinEditor.h
+@@ -52,6 +52,8 @@ public:
+
+ protected:
+ /* TODO: to be implemented. */
++ void updatePinyin (void);
++
+ };
+
+ };
+--
+1.7.6.4
+
+
+From 3ceb1022d20885ed032a3b0275a48fe8cf96182d Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Tue, 20 Sep 2011 16:12:46 +0800
+Subject: [PATCH 25/71] add char edit
+
+---
+ src/PYPFullPinyinEditor.cc | 39 +++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 39 insertions(+), 0 deletions(-)
+
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 5194ef8..2b8babc 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -55,6 +55,45 @@ LibPinyinFullPinyinEditor::insert (gint ch)
+ }
+
+ gboolean
++LibPinyinFullPinyinEditor::removeCharBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor --;
++ m_text.erase (m_cursor, 1);
++
++ updatePinyin ();
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::removeCharAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_text.erase (m_cursor, 1);
++
++ updatePinyin ();
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::removeWordBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ /* TODO: to be implemented. */
++ g_assert (FALSE);
++}
++
++gboolean
+ LibPinyinFullPinyinEditor::processKeyEvent (guint keyval,
+ guint keycode,
+ guint modifiers)
+--
+1.7.6.4
+
+
+From 5ccaad1bdee85c6762ddfbf52bba6e8e2f82fd0a Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 21 Sep 2011 10:14:49 +0800
+Subject: [PATCH 26/71] write full pinyin editor in progress
+
+---
+ src/PYPFullPinyinEditor.cc | 131 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 129 insertions(+), 2 deletions(-)
+
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 2b8babc..7e764c7 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -89,8 +89,135 @@ LibPinyinFullPinyinEditor::removeWordBefore (void)
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+- /* TODO: to be implemented. */
+- g_assert (FALSE);
++ guint cursor;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_pinyin_len;
++ } else {
++ guint pinyin_cursor = getPinyinCursor ();
++ cursor = m_pinyins[pinyin_cursor].begin;
++ /* cursor at the begin of one pinyin */
++ g_return_val_if_fail (pinyin_cursor > 0, FALSE);
++ if ( cursor == m_cursor)
++ cursor = m_pinyins[pinyin_cursor - 1].begin;
++ }
++
++ m_text.erase (cursor, m_cursor - cursor);
++ m_cursor = cursor;
++ updatePinyin ();
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::removeWordAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ guint cursor;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_text.length ();
++ } else {
++ guint pinyin_cursor = getPinyinCursor ();
++ PinyinSegment py = m_pinyins[pinyin_cursor];
++ cursor = py.begin + py.len;
++ }
++
++ m_text.erase (m_cursor, cursor - m_cursor);
++ updatePinyin ();
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::moveCursorLeft (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor --;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::moveCursorRight (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_cursor ++;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::moveCursorLeftByWord (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ guint cursor;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_pinyin_len;
++ } else {
++ guint pinyin_cursor = getPinyinCursor ();
++ cursor = m_pinyins[pinyin_cursor].begin;
++ /* cursor at the begin of one pinyin */
++ g_return_val_if_fail (pinyin_cursor > 0, FALSE);
++ if ( cursor == m_cursor)
++ cursor = m_pinyins[pinyin_cursor - 1].begin;
++ }
++
++ m_cursor = cursor;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::moveCursorRightByWord (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ guint cursor;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_text.length ();
++ } else {
++ guint pinyin_cursor = getPinyinCursor ();
++ PinyinSegment py = m_pinyins[pinyin_cursor];
++ cursor = py.begin + py.len;
++ }
++
++ m_cursor = cursor;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::moveCursorToBegin (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return TRUE;
++
++ m_cursor = 0;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::moveCursorToEnd (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_cursor = m_text.length ();
++ update ();
++ return TRUE;
+ }
+
+ gboolean
+--
+1.7.6.4
+
+
+From b9dce30dd8b368769f7843594ba3210a097bd6cc Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 21 Sep 2011 10:34:46 +0800
+Subject: [PATCH 27/71] use m_pinyin_poses in full pinyin editor
+
+---
+ src/PYPFullPinyinEditor.cc | 32 ++++++++++++++++++++++----------
+ 1 files changed, 22 insertions(+), 10 deletions(-)
+
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 7e764c7..0a05c5a 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -95,11 +95,16 @@ LibPinyinFullPinyinEditor::removeWordBefore (void)
+ cursor = m_pinyin_len;
+ } else {
+ guint pinyin_cursor = getPinyinCursor ();
+- cursor = m_pinyins[pinyin_cursor].begin;
++ PinyinKeyPos *pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ cursor = pos->m_pos;
+ /* cursor at the begin of one pinyin */
+ g_return_val_if_fail (pinyin_cursor > 0, FALSE);
+- if ( cursor == m_cursor)
+- cursor = m_pinyins[pinyin_cursor - 1].begin;
++ if ( cursor == m_cursor) {
++ pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor - 1);
++ cursor = pos->m_pos;
++ }
+ }
+
+ m_text.erase (cursor, m_cursor - cursor);
+@@ -121,8 +126,9 @@ LibPinyinFullPinyinEditor::removeWordAfter (void)
+ cursor = m_text.length ();
+ } else {
+ guint pinyin_cursor = getPinyinCursor ();
+- PinyinSegment py = m_pinyins[pinyin_cursor];
+- cursor = py.begin + py.len;
++ PinyinKeyPos *pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ cursor = pos->m_pos + pos->m_len;
+ }
+
+ m_text.erase (m_cursor, cursor - m_cursor);
+@@ -165,11 +171,16 @@ LibPinyinFullPinyinEditor::moveCursorLeftByWord (void)
+ cursor = m_pinyin_len;
+ } else {
+ guint pinyin_cursor = getPinyinCursor ();
+- cursor = m_pinyins[pinyin_cursor].begin;
++ PinyinKeyPos *pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ cursor = pos->m_pos;
+ /* cursor at the begin of one pinyin */
+ g_return_val_if_fail (pinyin_cursor > 0, FALSE);
+- if ( cursor == m_cursor)
+- cursor = m_pinyins[pinyin_cursor - 1].begin;
++ if ( cursor == m_cursor) {
++ pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor - 1);
++ cursor = pos->m_pos;
++ }
+ }
+
+ m_cursor = cursor;
+@@ -189,8 +200,9 @@ LibPinyinFullPinyinEditor::moveCursorRightByWord (void)
+ cursor = m_text.length ();
+ } else {
+ guint pinyin_cursor = getPinyinCursor ();
+- PinyinSegment py = m_pinyins[pinyin_cursor];
+- cursor = py.begin + py.len;
++ PinyinKeyPos *pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ cursor = pos->m_pos + pos->m_len;
+ }
+
+ m_cursor = cursor;
+--
+1.7.6.4
+
+
+From 9b3f8d14380de93c3b697a55cfd1df6dd8316eb3 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 21 Sep 2011 11:25:58 +0800
+Subject: [PATCH 28/71] use pinyin pos
+
+---
+ src/PYPPhoneticEditor.cc | 14 ++++++++------
+ src/PYPPinyinEditor.cc | 8 ++++----
+ 2 files changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index a26ce85..217e545 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -299,13 +299,15 @@ guint
+ LibPinyinPhoneticEditor::getPinyinCursor ()
+ {
+ /* Translate cursor position to pinyin position. */
+- guint pinyin_cursor = m_pinyins.size ();
+- PinyinArray::const_iterator iter = m_pinyins.begin ();
+- for ( ; iter != m_pinyins.end (); ++iter) {
+- guint end = iter->begin + iter->len;
+- if ( iter->begin <= m_cursor && m_cursor < end )
+- pinyin_cursor = iter - m_pinyins.begin ();
++ PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
++ guint pinyin_cursor = pinyin_poses->len;
++ for (size_t i = 0; i < pinyin_poses->len; ++i) {
++ PinyinKeyPos *pos = &g_array_index
++ (pinyin_poses, PinyinKeyPos, i);
++ if (pos->get_pos () <= m_cursor && m_cursor < pos->get_end_pos ())
++ pinyin_cursor = i;
+ }
++
+ g_assert (pinyin_cursor >= 0);
+ return pinyin_cursor;
+ }
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index a435b82..68617a3 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -272,12 +272,12 @@ LibPinyinPinyinEditor::updateAuxiliaryText ()
+
+ /* Note: cursor handling is defered to full/double pinyin editors. */
+ guint pinyin_cursor = getPinyinCursor ();
+- for (guint i = 0; i < m_pinyins.size (); ++i) {
++ PinyinKeyVector & pinyin_keys = m_instance->m_pinyin_keys;
++ for (guint i = 0; i < pinyin_keys->len; ++i) {
+ if (G_LIKELY (i))
+ m_buffer << ' ';
+- const Pinyin *pinyin = m_pinyins[i];
+- m_buffer << pinyin->sheng
+- << pinyin->yun;
++ PinyinKey * key = &g_array_index (pinyin_keys, PinyinKey, i);
++ m_buffer << key->get_key_string ();
+ }
+
+ /* append rest text */
+--
+1.7.6.4
+
+
+From 31e29393f3d7069c7dbbbda11d0cb354838a0e2c Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 21 Sep 2011 11:39:17 +0800
+Subject: [PATCH 29/71] re-factor full pinyin editor
+
+---
+ src/PYPFullPinyinEditor.cc | 83 +++++++++++++++++++------------------------
+ src/PYPFullPinyinEditor.h | 3 ++
+ 2 files changed, 40 insertions(+), 46 deletions(-)
+
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 0a05c5a..904064a 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -83,43 +83,35 @@ LibPinyinFullPinyinEditor::removeCharAfter (void)
+ return TRUE;
+ }
+
+-gboolean
+-LibPinyinFullPinyinEditor::removeWordBefore (void)
++guint
++LibPinyinFullPinyinEditor::getCursorLeftByWord (void)
+ {
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+ guint cursor;
+
+ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
+ cursor = m_pinyin_len;
+ } else {
++ PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
+ guint pinyin_cursor = getPinyinCursor ();
+ PinyinKeyPos *pos = &g_array_index
+- (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ (pinyin_poses, PinyinKeyPos, pinyin_cursor);
+ cursor = pos->m_pos;
++
+ /* cursor at the begin of one pinyin */
+- g_return_val_if_fail (pinyin_cursor > 0, FALSE);
++ g_return_val_if_fail (pinyin_cursor > 0, 0);
+ if ( cursor == m_cursor) {
+ pos = &g_array_index
+- (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor - 1);
++ (pinyin_poses, PinyinKeyPos, pinyin_cursor - 1);
+ cursor = pos->m_pos;
+ }
+ }
+
+- m_text.erase (cursor, m_cursor - cursor);
+- m_cursor = cursor;
+- updatePinyin ();
+- update ();
+- return TRUE;
++ return cursor;
+ }
+
+-gboolean
+-LibPinyinFullPinyinEditor::removeWordAfter (void)
++guint
++LibPinyinFullPinyinEditor::getCursorRightByWord (void)
+ {
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+ guint cursor;
+
+ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
+@@ -128,9 +120,33 @@ LibPinyinFullPinyinEditor::removeWordAfter (void)
+ guint pinyin_cursor = getPinyinCursor ();
+ PinyinKeyPos *pos = &g_array_index
+ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
+- cursor = pos->m_pos + pos->m_len;
++ cursor = pos->get_end_pos ();
+ }
+
++ return cursor;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::removeWordBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ guint cursor = getCursorLeftByWord ();
++ m_text.erase (cursor, m_cursor - cursor);
++ m_cursor = cursor;
++ updatePinyin ();
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinFullPinyinEditor::removeWordAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ guint cursor = getCursorRightByWord ();
+ m_text.erase (m_cursor, cursor - m_cursor);
+ updatePinyin ();
+ update ();
+@@ -165,23 +181,7 @@ LibPinyinFullPinyinEditor::moveCursorLeftByWord (void)
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+- guint cursor;
+-
+- if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
+- cursor = m_pinyin_len;
+- } else {
+- guint pinyin_cursor = getPinyinCursor ();
+- PinyinKeyPos *pos = &g_array_index
+- (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
+- cursor = pos->m_pos;
+- /* cursor at the begin of one pinyin */
+- g_return_val_if_fail (pinyin_cursor > 0, FALSE);
+- if ( cursor == m_cursor) {
+- pos = &g_array_index
+- (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor - 1);
+- cursor = pos->m_pos;
+- }
+- }
++ guint cursor = getCursorLeftByWord ();
+
+ m_cursor = cursor;
+ update ();
+@@ -194,16 +194,7 @@ LibPinyinFullPinyinEditor::moveCursorRightByWord (void)
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+- guint cursor;
+-
+- if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
+- cursor = m_text.length ();
+- } else {
+- guint pinyin_cursor = getPinyinCursor ();
+- PinyinKeyPos *pos = &g_array_index
+- (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
+- cursor = pos->m_pos + pos->m_len;
+- }
++ guint cursor = getCursorRightByWord ();
+
+ m_cursor = cursor;
+ update ();
+diff --git a/src/PYPFullPinyinEditor.h b/src/PYPFullPinyinEditor.h
+index afb52d5..11e53cb 100644
+--- a/src/PYPFullPinyinEditor.h
++++ b/src/PYPFullPinyinEditor.h
+@@ -54,6 +54,9 @@ protected:
+ /* TODO: to be implemented. */
+ void updatePinyin (void);
+
++ guint getCursorLeftByWord (void);
++ guint getCursorRightByWord (void);
++
+ };
+
+ };
+--
+1.7.6.4
+
+
+From f612432ccf5bd9d3fc9617bf52f1f99e2b7b5c0a Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 21 Sep 2011 12:22:55 +0800
+Subject: [PATCH 30/71] add update aux text func for full pinyin
+
+---
+ src/PYPFullPinyinEditor.cc | 37 +++++++++++++++++++++++++++++++++++++
+ src/PYPFullPinyinEditor.h | 2 ++
+ src/PYPPinyinEditor.cc | 4 ++--
+ src/PYPPinyinEditor.h | 6 +++---
+ 4 files changed, 44 insertions(+), 5 deletions(-)
+
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 904064a..af29f53 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -262,3 +262,40 @@ LibPinyinFullPinyinEditor::updatePinyin (void)
+
+ pinyin_guess_sentence(m_instance);
+ }
++
++void
++LibPinyinFullPinyinEditor::updateAuxiliaryText ()
++{
++ if (G_UNLIKELY (m_text.empty ())) {
++ hideAuxiliaryText ();
++ return;
++ }
++
++ m_buffer.clear ();
++
++ guint pinyin_cursor = getPinyinCursor ();
++ PinyinKeyVector & pinyin_keys = m_instance->m_pinyin_keys;
++ PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
++ for (guint i = 0; i < pinyin_keys->len; ++i) {
++ PinyinKey *key = &g_array_index (pinyin_keys, PinyinKey, i);
++ PinyinKeyPos *pos = &g_array_index (pinyin_poses, PinyinKeyPos, i);
++ guint cursor = pos->get_pos ();
++
++ if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
++ m_buffer << '|' << key->get_key_string ();
++ } else { /* in word */
++ /* raw text */
++ String raw = m_text.substr (cursor, pos->get_length ());
++ guint offset = m_cursor - cursor;
++ m_buffer << ' ' << raw.substr (0, offset)
++ << '|' << raw.substr (offset);
++ }
++ }
++
++ /* append rest text */
++ const gchar * p = m_text.c_str() + m_pinyin_len;
++ m_buffer << p;
++
++ StaticText aux_text (m_buffer);
++ Editor::updateAuxiliaryText (aux_text, TRUE);
++}
+diff --git a/src/PYPFullPinyinEditor.h b/src/PYPFullPinyinEditor.h
+index 11e53cb..5624c54 100644
+--- a/src/PYPFullPinyinEditor.h
++++ b/src/PYPFullPinyinEditor.h
+@@ -49,6 +49,8 @@ public:
+ /* virtual functions */
+ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+ virtual void reset (void);
++ virtual void updateAuxiliaryText (void);
++
+
+ protected:
+ /* TODO: to be implemented. */
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index 68617a3..b2e5987 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -276,12 +276,12 @@ LibPinyinPinyinEditor::updateAuxiliaryText ()
+ for (guint i = 0; i < pinyin_keys->len; ++i) {
+ if (G_LIKELY (i))
+ m_buffer << ' ';
+- PinyinKey * key = &g_array_index (pinyin_keys, PinyinKey, i);
++ PinyinKey *key = &g_array_index (pinyin_keys, PinyinKey, i);
+ m_buffer << key->get_key_string ();
+ }
+
+ /* append rest text */
+- const gchar * p = m_text.c_str() + m_pinyin_len;
++ const gchar *p = m_text.c_str() + m_pinyin_len;
+ m_buffer << p;
+
+ StaticText aux_text (m_buffer);
+diff --git a/src/PYPPinyinEditor.h b/src/PYPPinyinEditor.h
+index fd2b2ce..41aafc6 100644
+--- a/src/PYPPinyinEditor.h
++++ b/src/PYPPinyinEditor.h
+@@ -43,9 +43,9 @@ protected:
+
+ void commit ();
+
+- void updateAuxiliaryText (void);
+- void updateLookupTable (void);
+- void updatePreeditText (void);
++ virtual void updateAuxiliaryText (void);
++ virtual void updateLookupTable (void);
++ virtual void updatePreeditText (void);
+
+ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+
+--
+1.7.6.4
+
+
+From 62d47f889316ff95b764333bb10f9f0211e32558 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 21 Sep 2011 14:02:14 +0800
+Subject: [PATCH 31/71] begin to add double pinyin editor
+
+---
+ src/Makefile.am | 1 +
+ src/PYPDoublePinyinEditor.cc | 40 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 41 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPDoublePinyinEditor.cc
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index aeaaf89..a15a0ef 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -68,6 +68,7 @@ ibus_engine_pinyin_c_sources = \
+ PYPPhoneticEditor.cc \
+ PYPPinyinEditor.cc \
+ PYPFullPinyinEditor.cc \
++ PYPDoublePinyinEditor.cc \
+ PYPBopomofoEditor.cc \
+ $(NULL)
+ ibus_engine_pinyin_h_sources = \
+diff --git a/src/PYPDoublePinyinEditor.cc b/src/PYPDoublePinyinEditor.cc
+new file mode 100644
+index 0000000..5eb2067
+--- /dev/null
++++ b/src/PYPDoublePinyinEditor.cc
+@@ -0,0 +1,40 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYPDoublePinyinEditor.h"
++
++using namespace PY;
++
++
++gboolean
++LibPinyinDoublePinyinEditor::processKeyEvent (guint keyval, guint keycode,
++ guint modifiers)
++{
++ /* handle ';' key */
++ if (G_UNLIKELY (keyval == IBUS_semicolon)) {
++ if (cmshm_filter (modifiers) == 0) {
++ if (insert (keyval))
++ return TRUE;
++ }
++ }
++
++ return LibPinyinPinyinEditor::processKeyEvent (keyval, keycode, modifiers);
++}
+--
+1.7.6.4
+
+
+From 1e16137bf37a2bc597740585e2809679bc5b7605 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 21 Sep 2011 14:18:36 +0800
+Subject: [PATCH 32/71] move cursor edit funcs to pinyin editor
+
+---
+ src/PYPDoublePinyinEditor.h | 2 +
+ src/PYPFullPinyinEditor.cc | 168 ------------------------------------------
+ src/PYPFullPinyinEditor.h | 17 +----
+ src/PYPPinyinEditor.cc | 169 +++++++++++++++++++++++++++++++++++++++++++
+ src/PYPPinyinEditor.h | 18 +++++
+ 5 files changed, 190 insertions(+), 184 deletions(-)
+
+diff --git a/src/PYPDoublePinyinEditor.h b/src/PYPDoublePinyinEditor.h
+index 35baa6f..f0cb548 100644
+--- a/src/PYPDoublePinyinEditor.h
++++ b/src/PYPDoublePinyinEditor.h
+@@ -50,6 +50,8 @@ public:
+
+ protected:
+ /* TODO: to be implemented. */
++ virtual void updatePinyin (void);
++
+ };
+
+ };
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index af29f53..9c1644e 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -54,174 +54,6 @@ LibPinyinFullPinyinEditor::insert (gint ch)
+ return TRUE;
+ }
+
+-gboolean
+-LibPinyinFullPinyinEditor::removeCharBefore (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- m_cursor --;
+- m_text.erase (m_cursor, 1);
+-
+- updatePinyin ();
+- update ();
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::removeCharAfter (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_text.erase (m_cursor, 1);
+-
+- updatePinyin ();
+- update ();
+-
+- return TRUE;
+-}
+-
+-guint
+-LibPinyinFullPinyinEditor::getCursorLeftByWord (void)
+-{
+- guint cursor;
+-
+- if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
+- cursor = m_pinyin_len;
+- } else {
+- PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
+- guint pinyin_cursor = getPinyinCursor ();
+- PinyinKeyPos *pos = &g_array_index
+- (pinyin_poses, PinyinKeyPos, pinyin_cursor);
+- cursor = pos->m_pos;
+-
+- /* cursor at the begin of one pinyin */
+- g_return_val_if_fail (pinyin_cursor > 0, 0);
+- if ( cursor == m_cursor) {
+- pos = &g_array_index
+- (pinyin_poses, PinyinKeyPos, pinyin_cursor - 1);
+- cursor = pos->m_pos;
+- }
+- }
+-
+- return cursor;
+-}
+-
+-guint
+-LibPinyinFullPinyinEditor::getCursorRightByWord (void)
+-{
+- guint cursor;
+-
+- if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
+- cursor = m_text.length ();
+- } else {
+- guint pinyin_cursor = getPinyinCursor ();
+- PinyinKeyPos *pos = &g_array_index
+- (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
+- cursor = pos->get_end_pos ();
+- }
+-
+- return cursor;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::removeWordBefore (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- guint cursor = getCursorLeftByWord ();
+- m_text.erase (cursor, m_cursor - cursor);
+- m_cursor = cursor;
+- updatePinyin ();
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::removeWordAfter (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- guint cursor = getCursorRightByWord ();
+- m_text.erase (m_cursor, cursor - m_cursor);
+- updatePinyin ();
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::moveCursorLeft (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- m_cursor --;
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::moveCursorRight (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_cursor ++;
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::moveCursorLeftByWord (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- guint cursor = getCursorLeftByWord ();
+-
+- m_cursor = cursor;
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::moveCursorRightByWord (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- guint cursor = getCursorRightByWord ();
+-
+- m_cursor = cursor;
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::moveCursorToBegin (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return TRUE;
+-
+- m_cursor = 0;
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinFullPinyinEditor::moveCursorToEnd (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_cursor = m_text.length ();
+- update ();
+- return TRUE;
+-}
+
+ gboolean
+ LibPinyinFullPinyinEditor::processKeyEvent (guint keyval,
+diff --git a/src/PYPFullPinyinEditor.h b/src/PYPFullPinyinEditor.h
+index 5624c54..6214f22 100644
+--- a/src/PYPFullPinyinEditor.h
++++ b/src/PYPFullPinyinEditor.h
+@@ -34,18 +34,6 @@ public:
+ public:
+ gboolean insert (gint ch);
+
+- gboolean removeCharBefore (void);
+- gboolean removeCharAfter (void);
+- gboolean removeWordBefore (void);
+- gboolean removeWordAfter (void);
+-
+- gboolean moveCursorLeft (void);
+- gboolean moveCursorRight (void);
+- gboolean moveCursorLeftByWord (void);
+- gboolean moveCursorRightByWord (void);
+- gboolean moveCursorToBegin (void);
+- gboolean moveCursorToEnd (void);
+-
+ /* virtual functions */
+ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+ virtual void reset (void);
+@@ -54,10 +42,7 @@ public:
+
+ protected:
+ /* TODO: to be implemented. */
+- void updatePinyin (void);
+-
+- guint getCursorLeftByWord (void);
+- guint getCursorRightByWord (void);
++ virtual void updatePinyin (void);
+
+ };
+
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index b2e5987..08fc04e 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -295,3 +295,172 @@ LibPinyinPinyinEditor::updateLookupTable ()
+ m_lookup_table.setOrientation (m_config.orientation ());
+ LibPinyinPhoneticEditor::updateLookupTable ();
+ }
++
++gboolean
++LibPinyinPinyinEditor::removeCharBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor --;
++ m_text.erase (m_cursor, 1);
++
++ updatePinyin ();
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinPinyinEditor::removeCharAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_text.erase (m_cursor, 1);
++
++ updatePinyin ();
++ update ();
++
++ return TRUE;
++}
++
++guint
++LibPinyinPinyinEditor::getCursorLeftByWord (void)
++{
++ guint cursor;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_pinyin_len;
++ } else {
++ PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
++ guint pinyin_cursor = getPinyinCursor ();
++ PinyinKeyPos *pos = &g_array_index
++ (pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ cursor = pos->m_pos;
++
++ /* cursor at the begin of one pinyin */
++ g_return_val_if_fail (pinyin_cursor > 0, 0);
++ if ( cursor == m_cursor) {
++ pos = &g_array_index
++ (pinyin_poses, PinyinKeyPos, pinyin_cursor - 1);
++ cursor = pos->m_pos;
++ }
++ }
++
++ return cursor;
++}
++
++guint
++LibPinyinPinyinEditor::getCursorRightByWord (void)
++{
++ guint cursor;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_text.length ();
++ } else {
++ guint pinyin_cursor = getPinyinCursor ();
++ PinyinKeyPos *pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ cursor = pos->get_end_pos ();
++ }
++
++ return cursor;
++}
++
++gboolean
++LibPinyinPinyinEditor::removeWordBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ guint cursor = getCursorLeftByWord ();
++ m_text.erase (cursor, m_cursor - cursor);
++ m_cursor = cursor;
++ updatePinyin ();
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPinyinEditor::removeWordAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ guint cursor = getCursorRightByWord ();
++ m_text.erase (m_cursor, cursor - m_cursor);
++ updatePinyin ();
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPinyinEditor::moveCursorLeft (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor --;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPinyinEditor::moveCursorRight (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_cursor ++;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPinyinEditor::moveCursorLeftByWord (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ guint cursor = getCursorLeftByWord ();
++
++ m_cursor = cursor;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPinyinEditor::moveCursorRightByWord (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ guint cursor = getCursorRightByWord ();
++
++ m_cursor = cursor;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPinyinEditor::moveCursorToBegin (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return TRUE;
++
++ m_cursor = 0;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPinyinEditor::moveCursorToEnd (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_cursor = m_text.length ();
++ update ();
++ return TRUE;
++}
+diff --git a/src/PYPPinyinEditor.h b/src/PYPPinyinEditor.h
+index 41aafc6..974d2a5 100644
+--- a/src/PYPPinyinEditor.h
++++ b/src/PYPPinyinEditor.h
+@@ -35,6 +35,20 @@ class LibPinyinPinyinEditor : public LibPinyinPhoneticEditor {
+ public:
+ LibPinyinPinyinEditor (PinyinProperties & props, Config & config);
+
++public:
++ gboolean removeCharBefore (void);
++ gboolean removeCharAfter (void);
++ gboolean removeWordBefore (void);
++ gboolean removeWordAfter (void);
++
++ gboolean moveCursorLeft (void);
++ gboolean moveCursorRight (void);
++ gboolean moveCursorLeftByWord (void);
++ gboolean moveCursorRightByWord (void);
++ gboolean moveCursorToBegin (void);
++ gboolean moveCursorToEnd (void);
++
++
+ protected:
+ gboolean processPinyin (guint keyval, guint keycode, guint modifiers);
+ gboolean processNumber (guint keyval, guint keycode, guint modifiers);
+@@ -49,6 +63,10 @@ protected:
+
+ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+
++ virtual void updatePinyin (void) = 0;
++
++ guint getCursorLeftByWord (void);
++ guint getCursorRightByWord (void);
+ };
+
+ };
+--
+1.7.6.4
+
+
+From 17a5f2c269d903f892b59ab2a28e8476b5fa0035 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 21 Sep 2011 14:52:09 +0800
+Subject: [PATCH 33/71] add update pinyin
+
+---
+ src/PYPDoublePinyinEditor.cc | 16 ++++++++++++++++
+ src/PYPDoublePinyinEditor.h | 12 ------------
+ src/PYPFullPinyinEditor.cc | 8 +++++---
+ 3 files changed, 21 insertions(+), 15 deletions(-)
+
+diff --git a/src/PYPDoublePinyinEditor.cc b/src/PYPDoublePinyinEditor.cc
+index 5eb2067..501ec30 100644
+--- a/src/PYPDoublePinyinEditor.cc
++++ b/src/PYPDoublePinyinEditor.cc
+@@ -38,3 +38,19 @@ LibPinyinDoublePinyinEditor::processKeyEvent (guint keyval, guint keycode,
+
+ return LibPinyinPinyinEditor::processKeyEvent (keyval, keycode, modifiers);
+ }
++
++void
++LibPinyinDoublePinyinEditor::updatePinyin (void)
++{
++ if (G_UNLIKELY (m_text.empty ())) {
++ m_pinyins.clear ();
++ m_pinyin_len = 0;
++ /* TODO: check whether to replace "" with NULL. */
++ pinyin_parse_more_double_pinyins (m_instance, "");
++ return;
++ }
++
++ m_pinyin_len =
++ pinyin_parse_more_double_pinyins (m_instance, m_text.c_str ());
++ pinyin_guess_sentence (m_instance);
++}
+diff --git a/src/PYPDoublePinyinEditor.h b/src/PYPDoublePinyinEditor.h
+index f0cb548..d756fbd 100644
+--- a/src/PYPDoublePinyinEditor.h
++++ b/src/PYPDoublePinyinEditor.h
+@@ -32,18 +32,6 @@ public:
+
+ gboolean insert (gint ch);
+
+- gboolean removeCharBefore (void);
+- gboolean removeCharAfter (void);
+- gboolean removeWordBefore (void);
+- gboolean removeWordAfter (void);
+-
+- gboolean moveCursorLeft (void);
+- gboolean moveCursorRight (void);
+- gboolean moveCursorLeftByWord (void);
+- gboolean moveCursorRightByWord (void);
+- gboolean moveCursorToBegin (void);
+- gboolean moveCursorToEnd (void);
+-
+ /* override virtual functions */
+ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+ void reset (void);
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 9c1644e..05de60d 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -69,6 +69,8 @@ LibPinyinFullPinyinEditor::updatePinyin (void)
+ if (G_UNLIKELY (m_text.empty ())) {
+ m_pinyins.clear ();
+ m_pinyin_len = 0;
++ /* TODO: check whether to replace "" with NULL. */
++ pinyin_parse_more_full_pinyins (m_instance, "");
+ return;
+ }
+
+@@ -88,11 +90,11 @@ LibPinyinFullPinyinEditor::updatePinyin (void)
+ PinyinSegment py = *iter;
+ pinyin_parse_full_pinyin (m_instance, py.pinyin->text, &key);
+ pos.set_pos (py.begin); pos.set_length (py.len);
+- g_array_append_val(m_instance->m_pinyin_keys, key);
+- g_array_append_val(m_instance->m_pinyin_poses, pos);
++ g_array_append_val (m_instance->m_pinyin_keys, key);
++ g_array_append_val (m_instance->m_pinyin_poses, pos);
+ }
+
+- pinyin_guess_sentence(m_instance);
++ pinyin_guess_sentence (m_instance);
+ }
+
+ void
+--
+1.7.6.4
+
+
+From 15e5c137425de55f79c0c51d9ede5c9482e5f745 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 22 Sep 2011 14:24:09 +0800
+Subject: [PATCH 34/71] write double pinyin editor
+
+---
+ src/PYPDoublePinyinEditor.cc | 93 ++++++++++++++++++++++++++++++++++++++++++
+ src/PYPDoublePinyinEditor.h | 1 +
+ src/PYPFullPinyinEditor.cc | 2 +-
+ src/PYPPinyinEditor.cc | 2 +-
+ 4 files changed, 96 insertions(+), 2 deletions(-)
+
+diff --git a/src/PYPDoublePinyinEditor.cc b/src/PYPDoublePinyinEditor.cc
+index 501ec30..0e1e3d3 100644
+--- a/src/PYPDoublePinyinEditor.cc
++++ b/src/PYPDoublePinyinEditor.cc
+@@ -20,9 +20,64 @@
+ */
+
+ #include "PYPDoublePinyinEditor.h"
++#include "PYConfig.h"
++
++#define DEFINE_DOUBLE_PINYIN_TABLES
++#include "PYDoublePinyinTable.h"
+
+ using namespace PY;
+
++/*
++ * c in 'a' ... 'z' => id = c - 'a'
++ * c == ';' => id = 26
++ * else => id = -1
++ */
++#define ID(c) \
++ ((c >= IBUS_a && c <= IBUS_z) ? c - IBUS_a : (c == IBUS_semicolon ? 26 : -1))
++
++#define ID_TO_SHENG(id) \
++ (double_pinyin_map[m_config.doublePinyinSchema ()].sheng[id])
++#define ID_TO_YUNS(id) \
++ (double_pinyin_map[m_config.doublePinyinSchema ()].yun[id])
++
++#define IS_ALPHA(c) \
++ ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
++
++
++LibPinyinDoublePinyinEditor::LibPinyinDoublePinyinEditor
++( PinyinProperties & props, Config & config)
++ : LibPinyinPinyinEditor (props, config)
++{
++}
++
++gboolean
++LibPinyinDoublePinyinEditor::insert (gint ch)
++{
++ /* is full */
++ if (G_UNLIKELY (m_text.length () >= MAX_PINYIN_LEN))
++ return TRUE;
++
++ gint id = ID (ch);
++ if (id == -1) {
++ /* it is not available ch */
++ return FALSE;
++ }
++
++ if (G_UNLIKELY (m_text.empty () && ID_TO_SHENG (id) == PINYIN_ID_VOID)) {
++ return FALSE;
++ }
++
++ m_text.insert (m_cursor++, ch);
++ updatePinyin ();
++ update ();
++
++ return TRUE;
++}
++
++void LibPinyinDoublePinyinEditor::reset (void)
++{
++ LibPinyinPinyinEditor::reset ();
++}
+
+ gboolean
+ LibPinyinDoublePinyinEditor::processKeyEvent (guint keyval, guint keycode,
+@@ -54,3 +109,41 @@ LibPinyinDoublePinyinEditor::updatePinyin (void)
+ pinyin_parse_more_double_pinyins (m_instance, m_text.c_str ());
+ pinyin_guess_sentence (m_instance);
+ }
++
++
++void
++LibPinyinDoublePinyinEditor::updateAuxiliaryText (void)
++{
++ if (G_UNLIKELY (m_text.empty ())) {
++ hideAuxiliaryText ();
++ return;
++ }
++
++ m_buffer.clear ();
++
++ // guint pinyin_cursor = getPinyinCursor ();
++ PinyinKeyVector & pinyin_keys = m_instance->m_pinyin_keys;
++ PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
++ for (guint i = 0; i < pinyin_keys->len; ++i) {
++ PinyinKey *key = &g_array_index (pinyin_keys, PinyinKey, i);
++ PinyinKeyPos *pos = &g_array_index (pinyin_poses, PinyinKeyPos, i);
++ guint cursor = pos->get_pos ();
++
++ if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
++ m_buffer << '|' << key->get_key_string ();
++ } else { /* in word */
++ /* raw text */
++ String raw = m_text.substr (cursor, pos->get_length ());
++ guint offset = m_cursor - cursor;
++ m_buffer << ' ' << raw.substr (0, offset)
++ << '|' << raw.substr (offset);
++ }
++ }
++
++ /* append rest text */
++ const gchar * p = m_text.c_str() + m_pinyin_len;
++ m_buffer << p;
++
++ StaticText aux_text (m_buffer);
++ Editor::updateAuxiliaryText (aux_text, TRUE);
++}
+diff --git a/src/PYPDoublePinyinEditor.h b/src/PYPDoublePinyinEditor.h
+index d756fbd..b06e144 100644
+--- a/src/PYPDoublePinyinEditor.h
++++ b/src/PYPDoublePinyinEditor.h
+@@ -38,6 +38,7 @@ public:
+
+ protected:
+ /* TODO: to be implemented. */
++ virtual void updateAuxiliaryText (void);
+ virtual void updatePinyin (void);
+
+ };
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 05de60d..80f8a46 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -107,7 +107,7 @@ LibPinyinFullPinyinEditor::updateAuxiliaryText ()
+
+ m_buffer.clear ();
+
+- guint pinyin_cursor = getPinyinCursor ();
++ // guint pinyin_cursor = getPinyinCursor ();
+ PinyinKeyVector & pinyin_keys = m_instance->m_pinyin_keys;
+ PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
+ for (guint i = 0; i < pinyin_keys->len; ++i) {
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index 08fc04e..8108002 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -271,7 +271,7 @@ LibPinyinPinyinEditor::updateAuxiliaryText ()
+ m_buffer.clear ();
+
+ /* Note: cursor handling is defered to full/double pinyin editors. */
+- guint pinyin_cursor = getPinyinCursor ();
++ // guint pinyin_cursor = getPinyinCursor ();
+ PinyinKeyVector & pinyin_keys = m_instance->m_pinyin_keys;
+ for (guint i = 0; i < pinyin_keys->len; ++i) {
+ if (G_LIKELY (i))
+--
+1.7.6.4
+
+
+From dc1008b9450edadac06e5927f4bfc53914339619 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 22 Sep 2011 14:35:40 +0800
+Subject: [PATCH 35/71] begin to write bopomofo editor
+
+---
+ src/PYPBopomofoEditor.cc | 119 ----------------------------------------------
+ src/PYPBopomofoEditor.h | 20 ++------
+ src/PYPPhoneticEditor.h | 2 +
+ src/PYPPinyinEditor.h | 2 +-
+ 4 files changed, 8 insertions(+), 135 deletions(-)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 35c9ed2..9efd8f1 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -72,125 +72,6 @@ LibPinyinBopomofoEditor::insert (gint ch)
+ return TRUE;
+ }
+
+-gboolean
+-LibPinyinBopomofoEditor::removeCharBefore (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- m_cursor --;
+- m_text.erase (m_cursor, 1);
+- update();
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::removeCharAfter (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_text.erase (m_cursor, 1);
+- update ();
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::removeWordBefore (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- /* TODO: to be implemented. */
+- g_assert(FALSE);
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::removeWordAfter (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- /* TODO: remove one word instead of the sentence. */
+- g_assert(FALSE);
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::moveCursorLeft (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- m_cursor --;
+- update ();
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::moveCursorRight (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_cursor ++;
+- update ();
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::moveCursorLeftByWord (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- /* TODO: to be implemented. */
+- g_assert(FALSE);
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::moveCursorRightByWord (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- /* TODO: to be implemented. */
+- g_assert(FALSE);
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::moveCursorToBegin (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- m_cursor = 0;
+- update();
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinBopomofoEditor::moveCursorToEnd (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_cursor = m_text.length ();
+- update();
+- return TRUE;
+-}
+
+ gboolean
+ LibPinyinBopomofoEditor::processGuideKey (guint keyval, guint keycode,
+diff --git a/src/PYPBopomofoEditor.h b/src/PYPBopomofoEditor.h
+index f78375f..9b6b4b6 100644
+--- a/src/PYPBopomofoEditor.h
++++ b/src/PYPBopomofoEditor.h
+@@ -46,31 +46,21 @@ protected:
+ gboolean processBopomofo (guint keyval, guint keycode, guint modifiers);
+ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+
++
++ virtual void updateAuxiliaryText ();
++ virtual void updatePinyin (void);
++
+ #if 0
+- void updateAuxiliaryText ();
+ void updateLookupTable ();
+ void updatePreeditText ();
++#endif
+
+- void update ();
+ void commit ();
+-#endif
+ void reset ();
+
+ gboolean insert (gint ch);
+ gint keyvalToBopomofo (gint ch);
+
+- gboolean removeCharBefore (void);
+- gboolean removeCharAfter (void);
+- gboolean removeWordBefore (void);
+- gboolean removeWordAfter (void);
+-
+- gboolean moveCursorLeft (void);
+- gboolean moveCursorRight (void);
+- gboolean moveCursorLeftByWord (void);
+- gboolean moveCursorRightByWord (void);
+- gboolean moveCursorToBegin (void);
+- gboolean moveCursorToEnd (void);
+-
+ };
+
+ };
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index 428f17b..56a8ee4 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -74,6 +74,8 @@ protected:
+ virtual void commit (void) = 0;
+ virtual void updateAuxiliaryText (void) = 0;
+ virtual void updatePreeditText (void) = 0;
++ virtual void updatePinyin (void) = 0;
++
+
+ /* varibles */
+ PinyinArray m_pinyins;
+diff --git a/src/PYPPinyinEditor.h b/src/PYPPinyinEditor.h
+index 974d2a5..00b49ce 100644
+--- a/src/PYPPinyinEditor.h
++++ b/src/PYPPinyinEditor.h
+@@ -63,7 +63,7 @@ protected:
+
+ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+
+- virtual void updatePinyin (void) = 0;
++ virtual void updatePinyin (void);
+
+ guint getCursorLeftByWord (void);
+ guint getCursorRightByWord (void);
+--
+1.7.6.4
+
+
+From 4fa55bf0d8333d1bb21c64572d017e05a22f4d48 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 22 Sep 2011 15:00:11 +0800
+Subject: [PATCH 36/71] write bopomofo editor in progress
+
+---
+ src/PYPBopomofoEditor.cc | 68 ++++++++++++++++++++++++++++++++++++++++++++++
+ src/PYPPinyinEditor.h | 2 +-
+ 2 files changed, 69 insertions(+), 1 deletions(-)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 9efd8f1..3a2a70e 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -226,6 +226,22 @@ LibPinyinBopomofoEditor::processKeyEvent (guint keyval, guint keycode,
+ return FALSE;
+ }
+
++void
++LibPinyinBopomofoEditor::updatePinyin (void)
++{
++ if (G_UNLIKELY (m_text.empty ())) {
++ m_pinyins.clear ();
++ m_pinyin_len = 0;
++ /* TODO: check whether to replace "" with NULL. */
++ pinyin_parse_more_chewings (m_instance, "");
++ return;
++ }
++
++ m_pinyin_len =
++ pinyin_parse_more_chewings (m_instance, m_text.c_str ());
++ pinyin_guess_sentence (m_instance);
++}
++
+ gint
+ LibPinyinBopomofoEditor::keyvalToBopomofo(gint ch)
+ {
+@@ -239,3 +255,55 @@ LibPinyinBopomofoEditor::keyvalToBopomofo(gint ch)
+
+ return BOPOMOFO_ZERO;
+ }
++
++void
++LibPinyinBopomofoEditor::commit ()
++{
++ g_assert (FALSE);
++}
++
++void
++LibPinyinBopomofoEditor::updateAuxiliaryText (void)
++{
++ if (G_UNLIKELY (m_text.empty ())) {
++ hideAuxiliaryText ();
++ return;
++ }
++
++ m_buffer.clear ();
++
++ // guint pinyin_cursor = getPinyinCursor ();
++ PinyinKeyVector & pinyin_keys = m_instance->m_pinyin_keys;
++ PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
++ for (guint i = 0; i < pinyin_keys->len; ++i) {
++ PinyinKey *key = &g_array_index (pinyin_keys, PinyinKey, i);
++ PinyinKeyPos *pos = &g_array_index (pinyin_poses, PinyinKeyPos, i);
++ guint cursor = pos->get_pos ();
++
++ if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
++ m_buffer << '|' << key->get_key_zhuyin_string ();
++ } else { /* in word */
++ /* raw text */
++ String raw = m_text.substr (cursor, pos->get_length ());
++ guint offset = m_cursor - cursor;
++ m_buffer << ' ';
++ String before = raw.substr (0, offset);
++ String after = raw.substr (offset);
++ String::const_iterator iter;
++ for ( iter = before.begin (); iter != before.end (); ++iter) {
++ m_buffer << bopomofo_char[keyvalToBopomofo (*iter)];
++ }
++ m_buffer << '|';
++ for ( iter = after.begin (); iter != after.end (); ++iter) {
++ m_buffer << bopomofo_char[keyvalToBopomofo (*iter)];
++ }
++ }
++ }
++
++ /* append rest text */
++ const gchar * p = m_text.c_str() + m_pinyin_len;
++ m_buffer << p;
++
++ StaticText aux_text (m_buffer);
++ Editor::updateAuxiliaryText (aux_text, TRUE);
++}
+diff --git a/src/PYPPinyinEditor.h b/src/PYPPinyinEditor.h
+index 00b49ce..974d2a5 100644
+--- a/src/PYPPinyinEditor.h
++++ b/src/PYPPinyinEditor.h
+@@ -63,7 +63,7 @@ protected:
+
+ virtual gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+
+- virtual void updatePinyin (void);
++ virtual void updatePinyin (void) = 0;
+
+ guint getCursorLeftByWord (void);
+ guint getCursorRightByWord (void);
+--
+1.7.6.4
+
+
+From cd133bc9853f92d5c8ab72fd74a9a4d0670390fe Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 22 Sep 2011 15:18:37 +0800
+Subject: [PATCH 37/71] write bopomofo editor
+
+---
+ src/PYPBopomofoEditor.cc | 35 ++++++++++++++++++++++++++++++++++-
+ src/PYPPinyinEditor.cc | 10 ++++++----
+ 2 files changed, 40 insertions(+), 5 deletions(-)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 3a2a70e..023634b 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -22,6 +22,8 @@
+ #include "PYConfig.h"
+ #include "PYPinyinProperties.h"
+ #include "PYSimpTradConverter.h"
++#include "PYHalfFullConverter.h"
++
+
+ namespace PY {
+ #include "PYBopomofoKeyboard.h"
+@@ -259,7 +261,38 @@ LibPinyinBopomofoEditor::keyvalToBopomofo(gint ch)
+ void
+ LibPinyinBopomofoEditor::commit ()
+ {
+- g_assert (FALSE);
++ if (G_UNLIKELY (m_text.empty ()))
++ return;
++
++ m_buffer.clear ();
++
++ /* sentence candidate */
++ char *tmp = NULL;
++ pinyin_get_sentence(m_instance, &tmp);
++ if (m_props.modeSimp ()) {
++ m_buffer << tmp;
++ } else {
++ SimpTradConverter::simpToTrad (tmp, m_buffer);
++ }
++ g_free (tmp);
++
++ /* text after pinyin */
++ const gchar *p = m_text.c_str() + m_pinyin_len;
++ while (*p != '\0') {
++ if (keyvalToBopomofo (*p)) {
++ m_buffer << keyvalToBopomofo (*p);
++ } else {
++ if (G_UNLIKELY (m_props.modeFull ())) {
++ m_buffer.appendUnichar (HalfFullConverter::toFull (*p++));
++ } else {
++ m_buffer << p;
++ }
++ }
++ }
++
++ pinyin_train(m_instance);
++ LibPinyinPhoneticEditor::commit ((const gchar *)m_buffer);
++ reset();
+ }
+
+ void
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index 8108002..5599416 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -200,8 +200,7 @@ LibPinyinPinyinEditor::processKeyEvent (guint keyval, guint keycode,
+ void
+ LibPinyinPinyinEditor::commit ()
+ {
+-
+- if (G_UNLIKELY (m_buffer.empty ()))
++ if (G_UNLIKELY (m_text.empty ()))
+ return;
+
+ m_buffer.clear ();
+@@ -209,9 +208,12 @@ LibPinyinPinyinEditor::commit ()
+ /* sentence candidate */
+ char *tmp = NULL;
+ pinyin_get_sentence(m_instance, &tmp);
+- m_buffer << tmp;
++ if (m_props.modeSimp ()) {
++ m_buffer << tmp;
++ } else {
++ SimpTradConverter::simpToTrad (tmp, m_buffer);
++ }
+ g_free (tmp);
+- tmp = NULL;
+
+ /* text after pinyin */
+ const gchar *p = m_text.c_str() + m_pinyin_len;
+--
+1.7.6.4
+
+
+From 57d303dd2b725c56abea46490609e0cd3d1f2938 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 22 Sep 2011 15:31:06 +0800
+Subject: [PATCH 38/71] remove m_pinyins
+
+---
+ src/PYPBopomofoEditor.cc | 1 -
+ src/PYPDoublePinyinEditor.cc | 1 -
+ src/PYPFullPinyinEditor.cc | 9 +++++----
+ src/PYPPhoneticEditor.cc | 2 --
+ src/PYPPhoneticEditor.h | 2 ++
+ 5 files changed, 7 insertions(+), 8 deletions(-)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 023634b..0c7e46f 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -232,7 +232,6 @@ void
+ LibPinyinBopomofoEditor::updatePinyin (void)
+ {
+ if (G_UNLIKELY (m_text.empty ())) {
+- m_pinyins.clear ();
+ m_pinyin_len = 0;
+ /* TODO: check whether to replace "" with NULL. */
+ pinyin_parse_more_chewings (m_instance, "");
+diff --git a/src/PYPDoublePinyinEditor.cc b/src/PYPDoublePinyinEditor.cc
+index 0e1e3d3..d37a480 100644
+--- a/src/PYPDoublePinyinEditor.cc
++++ b/src/PYPDoublePinyinEditor.cc
+@@ -98,7 +98,6 @@ void
+ LibPinyinDoublePinyinEditor::updatePinyin (void)
+ {
+ if (G_UNLIKELY (m_text.empty ())) {
+- m_pinyins.clear ();
+ m_pinyin_len = 0;
+ /* TODO: check whether to replace "" with NULL. */
+ pinyin_parse_more_double_pinyins (m_instance, "");
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 80f8a46..064ae40 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -67,17 +67,18 @@ void
+ LibPinyinFullPinyinEditor::updatePinyin (void)
+ {
+ if (G_UNLIKELY (m_text.empty ())) {
+- m_pinyins.clear ();
+ m_pinyin_len = 0;
+ /* TODO: check whether to replace "" with NULL. */
+ pinyin_parse_more_full_pinyins (m_instance, "");
+ return;
+ }
+
++ PinyinArray pinyins (MAX_PINYIN_LEN);
++
+ m_pinyin_len = PinyinParser::parse (m_text, // text
+ m_text.length (), // text length
+ m_config.option (), // option
+- m_pinyins, // result
++ pinyins, // result
+ MAX_PHRASE_LEN); // max result length
+
+ /* propagate to libpinyin */
+@@ -85,8 +86,8 @@ LibPinyinFullPinyinEditor::updatePinyin (void)
+ g_array_set_size (m_instance->m_pinyin_poses, 0);
+
+ PinyinKey key; PinyinKeyPos pos;
+- PinyinArray::const_iterator iter = m_pinyins.begin ();
+- for ( ; iter != m_pinyins.end (); ++iter ) {
++ PinyinArray::const_iterator iter = pinyins.begin ();
++ for ( ; iter != pinyins.end (); ++iter ) {
+ PinyinSegment py = *iter;
+ pinyin_parse_full_pinyin (m_instance, py.pinyin->text, &key);
+ pos.set_pos (py.begin); pos.set_length (py.len);
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index 217e545..60e2da9 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -29,7 +29,6 @@ using namespace PY;
+ LibPinyinPhoneticEditor::LibPinyinPhoneticEditor (PinyinProperties &props,
+ Config &config):
+ Editor (props, config),
+- m_pinyins (MAX_PHRASE_LEN),
+ m_pinyin_len (0),
+ m_lookup_table (m_config.pageSize ())
+ {
+@@ -273,7 +272,6 @@ LibPinyinPhoneticEditor::candidateClicked (guint index, guint button, guint stat
+ void
+ LibPinyinPhoneticEditor::reset (void)
+ {
+- m_pinyins.clear ();
+ m_pinyin_len = 0;
+ m_lookup_table.clear ();
+
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index 56a8ee4..9d522bf 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -78,7 +78,9 @@ protected:
+
+
+ /* varibles */
++#if 0
+ PinyinArray m_pinyins;
++#endif
+ guint m_pinyin_len;
+ LookupTable m_lookup_table;
+ String m_buffer;
+--
+1.7.6.4
+
+
+From f37f4807b0408d4269ad6a57e8a29049c18cabb1 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 22 Sep 2011 15:49:29 +0800
+Subject: [PATCH 39/71] fixes Makefile.am
+
+---
+ src/Makefile.am | 2 ++
+ src/PYPBopomofoEditor.cc | 1 +
+ 2 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index a15a0ef..4a83521 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -115,6 +115,8 @@ ibus_engine_pinyin_h_sources = \
+ PYLibPinyin.h \
+ PYPPhoneticEditor.h \
+ PYPPinyinEditor.h \
++ PYPFullPinyinEditor.h \
++ PYPDoublePinyinEditor.h \
+ PYPBopomofoEditor.h \
+ $(NULL)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 0c7e46f..db4f9b4 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -69,6 +69,7 @@ LibPinyinBopomofoEditor::insert (gint ch)
+ return TRUE;
+
+ m_text.insert (m_cursor++, ch);
++ updatePinyin ();
+ update ();
+
+ return TRUE;
+--
+1.7.6.4
+
+
+From 4adb383aeaeb0053f161283888609ea3078e2bdb Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 23 Sep 2011 14:44:10 +0800
+Subject: [PATCH 40/71] add set chewing options
+
+---
+ src/PYLibPinyin.cc | 29 ++++++++++++++++++++++++++++-
+ src/PYLibPinyin.h | 3 ++-
+ 2 files changed, 30 insertions(+), 2 deletions(-)
+
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+index 36eaba3..ceada04 100644
+--- a/src/PYLibPinyin.cc
++++ b/src/PYLibPinyin.cc
+@@ -43,7 +43,7 @@ LibPinyinBackEnd::~LibPinyinBackEnd(){
+ /* Here are the fuzzy pinyin options conversion table. */
+ static const struct {
+ guint ibus_pinyin_option;
+- PinyinAmbiguity libpinyin_option;
++ PinyinAmbiguity libpinyin_option;
+ } fuzzy_options [] = {
+ /* fuzzy pinyin */
+ { PINYIN_FUZZY_C_CH, PINYIN_AmbCiChi },
+@@ -68,6 +68,7 @@ static const struct {
+ { PINYIN_FUZZY_ING_IN, PINYIN_AmbIngIn }
+ };
+
++
+ gboolean
+ LibPinyinBackEnd::setPinyinOptions (Config * config)
+ {
+@@ -88,3 +89,29 @@ LibPinyinBackEnd::setPinyinOptions (Config * config)
+
+ return TRUE;
+ }
++
++/* Here are the chewing keyboard scheme mapping table. */
++static const struct {
++ guint bopomofo_keyboard;
++ PinyinZhuYinScheme chewing_keyboard;
++} chewing_options [] = {
++ {0, ZHUYIN_STANDARD},
++ {1, ZHUYIN_GIN_YIEH},
++ {2, ZHUYIN_ET26},
++ {3, ZHUYIN_IBM}
++};
++
++
++gboolean
++LibPinyinBackEnd::setChewingOptions (Config *config)
++{
++ const guint map = config->bopomofoKeyboardMapping ();
++ for (guint i = 0; i < G_N_ELEMENTS (chewing_options); i++) {
++ if (map == chewing_options[i].bopomofo_keyboard){
++ /* TODO: set chewing scheme. */
++ PinyinZhuYinScheme scheme = chewing_options[i].chewing_keyboard;
++ g_assert (FALSE);
++ }
++ }
++ return TRUE;
++}
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+index 83aa1fc..538930c 100644
+--- a/src/PYLibPinyin.h
++++ b/src/PYLibPinyin.h
+@@ -35,7 +35,8 @@ public:
+ LibPinyinBackEnd();
+ ~LibPinyinBackEnd();
+
+- gboolean setPinyinOptions(Config *config);
++ gboolean setPinyinOptions (Config *config);
++ gboolean setChewingOptions (Config *config);
+
+ /* use static initializer in C++. */
+ static LibPinyinBackEnd & instance (void) { return *m_instance; }
+--
+1.7.6.4
+
+
+From 67ddca2bedeb5716ba8f2ec049d67f65db562a80 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 26 Sep 2011 15:33:00 +0800
+Subject: [PATCH 41/71] add libpinyin pinyin/chewing scheme options
+
+---
+ src/PYLibPinyin.cc | 45 ++++++++++++++++++++++++++++++++++++++-------
+ src/PYLibPinyin.h | 7 ++++++-
+ 2 files changed, 44 insertions(+), 8 deletions(-)
+
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+index ceada04..8e3d7af 100644
+--- a/src/PYLibPinyin.cc
++++ b/src/PYLibPinyin.cc
+@@ -70,7 +70,7 @@ static const struct {
+
+
+ gboolean
+-LibPinyinBackEnd::setPinyinOptions (Config * config)
++LibPinyinBackEnd::setFuzzyOptions (Config *config, pinyin_context_t *context)
+ {
+ guint option = config->option ();
+ PinyinCustomSettings custom;
+@@ -85,14 +85,43 @@ LibPinyinBackEnd::setPinyinOptions (Config * config)
+ (fuzzy_options[i].libpinyin_option, true);
+ }
+
+- pinyin_set_options(m_pinyin_context, &custom);
++ pinyin_set_options(context, &custom);
+
+ return TRUE;
+ }
+
++/* Here are the double pinyin keyboard scheme mapping table. */
++static const struct{
++ gint double_pinyin_keyboard;
++ PinyinShuangPinScheme shuang_pin_keyboard;
++} shuang_pin_options [] = {
++ {0, SHUANG_PIN_MS},
++ {1, SHUANG_PIN_ZRM},
++ {2, SHUANG_PIN_ABC},
++ {3, SHUANG_PIN_ZIGUANG},
++ {4, SHUANG_PIN_PYJJ},
++ {5, SHUANG_PIN_XHE}
++};
++
++gboolean
++LibPinyinBackEnd::setPinyinOptions (Config *config)
++{
++ const gint map = config->doublePinyinSchema ();
++ for (guint i = 0; i < G_N_ELEMENTS (shuang_pin_options); i++) {
++ if (map == shuang_pin_options[i].double_pinyin_keyboard) {
++ /* TODO: set double pinyin scheme. */
++ PinyinShuangPinScheme scheme = shuang_pin_options[i].shuang_pin_keyboard;
++ pinyin_set_double_pinyin_scheme (m_pinyin_context, scheme);
++ }
++ }
++
++ setFuzzyOptions (config, m_pinyin_context);
++ return TRUE;
++}
++
+ /* Here are the chewing keyboard scheme mapping table. */
+ static const struct {
+- guint bopomofo_keyboard;
++ gint bopomofo_keyboard;
+ PinyinZhuYinScheme chewing_keyboard;
+ } chewing_options [] = {
+ {0, ZHUYIN_STANDARD},
+@@ -105,13 +134,15 @@ static const struct {
+ gboolean
+ LibPinyinBackEnd::setChewingOptions (Config *config)
+ {
+- const guint map = config->bopomofoKeyboardMapping ();
++ const gint map = config->bopomofoKeyboardMapping ();
+ for (guint i = 0; i < G_N_ELEMENTS (chewing_options); i++) {
+- if (map == chewing_options[i].bopomofo_keyboard){
++ if (map == chewing_options[i].bopomofo_keyboard) {
+ /* TODO: set chewing scheme. */
+ PinyinZhuYinScheme scheme = chewing_options[i].chewing_keyboard;
+- g_assert (FALSE);
+- }
++ pinyin_set_chewing_scheme (m_chewing_context, scheme);
++ }
+ }
++
++ setFuzzyOptions (config, m_chewing_context);
+ return TRUE;
+ }
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+index 538930c..3d40b1d 100644
+--- a/src/PYLibPinyin.h
++++ b/src/PYLibPinyin.h
+@@ -41,8 +41,13 @@ public:
+ /* use static initializer in C++. */
+ static LibPinyinBackEnd & instance (void) { return *m_instance; }
+
++protected:
++ gboolean setFuzzyOptions (Config *config, pinyin_context_t *context);
++
+ private:
+- pinyin_context_t *m_pinyin_context; /* libpinyin context */
++ /* libpinyin context */
++ pinyin_context_t *m_pinyin_context;
++ pinyin_context_t *m_chewing_context;
+
+ private:
+ static std::unique_ptr<LibPinyinBackEnd> m_instance;
+--
+1.7.6.4
+
+
+From 97cd3846b283bb7554604f692f027a5259ab4380 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 28 Sep 2011 15:08:11 +0800
+Subject: [PATCH 42/71] add PYPPinyinEngine.h
+
+---
+ src/Makefile.am | 1 +
+ src/PYPPinyinEngine.h | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 81 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPPinyinEngine.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 4a83521..be20605 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -118,6 +118,7 @@ ibus_engine_pinyin_h_sources = \
+ PYPFullPinyinEditor.h \
+ PYPDoublePinyinEditor.h \
+ PYPBopomofoEditor.h \
++ PYPPinyinEngine.h \
+ $(NULL)
+
+ if IBUS_BUILD_LUA_EXTENSION
+diff --git a/src/PYPPinyinEngine.h b/src/PYPPinyinEngine.h
+new file mode 100644
+index 0000000..d8040c1
+--- /dev/null
++++ b/src/PYPPinyinEngine.h
+@@ -0,0 +1,80 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_PINYIN_ENGINE_H_
++#define __PY_LIB_PINYIN_PINYIN_ENGINE_H_
++
++#include "PYEngine.h"
++#include "PYPinyinProperties.h"
++
++namespace PY {
++class LibPinyinPinyinEngine : public Engine {
++public:
++ LibPinyinPinyinEngine (IBusEngine *engine);
++ ~LibPinyinPinyinEngine (void);
++
++ //virtual functions
++ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ void focusIn (void);
++ void focusOut (void);
++ void reset (void);
++ void enable (void);
++ void disable (void);
++ void pageUp (void);
++ void pageDown (void);
++ void cursorUp (void);
++ void cursorDown (void);
++ gboolean propertyActivate (const gchar *prop_name, guint prop_state);
++ void candidateClicked (guint index, guint button, guint state);
++
++private:
++ gboolean processPunct (guint keyval, guint keycode, guint modifiers);
++
++ void showSetupDialog (void);
++ void connectEditorSignals (EditorPtr editor);
++
++ void commitText (Text & text);
++
++private:
++ PinyinProperties m_props;
++
++ guint m_prev_pressed_key;
++
++ enum {
++ MODE_INIT = 0, // init mode
++ MODE_PUNCT, // punct mode
++ MODE_RAW, // raw mode
++ MODE_ENGLISH, // press v into English input mode
++ #if 0
++ MODE_STROKE, // press u into stroke input mode
++ #endif
++ MODE_EXTENSION, // press i into extension input mode
++ MODE_LAST,
++ } m_input_mode;
++
++ EditorPtr m_editors[MODE_LAST];
++ EditorPtr m_fallback_editor;
++
++};
++
++};
++
++#endif
+--
+1.7.6.4
+
+
+From 269e8a835a6ac38a1c4b099f9a62bde9375e9a21 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 28 Sep 2011 17:09:11 +0800
+Subject: [PATCH 43/71] add libpinyin pinyin engine
+
+---
+ src/Makefile.am | 1 +
+ src/PYPPinyinEngine.cc | 325 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 326 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPPinyinEngine.cc
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index be20605..fc73a9b 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -70,6 +70,7 @@ ibus_engine_pinyin_c_sources = \
+ PYPFullPinyinEditor.cc \
+ PYPDoublePinyinEditor.cc \
+ PYPBopomofoEditor.cc \
++ PYPPinyinEngine.cc \
+ $(NULL)
+ ibus_engine_pinyin_h_sources = \
+ PYBopomofo.h \
+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 at gmail.com>
++ * Copyright (c) 2011 Peng Wu <alexepico at 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));
++}
+--
+1.7.6.4
+
+
+From a0b8bc5114056a844e59998766c886f26768cef8 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 28 Sep 2011 17:30:41 +0800
+Subject: [PATCH 44/71] write bopomofo editor
+
+---
+ src/PYPBopomofoEditor.cc | 131 ++++++++++++++++++++++++++++++++++++++++++++++
+ src/PYPBopomofoEditor.h | 14 ++++--
+ src/PYPPhoneticEditor.cc | 71 +++++++++++++++++++++++++
+ src/PYPPhoneticEditor.h | 12 ++--
+ 4 files changed, 218 insertions(+), 10 deletions(-)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index db4f9b4..1945183 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -296,6 +296,38 @@ LibPinyinBopomofoEditor::commit ()
+ }
+
+ void
++LibPinyinBopomofoEditor::updatePreeditText ()
++{
++ /* preedit text = guessed sentence + un-parsed pinyin text */
++ if (G_UNLIKELY (m_text.empty ())) {
++ hidePreeditText ();
++ return;
++ }
++
++ m_buffer.clear ();
++ char *tmp = NULL;
++ pinyin_get_sentence(m_instance, &tmp);
++ if (m_props.modeSimp ()) {
++ m_buffer<<tmp;
++ } else {
++ SimpTradConverter::simpToTrad (tmp, m_buffer);
++ }
++ g_free (tmp);
++ tmp = NULL;
++
++ /* append rest text */
++ const gchar *p = m_text.c_str () + m_pinyin_len;
++ m_buffer << p;
++
++ StaticText preedit_text (m_buffer);
++ /* underline */
++ preedit_text.appendAttribute (IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, -1);
++
++ guint pinyin_cursor = getPinyinCursor ();
++ Editor::updatePreeditText (preedit_text, pinyin_cursor, TRUE);
++}
++
++void
+ LibPinyinBopomofoEditor::updateAuxiliaryText (void)
+ {
+ if (G_UNLIKELY (m_text.empty ())) {
+@@ -340,3 +372,102 @@ LibPinyinBopomofoEditor::updateAuxiliaryText (void)
+ StaticText aux_text (m_buffer);
+ Editor::updateAuxiliaryText (aux_text, TRUE);
+ }
++
++/* move cursor functions */
++
++guint
++LibPinyinBopomofoEditor::getCursorLeftByWord (void)
++{
++ guint cursor;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_pinyin_len;
++ } else {
++ PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_poses;
++ guint pinyin_cursor = getPinyinCursor ();
++ PinyinKeyPos *pos = &g_array_index
++ (pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ cursor = pos->m_pos;
++
++ /* cursor at the begin of one pinyin */
++ g_return_val_if_fail (pinyin_cursor > 0, 0);
++ if ( cursor == m_cursor) {
++ pos = &g_array_index
++ (pinyin_poses, PinyinKeyPos, pinyin_cursor - 1);
++ cursor = pos->m_pos;
++ }
++ }
++
++ return cursor;
++}
++
++guint
++LibPinyinBopomofoEditor::getCursorRightByWord (void)
++{
++ guint cursor;
++
++ if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
++ cursor = m_text.length ();
++ } else {
++ guint pinyin_cursor = getPinyinCursor ();
++ PinyinKeyPos *pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ cursor = pos->get_end_pos ();
++ }
++
++ return cursor;
++}
++
++gboolean
++LibPinyinBopomofoEditor::removeWordBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ guint cursor = getCursorLeftByWord ();
++ m_text.erase (cursor, m_cursor - cursor);
++ m_cursor = cursor;
++ updatePinyin ();
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::removeWordAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ guint cursor = getCursorRightByWord ();
++ m_text.erase (m_cursor, cursor - m_cursor);
++ updatePinyin ();
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::moveCursorLeftByWord (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ guint cursor = getCursorLeftByWord ();
++
++ m_cursor = cursor;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinBopomofoEditor::moveCursorRightByWord (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ guint cursor = getCursorRightByWord ();
++
++ m_cursor = cursor;
++ update ();
++ return TRUE;
++}
++
+diff --git a/src/PYPBopomofoEditor.h b/src/PYPBopomofoEditor.h
+index 9b6b4b6..cfdca2a 100644
+--- a/src/PYPBopomofoEditor.h
++++ b/src/PYPBopomofoEditor.h
+@@ -35,6 +35,13 @@ public:
+ LibPinyinBopomofoEditor (PinyinProperties & props, Config & config);
+ ~LibPinyinBopomofoEditor (void);
+
++public:
++ gboolean removeWordBefore (void);
++ gboolean removeWordAfter (void);
++
++ gboolean moveCursorLeftByWord (void);
++ gboolean moveCursorRightByWord (void);
++
+ protected:
+ String bopomofo;
+ gboolean m_select_mode;
+@@ -47,13 +54,12 @@ protected:
+ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+
+
++ virtual void updatePreeditText ();
+ virtual void updateAuxiliaryText ();
+ virtual void updatePinyin (void);
+
+-#if 0
+- void updateLookupTable ();
+- void updatePreeditText ();
+-#endif
++ guint getCursorLeftByWord (void);
++ guint getCursorRightByWord (void);
+
+ void commit ();
+ void reset ();
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index 60e2da9..6fde250 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -334,4 +334,75 @@ LibPinyinPhoneticEditor::selectCandidateInPage (guint i)
+ return selectCandidate (i);
+ }
+
++gboolean
++LibPinyinPhoneticEditor::removeCharBefore (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor --;
++ m_text.erase (m_cursor, 1);
++
++ updatePinyin ();
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinPhoneticEditor::removeCharAfter (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_text.erase (m_cursor, 1);
++
++ updatePinyin ();
++ update ();
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinPhoneticEditor::moveCursorLeft (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return FALSE;
++
++ m_cursor --;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPhoneticEditor::moveCursorRight (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_cursor ++;
++ update ();
++ return TRUE;
++}
++
++gboolean
++LibPinyinPhoneticEditor::moveCursorToBegin (void)
++{
++ if (G_UNLIKELY (m_cursor == 0))
++ return TRUE;
++
++ m_cursor = 0;
++ update ();
++ return TRUE;
++}
+
++gboolean
++LibPinyinPhoneticEditor::moveCursorToEnd (void)
++{
++ if (G_UNLIKELY (m_cursor == m_text.length ()))
++ return FALSE;
++
++ m_cursor = m_text.length ();
++ update ();
++ return TRUE;
++}
+diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
+index 9d522bf..f2d7309 100644
+--- a/src/PYPPhoneticEditor.h
++++ b/src/PYPPhoneticEditor.h
+@@ -61,16 +61,16 @@ protected:
+
+ /* pure virtual functions */
+ virtual gboolean insert (gint ch) = 0;
+- virtual gboolean removeCharBefore (void) = 0;
+- virtual gboolean removeCharAfter (void) = 0;
++ virtual gboolean removeCharBefore (void);
++ virtual gboolean removeCharAfter (void);
+ virtual gboolean removeWordBefore (void) = 0;
+ virtual gboolean removeWordAfter (void) = 0;
+- virtual gboolean moveCursorLeft (void) = 0;
+- virtual gboolean moveCursorRight (void) = 0;
++ virtual gboolean moveCursorLeft (void);
++ virtual gboolean moveCursorRight (void);
+ virtual gboolean moveCursorLeftByWord (void) = 0;
+ virtual gboolean moveCursorRightByWord (void) = 0;
+- virtual gboolean moveCursorToBegin (void) = 0;
+- virtual gboolean moveCursorToEnd (void) = 0;
++ virtual gboolean moveCursorToBegin (void);
++ virtual gboolean moveCursorToEnd (void);
+ virtual void commit (void) = 0;
+ virtual void updateAuxiliaryText (void) = 0;
+ virtual void updatePreeditText (void) = 0;
+--
+1.7.6.4
+
+
+From d372fbc3c073d37496be1571fdd6a0fec86307ea Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 28 Sep 2011 17:35:18 +0800
+Subject: [PATCH 45/71] re-factor pinyin editor
+
+---
+ src/PYPPinyinEditor.cc | 73 +-----------------------------------------------
+ src/PYPPinyinEditor.h | 6 ----
+ 2 files changed, 1 insertions(+), 78 deletions(-)
+
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index 5599416..817f621 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -298,34 +298,7 @@ LibPinyinPinyinEditor::updateLookupTable ()
+ LibPinyinPhoneticEditor::updateLookupTable ();
+ }
+
+-gboolean
+-LibPinyinPinyinEditor::removeCharBefore (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- m_cursor --;
+- m_text.erase (m_cursor, 1);
+-
+- updatePinyin ();
+- update ();
+-
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinPinyinEditor::removeCharAfter (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_text.erase (m_cursor, 1);
+-
+- updatePinyin ();
+- update ();
+-
+- return TRUE;
+-}
++/* move cursor functions */
+
+ guint
+ LibPinyinPinyinEditor::getCursorLeftByWord (void)
+@@ -398,28 +371,6 @@ LibPinyinPinyinEditor::removeWordAfter (void)
+ }
+
+ gboolean
+-LibPinyinPinyinEditor::moveCursorLeft (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return FALSE;
+-
+- m_cursor --;
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinPinyinEditor::moveCursorRight (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_cursor ++;
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+ LibPinyinPinyinEditor::moveCursorLeftByWord (void)
+ {
+ if (G_UNLIKELY (m_cursor == 0))
+@@ -444,25 +395,3 @@ LibPinyinPinyinEditor::moveCursorRightByWord (void)
+ update ();
+ return TRUE;
+ }
+-
+-gboolean
+-LibPinyinPinyinEditor::moveCursorToBegin (void)
+-{
+- if (G_UNLIKELY (m_cursor == 0))
+- return TRUE;
+-
+- m_cursor = 0;
+- update ();
+- return TRUE;
+-}
+-
+-gboolean
+-LibPinyinPinyinEditor::moveCursorToEnd (void)
+-{
+- if (G_UNLIKELY (m_cursor == m_text.length ()))
+- return FALSE;
+-
+- m_cursor = m_text.length ();
+- update ();
+- return TRUE;
+-}
+diff --git a/src/PYPPinyinEditor.h b/src/PYPPinyinEditor.h
+index 974d2a5..87fe210 100644
+--- a/src/PYPPinyinEditor.h
++++ b/src/PYPPinyinEditor.h
+@@ -36,17 +36,11 @@ public:
+ LibPinyinPinyinEditor (PinyinProperties & props, Config & config);
+
+ public:
+- gboolean removeCharBefore (void);
+- gboolean removeCharAfter (void);
+ gboolean removeWordBefore (void);
+ gboolean removeWordAfter (void);
+
+- gboolean moveCursorLeft (void);
+- gboolean moveCursorRight (void);
+ gboolean moveCursorLeftByWord (void);
+ gboolean moveCursorRightByWord (void);
+- gboolean moveCursorToBegin (void);
+- gboolean moveCursorToEnd (void);
+
+
+ protected:
+--
+1.7.6.4
+
+
+From a87fbe8b02845f67eec4443abb5eee373579c999 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 28 Sep 2011 17:51:56 +0800
+Subject: [PATCH 46/71] polish code
+
+---
+ src/PYPPinyinEngine.cc | 29 +++++++++--------------------
+ src/PYPPinyinEngine.h | 2 ++
+ 2 files changed, 11 insertions(+), 20 deletions(-)
+
+diff --git a/src/PYPPinyinEngine.cc b/src/PYPPinyinEngine.cc
+index 2877702..f8e20ee 100644
+--- a/src/PYPPinyinEngine.cc
++++ b/src/PYPPinyinEngine.cc
+@@ -46,7 +46,9 @@ LibPinyinPinyinEngine::LibPinyinPinyinEngine (IBusEngine *engine)
+ {
+ gint i;
+
+- if (PinyinConfig::instance ().doublePinyin ())
++ m_double_pinyin = PinyinConfig::instance ().doublePinyin ();
++
++ if (m_double_pinyin)
+ m_editors[MODE_INIT].reset
+ (new LibPinyinDoublePinyinEditor (m_props, PinyinConfig::instance ()));
+ else
+@@ -148,23 +150,7 @@ LibPinyinPinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modif
+ #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 ();
+- }
+- }
++ g_assert_not_reached ();
+ }
+ }
+ retval = m_editors[m_input_mode]->processKeyEvent (keyval, keycode, modifiers);
+@@ -189,17 +175,20 @@ 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) {
++ if (!m_double_pinyin) {
+ m_editors[MODE_INIT].reset (new LibPinyinDoublePinyinEditor (m_props, PinyinConfig::instance ()));
+ connectEditorSignals (m_editors[MODE_INIT]);
+ }
++ m_double_pinyin = TRUE;
+ }
+ else {
+- if (dynamic_cast <LibPinyinFullPinyinEditor *> (m_editors[MODE_INIT].get ()) == NULL) {
++ if (m_double_pinyin) {
+ m_editors[MODE_INIT].reset (new LibPinyinFullPinyinEditor (m_props, PinyinConfig::instance ()));
+ connectEditorSignals (m_editors[MODE_INIT]);
+ }
++ m_double_pinyin = FALSE;
+ }
++
+ registerProperties (m_props.properties ());
+ }
+
+diff --git a/src/PYPPinyinEngine.h b/src/PYPPinyinEngine.h
+index d8040c1..7a2d635 100644
+--- a/src/PYPPinyinEngine.h
++++ b/src/PYPPinyinEngine.h
+@@ -70,6 +70,8 @@ private:
+ MODE_LAST,
+ } m_input_mode;
+
++ gboolean m_double_pinyin;
++
+ EditorPtr m_editors[MODE_LAST];
+ EditorPtr m_fallback_editor;
+
+--
+1.7.6.4
+
+
+From a7fa96bf9d0081b3b85fe8177a1b51268267d9e4 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 29 Sep 2011 10:28:25 +0800
+Subject: [PATCH 47/71] fixes libpinyin pinyin engine
+
+---
+ src/PYPPinyinEngine.cc | 4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/src/PYPPinyinEngine.cc b/src/PYPPinyinEngine.cc
+index f8e20ee..1fc4933 100644
+--- a/src/PYPPinyinEngine.cc
++++ b/src/PYPPinyinEngine.cc
+@@ -149,7 +149,7 @@ LibPinyinPinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modif
+ break;
+ #endif
+ }
+- } else {
++ } else { /* Unknown */
+ g_assert_not_reached ();
+ }
+ }
+@@ -277,10 +277,12 @@ LibPinyinPinyinEngine::commitText (Text & text)
+ Engine::commitText (text);
+ if (m_input_mode != MODE_INIT)
+ m_input_mode = MODE_INIT;
++#if 0
+ if (text.text ())
+ static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (*text.text ());
+ else
+ static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (0);
++#endif
+ }
+
+ void
+--
+1.7.6.4
+
+
+From f94b146760628458572483726768faa5cf5cf756 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 29 Sep 2011 11:03:50 +0800
+Subject: [PATCH 48/71] re-factor libpinyin backend
+
+---
+ src/PYLibPinyin.cc | 22 ++++++++++++++++------
+ src/PYLibPinyin.h | 3 +++
+ src/PYMain.cc | 3 +++
+ 3 files changed, 22 insertions(+), 6 deletions(-)
+
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+index 8e3d7af..e4d1b84 100644
+--- a/src/PYLibPinyin.cc
++++ b/src/PYLibPinyin.cc
+@@ -29,15 +29,25 @@ std::unique_ptr<LibPinyinBackEnd> LibPinyinBackEnd::m_instance;
+
+ static LibPinyinBackEnd libpinyin_backend;
+
+-LibPinyinBackEnd::LibPinyinBackEnd(){
+- g_assert (NULL == m_instance.get ());
+- m_pinyin_context = pinyin_init("/usr/share/libpinyin/data", "../data");
+- m_instance.reset(this);
++LibPinyinBackEnd::LibPinyinBackEnd () {
++ m_pinyin_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
++ m_chewing_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
+ }
+
+-LibPinyinBackEnd::~LibPinyinBackEnd(){
++LibPinyinBackEnd::~LibPinyinBackEnd () {
+ pinyin_fini(m_pinyin_context);
+- m_instance = NULL;
++ pinyin_fini(m_chewing_context);
++}
++
++void
++LibPinyinBackEnd::init (void) {
++ g_assert (NULL == m_instance.get ());
++ LibPinyinBackEnd * backend = new LibPinyinBackEnd;
++ m_instance.reset(backend);
++}
++
++void
++LibPinyinBackEnd::finalize (void) {
+ }
+
+ /* Here are the fuzzy pinyin options conversion table. */
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+index 3d40b1d..212bf53 100644
+--- a/src/PYLibPinyin.h
++++ b/src/PYLibPinyin.h
+@@ -41,6 +41,9 @@ public:
+ /* use static initializer in C++. */
+ static LibPinyinBackEnd & instance (void) { return *m_instance; }
+
++ static void init (void);
++ static void finalize (void);
++
+ protected:
+ gboolean setFuzzyOptions (Config *config, pinyin_context_t *context);
+
+diff --git a/src/PYMain.cc b/src/PYMain.cc
+index 021201f..a19a5bf 100644
+--- a/src/PYMain.cc
++++ b/src/PYMain.cc
+@@ -30,6 +30,7 @@
+ #include "PYBus.h"
+ #include "PYConfig.h"
+ #include "PYDatabase.h"
++#include "PYLibPinyin.h"
+
+ using namespace PY;
+
+@@ -83,6 +84,7 @@ start_component (void)
+ Database::init ();
+ PinyinConfig::init (bus);
+ BopomofoConfig::init (bus);
++ LibPinyinBackEnd::init ();
+
+ g_signal_connect ((IBusBus *)bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL);
+
+@@ -143,6 +145,7 @@ sigterm_cb (int sig)
+ static void
+ atexit_cb (void)
+ {
++ LibPinyinBackEnd::finalize ();
+ PY::Database::finalize ();
+ }
+
+--
+1.7.6.4
+
+
+From 5f27536c62860b9436bd38ad509b195c26c1a288 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 29 Sep 2011 13:46:48 +0800
+Subject: [PATCH 49/71] add PYPBopomofoEngine.h
+
+---
+ src/Makefile.am | 1 +
+ src/PYPBopomofoEngine.h | 84 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 85 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPBopomofoEngine.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index fc73a9b..e3c8026 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -120,6 +120,7 @@ ibus_engine_pinyin_h_sources = \
+ PYPDoublePinyinEditor.h \
+ PYPBopomofoEditor.h \
+ PYPPinyinEngine.h \
++ PYPBopomofoEngine.h \
+ $(NULL)
+
+ if IBUS_BUILD_LUA_EXTENSION
+diff --git a/src/PYPBopomofoEngine.h b/src/PYPBopomofoEngine.h
+new file mode 100644
+index 0000000..f767908
+--- /dev/null
++++ b/src/PYPBopomofoEngine.h
+@@ -0,0 +1,84 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (c) 2010 BYVoid <byvoid1 at gmail.com>
++ * Copyright (c) 2011 Peng Wu <alexepico at 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.
++ */
++#ifndef __PY_LIB_PINYIN_BOPOMOFO_ENGINE_H_
++#define __PY_LIB_PINYIN_BOPOMOFO_ENGINE_H_
++
++#include "PYEngine.h"
++#include "PYPinyinProperties.h"
++
++namespace PY {
++
++class LibPinyinBopomofoEngine : public Engine {
++public:
++ LibPinyinBopomofoEngine (IBusEngine *engine);
++ ~LibPinyinBopomofoEngine (void);
++
++ // virtual functions
++ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
++ void focusIn (void);
++ void focusOut (void);
++ void reset (void);
++ void enable (void);
++ void disable (void);
++ void pageUp (void);
++ void pageDown (void);
++ void cursorUp (void);
++ void cursorDown (void);
++ gboolean propertyActivate (const gchar *prop_name, guint prop_state);
++ void candidateClicked (guint index, guint button, guint state);
++
++private:
++ gboolean processPunct (guint keyval, guint keycode, guint modifiers);
++
++private:
++ void showSetupDialog (void);
++ void connectEditorSignals (EditorPtr editor);
++
++private:
++ void commitText (Text & text);
++
++private:
++ PinyinProperties m_props;
++
++ guint m_prev_pressed_key;
++
++ enum {
++ MODE_INIT = 0, // init mode
++ MODE_PUNCT, // punct mode
++#if 0
++ MODE_RAW, // raw mode
++ MODE_ENGLISH, // press v into English input mode
++ MODE_STROKE, // press u into stroke input mode
++ MODE_EXTENSION, // press i into extension input mode
++#endif
++ MODE_LAST,
++ } m_input_mode;
++
++ EditorPtr m_editors[MODE_LAST];
++ EditorPtr m_fallback_editor;
++};
++
++};
++
++
++#endif
+--
+1.7.6.4
+
+
+From a4d249bf8ed06be72eb667d12639a1ba77418d44 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 29 Sep 2011 14:59:44 +0800
+Subject: [PATCH 50/71] add PYPBopomofoEngine.cc
+
+---
+ src/Makefile.am | 1 +
+ src/PYPBopomofoEngine.cc | 254 ++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 255 insertions(+), 0 deletions(-)
+ create mode 100644 src/PYPBopomofoEngine.cc
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index e3c8026..b2a2670 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -71,6 +71,7 @@ ibus_engine_pinyin_c_sources = \
+ PYPDoublePinyinEditor.cc \
+ PYPBopomofoEditor.cc \
+ PYPPinyinEngine.cc \
++ PYPBopomofoEngine.cc \
+ $(NULL)
+ ibus_engine_pinyin_h_sources = \
+ PYBopomofo.h \
+diff --git a/src/PYPBopomofoEngine.cc b/src/PYPBopomofoEngine.cc
+new file mode 100644
+index 0000000..e48e9af
+--- /dev/null
++++ b/src/PYPBopomofoEngine.cc
+@@ -0,0 +1,254 @@
++/* vim:set et ts=4 sts=4:
++ *
++ * ibus-pinyin - The Chinese PinYin engine for IBus
++ *
++ * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (c) 2010 BYVoid <byvoid1 at gmail.com>
++ * Copyright (c) 2011 Peng Wu <alexepico at 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 "PYPBopomofoEngine.h"
++#include <string>
++#include "PYPunctEditor.h"
++#include "PYPBopomofoEditor.h"
++#include "PYFallbackEditor.h"
++#include "PYConfig.h"
++
++using namespace PY;
++
++/* constructor */
++LibPinyinBopomofoEngine::LibPinyinBopomofoEngine (IBusEngine *engine)
++ : Engine (engine),
++ m_props (BopomofoConfig::instance ()),
++ m_prev_pressed_key (IBUS_VoidSymbol),
++ m_input_mode (MODE_INIT),
++ m_fallback_editor (new FallbackEditor (m_props, BopomofoConfig::instance()))
++{
++ gint i;
++
++ /* create editors */
++ m_editors[MODE_INIT].reset (new LibPinyinBopomofoEditor (m_props, BopomofoConfig::instance ()));
++ m_editors[MODE_PUNCT].reset (new PunctEditor (m_props, BopomofoConfig::instance ()));
++
++ m_props.signalUpdateProperty ().connect
++ (std::bind (&LibPinyinBopomofoEngine::updateProperty, this, _1));
++
++ for (i = MODE_INIT; i < MODE_LAST; i++) {
++ connectEditorSignals (m_editors[i]);
++ }
++
++ connectEditorSignals (m_fallback_editor);
++}
++
++/* destructor */
++LibPinyinBopomofoEngine::~LibPinyinBopomofoEngine (void)
++{
++}
++
++gboolean
++LibPinyinBopomofoEngine::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 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 (G_UNLIKELY (m_input_mode == MODE_INIT &&
++ m_editors[MODE_INIT]->text ().empty () &&
++ cmshm_filter (modifiers) == 0 &&
++ keyval == IBUS_grave)){
++ /* if BopomofoEditor is empty and get a grave key,
++ * switch current editor to PunctEditor */
++ m_input_mode = MODE_PUNCT;
++ }
++
++ 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
++LibPinyinBopomofoEngine::focusIn (void)
++{
++ registerProperties (m_props.properties ());
++}
++
++void
++LibPinyinBopomofoEngine::focusOut (void)
++{
++ reset ();
++}
++
++void
++LibPinyinBopomofoEngine::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
++LibPinyinBopomofoEngine::enable (void)
++{
++ m_props.reset ();
++}
++
++void
++LibPinyinBopomofoEngine::disable (void)
++{
++}
++
++void
++LibPinyinBopomofoEngine::pageUp (void)
++{
++ m_editors[m_input_mode]->pageUp ();
++}
++
++void
++LibPinyinBopomofoEngine::pageDown (void)
++{
++ m_editors[m_input_mode]->pageDown ();
++}
++
++void
++LibPinyinBopomofoEngine::cursorUp (void)
++{
++ m_editors[m_input_mode]->cursorUp ();
++}
++
++void
++LibPinyinBopomofoEngine::cursorDown (void)
++{
++ m_editors[m_input_mode]->cursorDown ();
++}
++
++inline void
++LibPinyinBopomofoEngine::showSetupDialog (void)
++{
++ g_assert (FALSE);
++}
++
++gboolean
++LibPinyinBopomofoEngine::propertyActivate (const gchar *prop_name,
++ guint prop_state)
++{
++ const static std::string setup ("setup");
++ if (m_props.propertyActivate (prop_name, prop_state)) {
++ return TRUE;
++ }
++ else if (setup == prop_name) {
++ showSetupDialog ();
++ return TRUE;
++ }
++ return FALSE;
++}
++
++void
++LibPinyinBopomofoEngine::candidateClicked (guint index,
++ guint button,
++ guint state)
++{
++ m_editors[m_input_mode]->candidateClicked (index, button, state);
++}
++
++void
++LibPinyinBopomofoEngine::commitText (Text & text)
++{
++ Engine::commitText (text);
++ if (m_input_mode != MODE_INIT)
++ m_input_mode = MODE_INIT;
++#if 0
++ if (text.text ())
++ static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (*text.text ());
++ else
++ static_cast<FallbackEditor*> (m_fallback_editor.get ())->setPrevCommittedChar (0);
++#endif
++}
++
++void
++LibPinyinBopomofoEngine::connectEditorSignals (EditorPtr editor)
++{
++ editor->signalCommitText ().connect (
++ std::bind (&LibPinyinBopomofoEngine::commitText, this, _1));
++
++ editor->signalUpdatePreeditText ().connect (
++ std::bind (&LibPinyinBopomofoEngine::updatePreeditText, this, _1, _2, _3));
++ editor->signalShowPreeditText ().connect (
++ std::bind (&LibPinyinBopomofoEngine::showPreeditText, this));
++ editor->signalHidePreeditText ().connect (
++ std::bind (&LibPinyinBopomofoEngine::hidePreeditText, this));
++
++ editor->signalUpdateAuxiliaryText ().connect (
++ std::bind (&LibPinyinBopomofoEngine::updateAuxiliaryText, this, _1, _2));
++ editor->signalShowAuxiliaryText ().connect (
++ std::bind (&LibPinyinBopomofoEngine::showAuxiliaryText, this));
++ editor->signalHideAuxiliaryText ().connect (
++ std::bind (&LibPinyinBopomofoEngine::hideAuxiliaryText, this));
++
++ editor->signalUpdateLookupTable ().connect (
++ std::bind (&LibPinyinBopomofoEngine::updateLookupTable, this, _1, _2));
++ editor->signalUpdateLookupTableFast ().connect (
++ std::bind (&LibPinyinBopomofoEngine::updateLookupTableFast, this, _1, _2));
++ editor->signalShowLookupTable ().connect (
++ std::bind (&LibPinyinBopomofoEngine::showLookupTable, this));
++ editor->signalHideLookupTable ().connect (
++ std::bind (&LibPinyinBopomofoEngine::hideLookupTable, this));
++}
++
++
+--
+1.7.6.4
+
+
+From fdb0faafb87135edb9ac6b9d25525dbc2f268f71 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 29 Sep 2011 15:08:52 +0800
+Subject: [PATCH 51/71] add libpinyin engines to PYEngine.cc
+
+---
+ src/PYEngine.cc | 25 ++++++++++++++++++++-----
+ 1 files changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/src/PYEngine.cc b/src/PYEngine.cc
+index 7987146..3a34afc 100644
+--- a/src/PYEngine.cc
++++ b/src/PYEngine.cc
+@@ -23,6 +23,8 @@
+ #include "PYEngine.h"
+ #include "PYPinyinEngine.h"
+ #include "PYBopomofoEngine.h"
++#include "PYPPinyinEngine.h"
++#include "PYPBopomofoEngine.h"
+
+ namespace PY {
+ /* code of engine class of GObject */
+@@ -155,11 +157,24 @@ ibus_pinyin_engine_constructor (GType type,
+ construct_params);
+ name = ibus_engine_get_name ((IBusEngine *) engine);
+
+- if (name &&
+- (std::strcmp (name, "bopomofo") == 0 || std::strcmp (name, "bopomofo-debug") == 0)) {
+- engine->engine = new BopomofoEngine (IBUS_ENGINE (engine));
+- }
+- else {
++ if (name) {
++ if (std::strcmp (name, "pinyin") == 0 ||
++ std::strcmp (name, "pinyin-debug") == 0) {
++ engine->engine = new PinyinEngine (IBUS_ENGINE (engine));
++ }
++ if (std::strcmp (name, "bopomofo") == 0 ||
++ std::strcmp (name, "bopomofo-debug") == 0) {
++ engine->engine = new BopomofoEngine (IBUS_ENGINE (engine));
++ }
++ if (std::strcmp (name, "libpinyin") == 0 ||
++ std::strcmp (name, "libpinyin-debug") == 0) {
++ engine->engine = new LibPinyinPinyinEngine (IBUS_ENGINE (engine));
++ }
++ if (std::strcmp (name, "libbopomofo") == 0 ||
++ std::strcmp (name, "libbopomofo") == 0 ) {
++ engine->engine = new LibPinyinBopomofoEngine (IBUS_ENGINE (engine));
++ }
++ } else {
+ engine->engine = new PinyinEngine (IBUS_ENGINE (engine));
+ }
+ return (GObject *) engine;
+--
+1.7.6.4
+
+
+From 485d515721c2127a9a1fa8996799cdbd900d1b72 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 30 Sep 2011 10:30:11 +0800
+Subject: [PATCH 52/71] add show setup
+
+---
+ src/PYPBopomofoEngine.cc | 3 ++-
+ src/PYPPinyinEngine.cc | 6 +++---
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/src/PYPBopomofoEngine.cc b/src/PYPBopomofoEngine.cc
+index e48e9af..a8ff6fc 100644
+--- a/src/PYPBopomofoEngine.cc
++++ b/src/PYPBopomofoEngine.cc
+@@ -181,7 +181,8 @@ LibPinyinBopomofoEngine::cursorDown (void)
+ inline void
+ LibPinyinBopomofoEngine::showSetupDialog (void)
+ {
+- g_assert (FALSE);
++ g_spawn_command_line_async
++ (LIBEXECDIR"/ibus-setup-pinyin bopomofo --libpinyin", NULL);
+ }
+
+ gboolean
+diff --git a/src/PYPPinyinEngine.cc b/src/PYPPinyinEngine.cc
+index 1fc4933..c163cfc 100644
+--- a/src/PYPPinyinEngine.cc
++++ b/src/PYPPinyinEngine.cc
+@@ -150,7 +150,7 @@ LibPinyinPinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modif
+ #endif
+ }
+ } else { /* Unknown */
+- g_assert_not_reached ();
++ g_warn_if_reached ();
+ }
+ }
+ retval = m_editors[m_input_mode]->processKeyEvent (keyval, keycode, modifiers);
+@@ -247,8 +247,8 @@ LibPinyinPinyinEngine::cursorDown (void)
+ inline void
+ LibPinyinPinyinEngine::showSetupDialog (void)
+ {
+- /* TODO: to be implemented */
+- g_assert (FALSE);
++ g_spawn_command_line_async
++ (LIBEXECDIR"/ibus-setup-pinyin pinyin --libpinyin", NULL);
+ }
+
+ gboolean
+--
+1.7.6.4
+
+
+From 0c6b69bce0c9bf0c79bd4d3db464e6c2eb8cb1e7 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 30 Sep 2011 10:54:25 +0800
+Subject: [PATCH 53/71] add lazy init
+
+---
+ src/PYLibPinyin.cc | 45 ++++++++++++++++++++++++++++++++++++++++-----
+ src/PYLibPinyin.h | 5 +++++
+ 2 files changed, 45 insertions(+), 5 deletions(-)
+
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+index e4d1b84..a7097fe 100644
+--- a/src/PYLibPinyin.cc
++++ b/src/PYLibPinyin.cc
+@@ -30,24 +30,59 @@ std::unique_ptr<LibPinyinBackEnd> LibPinyinBackEnd::m_instance;
+ static LibPinyinBackEnd libpinyin_backend;
+
+ LibPinyinBackEnd::LibPinyinBackEnd () {
+- m_pinyin_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
+- m_chewing_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
++ m_pinyin_context = NULL;
++ m_chewing_context = NULL;
+ }
+
+ LibPinyinBackEnd::~LibPinyinBackEnd () {
+- pinyin_fini(m_pinyin_context);
+- pinyin_fini(m_chewing_context);
++ if (m_pinyin_context)
++ pinyin_fini(m_pinyin_context);
++ m_pinyin_context = NULL;
++ if (m_chewing_context)
++ pinyin_fini(m_chewing_context);
++ m_chewing_context = NULL;
++}
++
++pinyin_instance_t *
++LibPinyinBackEnd::allocPinyinInstance ()
++{
++ if (NULL == m_pinyin_context) {
++ m_pinyin_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
++ }
++ return pinyin_alloc_instance (m_pinyin_context);
++}
++
++void
++LibPinyinBackEnd::freePinyinInstance (pinyin_instance_t *instance)
++{
++ pinyin_free_instance (instance);
++}
++
++pinyin_instance_t *
++LibPinyinBackEnd::allocChewingInstance ()
++{
++ if (NULL == m_chewing_context) {
++ m_chewing_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
++ }
++ return pinyin_alloc_instance (m_chewing_context);
++}
++
++void
++LibPinyinBackEnd::freeChewingInstance (pinyin_instance_t *instance)
++{
++ pinyin_free_instance (instance);
+ }
+
+ void
+ LibPinyinBackEnd::init (void) {
+ g_assert (NULL == m_instance.get ());
+ LibPinyinBackEnd * backend = new LibPinyinBackEnd;
+- m_instance.reset(backend);
++ m_instance.reset (backend);
+ }
+
+ void
+ LibPinyinBackEnd::finalize (void) {
++ m_instance.reset ();
+ }
+
+ /* Here are the fuzzy pinyin options conversion table. */
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+index 212bf53..44ed727 100644
+--- a/src/PYLibPinyin.h
++++ b/src/PYLibPinyin.h
+@@ -38,6 +38,11 @@ public:
+ gboolean setPinyinOptions (Config *config);
+ gboolean setChewingOptions (Config *config);
+
++ pinyin_instance_t *allocPinyinInstance ();
++ void freePinyinInstance (pinyin_instance_t *instance);
++ pinyin_instance_t *allocChewingInstance ();
++ void freeChewingInstance (pinyin_instance_t *instance);
++
+ /* use static initializer in C++. */
+ static LibPinyinBackEnd & instance (void) { return *m_instance; }
+
+--
+1.7.6.4
+
+
+From f1073c63e615ab2b7159937b586007a75a0b492a Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 7 Oct 2011 12:53:14 +0800
+Subject: [PATCH 54/71] write libpinyin backend
+
+---
+ src/PYLibPinyin.cc | 10 ++++++++++
+ 1 files changed, 10 insertions(+), 0 deletions(-)
+
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+index a7097fe..d76e612 100644
+--- a/src/PYLibPinyin.cc
++++ b/src/PYLibPinyin.cc
+@@ -48,6 +48,7 @@ LibPinyinBackEnd::allocPinyinInstance ()
+ {
+ if (NULL == m_pinyin_context) {
+ m_pinyin_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
++ setPinyinOptions (&PinyinConfig::instance ());
+ }
+ return pinyin_alloc_instance (m_pinyin_context);
+ }
+@@ -63,6 +64,7 @@ LibPinyinBackEnd::allocChewingInstance ()
+ {
+ if (NULL == m_chewing_context) {
+ m_chewing_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
++ setChewingOptions (&BopomofoConfig::instance ());
+ }
+ return pinyin_alloc_instance (m_chewing_context);
+ }
+@@ -117,6 +119,8 @@ static const struct {
+ gboolean
+ LibPinyinBackEnd::setFuzzyOptions (Config *config, pinyin_context_t *context)
+ {
++ g_assert (context);
++
+ guint option = config->option ();
+ PinyinCustomSettings custom;
+
+@@ -151,6 +155,9 @@ static const struct{
+ gboolean
+ LibPinyinBackEnd::setPinyinOptions (Config *config)
+ {
++ if (NULL == m_pinyin_context)
++ return FALSE;
++
+ const gint map = config->doublePinyinSchema ();
+ for (guint i = 0; i < G_N_ELEMENTS (shuang_pin_options); i++) {
+ if (map == shuang_pin_options[i].double_pinyin_keyboard) {
+@@ -179,6 +186,9 @@ static const struct {
+ gboolean
+ LibPinyinBackEnd::setChewingOptions (Config *config)
+ {
++ if (NULL == m_chewing_context)
++ return FALSE;
++
+ const gint map = config->bopomofoKeyboardMapping ();
+ for (guint i = 0; i < G_N_ELEMENTS (chewing_options); i++) {
+ if (map == chewing_options[i].bopomofo_keyboard) {
+--
+1.7.6.4
+
+
+From a7efa0d82a7c4cae3a22f1f0e446ca5fff005ffd Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Fri, 7 Oct 2011 13:05:20 +0800
+Subject: [PATCH 55/71] write PYConfig
+
+---
+ src/PYConfig.cc | 7 +++++++
+ 1 files changed, 7 insertions(+), 0 deletions(-)
+
+diff --git a/src/PYConfig.cc b/src/PYConfig.cc
+index 1373607..9e539c8 100644
+--- a/src/PYConfig.cc
++++ b/src/PYConfig.cc
+@@ -23,6 +23,7 @@
+ #include "PYTypes.h"
+ #include "PYBus.h"
+ #include "PYDoublePinyinTable.h"
++#include "PYLibPinyin.h"
+
+ namespace PY {
+
+@@ -336,6 +337,12 @@ Config::valueChangedCallback (IBusConfig *config,
+ Config *self)
+ {
+ self->valueChanged (section, name, value);
++ if (self->m_section != section)
++ return;
++ if (self->m_section == "engine/Pinyin")
++ LibPinyinBackEnd::instance ().setPinyinOptions (self);
++ if (self->m_section == "engine/Bopomofo")
++ LibPinyinBackEnd::instance ().setChewingOptions (self);
+ }
+
+ static const struct {
+--
+1.7.6.4
+
+
+From a73a74a6c1ecb79b7fde223e1e71e6cbec04c802 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Sat, 8 Oct 2011 10:03:26 +0800
+Subject: [PATCH 56/71] alloc/free pinyin instance
+
+---
+ src/PYMain.cc | 2 +-
+ src/PYPBopomofoEditor.cc | 4 ++++
+ src/PYPDoublePinyinEditor.cc | 8 ++++++++
+ src/PYPDoublePinyinEditor.h | 1 +
+ src/PYPFullPinyinEditor.cc | 4 ++++
+ src/PYPPinyinEditor.h | 2 --
+ 6 files changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/src/PYMain.cc b/src/PYMain.cc
+index a19a5bf..c4895ec 100644
+--- a/src/PYMain.cc
++++ b/src/PYMain.cc
+@@ -82,9 +82,9 @@ start_component (void)
+ }
+
+ Database::init ();
++ LibPinyinBackEnd::init ();
+ PinyinConfig::init (bus);
+ BopomofoConfig::init (bus);
+- LibPinyinBackEnd::init ();
+
+ g_signal_connect ((IBusBus *)bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL);
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 1945183..f13fcc9 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -20,6 +20,7 @@
+ */
+ #include "PYPBopomofoEditor.h"
+ #include "PYConfig.h"
++#include "PYLibPinyin.h"
+ #include "PYPinyinProperties.h"
+ #include "PYSimpTradConverter.h"
+ #include "PYHalfFullConverter.h"
+@@ -48,10 +49,13 @@ LibPinyinBopomofoEditor::LibPinyinBopomofoEditor
+ : LibPinyinPhoneticEditor (props, config),
+ m_select_mode (FALSE)
+ {
++ m_instance = LibPinyinBackEnd::instance ().allocChewingInstance ();
+ }
+
+ LibPinyinBopomofoEditor::~LibPinyinBopomofoEditor (void)
+ {
++ LibPinyinBackEnd::instance ().freeChewingInstance (m_instance);
++ m_instance = NULL;
+ }
+
+ void
+diff --git a/src/PYPDoublePinyinEditor.cc b/src/PYPDoublePinyinEditor.cc
+index d37a480..8db80a4 100644
+--- a/src/PYPDoublePinyinEditor.cc
++++ b/src/PYPDoublePinyinEditor.cc
+@@ -21,6 +21,7 @@
+
+ #include "PYPDoublePinyinEditor.h"
+ #include "PYConfig.h"
++#include "PYLibPinyin.h"
+
+ #define DEFINE_DOUBLE_PINYIN_TABLES
+ #include "PYDoublePinyinTable.h"
+@@ -48,6 +49,13 @@ LibPinyinDoublePinyinEditor::LibPinyinDoublePinyinEditor
+ ( PinyinProperties & props, Config & config)
+ : LibPinyinPinyinEditor (props, config)
+ {
++ m_instance = LibPinyinBackEnd::instance ().allocPinyinInstance ();
++}
++
++LibPinyinDoublePinyinEditor::~LibPinyinDoublePinyinEditor (void)
++{
++ LibPinyinBackEnd::instance ().freePinyinInstance (m_instance);
++ m_instance = NULL;
+ }
+
+ gboolean
+diff --git a/src/PYPDoublePinyinEditor.h b/src/PYPDoublePinyinEditor.h
+index b06e144..0989a24 100644
+--- a/src/PYPDoublePinyinEditor.h
++++ b/src/PYPDoublePinyinEditor.h
+@@ -29,6 +29,7 @@ class LibPinyinDoublePinyinEditor : public LibPinyinPinyinEditor {
+
+ public:
+ LibPinyinDoublePinyinEditor (PinyinProperties & props, Config & config);
++ ~LibPinyinDoublePinyinEditor (void);
+
+ gboolean insert (gint ch);
+
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 064ae40..f07204b 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -21,6 +21,7 @@
+
+ #include "PYPFullPinyinEditor.h"
+ #include "PYConfig.h"
++#include "PYLibPinyin.h"
+
+ using namespace PY;
+
+@@ -28,10 +29,13 @@ LibPinyinFullPinyinEditor::LibPinyinFullPinyinEditor
+ (PinyinProperties & props, Config & config)
+ : LibPinyinPinyinEditor (props, config)
+ {
++ m_instance = LibPinyinBackEnd::instance ().allocPinyinInstance ();
+ }
+
+ LibPinyinFullPinyinEditor::~LibPinyinFullPinyinEditor (void)
+ {
++ LibPinyinBackEnd::instance ().freePinyinInstance (m_instance);
++ m_instance = NULL;
+ }
+
+ void
+diff --git a/src/PYPPinyinEditor.h b/src/PYPPinyinEditor.h
+index 87fe210..3c61918 100644
+--- a/src/PYPPinyinEditor.h
++++ b/src/PYPPinyinEditor.h
+@@ -29,8 +29,6 @@ namespace PY {
+
+ class Config;
+
+-class SpecialPhraseTable;
+-
+ class LibPinyinPinyinEditor : public LibPinyinPhoneticEditor {
+ public:
+ LibPinyinPinyinEditor (PinyinProperties & props, Config & config);
+--
+1.7.6.4
+
+
+From d4baea8eb96460c50d241933713b0e419a9abddf Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Sat, 8 Oct 2011 10:11:35 +0800
+Subject: [PATCH 57/71] add engines
+
+---
+ src/PYMain.cc | 32 +++++++++++++++++++++++++++++++-
+ 1 files changed, 31 insertions(+), 1 deletions(-)
+
+diff --git a/src/PYMain.cc b/src/PYMain.cc
+index c4895ec..3516b90 100644
+--- a/src/PYMain.cc
++++ b/src/PYMain.cc
+@@ -103,7 +103,8 @@ start_component (void)
+ "zh_CN",
+ "GPL",
+ "Peng Huang <shawn.p.huang at gmail.com>\n"
+- "BYVoid <byvoid1 at gmail.com>",
++ "BYVoid <byvoid1 at gmail.com>\n"
++ "Peng Wu <alexepico at gmail.com>",
+ PKGDATADIR "/icons/ibus-pinyin.svg",
+ "us"));
+ ibus_component_add_engine (component,
+@@ -113,20 +114,49 @@ start_component (void)
+ "zh_CN",
+ "GPL",
+ "BYVoid <byvoid1 at gmail.com>\n"
++ "Peng Huang <shawn.p.huang at gmail.com>\n"
++ "Peng Wu <alexepico at gmail.com>",
++ PKGDATADIR "/icons/ibus-bopomofo.svg",
++ "us"));
++
++ ibus_component_add_engine (component,
++ ibus_engine_desc_new ("libpinyin-debug",
++ N_("Intelligent Pinyin (debug)"),
++ N_("Intelligent Pinyin input method (debug)"),
++ "zh_CN",
++ "GPL",
++ "Peng Huang <shawn.p.huang at gmail.com>\n"
++ "Peng Wu <alexepico at gmail.com>\n"
++ "BYVoid <byvoid1 at gmail.com>",
++ PKGDATADIR "/icons/ibus-pinyin.svg",
++ "us"));
++ ibus_component_add_engine (component,
++ ibus_engine_desc_new ("libbopomofo-debug",
++ N_("Intelligent Bopomofo (debug)"),
++ N_("Intelligent Bopomofo input method (debug)"),
++ "zh_CN",
++ "GPL",
++ "BYVoid <byvoid1 at gmail.com>\n"
++ "Peng Wu <alexepico at gmail.com>\n"
+ "Peng Huang <shawn.p.huang at gmail.com>",
+ PKGDATADIR "/icons/ibus-bopomofo.svg",
+ "us"));
+
++
+ factory = ibus_factory_new (ibus_bus_get_connection (bus));
+
+ if (ibus) {
+ ibus_factory_add_engine (factory, "pinyin", IBUS_TYPE_PINYIN_ENGINE);
+ ibus_factory_add_engine (factory, "bopomofo", IBUS_TYPE_PINYIN_ENGINE);
++ ibus_factory_add_engine (factory, "libpinyin", IBUS_TYPE_PINYIN_ENGINE);
++ ibus_factory_add_engine (factory, "libbopomofo", IBUS_TYPE_PINYIN_ENGINE);
+ ibus_bus_request_name (bus, "org.freedesktop.IBus.Pinyin", 0);
+ }
+ else {
+ ibus_factory_add_engine (factory, "pinyin-debug", IBUS_TYPE_PINYIN_ENGINE);
+ ibus_factory_add_engine (factory, "bopomofo-debug", IBUS_TYPE_PINYIN_ENGINE);
++ ibus_factory_add_engine (factory, "libpinyin-debug", IBUS_TYPE_PINYIN_ENGINE);
++ ibus_factory_add_engine (factory, "libbopomofo-debug", IBUS_TYPE_PINYIN_ENGINE);
+ ibus_bus_register_component (bus, component);
+ }
+
+--
+1.7.6.4
+
+
+From 33a08c7702e7bdf816cd4e9a21fd8190d2cbc35d Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Sat, 8 Oct 2011 10:37:40 +0800
+Subject: [PATCH 58/71] fixes full editor
+
+---
+ src/PYPFullPinyinEditor.cc | 5 ++++-
+ src/PYPPhoneticEditor.cc | 3 +++
+ src/PYPPinyinEngine.cc | 4 ++--
+ 3 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index f07204b..0b7d603 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -122,12 +122,15 @@ LibPinyinFullPinyinEditor::updateAuxiliaryText ()
+
+ if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
+ m_buffer << '|' << key->get_key_string ();
+- } else { /* in word */
++ } else if (G_LIKELY ( cursor < m_cursor &&
++ m_cursor < pos->get_end_pos() )) { /* in word */
+ /* raw text */
+ String raw = m_text.substr (cursor, pos->get_length ());
+ guint offset = m_cursor - cursor;
+ m_buffer << ' ' << raw.substr (0, offset)
+ << '|' << raw.substr (offset);
++ } else { /* other words */
++ m_buffer << ' ' << key->get_key_string ();
+ }
+ }
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index 6fde250..14773a7 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -32,6 +32,7 @@ LibPinyinPhoneticEditor::LibPinyinPhoneticEditor (PinyinProperties &props,
+ m_pinyin_len (0),
+ m_lookup_table (m_config.pageSize ())
+ {
++ m_candidates = g_array_new(FALSE, TRUE, sizeof(phrase_token_t));
+ }
+
+ gboolean
+@@ -281,6 +282,8 @@ LibPinyinPhoneticEditor::reset (void)
+ void
+ LibPinyinPhoneticEditor::update (void)
+ {
++ guint pinyin_cursor = getPinyinCursor ();
++ pinyin_get_candidates (m_instance, pinyin_cursor, m_candidates);
+ updateLookupTable ();
+ updatePreeditText ();
+ updateAuxiliaryText ();
+diff --git a/src/PYPPinyinEngine.cc b/src/PYPPinyinEngine.cc
+index c163cfc..4aae9a9 100644
+--- a/src/PYPPinyinEngine.cc
++++ b/src/PYPPinyinEngine.cc
+@@ -149,8 +149,8 @@ LibPinyinPinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modif
+ break;
+ #endif
+ }
+- } else { /* Unknown */
+- g_warn_if_reached ();
++ } else {
++ /* TODO: Unknown */
+ }
+ }
+ retval = m_editors[m_input_mode]->processKeyEvent (keyval, keycode, modifiers);
+--
+1.7.6.4
+
+
+From 1d4b7682ac6e05758e2d9dd45b373d48903568b1 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Sat, 8 Oct 2011 11:29:03 +0800
+Subject: [PATCH 59/71] fixes double pinyin
+
+---
+ src/PYPDoublePinyinEditor.cc | 8 +++++++-
+ src/PYPFullPinyinEditor.cc | 3 +++
+ 2 files changed, 10 insertions(+), 1 deletions(-)
+
+diff --git a/src/PYPDoublePinyinEditor.cc b/src/PYPDoublePinyinEditor.cc
+index 8db80a4..4ea039e 100644
+--- a/src/PYPDoublePinyinEditor.cc
++++ b/src/PYPDoublePinyinEditor.cc
+@@ -138,15 +138,21 @@ LibPinyinDoublePinyinEditor::updateAuxiliaryText (void)
+
+ if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
+ m_buffer << '|' << key->get_key_string ();
+- } else { /* in word */
++ } else if (G_LIKELY ( cursor < m_cursor &&
++ m_cursor < pos->get_end_pos() )) { /* in word */
+ /* raw text */
+ String raw = m_text.substr (cursor, pos->get_length ());
+ guint offset = m_cursor - cursor;
+ m_buffer << ' ' << raw.substr (0, offset)
+ << '|' << raw.substr (offset);
++ } else { /* other words */
++ m_buffer << ' ' << key->get_key_string ();
+ }
+ }
+
++ if (m_cursor == m_pinyin_len)
++ m_buffer << '|';
++
+ /* append rest text */
+ const gchar * p = m_text.c_str() + m_pinyin_len;
+ m_buffer << p;
+diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
+index 0b7d603..69ed5ab 100644
+--- a/src/PYPFullPinyinEditor.cc
++++ b/src/PYPFullPinyinEditor.cc
+@@ -134,6 +134,9 @@ LibPinyinFullPinyinEditor::updateAuxiliaryText ()
+ }
+ }
+
++ if (m_cursor == m_pinyin_len)
++ m_buffer << '|';
++
+ /* append rest text */
+ const gchar * p = m_text.c_str() + m_pinyin_len;
+ m_buffer << p;
+--
+1.7.6.4
+
+
+From de6e93108fc2c3b2ce3b8fba522a3edad082b738 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Sat, 8 Oct 2011 11:40:11 +0800
+Subject: [PATCH 60/71] fixes chewing editor
+
+---
+ src/PYEngine.cc | 2 +-
+ src/PYPBopomofoEditor.cc | 8 +++++++-
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/src/PYEngine.cc b/src/PYEngine.cc
+index 3a34afc..27cc312 100644
+--- a/src/PYEngine.cc
++++ b/src/PYEngine.cc
+@@ -171,7 +171,7 @@ ibus_pinyin_engine_constructor (GType type,
+ engine->engine = new LibPinyinPinyinEngine (IBUS_ENGINE (engine));
+ }
+ if (std::strcmp (name, "libbopomofo") == 0 ||
+- std::strcmp (name, "libbopomofo") == 0 ) {
++ std::strcmp (name, "libbopomofo-debug") == 0 ) {
+ engine->engine = new LibPinyinBopomofoEngine (IBUS_ENGINE (engine));
+ }
+ } else {
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index f13fcc9..1a330cc 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -351,7 +351,8 @@ LibPinyinBopomofoEditor::updateAuxiliaryText (void)
+
+ if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
+ m_buffer << '|' << key->get_key_zhuyin_string ();
+- } else { /* in word */
++ } else if (G_LIKELY ( cursor < m_cursor &&
++ m_cursor < pos->get_end_pos() )) { /* in word */
+ /* raw text */
+ String raw = m_text.substr (cursor, pos->get_length ());
+ guint offset = m_cursor - cursor;
+@@ -366,9 +367,14 @@ LibPinyinBopomofoEditor::updateAuxiliaryText (void)
+ for ( iter = after.begin (); iter != after.end (); ++iter) {
+ m_buffer << bopomofo_char[keyvalToBopomofo (*iter)];
+ }
++ } else { /* other words */
++ m_buffer << ' ' << key->get_key_zhuyin_string ();
+ }
+ }
+
++ if (m_cursor == m_pinyin_len)
++ m_buffer << '|';
++
+ /* append rest text */
+ const gchar * p = m_text.c_str() + m_pinyin_len;
+ m_buffer << p;
+--
+1.7.6.4
+
+
+From fd277418074f4ee9c587f95cf93ce83bb71bb4ce Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Sat, 8 Oct 2011 18:53:12 +0800
+Subject: [PATCH 61/71] add to pinyin.xml.in.in
+
+---
+ src/pinyin.xml.in.in | 28 ++++++++++++++++++++++++++++
+ 1 files changed, 28 insertions(+), 0 deletions(-)
+
+diff --git a/src/pinyin.xml.in.in b/src/pinyin.xml.in.in
+index 94b803a..f8ada12 100644
+--- a/src/pinyin.xml.in.in
++++ b/src/pinyin.xml.in.in
+@@ -37,6 +37,34 @@ Peng Wu <alexepico at gmail.com></author>
+ <description>Bopomofo input method</description>
+ <rank>98</rank>
+ </engine>
++ <engine>
++ <name>libpinyin</name>
++ <language>zh</language>
++ <license>GPL</license>
++ <author>Peng Huang <shawn.p.huang at gmail.com>
++ Peng Wu <alexepico at gmail.com>
++ BYVoid <byvoid1 at gmail.com>
++ </author>
++ <icon>${pkgdatadir}/icons/ibus-pinyin.svg</icon>
++ <layout>us</layout>
++ <longname>Intelligent Pinyin</longname>
++ <description>Intelligent Pinyin input method</description>
++ <rank>99</rank>
++ </engine>
++ <engine>
++ <name>libbopomofo</name>
++ <language>zh</language>
++ <license>GPL</license>
++ <author>BYVoid <byvoid1 at gmail.com>
++ Peng Wu <alexepico at gmail.com>
++ Peng Huang <shawn.p.huang at gmail.com>
++ </author>
++ <icon>${pkgdatadir}/icons/ibus-bopomofo.svg</icon>
++ <layout>us</layout>
++ <longname>Intelligent Bopomofo</longname>
++ <description>Intelligent Bopomofo input method</description>
++ <rank>98</rank>
++ </engine>
+ </engines>
+
+ </component>
+--
+1.7.6.4
+
+
+From 2451a4c83885e796d7ddfee9d0321d56bc3703ef Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Sat, 8 Oct 2011 19:01:16 +0800
+Subject: [PATCH 62/71] fixes update preedit text
+
+---
+ src/PYPBopomofoEditor.cc | 14 ++++++++------
+ src/PYPPinyinEditor.cc | 14 ++++++++------
+ 2 files changed, 16 insertions(+), 12 deletions(-)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 1a330cc..185fdb3 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -311,13 +311,15 @@ LibPinyinBopomofoEditor::updatePreeditText ()
+ m_buffer.clear ();
+ char *tmp = NULL;
+ pinyin_get_sentence(m_instance, &tmp);
+- if (m_props.modeSimp ()) {
+- m_buffer<<tmp;
+- } else {
+- SimpTradConverter::simpToTrad (tmp, m_buffer);
++ if (tmp) {
++ if (m_props.modeSimp ()) {
++ m_buffer<<tmp;
++ } else {
++ SimpTradConverter::simpToTrad (tmp, m_buffer);
++ }
++ g_free (tmp);
++ tmp = NULL;
+ }
+- g_free (tmp);
+- tmp = NULL;
+
+ /* append rest text */
+ const gchar *p = m_text.c_str () + m_pinyin_len;
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index 817f621..3d7deff 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -242,13 +242,15 @@ LibPinyinPinyinEditor::updatePreeditText ()
+ m_buffer.clear ();
+ char *tmp = NULL;
+ pinyin_get_sentence(m_instance, &tmp);
+- if (m_props.modeSimp ()) {
+- m_buffer<<tmp;
+- } else {
+- SimpTradConverter::simpToTrad (tmp, m_buffer);
++ if (tmp) {
++ if (m_props.modeSimp ()) {
++ m_buffer<<tmp;
++ } else {
++ SimpTradConverter::simpToTrad (tmp, m_buffer);
++ }
++ g_free (tmp);
++ tmp = NULL;
+ }
+- g_free (tmp);
+- tmp = NULL;
+
+ /* append rest text */
+ const gchar *p = m_text.c_str () + m_pinyin_len;
+--
+1.7.6.4
+
+
+From 83bd966f202824cbb431a581fea626f1252ce96e Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 10 Oct 2011 13:08:27 +0800
+Subject: [PATCH 63/71] update main.py
+
+---
+ setup/main.py | 21 +++++++++++++++------
+ 1 files changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/setup/main.py b/setup/main.py
+index 0e3a729..197ea8b 100644
+--- a/setup/main.py
++++ b/setup/main.py
+@@ -31,12 +31,13 @@ from xdg import BaseDirectory
+ _ = lambda a : gettext.dgettext("ibus-pinyin", a)
+
+ class PreferencesDialog:
+- def __init__(self,engine):
++ def __init__(self,engine,libpinyin):
+ locale.setlocale(locale.LC_ALL, "")
+ localedir = os.getenv("IBUS_LOCALEDIR")
+ gettext.bindtextdomain("ibus-pinyin", localedir)
+ gettext.bind_textdomain_codeset("ibus-pinyin", "UTF-8")
+
++ self.__libpinyin = libpinyin
+ self.__bus = ibus.Bus()
+ self.__config = self.__bus.get_config()
+ self.__builder = gtk.Builder()
+@@ -50,14 +51,16 @@ class PreferencesDialog:
+ self.__init_general()
+ self.__init_pinyin()
+ self.__init_fuzzy()
+- self.__init_dictionary()
++ if not self.__libpinyin:
++ self.__init_dictionary()
+ self.__init_about()
+ elif engine == "bopomofo":
+ self.__config_namespace = "engine/Bopomofo"
+ self.__init_general()
+ self.__init_bopomofo()
+ self.__init_fuzzy()
+- self.__init_dictionary()
++ if not self.__libpinyin:
++ self.__init_dictionary()
+ self.__init_about()
+ self.__convert_fuzzy_pinyin_to_bopomofo()
+
+@@ -138,6 +141,8 @@ class PreferencesDialog:
+ self.__double_pinyin_schema = self.__builder.get_object("DoublePinyinSchema")
+ # self.__double_pinyin_schema_label = self.__builder.get_object("labelDoublePinyinSchema")
+ self.__double_pinyin_show_raw = self.__builder.get_object("DoublePinyinShowRaw")
++ if self.__libpinyin:
++ self.__double_pinyin_show_raw.hide ()
+
+ renderer = gtk.CellRendererText()
+ self.__double_pinyin_schema.pack_start(renderer)
+@@ -409,11 +414,15 @@ class PreferencesDialog:
+
+ def main():
+ name = "pinyin"
+- if len(sys.argv) == 2:
+- name = sys.argv[1]
++ libpinyin = False
++ for arg in sys.argv[1:]:
++ if arg == "--libpinyin":
++ libpinyin = True
++ else:
++ name = arg
+ if name not in ("pinyin", "bopomofo"):
+ name = "pinyin"
+- PreferencesDialog(name).run()
++ PreferencesDialog(name, libpinyin).run()
+
+
+ if __name__ == "__main__":
+--
+1.7.6.4
+
+
+From 6ecd8e73f2d5d035f36c5083aa8e69dbf198c671 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 10 Oct 2011 14:08:17 +0800
+Subject: [PATCH 64/71] add update when select candidate
+
+---
+ src/PYPBopomofoEditor.cc | 2 ++
+ src/PYPPhoneticEditor.cc | 3 ++-
+ src/PYPPinyinEditor.cc | 3 ++-
+ 3 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 185fdb3..34f3df7 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -134,6 +134,7 @@ LibPinyinBopomofoEditor::processAuxiliarySelectKey
+ m_select_mode = TRUE;
+ selectCandidateInPage (i);
+
++ update ();
+ return TRUE;
+ }
+
+@@ -162,6 +163,7 @@ LibPinyinBopomofoEditor::processSelectKey (guint keyval, guint keycode,
+ guint i = pos - keys;
+ selectCandidateInPage (i);
+
++ update ();
+ return TRUE;
+ }
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index 14773a7..a5d7675 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -320,7 +320,8 @@ LibPinyinPhoneticEditor::selectCandidate (guint i)
+
+ /* NOTE: deal with normal candidates selection here by libpinyin. */
+ phrase_token_t *token = &g_array_index (m_candidates, phrase_token_t, i);
+- pinyin_choose_candidate(m_instance, pinyin_cursor, *token);
++ pinyin_choose_candidate (m_instance, pinyin_cursor, *token);
++ pinyin_guess_sentence (m_instance);
+ return TRUE;
+ }
+
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index 3d7deff..4b8aa21 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -57,7 +57,7 @@ LibPinyinPinyinEditor::processNumber (guint keyval, guint keycode,
+ {
+ guint i;
+
+- if (!m_text)
++ if (m_text.empty ())
+ return FALSE;
+
+ switch (keyval) {
+@@ -78,6 +78,7 @@ LibPinyinPinyinEditor::processNumber (guint keyval, guint keycode,
+ if (modifiers == 0)
+ selectCandidateInPage (i);
+
++ update ();
+ return TRUE;
+ }
+
+--
+1.7.6.4
+
+
+From 8c5d9452dba95acae0adfd06769f262f18614041 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 10 Oct 2011 15:25:20 +0800
+Subject: [PATCH 65/71] fixes commit/reset
+
+---
+ src/PYPPhoneticEditor.cc | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index a5d7675..c50b265 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -275,6 +275,7 @@ LibPinyinPhoneticEditor::reset (void)
+ {
+ m_pinyin_len = 0;
+ m_lookup_table.clear ();
++ pinyin_reset (m_instance);
+
+ Editor::reset ();
+ }
+--
+1.7.6.4
+
+
+From 4ecd95e7e241ab53934483b36bb7fba2717afc54 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Mon, 10 Oct 2011 17:30:39 +0800
+Subject: [PATCH 66/71] fixes space handle
+
+---
+ src/PYPPhoneticEditor.cc | 7 ++-----
+ src/PYPPinyinEditor.cc | 2 ++
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index c50b265..dc494d5 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -43,11 +43,8 @@ LibPinyinPhoneticEditor::processSpace (guint keyval, guint keycode,
+ return FALSE;
+ if (cmshm_filter (modifiers) != 0)
+ return TRUE;
+- if (m_lookup_table.size () != 0) {
+- selectCandidate (m_lookup_table.cursorPos ());
+- } else {
+- commit ();
+- }
++
++ commit ();
+ return TRUE;
+ }
+
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index 4b8aa21..195d0e3 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -121,6 +121,7 @@ LibPinyinPinyinEditor::processPunct (guint keyval, guint keycode,
+ break;
+ }
+
++#if 0
+ if (m_config.autoCommit ()) {
+ if (m_lookup_table.size ()) {
+ /* TODO: check here. */
+@@ -129,6 +130,7 @@ LibPinyinPinyinEditor::processPunct (guint keyval, guint keycode,
+ commit ();
+ return FALSE;
+ }
++#endif
+
+ return TRUE;
+ }
+--
+1.7.6.4
+
+
+From 9a5d9bdde8bb12ac38af7a1eb2b7bb73a1ccf3ff Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Tue, 11 Oct 2011 11:14:18 +0800
+Subject: [PATCH 67/71] fixes choose candidate
+
+---
+ src/PYPPhoneticEditor.cc | 8 +++++++-
+ 1 files changed, 7 insertions(+), 1 deletions(-)
+
+diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
+index dc494d5..6be7079 100644
+--- a/src/PYPPhoneticEditor.cc
++++ b/src/PYPPhoneticEditor.cc
+@@ -318,8 +318,14 @@ LibPinyinPhoneticEditor::selectCandidate (guint i)
+
+ /* NOTE: deal with normal candidates selection here by libpinyin. */
+ phrase_token_t *token = &g_array_index (m_candidates, phrase_token_t, i);
+- pinyin_choose_candidate (m_instance, pinyin_cursor, *token);
++ guint8 len = pinyin_choose_candidate (m_instance, pinyin_cursor, *token);
+ pinyin_guess_sentence (m_instance);
++
++ pinyin_cursor += len;
++ PinyinKeyPos *pos = &g_array_index
++ (m_instance->m_pinyin_poses, PinyinKeyPos, pinyin_cursor);
++ m_cursor = pos->get_pos();
++
+ return TRUE;
+ }
+
+--
+1.7.6.4
+
+
+From a4054b39925e3c194d6e8dddad6bbc403dd74ac0 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Tue, 25 Oct 2011 14:11:13 +0800
+Subject: [PATCH 68/71] update pinyin.xml.in.in
+
+---
+ src/pinyin.xml.in.in | 10 ++++++++--
+ 1 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/src/pinyin.xml.in.in b/src/pinyin.xml.in.in
+index f8ada12..d2b267d 100644
+--- a/src/pinyin.xml.in.in
++++ b/src/pinyin.xml.in.in
+@@ -47,10 +47,13 @@ Peng Wu <alexepico at gmail.com></author>
+ </author>
+ <icon>${pkgdatadir}/icons/ibus-pinyin.svg</icon>
+ <layout>us</layout>
+- <longname>Intelligent Pinyin</longname>
++ <longname>Intelligent Pinyin(Beta)</longname>
+ <description>Intelligent Pinyin input method</description>
+ <rank>99</rank>
++ @IBUS_HOTKEYS_XML@
++ @IBUS_SYMBOL_XML@
+ </engine>
++<!--
+ <engine>
+ <name>libbopomofo</name>
+ <language>zh</language>
+@@ -61,10 +64,13 @@ Peng Wu <alexepico at gmail.com></author>
+ </author>
+ <icon>${pkgdatadir}/icons/ibus-bopomofo.svg</icon>
+ <layout>us</layout>
+- <longname>Intelligent Bopomofo</longname>
++ <longname>Intelligent Bopomofo(Beta)</longname>
+ <description>Intelligent Bopomofo input method</description>
+ <rank>98</rank>
++ @IBUS_HOTKEYS_XML@
++ @IBUS_SYMBOL_XML@
+ </engine>
++-->
+ </engines>
+
+ </component>
+--
+1.7.6.4
+
+
+From 4c36af48e4a173a7008d2742fbdf1e0a97481c1b Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Tue, 25 Oct 2011 14:36:36 +0800
+Subject: [PATCH 69/71] add user data directory support
+
+---
+ src/PYLibPinyin.cc | 16 +++++++++++++++-
+ 1 files changed, 15 insertions(+), 1 deletions(-)
+
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+index d76e612..077e7e0 100644
+--- a/src/PYLibPinyin.cc
++++ b/src/PYLibPinyin.cc
+@@ -47,8 +47,15 @@ pinyin_instance_t *
+ LibPinyinBackEnd::allocPinyinInstance ()
+ {
+ if (NULL == m_pinyin_context) {
+- m_pinyin_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
++ gchar * userdir = g_build_filename (g_get_home_dir(), ".cache",
++ "ibus", "libpinyin", NULL);
++ int retval = g_mkdir_with_parents (userdir, 0700);
++ if (retval) {
++ g_free(userdir); userdir = NULL;
++ }
++ m_pinyin_context = pinyin_init ("/usr/share/libpinyin/data", userdir);
+ setPinyinOptions (&PinyinConfig::instance ());
++ g_free(userdir);
+ }
+ return pinyin_alloc_instance (m_pinyin_context);
+ }
+@@ -63,8 +70,15 @@ pinyin_instance_t *
+ LibPinyinBackEnd::allocChewingInstance ()
+ {
+ if (NULL == m_chewing_context) {
++ gchar * userdir = g_build_filename (g_get_home_dir(), ".cache",
++ "ibus", "libbopomofo", NULL);
++ int retval = g_mkdir_with_parents (userdir, 0700);
++ if (retval) {
++ g_free(userdir); userdir = NULL;
++ }
+ m_chewing_context = pinyin_init ("/usr/share/libpinyin/data", NULL);
+ setChewingOptions (&BopomofoConfig::instance ());
++ g_free(userdir);
+ }
+ return pinyin_alloc_instance (m_chewing_context);
+ }
+--
+1.7.6.4
+
+
+From e4f2fa619027b987645b0c5e5cf4d5d152c67306 Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Wed, 26 Oct 2011 10:10:58 +0800
+Subject: [PATCH 70/71] add save support
+
+---
+ src/PYLibPinyin.cc | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ src/PYLibPinyin.h | 8 +++++++
+ src/PYPBopomofoEditor.cc | 1 +
+ src/PYPPinyinEditor.cc | 2 +
+ 4 files changed, 62 insertions(+), 0 deletions(-)
+
+diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
+index 077e7e0..062b3c9 100644
+--- a/src/PYLibPinyin.cc
++++ b/src/PYLibPinyin.cc
+@@ -23,6 +23,8 @@
+ #include "PYTypes.h"
+ #include "PYConfig.h"
+
++#define LIBPINYIN_SAVE_TIMEOUT (5 * 60)
++
+ using namespace PY;
+
+ std::unique_ptr<LibPinyinBackEnd> LibPinyinBackEnd::m_instance;
+@@ -30,11 +32,19 @@ std::unique_ptr<LibPinyinBackEnd> LibPinyinBackEnd::m_instance;
+ static LibPinyinBackEnd libpinyin_backend;
+
+ LibPinyinBackEnd::LibPinyinBackEnd () {
++ m_timeout_id = 0;
++ m_timer = g_timer_new();
+ m_pinyin_context = NULL;
+ m_chewing_context = NULL;
+ }
+
+ LibPinyinBackEnd::~LibPinyinBackEnd () {
++ g_timer_destroy (m_timer);
++ if (m_timeout_id != 0) {
++ saveUserDB ();
++ g_source_remove (m_timeout_id);
++ }
++
+ if (m_pinyin_context)
+ pinyin_fini(m_pinyin_context);
+ m_pinyin_context = NULL;
+@@ -215,3 +225,44 @@ LibPinyinBackEnd::setChewingOptions (Config *config)
+ setFuzzyOptions (config, m_chewing_context);
+ return TRUE;
+ }
++
++void
++LibPinyinBackEnd::modified (void)
++{
++ /* Restart the timer */
++ g_timer_start (m_timer);
++
++ if (m_timeout_id != 0)
++ return;
++
++ m_timeout_id = g_timeout_add_seconds (LIBPINYIN_SAVE_TIMEOUT,
++ LibPinyinBackEnd::timeoutCallback,
++ static_cast<gpointer> (this));
++}
++
++gboolean
++LibPinyinBackEnd::timeoutCallback (gpointer data)
++{
++ LibPinyinBackEnd *self = static_cast<LibPinyinBackEnd *> (data);
++
++ /* Get the elapsed time since last modification of database. */
++ guint elapsed = (guint)g_timer_elapsed (self->m_timer, NULL);
++
++ if (elapsed >= LIBPINYIN_SAVE_TIMEOUT &&
++ self->saveUserDB ()) {
++ self->m_timeout_id = 0;
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++gboolean
++LibPinyinBackEnd::saveUserDB (void)
++{
++ if (m_pinyin_context)
++ pinyin_save (m_pinyin_context);
++ if (m_chewing_context)
++ pinyin_save (m_chewing_context);
++ return TRUE;
++}
+diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
+index 44ed727..32919b9 100644
+--- a/src/PYLibPinyin.h
++++ b/src/PYLibPinyin.h
+@@ -42,6 +42,7 @@ public:
+ void freePinyinInstance (pinyin_instance_t *instance);
+ pinyin_instance_t *allocChewingInstance ();
+ void freeChewingInstance (pinyin_instance_t *instance);
++ void modified (void);
+
+ /* use static initializer in C++. */
+ static LibPinyinBackEnd & instance (void) { return *m_instance; }
+@@ -53,10 +54,17 @@ protected:
+ gboolean setFuzzyOptions (Config *config, pinyin_context_t *context);
+
+ private:
++ gboolean saveUserDB (void);
++ static gboolean timeoutCallback (gpointer data);
++
++private:
+ /* libpinyin context */
+ pinyin_context_t *m_pinyin_context;
+ pinyin_context_t *m_chewing_context;
+
++ guint m_timeout_id;
++ GTimer *m_timer;
++
+ private:
+ static std::unique_ptr<LibPinyinBackEnd> m_instance;
+ };
+diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
+index 34f3df7..7592e2a 100644
+--- a/src/PYPBopomofoEditor.cc
++++ b/src/PYPBopomofoEditor.cc
+@@ -297,6 +297,7 @@ LibPinyinBopomofoEditor::commit ()
+ }
+
+ pinyin_train(m_instance);
++ LibPinyinBackEnd::instance ().modified();
+ LibPinyinPhoneticEditor::commit ((const gchar *)m_buffer);
+ reset();
+ }
+diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
+index 195d0e3..e676f6d 100644
+--- a/src/PYPPinyinEditor.cc
++++ b/src/PYPPinyinEditor.cc
+@@ -24,6 +24,7 @@
+ #include "PYPinyinProperties.h"
+ #include "PYSimpTradConverter.h"
+ #include "PYHalfFullConverter.h"
++#include "PYLibPinyin.h"
+
+ using namespace PY;
+
+@@ -229,6 +230,7 @@ LibPinyinPinyinEditor::commit ()
+ }
+
+ pinyin_train(m_instance);
++ LibPinyinBackEnd::instance ().modified ();
+ LibPinyinPhoneticEditor::commit ((const gchar *)m_buffer);
+ reset();
+ }
+--
+1.7.6.4
+
+
+From 025580e8f4ad1d758729e467e73011046fdba64b Mon Sep 17 00:00:00 2001
+From: Peng Wu <alexepico at gmail.com>
+Date: Thu, 27 Oct 2011 11:36:59 +0800
+Subject: [PATCH 71/71] hide bopomofo
+
+---
+ src/pinyin.xml.in.in | 23 ++++-------------------
+ 1 files changed, 4 insertions(+), 19 deletions(-)
+
+diff --git a/src/pinyin.xml.in.in b/src/pinyin.xml.in.in
+index d2b267d..93b14a1 100644
+--- a/src/pinyin.xml.in.in
++++ b/src/pinyin.xml.in.in
+@@ -23,6 +23,8 @@ Peng Wu <alexepico at gmail.com></author>
+ <longname>Pinyin</longname>
+ <description>Pinyin input method</description>
+ <rank>99</rank>
++ @IBUS_HOTKEYS_XML@
++ @IBUS_SYMBOL_XML@
+ </engine>
+ <engine>
+ <name>bopomofo</name>
+@@ -36,6 +38,8 @@ Peng Wu <alexepico at gmail.com></author>
+ <longname>Bopomofo</longname>
+ <description>Bopomofo input method</description>
+ <rank>98</rank>
++ @IBUS_HOTKEYS_XML@
++ @IBUS_SYMBOL_XML@
+ </engine>
+ <engine>
+ <name>libpinyin</name>
+@@ -53,24 +57,5 @@ Peng Wu <alexepico at gmail.com></author>
+ @IBUS_HOTKEYS_XML@
+ @IBUS_SYMBOL_XML@
+ </engine>
+-<!--
+- <engine>
+- <name>libbopomofo</name>
+- <language>zh</language>
+- <license>GPL</license>
+- <author>BYVoid <byvoid1 at gmail.com>
+- Peng Wu <alexepico at gmail.com>
+- Peng Huang <shawn.p.huang at gmail.com>
+- </author>
+- <icon>${pkgdatadir}/icons/ibus-bopomofo.svg</icon>
+- <layout>us</layout>
+- <longname>Intelligent Bopomofo(Beta)</longname>
+- <description>Intelligent Bopomofo input method</description>
+- <rank>98</rank>
+- @IBUS_HOTKEYS_XML@
+- @IBUS_SYMBOL_XML@
+- </engine>
+--->
+ </engines>
+-
+ </component>
+--
+1.7.6.4
+
diff --git a/ibus-pinyin-xx-icon-symbol.patch b/ibus-pinyin-xx-icon-symbol.patch
index 4ddec26..4b195eb 100644
--- a/ibus-pinyin-xx-icon-symbol.patch
+++ b/ibus-pinyin-xx-icon-symbol.patch
@@ -2,7 +2,7 @@ Index: ibus-pinyin-1.3.99.20110706/configure.ac
===================================================================
--- ibus-pinyin-1.3.99.20110706.orig/configure.ac
+++ ibus-pinyin-1.3.99.20110706/configure.ac
-@@ -141,6 +141,10 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GET
+@@ -146,6 +146,10 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GET
AM_GLIB_GNU_GETTEXT
@@ -13,28 +13,6 @@ Index: ibus-pinyin-1.3.99.20110706/configure.ac
# --enable-db-android
AC_ARG_ENABLE(db-android,
AS_HELP_STRING([--disable-db-android],
-Index: ibus-pinyin-1.3.99.20110706/src/pinyin.xml.in.in
-===================================================================
---- ibus-pinyin-1.3.99.20110706.orig/src/pinyin.xml.in.in
-+++ ibus-pinyin-1.3.99.20110706/src/pinyin.xml.in.in
-@@ -23,6 +23,8 @@ Peng Wu <alexepico at gmail.com></aut
- <longname>Pinyin</longname>
- <description>Pinyin input method</description>
- <rank>99</rank>
-+ @IBUS_HOTKEYS_XML@
-+ @IBUS_SYMBOL_XML@
- </engine>
- <engine>
- <name>bopomofo</name>
-@@ -36,6 +38,8 @@ Peng Wu <alexepico at gmail.com></aut
- <longname>Bopomofo</longname>
- <description>Bopomofo input method</description>
- <rank>98</rank>
-+ @IBUS_HOTKEYS_XML@
-+ @IBUS_SYMBOL_XML@
- </engine>
- </engines>
-
Index: ibus-pinyin-1.3.99.20110706/m4/ibus.m4
===================================================================
--- /dev/null
diff --git a/ibus-pinyin.spec b/ibus-pinyin.spec
index 26eceef..1829501 100644
--- a/ibus-pinyin.spec
+++ b/ibus-pinyin.spec
@@ -1,12 +1,13 @@
Name: ibus-pinyin
Version: 1.3.99.20110706
-Release: 2%{?dist}
+Release: 3%{?dist}
Summary: The Chinese Pinyin and Bopomofo engines for IBus input platform
License: GPLv2+
Group: System Environment/Libraries
URL: http://code.google.com/p/ibus
Source0: http://ibus.googlecode.com/files/%{name}-%{version}.tar.gz
Source1: http://ibus.googlecode.com/files/pinyin-database-1.2.99.tar.bz2
+Patch0: ibus-pinyin-libpinyin-integration.patch
Patch1: ibus-pinyin-xx-icon-symbol.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -52,6 +53,7 @@ The phrase database for ibus Pinyin and Bopomofo from android project.
%prep
%setup -q
+%patch0 -p1 -b .integration
%patch1 -p1 -b .xx-icon
cp %{SOURCE1} data/db/open-phrase
@@ -108,6 +110,9 @@ rm -rf $RPM_BUILD_ROOT
%{_datadir}/ibus-pinyin/db/android.db
%changelog
+* Thu Oct 27 2011 Peng Wu <pwu at redhat.com> - 1.3.99.20110706-3
+- Add ibus-pinyin-libpinyin-integration.patch
+
* Mon Aug 01 2011 Peng Wu <pwu at redhat.com> - 1.3.99.20110706-2
- Add ibus-pinyin-xx-icon-symbol.patch
More information about the scm-commits
mailing list