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