/*
 * starttools.c   V1.4
 *
 * CLI & WB startup procedure
 *
 * (c) 1991 by Stefan Becker
 *
 */
#include "ToolManager.h"

/* Start tool as a CLI process */
static BOOL StartCLITool(struct AppMessage *msg, struct ToolNode *tn,
                         char *name)
{
 BPTR fl;                       /* AmigaDOS file handle */
 BOOL rc=TRUE;
 char cmd[NAMELEN];             /* Buffer for command line */
 int cmdlen;                    /* Command line length */
 char dir[NAMELEN];
 struct WBArg *wa=msg->am_ArgList;
 int i;

 fl=CurrentDir(tn->tn_DirLock); /* Change to tool's directory */

 strcpy(cmd,name);              /* Command name first */
 cmdlen=strlen(cmd);

 for (i=msg->am_NumArgs; i; i--,wa++)
  {
   char *cp;
   int namelen;

   if (!wa->wa_Lock) continue;  /* Skip arguments which don't support locks! */

   if (cmdlen>NAMELEN-2) break; /* Append a space for each parameter */
   strcat(cmd," ");
   cmdlen++;

   /* Build parameter from Lock & name */
   if (SameLock(tn->tn_DirLock,wa->wa_Lock)==LOCK_SAME) cp=wa->wa_Name;
   else
    {
     if (!NameFromLock(wa->wa_Lock,dir,NAMELEN)) continue;
     if (!AddPart(dir,wa->wa_Name,NAMELEN)) continue;
     cp=dir;
    }

   namelen=strlen(cp);

   if (strchr(cp,' '))          /* Special case: Space in a filename */
    if (namelen>NAMELEN-3) break;
    else
     {
      strins(cp,"\"");          /* Set parameter in double quotes */
      strcat(cp,"\"");
      namelen+=2;
     }

   if (cmdlen+namelen>NAMELEN-2) break;
   strcat(cmd,cp);              /* Append parameter */
   cmdlen+=namelen;             /* New command line length */
  }

 /* Start tool */
 if (SystemTags(cmd,SYS_Input,Open("NIL:",MODE_NEWFILE),
                    SYS_Output,Open("NIL:",MODE_NEWFILE),
                    SYS_Asynch,TRUE, /* Run tools asynchronously */
                    NP_StackSize,tn->tn_Stack,
                    TAG_DONE)==-1)
  rc=FALSE; /* An error occured */

 CurrentDir(fl);                /* Change to old directory */
 return(rc);
}

