#include	"functions.h"
#include	"exec/types.h"	/*Needed for SOFFSET macro*/
#include	"exec/execbase.h"
#include	"exec/tasks.h"
#include	"exec/memory.h"
#include	"exec/ports.h"
#include	"clib/graphics_protos.h"
#include	"graphics/view.h"
#include	"graphics/gfx.h"
#include	"graphics/gfxbase.h"
#include	"graphics/gfxmacros.h"
#include	"graphics/rastport.h"
#include	"intuition/intuitionbase.h"
#include	"intuition/intuition.h"
#include	"intuition/preferences.h"
#include	"libraries/dos.h"
#include	"libraries/dosextens.h"
#include	"stdio.h"
#include	"exec/io.h"
#include	"iff/iff.h"
#include	"iff/ilbm.h"

double XWidth,XHeight,XCenter,YCenter,HWidth,HHeight,Factor,xRel,yRel,Zr,Zi,Z2;
double Zr2,Zi2,Limit,FP7,Two;
double LastX,LastY,LastLim,LastFactor;
LONG	xtemp,ytemp,MaxCnt,CurCnt,XC,YC,LeftEdge,RightEdge,NearEdge,FarEdge;
LONG	S1Height,S1Width,MltPlr;
ULONG	*PlnPtr;

BPTR	FileHandle;
#define	Pf_Size	0xe8
#define	ScnFlg	0x1;
#define	LacFlg	0x2;
#define	ChdFlg	DefFlg | CHECKIT | CHECKED
#define	ChkFlg	DefFlg | CHECKIT

CmpFlg	= MOUSEBUTTONS | MENUPICK;
MyFlag	 =	NOCAREREFRESH|REPORTMOUSE|BORDERLESS;
MenFlg	 =	MENUENABLED | MIDRAWN;
DefFlg	 =	ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP;


struct Library *DOSBase;
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct ExecBase	*SysBase;
struct	Gadget	*GadStuff;
struct	NewScreen	ns;
struct	NewWindow	nw;
BYTE	CurrentXOffset;
BYTE	CurrentYOffset;
UBYTE	Title[] = "                          Julian Explorer";
UBYTE	*WindowName;
SHORT	SWidth,SHeight;
USHORT	MyView,SUFlag,SysFlag,ScnSts,OvsChk,LacChk,LacMod,NLcChk,MenVal,NrmChk;
struct	Screen	*IntScreen;
struct	Screen	*WBScreen;
struct	Window	*InfoWindow;
struct	Window	*IntWindow;
struct	MsgPort	*MyPort,*IntPort;
struct	RastPort	*MyRasta,*WBRast,*CWRast;
struct	ViewPort	VPorta,VPortb;
struct	Preferences	MyNewPrefs,*CurPrefs;
struct	Menu		Menu1,Menu2,Menu3,Menu4;
struct	MenuItem	*MIStruct;
struct	IntuiText	*ITStruct;

struct	MenuItem	MI11,MI12,MI13,MI14;
struct	MenuItem	MI21,MI22,MI23,MI24;
struct	MenuItem	MI31,MI32,MI33,MI34;
struct	MenuItem	MI41,MI42,MI43,MI44;
struct	IntuiText	IT11,IT12,IT13,IT14;
struct	IntuiText	IT21,IT22,IT23,IT24;
struct	IntuiText	IT31,IT32,IT33,IT34;
struct	IntuiText	IT41,IT42,IT43,IT44;

struct	PLANEPTR	*PlanePtrA,*PlanePtrB;
static	char	Err020[]	= "Sorry, but this Mandelbrot Generator requires both a 68881 and a 68020!";
static	char	Err021[]	= "Use SManLb as a slow alternative!";
static	char	Message[] 	= "by David M. McKinstry";
static	char	Mesag2[]	= "Copyright ";
UBYTE	Mesag2b[]	= 0xa9;
UBYTE	Comma[] = 0x2c;
static	char	Mesag2c[]	= " 1989-91";
static	char	Mesag3[]	= "System Hardware: ";
static	char	Mesag4[]	= "Use the menu options on the Custom Screen to change the following parameters!";
static	char	Mesag5[]	= "Click on the Close Gadget to bring the Custom Screen forward!";
static	char	Mesag6[]	= "(Note:  This window won't be closed, just hidden.)";
static	char	Mesag7[]	= "To return to this WorkBench Screen, select 'About' from the SManLb menu!";
static	char	ScrMsg[]	= "Screen center is at ";
static	char	ChpMsg[]	= "Chip Memory Free = ";
static	char	ChpEnd[]	= "                ";
static	char	FstMsg[]	= "Fast Memory Free = ";
static	char	FstEnd[]	= "                ";
static	char	WdtMsg[]	= "Screen Width =  ";
static	char	WdtEnd[]	= "        ";
static	char	HgtMsg[]	= "Screen Height = ";
static	char	HgtEnd[]	= "        ";
static	char	MagMsg[]	= "Magnification = ";
static	char	MagEnd[]	= "                  ";
static	char	XPos[]		= "x = ";
static	char	XPsEnd[]	= "                  ";
static	char	YPos[]		= "y = ";
static	char	YPsEnd[]	= "                  ";
static	char	CntMsg[]	= "Maximum Count = ";
static	char	CntEnd[]	= "        ";
static	char	HavMsg[]	= "You have at least a 68020 and 68881.  Why not use SManCP?";
static	char	StrngBuffer[200];
SHORT	VertPos;
USHORT	CTable[] = {0,0xf00,0xff0,0x3f8,0x5ea,0xf3a,0x0de,0xf80,0x9f0,0x7df,0x69f,
					0x00f,0xf2e,0xc0e,0x60e,0x607};

