/*
	Julia
	Source is for Manx Aztec C 5.0d
	Modifications are necessary to compile this on gnuc (i.e. the bases)
	status: Freeware
	(C) Thomas Radtke 1995
*/

#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,
	WINDOWSIZING | WINDOWCLOSE | GIMMEZEROZERO | SMART_REFRESH | WINDOWDEPTH | ACTIVATE | WINDOWDRAG,
	0,0,0,0,0,0,0,0,0,
	PUBLICSCREEN
};

#define ran() ((double)rand()/(double)RAND_MAX)

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;

	for (n=0; n<colors; n++)
	{
		coltab[n]=GetRGB4(PubScreen->ViewPort.ColorMap,n);
		pentab[n]=n;
	}

	UnlockPubScreen(0L,PubScreen);

/*	order pens	*/
/*
	for (j=0; j<colors-1; j++)
	{
		for (i=j+1; i<colors; i++)
		{
			if (((coltab[i]&0x00f)+((coltab[i]&0x0f0)>>4)+((coltab[i]&0xf00)>>8))>
				((coltab[j]&0x00f) + ((coltab[j]&0x0f0)>>4) + ((coltab[j]&0xf00)>>8)))
				{
					color=coltab[i];
					coltab[i]=coltab[j];
					coltab[j]=color;

					color=pentab[i];
					pentab[i]=pentab[j];
					pentab[j]=color;
				}
		}
	}
*/
	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,pentab[colors-1]);

				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,pentab[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);

		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:
				ReplyMsg(message);
				SetWindowTitles(CustWindow,"Oh, year...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;
		}
	}	
}
