/* * 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 * * (C) Copyright 1989 by Olaf Seibert. * Mandel may be freely distributed. See file 'doc/Notice' for details. * * Main Loop, and a lot of Variables. */ #include #include #ifdef DEBUG # include # undef STATIC # define STATIC /* EMPTY */ #endif #include "mandel.h" extern int Enable_Abort; struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct LayersBase *LayersBase; struct TextAttr Topaz80 = { (STRPTR) "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT }; struct TextAttr Topaz60 = { (STRPTR) "topaz.font", TOPAZ_SIXTY, FS_NORMAL, FPF_ROMFONT }; struct NewScreen MandelNScreen = { 0, 0, 320, 256, /* LeftEdge, TopEdge, Width, Height */ 4, /* Depth */ 2, 1, /* DetailPen, BlockPen */ NULL, /* viewmode LORES */ CUSTOMSCREEN, /* type */ &Topaz80, /* Font (default) */ #ifdef IEEEDP (UBYTE *) "DP Mandelbrot Construction Set 1.3" #else (UBYTE *) "FFP Mandelbrot Construction Set 1.3" #endif }; struct NewWindow MainNWindow = { 0, 0, 0, 0, /* LeftEdge, TopEdge, Width, Height */ 2, 1, /* DetailPen, BlockPen */ CLOSEWINDOW | MENUPICK | MOUSEBUTTONS | VANILLAKEY | SIZEVERIFY /* | MENUVERIFY */ , WINDOWCLOSE | ACTIVATE | WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH | SMART_REFRESH | GIMMEZEROZERO, NULL, /* FirstGadget */ NULL, /* default CheckMark */ (UBYTE *) "Mandelbrot Construction Window", /* Title */ NULL, /* Screen */ NULL, /* BitMap */ 60, 25, /* MinWidth, MinHeight */ -1, -1, /* MaxWidth, MaxHeight */ CUSTOMSCREEN /* Screen type */ }; struct BorderInfo borderinfo; struct IntuiText PositiveText = { AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE, NULL, (UBYTE *) "Continue", NULL }, NegativeText = { AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE, &Topaz60, (UBYTE *) "Cancel", NULL }; STATIC SHORT XY1[] = {0, 0, 0, 13, 78, 13, 78, 0, 0, 0}; STATIC SHORT XY2[] = {0, 0, 0, 17, 82, 17, 82, 0, 0, 0}; STATIC struct Border border[] = { {0, 0, 2, 0, JAM1, 5, XY1, &border[1]}, {-2, -2, 3, 0, JAM1, 5, XY2, NULL} }; struct Gadget NegativeGadget = { NULL, -100, -20, 79, 14, /* next, LTWH */ GADGHCOMP | GRELBOTTOM | GRELRIGHT, RELVERIFY | ENDGADGET, BOOLGADGET | REQGADGET, (APTR) & border[0], NULL, &NegativeText, 0, NULL, NEGGADGETID, NULL }; struct Gadget PositiveGadget = { &NegativeGadget, 20, -20, 79, 14, /* next, LTWH */ GADGHCOMP | GRELBOTTOM, RELVERIFY | ENDGADGET, BOOLGADGET | REQGADGET, (APTR) & border[0], NULL, &PositiveText, 0, NULL, POSGADGETID, NULL }; UBYTE PenTable[MAXDEPTH]; unsigned PenTableMode = MODULO; short RangeWidth = 2; struct Screen *MandelScreen = NULL; /* Pointer for OpenScreen return * value */ struct Window *MainWindow = NULL; /* Idem for OpenWindow */ struct Window *XYwindow; /* The X/Y window */ extern struct Window *ColorWindow; /* Palette */ USHORT WBWidth = 0; /* Preferred size of our screen */ USHORT WBHeight = 0; /* in Hires/noninterlace values */ int (*DepthFunc) () = ZQuadMinC; UBYTE FunctionNr = 0; void (*IPlotFunc) () = None; UBYTE IPlotNr = 0; void (*EPlotFunc) () = PlotIterationCount; UBYTE EPlotNr = 0; double LeftEdge = -0.800, /* Left edge of the picture */ RightEdge = 2.100, TopEdge = 1.200, BottomEdge = -1.200; double CXStep, /* Stepsize through the complex plane */ CYStep; int PixelStep = 1, /* Stepsize on the screen */ MaxDepth = 100; /* Maximum iteration count */ int NumColors; /* Number of colors on the screen */ unsigned short FrameX1, FrameX2, FrameY1, FrameY2; short MouseStatus = NOTFRAMING; /* Where we are in the * process of selecting a * frame */ bool finished = FALSE; /* TRUE to stop the program */ bool Saved = TRUE; /* Indicates the picture has been SAVEd */ bool NameValid = FALSE; /* Indicates the file name is * valid */ bool StillDrawing = FALSE; /* Are we still drawing ? */ FILE *BatchFILE; /* Current batch file */ int DrawSigBit = -1;/* Signal when drawing is finished */ long DrawSigMask; #ifdef AREXX /* * And here is some AREXX stuff. Not very complicated, thanks to * MinRexx by Tomas Rokicki (Radical Eye Software). */ long RexxMask; /* Wait signal mask */ extern short BatchWaiting; /* Halting all Arexx traffic as well */ #endif /* * M A I N E N T R Y P O I N T */ main(argc, argv) int argc; char **argv; { char *Main(); extern struct SignalSemaphore DrawSemaphore; /* * Before we do anything, do an operation which requires the floating * point library. So if it is not available, we abort before we need * to clean up anything. Note that CXStep is not initialized at this * moment. */ CXStep = 1.0; CXStep = CXStep * 2.0; /* * Make sure we aren't interrupted by any user pressing ^C while we * are doing I/O. */ Enable_Abort = 0; /* * Open each of the libraries and check for a NULL return, which * indicates unavailability. */ IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", LIBRARY_VERSION); if (IntuitionBase == NULL) MyExit("Can't open Intuition V1.2 or newer!"); GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", LIBRARY_VERSION); if (GfxBase == NULL) MyExit("Can't open Gfx V1.2 or newer!"); LayersBase = (struct LayersBase *) OpenLibrary("layers.library", LIBRARY_VERSION); if (LayersBase == NULL) MyExit("Can't open Layers V1.2 or newer!"); DrawSigBit = AllocSignal(-1L); if (DrawSigBit == -1) MyExit("Can't allocate signal!"); DrawSigMask = 1L << DrawSigBit; InitSemaphore(&DrawSemaphore); MandelTask = FindTask(NULL); #ifdef AREXX /* * For rexx, we open up a Rexx port, and Batch() will send out * the first command, if there was one. */ RexxMask = upRexxPort("MANDEL", NULL, "mand", NULL) ; #endif if (InitDisplay((bool) FALSE)) MyExit("Can't initialise the display properly!"); CalcCSteps(); Options(argc, argv); /* Maybe open the batch */ Batch(); /* Check the batch */ MyExit(Main()); } char * Main() { register ULONG Class; /* IntuiMessage class */ register USHORT Code; /* and Code field */ struct IntuiMessage *message; /* Expected message pointer */ struct Window *window; /* window related to message */ long signalmask; long signals; #ifdef AREXX /* * If we're working with Rexx, we wait on the Rexx bit as well. * Then, we handle any Rexx messages. */ signalmask = RexxMask | DrawSigMask | (1L << MainWindow->UserPort->mp_SigBit); #else signalmask = DrawSigMask | (1L << MainWindow->UserPort->mp_SigBit); #endif again: finished = FALSE; while (!finished) { /* * Wait for message port to become not empty, and extract the * message or, alternatively, for the drawing to finish. */ signals = Wait(signalmask); #ifdef AREXX if ((signals & RexxMask) && !BatchWaiting) { dispRexxPort(); } #endif if (signals & DrawSigMask) { /* drawing finished */ Batch(); /* Check the batch */ #ifdef AREXX Signal(MandelTask, RexxMask);/* Wake up Arexx as well */ #endif } while (message = (struct IntuiMessage *) GetMsg(MainWindow->UserPort)) { window = message->IDCMPWindow; if (window == ColorWindow) { HandleColorWindow(message); continue; } Class = message->Class; Code = message->Code; if (Class & ~(MOUSEBUTTONS | INTUITICKS)) { ReplyMsg(message); /* Pointer is not valid anymore */ } switch (Class) { case MENUPICK: GotMenu(Code); break; case MOUSEBUTTONS: case INTUITICKS: CheckMouse(message); ReplyMsg(message); break; case SIZEVERIFY: StopFraming(); /* Fall Through to MenuVerify */ case MENUVERIFY: break; /* Just make sure there is no half-drawn * frame */ case CLOSEWINDOW: if (window == MainWindow) { finished = TRUE; } else { CloseXYwindow(); } break; case VANILLAKEY: if (Code == ('Q' & 0x1F)) { /* Ctrl-Q; don't check to * be sure */ skipto finished; } break; /* default: Ignore strange messages */ } /* End Switch The Class Of The Message */ } /* End While There Is A Message */ } /* End While Not Finished */ /* * So we are finished. And, by the way, are we SURE we are finished * alltogether ?? */ if (!Sure()) { backto again; } finished: CleanupDisplay((bool) TRUE); return NULL; /* Indicate Good Exit */ } /* End of Main */