Back to index

im-sdk  12.3.91
XSunIMCm.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 #pragma ident   "@(#)XSunIMCm.c    1.1 97/08/20        Sun Microsystems,Inc."
00043 
00044 /******************************************************************
00045 
00046               Copyright 1990, 1991, by Sun Microsystems, Inc.
00047 
00048 Permission to use, copy, modify, distribute, and sell this software
00049 and its documentation for any purpose is hereby granted without fee,
00050 provided that the above copyright notice appear in all copies and
00051 that both that copyright notice and this permission notice appear
00052 in supporting documentation, and that the name of Sun Microsystems, Inc.
00053 not be used in advertising or publicity pertaining to distribution
00054 of the software without specific, written prior permission.
00055 Sun Microsystems, Inc. makes no representations about the suitability of
00056 this software for any purpose.  It is provided "as is" without
00057 express or implied warranty.
00058 
00059 Sun Microsystems Inc. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
00060 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
00061 IN NO EVENT SHALL Sun Microsystems, Inc. BE LIABLE FOR ANY SPECIAL, INDIRECT
00062 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
00063 OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00064 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
00065 OR PERFORMANCE OF THIS SOFTWARE.
00066 
00067   Author: Hideki Hiura (hhiura@Sun.COM)
00068                                         Sun Microsystems, Inc.
00069 ******************************************************************/
00070 
00071 #ifndef lint
00072 #ident  "@(#)XSunIMCm.c     2.7    94/08/08 SMI"
00073 #endif
00074 
00075 /* This module uses many Solaris-specific extensions. */
00076 #define __EXTENSIONS__
00077 
00078 #include <stdio.h>
00079 #include <stdlib.h>
00080 #include <fcntl.h>
00081 #ifdef SVR4
00082 #include <sys/utsname.h>
00083 #include <sys/systeminfo.h>
00084 #endif /* SVR4 */
00085 #ifdef X_LOCALE
00086 #include <X11/Xlocale.h>
00087 #else
00088 #include <locale.h>
00089 #endif
00090 #include <sys/types.h>
00091 #include <sys/stat.h>
00092 #include <X11/X.h>
00093 #include <X11/Xlib.h>
00094 #include <X11/Xlibint.h>
00095 #if XlibSpecificationRelease < 5
00096 #include <X11/XlibR5.h>
00097 #endif /* XlibSpecificationRelease */
00098 #include "XSunExt.h"
00099 #include <X11/keysym.h>
00100 #include <X11/Xutil.h>
00101 
00102 #ifdef sun
00103 #include <X11/Sunkeysym.h>
00104 #ifndef SunXK_Hangul
00105 #define SunXK_Hangul        0xFF31
00106 #endif
00107 #ifndef SunXK_Hangul_Hanja
00108 #define SunXK_Hangul_Hanja  0xFF34
00109 #endif
00110 #endif
00111 
00112 #ifdef SVR4 
00113 #include <libintl.h>
00114 #endif /* SVR4 */
00115 
00116 #include "mle/cm.h"
00117 #include "mle/env.h"
00118 #include "mle/cmkeys.h"
00119 #include <pwd.h>
00120 #include <grp.h>
00121 #include "XSunIMProt.h"
00122 #include "XSunIMPriv.h"
00123 #include "XSunIMMMan.h"
00124 #include "XSunIMMthd.h"
00125 #include "XSunIMCm.h"
00126 #include "XSunIMPub.h"
00127 
00128 #define CM_IF_VERSION "1.26"
00129 
00130 Public int i18nXView2_COMPAT ;
00131 
00132 #define       IMS_CM_NEGO_GET             1
00133 #define       IMS_CM_NEGO_SET      2
00134 
00135 #ifndef ENV_SET_SIMPLE_MODE
00136 /*
00137  * This is for ALE support. JLE header file does not contains this
00138  * declaration.
00139  * ENV_SET_SIMPLE_MODE((e_char *)ce_string) sets the mode to ce_string,
00140  * ENV will display the corresponding string for the mode.
00141  */
00142 #      define ENV_SET_SIMPLE_MODE     117
00143 #endif
00144 
00145 Private Bool             iml_cm_OpenIF      (iml_if_t *, char*, void*);
00146 Private Bool             iml_cm_CloseIF     (iml_if_t *);
00147 Private Bool             iml_cm_GetIFValue  (iml_if_t *, char *, void*);
00148 Private Bool             iml_cm_SetIFValue  (iml_if_t *, char *, void*);
00149 Private void *           iml_cm_CreateSC    (iml_if_t *, void *, char*);
00150 Private Bool             iml_cm_DestroySC   (iml_session_t*);
00151 Private Bool             iml_cm_SetSCValue  (iml_session_t*, char *, void*);
00152 Private Bool             iml_cm_GetSCValue  (iml_session_t*, char *, void*);
00153 Private char *           iml_cm_ResetSC     (iml_session_t*);
00154 Private void             iml_cm_SetSCFocus  (iml_session_t*);
00155 Private void             iml_cm_UnsetSCFocus(iml_session_t*);
00156 Private void             iml_cm_SendEvent   (iml_session_t*, XKeyEvent*);
00157 Private Bool             iml_cm_FilterEvent (XEvent*);
00158 
00159 #ifdef DYNAMICIF
00160 Private
00161 #else
00162 Public
00163 #endif  
00164 if_methods_t cm2_methods = {
00165     iml_cm_OpenIF,      
00166     iml_cm_CloseIF,     
00167     iml_cm_GetIFValue,  
00168     iml_cm_SetIFValue,  
00169     iml_cm_CreateSC,    
00170     iml_cm_DestroySC,   
00171     iml_cm_SetSCValue,  
00172     iml_cm_GetSCValue,  
00173     iml_cm_ResetSC,     
00174     iml_cm_SetSCFocus,  
00175     iml_cm_UnsetSCFocus,
00176     iml_cm_SendEvent,
00177     iml_cm_FilterEvent,
00178     NULL                    /* if_SetAuxValues */
00179 } ;
00180 
00181 Private Bool
00182 iml_cm_OpenIF(If, unused_char, unused_data)
00183 iml_if_t *If ;
00184 char *unused_char;
00185 void *unused_data;
00186 {
00187     cm_opsw_init();
00188     return True ;
00189 }
00190 Private Bool
00191 iml_cm_CloseIF(If)
00192 iml_if_t *If ;
00193 {
00194     return True;
00195 }
00196 Private Bool
00197 iml_cm_GetIFValue(If, attr, value)
00198 iml_if_t *If ;
00199 char *attr;
00200 void *value;
00201 {
00202     if(!strcmp(attr, IF_VERSION)){
00203        *(char**)value = CM_IF_VERSION ;
00204        return True ;
00205     }
00206     return False ;
00207 }
00208 Private Bool
00209 iml_cm_SetIFValue(If, attr, value)
00210 iml_if_t *If ;
00211 char *attr;
00212 void *value;
00213 {
00214     return False ;
00215 }
00216 Private void * 
00217 iml_cm_CreateSC(If, ic, le_name)
00218 iml_if_t *If ;
00219 void *ic ;
00220 char *le_name ; /* This is for multiple language engine per I/F */
00221 {
00222     Private int cm_create_session(/*int id,iml_session_t *s,Bool is_recycled*/);
00223     int le_id;
00224     iml_session_t *s ;
00225 
00226     if(le_name == NULL){
00227        le_id = 0 ;
00228     } else {
00229        le_id = atoi(le_name);
00230     }
00231     return (void *) If->m->iml_construct_session(If, ic, le_id,
00232                                            sizeof(iml_session_t),
00233                                            cm_create_session);
00234 }
00235 Private Bool
00236 iml_cm_DestroySC(s)
00237 iml_session_t *s ;
00238 {
00239     cm_destruct_session(s);
00240 }
00241 Private char * 
00242 iml_cm_ResetSC(s)
00243 iml_session_t *s ;
00244 {
00245     cm_send_commit(s);
00246 }
00247 
00248 Private Bool
00249 iml_cm_SetSCValue(s, attr, value)
00250 iml_session_t *s ;
00251 char *attr ;
00252 void *value ;
00253 {
00254     if(!strcmp(attr, SC_Henkan_Mode) || !strcmp(attr, XNExtXimp_Conversion)){
00255        if((Bool)value == True){
00256            if(!(s->public_status & IMLSTATUS_Henkan_Mode)){
00257               s->public_status |= IMLSTATUS_Henkan_Mode ;
00258               cm_make_conversion_on(s);
00259            }
00260        } else {
00261            if(s->public_status & IMLSTATUS_Henkan_Mode){
00262               s->public_status &= ~IMLSTATUS_Henkan_Mode ;
00263               cm_make_conversion_off(s);
00264            }
00265        }
00266        return True ;
00267     } else if(!strcmp(attr, SC_STATUS)){
00268        if(!(s->public_status & IMLSTATUS_Henkan_Mode)){
00269            if((iml_status_t)value & IMLSTATUS_Henkan_Mode){
00270               cm_make_conversion_on(s);
00271            }
00272        }
00273        s->public_status = (iml_status_t)value ;
00274        return True ;
00275     } else {
00276        if(ims_cm_negotiation_pool(IMS_CM_NEGO_SET, s, attr, value))
00277               return True;
00278        else
00279               return False;
00280     }
00281 }
00282 
00283 Private Bool
00284 iml_cm_GetSCValue(s, attr, value)
00285 iml_session_t *s ;
00286 char *attr ;
00287 void *value ;
00288 {
00289     if(!strcmp(attr, SC_STATUS)){
00290        iml_inst *lp = s->If->m->iml_make_status_notify_inst(s);
00291        *(iml_status_t*)value = s->public_status ;
00292        if(lp = s->If->m->iml_execute(s, &lp)){
00293            cm_eval_results(s, lp);
00294        }
00295        return True ;
00296     }
00297     /* SetSCValue sets the value in negotiation pool and get should get
00298        it from negot pool ??? */
00299     return ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, attr, value);
00300     
00301 }
00302 Private void
00303 iml_cm_SetSCFocus(s)
00304 iml_session_t *s ;
00305 {
00306     iml_inst *lp = s->If->m->iml_make_status_notify_inst(s);
00307     if(lp = s->If->m->iml_execute(s, &lp)){
00308        cm_eval_results(s, lp);
00309     }
00310 }
00311 Private void
00312 iml_cm_UnsetSCFocus(s)
00313 iml_session_t *s ;
00314 {
00315     iml_inst *lp = s->If->m->iml_make_status_notify_inst(s);
00316     if(lp = s->If->m->iml_execute(s, &lp)){
00317        cm_eval_results(s, lp);
00318     }
00319 }
00320     
00321 Private Bool translate_keysym_to_cm_keycode(/*s, keysym, cm_keycode*/) ;
00322 
00323 #define cm_is_conv_on_key(s,l) ((l)>0 && ((s)->conversion_on_key == *((s)->XLookupBuf)))
00324 Private void
00325 iml_cm_SendEvent(s, e)
00326 iml_session_t *s ;
00327 XKeyEvent *e;  /* If this is NULL, this event must be pseudo event */
00328 {
00329     char localename[LOCALENAMELEN];
00330     Private struct cm_to_env cte ;
00331     Private struct cm_to_env *ctep = &cte ;
00332     Private struct env_to_cm etc ;
00333     int l ; /* length of Lookuped string */
00334     iml_inst *lp ;
00335     XComposeStatus NotSuppoted ;
00336     unsigned int   save_state;
00337     
00338     /*
00339      * jle103 engine does not use KeyPress Event
00340      */
00341     if(e && e->type != KeyPress){
00342        return ; 
00343     }
00344     if(e){
00345        s->event = e ; /* save current KeyEvent */
00346     } else {
00347        e = s->event ; /* May NOT be needed: restore KeyEvent */
00348     }
00349 
00350     save_state = e->state;
00351     if(s->public_status & IMLSTATUS_Henkan_Mode && e->state & ControlMask) {
00352        if (e->display)
00353            e->state &= ~e->display->mode_switch;
00354     }
00355     l= s->If->m->iml_lookupString(e, (char*)s->XLookupBuf,s->XLookupBuflen,&s->keysym);
00356     e->state = save_state;
00357 
00358     if(! (s->public_status & IMLSTATUS_Henkan_Mode)){
00359        /*
00360         * in case when conversion mode is off
00361         */
00362        iml_inst *rv ;
00363        if((s->keysym == XK_Henkan_Mode) || 
00364           (s->keysym == SunXK_Hangul) || cm_is_conv_on_key(s,l)){
00365            cm_make_conversion_on(s);
00366            return ;
00367        } 
00368        lp = s->If->m->iml_make_keypress_inst(s, (char*)s->XLookupBuf) ;
00369        if(lp = s->If->m->iml_execute(s, &lp)){
00370            cm_eval_results(s, lp);
00371        }
00372        return ;
00373     }
00374 
00375     if(s->whoIsMaster == CBIsMaster && IS_REGION_ACTIVE(s, LOOKUP)){
00376        lp = s->If->m->iml_make_lookup_process_inst(s, True, 0);
00377        if(lp = s->If->m->iml_execute(s, &lp)){
00378               cm_eval_results(s, lp);
00379        }
00380        return;
00381     }
00382        
00383     /*
00384      * in case when conversion mode is on
00385      */
00386     if(translate_keysym_to_cm_keycode(s, s->keysym, &etc.ec_key, l)){
00387        iml_inst **rrv ;
00388        etc.ec_operation = CM_SIMPLE_EVENT ;
00389        etc.ec_next = NULL ;
00390        ctep = cm_put(s->language_engine, s->session_id, &etc);
00391        eval_cm_to_env_packet(s, ctep);
00392        return;
00393     } else {
00394        /*
00395         * send keypress, but do not what will happen as the results.
00396         */
00397        lp = s->If->m->iml_make_keypress_inst(s, (char*)s->XLookupBuf) ;
00398        if(lp = s->If->m->iml_execute(s, &lp)){
00399            cm_eval_results(s, lp);
00400        }
00401        return;
00402     }
00403 }
00404 
00405 Private Bool
00406 iml_cm_FilterEvent(e)
00407 XEvent *e ;
00408 {
00409     return False ;
00410 }
00411 
00412 Private void
00413 cm_conversion_on(s)
00414 iml_session_t *s;
00415 {
00416     iml_inst *rv ;
00417 
00418     if(s->remainder){
00419        rv = s->remainder ;
00420        s->remainder = NULL ;
00421        return;
00422     }
00423     cm_make_conversion_on(s);
00424 }
00425 
00426 Private void
00427 cm_eval_results(s, results)
00428 iml_session_t *s;
00429 iml_inst *results ;
00430 {
00431     XIMLookupStartCallbackStruct *ls;
00432     XIMLookupProcessCallbackStruct *lp;
00433     Private struct cm_to_env cte ;
00434     int *i ;
00435     
00436     if(results->opcode & IMM_CB_RESULT_REQUIRED){
00437        results->opcode &= ~IMM_CB_RESULT_REQUIRED ;
00438        switch(results->opcode){
00439          case IMM_LOOKUP_START:
00440            ls = (XIMLookupStartCallbackStruct *)& results->operand ;
00441            if(s->whoIsMaster == HasNotBeenNegotiated) {
00442              s->whoIsMaster =  ls->whoIsMaster ;
00443            } else {
00444               break;
00445            }
00446            /*
00447             * Obey CBPreferrence
00448             */
00449            s->XIMPreference = s->CBPreference ;
00450            break;
00451          case IMM_LOOKUP_PROCESS:
00452            lp = (XIMLookupProcessCallbackStruct *)& results->operand ;
00453             switch(lp->index_of_choice_selected) {
00454                 case XIM_UNDETERMINED:
00455                 case XIM_UNKNOWN_KEYSYM:
00456                   /*
00457                    * invalid label input is done.
00458                    */
00459                         break;
00460                 case XIM_UNKNOWN_CONTROL:
00461                         if(s->whoIsMaster == CBIsMaster)
00462                                 cm_select_unknown_control(s);
00463                         break;
00464                 default:
00465                         cm_set_choice(s, lp->index_of_choice_selected);
00466             }
00467            return;
00468        case IMM_PREEDIT_START:
00469            s->PreEditBufferSizeInCallback = *(int *)&results->operand ;
00470            break;
00471          default:
00472            break;
00473        }
00474        return ;
00475     }
00476 }
00477 
00478 Private void
00479 cm_make_conversion_off(s)
00480 iml_session_t *s ;
00481 {
00482     cm_send_commit(s);
00483 }
00484 Private void
00485 cm_make_conversion_on(s)
00486 iml_session_t *s ;
00487 {
00488     iml_inst *rv = NULL;
00489     struct cm_to_env *ctep ;
00490     struct env_to_cm *etcp ;
00491     iml_inst *lp ;
00492     
00493     s->public_status |= IMLSTATUS_Henkan_Mode ;
00494     etcp = (struct env_to_cm *)_iml_new(s, sizeof(struct env_to_cm));
00495     bzero(etcp, sizeof(struct env_to_cm));
00496     etcp->ec_operation = CM_CMON ;
00497     etcp->ec_next = NULL ;
00498     ctep = cm_put(s->language_engine, s->session_id, etcp);
00499     
00500     lp = s->If->m->iml_make_status_notify_inst(s);
00501     s->If->m->iml_link_inst_tail(&rv, lp);
00502     lp = s->If->m->iml_make_preedit_start_inst(s);
00503     s->If->m->iml_link_inst_tail(&rv, lp);
00504     if(lp = s->If->m->iml_execute(s, &rv)){
00505        cm_eval_results(s, lp);
00506     }
00507     eval_cm_to_env_packet(s, ctep);
00508 }
00509 Private int
00510 cm_create_session(cm_id, s, is_recycled)
00511 int cm_id ;
00512 iml_session_t *s ;
00513 Bool is_recycled ;
00514 {
00515     struct cm_initstruct cm_initvalue ;
00516     struct cm_to_env *cte ;
00517     struct env_to_cm etc;
00518     int session_id ;
00519     cmif_spec_t    *if_spec = (cmif_spec_t *)s->If->if_spec ;
00520     
00521     construct_cm_initial_data(& cm_initvalue);
00522     if((session_id = cm_open(cm_id, & cm_initvalue, &cte)) == -1){
00523 #ifdef SVR4
00524         fprintf(stderr,dgettext("SUNW_XIM_HTT_MSG",
00525                  "cm I/F: language engine (id %d) open failed.\n"), cm_id);
00526 #else /* SVR4 */
00527         fprintf(stderr,"cm I/F: language engine (id %d) open failed.\n",cm_id);
00528 #endif /* SVR4 */
00529        return(-1);
00530     }
00531     if(!if_spec) {
00532        if((s->If->if_spec = (void*)calloc(1,sizeof(cmif_spec_t))) == NULL){
00533 #ifdef SVR4
00534             fprintf(stderr,dgettext("SUNW_XIM_HTT_MSG", "htt: exceeds memory high water\n"));
00535 #else /* SVR4 */
00536             fprintf(stderr,"htt: exceeds memory high water\n");
00537 #endif /* SVR4 */
00538            exit(1) ;
00539        }
00540        init_status_string(s);
00541     } 
00542     eval_cm_to_env_packet(s, cte);
00543 
00544     ims_cm_negotiation_init(s, &etc);
00545     if(!cm_initvalue.env_value) {
00546        (void)cm_put(cm_id, session_id, &etc);
00547        s->nego = True;
00548     }
00549     else {
00550        s->nego = False;
00551     }
00552     ims_cm_negotiation_resolve(s, &etc);
00553 
00554     return(session_id);
00555 }
00556 
00557 Private int
00558 construct_cm_initial_data(cm_initp)
00559 struct cm_initstruct *cm_initp;
00560 {
00561     struct group   *gp;
00562     struct passwd  *pp;
00563     Private char     host_name[64];
00564 #ifdef SVR4
00565     static char     id_string[64];
00566 #endif /* SVR4 */    
00567 
00568 #define       ENV_VERSION   2
00569     cm_initp->env_value = (e_char *) ENV_VERSION;
00570 
00571     cm_initp->usr_auth_info.uid = getuid();
00572     cm_initp->usr_auth_info.gid = getgid();
00573 #ifdef SVR4
00574     sysinfo(SI_HW_SERIAL, id_string, sizeof(id_string));
00575     cm_initp->usr_auth_info.hid = atoi(id_string);
00576 #else
00577     cm_initp->usr_auth_info.hid = gethostid();
00578 #endif /* SVR4 */    
00579     pp = getpwuid(getuid());
00580     if (pp != (struct passwd *)NULL)
00581       cm_initp->usr_auth_info.user_name = pp->pw_name;
00582     else
00583       cm_initp->usr_auth_info.user_name = (char *)NULL;
00584     gp = getgrgid(getgid());
00585     if (gp != (struct group *)NULL)
00586       cm_initp->usr_auth_info.grp_name = gp->gr_name;
00587     else
00588       cm_initp->usr_auth_info.grp_name = (char *)NULL;
00589 #ifdef SVR4
00590     sysinfo(SI_HOSTNAME, host_name, sizeof(host_name));
00591 #else  
00592     gethostname(host_name, sizeof(host_name));
00593 #endif /* SVR4 */
00594     cm_initp->usr_auth_info.host_name = host_name;
00595 
00596 }
00597 
00598 Private Bool
00599 ims_cm_negotiation_pool(op, s, attr, value)
00600 int          op;
00601 iml_session_t *s ;
00602 char         *attr;
00603 void         *value;
00604 {
00605     static ImsCmNegotiation   nego;
00606     static LucNegotiation     luc;
00607     static int                    nrows = 0;
00608     static int                    ncols = 0;
00609 
00610     nego.luc = &luc;
00611     switch (op) {
00612        case IMS_CM_NEGO_GET:
00613               if(!strcmp(attr, SC_nego_data)) {
00614                      *(ImsCmNegotiation **)value = &nego;
00615                      return True;
00616               }
00617               if(!strcmp(attr, SC_lookup_ncols)) {
00618                      *(int *)value = ncols;
00619                      return True;
00620               }
00621               if (!strcmp(attr, SC_lookup_nrows)) {
00622                      *(int *)value = nrows;
00623                      return True;
00624               }
00625               if(!strcmp(attr, SC_lookup_root)) {
00626                 *(int *) value = luc.luc_is_rootwindow;
00627                 return True;
00628               }
00629               if(!strcmp(attr, SC_lookup_imscontrol)) {
00630                 *(Bool *) value = luc.ims_takes_control;
00631                 return True;
00632               }
00633               printf ("Unknown option %s\n", attr);
00634               return False;
00635        case IMS_CM_NEGO_SET:
00636               if(!strcmp(attr, SC_lookup_root))
00637                      luc.luc_is_rootwindow = (int)value;
00638               else if(!strcmp(attr, SC_lookup_imscontrol))
00639                      luc.ims_takes_control = (int)value;
00640               else if(!strcmp(attr, SC_lookup_labeltype)) {
00641                      switch ( (int)value ) {
00642                         case IM_LUC_LABEL_NONE:
00643                             luc.label_type  = LUC_LABEL_NONE;
00644                             break;
00645                         case IM_LUC_LABEL_NUMERIC:
00646                             luc.label_type  = LUC_LABEL_NUMERIC;
00647                             break;
00648                         case IM_LUC_LABEL_ALPHABETIC:
00649                             luc.label_type  = LUC_LABEL_ALPHABETIC;
00650                             break;
00651                         case IM_LUC_LABEL_ALPHA_UPPER:
00652                             luc.label_type  = LUC_LABEL_ALPHA_UPPER;
00653                             break;
00654                      }
00655               }
00656               else if(!strcmp(attr, SC_lookup_nchoices))
00657                      luc.choice_per_window = (int)value;
00658               else if(!strcmp(attr, SC_lookup_rootwidth))
00659                      luc.root_width = (int)value;
00660               else if(!strcmp(attr, SC_lookup_lines))
00661                      luc.root_lines = (int)value;
00662               else if(!strcmp(attr, SC_lookup_ewidth))
00663                      luc.e_width_per_can = (int)value;
00664               else if(!strcmp(attr, SC_lookup_cwidth))
00665                      luc.max_width_per_car = (int)value;
00666               else if(!strcmp(attr, SC_lookup_nrows))
00667                      nrows = (int)value;
00668               else if(!strcmp(attr, SC_lookup_ncols))
00669                      ncols = (int)value;
00670               else if(!strcmp(attr, SC_nego_flush))
00671                      if((Bool)value == True)
00672                             ims_cm_luc_negotiation(s);
00673               else if(!strcmp(attr, SC_lookup_direction))
00674                      ;      /* nothing to do */
00675               else if(!strcmp(attr, SC_lookup_whoownslabel))
00676                      ;      /* nothing to do */
00677               else
00678                      return False;
00679               return True;
00680        default:
00681               return False;
00682 
00683     }
00684 }
00685 
00686 Private
00687 ims_cm_negotiation_init(s, etcp)
00688 iml_session_t *s;
00689 struct env_to_cm *etcp;
00690 {
00691     iml_inst *lp ;
00692     ImsCmNegotiation *negop;
00693  
00694     (void)ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, SC_nego_data, &negop);
00695     bzero(etcp, sizeof(struct env_to_cm));
00696     etcp->ec_operation = CM_IMSERVER_NEGOTIATION;
00697     etcp->ec_parameter.ep_string.e_keyptr = (e_char *)(negop);
00698     negop->cm_interested = 0;
00699 }
00700 
00701 Private
00702 ims_cm_negotiation_resolve(s, etcp)
00703 iml_session_t *s;
00704 struct env_to_cm *etcp;
00705 {
00706     ImsCmNegotiation 
00707        *negop = (ImsCmNegotiation *)etcp->ec_parameter.ep_string.e_keyptr;
00708     char      *locale;
00709 
00710    /*
00711     *  Fake!. Wrapper libmle in ja locale assumes that CM_SELECT should
00712     *  be the very first packet once it gets into a selection region.
00713     *  If we send some other packet before CM_SELECT, libmle dies.
00714     *  Thus we pretend that the wrapper libmle responded to this 
00715     *  negotiation and it preferred IM to take control of LUC.
00716     */
00717     locale = setlocale(LC_CTYPE, NULL);
00718     if(!strncmp(locale, "ja", 2)) {
00719        negop->cm_interested |= IM_CM_LUC_NEGOTIATED;
00720        negop->luc->ims_takes_control = 1;
00721     }
00722 
00723     if(negop->cm_interested & IM_CM_LUC_NEGOTIATED) {
00724        int    tmp_ltype;
00725        switch(negop->luc->label_type) {
00726               case LUC_LABEL_NONE:
00727                      tmp_ltype = IM_LUC_LABEL_NONE;
00728                      break;
00729               case LUC_LABEL_ALPHABETIC:
00730                      tmp_ltype = IM_LUC_LABEL_ALPHABETIC;
00731                      break;
00732               case LUC_LABEL_NUMERIC:
00733                      tmp_ltype = IM_LUC_LABEL_NUMERIC;
00734                      break;
00735               case LUC_LABEL_ALPHA_UPPER:
00736                      tmp_ltype = IM_LUC_LABEL_ALPHA_UPPER;
00737                      break;
00738               default:  /* Must be an error within cm_put() */
00739                      tmp_ltype = IM_LUC_LABEL_ALPHABETIC;
00740                      break;
00741        }
00742        if(negop->luc->ims_takes_control) {
00743           /* Things work with CBPreference */
00744               s->whoIsMaster = CBIsMaster;
00745               s->CBPreference.WhoOwnsLabel = CBOwnsLabel;
00746               s->CBPreference.choice_per_window = negop->luc->choice_per_window;
00747               s->CBPreference.label_type = tmp_ltype;
00748               /* Other fieleds should not be changed by cm_put() */
00749                (void)ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, SC_lookup_ncols,
00750                             &(s->CBPreference.ncolumns));
00751                (void)ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, SC_lookup_nrows,
00752                             &(s->CBPreference.nrows));
00753        }
00754        else {
00755           /* Things work with XIMPreference */
00756               s->whoIsMaster = XIMIsMaster;
00757               s->XIMPreference.choice_per_window = negop->luc->choice_per_window;
00758               s->XIMPreference.label_type = tmp_ltype;
00759               /* Followings are the copy of CBPreference data */
00760               s->XIMPreference.WhoOwnsLabel = CBOwnsLabel;
00761                (void)ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, SC_lookup_ncols,
00762                             &s->XIMPreference.ncolumns);
00763                (void)ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, SC_lookup_nrows,
00764                             &s->XIMPreference.nrows);
00765        }
00766     }
00767     else {
00768       /* Things work with XIMPreference */
00769        (void)ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, SC_nego_data, &negop);
00770        s->whoIsMaster = XIMIsMaster;
00771        s->XIMPreference.choice_per_window = negop->luc->choice_per_window;
00772         s->XIMPreference.label_type  = negop->luc->label_type;
00773         s->XIMPreference.WhoOwnsLabel = CBOwnsLabel;
00774         (void)ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, SC_lookup_ncols,
00775                             &s->XIMPreference.ncolumns);
00776         (void)ims_cm_negotiation_pool(IMS_CM_NEGO_GET, s, SC_lookup_nrows,
00777                             &s->XIMPreference.nrows);
00778     }
00779 
00780 }
00781 
00782 ims_cm_luc_negotiation(s)
00783 iml_session_t *s;
00784 {
00785     struct env_to_cm etc;
00786 
00787     ims_cm_negotiation_init(s, &etc);
00788     if(s->nego)
00789        (void)cm_put(s->language_engine, s->session_id, &etc);
00790     ims_cm_negotiation_resolve(s, &etc);
00791 }
00792 
00793 Private 
00794 env_commit(s, rrv, ctep)
00795 iml_session_t *s;
00796 iml_inst **rrv;
00797 struct cm_to_env **ctep;
00798 {
00799     iml_inst *lp ;
00800     struct cm_to_env *rp = get_cte(ctep);
00801     int len;
00802     if(i18nXView2_COMPAT){
00803        lp = s->If->m->iml_make_preedit_erase_inst(s);
00804        s->If->m->iml_link_inst_tail(rrv, lp);
00805        lp = s->If->m->iml_make_preedit_done_inst(s);
00806        s->If->m->iml_link_inst_tail(rrv, lp);
00807     }    
00808     /*
00809      * Only multi byte format can be used for commit string.
00810      */
00811     if (rp->ce_string) {
00812        len = strlen((const char*)rp->ce_string);
00813     } else {
00814        len = 0;
00815     }
00816     lp = s->If->m->iml_make_commit_inst(s, len, rp->ce_string);
00817     s->If->m->iml_link_inst_tail(rrv, lp);
00818 }
00819 
00820 Private 
00821 env_set_current_region(s, rrv, ctep)
00822 iml_session_t *s;
00823 iml_inst **rrv;
00824 struct cm_to_env **ctep;
00825 {
00826     iml_inst *lp ;
00827     iml_inst *results ;
00828     struct cm_to_env *rp = get_cte(ctep);
00829     
00830     switch(rp->ce_region){
00831     case INTERM_REGION:
00832        if(!IS_REGION_ACTIVE(s, PREEDIT)){
00833            ACTIVATE_REGION(s, PREEDIT) ;
00834            lp = s->If->m->iml_make_preedit_start_inst(s);
00835            if(lp = s->If->m->iml_execute(s, &lp)){
00836               cm_eval_results(s, lp);
00837            }
00838        }
00839        lp = s->If->m->iml_make_nop_inst(s);
00840        break;
00841     case MISC_REGION:
00842        /*
00843         * postpone start.
00844         */
00845        _imm_trace("IMM_SET_REGION(AUX)changed to NOP",0,0);
00846        lp = s->If->m->iml_make_nop_inst(s);
00847        break ;
00848     case SELECT_REGION:
00849        if(!IS_REGION_ACTIVE(s, LOOKUP)){
00850            ACTIVATE_REGION(s, LOOKUP) ;
00851            lp = s->If->m->iml_make_lookup_start_inst(s);
00852            if(lp = s->If->m->iml_execute(s, &lp)){
00853               cm_eval_results(s, lp);
00854            }
00855        }
00856        lp = s->If->m->iml_make_nop_inst(s);
00857        break ;
00858     case MODE_REGION:
00859        if(IS_REGION_ACTIVE(s, STATUS )) {
00860            lp = s->If->m->iml_make_nop_inst(s);
00861        } else {
00862            ACTIVATE_REGION(s, LOOKUP) ;
00863            lp = s->If->m->iml_make_status_start_inst(s);
00864        }
00865        break;
00866     }
00867     if(lp) lp->next = NULL ;
00868     *rrv = lp;
00869 }
00870 /*------------------------------------------------------------------*/
00871 
00872 Private 
00873 env_select_prev(s, rrv, ctep)
00874 iml_session_t *s;
00875 iml_inst **rrv;
00876 struct cm_to_env **ctep;
00877 {
00878     iml_inst *lp ;
00879     struct cm_to_env *rp = get_cte(ctep);
00880 
00881     if(!IS_REGION_ACTIVE(s, LOOKUP)){
00882        ACTIVATE_REGION(s, LOOKUP) ;
00883        lp = s->If->m->iml_make_lookup_start_inst(s);
00884        if(lp = s->If->m->iml_execute(s, &lp)){
00885            cm_eval_results(s, lp);
00886        }
00887     }
00888     lp = s->If->m->iml_make_lookup_process_inst(s, False, 0);
00889     s->If->m->iml_link_inst_tail(rrv, lp);
00890     *rrv = lp;
00891 }
00892 Private 
00893 env_cm_off(s, rrv, ctep)
00894 iml_session_t *s;
00895 iml_inst **rrv;
00896 struct cm_to_env **ctep;
00897 {
00898     iml_inst *lp ;
00899     iml_status_t *status ;
00900     struct cm_to_env *rp = get_cte(ctep);
00901     
00902     s->public_status &= ~IMLSTATUS_Henkan_Mode;
00903     lp = s->If->m->iml_make_status_notify_inst(s);
00904     s->If->m->iml_link_inst_tail(rrv, lp);
00905     lp = s->If->m->iml_make_preedit_done_inst(s);
00906     s->If->m->iml_link_inst_tail(rrv, lp);
00907 
00908     _imm_trace("IMM_SET_STATUS",0,*status);
00909 }
00910 Private 
00911 env_setkey_cm_on(s, rrv, ctep)
00912 iml_session_t *s;
00913 iml_inst **rrv;
00914 struct cm_to_env **ctep;
00915 {
00916     iml_inst *lp ;
00917     struct cm_to_env *rp = get_cte(ctep);
00918 
00919     lp = s->If->m->iml_make_nop_inst(s); 
00920     s->If->m->iml_link_inst_tail(rrv, lp);
00921     /*
00922      * Since every thing is done inside imlogic, IMM_GET_KEY is
00923      * now obsolete. conv_on_key is stored as mbchar in session.
00924      */
00925     s->conversion_on_key = rp->ce_rtn_value;/* In multi byte form */
00926     _imm_trace("IMM_NOP(ON key is stored)",s->conversion_on_key,0);
00927 }
00928 Private 
00929 env_nop(s, rrv, ctep)
00930 iml_session_t *s;
00931 iml_inst **rrv;
00932 struct cm_to_env **ctep;
00933 {
00934     iml_inst *lp ;
00935     struct cm_to_env *rp = get_cte(ctep);
00936 
00937     _imm_trace("IMM_NOP(ENV_NOP)",0,0);
00938     lp = s->If->m->iml_make_nop_inst(s);
00939     *rrv = lp ;
00940 }
00941 Private 
00942 env_interm_reset(s, rrv, ctep)
00943 iml_session_t *s;
00944 iml_inst **rrv;
00945 struct cm_to_env **ctep;
00946 {
00947     iml_inst *lp ;
00948     struct cm_to_env *rp = get_cte(ctep);
00949 
00950     _imm_trace("IMM_RESET",0,0);
00951     lp=s->If->m->iml_make_preedit_erase_inst(s);
00952     s->If->m->iml_link_inst_tail(rrv, lp);
00953 }    
00954 Private iml_inst *
00955 make_preedit_draw_inst(s, rp)
00956 iml_session_t *s;
00957 struct cm_to_env *rp ;
00958 {
00959     char    *cmbs = (char *) rp->ce_text ;                  /* current mbstr */
00960     int      cmbl = strlen(cmbs);                           /* current mblen */
00961     wchar_t *cws ;                                          /* current wstr */
00962     int      cwl ;                                          /* current len */
00963     XIMFeedback *cfb ;                                      /* current fb */
00964 
00965     cws = (wchar_t*)_iml_new(s, (cmbl+1)*sizeof(wchar_t));
00966     mbstowcs(cws,cmbs,IML_MAX_SLOT_SIZE);
00967     cwl = wslen(cws);
00968     cfb = _iml_new(s, (cmbl + 1)*sizeof(XIMFeedback));
00969     cm_attr2feedback(cfb, rp->ce_text_attr, cwl, cmbs);
00970 #ifndef NO_COLOR_FEEDBACK
00971     /* Currently, cm/env spec doesn't have color text feedback.
00972      * Up until there is a color feedback, NULL feedback will be
00973      * used. 12/5/93 
00974      *
00975      * cm_colorattr2colortextfeedback(cffg, cfbg, rp->ce_text_attr, cwl, cmbs);
00976      */
00977     return s->If->m->iml_make_preedit_draw_inst(s, cws, cfb, 
00978        (XIMTextColorFeedback *)NULL, (XIMTextColorFeedback *)NULL);
00979 #else
00980     return s->If->m->iml_make_preedit_draw_inst(s, cws, cfb);
00981 #endif  /* NO_COLOR_FEEDBACK */
00982 }
00983 
00984 Private 
00985 env_interm(s, rrv, ctep)
00986 iml_session_t *s;
00987 iml_inst **rrv;
00988 struct cm_to_env **ctep;
00989 {
00990     iml_inst *lp ;
00991     struct cm_to_env *rp = get_cte(ctep);
00992     
00993     if(!IS_REGION_ACTIVE(s, PREEDIT)){
00994        ACTIVATE_REGION(s, PREEDIT) ;
00995        lp = s->If->m->iml_make_preedit_start_inst(s);
00996        if(lp = s->If->m->iml_execute(s, &lp)){
00997            cm_eval_results(s, lp);
00998        }
00999     }
01000     lp = make_preedit_draw_inst(s, rp);
01001     s->If->m->iml_link_inst_tail(rrv, lp);
01002     _imm_trace("IMM_SET_REGION(pseudo PREEDIT)",0,0);
01003 }
01004 Private 
01005 env_m_interactive(s, rrv, ctep)
01006 iml_session_t *s;
01007 iml_inst **rrv;
01008 struct cm_to_env **ctep;
01009 {
01010 #ifdef IMM_AUX_DRAW
01011     iml_inst *lp ;
01012     struct cm_to_env *rp = get_cte(ctep);
01013     
01014     lp = make_preedit_draw_inst(s, rp);
01015     lp->opcode = IMM_AUX_DRAW ;
01016     _imm_trace("IMM_PREEDIT_DRAW(Draw All)",wc_text,p->text.length);
01017     s->If->m->iml_link_inst_tail(rrv, lp);
01018 #endif
01019 }
01020 
01021 Private 
01022 env_select_reset(s, rrv, ctep)
01023 iml_session_t *s;
01024 iml_inst **rrv;
01025 struct cm_to_env **ctep;
01026 {
01027     iml_inst *lp ;
01028     struct cm_to_env *rp = get_cte(ctep);
01029 
01030     _imm_trace("IMM_RESET",0,0);
01031     lp = (iml_inst*)s->If->m->iml_make_lookup_done_inst(s);
01032     s->If->m->iml_link_inst_tail(rrv, lp);
01033 }    
01034 
01035 Private 
01036 env_select(s, rrv, ctep)
01037 iml_session_t *s;
01038 iml_inst **rrv;
01039 struct cm_to_env **ctep;
01040 {
01041     iml_inst *lp ;
01042     struct cm_to_env *rp = get_cte(ctep);
01043     
01044     if(!IS_REGION_ACTIVE(s, LOOKUP)){
01045        ACTIVATE_REGION(s, LOOKUP) ;
01046        lp = s->If->m->iml_make_lookup_start_inst(s);
01047        s->If->m->iml_link_inst_tail(rrv, lp);
01048     }
01049     lp = s->If->m->iml_make_lookup_draw_inst(s, rp->ce_candidate, rp->ce_ncandidate);
01050     s->If->m->iml_link_inst_tail(rrv, lp);
01051     _imm_trace("PSEUDO LOOKUP",0,0);
01052 }
01053 
01054 Private 
01055 env_select_end(s, rrv, ctep)
01056 iml_session_t *s;
01057 iml_inst **rrv;
01058 struct cm_to_env **ctep;
01059 {
01060     iml_inst *lp ;
01061     struct cm_to_env *rp = get_cte(ctep);
01062 
01063     lp = s->If->m->iml_make_lookup_done_inst(s);
01064     s->If->m->iml_link_inst_tail(rrv, lp);
01065     INACTIVATE_REGION(s, LOOKUP) ;
01066 }
01067 Private 
01068 env_select_next(s, rrv, ctep)
01069 iml_session_t *s;
01070 iml_inst **rrv;
01071 struct cm_to_env **ctep;
01072 {
01073     iml_inst *lp ;
01074     struct cm_to_env *rp = get_cte(ctep);
01075 
01076     if(!IS_REGION_ACTIVE(s, LOOKUP)){
01077        ACTIVATE_REGION(s, LOOKUP) ;
01078        lp = s->If->m->iml_make_lookup_start_inst(s);
01079        if(lp = s->If->m->iml_execute(s, &lp)){
01080            cm_eval_results(s, lp);
01081        }
01082     }
01083     lp = s->If->m->iml_make_lookup_process_inst(s, False, 0);
01084     s->If->m->iml_link_inst_tail(rrv, lp);
01085 }
01086 Private 
01087 env_select_commit(s, rrv, ctep)
01088 iml_session_t *s;
01089 iml_inst **rrv;
01090 struct cm_to_env **ctep;
01091 {
01092     iml_inst *lp ;
01093     struct cm_to_env *rp = get_cte(ctep);
01094     
01095     lp = s->If->m->iml_make_lookup_process_inst(s, True, 0);
01096     s->If->m->iml_link_inst_tail(rrv, lp);
01097     _imm_trace("IMM_LOOKUP_PROCESS",0,0);
01098 }
01099 Private 
01100 _env_set_mode(s, rrv, ctep, simple)
01101 iml_session_t *s;
01102 iml_inst **rrv;
01103 struct cm_to_env **ctep;
01104 Bool simple;
01105 {
01106     iml_inst *lp ;
01107     struct cm_to_env *rp = get_cte(ctep);
01108     wchar_t *ws ;
01109     XIMFeedback *fb ;
01110     
01111     if(!IS_REGION_ACTIVE(s, STATUS)){
01112        ACTIVATE_REGION(s, STATUS) ;
01113        lp = s->If->m->iml_make_status_start_inst(s);
01114        s->If->m->iml_link_inst_tail(rrv, lp);
01115     }
01116     ws = s->status_cache.ws ;
01117     if(cm_make_status_string(s, ws, (unsigned char *)rp->ce_mode_list, simple)>0){
01118        register i, l = wslen(s->status_cache.ws) ;
01119        
01120        /*
01121         * could be re-allocated in cm_make_status_string
01122         */
01123        ws = s->status_cache.ws ;
01124        fb = (XIMFeedback *)_iml_new(s, wslen(ws)*sizeof(XIMFeedback));    
01125        for(i = 0 ; i < l ; i++)
01126            s->status_cache.sfb[i] = s->status_cache.fb[i] | XIMTertiary ; /* for stipple */
01127 #ifndef NO_COLOR_FEEDBACK
01128        if(s->private_status & BEING_FOCUSED)
01129            lp = s->If->m->iml_make_status_draw_inst(s, ws, fb,
01130               s->status_cache.cffg, s->status_cache.cfbg);
01131        else
01132            lp = s->If->m->iml_make_status_draw_inst(s, ws, s->status_cache.sfb,
01133               s->status_cache.scffg, s->status_cache.scfbg);
01134 #else
01135        if(s->private_status & BEING_FOCUSED)
01136            lp = s->If->m->iml_make_status_draw_inst(s, ws, fb);
01137        else
01138            lp = s->If->m->iml_make_status_draw_inst(s,ws,s->status_cache.sfb);
01139 #endif  /* NO_COLOR_FEEDBACK */
01140        s->If->m->iml_link_inst_tail(rrv, lp);
01141     } else {
01142        s->status_cache.ws = (wchar_t *) "\00\00\00\00" ;
01143     }
01144     _imm_trace("IMM_STATUS_DRAW",ws,t->length);
01145 }
01146 Private
01147 env_set_mode(s, rrv, ctep)
01148 iml_session_t *s;
01149 iml_inst **rrv;
01150 struct cm_to_env **ctep;
01151 {
01152     _env_set_mode(s, rrv, ctep, 0);
01153 }
01154 Private
01155 env_set_smode(s, rrv, ctep)
01156 iml_session_t *s;
01157 iml_inst **rrv;
01158 struct cm_to_env **ctep;
01159 {
01160     _env_set_mode(s, rrv, ctep, 1);
01161 }
01162 Private 
01163 env_misc_reset(s, rrv, ctep)
01164 iml_session_t *s;
01165 iml_inst **rrv;
01166 struct cm_to_env **ctep;
01167 {
01168     iml_inst *lp ;
01169     struct cm_to_env *rp = get_cte(ctep);
01170 #ifdef IMM_AUX_DONE
01171 /*
01172  * NOT IMPLEMENTED YET
01173  */
01174     _imm_trace("IMM_NOP(ENV_MISC_RESET)",0,0);
01175     lp=(iml_inst*)_iml_new(s, sizeof(iml_inst));
01176     lp->opcode = IMM_AUX_DONE ;
01177     lp->next = NULL ;
01178     s->If->m->iml_link_inst_tail(rrv, lp);
01179 #endif
01180 }    
01181 
01182 Private 
01183 env_m_label(s, rrv, ctep)
01184 iml_session_t *s;
01185 iml_inst **rrv;
01186 struct cm_to_env **ctep;
01187 {
01188     iml_inst *lp ;
01189     struct cm_to_env *rp = get_cte(ctep);
01190 #ifdef IMM_AUX_START
01191     XIMAuxStartCallbackStruct *q ;
01192     XIMText *t;
01193     int l ;
01194 
01195     _imm_trace("IMM_AUX_START(ENV_M_LABEL)",0,0);
01196     _iml_put_current_region(s, AUX) ;
01197     lp=(iml_inst*)_iml_new(s, sizeof(iml_inst)+
01198                         sizeof(XIMAuxStartCallbackStruct));
01199     lp->opcode = IMM_AUX_START ;
01200     lp->next = NULL ;
01201     q = (XIMAuxStartCallbackStruct *)&lp->operand ;
01202     l = strlen(rp->ce_misc_text)*sizeof(wchar_t);
01203     q->event = s->event ;
01204     t = q->label = _iml_new(s, sizeof(XIMText));
01205     t->encoding_is_wchar = True ;
01206     t->string.wide_char = _iml_new(s, l);
01207     t->length = mbstowcs(t->string.wide_char, (char *)rp->ce_misc_text, l)
01208                        *sizeof(wchar_t);
01209     t->feedback = _iml_new(s, t->length);
01210 #ifdef SVR4
01211     memset(t->feedback, 0, t->length);
01212 #else
01213     bzero(t->feedback, t->length);
01214 #endif /* SVR4 */    
01215     t = q->text = _iml_new(s, sizeof(XIMText));        
01216     t->length = 0 ;
01217     s->If->m->iml_link_inst_tail(rrv, lp);
01218 #endif
01219 }
01220 
01221 
01222 /*
01223  * get cm_to_env *cte from cm_to_env link chain and remove from the chain
01224  */
01225 Private struct cm_to_env *
01226 get_cte(ctep)
01227 struct cm_to_env **ctep;
01228 {
01229     struct cm_to_env *rp = NULL ;
01230     if(ctep){
01231        rp = *ctep ;
01232        if (rp != NULL){
01233            *ctep = rp->ce_next ;
01234        } else {
01235            *ctep = NULL ;
01236        }
01237        return rp ;
01238     } 
01239     return NULL;
01240 }
01241 
01242 Private (*opsw[MAX_ENV_OPCODE])();
01243 
01244 Private iml_inst **
01245 eval_it(s, cte, rrv)
01246 iml_session_t *s ;
01247 struct cm_to_env *cte;
01248 iml_inst **rrv;
01249 {
01250     struct cm_to_env *rp ;
01251     iml_inst *lp = 0;
01252     int op ; 
01253 
01254     for(rp = get_cte(&cte) ; rp ; rp = get_cte(&cte)) {
01255        op = rp->ce_operation ;
01256        if(op > MAX_ENV_OPCODE || op < 0 ){
01257 #ifdef SVR4
01258             fprintf(stderr,dgettext("SUNW_XIM_HTT_MSG",
01259             "htt: Invalid opcode %d is specified from cm -- ignored\n"), op);
01260 #else /* SVR4 */
01261             fprintf(stderr,"htt: Invalid opcode %d is specified from cm -- ignored\n", op);
01262 #endif /* SVR4 */
01263            continue ;
01264        }
01265        lp = NULL ;
01266        (*opsw[op])(s, &lp , &rp);
01267        s->If->m->iml_link_inst_tail(rrv, lp);
01268     }
01269     return(&lp->next); /* iml_inst lin last point */
01270 }
01271 Private int
01272 cm_make_status_string(s,ws,s1,simple)
01273 iml_session_t *s ; 
01274 wchar_t *ws ; /* This sould be s->status_cache.ws */
01275 unsigned char *s1 ;
01276 int simple ;
01277 {
01278     wchar_t   *list[MAXSTATUS];
01279     wchar_t   *name[MAXSTATUS];
01280     wchar_t   *value[MAXSTATUS];
01281     wchar_t   *string[MAXSTATUS];
01282     int         order[MAXSTATUS];
01283     int         i = 0, k = 0, j = 0;
01284     int         num = 0;
01285     wchar_t    *p ;
01286     char       *strtok();
01287     wchar_t    *my_wstok();
01288     wchar_t     s2[BUFSIZE];
01289     wchar_t   w[2];
01290     cmif_spec_t *if_spec = (cmif_spec_t *)s->If->if_spec ;
01291     
01292     if(simple){
01293        return mbstowcs(ws, (char *)s1, MAXSTATUS) ; /* assume s < MAXSTATUS */
01294     } else {    
01295        mbstowcs(s2, (char *)s1, BUFSIZE);
01296        mbstowcs(w, "(", 2);
01297        list[i] = (wchar_t *) my_wstok(s2, w);
01298        for (i = 1, num = 0;
01299             ((list[i] =  my_wstok(NULL, w)) != NULL);
01300             i++, num++);
01301 
01302        mbstowcs(w, ")", 2);
01303        for(i = 0; i <= num ; i++)
01304               my_wstok(list[i], w);
01305        
01306        mbstowcs(w, " ", 2);
01307        for (i = 0; i <= num; i++) {
01308            name[i] =  my_wstok(list[i], w);
01309            value[i] = my_wstok(NULL, w);
01310        }
01311        for (i = 0; i <= num; i++) {
01312            if (!((name[i]) && (value[i])))       continue;
01313            for (k = 0; k <= if_spec->NStatusInFile; k++) {
01314               if (((wscmp(name[i], if_spec->StatusString[k].name)) == 0) &&
01315                   (wscmp(value[i], if_spec->StatusString[k].value) == 0)) {
01316                   value[i] = if_spec->StatusString[k].value;
01317                   string[i] = if_spec->StatusString[k].string;
01318                     order[i] = if_spec->StatusString[k].order;
01319                   break;
01320               }
01321            }
01322        }
01323        for (j = 0; j <= num; j++) {
01324            for (i = 0; i <= if_spec->NStatus; i++) {
01325               if (if_spec->CurrentStatusString[i].name &&
01326                   (order[j] == i + 1)){
01327                   if_spec->CurrentStatusString[i].value = value[j];
01328                   if_spec->CurrentStatusString[i].string = string[j];
01329                   break;
01330               }
01331            }
01332        }
01333        p = ws ;
01334        for (i = 0; i <= if_spec->NStatus; i++)
01335          if (if_spec->CurrentStatusString[i].string) {
01336              wscpy(p, if_spec->CurrentStatusString[i].string);
01337              p += wslen(if_spec->CurrentStatusString[i].string);
01338          }
01339        /*
01340         * We don't check the status string length is shorter than 
01341         * s->status_cache.size. This is sort of bug.
01342         * but currently this buffer size is enough big for status string
01343         */
01344        return p - ws ;
01345     }
01346 }
01347 
01348 wchar_t *my_wstok(s1, s2)
01349     wchar_t   *s1;
01350     wchar_t   *s2;
01351 {
01352     wchar_t   *sp;
01353     wchar_t   *t1, *t2;
01354     wchar_t   *ret;
01355     static wchar_t   *ss = (wchar_t *)NULL;
01356     int              match;
01357 
01358     if(s1) {
01359        for(t1 = s1; *t1; t1++) {
01360               match = 0;
01361               for(t2 = s2; *t2; t2++) {
01362                      if(*t1 == *t2) {
01363                             match = 1;
01364                             break;
01365                      }
01366               }
01367               if(!match)
01368                      break;
01369        }
01370         if(!t1) {
01371                ss = (wchar_t *)NULL;
01372                return (wchar_t *)NULL;
01373         }
01374        else {
01375               ss = sp = t1;
01376        }
01377     }
01378     else
01379        sp = ss;
01380 
01381     if( !ss && !s1 )
01382        return (wchar_t *)NULL;
01383 
01384     for(t1 = sp ; *t1; t1++) {
01385        match = 0;
01386        for(t2 = s2; *t2; t2++) {
01387               if(*t1 == *t2) {
01388                      match = 1;
01389                      break;
01390               }
01391        }
01392        if(match) {
01393               *t1 = (wchar_t)NULL;
01394               ret = ss;
01395               ss = ++t1;
01396               return ret;
01397        }
01398     }
01399     
01400     ret = ss;
01401     ss = (wchar_t *)NULL;
01402     return ret;
01403 }
01404 
01405 Private unsigned char *
01406 get_mlepath(s, path)
01407 iml_session_t *s ;
01408 char *path;
01409 {
01410     char *openwinpath,*mlepath,*getenv();
01411     struct stat statbuf;    
01412 
01413     if ((mlepath = getenv("MLEPATH")) != (char *)0) {
01414        sprintf(path, "%s/%s/%s\0", mlepath, s->If->locale, MODE_DAT_PATH);
01415         if (stat(path, &statbuf) >= 0) {
01416             return (unsigned char *) path ;
01417        }
01418     }
01419     if ((openwinpath = getenv("OPENWINHOME")) != (char *)0) {
01420        sprintf(path, "%s/%s/%s/%s\0", openwinpath, OW_LOCALE_PATH,
01421                      s->If->locale, MODE_DAT_PATH);
01422        if (stat(path, &statbuf) >= 0) {
01423               return (unsigned char *) path ;
01424        }
01425     }
01426     sprintf(path, "%s/%s/%s/%s\0", DEFAULT_OPENWINHOME, OW_LOCALE_PATH,
01427                      s->If->locale, MODE_DAT_PATH);
01428     if (stat(path, &statbuf) >= 0) {
01429        return (unsigned char *) path ;
01430     }
01431     sprintf(path, "%s/%s/%s\0", DEFAULT_MLEPATH, s->If->locale, MODE_DAT_PATH);
01432     if (stat(path, &statbuf) >= 0) {
01433        return (unsigned char *) path ;
01434     }
01435     sprintf(path, "%s/%s/%s\0", DEFAULT_MLEPATH, s->If->locale, XXXCOMPAT_MODE_DAT_PATH);
01436     if (stat(path, &statbuf) >= 0) {
01437        return (unsigned char *) path ;
01438     }
01439     /*
01440      * Because this mode.dat file is JLE cm specific
01441      */
01442     sprintf(path, "%s/%s/%s\0", DEFAULT_MLEPATH, "ja", XXXCOMPAT_MODE_DAT_PATH);
01443     if (stat(path, &statbuf) >= 0) {
01444        return (unsigned char *) path ;
01445     }
01446     sprintf(path, "%s/%s/%s\0", DEFAULT_MLEPATH, "japanese", XXXCOMPAT_MODE_DAT_PATH);
01447     return (unsigned char *) path ;
01448 }
01449 Private void
01450 init_status_string(s)
01451 iml_session_t *s ;
01452 {
01453     int                 file_fd;
01454     char           *name;
01455     char           *value;
01456     char           *p1, *p2;
01457     char           buf[BUFSIZE];
01458     wchar_t      buf2[BUFSIZE];
01459     int j, k;
01460     cmif_spec_t    *if_spec = (cmif_spec_t *)s->If->if_spec ;
01461 #ifndef MAXPATHLEN
01462 #define MAXPATHLEN 255
01463 #endif
01464     char mlepath[MAXPATHLEN];
01465     (void)get_mlepath(s, mlepath);
01466     if_spec->NStatusInFile = -1 ;
01467     file_fd = open((char *) mlepath, O_RDONLY);
01468     if (file_fd == -1) {    /* just in case, try again */
01469        sleep(1);
01470        file_fd = open((char *) mlepath, O_RDONLY);
01471     }
01472     if(file_fd) {
01473        ReadOneLine((char *)NULL, 0, file_fd);
01474        while ((ReadOneLine(buf, BUFSIZE, file_fd)) != 0) {
01475            if (buf[0] == '#')
01476              continue;
01477            if_spec->NStatusInFile++;
01478            p1 = buf;
01479            p2 = (char *) index(p1, ':');
01480            *p2 = '\0';
01481            mbstowcs(if_spec->StatusString[if_spec->NStatusInFile].name,
01482                    p1, p2 - p1);
01483            p1 = p2 + 1;
01484            p2 = (char *) index(p1, ':');
01485            *p2 = '\0';
01486            mbstowcs(if_spec->StatusString[if_spec->NStatusInFile].value,
01487                    p1, p2 - p1);
01488            p1 = p2 + 1;
01489            p2 = (char *) index(p1, ':');
01490            *p2 = '\0';
01491            mbstowcs(if_spec->StatusString[if_spec->NStatusInFile].string,
01492                    p1, p2 - p1);
01493            if_spec->StatusString[if_spec->NStatusInFile].order =
01494              atoi(p2 + 1);
01495        }
01496        k = if_spec->StatusString[0].order - 1;
01497        if_spec->CurrentStatusString[k].name = if_spec->StatusString[0].name;
01498        if_spec->CurrentStatusString[k].value = if_spec->StatusString[0].value;
01499        if_spec->CurrentStatusString[k].string = if_spec->StatusString[0].string;
01500        
01501        for (j = 1, if_spec->NStatus = 0; j <= if_spec->NStatusInFile; j++) {
01502            if ((!if_spec->CurrentStatusString[k].name) ||
01503               (!if_spec->StatusString[j].name))
01504              continue;
01505            if ((wscmp(if_spec->CurrentStatusString[k].name,
01506                      if_spec->StatusString[j].name))!= 0) {
01507               k = if_spec->StatusString[j].order - 1;
01508               if_spec->CurrentStatusString[k].name = if_spec->StatusString[j].name;
01509               if_spec->CurrentStatusString[k].value = if_spec->StatusString[j].value;
01510               if_spec->CurrentStatusString[k].string = if_spec->StatusString[j].string;
01511               if_spec->NStatus++;
01512            }
01513        }
01514        close(file_fd);
01515     } else {
01516        /* assume using SIMPLE MODE */
01517     }
01518 }
01519 
01520 Private
01521 ReadOneLine(buf, nb, fd)
01522 char  *buf;
01523 int   nb;
01524 int   fd;
01525 {
01526     int                read_bytes;
01527     char        *readpointer, *endofline;
01528     static char        ibuf[BUFSIZE];
01529     static int         index = 0;
01530     int                prevbytes = 0;
01531     int                returnbytes;
01532 
01533     if(nb == 0){
01534        index = 0;
01535        return 0;
01536     }
01537        
01538     readpointer = ibuf + index;
01539     if(index == 0) {
01540        read_bytes = read(fd, ibuf, nb-1);
01541        if(read_bytes <= 0)
01542               return NULL;
01543        ibuf[read_bytes] = 0;
01544     }
01545 
01546     if(!(endofline = (char *) strchr(readpointer, (int)'\n'))) {
01547        prevbytes = BUFSIZE-index-1;
01548        bcopy(readpointer, buf, prevbytes);
01549        read_bytes = read(fd, ibuf, nb-1);
01550        if(read_bytes <= 0)
01551               return NULL;
01552        ibuf[read_bytes] = 0;
01553        if(!(endofline = (char *) strchr(ibuf , (int)'\n')))
01554               return NULL;
01555        readpointer = ibuf;
01556     }
01557 
01558     returnbytes = endofline - readpointer + 1;
01559     bcopy(readpointer, buf + prevbytes, returnbytes);
01560     buf[prevbytes + returnbytes] = 0;
01561     index = endofline - ibuf + 1;
01562      
01563     return (returnbytes);
01564 }
01565 
01566 Private void
01567 eval_cm_to_env_packet(s, cte)
01568 iml_session_t *s ;
01569 struct cm_to_env *cte;
01570 {
01571     iml_inst *rv = NULL ;
01572     eval_it(s, cte, &rv);
01573     if(rv = s->If->m->iml_execute(s, &rv)){
01574        cm_eval_results(s, rv);
01575     }
01576 }
01577 Private void
01578 cm_destruct_session(s)
01579 iml_session_t *s ;
01580 {
01581     s->If->m->iml_destruct_session(s, destruct_session);
01582 
01583 }
01584 Private int
01585 destruct_session(s)
01586 iml_session_t *s ;
01587 {
01588     struct cm_to_env *ctep = (struct cm_to_env *)
01589        cm_close(s->language_engine, s->session_id);
01590     eval_cm_to_env_packet(s, ctep);
01591     return 0;
01592 }
01593 
01594 Private void
01595 cm_reset(s, rrv)
01596 iml_session_t *s ;
01597 iml_inst **rrv ;
01598 {
01599     iml_inst *lp ;
01600     lp = s->If->m->iml_make_nop_inst(s);
01601     s->If->m->iml_link_inst_tail(rrv, lp);
01602 }
01603 /*
01604  * Commit intermediate text by sending CM_RESET to Language engine.
01605  * This function is called from XmbReset();
01606  * IMLogic(,,IML_COMMIT,) and then iml_send_commit().
01607  * Assignment of cm_send_commit() to function entity of
01608  * iml_send_commit() is done in cm_configure().
01609  *
01610  */
01611 Private void
01612 cm_send_commit(s)
01613 iml_session_t *s;
01614 {
01615     struct cm_to_env *ctep;
01616     static struct env_to_cm etc;
01617 
01618     if(s->remainder){
01619        if(s->remainder = s->If->m->iml_execute(s, &s->remainder)){
01620            cm_eval_results(s, s->remainder);
01621        }
01622         s->remainder = NULL;
01623         return;
01624     }
01625     etc.ec_operation = CM_RESET;
01626     etc.ec_next = NULL ;
01627     s->public_status &= ~IMLSTATUS_Henkan_Mode ;
01628     ctep = cm_put(s->language_engine, s->session_id, &etc);
01629     eval_cm_to_env_packet(s, ctep);
01630 }
01631 
01632 Private void
01633 cm_set_choice(s, i)
01634 iml_session_t *s ;
01635 int i ; /* index */
01636 {
01637     Private struct cm_to_env cte ;
01638     Private struct cm_to_env *ctep = &cte ;
01639     Private struct env_to_cm etc ;
01640     
01641     etc.ec_operation = CM_SELECT ;
01642     etc.ec_select = i ;
01643     etc.ec_next = NULL ;
01644     ctep = cm_put(s->language_engine, s->session_id, &etc);
01645     eval_cm_to_env_packet(s, ctep);
01646     /* BugId : 4212962. Do not free memory here
01647        _iml_delete2(s); */
01648 }
01649 
01650 Private void
01651 cm_select_unknown_control(s)
01652 iml_session_t *s ;
01653 {
01654     Private struct cm_to_env cte ;
01655     Private struct cm_to_env *ctep = &cte ;
01656     Private struct env_to_cm etc ;
01657 
01658     if(translate_keysym_to_cm_keycode(s, s->keysym, &etc.ec_key, 1)){
01659         iml_inst **rrv ;
01660         etc.ec_operation = CM_SIMPLE_EVENT;
01661         etc.ec_next = NULL ;
01662         ctep = cm_put(s->language_engine, s->session_id, &etc);
01663         eval_cm_to_env_packet(s, ctep);
01664     }
01665 }
01666 
01667 Private void
01668 cm_attr2feedback(p, q, len, e)
01669 XIMFeedback *p ;
01670 unsigned char *q ; 
01671 int len ;
01672 char *e ;
01673 {
01674     register i,j,l;
01675     register char r ;
01676     
01677 #ifdef DEBUG
01678     _iml_xdmem(q,len*sizeof(wchar_t));
01679 #endif
01680     
01681     for(i=0,j=0;j<len;i+=l,j++){
01682 #ifdef NEXT_GENERATION_OF_JLE_ATTRIBUTE_COMPATIBLE
01683        p[i] = q[j] ;
01684 #else
01685        l = mblen(e+i,4);
01686        r = q[i];
01687        p[j]=0;
01688 
01689        if(r & ATTR_REVERSE)
01690          p[j] |= XIMReverse ;
01691        else
01692          p[j] |= XIMUnderline ; /* because of cm bug */
01693 
01694 #endif
01695     }
01696     
01697 #ifdef DEBUG
01698     _iml_xdmem(p,len*sizeof(XIMFeedback)) ;
01699 #endif
01700 }
01701 Private void
01702 cm_opsw_init(void)
01703 {
01704     register i ;
01705     
01706     if(opsw[ENV_NOP]) return;
01707 
01708     for(i = 0 ; i < MAX_ENV_OPCODE ; i++){
01709        opsw[i] = env_nop ;
01710     }
01711     opsw[ENV_NOP] = env_nop ;
01712     opsw[ENV_COMMIT] = env_commit ;
01713     opsw[ENV_SET_CURRENT_REGION] = env_set_current_region ;
01714     opsw[ENV_CM_OFF] = env_cm_off ;
01715     opsw[ENV_SETKEY_CM_ON] = env_setkey_cm_on ;
01716     opsw[ENV_INTERM_RESET] = env_interm_reset ;
01717     opsw[ENV_INTERM] = env_interm ;
01718     opsw[ENV_M_INTERACTIVE] = env_m_interactive ;
01719     opsw[ENV_SELECT_RESET] = env_select_reset ;
01720     opsw[ENV_SELECT] = env_select ;
01721     opsw[ENV_SELECT_END] = env_select_end ;
01722     opsw[ENV_SELECT_NEXT] = env_select_next ;
01723     opsw[ENV_SELECT_PREV] = env_select_prev ;
01724     opsw[ENV_SELECT_COMMIT] = env_select_commit ;
01725     opsw[ENV_SELECT_TEST] = env_nop ;
01726     opsw[ENV_SET_SIMPLE_MODE] =  env_set_smode ;
01727     opsw[ENV_SET_MODE] = env_set_mode ;
01728     opsw[ENV_MISC_RESET] = env_misc_reset ;
01729     opsw[ENV_M_LABEL] = env_m_label ;
01730     opsw[ENV_M_MESS] = env_nop ;
01731 
01732 }
01733 Private Bool
01734 translate_keysym_to_cm_keycode(s, keysym, cm_keycode, l)
01735 iml_session_t *s ;
01736 KeySym keysym ;
01737 unsigned long *cm_keycode;
01738 int    l;
01739 {
01740 #define functionKey(keysym,s) 
01741     switch(keysym){
01742       case XK_Shift_L:
01743       case XK_Shift_R:
01744       case XK_Control_L:
01745       case XK_Control_R:
01746       case XK_Caps_Lock:
01747       case XK_Shift_Lock:
01748       case XK_Meta_L:
01749       case XK_Meta_R:
01750       case XK_Alt_L:
01751       case XK_Alt_R:
01752       case XK_Super_L:
01753       case XK_Super_R:
01754       case XK_Hyper_L:
01755       case XK_Hyper_R:
01756        /*
01757         * Only modifier key is coming..
01758         */
01759        return False;
01760        /*
01761         * Function Key Operations
01762         */
01763       case XK_Multi_key: /* 0xFF20  Multi-key character compose */
01764        functionKey( XK_Multi_key, "XK_Multi_key");
01765        break;
01766       case XK_Kanji: /* 0xFF21     Kanji, Kanji convert */
01767        functionKey( XK_Kanji, "XK_Kanji");
01768        *cm_keycode = 0x0002 | CM_BF_START ;
01769        goto VALID;
01770        break;
01771       case XK_Muhenkan: /* 0xFF22   Cancel Conversion */
01772        functionKey( XK_Muhenkan, "XK_Muhenkan");
01773        break;
01774       case SunXK_Hangul: /* 0xFF31  Start/Stop Conversion */
01775       case XK_Henkan_Mode: /* 0xFF23  Start/Stop Conversion */
01776        functionKey( XK_Henkan_Mode, "XK_Henkan_Mode");
01777        *cm_keycode = 0x0003 | CM_BF_START ;
01778        goto VALID;
01779        break;
01780       case XK_Romaji: /* 0xFF24   to Romaji */
01781        functionKey( XK_Romaji, "XK_Romaji");
01782        break;
01783       case XK_Hiragana: /* 0xFF25   to Hiragana */
01784        functionKey( XK_Hiragana, "XK_Hiragana");
01785        break;
01786       case XK_Katakana: /* 0xFF26   to Katakana */
01787        functionKey( XK_Katakana, "XK_Katakana");
01788        break;
01789       case XK_Hiragana_Katakana: /* 0xFF27  Hiragana/Katakana toggle */
01790        functionKey( XK_Hiragana_Katakana, "XK_Hiragana_Katakana");
01791        break;
01792       case XK_Zenkaku: /* 0xFF28   to Zenkaku */
01793        functionKey( XK_Zenkaku, "XK_Zenkaku");
01794        break;
01795       case XK_Hankaku: /* 0xFF29   to Hankaku */
01796        functionKey( XK_Hankaku, "XK_Hankaku");
01797        break;
01798       case XK_Zenkaku_Hankaku: /* 0xFF2A   Zenkaku/Hankaku toggle */
01799        functionKey( XK_Zenkaku_Hankaku, "XK_Zenkaku_Hankaku");
01800        break;
01801       case XK_Touroku: /* 0xFF2B   Add to Dictionary */
01802        functionKey( XK_Touroku, "XK_Touroku");
01803        break;
01804       case XK_Massyo: /* 0xFF2C   Delete from Dictionary */
01805        functionKey( XK_Massyo, "XK_Massyo");
01806        break;
01807       case XK_Kana_Lock: /* 0xFF2D  Kana Lock */
01808        functionKey( XK_Kana_Lock, "XK_Kana_Lock");
01809        break;
01810       case XK_Kana_Shift: /* 0xFF2E  Kana Shift */
01811        functionKey( XK_Kana_Shift, "XK_Kana_Shift");
01812        break;
01813       case XK_Eisu_Shift: /* 0xFF2F  Alphanumeric Shift */
01814        functionKey( XK_Eisu_Shift, "XK_Eisu_Shift");
01815        break;
01816       case XK_Eisu_toggle: /* 0xFF30  Alphanumeric toggle */
01817        functionKey( XK_Eisu_toggle, "XK_Eisu_toggle");
01818        break;
01819       case XK_Home: /*      0xFF50 */
01820        functionKey( XK_Home, "XK_Home");
01821        break;
01822       case XK_Left: /*      0xFF51 Move left, left arrow */
01823        functionKey( XK_Left, "XK_Left");
01824        break;
01825       case XK_Up: /*        0xFF52 /* Move up, up arrow */
01826        functionKey( XK_Up, "XK_Up");
01827        break;
01828       case XK_Right: /* 0xFF53     /* Move right, right arrow */
01829        functionKey( XK_Right, "XK_Right");
01830        break;
01831       case XK_Down: /*      0xFF54 /* Move down, down arrow */
01832        functionKey( XK_Down, "XK_Down");
01833        break;
01834       case XK_Prior: /* 0xFF55     /* Prior, previous */
01835        functionKey( XK_Prior, "XK_Prior");
01836        break;
01837       case XK_Next: /*      0xFF56 /* Next */
01838        functionKey( XK_Next, "XK_Next");
01839        break;
01840       case XK_End: /*       0xFF57 /* EOL */
01841        functionKey( XK_End, "XK_End");
01842        break;
01843       case XK_Begin: /* 0xFF58     /* BOL */
01844        functionKey( XK_Begin, "XK_Begin");
01845        break;
01846       case XK_Select: /* 0xFF60     Select, mark */
01847        functionKey( XK_Select, "XK_Select");
01848        break;
01849       case XK_Print: /* 0xFF61 */
01850        functionKey( XK_Print, "XK_Print");
01851        break;
01852       case XK_Execute: /* 0xFF62  Execute, run, do */
01853        functionKey( XK_Execute, "XK_Execute");
01854        *cm_keycode = 0xb001 | CM_BF_START ;
01855        goto VALID;
01856        break;
01857       case XK_Insert: /* 0xFF63     Insert, insert here */
01858        functionKey( XK_Insert, "XK_Insert");
01859        break;
01860       case XK_Undo: /*      0xFF65 Undo, oops */
01861        functionKey( XK_Undo, "XK_Undo");
01862        break;
01863       case XK_Redo: /*      0xFF66 redo, again */
01864        functionKey( XK_Redo, "XK_Redo");
01865        break;
01866       case XK_Menu: /*      0xFF67 */
01867        functionKey( XK_Menu, "XK_Menu");
01868        break;
01869       case XK_Find: /*      0xFF68  Find, search */
01870        functionKey( XK_Find, "XK_Find");
01871        break;
01872       case XK_Cancel: /* 0xFF69    Cancel, stop, abort, exit */
01873        functionKey( XK_Cancel, "XK_Cancel");
01874        break;
01875       case XK_Help: /*      0xFF6A Help, ? */
01876        functionKey( XK_Help, "XK_Help");
01877        break;
01878       case XK_Break: /* 0xFF6B */
01879        functionKey( XK_Break, "XK_Break");
01880        break;
01881       case XK_Mode_switch: /* 0xFF7E Character set switch */
01882        /* case XK_script_switch: 0xFF7E Alias for mode_switch */
01883        functionKey( XK_Mode_switch, "XK_Mode_switch");
01884        /*
01885         * something wrong in cm if there is any problem here.
01886         */
01887        *cm_keycode = 0xb004 | CM_BF_START ;
01888        goto VALID;
01889        break;
01890       case SunXK_Hangul_Hanja: /* 0xFF34 HangleCharacter set switch */
01891        functionKey( SunXK_Hangul_Hanja, "SunXK_Hangui_Hanja");
01892        *cm_keycode = 0xb004 | CM_BF_START ;
01893        goto VALID;
01894        break;
01895       case XK_Num_Lock: /* 0xFF7F */
01896        functionKey( XK_Num_Lock, "XK_Num_Lock");
01897        *cm_keycode = 0xb004 | CM_RF_START ;
01898        break;
01899       case XK_KP_Space: /* 0xFF80   space */
01900        functionKey( XK_KP_Space, "XK_KP_Space");
01901        break;
01902       case XK_KP_Tab: /* 0xFF89 */
01903        functionKey( XK_KP_Tab, "XK_KP_Tab");
01904        break;
01905       case XK_KP_Enter: /* 0xFF8D enter */
01906        functionKey( XK_KP_Enter, "XK_KP_Enter");
01907        *cm_keycode = '\n';
01908        goto VALID;
01909        break;
01910       case XK_KP_F1: /* 0xFF91     PF1, KP_A, ... */
01911        functionKey( XK_KP_F1, "XK_KP_F1");
01912        break;
01913       case XK_KP_F2: /* 0xFF92 */
01914        functionKey( XK_KP_F2, "XK_KP_F2");
01915        break;
01916       case XK_KP_F3: /* 0xFF93 */
01917        functionKey( XK_KP_F3, "XK_KP_F3");
01918        break;
01919       case XK_KP_F4: /* 0xFF94 */
01920        functionKey( XK_KP_F4, "XK_KP_F4");
01921        break;
01922       case XK_KP_Equal: /* 0xFFBD  equals */
01923        functionKey( XK_KP_Equal, "XK_KP_Equal");
01924        *cm_keycode = '=';
01925        goto VALID;
01926        break;
01927       case XK_KP_Multiply: /* 0xFFAA */
01928        functionKey( XK_KP_Multiply, "XK_KP_Multiply");
01929        *cm_keycode = '*';
01930        goto VALID;
01931        break;
01932       case XK_KP_Add: /* 0xFFAB */
01933        functionKey( XK_KP_Add, "XK_KP_Add");
01934        *cm_keycode = '+';
01935        goto VALID;
01936        break;
01937       case XK_KP_Separator: /* 0xFFAC separator, often comma */
01938        functionKey( XK_KP_Separator, "XK_KP_Separator");
01939        *cm_keycode = ',';
01940        goto VALID;
01941        break;
01942       case XK_KP_Subtract: /* 0xFFAD */
01943        functionKey( XK_KP_Subtract, "XK_KP_Subtract");
01944        *cm_keycode = '-';
01945        goto VALID;
01946        break;
01947       case XK_KP_Decimal: /* 0xFFAE */
01948        functionKey( XK_KP_Decimal, "XK_KP_Decimal");
01949        *cm_keycode = '.';
01950        goto VALID;
01951        break;
01952       case XK_KP_Divide: /* 0xFFAF */
01953        functionKey( XK_KP_Divide, "XK_KP_Divide");
01954        *cm_keycode = '/';
01955        goto VALID;
01956        break;
01957       case XK_KP_0: /*      0xFFB0 */
01958        functionKey( XK_KP_0, "XK_KP_0");
01959        *cm_keycode = '0';
01960        goto VALID;
01961        break;
01962       case XK_KP_1: /*      0xFFB1 */
01963        functionKey( XK_KP_1, "XK_KP_1");
01964        *cm_keycode = '1';
01965        goto VALID;
01966        break;
01967       case XK_KP_2: /*      0xFFB2 */
01968        functionKey( XK_KP_2, "XK_KP_2");
01969        *cm_keycode = '2';
01970        goto VALID;
01971        break;
01972       case XK_KP_3: /*      0xFFB3 */
01973        functionKey( XK_KP_3, "XK_KP_3");
01974        *cm_keycode = '3';
01975        goto VALID;
01976        break;
01977       case XK_KP_4: /*      0xFFB4 */
01978        functionKey( XK_KP_4, "XK_KP_4");
01979        *cm_keycode = '4';
01980        goto VALID;
01981        break;
01982       case XK_KP_5: /*      0xFFB5 */
01983        functionKey( XK_KP_5, "XK_KP_5");
01984        *cm_keycode = '5';
01985        goto VALID;
01986        break;
01987       case XK_KP_6: /*      0xFFB6 */
01988        functionKey( XK_KP_6, "XK_KP_6");
01989        *cm_keycode = '6';
01990        goto VALID;
01991        break;
01992       case XK_KP_7: /*      0xFFB7 */
01993        functionKey( XK_KP_7, "XK_KP_7");
01994        *cm_keycode = '7';
01995        goto VALID;
01996        break;
01997       case XK_KP_8: /*      0xFFB8 */
01998        functionKey( XK_KP_8, "XK_KP_8");
01999        *cm_keycode = '8';
02000        goto VALID;
02001        break;
02002       case XK_KP_9: /*  0xFFB9 */
02003        functionKey( XK_KP_9, "XK_KP_9");
02004        *cm_keycode = '9';
02005        goto VALID;
02006        break;
02007       case XK_F1:
02008        functionKey(XK_F1,"XK_F1");
02009        *cm_keycode = 0x1 | CM_TF_START ;
02010        goto VALID;
02011        break;
02012       case XK_F2:
02013        functionKey(XK_F2,"XK_F2");
02014        *cm_keycode = 0x2 | CM_TF_START ;
02015        goto VALID;
02016        break;
02017       case XK_F3:
02018        functionKey(XK_F3,"XK_F3");
02019        *cm_keycode = 0x3 | CM_TF_START ;
02020        goto VALID;
02021        break;
02022       case XK_F4:
02023        functionKey(XK_F4,"XK_F4");
02024        *cm_keycode = 0x4 | CM_TF_START ;
02025        goto VALID;
02026        break;
02027       case XK_F5:
02028        functionKey(XK_F5,"XK_F5");
02029        *cm_keycode = 0x5 | CM_TF_START ;
02030        goto VALID;
02031        break;
02032       case XK_F6:
02033        functionKey(XK_F6,"XK_F6");
02034        *cm_keycode = 0x6 | CM_TF_START ;
02035        goto VALID;
02036        break;
02037       case XK_F7:
02038        functionKey(XK_F7,"XK_F7");
02039        *cm_keycode = 0x7 | CM_TF_START ;
02040        goto VALID;
02041        break;
02042       case XK_F8:
02043        functionKey(XK_F8,"XK_F8");
02044        *cm_keycode = 0x8 | CM_TF_START ;
02045        goto VALID;
02046        break;
02047       case XK_F9:
02048        functionKey(XK_F9,"XK_F9");
02049        *cm_keycode = 0x9 | CM_TF_START ;
02050        goto VALID;
02051        break;
02052       case XK_F10:
02053        functionKey(XK_F10,"XK_F10");
02054        *cm_keycode = 0xa | CM_TF_START ;
02055        goto VALID;
02056        break;
02057 #if XlibSpecificationRelease != 5
02058 #ifdef OWNV2
02059       case XK_SunF36: 
02060 #endif /* sun */
02061 #endif /* XlibSpecificationRelease */
02062       case SunXK_F36: /* Labeled F11 */
02063        *cm_keycode = 0xb | CM_TF_START ;
02064        goto VALID;
02065        break;
02066 #if XlibSpecificationRelease != 5
02067 #ifdef OWNV2
02068       case XK_SunF37: 
02069 #endif /* sun */
02070 #endif /* XlibSpecificationRelease */
02071       case SunXK_F37: /* Labeled F12 */
02072        functionKey(XK_F12,"XK_F12");
02073        *cm_keycode = 0xc | CM_TF_START ;
02074        goto VALID;
02075        break;
02076 /*
02077  * don't trap Left/right function key
02078  */
02079 #define break 
02080       case XK_F11: /* XK_L1 */
02081        functionKey(XK_F11,"XK_F11");
02082        break;
02083       case XK_F12: /* XK_L2 */
02084        functionKey(XK_F12,"XK_F12");
02085        break;
02086       case XK_F13: /* XK_L3 */
02087        functionKey(XK_F13,"XK_F13");
02088        break;
02089       case XK_F14: /* XK_L4 */
02090        functionKey(XK_F14,"XK_F14");
02091        break;
02092       case XK_F15: /* XK_L5 */
02093        functionKey(XK_F15,"XK_F15");
02094        break;
02095       case XK_F16: /* XK_L6 */
02096        functionKey(XK_F16,"XK_F16");
02097        break;
02098       case XK_F17: /* XK_L7 */
02099        functionKey(XK_F17,"XK_F17");
02100        break;
02101       case XK_F18: /* XK_L8 */
02102        functionKey(XK_F18,"XK_F18");
02103        break;
02104       case XK_F19: /* XK_L9 */
02105        functionKey(XK_F19,"XK_F19");
02106        break;
02107       case XK_F20: /* XK_L10 */
02108        functionKey(XK_F20,"XK_F20");
02109        break;
02110       case XK_F21: /* XK_R1 */
02111        functionKey(XK_F21,"XK_F21");
02112        break;
02113       case XK_F22: /* XK_R2 */
02114        functionKey(XK_F22,"XK_F22");
02115        break;
02116       case XK_F23: /* XK_R3 */
02117        functionKey(XK_F23,"XK_F23");
02118        break;
02119       case XK_F24: /* XK_R4 */
02120        functionKey(XK_F24,"XK_F24");
02121        break;
02122       case XK_F25: /* XK_R5 */
02123        functionKey(XK_F25,"XK_F25");
02124        break;
02125       case XK_F26: /* XK_R6 */
02126        functionKey(XK_F26,"XK_F26");
02127        break;
02128       case XK_F27: /* XK_R7 */
02129        functionKey(XK_F27,"XK_F27");
02130        break;
02131       case XK_F28: /* XK_R8 */
02132        functionKey(XK_F28,"XK_F28");
02133        break;
02134       case XK_F29: /* XK_R9 */
02135        functionKey(XK_F29,"XK_F29");
02136        break;
02137       case XK_F30: /* XK_R10 */
02138        functionKey(XK_F30,"XK_F30");
02139        break;
02140       case XK_F31: /* XK_R11 */
02141        functionKey(XK_F31,"XK_F31");
02142        break;
02143       case XK_F32: /* XK_R12 */
02144        functionKey(XK_F32,"XK_F32");
02145        break;
02146       case XK_R13: /* XK_F33 */
02147        functionKey(XK_R13,"XK_R13");
02148        break;
02149       case XK_F34: /* XK_R14 */
02150        functionKey(XK_F34,"XK_F34");
02151        break;
02152       case XK_F35: /* XK_R15 */
02153        functionKey(XK_F35,"XK_F35");
02154        break;
02155        return False ;
02156 #undef break
02157       default:       
02158        if(l)
02159            *cm_keycode = s->XLookupBuf[0]; /* How badly cm is designed! */
02160 VALID:
02161        return True ;
02162     }
02163     return False ;
02164 }