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