/* RxWB.c	(c) Bob Malzan 1991

	funktioniert genau wie der rx-Befehl, nur führt
	RxWB ARexx-Programme auf der WorkBench aus.
	Das ARexx-Prg. muß vom Typ 'Project' sein und als
	'default tool' RxWB (oder C:RxWB ...) eingetragen haben.

	Das ARexx-Programm muß unter 'Tool Types' einen Eintrag
	der Form
		'WINDOW=0/0/640/256/RxWB-Fenster'
	oder so ähnlich haben, sonst bricht das Programm ab!

	Man kann mehrere Jobs hintereinander aufrufen, indem
	man mehrere Icons mit Shift-Taste selektiert und erst
	beim letzten den Doppelklick gibt.
*/

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <libraries/dosextens.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <intuition/intuitionbase.h>
#include "Rexx.h"

/*    keine Extension, sieht auf der WBench besser aus    */
#define REXX_EXTENSION	""

/*     Funktionsdeklarationen (vergib mir, ANSI-C !)      */
void			CleanUp();
BOOL			RxIO();

extern void		*AllocMem();
extern struct RexxMsg	*CreateRexxMsg(),*GetMsg();
extern STRPTR		CreateArgstring();
extern struct MsgPort	*CreatePort(),*FindPort();
extern void		*OpenLibrary();

/*--------------------------------------------------------*/
/*                   Globale Strukturen                   */
/*--------------------------------------------------------*/
extern struct IntuitionBase *IntuitionBase = NULL;
LONG		*RexxSysBase = NULL;	/* rexx library base */
LONG		*IconBase    = NULL;
struct MsgPort	*rexx_port = NULL;	/* Rexx Port         */
struct MsgPort	*RxWB_port = NULL;	/* mein Port         */
struct RexxMsg	*RxMsg;
char		PortName[40];		/* muß noch definiert werden */
char		FehlerString[40];	/* für die Fehlermeldungen */
UBYTE		FehlerOut[45];		/* Fehlerausgabebuffer */

struct	IntuiText OkText =
{
  3,0,		/* FrontPen, BackPen; */
  JAM1,		/* DrawMode */
  6,4, 		/* LeftEdge, TopEdge */
  NULL, 	/* *ITextFont */
  (UBYTE *)"Kapiert!",
  NULL 		/* *NextText; */
};

struct	IntuiText ErrText =
{
  0,2,		/* FrontPen, BackPen; */
  JAM1,		/* DrawMode */
  10,12,	/* LeftEdge, TopEdge */
  NULL, 	/* *ITextFont */
  (UBYTE *)NULL, /* wird später eingefügt... */
  NULL 		/* *NextText; */
};

/*--------------------------------------------------------*/
/*                    Hilfsfunktionen                     */
/*--------------------------------------------------------*/
void	CleanUp(str)
char	*str;
{
  if (RxWB_port)	DeletePort(RxWB_port);
  if (RexxSysBase)	CloseLibrary(RexxSysBase);
  if (IconBase)		CloseLibrary(IconBase);
  if (IntuitionBase)	CloseLibrary(IntuitionBase);

  if (str)
  {
    sprintf(FehlerOut,"RxWB: %s",str);
    ErrText.IText = FehlerOut;
    AutoRequest(IntuitionBase->ActiveWindow,&ErrText,NULL,&OkText,NULL,GADGETUP,
		400,60);
  }
  exit(0);
}

void	OpenUp()
{
  IconBase = OpenLibrary("icon.library",0L);
  if (!IconBase) CleanUp("Pardon, konnte icon.library nicht öffnen!");

  IntuitionBase = OpenLibrary("intuition.library",0L);
  if (!IntuitionBase) CleanUp("Pardon, konnte intuition.library nicht öffnen!");

  RexxSysBase = OpenLibrary("rexxsyslib.library",0L);
  if (!RexxSysBase) CleanUp("Pardon, konnte rexxsyslib.library nicht öffnen!");

  rexx_port = FindPort("REXX");
  if (!rexx_port) CleanUp("RexxMast muß zuerst gestartet werden!");

  /* Jetzt brauche ich einen Public Port für Antworten */
  Forbid();  RxWB_port = CreatePort(PortName,0L);  Permit();

  if (!RxWB_port) CleanUp("Pardon, konnte keinen REXX-Port öffnen!");
}

