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