/*
 * toolmanager.c   V1.3
 *
 * startup routines
 *
 * (c) 1991 by Stefan Becker
 *
 */
#include "ToolManager.h"

/* Library pointers */
extern struct Library *SysBase,*IntuitionBase,*GfxBase; /* Autoinit Libs */
struct Library *WorkbenchBase,*IconBase,*GadToolsBase,*AslBase;

/* CLI command line options */
static char NoIconOpt[]="-n";
static char ConfigOpt[]="-f";

/* miscellaneous */
extern char InternalConfigName[];
static struct DiskObject *dobj=NULL;
static struct AppMenuItem *QTMAppMenuItem;
static struct AppMenuItem *OTWAppMenuItem;
static APTR OldConsoleTask=NULL;

/* Open libraries and other stuff */
static BOOL openstuff(void)
{
 if (SysBase->lib_Version<36)  /* Sanity check */
  {
   puts("You need a Kickstart 2.0 or better to run ToolManager!");
   exit(20);
  }

 /* Open libraries */
 if (!(WorkbenchBase=OpenLibrary(WORKBENCH_NAME,0)))
  cleanup(1);

 if (!(IconBase=OpenLibrary(ICONNAME,0)))
  cleanup(2);

 if (!(GadToolsBase=OpenLibrary("gadtools.library",0)))
  cleanup(3);

 if (!(AslBase=OpenLibrary(AslName,0)))
  cleanup(4);

 Forbid();                     /* Is "ToolManager" already running? */
 MyMP=FindPort(MyName);
 Permit();
 if (MyMP) return(TRUE);       /* Yes, don't start again! */

 if (!(MyMP=CreateMsgPort()))  /* No, create message port */
  cleanup(5);
 MyMP->mp_Node.ln_Pri=0;
 MyMP->mp_Node.ln_Name=MyName; /* Our name */
 AddPort(MyMP);                /* Announce our presence */
 return(FALSE);                /* No, start ToolManager */
}

/* Init tool stuff */
static void inittool(void)
{
 SetConfigFileName(InternalConfigName); /* Copy config file name */
 NewList(&ToolList);                    /* Initialize tool list */

 /* Notify Workbench about special menu items. */
 /* 1. If this item is selected, the program will quit */
 if (!(QTMAppMenuItem=AddAppMenuItem(0,NULL,"Quit ToolManager",MyMP,TAG_DONE)))
  cleanup(6);

 /* 2. If this item is selected, the status window will open */
 if (!(OTWAppMenuItem=AddAppMenuItem(1,NULL,"Open TM Window",MyMP,TAG_DONE)))
  cleanup(7);
}

/* Send an AppMessage with our parameters to a running ToolManager process */
static void SendParameters(LONG nargs, struct WBArg *arg)
{
 struct MsgPort *sp,*rp;
 struct AppMessage *msg;

 /* Allocate memory for AppMessage */
 if (!(msg=malloc(sizeof(struct AppMessage)))) goto e1;

 /* Create a reply port */
 if (!(rp=CreateMsgPort())) goto e2;

 /* Build AppMessage */
 msg->am_Message.mn_Node.ln_Type=NT_MESSAGE;
 msg->am_Message.mn_Node.ln_Pri=0;
 msg->am_Message.mn_ReplyPort=rp;
 msg->am_Type=MTYPE_APPICON;
 msg->am_NumArgs=nargs;
 msg->am_ArgList=arg;

 Forbid();                     /* Find "ToolManager" message port */
 sp=FindPort(MyName);
 if (sp) PutMsg(sp,(struct Message *) msg); /* Send AppMessage */
 Permit();

 if (sp)
  {                            /* We have send the message */
   WaitPort(rp);               /* Wait on the reply */
   GetMsg(rp);                 /* Remove reply from port */
  }

    DeleteMsgPort(rp);
e2: free(msg);
e1: return;
}

/* Workbench main entry point */
void wbmain(struct WBStartup *wbarg)
{
 BPTR fl;

 if (openstuff())         /* common startup code */
  {                       /* ToolManager already running, send parameters */
   if (wbarg->sm_NumArgs>1)
    SendParameters(wbarg->sm_NumArgs-1,wbarg->sm_ArgList+1);
   cleanup(5);            /* All done */
  }

 inittool();              /* Init tool stuff */

 /* Process WB startup parameters */
 WBAddToolNode(wbarg->sm_ArgList+1,wbarg->sm_NumArgs-1);

 /* Get the program icon */
 fl=CurrentDir(wbarg->sm_ArgList->wa_Lock);
 if (dobj=GetDiskObject(wbarg->sm_ArgList->wa_Name))
  {
   char *cp,**ttp=dobj->do_ToolTypes;

   /* Retreive ToolTypes from icon */
   /* 1. CONFIG=<name> Set configuration file name */
   if (cp=FindToolType(ttp,"CONFIG")) SetConfigFileName(cp);

   /* 2. INTERNALICON Use the internal icon as AppIcon */
   if (!FindToolType(ttp,"INTERNALICON")) MyIcon=dobj;

   /* 3. SHOWICON=YES|NO Show AppIcon */
   if (cp=FindToolType(ttp,"SHOWICON"))
    if (!(ShowIcon=MatchToolValue(cp,"YES")))
     {
      FreeDiskObject(dobj);
      dobj=NULL;
     }
  }
 CurrentDir(fl);

 /* Read configuration file */
 ReadConfigFile(wbarg->sm_ArgList->wa_Lock);

 mainloop(); /* Go into main loop */
}

