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