1# vim:set et sts=4 sw=4: 2# -*- coding: utf-8 -*- 3# 4# ibus-anthy - The Anthy engine for IBus 5# 6# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com> 7# Copyright (c) 2010-2017 Takao Fujiwara <takao.fujiwara1@gmail.com> 8# Copyright (c) 2007-2017 Red Hat, Inc. 9# 10# This program is free software; you can redistribute it and/or modify 11# it under the terms of the GNU General Public License as published by 12# the Free Software Foundation; either version 2 of the License, or 13# (at your option) any later version. 14# 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License along 21# with this program; if not, write to the Free Software Foundation, Inc., 22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 24import sys 25 26from tables import * 27import segment 28 29def romaji_correction_rule_get(k, d): 30 return ('ん', k[1:2]) if k[0:1] == 'n' and not k[1:2] in "aiueony'" else d 31 32class RomajiSegment(segment.Segment): 33 _prefs = None 34 _romaji_typing_rule_method = None 35 _latin_with_shift = True 36 _shift_mode = False 37 38 def __init__(self, enchars='', jachars='', shift=False, unshift=False): 39 if self._latin_with_shift: 40 # If Shift key is pressed, Latin mode. 41 # If Hiragana_Katakana key is pressed, Hiragana mode. 42 if shift: 43 self._shift_mode = True 44 if unshift: 45 self._shift_mode = False 46 47 enchars_orig = enchars 48 # Even if the chars are capital with CapsLock, Hiragana 49 # should be converted. E.g. 'SA' 50 enchars = enchars.lower() 51 52 if not jachars and not shift: 53 jachars = self.__get_romaji_typing_rule(enchars, None) 54 if jachars == None: 55 jachars = symbol_rule.get(enchars, '') 56 super(RomajiSegment, self).__init__(enchars_orig, jachars) 57 58 @classmethod 59 def INIT_ROMAJI_TYPING_RULE(cls, prefs): 60 cls._prefs = prefs 61 if prefs == None: 62 cls._romaji_typing_rule_method = None 63 return 64 method = prefs.get_value('romaji-typing-rule', 'method') 65 if method == None: 66 method = 'default' 67 cls._romaji_typing_rule_method = method 68 keymap = prefs.get_value('romaji-typing-rule', 'list') 69 if cls._romaji_typing_rule_method not in keymap.keys(): 70 cls._romaji_typing_rule_method = None 71 72 @classmethod 73 def SET_LATIN_WITH_SHIFT(cls, latin_with_shift): 74 # Do not use IBus.Config in every conversion for the performance. 75 cls._latin_with_shift = latin_with_shift 76 77 def __get_romaji_typing_rule(self, enchars, retval=None): 78 prefs = self._prefs 79 value = None 80 method = self._romaji_typing_rule_method 81 if method != None: 82 # Need to send Unicode to typing_to_config_key instead of UTF-8 83 # not to separate U+A5 84 gkey = prefs.typing_to_config_key(enchars) 85 if gkey == '': 86 return None 87 keymap = prefs.get_value('romaji-typing-rule', 'list')[method] 88 value = keymap.get(gkey) 89 if value == '': 90 value = None 91 if value == None: 92 value = retval 93 else: 94 value = romaji_typing_rule_static.get(enchars, retval) 95 return value 96 97 def is_finished(self): 98 return self._jachars != '' 99 100 def append(self, enchar, shift=False, unshift=False): 101 if self.is_finished(): 102 if enchar == '' and enchar == '\0': 103 return [] 104 return [RomajiSegment(enchar)] 105 106 text_orig = self._enchars + enchar 107 text = text_orig.lower() 108 109 if self._latin_with_shift: 110 # If Shift key is pressed, Latin mode. 111 # If Hiragana_Katakana key is pressed, Hiragana mode. 112 if shift: 113 self._shift_mode = True 114 if unshift: 115 self._shift_mode = False 116 if self._shift_mode: 117 self._enchars = text_orig 118 return [] 119 120 if shift: 121 self._enchars = text_orig 122 return [] 123 124 jachars = self.__get_romaji_typing_rule(text, None) 125 if jachars == None: 126 jachars = symbol_rule.get(text, None) 127 if jachars: 128 self._enchars = text_orig 129 self._jachars = jachars 130 return [] 131 132 jachars, c = romaji_double_consonat_typing_rule.get(text, (None, None)) 133 if jachars: 134 self._enchars = text_orig[0] 135 self._jachars = jachars 136 return [RomajiSegment(c)] 137 138# jachars, c = romaji_correction_rule.get(text, (None, None)) 139 jachars, c = romaji_correction_rule_get(text, (None, None)) 140 if jachars: 141 self._enchars = text_orig[0] 142 self._jachars = jachars 143 return [RomajiSegment(c)] 144 145 for i in range(-min(4, len(text)), 0): 146 enchars = text[i:] 147 148 jachars = self.__get_romaji_typing_rule(enchars, None) 149 if jachars == None: 150 jachars = symbol_rule.get(enchars, None) 151 if jachars: 152 jasegment = RomajiSegment(enchars, jachars) 153 self._enchars = text_orig[:i] 154 return [jasegment] 155 156 jachars, c = romaji_double_consonat_typing_rule.get(enchars, (None, None)) 157 if jachars: 158 jasegment = RomajiSegment(enchars[:-len(c)], jachars) 159 self._enchars = text_orig[:i] 160 if c: 161 return [jasegment, RomajiSegment(c)] 162 return [jasegment] 163 164# jachars, c = romaji_correction_rule.get(enchars, (None, None)) 165 jachars, c = romaji_correction_rule_get(enchars, (None, None)) 166 if jachars: 167 jasegment = RomajiSegment(enchars[:-len(c)], jachars) 168 self._enchars = text_orig[:i] 169 if c: 170 return [jasegment, RomajiSegment(c)] 171 return [jasegment] 172 173 self._enchars = text_orig 174 return [] 175 176 def prepend(self, enchar, shift=False, unshift=False): 177 if enchar == '' or enchar == '\0': 178 return [] 179 180 if self.is_finished(): 181 return [RomajiSegment(enchar)] 182 183 text_orig = enchar + self._enchars 184 text = text_orig.lower() 185 186 if self._latin_with_shift: 187 if shift: 188 self._shift_mode = True 189 if unshift: 190 self._shift_mode = False 191 if self._shift_mode: 192 self._enchars = text_orig 193 return [] 194 195 if shift: 196 self._enchars = text_orig 197 return [] 198 199 jachars = self.__get_romaji_typing_rule(text, None) 200 if jachars == None: 201 jachars = symbol_rule.get(text, None) 202 if jachars: 203 self._enchars = text_orig 204 self._jachars = jachars 205 return [] 206 207 jachars, c = romaji_double_consonat_typing_rule.get(text, (None, None)) 208 if jachars: 209 self._enchars = c 210 return [RomajiSegment(text_orig[0], jachars)] 211 212# jachars, c = romaji_correction_rule.get(text, (None, None)) 213 jachars, c = romaji_correction_rule_get(text, (None, None)) 214 if jachars: 215 self._enchars = c 216 return [RomajiSegment(text_orig[0], jachars)] 217 218 for i in range(min(4, len(text)), 0, -1): 219 enchars = text[:i] 220 221 jachars = self.__get_romaji_typing_rule(enchars, None) 222 if jachars == None: 223 jachars = symbol_rule.get(enchars, None) 224 if jachars: 225 jasegment = RomajiSegment(enchars, jachars) 226 self._enchars = text_orig[i:] 227 return [jasegment] 228 229 jachars, c = romaji_double_consonat_typing_rule.get(enchars, (None, None)) 230 if jachars: 231 self._enchars = c + text_orig[i:] 232 return [RomajiSegment(enchars[:-len(c)], jachars)] 233 234# jachars, c = romaji_correction_rule.get(enchars, (None, None)) 235 jachars, c = romaji_correction_rule_get(enchars, (None, None)) 236 if jachars: 237 self._enchars = c + text_orig[i:] 238 return [RomajiSegment(enchars[:-len(c)], jachars)] 239 240 self._enchars = text_orig 241 return [] 242 243 def pop(self, index=-1): 244 if index == -1: 245 index = len(self._enchars) - 1 246 if index < 0 or index >= len(self._enchars): 247 raise IndexError('Out of bound') 248 if self.is_finished(): 249 self._enchars = '' 250 self._jachars = '' 251 else: 252 enchars = list(self._enchars) 253 del enchars[index] 254 self._enchars = ''.join(enchars) 255 jachars = self.__get_romaji_typing_rule(self._enchars, None) 256 if jachars == None: 257 jachars = symbol_rule.get(self._enchars, '') 258 self._jachars = jachars 259 260 261