[mod.mac.sources] Moire 3.1 sources

macintosh@felix.UUCP (02/10/87)

[Moire 3.1 sources]

Here are the source files for Moire 3.1.  It is interesting as an example
program since:

	- it does lots of quickdraw stuff
	- it handles menus and multiple windows
	- it can toggle between full screen and regular window display
	- it handles multiple modeless dialogs
	- it does some file i/o.

All simple stuff if you are already a mac hacker - but it took me a while
to learn it.

The biggest difference with Moire 3.0 is that documents are
double-clickable.  I would like to automatically create a unique icon
for each document (from the moire window) instead of having the same
icon for all moire documents.  Has anyone tried anything like this?  My
guess is that the program will have to create bundle and FREF resources
for each document. (Follow up to comp.mac.sys)

Also, acceleration is fixed, rounded rectangles are more rounded, and
the variance may vary more.  A hidden feature is that when you hold the
mouse button down in the Moire window, the trail length will shrink to
zero so that you can take a snap shot of it - with the cursor obscured.
Send me nice pictures - I have no printer.

Lots of people want Moire to be a DA or an automatic idle program.
It's getting a little big for that sort of thing, but I'm working on it.
DAs are allowed only one menu, hence the modeless dialogs.  I also
plan to put all the options in one window with iconic representations.

If you wish to post Moire to other places, you might want to mail to me
first to get the latest version.  Thanks.


Dan LaLiberte
liberte@b.cs.uiuc.edu
liberte@uiuc.csnet
ihnp4!uiucdcs!liberte

---
#! /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.
# The following files will be created:
#	Moire_main
#	Moire_globals
#	Moire_utilities
#	Moire_init
#	Moire_interface
#	Moire_routines
#	Moire_general
#	Moire.R.text
# This archive created: Wed Jan 14 00:37:58 1987
export PATH; PATH=/bin:$PATH
if test -f 'Moire_main'
then
	echo shar: over-writing existing file "'Moire_main'"
fi
cat << \SHAR_EOF > 'Moire_main'
PROGRAM Moire;

{ Copyright (C) 1987 by Daniel LaLiberte }

{ Moire displays various patterns named after some French guy.}

{  Moire owes its existence to a simple program I found originally }
{  on a 3B2 5620.  There are also several other such bouncy, zoomy demo}
{  programs for the Macintosh.  I used the TML Pascal window demo program. }

{  This program is free.  As compensation, please send ideas for }
{  improvements and report problems you have experienced. }
{  To get the latest version of the source on disk send $10 and tell me }
{  which version you have (so I dont send you the same one).   }
{  Feel free to modify the source and port it to other machines, }
{  but keep these comments if you use a substantial part of it. }

{  Daniel LaLiberte	liberte@uiucdcs  }
{  Department of Computer Science  }
{  University of Illinois, Urbana-Champaign  }
{  1304 W Springfield Ave  }
{  Urbana IL  61801  }

{  Pascal source files }
	{ Moire Globals - used by most every unit }
	{ Moire Utilities - moire specific utilities }
	{ Moire Init - moire initialization, reading and writing of parameters }
	{ Moire Interface - menus and dialogs }
	{ Moire Routines - the real thing - everything else is fluff }
	{ Moire General - macintosh initialization, event loop, event handlers }

{  Resoures:		Moire.R }
	{ includes an application icon which must be bundled manually }
	{ includes all menus, dialogs and windows }
	{ should include the default settings so they could be changed }


{ Modification history:}
{	Version 1 was written in Rascal. }
{	Version 2 was written in TML Pascal. }
{	Version 2.1 was written in Lightspeed Pascal. }
{	Version 3.0}
{		generalized mode specification.}
{		changed object and option menus to modeless dialog boxes}
{			in preparation for DA version.}
{		added reflection.}
{	Version 3.1}
{		fixed round rectangles. }
{		fixed acceleration so it doesnt get lost in the corner }
{		cleaned up source for distribution. }
{		cursor obscuring is now sensitive to the frontwindow }
{		no refresh when there is no change in variance }
{		set creator of parameter file; startup with user selected document }

	USES
		Moire_general;

BEGIN
	InitThings;
	SetUpThings;
	MainEventLoop;
	CloseThings;
END.
SHAR_EOF
if test -f 'Moire_globals'
then
	echo shar: over-writing existing file "'Moire_globals'"
fi
cat << \SHAR_EOF > 'Moire_globals'
UNIT Moire_globals;

