summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeng Huang <shawn.p.huang@gmail.com>2009-09-23 13:30:02 +0800
committerPeng Huang <shawn.p.huang@gmail.com>2009-09-23 13:30:02 +0800
commit998c9299f04a4756ff8a08ab3448b3f7860b9fe0 (patch)
tree89a3ccd529632944e1659d7b2b01a1d5595d30c2
parent9911013dd7e4edc7c295dad24121309b1fda5718 (diff)
downloadibus-libpinyin-998c9299f04a4756ff8a08ab3448b3f7860b9fe0.tar.gz
ibus-libpinyin-998c9299f04a4756ff8a08ab3448b3f7860b9fe0.tar.xz
ibus-libpinyin-998c9299f04a4756ff8a08ab3448b3f7860b9fe0.zip
Import c version pinyin engine
-rw-r--r--AUTHORS8
-rw-r--r--Makefile.am20
-rw-r--r--README2
-rwxr-xr-xautogen.sh4
-rw-r--r--configure.ac64
-rw-r--r--data/Makefile.am (renamed from icons/Makefile.am)49
-rw-r--r--data/icons/Makefile.am37
-rw-r--r--data/icons/chinese.svg (renamed from icons/chinese.svg)0
-rw-r--r--data/icons/english.svg (renamed from icons/english.svg)0
-rw-r--r--data/icons/full-punct.svg (renamed from icons/full-punct.svg)0
-rw-r--r--data/icons/full.svg (renamed from icons/full-letter.svg)0
-rw-r--r--data/icons/half-punct.svg (renamed from icons/half-punct.svg)0
-rw-r--r--data/icons/half.svg (renamed from icons/half-letter.svg)0
-rw-r--r--data/icons/ibus-pinyin.svg (renamed from icons/ibus-pinyin.svg)0
-rw-r--r--data/scripts/create_db.py94
-rw-r--r--data/scripts/create_index.py21
-rw-r--r--data/scripts/create_unique_index.py27
-rw-r--r--data/scripts/double.py38
-rw-r--r--data/scripts/id.py1
-rw-r--r--data/scripts/pydict.py (renamed from engine/pydict.py)0
-rw-r--r--data/scripts/pyutil.py (renamed from engine/pyutil.py)0
-rw-r--r--debian/README.Debian6
-rw-r--r--debian/changelog6
-rw-r--r--debian/compat1
-rw-r--r--debian/control12
-rw-r--r--debian/copyright22
-rw-r--r--debian/cron.d.ex4
-rw-r--r--debian/dirs2
-rw-r--r--debian/docs2
-rw-r--r--debian/emacsen-install.ex45
-rw-r--r--debian/emacsen-remove.ex15
-rw-r--r--debian/emacsen-startup.ex25
-rw-r--r--debian/ibus-pinyin-default.ex10
-rw-r--r--debian/ibus-pinyin.doc-base.EX22
-rw-r--r--debian/init.d.ex157
-rw-r--r--debian/init.d.lsb.ex281
-rw-r--r--debian/manpage.1.ex59
-rw-r--r--debian/manpage.sgml.ex156
-rw-r--r--debian/manpage.xml.ex144
-rw-r--r--debian/menu.ex2
-rw-r--r--debian/postinst.ex41
-rw-r--r--debian/postrm.ex39
-rw-r--r--debian/preinst.ex37
-rw-r--r--debian/prerm.ex40
-rw-r--r--debian/rules99
-rw-r--r--debian/watch.ex22
-rw-r--r--engine/Makefile.am90
-rw-r--r--engine/factory.py62
-rw-r--r--engine/ibus-engine-pinyin.in29
-rw-r--r--engine/main.py96
-rw-r--r--engine/pinyin.py1317
-rw-r--r--engine/pycreatedb.py56
-rw-r--r--engine/pyparser.py153
-rw-r--r--engine/pysqlitedb.py538
-rw-r--r--engine/special_phrase18
-rw-r--r--engine/specialphrase.py76
-rw-r--r--engine/specialtable.py74
-rw-r--r--ibus-pinyin.spec.in28
-rw-r--r--po/LINGUAS1
-rw-r--r--po/POTFILES.in23
-rw-r--r--po/ja.po245
-rw-r--r--po/zh_CN.gmobin0 -> 2451 bytes
-rw-r--r--po/zh_CN.po303
-rw-r--r--setup/Makefile.am3
-rw-r--r--setup/ibus-pinyin-preferences.glade1239
-rw-r--r--setup/ibus-setup-pinyin.in3
-rw-r--r--setup/main.py483
l---------setup/pydict.py1
-rw-r--r--setup/setup.glade958
-rw-r--r--src/Array.h108
-rw-r--r--src/Bus.h17
-rw-r--r--src/Config.cc203
-rw-r--r--src/Config.h56
-rw-r--r--src/Database.cc583
-rw-r--r--src/Database.h60
-rw-r--r--src/DoublePinyinEditor.cc246
-rw-r--r--src/DoublePinyinEditor.h36
-rw-r--r--src/DoublePinyinTable.h301
-rw-r--r--src/Engine.cc207
-rw-r--r--src/Engine.h15
-rw-r--r--src/FullPinyinEditor.cc182
-rw-r--r--src/FullPinyinEditor.h52
-rw-r--r--src/HalfFullConverter.cc98
-rw-r--r--src/HalfFullConverter.h19
-rw-r--r--src/LookupTable.h36
-rw-r--r--src/Main.cc100
-rw-r--r--src/Makefile.am158
-rw-r--r--src/PhraseArray.h13
-rw-r--r--src/PhraseEditor.cc157
-rw-r--r--src/PhraseEditor.h92
-rw-r--r--src/PinyinArray.h13
-rw-r--r--src/PinyinEditor.cc20
-rw-r--r--src/PinyinEditor.h52
-rw-r--r--src/PinyinEngine.cc680
-rw-r--r--src/PinyinEngine.h121
-rw-r--r--src/PinyinParser.cc243
-rw-r--r--src/PinyinParser.h26
-rw-r--r--src/Pointer.h55
-rw-r--r--src/Property.h43
-rw-r--r--src/SpecialTable.cc0
-rw-r--r--src/SpecialTable.h17
-rw-r--r--src/String.h150
-rw-r--r--src/Text.h27
-rw-r--r--src/Types.h135
-rw-r--r--src/Util.h64
l---------src/main.db1
-rw-r--r--src/pinyin.xml.in.in (renamed from engine/pinyin.xml.in.in)12
-rw-r--r--src/scripts/genpytable.py354
-rw-r--r--src/scripts/pydict.py105
-rw-r--r--src/special_table (renamed from engine/special_table)4
110 files changed, 6761 insertions, 5510 deletions
diff --git a/AUTHORS b/AUTHORS
index d6c43bf..a32ecc2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,9 +1 @@
-
Huang Peng <shawn.p.huang@gmail.com>
-
-Translators:
------------
-zh_CN.po:
-Huang Peng <shawn.p.huang@gmail.com>
-ja.po:
-UTUMI Hirosi <utuhiro78@yahoo.co.jp>
diff --git a/Makefile.am b/Makefile.am
index ba1b395..f8f9eec 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
# vim:set noet ts=4:
#
-# ibus-pinyin - The PinYin engine for IBus
+# ibus-pinyin - The Chinese PinYin engine for IBus
#
# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
#
@@ -19,9 +19,9 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
SUBDIRS = \
- engine \
+ src \
setup \
- icons \
+ data \
m4 \
po \
$(NULL)
@@ -30,7 +30,7 @@ ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = \
autogen.sh \
- @PACKAGE_NAME@.spec.in \
+ ibus-pinyin.spec.in \
$(NULL)
noinst_DIST = \
@@ -44,18 +44,18 @@ DISTCLEANFILES = \
rpm: dist @PACKAGE_NAME@.spec
rpmbuild -bb \
--define "_sourcedir `pwd`" \
- --define "_builddir `pwd`" \
+ --define "_builddir `pwd`/rpm" \
+ --define "_srcrpmdir `pwd`/rpm" \
+ --define "_rpmdir `pwd`/rpm" \
--define "_specdir `pwd`" \
- --define "_rpmdir `pwd`" \
- --define "_srcrpmdir `pwd`" \
@PACKAGE_NAME@.spec
srpm: dist @PACKAGE_NAME@.spec
rpmbuild -bs \
--define "_sourcedir `pwd`" \
- --define "_builddir `pwd`" \
- --define "_srcrpmdir `pwd`" \
- --define "_rpmdir `pwd`" \
+ --define "_builddir `pwd`/rpm" \
+ --define "_srcrpmdir `pwd`/rpm" \
+ --define "_rpmdir `pwd`/rpm" \
--define "_specdir `pwd`" \
@PACKAGE_NAME@.spec
diff --git a/README b/README
index 25d8464..3230969 100644
--- a/README
+++ b/README
@@ -1,2 +1,2 @@
ibus-pinyin
-It is a PinYin engine for IBus.
+It is a Chinese Pinyin input method for IBus.
diff --git a/autogen.sh b/autogen.sh
index 94f8fd3..9e533f0 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -5,7 +5,9 @@ set -x
autopoint
libtoolize --automake --copy
aclocal -I m4
-# autoheader
+autoheader
automake --add-missing --copy
autoconf
+export CFLAGS="-Wall -g -O0 -Wl,--no-undefined"
+export CXXFLAGS="$CFLAGS"
./configure --enable-maintainer-mode $*
diff --git a/configure.ac b/configure.ac
index ee158a8..5c175c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
# vim:set et ts=4:
#
-# ibus-pinyin - The PinYin engine for IBus
+# ibus-pinyin - The Chinese PinYin engine for IBus
#
# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
#
@@ -19,42 +19,60 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# if not 1, append datestamp to the version number.
-m4_define([package_name], [ibus-pinyin])
m4_define([ibus_released], [0])
m4_define([ibus_major_version], [1])
m4_define([ibus_minor_version], [2])
-m4_define([ibus_micro_version], [0])
+m4_define([ibus_micro_version], [99])
m4_define(ibus_maybe_datestamp,
m4_esyscmd([if test x]ibus_released[ != x1; then date +.%Y%m%d | tr -d '\n\r'; fi]))
m4_define([ibus_version],
ibus_major_version.ibus_minor_version.ibus_micro_version[]ibus_maybe_datestamp)
-AC_INIT([package_name], [ibus_version], [http://code.google.com/p/ibus/issues/entry], [package_name])
+AC_INIT([ibus-pinyin], [ibus_version], [http://code.google.com/p/ibus/issues/entry],[ibus-pinyin])
AM_INIT_AUTOMAKE([1.10])
-# AC_GNU_SOURCE
+AC_GNU_SOURCE
-# AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
# define PACKAGE_VERSION_* variables
-# AS_VERSION
-# AS_NANO
-# AM_SANITY_CHECK
+AS_VERSION
+AS_NANO
+AM_SANITY_CHECK
AM_MAINTAINER_MODE
-# AM_DISABLE_STATIC
-# AC_PROG_CC
-# AM_PROG_CC_C_O
-# AC_PROG_CXX
-# AC_ISC_POSIX
-# AC_HEADER_STDC
-# AM_PROG_LIBTOOL
+AM_DISABLE_STATIC
+AC_PROG_CC
+AC_PROG_CXX
+AM_PROG_CC_C_O
+AC_ISC_POSIX
+AC_HEADER_STDC
+AM_PROG_LIBTOOL
+
+# check ibus
+PKG_CHECK_MODULES(IBUS, [
+ ibus-1.0
+])
+
+# check sqlite
+PKG_CHECK_MODULES(SQLITE, [
+ sqlite3
+])
+
+# check uuid
+PKG_CHECK_MODULES(UUID, [
+ uuid
+])
+
+# check env
+AC_PATH_PROG(ENV, env)
+AC_SUBST(ENV)
#check python
AM_PATH_PYTHON([2.5])
# define GETTEXT_* variables
-GETTEXT_PACKAGE="$PACKAGE_NAME"
+GETTEXT_PACKAGE=ibus-pinyin
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Define to the read-only architecture-independent data directory.])
@@ -63,16 +81,16 @@ AM_GNU_GETTEXT_VERSION(0.16.1)
# OUTPUT files
-AC_CONFIG_FILES(po/Makefile.in
+AC_CONFIG_FILES([ po/Makefile.in
Makefile
ibus-pinyin.spec
-engine/Makefile
-engine/ibus-engine-pinyin
-engine/pinyin.xml.in
+src/Makefile
+src/pinyin.xml.in
setup/Makefile
setup/ibus-setup-pinyin
-icons/Makefile
+data/Makefile
+data/icons/Makefile
m4/Makefile
-)
+])
AC_OUTPUT
diff --git a/icons/Makefile.am b/data/Makefile.am
index ee5c45c..bca638d 100644
--- a/icons/Makefile.am
+++ b/data/Makefile.am
@@ -1,6 +1,6 @@
# vim:set noet ts=4:
#
-# ibus-pinyin - The PinYin engine for IBus
+# ibus-pinyin - The Chinese PinYin engine for IBus
#
# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
#
@@ -18,18 +18,43 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-icons_DATA = \
- ibus-pinyin.svg \
- full-letter.svg \
- half-letter.svg \
- full-punct.svg \
- half-punct.svg \
- chinese.svg \
- english.svg \
+
+SUBDIRS = \
+ icons \
+ $(NULL)
+
+main_db_DATA = \
+ db/main.db \
+ db/COPYING \
+ db/create_index.sql \
$(NULL)
+main_dbdir = $(pkgdatadir)/db
+
+install-data-hook:
+ @( \
+if test "$(NO_INDEX)" = ""; then \
+ cd $(DESTDIR)$(main_dbdir); \
+ echo "Create INDEX"; \
+ sqlite3 main.db ".read create_index.sql"; \
+fi)
+
+DBVER = 1.2.99
+DBTAR = pinyin-database-$(DBVER).tar.bz2
-iconsdir = $(pkgdatadir)/icons
+$(DBTAR):
+ wget http://ibus.googlecode.com/files/$(DBTAR)
+
+db.stamp: $(DBTAR)
+ tar jxvfm $(DBTAR)
+ touch $@
+
+$(main_db_DATA): db.stamp
+
+CLEANFILES = \
+ db.stamp \
+ db/* \
+ $(NULL)
-EXTRA_DIST = \
- $(icons_DATA) \
+DISTCLEANFILES = \
+ $(DBTAR) \
$(NULL)
diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am
new file mode 100644
index 0000000..5d59077
--- /dev/null
+++ b/data/icons/Makefile.am
@@ -0,0 +1,37 @@
+# vim:set noet ts=4:
+#
+# ibus-pinyin - The Chinese PinYin engine for IBus
+#
+# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+
+icons_DATA = \
+ ibus-pinyin.svg \
+ chinese.svg \
+ english.svg \
+ full.svg \
+ full-punct.svg \
+ half.svg \
+ half-punct.svg \
+ $(NULL)
+
+iconsdir = $(pkgdatadir)/icons
+
+EXTRA_DIST = \
+ $(icons_DATA) \
+ $(NULL)
+
diff --git a/icons/chinese.svg b/data/icons/chinese.svg
index aa7b61d..aa7b61d 100644
--- a/icons/chinese.svg
+++ b/data/icons/chinese.svg
diff --git a/icons/english.svg b/data/icons/english.svg
index 4369a7f..4369a7f 100644
--- a/icons/english.svg
+++ b/data/icons/english.svg
diff --git a/icons/full-punct.svg b/data/icons/full-punct.svg
index 2a91f19..2a91f19 100644
--- a/icons/full-punct.svg
+++ b/data/icons/full-punct.svg
diff --git a/icons/full-letter.svg b/data/icons/full.svg
index 9653d63..9653d63 100644
--- a/icons/full-letter.svg
+++ b/data/icons/full.svg
diff --git a/icons/half-punct.svg b/data/icons/half-punct.svg
index 41fae25..41fae25 100644
--- a/icons/half-punct.svg
+++ b/data/icons/half-punct.svg
diff --git a/icons/half-letter.svg b/data/icons/half.svg
index 362793e..362793e 100644
--- a/icons/half-letter.svg
+++ b/data/icons/half.svg
diff --git a/icons/ibus-pinyin.svg b/data/icons/ibus-pinyin.svg
index 1582c0d..1582c0d 100644
--- a/icons/ibus-pinyin.svg
+++ b/data/icons/ibus-pinyin.svg
diff --git a/data/scripts/create_db.py b/data/scripts/create_db.py
new file mode 100644
index 0000000..e4826ae
--- /dev/null
+++ b/data/scripts/create_db.py
@@ -0,0 +1,94 @@
+import sqlite3
+from pydict import *
+from id import *
+import sys
+
+con1 = sqlite3.connect("py.db")
+con2 = sqlite3.connect("py-new.db")
+con2.execute ("PRAGMA synchronous = NORMAL;")
+con2.execute ("PRAGMA temp_store = MEMORY;")
+con2.execute ("PRAGMA default_cache_size = 5000;")
+
+sql = "CREATE TABLE py_phrase_%d (phrase TEXT, freq INTEGER, %s)"
+
+for i in range(0, 16):
+ column= []
+ for j in range(0, i + 1):
+ column.append ("s%d INTEGER" % j)
+ column.append ("y%d INTEGER" % j)
+ column = ",".join(column)
+ con2.execute(sql % (i, column))
+con2.commit()
+
+def get_sheng_yun(pinyin):
+ if pinyin == None:
+ return None, None
+ if pinyin == "ng":
+ return "", "en"
+ for i in xrange(2, 0, -1):
+ t = pinyin[:i]
+ if t in SHENGMU_DICT:
+ return t, pinyin[len(t):]
+ return "", pinyin
+
+def encode_pinyin(pinyin):
+ if pinyin == None or pinyin == "":
+ return 0
+ return pinyin_id[pinyin]
+ e = 0
+ for c in pinyin:
+ e = (e << 5) + (ord(c) - ord('a') + 1)
+ return e
+
+insert_sql = "INSERT INTO py_phrase_%d VALUES (%s);"
+con2.commit()
+new_freq = 0
+freq = 0
+
+print "INSERTING"
+for r in con1.execute("SELECT * FROM py_phrase ORDER BY freq"):
+ ylen = r[0]
+ phrase = r[10]
+ if r[11] > freq:
+ freq = r[11]
+ new_freq += 1
+
+ if ylen <= 4:
+ pys = map(lambda id: ID_PINYIN_DICT[id], r[1: 1 + ylen])
+ else:
+ pys = map(lambda id: ID_PINYIN_DICT[id], r[1: 5]) + r[5].encode("utf8").split("'")
+
+ i = ylen - 1
+ if i >= 15:
+ i = 15
+
+ pys = pys[0:16]
+
+ sheng_yun = []
+ for s, y in map(get_sheng_yun, pys):
+ sheng_yun.append(s)
+ sheng_yun.append(y)
+
+
+ column = [phrase, new_freq] + map(encode_pinyin, sheng_yun)
+
+ sql = insert_sql % (i, ",".join(["?"] * len(column)))
+ con2.execute (sql, column)
+
+print "Remove duplicate"
+for i in xrange(0, 16):
+ sql = "DELETE FROM py_phrase_%d WHERE rowid IN (SELECT rowid FROM (SELECT count() as count, rowid FROM py_phrase_%d GROUP by %s,phrase) WHERE count > 1)" % (i, i, ",".join(map(lambda i: "s%d,y%d"%(i,i), range(0, i + 1))))
+ con2.execute(sql)
+con2.commit()
+print "CACUUM"
+con2.execute("VACUUM;")
+con2.commit()
+
+# con2.execute("create index index_0_0 on py_phrase_0(s0, y0)")
+#
+# for i in xrange(1, 16):
+# con2.execute("create index index_%d_0 on py_phrase_%d(s0, y0, s1, y1)" % (i, i))
+# con2.execute("create index index_%d_1 on py_phrase_%d(s0, s1, y1)" % (i, i))
+#
+# con2.execute("vacuum")
+# con2.commit()
diff --git a/data/scripts/create_index.py b/data/scripts/create_index.py
new file mode 100644
index 0000000..823e616
--- /dev/null
+++ b/data/scripts/create_index.py
@@ -0,0 +1,21 @@
+import sqlite3
+
+con2 = sqlite3.connect("py-new.db")
+con2.execute ("PRAGMA synchronous = NORMAL;")
+con2.execute ("PRAGMA temp_store = MEMORY;")
+
+
+con2.execute("CREATE INDEX index_0_0 ON py_phrase_0(s0, y0)")
+print "py_phrase_%d done" % 0
+
+con2.execute("CREATE INDEX index_1_0 ON py_phrase_1(s0, y0, s1, y1)")
+con2.execute("CREATE INDEX index_1_1 ON py_phrase_1(s0, s1, y1)")
+print "py_phrase_%d done" % 1
+
+for i in xrange(2, 16):
+ con2.execute("CREATE INDEX index_%d_0 ON py_phrase_%d(s0, y0, s1, y1, s2, y2)" % (i, i))
+ con2.execute("CREATE INDEX index_%d_1 ON py_phrase_%d(s0, s1, s2, y2)" % (i, i))
+ print "py_phrase_%d done" % i
+
+# con2.execute("vacuum")
+con2.commit()
diff --git a/data/scripts/create_unique_index.py b/data/scripts/create_unique_index.py
new file mode 100644
index 0000000..e22d986
--- /dev/null
+++ b/data/scripts/create_unique_index.py
@@ -0,0 +1,27 @@
+import sqlite3
+
+con2 = sqlite3.connect("py-new.db")
+con2.execute ("PRAGMA synchronous = NORMAL;")
+con2.execute ("PRAGMA temp_store = MEMORY;")
+
+
+con2.execute("CREATE UNIQUE INDEX IF NOT EXISTS index_0_0 ON py_phrase_0(s0, y0, phrase)")
+print "py_phrase_%d done" % 0
+
+con2.execute("CREATE UNIQUE INDEX IF NOT EXISTS index_1_0 ON py_phrase_1(s0, y0, s1, y1, phrase)")
+con2.execute("CREATE INDEX IF NOT EXISTS index_1_1 ON py_phrase_1(s0, s1, y1)")
+print "py_phrase_%d done" % 1
+
+for i in xrange(2, 16):
+ sql = "CREATE UNIQUE INDEX IF NOT EXISTS index_%d_0 ON py_phrase_%d (" % (i, i)
+ sql = sql + "s0,y0"
+ for j in xrange(1, i + 1):
+ sql = sql + ",s%d,y%d" % (j, j)
+ sql = sql + ", phrase)"
+ print sql
+ con2.execute(sql)
+ con2.execute("CREATE INDEX IF NOT EXISTS index_%d_1 ON py_phrase_%d(s0, s1, s2, y2)" % (i, i))
+ print "py_phrase_%d done" % i
+
+# con2.execute("vacuum")
+con2.commit()
diff --git a/data/scripts/double.py b/data/scripts/double.py
new file mode 100644
index 0000000..1ee8359
--- /dev/null
+++ b/data/scripts/double.py
@@ -0,0 +1,38 @@
+import pydict
+
+for name, (sheng, yun) in pydict.SHUANGPIN_SCHEMAS.items():
+ print "static const gint double_pinyin_%s_sheng[] = {" % name.lower()
+ for c in "abcdefghijklmnopqrstuvwxyz;":
+ s = sheng.get(c, "VOID")
+ if s == "'":
+ s = "ZERO"
+ else:
+ s = s.upper()
+ print " PINYIN_ID_%s // %s" % ((s + ",").ljust(5), c.upper())
+ print "};"
+
+ print "static const gint double_pinyin_%s_yun[][2] = {" % name.lower()
+ for c in "abcdefghijklmnopqrstuvwxyz;":
+ s = yun.get(c, ("VOID", "VOID"))
+ if len(s) == 1:
+ s1 = s[0]
+ s2 = "VOID"
+ else:
+ s1, s2 = s
+ if s1 == "'":
+ s1 = "ZERO"
+ if s2 == "'":
+ s2 = "ZERO"
+ s1 = s1.upper()
+ s2 = s2.upper()
+ print " { PINYIN_ID_%s PINYIN_ID_%s }, // %s" % ((s1 + ",").ljust(5), s2.ljust(4), c.upper())
+ print "};"
+
+print '''
+static const struct {
+ const gint (&sheng)[27];
+ const gint (&yun)[27][2];
+} double_pinyin_map [] = {'''
+for name, (sheng, yun) in pydict.SHUANGPIN_SCHEMAS.items():
+ print " { double_pinyin_%s_sheng, double_pinyin_%s_yun}," % (name.lower(), name.lower())
+print "};"
diff --git a/data/scripts/id.py b/data/scripts/id.py
new file mode 100644
index 0000000..44bd80c
--- /dev/null
+++ b/data/scripts/id.py
@@ -0,0 +1 @@
+pinyin_id = {'ch': 3, 'zh': 23, 'ai': 25, 'uan': 50, 'iu': 43, 'ong': 45, 'ao': 28, 'an': 26, 'uai': 49, 'ang': 27, 'iong': 42, 'in': 40, 'ia': 35, 'ei': 30, 'ing': 41, 'ie': 39, 'er': 33, 'iao': 38, 'ian': 36, 'eng': 32, 'iang': 37, 'uo': 55, 'r': 15, 'en': 31, 'ui': 53, 'un': 54, 'ue': 52, 'uang': 51, 'a': 24, 'c': 2, 'b': 1, 'e': 29, 'd': 4, 'g': 6, 'f': 5, 'i': 34, 'h': 7, 'k': 9, 'j': 8, 'm': 11, 'l': 10, 'o': 44, 'n': 12, 'q': 14, 'p': 13, 's': 16, 'sh': 17, 'u': 47, 't': 18, 'w': 19, 'v': 56, 'y': 21, 'x': 20, 'ou': 46, 'z': 22, 'ua': 48}
diff --git a/engine/pydict.py b/data/scripts/pydict.py
index 4646477..4646477 100644
--- a/engine/pydict.py
+++ b/data/scripts/pydict.py
diff --git a/engine/pyutil.py b/data/scripts/pyutil.py
index 1872659..1872659 100644
--- a/engine/pyutil.py
+++ b/data/scripts/pyutil.py
diff --git a/debian/README.Debian b/debian/README.Debian
deleted file mode 100644
index e9e6ec8..0000000
--- a/debian/README.Debian
+++ /dev/null
@@ -1,6 +0,0 @@
-ibus-pinyin for Debian
-----------------------
-
-<possible notes regarding this package - if none, delete this file>
-
- -- oneleaf <oneleaf@gmail.com> Thu, 11 Sep 2008 10:29:30 +0800
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 2175cd9..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,6 +0,0 @@
-ibus-pinyin (0.1.1.20080901-1) unstable; urgency=low
-
- * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
-
- -- oneleaf <oneleaf@gmail.com> Thu, 11 Sep 2008 10:29:30 +0800
-
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index 7ed6ff8..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-5
diff --git a/debian/control b/debian/control
deleted file mode 100644
index 161986c..0000000
--- a/debian/control
+++ /dev/null
@@ -1,12 +0,0 @@
-Source: ibus-pinyin
-Section: unknown
-Priority: extra
-Maintainer: oneleaf <oneleaf@gmail.com>
-Build-Depends: debhelper (>= 5), autotools-dev
-Standards-Version: 3.7.2
-
-Package: ibus-pinyin
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, ibus
-Description: ibus-pinyin
- It is a PinYin engine for IBus.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index 26049cd..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,22 +0,0 @@
-This package was debianized by oneleaf <oneleaf@gmail.com> on
-Thu, 11 Sep 2008 09:58:03 +0800.
-
-It was downloaded from <http://code.google.com/p/ibus/>
-
-Upstream Author(s):
-
- Shawn.P.Huang <Shawn.P.Huang@gmail.com>
-
-Copyright:
-
- <Copyright (C) Shawn.P.Huang>
-
-License:
-
- GNU Lesser General Public License
-
-The Debian packaging is (C) 2008, oneleaf <oneleaf@gmail.com> and
-is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
-
-# Please also look if there are files or directories which have a
-# different copyright/license attached and list them here.
diff --git a/debian/cron.d.ex b/debian/cron.d.ex
deleted file mode 100644
index 02b68ea..0000000
--- a/debian/cron.d.ex
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# Regular cron jobs for the ibus-pinyin package
-#
-0 4 * * * root ibus-pinyin_maintenance
diff --git a/debian/dirs b/debian/dirs
deleted file mode 100644
index ca882bb..0000000
--- a/debian/dirs
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/bin
-usr/sbin
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index 50bd824..0000000
--- a/debian/docs
+++ /dev/null
@@ -1,2 +0,0 @@
-NEWS
-README
diff --git a/debian/emacsen-install.ex b/debian/emacsen-install.ex
deleted file mode 100644
index 09c12aa..0000000
--- a/debian/emacsen-install.ex
+++ /dev/null
@@ -1,45 +0,0 @@
-#! /bin/sh -e
-# /usr/lib/emacsen-common/packages/install/ibus-pinyin
-
-# Written by Jim Van Zandt <jrv@debian.org>, borrowing heavily
-# from the install scripts for gettext by Santiago Vila
-# <sanvila@ctv.es> and octave by Dirk Eddelbuettel <edd@debian.org>.
-
-FLAVOR=$1
-PACKAGE=ibus-pinyin
-
-if [ ${FLAVOR} = emacs ]; then exit 0; fi
-
-echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR}
-
-#FLAVORTEST=`echo $FLAVOR | cut -c-6`
-#if [ ${FLAVORTEST} = xemacs ] ; then
-# SITEFLAG="-no-site-file"
-#else
-# SITEFLAG="--no-site-file"
-#fi
-FLAGS="${SITEFLAG} -q -batch -l path.el -f batch-byte-compile"
-
-ELDIR=/usr/share/emacs/site-lisp/${PACKAGE}
-ELCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE}
-
-# Install-info-altdir does not actually exist.
-# Maybe somebody will write it.
-if test -x /usr/sbin/install-info-altdir; then
- echo install/${PACKAGE}: install Info links for ${FLAVOR}
- install-info-altdir --quiet --section "" "" --dirname=${FLAVOR} /usr/share/info/${PACKAGE}.info.gz
-fi
-
-install -m 755 -d ${ELCDIR}
-cd ${ELDIR}
-FILES=`echo *.el`
-cp ${FILES} ${ELCDIR}
-cd ${ELCDIR}
-
-cat << EOF > path.el
-(setq load-path (cons "." load-path) byte-compile-warnings nil)
-EOF
-${FLAVOR} ${FLAGS} ${FILES}
-rm -f *.el path.el
-
-exit 0
diff --git a/debian/emacsen-remove.ex b/debian/emacsen-remove.ex
deleted file mode 100644
index 853219d..0000000
--- a/debian/emacsen-remove.ex
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh -e
-# /usr/lib/emacsen-common/packages/remove/ibus-pinyin
-
-FLAVOR=$1
-PACKAGE=ibus-pinyin
-
-if [ ${FLAVOR} != emacs ]; then
- if test -x /usr/sbin/install-info-altdir; then
- echo remove/${PACKAGE}: removing Info links for ${FLAVOR}
- install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/share/info/ibus-pinyin.info.gz
- fi
-
- echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR}
- rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE}
-fi
diff --git a/debian/emacsen-startup.ex b/debian/emacsen-startup.ex
deleted file mode 100644
index 0691f53..0000000
--- a/debian/emacsen-startup.ex
+++ /dev/null
@@ -1,25 +0,0 @@
-;; -*-emacs-lisp-*-
-;;
-;; Emacs startup file, e.g. /etc/emacs/site-start.d/50ibus-pinyin.el
-;; for the Debian ibus-pinyin package
-;;
-;; Originally contributed by Nils Naumann <naumann@unileoben.ac.at>
-;; Modified by Dirk Eddelbuettel <edd@debian.org>
-;; Adapted for dh-make by Jim Van Zandt <jrv@debian.org>
-
-;; The ibus-pinyin package follows the Debian/GNU Linux 'emacsen' policy and
-;; byte-compiles its elisp files for each 'emacs flavor' (emacs19,
-;; xemacs19, emacs20, xemacs20...). The compiled code is then
-;; installed in a subdirectory of the respective site-lisp directory.
-;; We have to add this to the load-path:
-(let ((package-dir (concat "/usr/share/"
- (symbol-name flavor)
- "/site-lisp/ibus-pinyin")))
-;; If package-dir does not exist, the ibus-pinyin package must have
-;; removed but not purged, and we should skip the setup.
- (when (file-directory-p package-dir)
- (setq load-path (cons package-dir load-path))
- (autoload 'ibus-pinyin-mode "ibus-pinyin-mode"
- "Major mode for editing ibus-pinyin files." t)
- (add-to-list 'auto-mode-alist '("\\.ibus-pinyin$" . ibus-pinyin-mode))))
-
diff --git a/debian/ibus-pinyin-default.ex b/debian/ibus-pinyin-default.ex
deleted file mode 100644
index 9ca3204..0000000
--- a/debian/ibus-pinyin-default.ex
+++ /dev/null
@@ -1,10 +0,0 @@
-# Defaults for ibus-pinyin initscript
-# sourced by /etc/init.d/ibus-pinyin
-# installed at /etc/default/ibus-pinyin by the maintainer scripts
-
-#
-# This is a POSIX shell fragment
-#
-
-# Additional options that are passed to the Daemon.
-DAEMON_OPTS=""
diff --git a/debian/ibus-pinyin.doc-base.EX b/debian/ibus-pinyin.doc-base.EX
deleted file mode 100644
index 14ad664..0000000
--- a/debian/ibus-pinyin.doc-base.EX
+++ /dev/null
@@ -1,22 +0,0 @@
-Document: ibus-pinyin
-Title: Debian ibus-pinyin Manual
-Author: <insert document author here>
-Abstract: This manual describes what ibus-pinyin is
- and how it can be used to
- manage online manuals on Debian systems.
-Section: unknown
-
-Format: debiandoc-sgml
-Files: /usr/share/doc/ibus-pinyin/ibus-pinyin.sgml.gz
-
-Format: postscript
-Files: /usr/share/doc/ibus-pinyin/ibus-pinyin.ps.gz
-
-Format: text
-Files: /usr/share/doc/ibus-pinyin/ibus-pinyin.text.gz
-
-Format: HTML
-Index: /usr/share/doc/ibus-pinyin/html/index.html
-Files: /usr/share/doc/ibus-pinyin/html/*.html
-
-
diff --git a/debian/init.d.ex b/debian/init.d.ex
deleted file mode 100644
index 0b800d9..0000000
--- a/debian/init.d.ex
+++ /dev/null
@@ -1,157 +0,0 @@
-#! /bin/sh
-#
-# skeleton example file to build /etc/init.d/ scripts.
-# This file should be used to construct scripts for /etc/init.d.
-#
-# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
-# Modified for Debian
-# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
-# Further changes by Javier Fernandez-Sanguino <jfs@debian.org>
-#
-# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl
-#
-
-PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-DAEMON=/usr/sbin/ibus-pinyin
-NAME=ibus-pinyin
-DESC=ibus-pinyin
-
-test -x $DAEMON || exit 0
-
-LOGDIR=/var/log/ibus-pinyin
-PIDFILE=/var/run/$NAME.pid
-DODTIME=1 # Time to wait for the server to die, in seconds
- # If this value is set too low you might not
- # let some servers to die gracefully and
- # 'restart' will not work
-
-# Include ibus-pinyin defaults if available
-if [ -f /etc/default/ibus-pinyin ] ; then
- . /etc/default/ibus-pinyin
-fi
-
-set -e
-
-running_pid()
-{
- # Check if a given process pid's cmdline matches a given name
- pid=$1
- name=$2
- [ -z "$pid" ] && return 1
- [ ! -d /proc/$pid ] && return 1
- cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
- # Is this the expected child?
- [ "$cmd" != "$name" ] && return 1
- return 0
-}
-
-running()
-{
-# Check if the process is running looking at /proc
-# (works for all users)
-
- # No pidfile, probably no daemon present
- [ ! -f "$PIDFILE" ] && return 1
- # Obtain the pid and check it against the binary name
- pid=`cat $PIDFILE`
- running_pid $pid $NAME || return 1
- return 0
-}
-
-force_stop() {
-# Forcefully kill the process
- [ ! -f "$PIDFILE" ] && return
- if running ; then
- kill -15 $pid
- # Is it really dead?
- [ -n "$DODTIME" ] && sleep "$DODTIME"s
- if running ; then
- kill -9 $pid
- [ -n "$DODTIME" ] && sleep "$DODTIME"s
- if running ; then
- echo "Cannot kill $LABEL (pid=$pid)!"
- exit 1
- fi
- fi
- fi
- rm -f $PIDFILE
- return 0
-}
-
-case "$1" in
- start)
- echo -n "Starting $DESC: "
- start-stop-daemon --start --quiet --pidfile $PIDFILE \
- --exec $DAEMON -- $DAEMON_OPTS
- if running then
- echo "$NAME."
- else
- echo " ERROR."
- fi
- ;;
- stop)
- echo -n "Stopping $DESC: "
- start-stop-daemon --stop --quiet --pidfile $PIDFILE \
- --exec $DAEMON
- echo "$NAME."
- ;;
- force-stop)
- echo -n "Forcefully stopping $DESC: "
- force_stop
- if ! running then
- echo "$NAME."
- else
- echo " ERROR."
- fi
- ;;
- #reload)
- #
- # If the daemon can reload its config files on the fly
- # for example by sending it SIGHUP, do it here.
- #
- # If the daemon responds to changes in its config file
- # directly anyway, make this a do-nothing entry.
- #
- # echo "Reloading $DESC configuration files."
- # start-stop-daemon --stop --signal 1 --quiet --pidfile \
- # /var/run/$NAME.pid --exec $DAEMON
- #;;
- force-reload)
- #
- # If the "reload" option is implemented, move the "force-reload"
- # option to the "reload" entry above. If not, "force-reload" is
- # just the same as "restart" except that it does nothing if the
- # daemon isn't already running.
- # check wether $DAEMON is running. If so, restart
- start-stop-daemon --stop --test --quiet --pidfile \
- /var/run/$NAME.pid --exec $DAEMON \
- && $0 restart \
- || exit 0
- ;;
- restart)
- echo -n "Restarting $DESC: "
- start-stop-daemon --stop --quiet --pidfile \
- /var/run/$NAME.pid --exec $DAEMON
- [ -n "$DODTIME" ] && sleep $DODTIME
- start-stop-daemon --start --quiet --pidfile \
- /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
- echo "$NAME."
- ;;
- status)
- echo -n "$LABEL is "
- if running ; then
- echo "running"
- else
- echo " not running."
- exit 1
- fi
- ;;
- *)
- N=/etc/init.d/$NAME
- # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
- echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/debian/init.d.lsb.ex b/debian/init.d.lsb.ex
deleted file mode 100644
index e73dc7f..0000000
--- a/debian/init.d.lsb.ex
+++ /dev/null
@@ -1,281 +0,0 @@
-#!/bin/sh
-#
-# Example init.d script with LSB support.
-#
-# Please read this init.d carefully and modify the sections to
-# adjust it to the program you want to run.
-#
-# Copyright (c) 2007 Javier Fernandez-Sanguino <jfs@debian.org>
-#
-# This is free software; you may 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 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 with
-# the Debian operating system, in /usr/share/common-licenses/GPL; if
-# not, write to the Free Software Foundation, Inc., 59 Temple Place,
-# Suite 330, Boston, MA 02111-1307 USA
-#
-### BEGIN INIT INFO
-# Provides: ibus-pinyin
-# Required-Start: $network $local_fs
-# Required-Stop:
-# Should-Start: $named
-# Should-Stop:
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: <Enter a short description of the sortware>
-# Description: <Enter a long description of the software>
-# <...>
-# <...>
-### END INIT INFO
-
-PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-
-DAEMON=/usr/sbin/ibus-pinyin # Introduce the server's location here
-NAME=#PACKAGE # Introduce the short server's name here
-DESC=#PACKAGE # Introduce a short description here
-LOGDIR=/var/log/ibus-pinyin # Log directory to use
-
-PIDFILE=/var/run/$NAME.pid
-
-test -x $DAEMON || exit 0
-test -x $DAEMON_WRAPPER || exit 0
-
-. /lib/lsb/init-functions
-
-# Default options, these can be overriden by the information
-# at /etc/default/$NAME
-DAEMON_OPTS="" # Additional options given to the server
-
-DODTIME=10 # Time to wait for the server to die, in seconds
- # If this value is set too low you might not
- # let some servers to die gracefully and
- # 'restart' will not work
-
-LOGFILE=$LOGDIR/$NAME.log # Server logfile
-#DAEMONUSER=ibus-pinyin # Users to run the daemons as. If this value
- # is set start-stop-daemon will chuid the server
-
-# Include defaults if available
-if [ -f /etc/default/$NAME ] ; then
- . /etc/default/$NAME
-fi
-
-# Use this if you want the user to explicitly set 'RUN' in
-# /etc/default/
-#if [ "x$RUN" != "xyes" ] ; then
-# log_failure_msg "$NAME disabled, please adjust the configuration to your needs "
-# log_failure_msg "and then set RUN to 'yes' in /etc/default/$NAME to enable it."
-# exit 1
-#fi
-
-# Check that the user exists (if we set a user)
-# Does the user exist?
-if [ -n "$DAEMONUSER" ] ; then
- if getent passwd | grep -q "^$DAEMONUSER:"; then
- # Obtain the uid and gid
- DAEMONUID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $3}'`
- DAEMONGID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $4}'`
- else
- log_failure_msg "The user $DAEMONUSER, required to run $NAME does not exist."
- exit 1
- fi
-fi
-
-
-set -e
-
-running_pid() {
-# Check if a given process pid's cmdline matches a given name
- pid=$1
- name=$2
- [ -z "$pid" ] && return 1
- [ ! -d /proc/$pid ] && return 1
- cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
- # Is this the expected server
- [ "$cmd" != "$name" ] && return 1
- return 0
-}
-
-running() {
-# Check if the process is running looking at /proc
-# (works for all users)
-
- # No pidfile, probably no daemon present
- [ ! -f "$PIDFILE" ] && return 1
- pid=`cat $PIDFILE`
- running_pid $pid $DAEMON_WRAPPER || return 1
- return 0
-}
-
-start_server() {
-# Start the process using the wrapper
- if [ -z "$DAEMONUSER" ] ; then
- start-stop-daemon --start --quiet --pidfile $PIDFILE \
- --exec $DAEMON -- $DAEMON_OPTS
- errcode=$?
- else
-# if we are using a daemonuser then change the user id
- start-stop-daemon --start --quiet --pidfile $PIDFILE \
- --chuid $DAEMONUSER \
- --exec $DAEMON -- $DAEMON_OPTS
- errcode=$?
- fi
- return $errcode
-}
-
-stop_server() {
-# Stop the process using the wrapper
- if [ -z "$DAEMONUSER" ] ; then
- start-stop-daemon --stop --quiet --pidfile $PIDFILE \
- --exec $DAEMON
- errcode=$
- else
-# if we are using a daemonuser then look for process that match
- start-stop-daemon --stop --quiet --pidfile $PIDFILE \
- --user $DAEMONUSER \
- --exec $DAEMON
- errcode=$
- fi
-
- return $errcode
-}
-
-reload_server() {
- [ ! -f "$PIDFILE" ] && return 1
- pid=`cat $PIDFILE` # This is the daemon's pid
- # Send a SIGHUP
- kill -1 $pid
- return $?
-}
-
-force_stop() {
-# Force the process to die killing it manually
- [ ! -e "$PIDFILE" ] && return
- if running ; then
- kill -15 $pid
- # Is it really dead?
- sleep "$DIETIME"s
- if running ; then
- kill -9 $pid
- sleep "$DIETIME"s
- if running ; then
- echo "Cannot kill $NAME (pid=$pid)!"
- exit 1
- fi
- fi
- fi
- rm -f $PIDFILE
-}
-
-
-case "$1" in
- start)
- log_daemon_msg "Starting $DESC " "$NAME"
- # Check if it's running first
- if running ; then
- log_progress_msg "apparently already running"
- log_end_msg 0
- exit 0
- fi
- if start_server && running ; then
- # It's ok, the server started and is running
- log_end_msg 0
- else
- # Either we could not start it or it is not running
- # after we did
- # NOTE: Some servers might die some time after they start,
- # this code does not try to detect this and might give
- # a false positive (use 'status' for that)
- log_end_msg 1
- fi
- ;;
- stop)
- log_daemon_msg "Stopping $DESC" "$NAME"
- if running ; then
- # Only stop the server if we see it running
- stop_server
- log_end_msg $?
- else
- # If it's not running don't do anything
- log_progress_msg "apparently not running"
- log_end_msg 0
- exit 0
- fi
- ;;
- force-stop)
- # First try to stop gracefully the program
- $0 stop
- if running; then
- # If it's still running try to kill it more forcefully
- log_daemon_msg "Stopping (force) $DESC" "$NAME"
- force_stop
- log_end_msg $?
- fi
- ;;
- restart|force-reload)
- log_daemon_msg "Restarting $DESC" "$NAME"
- stop_server
- # Wait some sensible amount, some server need this
- [ -n "$DIETIME" ] && sleep $DIETIME
- start_server
- running
- log_end_msg $?
- ;;
- status)
-
- log_daemon_msg "Checking status of $DESC" "$NAME"
- if running ; then
- log_progress_msg "running"
- log_end_msg 0
- else
- log_progress_msg "apparently not running"
- log_end_msg 1
- exit 1
- fi
- ;;
- # Use this if the daemon cannot reload
- reload)
- log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon"
- log_warning_msg "cannot re-read the config file (use restart)."
- ;;
- # And this if it cann
- #reload)
- #
- # If the daemon can reload its config files on the fly
- # for example by sending it SIGHUP, do it here.
- #
- # If the daemon responds to changes in its config file
- # directly anyway, make this a do-nothing entry.
- #
- # log_daemon_msg "Reloading $DESC configuration files" "$NAME"
- # if running ; then
- # reload_server
- # if ! running ; then
- # Process died after we tried to reload
- # log_progress_msg "died on reload"
- # log_end_msg 1
- # exit 1
- # fi
- # else
- # log_progress_msg "server is not running"
- # log_end_msg 1
- # exit 1
- # fi
- #;;
-
- *)
- N=/etc/init.d/$NAME
- echo "Usage: $N {start|stop|force-stop|restart|force-reload|status}" >&2
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/debian/manpage.1.ex b/debian/manpage.1.ex
deleted file mode 100644
index 15dae44..0000000
--- a/debian/manpage.1.ex
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" Hey, EMACS: -*- nroff -*-
-.\" First parameter, NAME, should be all caps
-.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
-.\" other parameters are allowed: see man(7), man(1)
-.TH IBUS-PINYIN SECTION "九月 11, 2008"
-.\" Please adjust this date whenever revising the manpage.
-.\"
-.\" Some roff macros, for reference:
-.\" .nh disable hyphenation
-.\" .hy enable hyphenation
-.\" .ad l left justify
-.\" .ad b justify to both left and right margins
-.\" .nf disable filling
-.\" .fi enable filling
-.\" .br insert line break
-.\" .sp <n> insert n+1 empty lines
-.\" for manpage-specific macros, see man(7)
-.SH NAME
-ibus-pinyin \- program to do something
-.SH SYNOPSIS
-.B ibus-pinyin
-.RI [ options ] " files" ...
-.br
-.B bar
-.RI [ options ] " files" ...
-.SH DESCRIPTION
-This manual page documents briefly the
-.B ibus-pinyin
-and
-.B bar
-commands.
-.PP
-.\" TeX users may be more comfortable with the \fB<whatever>\fP and
-.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
-.\" respectively.
-\fBibus-pinyin\fP is a program that...
-.SH OPTIONS
-These programs follow the usual GNU command line syntax, with long
-options starting with two dashes (`-').
-A summary of options is included below.
-For a complete description, see the Info files.
-.TP
-.B \-h, \-\-help
-Show summary of options.
-.TP
-.B \-v, \-\-version
-Show version of program.
-.SH SEE ALSO
-.BR bar (1),
-.BR baz (1).
-.br
-The programs are documented fully by
-.IR "The Rise and Fall of a Fooish Bar" ,
-available via the Info system.
-.SH AUTHOR
-ibus-pinyin was written by <upstream author>.
-.PP
-This manual page was written by oneleaf <oneleaf@gmail.com>,
-for the Debian project (but may be used by others).
diff --git a/debian/manpage.sgml.ex b/debian/manpage.sgml.ex
deleted file mode 100644
index 5adbcb0..0000000
--- a/debian/manpage.sgml.ex
+++ /dev/null
@@ -1,156 +0,0 @@
-<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
-
-<!-- Process this file with docbook-to-man to generate an nroff manual
- page: `docbook-to-man manpage.sgml > manpage.1'. You may view
- the manual page with: `docbook-to-man manpage.sgml | nroff -man |
- less'. A typical entry in a Makefile or Makefile.am is:
-
-manpage.1: manpage.sgml
- docbook-to-man $< > $@
-
-
- The docbook-to-man binary is found in the docbook-to-man package.
- Please remember that if you create the nroff version in one of the
- debian/rules file targets (such as build), you will need to include
- docbook-to-man in your Build-Depends control field.
-
- -->
-
- <!-- Fill in your name for FIRSTNAME and SURNAME. -->
- <!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>">
- <!ENTITY dhsurname "<surname>SURNAME</surname>">
- <!-- Please adjust the date whenever revising the manpage. -->
- <!ENTITY dhdate "<date>九月 11, 2008</date>">
- <!-- SECTION should be 1-8, maybe w/ subsection other parameters are
- allowed: see man(7), man(1). -->
- <!ENTITY dhsection "<manvolnum>SECTION</manvolnum>">
- <!ENTITY dhemail "<email>oneleaf@gmail.com</email>">
- <!ENTITY dhusername "oneleaf">
- <!ENTITY dhucpackage "<refentrytitle>IBUS-PINYIN</refentrytitle>">
- <!ENTITY dhpackage "ibus-pinyin">
-
- <!ENTITY debian "<productname>Debian</productname>">
- <!ENTITY gnu "<acronym>GNU</acronym>">
- <!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
-]>
-
-<refentry>
- <refentryinfo>
- <address>
- &dhemail;
- </address>
- <author>
- &dhfirstname;
- &dhsurname;
- </author>
- <copyright>
- <year>2003</year>
- <holder>&dhusername;</holder>
- </copyright>
- &dhdate;
- </refentryinfo>
- <refmeta>
- &dhucpackage;
-
- &dhsection;
- </refmeta>
- <refnamediv>
- <refname>&dhpackage;</refname>
-
- <refpurpose>program to do something</refpurpose>
- </refnamediv>
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>&dhpackage;</command>
-
- <arg><option>-e <replaceable>this</replaceable></option></arg>
-
- <arg><option>--example <replaceable>that</replaceable></option></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
- <refsect1>
- <title>DESCRIPTION</title>
-
- <para>This manual page documents briefly the
- <command>&dhpackage;</command> and <command>bar</command>
- commands.</para>
-
- <para>This manual page was written for the &debian; distribution
- because the original program does not have a manual page.
- Instead, it has documentation in the &gnu;
- <application>Info</application> format; see below.</para>
-
- <para><command>&dhpackage;</command> is a program that...</para>
-
- </refsect1>
- <refsect1>
- <title>OPTIONS</title>
-
- <para>These programs follow the usual &gnu; command line syntax,
- with long options starting with two dashes (`-'). A summary of
- options is included below. For a complete description, see the
- <application>Info</application> files.</para>
-
- <variablelist>
- <varlistentry>
- <term><option>-h</option>
- <option>--help</option>
- </term>
- <listitem>
- <para>Show summary of options.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><option>-v</option>
- <option>--version</option>
- </term>
- <listitem>
- <para>Show version of program.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- <title>SEE ALSO</title>
-
- <para>bar (1), baz (1).</para>
-
- <para>The programs are documented fully by <citetitle>The Rise and
- Fall of a Fooish Bar</citetitle> available via the
- <application>Info</application> system.</para>
- </refsect1>
- <refsect1>
- <title>AUTHOR</title>
-
- <para>This manual page was written by &dhusername; &dhemail; for
- the &debian; system (but may be used by others). Permission is
- granted to copy, distribute and/or modify this document under
- the terms of the &gnu; General Public License, Version 2 any
- later version published by the Free Software Foundation.
- </para>
- <para>
- On Debian systems, the complete text of the GNU General Public
- License can be found in /usr/share/common-licenses/GPL.
- </para>
-
- </refsect1>
-</refentry>
-
-<!-- Keep this comment at the end of the file
-Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:2
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-default-dtd-file:nil
-sgml-exposed-tags:nil
-sgml-local-catalogs:nil
-sgml-local-ecat-files:nil
-End:
--->
-
-
diff --git a/debian/manpage.xml.ex b/debian/manpage.xml.ex
deleted file mode 100644
index b99a183..0000000
--- a/debian/manpage.xml.ex
+++ /dev/null
@@ -1,144 +0,0 @@
-<?xml version='1.0' encoding='ISO-8859-1'?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
-
-<!--
-
-Process this file with an XSLT processor: `xsltproc \
--''-nonet /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\
-manpages/docbook.xsl manpage.dbk'. A manual page
-<package>.<section> will be generated. You may view the
-manual page with: nroff -man <package>.<section> | less'. A
-typical entry in a Makefile or Makefile.am is:
-
-DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\
-manpages/docbook.xsl
-XP=xsltproc -''-nonet
-
-manpage.1: manpage.dbk
- $(XP) $(DB2MAN) $<
-
-The xsltproc binary is found in the xsltproc package. The
-XSL files are in docbook-xsl. Please remember that if you
-create the nroff version in one of the debian/rules file
-targets (such as build), you will need to include xsltproc
-and docbook-xsl in your Build-Depends control field.
-
--->
-
- <!-- Fill in your name for FIRSTNAME and SURNAME. -->
- <!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>">
- <!ENTITY dhsurname "<surname>SURNAME</surname>">
- <!-- Please adjust the date whenever revising the manpage. -->
- <!ENTITY dhdate "<date>九月 11, 2008</date>">
- <!-- SECTION should be 1-8, maybe w/ subsection other parameters are
- allowed: see man(7), man(1). -->
- <!ENTITY dhsection "<manvolnum>SECTION</manvolnum>">
- <!ENTITY dhemail "<email>oneleaf@gmail.com</email>">
- <!ENTITY dhusername "oneleaf">
- <!ENTITY dhucpackage "<refentrytitle>IBUS-PINYIN</refentrytitle>">
- <!ENTITY dhpackage "ibus-pinyin">
-
- <!ENTITY debian "<productname>Debian</productname>">
- <!ENTITY gnu "<acronym>GNU</acronym>">
- <!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
-]>
-
-<refentry>
- <refentryinfo>
- <address>
- &dhemail;
- </address>
- <copyright>
- <year>2007</year>
- <holder>&dhusername;</holder>
- </copyright>
- &dhdate;
- </refentryinfo>
- <refmeta>
- &dhucpackage;
-
- &dhsection;
- </refmeta>
- <refnamediv>
- <refname>&dhpackage;</refname>
-
- <refpurpose>program to do something</refpurpose>
- </refnamediv>
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>&dhpackage;</command>
-
- <arg><option>-e <replaceable>this</replaceable></option></arg>
-
- <arg><option>--example <replaceable>that</replaceable></option></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
- <refsect1>
- <title>DESCRIPTION</title>
-
- <para>This manual page documents briefly the
- <command>&dhpackage;</command> and <command>bar</command>
- commands.</para>
-
- <para>This manual page was written for the &debian; distribution
- because the original program does not have a manual page.
- Instead, it has documentation in the &gnu;
- <application>Info</application> format; see below.</para>
-
- <para><command>&dhpackage;</command> is a program that...</para>
-
- </refsect1>
- <refsect1>
- <title>OPTIONS</title>
-
- <para>These programs follow the usual &gnu; command line syntax,
- with long options starting with two dashes (`-'). A summary of
- options is included below. For a complete description, see the
- <application>Info</application> files.</para>
-
- <variablelist>
- <varlistentry>
- <term><option>-h</option>
- <option>--help</option>
- </term>
- <listitem>
- <para>Show summary of options.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><option>-v</option>
- <option>--version</option>
- </term>
- <listitem>
- <para>Show version of program.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- <title>SEE ALSO</title>
-
- <para>bar (1), baz (1).</para>
-
- <para>The programs are documented fully by <citetitle>The Rise and
- Fall of a Fooish Bar</citetitle> available via the
- <application>Info</application> system.</para>
- </refsect1>
- <refsect1>
- <title>AUTHOR</title>
-
- <para>This manual page was written by &dhusername; &dhemail; for
- the &debian; system (but may be used by others). Permission is
- granted to copy, distribute and/or modify this document under
- the terms of the &gnu; General Public License, Version 2 any
- later version published by the Free Software Foundation.
- </para>
- <para>
- On Debian systems, the complete text of the GNU General Public
- License can be found in /usr/share/common-licenses/GPL.
- </para>
-
- </refsect1>
-</refentry>
-
diff --git a/debian/menu.ex b/debian/menu.ex
deleted file mode 100644
index 67524d6..0000000
--- a/debian/menu.ex
+++ /dev/null
@@ -1,2 +0,0 @@
-?package(ibus-pinyin):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\
- title="ibus-pinyin" command="/usr/bin/ibus-pinyin"
diff --git a/debian/postinst.ex b/debian/postinst.ex
deleted file mode 100644
index 6094692..0000000
--- a/debian/postinst.ex
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-# postinst script for ibus-pinyin
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-# * <postinst> `configure' <most-recently-configured-version>
-# * <old-postinst> `abort-upgrade' <new version>
-# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
-# <new-version>
-# * <postinst> `abort-remove'
-# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
-# <failed-install-package> <version> `removing'
-# <conflicting-package> <version>
-# for details, see http://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-case "$1" in
- configure)
- ;;
-
- abort-upgrade|abort-remove|abort-deconfigure)
- ;;
-
- *)
- echo "postinst called with unknown argument \`$1'" >&2
- exit 1
- ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
-
-
diff --git a/debian/postrm.ex b/debian/postrm.ex
deleted file mode 100644
index e56c758..0000000
--- a/debian/postrm.ex
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-# postrm script for ibus-pinyin
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-# * <postrm> `remove'
-# * <postrm> `purge'
-# * <old-postrm> `upgrade' <new-version>
-# * <new-postrm> `failed-upgrade' <old-version>
-# * <new-postrm> `abort-install'
-# * <new-postrm> `abort-install' <old-version>
-# * <new-postrm> `abort-upgrade' <old-version>
-# * <disappearer's-postrm> `disappear' <overwriter>
-# <overwriter-version>
-# for details, see http://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-case "$1" in
- purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
- ;;
-
- *)
- echo "postrm called with unknown argument \`$1'" >&2
- exit 1
- ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
-
-
diff --git a/debian/preinst.ex b/debian/preinst.ex
deleted file mode 100644
index a3dd684..0000000
--- a/debian/preinst.ex
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/sh
-# preinst script for ibus-pinyin
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-# * <new-preinst> `install'
-# * <new-preinst> `install' <old-version>
-# * <new-preinst> `upgrade' <old-version>
-# * <old-preinst> `abort-upgrade' <new-version>
-# for details, see http://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-case "$1" in
- install|upgrade)
- ;;
-
- abort-upgrade)
- ;;
-
- *)
- echo "preinst called with unknown argument \`$1'" >&2
- exit 1
- ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
-
-
diff --git a/debian/prerm.ex b/debian/prerm.ex
deleted file mode 100644
index a237b14..0000000
--- a/debian/prerm.ex
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/sh
-# prerm script for ibus-pinyin
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-# * <prerm> `remove'
-# * <old-prerm> `upgrade' <new-version>
-# * <new-prerm> `failed-upgrade' <old-version>
-# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
-# * <deconfigured's-prerm> `deconfigure' `in-favour'
-# <package-being-installed> <version> `removing'
-# <conflicting-package> <version>
-# for details, see http://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-case "$1" in
- remove|upgrade|deconfigure)
- ;;
-
- failed-upgrade)
- ;;
-
- *)
- echo "prerm called with unknown argument \`$1'" >&2
- exit 1
- ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
-
-
diff --git a/debian/rules b/debian/rules
deleted file mode 100644
index 222c57f..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-
-# These are used for cross-compiling and for saving the configure script
-# from having to guess our platform (since we know it already)
-DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-
-
-config.status: configure
- dh_testdir
- # Add here commands to configure the package.
-ifneq "$(wildcard /usr/share/misc/config.sub)" ""
- cp -f /usr/share/misc/config.sub config.sub
-endif
-ifneq "$(wildcard /usr/share/misc/config.guess)" ""
- cp -f /usr/share/misc/config.guess config.guess
-endif
- ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs"
-
-
-build: build-stamp
-
-build-stamp: config.status
- dh_testdir
-
- # Add here commands to compile the package.
- $(MAKE)
- #docbook-to-man debian/ibus-pinyin.sgml > ibus-pinyin.1
-
- touch $@
-
-clean:
- dh_testdir
- dh_testroot
- rm -f build-stamp
-
- # Add here commands to clean up after the build process.
- -$(MAKE) distclean
- rm -f config.sub config.guess
-
- dh_clean
-
-install: build
- dh_testdir
- dh_testroot
- dh_clean -k
- dh_installdirs
-
- # Add here commands to install the package into debian/ibus-pinyin.
- $(MAKE) DESTDIR=$(CURDIR)/debian/ibus-pinyin install
-
-
-# Build architecture-independent files here.
-binary-indep: build install
-# We have nothing to do by default.
-
-# Build architecture-dependent files here.
-binary-arch: build install
- dh_testdir
- dh_testroot
- dh_installchangelogs ChangeLog
- dh_installdocs
- dh_installexamples
-# dh_install
-# dh_installmenu
-# dh_installdebconf
-# dh_installlogrotate
-# dh_installemacsen
-# dh_installpam
-# dh_installmime
-# dh_python
-# dh_installinit
-# dh_installcron
-# dh_installinfo
- dh_installman
- dh_link
- dh_strip
- dh_compress
- dh_fixperms
-# dh_perl
-# dh_makeshlibs
- dh_installdeb
- dh_shlibdeps
- dh_gencontrol
- dh_md5sums
- dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install
diff --git a/debian/watch.ex b/debian/watch.ex
deleted file mode 100644
index 545b10f..0000000
--- a/debian/watch.ex
+++ /dev/null
@@ -1,22 +0,0 @@
-# Example watch control file for uscan
-# Rename this file to "watch" and then you can run the "uscan" command
-# to check for upstream updates and more.
-# See uscan(1) for format
-
-# Compulsory line, this is a version 3 file
-version=3
-
-# Uncomment to examine a Webpage
-# <Webpage URL> <string match>
-#http://www.example.com/downloads.php ibus-pinyin-(.*)\.tar\.gz
-
-# Uncomment to examine a Webserver directory
-#http://www.example.com/pub/ibus-pinyin-(.*)\.tar\.gz
-
-# Uncommment to examine a FTP server
-#ftp://ftp.example.com/pub/ibus-pinyin-(.*)\.tar\.gz debian uupdate
-
-# Uncomment to find new files on sourceforge, for debscripts >= 2.9
-# http://sf.net/ibus-pinyin/ibus-pinyin-(.*)\.tar\.gz
-
-
diff --git a/engine/Makefile.am b/engine/Makefile.am
deleted file mode 100644
index aaae759..0000000
--- a/engine/Makefile.am
+++ /dev/null
@@ -1,90 +0,0 @@
-# vim:set noet ts=4:
-#
-# ibus-pinyin - The PinYin engine for IBus
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
-
-engine_pinyin_PYTHON = \
- factory.py \
- main.py \
- pinyin.py \
- pydict.py \
- pyparser.py \
- specialphrase.py \
- specialtable.py \
- pysqlitedb.py \
- pyutil.py \
- $(NULL)
-engine_pinyin_DATA = \
- special_phrase \
- special_table \
- py.db \
- $(NULL)
-engine_pinyindir = $(datadir)/ibus-pinyin/engine
-
-libexec_SCRIPTS = ibus-engine-pinyin
-
-engine_DATA = pinyin.xml
-enginedir = $(datadir)/ibus/component
-
-DBVER = 0.1.10.6
-DBTAR = pinyin-database-${DBVER}.tar.bz2
-
-${DBTAR}:
- wget http://ibus.googlecode.com/files/${DBTAR}
-
-py.db: ${DBTAR}
- tar jxvfm ${DBTAR}
-
-
-EXTRA_DIST = \
- ibus-engine-pinyin.in \
- pinyin.xml.in \
- special_phrase \
- special_table \
- $(NULL)
-
-CLEANFILES = \
- pinyin.xml \
- *.pyc \
- py.db \
- $(DBTAR) \
- $(NULL)
-
-pinyin.xml: pinyin.xml.in
- ( \
- libexecdir=${libexecdir}; \
- pkgdatadir=${pkgdatadir}; \
- s=`cat $<`; \
- eval "echo \"$${s}\""; \
- ) > $@
-
-test:
- $(ENV) \
- IBUS_PINYIN_LOCATION=$(abs_top_srcdir) \
- DBUS_DEBUG=true \
- LANG=en_US \
- PYTHONPATH=$(abs_top_srcdir):$(pyexecdir) \
- $(PYTHON) $(srcdir)/main.py
-
-install-data-hook:
- @(if test "${NO_INDEX}" = ""; then \
- cd $(DESTDIR)$(engine_pinyindir); \
- echo "Creating INDEX"; \
- $(PYTHON) -c "import pysqlitedb; db = pysqlitedb.PYSQLiteDB (filename='py.db'); db.create_indexes ();" ;\
- fi)
-
diff --git a/engine/factory.py b/engine/factory.py
deleted file mode 100644
index 6f66d8b..0000000
--- a/engine/factory.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# vim:set et sts=4 sw=4:
-#
-# ibus-tmpl - The Input Bus template project
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
-
-import ibus
-import pinyin
-import os
-
-from gettext import dgettext
-_ = lambda a : dgettext("ibus-pinyin", a)
-N_ = lambda a : a
-
-
-class EngineFactory(ibus.EngineFactoryBase):
- FACTORY_PATH = "/com/redhat/IBus/engines/PinYin/Factory"
- ENGINE_PATH = "/com/redhat/IBus/engines/PinYin/Engine"
- NAME = _("PinYin")
- LANG = "zh_CN"
- ICON = os.getenv("IBUS_PINYIN_LOCATION") + "/icons/ibus-pinyin.svg"
- AUTHORS = "Huang Peng <shawn.p.huang@gmail.com>"
- CREDITS = "GPLv2"
-
- def __init__(self, bus):
- self.__bus = bus
- pinyin.PinYinEngine.CONFIG_RELOADED(bus)
- super(EngineFactory, self).__init__(bus)
-
- self.__id = 0
- self.__config = self.__bus.get_config()
-
- self.__config.connect("reloaded", self.__config_reloaded_cb)
- self.__config.connect("value-changed", self.__config_value_changed_cb)
-
- def create_engine(self, engine_name):
- if engine_name == "pinyin":
- self.__id += 1
- return pinyin.PinYinEngine(self.__bus, "%s/%d" % (self.ENGINE_PATH, self.__id))
-
- return super(EngineFactory, self).create_engine(engine_name)
-
- def __config_reloaded_cb(self, config):
- pinyin.PinYinEngine.CONFIG_RELOADED(self.__bus)
-
- def __config_value_changed_cb(self, config, section, name, value):
- pinyin.PinYinEngine.CONFIG_VALUE_CHANGED(self.__bus, section, name, value)
-
diff --git a/engine/ibus-engine-pinyin.in b/engine/ibus-engine-pinyin.in
deleted file mode 100644
index 9a3c8bb..0000000
--- a/engine/ibus-engine-pinyin.in
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# vim:set noet ts=4:
-#
-# ibus-tmpl - The Input Bus template project
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libexecdir=@libexecdir@
-pyexecdir=@pyexecdir@
-export PYTHONPATH=@pyexecdir@:$PYTHONPATH
-export IBUS_PINYIN_LOCATION=@prefix@/share/ibus-pinyin
-export LIBEXECDIR=$libexecdir
-exec python @prefix@/share/ibus-pinyin/engine/main.py $@
-
diff --git a/engine/main.py b/engine/main.py
deleted file mode 100644
index fd4d88c..0000000
--- a/engine/main.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# vim:set et sts=4 sw=4:
-#
-# ibus-pinyin - The PinYin engine for IBus
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
-
-import os
-import sys
-import getopt
-import ibus
-import gobject
-import factory
-
-class IMApp:
- def __init__(self, exec_by_ibus):
- self.__component = ibus.Component("org.freedesktop.IBus.PinYin",
- "Chinese PinYin Component",
- "0.1.0",
- "GPL",
- "Peng Huang <shawn.p.huang@gmail.com>")
- self.__component.add_engine("pinyin",
- "pinyin",
- "Chinese PinYin",
- "zh_CN",
- "GPL",
- "Peng Huang <shawn.p.huang@gmail.com>",
- "",
- "en")
- self.__mainloop = gobject.MainLoop()
- self.__bus = ibus.Bus()
- self.__bus.connect("destroy", self.__bus_destroy_cb)
- self.__factory = factory.EngineFactory(self.__bus)
- if exec_by_ibus:
- self.__bus.request_name("org.freedesktop.IBus.PinYin", 0)
- else:
- self.__bus.register_component(self.__component)
-
- def run(self):
- self.__mainloop.run()
-
- def __bus_destroy_cb(self, bus):
- self.__mainloop.quit()
-
-
-def launch_engine(exec_by_ibus):
- IMApp(exec_by_ibus).run()
-
-def print_help(out, v = 0):
- print >> out, "-i, --ibus execute by ibus."
- print >> out, "-h, --help show this message."
- print >> out, "-d, --daemonize daemonize ibus"
- sys.exit(v)
-
-def main():
- daemonize = False
- exec_by_ibus = False
- shortopt = "hdi"
- longopt = ["help", "daemonize", "ibus"]
- try:
- opts, args = getopt.getopt(sys.argv[1:], shortopt, longopt)
- except getopt.GetoptError, err:
- print_help(sys.stderr, 1)
-
- for o, a in opts:
- if o in("-h", "--help"):
- print_help(sys.stdout)
- elif o in ("-d", "--daemonize"):
- daemonize = True
- elif o in ("-i", "--ibus"):
- exec_by_ibus = True
- else:
- print >> sys.stderr, "Unknown argument: %s" % o
- print_help(sys.stderr, 1)
-
- if daemonize:
- if os.fork():
- sys.exit()
-
- launch_engine(exec_by_ibus)
-
-if __name__ == "__main__":
- main()
diff --git a/engine/pinyin.py b/engine/pinyin.py
deleted file mode 100644
index 4182336..0000000
--- a/engine/pinyin.py
+++ /dev/null
@@ -1,1317 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim:set et sts=4 sw=4:
-#
-# ibus-pinyin - The PinYin engine for IBus
-#
-# Copyright(c) 2007-2008 Huang Peng <shawn.p.huang@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.
-
-__all__ = (
- "PinYinEngine",
-)
-import ibus
-import gobject
-import os
-import signal
-import os.path as path
-from ibus import keysyms
-from ibus import modifier
-from ibus import ascii
-
-import pyparser
-import pysqlitedb
-from specialtable import SpecialTable
-from specialphrase import SpecialPhrase
-import pyutil
-import pydict
-
-from gettext import dgettext
-_ = lambda a : dgettext("ibus-pinyin", a)
-N_ = lambda a : a
-
-IBUS_PINYIN_LOCATION = os.getenv("IBUS_PINYIN_LOCATION")
-LIBEXECDIR = os.getenv("LIBEXECDIR")
-
-__MAX_LEN__ = 64 # Max length of preedit pinyin
-
-# Define colours
-RGB = lambda r, g, b : (((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff) )
-
-try:
- import enchant
- __EN_DICT__ = enchant.Dict("en_US")
-except:
- class MY_DICT:
- def __init__(self):
- pass
- def suggest(self, word):
- return []
- def check(self, word):
- return True
- __EN_DICT__ = MY_DICT()
-
-
-
-class PinYinEngine(ibus.EngineBase):
-
- # create pinyin database
- __pydb = pysqlitedb.PYSQLiteDB(user_db = "user.db")
-
- # create special table
- __special_phrase = SpecialPhrase()
- __special_table = SpecialTable()
-
- # shuang pin
- __shuangpin = False
- __shuangpin_schema = "MSPY"
-
- # gbk
- __gbk = False
-
- # fuzzy pinyin & auto correct
- __fuzzy_pinyin = False
- __auto_correct = True
- __spell_check = True
-
- # colors
- __phrase_color = RGB(0, 0, 0)
- __user_phrase_color = RGB(0, 0, 0xef)
- __new_phrase_color = RGB(0xef, 0, 0)
- __special_phrase_color = RGB(0, 0xbf, 0)
- __english_phrase_color = RGB(0, 0xbf, 0)
- __error_eng_phrase_color = RGB(0xef, 0, 0)
-
- # lookup table page size
- __page_size = 5
-
- # press [u] or [v] to temp English mode
- __uv_to_temp = True
-
- # press [shift] to select candidates
- __shift_select_candidates = True
-
- # press [-] [=] to page down & up candidates
- __equal_page_down_up = True
-
- # press [,] [.] to page down & up candidates
- __comma_page_down_up = True
-
- # auto commit
- __auto_commit = False
-
- # setup pid
- __setup_pid = 0
-
- # half punctuations
- __half_puncts = u"+-*/=%"
-
-
- def __init__(self, conn, object_path):
- super(PinYinEngine, self).__init__(conn, object_path)
-
- self.__need_update = False
- self.__lookup_table = ibus.LookupTable(PinYinEngine.__page_size)
-
- self.__py_parser = pyparser.PinYinParser()
- self.__user_input = UserInput(self.__py_parser)
-
- # 0 = english input mode
- # 1 = chinese input mode
- self.__mode = 1
- self.__full_width_letter = [False, False]
- self.__full_width_punct = [False, True]
- self.__full_width_punct[1] = True #config.get_value("engine/PinYin/FullWidthPunct", True)
-
- self.__committed_phrases = PhraseList()
- self.__preedit_phrases = PhraseList()
- self.reset()
-
- # init properties
- self.__prop_list = ibus.PropList()
- self.__status_property = ibus.Property(u"status")
- self.__prop_list.append(self.__status_property)
- self.__letter_property = ibus.Property(u"full_letter")
- self.__prop_list.append(self.__letter_property)
- self.__punct_property = ibus.Property(u"full_punct")
- self.__prop_list.append(self.__punct_property)
- # self.__shuangpin_property = ibus.Property("shuangpin")
- # self.__prop_list.append(self.__shuangpin_property)
- # self.__gbk_property = ibus.Property("gbk")
- # self.__prop_list.append(self.__gbk_property)
- self.__setup_property = ibus.Property(u"setup")
- self.__setup_property.tooltip = _(u"Configure PinYin")
- self.__prop_list.append(self.__setup_property)
-
-
- def __refresh_properties(self):
- if self.__mode == 1: # refresh mode
- self.__status_property.icon = path.join(IBUS_PINYIN_LOCATION, "icons", "chinese.svg")
- self.__status_property.label = _(u"CN")
- self.__status_property.tooltip = _(u"Switch to English mode")
- else:
- self.__status_property.icon = path.join(IBUS_PINYIN_LOCATION, "icons", "english.svg")
- self.__status_property.label = _(u"EN")
- self.__status_property.tooltip = _(u"Switch to Chinese mode")
-
- if self.__full_width_letter[self.__mode]:
- self.__letter_property.icon = path.join(IBUS_PINYIN_LOCATION, "icons", "full-letter.svg")
- self.__letter_property.label = u"Aa"
- self.__letter_property.tooltip = _(u"Switch to half letter mode")
- else:
- self.__letter_property.icon = path.join(IBUS_PINYIN_LOCATION, "icons", "half-letter.svg")
- self.__letter_property.label = u"Aa"
- self.__letter_property.tooltip = _(u"Switch to full letter mode")
-
- if self.__full_width_punct[self.__mode]:
- self.__punct_property.icon = path.join(IBUS_PINYIN_LOCATION, "icons", "full-punct.svg")
- self.__punct_property.label = u",。"
- self.__punct_property.tooltip = _(u"Switch to half punctuation mode")
- else:
- self.__punct_property.icon = path.join(IBUS_PINYIN_LOCATION, "icons", "half-punct.svg")
- self.__punct_property.label = u".,"
- self.__punct_property.tooltip = _(u"Switch to full punctuation mode")
-
- # if PinYinEngine.__shuangpin:
- # self.__shuangpin_property.label = _("SHUANG")
- # self.__shuangpin_property.tip = _("Switch to QUAN PIN")
- # else:
- # self.__shuangpin_property.label = _("QUAN")
- # self.__shuangpin_property.tip = _("Switch to SHUANG PIN")
-
- # if PinYinEngine.__gbk:
- # self.__gbk_property.label = _("GBK")
- # self.__gbk_property.tip = _("Switch to GB2312 codeset")
- # else:
- # self.__gbk_property.label = _("GB")
- # self.__gbk_property.tip = _("Switch to GBK codeset")
-
- properties =(
- self.__status_property,
- self.__letter_property,
- self.__punct_property,
- # self.__shuangpin_property,
- # self.__gbk_property,
- )
-
- for prop in properties:
- self.update_property(prop)
-
-
- def __change_mode(self):
- self.__mode =(self.__mode + 1) % 2
- self.__refresh_properties()
-
- def __is_input_english(self):
- return self.__mode == 0
-
- def __update_candidates(self):
- if self.__temp_english_mode:
- if self.__spell_check == False:
- return
- self.__english_candidates = []
- string = "".join(self.__user_input.get_chars())
- if string[0] in u"uv":
- string = string [1:]
- words = string.split()
- if not words:
- return
- word = words[-1]
-
- if len(words) == 1 and word[0:1] in u"uv":
- word = word[1:]
-
- if not word.isalpha():
- return
- if __EN_DICT__.check(word):
- return
- self.__current_word = word
- candidates = __EN_DICT__.suggest(word)
- is_same = lambda x : x[0].isupper() == word[0].isupper()
- self.__english_candidates = filter(is_same, candidates)[:10]
- return
-
- if self.__i_mode:
- chars = self.__user_input.get_chars()[1:]
- self.__candidates = self.__special_phrase.lookup(u"".join(chars))
- self.__candidates += self.__special_table.lookup(u"".join(chars))
- return
-
- self.__preedit_phrases.clean()
-
- if len(self.__user_input.get_pinyin_list()) == 0:
- self.__candidates = []
- self.__special_candidates = []
- return
-
- if len(self.__committed_phrases) == 0:
- self.__special_candidates = self.__special_phrase.lookup(u"".join(self.__user_input.get_chars()))
- else:
- self.__special_candidates = []
-
-
- pinyin_list = self.__user_input.get_pinyin_list()
- pinyin_list = pinyin_list [self.__committed_phrases.length_of_chars():]
-
-
- if pinyin_list:
- self.__candidates = self.__get_candidates(pinyin_list)
- self.__preedit_phrases.append(self.__candidates[0])
-
- count = self.__preedit_phrases.length_of_chars()
-
- while count < len(pinyin_list):
- candidate = self.__get_a_candidate(pinyin_list[count:])
- self.__preedit_phrases.append(candidate)
- count += candidate[pysqlitedb.YLEN]
-
- def __update_ui(self):
- if self.__i_mode:
- preedit_string = u"".join(self.__user_input.get_chars())
- self.update_preedit(preedit_string, None, len(preedit_string), True)
-
- self.hide_auxiliary_text()
-
- self.__lookup_table.clean()
- self.__lookup_table.show_cursor(True)
- if not self.__candidates:
- self.hide_lookup_table()
- else:
- for c in self.__candidates:
- self.__lookup_table.append_candidate(ibus.Text(c))
- self.update_lookup_table(self.__lookup_table, True, True)
- return
-
- if self.__temp_english_mode:
- preedit_string = u"".join(self.__user_input.get_chars())
- if preedit_string [0:1] in(u"v", u"u"):
- preedit_string = " " + preedit_string[1:]
- else:
- preedit_string = " " + preedit_string
-
- words = preedit_string.split()
- if words:
- aux_string = words[-1]
- else:
- aux_string = u""
-
- if preedit_string:
- self.update_preedit(preedit_string, None, len(preedit_string), True)
- if self.__spell_check:
- attrs = ibus.AttrList()
- if aux_string and not __EN_DICT__.check(aux_string):
- attr = ibus.AttributeForeground(PinYinEngine.__error_eng_phrase_color, 0, len(aux_string))
- attrs.append(attr)
- self.update_aux_string(aux_string, attrs, True)
- else:
- self.hide_preedit_text()
- self.hide_auxiliary_text()
-
-
- self.__lookup_table.clean()
- self.__lookup_table.show_cursor(False)
- if not self.__english_candidates:
- self.hide_lookup_table()
- else:
- for c in self.__english_candidates:
- attrs = ibus.AttrList()
- attr = ibus.AttributeForeground(PinYinEngine.__english_phrase_color, 0, len(c))
- attrs.append(attr)
- self.__lookup_table.append_candidate(ibus.Text(c, attrs))
- self.update_lookup_table(self.__lookup_table, True, True)
-
- return
-
- if len(self.__candidates) == 0:
- self.hide_lookup_table()
- else:
- self.__lookup_table.clean()
- candidates = self.__candidates[:]
- if len(self.__preedit_phrases) != 1: # we need display the automatically created new phrase
- attrs = ibus.AttrList ()
- preedit_string = self.__preedit_phrases.get_string()
- attr = ibus.AttributeForeground(PinYinEngine.__new_phrase_color, 0, len(preedit_string))
- attrs.append (attr)
- self.__lookup_table.append_candidate(ibus.Text(preedit_string, attrs))
- else:
- c = candidates[0]
- attrs = ibus.AttrList ()
- if c[pysqlitedb.FREQ] == None: # This phrase was created by user.
- attr = ibus.AttributeForeground(PinYinEngine.__user_phrase_color, 0, c[pysqlitedb.YLEN])
- else:
- attr = ibus.AttributeForeground(PinYinEngine.__phrase_color, 0, c[pysqlitedb.YLEN])
- attrs.append(attr)
- self.__lookup_table.append_candidate(ibus.Text(c[pysqlitedb.PHRASE], attrs))
- del candidates[0]
-
- for c in self.__special_candidates:
- attrs = ibus.AttrList ()
- attr = ibus.AttributeForeground(PinYinEngine.__special_phrase_color, 0, len(c))
- attrs.append(attr)
- self.__lookup_table.append_candidate(ibus.Text(c, attrs))
-
- for c in candidates:
- attrs = ibus.AttrList ()
- if c[pysqlitedb.FREQ] == None: # This phrase was created by user.
- attr = ibus.AttributeForeground(PinYinEngine.__user_phrase_color, 0, c[pysqlitedb.YLEN])
- else:
- attr = ibus.AttributeForeground(PinYinEngine.__phrase_color, 0, c[pysqlitedb.YLEN])
- attrs.append(attr)
- self.__lookup_table.append_candidate(ibus.Text(c[pysqlitedb.PHRASE], attrs))
- self.__lookup_table.show_cursor(True)
- self.__lookup_table.set_cursor_pos(0)
- self.update_lookup_table(self.__lookup_table, True, True)
-
- committed_string = self.__committed_phrases.get_string()
- invalid_pinyin = self.__user_input.get_invalid_string()
- preedit_string = " ".join([committed_string, self.__preedit_phrases.get_string(), invalid_pinyin])
- preedit_string = preedit_string.strip()
-
- if preedit_string:
- self.update_preedit(preedit_string, None, len(preedit_string), True)
- else:
- self.hide_preedit_text()
-
- if committed_string or len(self.__user_input) != 0:
- pinyin_list = self.__user_input.get_pinyin_list()
- pinyin_list = pinyin_list [len(committed_string):]
- pinyin_list = map(str, pinyin_list)
- if committed_string:
- aux_string = u"".join([committed_string, u" ", u"'".join(pinyin_list)])
- else:
- aux_string = u"'".join(pinyin_list)
-
- if PinYinEngine.__shuangpin:
- aux_string += " [" + u"".join(self.__user_input.get_chars()) + "]"
-
- if aux_string:
- self.update_aux_string(aux_string, None, True)
- else:
- self.hide_auxiliary_text()
- else:
- self.hide_auxiliary_text()
-
- def __invalidate(self):
- if self.__need_update:
- return
- self.__need_update = True
-
- def __update(self):
- if self.__need_update:
- self.__update_candidates()
- self.__update_ui()
- self.__need_update = False
-
- def __is_gb2312(self, record):
- try:
- record[pysqlitedb.PHRASE].encode("gb2312")
- except:
- return False
- return True
-
- def __get_candidates(self, pinyin_list):
- candidates = []
-
- for i in range(len(pinyin_list), 0, -1):
- candidates += self.__pydb.select_words_by_pinyin_list(pinyin_list[:i], PinYinEngine.__fuzzy_pinyin)
- if not PinYinEngine.__gbk:
- candidates = filter(self.__is_gb2312, candidates)
- return candidates
-
- def __get_a_candidate(self, pinyin_list):
- for i in range(len(pinyin_list), 0, -1):
- candidates = self.__pydb.select_words_by_pinyin_list(pinyin_list[:i], PinYinEngine.__fuzzy_pinyin)
- if not PinYinEngine.__gbk:
- candidates = filter(self.__is_gb2312, candidates)
- if candidates:
- return candidates[0]
- return None
-
-
- def __append_char(self, char):
- self.__user_input.append(char)
- self.__committed_phrases.clean()
- self.__invalidate()
-
- return True
-
- def __pop_char(self):
- if len(self.__user_input) == 0:
- return False
- if len(self.__committed_phrases) != 0:
- self.__committed_phrases.pop()
- else:
- self.__user_input.pop()
- self.__invalidate()
-
- return True
-
- def __match_hotkey(self, key, code, mask):
- if key.code == code and key.mask == mask:
- if self.__prev_key and key.code == self.__prev_key.code and key.mask & modifier.RELEASE_MASK:
- return True
- if not key.mask & modifier.RELEASE_MASK:
- return True
-
- return False
-
- def __internal_process_key_event(self, key):
-
- # When CapsLock is lock, we ignore all key events
- if key.mask & modifier.LOCK_MASK:
- if self.__user_input:
- self.reset()
- return False
-
- # ignore NumLock mask
- key.mask &= ~modifier.MOD2_MASK
-
- # Match mode switch hotkey
- if self.__match_hotkey(key, keysyms.Shift_L, modifier.SHIFT_MASK + modifier.RELEASE_MASK) or \
- self.__match_hotkey(key, keysyms.Shift_R, modifier.SHIFT_MASK + modifier.RELEASE_MASK):
- if self.__candidates and not self.__is_input_english() and PinYinEngine.__shift_select_canidates:
- index = self.__lookup_table.get_current_page_start()
- if key.code == keysyms.Shift_L:
- index += 1
- else:
- index += 2
- result = self.__commit_candidate(index)
- if result:
- if self.__committed_special_phrase:
- self.commit_string(self.__committed_special_phrase)
- else:
- commit_phrases = self.__committed_phrases.get_phrases()
- commit_string = self.__committed_phrases.get_string()
- self.commit_string(commit_string + self.__user_input.get_invalid_string())
-
- # adjust phrase freq and create new phrase
- try:
- self.__pydb.commit_phrases(commit_phrases)
- if len(commit_phrases) > 1:
- self.__pydb.new_phrase(commit_phrases)
- except:
- print "Can not inster phrases in db"
- return True
- else:
- self.property_activate("status")
- self.reset()
- return True
-
- # Match full half letter mode switch hotkey
- if self.__match_hotkey(key, keysyms.space, modifier.SHIFT_MASK):
- self.property_activate("full_letter")
- return True
-
- # Match full half punct mode switch hotkey
- if self.__match_hotkey(key, keysyms.period, modifier.CONTROL_MASK):
- self.property_activate("full_punct")
- return True
-
- # Match remove user phrase hotkeys
- for code in xrange(keysyms._1, keysyms._1 + PinYinEngine.__page_size):
- if self.__match_hotkey(key, code, modifier.CONTROL_MASK):
- index = code - keysyms._1 + self.__lookup_table.get_current_page_start()
- return self.__remove_candidate(index)
-
- # we ignore all hotkeys
- if key.mask &(modifier.CONTROL_MASK + modifier.ALT_MASK):
- return False
-
- # Ignore key release event
- if key.mask & modifier.RELEASE_MASK:
- return True
-
- if self.__is_input_english():
- return self.__english_mode_process_key_event(key)
- else:
- if self.__temp_english_mode:
- return self.__temp_english_mode_process_key_event(key)
- elif self.__i_mode:
- return self.__i_mode_process_key_event(key)
- else:
- return self.__chinese_mode_process_key_event(key)
-
- def __convert_to_full_width(self, c):
- if c in PinYinEngine.__half_puncts:
- return c
- elif c == u".":
- return u"\u3002"
- elif c == u"\\":
- return u"\u3001"
- elif c == u"^":
- return u"\u2026\u2026"
- elif c == u"_":
- return u"\u2014\u2014"
- elif c == u"$":
- return u"\uffe5"
- elif c == u"\"":
- self.__double_quotation_state = not self.__double_quotation_state
- if self.__double_quotation_state:
- return u"\u201c"
- else:
- return u"\u201d"
- elif c == u"'":
- self.__single_quotation_state = not self.__single_quotation_state
- if self.__single_quotation_state:
- return u"\u2018"
- else:
- return u"\u2019"
-
- elif c == u"<":
- if not self.__is_input_english():
- return u"\u300a"
- elif c == u">":
- if not self.__is_input_english():
- return u"\u300b"
-
- return ibus.unichar_half_to_full(c)
-
- def __english_mode_process_key_event(self, key):
- # ignore if key code is not a normal ascii char
- if key.code >= 128:
- return False
-
- c = unichr(key.code)
- if ascii.ispunct(key.code): # if key code is a punctation
- if self.__full_width_punct[self.__mode]:
- self.commit_string(self.__convert_to_full_width(c), False)
- return True
- else:
- self.commit_string(c, False)
- return True
-
- if self.__full_width_letter[self.__mode]: # if key code is a letter or digit
- self.commit_string(self.__convert_to_full_width(c), False)
- return True
- else:
- self.commit_string(c, False)
- return True
-
- # should not reach there
- return False
-
- def __i_mode_process_key_event(self, key):
- if key.code in(keysyms.Return, keysyms.KP_Enter):
- commit_string = u"".join(self.__user_input.get_chars())
- self.commit_string(commit_string)
- return True
- elif key.code == keysyms.BackSpace and len(self.__user_input) != 0:
- self.__user_input.pop()
- if len(self.__user_input) == 0:
- self.__i_mode = False
- self.__invalidate()
- return True
- elif key.code == keysyms.Escape:
- self.__user_input.clean()
- self.__i_mode = False
- self.__invalidate()
- return True
- elif key.code >= keysyms._1 and key.code <= keysyms._9:
- if not self.__candidates:
- return True
- index = key.code - keysyms._1
- if index >= PinYinEngine.__page_size:
- return True
- index += self.__lookup_table.get_current_page_start()
- if index >= len(self.__candidates):
- return True
- self.commit_string(self.__candidates[index])
- return True
- elif key.code in(keysyms.KP_Space, keysyms.space):
- if not self.__candidates:
- return True
- index = self.__lookup_table.get_cursor_pos()
- if index >= len(self.__candidates):
- return True
- self.commit_string(self.__candidates[index])
- return True
- elif key.code == keysyms.Down:
- self.cursor_down()
- return True
- elif key.code == keysyms.Up:
- self.cursor_up()
- return True
- elif key.code == keysyms.Page_Down and self.__candidates: # press PageDown
- self.page_down()
- return True
- elif key.code == keysyms.Page_Up and self.__candidates: # press PageUp
- self.page_up()
- return True
- elif key.code == keysyms.period and self.__candidates and PinYinEngine.__comma_page_down_up: # press .
- self.page_down()
- return True
- elif key.code == keysyms.comma and self.__candidates and PinYinEngine.__comma_page_down_up: # press ,
- self.page_up()
- return True
- elif key.code == keysyms.equal and self.__candidates and PinYinEngine.__equal_page_down_up: # press =
- self.page_down()
- return True
- elif key.code == keysyms.minus and self.__candidates and PinYinEngine.__equal_page_down_up: # press -
- self.page_up()
- return True
-
- if key.code >= 128:
- return True
-
- self.__user_input.append(unichr(key.code))
- self.__invalidate()
-
- return True
-
- def __temp_english_mode_process_key_event(self, key):
- if key.code in(keysyms.Return, keysyms.KP_Enter):
- commit_string = u"".join(self.__user_input.get_chars())
- if commit_string[0] in(u"v", u"u"):
- commit_string = commit_string[1:]
- self.commit_string(commit_string)
- return True
- elif key.code == keysyms.BackSpace and len(self.__user_input) != 0:
- self.__user_input.pop()
- if len(self.__user_input) == 0:
- self.__temp_english_mode = False
- self.__invalidate()
- return True
- elif key.code == keysyms.Escape:
- self.__user_input.clean()
- self.__temp_english_mode = False
- self.__invalidate()
- return True
- elif key.code >= keysyms._1 and key.code <= keysyms._9 and self.__english_candidates:
- index = key.code - keysyms._1
- if index >= PinYinEngine.__page_size:
- return False
- index += self.__lookup_table.get_current_page_start()
- if index >=0 and index < len(self.__english_candidates):
- for i in xrange(0, len(self.__current_word)):
- self.__user_input.pop()
- for c in self.__english_candidates[index]:
- self.__user_input.append(c)
- self.__invalidate()
- return True
- return False
- elif key.code in(keysyms.Page_Down, ) and self.__english_candidates:
- self.page_down()
- return True
- elif key.code in(keysyms.Page_Up, ) and self.__english_candidates:
- self.page_up()
- return True
-
- if key.code >= 128:
- return True
-
- self.__user_input.append(unichr(key.code))
- self.__invalidate()
-
- return True
-
- def __chinese_mode_process_key_event(self, key):
- # define a condition half to full width translate functions
- cond_letter_translate = lambda(c): \
- self.__convert_to_full_width(c) if self.__full_width_letter [self.__mode] else c
- cond_punct_translate = lambda(c): \
- self.__convert_to_full_width(c) if self.__full_width_punct [self.__mode] else c
-
- if key.code in(keysyms.Return, keysyms.KP_Enter):
- if len(self.__user_input) == 0: # forward Return if inputed chars is empty
- return False
- chars = map(cond_letter_translate, self.__user_input.get_chars())
- commit_string = u"".join(chars)
- self.commit_string(commit_string)
- return True
- elif key.code == keysyms.Escape:
- if len(self.__user_input) != 0:
- self.reset()
- return True
- return False
- elif key.code == keysyms.Down:
- return self.cursor_down()
- elif key.code == keysyms.Up:
- return self.cursor_up()
- elif key.code == keysyms.BackSpace:
- return self.__pop_char()
- elif key.code >= keysyms._1 and key.code <= keysyms._9:
- if not self.__candidates:
- self.commit_string(cond_letter_translate(unichr(key.code)))
- else:
- index = key.code - keysyms._1
- if index >= PinYinEngine.__page_size:
- return True
- index += self.__lookup_table.get_current_page_start()
- result = self.__commit_candidate(index)
- if result:
- if self.__committed_special_phrase:
- self.commit_string(self.__committed_special_phrase)
- else:
- commit_phrases = self.__committed_phrases.get_phrases()
- commit_string = self.__committed_phrases.get_string()
- self.commit_string(commit_string + self.__user_input.get_invalid_string())
-
- # adjust phrase freq and create new phrase
- try:
- self.__pydb.commit_phrases(commit_phrases)
- if len(commit_phrases) > 1:
- self.__pydb.new_phrase(commit_phrases)
- except:
- print "Can not inster phrases in db"
- return True
- elif key.code in(keysyms.KP_Space, keysyms.space):
- if not self.__candidates:
- self.commit_string(cond_letter_translate(u" "))
- else:
- index = self.__lookup_table.get_cursor_pos()
- result = self.__commit_candidate(index)
- if result:
- if self.__committed_special_phrase:
- self.commit_string(self.__committed_special_phrase)
- else:
- commit_phrases = self.__committed_phrases.get_phrases()
- commit_string = self.__committed_phrases.get_string()
- self.commit_string(commit_string + self.__user_input.get_invalid_string())
-
- # adjust phrase freq and create new phrase
- try:
- self.__pydb.commit_phrases(commit_phrases)
- if len(commit_phrases) > 1:
- self.__pydb.new_phrase(commit_phrases)
- except:
- print "Can not inster phrases in db"
- return True
- elif key.code == keysyms.Page_Down and self.__candidates: # press PageDown
- self.page_down()
- return True
- elif key.code == keysyms.equal and self.__candidates and PinYinEngine.__equal_page_down_up: # press equal
- self.page_down()
- return True
- elif key.code == keysyms.period and self.__candidates and PinYinEngine.__comma_page_down_up: # press period
- self.page_down()
- return True
- elif key.code == keysyms.Page_Up and self.__candidates: # press PageUp
- self.page_up()
- return True
- elif key.code == keysyms.minus and self.__candidates and PinYinEngine.__equal_page_down_up: # press minus
- self.page_up()
- return True
- elif key.code == keysyms.comma and self.__candidates and PinYinEngine.__comma_page_down_up: #press comma
- self.page_up()
- return True
-
- elif key.code in(keysyms.bracketleft, keysyms.bracketright) and self.__candidates:
- cursor_pos = self.__lookup_table.get_cursor_pos()
- candidate = self.__candidates[cursor_pos]
- if key.code == keysyms.bracketleft:
- i = 0
- else:
- i = len(candidate[pysqlitedb.PHRASE]) - 1
- char = candidate[pysqlitedb.PHRASE][i]
- if i < 4:
- pinyin_id = candidate[pysqlitedb.Y0 + i]
- shengmu_id = candidate[pysqlitedb.S0 + i]
- else:
- pinyin = candidate[pysqlitedb.YX].split("'")[-1]
- word = pyutil.PinYinWord(pinyin)
- pinyin_id = word.get_pinyin_id()
- shengmu_id = word.get_sheng_mu_id()
-
- self.__pydb.commit_char(char, pinyin_id, shengmu_id)
- self.commit_string(char)
- return True
- elif PinYinEngine.__uv_to_temp and not PinYinEngine.__shuangpin \
- and len(self.__user_input) == 0 \
- and key.code in(keysyms.v, keysyms.u):
- self.__user_input.append(unichr(key.code))
- self.__temp_english_mode = True
- self.__invalidate()
- return True
- elif key.code >= keysyms.A and key.code <= keysyms.Z and len(self.__user_input) == 0:
- self.__user_input.append(unichr(key.code))
- self.__temp_english_mode = True
- self.__invalidate()
- return True
- elif key.code == keysyms.i and \
- len(self.__user_input) == 0 and \
- not PinYinEngine.__shuangpin:
- # we goto i_mode
- self.__user_input.append(unichr(key.code))
- self.__i_mode = True
- self.__invalidate()
- return True
- elif(key.code >= keysyms.a and key.code <= keysyms.z) or \
- (key.code == keysyms.apostrophe and len(self.__user_input) != 0) or \
- (key.code == keysyms.semicolon and len(self.__user_input) != 0 and PinYinEngine.__shuangpin) :
- return self.__append_char(unichr(key.code))
- elif key.code <= 127:
- if len(self.__user_input) != 0:
- if PinYinEngine.__auto_commit:
- self.__chinese_mode_process_key_event(KeyEvent(keysyms.space, True, key.mask))
- else:
- return True
- c = chr(key.code)
- if c == "." and self.__prev_char and self.__prev_char.isdigit() \
- and self.__prev_key and chr(self.__prev_key.code) == self.__prev_char:
- self.commit_string(u".")
- elif ascii.ispunct(key.code):
- self.commit_string(cond_punct_translate(unichr(key.code)))
- else:
- self.commit_string(cond_letter_translate(unichr(key.code)))
- return True
- elif len(self.__user_input) != 0:
- return True
-
- return False
-
- def __commit_candidate(self, i):
- if i == 0:
- for phrase in self.__preedit_phrases.get_phrases():
- self.__committed_phrases.append(phrase)
- return True
-
- if i >=1 and i <= len(self.__special_candidates):
- self.__committed_special_phrase = self.__special_candidates [i - 1]
- return True
-
- if len(self.__preedit_phrases) != 1:
- i -= 1
-
- i -= len(self.__special_candidates)
-
- if i >= len(self.__candidates):
- return False
-
- self.__committed_phrases.append( self.__candidates[i])
- pinyin_list = self.__user_input.get_pinyin_list()
-
- if self.__committed_phrases.length_of_chars() == len(pinyin_list):
- return True
-
- self.__invalidate()
-
- return False
-
- def __remove_candidate(self, i):
- if i >= 1:
- i -= len(self.__special_candidates)
-
- if len(self.__preedit_phrases) != 1:
- i -= 1
-
- if i >= len(self.__candidates) or i < 0:
- return False
-
- if self.__candidates[i][pysqlitedb.FREQ] != None: # This phrase was not create by user.
- return False
-
- candidate = self.__candidates.pop(i)
- try:
- self.__pydb.remove_phrase(candidate)
- except:
- print "Can not remove phrase from db"
- self.__invalidate()
-
- return True
-
- def __start_setup(self):
- if PinYinEngine.__setup_pid != 0:
- pid, state = os.waitpid(PinYinEngine.__setup_pid, os.P_NOWAIT)
- if pid != PinYinEngine.__setup_pid:
- os.kill(PinYinEngine.__setup_pid, signal.SIGUSR1)
- return
- PinYinEngine.__setup_pid = 0
- setup_cmd = path.join(LIBEXECDIR, "ibus-setup-pinyin")
- PinYinEngine.__setup_pid = os.spawnl(os.P_NOWAIT, setup_cmd, "ibus-setup-pinyin")
-
-
- def process_key_event(self, keyval, keycode, state):
- key = KeyEvent(keyval, state & modifier.RELEASE_MASK == 0, state)
- result = self.__internal_process_key_event(key)
- self.__update()
- self.__prev_key = key
- return result
-
- def commit_string(self, string, need_update = True):
- self.__temp_english_mode = False
- self.__i_mode = False
- self.__candidates = []
- self.__english_candidates = []
- self.__cursor = 0
- self.__user_input.clean()
- self.__preedit_string = u""
- self.__committed_phrases.clean()
- self.__committed_special_phrase = u""
- self.__need_update = True
- self.__update()
- super(PinYinEngine,self).commit_text(ibus.Text(string))
- self.__prev_char = string[-1]
-
- def update_preedit(self, preedit_string, preedit_attrs, cursor_pos, visible):
- if preedit_attrs == None:
- preedit_attrs = ibus.AttrList()
- attr = ibus.AttributeUnderline(ibus.ATTR_UNDERLINE_SINGLE, 0, len(preedit_string))
- preedit_attrs.append(attr)
-
- super(PinYinEngine, self).update_preedit_text(ibus.Text(preedit_string, preedit_attrs), cursor_pos, visible)
-
- def update_aux_string(self, aux_string, aux_attrs, visible):
- super(PinYinEngine,self).update_auxiliary_text(ibus.Text(aux_string, aux_attrs), visible)
-
- def page_up(self):
- if self.__lookup_table.page_up():
- self.update_lookup_table(self.__lookup_table, True, True)
- return True
-
- return True
-
- def page_down(self):
- if self.__lookup_table.page_down():
- self.update_lookup_table(self.__lookup_table, True, True)
- return True
- return True
-
- def cursor_up(self):
- if len(self.__candidates) == 0:
- return False
-
- if self.__lookup_table.cursor_up():
- self.update_lookup_table(self.__lookup_table, True, True)
- return True
-
- def cursor_down(self):
- if len(self.__candidates) == 0:
- return False
-
- if self.__lookup_table.cursor_down():
- self.update_lookup_table(self.__lookup_table, True, True)
- return True
-
- def candidate_clicked(self, index, button, state):
- if button == 1:
- self.process_key_event(keysyms._1 + index, state)
-
- def reset(self):
- self.__temp_english_mode = False
- self.__i_mode = False
- self.__user_input.clean()
- self.__committed_phrases.clean()
- self.__committed_special_phrase = u""
- self.__preedit_string = u""
- self.__special_candidates = []
- self.__candidates = []
- self.__english_candidates = []
- self.__cursor = 0
- self.__double_quotation_state = False
- self.__single_quotation_state = False
- self.__prev_key = None
- self.__prev_char = None
- self.__invalidate()
-
- def focus_in(self):
- self.register_properties(self.__prop_list)
- self.__refresh_properties()
- if PinYinEngine.__shuangpin:
- self.__py_parser = pyparser.ShuangPinParser(PinYinEngine.__shuangpin_schema)
- else:
- self.__py_parser = pyparser.PinYinParser()
- self.__lookup_table.set_page_size(PinYinEngine.__page_size)
- self.__user_input.set_parser(self.__py_parser)
- self.__user_input.set_gbk(PinYinEngine.__gbk)
- self.__user_input.set_auto_correct(PinYinEngine.__auto_correct)
- self.__invalidate()
-
- def focus_out(self):
- self.reset()
-
- def enable(self):
- self.focus_in()
-
- def property_activate(self, prop_name, prop_state = ibus.PROP_STATE_UNCHECKED):
- if prop_name == "status":
- self.__change_mode()
- elif prop_name == "full_letter":
- self.__full_width_letter [self.__mode] = not self.__full_width_letter [self.__mode]
- self.__refresh_properties()
- elif prop_name == "full_punct":
- self.__full_width_punct [self.__mode] = not self.__full_width_punct [self.__mode]
- self.__refresh_properties()
- # elif property == "shuangpin":
- # PinYinEngine.__shuangpin = not PinYinEngine.__shuangpin
- # self.reset()
- # if PinYinEngine.__shuangpin:
- # self.__py_parser = pyparser.ShuangPinParser(PinYinEngine.__shuangpin_schema)
- # else:
- # self.__py_parser = pyparser.PinYinParser()
- # self.__user_input.set_parser(self.__py_parser)
- # self.__config.write("engine/PinYin/ShuangPin", PinYinEngine.__shuangpin)
- # self.__refresh_properties()
- # elif property == "gbk":
- # PinYinEngine.__gbk = not PinYinEngine.__gbk
- # self.reset()
- # self.__config.write("engine/PinYin/SupportGBK", PinYinEngine.__gbk)
- # self.__refresh_properties()
-
- elif prop_name == "setup":
- self.__start_setup()
-
- def process_helper_event(self, helper_uuid, trans):
- IMEngine.process_helper_event(self, helper_uuid, trans)
-
- def update_client_capabilities(self, cap):
- IMEngine.update_client_capabilities(self, cap)
-
- @classmethod
- def CONFIG_VALUE_CHANGED(cls, bus, section, name, value):
- config = bus.get_config()
-
- if section != "engine/PinYin":
- return
- if name == "ShuangPinSchema":
- PinYinEngine.__shuangpin_schema = \
- config.get_value("engine/PinYin", "ShuangPinSchema", "MSPY")
- if PinYinEngine.__shuangpin_schema not in pydict.SHUANGPIN_SCHEMAS:
- PinYinEngine.__shuangpin_schema = "MSPY"
- elif name == "FuzzyPinYin":
- PinYinEngine.__fuzzy_pinyin = \
- config.get_value("engine/PinYin", "FuzzyPinYin", False)
- PinYinEngine.__fuzzy_pinyin = False
- elif name == "AutoCorrect":
- PinYinEngine.__auto_correct = \
- config.get_value("engine/PinYin", "AutoCorrect", True)
- elif name == "SpellCheck":
- PinYinEngine.__spell_check = \
- config.get_value("engine/PinYin", "SpellCheck", True)
- elif name == "PageSize":
- PinYinEngine.__page_size = \
- config.get_value("engine/PinYin", "PageSize", 5)
- if PinYinEngine.__page_size < 1 or PinYinEngine.__page_size > 9:
- PinYinEngine.__page_size = 5
- elif name == "SupportGBK":
- PinYinEngine.__gbk = \
- config.get_value("engine/PinYin", "SupportGBK", False)
- elif name == "ShuangPin":
- PinYinEngine.__shuangpin = \
- config.get_value("engine/PinYin", "ShuangPin", False)
- elif name == "PhraseColor":
- PinYinEngine.__phrase_color = \
- config.get_value("engine/PinYin", "PhraseColor", PinYinEngine.__phrase_color)
- elif name == "NewPhraseColor":
- PinYinEngine.__new_phrase_color = \
- config.get_value("engine/PinYin", "NewPhraseColor", PinYinEngine.__new_phrase_color)
- elif name == "UserPhraseColor":
- PinYinEngine.__user_phrase_color = \
- config.get_value("engine/PinYin", "UserPhraseColor", PinYinEngine.__user_phrase_color)
- elif name == "SpecialPhraseColor":
- PinYinEngine.__special_phrase_color = \
- config.get_value("engine/PinYin", "SpecialPhraseColor", PinYinEngine.__special_phrase_color)
- elif name == "EnglishPhraseColor":
- PinYinEngine.__english_phrase_color = \
- config.get_value("engine/PinYin", "EnglishPhraseColor", PinYinEngine.__english_phrase_color)
- elif name == "ErrorEnglishPhraseColor":
- PinYinEngine.__error_eng_phrase_color = \
- config.get_value("engine/PinYin", "ErrorEnglishPhraseColor", PinYinEngine.__error_eng_phrase_color)
- elif name == "UVToTemp":
- PinYinEngine.__uv_to_temp = \
- config.get_value("engine/PinYin", "UVToTemp", PinYinEngine.__uv_to_temp)
- elif name == "ShiftSelectCandidates":
- PinYinEngine.__shift_select_canidates = \
- config.get_value("engine/PinYin", "ShiftSelectCandidates", PinYinEngine.__shift_select_candidates)
- elif name == "CommaPageDownUp":
- PinYinEngine.__comma_page_down_up = \
- config.get_value("engine/PinYin", "CommaPageDownUp", PinYinEngine.__comma_page_down_up)
- elif name == "EqualPageDownUp":
- PinYinEngine.__equal_page_down_up = \
- config.get_value("engine/PinYin", "EqualPageDownUp", PinYinEngine.__equal_page_down_up)
- elif name == "AutoCommit":
- PinYinEngine.__auto_commit = \
- config.get_value("engine/PinYin", "AutoCommit", PinYinEngine.__auto_commit)
- elif name == "HalfPunctuations":
- PinYinEngine.__half_puncts = \
- config.get_value("engine/PinYin", "HalfPunctuations", PinYinEngine.__half_puncts)
- else:
- print "Unknow name(%s)" % name
-
- @classmethod
- def CONFIG_RELOADED(cls, bus):
-
- config = bus.get_config()
-
- PinYinEngine.__shuangpin_schema = \
- config.get_value("engine/PinYin", "ShuangPinSchema", "MSPY")
- if PinYinEngine.__shuangpin_schema not in pydict.SHUANGPIN_SCHEMAS:
- PinYinEngine.__shuangpin_schema = "MSPY"
-
- PinYinEngine.__fuzzy_pinyin = \
- config.get_value("engine/PinYin", "FuzzyPinYin", False)
- PinYinEngine.__fuzzy_pinyin = False
- PinYinEngine.__auto_correct = \
- config.get_value("engine/PinYin", "AutoCorrect", True)
- PinYinEngine.__spell_check = \
- config.get_value("engine/PinYin", "SpellCheck", True)
- PinYinEngine.__page_size = \
- config.get_value("engine/PinYin", "PageSize", 5)
- if PinYinEngine.__page_size < 1 or PinYinEngine.__page_size > 9:
- PinYinEngine.__page_size = 5
- PinYinEngine.__gbk = \
- config.get_value("engine/PinYin", "SupportGBK", False)
- PinYinEngine.__shuangpin = \
- config.get_value("engine/PinYin", "ShuangPin", False)
-
- PinYinEngine.__phrase_color = \
- config.get_value("engine/PinYin", "PhraseColor", PinYinEngine.__phrase_color)
- PinYinEngine.__new_phrase_color = \
- config.get_value("engine/PinYin", "NewPhraseColor", PinYinEngine.__new_phrase_color)
- PinYinEngine.__user_phrase_color = \
- config.get_value("engine/PinYin", "UserPhraseColor", PinYinEngine.__user_phrase_color)
- PinYinEngine.__special_phrase_color = \
- config.get_value("engine/PinYin", "SpecialPhraseColor", PinYinEngine.__special_phrase_color)
- PinYinEngine.__english_phrase_color = \
- config.get_value("engine/PinYin", "EnglishPhraseColor", PinYinEngine.__english_phrase_color)
- PinYinEngine.__error_eng_phrase_color = \
- config.get_value("engine/PinYin", "ErrorEnglishPhraseColor", PinYinEngine.__error_eng_phrase_color)
- PinYinEngine.__uv_to_temp = \
- config.get_value("engine/PinYin", "UVToTemp", PinYinEngine.__uv_to_temp)
- PinYinEngine.__shift_select_canidates = \
- config.get_value("engine/PinYin", "ShiftSelectCandidates", PinYinEngine.__shift_select_candidates)
- PinYinEngine.__comma_page_down_up = \
- config.get_value("engine/PinYin", "CommaPageDownUp", PinYinEngine.__comma_page_down_up)
- PinYinEngine.__equal_page_down_up = \
- config.get_value("engine/PinYin", "EqualPageDownUp", PinYinEngine.__equal_page_down_up)
- PinYinEngine.__auto_commit = \
- config.get_value("engine/PinYin", "AutoCommit", PinYinEngine.__auto_commit)
- PinYinEngine.__half_puncts = \
- config.get_value("engine/PinYin", "HalfPunctuations", PinYinEngine.__half_puncts)
- PinYinEngine.__half_puncts = PinYinEngine.__half_puncts.replace(" ", "")
-
-class KeyEvent:
- def __init__(self, keyval, is_press, state):
- self.code = keyval
- self.mask = state
- if not is_press:
- self.mask |= modifier.RELEASE_MASK
- def __str__(self):
- return "%s 0x%08x" % (keysyms.keycode_to_name(self.code), self.mask)
-
-
-class UserInput:
- "UserInput holds user input chars"
- def __init__(self, parser, max_length = __MAX_LEN__):
- self.__parser = parser
- self.__max_length = max_length
- self.__auto_correct = True
- self.__gbk = False
- self.__chars =([], [])
- self.__pinyin_list = []
-
-
- def clean(self):
- self.__chars =([], [])
- self.__pinyin_list = []
-
- def set_parser(self, parser):
- self.clean()
- self.__parser = parser
-
- def set_gbk(self, gbk):
- self.__gbk = gbk
- self.clean()
-
- def set_auto_correct(self, auto_correct):
- self.__auto_correct = auto_correct
- self.clean()
-
- def get_pinyin_list(self):
- return self.__pinyin_list
-
- def get_chars(self):
- return self.__chars[0] + self.__chars[1]
-
- def get_invalid_chars(self):
- return self.__chars[1]
-
- def get_invalid_string(self):
- return "".join(self.__chars[1])
-
- def append(self, c):
- if len(self.__chars[0]) + len(self.__chars[1]) == self.__max_length:
- return
-
- if self.__chars[1]:
- self.__chars[1].append(c)
- else:
- try:
- self.__pinyin_list = self.__parser.parse("".join(self.__chars[0] + [c]), self.__auto_correct, self.__gbk)
- self.__chars[0].append(c)
- except:
- self.__chars[1].append(c)
-
- def pop(self):
- resutl = []
- if len(self.__chars[1]) != 0:
- return self.__chars[1].pop()
- elif len(self.__chars[0]) != 0:
- c = self.__chars[0].pop()
- if len(self.__chars[0]) != 0:
- self.__pinyin_list = self.__parser.parse("".join(self.__chars[0]), self.__auto_correct, self.__gbk)
- else:
- self.__pinyin_list = []
- return c
- else:
- return ""
-
- def __len__(self):
- return len(self.__chars[0]) + len(self.__chars[1])
-
-class PhraseList:
- """PhraseList contains phrases"""
- def __init__(self):
- self.__list = []
- self.__length_of_chars = 0
-
- def clean(self):
- """Remove all phrases from the list"""
- self.__list = []
- self.__length_of_chars = 0
-
- def append(self, phrase):
- """Append a phrase into the list"""
- self.__list.append(phrase)
- self.__length_of_chars += phrase[pysqlitedb.YLEN]
-
- def pop(self):
- phrase = self.__list.pop()
- self.__length_of_chars -= phrase[pysqlitedb.YLEN]
- return phrase
-
- def count(self):
- """Return count of phrases in the list"""
- return len(self.__list)
-
- def length_of_chars(self):
- """Return number of chars in all phrases in the list"""
- return self.__length_of_chars
-
- def get_phrases(self):
- """Return all phrases"""
- return self.__list
-
- def get_string(self):
- """Join all phrases into a string object and return it."""
- get_phrase = lambda x: x[pysqlitedb.PHRASE]
- return u"".join(map(get_phrase, self.__list))
-
- def __str__(self):
- return self.get_string().encode("utf8")
-
- def __len__(self):
- return len(self.__list)
-
-
diff --git a/engine/pycreatedb.py b/engine/pycreatedb.py
deleted file mode 100644
index e780faf..0000000
--- a/engine/pycreatedb.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim:set et sts=4 sw=4:
-#
-# ibus-pinyin - The PinYin engine for IBus
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
-
-import sys, os, re
-import pysqlitedb
-import bz2
-
-def phrase_pinyin_parser(f):
- for l in f:
- pinyin, phrase, freq = unicode(l, "utf-8").strip().split()
- pinyin = pinyin.replace(u"u:", u"v")
- yield (phrase, pinyin, int(freq))
-
-def main():
- srcdir = "."
- if len(sys.argv) == 2:
- srcdir = sys.argv[1]
-
- filename = "py-new.db"
- try:
- os.unlink(filename)
- except:
- pass
-
- db = pysqlitedb.PYSQLiteDB(filename = filename)
- db.create_tables()
- db.init_pinyin_table()
- db.init_shengmu_table()
-
- for phrase_filename in sys.argv[1:]:
- print "Loading %s" % phrase_filename
- db.add_phrases(phrase_pinyin_parser(file(phrase_filename)))
-
- print "Optimizing database"
- db.optimize_database()
-
-if __name__ == "__main__":
- main()
diff --git a/engine/pyparser.py b/engine/pyparser.py
deleted file mode 100644
index 5266c4c..0000000
--- a/engine/pyparser.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim:set et sts=4 sw=4:
-#
-# ibus-pinyin - The PinYin engine for IBus
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
-
-import sys
-import pyutil
-import pydict
-
-class PinYinParser:
- pinyin_dict = set (pydict.PINYIN_DICT.keys () + pydict.SHENGMU_DICT.keys ())
- gb2312_pinyin_dict = pinyin_dict - set (["eng", "chua", "fe", "fiao", "liong"])
- correct_yunmu = {
- "ing" : ("ign", "img"), "ui" : ("uei", "iu", "i"),
- "un" : ("uen",), "iu" : ("iou", "ui"),
- "ao" : ("au", ), "ei" : ("i", ),
- "iao" : ("ioa", "ia", "i"), "ian" : ("ia", "i"), "iang" : ("ian", "ia", "i")}
-
- correct_table = {}
-
- def __init__ (self):
- self.init_corrent_table ()
-
- def init_corrent_table (self):
- if PinYinParser.correct_table:
- return
- for key, id in pydict.PINYIN_DICT.items ():
- if key[-3:] in PinYinParser.correct_yunmu:
- for yunmu in PinYinParser.correct_yunmu[key[-3:]]:
- pinyin = key[:-3] + yunmu
- if pinyin not in pydict.PINYIN_DICT:
- PinYinParser.correct_table [pinyin] = key
- if key[-2:] in PinYinParser.correct_yunmu:
- for yunmu in PinYinParser.correct_yunmu[key[-2:]]:
- pinyin = key[:-2] + yunmu
- if pinyin not in pydict.PINYIN_DICT:
- PinYinParser.correct_table [pinyin] = key
-
- def parse_recursive (self, string, auto_correct = True, gbk = True):
- l = min (6, len (string))
- if l == 0:
- return []
- p = None
- for i in range (l, 0, -1):
- py = string[-i:]
-
- if gbk:
- if py in self.pinyin_dict:
- p = pyutil.PinYinWord (py)
- break
- else:
- if py in self.gb2312_pinyin_dict:
- p = pyutil.PinYinWord (py)
- break
-
- if p == None and auto_correct and py in PinYinParser.correct_table:
- py = PinYinParser.correct_table[py]
- if gbk:
- if py in self.pinyin_dict:
- p = pyutil.PinYinWord (py)
- break
- else:
- if py in self.gb2312_pinyin_dict:
- p = pyutil.PinYinWord (py)
- break
- if p == None:
- raise Exception ("can not parse '%s'" % string.encode ("utf-8"))
- pys = self.parse_recursive (string[:-i], auto_correct, gbk)
- pys.append (p)
- return pys
-
- def parse (self, string, auto_correct = True, gbk = True):
- try:
- pys = []
- for py in string.split (u"'"):
- pys += self.parse_recursive (py, auto_correct, gbk)
- return pys
- except Exception, e:
- import traceback
- traceback.print_exc ()
- raise e
-
-class ShuangPinParser:
- def __init__ (self, schema = "MSPY"):
- self._gbk = True
- self._schema = schema
- self._shengmu_dict, self._yunmu_dict = pydict.SHUANGPIN_SCHEMAS[self._schema]
-
- def parse_shuangpin_recursive (self, pys, string, auto_correct = True, gbk = True):
- if len (string) == 0:
- return []
-
- if len (string) == 1:
- try:
- shengmu = self._shengmu_dict[string[0]]
- if shengmu == "'":
- shengmu = ""
- except:
- raise Exception ("can not parse '%s'" % string.encode ("utf-8"))
-
- return [pyutil.PinYinWord (shengmu)]
-
- try:
- shengmu = self._shengmu_dict[string[0]]
- if shengmu == "'":
- shengmu = ""
- yunmu = self._yunmu_dict[string[1]]
- except:
- raise Exception ("can not parse '%s'" % string.encode ("utf-8"))
-
- p = None
-
- for i in yunmu:
- pinyin = shengmu + i
- if pinyin in PinYinParser.pinyin_dict:
- p = pyutil.PinYinWord (pinyin)
- break
-
- if p == None:
- raise Exception ("can not parse '%s'" % string.encode ("utf-8"))
-
- pys.append (p)
- pys = self.parse_shuangpin_recursive (pys, string[2:], auto_correct, gbk)
-
- return pys
-
- def parse (self, string, auto_correct = True, gbk = True):
- pys = []
- pys += self.parse_shuangpin_recursive (pys, string, auto_correct, gbk)
- return pys
-
-if __name__ == "__main__":
- # parser = PinYinParser ()
- parser = ShuangPinParser ()
- pys = parser.parse (sys.argv[1])
- print "'".join (map (str, pys))
-
diff --git a/engine/pysqlitedb.py b/engine/pysqlitedb.py
deleted file mode 100644
index 399c14a..0000000
--- a/engine/pysqlitedb.py
+++ /dev/null
@@ -1,538 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim:set et sts=4 sw=4:
-#
-# ibus-pinyin - The PinYin engine for IBus
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
-
-import os
-import os.path as path
-import time
-import sys
-import sqlite3 as sqlite
-import re
-import uuid
-import traceback
-import pyutil
-import pydict
-import pyparser
-
-(YLEN, Y0, Y1, Y2, Y3, YX, S0, S1, S2, S3, PHRASE, FREQ, USER_FREQ) = range(13)
-
-FLUSH_PERIOD = 60 * 5 # 5 minute
-
-class PYSQLiteDB:
- """phrase database that contains all phrases and phrases' pinyin"""
- def __init__ (self, name = "py.db", user_db = None, filename = None):
-
- # init last flush time
- self._last_flush_time = None
-
- if filename:
- self.db = sqlite.connect (filename)
- self.parser = pyparser.PinYinParser ()
- return
-
- dirname = path.dirname(__file__)
-
- name = os.path.join (dirname, name)
-
- # open system phrase database
- self.db = sqlite.connect (name)
-
- self.parser = pyparser.PinYinParser ()
- # self.db.execute ("PRAGMA locking_mode = EXCLUSIVE;")
- self.db.execute ("PRAGMA synchronous = NORMAL;")
- self.db.execute ("PRAGMA temp_store = MEMORY;")
-
- if user_db != None:
- home_path = os.getenv ("HOME")
- pinyin_path = path.join (home_path, ".ibus", "pinyin")
- user_db = path.join (pinyin_path, user_db)
- if not path.isdir (pinyin_path):
- os.makedirs (pinyin_path)
-
- try:
- desc = get_database_desc (user_db)
- if desc == None or desc["id"] != "0.1":
- new_name = "%s.%d" %(user_db, os.getpid())
- print >> sys.stderr, "Can not support the user db. We will rename it to %s" % new_name
- os.rename (user_db, new_name)
- except:
- pass
- else:
- user_db = ":memory:"
-
-
- # open user phrase database
- try:
- self.db.execute ("ATTACH DATABASE \"%s\" AS user_db;" % user_db)
- except:
- print >> sys.stderr, "The user database was damaged. We will recreate it!"
- os.rename (user_db, "%s.%d" % (user_db, os.getpid ()))
- self.db.execute ("ATTACH DATABASE \"%s\" AS user_db;" % user_db)
-
-
- # try create all tables in user database
- self.create_tables ("user_db")
- self.create_indexes ("user_db")
- self.generate_userdb_desc ()
-
- self.select_cache = Cache ()
-
- def create_tables (self, database = "main"):
- """create all phrases tables that contain all phrases"""
-
- try:
- self.db.executescript ("PRAGMA default_cache_size = 5000;")
- self.flush (True)
- except:
- pass
-
- # create pinyin table
- sqlstring = "CREATE TABLE IF NOT EXISTS %s.py_pinyin (pinyin TEXT PREMARY KEY);" % database
- self.db.execute (sqlstring)
-
- # create pinyin table
- sqlstring = "CREATE TABLE IF NOT EXISTS %s.py_shengmu (shengmu TEXT PREMARY KEY);" % database
- self.db.execute (sqlstring)
-
- # create phrase table
- sqlstring = """CREATE TABLE IF NOT EXISTS %(database)s.py_phrase (
- ylen INTEGER,
- y0 INTEGER, y1 INTEGER, y2 INTEGER, y3 INTEGER, yx TEXT,
- s0 INTEGER, s1 INTEGER, s2 INTEGER, s3 INTEGER,
- phrase TEXT,
- freq INTEGER, user_freq INTEGER);"""
-
- self.db.executescript (sqlstring % { "database":database })
- self.flush (True)
-
- def generate_userdb_desc (self):
- try:
- sqlstring = "CREATE TABLE user_db.desc (name PRIMARY KEY, value);"
- self.db.executescript (sqlstring)
- sqlstring = "INSERT INTO user_db.desc VALUES (?, ?);"
- self.db.execute (sqlstring, ("version", "0.1"))
- self.db.execute (sqlstring, ("id", str (uuid.uuid4 ())))
- sqlstring = "INSERT INTO user_db.desc VALUES (?, DATETIME(\"now\", \"localtime\"));"
- self.db.execute (sqlstring, ("create-time", ))
- self.flush (True)
- except:
- print "desc table has been created."
-
- def create_indexes (self, database = "main"):
- # create indexes
- sqlstring = """
- /*
- CREATE INDEX IF NOT EXISTS %(database)s.py_phrase_index_1 ON
- py_phrase (y0, y1, y2, y3);
- */
-
- CREATE INDEX IF NOT EXISTS %(database)s.py_phrase_index_2 ON
- py_phrase (ylen, y0, y1, y2, y3);
- CREATE INDEX IF NOT EXISTS %(database)s.py_phrase_index_3 ON
- py_phrase (ylen, s0, s1, s2, s3);
-
- /*
- CREATE INDEX IF NOT EXISTS %(database)s.py_phrase_index_4 ON
- py_phrase (s0, s1, s2, s2, s3);
- CREATE INDEX IF NOT EXISTS %(database)s.py_phrase_index_5 ON
- py_phrase (phrase);
- */
- """
- self.db.executescript (sqlstring % { "database" : database })
- self.flush (True)
-
- def optimize_database (self):
- sqlstring = """
- CREATE TABLE tmp AS SELECT * FROM py_phrase;
- DELETE FROM py_phrase;
- INSERT INTO py_phrase SELECT * FROM tmp ORDER BY ylen, y0, y1, y2, y3, yx, phrase;
- DROP TABLE tmp;
- """
- self.db.executescript (sqlstring)
- self.db.executescript ("VACUUM;")
-
- def init_pinyin_table (self):
- """create table pinyin that contains all pinyin"""
- sqlstring = "INSERT INTO py_pinyin (pinyin) VALUES (?)"
- for py in pydict.PINYIN_DICT.keys ():
- self.db.execute (sqlstring, (unicode (py),))
- self.flush (True)
-
- def init_shengmu_table (self):
- """create table shengmu that contains all shengmu of pinyin"""
- sqlstring = "INSERT INTO py_shengmu (shengmu) VALUES (?)"
- for shengmu in pydict.SHENGMU_DICT.keys ():
- self.db.execute (sqlstring, (unicode (shengmu),))
- self.flush (True)
-
- def add_phrases (self, phrases, database = "main"):
- """ add phrases to database, phrases is a iterable object
- Like: [(phrase, pinyin, freq), (phrase, pinyin, freq), ...]
- """
- sqlstring = """INSERT INTO %s.py_phrase (ylen, y0, y1, y2, y3, yx, s0, s1, s2, s3, phrase, freq, user_freq)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"""
- line = 1
- for phrase, pinyin, freq in phrases:
- try:
- py = self.parser.parse (pinyin)
- if len (py) != len (phrase):
- error_message = u"%s %s: Can not parse pinyin." % (phrase, pinyin)
- raise Exception (error_message.encode ("utf8"))
- record = [None, None, None, None, None, None, None, None, None, None, None, None, None]
- record [YLEN] = len (py)
- i = 0
- for p in py[:4]:
- record[Y0 + i] = p.get_pinyin_id ()
- record[S0 + i] = p.get_sheng_mu_id ()
- i += 1
- if len (py) > 4:
- record[YX] = "'".join (map (str, py[4:]))
- record[PHRASE] = phrase
- record[FREQ] = freq
- record[USER_FREQ] = None
- self.db.execute (sqlstring % database, record)
- except Exception, e:
- print line, ":", phrase.encode ("utf-8"), pinyin, freq
- import traceback
- traceback.print_exc ()
- # print e
- line += 1
-
- self.flush (True)
-
- def get_pinyin_table (self):
- """get pinyin table"""
- try:
- return self._pinyin_table
- except:
- pass
-
- sql = "SELECT phrase, y0, s0 FROM py_phrase WHERE ylen = 1"
-
- pinyin_table = {}
- result = self.db.execute (sql % i)
- for phrase, y0, s0 in result:
- if phrase not in pinyin_table:
- pinyin_table [phrase] = []
- pinyin_table [phrase].append ((y0, s0))
- self._pinyin_table = pinyin_table
-
- return pinyin_table
-
- def select_words_by_pinyin_list (self, pys, mohu = False):
- """select words from database by list that contains pyutil.PinYinWord objects"""
-
- pinyin_string = u"'".join (map (str, pys))
- result = self.select_cache [pinyin_string]
- if result != None:
- return result
-
- tables_union = """( SELECT * FROM main.py_phrase WHERE %(conditions)s UNION ALL
- SELECT * FROM user_db.py_phrase WHERE %(conditions)s )"""
-
- if mohu:
- sql_conditions = ["+ylen = %d" % len (pys) ]
- else:
- sql_conditions = ["ylen = %d" % len (pys) ]
-
-
- i = 0
- if mohu == False:
- for py in pys[:4]:
- if py.is_valid_pinyin ():
- sql_conditions.append ("y%d = %d" % (i, py.get_pinyin_id ()))
- else:
- sql_conditions.append ("s%d = %d" % (i, py.get_sheng_mu_id ()))
- i += 1
- else:
- for py in pys[:4]:
- if py.is_valid_pinyin ():
- shengmu = py.get_shengmu ()
- yunmu = py.get_pinyin ()[len (shengmu):]
- if shengmu in pydict.MOHU_SHENGMU:
- shengmu_list = pydict.MOHU_SHENGMU[shengmu]
- else:
- shengmu_list = [shengmu]
-
- if yunmu in pydict.MOHU_YUNMU:
- yunmu_list = pydict.MOHU_YUNMU[yunmu]
- else:
- yunmu_list = [yunmu]
-
- pinyin_ids = []
- for s in shengmu_list:
- for y in yunmu_list:
- pinyin = s + y
- if pinyin in pydict.PINYIN_DICT:
- pinyin_ids.append (str (pydict.PINYIN_DICT[pinyin]))
- if len (pinyin_ids) > 1:
- sql_conditions.append ("y%d in (%s)" % (i, ",".join (pinyin_ids)))
- else:
- sql_conditions.append ("y%d == %s" % (i, pinyin_ids[0]))
-
- else:
- shengmu = py.get_shengmu ()
- if shengmu in pydict.MOHU_SHENGMU:
- shengmu_ids = []
- for s in pydict.MOHU_SHENGMU[shengmu]:
- shengmu_ids.append (str (pydict.SHENGMU_DICT[s]))
- sql_conditions.append ("s%d in (%s)" % (i, ",".join (shengmu_ids)))
- else:
- sql_conditions.append ("s%d = %d" % (i, py.get_sheng_mu_id ()))
- i += 1
-
- if pys[4:]:
- pp = lambda (x): x.get_pattern (mohu)
- pattern = "'".join (map (pp, pys[4:]))
- sql_conditions.append ("yx LIKE \"" + pattern + "\"")
-
-
- tables_union = tables_union % { "conditions" : " AND ".join (sql_conditions) }
- sql_prefix = "SELECT * FROM " + tables_union
-
- sql_string = sql_prefix + " GROUP BY phrase ORDER BY user_freq DESC, freq DESC;"
-
- result = list (self.db.execute (sql_string).fetchall ())
-
- self.select_cache [pinyin_string] = result
-
- return result
-
- def select_words_by_pinyin_string (self, string, mohu = False):
- """select words from the database by pinyin string"""
-
- pys = self.parser.parse (string)
- result = self.select_words_by_pinyin_list (pys, mohu)
- return result
-
- def commit_phrases (self, records):
- """this function adjusts frequence of phrase in user database."""
-
- for record in records:
- if record [USER_FREQ] != None:
- sql = "UPDATE user_db.py_phrase SET user_freq = user_freq + 1 WHERE ylen = ? AND y0 = ? AND phrase = ?;"
- self.db.execute (sql, (record[YLEN], record[Y0], record[PHRASE]))
- else:
- sql = """INSERT INTO user_db.py_phrase (ylen, y0, y1, y2, y3, yx, s0, s1, s2, s3, phrase, freq, user_freq)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1);"""
- self.db.execute (sql, record[:12])
- self.flush ()
- self.select_cache.clear ()
-
- def commit_phrase (self, record):
- self.commit_phrases ([record])
-
- def commit_char (self, char, pinyin_id, shengmu_id):
- sql = "SELECT * FROM main.py_phrase WHERE ylen = 1 AND y0 = ? AND phrase = ?"
- records = self.db.execute (sql, (pinyin_id, char)).fetchall ()
- self.commit_phrases (records)
-
- def new_phrase (self, phrases, freq = None, user_freq = 1):
- """this function create a new phrase from a phrase list and put it into user database."""
- pinyin_ids = []
- shengmu_ids = []
- phrase = u""
- phrase_length = 0
- for p in phrases:
- if phrase_length + p[YLEN] > 8:
- break
- phrase += p[PHRASE]
- phrase_length += p[YLEN]
- if p[YLEN] > 4:
- ys = p[YX].split ("'")
- for i in range (0, p[YLEN]):
- if i < 4:
- pinyin_ids.append (p[Y0 + i])
- shengmu_ids.append (p[S0 + i])
- else:
- w = pyutil.PinYinWord (ys[i - 4])
- pinyin_ids.append (w.get_pinyin_id ())
- shengmu_ids.append (w.get_sheng_mu_id ())
-
- sql = """INSERT INTO user_db.py_phrase
- (ylen, y0, y1, y2, y3, yx, s0, s1, s2, s3, phrase, freq, user_freq)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"""
-
- values = [phrase_length, None, None, None, None, None, None, None, None, None, phrase, freq, user_freq]
-
- if phrase_length <=4:
- values[1: 1 + phrase_length] = pinyin_ids [:phrase_length]
- values[6: 6 + phrase_length] = shengmu_ids [:phrase_length]
- else:
- values[1: 5] = pinyin_ids [:4]
- values[6: 10] = shengmu_ids [:4]
- get_pinyin = lambda id: pydict.ID_PINYIN_DICT[id]
- values[5] = "'".join (map (get_pinyin, pinyin_ids[4:]))
-
- self.db.execute (sql, values)
-
- self.flush ()
- self.select_cache.clear ()
-
- def remove_phrase (self, record):
- "Remove phrase from user database"
-
- sql = "DELETE FROM user_db.py_phrase WHERE ylen = ? AND y0 = ? AND phrase = ?"
-
- self.db.execute (sql, (record[YLEN], record[Y0], record[PHRASE]))
-
- self.flush ()
- self.select_cache.clear ()
-
- def flush (self, force = False):
- if self._last_flush_time == None:
- self._last_flush_time = time.time ()
- if force or time.time() - self._last_flush_time >= FLUSH_PERIOD:
- self.db.commit ()
- self._last_flush_time = time.time ()
-
-
-class Cache:
- """cache object for cache history queries"""
-
- class Slot:
- """Slot item of cache object"""
- def __init__ (self):
- self.time = -1
- self.value = None
- self.index = None
-
- def __init__ (self, max_slot = 1024):
- self._max_slot = max_slot
- self.clear ()
-
- def clear (self):
- self._slots = []
- self._dict = {}
- self._time = 0
-
- def __delitem__ (self, index):
- if not self._dict.has_key (index):
- return None
- del self._dict [index]
-
- def __getitem__ (self, index):
- """return a vale associate with the giving index. It cache does not has this index,
- it will retrun None."""
- if not self._dict.has_key (index):
- return None
-
- slot = self._dict [index]
- self._time += 1
- slot.time = self._time
- return slot.value
-
- def __setitem__ (self, index, value):
- if self._dict.has_key (index):
- slot = self._dict[index]
- else:
- slot = self.get_slot ()
- self._time += 1
- slot.value = value
- slot.time = self._time
- slot.index = index
- self._dict[index] = slot
-
- def get_slot (self):
- """get_slot will return a empty slot. If there is not any empty slot
- it will find the oldest slot and return it."""
- if len (self._slots) < self._max_slot:
- slot = Cache.Slot ()
- self._slots.append (slot)
- else:
- self._slots.sort (lambda x,y : x.time - y.time)
- slot = self._slots[0]
- del self._dict[slot.index]
- return slot
-
-def get_database_desc (db_file):
- if not path.exists (db_file):
- raise Exception ("%s does not exist!" % dbname)
- try:
- desc = {}
- db = sqlite.connect (db_file)
- for row in db.executescript ("SELECT * FROM desc;"):
- desc [row[0]] = row[1]
- return desc
- except:
- return None
-
-def test_select_words ():
- import time
-
- db = PYSQLiteDB ()
- while True:
- l = raw_input ().strip ()
- if not l:
- break
- t = time.time ()
- res = db.select_words_by_pinyin_string (l)
-
- t = time.time () - t
-
- i = 0
- for p in res:
- print "%s = %s %s " % (i, str (p), p[PHRASE].encode ("utf8"))
- i += 1
- print "OK t =", t, " count =", len (res)
- while True:
- try:
- commit = int (raw_input ("commit = ").strip ())
- db.commit_phrase (res[commit])
- except KeyboardInterrupt, e:
- print "Exit"
- sys.exit (0)
- except:
- print "Input is invalidate"
- continue
- break
-
-
-
-def test_case (string):
- db = PYSQLiteDB ()
- parser = pyparser.PinYinParser ()
- pys = parser.parse (string)
-
- result = u""
-
- while len (result) != len (pys):
- pps = pys[len (result):]
- for x in range (len (pps), 0, -1):
- candidates = db.select_words_by_pinyin_list (pps[:x])
- if candidates:
- result += candidates[0][PHRASE]
- break
- print "'".join (map (str, pys))
- print result
-
-def test ():
- test_case ("gaodangfangdichankaifashangdedongtianjiuyaolaile")
- test_case ("huanyingshiyongwokaifadezhinengpinyinshurufa")
- test_case ("beijingshirenminzhengfujuedingzaitongzhouqujianlizhengfuxingzhengjidi")
- test_case ("woguojuminshoumingqiwangtigaodaoqishisansui")
- test_case ("wgjmshmqwtgdqshss")
- test_case ("xjinyhuiyouyongme")
-
-if __name__ == "__main__":
- import timeit
- t = timeit.Timer ("pysqlitedb.test ()", "import pysqlitedb")
- print t.repeat (3,1)
-
diff --git a/engine/special_phrase b/engine/special_phrase
deleted file mode 100644
index b1076f6..0000000
--- a/engine/special_phrase
+++ /dev/null
@@ -1,18 +0,0 @@
-# py phrase
-hehe :-)
-haha ^_^
-haha o(∩_∩)o...哈哈
-xixi (*^__^*) 嘻嘻……
-bsn ╭∩╮(︶︿︶)╭∩╮鄙视你!
-rq #%(year)d年%(month)d月%(day)d日
-rq #%(year)d-%(month)d-%(day)d
-sj #%(hour_24)d时%(minute)d分%(second)d秒
-sj #%(hour_24)d:%(minute)d:%(second)d
-xq #星期%(week1)s
-xq #星期%(week2)s
-xq #礼拜%(week1)s
-xq #礼拜%(week2)s
-lb #礼拜%(week1)s
-lb #礼拜%(week2)s
-lb #星期%(week1)s
-lb #星期%(week2)s
diff --git a/engine/specialphrase.py b/engine/specialphrase.py
deleted file mode 100644
index 5f2ac6c..0000000
--- a/engine/specialphrase.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# vim: set noet ts=4:
-# -*- coding: utf-8 -*-
-#
-# scim-python
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
-#
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this program; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
-# Boston, MA 02111-1307 USA
-#
-# $Id: $
-#
-import os.path
-import time
-
-class SpecialPhrase:
- _dict = None
- def __init__ (self):
- if SpecialPhrase._dict == None:
- self._load_table ()
- SpecialPhrase._dict = self._dict
- else:
- self._dict = SpecialPhrase._dict
-
- def _load_table (self):
- self._dict = {}
- name = os.path.join (os.getenv("IBUS_PINYIN_LOCATION"), "engine", "special_phrase")
- for l in file (name):
- l = l.strip ()
- if l == "" or l[0] == "#":
- continue
- py, phrase = l.split ("\t")
- phrase = unicode (phrase, "utf8")
- if py not in self._dict:
- self._dict[py] = []
- self._dict[py].append (phrase)
-
- def lookup (self, py):
- result = []
- now = time.localtime ()
- weeks1 = (u"一", u"二", u"三", u"四", u"五", u"六", u"日")
- weeks2 = (u"一", u"二", u"三", u"四", u"五", u"六", u"天")
- values = {
- "year" : now[0],
- "month" : now[1],
- "day" : now[2],
- "hour_24" : now[3],
- "minute" : now[4],
- "second" : now[5],
- "week1" : weeks1[now[6]],
- "week2" : weeks2[now[6]],
- }
- if py in self._dict:
- for phrase in self._dict[py]:
- if phrase[0] == "#":
- phrase = phrase[1:] % values
- if phrase not in result:
- result.append (phrase)
- return result
-
-if __name__ == "__main__":
- SpecialPhrase ()._load_table ()
-
diff --git a/engine/specialtable.py b/engine/specialtable.py
deleted file mode 100644
index cdabbe0..0000000
--- a/engine/specialtable.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# vim: set noet ts=4:
-#
-# scim-python
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
-#
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this program; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
-# Boston, MA 02111-1307 USA
-#
-# $Id: $
-#
-import os.path
-import time
-
-class SpecialTable:
- _dict = None
- def __init__ (self):
- if SpecialTable._dict == None:
- self._load_table ()
-
- def _load_table (self):
- _dict = {}
- def parse_table (name, _dict):
- if not os.path.isfile (name):
- return
- for l in file (name):
- l = l.strip ()
- if l == "" or l[0] == "#":
- continue
- key, values = l.decode ("utf8").split (u"=")
- key = key.strip ()
- values = map (lambda x: x.decode ("utf8"), eval (values + u","))
- if key not in _dict:
- _dict[key] = []
- _dict[key] += list (values)
- name = os.path.join (os.getenv("IBUS_PINYIN_LOCATION"), "engine", "special_table")
- try:
- parse_table (name, _dict)
- except Exception, e:
- print e
- name = os.path.expanduser ("~/.scim/scim-python/pinyin/special_table")
- try:
- parse_table (name, _dict)
- except Exception, e:
- print e
- SpecialTable._dict = _dict
-
- def lookup (self, key):
- if key in SpecialTable._dict:
- return SpecialTable._dict[key][:]
- keys = SpecialTable._dict.keys ()
- keys = filter (lambda k: k.startswith(key), keys)
- if len (keys) == 1:
- return SpecialTable._dict.get (keys[0], [])[:]
- else:
- return []
-
-if __name__ == "__main__":
- SpecialTable ()._load_table ()
- print SpecialTable._dict
-
diff --git a/ibus-pinyin.spec.in b/ibus-pinyin.spec.in
index d3648a3..fca54f4 100644
--- a/ibus-pinyin.spec.in
+++ b/ibus-pinyin.spec.in
@@ -1,26 +1,32 @@
Name: @PACKAGE_NAME@
Version: @PACKAGE_VERSION@
Release: 1%{?dist}
-Summary: The PinYin engine for IBus platform
+Summary: The Chinese Pinyin engine 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://scim-python.googlecode.com/files/pinyin-database-0.1.10.6.tar.bz2
+Source1: pinyin-database-1.2.99.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-BuildArch: noarch
BuildRequires: gettext-devel
+BuildRequires: libtool
+BuildRequires: pkgconfig
+BuildRequires: sqlite-devel
+BuildRequires: libuuid-devel
+BuildRequires: ibus-devel >= 1.2.0
-Requires: ibus
+Requires(post): sqlite
+
+Requires: ibus >= 1.2.0
%description
-PinYin engine for IBus platform. It provides a Chinese PinYin input method.
+The Chinese Pinyin input method for IBus platform.
%prep
%setup -q
-cp %{SOURCE1} engine
+cp %{SOURCE1} data
%build
%configure --disable-static
@@ -37,17 +43,17 @@ make DESTDIR=${RPM_BUILD_ROOT} NO_INDEX=true install
rm -rf $RPM_BUILD_ROOT
%post
-cd /usr/share/ibus-pinyin/engine
-python -c "import pysqlitedb; db = pysqlitedb.PYSQLiteDB (); db.create_indexes ();" >/dev/null
+cd %{_datadir}/ibus-pinyin/db
+sqlite3 main.db ".read create_index.sql"
%files -f %{name}.lang
%defattr(-,root,root,-)
%doc AUTHORS COPYING README
-%{_datadir}/ibus-pinyin
-%{_datadir}/ibus/component/*
%{_libexecdir}/ibus-engine-pinyin
%{_libexecdir}/ibus-setup-pinyin
+%{_datadir}/@PACKAGE@
+%{_datadir}/ibus/component/*
%changelog
-* Wed Jun 25 2008 Huang Peng <shawn.p.huang@gmail.com> - @VERSION@-1
+* Fri Aug 08 2008 Huang Peng <shawn.p.huang@gmail.com> - @VERSION@-1
- The first version.
diff --git a/po/LINGUAS b/po/LINGUAS
index 4caba33..22bdb91 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -1,3 +1,2 @@
-ja
zh_CN
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 17701be..e249584 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,12 +1,11 @@
-./engine/pydict.py
-./engine/main.py
-./engine/pysqlitedb.py
-./engine/specialtable.py
-./engine/pyparser.py
-./engine/pinyin.py
-./engine/pyutil.py
-./engine/specialphrase.py
-./engine/factory.py
-./setup/pydict.py
-./setup/main.py
-./setup/setup.glade
+src/Config.cc
+src/Database.cc
+src/Engine.cc
+src/HalfFullConverter.cc
+src/Main.cc
+src/PhraseEditor.cc
+src/PinyinEditor.cc
+src/PinyinEngine.cc
+src/PinyinParser.cc
+src/SpecialTable.cc
+setup/ibus-pinyin-preferences.glade
diff --git a/po/ja.po b/po/ja.po
deleted file mode 100644
index b72370d..0000000
--- a/po/ja.po
+++ /dev/null
@@ -1,245 +0,0 @@
-# Japanese translation of ibus-pinyin.
-# Copyright (C) 2008 Huang Peng <shawn.p.huang@gmail.com>
-# This file is distributed under the same license as the ibus-pinyin package.
-# UTUMI Hirosi <utuhiro78@yahoo.co.jp>, 2008.
-#
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: ibus-pinyin VERSION\n"
-"Report-Msgid-Bugs-To: http://code.google.com/p/ibus/issues/entry\n"
-"POT-Creation-Date: 2009-09-19 15:09+0800\n"
-"PO-Revision-Date: 2008-08-28 19:19+0900\n"
-"Last-Translator: UTUMI Hirosi <utuhiro78@yahoo.co.jp>\n"
-"Language-Team: Japanese <gnome-translation@gnome.gr.jp>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: engine/pydict.py:358 setup/pydict.py:358
-msgid "MSPY"
-msgstr "MSPY"
-
-#: engine/pydict.py:359 setup/pydict.py:359
-msgid "ZRM"
-msgstr "ZRM"
-
-#: engine/pydict.py:360 setup/pydict.py:360
-msgid "ABC"
-msgstr "ABC"
-
-#: engine/pydict.py:361 setup/pydict.py:361
-msgid "ZGPY"
-msgstr "ZGPY"
-
-#: engine/pydict.py:362 setup/pydict.py:362
-msgid "PYJJ"
-msgstr "PYJJ"
-
-#: engine/pinyin.py:155
-msgid "Configure PinYin"
-msgstr "ピンインを設定"
-
-#: engine/pinyin.py:162
-msgid "CN"
-msgstr "中"
-
-#: engine/pinyin.py:163
-msgid "Switch to English mode"
-msgstr "英語モードに切替"
-
-#: engine/pinyin.py:166
-msgid "EN"
-msgstr "英"
-
-#: engine/pinyin.py:167
-msgid "Switch to Chinese mode"
-msgstr "中国語モードに切替"
-
-#: engine/pinyin.py:172
-msgid "Switch to half letter mode"
-msgstr "半角文字モードに切替"
-
-#: engine/pinyin.py:176
-msgid "Switch to full letter mode"
-msgstr "全角文字モードに切替"
-
-#: engine/pinyin.py:181
-msgid "Switch to half punctuation mode"
-msgstr "半角句読点モードに切替"
-
-#: engine/pinyin.py:185
-msgid "Switch to full punctuation mode"
-msgstr "全角句読点モードに切替"
-
-#: engine/factory.py:33
-msgid "PinYin"
-msgstr "ピンイン"
-
-#: setup/main.py:216
-msgid "Are you sure to close Python PinYin Setup without save configure?"
-msgstr "設定を保存せずに Python ピンインセットアップを閉じますか?"
-
-#: setup/main.py:227
-msgid ""
-"The user phrases database will be reorganized! Please don't use python "
-"PinYin now."
-msgstr ""
-"ユーザーフレーズデータベースを再構築します。Python ピンインを使わないでくださ"
-"い"
-
-#: setup/main.py:249
-msgid "Reorganizing is over!"
-msgstr "再構築しました"
-
-#: setup/setup.glade:7
-msgid "Python PinYin Setup"
-msgstr "Python ピンインセットアップ"
-
-#: setup/setup.glade:43
-#, fuzzy
-msgid "Half punctuations"
-msgstr "半角句読点モードに切替"
-
-#: setup/setup.glade:54
-msgid "Press [u] or [v] to temporary English mode"
-msgstr "[u] か [v] で一時的な英語モード"
-
-#: setup/setup.glade:118 setup/setup.glade:132
-msgid "1\n"
-msgstr "1\n"
-
-#: setup/setup.glade:147
-msgid "English spelling check"
-msgstr "英語スペルのチェック"
-
-#: setup/setup.glade:158
-msgid "Wrong PinYin auto correct"
-msgstr "誤ったピンインの自動修正"
-
-#: setup/setup.glade:169
-msgid "Lookup table page size"
-msgstr "ページ当たりの候補の数"
-
-#: setup/setup.glade:180
-msgid "ShuangPin Schema"
-msgstr "ShuangPin スキーマ"
-
-#: setup/setup.glade:191
-msgid "ShuangPin"
-msgstr "ShuangPin"
-
-#: setup/setup.glade:202
-msgid "Support GBK"
-msgstr "GBK をサポート"
-
-#: setup/setup.glade:243
-msgid "Press [shift] to select candidates"
-msgstr "[shift] で候補を選択"
-
-#: setup/setup.glade:271
-msgid "Press [-] [=] to page down up."
-msgstr "[-] [=] でページを切替"
-
-#: setup/setup.glade:333
-msgid "Auto commit"
-msgstr "自動確定"
-
-#: setup/setup.glade:344
-msgid "Press [,] [.] to page down up."
-msgstr "[,] [.] でページを切替"
-
-#: setup/setup.glade:356
-#, fuzzy
-msgid "General"
-msgstr "一般"
-
-#: setup/setup.glade:373
-msgid "Enable Fuzzy PinYin"
-msgstr "ファジーピンイン有効"
-
-#: setup/setup.glade:383
-msgid "s <=> sh"
-msgstr "s <=> sh"
-
-#: setup/setup.glade:398
-msgid "c <=> ch"
-msgstr "c <=> ch"
-
-#: setup/setup.glade:413
-msgid "z <=> zh"
-msgstr "z <=> zh"
-
-#: setup/setup.glade:428
-msgid "l <=> n"
-msgstr "l <=> n"
-
-#: setup/setup.glade:443
-msgid "in <=> ing"
-msgstr "in <=> ing"
-
-#: setup/setup.glade:460
-msgid "en <=> eng"
-msgstr "en <=> eng"
-
-#: setup/setup.glade:477
-msgid "an <=> ang"
-msgstr "an <=> ang"
-
-#: setup/setup.glade:547
-msgid "Fuzzy PinYin"
-msgstr "ファジーピンイン"
-
-#: setup/setup.glade:567
-msgid "Color of Spelling Error"
-msgstr "スペルエラーの色"
-
-#: setup/setup.glade:578
-msgid "Color of English Candidates"
-msgstr "英語候補の色"
-
-#: setup/setup.glade:589
-msgid "Color of Special Phrases"
-msgstr "特殊語句の色"
-
-#: setup/setup.glade:600
-msgid "Color of User Phrases"
-msgstr "ユーザー語句の色"
-
-#: setup/setup.glade:611
-msgid "Color of New Phrases"
-msgstr "新規語句の色"
-
-#: setup/setup.glade:622
-msgid "Color of Normal Phrases"
-msgstr "一般語句の色"
-
-#: setup/setup.glade:745
-msgid "Colors"
-msgstr "配色"
-
-#: setup/setup.glade:784
-msgid "Optimize User DB"
-msgstr "ユーザーDBを最適化"
-
-#: setup/setup.glade:858
-msgid "User DB"
-msgstr "ユーザーDB"
-
-#: setup/setup.glade:869
-msgid ""
-"Python PinYin\n"
-"\n"
-"provided by\n"
-"\n"
-"Huang Peng <shawn.p.huang@gmail.com>\n"
-msgstr ""
-"Python PinYin\n"
-"\n"
-"provided by\n"
-"\n"
-"Huang Peng <shawn.p.huang@gmail.com>\n"
-
-#: setup/setup.glade:883
-msgid "About"
-msgstr "About"
diff --git a/po/zh_CN.gmo b/po/zh_CN.gmo
new file mode 100644
index 0000000..a0147ff
--- /dev/null
+++ b/po/zh_CN.gmo
Binary files differ
diff --git a/po/zh_CN.po b/po/zh_CN.po
index a6efd4c..b62e0b9 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -1,235 +1,166 @@
-# Translation for ibus-pinyin
+# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Huang Peng <shawn.p.huang@gmail.com>
-# This file is distributed under the same license as the ibus-pinyin package.
-# Huang Peng <shawn.p.huang@gmail.com>, 2008.
+# This file is distributed under the same license as the PACKAGE package.
+# Huang Peng <shawn.p.huang@gmail.com>, 2009.
#
msgid ""
msgstr ""
-"Project-Id-Version: 0.1.1.20080813\n"
+"Project-Id-Version: ibus-pinyin 1.3.0\n"
"Report-Msgid-Bugs-To: http://code.google.com/p/ibus/issues/entry\n"
-"POT-Creation-Date: 2009-09-19 15:09+0800\n"
-"PO-Revision-Date: 2008-08-13 22:52+0800\n"
-"Last-Translator: Huang Peng <shawn.p.huang@gmail.com>\n"
-"Language-Team: Huang Peng <shawn.p.huang@gmail.com>\n"
+"POT-Creation-Date: 2009-09-22 17:10+0800\n"
+"PO-Revision-Date: 2009-09-20 16:05+8\n"
+"Last-Translator: Peng Huang <shawn.p.huang@gmail.com>\n"
+"Language-Team: Peng Huang <shawn.p.huang@gmail.com>\n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: engine/pydict.py:358 setup/pydict.py:358
-msgid "MSPY"
-msgstr "微软拼音"
+#: src/Main.cc:50 src/Main.cc:59 src/Main.cc:60
+msgid "Pinyin input method"
+msgstr "拼音输入法"
-#: engine/pydict.py:359 setup/pydict.py:359
-msgid "ZRM"
-msgstr "自然码"
+#: src/PinyinEngine.cc:44 setup/ibus-pinyin-preferences.glade:188
+msgid "Chinese"
+msgstr "中文"
-#: engine/pydict.py:360 setup/pydict.py:360
-msgid "ABC"
-msgstr "智能ABC"
+#: src/PinyinEngine.cc:57
+msgid "Full/Half width"
+msgstr "全角/半角"
-#: engine/pydict.py:361 setup/pydict.py:361
-msgid "ZGPY"
-msgstr "紫光拼音"
+#: src/PinyinEngine.cc:70
+msgid "Full/Half width punctuation"
+msgstr "半角符号"
-#: engine/pydict.py:362 setup/pydict.py:362
-msgid "PYJJ"
-msgstr "拼音加加"
-
-#: engine/pinyin.py:155
-msgid "Configure PinYin"
+#: src/PinyinEngine.cc:79 src/PinyinEngine.cc:81
+#: setup/ibus-pinyin-preferences.glade:7
+msgid "Pinyin preferences"
msgstr "拼音设置"
-#: engine/pinyin.py:162
-msgid "CN"
-msgstr "中"
-
-#: engine/pinyin.py:163
-msgid "Switch to English mode"
-msgstr "切换到英语"
-
-#: engine/pinyin.py:166
-msgid "EN"
-msgstr "英"
-
-#: engine/pinyin.py:167
-msgid "Switch to Chinese mode"
-msgstr "切换到中文"
-
-#: engine/pinyin.py:172
-msgid "Switch to half letter mode"
-msgstr "字母切换到半角"
+#: setup/ibus-pinyin-preferences.glade:51
+msgid "Full pinyin"
+msgstr "全拼"
-#: engine/pinyin.py:176
-msgid "Switch to full letter mode"
-msgstr "字母切换到全角"
-
-#: engine/pinyin.py:181
-msgid "Switch to half punctuation mode"
-msgstr "标点切换到半角"
-
-#: engine/pinyin.py:185
-msgid "Switch to full punctuation mode"
-msgstr "标点切换到全角"
+#: setup/ibus-pinyin-preferences.glade:65
+msgid "Double pinyin"
+msgstr "双拼"
-#: engine/factory.py:33
-msgid "PinYin"
-msgstr "拼音"
+#: setup/ibus-pinyin-preferences.glade:79
+msgid "Simple pinyin"
+msgstr "简拼"
-#: setup/main.py:216
-msgid "Are you sure to close Python PinYin Setup without save configure?"
-msgstr ""
+#: setup/ibus-pinyin-preferences.glade:99
+msgid "Schema:"
+msgstr "双拼方案:"
-#: setup/main.py:227
-msgid ""
-"The user phrases database will be reorganized! Please don't use python "
-"PinYin now."
-msgstr "准备优化用户词库,请不要使用拼音输入法!"
+#: setup/ibus-pinyin-preferences.glade:132
+msgid "<b>Pinyin</b>"
+msgstr "<b>拼音</b>"
-#: setup/main.py:249
-msgid "Reorganizing is over!"
-msgstr "优化完毕!"
+#: setup/ibus-pinyin-preferences.glade:161
+msgid "Language:"
+msgstr "语言:"
-#: setup/setup.glade:7
-msgid "Python PinYin Setup"
-msgstr "拼音设置"
+#: setup/ibus-pinyin-preferences.glade:168
+msgid "Half/full with:"
+msgstr "全角/半角:"
-#: setup/setup.glade:43
-msgid "Half punctuations"
-msgstr "半角标点"
+#: setup/ibus-pinyin-preferences.glade:179
+msgid "Half/full punctuation:"
+msgstr "全角/半角标点:"
-#: setup/setup.glade:54
-msgid "Press [u] or [v] to temporary English mode"
-msgstr "使用[u]或者[v]自动进入临时英语模式"
+#: setup/ibus-pinyin-preferences.glade:203
+msgid "English"
+msgstr "英文"
-#: setup/setup.glade:118 setup/setup.glade:132
-msgid "1\n"
-msgstr ""
+#: setup/ibus-pinyin-preferences.glade:216
+#: setup/ibus-pinyin-preferences.glade:248
+msgid "Full"
+msgstr "全角"
-#: setup/setup.glade:147
-msgid "English spelling check"
-msgstr "英语单词拼写检查"
+#: setup/ibus-pinyin-preferences.glade:233
+#: setup/ibus-pinyin-preferences.glade:264
+msgid "Half"
+msgstr "半角"
-#: setup/setup.glade:158
-msgid "Wrong PinYin auto correct"
-msgstr "自动纠正错误拼音"
+#: setup/ibus-pinyin-preferences.glade:285
+msgid "<b>Initial state</b>"
+msgstr "<b>初始状态</b>"
-#: setup/setup.glade:169
-msgid "Lookup table page size"
-msgstr "候选词个数"
+#: setup/ibus-pinyin-preferences.glade:316
+msgid "Number of candidates:"
+msgstr "每页候选词个数:"
-#: setup/setup.glade:180
-msgid "ShuangPin Schema"
-msgstr "双拼方案"
+#: setup/ibus-pinyin-preferences.glade:335
+msgid "Press [Shift] key to select candidate"
+msgstr "按[Shift]键选词"
-#: setup/setup.glade:191
-msgid "ShuangPin"
-msgstr "双拼"
+#: setup/ibus-pinyin-preferences.glade:350
+msgid "Press [-] [=] key to flip page"
+msgstr "按[-][=]键翻页"
-#: setup/setup.glade:202
-msgid "Support GBK"
-msgstr "大字符集"
+#: setup/ibus-pinyin-preferences.glade:365
+msgid "Press [,] [.] key to flip page"
+msgstr "按[,][.]键翻页"
-#: setup/setup.glade:243
-msgid "Press [shift] to select candidates"
-msgstr "按 [shift] 选词"
+#: setup/ibus-pinyin-preferences.glade:380
+msgid "Auto commit phrase"
+msgstr "自动上词"
-#: setup/setup.glade:271
-msgid "Press [-] [=] to page down up."
-msgstr "按 [-] [=] 上下翻页。"
+#: setup/ibus-pinyin-preferences.glade:397
+msgid "Half width punctuations:"
+msgstr "半角符号:"
-#: setup/setup.glade:333
-msgid "Auto commit"
-msgstr "自动上词"
+#: setup/ibus-pinyin-preferences.glade:410
+msgid "+-*/=%"
+msgstr "+-*/=%"
-#: setup/setup.glade:344
-msgid "Press [,] [.] to page down up."
-msgstr "按 [,] [.] 上下翻页。"
+#: setup/ibus-pinyin-preferences.glade:426
+msgid "<b>Others</b>"
+msgstr "<b>其他</b>"
-#: setup/setup.glade:356
+#: setup/ibus-pinyin-preferences.glade:443
msgid "General"
msgstr "常规"
-#: setup/setup.glade:373
-msgid "Enable Fuzzy PinYin"
-msgstr "启动模糊拼音"
-
-#: setup/setup.glade:383
-msgid "s <=> sh"
-msgstr ""
-
-#: setup/setup.glade:398
-msgid "c <=> ch"
-msgstr ""
-
-#: setup/setup.glade:413
-msgid "z <=> zh"
-msgstr ""
-
-#: setup/setup.glade:428
-msgid "l <=> n"
-msgstr ""
-
-#: setup/setup.glade:443
-msgid "in <=> ing"
-msgstr ""
-
-#: setup/setup.glade:460
-msgid "en <=> eng"
-msgstr ""
+#: setup/ibus-pinyin-preferences.glade:463
+#: setup/ibus-pinyin-preferences.glade:595
+msgid "Correct pinyin"
+msgstr "拼音纠错"
-#: setup/setup.glade:477
-msgid "an <=> ang"
-msgstr ""
+#: setup/ibus-pinyin-preferences.glade:575
+msgid "<b>Correct pinyin</b>"
+msgstr "<b>拼音纠错</b>"
-#: setup/setup.glade:547
-msgid "Fuzzy PinYin"
+#: setup/ibus-pinyin-preferences.glade:616
+#: setup/ibus-pinyin-preferences.glade:1037
+msgid "Fuzzy pinyin"
msgstr "模糊拼音"
-#: setup/setup.glade:567
-msgid "Color of Spelling Error"
-msgstr "错误拼写英文单词的颜色"
-
-#: setup/setup.glade:578
-msgid "Color of English Candidates"
-msgstr "英文单词的颜色"
-
-#: setup/setup.glade:589
-msgid "Color of Special Phrases"
-msgstr "特殊词语的颜色"
-
-#: setup/setup.glade:600
-msgid "Color of User Phrases"
-msgstr "用户自造词的颜色"
-
-#: setup/setup.glade:611
-msgid "Color of New Phrases"
-msgstr "系统自动生成的新候选词的颜色"
+#: setup/ibus-pinyin-preferences.glade:1017
+msgid "<b>Fuzzy pinyin</b>"
+msgstr "<b>模糊拼音</b>"
-#: setup/setup.glade:622
-msgid "Color of Normal Phrases"
-msgstr "普通候选词的颜色"
+#: setup/ibus-pinyin-preferences.glade:1074
+msgid "<big><b>IBus Pinyin 1.3.0</b></big>"
+msgstr "<big><b>IBus Pinyin 1.3.0</b></big>"
-#: setup/setup.glade:745
-msgid "Colors"
-msgstr "颜色"
+#: setup/ibus-pinyin-preferences.glade:1085
+msgid "Pinyin input method for IBus"
+msgstr "Pinyin input method for IBus"
-#: setup/setup.glade:784
-msgid "Optimize User DB"
-msgstr "优化用户词库"
-
-#: setup/setup.glade:858
-msgid "User DB"
-msgstr "用户词库"
-
-#: setup/setup.glade:869
+#: setup/ibus-pinyin-preferences.glade:1095
msgid ""
-"Python PinYin\n"
-"\n"
-"provided by\n"
-"\n"
-"Huang Peng <shawn.p.huang@gmail.com>\n"
+"<small>Copyright (c) 2009 Huang Peng &lt;shawn.p.huang@gmail.com&gt;</small>"
msgstr ""
+"<small>Copyright (c) 2009 Huang Peng &lt;shawn.p.huang@gmail.com&gt;</small>"
-#: setup/setup.glade:883
+#: setup/ibus-pinyin-preferences.glade:1105
+msgid "http://ibus.googlecode.com"
+msgstr "http://ibus.googlecode.com"
+
+#: setup/ibus-pinyin-preferences.glade:1135
msgid "About"
msgstr "关于"
+
+#~ msgid "gtk-close"
+#~ msgstr "gtk-close"
diff --git a/setup/Makefile.am b/setup/Makefile.am
index 4a4b53a..a83dcb3 100644
--- a/setup/Makefile.am
+++ b/setup/Makefile.am
@@ -19,9 +19,8 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
setup_pinyin_PYTHON = \
- pydict.py \
main.py \
- setup.glade \
+ ibus-pinyin-preferences.glade \
$(NULL)
setup_pinyindir = $(datadir)/ibus-pinyin/setup
diff --git a/setup/ibus-pinyin-preferences.glade b/setup/ibus-pinyin-preferences.glade
new file mode 100644
index 0000000..95eefd9
--- /dev/null
+++ b/setup/ibus-pinyin-preferences.glade
@@ -0,0 +1,1239 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkDialog" id="dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Pinyin preferences</property>
+ <property name="icon_name">gtk-preferences</property>
+ <property name="type_hint">normal</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkNotebook" id="notebook1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkAlignment" id="alignment5">
+ <property name="visible">True</property>
+ <property name="top_padding">12</property>
+ <property name="bottom_padding">12</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox4">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment6">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table2">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="FullPinyin">
+ <property name="label" translatable="yes">Full pinyin</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">DoublePinyin</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="DoublePinyin">
+ <property name="label" translatable="yes">Double pinyin</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="SimplePinyin">
+ <property name="label" translatable="yes">Simple pinyin</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="labelDoublePinyinSchema">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Schema:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="DoublePinyinSchema">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="model">liststoreDoublePinyin</property>
+ <property name="button_sensitivity">on</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Pinyin&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame4">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment7">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table4">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">3</property>
+ <child>
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Language:</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Half/full with:</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Half/full punctuation:</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="InitChinese">
+ <property name="label" translatable="yes">Chinese</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">InitEnglish</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="InitEnglish">
+ <property name="label" translatable="yes">English</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="InitFull">
+ <property name="label" translatable="yes">Full</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">InitHalf</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="InitHalf">
+ <property name="label" translatable="yes">Half</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="InitFullPunct">
+ <property name="label" translatable="yes">Full</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">InitHalfPunct</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="InitHalfPunct">
+ <property name="label" translatable="yes">Half</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Initial state&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame5">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment8">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table3">
+ <property name="visible">True</property>
+ <property name="n_rows">6</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label16">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Number of candidates:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="LookupTablePageSize">
+ <property name="visible">True</property>
+ <property name="model">liststorePageSize</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ShiftSelectCandidate">
+ <property name="label" translatable="yes">Press [Shift] key to select candidate</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="MinusEqualPage">
+ <property name="label" translatable="yes">Press [-] [=] key to flip page</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CommaPeriodPage">
+ <property name="label" translatable="yes">Press [,] [.] key to flip page</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="AutoCommit">
+ <property name="label" translatable="yes">Auto commit phrase</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label17">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Half width punctuations:</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="HalfWidthPuncts">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">&#x25CF;</property>
+ <property name="text" translatable="yes">+-*/=%</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Others&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">General</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="top_padding">12</property>
+ <property name="bottom_padding">12</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="CorrectPinyin">
+ <property name="label" translatable="yes">Correct pinyin</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment4">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="CorrectPinyin_GN_NG">
+ <property name="label">gn =&gt; ng</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CorrectPinyin_MG_NG">
+ <property name="label">mg =&gt; ng</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CorrectPinyin_IOU_IU">
+ <property name="label">iou =&gt; iu</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CorrectPinyin_UEI_UI">
+ <property name="label">uei =&gt; ui</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CorrectPinyin_UEN_UN">
+ <property name="label">uen =&gt; un</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CorrectPinyin_VE_UE">
+ <property name="label">ve =&gt; ue</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Correct pinyin&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Correct pinyin</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="top_padding">12</property>
+ <property name="bottom_padding">12</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin">
+ <property name="label" translatable="yes">Fuzzy pinyin</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">12</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_C_CH">
+ <property name="label">c =&gt; ch</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_Z_ZH">
+ <property name="label">z =&gt; zh</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_S_SH">
+ <property name="label">s =&gt; sh</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_L_N">
+ <property name="label">l =&gt; n</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_F_H">
+ <property name="label">f =&gt; h</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_L_R">
+ <property name="label">l =&gt; r</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_K_G">
+ <property name="label">k =&gt; g</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_AN_ANG">
+ <property name="label">an =&gt; ang</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_EN_ENG">
+ <property name="label">en =&gt; eng</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_IN_ING">
+ <property name="label">in =&gt; ing</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">9</property>
+ <property name="bottom_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_CH_C">
+ <property name="label">ch =&gt; c</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_ZH_Z">
+ <property name="label">zh =&gt; z</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_SH_S">
+ <property name="label">sh =&gt; s</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_N_L">
+ <property name="label">n =&gt; l</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_H_F">
+ <property name="label">h =&gt; f</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_R_L">
+ <property name="label">r =&gt; l</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_G_K">
+ <property name="label">g =&gt; k</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_ANG_AN">
+ <property name="label">ang =&gt; an</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_ENG_EN">
+ <property name="label">eng =&gt; en</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_ING_IN">
+ <property name="label">ing =&gt; in</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">9</property>
+ <property name="bottom_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_UAN_UANG">
+ <property name="label">uan =&gt; uang</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">11</property>
+ <property name="bottom_attach">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_UANG_UAN">
+ <property name="label">uang =&gt; uan</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">11</property>
+ <property name="bottom_attach">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_IAN_IANG">
+ <property name="label">ian =&gt; iang</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">10</property>
+ <property name="bottom_attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="FuzzyPinyin_IANG_IAN">
+ <property name="label">iang =&gt; ian</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">10</property>
+ <property name="bottom_attach">11</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Fuzzy pinyin&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Fuzzy pinyin</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment9">
+ <property name="visible">True</property>
+ <property name="yscale">0.30000001192092896</property>
+ <property name="top_padding">12</property>
+ <property name="bottom_padding">12</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox6">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkVBox" id="vbox7">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="pixel_size">48</property>
+ <property name="icon_name">gtk-about</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;big&gt;&lt;b&gt;IBus Pinyin 1.3.0&lt;/b&gt;&lt;/big&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Pinyin input method for IBus</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;small&gt;Copyright (c) 2009 Huang Peng &amp;lt;shawn.p.huang@gmail.com&amp;gt;&lt;/small&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLinkButton" id="linkbutton1">
+ <property name="label" translatable="yes">http://ibus.googlecode.com</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="relief">none</property>
+ <property name="uri">http://ibus.googlecode.com</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">About</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="buttonClose">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">buttonClose</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkListStore" id="liststoreDoublePinyin">
+ <columns>
+ <!-- column-name schema -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">MSPY</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">ZRM</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">ABC</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">ZGPY</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">PYJJ</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="liststorePageSize">
+ <columns>
+ <!-- column-name pageSize -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">1</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">3</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">4</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">5</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">6</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">7</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">8</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">9</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">10</col>
+ </row>
+ </data>
+ </object>
+</interface>
diff --git a/setup/ibus-setup-pinyin.in b/setup/ibus-setup-pinyin.in
index a7eb522..27c700c 100644
--- a/setup/ibus-setup-pinyin.in
+++ b/setup/ibus-setup-pinyin.in
@@ -25,5 +25,6 @@ datarootdir=@datarootdir@
export IBUS_PREFIX=@prefix@
export IBUS_DATAROOTDIR=@datarootdir@
export IBUS_LOCALEDIR=@localedir@
-exec python @prefix@/share/ibus-pinyin/setup/main.py $@
+cd @prefix@/share/ibus-pinyin/setup/
+exec python main.py $@
diff --git a/setup/main.py b/setup/main.py
index 7f17f83..6396117 100644
--- a/setup/main.py
+++ b/setup/main.py
@@ -1,284 +1,225 @@
-# vim:set et sts=4 sw=4:
-#
-# ibus-pinyin - The PinYin engine for IBus
-#
-# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
-
-import sys
-from os import path
-import os
-import signal
-import gobject
import gtk
-import gtk.gdk as gdk
-import gtk.glade as glade
import ibus
-import gettext
import locale
-from pydict import SHUANGPIN_SCHEMAS
-
-from gettext import dgettext
-_ = lambda a : dgettext("ibus-pinyin", a)
-
-RGB_COLOR = lambda c : ((c.red & 0xff00) << 8) + (c.green & 0xff00) + ((c.blue & 0xff00) >> 8)
-GDK_COLOR = lambda c : gdk.Color(((c >> 16) & 0xff) * 256, ((c >> 8) & 0xff) * 256, (c & 0xff) * 256)
-RGB = lambda r, g, b : ((r & 0xff) << 16) + ((g & 0xff) << 8) + (b & 0xff)
+import os
+import gettext
+class PreferencesDialog:
+ def __init__(self):
+ locale.setlocale(locale.LC_ALL, "")
+ localedir = os.getenv("IBUS_LOCALEDIR")
+ gettext.bindtextdomain("ibus-pinyin", localedir)
+ gettext.bind_textdomain_codeset("ibus-pinyin", "UTF-8")
-class SetupUI ():
- def __init__ (self):
- self.__need_reload_config = False
self.__bus = ibus.Bus()
self.__config = self.__bus.get_config()
-
- self.__options = {
- "SupportGBK" : [False, self.__checkbutton_op],
- "ShuangPin" : [False, self.__checkbutton_op],
- "AutoCorrect" : [True, self.__checkbutton_op],
-
- "FuzzyPinYin" : [False, self.__checkbutton_op],
- "FuzzyS_Sh" : [False, self.__checkbutton_op],
- "FuzzyC_Ch" : [False, self.__checkbutton_op],
- "FuzzyZ_Zh" : [False, self.__checkbutton_op],
- "FuzzyL_N" : [False, self.__checkbutton_op],
- "FuzzyIn_Ing" : [False, self.__checkbutton_op],
- "FuzzyEn_Eng" : [False, self.__checkbutton_op],
- "FuzzyAn_Ang" : [False, self.__checkbutton_op],
-
- "SpellCheck" : [True, self.__checkbutton_op],
- "UVToTemp" : [True, self.__checkbutton_op],
- "ShiftSelectCandidates" :
- [True, self.__checkbutton_op],
-
- "CommaPageDownUp" : [True, self.__checkbutton_op],
- "EqualPageDownUp" : [True, self.__checkbutton_op],
- "AutoCommit" : [False, self.__checkbutton_op],
-
- "PhraseColor" : [RGB (0, 0, 0), self.__colorbutton_op],
- "NewPhraseColor" : [RGB (0xef, 0, 0), self.__colorbutton_op],
- "UserPhraseColor" : [RGB (0, 0, 0xbf), self.__colorbutton_op],
- "SpecialPhraseColor" :
- [RGB (0, 0xbf, 0), self.__colorbutton_op],
- "EnglishPhraseColor" :
- [RGB (0, 0xbf, 0), self.__colorbutton_op],
- "ErrorEnglishPhraseColor" :
- [RGB (0xef, 0, 0), self.__colorbutton_op],
- "PageSize" : [5, self.__combobox_op, range(1, 10)],
- "ShuangPinSchema" : ["MSPY", self.__combobox_op, SHUANGPIN_SCHEMAS.keys()],
- "HalfPunctuations" : ["+-*/=%", self.__entry_op],
- }
+ self.__builder = gtk.Builder()
+ self.__builder.set_translation_domain("ibus-pinyin")
+ self.__builder.add_from_file("ibus-pinyin-preferences.glade")
+ self.__dialog = self.__builder.get_object("dialog")
+
+ self.__init_pinyin()
+ self.__init_init_state()
+ self.__init_others()
+ self.__init_correct_pinyin()
+ self.__init_fuzzy_pinyin()
+
+ def __init_pinyin(self):
+ # pinyin
+ self.__full_pinyin = self.__builder.get_object("FullPinyin")
+ self.__simple_pinyin = self.__builder.get_object("SimplePinyin")
+ self.__double_pinyin = self.__builder.get_object("DoublePinyin")
+ self.__double_pinyin_schema = self.__builder.get_object("DoublePinyinSchema")
+ self.__double_pinyin_schema_label = self.__builder.get_object("labelDoublePinyinSchema")
+
+ renderer = gtk.CellRendererText()
+ self.__double_pinyin_schema.pack_start(renderer)
+ self.__double_pinyin_schema.set_attributes(renderer, text=0)
+
+ # read value
+ self.__simple_pinyin.set_active(self.__get_value("SimplePinyin", True))
+ self.__full_pinyin.set_active(not self.__get_value("DoublePinyin", False))
+ self.__double_pinyin_schema.set_active(self.__get_value("DoublePinyinSchema", 0))
+ if self.__full_pinyin.get_active():
+ self.__simple_pinyin.set_sensitive(True)
+ self.__double_pinyin_schema.set_sensitive(False)
+ self.__double_pinyin_schema_label.set_sensitive(False)
+ else:
+ self.__simple_pinyin.set_sensitive(False)
+ self.__double_pinyin_schema.set_sensitive(True)
+ self.__double_pinyin_schema_label.set_sensitive(True)
+
+ def __full_pinyin_toggled_cb(widget):
+ val = widget.get_active()
+ self.__set_value("DoublePinyin", not val)
+ self.__simple_pinyin.set_sensitive(val)
+
+ def __double_pinyin_toggled_cb(widget):
+ val = widget.get_active()
+ self.__set_value("DoublePinyin", val)
+ self.__double_pinyin_schema.set_sensitive(val)
+ self.__double_pinyin_schema_label.set_sensitive(val)
+
+ def __double_pinyin_schema_changed_cb(widget):
+ self.__set_value("DoublePinyinSchema", widget.get_active())
+
+ # connect signals
+ self.__full_pinyin.connect("toggled", __full_pinyin_toggled_cb)
+ self.__double_pinyin.connect("toggled", __double_pinyin_toggled_cb)
+ self.__simple_pinyin.connect("toggled", self.__toggled_cb, "SimplePinyin")
+ self.__double_pinyin_schema.connect("changed", __double_pinyin_schema_changed_cb)
+
+ def __init_init_state(self):
+ # init state
+ self.__init_chinese = self.__builder.get_object("InitChinese")
+ self.__init_english = self.__builder.get_object("InitEnglish")
+ self.__init_full = self.__builder.get_object("InitFull")
+ self.__init_half = self.__builder.get_object("InitHalf")
+ self.__init_full_punct = self.__builder.get_object("InitFullPunct")
+ self.__init_half_punct = self.__builder.get_object("InitHalfPunct")
+
+ # read values
+ self.__init_chinese.set_active(self.__get_value("InitChinese", True))
+ self.__init_full.set_active(self.__get_value("InitFull", False))
+ self.__init_full_punct.set_active(self.__get_value("InitFullPunct", True))
+
+ # connect signals
+ self.__init_chinese.connect("toggled", self.__toggled_cb, "InitChinese")
+ self.__init_full.connect("toggled", self.__toggled_cb, "InitFull")
+ self.__init_full_punct.connect("toggled", self.__toggled_cb, "InitFullPunct")
+
+ def __init_others(self):
+ #others
+ self.__lookup_table_page_size = self.__builder.get_object("LookupTablePageSize")
+ renderer = gtk.CellRendererText()
+ self.__lookup_table_page_size.pack_start(renderer)
+ self.__lookup_table_page_size.set_attributes(renderer, text=0)
+
+ self.__shift_select_candidate = self.__builder.get_object("ShiftSelectCandidate")
+ self.__minus_equal_page = self.__builder.get_object("MinusEqualPage")
+ self.__comma_period_page = self.__builder.get_object("CommaPeriodPage")
+ self.__auto_commit = self.__builder.get_object("AutoCommit")
+ self.__half_width_puncts = self.__builder.get_object("HalfWidthPuncts")
+
+ # read values
+ self.__lookup_table_page_size.set_active(self.__get_value("LookupTablePageSize", 5) - 1)
+ self.__shift_select_candidate.set_active(self.__get_value("ShiftSelectCandidate", False))
+ self.__minus_equal_page.set_active(self.__get_value("MinusEqualPage", True))
+ self.__comma_period_page.set_active(self.__get_value("CommaPeriodPage", True))
+ self.__half_width_puncts.set_text(self.__get_value("HalfWidthPuncts", "+-*/=%"))
+
+ # connect signals
+ def __lookup_table_page_size_changed_cb(widget):
+ self.__set_value("LookupTablePageSize", widget.get_active() + 1)
+
+ self.__shift_select_candidate.connect("toggled", self.__toggled_cb, "ShiftSelectCandidate")
+ self.__minus_equal_page.connect("toggled", self.__toggled_cb, "MinusEqualPage")
+ self.__comma_period_page.connect("toggled", self.__toggled_cb, "CommaPeriodPage")
+ self.__lookup_table_page_size.connect("changed", __lookup_table_page_size_changed_cb)
+
+ def __entry_activate_cb(widget, name):
+ text = widget.get_text()
+ self.__set_value(name, text)
+ self.__half_width_puncts.connect("activate", __entry_activate_cb, "HalfWidthPuncts")
+
+ def __init_correct_pinyin(self):
+ # auto correct
+ self.__correct_pinyin = self.__builder.get_object("CorrectPinyin")
+ self.__correct_pinyin_widgets = [
+ ("CorrectPinyin_GN_NG", True),
+ ("CorrectPinyin_MG_NG", True),
+ ("CorrectPinyin_IOU_IU", True),
+ ("CorrectPinyin_UEI_UI", True),
+ ("CorrectPinyin_UEN_UN", True),
+ ("CorrectPinyin_VE_UE", True),
+ ]
+
+ def __correct_pinyin_toggled_cb(widget):
+ val = widget.get_active()
+ map(lambda w: self.__builder.get_object(w[0]).set_sensitive(val),
+ self.__correct_pinyin_widgets)
+ self.__correct_pinyin.connect("toggled", __correct_pinyin_toggled_cb)
+
+ # init value
+ self.__correct_pinyin.set_active(self.__get_value("CorrectPinyin", True))
+ for name, defval in self.__correct_pinyin_widgets:
+ widget = self.__builder.get_object(name)
+ widget.set_active(self.__get_value(name, defval))
+
+ self.__correct_pinyin.connect("toggled", self.__toggled_cb, "CorrectPinyin")
+ for name, defval in self.__correct_pinyin_widgets:
+ widget = self.__builder.get_object(name)
+ widget.connect("toggled", self.__toggled_cb, name)
+
+ def __init_fuzzy_pinyin(self):
+ # fuzzy pinyin
+ self.__fuzzy_pinyin = self.__builder.get_object("FuzzyPinyin")
+ self.__fuzzy_pinyin_widgets = [
+ ("FuzzyPinyin_C_CH", True),
+ ("FuzzyPinyin_Z_ZH", True),
+ ("FuzzyPinyin_S_SH", True),
+ ("FuzzyPinyin_CH_C", False),
+ ("FuzzyPinyin_ZH_Z", False),
+ ("FuzzyPinyin_SH_S", False),
+ ("FuzzyPinyin_L_N", True),
+ ("FuzzyPinyin_F_H", True),
+ ("FuzzyPinyin_L_R", False),
+ ("FuzzyPinyin_K_G", True),
+ ("FuzzyPinyin_N_L", False),
+ ("FuzzyPinyin_H_F", False),
+ ("FuzzyPinyin_R_L", False),
+ ("FuzzyPinyin_G_K", False),
+ ("FuzzyPinyin_AN_ANG", True),
+ ("FuzzyPinyin_EN_ENG", True),
+ ("FuzzyPinyin_IN_ING", True),
+ ("FuzzyPinyin_ANG_AN", True),
+ ("FuzzyPinyin_ENG_EN", True),
+ ("FuzzyPinyin_ING_IN", True),
+ ("FuzzyPinyin_IAN_IANG", False),
+ ("FuzzyPinyin_UAN_UANG", False),
+ ("FuzzyPinyin_IANG_IAN", False),
+ ("FuzzyPinyin_UANG_UAN", False),
+ ]
+
+ def __fuzzy_pinyin_toggled_cb(widget):
+ val = widget.get_active()
+ map(lambda w: self.__builder.get_object(w[0]).set_sensitive(val),
+ self.__fuzzy_pinyin_widgets)
+ self.__fuzzy_pinyin.connect("toggled", __fuzzy_pinyin_toggled_cb)
+
+ # init value
+ self.__fuzzy_pinyin.set_active(self.__get_value("FuzzyPinyin", False))
+ for name, defval in self.__fuzzy_pinyin_widgets:
+ widget = self.__builder.get_object(name)
+ widget.set_active(self.__get_value(name, defval))
+
+ self.__fuzzy_pinyin.connect("toggled", self.__toggled_cb, "FuzzyPinyin")
+ for name, defval in self.__fuzzy_pinyin_widgets:
+ widget = self.__builder.get_object(name)
+ widget.connect("toggled", self.__toggled_cb, name)
+
+ def __changed_cb(self, widget, name):
+ self.__set_value(name, widget.get_active())
+
+ def __toggled_cb(self, widget, name):
+ self.__set_value(name, widget.get_active ())
+
+ def __get_value(self, name, defval):
+ value = self.__config.get_value("engine/Pinyin", name, "test_default_value_9898")
+ if value != "test_default_value_9898":
+ return value
+ self.__set_value(name, defval)
+ return defval
+
+ def __set_value(self, name, val):
+ self.__config.set_value("engine/Pinyin", name, val)
def run(self):
- self.__init_ui()
- self.__load_config()
- signal.signal(signal.SIGUSR1, self.__sigusr1_cb)
- gtk.main()
-
- def __sigusr1_cb(self, *arg):
- window = self.__xml.get_widget("window_main")
- window.present()
-
- def __entry_op(self, name, opt, info):
- widget = self.__xml.get_widget(name)
- if widget == None:
- print >> sys.stderr, "Can not find widget %s" % name
- return ""
- if opt == "read":
- info[0] = self.__read(name, info[0])
- widget.set_text(info[0])
- return True
- if opt == "write":
- info[0] = widget.get_text()
- self.__write(name, info[0])
- return True
- if opt == "check":
- return info[0] != widget.get_text()
- return ""
-
- def __combobox_op(self, name, opt, info):
- widget = self.__xml.get_widget(name)
- if widget == None:
- print >> sys.stderr, "Can not find widget %s" % name
- return False
- if opt == "read":
- info[0] = self.__read(name, info[0])
- widget.set_active(info[2].index(info[0]))
- return True
- if opt == "write":
- info[0] = info[2][widget.get_active()]
- self.__write(name, info[0])
- return True
- if opt == "check":
- return info[0] != info[2][widget.get_active()]
-
- if opt == "init":
- model = gtk.ListStore(str)
- for v in info[2]:
- model.append([_(str(v))])
- widget.set_model(model)
- return False
-
- def __colorbutton_op(self, name, opt, info):
- widget = self.__xml.get_widget(name)
- if widget == None:
- print >> sys.stderr, "Can not find widget %s" % name
- return False
- if opt == "read":
- info[0] = self.__read(name, info[0])
- widget.set_color(GDK_COLOR(info[0]))
- return True
- if opt == "write":
- info[0] = RGB_COLOR (widget.get_color())
- self.__write(name, info[0])
- return True
- if opt == "check":
- return info[0] != RGB_COLOR(widget.get_color())
- return False
-
- def __checkbutton_op(self, name, opt, info):
- widget = self.__xml.get_widget(name)
- if widget == None:
- print >> sys.stderr, "Can not find widget %s" % name
- return False
-
- if opt == "read":
- info[0] = self.__read(name, info[0])
- widget.set_active(info[0])
- return True
- if opt == "write":
- info[0] = widget.get_active()
- self.__write(name, info[0])
- return True
- if opt == "check":
- return info[0] != widget.get_active()
- return False
-
- def __read(self, name, v):
- return self.__config.get_value("engine/PinYin", name, v)
-
- def __write(self, name, v):
- return self.__config.set_value("engine/PinYin", name, v)
-
- def __init_ui(self):
-
- locale.setlocale(locale.LC_ALL, "")
- localedir = os.getenv("IBUS_LOCALEDIR")
+ return self.__dialog.run()
- gettext.bindtextdomain("ibus-pinyin", localedir)
- gettext.bind_textdomain_codeset("ibus-pinyin", "UTF-8")
- glade.bindtextdomain("ibus-pinyin", localedir)
- glade.textdomain("ibus-pinyin")
-
- glade_file = path.join(path.dirname(__file__), "setup.glade")
- self.__xml = glade.XML (glade_file)
- self.__window = self.__xml.get_widget("window_main")
- for name, info in self.__options.items():
- info[1] (name, "init", info)
- info[1] (name, "read", info)
- self.__xml.signal_autoconnect(self)
- self.__window.show_all()
-
- def __load_config(self):
- for name, info in self.__options.items():
- info[1] (name, "read", info)
-
- def __save_config(self):
- self.__need_reload_config = True
- for name, info in self.__options.items():
- info[1] (name, "write", info)
-
- def __query_changed(self):
- for name, info in self.__options.items():
- if info[1] (name, "check", info):
- return True
- return False
-
- def __quit(self, need_confirm ):
- if need_confirm == False:
- gtk.main_quit()
- return True
- else:
- dlg = gtk.MessageDialog(self.__window, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION,
- gtk.BUTTONS_YES_NO, _("Are you sure to close Python PinYin Setup without save configure?"))
- id = dlg.run()
- dlg.destroy()
- if id == gtk.RESPONSE_YES:
- gtk.main_quit()
- return True
- return False
-
- def __optimize_user_db(self):
- import sqlite3
- dlg = gtk.MessageDialog(self.__window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO,
- gtk.BUTTONS_OK, _("The user phrases database will be reorganized! Please don't use python PinYin now."))
- dlg.run()
- dlg.destroy()
-
- try:
- db = sqlite3.connect(path.expanduser("~/.ibus/pinyin/user.db"))
- sqlstring = """
- BEGIN TRANSACTION;
- CREATE TABLE tmp AS SELECT * FROM py_phrase;
- DELETE FROM py_phrase;
- INSERT INTO py_phrase SELECT * FROM tmp ORDER BY ylen, y0, y1, y2, y3, yx, phrase;
- DROP TABLE tmp;
- COMMIT;
- """
- db.executescript(sqlstring)
- db.executescript("VACUUM;")
- except:
- import traceback
- traceback.print_exc()
-
- dlg.destroy()
- dlg = gtk.MessageDialog(self.__window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO,
- gtk.BUTTONS_OK, _("Reorganizing is over!"))
- dlg.run()
- dlg.destroy()
-
- # events handlers
- def on_window_main_delete_event(self, widget, event):
- changed = self.__query_changed()
- self.__quit(changed)
-
- def on_button_ok_clicked(self, button):
- changed = self.__query_changed()
- if changed:
- self.__save_config()
- self.__quit(False)
-
- def on_button_apply_clicked(self, button):
- self.__save_config()
-
- def on_button_cancel_clicked(self, button):
- changed = self.__query_changed()
- self.__quit(changed)
-
- def on_button_optimize_db_clicked(self, button):
- self.__optimize_user_db()
-
- def on_value_changed(self, widget, data = None):
- if self.__query_changed():
- self.__xml.get_widget("button_apply").set_sensitive(True)
- else:
- self.__xml.get_widget("button_apply").set_sensitive(False)
+def main():
+ PreferencesDialog().run()
if __name__ == "__main__":
- ui = SetupUI()
- ui.run()
-
+ main()
diff --git a/setup/pydict.py b/setup/pydict.py
deleted file mode 120000
index b106fef..0000000
--- a/setup/pydict.py
+++ /dev/null
@@ -1 +0,0 @@
-../engine/pydict.py \ No newline at end of file
diff --git a/setup/setup.glade b/setup/setup.glade
deleted file mode 100644
index ad16a12..0000000
--- a/setup/setup.glade
+++ /dev/null
@@ -1,958 +0,0 @@
-<?xml version="1.0"?>
-<glade-interface>
- <!-- interface-requires gtk+ 2.16 -->
- <!-- interface-naming-policy toplevel-contextual -->
- <widget class="GtkWindow" id="window_main">
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="title" translatable="yes">Python PinYin Setup</property>
- <property name="window_position">center</property>
- <child>
- <widget class="GtkVBox" id="vbox1">
- <property name="visible">True</property>
- <child>
- <widget class="GtkNotebook" id="notebook">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="scrollable">True</property>
- <child>
- <widget class="GtkTable" id="table1">
- <property name="visible">True</property>
- <property name="n_rows">12</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">4</property>
- <property name="row_spacing">2</property>
- <property name="homogeneous">True</property>
- <child>
- <widget class="GtkEntry" id="HalfPunctuations">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">&#x25CF;</property>
- <signal name="changed" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">11</property>
- <property name="bottom_attach">12</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label12">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Half punctuations</property>
- </widget>
- <packing>
- <property name="top_attach">11</property>
- <property name="bottom_attach">12</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label21">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Press [u] or [v] to temporary English mode</property>
- </widget>
- <packing>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="UVToTemp">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_value_changed"/>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="SpellCheck">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_value_changed"/>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="AutoCorrect">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_value_changed"/>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- </packing>
- </child>
- <child>
- <widget class="GtkComboBox" id="PageSize">
- <property name="visible">True</property>
- <property name="items" translatable="yes">1
-</property>
- <signal name="changed" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- </packing>
- </child>
- <child>
- <widget class="GtkComboBox" id="ShuangPinSchema">
- <property name="visible">True</property>
- <property name="items" translatable="yes">1
-</property>
- <signal name="changed" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label14">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">English spelling check</property>
- </widget>
- <packing>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label13">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Wrong PinYin auto correct</property>
- </widget>
- <packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label11">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Lookup table page size</property>
- </widget>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label10">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">ShuangPin Schema</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label16">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">ShuangPin</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label17">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Support GBK</property>
- </widget>
- </child>
- <child>
- <widget class="GtkCheckButton" id="ShuangPin">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_value_changed"/>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="SupportGBK">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_value_changed"/>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label20">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Press [shift] to select candidates</property>
- </widget>
- <packing>
- <property name="top_attach">7</property>
- <property name="bottom_attach">8</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="ShiftSelectCandidates">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">7</property>
- <property name="bottom_attach">8</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label22">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Press [-] [=] to page down up.</property>
- </widget>
- <packing>
- <property name="top_attach">8</property>
- <property name="bottom_attach">9</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="EqualPageDownUp">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">8</property>
- <property name="bottom_attach">9</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="CommaPageDownUp">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">9</property>
- <property name="bottom_attach">10</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="AutoCommit">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">10</property>
- <property name="bottom_attach">11</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label23">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Auto commit</property>
- </widget>
- <packing>
- <property name="top_attach">10</property>
- <property name="bottom_attach">11</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label24">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Press [,] [.] to page down up.</property>
- </widget>
- <packing>
- <property name="top_attach">9</property>
- <property name="bottom_attach">10</property>
- </packing>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">General</property>
- </widget>
- <packing>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- <child>
- <widget class="GtkTable" id="table4">
- <property name="no_show_all">True</property>
- <property name="n_rows">12</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">2</property>
- <property name="row_spacing">2</property>
- <property name="homogeneous">True</property>
- <child>
- <widget class="GtkCheckButton" id="FuzzyPinYin">
- <property name="label" translatable="yes">Enable Fuzzy PinYin</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- </child>
- <child>
- <widget class="GtkCheckButton" id="FuzzyS_Sh">
- <property name="label" translatable="yes">s &lt;=&gt; sh</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"></property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="FuzzyC_Ch">
- <property name="label" translatable="yes">c &lt;=&gt; ch</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options"></property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="FuzzyZ_Zh">
- <property name="label" translatable="yes">z &lt;=&gt; zh</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options"></property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="FuzzyL_N">
- <property name="label" translatable="yes">l &lt;=&gt; n</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options"></property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="FuzzyIn_Ing">
- <property name="label" translatable="yes">in &lt;=&gt; ing</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"></property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="FuzzyEn_Eng">
- <property name="label" translatable="yes">en &lt;=&gt; eng</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options"></property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="FuzzyAn_Ang">
- <property name="label" translatable="yes">an &lt;=&gt; ang</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options"></property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="Fuzzytab">
- <property name="label" translatable="yes">Fuzzy PinYin</property>
- </widget>
- <packing>
- <property name="position">1</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- <child>
- <widget class="GtkTable" id="table2">
- <property name="visible">True</property>
- <property name="n_rows">11</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">2</property>
- <property name="row_spacing">2</property>
- <property name="homogeneous">True</property>
- <child>
- <widget class="GtkLabel" id="label9">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Color of Spelling Error</property>
- </widget>
- <packing>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label8">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Color of English Candidates</property>
- </widget>
- <packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label7">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Color of Special Phrases</property>
- </widget>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label6">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Color of User Phrases</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label5">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Color of New Phrases</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label4">
- <property name="visible">True</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">Color of Normal Phrases</property>
- </widget>
- </child>
- <child>
- <widget class="GtkColorButton" id="ErrorEnglishPhraseColor">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <signal name="color_set" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- </packing>
- </child>
- <child>
- <widget class="GtkColorButton" id="EnglishPhraseColor">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <signal name="color_set" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- </packing>
- </child>
- <child>
- <widget class="GtkColorButton" id="SpecialPhraseColor">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <signal name="color_set" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- </packing>
- </child>
- <child>
- <widget class="GtkColorButton" id="UserPhraseColor">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <signal name="color_set" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkColorButton" id="NewPhraseColor">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <signal name="color_set" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkColorButton" id="PhraseColor">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <signal name="color_set" handler="on_value_changed"/>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Colors</property>
- </widget>
- <packing>
- <property name="position">2</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- <child>
- <widget class="GtkTable" id="table3">
- <property name="no_show_all">True</property>
- <property name="n_rows">6</property>
- <property name="n_columns">3</property>
- <property name="homogeneous">True</property>
- <child>
- <widget class="GtkButton" id="button_optimize_db">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <signal name="clicked" handler="on_button_optimize_db_clicked"/>
- <child>
- <widget class="GtkHBox" id="hbox1">
- <property name="visible">True</property>
- <child>
- <widget class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="xalign">0.80000001192092896</property>
- <property name="stock">gtk-execute</property>
- <property name="icon-size">4</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label19">
- <property name="visible">True</property>
- <property name="xalign">0.10000000149011612</property>
- <property name="label" translatable="yes">Optimize User DB</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label3">
- <property name="label" translatable="yes">User DB</property>
- </widget>
- <packing>
- <property name="position">3</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label15">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Python PinYin
-
-provided by
-
-Huang Peng &lt;shawn.p.huang@gmail.com&gt;
-</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label18">
- <property name="label" translatable="yes">About</property>
- </widget>
- <packing>
- <property name="position">4</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHButtonBox" id="hbuttonbox1">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <property name="layout_style">end</property>
- <child>
- <widget class="GtkButton" id="button_apply">
- <property name="label">gtk-apply</property>
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_stock">True</property>
- <signal name="clicked" handler="on_button_apply_clicked"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="button_cancel">
- <property name="label">gtk-cancel</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_stock">True</property>
- <signal name="clicked" handler="on_button_cancel_clicked"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="button_ok">
- <property name="label">gtk-ok</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_stock">True</property>
- <signal name="clicked" handler="on_button_ok_clicked"/>
- <signal name="activate" handler="on_button_ok_activate"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="padding">7</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
-</glade-interface>
diff --git a/src/Array.h b/src/Array.h
new file mode 100644
index 0000000..535ced8
--- /dev/null
+++ b/src/Array.h
@@ -0,0 +1,108 @@
+#ifndef __PY_ARRAY_H_
+#define __PY_ARRAY_H_
+
+namespace PY {
+
+template<typename T>
+class Array {
+public:
+ Array (guint init_size = 0) {
+ m_array = g_array_sized_new (FALSE, FALSE, sizeof (T), init_size);
+ }
+
+ ~Array () {
+ g_array_free (m_array, TRUE);
+ }
+
+ T & get (guint i) {
+ return g_array_index (m_array, T, i);
+ }
+
+ const T & get (guint i) const {
+ return g_array_index (m_array, T, i);
+ }
+
+ guint length (void) const {
+ return m_array->len;
+ }
+
+ gboolean isEmpty (void) const {
+ return length () == 0;
+ }
+
+ Array<T> & setSize (guint size) {
+ g_array_set_size (m_array, size);
+ return *this;
+ }
+
+ Array<T> & removeAll () {
+ setSize (0);
+ return *this;
+ }
+
+ Array<T> & append (const T & v) {
+ g_array_append_val (m_array, v);
+ return *this;
+ }
+
+ Array<T> & append (const Array<T> & a) {
+ for (guint i = 0; i < a.length (); i++)
+ append (a[i]);
+ return *this;
+ }
+
+ Array<T> & push (const T & v) {
+ append (v);
+ return *this;
+ }
+
+ T & pop (void) {
+ T & v = g_array_index (m_array, T, length () - 1);
+ g_array_set_size (m_array, length () - 1);
+ return v;
+ }
+
+ Array<T> & operator = (const Array<T> & v) {
+ removeAll ();
+ for (guint i = 0; i < v.length(); i++)
+ append (v[i]);
+ return *this;
+ }
+
+ gboolean operator == (const Array<T> &v) const {
+ if (length () != v.length ())
+ return FALSE;
+ for (guint i = 0; i < length (); i++) {
+ if (get (i) != v[i])
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ Array<T> & operator << (const T & v) {
+ return append (v);
+ }
+
+ Array<T> & operator << (const Array<T> & a) {
+ return append (a);
+ }
+
+ T & operator[] (guint i) {
+ return get (i);
+ }
+
+ const T & operator[] (guint i) const {
+ return get (i);
+ }
+
+ operator gboolean (void) const {
+ return length () != 0;
+ }
+
+private:
+ GArray *m_array;
+};
+
+};
+
+#endif
diff --git a/src/Bus.h b/src/Bus.h
new file mode 100644
index 0000000..be76894
--- /dev/null
+++ b/src/Bus.h
@@ -0,0 +1,17 @@
+#ifndef __PY_BUS_H_
+#define __PY_BUS_H_
+
+#include <ibus.h>
+#include "Pointer.h"
+
+namespace PY {
+
+class Bus : public Pointer <IBusBus> {
+public:
+ Bus (void) {
+ set (ibus_bus_new ());
+ }
+};
+
+};
+#endif
diff --git a/src/Config.cc b/src/Config.cc
new file mode 100644
index 0000000..a629c33
--- /dev/null
+++ b/src/Config.cc
@@ -0,0 +1,203 @@
+#include "Types.h"
+#include "Config.h"
+#include "Util.h"
+
+namespace PY {
+
+guint Config::m_option = PINYIN_SIMPLE_PINYIN | PINYIN_CORRECT_ALL;
+guint Config::m_option_mask = PINYIN_SIMPLE_PINYIN | PINYIN_CORRECT_ALL;
+guint Config::m_page_size = 5;
+gboolean Config::m_minus_equal_page = TRUE;
+gboolean Config::m_comma_period_page = TRUE;
+gboolean Config::m_double_pinyin = FALSE;
+gint Config::m_double_pinyin_schema = 0;
+gboolean Config::m_init_chinese = TRUE;
+gboolean Config::m_init_full = FALSE;
+gboolean Config::m_init_full_punct = TRUE;
+
+static const StaticString engine_pinyin ("engine/Pinyin");
+static const StaticString correct_pinyin ("CorrectPinyin");
+static const StaticString fuzzy_pinyin ("FuzzyPinyin");
+static const StaticString page_size ("LookupTablePageSize");
+static const StaticString minus_equal_page ("MinusEqualPage");
+static const StaticString comma_period_page ("CommaPeriodPage");
+static const StaticString double_pinyin ("DoublePinyin");
+static const StaticString double_pinyin_schema ("DoublePinyinSchema");
+static const StaticString init_chinese ("InitChinese");
+static const StaticString init_full ("InitFull");
+static const StaticString init_full_punct ("InitFullPunct");
+
+static const struct {
+ StaticString name;
+ guint option;
+ bool defval;
+} options [] = {
+ { StaticString ("SimplePinyin"), PINYIN_SIMPLE_PINYIN, TRUE },
+ /* correct */
+ { StaticString ("CorrectPinyin_GN_NG"), PINYIN_CORRECT_GN_TO_NG, TRUE },
+ { StaticString ("CorrectPinyin_GN_NG"), PINYIN_CORRECT_GN_TO_NG, TRUE },
+ { StaticString ("CorrectPinyin_MG_NG"), PINYIN_CORRECT_MG_TO_NG, TRUE },
+ { StaticString ("CorrectPinyin_IOU_IU"), PINYIN_CORRECT_IOU_TO_IU, TRUE },
+ { StaticString ("CorrectPinyin_UEI_UI"), PINYIN_CORRECT_UEI_TO_UI, TRUE },
+ { StaticString ("CorrectPinyin_UEN_UN"), PINYIN_CORRECT_UEN_TO_UN, TRUE },
+ { StaticString ("CorrectPinyin_VE_UE"), PINYIN_CORRECT_VE_TO_UE, TRUE },
+ /* fuzzy pinyin */
+ { StaticString ("FuzzyPinyin_C_CH"), PINYIN_FUZZY_C_CH, FALSE },
+ { StaticString ("FuzzyPinyin_CH_C"), PINYIN_FUZZY_CH_C, FALSE },
+ { StaticString ("FuzzyPinyin_Z_ZH"), PINYIN_FUZZY_Z_ZH, FALSE },
+ { StaticString ("FuzzyPinyin_ZH_Z"), PINYIN_FUZZY_ZH_Z, FALSE },
+ { StaticString ("FuzzyPinyin_S_SH"), PINYIN_FUZZY_S_SH, FALSE },
+ { StaticString ("FuzzyPinyin_SH_S"), PINYIN_FUZZY_SH_S, FALSE },
+ { StaticString ("FuzzyPinyin_L_N"), PINYIN_FUZZY_L_N, FALSE },
+ { StaticString ("FuzzyPinyin_N_L"), PINYIN_FUZZY_N_L, FALSE },
+ { StaticString ("FuzzyPinyin_F_H"), PINYIN_FUZZY_F_H, FALSE },
+ { StaticString ("FuzzyPinyin_H_F"), PINYIN_FUZZY_H_F, FALSE },
+ { StaticString ("FuzzyPinyin_L_R"), PINYIN_FUZZY_L_R, FALSE },
+ { StaticString ("FuzzyPinyin_R_L"), PINYIN_FUZZY_R_L, FALSE },
+ { StaticString ("FuzzyPinyin_K_G"), PINYIN_FUZZY_K_G, FALSE },
+ { StaticString ("FuzzyPinyin_G_K"), PINYIN_FUZZY_G_K, FALSE },
+ { StaticString ("FuzzyPinyin_AN_ANG"), PINYIN_FUZZY_AN_ANG, FALSE },
+ { StaticString ("FuzzyPinyin_ANG_AN"), PINYIN_FUZZY_ANG_AN, FALSE },
+ { StaticString ("FuzzyPinyin_EN_ENG"), PINYIN_FUZZY_EN_ENG, FALSE },
+ { StaticString ("FuzzyPinyin_ENG_EN"), PINYIN_FUZZY_ENG_EN, FALSE },
+ { StaticString ("FuzzyPinyin_IN_ING"), PINYIN_FUZZY_IN_ING, FALSE },
+ { StaticString ("FuzzyPinyin_ING_IN"), PINYIN_FUZZY_ING_IN, FALSE },
+ { StaticString ("FuzzyPinyin_UAN_UANG"), PINYIN_FUZZY_UAN_UANG, FALSE },
+ { StaticString ("FuzzyPinyin_UANG_UAN"), PINYIN_FUZZY_UANG_UAN, FALSE },
+};
+
+void
+Config::readDefaultValues (void)
+{
+ /* double pinyin */
+ m_double_pinyin = read (engine_pinyin, double_pinyin, false);
+ m_double_pinyin_schema = read (engine_pinyin, double_pinyin_schema, 0);
+
+ /* init states */
+ m_init_chinese = read (engine_pinyin, init_chinese, true);
+ m_init_full = read (engine_pinyin, init_full, false);
+ m_init_full_punct = read (engine_pinyin, init_full_punct, true);
+
+ /* others */
+ m_page_size = read (engine_pinyin, page_size, 5);
+ m_minus_equal_page = read (engine_pinyin, minus_equal_page, true);
+ m_comma_period_page = read (engine_pinyin, comma_period_page, true);
+
+ /* correct pinyin */
+ if (read (engine_pinyin, correct_pinyin, true))
+ m_option_mask |= PINYIN_CORRECT_ALL;
+ else
+ m_option_mask &= ~PINYIN_CORRECT_ALL;
+
+ /* fuzzy pinyin */
+ if (read (engine_pinyin, fuzzy_pinyin, false))
+ m_option_mask |= PINYIN_FUZZY_ALL;
+ else
+ m_option_mask &= ~PINYIN_FUZZY_ALL;
+
+ /* read values */
+ for (guint i = 0;i < sizeof (options) / sizeof (options[0]); i++) {
+ if (read (engine_pinyin, options[i].name, options[i].defval))
+ m_option |= options[i].option;
+ else
+ m_option &= ~options[i].option;
+ }
+}
+
+inline bool
+Config::read (const gchar *section, const gchar *name, bool defval)
+{
+ GValue value = {0};
+ if (ibus_config_get_value (m_config, section, name, &value)) {
+ if (G_VALUE_TYPE (&value) == G_TYPE_BOOLEAN)
+ return g_value_get_boolean (&value);
+ }
+ return defval;
+}
+
+inline gint
+Config::read (const gchar *section, const gchar *name, gint defval)
+{
+ GValue value = {0};
+ if (ibus_config_get_value (m_config, section, name, &value)) {
+ if (G_VALUE_TYPE (&value) == G_TYPE_INT)
+ return g_value_get_int (&value);
+ }
+ return defval;
+}
+
+static inline bool
+normalizeGValue (const GValue *value, bool defval)
+{
+ if (value == NULL || G_VALUE_TYPE (value) != G_TYPE_BOOLEAN)
+ return defval;
+ return g_value_get_boolean (value);
+}
+
+static inline gint
+normalizeGValue (const GValue *value, gint defval)
+{
+ if (value == NULL || G_VALUE_TYPE (value) != G_TYPE_INT)
+ return defval;
+ return g_value_get_int (value);
+}
+
+void
+Config::valueChangedCallback (IBusConfig *config,
+ const gchar *section,
+ const gchar *name,
+ const GValue *value,
+ Config *self)
+{
+ if (engine_pinyin != section)
+ return;
+
+ /* double pinyin */
+ if (double_pinyin == name)
+ m_double_pinyin = normalizeGValue (value, false);
+ else if (double_pinyin_schema == name)
+ m_double_pinyin_schema = normalizeGValue (value, 0);
+ /* init states */
+ else if (init_chinese == name)
+ m_init_chinese = normalizeGValue (value, true);
+ else if (init_full == name)
+ m_init_full = normalizeGValue (value, true);
+ else if (init_full_punct == name)
+ m_init_full_punct = normalizeGValue (value, true);
+ /* lookup table page size */
+ else if (page_size == name)
+ m_page_size = normalizeGValue (value, 5);
+ else if (minus_equal_page == name)
+ m_minus_equal_page = normalizeGValue (value, true);
+ else if (comma_period_page == name)
+ m_comma_period_page = normalizeGValue (value, true);
+ /* correct pinyin */
+ else if (correct_pinyin == name) {
+ if (normalizeGValue (value, TRUE))
+ m_option_mask |= PINYIN_CORRECT_ALL;
+ else
+ m_option_mask &= ~PINYIN_CORRECT_ALL;
+ }
+ /* fuzzy pinyin */
+ else if (fuzzy_pinyin == name) {
+ if (normalizeGValue (value, TRUE))
+ m_option_mask |= PINYIN_FUZZY_ALL;
+ else
+ m_option_mask &= ~PINYIN_FUZZY_ALL;
+ }
+ else {
+ for (guint i = 0;i < sizeof (options) / sizeof (options[0]); i++) {
+ if (G_LIKELY (options[i].name != name))
+ continue;
+ if (normalizeGValue (value, options[i].defval))
+ m_option |= options[i].option;
+ else
+ m_option &= ~options[i].option;
+ break;
+ }
+ }
+
+}
+
+
+};
diff --git a/src/Config.h b/src/Config.h
new file mode 100644
index 0000000..cd7630d
--- /dev/null
+++ b/src/Config.h
@@ -0,0 +1,56 @@
+#ifndef __PY_CONFIG_H_
+#define __PY_CONFIG_H_
+
+#include <glib.h>
+#include <glib-object.h>
+#include <ibus.h>
+#include "Pointer.h"
+
+namespace PY {
+
+class Config {
+public:
+ Config (Pointer<IBusBus> & bus) {
+ m_config = ibus_bus_get_config (bus);
+ readDefaultValues ();
+ g_signal_connect ((IBusConfig *) m_config, "value-changed", G_CALLBACK (valueChangedCallback), this);
+ }
+
+ static guint option (void) { return m_option & m_option_mask; }
+ static guint pageSize (void) { return m_page_size; }
+ static gboolean minusEqualPage (void) { return m_minus_equal_page; }
+ static gboolean commaPeriodPage (void) { return m_comma_period_page; }
+ static gboolean doublePinyin (void) { return m_double_pinyin; }
+ static gint doublePinyinSchema (void) { return m_double_pinyin_schema; }
+ static gboolean initChinese (void) { return m_init_chinese; }
+ static gboolean initFull (void) { return m_init_full; }
+ static gboolean initFullPunct (void) { return m_init_full_punct; }
+
+private:
+ bool read (const gchar *section, const gchar *name, bool defval);
+ int read (const gchar *section, const gchar *name, int defval);
+ void readDefaultValues (void);
+ static void valueChangedCallback (IBusConfig *config,
+ const gchar *section,
+ const gchar *name,
+ const GValue *value,
+ Config *self);
+
+private:
+ Pointer<IBusConfig> m_config;
+
+private:
+ static guint m_option;
+ static guint m_option_mask;
+ static guint m_page_size;
+ static gboolean m_minus_equal_page;
+ static gboolean m_comma_period_page;
+ static gboolean m_double_pinyin;
+ static gint m_double_pinyin_schema;
+ static gboolean m_init_chinese;
+ static gboolean m_init_full;
+ static gboolean m_init_full_punct;
+};
+
+};
+#endif
diff --git a/src/Database.cc b/src/Database.cc
new file mode 100644
index 0000000..918cfd2
--- /dev/null
+++ b/src/Database.cc
@@ -0,0 +1,583 @@
+/* vim:set et sts=4: */
+#include <string.h>
+#include <glib.h>
+#include <sqlite3.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "Database.h"
+#include "Util.h"
+
+namespace PY {
+
+#define DB_CACHE_SIZE "5000"
+#define DB_INDEX_SIZE (3)
+/* define columns */
+#define DB_COLUMN_USER_FREQ (0)
+#define DB_COLUMN_PHRASE (1)
+#define DB_COLUMN_FREQ (2)
+#define DB_COLUMN_S0 (3)
+
+#define DB_PREFETCH_LEN (6)
+
+Database::Database (void)
+ : m_db (NULL),
+ m_sql (1024),
+ m_buffer (1024),
+ m_conditions (32),
+ m_strings (32)
+{
+ init ();
+}
+
+Database::~Database (void)
+{
+ for (guint i = 0; i < m_strings.length (); i++) {
+ delete m_strings[i];
+ }
+
+ if (m_db) {
+ sqlite3_close (m_db);
+ m_db = NULL;
+ }
+}
+
+gboolean
+Database::init (void)
+{
+ gchar *errmsg;
+ gchar *userdb;
+ gboolean retval;
+
+ sqlite3_initialize ();
+
+ if (sqlite3_open_v2 (PKGDATADIR"/db/main.db", &m_db,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) {
+ if (sqlite3_open_v2 ("main.db", &m_db,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK)
+ goto _failed;
+ }
+
+ if (sqlite3_exec (m_db, "PRAGMA cache_size=" DB_CACHE_SIZE, NULL, NULL, &errmsg) != SQLITE_OK) {
+ g_debug ("%s", errmsg);
+ sqlite3_free (errmsg);
+ goto _failed;
+ }
+
+ userdb = g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), ".ibus", "pinyin", NULL);
+ g_mkdir_with_parents (userdb, 0750);
+ g_free (userdb);
+ userdb = g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), ".ibus", "pinyin", "user-1.3.db", NULL);
+ retval = initUserDatabase (userdb);
+ if (!retval) {
+ g_free (userdb);
+ g_warning ("can not open user database %s", userdb);
+ if (!initUserDatabase (":memory:"))
+ goto _failed;
+ }
+ g_free (userdb);
+
+ prefetch ();
+
+ return TRUE;
+
+_failed:
+ if (m_db) {
+ sqlite3_close (m_db);
+ m_db = NULL;
+ }
+ return FALSE;
+}
+
+gboolean
+Database::initUserDatabase (const gchar *userdb)
+{
+ gchar *errmsg;
+
+ m_sql.printf ("ATTACH DATABASE \"%s\" AS userdb;", userdb);
+ if (sqlite3_exec (m_db, m_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
+ g_debug ("%s", errmsg);
+ sqlite3_free (errmsg);
+ return FALSE;
+ }
+
+ m_sql = "BEGIN TRANSACTION;\n";
+ /* create desc table*/
+ m_sql << "CREATE TABLE IF NOT EXISTS userdb.desc (name PRIMARY KEY, value TEXT);\n";
+ m_sql << "INSERT OR IGNORE INTO userdb.desc VALUES " << "('version', '1.2.0');\n"
+ << "INSERT OR IGNORE INTO userdb.desc VALUES " << "('uuid', '" << UUID () << "');\n"
+ << "INSERT OR IGNORE INTO userdb.desc VALUES " << "('hostname', '" << Hostname () << "');\n"
+ << "INSERT OR IGNORE INTO userdb.desc VALUES " << "('username', '" << getenv ("USERNAME") << "');\n"
+ << "INSERT OR IGNORE INTO userdb.desc VALUES " << "('create-time', datetime());\n"
+ << "INSERT OR IGNORE INTO userdb.desc VALUES " << "('attach-time', datetime());\n";
+
+ /* create phrase tables */
+ for (guint i = 0; i < MAX_PHRASE_LEN; i++) {
+ m_sql.appendPrintf ("CREATE TABLE IF NOT EXISTS userdb.py_phrase_%d (user_freq, phrase TEXT, freq INTEGER ", i);
+ for (guint j = 0; j <= i; j++)
+ m_sql.appendPrintf (",s%d INTEGER, y%d INTEGER", j, j);
+ m_sql << ");\n";
+ }
+
+ /* create index */
+ m_sql << "CREATE UNIQUE INDEX IF NOT EXISTS " << "userdb.index_0_0 ON py_phrase_0(s0,y0,phrase);\n";
+ m_sql << "CREATE UNIQUE INDEX IF NOT EXISTS " << "userdb.index_1_0 ON py_phrase_1(s0,y0,s1,y1,phrase);\n";
+ m_sql << "CREATE INDEX IF NOT EXISTS " << "userdb.index_1_1 ON py_phrase_1(s0,s1,y1);\n";
+ for (guint i = 2; i < MAX_PHRASE_LEN; i++) {
+ m_sql << "CREATE UNIQUE INDEX IF NOT EXISTS " << "userdb.index_" << i << "_0 ON py_phrase_" << i
+ << "(s0,y0";
+ for (guint j = 1; j <= i; j++)
+ m_sql << ",s" << j << ",y" << j;
+ m_sql << ",phrase);\n";
+ m_sql << "CREATE INDEX IF NOT EXISTS " << "userdb.index_" << i << "_1 ON py_phrase_" << i << "(s0,s1,s2,y2);\n";
+ }
+ m_sql << "COMMIT;\n";
+
+ if (sqlite3_exec (m_db, m_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
+ g_debug ("%s", errmsg);
+ sqlite3_free (errmsg);
+ goto _failed;
+ }
+
+ m_sql = "UPDATE userdb.desc SET value=datetime() WHERE name='attach-time';\n";
+
+ if (sqlite3_exec (m_db, m_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
+ g_debug ("%s", errmsg);
+ sqlite3_free (errmsg);
+ goto _failed;
+ }
+ return TRUE;
+
+_failed:
+ m_sql = "DETACH DATABASE userdb;\n";
+ if (sqlite3_exec (m_db, m_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
+ g_debug ("%s", errmsg);
+ sqlite3_free (errmsg);
+ }
+ return FALSE;
+}
+
+void
+Database::prefetch (void)
+{
+ for (guint i = 0; i < DB_PREFETCH_LEN; i++) {
+ gchar *errmsg;
+ m_sql = "SELECT * FROM py_phrase_";
+ m_sql << i;
+ if (sqlite3_exec (m_db, m_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
+ g_debug ("%s", errmsg);
+ sqlite3_free (errmsg);
+ }
+ }
+}
+
+gint
+Database::query (const PinyinArray &pinyin,
+ guint m,
+ guint option,
+ PhraseArray &result)
+{
+ gint len;
+ gint i;
+ gint row;
+ gint ret;
+
+ len = MIN (pinyin.length (), MAX_PHRASE_LEN);
+
+ row = 0;
+ for (i = len; i > 0; i--) {
+ if (m < 0) {
+ ret = query (pinyin, 0, i, -1, option, result);
+ if (ret < 0)
+ return ret;
+ row += ret;
+ }
+ else {
+ ret = query (pinyin, 0, i, m - result.length (), option, result);
+ if (ret < 0)
+ return ret;
+ row += ret;
+ if (result.length () >= m)
+ break;
+ }
+ }
+ return row;
+}
+
+
+
+inline static void
+_conditions_append_vprintf (Array<String *> &array,
+ gint begin,
+ gint end,
+ const gchar *fmt,
+ va_list args)
+{
+ gchar str[64];
+ g_vsnprintf (str, sizeof(str), fmt, args);
+
+ for (gint i = begin; i < end; i++) {
+ (*array[i]) << str;
+ }
+}
+
+inline static void
+_conditions_append_printf (Array<String *> &array,
+ gint begin,
+ gint end,
+ const gchar *fmt,
+ ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ _conditions_append_vprintf (array, begin, end, fmt, args);
+ va_end (args);
+}
+
+#define CONDITION_INIT_SIZE (256)
+
+inline void
+Database::conditionsDouble (void)
+{
+ gint i, len;
+
+ len = m_conditions.length ();
+
+ for (i = 0; i < len; i++) {
+ String *new_str;
+ new_str = string (len + i);
+ *new_str = *m_conditions[i];
+ m_conditions << new_str;
+ }
+}
+
+inline void
+Database::conditionsTriple (void)
+{
+ gint i, len;
+
+ len = m_conditions.length ();
+
+ for (i = 0; i < len; i++) {
+ String *new_str;
+ new_str = string ((i << 1) + len);
+ *new_str = *m_conditions[i];
+ m_conditions << new_str;
+ new_str = string ((i << 1) + len + 1);
+ *new_str = *m_conditions[i];
+ m_conditions << new_str;
+ }
+}
+
+inline static gboolean
+pinyin_option_check_sheng (guint option, gint id, gint fid)
+{
+ switch ((id << 16) | fid) {
+ case (PINYIN_ID_C << 16) | PINYIN_ID_CH:
+ return (option & PINYIN_FUZZY_C_CH);
+ case (PINYIN_ID_CH << 16) | PINYIN_ID_C:
+ return (option & PINYIN_FUZZY_CH_C);
+ case (PINYIN_ID_Z << 16) | PINYIN_ID_ZH:
+ return (option & PINYIN_FUZZY_Z_ZH);
+ case (PINYIN_ID_ZH << 16) | PINYIN_ID_Z:
+ return (option & PINYIN_FUZZY_ZH_Z);
+ case (PINYIN_ID_S << 16) | PINYIN_ID_SH:
+ return (option & PINYIN_FUZZY_S_SH);
+ case (PINYIN_ID_SH << 16) | PINYIN_ID_S:
+ return (option & PINYIN_FUZZY_SH_S);
+ case (PINYIN_ID_L << 16) | PINYIN_ID_N:
+ return (option & PINYIN_FUZZY_L_N);
+ case (PINYIN_ID_N << 16) | PINYIN_ID_L:
+ return (option & PINYIN_FUZZY_N_L);
+ case (PINYIN_ID_F << 16) | PINYIN_ID_H:
+ return (option & PINYIN_FUZZY_F_H);
+ case (PINYIN_ID_H << 16) | PINYIN_ID_F:
+ return (option & PINYIN_FUZZY_H_F);
+ case (PINYIN_ID_L << 16) | PINYIN_ID_R:
+ return (option & PINYIN_FUZZY_L_R);
+ case (PINYIN_ID_R << 16) | PINYIN_ID_L:
+ return (option & PINYIN_FUZZY_R_L);
+ case (PINYIN_ID_K << 16) | PINYIN_ID_G:
+ return (option & PINYIN_FUZZY_K_G);
+ case (PINYIN_ID_G << 16) | PINYIN_ID_K:
+ return (option & PINYIN_FUZZY_G_K);
+ default: return FALSE;
+ }
+}
+
+inline static gboolean
+pinyin_option_check_yun (guint option, gint id, gint fid)
+{
+ switch ((id << 16) | fid) {
+ case (PINYIN_ID_AN << 16) | PINYIN_ID_ANG:
+ return (option & PINYIN_FUZZY_AN_ANG);
+ case (PINYIN_ID_ANG << 16) | PINYIN_ID_AN:
+ return (option & PINYIN_FUZZY_ANG_AN);
+ case (PINYIN_ID_EN << 16) | PINYIN_ID_ENG:
+ return (option & PINYIN_FUZZY_EN_ENG);
+ case (PINYIN_ID_ENG << 16) | PINYIN_ID_EN:
+ return (option & PINYIN_FUZZY_ENG_EN);
+ case (PINYIN_ID_IN << 16) | PINYIN_ID_ING:
+ return (option & PINYIN_FUZZY_IN_ING);
+ case (PINYIN_ID_ING << 16) | PINYIN_ID_IN:
+ return (option & PINYIN_FUZZY_ING_IN);
+ case (PINYIN_ID_IAN << 16) | PINYIN_ID_IANG:
+ return (option & PINYIN_FUZZY_IAN_IANG);
+ case (PINYIN_ID_IANG << 16) | PINYIN_ID_IAN:
+ return (option & PINYIN_FUZZY_IANG_IAN);
+ case (PINYIN_ID_UAN << 16) | PINYIN_ID_UANG:
+ return (option & PINYIN_FUZZY_UAN_UANG);
+ case (PINYIN_ID_UANG << 16) | PINYIN_ID_UAN:
+ return (option & PINYIN_FUZZY_UANG_UAN);
+ default: return FALSE;
+ }
+}
+
+gint
+Database::query (const PinyinArray &pinyin,
+ guint pinyin_begin,
+ guint pinyin_len,
+ gint m,
+ guint option,
+ PhraseArray &result)
+{
+ if (G_UNLIKELY (pinyin_begin > pinyin.length ()))
+ pinyin_begin = pinyin.length ();
+
+ if (G_UNLIKELY (pinyin_len > pinyin.length () - pinyin_begin))
+ pinyin_len = pinyin.length () - pinyin_begin;
+
+ if (G_UNLIKELY (pinyin_len > MAX_PHRASE_LEN))
+ return -1;
+
+ /* prepare sql */
+ m_conditions.setSize (1);
+ m_conditions[0] = this->string (0);
+
+ for (guint i = 0; i < pinyin_len; i++) {
+ const Pinyin *p;
+ gboolean fs1, fs2;
+ p = pinyin[i + pinyin_begin];
+
+ fs1 = pinyin_option_check_sheng (option, p->sheng_id, p->fsheng_id);
+ fs2 = pinyin_option_check_sheng (option, p->sheng_id, p->fsheng_id_2);
+
+ if (G_LIKELY (i > 0))
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length (),
+ " AND ");
+
+ if (fs1 || fs2) {
+ if (G_LIKELY (i < DB_INDEX_SIZE)) {
+ if (fs1 && fs2 == 0) {
+ conditionsDouble ();
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length () >> 1,
+ "s%d=%d", i, p->sheng_id);
+ _conditions_append_printf (m_conditions,
+ m_conditions.length () >> 1, m_conditions.length (),
+ "s%d=%d", i, p->fsheng_id);
+ }
+ else if (fs1 == 0 && fs2) {
+ conditionsDouble ();
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length () >> 1,
+ "s%d=%d", i, p->sheng_id);
+ _conditions_append_printf (m_conditions,
+ m_conditions.length () >> 1, m_conditions.length (),
+ "s%d=%d", i, p->fsheng_id_2);
+ }
+ else {
+ gint len = m_conditions.length ();
+ conditionsTriple ();
+ _conditions_append_printf (m_conditions,
+ 0, len,
+ "s%d=%d", i, p->sheng_id);
+ _conditions_append_printf (m_conditions,
+ len, len << 1,
+ "s%d=%d", i, p->fsheng_id);
+ _conditions_append_printf (m_conditions,
+ len << 1, m_conditions.length (),
+ "s%d=%d", i, p->fsheng_id_2);
+ }
+ }
+ else {
+ if (fs1 && fs2 == 0) {
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length (),
+ "s%d IN (%d,%d)", i, p->sheng_id, p->fsheng_id);
+ }
+ else if (fs1 == 0 && fs2) {
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length (),
+ "s%d IN (%d,%d)", i, p->sheng_id, p->fsheng_id_2);
+ }
+ else {
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length (),
+ "s%d IN (%d,%d,%d)", i, p->sheng_id, p->fsheng_id, p->fsheng_id_2);
+ }
+ }
+ }
+ else {
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length (),
+ "s%d=%d", i, p->sheng_id);
+ }
+
+ if (p->yun_id != PINYIN_ID_ZERO) {
+ if (pinyin_option_check_yun (option, p->yun_id, p->fyun_id)) {
+ if (G_LIKELY (i < DB_INDEX_SIZE)) {
+ conditionsDouble ();
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length () >> 1,
+ " AND y%d=%d", i, p->yun_id);
+ _conditions_append_printf (m_conditions,
+ m_conditions.length () >> 1, m_conditions.length (),
+ " and y%d=%d", i, p->fyun_id);
+ }
+ else {
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length (),
+ " AND y%d IN (%d,%d)", i, p->yun_id, p->fyun_id);
+ }
+ }
+ else {
+ _conditions_append_printf (m_conditions,
+ 0, m_conditions.length (),
+ " AND y%d=%d", i, p->yun_id);
+ }
+ }
+ }
+
+
+ m_buffer.truncate (0);
+ for (guint i = 0; i < m_conditions.length (); i++) {
+ if (G_UNLIKELY (i == 0))
+ m_buffer << " (" << (*m_conditions[i]) << ")\n";
+ else
+ m_buffer << " OR (" << (*m_conditions[i]) << ")\n";
+ }
+ m_conditions.removeAll ();
+
+ m_sql.printf ("SELECT * FROM ("
+ "SELECT 0 AS user_freq, * FROM main.py_phrase_%d WHERE %s UNION ALL "
+ "SELECT * FROM userdb.py_phrase_%d WHERE %s) "
+ "GROUP BY phrase ORDER BY user_freq DESC, freq DESC ",
+ pinyin_len - 1, (const gchar *) m_buffer, pinyin_len - 1, (const gchar *)m_buffer);
+ if (m > 0)
+ m_sql << "LIMIT " << m;
+#if 0
+ g_debug ("sql =\n%s", (const gchar *)m_sql);
+#endif
+
+ /* query database */
+ sqlite3_stmt *stmt;
+ if (sqlite3_prepare (m_db,
+ (const gchar *) m_sql,
+ -1,
+ &stmt,
+ NULL) != SQLITE_OK) {
+ g_debug ("parse sql failed!\n %s", (const gchar *)m_sql);
+ return -1;
+ }
+
+ gint row = 0;
+ while (sqlite3_step (stmt) == SQLITE_ROW) {
+ result.setSize (result.length () + 1);
+ Phrase &p = result[result.length() - 1];
+
+ strcpy (p.phrase, (gchar *) sqlite3_column_text (stmt, DB_COLUMN_PHRASE));
+ p.freq = sqlite3_column_int (stmt, DB_COLUMN_FREQ);
+ p.user_freq = sqlite3_column_int (stmt, DB_COLUMN_USER_FREQ);
+ p.len = pinyin_len;
+
+ for (guint i = 0; i < pinyin_len; i++) {
+ p.pinyin_id[i][0] = sqlite3_column_int (stmt, (i << 1) + DB_COLUMN_S0);
+ p.pinyin_id[i][1] = sqlite3_column_int (stmt, (i << 1) + DB_COLUMN_S0 + 1);
+ }
+ row ++;
+ }
+
+ sqlite3_finalize (stmt);
+ return row;
+}
+
+inline void
+Database::phraseWhereSql (const Phrase & p, String & sql)
+{
+ sql << " WHERE";
+ sql << " s0=" << p.pinyin_id[0][0]
+ << " AND y0=" << p.pinyin_id[0][1];
+ for (guint i = 1; i < p.len; i++) {
+ sql << " AND s" << i << '=' << p.pinyin_id[i][0]
+ << " AND y" << i << '=' << p.pinyin_id[i][1];
+ }
+ sql << " AND phrase=\"" << p.phrase << "\"";
+
+}
+
+inline void
+Database::phraseSql (const Phrase & p, String & sql)
+{
+ sql << "INSERT OR IGNORE INTO userdb.py_phrase_" << p.len - 1
+ << " VALUES(" << 0 /* user_freq */
+ << ",\"" << p.phrase << '"' /* phrase */
+ << ',' << p.freq; /* freq */
+ for (guint i = 0; i < p.len; i++) {
+ sql << ',' << p.pinyin_id[i][0] << ',' << p.pinyin_id[i][1];
+ }
+ sql << ");\n";
+
+ sql << "UPDATE userdb.py_phrase_" << p.len - 1
+ << " SET user_freq=user_freq+1";
+
+ phraseWhereSql (p, sql);
+ sql << "\n;";
+}
+
+void
+Database::commit (const PhraseArray &phrases)
+{
+ gchar *errmsg;
+ Phrase phrase = {""};
+
+ m_sql = "BEGIN TRANSACTION;\n";
+ for (guint i = 0; i < phrases.length (); i++) {
+ strcat (phrase.phrase, phrases[i].phrase);
+ for (guint j = 0; j < phrases[i].len; j++) {
+ phrase.pinyin_id[phrase.len + j][0] = phrases[i].pinyin_id[j][0];
+ phrase.pinyin_id[phrase.len + j][1] = phrases[i].pinyin_id[j][1];
+ }
+ phrase.len += phrases[i].len;
+ phraseSql (phrases[i], m_sql);
+ }
+ if (phrases.length () > 1)
+ phraseSql (phrase, m_sql);
+ m_sql << "COMMIT;";
+
+ if (sqlite3_exec (m_db, m_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
+ g_debug ("%s", errmsg);
+ g_debug ("m_sql = %s", (const gchar *)m_sql);
+ sqlite3_free (errmsg);
+ }
+}
+
+void
+Database::remove (const Phrase & phrase)
+{
+ gchar *errmsg;
+ m_sql = "BEGIN TRANSACTION;\n";
+ m_sql << "DELETE FROM userdb.py_phrase_" << phrase.len - 1;
+ phraseWhereSql (phrase, m_sql);
+ m_sql << ";\n";
+ m_sql << "COMMIT;\n";
+
+ if (sqlite3_exec (m_db, m_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
+ g_debug ("%s", errmsg);
+ sqlite3_free (errmsg);
+ }
+
+}
+
+};
diff --git a/src/Database.h b/src/Database.h
new file mode 100644
index 0000000..f07f212
--- /dev/null
+++ b/src/Database.h
@@ -0,0 +1,60 @@
+/* vim:set et sts=4: */
+#ifndef __PY_DATABASE_H__
+#define __PY_DATABASE_H__
+
+#include <sqlite3.h>
+#include "Types.h"
+#include "Array.h"
+#include "String.h"
+#include "PinyinArray.h"
+#include "PhraseArray.h"
+
+namespace PY {
+
+class Database {
+public:
+ Database ();
+ ~Database ();
+ gint query (const PinyinArray & pinyin,
+ guint m,
+ guint option,
+ PhraseArray & result);
+
+ gint query (const PinyinArray & pinyin,
+ guint pinyin_begin,
+ guint pinyin_len,
+ gint m,
+ guint option,
+ PhraseArray & result);
+ void commit (const PhraseArray & phrases);
+ void remove (const Phrase & phrase);
+
+ String *string (guint i) {
+ guint j;
+ for (j = m_strings.length (); j <= i; j++) {
+ m_strings.append (new String (256));
+ }
+ return &(m_strings[i]->truncate (0));
+ }
+
+ void conditionsDouble (void);
+ void conditionsTriple (void);
+
+private:
+ gboolean init (void);
+ gboolean initUserDatabase (const gchar *userdb);
+ void prefetch (void);
+ void phraseSql (const Phrase & p, String & sql);
+ void phraseWhereSql (const Phrase & p, String & sql);
+
+private:
+ sqlite3 *m_db; /* sqlite3 database */
+ String m_sql; /* sql stmt */
+ String m_buffer; /* temp buffer */
+ Array<String *> m_conditions; /* select conditions */
+ Array<String *> m_strings; /* strings */
+};
+
+};
+
+#endif
diff --git a/src/DoublePinyinEditor.cc b/src/DoublePinyinEditor.cc
new file mode 100644
index 0000000..eb872a9
--- /dev/null
+++ b/src/DoublePinyinEditor.cc
@@ -0,0 +1,246 @@
+#include "Config.h"
+#include "DoublePinyinEditor.h"
+
+namespace PY {
+
+#include "DoublePinyinTable.h"
+
+DoublePinyinEditor::DoublePinyinEditor (void)
+{
+}
+
+static inline gint
+char_to_id (gint ch)
+{
+ switch (ch) {
+ case IBUS_a ... IBUS_z:
+ return ch - IBUS_a;
+ case IBUS_semicolon:
+ return 26;
+ default:
+ return -1;
+ }
+}
+
+inline const Pinyin *
+DoublePinyinEditor::isPinyin (gchar i, gchar j)
+{
+ const Pinyin *pinyin;
+ gint schema = Config::doublePinyinSchema ();
+ gint sheng = double_pinyin_map[schema].sheng[char_to_id(i)];
+ const gint *yun = double_pinyin_map[schema].yun[char_to_id(j)];
+
+ if (sheng == PINYIN_ID_VOID || yun[0] == PINYIN_ID_VOID)
+ return NULL;
+
+ if (sheng == PINYIN_ID_ZERO && yun[0] == PINYIN_ID_ZERO)
+ return NULL;
+
+ pinyin = m_parser.isPinyin (sheng, yun[0], Config::option () & PINYIN_FUZZY_ALL);
+ if (pinyin == NULL && yun[1] != PINYIN_ID_ZERO)
+ pinyin = m_parser.isPinyin (sheng, yun[1], Config::option () & PINYIN_FUZZY_ALL);
+ return pinyin;
+}
+
+gboolean
+DoublePinyinEditor::insert (gint ch)
+{
+ /* is full */
+ if (G_UNLIKELY (m_text.length () >= MAX_PINYIN_LEN))
+ return FALSE;
+
+ gint i = char_to_id (ch);
+ if (i < 0)
+ return FALSE;
+
+ m_text.insert (m_cursor++, ch);
+
+ if (m_cursor != m_pinyin_len + 2)
+ return TRUE;
+
+ const Pinyin *pinyin = isPinyin (m_text[m_cursor - 2], ch);
+ if (pinyin == NULL)
+ return TRUE;
+ m_pinyin << pinyin;
+ m_pinyin_len += 2;
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::removeCharBefore (void)
+{
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+ m_cursor --;
+ m_text.erase (m_cursor, 1);
+
+ if (m_cursor < m_pinyin_len) {
+ m_pinyin.pop ();
+ m_pinyin_len -= 2;
+ }
+
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::removeCharAfter (void)
+{
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+ m_text.erase (m_cursor, 1);
+
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::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 {
+ m_pinyin.pop ();
+ cursor = m_cursor - 2;
+ m_pinyin_len -= 2;
+ }
+
+ m_text.erase (cursor, m_cursor - cursor);
+ m_cursor = cursor;
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::removeWordAfter (void)
+{
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+ m_text.erase (m_cursor, -1);
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::moveCursorLeft (void)
+{
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+ m_cursor --;
+
+ if (m_cursor >= m_pinyin_len)
+ return TRUE;
+
+ m_pinyin.pop ();
+ m_pinyin_len -= 2;
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::moveCursorRight (void)
+{
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+ m_cursor ++;
+ updatePinyin ();
+
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::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;
+ }
+
+ m_pinyin.pop ();
+ m_cursor -= 2;
+ m_pinyin_len -= 2;
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::moveCursorRightByWord (void)
+{
+ return moveCursorToEnd ();
+}
+
+gboolean
+DoublePinyinEditor::moveCursorToBegin (void)
+{
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+ m_cursor = 0;
+ m_pinyin.removeAll ();
+ m_pinyin_len = 0;
+
+ return TRUE;
+}
+
+gboolean
+DoublePinyinEditor::moveCursorToEnd (void)
+{
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+ m_cursor = m_text.length ();
+ updatePinyin ();
+
+ return TRUE;
+}
+gboolean
+DoublePinyinEditor::reset (void)
+{
+ gboolean retval = FALSE;
+ if (m_cursor != 0) {
+ m_cursor = 0;
+ retval = TRUE;
+ }
+
+ if (m_text.length () != 0) {
+ m_text.truncate (0);
+ retval = TRUE;
+ }
+
+ if (retval)
+ updatePinyin ();
+
+ return retval;
+ }
+
+
+void
+DoublePinyinEditor::updatePinyin (void)
+{
+ if (G_UNLIKELY (m_text.isEmpty ())) {
+ m_pinyin.removeAll ();
+ m_pinyin_len = 0;
+ return;
+ }
+
+ m_pinyin.removeAll ();
+ m_pinyin_len = 0;
+ for (guint i = 0; i + 1 < m_cursor; i+= 2) {
+ const Pinyin *pinyin = isPinyin (m_text[i], m_text[i + 1]);
+ if (pinyin == NULL)
+ break;
+ m_pinyin << pinyin;
+ m_pinyin_len += 2;
+ }
+}
+
+};
+
+
diff --git a/src/DoublePinyinEditor.h b/src/DoublePinyinEditor.h
new file mode 100644
index 0000000..75d419a
--- /dev/null
+++ b/src/DoublePinyinEditor.h
@@ -0,0 +1,36 @@
+#ifndef __PY_DOUBLE_PINYIN_EDITOR_H_
+#define __PY_DOUBLE_PINYIN_EDITOR_H_
+
+#include "PinyinEditor.h"
+
+namespace PY {
+
+class DoublePinyinEditor : public PinyinEditor {
+
+public:
+ DoublePinyinEditor (void);
+
+ 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);
+
+ gboolean reset (void);
+private:
+ void updatePinyin (void);
+ const Pinyin *isPinyin (gchar i, gchar j);
+
+};
+
+};
+
+#endif
diff --git a/src/DoublePinyinTable.h b/src/DoublePinyinTable.h
new file mode 100644
index 0000000..f75f09d
--- /dev/null
+++ b/src/DoublePinyinTable.h
@@ -0,0 +1,301 @@
+static const gint double_pinyin_mspy_sheng[] = {
+ PINYIN_ID_VOID, // A
+ PINYIN_ID_B, // B
+ PINYIN_ID_C, // C
+ PINYIN_ID_D, // D
+ PINYIN_ID_VOID, // E
+ PINYIN_ID_F, // F
+ PINYIN_ID_G, // G
+ PINYIN_ID_H, // H
+ PINYIN_ID_CH, // I
+ PINYIN_ID_J, // J
+ PINYIN_ID_K, // K
+ PINYIN_ID_L, // L
+ PINYIN_ID_M, // M
+ PINYIN_ID_N, // N
+ PINYIN_ID_ZERO, // O
+ PINYIN_ID_P, // P
+ PINYIN_ID_Q, // Q
+ PINYIN_ID_R, // R
+ PINYIN_ID_S, // S
+ PINYIN_ID_T, // T
+ PINYIN_ID_SH, // U
+ PINYIN_ID_ZH, // V
+ PINYIN_ID_W, // W
+ PINYIN_ID_X, // X
+ PINYIN_ID_Y, // Y
+ PINYIN_ID_Z, // Z
+ PINYIN_ID_VOID, // ;
+};
+static const gint double_pinyin_mspy_yun[][2] = {
+ { PINYIN_ID_A, PINYIN_ID_VOID }, // A
+ { PINYIN_ID_OU, PINYIN_ID_VOID }, // B
+ { PINYIN_ID_IAO, PINYIN_ID_VOID }, // C
+ { PINYIN_ID_UANG, PINYIN_ID_IANG }, // D
+ { PINYIN_ID_E, PINYIN_ID_VOID }, // E
+ { PINYIN_ID_EN, PINYIN_ID_VOID }, // F
+ { PINYIN_ID_ENG, PINYIN_ID_NG }, // G
+ { PINYIN_ID_ANG, PINYIN_ID_VOID }, // H
+ { PINYIN_ID_I, PINYIN_ID_VOID }, // I
+ { PINYIN_ID_AN, PINYIN_ID_VOID }, // J
+ { PINYIN_ID_AO, PINYIN_ID_VOID }, // K
+ { PINYIN_ID_AI, PINYIN_ID_VOID }, // L
+ { PINYIN_ID_IAN, PINYIN_ID_VOID }, // M
+ { PINYIN_ID_IN, PINYIN_ID_VOID }, // N
+ { PINYIN_ID_UO, PINYIN_ID_O }, // O
+ { PINYIN_ID_UN, PINYIN_ID_VOID }, // P
+ { PINYIN_ID_IU, PINYIN_ID_VOID }, // Q
+ { PINYIN_ID_UAN, PINYIN_ID_ER }, // R
+ { PINYIN_ID_ONG, PINYIN_ID_IONG }, // S
+ { PINYIN_ID_UE, PINYIN_ID_VOID }, // T
+ { PINYIN_ID_U, PINYIN_ID_VOID }, // U
+ { PINYIN_ID_UI, PINYIN_ID_UE }, // V
+ { PINYIN_ID_IA, PINYIN_ID_UA }, // W
+ { PINYIN_ID_IE, PINYIN_ID_VOID }, // X
+ { PINYIN_ID_UAI, PINYIN_ID_V }, // Y
+ { PINYIN_ID_EI, PINYIN_ID_VOID }, // Z
+ { PINYIN_ID_ING, PINYIN_ID_VOID }, // ;
+};
+static const gint double_pinyin_zrm_sheng[] = {
+ PINYIN_ID_VOID, // A
+ PINYIN_ID_B, // B
+ PINYIN_ID_C, // C
+ PINYIN_ID_D, // D
+ PINYIN_ID_VOID, // E
+ PINYIN_ID_F, // F
+ PINYIN_ID_G, // G
+ PINYIN_ID_H, // H
+ PINYIN_ID_CH, // I
+ PINYIN_ID_J, // J
+ PINYIN_ID_K, // K
+ PINYIN_ID_L, // L
+ PINYIN_ID_M, // M
+ PINYIN_ID_N, // N
+ PINYIN_ID_ZERO, // O
+ PINYIN_ID_P, // P
+ PINYIN_ID_Q, // Q
+ PINYIN_ID_R, // R
+ PINYIN_ID_S, // S
+ PINYIN_ID_T, // T
+ PINYIN_ID_SH, // U
+ PINYIN_ID_ZH, // V
+ PINYIN_ID_W, // W
+ PINYIN_ID_X, // X
+ PINYIN_ID_Y, // Y
+ PINYIN_ID_Z, // Z
+ PINYIN_ID_VOID, // ;
+};
+static const gint double_pinyin_zrm_yun[][2] = {
+ { PINYIN_ID_A, PINYIN_ID_VOID }, // A
+ { PINYIN_ID_OU, PINYIN_ID_VOID }, // B
+ { PINYIN_ID_IAO, PINYIN_ID_VOID }, // C
+ { PINYIN_ID_UANG, PINYIN_ID_IANG }, // D
+ { PINYIN_ID_E, PINYIN_ID_VOID }, // E
+ { PINYIN_ID_EN, PINYIN_ID_VOID }, // F
+ { PINYIN_ID_ENG, PINYIN_ID_NG }, // G
+ { PINYIN_ID_ANG, PINYIN_ID_VOID }, // H
+ { PINYIN_ID_I, PINYIN_ID_VOID }, // I
+ { PINYIN_ID_AN, PINYIN_ID_VOID }, // J
+ { PINYIN_ID_AO, PINYIN_ID_VOID }, // K
+ { PINYIN_ID_AI, PINYIN_ID_VOID }, // L
+ { PINYIN_ID_IAN, PINYIN_ID_VOID }, // M
+ { PINYIN_ID_IN, PINYIN_ID_VOID }, // N
+ { PINYIN_ID_UO, PINYIN_ID_O }, // O
+ { PINYIN_ID_UN, PINYIN_ID_VOID }, // P
+ { PINYIN_ID_IU, PINYIN_ID_VOID }, // Q
+ { PINYIN_ID_UAN, PINYIN_ID_ER }, // R
+ { PINYIN_ID_ONG, PINYIN_ID_IONG }, // S
+ { PINYIN_ID_UE, PINYIN_ID_VOID }, // T
+ { PINYIN_ID_U, PINYIN_ID_VOID }, // U
+ { PINYIN_ID_UI, PINYIN_ID_V }, // V
+ { PINYIN_ID_IA, PINYIN_ID_UA }, // W
+ { PINYIN_ID_IE, PINYIN_ID_VOID }, // X
+ { PINYIN_ID_UAI, PINYIN_ID_ING }, // Y
+ { PINYIN_ID_EI, PINYIN_ID_VOID }, // Z
+ { PINYIN_ID_VOID, PINYIN_ID_VOID }, // ;
+};
+static const gint double_pinyin_abc_sheng[] = {
+ PINYIN_ID_ZH, // A
+ PINYIN_ID_B, // B
+ PINYIN_ID_C, // C
+ PINYIN_ID_D, // D
+ PINYIN_ID_CH, // E
+ PINYIN_ID_F, // F
+ PINYIN_ID_G, // G
+ PINYIN_ID_H, // H
+ PINYIN_ID_VOID, // I
+ PINYIN_ID_J, // J
+ PINYIN_ID_K, // K
+ PINYIN_ID_L, // L
+ PINYIN_ID_M, // M
+ PINYIN_ID_N, // N
+ PINYIN_ID_ZERO, // O
+ PINYIN_ID_P, // P
+ PINYIN_ID_Q, // Q
+ PINYIN_ID_R, // R
+ PINYIN_ID_S, // S
+ PINYIN_ID_T, // T
+ PINYIN_ID_VOID, // U
+ PINYIN_ID_SH, // V
+ PINYIN_ID_W, // W
+ PINYIN_ID_X, // X
+ PINYIN_ID_Y, // Y
+ PINYIN_ID_Z, // Z
+ PINYIN_ID_VOID, // ;
+};
+static const gint double_pinyin_abc_yun[][2] = {
+ { PINYIN_ID_A, PINYIN_ID_VOID }, // A
+ { PINYIN_ID_OU, PINYIN_ID_VOID }, // B
+ { PINYIN_ID_IN, PINYIN_ID_UAI }, // C
+ { PINYIN_ID_IA, PINYIN_ID_UA }, // D
+ { PINYIN_ID_E, PINYIN_ID_VOID }, // E
+ { PINYIN_ID_EN, PINYIN_ID_VOID }, // F
+ { PINYIN_ID_ENG, PINYIN_ID_NG }, // G
+ { PINYIN_ID_ANG, PINYIN_ID_VOID }, // H
+ { PINYIN_ID_I, PINYIN_ID_VOID }, // I
+ { PINYIN_ID_AN, PINYIN_ID_VOID }, // J
+ { PINYIN_ID_AO, PINYIN_ID_VOID }, // K
+ { PINYIN_ID_AI, PINYIN_ID_VOID }, // L
+ { PINYIN_ID_UE, PINYIN_ID_UI }, // M
+ { PINYIN_ID_UN, PINYIN_ID_VOID }, // N
+ { PINYIN_ID_UO, PINYIN_ID_O }, // O
+ { PINYIN_ID_UAN, PINYIN_ID_VOID }, // P
+ { PINYIN_ID_EI, PINYIN_ID_VOID }, // Q
+ { PINYIN_ID_ER, PINYIN_ID_IU }, // R
+ { PINYIN_ID_ONG, PINYIN_ID_IONG }, // S
+ { PINYIN_ID_IANG, PINYIN_ID_UANG }, // T
+ { PINYIN_ID_U, PINYIN_ID_VOID }, // U
+ { PINYIN_ID_V, PINYIN_ID_UE }, // V
+ { PINYIN_ID_IAN, PINYIN_ID_VOID }, // W
+ { PINYIN_ID_IE, PINYIN_ID_VOID }, // X
+ { PINYIN_ID_ING, PINYIN_ID_VOID }, // Y
+ { PINYIN_ID_IAO, PINYIN_ID_VOID }, // Z
+ { PINYIN_ID_VOID, PINYIN_ID_VOID }, // ;
+};
+static const gint double_pinyin_zgpy_sheng[] = {
+ PINYIN_ID_CH, // A
+ PINYIN_ID_B, // B
+ PINYIN_ID_C, // C
+ PINYIN_ID_D, // D
+ PINYIN_ID_VOID, // E
+ PINYIN_ID_F, // F
+ PINYIN_ID_G, // G
+ PINYIN_ID_H, // H
+ PINYIN_ID_SH, // I
+ PINYIN_ID_J, // J
+ PINYIN_ID_K, // K
+ PINYIN_ID_L, // L
+ PINYIN_ID_M, // M
+ PINYIN_ID_N, // N
+ PINYIN_ID_ZERO, // O
+ PINYIN_ID_P, // P
+ PINYIN_ID_Q, // Q
+ PINYIN_ID_R, // R
+ PINYIN_ID_S, // S
+ PINYIN_ID_T, // T
+ PINYIN_ID_ZH, // U
+ PINYIN_ID_VOID, // V
+ PINYIN_ID_W, // W
+ PINYIN_ID_X, // X
+ PINYIN_ID_Y, // Y
+ PINYIN_ID_Z, // Z
+ PINYIN_ID_VOID, // ;
+};
+static const gint double_pinyin_zgpy_yun[][2] = {
+ { PINYIN_ID_A, PINYIN_ID_VOID }, // A
+ { PINYIN_ID_IAO, PINYIN_ID_VOID }, // B
+ { PINYIN_ID_VOID, PINYIN_ID_VOID }, // C
+ { PINYIN_ID_IE, PINYIN_ID_VOID }, // D
+ { PINYIN_ID_E, PINYIN_ID_VOID }, // E
+ { PINYIN_ID_IAN, PINYIN_ID_VOID }, // F
+ { PINYIN_ID_IANG, PINYIN_ID_UANG }, // G
+ { PINYIN_ID_ONG, PINYIN_ID_IONG }, // H
+ { PINYIN_ID_I, PINYIN_ID_VOID }, // I
+ { PINYIN_ID_ER, PINYIN_ID_IU }, // J
+ { PINYIN_ID_EI, PINYIN_ID_VOID }, // K
+ { PINYIN_ID_UAN, PINYIN_ID_VOID }, // L
+ { PINYIN_ID_UN, PINYIN_ID_VOID }, // M
+ { PINYIN_ID_UE, PINYIN_ID_UI }, // N
+ { PINYIN_ID_UO, PINYIN_ID_O }, // O
+ { PINYIN_ID_AI, PINYIN_ID_VOID }, // P
+ { PINYIN_ID_AO, PINYIN_ID_VOID }, // Q
+ { PINYIN_ID_AN, PINYIN_ID_VOID }, // R
+ { PINYIN_ID_ANG, PINYIN_ID_VOID }, // S
+ { PINYIN_ID_ENG, PINYIN_ID_NG }, // T
+ { PINYIN_ID_U, PINYIN_ID_VOID }, // U
+ { PINYIN_ID_V, PINYIN_ID_VOID }, // V
+ { PINYIN_ID_EN, PINYIN_ID_VOID }, // W
+ { PINYIN_ID_IA, PINYIN_ID_UA }, // X
+ { PINYIN_ID_IN, PINYIN_ID_UAI }, // Y
+ { PINYIN_ID_OU, PINYIN_ID_VOID }, // Z
+ { PINYIN_ID_ING, PINYIN_ID_VOID }, // ;
+};
+static const gint double_pinyin_pyjj_sheng[] = {
+ PINYIN_ID_ZERO, // A
+ PINYIN_ID_B, // B
+ PINYIN_ID_C, // C
+ PINYIN_ID_D, // D
+ PINYIN_ID_VOID, // E
+ PINYIN_ID_F, // F
+ PINYIN_ID_G, // G
+ PINYIN_ID_H, // H
+ PINYIN_ID_SH, // I
+ PINYIN_ID_J, // J
+ PINYIN_ID_K, // K
+ PINYIN_ID_L, // L
+ PINYIN_ID_M, // M
+ PINYIN_ID_N, // N
+ PINYIN_ID_ZERO, // O
+ PINYIN_ID_P, // P
+ PINYIN_ID_Q, // Q
+ PINYIN_ID_R, // R
+ PINYIN_ID_S, // S
+ PINYIN_ID_T, // T
+ PINYIN_ID_CH, // U
+ PINYIN_ID_ZH, // V
+ PINYIN_ID_W, // W
+ PINYIN_ID_X, // X
+ PINYIN_ID_Y, // Y
+ PINYIN_ID_Z, // Z
+ PINYIN_ID_VOID, // ;
+};
+static const gint double_pinyin_pyjj_yun[][2] = {
+ { PINYIN_ID_A, PINYIN_ID_VOID }, // A
+ { PINYIN_ID_IA, PINYIN_ID_UA }, // B
+ { PINYIN_ID_UAN, PINYIN_ID_VOID }, // C
+ { PINYIN_ID_AO, PINYIN_ID_VOID }, // D
+ { PINYIN_ID_E, PINYIN_ID_VOID }, // E
+ { PINYIN_ID_AN, PINYIN_ID_VOID }, // F
+ { PINYIN_ID_ANG, PINYIN_ID_VOID }, // G
+ { PINYIN_ID_IANG, PINYIN_ID_UANG }, // H
+ { PINYIN_ID_I, PINYIN_ID_VOID }, // I
+ { PINYIN_ID_IAN, PINYIN_ID_VOID }, // J
+ { PINYIN_ID_IAO, PINYIN_ID_VOID }, // K
+ { PINYIN_ID_IN, PINYIN_ID_VOID }, // L
+ { PINYIN_ID_IE, PINYIN_ID_VOID }, // M
+ { PINYIN_ID_IU, PINYIN_ID_VOID }, // N
+ { PINYIN_ID_UO, PINYIN_ID_O }, // O
+ { PINYIN_ID_OU, PINYIN_ID_VOID }, // P
+ { PINYIN_ID_ER, PINYIN_ID_ING }, // Q
+ { PINYIN_ID_EN, PINYIN_ID_VOID }, // R
+ { PINYIN_ID_AI, PINYIN_ID_VOID }, // S
+ { PINYIN_ID_ENG, PINYIN_ID_NG }, // T
+ { PINYIN_ID_U, PINYIN_ID_VOID }, // U
+ { PINYIN_ID_V, PINYIN_ID_UI }, // V
+ { PINYIN_ID_EI, PINYIN_ID_VOID }, // W
+ { PINYIN_ID_UAI, PINYIN_ID_UE }, // X
+ { PINYIN_ID_ONG, PINYIN_ID_IONG }, // Y
+ { PINYIN_ID_UN, PINYIN_ID_VOID }, // Z
+ { PINYIN_ID_VOID, PINYIN_ID_VOID }, // ;
+};
+
+static const struct {
+ const gint (&sheng)[27];
+ const gint (&yun)[27][2];
+} double_pinyin_map [] = {
+ { double_pinyin_mspy_sheng, double_pinyin_mspy_yun},
+ { double_pinyin_zrm_sheng, double_pinyin_zrm_yun},
+ { double_pinyin_abc_sheng, double_pinyin_abc_yun},
+ { double_pinyin_zgpy_sheng, double_pinyin_zgpy_yun},
+ { double_pinyin_pyjj_sheng, double_pinyin_pyjj_yun},
+};
diff --git a/src/Engine.cc b/src/Engine.cc
new file mode 100644
index 0000000..f15ff81
--- /dev/null
+++ b/src/Engine.cc
@@ -0,0 +1,207 @@
+/* vim:set et sts=4: */
+
+#include <ibus.h>
+#include <string.h>
+#include "Engine.h"
+#include "PinyinEngine.h"
+
+namespace PY {
+/* code of engine class of GObject */
+#define IBUS_PINYIN_ENGINE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_PINYIN_ENGINE, IBusPinyinEngine))
+#define IBUS_PINYIN_ENGINE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_PINYIN_ENGINE, IBusPinyinEngineClass))
+#define IBUS_IS_PINYIN_ENGINE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_PINYIN_ENGINE))
+#define IBUS_IS_PINYIN_ENGINE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_PINYIN_ENGINE))
+#define IBUS_PINYIN_ENGINE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_PINYIN_ENGINE, IBusPinyinEngineClass))
+
+
+typedef struct _IBusPinyinEngine IBusPinyinEngine;
+typedef struct _IBusPinyinEngineClass IBusPinyinEngineClass;
+
+struct _IBusPinyinEngine {
+ IBusEngine parent;
+
+ /* members */
+ PinyinEngine *engine;
+};
+
+struct _IBusPinyinEngineClass {
+ IBusEngineClass parent;
+};
+
+/* functions prototype */
+static void ibus_pinyin_engine_class_init (IBusPinyinEngineClass *klass);
+static void ibus_pinyin_engine_init (IBusPinyinEngine *pinyin);
+static void ibus_pinyin_engine_destroy (IBusPinyinEngine *pinyin);
+static gboolean ibus_pinyin_engine_process_key_event
+ (IBusEngine *engine,
+ guint keyval,
+ guint keycode,
+ guint modifiers);
+static void ibus_pinyin_engine_focus_in (IBusEngine *engine);
+static void ibus_pinyin_engine_focus_out (IBusEngine *engine);
+static void ibus_pinyin_engine_reset (IBusEngine *engine);
+static void ibus_pinyin_engine_enable (IBusEngine *engine);
+static void ibus_pinyin_engine_disable (IBusEngine *engine);
+
+#if 0
+static void ibus_engine_set_cursor_location (IBusEngine *engine,
+ gint x,
+ gint y,
+ gint w,
+ gint h);
+static void ibus_pinyin_engine_set_capabilities (IBusEngine *engine,
+ guint caps);
+#endif
+
+static void ibus_pinyin_engine_page_up (IBusEngine *engine);
+static void ibus_pinyin_engine_page_down (IBusEngine *engine);
+static void ibus_pinyin_engine_cursor_up (IBusEngine *engine);
+static void ibus_pinyin_engine_cursor_down (IBusEngine *engine);
+static void ibus_pinyin_engine_property_activate
+ (IBusEngine *engine,
+ const gchar *prop_name,
+ guint prop_state);
+#if 0
+static void ibus_pinyin_engine_property_show (IBusEngine *engine,
+ const gchar *prop_name);
+static void ibus_pinyin_engine_property_hide (IBusEngine *engine,
+ const gchar *prop_name);
+static void ibus_config_value_changed (IBusConfig *config,
+ const gchar *section,
+ const gchar *name,
+ GValue *value,
+ gpointer user_data);
+#endif
+
+static IBusEngineClass *parent_class = NULL;
+
+GType
+ibus_pinyin_engine_get_type (void)
+{
+ static GType type = 0;
+
+ static const GTypeInfo type_info = {
+ sizeof (IBusPinyinEngineClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ibus_pinyin_engine_class_init,
+ NULL,
+ NULL,
+ sizeof (IBusPinyinEngine),
+ 0,
+ (GInstanceInitFunc) ibus_pinyin_engine_init,
+ };
+
+ if (type == 0) {
+ type = g_type_register_static (IBUS_TYPE_ENGINE,
+ "IBusPinyinEngine",
+ &type_info,
+ (GTypeFlags) 0);
+ }
+
+ return type;
+}
+
+static void
+ibus_pinyin_engine_class_init (IBusPinyinEngineClass *klass)
+{
+ // GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
+ IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass);
+
+ parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass);
+
+ ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_pinyin_engine_destroy;
+
+ engine_class->process_key_event = ibus_pinyin_engine_process_key_event;
+
+ engine_class->reset = ibus_pinyin_engine_reset;
+ engine_class->enable = ibus_pinyin_engine_enable;
+ engine_class->disable = ibus_pinyin_engine_disable;
+
+ engine_class->focus_in = ibus_pinyin_engine_focus_in;
+ engine_class->focus_out = ibus_pinyin_engine_focus_out;
+
+ engine_class->page_up = ibus_pinyin_engine_page_up;
+ engine_class->page_down = ibus_pinyin_engine_page_down;
+
+ engine_class->cursor_up = ibus_pinyin_engine_cursor_up;
+ engine_class->cursor_down = ibus_pinyin_engine_cursor_down;
+
+ engine_class->property_activate = ibus_pinyin_engine_property_activate;
+}
+
+static void
+ibus_pinyin_engine_init (IBusPinyinEngine *pinyin)
+{
+ if (g_object_is_floating (pinyin))
+ g_object_ref_sink (pinyin); // make engine sink
+ pinyin->engine = new PinyinEngine (IBUS_ENGINE (pinyin));
+}
+
+static void
+ibus_pinyin_engine_destroy (IBusPinyinEngine *pinyin)
+{
+ if (pinyin->engine) {
+ delete pinyin->engine;
+ pinyin->engine = NULL;
+ }
+ IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)pinyin);
+}
+
+static gboolean
+ibus_pinyin_engine_process_key_event (IBusEngine *engine,
+ guint keyval,
+ guint keycode,
+ guint modifiers)
+{
+ IBusPinyinEngine *pinyin = (IBusPinyinEngine *) engine;
+ return pinyin->engine->processKeyEvent (keyval, keycode, modifiers);
+}
+
+static void
+ibus_pinyin_engine_property_activate (IBusEngine *engine,
+ const gchar *prop_name,
+ guint prop_state)
+{
+ IBusPinyinEngine *pinyin = (IBusPinyinEngine *) engine;
+ pinyin->engine->propertyActivate (prop_name, prop_state);
+}
+#define FUNCTION(name, Name) \
+ static void \
+ ibus_pinyin_engine_##name (IBusEngine *engine) \
+ { \
+ IBusPinyinEngine *pinyin = (IBusPinyinEngine *) engine; \
+ pinyin->engine->Name (); \
+ parent_class->name (engine); \
+ }
+FUNCTION(focus_in, focusIn)
+FUNCTION(focus_out, focusOut)
+FUNCTION(reset, reset)
+FUNCTION(enable, enable)
+FUNCTION(disable, disable)
+FUNCTION(page_up, pageUp)
+FUNCTION(page_down, pageDown)
+FUNCTION(cursor_up, cursorUp)
+FUNCTION(cursor_down, cursorDown)
+#undef FUNCTION
+
+
+#if 0
+static void
+ibus_config_value_changed (IBusConfig *config,
+ const gchar *section,
+ const gchar *name,
+ GValue *value,
+ gpointer user_data)
+{
+}
+#endif
+
+};
+
diff --git a/src/Engine.h b/src/Engine.h
new file mode 100644
index 0000000..0b39081
--- /dev/null
+++ b/src/Engine.h
@@ -0,0 +1,15 @@
+/* vim:set et sts=4: */
+#ifndef __PY_ENGINE_H__
+#define __PY_ENGINE_H__
+
+#include <ibus.h>
+
+namespace PY {
+
+#define IBUS_TYPE_PINYIN_ENGINE \
+ (PY::ibus_pinyin_engine_get_type ())
+
+GType ibus_pinyin_engine_get_type (void);
+};
+
+#endif
diff --git a/src/FullPinyinEditor.cc b/src/FullPinyinEditor.cc
new file mode 100644
index 0000000..0514f8a
--- /dev/null
+++ b/src/FullPinyinEditor.cc
@@ -0,0 +1,182 @@
+#include "Config.h"
+#include "FullPinyinEditor.h"
+
+namespace PY {
+
+
+FullPinyinEditor::FullPinyinEditor (void)
+{
+}
+
+
+gboolean
+FullPinyinEditor::insert (gint ch)
+{
+ /* is full */
+ if (G_UNLIKELY (m_text.length () >= MAX_PINYIN_LEN))
+ return FALSE;
+
+ m_text.insert (m_cursor++, ch);
+
+ if (G_UNLIKELY ((Config::option () & PINYIN_SIMPLE_PINYIN) == 0)) {
+ updatePinyin ();
+ }
+ else {
+ if (G_LIKELY ((m_cursor - 1 == m_pinyin_len) ||
+ (m_cursor - 2 == m_pinyin_len &&
+ m_text[m_pinyin_len] == '\''))) {
+ updatePinyin ();
+ }
+ }
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::removeCharBefore (void)
+{
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+ m_cursor --;
+ m_text.erase (m_cursor, 1);
+
+ updatePinyin ();
+
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::removeCharAfter (void)
+{
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+ m_text.erase (m_cursor, 1);
+
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::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.pop ();
+ cursor = m_cursor - p->len;
+ m_pinyin_len -= p->len;
+ }
+
+ m_text.erase (cursor, m_cursor - cursor);
+ m_cursor = cursor;
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::removeWordAfter (void)
+{
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+ m_text.erase (m_cursor, -1);
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::moveCursorLeft (void)
+{
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+ m_cursor --;
+ updatePinyin ();
+
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::moveCursorRight (void)
+{
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+ m_cursor ++;
+ updatePinyin ();
+
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::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.pop ();
+ m_cursor -= p->len;
+ m_pinyin_len -= p->len;
+
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::moveCursorRightByWord (void)
+{
+ return moveCursorToEnd ();
+}
+
+gboolean
+FullPinyinEditor::moveCursorToBegin (void)
+{
+ if (G_UNLIKELY (m_cursor == 0))
+ return FALSE;
+
+ m_cursor = 0;
+ m_pinyin.removeAll ();
+ m_pinyin_len = 0;
+
+ return TRUE;
+}
+
+gboolean
+FullPinyinEditor::moveCursorToEnd (void)
+{
+ if (G_UNLIKELY (m_cursor == m_text.length ()))
+ return FALSE;
+
+ m_cursor = m_text.length ();
+ updatePinyin ();
+
+ return TRUE;
+}
+
+void
+FullPinyinEditor::updatePinyin (void)
+{
+ if (G_UNLIKELY (m_text.isEmpty ())) {
+ m_pinyin.removeAll ();
+ m_pinyin_len = 0;
+ }
+ else {
+ m_pinyin_len = m_parser.parse (m_text,
+ m_cursor,
+ Config::option (),
+ m_pinyin,
+ MAX_PHRASE_LEN);
+ }
+}
+
+};
+
+
diff --git a/src/FullPinyinEditor.h b/src/FullPinyinEditor.h
new file mode 100644
index 0000000..6e7a253
--- /dev/null
+++ b/src/FullPinyinEditor.h
@@ -0,0 +1,52 @@
+#ifndef __PY_FULL_PINYIN_EDITOR_H_
+#define __PY_FULL_PINYIN_EDITOR_H_
+
+#include "PinyinEditor.h"
+
+namespace PY {
+
+class FullPinyinEditor : public PinyinEditor {
+
+public:
+ FullPinyinEditor (void);
+
+ 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);
+
+ gboolean reset (void) {
+ gboolean retval = FALSE;
+ if (m_cursor != 0) {
+ m_cursor = 0;
+ retval = TRUE;
+ }
+
+ if (m_text.length () != 0) {
+ m_text.truncate (0);
+ retval = TRUE;
+ }
+
+ if (retval)
+ updatePinyin ();
+
+ return retval;
+ }
+
+private:
+ void updatePinyin (void);
+
+};
+
+};
+
+#endif
diff --git a/src/HalfFullConverter.cc b/src/HalfFullConverter.cc
new file mode 100644
index 0000000..2d0b34e
--- /dev/null
+++ b/src/HalfFullConverter.cc
@@ -0,0 +1,98 @@
+
+#include "HalfFullConverter.h"
+
+namespace PY {
+
+const guint
+HalfFullConverter::m_table[][3] = {
+ { 0x0020, 0x3000, 1 },
+ { 0x0021, 0xFF01, 94 },
+ { 0x00A2, 0xFFE0, 2 },
+ { 0x00A5, 0xFFE5, 1 },
+ { 0x00A6, 0xFFE4, 1 },
+ { 0x00AC, 0xFFE2, 1 },
+ { 0x00AF, 0xFFE3, 1 },
+ { 0x20A9, 0xFFE6, 1 },
+ { 0xFF61, 0x3002, 1 },
+ { 0xFF62, 0x300C, 2 },
+ { 0xFF64, 0x3001, 1 },
+ { 0xFF65, 0x30FB, 1 },
+ { 0xFF66, 0x30F2, 1 },
+ { 0xFF67, 0x30A1, 1 },
+ { 0xFF68, 0x30A3, 1 },
+ { 0xFF69, 0x30A5, 1 },
+ { 0xFF6A, 0x30A7, 1 },
+ { 0xFF6B, 0x30A9, 1 },
+ { 0xFF6C, 0x30E3, 1 },
+ { 0xFF6D, 0x30E5, 1 },
+ { 0xFF6E, 0x30E7, 1 },
+ { 0xFF6F, 0x30C3, 1 },
+ { 0xFF70, 0x30FC, 1 },
+ { 0xFF71, 0x30A2, 1 },
+ { 0xFF72, 0x30A4, 1 },
+ { 0xFF73, 0x30A6, 1 },
+ { 0xFF74, 0x30A8, 1 },
+ { 0xFF75, 0x30AA, 2 },
+ { 0xFF77, 0x30AD, 1 },
+ { 0xFF78, 0x30AF, 1 },
+ { 0xFF79, 0x30B1, 1 },
+ { 0xFF7A, 0x30B3, 1 },
+ { 0xFF7B, 0x30B5, 1 },
+ { 0xFF7C, 0x30B7, 1 },
+ { 0xFF7D, 0x30B9, 1 },
+ { 0xFF7E, 0x30BB, 1 },
+ { 0xFF7F, 0x30BD, 1 },
+ { 0xFF80, 0x30BF, 1 },
+ { 0xFF81, 0x30C1, 1 },
+ { 0xFF82, 0x30C4, 1 },
+ { 0xFF83, 0x30C6, 1 },
+ { 0xFF84, 0x30C8, 1 },
+ { 0xFF85, 0x30CA, 6 },
+ { 0xFF8B, 0x30D2, 1 },
+ { 0xFF8C, 0x30D5, 1 },
+ { 0xFF8D, 0x30D8, 1 },
+ { 0xFF8E, 0x30DB, 1 },
+ { 0xFF8F, 0x30DE, 5 },
+ { 0xFF94, 0x30E4, 1 },
+ { 0xFF95, 0x30E6, 1 },
+ { 0xFF96, 0x30E8, 6 },
+ { 0xFF9C, 0x30EF, 1 },
+ { 0xFF9D, 0x30F3, 1 },
+ { 0xFFA0, 0x3164, 1 },
+ { 0xFFA1, 0x3131, 30 },
+ { 0xFFC2, 0x314F, 6 },
+ { 0xFFCA, 0x3155, 6 },
+ { 0xFFD2, 0x315B, 9 },
+ { 0xFFE9, 0x2190, 4 },
+ { 0xFFED, 0x25A0, 1 },
+ { 0xFFEE, 0x25CB, 1 },
+ { 0, 0, 0 },
+};
+
+gunichar
+HalfFullConverter::toFull (gunichar ch)
+{
+ for (guint i = 0; m_table[i][0] != 0; i++) {
+ if (G_UNLIKELY (ch < m_table[i][0]))
+ return ch;
+ if (G_UNLIKELY (ch < m_table[i][0] + m_table[i][2]))
+ return ch + m_table[i][1] - m_table[i][0];
+ }
+ return ch;
+}
+
+gunichar
+HalfFullConverter::toHalf (gunichar ch)
+{
+ for (guint i = 0; m_table[i][0] != 0; i++) {
+ if (G_LIKELY (ch < m_table[i][1]))
+ continue;
+ if (G_LIKELY (ch >= m_table[i][1] + m_table[i][2]))
+ continue;
+ return ch + m_table[i][0] + m_table[i][1];
+ }
+ return ch;
+}
+
+};
+
diff --git a/src/HalfFullConverter.h b/src/HalfFullConverter.h
new file mode 100644
index 0000000..7a18f6b
--- /dev/null
+++ b/src/HalfFullConverter.h
@@ -0,0 +1,19 @@
+#ifndef __PY_HALF_FULL_CONVERTER_H_
+#define __PY_HALF_FULL_CONVERTER_H_
+
+#include <glib.h>
+
+namespace PY {
+
+class HalfFullConverter {
+
+public:
+ static gunichar toFull (gunichar ch);
+ static gunichar toHalf (gunichar ch);
+
+private:
+ const static guint m_table[][3];
+};
+
+};
+#endif
diff --git a/src/LookupTable.h b/src/LookupTable.h
new file mode 100644
index 0000000..53b9b51
--- /dev/null
+++ b/src/LookupTable.h
@@ -0,0 +1,36 @@
+#ifndef __PY_LOOKUP_TABLE_H_
+#define __PY_LOOKUP_TABLE_H_
+
+#include <ibus.h>
+#include "Pointer.h"
+#include "Text.h"
+
+namespace PY {
+
+class LookupTable : public Pointer <IBusLookupTable> {
+public:
+ LookupTable (guint page_size = 10,
+ guint cursor_pos = 0,
+ gboolean cursor_visible = TRUE,
+ gboolean round = FALSE)
+ : Pointer <IBusLookupTable> (ibus_lookup_table_new (page_size, cursor_pos, cursor_visible, round)) { }
+
+ guint pageSize (void) { return ibus_lookup_table_get_page_size (*this); }
+ guint cursorPos (void) { return ibus_lookup_table_get_cursor_pos (*this); }
+
+ gboolean pageUp (void) { return ibus_lookup_table_page_up (*this); }
+ gboolean pageDown (void) { return ibus_lookup_table_page_down (*this); }
+ gboolean cursorUp (void) { return ibus_lookup_table_cursor_up (*this); }
+ gboolean cursorDown (void) { return ibus_lookup_table_cursor_down (*this); }
+
+ void setPageSize (guint size) { ibus_lookup_table_set_page_size (*this, size); }
+ void clear (void) { ibus_lookup_table_clear (*this); }
+
+ void appendCandidate (Text & text) {
+ ibus_lookup_table_append_candidate (*this, text);
+ }
+};
+
+};
+
+#endif
diff --git a/src/Main.cc b/src/Main.cc
new file mode 100644
index 0000000..acf6c44
--- /dev/null
+++ b/src/Main.cc
@@ -0,0 +1,100 @@
+/* vim:set et sts=4: */
+
+#include <ibus.h>
+#include <stdlib.h>
+#include <locale.h>
+#include "Engine.h"
+#include "Pointer.h"
+#include "Bus.h"
+#include "Config.h"
+
+using namespace PY;
+
+#define N_(text) text
+
+static Pointer<IBusFactory> factory;
+
+/* options */
+static gboolean ibus = FALSE;
+static gboolean verbose = FALSE;
+
+static const GOptionEntry entries[] =
+{
+ { "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", NULL },
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose", NULL },
+ { NULL },
+};
+
+
+static void
+ibus_disconnected_cb (IBusBus *bus,
+ gpointer user_data)
+{
+ g_debug ("bus disconnected");
+ ibus_quit ();
+}
+
+
+static void
+start_component (void)
+{
+ Pointer<IBusComponent> component;
+
+ ibus_init ();
+ Bus bus;
+ Config config (bus);
+
+ g_signal_connect (bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL);
+
+ component = ibus_component_new ("org.freedesktop.IBus.Pinyin",
+ N_("Pinyin input method"),
+ "0.1.0",
+ "GPL",
+ "Peng Huang <shawn.p.huang@gmail.com>",
+ "http://code.google.com/p/ibus/",
+ "",
+ "ibus-pinyin");
+ ibus_component_add_engine (component,
+ ibus_engine_desc_new ("pinyin",
+ N_("Pinyin input method"),
+ N_("Pinyin input method"),
+ "zh_CN",
+ "GPL",
+ "Peng Huang <shawn.p.huang@gmail.com>",
+ PKGDATADIR"/icons/ibus-pinyin.svg",
+ "us"));
+
+ factory = ibus_factory_new (ibus_bus_get_connection (bus));
+
+ ibus_factory_add_engine (factory, "pinyin", IBUS_TYPE_PINYIN_ENGINE);
+
+ if (ibus) {
+ ibus_bus_request_name (bus, "org.freedesktop.IBus.Pinyin", 0);
+ }
+ else {
+ ibus_bus_register_component (bus, component);
+ }
+
+ ibus_main ();
+}
+
+int
+main (gint argc, gchar **argv)
+{
+ GError *error = NULL;
+ GOptionContext *context;
+
+ setlocale (LC_ALL, "");
+
+ context = g_option_context_new ("- ibus pinyin engine component");
+
+ g_option_context_add_main_entries (context, entries, "ibus-pinyin");
+
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ g_print ("Option parsing failed: %s\n", error->message);
+ exit (-1);
+ }
+
+ start_component ();
+ return 0;
+}
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..39e6b53
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,158 @@
+# vim:set noet ts=4:
+#
+# ibus-pinyin - The Chinese PinYin engine for IBus
+#
+# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@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.
+
+@MAINTAINER_MODE_FALSE@skip_genpytable=test -f $@ ||
+GENPYTABLE = scripts/genpytable.py
+
+AM_CFLAGS = \
+ @IBUS_CFLAGS@ \
+ @SQLITE_CFLAGS@ \
+ -DPKGDATADIR=\"$(pkgdatadir)\" \
+ $(NULL)
+AM_LDFLAGS = \
+ @IBUS_LIBS@ \
+ @SQLITE_LIBS@ \
+ $(NULL)
+
+AM_CXXFLAGS = $(AM_CFLAGS)
+
+libexec_PROGRAMS = ibus-engine-pinyin
+
+ibus_engine_c_sources = \
+ Config.cc \
+ Database.cc \
+ DoublePinyinEditor.cc \
+ Engine.cc \
+ FullPinyinEditor.cc \
+ HalfFullConverter.cc \
+ Main.cc \
+ PhraseEditor.cc \
+ PinyinEditor.cc \
+ PinyinEngine.cc \
+ PinyinParser.cc \
+ SpecialTable.cc \
+ $(NULL)
+ibus_engine_h_sources = \
+ Array.h \
+ Bus.h \
+ Config.h \
+ Database.h \
+ DoublePinyinEditor.h \
+ DoublePinyinTable.h \
+ Engine.h \
+ FullPinyinEditor.h \
+ HalfFullConverter.h \
+ LookupTable.h \
+ PhraseArray.h \
+ PhraseEditor.h \
+ PinyinArray.h \
+ PinyinEditor.h \
+ PinyinEngine.h \
+ PinyinParser.h \
+ Pointer.h \
+ Property.h \
+ SpecialTable.h \
+ String.h \
+ Table.h \
+ Text.h \
+ Types.h \
+ Util.h \
+ $(NULL)
+ibus_engine_pinyin_SOURCES = \
+ $(ibus_engine_c_sources) \
+ $(ibus_engine_h_sources) \
+ $(NULL)
+ibus_engine_pinyin_CXXFLAGS = \
+ @IBUS_CFLAGS@ \
+ @SQLITE_CFLAGS@ \
+ @UUID_CFLAGS@ \
+ -DGETTEXT_PACKAGE=\"@GETTEXT_PACKAGE@\" \
+ -DPKGDATADIR=\"$(pkgdatadir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ $(NULL)
+ibus_engine_pinyin_LDFLAGS = \
+ @IBUS_LIBS@ \
+ @SQLITE_LIBS@ \
+ @UUID_LIBS@ \
+ $(NULL)
+
+BUILT_SOURCES = \
+ $(ibus_engine_built_c_sources) \
+ $(ibus_engine_built_h_sources) \
+ $(NULL)
+
+# db_DATA = \
+# py.db \
+# $(NULL)
+# dbdir = $(pkgdatadir)
+
+component_DATA = \
+ pinyin.xml \
+ $(NULL)
+componentdir = @datadir@/ibus/component
+
+EXTRA_DIST = \
+ pinyin.xml.in \
+ $(NULL)
+
+CLEANFILES = \
+ pinyin.xml \
+ $(NULL)
+
+check_PROGRAMS =
+
+# check_PROGRAMS += test-parser
+# test_parser_SOURCES = \
+# PinyinParser.cc \
+# Table.h \
+# $(NULL)
+# test_parser_CFLAGS = \
+# $(AM_CFLAGS) \
+# -DTEST \
+# $(NULL)
+#
+# check_PROGRAMS += test-pydatabase
+# test_pydatabase_SOURCES = \
+# Database.cc \
+# Database.h \
+# $(NULL)
+# test_pydatabase_CFLAGS = \
+# $(AM_CFLAGS) \
+# -DTEST \
+# $(NULL)
+
+TESTS = \
+ $(check_PROGRAMS) \
+ $(NULL)
+
+Table.h:
+ $(skip_genpytable) $(PYTHON) $(srcdir)/$(GENPYTABLE) > $@
+
+pinyin.xml: pinyin.xml.in
+ ( \
+ libexecdir=${libexecdir}; \
+ pkgdatadir=${pkgdatadir}; \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+test: ibus-engine-pinyin
+ $(builddir)/ibus-engine-pinyin
+
diff --git a/src/PhraseArray.h b/src/PhraseArray.h
new file mode 100644
index 0000000..f19cd55
--- /dev/null
+++ b/src/PhraseArray.h
@@ -0,0 +1,13 @@
+#ifndef __PY_PHRASE_ARRAY_H_
+#define __PY_PHRASE_ARRAY_H_
+
+#include "Types.h"
+#include "Array.h"
+
+namespace PY {
+
+typedef Array<Phrase> PhraseArray;
+
+};
+
+#endif
diff --git a/src/PhraseEditor.cc b/src/PhraseEditor.cc
new file mode 100644
index 0000000..83bb553
--- /dev/null
+++ b/src/PhraseEditor.cc
@@ -0,0 +1,157 @@
+#include "Config.h"
+#include "PhraseEditor.h"
+
+namespace PY {
+
+/* init static members */
+Database PhraseEditor::m_database;
+
+PhraseEditor::PhraseEditor (void)
+ : m_candidates (32),
+ m_phrases1 (8),
+ m_string1 (32),
+ m_phrases2 (8),
+ m_string2 (32),
+ m_pinyin (16),
+ m_cursor (0)
+{
+}
+
+PhraseEditor::~PhraseEditor (void)
+{
+}
+
+void
+PhraseEditor::update (const PinyinArray &pinyin)
+{
+ gboolean diff = FALSE;
+
+ if (m_cursor > pinyin.length ()) {
+ diff = TRUE;
+ }
+ else {
+ for (gint i = m_cursor - 1; i >= 0; i--) {
+ if (m_pinyin[i] != pinyin[i]) {
+ diff = TRUE;
+ break;
+ }
+ }
+ }
+
+ m_pinyin = pinyin;
+
+ if (diff) {
+ /* FIXME, should not remove all phrases1 */
+ m_phrases1.removeAll ();
+ m_string1.truncate (0);
+ m_cursor = 0;
+ }
+
+ updateCandidates ();
+ updatePhrases ();
+}
+
+gboolean
+PhraseEditor::resetCandidate (guint i)
+{
+ if (G_UNLIKELY (i >= m_candidates.length ()))
+ return FALSE;
+
+ if (G_UNLIKELY (i == 0 && m_phrases2.length () > 1))
+ return FALSE;
+
+ m_database.remove (m_candidates[i]);
+
+ updateCandidates ();
+ updatePhrases ();
+ return TRUE;
+}
+
+gboolean
+PhraseEditor::selectCandidate (guint i)
+{
+ if (G_LIKELY (i == 0)) {
+ m_phrases1 << m_phrases2;
+ m_string1 << m_string2;
+ m_cursor = m_pinyin.length ();
+ }
+ else {
+ if (m_phrases2.length() > 1)
+ i --;
+
+ if (G_UNLIKELY (i >= m_candidates.length ()))
+ return FALSE;
+
+ m_phrases1 << m_candidates[i];
+ m_string1 << m_candidates[i].phrase;
+ m_cursor += m_candidates[i].len;
+ }
+
+ updateCandidates ();
+ updatePhrases ();
+ return TRUE;
+}
+
+void
+PhraseEditor::updateCandidates (void)
+{
+ gboolean retval;
+ m_candidates.removeAll ();
+
+ guint len = MIN (MAX_PHRASE_LEN, m_pinyin.length () - m_cursor);
+ for (; len > 0; len--) {
+ retval = m_database.query (m_pinyin,
+ m_cursor,
+ len,
+ -1,
+ Config::option (),
+ m_candidates);
+ }
+}
+
+void
+PhraseEditor::updatePhrases (void)
+{
+ guint begin;
+ guint end;
+ gboolean retval;
+
+ m_phrases2.removeAll ();
+ m_string2.truncate (0);
+
+ if (G_UNLIKELY (m_pinyin.length () == 0))
+ return;
+
+ if (G_LIKELY (m_cursor < m_pinyin.length ())) {
+ m_phrases2 << m_candidates[0];
+
+ begin = m_phrases2[0].len + m_cursor;
+ end = m_pinyin.length ();
+
+ while (begin != end) {
+ for (guint i = MIN (end, begin + MAX_PHRASE_LEN); i > begin; i--) {
+ retval = m_database.query (m_pinyin,
+ begin,
+ i - begin,
+ 1,
+ Config::option (),
+ m_phrases2);
+ if (G_LIKELY (retval > 0)) {
+ begin += m_phrases2[m_phrases2.length () - 1].len;
+ break;
+ }
+ }
+ if (retval <= 0)
+ g_debug ("%s", m_pinyin[begin]->text);
+ g_assert (retval > 0);
+ }
+ }
+
+ for (guint i = 0; i < m_phrases2.length (); i++) {
+ m_string2 << m_phrases2[i].phrase;
+ }
+}
+
+};
+
+
diff --git a/src/PhraseEditor.h b/src/PhraseEditor.h
new file mode 100644
index 0000000..d998e0c
--- /dev/null
+++ b/src/PhraseEditor.h
@@ -0,0 +1,92 @@
+#ifndef __PY_PHRASE_EDITOR_H_
+#define __PY_PHRASE_EDITOR_H_
+
+#include "Database.h"
+#include "PhraseArray.h"
+
+namespace PY {
+
+class PhraseEditor {
+public:
+ PhraseEditor(void);
+ ~PhraseEditor(void);
+
+ const String & string1 (void) const { return m_string1; }
+ const String & string2 (void) const { return m_string2; }
+ const PinyinArray & pinyin (void) const { return m_pinyin; }
+ const PhraseArray & candidates (void) const { return m_candidates; }
+ guint cursor (void) const { return m_cursor; }
+
+ guint candidateNumber (void) const {
+ if (m_phrases2.length () > 1)
+ return m_candidates.length () + 1;
+ return m_candidates.length ();
+ }
+
+ const gchar * candidate (guint i) const {
+ if (G_UNLIKELY (i == 0))
+ return m_string2;
+ if (G_UNLIKELY (m_phrases2.length () > 1))
+ return m_candidates[i - 1].phrase;
+ return m_candidates[i].phrase;
+ }
+
+ gboolean candidateInUserPhease (guint i) const {
+ if (G_UNLIKELY (m_phrases2.length () > 1)) {
+ if (G_UNLIKELY (i == 0))
+ return FALSE;
+ else
+ return m_candidates[i - 1].user_freq > 0 && m_candidates[i - 1].freq == 0;
+ }
+ else {
+ return m_candidates[i].user_freq > 0 && m_candidates[i].freq == 0;
+ }
+ }
+
+ void reset (void) {
+ m_candidates.removeAll ();
+ m_phrases1.removeAll ();
+ m_string1.truncate (0);
+ m_phrases2.removeAll ();
+ m_string2.truncate (0);
+ m_pinyin.removeAll ();
+ m_cursor = 0;
+ }
+
+ void update (const PinyinArray &pinyin);
+ gboolean selectCandidate (guint i);
+ gboolean resetCandidate (guint i);
+ void commit (void) {
+ m_phrases1 << m_phrases2;
+ m_database.commit (m_phrases1);
+ reset ();
+ }
+
+ gboolean isEmpty (void) const {
+ return m_string1.isEmpty () && m_string2.isEmpty ();
+ }
+
+ operator gboolean (void) const {
+ return !isEmpty ();
+ }
+
+private:
+ void updateCandidates (void);
+ void updatePhrases (void);
+
+private:
+ PhraseArray m_candidates; // candidates phrase array
+ PhraseArray m_phrases1; // phrases before cursor
+ String m_string1; // phrases before cursor as string
+ PhraseArray m_phrases2; // phrases after cursor
+ String m_string2; // phrases before cursor as string
+ PinyinArray m_pinyin;
+ guint m_cursor;
+
+private:
+ static Database m_database;
+};
+
+};
+
+#endif
diff --git a/src/PinyinArray.h b/src/PinyinArray.h
new file mode 100644
index 0000000..fb58fa6
--- /dev/null
+++ b/src/PinyinArray.h
@@ -0,0 +1,13 @@
+#ifndef __PY_PINYIN_ARRAY_H_
+#define __PY_PINYIN_ARRAY_H_
+
+#include "Types.h"
+#include "Array.h"
+
+namespace PY {
+
+typedef Array<const Pinyin *> PinyinArray;
+
+};
+
+#endif
diff --git a/src/PinyinEditor.cc b/src/PinyinEditor.cc
new file mode 100644
index 0000000..fd4760c
--- /dev/null
+++ b/src/PinyinEditor.cc
@@ -0,0 +1,20 @@
+#include "Config.h"
+#include "PinyinEditor.h"
+
+namespace PY {
+
+#define MAX_PINYIN_LEN 64
+
+
+PinyinParser PinyinEditor::m_parser;
+
+PinyinEditor::PinyinEditor (void)
+ : m_text (MAX_PINYIN_LEN),
+ m_cursor (0),
+ m_pinyin (MAX_PHRASE_LEN),
+ m_pinyin_len (0)
+{
+}
+
+};
+
diff --git a/src/PinyinEditor.h b/src/PinyinEditor.h
new file mode 100644
index 0000000..3ad2405
--- /dev/null
+++ b/src/PinyinEditor.h
@@ -0,0 +1,52 @@
+#ifndef __PY_PINYIN_EDITOR_H_
+#define __PY_PINYIN_EDITOR_H_
+
+#include <glib.h>
+#include "String.h"
+#include "PinyinParser.h"
+
+#define MAX_PINYIN_LEN 64
+
+namespace PY {
+
+class PinyinEditor {
+public:
+ PinyinEditor (void);
+
+ const String & text (void) const { return m_text; }
+ const gchar * textAfterPinyin (void) const { return (const gchar *)m_text + m_pinyin_len; }
+ const gchar * textAfterCursor (void) const { return (const gchar *)m_text + m_cursor; }
+ guint cursor (void) const { return m_cursor; }
+ gboolean isEmpty (void) const { return m_text.isEmpty (); }
+ const PinyinArray & pinyin (void) const { return m_pinyin; }
+ guint pinyinLength (void) const { return m_pinyin_len; }
+ operator gboolean (void) const { return !isEmpty (); }
+
+ /* 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 gboolean reset (void) = 0;
+
+protected:
+ String m_text; // text buffer
+ guint m_cursor; // cursor pos in char
+ PinyinArray m_pinyin; // pinyin array
+ guint m_pinyin_len; // pinyin length in char
+
+protected:
+ static PinyinParser m_parser;
+
+};
+
+};
+
+#endif
diff --git a/src/PinyinEngine.cc b/src/PinyinEngine.cc
new file mode 100644
index 0000000..9687410
--- /dev/null
+++ b/src/PinyinEngine.cc
@@ -0,0 +1,680 @@
+/* vim:set et sts=4: */
+
+#include <ibus.h>
+#include <string.h>
+#include <libintl.h>
+#include "FullPinyinEditor.h"
+#include "DoublePinyinEditor.h"
+#include "PinyinEngine.h"
+#include "HalfFullConverter.h"
+#include "Config.h"
+#include "Text.h"
+#include "Util.h"
+
+#define _(text) (dgettext (GETTEXT_PACKAGE, text))
+
+namespace PY {
+
+/* constructor */
+PinyinEngine::PinyinEngine (IBusEngine *engine)
+ : m_engine (engine),
+ m_pinyin_editor (NULL),
+ m_need_update (0),
+ m_lookup_table (Config::pageSize ()),
+ m_mode_chinese (Config::initChinese ()),
+ m_mode_full (Config::initFull ()),
+ m_mode_full_punct (Config::initFullPunct ()),
+ m_quote (TRUE),
+ m_double_quote (TRUE),
+ m_prev_pressed_key (0)
+{
+ /* */
+ if (Config::doublePinyin ())
+ m_pinyin_editor = new DoublePinyinEditor ();
+ else
+ m_pinyin_editor = new FullPinyinEditor ();
+
+ /* create properties */
+ m_prop_chinese = ibus_property_new ("mode.chinese",
+ PROP_TYPE_NORMAL,
+ Text ("CN"),
+ m_mode_chinese ?
+ PKGDATADIR"/icons/chinese.svg" :
+ PKGDATADIR"/icons/english.svg",
+ Text (_("Chinese")),
+ TRUE,
+ TRUE,
+ PROP_STATE_UNCHECKED,
+ NULL);
+ m_props.append (m_prop_chinese);
+
+ m_prop_full = ibus_property_new ("mode.full",
+ PROP_TYPE_NORMAL,
+ Text (m_mode_full? "Aa" : "Aa"),
+ m_mode_full ?
+ PKGDATADIR"/icons/full.svg" :
+ PKGDATADIR"/icons/half.svg",
+ Text (_("Full/Half width")),
+ TRUE,
+ TRUE,
+ PROP_STATE_UNCHECKED,
+ NULL);
+ m_props.append (m_prop_full);
+
+ m_prop_full_punct = ibus_property_new ("mode.full_punct",
+ PROP_TYPE_NORMAL,
+ Text (m_mode_full_punct ? ",。" : ",."),
+ m_mode_full_punct ?
+ PKGDATADIR"/icons/full-punct.svg" :
+ PKGDATADIR"/icons/half-punct.svg",
+ Text (_("Full/Half width punctuation")),
+ TRUE,
+ TRUE,
+ PROP_STATE_UNCHECKED,
+ NULL);
+ m_props.append (m_prop_full_punct);
+
+ m_prop_setup = ibus_property_new ("setup",
+ PROP_TYPE_NORMAL,
+ Text (_("Pinyin preferences")),
+ "gtk-preferences",
+ Text (_("Pinyin preferences")),
+ TRUE,
+ TRUE,
+ PROP_STATE_UNCHECKED,
+ NULL);
+ m_props.append (m_prop_setup);
+
+}
+
+/* destructor */
+PinyinEngine::~PinyinEngine (void)
+{
+ delete m_pinyin_editor;
+}
+
+#define MASK_FILTER(modifiers) \
+ (modifiers & (IBUS_CONTROL_MASK | \
+ IBUS_MOD1_MASK | \
+ IBUS_SUPER_MASK | \
+ IBUS_HYPER_MASK | \
+ IBUS_META_MASK))
+
+/**
+ * process ascii letter
+ */
+inline gboolean
+PinyinEngine::processPinyin (guint keyval, guint keycode, guint modifiers)
+{
+ if (G_UNLIKELY (MASK_FILTER(modifiers) != 0))
+ return FALSE;
+
+ if (G_UNLIKELY (m_mode_chinese == FALSE)) {
+ if (G_LIKELY (m_mode_full))
+ commit (HalfFullConverter::toFull (keyval));
+ else
+ commit ((gchar) keyval);
+ return TRUE;
+ }
+
+ if (m_pinyin_editor->insert (keyval))
+ update (FALSE);
+ return TRUE;
+}
+
+inline gboolean
+PinyinEngine::processNumber (guint keyval, guint keycode, guint modifiers)
+{
+ /* English mode */
+ if (G_UNLIKELY (!m_mode_chinese)) {
+ commit ((gunichar) m_mode_full ? HalfFullConverter::toFull (keyval) : keyval);
+ return TRUE;
+ }
+
+ /* Chinese mode, if empty */
+ if (G_UNLIKELY (m_pinyin_editor->isEmpty ())) {
+ if (G_UNLIKELY (MASK_FILTER (modifiers) != 0))
+ return FALSE;
+ commit ((gunichar) m_mode_full ? HalfFullConverter::toFull (keyval) : keyval);
+ return TRUE;
+ }
+
+ /* Chinese mode, if has candidates */
+ guint i;
+ if (G_UNLIKELY (keyval == IBUS_0))
+ i = 10;
+ else
+ i = keyval - IBUS_1;
+
+ if (modifiers == 0)
+ selectCandidate (i);
+ else if ((modifiers & ~ IBUS_LOCK_MASK) == IBUS_CONTROL_MASK)
+ resetCandidate (i);
+ return TRUE;
+}
+
+inline gboolean
+PinyinEngine::processPunct (guint keyval, guint keycode, guint modifiers)
+{
+ if (G_UNLIKELY (MASK_FILTER(modifiers) != 0))
+ return FALSE;
+
+ /* English mode */
+ if (G_UNLIKELY (!m_mode_chinese)) {
+ if (G_UNLIKELY (m_mode_full))
+ commit (HalfFullConverter::toFull (keyval));
+ else
+ commit (keyval);
+ return TRUE;
+ }
+
+ /* Chinese mode */
+ if (G_UNLIKELY (isEmpty ())) {
+ if (m_mode_full_punct) {
+ switch (keyval) {
+ case '.':
+ commit ("。"); break;
+ case '\\':
+ commit ("、"); break;
+ case '^':
+ commit ("……"); break;
+ case '_':
+ commit ("——"); break;
+ case '$':
+ commit ("¥"); break;
+ case '<':
+ commit ("《"); break;
+ case '>':
+ commit ("》"); break;
+ case '"':
+ commit (m_double_quote ? "“" : "”");
+ m_double_quote = !m_double_quote;
+ break;
+ case '\'':
+ commit (m_quote ? "‘" : "’");
+ m_quote = !m_quote;
+ break;
+ default:
+ commit (HalfFullConverter::toFull (keyval));
+ break;
+ }
+ }
+ else {
+ commit (keyval);
+ }
+ return TRUE;
+ }
+
+ switch (keyval) {
+ case IBUS_space:
+ commit (); return TRUE;
+ case IBUS_apostrophe:
+ return processPinyin (keyval, keycode, modifiers);
+ case IBUS_comma:
+ if (Config::commaPeriodPage ())
+ pageUp ();
+ return TRUE;
+ case IBUS_minus:
+ if (Config::minusEqualPage ())
+ pageUp ();
+ return TRUE;
+ case IBUS_period:
+ if (Config::commaPeriodPage ())
+ pageDown ();
+ return TRUE;
+ case IBUS_equal:
+ if (Config::minusEqualPage ())
+ pageDown ();
+ return TRUE;
+ case IBUS_semicolon:
+ /* double pinyin need process ';' */
+ if (G_UNLIKELY (Config::doublePinyin ()))
+ return processPinyin (keyval, keycode, modifiers);
+ return TRUE;
+ default:
+ return TRUE;
+ }
+}
+
+inline gboolean
+PinyinEngine::processOthers (guint keyval, guint keycode, guint modifiers)
+{
+ if (G_UNLIKELY (isEmpty ()))
+ return FALSE;
+
+ /* process some cursor control keys */
+ gboolean _update = FALSE;
+ switch (keyval) {
+ case IBUS_Return:
+ if (G_UNLIKELY (m_mode_full)) {
+ m_buffer.truncate (0);
+ for (const gchar *p = m_pinyin_editor->text (); *p != 0; p++) {
+ m_buffer.appendUnichar (HalfFullConverter::toFull (*p));
+ }
+ commit (m_buffer);
+ }
+ else {
+ commit (m_pinyin_editor->text ());
+ }
+ m_pinyin_editor->reset ();
+ _update = TRUE;
+ break;
+
+ case IBUS_BackSpace:
+ if (G_LIKELY (modifiers == 0))
+ _update = m_pinyin_editor->removeCharBefore ();
+ else if (G_LIKELY (modifiers == IBUS_CONTROL_MASK))
+ _update = m_pinyin_editor->removeWordBefore ();
+ break;
+
+ case IBUS_Delete:
+ if (G_LIKELY (modifiers == 0))
+ _update = m_pinyin_editor->removeCharAfter ();
+ else if (G_LIKELY (modifiers == IBUS_CONTROL_MASK))
+ _update = m_pinyin_editor->removeWordAfter ();
+ break;
+
+ case IBUS_Left:
+ if (G_LIKELY (modifiers == 0)) {
+ // move left single char
+ _update = m_pinyin_editor->moveCursorLeft ();
+ }
+ else if (G_LIKELY (modifiers == IBUS_CONTROL_MASK)) {
+ // move left one pinyin
+ _update = m_pinyin_editor->moveCursorLeftByWord ();
+ }
+ break;
+
+ case IBUS_Right:
+ if (G_LIKELY (modifiers == 0)) {
+ // move right single char
+ _update = m_pinyin_editor->moveCursorRight ();
+ }
+ else if (G_LIKELY (modifiers == IBUS_CONTROL_MASK)) {
+ // move right to end
+ _update = m_pinyin_editor->moveCursorToEnd ();
+ }
+ break;
+
+ case IBUS_Home:
+ if (G_LIKELY (modifiers == 0)) {
+ // move to begin
+ _update = m_pinyin_editor->moveCursorToBegin ();
+ }
+ break;
+
+ case IBUS_End:
+ if (G_LIKELY (modifiers == 0)) {
+ // move to end
+ _update = m_pinyin_editor->moveCursorToEnd ();
+ }
+ break;
+
+ case IBUS_Up:
+ cursorUp (); break;
+ case IBUS_Down:
+ cursorDown (); break;
+ case IBUS_Page_Up:
+ pageUp (); break;
+ case IBUS_Page_Down:
+ pageDown (); break;
+ case IBUS_Escape:
+ reset (); break;
+ }
+ if (G_LIKELY (_update))
+ update (FALSE);
+ return TRUE;
+}
+
+gboolean
+PinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modifiers)
+{
+ gboolean retval = FALSE;
+
+ // ignore release event
+ if (modifiers & IBUS_RELEASE_MASK) {
+ if (m_prev_pressed_key != keyval)
+ return TRUE;
+
+ switch (keyval) {
+ case IBUS_Shift_L:
+ case IBUS_Shift_R:
+ if (isEmpty ())
+ toggleModeChinese ();
+ return TRUE;
+ default:
+ return TRUE;
+ }
+ }
+
+ 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:
+ case IBUS_A ... IBUS_Z:
+ retval = processPinyin (keyval, keycode, modifiers);
+ break;
+ /* numbers */
+ case IBUS_0 ... IBUS_9:
+ retval = processNumber (keyval, keycode, modifiers);
+ break;
+ /* punct */
+ case IBUS_space ... IBUS_slash:
+ case IBUS_colon ... IBUS_at:
+ case IBUS_bracketleft ... IBUS_quoteleft:
+ case IBUS_braceleft ... IBUS_asciitilde:
+ retval = processPunct (keyval, keycode, modifiers);
+ break;
+ /* others */
+ default:
+ retval = processOthers (keyval, keycode, modifiers);
+ break;
+ }
+
+ m_prev_pressed_key = keyval;
+ return retval;
+}
+
+void
+PinyinEngine::focusIn (void)
+{
+ if (Config::doublePinyin ()) {
+ if (dynamic_cast <DoublePinyinEditor *> (m_pinyin_editor) == NULL)
+ delete m_pinyin_editor;
+ m_pinyin_editor = new DoublePinyinEditor ();
+ }
+ else {
+ if (dynamic_cast <FullPinyinEditor *> (m_pinyin_editor) == NULL)
+ delete m_pinyin_editor;
+ m_pinyin_editor = new FullPinyinEditor ();
+ }
+
+ resetQuote ();
+ ibus_engine_register_properties (m_engine, m_props);
+}
+
+
+void
+PinyinEngine::pageUp (void)
+{
+ if (m_lookup_table.pageUp ()) {
+ ibus_engine_update_lookup_table_fast (m_engine, m_lookup_table, TRUE);
+ }
+}
+
+void
+PinyinEngine::pageDown (void)
+{
+ if (m_lookup_table.pageDown ()) {
+ ibus_engine_update_lookup_table_fast (m_engine, m_lookup_table, TRUE);
+ }
+}
+
+void
+PinyinEngine::cursorUp (void)
+{
+ if (m_lookup_table.cursorUp ()) {
+ ibus_engine_update_lookup_table_fast (m_engine, m_lookup_table, TRUE);
+ }
+}
+
+void
+PinyinEngine::cursorDown (void)
+{
+ if (m_lookup_table.cursorDown ()) {
+ ibus_engine_update_lookup_table_fast (m_engine, m_lookup_table, TRUE);
+ }
+}
+
+inline void
+PinyinEngine::toggleModeChinese (void)
+{
+ m_mode_chinese = ! m_mode_chinese;
+ m_prop_chinese.setLabel (m_mode_chinese ? "CN" : "EN");
+ m_prop_chinese.setIcon (m_mode_chinese ?
+ PKGDATADIR"/icons/chinese.svg" :
+ PKGDATADIR"/icons/english.svg");
+ ibus_engine_update_property (m_engine, m_prop_chinese);
+
+ m_prop_full_punct.setSensitive (m_mode_chinese);
+ ibus_engine_update_property (m_engine, m_prop_full_punct);
+}
+
+inline void
+PinyinEngine::toggleModeFull (void)
+{
+ m_mode_full = !m_mode_full;
+ m_prop_full.setLabel (m_mode_full ? "Aa" : "Aa");
+ m_prop_full.setIcon (m_mode_full ?
+ PKGDATADIR"/icons/full.svg" :
+ PKGDATADIR"/icons/half.svg");
+ ibus_engine_update_property (m_engine, m_prop_full);
+}
+
+inline void
+PinyinEngine::toggleModeFullPunct (void)
+{
+ m_mode_full_punct = !m_mode_full_punct;
+ m_prop_full_punct.setLabel (m_mode_full_punct ? ",。" : ",.");
+ m_prop_full_punct.setIcon (m_mode_full_punct ?
+ PKGDATADIR"/icons/full-punct.svg" :
+ PKGDATADIR"/icons/half-punct.svg");
+ ibus_engine_update_property (m_engine, m_prop_full_punct);
+}
+
+inline void
+PinyinEngine::showSetupDialog (void)
+{
+ g_spawn_command_line_async (LIBEXECDIR"/ibus-setup-pinyin", NULL);
+}
+
+void
+PinyinEngine::propertyActivate (const gchar *prop_name, guint prop_state)
+{
+ const static StaticString mode_chinese ("mode.chinese");
+ const static StaticString mode_full ("mode.full");
+ const static StaticString mode_full_punct ("mode.full_punct");
+ const static StaticString setup ("setup");
+
+ if (mode_chinese == prop_name) {
+ toggleModeChinese ();
+ }
+ else if (mode_full == prop_name) {
+ toggleModeFull ();
+ }
+ else if (mode_full_punct == prop_name) {
+ toggleModeFullPunct ();
+ }
+ else if (setup == prop_name) {
+ showSetupDialog ();
+ }
+}
+
+void
+PinyinEngine::updatePreeditText (void)
+{
+ if (G_UNLIKELY (m_phrase_editor.isEmpty () && m_pinyin_editor->isEmpty ())) {
+ ibus_engine_hide_preedit_text (m_engine);
+ return;
+ }
+
+ m_buffer.truncate (0);
+ if (G_UNLIKELY (m_phrase_editor.string1 ()))
+ m_buffer << m_phrase_editor.string1 () << ' ';
+
+ m_buffer << m_phrase_editor.string2 ()
+ << m_pinyin_editor->textAfterPinyin ();
+
+ Text preedit_text (m_buffer);
+ preedit_text.appendAttribute (IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, -1);
+ ibus_engine_update_preedit_text (m_engine, preedit_text, m_buffer.length (), TRUE);
+}
+
+void
+PinyinEngine::updateAuxiliaryText (void)
+{
+
+ /* clear pinyin array */
+ if (G_UNLIKELY (isEmpty ())) {
+ ibus_engine_hide_auxiliary_text (m_engine);
+ return;
+ }
+
+ guint cursor_pos;
+
+ m_buffer.truncate (0);
+ if (G_UNLIKELY (m_phrase_editor.string1 ())) {
+ m_buffer << m_phrase_editor.string1 ();
+ }
+
+ for (guint i = m_phrase_editor.cursor (); i < m_pinyin_editor->pinyin().length (); ++i) {
+ if (G_LIKELY (i != m_phrase_editor.cursor ()))
+ m_buffer << '\'';
+ const Pinyin *p = m_pinyin_editor->pinyin()[i];
+ m_buffer << p->sheng;
+ m_buffer << p->yun;
+ }
+
+ if (G_UNLIKELY (m_pinyin_editor->pinyinLength () == m_pinyin_editor->cursor ())) {
+ /* aux = pinyin + non-pinyin */
+ cursor_pos = m_buffer.utf8Length ();
+ m_buffer << '|' << m_pinyin_editor->textAfterPinyin ();
+ }
+ else {
+ /* aux = pinyin + non-pinyin before cursor + non-pinyin after cursor */
+ m_buffer.append (m_pinyin_editor->textAfterPinyin (),
+ m_pinyin_editor->cursor () - m_pinyin_editor->pinyinLength ());
+ cursor_pos = m_buffer.utf8Length ();
+ m_buffer << '|' << m_pinyin_editor->textAfterCursor ();
+ }
+
+ Text aux_text (m_buffer);
+ /*
+ aux_text.appendAttribute (IBUS_ATTR_TYPE_FOREGROUND, 0x00afafaf, len, cursor_pos);
+ aux_text.appendAttribute (IBUS_ATTR_TYPE_FOREGROUND, 0x00afafaf, cursor_pos + 1, -1);
+ */
+ ibus_engine_update_auxiliary_text (m_engine, aux_text, TRUE);
+}
+
+void
+PinyinEngine::updateLookupTable (void)
+{
+ m_lookup_table.clear ();
+ m_lookup_table.setPageSize (Config::pageSize ());
+
+ guint candidate_nr = m_phrase_editor.candidateNumber ();
+
+ if (G_UNLIKELY (candidate_nr == 0)) {
+ ibus_engine_hide_lookup_table (m_engine);
+ return;
+ }
+
+ for (guint i = 0; i < candidate_nr; i++) {
+ //const Phrase &phrase = m_phrase_editor.candidates()[i];
+ Text text (m_phrase_editor.candidate (i));
+ if (m_phrase_editor.candidateInUserPhease (i))
+ text.appendAttribute (IBUS_ATTR_TYPE_FOREGROUND, 0x000000ef, 0, -1);
+ m_lookup_table.appendCandidate (text);
+ }
+
+ ibus_engine_update_lookup_table_fast (m_engine,
+ m_lookup_table,
+ TRUE);
+}
+
+void
+PinyinEngine::updatePhraseEditor (void)
+{
+ m_phrase_editor.update (m_pinyin_editor->pinyin ());
+}
+
+inline void
+PinyinEngine::commit (gchar ch)
+{
+ gchar str[2] = {ch, 0};
+ ibus_engine_commit_text (m_engine, Text (str));
+}
+
+inline void
+PinyinEngine::commit (gunichar ch)
+{
+ ibus_engine_commit_text (m_engine, Text (ch));
+}
+
+inline void
+PinyinEngine::commit (const gchar *str)
+{
+ ibus_engine_commit_text (m_engine, Text (str));
+}
+
+inline void
+PinyinEngine::commit (const String &str)
+{
+ commit ((const gchar *)str);
+}
+
+inline void
+PinyinEngine::commit (void)
+{
+ if (G_UNLIKELY (m_pinyin_editor->isEmpty ()))
+ return;
+
+ m_buffer.truncate (0);
+ m_buffer << m_phrase_editor.string1 () << m_phrase_editor.string2 ();
+ const gchar *p = m_pinyin_editor->textAfterPinyin ();
+ if (G_UNLIKELY (m_mode_full)) {
+ while (*p != 0)
+ m_buffer.appendUnichar (HalfFullConverter::toFull (*p++));
+ }
+ else {
+ m_buffer << p;
+ }
+ commit ((const gchar *)m_buffer);
+ m_phrase_editor.commit ();
+ reset ();
+}
+
+inline gboolean
+PinyinEngine::selectCandidate (guint i)
+{
+ guint page_size = m_lookup_table.pageSize ();
+ guint cursor_pos = m_lookup_table.cursorPos ();
+ i += (cursor_pos / page_size) * page_size;
+
+ if (m_phrase_editor.selectCandidate (i)) {
+ if (G_UNLIKELY (m_phrase_editor.cursor () == m_pinyin_editor->pinyin ().length ())) {
+ commit ();
+ }
+ else {
+ updatePreeditText ();
+ updateAuxiliaryText ();
+ updateLookupTable ();
+ }
+ }
+ return TRUE;
+}
+
+inline gboolean
+PinyinEngine::resetCandidate (guint i)
+{
+ guint page_size = m_lookup_table.pageSize ();
+ guint cursor_pos = m_lookup_table.cursorPos ();
+ i += (cursor_pos / page_size) * page_size;
+
+ if (m_phrase_editor.resetCandidate (i)) {
+ updatePreeditText ();
+ updateAuxiliaryText ();
+ updateLookupTable ();
+ }
+ return TRUE;
+}
+
+};
+
diff --git a/src/PinyinEngine.h b/src/PinyinEngine.h
new file mode 100644
index 0000000..6472302
--- /dev/null
+++ b/src/PinyinEngine.h
@@ -0,0 +1,121 @@
+/* vim:set et sts=4: */
+#ifndef __PY_PIN_YIN_ENGINE_H__
+#define __PY_PIN_YIN_ENGINE_H__
+
+#include <ibus.h>
+#include "Pointer.h"
+#include "Database.h"
+#include "FullPinyinEditor.h"
+#include "PhraseEditor.h"
+#include "LookupTable.h"
+#include "Property.h"
+#include "Config.h"
+
+namespace PY {
+
+class PinyinEngine {
+public:
+ PinyinEngine (IBusEngine *engine);
+ ~PinyinEngine (void);
+
+ gboolean processKeyEvent (guint keyval, guint keycode, guint modifiers);
+ void focusIn (void);
+ void focusOut (void) {}
+
+ void reset (gboolean need_update = TRUE) {
+ m_pinyin_editor->reset ();
+ update (need_update);
+ }
+
+ void resetQuote (void) {
+ m_quote = TRUE;
+ m_double_quote = TRUE;
+ }
+
+ void enable (void) {}
+ void disable (void) {}
+ void pageUp (void);
+ void pageDown (void);
+ void cursorUp (void);
+ void cursorDown (void);
+
+ void propertyActivate (const gchar *prop_name, guint prop_state);
+
+ void update (gboolean now = TRUE) {
+ if (G_UNLIKELY (now || m_need_update >= 4)) {
+ updatePhraseEditor ();
+ updateLookupTable ();
+ updateAuxiliaryText ();
+ updatePreeditText ();
+ m_need_update = 0;
+ } else {
+ if (m_need_update == 0) {
+ g_idle_add ((GSourceFunc) delayUpdateHandler, this);
+ }
+ m_need_update ++;
+ }
+ }
+
+private:
+ 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 processOthers (guint keyval, guint keycode, guint modifiers);
+
+private:
+ gboolean isEmpty (void) { return m_pinyin_editor->isEmpty (); }
+
+ void commit (void);
+ void commit (gchar ch);
+ void commit (gunichar ch);
+ void commit (const gchar *str);
+ void commit (const String &str);
+
+ void toggleModeChinese (void);
+ void toggleModeFull (void);
+ void toggleModeFullPunct (void);
+ void showSetupDialog (void);
+
+ gboolean selectCandidate (guint i);
+ gboolean resetCandidate (guint i);
+ void updatePreeditText (void);
+ void updateAuxiliaryText (void);
+ void updateLookupTable (void);
+ void updatePhraseEditor (void);
+
+ static gboolean delayUpdateHandler (PinyinEngine *pinyin) {
+ if (pinyin->m_need_update > 0)
+ pinyin->update (TRUE);
+ return FALSE;
+ }
+
+private:
+ Pointer<IBusEngine> m_engine; // engine pointer
+
+ PinyinEditor *m_pinyin_editor; // pinyin editor
+ PhraseEditor m_phrase_editor; // phrase editor
+ String m_buffer; // string buffer
+
+ gint m_need_update; // need update preedit, aux, or lookup table
+
+ LookupTable m_lookup_table;
+ Property m_prop_chinese;
+ Property m_prop_full;
+ Property m_prop_full_punct;
+ Property m_prop_setup;
+ PropList m_props;
+
+ gboolean m_mode_chinese;
+ gboolean m_mode_full;
+ gboolean m_mode_full_punct;
+
+ gboolean m_quote;
+ gboolean m_double_quote;
+
+ guint m_prev_pressed_key;
+
+};
+
+};
+
+#endif
diff --git a/src/PinyinParser.cc b/src/PinyinParser.cc
new file mode 100644
index 0000000..2bdfa49
--- /dev/null
+++ b/src/PinyinParser.cc
@@ -0,0 +1,243 @@
+/* vim:set et sts=4: */
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include "Table.h"
+#include "PinyinParser.h"
+
+namespace PY {
+
+static int
+py_cmp (const void *p1, const void *p2)
+{
+ const gchar *str = (const gchar *) p1;
+ const Pinyin *py = (const Pinyin *) p2;
+
+ return strcmp (str, py->text);
+}
+
+static const Pinyin *
+is_pinyin (const gchar *p,
+ const gchar *end,
+ gint len,
+ guint option)
+{
+ gchar buf[7];
+ const Pinyin *result;
+
+ if (G_UNLIKELY (len > 6))
+ return NULL;
+
+ if (G_UNLIKELY (len > end - p))
+ return NULL;
+
+ if (G_LIKELY (len > 0)) {
+ strncpy (buf, p, len);
+ buf[len] = 0;
+ result = (const Pinyin *) bsearch (buf, pinyin_table, PINYIN_TABLE_NR,
+ sizeof (Pinyin), py_cmp);
+ if (G_UNLIKELY (result == NULL))
+ return NULL;
+ if (G_LIKELY (result->flags == 0))
+ return result;
+ if(G_LIKELY (result->flags & option))
+ return result;
+ return NULL;
+ }
+
+ len = strnlen (p, 6);
+ len = MIN (len, end - p);
+ strncpy (buf, p, len);
+
+ for (; len > 0; len --) {
+ buf[len] = 0;
+ result = (const Pinyin *) bsearch (buf, pinyin_table, PINYIN_TABLE_NR,
+ sizeof (Pinyin), py_cmp);
+ if (G_UNLIKELY (result && ((result->flags == 0) || (result->flags & option)))) {
+ return result;
+ }
+ }
+
+ return NULL;
+}
+
+static int
+sp_cmp (const void *p1,
+ const void *p2)
+{
+ const Pinyin **pys = (const Pinyin **) p1;
+ const Pinyin **e = (const Pinyin **) p2;
+
+ return ((pys[0] - e[0]) << 16) + (pys[1] - e[1]);
+}
+
+static const Pinyin **
+need_resplit(const Pinyin *p1,
+ const Pinyin *p2)
+{
+ const Pinyin * pys[] = {p1, p2};
+
+ return (const Pinyin **) bsearch (pys, special_table, SPECIAL_TABLE_NR,
+ sizeof (special_table[0]), sp_cmp);
+}
+
+guint
+PinyinParser::parse (const String &pinyin,
+ gint len,
+ guint option,
+ PinyinArray &result,
+ guint max)
+{
+
+ const gchar *p;
+ const gchar *end;
+ const Pinyin *py;
+ const Pinyin *prev_py;
+ gchar prev_c;
+
+ result.removeAll ();
+
+ if (G_UNLIKELY (len < 0))
+ len = pinyin.length ();
+
+ p = pinyin;
+ end = p + len;
+
+ prev_py = NULL;
+
+ prev_c = 0;
+ for (; p < end && result.length () < max; ) {
+ switch (prev_c) {
+ case 'r':
+ case 'n':
+ case 'g':
+ case 'e':
+ switch (*p) {
+ case 'i':
+ case 'u':
+ case 'v':
+ case 'a':
+ case 'e':
+ case 'o':
+ case 'r':
+ {
+ const Pinyin **pp;
+ const Pinyin *new_py1;
+ const Pinyin *new_py2;
+
+ py = is_pinyin (p, end, -1, option);
+
+ if ((new_py1 = is_pinyin (prev_py->text,
+ prev_py->text + prev_py->len,
+ prev_py->len - 1,
+ option)) != NULL) {
+ new_py2 = is_pinyin (p -1, end, -1, option);
+
+ if (((new_py2 != NULL) && (new_py2->len > 1 )) &&
+ (py == NULL || new_py2->len > py->len + 1)) {
+ result[result.length () - 1] = new_py1;
+ py = new_py2;
+ p --;
+ break;
+ }
+ }
+
+ if ( py == NULL)
+ break;
+
+ pp = need_resplit (prev_py, py);
+ if (pp != NULL) {
+ result[result.length () - 1] = pp[2];
+ py = pp[3];
+ p --;
+ break;
+ }
+ }
+ default:
+ py = is_pinyin (p, end, -1, option);
+ break;
+ }
+ break;
+ default:
+ py = is_pinyin (p, end, -1, option);
+ break;
+ }
+
+ if (G_UNLIKELY (py == NULL))
+ break;
+
+ result << py;
+ p += py->len;
+ prev_c = py->text[py->len - 1];
+ prev_py = py;
+
+ if (G_UNLIKELY (*p == '\'')) {
+ prev_c = '\'';
+ p++;
+ }
+ }
+
+ if (G_UNLIKELY (p == (const gchar *)pinyin))
+ return 0;
+#if 0
+ if (G_UNLIKELY (*(p - 1) == '\''))
+ p --;
+#endif
+ return p - (const gchar *)pinyin;
+}
+
+static int
+py_id_cmp (const void *p1, const void *p2)
+{
+ const gint *id = (const gint *) p1;
+ const Pinyin *py = (const Pinyin *) p2;
+
+ return ((id[0] - py->sheng_id) << 16) + (id[1] - py->yun_id);
+}
+
+const Pinyin *
+PinyinParser::isPinyin (gint sheng, gint yun, guint option)
+{
+ const Pinyin *result;
+ gint buf[2] = {sheng, yun};
+
+ result = (const Pinyin *) bsearch (buf, pinyin_table, PINYIN_TABLE_NR,
+ sizeof (Pinyin), py_id_cmp);
+ if (result != NULL && result->flags != 0 && (result->flags & option) == 0)
+ return NULL;
+ return result;
+}
+
+};
+
+
+#ifdef TEST
+#include <glib/gprintf.h>
+int main(int argc, char **argv)
+{
+ gint len;
+ GArray *array;
+ Pinyin **p;
+ gchar *str;
+
+ str = "qinaide";
+
+ if (argc > 1)
+ str = argv[1];
+
+ array = g_array_new (TRUE, TRUE, sizeof (Pinyin *));
+
+ len = py_parse_pinyin (str, -1, 0xffffffff, array);
+
+ if (len) {
+ p = (Pinyin **) array->data;
+ while (*p) {
+ g_printf ("%s'", (*p)->text);
+ p ++;
+ }
+ }
+ g_printf ("%s\n", str + len);
+
+ return 0;
+}
+#endif
diff --git a/src/PinyinParser.h b/src/PinyinParser.h
new file mode 100644
index 0000000..c9ad552
--- /dev/null
+++ b/src/PinyinParser.h
@@ -0,0 +1,26 @@
+/* vim:set et sts=4: */
+#ifndef __PY_PARSER_H__
+#define __PY_PARSER_H__
+
+#include <glib.h>
+#include "String.h"
+#include "PinyinArray.h"
+
+namespace PY {
+
+class PinyinParser {
+
+public:
+ PinyinParser (void) {}
+ ~PinyinParser (void) {}
+
+ guint parse (const String &pinyin, // pinyin string
+ gint len, // length of pinyin string
+ guint option, // option
+ PinyinArray &result, // store pinyin in result
+ guint max); // max length of the result
+ const Pinyin * isPinyin (gint sheng, gint yun, guint option);
+};
+
+};
+#endif
diff --git a/src/Pointer.h b/src/Pointer.h
new file mode 100644
index 0000000..05de8aa
--- /dev/null
+++ b/src/Pointer.h
@@ -0,0 +1,55 @@
+#ifndef __PY_POINTER_H_
+#define __PY_POINTER_H_
+
+#include <glib-object.h>
+
+namespace PY {
+
+template<typename T>
+class Pointer {
+public:
+ Pointer (T *p = NULL) : m_p (NULL) {
+ set (p);
+ }
+
+ ~Pointer (void) {
+ set (NULL);
+ }
+
+ void set (T * p) {
+ if (m_p) {
+ g_object_unref (m_p);
+ }
+
+ m_p = p;
+ if (p) {
+ // g_debug ("%s, floating = %d",G_OBJECT_TYPE_NAME (p), g_object_is_floating (p));
+ g_object_ref_sink (p);
+ }
+ }
+
+ Pointer<T> &operator = (T *p) {
+ set (p);
+ return *this;
+ }
+
+ Pointer<T> &operator = (const Pointer<T> & p) {
+ set (p.m_p);
+ return *this;
+ }
+
+ operator T * (void) const {
+ return m_p;
+ }
+
+ operator gboolean (void) const {
+ return m_p != NULL;
+ }
+
+private:
+ T *m_p;
+};
+
+};
+
+#endif
diff --git a/src/Property.h b/src/Property.h
new file mode 100644
index 0000000..5237cd7
--- /dev/null
+++ b/src/Property.h
@@ -0,0 +1,43 @@
+#ifndef __PY_PROPERTY_H_
+#define __PY_PROPERTY_H_
+
+#include <ibus.h>
+#include "Pointer.h"
+#include "Text.h"
+
+namespace PY {
+
+class Property : public Pointer<IBusProperty> {
+public:
+ Property & operator= (IBusProperty *p) {
+ set (p);
+ return *this;
+ }
+
+ void setLabel (const Text & text) {
+ ibus_property_set_label (*this, text);
+ }
+ void setLabel (const gchar *text) {
+ setLabel (Text (text));
+ }
+ void setIcon (const gchar *icon) {
+ ibus_property_set_icon (*this, icon);
+ }
+ void setSensitive (gboolean sensitive) {
+ ibus_property_set_sensitive (*this, sensitive);
+ }
+};
+
+
+class PropList : public Pointer<IBusPropList> {
+public:
+ PropList (void) : Pointer<IBusPropList> (ibus_prop_list_new ()) { }
+
+ void append (Property &prop) {
+ ibus_prop_list_append (*this, prop);
+ }
+};
+
+};
+
+#endif
diff --git a/src/SpecialTable.cc b/src/SpecialTable.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/SpecialTable.cc
diff --git a/src/SpecialTable.h b/src/SpecialTable.h
new file mode 100644
index 0000000..43d9d92
--- /dev/null
+++ b/src/SpecialTable.h
@@ -0,0 +1,17 @@
+#ifndef __PY_SPECIAL_TABLE_H_
+#define __PY_SPECIAL_TABLE_H_
+
+#include <glib.h>
+
+namespace PY {
+
+class SpecialTable {
+public:
+ SpecialTable (void) {}
+private:
+ gboolean load (const gchar *file);
+};
+
+};
+
+#endif
diff --git a/src/String.h b/src/String.h
new file mode 100644
index 0000000..b473a48
--- /dev/null
+++ b/src/String.h
@@ -0,0 +1,150 @@
+#ifndef __PY_STRING_H_
+#define __PY_STRING_H_
+#include <glib.h>
+#include <stdarg.h>
+
+namespace PY {
+
+class String {
+public:
+ String (const gchar *init) {
+ m_string = g_string_new (init);
+ }
+
+ String (const gchar *init, gssize len) {
+ m_string = g_string_new_len (init, len);
+ }
+
+ String (gsize init_size = 0) {
+ m_string = g_string_sized_new (init_size);
+ }
+
+ ~String (void) {
+ g_string_free (m_string, TRUE);
+ }
+
+ gsize length (void) const {
+ return m_string->len;
+ }
+
+ gsize utf8Length (void) const {
+ return g_utf8_strlen (m_string->str, m_string->len);
+ }
+
+ gboolean isEmpty (void) const {
+ return m_string->len == 0;
+ }
+
+ String & assign (const gchar *str) {
+ g_string_assign (m_string, str);
+ return *this;
+ }
+
+ String & assign (const String &str) {
+ return assign ((const gchar *) str);
+ }
+
+ String & insert (gint pos, gchar ch) {
+ g_string_insert_c (m_string, pos, ch);
+ return *this;
+ }
+
+ String & append (const gchar *str) {
+ g_string_append (m_string, str);
+ return *this;
+ }
+
+ String & appendUnichar (gunichar ch) {
+ g_string_append_unichar (m_string, ch);
+ return *this;
+ }
+
+ String & append (const gchar *str, gint len) {
+ g_string_append_len (m_string, str, len);
+ return *this;
+ }
+
+ String & printf (const gchar *fmt, ...) {
+ va_list args;
+
+ va_start (args, fmt);
+ g_string_vprintf (m_string, fmt, args);
+ va_end (args);
+
+ return *this;
+ }
+
+ String & appendPrintf (const gchar *fmt, ...) {
+ va_list args;
+
+ va_start (args, fmt);
+ g_string_append_vprintf (m_string, fmt, args);
+ va_end (args);
+
+ return *this;
+ }
+
+ String & truncate (gint len) {
+ g_string_truncate (m_string, len);
+ return *this;
+ }
+
+ String & erase (gint pos, gint len) {
+ g_string_erase (m_string, pos, len);
+ return *this;
+ }
+
+ String & operator = (const gchar *str) {
+ return assign (str);
+ }
+
+ String & operator = (const String &str) {
+ return assign (str);
+ }
+
+ String & operator += (const gchar *str) {
+ return append (str);
+ }
+
+ String & operator << (const gchar *str) {
+ return append (str);
+ }
+
+ String & operator << (const String &str) {
+ return append ((const gchar *) str);
+ }
+
+ String & operator << (gint d) {
+ g_string_append_printf (m_string, "%d", d);
+ return *this;
+ }
+
+ String & operator << (guint d) {
+ g_string_append_printf (m_string, "%u", d);
+ return *this;
+ }
+
+ String & operator << (gchar ch) {
+ g_string_append_c (m_string, ch);
+ return *this;
+ }
+
+ gchar operator[] (guint i) {
+ if (i >= length ())
+ return 0;
+ return m_string->str[i];
+ }
+
+ operator const gchar *() const {
+ return m_string->str;
+ }
+
+ operator gboolean () const {
+ return m_string->len != 0;
+ }
+
+private:
+ GString *m_string;
+};
+};
+#endif
diff --git a/src/Text.h b/src/Text.h
new file mode 100644
index 0000000..22a5aab
--- /dev/null
+++ b/src/Text.h
@@ -0,0 +1,27 @@
+#ifndef __PY_TEXT_H_
+#define __PY_TEXT_H_
+
+#include <ibus.h>
+#include "Pointer.h"
+
+namespace PY {
+
+class Text : public Pointer <IBusText> {
+public:
+ Text (const gchar *str)
+ : Pointer <IBusText> (ibus_text_new_from_static_string (str)) { }
+
+ Text (gunichar ch)
+ : Pointer <IBusText> (ibus_text_new_from_unichar (ch)) { }
+
+ Text (const String & str)
+ : Pointer <IBusText> (ibus_text_new_from_static_string ((const gchar *) str)) { }
+
+ void appendAttribute (guint type, guint value, guint start, guint end) {
+ ibus_text_append_attribute (*this, type, value, start, end);
+ }
+};
+
+};
+
+#endif
diff --git a/src/Types.h b/src/Types.h
new file mode 100644
index 0000000..d083f50
--- /dev/null
+++ b/src/Types.h
@@ -0,0 +1,135 @@
+/* vim:set et sts=4: */
+#ifndef __PY_TYPE_H_
+#define __PY_TYPE_H_
+
+#include <glib.h>
+
+namespace PY {
+
+#define PINYIN_ID_VOID (-1)
+#define PINYIN_ID_ZERO (0)
+#define PINYIN_ID_B (1)
+#define PINYIN_ID_C (2)
+#define PINYIN_ID_CH (3)
+#define PINYIN_ID_D (4)
+#define PINYIN_ID_F (5)
+#define PINYIN_ID_G (6)
+#define PINYIN_ID_H (7)
+#define PINYIN_ID_J (8)
+#define PINYIN_ID_K (9)
+#define PINYIN_ID_L (10)
+#define PINYIN_ID_M (11)
+#define PINYIN_ID_N (12)
+#define PINYIN_ID_P (13)
+#define PINYIN_ID_Q (14)
+#define PINYIN_ID_R (15)
+#define PINYIN_ID_S (16)
+#define PINYIN_ID_SH (17)
+#define PINYIN_ID_T (18)
+#define PINYIN_ID_W (19)
+#define PINYIN_ID_X (20)
+#define PINYIN_ID_Y (21)
+#define PINYIN_ID_Z (22)
+#define PINYIN_ID_ZH (23)
+#define PINYIN_ID_A (24)
+#define PINYIN_ID_AI (25)
+#define PINYIN_ID_AN (26)
+#define PINYIN_ID_ANG (27)
+#define PINYIN_ID_AO (28)
+#define PINYIN_ID_E (29)
+#define PINYIN_ID_EI (30)
+#define PINYIN_ID_EN (31)
+#define PINYIN_ID_ENG (32)
+#define PINYIN_ID_ER (33)
+#define PINYIN_ID_I (34)
+#define PINYIN_ID_IA (35)
+#define PINYIN_ID_IAN (36)
+#define PINYIN_ID_IANG (37)
+#define PINYIN_ID_IAO (38)
+#define PINYIN_ID_IE (39)
+#define PINYIN_ID_IN (40)
+#define PINYIN_ID_ING (41)
+#define PINYIN_ID_IONG (42)
+#define PINYIN_ID_IU (43)
+#define PINYIN_ID_O (44)
+#define PINYIN_ID_ONG (45)
+#define PINYIN_ID_OU (46)
+#define PINYIN_ID_U (47)
+#define PINYIN_ID_UA (48)
+#define PINYIN_ID_UAI (49)
+#define PINYIN_ID_UAN (50)
+#define PINYIN_ID_UANG (51)
+#define PINYIN_ID_UE (52)
+#define PINYIN_ID_UI (53)
+#define PINYIN_ID_UN (54)
+#define PINYIN_ID_UO (55)
+#define PINYIN_ID_V (56)
+#define PINYIN_ID_NG PINYIN_ID_VOID
+
+#define PINYIN_SIMPLE_PINYIN (1 << 0)
+
+#define PINYIN_CORRECT_GN_TO_NG (1 << 1)
+#define PINYIN_CORRECT_MG_TO_NG (1 << 2)
+#define PINYIN_CORRECT_IOU_TO_IU (1 << 3)
+#define PINYIN_CORRECT_UEI_TO_UI (1 << 4)
+#define PINYIN_CORRECT_UEN_TO_UN (1 << 5)
+#define PINYIN_CORRECT_VE_TO_UE (1 << 6)
+#define PINYIN_CORRECT_ALL (0x0000007e)
+
+#define PINYIN_FUZZY_C_CH (1 << 7)
+#define PINYIN_FUZZY_CH_C (1 << 8)
+#define PINYIN_FUZZY_Z_ZH (1 << 9)
+#define PINYIN_FUZZY_ZH_Z (1 << 10)
+#define PINYIN_FUZZY_S_SH (1 << 11)
+#define PINYIN_FUZZY_SH_S (1 << 12)
+#define PINYIN_FUZZY_L_N (1 << 13)
+#define PINYIN_FUZZY_N_L (1 << 14)
+#define PINYIN_FUZZY_F_H (1 << 15)
+#define PINYIN_FUZZY_H_F (1 << 16)
+#define PINYIN_FUZZY_L_R (1 << 17)
+#define PINYIN_FUZZY_R_L (1 << 18)
+#define PINYIN_FUZZY_K_G (1 << 19)
+#define PINYIN_FUZZY_G_K (1 << 20)
+
+#define PINYIN_FUZZY_AN_ANG (1 << 21)
+#define PINYIN_FUZZY_ANG_AN (1 << 22)
+#define PINYIN_FUZZY_EN_ENG (1 << 23)
+#define PINYIN_FUZZY_ENG_EN (1 << 24)
+#define PINYIN_FUZZY_IN_ING (1 << 25)
+#define PINYIN_FUZZY_ING_IN (1 << 26)
+#define PINYIN_FUZZY_IAN_IANG (1 << 27)
+#define PINYIN_FUZZY_IANG_IAN (1 << 28)
+#define PINYIN_FUZZY_UAN_UANG (1 << 29)
+#define PINYIN_FUZZY_UANG_UAN (1 << 30)
+#define PINYIN_FUZZY_ALL (0x7fffff10)
+
+typedef struct _Pinyin Pinyin;
+struct _Pinyin {
+ const char *text;
+ const char *sheng;
+ const char *yun;
+ const char sheng_id;
+ const char yun_id;
+ const char fsheng_id;
+ const char fyun_id;
+ const char fsheng_id_2;
+ const char fyun_id_2;
+ const int len;
+ const int flags;
+};
+
+#define MAX_UTF8_LEN 6
+#define MAX_PHRASE_LEN 16
+
+typedef struct _Phrase Phrase;
+struct _Phrase {
+ gchar phrase[(MAX_PHRASE_LEN + 1) * MAX_UTF8_LEN];
+ guint freq;
+ guint user_freq;
+ guint pinyin_id[MAX_PHRASE_LEN][2];
+ guint len;
+};
+
+};
+
+#endif
diff --git a/src/Util.h b/src/Util.h
new file mode 100644
index 0000000..aaa0178
--- /dev/null
+++ b/src/Util.h
@@ -0,0 +1,64 @@
+#ifndef __PY_UTIL_H_
+#define __PY_UTIL_H_
+
+#include <uuid/uuid.h>
+#include <sys/utsname.h>
+
+namespace PY {
+
+class UUID {
+public:
+ UUID (void) {
+ uuid_t u;
+ uuid_generate (u);
+ uuid_unparse (u, m_uuid);
+ }
+
+ operator const gchar * (void) const {
+ return m_uuid;
+ }
+
+private:
+ gchar m_uuid[40];
+};
+
+class Uname {
+public:
+ Uname (void) {
+ uname (&m_buf);
+ }
+
+ const gchar *hostname (void) const { return m_buf.nodename; }
+private:
+ struct utsname m_buf;
+};
+
+class Hostname : public Uname {
+public:
+ operator const gchar * (void) const {
+ return hostname ();
+ }
+};
+
+class StaticString {
+public:
+ StaticString (const gchar *str) : m_string (str) {}
+ gboolean operator == (const gchar *str) const {
+ if (G_UNLIKELY (m_string == str))
+ return TRUE;
+ return g_strcmp0 (m_string, str) == 0;
+ }
+ gboolean operator != (const gchar *str) const {
+ if (G_UNLIKELY (m_string == str))
+ return FALSE;
+ return g_strcmp0 (m_string, str) != 0;
+ }
+ operator const gchar * (void) const {
+ return m_string;
+ }
+private:
+ const gchar *m_string;
+};
+
+};
+#endif
diff --git a/src/main.db b/src/main.db
new file mode 120000
index 0000000..9cd4f3e
--- /dev/null
+++ b/src/main.db
@@ -0,0 +1 @@
+../data/db/main.db \ No newline at end of file
diff --git a/engine/pinyin.xml.in.in b/src/pinyin.xml.in.in
index a7f7760..9e04313 100644
--- a/engine/pinyin.xml.in.in
+++ b/src/pinyin.xml.in.in
@@ -1,8 +1,8 @@
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<!-- filename: pinyin.xml -->
<component>
- <name>org.freedesktop.IBus.PinYin</name>
- <description>PinYin Component</description>
+ <name>org.freedesktop.IBus.Pinyin</name>
+ <description>Pinyin Component</description>
<exec>${libexecdir}/ibus-engine-pinyin --ibus</exec>
<version>@VERSION@</version>
<author>Peng Huang &lt;shawn.p.huang@gmail.com&gt;</author>
@@ -10,18 +10,18 @@
<homepage>http://code.google.com/p/ibus</homepage>
<textdomain>ibus-pinyin</textdomain>
- <!-- for static engines -->
<engines>
<engine>
<name>pinyin</name>
- <language>zh_CN</language>
+ <language>zh</language>
<license>GPL</license>
<author>Peng Huang &lt;shawn.p.huang@gmail.com&gt;</author>
<icon>${pkgdatadir}/icons/ibus-pinyin.svg</icon>
<layout>us</layout>
- <longname>PinYin</longname>
- <description>PinYin Input Method</description>
+ <longname>Pinyin</longname>
+ <description>Pinyin input method</description>
<rank>99</rank>
</engine>
</engines>
+
</component>
diff --git a/src/scripts/genpytable.py b/src/scripts/genpytable.py
new file mode 100644
index 0000000..c3d8cf3
--- /dev/null
+++ b/src/scripts/genpytable.py
@@ -0,0 +1,354 @@
+# vim:set et sts=4:
+
+from pydict import *
+
+def str_cmp(a, b):
+ if len(a) == len(b):
+ return cmp(a, b)
+ else:
+ return len(a) - len(b)
+
+pinyin_list = PINYIN_DICT.keys()
+pinyin_list.sort()
+
+shengmu_list = SHENGMU_DICT.keys()
+shengmu_list.remove("")
+shengmu_list.sort()
+
+auto_correct = [
+ ("ng", "gn"),
+ ("ng", "mg"),
+ ("iu", "iou"),
+ ("ui", "uei"),
+ ("un", "uen"),
+ ("ue", "ve")]
+
+fuzzy_shengmu = [
+ ("c", "ch"),
+ ("ch", "c"),
+ ("z", "zh"),
+ ("zh", "z"),
+ ("s", "sh"),
+ ("sh", "s"),
+ ("l", "n"),
+ ("n", "l"),
+ ("f", "h"),
+ ("h", "f"),
+ ("l", "r"),
+ ("r", "l"),
+ ("k", "g"),
+ ("g", "k"),
+ ]
+
+fuzzy_yunmu = [
+ ("an", "ang"),
+ ("ang", "an"),
+ ("en", "eng"),
+ ("eng", "en"),
+ ("in", "ing"),
+ ("ing", "in"),
+ ("ian", "iang"),
+ ("iang", "ian"),
+ ("uan", "uang"),
+ ("uang", "uan"),
+ ]
+
+def get_sheng_yun(pinyin):
+ if pinyin == None:
+ return None, None
+ if pinyin == "ng":
+ return "", "ng"
+ for i in range(2, 0, -1):
+ s = pinyin[:i]
+ if s in shengmu_list:
+ return s, pinyin[i:]
+ return "", pinyin
+
+yunmu_list = set([])
+for p in pinyin_list:
+ s, y = get_sheng_yun(p)
+ yunmu_list |= set([y])
+yunmu_list = list(yunmu_list)
+yunmu_list.sort()
+
+shengmu_yunmu_list = shengmu_list + yunmu_list
+id_dict = {}
+for i, y in enumerate(shengmu_yunmu_list):
+ id_dict[y] = i + 1
+
+fuzzy_shengmu_dict = {}
+for s1, s2 in fuzzy_shengmu:
+ if s1 not in fuzzy_shengmu_dict:
+ fuzzy_shengmu_dict[s1] = []
+ fuzzy_shengmu_dict[s1].append(s2)
+
+fuzzy_yunmu_dict = {}
+for y1, y2 in fuzzy_yunmu:
+ if y1 not in fuzzy_yunmu_dict:
+ fuzzy_yunmu_dict[y1] = []
+ fuzzy_yunmu_dict[y1].append(y2)
+
+def encode_pinyin(pinyin):
+ if pinyin == None or pinyin == "":
+ return 0
+ return id_dict[pinyin]
+
+ e = 0
+ for c in pinyin:
+ e = (e << 5) + (ord(c) - ord('a') + 1)
+ return e
+
+def get_pinyin():
+ for p in pinyin_list:
+ s, y = get_sheng_yun(p)
+ yield p, s, y, len(p), []
+
+ for s in shengmu_list:
+ yield s, s, "", len(s), ["PINYIN_SIMPLE_PINYIN"]
+
+ for c, w in auto_correct:
+ flag = "PINYIN_CORRECT_%s_TO_%s" % (w.upper(), c.upper())
+ for p in pinyin_list:
+ if p.endswith(c) and p != c:
+ wp = p.replace(c, w)
+ s, y = get_sheng_yun(p)
+ yield wp, s, y, len(wp), [flag]
+
+ for s1, s2 in fuzzy_shengmu:
+ flag = "PINYIN_FUZZY_%s_%s" % (s1.upper(), s2.upper())
+ for y in yunmu_list:
+ if s1 + y not in pinyin_list and s2 + y in pinyin_list:
+ yield s1 + y, s1, y, len(s1) + len(y), [flag]
+ # if s2 + y not in pinyin_list and s1 + y in pinyin_list:
+ # yield s2 + y, s2, y, len (s2) + len(y), [flag]
+
+ for y1, y2 in fuzzy_yunmu:
+ flag = "PINYIN_FUZZY_%s_%s" % (y1.upper(), y2.upper())
+ for s in shengmu_list:
+ if s + y1 not in pinyin_list and s + y2 in pinyin_list:
+ yield s + y1, s, y1, len(s) + len(y1), [flag]
+ # if s + y2 not in pinyin_list and s + y1 in pinyin_list:
+ # yield s + y2, s, y2, len(s) + len(y2), [flag]
+
+
+def get_pinyin_with_fuzzy():
+ for text, s, y, l, flags in get_pinyin():
+ fss = fuzzy_shengmu_dict.get(s, ["", ""])
+ fys = fuzzy_yunmu_dict.get(y, ["", ""])
+
+ try:
+ fs1, fs2 = fss
+ except:
+ fs1, fs2 = fss[0], ""
+
+ try:
+ fy1, fy2 = fys
+ except:
+ fy1, fy2 = fys[0], ""
+
+ if fs1 and \
+ (fs1 + y not in pinyin_list) and \
+ (fy1 and fs1 + fy1 not in pinyin_list) and \
+ (fy2 and fs1 + fy2 not in pinyin_list):
+ fs1 = ""
+
+ if fs2 and \
+ (fs2 + y not in pinyin_list) and \
+ (fy1 and fs2 + fy1 not in pinyin_list) and \
+ (fy2 and fs2 + fy2 not in pinyin_list):
+ fs2 = ""
+
+ if fy1 and \
+ (s + fy1 not in pinyin_list) and \
+ (fs1 and fs1 + fy1 not in pinyin_list) and \
+ (fs2 and fs2 + fy1 not in pinyin_list):
+ fy1 = ""
+
+ if fy2 and \
+ (s + fy2 not in pinyin_list) and \
+ (fs1 and fs1 + fy2 not in pinyin_list) and \
+ (fs2 and fs2 + fy2 not in pinyin_list):
+ fy2 = ""
+
+ yield text, s, y, s, y, fs1, fy1, fs2, fy2, l, flags
+
+
+def gen_header():
+ print '''/* Please do not modify this file. It is generated by script */
+#include "Types.h"
+
+namespace PY {
+'''
+
+def gen_macros():
+ print '#define PINYIN_ID_VOID (-1)'
+ print '#define PINYIN_ID_ZERO (0)'
+ for y in shengmu_list:
+ print '#define PINYIN_ID_%s (%d)' % (y.upper(), encode_pinyin(y))
+
+ for y in yunmu_list:
+ print '#define PINYIN_ID_%s (%d)' % (y.upper(), encode_pinyin(y))
+ print
+ print
+ print
+
+def gen_option_check(name, fuzzy):
+ print '''static gboolean
+%s (guint option, gint id, gint fid)
+{
+ switch ((id << 16) | fid) {''' % name
+ for y1, y2 in fuzzy:
+ flag = "PINYIN_FUZZY_%s_%s" % (y1.upper(), y2.upper())
+ args = tuple(["PINYIN_ID_%s" % y.upper() for y in [y1, y2]]) + (flag, )
+ print ''' case (%s << 16) | %s:
+ return (option & %s);''' % args
+
+ print ' default: return FALSE;'
+ print ' }'
+ print '}'
+
+def union_dups(a):
+ n = {}
+ for r in a:
+ if r[:-1] in n:
+ n[r[:-1]] += r[-1]
+ else:
+ n[r[:-1]] = r[-1]
+ na = []
+ for k, flags in n.items():
+ na.append (tuple(list(k) + [" | ".join(flags) if flags else 0]))
+ na.sort()
+ return na
+
+def gen_tables():
+
+ pinyins = list(get_pinyin_with_fuzzy())
+ pinyins = union_dups(pinyins)
+
+ print 'static const Pinyin pinyin_table[] = {'
+ for i, p in enumerate(pinyins):
+ args = (i, ) + tuple(['"%s"' % s for s in p[:3]]) + tuple(["PINYIN_ID_%s" % s.upper() if s else "PINYIN_ID_ZERO" for s in p[3:9]]) + p[9:-1] + (str(p[-1]), )
+ print ''' { /* %d */
+ text : %s,
+ sheng : %s,
+ yun : %s,
+ sheng_id : %s,
+ yun_id : %s,
+ fsheng_id : %s,
+ fyun_id : %s,
+ fsheng_id_2 : %s,
+ fyun_id_2 : %s,
+ len : %d,
+ flags : %s
+ },''' % args
+
+ print '};'
+ print
+ print '#define PINYIN_TABLE_NR (sizeof (pinyin_table) / sizeof (pinyin_table[0]))'
+
+ return pinyins
+
+def get_all_special():
+ for p in pinyin_list:
+ if p[-1] in ["n", "g", "r"]:
+ for yun in yunmu_list:
+ if yun not in pinyin_list:
+ continue
+ new_pinyin = p[-1] + yun
+ # if new_pinyin in pinyin_list:
+ yield p, yun, p[:-1], new_pinyin
+ elif p[-1] in ["e"]:
+ yield p, "r", p[:-1], "er"
+
+def get_freq_sum_2(db, p1, p2):
+ s1, y1 = get_sheng_yun(p1)
+ s2, y2 = get_sheng_yun(p2)
+
+ sql = "select max(freq), phrase from py_phrase_1 where s0 = %d and y0 = %d and s1 = %d and y1 = %d"
+
+ c = db.execute(sql % (encode_pinyin(s1), encode_pinyin(y1), encode_pinyin(s2), encode_pinyin(y2)))
+ for r in c:
+ return r[0]
+ return 0
+
+def get_freq_sum_1(db, p1):
+ s1, y1 = get_sheng_yun(p1)
+
+ sql = "select max(freq), phrase from py_phrase_0 where s0 = %d and y0 = %d"
+
+ c = db.execute(sql % (encode_pinyin(s1), encode_pinyin(y1)))
+ for r in c:
+ return r[0] if r[0] else 0
+ return 0
+
+def compaired_special():
+ import sqlite3
+ db = sqlite3.connect("py.db")
+
+ for p1, p2, p3, p4 in get_all_special():
+ if p3 not in pinyin_list or p4 not in pinyin_list:
+ continue
+ if p1 not in pinyin_list or p2 not in pinyin_list:
+ yield p1, p2, p3, p4
+ continue
+
+ if p3 not in pinyin_list or p4 not in pinyin_list:
+ continue
+
+ a1 = get_freq_sum_2(db, p1, p2)
+ a2 = get_freq_sum_2(db, p3, p4)
+ if a1 == a2:
+ a1 = get_freq_sum_1(db, p1) + get_freq_sum_1(db, p2)
+ a2 = get_freq_sum_1(db, p3) + get_freq_sum_1(db, p4)
+ if a1 < a2:
+ yield p1, p2, p3, p4
+
+def gen_full_pinyin_table(pinyins):
+ _dict = {}
+ for i in xrange(0, len(pinyins)):
+ _dict[pinyins[i]] = i
+ full_pinyin = []
+ for i in xrange(0, len(pinyins)):
+ if pinyins[i][0] in pinyin_list:
+ full_pinyin.append (pinyins[i])
+ full_pinyin.sort(lambda a, b: (cmp(a[1], b[1]) << 16) + cmp(a[2],b[4]))
+ print 'static const Pinyin *full_pinyin_table[] = {'
+ for p in full_pinyin:
+ print " &pinyin_table[%d], // %s" % (_dict[p], p[0])
+ print '};'
+ print '#define FULL_PINYIN_TABLE_NR (sizeof (full_pinyin_table) / sizeof (full_pinyin_table[0]))'
+ print
+
+
+def gen_special_table(pinyins):
+ _dict = {}
+ for i in xrange(0, len(pinyins)):
+ _dict[pinyins[i][0]] = i
+
+ l = list(compaired_special())
+ l.sort()
+ print 'static const Pinyin *special_table[][4] = {'
+ for r in l:
+ ids = [("&pinyin_table[%d]," % _dict[py]).ljust(20) for py in r]
+
+ print ' { %s %s %s %s },' % tuple(ids), "/* %s %s => %s %s */" % r
+ print '};'
+ print '#define SPECIAL_TABLE_NR (sizeof (special_table) / sizeof (special_table[0]))'
+ print
+
+
+def main():
+ gen_header()
+ # gen_macros()
+ pinyins = gen_tables()
+ # gen_full_pinyin_table (pinyins)
+ gen_special_table(pinyins)
+ # gen_option_check("pinyin_option_check_sheng", fuzzy_shengmu)
+ # gen_option_check("pinyin_option_check_yun", fuzzy_yunmu)
+
+ print "};"
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/src/scripts/pydict.py b/src/scripts/pydict.py
new file mode 100644
index 0000000..72e1449
--- /dev/null
+++ b/src/scripts/pydict.py
@@ -0,0 +1,105 @@
+PINYIN_DICT = {
+ "a" : 1, "ai" : 2, "an" : 3, "ang" : 4, "ao" : 5,
+ "ba" : 6, "bai" : 7, "ban" : 8, "bang" : 9, "bao" : 10,
+ "bei" : 11, "ben" : 12, "beng" : 13, "bi" : 14, "bian" : 15,
+ "biao" : 16, "bie" : 17, "bin" : 18, "bing" : 19, "bo" : 20,
+ "bu" : 21, "ca" : 22, "cai" : 23, "can" : 24, "cang" : 25,
+ "cao" : 26, "ce" : 27, "cen" : 28, "ceng" : 29, "ci" : 30,
+ "cong" : 31, "cou" : 32, "cu" : 33, "cuan" : 34, "cui" : 35,
+ "cun" : 36, "cuo" : 37, "cha" : 38, "chai" : 39, "chan" : 40,
+ "chang" : 41, "chao" : 42, "che" : 43, "chen" : 44, "cheng" : 45,
+ "chi" : 46, "chong" : 47, "chou" : 48, "chu" : 49, "chuai" : 50,
+ "chuan" : 51, "chuang" : 52, "chui" : 53, "chun" : 54, "chuo" : 55,
+ "da" : 56, "dai" : 57, "dan" : 58, "dang" : 59, "dao" : 60,
+ "de" : 61, "dei" : 62,
+ # "den" : 63,
+ "deng" : 64, "di" : 65,
+ "dia" : 66, "dian" : 67, "diao" : 68, "die" : 69, "ding" : 70,
+ "diu" : 71, "dong" : 72, "dou" : 73, "du" : 74, "duan" : 75,
+ "dui" : 76, "dun" : 77, "duo" : 78, "e" : 79, "ei" : 80,
+ "en" : 81, "er" : 82, "fa" : 83, "fan" : 84, "fang" : 85,
+ "fei" : 86, "fen" : 87, "feng" : 88, "fo" : 89, "fou" : 90,
+ "fu" : 91, "ga" : 92, "gai" : 93, "gan" : 94, "gang" : 95,
+ "gao" : 96, "ge" : 97, "gei" : 98, "gen" : 99, "geng" : 100,
+ "gong" : 101, "gou" : 102, "gu" : 103, "gua" : 104, "guai" : 105,
+ "guan" : 106, "guang" : 107, "gui" : 108, "gun" : 109, "guo" : 110,
+ "ha" : 111, "hai" : 112, "han" : 113, "hang" : 114, "hao" : 115,
+ "he" : 116, "hei" : 117, "hen" : 118, "heng" : 119, "hong" : 120,
+ "hou" : 121, "hu" : 122, "hua" : 123, "huai" : 124, "huan" : 125,
+ "huang" : 126, "hui" : 127, "hun" : 128, "huo" : 129, "ji" : 130,
+ "jia" : 131, "jian" : 132, "jiang" : 133, "jiao" : 134, "jie" : 135,
+ "jin" : 136, "jing" : 137, "jiong" : 138, "jiu" : 139, "ju" : 140,
+ "juan" : 141, "jue" : 142, "jun" : 143, "ka" : 144, "kai" : 145,
+ "kan" : 146, "kang" : 147, "kao" : 148, "ke" : 149,
+ # "kei" : 150,
+ "ken" : 151, "keng" : 152, "kong" : 153, "kou" : 154, "ku" : 155,
+ "kua" : 156, "kuai" : 157, "kuan" : 158, "kuang" : 159, "kui" : 160,
+ "kun" : 161, "kuo" : 162, "la" : 163, "lai" : 164, "lan" : 165,
+ "lang" : 166, "lao" : 167, "le" : 168, "lei" : 169, "leng" : 170,
+ "li" : 171, "lia" : 172, "lian" : 173, "liang" : 174, "liao" : 175,
+ "lie" : 176, "lin" : 177, "ling" : 178, "liu" : 179,
+ "lo" : 180,
+ "long" : 181, "lou" : 182, "lu" : 183, "luan" : 184, "lue" : 185,
+ "lun" : 186, "luo" : 187, "lv" : 188,
+ # "lve" : 189,
+ "ma" : 190,
+ "mai" : 191, "man" : 192, "mang" : 193, "mao" : 194, "me" : 195,
+ "mei" : 196, "men" : 197, "meng" : 198, "mi" : 199, "mian" : 200,
+ "miao" : 201, "mie" : 202, "min" : 203, "ming" : 204, "miu" : 205,
+ "mo" : 206, "mou" : 207, "mu" : 208, "na" : 209, "nai" : 210,
+ "nan" : 211, "nang" : 212, "nao" : 213, "ne" : 214, "nei" : 215,
+ "nen" : 216, "neng" : 217, "ni" : 218, "nian" : 219, "niang" : 220,
+ "niao" : 221, "nie" : 222, "nin" : 223, "ning" : 224, "niu" : 225,
+ # "ng" : 226,
+ "nong" : 227, "nou" : 228, "nu" : 229, "nuan" : 230,
+ "nue" : 231, "nuo" : 232, "nv" : 233,
+ #"nve" : 234,
+ "o" : 235,
+ "ou" : 236, "pa" : 237, "pai" : 238, "pan" : 239, "pang" : 240,
+ "pao" : 241, "pei" : 242, "pen" : 243, "peng" : 244, "pi" : 245,
+ "pian" : 246, "piao" : 247, "pie" : 248, "pin" : 249, "ping" : 250,
+ "po" : 251, "pou" : 252, "pu" : 253, "qi" : 254, "qia" : 255,
+ "qian" : 256, "qiang" : 257, "qiao" : 258, "qie" : 259, "qin" : 260,
+ "qing" : 261, "qiong" : 262, "qiu" : 263, "qu" : 264, "quan" : 265,
+ "que" : 266, "qun" : 267, "ran" : 268, "rang" : 269, "rao" : 270,
+ "re" : 271, "ren" : 272, "reng" : 273, "ri" : 274, "rong" : 275,
+ "rou" : 276, "ru" : 277, "ruan" : 278, "rui" : 279, "run" : 280,
+ "ruo" : 281, "sa" : 282, "sai" : 283, "san" : 284, "sang" : 285,
+ "sao" : 286, "se" : 287, "sen" : 288, "seng" : 289, "si" : 290,
+ "song" : 291, "sou" : 292, "su" : 293, "suan" : 294, "sui" : 295,
+ "sun" : 296, "suo" : 297, "sha" : 298, "shai" : 299, "shan" : 300,
+ "shang" : 301, "shao" : 302, "she" : 303, "shei" : 304, "shen" : 305,
+ "sheng" : 306, "shi" : 307, "shou" : 308, "shu" : 309, "shua" : 310,
+ "shuai" : 311, "shuan" : 312, "shuang" : 313, "shui" : 314, "shun" : 315,
+ "shuo" : 316, "ta" : 317, "tai" : 318, "tan" : 319, "tang" : 320,
+ "tao" : 321, "te" : 322,
+ # "tei" : 323,
+ "teng" : 324, "ti" : 325,
+ "tian" : 326, "tiao" : 327, "tie" : 328, "ting" : 329, "tong" : 330,
+ "tou" : 331, "tu" : 332, "tuan" : 333, "tui" : 334, "tun" : 335,
+ "tuo" : 336, "wa" : 337, "wai" : 338, "wan" : 339, "wang" : 340,
+ "wei" : 341, "wen" : 342, "weng" : 343, "wo" : 344, "wu" : 345,
+ "xi" : 346, "xia" : 347, "xian" : 348, "xiang" : 349, "xiao" : 350,
+ "xie" : 351, "xin" : 352, "xing" : 353, "xiong" : 354, "xiu" : 355,
+ "xu" : 356, "xuan" : 357, "xue" : 358, "xun" : 359, "ya" : 360,
+ "yan" : 361, "yang" : 362, "yao" : 363, "ye" : 364, "yi" : 365,
+ "yin" : 366, "ying" : 367, "yo" : 368, "yong" : 369, "you" : 370,
+ "yu" : 371, "yuan" : 372, "yue" : 373, "yun" : 374, "za" : 375,
+ "zai" : 376, "zan" : 377, "zang" : 378, "zao" : 379, "ze" : 380,
+ "zei" : 381, "zen" : 382, "zeng" : 383, "zi" : 384, "zong" : 385,
+ "zou" : 386, "zu" : 387, "zuan" : 388, "zui" : 389, "zun" : 390,
+ "zuo" : 391, "zha" : 392, "zhai" : 393, "zhan" : 394, "zhang" : 395,
+ "zhao" : 396, "zhe" : 397, "zhen" : 398, "zheng" : 399, "zhi" : 400,
+ "zhong" : 401, "zhou" : 402, "zhu" : 403, "zhua" : 404, "zhuai" : 405,
+ "zhuan" : 406, "zhuang" : 407, "zhui" : 408, "zhun" : 409, "zhuo" : 410,
+ # some weird pinyins
+ #~ "eng" : 411, "chua" : 412, "fe" : 413, "fiao" : 414, "liong" : 415
+}
+
+SHENGMU_DICT = {
+ "" : 0, "b" : 1, "p" : 2, "m" : 3, "f" : 4, "d" : 5,
+ "t" : 6, "n" : 7, "l" : 8, "g" : 9, "k" : 10, "h" : 11,
+ "j" : 12, "q" : 13, "x" : 14, "zh" : 15, "ch" : 16, "sh" : 17,
+ "r" : 18, "z" : 19, "c" : 20, "s" : 21, "y" : 22, "w" : 23
+}
+
diff --git a/engine/special_table b/src/special_table
index f00d13c..0948b37 100644
--- a/engine/special_table
+++ b/src/special_table
@@ -8,9 +8,7 @@
#
# 以 X_ 开头的特殊字符串为内建标识 例如 X_DATE_1 代表阿拉伯数字格式的当前日期.
#
-# 以 0x 开头的是16进制 Unicode 编码
-#
-# 用户可以按照该文件格式自行编辑定制的用户文件 ~/.scim/chinese/special_table
+# 用户可以按照该文件格式自行编辑定制的用户文件 ~/.ibus/pinyin/special_table
#
# 当前日期