imInsClbk.c revision b4ee4795
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#define NEED_EVENTS
34#include	"Xlibint.h"
35#include	"Xlcint.h"
36#include	"XlcPublic.h"
37#include	"Ximint.h"
38
39
40typedef struct _XimInstCallback {
41    Bool			 call;
42    Bool			 destroy;
43    Display			*display;
44    XLCd			 lcd;
45    char			 name[XIM_MAXLCNAMELEN];
46    char			*modifiers;
47    XrmDatabase			 rdb;
48    char			*res_name;
49    char			*res_class;
50    XIDProc			 callback;
51    XPointer			 client_data;
52    struct _XimInstCallback	*next;
53} XimInstCallbackRec, *XimInstCallback;
54
55
56Private XimInstCallback	callback_list	= NULL;
57Private Bool		lock		= False;
58
59
60Private void
61MakeLocale( XLCd lcd, char locale[] )
62{
63    char	*language, *territory, *codeset;
64
65    _XGetLCValues( lcd, XlcNLanguage, &language, XlcNTerritory, &territory,
66		     XlcNCodeset, &codeset, NULL );
67
68    strcpy( locale, language );
69    if( territory  &&  *territory ) {
70	strcat( locale, "_" );
71	strcat( locale, territory );
72    }
73    if( codeset  &&  *codeset ) {
74	strcat( locale, "." );
75	strcat( locale, codeset );
76    }
77}
78
79
80Private Bool
81_XimFilterPropertyNotify(
82    Display	*display,
83    Window	 window,
84    XEvent	*event,
85    XPointer	 client_data)
86{
87    Atom		ims, actual_type, *atoms;
88    int			actual_format;
89    unsigned long	nitems, bytes_after;
90    int			ii;
91    XIM			xim;
92    Bool		flag = False;
93    XimInstCallback	icb, picb, tmp;
94
95    if( (ims = XInternAtom( display, XIM_SERVERS, True )) == None  ||
96	event->xproperty.atom != ims  ||
97	event->xproperty.state == PropertyDelete )
98	return( False );
99
100    if( XGetWindowProperty( display, RootWindow(display, 0), ims, 0L, 1000000L,
101			    False, XA_ATOM, &actual_type, &actual_format,
102			    &nitems, &bytes_after, (unsigned char **)&atoms )
103	    != Success ) {
104	return( False );
105    }
106    if( actual_type != XA_ATOM  ||  actual_format != 32 ) {
107	XFree( atoms );
108	return( False );
109    }
110
111    lock = True;
112    for( ii = 0; ii < nitems; ii++, atoms ) {
113	if(XGetSelectionOwner (display, atoms[ii])) {
114	    for( icb = callback_list; icb; icb = icb->next ) {
115		if( !icb->call  &&  !icb->destroy ) {
116		    xim = (*icb->lcd->methods->open_im)( icb->lcd, display,
117							 icb->rdb,
118							 icb->res_name,
119							 icb->res_class );
120		    if( xim ) {
121			xim->methods->close( (XIM)xim );
122			flag = True;
123			icb->call = True;
124			icb->callback( icb->display, icb->client_data, NULL );
125		    }
126		}
127	    }
128	    break;
129	}
130    }
131    XFree( atoms );
132
133    for( icb = callback_list, picb = NULL; icb; ) {
134	if( icb->destroy ) {
135	    if( picb )
136		picb->next = icb->next;
137	    else
138		callback_list = icb->next;
139	    tmp = icb;
140	    icb = icb->next;
141	    XFree( tmp );
142	}
143	else {
144	    picb = icb;
145	    icb = icb->next;
146	}
147    }
148    lock = False;
149
150    return( flag );
151}
152
153
154Public Bool
155_XimRegisterIMInstantiateCallback(
156    XLCd	 lcd,
157    Display	*display,
158    XrmDatabase	 rdb,
159    char	*res_name,
160    char	*res_class,
161    XIDProc	 callback,
162    XPointer	 client_data)
163{
164    XimInstCallback	icb, tmp;
165    XIM			xim;
166    Window		root;
167    XWindowAttributes	attr;
168
169    if( lock )
170	return( False );
171
172    icb = (XimInstCallback)Xmalloc(sizeof(XimInstCallbackRec));
173    if( !icb )
174	return( False );
175    icb->call = icb->destroy = False;
176    icb->display = display;
177    icb->lcd = lcd;
178    MakeLocale( lcd, icb->name );
179    icb->modifiers = lcd->core->modifiers;	/* XXXXX */
180    icb->rdb = rdb;
181    icb->res_name = res_name;
182    icb->res_class = res_class;
183    icb->callback = callback;
184    icb->client_data = client_data;
185    icb->next = NULL;
186
187    if( !callback_list )
188	callback_list = icb;
189    else {
190	for( tmp = callback_list; tmp->next; tmp = tmp->next );
191	tmp->next = icb;
192    }
193
194    xim = (*lcd->methods->open_im)( lcd, display, rdb, res_name, res_class );
195
196    if( icb == callback_list ) {
197	root = RootWindow( display, 0 );
198	XGetWindowAttributes( display, root, &attr );
199	_XRegisterFilterByType( display, root, PropertyNotify, PropertyNotify,
200				_XimFilterPropertyNotify, (XPointer)NULL );
201	XSelectInput( display, root,
202		      attr.your_event_mask | PropertyChangeMask );
203    }
204
205    if( xim ) {
206	lock = True;
207	xim->methods->close( (XIM)xim );
208	lock = False;
209	icb->call = True;
210	callback( display, client_data, NULL );
211    }
212
213    return( True );
214}
215
216
217Public Bool
218_XimUnRegisterIMInstantiateCallback(
219    XLCd	 lcd,
220    Display	*display,
221    XrmDatabase	 rdb,
222    char	*res_name,
223    char	*res_class,
224    XIDProc	 callback,
225    XPointer	 client_data)
226{
227    char		locale[XIM_MAXLCNAMELEN];
228    XimInstCallback	icb, picb;
229
230    if( !callback_list )
231	return( False );
232
233    MakeLocale( lcd, locale );
234
235    for( icb = callback_list, picb = NULL; icb; picb = icb, icb = icb->next ) {
236	if( !strcmp( locale, icb->name )  &&
237	    (lcd->core->modifiers == icb->modifiers  ||		/* XXXXX */
238	     (lcd->core->modifiers  &&  icb->modifiers  &&
239	      !strcmp( lcd->core->modifiers, icb->modifiers )))  &&
240	    rdb == icb->rdb  &&					/* XXXXX */
241	    ((res_name == NULL  &&  icb->res_name == NULL)  ||
242	     (res_name != NULL  &&  icb->res_name != NULL  &&
243	      !strcmp( res_name, icb->res_name )))  &&
244	    ((res_class == NULL  &&  icb->res_class == NULL)  ||
245	     (res_class != NULL  &&  icb->res_class != NULL  &&
246	      !strcmp( res_class, icb->res_class )))  &&
247	    (callback == icb->callback)  &&
248	    (client_data  ==  icb->client_data)  &&		/* XXXXX */
249	    !icb->destroy ) {
250	    if( lock )
251		icb->destroy = True;
252	    else {
253		if( !picb ) {
254		    callback_list = icb->next;
255		    _XUnregisterFilter( display, RootWindow(display, 0),
256					_XimFilterPropertyNotify,
257					(XPointer)NULL );
258		}
259		else
260		    picb->next = icb->next;
261		_XCloseLC( icb->lcd );
262		XFree( icb );
263	    }
264	    return( True );
265	}
266    }
267    return( False );
268}
269
270
271Public void
272_XimResetIMInstantiateCallback(Xim xim)
273{
274    char		 locale[XIM_MAXLCNAMELEN];
275    XimInstCallback	 icb;
276    XLCd	 	 lcd = xim->core.lcd;
277
278    if( !callback_list  &&  lock )
279	return;
280
281    MakeLocale( lcd, locale );
282
283    for( icb = callback_list; icb; icb = icb->next )
284	if( !strcmp( locale, icb->name )  &&
285	    (lcd->core->modifiers == icb->modifiers  ||
286	     (lcd->core->modifiers  &&  icb->modifiers  &&
287	      !strcmp( lcd->core->modifiers, icb->modifiers ))) )
288	    icb->call = False;
289}
290