[net.sources.mac] Fractal Contours Aztec C source.

keithr@hercules.UUCP (08/12/85)

[]

This is the source to Fractal Contours that I promised to post.
Sorry for the delay in posting this but the power supply in 
my mac died. 

This program was written in Aztec C by Jim Cathey. Jim has moved
onto other projects so he probably won't be releasing any improvements 
in this program. 

Enjoy

Keith Rule

tektronix!teklds!keithr

---------------------------- Cut Here ------------------------------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	Makefile
#	fractal.c
#	fractal.h
#	fractal.r
#	fractal2.c
# This archive created: Sun Aug 11 21:32:45 1985
# By:	Keith Rule    tektronix!teklds!keithr (Tektronix, Inc.)
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'
#
# Dependency Rules
#
#fractal.res: fractal.r
#	rmaker fractal.r
fractal.o: fractal.c fractal.h

fractal2.o: fractal2.c fractal.h

fractal: fractal.o fractal2.o
	ln -m -o fractal sys:lib/sacroot.o fractal.o fractal2.o sys:lib/m.lib -lc
SHAR_EOF
if test -f 'fractal.c'
then
	echo shar: over-writing existing file "'fractal.c'"
fi
cat << \SHAR_EOF > 'fractal.c'
/*
**  Three-dimensional Fractal Contour Map generator.
**  Program originally in MicroSoft BASIC for the Macintosh.
**  Taken from July 1985 Creative Computing.
**
**  Used as an example BASIC-C comparison.
*/

#include <memory.h>
#include <quickdraw.h>
#include <font.h>
#include <window.h>
#include <osutil.h>
#include <menu.h>
#include <event.h>
#include <textedit.h>
#include <dialog.h>
#include <desk.h>
#include <control.h>
#include <toolutil.h>
#define watchCursor 4	/* Should be in TOOLUTIL.H but isn't.  JEC */
#include <resource.h>
#include <stdio.h>

#include "fractal.h"

GrafPtr screenport;		/* A port for the whole screen. */
WindowPtr mywindow;		/* Our one window. */
WindowRecord wrecord;		/* Storage for window record. */
MenuHandle mymenus[LASTMENU + 1]; /* Our menus. */
PicHandle thepicture;
BitMap savepix;			/* Storage for the update bitmap. */

EventRecord myevent;
WindowPtr whichwindow;		/* Points to window of MouseDown. */
int windowcode;			/* What mouse was in when event posted. */
Boolean userdone;		/* True when user wants to exit program. */
int ispicture;		/* True if there is a Picture definition of the
			   contour available. */
int isbitmap;		/* True if there is a bitmap copy of the contour
			   available.  Saves time in update events. */
int usebitmap;		/* True if the bitmap should be used to update. */

main() {
    setup();
    maineventloop();
}

/*############################   MainEventLoop  ########################*/  

maineventloop() {

    FlushEvents(everyEvent, 0);/* discard leftover events */

/* get next event, and handle it appropriately, until user QUITs */

    userdone = 0;
    do {
	SystemTask();		/* Handle desk accessories. */
	if (GetNextEvent(everyEvent, &myevent)) {
				/* get event; if for us... */
	    switch (myevent.what) {/* handle each kind of event */
		case mouseDown: /* find out what window the mouse went
				   down in, and where in it */
		    windowcode = FindWindow(pass(myevent.where), &whichwindow);
		    switch (windowcode) {
				/* handle mouse-down for each place */
			case inSysWindow: 
				/* handle the desk accessories */
			    SystemClick(&myevent, whichwindow);
			    break;/* insyswindow */
			case inMenuBar: /* handle the command */
			    userdone = docommand(MenuSelect(&myevent.where));
			    break;/* inmenubar */
			case inDrag: /* No Drag Region, treat as Content. */
			case inContent: 
				/* includes inGrow if window inactive.
				   Activate window */
			    if (whichwindow == mywindow)
				/* make sure it's for mine */
				if (whichwindow != FrontWindow())
				    SelectWindow(whichwindow);
				/* make it active */
			    break;
			case inGrow: /* No Grow Region */
			    break;
			case inGoAway: 
				/* we don't have a GoAway region */
			    break;
		    }
		    break;	/* switch */

		case keyDown: 
		case autoKey: 	/* if command key, pass the char to
				   MenuKey */
		    if ((myevent.modifiers & cmdKey) != 0)
			userdone = docommand(MenuKey((char) (myevent.message & charCodeMask)));
		case updateEvt: /* if it's for our window, update it */
		    if ((WindowPtr) (myevent.message) == mywindow)
			updatewindow(mywindow);
				/* redraw the window contents */
		    break;
		case activateEvt: 
				/* if for our window, set port as nec. */
		    if ((WindowPtr) (myevent.message) == mywindow) {
				/* my window */
			if (myevent.modifiers & 1) {
				/* odd means an activate event */
			    SetPort(mywindow);
				/* activate evt: work in our own port */
				DisableItem(mymenus[EDITMENU], 0);
				EnableItem(mymenus[FILEMENU], 0);
				EnableItem(mymenus[SETUPMENU], 0);
				DrawMenuBar();
			}
			else {
				SetPort(screenport);
				/* deactivate evt: our port is gone; keep
				   port from dangling */
				EnableItem(mymenus[EDITMENU], 0);
				DisableItem(mymenus[FILEMENU], 0);
				DisableItem(mymenus[SETUPMENU], 0);
				DrawMenuBar();
			}
		    } break;
	    }
	}

    } while (userdone == 0);
}