SHORT	PolyTab[10];
SHORT	*PolyPnt;
SHORT DeltaX,DeltaY;
SHORT	x1,y1,x2,y2;
ULONG	IMClass;

ScanOn()
{
	NrmChk = ChkFlg;
	OvsChk = ChdFlg;
	SWidth = 704;
	SHeight = 478;
	S1Width = 703;
	S1Height = 477;
	XC = 352;
	YC = 239;
	NearEdge = 0;
	LeftEdge = 0;
	RightEdge = 704;
	FarEdge = 478;
	ScnSts = 1;	/* Indicate overscan on */
}

ScnOff()
{
	NrmChk = ChdFlg;
	OvsChk = ChkFlg;
	SWidth = 640;
	SHeight = 400;
	S1Width = 639;
	S1Height = 399;
	XC = 320;
	YC = 199;
	NearEdge = 0;
	LeftEdge = 0;
	RightEdge = 640;
	FarEdge = 400;
	ScnSts = 0;	/* Change to no overscan */
}

LaceOff()
{
	MyView = HIRES;
	LacChk = ChkFlg;
	NLcChk = ChdFlg;
	LacMod = 0;
	SHeight = SHeight/2;
	S1Height = SHeight;
	--S1Height;
	FarEdge = FarEdge/2;
}

LaceOn()
{
	MyView = HIRES | LACE;
	LacChk = ChdFlg;
	NLcChk = ChkFlg;
	LacMod = 1;
}
ScnSet()
{
	if (SUFlag & 0x2)	{
		LaceOn();
		}
	else LaceOff();
}

ViewSet()
{
	if (SUFlag & 0x1)	{	/* See if Overscan flag set */
		ScanOn();
		ScnSet();
		}
	else {
		ScnOff();
		ScnSet();
		}
}

SetLim()
{
	Limit = Two*Factor;
	Limit = Limit*Limit;
}

InitPar()
{
	XWidth = SWidth;
	XHeight = SHeight;
	HWidth = XC;
	XCenter = XC;
	HHeight = YC;
	YCenter = YC;
	SetLim();
}

HasFast()
{
	ViewSet();
	Factor = MltPlr;
	Factor = MltPlr;
	InitPar();
}


void ITInit(Item,NamePtr)
struct	IntuiText	*Item;
UBYTE	*NamePtr;
{
	Item -> IText = NamePtr;
	Item -> BackPen = 3;
	Item -> FrontPen = 5;
	Item -> DrawMode = JAM1;
}
MIInit(Item,NxtItem,TEdge,Cmd,ITItem,Width)
struct	MenuItem	*Item,*NxtItem;
APTR	ITItem;
SHORT	TEdge,Width;
BYTE	Cmd;
{
	Item -> Command = Cmd;
	Item -> TopEdge = TEdge;
	Item -> NextItem = NxtItem;
	Item -> ItemFill = (APTR)ITItem;
	Item -> Flags = (USHORT)DefFlg;
	Item -> Height = 9;
	Item -> Width = Width;
}

void MenuInit(MenuStruct,NxtMenu,NamePtr,LEdge,MWidth)
struct Menu	*MenuStruct,*NxtMenu;
SHORT	LEdge,MWidth;
BYTE	*NamePtr;
{
	MenuStruct -> NextMenu = NxtMenu;
	MenuStruct -> Width = MWidth;
	MenuStruct -> Height = 9;
	MenuStruct -> LeftEdge = LEdge;
	MenuStruct -> TopEdge = 0;
	MenuStruct -> MenuName = NamePtr;
	MenuStruct -> Flags = MenFlg;

}

