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