[comp.sources.amiga] v89i144: mandel - mandelobrot generator v180, Part03/04

page%swap@Sun.COM (Bob Page) (05/17/89)

Submitted-by: u211344@hnykun11.bitnet (Olaf 'Rhialto' Seibert)
Posting-number: Volume 89, Issue 144
Archive-name: graphics/mandel180.3

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	Main.c
#	Makefile
#	Mandel.h
#	Menu.c
#	MinRexx.c
#	Misc.c
# This is archive 3 of a 4-part kit.
# This archive created: Wed May 17 20:45:13 1989
echo "extracting Main.c"
sed 's/^X//' << \SHAR_EOF > Main.c
X/*
X * M A N D E L B R O T	  C O N S T R U C T I O N   S E T
X *
X * (C) Copyright 1989 by Olaf Seibert.
X * Mandel may be freely distributed. See file 'doc/Notice' for details.
X *
X * Main Loop, and a lot of Variables.
X */
X
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#ifdef DEBUG
X#   include <stdio.h>
X#   undef STATIC
X#   define STATIC		/* EMPTY */
X#endif
X
X#include "mandel.h"
X
Xextern int	Enable_Abort;
X
Xstruct IntuitionBase *IntuitionBase;
Xstruct GfxBase *GfxBase;
Xstruct LayersBase *LayersBase;
X
Xstruct TextAttr Topaz80 = {
X    (STRPTR) "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT
X};
X
Xstruct TextAttr Topaz60 = {
X    (STRPTR) "topaz.font", TOPAZ_SIXTY, FS_NORMAL, FPF_ROMFONT
X};
X
Xstruct NewScreen MandelNScreen =
X{
X    0, 0, 320, 256,		/* LeftEdge, TopEdge, Width, Height */
X    4,				/* Depth */
X    2, 1,			/* DetailPen, BlockPen */
X    NULL,			/* viewmode LORES */
X    CUSTOMSCREEN,		/* type */
X    &Topaz80,			/* Font (default) */
X#ifdef IEEEDP
X    (UBYTE *) "DP Mandelbrot Construction Set 1.3"
X#else
X    (UBYTE *) "FFP Mandelbrot Construction Set 1.3"
X#endif
X};
X
Xstruct NewWindow MainNWindow =
X{
X    0, 0, 0, 0, 		/* LeftEdge, TopEdge, Width, Height */
X    2, 1,			/* DetailPen, BlockPen */
X    CLOSEWINDOW | MENUPICK | MOUSEBUTTONS | VANILLAKEY |
X    SIZEVERIFY /* | MENUVERIFY */ ,
X    WINDOWCLOSE | ACTIVATE | WINDOWSIZING | WINDOWDRAG |
X    WINDOWDEPTH | NOCAREREFRESH | SMART_REFRESH | GIMMEZEROZERO,
X    NULL,			/* FirstGadget */
X    NULL,			/* default CheckMark */
X    (UBYTE *) "Mandelbrot Construction Window", /* Title */
X    NULL,			/* Screen */
X    NULL,			/* BitMap */
X    60, 25,			/* MinWidth, MinHeight */
X    -1, -1,			/* MaxWidth, MaxHeight */
X    CUSTOMSCREEN		/* Screen type */
X};
X
Xstruct BorderInfo borderinfo;
X
Xstruct IntuiText PositiveText = {
X    AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
X    AUTOLEFTEDGE, AUTOTOPEDGE, NULL, (UBYTE *) "Continue", NULL
X},
X
X		NegativeText = {
X    AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
X    AUTOLEFTEDGE, AUTOTOPEDGE, &Topaz60, (UBYTE *) "Cancel", NULL
X};
X
XSTATIC SHORT	XY1[] = {0, 0, 0, 13, 78, 13, 78, 0, 0, 0};
XSTATIC SHORT	XY2[] = {0, 0, 0, 17, 82, 17, 82, 0, 0, 0};
XSTATIC struct Border border[] = {
X    {0, 0, 2, 0, JAM1, 5, XY1, &border[1]},
X    {-2, -2, 3, 0, JAM1, 5, XY2, NULL}
X};
Xstruct Gadget	NegativeGadget = {
X    NULL, -100, -20, 79, 14,	/* next, LTWH */
X    GADGHCOMP | GRELBOTTOM | GRELRIGHT,
X    RELVERIFY | ENDGADGET,
X    BOOLGADGET | REQGADGET,
X    (APTR) & border[0], NULL,
X    &NegativeText, 0, NULL,
X    NEGGADGETID, NULL
X};
Xstruct Gadget	PositiveGadget = {
X    &NegativeGadget, 20, -20, 79, 14,	/* next, LTWH */
X    GADGHCOMP | GRELBOTTOM,
X    RELVERIFY | ENDGADGET,
X    BOOLGADGET | REQGADGET,
X    (APTR) & border[0], NULL,
X    &PositiveText, 0, NULL,
X    POSGADGETID, NULL
X};
X
XUBYTE		PenTable[MAXDEPTH];
Xunsigned	PenTableMode = MODULO;
Xshort		RangeWidth = 2;
X
Xstruct Screen  *MandelScreen = NULL;	/* Pointer for OpenScreen return
X					 * value */
Xstruct Window  *MainWindow = NULL;	/* Idem for OpenWindow */
Xstruct Window  *XYwindow;	/* The X/Y window */
Xextern struct Window *ColorWindow;	/* Palette */
X
X
XUSHORT		WBWidth = 0;	/* Preferred size of our screen */
XUSHORT		WBHeight = 0;	/* in Hires/noninterlace values */
X
Xint		(*DepthFunc) () = ZQuadMinC;
XUBYTE		FunctionNr = 0;
X
Xvoid		(*IPlotFunc) () = None;
XUBYTE		IPlotNr = 0;
X
Xvoid		(*EPlotFunc) () = PlotIterationCount;
XUBYTE		EPlotNr = 0;
X
Xdouble		LeftEdge = -0.800,	/* Left edge of the picture */
X		RightEdge = 2.100,
X		TopEdge = 1.200,
X		BottomEdge = -1.200;
X
Xdouble		CXStep, 	/* Stepsize through the complex plane */
X		CYStep;
Xint		PixelStep = 1,	/* Stepsize on the screen */
X		MaxDepth = 100; /* Maximum iteration count */
X
Xint NumColors;			/* Number of colors on the screen */
X
Xunsigned short	FrameX1,
X		FrameX2,
X		FrameY1,
X		FrameY2;
X
Xshort		MouseStatus = NOTFRAMING;	/* Where we are in the
X						 * process of selecting a
X						 * frame */
X
Xbool		finished = FALSE;	/* TRUE to stop the program */
Xbool		Saved = TRUE;	/* Indicates the picture has been SAVEd */
Xbool		NameValid = FALSE;	/* Indicates the file name is
X					 * valid */
Xbool		StillDrawing = FALSE;	/* Are we still drawing ? */
X
XFILE	       *BatchFILE;	/* Current batch file */
Xint		DrawSigBit = -1;/* Signal when drawing is finished */
Xlong		DrawSigMask;
X
X#ifdef AREXX
X
X/*
X *  And here is some AREXX stuff. Not very complicated, thanks to
X *  MinRexx by Tomas Rokicki (Radical Eye Software).
X */
X
Xlong		RexxMask;	/* Wait signal mask */
Xextern short	BatchWaiting;	/* Halting all Arexx traffic as well */
X
X#endif
X
X/*
X * M A I N   E N T R Y	 P O I N T
X */
X
Xmain(argc, argv)
Xint		argc;
Xchar	      **argv;
X{
X    char	   *Main();
X    extern struct SignalSemaphore DrawSemaphore;
X
X    /*
X     * Before we do anything, do an operation which requires the floating
X     * point library. So if it is not available, we abort before we need
X     * to clean up anything. Note that CXStep is not initialized at this
X     * moment.
X     */
X
X    CXStep = 1.0;
X    CXStep = CXStep * 2.0;
X
X    /*
X     * Make sure we aren't interrupted by any user pressing ^C while we
X     * are doing I/O.
X     */
X    Enable_Abort = 0;
X
X    /*
X     * Open each of the libraries and check for a NULL return, which
X     * indicates unavailability.
X     */
X
X    IntuitionBase = (struct IntuitionBase *)
X	OpenLibrary("intuition.library", LIBRARY_VERSION);
X    if (IntuitionBase == NULL)
X	MyExit("Can't open Intuition V1.2 or newer!");
X
X    GfxBase = (struct GfxBase *)
X	OpenLibrary("graphics.library", LIBRARY_VERSION);
X    if (GfxBase == NULL)
X	MyExit("Can't open Gfx V1.2 or newer!");
X
X    LayersBase = (struct LayersBase *)
X	OpenLibrary("layers.library", LIBRARY_VERSION);
X    if (LayersBase == NULL)
X	MyExit("Can't open Layers V1.2 or newer!");
X
X    DrawSigBit = AllocSignal(-1L);
X    if (DrawSigBit == -1)
X	MyExit("Can't allocate signal!");
X    DrawSigMask = 1L << DrawSigBit;
X    InitSemaphore(&DrawSemaphore);
X    MandelTask = FindTask(NULL);
X
X#ifdef AREXX
X/*
X *   For rexx, we open up a Rexx port, and Batch() will send out
X *   the first command, if there was one.
X */
X    RexxMask = upRexxPort("MANDEL", NULL, "mand", NULL) ;
X#endif
X    if (InitDisplay((bool) FALSE))
X	MyExit("Can't initialise the display properly!");
X
X    CalcCSteps();
X    Options(argc, argv);        /* Maybe open the batch */
X    Batch();                    /* Check the batch */
X
X    MyExit(Main());
X}
X
Xchar	       *
XMain()
X{
X    register ULONG  Class;	/* IntuiMessage class */
X    register USHORT Code;	/* and Code field */
X    struct IntuiMessage *message;	/* Expected message pointer */
X    struct Window  *window;	/* window related to message */
X    long	    signalmask;
X    long	    signals;
X
X#ifdef AREXX
X/*
X *   If we're working with Rexx, we wait on the Rexx bit as well.
X *   Then, we handle any Rexx messages.
X */
X    signalmask = RexxMask | DrawSigMask |
X		   (1L << MainWindow->UserPort->mp_SigBit);
X#else
X    signalmask = DrawSigMask | (1L << MainWindow->UserPort->mp_SigBit);
X#endif
X
Xagain:
X    finished = FALSE;
X    while (!finished) {
X	/*
X	 * Wait for message port to become not empty, and extract the
X	 * message or, alternatively, for the drawing to finish.
X	 */
X
X	signals = Wait(signalmask);
X#ifdef AREXX
X	if ((signals & RexxMask) && !BatchWaiting) {
X	    dispRexxPort();
X	}
X#endif
X	if (signals & DrawSigMask) {    /* drawing finished */
X	    Batch();                    /* Check the batch */
X#ifdef AREXX
X	    Signal(MandelTask, RexxMask);/* Wake up Arexx as well */
X#endif
X	}
X	while (message = (struct IntuiMessage *)
X	       GetMsg(MainWindow->UserPort)) {
X	    window = message->IDCMPWindow;
X
X	    if (window == ColorWindow) {
X		HandleColorWindow(message);
X		continue;
X	    }
X
X	    Class = message->Class;
X	    Code = message->Code;
X
X	    if (Class & ~(MOUSEBUTTONS | INTUITICKS)) {
X		ReplyMsg(message);      /* Pointer is not valid anymore */
X	    }
X	    switch (Class) {
X	    case MENUPICK:
X		GotMenu(Code);
X		break;
X	    case MOUSEBUTTONS:
X	    case INTUITICKS:
X		CheckMouse(message);
X		ReplyMsg(message);
X		break;
X	    case SIZEVERIFY:
X		StopFraming();  /* Fall Through to MenuVerify */
X	    case MENUVERIFY:
X		break;		/* Just make sure there is no half-drawn
X				 * frame */
X	    case CLOSEWINDOW:
X		if (window == MainWindow) {
X		    finished = TRUE;
X		} else {
X		    CloseXYwindow();
X		}
X		break;
X	    case VANILLAKEY:
X		if (Code == ('Q' & 0x1F)) {     /* Ctrl-Q; don't check to
X						 * be sure */
X		    skipto	    finished;
X		}
X		break;
X		/* default: Ignore strange messages */
X	    }			/* End Switch The Class Of The Message */
X	}			/* End While There Is A Message */
X    }				/* End While Not Finished */
X
X    /*
X     * So we are finished. And, by the way, are we SURE we are finished
X     * alltogether ??
X     */
X
X    if (!Sure()) {
X	backto		again;
X    }
Xfinished:
X    CleanupDisplay((bool) TRUE);
X    return NULL;		/* Indicate Good Exit */
X}				/* End of Main */
SHAR_EOF
echo "extracting Makefile"
sed 's/^X//' << \SHAR_EOF > Makefile
X#
X#	Makefile for the Mandelbrot Construction Set by Olaf Seibert, KosmoSoft
X#
X
XSPOBJ	= Main.o Misc.o GotMenu.o Batch.o \
X	  Palette.o Draw.o
XDPOBJ	= Main.odp Misc.odp GotMenu.odp Batch.odp \
X	  Palette.odp Draw.odp
XINTOBJ	= Display.o Select.o GetFile.o Jiff.o Menu.o Rev.o
XREXXOBJ = MinRexx.o RexxBind.o
XHEADERS = Mandel.h
XLIBS	= -lm -lc
XDPLIBS	= -lma -lc
XDUMP	= ii
XCFLAGS	= +I$(DUMP) +x3,5 -DAREXX
XCC	= cc
X
X.SUFFIXES:
X
X.SUFFIXES:  .odp .o .asm .c .req
X
X.c.odp:
X	$(CC) $(CFLAGS) +fi -DIEEEDP $< -o $@
X
X.c.o:
X	$(CC) $(CFLAGS) $< -o $@
X
X.c.asm:
X	$(CC) $(CFLAGS) -at $< -o $@
X
XDebug:	$(SPOBJ) $(INTOBJ) $(REXXOBJ) $(DUMP)
X	air
X	ln -o Debug -w $(INTOBJ) $(REXXOBJ) $(SPOBJ) $(LIBS)
X
XMandel: $(SPOBJ) $(INTOBJ) $(DUMP)
X	air
X	ln -o Mandel $(INTOBJ) $(REXXOBJ) $(SPOBJ) $(LIBS)
X
XMandel-dp: $(DPOBJ) $(INTOBJ) $(DUMP)
X#	No IncRev so the number is the same as the FFP version
X	ln -o Mandel-dp $(INTOBJ) $(REXXOBJ) $(DPOBJ) $(DPLIBS)
X
Xall:	Mandel Mandel-dp
X
X$(INTOBJ):  $(HEADERS)
X$(SPOBJ):   $(HEADERS)
X$(DPOBJ):   $(HEADERS)
X
XSelect.o:   Select.req
X
XSelect.req: Select.blk
X	    blk -d $? $@
X
XMinRexx.o:  MinRexx.h
X
X$(DUMP):    dummy.c
X	cc -a +H$(DUMP) dummy.c -o nil:
SHAR_EOF
echo "extracting Mandel.h"
sed 's/^X//' << \SHAR_EOF > Mandel.h
X/*
X * :ts=8 Common DEFINEs and external declarations for the Mandelbrot
X * Construction Set...
X */
X
X#undef LIBRARY_VERSION
X#define LIBRARY_VERSION     33L /* V1.2 */
X
X
X#define MYFRONTPEN  2		/* Black */
X
X/* Menus */
X#define CPRMENU     0		/* Copyright Menu */
X#define PRJMENU     1		/* Poject Menu */
X#define OPTMENU     2		/* Option Menu */
X#define DRWMENU     3		/* Draw functions Menu */
X#define BATMENU     4		/* Batch Menu */
X
X/* Menu items */
X#define PRJNEW	    0		/* Project Menu: New */
X#define PRJOPN	    1		/* Open */
X#define PRJSVE	    2		/* Save */
X#define PRJSVA	    3		/* Save As */
X#define PRJSTP	    4		/* Stop */
X#define PRJQUI	    5		/* Quit */
X
X#define PNABS	    0		/* Project New: Absolute */
X#define PNENL	    1		/* Enlarge */
X#define PNRED	    2		/* Reduce */
X#define PNSHF	    3		/* Shift */
X#define PNZI	    4		/* Zoom In */
X#define PNZO	    5		/* Zoom Out */
X
X#define OPTCOL	    0		/* Option Menu: Colors */
X#define OPTRES	    1		/* Resolution */
X#define OPTPAR	    2		/* Parameters */
X#define OPTPRI	    3		/* Priority */
X
X#define OCSEL	    0		/* Opt Color: Select */
X#define OCMOD	    1		/* Modulo */
X#define OCRAN	    2		/* Ranges */
X#define OCPAL	    3		/* Palette */
X
X#define ORNRM	    0		/* Opt Resl: Normal */
X#define OR12	    1		/* 1/2 */
X#define OR13	    2		/* 1/3 */
X#define OR14	    3		/* 1/4 */
X#define ORFIL	    4		/* Fill In */
X#define ORHI	    5		/* HiRes */
X#define ORILC	    6		/* Interlace */
X#define ORBCK	    7		/* Borderless */
X#define OREHB	    8		/* Extra Half Brite */
X
X#define OPNOR	    0		/* Normal priority */
X#define OPLOW	    1		/* Low priority */
X
X#define DRWFUN	    0		/* Draw functions */
X#define DRWIPL	    1		/* - Iteration plot */
X#define DRWEPL	    2		/* - End plot */
X
X#define DF1	    0		/* Functions Menu: Z^2-C */
X#define DF2	    1		/* ZC1MinZ */
X#define DF3	    2		/* Z3PlusZCMin1MinC */
X#define DFUPF	    3		/* Not on the menu for now */
X#define DF5	    4		/* i:Z^2 - C */
X
X#define DINONE	    0		/* draw iplot none */
X#define DIZ	    1		/* iplot Z */
X
X#define DEDEPTH     0		/* draw eplot depth */
X#define DEZ	    1		/* eplot Z */
X
X#define BATFILE     0		/* Batch Menu: File... */
X#define BATWAIT     1		/* Wait */
X#define BATCONT     2		/* Continue */
X#define BATABORT    3		/* Abort */
X
X
X#define POSGADGETID 10		/* For Positive Gadget */
X#define NEGGADGETID 11		/* For Negative Gadget */
X
X#define FNAME_SIZE  32L 	/* Filename size */
X#define DNAME_SIZE  66L 	/* Directoryname size */
X
X#define MAXDEPTH    512 	/* Maximum maximum depth */
X#define BMDEPTH     5		/* Depth of our bitmap */
X#define MAXCOL (1<<BMDEPTH)     /* Maximum number of colors */
X
X#define NOTFRAMING  0		/* We are not framing */
X#define NOPOINT     1		/* We have no points of a frame */
X#define POINT1	    2		/* We have 1 point of a frame */
X#define CENTERFRAMING 3 	/* We have a center and are busy with a
X				 * corner */
X#define FLASHING    4		/* We are still flashing the frame */
X
X#define MODULO	    0		/* Pen assignment to the depths */
X#define RANGES	    1
X#define SELECT	    2
X
X#define MAND	    ((ULONG)'M'<<24 | (ULONG)'A'<<16 | 'N'<<8 | 'D')
X
X#define MINSCREENHEIGHT 150	/* Minimum required screen sizes */
X#define MINSCREENWIDTH	320
X
X/* Let's try to make `goto' a little more structured... :-) */
X
X#define skipto	    goto
X#define backto	    goto
X
X#define OFFSETOF(member, structure) ((long) &((struct structure *)0)->member)
X
X/* Type definitions */
X
Xtypedef short bool;
X
Xstruct BitMapHeader {
X    UWORD	    w,
X		    h;
X    UWORD	    x,
X		    y;
X    UBYTE	    nPlanes;
X    UBYTE	    masking;
X    UBYTE	    compression;
X    UBYTE	    pad1;
X    UWORD	    transparentColor;
X    UBYTE	    xAspect,
X		    yAspect;
X    WORD	    pageWidth,
X		    pageHeight;
X};
X
X/*
X * ILBM_info is the structure read_iff returns, and is hopefully all you
X * need to deal with out of the iff reader routines below
X */
Xstruct ILBM_info {
X    struct BitMapHeader header;
X    UBYTE	    cmap[MAXCOL * 3];
X    struct BitMap   bitmap;
X    struct Mand    *mand;
X    long	    mandsize;
X};
X
Xstruct Mand {
X    ULONG	    MandID;	/* 'MAND' */
X    LONG	    Size;	/* sizeof(struct Mand) */
X    WORD	    MaxDepth;	/* Maximum iteration count */
X    WORD	    RangeWidth;
X    BYTE	    RainDist;	/* From the palette Rainbow mode */
X    BYTE	    RainRMax;	/* From the palette Rainbow mode */
X    BYTE	    RainGMax;	/* From the palette Rainbow mode */
X    BYTE	    RainBMax;	/* From the palette Rainbow mode */
X    BYTE	    Coords[4 * 18];	/* Ascii representation */
X    BYTE	    FunctionNr; /* Which function was used (1...4) */
X    BYTE	    PenTableMode;	/* MODULO, RANGES, SELECT */
X    USHORT	    WBWidth;
X    USHORT	    WBHeight;
X};
X
Xstruct BorderInfo {
X    BYTE	    SizeX,
X		    SizeY;
X    BYTE	    MoveX,
X		    MoveY;
X};
X
X/* Some definitions for the User Programmed Functions */
X
Xstruct Program {
X    char	    pr_OpCode;
X    char	    pr_Dest;
X    char	    pr_Op1;
X    char	    pr_Op2;
X    long	    pr__Reserved;
X};
X
Xenum Opcode {
X    End, Rassign, Cassign, Ri, Ci, Rplus, Cplus, Rminus, Cminus,
X    Rtimes, Ctimes,
X};
X
X#define PROGRAMSIZE	64
X#define PROGRAMREGS	16
X
Xextern struct Program Program[PROGRAMSIZE];
Xextern double	PrgReg[2 * PROGRAMREGS];
X
X#define RE(x)           (x)     /* These RE and IM cannot */
X#define IM(x)           ((x) + PROGRAMREGS)     /* be exchanged! */
X
X/* Some Other Macros */
X
X#define MENU(menu,item,subitem)\
X	(LONG)(SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(subitem))
X
X/* External declarations */
X
X#include <functions.h>
Xextern long	GetScreenData();
X
X/*
X * extern struct Screen *OpenScreen(); extern struct Window *OpenWindow();
X * extern struct IntuiMessage *GetMsg(); extern struct Library
X * *OpenLibrary(); extern struct MenuItem *ItemAddress(); extern long
X * AutoRequest(), DisplayAlert(), Request(), MoveLayer(), SizeLayer();
X * extern void SetAPen(), WritePixel(), WindowLimits(), EndRequest();
X * extern struct Task *FindTask(); extern long Wait();
X */
X
X
X/* Forward POINTER declarations */
X
Xextern struct Screen *MandelScreen;
Xextern struct Window *MainWindow;
Xextern struct IntuiMessage *message;
Xextern int	(*DepthFunc) ();
Xextern void	(*IPlotFunc) ();
Xextern void	(*EPlotFunc) ();
Xextern struct IntuitionBase *IntuitionBase;
Xextern struct LayersBase *LayersBase;
Xextern struct GfxBase *GfxBase;
Xextern FILE    *BatchFILE;
Xextern struct Task *MandelTask,
X	       *DrawTask;
X
X
X/* Forward STRUCT declarations */
X
Xextern struct Menu MandelMenu[];
Xextern struct NewScreen MandelNScreen;
Xextern struct NewWindow MainNWindow;
Xextern struct TextAttr Topaz60,
X		Topaz80;
Xextern struct IntuiText PositiveText,
X		NegativeText;
Xextern struct Gadget PositiveGadget,
X		NegativeGadget;
Xextern struct BorderInfo borderinfo;
X
X
X/* Forward ARRAY declarations */
X
Xextern TEXT	FileName[FNAME_SIZE + 1];
Xextern TEXT	DirName[DNAME_SIZE + 2];
X
X
X/* Forward `SIMPLE' declarations */
X
Xextern int	NumColors,
X		MaxDepth,
X		PixelStep,
X		RangeWidth;
Xextern int	DrawPri;
Xextern unsigned PenTableMode;
Xextern unsigned short FrameX1,
X		FrameX2,
X		FrameY1,
X		FrameY2;
Xextern short	MouseStatus;
Xextern bool	finished,
X		StillDrawing,
X		Saved,
X		NameValid;
Xextern double	LeftEdge,
X		RightEdge,
X		TopEdge,
X		BottomEdge,
X		CXStep,
X		CYStep;
Xextern UBYTE	PenTable[MAXDEPTH];
Xextern UBYTE	FunctionNr;
X
Xextern SHORT	RainbowDistance,
X		RainbowRMax,
X		RainbowGMax,
X		RainbowBMax;
Xextern long	DrawSigMask;
Xextern int	DrawSigBit;
Xextern USHORT	WBWidth,
X		WBHeight;
X
X
X/* Forward FUNCTION declarations */
X
Xextern bool	InitDisplay();
Xextern bool	ReInitDisplay();
Xextern bool	Sure();
Xextern bool	CleanupDisplay();
Xextern bool	InterpretMAND();
Xextern bool	DoBorderless();
Xextern bool	DrawPicture();
Xextern bool	OpenAs();
Xextern bool	SaveAs();
Xextern bool	OpenBatch();
X
Xextern int	WaitMyRequest();
Xextern int	write_iff();
Xextern int	ZQuadMinC();
Xextern int	ZC1MinZ();
Xextern int	Z3PlusZCMin1MinC();
Xextern int	UserProgFunc();
Xextern int	I_ZQuadMinC();
X
Xextern float	Ratio();
Xextern char    *get_fname();
Xextern char    *index();
Xextern struct ILBM_info *win_read_iff();
Xextern struct Window *MyRequest();
X
Xextern void	MyExit();
Xextern void	GotMenu();
Xextern void	UndoBorderless();
Xextern void	CprMenu();
Xextern void	PrjMenu();
Xextern void	EdtMenu();
Xextern void	OptMenu();
Xextern void	DrwMenu();
Xextern void	BatchMenu();
Xextern void	UnImpl();
Xextern void	EndMyRequest();
Xextern void	CloseWindowSafely();
Xextern void	get_ea_cmap();
Xextern void	put_ea_cmap();
Xextern void	free_planes();
Xextern void	RectDraw();
Xextern void	CrossDraw();
Xextern void	CheckMouse();
Xextern void	InitPenTable();
Xextern void	StopFraming();
Xextern void	EnableSystemGadgets();
Xextern void	DisableSystemGadgets();
Xextern void	Parameters();
Xextern void	Palette();
Xextern void	MakeMAND();
Xextern void	StopDrawing();
Xextern void	CalcCSteps();
Xextern void	None();
Xextern void	PlotZ();
Xextern void	PlotIterationCount();
Xextern void	SelectMenu();
Xextern void	SuspendDrawing();
Xextern void	ResumeDrawing();
Xextern void	UpdateCheckmarks();
Xextern void	UpdateDrwFunCm();
Xextern void	UpdateDrwIplotCm();
Xextern void	UpdateDrwEplotCm();
Xextern void	UpdateOptColorCm();
Xextern void	UpdateOptDrawResCm();
Xextern void	UpdateOptViewResCm();
Xextern void	UpdateOptPriCm();
Xextern void	CloseBatch();
X
X#ifdef AREXX
X/*
X *   This is the list of functions we can access.  (Cheap forward
X *   declarations, too.)
X */
Xextern long upRexxPort() ;
Xextern void dnRexxPort() ;
Xextern void dispRexxPort() ;
Xextern struct RexxMsg *sendRexxCmd() ;
Xextern struct RexxMsg *syncRexxCmd() ;
Xextern struct RexxMsg *asyncRexxCmd() ;
Xextern void replyRexxCmd() ;
X
Xextern long RexxMask;
X#endif
X
SHAR_EOF
echo "extracting Menu.c"
sed 's/^X//' << \SHAR_EOF > Menu.c
X/*
X * M A N D E L B R O T	  C O N S T R U C T I O N   S E T
X *
X * (C) Copyright 1989 by Olaf Seibert.
X * Mandel may be freely distributed. See file 'doc/Notice' for details.
X *
X * Menu definitions.
X */
X
X#include <exec/types.h>
X#include <intuition/intuition.h>
X
X#define MENUFRONTPEN 2
X
X/*-
X * (C)             project     options         draw        batch
X * ----------------------------------------------------------------
X * About Mandel... new *       colors *        function    file...
X *		   open... /O  resolution *    iplot	   wait
X *		   save    /S  parameters      eplot	   continue
X *		   save as...  priority *		   abort
X *		   stop
X *		   quit    /Q
X *
X * new		      colors	  resolution	 priority
X * -------------------------------------------------------------
X * absolute pos'n /A  select      normal     /1  normal /0
X * enlarge	  /E  modulo	  1/2	     /2  low	/-
X * reduce	  /R  ranges	  1/3	     /3
X * shift	  /T  palette /P  1/4	     /4
X * zoom in	  /<		  fill in    /F
X * zoom out	  />		  hi-res     /H
X *				  interlace  /I
X *				  borderless /B
X *				  halfbrite  //
X *
X * functions	   iplot    eplot
X * -------------------------------------------------------------------
X * z^2-c	   None     Depth
X * z*c*(1-z)       Z        Z
X * z^3+z*(c-1)-c
X * i:user
X * i:z^2-c
X */
X
X/*
X * Define some handy shortcuts.
X */
X
X#define ITEXT(left,text) \
X    {  MENUFRONTPEN,AUTOBACKPEN,JAM1,left,1,NULL, (UBYTE*)text, NULL  }
X
X#define ITEM(num,top,next,text,flags,mutex,cmd) \
X		SITEM(num,top,next,text,flags,mutex,cmd,NULL)
X
X#define SITEM(num,top,next,text,flags,mutex,cmd,sub) \
X   {next,MLEFT,top,MWIDTH,10,flags,mutex,(APTR)&text[num],NULL,cmd,sub}
X
X#define Ax	COMMSEQ
X#define Vx	CHECKIT
X#define VV	CHECKIT | CHECKED
X#define TG	MENUTOGGLE
X#define EN	ITEMENABLED
X
X#define DEFMLEFT    40
X
X/*
X * First the menu texts.
X */
X
Xstruct IntuiText c_it[] = {
X    ITEXT(1, "About Mandel..."),
X};
X
Xstruct IntuiText project_it[] = {
X    ITEXT(1, "New        \xBB"),    /* 0xBB is the >> character */
X    ITEXT(1, "Open..."),
X    ITEXT(1, "Save"),
X    ITEXT(1, "Save As..."),
X    ITEXT(1, "Stop"),
X    ITEXT(1, "Quit..."),
X};
X
Xstruct IntuiText opts_it[] = {
X    ITEXT(1, "Colors     \xBB"),
X    ITEXT(1, "Resolution \xBB"),
X    ITEXT(1, "Parameters"),
X    ITEXT(1, "Priority   \xBB"),
X};
X
Xstruct IntuiText draw_it[] = {
X    ITEXT(1, "Func  \xBB"),
X    ITEXT(1, "IPlot \xBB"),
X    ITEXT(1, "EPlot \xBB"),
X};
X
Xstruct IntuiText batch_it[] = {
X    ITEXT(1, "File..."),
X    ITEXT(1, "Wait"),
X    ITEXT(1, "Continue"),
X    ITEXT(1, "Abort"),
X};
X
Xstruct IntuiText new_it[] = {
X    ITEXT(1, "Absolute"),
X    ITEXT(1, "Enlarge"),
X    ITEXT(1, "Reduce"),
X    ITEXT(1, "Shift"),
X    ITEXT(1, "Zoom In"),
X    ITEXT(1, "Zoom Out"),
X};
X
Xstruct IntuiText color_it[] = {
X    ITEXT(CHECKWIDTH, "Select"),
X    ITEXT(CHECKWIDTH, "Modulo"),
X    ITEXT(CHECKWIDTH, "Ranges"),
X    ITEXT(CHECKWIDTH, "Palette"),
X};
X
Xstruct IntuiText pri_it[] = {
X    ITEXT(CHECKWIDTH, "Normal"),
X    ITEXT(CHECKWIDTH, "Low"),
X};
X
Xstruct IntuiText res_it[] = {
X    ITEXT(CHECKWIDTH, "Normal"),
X    ITEXT(CHECKWIDTH, "1/2"),
X    ITEXT(CHECKWIDTH, "1/3"),
X    ITEXT(CHECKWIDTH, "1/4"),
X    ITEXT(CHECKWIDTH, "Fill In"),
X    ITEXT(CHECKWIDTH, "Hires"),
X    ITEXT(CHECKWIDTH, "Interlace"),
X    ITEXT(CHECKWIDTH, "BorderLess"),
X    ITEXT(CHECKWIDTH, "HalfBrite"),
X};
X
Xstruct IntuiText fun_it[] = {
X    ITEXT(CHECKWIDTH, "Z^2-C"),
X    ITEXT(CHECKWIDTH, "Z*C*(1-Z)"),
X    ITEXT(CHECKWIDTH, "Z^3+Z*(C-1)-C"),
X    ITEXT(CHECKWIDTH, "iplot: User"),
X    ITEXT(CHECKWIDTH, "iplot: Z^2-C"),
X};
X
Xstruct IntuiText plot_it[] = {
X    ITEXT(CHECKWIDTH, "None"),
X    ITEXT(CHECKWIDTH, "Depth"),
X    ITEXT(CHECKWIDTH, "Z"),
X};
X
X
X#define FLAGS	ITEMTEXT | ITEMENABLED | HIGHBOX
X
X/*
X *  New submenu
X */
X
X#define MLEFT	DEFMLEFT
X#define MWIDTH	8*8+2+COMMWIDTH+8   /* Funny we need 2 more pixels */
X
Xstruct MenuItem new_mi[] = {
X    ITEM(0,05,&new_mi[1],new_it,FLAGS|Ax,0,'A'), /* absolute */
X    ITEM(1,15,&new_mi[2],new_it,FLAGS|Ax,0,'E'), /* enlarge */
X    ITEM(2,25,&new_mi[3],new_it,FLAGS|Ax,0,'R'), /* reduce */
X    ITEM(3,35,&new_mi[4],new_it,FLAGS|Ax,0,'T'), /* shift */
X    ITEM(4,45,&new_mi[5],new_it,FLAGS|Ax,0,'<'), /* Zoom In */
X    ITEM(5,55,NULL,      new_it,FLAGS|Ax,0,'>'), /* Zoom Out */
X};
X
X/*
X *  Colors submenu
X */
X
X#undef	MWIDTH
X#define MWIDTH	CHECKWIDTH+7*8+COMMWIDTH+8
X
Xstruct MenuItem color_mi[] = {
X    ITEM(0,05,&color_mi[1],color_it,FLAGS|Vx,1<<1|1<<2,0), /* select */
X    ITEM(1,15,&color_mi[2],color_it,FLAGS|VV,1<<0|1<<2,0), /* modulo */
X    ITEM(2,25,&color_mi[3],color_it,FLAGS|Vx,1<<0|1<<1,0), /* ranges */
X    ITEM(3,35,NULL        ,color_it,FLAGS|Ax,0,      'P'), /* palette */
X};
X
X#undef	MWIDTH
X#define MWIDTH CHECKWIDTH+10*8+COMMWIDTH+8
X
Xstruct MenuItem res_mi[] = {
X    ITEM(0,05,&res_mi[1],res_it,FLAGS|Ax|VV,1<<1|1<<2|1<<3,'1'), /* normal */
X    ITEM(1,15,&res_mi[2],res_it,FLAGS|Ax|Vx,1<<0|1<<2|1<<3,'2'), /* 1/2 */
X    ITEM(2,25,&res_mi[3],res_it,FLAGS|Ax|Vx,1<<0|1<<1|1<<3,'3'), /* 1/3 */
X    ITEM(3,35,&res_mi[4],res_it,FLAGS|Ax|Vx,1<<0|1<<1|1<<2,'4'), /* 1/4 */
X    ITEM(4,45,&res_mi[5],res_it,FLAGS|Ax   ,0             ,'F'), /* fill in */
X
X    ITEM(5,60,&res_mi[6],res_it,FLAGS|Ax|Vx|TG,1<<8,'H'),   /* hi-res */
X    ITEM(6,70,&res_mi[7],res_it,FLAGS|Ax|Vx|TG,0   ,'I'),   /* interlace */
X    ITEM(7,80,&res_mi[8],res_it,FLAGS|Ax|Vx|TG,0   ,'B'),   /* borderless */
X    ITEM(8,90,NULL      ,res_it,FLAGS|Ax|Vx|TG,1<<4,'/'),   /* extra halfbrite */
X};
X
X#undef	MWIDTH
X#define MWIDTH CHECKWIDTH+6*8+COMMWIDTH+8
X
Xstruct MenuItem pri_mi[] = {
X    ITEM(0,05,&pri_mi[1],pri_it,FLAGS|Ax|VV,1<<1,'0'), /* normal */
X    ITEM(1,15,NULL      ,pri_it,FLAGS|Ax|Vx,1<<0,'-'), /* low */
X};
X
X/*
X *  Functions submenu:
X */
X
X#undef	MWIDTH
X#define MWIDTH	CHECKWIDTH+104
X#undef	MLEFT
X#define MLEFT	DEFMLEFT - 8
X
Xstruct MenuItem fun_mi[] = {
X    ITEM(0,05,&fun_mi[1],fun_it,FLAGS|VV,0x1F- 1,0), /* Z^2 - C */
X    ITEM(1,15,&fun_mi[2],fun_it,FLAGS|Vx,0x1F- 2,0), /* z*c*(1-z) */
X    ITEM(2,25,&fun_mi[3],fun_it,FLAGS|Vx,0x1F- 4,0), /* z^3+z*(c-1)-c */
X    ITEM(3,35,&fun_mi[4],fun_it,FLAGS|Vx,0x1F- 8,0), /* i: User */
X    ITEM(4,45,NULL      ,fun_it,FLAGS|Vx,0x1F-16,0), /* i: Z^2 - C */
X};
X
X/*
X *  iplot submenu
X */
X
X#undef	MWIDTH
X#define MWIDTH	CHECKWIDTH + (5*8)
X#undef	MLEFT
X#define MLEFT	DEFMLEFT
X
Xstruct MenuItem iplot_mi[] = {
X    ITEM(0,05,&iplot_mi[1],  plot_it,  FLAGS|VV,1<<1,0), /* None */
X    ITEM(1,15,NULL        ,(plot_it+1),FLAGS|Vx,1<<0,0), /* Z */
X};
X
X/*
X *  eplot submenu
X */
X
Xstruct MenuItem eplot_mi[] = {
X    ITEM(0,05,&eplot_mi[1],(plot_it+1),FLAGS|VV,1<<1,0), /* Depth */
X    ITEM(1,15,NULL        ,(plot_it+1),FLAGS|Vx,1<<0,0), /* Z */
X};
X
X/*
X *  (C) menu
X */
X
X#undef	MLEFT
X#define MLEFT	0
X#undef	MWIDTH
X#define MWIDTH	15*8
X
Xstruct MenuItem c_mi[] = {
X    ITEM(0,00,NULL,c_it,FLAGS,0,0), /* About Mandel... */
X};
X
X/*
X *  Project menu
X */
X
X#undef	MWIDTH
X#define MWIDTH	9*8+COMMWIDTH
X
Xstruct MenuItem project_mi[] = {
X    SITEM(0,00,&project_mi[1],project_it,FLAGS   ,0,0,new_mi), /* new */
X     ITEM(1,10,&project_mi[2],project_it,FLAGS|Ax,0,'O'     ), /* open... */
X     ITEM(2,20,&project_mi[3],project_it,FLAGS|Ax,0,'S'     ), /* save */
X     ITEM(3,30,&project_mi[4],project_it,FLAGS   ,0,0       ), /* save as... */
X     ITEM(4,45,&project_mi[5],project_it,FLAGS   ,0,0       ), /* stop */
X     ITEM(5,55,NULL          ,project_it,FLAGS|Ax,0,'Q'     ), /* quit */
X};
X
X/*
X *  Options menu
X */
X
X#undef	MWIDTH
X#define MWIDTH 12*8+2
X
Xstruct MenuItem opt_mi[] = {
X    SITEM(0,00,&opt_mi[1],opts_it,FLAGS,0,0,color_mi), /* colors */
X    SITEM(1,10,&opt_mi[2],opts_it,FLAGS,0,0,res_mi  ), /* resolution */
X     ITEM(2,20,&opt_mi[3],opts_it,FLAGS,0,0         ), /* parameters */
X    SITEM(3,30,NULL      ,opts_it,FLAGS,0,0,pri_mi  ), /* priority */
X};
X
X
X/*
X *  Draw Menu
X */
X
X#undef	MWIDTH
X#define MWIDTH	(7*8)
X#undef	MLEFT
X#define MLEFT	-MWIDTH+40
X
Xstruct MenuItem draw_mi[] = {
X    SITEM(0,00,&draw_mi[1],draw_it,FLAGS,0,0,fun_mi  ), /* func */
X    SITEM(1,10,&draw_mi[2],draw_it,FLAGS,0,0,iplot_mi), /* iplot */
X    SITEM(2,20,NULL       ,draw_it,FLAGS,0,0,eplot_mi), /* eplot */
X};
X
X
X/*
X *  Batch Menu
X */
X
X#undef	MWIDTH
X#define MWIDTH	(8*8)
X#undef	MLEFT
X#define MLEFT	-MWIDTH+43
X
Xstruct MenuItem batch_mi[] = {
X    ITEM(0,00,&batch_mi[1],batch_it,FLAGS,     0,0), /* file */
X    ITEM(1,10,&batch_mi[2],batch_it,(FLAGS)-EN,0,0), /* wait */
X    ITEM(2,20,&batch_mi[3],batch_it,(FLAGS)-EN,0,0), /* continue */
X    ITEM(3,30,NULL        ,batch_it,(FLAGS)-EN,0,0), /* abort */
X};
X
X/*
X *  Main MenuStrip structure
X */
X
Xstruct Menu MandelMenu[] = {
X    { &MandelMenu[1],	2,0,21,10, MENUENABLED, " \xA9",    c_mi       },
X    { &MandelMenu[2],  30,0,59,10, MENUENABLED, "Project",  project_mi },
X    { &MandelMenu[3], 100,0,59,10, MENUENABLED, "Options",  opt_mi     },
X    { &MandelMenu[4], 170,0,37,10, MENUENABLED, "Draw",     draw_mi    },
X    { NULL,	      220,0,43,10, MENUENABLED, "Batch",    batch_mi   },
X};
SHAR_EOF
echo "extracting MinRexx.c"
sed 's/^X//' << \SHAR_EOF > MinRexx.c
X/*
X *   This is an example of how REXX messages might be handled.	This is
X *   a `minimum' example that both accepts asynchronous REXX messages and
X *   can request REXX service.
X *
X *   Read this entire file!  It's short enough.
X *
X *   It is written in such a fashion that it can be attached to a program
X *   with a minimum of fuss.  The only external symbols it makes available
X *   are the seven functions and RexxSysBase.
X *
X *   This code is by Radical Eye Software, but it is put in the public
X *   domain.  I would appreciate it if the following string was left in
X *   both as a version check and as thanks from you for the use of this
X *   code.
X *
X *   If you modify this file for your own use, don't bump the version
X *   number; add a suffix, such as 1.0a or 1.0.3 or something, so we
X *   don't have fake `versions' floating around.
X *
X *   I [Olaf Seibert] changed it a bit for Mandel, that has its own
X *   kind of association list and command dispatcher. And I adjusted some
X *   comments to match the code.
X */
Xstatic char *blurb = "Radical Eye MinRexx 0.4 for Mandel" ;
X/*
X *   We read in our own personal little include.
X */
X#include "minrexx.h"
X/*
X *   All of our local globals, hidden from sight.
X */
Xstatic struct MsgPort *rexxPort ;	   /* this is *our* rexx port */
Xstatic int bringerdown ;		   /* are we trying to shut down? */
Xstatic struct rexxCommandList *globalrcl ; /* our command association list */
Xstatic long stillNeedReplies ;		   /* how many replies are pending? */
Xstatic long rexxPortBit ;		   /* what bit to wait on for Rexx? */
Xstatic char *extension ;		   /* the extension for macros */
Xstatic int (*userdisp)() ;                 /* the user's dispatch function */
Xstruct RexxMsg *oRexxMsg ;		   /* the outstanding Rexx message */
X/*
X *   Our library base.	Don't you dare close this!
X */
Xstruct RxsLib *RexxSysBase ;
X/*
X *   This is the main entry point into this code.
X */
Xlong upRexxPort(s, rcl, exten, uf)
X/*
X *   The first argument is the name of your port to be registered;
X *   this will be used, for instance, with the `address' command of ARexx.
X */
Xchar *s ;
X/*
X *   The second argument is an association list of command-name/user-data
X *   pairs.  It's an array of struct rexxCommandList, terminated by a
X *   structure with a NULL in the name field. The commands are case
X *   sensitive.  The user-data field can contain anything appropriate,
X *   perhaps a function to call or some other data.
X */
Xstruct rexxCommandList *rcl ;
X/*
X *   The third argument is the file extension for ARexx macros invoked
X *   by this program.  If you supply this argument, any `primitive' not
X *   in the association list rcl will be sent out to ARexx for
X *   interpretation, thus allowing macro programs to work just like
X *   primitives.  If you do not want this behavior, supply a `NULL'
X *   here, and those commands not understood will be replied with an
X *   error value of RXERRORNOCMD.
X */
Xchar *exten ;
X/*
X *   The fourth argument is the user dispatch function.  This function
X *   will *only* be called from dispRexxPort(), either from the user calling
X *   this function directly, or from dnRexxPort().  Anytime a command
X *   match is found in the association list, this user-supplied function
X *   will be called with three arguments---the Rexx message that was
X *   received, a pointer to the association pair, and a pointer to the
X *   command string.
X *   Note that the user function should never ReplyMsg() the message;
X *   instead he should indicate the return values with replyRexxCmd();
X *   otherwise we lose track of the messages that still lack replies.
X */
Xint (*uf)() ;
X/*
X *   upRexxPort() returns the signal bit to wait on for Rexx messages.
X *   If something goes wrong, it simply returns a `0'.  Note that this
X *   function is safe to call multiple times because we check to make
X *   sure we haven't opened already.  It's also a quick way to change
X *   the association list or dispatch function.
X */
X{
X   struct MsgPort *FindPort() ;
X   struct MsgPort *CreatePort() ;
X
X/*
X *   Some basic error checking.
X */
X /*
X   if (rcl == NULL || uf == NULL)
X      return(0L) ;
X  */
X/*
X *   If we aren't open, we make sure no one else has opened a port with
X *   this name already.  If that works, and the createport succeeds, we
X *   fill rexxPortBit with the value to return.
X *
X *   Note that rexxPortBit will be 0 iff rexxPort is NULL, so the check
X *   for rexxPort == NULL also insures that our rexxPortBit is 0.
X */
X   if (rexxPort == NULL) {
X      Forbid() ;
X      if (FindPort(s)==NULL)
X	 rexxPort = CreatePort(s, 0L) ;
X      Permit() ;
X      if (rexxPort != NULL)
X	 rexxPortBit = 1L << rexxPort->mp_SigBit ;
X   }
X/*
X *   Squirrel away these values for our own internal access, and return
X *   the wait bit.
X */
X   globalrcl = rcl ;
X   extension = exten ;
X   userdisp = uf ;
X   return(rexxPortBit) ;
X}
X/*
X *   This function closes the rexx library, but only if it is open
X *   and we aren't expecting further replies from REXX.  It's
X *   *private*, but it doesn't have to be; it's pretty safe to
X *   call anytime.
X */
Xstatic void closeRexxLib() {
X   if (stillNeedReplies == 0 && RexxSysBase) {
X      CloseLibrary(RexxSysBase) ;
X      RexxSysBase = NULL ;
X   }
X}
X/*
X *   This function closes down the Rexx port.  It is always safe to
X *   call, and should *definitely* be made a part of your cleanup
X *   routine.  No arguments and no return.  It removes the Rexx port,
X *   replies to all of the messages and insures that we get replies
X *   to all the ones we sent out, closes the Rexx library, deletes the
X *   port, clears a few flags, and leaves.
X */
Xvoid dnRexxPort() {
X   if (rexxPort) {
X      RemPort(rexxPort) ;
X      bringerdown = 1 ;
X/*
X *   A message still hanging around?  We kill it off.
X */
X      if (oRexxMsg) {
X	 oRexxMsg->rm_Result1 = RXERRORIMGONE ;
X	 ReplyMsg(oRexxMsg) ;
X	 oRexxMsg = NULL ;
X      }
X      while (stillNeedReplies) {
X	 WaitPort(rexxPort) ;
X	 dispRexxPort() ;
X      }
X      closeRexxLib() ;
X      DeletePort(rexxPort) ;
X      rexxPort = NULL ;
X   }
X   rexxPortBit = 0 ;
X}
X/*
X *   Here we dispatch any REXX messages that might be outstanding.
X *   This is the main routine for handling Rexx messages.
X *   This function is fast if no messages are outstanding, so it's
X *   pretty safe to call fairly often.
X *
X *   If we are bring the system down and flushing messages, we reply
X *   with a pretty serious return code RXERRORIMGONE.
X *
X *   No arguments, no returns.
X */
Xvoid dispRexxPort() {
X   register struct RexxMsg *GetMsg() ;
X   register struct RexxMsg *RexxMsg ;
X   register char *p ;
X   register int dontreply ;
X
X/*
X *   If there's no rexx port, we're out of here.
X */
X   if (rexxPort == NULL)
X      return ;
X/*
X *   Otherwise we have our normal loop on messages.
X */
X   while (RexxMsg = (struct RexxMsg *)GetMsg(rexxPort)) {
X/*
X *   If we have a reply to a message we sent, we look at the second
X *   argument.	If it's set, it's a function we are supposed to call
X *   so we call it.  Then, we kill the argstring and the message
X *   itself, decrement the outstanding count, and attempt to close
X *   down the Rexx library.  Note that this call only succeeds if
X *   there are no outstanding messages.  Also, it's pretty quick, so
X *   don't talk to me about efficiency.
X */
X      if (RexxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
X	 if (RexxMsg->rm_Args[1]) {
X	    ((int (*)())(RexxMsg->rm_Args[1]))(RexxMsg) ;
X	 }
X	 DeleteArgstring(RexxMsg->rm_Args[0]) ;
X	 DeleteRexxMsg(RexxMsg) ;
X	 stillNeedReplies-- ;
X	 closeRexxLib() ;
X/*
X *   The default case is we got a message and we need to check it for
X *   primitives.  We skip past any initial tabs or spaces and initialize
X *   the return code fields.
X */
X      } else {
X	 p = (char *)RexxMsg->rm_Args[0] ;
X	 while (*p > 0 && *p <= ' ')
X	    p++ ;
X	 RexxMsg->rm_Result1 = 0 ;
X	 RexxMsg->rm_Result2 = 0 ;
X/*
X *   If somehow the reply is already done or postponed, `dontreply' is
X *   set.
X */
X	 dontreply = 0 ;
X/*
X *   If the sky is falling, we just blow up and replymsg.
X */
X	 if (bringerdown) {
X	    RexxMsg->rm_Result1 = RXERRORIMGONE ;
X/*
X *   Otherwise we call ExecuteBatchCommand() to find and execute
X *   the command.
X */
X	 } else {
X	    int result;
X
X	    oRexxMsg = RexxMsg ;
X	    result = ExecuteBatchCommand(p);
X/*
X *   If we did get -1, we didn't understand the command.  In
X *   this case, if we were supplied an extension in upRexxPort, we know
X *   that we should send the command out, so we do so, synchronously.
X *   The synchronous send takes care of our reply.  If we were given a
X *   NULL extension, we bitch that the command didn't make sense to us.
X */
X	    if (result == -1) {
X	       if (extension) {
X		  syncRexxCmd(RexxMsg->rm_Args[0], RexxMsg) ;
X		  dontreply = 1 ;
X	       } else {
X		  RexxMsg->rm_Result1 = RXERRORNOCMD ;
X	       }
X	    } else if (result == 0) {   /* Command failed */
X	       RexxMsg->rm_Result1 = 20;
X	       RexxMsg->rm_Result2 = 10;
X	    }
X	 }
X/*
X *   Finally, reply if appropriate.
X */
X	 oRexxMsg = NULL ;
X	 if (! dontreply)
X	    ReplyMsg(RexxMsg) ;
X      }
X   }
X}
X/*
X *   Opens the Rexx library if unopened.  Returns success (1) or
X *   failure (0).  This is another function that is *private* but
X *   that doesn't have to be.
X */
Xstatic int openRexxLib() {
X   struct RxsLib *OpenLibrary() ;
X
X   if (RexxSysBase)
X      return(1) ;
X   return((RexxSysBase = OpenLibrary(RXSNAME, 0L)) != NULL) ;
X}
X/*
X *   This is the general ARexx command interface, but is not the one
X *   you will use most of the time; ones defined later are easier to
X *   understand and use.  But they all go through here.
X */
Xstruct RexxMsg *sendRexxCmd(s, f, p1, p2, p3)
Xchar *s ;
X/*
X *   The first parameter is the command to send to Rexx.
X */
Xint (*f)() ;
X/*
X *   The second parameter is either NULL, indicating that the command
X *   should execute asynchronously, or a function to be called when the
X *   message we build up and send out here finally returns.  Please note
X *   that the function supplied here could be called during cleanup after
X *   a fatal error, so make sure it is `safe'.  This function always is
X *   passed one argument, the RexxMsg that is being replied.
X */
XSTRPTR p1, p2, p3 ;
X/*
X *   These are up to three arguments to be stuffed into the RexxMsg we
X *   are building up, making the values available when the message is
X *   finally replied to.  The values are stuffed into Args[2]..Args[4].
X */
X{
X   struct RexxMsg *CreateRexxMsg() ;
X   STRPTR CreateArgstring() ;
X   register struct MsgPort *rexxport ;
X   register struct RexxMsg *RexxMsg ;
X
X/*
X *   If we have too many replies out there, we just return failure.
X *   Note that you should check the return code to make sure your
X *   message got out!  Then, we forbid, and make sure that:
X *	- we have a rexx port open
X *	- Rexx is out there
X *	- the library is open
X *	- we can create a message
X *	- we can create an argstring
X *
X *   If all of these succeed, we stuff a few values and send the
X *   message, permit, and return.
X */
X   if (rexxPort == NULL || stillNeedReplies > MAXRXOUTSTANDING-1)
X      return(NULL) ;
X   RexxMsg = NULL ;
X   if (openRexxLib() && (RexxMsg =
X	     CreateRexxMsg(rexxPort, extension, rexxPort->mp_Node.ln_Name)) &&
X	     (RexxMsg->rm_Args[0] = CreateArgstring(s, (long)strlen(s)))) {
X      RexxMsg->rm_Action = RXCOMM ;
X      RexxMsg->rm_Args[1] = (STRPTR)f ;
X      RexxMsg->rm_Args[2] = p1 ;
X      RexxMsg->rm_Args[3] = p2 ;
X      RexxMsg->rm_Args[4] = p3 ;
X      RexxMsg->rm_Node.mn_Node.ln_Name = RXSDIR ;
X      Forbid() ;
X      if (rexxport = FindPort(RXSDIR))
X	 PutMsg(rexxport, RexxMsg) ;
X      Permit() ;
X      if (rexxport) {
X	 stillNeedReplies++ ;
X	 return(RexxMsg) ;
X      } else
X	 DeleteArgstring(RexxMsg->rm_Args[0]) ;
X   }
X   if (RexxMsg)
X      DeleteRexxMsg(RexxMsg) ;
X   closeRexxLib() ;
X   return(NULL) ;
X}
X/*
X *   This function is used to send out an ARexx message and return
X *   immediately.  Its single parameter is the command to send.
X */
Xstruct RexxMsg *asyncRexxCmd(s)
Xchar *s ;
X{
X   return(sendRexxCmd(s, NULL, NULL, NULL, NULL)) ;
X}
X/*
X *   This function sets things up to reply to the message that caused
X *   it when we get a reply to the message we are sending out here.
X *   But first the function we pass in, which actually handles the reply.
X *   Note how we get the message from the Args[2]; Args[0] is the command,
X *   Args[1] is this function, and Args[2]..Args[4] are any parameters
X *   passed to sendRexxCmd() as p1..p3.  We pass the result codes right
X *   along.
X */
Xstatic void replytoit(msg)
Xregister struct RexxMsg *msg ;
X{
X   register struct RexxMsg *omsg ;
X
X   omsg = (struct RexxMsg *)(msg->rm_Args[2]) ;
X   replyRexxCmd(omsg, msg->rm_Result1, msg->rm_Result2, NULL) ;
X   ReplyMsg(omsg) ;
X}
X/*
X *   This function makes use of everything we've put together so far,
X *   and functions as a synchronous Rexx call; as soon as the macro
X *   invoked here returns, we reply to `msg', passing the return codes
X *   back.
X */
Xstruct RexxMsg *syncRexxCmd(s, msg)
Xchar *s ;
Xstruct RexxMsg *msg ;
X{
X   return(sendRexxCmd(s, (APTR)&replytoit, msg, NULL, NULL)) ;
X}
X/*
X *   There are times when you want to pass back return codes or a
X *   return string; call this function when you want to do that.
X */
Xvoid replyRexxCmd(msg, primary, secondary, string)
X/*
X *   The first parameter is the message we are replying to.
X */
Xregister struct RexxMsg *msg ;
X/*
X *   The next two parameters are the primary and secondary return
X *   codes.
X */
Xregister long primary, secondary ;
X/*
X *   The final parameter is a return string.  This string is only
X *   returned if the primary return code is 0, and a string was
X *   requested.
X */
Xregister char *string ;
X{
X   STRPTR CreateArgstring() ;
X
X/*
X *   Note how we make sure the Rexx Library is open before calling
X *   CreateArgstring . . . and we close it down at the end, if possible.
X */
X   if (primary == 0 && (msg->rm_Action & (1L << RXFB_RESULT))) {
X      if (string && openRexxLib())
X	 secondary = (long)CreateArgstring(string, (long)strlen(string)) ;
X      else
X	 secondary = 0L ;
X   }
X   msg->rm_Result1 = primary ;
X   msg->rm_Result2 = secondary ;
X   closeRexxLib() ;
X}
SHAR_EOF
echo "extracting Misc.c"
sed 's/^X//' << \SHAR_EOF > Misc.c
X/*
X * M A N D E L B R O T	C O N S T R U C T I O N   S E T
X *
X * (C) Copyright 1989 by Olaf Seibert.
X * Mandel may be freely distributed. See file 'doc/Notice' for details.
X *
X * Main Program, including some general routines
X */
X
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#ifdef DEBUG
X#   include <stdio.h>
X#   undef STATIC
X#   define STATIC   /* EMPTY */
X#endif
X#include "mandel.h"
X
Xextern struct NewWindow XYNWindow;
Xextern struct Window *XYwindow;
X
X#define BORDERLEFT	3
X#define BORDERTOP	11
X#define BORDERBOTTOM	3
X
X#define CHARS		16	/* Change UpdateXYwindow also with this */
X
Xstruct NewWindow XYNWindow =
X{
X    2 * BORDERLEFT, 2 * BORDERTOP,
X    CHARS*8+BORDERLEFT*2, 2*8+BORDERTOP+BORDERBOTTOM,
X    2, 1,		    /* DetailPen, BlockPen */
X    0,			    /* CLOSEWINDOW */
X    WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH | SIMPLE_REFRESH,
X    NULL,		    /* FirstGadget */
X    NULL,		    /* default CheckMark */
X    (UBYTE *) "Re and Im",  /* Title */
X    NULL,		    /* Screen */
X    NULL,		    /* BitMap */
X    0, 0,		    /* MinWidth, MinHeight */
X    0, 0,		    /* MaxWidth, MaxHeight */
X    CUSTOMSCREEN	    /* Screen type */
X};
X
Xdouble ReMouse, ImMouse;
X
X/*
X *  We always ask for INTUITICKS, since this window will only be open
X *  as long as we have the flashing lines.
X */
X
Xvoid OpenXYwindow()
X{
X    if (XYwindow == NULL) {
X	XYNWindow.Screen = MandelScreen;
X
X	if (XYwindow = OpenWindow(&XYNWindow)) {
X	    XYwindow->UserPort = MainWindow->UserPort;
X	    ModifyIDCMP(XYwindow, (long)CLOSEWINDOW | MOUSEBUTTONS | INTUITICKS);
X	    SetDrMd(XYwindow->RPort, (long)JAM2);
X	    SetAPen(XYwindow->RPort, (long)1);
X	    SetBPen(XYwindow->RPort, (long)0);
X	}
X    }
X}
X
Xvoid CloseXYwindow()
X{
X    if (XYwindow) {
X	CloseWindowSafely(XYwindow);
X	XYwindow = NULL;
X    }
X}
X
Xvoid UpdateXYwindow(x, y)   /* corrected: 0..max */
Xint x, y;
X{
X    register int chars;
X    register struct RastPort *rp;
X    register long left, top;
X    char buffer[CHARS+2];	/* 1 extra for \0, and 1 for safety */
X    static char format[] = "%-16.10g";      /* 16 == CHARS */
X    /* -1.234567890e-99 is 16 chars with a precision of 10 digits */
X
X    ReMouse = LeftEdge + CXStep * x;
X    ImMouse = TopEdge - CYStep * y;
X
X    if (XYwindow) {
X	rp = XYwindow->RPort;
X	left = XYwindow->BorderLeft;
X	top = XYwindow->BorderTop;
X
X	chars = sprintf(buffer, format, ReMouse);
X	Move(rp, left, top+7);
X	Text(rp, buffer, (long)chars);
X
X	chars = sprintf(buffer, format, ImMouse);
X	Move(rp, left, top+15);
X	Text(rp, buffer, (long)chars);
X    }
X}
X
Xvoid MyExit(status)
Xchar *status;
X{
X    static char message[] = "\
X\0\144\25Mandelbrot Construction Set -- By KosmoSoft Productions\0a\
X\0\144\41								  \0";
X/*	3^5^  10^    ^	20^    ^  30^	 ^  40^    ^  50^  55^58^     */
X    register char *c=message+63;
X
X#ifdef AREXX
X    dnRexxPort();
X#endif
X
X    if (status) {
X	/* Center the message. */
X
X	{
X	    register int halfway = 320 - (strlen(status) << 2);
X	    message[60] = halfway >> 8; /* High byte */
X	    message[61] = halfway;	/* Low byte */
X	}
X	while ((*(c++) = *(status++)) && c < message + 127);
X	*c = 0;
X
X	/* Let's be paranoid for a change... */
X	if (!IntuitionBase) IntuitionBase = (struct IntuitionBase *)
X	    OpenLibrary ("intuition.library", 0L);
X	if (IntuitionBase)
X	    DisplayAlert(RECOVERY_ALERT, message, 50L);
X	else {	/* AT_Recovery | AG_OpenLib | AO_Intuition */
X	    CPTR AlertParameter = (CPTR) FindTask(NULL);
X	    Alert(0x00038004L, &AlertParameter);
X	}
X
X	status=1;
X    }
X    CleanupDisplay((bool) TRUE);
X    if (DrawSigBit != -1) FreeSignal((long)DrawSigBit);
X    if (IntuitionBase) CloseLibrary(IntuitionBase);
X    if (LayersBase) CloseLibrary(LayersBase);
X    if (GfxBase) CloseLibrary(GfxBase);
X    exit ((int) (status != NULL));
X}
X
Xvoid _abort()
X{
X    MyExit("_abort() called...");
X}
X
Xbool Sure()
X{
X    bool Result;
X    ULONG OldIDCMP = MainWindow->IDCMPFlags;
X
X    static struct IntuiText Body[] =
X    {
X	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
X	    25, 10, NULL, (UBYTE *) "You are going to", &Body[1]    },
X	{   MYFRONTPEN+1, AUTOBACKPEN, AUTODRAWMODE,
X	    57, 25, &Topaz60, (UBYTE *) "destroy", &Body[2] },
X	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
X	    33, 40, NULL, (UBYTE *) "your picture !", NULL  }
X    };
X
X    if (Saved) return TRUE;
X
X    ModifyIDCMP(MainWindow, OldIDCMP &~ (MENUVERIFY | SIZEVERIFY | REQVERIFY));
X    Result = AutoRequest(MainWindow, &Body[0], &PositiveText, &NegativeText,
X	NULL, NULL, 200L, 90L);
X    ModifyIDCMP(MainWindow, OldIDCMP);
X
X    return Result;
X}
X
X/*
X * Render a requester in a window. If it won't fit, open a new window.
X * This new window will share the IDCMP port with the original
X * window. This is to save memory, signal bits and VERIFY deadlocks.
X * Returns the window in which the requester actually appears.
X */
X
Xstruct Window *MyRequest(request, window)
Xstruct Requester *request;
Xstruct Window *window;
X{
X    static struct NewWindow newwindow = {
X	0, 0, 0, 0, 2, 1,
X	NULL,		/* IDCMP flags -- port shared with main window */
X	WINDOWDEPTH | WINDOWDRAG | ACTIVATE | SIMPLE_REFRESH | NOCAREREFRESH,
X	NULL, NULL, NULL, NULL,
X	NULL, 0, 0, 0, 0, NULL	};
X    int width, height;
X    int borderleft, borderright, bordertop, borderbottom;
X    struct Window *oldwindow = window;
X
X    borderleft	 = window->WScreen->WBorLeft;
X    borderright  = window->BorderRight;
X    bordertop	 = window->WScreen->BarHeight + 1;
X    borderbottom = window->BorderBottom;
X
X    /* Center the requester in the given window.
X     * If impossible, open a new window to the place the requester in.
X     */
X
X     width = window->GZZWidth;
X     height = window->GZZHeight;
X
X     if (width < request->Width || height < request-> Height) {
X	/* Window too small. Open a new one */
X	newwindow.Screen = window->WScreen;
X	newwindow.Type = window->WScreen->Flags & SCREENTYPE;
X	newwindow.Title = window->Title;
X	newwindow.Width = request->Width + 2 * borderleft;
X	newwindow.Height = request->Height + bordertop + borderbottom;
X	newwindow.LeftEdge = (newwindow.Screen->Width - newwindow.Width) / 2;
X	newwindow.TopEdge = (newwindow.Screen->Height - newwindow.Height) / 2;
X
X	if (window = OpenWindow(&newwindow)) {
X	    window->UserPort = oldwindow->UserPort;
X	    /* Upen up the other port */
X	    ModifyIDCMP(window, GADGETUP);
X	}
X
X	request->LeftEdge = borderleft;
X	request->TopEdge = bordertop;
X    } else {	/* The requester fits. Center it! */
X	request->LeftEdge = ((width - request->Width) >> 1);
X	request->TopEdge = ((height - request->Height) >> 1);
X	if (!(window->Flags & GIMMEZEROZERO)) {
X	    request->LeftEdge += borderleft;
X	    request->TopEdge += bordertop;
X	}
X    }
X
X    if (window && Request(request, window)) return window;
X
X    if (window) CloseWindowSafely(window);
X    return NULL;
X}
X
Xvoid EndMyRequest(request, window, original)
Xstruct Requester *request;
Xstruct Window *window, *original;
X{
X    EndRequest(request, window);
X    if (window != original) CloseWindowSafely(window);
X}
X
X/*
X * Wait on a request posted by MyRequest.
X * Returns when a gadget with GadgetID >= POSGADGETID is released,
X * so Gadgets with an ID < POSGADGETID will be ignored.
X * NEGGADID > POSGADID.
X * Any messages other than GADGETUP will be ignored.
X */
X
Xint WaitMyRequest(window)
Xstruct Window *window;
X{
X    int ID = 0;
X    struct IntuiMessage *message;
X    struct Gadget *Gadget;
X    ULONG Class;
X    ULONG OldIDCMP = window->IDCMPFlags;
X    ULONG SigMask;
X
X    if (!window)
X	return NEGGADGETID;
X
X    ModifyIDCMP(window, GADGETUP);
X
X#ifdef AREXX
X    SigMask = RexxMask | (1L << MainWindow->UserPort->mp_SigBit);
X#else
X    SigMask = (1L << MainWindow->UserPort->mp_SigBit);
X#endif
X
X    while (ID < POSGADGETID) {
X	Wait(SigMask);
X#ifdef AREXX
X	dispRexxPort();
X#endif
X	while (message = (struct IntuiMessage *) GetMsg(window->UserPort) ) {
X	    Class = message->Class;
X	    Gadget = (struct Gadget *)message->IAddress;
X	    ReplyMsg(message);
X	    if (Class != GADGETUP) continue;
X	    ID = Gadget->GadgetID;
X	    if (ID >= POSGADGETID) break; /* Also gets out of outer loop */
X	}
X    }
X    ModifyIDCMP(window, OldIDCMP);
X    return ID;
X}
X
Xvoid RectDraw(rp, x1, y1, x2, y2)
Xstruct RastPort *rp;
XSHORT x1, y1, x2,y2;
X{
X    Move(rp, (long) x1, (long) y1);
X    Draw(rp, (long) x2, (long) y1);
X    Draw(rp, (long) x2, (long) y2);
X    Draw(rp, (long) x1, (long) y2);
X    if (y2 > y1) y1++; else y1--;   /* Don't XOR the first pixel twice */
X    Draw(rp, (long) x1, (long) y1);
X}
X
Xvoid CrossDraw(rp, x, y, left, right, top, bottom)
Xstruct RastPort *rp;
XSHORT x, y, top, bottom, left, right;
X{
X    Move(rp, (long) left, (long) y);
X    Draw(rp, (long) right, (long) y);
X    Move(rp, (long) x, (long) top);
X    Draw(rp, (long) x, (long) bottom);
X}
X
Xvoid DisableSystemGadgets(gadget)
Xstruct Gadget *gadget;
X{
X    while (gadget) {
X	if (gadget->GadgetType & SYSGADGET) {
X	    /* Ghost everything except the Title/Dragbar */
X	    if ((gadget->GadgetType & 0x00F0) != WDRAGGING)
X		OffGadget(gadget, MainWindow, NULL);
X	    gadget->Flags |= GADGDISABLED;
X	}
X	gadget = gadget->NextGadget;
X    }
X}
X
Xvoid EnableSystemGadgets(gadget)
Xstruct Gadget *gadget;
X{
X    USHORT Flags = 0;
X
X    while (gadget) {
X	if (gadget->GadgetType & SYSGADGET) {
X	    Flags |= gadget->Flags;
X	    gadget->Flags &= ~GADGDISABLED;
X	}
X	gadget = gadget->NextGadget;
X    }
X    /* Unghost everthing if necessary */
X    if (Flags & GADGDISABLED)   RefreshWindowFrame(MainWindow);
X}
X
Xvoid StopFraming()
X{
X    if (MainWindow) {
X	EnableSystemGadgets(MainWindow->FirstGadget);
X	ModifyIDCMP(MainWindow, MainWindow->IDCMPFlags & ~INTUITICKS);
X    }
X    MouseStatus = NOTFRAMING;
X    CloseXYwindow();
X}
X
Xvoid CheckMouse(Message)
Xregister struct IntuiMessage *Message;
X{
X    register SHORT top = MainWindow->BorderTop,
X		   bottom = MainWindow->Height - MainWindow->BorderBottom - 1,
X		   left = MainWindow->BorderLeft,
X		   right = MainWindow->Width - MainWindow->BorderRight - 1;
X    static ULONG OldSecs, OldMicros;
X    static SHORT MidX, MidY;
X    USHORT MouseX, MouseY;
X
X    if (Message->IDCMPWindow == MainWindow) {
X	MouseX = Message->MouseX;
X	MouseY = Message->MouseY;
X    } else {
X	MouseX = MainWindow->MouseX;
X	MouseY = MainWindow->MouseY;
X    }
X
X    if (StillDrawing || MouseStatus != FLASHING &&
X	(MouseX < left || MouseX > right || MouseY < top || MouseY > bottom))
X	return;
X
X    MouseX -= left;
X    MouseY -= top;
X
X    if (Message->Class == MOUSEBUTTONS) {
X	if (Message->Code == SELECTDOWN) {
X	    /* We selected a point */
X	    switch (MouseStatus) {
X	    case NOTFRAMING:
X	    case FLASHING:
X		MouseStatus = NOPOINT;
X		DisableSystemGadgets(MainWindow->FirstGadget);
X		ModifyIDCMP(MainWindow, MainWindow->IDCMPFlags | INTUITICKS);
X		OpenXYwindow();
X		/* Now we can select our first corner */
X		break;
X	    case NOPOINT:
X		FrameX1 = FrameX2 = MouseX;
X		FrameY1 = FrameY2 = MouseY;
X		MouseStatus = POINT1;
X		OldMicros = Message->Micros;
X		OldSecs = Message->Seconds;
X		/* We have the first point. Now go for the second */
X		break;
X	    case POINT1:
X		if (DoubleClick(OldSecs, OldMicros,
X				Message->Seconds, Message->Micros)) {
X		    /* Did we double-click? Then we have selected a center */
X		    MouseStatus = CENTERFRAMING;
X		    MidX = FrameX1;
X		    MidY = FrameY1;
X		    break;
X		}
X		FrameX2 = MouseX;
X		FrameY2 = MouseY;
X		/* Fall through to CENTERFRAMING */
X	    case CENTERFRAMING:
X		if (FrameX1 == FrameX2 || FrameY1 == FrameY2) break;
X		EnableSystemGadgets(MainWindow->FirstGadget);
X		MouseStatus = FLASHING;
X		/* Point 1 should be upper left */
X		if (FrameX2 < FrameX1) {
X		    /* I DO know I am reusing a variable here. Sorry! */
X		    left=FrameX2; FrameX2=FrameX1; FrameX1=left;
X		}
X		if (FrameY2 < FrameY1) {
X		    left=FrameY2; FrameY2=FrameY1; FrameY1=left;
X		}
X		break;
X	    }	/* End switch MouseStatus */
X	}   /* End if Code == SELECTDOWN */
X	return;
X    }	/* End if Class == MOUSEBUTTONS */
X
X    /* We are moving the mouse. Show something! */
X
X    UpdateXYwindow(MouseX, MouseY);
X
X    SetDrMd(MainWindow->RPort, (ULONG) COMPLEMENT);
X
X    switch (MouseStatus) {
X    /* case NOTFRAMING: */
X    /*	return; */
X    case NOPOINT:
X	FrameX1 = FrameX2 = MouseX;
X	FrameY1 = FrameY2 = MouseY;
X	WaitTOF();
X	CrossDraw(MainWindow->RPort, FrameX1, FrameY1,
X		    0, MainWindow->GZZWidth-1, 0, MainWindow->GZZHeight-1);
X	WaitTOF();
X	CrossDraw(MainWindow->RPort, FrameX1, FrameY1,
X		    0, MainWindow->GZZWidth-1, 0, MainWindow->GZZHeight-1);
X	break;
X    case CENTERFRAMING:
X	FrameX1 = MouseX;
X	FrameY1 = MouseY;
X	FrameX2 = 2*MidX - FrameX1;
X	FrameY2 = 2*MidY - FrameY1;
X	skipto flashing;
X    case POINT1:
X	FrameX2 = MouseX;
X	FrameY2 = MouseY;
X	/* Deliberate Fall-Through to FLASHING */
X    case FLASHING:
Xflashing:
X	WaitTOF();
X	RectDraw(MainWindow->RPort, FrameX1, FrameY1, FrameX2, FrameY2);
X	WaitTOF();
X	RectDraw(MainWindow->RPort, FrameX1, FrameY1, FrameX2, FrameY2);
X    }
X}
X
Xvoid InitPenTable()
X{
X    register int i;
X
X    switch (PenTableMode) {
X    case MODULO:
X	PenTable[0] = 0;
X	for (i=1; i<MAXDEPTH; i++) PenTable[i] = 1 + i % (NumColors - 1);
X	break;
X    case RANGES:
X	PenTable[0] = 0;
X	for (i=1; i<MAXDEPTH; i++)
X	    PenTable[i] = 1 + (i/RangeWidth) % (NumColors - 1);
X    case SELECT:
X	/* Don't change the table if it is user-defined */
X	break;
X    }
X}
X
Xvoid SelectMenu(MenuNum, CheckIt)
XLONG MenuNum;
Xbool CheckIt;
X{
X    struct MenuItem *Item = ItemAddress(MandelMenu, MenuNum);
X
X    ClearMenuStrip(MainWindow);
X
X    if (CheckIt)
X	Item->Flags |= CHECKED;
X    else
X	Item->Flags &= ~CHECKED;
X
X    SetMenuStrip(MainWindow, MandelMenu);
X}
X
Xvoid MakeMAND(mand)
Xstruct Mand *mand;
X{
X    int i;
X
X    mand->MandID = MAND;
X    mand->Size = sizeof(struct Mand) - 2 * sizeof(LONG);
X    mand->MaxDepth = MaxDepth;
X    mand->RangeWidth = RangeWidth;
X
X    mand->RainDist = RainbowDistance;
X    mand->RainRMax = RainbowRMax;
X    mand->RainGMax = RainbowGMax;
X    mand->RainBMax = RainbowBMax;
X
X    for (i=0; i < sizeof(mand->Coords); i++)
X	mand->Coords[i] = '\0';
X    sprintf(&mand->Coords[0], "%1.10g %1.10g %1.10g %1.10g",
X	LeftEdge, RightEdge, TopEdge, BottomEdge);
X
X    mand->FunctionNr = FunctionNr;
X    mand->PenTableMode = PenTableMode;
X    mand->WBWidth = WBWidth;
X    mand->WBHeight = WBHeight;
X
X}
X
Xbool InterpretMAND(mand, ilbminfo)
Xstruct Mand *mand;
Xstruct ILBM_info *ilbminfo;
X{
X    double NewLeftEdge, NewRightEdge, NewTopEdge, NewBottomEdge;
X    double Ratio;
X
X    /* Perform some checks on correctness of the chunk */
X    if (mand->MandID != MAND ||
X	 mand->Size > sizeof(struct Mand) - 2 * sizeof(LONG) ||
X	  mand->MaxDepth > MAXDEPTH ||
X	   mand->RangeWidth > MAXDEPTH)
X	return FALSE;
X
X    if (sscanf(&mand->Coords[0], "%lf %lf %lf %lf",
X	&NewLeftEdge, &NewRightEdge, &NewTopEdge, &NewBottomEdge) < 4)
X	return FALSE;
X
X    MaxDepth	= mand->MaxDepth;
X    RangeWidth	= mand->RangeWidth;
X
X    /* Compensate for different sized windows */
X
X    Ratio	= (double)MainWindow->GZZWidth / (double)ilbminfo->header.w;
X    LeftEdge	= NewLeftEdge;
X    if (Ratio != 1.0)
X	RightEdge = NewLeftEdge + Ratio * (NewRightEdge - NewLeftEdge);
X    else	    /* avoid round-off when almost exactly 1.0000 */
X	RightEdge = NewRightEdge;
X
X    Ratio	= (double)MainWindow->GZZHeight / (double)ilbminfo->header.h;
X    TopEdge	= NewTopEdge;
X    if (Ratio != 1.0)
X	BottomEdge = NewTopEdge - Ratio * (NewTopEdge - NewBottomEdge);
X    else	    /* avoid round-off when almost exactly 1.0000 */
X	BottomEdge = NewBottomEdge;
X
X    CalcCSteps();
X
X    RainbowDistance = mand->RainDist;
X    RainbowRMax = mand->RainRMax;
X    RainbowGMax = mand->RainGMax;
X    RainbowBMax = mand->RainBMax;
X
X    if (mand->Size > OFFSETOF(FunctionNr, Mand) - 2*sizeof(long)) {
X	SetDrawingFunction(mand->FunctionNr);
X	PenTableMode = mand->PenTableMode;
X	WBWidth = mand->WBWidth;
X	WBHeight = mand->WBHeight;
X	InitPenTable();
X    }
X
X    UpdateCheckmarks();
X
X    return TRUE;
X}
SHAR_EOF
echo "End of archive 3 (of 4)"
# if you want to concatenate archives, remove anything after this line
exit