void ScreenSet()
{
SHORT	MWidth,MHeight,LEdge,TEdge;
UBYTE	MICommand;
struct	Menu	*MenStrct;
BOOL Test;
ns.LeftEdge    =    0;
ns.TopEdge     =   0;		/*Was 20 */
ns.Width       =  SWidth;
ns.Height      =  SHeight;
ns.DetailPen   =   0;
ns.BlockPen    =   1;
ns.Depth       =   4;
ns.ViewModes   =   MyView;

	IntScreen = (struct Screen *)OpenScreen( &ns );
	PlanePtrA = (struct PLANEPTR *)(IntScreen -> BitMap.Planes);
	MyRasta = &(IntScreen -> RastPort);
	VPorta = IntScreen -> ViewPort;
	LoadRGB4(&VPorta,&CTable[0],16);
	if (ScnSts)	{
		MyNewPrefs.ViewXOffset = 0xde;
		MyNewPrefs.ViewYOffset = 0xed;
		}
	else	{
		MyNewPrefs.ViewXOffset = CurrentXOffset;
		MyNewPrefs.ViewYOffset = CurrentYOffset;
		}
	SetPrefs(&MyNewPrefs,Pf_Size,FALSE);

	nw.Title = NULL;
nw.LeftEdge		=	0;
nw.TopEdge		=	0;
nw.Width		=	SWidth;
nw.Height		=	SHeight;
nw.DetailPen	=	5;
nw.BlockPen		=	2;
/*nw.IDCMPFlags	=	GADGETUP | MENUPICK;*/
nw.IDCMPFlags	=	CmpFlg;
nw.Type			=	CUSTOMSCREEN;
nw.Flags		=	MyFlag;	ACTIVATE | SMART_REFRESH;
nw.FirstGadget	=	NULL;
nw.CheckMark	=	NULL;
nw.Screen		=	IntScreen;
nw.BitMap		=	NULL;
nw.MinWidth		=	320;
nw.MinHeight	=	100;
nw.MaxWidth		=	SWidth;
nw.MaxHeight	=	SHeight;

	IntWindow = (struct Window *)OpenWindow( &nw );

/* Get associated information about Int window */
/*	GadStuff = IntWindow -> FirstGadget;*/
	CWRast = IntWindow -> RPort;
	SetRast(CWRast,0);
	IntPort	= IntWindow -> UserPort;

/*	Template is 
	MenuInit(&Menu1,&Menu2,"Strng",LEdge,MWidth);
		*/

	MenuInit(&Menu1,&Menu2,"SManLb",20,100);
	Menu1.FirstItem = &MI11;
	MIInit(&MI11,&MI12,0,0x41,&IT11,150);	
	MIInit(&MI12,&MI13,9,0x52,&IT12,150);
	MIInit(&MI13,&MI14,18,0x53,&IT13,150);
	MIInit(&MI14,0,27,0x51,&IT14,150);	

	ITInit(&IT11,"About");
	ITInit(&IT12,"Redraw(Same P)");
	ITInit(&IT13,"Save");
	ITInit(&IT14,"Quit");

	MenuInit(&Menu2,&Menu3,"View Mode",180,130);
	Menu2.FirstItem = &MI21;
	MIInit(&MI21,&MI22,0,0x4c,&IT21,150);	
	MIInit(&MI22,&MI23,9,0x43,&IT22,150);
	MIInit(&MI23,&MI24,18,0x4d,&IT23,150);
	MIInit(&MI24,0,27,0x4e,&IT24,150);	

	ITInit(&IT21,"   Lace On");
	ITInit(&IT22,"   Lace Off");
	ITInit(&IT23,"   Overscan");
	ITInit(&IT24,"   Normal");

	MenuInit(&Menu3,&Menu4,"Maximum Count",350,130);
	Menu3.FirstItem = &MI31;
	MIInit(&MI31,&MI32,0,43,&IT31,150);	
	MIInit(&MI32,&MI33,9,45,&IT32,150);
	MIInit(&MI33,&MI34,18,0x44,&IT33,150);
	MIInit(&MI34,0,27,0x48,&IT34,150);	

	ITInit(&IT31,"Increase by 10");
	ITInit(&IT32,"Decrease by 10");
	ITInit(&IT33,"Double");
	ITInit(&IT34,"Halve");


	MenuInit(&Menu4,0,"Zoom",505,100);
	Menu4.FirstItem = &MI41;
	MIInit(&MI41,&MI42,0,0x5a,&IT41,140);	
	MIInit(&MI42,0,9,0x49,&IT42,140);	

	ITInit(&IT41,"Select");
	ITInit(&IT42,"Restore");

	MI21.Flags = LacChk;
	MI22.Flags = NLcChk;
	MI23.Flags = OvsChk;
	MI24.Flags = NrmChk;
	Test = SetMenuStrip(IntWindow,&Menu1);

	ActivateWindow(InfoWindow);
}