/*
handle a command given through a menu selection
############################   DoCommand   ##############################

   We carry out the command indicated by mResult.
   If it was Quit, we return true, else false.  Since the menu was
   highlighted by MenuSelect, we must finish by unhighlighting it
   to indicate we're done.
*/
int     docommand(mresult)
long    mresult;
{
    int     refnum;
    int     themenu,
            theitem;
    char    name[255];
    GrafPtr saveport;		/* for saving current port in when opening
				   a desk accessory */
    int     returns;

    returns = 0;		/* assume Quit not selected */
    themenu = HiWord(mresult);	/* get the menu selected */
    theitem = LoWord(mresult);	/* ... and the item of that menu */
    switch (themenu) {
	case 0: 
	    break;		/* user made no selection; do nothing */

	case APPLEMENU: 

	    if (theitem == 1)	/* Tell about FracCont */
		report();
	    else {		/* run a desk accessory; make sure port is
				   preserved */
		GetPort(&saveport);
		GetItem(mymenus[APPLEMENU], theitem, name);
				/* get name */
		refnum = OpenDeskAcc(name);/* run the desk accessory */
		SetPort(saveport);
	    }
	    break;

	case FILEMENU: 
	    switch (theitem) {
		case ANOTHER: 	/* New Surface */
			calcsurf(contlevl);
			InvalRect(&mywindow -> portRect);
			usebitmap = FALSE;
			break;
		case SAVEPAINT: /* Not yet. */
		    break;
		case IQUIT: 
		    returns = 1;/* Quit */
		    break;
	    }			/* FILEMENU case */
	    break;

	case SETUPMENU: 
	    switch (theitem) {
		case SETUP: 	/* Setup */
		    setupDlg();
		    break;
	    }			/* SETUPMENU case */

    }				/* menu case */

    HiliteMenu(0);		/* turn off hilighting on the menu just
				   used */
    return (returns);
}				/* DoCommand */

/*############################   Setup Dialog   ######################*/

TerrainBTN(ptr, oncontrl, offcontrl)
DialogPtr ptr;
int oncontrl, offcontrl;
{
	int itemtype;
	ControlHandle item;
	Rect itembox;

	GetDItem(ptr, offcontrl, &itemtype, &item, &itembox);
	SetCtlVal(item, 0);	/* Turn off old Default Button. */
	GetDItem(ptr, oncontrl, &itemtype, &item, &itembox);
	SetCtlVal(item, 1);	/* Turn on Default Button. */
	return oncontrl;
}
	