INTERFACE

	CONST
		version = 3.1;

	{menu stuff}
		AppleMenu = 256;
		FileMenu = 257;
		EditMenu = 258;
		MoireMenuID = 1000;

	{window IDs}
		MoireWindowID = 256;
		ObjectsDialogID = 128;
		ControlDialogID = 129;
		ModeDialogID = 130;

		firstObj2 = 11;	{ The item number of the first Object 2 }
		NumPatterns = 10;		{ Number of patterns, black to white }


	TYPE

		movingpoint = RECORD
				CASE boolean OF
					True : (
							y : integer;	{ may be used as point }
							x : integer;
							vy : integer;	{ velocity }
							vx : integer
					);
					False : (
							p : Point;
							v : Point
					)
			END;

		PointSet = ARRAY[0..9] OF movingpoint;


	VAR
	{general mac interface stuff}

		Finished : Boolean;			{used to terminate the program}
		ClockCursor : CursHandle;	{handle to the waiting watch cursor}

	{Screen stuff}
		DragArea : Rect;		{holds the area where window can be dragged in}
		GrowArea : Rect;	{holds the area to which a window's size can change}

	{Window stuff}
		MoireWindow : WindowPtr;
		MoireRect : Rect;	{ redundant with MoireWindow^.portRect }

		ObjectsDialog : DialogPtr;
		ControlDialog : DialogPtr;
		ModeDialog : DialogPtr;

		LengthScrollBar : ControlHandle;	{ not used yet }
		VarianceScrollBar : ControlHandle;	{ not used yet }

		OldPortRect : Rect;		{ for full screen option, remember old port }


	{Menu stuff}
		MoireMenu : MenuHandle;

{ Moire vars }
		head : PointSet;		{ leading edge of drawing }
		tail : PointSet;		{ trailing edge }

		Object1Num, Object2Num : integer; { which objects are being drawn }
		obj2 : integer;			{ offset in PointSet for obj2 }

		lowx, lowy, highx, highy : integer; { window boundaries - redundant, but faster? }
		width, height, midx, midy : integer;	{ of window boundaries }


		background : Pattern;
{mode : array[0..1] of integer;	{ mode[0] for head; [1] for tail }
		lastheadmode, lasttailmode : integer;		{ redundant with mode array }

		isFullScreen : Boolean;
		isBlackBackground : Boolean;

		tail_length : integer;			{ desired length of tail }
		current_length : integer;	{ what the length is currently }
		variance : integer;			{ how much do things vary }
		doAccel : Boolean;		{ flag for acceleration }
		isPolar : Boolean;		{ flag for polar conversion }
		reflect : ARRAY[0..3] OF Boolean;  { flags for each reflection }

		vary_pensize : Boolean;		{ true if pen size is variable }
		currentPenSize : point;					{ current pen size }

		vary_pattern : Boolean;		{ true if pen pattern is variable }
		PatList : ARRAY[1..numPatterns] OF Pattern;		{ selected standard patterns }
		currentPat : 1..numPatterns;		{ index into PatList }

		isPainted : Boolean;		{ flag for Painting objects }

IMPLEMENTATION

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

UNIT Moire_utilities;

INTERFACE

	USES
		Moire_globals;

	PROCEDURE copyPointSet (VAR f1, f2 : PointSet);

	PROCEDURE InvertWindow;
	PROCEDURE IncludeMenuBar;
	PROCEDURE RefreshMoire;
	PROCEDURE SetBounds;

	PROCEDURE AboutMoire;

	PROCEDURE OldWindow;
	PROCEDURE FullScreen;


IMPLEMENTATION


	PROCEDURE ReadParameters;
	external;	{ In Moire Init }

	PROCEDURE WriteParameters;
	external;	{ In Moire Init }



	PROCEDURE copyPointSet;
{    (    var    f1, f2 : PointSet    );    }
{ copy PointSet f1 to f2 }
		VAR
			i : integer;
	BEGIN

		FOR i := 0 TO 9 DO
			BEGIN
				f1[i] := f2[i];
			END;
	END;


	PROCEDURE InvertWindow;
	{ Invert the Moire window and the background pattern }
		VAR
			savePort : WindowPtr;
	BEGIN
		getPort(savePort);
		setPort(MoireWindow);

		isBlackBackground := NOT isBlackBackground;
		IF isBlackBackground THEN
			StuffHex(@background, 'FFFFFFFFFFFFFFFF') { black }
		ELSE
			StuffHex(@background, '0000000000000000'); { white }

		BackPat(background);
		InvertRect(MoireWindow^.portrect);

		setPort(savePort);
	END;


	PROCEDURE IncludeMenuBar;
	{ with Full Screen active, include the menu bar in the window }
		VAR
			TheMenu : ^integer;	{ Currently highlighted menu }
			MenuRect : Rect;
			MenuRgn : RgnHandle;
			savePort : WindowPtr;
	BEGIN
		getPort(savePort);
		setPort(MoireWindow);

		IF isFullScreen THEN
			BEGIN
		{ avoid unhighlighting menu selection }
				TheMenu := Pointer($A26);
				TheMenu^ := 0;

		{ "or" in the menu area into the visible region of MoireWindow }
				SetRect(MenuRect, 0, 0, screenBits.bounds.right, 20);
				GlobalToLocal(MenuRect.topLeft);
				GlobalToLocal(MenuRect.botRight);
				MenuRgn := NewRgn;
				RectRgn(MenuRgn, MenuRect);

				WITH MoireWindow^ DO
					UnionRgn(VisRgn, MenuRgn, VisRgn);
				DisposeRgn(MenuRgn);
			END;

		setPort(savePort);
	END;


	PROCEDURE RefreshMoire;
{ display a Refreshed Moire window by copying the PointSet tail to the head }
		VAR
			savePort : WindowPtr;
	BEGIN
		getPort(savePort);
		setPort(MoireWindow);

		IncludeMenuBar;

		BackPat(background);
		EraseRect(MoireWindow^.portrect);
		current_length := 0;  { nothing shown }
		copyPointSet(tail, head);

		setPort(savePort);
	END;


	PROCEDURE SetBounds;
{ set the bounds based on the Moire window and change its origin }
		VAR
			savePort : WindowPtr;
	BEGIN
		getPort(savePort);
		setPort(MoireWindow);

		WITH MoireWindow^.portRect DO
			BEGIN
				midx := (right - left) DIV 2;
				midy := (bottom - top) DIV 2;
				setOrigin(-midx, -midy);

				lowy := top;
				lowx := left;
				highy := bottom;
				highx := right;

				width := highx - lowx;
				height := highy - lowy;
				midx := (right - left) DIV 2;
				midy := (bottom - top) DIV 2;
			END;

		RefreshMoire;		{ since bounds have changed }
		setPort(savePort);
	END;



	PROCEDURE AboutMoire;
		CONST
			AboutID = 1000;
		VAR
			ignore : Integer;
	BEGIN
		ignore := Alert(AboutID, NIL);
	END;



	PROCEDURE OldWindow;
{ set the Moire Window to the old window size }
	BEGIN
		isFullScreen := False;

		HideWindow(MoireWindow); { to hide moving/sizing mess }
		WITH OldPortRect DO
			BEGIN
				MoveWindow(MoireWindow, left, top, True);
				SizeWindow(MoireWindow, right - left, bottom - top, True);
			END;
		ShowWindow(MoireWindow);

		SetBounds;
		DrawMenuBar;
	END;


	PROCEDURE FullScreen;
{ remember the old Moire Window port size and position and change to the full screen }
		VAR
			savePort : WindowPtr;
	BEGIN
		getPort(savePort);
		setPort(MoireWindow);

		isFullScreen := True;

		OldPortRect := MoireWindow^.portRect;

		WITH OldPortRect DO
			BEGIN
				LocalToGlobal(topLeft);
				LocalToGlobal(botRight);
			END;

	{ The following Size and Move commands are needed to obscure other windows. }
		HideWindow(MoireWindow);
		WITH ScreenBits.bounds DO
			BEGIN
				SizeWindow(MoireWindow, right, bottom, True);
				MoveWindow(MoireWindow, left, top, True);
			END;
		ShowWindow(MoireWindow);

		SetBounds;
		setPort(savePort);
	END;


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

UNIT Moire_init;
INTERFACE

	USES
		Moire_globals, Moire_utilities;

	PROCEDURE StartOver;
	PROCEDURE SetupMoireMenus;
	PROCEDURE SetUpMoire;

	PROCEDURE ReadParameters;
	PROCEDURE WriteParameters;


IMPLEMENTATION

	{ the following are in Moire Interface }
	PROCEDURE ShowObjectsDialogSettings (Flag : Boolean);
	external;
	PROCEDURE ShowControlDialogSettings;
	external;
	PROCEDURE ShowModeDialogSettings (Flag : Boolean);
	external;


	PROCEDURE SetupMoireMenus;
	BEGIN
		MoireMenu := GetMenu(MoireMenuID);
		InsertMenu(MoireMenu, 0);

	{ Dialogs must be nil when not opened - so we don't try to change the items }
		ObjectsDialog := NIL;
		ControlDialog := NIL;
		ModeDialog := NIL;
	END;


	PROCEDURE StartingPoints;

		PROCEDURE initpoint (pointnum, xinit, yinit, vxinit, vyinit : integer);
		BEGIN
			head[pointnum].x := xinit;
			head[pointnum].y := yinit;
			head[pointnum].vx := vxinit;
			head[pointnum].vy := vyinit;
		END;

	BEGIN

		initpoint(0, lowx, lowy, 2, 3);
		initpoint(1, lowx, highy, 1, -2);
		initpoint(2, highx, lowy, -3, 1);
		initpoint(3, highx, highy, -2, -2);
		initpoint(4, trunc((highx - lowx) / 2), trunc((highy - lowy) / 2), 1, 1);  { pensize }

	{ for accelleration }
		initpoint(5, lowx, lowy + 1, 1, 4);
		initpoint(6, lowx, highy - 1, 2, -3);
		initpoint(7, highx, lowy + 1, -1, 2);
		initpoint(8, highx, highy - 1, -1, -4);
		initpoint(9, trunc((highx - lowx) / 2), trunc((highy - lowy) / 2), 2, 3);  { pensize }

	END;


	PROCEDURE StartOver;
		VAR
			savePort : WindowPtr;

	BEGIN
		{ Erase old settings }
		ShowObjectsDialogSettings(False);
		ShowModeDialogSettings(False);

		getPort(savePort);
		setPort(MoireWindow);

		currentPat := numPatterns;	{ black }
		PenPat(PatList[currentPat]);
		vary_pattern := False;

		lastheadmode := srcXor;		{ used as index into Mode dialog items }
		lasttailmode := srcXor;

		object1Num := 2;  { default one segment }
		object2Num := firstObj2;  { none }

		tail_length := 64;
		current_length := 0; { initially nothing drawn }
		variance := 5;
		vary_pensize := False;
		currentPenSize.h := 1;
		currentPenSize.v := 1;
		PenSize(currentPenSize.h, currentPenSize.v);

		isPainted := False;
		doAccel := False;
		isPolar := False;
		reflect[0] := False;
		reflect[1] := False;
		reflect[2] := False;
		reflect[3] := False;

		IF isFullScreen THEN
			OldWindow;
		isFullScreen := False;
		isBlackBackground := True;
		StuffHex(@background, 'FFFFFFFFFFFFFFFF'); { black }

		SetBounds;
		StartingPoints;
		RefreshMoire;

		ShowObjectsDialogSettings(True);
		ShowControlDialogSettings;
		ShowModeDialogSettings(True);
	END;


	PROCEDURE readParamFile (name : STRING);
	forward;	{ it's the next one down }


	PROCEDURE SetUpMoire;
		LABEL
			321;
		VAR
			mess, count : integer;
			theFile : AppFile;
	BEGIN

{ Initialize the patterns from the system resource file }

		getIndPattern(patList[1], SysPatListID, 20);		{ white }
		getIndPattern(patList[2], SysPatListID, 13);
		getIndPattern(patList[3], SysPatListID, 21);
		getIndPattern(patList[4], SysPatListID, 22);
		getIndPattern(patList[5], SysPatListID, 23);
		getIndPattern(patList[6], SysPatListID, 4);
		getIndPattern(patList[7], SysPatListID, 3);
		getIndPattern(patList[8], SysPatListID, 2);
		StuffHex(@patList[9], '7FFFFFFFFFFFFFFF');
		getIndPattern(patList[10], SysPatListID, 1);		{ black }

		isFullScreen := False;

		StartOver;	{ this is redundant if cout > 0 below }

		CountAppFiles(mess, count);
		IF count > 0 THEN
			BEGIN
				GetAppFiles(1, theFile);
				IF SetVol(NIL, theFile.vRefNum) <> NoErr THEN
					GOTO 321;

				ReadParamFile(theFile.fName);

				ClrAppFiles(1);
			END;
321 :	{ exit for errors }

	END;


	PROCEDURE readParamFile;{ (name : string)}
		VAR
			paramFile : Text;
			readVersion : real;		{ the version read from the data file }
			newIsFullScreen, newIsBlackBackground : Boolean;

	BEGIN

		open(paramFile, name);

		{ Erase old settings }
		ShowObjectsDialogSettings(False);
		ShowModeDialogSettings(False);

		read(paramfile, readVersion);	{ For future versions, need to know about old files }
		{ Should test here if the file is a valid moire file.  }

		read(paramfile, newIsFullScreen, newIsBlackBackground);
		IF (newIsFullScreen <> isFullScreen) THEN
			IF newIsFullScreen THEN
				FullScreen
			ELSE
				OldWindow;
		isFullScreen := newIsFullScreen;

		IF (newIsBlackBackground <> isBlackBackground) THEN
			InvertWindow;

		read(paramfile, object1Num, object2Num);
		read(paramfile, tail_length, variance, doAccel, isPolar);
		read(paramfile, vary_pensize, currentPenSize.h, vary_pattern, currentPat, isPainted);

		currentPenSize.v := currentPenSize.h;
		pensize(currentPenSize.h, currentPenSize.v);
		penPat(PatList[currentPat]);

		read(paramfile, reflect[0], reflect[1], reflect[2], reflect[3]);
		read(paramfile, lastheadmode, lasttailmode);

		close(paramfile);

		ShowObjectsDialogSettings(True);
		ShowControlDialogSettings;
		ShowModeDialogSettings(True);

		RefreshMoire;
	END;


	PROCEDURE ReadParameters;
		VAR
			name : STRING;
	BEGIN
		name := OldFileName('Open Moire Parameter File');

		IF name <> '' THEN
			readParamFile(name);
	END;


	PROCEDURE WriteParameters;
		LABEL
			321;
		VAR
			paramfile : Text;
			name : STRING;
			finderInfo : Finfo;
			vName : STRING;
			vRefNum : integer;
	BEGIN
		name := NewFileName('Save Moire Parameter File');

		IF name <> '' THEN
			BEGIN
				open(paramfile, name);

		{ get the volume Reference number }
				IF GetVol(@vName, vRefNum) <> NoErr THEN
					GOTO 321;

		{ set up the finder info }
				IF GetFInfo(name, vRefNum, finderInfo) <> NoErr THEN
					GOTO 321;
				finderInfo.fdCreator := 'MOIR';
				IF SetFInfo(name, vRefNum, finderinfo) <> NoErr THEN
					GOTO 321;

				writeln(paramfile, version);
				writeln(paramfile, isFullScreen, ' ', isBlackBackground);
				writeln(paramfile, object1Num, ' ', object2Num);

				writeln(paramfile, tail_length, ' ', variance, ' ', doAccel, ' ', isPolar);
				writeln(paramfile, vary_pensize, ' ', currentPenSize.h, ' ', vary_pattern, ' ', CurrentPat, ' ', isPainted);
				writeln(paramfile, reflect[0], ' ', reflect[1], ' ', reflect[2], ' ', reflect[3]);

				writeln(paramfile, lastheadmode, ' ', lasttailmode);

				writeln(paramfile);
				close(paramfile);
			END;

321 :	{ label for error exit }

	END;


END.
SHAR_EOF
if test -f 'Moire_interface'
then
	echo shar: over-writing existing file "'Moire_interface'"
fi
cat << \SHAR_EOF > 'Moire_interface'
UNIT Moire_interface;

INTERFACE

	USES
		Moire_globals, Moire_utilities, Moire_init;

	PROCEDURE ShowObjectsDialogSettings (Flag : Boolean);
	PROCEDURE ShowControlDialogSettings;
	PROCEDURE ShowModeDialogSettings (Flag : Boolean);

	PROCEDURE DoObjectsDialogEvent (itemNumber : integer);
	PROCEDURE DoControlDialogEvent (itemNumber : integer);
	PROCEDURE DoModeDialogEvent (itemNumber : integer);

	PROCEDURE DoMoireMenu (menuid, menuitem : integer);


IMPLEMENTATION

	TYPE
		ControlItem = (iZero, iLength, iVariance, iAccelerate, iPolarizer, iPaintObject, iVaryPen, iVaryPat, iReflectH, iReflectV, iReflectF, iReflectR);

	VAR
		LengthHandle, VarianceHandle : Handle;	{ should be global }


{ -------------------------------------------------------- }
{ The following are some utilities for dialog management }

	PROCEDURE ActivateDialog (theDialog : dialogPtr);
	BEGIN
		SelectWindow(theDialog);
		ShowWindow(theDialog);
		DrawDialog(theDialog);
	END;


	PROCEDURE CheckDItem (theDialog : dialogPtr;
									itemNumber : integer;
									check : Boolean);
	{ set the itemNumber value of theDialog to check }
		VAR
			itemType : integer;
			item : Handle;
			box : Rect;
	BEGIN
		getDItem(theDialog, itemNumber, itemType, item, box);
		setCtlValue(ControlHandle(item), ord(check));
	END;



	FUNCTION getItemHandle (dPtr : DialogPtr;
									item : integer) : Handle;
		VAR
			itemNumber : integer;
			itemType : integer;
			itemHandle : Handle;
			dispRect : Rect;
	BEGIN
		getDItem(dPtr, item, itemType, itemHandle, dispRect);
		getItemHandle := itemHandle;
	END;



	PROCEDURE setINum (itemHandle : Handle;
									num : longint);
		VAR
			str : str255;
	BEGIN
		NumToString(num, str);
		setIText(itemHandle, str);
	END;


{ -------------------------------------------------------------- }

	PROCEDURE ShowObjectsDialogSettings; {(Flag : Boolean)}
	{ show or erase the settings for the object dialog }
	BEGIN
		IF ObjectsDialog <> NIL THEN
			BEGIN
				CheckDItem(ObjectsDialog, object1Num, Flag);
				CheckDItem(ObjectsDialog, object2Num, Flag);
			END;
	END;


	PROCEDURE DoObjectsDialogEvent; {(itemNumber : integer)}

	BEGIN

		ShowObjectsDialogSettings(False);
		IF itemNumber < firstObj2 THEN
			object1Num := itemNumber
		ELSE
			object2Num := itemNumber;
		ShowObjectsDialogSettings(True);

		RefreshMoire;
	END;


{ -------------------------------------------------------------- }

	PROCEDURE ShowControlDialogSettings;
	{ No Flag is needed here since all the settings are explicit }
	BEGIN
		IF ControlDialog <> NIL THEN
			BEGIN
				SetINum(LengthHandle, tail_length);
				SetINum(VarianceHandle, variance);
				CheckDItem(ControlDialog, ord(iAccelerate), doAccel);
				CheckDItem(ControlDialog, ord(iPolarizer), isPolar);
				CheckDItem(ControlDialog, ord(iPaintObject), isPainted);
				CheckDItem(ControlDialog, ord(iVaryPen), vary_pensize);
				CheckDItem(ControlDialog, ord(iVaryPat), vary_pattern);
				checkDItem(ControlDialog, ord(iReflectH), reflect[0]);
				checkDItem(ControlDialog, ord(iReflectV), reflect[1]);
				checkDItem(ControlDialog, ord(iReflectF), reflect[2]);
				checkDItem(ControlDialog, ord(iReflectR), reflect[3]);
			END;
	END;


	PROCEDURE HandleLengthScroll;
{ well, it doesnt scroll yet, but that's the plan - hints appreciated. }
		VAR
			str : str255;
			num : longint;
	BEGIN
		GetIText(LengthHandle, str);
		StringToNum(str, num);

		IF (num > 1024) THEN
			num := 1024;
		IF (num < 1) THEN
			num := 1;
		tail_length := num;

		SetINum(LengthHandle, tail_length);
	END;


	PROCEDURE HandleVarianceScroll;
		CONST
			maxVariance = 64;
		VAR
			str : str255;
			num : longint;
	BEGIN
		GetIText(VarianceHandle, str);
		StringToNum(str, num);

		IF (num > maxVariance) THEN
			num := maxVariance;
		IF (num < 1) THEN
			num := 1;

		IF num <> variance THEN
			RefreshMoire;

		variance := num;
		SetINum(VarianceHandle, variance);
	END;



	PROCEDURE ScrollAction (whichControl : ControlHandle;
									theCode : INTEGER);
		VAR
			inc : integer;
	BEGIN

		CASE theCode OF
			inUpButton : 
				inc := -10;
			inDownButton : 
				inc := 10;
			inPageUP : 
				inc := -10;
			inPageDown : 
				inc := 10;
			inThumb : 
		END;
		SetCtlValue(whichControl, GetCtlValue(whichControl) + inc);

	END;



	PROCEDURE DoControlDialogEvent; {(itemNumber : integer)}
		VAR
			i : integer;
	BEGIN

		CASE ControlItem(itemNumber) OF

			ilength : 
				HandleLengthScroll;

			iVariance : 
				HandleVarianceScroll;

			iAccelerate : 
				BEGIN
					doAccel := NOT doAccel;
					CheckDItem(ControlDialog, itemNumber, doAccel);
				END;

			iPolarizer : 
				BEGIN
					isPolar := NOT isPolar;
					CheckDItem(ControlDialog, itemNumber, isPolar);
				END;

			iPaintObject : 
				BEGIN
					isPainted := NOT isPainted;  { toggle }
					CheckDItem(ControlDialog, itemNumber, isPainted);
				END;

			iVaryPen : 
				BEGIN
					vary_pensize := NOT vary_pensize;
					CheckDItem(ControlDialog, itemNumber, vary_pensize);  { check }
  { for fun, leave pensize as is - use Start Over to get back to pensize 1,1 }
{ need to set port to MoireWindow }
{currentPenSize.h := 1;}
{currentPenSize.v := 1;}
{pensize(currentPenSize.h, currentPenSize.v);}
				END;

			iVaryPat : 
				BEGIN
					vary_pattern := NOT vary_pattern;
					CheckDItem(ControlDialog, itemNumber, vary_pattern);  { check }
{ I don't know how much fun this is, but leave pattern as is. }
{ reset to black }
{currentPat := numPatterns;}
{penPat(PatList[currentPat]);}
				END;

			iReflectH, iReflectV, iReflectF, iReflectR : 
				BEGIN
					i := itemNumber - ord(iReflectH);
					reflect[i] := NOT reflect[i];
					checkDItem(ControlDialog, itemNumber, reflect[i]);
				END;

		END;	{ case }

{ Length changes do not "need" a Refresh and the variance may not have changed. }
		IF itemNumber > ord(iVariance) THEN
			RefreshMoire;
	END;


{ -------------------------------------------------------------- }

	PROCEDURE ShowModeDialogSettings; {(Flag : Boolean)}
	BEGIN
		IF ModeDialog <> NIL THEN
			BEGIN
			{ first 9 items are for the head, next 9 items are for the tail }
				CheckDItem(ModeDialog, lastheadmode + 1, Flag);
				CheckDItem(ModeDialog, lasttailmode + 1 + 9, Flag);
			END;
	END;


	PROCEDURE DoModeDialogEvent;{ (itemNumber : integer)}
	BEGIN

		ShowModeDialogSettings(False);
		IF itemNumber <= 9 THEN	{ leading }
			lastheadmode := itemNumber - 1
		ELSE 	{ trailing }
			lasttailmode := itemNumber - 1 - 9;
		ShowModeDialogSettings(True);

		RefreshMoire;
	END;  { DoModeDialog }


{ -------------------------------------------------------------- }

	PROCEDURE DoMoireMenu;
	{ includes File and Edit menus for convenience }
		TYPE
			mItem = (iZero, iStartOver, iFullScreen, iRefresh, iInvert, inothing, iObjects, iControl, iMode);

	BEGIN { MoireMenu }

		CASE menuid OF

			FileMenu : 
				BEGIN
					CASE menuItem OF
						1 : 
							ReadParameters;
						2 : 
							WriteParameters;
						3 : 
							Finished := True;          {quit}
					END;
				END;

			EditMenu : 
				BEGIN
					IF NOT SystemEdit(menuItem - 1) THEN {if not for a desk accessory}
						;	{ Do I need to do anything more here? }
				END;

			MoireMenuID : 
				CASE mItem(menuitem) OF

					iStartOver : 
						StartOver;

					iFullScreen : 
						IF (isFullScreen) THEN
							BEGIN
								OldWindow;
								SetItem(MoireMenu, ord(iFullScreen), 'Full Screen');
							END

						ELSE
							BEGIN
								FullScreen;
								SetItem(MoireMenu, ord(iFullScreen), 'Old Window');
							END;

					iRefresh : 
						RefreshMoire;

					iInvert : 
						InvertWindow;

					iObjects : 
						IF ObjectsDialog = NIL THEN
							BEGIN
								ObjectsDialog := GetNewDialog(ObjectsDialogID, NIL, POINTER(-1));
								ShowObjectsDialogSettings(True);
							END
						ELSE
							ActivateDialog(ObjectsDialog);

					iControl : 
						IF ControlDialog = NIL THEN
							BEGIN
								ControlDialog := GetNewDialog(ControlDialogID, NIL, POINTER(-1));
								LengthHandle := getItemHandle(ControlDialog, 1);
								VarianceHandle := getItemHandle(ControlDialog, 2);
								ShowControlDialogSettings;
							END
						ELSE
							ActivateDialog(ControlDialog);

					iMode : 
						IF ModeDialog = NIL THEN
							BEGIN
								ModeDialog := GetNewDialog(ModeDialogID, NIL, POINTER(-1));
								ShowModeDialogSettings(True);
							END
						ELSE
							ActivateDialog(ModeDialog);

				END; { WindowMenu case }

		END; { case }
	END;

END.
SHAR_EOF
if test -f 'Moire_routines'
then
	echo shar: over-writing existing file "'Moire_routines'"
fi
cat << \SHAR_EOF > 'Moire_routines'
UNIT Moire_routines;

INTERFACE
	USES
		Moire_globals, Moire_utilities;

	PROCEDURE MoireStep;
	PROCEDURE MoireContent (where : Point);


IMPLEMENTATION

	VAR
		Xsign, Ysign : integer;


	FUNCTION polarize (P : Point) : Point;
{ return P converted into rectangular coordinates}
{	as if it were a polar (r, theta) value }
{ Should use a table lookup to speed things along }
		VAR
			Q : Point;
	BEGIN
		IF isPolar THEN
			BEGIN
				Q.h := trunc(2 * P.v * cos(P.h * 0.03));
				Q.v := trunc(2 * P.v * sin(P.h * 0.03));
				polarize := Q;
			END
		ELSE
			polarize := P
	END;


{ These routines transform the points based on the reflection paramters }

	PROCEDURE moveP (P : Point);
	BEGIN
		moveto(P.h * Xsign - currentPenSize.h * ord(Xsign < 0), P.v * Ysign - currentPenSize.v * ord(Ysign < 0));
	END;


	PROCEDURE lineP (P : Point);
	BEGIN
		lineto(P.h * Xsign - currentPenSize.h * ord(Xsign < 0), P.v * Ysign - currentPenSize.v * ord(Ysign < 0));
	END;


	FUNCTION tranP (P : Point) : Point;
{ transform point p with Xsign and Ysign correcting for pensize }
		VAR
			Q : Point;
	BEGIN
		Q.h := P.h * Xsign - currentPenSize.h * ord(Xsign < 0);
		Q.v := P.v * Ysign - currentPenSize.v * ord(Ysign < 0);
		tranP := Q;
	END;


	FUNCTION tranA (A : integer) : integer;
{ transform the angle A depending on Xsign and Ysign }
	BEGIN
		IF Ysign < 0 THEN
			tranA := 180 - (A * Xsign)
		ELSE
			tranA := A * Xsign;
	END;



{ --------------- objects ----------------- }
	PROCEDURE segment (VAR f : PointSet);
		VAR
			p1, p2 : Point;
	BEGIN
		p1 := polarize(f[0 + obj2].p);
		p2 := polarize(f[1 + obj2].p);
		moveP(p1);
		lineP(p2);
	END;


	PROCEDURE angle (VAR f : PointSet);
	BEGIN
		moveP(f[0].p);
		lineP(f[1].p);
		lineP(f[2].p);
	END;


	PROCEDURE triangle (VAR f : PointSet);
		VAR
			poly : PolyHandle;
	BEGIN
		poly := OpenPoly;
		moveP(f[0].p);
		lineP(f[1].p);
		lineP(f[2].p);
		lineP(f[0].p);
		ClosePoly;
		IF (isPainted) THEN
			PaintPoly(poly)
		ELSE
			FramePoly(poly);
		KillPoly(poly);
	END;


	PROCEDURE quadrangle (VAR f : PointSet);
		VAR
			poly : PolyHandle;
	BEGIN
		poly := OpenPoly;
		moveP(f[0].p);
		lineP(f[1].p);
		lineP(f[2].p);
		lineP(f[3].p);
		lineP(f[0].p);
		ClosePoly;
		IF (isPainted) THEN
			PaintPoly(poly)
		ELSE
			FramePoly(poly);
		KillPoly(poly);
	END;


	PROCEDURE tetrahedron (VAR f : PointSet);
	BEGIN
		moveP(f[0].p);
		lineP(f[1].p);
		lineP(f[2].p);
		lineP(f[3].p);
		lineP(f[0].p);
		lineP(f[2].p);
		moveP(f[3].p);
		lineP(f[1].p);
	END;


	PROCEDURE rectangle (VAR f : PointSet);
		VAR
			r : Rect;
			p1, p2 : Point;
	BEGIN
		p1 := polarize(f[0 + obj2].p);
		p2 := polarize(f[1 + obj2].p);
		Pt2Rect(tranP(p1), tranP(p2), r);
	{ need to correct for the pensize since bottom right is inset by pensize }
		r.botRight := Point(longint(r.botRight) + longint(currentPenSize));
		IF (isPainted) THEN
			Paintrect(r)
		ELSE
			framerect(r);
	END;


	PROCEDURE roundrect (VAR f : PointSet);
		VAR
			r : Rect;
			p1, p2 : Point;
	BEGIN
		p1 := polarize(f[0 + obj2].p);
		p2 := polarize(f[1 + obj2].p);
		Pt2Rect(tranP(p1), tranP(p2), r);
		r.botRight := Point(longint(r.botRight) + longint(currentPenSize));
		IF (isPainted) THEN
			PaintRoundRect(r, f[2 - obj2].x + highx, f[2 - obj2].y + highy)
		ELSE
			FrameRoundRect(r, f[2 - obj2].x + highx, f[2 - obj2].y + highy);
	END;


	PROCEDURE oval (VAR f : PointSet);
		VAR
			r : Rect;
			p1, p2 : Point;
	BEGIN
		p1 := polarize(f[0 + obj2].p);
		p2 := polarize(f[1 + obj2].p);
		Pt2Rect(tranP(p1), tranP(p2), r);
		r.botRight := Point(longint(r.botRight) + longint(currentPenSize));
		IF (isPainted) THEN
			Paintoval(r)
		ELSE
			frameoval(r);
	END;


	PROCEDURE arc (VAR f : PointSet);
		VAR
			r : Rect;
			p1, p2 : Point;
	BEGIN
		p1 := polarize(f[0 + obj2].p);
		p2 := polarize(f[1 + obj2].p);
		Pt2Rect(tranP(p1), tranP(p2), r);
		r.botRight := Point(longint(r.botRight) + longint(currentPenSize));
		IF (isPainted) THEN
			Paintarc(r, tranA(f[2 - obj2].x), f[2 - obj2].y * Xsign * Ysign)
		ELSE
			framearc(r, tranA(f[2 - obj2].x), f[2 - obj2].y * Xsign * Ysign);
	END;



{ ----------------------------------- }

	PROCEDURE drawObject (VAR f : PointSet);
		VAR
			i : integer;
			t : integer;	{ temporary }


{ The next two utilities, incrx and incry, might be combined into one, }
{   but maybe at time expense?  They are used at every step of the drawing. }

		PROCEDURE incrx (i : integer);
{ Increment x which is moving at velocity vx. }
{ If it exceeds lowx or highx (adjusted for pen size),   it is intersecting at y. }
{ If doAccel, a different increment algorithm is used - which has}
{  some bazaar, mysterious side effects. }
			VAR
				t : integer; { temporary }
		BEGIN
			IF doAccel THEN
		{ set velocity between -variance and variance }
				f[i].vx := (f[i + 5].x * variance) DIV highx;

			WITH f[i] DO
				BEGIN

					x := x + vx;

	{ check if bumping edge of window }
					IF (((x >= (highx - currentPenSize.h)) AND (vx > 0)) OR ((x < lowx) AND (vx < 0))) THEN
						BEGIN { passed edge }
							x := x - vx;  { return to original point }

		{ calculate new velocity }
							IF doAccel THEN
								BEGIN
									vx := -vx;
									f[i + 5].x := -f[i + 5].x;
									f[i + 5].vx := f[i + 5].vx * (ord(odd(y)) * 2 - 1);
								END
							ELSE
								BEGIN
									t := (1 + ((i + x + y + vx + variance) MOD (variance + 1)));
									IF (vx > 0) THEN
										t := -t;
									vx := t;
								END;

							x := x + vx;  { off in a new direction }

							IF isFullScreen AND (FrontWindow = WindowPtr(MoireWindow)) THEN
								ObscureCursor;

						END;
				END; { with }
		END;


		PROCEDURE incry (i : integer);
{ Increment y moving at velocity vy. }
{ If it exceeds lowy or highy, it is intersecting at x. }
			VAR
				t : integer; { temporary }
		BEGIN

			IF doAccel THEN
				f[i].vy := (f[i + 5].y * variance) DIV highy;

			WITH f[i] DO
				BEGIN

					y := y + vy;
					IF (((y >= (highy - currentPenSize.v)) AND (vy > 0)) OR ((y <= lowy) AND (vy < 0))) THEN
						BEGIN
							y := y - vy;  { return to original point }

							IF doAccel THEN
								BEGIN
									vy := -vy;
									f[i + 5].y := -f[i + 5].y;
									f[i + 5].vy := f[i + 5].vy * (ord(odd(x)) * 2 - 1);
								END
							ELSE
								BEGIN
									t := (1 + ((i + x + y + vy + variance) MOD variance));
									IF (vy > 0) THEN
										t := -t;
									vy := t;
								END;

							y := y + vy;  { off in a new direction }
		{ ObscureCursor; }
						END;
				END; {with}
		END;


		PROCEDURE ReallyDrawObject;
	{ well not really since this calls the object drawer which calls the toolbox routines }
		BEGIN
			obj2 := 0;
			CASE object1Num - 1 OF
				0 : 
					; {none}
				1 : 
					segment(f);
				2 : 
					rectangle(f);
				3 : 
					roundrect(f);
				4 : 
					oval(f);
				5 : 
					arc(f);
				6 : 
					angle(f);
				7 : 
					triangle(f);
				8 : 
					quadrangle(f);
				9 : 
					tetrahedron(f);
			END;

			obj2 := 2;	{ amount to offset in PointSet so that the same routines may be used }
			CASE object2Num - firstObj2 OF
				0 : 
					;	{ none }
				1 : 
					segment(f);
				2 : 
					rectangle(f);
				3 : 
					roundrect(f);
				4 : 
					oval(f);
				5 : 
					arc(f);
			END;
		END;


	BEGIN { drawObject }

		IF (vary_pensize) THEN
			BEGIN { calculate pen size }
				currentPenSize.h := 1 + abs((f[4].x + highx) * variance) DIV width;
				currentPenSize.v := currentPenSize.h; { square pen for now }
				pensize(currentPenSize.h, currentPenSize.v);
			END;

		IF (vary_pattern) THEN
			BEGIN
				currentPat := 1 + ((f[4].y + highy) * numPatterns) DIV height;
				penPat(PatList[currentPat]);
			END;

		Xsign := 1;
		Ysign := 1;
		ReallyDrawObject;

	{ The following draws the reflected objects.}
		{ 0 is horizontal (left-right) }
		{ 1 is vertical (top-bottom) }
		{ 2 is diagonal /}
		{ 3 is diagonal \}
	{ To give more variety, the diagonal reflection is not complete }

		Xsign := -1;
		IF reflect[0] THEN { or (reflect[1] and reflect[2] and reflect[3]) }
			ReallyDrawObject;

		Ysign := -1;
		IF (reflect[0] AND reflect[1]) OR ((NOT reflect[0]) AND (NOT reflect[1]) AND reflect[2] AND reflect[3]) THEN
			ReallyDrawObject;

		Xsign := 1;
		IF reflect[1] THEN {or (reflect[0] and reflect[2] and reflect[3]) }
			ReallyDrawObject;


		IF reflect[2] OR reflect[3] THEN
			BEGIN

		{ swap X and Y for diagonal reflections }
				FOR i := 0 TO 4 DO
					WITH f[i] DO
						BEGIN
							t := x;
							x := y;
							y := t;
						END;

				Xsign := 1;
				Ysign := 1;

				IF reflect[3] OR (reflect[0] AND reflect[1] AND reflect[2]) THEN
					ReallyDrawObject;

				Ysign := -1;
				IF (reflect[0] AND reflect[2]) OR (reflect[1] AND reflect[3]) THEN
					ReallyDrawObject;

				Xsign := -1;
				IF reflect[2] OR (reflect[0] AND reflect[1] AND reflect[3]) THEN
					ReallyDrawObject;

				Ysign := 1;
				IF (reflect[0] AND reflect[3]) OR (reflect[1] AND reflect[2]) THEN
					ReallyDrawObject;

		{ restore X and Y }
				FOR i := 0 TO 4 DO
					WITH f[i] DO
						BEGIN
							t := x;
							x := y;
							y := t;
						END;

			END;


	{ increment the points; include 5th point if it is varying }

		FOR i := 0 TO 3 + ord(vary_pensize OR vary_pattern) DO
			BEGIN
				incrx(i);
				incry(i);
			END;

	{ increment the points used for acceleration - if doAccel }

		IF doAccel THEN
			BEGIN
				doAccel := False; { to avoid acceleration of these points }
				FOR i := 5 TO 8 DO { + ord(vary_pensize) }
					BEGIN
						incrx(i);
						incry(i);
					END;
				doAccel := True;
			END;
	END;


	PROCEDURE MoireStep;
{ Do one step of the Moire drawing }
		VAR
			savePort : WindowPtr;
	BEGIN
		GetPort(savePort);
		setPort(MoireWindow);

		IF (current_length < tail_length) THEN
			BEGIN
				penmode(lastHeadMode + 8);	{ add 8 to get the Pattern modes }
				drawObject(head);
				current_length := current_length + 1;
			END;

		IF (current_length >= tail_length) THEN
			BEGIN
				penmode(lastTailMode + 8);
				drawObject(tail);
				current_length := current_length - 1;
			END;

		setPort(savePort);
	END;


	PROCEDURE MoireContent;
	{ Mouse down in the Moire window }
		VAR
			save_length : integer;	{ save the tail_length for restoring later }
	BEGIN
	{ make the tail length shrink to 0 }
		save_length := tail_length;
		tail_length := 0;

		SetCursor(ClockCursor^^);
		WHILE StillDown AND (current_length > 0) DO
			MoireStep;

		WHILE StillDown DO
			ObscureCursor;
		InitCursor;
		ObscureCursor;	{ In case mouse was moved while letting go }

		tail_length := save_length;
	END;

END.
SHAR_EOF
if test -f 'Moire_general'
then
	echo shar: over-writing existing file "'Moire_general'"
fi
cat << \SHAR_EOF > 'Moire_general'
{ General Toolbox handlers - originally from TML window demo }

UNIT Moire_general;

INTERFACE

	USES
		Moire_globals, Moire_init, Moire_utilities, Moire_routines, Moire_interface;

	PROCEDURE InitThings;
	PROCEDURE SetUpThings;
	PROCEDURE MainEventLoop;
	PROCEDURE CloseThings;


IMPLEMENTATION

	PROCEDURE ReSizeWindow (theWindow : WindowPtr;
									MouseLoc : Point);
		VAR
			NewSize : Point;
			Width : Integer;
			Height : Integer;
	BEGIN
		NewSize := Point(GrowWindow(theWindow, MouseLoc, GrowArea));      { grow this window}
       { mouse location  }
      { limits of growth - global var}
		IF longint(NewSize) <> 0 THEN
			BEGIN
				Height := NewSize.v;
				Width := NewSize.h;

      { Update_Scroll_Bar_Areas(theWindow); {erase where the scroll bars WERE}
				InvalRect(theWindow^.portRect);

				IF Height < 40 THEN
					Height := 40; {don't let the window be too small}
				IF Width < 40 THEN
					Width := 40;

      {now set the new size}
				SizeWindow(theWindow, Width, Height, TRUE);   {resize this Window}

				InvalRect(theWindow^.portRect);

				IF theWindow = MoireWindow THEN
					SetBounds;

			END;
	END;

{-------------------------------------------------------------------}

	PROCEDURE ProcessMenu_in (CodeWord : longint);
		VAR
			Menu_No : integer;	{menu number that was selected}
			Item_No : integer;	{item in menu that was selected}
			NameHolder : Str255;		{name holder for desk accessory or font}
			DNA : integer;	{OpenDA will never return 0, so don't care}

	BEGIN
		IF CodeWord <> 0 THEN
			BEGIN {go ahead and process the command}
				Menu_No := HiWord(CodeWord);   {get the Hi word of...}
				Item_no := LoWord(CodeWord);   {get the Lo word of...}

				CASE Menu_No OF
					AppleMenu : 
						IF Item_no = 1 THEN
							AboutMoire
						ELSE
							BEGIN { Desk Accessory }
								GetItem(GetMHandle(AppleMenu), Item_No, NameHolder);
								DNA := OpenDeskAcc(NameHolder);
							END;

					OTHERWISE
						DoMoireMenu(Menu_No, Item_no);

				END;

				HiliteMenu(0);               {unhilite after processing menu}
			END;
	END; {of ProcessMenu_in procedure}


{-------------------------------------------------------------------}
{----- These are procedures called from the main event loop  -------}

	PROCEDURE DealwithMouseDowns (Event : EventRecord);
		VAR
			Location : integer;
			WindowPointedTo : WindowPtr;
			MouseLoc : Point;
			WindoLoc : integer;
	BEGIN
		MouseLoc := Event.Where;
		WindoLoc := FindWindow(MouseLoc, WindowPointedTo);
		CASE WindoLoc OF

			inMenuBar : 
				ProcessMenu_in(MenuSelect(MouseLoc));

			inSysWindow : 
				SystemClick(Event, WindowPointedTo);

			inContent : 
				IF WindowPointedTo <> FrontWindow THEN
					SelectWindow(WindowPointedTo)
				ELSE
					BEGIN
						MoireContent(MouseLoc);
					END;

			inGrow : 
				IF WindowPointedTo <> FrontWindow THEN
					SelectWindow(WindowPointedTo)
				ELSE
					ReSizeWindow(WindowPointedTo, MouseLoc);

			inDrag : 
				DragWindow(WindowPointedTo, MouseLoc, DragArea);

			inGoAway : 
				IF TrackGoAway(WindowPointedTo, MouseLoc) THEN
					BEGIN
						IF WindowPointedTo = MoireWindow THEN
							Finished := True { alternative to 'quit' }
						ELSE
							HideWindow(WindowPointedTo);
					END;
			OTHERWISE
				;
		END;{ of case}
	END;

{-----------------------------------------------------------------------------}

	PROCEDURE DealwithKeyDowns (Event : EventRecord);
		VAR
			CharCode : char;
	BEGIN
		CharCode := char(BitAnd(Event.message, CharCodeMask));

		IF BitAnd(Event.modifiers, CmdKey) = CmdKey THEN
			BEGIN
      {key board command - probably a menu command}
				ProcessMenu_in(MenuKey(CharCode));
			END
		ELSE
			BEGIN
      { regular keyboard entry}
			END;
	END;


{-----------------------------------------------------------------------------}

	PROCEDURE DealwithActivates (Event : EventRecord);
		VAR
			TargetWindow : WindowPtr;
	BEGIN
		TargetWindow := WindowPtr(Event.message);
   { if not isFullScreen then DrawGrowIcon(TargetWindow); }

		IF Odd(Event.modifiers) THEN
			BEGIN
       {then the window is becoming active}
				SetPort(TargetWindow);
			END;

		IncludeMenuBar;	{ in case someone wants to steal the menu bar back }
	END;

{-----------------------------------------------------------------------------}

	PROCEDURE DealwithUpdates (Event : EventRecord);
		VAR
			UpDateWindow, savePort : WindowPtr;
	BEGIN
		UpDateWindow := WindowPtr(Event.message);
		GetPort(savePort);                {Save the current port}
		SetPort(UpDateWindow);      {set the port to one in Evt.msg}

		BeginUpDate(UpDateWindow);
{EraseRect(UpDateWindow^.portRect);}
   (* or EraseRect(UpDateWindow^.VisRgn^^.rgnBBox); *)
{DrawGrowIcon(UpDateWindow);}
		EndUpDate(UpDateWindow);

		IF UpDateWindow = MoireWindow THEN
			RefreshMoire
		ELSE
			IncludeMenuBar;

		SetPort(savePort);             {restore to the previous port}
	END;


	PROCEDURE DealwithDialogEvent (Event : EventRecord);
		VAR
			theDialog : DialogPtr;
			itemHit : integer;
			CharCode : char;
			forDialog : Boolean;	{ sometimes the event should not go to the dialog }
	BEGIN
		forDialog := True;
		IF Event.what = KeyDown THEN
			forDialog := BitAnd(Event.modifiers, CmdKey) <> CmdKey;

		IF forDialog THEN
			IF DialogSelect(Event, theDialog, itemHit) THEN
				IF theDialog = ObjectsDialog THEN
					DoObjectsDialogEvent(itemHit)
				ELSE IF theDialog = ControlDialog THEN
					DoControlDialogEvent(itemHit)
				ELSE IF theDialog = ModeDialog THEN
					DoModeDialogEvent(itemHit);
	END;


{-----------------------------------------------------------------------------}

	PROCEDURE MainEventLoop;
		VAR
			Event : EventRecord;
			ProcessIt : Boolean;
	BEGIN
		REPEAT
			SystemTask;             {to support Desk Accessories}


			ProcessIt := GetNextEvent(EveryEvent, Event);
			IF IsDialogEvent(Event) THEN
				DealwithDialogEvent(Event);

			IF ProcessIt THEN

				CASE Event.what OF
					mouseDown : 
						DealwithMouseDowns(Event);
					KeyDown : 
						DealwithKeyDowns(Event);
					ActivateEvt : 
						DealwithActivates(Event);
					UpDateEvt : 
						DealwithUpdates(Event);
					OTHERWISE
						;
				END {of Case}

			ELSE
				MoireStep; 		{ <<<< }

		UNTIL Finished; {terminate the program}
	END;

{-----------------------------------------------------------------------------}

	PROCEDURE InitThings;
	BEGIN
		InitGraf(@thePort);          {create a grafport for the screen}

		MoreMasters;                 {extra pointer blocks at the bottom of the heap}
		MoreMasters;                 {this is 5 X 64 master pointers}
		MoreMasters;
		MoreMasters;
		MoreMasters;

   {get the cursors we use and lock them down - no clutter}
		ClockCursor := GetCursor(watchCursor);
		HLock(Handle(ClockCursor));

   {show the watch while we wait for inits & setups to finish}
		SetCursor(ClockCursor^^);

   {init everything in case the app is the Startup App}
		InitFonts;                     {startup the fonts manager}
		InitWindows;                   {startup the window manager}
		InitMenus;                     {startup the menu manager}
		TEInit;                        {startup the text edit manager}
		InitDialogs(NIL);              {startup the dialog manager}

		Finished := False;             {set program terminator to false}
		FlushEvents(everyEvent, 0);     {clear events from previous program}
	END;

{-----------------------------------------------------------------------------}

	PROCEDURE SetupLimits;
	BEGIN
		WITH ScreenBits.Bounds DO
			BEGIN
				SetRect(DragArea, left, top + 24, right, bottom);
				SetRect(GrowArea, left, top + 24, right, bottom);
			END;
	END;

{-----------------------------------------------------------------------------}

	PROCEDURE SetupMenus;
		VAR
			MenuTopic : MenuHandle;
	BEGIN
		MenuTopic := GetMenu(AppleMenu);  {get the apple desk accessories menu}
		AddResMenu(MenuTopic, 'DRVR');     {adds all names into item list}
		InsertMenu(MenuTopic, 0);          {put in list held by menu manager}

		MenuTopic := GetMenu(FileMenu);   {always need this for Quiting}
		InsertMenu(MenuTopic, 0);

		MenuTopic := GetMenu(EditMenu);   {always need for editing Desk Accessories}
		InsertMenu(MenuTopic, 0);

		SetupMoireMenus;   { <<<<< }

		DrawMenuBar;           {all done so show the menu bar}
	END;

{-----------------------------------------------------------------------------}

	PROCEDURE SetupWindows;
	BEGIN
   { Create the window from information stored on the Resource file }

		MoireWindow := GetNewWindow(MoireWindowID, NIL, POINTER(-1));
		setPort(MoireWindow);
	END;


	PROCEDURE SetUpThings;
	BEGIN
		SetupWindows;         {do first so it's low in heap}
		SetupMenus;
		SetupLimits;
		SetupMoire;	{ <<<<< }
		InitCursor;           {ready to go, so show the Arrow cursor}
	END;


	PROCEDURE CloseThings;
	BEGIN
	END;

END.
SHAR_EOF
if test -f 'Moire.R.text'
then
	echo shar: over-writing existing file "'Moire.R.text'"
fi
cat << \SHAR_EOF > 'Moire.R.text'

*  Moire.R 
* 
*  Resource definitions for the application Moire
*
*  Define output file.  
LS Pascal:Moire Folder:Moire/Rsrc

Type MOIR = STR 
  ,0
Daniel LaLiberte    Version 3.1  Jan 10, 1986.

Type FREF
  ,128
  APPL 0
  ,129
  TEXT 1

Type BNDL
  ,128
  MOIR 0
  ICN#
  0  1234  1  1235
  FREF
  0  128  1  129


Type WIND
,256 (36)
Moire
40 1 215 297
Visible GoAway 
0
0



Type MENU
* the desk accessory menu
 ,256 (36)
\14
  About Moire
  (-

* the File menu
 ,257
File
  Open
  Save as.../S
  Quit /Q

* the edit menu
 ,258
Edit
  Undo /Z
  (-
  Cut /X
  Copy /C
  Paste /V
  Clear

* the Moire menu
,1000
Moire
  Start Over
  Full Screen /W
  Refresh /R
  Invert /I
  (-
  Objects /O
  Control /N
  Mode /M


type DLOG
,128 (36)
Moire Objects
160 320 340 510
Visible GoAway
16
0
128

type DITL
,128 (36)
18
*   1
RadioItem Enabled
25 5 42 85
None

*   2
RadioItem Enabled
40 5 57 85
Line

*   3
RadioItem Enabled
55 5 72 90
Rectangle

*   4
RadioItem Enabled
70 5 87 94
RoundRect

*   5
RadioItem Enabled
85 5 102 90
Oval

*   6
RadioItem Enabled
100 5 117 90
Arc

*   7
RadioItem Enabled
115 5 132 90
Angle

*   8
RadioItem Enabled
130 5 147 90
Triangle

*   9
RadioItem Enabled
145 5 162 115
Quadralateral

*   10
RadioItem Enabled
160 5 177 115
Tetrahedron

*   11
RadioItem Enabled
25 95 42 175
None

*   12
RadioItem Enabled
40 95 57 175
Line

*   13
RadioItem Enabled
55 95 72 180
Rectangle

*   14
RadioItem Enabled
70 95 87 185
RoundRect

*   15
RadioItem Enabled
85 95 102 180
Oval

*   16
RadioItem Enabled
100 95 117 180
Arc

StatText Enabled
5 5 21 75 
Object 1

StatText Enabled
5 95 21 165 
Object 2



*------------------------------
type DLOG
,129 (36)
Moire Control
241 4 341 313
Visible GoAway
16
0
129


type DITL
,129 (36)
14
EditText Enabled
30 19 45 54 
20

EditText Enabled
70 19 85 54 
2

ChkItem Enabled
10 85 25 175 
Accelerate

ChkItem Enabled
25 85 40 165 
Polarize

ChkItem Enabled
40 85 55 190 
Paint Objects

ChkItem Enabled
60 85 75 190 
Vary Pensize

ChkItem Enabled
75 85 90 190 
Vary Pattern

ChkItem Enabled
30 200 45 305 
Horizontally

ChkItem Enabled
45 200 60 290 
Vertically

ChkItem Enabled
60 200 75 300 
Diagonally /

ChkItem Enabled
75 200 90 300 
Diagonally \

StatText Disabled
10 10 26 60 
Length

StatText Disabled
50 5 66 65 
Variance

StatText Disabled
13 201 29 256 
Reflect





*---------------------------
type DLOG
,130 (36)
Moire Mode
39 338 205 509
Visible GoAway
16
0
130


type DITL
,130 (36)
20
RadioItem Enabled
25 5 42 70 
Copy

RadioItem Enabled
40 5 56 70 
Or

RadioItem Enabled
55 5 72 70 
Xor

RadioItem Enabled
70 5 87 70 
Bic

RadioItem Enabled
85 5 102 85 
Not Copy

RadioItem Enabled
100 5 117 70 
Not Or

RadioItem Enabled
115 5 132 75 
Not Xor

RadioItem Enabled
130 5 147 75 
Not Bic

RadioItem Enabled
145 5 162 70 
None

RadioItem Enabled
25 90 42 155 
Copy

RadioItem Enabled
40 90 57 155 
Or

RadioItem Enabled
55 90 72 155 
Xor

RadioItem Enabled
70 90 87 155 
Bic

RadioItem Enabled
85 90 102 170 
Not Copy

RadioItem Enabled
100 90 117 155 
Not Or

RadioItem Enabled
115 90 132 160 
Not Xor

RadioItem Enabled
130 90 147 155 
Not Bic

RadioItem Enabled
145 90 162 155 
None

StatText Enabled
5 5 22 70 
Leading

StatText Enabled
5 90 22 155 
Trailing



*----------------------------------

Type ALRT
* For About Moire
     ,1000 (36)
35 45 325 460
1000
4444


Type DITL

     ,1000 (36)
6
*   1
StatText Disabled
13 10 64 406
Moire 3.1 is free.  The source (in Lightspeed Pascal) is available on disk for $10.  Much more is possible, so please send your ideas and tell me of any problems.

*   2
StatText Disabled
70 10 171 206
There are 10 moving points:  4 are for objects, 1 for the pen size and pattern, and 5 for the acceleration of the first 5 points.  Some points are reused.

*   3
StatText Disabled
70 214 171 406
The points bounce off of walls using both the x and y position, the velocity, variance, and the point number.  So the pattern has a very long cycle time.

*   4
StatText Disabled
180 37 196 372
Please send ideas (or money, if you prefer) to:

*   5
StatText Disabled
200 115 285 395
Daniel LaLiberte             liberte@uiucdcs\0DUniversity of Illinois, Urbana-Champaign\0DDepartment of Computer Science\0D1304 W Springfield\0DUrbana  IL   61801

*   6
BtnItem Enabled
240 15 272 95
OK


Type ICN# = GNRL

* Application icon
     ,1234 (36)
.H
01FFFF80
01FFFF80
007FFE00
007FFE00
003FFC00
003FFC00
001FF800
801FF801
800FF001
E00FF007
E007E007
F007E00F
F003C00F
FC03C03F
FC01803F
FE01807F
3E03C07C
3F83C1FC
0F87E1F0
0FC7E3F0
07CFF3E0
87FFFFE1
81EFF781
E1E7E787
E047E207
F841821F
3841821C
3E41827C
0EF18F70
CF73CEF3
C27BDE43
F23BDC4F
*
00FFFF00
00FFFF00
003FFC00
003FFC00
001FF800
801FF801
000FF000
C00FF003
C007E003
F007E00F
F003C00F
F803C01F
F801801F
FE01807F
7E00007E
7F0000FE
1F0180F8
1FC183F8
07C3C3E0
07E3C7E0
83E7E7C1
C3F7EFC3
C0F7EF03
F0F3CF0F
7063C60E
7C22443E
1C000038
1F0000F8
87781EE1
E7B99DE7
E13DBC87
791DB89E

* document icon
     ,1235 (36)
.H
1FFFFF00
10FFFF80
107FFE40
107FFE20
103FFC10
103FFC08
101FF808
101FF808
100FF008
100FF008
1007E008
1007E008
1003C008
1C03C038
1C018038
1E018078
1E03C078
1F83C1F8
1F87E1F8
1FC7E3F8
17CFF3E8
17FFFFE8
11EFF788
11E7E788
1047E208
18418218
18418218
1E418278
1EF18F78
1F73CEF8
127BDE48
1FFFFFF8
*
1FFFFF00
10FFFF80
103FFC40
103FFC20
101FF810
101FF808
100FF008
100FF008
1007E008
1007E008
1003C008
1803C018
18018018
1E018078
1E000078
1F0000F8
1F0180F8
1FC183F8
17C3C3E8
17E3C7E8
13E7E7C8
13F7EFC8
10F7EF08
10F3CF08
1063C608
1C224438
1C000038
1F0000F8
17781EE8
17B99DE8
113DBC88
1FFFFFF8
SHAR_EOF
#	End of shell archive
exit 0