/* Graphics1.c */
/* ARexx Macro written in C that opens an input window. */
/* This macro receives requests from the user to draw either a circle */
/* or a box and then passes those requests to Graphics2 for the */
/* actual output. */

#include "Graphics.h"

/* Library Pointers */
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct RxsLib *RexxSysBase = NULL;

/* Globals */
struct MsgPort *Graph1 = NULL;
struct MsgPort *WindowIDCMP = NULL;

/* Box Gadget */
SHORT BVectors[] = { 0, 0, 67, 0, 67, 12, 0, 12, 0, 0 };
struct Border BBorder = {	-1, -1, 3, 0, JAM1, 5, BVectors, NULL };
struct IntuiText BText = { 3, 0, JAM2, 20, 2, NULL, (UBYTE *)"BOX", NULL };
struct Gadget BGadget = { NULL, 16, 35, 66, 11, NULL, RELVERIFY, BOOLGADGET,\
	(APTR)&BBorder, NULL, &BText, NULL, NULL, BOX, NULL };
/* Circle Gadget */
SHORT CVectors[] = { 0, 0, 82, 0, 82, 15, 0,15, 0, 0 };
struct Border CBorder = { -1, -1, 3, 0, JAM1, 5, CVectors, NULL };
struct IntuiText CText = { 3, 0, JAM2, 14, 4, NULL, (UBYTE *)"CIRCLE", NULL };
struct Gadget CGadget = { NULL, 10, 14, 81, 14, NULL, RELVERIFY, BOOLGADGET,\
	(APTR)&CBorder, NULL, &CText, NULL, NULL, CIRCLE, NULL };

int main(void)
{
	int exitvalue;
	long idcmpsignal, arexxsignal, signal;
	BOOL closedown;
	struct Window *Graph;

	exitvalue = 0;
	closedown = FALSE;

	if(!Open_Libs())	/* Open the libraries I require */
	{
		exitvalue = 1;
		goto main_exit;
	}

	if(!(Graph = Open_Window((SHORT) 10, (SHORT) 10, (SHORT) 100,\
		(SHORT) 50, (ULONG) CLOSEWINDOW|GADGETUP, (ULONG)\
		WINDOWCLOSE|WINDOWDRAG, (UBYTE *) "Input Window")))
	{
		exitvalue = 2;
		goto main_exit;
	}

	AddGadget(Graph, &CGadget, (LONG) -1);
	AddGadget(Graph, &BGadget, (LONG) -1);
	RefreshGList(Graph->FirstGadget, Graph, (struct Requester *) 0, -1);

		/* Get a Message Port */
	if(!(Graph1 = Open_Port((char *) MYPORT)))
	{
		exitvalue = 3;
		goto main_exit;
	}

	WindowIDCMP = Graph->UserPort;	/* Get the window's user msg port */
	idcmpsignal = 1<<WindowIDCMP->mp_SigBit; /* get idcmp signal */
	arexxsignal = 1<<Graph1->mp_SigBit; /* arexx signal */

	if(!(Execute("run Graphics2", (BPTR) 0, (BPTR) 0)))
	{
		printf("Unable to load Graphics2, exiting.");
		goto main_exit;
	}

	for (;;)	/* infinate loop */
	{
		/* See if there are any messages waiting */
		signal = Wait(idcmpsignal|arexxsignal);

		if (signal&idcmpsignal)	/* take care of idcmp messages first */
			closedown = getidcmpmsg();

		if (signal&arexxsignal)
			getarexxmsg();	/* take care of any arexx messages */

		if (closedown)	/* see if CLOSEWINDOW gadget was selected */
			break;
	}

main_exit:
	if(Graph1)
		Release_Port();
	if(Graph)
	{
		RemoveGadget(Graph, &BGadget);
	 	RemoveGadget(Graph, &CGadget);
		Graph->FirstGadget = (struct Gadget *) 0;
		CloseWindow(Graph);
	}
	Close_Libs();
	return(exitvalue);
}


BOOL Open_Libs(void)
{
	BOOL success;

	success = TRUE;

	if(!(IntuitionBase = (struct IntuitionBase *)\
		OpenLibrary("intuition.library", INTUITION_REV)))
	{
		printf("intuition.library could not be loaded.\n");
		success = FALSE;
	}

	if(!(GfxBase = (struct GfxBase *)\
		OpenLibrary("graphics.library", GRAPHICS_REV)))
	{
		printf("graphics.library could not be loaded.\n");
		success = FALSE;
	}

	if(!(RexxSysBase = (struct RxsLib *) OpenLibrary(RXSNAME, 0L)))
	{
		printf("rexxsyslib.library could not be loaded.\n");
		success = FALSE;
	}

	return(success);
}


void Close_Libs(void)
{
	if(IntuitionBase)
		CloseLibrary((struct Library *) IntuitionBase);

	if(GfxBase)
		CloseLibrary((struct Library *) GfxBase);

	if(RexxSysBase)
		CloseLibrary((struct Library *) RexxSysBase);

}


