imRmAttr.c revision 57f47464
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 = NULL;
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	    Xfree(missing_list);
351	    *((XFontSet *)value) = rep;
352	    break;
353	}
354
355    case XimType_XIMHotKeyTriggers:
356	{
357	    INT32			 num = *((CARD32 *)data);
358	    register CARD32		*key_list = (CARD32 *)&data[2];
359	    XIMHotKeyTrigger		*key;
360	    XIMHotKeyTriggers		*rep;
361	    register int		 i;
362	    char			*p;
363	    int				 alloc_len;
364
365	    if (!(value))
366		return False;
367
368	    alloc_len = sizeof(XIMHotKeyTriggers)
369		      + sizeof(XIMHotKeyTrigger) * num;
370	    if (!(p = (char *)Xmalloc(alloc_len)))
371		return False;
372
373	    rep = (XIMHotKeyTriggers *)p;
374	    key = (XIMHotKeyTrigger *)(p + sizeof(XIMHotKeyTriggers));
375
376	    for (i = 0; i < num; i++, key_list += 3) {
377		key[i].keysym        = (KeySym)key_list[0]; /* keysym */
378		key[i].modifier      = (int)key_list[1];    /* modifier */
379		key[i].modifier_mask = (int)key_list[2];    /* modifier_mask */
380	    }
381
382	    rep->num_hot_key = (int)num;
383	    rep->key = key;
384	    *((XIMHotKeyTriggers **)value) = rep;
385	    break;
386	}
387
388    case XimType_XIMStringConversion:
389	{
390	    break;
391	}
392
393    default:
394	return False;
395    }
396    return True;
397}
398
399Private Bool
400_XimDecodeInnerIMATTRIBUTE(
401    Xim			 im,
402    XIMArg		*arg)
403{
404    XIMResourceList	 res;
405    XimDefIMValues	 im_values;
406
407    if (!(res = _XimGetResourceListRec(im->private.proto.im_inner_resources,
408			im->private.proto.im_num_inner_resources, arg->name)))
409	return False;
410
411    _XimGetCurrentIMValues(im, &im_values);
412    return _XimDecodeLocalIMAttr(res, (XPointer)&im_values, arg->value);
413}
414
415Public char *
416_XimDecodeIMATTRIBUTE(
417    Xim			 im,
418    XIMResourceList	 res_list,
419    unsigned int	 res_num,
420    CARD16		*data,
421    INT16		 data_len,
422    XIMArg		*arg,
423    BITMASK32		 mode)
424{
425    register XIMArg	*p;
426    XIMResourceList	 res;
427    int			 check;
428    INT16		 len;
429    CARD16		*buf;
430    INT16		 total;
431    INT16		 min_len = sizeof(CARD16)	/* sizeof attributeID */
432			 	 + sizeof(INT16);	/* sizeof length */
433
434    for (p = arg; p->name; p++) {
435	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
436	    if (_XimDecodeInnerIMATTRIBUTE(im, p))
437		continue;
438	    return p->name;
439	}
440
441	check = _XimCheckIMMode(res, mode);
442	if(check == XIM_CHECK_INVALID)
443	    continue;
444	else if(check == XIM_CHECK_ERROR)
445	    return p->name;
446
447	total = data_len;
448	buf = data;
449	while (total >= min_len) {
450	    if (res->id == buf[0])
451		break;
452
453	    len = buf[1];
454	    len += XIM_PAD(len) + min_len;
455	    buf = (CARD16 *)((char *)buf + len);
456	    total -= len;
457	}
458	if (total < min_len)
459	    return p->name;
460
461	if (!(_XimAttributeToValue((Xic) im->private.local.current_ic,
462				   res, &buf[2], buf[1], p->value, mode)))
463	    return p->name;
464    }
465    return (char *)NULL;
466}
467
468Private Bool
469_XimDecodeInnerICATTRIBUTE(
470    Xic			 ic,
471    XIMArg		*arg,
472    unsigned long	 mode)
473{
474    XIMResourceList	 res;
475    XimDefICValues	 ic_values;
476
477    if (!(res = _XimGetResourceListRec(ic->private.proto.ic_inner_resources,
478			ic->private.proto.ic_num_inner_resources, arg->name)))
479	return False;
480
481    _XimGetCurrentICValues(ic, &ic_values);
482    if (!_XimDecodeLocalICAttr(res, (XPointer)&ic_values, arg->value, mode))
483	return False;
484    _XimSetCurrentICValues(ic, &ic_values);
485    return True;
486}
487
488Public char *
489_XimDecodeICATTRIBUTE(
490    Xic			 ic,
491    XIMResourceList	 res_list,
492    unsigned int	 res_num,
493    CARD16		*data,
494    INT16		 data_len,
495    XIMArg		*arg,
496    BITMASK32		 mode)
497{
498    register XIMArg	*p;
499    XIMResourceList	 res;
500    int			 check;
501    INT16		 len;
502    CARD16		*buf;
503    INT16		 total;
504    char		*name;
505    INT16		 min_len = sizeof(CARD16)	/* sizeof attributeID */
506			 	 + sizeof(INT16);	/* sizeof length */
507    XrmQuark		 pre_quark;
508    XrmQuark		 sts_quark;
509
510    if (!arg)
511	return (char *)NULL;
512
513    pre_quark = XrmStringToQuark(XNPreeditAttributes);
514    sts_quark = XrmStringToQuark(XNStatusAttributes);
515
516    for (p = arg; p->name; p++) {
517	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
518	    if (_XimDecodeInnerICATTRIBUTE(ic, p, mode))
519		continue;
520	    return p->name;
521	}
522
523	check = _XimCheckICMode(res, mode);
524	if (check == XIM_CHECK_INVALID)
525	    continue;
526	else if (check == XIM_CHECK_ERROR)
527	    return p->name;
528
529	total = data_len;
530	buf = data;
531	while (total >= min_len) {
532	    if (res->id == buf[0])
533		break;
534
535	    len = buf[1];
536	    len += XIM_PAD(len) + min_len;
537	    buf = (CARD16 *)((char *)buf + len);
538	    total -= len;
539	}
540	if (total < min_len)
541	    return p->name;
542
543	if (res->resource_size == XimType_NEST) {
544	    if (res->xrm_name == pre_quark) {
545	        if ((name = _XimDecodeICATTRIBUTE(ic, res_list, res_num,
546			&buf[2], buf[1], (XIMArg *)p->value,
547			(mode | XIM_PREEDIT_ATTR))))
548		    return name;
549	    } else if (res->xrm_name == sts_quark) {
550	        if ((name = _XimDecodeICATTRIBUTE(ic, res_list, res_num,
551			&buf[2], buf[1], (XIMArg *)p->value,
552			(mode | XIM_STATUS_ATTR))))
553		    return name;
554	    }
555	} else {
556	    if (!(_XimAttributeToValue(ic, res, &buf[2], buf[1],
557							p->value, mode)))
558		return p->name;
559	}
560    }
561    return (char *)NULL;
562}
563
564Private Bool
565_XimValueToAttribute(
566    XIMResourceList	 res,
567    XPointer		 buf,
568    int			 buf_size,
569    XPointer		 value,
570    int			*len,
571    unsigned long	 mode,
572    XPointer		 param)
573{
574    int			 ret_len;
575
576    switch (res->resource_size) {
577    case XimType_SeparatorOfNestedList:
578    case XimType_NEST:
579	*len = 0;
580	break;
581
582    case XimType_CARD8:
583	ret_len = sizeof(CARD8);
584	if (buf_size < ret_len + XIM_PAD(ret_len)) {
585	    *len = -1;
586	    return False;
587	}
588
589	*((CARD8 *)buf) = (CARD8)(long)value;
590	*len = ret_len;
591	break;
592
593    case XimType_CARD16:
594	ret_len = sizeof(CARD16);
595	if (buf_size < ret_len + XIM_PAD(ret_len)) {
596	    *len = -1;
597	    return False;
598	}
599
600	*((CARD16 *)buf) = (CARD16)(long)value;
601	*len = ret_len;
602	break;
603
604    case XimType_CARD32:
605    case XimType_Window:
606    case XimType_XIMHotKeyState:
607	ret_len = sizeof(CARD32);
608	if (buf_size < ret_len + XIM_PAD(ret_len)) {
609	    *len = -1;
610	    return False;
611	}
612
613	*((CARD32 *)buf) = (CARD32)(long)value;
614	*len = ret_len;
615	break;
616
617    case XimType_STRING8:
618	if (!value) {
619	    *len = 0;
620	    return False;
621	}
622
623	ret_len = strlen((char *)value);
624	if (buf_size < ret_len + XIM_PAD(ret_len)) {
625	    *len = -1;
626	    return False;
627	}
628
629	(void)memcpy((char *)buf, (char *)value, ret_len);
630	*len = ret_len;
631	break;
632
633    case XimType_XRectangle:
634	{
635	    XRectangle	*rect = (XRectangle *)value;
636	    CARD16	*buf_s = (CARD16 *)buf;
637
638	    if (!rect) {
639		*len = 0;
640		return False;
641	    }
642
643	    ret_len = sizeof(INT16)		/* sizeof X */
644	    	    + sizeof(INT16)		/* sizeof Y */
645	            + sizeof(CARD16)		/* sizeof width */
646	            + sizeof(CARD16);		/* sizeof height */
647	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
648		*len = -1;
649		return False;
650	    }
651
652	    buf_s[0] = (CARD16)rect->x;		/* X */
653	    buf_s[1] = (CARD16)rect->y;		/* Y */
654	    buf_s[2] = (CARD16)rect->width;	/* width */
655	    buf_s[3] = (CARD16)rect->height;	/* heght */
656	    *len = ret_len;
657	    break;
658	}
659
660    case XimType_XPoint:
661	{
662	    XPoint	*point = (XPoint *)value;
663	    CARD16	*buf_s = (CARD16 *)buf;
664
665	    if (!point) {
666		*len = 0;
667		return False;
668	    }
669
670	    ret_len = sizeof(INT16)		/* sizeof X */
671	            + sizeof(INT16);		/* sizeof Y */
672	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
673		*len = -1;
674		return False;
675	    }
676
677	    buf_s[0] = (CARD16)point->x;		/* X */
678	    buf_s[1] = (CARD16)point->y;		/* Y */
679	    *len = ret_len;
680	    break;
681	}
682
683    case XimType_XFontSet:
684	{
685	    XFontSet	 font = (XFontSet)value;
686	    Xic		 ic = (Xic)param;
687	    char	*base_name = NULL;
688	    int		 length = 0;
689	    CARD16	*buf_s = (CARD16 *)buf;
690
691	    if (!font) {
692		*len = 0;
693		return False;
694	    }
695
696	    if (mode & XIM_PREEDIT_ATTR) {
697		base_name = ic->private.proto.preedit_font;
698		length	  = ic->private.proto.preedit_font_length;
699	    } else if (mode & XIM_STATUS_ATTR) {
700		base_name = ic->private.proto.status_font;
701		length	  = ic->private.proto.status_font_length;
702	    }
703
704	    if (!base_name) {
705		*len = 0;
706		return False;
707	    }
708
709	    ret_len = sizeof(CARD16)		/* sizeof length of Base name */
710		    + length;			/* sizeof Base font name list */
711	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
712		*len = -1;
713		return False;
714	    }
715
716	    buf_s[0] = (INT16)length;		/* length of Base font name */
717	    (void)memcpy((char *)&buf_s[1], base_name, length);
718						/* Base font name list */
719	    *len = ret_len;
720	    break;
721	}
722
723    case XimType_XIMHotKeyTriggers:
724	{
725	    XIMHotKeyTriggers	*hotkey = (XIMHotKeyTriggers *)value;
726	    INT32		 num;
727	    CARD32		*buf_l = (CARD32 *)buf;
728	    register CARD32	*key = (CARD32 *)&buf_l[1];
729	    register int	 i;
730
731	    if (!hotkey) {
732		*len = 0;
733		return False;
734	    }
735	    num = (INT32)hotkey->num_hot_key;
736
737	    ret_len = sizeof(INT32)		/* sizeof number of key list */
738	           + (sizeof(CARD32)		/* sizeof keysyn */
739	           +  sizeof(CARD32)		/* sizeof modifier */
740	           +  sizeof(CARD32))		/* sizeof modifier_mask */
741	           *  num;			/* number of key list */
742	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
743		*len = -1;
744		return False;
745	    }
746
747	    buf_l[0] = num;		/* number of key list */
748	    for (i = 0; i < num; i++, key += 3) {
749		key[0] = (CARD32)(hotkey->key[i].keysym);
750						/* keysym */
751		key[1] = (CARD32)(hotkey->key[i].modifier);
752						/* modifier */
753		key[2] = (CARD32)(hotkey->key[i].modifier_mask);
754						/* modifier_mask */
755	    }
756	    *len = ret_len;
757	    break;
758	}
759
760    case XimType_XIMStringConversion:
761	{
762	    *len = 0;
763	    break;
764	}
765
766    default:
767	return False;
768    }
769    return True;
770}
771
772Private Bool
773_XimSetInnerIMAttributes(
774    Xim			 im,
775    XPointer		 top,
776    XIMArg		*arg,
777    unsigned long	 mode)
778{
779    XIMResourceList	 res;
780    int			 check;
781
782    if (!(res = _XimGetResourceListRec(im->private.proto.im_inner_resources,
783			im->private.proto.im_num_inner_resources, arg->name)))
784	return False;
785
786    check = _XimCheckIMMode(res, mode);
787    if(check == XIM_CHECK_INVALID)
788	return True;
789    else if(check == XIM_CHECK_ERROR)
790	return False;
791
792    return _XimEncodeLocalIMAttr(res, top, arg->value);
793}
794
795Public char *
796_XimEncodeIMATTRIBUTE(
797    Xim			  im,
798    XIMResourceList	  res_list,
799    unsigned int	  res_num,
800    XIMArg		 *arg,
801    XIMArg		**arg_ret,
802    char		 *buf,
803    int			  size,
804    int			 *ret_len,
805    XPointer		  top,
806    unsigned long	  mode)
807{
808    register XIMArg	*p;
809    XIMResourceList	 res;
810    int			 check;
811    CARD16		*buf_s;
812    int			 len;
813    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
814				 + sizeof(INT16); /* sizeof value length */
815
816    *ret_len = 0;
817    for (p = arg; p->name; p++) {
818	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
819	    if (_XimSetInnerIMAttributes(im, top, p, mode))
820		continue;
821	    return p->name;
822	}
823
824	check = _XimCheckIMMode(res, mode);
825	if (check == XIM_CHECK_INVALID)
826	    continue;
827	else if (check == XIM_CHECK_ERROR)
828	    return p->name;
829
830	if (!(_XimEncodeLocalIMAttr(res, top, p->value)))
831	    return p->name;
832
833	buf_s = (CARD16 *)buf;
834	if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2], (size - min_len),
835				p->value, &len, mode, (XPointer)NULL)))
836	    return p->name;
837
838	if (len == 0) {
839	    continue;
840	} else if (len < 0) {
841	    *arg_ret = p;
842	    return (char *)NULL;
843	}
844
845	buf_s[0] = res->id;			/* attribute ID */
846	buf_s[1] = len;				/* value length */
847	XIM_SET_PAD(&buf_s[2], len);		/* pad */
848	len += min_len;
849
850	buf += len;
851	*ret_len += len;
852	size -= len;
853    }
854    *arg_ret = (XIMArg *)NULL;
855    return (char *)NULL;
856}
857
858#ifdef XIM_CONNECTABLE
859Public	Bool
860_XimEncodeSavedIMATTRIBUTE(
861    Xim			 im,
862    XIMResourceList	 res_list,
863    unsigned int	 res_num,
864    int			*idx,
865    char		*buf,
866    int			 size,
867    int			*ret_len,
868    XPointer		 top,
869    unsigned long	 mode)
870{
871    register int	 i;
872    int			 num = im->private.proto.num_saved_imvalues;
873    XrmQuark		*quark_list = im->private.proto.saved_imvalues;
874    XIMResourceList	 res;
875    XPointer		 value;
876    CARD16		*buf_s;
877    int			 len;
878    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
879				 + sizeof(INT16); /* sizeof value length */
880
881    if (!im->private.proto.saved_imvalues) {
882	*idx = -1;
883	*ret_len = 0;
884	return True;
885    }
886
887    *ret_len = 0;
888    for (i = *idx; i < num; i++) {
889	if (!(res = _XimGetResourceListRecByQuark(res_list,
890						res_num, quark_list[i])))
891	    continue;
892
893	if (!_XimDecodeLocalIMAttr(res, top, value))
894	    return False;
895
896	buf_s = (CARD16 *)buf;
897	if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
898			(size - min_len), value, &len, mode, (XPointer)NULL)))
899	    return False;
900
901	if (len == 0) {
902	    continue;
903	} else if (len < 0) {
904	    *idx = i;
905	    return True;
906	}
907
908	buf_s[0] = res->id;			/* attribute ID */
909	buf_s[1] = len;				/* value length */
910	XIM_SET_PAD(&buf_s[2], len);		/* pad */
911	len += min_len;
912
913	buf += len;
914	*ret_len += len;
915	size -= len;
916    }
917    *idx = -1;
918    return True;
919}
920#endif /* XIM_CONNECTABLE */
921
922Private Bool
923_XimEncodeTopValue(
924    Xic			 ic,
925    XIMResourceList	 res,
926    XIMArg		*p)
927{
928    if (res->xrm_name == XrmStringToQuark(XNClientWindow)) {
929	ic->core.client_window = (Window)p->value;
930	if (ic->core.focus_window == (Window)0)
931	    ic->core.focus_window = ic->core.client_window;
932	_XimRegisterFilter(ic);
933
934    } else if (res->xrm_name == XrmStringToQuark(XNFocusWindow)) {
935	if (ic->core.client_window) {
936	    _XimUnregisterFilter(ic);
937	    ic->core.focus_window = (Window)p->value;
938	    _XimRegisterFilter(ic);
939	} else /* client_window not yet */
940	    ic->core.focus_window = (Window)p->value;
941    }
942    return True;
943}
944
945Private Bool
946_XimEncodePreeditValue(
947    Xic			 ic,
948    XIMResourceList	 res,
949    XIMArg		*p)
950{
951    if (res->xrm_name == XrmStringToQuark(XNStdColormap)) {
952	XStandardColormap	*colormap_ret;
953	int			 count;
954
955	if (!(XGetRGBColormaps(ic->core.im->core.display,
956				ic->core.focus_window, &colormap_ret,
957				&count, (Atom)p->value)))
958	    return False;
959
960	XFree(colormap_ret);
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 = NULL;
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	XFree(colormap_ret);
1013    } else if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
1014	int		  list_ret;
1015	XFontStruct	**struct_list;
1016	char		**name_list;
1017	char		 *tmp;
1018	int		  len;
1019	register int	  i;
1020
1021	if (!p->value)
1022	    return False;
1023
1024	if (ic->private.proto.status_font)
1025	    Xfree(ic->private.proto.status_font);
1026
1027	list_ret = XFontsOfFontSet((XFontSet)p->value,
1028						 &struct_list, &name_list);
1029	for (i = 0, len = 0; i < list_ret; i++) {
1030	     len += (strlen(name_list[i]) + sizeof(char));
1031	}
1032	if (!(tmp = Xmalloc(len+1))) {
1033	    ic->private.proto.status_font = NULL;
1034	    return False;
1035	}
1036
1037	tmp[0] = '\0';
1038	for(i = 0; i < list_ret; i++) {
1039	    strcat(tmp, name_list[i]);
1040	    strcat(tmp, ",");
1041	}
1042	tmp[len - 1] = 0;
1043	ic->private.proto.status_font        = tmp;
1044	ic->private.proto.status_font_length = len - 1;
1045    }
1046    return True;
1047}
1048
1049Private Bool
1050_XimSetInnerICAttributes(
1051    Xic			 ic,
1052    XPointer		 top,
1053    XIMArg		*arg,
1054    unsigned long	 mode)
1055{
1056    XIMResourceList	 res;
1057    int			 check;
1058
1059    if (!(res = _XimGetResourceListRec(ic->private.proto.ic_inner_resources,
1060			ic->private.proto.ic_num_inner_resources, arg->name)))
1061	return False;
1062
1063    check = _XimCheckICMode(res, mode);
1064    if(check == XIM_CHECK_INVALID)
1065	return True;
1066    else if(check == XIM_CHECK_ERROR)
1067	return False;
1068
1069    return _XimEncodeLocalICAttr(ic, res, top, arg, mode);
1070}
1071
1072Public char *
1073_XimEncodeICATTRIBUTE(
1074    Xic			  ic,
1075    XIMResourceList	  res_list,
1076    unsigned int	  res_num,
1077    XIMArg		 *arg,
1078    XIMArg		**arg_ret,
1079    char		 *buf,
1080    int			  size,
1081    int			 *ret_len,
1082    XPointer		  top,
1083    BITMASK32		 *flag,
1084    unsigned long	  mode)
1085{
1086    register XIMArg	*p;
1087    XIMResourceList	 res;
1088    int			 check;
1089    CARD16		*buf_s;
1090    int			 len;
1091    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
1092				 + sizeof(INT16); /* sizeof value length */
1093    XrmQuark		 pre_quark;
1094    XrmQuark		 sts_quark;
1095    char		*name;
1096
1097    pre_quark = XrmStringToQuark(XNPreeditAttributes);
1098    sts_quark = XrmStringToQuark(XNStatusAttributes);
1099
1100    *ret_len = 0;
1101    for (p = arg; p && p->name; p++) {
1102	buf_s = (CARD16 *)buf;
1103	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
1104	    if (_XimSetInnerICAttributes(ic, top, p, mode))
1105		continue;
1106	    return p->name;
1107	}
1108
1109	check = _XimCheckICMode(res, mode);
1110	if (check == XIM_CHECK_INVALID)
1111	    continue;
1112	else if (check == XIM_CHECK_ERROR)
1113	    return p->name;
1114
1115	if (mode & XIM_PREEDIT_ATTR) {
1116	    if (!(_XimEncodePreeditValue(ic, res, p)))
1117		return p->name;
1118	} else if (mode & XIM_STATUS_ATTR) {
1119	    if (!(_XimEncodeStatusValue(ic, res, p)))
1120		return p->name;
1121	} else {
1122	    if (!(_XimEncodeTopValue(ic, res, p)))
1123		return p->name;
1124	}
1125
1126	if (res->resource_size == XimType_NEST) {
1127	    XimDefICValues	*ic_attr = (XimDefICValues *)top;
1128
1129	    if (res->xrm_name == pre_quark) {
1130		XIMArg		*arg_rt;
1131		if ((name = _XimEncodeICATTRIBUTE(ic, res_list, res_num,
1132				(XIMArg *)p->value, &arg_rt,
1133				(char *)&buf_s[2], (size - min_len),
1134				 &len, (XPointer)&ic_attr->preedit_attr, flag,
1135				(mode | XIM_PREEDIT_ATTR)))) {
1136		    return name;
1137		}
1138
1139	    } else if (res->xrm_name == sts_quark) {
1140		XIMArg		*arg_rt;
1141		if ((name = _XimEncodeICATTRIBUTE(ic, res_list, res_num,
1142				(XIMArg *)p->value,  &arg_rt,
1143				(char *)&buf_s[2], (size - min_len),
1144				 &len, (XPointer)&ic_attr->status_attr, flag,
1145				(mode | XIM_STATUS_ATTR)))) {
1146		    return name;
1147		}
1148	    }
1149	} else {
1150#ifdef EXT_MOVE
1151	    if (flag)
1152		*flag |= _XimExtenArgCheck(p);
1153#endif
1154    	    if (!(_XimEncodeLocalICAttr(ic, res, top, p, mode)))
1155		return p->name;
1156
1157	    if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
1158			 	(size - min_len), p->value,
1159				&len, mode, (XPointer)ic)))
1160		return p->name;
1161	}
1162
1163	if (len == 0) {
1164	    continue;
1165	} else if (len < 0) {
1166	    *arg_ret = p;
1167	    return (char *)NULL;
1168	}
1169
1170	buf_s[0] = res->id;			/* attribute ID */
1171	buf_s[1] = len;				/* value length */
1172	XIM_SET_PAD(&buf_s[2], len);		/* pad */
1173	len += min_len;
1174
1175	buf += len;
1176	*ret_len += len;
1177	size -= len;
1178    }
1179    *arg_ret = (XIMArg *)NULL;
1180    return (char *)NULL;
1181}
1182
1183#ifdef XIM_CONNECTABLE
1184Private Bool
1185_XimEncodeSavedPreeditValue(
1186    Xic			  ic,
1187    XIMResourceList	  res,
1188    XPointer		  value)
1189{
1190    int			  list_ret;
1191    XFontStruct		**struct_list;
1192    char		**name_list;
1193    char		 *tmp;
1194    int			  len;
1195    register int	  i;
1196
1197    if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
1198	if (!value)
1199	    return False;
1200
1201	if (ic->private.proto.preedit_font)
1202	    Xfree(ic->private.proto.preedit_font);
1203
1204	list_ret = XFontsOfFontSet((XFontSet)value,
1205						&struct_list, &name_list);
1206	for(i = 0, len = 0; i < list_ret; i++) {
1207	    len += (strlen(name_list[i]) + sizeof(char));
1208	}
1209	if(!(tmp = Xmalloc(len + 1))) {
1210	    ic->private.proto.preedit_font = NULL;
1211	    return False;
1212	}
1213
1214	tmp[0] = '\0';
1215	for(i = 0; i < list_ret; i++) {
1216	    strcat(tmp, name_list[i]);
1217	    strcat(tmp, ",");
1218	}
1219	tmp[len - 1] = 0;
1220	ic->private.proto.preedit_font        = tmp;
1221	ic->private.proto.preedit_font_length = len - 1;
1222    }
1223    return True;
1224}
1225
1226Private Bool
1227_XimEncodeSavedStatusValue(
1228    Xic			  ic,
1229    XIMResourceList	  res,
1230    XPointer		  value)
1231{
1232    int			  list_ret;
1233    XFontStruct		**struct_list;
1234    char		**name_list;
1235    char		 *tmp;
1236    int			  len;
1237    register int	  i;
1238
1239    if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
1240	if (!value)
1241	    return False;
1242
1243	if (ic->private.proto.status_font)
1244	    Xfree(ic->private.proto.status_font);
1245
1246	list_ret = XFontsOfFontSet((XFontSet)value,
1247						&struct_list, &name_list);
1248	for(i = 0, len = 0; i < list_ret; i++) {
1249	    len += (strlen(name_list[i]) + sizeof(char));
1250	}
1251	if(!(tmp = Xmalloc(len + 1))) {
1252	    ic->private.proto.status_font = NULL;
1253	    return False;
1254	}
1255
1256	tmp[0] = '\0';
1257	for(i = 0; i < list_ret; i++) {
1258	    strcat(tmp, name_list[i]);
1259	    strcat(tmp, ",");
1260	}
1261	tmp[len - 1] = 0;
1262	ic->private.proto.status_font        = tmp;
1263	ic->private.proto.status_font_length = len - 1;
1264    }
1265    return True;
1266}
1267
1268Public	Bool
1269_XimEncodeSavedICATTRIBUTE(
1270    Xic			 ic,
1271    XIMResourceList	 res_list,
1272    unsigned int	 res_num,
1273    int			*idx,
1274    char		*buf,
1275    int			 size,
1276    int			*ret_len,
1277    XPointer		 top,
1278    unsigned long	 mode)
1279{
1280    int			 i;
1281    int			 num = ic->private.proto.num_saved_icvalues;
1282    XrmQuark		*quark_list = ic->private.proto.saved_icvalues;
1283    XIMResourceList	 res;
1284    XPointer		 value;
1285    CARD16		*buf_s;
1286    int			 len;
1287    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
1288				 + sizeof(INT16); /* sizeof value length */
1289    XrmQuark		 pre_quark;
1290    XrmQuark		 sts_quark;
1291    XrmQuark		 separator;
1292
1293    if (!ic->private.proto.saved_icvalues) {
1294	*idx = -1;
1295	*ret_len = 0;
1296	return True;
1297    }
1298
1299    pre_quark = XrmStringToQuark(XNPreeditAttributes);
1300    sts_quark = XrmStringToQuark(XNStatusAttributes);
1301    separator = XrmStringToQuark(XNSeparatorofNestedList);
1302
1303    *ret_len = 0;
1304    for (i = *idx; i < num; i++) {
1305	if (quark_list[i] == separator) {
1306	    *idx = i;
1307	    return True;
1308	}
1309
1310	if (!(res = _XimGetResourceListRecByQuark(res_list,
1311						res_num, quark_list[i])))
1312	    continue;
1313
1314	if (!_XimDecodeLocalICAttr(res, top,(XPointer)&value, mode))
1315	    return False;
1316
1317	if (mode & XIM_PREEDIT_ATTR) {
1318	    if (!(_XimEncodeSavedPreeditValue(ic, res, value))) {
1319		return False;
1320	    }
1321	} else if (mode & XIM_STATUS_ATTR) {
1322	    if (!(_XimEncodeSavedStatusValue(ic, res, value))) {
1323		return False;
1324	    }
1325	}
1326
1327	buf_s = (CARD16 *)buf;
1328	if (res->resource_size == XimType_NEST) {
1329	    XimDefICValues	*ic_attr = (XimDefICValues *)top;
1330
1331	    i++;
1332	    if (res->xrm_name == pre_quark) {
1333		if (!_XimEncodeSavedICATTRIBUTE(ic, res_list, res_num,
1334				 &i, (char *)&buf_s[2], (size - min_len),
1335				 &len, (XPointer)&ic_attr->preedit_attr,
1336				(mode | XIM_PREEDIT_ATTR))) {
1337		    return False;
1338		}
1339
1340	    } else if (res->xrm_name == sts_quark) {
1341		if (!_XimEncodeSavedICATTRIBUTE(ic, res_list, res_num,
1342				&i, (char *)&buf_s[2], (size - min_len),
1343				&len, (XPointer)&ic_attr->status_attr,
1344				(mode | XIM_STATUS_ATTR))) {
1345		    return False;
1346		}
1347	    }
1348	} else {
1349	    if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
1350			 	(size - min_len), value,
1351				&len, mode, (XPointer)ic))) {
1352		return False;
1353	    }
1354	}
1355
1356	if (len == 0) {
1357	    continue;
1358	} else if (len < 0) {
1359	    if (quark_list[i] == separator)
1360		i++;
1361	    *idx = i;
1362	    return True;
1363	}
1364
1365	buf_s[0] = res->id;			/* attribute ID */
1366	buf_s[1] = len;				/* value length */
1367	XIM_SET_PAD(&buf_s[2], len);		/* pad */
1368	len += min_len;
1369
1370	buf += len;
1371	*ret_len += len;
1372	size -= len;
1373    }
1374    *idx = -1;
1375    return True;
1376}
1377#endif /* XIM_CONNECTABLE */
1378
1379Private unsigned int
1380_XimCountNumberOfAttr(
1381    INT16	 total,
1382    CARD16	*attr,
1383    int		*names_len)
1384{
1385    unsigned int n;
1386    INT16	 len;
1387    INT16	 min_len = sizeof(CARD16)	/* sizeof attrinute ID */
1388			 + sizeof(CARD16)	/* sizeof type of value */
1389			 + sizeof(INT16);	/* sizeof length of attribute */
1390
1391    n = 0;
1392    *names_len = 0;
1393    while (total > min_len) {
1394	len = attr[2];
1395	*names_len += (len + 1);
1396	len += (min_len + XIM_PAD(len + 2));
1397	total -= len;
1398	attr = (CARD16 *)((char *)attr + len);
1399	n++;
1400    }
1401    return n;
1402}
1403
1404Public Bool
1405_XimGetAttributeID(
1406    Xim			  im,
1407    CARD16		 *buf)
1408{
1409    unsigned int	  n;
1410    XIMResourceList	  res;
1411    int			  res_len;
1412    char		 *names;
1413    int			  names_len;
1414    XPointer		  tmp;
1415    XIMValuesList	 *values_list;
1416    char		**values;
1417    int			  values_len;
1418    register int	  i;
1419    INT16		  len;
1420    INT16		  min_len = sizeof(CARD16) /* sizeof attrinute ID */
1421				  + sizeof(CARD16) /* sizeof type of value */
1422				  + sizeof(INT16); /* sizeof length of attr */
1423    /*
1424     * IM attribute ID
1425     */
1426
1427    if (!(n = _XimCountNumberOfAttr(buf[0], &buf[1], &names_len)))
1428	return False;
1429    res_len = sizeof(XIMResource) * n;
1430
1431    if (!(res = (XIMResourceList)Xmalloc(res_len)))
1432	return False;
1433    bzero((char *)res, res_len);
1434
1435    values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
1436    if (!(tmp = (XPointer)Xmalloc(values_len)))
1437	return False;
1438    bzero(tmp, values_len);
1439
1440    values_list = (XIMValuesList *)tmp;
1441    values = (char **)((char *)tmp + sizeof(XIMValuesList));
1442    names = (char *)((char *)values + (sizeof(char **) * n));
1443
1444    values_list->count_values = n;
1445    values_list->supported_values = values;
1446
1447    buf++;
1448    for (i = 0; i < n; i++) {
1449	len = buf[2];
1450	(void)memcpy(names, (char *)&buf[3], len);
1451	values[i] = names;
1452	names[len] = '\0';
1453	res[i].resource_name = names;
1454	res[i].resource_size = buf[1];
1455	res[i].id	     = buf[0];
1456	names += (len + 1);
1457	len += (min_len + XIM_PAD(len + 2));
1458	buf = (CARD16 *)((char *)buf + len);
1459    }
1460    _XIMCompileResourceList(res, n);
1461
1462    if (im->core.im_resources)
1463	Xfree(im->core.im_resources);
1464    if (im->core.im_values_list)
1465	Xfree(im->core.im_values_list);
1466    im->core.im_resources     = res;
1467    im->core.im_num_resources = n;
1468    im->core.im_values_list   = values_list;
1469
1470    /*
1471     * IC attribute ID
1472     */
1473
1474    if (!(n = _XimCountNumberOfAttr(buf[0], &buf[2], &names_len)))
1475	return False;
1476    res_len = sizeof(XIMResource) * n;
1477
1478    if (!(res = (XIMResourceList)Xmalloc(res_len)))
1479	return False;
1480    bzero((char *)res, res_len);
1481
1482    values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
1483    if (!(tmp = (XPointer)Xmalloc(values_len)))
1484	return False;
1485    bzero(tmp, values_len);
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