void ScreensClose()
{
	if(InfoWindow) CloseWindow(InfoWindow);
	if(IntWindow) CloseWindow(IntWindow);
	if(IntScreen) CloseScreen(IntScreen);
}
void ScreenClose()
{
	if(IntWindow) ClearMenuStrip(IntWindow);
	if(IntWindow) CloseWindow(IntWindow);
	if(IntScreen) CloseScreen(IntScreen);
}


OpenWrite(NamPtr)
char	*NamPtr;
{
	FileHandle = Open((UBYTE *)NamPtr,MODE_NEWFILE);
	if (!FileHandle)	return(-1);
	return(0);
}

WriteFile(Source,FileLength)
char	*Source;
ULONG	FileLength;
{
ULONG	Count,*Destination;
ULONG	ReadLength;
	Write(FileHandle,(char *)Source,FileLength);
	return(0);
}
CloseWrite()
{
	Close(FileHandle);
}

ULONG WritePlanes(NamPtr)
char	*NamPtr;
{
USHORT	PlnCnt,LineCount;

ULONG	Count,*Source1,*Source2,*Source3,*Source4;
ULONG	FileLength,LineLength;
	FileLength = 32000;
	Source1 = (ULONG *)*PlnPtr++;
	Source2 = (ULONG *)*PlnPtr++;
	Source3 = (ULONG *)*PlnPtr++;
	Source4 = (ULONG *)*PlnPtr++;
	LineCount = ns.Height;
	FileLength = ns.Width >> 3;
	LineLength = FileLength >> 2; /* # of long words on line */
	while (LineCount)	{
		FileLength = Write(FileHandle,(char *)Source1,FileLength);
		Source1 = Source1 + LineLength;
		FileLength = Write(FileHandle,(char *)Source2,FileLength);
		Source2 = Source2 + LineLength;
		FileLength = Write(FileHandle,(char *)Source3,FileLength);
		Source3 = Source3 + LineLength;
		FileLength = Write(FileHandle,(char *)Source4,FileLength);
		Source4 = Source4 + LineLength;
		--LineCount;
		}
	return(0);
}


Save()
{
ULONG	*HdrSize,*HdrTop,*HdrBottom;
UBYTE	*MyColors;
USHORT	*CurrentColor,Red,Green,Blue;
static	char	HexName[] = "Hex.iff";
char	*NamPtr;
ChunkHeader		*Chunk3D;
BitMapHeader	*MyHeader;

typedef		struct	{
	ID		ckID;
	}	sChunk;

sChunk	*ChunkID;
char	*HdrBuffer;

ULONG	CTSize,CTCount,FileLength,BodyLength,Depth;
	HdrBuffer = AllocMem(160,MEMF_PUBLIC|MEMF_CLEAR);
	Chunk3D = (ChunkHeader *) HdrBuffer;
	Chunk3D -> ckID = FORM;
	Chunk3D++;
	ChunkID = (sChunk *) Chunk3D;
	ChunkID -> ckID = ID_ILBM;
	ChunkID++;
	ChunkID -> ckID = ID_BMHD;
	ChunkID++;
	HdrSize = (ULONG *)ChunkID;
	*HdrSize++ = 20;
	MyHeader = (BitMapHeader *)HdrSize;
	MyHeader -> w = ns.Width;
	MyHeader -> h = ns.Height;
	CTCount = ns.Depth;
	MyHeader -> nPlanes = CTCount;
	MyHeader -> xAspect = 1;
	MyHeader -> yAspect = 1;
	MyHeader -> pageWidth = ns.Width;
	MyHeader -> pageHeight = ns.Height;
	MyHeader++;
	Chunk3D = (ChunkHeader *)MyHeader;
	Chunk3D -> ckID = ID_CMAP;
	CTSize = 1;
	while (CTCount)	{
		CTSize <<= 1;
		--CTCount;
		}
	Chunk3D -> ckSize = 3*CTSize;
	Chunk3D++;
	MyColors = (UBYTE *)Chunk3D;
	CTCount = ns.Depth;
	CurrentColor = &CTable[0];
	while (CTSize)	{
		Red = *CurrentColor;
		Red = 0xf00 & Red;
		Red >>= 4;
		*MyColors++ = (UBYTE)Red;
		Green = *CurrentColor;
		Green = 0xf0 & Green;
		*MyColors++ = (UBYTE)Green;
		Blue = *CurrentColor++;
		Blue = 0xf & Blue;
		Blue <<= 4;
		*MyColors++ = (UBYTE)Blue;
		--CTSize;
		}
	Chunk3D = (ChunkHeader *)MyColors;
	Chunk3D -> ckID = ID_BODY;
	CTCount = ns.Width;
	CTCount >>= 3;
	CTCount = CTCount*ns.Height;
	CTCount = CTCount*ns.Depth;
	Chunk3D -> ckSize = CTCount;
	BodyLength = CTCount;
	Chunk3D++;
	HdrTop = (ULONG *)Chunk3D;
	HdrBottom = (ULONG *)HdrBuffer;
	FileLength = HdrTop - HdrBottom;
	FileLength <<= 2;	/* Get # bytes */
	Chunk3D = (ChunkHeader *)HdrBuffer;
	CTCount = CTCount + FileLength;
	Chunk3D -> ckSize = CTCount - 8;
	NamPtr = &HexName[0];
	OpenWrite(NamPtr);
	WriteFile(HdrBuffer,FileLength);
	PlnPtr = (ULONG *) PlanePtrA;
	WritePlanes(NamPtr);
	CloseWrite();		
	if (HdrBuffer) FreeMem(HdrBuffer,160);
	return(0);
}

