home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 1 / FFMCD01.bin / bbs / libdisks / d700t799 / disk793.lha / Snap / src.lha / src / atie.c next >
Encoding:
C/C++ Source or Header  |  1992-12-15  |  10.1 KB  |  350 lines

  1. /* atie.c -- Ascii To Input Event */
  2.  
  3. /* The contents of this file are copyright 1990, Mikael Karlsson.
  4.  * You may use these routines freely in non-commerical programs,
  5.  * provided that some notice of it's use is given in the program
  6.  * and/or documentation.
  7. */
  8.  
  9. struct HalfMap {
  10.     UBYTE *KeyMapTypes;
  11.     ULONG *KeyMap;
  12.     UBYTE *Capsable;
  13.     UBYTE *Repeatable;
  14. };
  15.  
  16. struct DeadSpec {
  17.     UBYTE ds_Prev1DownCode;
  18.     UBYTE ds_Prev1DownQual;
  19.     UBYTE ds_Prev2DownCode;
  20.     UBYTE ds_Prev2DownQual;
  21. };
  22.  
  23. #define CONTROLBITS ((1 << 5) | (1 << 6))
  24. #define KEYMAPSIZE  64
  25.  
  26. #define S IEQUALIFIER_LSHIFT
  27. #define A IEQUALIFIER_LALT
  28. #define C IEQUALIFIER_CONTROL
  29.  
  30. /* These tables can be found in RKM Libraries & Devices 1.3 */
  31.  
  32. WORD deadQuals[8][10] = {
  33.     { KC_NOQUAL                     , 1, 0                                },
  34.     {                     KCF_SHIFT , 2, 0, S                             },
  35.     {             KCF_ALT           , 2, 0, A                             },
  36.     {             KCF_ALT+KCF_SHIFT , 4, 0, S, A, S+A                     },
  37.     { KCF_CONTROL                   , 2, 0, C                             },
  38.     { KCF_CONTROL+        KCF_SHIFT , 4, 0, S, C, S+C                     },
  39.     { KCF_CONTROL+KCF_ALT           , 4, 0, A, C, A+C                     },
  40.     { KCF_CONTROL+KCF_ALT+KCF_SHIFT , 8, 0, S, A, S+A, C, C+S, C+A, C+S+A }
  41. };
  42.  
  43. WORD normalQuals[8][6] = {
  44.     { KC_NOQUAL                     , 1,   0, 0, 0, 0 },
  45.     {                     KCF_SHIFT , 2,   0, 0, S, 0 },
  46.     {             KCF_ALT           , 2,   0, 0, A, 0 },
  47.     {             KCF_ALT+KCF_SHIFT , 4, S+A, A, S, 0 },
  48.     { KCF_CONTROL                   , 2,   0, 0, C, 0 },
  49.     { KCF_CONTROL+        KCF_SHIFT , 4, C+S ,C, S, 0 },
  50.     { KCF_CONTROL+KCF_ALT           , 4, C+A, C, A, 0 },
  51.     { KCF_CONTROL+KCF_ALT+KCF_SHIFT , 4, S+A, A, S, 0 }
  52. };
  53.  
  54. #define keytype 0
  55. #define combos 1
  56.  
  57. #undef S
  58. #undef A
  59. #undef C
  60.  
  61. STATIC WORD checkNormalQual(four_bytesp, val, type, qualp)
  62. LONG four_bytesp;
  63. UBYTE val;
  64. UWORD type;
  65. UWORD *qualp;
  66. {
  67.     register UBYTE *p = (UBYTE *)four_bytesp; /* codes held in long word  */
  68.     register WORD position;
  69.     register WORD i = normalQuals[type][combos];
  70.  
  71.     position = 4;
  72.  
  73.     while (i--) {
  74.         --position;
  75.         if (p[position] == val) {
  76.             *qualp = normalQuals[type][position + 2];
  77.             return 1;
  78.         }
  79.     }
  80.     return 0;
  81. }
  82.  
  83. WORD checkNormal(p, val, type, qualp)
  84. UBYTE *p;
  85. UBYTE val;
  86. WORD type;
  87. UWORD *qualp;
  88. {
  89.     /* only one way to match a vanilla control key  */
  90.     if (type == KC_VANILLA && (val & CONTROLBITS) == NULL) { /* control vanilla */
  91.         if (checkNormalQual(p, val | CONTROLBITS, type, qualp)) {
  92.             *qualp |= IEQUALIFIER_CONTROL;
  93.             return (1);
  94.         } else {
  95.             return (0);
  96.         }
  97.     } else { /* not a control */
  98.         return (checkNormalQual(p, val, type, qualp));
  99.     }
  100. }
  101.  
  102.  
  103. STATIC WORD checkDead(keybase, val, type, qualp, indexp)
  104. UBYTE *keybase;                      /* note: byte pointer   */
  105. UBYTE val;
  106. WORD type;
  107. UWORD *qualp;
  108. ULONG *indexp;
  109. {
  110.     WORD i;
  111.     WORD j;
  112.     register UBYTE *p = keybase;  /* need to remember keybase for offsets */
  113.     UBYTE *deadp;
  114.  
  115.     /* walk through two-byte entries, one for each qual. combo.       */
  116.     for (i = 0; i < deadQuals[type][combos]; ++i, p += 2) {
  117.         switch (p[0]) {
  118.             case DPF_DEAD:       /* dead keys do not themselves map to anything */
  119.                 break;
  120.             case DPF_MOD:        /* dead key modifiable  */
  121.                 deadp = keybase + p[1];
  122.                 /* look down the string indexed by dead-key     index */
  123.                 for (j = 0; j < 6; ++j) {
  124.                     if (deadp[j] == val) {
  125.                         *qualp = deadQuals[type][i + 2];
  126.                         *indexp = j;
  127.                         return 1;
  128.                     }
  129.                 }
  130.                 break;
  131.             case 0:                      /* normal stroke for this key   */
  132.                 if (p[1] == val) {
  133.                     *qualp = deadQuals[type][i + 2];
  134.                     return 1;
  135.             }
  136.         }
  137.     }
  138.     return (0);
  139. }
  140.  
  141. /*
  142.  * Calculates Code+Qual of previous dead key (should be keys)
  143.  * and puts them in DeapSpec.
  144.  * returns success (1) or failure (0).
  145.  */
  146. STATIC WORD BuildDeadSpec(inx, hm, hms, ds)
  147. ULONG inx;
  148. struct HalfMap *hm;
  149. WORD hms;
  150. struct DeadSpec *ds;
  151. {
  152.     /* find keystroke which generates index */
  153.  
  154.     register WORD code = 0;
  155.     register UBYTE *deadthing;
  156.     register WORD i;
  157.  
  158.     do {
  159.         /* check each deadkey in the table      */
  160.  
  161.         if (hm->KeyMapTypes[code] & KCF_DEAD) {
  162.             register WORD type = hm->KeyMapTypes[code] & 7;
  163.  
  164.             /* keymap entry is pointer to prefix:byte pairs   */
  165.  
  166.             deadthing = (UBYTE *)hm->KeyMap[code];
  167.             for (i = 0; i < deadQuals[type][combos]; ++i, deadthing += 2) {
  168.                   /* check for index prefix and correct index     */
  169.                 if (deadthing[0] == DPF_DEAD &&
  170.                   (deadthing[1] & DP_2DINDEXMASK) == inx) {
  171.                     ds->ds_Prev1DownCode = code;
  172.                     ds->ds_Prev1DownQual = deadQuals[type][i + 2];
  173.                     ds->ds_Prev2DownCode = 0;
  174.                     ds->ds_Prev2DownQual = 0;
  175.                     return 1;
  176.                 }
  177.             }
  178.         }
  179.     } while (++code < hms);
  180.  
  181.     return 0;   /* Not found */
  182. }
  183.  
  184. STATIC WORD checkString(keybase, val, type, qualp)
  185. UBYTE *keybase;                      /* note: byte pointer   */
  186. UBYTE val;
  187. WORD type;
  188. UWORD *qualp;
  189. {
  190.     WORD i;
  191.     register UBYTE *p = keybase;  /* need to remember keybase for offsets */
  192.  
  193.     /* walk through two-byte entries, one for each qual. combo.       */
  194.     for (i = 0; i < deadQuals[type][combos]; ++i, p += 2) {
  195.         if (p[0] == 1) {         /* One char in string */
  196.             if (keybase[p[1]] == val) {   /* Our char? */
  197.                 *qualp = deadQuals[type][i + 2];
  198.                 return 1;
  199.             }
  200.         }
  201.     }
  202.     return (0);
  203. }
  204.  
  205. /* BuildEvent tries to generate an input event.
  206.  * returns success (1) or failure (0).
  207.  */
  208. STATIC UWORD BuildEvent(value, hm, hms, ie, km)
  209. register UBYTE  value;
  210. struct HalfMap *hm;
  211. WORD hms;
  212. struct InputEvent *ie;
  213. struct KeyMap *km;      /* We need this to find dead prefix */
  214. {
  215.     register UWORD code = 0;
  216.     register WORD type;
  217.     register LONG *p;             /* points to four-byte lokeymap entry   */
  218.     UWORD *qualp = &ie->ie_Qualifier;
  219.     WORD found_it = 0;
  220.     ULONG index = 0;
  221.  
  222.     p = (LONG *) hm->KeyMap;
  223.  
  224.     do  {
  225.         type = hm->KeyMapTypes[code];
  226.         /* determine type of key        */
  227.         if (type & KCF_STRING) {
  228.             found_it = checkString((UBYTE *)*p, value, type & 7, qualp);
  229.         } else if (type & KCF_DEAD) {
  230.             found_it = checkDead((UBYTE *)*p, value, type & 7, qualp, &index);
  231.         } else if (!(type & KCF_NOP)) {
  232.             found_it = checkNormal((LONG)p, value, type & 7, qualp);
  233.         }
  234.         ++p;
  235.     } while (!found_it && ++code < hms);
  236.  
  237.     if (found_it) {
  238.         ie->ie_Code = code;
  239.           /* Successful BuildEvent. Check for dead key. */
  240.         if (index) {
  241.             struct HalfMap *dhm;
  242.             struct DeadSpec *ds = (struct DeadSpec *)&ie->ie_EventAddress;
  243.  
  244.             dhm = (struct HalfMap *)&km->km_LoKeyMapTypes;
  245.             if (BuildDeadSpec(index, dhm, 64, ds)) {
  246.                 return 1;
  247.             }
  248.             dhm = (struct HalfMap *)&km->km_HiKeyMapTypes;
  249.             if (BuildDeadSpec(index, dhm, 56, ds)) {
  250.                 return 1;
  251.             }
  252.             return 0;   /* Couldn't find index generating dead key */
  253.         } else {
  254.             return 1;
  255.         }
  256.     } else {
  257.         return 0;
  258.     }
  259. }
  260.  
  261. /*
  262.  * NAME
  263.  *      AsciiToInputEvent -- build input event to generate ascii
  264.  *
  265.  * SYNOPSIS
  266.  *      success = AsciiToInputEvent(ascii, inputevent, keymap)
  267.  *      ULONG AsciiToInputEvent(ULONG, struct InputEvent *, struct KeyMap *)
  268.  *
  269.  * FUNCTION
  270.  *      This function tries to generate an input event that, when sent
  271.  *      to the input handler, will generate the specified ascii code.
  272.  *
  273.  * INPUTS
  274.  *      ascii - the ascii code to be generated by the constructed
  275.  *              input event.
  276.  *
  277.  *      inputevent - the input event that will be filled will the
  278.  *              appropriate values to generate the given ascii code.
  279.  *
  280.  *      keymap - the keymap that the input event will be reverse-
  281.  *              engineered from.
  282.  *
  283.  *
  284.  * RESULT
  285.  *      success - a boolean value indicating whether the reverse-
  286.  *              engineering was successful.
  287.  *
  288.  * NOTE
  289.  *      The ascii code must be available in the given keymap to be
  290.  *      generatable. Ascii values between 128 and 160 are usually
  291.  *      not available with normal keymaps.
  292.  *
  293.  * SEE ALSO
  294.  *      RawKeyConvert(), V36 keymap.library/MapANSI().
  295.  */
  296.  
  297. ULONG AsciiToInputEvent(ascii, ie, km)
  298. ULONG ascii;
  299. register struct InputEvent *ie;
  300. struct KeyMap *km;
  301. {
  302.     struct HalfMap *hm;
  303.  
  304.     ie->ie_Class = IECLASS_RAWKEY;
  305.     ie->ie_Qualifier = 0;
  306.     ie->ie_EventAddress = 0;
  307.  
  308.     /* Some ascii values has to be treated separately
  309.        since some programs know the difference between
  310.        for example CTRL-M and RETURN.  */
  311.     {
  312.         WORD code = 0;
  313.  
  314.         switch(ascii)
  315.         {
  316.             case 0x08:              /* backspace  */
  317.                 code = 0x41;
  318.                 break;
  319.             case '\t':              /* tab        */
  320.                 code = 0x42;
  321.                 break;
  322.             case 0x0D:              /* return     */
  323.                 code = 0x44;
  324.                 break;
  325.             case 0x1B:              /* esc        */
  326.                 code = 0x45;
  327.                 break;
  328.             case 0x7F:              /* del        */
  329.                 code = 0x46;
  330.                 break;
  331.         }
  332.  
  333.         if (code) {
  334.             ie->ie_Code = code;
  335.             return 1;
  336.         }
  337.     }
  338.  
  339.     hm = (struct HalfMap *)&km->km_LoKeyMapTypes;
  340.     if (BuildEvent((UBYTE)ascii, hm, 64, ie, km)) {
  341.         return 1;   /* Key found in LoKeyMap */
  342.     }
  343.     hm = (struct HalfMap *)&km->km_HiKeyMapTypes;
  344.     if (BuildEvent((UBYTE)ascii, hm, 56, ie, km)) {
  345.         ie->ie_Code += 64;  /* Don't forget that we're in the hi keymap */
  346.         return 1;   /* Key found in HiKeyMap */
  347.     }
  348.     return 0;     /* No luck */
  349. }
  350.