struct Window *Open_Window(SHORT leftedge, SHORT topedge, SHORT width, SHORT height,
			   ULONG idcmp, ULONG flags, UBYTE *title)
{
	struct NewWindow NewWindow;

	NewWindow.LeftEdge = leftedge;
	NewWindow.TopEdge = topedge;
	NewWindow.Width = width;
	NewWindow.Height = height;
	NewWindow.DetailPen = (UBYTE) 0;
	NewWindow.BlockPen = (UBYTE) 1;
	NewWindow.IDCMPFlags = idcmp;
	NewWindow.Flags = flags;
	NewWindow.FirstGadget = (struct Gadget *) 0;
	NewWindow.CheckMark = (struct Image *) 0;
	NewWindow.Title = title;
	NewWindow.Screen = (struct Screen *) 0;
	NewWindow.BitMap = (struct BitMap *) 0;
	NewWindow.MinWidth = width;
	NewWindow.MinHeight = height;
	NewWindow.MaxWidth = (USHORT) width;
	NewWindow.MaxHeight = (USHORT) height;
	NewWindow.Type = WBENCHSCREEN;

	return(OpenWindow(&NewWindow));
}


struct MsgPort *Open_Port(char * name)
{
	struct MsgPort *new_port;

	new_port = 0;

	Forbid();	/* turn off task switching */

		/* check to see if a port already exists by my port's name */
	if(!(FindPort(name)))
		new_port = CreatePort(name,(long) 0); /* ok to create one */

	Permit();	/* turn task switching on */

	return(new_port);
}


void Release_Port(void)
{
	struct RexxMsg *rtnmsg;

	Forbid();

	/* delete all outstanding messages */
	while (rtnmsg = (struct RexxMsg *) GetMsg(Graph1))
	{
		if (rtnmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
		{ /* a reply to one of my messages so delete it */
		  DeleteArgstring(rtnmsg->rm_Args[0]);
		  DeleteRexxMsg(rtnmsg);
		}else{ /* not one of my messages so reply to it */
		  rtnmsg->rm_Result1 = RC_ERROR; /* indicate error */
		  ReplyMsg((struct Message *)rtnmsg);
		}
	}

	DeletePort(Graph1); /* delete the port */

	Permit();
	return;
}


BOOL getidcmpmsg(void)
{
	BOOL returnval;
	ULONG msgclass;
	USHORT myid;
	struct Gadget *gadgetaddr;
	struct IntuiMessage *message;

	returnval = FALSE;

	while((message = (struct IntuiMessage *) GetMsg(WindowIDCMP)))
	{
		/* extract the important information */
		msgclass = message->Class;
		gadgetaddr = (struct Gadget *) message->IAddress;
		myid = gadgetaddr->GadgetID;

		ReplyMsg((struct Message *)message); /* reply to the message right away */

		switch (msgclass)
		{
			case GADGETUP:
				switch (myid)
				{
					case CIRCLE:
						arexxsend((STRPTR) "CIRCLE");
						break;
					case BOX:
						arexxsend((STRPTR) "BOX");
						break;
					default:
						printf("Not one of my Gadgets!");
				}
				break;
			case CLOSEWINDOW:
				arexxsend((STRPTR) "CLOSEWINDOW");
				returnval = TRUE;
				break;
			default:
				printf("Something is seriously wrong here!");
		}
	}

	return(returnval);
}


void arexxsend(STRPTR commandstr)
{
	struct MsgPort *sendport;
	struct RexxMsg *rexxmsg;

	if (!(rexxmsg = CreateRexxMsg((struct RexxMsgPort *)Graph1,\
                                      (STRPTR) 0, (STRPTR) MYPORT1)))
		goto rs_exit;		/* not able to create a message */

	if (!(rexxmsg->rm_Args[0] = CreateArgstring(commandstr,\
					(ULONG) strlen((char *) commandstr))))
	{
		DeleteRexxMsg(rexxmsg);	/* not able to create argstring */
		goto rs_exit;	/* so delete rexxmsg and leave routine */
	}

	rexxmsg->rm_Action = RXCOMM;

	Forbid();

	if (!(sendport = FindPort(MYPORT1)))
		{
		Permit();	/* unable to find the port so delete the */
		DeleteArgstring(rexxmsg->rm_Args[0]); /* argstring */
		DeleteRexxMsg(rexxmsg);	/* and the rexxmsg */
		goto rs_exit;		/* and leave the routine */
	}

		/* everything went ok so send the message */
	PutMsg(sendport, (struct Message *) rexxmsg);

	Permit();

rs_exit:

	return;
}


void getarexxmsg(void)
{
	struct RexxMsg *rtnmsg;

	rtnmsg = (struct RexxMsg *) GetMsg(Graph1);

	if (rtnmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
	{		/* see if this is a reply to one of my messages */
		DeleteArgstring(rtnmsg->rm_Args[0]); /* if so, delete */
		DeleteRexxMsg(rtnmsg);	/* the argstring and rexxmsg */
	}else{
		rtnmsg->rm_Result1 = RC_ERROR;	/* return an error condition */
		ReplyMsg((struct Message *)rtnmsg); /* Sorry, no commands today. */
	}

	return;
}
