[net.sources.mac] Example, part 1 of 2 - a skeleton Sumacc program

kdmoen@watcgl.UUCP (Doug Moen) (03/23/85)

: This is a shar archive.	Extract with sh, not csh.
: The rest of this file will extract:
: README INSTRUCTIONS Makefile example.rc defs.h windows.h documents.h resources.h util.h file.h strings.c util.c fileio.c debug.c ram.c
echo Extracting README
sed 's/^X//' > README << 'e-o-f'
X"Example" is a skeleton Sumacc program that provides a
Xreasonably complete framework for implementing an editor of
Xsome kind.  The program supports:
X - Apple, File and Edit menus
X   (consistent with the Inside Mac user interface guidelines)
X - an 'About Example' window
X - The use of desk accessories.  Desk accessories whose names do
X   not start with a NUL can be opened without problems.  This is a
X   bug in most Sumacc programs.
X - a 'New' command which allows the creation of multiple document windows
X   (there is no maximum number of open documents)
X - Open, Save and Save As commands allowing documents to be loaded
X   and saved to disk.
X - A cursor that changes to a watch when the system is busy
X   and changes shape depending on what window it is over.
X - Several useful debugging routines.
X
XThings I haven't implemented yet are:
X - Close, Revert to Saved, Page Setup and Print commands
X - Show Clipboard command
X - proper handling of window activate and deactivate events
X - disabling of invalid commands in the menu bar (by graying them out)
X - asking the user if he really wants to close an unsaved document
e-o-f
echo Extracting INSTRUCTIONS
sed 's/^X//' > INSTRUCTIONS << 'e-o-f'
X'Example' provides the basic framework for writing an editor
Xof some sort -- eg, a text editor, a graphics editor, etc.
X
XTry compiling and running Example.  The Apple menu provides an
X'About Example' command, and access to desk accessories.
XThe File menu contains New, Open, Save, and Save As, which allow
Xyou to create, load and save documents.  You may have as many documents
Xopen at one time as you like, and you can move and resize document windows.
XCurrently, document windows are featureless, and saved document files
Xhave zero length.  The Edit menu contains Undo, Cut, Paste, etc,
Xwhich currently only work on Desk Accessory windows.
X
XHere is the minimum you need to change to build a working program:
Xdocuments.h:
X	Add declarations for your per-document data structures
X	to struct Document.
Xdocuments.c:
X	Add code to NewDocument() and FreeDocument() to initialize
X	and dispose of the data stored in a Document.
XdocWindows.c:
X	Add code to UpdateDocument(), DocumentClick(), and maybe
X	DocumentKey() and DocumentCursor(), to handle various events
X	within a document window.
X
XIf you want to be able to load and save document files, add code
Xto ReadDocument() in getDoc.c and WriteDocument() in putDoc.c.
X
XIf you want to add new commands to the menu bar, you need to make
Xstraightforward changes to menus.c and example.rc.
X
Xdebug.c contains MessageF() and CheckHandle(), which are useful for
Xdebugging.
X
XBeyond this, I suggest you make a printout of the source, and study
Xfirst the headers of each source file, then the source files themselves.
X(type make print)
e-o-f
echo Extracting Makefile
sed 's/^X//' > Makefile << 'e-o-f'
X.SUFFIXES: .rsrc .b .s .c
XCFLAGS = -O
XCSRC1 = \
X	main.c events.c menus.c windows.c edit.c file.c info.c \
X	documents.c docWindows.c makeDoc.c getDoc.c putDoc.c
XCSRC2 =	strings.c util.c fileio.c debug.c ram.c
XCSRC = $(CSRC1) $(CSRC2)
XSRC = $(CSRC) pGetItem.s
XOBJ = \
X	main.b events.b menus.b windows.b edit.b file.b info.b \
X	documents.b docWindows.b makeDoc.b getDoc.b putDoc.b\
X	strings.b util.b fileio.b debug.b ram.b pGetItem.b
XHDR = \
X	defs.h windows.h documents.h resources.h util.h file.h
X
X.c.b:
X	cc68 $(CFLAGS) -c $<
X
X.c.s:
X	cc68 -S $<
X
X.s.b:
X	cc68 -c $<
X
Xexample.rsrc: example example.rc
X	rmaker example.rc
X
Xexample: $(OBJ)
X	cc68 -m $(OBJ) -o example
X	size example | sed 1d >>Sizes
X
Xobjects: $(OBJ)
X
Xput: example.rsrc
X	macput -o -r example
X
Xlint:
X	-lint -hbx -lmac $(CSRC) >Lint
X	-grep -n '\<if\>.*[^!=<>]=[^=]' $(CSRC) >>Lint
X
Xclean:
X	rm -f *.b *.rsrc example
X
Xprint:
X	(pr `ls $(HDR)` `ls $(SRC)` example.rc | expand -4) | lpr
X
Xshar:
X	shar README INSTRUCTIONS Makefile example.rc $(HDR) $(CSRC2) >SHAR1
X	shar $(CSRC1) pGetItem.s >SHAR2
e-o-f
echo Extracting example.rc
sed 's/^X//' > example.rc << 'e-o-f'
X* Resource file for Example, a skeleton Macintosh application
X* Doug Moen, watmath!watcgl!kdmoen, March 1985
X
Xexample.rsrc
X
XType CODE
X    example,0
X
XType MENU
X    ,1
X    @
X        About Example
X        (-
X
XType MENU
X    ,2
X    File
X        New
X		Open...
X		(-
X		Close
X		Save
X		Save As...
X		Revert To Saved
X		(-
X		Page Setup...
X		Print...
X		(-
X        Quit/Q
X
XType MENU
X    ,3
X    Edit
X        Undo/Z
X        (-
X        Cut/X
X        Copy/C
X        Paste/V
X        Clear
X        (-
X        Show Clipboard
X        Select All
X
X*
X* 'About Example' modeless dialog window
X*
X
XType DLOG
X    ,1
X    70 105 150 405
X    Visible 0 Goaway 0
X    1
XAbout Example
X
XType DITL
X    ,1
X    3
X    StatText Disabled
X    10 10 30 350
XExample: A Skeleton Macintosh Application
X
X    StatText Disabled
X    30 10 50 350
XBy Doug Moen (watmath!watcgl!kdmoen)
X
X    StatText Disabled
X    50 10 70 350
XVersion 1.0: March, 1985
X
X
X*******************
X* Various strings *
X*******************
X
XType STR
X    ,256
XUntitled-
X
XType STR
X    ,257
XSave current document as:
e-o-f
echo Extracting defs.h
sed 's/^X//' > defs.h << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * defs.h
X *	Master header file.
X */
X
X#include <strings.h>
X
X#include "mac/quickdraw.h"
X#include "mac/osintf.h"
X#include "mac/toolintf.h"
X#include "mac/packintf.h"
X
X#define DEBUG
X
X/*
X * These macros are used for declaring and initializing global
X * variables.  INIT is only defined within main.c.
X */
X#ifdef INIT
X#	define EXTERN
X#	define IS(x) = x
X#else
X#	define EXTERN extern
X#	define IS(x)
X#endif
X
X/* this gets around bug in C compiler: (void) casts don't work */
X#ifdef lint
X#	define VOID (void)
X#else
X#	define VOID
X#endif
X
X#include "util.h"
X#include "file.h"
X#include "windows.h"
X#include "documents.h"
X#include "resources.h"
e-o-f
echo Extracting windows.h
sed 's/^X//' > windows.h << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * windows.h
X */
X
X/*
X * tags for identifying the class of a window.
X * These are placed in the 'windowKind' field of the window record.
X */
X#define infoKind 9
X#define documentKind 10
X
X#define WindowKind(w) ((WindowPeek)(w))->windowKind
X#define SetWindowKind(w,kind) (((WindowPeek)(w))->windowKind = (kind))
X
X#define WindowHeight(w) ((w)->portRect.bottom - (w)->portRect.top)
X#define WindowWidth(w) ((w)->portRect.right - (w)->portRect.left)
e-o-f
echo Extracting documents.h
sed 's/^X//' > documents.h << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * documents.h
X * Define the structure of a document record
X */
X
Xstruct Document {
X	/* next record in the linked list of documents */
X	struct Document **next;
X
X	/* the document window */
X	WindowPtr window;
X
X	/* has the document been modified since it was last saved */
X	Boolean dirty;
X	
X	/* Does the document have an associated disk file */
X	Boolean untitled;
X
X	/*
X	 * Reference number of disk that document resides on
X	 * (file name is title of window)
X	 */
X	Int16 vRefNum;
X
X	/*
X	 * Add whatever data structures you need to represent
X	 * the contents of the document right here.
X	 */
X};
Xtypedef struct Document Document;
X
X/* linked list of document records for all active documents */
XEXTERN Document **docList IS( NIL );
X
XDocument **NewDocument(), **MakeDocument();
e-o-f
echo Extracting resources.h
sed 's/^X//' > resources.h << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * resources.h:
X *	Constants defining resource IDs
X */
X
X/* String resource ID's */
X#define S_Untitled 256
X#define S_SaveAs 257
X
X/* Dialog & window resource ID's */
X#define W_Info 1
e-o-f
echo Extracting util.h
sed 's/^X//' > util.h << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * util.h:
X * Misc. global variables, constants and types.
X */
X
X/*
X * Various system-provided cursors.
X */
XCursHandle IBeamCursor, CrossCursor, WatchCursor;
X
X/*
X * screenport is a grafport covering the entire screen.
X */
XGrafPtr screenPort;
X
X/*
X * deskBounds is a rectangle covering the desktop area.
X * It is used as an argument to DragWindow() in windows.c
X */
XRect deskBounds;
X
X/*
X * dimensions of the grow box in the bottom right corner of a document window
X */
X#define growBoxHeight 15
X#define growBoxWidth 15
X
X#define menuBarHeight 20
X
X/* thickness of document window frame on all 4 sides */
X#define wFrameTop 19
X#define wFrameLeft 1
X#define wFrameBottom 2
X#define wFrameRight 2
X
X/* a nice thickness for thin borders and margins */
X#define thinMargin 4
X
X/*
X * A Box is the same as a Rect, except that it is a struct,
X * not a union.  This permits arrays of Boxes to be statically
X * initialized, for use with TrackBoxes().
X */
Xtypedef struct {
X	short t,l,b,r;
X} Box;
X
XBox *TrackBoxes();
X
X#define NIL 0
X#define FALSE 0
X#define TRUE 1
X
Xtypedef char Boolean;
Xtypedef char Int8;
Xtypedef short Int16;
Xtypedef int Int32;
X
X#define minInt16 (-32767-1)
X#define maxInt16 32767
X
X#define LoWord(n) ((n) & 0xFFFF)
X#define HiWord(n) ((unsigned long)(n) >> 16)
e-o-f
echo Extracting file.h
sed 's/^X//' > file.h << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * file.h
X *	Stuff for doing file io.
X */
X
X/* creator and file type for document files */
XEXTERN OsType programID IS("XMPL");
XEXTERN OsType documentID IS("XDOC");
X
X/* version code written at the beginning of document files */
X#define versionCode 1
X
X/* application specific io error codes */
X#define badVersionErr -1024
X#define fileTooLongErr -1025
X
X/*
X * Check() and DCheck() are shorthand
X * that allow a function performing file i/o
X * to terminate early with an error return if an error occurs.
X * DCheck() additionally displays an error message
X * using MessageF() if debugging is enabled.
X */
X#define Check(x) {int er = (x); if (er != noErr) return er;}
X
X#ifdef DEBUG
X#	define DCheck(x,msg) {\
X		register int er = (x);\
X		if (er != noErr) {\
X			MessageF("%s: error code %d", msg, er);\
X			return er;\
X		}\
X	}
X#else
X#	define DCheck(x,msg) Check(x)
X#endif
e-o-f
echo Extracting strings.c
sed 's/^X//' > strings.c << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * strings.c
X * Code for dealing with the differences between
X * C strings (null terminated) and Pascal strings
X * (which contain a length byte followed by 0-255 characters).
X */
X
X#include "defs.h"
X
X/*
X * Copy a Pascal string into a buffer, converting it into a C string.
X */
XCPstrcpy(cDestination, pSource)
Xchar *cDestination;
Xchar *pSource;
X{
X	int i;
X
X	for (i = 0; i < pSource[0]; ++i)
X		cDestination[i] = pSource[i + 1];
X	cDestination[i] = '\0';
X}
e-o-f
echo Extracting util.c
sed 's/^X//' > util.c << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * util.c:
X * Globally useful utility routines.
X *
X * SetupUtil() initializes several useful global variables.
X *
X * TrackBoxes() can be used to track the cursor as it is used to
X * activate one of several rectangular control regions.
X *
X * SetControl() can be used to change the range and value of
X * a scroll bar.
X */
X
X#include "defs.h"
X
Xstatic GrafPort _screenPort;
X
XSetupUtil()
X{
X	GrafPtr savePort;
X
X	IBeamCursor = GetCursor(iBeamCursor);
X	CrossCursor = GetCursor(crossCursor);
X	WatchCursor = GetCursor(watchCursor);
X
X	GetPort(&savePort);
X	OpenPort(&_screenPort);
X	screenPort = &_screenPort;
X	SetPort(savePort);
X
X	deskBounds = QD->screenBits.bounds;
X	deskBounds.top += menuBarHeight;
X	InsetRect(&deskBounds, thinMargin, thinMargin);
X}
X
X/*
X * Track the cursor as it is dragged over a group
X * of rectangular control boxes, highlighting the box
X * that the cursor is currently over.
X * Returns a pointer to the box that the cursor is over
X * when the button is released, or NIL if it wasn't on
X * top of any box.
X */
XBox *TrackBoxes(boxes, nBoxes, leaveInverted)
XBox *boxes;
Xint nBoxes;
XBoolean leaveInverted;
X{
X	Box *FindBox();
X	Box *currentBox, *newBox;
X	EventRecord event;
X
X	currentBox = NIL;
X	do {
X		VOID GetNextEvent(mUpMask, &event);
X		GlobalToLocal(&event.where);
X		newBox = FindBox(boxes, nBoxes, &event.where);
X		if (newBox != currentBox) {
X			InvertBox(currentBox);
X			InvertBox(newBox);
X			currentBox = newBox;
X		}
X	} while (event.what != mouseUp);
X	if (!leaveInverted)
X		InvertBox(currentBox);
X	return currentBox;
X}
X
XInvertBox(box)
XBox *box;
X{
X	if (box != NIL)
X		InvertRect((Rect *)box);
X}
X
XBox *FindBox(boxes, nBoxes, point)
XBox *boxes;
Xint nBoxes;
XPoint *point;
X{
X	int i;
X
X	for (i = 0; i < nBoxes; ++i)
X		if (PtInRect(point, (Rect *)&boxes[i]))
X			return &boxes[i];
X	return NIL;
X}
X
X/*
X * The Control Manager has no routine that simply redraws a single
X * control.  If the value and range of a scroll bar change, the
X * 'official' way to do it is to call SetCtlMin(), SetCtlValue(), and
X * SetCtlMax().  This causes the control to be redrawn up to 3 times
X * in succession.  Hence this routine.
X */
XSetControl(control, cMin, cMax, cValue, redraw)
XControlHandle control;
Xint cMin, cMax, cValue, redraw;
X{
X	register ControlPtr c = *control;
X	int changed;
X
X	changed = cMin != c->contrlMin 
X			  || cMax != c->contrlMax
X			  || cValue != c->contrlValue;
X	c->contrlMin = cMin;
X	c->contrlMax = cMax;
X	c->contrlValue = cValue;
X	if (redraw && changed) {
X		/* trick the control manager into redrawing the control */
X		c->contrlVis = FALSE;
X		ShowControl(control);
X	}
X}
e-o-f
echo Extracting fileio.c
sed 's/^X//' > fileio.c << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * fileio.c
X * Utility subroutines for doing file i/o.
X */
X
X#include "defs.h"
X
X/*
X * Simplified interface to SFGetFile.
X */
XGetFile(fType, reply)
XOsType *fType;
XSFReply *reply;
X{
X	Point where;
X
X	where.h = (QD->screenBits.bounds.right - 348) / 2;
X	where.v = (QD->screenBits.bounds.bottom - 136) / 2;
X	SFGetFile(&where, "", (ProcPtr)NIL, 1, (char *)fType, (ProcPtr)NIL, reply);
X}
X
X/*
X * Simplified interface to SFPutFile:
X */
XPutFile(prompt, origName, reply)
Xchar *prompt;
Xchar *origName;
XSFReply *reply;
X{
X	Point where;
X
X	where.h = (QD->screenBits.bounds.right - 304) / 2;
X	where.v = (QD->screenBits.bounds.bottom - 104) / 2;
X	SFPutFile(&where, prompt, origName, (ProcPtr) NIL, reply);
X}
X
X/*
X * Put up a window notifying the user of a file error.
X */
XHandleFileError(err)
Xint err;
X{
X	if (err != noErr) {
X		SetCursor(&QD->arrow);
X		MessageF("File error %d: (press space to continue)", err);
X	}
X}
X
Xint CreateAndOpen(fName, vRefNum, creator, type, refNum)
Xchar *fName;
Xint vRefNum;
XOsType *creator, *type;
Xint *refNum;
X{
X	int err;
X	FInfo fInfo;
X
X	err = Create(fName, vRefNum, (char *)creator, (char *)type);
X	switch (err) {
X	case noErr:
X		return FSOpen(fName, vRefNum, refNum);
X	default:
X		return err;
X	case dupFNErr:
X		DCheck(GetFInfo(fName, vRefNum, &fInfo), "CreateAndOpen: GetFInfo");
X		/*
X		 * The bizzare use of casts to 'long *' in the next 2 lines
X		 * works around a compiler bug.
X		 * p.s.: sizeof(long) == sizeof(OsType) == 4.
X		 */
X		*(long *)&fInfo.fdType = *(long *)type;
X		*(long *)&fInfo.fdCreator = *(long *)creator;
X		DCheck(SetFInfo(fName, vRefNum, &fInfo), "CreateAndOpen: SetFInfo");
X		DCheck(FSOpen(fName, vRefNum, refNum), "CreateAndOpen: FSOpen");
X		return SetEOF(*refNum, (Int32)0);
X	}
X}
X
X/*
X * Simplified interface to FSWrite.
X */
XWrite(fileNum, nBytes, buf)
Xint fileNum, nBytes;
XPtr buf;
X{
X	Int32 count;
X
X	count = nBytes;
X	return FSWrite(fileNum, &count, buf);
X}
X
X/*
X * Simplified interface to FSRead.
X */
XRead(file, nBytes, buf)
Xint file, nBytes;
XPtr buf;
X{
X	Int32 count;
X	count = nBytes;
X	return FSRead(file, &count, buf);
X}
X
X/*
X * Write a 16 bit word.
X */
XWriteWord(n, file)
XInt16 n;
Xint file;
X{
X	return Write(file, sizeof n, (Ptr)&n);
X}
X
X/*
X * Read a 16 bit word.
X */
XReadWord(n, file)
XInt16 *n;
Xint file;
X{
X	return Read(file, sizeof *n, (Ptr)n);
X}
e-o-f
echo Extracting debug.c
sed 's/^X//' > debug.c << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * debug.c
X * Routines for printing debugging messages:
X *
X * MessageF( printf arguments )
X *     Displays a message in the menu bar, and waits.
X *     Click the mouse or press space to continue.
X *
X * CheckHandle( Handle h )
X *     If h is an invalid handle, display a message and return TRUE.
X */
X
X#include "defs.h"
X
X#ifdef DEBUG
X
X/*
X * Display a debugging message in the menu bar.
X * Click the mouse or press space to continue.
X */
XMessage(msg)
Xchar *msg;
X{
X	GrafPtr savePort;
X	Rect bar;
X	EventRecord event;
X	int mouseEvents;
X
X	GetPort(&savePort);
X	SetPort(screenPort);
X	bar.top = 0; bar.left= 18; bar.bottom = 19; bar.right = 490;
X	EraseRect(&bar);
X	MoveTo(18, 15);
X	DrawString(msg);
X	SysBeep(10);
X
X	mouseEvents = 0;
X	for (;;) {
X		VOID GetNextEvent(mUpMask | mDownMask | keyDownMask, &event);
X		if (event.what == keyDown)
X			break;
X		if (event.what == mouseDown || event.what == mouseUp)
X			if (++mouseEvents == 2)
X				break;
X	}
X	DrawMenuBar();
X	SetPort(savePort);
X}
X
Xchar * putCstr(str, bufp)
Xchar *str, *bufp;
X{
X	while (*bufp = *str)
X		++bufp, ++str;
X	return bufp;
X}
X
Xchar * putPstr(str, bufp)
Xchar *str, *bufp;
X{
X	int n, i;
X
X	n = (int)str[0];
X	for (i = 1; i <=n; ++i) {
X		switch (str[i]) {
X		default:
X			*bufp++ = str[i];
X			break;
X		case '\0':
X			bufp = putCstr("\\0", bufp);
X			break;
X		case '\r':
X			bufp = putCstr("\\r", bufp);
X			break;
X		case '\t':
X			bufp = putCstr("\\t", bufp);
X			break;
X		}
X	}
X	return bufp;
X}
X
Xchar * putDnum(num, bufp)
Xint num;
Xchar *bufp;
X{
X	if (num < 0) {
X		*bufp++ = '-';
X		num = -num;
X	}
X	if (num > 9)
X		bufp = putDnum(num / 10, bufp);
X	*bufp++ = '0' + num % 10;
X	return bufp;
X}
X
X/*
X * Like Message, but accepts printf style arguments.
X * Supports the formats:
X *	%d - print a number in decimal
X *	%s - print a C style string (null terminated)
X *	%p - print a Pascal style string
X */
X/*VARARGS1*/
XMessageF(fmt, args)
Xchar *fmt;
Xint args;
X{
X	char buf[512];
X	int *argp;
X	char *fmtp, *bufp;
X
X	argp = &args;
X	fmtp = fmt;
X	bufp = buf;
X
X	for (;;) {
X		switch (*fmtp) {
X		default:
X			*bufp++ = *fmtp++;
X			continue;
X		case '\0':
X			*bufp = '\0';
X			break;
X		case '%':
X			++fmtp;
X			switch (*fmtp) {
X			default:
X				*bufp++ = '%';
X				*bufp++ = *fmtp++;
X				continue;
X			case '\0':
X				*bufp++ = '%';
X				*bufp++ = '\0';
X				break;
X			case 's':
X				++fmtp;
X				bufp = putCstr((char *)*argp++, bufp);
X				continue;
X			case 'p':
X				++fmtp;
X				bufp = putPstr((char *)*argp++, bufp);
X				continue;
X			case 'd':
X				++fmtp;
X				bufp = putDnum(*argp++, bufp);
X				continue;
X			}
X			break;
X		}
X		break;
X	}
X	Message(buf);
X}
X
X/*
X * Check a handle for validity.
X * Display a message and return TRUE if the handle is bad.
X */
XCheckHandle(handle, message)
XHandle handle;
Xchar *message;
X{
X	int size;
X
X	if (handle == NIL) {
X		MessageF("%s: NIL handle", message);
X		return TRUE;
X	}
X	if (*handle == NIL) {
X		MessageF("%s: handle has NIL master pointer", message);
X		return TRUE;
X	}
X	size = GetHandleSize(handle);
X	if (size == 0)
X		MessageF("%s: handle points to zero length block", message);
X	else if (size < 0)
X		MessageF("%s: bad handle", message);
X	else
X		return FALSE;
X	return TRUE;
X}
X
X#endif DEBUG
e-o-f
echo Extracting ram.c
sed 's/^X//' > ram.c << 'e-o-f'
X/*
X * Example: a skeleton Macintosh program for new users of Sumacc
X * Doug Moen, watcgl!kdmoen, 1985
X *
X * ram.c
X * Deal with the Macintosh memory manager.
X *
X * You don't need to modify this file until you become a wizard.
X * This is where code to deal with out-of-memory conditions
X * should be added.
X */
X
X#include "defs.h"
X
X#define maxStackSize 8192	/* max size of stack; the heap gets the rest */
X#define CurStackBase (*(Ptr *)0x908)
X
XSetupRam()
X{
X
X	/* 
X	 * Define a GrowZone function to deal with out-of-memory conditions.
X
X	SetGrowZone(&mygrowzone);
X
X	 */
X
X	/* 
X	 * Place a longint -1 (an odd and therefore illegal address) in the
X	 * memory location that would be referenced by an accidentally-NULL
X	 * handle, so the error will be caught at handle-reference time (as
X	 * an Address error, ID=02) instead of later on.
X	 *
X	 * This doesn't sound very safe -- doug
X
X	(*(Ptr *)NIL) = -1;
X
X	 */
X
X	/* 
X	 * If you needed to use an Application heap limit other than the
X	 * default (which allows 8K for the stack), you'd set it here,
X	 * possible using this technique of explicitly specifying the maximum
X	 * stack size and allocating the rest to the heap.  Should be
X	 * independent of memory size.
X	 */
X	SetApplLimit(CurStackBase - maxStackSize);
X
X	/* 
X	 * Expand the application heap zone to its maximum size, without
X	 * purging any purgeable resources.  This saves memory compactions
X	 * and heap expansions later.
X	 */
X	MaxApplZone();
X
X	/* 
X	 * Get plenty of master pointers now.  If we let the Memory Manager
X	 * allocate them as needed, they'd form non-relocatable islands in
X	 * the heap.
X	 */
X	VOID MoreMasters();
X	VOID MoreMasters();
X	VOID MoreMasters();
X
X	/* 
X	 * Here you might install bulwarks against running out of memory
X	 * unexpectedly.  One such (cheesy) technique is to here allocate
X	 * a large handle, call it "CheeseBuf", which you can de-allocate
X	 * in your GrowZone function, when you must obtain more memory to
X	 * avoid a crash.  While de-allocated, the program could prevent
X	 * the user from doing anything requiring memory, and tell him he
X	 * must discard windows or some such memory freeing action. Each
X	 * time he does so, the program can try to re-allocate CheeseBuf;
X	 * if it succeeds, the user can go on doing memory-eating operations.
X	 */
X}
e-o-f
exit 0