// KKConv 仮名漢字変換
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ctype.h>
#include <gdk/gdk.h>
#include "xim.h"
#include "convdisp.h"
#include "kkconv.h"
#include "rkconv.h"
// rkmap.h は一度だけどこかでインクルード
#include "rkmap.h"
#ifndef __GNUC__
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# endif
#endif
// キャラクタコード32から、
//このソースはEUCで書かれている。
static char *ascii_wide_tab[]={
0,"!","”","#","$","%","&","’",
"(",")","*","+",",","−",".","/",
"0","1","2","3","4","5","6","7",
"8","9",":",";","<","=",">","?",
"@","A","B","C","D","E","F","G",
"H","I","J","K","L","M","N","O",
"P","Q","R","S","T","U","V","W",
"X","Y","Z","[","\","]","^","_",
"‘","a","b","c","d","e","f","g",
"h","i","j","k","l","m","n","o",
"p","q","r","s","t","u","v","w",
"x","y","z","{","|","}","〜",
};
/*
modeがINPUT_MODE_WIDEのときは英数で全角化する。
INPUT_MODE_HIRAのときは日本語の全角にする。
*/
cchar ascii_to_wide(cchar a)
{
if (a < 256 && isprint(a)) {
unsigned char *b = (unsigned char *)ascii_wide_tab[a-32];
if (!b) {
return 0;
}
cchar c;
c = ((((int)b[0])<<8)+(int)b[1])&0x7f7f;
return c;
}
return 0;
}
void hirakana_conv(jstring_t *dst, jstring_t *s)
{
jstring_t::iterator i,j;
for (i = s->begin(); i != s->end(); i++) {
cchar c, d;
c = *i;
j = i;
j++;
if (j == s->end()) {
d = 0;
} else {
d = *j;
}
if (c >= 0x2400 && c < 0x2600) {
if (c < 0x24ff) {
// 平仮名から片仮名
if (c == 0x2426 && d == 0x212b) {
// う゛
c = 0x2574;
i++;
} else {
c += 256;
}
} else {
// 片仮名から平仮名
if (c == 0x2574) {
dst->push_back(0x2426);
c = 0x212b;
} else {
c -= 256;
}
}
}
dst->push_back(c);
}
}
int jstring_get_ctext_len(jstring_t *s)
{
jstring_t::iterator i;
bool jp_mode;
int len;
int cur;
jp_mode = false;
len = 0;
for (i = s->begin(); i != s->end(); i++) {
cur = *i;
if (!(cur & 0xff00)) {
// 2byte文字ではない
if (jp_mode) {
jp_mode = false;
len += 4;
} else {
len += 1;
}
} else {
// 2byte文字だ、
if (jp_mode) {
len += 2;
} else {
len += 6;
jp_mode = true;
}
}
}
if (jp_mode) {
len += 3;
}
return len;
}
char *jstring_to_ctext(jstring_t *s)
{
int len;
char *t;
len = jstring_get_ctext_len(s);
t = (char *)malloc(len+1);
t[len] = 0;
jstring_t::iterator i;
bool jp_mode=false;
int cur,j=0;
for (i = s->begin(); i != s->end(); i++) {
cur = *i;
if (!(cur & 0xff00)) {
// 1byte文字
if (jp_mode) {
t[j++] = 0x1b;
t[j++] = 0x28;
t[j++] = 0x42;
jp_mode = false;
}
t[j++] = cur & 0xff;
} else {
if (!jp_mode) {
jp_mode = true;
t[j++] = 0x1b;
t[j++] = 0x24;
t[j++] = 0x29;
t[j++] = 0x42;
}
t[j++] = (cur >> 8)|0x80;
t[j++] = (cur & 0xff)|0x80;
}
}
if (jp_mode) {
t[j++] = 0x1b;
t[j++] = 0x28;
t[j++] = 0x42;
}
return t;
}
char *jstring_to_str(jstring_t *s)
{
jstring_t::iterator i;
int l=0;
char *c;
for (i = s->begin(); i!= s->end(); i++) {
l++;
if (*i > 256) {
l ++;
}
}
c = (char *)malloc(l+1);
c[l] = 0;
l = 0;
for (i = s->begin() ; i!= s->end(); i++) {
if (*i < 256) {
c[l] = *i;
l++;
} else {
c[l] = ((*i)>>8)|0x80;
c[l+1] = ((*i)&0xff)|0x80;
l+=2;
}
}
return c;
}
// XXX 動作は未検証
void ctext_to_jstring(char *c, jstring_t *s)
{
bool jp_mode = false;
while (*c) {
if (jp_mode) {
if (*c != 0x1b) {
s->push_back(c[0]*256+c[1]);
} else {
jp_mode = false;
c++;c++;c++;
}
} else {
if (*c != 0x1b) {
s->push_back(*c);
c++;
} else {
jp_mode = true;
c++;c++;c++;
}
}
}
}
void print_jstring(jstring_t *s)
{
jstring_t::iterator i;
printf("length=%d : ", s->size());
int ch;
char buf[3];
for (i = s->begin(); i != s->end(); i++) {
ch = *i;
buf[1]=0;
buf[2]=0;
if (ch < 256) {
buf[0]=ch;
} else {
buf[1]=(ch & 255)|0x80;
buf[0]=((ch>>8)&255)|0x80;
}
printf(buf);
}
printf("\n");
}
void erase_jstring(jstring_t *s)
{
s->erase(s->begin(), s->end());
}
void append_jstring(jstring_t *d, jstring_t *s)
{
jstring_t::iterator i;
for (i = s->begin(); i !=s->end(); i++) {
d->push_back(*i);
}
}
// EUCとJISの両方に対応
void str_to_jstring(jstring_t *d, char *s)
{
int i,len;
bool inJis= false;
len = strlen(s);
for (i = 0; i < len; i++) {
if (s[i] == 0x1b) {
if (s[i+1] == 0x24 && s[i+2]== 0x42) {
inJis = true;
} else if (s[i+1] == 0x28 && s[i+2] == 0x42) {
inJis = false;
}
i += 2;
} else if(inJis || (s[i] & 0x80)) {
//2バイト文字
cchar ch;
ch = ((s[i]&0x7f)<<8)|(s[i+1]&0x7f);
i++;
d->push_back(ch);
} else {
d->push_back(s[i]);
}
}
}
//カット&ペースト
void paste_from_global_buffer(jstring_t *s)
{
}
void copy_to_global_buffer(jstring_t *s)
{
char *buf;
buf = jstring_to_str(s);
free(buf);
XFlush(gDpy);
}
//
KKConv *current_conv;
KKConv *init_kkconv()
{
init_conv();
return current_conv;
}
void register_kkconv(KKConv *conv)
{
current_conv = conv;
}
void free_kkconv()
{
if (current_conv) {
delete current_conv;
}
}
KKContext *createKKContext(XimIC *ic)
{
KKContext *c;
c = NULL;
if (current_conv) {
c = current_conv->createContext(ic);
}
return c;
}
char **getKKIcon()
{
char **c;
c = NULL;
if (current_conv) {
c = current_conv->getIcon ();
}
return c;
}
// tool barの仮名漢字変換のボタンが押された。
void onPushIcon()
{
char **c=0;
if (current_conv) {
c = current_conv->getIcon ();
if (c) {
current_conv->onPushIcon ();
}
}
}
//
// KKContextのメソッド
KKContext::KKContext(XimIC *ic)
{
m_ic = ic;
m_pe = new pe_stat(this);
m_convdisp = 0;
}
KKContext::~KKContext()
{
if (m_convdisp) {
m_convdisp->set_pe(0);
}
delete m_pe;
}
void KKContext::update_preedit()
{
OnUpdatePe(m_pe);
if (m_convdisp) {
m_convdisp->update_preedit();
}
}
void KKContext::set_convdisp(Convdisp *c)
{
m_convdisp = c;
if (m_convdisp) {
m_convdisp->set_pe(m_pe);
}
}
void KKContext::commit_jstring(jstring_t *s)
{
m_ic->commit_jstring(s);
}
void KKContext::candidate_selected(int n)
{
}
bool KKContext::extra_input(jstring_t *s)
{
return false;
}
XimIC *KKContext::get_ic()
{
return m_ic;
}
keyState::keyState(keyEventX *x)
{
atom = 0;
m_key_code = x->key_sym;
m_state = x->state;
m_bPush = x->press;
m_char_code = conv_keysym_to_charcode(x->key_sym);
}
keyState::keyState(GdkEventKey *g)
{
atom = 0;
m_state = conv_gdk_state((int)g->state);
if (g->type == GDK_KEY_RELEASE) {
m_bPush = false;
} else {
m_bPush = true;
}
m_key_code = g->keyval;
m_char_code = conv_keysym_to_charcode(g->keyval);
}
atom_t keyState::get_atom()
{
char *m,*k;
char buf[32];
if (atom) {
return atom;
}
m = modifier_to_str();
k = gdk_keyval_name(m_key_code);
if (m) {
sprintf(buf,"%s-%s",m,k);
} else {
sprintf(buf,"%s",k);
}
atom = get_atom_by_name(buf);
return atom;
}
int keyState::char_code()
{
return m_char_code;
}
int keyState::key_code()
{
return m_key_code;
}
bool keyState::is_modifier()
{
// ugly, but this works
if (m_key_code >= XK_Shift_L && m_key_code <= XK_Hyper_R) {
return true;
}
return false;
}
int keyState::to_lower()
{
if (m_char_code < 256) {
return tolower(m_char_code);
}
return m_char_code;
}
bool keyState::modifier(int type)
{
return type & m_state;
}
bool keyState::is_push()
{
return m_bPush;
}
void keyState::print()
{
printf("key code=%x,char_code=%x,modifier=%d,name=%s.\n",
m_key_code, m_char_code,
m_state, get_atom_name(get_atom()));
}
bool keyState::is_alpha()
{
return isalpha(m_char_code);
}
bool keyState::is_bind_to(atom_t a)
{
return ::is_bind_to(get_atom(),a);
}
int keyState::conv_gdk_state(int s)
{
int r=0;
if (s & GDK_SHIFT_MASK) {
r |= SHIFT_KEY;
}
if (s & GDK_LOCK_MASK) {
r |= CAPS_LOCK;
}
if (s & GDK_CONTROL_MASK) {
r |= CTRL_KEY;
}
// XXX KANA_LOCKはGDKのどれにあたるのでしょうか?
return r;
}
int keyState::conv_keysym_to_charcode(int k)
{
if (k > 127 || k < 32 || (m_state&CTRL_KEY)) {
return 0;
}
return k;
}
char *keyState::modifier_to_str()
{
static char buf[8];
int i = 0;
if (m_state & SHIFT_KEY) {
buf[i] = 'S';
i++;
}
if (m_state & CTRL_KEY) {
buf[i] = 'C';
i++;
}
if (m_state & ALT_KEY) {
buf[i] = 'A';
i++;
}
if (i == 0) {
return 0;
}
buf[i] = 0;
return buf;
}
Candidates::Candidates()
{
nth = 0;
opCount = 0;
}
void Candidates::clear()
{
nth = 0;
cands.erase(cands.begin(),cands.end());
}
int Candidates::proc_key(keyState *k,jstring_t *s)
{
int size = (int)cands.size();
if (k->is_bind_to(A_next_candidate) && nth < size) {
nth ++;
opCount ++;
if (nth == size) {
return CAND_EXHAUST;
}
return CAND_NOP;
}
if (k->is_bind_to(A_go_up)) {
if (nth > 0) {
opCount ++;
nth --;
}
return CAND_NOP;
}
if (k->is_bind_to(A_go_down)) {
if (nth < size-1) {
opCount ++;
nth++;
}
return CAND_NOP;
}
if (k->is_bind_to(A_page_up) && nth > 0) {
nth -= CAND_COUNT;
opCount ++;
if (nth < 0) {
nth = 0;
}
return CAND_NOP;
}
if (k->is_bind_to(A_page_down)) {
nth += CAND_COUNT;
opCount ++;
if (nth > size-1) {
nth = size-1;
}
return CAND_NOP;
}
if (k->is_bind_to(A_cancel)) {
return CAND_CANCEL;
}
if (s) {
*s = cands[nth];
}
return CAND_COMMIT;
}
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1