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