setupDlg()			/* Do the SETUP menu dialog. */
{
	int newtype;		/* Selected Contour type. */
	int newlevel;		/* Selected Level of Detail. */
	int userexit;
	int doanother;		/* True if we need to recalc. */
	int	itemhit;	/* Item # of punched button (or whatever) */
	DialogPtr setupptr;
	char asciibufr[10];
	int itemtype;
	ControlHandle item;
	Rect itembox;
	
	newtype = conttype;	/* SETUPMTN, SETUPHIL, or SETUPWATR */
	newlevel = contlevl;
	doanother = FALSE;
	
	setupptr = GetNewDialog(STPDLGID, NULL, (long) -1);
	TerrainBTN(setupptr, conttype, conttype);
	asciibufr[1] = newlevel + '0';	/* Only good for 0..9, OK here. */
	asciibufr[0] = 1;
	GetDItem(setupptr, SETUPLEVL, &itemtype, &item, &itembox);
	SetIText(item, asciibufr);
	SelIText(setupptr, SETUPLEVL, 0, 100);	/* Hilite text field. */
	userexit = FALSE;
	do {
		ModalDialog(NULL, &itemhit);
				/* carry out dialog; NIL => no FilterProc;
				   return item Hit when done */
		GetDItem(setupptr, SETUPLEVL, &itemtype, &item, &itembox);
		GetIText(item, asciibufr);	/* Get Level field */
		if (asciibufr[0] != 1)	/* Only good for 1..9, OK here. */
			newlevel = 100;
		else
			newlevel = asciibufr[1] - '0';
		if (newlevel < 1 || newlevel > MAXLEVEL)
			SelIText(setupptr, SETUPLEVL, 0, 100);	/* Hilite text field. */
		if (itemhit == SETUPMTN)
			newtype = TerrainBTN(setupptr, itemhit, newtype);
		if (itemhit == SETUPHIL)
			newtype = TerrainBTN(setupptr, itemhit, newtype);
		if (itemhit == SETUPWATR)
			newtype = TerrainBTN(setupptr, itemhit, newtype);
		if (itemhit == SETUPOK && ((newlevel > 0) & (newlevel <= MAXLEVEL))) {
			if (conttype != newtype || contlevl != newlevel) {
				if (contlevl != newlevel)
					doanother = TRUE;
				InvalRect(&mywindow -> portRect);
				usebitmap = FALSE;
			}
			contlevl = newlevel;
			conttype = newtype;
			userexit = TRUE;
		}
		if (itemhit == SETUPCAN)
			userexit = TRUE;
	} while (!userexit);
	DisposDialog(setupptr);	/* release storage and remove dialog from
					   screen */
	if (doanother)
		calcsurf(newlevel);	/* Removes dialog first. */
}	/* Setup */


/* 
############################   Report   #################################
*/

report()
{
    int     itemhit;		
    DialogPtr reportptr;

    reportptr = GetNewDialog(INFOSCR1, NULL, (long) -1);
				/* Get from Resource file; NIL => use heap
				   storage; -1 => make dlg frontmost */

    ModalDialog(NULL, &itemhit);
				/* carry out dialog; NIL => no FilterProc;
				   return item Hit when done */
    DisposDialog(reportptr);	/* release storage and remove dialog from
				   screen */
    if (itemhit == INFOMORE) {
	reportptr = GetNewDialog(INFOSCR2, NULL, (long) -1);
	ModalDialog(NULL, &itemhit);
	DisposDialog(reportptr);
    }
}


/*

SetUps for handling memory
##########################   SetUpMemory   ############################
*/

setupmemory() {


#define maxStackSize 8192	/* max size of stack; the heap gets the
				   rest */

    typedef long   *lomemptr;	/* a pointer to low memory locations */

    lomemptr nilptr;		/* will have value NIL */
    lomemptr stackbaseptr;	/* points to current stack base */

/* 
  If you define a GrowZone function to handle bad memory problems,
  you should define it at the top level (not nested), and set it
  here. We don't.
*/
/*  SetGrowZone(&mygrowzone);     */

/* 
  Place a longint -1 (an odd and therefore illegal address) in the
  memory location that would be referenced by an accidentally-NULL
  handle, so the error will be caught at handle-reference time (as
  an Address error, ID=02) instead of later on.
*/

    nilptr = NULL;
    *nilptr = -1;

/* 
  If you needed to use an Application heap limit other than the
  default (which allows 8K for the stack), you'd set it here,
  possible using this technique of explicitly specifying the maximum
  stack size and allocating the rest to the heap.  Should be
  independent of memory size. */

    stackbaseptr = (lomemptr) 0x908;
				/* CurStackBase from Tlasm/sysequ.text */
    SetApplLimit((Ptr) (*stackbaseptr - maxStackSize));

/* 
  Expand the application heap zone to its maximum size, without
  purging any purgeable resources.  This saves memory compactions
  and heap expansions later.
*/

    MaxApplZone();

/* 
  get plenty of master pointers now; if we let the Memory Manager
  allocate them as needed, they'd form non-relocatable islands in
  the heap.
*/

    MoreMasters();
    MoreMasters();

}				/* SetUpMemory */

/*
############################   SetUpMenus   #############################
    Once-only initialization for menus
    We read in all menus from the resource file, and install them,
    and all desk accessories (drivers).
*/

setupmenus() {
    int     i;
    for (i = 1; i <= LASTMENU; i++)/* get all my menus in */
	mymenus[i] = GetMenu(i);/* use the fact that our menu ID's start
				   at 1 */
    AddResMenu(mymenus[APPLEMENU], 'DRVR');
				/* pull in all desk accessories */
    for (i = 1; i <= LASTMENU; i++)
	InsertMenu(mymenus[i], 0);/* insert menus; 0 => put at end */
    DrawMenuBar();
}

