/* Graphics2.c */
/* ARexx Macro written in C to be a companion program to Graphics1. */
/* This macro receives messages from Graphics1 and then draws the */
/* requested figures to the output window. */

#include "Graphics.h"

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

/* Globals */
struct MsgPort *Graph2 = NULL;

int main(void)
{
  int exitvalue;
  long x, x1, y, y1, radius;
  struct Window *Graph;
  struct RastPort *rp;
  struct RexxMsg *command;

  exitvalue = 0;

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

  if(!(Graph = Open_Window((SHORT) 100, (SHORT) 100, (SHORT) 400,\
      (SHORT) 100, (ULONG) 0, (ULONG) WINDOWDRAG,\
      (UBYTE *) "Output Window")))
  {
    exitvalue = 2;
    goto main_exit;
  }

  /* Get an ARexx Message Port */
  if((Graph2 = Open_Port((char *) MYPORT1)) == 0)
  {
    exitvalue = 3;
    goto main_exit;
  }

  rp = Graph->RPort;  /* Get the window's raster port struct pointer */

  seedrandom();

  for (;;)  /* infinate loop */
  {
    /* See if there is a message waiting */
    if (!(command = (struct RexxMsg *)GetMsg(Graph2)))
    {
      WaitPort(Graph2);  /* If not, wait for one */
      command = (struct RexxMsg *)GetMsg(Graph2);
    }

    if (strcmp((char *)command->rm_Args[0], "CIRCLE") == 0)
    {
      /* Draw a circle */
      radius = random((double) 1, (double) 48);
      x = random((double) 1+radius, (double) 398-radius);
      y = random((double) 1+radius, (double) 98-radius);
      SetAPen(rp, 1L);
      DrawCircle(rp, x, y, radius);
    }

    if (strcmp((char *)command->rm_Args[0], "BOX") == 0)
    {
      /* Draw a box */
      x = random((double) 1, (double) 397);
      y = random((double) 1, (double) 97);
      x1 = random((double) 1+x, (double) 398);
      y1 = random((double) 1+y, (double) 98);
      SetAPen(rp, 3L);
      RectFill(rp, x, y, x1, y1);
    }

    if (strcmp((char *)command->rm_Args[0], "CLOSEWINDOW") == 0)
    {
      ReplyMsg((struct Message *) command);
      break;  /* leave the for loop */
    }

    ReplyMsg((struct Message *) command);
  }

main_exit:
  if(Graph2)
    Release_Port();
  if(Graph)
    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((char *)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 *command;

  Forbid();

  /* reply to any outstanding messages */
  while (command = (struct RexxMsg *) GetMsg(Graph2))
  {
    command->rm_Result1 = RC_ERROR; /* indicate error */
    ReplyMsg((struct Message *)command);
  }

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

  Permit();
  return;
}


void seedrandom(void)
{
  time_t *dummy;

  sran((double) time(dummy));
}


long random(double lower, double upper)
{
  return((long) (ran()*upper+lower));
}
