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 / KeyMacro.c < prev    next >
C/C++ Source or Header  |  1990-11-01  |  28KB  |  1,374 lines

  1. /****************************************************************************
  2. *
  3. *    KeyMacro.c ------------    KeyMacro main process.
  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.     /* Buffered IO include. */
  17.  
  18. #include "MRArpFile.h"
  19.  
  20.     /* Function prototypes. */
  21.  
  22. VOID            CalcDimensions(UBYTE *cd_String,LONG *cd_Width,LONG *cd_Height,LONG cd_MaxWidth);
  23. LONG            MovePointer(struct Screen *mp_Screen,LONG mp_Button,LONG mp_X,LONG mp_Y);
  24. LONG            WriteConsole(struct Window *wc_Window,UBYTE *wc_String);
  25. VOID            EraseGadget(struct RastPort *RPort,struct Gadget *Gadget,LONG Colour);
  26. BYTE            PopRequest(struct Window *pr_ParentWindow,UBYTE *pr_TitleText,UBYTE *pr_BodyText,UBYTE *pr_PosText,UBYTE *pr_NegText,LONG pr_Default);
  27.  
  28. UBYTE *            GetToken(UBYTE *s,LONG *start);
  29. struct MacroKey *    AddMacroKey(struct MacroKey *MacroKey);
  30. BYTE            Interprete(UBYTE *String,LONG Line);
  31. BYTE            UpdateList(char *Name);
  32. BYTE            GetDefaultKeyMap(VOID);
  33. BYTE            UStrCmp(UBYTE *a,UBYTE *b);
  34.  
  35. VOID *            SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port);
  36. VOID *            AllocRem(LONG ByteSize,LONG Requirements);
  37. VOID *            FreeRem(LONG *MemoryBlock);
  38. ULONG            InvertKeyMap(ULONG ansicode,struct InputEvent *ie,struct KeyMap *km);
  39.  
  40. VOID            main(int argc,char **argv);
  41.  
  42.     /* The Arp CLI-Interface data. */
  43.  
  44. char *CLI_Template    = "Startup,Q=Quit/s,I=Info/s";
  45. char *CLI_Help        = "\nUsage: \33[1mKeyMacro\33[0m <Startup File> [Quit] [Info]\n";
  46.  
  47. #define ARG_STARTUP    1
  48. #define ARG_QUIT    2
  49. #define ARG_INFO    3
  50. #define ARG_UPDATE    4
  51.  
  52.     /* Easy macro. */
  53.  
  54. #define From_CLI    (ThatsMe -> pr_CLI)
  55.  
  56.     /* Global and shared data structures. */
  57.  
  58. extern struct ExecBase        *SysBase;
  59. extern struct IntuitionBase    *IntuitionBase;
  60. struct MSeg            *MSeg;
  61. struct MacroKey            *KeyList;
  62.  
  63.     /* We use this list to identify the non-ascii keys. */
  64.  
  65. struct KeyAlias KeyTab[22] =
  66. {
  67.     {"TAB",        0x42},
  68.     {"ESC",        0x45},
  69.     {"SPACE",    0x40},
  70.     {"RETURN",    0x44},
  71.     {"ENTER",    0x43},
  72.     {"DEL",        0x46},
  73.     {"BACKSPACE",    0x41},
  74.     {"HELP",    0x5F},
  75.     {"LEFT",    0x4F},
  76.     {"RIGHT",    0x4E},
  77.     {"UP",        0x4C},
  78.     {"DOWN",    0x4D},
  79.  
  80.     {"F1",        0x50},
  81.     {"F2",        0x51},
  82.     {"F3",        0x52},
  83.     {"F4",        0x53},
  84.     {"F5",        0x54},
  85.     {"F6",        0x55},
  86.     {"F7",        0x56},
  87.     {"F8",        0x57},
  88.     {"F9",        0x58},
  89.     {"F10",        0x59}
  90. };
  91.  
  92.     /* These are the qualifiers. */
  93.  
  94. struct KeyAlias QualifierTab[9] =
  95. {
  96.     {"NONE",    0},
  97.     {"CTRL",    IEQUALIFIER_CONTROL},
  98.     {"NUMPAD",    IEQUALIFIER_NUMERICPAD},
  99.     {"LSHIFT",    IEQUALIFIER_LSHIFT},
  100.     {"RSHIFT",    IEQUALIFIER_RSHIFT},
  101.     {"LALT",    IEQUALIFIER_LALT},
  102.     {"RALT",    IEQUALIFIER_RALT},
  103.     {"LAMIGA",    IEQUALIFIER_LCOMMAND},
  104.     {"RAMIGA",    IEQUALIFIER_RCOMMAND}
  105. };
  106.  
  107.     /* Our current version tag. */
  108.  
  109. const char *VersionTag = "$VER: KeyMacro 1.6 (09 Sep 1990)\n\r";
  110.  
  111.     /* UStrCmp():
  112.      *
  113.      *    strcmp function which ignores case.
  114.      */
  115.  
  116. BYTE
  117. UStrCmp(UBYTE *a,UBYTE *b)
  118. {
  119.     for( ; ToUpper(*a) == ToUpper(*b) ; a++, b++)
  120.     {
  121.         if(!(*a))
  122.             return(0);
  123.     }
  124.  
  125.     return(1);
  126. }
  127.  
  128.     /* CalcDimensions():
  129.      *
  130.      *    Calculate width and height for text string.
  131.      */
  132.  
  133. VOID
  134. CalcDimensions(UBYTE *cd_String,LONG *cd_Width,LONG *cd_Height,LONG cd_MaxWidth)
  135. {
  136.     LONG i,cd_InLine = 0,cd_NumLines = 0;
  137.  
  138.     *cd_Width = *cd_Height = 0;
  139.  
  140.     for(i = 0 ; i < strlen(cd_String) ; i++)
  141.     {
  142.         if(cd_String[i] == '\n' || cd_InLine == cd_MaxWidth)
  143.         {
  144.             if(cd_InLine > *cd_Width)
  145.                 *cd_Width = cd_InLine;
  146.  
  147.             cd_NumLines++;
  148.             cd_InLine = 0;
  149.  
  150.             continue;
  151.         }
  152.  
  153.         if(cd_String[i] == '\33')
  154.         {
  155.             while(cd_String[i] != 'm' && cd_String[i] != 'w' && i < strlen(cd_String))
  156.                 i++;
  157.  
  158.             if(i >= strlen(cd_String))
  159.                 i = strlen(cd_String) - 1;
  160.  
  161.             continue;
  162.         }
  163.  
  164.         if(cd_String[i] < ' ')
  165.             continue;
  166.  
  167.         cd_InLine++;
  168.     }
  169.  
  170.     *cd_Height = cd_NumLines;
  171.  
  172.     if(cd_InLine > *cd_Width)
  173.         *cd_Width = cd_InLine;
  174. }
  175.  
  176.     /* MovePointer():
  177.      *
  178.      *    Move the mouse pointer to a given position on a
  179.      *    screen.
  180.      */
  181.  
  182. LONG
  183. MovePointer(struct Screen *mp_Screen,LONG mp_Button,LONG mp_X,LONG mp_Y)
  184. {
  185.     STATIC struct InputEvent mp_StaticEvent =
  186.     {
  187.         NULL,
  188.         IECLASS_POINTERPOS,
  189.         0,
  190.         IECODE_NOBUTTON,
  191.         0,0,0,0
  192.     };
  193.  
  194.     struct MsgPort        *mp_InputPort;
  195.     struct IOStdReq        *mp_InputRequest;
  196.     struct InputEvent    *mp_FakeEvent;
  197.  
  198.     LONG mp_Success = FALSE;
  199.  
  200.     if(mp_InputPort = (struct MsgPort *)CreatePort(NULL,0))
  201.     {
  202.         if(mp_InputRequest = (struct IOStdReq *)CreateStdIO(mp_InputPort))
  203.         {
  204.             if(!OpenDevice("input.device",0,mp_InputRequest,0))
  205.             {
  206.                 if(mp_FakeEvent = (struct InputEvent *)AllocPub(sizeof(struct InputEvent)))
  207.                 {
  208.                     CopyMem(&mp_StaticEvent,mp_FakeEvent,sizeof(struct InputEvent));
  209.  
  210.                     mp_InputRequest -> io_Command    = IND_WRITEEVENT;
  211.                     mp_InputRequest -> io_Flags    = 0;
  212.                     mp_InputRequest -> io_Length    = sizeof(struct InputEvent);
  213.                     mp_InputRequest -> io_Data    = (APTR)mp_FakeEvent;
  214.  
  215.                     mp_FakeEvent -> ie_X = mp_X;
  216.                     mp_FakeEvent -> ie_Y = mp_Y;
  217.  
  218.                     if(!(mp_Screen -> ViewPort . Modes & HIRES))
  219.                         mp_FakeEvent -> ie_X *= 2;
  220.  
  221.                     if(!(mp_Screen -> ViewPort . Modes & LACE))
  222.                         mp_FakeEvent -> ie_Y *= 2;
  223.  
  224.                     mp_FakeEvent -> ie_Y += (2 * mp_Screen -> TopEdge);
  225.  
  226.                     if(mp_Button)
  227.                         mp_FakeEvent -> ie_Code = IECODE_LBUTTON;
  228.  
  229.                     DoIO(mp_InputRequest);
  230.  
  231.                     if(mp_Button)
  232.                     {
  233.                         mp_FakeEvent -> ie_Code = IECODE_LBUTTON | IECODE_UP_PREFIX;
  234.                         DoIO(mp_InputRequest);
  235.                     }
  236.  
  237.                     mp_Success = TRUE;
  238.  
  239.                     FreeRem(mp_FakeEvent);
  240.                 }
  241.  
  242.                 CloseDevice(mp_InputRequest);
  243.             }
  244.  
  245.             DeleteStdIO(mp_InputRequest);
  246.         }
  247.  
  248.         DeletePort(mp_InputPort);
  249.     }
  250.  
  251.     return(mp_Success);
  252. }
  253.  
  254.     /* WriteConsole():
  255.      *
  256.      *    Write a string to a window using the console.device.
  257.      */
  258.  
  259. LONG
  260. WriteConsole(struct Window *wc_Window,UBYTE *wc_String)
  261. {
  262.     struct IOStdReq    *wc_ConWrite;
  263.     struct MsgPort    *wc_ConPort;
  264.  
  265.     LONG wc_Success = FALSE;
  266.  
  267.     if(wc_ConPort = (struct MsgPort *)CreatePort(NULL,0))
  268.     {
  269.         if(wc_ConWrite = (struct IOStdReq *)CreateStdIO(wc_ConPort))
  270.         {
  271.             wc_ConWrite -> io_Data        = (APTR)wc_Window;
  272.             wc_ConWrite -> io_Length    = sizeof(struct Window);
  273.  
  274.             if(!OpenDevice("console.device",0,wc_ConWrite,0))
  275.             {
  276.                 wc_ConWrite -> io_Command    = CMD_WRITE;
  277.                 wc_ConWrite -> io_Data        = (APTR)"\2330 p";
  278.                 wc_ConWrite -> io_Length    = -1;
  279.  
  280.                 DoIO(wc_ConWrite);
  281.  
  282.                 wc_ConWrite -> io_Data        = (APTR)wc_String;
  283.                 wc_ConWrite -> io_Length    = -1;
  284.  
  285.                 DoIO(wc_ConWrite);
  286.  
  287.                 wc_Success = TRUE;
  288.  
  289.                 CloseDevice(wc_ConWrite);
  290.             }
  291.  
  292.             DeleteStdIO(wc_ConWrite);
  293.         }
  294.  
  295.         DeletePort(wc_ConPort);
  296.     }
  297.  
  298.     return(wc_Success);
  299. }
  300.  
  301.     /* EraseGadget():
  302.      *
  303.      *    Erase the background of a gadget.
  304.      */
  305.  
  306. VOID
  307. EraseGadget(struct RastPort *RPort,struct Gadget *Gadget,LONG Colour)
  308. {
  309.     BYTE FgPen = RPort -> FgPen;
  310.  
  311.     SetAPen(RPort,Colour);
  312.     RectFill(RPort,Gadget -> LeftEdge,Gadget -> TopEdge,Gadget -> LeftEdge + Gadget -> Width - 1,Gadget -> TopEdge + Gadget -> Height - 1);
  313.     SetAPen(RPort,FgPen);
  314. }
  315.  
  316.     /* PopRequest():
  317.      *
  318.      *    Display a pop-up requester.
  319.      */
  320.  
  321. BYTE
  322. PopRequest(struct Window *pr_ParentWindow,UBYTE *pr_TitleText,UBYTE *pr_BodyText,UBYTE *pr_PosText,UBYTE *pr_NegText,LONG pr_Default)
  323. {
  324.     STATIC struct NewWindow pr_StaticNewWindow =
  325.     {
  326.         0,0,
  327.         0,1,
  328.         0,1,
  329.         VANILLAKEY | MOUSEBUTTONS | GADGETUP | CLOSEWINDOW,
  330.         RMBTRAP | WINDOWDRAG | WINDOWDEPTH,
  331.         (struct Gadget *)NULL,
  332.         (struct Image *)NULL,
  333.         (STRPTR)NULL,
  334.         (struct Screen *)NULL,
  335.         (struct BitMap *)NULL,
  336.         0,0,
  337.         0,0,
  338.         WBENCHSCREEN
  339.     };
  340.  
  341.     STATIC struct Gadget pr_StaticGadget =
  342.     {
  343.         (struct Gadget *)NULL,
  344.         0,0,
  345.         0,0,
  346.         GADGHBOX,
  347.         RELVERIFY | GADGIMMEDIATE,
  348.         BOOLGADGET,
  349.         (APTR)NULL,
  350.         (APTR)NULL,
  351.         (struct IntuiText *)NULL,
  352.         NULL,
  353.         (APTR)NULL,
  354.         0,
  355.         (APTR)NULL
  356.     };
  357.  
  358.     STATIC struct TextAttr pr_TextAttr =
  359.     {
  360.         (UBYTE *)"topaz.font",
  361.         8,
  362.         FS_NORMAL,
  363.         FPF_ROMFONT
  364.     };
  365.  
  366.     struct NewWindow    *pr_NewWindow;
  367.     struct Window        *pr_Window;
  368.     struct IntuiMessage    *pr_IMsg;
  369.     struct Gadget        *pr_PosGadget = NULL,*pr_NegGadget = NULL,*pr_TempGadget;
  370.  
  371.     struct Screen         pr_Screen,*pr_FrontScreen;
  372.     struct TextFont        *pr_TextFont;
  373.  
  374.     LONG             pr_Width,pr_Height;
  375.     LONG             pr_Result = FALSE;
  376.  
  377.     LONG             pr_TickCount = 0;
  378.     ULONG             pr_IntuiLock;
  379.  
  380.     if(!pr_BodyText)
  381.         return(pr_Result);
  382.  
  383.     if(!(pr_NewWindow = (struct NewWindow *)AllocRem(sizeof(struct NewWindow),MEMF_PUBLIC)))
  384.         return(pr_Result);
  385.  
  386.     CopyMem(&pr_StaticNewWindow,pr_NewWindow,sizeof(struct NewWindow));
  387.  
  388.     pr_IntuiLock = LockIBase(NULL);
  389.  
  390.     pr_FrontScreen = IntuitionBase -> FirstScreen;
  391.  
  392.     UnlockIBase(pr_IntuiLock);
  393.  
  394.     if(pr_ParentWindow)
  395.     {
  396.         pr_NewWindow -> Type    = CUSTOMSCREEN;
  397.         pr_NewWindow -> Screen    = pr_ParentWindow -> WScreen;
  398.     }
  399.     else
  400.         OpenWorkBench();
  401.  
  402.     if(!GetScreenData(&pr_Screen,sizeof(struct Screen),pr_NewWindow -> Type,pr_NewWindow -> Screen))
  403.     {
  404.         FreeRem(pr_NewWindow);
  405.         return(pr_Result);
  406.     }
  407.  
  408.     CalcDimensions(pr_BodyText,&pr_Width,&pr_Height,(pr_Screen . Width - 6) / 8);
  409.  
  410.     if(pr_Height > (pr_Screen . Height - 15 - 13) / 8)
  411.     {
  412.         FreeRem(pr_NewWindow);
  413.         return(pr_Result);
  414.     }
  415.  
  416.     pr_NewWindow -> Width    = pr_Width * 8 + 6 + 4;
  417.     pr_NewWindow -> Height    = pr_Height * 8 + 15 + 19 + 2;
  418.  
  419.     if(pr_TitleText)
  420.         pr_NewWindow -> Title = pr_TitleText;
  421.     else
  422.         pr_NewWindow -> Title = (UBYTE *)"System Request";
  423.  
  424.     if(!pr_PosText && !pr_NegText)
  425.         pr_NegText = (UBYTE *)"Okay";
  426.  
  427.     if(pr_PosText)
  428.     {
  429.         if(!(pr_PosGadget = (struct Gadget *)AllocRem(sizeof(struct Gadget),MEMF_PUBLIC)))
  430.         {
  431.             FreeRem(pr_NewWindow);
  432.             return(pr_Result);
  433.         }
  434.  
  435.         CopyMem(&pr_StaticGadget,pr_PosGadget,sizeof(struct Gadget));
  436.  
  437.         pr_PosGadget -> Width    = 8 * strlen(pr_PosText) + 4;
  438.         pr_PosGadget -> Height    = 8 + 2;
  439.  
  440.         pr_PosGadget -> LeftEdge= 3 + 2 + 3;
  441.         pr_PosGadget -> TopEdge    = pr_NewWindow -> Height - 13 - 1;
  442.     }
  443.  
  444.     if(pr_NegText)
  445.     {
  446.         if(!(pr_NegGadget = (struct Gadget *)AllocRem(sizeof(struct Gadget),MEMF_PUBLIC)))
  447.         {
  448.             FreeRem(pr_NewWindow);
  449.  
  450.             if(pr_PosGadget)
  451.                 FreeRem(pr_PosGadget);
  452.  
  453.             return(pr_Result);
  454.         }
  455.  
  456.         CopyMem(&pr_StaticGadget,pr_NegGadget,sizeof(struct Gadget));
  457.  
  458.         pr_NegGadget -> Width    = 8 * strlen(pr_NegText) + 4;
  459.         pr_NegGadget -> Height    = 8 + 2;
  460.  
  461.         pr_Width = pr_NegGadget -> Width + 6 + 4 + 6;
  462.  
  463.         if(pr_PosGadget)
  464.             pr_Width += (pr_PosGadget -> Width + 12);
  465.  
  466.         if(pr_NewWindow -> Width < pr_Width)
  467.             pr_NewWindow -> Width = pr_Width;
  468.  
  469.         pr_NegGadget -> LeftEdge= pr_NewWindow -> Width - pr_NegGadget -> Width - 3 - 2 - 3;
  470.         pr_NegGadget -> TopEdge    = pr_NewWindow -> Height - 13 - 1;
  471.  
  472.         pr_NegGadget -> GadgetID= 1;
  473.     }
  474.  
  475.     if(!pr_NegGadget && pr_NewWindow -> Width < pr_PosGadget -> Width + 6 + 4 + 6)
  476.         pr_NewWindow -> Width = pr_PosGadget -> Width + 6 + 4 + 6;
  477.  
  478.     if(pr_Default && !pr_PosGadget)
  479.         pr_Default = FALSE;
  480.  
  481.     if(!pr_Default && !pr_NegGadget)
  482.         pr_Default = TRUE;
  483.  
  484.     if(pr_Default)
  485.         pr_TempGadget = pr_PosGadget;
  486.     else
  487.         pr_TempGadget = pr_NegGadget;
  488.  
  489.     pr_NewWindow -> LeftEdge= pr_Screen . MouseX - (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2);
  490.     pr_NewWindow -> TopEdge    = pr_Screen . MouseY - (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2);
  491.  
  492.     while(pr_NewWindow -> LeftEdge < 0)
  493.         pr_NewWindow -> LeftEdge++;
  494.  
  495.     while(pr_NewWindow -> TopEdge < 0)
  496.         pr_NewWindow -> TopEdge++;
  497.  
  498.     while(pr_NewWindow -> LeftEdge + pr_NewWindow -> Width >= pr_Screen . Width)
  499.         pr_NewWindow -> LeftEdge--;
  500.  
  501.     while(pr_NewWindow -> TopEdge + pr_NewWindow -> Height >= pr_Screen . Height)
  502.         pr_NewWindow -> TopEdge--;
  503.  
  504.     if(!(pr_TextFont = (struct TextFont *)OpenFont(&pr_TextAttr)))
  505.     {
  506.         if(pr_PosGadget)
  507.             FreeRem(pr_PosGadget);
  508.  
  509.         if(pr_NegGadget)
  510.             FreeRem(pr_NegGadget);
  511.  
  512.         FreeRem(pr_NewWindow);
  513.  
  514.         return(pr_Result);
  515.     }
  516.  
  517.     if(!(pr_Window = (struct Window *)OpenWindow(pr_NewWindow)))
  518.     {
  519.         CloseFont(pr_TextFont);
  520.  
  521.         if(pr_PosGadget)
  522.             FreeRem(pr_PosGadget);
  523.  
  524.         if(pr_NegGadget)
  525.             FreeRem(pr_NegGadget);
  526.  
  527.         FreeRem(pr_NewWindow);
  528.  
  529.         return(pr_Result);
  530.     }
  531.  
  532.     SetFont(pr_Window -> RPort,pr_TextFont);
  533.  
  534.     WriteConsole(pr_Window,pr_BodyText);
  535.  
  536.     if(pr_PosGadget)
  537.     {
  538.         AddGadget(pr_Window,pr_PosGadget,1);
  539.  
  540.         EraseGadget(pr_Window -> RPort,pr_PosGadget,2);
  541.  
  542.         Move(pr_Window -> RPort,pr_PosGadget -> LeftEdge + 2,pr_PosGadget -> TopEdge + 1 + pr_TextFont -> tf_Baseline);
  543.         Text(pr_Window -> RPort,pr_PosText,strlen(pr_PosText));
  544.     }
  545.  
  546.     if(pr_NegGadget)
  547.     {
  548.         AddGadget(pr_Window,pr_NegGadget,1);
  549.  
  550.         EraseGadget(pr_Window -> RPort,pr_NegGadget,2);
  551.  
  552.         Move(pr_Window -> RPort,pr_NegGadget -> LeftEdge + 2,pr_NegGadget -> TopEdge + 1 + pr_TextFont -> tf_Baseline);
  553.         Text(pr_Window -> RPort,pr_NegText,strlen(pr_NegText));
  554.     }
  555.  
  556.     MoveScreen(pr_Window -> WScreen,0,- pr_Window -> WScreen -> TopEdge);
  557.     ScreenToFront(pr_Window -> WScreen);
  558.     ActivateWindow(pr_Window);
  559.  
  560.     MovePointer(pr_Window -> WScreen,FALSE,
  561.         pr_Window -> LeftEdge + (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2),
  562.         pr_Window -> TopEdge + (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2));
  563.  
  564. Skip1:    FOREVER
  565.     {
  566.         ULONG pr_Class,pr_Code;
  567.         struct Gadget *pr_Gadget;
  568.  
  569.         WaitPort(pr_Window -> UserPort);
  570.  
  571.         if(pr_IMsg = (struct IntuiMessage *)GetMsg(pr_Window -> UserPort))
  572.         {
  573.             pr_Class    = pr_IMsg -> Class;
  574.             pr_Code        = pr_IMsg -> Code;
  575.             pr_Gadget    = (struct Gadget *)pr_IMsg -> IAddress;
  576.  
  577.             if(pr_Class == VANILLAKEY)
  578.                 pr_Code = ToUpper(pr_Code);
  579.  
  580.             ReplyMsg(pr_IMsg);
  581.  
  582.             if(pr_Class == INTUITICKS)
  583.             {
  584.                 if(pr_TickCount)
  585.                     pr_TickCount--;
  586.                 else
  587.                 {
  588.                     pr_Result = pr_Default;
  589.                     break;
  590.                 }
  591.  
  592.                 continue;
  593.             }
  594.  
  595.             if(pr_Class == INACTIVEWINDOW)
  596.             {
  597.                 MoveScreen(pr_Window -> WScreen,0,- pr_Window -> WScreen -> TopEdge);
  598.                 ScreenToFront(pr_Window -> WScreen);
  599.                 ActivateWindow(pr_Window);
  600.  
  601.                 continue;
  602.             }
  603.  
  604.             if(pr_Class == GADGETUP)
  605.             {
  606.                 if(pr_Gadget -> GadgetID == 0)
  607.                     pr_Result = TRUE;
  608.  
  609.                 break;
  610.             }
  611.  
  612.             if(pr_Class == CLOSEWINDOW)
  613.                 break;
  614.  
  615.             if(pr_Class == VANILLAKEY)
  616.             {
  617.                 pr_Code = ToUpper(pr_Code);
  618.  
  619.                 if((pr_Code == 'Y' || pr_Code == 'J' || pr_Code == 'V' || pr_Code == 'C' || pr_Code == 'R' || pr_Code == '\r') && pr_PosText)
  620.                 {
  621.                     pr_Result = TRUE;
  622.                     break;
  623.                 }
  624.  
  625.                 if((pr_Code == 'N' || pr_Code == 'Q' || pr_Code == 'B' || pr_Code == '\33') && pr_NegText)
  626.                     break;
  627.  
  628.                 continue;
  629.             }
  630.  
  631.             if(pr_Class == MOUSEBUTTONS && pr_Code == MENUDOWN)
  632.             {
  633.                 MovePointer(pr_Window -> WScreen,FALSE,
  634.                     pr_Window -> LeftEdge+ (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2),
  635.                     pr_Window -> TopEdge + (pr_TempGadget -> TopEdge  + pr_TempGadget -> Height / 2));
  636.             }
  637.         }
  638.     }
  639.  
  640.     CloseFont(pr_TextFont);
  641.  
  642.     if(pr_PosGadget)
  643.     {
  644.         RemoveGadget(pr_Window,pr_PosGadget);
  645.         FreeRem(pr_PosGadget);
  646.     }
  647.  
  648.     if(pr_NegGadget)
  649.     {
  650.         RemoveGadget(pr_Window,pr_NegGadget);
  651.         FreeRem(pr_NegGadget);
  652.     }
  653.  
  654.     FreeRem(pr_NewWindow);
  655.  
  656.     pr_IntuiLock = LockIBase(NULL);
  657.  
  658.     if(pr_FrontScreen == IntuitionBase -> FirstScreen)
  659.         pr_FrontScreen = NULL;
  660.  
  661.     UnlockIBase(pr_IntuiLock);
  662.  
  663.     if(pr_FrontScreen)
  664.         ScreenToFront(pr_FrontScreen);
  665.  
  666.     CloseWindow(pr_Window);
  667.  
  668.     return(pr_Result);
  669. }
  670.  
  671.     /* GetToken(s,start):
  672.      *
  673.      *    Parse a string and split it into single tokens.
  674.      */
  675.  
  676. UBYTE *
  677. GetToken(UBYTE *s,LONG *start)
  678. {
  679.     static UBYTE    buffer[256];
  680.     LONG        i,end = 0,quote = FALSE,maxlen = strlen(s);
  681.     char        t;
  682.  
  683.     if(maxlen > 255)
  684.         maxlen = 255;
  685.  
  686.     if(*start > strlen(s) - 1 || !strlen(s) || !s)
  687.         return(NULL);
  688.  
  689.     for(i = *start ; i <= maxlen ; i++)
  690.     {
  691.         if(!end && (s[i] == ' ' || s[i] == '\t'))
  692.         {
  693.             while((s[i] == ' ' || s[i] == '\t') && i < maxlen)
  694.             {
  695.                 i++;
  696.                 (*start)++;
  697.             }
  698.         }
  699.  
  700.         t = s[i];
  701.  
  702.         if(!end && t == '+')
  703.         {
  704.             (*start)++;
  705.             continue;
  706.         }
  707.  
  708.         if(!end && t == '=')
  709.         {
  710.             strcpy(buffer,"=");
  711.             (*start)++;
  712.  
  713.             return(buffer);
  714.         }
  715.  
  716.         if(s[i] == '\\' && s[i + 1] == '\"')
  717.         {
  718.             i += 2;
  719.  
  720.             end = i - *start + 1;
  721.  
  722.             t = s[i];
  723.         }
  724.  
  725.         if(t == '\"' && !quote)
  726.         {
  727.             quote = TRUE;
  728.  
  729.             (*start)++;
  730.  
  731.             end++;
  732.  
  733.             continue;
  734.         }
  735.  
  736.         if((t == '+' || t == '=' || t == ' ' || t == '\t' || t == ';') && quote)
  737.         {
  738.             end++;
  739.             continue;
  740.         }
  741.  
  742.         if((t == '+' || t == '\n' || t == '=' || t == ' ' || t == 0) || (t == '\"' && quote) || (t == ';' && !quote))
  743.         {
  744.             if(t == ';' && !end)
  745.                 return(NULL);
  746.  
  747.             if(t == '\"')
  748.             {
  749.                 strncpy(buffer,s + *start,end - 1);
  750.                 buffer[end - 1] = 0;
  751.             }
  752.             else
  753.             {
  754.                 strncpy(buffer,s + *start,end);
  755.                 buffer[end] = 0;
  756.             }
  757.  
  758.             (*start) += end;
  759.  
  760.             return(buffer);
  761.         }
  762.  
  763.         end++;
  764.     }
  765.  
  766.     return(NULL);
  767. }
  768.  
  769.     /* AddMacroKey(MacroKey):
  770.      *
  771.      *    Add a macro key to the big list.
  772.      */
  773.  
  774. struct MacroKey *
  775. AddMacroKey(struct MacroKey *MacroKey)
  776. {
  777.     struct MacroKey    *TheKey = NULL;
  778.     LONG         i;
  779.  
  780.     for(i = 0 ; i < MAXMACROS ; i++)
  781.     {
  782.         if(KeyList[i] . mk_Type == MK_UNUSED)
  783.         {
  784.             TheKey = &KeyList[i];
  785.             break;
  786.         }
  787.     }
  788.  
  789.     if(!TheKey)
  790.         return(NULL);
  791.  
  792.     CopyMem(MacroKey,TheKey,sizeof(struct MacroKey));
  793.  
  794.     return(TheKey);
  795. }
  796.  
  797.     /* Interprete(String,Line):
  798.      *
  799.      *    Interprete a command line from the config file.
  800.      */
  801.  
  802. BYTE
  803. Interprete(UBYTE *String,LONG Line)
  804. {
  805.     ULONG             Qualifier = 0;
  806.     ULONG             Code = -1;
  807.     struct InputEvent     FakeEvent;
  808.     struct MacroKey         NewKey;
  809.  
  810.     LONG             Start = 0,Key = FALSE,i,KeyCount = 0;
  811.     volatile LONG         QuitLoop;
  812.     UBYTE            *Token,*CommandString,*WindowName = NULL,Recognized = FALSE;
  813.  
  814.     UBYTE             MessBuff[256],KeyBuff1[40],KeyBuff2[40];
  815.  
  816.     if(String[strlen(String) - 1] == '\n')
  817.         String[strlen(String) - 1] = 0;
  818.  
  819.     if(Token = GetToken(String,&Start))
  820.     {
  821.         if(!UStrCmp("KEY",Token))
  822.             Key = TRUE;
  823.  
  824.         if(UStrCmp("COMMAND",Token) && !Key)
  825.         {
  826.             SPrintf(MessBuff,"Line %ld: Unknown keyword:\n\n'%s'",Line,String);
  827.  
  828.             PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE);
  829.             return(FALSE);
  830.         }
  831.     }
  832.     else
  833.         return(TRUE);
  834.  
  835.     FOREVER
  836.     {
  837.         if(Token = GetToken(String,&Start))
  838.         {
  839.             QuitLoop = TRUE;
  840.  
  841.             for(i = 0 ; i < 9 ; i++)
  842.             {
  843.                 if(!UStrCmp(QualifierTab[i] . ka_Name,Token))
  844.                 {
  845.                     Recognized = TRUE;
  846.                     QuitLoop = FALSE;
  847.  
  848.                     Qualifier |= QualifierTab[i] . ka_Key;
  849.                 }
  850.             }
  851.         }
  852.         else
  853.             break;
  854.  
  855.         if(QuitLoop)
  856.             break;
  857.     }
  858.  
  859.     if(!Recognized)
  860.     {
  861.         SPrintf(MessBuff,"Line %ld: Didn't recognize qualifier:\n\n'%s'",Line,String);
  862.  
  863.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE);
  864.         return(FALSE);
  865.     }
  866.  
  867.     if(Token)
  868.         goto JumpIn;
  869.  
  870.     if(Token = GetToken(String,&Start))
  871.     {
  872. JumpIn:        for(i = 0 ; i < 22 ; i++)
  873.         {
  874.             if(!UStrCmp(KeyTab[i] . ka_Name,Token))
  875.             {
  876.                 Code = KeyTab[i] . ka_Key;
  877.                 goto Next;
  878.             }
  879.         }
  880.  
  881.         if(InvertKeyMap(Token[0],&FakeEvent,MSeg -> DefaultKeyMap))
  882.             Code = FakeEvent . ie_Code;
  883.     }
  884.  
  885.     if(Code == -1)
  886.     {
  887.         SPrintf(MessBuff,"Line %ld: Didn't recognize key:\n\n'%s'",Line,String);
  888.  
  889.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE);
  890.         return(FALSE);
  891.     }
  892.  
  893. Next:    FOREVER
  894.     {
  895.         if(Token = GetToken(String,&Start))
  896.         {
  897.             if(!UStrCmp("=",Token))
  898.                 break;
  899.         }
  900.         else
  901.         {
  902.             SPrintf(MessBuff,"Line %ld: Statement '=' missing:\n\n'%s'",Line,String);
  903.  
  904.             PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE);
  905.             return(FALSE);
  906.         }
  907.     }
  908.  
  909.     if(Token = GetToken(String,&Start))
  910.         strcpy(KeyBuff1,Token);
  911.     else
  912.     {
  913.         SPrintf(MessBuff,"Line %ld: Didn't find macro:\n\n'%s'",Line,String);
  914.  
  915.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE);
  916.         return(FALSE);
  917.     }
  918.  
  919.     if(Key)
  920.         goto AddIt;
  921.  
  922.     if(!(Token = GetToken(String,&Start)))
  923.         goto AddIt;
  924.  
  925.     if(UStrCmp("WINDOW",Token))
  926.     {
  927.         SPrintf(MessBuff,"Line %ld: Didn't recognize 'WINDOW' statement:\n\n'%s'",Line,String);
  928.  
  929.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE);
  930.         return(FALSE);
  931.     }
  932.  
  933.     if(!(Token = GetToken(String,&Start)))
  934.     {
  935.         SPrintf(MessBuff,"Line %ld: Didn't find window title:\n\n'%s'",Line,String);
  936.  
  937.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE);
  938.         return(FALSE);
  939.     }
  940.  
  941.     if(!(WindowName = (UBYTE *)AllocRem(strlen(Token) + 1,MEMF_PUBLIC)))
  942.     {
  943.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE);
  944.         return(FALSE);
  945.     }
  946.  
  947.     strcpy(WindowName,Token);
  948.  
  949. AddIt:    for(i = 0 ; i < strlen(KeyBuff1) ; i++)
  950.     {
  951.         UBYTE c;
  952.  
  953.         if(KeyBuff1[i] != '\\')
  954.         {
  955.             KeyBuff2[KeyCount++] = KeyBuff1[i];
  956.             continue;
  957.         }
  958.  
  959.         if(i == strlen(KeyBuff1) - 1)
  960.             break;
  961.  
  962.         i++;
  963.  
  964.         c = 0;
  965.  
  966.         switch(ToUpper(KeyBuff1[i]))
  967.         {
  968.             case 'U':    c = KC_CURSORUP;
  969.                     break;
  970.  
  971.             case 'D':    c = KC_CURSORDOWN;
  972.                     break;
  973.  
  974.             case 'L':    c = KC_CURSORLEFT;
  975.                     break;
  976.  
  977.             case 'R':    c = KC_CURSORRIGHT;
  978.                     break;
  979.  
  980.             case 'H':    c = KC_HELP;
  981.                     break;
  982.  
  983.             case 'B':    c = 8;
  984.                     break;
  985.  
  986.             case 'E':    c = 127;
  987.                     break;
  988.  
  989.             case 'F':    if(i == strlen(KeyBuff1) - 1)
  990.                         break;
  991.  
  992.                     i++;
  993.  
  994.                     if(!isdigit(KeyBuff1[i]))
  995.                         break;
  996.  
  997.                     if(!KeyBuff1[i] == '1')
  998.                     {
  999.                         c = KC_FKEY1 + KeyBuff1[i] - '1';
  1000.                         break;
  1001.                     }
  1002.  
  1003.                     if(i == strlen(KeyBuff1) - 1)
  1004.                         break;
  1005.  
  1006.                     i++;
  1007.  
  1008.                     if(!isdigit(KeyBuff1[i]))
  1009.                     {
  1010.                         c = KC_FKEY1;
  1011.                         break;
  1012.                     }
  1013.  
  1014.                     if(KeyBuff1[i] != '0')
  1015.                         break;
  1016.  
  1017.                     c = KC_FKEY10;
  1018.                     break;
  1019.  
  1020.             case 'N':    c = '\n';
  1021.                     break;
  1022.  
  1023.             case '\\':    c = '\\';
  1024.                     break;
  1025.  
  1026.             default:    c = KeyBuff1[i];
  1027.  
  1028.                     break;
  1029.         }
  1030.  
  1031.         if(c)
  1032.             KeyBuff2[KeyCount++] = c;
  1033.     }
  1034.  
  1035.     KeyBuff2[KeyCount] = 0;
  1036.  
  1037.     if(!(CommandString = (UBYTE *)AllocRem(strlen(KeyBuff2) + 1,MEMF_PUBLIC)))
  1038.     {
  1039.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE);
  1040.         FreeRem(WindowName);
  1041.  
  1042.         return(FALSE);
  1043.     }
  1044.  
  1045.     strcpy(CommandString,KeyBuff2);
  1046.  
  1047.     memset(&NewKey,0,sizeof(struct MacroKey));
  1048.  
  1049.     NewKey . mk_CommandKey        = Code;
  1050.     NewKey . mk_CommandQualifier    = Qualifier;
  1051.  
  1052.     NewKey . mk_String        = CommandString;
  1053.     NewKey . mk_Window        = WindowName;
  1054.  
  1055.     if(Key)
  1056.         NewKey . mk_Type    = MK_WORD;
  1057.     else
  1058.         NewKey . mk_Type    = MK_COMMAND;
  1059.  
  1060.     if(AddMacroKey(&NewKey))
  1061.         return(TRUE);
  1062.  
  1063.     SPrintf(MessBuff,"Line %ld: Key macro table full.",Line);
  1064.  
  1065.     PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE);
  1066.     return(FALSE);
  1067. }
  1068.  
  1069.     /* UpdateList(Name):
  1070.      *
  1071.      *    Update the big macro key list.
  1072.      */
  1073.  
  1074. BYTE
  1075. UpdateList(char *Name)
  1076. {
  1077.     char         LineBuff[257];
  1078.     LONG         LineNum = 1;
  1079.     ARPFileHandle    *ConfigFile;
  1080.  
  1081.     if(!Name)
  1082.         Name = "S:KeyMacro.config";
  1083.  
  1084.     if(!(KeyList = (struct MacroKey *)AllocRem(sizeof(struct MacroKey) * MAXMACROS,MEMF_PUBLIC | MEMF_CLEAR)))
  1085.     {
  1086.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE);
  1087.         return(FALSE);
  1088.     }
  1089.  
  1090.     GetDefaultKeyMap();
  1091.  
  1092.     if(ConfigFile = OpenARPFile(Name,MODE_OLDFILE,976))
  1093.     {
  1094.         while(FGetsARP(LineBuff,256,ConfigFile))
  1095.         {
  1096.             if(!Interprete(LineBuff,LineNum++))
  1097.             {
  1098.                 CloseARPFile(ConfigFile);
  1099.  
  1100.                 FreeRem(KeyList);
  1101.  
  1102.                 return(FALSE);
  1103.             }
  1104.         }
  1105.  
  1106.         CloseARPFile(ConfigFile);
  1107.     }
  1108.     else
  1109.     {
  1110.         PopRequest(NULL,"KeyMacro Problem:","Couldn't open configuration file!",NULL,"Continue?",FALSE);
  1111.  
  1112.         FreeRem(KeyList);
  1113.  
  1114.         return(FALSE);
  1115.     }
  1116.  
  1117.     return(TRUE);
  1118. }
  1119.  
  1120. BYTE
  1121. GetDefaultKeyMap()
  1122. {
  1123.     struct IOStdReq    *ConsoleRequest;
  1124.     struct MsgPort    *ConsolePort;
  1125.     BYTE         Result = FALSE;
  1126.  
  1127.     if(ConsolePort = CreatePort(NULL,0))
  1128.     {
  1129.         if(ConsoleRequest = CreateStdIO(ConsolePort))
  1130.         {
  1131.             if(!OpenDevice("console.device",CONU_STANDARD,ConsoleRequest,0))
  1132.             {
  1133.                 ConsoleRequest -> io_Command    = CD_ASKDEFAULTKEYMAP;
  1134.                 ConsoleRequest -> io_Length    = sizeof(struct KeyMap);
  1135.                 ConsoleRequest -> io_Data    = (APTR)MSeg -> DefaultKeyMap;
  1136.                 ConsoleRequest -> io_Flags    = IOF_QUICK;
  1137.  
  1138.                 if(!DoIO(ConsoleRequest))
  1139.                     Result = TRUE;
  1140.  
  1141.                 CloseDevice(ConsoleRequest);
  1142.             }
  1143.  
  1144.             DeleteStdIO(ConsoleRequest);
  1145.         }
  1146.  
  1147.         DeletePort(ConsolePort);
  1148.     }
  1149.  
  1150.     return(Result);
  1151. }
  1152.  
  1153.     /* main(argc,argv):
  1154.      *
  1155.      *    The entry point to this program.
  1156.      */
  1157.  
  1158. VOID
  1159. main(int argc,char **argv)
  1160. {
  1161.     struct Process    *ThatsMe = (struct Process *)SysBase -> ThisTask;
  1162.     char        *FileName = argv[ARG_STARTUP];
  1163.     LONG         Created = FALSE;
  1164.     LONG         i;
  1165.  
  1166.         /* No ^C trapping, please. */
  1167.  
  1168.     Enable_Abort = FALSE;
  1169.  
  1170.         /* Started from Workbench? */
  1171.  
  1172.     if(!From_CLI)
  1173.         FileName = NULL;
  1174.  
  1175.         /* Look if handler process is already running. */
  1176.  
  1177.     MSeg = (struct MSeg *)FindPort(PORTNAME);
  1178.  
  1179.         /* Short info? */
  1180.  
  1181.     if(argv[ARG_INFO])
  1182.     {
  1183.         Printf("\n\33[1m\33[33mKeyMacro\33[31m\33[0m the Amiga macro key handler.\n\n");
  1184.  
  1185.         Printf("         This program may be non-commercially\n");
  1186.         Printf("         redistributed!\n\n");
  1187.  
  1188.         Printf("\33[1m\33[33mAuthor\33[31m\33[0m - Olaf Barthel, MXM\n");
  1189.         Printf("         Brabeckstrasse 35\n");
  1190.         Printf("         D-3000 Hannover 71\n\n");
  1191.  
  1192.         Printf("     Federal Republic of Germany.\n\n");
  1193.  
  1194.         exit(RETURN_OK);
  1195.     }
  1196.  
  1197.         /* Remove the handler? */
  1198.  
  1199.     if(argv[ARG_QUIT])
  1200.     {
  1201.         Printf("Removing \33[1m\33[33mKeyMacro\33[31m\33[0m, ");
  1202.  
  1203.         if(!MSeg)
  1204.         {
  1205.             Printf("failed!\a\n");
  1206.  
  1207.             exit(RETURN_OK);
  1208.         }
  1209.  
  1210.         MSeg -> Father = (struct Task *)SysBase -> ThisTask;
  1211.  
  1212.         if(MSeg -> Child)
  1213.         {
  1214.             Signal(MSeg -> Child,SIG_CLOSE);
  1215.             Wait(SIG_CLOSE);
  1216.         }
  1217.  
  1218.         RemPort(&MSeg -> Port);
  1219.  
  1220.         FreeMem(MSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
  1221.  
  1222.         if(MSeg -> Segment)
  1223.             UnLoadPrg(MSeg -> Segment);
  1224.  
  1225.         if(MSeg -> MacroList)
  1226.         {
  1227.             for(i = 0 ; i < MSeg -> NumMacros ; i++)
  1228.             {
  1229.                 if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  1230.                     continue;
  1231.  
  1232.                 if(MSeg -> MacroList[i] . mk_String)
  1233.                     FreeRem(MSeg -> MacroList[i] . mk_String);
  1234.  
  1235.                 if(MSeg -> MacroList[i] . mk_Window)
  1236.                     FreeRem(MSeg -> MacroList[i] . mk_Window);
  1237.             }
  1238.  
  1239.             FreeRem(MSeg -> MacroList);
  1240.         }
  1241.  
  1242.         FreeRem(MSeg -> DefaultKeyMap);
  1243.         FreeRem(MSeg);
  1244.  
  1245.         Printf("OK.\n");
  1246.  
  1247.         exit(RETURN_OK);
  1248.     }
  1249.  
  1250.         /* Allocate the handler data. */
  1251.  
  1252.     if(!MSeg)
  1253.     {
  1254.         if(MSeg = (struct MSeg *)AllocRem(sizeof(struct MSeg),MEMF_PUBLIC | MEMF_CLEAR))
  1255.         {
  1256.             MSeg -> Port . mp_Flags            = PA_IGNORE;
  1257.             MSeg -> Port . mp_Node . ln_Pri        = 0;
  1258.             MSeg -> Port . mp_Node . ln_Type    = NT_MSGPORT;
  1259.             MSeg -> Port . mp_Node . ln_Name    = AllocMem(sizeof(PORTNAME),MEMF_PUBLIC);
  1260.             MSeg -> Child                = NULL;
  1261.             MSeg -> Father                = (struct Task *)SysBase -> ThisTask;
  1262.             MSeg -> SegSize                = sizeof(struct MSeg);
  1263.             MSeg -> RingBack            = SIGBREAKF_CTRL_C;
  1264.             MSeg -> Revision            = REVISION;
  1265.  
  1266.             NewList(&MSeg -> Port . mp_MsgList);
  1267.  
  1268.             if(From_CLI)
  1269.             {
  1270.                 Printf("\33[1m\33[33mKeyMacro v1.%ld \33[31m\33[0m© Copyright 1989, 1990 by \33[4mMXM\33[0m, All rights reserved.\n",REVISION);
  1271.  
  1272.                 Printf("Installing \33[33m\33[1mKeyMacro\33[0m\33[31m, ");
  1273.             }
  1274.  
  1275.             if(MSeg -> Port . mp_Node . ln_Name)
  1276.                 strcpy(MSeg -> Port . mp_Node . ln_Name,PORTNAME);
  1277.             else
  1278.             {
  1279. Failed:                FreeRem(MSeg);
  1280.  
  1281.                 if(From_CLI)
  1282.                     Printf("failed!\a\n");
  1283.  
  1284.                 exit(RETURN_FAIL);
  1285.             }
  1286.  
  1287.             if(!(MSeg -> DefaultKeyMap = (struct KeyMap *)AllocPub(sizeof(struct KeyMap))))
  1288.                 goto Failed;
  1289.  
  1290.             if(!(MSeg -> Segment = LoadPrg("KeyMacro-Handler")))
  1291.                 MSeg -> Segment = LoadPrg("L:KeyMacro-Handler");
  1292.  
  1293.             if(!MSeg -> Segment)
  1294.             {
  1295.                 if(From_CLI)
  1296.                     Printf("unable to find \33[33mL:KeyMacro-Handler\33[31m\a!\n");
  1297.  
  1298.                 FreeRem(MSeg -> DefaultKeyMap);
  1299.                 FreeRem(MSeg -> Port . mp_Node . ln_Name);
  1300.                 FreeRem(MSeg);
  1301.             }
  1302.             else
  1303.             {
  1304.                 AddPort(&MSeg -> Port);
  1305.  
  1306.                 if(!CreateProc("KeyMacro-Handler",10,MSeg -> Segment,4096))
  1307.                     goto NoMem;
  1308.  
  1309.                 Wait(SIGBREAKF_CTRL_C);
  1310.  
  1311.                 if(!MSeg -> Child)
  1312.                 {
  1313. NoMem:                    if(From_CLI)
  1314.                         Printf("\33[33mFAILED!\33[31m (care to retry?)\n");
  1315.  
  1316.                     RemPort(&MSeg -> Port);
  1317.  
  1318.                     FreeRem(MSeg -> DefaultKeyMap);
  1319.                     FreeRem(MSeg -> Port . mp_Node . ln_Name);
  1320.  
  1321.                     if(MSeg -> Segment)
  1322.                         UnLoadPrg(MSeg -> Segment);
  1323.  
  1324.                     FreeRem(MSeg);
  1325.  
  1326.                     exit(RETURN_FAIL);
  1327.                 }
  1328.                 else
  1329.                 {
  1330.                     if(From_CLI)
  1331.                         Printf("initializing, ");
  1332.  
  1333.                     GetDefaultKeyMap();
  1334.  
  1335.                     if(From_CLI)
  1336.                         Puts("Okay.");
  1337.                     else
  1338.                         PopRequest(NULL,"KeyMacro Info:","\33[1mKeyMacro\33[0m installed.",NULL,"Continue?",FALSE);
  1339.  
  1340.                     Created = TRUE;
  1341.                 }
  1342.             }
  1343.         }
  1344.     }
  1345.  
  1346.         /* Update the macro key list. */
  1347.  
  1348.     if(UpdateList(FileName))
  1349.     {
  1350.         if(Created)
  1351.         {
  1352.             MSeg -> NumMacros = MAXMACROS;
  1353.             MSeg -> MacroList = KeyList;
  1354.         }
  1355.         else
  1356.         {
  1357.             struct MacroMessage UpdateMsg;
  1358.  
  1359.             UpdateMsg . mm_Type        = MM_UPDATE;
  1360.             UpdateMsg . mm_NumMacros    = MAXMACROS;
  1361.             UpdateMsg . mm_MacroList    = KeyList;
  1362.  
  1363.             SendMacroMsg(&UpdateMsg,&MSeg -> Port);
  1364.  
  1365.             if(From_CLI)
  1366.                 Printf("\33[1mKeyMacro:\33[0m Updating macro keys...\n");
  1367.         }
  1368.     }
  1369.     else
  1370.         exit(RETURN_ERROR);
  1371.  
  1372.     exit(RETURN_OK);
  1373. }
  1374.