imDefIc.c revision 6cc2b21f
1/*
2 * Copyright 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
27Permission to use, copy, modify, distribute, and sell this software
28and its documentation for any purpose is hereby granted without fee,
29provided that the above copyright notice appear in all copies and
30that both that copyright notice and this permission notice appear
31in supporting documentation, and that the name of FUJITSU LIMITED
32not be used in advertising or publicity pertaining to distribution
33of the software without specific, written prior permission.
34FUJITSU LIMITED makes no representations about the suitability of
35this software for any purpose.
36It is provided "as is" without express or implied warranty.
37
38FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
39INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
40EVENT SHALL FUJITSU LIMITED 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
50******************************************************************/
51
52#ifdef HAVE_CONFIG_H
53#include <config.h>
54#endif
55#include "Xlibint.h"
56#include "Xlcint.h"
57#include "Ximint.h"
58
59Private Bool
60_XimCreateICCheck(
61    Xim          im,
62    INT16        len,
63    XPointer	 data,
64    XPointer     arg)
65{
66    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
67    CARD8	 major_opcode = *((CARD8 *)data);
68    CARD8	 minor_opcode = *((CARD8 *)data + 1);
69    XIMID	 imid = buf_s[0];
70
71    if ((major_opcode == XIM_CREATE_IC_REPLY)
72     && (minor_opcode == 0)
73     && (imid == im->private.proto.imid))
74	return True;
75    if ((major_opcode == XIM_ERROR)
76     && (minor_opcode == 0)
77     && (buf_s[2] & XIM_IMID_VALID)
78     && (imid == im->private.proto.imid))
79	return True;
80    return False;
81}
82
83#ifdef XIM_CONNECTABLE
84Public Bool
85_XimReCreateIC(ic)
86    Xic			 ic;
87{
88    Xim			 im = (Xim)ic->core.im;
89    Xic			 save_ic;
90    XIMResourceList	 res;
91    unsigned int         num;
92    XIMStyle		 input_style = ic->core.input_style;
93    XimDefICValues	 ic_values;
94    INT16		 len;
95    CARD16		*buf_s;
96    char		*tmp;
97    CARD32		 tmp_buf32[BUFSIZE/4];
98    char		*tmp_buf = (char *)tmp_buf32;
99    char		*buf;
100    int			 buf_size;
101    char		*data;
102    int			 data_len;
103    int			 ret_len;
104    int			 total;
105    int			 idx;
106    CARD32		 reply32[BUFSIZE/4];
107    char		*reply = (char *)reply32;
108    XPointer		 preply;
109    int			 ret_code;
110
111    if (!(save_ic = (Xic)Xmalloc(sizeof(XicRec))))
112	return False;
113    memcpy((char *)save_ic, (char *)ic, sizeof(XicRec));
114
115    ic->core.filter_events = im->private.proto.forward_event_mask;
116    ic->private.proto.forward_event_mask =
117				im->private.proto.forward_event_mask;
118    ic->private.proto.synchronous_event_mask =
119				im->private.proto.synchronous_event_mask;
120
121    num = im->core.ic_num_resources;
122    buf_size = sizeof(XIMResource) * num;
123    if (!(res = (XIMResourceList)Xmalloc(buf_size)))
124	goto ErrorOnReCreateIC;
125    (void)memcpy((char *)res, (char *)im->core.ic_resources, buf_size);
126    ic->private.proto.ic_resources     = res;
127    ic->private.proto.ic_num_resources = num;
128
129    num = im->private.proto.ic_num_inner_resources;
130    buf_size = sizeof(XIMResource) * num;
131    if (!(res = (XIMResourceList)Xmalloc(buf_size)))
132	goto ErrorOnReCreateIC;
133    (void)memcpy((char *)res,
134			(char *)im->private.proto.ic_inner_resources, buf_size);
135    ic->private.proto.ic_inner_resources     = res;
136    ic->private.proto.ic_num_inner_resources = num;
137
138    _XimSetICMode(ic->private.proto.ic_resources,
139			ic->private.proto.ic_num_resources, input_style);
140
141    _XimSetICMode(ic->private.proto.ic_inner_resources,
142			ic->private.proto.ic_num_inner_resources, input_style);
143
144    _XimGetCurrentICValues(ic, &ic_values);
145    buf = tmp_buf;
146    buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16);
147    data_len = BUFSIZE - buf_size;
148    total = 0;
149    idx = 0;
150    for (;;) {
151	data = &buf[buf_size];
152	if (!_XimEncodeSavedICATTRIBUTE(ic, ic->private.proto.ic_resources,
153		ic->private.proto.ic_num_resources, &idx, data, data_len,
154		&ret_len, (XPointer)&ic_values, XIM_CREATEIC)) {
155	    if (buf != tmp_buf)
156		Xfree(buf);
157	    goto ErrorOnReCreateIC;
158	}
159
160	total += ret_len;
161	if (idx == -1) {
162	    break;
163	}
164
165	buf_size += ret_len;
166	if (buf == tmp_buf) {
167	    if (!(tmp = (char *)Xmalloc(buf_size + data_len))) {
168		goto ErrorOnReCreateIC;
169	    }
170	    memcpy(tmp, buf, buf_size);
171	    buf = tmp;
172	} else {
173	    if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) {
174		Xfree(buf);
175		goto ErrorOnReCreateIC;
176	    }
177	    buf = tmp;
178	}
179    }
180
181    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
182    buf_s[0] = im->private.proto.imid;
183    buf_s[1] = (INT16)total;
184
185    len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total);
186    _XimSetHeader((XPointer)buf, XIM_CREATE_IC, 0, &len);
187    if (!(_XimWrite(im, len, (XPointer)buf))) {
188	if (buf != tmp_buf)
189	    Xfree(buf);
190	goto ErrorOnReCreateIC;
191    }
192    _XimFlush(im);
193    if (buf != tmp_buf)
194	Xfree(buf);
195    ic->private.proto.waitCallback = True;
196    buf_size = BUFSIZE;
197    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
198						 _XimCreateICCheck, 0);
199    if (ret_code == XIM_TRUE) {
200	preply = reply;
201    } else if (ret_code == XIM_OVERFLOW) {
202	if (len <= 0) {
203	    preply = reply;
204	} else {
205	    buf_size = (int)len;
206	    preply = (XPointer)Xmalloc(buf_size);
207	    ret_code = _XimRead(im, &len, preply, buf_size,
208						 _XimCreateICCheck, 0);
209	    if (ret_code != XIM_TRUE) {
210		Xfree(preply);
211		ic->private.proto.waitCallback = False;
212		goto ErrorOnReCreateIC;
213	    }
214	}
215    } else {
216	ic->private.proto.waitCallback = False;
217	goto ErrorOnReCreateIC;
218    }
219    ic->private.proto.waitCallback = False;
220    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
221    if (*((CARD8 *)preply) == XIM_ERROR) {
222	_XimProcError(im, 0, (XPointer)&buf_s[3]);
223	if (reply != preply)
224	    Xfree(preply);
225	goto ErrorOnReCreateIC;
226    }
227
228    ic->private.proto.icid = buf_s[1];		/* icid */
229    if (reply != preply)
230	Xfree(preply);
231
232    _XimRegisterFilter(ic);
233    MARK_IC_CONNECTED(ic);
234    if (save_ic->private.proto.ic_resources)
235	Xfree(save_ic->private.proto.ic_resources);
236    if (save_ic->private.proto.ic_inner_resources)
237	Xfree(save_ic->private.proto.ic_inner_resources);
238    Xfree(save_ic);
239    return True;
240
241ErrorOnReCreateIC:
242    memcpy((char *)ic, (char *)save_ic, sizeof(XicRec));
243    Xfree(save_ic);
244    return False;
245}
246
247Private char *
248_XimDelayModeGetICValues(ic, arg)
249    Xic			 ic;
250    XIMArg		*arg;
251{
252    XimDefICValues	 ic_values;
253
254    _XimGetCurrentICValues(ic, &ic_values);
255    return  _XimGetICValueData(ic, (XPointer)&ic_values,
256				ic->private.proto.ic_resources,
257				ic->private.proto.ic_num_resources,
258				arg, XIM_GETICVALUES);
259}
260#endif /* XIM_CONNECTABLE */
261
262Private Bool
263_XimGetICValuesCheck(
264    Xim          im,
265    INT16        len,
266    XPointer	 data,
267    XPointer     arg)
268{
269    Xic		 ic = (Xic)arg;
270    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
271    CARD8	 major_opcode = *((CARD8 *)data);
272    CARD8	 minor_opcode = *((CARD8 *)data + 1);
273    XIMID	 imid = buf_s[0];
274    XICID	 icid = buf_s[1];
275
276    if ((major_opcode == XIM_GET_IC_VALUES_REPLY)
277     && (minor_opcode == 0)
278     && (imid == im->private.proto.imid)
279     && (icid == ic->private.proto.icid))
280	return True;
281    if ((major_opcode == XIM_ERROR)
282     && (minor_opcode == 0)
283     && (buf_s[2] & XIM_IMID_VALID)
284     && (imid == im->private.proto.imid)
285     && (buf_s[2] & XIM_ICID_VALID)
286     && (icid == ic->private.proto.icid))
287	return True;
288    return False;
289}
290
291Private char *
292_XimProtoGetICValues(
293    XIC			 xic,
294    XIMArg		*arg)
295{
296    Xic			 ic = (Xic)xic;
297    Xim			 im = (Xim)ic->core.im;
298    register XIMArg	*p;
299    register XIMArg	*pp;
300    register int	 n;
301    CARD8		*buf;
302    CARD16		*buf_s;
303    INT16		 len;
304    CARD32		 reply32[BUFSIZE/4];
305    char		*reply = (char *)reply32;
306    XPointer		 preply = NULL;
307    int			 buf_size;
308    int			 ret_code;
309    char		*makeid_name;
310    char		*decode_name;
311    CARD16		*data = NULL;
312    INT16		 data_len = 0;
313
314#ifndef XIM_CONNECTABLE
315    if (!IS_IC_CONNECTED(ic))
316	return arg->name;
317#else
318    if (!IS_IC_CONNECTED(ic)) {
319	if (IS_CONNECTABLE(im)) {
320	    if (_XimConnectServer(im)) {
321		if (!_XimReCreateIC(ic)) {
322		    _XimDelayModeSetAttr(im);
323	            return _XimDelayModeGetICValues(ic, arg);
324		}
325	    } else {
326	        return _XimDelayModeGetICValues(ic, arg);
327	    }
328        } else {
329	    return arg->name;
330        }
331    }
332#endif /* XIM_CONNECTABLE */
333
334    for (n = 0, p = arg; p && p->name; p++) {
335	n++;
336	if ((strcmp(p->name, XNPreeditAttributes) == 0)
337	 || (strcmp(p->name, XNStatusAttributes) == 0)) {
338	     n++;
339	     for (pp = (XIMArg *)p->value; pp && pp->name; pp++)
340	 	n++;
341	}
342    }
343
344    if (!n)
345	return (char *)NULL;
346
347    buf_size =  sizeof(CARD16) * n;
348    buf_size += XIM_HEADER_SIZE
349	     + sizeof(CARD16)
350	     + sizeof(CARD16)
351	     + sizeof(INT16)
352	     + XIM_PAD(2 + buf_size);
353
354    if (!(buf = (CARD8 *)Xmalloc(buf_size)))
355	return arg->name;
356    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
357
358    makeid_name = _XimMakeICAttrIDList(ic, ic->private.proto.ic_resources,
359				ic->private.proto.ic_num_resources, arg,
360				&buf_s[3], &len, XIM_GETICVALUES);
361
362    if (len > 0) {
363	buf_s[0] = im->private.proto.imid;		/* imid */
364	buf_s[1] = ic->private.proto.icid;		/* icid */
365	buf_s[2] = len;				/* length of ic-attr-id */
366	len += sizeof(INT16);                       /* sizeof length of attr */
367	XIM_SET_PAD(&buf_s[2], len);		/* pad */
368	len += sizeof(CARD16)			/* sizeof imid */
369	     + sizeof(CARD16);			/* sizeof icid */
370
371	_XimSetHeader((XPointer)buf, XIM_GET_IC_VALUES, 0, &len);
372	if (!(_XimWrite(im, len, (XPointer)buf))) {
373	    Xfree(buf);
374	    return arg->name;
375	}
376	_XimFlush(im);
377	Xfree(buf);
378	buf_size = BUFSIZE;
379	ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
380				 _XimGetICValuesCheck, (XPointer)ic);
381	if (ret_code == XIM_TRUE) {
382	    preply = reply;
383	} else if (ret_code == XIM_OVERFLOW) {
384	    if (len <= 0) {
385		preply = reply;
386	    } else {
387		buf_size = (int)len;
388		preply = (XPointer)Xmalloc(len);
389		ret_code = _XimRead(im, &len, preply, buf_size,
390				_XimGetICValuesCheck, (XPointer)ic);
391		if (ret_code != XIM_TRUE) {
392		    if (preply != reply)
393		        Xfree(preply);
394		    return arg->name;
395		}
396	    }
397	} else {
398	    return arg->name;
399	}
400	buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
401	if (*((CARD8 *)preply) == XIM_ERROR) {
402	    _XimProcError(im, 0, (XPointer)&buf_s[3]);
403	    if (reply != preply)
404		Xfree(preply);
405	    return arg->name;
406	}
407	data = &buf_s[4];
408	data_len = buf_s[2];
409    }
410    else if (len < 0) {
411	return arg->name;
412    }
413
414    decode_name = _XimDecodeICATTRIBUTE(ic, ic->private.proto.ic_resources,
415			ic->private.proto.ic_num_resources, data, data_len,
416			arg, XIM_GETICVALUES);
417    if (reply != preply)
418	Xfree(preply);
419
420    if (decode_name)
421	return decode_name;
422    else
423	return makeid_name;
424}
425
426#ifdef XIM_CONNECTABLE
427Private Bool
428_XimCheckNestQuarkList(quark_list, num_quark, quark, separator)
429    XrmQuark		*quark_list;
430    int			 num_quark;
431    XrmQuark		 quark;
432    XrmQuark		 separator;
433{
434    register int	 i;
435
436    for (i = 0; i < num_quark; i++) {
437	if (quark_list[i] == separator) {
438	    break;
439	}
440	if (quark_list[i] == quark) {
441	    return True;
442	}
443    }
444    return False;
445}
446
447Private Bool
448_XimCheckNestedQuarkList(quark_list, idx, num_quark, arg, separator)
449    XrmQuark		**quark_list;
450    int			  idx;
451    int			 *num_quark;
452    XIMArg		 *arg;
453    XrmQuark		  separator;
454{
455    XrmQuark		 *q_list = *quark_list;
456    int			  n_quark = *num_quark;
457    register XIMArg	 *p;
458    XrmQuark		  quark;
459    XrmQuark		 *tmp;
460    register int	  i;
461
462    for (p = arg; p && p->name; p++) {
463	quark = XrmStringToQuark(p->name);
464	if (_XimCheckNestQuarkList(&q_list[idx], n_quark - idx,
465							quark, separator)) {
466	    continue;
467	}
468	if (!(tmp = (XrmQuark *)Xmalloc((sizeof(XrmQuark) * (n_quark + 1))))) {
469	    *quark_list = q_list;
470	    *num_quark = n_quark;
471	    return False;
472	}
473	n_quark++;
474	for (i = 0; i < idx; i++) {
475	    tmp[i] = q_list[i];
476	}
477	tmp[i] = quark;
478	for (i = idx  + 1; i < n_quark; i++) {
479	    tmp[i] = q_list[i - 1];
480	}
481	q_list = tmp;
482    }
483    *quark_list = q_list;
484    *num_quark = n_quark;
485    return True;
486}
487
488Private Bool
489_XimCheckICQuarkList(quark_list, num_quark, quark, idx)
490    XrmQuark		*quark_list;
491    int			 num_quark;
492    XrmQuark		 quark;
493    int			*idx;
494{
495    register int	 i;
496
497    for (i = 0; i < num_quark; i++) {
498	if (quark_list[i] == quark) {
499	    *idx = i;
500	    return True;
501	}
502    }
503    return False;
504}
505
506Private Bool
507_XimSaveICValues(ic, arg)
508    Xic			 ic;
509    XIMArg		*arg;
510{
511    register XIMArg	*p;
512    register int	 n;
513    XrmQuark		*quark_list;
514    XrmQuark		*tmp;
515    XrmQuark		 quark;
516    int			 num_quark;
517    XrmQuark		 pre_quark;
518    XrmQuark		 sts_quark;
519    XrmQuark		 separator;
520    int			 idx;
521
522    pre_quark = XrmStringToQuark(XNPreeditAttributes);
523    sts_quark = XrmStringToQuark(XNStatusAttributes);
524    separator = XrmStringToQuark(XNSeparatorofNestedList);
525
526    if (quark_list = ic->private.proto.saved_icvalues) {
527	num_quark = ic->private.proto.num_saved_icvalues;
528	for (p = arg; p && p->name; p++) {
529	    quark = XrmStringToQuark(p->name);
530	    if ((quark == pre_quark) || (quark == sts_quark)) {
531	        if (!_XimCheckICQuarkList(quark_list, num_quark, quark, &idx)) {
532		    register XIMArg	*pp;
533		    int			 nn;
534		    XrmQuark		*q_list;
535
536		    for (pp = (XIMArg *)p->value, nn = 0;
537						pp && pp->name; pp++, nn++);
538	            if (!(tmp = (XrmQuark *)Xrealloc(quark_list,
539				(sizeof(XrmQuark) * (num_quark + nn + 2))))) {
540		        ic->private.proto.saved_icvalues = quark_list;
541		        ic->private.proto.num_saved_icvalues = num_quark;
542		        return False;
543	            }
544	            quark_list = tmp;
545		    q_list = &quark_list[num_quark];
546	            num_quark += nn + 2;
547		    *q_list++ = quark;
548		    for (pp = (XIMArg *)p->value;
549					pp && pp->name; pp++, quark_list++) {
550			*q_list = XrmStringToQuark(pp->name);
551		    }
552		    *q_list = separator;
553		} else {
554		    if (!_XimCheckNestedQuarkList(&quark_list, idx + 1,
555				&num_quark, (XIMArg *)p->value, separator)) {
556		        ic->private.proto.saved_icvalues = quark_list;
557		        ic->private.proto.num_saved_icvalues = num_quark;
558		        return False;
559		    }
560		}
561	    } else {
562	        if (_XimCheckICQuarkList(quark_list, num_quark, quark, &idx)) {
563		    continue;
564	        }
565	        if (!(tmp = (XrmQuark *)Xrealloc(quark_list,
566				(sizeof(XrmQuark) * (num_quark + 1))))) {
567		    ic->private.proto.saved_icvalues = quark_list;
568		    ic->private.proto.num_saved_icvalues = num_quark;
569		    return False;
570	        }
571	        quark_list = tmp;
572	        quark_list[num_quark] = quark;
573	        num_quark++;
574	    }
575	}
576	ic->private.proto.saved_icvalues = quark_list;
577	ic->private.proto.num_saved_icvalues = num_quark;
578	return True;
579    }
580
581    for (p = arg, n = 0; p && p->name; p++, n++) {
582	if ((!strcmp(p->name, XNPreeditAttributes))
583	 || (!strcmp(p->name, XNStatusAttributes))) {
584	    register XIMArg	*pp;
585	    int			 nn;
586
587	    for (pp = (XIMArg *)p->value, nn = 0; pp && pp->name; pp++, nn++);
588	    n += nn + 1;
589	}
590    }
591
592    if (!(quark_list = (XrmQuark *)Xmalloc(sizeof(XrmQuark) * n))) {
593	return False;
594    }
595
596    ic->private.proto.saved_icvalues = quark_list;
597    ic->private.proto.num_saved_icvalues = n;
598    for (p = arg; p && p->name; p++, quark_list++) {
599	*quark_list = XrmStringToQuark(p->name);
600	if ((*quark_list == pre_quark) || (*quark_list == sts_quark)) {
601	    register XIMArg	*pp;
602
603	    quark_list++;
604	    for (pp = (XIMArg *)p->value; pp && pp->name; pp++, quark_list++) {
605		*quark_list = XrmStringToQuark(pp->name);
606	    }
607	    *quark_list = separator;
608	}
609    }
610    return True;
611}
612
613Private char *
614_XimDelayModeSetICValues(ic, arg)
615    Xic			 ic;
616    XIMArg		*arg;
617{
618    XimDefICValues	 ic_values;
619    char		*name;
620
621    _XimGetCurrentICValues(ic, &ic_values);
622    name = _XimSetICValueData(ic, (XPointer)&ic_values,
623			ic->private.proto.ic_resources,
624			ic->private.proto.ic_num_resources,
625			arg, XIM_SETICVALUES, False);
626    _XimSetCurrentICValues(ic, &ic_values);
627    return name;
628}
629#endif /* XIM_CONNECTABLE */
630
631Private Bool
632_XimSetICValuesCheck(
633    Xim          im,
634    INT16        len,
635    XPointer	 data,
636    XPointer     arg)
637{
638    Xic		 ic = (Xic)arg;
639    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
640    CARD8	 major_opcode = *((CARD8 *)data);
641    CARD8	 minor_opcode = *((CARD8 *)data + 1);
642    XIMID	 imid = buf_s[0];
643    XICID	 icid = buf_s[1];
644
645    if ((major_opcode == XIM_SET_IC_VALUES_REPLY)
646     && (minor_opcode == 0)
647     && (imid == im->private.proto.imid)
648     && (icid == ic->private.proto.icid))
649	return True;
650    if ((major_opcode == XIM_ERROR)
651     && (minor_opcode == 0)
652     && (buf_s[2] & XIM_IMID_VALID)
653     && (imid == im->private.proto.imid)
654     && (buf_s[2] & XIM_ICID_VALID)
655     && (icid == ic->private.proto.icid))
656	return True;
657    return False;
658}
659
660Private char *
661_XimProtoSetICValues(
662    XIC			 xic,
663    XIMArg		*arg)
664{
665    Xic			 ic = (Xic)xic;
666    Xim			 im = (Xim)ic->core.im;
667    XimDefICValues	 ic_values;
668    INT16		 len;
669    CARD16		*buf_s;
670    char		*tmp;
671    CARD32		 tmp_buf32[BUFSIZE/4];
672    char		*tmp_buf = (char *)tmp_buf32;
673    char		*buf;
674    int			 buf_size;
675    char		*data;
676    int			 data_len;
677    int			 ret_len;
678    int			 total;
679    XIMArg		*arg_ret;
680    CARD32		 reply32[BUFSIZE/4];
681    char		*reply = (char *)reply32;
682    XPointer		 preply = NULL;
683    int			 ret_code;
684    BITMASK32		 flag = 0L;
685    char		*name;
686    char		*tmp_name = (arg) ? arg->name : NULL;
687
688#ifndef XIM_CONNECTABLE
689    if (!IS_IC_CONNECTED(ic))
690	return tmp_name;
691#else
692    if (!_XimSaveICValues(ic, arg))
693	return NULL;
694
695    if (!IS_IC_CONNECTED(ic)) {
696	if (IS_CONNECTABLE(im)) {
697	    if (_XimConnectServer(im)) {
698	        if (!_XimReCreateIC(ic)) {
699		    _XimDelayModeSetAttr(im);
700	            return _XimDelayModeSetICValues(ic, arg);
701		}
702	    } else {
703	        return _XimDelayModeSetICValues(ic, arg);
704	    }
705        } else {
706	    return tmp_name;
707        }
708    }
709#endif /* XIM_CONNECTABLE */
710
711    _XimGetCurrentICValues(ic, &ic_values);
712    buf = tmp_buf;
713    buf_size = XIM_HEADER_SIZE
714	+ sizeof(CARD16) + sizeof(CARD16) + sizeof(INT16) + sizeof(CARD16);
715    data_len = BUFSIZE - buf_size;
716    total = 0;
717    arg_ret = arg;
718    for (;;) {
719	data = &buf[buf_size];
720	if ((name = _XimEncodeICATTRIBUTE(ic, ic->private.proto.ic_resources,
721			ic->private.proto.ic_num_resources, arg, &arg_ret,
722			data, data_len, &ret_len, (XPointer)&ic_values,
723			&flag, XIM_SETICVALUES))) {
724	    break;
725	}
726
727	total += ret_len;
728	if (!(arg = arg_ret)) {
729	    break;
730	}
731
732	buf_size += ret_len;
733	if (buf == tmp_buf) {
734	    if (!(tmp = (char *)Xmalloc(buf_size + data_len))) {
735		return tmp_name;
736	    }
737	    memcpy(tmp, buf, buf_size);
738	    buf = tmp;
739	} else {
740	    if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) {
741		Xfree(buf);
742		return tmp_name;
743	    }
744	    buf = tmp;
745	}
746    }
747    _XimSetCurrentICValues(ic, &ic_values);
748
749    if (!total) {
750        return tmp_name;
751    }
752
753    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
754
755#ifdef EXT_MOVE
756    if (_XimExtenMove(im, ic, flag, &buf_s[4], (INT16)total))
757	return name;
758#endif
759
760    buf_s[0] = im->private.proto.imid;
761    buf_s[1] = ic->private.proto.icid;
762    buf_s[2] = (INT16)total;
763    buf_s[3] = 0;
764    len = (INT16)(sizeof(CARD16) + sizeof(CARD16)
765				+ sizeof(INT16) + sizeof(CARD16) + total);
766
767    _XimSetHeader((XPointer)buf, XIM_SET_IC_VALUES, 0, &len);
768    if (!(_XimWrite(im, len, (XPointer)buf))) {
769	if (buf != tmp_buf)
770	    Xfree(buf);
771	return tmp_name;
772    }
773    _XimFlush(im);
774    if (buf != tmp_buf)
775	Xfree(buf);
776    ic->private.proto.waitCallback = True;
777    buf_size = BUFSIZE;
778    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
779					_XimSetICValuesCheck, (XPointer)ic);
780    if (ret_code == XIM_TRUE) {
781	preply = reply;
782    } else if (ret_code == XIM_OVERFLOW) {
783	buf_size = (int)len;
784	preply = (XPointer)Xmalloc(buf_size);
785	ret_code = _XimRead(im, &len, preply, buf_size,
786					_XimSetICValuesCheck, (XPointer)ic);
787	if (ret_code != XIM_TRUE) {
788	    Xfree(preply);
789	    ic->private.proto.waitCallback = False;
790	    return tmp_name;
791	}
792    } else {
793	ic->private.proto.waitCallback = False;
794	return tmp_name;
795    }
796    ic->private.proto.waitCallback = False;
797    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
798    if (*((CARD8 *)preply) == XIM_ERROR) {
799	_XimProcError(im, 0, (XPointer)&buf_s[3]);
800	if (reply != preply)
801	    Xfree(preply);
802	return tmp_name;
803    }
804    if (reply != preply)
805	Xfree(preply);
806
807    return name;
808}
809
810Private Bool
811_XimDestroyICCheck(
812    Xim          im,
813    INT16        len,
814    XPointer	 data,
815    XPointer     arg)
816{
817    Xic		 ic = (Xic)arg;
818    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
819    CARD8	 major_opcode = *((CARD8 *)data);
820    CARD8	 minor_opcode = *((CARD8 *)data + 1);
821    XIMID	 imid = buf_s[0];
822    XICID	 icid = buf_s[1];
823    Bool	 ret = False;
824
825    if ((major_opcode == XIM_DESTROY_IC_REPLY)
826     && (minor_opcode == 0)
827     && (imid == im->private.proto.imid)
828     && (icid == ic->private.proto.icid))
829	ret = True;
830    if ((major_opcode == XIM_ERROR)
831     && (minor_opcode == 0)
832     && (buf_s[2] & XIM_IMID_VALID)
833     && (imid == im->private.proto.imid)
834     && (buf_s[2] & XIM_ICID_VALID)
835     && (icid == ic->private.proto.icid))
836    ret = False;
837    return ret;
838}
839
840Private void
841_XimProtoICFree(
842    Xic		 ic)
843{
844#ifdef XIM_CONNECTABLE
845    Xim		 im = (Xim)ic->core.im;
846#endif
847
848    if (ic->private.proto.preedit_font) {
849	Xfree(ic->private.proto.preedit_font);
850	ic->private.proto.preedit_font = NULL;
851    }
852    if (ic->private.proto.status_font) {
853	Xfree(ic->private.proto.status_font);
854	ic->private.proto.status_font = NULL;
855    }
856    if (ic->private.proto.commit_info) {
857	_XimFreeCommitInfo(ic);
858	ic->private.proto.commit_info = NULL;
859    }
860    if (ic->private.proto.ic_inner_resources) {
861	Xfree(ic->private.proto.ic_inner_resources);
862	ic->private.proto.ic_inner_resources = NULL;
863    }
864
865#ifdef XIM_CONNECTABLE
866    if (IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) {
867	return;
868    }
869#endif /* XIM_CONNECTABLE */
870
871    if (ic->private.proto.saved_icvalues) {
872	Xfree(ic->private.proto.saved_icvalues);
873	ic->private.proto.saved_icvalues = NULL;
874    }
875    if (ic->private.proto.ic_resources) {
876	Xfree(ic->private.proto.ic_resources);
877	ic->private.proto.ic_resources = NULL;
878    }
879    if (ic->core.hotkey) {
880	Xfree(ic->core.hotkey);
881	ic->core.hotkey = NULL;
882    }
883
884    return;
885}
886
887Private void
888_XimProtoDestroyIC(
889    XIC		 xic)
890{
891    Xic		 ic = (Xic)xic;
892    Xim	 	 im = (Xim)ic->core.im;
893    CARD32	 buf32[BUFSIZE/4];
894    CARD8	*buf = (CARD8 *)buf32;
895    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
896    INT16	 len;
897    CARD32	 reply32[BUFSIZE/4];
898    char	*reply = (char *)reply32;
899    XPointer	 preply;
900    int		 buf_size;
901    int		 ret_code;
902
903    if (IS_SERVER_CONNECTED(im)) {
904	buf_s[0] = im->private.proto.imid;		/* imid */
905	buf_s[1] = ic->private.proto.icid;		/* icid */
906
907	len = sizeof(CARD16)			/* sizeof imid */
908	    + sizeof(CARD16);			/* sizeof icid */
909
910	_XimSetHeader((XPointer)buf, XIM_DESTROY_IC, 0, &len);
911	(void)_XimWrite(im, len, (XPointer)buf);
912	_XimFlush(im);
913	buf_size = BUFSIZE;
914	ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
915					_XimDestroyICCheck, (XPointer)ic);
916	if (ret_code == XIM_OVERFLOW) {
917	    buf_size = len;
918	    preply = (XPointer)Xmalloc(buf_size);
919	    (void)_XimRead(im, &len, preply, buf_size,
920					_XimDestroyICCheck, (XPointer)ic);
921	    Xfree(preply);
922	}
923    }
924    UNMARK_IC_CONNECTED(ic);
925    _XimUnregisterFilter(ic);
926    _XimProtoICFree(ic);
927    return;
928}
929
930Private void
931_XimProtoSetFocus(
932    XIC		 xic)
933{
934    Xic		 ic = (Xic)xic;
935    Xim		 im = (Xim)ic->core.im;
936    CARD32	 buf32[BUFSIZE/4];
937    CARD8	*buf = (CARD8 *)buf32;
938    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
939    INT16	 len;
940
941#ifndef XIM_CONNECTABLE
942    if (!IS_IC_CONNECTED(ic))
943	return;
944#else
945    if (!IS_IC_CONNECTED(ic)) {
946	if (IS_CONNECTABLE(im)) {
947	    if (_XimConnectServer(im)) {
948		if (!_XimReCreateIC(ic)) {
949		    _XimDelayModeSetAttr(im);
950		    return;
951		}
952	    } else {
953		return;
954	    }
955	} else {
956	    return;
957	}
958    }
959#endif /* XIM_CONNECTABLE */
960
961    buf_s[0] = im->private.proto.imid;		/* imid */
962    buf_s[1] = ic->private.proto.icid;		/* icid */
963
964    len = sizeof(CARD16)			/* sizeof imid */
965	+ sizeof(CARD16);			/* sizeof icid */
966
967    _XimSetHeader((XPointer)buf, XIM_SET_IC_FOCUS, 0, &len);
968    (void)_XimWrite(im, len, (XPointer)buf);
969    _XimFlush(im);
970
971    MARK_FOCUSED(ic);
972
973    _XimRegisterFilter(ic);
974    return;
975}
976
977Private void
978_XimProtoUnsetFocus(
979    XIC		 xic)
980{
981    Xic		 ic = (Xic)xic;
982    Xim		 im = (Xim)ic->core.im;
983    CARD32	 buf32[BUFSIZE/4];
984    CARD8	*buf = (CARD8 *)buf32;
985    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
986    INT16	 len;
987
988#ifndef XIM_CONNECTABLE
989    if (!IS_IC_CONNECTED(ic))
990	return;
991#else
992    if (!IS_IC_CONNECTED(ic)) {
993	if (IS_CONNECTABLE(im)) {
994	    if (_XimConnectServer(im)) {
995		if (!_XimReCreateIC(ic)) {
996		    _XimDelayModeSetAttr(im);
997		    return;
998		}
999	    } else {
1000		return;
1001	    }
1002	} else {
1003	    return;
1004	}
1005    }
1006#endif /* XIM_CONNECTABLE */
1007
1008    buf_s[0] = im->private.proto.imid;		/* imid */
1009    buf_s[1] = ic->private.proto.icid;		/* icid */
1010
1011    len = sizeof(CARD16)			/* sizeof imid */
1012	+ sizeof(CARD16);			/* sizeof icid */
1013
1014    _XimSetHeader((XPointer)buf, XIM_UNSET_IC_FOCUS, 0, &len);
1015    (void)_XimWrite(im, len, (XPointer)buf);
1016    _XimFlush(im);
1017
1018    UNMARK_FOCUSED(ic);
1019
1020    _XimUnregisterFilter(ic);
1021    return;
1022}
1023
1024Private Bool
1025_XimResetICCheck(
1026    Xim          im,
1027    INT16        len,
1028    XPointer	 data,
1029    XPointer     arg)
1030{
1031    Xic		 ic = (Xic)arg;
1032    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
1033    CARD8	 major_opcode = *((CARD8 *)data);
1034    CARD8	 minor_opcode = *((CARD8 *)data + 1);
1035    XIMID	 imid = buf_s[0];
1036    XICID	 icid = buf_s[1];
1037
1038    if ((major_opcode == XIM_RESET_IC_REPLY)
1039     && (minor_opcode == 0)
1040     && (imid == im->private.proto.imid)
1041     && (icid == ic->private.proto.icid))
1042	return True;
1043    if ((major_opcode == XIM_ERROR)
1044     && (minor_opcode == 0)
1045     && (buf_s[2] & XIM_IMID_VALID)
1046     && (imid == im->private.proto.imid)
1047     && (buf_s[2] & XIM_ICID_VALID)
1048     && (icid == ic->private.proto.icid))
1049	return True;
1050    return False;
1051}
1052
1053Private char *
1054_XimProtoReset(
1055    XIC		 xic,
1056    char *     (*retfunc) (Xim im, Xic ic, XPointer buf) )
1057{
1058    Xic		 ic = (Xic)xic;
1059    Xim	 	 im = (Xim)ic->core.im;
1060    CARD32	 buf32[BUFSIZE/4];
1061    CARD8	*buf = (CARD8 *)buf32;
1062    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
1063    INT16	 len;
1064    CARD32	 reply32[BUFSIZE/4];
1065    char	*reply = (char *)reply32;
1066    XPointer	 preply;
1067    int		 buf_size;
1068    int		 ret_code;
1069    char	*commit;
1070
1071    if (!IS_IC_CONNECTED(ic))
1072	return (char *)NULL;
1073
1074    buf_s[0] = im->private.proto.imid;		/* imid */
1075    buf_s[1] = ic->private.proto.icid;		/* icid */
1076
1077    len = sizeof(CARD16)			/* sizeof imid */
1078	+ sizeof(CARD16);			/* sizeof icid */
1079
1080    _XimSetHeader((XPointer)buf, XIM_RESET_IC, 0, &len);
1081    if (!(_XimWrite(im, len, (XPointer)buf)))
1082	return NULL;
1083    _XimFlush(im);
1084    ic->private.proto.waitCallback = True;
1085    buf_size = BUFSIZE;
1086    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
1087    					_XimResetICCheck, (XPointer)ic);
1088    if (ret_code == XIM_TRUE) {
1089    	preply = reply;
1090    } else if (ret_code == XIM_OVERFLOW) {
1091    	if (len < 0) {
1092    	    preply = reply;
1093    	} else {
1094    	    buf_size = len;
1095    	    preply = (XPointer)Xmalloc(buf_size);
1096    	    ret_code = _XimRead(im, &len, preply, buf_size,
1097    					_XimResetICCheck, (XPointer)ic);
1098    	    if (ret_code != XIM_TRUE) {
1099		Xfree(preply);
1100    		ic->private.proto.waitCallback = False;
1101    		return NULL;
1102    	    }
1103    	}
1104    } else {
1105	ic->private.proto.waitCallback = False;
1106	return NULL;
1107    }
1108    ic->private.proto.waitCallback = False;
1109    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
1110    if (*((CARD8 *)preply) == XIM_ERROR) {
1111	_XimProcError(im, 0, (XPointer)&buf_s[3]);
1112    	if (reply != preply)
1113    	    free(preply);
1114	return NULL;
1115    }
1116
1117    commit = retfunc(im, ic, (XPointer)&buf_s[2]);
1118
1119    if (reply != preply)
1120    	Xfree(preply);
1121    return commit;
1122}
1123
1124Private char *
1125_XimCommitedMbString(
1126    Xim			 im,
1127    Xic			 ic,
1128    XPointer		 buf)
1129{
1130    CARD16		*buf_s = (CARD16 *)buf;
1131    XimCommitInfo	 info;
1132    int			 len;
1133    int			 new_len;
1134    char		*commit;
1135    char		*new_commit = NULL;
1136    char		*str;
1137    Status		 status;
1138
1139    len = 0;
1140    for (info = ic->private.proto.commit_info; info; info = info->next)
1141	len += info->string_len;
1142    len += buf_s[0];
1143    if ( len == 0 )
1144	return( NULL );
1145
1146    if (!(commit = (char *)Xmalloc(len + 1)))
1147	goto Error_On_Reset;
1148
1149    str = commit;
1150    for (info = ic->private.proto.commit_info; info; info = info->next) {
1151	(void)memcpy(str, info->string, info->string_len);
1152	str += info->string_len;
1153    }
1154    (void)memcpy(str, (char *)&buf_s[1], buf_s[0]);
1155    commit[len] = '\0';
1156
1157    new_len = im->methods->ctstombs((XIM)im, commit, len, NULL, 0, &status);
1158    if (status != XLookupNone) {
1159	if (!(new_commit = Xmalloc(new_len + 1))) {
1160	    Xfree(commit);
1161	    goto Error_On_Reset;
1162	}
1163	(void)im->methods->ctstombs((XIM)im, commit, len,
1164						new_commit, new_len, NULL);
1165	new_commit[new_len] = '\0';
1166    }
1167    Xfree(commit);
1168
1169Error_On_Reset:
1170    _XimFreeCommitInfo( ic );
1171    return new_commit;
1172}
1173
1174Private char *
1175_XimProtoMbReset(
1176    XIC		 xic)
1177{
1178    return _XimProtoReset(xic, _XimCommitedMbString);
1179}
1180
1181Private wchar_t *
1182_XimCommitedWcString(
1183    Xim		 im,
1184    Xic		 ic,
1185    XPointer	 buf)
1186{
1187    CARD16		*buf_s = (CARD16 *)buf;
1188    XimCommitInfo	 info;
1189    int			 len;
1190    int			 new_len;
1191    char		*commit;
1192    wchar_t		*new_commit = (wchar_t *)NULL;
1193    char		*str;
1194    Status		 status;
1195
1196    len = 0;
1197    for (info = ic->private.proto.commit_info; info; info = info->next)
1198	len += info->string_len;
1199    len += buf_s[0];
1200    if ( len == 0 )
1201	return( (wchar_t *)NULL );
1202
1203    if (!(commit = (char *)Xmalloc(len + 1)))
1204	goto Error_On_Reset;
1205
1206    str = commit;
1207    for (info = ic->private.proto.commit_info; info; info = info->next) {
1208	(void)memcpy(str, info->string, info->string_len);
1209	str += info->string_len;
1210    }
1211    (void)memcpy(str, (char *)&buf_s[1], buf_s[0]);
1212    commit[len] = '\0';
1213
1214    new_len = im->methods->ctstowcs((XIM)im, commit, len, NULL, 0, &status);
1215    if (status != XLookupNone) {
1216	if (!(new_commit =
1217		     (wchar_t *)Xmalloc(sizeof(wchar_t) * (new_len + 1)))) {
1218	    Xfree(commit);
1219	    goto Error_On_Reset;
1220	}
1221	(void)im->methods->ctstowcs((XIM)im, commit, len,
1222						new_commit, new_len, NULL);
1223	new_commit[new_len] = (wchar_t)'\0';
1224    }
1225    Xfree(commit);
1226
1227Error_On_Reset:
1228    _XimFreeCommitInfo( ic );
1229    return new_commit;
1230}
1231
1232Private wchar_t *
1233_XimProtoWcReset(
1234    XIC		 xic)
1235{
1236    return (wchar_t *) _XimProtoReset(xic,
1237			(char * (*) (Xim, Xic, XPointer)) _XimCommitedWcString);
1238}
1239
1240Private char *
1241_XimCommitedUtf8String(
1242    Xim			 im,
1243    Xic			 ic,
1244    XPointer		 buf)
1245{
1246    CARD16		*buf_s = (CARD16 *)buf;
1247    XimCommitInfo	 info;
1248    int			 len;
1249    int			 new_len;
1250    char		*commit;
1251    char		*new_commit = NULL;
1252    char		*str;
1253    Status		 status;
1254
1255    len = 0;
1256    for (info = ic->private.proto.commit_info; info; info = info->next)
1257	len += info->string_len;
1258    len += buf_s[0];
1259    if ( len == 0 )
1260	return( NULL );
1261
1262    if (!(commit = (char *)Xmalloc(len + 1)))
1263	goto Error_On_Reset;
1264
1265    str = commit;
1266    for (info = ic->private.proto.commit_info; info; info = info->next) {
1267	(void)memcpy(str, info->string, info->string_len);
1268	str += info->string_len;
1269    }
1270    (void)memcpy(str, (char *)&buf_s[1], buf_s[0]);
1271    commit[len] = '\0';
1272
1273    new_len = im->methods->ctstoutf8((XIM)im, commit, len, NULL, 0, &status);
1274    if (status != XLookupNone) {
1275	if (!(new_commit = Xmalloc(new_len + 1))) {
1276	    Xfree(commit);
1277	    goto Error_On_Reset;
1278	}
1279	(void)im->methods->ctstoutf8((XIM)im, commit, len,
1280						new_commit, new_len, NULL);
1281	new_commit[new_len] = '\0';
1282    }
1283    Xfree(commit);
1284
1285Error_On_Reset:
1286    _XimFreeCommitInfo( ic );
1287    return new_commit;
1288}
1289
1290Private char *
1291_XimProtoUtf8Reset(
1292    XIC		 xic)
1293{
1294    return _XimProtoReset(xic, _XimCommitedUtf8String);
1295}
1296
1297Private XICMethodsRec ic_methods = {
1298    _XimProtoDestroyIC,		/* destroy */
1299    _XimProtoSetFocus,		/* set_focus */
1300    _XimProtoUnsetFocus,	/* unset_focus */
1301    _XimProtoSetICValues,	/* set_values */
1302    _XimProtoGetICValues,	/* get_values */
1303    _XimProtoMbReset,		/* mb_reset */
1304    _XimProtoWcReset,		/* wc_reset */
1305    _XimProtoUtf8Reset,		/* utf8_reset */
1306    _XimProtoMbLookupString,	/* mb_lookup_string */
1307    _XimProtoWcLookupString,	/* wc_lookup_string */
1308    _XimProtoUtf8LookupString	/* utf8_lookup_string */
1309};
1310
1311Private Bool
1312_XimGetInputStyle(
1313    XIMArg		*arg,
1314    XIMStyle		*input_style)
1315{
1316    register XIMArg	*p;
1317
1318    for (p = arg; p && p->name; p++) {
1319	if (!(strcmp(p->name, XNInputStyle))) {
1320	    *input_style = (XIMStyle)p->value;
1321	    return True;
1322	}
1323    }
1324    return False;
1325}
1326
1327#ifdef XIM_CONNECTABLE
1328Private Bool
1329_XimDelayModeCreateIC(
1330    Xic			 ic,
1331    XIMArg		*values,
1332    XIMResourceList	 res,
1333    unsigned int	 num)
1334{
1335    Xim			 im = (Xim)ic->core.im;
1336    XimDefICValues	 ic_values;
1337    int			 len;
1338    XIMStyle		 input_style;
1339
1340    bzero((char *)&ic_values, sizeof(XimDefICValues));
1341    _XimGetCurrentICValues(ic, &ic_values);
1342    if (!(_XimGetInputStyle(values, &input_style)))
1343	return False;
1344
1345    _XimSetICMode(res, num, input_style);
1346
1347    if (_XimSetICValueData(ic, (XPointer)&ic_values, res, num,
1348					values, XIM_CREATEIC, False)) {
1349	return False;
1350    }
1351    _XimSetCurrentICValues(ic, &ic_values);
1352    if (!_XimSetICDefaults(ic, (XPointer)&ic_values,
1353					XIM_SETICDEFAULTS, res, num)) {
1354	return False;
1355    }
1356    ic_values.filter_events = KeyPressMask;
1357    _XimSetCurrentICValues(ic, &ic_values);
1358    _XimRegisterFilter(ic);
1359
1360    return True;
1361}
1362
1363Public Bool
1364_XimReconnectModeCreateIC(ic)
1365    Xic			 ic;
1366{
1367    Xim			 im = (Xim)ic->core.im;
1368    int			 len;
1369    XIMStyle		 input_style = ic->core.input_style;
1370    XIMResourceList	 res;
1371    unsigned int	 num;
1372
1373    num = im->core.ic_num_resources;
1374    len = sizeof(XIMResource) * num;
1375    if (!(res = (XIMResourceList)Xmalloc(len)))
1376	return False;
1377    (void)memcpy((char *)res, (char *)im->core.ic_resources, len);
1378    ic->private.proto.ic_resources     = res;
1379    ic->private.proto.ic_num_resources = num;
1380
1381    _XimSetICMode(res, num, input_style);
1382
1383    ic->core.filter_events = KeyPressMask;
1384
1385    return True;
1386}
1387#endif /* XIM_CONNECTABLE */
1388
1389Public XIC
1390_XimProtoCreateIC(
1391    XIM			 xim,
1392    XIMArg		*arg)
1393{
1394    Xim			 im = (Xim)xim;
1395    Xic			 ic;
1396    XimDefICValues	 ic_values;
1397    XIMResourceList	 res;
1398    unsigned int         num;
1399    XIMStyle		 input_style;
1400    INT16		 len;
1401    CARD16		*buf_s;
1402    char		*tmp;
1403    CARD32		 tmp_buf32[BUFSIZE/4];
1404    char		*tmp_buf = (char *)tmp_buf32;
1405    char		*buf;
1406    int			 buf_size;
1407    char		*data;
1408    int			 data_len;
1409    int			 ret_len;
1410    int			 total;
1411    XIMArg		*arg_ret;
1412    CARD32		 reply32[BUFSIZE/4];
1413    char		*reply = (char *)reply32;
1414    XPointer		 preply;
1415    int			 ret_code;
1416
1417#ifdef XIM_CONNECTABLE
1418    if (!IS_SERVER_CONNECTED(im) && !IS_CONNECTABLE(im))
1419	return (XIC)NULL;
1420#else
1421    if (!IS_SERVER_CONNECTED(im))
1422	return (XIC)NULL;
1423#endif /* XIM_CONNECTABLE */
1424
1425    if (!(_XimGetInputStyle(arg, &input_style)))
1426	return (XIC)NULL;
1427
1428    if ((ic = Xcalloc(1, sizeof(XicRec))) == (Xic)NULL)
1429	return (XIC)NULL;
1430
1431    ic->methods = &ic_methods;
1432    ic->core.im = (XIM)im;
1433    ic->core.input_style = input_style;
1434
1435    num = im->core.ic_num_resources;
1436    len = sizeof(XIMResource) * num;
1437    if (!(res = (XIMResourceList)Xmalloc(len)))
1438	goto ErrorOnCreatingIC;
1439    (void)memcpy((char *)res, (char *)im->core.ic_resources, len);
1440    ic->private.proto.ic_resources     = res;
1441    ic->private.proto.ic_num_resources = num;
1442
1443#ifdef XIM_CONNECTABLE
1444    if (!_XimSaveICValues(ic, arg))
1445	return False;
1446
1447    if (!IS_SERVER_CONNECTED(im)) {
1448	if (!_XimConnectServer(im)) {
1449	    if (_XimDelayModeCreateIC(ic, arg, res, num)) {
1450		return (XIC)ic;
1451	    }
1452	    goto ErrorOnCreatingIC;
1453	}
1454    }
1455#endif /* XIM_CONNECTABLE */
1456
1457    ic->core.filter_events = im->private.proto.forward_event_mask;
1458    ic->private.proto.forward_event_mask =
1459				im->private.proto.forward_event_mask;
1460    ic->private.proto.synchronous_event_mask =
1461				im->private.proto.synchronous_event_mask;
1462
1463    num = im->private.proto.ic_num_inner_resources;
1464    len = sizeof(XIMResource) * num;
1465    if (!(res = (XIMResourceList)Xmalloc(len)))
1466	goto ErrorOnCreatingIC;
1467    (void)memcpy((char *)res,
1468			 (char *)im->private.proto.ic_inner_resources, len);
1469    ic->private.proto.ic_inner_resources     = res;
1470    ic->private.proto.ic_num_inner_resources = num;
1471
1472    _XimSetICMode(ic->private.proto.ic_resources,
1473			ic->private.proto.ic_num_resources, input_style);
1474
1475    _XimSetICMode(ic->private.proto.ic_inner_resources,
1476			ic->private.proto.ic_num_inner_resources, input_style);
1477
1478    _XimGetCurrentICValues(ic, &ic_values);
1479    buf = tmp_buf;
1480    buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16);
1481    data_len = BUFSIZE - buf_size;
1482    total = 0;
1483    arg_ret = arg;
1484    for (;;) {
1485	data = &buf[buf_size];
1486	if (_XimEncodeICATTRIBUTE(ic, ic->private.proto.ic_resources,
1487		ic->private.proto.ic_num_resources, arg, &arg_ret, data,
1488		data_len, &ret_len, (XPointer)&ic_values, 0, XIM_CREATEIC)) {
1489	    goto ErrorOnCreatingIC;
1490	}
1491
1492	total += ret_len;
1493	if (!(arg = arg_ret)) {
1494	    break;
1495	}
1496
1497	buf_size += ret_len;
1498	if (buf == tmp_buf) {
1499	    if (!(tmp = (char *)Xmalloc(buf_size + data_len))) {
1500	        goto ErrorOnCreatingIC;
1501	    }
1502	    memcpy(tmp, buf, buf_size);
1503	    buf = tmp;
1504	} else {
1505	    if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) {
1506		Xfree(buf);
1507	        goto ErrorOnCreatingIC;
1508	    }
1509	    buf = tmp;
1510	}
1511    }
1512    _XimSetCurrentICValues(ic, &ic_values);
1513
1514    if (!(_XimCheckCreateICValues(ic->private.proto.ic_resources,
1515					ic->private.proto.ic_num_resources)))
1516	goto ErrorOnCreatingIC;
1517
1518    _XimRegisterFilter(ic);
1519
1520    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
1521    buf_s[0] = im->private.proto.imid;
1522    buf_s[1] = (INT16)total;
1523
1524    len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total);
1525    _XimSetHeader((XPointer)buf, XIM_CREATE_IC, 0, &len);
1526    if (!(_XimWrite(im, len, (XPointer)buf))) {
1527	if (buf != tmp_buf)
1528	    Xfree(buf);
1529	goto ErrorOnCreatingIC;
1530    }
1531    _XimFlush(im);
1532    if (buf != tmp_buf)
1533	Xfree(buf);
1534    ic->private.proto.waitCallback = True;
1535    buf_size = BUFSIZE;
1536    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
1537						 _XimCreateICCheck, 0);
1538    if (ret_code == XIM_TRUE) {
1539	preply = reply;
1540    } else if (ret_code == XIM_OVERFLOW) {
1541	if (len <= 0) {
1542	    preply = reply;
1543	} else {
1544	    buf_size = (int)len;
1545	    preply = (XPointer)Xmalloc(buf_size);
1546	    ret_code = _XimRead(im, &len, preply, buf_size,
1547						 _XimCreateICCheck, 0);
1548	    if (ret_code != XIM_TRUE) {
1549		Xfree(preply);
1550		ic->private.proto.waitCallback = False;
1551		goto ErrorOnCreatingIC;
1552	    }
1553	}
1554    } else {
1555	ic->private.proto.waitCallback = False;
1556	goto ErrorOnCreatingIC;
1557    }
1558    ic->private.proto.waitCallback = False;
1559    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
1560    if (*((CARD8 *)preply) == XIM_ERROR) {
1561	_XimProcError(im, 0, (XPointer)&buf_s[3]);
1562	if (reply != preply)
1563	    Xfree(preply);
1564	goto ErrorOnCreatingIC;
1565    }
1566
1567    ic->private.proto.icid = buf_s[1];		/* icid */
1568    if (reply != preply)
1569	Xfree(preply);
1570    MARK_IC_CONNECTED(ic);
1571    return (XIC)ic;
1572
1573ErrorOnCreatingIC:
1574    _XimUnregisterFilter(ic);
1575    if (ic->private.proto.ic_resources)
1576	Xfree(ic->private.proto.ic_resources);
1577    if (ic->private.proto.ic_inner_resources)
1578	Xfree(ic->private.proto.ic_inner_resources);
1579    Xfree(ic);
1580    return (XIC)NULL;
1581}
1582