diff options
Diffstat (limited to 'lib/libX11/modules/im/ximcp/imDefIm.c')
-rw-r--r-- | lib/libX11/modules/im/ximcp/imDefIm.c | 2028 |
1 files changed, 2028 insertions, 0 deletions
diff --git a/lib/libX11/modules/im/ximcp/imDefIm.c b/lib/libX11/modules/im/ximcp/imDefIm.c new file mode 100644 index 000000000..a1c83a917 --- /dev/null +++ b/lib/libX11/modules/im/ximcp/imDefIm.c @@ -0,0 +1,2028 @@ +/* $Xorg: imDefIm.c,v 1.5 2000/08/17 19:45:12 cpqbld Exp $ */ +/****************************************************************** + Copyright 1990, 1991, 1992 by Sun Microsystems, Inc. + Copyright 1992, 1993, 1994 by FUJITSU LIMITED + Copyright 1993, 1994 by Sony Corporation + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation, and +that the name of Sun Microsystems, Inc., FUJITSU LIMITED and Sony +Corporation not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. +Sun Microsystems, Inc., FUJITSU LIMITED and Sony Corporation makes no +representations about the suitability of this software for any purpose. It +is provided "as is" without express or implied warranty. + +Sun Microsystems Inc., FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Sun Microsystems, Inc., +FUJITSU LIMITED AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. + + Author: Hideki Hiura (hhiura@Sun.COM) Sun Microsystems, Inc. + Takashi Fujiwara FUJITSU LIMITED + fujiwara@a80.tech.yk.fujitsu.co.jp + Makoto Wakamatsu Sony Corporation + makoto@sm.sony.co.jp + +******************************************************************/ +/* $XFree86: xc/lib/X11/imDefIm.c,v 1.15 2003/08/22 19:27:24 eich Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/Xatom.h> +#define NEED_EVENTS +#include "Xlibint.h" +#include "Xlcint.h" +#include "XlcPublic.h" +#include "XlcPubI.h" +#include "XimTrInt.h" +#include "Ximint.h" + + +Public int +_XimCheckDataSize( + XPointer buf, + int len) +{ + CARD16 *buf_s = (CARD16 *)buf; + + if(len < XIM_HEADER_SIZE) + return -1; + return buf_s[1]; +} + +Public void +_XimSetHeader( + XPointer buf, + CARD8 major_opcode, + CARD8 minor_opcode, + INT16 *len +) +{ + CARD8 *buf_b = (CARD8 *)buf; + CARD16 *buf_s = (CARD16 *)buf; + + buf_b[0] = major_opcode; + buf_b[1] = minor_opcode; + buf_s[1] = ((*len) / 4); + *len += XIM_HEADER_SIZE; + return; +} + +Public char +_XimGetMyEndian(void) +{ + CARD16 test_card = 1; + + if(*((char *)&test_card)) + return LITTLEENDIAN; + else + return BIGENDIAN; +} + +Private Bool +_XimCheckServerName( + Xim im, + char *str) +{ + char *server_name = im->core.im_name; + int len; + int str_len; + int category_len = strlen(XIM_SERVER_CATEGORY); + char *pp; + register char *p; + + if(server_name && *server_name) + len = strlen(server_name); + else + return True; + + if((int)strlen(str) < category_len) + return False; + + if(strncmp(str, XIM_SERVER_CATEGORY, category_len)) + return False; + + pp = &str[category_len]; + + for(;;) { + for(p = pp; (*p != ',') && (*p); p++); + str_len = (int)(p - pp); + + if((len == str_len) && (!strncmp(pp, server_name, len))) + break; + if(!(*p)) + return False; + pp = p + 1; + } + return True; +} + +Private char * +_XimCheckLocaleName( + Xim im, + char *address, + int address_len, + char *locale_name[], + int len) +{ + int category_len; + char *pp; + register char *p; + register int n; + Bool finish = False; + + category_len = strlen(XIM_LOCAL_CATEGORY); + if(address_len < category_len) + return (char*)NULL; + + if(strncmp(address, XIM_LOCAL_CATEGORY, category_len)) + return (char*)NULL; + + pp = &address[category_len]; + + for(;;) { + for( p = pp; *p && *p != ','; p++); + if (!*p) + finish = True; + address_len = (int)(p - pp); + *p = '\0'; + + for( n = 0; n < len; n++ ) + if( locale_name[n] && !_XlcCompareISOLatin1( pp, locale_name[n] ) ) + return locale_name[n]; + if (finish) + break; + pp = p + 1; + } + return (char *)NULL; +} + +Private Bool +_XimCheckTransport( + char *address, + int address_len, + char *transport, + int len, + char **trans_addr) +{ + int category_len = strlen(XIM_TRANSPORT_CATEGORY); + char *pp; + register char *p; + + if(address_len < category_len) + return False; + + if(strncmp(address, XIM_TRANSPORT_CATEGORY, category_len)) + return False; + + pp = &address[category_len]; + + for(;;) { + *trans_addr = pp; + + for(p = pp; (*p != '/') && (*p != ',') && (*p); p++); + if(*p == ',') { + pp = p + 1; + continue; + } + if(!(*p)) + return False; + + address_len = (int)(p - pp); + + if((len == address_len) && (!strncmp(pp, transport, len))) + break; + pp = p + 1; + } + pp = p + 1; + for(p = pp; (*p != ',') && (*p); p++); + if (*p) + *p = '\0'; + return True; +} + +Private Bool +_CheckSNEvent( + Display *display, + XEvent *xevent, + XPointer arg) +{ + XSelectionEvent *event = (XSelectionEvent *)xevent; + Window window = *(Window*)arg; + + if((event->type == SelectionNotify) && (window == event->requestor)) + return True; + return False; +} + +Private Bool +_XimGetSelectionNotify( + Display *display, + Window window, + Atom target, + char **ret_address) +{ + XEvent event; + XSelectionEvent *ev = (XSelectionEvent *)&event; + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + + for(;;) { + XIfEvent(display, &event, _CheckSNEvent, (XPointer)&window); + if((ev->type == SelectionNotify) && (window == ev->requestor)) + break; + } + + if(ev->property == (Atom)None) + return False; + if( XGetWindowProperty( display, window, target, 0L, 1000000L, + True, target, &actual_type, &actual_format, + &nitems, &bytes_after, + (unsigned char **)&*ret_address ) != Success ) + return False; + return True; +} + +Private Bool +_XimPreConnectionIM( + Xim im, + Atom selection) +{ + Display *display = im->core.display; + Atom locales, transport; + char *address; + XLCd lcd; + char *language; + char *territory; + char *codeset; + char *trans_addr; + char *locale_name[4], *locale; + int llen, tlen, clen; + register int i; + Window window; + char *str; + + if(!(lcd = im->core.lcd)) + return False; + + for( i = 0; i < 4; i++ ) + locale_name[i] = NULL; + /* requestor window */ + if(!(window = XCreateSimpleWindow(display, DefaultRootWindow(display), + 0, 0, 1, 1, 1, 0, 0))) + return False; + + /* server name check */ + if( !(str = XGetAtomName( display, selection )) ) + return False; + if(!_XimCheckServerName(im, str)) { + XFree( (XPointer)str ); + goto Error; + } + XFree( (XPointer)str ); + + /* locale name check */ + _XGetLCValues(lcd, XlcNLanguage, &language, XlcNTerritory, &territory, + XlcNCodeset, &codeset, NULL); + llen = strlen( language ); + tlen = territory ? strlen( territory ): 0; + clen = codeset ? strlen( codeset ): 0; + + if( tlen != 0 && clen != 0 ) { + if( (locale_name[0] = Xmalloc(llen+tlen+clen+3)) != NULL ) + sprintf( locale_name[0], "%s_%s.%s", language, territory, codeset ); + } + if( clen != 0 ) { + if( (locale_name[1] = Xmalloc(llen+clen+2)) != NULL ) + sprintf( locale_name[1], "%s.%s", language, codeset ); + else + goto Error; + } + if( tlen != 0 ) { + if( (locale_name[2] = Xmalloc(llen+tlen+2)) != NULL ) + sprintf( locale_name[2], "%s_%s", language, territory ); + else + goto Error; + } + if( (locale_name[3] = Xmalloc(llen+1)) != NULL ) + strcpy( locale_name[3], language ); + else + goto Error; + if((locales = XInternAtom(display, XIM_LOCALES, True)) == (Atom)None) + goto Error; + + XConvertSelection(display, selection, locales, locales, window, + CurrentTime); + if(!(_XimGetSelectionNotify(display, window, locales, &address))) + goto Error; + + if((locale = _XimCheckLocaleName(im, address, strlen(address), locale_name, + 4)) == NULL) { + XFree((XPointer)address); + goto Error; + } + im->private.proto.locale_name = locale; + for( i = 0; i < 4; i++ ) { + if( locale_name[i] != NULL && locale_name[i] != locale ) { + XFree( locale_name[i] ); + locale_name[i] = NULL; + } + } + XFree((XPointer)address); + + /* transport check */ + if((transport = XInternAtom(display, XIM_TRANSPORT, True)) == (Atom)None) + goto Error; + + XConvertSelection(display, selection, transport, transport, window, + CurrentTime); + if(!_XimGetSelectionNotify(display, window, transport, &address)) + goto Error; + + for(i = 0; _XimTransportRec[i].transportname ; i++) { + if( _XimCheckTransport(address, strlen(address), + _XimTransportRec[i].transportname, + strlen(_XimTransportRec[i].transportname), + &trans_addr)) { + if( _XimTransportRec[i].config(im, trans_addr) ) { + XFree((XPointer)address); + XDestroyWindow(display, window); + return True; + } + } + } + + XFree((XPointer)address); +Error: + for( i = 0; i < 4; i++ ) + if( locale_name[i] != NULL ) + XFree( locale_name[i] ); + XDestroyWindow(display, window); + return False; +} + +Private Bool +_XimPreConnect( + Xim im) +{ + Display *display = im->core.display; + Atom imserver; + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop_return; + Atom *atoms; + Window im_window = 0; + register int i; + + if((imserver = XInternAtom(display, XIM_SERVERS, True)) == (Atom)None) + return False; + + if(XGetWindowProperty(display, RootWindow(display, 0), + imserver, 0L, 1000000L, False, XA_ATOM, &actual_type, + &actual_format, &nitems, &bytes_after, + &prop_return) != Success) + return False; + + if( (actual_type != XA_ATOM) || (actual_format != 32) ) { + if( nitems ) + XFree((XPointer)prop_return); + return False; + } + + atoms = (Atom *)prop_return; + for(i = 0; i < nitems; i++) { + if((im_window = XGetSelectionOwner(display, atoms[i])) == (Window)None) + continue; + + if(_XimPreConnectionIM(im, atoms[i])) + break; + } + + XFree((XPointer)prop_return); + if(i >= nitems) + return False; + + im->private.proto.im_window = im_window; + return True; +} + +Private Bool +_XimGetAuthProtocolNames( + Xim im, + CARD16 *buf, + CARD8 *num, + INT16 *len) +{ + if (!IS_USE_AUTHORIZATION_FUNC(im)) { + *num = 0; + *len = 0; + return True; + } + /* + * Not yet + */ + return True; +} + +Private Bool +_XimSetAuthReplyData( + Xim im, + XPointer buf, + INT16 *len) +{ + /* + * Not yet + */ + *len = 0; + return True; +} + +Private Bool +_XimSetAuthNextData( + Xim im, + XPointer buf, + INT16 *len) +{ + /* + * Not yet + */ + *len = 0; + return True; +} + +Private Bool +_XimSetAuthRequiredData( + Xim im, + XPointer buf, + INT16 *len) +{ + /* + * Not yet + */ + *len = 0; + return True; +} + +Private Bool +_XimCheckAuthSetupData( + Xim im, + XPointer buf) +{ + /* + * Not yet + */ + return True; +} + +Private Bool +_XimCheckAuthNextData( + Xim im, + XPointer buf) +{ + /* + * Not yet + */ + return True; +} + +#define NO_MORE_AUTH 2 +#define GOOD_AUTH 1 +#define BAD_AUTH 0 + +Private int +_XimClientAuthCheck( + Xim im, + XPointer buf) +{ + /* + * Not yet + */ + return NO_MORE_AUTH; +} + +Private void +_XimAuthNG( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + INT16 len = 0; + + _XimSetHeader((XPointer)buf, XIM_AUTH_NG, 0, &len); + (void)_XimWrite(im, len, (XPointer)buf); + _XimFlush(im); + return; +} + +Private Bool +_XimAllRecv( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + return True; +} + +#define CLIENT_WAIT1 1 +#define CLIENT_WAIT2 2 + +Private Bool +_XimConnection( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD8 *buf_b = &buf[XIM_HEADER_SIZE]; + CARD16 *buf_s = (CARD16 *)((XPointer)buf_b); + INT16 len; + CARD8 num; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + CARD8 major_opcode; + int wait_mode; + int ret; + + if(!(_XimConnect(im))) /* Transport Connect */ + return False; + + if(!_XimDispatchInit(im)) + return False; + + _XimRegProtoIntrCallback(im, XIM_ERROR, 0, _XimErrorCallback, (XPointer)im); + + if(!_XimGetAuthProtocolNames(im, &buf_s[4], &num, &len)) + return False; + + im->private.proto.protocol_major_version = PROTOCOLMAJORVERSION; + im->private.proto.protocol_minor_version = PROTOCOLMINORVERSION; + + buf_b[0] = _XimGetMyEndian(); + buf_b[1] = 0; + buf_s[1] = PROTOCOLMAJORVERSION; + buf_s[2] = PROTOCOLMINORVERSION; + buf_s[3] = num; + len += sizeof(CARD8) + + sizeof(CARD8) + + sizeof(CARD16) + + sizeof(CARD16) + + sizeof(CARD16); + + major_opcode = XIM_CONNECT; + wait_mode = (IS_USE_AUTHORIZATION_FUNC(im)) ? CLIENT_WAIT1 : CLIENT_WAIT2; + + for(;;) { + _XimSetHeader((XPointer)buf, major_opcode, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, reply, buf_size, _XimAllRecv, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, _XimAllRecv, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + + major_opcode = *((CARD8 *)preply); + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + + if (wait_mode == CLIENT_WAIT1) { + if (major_opcode == XIM_AUTH_REQUIRED) { + ret = _XimClientAuthCheck(im, (XPointer)buf_s); + if(reply != preply) + Xfree(preply); + if (ret == NO_MORE_AUTH) { + if (!(_XimSetAuthReplyData(im, + (XPointer)&buf[XIM_HEADER_SIZE], &len))) { + _XimAuthNG(im); + return False; + } + major_opcode = XIM_AUTH_REPLY; + wait_mode = CLIENT_WAIT2; + } else if (ret == GOOD_AUTH) { + if (!(_XimSetAuthNextData(im, + (XPointer)&buf[XIM_HEADER_SIZE], &len))) { + _XimAuthNG(im); + return False; + } + major_opcode = XIM_AUTH_NEXT; + } else { /* BAD_AUTH */ + _XimAuthNG(im); + return False; + } + } else { + if(reply != preply) + Xfree(preply); + _XimAuthNG(im); + return False; + } + } else { /* CLIENT_WAIT2 */ + if (major_opcode == XIM_CONNECT_REPLY) { + break; + } else if (major_opcode == XIM_AUTH_SETUP) { + if (!(_XimCheckAuthSetupData(im, (XPointer)buf_s))) { + _XimAuthNG(im); + return False; + } + if(reply != preply) + Xfree(preply); + if (!(_XimSetAuthRequiredData(im, + (XPointer)&buf[XIM_HEADER_SIZE], &len))) { + _XimAuthNG(im); + return False; + } + major_opcode = XIM_AUTH_REQUIRED; + } else if (major_opcode == XIM_AUTH_NEXT) { + if (!(_XimCheckAuthNextData(im, (XPointer)buf_s))) { + _XimAuthNG(im); + return False; + } + if(reply != preply) + Xfree(preply); + if (!(_XimSetAuthRequiredData(im, + (XPointer)&buf[XIM_HEADER_SIZE], &len))) { + _XimAuthNG(im); + return False; + } + major_opcode = XIM_AUTH_REQUIRED; + } else if (major_opcode == XIM_AUTH_NG) { + if(reply != preply) + Xfree(preply); + return False; + } else { + _XimAuthNG(im); + if(reply != preply) + Xfree(preply); + return False; + } + } + } + + if (!( buf_s[0] == im->private.proto.protocol_major_version + && buf_s[1] == im->private.proto.protocol_minor_version)) { + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + MARK_SERVER_CONNECTED(im); + + _XimRegProtoIntrCallback(im, XIM_REGISTER_TRIGGERKEYS, 0, + _XimRegisterTriggerKeysCallback, (XPointer)im); + return True; +} + +Private Bool +_XimDisconnectCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + + if ((major_opcode == XIM_DISCONNECT_REPLY) + && (minor_opcode == 0)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0)) + return True; + return False; +} + +Private Bool +_XimDisconnect( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + INT16 len = 0; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + + if (IS_SERVER_CONNECTED(im)) { + _XimSetHeader((XPointer)buf, XIM_DISCONNECT, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimDisconnectCheck, 0); + if(ret_code == XIM_OVERFLOW) { + if(len > 0) { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimDisconnectCheck, 0); + Xfree(preply); + if(ret_code != XIM_TRUE) + return False; + } + } else if(ret_code == XIM_FALSE) + return False; + + } + if (!(_XimShutdown(im))) /* Transport shutdown */ + return False; + return True; +} + +Private Bool +_XimOpenCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + + if ((major_opcode == XIM_OPEN_REPLY) + && (minor_opcode == 0)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0)) + return True; + return False; +} + +Private Bool +_XimOpen( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD8 *buf_b = &buf[XIM_HEADER_SIZE]; + CARD16 *buf_s; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + char *locale_name; + + locale_name = im->private.proto.locale_name; + len = strlen(locale_name); + buf_b[0] = (BYTE)len; /* length of locale name */ + (void)strcpy((char *)&buf_b[1], locale_name); /* locale name */ + len += sizeof(BYTE); /* sizeof length */ + XIM_SET_PAD(buf_b, len); /* pad */ + + _XimSetHeader((XPointer)buf, XIM_OPEN, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, reply, buf_size, + _XimOpenCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimOpenCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + + im->private.proto.imid = buf_s[0]; /* imid */ + + if (!(_XimGetAttributeID(im, &buf_s[1]))) { + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + + if (!(_XimSetInnerIMResourceList(&(im->private.proto.im_inner_resources), + &(im->private.proto.im_num_inner_resources)))) + return False; + + if (!(_XimSetInnerICResourceList(&(im->private.proto.ic_inner_resources), + &(im->private.proto.ic_num_inner_resources)))) + return False; + + _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); + _XimSetIMMode(im->private.proto.im_inner_resources, + im->private.proto.im_num_inner_resources); + + /* Transport Callbak */ + _XimRegProtoIntrCallback(im, XIM_SET_EVENT_MASK, 0, + _XimSetEventMaskCallback, (XPointer)im); + _XimRegProtoIntrCallback(im, XIM_FORWARD_EVENT, 0, + _XimForwardEventCallback, (XPointer)im); + _XimRegProtoIntrCallback(im, XIM_COMMIT, 0, + _XimCommitCallback, (XPointer)im); + _XimRegProtoIntrCallback(im, XIM_SYNC, 0, + _XimSyncCallback, (XPointer)im); + + if(!_XimExtension(im)) + return False; + + /* register a hook for callback protocols */ + _XimRegisterDispatcher(im, _XimCbDispatch, (XPointer)im); + + return True; +} + +Private Bool +_XimCloseCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_CLOSE_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +Private Bool +_XimClose( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + + if (!IS_SERVER_CONNECTED(im)) + return True; + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = 0; /* unused */ + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof unused */ + + _XimSetHeader((XPointer)buf, XIM_CLOSE, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimCloseCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, _XimCloseCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + + if(reply != preply) + Xfree(preply); + return True; +} + +Public void +_XimProtoIMFree( + Xim im) +{ + /* XIMPrivateRec */ + if (im->private.proto.im_onkeylist) { + Xfree(im->private.proto.im_onkeylist); + im->private.proto.im_onkeylist = NULL; + } + if (im->private.proto.im_offkeylist) { + Xfree(im->private.proto.im_offkeylist); + im->private.proto.im_offkeylist = NULL; + } + if (im->private.proto.intrproto) { + _XimFreeProtoIntrCallback(im); + im->private.proto.intrproto = NULL; + } + if (im->private.proto.im_inner_resources) { + Xfree(im->private.proto.im_inner_resources); + im->private.proto.im_inner_resources = NULL; + } + if (im->private.proto.ic_inner_resources) { + Xfree(im->private.proto.ic_inner_resources); + im->private.proto.ic_inner_resources = NULL; + } + if (im->private.proto.hold_data) { + Xfree(im->private.proto.hold_data); + im->private.proto.hold_data = NULL; + } + if (im->private.proto.locale_name) { + Xfree(im->private.proto.locale_name); + im->private.proto.locale_name = NULL; + } + if (im->private.proto.ctom_conv) { + _XlcCloseConverter(im->private.proto.ctom_conv); + im->private.proto.ctom_conv = NULL; + } + if (im->private.proto.ctow_conv) { + _XlcCloseConverter(im->private.proto.ctow_conv); + im->private.proto.ctow_conv = NULL; + } + if (im->private.proto.ctoutf8_conv) { + _XlcCloseConverter(im->private.proto.ctoutf8_conv); + im->private.proto.ctoutf8_conv = NULL; + } + if (im->private.proto.cstomb_conv) { + _XlcCloseConverter(im->private.proto.cstomb_conv); + im->private.proto.cstomb_conv = NULL; + } + if (im->private.proto.cstowc_conv) { + _XlcCloseConverter(im->private.proto.cstowc_conv); + im->private.proto.cstowc_conv = NULL; + } + if (im->private.proto.cstoutf8_conv) { + _XlcCloseConverter(im->private.proto.cstoutf8_conv); + im->private.proto.cstoutf8_conv = NULL; + } + if (im->private.proto.ucstoc_conv) { + _XlcCloseConverter(im->private.proto.ucstoc_conv); + im->private.proto.ucstoc_conv = NULL; + } + if (im->private.proto.ucstoutf8_conv) { + _XlcCloseConverter(im->private.proto.ucstoutf8_conv); + im->private.proto.ucstoutf8_conv = NULL; + } + +#ifdef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) { + return; + } +#endif /* XIM_CONNECTABLE */ + + if (im->private.proto.saved_imvalues) { + Xfree(im->private.proto.saved_imvalues); + im->private.proto.saved_imvalues = NULL; + } + if (im->private.proto.default_styles) { + Xfree(im->private.proto.default_styles); + im->private.proto.default_styles = NULL; + } + + /* core */ + if (im->core.res_name) { + Xfree(im->core.res_name); + im->core.res_name = NULL; + } + if (im->core.res_class) { + Xfree(im->core.res_class); + im->core.res_class = NULL; + } + if (im->core.im_values_list) { + Xfree(im->core.im_values_list); + im->core.im_values_list = NULL; + } + if (im->core.ic_values_list) { + Xfree(im->core.ic_values_list); + im->core.ic_values_list = NULL; + } + if (im->core.im_name) { + Xfree(im->core.im_name); + im->core.im_name = NULL; + } + if (im->core.styles) { + Xfree(im->core.styles); + im->core.styles = NULL; + } + if (im->core.im_resources) { + Xfree(im->core.im_resources); + im->core.im_resources = NULL; + } + if (im->core.ic_resources) { + Xfree(im->core.ic_resources); + im->core.ic_resources = NULL; + } + + return; +} + +Private Status +_XimProtoCloseIM( + XIM xim) +{ + Xim im = (Xim)xim; + XIC ic; + XIC next; + Status status; + + ic = im->core.ic_chain; + while (ic) { + (*ic->methods->destroy) (ic); + next = ic->core.next; +#ifdef XIM_CONNECTABLE + if (!(!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im))) { + Xfree ((char *) ic); + } +#else + Xfree ((char *) ic); +#endif /* XIM_CONNECTABLE */ + ic = next; + } +#ifdef XIM_CONNECTABLE + if (!(!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im))) + im->core.ic_chain = NULL; +#else + im->core.ic_chain = NULL; +#endif + + _XimUnregisterServerFilter(im); + _XimResetIMInstantiateCallback(im); + status = (Status)_XimClose(im); + status = (Status)_XimDisconnect(im) && status; + _XimProtoIMFree(im); +#ifdef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) { + _XimReconnectModeSetAttr(im); + for (ic = im->core.ic_chain; ic; ic = ic->core.next) { + _XimReconnectModeCreateIC(ic); + } + return 0; + } +#endif /* XIM_CONNECTABLE */ + _XimDestroyIMStructureList(im); + return status; +} + +#ifdef XIM_CONNECTABLE +Private Bool +_XimCheckIMQuarkList( + XrmQuark *quark_list, + int num_quark, + XrmQuark quark) +{ + register int i; + + for (i = 0; i < num_quark; i++) { + if (quark_list[i] == quark) { + return True; + } + } + return False; +} + +Private Bool +_XimSaveIMValues( + Xim im, + XIMArg *arg) +{ + register XIMArg *p; + register int n; + XrmQuark *quark_list; + XrmQuark *tmp; + XrmQuark quark; + int num_quark; + + if (quark_list = im->private.proto.saved_imvalues) { + num_quark = im->private.proto.num_saved_imvalues; + for (p = arg; p && p->name; p++) { + quark = XrmStringToQuark(p->name); + if (_XimCheckIMQuarkList(quark_list, num_quark, quark)) { + continue; + } + if (!(tmp = (XrmQuark *)Xrealloc(quark_list, + (sizeof(XrmQuark) * (num_quark + 1))))) { + im->private.proto.saved_imvalues = quark_list; + im->private.proto.num_saved_imvalues = num_quark; + return False; + } + num_quark++; + quark_list = tmp; + quark_list[num_quark] = quark; + } + im->private.proto.saved_imvalues = quark_list; + im->private.proto.num_saved_imvalues = num_quark; + return True; + } + + for (p = arg, n = 0; p && p->name; p++, n++); + + if (!(quark_list = (XrmQuark *)Xmalloc(sizeof(XrmQuark) * n))) { + return False; + } + + im->private.proto.saved_imvalues = quark_list; + im->private.proto.num_saved_imvalues = n; + for (p = arg; p && p->name; p++, quark_list++) { + *quark_list = XrmStringToQuark(p->name); + } + + return True; +} + +Private char * +_XimDelayModeSetIMValues( + Xim im, + XIMArg *arg) +{ + XimDefIMValues im_values; + char *name; + XIMArg *values; + + _XimGetCurrentIMValues(im, &im_values); + name = _XimSetIMValueData(im, (XPointer)&im_values, values, + im->core.im_resources, im->core.im_num_resources); + _XimSetCurrentIMValues(im, &im_values); + + return name; +} +#endif /* XIM_CONNECTABLE */ + +Private Bool +_XimSetIMValuesCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_SET_IM_VALUES_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +Private char * +_XimProtoSetIMValues( + XIM xim, + XIMArg *arg) +{ + Xim im = (Xim)xim; + XimDefIMValues im_values; + INT16 len; + CARD16 *buf_s; + char *tmp; + CARD32 tmp_buf32[BUFSIZE/4]; + char *tmp_buf = (char *)tmp_buf32; + char *buf; + int buf_size; + char *data; + int data_len; + int ret_len; + int total; + XIMArg *arg_ret; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int ret_code; + char *name; + +#ifndef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im)) + return arg->name; +#else + if (!_XimSaveIMValues(im, arg)) + return arg->name; + + if (!IS_SERVER_CONNECTED(im)) { + if (IS_CONNECTABLE(im)) { + if (!_XimConnectServer(im)) { + return _XimDelayModeSetIMValues(im, arg); + } + } else { + return arg->name; + } + } +#endif /* XIM_CONNECTABLE */ + + _XimGetCurrentIMValues(im, &im_values); + buf = tmp_buf; + buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); + data_len = BUFSIZE - buf_size; + total = 0; + arg_ret = arg; + for (;;) { + data = &buf[buf_size]; + if ((name = _XimEncodeIMATTRIBUTE(im, im->core.im_resources, + im->core.im_num_resources, arg, &arg_ret, data, data_len, + &ret_len, (XPointer)&im_values, XIM_SETIMVALUES))) { + if (buf != tmp_buf) + Xfree(buf); + break; + } + + total += ret_len; + if (!(arg = arg_ret)) { + break; + } + + buf_size += ret_len; + if (buf == tmp_buf) { + if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { + return arg->name; + } + memcpy(tmp, buf, buf_size); + buf = tmp; + } else { + if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { + Xfree(buf); + return arg->name; + } + buf = tmp; + } + } + _XimSetCurrentIMValues(im, &im_values); + + if (!total) + return (char *)NULL; + + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + buf_s[0] = im->private.proto.imid; + buf_s[1] = (INT16)total; + + len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); + _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + if (buf != tmp_buf) + Xfree(buf); + return arg->name; + } + _XimFlush(im); + if (buf != tmp_buf) + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimSetIMValuesCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = (int)len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, reply, buf_size, + _XimSetIMValuesCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return arg->name; + } + } + } else + return arg->name; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return arg->name; + } + if(reply != preply) + Xfree(preply); + + return name; +} + +#ifdef XIM_CONNECTABLE +Private char * +_XimDelayModeGetIMValues( + Xim im, + XIMArg *arg) +{ + XimDefIMValues im_values; + + _XimGetCurrentIMValues(im, &im_values); + return(_XimGetIMValueData(im, (XPointer)&im_values, arg, + im->core.im_resources, im->core.im_num_resources)); +} +#endif /* XIM_CONNECTABLE */ + +Private Bool +_XimGetIMValuesCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_GET_IM_VALUES_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +Private char * +_XimProtoGetIMValues( + XIM xim, + XIMArg *arg) +{ + Xim im = (Xim)xim; + register XIMArg *p; + register int n; + CARD8 *buf; + CARD16 *buf_s; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply = NULL; + int buf_size; + int ret_code; + char *makeid_name; + char *decode_name; + CARD16 *data = NULL; + INT16 data_len = 0; + +#ifndef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im)) + return arg->name; +#else + if (!IS_SERVER_CONNECTED(im)) { + if (IS_CONNECTABLE(im)) { + if (!_XimConnectServer(im)) { + return _XimDelayModeGetIMValues(im, arg); + } + } else { + return arg->name; + } + } +#endif /* XIM_CONNECTABLE */ + + for (n = 0, p = arg; p->name; p++) + n++; + + if (!n) + return (char *)NULL; + + buf_size = sizeof(CARD16) * n; + buf_size += XIM_HEADER_SIZE + + sizeof(CARD16) + + sizeof(INT16) + + XIM_PAD(buf_size); + + if (!(buf = (CARD8 *)Xmalloc(buf_size))) + return arg->name; + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + + makeid_name = _XimMakeIMAttrIDList(im, im->core.im_resources, + im->core.im_num_resources, arg, + &buf_s[2], &len, XIM_GETIMVALUES); + + if (len) { + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = len; /* length of im-attr-id */ + XIM_SET_PAD(&buf_s[2], len); /* pad */ + len += sizeof(CARD16) /* sizeof imid */ + + sizeof(INT16); /* sizeof length of attr */ + + _XimSetHeader((XPointer)buf, XIM_GET_IM_VALUES, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + Xfree(buf); + return arg->name; + } + _XimFlush(im); + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimGetIMValuesCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimGetIMValuesCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return arg->name; + } + } + } else + return arg->name; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return arg->name; + } + data = &buf_s[2]; + data_len = buf_s[1]; + } + decode_name = _XimDecodeIMATTRIBUTE(im, im->core.im_resources, + im->core.im_num_resources, data, data_len, + arg, XIM_GETIMVALUES); + if (reply != preply) + Xfree(preply); + + if (decode_name) + return decode_name; + else + return makeid_name; +} + +Private XIMMethodsRec im_methods = { + _XimProtoCloseIM, /* close */ + _XimProtoSetIMValues, /* set_values */ + _XimProtoGetIMValues, /* get_values */ + _XimProtoCreateIC, /* create_ic */ + _Ximctstombs, /* ctstombs */ + _Ximctstowcs, /* ctstowcs */ + _Ximctstoutf8 /* ctstoutf8 */ +}; + +Private Bool +_XimSetEncodingByName( + Xim im, + char **buf, + int *len) +{ + char *encoding = (char *)NULL; + int encoding_len; + int compound_len; + BYTE *ret; + + _XGetLCValues(im->core.lcd, XlcNCodeset, &encoding, NULL); + if (!encoding) { + *buf = (char *)NULL; + *len = 0; + return True; + } + encoding_len = strlen(encoding); + compound_len = strlen("COMPOUND_TEXT"); + *len = encoding_len + sizeof(BYTE) + compound_len + sizeof(BYTE); + if (!(ret = (BYTE *)Xmalloc(*len))) { + return False; + } + *buf = (char *)ret; + + ret[0] = (BYTE)encoding_len; + (void)strncpy((char *)&ret[1], encoding, encoding_len); + ret += (encoding_len + sizeof(BYTE)); + ret[0] = (BYTE)compound_len; + (void)strncpy((char *)&ret[1], "COMPOUND_TEXT", compound_len); + return True; +} + +Private Bool +_XimSetEncodingByDetail( + Xim im, + char **buf, + int *len) +{ + *len = 0; + *buf = NULL; + return True; +} + +Private Bool +_XimGetEncoding( + Xim im, + CARD16 *buf, + char *name, + int name_len, + char *detail, + int detail_len) +{ + XLCd lcd = im->core.lcd; + CARD16 category = buf[0]; + CARD16 idx = buf[1]; + int len; + XlcConv ctom_conv = NULL; + XlcConv ctow_conv = NULL; + XlcConv ctoutf8_conv = NULL; + XlcConv conv; + XimProtoPrivateRec *private = &im->private.proto; + + if (idx == (CARD16)XIM_Default_Encoding_IDX) { /* XXX */ + if (!(ctom_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNMultiByte))) + return False; + if (!(ctow_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNWideChar))) + return False; + if (!(ctoutf8_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNUtf8String))) + return False; + } + + if (category == XIM_Encoding_NameCategory) { + while (name_len > 0) { + len = (int)name[0]; + if (!strncmp(&name[1], "COMPOUND_TEXT", len)) { + if (!(ctom_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNMultiByte))) + return False; + if (!(ctow_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNWideChar))) + return False; + if (!(ctoutf8_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNUtf8String))) + return False; + break; + } else { + /* + * Not yet + */ + } + len += sizeof(BYTE); + name_len -= len; + name += len; + } + } else if (category == XIM_Encoding_DetailCategory) { + /* + * Not yet + */ + } else { + return False; + } + + private->ctom_conv = ctom_conv; + private->ctow_conv = ctow_conv; + private->ctoutf8_conv = ctoutf8_conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte))) + return False; + private->cstomb_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNWideChar))) + return False; + private->cstowc_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String))) + return False; + private->cstoutf8_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNChar))) + return False; + private->ucstoc_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNUtf8String))) + return False; + private->ucstoutf8_conv = conv; + + return True; +} + +Private Bool +_XimEncodingNegoCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_ENCODING_NEGOTIATION_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +Private Bool +_XimEncodingNegotiation( + Xim im) +{ + char *name_ptr = 0; + int name_len = 0; + char *detail_ptr = 0; + int detail_len = 0; + CARD8 *buf; + CARD16 *buf_s; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + + if (!(_XimSetEncodingByName(im, &name_ptr, &name_len))) + return False; + + if (!(_XimSetEncodingByDetail(im, &detail_ptr, &detail_len))) { + if (name_ptr) + Xfree(name_ptr); + return False; + } + + len = sizeof(CARD16) + + sizeof(INT16) + + name_len + + XIM_PAD(name_len) + + sizeof(INT16) + + sizeof(CARD16) + + detail_len; + + if (!(buf = (CARD8 *)Xmalloc(XIM_HEADER_SIZE + len))) { + if (name_ptr) + Xfree(name_ptr); + if (detail_ptr) + Xfree(detail_ptr); + return False; + } + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + + buf_s[0] = im->private.proto.imid; + buf_s[1] = (INT16)name_len; + if (name_ptr) + (void)memcpy((char *)&buf_s[2], name_ptr, name_len); + XIM_SET_PAD(&buf_s[2], name_len); + buf_s = (CARD16 *)((char *)&buf_s[2] + name_len); + buf_s[0] = detail_len; + buf_s[1] = 0; + if (detail_ptr) + (void)memcpy((char *)&buf_s[2], detail_ptr, detail_len); + + _XimSetHeader((XPointer)buf, XIM_ENCODING_NEGOTIATION, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + Xfree(buf); + return False; + } + _XimFlush(im); + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimEncodingNegoCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimEncodingNegoCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + + if (!(_XimGetEncoding(im, &buf_s[1], name_ptr, name_len, + detail_ptr, detail_len))) { + if(reply != preply) + Xfree(preply); + return False; + } + if (name_ptr) + Xfree(name_ptr); + if (detail_ptr) + Xfree(detail_ptr); + + if(reply != preply) + Xfree(preply); + + return True; +} + +#ifdef XIM_CONNECTABLE +Private Bool +_XimSendSavedIMValues( + Xim im) +{ + XimDefIMValues im_values; + INT16 len; + CARD16 *buf_s; + char *tmp; + CARD32 tmp_buf32[BUFSIZE/4]; + char *tmp_buf = (char *)tmp_buf32; + char *buf; + int buf_size; + char *data; + int data_len; + int ret_len; + int total; + int idx; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int ret_code; + + _XimGetCurrentIMValues(im, &im_values); + buf = tmp_buf; + buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); + data_len = BUFSIZE - buf_size; + total = 0; + idx = 0; + for (;;) { + data = &buf[buf_size]; + if (!_XimEncodeSavedIMATTRIBUTE(im, im->core.im_resources, + im->core.im_num_resources, &idx, data, data_len, + &ret_len, (XPointer)&im_values, XIM_SETIMVALUES)) { + if (buf != tmp_buf) + Xfree(buf); + return False; + } + + total += ret_len; + if (idx == -1) { + break; + } + + buf_size += ret_len; + if (buf == tmp_buf) { + if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { + return False; + } + memcpy(tmp, buf, buf_size); + buf = tmp; + } else { + if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { + Xfree(buf); + return False; + } + buf = tmp; + } + } + + if (!total) + return True; + + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + buf_s[0] = im->private.proto.imid; + buf_s[1] = (INT16)total; + + len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); + _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + if (buf != tmp_buf) + Xfree(buf); + return False; + } + _XimFlush(im); + if (buf != tmp_buf) + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimSetIMValuesCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = (int)len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, reply, buf_size, + _XimSetIMValuesCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + + return True; +} + +Private void +_XimDelayModeIMFree( + Xim im) +{ + if (im->core.im_resources) { + Xfree(im->core.im_resources); + im->core.im_resources = NULL; + } + if (im->core.ic_resources) { + Xfree(im->core.ic_resources); + im->core.ic_resources = NULL; + } + if (im->core.im_values_list) { + Xfree(im->core.im_values_list); + im->core.im_values_list = NULL; + } + if (im->core.ic_values_list) { + Xfree(im->core.ic_values_list); + im->core.ic_values_list = NULL; + } + return; +} + +Public Bool +_XimConnectServer( + Xim im) +{ + Xim save_im; + + if (!(save_im = (Xim)Xmalloc(sizeof(XimRec)))) + return False; + memcpy((char *)save_im, (char *)im, sizeof(XimRec)); + + if (_XimPreConnect(im) && _XimConnection(im) + && _XimOpen(im) && _XimEncodingNegotiation(im)) { + if (_XimSendSavedIMValues(im)) { + _XimDelayModeIMFree(save_im); + _XimRegisterServerFilter(im); + Xfree(save_im); + return True; + } + } + memcpy((char *)im, (char *)save_im, sizeof(XimRec)); + Xfree(save_im); + return False; +} + +Public Bool +_XimDelayModeSetAttr( + Xim im) +{ + XimDefIMValues im_values; + + if(!_XimSetIMResourceList(&im->core.im_resources, + &im->core.im_num_resources)) { + return False; + } + if(!_XimSetICResourceList(&im->core.ic_resources, + &im->core.ic_num_resources)) { + return False; + } + + _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); + + _XimGetCurrentIMValues(im, &im_values); + if(!_XimSetLocalIMDefaults(im, (XPointer)&im_values, + im->core.im_resources, im->core.im_num_resources)) { + return False; + } + _XimSetCurrentIMValues(im, &im_values); + if (im->private.proto.default_styles) { + if (im->core.styles) + Xfree(im->core.styles); + im->core.styles = im->private.proto.default_styles; + } + + return True; +} + +Private Bool +_XimReconnectModeSetAttr( + Xim im) +{ + XimDefIMValues im_values; + + if(!_XimSetIMResourceList(&im->core.im_resources, + &im->core.im_num_resources)) { + return False; + } + if(!_XimSetICResourceList(&im->core.ic_resources, + &im->core.ic_num_resources)) { + return False; + } + + _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); + + if (im->private.proto.default_styles) { + if (im->core.styles) + Xfree(im->core.styles); + im->core.styles = im->private.proto.default_styles; + } + + return True; +} +#endif /* XIM_CONNECTABLE */ + +Public Bool +_XimProtoOpenIM( + Xim im) +{ + _XimInitialResourceInfo(); + + im->methods = &im_methods; + +#ifdef XIM_CONNECTABLE + _XimSetProtoResource(im); +#endif /* XIM_CONNECTABLE */ + + if (_XimPreConnect(im)) { + if (_XimConnection(im) && _XimOpen(im) && _XimEncodingNegotiation(im)) { + _XimRegisterServerFilter(im); + return True; + } + _XimShutdown(im); +#ifdef XIM_CONNECTABLE + } else if (IS_DELAYBINDABLE(im)) { + if (_XimDelayModeSetAttr(im)) + return True; +#endif /* XIM_CONNECTABLE */ + } + _XimProtoIMFree(im); + return False; +} |