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