// KKConv 仮名漢字変換 #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include "xim.h" #include "convdisp.h" #include "kkconv.h" #include "rkconv.h" // rkmap.h は一度だけどこかでインクルード #include "rkmap.h" #ifndef __GNUC__ # ifdef HAVE_ALLOCA_H # include # 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: */