imRmAttr.c revision 0f8248bf
1/******************************************************************
2
3           Copyright 1992, 1993, 1994 by FUJITSU LIMITED
4
5Permission to use, copy, modify, distribute, and sell this software
6and its documentation for any purpose is hereby granted without fee,
7provided that the above copyright notice appear in all copies and
8that both that copyright notice and this permission notice appear
9in supporting documentation, and that the name of FUJITSU LIMITED
10not be used in advertising or publicity pertaining to distribution
11of the software without specific, written prior permission.
12FUJITSU LIMITED makes no representations about the suitability of
13this software for any purpose.
14It is provided "as is" without express or implied warranty.
15
16FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22PERFORMANCE OF THIS SOFTWARE.
23
24  Author: Takashi Fujiwara     FUJITSU LIMITED
25                               fujiwara@a80.tech.yk.fujitsu.co.jp
26
27******************************************************************/
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include "Xlibint.h"
33#include "Xlcint.h"
34#include "Ximint.h"
35
36
37static XIMResourceList
38_XimGetNestedListSeparator(
39    XIMResourceList	 res_list,		/* LISTofIMATTR or IMATTR */
40    unsigned int	 res_num)
41{
42    return  _XimGetResourceListRec(res_list, res_num, XNSeparatorofNestedList);
43}
44
45static Bool
46_XimCheckInnerIMAttributes(
47    Xim			 im,
48    XIMArg		*arg,
49    unsigned long	 mode)
50{
51    XIMResourceList	 res;
52    int			 check;
53
54    if (!(res = _XimGetResourceListRec(im->private.proto.im_inner_resources,
55			im->private.proto.im_num_inner_resources, arg->name)))
56	return False;
57
58    check = _XimCheckIMMode(res, mode);
59    if(check == XIM_CHECK_INVALID)
60	return True;
61    else if(check == XIM_CHECK_ERROR)
62	return False;
63
64    return True;
65}
66
67char *
68_XimMakeIMAttrIDList(
69    Xim			 im,
70    XIMResourceList	 res_list,
71    unsigned int	 res_num,
72    XIMArg		*arg,
73    CARD16		*buf,
74    INT16		*len,
75    unsigned long	 mode)
76{
77    register XIMArg	*p;
78    XIMResourceList	 res;
79    int			 check;
80
81    *len = 0;
82    if (!arg)
83	return (char *)NULL;
84
85    for (p = arg; p->name; p++) {
86	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
87	    if (_XimCheckInnerIMAttributes(im, p, mode))
88		continue;
89	    return p->name;
90	}
91
92	check = _XimCheckIMMode(res, mode);
93	if (check == XIM_CHECK_INVALID)
94	    continue;
95	else if (check == XIM_CHECK_ERROR)
96	    return p->name;
97
98	*buf = res->id;
99	*len += sizeof(CARD16);
100	 buf++;
101    }
102    return (char *)NULL;
103}
104
105static Bool
106_XimCheckInnerICAttributes(
107    Xic			 ic,
108    XIMArg		*arg,
109    unsigned long	 mode)
110{
111    XIMResourceList	 res;
112    int			 check;
113
114    if (!(res = _XimGetResourceListRec(ic->private.proto.ic_inner_resources,
115			ic->private.proto.ic_num_inner_resources, arg->name)))
116	return False;
117
118    check = _XimCheckICMode(res, mode);
119    if(check == XIM_CHECK_INVALID)
120	return True;
121    else if(check == XIM_CHECK_ERROR)
122	return False;
123
124    return True;
125}
126
127char *
128_XimMakeICAttrIDList(
129    Xic			 ic,
130    XIMResourceList	 res_list,
131    unsigned int	 res_num,
132    XIMArg		*arg,
133    CARD16		*buf,
134    INT16		*len,
135    unsigned long	 mode)
136{
137    register XIMArg	*p;
138    XIMResourceList	 res;
139    int			 check;
140    XrmQuark		 pre_quark;
141    XrmQuark		 sts_quark;
142    char		*name;
143    INT16		 new_len;
144
145    *len = 0;
146    if (!arg)
147	return (char *)NULL;
148
149    pre_quark = XrmStringToQuark(XNPreeditAttributes);
150    sts_quark = XrmStringToQuark(XNStatusAttributes);
151
152    for (p = arg; p && p->name; p++) {
153	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
154	    if (_XimCheckInnerICAttributes(ic, p, mode))
155		continue;
156	    *len = -1;
157	    return p->name;
158	}
159
160	check = _XimCheckICMode(res, mode);
161	if(check == XIM_CHECK_INVALID)
162	    continue;
163	else if(check == XIM_CHECK_ERROR) {
164	    *len = -1;
165	    return p->name;
166	}
167
168	*buf = res->id;
169	*len += sizeof(CARD16);
170	buf++;
171	if (res->resource_size == XimType_NEST) {
172	    if (res->xrm_name == pre_quark) {
173		if ((name = _XimMakeICAttrIDList(ic, res_list, res_num,
174				(XIMArg *)p->value, buf, &new_len,
175				(mode | XIM_PREEDIT_ATTR)))) {
176		    if (new_len < 0) *len = -1;
177		    else *len += new_len;
178		    return name;
179		}
180		*len += new_len;
181		buf = (CARD16 *)((char *)buf + new_len);
182	    } else if (res->xrm_name == sts_quark) {
183		if ((name = _XimMakeICAttrIDList(ic, res_list, res_num,
184				(XIMArg *)p->value, buf, &new_len,
185				(mode | XIM_STATUS_ATTR)))) {
186		    if (new_len < 0) *len = -1;
187		    else *len += new_len;
188		    return name;
189		}
190		*len += new_len;
191		buf = (CARD16 *)((char *)buf + new_len);
192	    }
193
194	    if (!(res = _XimGetNestedListSeparator(res_list, res_num))) {
195		p++;
196		if (p) {
197		    *len = -1;
198		    return p->name;
199		}
200		else {
201		    return (char *)NULL;
202		}
203	    }
204	    *buf = res->id;
205	    *len += sizeof(CARD16);
206	    buf++;
207	}
208    }
209    return (char *)NULL;
210}
211
212static Bool
213_XimAttributeToValue(
214    Xic			  ic,
215    XIMResourceList	  res,
216    CARD16		 *data,
217    INT16		  data_len,
218    XPointer		  value,
219    BITMASK32		  mode)
220{
221    switch (res->resource_size) {
222    case XimType_SeparatorOfNestedList:
223    case XimType_NEST:
224	break;
225
226    case XimType_CARD8:
227    case XimType_CARD16:
228    case XimType_CARD32:
229    case XimType_Window:
230    case XimType_XIMHotKeyState:
231	_XCopyToArg((XPointer)data, (XPointer *)&value, data_len);
232	break;
233
234    case XimType_STRING8:
235	{
236	    char	*str;
237
238	    if (!(value))
239		return False;
240
241	    if (!(str = Xmalloc(data_len + 1)))
242		return False;
243
244	    (void)memcpy(str, (char *)data, data_len);
245	    str[data_len] = '\0';
246
247	    *((char **)value) = str;
248	    break;
249	}
250
251    case XimType_XIMStyles:
252	{
253	    INT16		 num = data[0];
254	    register CARD32	*style_list = (CARD32 *)&data[2];
255	    XIMStyle		*style;
256	    XIMStyles		*rep;
257	    register int	 i;
258	    char		*p;
259	    int			 alloc_len;
260
261	    if (!(value))
262		return False;
263
264	    alloc_len = sizeof(XIMStyles) + sizeof(XIMStyle) * num;
265	    if (!(p = Xmalloc(alloc_len)))
266		return False;
267
268	    rep   = (XIMStyles *)p;
269	    style = (XIMStyle *)(p + sizeof(XIMStyles));
270
271	    for (i = 0; i < num; i++)
272		style[i] = (XIMStyle)style_list[i];
273
274	    rep->count_styles = (unsigned short)num;
275	    rep->supported_styles = style;
276	    *((XIMStyles **)value) = rep;
277	    break;
278	}
279
280    case XimType_XRectangle:
281	{
282	    XRectangle	*rep;
283
284	    if (!(value))
285		return False;
286
287	    if (!(rep = Xmalloc(sizeof(XRectangle))))
288		return False;
289
290	    rep->x      = data[0];
291	    rep->y      = data[1];
292	    rep->width  = data[2];
293	    rep->height = data[3];
294	    *((XRectangle **)value) = rep;
295	    break;
296	}
297
298    case XimType_XPoint:
299	{
300	    XPoint	*rep;
301
302	    if (!(value))
303		return False;
304
305	    if (!(rep = Xmalloc(sizeof(XPoint))))
306		return False;
307
308	    rep->x = data[0];
309	    rep->y = data[1];
310	    *((XPoint **)value) = rep;
311	    break;
312	}
313
314    case XimType_XFontSet:
315	{
316	    INT16	 len = data[0];
317	    char	*base_name;
318	    XFontSet	 rep = (XFontSet)NULL;
319	    char	**missing_list = NULL;
320	    int		 missing_count;
321	    char	*def_string;
322
323	    if (!(value))
324		return False;
325	    if (!ic)
326		return False;
327
328	    if (!(base_name = Xmalloc(len + 1)))
329		return False;
330
331	    (void)strncpy(base_name, (char *)&data[1], (int)len);
332	    base_name[len] = '\0';
333
334	    if (mode & XIM_PREEDIT_ATTR) {
335		if (!strcmp(base_name, ic->private.proto.preedit_font)) {
336		    rep = ic->core.preedit_attr.fontset;
337		} else if (!ic->private.proto.preedit_font_length) {
338		    rep = XCreateFontSet(ic->core.im->core.display,
339					base_name, &missing_list,
340					&missing_count, &def_string);
341		}
342	    } else if (mode & XIM_STATUS_ATTR) {
343		if (!strcmp(base_name, ic->private.proto.status_font)) {
344		    rep = ic->core.status_attr.fontset;
345		} else if (!ic->private.proto.status_font_length) {
346		    rep = XCreateFontSet(ic->core.im->core.display,
347					base_name, &missing_list,
348					&missing_count, &def_string);
349		}
350	    }
351
352	    Xfree(base_name);
353	    Xfree(missing_list);
354	    *((XFontSet *)value) = rep;
355	    break;
356	}
357
358    case XimType_XIMHotKeyTriggers:
359	{
360	    INT32			 num = *((CARD32 *)data);
361	    register CARD32		*key_list = (CARD32 *)&data[2];
362	    XIMHotKeyTrigger		*key;
363	    XIMHotKeyTriggers		*rep;
364	    register int		 i;
365	    char			*p;
366	    int				 alloc_len;
367
368	    if (!(value))
369		return False;
370
371	    alloc_len = sizeof(XIMHotKeyTriggers)
372		      + sizeof(XIMHotKeyTrigger) * num;
373	    if (!(p = Xmalloc(alloc_len)))
374		return False;
375
376	    rep = (XIMHotKeyTriggers *)p;
377	    key = (XIMHotKeyTrigger *)(p + sizeof(XIMHotKeyTriggers));
378
379	    for (i = 0; i < num; i++, key_list += 3) {
380		key[i].keysym        = (KeySym)key_list[0]; /* keysym */
381		key[i].modifier      = (int)key_list[1];    /* modifier */
382		key[i].modifier_mask = (int)key_list[2];    /* modifier_mask */
383	    }
384
385	    rep->num_hot_key = (int)num;
386	    rep->key = key;
387	    *((XIMHotKeyTriggers **)value) = rep;
388	    break;
389	}
390
391    case XimType_XIMStringConversion:
392	{
393	    break;
394	}
395
396    default:
397	return False;
398    }
399    return True;
400}
401
402static Bool
403_XimDecodeInnerIMATTRIBUTE(
404    Xim			 im,
405    XIMArg		*arg)
406{
407    XIMResourceList	 res;
408    XimDefIMValues	 im_values;
409
410    if (!(res = _XimGetResourceListRec(im->private.proto.im_inner_resources,
411			im->private.proto.im_num_inner_resources, arg->name)))
412	return False;
413
414    _XimGetCurrentIMValues(im, &im_values);
415    return _XimDecodeLocalIMAttr(res, (XPointer)&im_values, arg->value);
416}
417
418char *
419_XimDecodeIMATTRIBUTE(
420    Xim			 im,
421    XIMResourceList	 res_list,
422    unsigned int	 res_num,
423    CARD16		*data,
424    INT16		 data_len,
425    XIMArg		*arg,
426    BITMASK32		 mode)
427{
428    register XIMArg	*p;
429    XIMResourceList	 res;
430    int			 check;
431    INT16		 len;
432    CARD16		*buf;
433    INT16		 total;
434    INT16		 min_len = sizeof(CARD16)	/* sizeof attributeID */
435			 	 + sizeof(INT16);	/* sizeof length */
436
437    for (p = arg; p->name; p++) {
438	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
439	    if (_XimDecodeInnerIMATTRIBUTE(im, p))
440		continue;
441	    return p->name;
442	}
443
444	check = _XimCheckIMMode(res, mode);
445	if(check == XIM_CHECK_INVALID)
446	    continue;
447	else if(check == XIM_CHECK_ERROR)
448	    return p->name;
449
450	total = data_len;
451	buf = data;
452	while (total >= min_len) {
453	    if (res->id == buf[0])
454		break;
455
456	    len = buf[1];
457	    len += XIM_PAD(len) + min_len;
458	    buf = (CARD16 *)((char *)buf + len);
459	    total -= len;
460	}
461	if (total < min_len)
462	    return p->name;
463
464	if (!(_XimAttributeToValue((Xic) im->private.local.current_ic,
465				   res, &buf[2], buf[1], p->value, mode)))
466	    return p->name;
467    }
468    return (char *)NULL;
469}
470
471static Bool
472_XimDecodeInnerICATTRIBUTE(
473    Xic			 ic,
474    XIMArg		*arg,
475    unsigned long	 mode)
476{
477    XIMResourceList	 res;
478    XimDefICValues	 ic_values;
479
480    if (!(res = _XimGetResourceListRec(ic->private.proto.ic_inner_resources,
481			ic->private.proto.ic_num_inner_resources, arg->name)))
482	return False;
483
484    _XimGetCurrentICValues(ic, &ic_values);
485    if (!_XimDecodeLocalICAttr(res, (XPointer)&ic_values, arg->value, mode))
486	return False;
487    _XimSetCurrentICValues(ic, &ic_values);
488    return True;
489}
490
491char *
492_XimDecodeICATTRIBUTE(
493    Xic			 ic,
494    XIMResourceList	 res_list,
495    unsigned int	 res_num,
496    CARD16		*data,
497    INT16		 data_len,
498    XIMArg		*arg,
499    BITMASK32		 mode)
500{
501    register XIMArg	*p;
502    XIMResourceList	 res;
503    int			 check;
504    INT16		 len;
505    CARD16		*buf;
506    INT16		 total;
507    char		*name;
508    INT16		 min_len = sizeof(CARD16)	/* sizeof attributeID */
509			 	 + sizeof(INT16);	/* sizeof length */
510    XrmQuark		 pre_quark;
511    XrmQuark		 sts_quark;
512
513    if (!arg)
514	return (char *)NULL;
515
516    pre_quark = XrmStringToQuark(XNPreeditAttributes);
517    sts_quark = XrmStringToQuark(XNStatusAttributes);
518
519    for (p = arg; p->name; p++) {
520	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
521	    if (_XimDecodeInnerICATTRIBUTE(ic, p, mode))
522		continue;
523	    return p->name;
524	}
525
526	check = _XimCheckICMode(res, mode);
527	if (check == XIM_CHECK_INVALID)
528	    continue;
529	else if (check == XIM_CHECK_ERROR)
530	    return p->name;
531
532	total = data_len;
533	buf = data;
534	while (total >= min_len) {
535	    if (res->id == buf[0])
536		break;
537
538	    len = buf[1];
539	    len += XIM_PAD(len) + min_len;
540	    buf = (CARD16 *)((char *)buf + len);
541	    total -= len;
542	}
543	if (total < min_len)
544	    return p->name;
545
546	if (res->resource_size == XimType_NEST) {
547	    if (res->xrm_name == pre_quark) {
548	        if ((name = _XimDecodeICATTRIBUTE(ic, res_list, res_num,
549			&buf[2], buf[1], (XIMArg *)p->value,
550			(mode | XIM_PREEDIT_ATTR))))
551		    return name;
552	    } else if (res->xrm_name == sts_quark) {
553	        if ((name = _XimDecodeICATTRIBUTE(ic, res_list, res_num,
554			&buf[2], buf[1], (XIMArg *)p->value,
555			(mode | XIM_STATUS_ATTR))))
556		    return name;
557	    }
558	} else {
559	    if (!(_XimAttributeToValue(ic, res, &buf[2], buf[1],
560							p->value, mode)))
561		return p->name;
562	}
563    }
564    return (char *)NULL;
565}
566
567static Bool
568_XimValueToAttribute(
569    XIMResourceList	 res,
570    XPointer		 buf,
571    int			 buf_size,
572    XPointer		 value,
573    int			*len,
574    unsigned long	 mode,
575    XPointer		 param)
576{
577    int			 ret_len;
578
579    switch (res->resource_size) {
580    case XimType_SeparatorOfNestedList:
581    case XimType_NEST:
582	*len = 0;
583	break;
584
585    case XimType_CARD8:
586	ret_len = sizeof(CARD8);
587	if (buf_size < ret_len + XIM_PAD(ret_len)) {
588	    *len = -1;
589	    return False;
590	}
591
592	*((CARD8 *)buf) = (CARD8)(long)value;
593	*len = ret_len;
594	break;
595
596    case XimType_CARD16:
597	ret_len = sizeof(CARD16);
598	if (buf_size < ret_len + XIM_PAD(ret_len)) {
599	    *len = -1;
600	    return False;
601	}
602
603	*((CARD16 *)buf) = (CARD16)(long)value;
604	*len = ret_len;
605	break;
606
607    case XimType_CARD32:
608    case XimType_Window:
609    case XimType_XIMHotKeyState:
610	ret_len = sizeof(CARD32);
611	if (buf_size < ret_len + XIM_PAD(ret_len)) {
612	    *len = -1;
613	    return False;
614	}
615
616	*((CARD32 *)buf) = (CARD32)(long)value;
617	*len = ret_len;
618	break;
619
620    case XimType_STRING8:
621	if (!value) {
622	    *len = 0;
623	    return False;
624	}
625
626	ret_len = strlen((char *)value);
627	if (buf_size < ret_len + XIM_PAD(ret_len)) {
628	    *len = -1;
629	    return False;
630	}
631
632	(void)memcpy((char *)buf, (char *)value, ret_len);
633	*len = ret_len;
634	break;
635
636    case XimType_XRectangle:
637	{
638	    XRectangle	*rect = (XRectangle *)value;
639	    CARD16	*buf_s = (CARD16 *)buf;
640
641	    if (!rect) {
642		*len = 0;
643		return False;
644	    }
645
646	    ret_len = sizeof(INT16)		/* sizeof X */
647	    	    + sizeof(INT16)		/* sizeof Y */
648	            + sizeof(CARD16)		/* sizeof width */
649	            + sizeof(CARD16);		/* sizeof height */
650	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
651		*len = -1;
652		return False;
653	    }
654
655	    buf_s[0] = (CARD16)rect->x;		/* X */
656	    buf_s[1] = (CARD16)rect->y;		/* Y */
657	    buf_s[2] = (CARD16)rect->width;	/* width */
658	    buf_s[3] = (CARD16)rect->height;	/* heght */
659	    *len = ret_len;
660	    break;
661	}
662
663    case XimType_XPoint:
664	{
665	    XPoint	*point = (XPoint *)value;
666	    CARD16	*buf_s = (CARD16 *)buf;
667
668	    if (!point) {
669		*len = 0;
670		return False;
671	    }
672
673	    ret_len = sizeof(INT16)		/* sizeof X */
674	            + sizeof(INT16);		/* sizeof Y */
675	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
676		*len = -1;
677		return False;
678	    }
679
680	    buf_s[0] = (CARD16)point->x;		/* X */
681	    buf_s[1] = (CARD16)point->y;		/* Y */
682	    *len = ret_len;
683	    break;
684	}
685
686    case XimType_XFontSet:
687	{
688	    XFontSet	 font = (XFontSet)value;
689	    Xic		 ic = (Xic)param;
690	    char	*base_name = NULL;
691	    int		 length = 0;
692	    CARD16	*buf_s = (CARD16 *)buf;
693
694	    if (!font) {
695		*len = 0;
696		return False;
697	    }
698
699	    if (mode & XIM_PREEDIT_ATTR) {
700		base_name = ic->private.proto.preedit_font;
701		length	  = ic->private.proto.preedit_font_length;
702	    } else if (mode & XIM_STATUS_ATTR) {
703		base_name = ic->private.proto.status_font;
704		length	  = ic->private.proto.status_font_length;
705	    }
706
707	    if (!base_name) {
708		*len = 0;
709		return False;
710	    }
711
712	    ret_len = sizeof(CARD16)		/* sizeof length of Base name */
713		    + length;			/* sizeof Base font name list */
714	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
715		*len = -1;
716		return False;
717	    }
718
719	    buf_s[0] = (INT16)length;		/* length of Base font name */
720	    (void)memcpy((char *)&buf_s[1], base_name, length);
721						/* Base font name list */
722	    *len = ret_len;
723	    break;
724	}
725
726    case XimType_XIMHotKeyTriggers:
727	{
728	    XIMHotKeyTriggers	*hotkey = (XIMHotKeyTriggers *)value;
729	    INT32		 num;
730	    CARD32		*buf_l = (CARD32 *)buf;
731	    register CARD32	*key = (CARD32 *)&buf_l[1];
732	    register int	 i;
733
734	    if (!hotkey) {
735		*len = 0;
736		return False;
737	    }
738	    num = (INT32)hotkey->num_hot_key;
739
740	    ret_len = sizeof(INT32)		/* sizeof number of key list */
741	           + (sizeof(CARD32)		/* sizeof keysyn */
742	           +  sizeof(CARD32)		/* sizeof modifier */
743	           +  sizeof(CARD32))		/* sizeof modifier_mask */
744	           *  num;			/* number of key list */
745	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
746		*len = -1;
747		return False;
748	    }
749
750	    buf_l[0] = num;		/* number of key list */
751	    for (i = 0; i < num; i++, key += 3) {
752		key[0] = (CARD32)(hotkey->key[i].keysym);
753						/* keysym */
754		key[1] = (CARD32)(hotkey->key[i].modifier);
755						/* modifier */
756		key[2] = (CARD32)(hotkey->key[i].modifier_mask);
757						/* modifier_mask */
758	    }
759	    *len = ret_len;
760	    break;
761	}
762
763    case XimType_XIMStringConversion:
764	{
765	    *len = 0;
766	    break;
767	}
768
769    default:
770	return False;
771    }
772    return True;
773}
774
775static Bool
776_XimSetInnerIMAttributes(
777    Xim			 im,
778    XPointer		 top,
779    XIMArg		*arg,
780    unsigned long	 mode)
781{
782    XIMResourceList	 res;
783    int			 check;
784
785    if (!(res = _XimGetResourceListRec(im->private.proto.im_inner_resources,
786			im->private.proto.im_num_inner_resources, arg->name)))
787	return False;
788
789    check = _XimCheckIMMode(res, mode);
790    if(check == XIM_CHECK_INVALID)
791	return True;
792    else if(check == XIM_CHECK_ERROR)
793	return False;
794
795    return _XimEncodeLocalIMAttr(res, top, arg->value);
796}
797
798char *
799_XimEncodeIMATTRIBUTE(
800    Xim			  im,
801    XIMResourceList	  res_list,
802    unsigned int	  res_num,
803    XIMArg		 *arg,
804    XIMArg		**arg_ret,
805    char		 *buf,
806    int			  size,
807    int			 *ret_len,
808    XPointer		  top,
809    unsigned long	  mode)
810{
811    register XIMArg	*p;
812    XIMResourceList	 res;
813    int			 check;
814    CARD16		*buf_s;
815    int			 len;
816    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
817				 + sizeof(INT16); /* sizeof value length */
818
819    *ret_len = 0;
820    for (p = arg; p->name; p++) {
821	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
822	    if (_XimSetInnerIMAttributes(im, top, p, mode))
823		continue;
824	    return p->name;
825	}
826
827	check = _XimCheckIMMode(res, mode);
828	if (check == XIM_CHECK_INVALID)
829	    continue;
830	else if (check == XIM_CHECK_ERROR)
831	    return p->name;
832
833	if (!(_XimEncodeLocalIMAttr(res, top, p->value)))
834	    return p->name;
835
836	buf_s = (CARD16 *)buf;
837	if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2], (size - min_len),
838				p->value, &len, mode, (XPointer)NULL)))
839	    return p->name;
840
841	if (len == 0) {
842	    continue;
843	} else if (len < 0) {
844	    *arg_ret = p;
845	    return (char *)NULL;
846	}
847
848	buf_s[0] = res->id;			/* attribute ID */
849	buf_s[1] = len;				/* value length */
850	XIM_SET_PAD(&buf_s[2], len);		/* pad */
851	len += min_len;
852
853	buf += len;
854	*ret_len += len;
855	size -= len;
856    }
857    *arg_ret = (XIMArg *)NULL;
858    return (char *)NULL;
859}
860
861#ifdef XIM_CONNECTABLE
862Bool
863_XimEncodeSavedIMATTRIBUTE(
864    Xim			 im,
865    XIMResourceList	 res_list,
866    unsigned int	 res_num,
867    int			*idx,
868    char		*buf,
869    int			 size,
870    int			*ret_len,
871    XPointer		 top,
872    unsigned long	 mode)
873{
874    register int	 i;
875    int			 num = im->private.proto.num_saved_imvalues;
876    XrmQuark		*quark_list = im->private.proto.saved_imvalues;
877    XIMResourceList	 res;
878    XPointer		 value;
879    CARD16		*buf_s;
880    int			 len;
881    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
882				 + sizeof(INT16); /* sizeof value length */
883
884    if (!im->private.proto.saved_imvalues) {
885	*idx = -1;
886	*ret_len = 0;
887	return True;
888    }
889
890    *ret_len = 0;
891    for (i = *idx; i < num; i++) {
892	if (!(res = _XimGetResourceListRecByQuark(res_list,
893						res_num, quark_list[i])))
894	    continue;
895
896	if (!_XimDecodeLocalIMAttr(res, top, value))
897	    return False;
898
899	buf_s = (CARD16 *)buf;
900	if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
901			(size - min_len), value, &len, mode, (XPointer)NULL)))
902	    return False;
903
904	if (len == 0) {
905	    continue;
906	} else if (len < 0) {
907	    *idx = i;
908	    return True;
909	}
910
911	buf_s[0] = res->id;			/* attribute ID */
912	buf_s[1] = len;				/* value length */
913	XIM_SET_PAD(&buf_s[2], len);		/* pad */
914	len += min_len;
915
916	buf += len;
917	*ret_len += len;
918	size -= len;
919    }
920    *idx = -1;
921    return True;
922}
923#endif /* XIM_CONNECTABLE */
924
925static Bool
926_XimEncodeTopValue(
927    Xic			 ic,
928    XIMResourceList	 res,
929    XIMArg		*p)
930{
931    if (res->xrm_name == XrmStringToQuark(XNClientWindow)) {
932	ic->core.client_window = (Window)p->value;
933	if (ic->core.focus_window == (Window)0)
934	    ic->core.focus_window = ic->core.client_window;
935	_XimRegisterFilter(ic);
936
937    } else if (res->xrm_name == XrmStringToQuark(XNFocusWindow)) {
938	if (ic->core.client_window) {
939	    _XimUnregisterFilter(ic);
940	    ic->core.focus_window = (Window)p->value;
941	    _XimRegisterFilter(ic);
942	} else /* client_window not yet */
943	    ic->core.focus_window = (Window)p->value;
944    }
945    return True;
946}
947
948static Bool
949_XimEncodePreeditValue(
950    Xic			 ic,
951    XIMResourceList	 res,
952    XIMArg		*p)
953{
954    if (res->xrm_name == XrmStringToQuark(XNStdColormap)) {
955	XStandardColormap	*colormap_ret;
956	int			 count;
957
958	if (!(XGetRGBColormaps(ic->core.im->core.display,
959				ic->core.focus_window, &colormap_ret,
960				&count, (Atom)p->value)))
961	    return False;
962
963	XFree(colormap_ret);
964    } else if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
965	int		  list_ret;
966	XFontStruct	**struct_list;
967	char		**name_list;
968	char		 *tmp;
969	int		  len;
970	register int	  i;
971
972	if (!p->value)
973	    return False;
974
975	Xfree(ic->private.proto.preedit_font);
976
977	list_ret = XFontsOfFontSet((XFontSet)p->value,
978						 &struct_list, &name_list);
979	for (i = 0, len = 0; i < list_ret; i++) {
980	     len += (strlen(name_list[i]) + sizeof(char));
981	}
982	if (!(tmp = Xmalloc(len + 1))) {
983	    ic->private.proto.preedit_font = NULL;
984	    return False;
985	}
986
987	tmp[0] = '\0';
988	for (i = 0; i < list_ret; i++) {
989	    strcat(tmp, name_list[i]);
990	    strcat(tmp, ",");
991	}
992	tmp[len - 1] = 0;
993	ic->private.proto.preedit_font        = tmp;
994	ic->private.proto.preedit_font_length = len - 1;
995    }
996    return True;
997}
998
999static Bool
1000_XimEncodeStatusValue(
1001    Xic			 ic,
1002    XIMResourceList	 res,
1003    XIMArg		*p)
1004{
1005    if (res->xrm_name == XrmStringToQuark(XNStdColormap)) {
1006	XStandardColormap	*colormap_ret = NULL;
1007	int			 count;
1008
1009	if (!(XGetRGBColormaps(ic->core.im->core.display,
1010				ic->core.focus_window, &colormap_ret,
1011				&count, (Atom)p->value)))
1012	    return False;
1013
1014	XFree(colormap_ret);
1015    } else if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
1016	int		  list_ret;
1017	XFontStruct	**struct_list;
1018	char		**name_list;
1019	char		 *tmp;
1020	int		  len;
1021	register int	  i;
1022
1023	if (!p->value)
1024	    return False;
1025
1026	Xfree(ic->private.proto.status_font);
1027
1028	list_ret = XFontsOfFontSet((XFontSet)p->value,
1029						 &struct_list, &name_list);
1030	for (i = 0, len = 0; i < list_ret; i++) {
1031	     len += (strlen(name_list[i]) + sizeof(char));
1032	}
1033	if (!(tmp = Xmalloc(len+1))) {
1034	    ic->private.proto.status_font = NULL;
1035	    return False;
1036	}
1037
1038	tmp[0] = '\0';
1039	for(i = 0; i < list_ret; i++) {
1040	    strcat(tmp, name_list[i]);
1041	    strcat(tmp, ",");
1042	}
1043	tmp[len - 1] = 0;
1044	ic->private.proto.status_font        = tmp;
1045	ic->private.proto.status_font_length = len - 1;
1046    }
1047    return True;
1048}
1049
1050static Bool
1051_XimSetInnerICAttributes(
1052    Xic			 ic,
1053    XPointer		 top,
1054    XIMArg		*arg,
1055    unsigned long	 mode)
1056{
1057    XIMResourceList	 res;
1058    int			 check;
1059
1060    if (!(res = _XimGetResourceListRec(ic->private.proto.ic_inner_resources,
1061			ic->private.proto.ic_num_inner_resources, arg->name)))
1062	return False;
1063
1064    check = _XimCheckICMode(res, mode);
1065    if(check == XIM_CHECK_INVALID)
1066	return True;
1067    else if(check == XIM_CHECK_ERROR)
1068	return False;
1069
1070    return _XimEncodeLocalICAttr(ic, res, top, arg, mode);
1071}
1072
1073char *
1074_XimEncodeICATTRIBUTE(
1075    Xic			  ic,
1076    XIMResourceList	  res_list,
1077    unsigned int	  res_num,
1078    XIMArg		 *arg,
1079    XIMArg		**arg_ret,
1080    char		 *buf,
1081    int			  size,
1082    int			 *ret_len,
1083    XPointer		  top,
1084    BITMASK32		 *flag,
1085    unsigned long	  mode)
1086{
1087    register XIMArg	*p;
1088    XIMResourceList	 res;
1089    int			 check;
1090    CARD16		*buf_s;
1091    int			 len;
1092    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
1093				 + sizeof(INT16); /* sizeof value length */
1094    XrmQuark		 pre_quark;
1095    XrmQuark		 sts_quark;
1096    char		*name;
1097
1098    pre_quark = XrmStringToQuark(XNPreeditAttributes);
1099    sts_quark = XrmStringToQuark(XNStatusAttributes);
1100
1101    *ret_len = 0;
1102    for (p = arg; p && p->name; p++) {
1103	buf_s = (CARD16 *)buf;
1104	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
1105	    if (_XimSetInnerICAttributes(ic, top, p, mode))
1106		continue;
1107	    return p->name;
1108	}
1109
1110	check = _XimCheckICMode(res, mode);
1111	if (check == XIM_CHECK_INVALID)
1112	    continue;
1113	else if (check == XIM_CHECK_ERROR)
1114	    return p->name;
1115
1116	if (mode & XIM_PREEDIT_ATTR) {
1117	    if (!(_XimEncodePreeditValue(ic, res, p)))
1118		return p->name;
1119	} else if (mode & XIM_STATUS_ATTR) {
1120	    if (!(_XimEncodeStatusValue(ic, res, p)))
1121		return p->name;
1122	} else {
1123	    if (!(_XimEncodeTopValue(ic, res, p)))
1124		return p->name;
1125	}
1126
1127	if (res->resource_size == XimType_NEST) {
1128	    XimDefICValues	*ic_attr = (XimDefICValues *)top;
1129
1130	    if (res->xrm_name == pre_quark) {
1131		XIMArg		*arg_rt;
1132		if ((name = _XimEncodeICATTRIBUTE(ic, res_list, res_num,
1133				(XIMArg *)p->value, &arg_rt,
1134				(char *)&buf_s[2], (size - min_len),
1135				 &len, (XPointer)&ic_attr->preedit_attr, flag,
1136				(mode | XIM_PREEDIT_ATTR)))) {
1137		    return name;
1138		}
1139
1140	    } else if (res->xrm_name == sts_quark) {
1141		XIMArg		*arg_rt;
1142		if ((name = _XimEncodeICATTRIBUTE(ic, res_list, res_num,
1143				(XIMArg *)p->value,  &arg_rt,
1144				(char *)&buf_s[2], (size - min_len),
1145				 &len, (XPointer)&ic_attr->status_attr, flag,
1146				(mode | XIM_STATUS_ATTR)))) {
1147		    return name;
1148		}
1149	    }
1150	} else {
1151#ifdef EXT_MOVE
1152	    if (flag)
1153		*flag |= _XimExtenArgCheck(p);
1154#endif
1155    	    if (!(_XimEncodeLocalICAttr(ic, res, top, p, mode)))
1156		return p->name;
1157
1158	    if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
1159			 	(size - min_len), p->value,
1160				&len, mode, (XPointer)ic)))
1161		return p->name;
1162	}
1163
1164	if (len == 0) {
1165	    continue;
1166	} else if (len < 0) {
1167	    *arg_ret = p;
1168	    return (char *)NULL;
1169	}
1170
1171	buf_s[0] = res->id;			/* attribute ID */
1172	buf_s[1] = len;				/* value length */
1173	XIM_SET_PAD(&buf_s[2], len);		/* pad */
1174	len += min_len;
1175
1176	buf += len;
1177	*ret_len += len;
1178	size -= len;
1179    }
1180    *arg_ret = (XIMArg *)NULL;
1181    return (char *)NULL;
1182}
1183
1184#ifdef XIM_CONNECTABLE
1185static Bool
1186_XimEncodeSavedPreeditValue(
1187    Xic			  ic,
1188    XIMResourceList	  res,
1189    XPointer		  value)
1190{
1191    int			  list_ret;
1192    XFontStruct		**struct_list;
1193    char		**name_list;
1194    char		 *tmp;
1195    int			  len;
1196    register int	  i;
1197
1198    if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
1199	if (!value)
1200	    return False;
1201
1202	if (ic->private.proto.preedit_font)
1203	    Xfree(ic->private.proto.preedit_font);
1204
1205	list_ret = XFontsOfFontSet((XFontSet)value,
1206						&struct_list, &name_list);
1207	for(i = 0, len = 0; i < list_ret; i++) {
1208	    len += (strlen(name_list[i]) + sizeof(char));
1209	}
1210	if(!(tmp = Xmalloc(len + 1))) {
1211	    ic->private.proto.preedit_font = NULL;
1212	    return False;
1213	}
1214
1215	tmp[0] = '\0';
1216	for(i = 0; i < list_ret; i++) {
1217	    strcat(tmp, name_list[i]);
1218	    strcat(tmp, ",");
1219	}
1220	tmp[len - 1] = 0;
1221	ic->private.proto.preedit_font        = tmp;
1222	ic->private.proto.preedit_font_length = len - 1;
1223    }
1224    return True;
1225}
1226
1227static Bool
1228_XimEncodeSavedStatusValue(
1229    Xic			  ic,
1230    XIMResourceList	  res,
1231    XPointer		  value)
1232{
1233    int			  list_ret;
1234    XFontStruct		**struct_list;
1235    char		**name_list;
1236    char		 *tmp;
1237    int			  len;
1238    register int	  i;
1239
1240    if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
1241	if (!value)
1242	    return False;
1243
1244	Xfree(ic->private.proto.status_font);
1245
1246	list_ret = XFontsOfFontSet((XFontSet)value,
1247						&struct_list, &name_list);
1248	for(i = 0, len = 0; i < list_ret; i++) {
1249	    len += (strlen(name_list[i]) + sizeof(char));
1250	}
1251	if(!(tmp = Xmalloc(len + 1))) {
1252	    ic->private.proto.status_font = NULL;
1253	    return False;
1254	}
1255
1256	tmp[0] = '\0';
1257	for(i = 0; i < list_ret; i++) {
1258	    strcat(tmp, name_list[i]);
1259	    strcat(tmp, ",");
1260	}
1261	tmp[len - 1] = 0;
1262	ic->private.proto.status_font        = tmp;
1263	ic->private.proto.status_font_length = len - 1;
1264    }
1265    return True;
1266}
1267
1268Bool
1269_XimEncodeSavedICATTRIBUTE(
1270    Xic			 ic,
1271    XIMResourceList	 res_list,
1272    unsigned int	 res_num,
1273    int			*idx,
1274    char		*buf,
1275    int			 size,
1276    int			*ret_len,
1277    XPointer		 top,
1278    unsigned long	 mode)
1279{
1280    int			 i;
1281    int			 num = ic->private.proto.num_saved_icvalues;
1282    XrmQuark		*quark_list = ic->private.proto.saved_icvalues;
1283    XIMResourceList	 res;
1284    XPointer		 value;
1285    CARD16		*buf_s;
1286    int			 len;
1287    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
1288				 + sizeof(INT16); /* sizeof value length */
1289    XrmQuark		 pre_quark;
1290    XrmQuark		 sts_quark;
1291    XrmQuark		 separator;
1292
1293    if (!ic->private.proto.saved_icvalues) {
1294	*idx = -1;
1295	*ret_len = 0;
1296	return True;
1297    }
1298
1299    pre_quark = XrmStringToQuark(XNPreeditAttributes);
1300    sts_quark = XrmStringToQuark(XNStatusAttributes);
1301    separator = XrmStringToQuark(XNSeparatorofNestedList);
1302
1303    *ret_len = 0;
1304    for (i = *idx; i < num; i++) {
1305	if (quark_list[i] == separator) {
1306	    *idx = i;
1307	    return True;
1308	}
1309
1310	if (!(res = _XimGetResourceListRecByQuark(res_list,
1311						res_num, quark_list[i])))
1312	    continue;
1313
1314	if (!_XimDecodeLocalICAttr(res, top,(XPointer)&value, mode))
1315	    return False;
1316
1317	if (mode & XIM_PREEDIT_ATTR) {
1318	    if (!(_XimEncodeSavedPreeditValue(ic, res, value))) {
1319		return False;
1320	    }
1321	} else if (mode & XIM_STATUS_ATTR) {
1322	    if (!(_XimEncodeSavedStatusValue(ic, res, value))) {
1323		return False;
1324	    }
1325	}
1326
1327	buf_s = (CARD16 *)buf;
1328	if (res->resource_size == XimType_NEST) {
1329	    XimDefICValues	*ic_attr = (XimDefICValues *)top;
1330
1331	    i++;
1332	    if (res->xrm_name == pre_quark) {
1333		if (!_XimEncodeSavedICATTRIBUTE(ic, res_list, res_num,
1334				 &i, (char *)&buf_s[2], (size - min_len),
1335				 &len, (XPointer)&ic_attr->preedit_attr,
1336				(mode | XIM_PREEDIT_ATTR))) {
1337		    return False;
1338		}
1339
1340	    } else if (res->xrm_name == sts_quark) {
1341		if (!_XimEncodeSavedICATTRIBUTE(ic, res_list, res_num,
1342				&i, (char *)&buf_s[2], (size - min_len),
1343				&len, (XPointer)&ic_attr->status_attr,
1344				(mode | XIM_STATUS_ATTR))) {
1345		    return False;
1346		}
1347	    }
1348	} else {
1349	    if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
1350			 	(size - min_len), value,
1351				&len, mode, (XPointer)ic))) {
1352		return False;
1353	    }
1354	}
1355
1356	if (len == 0) {
1357	    continue;
1358	} else if (len < 0) {
1359	    if (quark_list[i] == separator)
1360		i++;
1361	    *idx = i;
1362	    return True;
1363	}
1364
1365	buf_s[0] = res->id;			/* attribute ID */
1366	buf_s[1] = len;				/* value length */
1367	XIM_SET_PAD(&buf_s[2], len);		/* pad */
1368	len += min_len;
1369
1370	buf += len;
1371	*ret_len += len;
1372	size -= len;
1373    }
1374    *idx = -1;
1375    return True;
1376}
1377#endif /* XIM_CONNECTABLE */
1378
1379static unsigned int
1380_XimCountNumberOfAttr(
1381    INT16	 total,
1382    CARD16	*attr,
1383    int		*names_len)
1384{
1385    unsigned int n;
1386    INT16	 len;
1387    INT16	 min_len = sizeof(CARD16)	/* sizeof attribute ID */
1388			 + sizeof(CARD16)	/* sizeof type of value */
1389			 + sizeof(INT16);	/* sizeof length of attribute */
1390
1391    n = 0;
1392    *names_len = 0;
1393    while (total > min_len) {
1394	len = attr[2];
1395	*names_len += (len + 1);
1396	len += (min_len + XIM_PAD(len + 2));
1397	total -= len;
1398	attr = (CARD16 *)((char *)attr + len);
1399	n++;
1400    }
1401    return n;
1402}
1403
1404Bool
1405_XimGetAttributeID(
1406    Xim			  im,
1407    CARD16		 *buf)
1408{
1409    unsigned int	  n;
1410    XIMResourceList	  res;
1411    char		 *names;
1412    int			  names_len;
1413    XPointer		  tmp;
1414    XIMValuesList	 *values_list;
1415    char		**values;
1416    int			  values_len;
1417    register int	  i;
1418    INT16		  len;
1419    INT16		  min_len = sizeof(CARD16) /* sizeof attribute ID */
1420				  + sizeof(CARD16) /* sizeof type of value */
1421				  + sizeof(INT16); /* sizeof length of attr */
1422    /*
1423     * IM attribute ID
1424     */
1425
1426    if (!(n = _XimCountNumberOfAttr(buf[0], &buf[1], &names_len)))
1427	return False;
1428
1429    if (!(res = Xcalloc(n, sizeof(XIMResource))))
1430	return False;
1431
1432    values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
1433    if (!(tmp = Xcalloc(1, values_len))) {
1434	Xfree(res);
1435	return False;
1436    }
1437
1438    values_list = (XIMValuesList *)tmp;
1439    values = (char **)((char *)tmp + sizeof(XIMValuesList));
1440    names = (char *)((char *)values + (sizeof(char **) * n));
1441
1442    values_list->count_values = n;
1443    values_list->supported_values = values;
1444
1445    buf++;
1446    for (i = 0; i < n; i++) {
1447	len = buf[2];
1448	(void)memcpy(names, (char *)&buf[3], len);
1449	values[i] = names;
1450	names[len] = '\0';
1451	res[i].resource_name = names;
1452	res[i].resource_size = buf[1];
1453	res[i].id	     = buf[0];
1454	names += (len + 1);
1455	len += (min_len + XIM_PAD(len + 2));
1456	buf = (CARD16 *)((char *)buf + len);
1457    }
1458    _XIMCompileResourceList(res, n);
1459
1460    Xfree(im->core.im_resources);
1461    Xfree(im->core.im_values_list);
1462
1463    im->core.im_resources     = res;
1464    im->core.im_num_resources = n;
1465    im->core.im_values_list   = values_list;
1466
1467    /*
1468     * IC attribute ID
1469     */
1470
1471    if (!(n = _XimCountNumberOfAttr(buf[0], &buf[2], &names_len)))
1472	return False;
1473
1474    if (!(res = Xcalloc(n, sizeof(XIMResource))))
1475	return False;
1476
1477    values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
1478    if (!(tmp = Xcalloc(1, values_len))) {
1479	Xfree(res);
1480	return False;
1481    }
1482
1483    values_list = (XIMValuesList *)tmp;
1484    values = (char **)((char *)tmp + sizeof(XIMValuesList));
1485    names = (char *)((char *)values + (sizeof(char **) * n));
1486
1487    values_list->count_values = n;
1488    values_list->supported_values = values;
1489
1490    buf += 2;
1491    for (i = 0; i < n; i++) {
1492	len = buf[2];
1493	(void)memcpy(names, (char *)&buf[3], len);
1494	values[i] = names;
1495	names[len] = '\0';
1496	res[i].resource_name = names;
1497	res[i].resource_size = buf[1];
1498	res[i].id	     = buf[0];
1499	names += (len + 1);
1500	len += (min_len + XIM_PAD(len + 2));
1501	buf = (CARD16 *)((char *)buf + len);
1502    }
1503    _XIMCompileResourceList(res, n);
1504
1505
1506    Xfree(im->core.ic_resources);
1507    Xfree(im->core.ic_values_list);
1508
1509    im->core.ic_resources     = res;
1510    im->core.ic_num_resources = n;
1511    im->core.ic_values_list   = values_list;
1512
1513    return True;
1514}
1515