[comp.sources.amiga] v89i142: mandel - mandelobrot generator v180, Part01/04

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

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

This is Mandel, a flexible Mandelbrot generator. It was never designed
to be fast, just to play by the rules (with one exception that has
nothing to do with speed). Improvements over the version found on Fish
disk #111 include: * ARexx interface * Coordinates in sight * More
state info saved with picture * Batch files * Programmable functions,
allowing you to draw Julia sets and everything your imagination can
conceive (well, most of it, anyway) * More plotting options.

# 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:
#	Batch.c
#	Display.c
#	Draw.c
#	Dummy.c
#	GetFile.c
# This is archive 1 of a 4-part kit.
# This archive created: Wed May 17 20:45:11 1989
echo "extracting Batch.c"
sed 's/^X//' << \SHAR_EOF > Batch.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 * Batch processing department.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#include "mandel.h"
X
X#ifdef DEBUG
X#   undef STATIC
X#   define STATIC   /* EMPTY */
X#endif
X
X/*
X *  QUIT
X *  STOP
X *  WAIT
X *  FIXRAINBOW
X *  COLOR pen r g b
X *  DRAW
X *  FILLIN
X *  SHIFT hfraction vfraction
X *  SAVEAS filename
X *  OPEN filename
X *  FIXDISPLAY
X *  BATCH filename
X *  SELECT depth pen
X *  MODULO
X *  RANGES
X *  PROGRAM
X *  PRELUDE
X *  R
X *  C
X *  END
X *  REG 	regno value
X *  LEFTEDGE	rval
X *  RIGHTEDGE	rval
X *  TOPEDGE	ival
X *  BOTTOMEDGE	ival
X *  PIXELSTEP	value
X *  NUMCOLORS	value
X *  MAXDEPTH	value
X *  RANGEWIDTH	value
X *  BORDERLESS	value
X *  HIRES	0 or 1
X *  INTERLACE	0 or 1
X *  HALFBRITE	0 or 1
X *  FUNCTION	1 to 3
X *  IPLOT	1 to 2
X *  EPLOT	1 to 2
X *  DRAWPRI	-128 to -1
X *  WBWIDTH	value
X *  WBHEIGHT	value
X *  RAINDIST	value
X *  RAINRMAX	value
X *  RAINGMAX	value
X *  RAINBMAX	value
X */
X
Xextern void SetDrawingFunction(), SetIPlotFunction(), SetEPlotFunction();
X
X#define BATCH_MAGIC_BUT_TRUE	(-42)
X#define BATCH_COMMAND_NOT_FOUND (-1)
X
X#define BATCHLINESIZE		256
X
XSTATIC char BatchLine[BATCHLINESIZE];	/* Batch command line buffer */
X
X#ifdef AREXX
X
Xshort BatchWaiting;		/* Don't accept any commands */
X
X#endif
X
Xstruct Program *SetPC;		/* Where to place new instruction */
Xshort ProgramPart;		/* 0 = prelude, 1 = program */
X
XSTATIC bool SetDouble(), SetInt(), SetShort(), Cmd_quit(), Cmd_stop(),
X    Cmd_wait(), Cmd_fixrainbow(), Cmd_color(), Cmd_draw(), Cmd_shift(),
X    Cmd_loadsave(), Cmd_fixdisplay(), Cmd_borderless(), Cmd_viewmodes(),
X    Cmd_function(), Cmd_batch(), Cmd_drawpri(), Cmd_select(),
X    Cmd_pentablemode(), Cmd_program(), Cmd_r(), Cmd_end(), Cmd_reg();
X
Xbool GetLine();
X
XSTATIC struct BatchCmdDescription {
X    char *keyword;	/* command string to be matched */
X    int (*handler)();   /* handler to be called: (*handler)(harg [,args]) */
X    void *harg; 	/* special argument to pass to handler */
X};
X
X/*
X *  The following commands take no arguments, or
X *  do their own parsing of the command tail.
X */
X
XSTATIC struct BatchCmdDescription Batch_void[] = {
X    "program",          Cmd_program,        (void *)1,
X    "prelude",          Cmd_program,        (void *)0,
X    "r",                Cmd_r,              (void *)'r',
X    "c",                Cmd_r,              (void *)'c',
X    "end",              Cmd_end,            NULL,
X    "fixrainbow",       Cmd_fixrainbow,     NULL,
X    "color",            Cmd_color,          NULL,
X    "draw",             Cmd_draw,           (void *)(long)FALSE,
X    "fillin",           Cmd_draw,           (void *)(long)TRUE,
X    "shift",            Cmd_shift,          NULL,
X    "fixdisplay",       Cmd_fixdisplay,     NULL,
X    "batch",            Cmd_batch,          NULL,
X    "select",           Cmd_select,         NULL,
X    "modulo",           Cmd_pentablemode,   (void *)MODULO,
X    "ranges",           Cmd_pentablemode,   (void *)RANGES,
X    "reg",              Cmd_reg,            (void *)0,
X    "saveas",           Cmd_loadsave,       (void *)SaveAs,
X    "open",             Cmd_loadsave,       (void *)OpenAs,
X    "stop",             Cmd_stop,           NULL,
X    "wait",             Cmd_wait,           NULL,
X    "quit",             Cmd_quit,           NULL,
X    NULL,		NULL,		    NULL
X};
X
X/*
X *  The following commands take 1 double %lf argument
X */
X
XSTATIC struct BatchCmdDescription Batch_lf[] = {
X    "leftedge",         SetDouble,          &LeftEdge,
X    "rightedge",        SetDouble,          &RightEdge,
X    "topedge",          SetDouble,          &TopEdge,
X    "bottomedge",       SetDouble,          &BottomEdge,
X    NULL,		NULL,		    NULL
X};
X
X/*
X *  The following commands take 1 int (decimal) %d argument
X */
X
XSTATIC struct BatchCmdDescription Batch_d[] = {
X    "pixelstep",        SetInt,             &PixelStep,
X    "numcolors",        SetInt,             &NumColors,
X    "maxdepth",         SetInt,             &MaxDepth,
X    "rangewidth",       SetInt,             &RangeWidth,
X    "borderless",       Cmd_borderless,     NULL,
X    "hires",            Cmd_viewmodes,      (void *)HIRES,
X    "interlace",        Cmd_viewmodes,      (void *)LACE,
X    "halfbrite",        Cmd_viewmodes,      (void *)EXTRA_HALFBRITE,
X    "function",         Cmd_function,       (void *)SetDrawingFunction,
X    "iplot",            Cmd_function,       (void *)SetIPlotFunction,
X    "eplot",            Cmd_function,       (void *)SetEPlotFunction,
X    "drawpri",          Cmd_drawpri,        NULL,
X    NULL,		NULL,		    NULL
X};
X
X/*
X *  The following commands take 1 short int (decimal) %hd argument
X */
X
XSTATIC struct BatchCmdDescription Batch_hd[] = {
X    "wbwidth",          SetShort,           &WBWidth,
X    "wbheight",         SetShort,           &WBHeight,
X    "raindist",         SetShort,           &RainbowDistance,
X    "rainrmax",         SetShort,           &RainbowRMax,
X    "raingmax",         SetShort,           &RainbowGMax,
X    "rainbmax",         SetShort,           &RainbowBMax,
X    NULL,		NULL,		    NULL
X};
X
X/*
X *  This is a simple function:
X *  it just assigns a value to a variable of type double.
X */
X
XSTATIC bool SetDouble(harg, arg1)
Xvoid *harg;
Xdouble arg1;
X{
X    *(double *)harg = arg1;
X
X    return TRUE;
X}
X
X/*
X *  This is a simple function:
X *  it just assigns a value to a variable of type int.
X */
X
XSTATIC bool SetInt(harg, arg1)
Xvoid *harg;
Xint arg1;
X{
X    *(int *)harg = arg1;
X
X    UpdateOptDrawResCm();
X
X    return TRUE;
X}
X
X/*
X *  This is a simple function:
X *  it just assigns a value to a variable of type short.
X */
X
XSTATIC bool SetShort(harg, arg1)
Xvoid *harg;
Xshort arg1;
X{
X    *(short *)harg = arg1;
X
X    return TRUE;
X}
X
X/*
X *  Handle QUIT command.
X */
X
XSTATIC bool Cmd_quit()
X{
X    finished = TRUE;
X
X    return TRUE;
X}
X
X/*
X *  Handle STOP command.
X */
X
XSTATIC bool Cmd_stop()
X{
X    StopDrawing();
X
X    return TRUE;
X}
X
XSTATIC bool Cmd_wait()
X{
X#ifdef AREXX
X    /*
X     *	Halt all Arexx traffic as well...
X     *	This admittedly is a bit too rude, but as long as I can't test
X     *	better approaches...
X     */
X    BatchWaiting = TRUE;
X#endif
X
X    return BATCH_MAGIC_BUT_TRUE;
X}
X
XSTATIC bool Cmd_fixrainbow()
X{
X    extern SHORT RRMax; /* variable of the palette */
X
X    RRMax = -5; 	/* force color updating */
X    ModifyColors();     /* routine of the palette */
X
X    return TRUE;
X}
X
XSTATIC bool Cmd_color(harg, tail)
Xvoid *harg;
Xchar *tail;
X{
X    ULONG color, newred, newgreen, newblue;
X
X    if (sscanf(tail, "%ld %ld %ld %ld",
X	       &color, &newred, &newgreen, &newblue) == 4) {
X	if (color < NumColors && color < MAXCOL) {
X	    struct ViewPort *vp = &MandelScreen->ViewPort;
X	    SetRGB4(vp, color, newred, newgreen, newblue);
X	    return TRUE;
X	}
X    }
X
X    return FALSE;
X}
X
XSTATIC bool Cmd_draw(fillin)
Xvoid *fillin;
X{
X    return DrawPicture((bool)(long)fillin);
X}
X
XSTATIC bool Cmd_shift(harg, tail)
Xvoid *harg;
Xchar *tail;
X{
X    double HShift, VShift;
X    double Width  = RightEdge - LeftEdge,
X	   Height = BottomEdge - TopEdge;
X
X    if (sscanf(tail, "%lf %lf", &HShift, &VShift) == 2) {
X	LeftEdge   = LeftEdge + HShift * Width;
X	RightEdge  = RightEdge + HShift * Width;
X	TopEdge    = TopEdge + VShift * Height;
X	BottomEdge = BottomEdge + VShift * Height;
X
X	return TRUE;
X    }
X
X    return FALSE;
X}
X
XSTATIC char *ParseString(line)
Xchar *line;
X{
X    static char tmp[80];
X
X    if (line[0] == '"' || line[0] == '\'') {    /* Quoted ? */
X	char *end;
X
X	strncpy(tmp, ++line, sizeof(tmp)-2);
X	tmp[sizeof(tmp)-1] = '\0';
X	end = index(tmp, line[-1]);
X	if (end == NULL)
X	    return NULL;
X	*end = '\0';
X
X	return tmp;
X    }
X
X    return line;
X}
X
XSTATIC bool Cmd_loadsave(harg, tail)
Xvoid *harg;	/* Either OpenAs or SaveAs */
Xregister char *tail;
X{
X    tail = ParseString(tail);
X
X    /*
X     *	Cast harg into a pointer to a function returning bool
X     *	and call that function (OpenAs or SaveAs) with the name.
X     */
X
X    return (* (bool (*)()) harg) (tail);
X}
X
XSTATIC bool Cmd_borderless(harg, d)
Xvoid *harg;
Xint d;
X{
X    if (d)
X	DoBorderless(MainWindow, &borderinfo);
X    else
X	UndoBorderless(MainWindow, &borderinfo);
X
X    UpdateOptViewResCm();
X
X    return TRUE;
X}
X
XSTATIC bool Cmd_viewmodes(harg, d)
Xvoid *harg;
Xint d;
X{
X    if (d)
X	MandelNScreen.ViewModes |= (USHORT)(long)harg;
X    else
X	MandelNScreen.ViewModes &= ~(USHORT)(long)harg;
X
X    UpdateOptViewResCm();
X
X    return TRUE;
X}
X
XSTATIC bool Cmd_fixdisplay()
X{
X    return !ReInitDisplay();    /* returns failure... */
X}
X
XSTATIC bool Cmd_function(harg, d)      /* Numbered from 1 */
Xvoid *harg;
Xint d;
X{
X    (* (void (*)()) harg) (d - 1);
X    UpdateDrwCm();
X
X    return TRUE;
X}
X
XSTATIC bool Cmd_batch(harg, tail)
Xvoid *harg;
Xchar *tail;
X{
X    tail = ParseString(tail);
X
X    return OpenBatch(tail);
X}
X
XSTATIC bool Cmd_drawpri(harg, dpri)
Xvoid *harg;
Xint dpri;
X{
X    SetDrawPri(dpri);
X    UpdateOptPriCm();
X
X    return TRUE;
X}
X
XSTATIC bool Cmd_select(harg, tail)
Xvoid *harg;
Xchar *tail;
X{
X    int depth, pen;
X
X    if (sscanf(tail, "%d %d", &depth, &pen) == 2 &&
X	depth < MAXDEPTH &&
X	depth >= 0
X    ) {
X	PenTable[depth] = pen;
X	PenTableMode = SELECT;
X	UpdateOptColorCm();
X
X	return TRUE;
X    }
X
X    return FALSE;
X}
X
X
XSTATIC bool Cmd_pentablemode(harg)
Xvoid *harg;
X{
X    PenTableMode = (long) harg;
X    InitPenTable();
X    UpdateOptColorCm();
X
X    return TRUE;
X}
X
X/*-
X *  After the PROGRAM command, a small program of the following form
X *  must follow:
X *
X *	{"r", "c"} reg1 "=" reg2 [ {"i", "+", "-", "*"} reg3 ]
X *
X *  This fits in the sscanf pattern
X *
X *	"%1s %d = %d %1s %d"
X *
X *  which should match either 3 or 5 arguments.
X *
X *  This function only resets the program counter to the correct place.
X *  The program lines with r or c are handled by Cmd_r().
X-*/
X
XSTATIC bool Cmd_program(harg)
Xvoid *harg;		    /* 1 for PROGRAM, 0 for PRELUDE */
X{
X    int match;
X    register struct Program *pc = SetPC;
X
X    /* Find where to begin this program */
X    pc = &Program[0];
X    ProgramPart = match = (long)harg;
X
X    while (match--) {
X	while (pc->pr_OpCode != End) {
X	    pc++;
X	    /*
X	     *	This should not even be necessary since End == 0 and
X	     *	uninitialized static arrays contain binary zeros.
X	     */
X	    if (pc >= &Program[PROGRAMSIZE]) {
X		pc = &Program[0];
X		Program[0].pr_OpCode = End;
X		Program[1].pr_OpCode = End;
X		goto break_loops;
X	    }
X	}
X	pc++;
X    }
Xbreak_loops:
X    SetPC = pc;
X
X    return TRUE;
X}
X
XSTATIC bool Cmd_r(harg, tail)
Xvoid *harg;		    /* 'r' or 'c' */
Xchar *tail;
X{
X    auto char op[2];
X    auto int reg1, reg2, reg3;
X    int match;
X    register struct Program *pc = SetPC;
X
X    pc->pr_OpCode = End;    /* safety */
X    pc->pr_Dest = ProgramPart;
X
X    match = sscanf(tail, "%d = %d %1s %d", &reg1, &reg2, &op[0], &reg3);
X
X    pc->pr_Dest = reg1;
X    pc->pr_Op1 = reg2;
X
X    if (pc >= &Program[PROGRAMSIZE-1])
X	return FALSE;
X
X    if (match == 2) {
X	/* Must be an assignment */
X	pc->pr_OpCode = Rassign;
X    } else if (match == 4) {
X	pc->pr_Op2 = reg3;
X	switch (op[0]) {
X	case 'i':
X	    pc->pr_OpCode = Ri;
X	    break;
X	case '+':
X	    pc->pr_OpCode = Rplus;
X	    break;
X	case '-':
X	    pc->pr_OpCode = Rminus;
X	    break;
X	case '*':
X	    pc->pr_OpCode = Rtimes;
X	    break;
X	}
X    } else {
X	return FALSE;	    /* Parse errors are done rudely */
X    }
X    if (tolower((char)(long)harg) == 'c') {
X	pc->pr_OpCode++;    /* Make the opertation complex */
X    }
X    pc++;
X
X    SetPC = pc;
X    return TRUE;
X}
X
X
XSTATIC bool Cmd_end(harg, tail)
Xvoid *harg;
Xchar *tail;
X{
X    register struct Program *pc = SetPC;
X
X    pc->pr_OpCode = End;    /* safety */
X    pc->pr_Dest = ProgramPart++;
X
X    SetPC++;
X
X    return TRUE;
X}
X
XSTATIC bool Cmd_reg(harg, tail)
Xvoid *harg;
Xchar *tail;
X{
X    auto int regno;
X    auto double value;
X
X    if (sscanf(tail, "%d %lf", &regno, &value) == 2) {
X	if (regno >= 0 && regno < 2*PROGRAMREGS) {
X	    PrgReg[regno] = value;
X	    return TRUE;
X	}
X    }
X    return FALSE;
X}
X
X/*-----------------------------------------------------------------------*/
X
XSTATIC char *SkipNonWhite(line)
Xregister char *line;
X{
X    if (line)
X	while (*line && !isspace(*line))
X	    line++;
X
X    return line;
X}
X
XSTATIC char *SkipWhite(line)
Xregister char *line;
X{
X    if (line)
X	while (*line && isspace(*line))
X	    line++;
X
X    return line;
X}
X
X/*
X *   This is the function we use to see if the command matches
X *   the command string.  Not case sensitive.  Make sure all commands
X *   are given in lower case! [taken from MinRexx by Radical Eye Software]
X *   0 means equal enough, all other values mean not equal enough.
X */
X
XSTATIC int cmdcmp(c, m)
Xregister char *c, *m ;
X{
X    while (*c && ((*c == *m) || (*c == *m + 32 && ('a' <= *c && *c <= 'z')))) {
X	c++ ;
X	m++ ;
X    }
X    if (*m && !isspace(*m))
X	return 1;
X    return(*c) ;
X}
X
X/*
X *  Search a table of BatchCmdDescriptions for a keyword.
X *  When found, return a pointer to it.
X *  Otherwise, return NULL.
X */
X
XSTATIC struct BatchCmdDescription *SearchTable(table, string)
Xregister struct BatchCmdDescription *table;
Xregister char *string;
X{
X    while (table->keyword) {
X	if (cmdcmp(table->keyword, string) == 0)
X	    return table;
X	table++;
X    }
X
X    return NULL;
X}
X
X/*
X *  This executes a batch command line. Return value indicates success.
X#ifdef AREXX
X *  Can also be called from ARexx interface code.
X#endif
X */
X
Xbool ExecuteBatchCommand(command)
Xregister char *command;
X{
X    char *tail;
X    char *ptr;
X    bool success;
X    struct BatchCmdDescription *bcmdd;
X
X    command = SkipWhite(command);
X
X    if (command == NULL   ||
X	command[0] == ';' ||
X	command[0] == '/' ||
X	command[0] == '#' )
X	return TRUE;
X
X    tail = ptr = SkipNonWhite(command);
X    if (*tail)
X	tail = SkipWhite(tail);
X
X    if (bcmdd = SearchTable(Batch_void, command)) {
X	success = (*bcmdd->handler)(bcmdd->harg, tail);
X    } else if (bcmdd = SearchTable(Batch_d, command)) {
X	auto int d;
X	success = (sscanf(tail, "%d", &d) == 1) &&
X		  (*bcmdd->handler)(bcmdd->harg, d);
X    } else if (bcmdd = SearchTable(Batch_hd, command)) {
X	auto short hd;
X	success = (sscanf(tail, "%hd", &hd) == 1) &&
X		  (*bcmdd->handler)(bcmdd->harg, hd);
X    } else if (bcmdd = SearchTable(Batch_lf, command)) {
X	auto double lf;
X	success = (sscanf(tail, "%lf", &lf) == 1) &&
X		  (*bcmdd->handler)(bcmdd->harg, lf);
X    } else
X	success = BATCH_COMMAND_NOT_FOUND;
X
X    return success;
X
X}
X
Xvoid CloseBatch()
X{
X    if (BatchFILE) {
X	fclose(BatchFILE);
X	BatchFILE = NULL;
X    }
X
X    OffMenu(MainWindow, MENU(BATMENU, BATCONT,  NOSUB));
X    OffMenu(MainWindow, MENU(BATMENU, BATWAIT,  NOSUB));
X    OffMenu(MainWindow, MENU(BATMENU, BATABORT, NOSUB));
X}
X
Xbool OpenBatch(name)
Xregister char *name;
X{
X    CloseBatch();
X
X#ifdef AREXX
X    if (asyncRexxCmd(name))
X	return TRUE;
X#endif
X
X    BatchFILE = fopen(name, "r");
X
X    OnMenu(MainWindow, MENU(BATMENU, BATABORT, NOSUB));
X
X    if (BatchFILE == NULL) {
X	printf("Mandel: Cannot open batch file `%s'.\n", name);
X    } else if (isatty(fileno(BatchFILE))) {
X	printf("Mandel: Batch file `%s' is interactive.\n", name);
X	CloseBatch();
X    }
X
X    return BatchFILE != NULL;
X}
X
XSTATIC bool GetLine()
X{
X    if (fgets(BatchLine, BATCHLINESIZE, BatchFILE) != NULL) {
X	register char *newline;
X	if (newline = index(BatchLine, '\n')) {
X	    *newline = '\0';
X	} /* else silently truncate line */
X
X	return TRUE;
X    }
X
X    return FALSE;
X}
X
X/*
X *  This is the main entry point into the batch system.
X *  It fetches lines from the batch file (until EOF) and executes it.
X *  It stops doing that if a routine returns the special value
X *  BATCH_MAGIC_BUT_TRUE, or FALSE.
X *
X *  Ideally, this should also run as a separate task.
X */
X
Xbool Batch()
X{
X    bool result = TRUE;
X
X    BatchWaiting = FALSE;
X
X    if (BatchFILE != NULL) {
X	OnMenu( MainWindow, MENU(BATMENU, BATWAIT, NOSUB));
X	OffMenu(MainWindow, MENU(BATMENU, BATCONT, NOSUB));
X
X	while (GetLine()) {
X	    result = ExecuteBatchCommand(BatchLine);
X	    if (result == FALSE) {
X		printf("Batch command failed:\n%s\n", BatchLine);
X	    } else if (result == BATCH_COMMAND_NOT_FOUND) {
X		printf("Unknown batch command:\n%s\n", BatchLine);
X		break;
X	    } else if (result == BATCH_MAGIC_BUT_TRUE) {
X		/* Give up volontarily (wait command) */
X		OnMenu(MainWindow, MENU(BATMENU, BATCONT, NOSUB));
X		break;
X	    }
X	    if (MainWindow->UserPort->mp_MsgList.lh_Head->ln_Succ) {
X		/*
X		 *  Give up because of an intui-message. Signal
X		 *  ourselves to continue later on. This should not
X		 *  be done when we just did a wait command (see above).
X		 */
X		Signal(MandelTask, DrawSigMask);
X		break;
X	    }
X	}
X
X	OffMenu(MainWindow, MENU(BATMENU, BATWAIT, NOSUB));
X
X	if (feof(BatchFILE)) {
X	    CloseBatch();
X	}
X    }
X
X    return result;
X}
X
X/*
X *  This routine checks command line options
X */
X
Xvoid Options(argc, argv)
Xint argc;
Xchar **argv;
X{
X    if (argc > 2 || (argc == 1) && argv[1][0] == '?')
X	printf("Usage: %s [batchfile]\n", argv[0]);
X    else if (argc == 2) {
X	OpenBatch(argv[1]);
X    }
X}
X
X/*
X *  Batch menu handler
X */
X
Xvoid BatchMenu(Code)
XUSHORT Code;
X{
X    char Name[DNAME_SIZE + FNAME_SIZE + 3];
X    int Item = ITEMNUM(Code);
X
X    switch(Item) {
X    case BATFILE:
X	NameValid = FALSE;
X	if ( get_fname(MainWindow, "Select a BATCH file",
X		FileName, DirName) == NULL ) break;
X	CatFileComponents(Name, DirName, FileName);
X	OpenBatch(Name);
X	/* Fall through to start batch */
X    case BATCONT:
X	Signal(MandelTask, DrawSigMask);    /* Set the batch signal */
X	break;
X    case BATWAIT:
X	SetSignal(0L, DrawSigMask);         /* Clear the batch signal */
X	OnMenu( MainWindow, MENU(BATMENU, BATCONT, NOSUB));
X	break;
X    case BATABORT:
X	CloseBatch();
X	break;
X    }
X}
SHAR_EOF
echo "extracting Display.c"
sed 's/^X//' << \SHAR_EOF > Display.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 * The Display routines; initialisation and de-initialisation of
X * screen and window.
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
X#define BUGHEIGHT 213	/* See later comment */
X#define BUGWIDTH  640
X
XUSHORT ColorMap[MAXDEPTH];
Xbool ColorMapValid = FALSE;
X
X
X/*
X *  Initialize the screen and the windows and the menus
X *  Return value indicates FAILURE.
X */
X
Xbool InitDisplay(borderless)
Xbool borderless;
X{
X    USHORT ViewModes = MandelNScreen.ViewModes;
X    struct Screen WBScreen;
X    int i;
X
X    StopFraming();
X
X    Saved = TRUE;   /* We can easily reconstruct this `picture' */
X
X    if (WBWidth == 0) { /* Get Left, Top, Width, Height */
X	GetScreenData(&WBScreen, (long)sizeof(WBScreen),
X	    (long)WBENCHSCREEN, NULL);
X	WBWidth = WBScreen.Width;
X	WBHeight = WBScreen.Height;
X	/* Maybe we have an interlaced WorkBench screen */
X	if (WBScreen.ViewPort.Modes & LACE) WBHeight >>= 1;
X	/* And maybe, if we use MWB, it isn't hires... */
X	if (!(WBScreen.ViewPort.Modes & HIRES)) WBWidth <<= 1;
X    }
X    MandelNScreen.Width = WBWidth;
X    MandelNScreen.Height = WBHeight;
X
X    if (ViewModes & LACE) MandelNScreen.Height <<= 1;
X    if (MandelNScreen.Height < MINSCREENHEIGHT)
X	MandelNScreen.Height = MINSCREENHEIGHT;
X
X    if (ViewModes & HIRES) {
X	MandelNScreen.Depth = 4;
X
X	/* Avoid a bug in MrgCop()?? if you have a PAL machine with */
X	/* a screen wider than 640 taller than 213 and with 4 bitplanes */
X
X	if (MandelNScreen.Width > BUGWIDTH && MandelNScreen.Height > BUGHEIGHT)
X	    MandelNScreen.Width = BUGWIDTH;
X    } else {
X	MandelNScreen.Width >>= 1;
X	if (ViewModes & EXTRA_HALFBRITE) {
X	    MandelNScreen.Depth = 6;
X	} else {
X	    MandelNScreen.Depth = 5;
X	}
X    }
X
X    if (MandelNScreen.Width < MINSCREENWIDTH)
X	MandelNScreen.Width = MINSCREENWIDTH;
X
X    NumColors = 1 << MandelNScreen.Depth;
X
X    if ( !MandelScreen && !(MandelScreen = OpenScreen(&MandelNScreen)) ) {
X	skipto abort;
X    }
X
X    if (ColorMapValid)
X	LoadRGB4(&MandelScreen->ViewPort, ColorMap, (long) NumColors);
X
X    MainNWindow.Screen = MandelScreen;
X
X    if (MainNWindow.Height < MainNWindow.MinHeight) {
X	/* First time we open the window */
X	MainNWindow.LeftEdge = 0;
X	MainNWindow.TopEdge  = MandelScreen->BarHeight;
X	MainNWindow.Width    = MandelScreen->Width;
X	MainNWindow.Height   = MandelScreen->Height - MainNWindow.TopEdge;
X    } else {
X	if (ViewModes & HIRES) {
X	    MainNWindow.LeftEdge <<= 1;
X	    MainNWindow.Width <<= 1;
X	}
X	if (ViewModes & LACE) {
X	    MainNWindow.TopEdge <<= 1;
X	    MainNWindow.Height <<= 1;
X	}
X    }
X
X    /* Check for windows that can't be opened */
X
X    if (MainNWindow.LeftEdge + MainNWindow.Width > MandelScreen->Width)
X	MainNWindow.Width = MandelScreen->Width - MainNWindow.LeftEdge;
X
X    if (MainNWindow.TopEdge + MainNWindow.Height > MandelScreen->Height)
X	MainNWindow.Height = MandelScreen->Height - MainNWindow.TopEdge;
X
X    if ( !MainWindow && !(MainWindow = OpenWindow(&MainNWindow)) ) {
X	skipto abort;
X    }
X
X    SetMenuStrip(MainWindow, MandelMenu);
X    if (borderless) {
X	DoBorderless(MainWindow, &borderinfo);
X    }
X
X    InitPenTable();
X
X    return FALSE;
X
Xabort:
X    CleanupDisplay((bool) TRUE);
X    return TRUE;
X
X}
X
Xbool CleanupDisplay(everything)
Xbool everything;
X{
X    bool wasborderless;
X    int i;
X
X    StopDrawing();
X    StopFraming();
X
X    CloseColorWindow((BOOL) FALSE);
X
X    wasborderless = (MainWindow != NULL) &&
X	((MainWindow->Flags & BORDERLESS) != 0);
X
X    if (MainWindow) {
X	/* Save window appearance for later, in low-res non-lace pixels */
X	MainNWindow.LeftEdge = MainWindow->LeftEdge;
X	MainNWindow.TopEdge  = MainWindow->TopEdge;
X	MainNWindow.Width    = MainWindow->Width;
X	MainNWindow.Height   = MainWindow->Height;
X
X	ClearMenuStrip(MainWindow);     /* Remove menu strip */
X	CloseWindow(MainWindow);        /* Finally close it */
X	MainWindow = NULL;
X    }
X
X    /* Save the colors we may have established with great care */
X
X    if (MandelScreen) {
X	for (i=0; i < NumColors; i++) {
X	    ColorMap[i] = GetRGB4(MandelScreen->ViewPort.ColorMap, i);
X	}
X	ColorMapValid = TRUE;
X
X	if (MandelScreen->ViewPort.Modes & HIRES) {
X	    MainNWindow.LeftEdge >>= 1;
X	    MainNWindow.Width >>= 1;
X	}
X	if (MandelScreen->ViewPort.Modes & LACE) {
X	    MainNWindow.TopEdge >>= 1;
X	    MainNWindow.Height >>= 1;
X	}
X
X	/* Close the screen only if `everything' must be cleaned up */
X
X	if (everything) {
X	    CloseScreen(MandelScreen);
X	    MandelScreen = NULL;
X	}
X    }
X
X    return wasborderless;
X}
X
Xbool ReInitDisplay()
X{
X    bool WasBorderless;
X
X    WasBorderless = CleanupDisplay((bool) TRUE);
X    if (InitDisplay(WasBorderless)) { /* Trouble */
X	MandelNScreen.ViewModes &= ~(HIRES | LACE | EXTRA_HALFBRITE);
X	WBWidth = 0;	/* Re-use Workbench screen size */
X	if (InitDisplay((bool) FALSE))
X	    MyExit("Can't re-init display - Maybe low on memory");
X	SelectMenu(MENU(OPTMENU, OPTRES, ORHI), (bool)FALSE);
X	SelectMenu(MENU(OPTMENU, OPTRES, ORILC), (bool)FALSE);
X	SelectMenu(MENU(OPTMENU, OPTRES, ORBCK), (bool)FALSE);
X	SelectMenu(MENU(OPTMENU, OPTRES, OREHB), (bool)FALSE);
X
X	return TRUE;
X    }
X
X    return FALSE;
X}
X
Xbool DoBorderless(window, borderinfo)
Xstruct Window *window;
Xstruct BorderInfo *borderinfo;
X{
X    /* Make window borderless */
X
X/* register struct Layer_Info *LayerInfo = &window->WScreen->LayerInfo; */
X#define LayerInfo   NULL	    /* Since V1.2 */
X    register struct Layer *Layer = window->RPort->Layer;
X    register long movex;
X    register long movey;
X    register long sizex;
X    register long sizey;
X    bool Success = FALSE;
X
X    if (window->Flags & BORDERLESS) return TRUE;
X
X    LockLayer(LayerInfo, Layer);
X
X    window->Flags |= BORDERLESS;
X
X    movex = -window->BorderLeft;
X    movey = -window->BorderTop;
X    sizex = window->BorderRight - movex;
X    sizey = window->BorderBottom - movey;
X
X    window->BorderLeft =
X    window->BorderTop =
X    window->BorderRight =
X    window->BorderBottom = 0;
X
X    window->GZZWidth += sizex;
X    window->GZZHeight += sizey;
X
X    if ( MoveLayer(LayerInfo, Layer, movex, movey) ) {
X	Success = SizeLayer(LayerInfo, Layer, sizex, sizey);
X	if (!Success) {
X	    sizex = sizey = 0;
X	}
X    } else {
X	movex = movey = sizex = sizey = 0;
X    }
X    UnlockLayer(Layer);
X
X    borderinfo->MoveX = movex;
X    borderinfo->MoveY = movey;
X    borderinfo->SizeX = sizex;
X    borderinfo->SizeY = sizey;
X
X    /* Done making borderless */
X
X    if (Success) {
X	return Success;
X    } else {	/* Try to clean up the mess */
X	UndoBorderless(window, borderinfo);
X	return FALSE;
X    }
X#undef LayerInfo
X}
X
Xvoid UndoBorderless(window, borderinfo)
Xstruct Window *window;
Xstruct BorderInfo *borderinfo;
X{
X    /* ``Another fine mess you got me into!'' (Oliver Hardy) */
X
X/*  register struct Layer_Info *LayerInfo = &window->WScreen->LayerInfo; */
X#define LayerInfo   NULL	    /* Since V1.2 */
X    register struct Layer *Layer = window->RPort->Layer;
X    register long movex = borderinfo->MoveX;
X    register long movey = borderinfo->MoveY;
X    register long sizex = borderinfo->SizeX;
X    register long sizey = borderinfo->SizeY;
X    bool Success = FALSE;
X
X    if (!(window->Flags & BORDERLESS))  return;
X
X    LockLayer(LayerInfo, Layer);
X    SizeLayer(LayerInfo, Layer, -sizex, -sizey);
X    MoveLayer(LayerInfo, Layer, -movex, -movey);
X
X    window->GZZWidth -= sizex;
X    window->GZZHeight -= sizey;
X
X    window->BorderLeft = -movex;
X    window->BorderTop = -movey;
X    window->BorderRight = sizex + movex;
X    window->BorderBottom = sizey + movey;
X
X    window->Flags &= ~BORDERLESS;
X
X    RefreshWindowFrame(window);
X
X    UnlockLayer(Layer);
X
X    /* Done Undoing Borderless */
X#undef LayerInfo
X}
SHAR_EOF
echo "extracting Draw.c"
sed 's/^X//' << \SHAR_EOF > Draw.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 * The drawing task and interface code.
X *
X * This code MUST NOT be compiled with stack checking, since the drawing task
X * has its own stack. This is also true for anything that might get called
X * from here: DisableSizing(), EnableSizing(), StopFraming(), Sure(),
X * EnableSystemGadgets()...
X *
X * It must also be linked as one of the last files before the library, so it
X * is within 32K from the startup code containing geta4(). Otherwise, it
X * would need a4 in order to get a4.
X */
X
X#include <exec/types.h>
X#ifndef EXEC_SEMAPHORES_H
X#include <exec/semaphores.h>
X#endif
X#include <intuition/intuition.h>
X#include "mandel.h"
X#ifdef DEBUG
X#   include <stdio.h>
X#   undef STATIC
X#   define STATIC		/* EMPTY */
X#endif
X
Xextern double	ReMouse,
X		ImMouse;
X
Xint		DrawPri = 0;	/* Set with SetDrawPri() */
X
Xstruct Program	Program[PROGRAMSIZE];
Xdouble		PrgReg[2 * PROGRAMREGS];
X
X/* Complex multiplication using pointers to reduce overhead.   */
X/* YOU must make sure there are no (dynamic) aliases around... */
X
XSTATIC void
XMulCplx(ReRes, ImRes, ReA, ImA, ReB, ImB)
Xdouble	       *ReRes,
X	       *ImRes,
X	       *ReA,
X	       *ImA,
X	       *ReB,
X	       *ImB;
X{
X    *ReRes = *ReA * *ReB - *ImA * *ImB;
X    *ImRes = *ImA * *ReB + *ReA * *ImB;
X}
X
X/*
X * Private cache of the RastPort to speed up drawing
X */
X
XSTATIC struct RastPort *RastPort;
X
X/* Z^2-C: 4 multiplications per loop */
X
Xint
XZQuadMinC(ReC, ImC)
Xdouble		ReC,
X		ImC;
X{
X    register double ReZ = 0.0,
X		    ImZ = 0.0;
X    register double ReQuad,
X		    ImQuad;
X    register int    Depth = -1;
X
X    while (ImQuad = ImZ * ImZ, ReQuad = ReZ * ReZ, Depth++,
X	   (ImQuad + ReQuad < 8) && (Depth <= MaxDepth)) {
X	ImZ = 2 * ImZ * ReZ - ImC;
X	ReZ = ReQuad - ImQuad - ReC;
X    }
X
X    PrgReg[RE(0)] = ReZ;
X    PrgReg[IM(0)] = ImZ;
X
X    return Depth;
X}
X
X/* Z^2-C: 4 multiplications per loop */
X
Xint
XI_ZQuadMinC(ReC, ImC)
Xdouble		ReC,
X		ImC;
X{
X    register double ReZ = 0.0,
X		    ImZ = 0.0;
X    register double ReQuad,
X		    ImQuad;
X    register int    Depth = -1;
X
X    while (ImQuad = ImZ * ImZ, ReQuad = ReZ * ReZ, Depth++,
X	   (ImQuad + ReQuad < 8) && (Depth <= MaxDepth)) {
X	ImZ = 2 * ImZ * ReZ - ImC;
X	ReZ = ReQuad - ImQuad - ReC;
X
X	PrgReg[RE(0)] = ReZ;
X	PrgReg[IM(0)] = ImZ;
X
X	(*IPlotFunc)();
X    }
X
X    PrgReg[RE(0)] = ReZ;
X    PrgReg[IM(0)] = ImZ;
X
X    return Depth;
X}
X
X/* Z*C*(1-Z): 10 multiplications per loop */
X
Xint
XZC1MinZ(ReC, ImC)
Xdouble		ReC,
X		ImC;
X{
X#define ReZ	PrgReg[RE(0)]
X#define ImZ	PrgReg[IM(0)]
X    auto double     NewReZ,
X		    NewImZ;
X    auto double     Re1MinZ,
X		    Im1MinZ;
X    register int    Depth = -1;
X
X    ReZ = ReC;
X    ImZ = ImC;
X
X    while (Depth++, (ImZ * ImZ + ReZ * ReZ < 8) && (Depth <= MaxDepth)) {
X	Re1MinZ = 1 - ReZ;
X	Im1MinZ = -ImZ;
X	MulCplx(&NewReZ, &NewImZ, &ReZ, &ImZ, &ReC, &ImC);
X	MulCplx(&ReZ, &ImZ, &NewReZ, &NewImZ, &Re1MinZ, &Im1MinZ);
X    }
X
X#undef ReZ
X#undef ImZ
X
X    return Depth;
X}
X
X/* Z^3+Z*(C-1)-C: 12 multiplications per loop */
X
Xint
XZ3PlusZCMin1MinC(ReC, ImC)
Xdouble		ReC,
X		ImC;
X{
X#define ReZ	PrgReg[RE(0)]
X#define ImZ	PrgReg[IM(0)]
X    auto double     ReCMin1;
X    auto double     ReZ2,
X		    ImZ2,
X		    ReZ3,
X		    ImZ3;
X    register double ReQuad,
X		    ImQuad;
X    register int    Depth = -1;
X    register void (*iplot)() = IPlotFunc;
X
X    ReZ = ReC;
X    ImZ = ImC;
X
X    while (ImQuad = ImZ * ImZ, ReQuad = ReZ * ReZ, Depth++,
X	   (ImQuad + ReQuad < 8) && (Depth <= MaxDepth)) {
X	/* Calculate z^2 */
X	ReZ2 = ReQuad - ImQuad;
X	ImZ2 = 2 * ReZ * ImZ;
X
X	/* Make z^3 */
X	MulCplx(&ReZ3, &ImZ3, &ReZ2, &ImZ2, &ReZ, &ImZ);
X
X	/* Calculate z(c-1) while destroying z^2 */
X	ReCMin1 = ReC - 1;
X	MulCplx(&ReZ2, &ImZ2, &ReZ, &ImZ, &ReCMin1, &ImC);
X
X	/* Add everything */
X	ReZ = ReZ3 + ReZ2 - ReC;
X	ImZ = ImZ3 + ImZ2 - ImC;
X    }
X
X#undef ReZ
X#undef ImZ
X
X    return Depth;
X}
X
X/*
X * User programmed function...
X */
X
Xint
XUserProgFunc(ReC, ImC)
Xdouble		ReC,
X		ImC;
X{
X    register struct Program *pc;
X    register struct Program *MainPC;
X    register int    Depth = -1;
X    register int    pr_Dest;
X    register void (*iplot)() = IPlotFunc;
X
X    PrgReg[RE(2)] = ReC;
X    PrgReg[IM(2)] = ImC;
X
X    PrgReg[RE(3)] = ReMouse;
X    PrgReg[IM(3)] = ImMouse;
X
X#define ReZ	PrgReg[RE(0)]
X#define ImZ	PrgReg[IM(0)]
X
X#define ReQuad	PrgReg[RE(1)]
X#define ImQuad	PrgReg[IM(1)]
X
X#define ReC	PrgReg[RE(2)]
X#define ImC	PrgReg[IM(2)]
X
X    ReZ = 0.0;
X    ImZ = 0.0;
X
X    /* Do the prelude: */
X    pc = &Program[0];
X    goto InterpretLoop; 	/* I know this is ugly */
XPreludeDone:
X    MainPC = pc + 1;
X
X    while (ImQuad = ImZ * ImZ, ReQuad = ReZ * ReZ, Depth++,
X	   (ImQuad + ReQuad < 8) && (Depth <= MaxDepth)) {
X	pc = MainPC;
XInterpretLoop:
X	for (;;) {
X	    pr_Dest = pc->pr_Dest;
X
X	    switch (pc->pr_OpCode) {
X	    case End:
X		if (pr_Dest)    /* == 1 */
X		    goto EndOfProgram;
X		else
X		    goto PreludeDone;
X
X	    case Cassign:
X		PrgReg[IM(pr_Dest)] = PrgReg[IM(pc->pr_Op1)];
X	    case Rassign:
X		PrgReg[RE(pr_Dest)] = PrgReg[RE(pc->pr_Op1)];
X		break;
X
X	    case Ci:
X		PrgReg[IM(pr_Dest)] = (double) pc->pr_Op2;
X	    case Ri:
X		PrgReg[RE(pr_Dest)] = (double) pc->pr_Op1;
X		break;
X
X	    case Cplus:
X		PrgReg[IM(pr_Dest)] = PrgReg[IM(pc->pr_Op1)] +
X		    PrgReg[IM(pc->pr_Op2)];
X	    case Rplus:
X		PrgReg[RE(pr_Dest)] = PrgReg[RE(pc->pr_Op1)] +
X		    PrgReg[RE(pc->pr_Op2)];
X		break;
X
X	    case Cminus:
X		PrgReg[IM(pr_Dest)] = PrgReg[IM(pc->pr_Op1)] -
X		    PrgReg[IM(pc->pr_Op2)];
X	    case Rminus:
X		PrgReg[RE(pr_Dest)] = PrgReg[RE(pc->pr_Op1)] -
X		    PrgReg[RE(pc->pr_Op2)];
X		break;
X
X	    case Ctimes:
X		MulCplx(
X			&PrgReg[RE(pr_Dest)], &PrgReg[IM(pr_Dest)],
X			&PrgReg[RE(pc->pr_Op1)], &PrgReg[IM(pc->pr_Op1)],
X			&PrgReg[RE(pc->pr_Op2)], &PrgReg[IM(pc->pr_Op2)]
X		    );
X		break;
X
X	    case Rtimes:
X		PrgReg[RE(pr_Dest)] = PrgReg[RE(pc->pr_Op1)] *
X		    PrgReg[RE(pc->pr_Op2)];
X		break;
X	    }			/* end of switch */
X	    pc++;
X	}			/* end of for */
XEndOfProgram:
X	(*iplot)();
X    }				/* end of while */
X
X    return Depth;
X
X#undef ReZ
X#undef ImZ
X
X#undef ReQuad
X#undef ImQuad
X
X#undef ReC
X#undef ImC
X
X}
X
Xvoid PlotIterationCount(Count, x, y)
Xregister int	Count;
Xlong		x,
X		y;
X{
X    if (Count > MaxDepth)
X	Count = PenTable[0];
X    else
X	Count = PenTable[Count];
X
X    if (RastPort->FgPen != (BYTE) Count)
X	SetAPen(RastPort, (long) Count);
X    WritePixel(RastPort, x, y);
X}
X
Xvoid PlotZ()
X{
X    register int    Color;
X    register long   x,
X		    y;
X
X    x = (PrgReg[RE(0)] - LeftEdge) / CXStep;
X    y = (TopEdge -  PrgReg[IM(0)]) / CYStep;
X
X    /*
X     * Color will be -1 + 1 if we are within the window
X     */
X
X    if (Color = ReadPixel(RastPort, x, y) + 1) {
X	if (RastPort->FgPen != (BYTE) Color)
X	    SetAPen(RastPort, (long) Color);
X	WritePixel(RastPort, x, y);
X    }
X}
X
Xvoid None()
X{
X    /* empty */
X}
X
X/* Some private variables */
X
Xstruct Task    *DrawTask = NULL;
Xstruct Task    *MandelTask = NULL;
Xstruct SignalSemaphore DrawSemaphore;
X
X
X/*
X * This is what it is all about!
X */
X
XSTATIC bool	MyFillIn;	/* Parameter for new task */
X
XSTATIC void
XActuallyDrawPicture()
X{
X    double	    x,		/* Running Real value */
X		    y,		/* Running Imaginary value */
X		    Leftx;	/* Reset Real value */
X    register long   px, 	/* Running horizontal pixel coordinate */
X		    py; 	/* Running vertical pixel coordinate */
X
X    long	    Leftpx,	/* Reset horizontal pixel coordinate */
X		    minpx;	/* Minimal horizontal pixel coordinate */
X    register long   maxpx;	/* Maximal horizontal pixel coordinate */
X    long	    minpy,	/* Minimal vertical pixel coordinate */
X		    maxpy;	/* Maximal vertical pixel coordinate */
X    double	    MyXstep,	/* Real increment */
X		    MyYstep;	/* Imaginary increment */
X    int 	    MyPixelStep,/* Private copy of PixelStep */
X		    XOffset,	/* Running from 0 to MyPixelStep */
X		    YOffset;	/* Running from 0 to MyPixelStep */
X    struct Library *MathBasBase;/* Pointer to mathxxx.library */
X
X    register int    (*Function) ();
X    register void   (*Plot) ();
X
X    geta4();                    /* Manx small memory model */
X
X    ObtainSemaphore(&DrawSemaphore);
X
X#ifdef IEEEDP
X    /*
X     * We must open this library ourselves, just in case we have a math
X     * chip that needs extra context saving to be done. But to really
X     * access the library, we use the global library base that the main
X     * task has set for us. (but they are the same, anyway)
X     */
X    MathBasBase = OpenLibrary("mathieeedoubbas.library", LIBRARY_VERSION);
X#else
X    MathBasBase = OpenLibrary("mathffp.library", LIBRARY_VERSION);
X#endif
X
X    StillDrawing = TRUE;
X    DisableSizing();
X    StopFraming();
X    OffMenu(MainWindow, (ULONG) SHIFTMENU(PRJMENU) | SHIFTITEM(PRJNEW) |
X	    SHIFTSUB(NOSUB));
X    OffMenu(MainWindow, (ULONG) SHIFTMENU(OPTMENU) | SHIFTITEM(OPTRES) |
X	    SHIFTSUB(ORFIL));
X
X    if (!MyFillIn && !Sure())
X	skipto		exit;
X
X    if (!MyFillIn)
X	NameValid = FALSE;
X    Saved = FALSE;
X    MyPixelStep = PixelStep;
X    XOffset = 0;
X    YOffset = MyFillIn ? 1 : 0;
X
X    minpx = 0;
X    maxpx = MainWindow->GZZWidth - 1;
X    minpy = 0;
X    maxpy = MainWindow->GZZHeight - 1;
X
X    RastPort = MainWindow->RPort;
X    SetDrMd(RastPort, (long) JAM1);
X
X    if (!MyFillIn) {            /* Clear the window */
X	SetAPen(RastPort, (long) 2);    /* was PenTable[0] */
X	RectFill(RastPort, minpx, minpy, maxpx, maxpy);
X    }
X    CalcCSteps();               /* Calculate CXStep and CYStep */
X
X    MyXstep = MyPixelStep * CXStep;
X    MyYstep = MyPixelStep * CYStep;
X
X    Function = DepthFunc;
X    Plot = EPlotFunc;
X
X    ReleaseSemaphore(&DrawSemaphore);
X
Xagain:
X    Leftpx = minpx + XOffset;	/* Start in the upper left-hand corner */
X    py = minpy + YOffset;	/* of the window */
X    Leftx = LeftEdge + XOffset * CXStep;
X    y = TopEdge - YOffset * CYStep;
X
X    for (; py <= maxpy; y -= MyYstep, py += MyPixelStep) {
X	ObtainSemaphore(&DrawSemaphore);
X	for (px = Leftpx, x = Leftx; px <= maxpx; x += MyXstep, px += MyPixelStep) {
X	    (*Plot) ((*Function) (x, y), px, py);
X	    /* Check if we are asked to terminate. release s'phore. */
X	    if (StillDrawing < 0) {
X		ReleaseSemaphore(&DrawSemaphore);
X		skipto		exit;
X	    }
X	}
X	ReleaseSemaphore(&DrawSemaphore);
X    }
X
X    if (MyFillIn && (++YOffset < MyPixelStep)) {
X	backto		again;	/* Draw pixels below current pixel */
X    }
X    if (MyFillIn && (++XOffset < MyPixelStep)) {
X	YOffset = 0;		/* and next to them */
X	backto		again;
X    }
Xexit:
X    ObtainSemaphore(&DrawSemaphore);
X    if (MathBasBase)
X	CloseLibrary(MathBasBase);
X    EnableSizing();
X    OnMenu(MainWindow, (ULONG) SHIFTMENU(PRJMENU) | SHIFTITEM(PRJNEW) |
X	   SHIFTSUB(NOSUB));
X    OnMenu(MainWindow, (ULONG) SHIFTMENU(OPTMENU) | SHIFTITEM(OPTRES) |
X	   SHIFTSUB(ORFIL));
X    DrawTask = NULL;
X    StillDrawing = FALSE;	/* We are finished, finally... */
X    ReleaseSemaphore(&DrawSemaphore);
X
X    Signal(MandelTask, DrawSigMask);    /* and shout it off the roof */
X}
X
Xbool
XDrawPicture(FillIn)
Xbool		FillIn;
X{
X    register long   Priority;
X
X    if (StillDrawing == FALSE) {
X	Priority = MandelTask->tc_Node.ln_Pri + DrawPri;
X	MyFillIn = FillIn;
X
X	SetSignal(0L, DrawSigMask);     /* Clear the drawing signal */
X
X	DrawTask = CreateTask("Mandelbrot_Drawing.task", Priority,
X			      ActuallyDrawPicture, 2048L);
X    }
X    return DrawTask != NULL;
X}
X
X/* Interface because I wanted to CreateTask the drawing... */
X
Xvoid
XWaitForDrawing()
X{
X    Forbid();
X
X    if (StillDrawing)
X	Wait(DrawSigMask);
X
X    Permit();
X}
X
Xvoid
XStopDrawing()
X{
X    Forbid();
X
X    if (StillDrawing) {
X	StillDrawing = -1;	/* Indicate termination is wanted.  */
X	WaitForDrawing();       /* Clears the draw/batch signal.    */
X    }				/* Bug or feature? Need Batch/Cont. */
X    Permit();
X}
X
Xvoid
XSetDrawPri(Priority)
Xint		Priority;
X{
X    DrawPri = Priority;
X
X    Forbid();
X
X    if (StillDrawing) {
X	Priority = MandelTask->tc_Node.ln_Pri + DrawPri;
X	SetTaskPri(DrawTask, (long) Priority);
X    }
X    Permit();
X}
X
X/*
X * This is the external interface to the DrawSemaphore. Use it with care.
X * Always balance calls to SuspendDrawing() with ResumeDrawing() !!!
X */
X
Xvoid
XSuspendDrawing()
X{
X    ObtainSemaphore(&DrawSemaphore);
X}
X
Xvoid
XResumeDrawing()
X{
X    ReleaseSemaphore(&DrawSemaphore);
X}
X
Xvoid
XCalcCSteps()
X{
X    CXStep = (double) (RightEdge - LeftEdge) / (MainWindow->GZZWidth - 1);
X    CYStep = (double) (TopEdge - BottomEdge) / (MainWindow->GZZHeight - 1);
X}
SHAR_EOF
echo "extracting Dummy.c"
sed 's/^X//' << \SHAR_EOF > Dummy.c
X/**************************************************************************
X*
X* Include all necessary include-files for Mandel here.
X* Using the MANX +H<filename> option, compile it into a single, compacted
X* include-file, which can be used by all other compiles using the
X* +I<filename> option.
X*
X* THIS IS A GREAT DEAL	F A S T E R !!!
X*
X*************************************************************************/
X
X#include <exec/types.h>
X#include <exec/devices.h>
X#include <exec/memory.h>
X#include <exec/semaphores.h>
X
X#include <graphics/gels.h>
X#include <graphics/copper.h>
X#include <graphics/regions.h>
X
X#include <devices/keymap.h>
X
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X
X#include <intuition/intuition.h>
X#include <stdio.h>
SHAR_EOF
echo "extracting GetFile.c"
sed 's/^X//' << \SHAR_EOF > GetFile.c
X#undef DEBUG
X/************************************************************************
Xreq.c
X    This file contains a general-purpose <requester> that
Xwill prompt the user for a filename input.
X    The program actually uses a window instead of a 'Requester'
Xfor greater flexibility. It will take control of your window's
XIDCMP Port when called.
X
X*** This material is copyright (c) 1986 by C. Heath of Microsmiths, Inc.
XPermission is granted to use these files in any way with the following
Xexceptions:
X
X1) The files shall not be posted on any telecommunications service, public
Xor private, except for BIX until January 15, 1987.
X
X2) The files may only be distributed in archive format, with no modifications.
XIf you make any improvements on the file requester and would like to
Xgenerally distribute them, please contact "cheath" on BIX, or write to:
X    Microsmiths Inc, PO Box 561, Cambridge, MA 02140
X
X3) The requester may be used in any commercial product, but must be in
Xobject code format.  You are free to make modifications for use in your
Xproduct.  Permission is granted to Lattice, Inc, and to Manx, Inc, to
Xinclude the source files in archive format.
X
X    Thank you, and enjoy.
X	...cheath
X
X************************************************************************/
X
X#include <exec/types.h>
X#include <exec/devices.h>
X#include <intuition/intuition.h>
X
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <functions.h>
X
X#include "mandel.h"
X
X#define FAST register
X#define NL NULL
X#ifdef DEBUG
X#  undef STATIC     /* For the debugger's sake */
X#  define STATIC
X#endif
X
Xextern TEXT *dmore(), *dinit();
X
XSTATIC struct FileLock	    *pdir = NL;
XSTATIC struct FileInfoBlock *dir_info;
X
X/* STATIC struct Window   *eW;	   /* Parent Window. Uck   */
X
X/* STATIC struct TextAttr MyFont = {
X    "topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT };
X */
X#define MyFont Topaz80
X
X/* FGAD requires a few unique gadget-ids, origined at FGAD  */
X/* In the unlikely event this conflicts with any of your gadgets, */
X/* change this equate to allow 16 contiguous unique ID's    */
X
X#define FGAD	0x76c0L
X
X#define FCHARS	FNAME_SIZE  /* Number of chars allowed in file name */
X
X#define DIR_SIZ DNAME_SIZE  /* Number of chars in a dir name... */
X#define MAX_STR DIR_SIZ+2L
X
X#define DENTS	5L	/* Number of entries on screen	 */
X/* It's not as simple as changing 'DENTS'...      */
X
X#define DSIZE	FCHARS+1L   /* Size of a directory entry   */
X
X#define DBUFSIZ 3000L	/* Number of bytes to allocate for all ents */
X
X#define BCOL	1L  /* Background color */
X#define FCOL	2L  /* Foreground color */
X
X#define RHGHT	120L
X#define RWDTH	320L
X
X#define ZWDTH	270L
X
XSTATIC TEXT ubuf[MAX_STR];	/* Undo buffer	*/
X
XSTATIC struct dirent {
X    struct dirent *next;
X    BOOL isfile;
X    TEXT dE[DSIZE+2];
X};
XSTATIC struct dirent *FirstEntry;
XSTATIC struct dirent *NextEntry;
X
XSTATIC struct dirhead {
X    struct dirent *next;
X};
XSTATIC struct dirhead ListHead;
X
XSTATIC long   curent,maxent;
XSTATIC BOOL   more;
XSTATIC BOOL   redisplay_flag;
X
XSTATIC struct Window	*wRq = NL;	/* Requester window   */
XSTATIC struct RastPort	*wRp;
X
X/* Requester "Hailing" prompt */
XSTATIC struct IntuiText oTxt = {
X    2,2,JAM1,10,11,NL, NL ,NL};
X
XSTATIC struct IntuiText saydir = {
X    0,1,JAM2,0,1,&MyFont,(UBYTE *)"(dir) ",NL};
X
XSTATIC struct IntuiText rname[DENTS] = { /* File name list */
X    { 2,1,JAM2,48,1,NL,NL, NL	},
X    { 2,1,JAM2,48,1,NL,NL, NL	},
X    { 2,1,JAM2,48,1,NL,NL, NL	},
X    { 2,1,JAM2,48,1,NL,NL, NL	},
X    { 2,1,JAM2,48,1,NL,NL, NL	}
X};
X
X/* Display for file name ... */
X
XSTATIC SHORT oXY2[] = {
X    -2,-2, RWDTH-78,-2, RWDTH-78,9, -2,9, -2,-2};
XSTATIC struct Border thebd = {
X    0,0, 2,3,JAM1, 5,oXY2, NL};
X
XSTATIC struct IntuiText otxt = {
X    2,2,JAM1,-40,0,&MyFont,(UBYTE *)"file",NL};
XSTATIC struct StringInfo osx = {
X    NL, ubuf, NL,DSIZE,NL,NL,NL,NL,NL,NL,NL,NL,NL};
XSTATIC struct Gadget ogx = {
X    NL, 60,RHGHT-35,RWDTH-80 ,10,     /* File name gadget */
X    GADGHCOMP, RELVERIFY , STRGADGET,
X    (APTR)&thebd,NL,&otxt,NL,(APTR)&osx, FGAD+11,NL };
X
XSTATIC struct Gadget oga = {
X    &ogx, 10,70, ZWDTH,10,   /* Gadgets For   */
X    GADGHCOMP, RELVERIFY, BOOLGADGET,	  /* Directory entries	 */
X    NL,NL, &rname[4] ,NL,NL, FGAD+10,NL };
XSTATIC struct Gadget og9 = {
X    &oga, 10,60, ZWDTH,10,
X    GADGHCOMP, RELVERIFY, BOOLGADGET,
X    NL,NL, &rname[3] ,NL,NL, FGAD+9,NL };
XSTATIC struct Gadget og8 = {
X    &og9, 10,50, ZWDTH,10,
X    GADGHCOMP, RELVERIFY, BOOLGADGET,
X    NL,NL, &rname[2] ,NL,NL, FGAD+8,NL };
XSTATIC struct Gadget og7 = {
X    &og8, 10,40, ZWDTH,10,
X    GADGHCOMP, RELVERIFY, BOOLGADGET,
X    NL,NL, &rname[1] ,NL,NL, FGAD+7,NL };
XSTATIC struct Gadget og6 = {
X    &og7, 10,30, ZWDTH,10,
X    GADGHCOMP, RELVERIFY, BOOLGADGET,
X    NL,NL, &rname[0] ,NL,NL, FGAD+6,NL };
X
X
X/* Gadgets for requester  */
X
XSTATIC SHORT oXY3[] = {
X    0,0, 50,0, 50,9, 0,9, 0,0};
XSTATIC SHORT oXY4[] = {
X    2,-2, 48,-2, 52,2, 52,7, 48,11, 2,11, -2,7, -2,2, 2,-2};
XSTATIC struct Border obd2 = {
X    0,0, 2,3,JAM1, 9,oXY4, NL};
XSTATIC struct Border obd1 = {
X    0,0, 3,2,JAM1, 5,oXY3, &obd2};  /* OTAY / CANCEL box */
X
XSTATIC struct IntuiText ot1 = {
X    0,0,JAM1,1,1,&MyFont,(UBYTE *)"  OK  ",NL};
XSTATIC struct IntuiText ot2 = {
X    0,0,JAM1,1,1,&MyFont,(UBYTE *)"Cancel",NL};
X
XSTATIC struct IntuiText dtxt = {
X    2,2,JAM1,-60,0,NL,(UBYTE *)"drawer",NL};
XSTATIC struct StringInfo os5 = {
X    NL ,ubuf, NL,DIR_SIZ,NL,NL,NL,NL,NL,NL,NL,NL,NL};
XSTATIC struct Gadget og5 = {
X    &og6, RWDTH/2-80,19,190,10,     /* Directory */
X    GADGHCOMP, RELVERIFY, STRGADGET,
X    NL,NL,&dtxt,NL,(APTR)&os5, FGAD+5,NL };
X
XSTATIC struct Image   cc_img;
XSTATIC struct PropInfo	 cc_prop = {
X    AUTOKNOB | FREEVERT, 0,0, 0,MAXBODY,0,0,0,0,0,0 };
XSTATIC struct Gadget og3 = {
X    &og5,RWDTH-39,20,20,60,	 /* Scroll Bar	 */
X    GADGHNONE,GADGIMMEDIATE | FOLLOWMOUSE, PROPGADGET,
X    (APTR)&cc_img,NL,NL,NL,(APTR)&cc_prop,FGAD+3,NL };
X
XSTATIC struct Gadget og2 = {
X    &og3, RWDTH-70,RHGHT-20, 50,10,  /* CANCEL */
X    GADGHCOMP,	RELVERIFY, BOOLGADGET,
X    (APTR)&obd1,NL, &ot2,NL,NL, FGAD+2,NL };
X
XSTATIC struct Gadget og1 = {
X    &og2, 20,RHGHT-20, 50,10,	/* OTAY   */
X    GADGHCOMP,			/* Flags    */
X    RELVERIFY,			/* Activation	*/
X    BOOLGADGET,
X    (APTR)&obd1,NL,             /* GadgetRender, SelectRender   */
X    &ot1,NL,NL, 		/* IntuiText, MutualExclude,SpecialInfo   */
X    FGAD+1,NL };		/* Gadget Id, UserData	*/
X
X/* Open a requester "Window" */
X
XSTATIC struct NewWindow NewFiles = {
X    160, 30, RWDTH,RHGHT, BCOL,FCOL, NL, /* Fill in AFTER opening ... */
X    SMART_REFRESH | ACTIVATE | RMBTRAP | WINDOWDRAG,
X    &og1,NL,NL, NL,
X    NL, RWDTH,RHGHT,RWDTH,RHGHT, WBENCHSCREEN };
X
X
X/***************************************************
X*  get_fname(window,hail,ddef,ddir);
X*
X*   Displays a window/requester that
X* gets a file name for device,directory,default file, extension
X*
X*   Calling args:
X* window:   Window making the request
X* screen:   Screen, if NULL assumed workbench
X*	    (* Deleted by Olaf Seibert 6 May 1987 *)
X* hail:   Text prompt at top of requester
X* ddef:   Input default file-name. Has NO DIRECTORY OR EXTENSION.
X* ddir:   Directory of file, may be null
X
X/* Set a file-requester with prompt 'hail'   */
X
Xchar *get_fname(cW,hail,ddef,ddir)
Xstruct Window *cW;	/* Calling Window   */
XTEXT	    *hail;	/* Hailing prompt   */
XTEXT	    *ddef;	/* Propable file-name	*/
XTEXT	    *ddir;	/* Directory in which to search   */
X{
X    struct Screen *screen;  /* screen .... got from the window */
X    FAST struct IntuiMessage *imes; /* Wait for message in HERE   */
X    FAST struct Gadget	*igad;	    /* Get Gadjet Mumbo Jumbo	*/
X    FAST long	i,class;
X    FAST TEXT	*pnam;
X
X    FAST TEXT	*retval;
X    FAST BOOL	keepon;
X
X/*    if ( ! (eW = cW) )   return NL; */
X    if ( !cW )   return NL;
X
X    osx.Buffer = ddef;	/* Set default file name   */
X    os5.Buffer = ddir;	/* Set default device name   */
X
X    for ( i=0; i<DENTS; i++) {
X	rname[i].IText = (TEXT *)"";
X	rname[i].NextText = NL;
X    };
X
X    NewFiles.Title = cW->Title;
X    if ((dir_info = AllocMem((long)sizeof(struct FileInfoBlock),0L)) == NULL)
X	return NL;
X
X    /* Modified by Olaf Seibert 6 may 1987 */
X    screen = cW->WScreen;
X    NewFiles.Screen = screen;
X    NewFiles.Type = screen->Flags & SCREENTYPE;
X    NewFiles.LeftEdge = (screen->Width - RWDTH) / 2;
X    NewFiles.TopEdge = (screen->Height - RHGHT) / 2;
X
X    cc_prop.VertBody = MAXBODY;
X
X/*
X    if (screen)     (* User supplied a screen *)
X    {
X	NewFiles.Type = CUSTOMSCREEN;
X	NewFiles.Screen = screen;
X    }
X*/
X
X    if ( ! (FirstEntry = (struct dirent *)AllocMem((long)DBUFSIZ,0L)) ||
X	! (wRq = (struct Window *)OpenWindow( &NewFiles )) ) {
X	if ( FirstEntry )   FreeMem(FirstEntry,(long)DBUFSIZ);
X    /* notify("Can't Open Requester..."); */
X	FreeMem(dir_info,(long)sizeof(struct FileInfoBlock));
X	return NL;
X    }
X
X    SetWindowTitles(wRq, (CPTR) -1, hail);
X
X/* Set up directory, notify any errors...   */
X    if ( pnam = dinit(ddir) )   notify(pnam);
X
X
X/* This optional line will activate a string gadget, which gets messed	*/
X/* up by RefreshGadgets ... (intuition bug ?)   */
X#if 0
X    {
X	IMPORT struct Library	*IntuitionBase;
X	if ( IntuitionBase->lib_Version > 32 ) {
X	    ActivateGadget(&ogx,wRq,0L);
X	}
X    }
X#endif
X
X    wRp = wRq->RPort;
X
X    wRq->UserPort = cW->UserPort;
X    ModifyIDCMP(wRq,(long)(MOUSEBUTTONS | GADGETDOWN | GADGETUP | MOUSEMOVE));
X
X    SetAPen(wRp,1L);
X    RectFill(wRp,4L,10L,(long)(RWDTH-5),(long)(RHGHT-4));
X
X    oTxt.IText = hail;	 /* Set calling arg   */
X    oTxt.LeftEdge = (RWDTH - IntuiTextLength(&oTxt)) >> 1L;
X    PrintIText(wRp,&oTxt,0L,0L);
X
X    RefreshGadgets(&og1,wRq,(long)NL);
X    for ( retval= NL, keepon=TRUE; keepon ; ) {
X	while ( ! (imes=(struct IntuiMessage *)GetMsg(wRq->UserPort)) ) {
X	    if ( redisplay_flag ) {
X		/* update in-gadget filenames */
X		i = ((maxent-DENTS) * (ULONG)cc_prop.VertPot + MAXBODY/2)
X			/ MAXBODY;
X		if ( i > maxent-DENTS ) {
X		    i = maxent-DENTS;
X		    if ( i < 0 )   i = 0;
X		}
X		curent = i;
X		display_names();
X		redisplay_flag = FALSE;
X	    } /* End If redisplay_flag */
X	    if ( more ) {
X		if (pnam = dmore())   /* Continue to read the directory */
X		    notify(pnam);      /* Yucko error   */
X		/* if ( maxent <= DENTS ) redisplay_flag = TRUE; */
X	    } else /* not more */
X		WaitPort(wRq->UserPort);
X	} /* End While There Is No Message */
X	igad = (struct Gadget *)imes->IAddress;
X	class = imes->Class;
X	ReplyMsg(imes);
X
X	switch (class) {
X	case MOUSEMOVE:
X	    redisplay_flag = TRUE;
X	    break;
X
X	case GADGETUP:
X	case GADGETDOWN:
X	    switch ( i = igad->GadgetID) {
X	    case FGAD+6:
X	    case FGAD+7:
X	    case FGAD+8:
X	    case FGAD+9:
X	    case FGAD+10:	/* Replace file or directory name   */
X		pnam = rname[i - (FGAD+6)].IText;
X		if ( rname[igad->GadgetID - (FGAD+6)].NextText == NL ) {
X		    RemoveGadget(wRq,&ogx);
X		    for (i=0; i<DSIZE; i++)      ddef[i] = *pnam++;
X		    AddGadget(wRq,&ogx,-1L);
X		    RefreshGadgets(&ogx,wRq,(long)NL);
X		    break;
X		} else {
X		    RemoveGadget(wRq,&og5);
X		    rfnam(ddir,pnam);
X		    AddGadget(wRq,&og5,-1L);
X		    RefreshGadgets(&og5,wRq,(long)NL);
X		}
X	    case FGAD+5:
X		if ( pnam = dinit(ddir) )
X		    notify(pnam);
X	    case FGAD+3:
X		redisplay_flag = TRUE;
X		break;
X
X	    case FGAD+11:      /* Name gadget, OTAY gadget   */
X	    case FGAD+1:
X		retval = ddef;
X	    case FGAD+2:      /* Cancel gadget	 */
X		keepon = FALSE;
X	    }
X	}
X    }
X
X    FreeMem(FirstEntry,(long)DBUFSIZ );
X    FreeMem(dir_info,(long)sizeof(struct FileInfoBlock));
X    free_pdir();
X
X    CloseWindowSafely(wRq);
X    return retval;
X}
X
XSTATIC free_pdir()
X{
X    if ( pdir ) {
X	UnLock(pdir);
X	pdir = NL;
X    }
X}
X
X/*****************************************************************
X* dinit()
X*   Initialize the fib for directory muck.  Null return
X* is good, else return is a pointer to an error string	    */
X
XSTATIC TEXT *dinit(subdir)
Xchar *subdir;
X{
X    more = FALSE;
X    curent = maxent = 0;
X
X    NextEntry = FirstEntry;	 /* Allocate from here	 */
X    ListHead.next = NL; 	 /* Clear the boogie	 */
X
X    free_pdir();   /* Unlock any old lock... */
X
X    if (! (pdir=(struct FileLock *)Lock(subdir,(ULONG)ACCESS_READ)) )
X	return (TEXT *)"Wrong Diskette?";
X    if ( ! Examine(pdir, dir_info) )
X	return (TEXT *)"Wierd Disk Error";
X    if ( dir_info->fib_DirEntryType < 0L )
X	return (TEXT *)"Bizzare Alert!!";
X
X    more = TRUE;
X    return dmore();
X}
X
X
XSTATIC TEXT *dmore()
X{
X    FAST struct dirent	 *p_NewEntry = NextEntry;
X    FAST struct dirent	 *ptr = (struct dirent *)&ListHead;
X    FAST struct dirent	 *plink;
X
X    FAST   TEXT   *p_mung;
X
X    FAST long	 i;
X
X    FAST unsigned long VertBody;    /* KosmoSoft */
X
X    if ( ! more )   return NL;
X
X    if ( ExNext( pdir, dir_info ) ) {
X
X	if ( (ULONG)p_NewEntry >=
X	    ((ULONG)FirstEntry + (ULONG)DBUFSIZ - (ULONG)sizeof(struct dirent)) ) {
X	    more = FALSE;
X	    return (TEXT *)"Directory Truncated!";
X	}
X
X
X/* Here you can add a file/directory filter   */
X/* filename text string is at &p_NewEntry->dE[0]     */
X	p_NewEntry->isfile = ( dir_info->fib_DirEntryType < 0L );
X
X	p_mung = (TEXT *)&p_NewEntry->dE[0];
X	for ( i=0; i<FCHARS; i++)
X	    if ( ! (*p_mung++ = dir_info->fib_FileName[i]) )   break;
X
X	i = (long)p_mung;
X	NextEntry = (struct dirent *)( (i+5L) & ~3L );
X
X	for ( i=maxent++; i>=0; i--) {
X	    /* Start at the top and walk down until the new name */
X	    /* is 'smaller' than the next one (???) */
X	    if ( ! (plink = ptr->next)  )   break;
X	    if ( first_alpha_lower(p_NewEntry,plink) )   break;
X	    ptr = plink;
X	}
X	/* Insert the new name in front of the next one */
X	p_NewEntry->next = plink;
X	ptr->next = p_NewEntry;
X	redisplay_flag = maxent - i <= curent + DENTS;
X
X	/* Adjust the scroll bar */
X	if (maxent <= DENTS)
X	    VertBody = MAXBODY;
X	else
X	    VertBody = (ULONG) MAXBODY * DENTS / maxent;
X
X	ModifyProp(&og3, wRq, NULL, (ULONG) cc_prop.Flags,
X	    0L, (ULONG) cc_prop.VertPot, 0L, VertBody);
X
X	return NL;
X    }
X    else return ( IoErr() == ERROR_NO_MORE_ENTRIES) ?
X    (TEXT *)(more = (long)NL) : (TEXT *)"Error Reading Directory!!!";
X}
X
X
X/* dedicated alphabetizing function for dmore()   */
X
XSTATIC first_alpha_lower(snew,sold)
Xstruct dirent *snew,*sold;
X{
X    FAST struct dirent *pnew = snew;
X    FAST TEXT *ps1,*ps2, c,d;
X
X    if ( pnew->isfile == sold->isfile) {
X	ps1 = &pnew->dE[0];
X	ps2 = &sold->dE[0];
X	while ( (c=*ps1++) ) {
X	    if ( c > (d=*ps2++) )   return FALSE;
X	    else if ( c < d )      break;
X	}
X	return TRUE;
X    }
X    return !pnew->isfile; /* Directories first */
X}
X
X
X
X/* Display directory stuff   */
X
XSTATIC display_names()
X{
X    FAST long	i,new;
X    FAST long	x,y;
X    FAST struct dirent *ohboy = (struct dirent *)&ListHead;
X
X    new = curent;
X    for ( i=0; i<new; i++)   ohboy = ohboy->next;
X
X    y = 20L;
X    for (i=0; i<DENTS; i++) {
X	y += (x=10);
X	rname[i].NextText = NL;
X	rname[i].IText = (TEXT *)"";
X	rname[i].LeftEdge = 0;
X	if ( (new+i) < maxent ) {
X	    ohboy = ohboy->next;
X	    rname[i].IText = &ohboy->dE[0];
X	    if ( ohboy->isfile )   PrintIText(wRp,&rname[i],10L,y);
X	    else {
X		rname[i].LeftEdge = 48;
X		PrintIText(wRp,&saydir,10L,y);
X		PrintIText(wRp,&rname[i],10L,y);
X		rname[i].NextText = &saydir;
X	    }
X	    x = wRp->cp_x;
X	}
X	if ( x < ZWDTH+10 )   RectFill(wRp,x,y,(long)(ZWDTH+10),(long)(y+8L));
X    }
X}
X
X
X/**************************************************
X* rfnam()
X*   Combines dir, plus name into dir   */
X
XSTATIC rfnam(dir,fil_nam)
Xchar *dir,*fil_nam;
X{
X    FAST char	*pdst = dir;
X    FAST char	*psrc = fil_nam;
X    FAST char	c = ':';
X
X    while ( *pdst )
X	c = *pdst++;
X    if ( c != ':')   *pdst++ = '/';
X
X    while ( *pdst++ = *psrc++ )
X	;
X}
X
XSTATIC struct IntuiText b_txt = {
X    0,1,JAM2, 5,20,NL,NL,    NL};
XSTATIC struct IntuiText p_txt = {
X    0,1,JAM2, 5,3,NL, (TEXT *)"OK", NL};
X
X/****************************************************************/
X/* notify(txt)                                                  */
X/*   Prompts for Yes/No response				*/
X
XSTATIC notify(txt)
XTEXT *txt;
X{
X    b_txt.IText = txt;
X    AutoRequest(wRq,&b_txt,0L,&p_txt,0L,0L,
X    (long)(IntuiTextLength(&b_txt)+50L),70L);
X}
X
X/* CloseWindowSafely()
X*	This module should be used whenever you are sharing an IDCMP
X* message port with more than one window.  Rather than calling CloseWindow(),
X* you should use CloseWindowSafely().  This will keep Intuition from
X* Guru Meditation, and thus is considered a good thing.  You should still
X* use CloseWindow for the very last window you close.
X*	The reason this is needed, is because Intuition will re-claim
X* any outstanding messages for a window when the window is closed. But...
X* it can't take them out of your message port. Thus, you will receive
X* invalid messages and bad things will happen.	Very bad things.
X*	This code is a slightly condensed version of the same routine
X* written by Neil Katin of Amiga for the April '86 Commodore Developers
X* Newsletter, Amiga Mail (tm).
X*/
X
X/*
X#include <exec/types.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/ports.h>
X#include <intuition/intuition.h>
X#include <functions.h>
X*/
X
Xvoid CloseWindowSafely( p_wind )
Xstruct Window	*p_wind;
X{
X    register struct IntuiMessage    *msg;
X    register struct IntuiMessage    *succ;
X    register struct Window	    *win = p_wind;
X    register struct MsgPort	    *mp = (struct MsgPort *)win->UserPort;
X
X    Forbid();
X
X    msg = (struct IntuiMessage *)mp->mp_MsgList.lh_Head;
X
X    while ( succ=(struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ ) {
X	if ( msg->IDCMPWindow == win ) {
X	    Remove ( msg );
X	    ReplyMsg( msg );
X	}
X	msg = succ;
X    }
X    win->UserPort = NULL;
X    ModifyIDCMP( win, 0L );
X    Permit();
X    CloseWindow( win );
X}
X
X
SHAR_EOF
echo "End of archive 1 (of 4)"
# if you want to concatenate archives, remove anything after this line
exit