Newer
Older
scim-wnn / honoka / src / honoka_imengine.cpp
@tamra tamra on 8 Apr 2005 33 KB 名称変更処理。
/***************************************************************************
 *   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.             *
 ***************************************************************************/


#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

// 国際化のおまじない。
#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のおまじない。
#include "honoka_imengine.h"
#include "honoka_def.h"

#define scim_module_init honoka_LTX_scim_module_init
#define scim_module_exit honoka_LTX_scim_module_exit
#define scim_imengine_module_init honoka_LTX_scim_imengine_module_init
#define scim_imengine_module_create_factory honoka_LTX_scim_imengine_module_create_factory
#ifndef HONOKA_ICON_FILE
  #define HONOKA_ICON_FILE           (SCIM_ICONDIR "/honoka.png")
#endif


static Pointer <HonokaFactory> _honoka_factory;
static ConfigPointer _scim_config;

extern "C" {
    void scim_module_init (void)
    {
        bindtextdomain (GETTEXT_PACKAGE, HONOKA_LOCALEDIR);
        bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
    }

    void scim_module_exit (void)
    {
        _honoka_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 (_honoka_factory.null ()) {
            _honoka_factory =
                new HonokaFactory (utf8_mbstowcs (String (_("Honoka"))),String("ja_JP"));
        }
        return _honoka_factory;
    }
}

HonokaFactory::HonokaFactory() {
    m_name = utf8_mbstowcs(_("Honoka"));
    set_languages(String("ja_JP"));
}

HonokaFactory::~ HonokaFactory() {
}

