Newer
Older
scim-wnn / scim-wnn / src / romkan.cpp
/***************************************************************************
 *   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.             *
 ***************************************************************************/
#include "romkan.h"
#include "romkan_table.h"

#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

Romkan::Romkan(ConfigPointer cfg) : PreEditor(cfg)
{
    reset();
    iconvert.set_encoding ("EUC-JP");
    mode = ROMA;
}


Romkan::~Romkan()
{
}



/*!
    \fn Romkan::setPos(int p)
 */
void Romkan::setPos(int p)
{
    if (p < 0) p = 0;
    else if (p > getTextLength()) p = getTextLength();
    pos = p;
    buf.clear();
}


/*!
    \fn Romkan::clear()
 */
void Romkan::clear()
{
    text.clear();
    buf.clear();
}


/*!
    \fn Romkan::insert(char k)
 */
WideString Romkan::insert(char k)
{
    String s;
    s = k;
    if (k == 0) return(text);
    switch(mode) {
        case LATIN: {
            buf.clear();
            text = text.substr(0,pos) + utf8_mbstowcs(s) + text.substr(pos);
            pos ++;
            return(text);
            break;
        }
        case WLATIN: {
            buf.clear();
            WideString w = utf8_mbstowcs(s);
            convHanZen(w);
            text = text.substr(0,pos) + w + text.substr(pos);
            pos ++;
            return(text);
            break;
        }
        case ROMA: {
            if (k == 'q') {
                mode = LATIN;
                buf.clear();
                return(text);
                break;
            } else if (k == 'Q') {
                mode = WLATIN;
                buf.clear();
                return(text);
                break;
            }
            buf += k;
            text = text.substr(0,pos) + utf8_mbstowcs(s) + text.substr(pos);
            pos ++;
            return(eval());
            break;
        }
    }
    return(text);
}


/*!
    \fn Romkan::eval()
 */
WideString Romkan::eval()
{
    // エヴァる。

    if (buf.length() == 2) {

        // n+母音以外は「ん」+子音である
        // ただし、nyは除外である。
        if (buf[0] == 'n') {
            String b = "aiueoy";
            bool boin = false;
            for(unsigned int i = 0;i < b.length();i ++) {
                if (buf[1] == b[i]) boin = true;
            }
            if (!boin) {
                WideString w;
                iconvert.convert(w,String("ん"));
                text = text.substr(0,pos - 2) + w + text.substr(pos - 1);
                buf = buf.substr(buf.length() - 1,1);
            }
        }

        // 同じ文字が2文字続くとそれは「っ」+子音である。母音の連打がbufに残ってはいないはず。
        else if (buf[0] == buf[1]) {
            WideString w;
            iconvert.convert(w,String("っ"));
            text = text.substr(0,pos - 2) + w + text.substr(pos - 1);
            buf = buf.substr(buf.length() - 1,1);
            return(text);
        }
    }

    // テーブルを検索して入力する。
    unsigned int i = 0;
    while(strcmp(RomkanTable[i],"") != 0) {
        if (buf == String(RomkanTable[i])) {
            if (String(RomkanTable[i + 1]) == "") {
                return(text); // 保留する。
            }
            WideString w;
            iconvert.convert(w,String(RomkanTable[i + 1]));
            text = text.substr(0,pos - buf.length()) + w + text.substr(pos);
            pos = pos - buf.length() + w.length();
            buf.clear();
            return(text);
        }
        i += 2;
    }
    if (buf.length()) buf = buf.substr(1);
    return(text);
}




/*!
    \fn Romkan::reset()
 */
void Romkan::reset()
{
    clear();
    pos = 0;
    mode = ROMA;
}


/*!
    \fn Romkan::getText(bool hosei)
 */
WideString Romkan::getText(bool hosei)
{
    if (hosei) {
        if (buf.length()) {
            if (buf.substr(buf.length() - 1,1) == "n") {
                WideString w;
                iconvert.convert(w,String("ん"));
                text = text.substr(0,pos - 1) + w;
            }
        }
    }
    return(text);
}


/*!
    \fn Romkan::backspace()
 */
void Romkan::backspace()
{
    if (getPos() == 0) return;
    text = text.substr(0,pos - 1) + text.substr(pos);
    setPos(pos - 1);
    // BSは小バッファもBSするゾ。
    if (buf.length()) buf = buf.substr(0,buf.length() - 1);
}



/*!
    \fn Romkan::del()
 */
void Romkan::del()
{
    if (getPos() == getTextLength()) return;
    text = text.substr(0,pos) + text.substr(pos + 1);
}



/*!
    \fn Romkan::hiraKata()
 */
void Romkan::hiraKata()
{
    convHiraKata(text);
}


/*!
    \fn Romkan::kataHira()
 */
void Romkan::kataHira()
{
    convKataHira(text);
}


/*!
    \fn Romkan::keyEventHook(const KeyEvent &key)
 */
bool Romkan::keyEventHook(const KeyEvent &key)
{
    if ((isprint(key.code)) && ((mode == LATIN) || (mode == WLATIN))) {
        if (!(key.mask & (SCIM_KEY_AltMask | SCIM_KEY_ControlMask))) {
            insert(key.get_ascii_code());
            return(true);
        }
    }

    if (!buf.length()) return(false);
    if (buf[buf.length() - 1] == 'Z') {
        if (key.code == SCIM_KEY_space) {
            insert(' ');
            return(true);
        }
    }
    return(false);
}


/*!
    \fn Romkan::getModeName()
 */
String Romkan::getModeName()
{
    switch(mode) {
        case ROMA: {
            return(String(_("Roma-Kana")));
            break;
        }
        case LATIN: {
            return(String(_("Latin")));
            break;
        }
        case WLATIN: {
            return(String(_("Wide Latin")));
            break;
        }
    }
}


/*!
    \fn Romkan::cancelEvent()
 */
bool Romkan::cancelEvent()
{
    if ((mode == LATIN) || (mode == WLATIN)) {
        mode = ROMA;
        return(true);
    }
    return(false);
}


/*!
    \fn Romkan::inputEvent(const KeyEvent &key)
 */
bool Romkan::inputEvent(const KeyEvent &key)
{
    if (isprint(key.code) && (!key.is_alt_down()) && (!key.is_control_down())) {
        if (key.get_ascii_code() == ' ') return(false);
        insert(key.get_ascii_code());
        return(true);
    }
    return(false);
}