home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 19 / AACD19.BIN / AACD / System / SnoopDos / SnoopDos_Src / SnoopDos_Source / settings.c < prev    next >
C/C++ Source or Header  |  2001-02-04  |  84KB  |  1,907 lines

  1. /*
  2.  *              SETTINGS.C                                                                                      vi:ts=4
  3.  *
  4.  *      Copyright (c) Eddy Carroll, September 1994.
  5.  *
  6.  *              This module handles all the command parsing for tooltypes, command
  7.  *              line options, config files, AREXX, etc.
  8.  */             
  9.  
  10. #include "system.h"
  11. #include "snoopdos.h"
  12.  
  13. extern char Version[];                  /* From Snoopdos.c */
  14. extern char CommodityTitle[];   /* From Snoopdos.c */
  15.  
  16. char ConfigID[] = "<SnoopDos Settings>";
  17.  
  18. ULONG                   UpdateFlags;            /* Shows what settings were changed             */
  19. struct MsgPort *RemoteReplyPort;        /* Used when talking to b/g SnoopDos    */
  20.  
  21. /*
  22.  *              Now the result codes returned by our simple command interpreter
  23.  */
  24. typedef enum {
  25.         EXEC_FAIL,                      /* The command failed for some reason   */
  26.         EXEC_OKAY,                      /* The command succeeded                                */
  27.         EXEC_UNKNOWN,           /* The command wasn't recognised                */
  28.         EXEC_NOPARAM            /* The command was missing a parameter  */
  29. } ExecEnum;
  30.  
  31. /*
  32.  *              Now let's define the commands we understand.
  33.  */
  34. #define CMD_UNKNOWN             -1
  35. #define CMD_NOPARAM             -2
  36.  
  37. typedef enum {
  38.         CMD_END,
  39.  
  40.         /*
  41.          *              Options within function requester. Note that these MUST correspond
  42.          *              exactly with the first set of enums in SNOOPDOS.H for GID_???!
  43.          */
  44.         CMD_FINDPORT,
  45.         CMD_FINDRESIDENT,
  46.         CMD_FINDSEMAPHORE,
  47.         CMD_FINDTASK,
  48.         CMD_LOCKSCREEN,
  49.         CMD_OPENDEVICE,
  50.         CMD_OPENFONT,
  51.         CMD_OPENLIBRARY,
  52.         CMD_OPENRESOURCE,
  53.         CMD_READTOOLTYPES,
  54.         CMD_SENDREXX,
  55.  
  56.         CMD_CHANGEDIR,
  57.         CMD_DELETE,
  58.         CMD_EXECUTE,
  59.         CMD_GETVAR,
  60.         CMD_LOADSEG,
  61.         CMD_LOCK,
  62.         CMD_MAKEDIR,
  63.         CMD_MAKELINK,
  64.         CMD_OPEN,
  65.         CMD_RENAME,
  66.         CMD_RUNCOMMAND,
  67.         CMD_SETVAR,
  68.         CMD_DOSSYSTEM,          /* CMD_SYSTEM is defined in dos/dosextens.h     */
  69.  
  70.         CMD_DUMMY1,
  71.         CMD_DUMMY2,
  72.         CMD_DUMMY3,
  73.         CMD_DUMMY4,
  74.         CMD_DUMMY5,
  75.  
  76.         CMD_ONLYSHOWFAILS,
  77.         CMD_SHOWCLI,
  78.         CMD_SHOWFULLPATH,
  79.         CMD_USEDEVICENAME,
  80.         CMD_MONITORPACKETS,
  81.         CMD_MONALLPACKETS,
  82.         CMD_MONROMCALLS,
  83.         CMD_IGNORESHELL,
  84.  
  85. #define MAX_BOOL_CMD                    CMD_IGNORESHELL
  86.  
  87.         CMD_MATCHNAME,
  88.  
  89.         /*
  90.          *              General commands
  91.          */
  92.         CMD_LOADSETTINGS,
  93.         CMD_SAVESETTINGS,
  94.         CMD_LOADDEFSETTINGS,
  95.         CMD_SAVEDEFSETTINGS,
  96.         CMD_SETTINGS,
  97.         CMD_FUNCTIONS,
  98.         CMD_LANGUAGE,
  99.         CMD_CLEARBUFFER,
  100.         CMD_WINDOWWIDTH,
  101.         CMD_HELP,
  102.         CMD_COPYWINDOW,
  103.         CMD_COPYBUFFER,
  104.         CMD_SAVEWINDOW,
  105.         CMD_SAVEBUFFER,
  106.         CMD_SHOW,
  107.         CMD_HIDE,
  108.         CMD_OPENFORMAT,
  109.         CMD_OPENFUNCTION,
  110.         CMD_OPENSETUP,
  111.         CMD_CLOSEFORMAT,
  112.         CMD_CLOSEFUNCTION,
  113.         CMD_CLOSESETUP,
  114.         CMD_QUIT,
  115.         CMD_PAUSE,
  116.         CMD_UNPAUSE,
  117.         CMD_DISABLE,
  118.         CMD_ENABLE,
  119.         CMD_SINGLESTEP,
  120.         CMD_OPENLOG,
  121.         CMD_APPENDLOG,
  122.         CMD_OPENSERIALLOG,
  123.         CMD_CLOSELOG,
  124.         CMD_ADDLOG,
  125.         CMD_FLUSHLOG,
  126.         CMD_SCROLLUP,
  127.         CMD_SCROLLDOWN,
  128.         CMD_GOTO,
  129.  
  130.         /*
  131.          *              General settings
  132.          */
  133.         CMD_PATCHRAMLIB,
  134.         CMD_STACKLIMIT,
  135.         CMD_ICONPOS,
  136.         CMD_SHOWGADGETS,
  137.         CMD_HIDEGADGETS,
  138.         CMD_AUTOOPEN,
  139.         CMD_DISABLEWHENHIDDEN,
  140.         CMD_SHOWSTATUS,
  141.         CMD_HIDESTATUS,
  142.         CMD_CREATEICONS,
  143.         CMD_TEXTSPACING,
  144.         CMD_SIMPLEREFRESH,
  145.         CMD_SMARTREFRESH,
  146.         CMD_LEFTALIGNED,
  147.         CMD_RIGHTALIGNED,
  148.         CMD_ROWQUALIFIER,
  149.         CMD_MAINPOS,
  150.         CMD_MAINSIZE,
  151.         CMD_FUNCPOS,
  152.         CMD_FORMPOS,
  153.         CMD_SETPOS,
  154.         CMD_TASKPRI,
  155.         CMD_CXPRI,
  156.  
  157.         /*
  158.          *              Options within setup requester
  159.          */
  160.         CMD_HIDEMETHOD,
  161.         CMD_SCREENTYPE,
  162.         CMD_BUFFERSIZE,
  163.         CMD_LOGMODE,
  164.         CMD_FILEIOTYPE,
  165.         CMD_FORMAT,
  166.         CMD_LOGFORMAT,
  167.         CMD_HOTKEY,
  168.         CMD_SCREENNAME,
  169.         CMD_LOGNAME,
  170.         CMD_WINDOWFONT,
  171.         CMD_BUFFERFONT,
  172.  
  173.         NUMCOMMANDS
  174.  
  175. } COMMAND_ID;
  176.  
  177.  
  178. /*
  179.  *              Now associate a command string with each of these identifiers
  180.  */
  181. struct Command {
  182.         short   cmdid;                  /* Command ID                                                   */
  183.         short   changemask;             /* Which group of settings will change  */
  184.         short   numparms;               /* Min number of parameters (0 or more) */
  185.         char    *name;                  /* Command name                                                 */
  186. } CommandTable[] = {
  187.         /*
  188.          *              In alphabetical order, for quick reference
  189.          */
  190.         CMD_ADDLOG,                             SET_NONE,       1, "AddLog",
  191.         CMD_APPENDLOG,                  SET_NONE,       1, "AppendLog",
  192.         CMD_AUTOOPEN,                   SET_MAIN,       0, "AutoOpen",
  193.         CMD_BUFFERFONT,                 SET_SETUP,      1, "BufferFont",
  194.         CMD_BUFFERSIZE,                 SET_SETUP,      1, "BufferSize",
  195.         CMD_CHANGEDIR,                  SET_FUNC,       0, "ChangeDir",
  196.         CMD_CLEARBUFFER,                SET_FUNC,       0, "ClearBuffer",
  197.         CMD_CLOSEFORMAT,                SET_NONE,       0, "CloseFormat",
  198.         CMD_CLOSEFUNCTION,              SET_NONE,       0, "CloseFunction",
  199.         CMD_CLOSELOG,                   SET_NONE,       0, "CloseLog",
  200.         CMD_CLOSESETUP,                 SET_NONE,       0, "CloseSetup",
  201.         CMD_COPYBUFFER,                 SET_NONE,       0, "CopyBuffer",
  202.         CMD_COPYWINDOW,                 SET_NONE,       0, "CopyWindow",
  203.         CMD_CREATEICONS,                SET_MAIN,       0, "CreateIcons",
  204.         CMD_HOTKEY,                             SET_SETUP,      1, "CX_PopKey",
  205.         CMD_SHOW,                               SET_NONE,       0, "CX_Popup",
  206.         CMD_CXPRI,                              SET_NONE,       1, "CX_Priority",
  207.         CMD_DELETE,                     SET_FUNC,       0, "Delete",
  208.         CMD_DISABLE,                    SET_NONE,       0, "Disable",
  209.         CMD_DISABLEWHENHIDDEN,  SET_MAIN,       0, "DisableWhenHidden",
  210.         CMD_ENABLE,                     SET_NONE,       0, "Enable",
  211.         CMD_EXECUTE,                    SET_FUNC,       0, "Execute",
  212.         CMD_FILEIOTYPE,                 SET_SETUP,      1, "FileIOType",
  213.         CMD_FINDPORT,                   SET_FUNC,       0, "FindPort",
  214.         CMD_FINDRESIDENT,               SET_FUNC,       0, "FindResident",
  215.         CMD_FINDSEMAPHORE,              SET_FUNC,       0, "FindSemaphore",
  216.         CMD_FINDTASK,                   SET_FUNC,       0, "FindTask",
  217.         CMD_FLUSHLOG,                   SET_NONE,       0, "FlushLog",
  218.         CMD_FORMAT,                     SET_SETUP,      1, "Format",
  219.         CMD_FORMPOS,                    SET_MAIN,       1, "FormatWindowPos",
  220.         CMD_FUNCTIONS,                  SET_FUNC,       1, "Functions",
  221.         CMD_FUNCPOS,                    SET_MAIN,       1, "FunctionWindowPos",
  222.         CMD_GETVAR,                     SET_FUNC,       0, "GetVar",
  223.         CMD_GOTO,                               SET_NONE,       1, "GotoLine",
  224.         CMD_HELP,                               SET_NONE,       0, "Help",
  225.         CMD_HIDE,                               SET_NONE,       0, "Hide",
  226.         CMD_HIDEGADGETS,                SET_MAIN,       0, "HideGadgets",
  227.         CMD_HIDEMETHOD,                 SET_SETUP,      1, "HideMethod",
  228.         CMD_HIDESTATUS,                 SET_MAIN,       0, "HideStatus",
  229.         CMD_HOTKEY,                     SET_SETUP,      1, "HotKey",
  230.         CMD_ICONPOS,                    SET_MAIN,       1, "IconPos",
  231.         CMD_IGNORESHELL,                SET_FUNC,       0, "IgnoreShell",
  232.         CMD_LANGUAGE,                   SET_NONE,       1, "Language",
  233.         CMD_LEFTALIGNED,                SET_MAIN,       0, "LeftAligned",
  234.         CMD_LOADDEFSETTINGS,    SET_NONE,       0, "LoadDefSettings",
  235.         CMD_LOADSEG,                    SET_FUNC,       0, "LoadSeg",
  236.         CMD_LOADSETTINGS,               SET_NONE,       1, "LoadSettings",
  237.         CMD_LOCK,                               SET_FUNC,       0, "Lock",
  238.         CMD_LOCKSCREEN,                 SET_FUNC,       0, "LockScreen",
  239.         CMD_LOGFORMAT,                  SET_SETUP,      1, "LogFormat",
  240.         CMD_LOGMODE,                    SET_SETUP,      1, "LogMode",
  241.         CMD_LOGNAME,                    SET_SETUP,      1, "LogName",
  242.         CMD_MAINPOS,                    SET_MAIN,       1, "MainWindowPos",
  243.         CMD_MAINSIZE,                   SET_MAIN,       1, "MainWindowSize",
  244.         CMD_MAKEDIR,                    SET_FUNC,       0, "MakeDir",
  245.         CMD_MAKELINK,                   SET_FUNC,       0, "MakeLink",
  246.         CMD_MATCHNAME,                  SET_FUNC,       1, "MatchName",
  247.         CMD_MONITORPACKETS,     SET_FUNC,       0, "MonitorPackets",
  248.         CMD_MONROMCALLS,                SET_FUNC,       0, "MonitorROMCalls",
  249.         CMD_ONLYSHOWFAILS,              SET_FUNC,       0, "OnlyShowFails",
  250.         CMD_OPEN,                               SET_FUNC,       0, "Open",
  251.         CMD_OPENDEVICE,                 SET_FUNC,       0, "OpenDevice",
  252.         CMD_OPENFONT,                   SET_FUNC,       0, "OpenFont",
  253.         CMD_OPENFORMAT,                 SET_NONE,       0, "OpenFormat",
  254.         CMD_OPENFUNCTION,               SET_NONE,       0, "OpenFunction",
  255.         CMD_OPENLIBRARY,                SET_FUNC,       0, "OpenLibrary",
  256.         CMD_OPENLOG,                    SET_NONE,       1, "OpenLog",
  257.         CMD_OPENRESOURCE,               SET_FUNC,       0, "OpenResource",
  258.         CMD_OPENSERIALLOG,              SET_NONE,       0, "OpenSerialLog",
  259.         CMD_OPENSETUP,                  SET_NONE,       0, "OpenSetup",
  260.         CMD_MONALLPACKETS,              SET_FUNC,       0, "PacketDebugger",
  261.         CMD_PATCHRAMLIB,                SET_NONE,       0, "PatchRamLib",
  262.         CMD_PAUSE,                              SET_NONE,       0, "Pause",
  263.         CMD_QUIT,                               SET_NONE,       0, "Quit",
  264.         CMD_READTOOLTYPES,              SET_FUNC,       0, "ReadToolTypes",
  265.         CMD_RENAME,                     SET_FUNC,       0, "Rename",
  266.         CMD_RIGHTALIGNED,               SET_MAIN,       0, "RightAligned",
  267.         CMD_ROWQUALIFIER,               SET_MAIN,       1, "RowQualifier",
  268.         CMD_RUNCOMMAND,                 SET_FUNC,       0, "RunCommand",
  269.         CMD_SAVEBUFFER,                 SET_NONE,       1, "SaveBuffer",
  270.         CMD_SAVEDEFSETTINGS,    SET_NONE,       0, "SaveDefSettings",
  271.         CMD_SAVESETTINGS,               SET_NONE,       1, "SaveSettings",
  272.         CMD_SAVEWINDOW,                 SET_NONE,       1, "SaveWindow",
  273.         CMD_SCREENNAME,                 SET_SETUP,      1, "ScreenName",
  274.         CMD_SCREENTYPE,                 SET_SETUP,      1, "ScreenType",
  275.         CMD_SCROLLDOWN,                 SET_NONE,       1, "ScrollDown",
  276.         CMD_SCROLLUP,                   SET_NONE,       1, "ScrollUp",
  277.         CMD_SENDREXX,                   SET_FUNC,       0, "SendRexx",
  278.         CMD_SETTINGS,                   SET_NONE,       1, "Settings",
  279.         CMD_SETPOS,                     SET_MAIN,       1, "SetupWindowPos",
  280.         CMD_SETVAR,                     SET_FUNC,       0, "SetVar",
  281.         CMD_SHOW,                               SET_NONE,       0, "Show",
  282.         CMD_SHOWCLI,                    SET_FUNC,       0, "ShowCLI",
  283.         CMD_SHOWFULLPATH,               SET_FUNC,       0, "ShowFullPath",
  284.         CMD_SHOWGADGETS,                SET_MAIN,       0, "ShowGadgets",
  285.         CMD_SHOWSTATUS,                 SET_MAIN,       0, "ShowStatus",
  286.         CMD_SIMPLEREFRESH,              SET_MAIN,       0, "SimpleRefresh",
  287.         CMD_SINGLESTEP,                 SET_NONE,       0, "SingleStep",
  288.         CMD_SMARTREFRESH,               SET_MAIN,       0, "SmartRefresh",
  289.         CMD_STACKLIMIT,                 SET_MAIN,       1, "StackLimit",
  290.         CMD_DOSSYSTEM,                  SET_FUNC,       0, "System",
  291.         CMD_TASKPRI,                    SET_NONE,       1, "TaskPri",
  292.         CMD_TEXTSPACING,                SET_MAIN,       1, "TextSpacing",
  293.         CMD_UNPAUSE,                    SET_NONE,       0, "Unpause",
  294.         CMD_USEDEVICENAME,              SET_FUNC,       0, "UseDeviceNames",
  295.         CMD_WINDOWFONT,                 SET_SETUP,      1, "WindowFont",
  296.         CMD_WINDOWWIDTH,                SET_NONE,       1, "WindowWidth",
  297.         CMD_END,                                0,                      0, NULL
  298. };
  299.  
  300. #define NUM_CMDNAMES    (sizeof(CommandTable) / sizeof(CommandTable[0]))
  301.  
  302. char *CmdNames[NUMCOMMANDS];    /* Map command IDs back to name strings */
  303.  
  304. char *Names_HideMethod[] = { "Invisible", "Iconify",    "ToolsMenu",
  305.                                                          "None",           NULL };
  306. char *Names_ScreenType[] = { "Default",   "Front",              "Named",                NULL };
  307. char *Names_LogMode[]    = { "Prompt",    "Append",             "Overwrite",
  308.                                                      "SerialPort", NULL };
  309. char *Names_FileIOType[] = { "Automatic", "Immediate",  "Buffered",             NULL };
  310.  
  311. char *Names_Functions[]  = { "All", "None", "AllDos", "NoDos",
  312.                                                          "AllSystem", "NoSystem", NULL };
  313.  
  314. char *Names_RowQualifier[] = { "Ignore", "None", "Shift", "Alt", "Ctrl",
  315.                                                            "All",     NULL };
  316.  
  317. typedef enum {
  318.         FUNC_ALL, FUNC_NONE, FUNC_ALLDOS, FUNC_NODOS,
  319.         FUNC_ALLSYSTEM, FUNC_NOSYSTEM
  320. } FuncTypes;
  321.  
  322. /*
  323.  *              InitSettings()
  324.  *
  325.  *              Initialises variables associated with settings. For now, this
  326.  *              just means the mapping array that maps command IDs to command
  327.  *              names. This makes it easier to write out the configuration file.
  328.  */
  329. void InitSettings(void)
  330. {
  331.         struct Command *cmd;
  332.         int i;
  333.  
  334.         for (i = 0; i < NUMCOMMANDS; i++)
  335.                 CmdNames[i] = "";       /* Make sure non-cmds initialised to safe value */
  336.  
  337.         for (cmd = CommandTable; cmd->cmdid != CMD_END; cmd++)
  338.                 CmdNames[cmd->cmdid] = cmd->name; 
  339. }
  340.  
  341. /*
  342.  *              MatchParam(&var, param, keywords)
  343.  *
  344.  *              Searches the keyword list for a match with param and stores
  345.  *              the result in the given variable. If no match is found, var
  346.  *              is not altered and returns EXEC_FAIL, else returns EXEC_OKAY.
  347.  */
  348. int MatchParam(unsigned char *var, char *param, char **keywords)
  349. {
  350.         int i;
  351.  
  352.         for (i = 0; keywords[i]; i++) {
  353.                 if (stricmp(param, keywords[i]) == 0) {
  354.                         *var = i;
  355.                         return (EXEC_OKAY);
  356.                 }
  357.         }
  358.         return (EXEC_FAIL);
  359. }
  360.  
  361. /*
  362.  *              ParseFontName(fontspec, fontname, &fontsize)
  363.  *
  364.  *              Parses the font spec in fontspec, which is of the form
  365.  *              "fontname size" or "fontname.font size" or "fontname.size",
  366.  *              into two parts.
  367.  *
  368.  *              The bulk of the name (plus a .font suffix) is copied into fontname.
  369.  *              The size of the font is copied into fontsize. In the event of a parse
  370.  *              error, EXEC_FAIL is returned and no alteration is made to fontname
  371.  *              or fontsize. For success, EXEC_OKAY is returned.
  372.  *
  373.  *              Note that the contents of the string pointed to by fontspec may be
  374.  *              altered. If fontspec is "default" then a fontsize of 0 is returned
  375.  *              to indicate that SnoopDos should use the system default fonts.
  376.  */
  377. int ParseFontName(char *fontspec, char *fontname, USHORT *fontsize)
  378. {
  379.         char *p;
  380.         int size;
  381.  
  382.         /*
  383.          *              First, see if we can find a dot specifier. Anything before
  384.          *              the dot is a font name.
  385.          */
  386.         if (stricmp(fontspec, "default") == 0) {
  387.                 strcpy(fontname, fontspec);
  388.                 *fontsize = 0;
  389.                 return (EXEC_OKAY);
  390.         }
  391.         p = strchr(fontspec, '.');
  392.         if (p) {
  393.                 *p++ = '\0';
  394.                 if (strnicmp(p, "font", 4) == 0)
  395.                         p += 4;
  396.         } else {
  397.                 p = strchr(fontspec, ' ');
  398.                 if (!p)
  399.                         return (EXEC_FAIL);
  400.                 *p++ = '\0';
  401.         }
  402.         while (*p == ' ' || *p == '.')
  403.                 p++;
  404.         size = atoi(p);
  405.         if (size == 0)
  406.                 return (EXEC_FAIL);
  407.         
  408.         strcpy(fontname, fontspec);
  409.         strcat(fontname, ".font");
  410.         *fontsize = size;
  411.         return (EXEC_OKAY);
  412. }
  413.  
  414. /*
  415.  *              ParseTwoNums(param, &num1, &num2)
  416.  *
  417.  *              Parses the given param string, assumed to be in the form "x1,x2"
  418.  *              and stores the two numbers in the given variables. If either number
  419.  *              is invalid, then no change is made to either number and EXEC_FAIL
  420.  *              is returned, else EXEC_OKAY is returned.
  421.  *
  422.  *              The string pointed to by param may be altered.
  423.  */
  424. int ParseTwoNums(char *param, WORD *num1, WORD *num2)
  425. {
  426.         char *p;
  427.  
  428.         p = strchr(param, ',');
  429.         if (!p)
  430.                 return (EXEC_FAIL);
  431.         *p++ = '\0';
  432.  
  433.         while (*p == ' ')
  434.                 p++;
  435.         
  436.         if (*param < '-' || *param > '9' || *p < '-' || *p > '9')
  437.                 return (EXEC_FAIL);
  438.         
  439.         *num1 = atoi(param);
  440.         *num2 = atoi(p);
  441.         return (EXEC_OKAY);
  442. }
  443.  
  444. /*
  445.  *              cid = ParseCommand(cmdline, cmdname, param, &boolvalue, &cmd)
  446.  *
  447.  *              Copies the cmdline into two separate strings, one for the
  448.  *              command name and one for the parameters. Bool is initalised
  449.  *              to 0 or 1, according to the default value of the parameter
  450.  *              (1 if Yes,True,On, 0 if No, False, Off, or if the command
  451.  *              is prefixed by the word No).
  452.  *
  453.  *              cmd points to the command structure for this command.
  454.  *
  455.  *              cid is the command ID that matches the command, CMD_END for
  456.  *              a null command, CMD_UNKNOWN for an unrecognised command,
  457.  *              and CMD_NOPARAM for a known command with too few parameters.
  458.  *              If CMD_NOPARAM is returned, cmdname and &cmd will be initialised
  459.  *              to the command that was matched.
  460.  *
  461.  */
  462. int ParseCommand(char *cmdline, char *cmdname, char *param, int *boolvalue,
  463.                                  struct Command **pcmd)
  464. {
  465.         struct Command *cmd;
  466.         int cid;
  467.         char *p;
  468.         char *q;
  469.  
  470.         if (!cmdline)
  471.                 return (CMD_END);
  472.  
  473.         /*
  474.          *              First, copy just the command header
  475.          */
  476.         for (p = cmdline; *p == ' ' || *p == '\t'; p++)
  477.                 ;
  478.         q = cmdname;
  479.         while (*p        && *p != ';'  && *p != '='  &&
  480.                    *p != ' ' && *p != '\t' && *p != '\n')
  481.                 *q++ = *p++;
  482.         *q = '\0';
  483.  
  484.         if (!*cmdname)
  485.                 return (CMD_END);       /* Skip over blank lines and comments */
  486.  
  487.         /*
  488.          *              Now skip over any whitespace until we find the next parameter
  489.          */
  490.         while (*p == ' ' || *p == '=' || *p == '\t' || *p == '\n')
  491.                 p++;
  492.         q = param;
  493.         if (*p == '\"') {
  494.                 /*
  495.                  *              Got a quoted string .. copy everything inside the quotes
  496.                  */
  497.                 p++;
  498.                 while (*p && *p != '\n' && *p != '\"')
  499.                         *q++ = *p++;
  500.                 *q = '\0';
  501.         } else {
  502.                 /*
  503.                  *              Not a quoted string .. copy everything to end of line
  504.                  *              or semicolon, excluding any trailing spaces.
  505.                  */
  506.                 while (*p && *p != '\n' && *p != ';')
  507.                         *q++ = *p++;
  508.                 while (--q >= param && (*q == ' ' || *q == '\n' || *q == '\t'))
  509.                         ;
  510.                 *++q = '\0';
  511.                 if (q == param)
  512.                         q = NULL;
  513.         }
  514.  
  515.         /*
  516.          *              Finally, if we got no specific parameter, check if the
  517.          *              command beings with "No" -- if so, then assume the
  518.          *              parameter is boolean instead and set accordingly
  519.          */
  520.         *boolvalue = 1;
  521.         if (!q) {
  522.                 if (strnicmp(cmdname, "no", 2) == 0) {
  523.                         *boolvalue = 0;
  524.                         cmdname   += 2;
  525.                 }
  526.         } else {
  527.                 if (    stricmp(param, "off") == 0      ||
  528.                                 stricmp(param, "no")  == 0      ||
  529.                                 stricmp(param, "0")   == 0)
  530.                 {
  531.                         *boolvalue = 0;
  532.                 }
  533.         }
  534.  
  535.         /*
  536.          *              Now locate identifier which matches command
  537.          */
  538.         for (cmd = CommandTable; cmd->cmdid != CMD_END; cmd++)
  539.                 if (stricmp(cmd->name, cmdname) == 0)
  540.                         break;
  541.         
  542.         cid = cmd->cmdid;
  543.         if (cid == CMD_END)
  544.                 return (CMD_UNKNOWN);
  545.  
  546.         *pcmd = cmd;
  547.         if (cmd->numparms > 0 && !q)
  548.                 return (CMD_NOPARAM);
  549.         
  550.         return (cid);
  551. }
  552.  
  553. /*
  554.  *              ExecCommand(cmd, mode, set)
  555.  *
  556.  *              Interprets the given command and executes it. cmd points to the
  557.  *              command string which is one of the following forms:
  558.  *
  559.  *                      command
  560.  *                      command=value
  561.  *                      setting
  562.  *                      nosetting
  563.  *                      setting=on
  564.  *                      setting=off
  565.  *      
  566.  *              The "setting" commands are used to toggle the various boolean
  567.  *              settings that can be accessed through the requesters.
  568.  *
  569.  *              mode is the place where the setting occurs. This will be one of
  570.  *              MODE_REXX, MODE_SETTINGS, MODE_CMDLINE or MODE_TOOLTYPE, depending
  571.  *              on where the command being executed originated from. In some cases,
  572.  *              this affects how the command is executed.
  573.  *
  574.  *              set is a pointer to a copy of the current settings (NOT the actual
  575.  *              settings!) This copy is updated to reflect the changes. The intention
  576.  *              is that you can call ExecCommand() multiple times with the same
  577.  *              copy, and then finally call InstallSettings() at the end to make
  578.  *              the new settings take effect. This way, only a single update
  579.  *              needs to be done for an entire configuration file.
  580.  *
  581.  *              The global UpdateFlags should be initialised to 0 before the first
  582.  *              call, and then passed to InstallSettings() at the end -- it will
  583.  *              contain the appropriate combination of SET_??? flags to indicate
  584.  *              what settings actually changed.
  585.  *
  586.  *              Returns EXEC_OKAY for success, EXEC_FAIL for failure, or EXEC_UNKNOWN
  587.  *              if the command couldn't be understood.
  588.  */
  589. int ExecCommand(char *cmdline, int mode, Settings *set)
  590. {
  591.         APTR oldwinptr = *TaskWindowPtr;
  592.         struct Command *cmd;            /* Pointer to command                                           */
  593.         char cmdname[100];                      /* Storage area for command                             */
  594.         char parambuf[100];                     /* Storage for parameters                                       */
  595.         char *param;                            /* Pointer to parameters                                        */
  596.         int      boolvalue;                             /* for settings: either 1 or 0                          */
  597.         int  success = EXEC_OKAY;       /* Default return value                                         */
  598.         int  cid;
  599.         int  val;
  600.  
  601.         cid = ParseCommand(cmdline, cmdname, parambuf, &boolvalue, &cmd);
  602.         switch (cid) {
  603.                 case CMD_END:           return (EXEC_OKAY);
  604.                 case CMD_UNKNOWN:       return (EXEC_UNKNOWN);
  605.                 case CMD_NOPARAM:       return (EXEC_NOPARAM);
  606.         }
  607.  
  608.         UpdateFlags |= cmd->changemask;
  609.         param = parambuf;
  610.         
  611.         /*
  612.          *              Okay, got ourselves a valid command. Now interpret it.
  613.          */
  614.         if (cid <= MAX_BOOL_CMD) {
  615.                 /*
  616.                  *              Got a boolean option to update
  617.                  */
  618.                 set->Func.Opts[cid] = boolvalue;
  619.                 return (EXEC_OKAY);
  620.         }
  621.  
  622.         switch (cid) {
  623.                 case CMD_LANGUAGE:
  624.                         strcpy(Language, param);
  625.                         break;
  626.  
  627.                 case CMD_SETTINGS:
  628.                         strcpy(DefaultConfigName, param);
  629.                         strcpy(ConfigFileName, param);
  630.                         break;
  631.  
  632.                 case CMD_LOADDEFSETTINGS:
  633.                         success = LoadConfig(DefaultConfigName, mode, set);
  634.                         break;
  635.  
  636.                 case CMD_SAVEDEFSETTINGS:
  637.                         success = SaveConfig(DefaultConfigName, SAVE_NOICON);
  638.                         break;
  639.  
  640.                 case CMD_LOADSETTINGS:
  641.                         success = LoadConfig(param, mode, set);
  642.                         break;
  643.  
  644.                 case CMD_SAVESETTINGS:
  645.                         success = SaveConfig(param, SAVE_ICON);
  646.                         break;
  647.  
  648.                 case CMD_HELP:
  649.                 {
  650.                         char helpmsg[100];
  651.  
  652.                         /*
  653.                          *              We install the current settings first, to ensure
  654.                          *              that things like the default public screen are
  655.                          *              correctly set up before we open help.
  656.                          */
  657.                         if (UpdateFlags) {
  658.                                 InstallSettings(set, UpdateFlags);
  659.                                 UpdateFlags = 0;
  660.                                 *set = CurSettings;
  661.                         }
  662.                         if (*param)
  663.                                 mysprintf(helpmsg, "LINK %s\n", param);
  664.                         else
  665.                                 strcpy(helpmsg, MSG(MSG_LINK_MAIN));
  666.                         ShowAGuide(helpmsg);
  667.                         break;
  668.                 }
  669.  
  670.                 case CMD_SHOWGADGETS:   set->ShowGadgets   =  boolvalue;        break;
  671.                 case CMD_HIDEGADGETS:   set->ShowGadgets   = !boolvalue;        break;
  672.                 case CMD_SHOWSTATUS:    set->ShowStatus    =  boolvalue;        break;
  673.                 case CMD_HIDESTATUS:    set->ShowStatus    = !boolvalue;        break;
  674.                 case CMD_AUTOOPEN:              set->AutoOpenMain  =  boolvalue;        break;
  675.                 case CMD_DISABLEWHENHIDDEN: set->DisableWhenHidden = boolvalue; break;
  676.                 case CMD_CREATEICONS:   set->MakeIcons     =  boolvalue;        break;
  677.                 case CMD_SIMPLEREFRESH: set->SimpleRefresh =  boolvalue;        break;
  678.                 case CMD_SMARTREFRESH:  set->SimpleRefresh = !boolvalue;        break;
  679.                 case CMD_LEFTALIGNED:   set->RightAlign    = !boolvalue;        break;
  680.                 case CMD_RIGHTALIGNED:  set->RightAlign    =  boolvalue;        break;
  681.                 case CMD_TEXTSPACING:   
  682.                         val = *param - '0';
  683.                         if (val < 0 || val > 2)
  684.                                 return (EXEC_FAIL);
  685.                         set->TextSpacing = val;
  686.                         break;
  687.  
  688.                 case CMD_ROWQUALIFIER:
  689.                         return MatchParam(&set->RowQualifier, param, Names_RowQualifier);
  690.  
  691.                 case CMD_FUNCTIONS:
  692.                         /*
  693.                          *              Set or clear the function table according to the
  694.                          *              parameters
  695.                          */
  696.                 {
  697.                         unsigned char functype;
  698.                         int low  = FIRST_SYS_GADGET;
  699.                         int high = LAST_DOS_GADGET;
  700.                         int bool = 1;
  701.                         int i;
  702.  
  703.                         if (MatchParam(&functype, param, Names_Functions) == EXEC_FAIL)
  704.                                 return (EXEC_FAIL);
  705.  
  706.                         switch (functype) {
  707.                                 case FUNC_ALL:           break;                         /* Use defaults */
  708.                                 case FUNC_NONE:          bool = 0; break;
  709.                                 case FUNC_ALLDOS:        low  = FIRST_DOS_GADGET;                       break;
  710.                                 case FUNC_NODOS:         low  = FIRST_DOS_GADGET; bool = 0; break;
  711.                                 case FUNC_ALLSYSTEM: high = LAST_SYS_GADGET;                    break;
  712.                                 case FUNC_NOSYSTEM:      high = LAST_SYS_GADGET;  bool = 0; break;
  713.                         }
  714.                         for (i = low; i <= high; i++)
  715.                                 set->Func.Opts[i] = bool;
  716.                         break;
  717.                 }
  718.  
  719.                 case CMD_COPYWINDOW:
  720.                         DisableAllWindows();
  721.                         success = SaveBuffer(SAVEBUF_WINDOW, SAVEBUF_CLIPBOARD,
  722.                                                                  SAVEBUF_OVERWRITE);
  723.                         EnableAllWindows();
  724.                         break;
  725.                                                                 /* Fallthrough */
  726.                 case CMD_COPYBUFFER:
  727.                         DisableAllWindows();
  728.                         success = SaveBuffer(SAVEBUF_ALL, SAVEBUF_CLIPBOARD,
  729.                                                                  SAVEBUF_OVERWRITE);
  730.                         EnableAllWindows();
  731.                         break;
  732.  
  733.                 case CMD_SAVEWINDOW:
  734.                         DisableAllWindows();
  735.                         success = SaveBuffer(SAVEBUF_WINDOW, param, SAVEBUF_OVERWRITE);
  736.                         EnableAllWindows();
  737.                         break;
  738.  
  739.                 case CMD_SAVEBUFFER:
  740.                         DisableAllWindows();
  741.                         success = SaveBuffer(SAVEBUF_ALL, param, SAVEBUF_OVERWRITE);
  742.                         EnableAllWindows();
  743.                         break;
  744.                         
  745.                 case CMD_CXPRI:
  746.                         CommodityPriority = atoi(param);
  747.                         if (HotKeyActive) {
  748.                                 /*
  749.                                  *              Reinstall commodity to take advantage of the
  750.                                  *              updated priority
  751.                                  */
  752.                                 InstallHotKey(CurSettings.Setup.HotKey);
  753.                         }
  754.                         break;
  755.  
  756.                 case CMD_ICONPOS:
  757.                         success = ParseTwoNums(param, &set->IconPosLeft, &set->IconPosTop);
  758.                         break;
  759.  
  760.                 case CMD_HIDE:
  761.                 case CMD_SHOW:
  762.                         /*
  763.                          *              Install all settings modified so far
  764.                          */
  765.                         if (UpdateFlags) {
  766.                                 InstallSettings(set, UpdateFlags);
  767.                                 UpdateFlags = 0;
  768.                                 *set = CurSettings;
  769.                         }
  770.                         /*
  771.                          *              We allow both of these so that NOSHOW and NOHIDE
  772.                          *              will also work, as well as SHOW=YES and HIDE=NO
  773.                          *              In particular, CX_Popup=Yes and CX_Popup=No will
  774.                          *              work as expected.
  775.                          */
  776.                         if ((boolvalue && cid == CMD_SHOW) ||
  777.                                                                                 (!boolvalue && cid == CMD_HIDE)) {
  778.                                 /*
  779.                                  *              Showing SnoopDos. Install all settings changed
  780.                                  *              so far, so that they'll be in effect when the window
  781.                                  *              is open (especially font changes)
  782.                                  */
  783.                                 success = ShowSnoopDos();
  784.                                 HideOnStartup = 0;
  785.                         } else {
  786.                                 HideSnoopDos();
  787.                                 HideOnStartup = 1;
  788.                         }
  789.                         break;
  790.  
  791.                 case CMD_OPENFORMAT:
  792.                 case CMD_OPENFUNCTION:
  793.                 case CMD_OPENSETUP:
  794.                                 /*
  795.                                  *              Install the current settings, so that they take
  796.                                  *              effect before the window is opened (font changes
  797.                                  *              and the like).
  798.                                  */
  799.                                 if (UpdateFlags) {
  800.                                         InstallSettings(set, UpdateFlags);
  801.                                         UpdateFlags = 0;
  802.                                         *set = CurSettings;
  803.                                 }
  804.                                 switch (cid) {
  805.                                         case CMD_OPENFORMAT:    success = OpenFormatWindow();
  806.                                                                                         break;
  807.                                         case CMD_OPENFUNCTION:  success = OpenFunctionWindow();
  808.                                                                                         break;
  809.                                         case CMD_OPENSETUP:             success = OpenSettingsWindow();
  810.                                                                                         break;
  811.                                 }
  812.                                 break;
  813.  
  814.                 case CMD_CLOSEFORMAT:           CloseFormatWindow();                    break;
  815.                 case CMD_CLOSEFUNCTION:         CloseFunctionWindow();                  break;
  816.                 case CMD_CLOSESETUP:            CloseSettingsWindow();                  break;
  817.  
  818.                 case CMD_QUIT:
  819.                         if (mode != MODE_SETTINGS)
  820.                                 QuitFlag = 1;
  821.                         else
  822.                                 success = EXEC_FAIL;
  823.                         break;
  824.                         
  825.                 case CMD_SINGLESTEP:            SingleStep();                                           break;
  826.  
  827.                 case CMD_PAUSE:
  828.                 case CMD_DISABLE:
  829.                 case CMD_UNPAUSE:
  830.                 case CMD_ENABLE:
  831.                         /*
  832.                          *              We treat these four together so we can account for
  833.                          *              all the different boolean verisons (Disable=Yes,
  834.                          *              Enable=No, UnPause=Yes, Pause=No, etc.)
  835.                          */
  836.                         if ((cid == CMD_DISABLE && boolvalue) ||
  837.                                 (cid == CMD_ENABLE && !boolvalue))
  838.                         {
  839.                                 SetMonitorMode(MONITOR_DISABLED);
  840.                         } else if ((cid == CMD_PAUSE && boolvalue) ||
  841.                                            (cid == CMD_UNPAUSE && !boolvalue))
  842.                         {
  843.                                 SetMonitorMode(MONITOR_PAUSED);
  844.                         } else
  845.                                 SetMonitorMode(MONITOR_NORMAL);
  846.                         break;
  847.  
  848.                 case CMD_OPENLOG:
  849.                 case CMD_APPENDLOG:
  850.                         /*
  851.                          *              For these two, we make any current settings take effect,
  852.                          *              so that things like default file buffering mode will be
  853.                          *              activated.
  854.                          */
  855.                         if (UpdateFlags) {
  856.                                 InstallSettings(set, UpdateFlags);
  857.                                 UpdateFlags = 0;
  858.                                 *set = CurSettings;
  859.                         }
  860.                         if (cid == CMD_OPENLOG)
  861.                                 success = OpenLog(LOGMODE_OVERWRITE, param);
  862.                         else
  863.                                 success = OpenLog(LOGMODE_APPEND, param);
  864.                         break;
  865.  
  866.                 case CMD_OPENSERIALLOG:
  867.                         success = OpenLog(LOGMODE_SERIALPORT, param);
  868.                         break;
  869.  
  870.                 case CMD_CLOSELOG:
  871.                         CloseLog();
  872.                         break;
  873.  
  874.                 case CMD_ADDLOG:
  875.                         /*
  876.                          *              Output a user comment to the specified logfile
  877.                          */
  878.                         strcat(param, "\n");
  879.                         WriteLog(param);
  880.                         break;
  881.  
  882.                 case CMD_FLUSHLOG:
  883.                         /*
  884.                          *              Flush the current contents of the log
  885.                          */
  886.                         WriteLog(NULL);
  887.                         break;
  888.  
  889.                 case CMD_HIDEMETHOD: return MatchParam(&set->Setup.HideMethod,  param,
  890.                                                                                            Names_HideMethod);
  891.                 case CMD_SCREENTYPE: return MatchParam(&set->Setup.ScreenType,  param,
  892.                                                                                            Names_ScreenType);
  893.                 case CMD_LOGMODE:        return MatchParam(&set->Setup.LogMode,         param,
  894.                                                                                            Names_LogMode);
  895.                 case CMD_FILEIOTYPE: return MatchParam(&set->Setup.FileIOType,  param,
  896.                                                                                            Names_FileIOType);
  897.  
  898.                 case CMD_BUFFERSIZE:
  899.                         val = atoi(param);
  900.                         if (val > 1)
  901.                                 set->Setup.BufferSize = val;
  902.                         break;
  903.  
  904.                 case CMD_WINDOWWIDTH:
  905.                         SetMainWindowWidth(atoi(param));        /* 0 is supported */
  906.                         break;
  907.  
  908.                 case CMD_STACKLIMIT:
  909.                         if (*param < '0' || *param > '9')
  910.                                 return (EXEC_FAIL);
  911.                         set->StackLimit = atoi(param);
  912.                         break;
  913.  
  914.                 case CMD_PATCHRAMLIB:   break;  /* Actually handled in ParseStartup */
  915.  
  916.                 case CMD_FORMAT:                strcpy(set->Setup.BufferFormat,  param); break;
  917.                 case CMD_LOGFORMAT:
  918.                         if (stricmp(param, "none") == 0)
  919.                                 *param = '\0';
  920.                         strcpy(set->Setup.LogfileFormat, param); break;
  921.                         break;
  922.  
  923.                 case CMD_HOTKEY:                strcpy(set->Setup.HotKey,                param); break;
  924.                 case CMD_SCREENNAME:    strcpy(set->Setup.ScreenName,    param); break;
  925.                 case CMD_LOGNAME:               strcpy(set->Setup.LogFile,               param);
  926.                                                                 *TaskWindowPtr = (APTR)-1;
  927.                                                                 if (IsFileSystem(set->Setup.LogFile))
  928.                                                                         strcpy(ChosenLogName, param);
  929.                                                                 *TaskWindowPtr = oldwinptr;
  930.                                                                 break;
  931.  
  932.                 case CMD_MATCHNAME:     strcpy(set->Func.Pattern,                param); break;
  933.                 case CMD_WINDOWFONT:
  934.                         return ParseFontName(param, set->Setup.WindowFont,
  935.                                                                                 &set->Setup.WinFontSize);
  936.                 case CMD_BUFFERFONT:
  937.                         return ParseFontName(param, set->Setup.BufferFont,
  938.                                                                                 &set->Setup.BufFontSize);
  939.  
  940.                 case CMD_MAINSIZE:
  941.                         success = ParseTwoNums(param, &set->MainWinWidth,
  942.                                                                               &set->MainWinHeight);
  943.                         if (success && mode != MODE_SETTINGS && MainWindow)
  944.                                 SizeWindow(MainWindow, set->MainWinWidth - MainWindow->Width,
  945.                                                                            set->MainWinHeight- MainWindow->Height);
  946.                         break;
  947.  
  948.                 case CMD_MAINPOS:
  949.                         success = ParseTwoNums(param, &set->MainWinLeft, &set->MainWinTop);
  950.                         if (success && mode != MODE_SETTINGS && MainWindow)
  951.                                 MoveWindow(MainWindow, set->MainWinLeft - MainWindow->LeftEdge,
  952.                                                                            set->MainWinTop  - MainWindow->TopEdge);
  953.                         break;
  954.  
  955.                 case CMD_FORMPOS:
  956.                         success = ParseTwoNums(param, &set->FormWinLeft, &set->FormWinTop);
  957.                         if (success && mode != MODE_SETTINGS && FormWindow)
  958.                                 MoveWindow(FormWindow, set->FormWinLeft - FormWindow->LeftEdge,
  959.                                                                            set->FormWinTop  - FormWindow->TopEdge);
  960.                         break;
  961.  
  962.                 case CMD_FUNCPOS:
  963.                         success = ParseTwoNums(param, &set->FuncWinLeft, &set->FuncWinTop);
  964.                         if (success && mode != MODE_SETTINGS && FuncWindow)
  965.                                 MoveWindow(FuncWindow, set->FuncWinLeft - FuncWindow->LeftEdge,
  966.                                                                            set->FuncWinTop  - FuncWindow->TopEdge);
  967.                         break;
  968.  
  969.                 case CMD_SETPOS:
  970.                         success = ParseTwoNums(param, &set->SetupWinLeft,
  971.                                                                                   &set->SetupWinTop);
  972.                         if (success && mode != MODE_SETTINGS && SetWindow)
  973.                                 MoveWindow(SetWindow, set->SetupWinLeft - SetWindow->LeftEdge,
  974.                                                                           set->SetupWinTop  - SetWindow->TopEdge);
  975.                         break;
  976.  
  977.                 case CMD_TASKPRI:
  978.                         val = atoi(param);
  979.                         if ((val == 0 && *param != '0') || val < -20 || val > 20)
  980.                                 return (EXEC_FAIL);
  981.                         SetTaskPri(SysBase->ThisTask, val);
  982.                         if (MainWindow)
  983.                                 SetMenuOptions();
  984.                         break;
  985.  
  986.                 case CMD_CLEARBUFFER:
  987.                         ClearWindowBuffer();
  988.                         break;
  989.  
  990.                 case CMD_GOTO:
  991.                         val = atoi(param);
  992.                         if (val != 0) {
  993.                                 val += BaseSeq;         /* Get real start position */
  994.                                 if (val > TopSeq)
  995.                                         DoArrowScrolling(GID_DOWNARROW, val - TopSeq);
  996.                                 else
  997.                                         DoArrowScrolling(GID_UPARROW, TopSeq - val);
  998.                         } else
  999.                                 success = EXEC_FAIL;
  1000.                         break;
  1001.  
  1002.                 case CMD_SCROLLUP:
  1003.                 case CMD_SCROLLDOWN:
  1004.                         val = atoi(param);
  1005.                         if (!val)
  1006.                                 val = 1;
  1007.                         if (cid == CMD_SCROLLUP)
  1008.                                 DoArrowScrolling(GID_UPARROW, val);
  1009.                         else
  1010.                                 DoArrowScrolling(GID_DOWNARROW, val);
  1011.                         break;
  1012.         }
  1013.         return (success ? EXEC_OKAY : EXEC_FAIL);
  1014. }
  1015.  
  1016. /*
  1017.  *              GetFontDesc(fontdesc, fontname, size)
  1018.  *
  1019.  *              Builds a a string from the supplied fontname and size and stores
  1020.  *              it in fontdesc. Returns a pointer to the new string.
  1021.  *
  1022.  *              For example, name="courier.font" and size=13 will return the
  1023.  *              string "courier 13";
  1024.  *
  1025.  *              In the event that the fontname is invalid, the string "Default"
  1026.  *              is returned instead.
  1027.  */
  1028. char *GetFontDesc(char *fontdesc, char *fontname, int size)
  1029. {
  1030.         char *p;
  1031.  
  1032.         if (!fontname || !*fontname)
  1033.                 return ("Default");
  1034.  
  1035.         strcpy(fontdesc, fontname);
  1036.         p = strchr(fontdesc, '.');
  1037.         if (!p)
  1038.                 p = fontdesc + strlen(fontdesc);
  1039.         
  1040.         mysprintf(p, " %ld", size);
  1041.         return (fontdesc);
  1042. }
  1043.  
  1044. /*
  1045.  *              SaveConfig(filename, saveicon)
  1046.  *
  1047.  *              Writes the current configuration to the named disk file. Returns
  1048.  *              1 for success, 0 for failure.
  1049.  *
  1050.  *              saveicon is SAVE_ICON if an icon should be saved and CreateIcos
  1051.  *              is true, or SAVE_NOICON if an icon should never be saved.
  1052.  */
  1053. int SaveConfig(char *filename, int saveicon)
  1054. {
  1055.         char tempdesc[MAX_SHORT_LEN];
  1056.         SetupSettings *setup = &CurSettings.Setup;
  1057.         BPTR file;
  1058.         int i;
  1059.  
  1060.         mysprintf(StatusLineText, MSG(MSG_STATUS_SAVESET), filename);
  1061.         ShowStatus(StatusLineText);
  1062.  
  1063.         DisableAllWindows();
  1064.         RecordWindowSizes();
  1065.         file = Open(filename, MODE_NEWFILE);
  1066.         if (!file) {
  1067.                 EnableAllWindows();
  1068.                 UpdateStatus();
  1069.                 return (0);
  1070.         }
  1071.         FPrintf(file, "%s\n;\n;    %s\n;\n;    Settings file\n;\n",
  1072.                         ConfigID, Version);
  1073.  
  1074. #define NM(x)                   CmdNames[CMD_##x]
  1075. #define PF1(s,p)                FPrintf(file, s, p)
  1076. #define PF2(s,p1,p2)    FPrintf(file, s, p1, p2)
  1077.  
  1078.         /*
  1079.          *              First of all, write out the function settings
  1080.          */
  1081.         for (i = 1; i <= MAX_BOOL_CMD; i++) {
  1082.                 if (*CmdNames[i]) {
  1083.                         if (CurSettings.Func.Opts[i])
  1084.                                 PF1("%s\n",     CmdNames[i]);
  1085.                         else
  1086.                                 PF1("No%s\n", CmdNames[i]);
  1087.                 }
  1088.         }
  1089.         /*
  1090.          *              Now write out all the variable settings
  1091.          */
  1092.         PF2(";\n%s=\"%s\"\n",NM(MATCHNAME),     CurSettings.Func.Pattern);
  1093.         PF2("%s=%s\n",          NM(HIDEMETHOD), Names_HideMethod[setup->HideMethod]);
  1094.         PF2("%s=%s\n",          NM(SCREENTYPE), Names_ScreenType[setup->ScreenType]);
  1095.         PF2("%s=%s\n",          NM(LOGMODE),    Names_LogMode[setup->LogMode]);
  1096.         PF2("%s=%s\n",          NM(FILEIOTYPE), Names_FileIOType[setup->FileIOType]);
  1097.         PF2("%s=%ld\n",         NM(BUFFERSIZE), setup->BufferSize);
  1098.         PF2("%s=\"%s\"\n",      NM(HOTKEY),             setup->HotKey);
  1099.         PF2("%s=\"%s\"\n",      NM(SCREENNAME), setup->ScreenName);
  1100.         PF2("%s=\"%s\"\n",      NM(LOGNAME),    setup->LogFile);
  1101.         PF2("%s=\"%s\"\n",      NM(WINDOWFONT), GetFontDesc(tempdesc,
  1102.                                                                                                         setup->WindowFont,
  1103.                                                                                                         setup->WinFontSize));
  1104.         PF2("%s=\"%s\"\n",      NM(BUFFERFONT), GetFontDesc(tempdesc,
  1105.                                                                                                         setup->BufferFont,
  1106.                                                                                                         setup->BufFontSize));
  1107.         PF2("%s=\"%s\"\n",      NM(FORMAT),     setup->BufferFormat);
  1108.         PF2("%s=\"%s\"\n",      NM(LOGFORMAT),  setup->LogfileFormat);
  1109.  
  1110.         PF2("%s=%ld\n",         NM(TEXTSPACING), CurSettings.TextSpacing);
  1111.  
  1112.         PF1("%s\n",                     CurSettings.SimpleRefresh ? NM(SIMPLEREFRESH) :
  1113.                                                                                                     NM(SMARTREFRESH));
  1114.         PF1("%s\n",                     CurSettings.RightAlign    ? NM(RIGHTALIGNED) :
  1115.                                                                                                     NM(LEFTALIGNED));
  1116.         PF2("%s=%s\n",      NM(ROWQUALIFIER), Names_RowQualifier[RowQual]);
  1117.         PF1("%s\n",                     CurSettings.ShowStatus    ? NM(SHOWSTATUS)        :
  1118.                                                                                                     NM(HIDESTATUS));
  1119.         PF1("%s\n",                     CurSettings.ShowGadgets   ? NM(SHOWGADGETS)   :
  1120.                                                                                                     NM(HIDEGADGETS));
  1121.         PF2("%s%s\n",           (AutoOpen ? "" : "No"), NM(AUTOOPEN));
  1122.         PF2("%s%s\n",       (DisableOnHide ? "" : "No"), NM(DISABLEWHENHIDDEN));
  1123.         PF2("%s%s\n",           (CurSettings.MakeIcons ? "" : "No"), NM(CREATEICONS));
  1124.         
  1125.         FPrintf(file, "%s=%ld,%ld\n", NM(MAINPOS),      CurSettings.MainWinLeft,
  1126.                                                                                                 CurSettings.MainWinTop);
  1127.         FPrintf(file, "%s=%ld,%ld\n", NM(MAINSIZE),     CurSettings.MainWinWidth,
  1128.                                                                                                 CurSettings.MainWinHeight);
  1129.         FPrintf(file, "%s=%ld,%ld\n", NM(FORMPOS),      CurSettings.FormWinLeft,
  1130.                                                                                                 CurSettings.FormWinTop);
  1131.         FPrintf(file, "%s=%ld,%ld\n", NM(FUNCPOS),      CurSettings.FuncWinLeft,
  1132.                                                                                                 CurSettings.FuncWinTop);
  1133.         FPrintf(file, "%s=%ld,%ld\n", NM(SETPOS),       CurSettings.SetupWinLeft,
  1134.                                                                                                 CurSettings.SetupWinTop);
  1135.         FPrintf(file, "%s=%ld,%ld\n", NM(ICONPOS),  CurSettings.IconPosLeft,
  1136.                                                                                                 CurSettings.IconPosTop);
  1137.         FPrintf(file, "%s=%ld\n",     NM(STACKLIMIT), CurSettings.StackLimit);
  1138.         FPrintf(file, "%s=%ld\n",     NM(TASKPRI),
  1139.                                                                   SysBase->ThisTask->tc_Node.ln_Pri);
  1140.         Close(file);
  1141.         if (CreateIcons && saveicon != SAVE_NOICON)
  1142.                 WriteIcon(filename);
  1143.         EnableAllWindows();
  1144.         UpdateStatus();
  1145.         GotLastSaved = 1;               /* Indicate "Last Saved" can now be performed */
  1146.         return (1);
  1147. }
  1148.  
  1149. /*
  1150.  *              LoadConfig(filename, mode, set)
  1151.  *
  1152.  *              Attempts to load the specified configuration file into memory.
  1153.  *              Returns 1 for success (having executed all the commands, and updated
  1154.  *              windows etc. as appropriate) or 0 for failure (couldn't open file).
  1155.  *
  1156.  *              To prevent infinite loops, we only allow three levels of nested
  1157.  *              configuration files (i.e. a maximum of three recursive calls to
  1158.  *              LoadConfig)
  1159.  *
  1160.  *              Normally, set is NULL. If non-NULL, then it represents a set
  1161.  *              of settings currently being updated. In this case, LoadConfig
  1162.  *              doesn't actually install the new settings when it's finished
  1163.  *              reading them, it merely updates the values in set with the
  1164.  *              new values and relies on the caller to set them later on.
  1165.  *
  1166.  *              The mode parameter indicates how we are being called -- from
  1167.  *              the CLI, Workbench, ARexx or internally. This is used to determine
  1168.  *              how error messages should be displayed (currently, messages will
  1169.  *              only be displayed in a CLI window).
  1170.  *
  1171.  *              New: we now support reading from an interactive file (CON:....)
  1172.  *              This allows the user to open a command window by trying to load
  1173.  *              a suitable CON: specification. Commands will be executed as soon
  1174.  *              as they arrive, and settings will be updated immediately.
  1175.  */
  1176. int LoadConfig(char *filename, int mode, Settings *set)
  1177. {
  1178.         static int nestcount;
  1179.  
  1180.         Settings newsettings;
  1181.         Settings *myset;
  1182.         int  interactive;
  1183.         int  linenum   = 0;
  1184.         int  retvalue  = EXEC_FAIL;
  1185.         BPTR errorfile = NULL;
  1186.         BPTR file;
  1187.         char linebuf[200];
  1188.  
  1189.         if (set == NULL) {
  1190.                 myset           = &newsettings;
  1191.                 *myset          = CurSettings;
  1192.                 UpdateFlags = 0;
  1193.         } else {
  1194.                 myset = set;
  1195.         }
  1196.         if (nestcount >= MAX_LOAD_NESTING)
  1197.                 return (EXEC_FAIL);
  1198.         nestcount++;
  1199.         
  1200.         DisableAllWindows();
  1201.         mysprintf(StatusLineText, MSG(MSG_STATUS_LOADSET), filename);
  1202.         ShowStatus(StatusLineText);
  1203.  
  1204.         file = Open(filename, MODE_OLDFILE);
  1205.         if (!file)
  1206.                 goto abort_load;
  1207.  
  1208.         /*
  1209.          *              If we're executing this command from a CLI, then display
  1210.          *              error messages in the CLI window, else don't display them
  1211.          *              at all.
  1212.          */
  1213.         if (mode == MODE_CMDLINE)
  1214.                 errorfile = Output();
  1215.  
  1216.         interactive = IsInteractive(file);
  1217.         if (interactive) {
  1218.                 errorfile = file;       /* Send errors to the command window */
  1219.         } else {
  1220.                 /*
  1221.                  *              If we're not loading settings from an interactive
  1222.                  *              window, then check that the first line of the file
  1223.                  *              contains the settings file identifier
  1224.                  */
  1225.                 if (!FGets(file, linebuf, 199)                                                  ||
  1226.                         strnicmp(linebuf, ConfigID, strlen(ConfigID)) != 0)
  1227.                 {
  1228.                         goto abort_load;
  1229.                 }
  1230.                 linenum++;
  1231.         }
  1232.  
  1233.         /*
  1234.          *              Now read in lines from the command file and execute them.
  1235.          */
  1236.         if (interactive) {
  1237.                 FPrintf(errorfile, "%s%s", MSG(MSG_CMD_HEADER), MSG(MSG_CMD_PROMPT));
  1238.                 Flush(errorfile);
  1239.         }
  1240.         while (FGets(file, linebuf, 199) != NULL) {
  1241.                 char *cmdline = linebuf;
  1242.                 char *q;
  1243.                 int result;
  1244.  
  1245.                 linenum++;
  1246.                 for (q = cmdline; *q && *q != '\n'; q++)
  1247.                         ;
  1248.                 if (*q)
  1249.                         *q++ = '\0';
  1250.         
  1251.                 while (*cmdline == ' ' || *cmdline == '\t')
  1252.                         cmdline++;
  1253.  
  1254.                 if (!*cmdline || *cmdline == ';')
  1255.                         continue;       /* Skip over lines with no text on them */
  1256.  
  1257.                 if (stricmp(cmdline, "exit") == 0)      /* Skip rest of file */
  1258.                         break;
  1259.  
  1260.                 if (interactive && *cmdline == '?') {
  1261.                         ShowCommands(errorfile);
  1262.                         goto show_prompt;
  1263.                 }
  1264.                         
  1265.                 /*
  1266.                  *              Now execute the command ... interactive commands are
  1267.                  *              executed internally, to allow QUIT to be executed.
  1268.                  */
  1269.                 result = ExecCommand(cmdline,
  1270.                                                          (interactive ? MODE_INTERNAL : MODE_SETTINGS),
  1271.                                                          myset);
  1272.                 if (QuitFlag)
  1273.                         break;
  1274.  
  1275.                 if (result == EXEC_OKAY) {
  1276.                         if (interactive) {
  1277.                                 /*
  1278.                                  *              For interactive commands, we update the
  1279.                                  *              settings at each step along the way so
  1280.                                  *              the user can see them taking effect.
  1281.                                  */
  1282.                                 InstallSettings(myset, UpdateFlags);
  1283.                                 UpdateFlags = 0;
  1284.                                 *myset = CurSettings;
  1285.                         }
  1286.                 } else if (errorfile) {
  1287.                         int msgid;
  1288.  
  1289.                         switch (result) {
  1290.                                 case EXEC_UNKNOWN:      msgid = MSG_CMD_UNKNOWN;        break;
  1291.                                 case EXEC_FAIL:         msgid = MSG_CMD_FAIL;           break;
  1292.                                 case EXEC_NOPARAM:      msgid = MSG_CMD_NOPARAM;        break;
  1293.                         }
  1294.                         if (!interactive)
  1295.                                 FPrintf(errorfile, "%s, line %ld: ", filename, linenum);
  1296.                         FPrintf(errorfile, MSG(msgid), cmdline);
  1297.                 }
  1298.  
  1299. show_prompt:
  1300.                 if (interactive) {
  1301.                         FPrintf(errorfile, MSG(MSG_CMD_PROMPT));
  1302.                         Flush(errorfile);
  1303.                 }
  1304.         }
  1305.         retvalue = EXEC_OKAY;
  1306.  
  1307.         if (interactive) {
  1308.                 /*
  1309.                  *              For interactive use, we clear any CTRL-C typed by
  1310.                  *              the user during usage; this avoids confusion since
  1311.                  *              the CTRL-C wouldn't have taken effect immediately
  1312.                  *              anyway.
  1313.                  */
  1314.                 CheckSignal(SIGBREAKF_CTRL_C);
  1315.         }
  1316.         /*
  1317.          *              If we just successfully loaded a file, it was probably the
  1318.          *              defaults file, so enable the "Last Saved" menu option (if it's
  1319.          *              not enabled, then it doesn't try to load a file since there was
  1320.          *              no file ever saved).
  1321.          */
  1322.         GotLastSaved = 1;
  1323.  
  1324. abort_load:
  1325.         if (file)
  1326.                 Close(file);
  1327.         nestcount--;
  1328.         if (set == NULL)
  1329.                 InstallSettings(myset, UpdateFlags);
  1330.  
  1331.         UpdateStatus();
  1332.         EnableAllWindows();
  1333.         return (retvalue);
  1334. }
  1335.  
  1336. /*
  1337.  *              InitRexxPort
  1338.  *
  1339.  *              Attempts to create SnoopDos's public port and initialise SnoopPort
  1340.  *              and RexxPortMask accordingly. If the port already exists, still
  1341.  *              returns TRUE but SnoopPort will be NULL.
  1342.  *
  1343.  *              If we can't create the port for some reason, returns FALSE.
  1344.  */             
  1345. int InitRexxPort(void)
  1346. {
  1347.         struct MsgPort *port;
  1348.  
  1349.         Forbid();
  1350.         port = FindPort(PORT_NAME);
  1351.         if (!port) {
  1352.                 SnoopPort = CreateMsgPort();
  1353.                 if (!SnoopPort) {
  1354.                         Permit();
  1355.                         return (FALSE);
  1356.                 }
  1357.                 SnoopPort->mp_Node.ln_Name = PORT_NAME;
  1358.                 SnoopPort->mp_Node.ln_Pri  = 1; /* Speed up searches */
  1359.                 AddPort(SnoopPort);
  1360.                 RexxPortMask = 1 << SnoopPort->mp_SigBit;
  1361.         }
  1362.         Permit();
  1363.         return (TRUE);
  1364. }
  1365.  
  1366. /*
  1367.  *              CleanupRexxPort()
  1368.  *
  1369.  *              Cleans up our SnoopDos port -- removes it from the public port
  1370.  *              list, and then replies to any messages it has outstanding. Call
  1371.  *              before exiting.
  1372.  */
  1373. void CleanupRexxPort(void)
  1374. {
  1375.         if (SnoopPort) {
  1376.                 struct RexxMsg *msg;
  1377.  
  1378.                 Forbid();
  1379.                 RemPort(SnoopPort);
  1380.                 while ((msg = (struct RexxMsg *)GetMsg(SnoopPort)) != NULL) {
  1381.                         msg->rm_Result1 = RC_FATAL;
  1382.                         msg->rm_Result2 = NULL;
  1383.                         ReplyMsg(msg);
  1384.                 }
  1385.                 Permit();
  1386.                 DeleteMsgPort(SnoopPort);
  1387.                 SnoopPort = NULL;
  1388.         }
  1389.         if (RemoteReplyPort) {
  1390.                 DeleteMsgPort(RemoteReplyPort);
  1391.                 RemoteReplyPort = NULL;
  1392.         }
  1393. }
  1394.  
  1395. /*
  1396.  *              HandleRexxMsgs()
  1397.  *
  1398.  *              Handles any new messages at our Rexx port
  1399.  */
  1400. void HandleRexxMsgs(void)
  1401. {
  1402.         Settings newsettings = CurSettings;
  1403.         struct RexxMsg *msg;
  1404.  
  1405.         UpdateFlags = 0;
  1406.         while ((msg = (struct RexxMsg *)GetMsg(SnoopPort)) != NULL) {
  1407.                 msg->rm_Result1 = RC_OK;
  1408.                 msg->rm_Result2 = NULL;
  1409.                 if ((msg->rm_Action & RXCODEMASK) == RXCOMM) {
  1410.                         /*
  1411.                          *              Got a valid ARexx message, now process it
  1412.                          */
  1413.                         switch (ExecCommand(msg->rm_Args[0], MODE_REXX, &newsettings)) {
  1414.                                 /*
  1415.                                  *              See include:rexx/errors.h for the meanings of
  1416.                                  *              these Rexx return codes
  1417.                                  */
  1418.                                 case EXEC_NOPARAM:      msg->rm_Result1 = 10; break;
  1419.                                 case EXEC_FAIL:         msg->rm_Result1 = 20; break;
  1420.                                 case EXEC_UNKNOWN:      msg->rm_Result1 = 30; break;
  1421.                         }
  1422.                 }
  1423.                 ReplyMsg(msg);
  1424.         }
  1425.         InstallSettings(&newsettings, UpdateFlags);
  1426. }
  1427.  
  1428. /*
  1429.  *              SendRemote(cmdline, mode)
  1430.  *
  1431.  *              Sends a command to a remote copy of SnoopDos running in the
  1432.  *              background. The mode is MODE_CMDLINE or MODE_TOOLTYPE. The
  1433.  *              difference is that for MODE_TOOLYPE, HIDE commands are ignored.
  1434.  *
  1435.  *              In both cases, the command is first checked against the command
  1436.  *              table to make sure it's valid. If it's invalid, then if the mode
  1437.  *              is MODE_CMDLINE, an appropriate error message is printed.
  1438.  */
  1439. void SendRemote(char *cmdline, int mode)
  1440. {
  1441.         struct Command *cmd;
  1442.         struct MsgPort *ourport;
  1443.         char cmdname[100];
  1444.         char param[100];
  1445.         int boolvalue;
  1446.         int cid;
  1447.  
  1448.         cid = ParseCommand(cmdline, cmdname, param, &boolvalue, &cmd);
  1449.         switch (cid) {
  1450.                 case CMD_UNKNOWN:
  1451.                         if (mode == MODE_CMDLINE)
  1452.                                 Printf(MSG(MSG_ERROR_CLI_UNKNOWN), cmdline);
  1453.                         return;
  1454.  
  1455.                 case CMD_NOPARAM:
  1456.                         if (mode == MODE_CMDLINE)
  1457.                                 Printf(MSG(MSG_ERROR_CLI_NOPARAM), cmdline);
  1458.                         return;
  1459.  
  1460.                 case CMD_HIDE:
  1461.                         /*
  1462.                          *              Don't send a HIDE command to the current SnoopDos if
  1463.                          *              it was in an icon's tooltypes
  1464.                          */
  1465.                         if (mode == MODE_TOOLTYPE)
  1466.                                 return;
  1467.                         break;
  1468.  
  1469.                 case CMD_END:
  1470.                         return;
  1471.         }
  1472.         
  1473.         /*
  1474.          *              Got a command that's okay to send. Now locate SnoopDos port
  1475.          *              and send it. We have to locate the port each time, in case
  1476.          *              the user quits the background copy suddenly.
  1477.          */
  1478.         if (!RemoteReplyPort) {
  1479.                 RemoteReplyPort = CreateMsgPort();
  1480.                 if (!RemoteReplyPort)
  1481.                         return;
  1482.         }
  1483.         Forbid();
  1484.         ourport = FindPort(PORT_NAME);
  1485.         if (ourport) {
  1486.                 struct RexxMsg msg;
  1487.  
  1488.                 msg.rm_Action                    = RXCOMM;
  1489.                 msg.rm_Args[0]                   = cmdline;
  1490.                 msg.rm_Node.mn_ReplyPort = RemoteReplyPort;
  1491.  
  1492.                 PutMsg(ourport, &msg);
  1493.                 WaitPort(RemoteReplyPort);
  1494.                 GetMsg(RemoteReplyPort);
  1495.                 Permit();
  1496.                 if (mode == MODE_CMDLINE && msg.rm_Result1 >= RC_ERROR)
  1497.                         Printf(MSG(MSG_ERROR_CLI_FAILED), cmdline);
  1498.         } else
  1499.                 Permit();
  1500. }
  1501.  
  1502. /*
  1503.  *              ShowCommands(file)
  1504.  *
  1505.  *              Prints a neatly formatted list of recognised commands to
  1506.  *              the specified output file.
  1507.  */
  1508. void ShowCommands(BPTR file)
  1509. {
  1510.         int i;
  1511.         int numrows = (NUM_CMDNAMES + 3) / 4;
  1512.  
  1513.         FPrintf(file, MSG(MSG_CLI_HELPBANNER));
  1514.         for (i = 0; i < numrows; i++) {
  1515.                 int j;
  1516.  
  1517.                 if (CheckSignal(SIGBREAKF_CTRL_C)) {
  1518.                         FPrintf(file, "^C\n");
  1519.                         break;
  1520.                 }
  1521.                 for (j = i; j < NUM_CMDNAMES; j += numrows) {
  1522.                         char *pmsg = (CommandTable[j].numparms > 0) ? "*" : " ";
  1523.                         char *cmsg = CommandTable[j].name;
  1524.  
  1525.                         if (j < (NUM_CMDNAMES - numrows))
  1526.                                 FPrintf(file, "%s%-18s", pmsg, cmsg);
  1527.                         else
  1528.                                 FPrintf(file, "%s%s", pmsg, cmsg);
  1529.                 }
  1530.                 FPrintf(file, "\n");
  1531.         }
  1532. }
  1533.  
  1534. /*
  1535.  *              ParseStartupOpts()
  1536.  *
  1537.  *              Handles the startup options, either on the command line or via
  1538.  *              the tooltypes, and sets the default options accordingly.
  1539.  *
  1540.  *              We handle a couple of options specially (LOCALE and SETTINGS) since
  1541.  *              these must be set before doing anything else at all (we can't even
  1542.  *              print a meaningful error message without LOCALE, for example.)
  1543.  *
  1544.  *              After those, we read in our configuration file from disk, and then
  1545.  *              parse the remaining items which can thus override any of the options
  1546.  *              specified in the config file. This applies even to tooltypes, so if
  1547.  *              an icon has a certain option hardcoded into it, this will always
  1548.  *              override a config file with the same option set.
  1549.  *
  1550.  *              Normally, CLI and Tooltype options are only used to control things
  1551.  *              like opening a default logfile, set the Commodity priority or config
  1552.  *              file name, making SnoopDos start in the background, or automatically
  1553.  *              opening one or more windows.
  1554.  *
  1555.  *              As a final step, if we spot that we are not the main instance of
  1556.  *              SnoopDos, we send all the new commands to the background copy instead.
  1557.  *               We also signal the background copy to come to the foreground by
  1558.  *              default (Workbench) or if no other options are specified (CLI).
  1559.  *
  1560.  *              Returns TRUE for success, FALSE for failure.
  1561.  *
  1562.  */
  1563. int ParseStartupOpts(int argc, char **argv)
  1564. {
  1565.         struct Settings newset = DefaultSettings;
  1566.         struct DiskObject *IconCache[20];
  1567.         struct DiskObject *dobj = NULL;
  1568.         struct WBArg *wbarg;
  1569.         char msg[200];
  1570.         int success = 1;
  1571.         int maxargs;
  1572.         int i;
  1573.         int gotsettings = 0;            /* If true, settings keyword specified */
  1574.  
  1575.         /*
  1576.          *              We start off in a special disabled state (not 0, not 1)
  1577.          *              to ensure no events get monitored during our initialisation.
  1578.          *              We use a special state so that we can detect if the user
  1579.          *              specifies Disabled = Yes/No during startup.
  1580.          */
  1581.         Disabled = 2;           /* Start up in disabled state */
  1582.  
  1583.         if (WBenchMsg) {
  1584.                 /*
  1585.                  *              Starting up from Workbench.
  1586.                  */
  1587.                 if (!IconBase)
  1588.                         return (FALSE);
  1589.  
  1590.                 maxargs = min(WBenchMsg->sm_NumArgs, 20);
  1591.  
  1592.                 for (i = 0, wbarg = WBenchMsg->sm_ArgList; i < maxargs; i++, wbarg++) {
  1593.                         BPTR olddir;
  1594.  
  1595.                         IconCache[i] = NULL;
  1596.                         if (wbarg->wa_Lock && *wbarg->wa_Name) {
  1597.                                 olddir = CurrentDir(wbarg->wa_Lock);
  1598.                                 dobj   = GetDiskObject(wbarg->wa_Name);
  1599.                                 if (dobj) {
  1600.                                         char *param;
  1601.                                         
  1602.                                         param = FindToolType(dobj->do_ToolTypes,
  1603.                                                                                  CmdNames[CMD_SETTINGS]);
  1604.                                         if (param && *param) {
  1605.                                                 strcpy(DefaultConfigName, param);
  1606.                                                 gotsettings = 1;
  1607.                                         }
  1608.                                         param = FindToolType(dobj->do_ToolTypes,
  1609.                                                                                  CmdNames[CMD_LANGUAGE]);
  1610.                                         if (param && *param)
  1611.                                                 strcpy(Language, param);
  1612.  
  1613.                                         param = FindToolType(dobj->do_ToolTypes,
  1614.                                                                                  CmdNames[CMD_PATCHRAMLIB]);
  1615.                                         if (param && stricmp(param, "no") == 0)
  1616.                                                 NoPatchRamLib = 1;
  1617.  
  1618.                                         IconCache[i] = dobj;
  1619.                                 }
  1620.                                 CurrentDir(olddir);
  1621.                         }
  1622.                 }
  1623.         } else {
  1624.                 /*
  1625.                  *              Starting up from the CLI so scan the command line using
  1626.                  *              the passed-in arguments.
  1627.                  */
  1628.                 if (argc > 1) {
  1629.                         if (argv[1][0] == '-' || argv[1][0] == '?') {
  1630.                                 Printf(MSG(MSG_CLI_USAGE), CommodityTitle, argv[0]);
  1631.                                 return (FALSE);
  1632.                         }
  1633.                 }
  1634.  
  1635.                 /*
  1636.                  *              Do a prescan of the command line looking
  1637.                  *              for SETTINGS, LANGUAGE or PATCHRAMLIB, keywords.
  1638.                  */
  1639.                 for (i = 1; i < argc; i++) {
  1640.                         char cmdname[50];
  1641.                         char param[150];
  1642.                         char newcmd[200];
  1643.                         int boolvalue;
  1644.                         struct Command *cmd;
  1645.                         int cid;
  1646.  
  1647.                         cid = ParseCommand(argv[i], cmdname, param, &boolvalue, &cmd);
  1648.                         if (cid == CMD_NOPARAM && ((i + 1) < argc)) {
  1649.                                 /*
  1650.                                  *              Indicates we didn't get enough parameters for our
  1651.                                  *              command. Let's grab the next option off the command
  1652.                                  *              line instead and see if that makes sense.
  1653.                                  */
  1654.                                 mysprintf(newcmd, "%s %s", argv[i], argv[i+1]);
  1655.                                 cid = ParseCommand(newcmd, cmdname, param, &boolvalue, &cmd);
  1656.                                 i++;    /* Skip over next parameter */
  1657.                         }
  1658.                         switch (cid) {
  1659.                                 case CMD_SETTINGS:
  1660.                                         strcpy(DefaultConfigName, param);
  1661.                                         gotsettings = 1;
  1662.                                         break;
  1663.  
  1664.                                 case CMD_LANGUAGE:
  1665.                                         strcpy(Language, param);
  1666.                                         break;
  1667.  
  1668.                                 case CMD_PATCHRAMLIB:
  1669.                                         NoPatchRamLib = !boolvalue;
  1670.                                         break;
  1671.                         }
  1672.                 }
  1673.         }
  1674.  
  1675.         /*
  1676.          *              Now initialise locale according to the language chosen,
  1677.          *              and read in our default configuration file.
  1678.          */
  1679.         InitLocale(Language);
  1680.         InitMenus();
  1681.         /*
  1682.          *              Note that LoadConfig() and further ExecCommand() calls may
  1683.          *              cause the settings to be installed at any time, and UpdateFlags
  1684.          *              to be reset to null. Thus, it is important to ensure that
  1685.          *              we initialise them correctly in the first place.
  1686.          */
  1687.         UpdateFlags = SET_ALL;
  1688.         if (SnoopPort) {
  1689.                 /*
  1690.                  *              We only initialise our patches if we're the only task
  1691.                  *              running at the moment. We leave the initialisation
  1692.                  *              until now so that we can control whether or not our
  1693.                  *              ramlib patch gets installed.
  1694.                  */
  1695.                 if (!InitPatches()) {
  1696.                         if (WBenchMsg)
  1697.                                 ShowError(MSG(MSG_ERROR_INITPATCHES));
  1698.                         else
  1699.                                 Printf("%s\n", MSG(MSG_ERROR_INITPATCHES));
  1700.                         Cleanup(40);
  1701.                 }
  1702.                 if (!gotsettings) {
  1703.                         /*
  1704.                          *              If we haven't yet got a settings file, then try a number of
  1705.                          *              possible locations (in order of priority). If we find a
  1706.                          *              match, we overwrite the default config name with the new
  1707.                          *              name, for future use by LoadConfig and SaveConfig.
  1708.                          */
  1709.                         static char *defconfig[] = {
  1710.                                 "PROGDIR:" SETTINGS_BASENAME,
  1711.                                 "S:"       SETTINGS_BASENAME,
  1712.                                 "ENVARC:"  SETTINGS_BASENAME,
  1713.                                 NULL
  1714.                         };
  1715.                         APTR oldwinptr = *TaskWindowPtr;
  1716.                         char **pdefname;
  1717.  
  1718.                         *TaskWindowPtr = (APTR)-1;
  1719.                         for (pdefname = defconfig; *pdefname; pdefname++) {
  1720.                                 BPTR lk = Lock(*pdefname, ACCESS_READ);
  1721.  
  1722.                                 if (lk) {
  1723.                                         UnLock(lk);
  1724.                                         break;
  1725.                                 }
  1726.                         }
  1727.                         if (!*pdefname) {
  1728.                                 /*
  1729.                                  *              Choose a good default name. We try for ENVARC:
  1730.                                  *              initially, but if that fails, fall back on S:
  1731.                                  */
  1732.                                 if (IsFileSystem(defconfig[2]))
  1733.                                         pdefname = &defconfig[2];
  1734.                                 else
  1735.                                         pdefname = &defconfig[1];
  1736.                         }
  1737.                         strcpy(DefaultConfigName, *pdefname);
  1738.                         strcpy(ConfigFileName,    *pdefname);
  1739.                         *TaskWindowPtr = oldwinptr;
  1740.                 } else {
  1741.                         /*
  1742.                          *              Do a quick check to see if the filename specified
  1743.                          *              using the Settings keyword exists -- if it doesn't,
  1744.                          *              then don't bother to try loading it (this avoids
  1745.                          *              a requester being shown unnecessarily).
  1746.                          */
  1747.                         BPTR lk = Lock(DefaultConfigName, ACCESS_READ);
  1748.  
  1749.                         if (lk)
  1750.                                 UnLock(lk);
  1751.                         else
  1752.                                 gotsettings = 0;
  1753.                 }
  1754.  
  1755.                 /*
  1756.                  *              Now, one way or another, we have the default config filename
  1757.                  *              set up so try and load it.
  1758.                  */
  1759.                 if (!LoadConfig(DefaultConfigName,
  1760.                                                 (WBenchMsg ? MODE_TOOLTYPE : MODE_CMDLINE), &newset)
  1761.                         && gotsettings)
  1762.                 {
  1763.                         ShowError(MSG(MSG_ERROR_LOADING_SETTINGS), DefaultConfigName);
  1764.                 }
  1765.         }
  1766.  
  1767.         /*
  1768.          *              Finally, lets parse the remaining startup options and/or icons
  1769.          */
  1770.         if (WBenchMsg) {
  1771.                 /*
  1772.                  *              Scan all the config files (if any) that were passed as
  1773.                  *              parameters via icons.
  1774.                  */
  1775.                 wbarg = WBenchMsg->sm_ArgList + 1;
  1776.                 for (i = 1; i < WBenchMsg->sm_NumArgs; i++, wbarg++) {
  1777.                         char *name = wbarg->wa_Name;
  1778.  
  1779.                         if (SnoopPort) {
  1780.                                 BPTR olddir = CurrentDir(wbarg->wa_Lock);
  1781.  
  1782.                                 LoadConfig(name, MODE_INTERNAL, &newset);
  1783.                                 CurrentDir(olddir);
  1784.                         } else {
  1785.                                 /*
  1786.                                  *              There's a background copy running so we need
  1787.                                  *              to tell it to load the config file instead.
  1788.                                  */
  1789.                                 char *p;
  1790.  
  1791.                                 mysprintf(msg, "%s ", CmdNames[CMD_LOADSETTINGS]);
  1792.                                 p = msg + strlen(msg);
  1793.                                 NameFromLock(wbarg->wa_Lock, p, 150);
  1794.                                 AddPart(p, wbarg->wa_Name, 150);
  1795.                                 SendRemote(msg, MODE_TOOLTYPE);
  1796.                         }
  1797.                 }
  1798.  
  1799.                 /*
  1800.                  *              Rescan the icons, this time processing all the tooltypes that
  1801.                  *              we recognise.  Any we don't recognise are ignored. SETTINGS
  1802.                  *              command may get parsed a second time, but that's okay.
  1803.                  */
  1804.                 for (i = 0; i < maxargs; i++) {
  1805.                         dobj = IconCache[i];
  1806.                         if (dobj) {
  1807.                                 char **tooltypes;
  1808.  
  1809.                                 for (tooltypes = dobj->do_ToolTypes; *tooltypes; tooltypes++) {
  1810.                                         if (SnoopPort)
  1811.                                                 ExecCommand(*tooltypes, MODE_TOOLTYPE, &newset);
  1812.                                         else
  1813.                                                 SendRemote(*tooltypes, MODE_TOOLTYPE);
  1814.                                 }
  1815.                                 FreeDiskObject(dobj);
  1816.                         }
  1817.                 }
  1818.                 if (!SnoopPort)
  1819.                         SendRemote(CmdNames[CMD_SHOW], MODE_CMDLINE);
  1820.         } else {
  1821.                 /*
  1822.                  *              Do a proper scan of the CLI arguments.
  1823.                  */
  1824.                 for (i = 1; i < argc; i++) {
  1825.                         char newcmd[200];
  1826.                         char *thiscmd = argv[i];
  1827.                         struct Command *cmd;
  1828.                         int boolvalue;
  1829.                         int cid;
  1830.  
  1831.                         /*
  1832.                          *              Check if the command we're checking needs more than
  1833.                          *              one parameter. If so, and if it wasn't supplied, we
  1834.                          *              assume that the parameter after it on the command
  1835.                          *              line is to be used. This means the user doesn't have
  1836.                          *              to specifically type the '='.
  1837.                          *
  1838.                          *              HELP is a special case, since HELP will work with zero
  1839.                          *              parameters too. We only try and handle help if there
  1840.                          *              is at least one more parameter after it on the command
  1841.                          *              line. If there isn't, then we print a list of supported
  1842.                          *              commands instead.
  1843.                          */
  1844.                         cid = ParseCommand(thiscmd, newcmd, newcmd+50, &boolvalue, &cmd);
  1845.                         if ( (i+1) < argc && (cid == CMD_HELP ||
  1846.                                                                   (cid == CMD_NOPARAM && cmd->numparms > 0)) )
  1847.                         {
  1848.                                 /*
  1849.                                  *              We didn't have a parameter for this command, so
  1850.                                  *              assume the next parameter on the command line is
  1851.                                  *              the parameter instead.
  1852.                                  */
  1853.                                 mysprintf(newcmd, "%s %s", argv[i], argv[i+1]);
  1854.                                 thiscmd = newcmd;
  1855.                                 i++;
  1856.                         } else if (cid == CMD_HELP) {
  1857.                                 /*
  1858.                                  *              Didn't have anything following the HELP so
  1859.                                  *              print CLI help instead and exit immediately.
  1860.                                  */
  1861.                                 ShowCommands(Output());
  1862.                                 return (0);
  1863.                         }
  1864.                         if (SnoopPort) {
  1865.                                 switch (ExecCommand(thiscmd, MODE_CMDLINE, &newset)) {
  1866.                                         case EXEC_FAIL:
  1867.                                                 Printf(MSG(MSG_ERROR_CLI_FAILED), thiscmd);
  1868.                                                 success = 0;
  1869.                                                 break;
  1870.  
  1871.                                         case EXEC_NOPARAM:
  1872.                                                 Printf(MSG(MSG_ERROR_CLI_NOPARAM), thiscmd);
  1873.                                                 success = 0;
  1874.                                                 break;
  1875.  
  1876.                                         case EXEC_UNKNOWN:
  1877.                                                 Printf(MSG(MSG_ERROR_CLI_UNKNOWN), thiscmd);
  1878.                                                 success = 0;
  1879.                                                 break;
  1880.  
  1881.                                         // case EXEC_OKAY:
  1882.                                 }
  1883.                         } else {
  1884.                                 SendRemote(thiscmd, MODE_CMDLINE);
  1885.                         }
  1886.                 }
  1887.                 if (!SnoopPort && argc == 1)
  1888.                         SendRemote(CmdNames[CMD_SHOW], MODE_CMDLINE);
  1889.         }
  1890.         if (!SnoopPort)
  1891.                 success = 0;
  1892.  
  1893.         /*
  1894.          *              Now check if the user specified Disable=YES (or NO) during
  1895.          *              startup. If they didn't, then reset the disable flag.
  1896.          *              Regardless, we want to update the function flags to reflect
  1897.          *              the current disable state.
  1898.          */
  1899.         if (Disabled == 2)
  1900.                 SetMonitorMode(MONITOR_NORMAL);
  1901.  
  1902.         if (success)
  1903.                 InstallSettings(&newset, UpdateFlags | SET_FUNC);
  1904.  
  1905.         return (success);
  1906. }
  1907.