#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <dos/notify.h>
#include <string.h>
#include <libraries/WBStart.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <intuition/classes.h>
#include <clib/macros.h>
#include "gaugeclass.h"
#include "tinymeter.h"
#include "launchclass.h"

BOOL CopyPathList(struct PathList **pla, struct PathList **plc,struct PathList *oldpl)
{
    struct PathList *pl1=oldpl,*pl2=*plc,*pl3=NULL;
    while (pl1)
    {
	if (!(pl3 || (pl3=(struct PathList *)AllocVec(sizeof(struct PathList),MEMF_CLEAR|MEMF_PUBLIC)))) return(FALSE);
	if (pl3->PathLock=DupLock(pl1->PathLock))
	{
	    if (*pla) pl2->NextPath=MKBADDR(pl3);
	    else *pla=pl3;
	    pl2=pl3;
	    pl3=NULL;
	}
	pl1=BADDR(pl1->NextPath);
    }
    FreeVec(pl3);
    *plc=pl2;
    return(TRUE);
}

void FreePathList(struct PathList *pla)
{
    if (pla)
    {
	struct PathList *pl2;
	do
	{
	    pl2=BADDR(pla->NextPath);
	    UnLock(pla->PathLock);
	    FreeVec(pla);
	}
	while (pla=pl2);
    }
}

BOOL InitWorkbenchPath(struct tm_data *data)
{
    struct Process *wbproc=(struct Process *)FindTask("Workbench");
    if(!wbproc)     wbproc=(struct Process *)FindTask("DirectoryOpus");

    if (wbproc && (wbproc->pr_Task.tc_Node.ln_Type==NT_PROCESS))
    {
	struct CommandLineInterface *wbcli=BADDR(wbproc->pr_CLI);
	if (wbcli)
	{
	    struct PathList *dummy=0L; data->GlobalPath=0L;
	    if (CopyPathList(&data->GlobalPath,&dummy,(struct PathList *) BADDR(wbcli->cli_CommandDir)));
	}
    }
    return(TRUE); 
}

void FreeWorkbenchPath(struct tm_data *data)
{
    FreePathList(data->GlobalPath); data->GlobalPath=0L;
}

void RunCLI(struct lau_entry *entry, struct tm_data *data, struct WBArg *wbarg, ULONG numarg)
{
    BOOL            rc=FALSE;
    char           *def;
    char           *argstr=0L;
    BPTR            newcd,
		    ofh,
		    oldcd,
		    ifh;
    struct MsgPort *newct=NULL;

    if(wbarg)
    {
	if(argstr=(char *)pAllocVec(1024L))
	{
	    char    *actpos;
	    int     i;
	    strcpy(argstr,entry->lau_cmd);
	    strcat(argstr," ");
	    actpos=&argstr[strlen(argstr)];
	    for(i=0;i<numarg;i++)
	    {
		NameFromLock(((struct WBArg *)&wbarg[i])->wa_Lock,actpos,512L);
		AddPart(actpos,((struct WBArg *)&wbarg[i])->wa_Name,512L);
		strcat(actpos," ");
		actpos=&argstr[strlen(argstr)];
	    }
	}
    }
    if(entry->lau_pth)  newcd=Lock(entry->lau_pth,SHARED_LOCK);
    else                newcd=0L;
    if(!newcd)
    {
	char *foo;
	int i;
	foo=(char *)FilePart(entry->lau_cmd);
	if(def=(char *)pAllocVec(foo-entry->lau_cmd+2L))
	{
	    for(i=0;i<(foo-entry->lau_cmd);i++) def[i]=entry->lau_cmd[i]; def[i]=0;
	    newcd=Lock(def,SHARED_LOCK);
	    pFreeVec((ULONG *)def);
	}
    }
    if(!(ofh=Open(entry->lau_out, MODE_NEWFILE)))
	 ofh=Open("NIL:",         MODE_NEWFILE);
    if(ofh)
    {
	if (IsInteractive(ofh))
	{
	    struct MsgPort *oldct;
	    newct=((struct FileHandle *) BADDR(ofh))->fh_Type;
	    oldct=(struct MsgPort *)SetConsoleTask(newct);
	    ifh=Open("CONSOLE:",MODE_OLDFILE);
	    SetConsoleTask(oldct);
	}
	else ifh=Open("NIL:",MODE_OLDFILE);
	if (ifh)
	{
	    struct PathList *pla=NULL,*plc=NULL;
	    oldcd=CurrentDir(newcd);
	    if(CopyPathList(&pla,&plc,data->GlobalPath))
	    {
		if (SystemTags(argstr ? argstr : entry->lau_cmd,
		    SYS_Output,     ofh,
		    SYS_Input,      ifh,
		    SYS_Asynch,     TRUE, 
		    SYS_UserShell,  TRUE,
		    NP_StackSize,   entry->lau_stack < 4096L ? 4096L : entry->lau_stack,
		    NP_Priority,    0,
		    NP_Path,        MKBADDR(pla),
		    NP_ConsoleTask, newct,
		    TAG_DONE)!=-1) rc=TRUE;
		CurrentDir(oldcd);
		if(!rc)
		{
		    Close(ifh);
		    FreePathList(pla);
		}
	    }
	}
	if(!rc)
	{
	    Close(ofh);
	    DisplayBeep(0);
	}
    }
    UnLock(newcd);
    pFreeVec((ULONG *)argstr);
}

void RunWB(struct lau_entry *entry, struct tm_data *data, struct WBArg *wbarg, ULONG numarg)
{
    if(WBStartTags(WBStart_Name,                            entry->lau_cmd,
		   WBStart_DirectoryName,                   entry->lau_pth,
		   WBStart_Stack,                           entry->lau_stack < 4096L ? 4096L : entry->lau_stack,
		   wbarg ? WBStart_ArgumentList : TAG_END,  wbarg,
		   WBStart_ArgumentCount,                   numarg,
		   TAG_END))
    {
	DisplayBeep(0);
    }
}

void RunFile(struct lau_entry *entry, struct tm_data *data, struct WBArg *wbarg, ULONG numarg)
{
    if(entry->lau_type==0) RunWB(entry,data,wbarg,numarg);
    else                   RunCLI(entry,data,wbarg,numarg);
}