/* Start tool as a WB process */
static BOOL StartWBTool(struct AppMessage *msg, struct ToolNode *tn,
                        char *name)
{
 BPTR fl;                        /* AmigaDOS file handle */
 register struct WBStartup *wbs; /* WBStartup message for tool */
 struct DiskObject *tdob;        /* Tool icon */
 LONG ssize;                     /* StackSize, default */
 struct MsgPort *proc;           /* Process descriptor for tool */
/* struct Process *proc;  Process descriptor for CreateNewProc */
 struct WBArg *wbad,*wbas;       /* Pointers to WB arguments */
 char *proname=NULL;             /* Name of Project icon */
 int i;

 /* Allocate memory for WBStartup */
 if (!(wbs=calloc(sizeof(struct WBStartup)+
                  sizeof(struct WBArg)*(msg->am_NumArgs+2),1))) return (FALSE);

 /* Change to tool's directory */
 fl=CurrentDir(tn->tn_DirLock);

 /* Is it a project? */
 if (tdob=GetDiskObject(name))
  if (tdob->do_Type==WBPROJECT)
   {
    proname=name;                      /* Save original name */
    name=strdup(tdob->do_DefaultTool); /* Get name of default tool */
    FreeDiskObject(tdob);
    if (!name) goto e1;                /* Enough memory? */
    tdob=GetDiskObject(name);          /* Get icon of the default tool */
   }

 /* Is it a tool? */
 ssize=tn->tn_Stack;
 if (tdob)
  {
   if (tdob->do_Type==WBTOOL)          /* Only tools supply this information */
    {
     if (tdob->do_ToolWindow) wbs->sm_ToolWindow=strdup(tdob->do_ToolWindow);
     if (tdob->do_StackSize>ssize) ssize=tdob->do_StackSize;
    }

   FreeDiskObject(tdob);
  }

 /* Load tool code */
 if (!(wbs->sm_Segment=NewLoadSeg(name,NULL))) goto e2;

 /* Build WBStartup message */
 /* wbs->sm_Message.mn_Node.ln_Type=NT_MESSAGE; PutMsg() does this for us! */
 wbs->sm_Message.mn_ReplyPort=MyMP;
 wbs->sm_Message.mn_Length=sizeof(struct WBStartup);
 wbs->sm_NumArgs=msg->am_NumArgs+1;
 wbs->sm_ArgList=wbs+1;             /* WBArg array starts after WBStartup */

 /* Initialize WBArg pointers */
 wbas=msg->am_ArgList;
 wbad=wbs->sm_ArgList;

 /* 1. argument is the tool itself! */
 if (!(wbad->wa_Lock=DupLock(tn->tn_DirLock))) goto e3;
 if (!(wbad->wa_Name=strdup(name))) goto e4;
 wbad++;

 /* If tool is a project, add it as 2. parameter to the WBArg list */
 if (proname)
  {
   if (!(wbad->wa_Lock=DupLock(tn->tn_DirLock))) goto e4;
   if (!(wbad->wa_Name=strdup(proname))) goto e4;
   wbad++;
   wbs->sm_NumArgs++;
  }

 /* Copy WB arguments */
 for (i=msg->am_NumArgs; i; i--,wbas++,wbad++)
  {
   if (!(wbad->wa_Lock=DupLock(wbas->wa_Lock)))
    {
     wbad--;             /* Skip parameters, which don't support a lock */
     wbs->sm_NumArgs--;
     continue;           /* Next parameter */
    }

   /* Sanity check for name string... Enforcer is watching you! */
   if (!wbas->wa_Name || !(wbad->wa_Name=strdup(wbas->wa_Name))) goto e4;
  }

 /* Create process */
 if (!(wbs->sm_Process=CreateProc(wbs->sm_ArgList->wa_Name,0,wbs->sm_Segment,
                                  ssize))) goto e4;

/* if (!(proc=CreateNewProcTags(NP_Seglist,wbs->sm_Segment,
                              NP_FreeSeglist,TRUE,
  Maybe someday I will know   NP_StackSize,ssize,
  what Tags I need to make    NP_Name,wbs->sm_ArgList->wa_Name,
  CreateNewProc() behave      NP_CloseInput,FALSE,
  like CreateProc()           NP_CloseOutput,FALSE,
                              TAG_DONE))) goto e4; */

 /* Send WBStartup message to tool */
/* wbs->sm_Process=&proc->pr_MsgPort; for CreateNewProc() */
 PutMsg(wbs->sm_Process,(struct Message *) wbs);
 if (proname) free(name);       /* If project, then free default tool name */
 CurrentDir(fl);                /* Change to old directory */
 wbactive++;                    /* Tool started! */
 return(TRUE);

 /* An error occurred. Free all resources */
e4: wbas=wbs->sm_ArgList;
    for (i=wbs->sm_NumArgs; i; i--,wbas++)
     {
      UnLock(wbas->wa_Lock);
      if (wbas->wa_Name) free(wbas->wa_Name);
     }
e3: UnLoadSeg(wbs->sm_Segment);
e2: if (proname) free(name);
e1: CurrentDir(fl);
    free(wbs);
    return(FALSE);
}

/* Start a tool with arguments */
void StartTool(struct ToolNode *tn, struct AppMessage *msg)
{
 BOOL rc=TRUE;
 char *cp;
 struct AppMessage emsg;

 /* No Parameters? */
 if (!msg || tn->tn_Flags&TNFLAGS_NARG)
  {
   emsg.am_NumArgs=0;       /* Dummy AppMessage has 0 arguments */
   msg=&emsg;               /* Replace pointer to real message */
  }

 /* Get tool name */
 if (!(cp=tn->tn_RealName))
  cp=tn->tn_Node.ln_Name;

 /* Tool type? */
 switch(tn->tn_Type)
  {
   case TNTYPE_CLI:
    rc=StartCLITool(msg,tn,cp);
    break;
   case TNTYPE_WB:
    rc=StartWBTool(msg,tn,cp);
    break;
  }

 if (!rc) DisplayBeep(NULL); /* An error occured */
}
