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