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