/*************************************************************************** * Copyright (C) 2004 by TAM(Teppei Tamra) * * tam-t@par.odn.ne.jp * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ // って言うか先にWnnをC++向けに優しく包み込む母のようなライブラリ激しく希望。 // ああそうですね、「お前がやれ」ですよね。 #define Uses_SCIM_UTILITY #define Uses_SCIM_IMENGINE #define Uses_SCIM_LOOKUP_TABLE #define Uses_SCIM_CONFIG_BASE #define Uses_SCIM_ICONV #ifdef HAVE_CONFIG_H #include <config.h> #endif // 国際化のおまじない。 // まぁ愚痴を言わせてもらえば、これを毎回どうにかしなきゃいけないっつーのは // どうなんでしょうなぁ…。 // KDEなら飛ばせる部分ですが何か?。 #ifdef HAVE_GETTEXT #include <libintl.h> #define _(String) dgettext(GETTEXT_PACKAGE,String) #define N_(String) (String) #else #define _(String) (String) #define N_(String) (String) #define bindtextdomain(Package,Directory) #define textdomain(domain) #define bind_textdomain_codeset(domain,codeset) #endif // scimのおまじない。 // 一言で言えば、めんどくs #include "scim_wnn_imengine.h" #include "scim_wnn_def.h" #define scim_module_init wnn_LTX_scim_module_init #define scim_module_exit wnn_LTX_scim_module_exit #define scim_imengine_module_init wnn_LTX_scim_imengine_module_init #define scim_imengine_module_create_factory wnn_LTX_scim_imengine_module_create_factory #ifndef SCIM_WNN_ICON_FILE #define SCIM_WNN_ICON_FILE (SCIM_ICONDIR "/scim-wnn.png") #endif #define SCIM_PROP_WNN_INPUTMODE "/IMEngine/Wnn/InputMode" static Pointer <WnnFactory> _scim_wnn_factory; static ConfigPointer _scim_config; extern "C" { // あれでしょう。 // KDEなんかでも使われてる動的ローディングの小技。 // Cリンケージで関数名固定させて、そっからインスタンス作るっつーあれ。 // 面倒だよねぇ。まぁ別に良いけどさ。 void scim_module_init (void) { } void scim_module_exit (void) { _scim_wnn_factory.reset (); _scim_config.reset (); } unsigned int scim_imengine_module_init (const ConfigPointer &config) { _scim_config = config; return 1; } IMEngineFactoryPointer scim_imengine_module_create_factory (unsigned int factory) { if (factory != 0) return NULL; if (_scim_wnn_factory.null ()) { _scim_wnn_factory = new WnnFactory (utf8_mbstowcs (String (_("Wnn"))),String("ja_JP")); } return _scim_wnn_factory; } } WnnFactory::WnnFactory() { m_name = utf8_mbstowcs(_("Wnn")); set_languages(String("ja_JP")); } WnnFactory::~ WnnFactory() { } WnnFactory::WnnFactory(const WideString & name, const String & languages) { // 文字数制限か。 if (name.length () <= 8) m_name = name; else m_name.assign (name.begin (), name.begin () + 8); // とりあえず日本語環境で固定したいトコだ。 if (languages == String ("default")) set_languages (String (_("ja_JP"))); else set_languages (languages); } WideString WnnFactory::get_name () const { // 名前を返すのね。utf8_mbstowcs(_("Wnn"))で。 return m_name; } WideString WnnFactory::get_authors () const { // AUTHERね。 return utf8_mbstowcs (String (_("(C) 2004 TAM(Teppei Tamra) <tam-t@par.odn.ne.jp>"))); } WideString WnnFactory::get_credits () const { // CREDITね。とりあえず空で。 return WideString (); } WideString WnnFactory::get_help () const { // HELPも書かないとダメなのね。 return utf8_mbstowcs (String (_("SCIM-WNN HELP"))); } String WnnFactory::get_uuid () const { // uuidgen叩いて識別と。ユニークならなんでもよさげだけども。 return String ("c069395a-d62f-4a77-8229-446e44a99976"); } String WnnFactory::get_icon_file () const { // アイコンを指定。作らないとね。 return String (SCIM_WNN_ICON_FILE); } IMEngineInstancePointer WnnFactory::create_instance (const String& encoding, int id) { // 実際にインスタンスを作る。 return new WnnInstance (this, encoding, id); } // キーイベントチェック void WnnKeyEventList::append(const KeyEvent &k) { push_back(k); } void WnnKeyEventList::append(int code,int mask) { KeyEvent k; k.code = code; k.mask = mask; append(k); } bool WnnKeyEventList::comp(const KeyEvent &k) { for (unsigned int i = 0;i < size();i ++) { if ((at(i).code == k.code) && (at(i).mask == k.mask)) { return(true); } } return(false); } // 淫 醋 箪 笥 // 現物。 WnnInstance::WnnInstance (WnnFactory *factory, const String& encoding, int id) : IMEngineInstanceBase (factory, encoding, id) { m_conversion = false; m_lookup = false; m_connected = false; host = _scim_config->read(String(SCIM_CONFIG_WNN_SERVER),String("localhost")); rc = _scim_config->read(String(SCIM_CONFIG_WNN_RC),String("/usr/lib/wnn7/ja_JP/wnnenvrc")); alp = _scim_config->read(String(SCIM_CONFIG_WNN_ALP),SCIM_DEFAULT_WNN_ALP); // デフォルトキー設定。 // 設定ファイルから読むようにしてごにょごにょ。 scim_string_to_key_list(k_conversion_start, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_CONVERSION_START), String(SCIM_DEFAULT_WNN_KEY_CONVERSION_START))); scim_string_to_key_list(k_cancel, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_CANCEL), String(SCIM_DEFAULT_WNN_KEY_CANCEL))); scim_string_to_key_list(k_delete, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_DELETE), String(SCIM_DEFAULT_WNN_KEY_DELETE))); scim_string_to_key_list(k_backspace, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_BACKSPACE), String(SCIM_DEFAULT_WNN_KEY_BACKSPACE))); scim_string_to_key_list(k_commit, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_COMMIT), String(SCIM_DEFAULT_WNN_KEY_COMMIT))); scim_string_to_key_list(k_conversion_next, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_CONVERSION_NEXT), String(SCIM_DEFAULT_WNN_KEY_CONVERSION_NEXT))); scim_string_to_key_list(k_conversion_prev, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_CONVERSION_PREV), String(SCIM_DEFAULT_WNN_KEY_CONVERSION_PREV))); scim_string_to_key_list(k_conversion_expand, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_CONVERSION_EXPAND), String(SCIM_DEFAULT_WNN_KEY_CONVERSION_EXPAND))); scim_string_to_key_list(k_conversion_shrink, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_CONVERSION_SHRINK), String(SCIM_DEFAULT_WNN_KEY_CONVERSION_SHRINK))); scim_string_to_key_list(k_conversion_forward, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_CONVERSION_FORWARD), String(SCIM_DEFAULT_WNN_KEY_CONVERSION_FORWARD))); scim_string_to_key_list(k_conversion_backward, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_CONVERSION_BACKWARD), String(SCIM_DEFAULT_WNN_KEY_CONVERSION_BACKWARD))); scim_string_to_key_list(k_forward, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_FORWARD), String(SCIM_DEFAULT_WNN_KEY_FORWARD))); scim_string_to_key_list(k_backward, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_BACKWARD), String(SCIM_DEFAULT_WNN_KEY_BACKWARD))); scim_string_to_key_list(k_lookup_popup, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_LOOKUPPOPUP), String(SCIM_DEFAULT_WNN_KEY_LOOKUPPOPUP))); scim_string_to_key_list(k_lookup_pageup, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_LOOKUPPAGEUP), String(SCIM_DEFAULT_WNN_KEY_LOOKUPPAGEUP))); scim_string_to_key_list(k_lookup_pagedown, _scim_config->read(String(SCIM_CONFIG_WNN_KEY_LOOKUPPAGEDOWN), String(SCIM_DEFAULT_WNN_KEY_LOOKUPPAGEDOWN))); } WnnInstance::~ WnnInstance() { } bool WnnInstance::process_key_event (const KeyEvent& key) { if (key.is_key_release()) return false; if (m_conversion) return(process_conversion_key_event(key)); else return(process_preedit_key_event(key)); } /*! \fn WnnInstance::process_preedit_key_event(const KeyEvent &key) */ bool WnnInstance::process_preedit_key_event(const KeyEvent &key) { if (k_conversion_start.comp(key)) { if (!m_rk.getTextLength()) { return(false); } startConversion(m_rk.getText(true)); show_preedit_string(); if (m_conversion) { update_preedit_string(wnn.getText(),wnn.getAttributeList()); update_preedit_caret(wnn.getCaretPos()); } return(true); } else if (k_commit.comp(key)) { if (!m_rk.getTextLength()) { return(false); } commit_string(m_rk.getText(true)); m_rk.reset(); hide_preedit_string(); return(true); } else if (k_forward.comp(key) || k_backward.comp(key)) { if (!m_rk.getTextLength()) { return(false); } k_backward.comp(key) ? m_rk.setPos(m_rk.getPos() - 1) : m_rk.setPos(m_rk.getPos() + 1); update_preedit_caret(m_rk.getPos()); return(true); } else if (k_backspace.comp(key)) { if (!m_rk.getTextLength()) { return(false); } m_rk.backspace(); update_preedit_string(m_rk.getText()); update_preedit_caret(m_rk.getPos()); return(true); } else if (k_delete.comp(key)) { if (!m_rk.getTextLength()) { return(false); } m_rk.del(); update_preedit_string(m_rk.getText()); update_preedit_caret(m_rk.getPos()); return(true); } else if (k_cancel.comp(key)) { if (!m_rk.getTextLength()) { return(false); } m_rk.reset(); hide_preedit_string(); return(true); } else if (isprint(key.code)) { if (key.mask & (SCIM_KEY_AltMask | SCIM_KEY_ControlMask)) return(false); show_preedit_string(); SCIM_DEBUG_IMENGINE(1) << key.get_key_string() << "\n"; update_preedit_string(m_rk.insert(key.get_ascii_code())); update_preedit_caret(m_rk.getPos()); return true; } return false; } /*! \fn WnnInstance::process_conversion_key_event(const KeyEvent &key) */ bool WnnInstance::process_conversion_key_event(const KeyEvent &key) { if ((alp < alp_count) && (alp != 0)) { if (!m_lookup) startLookup(); } if (k_lookup_popup.comp(key)) { if (m_lookup) return(true); startLookup(); return(true); } else if (k_lookup_pageup.comp(key)) { if (m_lookup) { lookup_table_page_up(); } } else if (k_lookup_pagedown.comp(key)) { if (m_lookup) { lookup_table_page_down(); } } else if (k_commit.comp(key)) { commit_string(wnn.getText()); wnn.updateFrequency(); m_rk.reset(); wnn.reset(); m_conversion = false; hide_preedit_string(); hide_lookup_table(); hide_aux_string(); m_lookup = false; alp_count = 0; return(true); } else if (k_cancel.comp(key) || k_backspace.comp(key)) { wnn.reset(); m_conversion = false; update_preedit_string(m_rk.getText()); update_preedit_caret(m_rk.getPos()); hide_lookup_table(); hide_aux_string(); m_lookup = false; alp_count = 0; return(true); } else if (k_conversion_next.comp(key) || k_conversion_prev.comp(key)) { k_conversion_prev.comp(key) ? m_convList.pos --: m_convList.pos ++; if (m_convList.pos >= m_convList.count) m_convList.pos = 0; else if (m_convList.pos < 0) m_convList.pos = m_convList.count - 1; alp_count ++; wnn.select(m_convList.pos); update_preedit_string(wnn.getText(),wnn.getAttributeList()); update_preedit_caret(wnn.getCaretPos()); if (m_lookup) { m_lookup_table.set_cursor_pos(m_convList.pos); update_lookup_table(m_lookup_table); } return(true); } else if (k_conversion_expand.comp(key) || k_conversion_shrink.comp(key)) { bool r; k_conversion_shrink.comp(key) ? r = wnn.resizeRegion(-1) : r = wnn.resizeRegion(1); if (!r) return(true); m_convList = wnn.getConversionList(); update_preedit_string(wnn.getText(),wnn.getAttributeList()); update_preedit_caret(wnn.getCaretPos()); hide_lookup_table(); hide_aux_string(); m_lookup = false; alp_count = 0; return(true); } else if (k_conversion_forward.comp(key) || k_conversion_backward.comp(key)) { k_conversion_backward.comp(key) ? wnn.setPos(wnn.getPos() - 1) : wnn.setPos(wnn.getPos() + 1); m_convList = wnn.getConversionList(); update_preedit_string(wnn.getText(),wnn.getAttributeList()); update_preedit_caret(wnn.getCaretPos()); hide_lookup_table(); hide_aux_string(); m_lookup = false; alp_count = 0; return(true); } else if (isprint(key.code)) { if (key.mask & (SCIM_KEY_AltMask | SCIM_KEY_ControlMask)) return(false); commit_string(wnn.getText()); wnn.updateFrequency(); m_rk.reset(); wnn.reset(); m_conversion = false; hide_preedit_string(); hide_lookup_table(); hide_aux_string(); m_lookup = false; alp_count = 0; return(process_preedit_key_event(key)); } return(true); } void WnnInstance::move_preedit_caret (unsigned int pos) { if (!m_conversion) m_rk.setPos(pos); update_preedit_caret(pos); } void WnnInstance::select_candidate (unsigned int item) { if (!m_lookup_table.number_of_candidates()) return; int p = m_lookup_table.get_current_page_start() + item; m_convList.pos = p; wnn.select(m_convList.pos); update_preedit_string(wnn.getText(),wnn.getAttributeList()); update_preedit_caret(wnn.getCaretPos()); m_lookup_table.set_cursor_pos(m_convList.pos); update_lookup_table(m_lookup_table); } void WnnInstance::update_lookup_table_page_size (unsigned int page_size) { m_lookup_table.set_page_size (page_size); } void WnnInstance::lookup_table_page_up () { if (!m_lookup_table.number_of_candidates () || !m_lookup_table.get_current_page_start ()) return; int p = m_convList.pos - m_lookup_table.get_current_page_size(); if (p < 0) p = 0; m_convList.pos = p; wnn.select(m_convList.pos); update_preedit_string(wnn.getText(),wnn.getAttributeList()); update_preedit_caret(wnn.getCaretPos()); m_lookup_table.set_cursor_pos(m_convList.pos); update_lookup_table(m_lookup_table); } void WnnInstance::lookup_table_page_down () { if (!m_lookup_table.number_of_candidates () || m_lookup_table.get_current_page_start () + m_lookup_table.get_current_page_size () >= m_lookup_table.number_of_candidates ()) return; int p = m_convList.pos + m_lookup_table.get_current_page_size(); if (p >= m_convList.count) p = m_convList.count - 1; m_convList.pos = p; wnn.select(m_convList.pos); update_preedit_string(wnn.getText(),wnn.getAttributeList()); update_preedit_caret(wnn.getCaretPos()); m_lookup_table.set_cursor_pos(m_convList.pos); update_lookup_table(m_lookup_table); } void WnnInstance::reset () { alp_count = 0; m_conversion = false; m_lookup = false; hide_lookup_table (); hide_aux_string(); hide_preedit_string (); wnn.reset(); m_rk.reset(); } void WnnInstance::focus_in () { } void WnnInstance::focus_out () { if (m_conversion) { commit_string(wnn.getText()); wnn.updateFrequency(); m_rk.reset(); wnn.reset(); m_conversion = false; hide_preedit_string(); hide_lookup_table(); hide_aux_string(); m_lookup = false; alp_count = 0; } else if (m_rk.getTextLength()) { commit_string(m_rk.getText(true)); m_rk.reset(); hide_preedit_string(); } } void WnnInstance::trigger_property (const String &property) { } /*! \fn WnnInstance::startConversion(WideString s) */ void WnnInstance::startConversion(WideString s) { if (!m_connected) { m_connected = wnn.wnnConnect(String("test"),host,rc,0); } if (!m_connected) { update_aux_string(utf8_mbstowcs(String(_("could not connect to jserver.")))); show_aux_string(); return; } wnn.setYomiText(s); if (wnn.ren_conversion() == -1) { update_aux_string(utf8_mbstowcs(String(_("could not connect to jserver.")))); show_aux_string(); return; } m_convList = wnn.getConversionList(); m_conversion = true; alp_count = 0; } /*! \fn WnnInstance::createLookupTable(WnnConversionList cList) */ void WnnInstance::createLookupTable(WnnConversionList cList) { m_lookup_table.clear(); if (!cList.count) return; for (unsigned int i = 0;i < cList.count;i ++) { m_lookup_table.append_candidate(cList.kouho.at(i)); } m_lookup_table.set_cursor_pos(cList.pos); update_lookup_table(m_lookup_table); } /*! \fn WnnInstance::startLookup() */ void WnnInstance::startLookup() { createLookupTable(m_convList); m_lookup = true; update_aux_string(utf8_mbstowcs(String(_("lookup result")))); show_aux_string(); show_lookup_table(); }