/***************************************************************************
 *   Copyright (C) 2005 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 "asciiinput.h"

#include <asciiplugin.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

#include "compose.h"

AsciiInput::AsciiInput(ConfigPointer cfg) : PreEditor(cfg)
{
    scim_string_to_key_list(lowProprotyKey,cfg->read(HONOKA_CONFIG_ASCIIINPUT_LOW_PRIORITY_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_LOW_PRIORITY_KEY)));
    scim_string_to_key_list(autoCommitKey,cfg->read(HONOKA_CONFIG_ASCIIINPUT_AUTO_COMMIT_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_AUTO_COMMIT_KEY)));
    autoCommit = cfg->read(HONOKA_CONFIG_ASCIIINPUT_AUTO_COMMIT,HONOKA_DEFAULT_ASCIIINPUT_AUTO_COMMIT);
    
    scim_string_to_key_list(compose_key,cfg->read(HONOKA_CONFIG_ASCIIINPUT_COMPOSE_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_COMPOSE_KEY)));
    scim_string_to_key_list(dead_abovering,cfg->read(HONOKA_CONFIG_ASCIIINPUT_ABOVERING_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_ABOVERING_KEY)));
    scim_string_to_key_list(dead_acute,cfg->read(HONOKA_CONFIG_ASCIIINPUT_ACUTE_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_ACUTE_KEY)));
    scim_string_to_key_list(dead_cedilla,cfg->read(HONOKA_CONFIG_ASCIIINPUT_CEDILLA_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_CEDILLA_KEY)));
    scim_string_to_key_list(dead_circumflex,cfg->read(HONOKA_CONFIG_ASCIIINPUT_CIRCUMFLEX_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_CIRCUMFLEX_KEY)));
    scim_string_to_key_list(dead_diaeresis,cfg->read(HONOKA_CONFIG_ASCIIINPUT_DIAERESIS_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_DIAERESIS_KEY)));
    scim_string_to_key_list(dead_doubleacute,cfg->read(HONOKA_CONFIG_ASCIIINPUT_DOUBLEACUTE_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_DOUBLEACUTE_KEY)));
    scim_string_to_key_list(dead_grave,cfg->read(HONOKA_CONFIG_ASCIIINPUT_GRAVE_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_GRAVE_KEY)));
    scim_string_to_key_list(dead_tilde,cfg->read(HONOKA_CONFIG_ASCIIINPUT_TILDE_KEY,String(HONOKA_DEFAULT_ASCIIINPUT_TILDE_KEY)));


    compose = false;
    composeKey1.code = 0;
    composeKey2.code = 0;
}


AsciiInput::~AsciiInput()
{
}

/*!
    \fn AsciiInput::getModeName()
 */
String AsciiInput::getModeName()
{
    if (compose) return String(_("Cc"));
    return String(_("Aa"));
}

/*!
    \fn AsciiInput::getName()
 */
String AsciiInput::getName()
{
    return String("AsciiInput");
}

/*!
    \fn AsciiInput::getPropertyName()
 */
String AsciiInput::getPropertyName()
{
    return String(_("AsciiInput"));
}


/*!
    \fn AsciiInput::inputEvent(const KeyEvent &key)
 */
bool AsciiInput::inputEvent(const KeyEvent &key)
{
    return keyEvent(key);
}



/*!
    \fn AsciiInput::keyEventHook(const KeyEvent &key)
 */
