// SKKの変換 // // #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #ifndef __GNUC__ # ifdef HAVE_ALLOCA_H # include # endif #endif #include "skkconv.h" #include "skk.xpm" // SKK classes // SKKConv // SKKStat // SKKChildContext // SKKChildWindow // SKKContext // SKKDic // SKKContext -- SKKStat // | // SKKChildWindow -- SKKChildContext --SKKStat // | .. // -- SKKChildContext -- SKKStat //input mode #define INPUT_MODE_RAW 0 #define INPUT_MODE_HIRA 1 #define INPUT_MODE_KATA 2 #define INPUT_MODE_WIDE 3 atom_t A_skk_share_dic; atom_t A_skk_personal_dic; atom_t A_skk_learn_dic; atom_t A_skk_widelatin_mode; atom_t A_skk_toggle_hirakata; atom_t A_skk_begin_latin_conv; void init_preconf_kkconv() { } bool init_conv() { SKKConv *skk = new SKKConv(); skk->init(); register_kkconv(skk); return true; } KKContext *SKKConv::createContext(XimIC *ic) { return new SKKContext(this,ic); } char *SKKConv::getModeName(int num) { switch (num) { case INPUT_MODE_RAW: return "a"; case INPUT_MODE_HIRA: return "あ"; case INPUT_MODE_KATA: return "ア"; case INPUT_MODE_WIDE: return "A"; } return NULL; } SKKConv::~SKKConv() { delete dic; delete hira_map; delete kata_map; } void SKKConv::init() { hira_map = new RKMap(hiragana); kata_map = new RKMap(katakana); A_skk_share_dic = get_atom_by_name("SkkShareDic"); A_skk_personal_dic = get_atom_by_name("SkkPersonalDic"); A_skk_learn_dic = get_atom_by_name("SkkLearnDic"); A_skk_widelatin_mode = get_atom_by_name("skk_widelatin_mode"); A_skk_toggle_hirakata = get_atom_by_name("skk_toggle_hira_kata"); A_skk_begin_latin_conv = get_atom_by_name("skk_begin_latin_conv"); dic = createSKKDic(); bind_str_to_atom("S-L", A_skk_widelatin_mode); bind_str_to_atom("q", A_skk_toggle_hirakata); bind_str_to_atom("slash", A_skk_begin_latin_conv); } char **SKKConv::getIcon() { return skk_xpm; } void SKKConv::onPushIcon() { } RKMap *SKKConv::get_map(int mode) { if (mode == INPUT_MODE_KATA) { return kata_map; } return hira_map; } SKKDic *SKKConv::get_dic() { return dic; } // // // SKKStat::~SKKStat() { delete rkConv; } void SKKStat::init(SKKConv *c) { conv = c; dic = c->get_dic(); rkConv = new RKConv(); mode = INPUT_MODE_RAW; cands = 0; this->flush(); } void SKKStat::flush() { rkConv->flush(); convstat = STATE_DIRECT; erase_jstring(&head); erase_jstring(&okuri); okuri_head = 0; if (cands) { delete cands; cands = 0; } } void SKKStat::setMode(int m) { if (mode == m) { return ; } mode = m; if (mode != INPUT_MODE_RAW) { rkConv->flush(); rkConv->select_map(conv->get_map(mode)); } this->flush(); } int SKKStat::proc_key(keyState *k) { if (convstat == STATE_DIRECT) { return proc_no_conv(k); } return proc_conv(k); } int SKKStat::proc_conv(keyState *k) { int commit_mask = SKK_UPDATE_PREEDIT; switch(convstat){ case STATE_KANJI: commit_mask|= proc_kanji_state(k); break; case STATE_OKURI: commit_mask|= proc_okuri_state(k); break; case STATE_CONVERTING: commit_mask|= proc_converting_state(k); break; case STATE_WAITING: return SKK_FORWARD_CHILD; break; case STATE_LATIN: commit_mask|=proc_latin_state(k); break; }// switch return commit_mask; } int SKKStat::proc_kanji_state(keyState *k) { //shiftが押されたので送りがなモード if (k->modifier(SHIFT_KEY) &&k->is_alpha() && head.size()) { okuri_head = k->to_lower(); erase_jstring(&okuri); convstat = STATE_OKURI; return proc_conv(k); } //spaceが押されたので変換を行う if (k->is_bind_to(A_do_conv) && head.size() > 0) { return do_conv(); } if (k->is_bind_to(A_skk_toggle_hirakata)) { jstring_t *s= new jstring_t(); hirakana_conv(s, &head); pending = s; flush(); return SKK_COMMIT_PENDING; } if (k->is_bind_to(A_cancel)) { this->flush(); return 0; } if (k->is_bind_to(A_delete_back)) { if (!rkConv->back_space()) { if (head.size()) { head.pop_back(); } } return 0; } if (rkConv->push_key(k->to_lower())) { cchar ch; ch = rkConv->get_cchar(); while (ch){ head.push_back(ch); ch = rkConv->get_cchar(); } } else { head.push_back(k->char_code()); } return 0; } int SKKStat::proc_okuri_state(keyState *k) { if (k->is_bind_to(A_cancel)) { if (rkConv->is_pending()) { rkConv->flush(); return 0; } else { this->flush(); return 0; } } if (!rkConv->push_key(k->to_lower())) { return 0; } cchar ch; ch = rkConv->get_cchar(); if (!ch) { return 0; } while (ch) { okuri.push_back(ch); ch = rkConv->get_cchar(); } cands = dic->getCandidates(this); if (cands) { convstat = STATE_CONVERTING; } else { convstat = STATE_WAITING; return SKK_CREATE_CCONTEXT; } return 0; } int SKKStat::proc_converting_state(keyState *k) { int r; jstring_t s; r = cands->proc_key(k, &s); if (r & CAND_EXHAUST) { convstat = STATE_WAITING; return SKK_CREATE_CCONTEXT; } if (r & CAND_CANCEL) { cancel(); return 0; } if (r & CAND_COMMIT) { dic->commit(this, &s); jstring_t *ss= new jstring_t(); append_jstring(ss, &cands->cands[cands->nth]); append_jstring(ss, &okuri); pending = ss; flush(); delete cands; cands = 0; if (k->is_bind_to(A_commit)) { return SKK_COMMIT_PENDING; } return PUSHKEY_AGAIN |SKK_COMMIT_PENDING; } return 0; } int SKKStat::proc_latin_state(keyState *k) { if (k->is_bind_to(A_cancel)) { flush(); return 0; } if (k->is_bind_to(A_delete_back)) { if (head.size() > 0) { head.pop_back(); return 0; } flush(); return COMMIT_RAW; } int cc = k->char_code(); if (cc > 32 && cc != ' ' && cc < 128) { head.push_back(k->char_code()); return 0; } if (k->is_bind_to(A_do_conv) && head.size() > 0) { return do_conv(); } jstring_t *s; s = new jstring_t(); append_jstring(s, &head); pending = s; flush(); if (k->is_bind_to(A_commit)) { return SKK_COMMIT_PENDING; } return PUSHKEY_AGAIN |SKK_COMMIT_PENDING; } int SKKStat::proc_no_conv(keyState *k) { // XXX そのうち統一 if (mode == INPUT_MODE_RAW) { return proc_raw_mode(k); } if (mode == INPUT_MODE_WIDE) { return proc_wide_mode(k); } if (k->is_bind_to(A_latin_mode)) { mode = INPUT_MODE_RAW; rkConv->flush(); return UPDATE_MODE | SKK_UPDATE_PREEDIT; } if (k->is_bind_to(A_skk_widelatin_mode)) { mode = INPUT_MODE_WIDE; rkConv->flush(); return UPDATE_MODE | SKK_UPDATE_PREEDIT; } if (k->is_bind_to(A_skk_begin_latin_conv)) { this->flush(); convstat = STATE_LATIN; return SKK_UPDATE_PREEDIT; } if (rkConv->is_pending()) { if (k->is_bind_to(A_cancel)) { rkConv->flush(); return SKK_UPDATE_PREEDIT; } else if ( k->is_bind_to(A_delete_back)) { rkConv->back_space(); return SKK_UPDATE_PREEDIT; } } else if (k->is_bind_to(A_cancel)) { return COMMIT_RAW; } if (k->is_bind_to(A_skk_toggle_hirakata)) { if (mode == INPUT_MODE_HIRA) { mode = INPUT_MODE_KATA; } else { mode = INPUT_MODE_HIRA; } rkConv->select_map(conv->get_map(mode)); rkConv->flush(); return UPDATE_MODE|SKK_UPDATE_PREEDIT; } if (!rkConv->push_key(k->to_lower())) { // 入力が取り込まれなかった。 return COMMIT_RAW|SKK_UPDATE_PREEDIT; } cchar ch; ch = rkConv->get_cchar(); // shift とアルファベットにより変換開始 if (k->modifier(SHIFT_KEY) && k->is_alpha()) { erase_jstring(&head); erase_jstring(&okuri); convstat = STATE_KANJI; if (ch) { head.push_back(ch); } return DO_NOTHING | SKK_UPDATE_PREEDIT; } if (!ch) { return DO_NOTHING | SKK_UPDATE_PREEDIT; } //普通の平仮名か片仮名のコミット jstring_t *sy = new jstring_t(); do { sy->push_back(ch); ch = rkConv->get_cchar(); } while (ch); pending = sy; return SKK_COMMIT_PENDING | SKK_UPDATE_PREEDIT; } int SKKStat::proc_raw_mode(keyState *k) { if (k->is_bind_to(A_hira_mode)) { mode = INPUT_MODE_HIRA; rkConv->select_map(conv->get_map(mode)); rkConv->flush(); return UPDATE_MODE; } return COMMIT_RAW; } int SKKStat::proc_wide_mode(keyState *k) { if (k->is_bind_to(A_commit)) { mode = INPUT_MODE_HIRA; rkConv->select_map(conv->get_map(mode)); rkConv->flush(); return UPDATE_MODE; } return COMMIT_WIDE; } int SKKStat::do_conv() { cands = dic->getCandidates(this); if (cands) { convstat = STATE_CONVERTING; }else{ convstat = STATE_WAITING; return SKK_CREATE_CCONTEXT; } return 0; } void SKKStat::cancel() { if (cands) { delete cands; cands = 0; } append_jstring(&head, &okuri); erase_jstring(&okuri); okuri_head = 0; convstat = STATE_KANJI; } // // // SKKContext::SKKContext(SKKConv *c, XimIC *ic) : KKContext(ic) { mStat.init(c); m_child = 0; } SKKContext::~SKKContext() { if (m_child) { delete m_child; } } void SKKContext::OnUpdatePe(pe_stat *pe) { pe->clear(); if (mStat.mode == INPUT_MODE_RAW) { return ; } pe->new_segment(PE_UNDERLINE); switch (mStat.convstat) { case STATE_DIRECT: { // ローマ字に変換されてないものを表示する。 char buf[10]; if (mStat.rkConv->get_pending_char(buf, 10)) { int l = strlen(buf),i; for (i = 0; i < l; i++) { pe->push_cchar(buf[i]); } } break; } case STATE_KANJI: case STATE_OKURI: case STATE_LATIN: { // 途中を入力中 pe->push_cchar(0x2260);//▽0x2226 pe->new_segment(PE_UNDERLINE); jstring_t::iterator i; for (i = mStat.head.begin(); i != mStat.head.end(); i++) { pe->push_cchar(*i); } if (mStat.convstat == STATE_OKURI) { pe->push_cchar('*'); } char buf[10]; if (mStat.rkConv->get_pending_char(buf, 10)) { int i, l= strlen(buf); for (i = 0; i < l; i++) { pe->push_cchar(buf[i]); } } break; } case STATE_CONVERTING: { pe->new_segment(PE_REVERSE); if (mStat.cands->opCount > 3) { pe->cands = mStat.cands; } else { pe->cands = 0; } } case STATE_WAITING: { pe->push_cchar(0x2260);//▼0x2227 pe->new_segment(PE_REVERSE); jstring_t::iterator i; jstring_t *s = 0; if (mStat.convstat == STATE_WAITING) { s = &mStat.head; } else { s = &(mStat.cands->cands[mStat.cands->nth]); } for (i = s->begin(); i != s->end(); i++) { pe->push_cchar(*i); } pe->new_segment(PE_REVERSE); for (i = mStat.okuri.begin(); i != mStat.okuri.end(); i++) { pe->push_cchar(*i); } break; } }//switch } int SKKContext::pushKey(keyState *k) { int res=0; res = mStat.proc_key (k); if (res & SKK_UPDATE_PREEDIT) { update_preedit (); } if (res & SKK_COMMIT_PENDING) { commit_jstring (mStat.pending); delete mStat.pending; mStat.pending = 0; } if (res & SKK_CREATE_CCONTEXT) { create_child_context (); } if ((res & SKK_FORWARD_CHILD) && m_child) { int r; r = m_child->pushKey(k); } return res & KK_PUSHKEY_MASK; } int SKKContext::getMode() { return mStat.mode; } void SKKContext::setMode(int m) { mStat.setMode(m); } void SKKContext::candidate_selected(int n) { commit_jstring(&(mStat.cands->cands[n])); mStat.flush(); delete mStat.cands; mStat.cands = 0; update_preedit(); } bool SKKContext::extra_input(jstring_t *s) { if (mStat.convstat == STATE_WAITING) { return m_child->extra_input(s); } return false; } jstring_t *SKKContext::clear() { mStat.flush(); if (m_child) { m_child->close(); } return 0; } //再帰学習のためのWindowを作る void SKKContext::create_child_context() { if (!m_child) { m_child = new SKKChildWindow(mStat.conv, this); } m_child->open(&mStat); } //再帰学習のためのWindowが閉じるときに呼ばれる void SKKContext::commit_child(jstring_t *s) { mStat.dic->commit(&mStat, s); commit_jstring(s); mStat.flush(); } void SKKContext::cancel_child() { mStat.cancel(); update_preedit(); } // // SKKChildContext::SKKChildContext(SKKConv *c, SKKChildContext *p, SKKStat *s) { stat.init(c); init(); parent_context = p; learn = s->head; if (s->okuri.size()) { learn.push_back('*'); append_jstring(&learn, &s->okuri); if (s->okuri_head) { learn.push_back('('); learn.push_back(s->okuri_head); learn.push_back(')'); } } char buf[16]; sprintf(buf, ":%d", get_current_level()); int i; for (i = 0; i < (int)strlen( buf ); i++) { learn.push_back(buf[i]); } } SKKChildContext *SKKChildContext::get_parent_context() { return parent_context; } void SKKChildContext::cancel_child() { stat.flush(); } void SKKChildContext::commit_child(jstring_t *s) { stat.flush(); append_jstring(&pre, s); } int SKKChildContext::pushKey(keyState *k) { int res; res = stat.proc_key(k); if (res & SKK_COMMIT_PENDING) { append_jstring(&pre, stat.pending); delete stat.pending; stat.pending = 0; res &= (~SKK_COMMIT_PENDING); } if (res & (COMMIT_RAW|COMMIT_WIDE)) { res = proc_edit_key(k, res); } return res; } int SKKChildContext::get_current_level() { if (parent_context) { return parent_context->get_current_level()+1; } return 1; } int SKKChildContext::proc_edit_key(keyState *k, int res) { // テキストコントロールの操作を処理する if (k->is_bind_to(A_delete_back)) { if (pre.size() > 0) { pre.pop_back(); res |= SKK_UPDATE_PREEDIT; } } else if (k->is_bind_to(A_go_left)) { if (pre.size() > 0) { cchar c = *(pre.rbegin()); pre.pop_back(); post.push_front(c); res |= SKK_UPDATE_PREEDIT; } } else if (k->is_bind_to(A_go_right)) { if (post.size() > 0) { cchar c = *(post.begin()); post.pop_front(); pre.push_back(c); res |= SKK_UPDATE_PREEDIT; } } else if(k->is_bind_to(A_delete_here)) { if (post.size() > 0) { post.pop_front(); res |= SKK_UPDATE_PREEDIT; } } else if (k->is_bind_to(A_cancel)) { res |= (SKK_UPDATE_PREEDIT | SKK_CANCEL_CHILD); } else if (k->is_bind_to(A_go_line_head)) { append_jstring(&pre, &post); post = pre; erase_jstring(&pre); res |= SKK_UPDATE_PREEDIT; } else if (k->is_bind_to(A_go_line_end)) { append_jstring(&pre, &post); erase_jstring(&post); res |= SKK_UPDATE_PREEDIT; } else if (k->is_bind_to(A_return)) { res |= SKK_COMMIT_PENDING; } else if (k->is_bind_to(A_delete_right)) { copy_to_global_buffer(&post); erase_jstring(&post); // グローバルなカットバッファに入れる? res |= SKK_UPDATE_PREEDIT; } else { cchar c = k->char_code(); if (c) { if (res & COMMIT_WIDE) { c = ascii_to_wide(c); } pre.push_back(c); res |= SKK_UPDATE_PREEDIT; } } return res; } void SKKChildContext::init() { stat.setMode(INPUT_MODE_HIRA); erase_jstring(&pre); erase_jstring(&post); } bool SKKChildContext::extra_input(jstring_t *s) { if (stat.convstat == STATE_DIRECT) { append_jstring(&pre, s); return true; } return false; } // SKKChildWindow::SKKChildWindow(SKKConv *conv, SKKContext *cont) { init_win(); set_current_context(0); m_skkConv = conv; m_skkContext = cont; } SKKChildWindow::~SKKChildWindow() { close(); gtk_widget_destroy(m_win); } void SKKChildWindow::open(SKKStat *s) { set_current_context(new SKKChildContext(m_skkConv, 0, s)); gtk_widget_show(m_win); draw_text_entry(); update_mode(); } void SKKChildWindow::close() { SKKChildContext *c, *d; while ((c = get_current_context())) { d = c->get_parent_context(); delete c; set_current_context(d); } } void SKKChildWindow::init_win() { GtkWidget *table; m_pix = 0; m_win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_set_usize(m_win, 600, 100); gtk_window_set_title(GTK_WINDOW(m_win), "heke(skk)"); add_widget_watch(m_win, WIDGET_KEY_PRESS, this); table = gtk_table_new(5, 30, TRUE); gtk_container_add(GTK_CONTAINER(m_win), table); m_text = gtk_drawing_area_new(); gtk_table_attach_defaults(GTK_TABLE(table), m_text, 7, 23, 1, 4); add_widget_watch(m_text,WIDGET_EXPOSE, this); add_widget_watch(m_text,WIDGET_RESIZE, this); gtk_widget_show(m_text); m_commit_button = gtk_button_new_with_label("確定"); gtk_table_attach_defaults(GTK_TABLE(table), m_commit_button, 24, 29, 1, 2); gtk_widget_show(m_commit_button); add_widget_watch(m_commit_button, WIDGET_CLICK, this); m_cancel_button = gtk_button_new_with_label("キャンセル"); gtk_table_attach_defaults(GTK_TABLE(table), m_cancel_button, 24, 29, 3, 4); gtk_widget_show(m_cancel_button); add_widget_watch(m_cancel_button, WIDGET_CLICK,this); m_stat_menu = gtk_option_menu_new(); GtkWidget *menu; menu = gtk_menu_new(); add_input_mode(menu,"raw", INPUT_MODE_RAW); add_input_mode(menu,"ひらがな", INPUT_MODE_HIRA); add_input_mode(menu,"カタカナ", INPUT_MODE_KATA); add_input_mode(menu,"Wide", INPUT_MODE_WIDE); gtk_option_menu_set_menu(GTK_OPTION_MENU(m_stat_menu), menu); gtk_table_attach_defaults(GTK_TABLE(table), m_stat_menu, 1, 6, 2, 4); gtk_widget_show(menu); gtk_widget_show(m_stat_menu); gtk_widget_show(table); } void SKKChildWindow::add_input_mode(GtkWidget *menu, char *name, int mode) { GtkWidget *menu_item; menu_item = gtk_menu_item_new_with_label(name); gtk_menu_append(GTK_MENU (menu), menu_item); add_widget_watch(menu_item, WIDGET_ACTIVATE, this, (void *)mode); gtk_widget_show(menu_item); } void SKKChildWindow::key_press(GtkWidget *w, GdkEventKey *e) { keyState k(e); if (!k.is_modifier()) { pushKey(&k); } } int SKKChildWindow::pushKey(keyState *k) { // この関数はSKKの学習Windowに対する直接のキーイベントと // 入力ウィンドウからフォワードされてきたキーイベントの // 両方を受けとる。 int res; SKKChildContext *cc = get_current_context (); res = cc->pushKey (k); if (res & SKK_UPDATE_PREEDIT) { draw_text_entry (); } if (res & UPDATE_MODE) { update_mode (); } if (res & SKK_CREATE_CCONTEXT) { SKKChildContext *new_cont; new_cont = new SKKChildContext (m_skkConv, cc, &cc->stat); set_current_context (new_cont); draw_text_entry (); } if (res & SKK_CANCEL_CHILD) { cancel_current (); return res; } if (res & SKK_COMMIT_PENDING) { commit_to_parent (); return res; } return res; } void SKKChildWindow::resize(GtkWidget *g, int w, int h) { if (m_pix) { gdk_pixmap_unref(m_pix); } m_pix = gdk_pixmap_new(g->window, w, h, -1); clear_preedit(); draw_text_entry(); draw(); } void SKKChildWindow::expose(GtkWidget *g) { if (!m_pix) { resize(g, g->allocation.width, g->allocation.height); } draw(); } void SKKChildWindow::clicked(GtkWidget *w) { if (w == m_commit_button) { commit_to_parent(); } else if (w == m_cancel_button) { cancel_current(); } } void SKKChildWindow::draw() { gdk_draw_pixmap(m_text->window, m_text->style->fg_gc[GTK_WIDGET_STATE(m_text)], m_pix, 0, 0, 0, 0, m_text->allocation.width, m_text->allocation.height); } void SKKChildWindow::activate(GtkWidget *w, gpointer p) { SKKChildContext *c; int pos = (int)p; c = get_current_context(); if (c) { c->stat.setMode(pos); } } void SKKChildWindow::clear_preedit() { gdk_draw_rectangle(m_pix,m_text->style->white_gc, TRUE, 0, 0, m_text->allocation.width, m_text->allocation.height); } void SKKChildWindow::draw_text_entry() { int x=0; jstring_t::iterator i; SKKChildContext *c = get_current_context(); clear_preedit(); for (i = c->pre.begin(); i != c->pre.end(); i++) { x = draw_cchar(*i, x, 1, 0); } x = draw_preedit(x); x = draw_cchar('|', x, 1, 0); // カーソルのつもり for (i = c->post.begin(); i != c->post.end(); i++) { x = draw_cchar(*i, x, 1, 0); } // 変換元のやつを描画 int p = 20; for (i = c->learn.begin(); i != c->learn.end(); i++) { p = draw_cchar(*i, p, 0, 0); } draw(); } //text field中のSKKによる編集中の部分を書く int SKKChildWindow::draw_preedit(int x) { // この関数はSKKContext::OnUpdatePeとほとんど同じ // なんとかできないものか jstring_t::iterator i; SKKChildContext *c= get_current_context(); switch (c->stat.convstat ) { case STATE_DIRECT: { char buf[10]; if (c->stat.rkConv->get_pending_char(buf, 10)) { int l = strlen(buf), j; for (j = 0; j < l; j++) { x = draw_cchar(buf[j], x, 1, 0); } } } break; case STATE_KANJI: case STATE_OKURI: case STATE_LATIN: { x = draw_cchar(0x2226, x, 1, 0); for (i = c->stat.head.begin(); i != c->stat.head.end(); i++) { x = draw_cchar(*i, x, 1, 0); } if (c->stat.convstat == STATE_OKURI) { x = draw_cchar('*', x, 1, 0); } char buf[10]; if (c->stat.rkConv->get_pending_char(buf, 10)) { int i, l = strlen(buf); for (i = 0; i < l; i++) { x = draw_cchar(buf[i], x, 1, 0); } } } break; case STATE_CONVERTING: { // XXX 候補Windowを出してない x = draw_cchar(0x2227, x, 1, 0); jstring_t *s = &(c->stat.cands->cands[c->stat.cands->nth]); for(i = s->begin(); i != s->end(); i ++) { x = draw_cchar(*i, x, 1, 0); } for (i = c->stat.okuri.begin(); i!= c->stat.okuri.end() ; i++) { x = draw_cchar(*i, x, 1, 0); } } break; } return x; } int SKKChildWindow::draw_cchar(cchar c, int x, int y, int m) { char buf[3]; buf[2] = 0; if (c < 256) { buf[0] = c; buf[1] = 0; }else { buf[0] = ((c>>8)& 0xff) | 0x80; buf[1] = (c & 0xff) | 0x80; } gdk_draw_string(m_pix, m_text->style->font, m_text->style->black_gc, x, 20 + y*20, buf); x += gdk_string_width(m_text->style->font, buf); return x; } SKKChildContext *SKKChildWindow::get_current_context() { return m_context; } void SKKChildWindow::set_current_context(SKKChildContext *c) { m_context = c; } void SKKChildWindow::commit_to_parent() { SKKChildContext *cc, *pc; cc = get_current_context(); pc = cc->get_parent_context(); jstring_t s; append_jstring(&s, &cc->pre); append_jstring(&s, &cc->post); if (!pc) { gtk_widget_hide(m_win); m_skkContext->commit_child(&s); delete cc; set_current_context(0); } else { pc->commit_child(&s); delete cc; set_current_context(pc); draw_text_entry(); } } void SKKChildWindow::cancel_current() { SKKChildContext *cc, *pc; cc = get_current_context(); pc = cc->get_parent_context(); if (pc) { pc->cancel_child(); delete cc; set_current_context(pc); draw_text_entry(); } else { gtk_widget_hide(m_win); delete cc; set_current_context(0); m_skkContext->cancel_child(); } } bool SKKChildWindow::extra_input(jstring_t *s) { SKKChildContext *c; c = get_current_context(); if (c->extra_input(s)) { draw_text_entry(); return true; } return false; } void SKKChildWindow::update_mode() { SKKChildContext *c; c = get_current_context(); int m = c->stat.mode; gtk_option_menu_set_history(GTK_OPTION_MENU(m_stat_menu), m - 1); gtk_widget_draw(m_stat_menu, NULL); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * End: */