1 /*
2  *	convlib2.c -- X11 $B%D!<%k%-%C%HJQ49F~NOMQ%i%$%V%i%j(B
3  *
4  *		ishisone@sra.co.jp
5  */
6 
7 /*
8  * Copyright (c) 1991  Software Research Associates, Inc.
9  *
10  * Permission to use, copy, modify, and distribute this software and its
11  * documentation for any purpose and without fee is hereby granted, provided
12  * that the above copyright notice appear in all copies and that both that
13  * copyright notice and this permission notice appear in supporting
14  * documentation, and that the name of Software Research Associates not be
15  * used in advertising or publicity pertaining to distribution of the
16  * software without specific, written prior permission.  Software Research
17  * Associates makes no representations about the suitability of this software
18  * for any purpose.  It is provided "as is" without express or implied
19  * warranty.
20  *
21  * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
22  */
23 
24 /*
25  * --$B%$%s%?!<%U%'%$%9(B--
26  *
27  * $BMQ0U$5$l$F$$$k%U%!%s%/%7%g%s$O<!$N(B4$B$D(B ($B$=$N$&$A(B1$B$D$O(B backward
28  * compatibility $B$N$?$a(B) $B$@$1$G$"$k!#;DG0$J$,$i(B X11R5 $B$G:N$jF~$l$i$l$kI8(B
29  * $B=`F~NO%$%s%?!<%U%'%$%9(B XIM $B$K$O=>$C$F$$$J$$!#$7$+$7(B Xt $B%D!<%k%-%C%H$r(B
30  * $BMxMQ$9$k%W%m%0%i%`$J$i(B XIM $B$h$j$b$O$k$+$K4JC1$KAH$_9~$`$3$H$,$G$-$k$@(B
31  * $B$m$&!#(B
32  *
33  * int _beginConversionWithAttributes(
34  *	Widget w,		$BJQ49F~NO$r$7$?$$(B widget
35  *	Atom catom,		$B%;%l%/%7%g%s%"%H%`(B eg "_JAPANESE_CONVERSION"
36  *	Atom tatom,		$BJQ49%F%-%9%H%?%$%W(B eg "COMPOUND_TEXT"
37  *	void (*inputproc)(),	$BJQ49%F%-%9%HF~NO%3!<%k%P%C%/4X?t(B
38  *	void (*startendproc)(),	$BJQ493+;O(B / $B=*N;(B / $B%"%\!<%H(B $B%3!<%k%P%C%/4X?t(B
39  *	XtPointer client_data,	$B%3!<%k%P%C%/4X?t$KEO$5$l$k%G!<%?(B
40  *	ArgList attrs,		$BJQ49B0@-%j%9%H(B
41  *	Cardinal nattrs		$BB0@-%j%9%H$N9`L\?t(B
42  *	)
43  *
44  *	$BJQ49$r3+;O$9$k!#$b$C$H@53N$K$$$&$H!"0z?t(B catom $B$K;XDj$5$l$?%;%l(B
45  *	$B%/%7%g%s%"%H%`$N%*!<%J!<(B ($B$3$l$,JQ49%U%m%s%H%(%s%I!"Nc$($P(B
46  *	kinput2 $B$G$"$k(B) $B$rC5$7!"JQ49$N%j%/%(%9%H$rAw$k!#F1;~$K0z?t(B attrs
47  *	$B$G;XDj$5$l$kJQ49B0@-(B ($BNc$($P%+!<%=%k$N0LCV(B) $B$r%U%m%s%H%(%s%I$KDL(B
48  *	$BCN$9$k!#JQ49B0@-$K$D$$$F$O8e$GJL$K@bL@$9$k!#%U%m%s%H%(%s%I$,B8:_(B
49  *	$B$7$J$$;~$K$O(B -1 $B$r!"$=$l0J30$O(B 0 $B$rJV$9!#(B
50  *
51  *	startendproc $B$OJQ49$N>uBV$NJQ2=$r%"%W%j%1!<%7%g%s$KCN$i$;$k$?$a(B
52  *	$B$N%3!<%k%P%C%/$G$"$k!#$3$N%U%!%s%/%7%g%s$O<!$N$h$&$J7A<0$G8F$S=P(B
53  *	$B$5$l$k!#(B
54  *
55  *	(*startendproc)(Widget w, Atom catom, int state,
56  *			XtPointer client_data, Window convwin)
57  *
58  *	w, catom, client_data $B$O(B _beginConversionWithAttributes() $B$G;XDj(B
59  *	$B$7$?$b$N$HF1$8$b$N$,EO$5$l$k!#(Bstate $B$K$O(B3$B<oN`$"$j!"$=$l$>$l(B
60  *		 0: $B%U%m%s%H%(%s%I$,JQ49%j%/%(%9%H$r<u$1IU$1$?(B
61  *		-1: $B%U%m%s%H%(%s%I$,JQ49%j%/%(%9%H$r5qH]$7$?(B
62  *		 1: $BJQ49$,=*N;$7$?(B
63  *	$B$H$$$&$3$H$rI=$9!#(Bstate $B$,(B 0 $B$N;~!"(Bconvwin $B$K$O<B:]$KJQ49=hM}(B
64  *	$B$,9T$J$o$l$k%&%#%s%I%&$N(B ID $B$,F~$k!#$3$l$O(B eventCaptureMethod
65  *	$B$r(B "none" $B$K$7$F%/%i%$%"%s%H$KMh$?%-!<%$%Y%s%H$r%U%m%s%H%(%s%I(B
66  *	$B$K%U%)%o!<%I$9$k;~$J$I$K;HMQ$5$l$k!#(B
67  *
68  *	$B:F$S(B _beginConversionWithAttributes() $B$N0z?t$N@bL@$KLa$C$F(Btatom
69  *	$B$O%U%m%s%H%(%s%I$+$iAw$i$l$F$/$kJ8;zNs$N%(%s%3!<%G%#%s%0$N;XDj$G(B
70  *	$B$"$k!#(B
71  *	kinput2 $B%W%m%H%3%k$G$O!"%U%m%s%H%(%s%I$KBP$7$F(B COMPOUND_TEXT$B%(%s(B
72  *	$B%3!<%G%#%s%0$r%5%]!<%H$9$k$3$H$7$+5a$a$F$$$J$$$N$G!"B>$N%(%s%3!<(B
73  *	$B%G%#%s%0$r%5%]!<%H$9$k$+$I$&$+$O%U%m%s%H%(%s%I$N%$%s%W%j%a%s%F!<(B
74  *	$B%7%g%s$K0MB8$9$k!#=>$C$F(B COMPOUNT_TEXT $B0J30$N%(%s%3!<%G%#%s%0$r(B
75  *	$B;XDj$9$k$H!"<B:]$KAw$i$l$F$/$kJ8;zNs$N%(%s%3!<%G%#%s%0$,;XDj$7$?(B
76  *	$B$b$N$H0[$J$k$3$H$b$"$jF@$k$N$GCm0U$9$k$3$H!#(B
77  *
78  *	$B3NDjJ8;zNs$,JQ49%U%m%s%H%(%s%I$+$iAw$i$l$F$/$k$H(B inputproc $B$K;X(B
79  *	$BDj$5$l$?%3!<%k%P%C%/%U%!%s%/%7%g%s$,<!$N$h$&$J7A<0$G8F$P$l$k!#(B
80  *
81  *	(*inputproc)(Widget w, Atom catom,
82  *			Atom proptype, int propformat,
83  *			unsigned long propsize, unsigned char *propvalue,
84  *			XtPointer client_data)
85  *
86  *	w $B$H(B catom$B!"$=$l$K(B client_data $B$O(B
87  *	_beginConversionWithAttributes() $B$G;XDj$7$?$b$N$G$"$k!#(B
88  *
89  *	proptype $B$OJ8;zNs$N%(%s%3!<%G%#%s%0!"(Bpropformat $B$O(B1$BJ8;z$N%S%C%H(B
90  *	$BD9!"(Bpropsize $B$,D9$5!"$=$7$F(B propvalue $B$K<B:]$NJ8;zNs%G!<%?$,F~$C(B
91  *	$B$F$$$k!#<B$OJ8;zNs$O%U%m%s%H%(%s%I$+$i(B X $B$N%&%#%s%I%&%W%m%Q%F%#(B
92  *	$B$H$7$FEO$5$l$F$*$j!"$3$l$i$N%Q%i%a!<%?$O$=$N%W%m%Q%F%#$N%Q%i%a!<(B
93  *	$B%?$=$N$b$N$G$"$k!#=>$C$F(B XGetWindowProperty() $B$N@bL@$r;2>H$9$k$H(B
94  *	$B3F%Q%i%a!<%?$N0UL#$,$O$C$-$j$o$+$k$@$m$&!#(B
95  *
96  * void _changeConversionAttributes(
97  *	Widget	w,
98  *	Atom catom,		$B%;%l%/%7%g%s%"%H%`(B eg "_JAPANESE_CONVERSION"
99  *	ArgList attrs,		$BJQ49B0@-%j%9%H(B
100  *	Cardinal nattrs		$BB0@-%j%9%H$N9`L\?t(B
101  *	)
102  *
103  *	$BJQ49Cf$KJQ49B0@-$rJQ2=$5$;$k!#Nc$($P%+!<%=%k0LCV$,JQ$o$C$?$H$-$K(B
104  *	$B$3$N%U%!%s%/%7%g%s$G$=$l$r%U%m%s%H%(%s%I$KCN$i$;$k$3$H$,$G$-$k!#(B
105  *
106  * void _endConversion(
107  *	Widget w,
108  *	Atom catom,		$B%;%l%/%7%g%s%"%H%`(B eg "_JAPANESE_CONVERSION"
109  *	Boolean throwaway	$B$3$N8eMh$?JQ497k2L$r<u$1$H$k$+$I$&$+(B
110  *	)
111  *
112  *	$BJQ49$r=*N;$5$;$k!#DL>o!"JQ49$N=*N;$OJQ49%U%m%s%H%(%s%I$,9T$J$&$N(B
113  *	$B$GFC$K%"%W%j%1!<%7%g%s$+$i$3$N%U%!%s%/%7%g%s$r;H$C$F6/@)E*$K=*N;(B
114  *	$B$5$;$kI,MW$O$J$$!#(B
115  *	$B0z?t(B throwaway $B$,(B True $B$@$H$3$N%U%!%s%/%7%g%s$r<B9T$7$?8e$K%U%m(B
116  *	$B%s%H%(%s%I$+$iAw$i$l$?J8;zNs$rL5;k$9$k!#(B
117  *
118  * void _beginConversion(	-- provided for backward compatibility
119  *	Widgete w,		$BJQ49F~NO$r$7$?$$(B widget
120  *	Atom catom,		$B%;%l%/%7%g%s%"%H%`(B eg "_JAPANESE_CONVERSION"
121  *	Atom tatom,		$BJQ49%F%-%9%H%?%$%W(B eg "COMPOUND_TEXT"
122  *	void (*inputproc)(),	$BJQ49%F%-%9%HF~NO%3!<%k%P%C%/4X?t(B
123  *	XtPointer client_data	$B%3!<%k%P%C%/4X?t$KEO$5$l$k%G!<%?(B
124  *	)
125  *
126  *	$B$3$l$O(B backward compatibility $B$N$?$a$KMQ0U$5$l$?%U%!%s%/%7%g%s$G(B
127  *	$B$"$k!#$3$N%U%!%s%/%7%g%s$G$OJQ49B0@-$N;XDj$,0l@Z$G$-$J$$$7!"JQ49(B
128  *	$B>uBV$NJQ2=$bCN$k$3$H$,$G$-$J$$$N$G!"$G$-$k$@$1(B
129  *	_beginConversionWithAttributes() $B$rMQ$$$k$N$,K>$^$7$$!#(B
130  *
131  *
132  * --$B%;%l%/%7%g%s%"%H%`(B--
133  *
134  * _beginConversionWithAttributes() $B$J$I$K;XDj$9$k%;%l%/%7%g%s%"%H%`$O(B
135  * $BF~NO$7$?$$8@8l$K$h$C$F0[$J$j!"<!$N$h$&$JL>A0$K$J$C$F$$$k!#(B
136  *	"_<$B8@8lL>(B>_CONVERSION"
137  * $BNc$($PF|K\8l$N>l9g$O(B "_JAPANESE_CONVERSION" $B$G$"$k!#(B
138  *
139  *
140  * --$BJQ49B0@-%j%9%H(B--
141  *
142  * $BJQ49B0@-$O(B XtSetValues() $B$J$I$G;HMQ$5$l$k%j%9%H$HF1$87A(B (ArgList) $B$G$"$k!#(B
143  * $BB0@-$H$7$F;XDj$G$-$k$N$O<!$N9`L\$G$"$k!#4pK\E*$K$3$l$i$NB0@-$O(B XIM $B$N(B
144  * $B;EMM$G$NDj5A$r$=$N$^$^:NMQ$7$F$$$k$N$G!"5?LdE@$,$"$l$P(B XIM $B$N%I%-%e%a%s%H$r(B
145  * $B;2>H$7$F$[$7$$!#(B
146  *
147  * "inputStyle" : $BCM(B String
148  *	$BF~NO%9%?%$%k$r;XDj$9$k!#CM$O(B
149  *		"root" (root window style):	$BJL%&%#%s%I%&$K$h$kJQ49(B
150  *		"off" (off-the-spot style):	$B;XDj$7$?JQ49NN0hFb$G$NJQ49(B
151  *		"over" (over-the-spot style):	$B$=$N>lJQ49(B
152  *	$B$N$I$l$+$NJ8;zNs$r;XDj$9$k!#(B
153  *
154  * "focusWindow" : $BCM(B Window
155  *	$BJQ49$r9T$J$&%&%#%s%I%&$r;XDj$9$k!#$3$l$,;XDj$5$l$?$J$+$C$?>l9g$K(B
156  *	$B$O(B _beginConversionWithAttributes() $B$G;XDj$7$?(B Widget $B$N%&%#%s%I(B
157  *	$B%&$,;H$o$l$k$N$GDL>o$O;XDj$7$J$/$F$h$$!#(B
158  *
159  * "spotX", "spotY" : $BCM(B Position
160  *	$B%9%]%C%H%m%1!<%7%g%s$r;XDj$9$k!#$3$l$OF~NO%9%?%$%k$,(B
161  *	over-the-spot $B$N;~$N$_M-8z$G$"$k!#J8;z$r=q$-;O$a$k0LCV$r;XDj$9$k(B
162  *	$B$,!"(BspotY $B$O%Y!<%9%i%$%s$N0LCV$G$"$k$3$H$KCm0U!#(B
163  *	spotX$B!"(BspotY $B$N$&$AJRJ}$@$1;XDj$7$F$bL58z!#(B
164  *
165  * "foreground", "background" : $BCM(B Pixel
166  *	$BA07J?'!"GX7J?'$r;XDj$9$k!#$3$l$bJRJ}$@$1;XDj$7$F$bL58z!#(B
167  *
168  * "eventCaptureMethod" : $BCM(B String
169  *	$B%U%m%s%H%(%s%I$,$I$N$h$&$KF~NO%$%Y%s%H$r$H$k$+$r;XDj$9$k!#(B
170  *		"none"		$B2?$b$7$J$$(B
171  *		"inputOnly"	InputOnly $B%&%#%s%I%&$K$h$k(B
172  *		"focusSelect"	$B%U%)!<%+%9%&%#%s%I%&$N%$%Y%s%H$rD>@\(B
173  *				$B%;%l%/%H$9$k(B
174  *	$B$G$"$k!#(B
175  *
176  *	"$B2?$b$7$J$$(B" $B$r;XDj$7$?>l9g!"%"%W%j%1!<%7%g%s$OJQ49Cf$K%"%W%j%1!<(B
177  *	$B%7%g%s$KMh$?%$%Y%s%H$r%U%m%s%H%(%s%I$KEO$7$F(B (XSendEvent() $B$r;H(B
178  *	$B$&(B) $B$d$i$J$1$l$P$J$i$J$$!#$3$N%$%Y%s%H$N%U%)%o!<%I:n6H$O$3$N%i%$(B
179  *	$B%V%i%j$G$O%5%]!<%H$7$F$$$J$$!#=>$C$F(B "$B2?$b$7$J$$(B" $B$r;XDj$9$k$3$H(B
180  *	$B$O$"$^$j$*4+$a$7$J$$!#(B
181  *
182  *	"$B%U%)!<%+%9%&%#%s%I%&$N%$%Y%s%H$rD>@\%;%l%/%H$9$k(B" $B>l9g!"%"%W%j(B
183  *	$B%1!<%7%g%s$OJQ49Cf$O(B sendevent $B%U%i%0$NN)$C$F$$$J$$%-!<%$%Y%s%H(B
184  *	$B$rL5;k$7$J$/$F$O$J$i$J$$!#(Bsendevent $B%U%i%0$NN)$C$?%-!<%$%Y%s%H$O(B
185  *	$B%U%m%s%H%(%s%I$+$iLa$5$l$?%$%Y%s%H$G$"$k2DG=@-$,$"$j!"$3$l$OL5;k(B
186  *	$B$7$J$/$F$bNI$$$,!"EvA3$N$3$H$J$,$i%;%-%e%j%F%#$K$O5$$r$D$1$J$/$F(B
187  *	$B$O$J$i$J$$!#(B
188  *
189  *	"InputOnly $B%&%#%s%I%&$K$h$k(B" $B$r;XDj$9$k$H%U%m%s%H%(%s%I$O%/%i%$(B
190  *	$B%"%s%H$N%&%#%s%I%&(B ($B$3$l$O%U%)!<%+%9%&%#%s%I%&$G$O$J$/!"(B
191  *	_beginConversionWithAttributes() $B$G;XDj$7$?(B Widget $B$N%&%#%s%I%&(B
192  *	$B$G$"$k(B) $B$NA0$KF)L@$J%&%#%s%I%&$r:n$j!"$=$3$KMh$?%$%Y%s%H$r2#<h$j(B
193  *	$B$9$k!#$3$N>l9g%$%Y%s%H$O%U%m%s%H%(%s%I$,>!<j$K$H$C$F$7$^$&$N$G%"(B
194  *	$B%W%j%1!<%7%g%s$O%$%Y%s%H$K4X$7$F2?$b9M$($J$/$F$h$$!#=>$C$FJ}K!$H(B
195  *	$B$7$F$O$3$l$,0lHV4JC1$G$"$k!#$7$+$7$J$,$iNc$($P(B click-to-type $B7A(B
196  *	$B<0$N%&%#%s%I%&%^%M!<%8%c$r;H$C$?$j$7$F%-!<F~NO$N%U%)!<%+%9$,@_Dj(B
197  *	$B$5$l$F$$$k>l9g$K$O$&$^$/$$$+$J$$!#(B
198  *
199  * "lineSpacing" : $BCM(B int
200  *	$B9T4V3V$r;XDj$9$k!#%Y!<%9%i%$%s4V$N5wN%$r;XDj$9$k!#(B
201  *
202  * "clientArea" : $BCM(B XRectangle $B$X$N%]%$%s%?(B
203  *	$BJQ49%F%-%9%H$NI=<($K;HMQ$9$kNN0h$r;XDj$9$k!#(B
204  *
205  * "statusArea" : $BCM(B XRectangle $B$X$N%]%$%s%?(B
206  *	$B%b!<%II=<($K;HMQ$9$kNN0h$r;XDj$9$k!#(B
207  *
208  * "cursor" : $BCM(B Cursor
209  *	$B;HMQ$9$k%+!<%=%k(B ($B%^%&%9%+!<%=%k$M(B) $B$r;XDj$9$k!#(B
210  *
211  * "fonts" : $BCM(B NULL $B%?!<%_%M!<%H$5$l$?(B XFontStruct * $B$NG[Ns(B
212  *	$B;HMQ$9$k%U%)%s%H$r;XDj$9$k!#=gHV$O$I$&$G$b$h$$!#%U%m%s%H%(%s%IB&(B
213  *	$B$GH=CG$9$k!#$?$@$7(B XLFD $B$K=>$o$J$$%U%)%s%H$r;XDj$5$l$k$H!"%U%m%s(B
214  *	$B%H%(%s%I$G$=$N%-%c%i%/%?%;%C%H$,$o$+$i$:!"$=$N%U%)%s%H$,;H$o$l$J(B
215  *	$B$$$3$H$,$"$k!#(B
216  *
217  * $B>e5-$NB0@-$N$&$A!"(BinputStyle $B$H(B eventCaptureMethod $B$OJQ49ESCf$G(B ($B$D$^$j(B
218  * _changeConversionAttributes() $B$G(B) $BJQ99$9$k$3$H$O$G$-$J$$!#(B
219  */
220 
221 #ifndef lint
222 static char	*rcsid = "$Id: convlib2.c,v 1.12 1994/06/03 09:13:19 ishisone Rel $";
223 #endif
224 
225 #include <X11/StringDefs.h>
226 #include <X11/Intrinsic.h>
227 #include <X11/Xutil.h>
228 #include <X11/Xatom.h>
229 #include "ConvProto.h"
230 
231 typedef struct {
232     Display	*display;
233     Atom	profileAtom;	/* "_CONVERSION_PROFILE" */
234     Atom	typeAtom;	/* "_CONVERSION_ATTRIBUTE_TYPE" */
235     Atom	versionAtom;	/* "PROTOCOL-2.0" */
236     Atom	reqAtom;	/* "CONVERSION_REQUEST" */
237     Atom	notifyAtom;	/* "CONVERSION_NOTIFY" */
238     Atom	endAtom;	/* "CONVERSION_END" */
239     Atom	endReqAtom;	/* "CONVERSION_END_REQUEST" */
240     Atom	attrAtom;	/* "CONVERSION_ATTRIBUTE" */
241     Atom	attrNotifyAtom;	/* "CONVERSION_ATTRIBUTE_NOTIFY" */
242 } ConversionAtoms;
243 
244 typedef struct {
245     Atom	convatom;
246     Window	convowner;
247     Atom	property;
248     void	(*inputproc)();
249     void	(*startendproc)();
250     XtPointer	closure;
251 } ConversionContext;
252 
253 static XContext	convertPrivContext;
254 
255 #if __STDC__
256 /* function prototype */
257 static void callStart(Widget, ConversionContext *, Window);
258 static void callFail(Widget, ConversionContext *);
259 static void callEnd(Widget, ConversionContext *);
260 static long getInputStyle(String);
261 static long getCaptureMethod(String);
262 static ConversionAtoms *getAtoms(Widget);
263 static ConversionContext *getConversionContext(Widget);
264 static void recvConvAck(Widget, XtPointer, XEvent *, Boolean *);
265 static void getConv(Widget, XtPointer, XEvent *, Boolean *);
266 static Boolean setConvAttrProp(Widget, ArgList, Cardinal, Atom);
267 static int makeAttrData(Widget, ArgList, Cardinal, unsigned long **);
268 static Boolean checkProtocols(Display *, Window, ConversionAtoms *);
269 #else
270 static void callStart();
271 static void callFail();
272 static void callEnd();
273 static long getInputStyle();
274 static long getCaptureMethod();
275 static ConversionAtoms *getAtoms();
276 static ConversionContext *getConversionContext();
277 static void recvConvAck();
278 static void getConv();
279 static Boolean setConvAttrProp();
280 static int makeAttrData();
281 static Boolean checkProtocols();
282 #endif
283 
284 static void
callStart(w,context,convwin)285 callStart(w, context, convwin)
286 Widget w;
287 ConversionContext *context;
288 Window convwin;
289 {
290     if (context->startendproc != NULL) {
291 	(*context->startendproc)(w, context->convatom,
292 				 0, context->closure, convwin);
293     }
294 }
295 
296 static void
callFail(w,context)297 callFail(w, context)
298 Widget w;
299 ConversionContext *context;
300 {
301     if (context->startendproc != NULL) {
302 	(*context->startendproc)(w, context->convatom,
303 				 -1, context->closure, None);
304     }
305 }
306 
307 static void
callEnd(w,context)308 callEnd(w, context)
309 Widget w;
310 ConversionContext *context;
311 {
312     if (context->startendproc != NULL) {
313 	(*context->startendproc)(w, context->convatom,
314 				 1, context->closure, None);
315     }
316 }
317 
318 static long
getInputStyle(s)319 getInputStyle(s)
320 String s;
321 {
322     String p;
323     char buf[64];
324 
325     (void)strcpy(buf, s);
326     for (p = buf; *p != '\0'; p++) {
327 	if ('A' <= *p && *p <= 'Z') *p += 'a' - 'A';
328     }
329     if (!strcmp(buf, "over")) return CONVARG_OVERTHESPOT;
330     if (!strcmp(buf, "off")) return CONVARG_OFFTHESPOT;
331     return CONVARG_ROOTWINDOW;
332 }
333 
334 static long
getCaptureMethod(s)335 getCaptureMethod(s)
336 String s;
337 {
338     String p;
339     char buf[64];
340 
341     (void)strcpy(buf, s);
342     for (p = buf; *p != '\0'; p++) {
343 	if ('A' <= *p && *p <= 'Z') *p += 'a' - 'A';
344     }
345     if (!strcmp(buf, "none")) return CONVARG_NONE;
346     if (!strcmp(buf, "focusselect")) return CONVARG_SELECT_FOCUS_WINDOW;
347     return CONVARG_CREATE_INPUTONLY;
348 }
349 
350 static ConversionAtoms *
getAtoms(w)351 getAtoms(w)
352 Widget	w;
353 {
354     int i;
355     Display *disp = XtDisplay(w);
356     ConversionAtoms *cap;
357     static ConversionAtoms *convatomp;
358     static Cardinal ndisp = 0;
359 #define nalloc	2
360 
361     /*
362      * $B%"%H%`$O%G%#%9%W%l%$$4$H$K0c$&$N$G!"(B
363      * $B%G%#%9%W%l%$$4$H$K:n$i$J$/$F$O$J$i$J$$(B
364      */
365 
366     /* $B$9$G$K%"%H%`$,:n$i$l$F$$$k$+$I$&$+D4$Y$k(B */
367     cap = convatomp;
368     for (i = 0; i < ndisp; i++, cap++) {
369 	if (cap->display == disp) return cap;
370     }
371 
372     /*
373      * $B$^$@:n$i$l$F$$$J$$$N$G?7$7$/:n$k(B
374      */
375     if (ndisp == 0) {
376 	/* $B:G=i$J$N$G(B Context $B$bF1;~$K:n$k(B */
377 	convertPrivContext = XUniqueContext();
378 	convatomp = (ConversionAtoms *)
379 	  XtMalloc(sizeof(ConversionAtoms) * nalloc);
380 	cap = convatomp;
381     } else if (ndisp % nalloc == 0) {
382 	/* $B%5%$%:$rA}$d$9(B */
383 	convatomp = (ConversionAtoms *)
384 	  XtRealloc((char *)convatomp,
385 		    sizeof(ConversionAtoms) * (ndisp + nalloc));
386 	cap = convatomp + ndisp;
387     } else {
388 	cap = convatomp + ndisp;
389     }
390 
391     /* $B%G%#%9%W%l%$$NEPO?(B */
392     cap->display = disp;
393 
394     /* Atom $B$N:n@.(B */
395     cap->profileAtom = XInternAtom(disp, CONVERSION_PROFILE, False);
396     cap->typeAtom = XInternAtom(disp, CONVERSION_ATTRIBUTE_TYPE, False);
397     cap->versionAtom = XInternAtom(disp, PROTOCOL_VERSION, False);
398     cap->reqAtom = XInternAtom(disp, "CONVERSION_REQUEST", False);
399     cap->notifyAtom = XInternAtom(disp, "CONVERSION_NOTIFY", False);
400     cap->endAtom = XInternAtom(disp, "CONVERSION_END", False);
401     cap->endReqAtom = XInternAtom(disp, "CONVERSION_END_REQUEST", False);
402     cap->attrAtom = XInternAtom(disp, "CONVERSION_ATTRIBUTE", False);
403     cap->attrNotifyAtom = XInternAtom(disp, "CONVERSION_ATTRIBUTE_NOTIFY", False);
404 
405     ndisp++;
406 
407     return cap;
408 }
409 
410 static ConversionContext *
getConversionContext(w)411 getConversionContext(w)
412 Widget	w;
413 {
414     ConversionContext *context;
415 
416     if (XFindContext(XtDisplay(w), XtWindow(w),
417 		     convertPrivContext, (caddr_t *)&context)) {
418 	/* error -- $BB?J,%3%s%F%-%9%H$,8+$D$+$i$J$+$C$?$?$a(B */
419 	return NULL;
420     } else {
421 	return context;
422     }
423 }
424 
425 /* ARGSUSED */
426 static void
recvConvAck(w,closure,ev,junk)427 recvConvAck(w, closure, ev, junk)
428 Widget	w;
429 XtPointer	closure;
430 XEvent	*ev;
431 Boolean	*junk;	/* NOTUSED */
432 {
433     XClientMessageEvent *cev = &(ev->xclient);
434     ConversionAtoms *cap;
435     ConversionContext *context;
436 
437     if (ev->type != ClientMessage) return;
438 
439     cap = getAtoms(w);
440     context = getConversionContext(w);
441 
442     /* $B@5$7$$%$%Y%s%H$+$I$&$+%A%'%C%/$9$k(B */
443     if (cev->window != XtWindow(w) ||
444 	cev->message_type != cap->notifyAtom ||
445 	cev->data.l[0] != context->convatom) {
446 	return;
447     }
448 
449     /*
450      * $B$3$N%O%s%I%i$O$b$&MQ:Q$_$J$N$G30$9(B
451      */
452     XtRemoveEventHandler(w, NoEventMask, True, recvConvAck, closure);
453 
454     if (cev->data.l[2] == None) {
455 	XtWarning("selection request failed");
456 	XDeleteContext(XtDisplay(w), XtWindow(w), convertPrivContext);
457 	callFail(w, context);
458 	XtFree((char *)context);
459 	return;
460     }
461 
462     callStart(w, context, (Window)cev->data.l[3]);
463 
464     /*
465      * PropertyNotify $B$H(B CONVERSION_END $BMQ$N%$%Y%s%H%O%s%I%i$r(B
466      * $BEPO?$9$k(B
467      */
468     XtAddEventHandler(w, PropertyChangeMask, True, getConv, closure);
469 
470     /* $B%W%m%Q%F%#L>$r%9%H%"$9$k(B */
471     context->property = cev->data.l[2];
472 }
473 
474 /* ARGSUSED */
475 static void
getConv(w,closure,ev,junk)476 getConv(w, closure, ev, junk)
477 Widget	w;
478 XtPointer	closure;
479 XEvent	*ev;
480 Boolean	*junk;	/* NOTUSED */
481 {
482     ConversionAtoms *cap;
483     ConversionContext *context;
484 
485     /* PropertyNotify $B$H(B ClientMessage $B0J30$OL5;k$9$k(B */
486     if (ev->type != PropertyNotify && ev->type != ClientMessage) return;
487 
488     cap = getAtoms(w);
489     context = getConversionContext(w);
490 
491     if (ev->type == ClientMessage) {
492 	XClientMessageEvent *cev = &(ev->xclient);
493 
494 	/*
495 	 * $BK\Ev$KF~NO=*N;$N%$%Y%s%H$+$I$&$+%A%'%C%/$9$k(B
496 	 */
497 	if (cev->message_type == cap->endAtom &&
498 	    cev->format == 32 &&
499 	    cev->data.l[0] == context->convatom) {
500 	    /* $B%&%#%s%I%&$N%3%s%F%-%9%H$r:o=|$9$k(B */
501 	    XDeleteContext(XtDisplay(w), XtWindow(w),
502 			   convertPrivContext);
503 	    /* $B%$%Y%s%H%O%s%I%i$r30$9(B */
504 	    XtRemoveEventHandler(w, PropertyChangeMask, True,
505 				 getConv, closure);
506 	    callEnd(w, context);
507 	    XtFree((char *)context);
508 	}
509     } else {			/* PropertyNotify */
510 	XPropertyEvent *pev = &(ev->xproperty);
511 	Atom proptype;
512 	int propformat;
513 	unsigned long propsize, rest;
514 	unsigned char *propvalue;
515 
516 	if (context->property == None) return;
517 
518 	/* $B@5$7$$%$%Y%s%H$+$I$&$+$N%A%'%C%/(B */
519 	if (pev->window != XtWindow(w) ||
520 	    pev->atom != context->property ||
521 	    pev->state != PropertyNewValue) {
522 	    return;
523 	}
524 
525 	/* $B$b$7%3!<%k%P%C%/4X?t(B context->inputproc $B$,(B
526 	 * NULL $B$J$i$P%W%m%Q%F%#$r:o=|$9$k$@$1(B
527 	 */
528 	if (context->inputproc == NULL) {
529 	    XDeleteProperty(XtDisplay(w), XtWindow(w), context->property);
530 	    return;
531 	}
532 
533 	/* $B%W%m%Q%F%#$+$iJQ49J8;zNs$r<h$j=P$9(B */
534 	XGetWindowProperty(XtDisplay(w), XtWindow(w),
535 			   context->property,
536 			   0L, 100000L, True, AnyPropertyType,
537 			   &proptype, &propformat, &propsize, &rest,
538 			   &propvalue);
539 
540 	/* $B%W%m%Q%F%#$N%?%$%W!&%U%)!<%^%C%H$N%A%'%C%/(B */
541 	if (proptype == None) {
542 	    /* $B%W%m%Q%F%#$,B8:_$7$J$+$C$?(B
543 	     * $B$3$l$OO"B3$7$F2?2s$b%W%m%Q%F%#$K%G!<%?$,(B
544 	     * $BF~$l$i$l$?;~!"0l2s$N(B GetWindowProperty $B$G(B
545 	     * $BJ#?t$N%G!<%?$r$H$C$F$7$^$C$?$"$H$K5/$-$k(B
546 	     * $B=>$C$F$3$l$O%(%i!<$G$O$J$$(B
547 	     */
548 	    return;
549 	}
550 
551 	/* $B%3!<%k%P%C%/$r8F$V(B */
552 	(*context->inputproc)(w, context->convatom,
553 			      proptype, propformat,
554 			      propsize, propvalue,
555 			      context->closure);
556     }
557 }
558 
559 static Boolean
setConvAttrProp(w,attrs,nattrs,prop)560 setConvAttrProp(w, attrs, nattrs, prop)
561 Widget w;
562 ArgList attrs;
563 Cardinal nattrs;
564 Atom prop;
565 {
566     unsigned long *data;
567     int len;
568 
569     if ((len = makeAttrData(w, attrs, nattrs, &data)) > 0) {
570 	XChangeProperty(XtDisplay(w), XtWindow(w),
571 			prop, prop, 32,
572 			PropModeReplace, (unsigned char *)data, len);
573 	XtFree((char *)data);
574 	return True;
575     }
576     return False;
577 }
578 
579 static int
makeAttrData(w,args,nargs,datap)580 makeAttrData(w, args, nargs, datap)
581 Widget w;
582 ArgList args;
583 Cardinal nargs;
584 unsigned long **datap;
585 {
586     unsigned long *data;
587     Cardinal len;
588     Boolean spotx_specified = False, spoty_specified = False;
589     Boolean fore_specified = False, back_specified = False;
590     Pixel savedfg, savedbg;
591     Position savedx, savedy;
592 
593 #define ALLOC(n) \
594     data = (unsigned long *)XtRealloc((char *)data, \
595 				      sizeof(unsigned long)*(len+(n)))
596 
597     data = NULL;
598     len = 0;
599     while (nargs-- > 0) {
600 	if (!strcmp(args->name, "spotX")) {
601 	    savedx = (Position)args->value;
602 	    spotx_specified = True;
603 	} else if (!strcmp(args->name, "spotY")) {
604 	    savedy = (Position)args->value;
605 	    spoty_specified = True;
606 	} else if (!strcmp(args->name, "foreground")) {
607 	    savedfg = (Pixel)args->value;
608 	    fore_specified = True;
609 	} else if (!strcmp(args->name, "background")) {
610 	    savedbg = (Pixel)args->value;
611 	    back_specified = True;
612 	} else if (!strcmp(args->name, "focusWindow")) {
613 	    Window win = (Window)args->value;
614 	    ALLOC(2);
615 	    data[len] = CONV_ATTR(CONVATTR_FOCUS_WINDOW, 1);
616 	    data[len + 1] = (unsigned long)win;
617 	    len += 2;
618 	} else if (!strcmp(args->name, "inputStyle")) {
619 	    long style = getInputStyle((String)args->value);
620 	    ALLOC(2);
621 	    data[len] = CONV_ATTR(CONVATTR_INPUT_STYLE, 1);
622 	    data[len + 1] = style;
623 	    len += 2;
624 	} else if (!strcmp(args->name, "eventCaptureMethod")) {
625 	    long method = getCaptureMethod((String)args->value);
626 	    ALLOC(2);
627 	    data[len] = CONV_ATTR(CONVATTR_EVENT_CAPTURE_METHOD, 1);
628 	    data[len + 1] = method;
629 	    len += 2;
630 	} else if (!strcmp(args->name, "lineSpacing")) {
631 	    int spacing = (int)args->value;
632 	    ALLOC(2);
633 	    data[len] = CONV_ATTR(CONVATTR_LINE_SPACING, 1);
634 	    data[len + 1] = spacing;
635 	    len += 2;
636 	} else if (!strcmp(args->name, "clientArea")) {
637 	    XRectangle *rectp = (XRectangle *)args->value;
638 	    ALLOC(3);
639 	    data[len] = CONV_ATTR(CONVATTR_CLIENT_AREA, 2);
640 	    data[len + 1] = (rectp->x << 16) | (rectp->y & 0xffff);
641 	    data[len + 2] = (rectp->width << 16) | (rectp->height & 0xffff);
642 	    len += 3;
643 	} else if (!strcmp(args->name, "statusArea")) {
644 	    XRectangle *rectp = (XRectangle *)args->value;
645 	    ALLOC(3);
646 	    data[len] = CONV_ATTR(CONVATTR_STATUS_AREA, 2);
647 	    data[len + 1] = (rectp->x << 16) | (rectp->y & 0xffff);
648 	    data[len + 2] = (rectp->width << 16) | (rectp->height & 0xffff);
649 	    len += 3;
650 	} else if (!strcmp(args->name, "cursor")) {
651 	    Cursor cursor = (Cursor)args->value;
652 	    ALLOC(2);
653 	    data[len] = CONV_ATTR(CONVATTR_CURSOR, 1);
654 	    data[len + 1] = cursor;
655 	    len += 2;
656 	} else if (!strcmp(args->name, "fonts")) {
657 	    XFontStruct **fontp = (XFontStruct **)args->value;
658 	    int nfonts, nrealfonts;
659 	    int i;
660 
661 	    for (nfonts = 0; fontp[nfonts] != NULL; nfonts++)
662 	        ;
663 	    ALLOC(nfonts + 1);
664 	    nrealfonts = 0;
665 	    for (i = 0; i < nfonts; i++) {
666 		unsigned long atom;
667 		if (XGetFontProperty(fontp[i], XA_FONT, &atom)) {
668 		    data[len + ++nrealfonts] = atom;
669 		}
670 	    }
671 	    data[len] = CONV_ATTR(CONVATTR_FONT_ATOMS, nrealfonts);
672 	    len += nrealfonts + 1;
673 	} else {
674 	    String params[1];
675 	    Cardinal num_params;
676 
677 	    params[0] = args->name;
678 	    XtAppWarningMsg(XtWidgetToApplicationContext(w),
679 			    "conversionError", "invalidResource",
680 			    "ConversionLibraryError",
681 			    "_beginConversionWithAttributes: unknown resource %s",
682 			    params, &num_params);
683 	}
684 	args++;
685     }
686     if (spotx_specified && spoty_specified) {
687 	ALLOC(2);
688 	data[len] = CONV_ATTR(CONVATTR_SPOT_LOCATION, 1);
689 	data[len + 1] = (savedx << 16) | (savedy & 0xffff);
690 	len += 2;
691     }
692     if (fore_specified && back_specified) {
693 	ALLOC(3);
694 	data[len] = CONV_ATTR(CONVATTR_COLOR, 2);
695 	data[len + 1] = savedfg;
696 	data[len + 2] = savedbg;
697 	len += 3;
698     }
699     *datap = data;
700     return len;
701 #undef ALLOC
702 }
703 
704 static Boolean
checkProtocols(dpy,window,cap)705 checkProtocols(dpy, window, cap)
706 Display *dpy;
707 Window window;
708 ConversionAtoms *cap;
709 {
710     Atom type;
711     int format;
712     unsigned long nitems;
713     unsigned long bytesafter;
714     unsigned long *data, *saveddata;
715     int err;
716     Boolean ret;
717 
718     data = NULL;
719     err = XGetWindowProperty(dpy, window, cap->profileAtom,
720 			     0L, 100L, False,
721 			     cap->typeAtom,
722 			     &type, &format, &nitems,
723 			     &bytesafter, (unsigned char **)&data);
724     if (err) return False;
725     if (format != 32 || type != cap->typeAtom) {
726 	if (data != NULL) XtFree((char *)data);
727 	return False;
728     }
729 
730     ret = False;
731     saveddata = data;
732     while (nitems > 0) {
733 	int code = CODE_OF_ATTR(*data);
734 	int len = LENGTH_OF_ATTR(*data);
735 
736 	data++;
737 	nitems--;
738 	if (nitems < len) break;
739 
740 	switch (code) {
741 	case CONVPROF_PROTOCOL_VERSION:
742 	    if (*data == cap->versionAtom) ret = True;
743 	    break;
744 	case CONVPROF_SUPPORTED_STYLES:
745 	    break;	/* XXX for now */
746 	default:
747 	    break;
748 	}
749 	data += len;
750 	nitems -= len;
751     }
752     XtFree((char *)saveddata);
753 
754     return ret;
755 }
756 
757 
758 /*
759  *	public functions
760  */
761 
762 int
_beginConversionWithAttributes(w,catom,tatom,inputproc,startendproc,client_data,attrs,nattrs)763 _beginConversionWithAttributes(w, catom, tatom, inputproc, startendproc, client_data, attrs, nattrs)
764 Widget w;
765 Atom catom;		/* Selection Atom e.g. JAPANESE_CONVERSION */
766 Atom tatom;		/* Property Type Atom e.g. COMPOUND_TEXT */
767 void (*inputproc)();	/* conversion text callback function */
768 void (*startendproc)();	/* conversion start/end callback function */
769 XtPointer client_data;	/* client_data passed to callback function */
770 ArgList attrs;		/* attribute data */
771 Cardinal nattrs;	/* number of attr args */
772 {
773     Window owner;
774     XEvent event;
775     ConversionAtoms *cap;
776     ConversionContext *context;
777     Boolean anyattr;
778 
779     cap = getAtoms(w);
780 
781     /* $BJQ49%5!<%P$rC5$9(B */
782     if ((owner = XGetSelectionOwner(XtDisplay(w), catom)) == None) {
783 	/* $B$J$$(B
784 	 * $B$b$7$bJQ49Cf$@$C$?$iJQ49$rCf;_$9$k(B
785 	 */
786 	XtWarning("Conversion Server not found");
787 	if ((context = getConversionContext(w)) != NULL) {
788 	    /* $B%$%Y%s%H%O%s%I%i$r30$9(B */
789 	    XtRemoveEventHandler(w, NoEventMask, True, recvConvAck,
790 				 (XtPointer)NULL);
791 	    XtRemoveEventHandler(w, PropertyChangeMask, True, getConv,
792 				 (XtPointer)NULL);
793 	    /* $B%&%#%s%I%&$N%3%s%F%-%9%H$r:o=|$9$k(B */
794 	    XDeleteContext(XtDisplay(w), XtWindow(w), convertPrivContext);
795 	    callEnd(w, context);
796 	    XtFree((char *)context);
797 	}
798 	return -1;
799     }
800 
801     /*
802      * $B:#$9$G$KJQ49Cf$+$I$&$+D4$Y$k(B
803      * $BJQ49Cf$J$i2?$b$;$:$K%j%?!<%s$9$k!D$o$1$K$O$$$+$J$$(B
804      * $B$J$<$+$H$$$&$H!"JQ49%5!<%P$,2?$i$+$N;v>p$GESCf$G;`$s$@>l9g(B
805      * CONVERSION_END $B$,%/%i%$%"%s%H$KMh$J$$$3$H$,$"$k$+$i$G$"$k(B
806      * $B$=$3$G!"JQ49Cf$N>l9g$G$b(B SelectionOwner $B$rC5$7$F!"$=$l$,(B
807      * $B:G=i$K(B _beginConversion() $B$,8F$P$l$?;~$H(B WindowID $B$,F1$8$+(B
808      * $B$I$&$+3NG'$9$k(B
809      * $BK\Ev$O(B SelectionOwner $B$K$J$C$?;~4V$b%A%'%C%/$7$?$$$N$@$,(B
810      * ICCCM $B$K=R$Y$i$l$F$$$k$h$&$K!"(BGetSelectionOwner $B$G$O(B
811      * $B$=$l$,$o$+$i$J$$$N$G$"$-$i$a$k(B
812      */
813     if ((context = getConversionContext(w)) != NULL) {
814 	Window curOwner;
815 	curOwner = (catom == context->convatom) ? owner :
816 	  XGetSelectionOwner(XtDisplay(w), context->convatom);
817 	if (curOwner == context->convowner) {
818 	    /* $B2?$b$;$:$K%j%?!<%s(B */
819 	    return 0;
820 	}
821 	/* SelectionOwner $B$,JQ$o$C$F$$$k(B
822 	 * $B$3$l$OESCf$GJQ49%5!<%P$,%/%i%C%7%e$7$?$K0c$$$J$$(B
823 	 * $B$H$$$&$3$H$G(B CONVERSION_END $B$,Mh$?;~$HF1$8$h$&$J(B
824 	 * $B=hM}$r$9$k(B
825 	 */
826 	/* $B%$%Y%s%H%O%s%I%i$r30$9(B
827 	 * CONVERSION_NOTIFY $B$N%$%Y%s%H$,Mh$k$^$G$O(B
828 	 * recvConvAck() $B$,%O%s%I%i$G!"$=$N8e$O(B
829 	 * getConv() $B$,%O%s%I%i$G$"$k(B
830 	 */
831 	XtRemoveEventHandler(w, NoEventMask, True, recvConvAck,
832 			     (XtPointer)NULL);
833 	XtRemoveEventHandler(w, PropertyChangeMask, True, getConv,
834 			     (XtPointer)NULL);
835 	/* $B%&%#%s%I%&$N%3%s%F%-%9%H$r:o=|$9$k(B */
836 	XDeleteContext(XtDisplay(w), XtWindow(w), convertPrivContext);
837 	callEnd(w, context);
838 	XtFree((char *)context);
839     }
840 
841     /*
842      * $B%5!<%P$+$i$N(B CONVERSION_NOTIFY $BMQ$N%$%Y%s%H%O%s%I%i$r(B
843      * $BEPO?$9$k(B
844      */
845     XtAddEventHandler(w, NoEventMask, True, recvConvAck, (XtPointer)NULL);
846 
847     /*
848      * $B%3%s%F%-%9%H$r$D$/$C$FI,MW$J>pJs$rEPO?$9$k(B
849      */
850     context = XtNew(ConversionContext);
851     context->convatom = catom;
852     context->convowner = owner;
853     context->property = None;	/* $B$3$l$O(B CONVERSION_NOTIFY $B$,Mh$?;~$K(B
854 				 * $B@5$7$/@_Dj$5$l$k(B */
855     context->inputproc = inputproc;
856     context->startendproc = startendproc;
857     context->closure = client_data;
858     XSaveContext(XtDisplay(w), XtWindow(w),
859 		 convertPrivContext, (caddr_t)context);
860 
861     /*
862      * $BJQ49B0@-%j%9%H$,;XDj$5$l$F$$$l$P%W%m%Q%F%#$K$=$l$rEPO?$9$k(B
863      */
864     if (nattrs != 0 && attrs != NULL &&
865 	checkProtocols(XtDisplay(w), owner, cap)) {
866 	anyattr = setConvAttrProp(w, attrs, nattrs, cap->attrAtom);
867     }
868 
869     /*
870      * ClientMessage $B%$%Y%s%H$r;H$C$FF|K\8lF~NO$r%j%/%(%9%H$9$k(B
871      */
872     event.xclient.type = ClientMessage;
873     event.xclient.window = owner;
874     event.xclient.message_type = cap->reqAtom;
875     event.xclient.format = 32;
876     event.xclient.data.l[0] = catom;
877     event.xclient.data.l[1] = XtWindow(w);
878     event.xclient.data.l[2] = tatom;
879     /* $B7k2L$r%9%H%"$9$k%W%m%Q%F%#L>$O!"B?8@8l$rF1;~$K;HMQ$9$k$3$H$r(B
880      * $B9M$($F!"(Bselection atom $B$r;HMQ$9$k$3$H$K$9$k(B
881      */
882     event.xclient.data.l[3] = catom;
883     event.xclient.data.l[4] = anyattr ? cap->attrAtom : None;
884     XSendEvent(XtDisplay(w), owner, False, NoEventMask, &event);
885 
886     return 0;
887 }
888 
889 /* this is provided for backward compatibility */
890 void
_beginConversion(w,catom,tatom,inputproc,client_data)891 _beginConversion(w, catom, tatom, inputproc, client_data)
892 Widget	w;
893 Atom	catom;			/* Selection Atom e.g. JAPANESE_CONVERSION */
894 Atom	tatom;			/* Property Type Atom e.g. COMPOUND_TEXT */
895 void	(*inputproc)();		/* conversion text callback function */
896 XtPointer client_data;		/* client_data passed to callback function */
897 {
898     (void)_beginConversionWithAttributes(w, catom, tatom, inputproc,
899 				   (void (*)())NULL, client_data,
900 				   (ArgList)NULL, 0);
901 }
902 
903 void
_changeConversionAttributes(w,catom,attrs,nattrs)904 _changeConversionAttributes(w, catom, attrs, nattrs)
905 Widget	w;
906 Atom	catom;			/* Selection Atom e.g. JAPANESE_CONVERSION */
907 ArgList	attrs;			/* attribute data */
908 Cardinal nattrs;		/* number of attr args */
909 {
910     XEvent event;
911     ConversionAtoms *cap;
912     ConversionContext *context;
913     unsigned long *data;
914     int len;
915 
916     if (attrs == NULL || nattrs == 0) return;
917 
918     cap = getAtoms(w);
919     context = getConversionContext(w);
920 
921     if (context == NULL || (catom != None && catom != context->convatom)) {
922 	return;
923     }
924 
925     if (XGetSelectionOwner(XtDisplay(w), context->convatom) !=
926 	context->convowner) {
927 	/* $BJQ49%5!<%P$,0[$J$k!"$"$k$$$O$J$$(B */
928 	XtRemoveEventHandler(w, NoEventMask, True, recvConvAck,
929 			     (XtPointer)NULL);
930 	XtRemoveEventHandler(w, PropertyChangeMask, True, getConv,
931 			     (XtPointer)NULL);
932 	/* $B%&%#%s%I%&$N%3%s%F%-%9%H$r:o=|$9$k(B */
933 	XDeleteContext(XtDisplay(w), XtWindow(w), convertPrivContext);
934 	callEnd(w, context);
935 	XtFree((char *)context);
936 	return;
937     }
938 
939     data = NULL;
940     if ((len = makeAttrData(w, attrs, nattrs, &data)) == 0) return;
941 
942     event.xclient.type = ClientMessage;
943     event.xclient.window = context->convowner;
944     event.xclient.message_type = cap->attrNotifyAtom;
945     event.xclient.format = 32;
946     event.xclient.data.l[0] = context->convatom;
947     event.xclient.data.l[1] = XtWindow(w);
948     if (len <= 3 && len == LENGTH_OF_ATTR(data[0]) + 1) {
949 	int i;
950 	/* $B%$%Y%s%H$NCf$K<}$^$k(B */
951 	for (i = 0; i < len; i++) {
952 	    event.xclient.data.l[2 + i] = data[i];
953 	}
954     } else {
955 	XChangeProperty(XtDisplay(w), XtWindow(w),
956 			cap->attrAtom, cap->attrAtom, 32,
957 			PropModeReplace, (unsigned char *)data, len);
958 	event.xclient.data.l[2] = CONV_ATTR(CONVATTR_INDIRECT, 1);
959 	event.xclient.data.l[3] = cap->attrAtom;
960     }
961 
962     XSendEvent(XtDisplay(w), context->convowner, False, NoEventMask, &event);
963 
964     if (data != NULL) XtFree((char *)data);
965 }
966 
967 void
_endConversion(w,catom,throwaway)968 _endConversion(w, catom, throwaway)
969 Widget	w;
970 Atom	catom;		/* Selection Atom */
971 Boolean	throwaway;
972 {
973     XEvent event;
974     ConversionAtoms *cap;
975     ConversionContext *context;
976 
977     cap = getAtoms(w);
978     context = getConversionContext(w);
979 
980     if (context == NULL || (catom != None && catom != context->convatom)) {
981 	return;
982     }
983 
984     if (XGetSelectionOwner(XtDisplay(w), context->convatom) !=
985 	context->convowner) {
986 	/* $BJQ49%5!<%P$,0[$J$k!"$"$k$$$O$J$$(B */
987 	XtRemoveEventHandler(w, NoEventMask, True, recvConvAck,
988 			     (XtPointer)NULL);
989 	XtRemoveEventHandler(w, PropertyChangeMask, True, getConv,
990 			     (XtPointer)NULL);
991 	/* $B%&%#%s%I%&$N%3%s%F%-%9%H$r:o=|$9$k(B */
992 	XDeleteContext(XtDisplay(w), XtWindow(w), convertPrivContext);
993 	/* $B%3!<%k%P%C%/$r8F$V(B */
994 	callEnd(w, context);
995 	XtFree((char *)context);
996 	return;
997     }
998 
999     if (throwaway) context->inputproc = NULL;
1000 
1001     event.xclient.type = ClientMessage;
1002     event.xclient.window = context->convowner;
1003     event.xclient.message_type = cap->endReqAtom;
1004     event.xclient.format = 32;
1005     event.xclient.data.l[0] = context->convatom;
1006     event.xclient.data.l[1] = XtWindow(w);
1007 
1008     XSendEvent(XtDisplay(w), context->convowner, False, NoEventMask, &event);
1009 }
1010