From 924e244fff3a48eea3aa742bfbe0885c62f93d71 Mon Sep 17 00:00:00 2001 From: Huang Peng Date: Wed, 11 Jun 2008 18:01:32 +0800 Subject: [PATCH] WIP anthy engine. --- engine/anthy/Makefile | 4 +- engine/anthy/engine.py | 257 +++++++++++++++++++++++++++++++++++++ engine/anthy/factory.py | 33 +++++ engine/anthy/tables.py | 331 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 624 insertions(+), 1 deletion(-) create mode 100644 engine/anthy/engine.py create mode 100644 engine/anthy/factory.py create mode 100644 engine/anthy/tables.py diff --git a/engine/anthy/Makefile b/engine/anthy/Makefile index 36dbf74..70d0428 100644 --- a/engine/anthy/Makefile +++ b/engine/anthy/Makefile @@ -1,8 +1,10 @@ -all: _anthy.so +all: _anthy.so test anthy.py anthy_wrap.c: anthy.i swig -python -I/usr/include $< _anthy.so: anthy_wrap.c $(CC) -shared -o $@ $^ -fPIC `python-config --cflags --libs` `pkg-config anthy --cflags --libs` +test: + PYTHONPATH=../.. python main.py clean: $(RM) anthy.py anthy_wrap.c _anthy.so diff --git a/engine/anthy/engine.py b/engine/anthy/engine.py new file mode 100644 index 0000000..faf14d6 --- /dev/null +++ b/engine/anthy/engine.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python +import gobject +import gtk +import pango +import dbus +import ibus +import anthy +from tables import * +from ibus import keysyms +from ibus import interface + +class Engine (interface.IEngine): + def __init__ (self, dbusconn, object_path): + interface.IEngine.__init__ (self, dbusconn, object_path) + self._dbusconn = dbusconn + + # create anthy context + self._context = anthy.anthy_context () + self._context._set_encoding (2) + + self._lookup_table = ibus.LookupTable () + self._prop_list = ibus.PropList () + + # use reset to init values + self._reset () + + # reset values of engine + def _reset (self): + self._input_chars = u"" + self._convert_chars = u"" + self._cursor_pos = 0 + self._need_update = False + self._convert_begined = False + self._segments = [] + self._lookup_table.clean () + + # begine convert + def _begin_convert (self): + if self._convert_begined: + return + self._convert_begined = True + + self._context.set_string (self._input_chars.encode ("utf-8")) + conv_stat = anthy.anthy_conv_stat () + self._context.get_stat (conv_stat) + + for i in xrange (0, conv_stat.nr_segment): + buf = " " * 100 + l = self._context.get_segment (i, 0, buf, 100) + text = unicode (buf[:l], "utf-8") + self._segments.append ((0, text)) + + self._cursor_pos = 0 + + self._fill_lookup_table () + + def _fill_lookup_table (): + # get segment stat + seg_stat = anthy.anthy_segment_stat () + self._context.get_segment_stat (self._current_pos, seg_stat) + + # fill lookup_table + self._lookup_table.clean () + for i in xrange (0, seg_stat.nr_candidate): + buf = " " * 100 + l = self._context.get_segment (self._cursor_pos, i, buf, 100) + candidate = unicode (buf[:l], "utf-8") + self._lookup_table.append_candidate (candidate) + + def _process_key_event (self, keyval, is_press, state): + # ignore key release events + if not is_press: + return False + + if self._input_chars: + if keyval == keysyms.Return: + self._commit_string (self._input_chars) + return True + elif keyval == keysyms.Escape: + self._reset () + return True + elif keyval == keysyms.BackSpace: + self._input_chars = self._input_chars[:self._cursor_pos - 1] + self._input_chars [self._cursor_pos:] + self._invalidate () + return True + elif keyval == keysyms.space: + if not self._convert_begined: + self._begine_convert () + self._invalidate () + else: + self._cursor_down () + return True + elif keyval >= keysyms._1 and keyval <= keysyms._9: + index = keyval - keysyms._1 + candidates = self._lookup_table.get_canidates_in_current_page () + if index >= len (candidates): + return False + candidate = candidates[index][0] + self._commit_string (candidate) + return True + elif keyval == keysyms.Page_Up or keyval == keysyms.KP_Page_Up: + if self._lookup_table.page_up (): + self._update_lookup_table () + return True + elif keyval == keysyms.Up: + self._cursor_up () + return True + elif keyval == keysyms.Down: + self._cursor_down () + return True + elif keyval == keysyms.Left or keyval == keysyms.Right: + return True + elif keyval == keysyms.Page_Down or keyval == keysyms.KP_Page_Down: + if self._lookup_table.page_down (): + self._update_lookup_table () + return True + if keyval in xrange (keysyms.a, keysyms.z + 1) or \ + keyval in xrange (keysyms.A, keysyms.Z + 1): + if state & (keysyms.CONTROL_MASK | keysyms.ALT_MASK) == 0: + self._input_chars += unichr (keyval) + self._cursor_pos += 1 + self._invalidate () + return True + else: + if keyval < 128 and self._input_chars: + self._commit_string (self._input_chars) + + return False + + def _invalidate (self): + if self._need_update: + return + self._need_update = True + gobject.idle_add (self._update, priority = gobject.PRIORITY_LOW) + + def _cursor_up (self): + # only process cursor down in convert mode + if not self._convert_begined: + return False + + if not self._lookup_table.cursor_up (): + return False + + candidate = self._lookup_table.get_current_candidate ()[0] + index = self._lookup_table.get_cursor_pos () + self._segments[self._cursor_pos] = index, candidate + self._invalidate () + return True + + def _cursor_down (self): + # only process cursor down in convert mode + if not self._convert_begined: + return False + + if not self._lookup_table.cursor_down (): + return False + + candidate = self._lookup_table.get_current_candidate ()[0] + index = self._lookup_table.get_cursor_pos () + self._segments[self._cursor_pos] = index, candidate + self._invalidate () + return True + + def _commit_string (self, text): + self._reset () + self.CommitString (text) + self._update () + + def _update_input_chars (self): + begin, end = max (self._cursor_pos - 4, 0), self._cursor_pos + + for i in range (begin, end): + text = self._input_chars[i:end] + romja = romaji_typing_rule.get (text, None) + if romja != None: + self._input_chars = u"".join ((self._input_chars[:i], romja, self._input_chars[end:])) + self._cursor_pos -= len(text) + self._cursor_pos += len(romja) + + attrs = ibus.AttrList () + attrs.append (ibus.AttributeUnderline (pango.UNDERLINE_SINGLE, 0, len (self._input_chars.encode ("utf-8")))) + + self.UpdatePreedit (dbus.String (self._input_chars), + attrs.to_dbus_value (), + dbus.Int32 (self._cursor_pos), + len (self._input_chars) > 0) + + def _update_convert_chars (self): + self._convert_chars = u"" + buf = " " * 100 + pos = 0 + i = 0 + for seg_index, text in self._segments: + self._convert_chars += text + if i < self._cursor_pos: + pos += len (text) + i += 1 + + attrs = ibus.AttrList () + attrs.append (ibus.AttributeUnderline (pango.UNDERLINE_SINGLE, 0, len (self._convert_chars.encode ("utf-8")))) + + self.UpdatePreedit (dbus.String (self._convert_chars), + attrs.to_dbus_value (), + dbus.Int32 (pos), + True) + + def _update (self): + self._need_update = False + if self._convert_begined: + self._update_input_chars () + else: + self._update_convert_chars () + + # methods for dbus rpc + def ProcessKeyEvent (self, keyval, is_press, state): + try: + return self._process_key_event (keyval, is_press, state) + except Exception, e: + print e + return False + + def FocusIn (self): + self.RegisterProperties (self._prop_list.to_dbus_value ()) + print "FocusIn" + + def FocusOut (self): + print "FocusOut" + + def SetCursorLocation (self, x, y, w, h): + pass + + def Reset (self): + print "Reset" + + def PageUp (self): + print "PageUp" + + def PageDown (self): + print "PageDown" + + def CursorUp (self): + self._cursor_up () + + def CursorDown (self): + self._cursor_down () + + def SetEnable (self, enable): + self._enable = enable + if self._enable: + self.RegisterProperties (self._prop_list.to_dbus_value ()) + + def PropertyActivate (self, prop_name): + print "PropertyActivate (%s)" % prop_name + + def Destroy (self): + print "Destroy" + diff --git a/engine/anthy/factory.py b/engine/anthy/factory.py new file mode 100644 index 0000000..62f697c --- /dev/null +++ b/engine/anthy/factory.py @@ -0,0 +1,33 @@ +from ibus import interface +import engine + +FACTORY_PATH = "/com/redhat/IBus/engines/Anthy/Factory" +ENGINE_PATH = "/com/redhat/IBus/engines/Anthy/Engine/%d" + +class DemoEngineFactory (interface.IEngineFactory): + NAME = "AnthyEngine" + LANG = "ja" + ICON = "" + AUTHORS = "Huang Peng " + CREDITS = "GPLv2" + + def __init__ (self, dbusconn): + interface.IEngineFactory.__init__ (self, dbusconn, object_path = FACTORY_PATH) + self._dbusconn = dbusconn + self._max_engine_id = 1 + + def GetInfo (self): + return [ + self.NAME, + self.LANG, + self.ICON, + self.AUTHORS, + self.CREDITS + ] + + def CreateEngine (self): + engine_path = ENGINE_PATH % self._max_engine_id + self._max_engine_id += 1 + return engine.Engine (self._dbusconn, engine_path) + + diff --git a/engine/anthy/tables.py b/engine/anthy/tables.py new file mode 100644 index 0000000..e01a464 --- /dev/null +++ b/engine/anthy/tables.py @@ -0,0 +1,331 @@ +# -*- encoding: utf-8 -*- + +# string, result, cont +romaji_typing_rule = { + u"-" : u"ー", + u"a" : u"あ", + u"i" : u"い", + u"u" : u"う", + u"e" : u"え", + u"o" : u"お", + u"xa" : u"ぁ", + u"xi" : u"ぃ", + u"xu" : u"ぅ", + u"xe" : u"ぇ", + u"xo" : u"ぉ", + u"la" : u"ぁ", + u"li" : u"ぃ", + u"lu" : u"ぅ", + u"le" : u"ぇ", + u"lo" : u"ぉ", + u"wi" : u"うぃ", + u"we" : u"うぇ", + u"wha" : u"うぁ", + u"whi" : u"うぃ", + u"whe" : u"うぇ", + u"who" : u"うぉ", + u"va" : u"ヴぁ", + u"vi" : u"ヴぃ", + u"vu" : u"ヴ", + u"ve" : u"ヴぇ", + u"vo" : u"ヴぉ", + u"ka" : u"か", + u"ki" : u"き", + u"ku" : u"く", + u"ke" : u"け", + u"ko" : u"こ", + u"ga" : u"が", + u"gi" : u"ぎ", + u"gu" : u"ぐ", + u"ge" : u"げ", + u"go" : u"ご", + u"kya" : u"きゃ", + u"kyi" : u"きぃ", + u"kyu" : u"きゅ", + u"kye" : u"きぇ", + u"kyo" : u"きょ", + u"gya" : u"ぎゃ", + u"gyi" : u"ぎぃ", + u"gyu" : u"ぎゅ", + u"gye" : u"ぎぇ", + u"gyo" : u"ぎょ", + u"sa" : u"さ", + u"si" : u"し", + u"su" : u"す", + u"se" : u"せ", + u"so" : u"そ", + u"za" : u"ざ", + u"zi" : u"じ", + u"zu" : u"ず", + u"ze" : u"ぜ", + u"zo" : u"ぞ", + u"sya" : u"しゃ", + u"syi" : u"しぃ", + u"syu" : u"しゅ", + u"sye" : u"しぇ", + u"syo" : u"しょ", + u"sha" : u"しゃ", + u"shi" : u"し", + u"shu" : u"しゅ", + u"she" : u"しぇ", + u"sho" : u"しょ", + u"zya" : u"じゃ", + u"zyi" : u"じぃ", + u"zyu" : u"じゅ", + u"zye" : u"じぇ", + u"zyo" : u"じょ", + u"ja" : u"じゃ", + u"jya" : u"じゃ", + u"ji" : u"じ", + u"jyi" : u"じぃ", + u"ju" : u"じゅ", + u"jyu" : u"じゅ", + u"je" : u"じぇ", + u"jye" : u"じぇ", + u"jo" : u"じょ", + u"jyo" : u"じょ", + u"ta" : u"た", + u"ti" : u"ち", + u"tu" : u"つ", + u"tsu" : u"つ", + u"te" : u"て", + u"to" : u"と", + u"da" : u"だ", + u"di" : u"ぢ", + u"du" : u"づ", + u"de" : u"で", + u"do" : u"ど", + u"xtu" : u"っ", + u"xtsu" : u"っ", + u"ltu" : u"っ", + u"ltsu" : u"っ", + u"tya" : u"ちゃ", + u"tyi" : u"ちぃ", + u"tyu" : u"ちゅ", + u"tye" : u"ちぇ", + u"tyo" : u"ちょ", + u"cha" : u"ちゃ", + u"chi" : u"ち", + u"chu" : u"ちゅ", + u"che" : u"ちぇ", + u"cho" : u"ちょ", + u"dya" : u"ぢゃ", + u"dyi" : u"ぢぃ", + u"dyu" : u"ぢゅ", + u"dye" : u"ぢぇ", + u"dyo" : u"ぢょ", + u"tha" : u"てゃ", + u"thi" : u"てぃ", + u"thu" : u"てゅ", + u"the" : u"てぇ", + u"tho" : u"てょ", + u"dha" : u"でゃ", + u"dhi" : u"でぃ", + u"dhu" : u"でゅ", + u"dhe" : u"でぇ", + u"dho" : u"でょ", + u"na" : u"な", + u"ni" : u"に", + u"nu" : u"ぬ", + u"ne" : u"ね", + u"no" : u"の", + u"nya" : u"にゃ", + u"nyi" : u"にぃ", + u"nyu" : u"にゅ", + u"nye" : u"にぇ", + u"nyo" : u"にょ", + u"ha" : u"は", + u"hi" : u"ひ", + u"hu" : u"ふ", + u"fu" : u"ふ", + u"he" : u"へ", + u"ho" : u"ほ", + u"ba" : u"ば", + u"bi" : u"び", + u"bu" : u"ぶ", + u"be" : u"べ", + u"bo" : u"ぼ", + u"pa" : u"ぱ", + u"pi" : u"ぴ", + u"pu" : u"ぷ", + u"pe" : u"ぺ", + u"po" : u"ぽ", + u"hya" : u"ひゃ", + u"hyi" : u"ひぃ", + u"hyu" : u"ひゅ", + u"hye" : u"ひぇ", + u"hyo" : u"ひょ", + u"bya" : u"びゃ", + u"byi" : u"びぃ", + u"byu" : u"びゅ", + u"bye" : u"びぇ", + u"byo" : u"びょ", + u"pya" : u"ぴゃ", + u"pyi" : u"ぴぃ", + u"pyu" : u"ぴゅ", + u"pye" : u"ぴぇ", + u"pyo" : u"ぴょ", + u"fa" : u"ふぁ", + u"fi" : u"ふぃ", + u"fu" : u"ふ", + u"fe" : u"ふぇ", + u"fo" : u"ふぉ", + u"ma" : u"ま", + u"mi" : u"み", + u"mu" : u"む", + u"me" : u"め", + u"mo" : u"も", + u"mya" : u"みゃ", + u"myi" : u"みぃ", + u"myu" : u"みゅ", + u"mye" : u"みぇ", + u"myo" : u"みょ", + u"lya" : u"ゃ", + u"xya" : u"ゃ", + u"ya" : u"や", + u"lyu" : u"ゅ", + u"xyu" : u"ゅ", + u"yu" : u"ゆ", + u"lyo" : u"ょ", + u"xyo" : u"ょ", + u"yo" : u"よ", + u"ra" : u"ら", + u"ri" : u"り", + u"ru" : u"る", + u"re" : u"れ", + u"ro" : u"ろ", + u"rya" : u"りゃ", + u"ryi" : u"りぃ", + u"ryu" : u"りゅ", + u"rye" : u"りぇ", + u"ryo" : u"りょ", + u"xwa" : u"ゎ", + u"wa" : u"わ", + u"wo" : u"を", +# u"n'" : u"ん", + u"nn" : u"ん", + u"wyi" : u"ゐ", + u"wye" : u"ゑ", +} + +#hiragana, katakana, half_katakana +hiragana_katakana_table = { + u"あ" : (u"ア", u"ア"), + u"い" : (u"イ", u"イ"), + u"う" : (u"ウ", u"ウ"), + u"え" : (u"エ", u"エ"), + u"お" : (u"オ", u"オ"), + u"か" : (u"カ", u"カ"), + u"き" : (u"キ", u"キ"), + u"く" : (u"ク", u"ク"), + u"け" : (u"ケ", u"ケ"), + u"こ" : (u"コ", u"コ"), + u"が" : (u"ガ", u"ガ"), + u"ぎ" : (u"ギ", u"ギ"), + u"ぐ" : (u"グ", u"グ"), + u"げ" : (u"ゲ", u"ゲ"), + u"ご" : (u"ゴ", u"ゴ"), + u"さ" : (u"サ", u"サ"), + u"し" : (u"シ", u"シ"), + u"す" : (u"ス", u"ス"), + u"せ" : (u"セ", u"セ"), + u"そ" : (u"ソ", u"ソ"), + u"ざ" : (u"ザ", u"ザ"), + u"じ" : (u"ジ", u"ジ"), + u"ず" : (u"ズ", u"ズ"), + u"ぜ" : (u"ゼ", u"ゼ"), + u"ぞ" : (u"ゾ", u"ゾ"), + u"た" : (u"タ", u"タ"), + u"ち" : (u"チ", u"チ"), + u"つ" : (u"ツ", u"ツ"), + u"て" : (u"テ", u"テ"), + u"と" : (u"ト", u"ト"), + u"だ" : (u"ダ", u"ダ"), + u"ぢ" : (u"ヂ", u"ヂ"), + u"づ" : (u"ヅ", u"ヅ"), + u"で" : (u"デ", u"デ"), + u"ど" : (u"ド", u"ド"), + u"な" : (u"ナ", u"ナ"), + u"に" : (u"ニ", u"ニ"), + u"ぬ" : (u"ヌ", u"ヌ"), + u"ね" : (u"ネ", u"ネ"), + u"の" : (u"ノ", u"ノ"), + u"は" : (u"ハ", u"ハ"), + u"ひ" : (u"ヒ", u"ヒ"), + u"ふ" : (u"フ", u"フ"), + u"へ" : (u"ヘ", u"ヘ"), + u"ほ" : (u"ホ", u"ホ"), + u"ば" : (u"バ", u"バ"), + u"び" : (u"ビ", u"ビ"), + u"ぶ" : (u"ブ", u"ブ"), + u"べ" : (u"ベ", u"ベ"), + u"ぼ" : (u"ボ", u"ボ"), + u"ぱ" : (u"パ", u"パ"), + u"ぴ" : (u"ピ", u"ピ"), + u"ぷ" : (u"プ", u"プ"), + u"ぺ" : (u"ペ", u"ペ"), + u"ぽ" : (u"ポ", u"ポ"), + u"ま" : (u"マ", u"マ"), + u"み" : (u"ミ", u"ミ"), + u"む" : (u"ム", u"ム"), + u"め" : (u"メ", u"メ"), + u"も" : (u"モ", u"モ"), + u"や" : (u"ヤ", u"ヤ"), + u"ゆ" : (u"ユ", u"ユ"), + u"よ" : (u"ヨ", u"ヨ"), + u"ら" : (u"ラ", u"ラ"), + u"り" : (u"リ", u"リ"), + u"る" : (u"ル", u"ル"), + u"れ" : (u"レ", u"レ"), + u"ろ" : (u"ロ", u"ロ"), + u"わ" : (u"ワ", u"ワ"), + u"を" : (u"ヲ", u"ヲ"), + u"ん" : (u"ン", u"ン"), + u"ぁ" : (u"ァ", u"ァ"), + u"ぃ" : (u"ィ", u"ィ"), + u"ぅ" : (u"ゥ", u"ゥ"), + u"ぇ" : (u"ェ", u"ェ"), + u"ぉ" : (u"ォ", u"ォ"), + u"っ" : (u"ッ", u"ッ"), + u"ゃ" : (u"ャ", u"ャ"), + u"ゅ" : (u"ュ", u"ュ"), + u"ょ" : (u"ョ", u"ョ"), + u"ヵ" : (u"ヵ", u"カ"), + u"ヶ" : (u"ヶ", u"ケ"), + u"ゎ" : (u"ヮ", u"ワ"), + u"ゐ" : (u"ヰ", u"ィ"), + u"ゑ" : (u"ヱ", u"ェ"), + u"ヴ" : (u"ヴ", u"ヴ"), + u"ー" : (u"ー", u"ー"), + u"、" : (u"、", u"、"), + u"。" : (u"。", u"。"), + u"!" : (u"!", u"!"), + u"”" : (u"”", u"\""), + u"#" : (u"#", u"#"), + u"$" : (u"$", u"$"), + u"%" : (u"%", u"%"), + u"&" : (u"&", u"&"), + u"’" : (u"’", u"'"), + u"(" : (u"(", u""), + u")" : (u")", u")"), + u"〜" : (u"〜", u"~"), + u"=" : (u"=", u"="), + u"^" : (u"^", u"u"), + u"\" : (u"\", u"\\"), + u"|" : (u"|", u"|"), + u"‘" : (u"‘", u"`"), + u"@" : (u"@", u"@"), + u"{" : (u"{", u""), + u"「" : (u"「", u"「"), + u"+" : (u"+", u"+"), + u";" : (u";", u";"), + u"*" : (u"*", u"*"), + u":" : (u":", u" : u"), + u"}" : (u"}", u")"), + u"」" : (u"」", u"」"), + u"<" : (u"<", u"<"), + u">" : (u">", u">"), + u"?" : (u"?", u"?"), + u"/" : (u"/", u"/"), + u"_" : (u"_", u"_"), +} -- 2.7.4