home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / pmvnc100.zip / keybd.c < prev    next >
C/C++ Source or Header  |  1999-05-07  |  16KB  |  493 lines

  1. /*
  2.  * keybd.c - PM VNC Viewer, handling keyboard events
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #define INCL_PM
  10. #include <os2.h>
  11.  
  12. #include "pmvncdef.h"
  13. #include "pmvncres.h"
  14.  
  15. #define XK_MISCELLANY
  16. #define XK_XKB_KEYS
  17. #define XK_LATIN1
  18. #define XK_LATIN2
  19. #define XK_LATIN3
  20. #define XK_LATIN4
  21. #define XK_GREEK
  22.  
  23. #include "keysymdef.h"
  24.  
  25. /*
  26.  * Managing Modal Key (CTL & ALT)
  27.  */
  28.  
  29. static  BOOL    stateSftDown = FALSE ;
  30. static  BOOL    stateCtlDown = FALSE ;
  31. static  BOOL    stateAltDown = FALSE ;
  32.  
  33. static  void    sendKeyEvent(BOOL down, ULONG xkey)
  34. {
  35.     if (xkey == XK_Shift_L || xkey == XK_Shift_R) {
  36.         stateSftDown = down ;
  37.     }
  38.     if (xkey == XK_Control_L || xkey == XK_Control_R) {
  39.         kstCtlState(stateCtlDown = down) ;
  40.     }
  41.     if (xkey == XK_Alt_L || xkey == XK_Alt_R) {
  42.         kstAltState(stateAltDown = down) ;
  43.     }
  44.     protoSendKeyEvent(down, xkey) ;
  45. }
  46.  
  47. /*
  48.  * User defined mapping
  49.  */
  50.  
  51. BOOL    keyMapped(HWND hwnd, USHORT flags, USHORT ch, USHORT vk, USHORT sc)
  52. {
  53.     BOOL    down ;
  54.     ULONG   xkey ;
  55.     
  56.     if ((xkey = kmapQuery(sc)) == XK_VoidSymbol) {
  57.         return FALSE ;
  58.     }
  59.  
  60.     TRACE("Mapped %x to %x\n", sc, xkey) ;
  61.  
  62.     down = (flags & KC_KEYUP) ? FALSE : TRUE ;
  63.  
  64.     if (down && (flags & KC_PREVDOWN)) {
  65.         sendKeyEvent(FALSE, xkey) ;
  66.     }
  67.     sendKeyEvent(down, xkey) ;
  68.     return TRUE ;
  69. }
  70.  
  71. /*
  72.  * Mapping from PM Virtual Key to X Key
  73.  */
  74.  
  75. static  ULONG   vkMap[] = {
  76.     /* 00 - undef           */  XK_VoidSymbol,
  77.     /* 01 - VK_BUTTON1      */  XK_VoidSymbol,
  78.     /* 02 - VK_BUTTON2      */  XK_VoidSymbol,
  79.     /* 03 - VK_BUTTON3      */  XK_VoidSymbol,
  80.     /* 04 - VK_BREAK        */  XK_Break,
  81.     /* 05 - VK_BACKSPACE    */  XK_BackSpace,
  82.     /* 06 - VK_TAB          */  XK_Tab,
  83.     /* 07 - VK_BACKTAB      */  XK_VoidSymbol,
  84.     /* 08 - VK_NEWLINE      */  XK_Return,
  85.     /* 09 - VK_SHIFT        */  XK_Shift_L,
  86.     /* 0a - VK_CTRL         */  XK_Control_L,
  87.     /* 0b - VK_ALT          */  XK_VoidSymbol,
  88.     /* 0c - VK_ALTGRAF      */  XK_VoidSymbol,
  89.     /* 0d - VK_PAUSE        */  XK_Pause,
  90.     /* 0e - VK_CAPSLOCK     */  XK_Caps_Lock,
  91.     /* 0f - VK_ESC          */  XK_Escape,
  92.     /* 10 - VK_SPACE        */  XK_space,
  93.     /* 11 - VK_PAGEUP       */  XK_Page_Up,
  94.     /* 12 - VK_PAGEDOWN     */  XK_Page_Down,
  95.     /* 13 - VK_END          */  XK_End,
  96.     /* 14 - VK_HOME         */  XK_Home,
  97.     /* 15 - VK_LEFT         */  XK_Left,
  98.     /* 16 - VK_UP           */  XK_Up,
  99.     /* 17 - VK_RIGHT        */  XK_Right,
  100.     /* 18 - VK_DOWN         */  XK_Down,
  101.     /* 19 - VK_PRINTSCRN    */  XK_Print,
  102.     /* 1a - VK_INSERT       */  XK_Insert,
  103.     /* 1b - VK_DELETE       */  XK_Delete,
  104.     /* 1c - VK_SCRLLOCK     */  XK_Scroll_Lock,
  105.     /* 1d - VK_NUMLOCK      */  XK_VoidSymbol,
  106.     /* 1e - VK_ENTER        */  XK_Return,
  107.     /* 1f - VK_SYSRQ        */  XK_Sys_Req,
  108.     /* 20 - VK_F1           */  XK_F1,
  109.     /* 21 - VK_F2           */  XK_F2,
  110.     /* 22 - VK_F3           */  XK_F3,
  111.     /* 23 - VK_F4           */  XK_F4,
  112.     /* 24 - VK_F5           */  XK_F5,
  113.     /* 25 - VK_F6           */  XK_F6,
  114.     /* 26 - VK_F7           */  XK_F7,
  115.     /* 27 - VK_F8           */  XK_F8,
  116.     /* 28 - VK_F9           */  XK_F9,
  117.     /* 29 - VK_F10          */  XK_F10,
  118.     /* 2a - VK_F11          */  XK_F11,
  119.     /* 2b - VK_F12          */  XK_F12,
  120.     /* 2c - VK_F13          */  XK_F13,
  121.     /* 2d - VK_F14          */  XK_F14,
  122.     /* 2e - VK_F15          */  XK_F15,
  123.     /* 2f - VK_F16          */  XK_F16,
  124.     /* 30 - VK_F17          */  XK_F17,
  125.     /* 31 - VK_F18          */  XK_F18,
  126.     /* 32 - VK_F19          */  XK_F19,
  127.     /* 33 - VK_F20          */  XK_F20,
  128.     /* 34 - VK_F21          */  XK_F21,
  129.     /* 35 - VK_F22          */  XK_F22,
  130.     /* 36 - VK_F23          */  XK_F23,
  131.     /* 37 - VK_F24          */  XK_F24,
  132.     /* 38 - VK_ENDDRAG      */  XK_VoidSymbol,
  133.     /* 39 - VK_CLEAR        */  XK_Clear,
  134.     /* 3a - VK_EREOF        */  XK_VoidSymbol,
  135.     /* 3b - VK_PA1          */  XK_VoidSymbol,
  136.     /* 3c - VK_ATTN         */  XK_VoidSymbol,
  137.     /* 3d - VK_CRSEL        */  XK_VoidSymbol,
  138.     /* 3e - VK_EXSEL        */  XK_VoidSymbol,
  139.     /* 3f - VK_COPY         */  XK_VoidSymbol,
  140.     /* 40 - VK_BLK1         */  XK_VoidSymbol,
  141.     /* 41 - VK_BLK2         */  XK_VoidSymbol,
  142.     /* 42 - undef           */  XK_VoidSymbol,
  143.     /* 43 - undef           */  XK_VoidSymbol,
  144.     /* 44 - undef           */  XK_VoidSymbol,
  145.     /* 45 - undef           */  XK_VoidSymbol,
  146.     /* 46 - undef           */  XK_VoidSymbol,
  147.     /* 47 - undef           */  XK_VoidSymbol,
  148.     /* 48 - undef           */  XK_VoidSymbol,
  149.     /* 49 - undef           */  XK_VoidSymbol,
  150.     /* 4a - undef           */  XK_VoidSymbol,
  151.     /* 4b - undef           */  XK_VoidSymbol,
  152.     /* 4c - undef           */  XK_VoidSymbol,
  153.     /* 4d - undef           */  XK_VoidSymbol,
  154.     /* 4e - undef           */  XK_VoidSymbol,
  155.     /* 4f - undef           */  XK_VoidSymbol,
  156.     /* 50 - undef           */  XK_VoidSymbol,
  157.     /* 51 - undef           */  XK_VoidSymbol,
  158.     /* 52 - undef           */  XK_VoidSymbol,
  159.     /* 53 - undef           */  XK_VoidSymbol,
  160.     /* 54 - undef           */  XK_VoidSymbol,
  161.     /* 55 - undef           */  XK_VoidSymbol,
  162.     /* 56 - undef           */  XK_VoidSymbol,
  163.     /* 57 - undef           */  XK_VoidSymbol,
  164.     /* 58 - undef           */  XK_VoidSymbol,
  165.     /* 59 - undef           */  XK_VoidSymbol,
  166.     /* 5a - undef           */  XK_VoidSymbol,
  167.     /* 5b - undef           */  XK_VoidSymbol,
  168.     /* 5c - undef           */  XK_VoidSymbol,
  169.     /* 5d - undef           */  XK_VoidSymbol,
  170.     /* 5e - undef           */  XK_VoidSymbol,
  171.     /* 5f - undef           */  XK_VoidSymbol,
  172.     /* 60 - undef           */  XK_VoidSymbol,
  173.     /* 61 - undef           */  XK_VoidSymbol,
  174.     /* 62 - undef           */  XK_VoidSymbol,
  175.     /* 63 - undef           */  XK_VoidSymbol,
  176.     /* 64 - undef           */  XK_VoidSymbol,
  177.     /* 65 - undef           */  XK_VoidSymbol,
  178.     /* 66 - undef           */  XK_VoidSymbol,
  179.     /* 67 - undef           */  XK_VoidSymbol,
  180.     /* 68 - undef           */  XK_VoidSymbol,
  181.     /* 69 - undef           */  XK_VoidSymbol,
  182.     /* 6a - undef           */  XK_VoidSymbol,
  183.     /* 6b - undef           */  XK_VoidSymbol,
  184.     /* 6c - undef           */  XK_VoidSymbol,
  185.     /* 6d - undef           */  XK_VoidSymbol,
  186.     /* 6e - undef           */  XK_VoidSymbol,
  187.     /* 6f - undef           */  XK_VoidSymbol,
  188.     /* 70 - undef           */  XK_VoidSymbol,
  189.     /* 71 - undef           */  XK_VoidSymbol,
  190.     /* 72 - undef           */  XK_VoidSymbol,
  191.     /* 73 - undef           */  XK_VoidSymbol,
  192.     /* 74 - undef           */  XK_VoidSymbol,
  193.     /* 75 - undef           */  XK_VoidSymbol,
  194.     /* 76 - undef           */  XK_VoidSymbol,
  195.     /* 77 - undef           */  XK_VoidSymbol,
  196.     /* 78 - undef           */  XK_VoidSymbol,
  197.     /* 79 - undef           */  XK_VoidSymbol,
  198.     /* 7a - undef           */  XK_VoidSymbol,
  199.     /* 7b - undef           */  XK_VoidSymbol,
  200.     /* 7c - undef           */  XK_VoidSymbol,
  201.     /* 7d - undef           */  XK_VoidSymbol,
  202.     /* 7e - undef           */  XK_VoidSymbol,
  203.     /* 7f - undef           */  XK_VoidSymbol,
  204.     /* 80 - undef           */  XK_Romaji,
  205.     /* 81 - undef           */  XK_Katakana,
  206.     /* 82 - undef           */  XK_Hiragana,
  207.     /* 83 - undef           */  XK_Zenkaku_Hankaku,
  208.     /* 84 - undef           */  XK_Zenkaku_Hankaku,
  209.     /* 85 - undef           */  XK_VoidSymbol,
  210.     /* 86 - undef           */  XK_VoidSymbol,
  211.     /* 87 - undef           */  XK_VoidSymbol,
  212.     /* 88 - undef           */  XK_VoidSymbol,
  213.     /* 89 - undef           */  XK_VoidSymbol,
  214.     /* 8a - undef           */  XK_VoidSymbol,
  215.     /* 8b - undef           */  XK_VoidSymbol,
  216.     /* 8c - undef           */  XK_VoidSymbol,
  217.     /* 8d - undef           */  XK_VoidSymbol,
  218.     /* 8e - undef           */  XK_VoidSymbol,
  219.     /* 8f - undef           */  XK_VoidSymbol,
  220.     /* 90 - undef           */  XK_VoidSymbol,
  221.     /* 91 - undef           */  XK_VoidSymbol,
  222.     /* 92 - undef           */  XK_VoidSymbol,
  223.     /* 93 - undef           */  XK_VoidSymbol,
  224.     /* 94 - undef           */  XK_VoidSymbol,
  225.     /* 95 - undef           */  XK_VoidSymbol,
  226.     /* 96 - undef           */  XK_VoidSymbol,
  227.     /* 97 - undef           */  XK_VoidSymbol,
  228.     /* 98 - undef           */  XK_VoidSymbol,
  229.     /* 99 - undef           */  XK_VoidSymbol,
  230.     /* 9a - undef           */  XK_VoidSymbol,
  231.     /* 9b - undef           */  XK_VoidSymbol,
  232.     /* 9c - undef           */  XK_VoidSymbol,
  233.     /* 9d - undef           */  XK_VoidSymbol,
  234.     /* 9e - undef           */  XK_VoidSymbol,
  235.     /* 9f - undef           */  XK_VoidSymbol,
  236.     /* a0 - undef           */  XK_VoidSymbol,
  237.     /* a1 - undef           */  XK_Henkan,
  238.     /* a2 - undef           */  XK_Muhenkan,
  239.     /* a3 - undef           */  XK_VoidSymbol,
  240.     /* a4 - undef           */  XK_VoidSymbol,
  241.     /* a5 - undef           */  XK_VoidSymbol,
  242.     /* a6 - undef           */  XK_VoidSymbol,
  243.     /* a7 - undef           */  XK_VoidSymbol,
  244.     /* a8 - undef           */  XK_VoidSymbol,
  245.     /* a9 - undef           */  XK_VoidSymbol,
  246.     /* aa - undef           */  XK_VoidSymbol,
  247.     /* ab - undef           */  XK_VoidSymbol,
  248.     /* ac - undef           */  XK_VoidSymbol,
  249.     /* ad - undef           */  XK_VoidSymbol,
  250.     /* ae - undef           */  XK_VoidSymbol,
  251.     /* af - undef           */  XK_VoidSymbol
  252. } ;
  253.  
  254. #define vkMax   0xaf
  255.  
  256. /*
  257.  * keyVirtual - process Virtual Key
  258.  */
  259.  
  260. void    keyVirtual(HWND hwnd, USHORT flags, USHORT ch, USHORT vk, USHORT sc)
  261. {
  262.     BOOL    down ;
  263.     ULONG   xkey ;
  264.     
  265.     if (vk <= vkMax) {
  266.         xkey = vkMap[vk & 0xff] ;
  267.     } else {
  268.         xkey = XK_VoidSymbol ;
  269.     }
  270.     if (xkey == XK_VoidSymbol) {
  271.         return ;
  272.     }
  273.     down = (flags & KC_KEYUP) ? FALSE : TRUE ;
  274.     
  275.     if (down && (flags & KC_PREVDOWN)) {
  276.         sendKeyEvent(FALSE, xkey) ;
  277.     }
  278.     sendKeyEvent(down, xkey) ;
  279. }
  280.  
  281. /*
  282.  * keyControl - process CTRL key pressed
  283.  */
  284.  
  285. void    keyControl(HWND hwnd, USHORT flags, USHORT ch, USHORT vk, USHORT sc)
  286. {
  287.     BOOL    down ;
  288.     ULONG   xkey ;
  289.     
  290.     xkey = (ULONG) (ch & 0x1f) + 0x40 ;
  291.     down = (flags & KC_KEYUP) ? FALSE : TRUE ;
  292.  
  293.     if (down && (flags & KC_PREVDOWN)) {
  294.         sendKeyEvent(FALSE, xkey) ;
  295.     }
  296.     sendKeyEvent(down, xkey) ;
  297. }
  298.  
  299. /*
  300.  * keyNormal - normal (have char code) keys
  301.  */
  302.  
  303. void    keyNormal(HWND hwnd, USHORT flags, USHORT ch, USHORT vk, USHORT sc)
  304. {
  305.     ULONG   xkey ;
  306.     
  307.     xkey = (ULONG) (ch & 0xff) ;
  308.     sendKeyEvent(TRUE,  xkey) ; 
  309.     sendKeyEvent(FALSE, xkey) ; 
  310. }
  311.  
  312. /*
  313.  * keyEvent - process Keyboard Events
  314.  */
  315.  
  316. void    keyEvent(HWND hwnd, USHORT flags, USHORT ch, USHORT vk, USHORT sc)
  317. {
  318.     if (keyMapped(hwnd, flags, ch, vk, sc) == TRUE) {
  319.         return ;
  320.     }
  321.  
  322.     if (flags & KC_VIRTUALKEY) {
  323.         keyVirtual(hwnd, flags, ch, vk, sc) ;
  324.     return ;
  325.     }
  326.     if (flags & KC_ALT) {               /* ignore ALT combination   */
  327.         return ;
  328.     }
  329.     if (flags & KC_CTRL) {
  330.         keyControl(hwnd, flags, ch, vk, sc) ;
  331.     return ;
  332.     }
  333.     if (flags & KC_CHAR) {
  334.         keyNormal(hwnd, flags, ch, vk, sc) ;
  335.     return ;
  336.     }
  337. }
  338.  
  339. /*
  340.  * keyFocusChange - adjust modal key state to current state
  341.  */
  342.  
  343. void    keyFocusChange(HWND hwnd)
  344. {
  345.     LONG    sft, ctl, alt ;
  346.     BOOL    down ;
  347.     
  348.     sft = WinGetKeyState(hwnd, VK_SHIFT) ;
  349.     ctl = WinGetKeyState(hwnd, VK_CTRL)  ;
  350.     alt = WinGetKeyState(hwnd, VK_ALT)   ;
  351.     
  352.     down = (sft & 0x8000) ? TRUE : FALSE ;
  353.     if (stateSftDown != down) {
  354.         sendKeyEvent(down, XK_Shift_L) ;
  355.     }
  356.     down = (ctl & 0x8000) ? TRUE : FALSE ;
  357.     if (stateCtlDown != down) {
  358.         sendKeyEvent(down, XK_Control_L) ;
  359.     }
  360.     down = (alt & 0x8000) ? TRUE : FALSE ; 
  361.     if (stateAltDown != down) {
  362.         sendKeyEvent(down, XK_Alt_L) ;
  363.     }
  364. }
  365.  
  366. /*
  367.  * keyEmulateFixed - key emulation from menu (fixed sequence)
  368.  */
  369.  
  370. typedef struct  _KEYSEQ {
  371.     ULONG   xkey ;
  372.     BOOL    down ;
  373. } SEQREC, *SEQPTR ;
  374.  
  375. typedef struct  _KEYEMU {
  376.     SHORT   id  ;
  377.     SEQPTR  seq ;
  378. } EMUREC, *EMUPTR ;
  379.  
  380. static  SEQREC  seqCtlDn[] = { { XK_Control_L, TRUE},  { -1, 0} } ;
  381. static  SEQREC  seqCtlUp[] = { { XK_Control_L, FALSE}, { -1, 0} } ;
  382. static  SEQREC  seqAltDn[] = { { XK_Alt_L,     TRUE},  { -1, 0} } ;
  383. static  SEQREC  seqAltUp[] = { { XK_Alt_L,     FALSE}, { -1, 0} } ;
  384.  
  385. static  SEQREC  seqFunc01[] = { { XK_F1,  TRUE}, { XK_F1,  FALSE}, { -1, 0} } ;
  386. static  SEQREC  seqFunc02[] = { { XK_F2,  TRUE}, { XK_F2,  FALSE}, { -1, 0} } ;
  387. static  SEQREC  seqFunc03[] = { { XK_F3,  TRUE}, { XK_F3,  FALSE}, { -1, 0} } ;
  388. static  SEQREC  seqFunc04[] = { { XK_F4,  TRUE}, { XK_F4,  FALSE}, { -1, 0} } ;
  389. static  SEQREC  seqFunc05[] = { { XK_F5,  TRUE}, { XK_F5,  FALSE}, { -1, 0} } ;
  390. static  SEQREC  seqFunc06[] = { { XK_F6,  TRUE}, { XK_F6,  FALSE}, { -1, 0} } ;
  391. static  SEQREC  seqFunc07[] = { { XK_F7,  TRUE}, { XK_F7,  FALSE}, { -1, 0} } ;
  392. static  SEQREC  seqFunc08[] = { { XK_F8,  TRUE}, { XK_F8,  FALSE}, { -1, 0} } ;
  393. static  SEQREC  seqFunc09[] = { { XK_F9,  TRUE}, { XK_F9,  FALSE}, { -1, 0} } ;
  394. static  SEQREC  seqFunc10[] = { { XK_F10, TRUE}, { XK_F10, FALSE}, { -1, 0} } ;
  395. static  SEQREC  seqFunc11[] = { { XK_F11, TRUE}, { XK_F11, FALSE}, { -1, 0} } ;
  396. static  SEQREC  seqFunc12[] = { { XK_F12, TRUE}, { XK_F12, FALSE}, { -1, 0} } ;
  397.  
  398. static  SEQREC  seqC_A_D[] = {
  399.     { XK_Control_L, TRUE  } ,
  400.     { XK_Alt_L,     TRUE  } ,
  401.     { XK_Delete,    TRUE  } ,
  402.     { XK_Delete,    FALSE } ,
  403.     { XK_Alt_L,     FALSE } ,
  404.     { XK_Control_L, FALSE } ,
  405.     { -1, 0 }
  406. } ;
  407.  
  408. static  SEQREC  seqCtlEsc[] = {
  409.     { XK_Control_L, TRUE  } ,
  410.     { XK_Escape,    TRUE  } ,
  411.     { XK_Escape,    FALSE } ,
  412.     { XK_Control_L, FALSE } ,
  413.     { -1, 0 }
  414. } ;
  415.  
  416. static  SEQREC  seqAltTab[] = {
  417.     { XK_Alt_L, TRUE  } ,
  418.     { XK_Tab,   TRUE  } ,
  419.     { XK_Tab,   FALSE } ,
  420.     { XK_Alt_L, FALSE } ,
  421.     { -1, 0 }
  422. } ;
  423.  
  424. static  EMUREC  emuTab[] = {
  425.     {   IDM_CTLDN,  seqCtlDn    } ,
  426.     {   IDM_CTLUP,  seqCtlUp    } ,
  427.     {   IDM_ALTDN,  seqAltDn    } ,
  428.     {   IDM_ALTUP,  seqAltUp    } ,
  429.     {   IDM_FUNC01, seqFunc01   } ,
  430.     {   IDM_FUNC02, seqFunc02   } ,
  431.     {   IDM_FUNC03, seqFunc03   } ,
  432.     {   IDM_FUNC04, seqFunc04   } ,
  433.     {   IDM_FUNC05, seqFunc05   } ,
  434.     {   IDM_FUNC06, seqFunc06   } ,
  435.     {   IDM_FUNC07, seqFunc07   } ,
  436.     {   IDM_FUNC08, seqFunc08   } ,
  437.     {   IDM_FUNC09, seqFunc09   } ,
  438.     {   IDM_FUNC10, seqFunc10   } ,
  439.     {   IDM_FUNC11, seqFunc11   } ,
  440.     {   IDM_FUNC12, seqFunc12   } ,
  441.     {   IDM_C_A_D,  seqC_A_D    } ,
  442.     {   IDM_CTLESC, seqCtlEsc   } ,
  443.     {   IDM_ALTTAB, seqAltTab   } ,
  444.     {   0,          NULL        } 
  445. } ;
  446.  
  447. void    keyEmulateFixed(SHORT id)
  448. {
  449.     EMUPTR  ep ;
  450.     SEQPTR  sp ;
  451.     
  452.     for (ep = emuTab ; ep->id != 0 ; ep++) {
  453.         if (ep->id == id) {
  454.         break ;
  455.     }
  456.     }
  457.     if (ep->id != id) {
  458.         return ;
  459.     }
  460.     
  461.     for (sp = ep->seq ; sp->xkey != (ULONG) -1 ; sp++) {
  462.         sendKeyEvent(sp->down, sp->xkey) ; 
  463.     }
  464. }
  465.  
  466. /*
  467.  * keyEmulateToggle - key emulation from menu (toggle)
  468.  */
  469.  
  470. void    keyEmulateToggle(SHORT id)
  471. {
  472.     ULONG   xkey ;
  473.     BOOL    down ;
  474.     
  475.     switch (id) {
  476.     case IDM_CTLTGL :
  477.         xkey = XK_Control_L ;
  478.     down = stateCtlDown ? FALSE : TRUE ;
  479.         break ;
  480.     case IDM_ALTTGL :
  481.         xkey = XK_Alt_L ;
  482.     down = stateAltDown ? FALSE : TRUE ;
  483.         break ;
  484.     default :
  485.         xkey = XK_VoidSymbol ;
  486.     break ;
  487.     }
  488.     if (xkey == XK_VoidSymbol) {
  489.         return ;
  490.     }
  491.     sendKeyEvent(down, xkey) ;
  492. }
  493.