HonokaFactory::HonokaFactory(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 HonokaFactory::get_name () const
{
    return m_name;
}

WideString HonokaFactory::get_authors () const
{
    return utf8_mbstowcs (String (_("(C) 2004 TAM(Teppei Tamra) <tam-t@par.odn.ne.jp>")));
}

WideString HonokaFactory::get_credits () const
{
    return WideString ();
}

WideString HonokaFactory::get_help () const
{
    return utf8_mbstowcs (String (_("SCIM-WNN HELP")));
}

String HonokaFactory::get_uuid () const
{
    return String ("c069395a-d62f-4a77-8229-446e44a99976");
}

String HonokaFactory::get_icon_file () const
{
    return String (HONOKA_ICON_FILE);
}

IMEngineInstancePointer HonokaFactory::create_instance (const String& encoding, int id)
{
    return new HonokaInstance (this, encoding, id);
}



// キーイベントチェック

void HonokaKeyEventList::append(const KeyEvent &k) {
    push_back(k);
}

void HonokaKeyEventList::append(int code,int mask) {
    KeyEvent k;
    k.code = code;
    k.mask = mask;
    append(k);
}

bool HonokaKeyEventList::comp(const KeyEvent &k) {
    int kc = k.get_ascii_code();
    if ((kc > 0x60) && (kc < 0x7b)) kc -= 0x20;
    else if ((kc > 0x40) && (kc < 0x5b)) kc += 0x20;
    for (unsigned int i = 0;i < size();i ++) {
        if ((at(i).code == k.code) && (at(i).mask == k.mask)) {
            return(true);
        }
        if (kc && (at(i).code == kc) && (at(i).mask == k.mask)) {
            return(true);
        }
    }
    return(false);
}


// 現物。


HonokaInstance::HonokaInstance (HonokaFactory *factory, const String& encoding, int id)
    : IMEngineInstanceBase (factory, encoding, id)
{
    m_iconv.set_encoding ("EUC-JP");
    preeditors.push_back(new Romkan(_scim_config));
    preeditors.push_back(new KanaInput(_scim_config));
    m_preeditor = preeditors.at(0);
    wnn = 0;
    init();
}

HonokaInstance::~HonokaInstance()
{
    for(unsigned int i = 0;i < preeditors.size();i ++) {
        delete(preeditors.at(i));
    }
    if (wnn->isConnected()) wnn->disconnect();
}


/*!
    \fn HonokaInstance::init()
 */
void HonokaInstance::init()
{
    m_conversion = false;
    m_yosoku = false;
    m_lookup = false;

    // @todo if connected to jserver, should disconnect this.

    alp = _scim_config->read(String(HONOKA_CONFIG_ALP),HONOKA_DEFAULT_ALP);
    mini_status = _scim_config->read(String(HONOKA_CONFIG_MINISTATUS),HONOKA_DEFAULT_MINISTATUS);
    numkeyselect = _scim_config->read(String(HONOKA_CONFIG_NUMKEY_SELECT),HONOKA_DEFAULT_NUMKEY_SELECT);
    yosoku = _scim_config->read(String(HONOKA_CONFIG_YOSOKU),HONOKA_DEFAULT_YOSOKU);
    sType = _scim_config->read(String(HONOKA_CONFIG_SERVERTYPE),String(HONOKA_DEFAULT_SERVERTYPE));
    
    if (wnn) delete(wnn);
    #ifdef HAVE_LIBANTHY
    if (sType == "Anthy")
        wnn = new AnthyConversion(_scim_config);
    else 
    #endif
        wnn = new WnnConversion(_scim_config);

    
    defaultPreEditor = _scim_config->read(String(HONOKA_CONFIG_DEFAULT_PREEDITOR),String(HONOKA_DEFAULT_DEFAULT_PREEDITOR));
    auto_conversion = _scim_config->read(String(HONOKA_CONFIG_AUTO_CONVERSION),HONOKA_DEFAULT_AUTO_CONVERSION);;

    // デフォルトキー設定。
    scim_string_to_key_list(k_conversion_start,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_START),
            String(HONOKA_DEFAULT_KEY_CONVERSION_START)));
    scim_string_to_key_list(k_cancel,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CANCEL),
            String(HONOKA_DEFAULT_KEY_CANCEL)));
    scim_string_to_key_list(k_delete,
        _scim_config->read(String(HONOKA_CONFIG_KEY_DELETE),
            String(HONOKA_DEFAULT_KEY_DELETE)));
    scim_string_to_key_list(k_backspace,
        _scim_config->read(String(HONOKA_CONFIG_KEY_BACKSPACE),
            String(HONOKA_DEFAULT_KEY_BACKSPACE)));
    scim_string_to_key_list(k_commit,
        _scim_config->read(String(HONOKA_CONFIG_KEY_COMMIT),
            String(HONOKA_DEFAULT_KEY_COMMIT)));
    scim_string_to_key_list(k_conversion_next,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_NEXT),
            String(HONOKA_DEFAULT_KEY_CONVERSION_NEXT)));
    scim_string_to_key_list(k_conversion_prev,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_PREV),
            String(HONOKA_DEFAULT_KEY_CONVERSION_PREV)));
    scim_string_to_key_list(k_conversion_expand,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_EXPAND),
            String(HONOKA_DEFAULT_KEY_CONVERSION_EXPAND)));
    scim_string_to_key_list(k_conversion_shrink,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_SHRINK),
            String(HONOKA_DEFAULT_KEY_CONVERSION_SHRINK)));
    scim_string_to_key_list(k_conversion_forward,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_FORWARD),
            String(HONOKA_DEFAULT_KEY_CONVERSION_FORWARD)));
    scim_string_to_key_list(k_conversion_backward,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_BACKWARD),
            String(HONOKA_DEFAULT_KEY_CONVERSION_BACKWARD)));
    scim_string_to_key_list(k_forward,
        _scim_config->read(String(HONOKA_CONFIG_KEY_FORWARD),
            String(HONOKA_DEFAULT_KEY_FORWARD)));
    scim_string_to_key_list(k_backward,
        _scim_config->read(String(HONOKA_CONFIG_KEY_BACKWARD),
            String(HONOKA_DEFAULT_KEY_BACKWARD)));
    scim_string_to_key_list(k_home,
        _scim_config->read(String(HONOKA_CONFIG_KEY_HOME),
            String(HONOKA_DEFAULT_KEY_HOME)));
    scim_string_to_key_list(k_end,
        _scim_config->read(String(HONOKA_CONFIG_KEY_END),
            String(HONOKA_DEFAULT_KEY_END)));
    scim_string_to_key_list(k_lookup_popup,
        _scim_config->read(String(HONOKA_CONFIG_KEY_LOOKUPPOPUP),
            String(HONOKA_DEFAULT_KEY_LOOKUPPOPUP)));
    scim_string_to_key_list(k_lookup_pageup,
        _scim_config->read(String(HONOKA_CONFIG_KEY_LOOKUPPAGEUP),
            String(HONOKA_DEFAULT_KEY_LOOKUPPAGEUP)));
    scim_string_to_key_list(k_lookup_pagedown,
        _scim_config->read(String(HONOKA_CONFIG_KEY_LOOKUPPAGEDOWN),
            String(HONOKA_DEFAULT_KEY_LOOKUPPAGEDOWN)));
    scim_string_to_key_list(k_convert_hiragana,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_HIRAGANA),
            String(HONOKA_DEFAULT_KEY_CONVERT_HIRAGANA)));
    scim_string_to_key_list(k_convert_katakana,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_KATAKANA),
            String(HONOKA_DEFAULT_KEY_CONVERT_KATAKANA)));
    scim_string_to_key_list(k_convert_half,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_HALF),
            String(HONOKA_DEFAULT_KEY_CONVERT_HALF)));
    scim_string_to_key_list(k_convert_wide,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_WIDE),
            String(HONOKA_DEFAULT_KEY_CONVERT_WIDE)));

    scim_string_to_key_list(k_conversion_rensou,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_RENSOU),
            String(HONOKA_DEFAULT_KEY_CONVERSION_RENSOU)));
    scim_string_to_key_list(k_conversion_ikeiji,
        _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_IKEIJI),
            String(HONOKA_DEFAULT_KEY_CONVERSION_IKEIJI)));
    scim_string_to_key_list(k_select_yosoku,
        _scim_config->read(String(HONOKA_CONFIG_KEY_SELECT_YOSOKU),
            String(HONOKA_DEFAULT_KEY_SELECT_YOSOKU)));
    scim_string_to_key_list(k_auto_conversion,
        _scim_config->read(String(HONOKA_CONFIG_KEY_AUTO_CONVERSION),
            String(HONOKA_DEFAULT_KEY_AUTO_CONVERSION)));

    changePreEditor(defaultPreEditor);

    // ここで一度接続しておこう。
    wnn->connect();

}