/* CLI main entry point */
void main(int argc, char **argv)
{
 int i;
 BPTR fl;
 struct Process *pr=FindTask(NULL);

 /* Help requested? */
 if ((argc>1) && (*argv[1]=='?'))
  { /* Print out usage, but DON'T start ToolManager */
   puts("\nUsage: ToolManager [-n] [-f <file>] [program 1] ... [program n]");
   puts("       -n : Don't show the program icon");
   puts("       -f : Use <file> as configuration file");
   puts("Requires Kickstart 2.0 or better!\n");
   exit(0);
  }

 freopen("*","w",stderr);     /* Reopen the stderr for banner line */
 fputs(WindowTitle,stderr);   /* Put out banner line (only in CLI) */
 fputc('\n',stderr);
 fclose(stderr);

 if (openstuff())             /* common startup code */
  {                           /* ToolManager already running, send parameters */
   struct WBArg *wa,*wat;

   if (argc<2) cleanup(5);    /* No parameters to send */

   /* Allocate memory for WB parameters */
   if (!(wa=malloc(sizeof(struct WBArg)*(argc-1)))) cleanup(5);

   fl=CurrentDir(NULL);       /* Get current directory lock */

   wat=wa;                    /* Build WBArgs */
   for (i=argc-1; i; i--,wat++)
    {
     ++argv;

     if (strcmp(*argv,NoIconOpt) && strcmp(*argv,ConfigOpt))
      {
       wat->wa_Lock=fl;       /* Copy parameters */
       wat->wa_Name=*argv;
      }
     else
      {
       argc--;                /* Filter out CLI command line options */
       wat--;
      }
    }

   if (argc>1) SendParameters(argc-1,wa); /* Send parameters */

   CurrentDir(fl);            /* Go back to old directory */
   free(wa);                  /* Free WB parameters */
   cleanup(5);                /* All done */
  }

 inittool();                  /* Init tool stuff */
 fl=CurrentDir(NULL);         /* Get current directory lock */

 /* Process CLI startup parameters */
 for (i=argc-1; i; i--)
  {
   ++argv; /* Next command line parameter */

   /* Process CLI options */
   /* 1. "-n" Don't show AppIcon */
   if (!strcmp(*argv,NoIconOpt)) ShowIcon=FALSE;

   /* 2. <name> Add tool */
   else if (strcmp(*argv,ConfigOpt)) AddToolNode(fl,*argv,NULL,TRUE);

   /* 3. "-f <name>" Set configuration file name */
   else if (i>1)
         {
          i--;
          SetConfigFileName(*++argv);
         }
  }

 CurrentDir(DupLock(fl));     /* Go to current directory */
 ReadConfigFile(fl);          /* Read configuration file */

 UnLock(CurrentDir(fl));      /* Go back to old directory */
 fclose(stdin);               /* Detach from console window */
 fclose(stdout);
 OldConsoleTask=pr->pr_ConsoleTask;
 pr->pr_ConsoleTask=NULL;
 mainloop();                  /* Go into main loop */
}

/* Final cleanup routine */
void cleanup(int i)
{
 register struct Message *msg;

 switch(i)
  {
   case 99:
           if (ShowIcon) RemoveAppIcon(MyAppIcon);
           if (dobj) FreeDiskObject(dobj);
   case  8:RemoveTools();
           RemoveAppMenuItem(OTWAppMenuItem);
   case  7:RemoveAppMenuItem(QTMAppMenuItem);
   case  6:RemPort(MyMP);                           /* Remove message port */
           while (msg=GetMsg(MyMP)) ReplyMsg(msg);  /* Reply all messages */
           DeleteMsgPort(MyMP);
   case  5:CloseLibrary(AslBase);
   case  4:CloseLibrary(GadToolsBase);
   case  3:CloseLibrary(IconBase);
   case  2:CloseLibrary(WorkbenchBase);
   case  1:break;
  }

 /* Did we have a console window? */
 if (OldConsoleTask)
  {
   struct Process *pr=FindTask(NULL);

   pr->pr_ConsoleTask=OldConsoleTask; /* Yes, restore old value */
  }

 exit(RETURN_OK);    /* all o.k. */
}
