imDefIm.c revision b4ee4795
1/*
2 * Copyright 1990, 1991, 1992 Sun Microsystems, Inc.  All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24/******************************************************************
25         Copyright 1992, 1993, 1994 by FUJITSU LIMITED
26         Copyright 1993, 1994 by Sony Corporation
27
28Permission to use, copy, modify, and distribute this software and its
29documentation for any purpose and without fee is hereby granted,
30provided that the above copyright notice appear in all copies and that
31both that copyright notice and this permission notice appear in
32supporting documentation, and that the names of Digital, FUJITSU
33LIMITED and Sony Corporation not be used in advertising or publicity
34pertaining to distribution of the software without specific, written
35prior permission.
36
37DIGITAL, FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES
38WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
39MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL, FUJITSU LIMITED
40AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
41CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
42USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
43OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
44PERFORMANCE OF THIS SOFTWARE.
45
46  Author: Hideki Hiura (hhiura@Sun.COM) Sun Microsystems, Inc.
47          Takashi Fujiwara     FUJITSU LIMITED
48                               fujiwara@a80.tech.yk.fujitsu.co.jp
49          Makoto Wakamatsu     Sony Corporation
50                               makoto@sm.sony.co.jp
51
52******************************************************************/
53
54#ifdef HAVE_CONFIG_H
55#include <config.h>
56#endif
57#include <X11/Xatom.h>
58#define NEED_EVENTS
59#include "Xlibint.h"
60#include "Xlcint.h"
61#include "XlcPublic.h"
62#include "XlcPubI.h"
63#include "XimTrInt.h"
64#include "Ximint.h"
65
66
67Public int
68_XimCheckDataSize(
69    XPointer	 buf,
70    int		 len)
71{
72    CARD16	*buf_s = (CARD16 *)buf;
73
74    if(len < XIM_HEADER_SIZE)
75	return -1;
76    return  buf_s[1];
77}
78
79Public void
80_XimSetHeader(
81    XPointer	 buf,
82    CARD8	 major_opcode,
83    CARD8	 minor_opcode,
84    INT16	*len
85)
86{
87    CARD8	*buf_b = (CARD8 *)buf;
88    CARD16	*buf_s = (CARD16 *)buf;
89
90    buf_b[0] = major_opcode;
91    buf_b[1] = minor_opcode;
92    buf_s[1] = ((*len) / 4);
93    *len += XIM_HEADER_SIZE;
94    return;
95}
96
97Public char
98_XimGetMyEndian(void)
99{
100    CARD16	 test_card = 1;
101
102    if(*((char *)&test_card))
103	return LITTLEENDIAN;
104    else
105	return BIGENDIAN;
106}
107
108Private Bool
109_XimCheckServerName(
110    Xim		   im,
111    char	  *str)
112{
113    char	  *server_name = im->core.im_name;
114    int		   len;
115    int		   str_len;
116    int		   category_len = strlen(XIM_SERVER_CATEGORY);
117    char	  *pp;
118    register char *p;
119
120    if(server_name && *server_name)
121	len = strlen(server_name);
122    else
123	return True;
124
125    if((int)strlen(str) < category_len)
126	return False;
127
128    if(strncmp(str, XIM_SERVER_CATEGORY, category_len))
129	return False;
130
131    pp = &str[category_len];
132
133    for(;;) {
134	for(p = pp; (*p != ',') && (*p); p++);
135	str_len = (int)(p - pp);
136
137	if((len == str_len) && (!strncmp(pp, server_name, len)))
138	    break;
139	if(!(*p))
140	    return False;
141	pp = p + 1;
142    }
143    return True;
144}
145
146Private char *
147_XimCheckLocaleName(
148    Xim		   im,
149    char	  *address,
150    int		   address_len,
151    char	  *locale_name[],
152    int		   len)
153{
154    int		   category_len;
155    char	  *pp;
156    register char *p;
157    register int   n;
158    Bool           finish = False;
159
160    category_len = strlen(XIM_LOCAL_CATEGORY);
161    if(address_len < category_len)
162	return (char*)NULL;
163
164    if(strncmp(address, XIM_LOCAL_CATEGORY, category_len))
165	return (char*)NULL;
166
167    pp = &address[category_len];
168
169    for(;;) {
170	for( p = pp; *p && *p != ','; p++);
171	if (!*p)
172	    finish = True;
173	address_len = (int)(p - pp);
174	*p = '\0';
175
176	for( n = 0; n < len; n++ )
177	    if( locale_name[n] && !_XlcCompareISOLatin1( pp, locale_name[n] ) )
178		return locale_name[n];
179	if (finish)
180	    break;
181	pp = p + 1;
182    }
183    return (char *)NULL;
184}
185
186Private Bool
187_XimCheckTransport(
188    char	  *address,
189    int		   address_len,
190    const char	  *transport,
191    int		   len,
192    char	 **trans_addr)
193{
194    int		   category_len = strlen(XIM_TRANSPORT_CATEGORY);
195    char	  *pp;
196    register char *p;
197
198    if(address_len < category_len)
199	return False;
200
201    if(strncmp(address, XIM_TRANSPORT_CATEGORY, category_len))
202	return False;
203
204    pp = &address[category_len];
205
206    for(;;) {
207	*trans_addr = pp;
208
209	for(p = pp; (*p != '/') && (*p != ',') && (*p); p++);
210	if(*p == ',') {
211	    pp = p + 1;
212	    continue;
213	}
214	if(!(*p))
215	    return False;
216
217	address_len = (int)(p - pp);
218
219	if((len == address_len) && (!strncmp(pp, transport, len)))
220	    break;
221	pp = p + 1;
222    }
223    pp = p + 1;
224    for(p = pp; (*p != ',') && (*p); p++);
225    if (*p)
226	*p = '\0';
227    return True;
228}
229
230Private Bool
231_CheckSNEvent(
232    Display		*display,
233    XEvent		*xevent,
234    XPointer		 arg)
235{
236    XSelectionEvent	*event = (XSelectionEvent *)xevent;
237    Window		 window = *(Window*)arg;
238
239    if((event->type == SelectionNotify) && (window == event->requestor))
240	return True;
241    return False;
242}
243
244Private Bool
245_XimGetSelectionNotify(
246    Display		 *display,
247    Window		  window,
248    Atom		  target,
249    char		**ret_address)
250{
251    XEvent		  event;
252    XSelectionEvent	 *ev = (XSelectionEvent *)&event;
253    Atom		  actual_type;
254    int			  actual_format;
255    unsigned long	  nitems, bytes_after;
256
257    for(;;) {
258	XIfEvent(display, &event, _CheckSNEvent, (XPointer)&window);
259	if((ev->type == SelectionNotify) && (window == ev->requestor))
260	    break;
261    }
262
263    if(ev->property == (Atom)None)
264	return False;
265    if( XGetWindowProperty( display, window, target, 0L, 1000000L,
266			    True, target, &actual_type, &actual_format,
267			    &nitems, &bytes_after,
268			    (unsigned char **)&*ret_address ) != Success )
269	return False;
270    return True;
271}
272
273Private Bool
274_XimPreConnectionIM(
275    Xim			 im,
276    Atom		 selection)
277{
278    Display		*display = im->core.display;
279    Atom		 locales, transport;
280    char		*address;
281    XLCd		 lcd;
282    char		*language;
283    char		*territory;
284    char		*codeset;
285    char		*trans_addr;
286    char		*locale_name[4], *locale;
287    int			 llen, tlen, clen;
288    register int	 i;
289    Window		 window;
290    char		*str;
291
292    if(!(lcd = im->core.lcd))
293	return False;
294
295    for( i = 0; i < 4; i++ )
296	locale_name[i] = NULL;
297    /* requestor window */
298    if(!(window = XCreateSimpleWindow(display, DefaultRootWindow(display),
299			 				0, 0, 1, 1, 1, 0, 0)))
300	return False;
301
302    /* server name check */
303    if( !(str = XGetAtomName( display, selection )) )
304	return False;
305    if(!_XimCheckServerName(im, str)) {
306	XFree( (XPointer)str );
307	goto Error;
308    }
309    XFree( (XPointer)str );
310
311    /* locale name check */
312    _XGetLCValues(lcd, XlcNLanguage, &language, XlcNTerritory, &territory,
313                    XlcNCodeset, &codeset, NULL);
314    llen = strlen( language );
315    tlen = territory ? strlen( territory ): 0;
316    clen = codeset ? strlen( codeset ): 0;
317
318    if( tlen != 0  &&  clen != 0 ) {
319	if( (locale_name[0] = Xmalloc(llen+tlen+clen+3)) != NULL )
320	    sprintf( locale_name[0], "%s_%s.%s", language, territory, codeset );
321    }
322    if( clen != 0 ) {
323	if( (locale_name[1] = Xmalloc(llen+clen+2)) != NULL )
324	    sprintf( locale_name[1], "%s.%s", language, codeset );
325	else
326	    goto Error;
327    }
328    if( tlen != 0 ) {
329	if( (locale_name[2] = Xmalloc(llen+tlen+2)) != NULL )
330	    sprintf( locale_name[2], "%s_%s", language, territory );
331	else
332	    goto Error;
333    }
334    if( (locale_name[3] = Xmalloc(llen+1)) != NULL )
335	strcpy( locale_name[3], language );
336    else
337	goto Error;
338    if((locales = XInternAtom(display, XIM_LOCALES, True)) == (Atom)None)
339	goto Error;
340
341    XConvertSelection(display, selection, locales, locales, window,
342		      CurrentTime);
343    if(!(_XimGetSelectionNotify(display, window, locales, &address)))
344	goto Error;
345
346    if((locale = _XimCheckLocaleName(im, address, strlen(address), locale_name,
347				     4)) == NULL) {
348	XFree((XPointer)address);
349	goto Error;
350    }
351    im->private.proto.locale_name = locale;
352    for( i = 0; i < 4; i++ ) {
353	if( locale_name[i] != NULL  &&  locale_name[i] != locale ) {
354	    XFree( locale_name[i] );
355	    locale_name[i] = NULL;
356	}
357    }
358    XFree((XPointer)address);
359
360    /* transport check */
361    if((transport = XInternAtom(display, XIM_TRANSPORT, True)) == (Atom)None)
362	goto Error;
363
364    XConvertSelection(display, selection, transport, transport, window,
365		      CurrentTime);
366    if(!_XimGetSelectionNotify(display, window, transport, &address))
367	goto Error;
368
369    for(i = 0; _XimTransportRec[i].transportname ; i++) {
370	if( _XimCheckTransport(address, strlen(address),
371				_XimTransportRec[i].transportname,
372				strlen(_XimTransportRec[i].transportname),
373				 &trans_addr)) {
374	    if( _XimTransportRec[i].config(im, trans_addr) ) {
375		XFree((XPointer)address);
376		XDestroyWindow(display, window);
377		return True;
378	    }
379	}
380    }
381
382    XFree((XPointer)address);
383Error:
384    for( i = 0; i < 4; i++ )
385	if( locale_name[i] != NULL )
386	    XFree( locale_name[i] );
387    XDestroyWindow(display, window);
388    return False;
389}
390
391Private Bool
392_XimPreConnect(
393    Xim		    im)
394{
395    Display	   *display = im->core.display;
396    Atom	    imserver;
397    Atom	    actual_type;
398    int		    actual_format;
399    unsigned long   nitems;
400    unsigned long   bytes_after;
401    unsigned char  *prop_return;
402    Atom	   *atoms;
403    Window	    im_window = 0;
404    register int    i;
405
406    if((imserver = XInternAtom(display, XIM_SERVERS, True)) == (Atom)None)
407	return False;
408
409    if(XGetWindowProperty(display, RootWindow(display, 0),
410			imserver, 0L, 1000000L, False, XA_ATOM, &actual_type,
411			&actual_format, &nitems, &bytes_after,
412			&prop_return) != Success)
413	return False;
414
415    if( (actual_type != XA_ATOM) || (actual_format != 32) ) {
416	if( nitems )
417	    XFree((XPointer)prop_return);
418	return False;
419    }
420
421    atoms = (Atom *)prop_return;
422    for(i = 0; i < nitems; i++) {
423	if((im_window = XGetSelectionOwner(display, atoms[i])) == (Window)None)
424	    continue;
425
426	if(_XimPreConnectionIM(im, atoms[i]))
427	    break;
428    }
429
430    XFree((XPointer)prop_return);
431    if(i >= nitems)
432	return False;
433
434    im->private.proto.im_window = im_window;
435    return True;
436}
437
438Private Bool
439_XimGetAuthProtocolNames(
440    Xim		 im,
441    CARD16	*buf,
442    CARD8	*num,
443    INT16	*len)
444{
445    if (!IS_USE_AUTHORIZATION_FUNC(im)) {
446	*num = 0;
447	*len = 0;
448	return True;
449    }
450    /*
451     * Not yet
452     */
453    return True;
454}
455
456Private Bool
457_XimSetAuthReplyData(
458    Xim		 im,
459    XPointer	 buf,
460    INT16	*len)
461{
462    /*
463     * Not yet
464     */
465    *len = 0;
466    return True;
467}
468
469Private Bool
470_XimSetAuthNextData(
471    Xim		 im,
472    XPointer	 buf,
473    INT16	*len)
474{
475    /*
476     * Not yet
477     */
478    *len = 0;
479    return True;
480}
481
482Private Bool
483_XimSetAuthRequiredData(
484    Xim		 im,
485    XPointer	 buf,
486    INT16	*len)
487{
488    /*
489     * Not yet
490     */
491    *len = 0;
492    return True;
493}
494
495Private Bool
496_XimCheckAuthSetupData(
497    Xim		 im,
498    XPointer	 buf)
499{
500    /*
501     * Not yet
502     */
503    return True;
504}
505
506Private Bool
507_XimCheckAuthNextData(
508    Xim		 im,
509    XPointer	 buf)
510{
511    /*
512     * Not yet
513     */
514    return True;
515}
516
517#define	NO_MORE_AUTH	2
518#define	GOOD_AUTH	1
519#define	BAD_AUTH	0
520
521Private int
522_XimClientAuthCheck(
523    Xim		 im,
524    XPointer	 buf)
525{
526    /*
527     * Not yet
528     */
529    return NO_MORE_AUTH;
530}
531
532Private void
533_XimAuthNG(
534    Xim		 im)
535{
536    CARD32	 buf32[BUFSIZE/4];
537    CARD8	*buf = (CARD8 *)buf32;
538    INT16	 len = 0;
539
540    _XimSetHeader((XPointer)buf, XIM_AUTH_NG, 0, &len);
541    (void)_XimWrite(im, len, (XPointer)buf);
542    _XimFlush(im);
543    return;
544}
545
546Private	Bool
547_XimAllRecv(
548    Xim		 im,
549    INT16	 len,
550    XPointer	 data,
551    XPointer	 arg)
552{
553    return True;
554}
555
556#define	CLIENT_WAIT1		1
557#define	CLIENT_WAIT2		2
558
559Private Bool
560_XimConnection(
561    Xim		 im)
562{
563    CARD32	 buf32[BUFSIZE/4];
564    CARD8	*buf = (CARD8 *)buf32;
565    CARD8	*buf_b = &buf[XIM_HEADER_SIZE];
566    CARD16	*buf_s = (CARD16 *)((XPointer)buf_b);
567    INT16	 len;
568    CARD8	 num;
569    CARD32	 reply32[BUFSIZE/4];
570    char	*reply = (char *)reply32;
571    XPointer	 preply;
572    int		 buf_size;
573    int		 ret_code;
574    CARD8	 major_opcode;
575    int		 wait_mode;
576    int		 ret;
577
578    if(!(_XimConnect(im)))	/* Transport Connect */
579	return False;
580
581    if(!_XimDispatchInit(im))
582	return False;
583
584    _XimRegProtoIntrCallback(im, XIM_ERROR, 0, _XimErrorCallback, (XPointer)im);
585
586    if(!_XimGetAuthProtocolNames(im, &buf_s[4], &num, &len))
587	return False;
588
589    im->private.proto.protocol_major_version = PROTOCOLMAJORVERSION;
590    im->private.proto.protocol_minor_version = PROTOCOLMINORVERSION;
591
592    buf_b[0] = _XimGetMyEndian();
593    buf_b[1] = 0;
594    buf_s[1] = PROTOCOLMAJORVERSION;
595    buf_s[2] = PROTOCOLMINORVERSION;
596    buf_s[3] = num;
597    len  += sizeof(CARD8)
598          + sizeof(CARD8)
599          + sizeof(CARD16)
600          + sizeof(CARD16)
601          + sizeof(CARD16);
602
603    major_opcode = XIM_CONNECT;
604    wait_mode = (IS_USE_AUTHORIZATION_FUNC(im)) ? CLIENT_WAIT1 : CLIENT_WAIT2;
605
606    for(;;) {
607	_XimSetHeader((XPointer)buf, major_opcode, 0, &len);
608	if (!(_XimWrite(im, len, (XPointer)buf)))
609	    return False;
610	_XimFlush(im);
611	buf_size = BUFSIZE;
612	ret_code = _XimRead(im, &len, reply, buf_size, _XimAllRecv, 0);
613	if(ret_code == XIM_TRUE) {
614	    preply = reply;
615	} else if(ret_code == XIM_OVERFLOW) {
616	    if(len <= 0) {
617		preply = reply;
618	    } else {
619		buf_size = len;
620		preply = (XPointer)Xmalloc(buf_size);
621		ret_code = _XimRead(im, &len, preply, buf_size, _XimAllRecv, 0);
622		if(ret_code != XIM_TRUE) {
623		    Xfree(preply);
624		    return False;
625		}
626	    }
627	} else
628	    return False;
629
630	major_opcode = *((CARD8 *)preply);
631	buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
632
633	if (wait_mode == CLIENT_WAIT1) {
634	    if (major_opcode == XIM_AUTH_REQUIRED) {
635		ret = _XimClientAuthCheck(im, (XPointer)buf_s);
636		if(reply != preply)
637		    Xfree(preply);
638		if (ret == NO_MORE_AUTH) {
639		    if (!(_XimSetAuthReplyData(im,
640				(XPointer)&buf[XIM_HEADER_SIZE], &len))) {
641			_XimAuthNG(im);
642			return False;
643		    }
644		    major_opcode = XIM_AUTH_REPLY;
645		    wait_mode = CLIENT_WAIT2;
646		} else if (ret == GOOD_AUTH) {
647		    if (!(_XimSetAuthNextData(im,
648				(XPointer)&buf[XIM_HEADER_SIZE], &len))) {
649			_XimAuthNG(im);
650			return False;
651		    }
652		    major_opcode = XIM_AUTH_NEXT;
653		} else {	/* BAD_AUTH */
654		    _XimAuthNG(im);
655		    return False;
656		}
657	    } else {
658		if(reply != preply)
659		    Xfree(preply);
660		_XimAuthNG(im);
661		return False;
662	    }
663	} else {	/* CLIENT_WAIT2 */
664	    if (major_opcode == XIM_CONNECT_REPLY) {
665		break;
666	    } else if (major_opcode == XIM_AUTH_SETUP) {
667		if (!(_XimCheckAuthSetupData(im, (XPointer)buf_s))) {
668		    _XimAuthNG(im);
669		    return False;
670		}
671		if(reply != preply)
672		    Xfree(preply);
673		if (!(_XimSetAuthRequiredData(im,
674				(XPointer)&buf[XIM_HEADER_SIZE], &len))) {
675		    _XimAuthNG(im);
676		    return False;
677		}
678		major_opcode = XIM_AUTH_REQUIRED;
679	    } else if (major_opcode == XIM_AUTH_NEXT) {
680		if (!(_XimCheckAuthNextData(im, (XPointer)buf_s))) {
681		    _XimAuthNG(im);
682		    return False;
683		}
684		if(reply != preply)
685		    Xfree(preply);
686		if (!(_XimSetAuthRequiredData(im,
687				(XPointer)&buf[XIM_HEADER_SIZE], &len))) {
688		    _XimAuthNG(im);
689		    return False;
690		}
691		major_opcode = XIM_AUTH_REQUIRED;
692	    } else if (major_opcode == XIM_AUTH_NG) {
693		if(reply != preply)
694		    Xfree(preply);
695		return False;
696	    } else {
697		_XimAuthNG(im);
698		if(reply != preply)
699		    Xfree(preply);
700		return False;
701	    }
702	}
703    }
704
705    if (!( buf_s[0] == im->private.proto.protocol_major_version
706        && buf_s[1] == im->private.proto.protocol_minor_version)) {
707	if(reply != preply)
708	    Xfree(preply);
709	return False;
710    }
711    if(reply != preply)
712	Xfree(preply);
713    MARK_SERVER_CONNECTED(im);
714
715    _XimRegProtoIntrCallback(im, XIM_REGISTER_TRIGGERKEYS, 0,
716				 _XimRegisterTriggerKeysCallback, (XPointer)im);
717    return True;
718}
719
720Private	Bool
721_XimDisconnectCheck(
722    Xim		 im,
723    INT16	 len,
724    XPointer	 data,
725    XPointer	 arg)
726{
727    CARD8	 major_opcode = *((CARD8 *)data);
728    CARD8	 minor_opcode = *((CARD8 *)data + 1);
729
730    if ((major_opcode == XIM_DISCONNECT_REPLY)
731     && (minor_opcode == 0))
732	return True;
733    if ((major_opcode == XIM_ERROR)
734     && (minor_opcode == 0))
735	return True;
736    return False;
737}
738
739Private Bool
740_XimDisconnect(
741    Xim		 im)
742{
743    CARD32	 buf32[BUFSIZE/4];
744    CARD8	*buf = (CARD8 *)buf32;
745    INT16	 len = 0;
746    CARD32	 reply32[BUFSIZE/4];
747    char	*reply = (char *)reply32;
748    XPointer	 preply;
749    int		 buf_size;
750    int		 ret_code;
751
752    if (IS_SERVER_CONNECTED(im)) {
753	_XimSetHeader((XPointer)buf, XIM_DISCONNECT, 0, &len);
754	if (!(_XimWrite(im, len, (XPointer)buf)))
755	    return False;
756	_XimFlush(im);
757	buf_size = BUFSIZE;
758	ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
759						_XimDisconnectCheck, 0);
760	if(ret_code == XIM_OVERFLOW) {
761	    if(len > 0) {
762		buf_size = len;
763		preply = (XPointer)Xmalloc(buf_size);
764		ret_code = _XimRead(im, &len, preply, buf_size,
765						 _XimDisconnectCheck, 0);
766		Xfree(preply);
767		if(ret_code != XIM_TRUE)
768		    return False;
769	    }
770	} else if(ret_code == XIM_FALSE)
771	    return False;
772
773    }
774    if (!(_XimShutdown(im)))	/* Transport shutdown */
775	return False;
776    return True;
777}
778
779Private	Bool
780_XimOpenCheck(
781    Xim		 im,
782    INT16	 len,
783    XPointer	 data,
784    XPointer	 arg)
785{
786    CARD8	 major_opcode = *((CARD8 *)data);
787    CARD8	 minor_opcode = *((CARD8 *)data + 1);
788
789    if ((major_opcode == XIM_OPEN_REPLY)
790     && (minor_opcode == 0))
791	return True;
792    if ((major_opcode == XIM_ERROR)
793     && (minor_opcode == 0))
794	return True;
795    return False;
796}
797
798Private Bool
799_XimOpen(
800    Xim			 im)
801{
802    CARD32		 buf32[BUFSIZE/4];
803    CARD8		*buf = (CARD8 *)buf32;
804    CARD8		*buf_b = &buf[XIM_HEADER_SIZE];
805    CARD16		*buf_s;
806    INT16		 len;
807    CARD32		 reply32[BUFSIZE/4];
808    char		*reply = (char *)reply32;
809    XPointer		 preply;
810    int			 buf_size;
811    int			 ret_code;
812    char		*locale_name;
813
814    locale_name = im->private.proto.locale_name;
815    len = strlen(locale_name);
816    buf_b[0] = (BYTE)len;			   /* length of locale name */
817    (void)strcpy((char *)&buf_b[1], locale_name);  /* locale name */
818    len += sizeof(BYTE);			   /* sizeof length */
819    XIM_SET_PAD(buf_b, len);			   /* pad */
820
821    _XimSetHeader((XPointer)buf, XIM_OPEN, 0, &len);
822    if (!(_XimWrite(im, len, (XPointer)buf)))
823	return False;
824    _XimFlush(im);
825    buf_size = BUFSIZE;
826    ret_code = _XimRead(im, &len, reply, buf_size,
827					_XimOpenCheck, 0);
828    if(ret_code == XIM_TRUE) {
829	preply = reply;
830    } else if(ret_code == XIM_OVERFLOW) {
831	if(len <= 0) {
832	    preply = reply;
833	} else {
834	    buf_size = len;
835	    preply = (XPointer)Xmalloc(buf_size);
836	    ret_code = _XimRead(im, &len, preply, buf_size,
837					_XimOpenCheck, 0);
838	    if(ret_code != XIM_TRUE) {
839		Xfree(preply);
840		return False;
841	    }
842	}
843    } else
844	return False;
845    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
846    if (*((CARD8 *)preply) == XIM_ERROR) {
847	_XimProcError(im, 0, (XPointer)&buf_s[3]);
848	if(reply != preply)
849	    Xfree(preply);
850	return False;
851    }
852
853    im->private.proto.imid = buf_s[0];		/* imid */
854
855    if (!(_XimGetAttributeID(im, &buf_s[1]))) {
856	if(reply != preply)
857	    Xfree(preply);
858	return False;
859    }
860    if(reply != preply)
861	Xfree(preply);
862
863    if (!(_XimSetInnerIMResourceList(&(im->private.proto.im_inner_resources),
864				&(im->private.proto.im_num_inner_resources))))
865	return False;
866
867    if (!(_XimSetInnerICResourceList(&(im->private.proto.ic_inner_resources),
868				&(im->private.proto.ic_num_inner_resources))))
869	return False;
870
871    _XimSetIMMode(im->core.im_resources, im->core.im_num_resources);
872    _XimSetIMMode(im->private.proto.im_inner_resources,
873				im->private.proto.im_num_inner_resources);
874
875    /* Transport Callbak */
876    _XimRegProtoIntrCallback(im, XIM_SET_EVENT_MASK, 0,
877				 _XimSetEventMaskCallback, (XPointer)im);
878    _XimRegProtoIntrCallback(im, XIM_FORWARD_EVENT, 0,
879				 _XimForwardEventCallback, (XPointer)im);
880    _XimRegProtoIntrCallback(im, XIM_COMMIT, 0,
881				 _XimCommitCallback, (XPointer)im);
882    _XimRegProtoIntrCallback(im, XIM_SYNC, 0,
883				 _XimSyncCallback, (XPointer)im);
884
885    if(!_XimExtension(im))
886	return False;
887
888    /* register a hook for callback protocols */
889    _XimRegisterDispatcher(im, _XimCbDispatch, (XPointer)im);
890
891    return True;
892}
893
894Private	Bool
895_XimCloseCheck(
896    Xim		 im,
897    INT16	 len,
898    XPointer	 data,
899    XPointer	 arg)
900{
901    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
902    CARD8	 major_opcode = *((CARD8 *)data);
903    CARD8	 minor_opcode = *((CARD8 *)data + 1);
904    XIMID	 imid = buf_s[0];
905
906    if ((major_opcode == XIM_CLOSE_REPLY)
907     && (minor_opcode == 0)
908     && (imid == im->private.proto.imid))
909	return True;
910    if ((major_opcode == XIM_ERROR)
911     && (minor_opcode == 0)
912     && (buf_s[2] & XIM_IMID_VALID)
913     && (imid == im->private.proto.imid))
914	return True;
915    return False;
916}
917
918Private Bool
919_XimClose(
920    Xim		 im)
921{
922    CARD32	 buf32[BUFSIZE/4];
923    CARD8	*buf = (CARD8 *)buf32;
924    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
925    INT16	 len;
926    CARD32	 reply32[BUFSIZE/4];
927    char	*reply = (char *)reply32;
928    XPointer	 preply;
929    int		 buf_size;
930    int		 ret_code;
931
932    if (!IS_SERVER_CONNECTED(im))
933	return True;
934
935    buf_s[0] = im->private.proto.imid;		/* imid */
936    buf_s[1] = 0;				/* unused */
937    len = sizeof(CARD16)			/* sizeof imid */
938        + sizeof(CARD16);			/* sizeof unused */
939
940    _XimSetHeader((XPointer)buf, XIM_CLOSE, 0, &len);
941    if (!(_XimWrite(im, len, (XPointer)buf)))
942	return False;
943    _XimFlush(im);
944    buf_size = BUFSIZE;
945    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
946						_XimCloseCheck, 0);
947    if(ret_code == XIM_TRUE) {
948	preply = reply;
949    } else if(ret_code == XIM_OVERFLOW) {
950	if(len <= 0) {
951	    preply = reply;
952	} else {
953	    buf_size = len;
954	    preply = (XPointer)Xmalloc(buf_size);
955	    ret_code = _XimRead(im, &len, preply, buf_size, _XimCloseCheck, 0);
956	    if(ret_code != XIM_TRUE) {
957		Xfree(preply);
958		return False;
959	    }
960	}
961    } else
962	return False;
963    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
964    if (*((CARD8 *)preply) == XIM_ERROR) {
965	_XimProcError(im, 0, (XPointer)&buf_s[3]);
966	if(reply != preply)
967	    Xfree(preply);
968	return False;
969    }
970
971    if(reply != preply)
972	Xfree(preply);
973    return True;
974}
975
976Public void
977_XimProtoIMFree(
978    Xim		  im)
979{
980    /* XIMPrivateRec */
981    if (im->private.proto.im_onkeylist) {
982	Xfree(im->private.proto.im_onkeylist);
983	im->private.proto.im_onkeylist = NULL;
984    }
985    if (im->private.proto.im_offkeylist) {
986	Xfree(im->private.proto.im_offkeylist);
987	im->private.proto.im_offkeylist = NULL;
988    }
989    if (im->private.proto.intrproto) {
990	_XimFreeProtoIntrCallback(im);
991	im->private.proto.intrproto = NULL;
992    }
993    if (im->private.proto.im_inner_resources) {
994	Xfree(im->private.proto.im_inner_resources);
995	im->private.proto.im_inner_resources = NULL;
996    }
997    if (im->private.proto.ic_inner_resources) {
998	Xfree(im->private.proto.ic_inner_resources);
999	im->private.proto.ic_inner_resources = NULL;
1000    }
1001    if (im->private.proto.hold_data) {
1002	Xfree(im->private.proto.hold_data);
1003	im->private.proto.hold_data = NULL;
1004    }
1005    if (im->private.proto.locale_name) {
1006	Xfree(im->private.proto.locale_name);
1007	im->private.proto.locale_name = NULL;
1008    }
1009    if (im->private.proto.ctom_conv) {
1010	_XlcCloseConverter(im->private.proto.ctom_conv);
1011	im->private.proto.ctom_conv = NULL;
1012    }
1013    if (im->private.proto.ctow_conv) {
1014	_XlcCloseConverter(im->private.proto.ctow_conv);
1015	im->private.proto.ctow_conv = NULL;
1016    }
1017    if (im->private.proto.ctoutf8_conv) {
1018	_XlcCloseConverter(im->private.proto.ctoutf8_conv);
1019	im->private.proto.ctoutf8_conv = NULL;
1020    }
1021    if (im->private.proto.cstomb_conv) {
1022	_XlcCloseConverter(im->private.proto.cstomb_conv);
1023	im->private.proto.cstomb_conv = NULL;
1024    }
1025    if (im->private.proto.cstowc_conv) {
1026	_XlcCloseConverter(im->private.proto.cstowc_conv);
1027	im->private.proto.cstowc_conv = NULL;
1028    }
1029    if (im->private.proto.cstoutf8_conv) {
1030	_XlcCloseConverter(im->private.proto.cstoutf8_conv);
1031	im->private.proto.cstoutf8_conv = NULL;
1032    }
1033    if (im->private.proto.ucstoc_conv) {
1034	_XlcCloseConverter(im->private.proto.ucstoc_conv);
1035	im->private.proto.ucstoc_conv = NULL;
1036    }
1037    if (im->private.proto.ucstoutf8_conv) {
1038	_XlcCloseConverter(im->private.proto.ucstoutf8_conv);
1039	im->private.proto.ucstoutf8_conv = NULL;
1040    }
1041
1042#ifdef XIM_CONNECTABLE
1043    if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) {
1044	return;
1045    }
1046#endif /* XIM_CONNECTABLE */
1047
1048    if (im->private.proto.saved_imvalues) {
1049        Xfree(im->private.proto.saved_imvalues);
1050        im->private.proto.saved_imvalues = NULL;
1051    }
1052    if (im->private.proto.default_styles) {
1053	Xfree(im->private.proto.default_styles);
1054	im->private.proto.default_styles = NULL;
1055    }
1056
1057    /* core */
1058    if (im->core.res_name) {
1059        Xfree(im->core.res_name);
1060	im->core.res_name = NULL;
1061    }
1062    if (im->core.res_class) {
1063        Xfree(im->core.res_class);
1064	im->core.res_class = NULL;
1065    }
1066    if (im->core.im_values_list) {
1067	Xfree(im->core.im_values_list);
1068	im->core.im_values_list = NULL;
1069    }
1070    if (im->core.ic_values_list) {
1071	Xfree(im->core.ic_values_list);
1072	im->core.ic_values_list = NULL;
1073    }
1074    if (im->core.im_name) {
1075	Xfree(im->core.im_name);
1076	im->core.im_name = NULL;
1077    }
1078    if (im->core.styles) {
1079	Xfree(im->core.styles);
1080	im->core.styles = NULL;
1081    }
1082    if (im->core.im_resources) {
1083        Xfree(im->core.im_resources);
1084	im->core.im_resources = NULL;
1085    }
1086    if (im->core.ic_resources) {
1087        Xfree(im->core.ic_resources);
1088	im->core.ic_resources = NULL;
1089    }
1090
1091    return;
1092}
1093
1094Private Status
1095_XimProtoCloseIM(
1096    XIM		 xim)
1097{
1098    Xim		 im = (Xim)xim;
1099    XIC		 ic;
1100    XIC		 next;
1101    Status	 status;
1102
1103    ic = im->core.ic_chain;
1104    while (ic) {
1105	(*ic->methods->destroy) (ic);
1106	next = ic->core.next;
1107#ifdef XIM_CONNECTABLE
1108	if (!(!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im))) {
1109	    Xfree ((char *) ic);
1110	}
1111#else
1112	Xfree ((char *) ic);
1113#endif /* XIM_CONNECTABLE */
1114	ic = next;
1115    }
1116#ifdef XIM_CONNECTABLE
1117    if (!(!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)))
1118	im->core.ic_chain = NULL;
1119#else
1120    im->core.ic_chain = NULL;
1121#endif
1122
1123    _XimUnregisterServerFilter(im);
1124    _XimResetIMInstantiateCallback(im);
1125    status = (Status)_XimClose(im);
1126    status = (Status)_XimDisconnect(im) && status;
1127    _XimProtoIMFree(im);
1128#ifdef XIM_CONNECTABLE
1129    if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) {
1130	_XimReconnectModeSetAttr(im);
1131        for (ic = im->core.ic_chain; ic; ic = ic->core.next) {
1132	    _XimReconnectModeCreateIC(ic);
1133        }
1134	return 0;
1135    }
1136#endif /* XIM_CONNECTABLE */
1137    _XimDestroyIMStructureList(im);
1138    return status;
1139}
1140
1141#ifdef XIM_CONNECTABLE
1142Private Bool
1143_XimCheckIMQuarkList(
1144    XrmQuark		*quark_list,
1145    int			 num_quark,
1146    XrmQuark		 quark)
1147{
1148    register int	 i;
1149
1150    for (i = 0; i < num_quark; i++) {
1151	if (quark_list[i] == quark) {
1152	    return True;
1153	}
1154    }
1155    return False;
1156}
1157
1158Private Bool
1159_XimSaveIMValues(
1160    Xim			 im,
1161    XIMArg		*arg)
1162{
1163    register XIMArg	*p;
1164    register int	 n;
1165    XrmQuark		*quark_list;
1166    XrmQuark		*tmp;
1167    XrmQuark		 quark;
1168    int			 num_quark;
1169
1170    if (quark_list = im->private.proto.saved_imvalues) {
1171	num_quark = im->private.proto.num_saved_imvalues;
1172	for (p = arg; p && p->name; p++) {
1173	    quark = XrmStringToQuark(p->name);
1174	    if (_XimCheckIMQuarkList(quark_list, num_quark, quark)) {
1175		continue;
1176	    }
1177	    if (!(tmp = (XrmQuark *)Xrealloc(quark_list,
1178				(sizeof(XrmQuark) * (num_quark + 1))))) {
1179		im->private.proto.saved_imvalues = quark_list;
1180		im->private.proto.num_saved_imvalues = num_quark;
1181		return False;
1182	    }
1183	    num_quark++;
1184	    quark_list = tmp;
1185	    quark_list[num_quark] = quark;
1186	}
1187	im->private.proto.saved_imvalues = quark_list;
1188	im->private.proto.num_saved_imvalues = num_quark;
1189	return True;
1190    }
1191
1192    for (p = arg, n = 0; p && p->name; p++, n++);
1193
1194    if (!(quark_list = (XrmQuark *)Xmalloc(sizeof(XrmQuark) * n))) {
1195	return False;
1196    }
1197
1198    im->private.proto.saved_imvalues = quark_list;
1199    im->private.proto.num_saved_imvalues = n;
1200    for (p = arg; p && p->name; p++, quark_list++) {
1201	*quark_list = XrmStringToQuark(p->name);
1202    }
1203
1204    return True;
1205}
1206
1207Private char *
1208_XimDelayModeSetIMValues(
1209    Xim			 im,
1210    XIMArg		*arg)
1211{
1212    XimDefIMValues	 im_values;
1213    char		*name;
1214    XIMArg		*values;
1215
1216    _XimGetCurrentIMValues(im, &im_values);
1217    name = _XimSetIMValueData(im, (XPointer)&im_values, values,
1218		im->core.im_resources, im->core.im_num_resources);
1219    _XimSetCurrentIMValues(im, &im_values);
1220
1221    return name;
1222}
1223#endif /* XIM_CONNECTABLE */
1224
1225Private Bool
1226_XimSetIMValuesCheck(
1227    Xim          im,
1228    INT16        len,
1229    XPointer	 data,
1230    XPointer     arg)
1231{
1232    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
1233    CARD8	 major_opcode = *((CARD8 *)data);
1234    CARD8	 minor_opcode = *((CARD8 *)data + 1);
1235    XIMID	 imid = buf_s[0];
1236
1237    if ((major_opcode == XIM_SET_IM_VALUES_REPLY)
1238     && (minor_opcode == 0)
1239     && (imid == im->private.proto.imid))
1240	return True;
1241    if ((major_opcode == XIM_ERROR)
1242     && (minor_opcode == 0)
1243     && (buf_s[2] & XIM_IMID_VALID)
1244     && (imid == im->private.proto.imid))
1245	return True;
1246    return False;
1247}
1248
1249Private char *
1250_XimProtoSetIMValues(
1251    XIM			 xim,
1252    XIMArg		*arg)
1253{
1254    Xim			 im = (Xim)xim;
1255    XimDefIMValues	 im_values;
1256    INT16		 len;
1257    CARD16		*buf_s;
1258    char		*tmp;
1259    CARD32		 tmp_buf32[BUFSIZE/4];
1260    char		*tmp_buf = (char *)tmp_buf32;
1261    char		*buf;
1262    int			 buf_size;
1263    char		*data;
1264    int			 data_len;
1265    int			 ret_len;
1266    int			 total;
1267    XIMArg		*arg_ret;
1268    CARD32		 reply32[BUFSIZE/4];
1269    char		*reply = (char *)reply32;
1270    XPointer		 preply;
1271    int			 ret_code;
1272    char		*name;
1273
1274#ifndef XIM_CONNECTABLE
1275    if (!IS_SERVER_CONNECTED(im))
1276	return arg->name;
1277#else
1278    if (!_XimSaveIMValues(im, arg))
1279	return arg->name;
1280
1281    if (!IS_SERVER_CONNECTED(im)) {
1282	if (IS_CONNECTABLE(im)) {
1283	    if (!_XimConnectServer(im)) {
1284	        return _XimDelayModeSetIMValues(im, arg);
1285	    }
1286        } else {
1287	    return arg->name;
1288        }
1289    }
1290#endif /* XIM_CONNECTABLE */
1291
1292    _XimGetCurrentIMValues(im, &im_values);
1293    buf = tmp_buf;
1294    buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16);
1295    data_len = BUFSIZE - buf_size;
1296    total = 0;
1297    arg_ret = arg;
1298    for (;;) {
1299	data = &buf[buf_size];
1300	if ((name = _XimEncodeIMATTRIBUTE(im, im->core.im_resources,
1301		im->core.im_num_resources, arg, &arg_ret, data, data_len,
1302		&ret_len, (XPointer)&im_values, XIM_SETIMVALUES))) {
1303	    if (buf != tmp_buf)
1304		Xfree(buf);
1305	    break;
1306	}
1307
1308	total += ret_len;
1309	if (!(arg = arg_ret)) {
1310	    break;
1311	}
1312
1313	buf_size += ret_len;
1314	if (buf == tmp_buf) {
1315	    if (!(tmp = (char *)Xmalloc(buf_size + data_len))) {
1316		return arg->name;
1317	    }
1318	    memcpy(tmp, buf, buf_size);
1319	    buf = tmp;
1320	} else {
1321	    if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) {
1322		Xfree(buf);
1323		return arg->name;
1324	    }
1325	    buf = tmp;
1326	}
1327    }
1328    _XimSetCurrentIMValues(im, &im_values);
1329
1330    if (!total)
1331	return (char *)NULL;
1332
1333    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
1334    buf_s[0] = im->private.proto.imid;
1335    buf_s[1] = (INT16)total;
1336
1337    len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total);
1338    _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len);
1339    if (!(_XimWrite(im, len, (XPointer)buf))) {
1340	if (buf != tmp_buf)
1341	    Xfree(buf);
1342	return arg->name;
1343    }
1344    _XimFlush(im);
1345    if (buf != tmp_buf)
1346	Xfree(buf);
1347    buf_size = BUFSIZE;
1348    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
1349					 _XimSetIMValuesCheck, 0);
1350    if(ret_code == XIM_TRUE) {
1351	preply = reply;
1352    } else if(ret_code == XIM_OVERFLOW) {
1353	if(len <= 0) {
1354	    preply = reply;
1355	} else {
1356	    buf_size = (int)len;
1357	    preply = (XPointer)Xmalloc(buf_size);
1358	    ret_code = _XimRead(im, &len, reply, buf_size,
1359					_XimSetIMValuesCheck, 0);
1360	    if(ret_code != XIM_TRUE) {
1361		Xfree(preply);
1362		return arg->name;
1363	    }
1364	}
1365    } else
1366	return arg->name;
1367    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
1368    if (*((CARD8 *)preply) == XIM_ERROR) {
1369	_XimProcError(im, 0, (XPointer)&buf_s[3]);
1370	if(reply != preply)
1371	    Xfree(preply);
1372	return arg->name;
1373    }
1374    if(reply != preply)
1375	Xfree(preply);
1376
1377    return name;
1378}
1379
1380#ifdef XIM_CONNECTABLE
1381Private char *
1382_XimDelayModeGetIMValues(
1383    Xim			 im,
1384    XIMArg		*arg)
1385{
1386    XimDefIMValues	 im_values;
1387
1388    _XimGetCurrentIMValues(im, &im_values);
1389    return(_XimGetIMValueData(im, (XPointer)&im_values, arg,
1390			im->core.im_resources, im->core.im_num_resources));
1391}
1392#endif /* XIM_CONNECTABLE */
1393
1394Private Bool
1395_XimGetIMValuesCheck(
1396    Xim          im,
1397    INT16        len,
1398    XPointer	 data,
1399    XPointer     arg)
1400{
1401    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
1402    CARD8	 major_opcode = *((CARD8 *)data);
1403    CARD8	 minor_opcode = *((CARD8 *)data + 1);
1404    XIMID	 imid = buf_s[0];
1405
1406    if ((major_opcode == XIM_GET_IM_VALUES_REPLY)
1407     && (minor_opcode == 0)
1408     && (imid == im->private.proto.imid))
1409	return True;
1410    if ((major_opcode == XIM_ERROR)
1411     && (minor_opcode == 0)
1412     && (buf_s[2] & XIM_IMID_VALID)
1413     && (imid == im->private.proto.imid))
1414	return True;
1415    return False;
1416}
1417
1418Private char *
1419_XimProtoGetIMValues(
1420    XIM			 xim,
1421    XIMArg		*arg)
1422{
1423    Xim			 im = (Xim)xim;
1424    register XIMArg	*p;
1425    register int	 n;
1426    CARD8		*buf;
1427    CARD16		*buf_s;
1428    INT16		 len;
1429    CARD32		 reply32[BUFSIZE/4];
1430    char		*reply = (char *)reply32;
1431    XPointer		 preply = NULL;
1432    int			 buf_size;
1433    int			 ret_code;
1434    char		*makeid_name;
1435    char		*decode_name;
1436    CARD16		*data = NULL;
1437    INT16		 data_len = 0;
1438
1439#ifndef XIM_CONNECTABLE
1440    if (!IS_SERVER_CONNECTED(im))
1441	return arg->name;
1442#else
1443    if (!IS_SERVER_CONNECTED(im)) {
1444	if (IS_CONNECTABLE(im)) {
1445	    if (!_XimConnectServer(im)) {
1446	        return _XimDelayModeGetIMValues(im, arg);
1447	    }
1448        } else {
1449	    return arg->name;
1450        }
1451    }
1452#endif /* XIM_CONNECTABLE */
1453
1454    for (n = 0, p = arg; p->name; p++)
1455	n++;
1456
1457    if (!n)
1458	return (char *)NULL;
1459
1460    buf_size =  sizeof(CARD16) * n;
1461    buf_size += XIM_HEADER_SIZE
1462	     + sizeof(CARD16)
1463	     + sizeof(INT16)
1464	     + XIM_PAD(buf_size);
1465
1466    if (!(buf = (CARD8 *)Xmalloc(buf_size)))
1467	return arg->name;
1468    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
1469
1470    makeid_name = _XimMakeIMAttrIDList(im, im->core.im_resources,
1471				im->core.im_num_resources, arg,
1472				&buf_s[2], &len, XIM_GETIMVALUES);
1473
1474    if (len) {
1475	buf_s[0] = im->private.proto.imid;	/* imid */
1476	buf_s[1] = len;				/* length of im-attr-id */
1477	XIM_SET_PAD(&buf_s[2], len);		/* pad */
1478	len += sizeof(CARD16)			/* sizeof imid */
1479	     + sizeof(INT16);			/* sizeof length of attr */
1480
1481	_XimSetHeader((XPointer)buf, XIM_GET_IM_VALUES, 0, &len);
1482	if (!(_XimWrite(im, len, (XPointer)buf))) {
1483	    Xfree(buf);
1484	    return arg->name;
1485	}
1486	_XimFlush(im);
1487	Xfree(buf);
1488    	buf_size = BUFSIZE;
1489    	ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
1490    						_XimGetIMValuesCheck, 0);
1491	if(ret_code == XIM_TRUE) {
1492	    preply = reply;
1493	} else if(ret_code == XIM_OVERFLOW) {
1494	    if(len <= 0) {
1495		preply = reply;
1496	    } else {
1497		buf_size = len;
1498		preply = (XPointer)Xmalloc(buf_size);
1499		ret_code = _XimRead(im, &len, preply, buf_size,
1500						_XimGetIMValuesCheck, 0);
1501		if(ret_code != XIM_TRUE) {
1502		    Xfree(preply);
1503		    return arg->name;
1504		}
1505	    }
1506	} else
1507	    return arg->name;
1508	buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
1509	if (*((CARD8 *)preply) == XIM_ERROR) {
1510	    _XimProcError(im, 0, (XPointer)&buf_s[3]);
1511	    if(reply != preply)
1512		Xfree(preply);
1513	    return arg->name;
1514	}
1515	data = &buf_s[2];
1516	data_len = buf_s[1];
1517    }
1518    decode_name = _XimDecodeIMATTRIBUTE(im, im->core.im_resources,
1519			im->core.im_num_resources, data, data_len,
1520			arg, XIM_GETIMVALUES);
1521    if (reply != preply)
1522	Xfree(preply);
1523
1524    if (decode_name)
1525	return decode_name;
1526    else
1527	return makeid_name;
1528}
1529
1530Private XIMMethodsRec     im_methods = {
1531    _XimProtoCloseIM,           /* close */
1532    _XimProtoSetIMValues,       /* set_values */
1533    _XimProtoGetIMValues,       /* get_values */
1534    _XimProtoCreateIC,          /* create_ic */
1535    _Ximctstombs,		/* ctstombs */
1536    _Ximctstowcs,		/* ctstowcs */
1537    _Ximctstoutf8		/* ctstoutf8 */
1538};
1539
1540Private Bool
1541_XimSetEncodingByName(
1542    Xim		  im,
1543    char	**buf,
1544    int		 *len)
1545{
1546    char	*encoding = (char *)NULL;
1547    int		 encoding_len;
1548    int		 compound_len;
1549    BYTE	*ret;
1550
1551    _XGetLCValues(im->core.lcd, XlcNCodeset, &encoding, NULL);
1552    if (!encoding) {
1553	*buf = (char *)NULL;
1554	*len = 0;
1555	return True;
1556    }
1557    encoding_len = strlen(encoding);
1558    compound_len = strlen("COMPOUND_TEXT");
1559    *len = encoding_len + sizeof(BYTE) + compound_len + sizeof(BYTE);
1560    if (!(ret = (BYTE *)Xmalloc(*len))) {
1561	return False;
1562    }
1563    *buf = (char *)ret;
1564
1565    ret[0] = (BYTE)encoding_len;
1566    (void)strncpy((char *)&ret[1], encoding, encoding_len);
1567    ret += (encoding_len + sizeof(BYTE));
1568    ret[0] = (BYTE)compound_len;
1569    (void)strncpy((char *)&ret[1], "COMPOUND_TEXT", compound_len);
1570    return True;
1571}
1572
1573Private Bool
1574_XimSetEncodingByDetail(
1575    Xim		 im,
1576    char	**buf,
1577    int		 *len)
1578{
1579    *len = 0;
1580    *buf = NULL;
1581    return True;
1582}
1583
1584Private Bool
1585_XimGetEncoding(
1586    Xim		 im,
1587    CARD16	*buf,
1588    char	*name,
1589    int		 name_len,
1590    char	*detail,
1591    int		 detail_len)
1592{
1593    XLCd	 lcd = im->core.lcd;
1594    CARD16	 category = buf[0];
1595    CARD16	 idx = buf[1];
1596    int		 len;
1597    XlcConv	 ctom_conv = NULL;
1598    XlcConv	 ctow_conv = NULL;
1599    XlcConv	 ctoutf8_conv = NULL;
1600    XlcConv	 conv;
1601    XimProtoPrivateRec *private = &im->private.proto;
1602
1603    if (idx == (CARD16)XIM_Default_Encoding_IDX) { /* XXX */
1604	if (!(ctom_conv = _XlcOpenConverter(lcd,
1605				 XlcNCompoundText, lcd, XlcNMultiByte)))
1606	    return False;
1607	if (!(ctow_conv = _XlcOpenConverter(lcd,
1608				 XlcNCompoundText, lcd, XlcNWideChar)))
1609	    return False;
1610	if (!(ctoutf8_conv = _XlcOpenConverter(lcd,
1611				 XlcNCompoundText, lcd, XlcNUtf8String)))
1612	    return False;
1613    }
1614
1615    if (category == XIM_Encoding_NameCategory) {
1616	while (name_len > 0) {
1617	    len = (int)name[0];
1618	    if (!strncmp(&name[1], "COMPOUND_TEXT", len)) {
1619		if (!(ctom_conv = _XlcOpenConverter(lcd,
1620				 XlcNCompoundText, lcd, XlcNMultiByte)))
1621		    return False;
1622		if (!(ctow_conv = _XlcOpenConverter(lcd,
1623				 XlcNCompoundText, lcd, XlcNWideChar)))
1624		    return False;
1625		if (!(ctoutf8_conv = _XlcOpenConverter(lcd,
1626				 XlcNCompoundText, lcd, XlcNUtf8String)))
1627		    return False;
1628		break;
1629	    } else {
1630		/*
1631		 * Not yet
1632		 */
1633	    }
1634	    len += sizeof(BYTE);
1635	    name_len -= len;
1636	    name += len;
1637	}
1638    } else if (category == XIM_Encoding_DetailCategory) {
1639	/*
1640	 * Not yet
1641	 */
1642    } else {
1643	return False;
1644    }
1645
1646    private->ctom_conv = ctom_conv;
1647    private->ctow_conv = ctow_conv;
1648    private->ctoutf8_conv = ctoutf8_conv;
1649
1650    if (!(conv = _XlcOpenConverter(lcd,	XlcNCharSet, lcd, XlcNMultiByte)))
1651	return False;
1652    private->cstomb_conv = conv;
1653
1654    if (!(conv = _XlcOpenConverter(lcd,	XlcNCharSet, lcd, XlcNWideChar)))
1655	return False;
1656    private->cstowc_conv = conv;
1657
1658    if (!(conv = _XlcOpenConverter(lcd,	XlcNCharSet, lcd, XlcNUtf8String)))
1659	return False;
1660    private->cstoutf8_conv = conv;
1661
1662    if (!(conv = _XlcOpenConverter(lcd,	XlcNUcsChar, lcd, XlcNChar)))
1663	return False;
1664    private->ucstoc_conv = conv;
1665
1666    if (!(conv = _XlcOpenConverter(lcd,	XlcNUcsChar, lcd, XlcNUtf8String)))
1667	return False;
1668    private->ucstoutf8_conv = conv;
1669
1670    return True;
1671}
1672
1673Private	Bool
1674_XimEncodingNegoCheck(
1675    Xim		 im,
1676    INT16	 len,
1677    XPointer	 data,
1678    XPointer	 arg)
1679{
1680    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
1681    CARD8	 major_opcode = *((CARD8 *)data);
1682    CARD8	 minor_opcode = *((CARD8 *)data + 1);
1683    XIMID	 imid = buf_s[0];
1684
1685    if ((major_opcode == XIM_ENCODING_NEGOTIATION_REPLY)
1686     && (minor_opcode == 0)
1687     && (imid == im->private.proto.imid))
1688	return True;
1689    if ((major_opcode == XIM_ERROR)
1690     && (minor_opcode == 0)
1691     && (buf_s[2] & XIM_IMID_VALID)
1692     && (imid == im->private.proto.imid))
1693	return True;
1694    return False;
1695}
1696
1697Private Bool
1698_XimEncodingNegotiation(
1699    Xim		 im)
1700{
1701    char	*name_ptr = 0;
1702    int		 name_len = 0;
1703    char	*detail_ptr = 0;
1704    int		 detail_len = 0;
1705    CARD8	*buf;
1706    CARD16	*buf_s;
1707    INT16	 len;
1708    CARD32	 reply32[BUFSIZE/4];
1709    char	*reply = (char *)reply32;
1710    XPointer	 preply;
1711    int		 buf_size;
1712    int		 ret_code;
1713
1714    if (!(_XimSetEncodingByName(im, &name_ptr, &name_len)))
1715	return False;
1716
1717    if (!(_XimSetEncodingByDetail(im, &detail_ptr, &detail_len))) {
1718	if (name_ptr)
1719	    Xfree(name_ptr);
1720	return False;
1721    }
1722
1723    len = sizeof(CARD16)
1724	+ sizeof(INT16)
1725	+ name_len
1726	+ XIM_PAD(name_len)
1727	+ sizeof(INT16)
1728	+ sizeof(CARD16)
1729	+ detail_len;
1730
1731    if (!(buf = (CARD8 *)Xmalloc(XIM_HEADER_SIZE + len))) {
1732	if (name_ptr)
1733	    Xfree(name_ptr);
1734	if (detail_ptr)
1735	    Xfree(detail_ptr);
1736	return False;
1737    }
1738    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
1739
1740    buf_s[0] = im->private.proto.imid;
1741    buf_s[1] = (INT16)name_len;
1742    if (name_ptr)
1743	(void)memcpy((char *)&buf_s[2], name_ptr, name_len);
1744    XIM_SET_PAD(&buf_s[2], name_len);
1745    buf_s = (CARD16 *)((char *)&buf_s[2] + name_len);
1746    buf_s[0] = detail_len;
1747    buf_s[1] = 0;
1748    if (detail_ptr)
1749	(void)memcpy((char *)&buf_s[2], detail_ptr, detail_len);
1750
1751    _XimSetHeader((XPointer)buf, XIM_ENCODING_NEGOTIATION, 0, &len);
1752    if (!(_XimWrite(im, len, (XPointer)buf))) {
1753	Xfree(buf);
1754	return False;
1755    }
1756    _XimFlush(im);
1757    Xfree(buf);
1758    buf_size = BUFSIZE;
1759    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
1760					_XimEncodingNegoCheck, 0);
1761    if(ret_code == XIM_TRUE) {
1762	preply = reply;
1763    } else if(ret_code == XIM_OVERFLOW) {
1764	if(len <= 0) {
1765	    preply = reply;
1766	} else {
1767	    buf_size = len;
1768	    preply = (XPointer)Xmalloc(buf_size);
1769	    ret_code = _XimRead(im, &len, preply, buf_size,
1770					_XimEncodingNegoCheck, 0);
1771	    if(ret_code != XIM_TRUE) {
1772		Xfree(preply);
1773		return False;
1774	    }
1775	}
1776    } else
1777	return False;
1778    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
1779    if (*((CARD8 *)preply) == XIM_ERROR) {
1780	_XimProcError(im, 0, (XPointer)&buf_s[3]);
1781	if(reply != preply)
1782	    Xfree(preply);
1783	return False;
1784    }
1785
1786    if (!(_XimGetEncoding(im, &buf_s[1], name_ptr, name_len,
1787						detail_ptr, detail_len))) {
1788	if(reply != preply)
1789	    Xfree(preply);
1790	return False;
1791    }
1792    if (name_ptr)
1793	Xfree(name_ptr);
1794    if (detail_ptr)
1795	Xfree(detail_ptr);
1796
1797    if(reply != preply)
1798	Xfree(preply);
1799
1800    return True;
1801}
1802
1803#ifdef XIM_CONNECTABLE
1804Private Bool
1805_XimSendSavedIMValues(
1806    Xim			 im)
1807{
1808    XimDefIMValues	 im_values;
1809    INT16		 len;
1810    CARD16		*buf_s;
1811    char		*tmp;
1812    CARD32		 tmp_buf32[BUFSIZE/4];
1813    char		*tmp_buf = (char *)tmp_buf32;
1814    char		*buf;
1815    int			 buf_size;
1816    char		*data;
1817    int			 data_len;
1818    int			 ret_len;
1819    int			 total;
1820    int			 idx;
1821    CARD32		 reply32[BUFSIZE/4];
1822    char		*reply = (char *)reply32;
1823    XPointer		 preply;
1824    int			 ret_code;
1825
1826    _XimGetCurrentIMValues(im, &im_values);
1827    buf = tmp_buf;
1828    buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16);
1829    data_len = BUFSIZE - buf_size;
1830    total = 0;
1831    idx = 0;
1832    for (;;) {
1833	data = &buf[buf_size];
1834	if (!_XimEncodeSavedIMATTRIBUTE(im, im->core.im_resources,
1835		im->core.im_num_resources, &idx, data, data_len,
1836		&ret_len, (XPointer)&im_values, XIM_SETIMVALUES)) {
1837	    if (buf != tmp_buf)
1838		Xfree(buf);
1839	    return False;
1840	}
1841
1842	total += ret_len;
1843	if (idx == -1) {
1844	    break;
1845	}
1846
1847	buf_size += ret_len;
1848	if (buf == tmp_buf) {
1849	    if (!(tmp = (char *)Xmalloc(buf_size + data_len))) {
1850		return False;
1851	    }
1852	    memcpy(tmp, buf, buf_size);
1853	    buf = tmp;
1854	} else {
1855	    if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) {
1856		Xfree(buf);
1857		return False;
1858	    }
1859	    buf = tmp;
1860	}
1861    }
1862
1863    if (!total)
1864	return True;
1865
1866    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
1867    buf_s[0] = im->private.proto.imid;
1868    buf_s[1] = (INT16)total;
1869
1870    len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total);
1871    _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len);
1872    if (!(_XimWrite(im, len, (XPointer)buf))) {
1873	if (buf != tmp_buf)
1874	    Xfree(buf);
1875	return False;
1876    }
1877    _XimFlush(im);
1878    if (buf != tmp_buf)
1879	Xfree(buf);
1880    buf_size = BUFSIZE;
1881    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
1882    					 _XimSetIMValuesCheck, 0);
1883    if(ret_code == XIM_TRUE) {
1884	preply = reply;
1885    } else if(ret_code == XIM_OVERFLOW) {
1886	if(len <= 0) {
1887	    preply = reply;
1888	} else {
1889	    buf_size = (int)len;
1890	    preply = (XPointer)Xmalloc(buf_size);
1891	    ret_code = _XimRead(im, &len, reply, buf_size,
1892					_XimSetIMValuesCheck, 0);
1893    	    if(ret_code != XIM_TRUE) {
1894		Xfree(preply);
1895		return False;
1896	    }
1897	}
1898    } else
1899	return False;
1900
1901    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
1902    if (*((CARD8 *)preply) == XIM_ERROR) {
1903	_XimProcError(im, 0, (XPointer)&buf_s[3]);
1904    	if(reply != preply)
1905	    Xfree(preply);
1906	return False;
1907    }
1908    if(reply != preply)
1909	Xfree(preply);
1910
1911    return True;
1912}
1913
1914Private void
1915_XimDelayModeIMFree(
1916    Xim		 im)
1917{
1918    if (im->core.im_resources) {
1919	Xfree(im->core.im_resources);
1920	im->core.im_resources = NULL;
1921    }
1922    if (im->core.ic_resources) {
1923	Xfree(im->core.ic_resources);
1924	im->core.ic_resources = NULL;
1925    }
1926    if (im->core.im_values_list) {
1927	Xfree(im->core.im_values_list);
1928	im->core.im_values_list = NULL;
1929    }
1930    if (im->core.ic_values_list) {
1931	Xfree(im->core.ic_values_list);
1932	im->core.ic_values_list = NULL;
1933    }
1934    return;
1935}
1936
1937Public Bool
1938_XimConnectServer(
1939    Xim		 im)
1940{
1941    Xim		 save_im;
1942
1943    if (!(save_im = (Xim)Xmalloc(sizeof(XimRec))))
1944	return False;
1945    memcpy((char *)save_im, (char *)im, sizeof(XimRec));
1946
1947    if (_XimPreConnect(im) && _XimConnection(im)
1948			&& _XimOpen(im) && _XimEncodingNegotiation(im)) {
1949	if (_XimSendSavedIMValues(im)) {
1950	    _XimDelayModeIMFree(save_im);
1951	    _XimRegisterServerFilter(im);
1952	    Xfree(save_im);
1953	    return True;
1954	}
1955    }
1956    memcpy((char *)im, (char *)save_im, sizeof(XimRec));
1957    Xfree(save_im);
1958    return False;
1959}
1960
1961Public Bool
1962_XimDelayModeSetAttr(
1963    Xim			 im)
1964{
1965    XimDefIMValues	 im_values;
1966
1967    if(!_XimSetIMResourceList(&im->core.im_resources,
1968						&im->core.im_num_resources)) {
1969	return False;
1970    }
1971    if(!_XimSetICResourceList(&im->core.ic_resources,
1972						&im->core.ic_num_resources)) {
1973	return False;
1974    }
1975
1976    _XimSetIMMode(im->core.im_resources, im->core.im_num_resources);
1977
1978    _XimGetCurrentIMValues(im, &im_values);
1979    if(!_XimSetLocalIMDefaults(im, (XPointer)&im_values,
1980			im->core.im_resources, im->core.im_num_resources)) {
1981	return False;
1982    }
1983    _XimSetCurrentIMValues(im, &im_values);
1984    if (im->private.proto.default_styles) {
1985        if (im->core.styles)
1986	    Xfree(im->core.styles);
1987        im->core.styles = im->private.proto.default_styles;
1988    }
1989
1990    return True;
1991}
1992
1993Private Bool
1994_XimReconnectModeSetAttr(
1995    Xim			 im)
1996{
1997    XimDefIMValues	 im_values;
1998
1999    if(!_XimSetIMResourceList(&im->core.im_resources,
2000						&im->core.im_num_resources)) {
2001	return False;
2002    }
2003    if(!_XimSetICResourceList(&im->core.ic_resources,
2004						&im->core.ic_num_resources)) {
2005	return False;
2006    }
2007
2008    _XimSetIMMode(im->core.im_resources, im->core.im_num_resources);
2009
2010    if (im->private.proto.default_styles) {
2011        if (im->core.styles)
2012	    Xfree(im->core.styles);
2013        im->core.styles = im->private.proto.default_styles;
2014    }
2015
2016    return True;
2017}
2018#endif /* XIM_CONNECTABLE */
2019
2020Public Bool
2021_XimProtoOpenIM(
2022    Xim		 im)
2023{
2024    _XimInitialResourceInfo();
2025
2026    im->methods = &im_methods;
2027
2028#ifdef XIM_CONNECTABLE
2029    _XimSetProtoResource(im);
2030#endif /* XIM_CONNECTABLE */
2031
2032    if (_XimPreConnect(im)) {
2033	if (_XimConnection(im) && _XimOpen(im) && _XimEncodingNegotiation(im)) {
2034	    _XimRegisterServerFilter(im);
2035	    return True;
2036	}
2037	_XimShutdown(im);
2038#ifdef XIM_CONNECTABLE
2039    } else if (IS_DELAYBINDABLE(im)) {
2040	if (_XimDelayModeSetAttr(im))
2041	    return True;
2042#endif /* XIM_CONNECTABLE */
2043    }
2044    _XimProtoIMFree(im);
2045    return False;
2046}
2047