void WindowSet()
{

nw.LeftEdge		=	0;
nw.TopEdge		=	0;			/* Expose screen drag bar */
nw.Width		=	640;
nw.Height		=	200;
nw.DetailPen	=	5;
nw.BlockPen		=	2;
nw.IDCMPFlags	=	CLOSEWINDOW;
nw.Type			=	WBENCHSCREEN;
nw.Flags		=	WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SMART_REFRESH|ACTIVATE|REPORTMOUSE;
nw.FirstGadget	=	NULL;
nw.CheckMark	=	NULL;
nw.Screen		=	0;
WindowName 	= &Title[0];
nw.Title		=	(UBYTE *)WindowName;
nw.BitMap		=	NULL;
nw.MinWidth		=	320;
nw.MinHeight	=	100;
nw.MaxWidth		=	SWidth+20;
nw.MaxHeight	=	SHeight+20;

	InfoWindow = (struct Window *)OpenWindow( &nw );
	WBRast = InfoWindow -> RPort;	
	MyPort	= InfoWindow -> UserPort;
	WBScreen = InfoWindow -> WScreen;
}
/*
void ClearWindow()
{
	SetRast(WBRast,0);
	SetWindowTitles(InfoWindow,(UBYTE *)WindowName,(UBYTE *)-1);
	RefreshGadgets(GadStuff,InfoWindow,0);
}*/

void ErrorDisplay()
{
	SetAPen(WBRast,1);
	Move(WBRast,40,80);
	Text(WBRast,(STRPTR)Err020,strlen(Err020));	
	Move(WBRast,40,110);
	Text(WBRast,(STRPTR)Err021,strlen(Err021));	
	
}
void DescribeSystem()
{
	if (SysFlag == 0)	Text(WBRast,(STRPTR)" 68000",6);
	else	{
		if (SysFlag & AFB_68030) Text(WBRast,(STRPTR)" 68030",6);
		else if (SysFlag & AFB_68020) Text(WBRast,(STRPTR)" 68020",6);
		Text(WBRast,(STRPTR)Comma,1);
		if (SysFlag & AFB_68882) Text(WBRast,(STRPTR)" 68882",6);
		else if (SysFlag & AFB_68881) Text(WBRast,(STRPTR)" 68881",6);
		}
}

