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