diff --git a/ibus-anthy-HEAD.patch b/ibus-anthy-HEAD.patch
index 8b13789..8c50da5 100644
--- a/ibus-anthy-HEAD.patch
+++ b/ibus-anthy-HEAD.patch
@@ -1 +1,1555 @@
-
+diff --git a/engine/engine.py b/engine/engine.py
+index c5841cb..56e5b28 100644
+--- a/engine/engine.py
++++ b/engine/engine.py
+@@ -22,6 +22,7 @@
+
+ import os
+ from os import path
++from locale import getpreferredencoding
+ import sys
+ import gobject
+ import ibus
+@@ -96,6 +97,7 @@ class Engine(ibus.EngineBase):
+ __setup_pid = 0
+ __prefs = None
+ __keybind = {}
++ __thumb = None
+
+ def __init__(self, bus, object_path):
+ super(Engine, self).__init__(bus, object_path)
+@@ -105,8 +107,10 @@ class Engine(ibus.EngineBase):
+ self.__context._set_encoding(anthy.ANTHY_UTF8_ENCODING)
+
+ # init state
++ self.__idle_id = 0
+ self.__input_mode = INPUT_MODE_HIRAGANA
+ self.__prop_dict = {}
++ self.__is_utf8 = (getpreferredencoding().lower() == "utf-8")
+
+ # self.__lookup_table = ibus.LookupTable(page_size=9, round=True)
+ size = self.__prefs.get_value('common', 'page_size')
+@@ -130,7 +134,6 @@ class Engine(ibus.EngineBase):
+ self.__preedit_ja_string = jastring.JaString(Engine.__typing_mode)
+ self.__convert_chars = u""
+ self.__cursor_pos = 0
+- self.__need_update = False
+ self.__convert_mode = CONV_MODE_OFF
+ self.__segments = list()
+ self.__lookup_table.clean()
+@@ -138,6 +141,11 @@ class Engine(ibus.EngineBase):
+ self._MM = 0
+ self._SS = 0
+ self._H = 0
++ self._RMM = 0
++ self._RSS = 0
++ if self.__idle_id != 0:
++ gobject.source_remove(self.__idle_id)
++ self.__idle_id = 0
+
+ def __init_props(self):
+ anthy_props = ibus.PropList()
+@@ -485,6 +493,8 @@ class Engine(ibus.EngineBase):
+ return True
+ self.__prop_dict[prop_name].set_state(state)
+ self.update_property(self.__prop_dict[prop_name])
++ if prop_name == u"TypingMode.ThumbShift":
++ self._reset_thumb()
+
+ mode, label = typing_modes[prop_name]
+
+@@ -526,6 +536,12 @@ class Engine(ibus.EngineBase):
+ elif mode == 1:
+ self.__on_key_return()
+
++ def do_destroy(self):
++ if self.__idle_id != 0:
++ gobject.source_remove(self.__idle_id)
++ self.__idle_id = 0
++ super(Engine,self).do_destroy()
++
+ # begine convert
+ def __begin_anthy_convert(self):
+ if self.__convert_mode == CONV_MODE_ANTHY:
+@@ -562,6 +578,15 @@ class Engine(ibus.EngineBase):
+ def __end_convert(self):
+ self.__end_anthy_convert()
+
++ def __candidate_cb(self, candidate):
++ if not self.__is_utf8:
++ return
++ for key in romaji_utf8_rule.keys():
++ if candidate.find(key) >= 0:
++ for value in romaji_utf8_rule[key]:
++ candidate = candidate.replace(key, value)
++ self.__lookup_table.append_candidate(ibus.Text(candidate))
++
+ def __fill_lookup_table(self):
+ if self.__convert_mode == CONV_MODE_PREDICTION:
+ seg_stat = anthy.anthy_prediction_stat()
+@@ -573,7 +598,7 @@ class Engine(ibus.EngineBase):
+ buf = self.__context.get_prediction(i)
+ candidate = unicode(buf, "utf-8")
+ self.__lookup_table.append_candidate(ibus.Text(candidate))
+-
++ self.__candidate_cb(candidate)
+ return
+
+ # get segment stat
+@@ -586,13 +611,14 @@ class Engine(ibus.EngineBase):
+ buf = self.__context.get_segment(self.__cursor_pos, i)
+ candidate = unicode(buf, "utf-8")
+ self.__lookup_table.append_candidate(ibus.Text(candidate))
++ self.__candidate_cb(candidate)
+
+
+ def __invalidate(self):
+- if self.__need_update:
++ if self.__idle_id != 0:
+ return
+- self.__need_update = True
+- gobject.idle_add(self.__update, priority = gobject.PRIORITY_LOW)
++ self.__idle_id = gobject.idle_add(self.__update,
++ priority = gobject.PRIORITY_LOW)
+
+ # def __get_preedit(self):
+ def __get_preedit(self, commit=False):
+@@ -699,11 +725,11 @@ class Engine(ibus.EngineBase):
+ self.__lookup_table_visible)
+
+ def __update(self):
+- self.__need_update = False
+ if self.__convert_mode == CONV_MODE_OFF:
+ self.__update_input_chars()
+ else:
+ self.__update_convert_chars()
++ self.__idle_id = 0
+
+ def __on_key_return(self):
+ if self.__preedit_ja_string.is_empty():
+@@ -956,7 +982,7 @@ class Engine(ibus.EngineBase):
+ self.__invalidate()
+ return True
+
+- def __on_key_common(self, keyval):
++ def __on_key_common(self, keyval, state=0):
+
+ if self.__input_mode == INPUT_MODE_LATIN:
+ # Input Latin chars
+@@ -981,6 +1007,13 @@ class Engine(ibus.EngineBase):
+ elif self.__convert_mode != CONV_MODE_OFF:
+ self.__commit_string(self.__convert_chars)
+
++ # "n" + "'" == "nn" in romaji
++ if (keyval >= ord('A') and keyval <= ord('Z')) or \
++ (keyval >= ord('a') and keyval <= ord('z')):
++ shift = (state & modifier.SHIFT_MASK) != 0
++ else:
++ shift = False
++ self.__preedit_ja_string.set_shift(shift)
+ self.__preedit_ja_string.insert(unichr(keyval))
+ self.__invalidate()
+ return True
+@@ -1024,6 +1057,9 @@ class Engine(ibus.EngineBase):
+ cls.__prefs.set_value(base_sec, name, value)
+ if name == 'shortcut_type':
+ cls.__keybind = cls._mk_keybind()
++ elif base_sec == 'thumb':
++ cls.__prefs.set_value(base_sec, name, value)
++ cls._reset_thumb()
+ elif base_sec:
+ cls.__prefs.set_value(base_sec, name, value)
+ else:
+@@ -1056,6 +1092,15 @@ class Engine(ibus.EngineBase):
+ 'alt+' in s and modifier.MOD1_MASK or 0)
+ return cls._mk_key(keyval, state)
+
++ @classmethod
++ def _reset_thumb(cls):
++ if cls.__thumb == None:
++ import thumb
++ cls.__thumb = thumb.ThumbShiftKeyboard(cls.__prefs)
++
++ else:
++ cls.__thumb.reset()
++
+ @staticmethod
+ def _mk_key(keyval, state):
+ if state & (modifier.CONTROL_MASK | modifier.MOD1_MASK):
+@@ -1067,12 +1112,12 @@ class Engine(ibus.EngineBase):
+ return repr([int(state), int(keyval)])
+
+ def process_key_event_thumb(self, keyval, keycode, state):
+- import gtk
+- import thumb
++ if self.__thumb == None:
++ self._reset_thumb()
+
+ def on_timeout(keyval):
+ if self._MM:
+- insert(thumb.table[self._MM][self._SS])
++ insert(self.__thumb.get_char(self._MM)[self._SS])
+ else:
+ cmd_exec([0, RS(), LS()][self._SS])
+ self._H = None
+@@ -1089,6 +1134,7 @@ class Engine(ibus.EngineBase):
+
+ def insert(keyval):
+ try:
++ self._MM = self._SS = 0
+ ret = self.__on_key_common(ord(keyval))
+ if (keyval in u',.、。' and
+ self.__prefs.get_value('common', 'behavior_on_period')):
+@@ -1109,16 +1155,16 @@ class Engine(ibus.EngineBase):
+ return False
+
+ def RS():
+- return self.__prefs.get_value('common', 'thumb_rs')
++ return self.__thumb.get_rs()
+
+ def LS():
+- return self.__prefs.get_value('common', 'thumb_ls')
++ return self.__thumb.get_ls()
+
+ def T1():
+- return self.__prefs.get_value('common', 'thumb_t1')
++ return self.__thumb.get_t1()
+
+ def T2():
+- return self.__prefs.get_value('common', 'thumb_t2')
++ return self.__thumb.get_t2()
+
+ state = state & (modifier.SHIFT_MASK |
+ modifier.CONTROL_MASK |
+@@ -1132,12 +1178,16 @@ class Engine(ibus.EngineBase):
+ if state & modifier.RELEASE_MASK:
+ if keyval == self._MM:
+ if stop():
+- insert(thumb.table[self._MM][self._SS])
++ insert(self.__thumb.get_char(self._MM)[self._SS])
+ self._MM = 0
+ elif (1 if keyval == RS() else 2) == self._SS:
+ if stop():
+ cmd_exec([0, RS(), LS()][self._SS])
+ self._SS = 0
++ if keyval in [RS(), LS()]:
++ self._RSS = 0
++ elif keyval == self._RMM:
++ self._RMM = 0
+ else:
+ if keyval in [LS(), RS()] and state == 0:
+ if self._SS:
+@@ -1147,35 +1197,50 @@ class Engine(ibus.EngineBase):
+ start(T1())
+ elif self._MM:
+ stop()
+- insert(thumb.table[self._MM][1 if keyval == RS() else 2])
++ self._RMM = self._MM
++ self._RSS = 1 if keyval == RS() else 2
++ insert(self.__thumb.get_char(self._MM)[1 if keyval == RS() else 2])
+ else:
+- self._SS = 1 if keyval == RS() else 2
+- start(T1())
+- elif keyval in thumb.table.keys() and state == 0:
++ if self._RSS == (1 if keyval == RS() else 2):
++ if self._RMM:
++ insert(self.__thumb.get_char(self._RMM)[self._RSS])
++ else:
++ self._SS = 1 if keyval == RS() else 2
++ start(T1())
++ elif keyval in self.__thumb.get_chars() and state == 0:
+ if self._MM:
+ stop()
+- insert(thumb.table[self._MM][self._SS])
++ insert(self.__thumb.get_char(self._MM)[self._SS])
+ start(T2())
+ self._MM = keyval
+ elif self._SS:
+ stop()
+- insert(thumb.table[keyval][self._SS])
++ self._RMM = keyval
++ self._RSS = self._SS
++ insert(self.__thumb.get_char(keyval)[self._SS])
+ else:
+- if cmd_exec(keyval, state):
+- return True
+- start(T2())
+- self._MM = keyval
++ if self._RMM == keyval:
++ if self._RSS:
++ insert(self.__thumb.get_char(self._RMM)[self._RSS])
++ else:
++ if cmd_exec(keyval, state):
++ return True
++ start(T2())
++ self._MM = keyval
+ else:
+ if self._MM:
+ stop()
+- insert(thumb.table[self._MM][self._SS])
++ insert(self.__thumb.get_char(self._MM)[self._SS])
+ elif self._SS:
+ stop()
+ cmd_exec([0, RS(), LS()][self._SS])
+ if cmd_exec(keyval, state):
+ return True
+ elif 0x21 <= keyval <= 0x7e and state & (modifier.CONTROL_MASK | modifier.MOD1_MASK) == 0:
+- insert(thumb.shift_table.get(keyval, unichr(keyval)))
++ if state & modifier.SHIFT_MASK:
++ insert(self.__thumb.get_shift_char(keyval, unichr(keyval)))
++ elif self._SS == 0:
++ insert(unichr(keyval))
+ else:
+ if not self.__preedit_ja_string.is_empty():
+ return True
+@@ -1220,7 +1285,7 @@ class Engine(ibus.EngineBase):
+ keyval = keysyms.asciitilde
+ elif keyval == keysyms.backslash and keycode in [132-8, 133-8]:
+ keyval = keysyms.yen
+- ret = self.__on_key_common(keyval)
++ ret = self.__on_key_common(keyval, state)
+ if (unichr(keyval) in u',.' and
+ self.__prefs.get_value('common', 'behavior_on_period')):
+ return self.__cmd_convert(keyval, state)
+diff --git a/engine/jastring.py b/engine/jastring.py
+index 306691e..7aa2ff2 100644
+--- a/engine/jastring.py
++++ b/engine/jastring.py
+@@ -55,11 +55,15 @@ class JaString:
+ def reset(self):
+ self.__cursor = 0
+ self.__segments = list()
++ self.__shift = False
+
+ def set_mode(self, mode):
+ self.__mode = mode
+ self.reset()
+
++ def set_shift(self, shift):
++ self.__shift = shift
++
+ def insert(self, c):
+ segment_before = None
+ segment_after = None
+@@ -70,14 +74,21 @@ class JaString:
+ if self.__cursor < len(self.__segments):
+ segment_after = self.__segments[self.__cursor]
+ if segment_before and not segment_before.is_finished():
+- new_segments = segment_before.append(c)
++ if type(segment_before) == romaji.RomajiSegment:
++ new_segments = segment_before.append(c, self.__shift)
++ else:
++ new_segments = segment_before.append(c)
+ elif segment_after and not segment_after.is_finished():
+- new_segments = segment_after.prepend(c)
++ if type(segment_after) == romaji.RomajiSegment:
++ new_segments = segment_after.prepend(c, self.__shift)
++ else:
++ new_segments = segment_after.prepend(c)
+ else:
+ if c != u"\0" and c != u"":
+ if self.__mode == TYPING_MODE_ROMAJI:
+- new_segments = [romaji.RomajiSegment(c)]
++ new_segments = [romaji.RomajiSegment(c, u"", self.__shift)]
+ elif self.__mode == TYPING_MODE_KANA:
++ # kana mode doesn't have shift latin in MS.
+ new_segments = [kana.KanaSegment(c)]
+ elif self.__mode == TYPING_MODE_THUMB_SHIFT:
+ new_segments = [thumb.ThumbShiftSegment(c)]
+@@ -126,7 +137,9 @@ class JaString:
+ ret = ''
+ for c in s:
+ c = c if not period else PeriodTable.get(c, c)
+- c = c if not symbol else SymbolTable[symbol].get(c, c)
++ # thumb_left + '2' and '/' are different
++ if self.__mode != TYPING_MODE_THUMB_SHIFT:
++ c = c if not symbol else SymbolTable[symbol].get(c, c)
+ c = c if not half_symbol else HalfSymbolTable.get(c, c)
+ c = c if not half_number else HalfNumberTable.get(c, c)
+ ret += c
+diff --git a/engine/romaji.py b/engine/romaji.py
+index 12c6656..3deb8f9 100644
+--- a/engine/romaji.py
++++ b/engine/romaji.py
+@@ -28,8 +28,8 @@ def romaji_correction_rule_get(k, d):
+ return (u'ん', k[1:2]) if k[0:1] == u'n' and not k[1:2] in u"aiueony'" else d
+
+ class RomajiSegment(segment.Segment):
+- def __init__(self, enchars=u"", jachars=u""):
+- if not jachars:
++ def __init__(self, enchars=u"", jachars=u"", shift=False):
++ if not jachars and not shift:
+ jachars = romaji_typing_rule.get(enchars, None)
+ if jachars == None:
+ jachars = symbol_rule.get(enchars, u"")
+@@ -38,13 +38,16 @@ class RomajiSegment(segment.Segment):
+ def is_finished(self):
+ return self._jachars != u""
+
+- def append(self, enchar):
++ def append(self, enchar, shift=False):
+ if self.is_finished():
+ if enchar == u"" and enchar == u"\0":
+ return []
+ return [RomajiSegment(enchar)]
+
+ text = self._enchars + enchar
++ if shift:
++ self._enchars = text
++ return []
+
+ jachars = romaji_typing_rule.get(text, None)
+ if jachars == None:
+@@ -98,7 +101,7 @@ class RomajiSegment(segment.Segment):
+ self._enchars = text
+ return []
+
+- def prepend(self, enchar):
++ def prepend(self, enchar, shift=False):
+ if enchar == u"" or enchar == u"\0":
+ return []
+
+@@ -106,6 +109,10 @@ class RomajiSegment(segment.Segment):
+ return [RomajiSegment(enchar)]
+
+ text = enchar + self._enchars
++ if shift:
++ self._enchars = text
++ return []
++
+ jachars = romaji_typing_rule.get(text, None)
+ if jachars == None:
+ jachars = symbol_rule.get(text, None)
+diff --git a/engine/tables.py b/engine/tables.py
+index 2ea67e0..a86a26a 100644
+--- a/engine/tables.py
++++ b/engine/tables.py
+@@ -38,12 +38,6 @@ romaji_typing_rule = {
+ u"lu" : u"ぅ",
+ u"le" : u"ぇ",
+ u"lo" : u"ぉ",
+-# u"xka" : u"ゕ",
+- u"xka" : u"ヵ",
+-# u"xke" : u"ゖ",
+- u"xke" : u"ヶ",
+- u"wi" : u"うぃ",
+- u"we" : u"うぇ",
+ u"wha" : u"うぁ",
+ u"whi" : u"うぃ",
+ u"whe" : u"うぇ",
+@@ -58,6 +52,12 @@ romaji_typing_rule = {
+ u"ku" : u"く",
+ u"ke" : u"け",
+ u"ko" : u"こ",
++ u"lka" : u"ヵ",
++ u"lke" : u"ヶ",
++# u"xka" : u"ゕ",
++ u"xka" : u"ヵ",
++# u"xke" : u"ゖ",
++ u"xke" : u"ヶ",
+ u"ga" : u"が",
+ u"gi" : u"ぎ",
+ u"gu" : u"ぐ",
+@@ -68,11 +68,13 @@ romaji_typing_rule = {
+ u"kyu" : u"きゅ",
+ u"kye" : u"きぇ",
+ u"kyo" : u"きょ",
++ u"kwa" : u"くぁ",
+ u"gya" : u"ぎゃ",
+ u"gyi" : u"ぎぃ",
+ u"gyu" : u"ぎゅ",
+ u"gye" : u"ぎぇ",
+ u"gyo" : u"ぎょ",
++ u"gwa" : u"ぐぁ",
+ u"sa" : u"さ",
+ u"si" : u"し",
+ u"su" : u"す",
+@@ -128,6 +130,11 @@ romaji_typing_rule = {
+ u"tyu" : u"ちゅ",
+ u"tye" : u"ちぇ",
+ u"tyo" : u"ちょ",
++ u"cya" : u"ちゃ",
++ u"cyi" : u"ちぃ",
++ u"cyu" : u"ちゅ",
++ u"cye" : u"ちぇ",
++ u"cyo" : u"ちょ",
+ u"cha" : u"ちゃ",
+ u"chi" : u"ち",
+ u"chu" : u"ちゅ",
+@@ -139,6 +146,7 @@ romaji_typing_rule = {
+ u"dye" : u"ぢぇ",
+ u"dyo" : u"ぢょ",
+ u"tsa" : u"つぁ",
++ u"tsi" : u"つぃ",
+ u"tse" : u"つぇ",
+ u"tso" : u"つぉ",
+ u"tha" : u"てゃ",
+@@ -146,11 +154,13 @@ romaji_typing_rule = {
+ u"thu" : u"てゅ",
+ u"the" : u"てぇ",
+ u"tho" : u"てょ",
++ u"twu" : u"とぅ",
+ u"dha" : u"でゃ",
+ u"dhi" : u"でぃ",
+ u"dhu" : u"でゅ",
+ u"dhe" : u"でぇ",
+ u"dho" : u"でょ",
++ u"dwu" : u"どぅ",
+ u"na" : u"な",
+ u"ni" : u"に",
+ u"nu" : u"ぬ",
+@@ -211,15 +221,21 @@ romaji_typing_rule = {
+ 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"yi" : u"い",
+ u"yu" : u"ゆ",
++ u"ye" : u"いぇ",
++ u"yo" : u"よ",
++ u"lya" : u"ゃ",
++ u"lyi" : u"ぃ",
++ u"lyu" : u"ゅ",
++ u"lye" : u"ぇ",
+ u"lyo" : u"ょ",
++ u"xya" : u"ゃ",
++ u"xyi" : u"ぃ",
++ u"xyu" : u"ゅ",
++ u"xye" : u"ぇ",
+ u"xyo" : u"ょ",
+- u"yo" : u"よ",
+ u"ra" : u"ら",
+ u"ri" : u"り",
+ u"ru" : u"る",
+@@ -230,9 +246,13 @@ romaji_typing_rule = {
+ u"ryu" : u"りゅ",
+ u"rye" : u"りぇ",
+ u"ryo" : u"りょ",
+- u"xwa" : u"ゎ",
+ u"wa" : u"わ",
++ u"wi" : u"うぃ",
++ u"wu" : u"う",
++ u"we" : u"うぇ",
+ u"wo" : u"を",
++ u"lwa" : u"ゎ",
++ u"xwa" : u"ゎ",
+ u"n'" : u"ん",
+ u"nn" : u"ん",
+ u"wyi" : u"ゐ",
+@@ -337,6 +357,11 @@ romaji_correction_rule = {
+ u"n." : (u"ん", u"."),
+ }
+
++# EUC-JP and SJIS do not have the chars
++romaji_utf8_rule = {
++ u"ヴ" : (u"ゔ"),
++}
++
+ # a port of 101kana.sty from scim-anthy
+ kana_typing_rule = {
+ # no modifiers keys
+diff --git a/engine/thumb.py b/engine/thumb.py
+index b678cda..8c4baff 100644
+--- a/engine/thumb.py
++++ b/engine/thumb.py
+@@ -21,12 +21,20 @@
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+-import gtk
+-import gobject
+-import time
++__all__ = (
++ "ThumbShiftKeyboard",
++ "ThumbShiftSegment",
++ )
+
++from ibus import keysyms
++from ibus import modifier
+ import segment
+
++try:
++ from gtk.gdk import get_default_root_window
++except ImportError:
++ get_default_root_window = lambda : None
++
+
+ _table = {
+ 'q': [u'。', u'', u'ぁ'],
+@@ -76,6 +84,88 @@ _table = {
+ '7': [u'7', u']', u''],
+ '8': [u'8', u'(', u''],
+ '9': [u'9', u')', u''],
++ '\\': [u'¥', u'', u''],
++}
++
++_nicola_j_table = {
++ ':': [u':', u'', u''],
++ '@': [u'、', u'', u''],
++ '[': [u'゛', u'゜', u''],
++ ']': [u'」', u'', u''],
++ '8': [u'8', u'(', u''],
++ '9': [u'9', u')', u''],
++ '0': [u'0', u'', u''],
++}
++
++_nicola_a_table = {
++ ':': [u':', u'', u''],
++ '@': [u'@', u'', u''],
++ '[': [u'、', u'', u''],
++ ']': [u'゛', u'゜', u''],
++ '8': [u'8', u'', u''],
++ '9': [u'9', u'(', u''],
++ '0': [u'0', u')', u''],
++}
++
++_nicola_f_table = {
++ ':': [u'、', u'', u''],
++ '@': [u'@', u'', u''],
++ '[': [u'゛', u'゜', u''],
++ ']': [u'」', u'', u''],
++ '8': [u'8', u'(', u''],
++ '9': [u'9', u')', u''],
++ '0': [u'0', u'', u''],
++}
++
++_kb231_j_fmv_table = {
++ '3': [u'3', u'', u'~'],
++ '0': [u'0', u'『', u''],
++ '-': [u'-', u'』', u''],
++ '=': [u'=', u'', u''],
++}
++
++_kb231_a_fmv_table = {
++ '3': [u'3', u'', u'~'],
++ '0': [u'0', u')', u''],
++ '-': [u'-', u'『', u''],
++ '=': [u'=', u'』', u''],
++}
++
++_kb231_f_fmv_table = {
++ '3': [u'3', u'', u'~'],
++ '0': [u'0', u'『', u''],
++ '-': [u'-', u'』', u''],
++ '=': [u'=', u'', u''],
++}
++
++_kb611_j_fmv_table = {
++ '`': [u'‘', u'', u''],
++ '^': [u'々', u'£', u''],
++ ':': [u':', u'', u''],
++ '@': [u'、', u'¢', u''],
++ '[': [u'゛', u'゜', u''],
++ # keysyms are same and keycodes depend on the platforms.
++ #'¥': [u'¥', u'¬', u''],
++ '\\': [u'¥', u'¦', u''],
++}
++
++_kb611_a_fmv_table = {
++ '`': [u'々', u'', u'£'],
++ ':': [u':', u'', u''],
++ '@': [u'@', u'', u''],
++ '[': [u'、', u'¢', u''],
++ #'¥': [u'¥', u'¬', u''],
++ '\\': [u'¥', u'¦', u''],
++}
++
++_kb611_f_fmv_table = {
++ '`': [u'‘', u'', u''],
++ '^': [u'々', u'£', u''],
++ ':': [u'、', u'¢', u''],
++ '@': [u'@', u'', u''],
++ '[': [u'゛', u'゜', u''],
++ #'¥': [u'¥', u'¬', u''],
++ '\\': [u'¥', u'¦', u''],
+ }
+
+ _shift_table = {
+@@ -87,7 +177,6 @@ _shift_table = {
+ }
+
+ table = {}
+-shift_table = {}
+ r_table = {}
+
+ for k in _table.keys():
+@@ -95,10 +184,6 @@ for k in _table.keys():
+ for c in _table[k]:
+ r_table[c] = k
+
+-for k in _shift_table.keys():
+- shift_table[ord(k)] = _shift_table[k]
+- r_table[_shift_table[k]] = k
+-
+ kana_voiced_consonant_rule = {
+ u"か゛" : u"が",
+ u"き゛" : u"ぎ",
+@@ -129,6 +214,208 @@ kana_voiced_consonant_rule = {
+
+ _UNFINISHED_HIRAGANA = set(u"かきくけこさしすせそたちつてとはひふへほ")
+
++class ThumbShiftKeyboard:
++ def __init__(self, prefs=None):
++ self.__prefs = prefs
++ self.__table = table
++ self.__r_table = r_table
++ self.__shift_table = {}
++ self.__ls = 0
++ self.__rs = 0
++ self.__t1 = 0
++ self.__t2 = 0
++ self.__layout = 0
++ self.__fmv_extension = 2
++ self.__handakuten = False
++ if self.__prefs != None:
++ self.reset()
++ self.__reset_shift_table(False)
++
++ def __init_layout_table(self):
++ if self.__table != {}:
++ self.__table.clear()
++ if self.__r_table != {}:
++ self.__r_table.clear()
++ for k in _table.keys():
++ self.__table[ord(k)] = _table[k]
++ for c in _table[k]:
++ self.__r_table[c] = k
++
++ def __reset_layout_table(self, init, j_table, a_table, f_table):
++ if init:
++ self.__init_layout_table()
++ sub_table = None
++ if self.__layout == 0:
++ sub_table = j_table
++ elif self.__layout == 1:
++ sub_table = a_table
++ elif self.__layout == 2:
++ sub_table = f_table
++ if sub_table == None:
++ return
++ for k in sub_table.keys():
++ self.__table[ord(unicode(k))] = sub_table[k]
++ for c in sub_table[k]:
++ self.__r_table[c] = k
++
++ def __reset_extension_table(self, init):
++ self.__reset_layout_table(init,
++ _nicola_j_table,
++ _nicola_a_table,
++ _nicola_f_table)
++ if self.__fmv_extension == 0:
++ return
++ if self.__fmv_extension >= 1:
++ self.__reset_layout_table(False,
++ _kb231_j_fmv_table,
++ _kb231_a_fmv_table,
++ _kb231_f_fmv_table)
++ if self.__fmv_extension >= 2:
++ self.__reset_layout_table(False,
++ _kb611_j_fmv_table,
++ _kb611_a_fmv_table,
++ _kb611_f_fmv_table)
++
++ def __reset_shift_table(self, init):
++ self.__reset_extension_table(init)
++ if self.__handakuten:
++ for k in _shift_table.keys():
++ self.__shift_table[ord(k)] = _shift_table[k]
++ self.__r_table[_shift_table[k]] = k
++ elif self.__shift_table != {}:
++ for k in _shift_table.keys():
++ if ord(k) in self.__shift_table:
++ del self.__shift_table[ord(k)]
++ if _shift_table[k] in self.__r_table:
++ del self.__r_table[_shift_table[k]]
++
++ def __s_to_key_raw(self, s):
++ keyval = keysyms.name_to_keycode(s.split('+')[-1])
++ s = s.lower()
++ state = ('shift+' in s and modifier.SHIFT_MASK or 0) | (
++ 'ctrl+' in s and modifier.CONTROL_MASK or 0) | (
++ 'alt+' in s and modifier.MOD1_MASK or 0)
++ return (keyval, state)
++
++ def __get_xkb_layout(self):
++ root_window = get_default_root_window()
++ if not root_window:
++ return 0
++ prop = root_window.property_get("_XKB_RULES_NAMES")[2]
++ list = prop.split('\0')
++ layout = 0
++ for data in list:
++ if data == "jp":
++ layout = 0
++ elif data == "us":
++ layout = 1
++ elif data.find("japan:nicola_f_bs") >= 0:
++ layout = 2
++ elif data.find("japan:") >= 0:
++ layout = 0
++ return layout
++
++ def reset(self):
++ s = self.__prefs.get_value('thumb', 'ls')
++ ls, state = self.__s_to_key_raw(s)
++ if ls == 0xffffff:
++ ls = keysyms.Muhenkan
++ self.set_ls(ls)
++
++ s = self.__prefs.get_value('thumb', 'rs')
++ rs, state = self.__s_to_key_raw(s)
++ if rs == 0xffffff:
++ rs = keysyms.Henkan
++ self.set_rs(rs)
++
++ t1 = self.__prefs.get_value('thumb', 't1')
++ t2 = self.__prefs.get_value('thumb', 't2')
++ self.set_t1(t1)
++ self.set_t2(t2)
++
++ mode = self.__prefs.get_value('thumb', 'keyboard_layout_mode')
++ layout = 0
++ if mode == 1:
++ layout = self.__get_xkb_layout()
++ else:
++ layout = self.__prefs.get_value('thumb', 'keyboard_layout')
++ self.set_layout(layout)
++
++ fmv_extension = self.__prefs.get_value('thumb', 'fmv_extension')
++ self.set_fmv_extension(fmv_extension)
++ handakuten = self.__prefs.get_value('thumb', 'handakuten')
++ self.set_handakuten(handakuten)
++
++ def get_ls(self):
++ return self.__ls
++
++ def set_ls(self, ls):
++ self.__ls = ls
++
++ def get_rs(self):
++ return self.__rs
++
++ def set_rs(self, rs):
++ self.__rs = rs
++
++ def get_t1(self):
++ return self.__t1
++
++ def set_t1(self, t1):
++ self.__t1 = t1
++
++ def get_t2(self):
++ return self.__t2
++
++ def set_t2(self, t2):
++ self.__t2 = t2
++
++ def get_layout(self):
++ return self.__layout
++
++ def set_layout(self, layout):
++ if self.__layout == layout:
++ return
++ self.__layout = layout
++ self.__reset_shift_table(True)
++
++ def get_fmv_extension (self):
++ return self.__fmv_extension
++
++ def set_fmv_extension (self, fmv_extension):
++ if self.__fmv_extension == fmv_extension:
++ return
++ self.__fmv_extension = fmv_extension
++ self.__reset_shift_table(True)
++
++ def get_handakuten(self):
++ return self.__handakuten
++
++ def set_handakuten(self, handakuten):
++ if self.__handakuten == handakuten:
++ return
++ self.__handakuten = handakuten
++ self.__reset_shift_table(True)
++
++ def get_char(self, key, fallback=None):
++ return self.__table.get(key, fallback)
++
++ def get_chars(self):
++ return self.__table.keys()
++
++ def get_r_char(self, key, fallback=None):
++ return self.__r_table.get(key, fallback)
++
++ def get_r_chars(self):
++ return self.__r_table.keys()
++
++ def get_shift_char(self, key, fallback=None):
++ return self.__shift_table.get(key, fallback)
++
++ def get_shift_chars(self):
++ return self.__shift_table.keys()
++
++
+ class ThumbShiftSegment(segment.Segment):
+
+ def __init__(self, enchars=u"", jachars=u""):
+diff --git a/ibus-anthy.spec.in b/ibus-anthy.spec.in
+index ada402b..23e25fb 100644
+--- a/ibus-anthy.spec.in
++++ b/ibus-anthy.spec.in
+@@ -20,6 +20,7 @@ BuildRequires: swig
+ BuildRequires: pkgconfig
+ BuildRequires: intltool
+
++Requires: pygtk2 >= 2.15.2
+ Requires: ibus >= 1.2.0.20100111
+ Requires: anthy
+ %if %enable_kasumi
+diff --git a/setup/anthyprefs.py b/setup/anthyprefs.py
+index 9af9ba4..5444bab 100644
+--- a/setup/anthyprefs.py
++++ b/setup/anthyprefs.py
+@@ -170,11 +170,17 @@ _config = {
+
+ 'dict_admin_command': ['/usr/bin/kasumi', 'kasumi'],
+ 'add_word_command': ['/usr/bin/kasumi', 'kasumi', '-a'],
+-
+- 'thumb_rs': gtk.keysyms.Henkan,
+- 'thumb_ls': gtk.keysyms.Muhenkan,
+- 'thumb_t1': 100,
+- 'thumb_t2': 75,
++ },
++
++ 'thumb': {
++ 'keyboard_layout_mode': True,
++ 'keyboard_layout': 0,
++ 'fmv_extension': 2,
++ 'handakuten': False,
++ 'rs': 'Henkan',
++ 'ls': 'Muhenkan',
++ 't1': 100,
++ 't2': 75,
+ }
+ }
+
+diff --git a/setup/main.py b/setup/main.py
+index 1da35f7..5921d24 100644
+--- a/setup/main.py
++++ b/setup/main.py
+@@ -24,7 +24,7 @@ from os import path, getenv
+ import gtk
+ import pango
+ from gtk import glade
+-from ibus import keysyms, modifier
++from ibus import keysyms, modifier, Bus
+ from gettext import dgettext, bindtextdomain
+
+ from anthyprefs import AnthyPrefs
+@@ -41,7 +41,10 @@ def s_to_l(s):
+
+ class AnthySetup(object):
+ def __init__(self):
+- self.prefs = prefs = AnthyPrefs()
++ self.__config = Bus().get_config()
++ self.__thumb_kb_layout_mode = None
++ self.__thumb_kb_layout = None
++ self.prefs = prefs = AnthyPrefs(None, self.__config)
+
+ localedir = getenv("IBUS_LOCALEDIR")
+ bindtextdomain("ibus-anthy", localedir)
+@@ -63,8 +66,11 @@ class AnthySetup(object):
+ for name in ['input_mode', 'typing_method',
+ 'period_style', 'symbol_style', 'ten_key_mode',
+ 'behavior_on_focus_out', 'behavior_on_period',
+- 'half_width_symbol', 'half_width_number', 'half_width_space']:
+- xml.get_widget(name).set_active(prefs.get_value('common', name))
++ 'half_width_symbol', 'half_width_number', 'half_width_space',
++ 'thumb:keyboard_layout_mode', 'thumb:keyboard_layout',
++ 'thumb:fmv_extension', 'thumb:handakuten']:
++ section, key = self.__get_section_key(name)
++ xml.get_widget(name).set_active(prefs.get_value(section, key))
+
+ l = ['default', 'atok', 'wnn']
+ s_type = prefs.get_value('common', 'shortcut_type')
+@@ -89,6 +95,14 @@ class AnthySetup(object):
+ ls.append([k, l_to_s(self.prefs.get_value(sec, k))])
+ tv.set_model(ls)
+
++ self.__thumb_kb_layout_mode = xml.get_widget('thumb:keyboard_layout_mode')
++ self.__thumb_kb_layout = xml.get_widget('thumb:keyboard_layout')
++ self.__set_thumb_kb_label()
++
++ for name in ['thumb:ls', 'thumb:rs']:
++ section, key = self.__get_section_key(name)
++ xml.get_widget(name).set_text(prefs.get_value(section, key))
++
+ tv = xml.get_widget('treeview2')
+ tv.append_column(gtk.TreeViewColumn('', gtk.CellRendererText(), text=0))
+ tv.get_selection().connect_after('changed',
+@@ -97,6 +111,32 @@ class AnthySetup(object):
+
+ xml.signal_autoconnect(self)
+
++ def __get_section_key(self, name):
++ i = name.find(':')
++ if i > 0:
++ section = name[:i]
++ key = name[i + 1:]
++ else:
++ section = 'common'
++ key = name
++ return (section, key)
++
++ def __set_thumb_kb_label(self):
++ if self.__thumb_kb_layout_mode == None or \
++ self.__thumb_kb_layout == None:
++ return
++ section, key = self.__get_section_key(self.__thumb_kb_layout_mode.name)
++ layout_mode = self.prefs.get_value(section, key)
++ if layout_mode:
++ self.__thumb_kb_layout.set_sensitive(False)
++ else:
++ self.__thumb_kb_layout.set_sensitive(True)
++ if layout_mode and \
++ not self.__config.get_value('general', 'use_system_keyboard_layout', True):
++ self.xml.get_widget('thumb:warning_hbox').show()
++ else:
++ self.xml.get_widget('thumb:warning_hbox').hide()
++
+ def on_selection_changed(self, widget, id):
+ set_sensitive = lambda a, b: self.xml.get_widget(a).set_sensitive(b)
+ flg = True if widget.get_selected()[1] else False
+@@ -139,16 +179,22 @@ class AnthySetup(object):
+ widget.set_sensitive(False)
+
+ def on_cb_changed(self, widget):
+- self.prefs.set_value('common', widget.name, widget.get_active())
++ section, key = self.__get_section_key(widget.name)
++ self.prefs.set_value(section, key, widget.get_active())
+ self.xml.get_widget('btn_apply').set_sensitive(True)
+
+ def on_sb_changed(self, widget):
+- self.prefs.set_value('common', widget.name, widget.get_value_as_int())
++ section, key = self.__get_section_key(widget.name)
++ self.prefs.set_value(section, key, widget.get_value_as_int())
+ self.xml.get_widget('btn_apply').set_sensitive(True)
+
+ def on_ck_toggled(self, widget):
+- self.prefs.set_value('common', widget.name, widget.get_active())
++ section, key = self.__get_section_key(widget.name)
++ self.prefs.set_value(section, key, widget.get_active())
+ self.xml.get_widget('btn_apply').set_sensitive(True)
++ if self.__thumb_kb_layout_mode and \
++ widget.name == self.__thumb_kb_layout_mode.name:
++ self.__set_thumb_kb_label()
+
+ def on_btn_edit_clicked(self, widget):
+ ls, it = self.xml.get_widget('shortcut').get_selection().get_selected()
+@@ -179,6 +225,41 @@ class AnthySetup(object):
+ ls.set(it, 1, new)
+ self.xml.get_widget('btn_apply').set_sensitive(True)
+
++ def on_btn_thumb_key_clicked(self, widget):
++ if widget.name == 'thumb:button_ls':
++ entry = 'thumb:ls'
++ elif widget.name == 'thumb:button_rs':
++ entry = 'thumb:rs'
++ else:
++ return
++ text = self.xml.get_widget(entry).get_text()
++ m = self.xml.get_widget('treeview2').get_model()
++ m.clear()
++ if text != None:
++ m.append([text])
++ i = m.get_iter_first()
++ self.xml.get_widget('treeview2').get_selection().select_iter(i)
++ self.xml.get_widget('entry2').set_text('')
++ self.xml.get_widget('button4').hide()
++ self.xml.get_widget('button5').show()
++ self.xml.get_widget('button6').hide()
++ for w in ['checkbutton6', 'checkbutton7', 'checkbutton8']:
++ self.xml.get_widget(w).set_active(False)
++ dlg = self.xml.get_widget('edit_shortcut')
++ id = dlg.run()
++ dlg.hide()
++ self.xml.get_widget('button4').show()
++ self.xml.get_widget('button5').hide()
++ self.xml.get_widget('button6').show()
++ if id == gtk.RESPONSE_OK:
++ l, i = self.xml.get_widget('treeview2').get_selection().get_selected()
++ new = l[i][0]
++ if new != text:
++ section, key = self.__get_section_key(entry)
++ self.prefs.set_value(section, key, new)
++ self.xml.get_widget(entry).set_text(new)
++ self.xml.get_widget('btn_apply').set_sensitive(True)
++
+ def _get_shortcut_sec(self):
+ l = ['default', 'atok', 'wnn']
+ s_type = self.xml.get_widget('shortcut_type').get_active_text().lower()
+@@ -195,7 +276,8 @@ class AnthySetup(object):
+ for k in self.prefs.keys(sec):
+ ls.append([k, l_to_s(self.prefs.get_value(sec, k))])
+
+- self.prefs.set_value('common', widget.name, sec[len('shortcut/'):])
++ section, key = self.__get_section_key(widget.name)
++ self.prefs.set_value(section, key, sec[len('shortcut/'):])
+ self.xml.get_widget('btn_apply').set_sensitive(True)
+
+ def on_shortcut_key_release_event(self, widget, event):
+@@ -262,6 +344,24 @@ class AnthySetup(object):
+ return True
+ l.append([s])
+
++ def on_button5_clicked(self, widget):
++ s = self.xml.get_widget('entry2').get_text()
++ if not s or not keysyms.name_to_keycode(s):
++ dlg = self.xml.get_widget('invalid_keysym')
++ dlg.set_markup('%s' % _('Invalid keysym'))
++ dlg.format_secondary_text(_('This keysym is not valid'))
++ dlg.run()
++ dlg.hide()
++ return True
++ for w, m in [('checkbutton6', 'Ctrl+'),
++ ('checkbutton7', 'Alt+'),
++ ('checkbutton8', 'Shift+')]:
++ if self.xml.get_widget(w).get_active():
++ s = m + s
++ l, i = self.xml.get_widget('treeview2').get_selection().get_selected()
++ l[i][0] = s
++ return True
++
+ def on_button6_clicked(self, widget):
+ l, i = self.xml.get_widget('treeview2').get_selection().get_selected()
+ if i:
+diff --git a/setup/setup.glade b/setup/setup.glade
+index f068938..39fc754 100644
+--- a/setup/setup.glade
++++ b/setup/setup.glade
+@@ -460,7 +460,7 @@ Hold
+ True
+ 8
+
+-
++
+ True
+ _Shortcut Type:
+ True
+@@ -612,6 +612,373 @@ Wnn
+
+
+
++
++ True
++ 8
++ 4
++
++
++ True
++ 0
++ none
++
++
++ True
++ 8
++ 8
++ 12
++
++
++ True
++ 8
++ 8
++ 4
++
++
++ True
++ 2
++ 3
++ 8
++ 4
++
++
++ True
++ 0
++ True
++ Thumb Shift _Left Key:
++ thumb:ls
++
++
++
++
++
++
++ True
++ True
++ False
++
++
++ 1
++ 2
++
++
++
++
++ ...
++ True
++ True
++ False
++
++
++
++ 2
++ 3
++
++
++
++
++ True
++ 0
++ True
++ _Thumb Shift Right Key:
++ thumb:rs
++
++
++ 1
++ 2
++
++
++
++
++ True
++ True
++ False
++
++
++ 1
++ 2
++ 1
++ 2
++
++
++
++
++ ...
++ True
++ True
++ False
++
++
++
++ 2
++ 3
++ 1
++ 2
++
++
++
++
++
++
++
++
++
++ Adjust _input method layout to system keyboard layout
++ Adjust IM layout to XKB layout
++ True
++ True
++ False
++ True
++ True
++
++
++
++
++ 1
++ 2
++
++
++
++
++
++ True
++ 8
++
++
++ True
++ 0
++ True
++ Input _Method Layout:
++ thumb:keyboard_layout
++
++
++ False
++ False
++ 0
++
++
++
++
++ True
++ NICOLA-J
++NICOLA-A
++NICOLA-F
++
++
++
++ 1
++
++
++
++
++ 2
++ 3
++
++
++
++
++
++ True
++ 8
++
++
++ True
++ gtk-dialog-info
++
++
++ False
++ False
++ 0
++
++
++
++
++ True
++ 0
++ True
++ Restart ibus when you change the keyboard layout.
++ Restart ibus when you change XKB
++
++
++ False
++ False
++ 1
++
++
++
++
++ 3
++ 4
++
++
++
++
++
++ False
++ 8
++
++
++ True
++ gtk-dialog-warning
++
++
++ False
++ False
++ 0
++
++
++
++
++ True
++ 0
++ True
++ Strongly recommend to enable "Use system keyboard layout" check button in "Advanced" tab using 'ibus-setup' command
++
++
++ False
++ False
++ 1
++
++
++
++
++ 4
++ 5
++
++
++
++
++
++ True
++ 8
++
++
++ True
++ 0
++ True
++ _Additional Key Arrangement:
++ thumb:fmv_extension
++
++
++ False
++ False
++ 0
++
++
++
++
++ True
++ None
++FMV KB231 key extension
++FMV KB611 key extension
++ '~', 『', '¢', '£' and so on can be output with Thumb Shift key
++
++
++
++ 1
++
++
++
++
++ 5
++ 6
++
++
++
++
++
++ True
++ 8
++
++
++ True
++ gtk-dialog-info
++
++
++ False
++ False
++ 0
++
++
++
++
++ True
++ 0
++ True
++ You do not have to reconfigure the system keyboard layout for "Additional Key Arrangement" since this option changes input method layout only in case input method is turned on.
++ You do not have to reconfigure XKB since this option changes IM layout only with IM on.
++
++
++ False
++ False
++ 1
++
++
++
++
++ 6
++ 7
++
++
++
++
++
++ _Enable semi-voiced sound mark with Shift key
++ Seion + Shift can output Handakuon
++ True
++ True
++ False
++ True
++ True
++
++
++
++
++ 7
++ 8
++
++
++
++
++
++
++
++
++
++ True
++ <b>Thumb Shift Layout</b>
++ True
++
++
++ label_item
++
++
++
++
++ False
++ False
++ 0
++
++
++
++
++ 2
++
++
++
++
++ True
++ Thumb S_hift
++ True
++ vbox3
++
++
++ 2
++ False
++ tab
++
++
++
+
+ True
+ <span size='xx-large'><b>IBus-Anthy</b></span>
+@@ -626,18 +993,18 @@ URL : http://code.google.com/p/ibus/
+ start
+
+
+- 2
++ 3
+
+
+
+-
++
+ True
+ Abo_ut
+ True
+ about
+
+
+- 2
++ 3
+ False
+ tab
+
+@@ -752,7 +1119,7 @@ URL : http://code.google.com/p/ibus/
+ True
+ 8
+
+-
++
+ True
+ Key Code:
+
+@@ -799,7 +1166,7 @@ URL : http://code.google.com/p/ibus/
+ True
+ 8
+
+-
++
+ True
+ Modifier:
+
diff --git a/ibus-anthy.spec b/ibus-anthy.spec
index 21bd56d..2745108 100644
--- a/ibus-anthy.spec
+++ b/ibus-anthy.spec
@@ -1,15 +1,16 @@
%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
%define require_ibus_version 1.2.0.20100111
+%define require_pygtk2_version 2.15.2
Name: ibus-anthy
Version: 1.2.0.20100115
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: The Anthy 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: ibus-anthy.png
-# Patch0: ibus-anthy-HEAD.patch
+Patch0: ibus-anthy-HEAD.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -23,6 +24,7 @@ BuildRequires: intltool
Requires: ibus >= %{require_ibus_version}
Requires: anthy
+Requires: pygtk2 >= %{require_pygtk2_version}
Requires: kasumi
%description
@@ -32,7 +34,7 @@ libanthy.
%prep
%setup -q
cp %SOURCE1 icons
-# %patch0 -p1
+%patch0 -p1
%build
%configure --disable-static
@@ -60,6 +62,13 @@ rm -rf $RPM_BUILD_ROOT
%{_datadir}/ibus/component/*
%changelog
+* Fri Mar 05 2010 Takao Fujiwara - 1.2.0.20100115-2
+- Fix bug 564268 - Crash with enabled global input method
+- Fix bug 570680 - Support NICOLA-F and NICOLA-A
+- Fix romaji_typing_rule. #777
+- Fix Shift + char with CapsLock ON in romaji mode.
+- Fix chattering bug.
+
* Fri Jan 15 2010 Takao Fujiwara - 1.2.0.20100115-1
- Update to 1.2.0.20100115
- Fix bug 550001 - kasumi should be accessible from ibus-anthy