imRmAttr.c revision 16add077
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	buf_s = (CARD16 *)buf;
1119	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
1120	    if (_XimSetInnerICAttributes(ic, top, p, mode))
1121		continue;
1122	    return p->name;
1123	}
1124
1125	check = _XimCheckICMode(res, mode);
1126	if (check == XIM_CHECK_INVALID)
1127	    continue;
1128	else if (check == XIM_CHECK_ERROR)
1129	    return p->name;
1130
1131	if (mode & XIM_PREEDIT_ATTR) {
1132	    if (!(_XimEncodePreeditValue(ic, res, p)))
1133		return p->name;
1134	} else if (mode & XIM_STATUS_ATTR) {
1135	    if (!(_XimEncodeStatusValue(ic, res, p)))
1136		return p->name;
1137	} else {
1138	    if (!(_XimEncodeTopValue(ic, res, p)))
1139		return p->name;
1140	}
1141
1142	if (res->resource_size == XimType_NEST) {
1143	    XimDefICValues	*ic_attr = (XimDefICValues *)top;
1144
1145	    if (res->xrm_name == pre_quark) {
1146		XIMArg		*arg_rt;
1147		if ((name = _XimEncodeICATTRIBUTE(ic, res_list, res_num,
1148				(XIMArg *)p->value, &arg_rt,
1149				(char *)&buf_s[2], (size - min_len),
1150				 &len, (XPointer)&ic_attr->preedit_attr, flag,
1151				(mode | XIM_PREEDIT_ATTR)))) {
1152		    return name;
1153		}
1154
1155	    } else if (res->xrm_name == sts_quark) {
1156		XIMArg		*arg_rt;
1157		if ((name = _XimEncodeICATTRIBUTE(ic, res_list, res_num,
1158				(XIMArg *)p->value,  &arg_rt,
1159				(char *)&buf_s[2], (size - min_len),
1160				 &len, (XPointer)&ic_attr->status_attr, flag,
1161				(mode | XIM_STATUS_ATTR)))) {
1162		    return name;
1163		}
1164	    }
1165	} else {
1166#ifdef EXT_MOVE
1167	    if (flag)
1168		*flag |= _XimExtenArgCheck(p);
1169#endif
1170    	    if (!(_XimEncodeLocalICAttr(ic, res, top, p, mode)))
1171		return p->name;
1172
1173	    if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
1174			 	(size - min_len), p->value,
1175				&len, mode, (XPointer)ic)))
1176		return p->name;
1177	}
1178
1179	if (len == 0) {
1180	    continue;
1181	} else if (len < 0) {
1182	    *arg_ret = p;
1183	    return (char *)NULL;
1184	}
1185
1186	buf_s[0] = res->id;			/* attribute ID */
1187	buf_s[1] = len;				/* value length */
1188	XIM_SET_PAD(&buf_s[2], len);		/* pad */
1189	len += min_len;
1190
1191	buf += len;
1192	*ret_len += len;
1193	size -= len;
1194    }
1195    *arg_ret = (XIMArg *)NULL;
1196    return (char *)NULL;
1197}
1198
1199#ifdef XIM_CONNECTABLE
1200static Bool
1201_XimEncodeSavedPreeditValue(
1202    Xic			  ic,
1203    XIMResourceList	  res,
1204    XPointer		  value)
1205{
1206    int			  list_ret;
1207    XFontStruct		**struct_list;
1208    char		**name_list;
1209    char		 *tmp;
1210    int			  len;
1211    register int	  i;
1212
1213    if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
1214	if (!value)
1215	    return False;
1216
1217	if (ic->private.proto.preedit_font)
1218	    Xfree(ic->private.proto.preedit_font);
1219
1220	list_ret = XFontsOfFontSet((XFontSet)value,
1221						&struct_list, &name_list);
1222	for(i = 0, len = 0; i < list_ret; i++) {
1223	    len += (strlen(name_list[i]) + sizeof(char));
1224	}
1225	if(!(tmp = Xmalloc(len + 1))) {
1226	    ic->private.proto.preedit_font = NULL;
1227	    return False;
1228	}
1229
1230	tmp[0] = '\0';
1231	for(i = 0; i < list_ret; i++) {
1232	    strcat(tmp, name_list[i]);
1233	    strcat(tmp, ",");
1234	}
1235	tmp[len - 1] = 0;
1236	ic->private.proto.preedit_font        = tmp;
1237	ic->private.proto.preedit_font_length = len - 1;
1238    }
1239    return True;
1240}
1241
1242static Bool
1243_XimEncodeSavedStatusValue(
1244    Xic			  ic,
1245    XIMResourceList	  res,
1246    XPointer		  value)
1247{
1248    int			  list_ret;
1249    XFontStruct		**struct_list;
1250    char		**name_list;
1251    char		 *tmp;
1252    int			  len;
1253    register int	  i;
1254
1255    if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
1256	if (!value)
1257	    return False;
1258
1259	Xfree(ic->private.proto.status_font);
1260
1261	list_ret = XFontsOfFontSet((XFontSet)value,
1262						&struct_list, &name_list);
1263	for(i = 0, len = 0; i < list_ret; i++) {
1264	    len += (strlen(name_list[i]) + sizeof(char));
1265	}
1266	if(!(tmp = Xmalloc(len + 1))) {
1267	    ic->private.proto.status_font = NULL;
1268	    return False;
1269	}
1270
1271	tmp[0] = '\0';
1272	for(i = 0; i < list_ret; i++) {
1273	    strcat(tmp, name_list[i]);
1274	    strcat(tmp, ",");
1275	}
1276	tmp[len - 1] = 0;
1277	ic->private.proto.status_font        = tmp;
1278	ic->private.proto.status_font_length = len - 1;
1279    }
1280    return True;
1281}
1282
1283Bool
1284_XimEncodeSavedICATTRIBUTE(
1285    Xic			 ic,
1286    XIMResourceList	 res_list,
1287    unsigned int	 res_num,
1288    int			*idx,
1289    char		*buf,
1290    int			 size,
1291    int			*ret_len,
1292    XPointer		 top,
1293    unsigned long	 mode)
1294{
1295    int			 i;
1296    int			 num = ic->private.proto.num_saved_icvalues;
1297    XrmQuark		*quark_list = ic->private.proto.saved_icvalues;
1298    XIMResourceList	 res;
1299    XPointer		 value;
1300    CARD16		*buf_s;
1301    int			 len;
1302    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
1303				 + sizeof(INT16); /* sizeof value length */
1304    XrmQuark		 pre_quark;
1305    XrmQuark		 sts_quark;
1306    XrmQuark		 separator;
1307
1308    if (!ic->private.proto.saved_icvalues) {
1309	*idx = -1;
1310	*ret_len = 0;
1311	return True;
1312    }
1313
1314    pre_quark = XrmStringToQuark(XNPreeditAttributes);
1315    sts_quark = XrmStringToQuark(XNStatusAttributes);
1316    separator = XrmStringToQuark(XNSeparatorofNestedList);
1317
1318    *ret_len = 0;
1319    for (i = *idx; i < num; i++) {
1320	if (quark_list[i] == separator) {
1321	    *idx = i;
1322	    return True;
1323	}
1324
1325	if (!(res = _XimGetResourceListRecByQuark(res_list,
1326						res_num, quark_list[i])))
1327	    continue;
1328
1329	if (!_XimDecodeLocalICAttr(res, top,(XPointer)&value, mode))
1330	    return False;
1331
1332	if (mode & XIM_PREEDIT_ATTR) {
1333	    if (!(_XimEncodeSavedPreeditValue(ic, res, value))) {
1334		return False;
1335	    }
1336	} else if (mode & XIM_STATUS_ATTR) {
1337	    if (!(_XimEncodeSavedStatusValue(ic, res, value))) {
1338		return False;
1339	    }
1340	}
1341
1342	buf_s = (CARD16 *)buf;
1343	if (res->resource_size == XimType_NEST) {
1344	    XimDefICValues	*ic_attr = (XimDefICValues *)top;
1345
1346	    i++;
1347	    if (res->xrm_name == pre_quark) {
1348		if (!_XimEncodeSavedICATTRIBUTE(ic, res_list, res_num,
1349				 &i, (char *)&buf_s[2], (size - min_len),
1350				 &len, (XPointer)&ic_attr->preedit_attr,
1351				(mode | XIM_PREEDIT_ATTR))) {
1352		    return False;
1353		}
1354
1355	    } else if (res->xrm_name == sts_quark) {
1356		if (!_XimEncodeSavedICATTRIBUTE(ic, res_list, res_num,
1357				&i, (char *)&buf_s[2], (size - min_len),
1358				&len, (XPointer)&ic_attr->status_attr,
1359				(mode | XIM_STATUS_ATTR))) {
1360		    return False;
1361		}
1362	    }
1363	} else {
1364	    if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
1365			 	(size - min_len), value,
1366				&len, mode, (XPointer)ic))) {
1367		return False;
1368	    }
1369	}
1370
1371	if (len == 0) {
1372	    continue;
1373	} else if (len < 0) {
1374	    if (quark_list[i] == separator)
1375		i++;
1376	    *idx = i;
1377	    return True;
1378	}
1379
1380	buf_s[0] = res->id;			/* attribute ID */
1381	buf_s[1] = len;				/* value length */
1382	XIM_SET_PAD(&buf_s[2], len);		/* pad */
1383	len += min_len;
1384
1385	buf += len;
1386	*ret_len += len;
1387	size -= len;
1388    }
1389    *idx = -1;
1390    return True;
1391}
1392#endif /* XIM_CONNECTABLE */
1393
1394static unsigned int
1395_XimCountNumberOfAttr(
1396    CARD16	  total,
1397    CARD16	 *attr,
1398    unsigned int *names_len)
1399{
1400    unsigned int n;
1401    CARD16	 len;
1402    CARD16	 min_len = sizeof(CARD16)	/* sizeof attribute ID */
1403			 + sizeof(CARD16)	/* sizeof type of value */
1404			 + sizeof(INT16);	/* sizeof length of attribute */
1405
1406    n = 0;
1407    *names_len = 0;
1408    while (total > min_len) {
1409	len = attr[2];
1410	if (len > (total - min_len)) {
1411	    return 0;
1412	}
1413	*names_len += (len + 1);
1414	len += (min_len + XIM_PAD(len + 2));
1415	total -= len;
1416	attr = (CARD16 *)((char *)attr + len);
1417	n++;
1418    }
1419    return n;
1420}
1421
1422Bool
1423_XimGetAttributeID(
1424    Xim			  im,
1425    CARD16		 *buf)
1426{
1427    unsigned int	  n, names_len, values_len;
1428    XIMResourceList	  res;
1429    char		 *names;
1430    XPointer		  tmp;
1431    XIMValuesList	 *values_list;
1432    char		**values;
1433    register int	  i;
1434    CARD16		  len;
1435    CARD16		  min_len = sizeof(CARD16) /* sizeof attribute ID */
1436				  + sizeof(CARD16) /* sizeof type of value */
1437				  + sizeof(INT16); /* sizeof length of attr */
1438    /*
1439     * IM attribute ID
1440     */
1441
1442    if (!(n = _XimCountNumberOfAttr(buf[0], &buf[1], &names_len)))
1443	return False;
1444
1445    if (!(res = Xcalloc(n, sizeof(XIMResource))))
1446	return False;
1447
1448    values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
1449    if (!(tmp = Xcalloc(1, values_len))) {
1450	Xfree(res);
1451	return False;
1452    }
1453
1454    values_list = (XIMValuesList *)tmp;
1455    values = (char **)((char *)tmp + sizeof(XIMValuesList));
1456    names = (char *)((char *)values + (sizeof(char **) * n));
1457
1458    values_list->count_values = n;
1459    values_list->supported_values = values;
1460
1461    buf++;
1462    for (i = 0; i < n; i++) {
1463	len = buf[2];
1464	(void)memcpy(names, (char *)&buf[3], len);
1465	values[i] = names;
1466	names[len] = '\0';
1467	res[i].resource_name = names;
1468	res[i].resource_size = buf[1];
1469	res[i].id	     = buf[0];
1470	names += (len + 1);
1471	len += (min_len + XIM_PAD(len + 2));
1472	buf = (CARD16 *)((char *)buf + len);
1473    }
1474    _XIMCompileResourceList(res, n);
1475
1476    Xfree(im->core.im_resources);
1477    Xfree(im->core.im_values_list);
1478
1479    im->core.im_resources     = res;
1480    im->core.im_num_resources = n;
1481    im->core.im_values_list   = values_list;
1482
1483    /*
1484     * IC attribute ID
1485     */
1486
1487    if (!(n = _XimCountNumberOfAttr(buf[0], &buf[2], &names_len)))
1488	return False;
1489
1490    if (!(res = Xcalloc(n, sizeof(XIMResource))))
1491	return False;
1492
1493    values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
1494    if (!(tmp = Xcalloc(1, values_len))) {
1495	Xfree(res);
1496	return False;
1497    }
1498
1499    values_list = (XIMValuesList *)tmp;
1500    values = (char **)((char *)tmp + sizeof(XIMValuesList));
1501    names = (char *)((char *)values + (sizeof(char **) * n));
1502
1503    values_list->count_values = n;
1504    values_list->supported_values = values;
1505
1506    buf += 2;
1507    for (i = 0; i < n; i++) {
1508	len = buf[2];
1509	(void)memcpy(names, (char *)&buf[3], len);
1510	values[i] = names;
1511	names[len] = '\0';
1512	res[i].resource_name = names;
1513	res[i].resource_size = buf[1];
1514	res[i].id	     = buf[0];
1515	names += (len + 1);
1516	len += (min_len + XIM_PAD(len + 2));
1517	buf = (CARD16 *)((char *)buf + len);
1518    }
1519    _XIMCompileResourceList(res, n);
1520
1521
1522    Xfree(im->core.ic_resources);
1523    Xfree(im->core.ic_values_list);
1524
1525    im->core.ic_resources     = res;
1526    im->core.ic_num_resources = n;
1527    im->core.ic_values_list   = values_list;
1528
1529    return True;
1530}
1531