bool AsciiInput::keyEventHook(const KeyEvent &key)
{
    if (key.is_key_release()) return false;
    if ((key.code == SCIM_KEY_Multi_key) || (compose_key.comp(key))) {
        composeKey1.code = 0;
        composeKey2.code = 0;
        if (compose) {
            compose = false;
        } else compose = true;
        return true;
    } else
    if ((key.code == SCIM_KEY_dead_abovering) ||
        (key.code == SCIM_KEY_dead_acute) ||
        (key.code == SCIM_KEY_dead_cedilla) ||
        (key.code == SCIM_KEY_dead_circumflex) ||
        (key.code == SCIM_KEY_dead_diaeresis) ||
        (key.code == SCIM_KEY_dead_doubleacute) ||
        (key.code == SCIM_KEY_dead_grave) ||
        (key.code == SCIM_KEY_dead_tilde)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = key.code;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = key.code;
        }
    } else
    if (dead_abovering.comp(key)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = SCIM_KEY_dead_abovering;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = SCIM_KEY_dead_abovering;
        }
    } else
    if (dead_acute.comp(key)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = SCIM_KEY_dead_acute;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = SCIM_KEY_dead_acute;
        }
    } else
    if (dead_cedilla.comp(key)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = SCIM_KEY_dead_cedilla;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = SCIM_KEY_dead_cedilla;
        }
    } else
    if (dead_circumflex.comp(key)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = SCIM_KEY_dead_circumflex;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = SCIM_KEY_dead_circumflex;
        }
    } else
    if (dead_diaeresis.comp(key)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = SCIM_KEY_dead_diaeresis;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = SCIM_KEY_dead_diaeresis;
        }
    } else
    if (dead_doubleacute.comp(key)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = SCIM_KEY_dead_doubleacute;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = SCIM_KEY_dead_doubleacute;
        }
    } else
    if (dead_grave.comp(key)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = SCIM_KEY_dead_grave;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = SCIM_KEY_dead_grave;
        }
    } else
    if (dead_tilde.comp(key)) {
        if ((!compose) || ((compose) && (composeKey1.code == 0))) {
            compose = true;
            composeKey1.code = SCIM_KEY_dead_tilde;
            composeKey2.code = 0;
            return true;
        } else {
            composeKey2.code = SCIM_KEY_dead_tilde;
        }
    }

    // composeKey2まで揃った場合はここでもう挿入してしまう。
    if ((compose) && (composeKey2.code != 0)) {
        insertComposeKey(composeKey1,composeKey2);
        return true;
    }

    if (lowProprotyKey.comp(key)) return false;
    else return keyEvent(key);
}




/*!
    \fn AsciiInput::keyEvent(const KeyEvent &key)
 */
bool AsciiInput::keyEvent(const KeyEvent &key)
{
    if (PreEditor::isThrough(key)) return true;

    if ((compose)) {
        if (composeKey1.code == 0) {
            composeKey1 = key.code;
            return true;
        } else {
            if (composeKey2.code == 0) composeKey2.code = key.code;
            insertComposeKey(composeKey1,composeKey2);
            return true;
        }
    }


    if (autoCommit) {
        if (autoCommitKey.comp(key)) {
            if (isPrintable(key))
                setCommitString(text.substr(0,pos) + key.get_unicode_code());
            else setCommitString(text.substr(0,pos));
            reset();
            pos = 0;
            if (((key.code == SCIM_KEY_Return) ||
                 (key.code == SCIM_KEY_Linefeed) ||
                 (key.code == SCIM_KEY_Tab)) && 
                ((!key.is_alt_down()) &&
                 (!key.is_control_down()) &&
                 (!key.is_shift_down()))) return false;
            else return true;
        }
    }

    if (isPrintable(key)) {
        text = text.substr(0,pos) + key.get_unicode_code() + text.substr(pos);
        pos ++;
        return true;
    }
    return false;
}


/*!
    \fn AsciiInput::insertComposeKey(KeyEvent &k1,KeyEvent &k2)
 */
void AsciiInput::insertComposeKey(KeyEvent &k1,KeyEvent &k2)
{
    compose = false;
    String k1s,k2s;
    if (!scim_key_to_string(k1s,k1)) return;
    if (!scim_key_to_string(k2s,k2)) return;
    for(unsigned int i = 0;multikey_table[i].first != "";i ++) {
        if ((k1s == multikey_table[i].first) && (k2s == multikey_table[i].second)) {
            text = text.substr(0,pos) + multikey_table[i].character + text.substr(pos);
            pos ++;
        } else continue;
    }
    composeKey1.code = 0;
    composeKey2.code = 0;
}
