imInsClbk.c revision 3233502e
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    Window		root;
166    XWindowAttributes	attr;
167
168    if( lock )
169	return( False );
170
171    icb = Xmalloc(sizeof(XimInstCallbackRec));
172    if( !icb )
173	return( False );
174    icb->call = icb->destroy = False;
175    icb->display = display;
176    icb->lcd = lcd;
177    MakeLocale( lcd, icb->name );
178    icb->modifiers = lcd->core->modifiers;	/* XXXXX */
179    icb->rdb = rdb;
180    icb->res_name = res_name;
181    icb->res_class = res_class;
182    icb->callback = callback;
183    icb->client_data = client_data;
184    icb->next = NULL;
185
186    if( !callback_list )
187	callback_list = icb;
188    else {
189	for( tmp = callback_list; tmp->next; tmp = tmp->next );
190	tmp->next = icb;
191    }
192
193    xim = (*lcd->methods->open_im)( lcd, display, rdb, res_name, res_class );
194
195    if( icb == callback_list ) {
196	root = RootWindow( display, 0 );
197	XGetWindowAttributes( display, root, &attr );
198	_XRegisterFilterByType( display, root, PropertyNotify, PropertyNotify,
199				_XimFilterPropertyNotify, (XPointer)NULL );
200	XSelectInput( display, root,
201		      attr.your_event_mask | PropertyChangeMask );
202    }
203
204    if( xim ) {
205	lock = True;
206	xim->methods->close( (XIM)xim );
207	lock = False;
208	icb->call = True;
209	callback( display, client_data, NULL );
210    }
211
212    return( True );
213}
214
215
216Bool
217_XimUnRegisterIMInstantiateCallback(
218    XLCd	 lcd,
219    Display	*display,
220    XrmDatabase	 rdb,
221    char	*res_name,
222    char	*res_class,
223    XIDProc	 callback,
224    XPointer	 client_data)
225{
226    char		locale[XIM_MAXLCNAMELEN];
227    XimInstCallback	icb, picb;
228
229    if( !callback_list )
230	return( False );
231
232    MakeLocale( lcd, locale );
233
234    for( icb = callback_list, picb = NULL; icb; picb = icb, icb = icb->next ) {
235	if( !strcmp( locale, icb->name )  &&
236	    (lcd->core->modifiers == icb->modifiers  ||		/* XXXXX */
237	     (lcd->core->modifiers  &&  icb->modifiers  &&
238	      !strcmp( lcd->core->modifiers, icb->modifiers )))  &&
239	    rdb == icb->rdb  &&					/* XXXXX */
240	    ((res_name == NULL  &&  icb->res_name == NULL)  ||
241	     (res_name != NULL  &&  icb->res_name != NULL  &&
242	      !strcmp( res_name, icb->res_name )))  &&
243	    ((res_class == NULL  &&  icb->res_class == NULL)  ||
244	     (res_class != NULL  &&  icb->res_class != NULL  &&
245	      !strcmp( res_class, icb->res_class )))  &&
246	    (callback == icb->callback)  &&
247	    (client_data  ==  icb->client_data)  &&		/* XXXXX */
248	    !icb->destroy ) {
249	    if( lock )
250		icb->destroy = True;
251	    else {
252		if( !picb ) {
253		    callback_list = icb->next;
254		    _XUnregisterFilter( display, RootWindow(display, 0),
255					_XimFilterPropertyNotify,
256					(XPointer)NULL );
257		}
258		else
259		    picb->next = icb->next;
260		_XCloseLC( icb->lcd );
261		XFree( icb );
262	    }
263	    return( True );
264	}
265    }
266    return( False );
267}
268
269
270void
271_XimResetIMInstantiateCallback(Xim xim)
272{
273    char		 locale[XIM_MAXLCNAMELEN];
274    XimInstCallback	 icb;
275    XLCd	 	 lcd = xim->core.lcd;
276
277    if( !callback_list  &&  lock )
278	return;
279
280    MakeLocale( lcd, locale );
281
282    for( icb = callback_list; icb; icb = icb->next )
283	if( !strcmp( locale, icb->name )  &&
284	    (lcd->core->modifiers == icb->modifiers  ||
285	     (lcd->core->modifiers  &&  icb->modifiers  &&
286	      !strcmp( lcd->core->modifiers, icb->modifiers ))) )
287	    icb->call = False;
288}
289