From 591064e7c4112025a632a30f20525308935d7a50 Mon Sep 17 00:00:00 2001 From: Takao Fujiwara Date: Fri, 5 Mar 2010 02:24:14 +0000 Subject: [PATCH] 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. --- ibus-anthy-HEAD.patch | 1556 ++++++++++++++++++++++++++++++++++++++++- ibus-anthy.spec | 15 +- 2 files changed, 1567 insertions(+), 4 deletions(-) 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