Back to index

im-sdk  12.3.91
switchIM.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2001 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 
00043 #include "commonIM.h"
00044 #include "XimpIm.h"
00045 #include "switchIM.h"
00046 #include "iiimpIM.h"
00047 #include "composeIM.h"
00048 #include "iiimpIC.h"
00049 #include "status.h"
00050 #include "iiimpSwitcher.h"
00051 #include "iiimpAuxP.h"
00052 
00053 static int SwitchCloseIM(XIM);
00054 
00055 extern char* IIIMP_SetIMValues(XIM, XIMArg*);
00056 extern char* IIIMP_GetIMValues(XIM, XIMArg*);
00057 
00058 static XIC SwitchCreateIC(XIM, XIMArg*);
00059 extern int _Ximp_ctstombs(XIM, char*, int, char*, int, Status*);
00060 extern int _Ximp_ctstowcs(XIM, char*, int, wchar_t*, int, Status*);
00061 
00062 static XIMMethods
00063 get_switch_im_methods()
00064 {
00065     static XIMMethodsRec imm;
00066 
00067     if (!imm.close) {
00068        imm.close = SwitchCloseIM;
00069        imm.set_values = IIIMP_SetIMValues;
00070        imm.get_values = IIIMP_GetIMValues;
00071        imm.create_ic = SwitchCreateIC;
00072        imm.ctstombs = _Ximp_ctstombs;
00073        imm.ctstowcs = _Ximp_ctstowcs;
00074     }
00075     return &imm;
00076 }
00077 
00078 
00079 static void DestroyIC(XIC);
00080 static void SetFocus(XIC);
00081 static void UnSetFocus(XIC);
00082 static char *MbReset(XIC);
00083 static wchar_t *WcReset(XIC);
00084 extern char *IIIMP_SetICValues(XIC, XIMArg *);
00085 extern char *IIIMP_GetICValues(XIC, XIMArg *);
00086 static int MbLookupString(XIC, XKeyEvent *,
00087                        char *, int,
00088                        KeySym *, Status *);
00089 static int WcLookupString(XIC, XKeyEvent *,
00090                        wchar_t *, int,
00091                        KeySym *, Status *);
00092 
00093 static XICMethods
00094 get_switch_ic_methods()
00095 {
00096     static XICMethodsRec icm;
00097 
00098     if (!icm.destroy) {
00099        icm.destroy = DestroyIC;
00100        icm.set_focus = SetFocus;
00101        icm.unset_focus = UnSetFocus;
00102        icm.set_values = IIIMP_SetICValues;
00103        icm.get_values = IIIMP_GetICValues;
00104        icm.mb_reset = MbReset;
00105        icm.wc_reset = WcReset;
00106        icm.mb_lookup_string = MbLookupString;
00107        icm.wc_lookup_string = WcLookupString;
00108     }
00109     return &icm;
00110 }
00111 
00112 XIM
00113 _SwitchOpenIM(
00114     XLCd lcd,
00115     Display *dpy,
00116     XrmDatabase rdb,
00117     char *res_name,
00118     char *res_class
00119 )
00120 {
00121     XimCommon im = 0;
00122     char *disableMultiScriptIM = getenv("DISABLE_MULTI_SCRIPT_IM");
00123 
00124     if (disableMultiScriptIM &&
00125        !strcmp("true", disableMultiScriptIM)) return 0; /* hidden feature */
00126 
00127     im = Xmalloc(sizeof(XimCommonRec));
00128     if (!im) goto Error;
00129     memset(im, 0, sizeof(XimCommonRec));
00130 
00131     if (!CommonOpenIM((XIM)im, lcd, dpy, rdb, res_name, res_class))
00132        goto Error;
00133 
00134     im->methods = get_switch_im_methods();
00135 
00136     if (!im_switcher_active(im))
00137       if (!COMPOSE_OpenIM_SWITCH((XIM)im, lcd)) goto Error;
00138 
00139     if (!IIIMP_OpenIM_SWITCH((XIM)im, lcd, dpy)) goto Error;
00140 
00141     return (XIM)im;
00142 
00143 Error:
00144     if (im) Xfree(im);
00145     return 0;
00146 }
00147 
00148 static Status
00149 SwitchCloseIM(
00150     XIM xim
00151 )
00152 {
00153     XimCommon im = (XimCommon)xim;
00154 
00155     XIM_COMPOSE(im, switch_methods)->close(xim);
00156     XIM_IIIMP(im, switch_methods)->close(xim);
00157 
00158     CommonCloseIM((XIM)im);
00159 
00160     return True;
00161 }
00162 
00163 void
00164 RegisterSwitchFilter(
00165     XicCommon ic, 
00166     SwitchKeyEventProc is_switch_key,
00167     XFilterEventProc key_filter,
00168     XICMethods ic_methods
00169 )
00170 {
00171     SwitchFilterEventRec *rec;
00172 
00173     rec = (SwitchFilterEventList)Xmalloc(sizeof(SwitchFilterEventRec));
00174     if (!rec)
00175        return;
00176     rec->is_switch_key = is_switch_key;
00177     rec->key_filter = key_filter;
00178     rec->ic_methods = ic_methods;
00179     rec->next = ic->switch_filters;
00180     ic->switch_filters = rec;
00181     return;
00182 }
00183 
00184 void
00185 UnRegisterSwitchFilter(
00186     XicCommon ic, 
00187     SwitchKeyEventProc is_switch_key,
00188     XFilterEventProc key_filter,
00189     XICMethods ic_methods
00190 )
00191 {
00192     SwitchFilterEventList *prev, fl;
00193 
00194     for (prev = &ic->switch_filters; (fl = *prev) != NULL; ) {
00195        if (fl->is_switch_key == is_switch_key &&
00196            fl->key_filter == key_filter && fl->ic_methods == ic_methods) {
00197            *prev = fl->next;
00198            Xfree((char *)fl);
00199        } else
00200            prev = &fl->next;
00201     }
00202     return;
00203 }
00204 
00205 void
00206 ResetSwitchFilter(
00207     XicCommon ic
00208 )
00209 {
00210     extern Bool Ximp_Local_KeyFilter(Display *, Window, XEvent*, XPointer);
00211 
00212     ic->active_filter = Ximp_Local_KeyFilter; /* default */
00213     ic->active_methods = get_local_ic_methods();
00214     return;
00215 }
00216 
00217 /*
00218   ALLOW_SWITCH_FROM_REMOTE_TO_LOCAL is a bad idea, but for now as
00219   a quick solution to disable switching from a remote language engine
00220   to a local input mode, I have to put these codes..
00221   (by toshi with deepest regrets)
00222 */
00223   
00224 static Bool
00225 Switch_KeyFilter(
00226     Display *d /*unused*/,
00227     Window w /* unused */,
00228     XEvent *ev,
00229     XPointer client_data
00230 )
00231 {
00232     XicCommon ic = (XicCommon)client_data;
00233     SwitchFilterEventList filter;
00234     SwitchMode mode;
00235 #ifndef ALLOW_SWITCH_FROM_REMOTE_TO_LOCAL
00236     Bool IIIMP_Local_KeyFilter(Display *d /*unused*/,
00237                             Window w /* unused */,
00238                             XEvent *ev, XPointer client_data);
00239 #endif
00240 
00241     if (im_switcher_active((XimCommon)ic->core.im))
00242       return IIIMP_Local_KeyFilter (d, w, ev, client_data);
00243 
00244     for (filter = ic->switch_filters; filter; filter = filter->next) {
00245        if (ev->type == KeyPress)
00246            mode = filter->is_switch_key(ic, ev);
00247        else
00248            mode = Switch_NOP;
00249        switch (mode) {
00250          case Switch_ON:
00251           if (filter->next && filter->next->is_switch_key(ic, ev) == Switch_ON) {
00252               /* If this key is used for the next filter too, give way 
00253                 to the next */
00254               ic->active_filter = filter->next->key_filter;
00255               ic->active_methods = filter->next->ic_methods;
00256           } else {
00257               ic->active_filter = filter->key_filter;
00258               ic->active_methods = filter->ic_methods;
00259           }
00260           goto call_filter;
00261          case Switch_OFF:
00262           if (ic->active_filter) {
00263               /* Before turn off active filter, pass the event to the
00264                 handler because it may need to process the event to
00265                 finalize operations.  */
00266               ic->active_filter(d, w, ev, client_data);
00267           }
00268           ResetSwitchFilter(ic);
00269           goto call_filter;
00270          case Switch_NOP:
00271          default:
00272 #ifndef ALLOW_SWITCH_FROM_REMOTE_TO_LOCAL
00273           if (ic->active_filter == IIIMP_Local_KeyFilter)
00274               goto call_filter;
00275 #endif
00276           break;
00277        }
00278     }
00279 call_filter:
00280     if (!ic->active_filter) {
00281        ResetSwitchFilter(ic);
00282     }
00283     return ic->active_filter(d, w, ev, client_data);
00284 }
00285 
00286 static XIC
00287 SwitchCreateIC(
00288     XIM xim,
00289     XIMArg * arg
00290 )
00291 {
00292     XicCommon ic = 0;
00293     ic = Xmalloc(sizeof(XicCommonRec));
00294     if (!ic) goto Error;;
00295     memset(ic, 0, sizeof(XicCommonRec));
00296 
00297     ic->core.im = xim;
00298     ic->methods = get_switch_ic_methods();
00299 
00300     if (!CommonCreateIC((XIC)ic, arg)) goto Error;
00301     
00302     if (!im_switcher_active((XimCommon)ic->core.im))
00303       if (!COMPOSE_CreateIC_SWITCH((XIC)ic, arg)) goto Error;
00304     if (!IIIMP_CreateIC_SWITCH((XIC)ic, arg)) goto Error;
00305 
00306     ic->core.filter_events = KeyPressMask;
00307 
00308     ResetSwitchFilter(ic);
00309 
00310     return (XIC)ic;
00311 Error:
00312     if (ic) Xfree(ic);
00313     return 0;
00314 }
00315 
00316 static void
00317 DestroyIC(
00318     XIC xic
00319 )
00320 {
00321     XicCommon ic = (XicCommon)xic;
00322 
00323     _XUnregisterFilter(ic->core.im->core.display, ic->core.focus_window,
00324                      Switch_KeyFilter, (XPointer)ic);
00325 
00326     IIimpDestroryAuxData(ic);
00327 
00328     if (ic->local_icpart)
00329       XIC_COMPOSE(ic, switch_methods)->destroy(xic);
00330     XIC_IIIMP(ic, switch_methods)->destroy(xic);
00331 
00332     CommonDestroyIC(xic);
00333 
00334     return;
00335 }
00336 
00337 static void
00338 SetFocus(
00339     XIC xic
00340 )
00341 {
00342     XicCommon ic = (XicCommon)xic;
00343 
00344     _XRegisterFilterByType(ic->core.im->core.display, ic->core.focus_window,
00345                         KeyPress, KeyRelease,
00346                         Switch_KeyFilter, (XPointer)ic);
00347     ic->active_methods->set_focus(xic);
00348   
00349     return;
00350 }
00351 
00352 static void
00353 UnSetFocus(
00354     XIC xic
00355 )
00356 {
00357     XicCommon ic = (XicCommon)xic;
00358 
00359     ic->active_methods->unset_focus(xic);
00360   
00361     return;
00362 }
00363 
00364 static char*
00365 MbReset(
00366     XIC xic
00367 )
00368 {
00369     XicCommon ic = (XicCommon)xic;
00370 
00371     _XUnregisterFilter(ic->core.im->core.display, ic->core.focus_window,
00372                      Switch_KeyFilter, (XPointer)ic);
00373     return ic->active_methods->mb_reset(xic);
00374 }
00375 
00376 static wchar_t*
00377 WcReset(
00378     XIC xic
00379 )
00380 {
00381     XicCommon ic = (XicCommon)xic;
00382 
00383     _XUnregisterFilter(ic->core.im->core.display, ic->core.focus_window,
00384                      Switch_KeyFilter, (XPointer)ic);
00385     return ic->active_methods->wc_reset(xic);
00386 }
00387 
00388 static int
00389 MbLookupString(
00390     XIC xic,
00391     XKeyEvent *ev,
00392     char * buffer,
00393     int bytes,
00394     KeySym *keysym,
00395     Status *status
00396 )
00397 {
00398     XicCommon ic = (XicCommon)xic;
00399     int ret;
00400 
00401     ret = IIIMP_MbLookupString_SWITCH(xic, ev, buffer, bytes, keysym, status);
00402     if (0 < ret) {
00403        return ret;
00404     }
00405 
00406     return ic->active_methods->mb_lookup_string(xic,
00407                                           ev, buffer,
00408                                           bytes, keysym,
00409                                           status);
00410 }
00411 
00412 static int
00413 WcLookupString(
00414     XIC xic,
00415     XKeyEvent *ev,
00416     wchar_t * buffer, 
00417     int wlen,
00418     KeySym *keysym,
00419     Status *status
00420 )
00421 {
00422     XicCommon ic = (XicCommon)xic;
00423     int ret;
00424     ret = IIIMP_WcLookupString_SWITCH(xic, ev, buffer, wlen, keysym, status);
00425     if (0 < ret) {
00426        return ret;
00427     }
00428     return ic->active_methods->wc_lookup_string(xic,
00429                                           ev, buffer,
00430                                           wlen, keysym,
00431                                           status);
00432 }
00433       
00434 void
00435 SwitchUpdateStatus(
00436     XicCommon ic
00437 )
00438 {
00439     if (XIM_IS_SWITCH(ic->core.im) &&
00440        (ic->active_methods == get_local_ic_methods()) &&
00441        (None != ic->core.client_window)) {
00442        Ximp_Local_Status_Set(ic);
00443        Ximp_Local_Status_Start(ic);
00444        Ximp_Local_Status_Draw(ic);
00445     }
00446     return;
00447 }
00448 
00449 void
00450 SwitchKeyEventFilter(
00451     XicCommon ic,
00452     Window old_focus
00453 )
00454 {
00455     _XUnregisterFilter(ic->core.im->core.display, old_focus,
00456                      Switch_KeyFilter, (XPointer)ic);
00457     _XRegisterFilterByType(ic->core.im->core.display, ic->core.focus_window,
00458                         KeyPress, KeyRelease,
00459                         Switch_KeyFilter, (XPointer)ic);
00460     return;
00461 }
00462 
00463 /* Local Variables: */
00464 /* c-file-style: "iiim-project" */
00465 /* End: */