/*--------------------------------------------------------*/
void main(NotWBMsg,WBenchMsg)
int NotWBMsg; struct WBStartup *WBenchMsg;
{
  int			Arg;
  LONG			Task,FindTask();
  struct FileHandle	OldLock,CurrentDir();
  STRPTR		FName,FindToolType();
  struct DiskObject	*DO,*GetDiskObject();
  struct FileHandle	*ConWin=NULL,*Open();

  if (NotWBMsg) exit(5); /* wurde nicht von WB gestartet */

  Task=FindTask(0L);
  sprintf(PortName,"RxWB_%lx",Task);

  OpenUp();
  *FehlerString = '\0';

  if (WBenchMsg->sm_NumArgs==1)
    CleanUp("Welches ARexx-Makro sollte ich denn starten?");

  for (Arg=1; Arg<WBenchMsg->sm_NumArgs; Arg++)
  {
    /*            aktuelles Verzeichnis einstellen            */
    /*   DosLibrary wurde automatisch geöffnet (Startup)    */
    OldLock = CurrentDir(WBenchMsg->sm_ArgList[Arg].wa_Lock);

    /*        Privates Fenster für dieses Icon öffnen       */
    DO = GetDiskObject(WBenchMsg->sm_ArgList[Arg].wa_Name);
    if (!DO)
    {
      CleanUp("An diesem Icon war irgendwas falsch...");
    }

    /*           Ich bearbeite nur PROJECT-Icons...           */
    if (DO->do_Type == WBPROJECT)
    {
      /*        Suche nach einem Eintrag für WINDOW=xxx         */
      FName = FindToolType(DO->do_ToolTypes,"WINDOW");
      if (!FName)
      {
        FreeDiskObject(DO);
        CleanUp("Zuerst in ToolTypes ein Fenster definieren!");
      }

      /*                   Das Fenster öffnen                   */
      ConWin = Open(FName,MODE_NEWFILE);
      if (!ConWin)
      {
        FreeDiskObject(DO);
        CleanUp("Kann Fenster nicht öffnen!");
      }

      /*        Befehl abschicken und auf Antwort warten        */
      if ( !RxIO(WBenchMsg->sm_ArgList[Arg].wa_Name,ConWin,ConWin) )
        CleanUp("Konnte Makro nicht starten!");

      /*                Auf Programmende warten                 */
      Wait(1L<<RxWB_port->mp_SigBit);

      /* ich habe eine Antwort erhalten... */
      RxMsg = GetMsg(RxWB_port);

      /* ist das auch wirklich die Antwort? */
      if (RxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
      {
        /*                  Fehler aufgetreten?                   */
        if (RxMsg->rm_Result1)
        {
          if (RxMsg->rm_Result2)
          {
            sprintf(FehlerString,"REXX-Fehler: %ld",RxMsg->rm_Result2);
          }
          else sprintf(FehlerString,"Fehler: %ld",RxMsg->rm_Result2);
        }
        /*                    RxMsg freigeben                     */
        DeleteArgstring(RxMsg->rm_Args[0]);
        DeleteRexxMsg(RxMsg);
      }
      else
      {
        /*        ich kann mit der Message nix anfangen...        */
        /*              aber zurückgeben muß ich sie              */
        RxMsg->rm_Result1 = RC_ERROR;
        RxMsg->rm_Result2 = ERR10_008;
        ReplyMsg(RxMsg);
      }

      if (ConWin)
      {
        Close(ConWin);
        ConWin = NULL;
      }
    }
    FreeDiskObject(DO);
    CurrentDir(OldLock);
  }

  /*                         Schluß                         */
  CleanUp(*FehlerString ? FehlerString : NULL);
}

BOOL RxIO(Cmd,In,Out)
char *Cmd;
LONG In,Out;
{
  struct RexxMsg	*RxCmdMsg;   /* this is the message */
  struct FileHandle	*fhandle,*Open();

  /* Ich brauche ein Message Packet */
  if ( (RxCmdMsg =
        CreateRexxMsg(RxWB_port,REXX_EXTENSION,RxWB_port->mp_Node.ln_Name))
       == NULL)  return(FALSE);

  RxCmdMsg->rm_Stdin  = In;
  RxCmdMsg->rm_Stdout = Out;

  /* ArgString in der Message einsetzen */
  if ((RxCmdMsg->rm_Args[0] = CreateArgstring(Cmd,strlen(Cmd)))==NULL)
  {
    DeleteRexxMsg(RxCmdMsg);
    return(FALSE);
  }

  /* sage zu REXX: dies ist ein COMMAND, nicht eine FUNCTION, etc. */
  RxCmdMsg->rm_Action = RXCOMM;

  /* und los! */
  PutMsg(rexx_port,RxCmdMsg);

  return(TRUE);
}
