xenocara/lib/libX11/modules/im/ximcp/imDefIm.c
2015-04-06 20:57:55 +00:00

2043 lines
48 KiB
C

/*
* Copyright 1990, 1991, 1992 Oracle and/or its affiliates. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/******************************************************************
Copyright 1992, 1993, 1994 by FUJITSU LIMITED
Copyright 1993, 1994 by Sony Corporation
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
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 names of Digital, FUJITSU
LIMITED and Sony Corporation not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
DIGITAL, 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 DIGITAL, 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
******************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/Xatom.h>
#include "Xlibint.h"
#include "Xlcint.h"
#include "XlcPublic.h"
#include "XlcPubI.h"
#include "XimTrInt.h"
#include "Ximint.h"
int
_XimCheckDataSize(
XPointer buf,
int len)
{
CARD16 *buf_s = (CARD16 *)buf;
if(len < XIM_HEADER_SIZE)
return -1;
return buf_s[1];
}
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;
}
char
_XimGetMyEndian(void)
{
CARD16 test_card = 1;
if(*((char *)&test_card))
return LITTLEENDIAN;
else
return BIGENDIAN;
}
static 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;
}
static 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;
}
static 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;
}
static 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;
}
static 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;
}
static 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;
}
static 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;
}
static 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;
}
static Bool
_XimSetAuthReplyData(
Xim im,
XPointer buf,
INT16 *len)
{
/*
* Not yet
*/
*len = 0;
return True;
}
static Bool
_XimSetAuthNextData(
Xim im,
XPointer buf,
INT16 *len)
{
/*
* Not yet
*/
*len = 0;
return True;
}
static Bool
_XimSetAuthRequiredData(
Xim im,
XPointer buf,
INT16 *len)
{
/*
* Not yet
*/
*len = 0;
return True;
}
static Bool
_XimCheckAuthSetupData(
Xim im,
XPointer buf)
{
/*
* Not yet
*/
return True;
}
static Bool
_XimCheckAuthNextData(
Xim im,
XPointer buf)
{
/*
* Not yet
*/
return True;
}
#define NO_MORE_AUTH 2
#define GOOD_AUTH 1
#define BAD_AUTH 0
static int
_XimClientAuthCheck(
Xim im,
XPointer buf)
{
/*
* Not yet
*/
return NO_MORE_AUTH;
}
static 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;
}
static Bool
_XimAllRecv(
Xim im,
INT16 len,
XPointer data,
XPointer arg)
{
return True;
}
#define CLIENT_WAIT1 1
#define CLIENT_WAIT2 2
static 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 = 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;
}
static 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;
}
static 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 = 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;
}
static 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;
}
static 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 = 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;
}
static 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;
}
static 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 = 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;
}
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;
}
static 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 (ic);
}
#else
Xfree (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
static 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;
}
static 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 = 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 = 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;
}
static 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 */
static 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;
}
static 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 = Xmalloc(buf_size + data_len))) {
return arg->name;
}
memcpy(tmp, buf, buf_size);
buf = tmp;
} else {
if (!(tmp = 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 = 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
static 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 */
static 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;
}
static 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 = 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 = 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;
}
static XIMMethodsRec im_methods = {
_XimProtoCloseIM, /* close */
_XimProtoSetIMValues, /* set_values */
_XimProtoGetIMValues, /* get_values */
_XimProtoCreateIC, /* create_ic */
_Ximctstombs, /* ctstombs */
_Ximctstowcs, /* ctstowcs */
_Ximctstoutf8 /* ctstoutf8 */
};
static 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 = 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;
}
static Bool
_XimSetEncodingByDetail(
Xim im,
char **buf,
int *len)
{
*len = 0;
*buf = NULL;
return True;
}
static 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;
}
static 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;
}
static 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)))
goto free_name_ptr;
len = sizeof(CARD16)
+ sizeof(INT16)
+ name_len
+ XIM_PAD(name_len)
+ sizeof(INT16)
+ sizeof(CARD16)
+ detail_len;
if (!(buf = Xmalloc(XIM_HEADER_SIZE + len)))
goto free_detail_ptr;
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);
goto free_detail_ptr;
}
_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 = Xmalloc(buf_size);
ret_code = _XimRead(im, &len, preply, buf_size,
_XimEncodingNegoCheck, 0);
if(ret_code != XIM_TRUE)
goto free_preply;
}
} else
goto free_detail_ptr;
buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
if (*((CARD8 *)preply) == XIM_ERROR) {
_XimProcError(im, 0, (XPointer)&buf_s[3]);
goto free_preply;
}
if (!(_XimGetEncoding(im, &buf_s[1], name_ptr, name_len,
detail_ptr, detail_len)))
goto free_preply;
Xfree(name_ptr);
Xfree(detail_ptr);
if(reply != preply)
Xfree(preply);
return True;
free_preply:
if (reply != preply)
Xfree(preply);
free_detail_ptr:
Xfree(detail_ptr);
free_name_ptr:
Xfree(name_ptr);
return False;
}
#ifdef XIM_CONNECTABLE
static 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 = Xmalloc(buf_size + data_len))) {
return False;
}
memcpy(tmp, buf, buf_size);
buf = tmp;
} else {
if (!(tmp = 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 = 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;
}
static 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;
}
Bool
_XimConnectServer(
Xim im)
{
Xim save_im;
if (!(save_im = 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;
}
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;
}
static 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 */
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;
}