#include "struct.c"

struct DosLibrary    *DOSBase;
struct Library       *IconBase;
struct IntuitionBase *IntuitionBase;
struct Library       *RexxSysBase;
struct ExecBase	     *SysBase;

BOOL OpenLibs(void);
void CloseLibs(void);
long SimpleRequest(STRPTR, STRPTR, ...);
BOOL SendRexxMsg(char *);

char *DefaultRexxCmd = "ed";

const char Version[] = "$VER: WBRexx V1.1  "__DATE__"  "__TIME__;


ULONG __saveds main(void)
{
 struct Process	   *Me;
 struct WBStartup  *Msg = NULL;
 int  i;
 char Buffer[255], *RexxCmd;
 BPTR		    OldDir;
 struct DiskObject *ToolIcon, *ProjectIcon;

 SysBase = *((struct ExecBase **) 4L);
 if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37))
 {
  if (OpenLibs())
  {
   Me = (struct Process *)FindTask(NULL);
   if (Me->pr_CLI) SimpleRequest("My Fault", "WBRexx should only run from WorkBench");  
   else
   {
    /* get the WorkBench Startup message */
    WaitPort(&Me->pr_MsgPort);
    Msg = (struct WBStartup *)GetMsg(&Me->pr_MsgPort);
    
    /* Get DefaultRexxCmd from REXXCMD ToolType of Program */
    OldDir = CurrentDir(GetProgramDir());
    if (ToolIcon = GetDiskObject(Msg->sm_ArgList[0].wa_Name))
     RexxCmd = FindToolType(ToolIcon->do_ToolTypes, "REXXCMD");
    if (RexxCmd) DefaultRexxCmd = RexxCmd;
    CurrentDir(OldDir);
    
    if (Msg->sm_NumArgs) for(i=1; i<Msg->sm_NumArgs; i++)
    {
     /* Get RexxCmd from ProjectIcon (if any) */
     OldDir = CurrentDir(Msg->sm_ArgList[i].wa_Lock);
     if (ProjectIcon = GetDiskObject(Msg->sm_ArgList[i].wa_Name))
      RexxCmd = FindToolType(ProjectIcon->do_ToolTypes, "REXXCMD");
     if (!RexxCmd) RexxCmd = DefaultRexxCmd;
     
     sprintf(Buffer, "%s %s", RexxCmd, Msg->sm_ArgList[i].wa_Name);
     /* Send Command to ReXX */
     SendRexxMsg(Buffer);
     
     if (ProjectIcon) FreeDiskObject(ProjectIcon);
     CurrentDir(OldDir);
    }
    /* No Args, simple start RexxCmd without them */
    else SendRexxMsg(DefaultRexxCmd);
    
    if (ToolIcon) FreeDiskObject(ToolIcon);
   }
   CloseLibs();
  }
  CloseLibrary(DOSBase);
 }
 /* Why no DOS ? Get Kick 2.0 !!! */
 else Alert(AT_Recovery | AG_OpenLib | AO_DOSLib);
 Forbid();
 /* Give WB its message back */
 if (Msg) ReplyMsg(Msg);
}


/* a simple requester, stolen from Stefan Sticht */
long SimpleRequest(STRPTR Gadgets, STRPTR Text, ...)
{
 static struct EasyStruct SimpleReq =
 {
  sizeof(struct EasyStruct),
  0L,
  NULL, NULL, NULL
 };
 va_list ap;
 long	 rc;

 va_start(ap, Text);
 SimpleReq.es_Title = "RexxEdit";
 SimpleReq.es_TextFormat = (UBYTE *)Text;
 SimpleReq.es_GadgetFormat = (UBYTE *)Gadgets;

 rc = EasyRequestArgs(NULL, &SimpleReq, NULL, ap);
 va_end(ap);

 return rc;
}

/* more comfortable than OpenLibrary() */
struct Library *OpenLib(STRPTR Name, ULONG Version)
{
 struct Library *Lib;
 BOOL		 Ok = TRUE;

 do
 {
  if (!(Lib = OpenLibrary(Name, Version)))
  {
   if (IntuitionBase)
    Ok = SimpleRequest("Retry|Cancel", "%s (V%ld+) can't be opened!", Name, Version);
   else
    Ok = FALSE;
  }
 } while (!Lib && Ok);

 return Lib;
}

/* Open my Libs */
BOOL OpenLibs(void)
{
 if (IntuitionBase = (struct IntuitionBase *)OpenLib("intuition.library", 37))
  if (IconBase = OpenLib("icon.library", 37))
   if (RexxSysBase = OpenLib("rexxsyslib.library", 36))
    return TRUE;

 return FALSE;
}

/* Close Them */
void CloseLibs(void)
{
 CloseLibrary(RexxSysBase);
 CloseLibrary(IconBase);
 CloseLibrary(IntuitionBase);
}

/* Send a Message to REXX, this routine was written by tron@uni-paderborn.de */
/* and used in his famous SRI program. 					     */
BOOL SendRexxMsg(char *Command)
{
 struct MsgPort *ReplyPort,*TargetPort;
 struct RexxMsg *OutRexxMsg;
 UBYTE *CmdArgstring;

 if (ReplyPort=CreateMsgPort())
 {
  if (OutRexxMsg=CreateRexxMsg(ReplyPort,NULL,RXSDIR))
  {
   if (CmdArgstring=CreateArgstring(Command,strlen(Command)))
   {
    OutRexxMsg->rm_Action=RXCOMM|RXFF_NOIO;
    OutRexxMsg->rm_Args[0]=(STRPTR)CmdArgstring;

    Forbid();
    if (TargetPort=FindPort(RXSDIR))
    {
     PutMsg(TargetPort,&OutRexxMsg->rm_Node);
     Permit();

     WaitPort(ReplyPort);
     GetMsg(ReplyPort);

     DeleteArgstring(CmdArgstring);
     DeleteRexxMsg(OutRexxMsg);
     DeleteMsgPort(ReplyPort);

     return TRUE;
    }
    Permit();
    DeleteArgstring(CmdArgstring);
   }
   DeleteRexxMsg(OutRexxMsg);
  }
  DeleteMsgPort(ReplyPort);
 }

 return FALSE;
}