/*!
    \fn HonokaInstance::changePreEditor(const String &name)
 */
void HonokaInstance::changePreEditor(const String &name)
{
    for(unsigned int i = 0;i < preeditors.size();i ++) {
        if (preeditors[i]->getPropertyName() == name) {
            m_preeditor = preeditors[i];
            return;
        }
    }
    return;
}


/*!
    \fn HonokaInstance::updateProperty()
 */
void HonokaInstance::updateProperty()
{
    if (m_proplist.empty()) {
        Property p;
        p = Property(SCIM_PROP_WNN_INPUTMODE,"",String(""),_("input mode"));
        m_proplist.push_back(p);
        for(unsigned int i = 0;i < preeditors.size();i ++) {
            p = Property(String(SCIM_PROP_WNN_INPUTMODE) + String("/") + preeditors[i]->getPropertyName(),
                preeditors[i]->getName(),String(""),_("mode status"));
            m_proplist.push_back(p);
        }
        p = Property(SCIM_PROP_WNN_MODESTATUS,"",String(""),_("mode status"));
        m_proplist.push_back(p);
        p = Property(SCIM_PROP_WNN_CONVERSIONMODE,"",String(""),_("conversion mode"));
        m_proplist.push_back(p);
    }
    PropertyList::iterator it;
    it = find(m_proplist.begin(),m_proplist.end(),SCIM_PROP_WNN_INPUTMODE);
    if (it != m_proplist.end()) {
        it->set_label(m_preeditor->getName());
    }
    update_property(*it);
    it = find(m_proplist.begin(),m_proplist.end(),SCIM_PROP_WNN_MODESTATUS);
    if (it != m_proplist.end()) {
        if (m_conversion) it->set_label(_("Kanji"));
        else if (m_yosoku) it->set_label(_("Yosoku"));
        else it->set_label(m_preeditor->getModeName());
    }
    update_property(*it);
    it = find(m_proplist.begin(),m_proplist.end(),SCIM_PROP_WNN_CONVERSIONMODE);
    if (it != m_proplist.end()) {
        if (auto_conversion) it->set_label(_("AUTO"));
        else  it->set_label(_("REN"));
    }
    update_property(*it);
    register_properties(m_proplist);
}


