Back to index

im-sdk  12.3.91
XeIMWrap.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1985, 1986, 1987, 1991, 1998  The Open Group
00003 
00004 Portions Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a
00007 copy of this software and associated documentation files (the
00008 "Software"), to deal in the Software without restriction, including
00009 without limitation the rights to use, copy, modify, merge, publish,
00010 distribute, sublicense, and/or sell copies of the Software, and to
00011 permit persons to whom the Software is furnished to do so, subject to
00012 the following conditions: The above copyright notice and this
00013 permission notice shall be included in all copies or substantial
00014 portions of the Software.
00015 
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00019 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00020 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00021 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00022 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00023 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00024 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00025 
00026 
00027 Except as contained in this notice, the names of The Open Group and/or
00028 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00029 promote the sale, use or other dealings in this Software without prior
00030 written authorization from The Open Group and/or Sun Microsystems,
00031 Inc., as applicable.
00032 
00033 
00034 X Window System is a trademark of The Open Group
00035 
00036 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00037 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00038 Group. All other trademarks and registered trademarks mentioned herein
00039 are the property of their respective owners. No right, title or
00040 interest in or to any trademark, service mark, logo or trade name of
00041 Sun Microsystems, Inc. or its licensors is granted.
00042 
00043 */
00044 #ifdef HAVE_CONFIG_H
00045 #include <config.h>
00046 #endif
00047 
00048 #ifndef __XLIBINT_HH
00049 #define __XLIBINT_HH
00050 #include <X11/Xlibint.h>
00051 #endif /* __XLIBINT_HH */
00052 #include "Xlcint.h"
00053 #include "XIM.h"
00054 #include "switchIM.h"
00055 #include "iiimpIM.h"
00056 #include "genutil.h"
00057 #include <locale.h>
00058 #include <langinfo.h>
00059 
00060 static int
00061 getXIMArg(XIMArg *arg,
00062          char *name, void *value) {
00063   XIMArg *p;
00064 
00065   for (p = arg; p->name != 0; p++) {
00066     if (!strcmp(p->name, XNMultiLingualInput)) {
00067       *((Bool*)value) = (Bool)p->value;
00068       return 0;
00069     }
00070   }
00071   return -1;
00072 }
00073 
00074 #define NAME_LEN 20
00075 XIM
00076 __XOpenIM(Display *display, XrmDatabase rdb,
00077          char *res_name, char *res_class,
00078          XIMArg *arg) {
00079   Bool isMultilingual = False;
00080   XIM xim = (XIM)0;
00081   XOpenIMProc open_im;
00082   XLCd lcd = 0;
00083   char *current_locale = 0;
00084 
00085   (void)getXIMArg(arg,
00086                 XNMultiLingualInput, &isMultilingual);
00087   open_im = isMultilingual? _SwitchOpenIM : _IIIMP_OpenIM ;
00088   if (isMultilingual)
00089     putenv("DISABLE_MULTI_SCRIPT_IM=false"); /* hidden feature */
00090 
00091   current_locale = (char*)strdup(setlocale(LC_CTYPE, NULL));
00092 
00093   lcd = _XOpenLC((char*)NULL);
00094 
00095   /* try first with the current locale */
00096   if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) {
00097     if (lcd) {
00098       xim = open_im((XLCd)lcd, display, rdb, res_name, res_class);
00099       if (xim) {
00100        ((XimCommon)xim)->isUnicode = isMultilingual;
00101        goto Ret;
00102       }
00103     }
00104   }
00105 
00106   /* pick an UTF-8 locale best matching for the lang part of
00107      the current locale */
00108   if (lcd) {
00109     char new_locale[NAME_LEN];
00110     char *language, *territory;
00111     char *codeset;
00112     XLCd new_lcd;
00113 
00114     _XGetLCValues(lcd, XlcNLanguage,  &language,
00115                 XlcNTerritory, &territory,
00116                 XlcNCodeset,   &codeset,
00117                 (char*)NULL);
00118     _genutil_strlcpy(new_locale, language, NAME_LEN);
00119 
00120     if (territory && *territory) {
00121       _genutil_strlcat(new_locale, "_", NAME_LEN);
00122       _genutil_strlcat(new_locale, territory, NAME_LEN);
00123     }
00124     _genutil_strlcat(new_locale, ".UTF-8", NAME_LEN);
00125     new_lcd = _XOpenLC(new_locale);
00126     if (new_lcd) {
00127       xim = open_im((XLCd)new_lcd, display, rdb, res_name, res_class);
00128       if (xim) {
00129        _XCloseLC(lcd);             /* no more need */
00130        ((XimCommon)xim)->isUnicode = isMultilingual;
00131        goto Ret;
00132       }
00133       _XCloseLC(new_lcd);
00134       new_lcd = 0;
00135     }
00136     if (!territory || !*territory) {
00137       /* get territory name from current locale */
00138       char *p = index(current_locale, '_');
00139       if (p &&strlen(p) >= 2) {
00140        territory = p + 1; territory[2] = 0;
00141 
00142        _genutil_strlcpy(new_locale, language, NAME_LEN);
00143        _genutil_strlcat(new_locale, "_", NAME_LEN);
00144        _genutil_strlcat(new_locale, territory, NAME_LEN);
00145        _genutil_strlcat(new_locale, ".UTF-8", NAME_LEN);
00146 
00147        new_lcd = _XOpenLC(new_locale);
00148        if (new_lcd) {
00149          xim = open_im((XLCd)new_lcd, display, rdb, res_name, res_class);
00150          if (xim) {
00151            _XCloseLC(lcd);  /* no more need */
00152            ((XimCommon)xim)->isUnicode = isMultilingual;
00153            goto Ret;
00154          }
00155          _XCloseLC(new_lcd);
00156          new_lcd = 0;
00157        }
00158       }
00159     }
00160   }
00161 
00162 Ret:
00163   Xfree(current_locale);
00164   return xim;
00165 }
00166 
00167 /********************************************************************************
00168                               XIM callback
00169  ********************************************************************************/
00170 /******************************************************************
00171 
00172            Copyright 1993, 1994 by Sony Corporation
00173 
00174 Permission to use, copy, modify, distribute, and sell this software
00175 and its documentation for any purpose is hereby granted without fee,
00176 provided that the above copyright notice appear in all copies and
00177 that both that copyright notice and this permission notice appear
00178 in supporting documentation, and that the name of Sony Corporation
00179  not be used in advertising or publicity pertaining to distribution
00180  of the software without specific, written prior permission.
00181 Sony Corporation makes no representations about the suitability of
00182  this software for any purpose. It is provided "as is" without
00183  express or implied warranty.
00184 
00185 SONY CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00186 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
00187 EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00188 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
00189 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
00190 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00191 PERFORMANCE OF THIS SOFTWARE.
00192 
00193   Author:   Makoto Wakamatsu   Sony Corporation
00194                                makoto@sm.sony.co.jp
00195 
00196 ******************************************************************/
00197 
00198 typedef struct _XimInstCallback {
00199     Bool                     call;
00200     Bool                     destroy;
00201     Display                 *display;
00202     XLCd                     lcd;
00203     char                     name[NAME_LEN];
00204     char                    *modifiers;
00205     XrmDatabase                     rdb;
00206     char                    *res_name;
00207     char                    *res_class;
00208     XIDProc                  callback;
00209     XPointer                 client_data;
00210     struct _XimInstCallback *next;
00211 } XimInstCallbackRec, *XimInstCallback;
00212 
00213 
00214 static XimInstCallback      callback_list = NULL;
00215 static Bool          lock          = False;
00216 
00217 
00218 static void
00219 MakeLocale(XLCd lcd, char locale[])
00220 {
00221   char *language, *territory, *codeset;
00222 
00223   _XGetLCValues(lcd, XlcNLanguage, &language,
00224               XlcNTerritory, &territory,
00225               XlcNCodeset, &codeset, NULL);
00226 
00227   _genutil_strlcpy(locale, language, NAME_LEN);
00228   if (territory && *territory) {
00229     _genutil_strlcat(locale, "_", NAME_LEN);
00230     _genutil_strlcat(locale, territory, NAME_LEN);
00231   }
00232   if (codeset && *codeset) {
00233     _genutil_strlcat(locale, ".", NAME_LEN);
00234     _genutil_strlcat(locale, codeset, NAME_LEN);
00235   }
00236 }
00237 
00238 
00239 static Bool
00240 _XimFilterPropertyNotify(Display *display,
00241                       Window window,
00242                       XEvent *event,
00243                       XPointer client_data)
00244 {
00245 #if 0
00246     Atom             ims, actual_type, *atoms;
00247     int                     actual_format;
00248     unsigned long    nitems, bytes_after;
00249     Window           ims_window;
00250     int                     ii;
00251     XIM                     xim;
00252     Bool             flag = False;
00253     XimInstCallback  icb, picb, tmp;
00254 
00255     if( (ims = XInternAtom( display, XIM_SERVERS, True )) == None  ||
00256        event->xproperty.atom != ims  ||
00257        event->xproperty.state == PropertyDelete )
00258        return( False );
00259 
00260     if( XGetWindowProperty( display, RootWindow(display, 0), ims, 0L, 1000000L,
00261                          False, XA_ATOM, &actual_type, &actual_format,
00262                          &nitems, &bytes_after, (unsigned char **)&atoms )
00263            != Success ) {
00264        return( False );
00265     }
00266     if( actual_type != XA_ATOM  ||  actual_format != 32 ) {
00267        XFree( atoms );
00268        return( False );
00269     }
00270 
00271     lock = True;
00272     for( ii = 0; ii < nitems; ii++, atoms ) {
00273        if((ims_window = XGetSelectionOwner (display, atoms[ii]))) {
00274            for( icb = callback_list; icb; icb = icb->next ) {
00275               if( !icb->call  &&  !icb->destroy ) {
00276                   xim = (*icb->lcd->methods->open_im)( icb->lcd, display,
00277                                                   icb->rdb,
00278                                                   icb->res_name,
00279                                                   icb->res_class );
00280                   if( xim ) {
00281                      xim->methods->close( (XIM)xim );
00282                      flag = True;
00283                      icb->call = True;
00284                      icb->callback( icb->display, icb->client_data, NULL );
00285                   }
00286               }
00287            }
00288            break;
00289        }
00290     }
00291     XFree( atoms );
00292 
00293     for( icb = callback_list, picb = NULL; icb; ) {
00294        if( icb->destroy ) {
00295            if( picb )
00296               picb->next = icb->next;
00297            else
00298               callback_list = icb->next;
00299            tmp = icb;
00300            icb = icb->next;
00301            XFree( tmp );
00302        }
00303        else {
00304            picb = icb;
00305            icb = icb->next;
00306        }
00307     }
00308     lock = False;
00309 
00310     return( flag );
00311 #else
00312     return False;
00313 #endif
00314 }
00315 
00316 
00317 Bool
00318 _XimRegisterIMInstantiateCallback(
00319     XLCd       lcd,
00320     Display   *display,
00321     XrmDatabase       rdb,
00322     char      *res_name,
00323     char      *res_class,
00324     XIDProc    callback,
00325     XPointer   client_data)
00326 {
00327     XimInstCallback  icb, tmp;
00328     XIM                     xim;
00329     Window           root;
00330     XWindowAttributes       attr;
00331 
00332     if( lock )
00333        return( False );
00334 
00335     icb = (XimInstCallback)Xmalloc(sizeof(XimInstCallbackRec));
00336     if( !icb )
00337        return( False );
00338     icb->call = icb->destroy = False;
00339     icb->display = display;
00340     icb->lcd = lcd;
00341     MakeLocale( lcd, icb->name );
00342     icb->modifiers = lcd->core->modifiers;       /* XXXXX */
00343     icb->rdb = rdb;
00344     icb->res_name = res_name;
00345     icb->res_class = res_class;
00346     icb->callback = callback;
00347     icb->client_data = client_data;
00348     icb->next = NULL;
00349 
00350     if( !callback_list )
00351        callback_list = icb;
00352     else {
00353        for( tmp = callback_list; tmp->next; tmp = tmp->next );
00354        tmp->next = icb;
00355     }
00356 
00357     xim = (*lcd->methods->open_im)( lcd, display, rdb, res_name, res_class );
00358 
00359     if( icb == callback_list ) {
00360        root = RootWindow( display, 0 );
00361        XGetWindowAttributes( display, root, &attr );
00362        _XRegisterFilterByType( display, root, PropertyNotify, PropertyNotify,
00363                             _XimFilterPropertyNotify, (XPointer)NULL );
00364        XSelectInput( display, root,
00365                     attr.your_event_mask | PropertyChangeMask );
00366     }
00367 
00368     if( xim ) {
00369        lock = True;
00370        xim->methods->close( (XIM)xim );
00371        lock = False;
00372        icb->call = True;
00373        callback( display, client_data, NULL );
00374     }
00375 
00376     return( True );
00377 }
00378 
00379 
00380 Bool
00381 _XimUnRegisterIMInstantiateCallback(
00382     XLCd       lcd,
00383     Display   *display,
00384     XrmDatabase       rdb,
00385     char      *res_name,
00386     char      *res_class,
00387     XIDProc    callback,
00388     XPointer   client_data)
00389 {
00390     char locale[NAME_LEN];
00391     XimInstCallback  icb, picb;
00392 
00393     if (!callback_list)
00394        return False;
00395 
00396     MakeLocale( lcd, locale );
00397 
00398     for( icb = callback_list, picb = NULL; icb; picb = icb, icb = icb->next ) {
00399        if( !strcmp( locale, icb->name )  &&
00400            (lcd->core->modifiers == icb->modifiers  ||         /* XXXXX */
00401             (lcd->core->modifiers  &&  icb->modifiers  &&
00402              !strcmp( lcd->core->modifiers, icb->modifiers )))  &&
00403            rdb == icb->rdb  &&                                 /* XXXXX */
00404            ((res_name == NULL  &&  icb->res_name == NULL)  ||
00405             (res_name != NULL  &&  icb->res_name != NULL  &&
00406              !strcmp( res_name, icb->res_name )))  &&
00407            ((res_class == NULL  &&  icb->res_class == NULL)  ||
00408             (res_class != NULL  &&  icb->res_class != NULL  &&
00409              !strcmp( res_class, icb->res_class )))  &&
00410            callback == icb->callback  &&
00411            client_data  ==  icb->client_data  &&        /* XXXXX */
00412            !icb->destroy ) {
00413            if( lock )
00414               icb->destroy = True;
00415            else {
00416               if( !picb ) {
00417                   callback_list = icb->next;
00418                   _XUnregisterFilter( display, RootWindow(display, 0),
00419                                    _XimFilterPropertyNotify,
00420                                    (XPointer)NULL );
00421                   XSelectInput( display, RootWindow(display, 0),
00422                               NoEventMask );
00423               }
00424               else
00425                   picb->next = icb->next;
00426               _XCloseLC( icb->lcd );
00427               XFree( icb );
00428            }
00429            return( True );
00430        }
00431     }
00432     return( False );
00433 }
00434 
00435 void
00436 _XimResetIMInstantiateCallback(XIM xim)
00437 {
00438     char              locale[NAME_LEN];
00439     XimInstCallback   icb;
00440     XLCd              lcd = xim->core.lcd;
00441 
00442     if( !callback_list  &&  lock )
00443        return;
00444 
00445     MakeLocale( lcd, locale );
00446 
00447     for( icb = callback_list; icb; icb = icb->next )
00448        if( !strcmp( locale, icb->name )  &&
00449            (lcd->core->modifiers == icb->modifiers  ||
00450             (lcd->core->modifiers  &&  icb->modifiers  &&
00451              !strcmp( lcd->core->modifiers, icb->modifiers ))) )
00452            icb->call = False;
00453 }