home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 632.lha / ParM_v3.6 / ParM_Src.lzh / ParM_Src / ParM.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-09  |  21.9 KB  |  854 lines

  1. /*
  2.  *    ParM.c - Copyright © 1990 by S.R. & P.C.
  3.  *
  4.  *    Created:    01 Jul 1990
  5.  *    Modified:    09 Feb 1992  11:45:05
  6.  *
  7.  *    Make>> make
  8.  */
  9.  
  10. #include "ParMBase.h"
  11.  
  12. #define COPYRIGHT            "ParM V3.6 Copyright © 1990-92 by S.R. & P.C."
  13. #define DEFAULT_CONFIG_FILE "S:ParM.cfg"
  14.  
  15. #define BASE_TIME    100000    /* the base time for all time operations: 10 time per seconds */
  16.  
  17. #define THE_END            0
  18. #define NO_WIN            10
  19.  
  20. #define OPEN_ITEM        0
  21. #define UPDATE_ITEM        1
  22. #define STD_CFG_ITEM    2
  23. #define CMDMODE_ITEM    3
  24. #define COMMAND_ITEM    4
  25. #define CHDIR_ITEM        5
  26. #define QUIT_ITEM        6
  27.  
  28. /* MakeDateTimeString() arg */
  29. #define DATE_STRING        1
  30. #define TIME_STRING        2
  31.  
  32.  
  33. extern void setmem(void *mem, size_t size, long value);
  34. extern void CreateParMenu(short Color);
  35. extern void exit(int);
  36.  
  37.  
  38. /*****                global variables                    *****/
  39.  
  40. extern struct ExecBase *SysBase;
  41. extern struct ParMBase *ParMBase;
  42. extern struct LayersBase *LayersBase;
  43. extern struct IntuitionBase *IntuitionBase;
  44. extern struct Menu Menu1;
  45. extern struct MenuItem SubItem1;
  46. extern struct WBStartup *WBenchMsg;
  47. extern char HelpUsage[];
  48. extern char Template[];
  49.  
  50. struct TextAttr MenuFont;
  51.  
  52. /*****                 local variables                    *****/
  53.  
  54. struct ParMOpt {
  55.     short ParMMode;        /* Window, MyMenu, CLI */
  56.     short ParMenuColor;    /* Detail pen for first menu items */
  57.     short MTDetailPen;    /* detailpen of the info string */
  58.     short MTBlockPen;    /* blockpen of the info string */
  59.     UWORD RefreshTime;    /* number of BASE_TIME to wait before refreshing InfoTop */
  60.     UWORD Flags;        /* See below */
  61. };
  62.  
  63. /* ParM modes */
  64. #define MODE_CLI        0    /* default mode */
  65. #define MODE_WINDOW        1
  66. #define MODE_MYMENU        2
  67.  
  68. /* ParM Flags */
  69. #define PF_SHOWTIME        0x0001
  70. #define PF_SHOWMEM        0x0002
  71. #define PF_AUTOFRONT    0x0004
  72. #define PF_USENULL        0x0008        /* Redirect all commands to NULL: (Assure full detach) */
  73.  
  74.  
  75. static struct Process *ParMProcess;
  76. static struct Window *Win;
  77. static struct Screen *WBS;
  78. static struct Menu *LastWBMenu, *TheMenu;
  79. static struct MsgPort SwapPort;
  80. static short FirstParMMenuNum;    /* = 0  if not attached to WorkBench */
  81. static ULONG OldIDCMP, WinSignal;
  82. static BOOL PortTaken;
  83. static BOOL quit;
  84. static BOOL DoSetRast = TRUE;    /* Clear window on Open */
  85. static struct FileReq FileReq;
  86. static char Dir[REQ_DSIZE + 1];
  87. static char File[REQ_FCHARS + 1];
  88. static char Path[REQ_DSIZE + REQ_FCHARS + 2];
  89. static struct ParMConfig ParMConfig;
  90. static struct ParMOpt ParMOpt = {MODE_WINDOW, -1, 1, 2, 10, PF_AUTOFRONT};
  91. static BOOL DoNextSelect;
  92. static struct DateStamp Time;    /* the System Time */
  93. static struct TextFont *Font;
  94. static char InfoString[80];
  95. static short OSVersion;
  96.  
  97.  
  98. /*
  99.  *    ParseArg presume that all TTN_something between FIRST_WIN_ARG and
  100.  *    LAST_WIN_ARG are relative to ParM own window.
  101.  *    ParseArg also presume that all args between TTN_DRAGBAR and TTN_SHOWTIME,
  102.  *    and TTN_USENULL must have ON or OFF as argument.
  103.  */
  104.  
  105. #define FIRST_WIN_ARG    2
  106. #define LAST_WIN_ARG    14
  107.  
  108. #define TTN_MYMENU            0
  109. #define TTN_CLIWINDOW        1
  110. #define TTN_OWNWINDOW        2
  111. #define TTN_LEFTEDGE        3
  112. #define TTN_TOPEDGE            4
  113. #define TTN_DETAILPEN        5
  114. #define TTN_BLOCKPEN        6
  115. #define TTN_DRAGBAR            7
  116. #define TTN_DEPTH            8
  117. #define TTN_AUTOFRONT        9
  118. #define TTN_SHOWMEM            10
  119. #define TTN_SHOWTIME        11
  120. #define TTN_REFRESHTIME        12
  121. #define TTN_MTDETAILPEN        13
  122. #define TTN_MTBLOCKPEN        14
  123. #define TTN_MENUCOLOR        15
  124. #define TTN_STACKSIZE        16
  125. #define TTN_CONFIGFILE        17
  126. #define TTN_USENULL            18        /* Keep in last position to prevent WB access */
  127.  
  128. static char *ToolTypesArg[] = {
  129.     "MYMENU",
  130.     "CLIWINDOW",
  131.     "OWNWINDOW",
  132.     "LEFTEDGE",
  133.     "TOPEDGE",
  134.     "DETAILPEN",
  135.     "BLOCKPEN",
  136.     "NODRAGBAR",
  137.     "DEPTHGADGETS",
  138.     "NOAUTOFRONT",
  139.     "SHOWMEM",
  140.     "SHOWTIME",
  141.     "REFRESHTIME",
  142.     "MTDETAILPEN",
  143.     "MTBLOCKPEN",
  144.     "MENUCOLOR",
  145.     "STACKSIZE",
  146.     "CONFIGFILE",
  147.     "USENULL"
  148. };
  149.  
  150.  
  151. /* Number of CLI Args in template && ToolTypesArg in List */
  152.  
  153. #define NUM_ARGS    19        /* WARNING: also defined in Startup.c */
  154.  
  155.  
  156. static struct NewWindow NWS = {
  157.     0, 0,            /* window XY origin relative to TopLeft of screen */
  158.     0, 10,            /* window width and height */
  159.     1, 2,            /* detail and block pens */
  160.     MENUPICK|RAWKEY|REFRESHWINDOW|ACTIVEWINDOW|INACTIVEWINDOW,    /* IDCMP flags */
  161.     WINDOWDRAG|SMART_REFRESH|NOCAREREFRESH,    /* other window flags */
  162.     NULL,            /* first gadget in gadget list */
  163.     NULL,            /* custom CHECKMARK imagery */
  164.     (UBYTE *)"ParM",/* window title */
  165.     NULL,            /* custom screen pointer */
  166.     NULL,            /* custom bitmap */
  167.     5, 5,            /* minimum width and height */
  168.     -1, -1,            /* maximum width and height */
  169.     WBENCHSCREEN    /* destination screen type */
  170. };
  171.  
  172.  
  173. void MakeDateTimeString(char *dest, short Type)
  174. {
  175.     struct DateTime dt;
  176.     char Date[12], Time[12], Day[12];
  177.  
  178.     setmem(&dt, sizeof(struct DateTime), 0);
  179.     DateStamp(&dt.dat_Stamp);
  180.     if (Type == DATE_STRING) {
  181.         dt.dat_Flags = DTF_FUTURE;
  182.         dt.dat_StrDay = Day;
  183.         dt.dat_StrDate = Date;
  184.         dt.dat_StrTime = Time;
  185.     }
  186.     else
  187.         dt.dat_StrTime = dest;
  188.     StamptoStr(&dt);
  189.     dt.dat_StrTime[8] = '\0';    /* StamptoStr() don't allways NULL terminate this string */
  190.     if (Type == DATE_STRING)
  191.         SPrintf(dest, "%-10s %s %s", Day, Date, Time);
  192. }
  193.  
  194.  
  195. static void MakeInfoString(void)
  196. {
  197.     short chip_free, fast_free;
  198.     short i = 0;
  199.  
  200.     if (Win == IntuitionBase->ActiveWindow)
  201.         MakeDateTimeString(InfoString, DATE_STRING);
  202.     else {
  203.         if (ParMOpt.Flags & PF_SHOWMEM) {
  204.             chip_free = AvailMem(MEMF_CHIP) >> 10;
  205.             fast_free = AvailMem(MEMF_FAST) >> 10;
  206.             i = SPrintf(InfoString, "Chip:%4d Fast:%5d", chip_free, fast_free);
  207.         }
  208.         if (ParMOpt.Flags & PF_SHOWTIME) {
  209.             if (ParMOpt.Flags & PF_SHOWMEM)
  210.                 InfoString[i++] = ' ';
  211.             MakeDateTimeString(&InfoString[i], TIME_STRING);
  212.         }
  213.     }
  214. }
  215.  
  216.  
  217. static void RefreshInfoString(void)
  218. {
  219.     struct RastPort *rp;
  220.  
  221.     if (ParMOpt.Flags & (PF_SHOWMEM|PF_SHOWTIME)) {
  222.         MakeInfoString();
  223.         rp = Win->RPort;
  224.         if (DoSetRast) {
  225.             SetRast(rp, ParMOpt.MTBlockPen);
  226.             DoSetRast = FALSE;
  227.         }
  228.         SetAPen(rp, ParMOpt.MTDetailPen);
  229.         Move(rp, 4, Font->tf_Baseline + 1);
  230.         Text(rp, InfoString, strlen(InfoString));
  231.         if (rp->cp_x < Win->Width) {
  232.             SetAPen(rp, ParMOpt.MTBlockPen);
  233.             RectFill(rp, rp->cp_x, 1, Win->Width, Font->tf_YSize);
  234.         }
  235.     }
  236. }
  237.  
  238.  
  239. static struct Window *FindWorkBench(void)
  240. {
  241.     struct Window *WBW = NULL;
  242.     ULONG ilock;
  243.  
  244.     ilock = LockIBase(0L);    /* Just so's things don't change on us */
  245.     WBW = WBS->FirstWindow;
  246.     while (WBW) {
  247.         /* Only main WB Window has DISKINSERTED IDCMPFlag set, so find it */
  248.         if ((WBW->Flags & WBENCHWINDOW) && (WBW->IDCMPFlags & DISKINSERTED)) {
  249.             TheMenu = WBW->MenuStrip;
  250.             LastWBMenu = TheMenu->NextMenu->NextMenu;
  251.             FirstParMMenuNum = 3;
  252.             if (OSVersion >= 36) {
  253.                 LastWBMenu = LastWBMenu->NextMenu;
  254.                 FirstParMMenuNum = 4;
  255.             }
  256.             break;
  257.         }
  258.         WBW = WBW->NextWindow;
  259.     }
  260.     UnlockIBase(ilock);
  261.     return WBW;
  262. }
  263.  
  264.  
  265. void TakeMsgPort(void)
  266. {
  267.     struct MsgPort *WinPort;
  268.     struct List *myMsgList = &(SwapPort.mp_MsgList);
  269.     struct List *winMsgList;
  270.  
  271.     SwapPort.mp_Node.ln_Type = NT_MSGPORT;
  272.     SwapPort.mp_Flags = PA_SIGNAL;
  273.     Forbid();
  274.  
  275.     /* get the info we need */
  276.     WinPort = Win->UserPort;
  277.     winMsgList = &(WinPort->mp_MsgList);
  278.  
  279.     /* setup our port */
  280.     SwapPort.mp_SigBit = WinPort->mp_SigBit;
  281.     SwapPort.mp_SigTask = WinPort->mp_SigTask;
  282.  
  283.     /* flip things around */
  284.     WinPort->mp_SigTask = (struct Task *) ParMProcess;
  285.     /* Prevent signal for being allocated later */
  286.     WinSignal = AllocSignal(WinPort->mp_SigBit);
  287.     myMsgList->lh_Head = (struct Node *) & winMsgList->lh_Tail;
  288.     myMsgList->lh_TailPred = winMsgList->lh_TailPred;
  289.     winMsgList->lh_TailPred = (struct Node *) & myMsgList->lh_Head;
  290.     myMsgList->lh_TailPred->ln_Succ = (struct Node *) & myMsgList->lh_Tail;
  291.  
  292.     Permit();
  293.  
  294.     /* prevent deadlocks */
  295.     SetTaskPri((struct Task *) ParMProcess, SwapPort.mp_SigTask->tc_Node.ln_Pri + 1);
  296. }
  297.  
  298.  
  299. /* Restore things the way they were before TakeMsgPort() */
  300.  
  301. void DelMsgPort(void)
  302. {
  303.     struct Message *Msg;
  304.     struct List *myMsgList = &(SwapPort.mp_MsgList);
  305.  
  306.     Forbid();
  307.     /* clean out our list */
  308.     while (Msg = GetMsg(&SwapPort))
  309.         PutMsg(&SwapPort, Msg);
  310.     /* restore things */
  311.     myMsgList->lh_Head->ln_Pred = myMsgList->lh_TailPred;
  312.     myMsgList->lh_TailPred->ln_Succ = myMsgList->lh_Head;
  313.     Win->UserPort->mp_SigTask = SwapPort.mp_SigTask;
  314.     if (WinSignal)
  315.         FreeSignal(WinSignal);
  316.     Permit();
  317. }
  318.  
  319.  
  320. /* Configuration managing functions  */
  321.  
  322. static void InstallWBMenus(struct Menu * Menus)
  323. {
  324.     long ilock;
  325.  
  326.     ilock = LockIBase(0);
  327.     ClearMenuStrip(Win);
  328.     NewCleanUp(TheMenu, &MenuFont, 0);
  329.     LastWBMenu->NextMenu = Menus;
  330.     SetMenuStrip(Win, TheMenu);
  331.     UnlockIBase(ilock);
  332. }
  333.  
  334.  
  335. static void ClearMenus(void)
  336. {
  337.     if (ParMOpt.ParMMode == MODE_MYMENU) {
  338.         InstallWBMenus(NULL);
  339.         Menu1.LeftEdge = LastWBMenu->LeftEdge + LastWBMenu->Width;
  340.     }
  341.     else
  342.         ClearMenuStrip(Win);
  343. }
  344.  
  345.  
  346. void UpDateMenus(void)
  347. {
  348.     ClearMenus();
  349.     ParMConfig.MenuPen = ParMOpt.ParMenuColor;
  350.     if (!ParseMenus(&ParMConfig))
  351.         FreeMenus(&ParMConfig);
  352.     if (ParMOpt.ParMMode == MODE_MYMENU)
  353.         InstallWBMenus(&Menu1);
  354.     else
  355.         SetMenuStrip(Win, &Menu1);
  356. }
  357.  
  358.  
  359. static void OpenMenus(void)
  360. {
  361.     char *yuck;
  362.  
  363.     FileReq.Title = "Open";
  364.     strcpy(Dir, ParMConfig.CurCfg);
  365.     strcpy(File, yuck = BaseName(Dir));
  366.     *yuck = '\0';        /* cut off filename from fr_Dir */
  367.     if (!FileRequester(&FileReq))
  368.         return;        /* quit if Open canceled */
  369.     strcpy(ParMConfig.CurCfg, Path);
  370.     UpDateMenus();
  371. }
  372.  
  373.  
  374. /* Print busy message in place of window title */
  375.  
  376. static void Busy(BOOL status)
  377. {
  378.     if (ParMOpt.ParMMode == MODE_WINDOW) {
  379.         SetWindowTitles(Win, (status) ? "Busy" : "ParM", COPYRIGHT);
  380.         if (ParMOpt.Flags & (PF_SHOWMEM|PF_SHOWTIME)) {
  381.             if (status)        /* Busy */
  382.                 RefreshWindowFrame(Win);
  383.             else
  384.                 SetRast(Win->RPort, ParMOpt.MTBlockPen);
  385.         }
  386.     }
  387. }
  388.  
  389.  
  390. /* Atchao, bonsoir...  */
  391.  
  392. void Bye(short err)
  393. {
  394.     if (err == THE_END) {
  395.         ClearMenus();
  396.         FreeMenus(&ParMConfig);
  397.         if (PortTaken)
  398.             DelMsgPort();
  399.         if (ParMOpt.ParMMode == MODE_CLI)
  400.             ModifyIDCMP(Win, OldIDCMP);
  401.         else if (ParMOpt.ParMMode == MODE_WINDOW)
  402.             CloseWindowSafely(Win, NULL);
  403.     }
  404.     CloseFont(Font);
  405.     exit(err);
  406. }
  407.  
  408.  
  409. /* change parm current directory */
  410.  
  411. static void ChangeDir(char *dir)
  412. {
  413.     BPTR NewLock, OldLock;
  414.  
  415.     NewLock = Lock(dir, ACCESS_READ);
  416.     if (NewLock) {
  417.         OldLock = CurrentDir(NewLock);
  418.         if (OldLock)
  419.             UnLock(OldLock);
  420.     }
  421. }
  422.  
  423.  
  424. static void DoExtMenu(USHORT MenuNum)
  425. {
  426.     struct Extended_MenuItem *Item;
  427.     struct Extended_WBStartup *EWBS;
  428.  
  429.     Item = (struct Extended_MenuItem *) ItemAddress(TheMenu, MenuNum);
  430.     switch (Item->emi_Mode) {
  431.     case TOK_ARUN:
  432.         ARun(&ParMConfig, &Item->emi_RunInfo);
  433.         break;
  434.     case TOK_RUN:
  435.     case TOK_SHELL:
  436.         Run(&ParMConfig, &Item->emi_RunInfo, Item->emi_Mode);
  437.         break;
  438.     case TOK_WB:
  439.         if (EWBS = MakeWBStartup(&ParMConfig, &Item->emi_RunInfo))
  440.             WBRun(&ParMConfig, EWBS, Item->emi_RunInfo.ri_Pri);
  441.         break;
  442.     case TOK_CFG:        /* new cfg */
  443.         strcpy(ParMConfig.CurCfg, Item->emi_RunInfo.ri_Cmd);
  444.         UpDateMenus();
  445.         DoNextSelect = FALSE;    /* Tell DoIntuiMsg not to execute next menu selection */
  446.     }
  447. }
  448.  
  449.  
  450. static void parse_arg(short opt, char *args)
  451. {
  452.     char Buf[80];
  453.     long argl;
  454.  
  455.     if ((opt >= TTN_DRAGBAR && opt <= TTN_SHOWTIME) || opt == TTN_USENULL) {
  456.         if (!Strcmp(args, "ON"))
  457.             argl = 1;
  458.         else if (!Strcmp(args, "OFF"))
  459.             argl = 0;
  460.         else {
  461.             SPrintf(Buf, "ON|OFF argument required for %s", ToolTypesArg[opt]);
  462.             if (WBenchMsg)
  463.                 SimpleRequest(ParMConfig.ReqTitle, Buf);
  464.             else
  465.                 Printf("%s\n", Buf);
  466.             Bye(NO_WIN);
  467.         }
  468.     }
  469.     else
  470.         argl = Atol(args);
  471.     if (opt >= FIRST_WIN_ARG && opt <= LAST_WIN_ARG)
  472.         ParMOpt.ParMMode = MODE_WINDOW;
  473.     switch (opt) {
  474.     case TTN_MYMENU:
  475.         ParMOpt.ParMMode = MODE_MYMENU;
  476.         break;
  477.     case TTN_CLIWINDOW:
  478.         if (!WBenchMsg)
  479.             ParMOpt.ParMMode = MODE_CLI;
  480.         break;
  481.     case TTN_STACKSIZE:
  482.         if (argl >= 4000)
  483.             ParMConfig.DefaultStack = argl;
  484.         break;
  485.     case TTN_LEFTEDGE:
  486.         NWS.LeftEdge = argl;
  487.         break;
  488.     case TTN_TOPEDGE:
  489.         NWS.TopEdge = argl;
  490.         break;
  491.     case TTN_DETAILPEN:
  492.         NWS.DetailPen = argl;
  493.         break;
  494.     case TTN_BLOCKPEN:
  495.         NWS.BlockPen = argl;
  496.         ParMOpt.MTBlockPen = argl;    /* Default MTBLOCKPEN is BLOCKPEN */
  497.         break;
  498.     case TTN_MENUCOLOR:
  499.         ParMOpt.ParMenuColor = argl;
  500.         break;
  501.     case TTN_CONFIGFILE:
  502.         strcpy(ParMConfig.CurCfg, args);
  503.         break;
  504.     case TTN_DRAGBAR:    /* no drag bar */
  505.         if (argl)
  506.             NWS.Flags |= WINDOWDRAG;
  507.         else
  508.             NWS.Flags &= ~WINDOWDRAG;
  509.         break;
  510.     case TTN_DEPTH:        /* depth gadgets */
  511.         if (argl)
  512.             NWS.Flags |= WINDOWDEPTH;
  513.         else
  514.             NWS.Flags &= ~WINDOWDEPTH;
  515.         /* don't break, depth gadgets disable autofront */
  516.     case TTN_AUTOFRONT:
  517.         if (argl)
  518.             ParMOpt.Flags |= PF_AUTOFRONT;
  519.         else
  520.             ParMOpt.Flags &= ~PF_AUTOFRONT;
  521.         break;
  522.     case TTN_SHOWMEM:
  523.         if (argl)
  524.             ParMOpt.Flags |= PF_SHOWMEM;
  525.         else
  526.             ParMOpt.Flags &= ~PF_SHOWMEM;
  527.         break;
  528.     case TTN_SHOWTIME:
  529.         if (argl)
  530.             ParMOpt.Flags |= PF_SHOWTIME;
  531.         else
  532.             ParMOpt.Flags &= ~PF_SHOWTIME;
  533.         break;
  534.     case TTN_REFRESHTIME:
  535.         ParMOpt.RefreshTime = argl;
  536.         break;
  537.     case TTN_MTDETAILPEN:
  538.         ParMOpt.MTDetailPen = argl;
  539.         break;
  540.     case TTN_MTBLOCKPEN:
  541.         ParMOpt.MTBlockPen = argl;
  542.         break;
  543.     case TTN_USENULL:
  544.         if (argl)
  545.             ParMOpt.Flags |= PF_USENULL;
  546.         else
  547.             ParMOpt.Flags &= ~PF_USENULL;
  548.         break;
  549.     }
  550. }
  551.  
  552.  
  553. void main(int argc, char *argv[])
  554. {
  555.     struct CommandLineInterface *cli;
  556.     struct DiskObject *dop;
  557.     struct MsgPort *WorkPort;
  558.     struct IntuiMessage *IMsg;
  559.     ULONG Class;
  560.     USHORT Code, Qual;
  561.     APTR WindowPtr;
  562.     BPTR fh;
  563.     char *arg;
  564.     short i;
  565.  
  566.     /* for TopInfo String */
  567.     struct MsgPort *Timer_Port = NULL;
  568.     struct timerequest Time_Req;
  569.     long TimerOpen = 1;
  570.     long IntuiSignal = 0, TimerSignal = 0, Signal = 0;
  571.  
  572.     /* for GetEnv() */
  573.     int ParMOptArgC;
  574.     char **ParMOptArgV;
  575.     char ParMOptString[256];
  576.  
  577.     OSVersion = IntuitionBase->LibNode.lib_Version;
  578.     TheMenu = &Menu1;
  579.     InitDefaults(&ParMConfig);
  580.     ParMConfig.ReqTitle = "ParM Request";
  581.     ParMConfig.LinkMenu = &Menu1;
  582.     ParMConfig.SimpleCmdMode = TRUE;
  583.     FileReq.Dir = Dir;
  584.     FileReq.File = File;
  585.     FileReq.PathName = Path;
  586.     strcpy(FileReq.Show, "*.cfg");
  587.     ParMProcess = (struct Process *)SysBase->ThisTask;
  588.     strcpy(ParMConfig.CurCfg, DEFAULT_CONFIG_FILE);
  589.  
  590.     WBS = OpenWorkBench();
  591.     AskFont(&WBS->RastPort, &MenuFont);        /* Get workbench screen font */
  592.     Font = OpenFont(&MenuFont);
  593.  
  594.     /* read the ParMOpt environment first, so it can be overriden by CLI/WB arguments */
  595.     if (Getenv("ParMOpt", ParMOptString, 255)) {
  596.         ParMOptArgV = ArpAlloc(sizeof(APTR) * (NUM_ARGS + 1));
  597.         ParMOptArgC = (int) GADS(ParMOptString, strlen(ParMOptString), HelpUsage, ParMOptArgV, Template);
  598.         if (ParMOptArgC < 0) {
  599.             SimpleRequest(ParMConfig.ReqTitle, "Error in ParMOpt: %s", ParMOptArgV[0]);
  600.             Bye(NO_WIN);
  601.         }
  602.         else {
  603.             for (i = 0; i < NUM_ARGS; i++) {
  604.                 if (ParMOptArgV[i])
  605.                     parse_arg(i, ParMOptArgV[i]);
  606.             }
  607.         }
  608.     }
  609.  
  610.     if (WBenchMsg) {    /* Tool Types parsing */
  611.         if (dop = GetDiskObject(WBenchMsg->sm_ArgList->wa_Name)) {
  612.             ParMConfig.DefaultStack = dop->do_StackSize;
  613.             for (i = 0; i < NUM_ARGS-1; i++) {    /* NUM_ARGS-1 => don't parse USENULL */
  614.                 if (arg = FindToolType(dop->do_ToolTypes, ToolTypesArg[i]))
  615.                     parse_arg(i, arg);
  616.             }
  617.             FreeDiskObject(dop);
  618.         }
  619.         parse_arg(TTN_USENULL, "ON");    /* allways redirect output to NULL: if started from WorkBench */
  620.         if (ParMOpt.ParMMode == MODE_CLI)
  621.             ParMOpt.ParMMode = MODE_WINDOW;        /* Forbid CLI mode from WB */
  622.     }
  623.     else {            /* CLI parsing */
  624.         cli = (struct CommandLineInterface *) ((long) ParMProcess->pr_CLI << 2);
  625.         ParMConfig.DefaultStack = cli->cli_DefaultStack << 2;
  626.         for (i = 0; i < NUM_ARGS; i++) {
  627.             if (argv[i])
  628.                 parse_arg(i, argv[i]);
  629.         }
  630.     }
  631.     /* SHOWMEM, SHOWTIME and AUTOFRONT allowed only with ParM's own window */
  632.     if (ParMOpt.ParMMode != MODE_WINDOW)
  633.         ParMOpt.Flags &= ~(PF_SHOWMEM|PF_SHOWTIME|PF_AUTOFRONT);
  634.     switch (ParMOpt.ParMMode) {
  635.     case MODE_WINDOW:
  636.         /* Bug in 2.0. Screen->BarHeight is one pixel less than true height */
  637.         NWS.Height = WBS->BarHeight + (OSVersion >= 36);
  638.  
  639.         /* calculate the real lenght of string ParM (font can be proportional in 2.0) */
  640.         /* if the font is proportional tf_YSize chould contain max char size */
  641.         if ((ParMOpt.Flags & PF_SHOWMEM) && (ParMOpt.Flags & PF_SHOWTIME))
  642.             i = 29;        /* 29 = strlen("Chip:0000 Fast:00000 00:00:00") */
  643.         else if (ParMOpt.Flags & PF_SHOWTIME)
  644.             i = 8;        /* 8 = strlen("00:00:00") */
  645.         else if (ParMOpt.Flags & PF_SHOWMEM)
  646.             i = 20;        /* 20 = strlen("Chip:0000 Fast:00000") */
  647.         else {
  648.             i = 4;        /* strlen("ParM") */
  649.             NWS.Width = (OSVersion >= 36) ? 10 : 2;
  650.             if (NWS.Flags & WINDOWDEPTH)
  651.                 NWS.Width += 51;    /* Depth gadget stay hidden when show Mem/Time */
  652.         }
  653.         NWS.Width += Font->tf_XSize * i + 6;    
  654.  
  655.         if ((Timer_Port = CreatePort(0, 0L))) {
  656.             if (!(TimerOpen = OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *) & Time_Req, 0L))) {
  657.                 Time_Req.tr_node.io_Message.mn_ReplyPort = Timer_Port;
  658.                 Time_Req.tr_node.io_Command = TR_ADDREQUEST;
  659.                 Time_Req.tr_node.io_Flags = 0;
  660.                 Time_Req.tr_node.io_Error = 0;
  661.                 Time_Req.tr_time.tv_secs = 0;
  662.                 Time_Req.tr_time.tv_micro = BASE_TIME * ParMOpt.RefreshTime;
  663.             }
  664.         }
  665.         if (!(Win = OpenWindow(&NWS)))
  666.             Bye(NO_WIN);
  667.         SetWindowTitles(Win, "ParM", COPYRIGHT);
  668.         SetFont(Win->RPort, Font);
  669.         break;
  670.     case MODE_CLI:
  671.         Win = GetWindow();
  672.         if (Win->UserPort) {
  673.             if (Win->IDCMPFlags & MENUPICK) {
  674.                 SimpleRequest(ParMConfig.ReqTitle, "This window already have menus.");
  675.                 Bye(NO_WIN);
  676.             }
  677.             else {
  678.                 PortTaken = TRUE;
  679.                 OldIDCMP = Win->IDCMPFlags;
  680.             }
  681.         }
  682.         ModifyIDCMP(Win, Win->IDCMPFlags | MENUPICK | CLOSEWINDOW);
  683.         break;
  684.     case MODE_MYMENU:
  685.         if (Win = FindWorkBench()) {
  686.             if (LastWBMenu->NextMenu) {
  687.                 SimpleRequest(ParMConfig.ReqTitle, "Menus already installed in WorkBench.");
  688.                 Bye(NO_WIN);
  689.             }
  690.             else
  691.                 PortTaken = TRUE;
  692.         }
  693.         else {
  694.             SimpleRequest(ParMConfig.ReqTitle, "Can't find WorkBench.");
  695.             Bye(NO_WIN);
  696.         }
  697.     }
  698.     ParMConfig.Win = Win;
  699.     if (PortTaken)
  700.         TakeMsgPort();
  701.     if (ParMOpt.ParMenuColor < 0)
  702.         ParMOpt.ParMenuColor = Win->DetailPen;
  703.     CreateParMenu(ParMOpt.ParMenuColor);
  704.     UpDateMenus();
  705.     SetBPen(Win->RPort, ParMOpt.MTBlockPen);
  706.     SetDrMd(Win->RPort, JAM2);
  707.     RefreshInfoString();
  708.     if (ParMOpt.Flags & PF_USENULL) {
  709.         /* prevent request "Please insert volume NULL:" if not mounted */
  710.         WindowPtr = ParMProcess->pr_WindowPtr;
  711.         ParMProcess->pr_WindowPtr = (APTR)-1L;
  712.         if ((fh = Open("NULL:", MODE_NEWFILE)) || (fh = Open("NIL:", MODE_NEWFILE))) {
  713.             ParMProcess->pr_CIS = fh;
  714.             ParMProcess->pr_COS = fh;
  715.             ParMProcess->pr_ConsoleTask = (APTR)((struct FileHandle *)(fh << 2))->fh_Type;
  716.         }
  717.         ParMProcess->pr_WindowPtr = WindowPtr;
  718.     }
  719.  
  720.     /* Monitor Menu Events */
  721.  
  722.     WorkPort = (PortTaken) ? &SwapPort : Win->UserPort;
  723.     IntuiSignal = 1L << WorkPort->mp_SigBit;
  724.     if (Timer_Port) {
  725.         TimerSignal = 1L << Timer_Port->mp_SigBit;
  726.         SendIO((struct IORequest *) & Time_Req.tr_node);
  727.     }
  728.  
  729.     while (!quit) {
  730.         Signal = Wait(IntuiSignal | TimerSignal);
  731.         if (Signal & IntuiSignal) {
  732.             while (IMsg = (struct IntuiMessage *) GetMsg(WorkPort)) {
  733.                 Class = IMsg->Class;
  734.                 Code = IMsg->Code;
  735.                 Qual = IMsg->Qualifier;
  736.                 /* Use raw keys to prevent ALT and CTRL convertions. Allow only Shift qualifiers */
  737.                 if (Class == RAWKEY && !(Code & IECODE_UP_PREFIX) && (Qual & ParMConfig.ShortCutQual) && !(Qual & IEQUALIFIER_REPEAT)) {
  738.                     Code = RawKeyToAscii(Code, Qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT|IEQUALIFIER_RELATIVEMOUSE), IMsg->IAddress);
  739.                     if (Code > 32 && Code < 127) {
  740.                         Code = MakeMenuShortCut(&Menu1, Code);
  741.                         Class = MENUPICK;
  742.                     }
  743.                 }
  744.                 /*
  745.                  *    PutMsg() conditions (Messages given to port monitored):
  746.                  *    MODE_WINDOW:
  747.                  *        No such port, so all messages replied.
  748.                  *    MODE_MYMENU:
  749.                  *        give all messages but ParM's menus MENUPICK and RAWKEYs converted
  750.                  *        to MENUPICK. handle NEWPREFS after PutMsg().
  751.                  *        For OS2.0, disable ResetWB (1st item of Tools menu).
  752.                  *    MODE_CLI:
  753.                  *        if PortTaken, all but MENUPICK and CLOSEWINDOW.
  754.                  */
  755.                 if (!PortTaken
  756.                     || (Class == MENUPICK && (MENUNUM(Code) >= FirstParMMenuNum || OSVersion >= 36 && MENUNUM(Code) == 3 && ITEMNUM(Code) == 0))
  757.                     || (ParMOpt.ParMMode == MODE_CLI && Class == CLOSEWINDOW))
  758.                 {
  759.                     if (Class == 0x0FL)    /* Msg sent bye 'ParMCD' command */
  760.                         ChangeDir((char *) IMsg->IAddress);
  761.                     ReplyMsg((struct Message *) IMsg);
  762.                 }
  763.                 else {
  764.                     PutMsg(&SwapPort, (struct Message *) IMsg);
  765.                     if (Class == NEWPREFS) {
  766.                         while (LastWBMenu->NextMenu)
  767.                             Delay(10);
  768.                         InstallWBMenus(&Menu1);
  769.                     }
  770.                     continue;    /* Don't handle these messages */
  771.                 }
  772.                 switch (Class) {
  773.                 case ACTIVEWINDOW:
  774.                 case INACTIVEWINDOW:
  775.                     if (ParMOpt.ParMMode == MODE_WINDOW && (ParMOpt.Flags & (PF_SHOWMEM|PF_SHOWTIME)))
  776.                         DoSetRast = TRUE;
  777.                     break;
  778.                 case CLOSEWINDOW:
  779.                     quit = TRUE;
  780.                     break;
  781.                 case MENUPICK:
  782.                     DoNextSelect = TRUE;
  783.                     if (Code != MENUNULL) {
  784.                         Busy(TRUE);
  785.                         do {
  786.                             /* Prevent extended selection of workbench menus */
  787.                             if (MENUNUM(Code) == FirstParMMenuNum) {
  788.                                 switch (ITEMNUM(Code)) {
  789.                                 case OPEN_ITEM:
  790.                                     OpenMenus();
  791.                                     DoNextSelect = FALSE;
  792.                                     break;
  793.                                 case UPDATE_ITEM:
  794.                                     UpDateMenus();
  795.                                     DoNextSelect = FALSE;
  796.                                     break;
  797.                                 case STD_CFG_ITEM:
  798.                                     strcpy(ParMConfig.CurCfg, DEFAULT_CONFIG_FILE);
  799.                                     UpDateMenus();
  800.                                     DoNextSelect = FALSE;
  801.                                     break;
  802.                                 case CMDMODE_ITEM:
  803.                                     ParMConfig.SimpleCmdMode = SubItem1.Flags & CHECKED;
  804.                                     break;
  805.                                 case COMMAND_ITEM:
  806.                                     Command(&ParMConfig);
  807.                                     break;
  808.                                 case CHDIR_ITEM:
  809.                                     PathName(ParMProcess->pr_CurrentDir, Dir, REQ_DSIZE);
  810.                                     FileReq.Flags = FRQDIRONLYM;
  811.                                     FileReq.Title = "Enter New Dir...";
  812.                                     if (FileRequester(&FileReq))
  813.                                         ChangeDir(Dir);
  814.                                     FileReq.Flags = 0;
  815.                                     break;
  816.                                 case QUIT_ITEM:
  817.                                     quit = TRUE;
  818.                                     DoNextSelect = FALSE;
  819.                                 }
  820.                             }
  821.                             else if (MENUNUM(Code) > FirstParMMenuNum)    /* custom menus */
  822.                                 DoExtMenu(Code);
  823.                         } while (DoNextSelect && (Code = ItemAddress(TheMenu, Code)->NextSelect) != MENUNULL);
  824.                         Busy(FALSE);
  825.                     }
  826.                     break;
  827.                 }
  828.             }
  829.         }
  830.         if (Signal & TimerSignal) {
  831.             if (ParMOpt.ParMMode == MODE_WINDOW && (ParMOpt.Flags & PF_AUTOFRONT) && IsHidden(Win))
  832.                 WindowToFront(Win);
  833.             Time_Req.tr_time.tv_secs = 0;
  834.             Time_Req.tr_time.tv_micro = BASE_TIME * ParMOpt.RefreshTime;
  835.             SendIO((struct IORequest *) & Time_Req.tr_node);
  836.         }
  837.         if (ParMOpt.ParMMode == MODE_WINDOW)
  838.             RefreshInfoString();
  839.         /* See if some wb messages have been replied, and free them */
  840.         FreeRepliedWBMessages();
  841.     }
  842.  
  843.     if (!TimerOpen) {
  844.         WaitIO((struct IORequest *)&Time_Req.tr_node);    /* wait for the last timer msg before exit */
  845.         CloseDevice((struct IORequest *)&Time_Req);
  846.     }
  847.     if (Timer_Port)
  848.         DeletePort(Timer_Port);
  849.  
  850.     Bye(THE_END);
  851. }
  852.  
  853.  
  854.