void WriteStuff()
{
ULONG	MemSize;
char *TmpPtr;
	SetAPen(WBRast,1);
	Move(WBRast,0xd0,20);
	Text(WBRast,(STRPTR)Message,strlen(Message));
	SetAPen(WBRast,3);
	Move(WBRast,0xd8,30);
	Text(WBRast,(STRPTR)Mesag2,strlen(Mesag2));
	Text(WBRast,(STRPTR)Mesag2b,1);
	Text(WBRast,(STRPTR)Mesag2c,strlen(Mesag2c));
	Move(WBRast,0xe0,128);
	Text(WBRast,(STRPTR)ScrMsg,strlen(ScrMsg));
	SetAPen(WBRast,1);
	Move(WBRast,0x90,48);
	Text(WBRast,(STRPTR)Mesag3,strlen(Mesag3));
	DescribeSystem();
	SetAPen(WBRast,2);
	Move(WBRast,8,78);
	Text(WBRast,(STRPTR)Mesag4,strlen(Mesag4));
	Move(WBRast,0x40,152);
	Text(WBRast,(STRPTR)Mesag5,strlen(Mesag5));
	Move(WBRast,0x60,162);
	Text(WBRast,(STRPTR)Mesag6,strlen(Mesag6));
	Move(WBRast,0x18,172);
	Text(WBRast,(STRPTR)Mesag7,strlen(Mesag7));
	SetAPen(WBRast,1);
	TmpPtr = &CntEnd[0];
	--TmpPtr;
	sprintf(TmpPtr,"%d",MaxCnt);
	Move(WBRast,400,108);
	Text(WBRast,(STRPTR)CntMsg,strlen(CntMsg));
	Move(WBRast,0x28,60);
	MemSize = AvailMem(MEMF_CHIP);
	TmpPtr = &ChpEnd[0];
	--TmpPtr;
	sprintf(TmpPtr,"%d",MemSize);
	Text(WBRast,(STRPTR)ChpMsg,strlen(ChpMsg));
	Move(WBRast,400,60);
	MemSize = AvailMem(MEMF_FAST);
	TmpPtr = &FstEnd[0];
	--TmpPtr;
	sprintf(TmpPtr,"%d",MemSize);
	Text(WBRast,(STRPTR)FstMsg,strlen(FstMsg));
	Move(WBRast,0x28,94);
	TmpPtr = &WdtEnd[0];
	--TmpPtr;
	sprintf(TmpPtr,"%d",SWidth);
	Text(WBRast,(STRPTR)WdtMsg,strlen(WdtMsg));
	Move(WBRast,400,94);
	TmpPtr = &HgtEnd[0];
	--TmpPtr;
	sprintf(TmpPtr,"%d",SHeight);
	Text(WBRast,(STRPTR)HgtMsg,strlen(HgtMsg));
	Move(WBRast,0x28,108);
	TmpPtr = &MagEnd[0];
	--TmpPtr;
	sprintf(TmpPtr,"%e",Factor);

	Text(WBRast,(STRPTR)MagMsg,strlen(MagMsg));
	Move(WBRast,0x28,136);
	TmpPtr = &XPsEnd[0];
	--TmpPtr;
	sprintf(TmpPtr,"%e",(HWidth-XCenter)/Factor);
	Text(WBRast,(STRPTR)XPos,strlen(XPos));
	Move(WBRast,400,136);
	TmpPtr = &YPsEnd[0];
	--TmpPtr;
	sprintf(TmpPtr,"%e",(HHeight-YCenter)/Factor);
	Text(WBRast,(STRPTR)YPos,strlen(YPos));
	if (((SysFlag & AFB_68881)||(SysFlag & AFB_68882))&&((SysFlag & AFB_68020)||(SysFlag & AFB_68030)))	{
		SetAPen(WBRast,3);
		Move(WBRast,0x28,180);
		Text(WBRast,(STRPTR)HavMsg,strlen(HavMsg));
		SetAPen(WBRast,1);
		}
}

	
void LibsOpen()
{
	if (!DOSBase)	{
		DOSBase = (struct Library *)OpenLibrary((UBYTE *)"dos.library",0L);
		}

	GfxBase = (struct GfxBase *)OpenLibrary((UBYTE *)"graphics.library",0L);
	IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *)"intuition.library",0L);
}

void LibsClose()
{
	if(GfxBase)			CloseLibrary((struct Library *)GfxBase);
	if(IntuitionBase)	CloseLibrary((struct Library *)IntuitionBase);
	}

CheckMsg()
{
struct IntuiMessage *MyMsg;

	IMClass = 0;
    MyMsg = (struct IntuiMessage*) GetMsg(MyPort);
	if (MyMsg != NULL) {
  		IMClass = MyMsg -> Class;
		ReplyMsg((struct Message *)MyMsg);
	}
}

CheckIntMsg()
{
struct IntuiMessage *MyMsg;
	MenVal = 0;
    MyMsg = (struct IntuiMessage*) GetMsg(IntPort);
	if (MyMsg != NULL) {
		MenVal = MyMsg -> Code;
		ReplyMsg((struct Message *)MyMsg);
	}
}

MakeLace()
{
	ScreenClose();
	SUFlag = SUFlag | 0x2;
	ViewSet();
/*	HasFast();*/
	ScreenSet();
}

UnLace()
{
	ScreenClose();
	SUFlag = SUFlag & 0xfffd;
	ViewSet();
/*	HasFast();*/
	ScreenSet();
}

