// XIMプロトコルのパケットを下位層から受けとり、 // それをディスパッチする。 #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "xim.h" #ifndef __GNUC__ # ifdef HAVE_ALLOCA_H # include # endif #endif //色々な表 input_style input_style_tab[]={ {XIMPreeditNothing|XIMStatusNothing, IS_ROOT_WINDOW}, //{XIMPreeditPosition|XIMStatusArea, IS_OVER_THE_SPOT},// emacs {XIMPreeditPosition|XIMStatusNothing, IS_OVER_THE_SPOT}, //{XIMPreeditCallbacks|XIMStatusCallbacks, IS_ON_THE_SPOT},// OOo //{XIMPreeditArea|XIMStatusArea, IS_ROOT_WINDOW}, {XIMPreeditCallbacks|XIMStatusNothing, IS_ON_THE_SPOT}, {0, 0}, }; // XIMPreeditArea,XIMPreeditCallbacks,XIMPreeditPosition // XIMPreeditNothing,XIMPreeditNone // XIMStatusArea,XIMStatusCallbacks // XIMStatusNothing,XIMStatusNone static char *xim_packet_name[]={ // 0 0,"XIM_CONNECT","XIM_CONNECT_REPLY", "XIM_DISCONNECT","XIM_DISCONNECT_REPLY", 0,0,0,0,0, // 10 "XIM_AUTH_REQUIRED","XIM_AUTH_REPLY","XIM_AUTH_NEXT", "XIM_AUTH_SETUP","XIM_AUTH_NG",0,0,0,0,0, // 20 "XIM_ERROR",0,0,0,0,0,0,0,0,0, // 30 "XIM_OPEN","XIM_OPEN_REPLY","XIM_CLOSE", "XIM_CLOSE_REPLY","XIM_REGISTER_TRIGGERKEYS", "XIM_TRIGGER_NOTIFY","XIM_TRIGGER_NOTIFY_REPLY", "XIM_SET_EVENT_MASK","XIM_ENCODING_NEGOTIATION", "XIM_ENCODING_NEGOTIATION_REPLY", // 40 "XIM_QUERY_EXTENSION","XIM_QUERY_EXTENSION_REPLY", "XIM_SET_IM_VALUES","XIM_SET_IM_VALUES_REPLY", "XIM_GET_IM_VALUES","XIM_GET_IM_VALUES_REPLY", 0,0,0,0, // 50 "XIM_CREATE_IC","XIM_CREATE_IC_REPLY", "XIM_DESTROY_IC","XIM_DESTROY_IC_REPLY", "XIM_SET_IC_VALUES","XIM_SET_IC_VALUES_REPLY", "XIM_GET_IC_VALUES","XIM_GET_IC_VALUES_REPLY", "XIM_SET_IC_FOCUS","XIM_UNSET_FOCUS", // 60 "XIM_FORWARD_EVENT","XIM_SYNC","XIM_SYNC_REPLY", "XIM_COMMIT","XIM_RESET_IC","XIM_RESET_IC_REPLY", 0,0,0,0, // 70 "XIM_GEOMETRY","XIM_STR_CONVERSION", "XIM_STR_CONVERSION_REPLY","XIM_PREEDIT_START", "XIM_PREEDIT_START_REPLY","XIM_PREEDIT_DRAW", "XIM_PREEDIT_CARET","XIM_PREEDIT_CARET_REPLY", "XIM_PREEDIT_DONE","XIM_STATUS_START", // 80 "XIM_STATUS_DRAW","XIM_STATUS_DONE","XIM_PREEDITSTATE" }; static struct XIMATTRIBUTE{ XIMATTRIBUTE(char *n,int t); static void write_imattr_to_packet(TxPacket *p); char *name; int type; }xim_attributes[]={ XIMATTRIBUTE(XNQueryInputStyle,TYPE_XIMSTYLE), }; XIMATTRIBUTE::XIMATTRIBUTE(char *n, int t) { name = n; type = t; } void XIMATTRIBUTE::write_imattr_to_packet(TxPacket *p) { int i,l; char tmp[4]; for (i = 0; i < 4; i++) { tmp[i] = 0; } for (i = 0, l =0; i < (int)(sizeof(xim_attributes)/sizeof(XIMATTRIBUTE)); i++) { l += 6; l += strlen(xim_attributes[i].name); l += pad4(strlen(xim_attributes[i].name)+2); } p->pushC16(l); for (i = 0; i < (int)(sizeof(xim_attributes)/sizeof(XIMATTRIBUTE)); i++){ p->pushC16((unsigned int)i); p->pushC16((unsigned int)xim_attributes[i].type); p->pushC16((unsigned int)strlen(xim_attributes[i].name)); p->pushBytes(xim_attributes[i].name, strlen(xim_attributes[i].name)); p->pushBytes(tmp, pad4(strlen(xim_attributes[i].name))+2); } } static struct XICATTRIBUTE{ XICATTRIBUTE(char *n, int t); static void write_icattr_to_packet(TxPacket *p); char *name; int type; }xic_attributes[]={ //この順番とximpn.hで定義している番号は一致していないといけない //ktermとgtkでルートウィンドウスタイルのとき XICATTRIBUTE(XNInputStyle, TYPE_LONG), XICATTRIBUTE(XNClientWindow, TYPE_WINDOW), XICATTRIBUTE(XNFocusWindow, TYPE_WINDOW), //ktermでover the spotを行うとき XICATTRIBUTE(XNPreeditAttributes, TYPE_NESTEDLIST), XICATTRIBUTE(XNForeground, TYPE_LONG), XICATTRIBUTE(XNBackground, TYPE_LONG), XICATTRIBUTE(XNSpotLocation, TYPE_POINT), XICATTRIBUTE(XNFontSet, TYPE_XFONTSET), XICATTRIBUTE(XNArea, TYPE_XRECTANGLE), XICATTRIBUTE(XNLineSpace, TYPE_WORD), // XICATTRIBUTE(XNStatusAttributes, TYPE_NESTEDLIST), XICATTRIBUTE(XNAreaNeeded, TYPE_XRECTANGLE), XICATTRIBUTE(XNColormap, TYPE_WORD), XICATTRIBUTE(XNStdColormap, TYPE_WORD), XICATTRIBUTE(XNBackgroundPixmap, TYPE_LONG), XICATTRIBUTE(XNCursor, TYPE_WORD), XICATTRIBUTE(XNFilterEvents, TYPE_WORD), XICATTRIBUTE(XNSeparatorofNestedList, TYPE_SEPARATOR), }; XICATTRIBUTE::XICATTRIBUTE(char *n, int t) { name = n; type = t; } void XICATTRIBUTE::write_icattr_to_packet(TxPacket *p) { int i,l; char tmp[4]; for (i = 0; i < 4; i++) { tmp[i] = 0; } for (i = 0, l = 0; i < (int)(sizeof(xic_attributes)/sizeof(XICATTRIBUTE)) ; i++){ l += 6; l += strlen(xic_attributes[i].name); l += pad4(strlen(xic_attributes[i].name)+2); } p->pushC16(l); p->pushC16(0); for (i = 0; i < (int)(sizeof(xic_attributes)/sizeof(XICATTRIBUTE)); i++) { p->pushC16((unsigned int)i); p->pushC16((unsigned int)xic_attributes[i].type); p->pushC16((unsigned int)strlen(xic_attributes[i].name)); p->pushBytes(xic_attributes[i].name, strlen(xic_attributes[i].name)); p->pushBytes(tmp, pad4(strlen(xic_attributes[i].name)+2)); } } void force_event(Window w) { Window fw; int rev; XGetInputFocus(gDpy, &fw, &rev); XSetInputFocus(gDpy, w, rev, CurrentTime); XSetInputFocus(gDpy, fw, rev, CurrentTime); XFlush(gDpy); } Connection::Connection() { mIsCloseWait = false; mByteorder = BYTEORDER_UNKNOWN; } Connection::~Connection() { //自分で作ったIMを全てこわす。 std::list::iterator i; for (i = mCreatedIm.begin(); i != mCreatedIm.end(); i++) { close_im(*i); } // std::list::iterator ir; for (ir = mRxQ.begin(); ir != mRxQ.end(); ir ++) { delete *ir; } std::list::iterator it; for (it = mTxQ.begin(); it != mTxQ.end(); it ++) { delete *it; } for (it = mPTxQ.begin(); it != mPTxQ.end(); it ++) { delete *it; } } void Connection::terminate() { mIsCloseWait = true; } void Connection::OnRecv() { std::list::iterator i; i = mRxQ.begin(); if (i != mRxQ.end()) { int major = (*i)->getMajor(); //一通りそろったら、プロトコルの番号順に並びかえたい。 RxPacket *p = *i; if (g_option_mask & OPT_TRACE_XIM) { printf("<-: %s(%d,%d).\n", xim_packet_name[major], p->getC16(), p->getC16()); p->rewind(); } switch(major){ case XIM_CONNECT: xim_connect(p); break; case XIM_OPEN: xim_open(p); break; case XIM_QUERY_EXTENSION: xim_query_extension(p); break; case XIM_ENCODING_NEGOTIATION: xim_encoding_negotiation(p); break; case XIM_CLOSE: xim_close(p); break; case XIM_DISCONNECT: xim_disconnect(p); break; case XIM_GET_IM_VALUES: xim_get_im_values(p); break; case XIM_SET_IC_VALUES: xim_set_ic_values(p); break; case XIM_GET_IC_VALUES: xim_get_ic_values(p); break; case XIM_CREATE_IC: xim_create_ic(p); break; case XIM_DESTROY_IC: xim_destroy_ic(p); break; case XIM_SET_IC_FOCUS: xim_set_ic_focus(p); break; case XIM_UNSET_IC_FOCUS: xim_unset_ic_focus(p); break; case XIM_TRIGGER_NOTIFY: //xim_trigger_notify(*i);トリガーなんかは使わん。 break; case XIM_FORWARD_EVENT: xim_forward_event(p); break; case XIM_SYNC_REPLY: //xim_sync_reply(p); break; case XIM_RESET_IC: xim_reset_ic(p); break; case XIM_PREEDIT_START_REPLY: // do nothing break; case XIM_PREEDIT_CARET_REPLY: // do nothing break; case XIM_ERROR: xim_error(p); break; default: printf("Unknown(or not implemented.) packet from xim connection.\n"); (*i)->dump(); break; } mRxQ.pop_front(); delete p; } } void Connection::OnSend() { std::list::iterator i; for (i = mCreatedIm.begin(); i != mCreatedIm.end(); i++) { XimIM *im; im = get_im_by_id(*i); if (im) { im->onSendPacket(); } } } void Connection::OnClose() { std::list::iterator i; for (i = mCreatedIm.begin(); i != mCreatedIm.end(); i++) { close_im(*i); } mCreatedIm.erase(mCreatedIm.begin(), mCreatedIm.end()); } void Connection::push_packet(TxPacket *p) { OnPushPacket(); mTxQ.push_back(p); if (g_option_mask & OPT_TRACE_XIM) { printf("->: %s.\n", xim_packet_name[p->get_major()]); } } void Connection::push_passive_packet(TxPacket *p) { mPTxQ.push_back(p); if (g_option_mask & OPT_TRACE_XIM) { printf("(->): %s.\n", xim_packet_name[p->get_major()]); } } void Connection::push_error_packet(int imid, int icid, int er, char *str) { TxPacket *t; t = createTxPacket(XIM_ERROR,0); t->pushC16(imid); t->pushC16(icid); int m = 0; if (imid) { m+=1; } if (icid) { m+=2; } t->pushC16(m); t->pushC16(er); int l=strlen(str); char tmp[4]; t->pushC16(l); t->pushC16(0); t->pushBytes(str, l); t->pushBytes(tmp, pad4(l)); push_packet(t); } unsigned short Connection::to_hs(unsigned short s) { if (host_byte_order == mByteorder) { return s; } unsigned char *v; v = (unsigned char *)&s; s = (v[0]<<8) + v[1]; return s; } unsigned int Connection::to_hl(unsigned int l) { if (host_byte_order == mByteorder) { return l; } return l; } // // Packet handlers // void Connection::xim_connect(RxPacket *p) { TxPacket *t; p->rewind(); p->getC8(); p->getC8(); //discard if (p->isOverRun()) { push_error_packet(0, 0, 0, "Invalid Packet"); terminate(); return ; } t = createTxPacket(XIM_CONNECT_REPLY, 0); t->pushC16(1); t->pushC16(0); push_packet(t); if (g_option_mask & OPT_TRACE) { printf("accept xim connection.\n"); } } void Connection::xim_disconnect(RxPacket *p) { TxPacket *t; t = createTxPacket(XIM_DISCONNECT_REPLY,0); push_packet(t); // terminate(); if (g_option_mask & OPT_TRACE) { printf("disconnect xim connection.\n"); } } void Connection::xim_open(RxPacket *p) { char buf[16]; int l; for (l = 0; l < 16; l++) { buf[l] = 0; } l = p->getStr8Len(); if (l > 15) { printf("too long locale name.\n"); return ; } p->getStr8(buf); TxPacket *t; int imid; imid = unused_im_id(); mCreatedIm.push_back(imid);//作ったやつが責任もって破棄する。 create_im(this, imid); t = createTxPacket(XIM_OPEN_REPLY, 0); t->pushC16(imid); XIMATTRIBUTE::write_imattr_to_packet(t); XICATTRIBUTE::write_icattr_to_packet(t); push_packet(t); // イベントマスクの選択 t = createTxPacket(XIM_SET_EVENT_MASK, 0); t->pushC16(imid); t->pushC16(0); t->pushC32(KeyPressMask); t->pushC32(KeyPressMask); push_packet(t); } void Connection::xim_close(RxPacket *p) { int imid; imid = p->getC16(); TxPacket *t; t = createTxPacket(XIM_CLOSE_REPLY,0); t->pushC16(imid); t->pushC16(0); push_packet(t); close_im(imid); std::list::iterator i; for (i = mCreatedIm.begin(); i != mCreatedIm.end(); i++) { if (*i == imid) { mCreatedIm.erase(i); return; } } } void Connection::xim_query_extension(RxPacket *p) { int imid; imid = p->getC16(); TxPacket *t; t = createTxPacket(XIM_QUERY_EXTENSION_REPLY, 0); t->pushC16(imid); t->pushC16(0); push_packet(t); } void Connection::xim_encoding_negotiation(RxPacket *p) { TxPacket *t; t = createTxPacket(XIM_ENCODING_NEGOTIATION_REPLY,0); C16 l, m, s; int i, idx, index; int imid; char buf[32]; imid = p->getC16(); // m_imid l = p->getC16(); index = 0; for (m = 0, s = 0, idx = 0; m < l; m += (s+1), idx ++) { s = p->getStr8Len (); for (i= 0; i < 32; i++) { buf[i] = 0; } p->getStr8 (buf); /* COMPOUND_TEXT (eucJP is Buggy) */ if (!strcmp ("COMPOUND_TEXT", buf)) { index = idx; } } t->pushC16(imid); t->pushC16(0); t->pushC16(index); t->pushC16(0); push_packet(t); } void Connection::xim_get_im_values(RxPacket *p) { int l,i; int imid; TxPacket *t; t = createTxPacket(XIM_GET_IM_VALUES_REPLY, 0); imid = p->getC16(); // input-method id l = p->getC16() / 2; //個数 int *ra = (int *)alloca(sizeof(int)*l); int rlen = 0; for (i = 0; i < l; i++) { ra[i] = p->getC16(); rlen += 4; } // どうせIMAttributeは1種類しかないんだし、、 t->pushC16(imid); t->pushC16(16); // length // XIMATTRIBUTE int nr_style; for (nr_style = 0; input_style_tab[nr_style].style; nr_style ++); t->pushC16(0); // attribute id t->pushC16(nr_style*4); //length t->pushC16(nr_style); // 個数 t->pushC16(0); for (i = 0; i < nr_style; i++) { t->pushC32(input_style_tab[i].x_style); } push_packet(t); } void Connection::xim_set_ic_values(RxPacket *p) { int imid, icid; imid = p->getC16(); icid = p->getC16(); p->rewind(); XimIM *im = get_im_by_id(imid); if (im) { im->set_ic_values(p, icid); } TxPacket *t=createTxPacket(XIM_SET_IC_VALUES_REPLY,0); t->pushC16(imid); t->pushC16(icid); push_packet(t); } void Connection::xim_get_ic_values(RxPacket *p) { int imid; imid = p->getC16(); p->rewind(); XimIM *im; im = get_im_by_id(imid); if (im) { im->get_ic_values(p); } } void Connection::xim_create_ic(RxPacket *p) { XimIM *im; int imid; imid = p->getC16(); p->rewind(); im = get_im_by_id(imid); if (im) { im->create_ic(p); } } void Connection::xim_destroy_ic(RxPacket *p) { int imid; int icid; imid = p->getC16(); icid = p->getC16(); XimIM *im = get_im_by_id(imid); if (im) { im->destroy_ic(icid); } TxPacket *t = createTxPacket(XIM_DESTROY_IC_REPLY,0); t->pushC16(imid); t->pushC16(icid); push_packet(t); } void Connection::xim_set_ic_focus(RxPacket *p) { int imid; XimIM *im; imid = p->getC16(); im = get_im_by_id(imid); if (im) { im->set_ic_focus(p->getC16()); } } void Connection::xim_unset_ic_focus(RxPacket *p) { int imid; XimIM *im; imid = p->getC16(); im = get_im_by_id(imid); if (im) { im->unset_ic_focus(p->getC16()); } } void Connection::xim_forward_event(RxPacket *p) { int imid,icid; imid = p->getC16(); icid = p->getC16(); p->rewind(); XimIM *im = get_im_by_id(imid); if (im) { im->forward_event(p); } TxPacket *t = createTxPacket(XIM_SYNC_REPLY,0); t->pushC16(imid); t->pushC16(icid); push_packet(t); } void Connection::xim_reset_ic(RxPacket *p) { XimIC *ic = get_ic(p); if (ic) { ic->reset_ic(); } } void Connection::xim_error(RxPacket *p) { int imid,icid,mask,ecode,len; char *buf; imid = p->getC16(); icid = p->getC16(); mask = p->getC16(); ecode = p->getC16(); len = p->getStrLen(); buf = (char *)alloca(len+1); buf[len] = 0; p->getStr(buf); printf("XIM_ERROR received.\n"); if (mask & 1) { printf(" imid = %d\n", imid); } if (mask & 2) { printf(" icid = %d\n", icid); } printf(" error_code = %d\n", ecode); printf(" message=(%s)\n", buf); } XimIC *Connection::get_ic(RxPacket *p) { int imid,icid; XimIM *im; imid = p->getC16(); icid = p->getC16(); p->rewind(); im = get_im_by_id(imid); if (im) { return im->get_ic_by_id(icid); } return 0; } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * End: */