/*!
    \fn HonokaInstance::updatePreEditor()
 */
void HonokaInstance::updatePreEditor()
{
    if (m_preeditor->getTextLength()) {
        if (auto_conversion && (m_preeditor->getTextLength() == m_preeditor->getPos()))
            autoConversion();
        else {
            show_preedit_string();
            update_preedit_string(m_preeditor->getText(),m_preeditor->getAttributeList());
            update_preedit_caret(m_preeditor->getPos());
        }
        if ((!m_conversion) && yosoku && wnn->isConnected() && (sType == "Wnn7") && (!auto_conversion)) {
            m_convList = wnn->getYosokuList(m_preeditor->getText());
            if (m_convList.count) {
                m_lookup_table.clear();
                for(unsigned int i = 0;i < m_convList.count;i ++) {
                    m_lookup_table.append_candidate(m_convList.kouho.at(i));
                }
                startLookup();
            } else {
                //m_lookup_table.clear();
                hide_lookup_table();
            }
        } else hide_lookup_table();
    } else {
        hide_preedit_string();
        hide_lookup_table();
    }
    if (mini_status) {
        update_aux_string(utf8_mbstowcs(m_preeditor->getModeName()));
        show_aux_string();
    } else {
        hide_aux_string();
    }

    updateProperty();
}
/*!
    \fn HonokaInstance::updateConversion()
 */
void HonokaInstance::updateConversion()
{
    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);
        show_lookup_table();
    } else {
        hide_lookup_table();
        hide_aux_string();
    }
    updateProperty();
}


bool HonokaInstance::process_key_event (const KeyEvent& key)
{
    if (key.is_key_release()) return(false);
    KeyEvent ke = key;
    if (ke.mask & SCIM_KEY_CapsLockMask) ke.mask -= SCIM_KEY_CapsLockMask;
    if (ke.mask & SCIM_KEY_NumLockMask) ke.mask -= SCIM_KEY_NumLockMask;
    if (ke.mask & SCIM_KEY_ScrollLockMask) ke.mask -= SCIM_KEY_ScrollLockMask;
    if (m_conversion) return(process_conversion_key_event(ke));
    else if (m_yosoku) return(process_yosoku_key_event(ke));
    else return(process_preedit_key_event(ke));
}


/*!
    \fn HonokaInstance::process_preedit_key_event(const KeyEvent &key)
 */
bool HonokaInstance::process_preedit_key_event(const KeyEvent &key)
{
    // PreEditorのキーイベントフック。
    if (m_preeditor->keyEventHook(key)) {
        updatePreEditor();
        return(true);
    } else

    // バッファが空では無い場合。
    if (m_preeditor->getTextLength()) {
        if (k_conversion_start.comp(key)) {
            startConversion(m_preeditor->getText(true));
            alp_count ++;
            return(true);
        } else
        if (k_commit.comp(key)) {
            if (auto_conversion) {
                commit_string(wnn->getText());
                wnn->reset();
            } else commit_string(m_preeditor->getText(true));
            m_preeditor->reset();
            updatePreEditor();
            return(true);
        } else
        if (k_forward.comp(key) || k_backward.comp(key)) {
            k_backward.comp(key) ? m_preeditor->setPos(m_preeditor->getPos() - 1) : m_preeditor->setPos(m_preeditor->getPos() + 1);
            updatePreEditor();
            return(true);
        } else
        if (k_home.comp(key) || k_end.comp(key)) {
            k_end.comp(key) ? m_preeditor->setPos(m_preeditor->getTextLength()) : m_preeditor->setPos(0);
            updatePreEditor();
            return(true);
        } else
        if ((k_backspace.comp(key)) || (k_delete.comp(key))) {
            k_backspace.comp(key) ? m_preeditor->backspace(): m_preeditor->del();
            updatePreEditor();
            return(true);
        } else
        if (k_convert_hiragana.comp(key)) {
            m_preeditor->kataHira();
            updatePreEditor();
            return(true);
        } else
        if (k_convert_katakana.comp(key)) {
            m_preeditor->hiraKata();
            updatePreEditor();
            return(true);
        } else
        if (k_convert_half.comp(key)) {
            m_preeditor->toHalf();
            updatePreEditor();
            return(true);
        } else
        if (k_convert_wide.comp(key)) {
            m_preeditor->toWide();
            updatePreEditor();
            return(true);
        } else
        if (k_select_yosoku.comp(key) && yosoku) {
            if ((m_convList.kType == YOSOKU) && (m_convList.count)) {
                return(process_yosoku_key_event(key));
            }
        }
    }

    // バッファの存在にかかわらず。
    if (k_cancel.comp(key)) {
        if (m_preeditor->cancelEvent()) {
            updatePreEditor();
            return(true);
        }
        if (m_preeditor->getTextLength()) {
            m_preeditor->reset();
        }
        updatePreEditor();
        return(true);
    }

    if (k_auto_conversion.comp(key)) {
        auto_conversion ? auto_conversion = false : auto_conversion = true;
        updatePreEditor();
        return(true);
    }

    if (m_preeditor->inputEvent(key)) {
        updatePreEditor();

        return(true);
    } else {
        // preeditorで処理できなかった場合はやはりcommitしてアプリケーションに返すべきだ。
        if (m_preeditor->getTextLength()) {
            if (auto_conversion) {
                commit_string(wnn->getText());
                wnn->reset();
            } else commit_string(m_preeditor->getText(true));
        }
        m_preeditor->reset();
        updatePreEditor();
    }

    return(false);
}

