imInsClbk.c revision d4a3aaf4
1/******************************************************************
2
3           Copyright 1993, 1994 by Sony Corporation
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 Sony Corporation
10 not be used in advertising or publicity pertaining to distribution
11 of the software without specific, written prior permission.
12Sony Corporation makes no representations about the suitability of
13 this software for any purpose. It is provided "as is" without
14 express or implied warranty.
15
16SONY CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18EVENT SHALL SONY CORPORATION 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:   Makoto Wakamatsu   Sony Corporation
25                               makoto@sm.sony.co.jp
26
27******************************************************************/
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include	<X11/Xatom.h>
33#include	"Xlibint.h"
34#include	"Xlcint.h"
35#include	"XlcPublic.h"
36#include	"Ximint.h"
37
38
39typedef struct _XimInstCallback {
40    Bool			 call;
41    Bool			 destroy;
42    Display			*display;
43    XLCd			 lcd;
44    char			 name[XIM_MAXLCNAMELEN];
45    char			*modifiers;
46    XrmDatabase			 rdb;
47    char			*res_name;
48    char			*res_class;
49    XIDProc			 callback;
50    XPointer			 client_data;
51    struct _XimInstCallback	*next;
52} XimInstCallbackRec, *XimInstCallback;
53
54
55static XimInstCallback	callback_list	= NULL;
56static Bool		lock		= False;
57
58
59static void
60MakeLocale( XLCd lcd, char locale[] )
61{
62    char	*language, *territory, *codeset;
63
64    _XGetLCValues( lcd, XlcNLanguage, &language, XlcNTerritory, &territory,
65		     XlcNCodeset, &codeset, NULL );
66
67    strcpy( locale, language );
68    if( territory  &&  *territory ) {
69	strcat( locale, "_" );
70	strcat( locale, territory );
71    }
72    if( codeset  &&  *codeset ) {
73	strcat( locale, "." );
74	strcat( locale, codeset );
75    }
76}
77
78
79static Bool
80_XimFilterPropertyNotify(
81    Display	*display,
82    Window	 window,
83    XEvent	*event,
84    XPointer	 client_data)
85{
86    Atom		ims, actual_type, *atoms;
87    int			actual_format;
88    unsigned long	nitems, bytes_after;
89    int			ii;
90    XIM			xim;
91    Bool		flag = False;
92    XimInstCallback	icb, picb, tmp;
93
94    if( (ims = XInternAtom( display, XIM_SERVERS, True )) == None  ||
95	event->xproperty.atom != ims  ||
96	event->xproperty.state == PropertyDelete )
97	return( False );
98
99    if( XGetWindowProperty( display, RootWindow(display, 0), ims, 0L, 1000000L,
100			    False, XA_ATOM, &actual_type, &actual_format,
101			    &nitems, &bytes_after, (unsigned char **)&atoms )
102	    != Success ) {
103	return( False );
104    }
105    if( actual_type != XA_ATOM  ||  actual_format != 32 ) {
106	XFree( atoms );
107	return( False );
108    }
109
110    lock = True;
111    for( ii = 0; ii < nitems; ii++ ) {
112	if(XGetSelectionOwner (display, atoms[ii])) {
113	    for( icb = callback_list; icb; icb = icb->next ) {
114		if( !icb->call  &&  !icb->destroy ) {
115		    xim = (*icb->lcd->methods->open_im)( icb->lcd, display,
116							 icb->rdb,
117							 icb->res_name,
118							 icb->res_class );
119		    if( xim ) {
120			xim->methods->close( (XIM)xim );
121			flag = True;
122			icb->call = True;
123			icb->callback( icb->display, icb->client_data, NULL );
124		    }
125		}
126	    }
127	    break;
128	}
129    }
130    XFree( atoms );
131
132    for( icb = callback_list, picb = NULL; icb; ) {
133	if( icb->destroy ) {
134	    if( picb )
135		picb->next = icb->next;
136	    else
137		callback_list = icb->next;
138	    tmp = icb;
139	    icb = icb->next;
140	    XFree( tmp );
141	}
142	else {
143	    picb = icb;
144	    icb = icb->next;
145	}
146    }
147    lock = False;
148
149    return( flag );
150}
151
152
153Bool
154_XimRegisterIMInstantiateCallback(
155    XLCd	 lcd,
156    Display	*display,
157    XrmDatabase	 rdb,
158    char	*res_name,
159    char	*res_class,
160    XIDProc	 callback,
161    XPointer	 client_data)
162{
163    XimInstCallback	icb, tmp;
164    XIM			xim;
165    char		*modifiers = NULL;
166    Window		root;
167    XWindowAttributes	attr;
168
169    if( lock )
170	return( False );
171
172    icb = Xmalloc(sizeof(XimInstCallbackRec));
173    if( !icb )
174	return( False );
175    if (lcd->core->modifiers) {
176	modifiers = strdup(lcd->core->modifiers);
177	if (!modifiers) {
178	    Xfree(icb);
179	    return( False );
180	}
181    }
182    icb->call = icb->destroy = False;
183    icb->display = display;
184    icb->lcd = lcd;
185    MakeLocale( lcd, icb->name );
186    icb->modifiers = modifiers;
187    icb->rdb = rdb;
188    icb->res_name = res_name;
189    icb->res_class = res_class;
190    icb->callback = callback;
191    icb->client_data = client_data;
192    icb->next = NULL;
193
194    if( !callback_list )
195	callback_list = icb;
196    else {
197	for( tmp = callback_list; tmp->next; tmp = tmp->next );
198	tmp->next = icb;
199    }
200
201    xim = (*lcd->methods->open_im)( lcd, display, rdb, res_name, res_class );
202
203    if( icb == callback_list ) {
204	root = RootWindow( display, 0 );
205	XGetWindowAttributes( display, root, &attr );
206	_XRegisterFilterByType( display, root, PropertyNotify, PropertyNotify,
207				_XimFilterPropertyNotify, (XPointer)NULL );
208	XSelectInput( display, root,
209		      attr.your_event_mask | PropertyChangeMask );
210    }
211
212    if( xim ) {
213	lock = True;
214	xim->methods->close( (XIM)xim );
215	lock = False;
216	icb->call = True;
217	callback( display, client_data, NULL );
218    }
219
220    return( True );
221}
222
223
224Bool
225_XimUnRegisterIMInstantiateCallback(
226    XLCd	 lcd,
227    Display	*display,
228    XrmDatabase	 rdb,
229    char	*res_name,
230    char	*res_class,
231    XIDProc	 callback,
232    XPointer	 client_data)
233{
234    char		locale[XIM_MAXLCNAMELEN];
235    XimInstCallback	icb, picb;
236
237    if( !callback_list )
238	return( False );
239
240    MakeLocale( lcd, locale );
241
242    for( icb = callback_list, picb = NULL; icb; picb = icb, icb = icb->next ) {
243	if( !strcmp( locale, icb->name )  &&
244	    (lcd->core->modifiers == icb->modifiers  ||		/* XXXXX */
245	     (lcd->core->modifiers  &&  icb->modifiers  &&
246	      !strcmp( lcd->core->modifiers, icb->modifiers )))  &&
247	    rdb == icb->rdb  &&					/* XXXXX */
248	    ((res_name == NULL  &&  icb->res_name == NULL)  ||
249	     (res_name != NULL  &&  icb->res_name != NULL  &&
250	      !strcmp( res_name, icb->res_name )))  &&
251	    ((res_class == NULL  &&  icb->res_class == NULL)  ||
252	     (res_class != NULL  &&  icb->res_class != NULL  &&
253	      !strcmp( res_class, icb->res_class )))  &&
254	    (callback == icb->callback)  &&
255	    (client_data  ==  icb->client_data)  &&		/* XXXXX */
256	    !icb->destroy ) {
257	    if( lock )
258		icb->destroy = True;
259	    else {
260		if( !picb ) {
261		    callback_list = icb->next;
262		    _XUnregisterFilter( display, RootWindow(display, 0),
263					_XimFilterPropertyNotify,
264					(XPointer)NULL );
265		}
266		else
267		    picb->next = icb->next;
268		_XCloseLC( icb->lcd );
269		XFree( icb->modifiers );
270		XFree( icb );
271	    }
272	    return( True );
273	}
274    }
275    return( False );
276}
277
278
279void
280_XimResetIMInstantiateCallback(Xim xim)
281{
282    char		 locale[XIM_MAXLCNAMELEN];
283    XimInstCallback	 icb;
284    XLCd	 	 lcd = xim->core.lcd;
285
286    if( !callback_list  &&  lock )
287	return;
288
289    MakeLocale( lcd, locale );
290
291    for( icb = callback_list; icb; icb = icb->next )
292	if( !strcmp( locale, icb->name )  &&
293	    (lcd->core->modifiers == icb->modifiers  ||
294	     (lcd->core->modifiers  &&  icb->modifiers  &&
295	      !strcmp( lcd->core->modifiers, icb->modifiers ))) )
296	    icb->call = False;
297}
298