#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 * * MenuPick and some related things */ #include #ifndef EXEC_SEMAPHORES_H #include #endif #include #ifdef DEBUG # include # undef STATIC # define STATIC /* EMPTY */ #endif #include "mandel.h" STATIC TEXT FileName[FNAME_SIZE+1] = "Mandel.pic"; STATIC TEXT DirName[DNAME_SIZE+2] = "df0:"; STATIC UBYTE Buffer[5][20]; /* Forward declarations of static procedures */ void PrjNew(); void GotMenu(Code) USHORT Code; { static void (*MenuFunc[])()= { CprMenu, PrjMenu, OptMenu, FunMenu }; while (Code != MENUNULL) { (*MenuFunc[MENUNUM(Code)]) (Code); Code = ItemAddress(MandelMenu, (long) Code) -> NextSelect; /* This tends to make endless loops possible ... */ } } void CprMenu(Code) USHORT Code; { ULONG OldIDCMP = MainWindow->IDCMPFlags; static struct IntuiText Body[] = { { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 15, NULL, (UBYTE *)"Mandelbrot Construction Set", &Body[1] }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 30, NULL, (UBYTE *)"By KosmoSoft Productions", &Body[2] }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 40, NULL, (UBYTE *)"15 September 1987 V1.0", &Body[3] }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 55, NULL, (UBYTE *)"Ohh, please Copy-Me!", NULL } }, ExitText = { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE, NULL, (UBYTE *)" OK ", NULL }; ModifyIDCMP(MainWindow, OldIDCMP &~ (MENUVERIFY | SIZEVERIFY | REQVERIFY)); AutoRequest(MainWindow, &Body[0], NULL, &ExitText, NULL, NULL, 258L, 100L); ModifyIDCMP(MainWindow, OldIDCMP); } STATIC void PrjMenu(Code) USHORT Code; { int SubNum = SUBNUM(Code); int ItemNum = ITEMNUM(Code); struct Mand MandChunk; struct BitMap *bitmap; struct ILBM_info *ilbminfo; unsigned char ea_colormap[3*MAXCOL]; char Name[DNAME_SIZE + FNAME_SIZE + 3]; switch (ItemNum) { case PRJNEW: PrjNew(SubNum); break; case PRJOPN: if ( get_fname(MainWindow, "Select a filename to LOAD", FileName, DirName) == NULL ) break; strcpy(Name, DirName); if (Name[strlen(Name) - 1] != ':') strcat(Name, "/"); strcat(Name, FileName); StopDrawing(); MandChunk.MandID = 0; if (ilbminfo = read_iff(Name, (short)FALSE, sizeof(MandChunk), &MandChunk)) { put_ea_cmap(&ilbminfo->cmap, NumColors, MandelScreen); InterpretMAND(&MandChunk); } Saved = TRUE; break; case PRJSVE: /* Save */ if (NameValid) skipto prjsve; /* Fall Through */ case PRJSVA: /* Save As */ if ( get_fname(MainWindow, "Select a filename to SAVE", FileName, DirName) == NULL ) break; prjsve: strcpy(Name, DirName); if (Name[strlen(Name) - 1] != ':') strcat(Name, "/"); strcat(Name, FileName); get_ea_cmap(ea_colormap, NumColors, MandelScreen); MakeMAND(&MandChunk); bitmap = MainWindow->RPort->BitMap; /*** Warning: This MoveWindow will not happen immediately!!! ***/ /*** For some reason, this will deadlock Intuition, if I ***/ /*** uncomment both MoveWindow and DoBorderless. It seems to ***/ /*** collide with the closing filename requester window... ***/ /*** Maybe because the locking of the layers interfere buggyly? ***/ /*** Anyhow, if I LockLayers(), then the GZZ border doesn't ***/ /*** get updated until I UnlockLayers(), and the mouse ***/ /*** pointer is frozen! But we have to suspend the drawing ***/ /*** task somehow, to prevent creating a corrupt IFF file. ***/ /*** Who said `Very near to betting that it can't be ***/ /*** deadlocked' ?? [allchanges file: intuition 290] ***/ /* MoveWindow(MainWindow, (long)-MainWindow->LeftEdge, (long)-MainWindow->TopEdge); */ /* DoBorderless(MainWindow); */ SuspendDrawing(); NameValid = Saved = write_iff(Name, ea_colormap, bitmap, (short) 0, (short) 0, (short) bitmap->BytesPerRow * 8, (short) TRUE, sizeof(MandChunk), &MandChunk); ResumeDrawing(); break; case PRJQUI: if (StillDrawing) StopDrawing(); else finished = TRUE; } } STATIC void OptMenu(Code) USHORT Code; { int SubNum = SUBNUM(Code); int ItemNum = ITEMNUM(Code); switch (ItemNum) { case OPTCOL: switch (SubNum) { case OCSEL: SelectMenu(MENU(OPTMENU, OPTCOL, OCSEL), (bool)FALSE); UnImpl(); break; case OCMOD: PenTableMode = MODULO; break; case OCRAN: PenTableMode = RANGES; break; case OCPAL: Palette(MainWindow); } /* End Switch SUBNUM */ InitPenTable(); break; case OPTRES: switch (SubNum) { case ORNRM: PixelStep = 1; break; case OR12: PixelStep = 2; break; case OR13: PixelStep = 3; break; case OR14: PixelStep = 4; break; case ORFIL: DrawPicture((bool)TRUE); break; /* Fill in */ case ORHI: case ORILC: if (!Sure()) break; { USHORT newmode = MandelNScreen.ViewModes & ~(HIRES | LACE); bool WasBorderless; if (ItemAddress(MandelMenu, MENU(OPTMENU, OPTRES, ORHI)) -> Flags & CHECKED) newmode |= HIRES; if (ItemAddress(MandelMenu, MENU(OPTMENU, OPTRES, ORILC)) -> Flags & CHECKED) newmode |= LACE; if (newmode != MandelNScreen.ViewModes) { WasBorderless = CleanupDisplay((bool) TRUE); MandelNScreen.ViewModes = newmode; if (InitDisplay(WasBorderless)) { /* Trouble */ MandelNScreen.ViewModes &= ~(HIRES | LACE); if (InitDisplay((bool) FALSE)) MyExit("Can't re-init display - Maybe low on memory"); SelectMenu(MENU(OPTMENU, OPTRES, ORHI), (bool)FALSE); SelectMenu(MENU(OPTMENU, OPTRES, ORILC), (bool)FALSE); SelectMenu(MENU(OPTMENU, OPTRES, ORBCK), (bool)FALSE); } } } break; case ORBCK: if (ItemAddress(MandelMenu, MENU(OPTMENU,OPTRES,ORBCK))->Flags & CHECKED) DoBorderless(MainWindow, &borderinfo); else UndoBorderless(MainWindow, &borderinfo); } /* End Switch SUBNUM */ break; case OPTPAR: Parameters(); break; } /* End Switch ITEMNUM */ } void FunMenu(Code) USHORT Code; { switch (ITEMNUM(Code)) { case FUN1: WritePixelDepth = ZQuadMinC; break; case FUN2: WritePixelDepth = ZC1MinZ; break; case FUN3: WritePixelDepth = Z3PlusZCMin1MinC; break; } } void UnImpl() { static char alert[] = "\ \0\144\25Mandelbrot Construction Set -- By KosmoSoft Productions\0a\ \0\170\40Sorry, this function has not been implemented yet!\0"; DisplayAlert(RECOVERY_ALERT, alert, 50L); } STATIC USHORT OldMinWidth, OldMinHeight, OldMaxWidth, OldMaxHeight; /* Do not nest calls to DisableSizing: the original values will be lost. */ STATIC void DisableSizing() { OldMinWidth = MainWindow->MinWidth; OldMaxWidth = MainWindow->MaxWidth; OldMinHeight = MainWindow->MinHeight; OldMaxHeight = MainWindow->MaxHeight; WindowLimits(MainWindow, (long) MainWindow->Width, (long) MainWindow->Height, (long) MainWindow->Width, (long) MainWindow->Height); } STATIC void EnableSizing() { WindowLimits(MainWindow, (long) OldMinWidth, (long) OldMinHeight, (long) OldMaxWidth, (long) OldMaxHeight); } /* Complex multiplication using pointers to reduce overhead. */ /* YOU must make sure there are no (dynamic) aliases around... */ STATIC void MulCplx(ReRes, ImRes, ReA, ImA, ReB, ImB) double *ReRes, *ImRes, *ReA, *ImA, *ReB, *ImB; { *ReRes = *ReA * *ReB - *ImA * *ImB; *ImRes = *ImA * *ReB + *ReA * *ImB; } /* Z^2-C: 4 multiplications per loop */ void ZQuadMinC(x, y, ReC, ImC) long x, y; double ReC, ImC; { double ReZ = 0.0, ImZ = 0.0; double ReQuad, ImQuad; int Depth = -1; while (ImQuad=ImZ*ImZ, ReQuad=ReZ*ReZ, Depth++, (ImQuad + ReQuad < 8) && (Depth <= MaxDepth) ) { ImZ = 2 * ImZ * ReZ - ImC; ReZ = ReQuad - ImQuad - ReC; } if (Depth > MaxDepth) Depth = PenTable[0]; else Depth = PenTable[Depth]; SetAPen(MainWindow->RPort, (long) Depth); WritePixel(MainWindow->RPort, x, y); } /* Z*C*(1-Z): 10 multiplications per loop */ void ZC1MinZ(x, y, ReC, ImC) long x, y; double ReC, ImC; { static double ReZ, ImZ; static double NewReZ, NewImZ; static double Re1MinZ, Im1MinZ; int Depth = -1; ReZ = ReC; ImZ = ImC; while (Depth++, (ImZ*ImZ + ReZ*ReZ < 8) && (Depth <= MaxDepth) ) { Re1MinZ = 1 - ReZ; Im1MinZ = -ImZ; MulCplx(&NewReZ, &NewImZ, &ReZ, &ImZ, &ReC, &ImC); MulCplx(&ReZ, &ImZ, &NewReZ, &NewImZ, &Re1MinZ, &Im1MinZ); } if (Depth > MaxDepth) Depth = PenTable[0]; else Depth = PenTable[Depth]; SetAPen(MainWindow->RPort, (long) Depth); WritePixel(MainWindow->RPort, x, y); } /* Z^3+Z*(C-1)-C: 12 multiplications per loop */ void Z3PlusZCMin1MinC(x, y, ReC, ImC) long x, y; double ReC, ImC; { static double ReZ, ImZ; static double ReCMin1; static double ReZ2, ImZ2, ReZ3, ImZ3; double ReQuad, ImQuad; int Depth = -1; ReZ = ReC; ImZ = ImC; while (ImQuad=ImZ*ImZ, ReQuad=ReZ*ReZ, Depth++, (ImQuad + ReQuad < 8) && (Depth <= MaxDepth) ) { /* Calculate z^2 */ ReZ2 = ReQuad - ImQuad; ImZ2 = 2 * ReZ * ImZ; /* Make z^3 */ MulCplx(&ReZ3, &ImZ3, &ReZ2, &ImZ2, &ReZ, &ImZ); /* Calculate z(c-1) while destroying z^2 */ ReCMin1 = ReC - 1; MulCplx(&ReZ2, &ImZ2, &ReZ, &ImZ, &ReCMin1, &ImC); /* Add everything */ ReZ = ReZ3 + ReZ2 - ReC; ImZ = ImZ3 + ImZ2 - ImC; } if (Depth > MaxDepth) Depth = PenTable[0]; else Depth = PenTable[Depth]; SetAPen(MainWindow->RPort, (long) Depth); WritePixel(MainWindow->RPort, x, y); } /* Some *VERY PRIVATE* variables */ STATIC struct Task *DrawTask = NULL; STATIC struct Task *MandelTask = NULL; STATIC struct SignalSemaphore DrawSemaphore; /* This is what it is all about! */ STATIC bool MyFillIn; /* Parameter for new task */ STATIC void ActuallyDrawPicture() { static double x, y, Leftx, MyXstep, MyYstep; static long px, py, Leftpx, minpx, maxpx, minpy, maxpy; static int MyPixelStep, XOffset, YOffset; register void (*Function)(); geta4(); /* Manx small memory model */ ObtainSemaphore(&DrawSemaphore); StillDrawing = TRUE; DisableSizing(); StopFraming(); OffMenu(MainWindow, (ULONG) SHIFTMENU(PRJMENU) | SHIFTITEM(PRJNEW) | SHIFTSUB(NOSUB) ); OffMenu(MainWindow, (ULONG) SHIFTMENU(OPTMENU) | SHIFTITEM(OPTRES) | SHIFTSUB(ORFIL) ); if (!MyFillIn && !Sure()) skipto exit; if (!MyFillIn) NameValid = FALSE; Saved = FALSE; MyPixelStep = PixelStep; XOffset = 0; YOffset = MyFillIn? 1: 0; minpx = 0; maxpx = MainWindow->GZZWidth - 1; minpy = 0; maxpy = MainWindow->GZZHeight - 1; CalcCSteps(); if (!MyFillIn) { /* Clear the window */ SetAPen(MainWindow->RPort, (long) PenTable[0]); SetDrMd(MainWindow->RPort, (long) JAM1); RectFill(MainWindow->RPort, minpx, minpy, maxpx, maxpy); } MyXstep = MyPixelStep * CXStep; MyYstep = MyPixelStep * CYStep; Function = WritePixelDepth; ReleaseSemaphore(&DrawSemaphore); again: Leftpx = minpx + XOffset; /* Start in the upper left-hand corner */ py = minpy + YOffset; /* of the window */ Leftx = LeftEdge + XOffset * CXStep; y = TopEdge - YOffset * CYStep; for ( ; py <= maxpy; y -= MyYstep, py += MyPixelStep) { ObtainSemaphore(&DrawSemaphore); SetDrMd(MainWindow->RPort, (long) JAM1); for (px=Leftpx, x=Leftx ; px <= maxpx; x += MyXstep, px += MyPixelStep) { (*Function)(px, py, x, y); /* Check if we are asked to terminate. Don't release s'phore. */ if (StillDrawing < 0) skipto exit; } ReleaseSemaphore(&DrawSemaphore); } if (MyFillIn && (++YOffset < MyPixelStep) ) { backto again; /* Draw pixels below current pixel */ } if (MyFillIn && (++XOffset < MyPixelStep) ) { YOffset = 0; /* and next to them */ backto again; } exit: DisplayBeep(MandelScreen); ObtainSemaphore(&DrawSemaphore); EnableSizing(); OnMenu(MainWindow, (ULONG) SHIFTMENU(PRJMENU) | SHIFTITEM(PRJNEW) | SHIFTSUB(NOSUB) ); OnMenu(MainWindow, (ULONG) SHIFTMENU(OPTMENU) | SHIFTITEM(OPTRES) | SHIFTSUB(ORFIL) ); DrawTask = NULL; if (StillDrawing < 0) { /* Release the semaphore now. The main task waits for it. */ ReleaseSemaphore(&DrawSemaphore); } StillDrawing = FALSE; /* We are finished, finally... */ ReleaseSemaphore(&DrawSemaphore); DisplayBeep(MandelScreen); } void DrawPicture(FillIn) bool FillIn; { BYTE Priority; MandelTask = FindTask(NULL); Priority = MandelTask->tc_Node.ln_Pri; MyFillIn = FillIn; InitSemaphore(&DrawSemaphore); DrawTask = CreateTask("Mandelbrot_Drawing.task", (long) Priority, ActuallyDrawPicture, 2048L); } /* Interface because I wanted to CreateTask the drawing... */ void StopDrawing() { if (StillDrawing) { StillDrawing = -1; /* Indicate termination is wanted. */ /* In worst-case I think we will make the loop at most twice. */ /* This is only when the drawing task has not obtained it, */ /* which is only for very little of the time. */ do { ObtainSemaphore(&DrawSemaphore); ReleaseSemaphore(&DrawSemaphore); } while (StillDrawing < 0); } } /* This is the external interface to the DrawSemaphore. Use it with care. */ /* Always balance calls to SuspendDrawing() with ResumeDrawing() !!! */ void SuspendDrawing() { ObtainSemaphore(&DrawSemaphore); } void ResumeDrawing() { ReleaseSemaphore(&DrawSemaphore); } STATIC void PrjNew(SubNum) USHORT SubNum; { struct Window *window; int ID; static double HShift = 0.0, VShift = 0.0; double Width = RightEdge - LeftEdge, Height = BottomEdge - TopEdge, NewLeftEdge = LeftEdge, NewTopEdge = TopEdge, NewRightEdge = RightEdge, NewBottomEdge = BottomEdge; /* Stuff for the ABSOLUTE requester */ static struct IntuiText RatioText = { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 90, NULL, (UBYTE *) "Ratio: ", NULL }; static struct IntuiText AbsText = { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL, (UBYTE *) "Select an absolute position", &RatioText }; static struct IntuiText LRTBText[] = { { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL, (UBYTE *) "Left", NULL }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL, (UBYTE *) "Right", NULL }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL, (UBYTE *) "Top", NULL }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL, (UBYTE *) "Bottom", NULL } }; static struct StringInfo LRTBinfo[] = { { &Buffer[0][0], &Buffer[4][0], 0, 20, 0 }, { &Buffer[1][0], &Buffer[4][0], 0, 20, 0 }, { &Buffer[2][0], &Buffer[4][0], 0, 20, 0 }, { &Buffer[3][0], &Buffer[4][0], 0, 20, 0 } }; static struct Gadget LRTBGadget[] = { { &LRTBGadget[1], 66, 30, 160, 10, /* next, LTWH */ GADGHCOMP, /* Flags */ RELVERIFY, /* Activation */ STRGADGET | REQGADGET, /* GadgetType */ (APTR) NULL, NULL, /* rendering */ &LRTBText[0], 0, (APTR) &LRTBinfo[0], /* "Left" */ NEGGADGETID+1, NULL }, { &LRTBGadget[2], 66, 45, 160, 10, /* next, LTWH */ GADGHCOMP, RELVERIFY, STRGADGET | REQGADGET, (APTR) NULL, NULL, &LRTBText[1], 0, (APTR) &LRTBinfo[1], /* Right */ NEGGADGETID+1, NULL }, { &LRTBGadget[3], 66, 60, 160, 10, /* next, LTWH */ GADGHCOMP, RELVERIFY, STRGADGET | REQGADGET, (APTR) NULL, NULL, &LRTBText[2], 0, (APTR) &LRTBinfo[2], /* Top */ NEGGADGETID+1, NULL }, { NULL, 66, 75, 160, 10, /* next, LTWH */ GADGHCOMP, RELVERIFY, STRGADGET | REQGADGET, (APTR) NULL, NULL, &LRTBText[3], 0, (APTR) &LRTBinfo[3], /* Bottom */ NEGGADGETID+1, NULL } }; static struct Requester AbsRequest = { NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL, &AbsText, 0, 1 }; /* Stuff for the SHIFT requester */ static struct IntuiText ShiftText = { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL, (UBYTE *) "Select a window shift amount", NULL }; static struct IntuiText RDText[] = { { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL, (UBYTE *) "Right", NULL }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL, (UBYTE *) "Down", NULL } }; static struct Gadget RDGadget[] = { { &RDGadget[1], 66, 45, 160, 10, /* next, LTWH */ GADGHCOMP, 0, STRGADGET | REQGADGET, (APTR) NULL, NULL, &RDText[0], 0, (APTR) &LRTBinfo[0], /* Right */ 0, NULL }, { NULL, 66, 60, 160, 10, /* next, LTWH */ GADGHCOMP, 0, STRGADGET | REQGADGET, (APTR) NULL, NULL, &RDText[1], 0, (APTR) &LRTBinfo[1], /* Down */ 0, NULL } }; static struct Requester ShiftRequest = { NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL, &ShiftText, 0, 1 }; switch (SubNum) { case PNRED: if (MouseStatus != FLASHING) return; else { register SHORT w = MainWindow -> GZZWidth, h = MainWindow -> GZZHeight; register SHORT X1, Y1, X2, Y2; /* If you cast less, Aztec seems to do it wrong... */ X1 = (-(long)FrameX1 * w) / ((long)FrameX2 - (long)FrameX1); Y1 = (-(long)FrameY1 * h) / ((long)FrameY2 - (long)FrameY1); X2 = ((long)(w-1-FrameX1) * w) / ((long)FrameX2 - (long)FrameX1) - 1; Y2 = ((long)(h-1-FrameY1) * h) / ((long)FrameY2 - (long)FrameY1) - 1; #ifdef DEBUG2 fprintf(stderr,"REDUCE: w=%d h=%d X1=%d Y1=%d X2=%d Y2=%d\n", w, h, X1, Y1, X2, Y2); fprintf(stderr," FrameX1=%d FrameY1=%d FrameX2=%d FrameY2=%d\n", FrameX1, FrameY1, FrameX2, FrameY2); #endif NewLeftEdge = LeftEdge + X1 * CXStep; NewRightEdge = LeftEdge + X2 * CXStep; NewTopEdge = TopEdge - Y1 * CYStep; NewBottomEdge = TopEdge - Y2 * CYStep; skipto pnabs; } case PNENL: if (MouseStatus != FLASHING) return; NewLeftEdge = LeftEdge + FrameX1 * CXStep; NewRightEdge = LeftEdge + FrameX2 * CXStep; NewTopEdge = TopEdge - FrameY1 * CYStep; NewBottomEdge = TopEdge - FrameY2 * CYStep; skipto pnabs; case PNSHF: NegativeGadget.NextGadget = &RDGadget[0]; do { sprintf(Buffer[0], "%1.6g",HShift); sprintf(Buffer[1], "%1.6g",VShift); window = MyRequest(&ShiftRequest, MainWindow); ID = WaitMyRequest(window); EndMyRequest(&ShiftRequest, window, MainWindow); if (ID == NEGGADGETID) return; } while (sscanf(Buffer[0], "%lf", &HShift)+ sscanf(Buffer[1], "%lf", &VShift) != 2); NewLeftEdge = LeftEdge + HShift * Width; NewRightEdge = RightEdge + HShift * Width; NewTopEdge = TopEdge + VShift * Height; NewBottomEdge = BottomEdge + VShift * Height; skipto pnabs; case PNABS: NewLeftEdge = LeftEdge; NewRightEdge = RightEdge; NewTopEdge = TopEdge; NewBottomEdge = BottomEdge; pnabs: NegativeGadget.NextGadget = &LRTBGadget[0]; sprintf(Buffer[0], "%1.10g", NewLeftEdge); sprintf(Buffer[1], "%1.10g", NewRightEdge); sprintf(Buffer[2], "%1.10g", NewTopEdge); sprintf(Buffer[3], "%1.10g", NewBottomEdge); sprintf(RatioText.IText+7, "%1.4f ", Ratio(NewLeftEdge, NewRightEdge, NewTopEdge, NewBottomEdge, MainWindow)); do { window = MyRequest(&AbsRequest, MainWindow); while ( (ID = WaitMyRequest(window) ) > NEGGADGETID) { sscanf(Buffer[0], "%lf", &NewLeftEdge); sscanf(Buffer[1], "%lf", &NewRightEdge); sscanf(Buffer[2], "%lf", &NewTopEdge); sscanf(Buffer[3], "%lf", &NewBottomEdge); sprintf(RatioText.IText+7, "%1.4f ", Ratio(NewLeftEdge, NewRightEdge, NewTopEdge, NewBottomEdge, MainWindow)); PrintIText(AbsRequest.ReqLayer->rp, &RatioText, 0L, 0L); } EndMyRequest(&AbsRequest, window, MainWindow); } while (sscanf(Buffer[0], "%lf", &NewLeftEdge)+ sscanf(Buffer[1], "%lf", &NewRightEdge)+ sscanf(Buffer[2], "%lf", &NewTopEdge)+ sscanf(Buffer[3], "%lf", &NewBottomEdge) < 4); if (ID != POSGADGETID) return; LeftEdge = NewLeftEdge; RightEdge = NewRightEdge; TopEdge = NewTopEdge; BottomEdge = NewBottomEdge; StopFraming(); StopDrawing(); break; } DrawPicture((bool)FALSE); /* Don't fill in */ } float Ratio(l, r, t, b, window) double l, r, t, b; struct Window *window; { float PixelRatio; float ReImRatio; if (t == b) t = b+1; /* You never know... */ PixelRatio = (float) window->GZZWidth / window->GZZHeight; if (window->WScreen->ViewPort.Modes & HIRES) PixelRatio /= 2; if (window->WScreen->ViewPort.Modes & LACE) PixelRatio *= 2; ReImRatio = (r - l)/(t - b); return ReImRatio / PixelRatio; } void Parameters() { struct Window *window; int ID; int NewMaxDepth, NewRangeWidth; static struct IntuiText ParamText = { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL, (UBYTE *) "Select these parameters", NULL }; static struct IntuiText ParmText[] = { { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL, (UBYTE *) "Max depth", NULL }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL, (UBYTE *) "Range width", NULL }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL, (UBYTE *) "", NULL }, { MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL, (UBYTE *) "", NULL } }; static struct StringInfo Parminfo[] = { { &Buffer[0][0], &Buffer[4][0], 0, 20, 0 }, { &Buffer[1][0], &Buffer[4][0], 0, 20, 0 }, { &Buffer[2][0], &Buffer[4][0], 0, 20, 0 }, { &Buffer[3][0], &Buffer[4][0], 0, 20, 0 } }; static struct Gadget ParmGadget[] = { { &ParmGadget[1], 130, 30, 96, 10, /* next, LTWH */ GADGHCOMP, /* Flags */ RELVERIFY | LONGINT, /* Activation */ STRGADGET | REQGADGET, /* GadgetType */ (APTR) NULL, NULL, /* rendering */ &ParmText[0], 0, (APTR) &Parminfo[0], /* "MaxDepth" */ 0, NULL }, { &ParmGadget[2], 130, 45, 96, 10, /* next, LTWH */ GADGHCOMP, RELVERIFY | LONGINT, STRGADGET | REQGADGET, (APTR) NULL, NULL, &ParmText[1], 0, (APTR) &Parminfo[1], /* "RangeWidth" */ 0, NULL }, { &ParmGadget[3], 130, 60, 96, 10, /* next, LTWH */ GADGHCOMP, RELVERIFY, STRGADGET | REQGADGET, (APTR) NULL, NULL, &ParmText[2], 0, (APTR) &Parminfo[2], /* */ 0, NULL }, { NULL, 130, 75, 96, 10, /* next, LTWH */ GADGHCOMP, RELVERIFY, STRGADGET | REQGADGET, (APTR) NULL, NULL, &ParmText[3], 0, (APTR) &Parminfo[3], /* */ 0, NULL } }; static struct Requester ParmRequest = { NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL, &ParamText, 0, 1 }; /* Stuff for the PARAMETERS requester */ NegativeGadget.NextGadget = &ParmGadget[0]; Parminfo[0].LongInt = MaxDepth; Parminfo[1].LongInt = RangeWidth; do { sprintf(Buffer[0], "%ld", Parminfo[0].LongInt); sprintf(Buffer[1], "%ld", Parminfo[1].LongInt); Buffer[2][0] = Buffer[3][0] = '\0'; window = MyRequest(&ParmRequest, MainWindow); ID = WaitMyRequest(window); EndMyRequest(&ParmRequest, window, MainWindow); if (ID == NEGGADGETID) return; NewMaxDepth = Parminfo[0].LongInt; NewRangeWidth = Parminfo[1].LongInt; } while ( NewMaxDepth < 0 || NewMaxDepth > MAXDEPTH || NewRangeWidth < 0 || NewRangeWidth > MAXDEPTH ); if (NewRangeWidth != RangeWidth) InitPenTable(); MaxDepth = NewMaxDepth; RangeWidth = NewRangeWidth; }