/*!
    \fn HonokaInstance::process_conversion_key_event(const KeyEvent &key)
 */
bool HonokaInstance::process_conversion_key_event(const KeyEvent &key)
{
    if ((key.code == SCIM_KEY_Shift_L) ||
        (key.code == SCIM_KEY_Shift_R) ||
        (key.code == SCIM_KEY_Control_L) ||
        (key.code == SCIM_KEY_Control_R) ||
        (key.code == SCIM_KEY_Alt_L) ||
        (key.code == SCIM_KEY_Alt_R) ||
        (key.code == SCIM_KEY_Super_L) ||
        (key.code == SCIM_KEY_Super_R) ||
        (key.code == SCIM_KEY_Hyper_L) ||
        (key.code == SCIM_KEY_Hyper_R)) return(true);

    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_preeditor->reset();
        wnn->reset();
        m_conversion = false;
        updatePreEditor();
        m_lookup = false;
        alp_count = 1;
        return(true);
    } else
    if (k_cancel.comp(key) || k_backspace.comp(key)) {
        wnn->reset();
        m_conversion = false;
        m_lookup = false;
        alp_count = 0;
        updatePreEditor();
        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);
        updateConversion();
        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->getResultList();
        if (alp == -1) {
            startLookup();
        } else m_lookup = false;
        updateConversion();
        alp_count = 1;
        return(true);
    } else
    if (k_conversion_rensou.comp(key) && ((sType == "Wnn7") || (sType == "Wnn8")) ) {
        m_convList = wnn->getResultList(wnn->getPos(),RENSOU);
        if (m_convList.count == 0) return(true);
        startLookup();
        updateConversion();
        alp_count = 1;
        return(true);
    } else
    if (k_conversion_ikeiji.comp(key) && ((sType == "Wnn7") || (sType == "Wnn8")) ) {
        m_convList = wnn->getResultList(wnn->getPos(),IKEIJI);
        if (m_convList.count == 0) return(true);
        startLookup();
        updateConversion();
        alp_count = 1;
        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->getResultList();
        if (alp == -1) {
            startLookup();
        } else m_lookup = false;
        updateConversion();
        alp_count = 1;
        return(true);
    } else
    if (k_convert_hiragana.comp(key) || k_convert_katakana.comp(key)) {
        WideString res = m_convList.Yomi;
        k_convert_hiragana.comp(key) ? m_preeditor->convKataHira(res) : m_preeditor->convHiraKata(res);
        for(unsigned int i = 0;i < m_convList.count;i ++) {
            if (res == m_convList.kouho[i]) {
                m_convList.pos = i;
                wnn->select(m_convList.pos);
                updateConversion();
                break;
            }
        }
        return(true);
    } else
    if (key.get_ascii_code()) {
        if (key.mask & (SCIM_KEY_AltMask | SCIM_KEY_ControlMask)) return(false);
            if (m_lookup && numkeyselect) {
                char numk[] = "1234567890";
                int numc = 0;
                bool numkey = false;
                for(;numk[numc]; ++ numc) {
                    if (key.get_ascii_code() == numk[numc]) {
                        numkey = true;
                        break;
                    }
                }
                if (numkey) {
                    if (m_lookup_table.get_current_page_size() < numc) return(true);
                    m_convList.pos = numc + m_lookup_table.get_current_page_start();
                    wnn->select(m_convList.pos);
                    wnn->setPos(wnn->getPos() + 1);
                    m_convList = wnn->getResultList();
                    updateConversion();
                    startLookup();
                    return(true);
                }
            }

        commit_string(wnn->getText());
        wnn->updateFrequency();
        m_preeditor->reset();
        wnn->reset();
        m_conversion = false;
        m_lookup = false;
        alp_count = 0;
        updatePreEditor();
        return(process_preedit_key_event(key));
    }


    return(true);
}



