#define DEBUG /* :ts=4 * 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 * * Main Program, including some general routines */ #include #include /* #include */ #ifdef DEBUG # include # undef STATIC # define STATIC /* EMPTY */ #endif #include "mandel.h" 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) */ (UBYTE *)"Mandelbrot Construction Set V1.0" /* DefaultTitle for menubar */ }; struct NewWindow MainNWindow = { 0, 0, 0, 0, /* LeftEdge, TopEdge, Width, Height */ 2, 1, /* DetailPen, BlockPen */ CLOSEWINDOW | MENUPICK | MOUSEBUTTONS | 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 }; USHORT ColorMap[MAXDEPTH]; bool ColorMapValid = FALSE; 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 */ void (*WritePixelDepth)() = ZQuadMinC; 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 */ 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 ? */ /* Manx startup stubs, to save some memory. Not useful with Lattice! */ #ifdef MANX_C _cli_parse() {} _wb_parse() {} #endif /* M A I N E N T R Y P O I N T */ main() { register ULONG Class; /* IntuiMessage class */ register USHORT Code; /* and Code field */ struct IntuiMessage *message; /* Expected message pointer */ /* 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!"); if (InitDisplay((bool)FALSE)) MyExit ("Can't initialise the display properly!"); CalcCSteps(); again: finished = FALSE; while (!finished) { /* Wait for message port to become not empty, and extract the msg */ WaitPort(MainWindow->UserPort); while ( message = (struct IntuiMessage *) GetMsg(MainWindow->UserPort) ) { gotmessage: 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(Class, Code, message->MouseX, message->MouseY, message->Seconds, message->Micros); ReplyMsg(message); break; case SIZEVERIFY: StopFraming(); /* Fall Through to MenuVerify */ case MENUVERIFY: break; /* Just make sure there is no half-drawn frame */ case CLOSEWINDOW: finished = TRUE; 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; } CleanupDisplay((bool)TRUE); MyExit(NULL); /* Indicate Good Exit */ } /* End of main */ /* Initialize the screen and the windows and the menus */ bool InitDisplay(borderless) bool borderless; { USHORT ViewModes = MandelNScreen.ViewModes; struct Screen WBScreen; int i; StopFraming(); Saved = TRUE; /* We can easily reconstruct this `picture' */ /* Get Left, Top, Width, Height */ GetScreenData(&WBScreen, (long)sizeof(WBScreen), (long)WBENCHSCREEN, NULL); MandelNScreen.Width = WBScreen.Width; MandelNScreen.Height = WBScreen.Height; /* Maybe we have an interlaced WorkBench screen */ if (WBScreen.ViewPort.Modes & LACE) MandelNScreen.Height >>= 1; /* And maybe, if we use MWB, it isn't hires... */ if (!(WBScreen.ViewPort.Modes & HIRES)) MandelNScreen.Width <<= 1; if (ViewModes & LACE) MandelNScreen.Height <<= 1; if (ViewModes & HIRES) { MandelNScreen.Depth = 4; NumColors = 16; /* Avoid a bug in MrgCop()?? if you have a PAL machine with */ /* a screen wider than 640 taller than 213 and with 4 bitplanes */ if (MandelNScreen.Width > 640) MandelNScreen.Width = 640; } else { MandelNScreen.Depth = 5; NumColors = 32; MandelNScreen.Width >>= 1; } if ( !MandelScreen && !(MandelScreen = OpenScreen(&MandelNScreen)) ) { skipto abort; } if (ColorMapValid) LoadRGB4(&MandelScreen->ViewPort, ColorMap, (long) NumColors); MainNWindow.Screen = MandelScreen; if (MainNWindow.Height < MainNWindow.MinHeight) { /* First time we open the window */ MainNWindow.LeftEdge = 0; MainNWindow.TopEdge = MandelScreen->BarHeight; MainNWindow.Width = MandelScreen->Width; MainNWindow.Height = MandelScreen->Height - MainNWindow.TopEdge; } else { if (ViewModes & HIRES) { MainNWindow.LeftEdge <<= 1; MainNWindow.Width <<= 1; } if (ViewModes & LACE) { MainNWindow.TopEdge <<= 1; MainNWindow.Height <<= 1; } } /* Check for windows that can't be opened */ if (MainNWindow.LeftEdge + MainNWindow.Width > MandelScreen->Width) MainNWindow.Width = MandelScreen->Width - MainNWindow.LeftEdge; if (MainNWindow.TopEdge + MainNWindow.Height > MandelScreen->Height) MainNWindow.Height = MandelScreen->Height - MainNWindow.TopEdge; if ( !MainWindow && !(MainWindow = OpenWindow(&MainNWindow)) ) { skipto abort; } SetMenuStrip(MainWindow, MandelMenu); if (borderless) { DoBorderless(MainWindow, &borderinfo); } InitPenTable(); return FALSE; abort: CleanupDisplay((bool) TRUE); return TRUE; } bool CleanupDisplay(everything) bool everything; { bool wasborderless; int i; StopDrawing(); StopFraming(); wasborderless = (MainWindow != NULL) && ((MainWindow->Flags & BORDERLESS) != 0); if (MainWindow) { /* Save window appearance for later, in low-res non-lace pixels */ MainNWindow.LeftEdge = MainWindow->LeftEdge; MainNWindow.TopEdge = MainWindow->TopEdge; MainNWindow.Width = MainWindow->Width; MainNWindow.Height = MainWindow->Height; ClearMenuStrip(MainWindow); /* Remove menu strip */ CloseWindow(MainWindow); /* Finally close it */ MainWindow = NULL; } /* Save the colors we may have established with great care */ if (MandelScreen) { for (i=0; i < NumColors; i++) { ColorMap[i] = GetRGB4(MandelScreen->ViewPort.ColorMap, i); } ColorMapValid = TRUE; if (MandelScreen->ViewPort.Modes & HIRES) { MainNWindow.LeftEdge >>= 1; MainNWindow.Width >>= 1; } if (MandelScreen->ViewPort.Modes & LACE) { MainNWindow.TopEdge >>= 1; MainNWindow.Height >>= 1; } /* Close the screen only if `everything' must be cleaned up */ if (everything) { CloseScreen(MandelScreen); MandelScreen = NULL; } } return wasborderless; } bool DoBorderless(window, borderinfo) struct Window *window; struct BorderInfo *borderinfo; { /* Make window borderless */ /* register struct Layer_Info *LayerInfo = &window->WScreen->LayerInfo; */ #define LayerInfo NULL /* Since V1.2 */ register struct Layer *Layer = window->RPort->Layer; register long movex; register long movey; register long sizex; register long sizey; bool Success = FALSE; if (window->Flags & BORDERLESS) return TRUE; LockLayer(LayerInfo, Layer); window->Flags |= BORDERLESS; movex = -window->BorderLeft; movey = -window->BorderTop; sizex = window->BorderRight - movex; sizey = window->BorderBottom - movey; window->BorderLeft = window->BorderTop = window->BorderRight = window->BorderBottom = 0; window->GZZWidth += sizex; window->GZZHeight += sizey; if ( MoveLayer(LayerInfo, Layer, movex, movey) ) { Success = SizeLayer(LayerInfo, Layer, sizex, sizey); if (!Success) { sizex = sizey = 0; } } else { movex = movey = sizex = sizey = 0; } UnlockLayer(Layer); borderinfo->MoveX = movex; borderinfo->MoveY = movey; borderinfo->SizeX = sizex; borderinfo->SizeY = sizey; /* Done making borderless */ if (Success) { return Success; } else { /* Try to clean up the mess */ UndoBorderless(window, borderinfo); return FALSE; } #undef LayerInfo } void UndoBorderless(window, borderinfo) struct Window *window; struct BorderInfo *borderinfo; { /* ``Another fine mess you got me into!'' (Oliver Hardy) */ /* register struct Layer_Info *LayerInfo = &window->WScreen->LayerInfo; */ #define LayerInfo NULL /* Since V1.2 */ register struct Layer *Layer = window->RPort->Layer; register long movex = borderinfo->MoveX; register long movey = borderinfo->MoveY; register long sizex = borderinfo->SizeX; register long sizey = borderinfo->SizeY; bool Success = FALSE; if (!(window->Flags & BORDERLESS)) return; LockLayer(LayerInfo, Layer); SizeLayer(LayerInfo, Layer, -sizex, -sizey); MoveLayer(LayerInfo, Layer, -movex, -movey); window->GZZWidth -= sizex; window->GZZHeight -= sizey; window->BorderLeft = -movex; window->BorderTop = -movey; window->BorderRight = sizex + movex; window->BorderBottom = sizey + movey; window->Flags &= ~BORDERLESS; RefreshWindowFrame(window); UnlockLayer(Layer); /* Done Undoing Borderless */ #undef LayerInfo } void MyExit(status) char *status; { #ifndef DEBUG2 static char message[] = "\ \0\144\25Mandelbrot Construction Set -- By KosmoSoft Productions\0a\ \0\144\41 \0"; /* 3^5^ 10^ ^ 20^ ^ 30^ ^ 40^ ^ 50^ 55^58^ */ register char *c=message+65; if (status) { /* Center the message. Notice `60' is even. */ /* We assume WORD alignment for the string. */ *((WORD *) (message+60)) = 320 - (strlen(status) << 2); while ((*(c++) = *(status++)) && c < message + 127); *c = 0; /* Let's be paranoid for a change... */ if (!IntuitionBase) IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0L); if (IntuitionBase) DisplayAlert(RECOVERY_ALERT, message, 50L); else { /* AT_Recovery | AG_OpenLib | AO_Intuition */ CPTR AlertParameter = (CPTR) FindTask(NULL); Alert(0x00038004L, &AlertParameter); } status=1; } #else if (status) { fprintf(stderr, "Mandelbrot Construction Set Error:\n %s\n", status); status = 1; } #endif CleanupDisplay((bool) TRUE); if (IntuitionBase) CloseLibrary(IntuitionBase); if (LayersBase) CloseLibrary(LayersBase); if (GfxBase) CloseLibrary(GfxBase); exit ((int) (status != NULL)); } bool Sure() { bool Result; ULONG OldIDCMP = MainWindow->IDCMPFlags; static struct IntuiText Body[] = { { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 25, 10, NULL, (UBYTE *) "You are going to", &Body[1] }, { MYFRONTPEN+1, AUTOBACKPEN, AUTODRAWMODE, 57, 25, &Topaz60, (UBYTE *) "destroy", &Body[2] }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 33, 40, NULL, (UBYTE *) "your picture !", NULL } }; if (Saved) return TRUE; ModifyIDCMP(MainWindow, OldIDCMP &~ (MENUVERIFY | SIZEVERIFY | REQVERIFY)); Result = AutoRequest(MainWindow, &Body[0], &PositiveText, &NegativeText, NULL, NULL, 200L, 90L); ModifyIDCMP(MainWindow, OldIDCMP); return Result; } /*********************************************************************** * Render a requester in a window. If it won't fit, open a new window. * This new window will share the IDCMP port with the original * window. This is to save memory, signal bits and VERIFY deadlocks. * Returns the window in which the requester actually appears. */ struct Window *MyRequest(request, window) struct Requester *request; struct Window *window; { static struct NewWindow newwindow = { 0, 0, 0, 0, 2, 1, NULL, /* IDCMP flags -- port shared with main window */ WINDOWDEPTH | WINDOWDRAG | ACTIVATE | SIMPLE_REFRESH | NOCAREREFRESH, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL }; int width, height, left, top; int borderleft, borderright, bordertop, borderbottom; struct Window *oldwindow = window; borderleft = window->WScreen->WBorLeft; borderright = window->WScreen->WBorRight; bordertop = window->WScreen->BarHeight + 1; borderbottom = window->WScreen->WBorBottom; /* Center the requester in the given window. * If impossible, open a new window to the place the requester in. */ width = window->Width - borderleft - borderright; height = window->Height - bordertop - borderbottom; left = ((width - request->Width) >> 1) + borderleft; top = ((height - request->Height) >> 1) + bordertop; if (width < request->Width || height < request-> Height) { /* Window too small. Open a new one */ newwindow.Width = request->Width + 2 * borderleft; newwindow.Height = request->Height + bordertop + borderbottom; newwindow.LeftEdge = newwindow.TopEdge = 0; newwindow.Title = window->Title; newwindow.Screen = window->WScreen; newwindow.Type = window->WScreen->Flags & SCREENTYPE; if (window = OpenWindow(&newwindow)) { window->UserPort = oldwindow->UserPort; /* Upen up the other port */ ModifyIDCMP(window, GADGETUP); } request->LeftEdge = borderleft; request->TopEdge = bordertop; } else { /* The requester fits. Center it! */ request->LeftEdge = left; request->TopEdge = top; } if (window && Request(request, window)) return window; if (window) CloseWindowSafely(window); return NULL; } void EndMyRequest(request, window, original) struct Requester *request; struct Window *window, *original; { EndRequest(request, window); if (window != original) CloseWindowSafely(window); } /************************************************************************* * Wait on a request posted by MyRequest. * Returns when a gadget with GadgetID >= POSGADGETID is released, * so Gadgets with an ID < POSGADGETID will be ignored. * Any messages other than GADGETUP will be ignored. */ int WaitMyRequest(window) struct Window *window; { int ID = 0; struct IntuiMessage *message; struct Gadget *Gadget; ULONG Class; ULONG OldIDCMP = window->IDCMPFlags; if (!window) return NEGGADGETID; ModifyIDCMP(window, GADGETUP); while (ID < POSGADGETID) { WaitPort(window->UserPort); while (message = (struct IntuiMessage *) GetMsg(window->UserPort) ) { Class = message->Class; Gadget = (struct Gadget *)message->IAddress; ReplyMsg(message); if (Class != GADGETUP) continue; ID = Gadget->GadgetID; if (ID >= POSGADGETID) break; /* Also gets out of outer loop */ } } ModifyIDCMP(window, OldIDCMP); return ID; } void RectDraw(rp, x1, y1, x2, y2) struct RastPort *rp; SHORT x1, y1, x2,y2; { Move(rp, (long) x1, (long) y1); Draw(rp, (long) x2, (long) y1); Draw(rp, (long) x2, (long) y2); Draw(rp, (long) x1, (long) y2); if (y2 > y1) y1++; else y1--; /* Don't XOR the first pixel twice */ Draw(rp, (long) x1, (long) y1); } void CrossDraw(rp, x, y, left, right, top, bottom) struct RastPort *rp; SHORT x, y, top, bottom, left, right; { Move(rp, (long) left, (long) y); Draw(rp, (long) right, (long) y); Move(rp, (long) x, (long) top); Draw(rp, (long) x, (long) bottom); } void DisableSystemGadgets(gadget) struct Gadget *gadget; { while (gadget) { if (gadget->GadgetType & SYSGADGET) { /* Ghost everything except the Title/Dragbar */ if ((gadget->GadgetType & 0x00F0) != WDRAGGING) OffGadget(gadget, MainWindow, NULL); gadget->Flags |= GADGDISABLED; } gadget = gadget->NextGadget; } } void EnableSystemGadgets(gadget) struct Gadget *gadget; { USHORT Flags = 0; while (gadget) { if (gadget->GadgetType & SYSGADGET) { Flags |= gadget->Flags; gadget->Flags &= ~GADGDISABLED; } gadget = gadget->NextGadget; } /* Unghost everthing if necessary */ if (Flags & GADGDISABLED) RefreshWindowFrame(MainWindow); } void StopFraming() { if (MainWindow) { EnableSystemGadgets(MainWindow->FirstGadget); ModifyIDCMP(MainWindow, MainWindow->IDCMPFlags & ~INTUITICKS); } MouseStatus = NOTFRAMING; } void CheckMouse(Class, Code, MouseX, MouseY, Secs, Micros) ULONG Class; USHORT Code; SHORT MouseX, MouseY; ULONG Secs, Micros; { register SHORT top = MainWindow->BorderTop, bottom = MainWindow->Height - MainWindow->BorderBottom - 1, left = MainWindow->BorderLeft, right = MainWindow->Width - MainWindow->BorderRight - 1; static ULONG OldSecs, OldMicros; static SHORT MidX, MidY; if (StillDrawing || MouseStatus != FLASHING && (MouseX < left || MouseX > right || MouseY < top || MouseY > bottom)) return; MouseX -= left; MouseY -= top; if (Class == MOUSEBUTTONS) { if (Code == SELECTDOWN) { /* We selected a point */ switch (MouseStatus) { case NOTFRAMING: case FLASHING: MouseStatus = NOPOINT; DisableSystemGadgets(MainWindow->FirstGadget); ModifyIDCMP(MainWindow, MainWindow->IDCMPFlags | INTUITICKS); /* Now we can select our first corner */ break; case NOPOINT: FrameX1 = FrameX2 = MouseX; FrameY1 = FrameY2 = MouseY; MouseStatus = POINT1; OldMicros = Micros; OldSecs = Secs; /* We have the first point. Now go for the second */ break; case POINT1: if (DoubleClick(OldSecs, OldMicros, Secs, Micros)) { /* Did we double-click? Then we have selected a center */ MouseStatus = CENTERFRAMING; MidX = FrameX1; MidY = FrameY1; break; } FrameX2 = MouseX; FrameY2 = MouseY; /* Fall through to CENTERFRAMING */ case CENTERFRAMING: if (FrameX1 == FrameX2 || FrameY1 == FrameY2) break; EnableSystemGadgets(MainWindow->FirstGadget); MouseStatus = FLASHING; /* Point 1 should be upper left */ if (FrameX2 < FrameX1) { /* I DO know I am reusing a variable here. Sorry! */ left=FrameX2; FrameX2=FrameX1; FrameX1=left; } if (FrameY2 < FrameY1) { left=FrameY2; FrameY2=FrameY1; FrameY1=left; } break; } /* End switch MouseStatus */ } /* End if Code == SELECTDOWN */ return; } /* End if Class == MOUSEBUTTONS */ /* We are moving the mouse. Show something! */ SetDrMd(MainWindow->RPort, (ULONG) COMPLEMENT); switch (MouseStatus) { /* case NOTFRAMING: */ /* return; */ case NOPOINT: FrameX1 = FrameX2 = MouseX; FrameY1 = FrameY2 = MouseY; /* WaitBOVP(&MandelScreen->ViewPort); */ WaitTOF(); CrossDraw(MainWindow->RPort, FrameX1, FrameY1, 0, MainWindow->GZZWidth-1, 0, MainWindow->GZZHeight-1); /* WaitBOVP(&MandelScreen->ViewPort); */ WaitTOF(); CrossDraw(MainWindow->RPort, FrameX1, FrameY1, 0, MainWindow->GZZWidth-1, 0, MainWindow->GZZHeight-1); break; case CENTERFRAMING: FrameX1 = MouseX; FrameY1 = MouseY; FrameX2 = 2*MidX - FrameX1; FrameY2 = 2*MidY - FrameY1; skipto flashing; case POINT1: FrameX2 = MouseX; FrameY2 = MouseY; /* Deliberate Fall-Through to FLASHING */ case FLASHING: flashing: /* WaitBOVP(&MandelScreen->ViewPort); */ WaitTOF(); RectDraw(MainWindow->RPort, FrameX1, FrameY1, FrameX2, FrameY2); /* WaitBOVP(&MandelScreen->ViewPort); */ WaitTOF(); RectDraw(MainWindow->RPort, FrameX1, FrameY1, FrameX2, FrameY2); } } void InitPenTable() { register int i; switch (PenTableMode) { case MODULO: PenTable[0] = 0; for (i=1; iFlags |= CHECKED; else Item->Flags &= ~CHECKED; SetMenuStrip(MainWindow, MandelMenu); } void MakeMAND(mand) struct Mand *mand; { int i; mand->MandID = MAND; mand->Size = sizeof(struct Mand); mand->MaxDepth = MaxDepth; mand->RangeWidth = RangeWidth; mand->RainDist = RainbowDistance; mand->RainRMax = RainbowRMax; mand->RainGMax = RainbowGMax; mand->RainBMax = RainbowBMax; for (i=0; i < sizeof(mand->Coords); i++) mand->Coords[i] = '\0'; sprintf(&mand->Coords[0], "%1.10g %1.10g %1.10g %1.10g", LeftEdge, RightEdge, TopEdge, BottomEdge); } bool InterpretMAND(mand) struct Mand *mand; { double NewLeftEdge, NewRightEdge, NewTopEdge, NewBottomEdge; /* Perform some checks on correctness of the chunk */ if (mand->MandID != MAND || mand->Size > sizeof(struct Mand) || mand->MaxDepth > MAXDEPTH || mand->RangeWidth > MAXDEPTH) return FALSE; if (sscanf(&mand->Coords[0], "%lf %lf %lf %lf", &NewLeftEdge, &NewRightEdge, &NewTopEdge, &NewBottomEdge) < 4) return FALSE; MaxDepth = mand->MaxDepth; RangeWidth = mand->RangeWidth; LeftEdge = NewLeftEdge; RightEdge = NewRightEdge; TopEdge = NewTopEdge; BottomEdge = NewBottomEdge; CalcCSteps(); RainbowDistance = mand->RainDist; RainbowRMax = mand->RainRMax; RainbowGMax = mand->RainGMax; RainbowBMax = mand->RainBMax; return TRUE; } void CalcCSteps() { CXStep = (double) (RightEdge - LeftEdge) / ( MainWindow->GZZWidth - 1); CYStep = (double) (TopEdge - BottomEdge) / ( MainWindow->GZZHeight - 1); }