xenocara/lib/libX11/modules/im/ximcp/imDefIm.c
2007-09-30 10:11:57 +00:00

2029 lines
47 KiB
C

/* $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,
const 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;
}