/*!
    \fn HonokaInstance::process_yosoku_key_event(const KeyEvent &key)
 */
bool HonokaInstance::process_yosoku_key_event(const KeyEvent &key)
{
    if (!m_yosoku) {
        m_yosoku = true;
        update_preedit_string(m_convList.kouho.at(m_convList.pos));
        update_preedit_caret(0);
        show_preedit_string();
        updateProperty();
        return(true);
    }

    if (k_lookup_pageup.comp(key)) {
        lookup_table_page_up();
        return(true);
    } else
    if (k_lookup_pagedown.comp(key)) {
        lookup_table_page_down();
        return(true);
    } else
    if (k_conversion_next.comp(key) || k_conversion_prev.comp(key) || k_select_yosoku.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;
        m_lookup_table.set_cursor_pos(m_convList.pos);
        update_lookup_table(m_lookup_table);
        update_preedit_string(m_convList.kouho.at(m_convList.pos));
        update_preedit_caret(0);
//        select_candidate((unsigned int)m_convList.pos);
        updateProperty();
        return(true);
    } else
    if (k_commit.comp(key)) {
        m_yosoku = false;
        commit_string(m_convList.kouho.at(m_convList.pos));
        m_preeditor->reset();
        updatePreEditor();
        return(true);
    } else
    if (k_cancel.comp(key) || k_backspace.comp(key)) {
        m_yosoku = false;
        updatePreEditor();
        return(true);
    }
    if (!key.get_ascii_code()) return(true);
    if ((!(key.is_control_down() || key.is_alt_down() || key.is_shift_down())) && numkeyselect) {
        char numk[] = "1234567890";
        for(int numc = 0;numk[numc]; ++ numc) {
            if (key.get_ascii_code() == numk[numc]) {
                if (m_lookup_table.get_current_page_size() > numc)
                    select_candidate((unsigned int)numc);
                return(true);
            }
        }
    }

    m_yosoku = false;
    commit_string(m_convList.kouho.at(m_convList.pos));
    m_preeditor->reset();
    updatePreEditor();
    return(process_preedit_key_event(key));
}



void HonokaInstance::move_preedit_caret (unsigned int pos)
{
    //if (!m_conversion) m_preeditor->setPos(pos);
    //update_preedit_caret(pos);
}

void HonokaInstance::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);
    if (m_convList.kType != YOSOKU) {
        update_preedit_string(wnn->getText(),wnn->getAttributeList());
        update_preedit_caret(wnn->getCaretPos());
    } else {
        update_preedit_string(m_convList.kouho.at(m_convList.pos));
        update_preedit_caret(0);
        if (!m_yosoku) {
            // マウスで選択した場合は予測選択モードに突入。
            m_yosoku = true;
            show_preedit_string();
            updateProperty();
        }
    }
    m_lookup_table.set_cursor_pos(m_convList.pos);
    update_lookup_table(m_lookup_table);
}

void HonokaInstance::update_lookup_table_page_size (unsigned int page_size)
{
    m_lookup_table.set_page_size (page_size);
}

