# vim:set et sts=4 sw=4:
# -*- coding: utf-8 -*-
#
-# ibus-anthy - The Anthy engine for IBus
+# ibus-hangul - The Hangul engine for IBus
#
# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
#
import hangul
from tables import *
from ibus import keysyms
-
-MODE_HIRAGANA, \
-MODE_KATAKANA, \
-MODE_HALF_WIDTH_KATAKANA, \
-MODE_LATIN, \
-MODE_WIDE_LATIN = range(5)
+from ibus import modifier
_ = lambda a: a
class Engine(ibus.EngineBase):
+
+ # init hanja table
+ __hanja_table = None
+
def __init__(self, bus, object_path):
super(Engine, self).__init__(bus, object_path)
-
+ if Engine.__hanja_table == None:
+ table = "/usr/share/libhangul/hanja/hanja.txt"
+ Engine.__hanja_table = \
+ hangul.HanjaTable(table)
# create anthy context
- self.__context = anthy.anthy_context()
- self.__context._set_encoding(anthy.ANTHY_UTF8_ENCODING)
-
- # init state
- self.__input_mode = MODE_HIRAGANA
- self.__prop_dict = {}
-
- self.__lookup_table = ibus.LookupTable()
- self.__prop_list = self.__init_props()
-
- # use reset to init values
+ self.__context = hangul.HangulInputContext("2")
self.__reset()
- def __init_props(self):
- props = ibus.PropList()
-
- # init input mode properties
- mode_prop = ibus.Property(name = "InputMode",
- type = ibus.PROP_TYPE_MENU,
- label = u"あ",
- tooltip = "Switch input mode")
- self.__prop_dict["InputMode"] = mode_prop
-
- mode_props = ibus.PropList()
- mode_props.append(ibus.Property(name = "InputMode.Hiragana",
- type = ibus.PROP_TYPE_RADIO,
- label = "Hiragana"))
- mode_props.append(ibus.Property(name = "InputMode.Katakana",
- type = ibus.PROP_TYPE_RADIO,
- label = "Katakana"))
- mode_props.append(ibus.Property(name = "InputMode.HalfWidthKatakana",
- type = ibus.PROP_TYPE_RADIO,
- label = "Half width katakana"))
- mode_props.append(ibus.Property(name = "InputMode.Latin",
- type = ibus.PROP_TYPE_RADIO,
- label = "Latin"))
- mode_props.append(ibus.Property(name = "InputMode.WideLatin",
- type = ibus.PROP_TYPE_RADIO,
- label = "Wide Latin"))
-
- mode_props[self.__input_mode].set_state(ibus.PROP_STATE_CHECKED)
-
- for prop in mode_props:
- self.__prop_dict[prop.get_name()] = prop
-
- mode_prop.set_sub_props(mode_props)
- props.append(mode_prop)
-
-
- # init test property
- # test_prop = ibus.Property(name = "TestProp",
- # type = ibus.PROP_TYPE_TOGGLE,
- # label = u"あ",
- # tooltip = "test property")
- # self.__prop_dict["TestProp"] = test_prop
- # props.append(test_prop)
-
-
- return props
-
# 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 = list()
- self.__lookup_table.clean()
- self.__lookup_table_visible = False
+ self.__context.reset()
def page_up(self):
- # only process cursor down in convert mode
- if not self.__convert_begined:
- return False
-
- if not self.__lookup_table.page_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 page_down(self):
- # only process cursor down in convert mode
- if not self.__convert_begined:
- return False
-
- if not self.__lookup_table.page_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 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.commit_string(text)
- self.__invalidate()
+ def __update(self):
+ preedit_string = self.__context.get_preedit_string()
+ self.update_preedit(preedit_string, None, len(preedit_string), len(preedit_string) > 0)
+ commit_string = self.__context.get_commit_string()
+ if commit_string:
+ self.commit_string(commit_string)
def process_key_event(self, keyval, is_press, state):
# ignore key release events
if not is_press:
return False
+ state = state & (modifier.SHIFT_MASK | modifier.CONTROL_MASK | modifier.MOD1_MASK)
- if keyval == keysyms.Return:
- return self.__on_key_return()
- elif keyval == keysyms.Escape:
- return self.__on_key_escape()
- elif keyval == keysyms.BackSpace:
- return self.__on_key_back_space()
- elif keyval == keysyms.Delete or keyval == keysyms.KP_Delete:
- return self.__on_key_delete()
- elif keyval == keysyms.space:
- return self.__on_key_space()
- elif keyval >= keysyms._1 and keyval <= keysyms._9:
- return self.__on_key_number(keyval)
- elif keyval == keysyms.Page_Up or keyval == keysyms.KP_Page_Up:
- return self.__on_key_page_up()
- elif keyval == keysyms.Page_Down or keyval == keysyms.KP_Page_Down:
- return self.__on_key_page_down()
- elif keyval == keysyms.Up:
- return self.__on_key_up()
- elif keyval == keysyms.Down:
- return self.__on_key_down()
- elif keyval == keysyms.Left:
- return self.__on_key_left()
- elif keyval == keysyms.Right:
- return self.__on_key_right()
- elif keyval in xrange(keysyms.a, keysyms.z + 1) or \
- keyval in xrange(keysyms.A, keysyms.Z + 1) or \
- unichr(keyval) in symbols_set:
- return self.__on_key_common(keyval)
- else:
- return True
+ if state == 0:
+ if keyval >= keysyms.exclam and keyval <= keysyms.asciitilde:
+ if self.__context.process(keyval):
+ self.__update()
+ return True
+ elif keyval == keysyms.BackSpace:
+ if self.__context.backspace():
+ self.__update()
+ return True
+ return False
return False
def property_activate(self, prop_name, state):
- prop = self.__prop_dict[prop_name]
- prop.set_state(state)
-
- if state == ibus.PROP_STATE_CHECKED:
- if prop_name == "InputMode.Hiragana":
- prop = self.__prop_dict["InputMode"]
- prop.set_label(_(u"あ"))
- self.__input_mode = MODE_HIRAGANA
- self.update_property(prop)
- self.__reset()
- self.__invalidate()
- elif prop_name == "InputMode.Katakana":
- prop = self.__prop_dict["InputMode"]
- prop.set_label(_(u"ア"))
- self.__input_mode = MODE_KATAKANA
- self.update_property(prop)
- self.__reset()
- self.__invalidate()
- elif prop_name == "InputMode.HalfWidthKatakana":
- prop = self.__prop_dict["InputMode"]
- prop.set_label(_(u"ア"))
- self.__input_mode = MODE_HALF_WIDTH_KATAKANA
- self.update_property(prop)
- self.__reset()
- self.__invalidate()
- elif prop_name == "InputMode.Latin":
- prop = self.__prop_dict["InputMode"]
- self.__input_mode = MODE_LATIN
- prop.set_label(_(u"A"))
- self.update_property(prop)
- self.__reset()
- self.__invalidate()
- elif prop_name == "InputMode.WideLatin":
- prop = self.__prop_dict["InputMode"]
- prop.set_label(_(u"A"))
- self.__input_mode = MODE_WIDE_LATIN
- self.update_property(prop)
- self.__reset()
- self.__invalidate()
+ pass
def focus_in(self):
- self.register_properties(self.__prop_list)
+ pass
def focus_out(self):
pass
- # 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 = self.__context.get_segment(i, 0)
- text = unicode(buf, "utf-8")
- self.__segments.append((0, text))
-
- self.__cursor_pos = 0
- self.__fill_lookup_table()
- self.__lookup_table_visible = False
-
- def __fill_lookup_table(self):
- # get segment stat
- seg_stat = anthy.anthy_segment_stat()
- self.__context.get_segment_stat(self.__cursor_pos, seg_stat)
-
- # fill lookup_table
- self.__lookup_table.clean()
- for i in xrange(0, seg_stat.nr_candidate):
- buf = self.__context.get_segment(self.__cursor_pos, i)
- candidate = unicode(buf, "utf-8")
- self.__lookup_table.append_candidate(candidate)
-
-
- def __invalidate(self):
- if self.__need_update:
- return
- self.__need_update = True
- gobject.idle_add(self.__update, priority = gobject.PRIORITY_LOW)
-
- def __translate_to_ja(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:
- text = romja
- if self.__input_mode == MODE_HIRAGANA:
- text = romja
- elif self.__input_mode == MODE_KATAKANA:
- text = hiragana_katakana_table[romja][0]
- elif self.__input_mode == MODE_HALF_WIDTH_KATAKANA:
- text = hiragana_katakana_table[romja][1]
-
- self.__input_chars = u"".join((self.__input_chars[:i], text, self.__input_chars[end:]))
- self.__cursor_pos -= len(text)
- self.__cursor_pos += len(text)
-
- def __update_input_chars(self):
- self.__translate_to_ja()
-
- attrs = ibus.AttrList()
- attrs.append(ibus.AttributeUnderline(ibus.ATTR_UNDERLINE_SINGLE, 0, len(self.__input_chars.encode("utf-8"))))
-
- self.update_preedit(self.__input_chars, attrs, self.__cursor_pos, len(self.__input_chars) > 0)
- self.update_aux_string(u"", ibus.AttrList(), False)
- self.update_lookup_table(self.__lookup_table, self.__lookup_table_visible)
-
- def __update_convert_chars(self):
- self.__convert_chars = u""
- 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(ibus.ATTR_UNDERLINE_SINGLE, 0, len(self.__convert_chars)))
- attrs.append(ibus.AttributeBackground(ibus.RGB(200, 200, 240),
- pos - len(self.__segments[self.__cursor_pos][1]),
- pos))
- self.update_preedit(self.__convert_chars, attrs, pos, True)
- aux_string = u"( %d / %d )" % (self.__lookup_table.get_cursor_pos() + 1, self.__lookup_table.get_number_of_candidates())
- self.update_aux_string(aux_string, ibus.AttrList(), self.__lookup_table_visible)
- self.update_lookup_table(self.__lookup_table, self.__lookup_table_visible)
-
- def __update(self):
- self.__need_update = False
- if self.__convert_begined == False:
- self.__update_input_chars()
- else:
- self.__update_convert_chars()
-
- def __on_key_return(self):
- if not self.__input_chars:
- return False
- if self.__convert_begined == False:
- self.__commit_string(self.__input_chars)
- else:
- i = 0
- for seg_index, text in self.__segments:
- self.__context.commit_segment(i, seg_index)
- self.__commit_string(self.__convert_chars)
- return True
-
- def __on_key_escape(self):
- if not self.__input_chars:
- return False
- self.__reset()
- self.__invalidate()
- return True
-
- def __on_key_back_space(self):
- if not self.__input_chars:
- return False
-
- if self.__convert_begined:
- self.__convert_begined = False
- self.__cursor_pos = len(self.__input_chars)
- self.__lookup_table.clean()
- self.__lookup_table_visible = False
- elif self.__cursor_pos > 0:
- self.__input_chars = self.__input_chars[:self.__cursor_pos - 1] + self.__input_chars [self.__cursor_pos:]
- self.__cursor_pos -= 1
-
- self.__invalidate()
- return True
-
- def __on_key_delete(self):
- if not self.__input_chars:
- return False
-
- if self.__convert_begined:
- self.__convert_begined = False
- self.__cursor_pos = len(self.__input_chars)
- self.__lookup_table.clean()
- self.__lookup_table_visible = False
- elif self.__cursor_pos < len(self.__input_chars):
- self.__input_chars = self.__input_chars[:self.__cursor_pos] + self.__input_chars [self.__cursor_pos + 1:]
-
- self.__invalidate()
- return True
-
- def __on_key_space(self):
- if not self.__input_chars:
- return False
- if self.__convert_begined == False:
- self.__begin_convert()
- self.__invalidate()
- else:
- self.__lookup_table_visible = True
- self.cursor_down()
- return True
-
- def __on_key_up(self):
- if not self.__input_chars:
- return False
- self.__lookup_table_visible = True
- self.cursor_up()
- return True
-
- def __on_key_down(self):
- if not self.__input_chars:
- return False
- self.__lookup_table_visible = True
- self.cursor_down()
- return True
-
- def __on_key_page_up(self):
- if not self.__input_chars:
- return False
- if self.__lookup_table_visible == True:
- self.page_up()
- return True
-
- def __on_key_page_down(self):
- if not self.__input_chars:
- return False
- if self.__lookup_table_visible == True:
- self.page_down()
- return True
-
- def __on_key_left(self):
- if not self.__input_chars:
- return False
- if self.__cursor_pos == 0:
- return True
- self.__cursor_pos -= 1
- self.__lookup_table_visible = False
- self.__fill_lookup_table()
- self.__invalidate()
- return True
-
- def __on_key_right(self):
- if not self.__input_chars:
- return False
-
- if self.__convert_begined:
- max_pos = len(self.__segments) - 1
- else:
- max_pos = len(self.__input_chars)
- if self.__cursor_pos == max_pos:
- return True
- self.__cursor_pos += 1
- self.__lookup_table_visible = False
- self.__fill_lookup_table()
- self.__invalidate()
-
- return True
-
- def __on_key_number(self, keyval):
- if self.__input_mode == MODE_LATIN:
- char = unichr(keyval)
- self.__commit_string(char)
- return True
- elif self.__input_mode == MODE_WIDE_LATIN:
- char = ibus.unichar_half_to_full(unichr(keyval))
- self.__commit_string(char)
- return True
-
- if not self.__input_chars:
- self.__commit_string(unichr(keyval))
- return True
-
- index = keyval - keysyms._1
- if self.__convert_begined and self.__lookup_table_visible:
- candidates = self.__lookup_table.get_canidates_in_current_page()
- if self.__lookup_table.set_cursor_pos_in_current_page(index):
- index = self.__lookup_table.get_cursor_pos()
- candidate = self.__lookup_table.get_current_candidate()[0]
- self.__segments[self.__cursor_pos] = index, candidate
- self.__lookup_table_visible = False
- self.__on_key_right()
- self.__invalidate()
- return True
-
-
- def __on_key_common(self, keyval):
- if self.__input_mode == MODE_LATIN:
- char = unichr(keyval)
- self.__commit_string(char)
- return True
- elif self.__input_mode == MODE_WIDE_LATIN:
- char = unichr(keyval)
- if char in symbols_set:
- char = romaji_typing_rule[char]
- else:
- char = ibus.unichar_half_to_full(char)
- self.__commit_string(char)
- return True
-
- if self.__convert_begined:
- i = 0
- for seg_index, text in self.__segments:
- self.__context.commit_segment(i, seg_index)
- self.__commit_string(self.__convert_chars)
- self.__input_chars = \
- self.__input_chars[:self.__cursor_pos] + \
- unichr(keyval) + \
- self.__input_chars[self.__cursor_pos:]
- self.__cursor_pos += 1
- self.__invalidate()
- return True
-
-