/*

Recursion Demo

(c) by Gunnar Klauberg (G.Klauberg@innoTEC1)

benutzt  GadToolsBox-Oberflaeche  und  eine  Idee  aus  Robert Sedgewick's
"Algorithms"

*/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <string.h>
#include <workbench/workbench.h>

#include "Rdemo.h"

struct Library		* GadToolsBase		= NULL;
struct Library		* WorkbenchBase		= NULL;
struct IntuituionBase	* IntuitionBase		= NULL;
struct GfxBase		* GfxBase		= NULL;
struct RastPort		* rp			= NULL;

void Menuhandle (UWORD sel);
VOID star1(WORD x, WORD y, WORD r, char z);
VOID star(WORD x, WORD y, WORD r, char z);
VOID OpenAll(VOID);
VOID CloseAll(char *msg);

VOID CloseAll(char *msg)
	{
	CloseRecusive_DemoWindow();
	CloseDownScreen();
	if (WorkbenchBase)	CloseLibrary(WorkbenchBase);
	if (IntuitionBase)	CloseLibrary(IntuitionBase);
	if (GadToolsBase)	CloseLibrary(GadToolsBase);
	if (msg)		Write(Output(),msg,strlen(msg)); /* puts(msg) */
	exit(0);
	}

VOID OpenAll(VOID)
	{
	if (!(IntuitionBase	=(struct IntuitionBase *) OpenLibrary("intuition.library",36L)))
		CloseAll(	      "Open on intuition.library failed!\n");
	if (!(WorkbenchBase	=(struct Library *) OpenLibrary(WORKBENCH_NAME,36L)))
		CloseAll(	   "Open on " WORKBENCH_NAME " failed!\n");
	if (!(GfxBase		=(struct GfxBase *) OpenLibrary("graphics.library",36L)))
		CloseAll(	      "Open on graphics.library failed!\n");
	if (!(GadToolsBase	=(struct Library *) OpenLibrary("gadtools.library",36L)))
		CloseAll(	      "Open on GadTools.library failed!\n");
	if (SetupScreen())
		CloseAll(	      "SetupScreen failed!\n");
	if (OpenRecusive_DemoWindow())
		CloseAll(	      "SetupWindow failed!\n");
	rp=Recusive_DemoWnd->RPort;
	SetDrMd(rp,JAM1);
	SetAPen(rp,1);
	}

#define plot(a,b,x,y) Move(rp,a,b);Draw(rp,x,y)
#define corner(x,y,a,b) Move(rp,(x)+(a),y);Draw(rp,x,y);Draw(rp,x,(y)+(b))
#define half(x,y,a,b) plot((x)+((a)/2),y,(x)+(a),y);plot(x,(y)+((b)/2),x,(y)+(b))
#define acor(a,b) corner(x, y, a(r*2), b(r*2))
#define bcor(a,b) half(x, y, a(r*2), b(r*2))

VOID	(*f)(WORD, WORD, WORD, char)=&star1,
	(*g)(WORD, WORD, WORD, char)=&star;

BOOL	color=FALSE;

VOID star(WORD x, WORD y, WORD r, char z)
	{
	if (color==TRUE) SetAPen(rp,1);
	if (r>1)
		{
		switch(z)
			{
			case 0: bcor(-, -); break;
			case 1: bcor(+, -); break;
			case 2: bcor(-, +); break;
			case 3: bcor(+, +); break;
			}
		if (z!=0) (*g)(x-r, y-r, r/2, 3);
		if (z!=1) (*g)(x+r, y-r, r/2, 2);
		if (z!=2) (*g)(x-r, y+r, r/2, 1);
		if (z!=3) (*g)(x+r, y+r, r/2, 0);
		}
	else
	switch(z)
		{
		case 0: acor(-, -); break;
		case 1: acor(+, -); break;
		case 2: acor(-, +); break;
		case 3: acor(+, +); break;
		}
	}

VOID star1(WORD x, WORD y, WORD r, char z)
	{
	if (color==TRUE) SetAPen(rp,2);
	switch(z)
		{
		case 0: acor(-, -); break;
		case 1: acor(+, -); break;
		case 2: acor(-, +); break;
		case 3: acor(+, +); break;
		}
	if (r>1)
		{
		if (z!=0) (*f)(x-r, y-r, r/2, 3);
		if (z!=1) (*f)(x+r, y-r, r/2, 2);
		if (z!=2) (*f)(x-r, y+r, r/2, 1);
		if (z!=3) (*f)(x+r, y+r, r/2, 0);
		}
	}

#define CLR(rp) Move(rp,0,0);ClearScreen(rp);

void Menuhandle (UWORD sel)
	{
	UWORD menu, item, sub;
	if (sel!=MENUNULL)
		{
		menu=MENUNUM(sel);
		item=ITEMNUM(sel);
		sub =SUBNUM (sel);

		switch(menu)
			{
			case 0:
			switch(item)
				{
				case 0:
					CLR(rp);
					f=star1;
					star1(130,130,64,4);
					break;
				case 1:
					CLR(rp);
					g=star;
					star(130,130,64,4);
					break;
				case 2:
					CLR(rp);
					f=star;
					g=star1;
					star(130,130,64,4);
					break;
				case 3:
					CLR(rp);
					f=star;
					g=star1;
					star1(130,130,64,4);
					break;
				case 4: // BAR
				case 5:
					color^=TRUE;
					break;
				}
			break;
			}
		}
	}

VOID main(VOID)
	{
	struct IntuiMessage *IMsg;
	OpenAll();
	star(130,130,64,4);
	while(1)
		{
		Wait(1L<<Recusive_DemoWnd->UserPort->mp_SigBit);
		while(IMsg = (struct IntuiMessage *) GetMsg(Recusive_DemoWnd->UserPort))
			{
			ReplyMsg((struct Message *)IMsg);
			switch (IMsg->Class)
				{
				case IDCMP_CLOSEWINDOW:
					CloseAll(NULL);
					break;
				case MENUPICK:
					Menuhandle(IMsg->Code);
					break;
				}
			}
		}
	}