MakeOver()
{
	ScreenClose();
	SUFlag = SUFlag | 0x1;
	ViewSet();
/*	HasFast();*/
	ScreenSet();
}

MakeNorm()
{
	ScreenClose();
	SUFlag = SUFlag & 0xfffe;
	ViewSet();
/*	HasFast();*/
	ScreenSet();
}

CountChange()
{
	if((MenVal & 0xff) == 2)	MaxCnt = MaxCnt + 10;
	if((MenVal & 0xff) == 0x22)	MaxCnt = MaxCnt - 10;
	if((MenVal & 0xff) == 0x42)	MaxCnt = 2*MaxCnt;
	if((MenVal & 0xff) == 0x62) MaxCnt = MaxCnt/2;
	if (MaxCnt < 10)	MaxCnt = 10;
	WriteStuff();
	ActivateWindow(IntWindow);
}

ScreenChange()
{
/*	HWidth = XCenter;
	HHeight = YCenter;*/
	if((MenVal & 0xff) == 1)	MakeLace();
	if((MenVal & 0xff) == 0x21)	UnLace();
	if((MenVal & 0xff) == 0x41)	MakeOver();
	if((MenVal & 0xff) == 0x61) MakeNorm();
	WriteStuff();
	ActivateWindow(IntWindow);
}

void FncFind()
{
	xRel = xtemp;
	xRel = xRel - XCenter;
	CurCnt = 0;			/* Initialize Counter */
	Zr = CurCnt;
	Zi = Zr;			/* Zi is 0 */
	while (CurCnt < MaxCnt)	{
		Zr2 = Zr*Zr;		/* Find Zr^2 */
		Zi2 = Zi*Zi;		/* Find Zi^2 */
		Z2 = Zr2+Zi2;		/* Find Zr^2 + Zi^2 */
		if (Z2 > Limit)	{	/* is |Z| > 2*Factor */
			PlotIt();
			return;
				}
		Zr2 = Zr2 - Zi2;	/* Find Zr^2 - Zi^2 */
		Zr2 = Zr2/Factor;		/* Divide by Factor to get part of new Zr */
		Zi = Two*Zi*Zr;		/* Find original Zi * Zr */
		Zr = xRel + Zr2;	/* Find New Zr */
		Zi = Zi/Factor;		/* Divide by Factor */
		Zi = yRel + Zi;	/* Add in original Zi to get new Zi */
		CurCnt++;
		}
	CurCnt = 0xffff;
	PlotIt();
	return;
}

void Restore()
{
	Factor = LastFactor;
	XCenter = LastX;
	YCenter = LastY;
	Limit = LastLim;
}

void PolyUpDate()
{
	PolyPnt = &PolyTab[0];
	x2 = IntWindow -> MouseX;
	*PolyPnt++ = x1;		/* Upper-Left Corner */
	*PolyPnt++ = y1;
	*PolyPnt++ = x2;		/* Upper-Right Corner */
	*PolyPnt++ = y1;
	DeltaX = x2 - x1;
	DeltaY = SHeight*DeltaX/SWidth;
	y2 = y1 + DeltaY;
	*PolyPnt++ = x2;		/* Lower-Right Corner */
	*PolyPnt++ = y2;
	*PolyPnt++ = x1;		/* Lower-Left Corner */
	*PolyPnt++ = y2;
	*PolyPnt++ = x1;		/* Upper-Left Corner */
	*PolyPnt++ = y1;
	Move(CWRast,x1,y1);
	PolyPnt = &PolyTab[0];
	PolyDraw(CWRast,4,PolyPnt);
}

/* Clear by reversing again */
void PolyClear()
{
	PolyPnt = &PolyTab[0];
	PolyDraw(CWRast,4,PolyPnt);
}
/*WaitChg will wait until there is at least a difference of 10 between
 the original MouseX value and the new. */

void WaitChg()
{
	while ((x2 - x1) < 5)	{
		x2 = IntWindow -> MouseX;
		Delay(1);
		}
}

