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