home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 345.lha / snap_v1.4 / source / ikm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-13  |  8.9 KB  |  322 lines

  1. /* ikm.c -- invert keymaps      */
  2.  
  3. /** NOTICE:
  4.  * The contents of this file are copyright 1987, Jim Mackraz.  All rights
  5.  * reserved.  No use of the contents of this file or the compilation
  6.  * of them may be used apart from the entire Commodities Exchange
  7.  * without written permission.
  8.  */
  9.  
  10. #define CONTROLBITS     ( (1 << 5) | (1 << 6) )
  11.  
  12. /* return >= 0 if ok (no error checking now)    */
  13. ULONG InvertKeyMap(ansicode, ie, km)
  14. ULONG ansicode;
  15. register struct InputEvent *ie;
  16. struct KeyMap *km;
  17. {
  18.     ULONG   kindex;
  19.     UBYTE   code = 0;
  20.     extern struct KeyMap keymap;
  21.  
  22.     if (km == NULL) {
  23.         km = &keymap;
  24.     }
  25.  
  26.     ie->ie_Class = IECLASS_RAWKEY;
  27.     ie->ie_EventAddress = 0;
  28.  
  29.     /* check for codes in (default) high map first  */
  30.     switch(ansicode)
  31.     {
  32.         case ' ':
  33.             code = 0x40;        /* space            */
  34.             break;
  35.         case 0x08:              /* backspace    */
  36.             code = 0x41;
  37.             break;
  38.         case '\t':              /* tab                  */
  39.             code = 0x42;
  40.             break;
  41.         case 0x0D:              /* return               */
  42.             code = 0x44;
  43.             break;
  44.         case 0x1B:              /* esc                  */
  45.             code = 0x45;
  46.             break;
  47.         case 0x7F:              /* del                  */
  48.             code = 0x46;
  49.             break;
  50.     }
  51.  
  52.     if (code) {
  53.         ie->ie_Code = code;
  54.         ie->ie_Qualifier = 0;
  55.         return (1);
  56.     }
  57.  
  58.     if (LowKeyInvert((UBYTE) ansicode, km,
  59.             &ie->ie_Code, &ie->ie_Qualifier, &kindex) >= 0) {
  60.         if (kindex) {   /* was dead key, need "preceding" keystroke. */
  61.             IndexKey(kindex, km, (ULONG *)&ie->ie_EventAddress);
  62.         }
  63.     }
  64.  
  65.     return (1);
  66. }
  67.  
  68. #define KEYMAPSIZE      64
  69.  
  70. /* LowKeyInvert returns good code else <0 if no find
  71.  *
  72.  * regarding keymap as many-to-one mapping:
  73.  * -entries for a given key are scanned so that
  74.  *      the minimum number of qualifiers are associated
  75.  *      with the keystroke.
  76.  * -passing a character value of zero corresponds, in
  77.  *      the default keymap, to CTRL-`, which is probably a bug.
  78.  * -numerals are matched with numeric pad keystrokes (no
  79.  *      qualifiers) on standard keymap.  The way to specify
  80.  *      a key on the number row is via its shifted value;
  81.  *      specify explicitly that the qualifier is to be unshifted,
  82.  *      or a "don't care."
  83.  */
  84. UWORD LowKeyInvert(value, km, codep, qualp, indexp)
  85. register UBYTE  value;  /* translation value from low keymap    */
  86. struct  KeyMap  *km;
  87. UWORD   *codep;         /* pointers where answers are to be put */
  88. UWORD   *qualp;
  89. ULONG   *indexp;        /* dead-key index information (put into ie?)    */
  90. {
  91.     register UWORD code = 0;
  92.     register WORD type;
  93.     register LONG *p;             /* points to four-byte lokeymap entry   */
  94.     WORD found_it = 0;
  95.  
  96.     *indexp = *qualp = 0;
  97.  
  98.     p = (LONG *) km->km_LoKeyMap;
  99.  
  100.     do  {
  101.         /* determine type of key        */
  102.         if ((type = km->km_LoKeyMapTypes[code] ) == KC_VANILLA) {
  103.             found_it = checkVanilla((UBYTE *)p, value, qualp);
  104.         } else if (type & KCF_DEAD) {
  105.             found_it = checkDead((UBYTE **)p, value, qualp, indexp);
  106.         }
  107.         /**
  108.         else if (type & KCF_STRING) {
  109.         }
  110.         **/
  111.         else if (!(type & KCF_NOP)) {
  112.             found_it = checkNormal((LONG)p, value, (UWORD)type, qualp);
  113.         }
  114.  
  115.         ++p;
  116.     } while (!found_it && ++code < KEYMAPSIZE);
  117.  
  118.     *codep = code;
  119.     return (code);
  120. }
  121.  
  122. /*
  123.  * packs code|qual of previous key (should be keys) in *dead_vudup
  124.  * returns code, <0 if failure
  125.  */
  126. VOID IndexKey(inx, km, dead_vudup)
  127. ULONG   inx;
  128. struct  KeyMap  *km;
  129. ULONG   *dead_vudup;
  130. {
  131.     /* find keystroke which generates index */
  132.  
  133.     register WORD code = 0;
  134.     UWORD **p;            /* points to four-byte lokeymap entry   */
  135.     register UWORD *deadthing;
  136.     WORD i;
  137.     WORD qual = 0;
  138.     LONG vudu;
  139.  
  140.     p = (UWORD **) km->km_LoKeyMap;
  141.  
  142.     do {
  143.         /* check each deadkey in the table      */
  144.  
  145.         if (km->km_LoKeyMapTypes[code] & KCF_DEAD) {
  146.             /* keymap entry is pointer to eight prefix:byte pairs   */
  147.  
  148.             deadthing = *p;
  149.             for (i = 0; i < 8; ++i, ++deadthing) {
  150.                 /* check for index prefix and correct index     */
  151.                 if (*deadthing == ((DPF_DEAD << 8) | inx)) {
  152.                     deadQual((WORD)i, &qual);
  153.                     goto FOUND_IT;
  154.                 }
  155.             }
  156.         }
  157.         ++p;
  158.     } while (++code < KEYMAPSIZE);
  159.  
  160. FOUND_IT:
  161.  
  162.     /* pack as follows: [pred(-1)|qual(-1)|pred(-2)|qual(-2)]       */
  163.     /* for now, 2nd previous deadkey ignored                                        */
  164.  
  165.     if (code < 0) {
  166.         *dead_vudup = 0;
  167.     } else {
  168.         vudu =  code << 8;
  169.         vudu |= (0xFF & qual);
  170.         vudu <<= 16;
  171.  
  172.         *dead_vudup = vudu;
  173.     }
  174. }
  175.  
  176.  
  177. WORD checkNormal(four_bytesp, val, type, qualp)
  178. LONG    four_bytesp;
  179. UBYTE   val;
  180. UWORD   type;
  181. UWORD   *qualp;
  182. {
  183.     register UBYTE  *p = (UBYTE *) four_bytesp; /* codes held in long word  */
  184.     register WORD    position;
  185.  
  186.     /* start with last of four bytes, "more vanilla"        */
  187.     p += 3;
  188.  
  189.     for (position = 3; position >= 0; --position, --p) {
  190.         if (*p == val) {
  191.             switch (type) {
  192.                 case KC_NOQUAL:
  193.                     if (position != 3) goto NOT_THIS;
  194.                     break;
  195.  
  196.                 case KCF_SHIFT:
  197.                     if (!(position & 2)) goto NOT_THIS;
  198.                     if (position == 2) *qualp |= IEQUALIFIER_LSHIFT;
  199.                     break;
  200.  
  201.                 case KCF_ALT:
  202.                     if (!(position & 2)) goto NOT_THIS;
  203.                     if (position == 2) *qualp |= IEQUALIFIER_LALT;
  204.                     break;
  205.  
  206.                 case KCF_CONTROL:
  207.                     if (!(position & 2)) goto NOT_THIS;
  208.                     if (position == 2) *qualp |= IEQUALIFIER_CONTROL;
  209.                     break;
  210.  
  211.                 case KCF_ALT | KCF_CONTROL:
  212.                     if (!(position & 1)) *qualp |= IEQUALIFIER_LALT;
  213.                     if (!(position & 2)) *qualp |= IEQUALIFIER_CONTROL;
  214.                     break;
  215.  
  216.                 case KCF_SHIFT | KCF_CONTROL:
  217.                     if (!(position & 1)) *qualp |= IEQUALIFIER_LSHIFT;
  218.                     if (!(position & 2)) *qualp |= IEQUALIFIER_CONTROL;
  219.                     break;
  220.  
  221.                 case KCF_SHIFT | KCF_ALT:
  222.                     if (!(position & 1)) *qualp |= IEQUALIFIER_LSHIFT;
  223.                     if (!(position & 2)) *qualp |= IEQUALIFIER_LALT;
  224.                     break;
  225.                 default:
  226.                     break;
  227.             }
  228.             return (1);
  229.         }
  230. NOT_THIS:       ;
  231.     }
  232.     return (0);
  233. }
  234.  
  235. WORD checkVanilla(p, val, qualp)
  236. UBYTE   *p;                     /* note: byte pointer   */
  237. UBYTE   val;
  238. UWORD   *qualp;
  239. {
  240.     register WORD i;
  241.  
  242.     /* only one way to match a vanilla control key  */
  243.     if (!(val & CONTROLBITS)) {
  244.         /* is a control code    */
  245.  
  246.         if ((p[3] & ~CONTROLBITS) == val) {
  247.             *qualp |= IEQUALIFIER_CONTROL;
  248.             return (1);
  249.         }
  250.     } else {
  251.         /* not a control        */
  252.         for (i = 3; i >= 0; --i) {
  253.             if (p[i] == val) {
  254.                 if (!(i & 1)) *qualp |= IEQUALIFIER_LSHIFT;
  255.                 if (!(i & 2)) *qualp |= IEQUALIFIER_LALT;
  256.                 return (1);
  257.             }
  258.         }
  259.     }
  260.     return (0);
  261. }
  262.  
  263.  
  264. WORD checkDead(keybase, val, qualp, indexp)
  265. UBYTE   **keybase;                      /* note: byte pointer   */
  266. UBYTE   val;
  267. UWORD   *qualp;
  268. ULONG   *indexp;
  269. {
  270.     WORD i;
  271.     WORD j;
  272.  
  273.     register UWORD *p = (UWORD *) *keybase;
  274.     /* need to remember keybase for offsets */
  275.  
  276.     UBYTE *deadp;
  277.     WORD found_it = 0;
  278.  
  279.     /* walk through eight two-byte entries, one for each qual. combo.       */
  280.     for (i = 0; i < 8; ++i, ++p) {
  281.         switch (*p >> 8) {
  282.             case DPF_DEAD:       /* dead keys do not themselves map to anything */
  283.                 break;
  284.             case DPF_MOD:        /* dead key modifiable  */
  285.                 deadp = *keybase + (*p & 0xFF);
  286.                 /* look down the string indexed by dead-key     index */
  287.                 for (j = 0; j < 6; ++j) {
  288.                     if (deadp[j] == val) {
  289.                         found_it = 1;
  290.                         *indexp = j;
  291.                         break;
  292.                     }
  293.                 }
  294.                 break;
  295.             case 0:                      /* normal stroke for this key   */
  296.                 if ((*p & 0xFF) == val) {
  297.                     found_it = 1;
  298.             }
  299.         }
  300.  
  301.         if (found_it) {
  302.             deadQual((WORD)i, qualp);
  303.             return (1);
  304.         }
  305.     }
  306.  
  307.     return (0);
  308. }
  309.  
  310. /* figure out qualifier from position */
  311. WORD deadQual(wordpos, qualp)
  312. WORD    wordpos;                /* which word in dead-key string?       */
  313. UWORD   *qualp;
  314. {
  315.     if (wordpos & 1) *qualp |= IEQUALIFIER_LSHIFT;
  316.     if (wordpos & 2) *qualp |= IEQUALIFIER_LALT;
  317.     if (wordpos & 4) *qualp |= IEQUALIFIER_CONTROL;
  318.     return (0);
  319. }
  320.  
  321.  
  322.