imDefIc.c revision eb411b4b
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
59static 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
84Bool
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
247static 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
262static 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
291static 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
427static 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
447static 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
488static 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
506static 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
613static 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
631static 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
660static 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
810static 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
840static 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
887static 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
930static 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    _XimRegisterFilter(ic);
972    return;
973}
974
975static void
976_XimProtoUnsetFocus(
977    XIC		 xic)
978{
979    Xic		 ic = (Xic)xic;
980    Xim		 im = (Xim)ic->core.im;
981    CARD32	 buf32[BUFSIZE/4];
982    CARD8	*buf = (CARD8 *)buf32;
983    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
984    INT16	 len;
985
986#ifndef XIM_CONNECTABLE
987    if (!IS_IC_CONNECTED(ic))
988	return;
989#else
990    if (!IS_IC_CONNECTED(ic)) {
991	if (IS_CONNECTABLE(im)) {
992	    if (_XimConnectServer(im)) {
993		if (!_XimReCreateIC(ic)) {
994		    _XimDelayModeSetAttr(im);
995		    return;
996		}
997	    } else {
998		return;
999	    }
1000	} else {
1001	    return;
1002	}
1003    }
1004#endif /* XIM_CONNECTABLE */
1005
1006    buf_s[0] = im->private.proto.imid;		/* imid */
1007    buf_s[1] = ic->private.proto.icid;		/* icid */
1008
1009    len = sizeof(CARD16)			/* sizeof imid */
1010	+ sizeof(CARD16);			/* sizeof icid */
1011
1012    _XimSetHeader((XPointer)buf, XIM_UNSET_IC_FOCUS, 0, &len);
1013    (void)_XimWrite(im, len, (XPointer)buf);
1014    _XimFlush(im);
1015
1016    _XimUnregisterFilter(ic);
1017    return;
1018}
1019
1020static Bool
1021_XimResetICCheck(
1022    Xim          im,
1023    INT16        len,
1024    XPointer	 data,
1025    XPointer     arg)
1026{
1027    Xic		 ic = (Xic)arg;
1028    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
1029    CARD8	 major_opcode = *((CARD8 *)data);
1030    CARD8	 minor_opcode = *((CARD8 *)data + 1);
1031    XIMID	 imid = buf_s[0];
1032    XICID	 icid = buf_s[1];
1033
1034    if ((major_opcode == XIM_RESET_IC_REPLY)
1035     && (minor_opcode == 0)
1036     && (imid == im->private.proto.imid)
1037     && (icid == ic->private.proto.icid))
1038	return True;
1039    if ((major_opcode == XIM_ERROR)
1040     && (minor_opcode == 0)
1041     && (buf_s[2] & XIM_IMID_VALID)
1042     && (imid == im->private.proto.imid)
1043     && (buf_s[2] & XIM_ICID_VALID)
1044     && (icid == ic->private.proto.icid))
1045	return True;
1046    return False;
1047}
1048
1049static char *
1050_XimProtoReset(
1051    XIC		 xic,
1052    char *     (*retfunc) (Xim im, Xic ic, XPointer buf) )
1053{
1054    Xic		 ic = (Xic)xic;
1055    Xim	 	 im = (Xim)ic->core.im;
1056    CARD32	 buf32[BUFSIZE/4];
1057    CARD8	*buf = (CARD8 *)buf32;
1058    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
1059    INT16	 len;
1060    CARD32	 reply32[BUFSIZE/4];
1061    char	*reply = (char *)reply32;
1062    XPointer	 preply;
1063    int		 buf_size;
1064    int		 ret_code;
1065    char	*commit;
1066
1067    if (!IS_IC_CONNECTED(ic))
1068	return (char *)NULL;
1069
1070    buf_s[0] = im->private.proto.imid;		/* imid */
1071    buf_s[1] = ic->private.proto.icid;		/* icid */
1072
1073    len = sizeof(CARD16)			/* sizeof imid */
1074	+ sizeof(CARD16);			/* sizeof icid */
1075
1076    _XimSetHeader((XPointer)buf, XIM_RESET_IC, 0, &len);
1077    if (!(_XimWrite(im, len, (XPointer)buf)))
1078	return NULL;
1079    _XimFlush(im);
1080    ic->private.proto.waitCallback = True;
1081    buf_size = BUFSIZE;
1082    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
1083    					_XimResetICCheck, (XPointer)ic);
1084    if (ret_code == XIM_TRUE) {
1085    	preply = reply;
1086    } else if (ret_code == XIM_OVERFLOW) {
1087    	if (len < 0) {
1088    	    preply = reply;
1089    	} else {
1090    	    buf_size = len;
1091    	    preply = (XPointer)Xmalloc(buf_size);
1092    	    ret_code = _XimRead(im, &len, preply, buf_size,
1093    					_XimResetICCheck, (XPointer)ic);
1094    	    if (ret_code != XIM_TRUE) {
1095		Xfree(preply);
1096    		ic->private.proto.waitCallback = False;
1097    		return NULL;
1098    	    }
1099    	}
1100    } else {
1101	ic->private.proto.waitCallback = False;
1102	return NULL;
1103    }
1104    ic->private.proto.waitCallback = False;
1105    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
1106    if (*((CARD8 *)preply) == XIM_ERROR) {
1107	_XimProcError(im, 0, (XPointer)&buf_s[3]);
1108    	if (reply != preply)
1109    	    free(preply);
1110	return NULL;
1111    }
1112
1113    commit = retfunc(im, ic, (XPointer)&buf_s[2]);
1114
1115    if (reply != preply)
1116    	Xfree(preply);
1117    return commit;
1118}
1119
1120static char *
1121_XimCommitedMbString(
1122    Xim			 im,
1123    Xic			 ic,
1124    XPointer		 buf)
1125{
1126    CARD16		*buf_s = (CARD16 *)buf;
1127    XimCommitInfo	 info;
1128    int			 len;
1129    int			 new_len;
1130    char		*commit;
1131    char		*new_commit = NULL;
1132    char		*str;
1133    Status		 status;
1134
1135    len = 0;
1136    for (info = ic->private.proto.commit_info; info; info = info->next)
1137	len += info->string_len;
1138    len += buf_s[0];
1139    if ( len == 0 )
1140	return( NULL );
1141
1142    if (!(commit = (char *)Xmalloc(len + 1)))
1143	goto Error_On_Reset;
1144
1145    str = commit;
1146    for (info = ic->private.proto.commit_info; info; info = info->next) {
1147	(void)memcpy(str, info->string, info->string_len);
1148	str += info->string_len;
1149    }
1150    (void)memcpy(str, (char *)&buf_s[1], buf_s[0]);
1151    commit[len] = '\0';
1152
1153    new_len = im->methods->ctstombs((XIM)im, commit, len, NULL, 0, &status);
1154    if (status != XLookupNone) {
1155	if (!(new_commit = Xmalloc(new_len + 1))) {
1156	    Xfree(commit);
1157	    goto Error_On_Reset;
1158	}
1159	(void)im->methods->ctstombs((XIM)im, commit, len,
1160						new_commit, new_len, NULL);
1161	new_commit[new_len] = '\0';
1162    }
1163    Xfree(commit);
1164
1165Error_On_Reset:
1166    _XimFreeCommitInfo( ic );
1167    return new_commit;
1168}
1169
1170static char *
1171_XimProtoMbReset(
1172    XIC		 xic)
1173{
1174    return _XimProtoReset(xic, _XimCommitedMbString);
1175}
1176
1177static wchar_t *
1178_XimCommitedWcString(
1179    Xim		 im,
1180    Xic		 ic,
1181    XPointer	 buf)
1182{
1183    CARD16		*buf_s = (CARD16 *)buf;
1184    XimCommitInfo	 info;
1185    int			 len;
1186    int			 new_len;
1187    char		*commit;
1188    wchar_t		*new_commit = (wchar_t *)NULL;
1189    char		*str;
1190    Status		 status;
1191
1192    len = 0;
1193    for (info = ic->private.proto.commit_info; info; info = info->next)
1194	len += info->string_len;
1195    len += buf_s[0];
1196    if ( len == 0 )
1197	return( (wchar_t *)NULL );
1198
1199    if (!(commit = (char *)Xmalloc(len + 1)))
1200	goto Error_On_Reset;
1201
1202    str = commit;
1203    for (info = ic->private.proto.commit_info; info; info = info->next) {
1204	(void)memcpy(str, info->string, info->string_len);
1205	str += info->string_len;
1206    }
1207    (void)memcpy(str, (char *)&buf_s[1], buf_s[0]);
1208    commit[len] = '\0';
1209
1210    new_len = im->methods->ctstowcs((XIM)im, commit, len, NULL, 0, &status);
1211    if (status != XLookupNone) {
1212	if (!(new_commit =
1213		     (wchar_t *)Xmalloc(sizeof(wchar_t) * (new_len + 1)))) {
1214	    Xfree(commit);
1215	    goto Error_On_Reset;
1216	}
1217	(void)im->methods->ctstowcs((XIM)im, commit, len,
1218						new_commit, new_len, NULL);
1219	new_commit[new_len] = (wchar_t)'\0';
1220    }
1221    Xfree(commit);
1222
1223Error_On_Reset:
1224    _XimFreeCommitInfo( ic );
1225    return new_commit;
1226}
1227
1228static wchar_t *
1229_XimProtoWcReset(
1230    XIC		 xic)
1231{
1232    return (wchar_t *) _XimProtoReset(xic,
1233			(char * (*) (Xim, Xic, XPointer)) _XimCommitedWcString);
1234}
1235
1236static char *
1237_XimCommitedUtf8String(
1238    Xim			 im,
1239    Xic			 ic,
1240    XPointer		 buf)
1241{
1242    CARD16		*buf_s = (CARD16 *)buf;
1243    XimCommitInfo	 info;
1244    int			 len;
1245    int			 new_len;
1246    char		*commit;
1247    char		*new_commit = NULL;
1248    char		*str;
1249    Status		 status;
1250
1251    len = 0;
1252    for (info = ic->private.proto.commit_info; info; info = info->next)
1253	len += info->string_len;
1254    len += buf_s[0];
1255    if ( len == 0 )
1256	return( NULL );
1257
1258    if (!(commit = (char *)Xmalloc(len + 1)))
1259	goto Error_On_Reset;
1260
1261    str = commit;
1262    for (info = ic->private.proto.commit_info; info; info = info->next) {
1263	(void)memcpy(str, info->string, info->string_len);
1264	str += info->string_len;
1265    }
1266    (void)memcpy(str, (char *)&buf_s[1], buf_s[0]);
1267    commit[len] = '\0';
1268
1269    new_len = im->methods->ctstoutf8((XIM)im, commit, len, NULL, 0, &status);
1270    if (status != XLookupNone) {
1271	if (!(new_commit = Xmalloc(new_len + 1))) {
1272	    Xfree(commit);
1273	    goto Error_On_Reset;
1274	}
1275	(void)im->methods->ctstoutf8((XIM)im, commit, len,
1276						new_commit, new_len, NULL);
1277	new_commit[new_len] = '\0';
1278    }
1279    Xfree(commit);
1280
1281Error_On_Reset:
1282    _XimFreeCommitInfo( ic );
1283    return new_commit;
1284}
1285
1286static char *
1287_XimProtoUtf8Reset(
1288    XIC		 xic)
1289{
1290    return _XimProtoReset(xic, _XimCommitedUtf8String);
1291}
1292
1293static XICMethodsRec ic_methods = {
1294    _XimProtoDestroyIC,		/* destroy */
1295    _XimProtoSetFocus,		/* set_focus */
1296    _XimProtoUnsetFocus,	/* unset_focus */
1297    _XimProtoSetICValues,	/* set_values */
1298    _XimProtoGetICValues,	/* get_values */
1299    _XimProtoMbReset,		/* mb_reset */
1300    _XimProtoWcReset,		/* wc_reset */
1301    _XimProtoUtf8Reset,		/* utf8_reset */
1302    _XimProtoMbLookupString,	/* mb_lookup_string */
1303    _XimProtoWcLookupString,	/* wc_lookup_string */
1304    _XimProtoUtf8LookupString	/* utf8_lookup_string */
1305};
1306
1307static Bool
1308_XimGetInputStyle(
1309    XIMArg		*arg,
1310    XIMStyle		*input_style)
1311{
1312    register XIMArg	*p;
1313
1314    for (p = arg; p && p->name; p++) {
1315	if (!(strcmp(p->name, XNInputStyle))) {
1316	    *input_style = (XIMStyle)p->value;
1317	    return True;
1318	}
1319    }
1320    return False;
1321}
1322
1323#ifdef XIM_CONNECTABLE
1324static Bool
1325_XimDelayModeCreateIC(
1326    Xic			 ic,
1327    XIMArg		*values,
1328    XIMResourceList	 res,
1329    unsigned int	 num)
1330{
1331    Xim			 im = (Xim)ic->core.im;
1332    XimDefICValues	 ic_values;
1333    int			 len;
1334    XIMStyle		 input_style;
1335
1336    bzero((char *)&ic_values, sizeof(XimDefICValues));
1337    _XimGetCurrentICValues(ic, &ic_values);
1338    if (!(_XimGetInputStyle(values, &input_style)))
1339	return False;
1340
1341    _XimSetICMode(res, num, input_style);
1342
1343    if (_XimSetICValueData(ic, (XPointer)&ic_values, res, num,
1344					values, XIM_CREATEIC, False)) {
1345	return False;
1346    }
1347    _XimSetCurrentICValues(ic, &ic_values);
1348    if (!_XimSetICDefaults(ic, (XPointer)&ic_values,
1349					XIM_SETICDEFAULTS, res, num)) {
1350	return False;
1351    }
1352    ic_values.filter_events = KeyPressMask;
1353    _XimSetCurrentICValues(ic, &ic_values);
1354    _XimRegisterFilter(ic);
1355
1356    return True;
1357}
1358
1359Bool
1360_XimReconnectModeCreateIC(ic)
1361    Xic			 ic;
1362{
1363    Xim			 im = (Xim)ic->core.im;
1364    int			 len;
1365    XIMStyle		 input_style = ic->core.input_style;
1366    XIMResourceList	 res;
1367    unsigned int	 num;
1368
1369    num = im->core.ic_num_resources;
1370    len = sizeof(XIMResource) * num;
1371    if (!(res = (XIMResourceList)Xmalloc(len)))
1372	return False;
1373    (void)memcpy((char *)res, (char *)im->core.ic_resources, len);
1374    ic->private.proto.ic_resources     = res;
1375    ic->private.proto.ic_num_resources = num;
1376
1377    _XimSetICMode(res, num, input_style);
1378
1379    ic->core.filter_events = KeyPressMask;
1380
1381    return True;
1382}
1383#endif /* XIM_CONNECTABLE */
1384
1385XIC
1386_XimProtoCreateIC(
1387    XIM			 xim,
1388    XIMArg		*arg)
1389{
1390    Xim			 im = (Xim)xim;
1391    Xic			 ic;
1392    XimDefICValues	 ic_values;
1393    XIMResourceList	 res;
1394    unsigned int         num;
1395    XIMStyle		 input_style;
1396    INT16		 len;
1397    CARD16		*buf_s;
1398    char		*tmp;
1399    CARD32		 tmp_buf32[BUFSIZE/4];
1400    char		*tmp_buf = (char *)tmp_buf32;
1401    char		*buf;
1402    int			 buf_size;
1403    char		*data;
1404    int			 data_len;
1405    int			 ret_len;
1406    int			 total;
1407    XIMArg		*arg_ret;
1408    CARD32		 reply32[BUFSIZE/4];
1409    char		*reply = (char *)reply32;
1410    XPointer		 preply;
1411    int			 ret_code;
1412
1413#ifdef XIM_CONNECTABLE
1414    if (!IS_SERVER_CONNECTED(im) && !IS_CONNECTABLE(im))
1415	return (XIC)NULL;
1416#else
1417    if (!IS_SERVER_CONNECTED(im))
1418	return (XIC)NULL;
1419#endif /* XIM_CONNECTABLE */
1420
1421    if (!(_XimGetInputStyle(arg, &input_style)))
1422	return (XIC)NULL;
1423
1424    if ((ic = Xcalloc(1, sizeof(XicRec))) == (Xic)NULL)
1425	return (XIC)NULL;
1426
1427    ic->methods = &ic_methods;
1428    ic->core.im = (XIM)im;
1429    ic->core.input_style = input_style;
1430
1431    num = im->core.ic_num_resources;
1432    len = sizeof(XIMResource) * num;
1433    if (!(res = (XIMResourceList)Xmalloc(len)))
1434	goto ErrorOnCreatingIC;
1435    (void)memcpy((char *)res, (char *)im->core.ic_resources, len);
1436    ic->private.proto.ic_resources     = res;
1437    ic->private.proto.ic_num_resources = num;
1438
1439#ifdef XIM_CONNECTABLE
1440    if (!_XimSaveICValues(ic, arg))
1441	return False;
1442
1443    if (!IS_SERVER_CONNECTED(im)) {
1444	if (!_XimConnectServer(im)) {
1445	    if (_XimDelayModeCreateIC(ic, arg, res, num)) {
1446		return (XIC)ic;
1447	    }
1448	    goto ErrorOnCreatingIC;
1449	}
1450    }
1451#endif /* XIM_CONNECTABLE */
1452
1453    ic->core.filter_events = im->private.proto.forward_event_mask;
1454    ic->private.proto.forward_event_mask =
1455				im->private.proto.forward_event_mask;
1456    ic->private.proto.synchronous_event_mask =
1457				im->private.proto.synchronous_event_mask;
1458
1459    num = im->private.proto.ic_num_inner_resources;
1460    len = sizeof(XIMResource) * num;
1461    if (!(res = (XIMResourceList)Xmalloc(len)))
1462	goto ErrorOnCreatingIC;
1463    (void)memcpy((char *)res,
1464			 (char *)im->private.proto.ic_inner_resources, len);
1465    ic->private.proto.ic_inner_resources     = res;
1466    ic->private.proto.ic_num_inner_resources = num;
1467
1468    _XimSetICMode(ic->private.proto.ic_resources,
1469			ic->private.proto.ic_num_resources, input_style);
1470
1471    _XimSetICMode(ic->private.proto.ic_inner_resources,
1472			ic->private.proto.ic_num_inner_resources, input_style);
1473
1474    _XimGetCurrentICValues(ic, &ic_values);
1475    buf = tmp_buf;
1476    buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16);
1477    data_len = BUFSIZE - buf_size;
1478    total = 0;
1479    arg_ret = arg;
1480    for (;;) {
1481	data = &buf[buf_size];
1482	if (_XimEncodeICATTRIBUTE(ic, ic->private.proto.ic_resources,
1483		ic->private.proto.ic_num_resources, arg, &arg_ret, data,
1484		data_len, &ret_len, (XPointer)&ic_values, 0, XIM_CREATEIC)) {
1485	    goto ErrorOnCreatingIC;
1486	}
1487
1488	total += ret_len;
1489	if (!(arg = arg_ret)) {
1490	    break;
1491	}
1492
1493	buf_size += ret_len;
1494	if (buf == tmp_buf) {
1495	    if (!(tmp = (char *)Xmalloc(buf_size + data_len))) {
1496	        goto ErrorOnCreatingIC;
1497	    }
1498	    memcpy(tmp, buf, buf_size);
1499	    buf = tmp;
1500	} else {
1501	    if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) {
1502		Xfree(buf);
1503	        goto ErrorOnCreatingIC;
1504	    }
1505	    buf = tmp;
1506	}
1507    }
1508    _XimSetCurrentICValues(ic, &ic_values);
1509
1510    if (!(_XimCheckCreateICValues(ic->private.proto.ic_resources,
1511					ic->private.proto.ic_num_resources)))
1512	goto ErrorOnCreatingIC;
1513
1514    _XimRegisterFilter(ic);
1515
1516    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
1517    buf_s[0] = im->private.proto.imid;
1518    buf_s[1] = (INT16)total;
1519
1520    len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total);
1521    _XimSetHeader((XPointer)buf, XIM_CREATE_IC, 0, &len);
1522    if (!(_XimWrite(im, len, (XPointer)buf))) {
1523	if (buf != tmp_buf)
1524	    Xfree(buf);
1525	goto ErrorOnCreatingIC;
1526    }
1527    _XimFlush(im);
1528    if (buf != tmp_buf)
1529	Xfree(buf);
1530    ic->private.proto.waitCallback = True;
1531    buf_size = BUFSIZE;
1532    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
1533						 _XimCreateICCheck, 0);
1534    if (ret_code == XIM_TRUE) {
1535	preply = reply;
1536    } else if (ret_code == XIM_OVERFLOW) {
1537	if (len <= 0) {
1538	    preply = reply;
1539	} else {
1540	    buf_size = (int)len;
1541	    preply = (XPointer)Xmalloc(buf_size);
1542	    ret_code = _XimRead(im, &len, preply, buf_size,
1543						 _XimCreateICCheck, 0);
1544	    if (ret_code != XIM_TRUE) {
1545		Xfree(preply);
1546		ic->private.proto.waitCallback = False;
1547		goto ErrorOnCreatingIC;
1548	    }
1549	}
1550    } else {
1551	ic->private.proto.waitCallback = False;
1552	goto ErrorOnCreatingIC;
1553    }
1554    ic->private.proto.waitCallback = False;
1555    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
1556    if (*((CARD8 *)preply) == XIM_ERROR) {
1557	_XimProcError(im, 0, (XPointer)&buf_s[3]);
1558	if (reply != preply)
1559	    Xfree(preply);
1560	goto ErrorOnCreatingIC;
1561    }
1562
1563    ic->private.proto.icid = buf_s[1];		/* icid */
1564    if (reply != preply)
1565	Xfree(preply);
1566    MARK_IC_CONNECTED(ic);
1567    return (XIC)ic;
1568
1569ErrorOnCreatingIC:
1570    _XimUnregisterFilter(ic);
1571    if (ic->private.proto.ic_resources)
1572	Xfree(ic->private.proto.ic_resources);
1573    if (ic->private.proto.ic_inner_resources)
1574	Xfree(ic->private.proto.ic_inner_resources);
1575    Xfree(ic);
1576    return (XIC)NULL;
1577}
1578