DoZoom()
{
double Ratio;
	x1 = 0;
	y1 = 0;
	x2 = 0;
	y2 = 0;
	while (MenVal != SELECTDOWN)	{
		CheckIntMsg();
		}
	x1 = IntWindow -> MouseX;
	y1 = IntWindow -> MouseY;

/* Now prep for complementary polygon (i.e. rectangle) */
	SetDrMd(CWRast,2);
	WaitChg();
	PolyUpDate();
	while (MenVal != SELECTUP)	{
		CheckIntMsg();
		PolyClear();
		PolyUpDate();
		Delay(1);
		}
/* Clear Polygon and restore drawing mode */
	PolyClear();
	SetDrMd(CWRast,0);
	if (LacMod == 0)	{
		y1 = 2*y1;	/* Double y1 if not interlace */
		}
	LastFactor = Factor;
	LastX = XCenter;
	LastY = YCenter;
	LastLim = Limit;

	Ratio = XWidth/DeltaX;
	Factor = Ratio*Factor;

	XCenter = XCenter - (double)x1;
	XCenter = Ratio*XCenter;
	YCenter = YCenter - (double)y1;
	YCenter = Ratio*YCenter;
	SetLim();
	MenVal = 0xf803;
}

void Zoom()
{
	if((MenVal & 0xf0) == 0x00)	DoZoom();
	if((MenVal & 0xf0) == 0x20)	Restore();
}

SManMen()
{
		if (MenVal == 0xf800)	{
			WriteStuff();
			WBenchToFront();
			WindowToFront(InfoWindow);
			ActivateWindow(InfoWindow);
			}
		if (MenVal == 0xf840)	Save();
}

void SingleLine()
{
	yRel = ytemp;
	if	(!LacMod) {
		yRel = Two*yRel;
		}
	xtemp = 0;
	yRel = yRel - YCenter;
	while (xtemp < RightEdge)	{ 
		FncFind();
		xtemp++;
		CheckMsg();
		if (IMClass == CLOSEWINDOW)	{
			ScreenToFront(IntScreen);
			ActivateWindow(IntWindow);
			}
		CheckIntMsg();
		if (MenVal)	{
			if ((MenVal & 0xf) == 2)	CountChange();
			if (MenVal == 0xf860)	return;
			if ((MenVal & 0xf) == 1) return;
			if ((MenVal & 0xf) == 3) {
				Zoom();
				return;
				}
			if ((MenVal & 0xf) == 0)	{
				SManMen();
				if((MenVal & 0xff) == 0x20)	return;
				}
			}
		}
}

FullSurface()
{
	SetRast(CWRast,0);
/*	Execute((UBYTE *)"Date",0,0);*/
	ytemp = NearEdge;
	while (ytemp < FarEdge)	{
		SingleLine();		/*Draw next line*/
		Delay(1);
		if (MenVal)	{
			if (MenVal == 0xf860)	return;
			if ((MenVal & 0xf) == 1) return;
			if ((MenVal & 0xf) == 3) return;
			if ((MenVal & 0xff) == 0x20)	return;
			}
		ytemp++;
	}
/*	Execute((UBYTE *)"Date",0,0);*/
}

Status()
{
	while (!MenVal)	{
		Delay(1);
		CheckMsg();
		if (IMClass == CLOSEWINDOW)	{
			ScreenToFront(IntScreen);
			ActivateWindow(IntWindow);
			MenVal = 0;
			}
		CheckIntMsg();
		if (MenVal)	{
			if (MenVal == -1) MenVal = 0;
			if ((MenVal & 0xf) == 0)	{
				SManMen();
				if (MenVal == 0xf800) MenVal = 0;
				}
			if ((MenVal & 0xf) == 1)	ScreenChange();
			if ((MenVal & 0xf) == 2)	CountChange();
			if ((MenVal & 0xf) == 3)	Zoom();
			}
	}
}
void main()
{

	MltPlr = 0xa0;
	MaxCnt = 31;
	LibsOpen();
	WindowSet();
	CurPrefs = GetPrefs(&MyNewPrefs,Pf_Size);
	CurrentXOffset = CurPrefs -> ViewXOffset;
	CurrentYOffset = CurPrefs -> ViewYOffset;
	SysFlag = SysBase -> AttnFlags;
	Two = 2.000000000000;
	SUFlag = SUFlag & 0xfffe;	/*Clear ScnFlg*/
	SUFlag = SUFlag & 0xfffd;	/*Clear LacFlg*/
	HasFast();
	InitPar();
ns.Type        = CUSTOMSCREEN|SCREENBEHIND;
	ScreenSet();
ns.Type        = CUSTOMSCREEN;
	WriteStuff();
	ActivateWindow(InfoWindow);
	MenVal = 0xf801;
	while (MenVal != 0xf860)	{
		FullSurface();
		if ((MenVal & 0xf) == 1) ScreenChange();
		Status();
		}
	MyNewPrefs.ViewXOffset = CurrentXOffset;
	MyNewPrefs.ViewYOffset = CurrentYOffset;
	SetPrefs(&MyNewPrefs,Pf_Size,FALSE);
	ScreensClose();
	LibsClose();
}
