#include <math.h>
#include <stdlib.h>
#include <intuition/intuitionbase.h>
#include <stdio.h>

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

#define rp CustWindow->RPort

struct NewWindow BlankWindow=
{
	50,50,200,100,1,2,
	MOUSEBUTTONS | CLOSEWINDOW | NEWSIZE,
	RMBTRAP | WINDOWSIZING | WINDOWCLOSE | GIMMEZEROZERO | SMART_REFRESH | WINDOWDEPTH | ACTIVATE | WINDOWDRAG,
	0,0,0,0,0,0,0,0,0,
	PUBLICSCREEN
};

/*	ran() is an Aztec C library function	*/

#ifndef AZTEC
#define ran() ((double)rand()/(double)RAND_MAX)
#endif

main()
{
	double icon,rcon,is,di,rs,dr,iinc,rinc;
	USHORT i,j,n,colors;
	USHORT x,y,xsize,ysize;
	double re2,re,im,restart,imstart;
	char name[256];
	int col[2];
	int paint=1;
	double memi,memr;
	short tmp,startx,starty,xneu,yneu;
	double dx,dy;
	struct Screen *PubScreen;
	struct Window *CustWindow;
	struct IntuiMessage *message;
	struct IntuiMessage *GetMsg();
	ULONG color,coltab[256],pentab[256];

	if ((IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0))==NULL) exit(1);
	if ((GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0))==NULL) exit(1);

/*	get Number of colors and screensize	*/

	GetDefaultPubScreen(name);
	PubScreen=(struct Screen *)LockPubScreen(name);

	colors=1<<(PubScreen->BitMap.Depth);

	xsize=PubScreen->Width;
	ysize=PubScreen->Height;

	UnlockPubScreen(0L,PubScreen);

	BlankWindow.MinWidth=80;
	BlankWindow.MinHeight=30;
	BlankWindow.MaxWidth=xsize;
	BlankWindow.MaxHeight=ysize;
	BlankWindow.Screen=PubScreen;

	if ((CustWindow=(struct Window *)OpenWindow(&BlankWindow))==NULL)
	{
		printf("Kann den Bildschirm %s nicht finden\n",name);
	}

/*	Preferences	*/

	is=-3.0;		/*	Im-range	*/
	di=6.0;

	rs=-3.0;		/*	Re-range	*/
	dr=6.0;

	icon=-.2;	/*	complex constant	*/
	rcon=-1.3;

/*	make love to julia	*/

	while (1)
	{
		rinc=dr/(double)(CustWindow->GZZWidth);
		iinc=di/(double)(CustWindow->GZZHeight);

		SetWindowTitles(CustWindow,"Coming...",-1);

		if (!paint) goto next;

		memi=is;

		for (y=0; y<CustWindow->GZZHeight; y++)	/*	row	*/
		{
			memr=rs;

			for (x=0; x<CustWindow->GZZWidth; x++)
			{
				re=restart=(rs+=rinc);
				im=imstart=is;

				SetAPen(rp,0);

				for (n=0; n<colors-1; n++)
				{
					re2=re*re-im*im+rcon;
					im=2*re*im+icon;
					re=re2;

					if ((re-restart)*(re-restart)+(im-imstart)*(im-imstart)>100.0)
					{
						SetAPen(rp,n);
						break;
					}
				}
				WritePixel(rp,x,y);
			}
			rs=memr;
			is+=iinc;
		}
		is=memi;

next:		paint=1;

		SetWindowTitles(CustWindow,"Fun with Julia",-1);
wait:
		Wait(1L<<CustWindow->UserPort->mp_SigBit);

		message=GetMsg(CustWindow->UserPort);
/*
		printf("class: %x code: %x\n",message->Class,message->Code);
*/
		switch (message->Class)
		{
			case CLOSEWINDOW:
				ReplyMsg(message);
				CloseWindow(CustWindow);
				CloseLibrary(IntuitionBase);
				CloseLibrary(GfxBase);
				exit(1);
				break;

			case NEWSIZE:
				ReplyMsg(message);
				continue;
				break;

			default:
				break;
		}

		switch (message->Code)
		{
			case SELECTDOWN+1:
				ReplyMsg(message);

				while (1)
				{
					message=GetMsg(CustWindow->UserPort);

					if (message->Code==SELECTUP+1)
					{
						rs+=(-0.5*dr+(double)(CustWindow->GZZMouseX)*rinc);
						is+=(-0.5*di+(double)(CustWindow->GZZMouseY)*iinc);
						ReplyMsg(message);
						break;
					}
				}
				break;

			case SELECTDOWN:
				ReplyMsg(message);
				SetWindowTitles(CustWindow,"Oh, yeah...do it to me !",-1);

				startx=x=xneu=CustWindow->GZZMouseX;
				starty=y=yneu=CustWindow->GZZMouseY;

				SetDrMd(rp,2);

				while (1)
				{
					message=GetMsg(CustWindow->UserPort);

					if (message->Code==SELECTUP)
					{
						SetDrMd(rp,1);

						if (xneu<startx)
						{
							tmp=xneu;
							xneu=startx;
							startx=tmp;
						}
						if (yneu<starty)
						{
							tmp=yneu;
							yneu=starty;
							starty=tmp;
						}

						dx=(double)xneu-(double)startx;
						dy=(double)yneu-(double)starty;

						if (dx && dy)
						{
							rs+=(double)startx*rinc;
							is+=(double)starty*iinc;
							dr=dx*rinc;
							di=dy*iinc;
						}
						else
						{
							is=-3.0;
							di=6.0;
							rs=-3.0;
							dr=6.0;
							rcon=2.0*ran()-1.0;
							icon=2.0*ran()-1.0;
						}
						ReplyMsg(message);
						break;
					}

					if ((xneu=CustWindow->GZZMouseX)!=x || (yneu=CustWindow->GZZMouseY)!=y)
					{
						if (xneu<0) xneu=0;
						if (yneu<0) yneu=0;
						if (xneu>=CustWindow->GZZWidth) xneu=CustWindow->GZZWidth-1;
						if (yneu>=CustWindow->GZZHeight) yneu=CustWindow->GZZHeight-1;
						Move(rp,startx,starty);
						Draw(rp,startx,y);
						Draw(rp,x,y);
						Draw(rp,x,starty);
						Draw(rp,startx,starty);

						Move(rp,startx,starty);
						Draw(rp,startx,yneu);
						Draw(rp,xneu,yneu);
						Draw(rp,xneu,starty);
						Draw(rp,startx,starty);

						x=xneu;
						y=yneu;
					}
				}
				break;

			default:
				paint=0;
				break;
		}
	}	
}
