home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / keyboard / keymacro_398 / keymacro-handler.c < prev    next >
C/C++ Source or Header  |  1990-11-01  |  19KB  |  944 lines

  1. /****************************************************************************
  2. *
  3. *    KeyMacro-Handler.c ----    KeyMacro handler.
  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.     /* Function prototypes. */
  17.  
  18. struct Process *    CreateFuncProc(char *Name,LONG Priority,APTR InitCode,ULONG StackSize);
  19. VOID            FreeString(BPTR Byte);
  20. BPTR            CreateBSTR(char *s);
  21. BPTR            CopyPath(VOID);
  22. VOID            FakeCLI(VOID);
  23. VOID            ClearPath(BPTR InitPath);
  24. VOID            StopFakery(VOID);
  25. VOID *            DeleteMacroMsg(struct MacroMessage *scm_Msg);
  26. VOID            Executor(VOID);
  27. struct MacroKey *    FindMacroKey(LONG Code,LONG Qualifier);
  28. struct InputEvent *    EventHandler(struct InputEvent *Event);
  29. BYTE            OpenAll(VOID);
  30. VOID            CloseAll(VOID);
  31. BYTE            UStrCmp(UBYTE *a,UBYTE *b);
  32.  
  33. VOID *            AllocRem(LONG ByteSize,LONG Requirements);
  34. VOID *            FreeRem(LONG *MemoryBlock);
  35. VOID *            SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port);
  36. ULONG            InvertKeyMap(ULONG ansicode,struct InputEvent *ie,struct KeyMap *km);
  37.  
  38. LONG            _main(VOID);
  39.  
  40.     /* The magic stuff. */
  41.  
  42. #pragma regcall(EventHandler(a0))
  43.  
  44.     /* Shared library identifiers. */
  45.  
  46. extern struct ExecBase    *SysBase;
  47. struct IntuitionBase    *IntuitionBase;
  48. struct Library        *LayersBase;
  49.  
  50.     /* Global handshake data. */
  51.  
  52. struct MSeg        *MSeg;
  53.  
  54.     /* Process<->Process communication data. */
  55.  
  56. struct Process        *ExecuteProc;
  57. struct MsgPort        *ExecutePort;
  58.  
  59.     /* Input device data. */
  60.  
  61. struct MsgPort        *InputDevPort;
  62. struct IOStdReq        *InputRequestBlock;
  63. struct Interrupt    *InputHandler;
  64. struct InputEvent    *FakeInputEvent;
  65.  
  66.     /* Console device data. */
  67.  
  68. struct IOStdReq        *ConsoleRequest;
  69. struct MsgPort        *ConsolePort;
  70.  
  71.     /* Timer device data. */
  72.  
  73. struct timerequest    *TimeRequest;
  74. struct MsgPort        *TimePort;
  75.  
  76. BYTE             SigBit = -1;
  77.  
  78.     /* Our current version tag. */
  79.  
  80. const char *VersionTag = "$VER: KeyMacro-Handler 1.6 (09 Sep 1990)\n\r";
  81.  
  82.     /* _main():
  83.      *
  84.      *    This is the entry point to the handler process.
  85.      */
  86.  
  87. LONG
  88. _main()
  89. {
  90.     struct Process        *ThatsMe;
  91.     ULONG             SignalSet;
  92.     struct MacroMessage    *MacroMsg;
  93.     LONG             i;
  94.  
  95.         /* Do I know myself? */
  96.  
  97.     ThatsMe = (struct Process *)SysBase -> ThisTask;
  98.  
  99.         /* Don't let anybody call us from CLI. */
  100.  
  101.     if(ThatsMe -> pr_CLI)
  102.         goto Quit;
  103.  
  104.         /* Can we find the global MsgPort? */
  105.  
  106.     if(!(MSeg = (struct MSeg *)FindPort(PORTNAME)))
  107.     {
  108.         Forbid();
  109.  
  110.         Signal(MSeg -> Father,MSeg -> RingBack);
  111.  
  112.         goto Quit;
  113.     }
  114.  
  115.         /* This older revision probably doesn't support
  116.          * some newer structure tags -> exit.
  117.          */
  118.  
  119.     if(MSeg -> Revision < REVISION)
  120.     {
  121.         Forbid();
  122.  
  123.         Signal(MSeg -> Father,MSeg -> RingBack);
  124.  
  125.         goto Quit;
  126.     }
  127.  
  128.         /* The MsgPort is already owned by someone
  129.          * else.
  130.          */
  131.  
  132.     if(MSeg -> Port . mp_Flags & PA_SIGNAL)
  133.     {
  134.         Forbid();
  135.  
  136.         Signal(MSeg -> Father,MSeg -> RingBack);
  137.  
  138.         goto Quit;
  139.     }
  140.  
  141.         /* Open the libraries. */
  142.  
  143.     if(!OpenAll())
  144.     {
  145.         CloseAll();
  146.  
  147.         Forbid();
  148.  
  149.         Signal(MSeg -> Father,MSeg -> RingBack);
  150.  
  151.         goto Quit;
  152.     }
  153.  
  154.         /* Start the executing process. */
  155.  
  156.     MSeg -> Child = (struct Task *)ThatsMe;
  157.  
  158.     if(!(ExecuteProc = (struct Process *)CreateFuncProc("KeyMacro CLI",10,Executor,4000)))
  159.     {
  160.         CloseAll();
  161.  
  162.         Forbid();
  163.  
  164.         MSeg -> Child = NULL;
  165.         Signal(MSeg -> Father,MSeg -> RingBack);
  166.  
  167.         goto Quit;
  168.     }
  169.  
  170.         /* Wait for handshake signal. */
  171.  
  172.     Wait(SIG_SHAKE);
  173.  
  174.         /* Process creation failed. */
  175.  
  176.     if(!ExecuteProc)
  177.     {
  178.         CloseAll();
  179.  
  180.         Forbid();
  181.  
  182.         MSeg -> Child = NULL;
  183.         Signal(MSeg -> Father,MSeg -> RingBack);
  184.  
  185.         goto Quit;
  186.     }
  187.  
  188.         /* Now we are truly running. */
  189.  
  190.     Signal(MSeg -> Father,MSeg -> RingBack);
  191.  
  192.     MSeg -> Father = NULL;
  193.  
  194.         /* Re-init the MsgPort flags. */
  195.  
  196.     MSeg -> Port . mp_Flags        = PA_SIGNAL;
  197.     MSeg -> Port . mp_SigBit    = SigBit;
  198.     MSeg -> Port . mp_SigTask    = MSeg -> Child;
  199.  
  200.         /* Wait until somebody kicks us out. */
  201.  
  202.     FOREVER
  203.     {
  204.         SignalSet = Wait(SIG_CLOSE | SIG_PORT);
  205.  
  206.             /* We are to shut down. */
  207.  
  208.         if(SignalSet & SIG_CLOSE)
  209.         {
  210.             if(ExecuteProc)
  211.             {
  212.                 Signal((struct Task *)ExecuteProc,SIG_CLOSE);
  213.  
  214.                 Wait(SIG_SHAKE);
  215.             }
  216.  
  217.             CloseAll();
  218.  
  219.             Forbid();
  220.  
  221.             Signal(MSeg -> Father,SIG_CLOSE);
  222.  
  223.             goto Quit;
  224.         }
  225.  
  226.             /* A message arrived at our home port. */
  227.  
  228.         if(SignalSet & SIG_PORT)
  229.         {
  230.                 /* Walk through the list of messages. */
  231.  
  232.             while(MacroMsg = (struct MacroMessage *)GetMsg(&MSeg -> Port))
  233.             {
  234.                     /* Execute a keyboard macro. */
  235.  
  236.                 if(MacroMsg -> mm_Type == MM_INPUT)
  237.                 {
  238.                     struct MacroKey *TempMacroKey = MacroMsg -> mm_MacroKey;
  239.  
  240.                     if(TempMacroKey)
  241.                     {
  242.                             /* Let the execute process run the command. */
  243.  
  244.                         if(TempMacroKey -> mk_Type == MK_COMMAND)
  245.                         {
  246.                             struct MacroMessage CommandMsg;
  247.  
  248.                             CommandMsg . mm_Type        = MM_EXECUTE;
  249.  
  250.                             CommandMsg . mm_FileName    = TempMacroKey -> mk_String;
  251.                             CommandMsg . mm_WindowName    = TempMacroKey -> mk_Window;
  252.  
  253.                             SendMacroMsg(&CommandMsg,ExecutePort);
  254.                         }
  255.  
  256.                             /* Build a keyboard macro. */
  257.  
  258.                         if(TempMacroKey -> mk_Type == MK_WORD)
  259.                         {
  260.                             InputRequestBlock -> io_Command    = IND_WRITEEVENT;
  261.                             InputRequestBlock -> io_Data    = (APTR)FakeInputEvent;
  262.  
  263.                             memset(FakeInputEvent,0,sizeof(struct InputEvent));
  264.  
  265.                             FakeInputEvent -> ie_Class    = IECLASS_RAWKEY;
  266.                             FakeInputEvent -> ie_SubClass    = KM_SUBCLASS;
  267.  
  268.                             for(i = 0 ; i < strlen(TempMacroKey -> mk_String) ; i++)
  269.                             {
  270.                                 if(InvertKeyMap(TempMacroKey -> mk_String[i],FakeInputEvent,MSeg -> DefaultKeyMap))
  271.                                 {
  272.                                     FakeInputEvent -> ie_Qualifier |= IEQUALIFIER_RELATIVEMOUSE;
  273.  
  274.                                     DoIO(TimeRequest);
  275.  
  276.                                     FakeInputEvent -> ie_TimeStamp = TimeRequest -> tr_time;
  277.  
  278.                                     DoIO(InputRequestBlock);
  279.  
  280.                                     FakeInputEvent -> ie_Code |= IECODE_UP_PREFIX;
  281.  
  282.                                     DoIO(TimeRequest);
  283.  
  284.                                     FakeInputEvent -> ie_TimeStamp = TimeRequest -> tr_time;
  285.  
  286.                                     DoIO(InputRequestBlock);
  287.                                 }
  288.                             }
  289.                         }
  290.                     }
  291.                 }
  292.  
  293.                     /* This is a request to update the
  294.                      * macro keys.
  295.                      */
  296.  
  297.                 if(MacroMsg -> mm_Type == MM_UPDATE)
  298.                 {
  299.                     if(MSeg -> MacroList)
  300.                     {
  301.                         for(i = 0 ; i < MSeg -> NumMacros ; i++)
  302.                         {
  303.                             if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  304.                                 continue;
  305.  
  306.                             if(MSeg -> MacroList[i] . mk_String)
  307.                                 FreeRem(MSeg -> MacroList[i] . mk_String);
  308.  
  309.                             if(MSeg -> MacroList[i] . mk_Window)
  310.                                 FreeRem(MSeg -> MacroList[i] . mk_Window);
  311.                         }
  312.  
  313.                         FreeRem(MSeg -> MacroList);
  314.                     }
  315.  
  316.                     MSeg -> NumMacros = MacroMsg -> mm_NumMacros;
  317.                     MSeg -> MacroList = MacroMsg -> mm_MacroList;
  318.                 }
  319.  
  320.                     /* Remove the message. */
  321.  
  322.                 DeleteMacroMsg(MacroMsg);
  323.             }
  324.         }
  325.     }
  326.  
  327. Quit:    ;
  328. }
  329.  
  330.     /* UStrCmp():
  331.      *
  332.      *    strcmp function which ignores case and allows to
  333.      *    abbreviate the name of the source string to match
  334.      *    against the destination string.
  335.      */
  336.  
  337. BYTE
  338. UStrCmp(UBYTE *a,UBYTE *b)
  339. {
  340.     SHORT i;
  341.  
  342.     for(i = 0 ; i < strlen(a) ; i++)
  343.         if(ToUpper(a[i]) != ToUpper(b[i]))
  344.             return(1);
  345.  
  346.     return(0);
  347. }
  348.  
  349.     /* CreateFuncProc():
  350.      *
  351.      *    Create an independent process from a 'C' routine.
  352.      */
  353.  
  354. struct Process *
  355. CreateFuncProc(char *Name,LONG Priority,APTR InitCode,ULONG StackSize)
  356. {
  357.     struct Process *ChildProc = NULL;
  358.  
  359.     struct FakeSeg
  360.     {
  361.         BPTR    NextSeg;
  362.  
  363.         WORD    FirstCode;
  364.         APTR    RealCode;
  365.     } *FakeSeg;
  366.  
  367.     if(FakeSeg = (struct FakeSeg *)AllocMem(sizeof(struct FakeSeg),MEMF_PUBLIC | MEMF_CLEAR))
  368.     {
  369.         struct MsgPort *ChildPort;
  370.  
  371.         FakeSeg -> FirstCode    = 0x4EF9;
  372.         FakeSeg -> RealCode    = InitCode;
  373.  
  374.         if(ChildPort = (struct MsgPort *)CreateProc(Name,Priority,MKBADDR(FakeSeg),StackSize))
  375.             ChildProc = (struct Process *)ChildPort -> mp_SigTask;
  376.  
  377.         Delay(TICKS_PER_SECOND);
  378.  
  379.         FreeMem(FakeSeg,sizeof(struct FakeSeg));
  380.     }
  381.  
  382.     return(ChildProc);
  383. }
  384.  
  385.     /* FreeString(Byte):
  386.      *
  387.      *    Frees the memory occupied by the contents of a BSTR.
  388.      */
  389.  
  390. VOID
  391. FreeString(BPTR Byte)
  392. {
  393.     LONG *Ptr = (LONG *)BADDR(Byte);
  394.  
  395.     FreeMem(Ptr - 1,Ptr[-1]);
  396. }
  397.  
  398.     /* CreateBSTR(s):
  399.      *
  400.      *    Allocates enough memory to hold the contents of
  401.      *    a given string and makes it a BSTR.
  402.      */
  403.  
  404. BPTR
  405. CreateBSTR(char *s)
  406. {
  407.     LONG     BlockLength;
  408.     SHORT     Length;
  409.     char    *Byte;
  410.  
  411.     Length = strlen(s);
  412.  
  413.     BlockLength = (Length + 8) & ~3;
  414.  
  415.     if(!(Byte = (char *)AllocMem(BlockLength,MEMF_PUBLIC | MEMF_CLEAR)))
  416.         return(NULL);
  417.  
  418.     *(LONG *)Byte = BlockLength;
  419.  
  420.     Byte[4] = Length;
  421.     strncpy(Byte + 5,s,Length);
  422.  
  423.     return(MKBADDR(Byte + 4));
  424. }
  425.  
  426.     /* CopyPath():
  427.      *
  428.      *    Builds a fake pathlist inherited from any valid
  429.      *    CLI process or Workbench.
  430.      */
  431.  
  432. BPTR
  433. CopyPath()
  434. {
  435.     BPTR                *Next1,*Next2,*Last,NewPath = NULL;
  436.     struct Process            *Father;
  437.     struct CommandLineInterface    *CLI;
  438.  
  439.     Last = &NewPath;
  440.  
  441.         /* If using ARP this will also give us a valid
  442.          * pathlist.
  443.          */
  444.  
  445.     if(!(Father = (struct Process *)FindTask("Workbench")))
  446.         if(!(Father = (struct Process *)FindTask("ARP Shell Process")))
  447.             if(!(Father = (struct Process *)FindTask("New CLI")))
  448.                 if(!(Father = (struct Process *)FindTask("Initial CLI")))
  449.                     return(NULL);
  450.  
  451.     if(CLI = (struct CommandLineInterface *)BADDR(Father -> pr_CLI))
  452.     {
  453.         for(Next1 = (BPTR *)BADDR(CLI -> cli_CommandDir) ; Next1 ; Next1 = (BPTR *)BADDR(*Next1))
  454.         {
  455.             if(!(Next2 = (BPTR *)AllocMem(2 * sizeof(BPTR),MEMF_PUBLIC | MEMF_CLEAR)))
  456.                 break;
  457.  
  458.             *Last = MKBADDR(Next2);
  459.              Last = Next2;
  460.  
  461.             Next2[1] = (BPTR)DupLock(Next1[1]);
  462.             Next2[0] = NULL;
  463.         }
  464.     }
  465.  
  466.     return(NewPath);
  467. }
  468.  
  469.     /* FakeCLI():
  470.      *
  471.      *    Creates a fake CLI structure for our process. This
  472.      *    includes pathlist, currentdir, prompt and stack.
  473.      */
  474.  
  475. VOID
  476. FakeCLI()
  477. {
  478.     struct Process            *MyProcess = (struct Process *)SysBase -> ThisTask;
  479.     struct CommandLineInterface    *CLI;
  480.  
  481.     if(CLI = (struct CommandLineInterface *)AllocMem(sizeof(struct CommandLineInterface),MEMF_PUBLIC | MEMF_CLEAR))
  482.     {
  483.         MyProcess -> pr_CLI = MKBADDR(CLI);
  484.  
  485.         CLI -> cli_SetName    = CreateBSTR("SYS:");
  486.         CLI -> cli_Prompt    = CreateBSTR("%N> ");
  487.         CLI -> cli_DefaultStack    = 4000;
  488.  
  489.         CurrentDir(Lock("SYS:",ACCESS_READ));
  490.  
  491.         CLI -> cli_CommandDir    = CopyPath();
  492.     }
  493. }
  494.  
  495.     /* ClearPath(InitPath):
  496.      *
  497.      *    Frees the contents of our fake pathlist.
  498.      */
  499.  
  500. VOID
  501. ClearPath(BPTR InitPath)
  502. {
  503.     BPTR *Next,*Path;
  504.  
  505.     for(Path = (BPTR *)BADDR(InitPath) ; Path ; Path = Next)
  506.     {
  507.         Next = (BPTR *)BADDR(Path[0]);
  508.  
  509.         if(Path[1])
  510.             UnLock(Path[1]);
  511.  
  512.         FreeMem(Path,2 * sizeof(BPTR));
  513.     }
  514. }
  515.  
  516.     /* StopFakery():
  517.      *
  518.      *    Removes the contents of our fake CLI structure.
  519.      */
  520.  
  521. VOID
  522. StopFakery()
  523. {
  524.     struct CommandLineInterface    *CLI;
  525.     struct Process            *MyProcess;
  526.     BPTR                 MyCD;
  527.  
  528.     MyProcess = (struct Process *)SysBase -> ThisTask;
  529.  
  530.     if(CLI = (struct CommandLineInterface *)BADDR(MyProcess -> pr_CLI))
  531.     {
  532.         if(MyCD = (BPTR)CurrentDir(NULL))
  533.             UnLock(MyCD);
  534.  
  535.         FreeString(CLI -> cli_SetName);
  536.         FreeString(CLI -> cli_Prompt);
  537.  
  538.         ClearPath(CLI -> cli_CommandDir);
  539.  
  540.         MyProcess -> pr_CLI = NULL;
  541.  
  542.         FreeMem(CLI,sizeof(struct CommandLineInterface));
  543.     }
  544. }
  545.  
  546.     /* DeleteMacroMsg(scm_Msg):
  547.      *
  548.      *    Remove a message from memory.
  549.      */
  550.  
  551. VOID *
  552. DeleteMacroMsg(struct MacroMessage *scm_Msg)
  553. {
  554.     if(scm_Msg && scm_Msg -> mm_Message . mn_Node . ln_Name == (char *)scm_Msg)
  555.         FreeRem(scm_Msg);
  556.  
  557.     return(NULL);
  558. }
  559.  
  560.     /* Executor():
  561.      *
  562.      *    This is the dummy process to execute programs.
  563.      */
  564.  
  565. VOID
  566. Executor()
  567. {
  568.     ULONG             SignalSet;
  569.     BPTR             NIL;
  570.     struct MacroMessage    *ExecuteMsg;
  571.     struct Window        *TheWindow;
  572.     char             TempLine[300];
  573.  
  574.     struct Process        *ThatsMe;
  575.  
  576.     BYTE             Activate;
  577.  
  578.     geta4();
  579.  
  580.     ThatsMe = (struct Process *)SysBase -> ThisTask;
  581.  
  582.         /* These are inherited from the father process,
  583.          * we had better cleared them out.
  584.          */
  585.  
  586.     ThatsMe -> pr_WindowPtr = (APTR)-1;
  587.  
  588.         /* Try to allocate a port (we can't use our builtin
  589.          * DOS port since we are actually calling DOS
  590.          * routines which may mix up the messages coming
  591.          * in).
  592.          */
  593.  
  594.     if(!(ExecutePort = (struct MsgPort *)CreatePort(NULL,0)))
  595.     {
  596.         Forbid();
  597.  
  598.         ExecuteProc = NULL;
  599.  
  600.         Signal(MSeg -> Child,SIG_SHAKE);
  601.  
  602.         goto Quit;
  603.     }
  604.  
  605.         /* Open the NULL-Handler. */
  606.  
  607.     if(!(NIL = Open("NULL:",MODE_NEWFILE)))
  608.     {
  609.         Forbid();
  610.  
  611.         ExecuteProc = NULL;
  612.  
  613.         Signal(MSeg -> Child,SIG_SHAKE);
  614.         DeletePort(ExecutePort);
  615.  
  616.         goto Quit;
  617.     }
  618.  
  619.         /* Pretend to be a CLI. */
  620.  
  621.     FakeCLI();
  622.  
  623.         /* This path leads nowhere. */
  624.  
  625.     ThatsMe -> pr_CIS        = NIL;
  626.     ThatsMe -> pr_COS        = NIL;
  627.  
  628.     ThatsMe -> pr_ConsoleTask    = (APTR)DeviceProc("NULL:");
  629.  
  630.         /* We're on the scene now. */
  631.  
  632.     Signal(MSeg -> Child,SIG_SHAKE);
  633.  
  634.     FOREVER
  635.     {
  636.         SignalSet = Wait(SIG_CLOSE | (1 << ExecutePort -> mp_SigBit));
  637.  
  638.             /* Shut down? */
  639.  
  640.         if(SignalSet & SIG_CLOSE)
  641.         {
  642.             StopFakery();
  643.             Close(NIL);
  644.             DeletePort(ExecutePort);
  645.  
  646.             ExecuteProc = NULL;
  647.  
  648.             Forbid();
  649.  
  650.             Signal(MSeg -> Child,SIG_SHAKE);
  651.  
  652.             goto Quit;
  653.         }
  654.  
  655.             /* Execute a command? */
  656.  
  657.         while(ExecuteMsg = (struct MacroMessage *)GetMsg(ExecutePort))
  658.         {
  659.             TheWindow    = NULL;
  660.             Activate    = TRUE;
  661.  
  662.                 /* Try to find a matching window title. */
  663.  
  664.             if(ExecuteMsg -> mm_WindowName)
  665.             {
  666.                 ULONG         IntuiLock;
  667.  
  668.                 struct Screen    *ExScreen;
  669.                 struct Window    *ExWindow;
  670.  
  671.                 IntuiLock = LockIBase(NULL);
  672.  
  673.                 if(UStrCmp(ExecuteMsg -> mm_WindowName,IntuitionBase -> ActiveWindow -> Title))
  674.                 {
  675.                     ExScreen = IntuitionBase -> FirstScreen;
  676.  
  677.                     do
  678.                     {
  679.                         ExWindow = ExScreen -> FirstWindow;
  680.  
  681.                         do
  682.                         {
  683.                             if(!UStrCmp(ExecuteMsg -> mm_WindowName,ExWindow -> Title))
  684.                             {
  685.                                 TheWindow = ExWindow;
  686.                                 break;
  687.                             }
  688.                         }
  689.                         while((ExWindow = ExWindow -> NextWindow) && !TheWindow);
  690.                     }
  691.                     while((ExScreen = ExScreen -> NextScreen) && !TheWindow);
  692.                 }
  693.                 else
  694.                 {
  695.                     TheWindow = IntuitionBase -> ActiveWindow;
  696.                     Activate = FALSE;
  697.                 }
  698.  
  699.                 UnlockIBase(IntuiLock);
  700.             }
  701.  
  702.             if(!TheWindow)
  703.             {
  704.                     /* No chance, execute the command. */
  705.  
  706.                 strcpy(TempLine,"C:Run <NULL: >NULL: ");
  707.                 strcat(TempLine,ExecuteMsg -> mm_FileName);
  708.  
  709.                 Execute(TempLine,NULL,NIL);
  710.             }
  711.  
  712.             DeleteMacroMsg(ExecuteMsg);
  713.  
  714.                 /* Found a window? Bring it to the front. */
  715.  
  716.             if(TheWindow)
  717.             {
  718.                 LockLayers(TheWindow -> RPort -> Layer -> LayerInfo);
  719.  
  720.                 WindowToFront(TheWindow);
  721.  
  722.                 UnlockLayers(TheWindow -> RPort -> Layer -> LayerInfo);
  723.  
  724.                 ScreenToFront(TheWindow -> WScreen);
  725.  
  726.                 if(Activate)
  727.                     ActivateWindow(TheWindow);
  728.             }
  729.         }
  730.     }
  731.  
  732.         /* Finished, fall through. */
  733.  
  734. Quit:    ;
  735. }
  736.  
  737.     /* FindMacroKey(Code,Qualifier):
  738.      *
  739.      *    Find a macro key entry in the linked list of
  740.      *    macro key structures.
  741.      */
  742.  
  743. struct MacroKey *
  744. FindMacroKey(LONG Code,LONG Qualifier)
  745. {
  746.     SHORT i;
  747.  
  748.     if(MSeg -> MacroList)
  749.     {
  750.         for(i = 0 ; i < MSeg -> NumMacros ; i++)
  751.         {
  752.             if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  753.                 continue;
  754.  
  755.             if(MSeg -> MacroList[i] . mk_CommandKey == Code && (Qualifier & MSeg -> MacroList[i] . mk_CommandQualifier) == MSeg -> MacroList[i] . mk_CommandQualifier)
  756.                 return(&MSeg -> MacroList[i]);
  757.         }
  758.     }
  759.  
  760.     return(NULL);
  761. }
  762.  
  763.     /* EventHandler(Event):
  764.      *
  765.      *    The input event handler.
  766.      */
  767.  
  768. struct InputEvent *
  769. EventHandler(struct InputEvent *Event)
  770. {
  771.     struct MacroKey        *HandlerKey;
  772.     struct InputEvent    *ChainEvent;
  773.  
  774.         /* This is an interrupt, let's start with the register
  775.          * saving.
  776.          */
  777.  
  778.     int_start();
  779.  
  780.     for(ChainEvent = Event ; ChainEvent ; ChainEvent = ChainEvent -> ie_NextEvent)
  781.     {
  782.         if(ChainEvent -> ie_Class == IECLASS_RAWKEY && !(ChainEvent -> ie_Code & IECODE_UP_PREFIX) && ChainEvent -> ie_SubClass != KM_SUBCLASS)
  783.         {
  784.             if(HandlerKey = (struct MacroKey *)FindMacroKey(ChainEvent -> ie_Code,ChainEvent -> ie_Qualifier))
  785.             {
  786.                 struct MacroMessage HandlerMsg;
  787.  
  788.                 HandlerMsg . mm_Type        = MM_INPUT;
  789.                 HandlerMsg . mm_MacroKey    = HandlerKey;
  790.  
  791.                 SendMacroMsg(&HandlerMsg,&MSeg -> Port);
  792.  
  793.                 ChainEvent -> ie_Class = IECLASS_NULL;
  794.             }
  795.         }
  796.     }
  797.  
  798.         /* Restore the registers. */
  799.  
  800.     int_end();
  801.  
  802.     return(Event);
  803. }
  804.  
  805.     /* OpenAll():
  806.      *
  807.      *    Initialize the input event handler.
  808.      */
  809.  
  810. BYTE
  811. OpenAll()
  812. {
  813.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",33)))
  814.         return(FALSE);
  815.  
  816.     if(!(LayersBase = (struct Library *)OpenLibrary("layers.library",33)))
  817.         return(FALSE);
  818.  
  819.     if(!(InputDevPort = (struct MsgPort *)CreatePort(NULL,0)))
  820.         return(FALSE);
  821.  
  822.     if(!(InputRequestBlock = (struct IOStdReq *)CreateStdIO(InputDevPort)))
  823.         return(FALSE);
  824.  
  825.     if(OpenDevice("input.device",0,(struct IORequest *)InputRequestBlock,0))
  826.         return(FALSE);
  827.  
  828.     if(!(InputHandler = (struct Interrupt *)AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC | MEMF_CLEAR)))
  829.         return(FALSE);
  830.  
  831.     if(!(ConsolePort = (struct MsgPort *)CreatePort(NULL,0)))
  832.         return(FALSE);
  833.  
  834.     if(!(ConsoleRequest = (struct IOStdReq *)CreateStdIO(ConsolePort)))
  835.         return(FALSE);
  836.  
  837.     if(OpenDevice("console.device",CONU_LIBRARY,ConsoleRequest,0))
  838.         return(FALSE);
  839.  
  840.     if(!(TimePort = (struct MsgPort *)CreatePort(NULL,0)))
  841.         return(FALSE);
  842.  
  843.     if(!(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest))))
  844.         return(FALSE);
  845.  
  846.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
  847.         return(FALSE);
  848.  
  849.     TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  850.  
  851.     if(!(FakeInputEvent = (struct InputEvent *)AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC | MEMF_CLEAR)))
  852.         return(FALSE);
  853.  
  854.     if((SigBit = AllocSignal(-1)) == -1)
  855.         return(FALSE);
  856.  
  857.     InputHandler -> is_Code            = (APTR)EventHandler;
  858.     InputHandler -> is_Node . ln_Pri    = 51;
  859.     InputHandler -> is_Node . ln_Name    = "KeyMacro-Handler";
  860.  
  861.     InputRequestBlock -> io_Command        = IND_ADDHANDLER;
  862.     InputRequestBlock -> io_Data        = (APTR)InputHandler;
  863.  
  864.     if(DoIO(InputRequestBlock))
  865.         return(FALSE);
  866.  
  867.     ConsoleRequest -> io_Command    = CD_ASKDEFAULTKEYMAP;
  868.     ConsoleRequest -> io_Length    = sizeof(struct KeyMap);
  869.     ConsoleRequest -> io_Data    = (APTR)MSeg -> DefaultKeyMap;
  870.     ConsoleRequest -> io_Flags    = IOF_QUICK;
  871.  
  872.     if(DoIO(ConsoleRequest))
  873.         return(FALSE);
  874.  
  875.     return(TRUE);
  876. }
  877.  
  878.     /* CloseAll():
  879.      *
  880.      *    Remove the input event handler.
  881.      */
  882.  
  883. VOID
  884. CloseAll()
  885. {
  886.     if(InputRequestBlock)
  887.     {
  888.         if(InputRequestBlock -> io_Device)
  889.         {
  890.             if(InputHandler)
  891.             {
  892.                 InputRequestBlock -> io_Command    = IND_REMHANDLER;
  893.                 InputRequestBlock -> io_Data    = (APTR)InputHandler;
  894.  
  895.                 DoIO(InputRequestBlock);
  896.             }
  897.  
  898.             CloseDevice(InputRequestBlock);
  899.         }
  900.  
  901.         DeleteStdIO(InputRequestBlock);
  902.     }
  903.  
  904.     if(TimeRequest)
  905.     {
  906.         if(TimeRequest -> tr_node . io_Device)
  907.             CloseDevice(TimeRequest);
  908.  
  909.         DeleteExtIO(TimeRequest);
  910.     }
  911.  
  912.     if(TimePort)
  913.         DeletePort(TimePort);
  914.  
  915.     if(ConsoleRequest)
  916.     {
  917.         if(ConsoleRequest -> io_Device)
  918.             CloseDevice(ConsoleRequest);
  919.  
  920.         DeleteStdIO(ConsoleRequest);
  921.     }
  922.  
  923.     if(FakeInputEvent)
  924.         FreeMem(FakeInputEvent,sizeof(struct InputEvent));
  925.  
  926.     if(InputHandler)
  927.         FreeMem(InputHandler,sizeof(struct Interrupt));
  928.  
  929.     if(InputDevPort)
  930.         DeletePort(InputDevPort);
  931.  
  932.     if(ConsolePort)
  933.         DeletePort(ConsolePort);
  934.  
  935.     if(SigBit != -1)
  936.         FreeSignal(SigBit);
  937.  
  938.     if(LayersBase)
  939.         CloseLibrary(LayersBase);
  940.  
  941.     if(IntuitionBase)
  942.         CloseLibrary(IntuitionBase);
  943. }
  944.