home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / evbl0627.zip / everblue_20010627.zip / x11 / XKBBind.c < prev    next >
C/C++ Source or Header  |  1999-11-02  |  27KB  |  1,024 lines

  1. /* $TOG: XKBBind.c /main/27 1997/06/10 06:53:17 kaleb $ */
  2. /*
  3.  
  4. Copyright (c) 1985, 1987, 1994  X Consortium
  5.  
  6. Permission is hereby granted, free of charge, to any person obtaining
  7. a copy of this software and associated documentation files (the
  8. "Software"), to deal in the Software without restriction, including
  9. without limitation the rights to use, copy, modify, merge, publish,
  10. distribute, sublicense, and/or sell copies of the Software, and to
  11. permit persons to whom the Software is furnished to do so, subject to
  12. the following conditions:
  13.  
  14. The above copyright notice and this permission notice shall be included
  15. in all copies or substantial portions of the Software.
  16.  
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. OTHER DEALINGS IN THE SOFTWARE.
  24.  
  25. Except as contained in this notice, the name of the X Consortium shall
  26. not be used in advertising or otherwise to promote the sale, use or
  27. other dealings in this Software without prior written authorization
  28. from the X Consortium.
  29.  
  30. */
  31.     /* the new monsters ate the old ones */
  32.  
  33. #define NEED_EVENTS
  34. #include "Xlib_private.h"
  35. #include <X11/Xutil.h>
  36. #include <X11/keysym.h>
  37. #include <stdio.h>
  38. #include <ctype.h>
  39.  
  40. #include <X11/extensions/XKBproto.h>
  41. #include "XKBlibint.h"
  42.  
  43. #ifdef USE_OWN_COMPOSE
  44. #define    COMPOSE_NO_CONST_MEMBERS
  45. #include "imComp.h"
  46. #endif
  47.  
  48. #define AllMods (ShiftMask|LockMask|ControlMask| \
  49.          Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
  50.  
  51. static int _XkbLoadDpy(
  52. #if NeedFunctionPrototypes
  53.     Display *dpy
  54. #endif
  55. );
  56.  
  57. struct _XKeytrans {
  58.     struct _XKeytrans *next;/* next on list */
  59.     char *string;        /* string to return when the time comes */
  60.     int len;        /* length of string (since NULL is legit)*/
  61.     KeySym key;        /* keysym rebound */
  62.     unsigned int state;    /* modifier state */
  63.     KeySym *modifiers;    /* modifier keysyms you want */
  64.     int mlen;        /* length of modifier list */
  65. };
  66.  
  67. KeySym
  68. #if NeedFunctionPrototypes
  69. XkbKeycodeToKeysym(Display *dpy,
  70. #if NeedWidePrototypes
  71.          unsigned int kc,
  72. #else
  73.          KeyCode kc,
  74. #endif
  75.          int     group,
  76.          int    level)
  77. #else
  78. XkbKeycodeToKeysym(dpy, kc, group, level)
  79.     Display *dpy;
  80.     KeyCode kc;
  81.     int group;
  82.     int level;
  83. #endif
  84. {
  85.     DBUG_ENTER("XkbKeycodeToKeysym")
  86.     XkbDescRec    *xkb;
  87.     KeySym result;
  88.     
  89.     if (_XkbUnavailable(dpy))
  90.     DBUG_RETURN(NoSymbol);
  91.  
  92.     _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
  93.  
  94.     xkb = dpy->xkb_info->desc;
  95.     if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code))
  96.     DBUG_RETURN(NoSymbol);
  97.  
  98.     if ((group<0)||(level<0)||(group>=XkbKeyNumGroups(xkb,kc)))
  99.     DBUG_RETURN(NoSymbol);
  100.     if (level>=XkbKeyGroupWidth(xkb,kc,group)) {
  101.     /* for compatibility with the core protocol, _always_ allow  */
  102.     /* two symbols in the first two groups.   If either of the   */
  103.     /* two is of type ONE_LEVEL, just replicate the first symbol */
  104.     if ((group>XkbGroup2Index)||(XkbKeyGroupWidth(xkb,kc,group)!=1)||
  105.                                 (level!=1)) {
  106.         DBUG_RETURN(NoSymbol);
  107.     }
  108.     level= 0;
  109.     }
  110.     result = XkbKeySymEntry(xkb,kc,level,group);
  111.     DBUG_RETURN(result);
  112. }
  113.  
  114. KeySym
  115. #if NeedFunctionPrototypes
  116. XKeycodeToKeysym(Display *dpy,
  117. #if NeedWidePrototypes
  118.          unsigned int kc,
  119. #else
  120.          KeyCode kc,
  121. #endif
  122.          int col)
  123. #else
  124. XKeycodeToKeysym(dpy, kc, col)
  125.     Display *dpy;
  126.     KeyCode kc;
  127.     int col;
  128. #endif
  129. {
  130.     DBUG_ENTER("XKeycodeToKeysym")
  131.     XkbDescRec    *xkb;
  132.     
  133.     if (_XkbUnavailable(dpy)) {
  134.     KeySym result = _XKeycodeToKeysym(dpy, kc, col);
  135.         DBUG_RETURN(result);
  136.     }
  137.  
  138.     _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
  139.  
  140.     xkb = dpy->xkb_info->desc;
  141.     if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code))
  142.     DBUG_RETURN(NoSymbol);
  143.     
  144.     if (col>3) {
  145.     int lastSym,tmp,nGrp;
  146.  
  147.     lastSym= 3;
  148.     nGrp= XkbKeyNumGroups(xkb,kc);
  149.     if ((nGrp>0)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup1Index))>2)) {
  150.         if (col<=(lastSym+tmp-2)) {
  151.         KeySym result = XkbKeycodeToKeysym(dpy,kc,XkbGroup1Index,col-lastSym+2);
  152.         DBUG_RETURN(result);
  153.         }
  154.         lastSym+= tmp-2;
  155.     }
  156.     if ((nGrp>1)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup2Index))>2)) {
  157.         if (col<=(lastSym+tmp-2)) {
  158.         KeySym result = XkbKeycodeToKeysym(dpy,kc,XkbGroup2Index,col-lastSym+2);
  159.         DBUG_RETURN(result);
  160.         }
  161.         lastSym+= tmp-2;
  162.     }
  163.     if (nGrp>2) {
  164.         tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup3Index);
  165.         if (col<=lastSym+tmp) {
  166.         KeySym result = XkbKeycodeToKeysym(dpy,kc,XkbGroup3Index,col-lastSym);
  167.         DBUG_RETURN(result);
  168.         }
  169.         lastSym+= tmp;
  170.     }
  171.     if (nGrp>3) {
  172.         tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup4Index);
  173.         if (col<=lastSym+tmp) {
  174.         KeySym result = XkbKeycodeToKeysym(dpy,kc,XkbGroup4Index,col-lastSym);
  175.         DBUG_RETURN(result);
  176.         }
  177.     }
  178.     DBUG_RETURN(NoSymbol);
  179.     }
  180.     {
  181.     KeySym result = XkbKeycodeToKeysym(dpy,kc,(col>>1),(col&1));
  182.     DBUG_RETURN(result);
  183.     }
  184. }
  185.  
  186. KeyCode
  187. #if NeedFunctionPrototypes
  188. XKeysymToKeycode(Display *dpy, KeySym ks)
  189. #else
  190. XKeysymToKeycode(dpy, ks)
  191.     Display *dpy;
  192.     KeySym ks;
  193. #endif
  194. {
  195.     DBUG_ENTER("XKeysymToKeycode")
  196.     register int i, j, gotOne;
  197.  
  198.     if (_XkbUnavailable(dpy)) {
  199.     KeyCode result = _XKeysymToKeycode(dpy,ks);
  200.     DBUG_RETURN(result);
  201.     }
  202.     _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
  203.  
  204.     j= 0;
  205.     do {
  206.     register XkbDescRec *xkb = dpy->xkb_info->desc;
  207.     gotOne= 0;
  208.     for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
  209.         if ( j<(int)XkbKeyNumSyms(xkb,i) ) {
  210.         gotOne = 1;
  211.         if ((XkbKeySym(xkb,i,j)==ks))
  212.             DBUG_RETURN(i);
  213.         }
  214.     }
  215.     j++;
  216.     } while (gotOne);
  217.     DBUG_RETURN(0);
  218. }
  219.  
  220. static int
  221. #if NeedFunctionPrototypes
  222. _XkbComputeModmap(Display *dpy)
  223. #else
  224. _XkbComputeModmap(dpy)
  225.     Display *dpy;
  226. #endif
  227. {
  228.     DBUG_ENTER("_XkbComputeModmap")
  229.     register XkbDescPtr xkb;
  230.  
  231.     xkb= dpy->xkb_info->desc;
  232.     if (XkbGetUpdatedMap(dpy,XkbModifierMapMask,xkb)==Success)
  233.     DBUG_RETURN(1);
  234.     DBUG_RETURN(0);
  235. }
  236.  
  237. unsigned
  238. #if NeedFunctionPrototypes
  239. XkbKeysymToModifiers(Display *dpy,KeySym ks)
  240. #else
  241. XkbKeysymToModifiers(dpy,ks)
  242.     Display *dpy;
  243.     KeySym ks;
  244. #endif
  245. {
  246.     DBUG_ENTER("XkbKeysymToModifiers")
  247.     XkbDescRec *xkb;
  248.     register int i,j;
  249.     register KeySym *pSyms;
  250.     CARD8 mods;
  251.  
  252.     if (_XkbUnavailable(dpy)) {
  253.     unsigned result = _XKeysymToModifiers(dpy,ks);
  254.     DBUG_RETURN(result);
  255.     }
  256.     _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
  257.  
  258.     if (_XkbNeedModmap(dpy->xkb_info)&&(!_XkbComputeModmap(dpy))) {
  259.     unsigned result =_XKeysymToModifiers(dpy,ks);
  260.     DBUG_RETURN(result);
  261.     }
  262.  
  263.     xkb= dpy->xkb_info->desc;
  264.     mods= 0;
  265.     for (i = xkb->min_key_code; i <= (int)xkb->max_key_code; i++) {
  266.     pSyms= XkbKeySymsPtr(xkb,i);
  267.     for (j=XkbKeyNumSyms(xkb,i)-1;j>=0;j--) {
  268.         if (pSyms[j]==ks) {
  269.         mods|= xkb->map->modmap[i];
  270.         break;
  271.         }
  272.     }
  273.     }
  274.     DBUG_RETURN(mods);
  275. }
  276.  
  277. KeySym
  278. #if NeedFunctionPrototypes
  279. XLookupKeysym(register XKeyEvent *event, int col)
  280. #else
  281. XLookupKeysym(event, col)
  282.     register XKeyEvent *event;
  283.     int col;
  284. #endif
  285. {
  286.     DBUG_ENTER("XLookupKeysym")
  287.     Display *dpy = event->display;
  288.     if (_XkbUnavailable(dpy)) {
  289.     KeySym result = _XLookupKeysym(event, col);
  290.     DBUG_RETURN(result);
  291.     }
  292.     _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
  293.     {
  294.     KeySym result = XKeycodeToKeysym(dpy, event->keycode, col);
  295.     DBUG_RETURN(result);
  296.     }
  297. }
  298.  
  299.    /*
  300.     * Not a public entry point -- XkbTranslateKey is an obsolete name 
  301.     * that is preserved here so that functions linked against the old 
  302.     * version will continue to work in a shared library environment.
  303.     */
  304. int
  305. #if NeedFunctionPrototypes
  306. XkbTranslateKey(    register Display *    dpy,
  307.             KeyCode         key,
  308.             register unsigned int     mods,
  309.             unsigned int *        mods_rtrn,
  310.             KeySym *        keysym_rtrn)
  311. #else
  312. XkbTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn)
  313.     register Display *dpy;
  314.     KeyCode key;
  315.     register unsigned int mods;
  316.     unsigned int *mods_rtrn;
  317.     KeySym *keysym_rtrn;
  318. #endif
  319. {
  320.     DBUG_ENTER("XkbTranslateKey")
  321.     int result = XkbLookupKeySym(dpy,key,mods,mods_rtrn,keysym_rtrn);
  322.     DBUG_RETURN(result);
  323. }
  324.  
  325. Bool
  326. #if NeedFunctionPrototypes
  327. XkbLookupKeySym(    register Display *    dpy,
  328.             KeyCode         key,
  329.             register unsigned int     mods,
  330.             unsigned int *        mods_rtrn,
  331.             KeySym *        keysym_rtrn)
  332. #else
  333. XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn)
  334.     register Display *dpy;
  335.     KeyCode key;
  336.     register unsigned int mods;
  337.     unsigned int *mods_rtrn;
  338.     KeySym *keysym_rtrn;
  339. #endif
  340. {
  341.     DBUG_ENTER("XkbLookupKeySym")
  342.     Bool result;
  343.     if (_XkbUnavailable(dpy)) {
  344.     result =_XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn);
  345.     DBUG_RETURN(result);
  346.      }
  347.     _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
  348.    
  349.     result = XkbTranslateKeyCode(dpy->xkb_info->desc,key,mods,mods_rtrn,
  350.                                 keysym_rtrn);
  351.     DBUG_RETURN(result);
  352. }
  353.  
  354. Bool
  355. #if NeedFunctionPrototypes
  356. XkbTranslateKeyCode(    register XkbDescPtr    xkb,
  357.             KeyCode         key,
  358.             register unsigned int     mods,
  359.             unsigned int *        mods_rtrn,
  360.             KeySym *        keysym_rtrn)
  361. #else
  362. XkbTranslateKeyCode(xkb, key, mods, mods_rtrn, keysym_rtrn)
  363.     register XkbDescPtr xkb;
  364.     KeyCode key;
  365.     register unsigned int mods;
  366.     unsigned int *mods_rtrn;
  367.     KeySym *keysym_rtrn;
  368. #endif
  369. {
  370.     DBUG_ENTER("XkbTranslateKeyCode")
  371.     XkbKeyTypeRec *type;
  372.     int col,nKeyGroups;
  373.     unsigned preserve,effectiveGroup;
  374.     KeySym *syms;
  375.  
  376.     if (mods_rtrn!=NULL)
  377.     *mods_rtrn = 0;
  378.  
  379.     nKeyGroups= XkbKeyNumGroups(xkb,key);
  380.     if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
  381.     if (keysym_rtrn!=NULL)
  382.         *keysym_rtrn = NoSymbol;
  383.     DBUG_RETURN(False);
  384.     }
  385.  
  386.     syms = XkbKeySymsPtr(xkb,key);
  387.  
  388.     /* find the offset of the effective group */
  389.     col = 0;
  390.     effectiveGroup= XkbGroupForCoreState(mods);
  391.     if ( effectiveGroup>=nKeyGroups ) {
  392.     unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
  393.     switch (XkbOutOfRangeGroupAction(groupInfo)) {
  394.         default:
  395.         effectiveGroup %= nKeyGroups;
  396.         break;
  397.         case XkbClampIntoRange:
  398.         effectiveGroup = nKeyGroups-1;
  399.         break;
  400.         case XkbRedirectIntoRange:
  401.         effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
  402.         if (effectiveGroup>=nKeyGroups)
  403.             effectiveGroup= 0;
  404.         break;
  405.     }
  406.     }
  407.     col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
  408.     type = XkbKeyKeyType(xkb,key,effectiveGroup);
  409.  
  410.     preserve= 0;
  411.     if (type->map) { /* find the column (shift level) within the group */
  412.     register int i;
  413.     register XkbKTMapEntryPtr entry;
  414.     for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
  415.         if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
  416.         col+= entry->level;
  417.         if (type->preserve)
  418.             preserve= type->preserve[i].mask;
  419.         break;
  420.         }
  421.     }
  422.     }
  423.  
  424.     if (keysym_rtrn!=NULL)
  425.     *keysym_rtrn= syms[col];
  426.     if (mods_rtrn) {
  427.     *mods_rtrn= type->mods.mask&(~preserve);
  428.     /* The Motif VTS doesn't get the help callback called if help
  429.      * is bound to Shift+<whatever>, and it appears as though it 
  430.      * is XkbTranslateKeyCode that is causing the problem.  The 
  431.      * core X version of XTranslateKey always OR's in ShiftMask 
  432.      * and LockMask for mods_rtrn, so this "fix" keeps this behavior 
  433.      * and solves the VTS problem.
  434.      */
  435.     if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
  436.         (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) {
  437.         *mods_rtrn|= (ShiftMask|LockMask);
  438.     }
  439.     }
  440.     DBUG_RETURN(syms[col]!=NoSymbol);
  441. }
  442.  
  443. Status
  444. #if NeedFunctionPrototypes
  445. XkbRefreshKeyboardMapping(register XkbMapNotifyEvent *event)
  446. #else
  447. XkbRefreshKeyboardMapping(event)
  448.     register XkbMapNotifyEvent *event;
  449. #endif
  450. {
  451.     DBUG_ENTER("XkbRefreshKeyboardMapping")
  452.     Display *dpy = event->display;
  453.     XkbInfoPtr xkbi;
  454.  
  455.     if (_XkbUnavailable(dpy)) {
  456.     _XRefreshKeyboardMapping((XMappingEvent *)event);
  457.     DBUG_RETURN(Success);
  458.     }
  459.     xkbi= dpy->xkb_info;
  460.  
  461.     if (((event->type&0x7f)-xkbi->codes->first_event)!=XkbEventCode)
  462.     DBUG_RETURN(BadMatch);
  463.     if (event->xkb_type==XkbNewKeyboardNotify) {
  464.     _XkbReloadDpy(dpy);
  465.     DBUG_RETURN(Success);
  466.     }
  467.     if (event->xkb_type==XkbMapNotify) {
  468.     XkbMapChangesRec    changes;
  469.     Status            rtrn;
  470.  
  471.     if (xkbi->flags&XkbMapPending)
  472.          changes= xkbi->changes;
  473.     else bzero(&changes,sizeof(XkbChangesRec));
  474.     XkbNoteMapChanges(&changes,event,XKB_XLIB_MAP_MASK);
  475.     LockDisplay(dpy);
  476.     if ((rtrn=XkbGetMapChanges(dpy,xkbi->desc,&changes))!=Success) {
  477. #ifdef DEBUG
  478.         fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n");
  479. #endif
  480.         xkbi->changes= changes;
  481.     }
  482.     else if (xkbi->flags&XkbMapPending) {
  483.         xkbi->flags&= ~XkbMapPending;
  484.         bzero(&xkbi->changes,sizeof(XkbMapChangesRec));
  485.     }
  486.     UnlockDisplay(dpy);
  487.     DBUG_RETURN(rtrn);
  488.     }
  489.     DBUG_RETURN(BadMatch);
  490. }
  491.  
  492. int
  493. #if NeedFunctionPrototypes
  494. XRefreshKeyboardMapping(register XMappingEvent *event)
  495. #else
  496. XRefreshKeyboardMapping(event)
  497.     register XMappingEvent *event;
  498. #endif
  499. {
  500.     DBUG_ENTER("XRefreshKeyboardMapping")
  501.     XkbEvent    *xkbevent = (XkbEvent *)event;
  502.     Display *dpy = event->display;
  503.     XkbMapChangesRec changes;
  504.     XkbInfoPtr xkbi;
  505.     int result;
  506.  
  507.     /* always do this for input methods, which still use the old keymap */
  508.     (void) _XRefreshKeyboardMapping(event);
  509.  
  510.     if (_XkbUnavailable(dpy))
  511.     DBUG_RETURN(1);
  512.  
  513.     xkbi = dpy->xkb_info;
  514.  
  515.     if (((event->type&0x7f)-xkbi->codes->first_event)==XkbEventCode) {
  516.     result = XkbRefreshKeyboardMapping(&xkbevent->map);
  517.     DBUG_RETURN(result);
  518.     }
  519.  
  520.     if (xkbi->flags&XkbXlibNewKeyboard) {
  521.     _XkbReloadDpy(dpy);
  522.     DBUG_RETURN(1);
  523.     }
  524.  
  525.     if ((xkbi->flags&XkbMapPending)||(event->request==MappingKeyboard)) {
  526.     if (xkbi->flags&XkbMapPending) {
  527.         changes= xkbi->changes;
  528.         _XkbNoteCoreMapChanges(&changes,event,XKB_XLIB_MAP_MASK);
  529.     }
  530.     else {
  531.         bzero(&changes,sizeof(changes));
  532.         changes.changed= XkbKeySymsMask;
  533.         if (xkbi->desc->min_key_code<xkbi->desc->max_key_code) {
  534.         changes.first_key_sym= xkbi->desc->min_key_code;
  535.         changes.num_key_syms= xkbi->desc->max_key_code-
  536.                         xkbi->desc->min_key_code+1;
  537.         }
  538.         else {
  539.         changes.first_key_sym= event->first_keycode;
  540.         changes.num_key_syms= event->count;
  541.         }
  542.     }
  543.  
  544.     if (XkbGetMapChanges(dpy,xkbi->desc, &changes)!=Success) {
  545. #ifdef DEBUG
  546.         fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n");
  547.         if (changes.changed&XkbKeyTypesMask) {
  548.             int first= changes.first_type;
  549.             int last= changes.first_type+changes.num_types-1;
  550.             fprintf(stderr,"       types:  %d..%d\n",first,last);
  551.         }
  552.         if (changes.changed&XkbKeySymsMask) {
  553.             int first= changes.first_key_sym;
  554.             int last= changes.first_key_sym+changes.num_key_syms-1;
  555.             fprintf(stderr,"     symbols:  %d..%d\n",first,last);
  556.         }
  557.         if (changes.changed&XkbKeyActionsMask) {
  558.             int last,first= changes.first_key_act;
  559.             last= changes.first_key_act+changes.num_key_acts-1;
  560.             fprintf(stderr,"     acts:  %d..%d\n",first,last);
  561.         }
  562.         if (changes.changed&XkbKeyBehaviorsMask) {
  563.             int last,first= changes.first_key_behavior;
  564.             last= first+changes.num_key_behaviors-1;
  565.             fprintf(stderr,"   behaviors:  %d..%d\n",first,last);
  566.         }
  567.         if (changes.changed&XkbVirtualModsMask) {
  568.             fprintf(stderr,"virtual mods: 0x%04x\n",
  569.                     changes.vmods);
  570.         }
  571.         if (changes.changed&XkbExplicitComponentsMask) {
  572.             int last,first= changes.first_key_explicit;
  573.             last= first+changes.num_key_explicit-1;
  574.             fprintf(stderr,"    explicit:  %d..%d\n",first,last);
  575.         }
  576. #endif
  577.     }
  578.     LockDisplay(dpy);
  579.     if (xkbi->flags&XkbMapPending) {
  580.         xkbi->flags&= ~XkbMapPending;
  581.         bzero(&xkbi->changes,sizeof(XkbMapChangesRec));
  582.     }
  583.     UnlockDisplay(dpy);
  584.     }
  585.     if (event->request==MappingModifier) {
  586.     if (xkbi->desc->map->modmap) {
  587.         _XkbFree(xkbi->desc->map->modmap);
  588.         xkbi->desc->map->modmap= NULL;
  589.     }
  590.     if (dpy->key_bindings) {
  591.         register struct _XKeytrans *p;
  592.         for (p = dpy->key_bindings; p; p = p->next) {
  593.         register int i;
  594.         p->state= 0;
  595.           if (p->mlen>0) {
  596.             for (i = 0; i < p->mlen; i++) {
  597.             p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);
  598.             }
  599.             if (p->state)    p->state &= AllMods;
  600.             else        p->state = AnyModifier;
  601.         }
  602.         }
  603.     }
  604.     UnlockDisplay(dpy);
  605.     }
  606.     DBUG_RETURN(1);
  607. }
  608.  
  609. static int
  610. #if NeedFunctionPrototypes
  611. _XkbLoadDpy(Display *dpy)
  612. #else
  613. _XkbLoadDpy(dpy)
  614.     Display *dpy;
  615. #endif
  616. {
  617.     DBUG_ENTER("_XkbLoadDpy")
  618.     XkbInfoPtr xkbi;
  619.     unsigned query,oldEvents;
  620.     XkbDescRec *desc;
  621.  
  622.     if (!XkbUseExtension(dpy,NULL,NULL))
  623.     DBUG_RETURN(0);
  624.  
  625.     xkbi = dpy->xkb_info;
  626.     query = XkbAllClientInfoMask;
  627.     desc = XkbGetMap(dpy,query,XkbUseCoreKbd);
  628.     if (!desc) {
  629. #ifdef DEBUG
  630.     fprintf(stderr,"Warning! XkbGetMap failed!\n");
  631. #endif
  632.     DBUG_RETURN(0);
  633.     }
  634.     LockDisplay(dpy);
  635.     xkbi->desc = desc;
  636.  
  637.     _XkbGetConverters(_XkbGetCharset(),&xkbi->cvt);
  638.     _XkbGetConverters("ISO8859-1",&xkbi->latin1cvt);
  639.     UnlockDisplay(dpy);
  640.     oldEvents= xkbi->selected_events;
  641.     if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) {
  642.     XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbNewKeyboardNotify,
  643.                 XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask,
  644.                 XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask);
  645.     }
  646.     XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify,
  647.                 XkbAllClientInfoMask,XkbAllClientInfoMask);
  648.     LockDisplay(dpy);
  649.     xkbi->selected_events= oldEvents;
  650.     UnlockDisplay(dpy);
  651.     DBUG_RETURN(1);
  652. }
  653.  
  654. void
  655. #if NeedFunctionPrototypes
  656. _XkbReloadDpy(Display *dpy)
  657. #else
  658. _XkbReloadDpy(dpy)
  659.     Display *dpy;
  660. #endif
  661. {
  662.     DBUG_ENTER("_XkbReloadDpy")
  663.     XkbInfoPtr xkbi;
  664.     XkbDescRec *desc;
  665.     unsigned    oldDeviceID;
  666.  
  667.     if (_XkbUnavailable(dpy))
  668.     DBUG_VOID_RETURN;
  669.  
  670.     xkbi = dpy->xkb_info;
  671.     LockDisplay(dpy);
  672.     if (xkbi->desc) {
  673.     oldDeviceID= xkbi->desc->device_spec;
  674.     XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
  675.     xkbi->desc= NULL;
  676.     xkbi->flags&= ~(XkbMapPending|XkbXlibNewKeyboard);
  677.     xkbi->changes.changed= 0;
  678.     }
  679.     else oldDeviceID= XkbUseCoreKbd;
  680.     UnlockDisplay(dpy);
  681.     desc = XkbGetMap(dpy,XkbAllClientInfoMask,XkbUseCoreKbd);
  682.     if (!desc)
  683.     DBUG_VOID_RETURN;
  684.     LockDisplay(dpy);
  685.     xkbi->desc = desc;
  686.     UnlockDisplay(dpy);
  687.  
  688.     if (desc->device_spec!=oldDeviceID) {
  689.     /* transfer(?) event masks here */
  690. #ifdef NOTYET
  691.     unsigned oldEvents;
  692.     oldEvents= xkbi->selected_events;
  693.     XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify,
  694.                 XkbAllMapComponentsMask,XkbAllClientInfoMask);
  695.     LockDisplay(dpy);
  696.     xkbi->selected_events= oldEvents;
  697.     UnlockDisplay(dpy);
  698. #endif
  699.     }
  700.     DBUG_VOID_RETURN;
  701. }
  702.  
  703. int
  704. #if NeedFunctionPrototypes
  705. XkbTranslateKeySym(    register Display *    dpy,
  706.             register KeySym *    sym_rtrn,
  707.             unsigned int         mods,
  708.             char *            buffer,
  709.             int             nbytes,
  710.             int *            extra_rtrn)
  711. #else
  712. XkbTranslateKeySym(dpy, sym_rtrn, mods, buffer, nbytes, extra_rtrn)
  713.     register Display *dpy;
  714.     register KeySym *sym_rtrn;
  715.     unsigned int mods;
  716.     char *buffer;
  717.     int nbytes;
  718.     int *extra_rtrn;
  719. #endif
  720. {
  721.     DBUG_ENTER("XkbTranslateKeySym")
  722.     register XkbInfoPtr    xkb;
  723.     XkbKSToMBFunc cvtr;
  724.     XPointer priv;
  725.     char tmp[4];
  726.     register struct _XKeytrans *p; 
  727.     int n;
  728.  
  729.     if (extra_rtrn)
  730.     *extra_rtrn= 0;
  731.  
  732.     if (_XkbUnavailable(dpy))
  733.         return _XTranslateKeySym(dpy, *sym_rtrn, mods, buffer, nbytes);
  734.     _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
  735.  
  736.     xkb= dpy->xkb_info;
  737.     if ((buffer==NULL)||(nbytes==0)) {
  738.     buffer= tmp;
  739.     nbytes= 4;
  740.     }
  741.  
  742.     /* see if symbol rebound, if so, return that string. */
  743.     for (p = dpy->key_bindings; p; p = p->next) {
  744.     if (((mods & AllMods) == p->state) && (*sym_rtrn == p->key)) {
  745.         int tmp = p->len;
  746.         if (tmp > nbytes) {
  747.         if (extra_rtrn)
  748.             *extra_rtrn= tmp-nbytes;
  749.         tmp = nbytes;
  750.         }
  751.         memcpy (buffer, p->string, tmp);
  752.         DBUG_RETURN(tmp);
  753.     }
  754.     }
  755.  
  756.     if ( nbytes>0 )
  757.     buffer[0]= '\0';
  758.  
  759.     if ( xkb->cvt.KSToUpper && (mods&LockMask) ) {
  760.     *sym_rtrn = (*xkb->cvt.KSToUpper)(*sym_rtrn);
  761.     }
  762.     if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) {
  763.     cvtr = xkb->latin1cvt.KSToMB;
  764.     priv = xkb->latin1cvt.KSToMBPriv;
  765.     } else {
  766.     cvtr = xkb->cvt.KSToMB;
  767.     priv = xkb->cvt.KSToMBPriv;
  768.     }
  769.  
  770.     n = (*cvtr)(priv,*sym_rtrn,buffer,nbytes,extra_rtrn);
  771.  
  772.     if ((!xkb->cvt.KSToUpper)&&( mods&LockMask )) {
  773.     register int i;
  774.  
  775.     if (!xkb->cvt.KSToUpper) {
  776.         int change;
  777.         char ch;
  778.         for (i=change=0;i<n;i++) {
  779.         ch= toupper(buffer[i]);
  780.         change= (change||(buffer[i]!=ch));
  781.         buffer[i] = ch;
  782.         }
  783.         if (change) {
  784.         if (n==1)
  785.              *sym_rtrn=(*xkb->cvt.MBToKS)(xkb->cvt.MBToKSPriv,
  786.                                 buffer,n,0);
  787.         else *sym_rtrn= NoSymbol;
  788.         }
  789.     }
  790.     }
  791.  
  792.     if ( mods&ControlMask ) {
  793.     if ( n==1 ) {
  794.         register char c = buffer[0];
  795.  
  796.         if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
  797.         else if (c == '2') c = '\000';
  798.         else if (c >= '3' && c <= '7') c -= ('3' - '\033');
  799.         else if (c == '8') c = '\177';
  800.         else if (c == '/') c = '_' & 0x1F;
  801.  
  802.         buffer[0]= c;
  803.         if ( nbytes>1 )
  804.         buffer[1]= '\0';
  805.         DBUG_RETURN(1);
  806.     }
  807.     if ( nbytes > 0 )
  808.         buffer[0]= '\0';
  809.     DBUG_RETURN(0);
  810.     }
  811.     DBUG_RETURN(n);
  812. }
  813.  
  814. int
  815. #if NeedFunctionPrototypes
  816. XLookupString (    register XKeyEvent *    event,
  817.         char *            buffer,
  818.         int             nbytes,
  819.         KeySym *        keysym,
  820.         XComposeStatus *    status)
  821. #else
  822. XLookupString (event, buffer, nbytes, keysym, status)
  823.     register XKeyEvent *event;
  824.     char *buffer;    /* buffer */
  825.     int nbytes;    /* space in buffer for characters */
  826.     KeySym *keysym;
  827.     XComposeStatus *status;
  828. #endif
  829. {
  830.     DBUG_ENTER("XLookupString")
  831.     KeySym    dummy;
  832.     int rtrnLen;
  833.     unsigned int new_mods;
  834.     Display *dpy = event->display;
  835.     XkbDescPtr    xkb;
  836.     int result;
  837.  
  838.     if (_XkbUnavailable(dpy)) {
  839.     result = _XLookupString(event, buffer, nbytes, keysym, status);
  840.     DBUG_RETURN(result);
  841.     }
  842.     _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
  843.  
  844.     if (keysym==NULL)
  845.     keysym= &dummy;
  846.     xkb= dpy->xkb_info->desc;
  847.     if (!XkbTranslateKeyCode(xkb,event->keycode,event->state, &new_mods,keysym))
  848.     DBUG_RETURN(0);
  849.     new_mods= (event->state&(~new_mods));
  850.  
  851. #ifdef USE_OWN_COMPOSE
  852.     if ( status ) {
  853.     static int been_here= 0;
  854.     if ( !been_here ) {
  855.         XimCompInitTables();
  856.         been_here = 1;
  857.     }
  858.     if ( !XimCompLegalStatus(status) ) {
  859.         status->compose_ptr = NULL;
  860.         status->chars_matched = 0;
  861.     }
  862.     if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) || 
  863.         XimCompIsComposeKey(*keysym,event->keycode,status) ) {
  864.         XimCompRtrn rtrn;
  865.  
  866.         switch (XimCompProcessSym(status,*keysym,&rtrn)) {
  867.         case XIM_COMP_IGNORE:
  868.             break;
  869.         case XIM_COMP_IN_PROGRESS:
  870.             if ( keysym!=NULL )
  871.             *keysym = NoSymbol;
  872. #ifndef NO_COMPOSE_LED
  873.             if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
  874.             XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
  875.                         True,True,False,NULL);
  876.             }
  877. #endif
  878.             DBUG_RETURN(0);
  879.         case XIM_COMP_FAIL:
  880.         {
  881.             static Atom _ComposeFail= None;
  882.             int n = 0, len= 0;
  883. #ifndef NO_COMPOSE_LED
  884.             if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
  885.             XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
  886.                         True,False,False,NULL);
  887.             }
  888. #endif
  889. #ifndef NO_BELL_ON_COMPOSE_FAIL
  890.             if (dpy->xkb_info->xlib_ctrls&XkbLC_BeepOnComposeFail) {
  891.             if (_ComposeFail==None)
  892.                 _ComposeFail= XInternAtom(dpy,"ComposeFail",0);
  893.             XkbBell(dpy,event->window,0,_ComposeFail);
  894.             }
  895. #endif
  896.             for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
  897.             if ( nbytes-len > 0 ) {
  898.                 len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],new_mods,
  899.                             buffer+len,nbytes-len,
  900.                             NULL);
  901.             }
  902.             }
  903.             if ( keysym!=NULL ) {
  904.             if ( n==1 )    *keysym = rtrn.sym[0];
  905.             else        *keysym = NoSymbol;
  906.             }
  907.             DBUG_RETURN(len);
  908.         }
  909.         case XIM_COMP_SUCCEED:
  910.         {
  911.             int len,n = 0;
  912.  
  913. #ifndef NO_COMPOSE_LED
  914.             if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
  915.             XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
  916.                         True,False,False,NULL);
  917.             }
  918. #endif
  919.             *keysym = rtrn.matchSym;
  920.             if ( rtrn.str[0]!='\0' ) {
  921.             strncpy(buffer,rtrn.str,nbytes-1);
  922.             buffer[nbytes-1]= '\0';
  923.             len = (int)strlen(buffer);
  924.             }
  925.             else {
  926.             len = XkbTranslateKeySym(dpy,keysym,new_mods,
  927.                             buffer,nbytes,
  928.                             NULL);
  929.             }
  930.             for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
  931.             if ( nbytes-len > 0 ) {
  932.                 len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],
  933.                             event->state,
  934.                             buffer+len,nbytes-len,
  935.                             NULL);
  936.             }
  937.             }
  938.             DBUG_RETURN(len);
  939.         }
  940.         }
  941.     }
  942.     }
  943. #endif
  944.  
  945.     /* We *should* use the new_mods (which does not contain any modifiers */
  946.     /* that were used to compute the symbol here, but pre-XKB XLookupString */
  947.     /* did not and we have to remain compatible.  Sigh. */
  948.     if ((dpy->xkb_info->flags&XkbLC_ConsumeLookupMods)==0)
  949.     new_mods= event->state;
  950.  
  951.     rtrnLen= XkbLookupKeyBinding(dpy,*keysym,new_mods,buffer,nbytes,NULL);
  952.     if (rtrnLen>0)
  953.     DBUG_RETURN(rtrnLen);
  954.  
  955.     rtrnLen = XkbTranslateKeySym(dpy,keysym,new_mods,buffer,nbytes,NULL);
  956.     if ((event->state&ControlMask)&&(nbytes>0)&&
  957.             ((rtrnLen==0)||((rtrnLen==1)&&(buffer[0]>=' ')))&&
  958.             (XkbGroupForCoreState(event->state)!=XkbGroup1Index)&&
  959.             (dpy->xkb_info->xlib_ctrls&XkbLC_ControlFallback)) {
  960.     XKeyEvent    tmp_ev;
  961.     tmp_ev= *event;
  962.     tmp_ev.state= XkbBuildCoreState(event->state,XkbGroup1Index);
  963.     result = XLookupString (&tmp_ev, buffer, nbytes, keysym, status);
  964.     DBUG_RETURN(result);
  965.     }
  966.     DBUG_RETURN(rtrnLen);
  967. }
  968.  
  969.  
  970. int
  971. #if NeedFunctionPrototypes
  972. XkbLookupKeyBinding(    Display *        dpy,
  973.             register KeySym     sym,
  974.             unsigned int         mods,
  975.             char *            buffer,
  976.             int             nbytes,
  977.             int *             extra_rtrn)
  978. #else
  979. XkbLookupKeyBinding(dpy, sym, mods, buffer, nbytes, extra_rtrn)
  980.     Display *dpy;
  981.     register KeySym sym;
  982.     unsigned int mods;
  983.     char *buffer;
  984.     int nbytes;
  985.     int * extra_rtrn;
  986. #endif
  987. {
  988.     DBUG_ENTER("XkbLookupKeyBinding")
  989.     register struct _XKeytrans *p; 
  990.  
  991.     if (extra_rtrn)
  992.     *extra_rtrn= 0;
  993.     for (p = dpy->key_bindings; p; p = p->next) {
  994.     if (((mods & AllMods) == p->state) && (sym == p->key)) {
  995.         int tmp = p->len;
  996.         if (tmp > nbytes) {
  997.         if (extra_rtrn)
  998.             *extra_rtrn= (tmp-nbytes);
  999.         tmp = nbytes;
  1000.         }
  1001.         memcpy (buffer, p->string, tmp);
  1002.         if (tmp < nbytes)    buffer[tmp]= '\0';
  1003.         DBUG_RETURN(tmp);
  1004.     }
  1005.     }
  1006.     DBUG_RETURN(0);
  1007. }
  1008.  
  1009. char
  1010. #if NeedFunctionPrototypes
  1011. XkbToControl( char c )
  1012. #else
  1013. XkbToControl( c )
  1014.     char c;
  1015. #endif
  1016. {
  1017.     if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
  1018.     else if (c == '2') c = '\000';
  1019.     else if (c >= '3' && c <= '7') c -= ('3' - '\033');
  1020.     else if (c == '8') c = '\177';
  1021.     else if (c == '/') c = '_' & 0x1F;
  1022.     return c;
  1023. }
  1024.