void HonokaInstance::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 HonokaInstance::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 HonokaInstance::reset ()
{
    // Qt-immodule+scim-qtimmではこのメソッドが大量に呼ばれるようだが、他ではどうなのか?。
    alp_count = 0;
    m_conversion = false;
    m_lookup = false;
    wnn->reset();
    m_preeditor->reset();
    //if (wnn->isConnected()) wnn->wnnDisconnect();
    //wnn->wnnConnect(String("scim-wnn"),host,rc,sType,0);
    //updatePreEditor();
}

void HonokaInstance::focus_in ()
{
    if (!m_conversion) updatePreEditor();
    else updateProperty();
}

void HonokaInstance::focus_out ()
{
    if (m_conversion) {
        commit_string(wnn->getText());
        wnn->updateFrequency();
        wnn->reset();
        m_conversion = false;
        m_lookup = false;
        alp_count = 0;
    } else if (m_preeditor->getTextLength()) {
        commit_string(m_preeditor->getText(true));
    }
    m_preeditor->reset();
    updatePreEditor();
}

void HonokaInstance::trigger_property (const String &property)
{
    String s = SCIM_PROP_WNN_INPUTMODE;
    if ((property.length() > s.length()) && (property.substr(0,s.length()) == s)) {
        changePreEditor(property.substr(s.length() + 1));
        updateProperty();
    }
    s = SCIM_PROP_WNN_CONVERSIONMODE;
    if (property == s) {
        auto_conversion ? auto_conversion = false : auto_conversion = true;
        updatePreEditor();
    }
}






/*!
    \fn HonokaInstance::startConversion(WideString s)
 */
void HonokaInstance::startConversion(WideString s)
{
    // 一度lookupは消しておこう。
    m_lookup = false;
    m_lookup_table.clear();
    hide_lookup_table();

    hide_aux_string();
    if (!wnn->isConnected()) {
        if (!wnn->connect()) {
            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.kouho.clear();
    m_convList = wnn->getResultList();
    m_conversion = true;

    alp_count = 1;

    show_preedit_string();
    update_preedit_string(wnn->getText(),wnn->getAttributeList());
    update_preedit_caret(wnn->getCaretPos());
    if (alp == -1) {
        startLookup();
    }
    updateProperty();
}


/*!
    \fn HonokaInstance::autoConversion()
 */
void HonokaInstance::autoConversion()
{
    if (!wnn->isConnected()) {
        if (!wnn->connect()) {
            update_aux_string(utf8_mbstowcs(String(_("could not connect to jserver."))));
            show_aux_string();
            show_preedit_string();
            update_preedit_string(m_preeditor->getText(),m_preeditor->getAttributeList());
            update_preedit_caret(m_preeditor->getPos());
            return;
        }
    }

    wnn->reset();
    wnn->setYomiText(m_preeditor->getText(true));
    if (wnn->ren_conversion() == -1) {
        update_aux_string(utf8_mbstowcs(String(_("could not connect to jserver."))));
        show_aux_string();
        show_preedit_string();
        update_preedit_string(m_preeditor->getText(),m_preeditor->getAttributeList());
        update_preedit_caret(m_preeditor->getPos());
        return;
    }

    show_preedit_string();
    update_preedit_string(wnn->getText());
    update_preedit_caret(wnn->getText().size());
}


/*!
    \fn HonokaInstance::createLookupTable(ResultList cList)
 */
void HonokaInstance::createLookupTable(ResultList cList)
{
    hide_lookup_table();
    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 HonokaInstance::startLookup()
 */
void HonokaInstance::startLookup()
{
    createLookupTable(m_convList);
    if (m_convList.count == 0) return;
    m_lookup = true;
    switch(m_convList.kType) {
        case IKEIJI: {
            update_aux_string(utf8_mbstowcs(String(_("Ikeiji lookup result"))));
            break;
        }
        case RENSOU: {
            update_aux_string(utf8_mbstowcs(String(_("association lookup result"))));
            break;
        }
        case YOSOKU: {
            update_aux_string(utf8_mbstowcs(String(_("yosoku lookup result"))));
            break;
        }
        default: {
            update_aux_string(utf8_mbstowcs(String(_("lookup result"))));
            break;
        }
    }
    show_aux_string();
    show_lookup_table();
}