/***************************************************************************
* 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 "nicolainput.h"
#include <sys/time.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
// プライグイン化のおまじないです。
HonokaPluginRegister(NicolaInput);
HonokaPluginSetup(NicolaInput);
HonokaSetupCorePage *NicolaInput::setup()
{
HonokaSetupPage *page = new HonokaSetupPage(_("Nicola-plugin"),"","");
page->append(new HonokaSetupKeyItem(
_("_Left KANA-Shift keys:"),
HONOKA_CONFIG_NICOLAINPUT_LSHIFT,
"",
HONOKA_DEFAULT_NICOLAINPUT_LSHIFT
));
page->append(new HonokaSetupKeyItem(
_("_Right KANA-Shift keys:"),
HONOKA_CONFIG_NICOLAINPUT_RSHIFT,
"",
HONOKA_DEFAULT_NICOLAINPUT_RSHIFT
));
page->append(new HonokaSetupIntItem(
_("_Simultaneously press timer:"),
HONOKA_CONFIG_NICOLAINPUT_SPTIMER,
"",
HONOKA_DEFAULT_NICOLAINPUT_SPTIMER,
0,199
));
page->append(new HonokaSetupFileItem(
_("Nicola _table: "),
HONOKA_CONFIG_NICOLAINPUT_TABLE_FILE,
_("input the path of Nicola table file."),
HONOKA_DEFAULT_NICOLAINPUT_TABLE_FILE
));
HonokaSetupPage *sc = new HonokaSetupPage(_("shortcut keys: "),"","");
sc->append(new HonokaSetupKeyItem(
_("Nicola input: "),
String(HONOKA_CONFIG_KEY_PREEDITOR_PREFIX) + String("/Nicola"),
"",
""
));
page->append(sc);
return page;
};
namespace Honoka {
struct {
KeyCode key;
char noShift[6];
char leftShift[6];
char rightShift[6];
} _nicolaTable[] = {
{SCIM_KEY_1,"1","?",""},
{SCIM_KEY_2,"2","/",""},
{SCIM_KEY_3,"3","~",""},
{SCIM_KEY_4,"4","「",""},
{SCIM_KEY_5,"5","」",""},
{SCIM_KEY_6,"6","","["},
{SCIM_KEY_7,"7","","]"},
{SCIM_KEY_8,"8","","("},
{SCIM_KEY_9,"9","",")"},
{SCIM_KEY_0,"0","","『"},
{SCIM_KEY_minus,"-","","』"},
{SCIM_KEY_backslash,"\\","",""},
{SCIM_KEY_q,"。","ぁ",""},
{SCIM_KEY_w,"か","え","が"},
{SCIM_KEY_e,"た","り","だ"},
{SCIM_KEY_r,"こ","ゃ","ご"},
{SCIM_KEY_t,"さ","れ","ざ"},
{SCIM_KEY_y,"ら","ぱ","よ"},
{SCIM_KEY_u,"ち","ぢ","に"},
{SCIM_KEY_i,"く","ぐ","る"},
{SCIM_KEY_o,"つ","づ","ま"},
{SCIM_KEY_p,",","ぴ","ぇ"},
{SCIM_KEY_at,"、","",""},
{SCIM_KEY_bracketleft,"゛","","゜"},
{SCIM_KEY_a,"う","を",""},
{SCIM_KEY_s,"し","あ","じ"},
{SCIM_KEY_d,"て","な","で"},
{SCIM_KEY_f,"け","ゅ","げ"},
{SCIM_KEY_g,"せ","も","ぜ"},
{SCIM_KEY_h,"は","ば","み"},
{SCIM_KEY_j,"と","ど","お"},
{SCIM_KEY_k,"き","ぎ","の"},
{SCIM_KEY_l,"い","ぽ","ょ"},
{SCIM_KEY_semicolon,"ん","","っ"},
{SCIM_KEY_z,".","ぅ",""},
{SCIM_KEY_x,"ひ","ー","び"},
{SCIM_KEY_c,"す","ろ","ず"},
{SCIM_KEY_v,"ふ","や","ぶ"},
{SCIM_KEY_b,"へ","ぃ","べ"},
{SCIM_KEY_n,"め","ぷ","ぬ"},
{SCIM_KEY_m,"そ","","ゆ"},
{SCIM_KEY_comma,"ね","ぺ","む"},
{SCIM_KEY_period,"ほ","ぼ","わ"},
{SCIM_KEY_slash,"・","","ぉ"},
{SCIM_KEY_NullKey,"","",""} // terminator
};
}
NicolaInput::NicolaInput(ConfigPointer cfg) : PreEditor(cfg)
{
bkt = 0;
delay = cfg->read(HONOKA_CONFIG_NICOLAINPUT_SPTIMER,HONOKA_DEFAULT_NICOLAINPUT_SPTIMER);
scim_string_to_key_list(LShiftKey,cfg->read(HONOKA_CONFIG_NICOLAINPUT_LSHIFT,String(HONOKA_DEFAULT_NICOLAINPUT_LSHIFT)));
scim_string_to_key_list(RShiftKey,cfg->read(HONOKA_CONFIG_NICOLAINPUT_RSHIFT,String(HONOKA_DEFAULT_NICOLAINPUT_RSHIFT)));
String table = cfg->read(HONOKA_CONFIG_NICOLAINPUT_TABLE_FILE,String(HONOKA_DEFAULT_NICOLAINPUT_TABLE_FILE));
LShift = false;
RShift = false;
if (table.length()) loadTable(table);
if (!keymap.size()) {
for(unsigned int i = 0;_nicolaTable[i].key != SCIM_KEY_NullKey;i ++) {
NicolaKey k;
k.noShift = utf8_mbstowcs(_nicolaTable[i].noShift);
k.leftShift = utf8_mbstowcs(_nicolaTable[i].leftShift);
k.rightShift = utf8_mbstowcs(_nicolaTable[i].rightShift);
keymap.insert(pair<KeyEvent,NicolaKey>(_nicolaTable[i].key,k));
}
}
vsc = utf8_mbstowcs(String("゛"));
svsc = utf8_mbstowcs(String("゜"));
vs1 = utf8_mbstowcs(String("かきくけこさしすせそたちつてとはひふへほぱぴぷぺぽ"));
vs2 = utf8_mbstowcs(String("がぎぐげござじずぜぞだぢづでどばびぶべぼばびぶべぼ"));
svs1 = utf8_mbstowcs(String("はひふへほばびぶべぼ"));
svs2 = utf8_mbstowcs(String("ぱぴぷぺぽぱぴぷぺぽ"));
}
NicolaInput::~NicolaInput()
{
}
/*!
\fn Honoka::NicolaInput::loadTable(const String &filename)
*/
bool Honoka::NicolaInput::loadTable(const String &filename)
{
FILE *f = fopen(filename.c_str(),"r");
if (!f) {
#ifdef HONOKA_DATADIR
String fn = HONOKA_DATADIR;
fn += "/" + filename;
f = fopen(fn.c_str(),"r");
if (!f) return false;
#else
return false;
#endif
}
while(-1) {
char s[256];
if(fgets(s,256,f) == NULL) break;
String l = s;
unsigned int p = 0;
vector<String> t;
for(unsigned int i = 0;i < l.length();i ++) {
if ((l[i] == '\t') || (l[i] == '\n')) {
t.push_back(l.substr(p,i - p));
p = i + 1;
}
}
if (p < l.length()) t.push_back(l.substr(p));
if (t.size() != 4) continue;
KeyEvent k;
NicolaKey n;
n.noShift = utf8_mbstowcs(t[1]);
n.leftShift = utf8_mbstowcs(t[2]);
n.rightShift = utf8_mbstowcs(t[3]);
scim_string_to_key(k,t[0]);
keymap.insert(pair<KeyEvent,NicolaKey>(k,n));
}
fclose(f);
if (keymap.size()) return true;
return false;
}
/*!
\fn NicolaInput::getModeName()
*/
String NicolaInput::getModeName()
{
return String(_("KANA"));
}
/*!
\fn NicolaInput::getName()
*/
String NicolaInput::getName()
{
return String("Nicola");
}
/*!
\fn NicolaInput::getPropertyName()
*/
String NicolaInput::getPropertyName()
{
return String(_("NICOLA"));
}
/*!
\fn NicolaInput::inputEvent(const KeyEvent &key)
*/
bool NicolaInput::inputEvent(const KeyEvent &key)
{
if (PreEditor::isThrough(key)) return true;
map<KeyEvent,NicolaKey>::iterator it = keymap.find(key);
if (it == keymap.end()) {
if (isPrintable(key)) {
text = text.substr(0,pos) + key.get_unicode_code() + text.substr(pos);
pos ++;
return true;
} else return false;
}
WideString w;
if (LShift) w = it->second.leftShift;
else if (RShift) w = it->second.rightShift;
else w = it->second.noShift;
bk = key;
if (w == vsc) {
for(unsigned int i = 0;i < vs1.length();i ++) {
if (vs1[i] == text[pos - 1]) text = text.substr(0,pos - 1) + vs2[i] + text.substr(pos);
}
} else
if (w == svsc) {
for(unsigned int i = 0;i < svs1.length();i ++) {
if (svs1[i] == text[pos - 1]) text = text.substr(0,pos - 1) + svs2[i] + text.substr(pos);
}
} else
if (w.length()) {
struct timeval tv;
gettimeofday(&tv, NULL);
bkt = (tv.tv_sec * 1000000) + tv.tv_usec;
text = text.substr(0,pos) + w + text.substr(pos);
pos ++;
}
return true;
//return false;
}
/*!
\fn NicolaInput::keyEventHook(const KeyEvent &key)
*/
bool NicolaInput::keyEventHook(const KeyEvent &key)
{
for(unsigned int i = 0;i < RShiftKey.size();i ++) {
if (key.code == RShiftKey[i].code) {
if (key.is_key_press()) {
RShift = true;
struct timeval tv;
gettimeofday(&tv, NULL);
long t = (tv.tv_sec * 1000000) + tv.tv_usec;
if ((t - bkt) < (delay * 1000)) {
backspace();
return(inputEvent(bk));
}
}
else if (key.is_key_release()) RShift = false;
return true;
}
}
for(unsigned int i = 0;i < LShiftKey.size();i ++) {
if (key.code == LShiftKey[i].code) {
if (key.is_key_press()) {
LShift = true;
struct timeval tv;
gettimeofday(&tv, NULL);
long t = (tv.tv_sec * 1000000) + tv.tv_usec;
if ((t - bkt) < (delay * 1000)) {
backspace();
return(inputEvent(bk));
}
}
else if (key.is_key_release()) LShift = false;
return true;
}
}
return false;
}