// XIMプロトコルのパケットでIC(Input Context)に関わる物を処理する // 特にキーが押されたというメッセージと文字をコミットするメッセージを // 仮名漢字モジュールへとの間で仲介する。 #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include "xim.h" #include "convdisp.h" #include "kkconv.h" #ifndef __GNUC__ # ifdef HAVE_ALLOCA_H # include # endif #endif extern input_style input_style_tab[]; char invalid_style_msg[]= "サポートしていない入力スタイルの\n" "設定をクライアントが要求してきました。"; XimIC *XimIC::current_ic; int XimIC::nrActiveIC; pe_stat::pe_stat(KKContext *c) { cont = c; clear(); } void pe_stat::clear() { jstrings.erase(jstrings.begin(), jstrings.end()); cands = 0; } void pe_stat::new_segment(int s) { pe_jstring p; p.stat = s; jstrings.push_back(p); } void pe_stat::push_cchar(cchar c) { std::list::reverse_iterator i= jstrings.rbegin(); (*i).s.push_back(c); } int pe_stat::get_char_count() { std::list::iterator i; jstring_t::iterator j; int k=0; for (i = jstrings.begin(); i != jstrings.end(); i++) { for (j = (*i).s.begin(); j != (*i).s.end(); j++) { k++; } } return k; } icxatr::icxatr() { atr_mask = 0; change_mask = 0; font_set_name = NULL; font_set = NULL; foreground_pixel = BlackPixel(gDpy, DefaultScreen(gDpy)); background_pixel = WhitePixel(gDpy, DefaultScreen(gDpy)); } icxatr::~icxatr() { if (font_set_name) { free((void *)font_set_name); XFreeFontSet(gDpy,font_set); } } bool icxatr::has_atr(int id) { return atr_mask & (1<getMode()); if (mConvdisp) { mConvdisp->set_focus(); } } void XimIC::unset_focus() { if (!mIsActive) { return ; } mIsActive = false; nrActiveIC --; if (current_ic == this) { ui_update_ic_stat(); } if (mConvdisp) { mConvdisp->unset_focus(); } } void XimIC::OnKeyEvent(keyEventX e) { int s,t = 0; keyState k(&e); if (k.is_modifier()) { return ; } jstring_t *c= new jstring_t(); do { s = m_kkContext->pushKey(&k); t |= s; if (s & COMMIT_RAW) { send_key_event(&e.ev.xkey); } if (s & COMMIT_WIDE) { cchar ac; ac = ascii_to_wide(k.char_code()); if (ac) { c->push_back(ac); } else { send_key_event(&e.ev.xkey); } } } while(s & PUSHKEY_AGAIN); if (t & UPDATE_MODE) { int mode = m_kkContext->getMode(); ui_update_input_mode(mode); } if (t & COMMIT_WIDE) { commit_jstring(c); } delete c; } void XimIC::changeMode(int s) { m_kkContext->setMode(s); ui_update_input_mode(m_kkContext->getMode()); } void XimIC::send_key_event(XKeyEvent *e) { TxPacket *t; t = createTxPacket(XIM_FORWARD_EVENT,0); t->pushC16(mIMid); t->pushC16(mICid); t->pushC16(1); //flag , synchronous t->pushC16((e->serial>>16)&0xffff); t->pushC8(e->type); t->pushC8(e->keycode); t->pushC16(e->serial &0xffff); t->pushC32(e->time); t->pushC32(e->root); t->pushC32(e->window); t->pushC32(e->subwindow); t->pushC16(e->x_root); t->pushC16(e->y_root); t->pushC16(e->x); t->pushC16(e->y); t->pushC16(e->state); t->pushC8(e->same_screen); t->pushC8(0); m_conn->push_packet(t); } void XimIC::commit_jstring(jstring_t *s) { append_jstring(&mPending, s); } void XimIC::extra_input(jstring_t *s) { if (!m_kkContext->extra_input(s)) { commit_jstring(s); } if (m_xatr.has_atr(ICA_FocusWindow)) { force_event(m_xatr.focus_window); } } void XimIC::set_ic_attrs(void *val, int len) { unsigned char *p=(unsigned char *)val; int byte_order = m_conn->byte_order(); int i; for (i = 0; i < len ;) { int atr_id, atr_len; atr_id = readC16(&p[i], byte_order); i += 2; atr_len = readC16(&p[i], byte_order); i += 2; unsigned char *q; q = (unsigned char *)alloca(atr_len+pad4(atr_len)); int j; for(j = 0; j < atr_len +pad4(atr_len); j++, i++) { q[j] = p[i]; } set_ic_attr(atr_id, (C8 *)q, atr_len); } } int XimIC::get_ic_atr(int id, TxPacket *t) { int l = m_xatr.getSize(id); if (!t) { return l; } switch (id) { case ICA_FocusWindow: t->pushC32(m_xatr.focus_window); break; case ICA_FilterEvents: t->pushC32(KeyPressMask); break; default: printf("try to get unknown ic attribute %d.\n",id); break; } return l; } int XimIC::lookup_style(unsigned long s) { int i; for (i = 0; input_style_tab[i].x_style; i++) { if (input_style_tab[i].x_style == (int)s) { return input_style_tab[i].style; } } return IS_INVALID; } void XimIC::set_ic_attr(int id,C8 *val, int len) { if (id == ICA_PreeditAttribute || id == ICA_StatusAttributes) { // attributeリスト set_ic_attrs(val, len); } else { m_xatr.set_atr(id, val, len, m_conn->byte_order()); } if (mConvdisp) { mConvdisp->update_icxatr(); } if (!mConvdisp && m_xatr.has_atr(ICA_InputStyle)) { mConvdisp = create_convdisp( lookup_style(m_xatr.input_style), m_kkContext, &m_xatr, m_conn); if (!mConvdisp && id == ICA_InputStyle) { show_issue(invalid_style_msg); } } m_kkContext->set_convdisp(mConvdisp); if (mConvdisp) { mConvdisp->update_icxatr(); } } void XimIC::reset_ic() { TxPacket *t; t = createTxPacket(XIM_RESET_IC_REPLY,0); t->pushC16(mIMid); t->pushC16(mICid); jstring_t *s; s = m_kkContext->clear(); if (s) { char *p; int i,len; p = jstring_to_ctext(s); len = strlen(p); t->pushC16(len); for (i = 0 ; i < len; i++) { t->pushC8(p[i]); } len = pad4(len+2); for (i = 0; i < len; i++) { t->pushC8(p[i]); } free(p); delete s; }else{ t->pushC16(0);//コミットする文字の長さ // ここでコミットする文字を入れる。 t->pushC16(0);//padding ( 2bytes) } m_conn->push_packet(t); } Convdisp *XimIC::get_convdisp() { return mConvdisp; } void XimIC::onSendPacket() { if (!mPending.size()) { return; } char *p; p = jstring_to_ctext(&mPending); TxPacket *t; t = createTxPacket(XIM_COMMIT, 0); t->pushC16(mIMid); t->pushC16(mICid); t->pushC16(3); //XLookupChars|同期 int i,len; len = strlen(p); t->pushC16(len); for (i = 0 ; i < len ; i++) { t->pushC8(p[i]); } len = pad4(len); for (i = 0 ; i < len ; i++) { t->pushC8(0); } free(p); m_conn->push_passive_packet(t); erase_jstring(&mPending); } XimIC *XimIC::get_current_ic() { return current_ic; } bool XimIC::isAnyActive() { if ( nrActiveIC ){ return true; } return false; } XimIC *create_ic(Connection *c,RxPacket *p,int imid,int icid) { XimIC *ic; ic = new XimIC(c,imid,icid); p->rewind(); p->getC16();//discard int atr_len = p->getC16(); unsigned char *v; v = (unsigned char *)alloca(atr_len); int i; for ( i = 0 ; i < atr_len ;i++){ v[i] = p->getC8(); } ic->set_ic_attrs((void *)v,atr_len); if ( !ic->get_convdisp()){ delete ic; return 0; } return ic; } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * End: */