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