home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff398.lzh / KeyMacro / KeySupport.c < prev    next >
C/C++ Source or Header  |  1990-11-01  |  7KB  |  341 lines

  1. /****************************************************************************
  2. *
  3. *    KeySupport.c ----------    Keymacro support routines.
  4. *
  5. *    Author ----------------    Olaf Barthel, MXM
  6. *                Brabeckstrasse 35
  7. *                D-3000 Hannover 71
  8. *
  9. *    KeyMacro  ©  Copyright  1990  by  MXM;  Executable  program,
  10. *    documentation  and  source  code are shareware.  If you like
  11. *    this  program  a  small donation will entitle you to receive
  12. *    updates and new programs from MXM.
  13. *
  14. ****************************************************************************/
  15.  
  16.     /* AllocRem():
  17.      *
  18.      *    Allocate public memory and keep track of its size.
  19.      */
  20.  
  21. VOID *
  22. AllocRem(LONG ByteSize,LONG Requirements)
  23. {
  24.     LONG    *MemoryBlock = NULL;
  25.     LONG     RemSize = ByteSize + sizeof(LONG);
  26.  
  27.     if(ByteSize > 0)
  28.         MemoryBlock = (LONG *)AllocMem(RemSize,Requirements);
  29.  
  30.     if(MemoryBlock)
  31.         *MemoryBlock++ = RemSize;
  32.  
  33.     return((VOID *)MemoryBlock);
  34. }
  35.  
  36.     /* FreeRem():
  37.      *
  38.      *    Free a tracked portion of memory.
  39.      */
  40.  
  41. VOID *
  42. FreeRem(LONG *MemoryBlock)
  43. {
  44.     if(MemoryBlock--)
  45.         FreeMem(MemoryBlock,*MemoryBlock);
  46.  
  47.     return(NULL);
  48. }
  49.  
  50.     /* SendMacroMsg(scm_Msg,scm_Port):
  51.      *
  52.      *    Post a cloned macro message to a MsgPort.
  53.      */
  54.  
  55. VOID *
  56. SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port)
  57. {
  58.     struct MacroMessage *scm_TempMsg;
  59.  
  60.     if(scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR))
  61.     {
  62.         CopyMem(scm_Msg,scm_TempMsg,sizeof(struct MacroMessage));
  63.  
  64.         scm_TempMsg -> mm_Message . mn_Node . ln_Name    = (char *)scm_TempMsg;
  65.         scm_TempMsg -> mm_Message . mn_ReplyPort    = NULL;
  66.         scm_TempMsg -> mm_Message . mn_Length        = sizeof(struct MacroMessage);
  67.  
  68.         PutMsg(scm_Port,(struct Message *)scm_TempMsg);
  69.     }
  70.  
  71.     return((VOID *)scm_TempMsg);
  72. }
  73.  
  74.     /* The following piece of code was written by Jim Mackraz;
  75.      * I do not claim any publishing rights for it, the code
  76.      * is still his property. I will try to remove it as soon
  77.      * as Kick 2.x has left the beta phase (read the docs,
  78.      * there will probably be no further KeyMacro revisions
  79.      * for pre-2.x systems).
  80.      */
  81.  
  82. #define CONTROLBITS     ( (1 << 5) | (1 << 6) )
  83.  
  84. STATIC BYTE
  85. CheckNormal(four_bytesp, val, type, qualp)
  86. LONG four_bytesp;
  87. UBYTE val;
  88. UWORD type;
  89. UWORD *qualp;
  90. {
  91.     UBYTE *p = (UBYTE *)four_bytesp; /* codes held in long word  */
  92.     long position;
  93.  
  94.         /* start with last of four bytes, "more vanilla"        */
  95.  
  96.     p += 3;
  97.  
  98.     for(position = 3 ; position >= 0 ; --position, --p)
  99.     {
  100.         if(*p == val)
  101.         {
  102.             switch(type)
  103.             {
  104.                 case KC_NOQUAL:    if(position != 3)
  105.                             goto NOT_THIS;
  106.  
  107.                         break;
  108.  
  109.                 case KCF_SHIFT:    if(!(position & 2))
  110.                             goto NOT_THIS;
  111.  
  112.                         if(position == 2)
  113.                             *qualp |= IEQUALIFIER_LSHIFT;
  114.  
  115.                         break;
  116.  
  117.                 case KCF_ALT:    if(!(position & 2))
  118.                             goto NOT_THIS;
  119.  
  120.                         if(position == 2)
  121.                             *qualp |= IEQUALIFIER_LALT;
  122.  
  123.                         break;
  124.  
  125.  
  126.                 case KCF_CONTROL:
  127.  
  128.                         if(!(position & 2))
  129.                             goto NOT_THIS;
  130.  
  131.                         if(position == 2)
  132.                             *qualp |= IEQUALIFIER_CONTROL;
  133.  
  134.                         break;
  135.  
  136.                 case KCF_ALT | KCF_CONTROL:
  137.  
  138.                         if(!(position & 1))
  139.                             *qualp |= IEQUALIFIER_LALT;
  140.  
  141.                         if(!(position & 2))
  142.                             *qualp |= IEQUALIFIER_CONTROL;
  143.  
  144.                         break;
  145.  
  146.                 case KCF_SHIFT | KCF_CONTROL:
  147.  
  148.                         if(!(position & 1))
  149.                             *qualp |= IEQUALIFIER_LSHIFT;
  150.  
  151.                         if(!(position & 2))
  152.                             *qualp |= IEQUALIFIER_CONTROL;
  153.  
  154.                         break;
  155.  
  156.  
  157.                 case KCF_SHIFT | KCF_ALT:
  158.  
  159.                         if(!(position & 1))
  160.                             *qualp |= IEQUALIFIER_LSHIFT;
  161.  
  162.                         if(!(position & 2))
  163.                             *qualp |= IEQUALIFIER_LALT;
  164.  
  165.                         break;
  166.  
  167.                 default:    break;
  168.             }
  169.  
  170.             return(TRUE);
  171.         }
  172. NOT_THIS:       ;
  173.     }
  174.  
  175.     return(FALSE);
  176. }
  177.  
  178. STATIC BYTE
  179. CheckVanilla(p,val,qualp)
  180. UBYTE *p;        /* note: byte pointer   */
  181. UBYTE val;
  182. UWORD *qualp;
  183. {
  184.     int i;
  185.  
  186.         /* only one way to match a vanilla control key  */
  187.  
  188.     if(!(val & CONTROLBITS))
  189.     {
  190.         /* is a control code    */
  191.  
  192.         if((p[3] & ~CONTROLBITS) == val)
  193.         {
  194.             *qualp |= IEQUALIFIER_CONTROL;
  195.             return(TRUE);
  196.         }
  197.     }
  198.     else
  199.     {
  200.         /* not a control        */
  201.  
  202.         for(i = 3 ; i >= 0 ; --i)
  203.         {
  204.             if(p[i] == val)
  205.             {
  206.                 if(!(i & 1))
  207.                     *qualp |= IEQUALIFIER_LSHIFT;
  208.  
  209.                 if(!(i & 2))
  210.                     *qualp |= IEQUALIFIER_LALT;
  211.  
  212.                 return(TRUE);
  213.             }
  214.         }
  215.     }
  216.  
  217.     return(FALSE);
  218. }
  219.  
  220. #define KEYMAPSIZE      64
  221.  
  222. /* LowKeyInvert returns good code else <0 if no find
  223.  *
  224.  * regarding keymap as many-to-one mapping:
  225.  * -entries for a given key are scanned so that
  226.  *      the minimum number of qualifiers are associated
  227.  *      with the keystroke.
  228.  * -passing a character value of zero corresponds, in
  229.  *      the default keymap, to CTRL-`, which is probably a bug.
  230.  * -numerals are matched with numeric pad keystrokes (no
  231.  *      qualifiers) on standard keymap.  The way to specify
  232.  *      a key on the number row is via its shifted value;
  233.  *      specify explicitly that the qualifier is to be unshifted,
  234.  *      or a "don't care."
  235.  */
  236.  
  237. STATIC UWORD
  238. LowKeyInvert(value,km,codep,qualp,indexp)
  239. UBYTE value;        /* translation value from low keymap    */
  240. struct KeyMap *km;
  241. UWORD *codep;        /* pointers where answers are to be put */
  242. UWORD *qualp;
  243. ULONG *indexp;        /* dead-key index information (put into ie?)    */
  244. {
  245.     UWORD code = KEYMAPSIZE - 1;    /* last entry   */
  246.     unsigned int type;
  247.     LONG *p;        /* points to four-byte lokeymap entry   */
  248.     int found_it = 0;
  249.  
  250.     *indexp = *qualp = 0;
  251.  
  252.     p = (LONG *)km -> km_LoKeyMap + code;
  253.  
  254.     do
  255.     {
  256.             /* determine type of key        */
  257.  
  258.         if((type = km -> km_LoKeyMapTypes[code]) == KC_VANILLA)
  259.             found_it = CheckVanilla(p,value,qualp);
  260.         else
  261.             if(!(type & KCF_NOP))
  262.                 found_it = CheckNormal(p,value,type,qualp);
  263.  
  264.         --p;
  265.     }
  266.     while(!found_it && code--);
  267.  
  268.     *codep = code;
  269.  
  270.     return(code);
  271. }
  272.  
  273. ULONG
  274. InvertKeyMap(ULONG ansicode,struct InputEvent *ie,struct KeyMap *km)
  275. {
  276.     LONG    kindex;
  277.     UBYTE    code = 0;
  278.  
  279.     ie -> ie_Class        = IECLASS_RAWKEY;
  280.     ie -> ie_EventAddress    = 0;
  281.  
  282.         /* check for codes in (default) high map first  */
  283.  
  284.     switch(ansicode)
  285.     {
  286.         case ' ':    code = 0x40;    /* space            */
  287.                 break;
  288.  
  289.         case 0x08:      code = 0x41;    /* backspace    */
  290.                 break;
  291.  
  292.         case '\t':    code = 0x42;    /* tab                  */
  293.                 break;
  294.  
  295.         case 0x0A:
  296.         case 0x0D:    code = 0x44;    /* return               */
  297.                 break;
  298.  
  299.         case 0x1B:    code = 0x45;    /* esc                  */
  300.                 break;
  301.  
  302.         case 0x7F:    code = 0x46;    /* del                  */
  303.                 break;
  304.  
  305.         case '0':    code = 0x0a;
  306.                 break;
  307.  
  308.         case '1':
  309.         case '2':
  310.         case '3':
  311.         case '4':
  312.         case '5':
  313.         case '6':
  314.         case '7':
  315.         case '8':
  316.         case '9':    code = ansicode - '0';
  317.                 break;
  318.     }
  319.  
  320.     if(ansicode >= '1' && ansicode <= '0')
  321.         code = 
  322.  
  323.     ie -> ie_Code        = 0;
  324.     ie -> ie_Qualifier    = 0;
  325.  
  326.     if(code)
  327.     {
  328.         ie -> ie_Code        = code;
  329.         ie -> ie_Qualifier    = 0;
  330.  
  331.         return(TRUE);
  332.     }
  333.  
  334.     LowKeyInvert((UBYTE)ansicode,km,&ie -> ie_Code,&ie -> ie_Qualifier,(ULONG *)&kindex);
  335.  
  336.     if(!ie -> ie_Code && !ie -> ie_Qualifier)
  337.         return(FALSE);
  338.  
  339.     return(TRUE);
  340. }
  341.