/*
	
body of SetUp
Once-only initialization.
############################   SetUp   ##############################

   Initialize our program.  It seems best to handle:
   Memory inits first, ToolBox inits second, then the program variables'
   inits. Note that the order of inits is important; see "Using the
   Dialog Manager" in the Dialog Mgr section.

*/

setup() {

    char *ctop();
	
    setupmemory();		/*  init memory layout and protection */

/*  init QuickDraw, and everybody else */

    InitGraf(&thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(NULL);		/* NULL => no Restart proc; see Dialog Mgr
				   and System Error Handler */
    InitCursor();

/* 
  Init the system event mask, in case the previous program left
  it in a bad state.  If you set it non-standard here, FIX IT
  BEFORE EXITING, because the Finder (1.1g) does NOT set it.
*/
    SetEventMask(everyEvent - keyUpMask);/* standard setting */
/* 
  Get the port which is the whole screen, to use when deactivating
  our window.  This prevents the current grafPort pointer from
  ever dangling.
*/
    GetWMgrPort(&screenport);	/* get whole screen port that window mgr
				   uses */
    SetPort(screenport);	/* and start off with it */

/* 
  get window: use wRecord storage.  Port is set to that of the
  new window.
  GetNewWindow posts an update event for the new window,
  so it will be redrawn right away.
*/
#ifdef DEVELOP
	OpenResFile(ctop(DEVELOP));
#endif
	mywindow = GetNewWindow(WINDOWID, &wrecord, (long) -1);
				/* -1 => frontmost window */

/* pull in and set up our menus */
	setupmenus();
	CouldDialog(STPDLGID);	/* Preload the Setup Dialog. */

	conttype = DEFLTTYP;		/* Default style */
	contlevl = DEFLTLEV;		/* Default Level */
	isbitmap = FALSE;
    	/* Allocate the data array. */
	points = NewPtr((long) XDIM*YDIM*(sizeof(int)));	/* Non-reloc, but so what. */
	calcsurf(contlevl);		/* Do at least one first. */
}

/*

Update the contents of the given window
############################   UpdateWindow   ##########################

   This is our response to receipt of an update event for myWindow.
   Since the window is likely to be inactive, the current grafPort
   will be elsewhere.  We must change it for drawing, yet leave it
   as it was.
*/

updatewindow(awindow)
WindowPtr awindow;
{
    GrafPtr saveport;		/* to save and restore the old port */

    BeginUpdate(awindow);	/* reset ClipRgn etc to only redraw what's
				   necessary. */

    GetPort(&saveport);		/* don't trash the port; we might be
				   updating an inactive window */
    SetPort(awindow);		/* work in the specified window */

    drawwindow();		/* redraw contents of window */

    SetPort(saveport);		/* all nice and tidy as before */

    EndUpdate(awindow);

}				/* UpdateWindow */

/* 
Redraw my window
############################   DrawWindow   #############################

   We draw all the contents of our one window, myWindow.
*/

drawwindow()
{
	/* Possibly save the drawing contents in a picture.  This will allow
	   much faster update events than calling plotdata() repeatedly.
	   This is only to speed up Desk Accessory movement and the
	   re-painting after the Options Dialog is removed. */
	CursHandle ticktock;

	ticktock = GetCursor(watchCursor);
	if (ticktock)
		SetCursor(*ticktock);	/* Show watch (wait) */
	if (usebitmap) {
		CopyBits(&savepix, &mywindow->portBits,
			&savepix.bounds, &mywindow->portRect,
			srcCopy, 0L);
	}
	else {
		if (isbitmap)
			DisposPtr(savepix.baseAddr);
		savepix.bounds.top = mywindow->portRect.top;
		savepix.bounds.bottom = mywindow->portRect.bottom;
		savepix.bounds.left = mywindow->portRect.left;
		savepix.bounds.right = mywindow->portRect.right;
		savepix.rowBytes = mywindow->portBits.rowBytes;
		savepix.baseAddr = NewPtr((long) savepix.rowBytes *
			(savepix.bounds.bottom - savepix.bounds.top));
		EraseRect(&mywindow->portRect);
		plotdata();
		CopyBits(&mywindow->portBits, &savepix,
			&mywindow->portRect, &savepix.bounds,
			srcCopy, 0L);
		isbitmap = usebitmap = TRUE;
	}
#ifdef not_defined
	if (ispicture)
		KillPicture(thepicture);
	thepicture = OpenPicture(&mywindow -> portRect);
	ShowPen();	/* We want the picture shown while being drawn. */
	EraseRect(&mywindow -> portRect);
	plotdata();
	HidePen();	/* Balance the ShowPen() above. */
	ClosePicture();
	ispicture = TRUE;
#endif
	InitCursor();
}				/* DrawWindow */

/*
 *	The following routine was used while debugging and testing the program.
 *	The routine is called just like "printf()", but the output is
 *	directed to the printer port. Use -7 for the modem port.  The
 *	port must already be opened.  Use MIXCROOT and do a 2> .b(a)out
 *	to easily do this.
 */

#ifdef DEBUG
debug(fmt, arg)
char *fmt;
unsigned arg;
{
	int put();

	format(put, fmt, &arg);
}

put(c)
char c;
{
	long i;

	i = 1;
	if (c=='\n')
		put('\r');
	FSWrite(DEBUG, &i, &c);
	if (c=='\n')
		for (i=2000; i; i--)
			;
}
#endif

SHAR_EOF
if test -f 'fractal.h'
then
	echo shar: over-writing existing file "'fractal.h'"
fi
cat << \SHAR_EOF > 'fractal.h'
#define DEBUG -7		/* Includes debugging printer. */
				/* Use -7 for modem port, -9 for printer. */
#define DEVELOP "Frac:Fractal Contours"	/* Resource file to open for
					   faster program development. */

#define LASTMENU 4		/* Number of menus. */
#define APPLEMENU 1		/* Menu ID for Apple menu. */
#define FILEMENU 2		/* Menu ID for File menu. */
#define EDITMENU 3		/* Menu ID for Edit menu. */
#define SETUPMENU 4		/* Menu ID for parameter setting. */

#define ANOTHER 1		/* Items in the File menu. */
 /*-------*/
#define SAVEPAINT 3
 /*-------*/
#define IQUIT 5

#define SETUP 1			/* Items in the Setup menu. */

#define INFOSCR1 256		/* Resource ID for info dialog. */
#define INFOSCR2 257		/*   " info #2 dialog. */

#define INFOOK 1		/* OK Button */
#define INFOMORE 2		/* More Info Button */


#define WINDOWID 260		/* Resource ID for my window. */


/* Setup Dialog Stuff */
#define STPDLGID 258		/* ID of our setup dialog in resource
				   fork. */
#define SETUPOK 1		/* OK Button */
#define SETUPCAN 2		/* CANCEL Button */
#define SETUPLEVL 4		/* Level Text field */
#define SETUPMTN 5		/* Mountain RadButton */
#define SETUPHIL 6		/* Hills RadButton */
#define SETUPWATR 7		/* Water RadButton */

#define MAXLEVEL 7		/* Maximum level of detail. */
#define DEFLTLEV 4		/* Default level. */
#define DEFLTTYP SETUPWATR	/* Default type. */

#define XDIM 129		/* 2^MAXLEVEL+1 */
#define YDIM 65			/* 2^(MAXLEVEL-1)+1 */

int (*points)[XDIM][YDIM];	/* The array of points to be subdivided. */
int xmax, ymax;
int conttype; 			/* Contour type. */
int contlevl;			/* Level of detail. */

SHAR_EOF
if test -f 'fractal.r'
then
	echo shar: over-writing existing file "'fractal.r'"
fi
cat << \SHAR_EOF > 'fractal.r'
*  Fractal.r -- Resource definition file for fractal contour map
*               application.

* Tell RMAKER what to name the resource file
!fractal
APPLfrak

* Version data for the finder
*    Our signature is "frak"
*    res. ID = 0, by convention
*    finder version data
*    Note that the blank in 'STR ' is significant 3/8/85 WHJ
TYPE frak = STR 
  ,0
  Frac 1.0 -- July 13, 1985

* Menus
*   ID (4 => pre-load the resource; MUST NOT be purgeable!)
*   menu title: an Apple symbol (in hex) for the Apple menu.
*   menu entries, one per line. ( means it's initially disabled.
*   An entry of  (-  means a disabled line of dashes.
*   A trailing /Q means a command-key equivalent.
*   blank line at end of menu.
Type MENU
  ,1(4)
\14
 About Fractal Contours
 (-

Type MENU
  ,2(4)
File
 New/N
 (-
 (Save as Paint FileI
 (-
 Quit/Q

   ,3(4)
Edit
 (Undo
 (-
 Cut/X
 Copy/C
 Paste/V
 Clear

    ,4(4)
Options
 Contour ParametersI

* A Window template
*   ID,(4 => pre-load the resource; 32 => purgeable)
*    title
*    BoundsRect (global Top, Left, Bottom, Right): where it appears on the
screen
*    Vis NoGo: it's visible, does not have close box
*    ProcId: this is a standard type of window
*    Refcon, for program's use.  Frac doesn't use it.
Type WIND
  ,260(36)
  Fractal Contours
  39 1 341 511
  Visible NoGoAway
  0
  0

* Picture declarations.
* For the Information screens.
* Since RMaker doesn't know how to use these in
* DITL's, we have to get in and patch it up with
* ResEdit later.  Suck city!

* Type PICT = GNRL
*     ,128
*     .R
* Draw:Scrapbook PICT -32753
*
*     ,129
*     .R
* Draw:Scrapbook PICT -32752


* dialog box for About Fractal Contours
*   ID (4 => pre-load the resource; MUST NOT be purgeable!)
*   title
*   BoundsRect(global: TLBR)
*   Vis NoGo: it's visible, but has no close box
*   ProcID: Window type is modal dialog
*   RefCon: Unused user variable
*   res. ID of item list
Type DLOG
  ,256(4)
  Information Box
  28 24 328 485
  Visible NoGoAway
  1
  0
  256

  ,257(4)
  Information Box #2
  28 24 328 485
  Visible NoGoAway
  1
  0
  257

  ,258(4)
  Contour Parameters
  44 109 221 397
  Visible NoGoAway
  0
  0
  258



* dialog item list for About Fractal
*   ID (4 => pre-loaded; 32 => purgeable - it should always be purgeable.)
*   # Items
*   the first item:
*      a Button you can select
*      display rect (local coords)
*      title
Type DITL
  ,256(36)
  3
  Button Enabled
  97 14 118 99
OK

  Button Enabled
  96 114 118 201
More Info 

  StatText Disabled
  20 10 300 400
Picture here

  ,257(36)
  2
  Button Enabled
  273 205 294 290
OK

  StatText Disabled
  20 10 300 400
Picture here

* dialog item list for Setup
*   ID (4 => pre-loaded; 32 => purgeable - it should always be purgeable.)
  ,258(36)
8
*   1
BtnItem Enabled
144 32 164 92
OK

*   2
BtnItem Enabled
144 184 164 244
CANCEL

*   3
StatText Disabled
32 16 48 128
Level of Detail:

*   4
EditText Disabled
32 128 49 162

*   5
RadioItem Enabled
64 120 80 240
Mountainous

*   6
RadioItem Enabled
88 120 104 224
Foothills

*   7
RadioItem Enabled
112 120 128 264
Foothills & Water

*   8
StatText Disabled
64 16 83 116
Contour type:

***
* Finder's Information follows.
***

Type BNDL
   ,128(32)
   FRAC 0
   ICN# 0
   0 128 1 129
   FREF 0
   0 128 1 129

* a File Reference
*   ID, (32 => purgeable)
*   "APPL" : a file of type APPL (FRAC itself) gets the following icon (a
mountain);
*       local icon ID; maps to global ID as specified in BNDL
*   name of file that must accompany application if transferred; omit if none.
  Type FREF
   ,128(32)
   APPL 0

* An icon list for the application icon (a mountain)
*   ID (the application icon), (32 => purgeable)
*   Data is Hex data (.H)
*   the icon data: 32 lines of 8 hex chars each
*   the icon mask: 32 lines of 8 hex chars each
Type ICN# = GNRL
 ,128(32)
.H
0000 0000 0000 0000 0000 0000 0000 0000
0000 E000 0003 E000 0006 1000 0006 1000
000C 0800 003C 0C00 007C 7A00 0047 E300
01C6 1100 030C 1080 0278 10C0 06EE 3CE0
0583 47F0 1F00 C118 3303 820C 61BE 1C1E
4063 FFF7 7FFF 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
*
0000 0000 0000 0000 0000 0000 0000 0000
0000 E000 0003 E000 0007 F000 0007 F000
000F F800 003F FC00 007F FE00 007F FF00
01FF FF00 03FF FF80 03FF FFC0 07FF FFE0
07FF FFF0 1FFF FFF8 3FFF FFFC 7FFF FFFE
7FFF FFFF 7FFF 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000

****    end of information for the finder                          ****
***********************************************************************


*INCLUDE fractal.code

SHAR_EOF
if test -f 'fractal2.c'
then
	echo shar: over-writing existing file "'fractal2.c'"
fi
cat << \SHAR_EOF > 'fractal2.c'

/*
' 3-Dimensional Fractal surface generating program
' From July '85 Creative Computing.
*/

#include <quickdraw.h>
#include <toolutil.h>
#define watchCursor 4	/* Should be in TOOLUTIL.H but isn't.  JEC */
double ran();		/* Should be in MATH.H but isn't.  JEC */

#include "fractal.h"

#define TRUE (-1)
#define FALSE 0

int linestart;		/* True at the first of the line. */
int color;		/* True when plotting land, else false. */

calcsurf(level)
int level;
{
	int i, j, length, incrby, sk;
	float power;
	CursHandle ticktock;
	
	if (!points)
		return;
	ticktock = GetCursor(watchCursor);
	if (ticktock)
		SetCursor(*ticktock);	/* Show watch (wait) */

	xmax = 1 << level;
	ymax = xmax/2;
	for (i=0; i<=xmax; i++)		/* Clear the Array.  Use i & incrby as temps. */
		for (incrby=0; incrby<=ymax; incrby++)
			(*points)[i][incrby] = 0;

	for (i=1; i<= level; i++) {
		for (power=1.0, j=0; j<i; j++)
			power *= 1.8;
		length = 10000/power;		/* = 10000/(1.8^i) */
		incrby = xmax/(1 << i);	  /* # of line segments in a side of the triangle. */
		sk = incrby * 2;
		calcxs(length, incrby, sk);
		calcys(length, incrby, sk);
		calcdiags(length, incrby, sk);
	}
	InitCursor();		/* Put back the arrow. */
}

calcxs(len, incr, sk)	/* Assign heights along x in array. */
int len;
register int incr, sk;
{
	register int y, x;
	int d1, d2;

	for (y=0; y < xmax; y += sk) {
		for (x = incr+y; x <= xmax; x += sk) {
			d1 = getdata(x-incr, y);
			d2 = getdata(x+incr, y);
			stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
		}
	}
}

calcys(len, incr, sk)	/* Assign heights along y in array. */
int len;
register int incr, sk;
{
	register int y, x;
	int d1, d2;
	
	for (x=xmax; x >= 1; x -= sk)
		for (y = incr; y <= x; y += sk) {
			d1 = getdata(x, y+incr);
			d2 = getdata(x, y-incr);
			stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
		}
}

calcdiags(len, incr, sk)	/* Assign heights along diagonal in array. */
int len;
register int incr, sk;
{
	register int y, x;
	int d1, d2;
	
	for (x=0; x < xmax; x += sk)
		for (y = incr; y <= xmax-x; y += sk) {
			d1 = getdata(x+y-incr, y-incr);
			d2 = getdata(x+y+incr, y+incr);
			stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x+y, y);
		}
}

getdata(x, y)
register int x, y;
{
	if (y <= ymax)
		return (*points)[x][y];
	else
		return (*points)[xmax-x][xmax+1-y];
}

stuffdata(d, x, y)
register int d, x, y;
{
	if (y <= ymax)
		(*points)[x][y] = d;
	else
		(*points)[xmax-x][xmax+1-y] = d;
}


/*
**	Our window is already open at this point, and it is cleared,
**	all we have to do now is fill it.
**	Draw the 2D projection of the triangular database on the screen.
*/

plotdata()
{
	register int xindex, yindex;
	
	if (!points)
		return;
	color = TRUE;		/* On land to start. */

	for (xindex=0; xindex<=xmax; xindex++) {	/* Plot along X axis. */
		linestart = TRUE;
		for (yindex=0; yindex<=xindex; yindex++)
			doplot(xindex, yindex);
	}
	for (yindex=0; yindex<=xmax; yindex++) {	/* Plot along Y axis. */
		linestart = TRUE;
		for (xindex=yindex; xindex<=xmax; xindex++)
			doplot(xindex, yindex);
	}
	for (xindex=0; xindex<=xmax; xindex++) {	/* Plot along the diagonal. */
		linestart = TRUE;
		for (yindex=0; yindex<=xmax-xindex; yindex++)
			doplot(xindex+yindex, yindex);
	}
}

doplot(xindex, yindex)
int xindex, yindex;
{
	int xcoord, ycoord, zcoord;
	zcoord = getdata(xindex, yindex);
	ycoord = scaler(yindex, 10000, xmax);
	xcoord = scaler(xindex, 10000, xmax) - ycoord/2;
	if (conttype == SETUPWATR)
		sealevel(&xcoord, &ycoord, &zcoord);
	plotto(xcoord, ycoord, zcoord);
}

sealevel(newx, newy, newz)
int *newx, *newy, *newz;
{
	static int oldx, oldy, oldz;	/* The starting point for the next call. */
	int waterx, watery, waterz;	/* Where the vector hits the waterline. */
	float scratch;
	
	if (linestart) {	/* If at the beginning of the line */
		if ((oldz = *newz) < 0) {		/* and if we're underwater. */
			color = FALSE;
			*newz = 0;		/* Clip to the waterline. */
		}
		else
			color = TRUE;	/* Otherwise we're on land from the start. */
	}
	else {		/* Else we're in the middle of a line and ... */
		if (oldz > 0 && *newz > 0) {	/* start & end points both above water.. */
			oldz = *newz;
		}
		else if (oldz < 0 && *newz < 0) {	/* start & end points both under water... */
			oldz = *newz;
			*newz = 0;		/* Clip at the waterline */
		}
		else {	/* We're now crossing the waterline, */
			/* so calculate the exact point where it dives under. */
			scratch = (float) (*newz)/(*newz-oldz);	/* Proportion of the line that's */
			waterx = (int) ((oldx - *newx)*scratch) + *newx;	/* below the water. */
			watery = (int) ((oldy - *newy)*scratch) + *newy;
			waterz = 0;

			plotto(waterx, watery, waterz);		/* Draw to the waterline first. */
			/* The plot from the waterline to the endpoint in the new color 
			   is done elsewhere. */
			if (*newz > 0) {	/* Emerging from the water. */
				color = TRUE;	/* Set new color to 'land'. */
				oldz = *newz;
			}
			else {		/* Diving into the water. */
				color = FALSE;	/* Set new color to 'sea'. */
				oldz = *newz;
				*newz = 0;
			}
		}
	}
	oldx = *newx;	/* Save the real endpoint of the vector */
	oldy = *newy;	/* to use as the start of the next call. */
			/* (Z taken care of individually above). */
}

scaler(base, numer, denom)	/* Computes base*numer/denom with long intermediate.
*/
register int base, numer, denom;
{
	register long temp;
	temp = (long) base * (long) numer;
	temp /= (long) denom;
	return (int) temp;
}

plotto(x, y, z)		/* Convert 3-D line to a 2-D line and plot it. */
int x, y, z;
{
	rotate(&x, &y);		/* Rotate 30 deg. towards Y in the XY plane */
	tiltdown(&x, &z);	/* Tip 36 deg. down in the ZX plane */
	x /= 25;		/* Scale 10K to 400. */
	y /= 25;
	z /= 25;
	drawline(y, z);		/* Show the YZ planar projection. */
}

rotate(x, y)		/* Rotate XY plane 30 deg positive. */
int *x, *y;
{
	cordic(x, y, 5, 17);
}

tiltdown(x, z)		/* Rotate XZ plane 36 deg negative (+?). */
int *x, *z;
{
	cordic(x, z, 5, (conttype == SETUPMTN) ? 20 : -20);
}

drawline(x, y)		/* Draw either a line from the last endpoint */
int x, y;		/* to the given point, or only a point at x,y. */
{
	static int lastx, lasty;
	x += x/10 + 10;	/* Quick x1.1 + tiny offset. */
	if (conttype == SETUPMTN)
		y = 220 - y;	/* Move the baseline for mountains. */
	else
		y = 80 - y;
	if (linestart || !color)	/* Only a point then. */
		MoveTo(x, y);
	LineTo(x, y);
	lastx = x;
	lasty = y;
	linestart = FALSE;	/* Stuck in the middle with you... */
}

cordic(x, y, scale, count)	/* Spin XY vector 'count' steps to the left using */
int *x, *y;			/* CORDIC algorithm with a shift factor of 'scale'. */
register int scale, count;	/* Rotates atan(1/(2^scale)) degrees/step. */
				/* (Scale of 5 is 1.79 deg/step;  4 = 3.57 d/s...) */
				/* *x & *y should be large for accuracy. */
{
	register int tempx, tempy;
	tempx = *x;
	tempy = *y;
	if (count>0)	/* Positive count is CCW (left) */
		for (; count; count--) {
			tempx -= (tempy>>scale);
			tempy += (tempx>>scale);
		}
	else		/* Negative is CW (right) */
		for (; count; count++) {
			tempx += (tempy>>scale);
			tempy -= (tempx>>scale);
		}
	*x = tempx;
	*y = tempy;
}

SHAR_EOF
#	End of shell archive
exit 0