[mod.mac.sources] BlobDemo1 - Blob Manager Demo source

macintosh@felix.UUCP (01/29/87)

#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	BlobDemo/BlobDemo.h
#	BlobDemo/DemoAnagram.c
#	BlobDemo/DemoFar.c
#	BlobDemo/DemoFgg.c
#	BlobDemo/DemoFsh.c
#	BlobDemo/DemoHang.c
mkdir BlobDemo
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/BlobDemo.h
X/*
X	Blob Manager Demonstration:  Header file
X
X	19 July 1986	Paul DuBois
X*/
X
X# ifndef	_BlobMgr_
X# include	"BlobMgr.h"
X# endif
X
X# ifndef	nil
X# define	nil	0L
X# endif
X
X
X/*
X	Resource numbers
X*/
X
X# define	helpTextRes		1000	/* help text */
X# define	fshPictRes		1		/* fish picture */
X# define	letrSicnNo		130		/* SICN containing hebrew letters */
X# define	nameStrNo		130		/* STR# containing letter names */
X
X
Xenum
X{
X	aboutAlrtRes = 1000,	/* "About BlobDemo..." alert */
X	textDlogRes
X};
X
Xenum		/* window numbers.  the ones between firstWindRes */
X{			/* and lastWindRes should be consecutive */
X
X	firstWindRes = 1000,
X	fggWindRes = firstWindRes,
X	farWindRes,
X	hebWindRes,
X	tttWindRes,
X	tohWindRes,
X	fshWindRes,
X	aliceWindRes,
X	radixWindRes,
X	magicWindRes,
X	statesWindRes,
X	hangWindRes,
X	pegWindRes,
X	anaWindRes,
X	swapWindRes,
X	wolfWindRes,
X	pyrWindRes,
X	pongWindRes,
X	lastWindRes				/* not a real window - only a placeholder. */
X							/* should come last in list */
X};
X
X
Xenum		/* menu numbers */
X{
X	fileMenuRes = 256,
X	windMenuRes,
X	radixMenuRes,
X	clickMenuRes,
X	donorMenuRes,
X	receptorMenuRes,
X	editMenuRes,
X	swapCnfgMenuRes,
X	pegCnfgMenuRes
X};
X
Xenum		/* file menu item numbers */
X{
X	getInfo = 1,
X	/* ---- */
X	quit = 3
X};
X
Xenum		/* fox, goose, grain icon numbers */
X{
X	foxIconRes = 1000,
X	gooseIconRes,
X	grainIconRes,
X	farmerIconRes,
X	whewIconRes,
X	ratsIconRes
X};
X
X
Xint		DoWClobber();
Xint		DoMClobber();
X
X/*
X	Functions returning non-integral values
X*/
X
XBlobHandle	MakeCharBlob();
XGrafPtr		GetDemoWind();
XGrafPtr		NewOffPort();
Xchar		*PickWord();
XBlobHandle	NewVButtonBlob ();
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoAnagram.c
X
X/*
X	Blob Manager Demonstration:  Anagram module
X
X	19 July 1986	Paul DuBois
X*/
X
X
X# include	"BlobDemo.h"
X# include	<ControlMgr.h>
X
X
X# define	vWord		10
X# define	letterSize	18
X# define	letterGap	2
X
X
Xstatic GrafPtr			anaPort;
Xstatic BlobSetHandle	receptors = nil;
Xstatic int				hMid;
Xstatic ControlHandle	next;
Xstatic ControlHandle	answer;
X
X
X/*
X	Generate the next anagram.  Get a word from the word picker,
X	put each letter in a receptor and glue the receptor to itself.
X	Then scramble the receptors and show them.
X*/
X
Xstatic NextAnagram ()
X{
XBlobHandle	b;
Xint			i, h;
Xchar		*s;
X
X	if (receptors != nil)		/* dispose of any previous sets */
X	{
X		HideBlobSet (receptors);
X		DisposeBlobSet (receptors);
X	}
X	receptors = NewBlobSet ();
X	s = PickWord ();
X	h = hMid - (s[0] * (letterSize + letterGap) - letterGap) / 2;
X	for (i = 1; i <= s[0]; ++i)
X	{
X		b = MakeCharBlob (receptors, false, infiniteGlue,
X							false, h, vWord, s[i]);
X		h += letterSize + letterGap;
X		GlueGlob (b, b);
X	}
X	ShuffleGlobSet (receptors);
X	ShowBlobSet (receptors);
X	ValidRect (&anaPort->portRect);
X}
X
X
X/*
X	Show answer to anagram.  This may not be unique.  For instance,
X	"begin" can also be "being".  Clearing the globs shows the original
X	attachments, as well as disabling any further transactions until
X	the Next button is hit, since there won't be any globs to swap.
X*/
X
Xstatic ShowAnswer ()
X{
X	UnglueGlobSet (receptors);
X}
X
X
Xstatic Activate (active)
XBoolean active;
X{
X	if (active)
X	{
X		SetDragRects (anaPort);
X		SetBCPermissions (false, false, false, true, true);
X	}
X}
X
X
Xstatic Update (resized)
XBoolean	resized;
X{
X	DrawControls (anaPort);
X	DrawBlobSet (receptors);
X}
X
X
Xstatic Mouse (pt, t, mods)
XPoint	pt;
Xlong	t;
Xint		mods;
X{
XBlobHandle	b, d;
XControlHandle	ctl;
X
X	if (FindControl	(pt, anaPort, &ctl))
X	{
X		if (TrackControl (ctl, pt, nil))	/* button hit? */
X		{
X			if (ctl == next)
X				NextAnagram ();
X			else if (ctl == answer)
X				ShowAnswer ();
X		}
X	}
X	else
X		BlobClick (pt, t, nil, receptors);
X}
X
X
XAnagramInit ()
X{
XRect	r;
X
X	SkelWindow (anaPort = GetDemoWind (anaWindRes),
X				Mouse,			/* mouse clicks */
X				nil,			/* key clicks */
X				Update,			/* updates */
X				Activate,		/* activate/deactivate events */
X				nil,			/* close window */
X				DoWClobber,		/* dispose of window */
X				nil,			/* idle proc */
X				false);			/* irrelevant, since no idle proc */
X
X	hMid = anaPort->portRect.right / 2;
X	SetRect (&r, 0, 0, 80, 20);
X	OffsetRect (&r, hMid - 40 - 90 / 2, anaPort->portRect.bottom - 25);
X	next = NewControl (anaPort, &r, "\pNext", true, 0, 0, 0,
X							pushButProc, nil);
X	OffsetRect (&r, 90, 0);
X	answer = NewControl (anaPort, &r, "\pAnswer", true, 0, 0, 0,
X							pushButProc, nil);
X
X	SetCharBlobSize (letterSize);
X	NextAnagram ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoFar.c
X/*
X	Blob Manager Demonstration:  Fifteen-A-Row module
X	
X	25 June 1986	Paul DuBois
X*/
X
X# include	"BlobMgr.h"
X# include	"BlobDemo.h"
X# include	<ControlMgr.h>
X
X# define	xMid	145
X# define	yMid	100
X# define	radius	10
X
Xstatic GrafPtr			farPort;
Xstatic BlobSetHandle	farDBlobs;
Xstatic BlobSetHandle	farRBlobs;
X
Xstatic Boolean			wait = false;
Xstatic ControlHandle	restartCtl;
X
X
XFarTestAnswer ()
X{
XBlobHandle	b, b2;
Xint			i;
X
X	for (i = 0; i < 9; ++i)
X	{
X		b = GetBlobHandle (farRBlobs, i);
X		if ((**b).glob == nil) return;
X	}
X	b = GetBlobHandle (farRBlobs, 0);
X	if (GetBRefCon ((**b).glob) != 5L) return;
X	for (i = 1; i < 5; i++)
X	{
X		b = GetBlobHandle (farRBlobs, i);
X		b2 = GetBlobHandle (farRBlobs, i + 4);
X		if (GetBRefCon ((**b).glob) + GetBRefCon ((**b2).glob) != 10L)
X				return;
X	}
X	wait = true;
X	FreezeBlobSet (farRBlobs);
X	HiliteControl (restartCtl, 0);
X}
X
X
XFarDoLine (x, y)
Xint		x, y;
X{
X	MoveTo (xMid, yMid);
X	LineTo (xMid + x, yMid + y);
X}
X
X
XFarDoLines ()
X{
X	FarDoLine (-50, 0);
X	FarDoLine (-35, -35);
X	FarDoLine (0, -50);
X	FarDoLine (35, -35);
X	FarDoLine (50, 0);
X	FarDoLine (35, 35);
X	FarDoLine (0, 50);
X	FarDoLine (-35, 35);
X}
X
XFarUpdate (resized)
XBoolean	resized;
X{
X	DrawControls (farPort);
X	FarDoLines ();
X	DrawBlobSet (farRBlobs);
X	DrawBlobSet (farDBlobs);
X}
X
X
XFarActivate (active)
XBoolean	active;
X{
X	if (active)
X	{
X		SetDragRects (farPort);
X		SetBCPermissions (true, true, false, true, true);
X	}
X}
X
X
XFarNewRBlob (x, y)
Xint		x, y;
X{
XBlobHandle	b;
Xint			diameter;
XRect		r;
X
X	diameter = radius + radius;
X	SetRect (&r, 0, 0, diameter, diameter);
X	OffsetRect (&r, xMid + x - radius, yMid + y - radius);
X	b = NewBlob (farRBlobs, false, 1, false, 0L);
X	OpenBlob ();
X	PenSize (2, 2);
X	EraseOval (&r);
X	FrameOval (&r);
X	PenNormal ();
X	CloseRectBlob (b, &r, &r);
X}
X
X
XFarNewDBlob (val)
Xint		val;
X{
XBlobHandle	b;
Xint			diameter;
XRect		r;
X
X	diameter = radius + radius;
X	SetRect (&r, 0, 0, diameter, diameter);
X	OffsetRect (&r, (int) (val * (diameter + 6) + 5), 10);
X	b = NewBlob (farDBlobs, false, 1, false, (long) val);
X	OpenBlob ();
X	EraseOval (&r);
X	FrameOval (&r);
X	MoveTo (r.left + 6, r.bottom - 6);
X	DrawChar ((char) (val + '0'));
X	CloseRectBlob (b, &r, &r);
X}
X
X
XFarMouse (pt, t)
XPoint	pt;
Xlong	t;
X{
XControlHandle	ctl;
X
X	if (FindControl (pt, farPort, &ctl))
X	{
X		if (TrackControl (ctl, pt, nil))
X		{
X			HiliteControl (restartCtl, 255);
X			wait = false;
X			ThawBlobSet (farRBlobs);
X			ZUnglueGlobSet (farRBlobs);
X			InvalRect (&farPort->portRect);
X			ShuffleBlobSet (farDBlobs);
X			ValidRect (&farPort->portRect);	/* avoid update event */
X		}
X	}
X	else
X	{
X		BlobClick (pt, t, farDBlobs, farRBlobs);
X		FarTestAnswer ();
X	}
X}
X
X
XFarInit ()
X{
Xint		i;
XRect	r;
X
X	farPort = GetDemoWind (farWindRes);
X	SkelWindow (farPort,
X				FarMouse,		/* mouse clicks */
X				nil,			/* key clicks */
X				FarUpdate,		/* updates */
X				FarActivate,	/* activate/deactivate events */
X				nil,			/* close window */
X				DoWClobber,		/* dispose of window */
X				nil,			/* idle proc */
X				false);			/* irrelevant, since no idle proc */
X
X	farDBlobs = NewBlobSet ();
X	farRBlobs = NewBlobSet ();
X	FarNewRBlob (0, 0);  /* middle point */
X	FarNewRBlob (-50, 0);
X	FarNewRBlob (-35, -35);
X	FarNewRBlob (0, -50);
X	FarNewRBlob (35, -35);
X	FarNewRBlob (50, 0);
X	FarNewRBlob (35, 35);
X	FarNewRBlob (0, 50);
X	FarNewRBlob (-35, 35);
X	for (i = 0; i < 9; ++i)
X		FarNewDBlob (i+1);
X	SetRect (&r, 20, 160, 100, 180);
X	restartCtl = NewControl (farPort, &r, "\pRestart", true, 0, 0, 0,
X								pushButProc, nil);
X	HiliteControl (restartCtl, 255);
X	EnableBlobSet (farRBlobs);
X	EnableBlobSet (farDBlobs);
X	FarUpdate ();
X	ValidRect (&farPort->portRect);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoFgg.c
X
X/*
X	Blob Manager Demonstration:  Fox, Goose and Grain module
X
X	1 July 1986	Paul DuBois
X*/
X
X
X# include	"BlobDemo.h"
X# include	<ControlMgr.h>
X# include	<ToolboxUtil.h>
X
X	
X# define	left	0		/* beginning indices of blobs on each river bank */
X# define	right	3
X
X
X/*
X	positional constants - as yet woefully incomplete
X*/
X# define	xMid	185		/* x-midpoint of screen */
X# define	yOffMesg	110	/* y-offset of status message */
X# define	yOffBox	160		/* y-offset of text box */
X
X
Xstatic GrafPtr			fggPort;
Xstatic BlobSetHandle	donors;
Xstatic BlobSetHandle	receptors;
Xstatic BlobHandle		fox;
Xstatic BlobHandle		goose;
Xstatic BlobHandle		grain;
Xstatic BlobHandle		whew;
Xstatic BlobHandle		rats;
Xstatic BlobHandle		farmer;
Xstatic int				bank;
X
Xstatic ControlHandle	moveCtl;
Xstatic ControlHandle	restartCtl;
Xstatic Boolean			wait;
Xstatic Str255			statusStr = "\p";
X	
X
XFggStatusMesg (s)
XStr255	s;
X{
XRect	r;
X
X	SetRect (&r, xMid - 90, yOffMesg, xMid + 90, yOffMesg + 20);
X	TextBox (s+1, (long) s[0], &r, 1);
X	StrCpy (statusStr, s);
X}
X
X
X
XFggUpdate (resized)
XBoolean	resized;
X{
XRect	r;
X
X	DrawControls (fggPort);
X	DrawBlobSet (receptors);
X	FggStatusMesg (statusStr);
X	MoveTo (90, 10);
X	LineTo (90, 140);
X	MoveTo (279, 10);
X	LineTo (279, 140);
X	MoveTo (15, 15);
X	DrawString ("\pLeft Bank");
X	MoveTo (290, 15);
X	DrawString ("\pRight Bank");
X}
X
X
XFggActivate (active)
XBoolean	active;
X{
X	if (active)
X	{
X		SetDragRects (fggPort);
X		SetBCPermissions (false, true, false, true, true);
X	}
X}
X
X
XFggGameOver (msg, g)
XStr255		msg;
XBlobHandle	g;
X{
X	wait = true;
X	HideControl (moveCtl);
X	ShowControl (restartCtl);
X	FggStatusMesg (msg);
X	GlueGlob (g, farmer);
X}
X
X
XFreezeBank (bank)
Xint		bank;
X{
Xint		i;
X
X	for (i = bank; i < bank + 3; ++i)
X		FreezeBlob (GetBlobHandle (receptors, i));
X}
X
X
XFggRestart ()
X{
X	FggStatusMesg ("\p");
X	UnglueGlobSet (receptors);
X	ThawBlobSet (receptors);
X	MoveBlob (farmer, inFullBlob, 100, 63);
X	bank = left;
X	GlueGlob (fox, GetBlobHandle (receptors, left));
X	GlueGlob (goose, GetBlobHandle (receptors, left+1));
X	GlueGlob (grain, GetBlobHandle (receptors, left+2));
X	FreezeBank (right);
X	HideControl (restartCtl);
X	SetCTitle (moveCtl, "\pMove Right");
X	ShowControl (moveCtl);
X	wait = false;
X	FggUpdate ();
X	ValidRect (&fggPort->portRect);
X}
X
X
XFggLookFor (bank, i)
Xint		bank, i;
X{
XBlobHandle	b;
Xint	j;
X
X	for (j = bank; j < bank + 3; ++j)
X	{
X		b = GetBlobHandle (receptors, j);
X		if (GetBRefCon (BGlob (b)) == i)
X		{
X			switch (i)
X			{
X				case gooseIconRes:
X					FggGameOver	("\pYour goose is cooked!", rats);
X					return;
X				case grainIconRes:
X					FggGameOver	("\pToo bad about that grain!", rats);
X					return;
X			}
X		}
X	}
X}
X
X
X/*
X	Look for pairs that can't be together alone on a bank
X*/
X
XFggCheckStatus (bank)
Xint		bank;
X{
XBlobHandle	b;
Xint	i;
X
X	for (i = bank + 2; i >= bank; --i)
X	{
X		b = GetBlobHandle (receptors, i);
X		switch (GetBRefCon (BGlob (b)))
X		{
X			case foxIconRes: FggLookFor (bank, gooseIconRes); break;
X			case gooseIconRes: FggLookFor (bank, grainIconRes); break;
X		}
X	}
X}
X
X
XFggMouse (pt, t, mods)
XPoint	pt;
Xlong	t;
Xint		mods;
X{
XBlobHandle		b;
XControlHandle	ctl;
Xint				i, otherBank;
X
X	if (FindControl (pt, fggPort, &ctl))
X	{
X		if (TrackControl (ctl, pt, nil))
X		{
X			if (ctl == restartCtl)
X				FggRestart ();
X			else if (ctl == moveCtl)
X			{
X				otherBank = bank;
X				if (bank == left)
X				{
X					bank = right;
X					MoveBlob (farmer, inFullBlob, 125, 63);
X					MoveBlob (farmer, inFullBlob, 150, 63);
X					MoveBlob (farmer, inFullBlob, 175, 63);
X					MoveBlob (farmer, inFullBlob, 200, 63);
X					SetCTitle (moveCtl, "\pMove Left");
X				}
X				else
X				{
X					bank = left;
X					MoveBlob (farmer, inFullBlob, 175, 63);
X					MoveBlob (farmer, inFullBlob, 150, 63);
X					MoveBlob (farmer, inFullBlob, 125, 63);
X					MoveBlob (farmer, inFullBlob, 100, 63);
X					SetCTitle (moveCtl, "\pMove Right");
X				}
X				ThawBlobSet (receptors);
X				FreezeBank (otherBank);
X				ValidRect (&fggPort->portRect);
X				FggCheckStatus (otherBank);
X			}
X		}
X	}
X	if (wait) return;
X	BlobClick (pt, t, donors, receptors);
X
X	for (i = right; i < right + 3; ++i)	/* check if all transported */
X	{
X		if (BGlob (GetBlobHandle (receptors, i)) == nil)
X			return;				/* nope */
X	}
X	FggGameOver ("\pMission Accomplished.", whew);
X}
X
X
XBlobHandle MakeDonor (iconNum)
Xint		iconNum;
X{
XBlobHandle	b;
XHandle	h;
XRect	r;
X
X	b = NewBlob (donors, false, 1, false, (long) iconNum);
X	SetRect (&r, 0, 0, 32, 32);
X	h = GetIcon (iconNum);
X	OpenBlob ();
X	PlotIcon (&r, h);
X	CloseRectBlob (b, &r, &r);
X	return (b);
X}
X
X
XMakeFarmerBlob ()
X{
XRect	r, r2;
XHandle	h;
X
X	farmer = NewBlob (receptors, false, 0, false, 0L);
X	SetRect (&r, 0, 0, 70, 36);
X	SetRect (&r2, 2,	2, 34, 34);
X	h = GetIcon (farmerIconRes);
X	OpenBlob ();
X	FrameRect (&r);
X	EraseRect (&r2);
X	FrameRect (&r2);
X	OffsetRect (&r2, 34, 0);
X	PlotIcon (&r2, h);
X	OffsetRect (&r2, -34, 0);
X	CloseRectBlob (farmer, &r2, &r);	/* will be moved by FggRestart */
X	MoveBlob (farmer, inFullBlob, 100, 63);
X}
X
X
XMakeBankBlobs (bank, xPos)
Xint		bank, xPos;
X{
XBlobHandle	b;
XRect	r;
Xint	i;
X
X	for (i = bank; i < bank + 3; ++i)
X	{
X		b = NewBlob (receptors, false, 0, false, 0L);
X		SetRect (&r, 0, 0, 32, 32);
X		OffsetRect (&r, xPos, (int) 30 + (i-bank)*35);
X		OpenBlob ();
X		EraseRect (&r);
X		FrameRect (&r);
X		CloseRectBlob (b, &r, &r);
X	}
X}
X
X
XFggInit ()
X{
XRect	r;
X
X	fggPort	= GetDemoWind (fggWindRes);
X	SkelWindow (fggPort,
X				FggMouse,		/* mouse clicks */
X				nil,			/* key clicks */
X				FggUpdate,		/* updates */
X				FggActivate,	/* activate/deactivate events */
X				nil,			/* close window */
X				DoWClobber,		/* dispose of window */
X				nil,			/* idle proc */
X				false);			/* irrelevant, since no idle proc */
X
X	donors = NewBlobSet ();
X	receptors = NewBlobSet ();
X	
X	fox = MakeDonor (foxIconRes);		/* create fox, goose, grain blobs */
X	goose = MakeDonor (gooseIconRes);
X	grain = MakeDonor (grainIconRes);
X	MakeBankBlobs (left, 50);	/* make riverbank blobs - left MUST be 1st */
X	MakeBankBlobs (right, 288);
X	MakeFarmerBlob ();			/* create Farmer blob - MUST follow banks */
X	whew = MakeDonor (whewIconRes);		/* create "Whew!" blob */
X	rats = MakeDonor (ratsIconRes);		/* create "Rats!" blob */
X
X/*
X	both controls are at same position - only one is shown at a time.
X*/
X	SetRect (&r, 135, 10, 235, 30);
X	moveCtl =
X		NewControl (fggPort, &r, "\pMove Right", false, 0, 0, 0, pushButProc, nil);
X	restartCtl =
X		NewControl (fggPort, &r, "\pRestart", false, 0, 0, 0, pushButProc, nil);
X
X	EnableBlobSet (receptors);
X	FggRestart ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoFsh.c
X
X/*
X	Blob Manager Demonstration:  Fish Puzzle module
X
X	Cuts fish picture into pieces, allows user to reassemble.
X
X	26 July 1986	Paul DuBois
X*/
X
X
X# include	"BlobDemo.h"
X
X
X/*
X	The picture is 234 wide by 144 high
X*/
X
X# define	hOff		5	/* puzzle board offsets */
X# define	vOff		5
X# define	hWidth		18
X# define	vHeight		144
X# define	hGap		1
X# define	vGap		1
X# define	rows		1
X# define	cols		13
X# define	cells		13	/* i.e., rows x cols */
X
X
Xstatic GrafPtr			fshPort;
Xstatic GrafPtr			theFish;
Xstatic BlobSetHandle	receptors;	/* receptor blobs */
Xstatic BlobSetHandle	misc;
Xstatic BlobHandle		scrambleBlob;	/* simulated control */
Xstatic Boolean			paused;
X
Xstatic PicHandle		pic;
Xstatic Rect				picRect;
Xstatic int				hMid;
X
X
Xstatic Reset ()
X{
X	ShuffleGlobSet (receptors);
X	HiliteBlob (scrambleBlob, inDragBlob, dimDraw);
X	paused = false;
X}
X
X
Xstatic Pause ()
X{
X	HiliteBlob (scrambleBlob, inDragBlob, normalDraw);
X	paused = true;
X}
X
X
Xstatic Mouse (pt, t, mods)
XPoint	pt;
Xlong	t;
Xint		mods;
X{
XBlobHandle	b, d;
X
X	if (TestBlob (scrambleBlob, pt) == inDragBlob)
X	{
X		if (BTrackMouse (scrambleBlob, pt, inFullBlob))
X			Reset ();
X	}
X	else if (!paused)
X	{
X		BlobClick (pt, t, nil, receptors);
X		if (BlobSetQuiet (receptors))
X			Pause ();
X	}
X}
X
X
Xstatic Activate (active)
XBoolean	active;
X{
X	if (active)
X	{
X		SetDragRects (fshPort);
X		SetBCPermissions (false, false, false, true, true);
X	}
X}
X
X
Xstatic Update (resized)
XBoolean	resized;
X{
XRect	r;
X
X	EraseRect (&fshPort->portRect);
X	SetRect (&r, 0, 0, 
X				(hWidth + hGap) * cols + hGap + 4,
X				vHeight + 2 * hGap + 4);
X	OffsetRect (&r, hOff-hGap-2, vOff-vGap-2);
X	PenMode (patBic);
X	FrameRect (&r);
X	PenNormal ();
X	DrawGrid (rows, cols, hOff, vOff, hWidth, vHeight, hGap, vGap);
X	DrawBlobSet (receptors);
X	DrawBlob (scrambleBlob, inFullBlob);
X}
X
X
X/*
X	Make a receptor blob, glue it onto itself, and set it so that it
X	is matched when it is glued onto itself.  This provides an easy
X	way of telling when the fish has been reassembled after it is
X	scrambled.
X*/
X
Xstatic MakeRBlob (r)
XRect	*r;
X{
XBlobHandle	b;
Xstatic int	pieceNo = 0;
XRect		r2;
X
X	b = NewBlob (receptors, false, infiniteGlue, true, 0L);
X	OpenBlob ();
X	r2 = *r;
X	OffsetRect (&r2, pieceNo * hWidth - r->left, -r->top);
X	CopyBits (&theFish->portBits, &fshPort->portBits, &r2, r, srcCopy, nil);
X	CloseRectBlob (b, r, r);
X	NewBlobMatch (b, b);
X	GlueGlob	(b, b);
X	++pieceNo;
X}
X
X
Xstatic MakeBlobs ()
X{
X	receptors = NewBlobSet ();
X	pic = (PicHandle) GetResource ('PICT', fshPictRes);
X	picRect	= (**pic).picFrame;
X	OffsetRect (&picRect, -picRect.left, -picRect.top);	/* to (0, 0) */
X	theFish = NewOffPort (picRect);	/* draw fish into offscreen port */
X	SetPort	(theFish);
X	DrawPicture(pic, &picRect);
X	ReleaseResource	(pic);
X	SetPort	(fshPort);
X	MakeBlobGrid (rows, cols, hOff, vOff, hWidth, vHeight,
X					hGap, vGap, MakeRBlob);
X	DisposeOffPort (theFish);			/* throw away offscreen port */
X	EnableBlobSet (receptors);
X}
X
X
XFshInit	()
X{
XRect	r;
Xlong	count;
X
X	SkelWindow (fshPort	= GetDemoWind (fshWindRes),
X				Mouse,		/* mouse clicks */
X				nil,		/* key clicks */
X				Update,		/* updates */
X				Activate,	/* activate/deactivate events */
X				nil,		/* close window */
X				DoWClobber,	/* dispose of window */
X				nil,		/* idle proc */
X				false);		/* irrelevant, since no idle proc */
X
X	BackPat (black);
X	EraseRect (&fshPort->portRect);
X	hMid = fshPort->portRect.right / 2;
X	MakeBlobs ();
X
X	misc = NewBlobSet ();
X	SetRect (&r, 0, 0, 20, 134);
X	OffsetRect (&r, fshPort->portRect.right - 25, 10);
X	scrambleBlob = NewVButtonBlob (misc, &r, "\pScramble", false, 0L);
X	HiliteBlob (scrambleBlob, inDragBlob, dimDraw);
X/*
X	Show fish as it should look, then scramble it
X*/
X	Update ();
X	ShowBlob (scrambleBlob);
X	ValidRect (&fshPort->portRect);
X
X	for (count = 0; count < 100000L; ++count) { /* empty */ }
X	Reset ();
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoHang.c
X/*
X	Blob Manager Demonstration:	Hangman - the classic game
X
X	This module is a little unusual in that it doesn't use BlobClick.
X	The user chooses letters simply by clicking on them and the
X	scenario in effect drags the letters to the receptors itself.
X
X	26 July 1986		Paul DuBois
X*/
X
X
X# include	"BlobDemo.h"
X# include	<ControlMgr.h>
X
X
X# define	hWord		10	/* horizontal position of word to find */
X# define	vWord		5	/* vertical position */
X# define	hLetters	10	/* location of letter pool */
X# define	vLetters	35
X# define	vMesg		85
X# define	vMan		75
X
X# define	letterSize	18	/* size of letter blobs */
X# define	letterGap	2	/* gap between blobs */
X
X
Xstatic GrafPtr			hangPort;
Xstatic ControlHandle	button;
X
X
Xstatic BlobSetHandle	letters = nil;		/* donor blobs */
Xstatic BlobSetHandle	word = nil;			/* word to be found */
X
Xstatic Boolean			pause;
Xstatic int				wrongMoves;
Xstatic int				hMid;
Xstatic Str255			statusStr = "\p";
X	
X
Xstatic StatusMesg (s)
XStr255	s;
X{
XRect	r;
X
X	SetRect (&r, hMid - 45, vMesg, hMid + 45, vMesg + 20);
X	TextBox (s+1, (long) s[0], &r, 1);
X	StrCpy (statusStr, s);
X}
X
X
X/*
X	Make donor blobs.
X*/
X
Xstatic MakeDonors ()
X{
Xint			i, j, h, v;
X
X	letters = NewBlobSet ();
X	v = vLetters;
X	for (i = 0; i < 2; ++i)
X	{
X		h = hLetters;
X		for (j = 0; j < 13; ++j)
X		{
X			(void) MakeCharBlob (letters, true, infiniteGlue, false,
X								h, v, i * 13 + j + 'a');
X			h += letterSize + letterGap;
X		}
X		v += letterSize + letterGap;
X	}
X}
X
X
X/*
X	Generate a new problem to solve:  get a word from the word picker.
X*/
X
Xstatic GenerateProblem ()
X{
XBlobHandle	b;
Xchar		*s;
Xint			i;
Xint			h;
X
X	/* get rid of any old word blob set */
X
X	if (word != nil)
X	{
X		HideBlobSet (word);
X		DisposeBlobSet (word);
X	}
X	word = NewBlobSet ();
X	s = PickWord ();
X
X	/* create new blob set, attach match information */
X
X	h = hMid - (s[0] * (letterSize + letterGap) - letterGap) / 2;
X	for (i = 1; i <= s[0]; ++i)
X	{
X		b =  MakeCharBlob (word, true, 0, true, h, vWord, ' ');
X		NewBlobMatch (GetBlobHandle (letters, s[i] - 'a'), b);
X		h += letterSize + letterGap;
X	}
X}
X
X
Xstatic NextProblem ()
X{
X	StatusMesg ("\p");			/* clear message */
X	wrongMoves = 0;
X	DrawMan ();
X	HiliteControl (button, 255);
X	if (word != nil)
X		ZUnglueGlobSet (word);		/* detach all letters */
X	HiliteBlobSet (letters, inFullBlob, normalDraw);
X	GenerateProblem ();
X	pause = false;
X	ValidRect (&hangPort->portRect);
X}
X
X
X/*
X	Either the word was discovered or the man hung.	Set up to pause
X	until the Resume button is hit.
X*/
X
Xstatic HangPause (msg)
XStringPtr	msg;
X{
X	StatusMesg (msg);
X	HiliteControl (button, 0);	/* enable button */
X	pause = true;
X}
X
X
Xstatic _DrawMan (h, v)	/* h,v is point at top of man's head */
Xint		h, v;
X{
XRect		r;
XPenState	ps;
X
X	if (wrongMoves == 0)		/* erase man */
X	{
X		wrongMoves = 7;			/* draw entire man in bit-clear mode */
X		GetPenState (&ps);
X		PenMode (patBic);
X		_DrawMan (h, v);
X		wrongMoves = 0;
X		SetPenState (&ps);
X		return;
X	}
X	SetRect (&r, h - 6, v, h + 7, v + 16);
X	FrameOval (&r);
X	if (wrongMoves == 1) return;
X	MoveTo (h, v + 16);
X	LineTo (h, v + 20);
X	if (wrongMoves == 2) return;
X	LineTo (h - 16, v + 32);
X	if (wrongMoves == 3) return;
X	MoveTo (h, v + 20);
X	LineTo (h + 16, v + 32);
X	if (wrongMoves == 4) return;
X	MoveTo (h, v + 20);
X	LineTo (h, v + 40);
X	if (wrongMoves == 5) return;
X	LineTo (h - 16, v + 56);
X	if (wrongMoves == 6) return;
X	MoveTo (h, v + 40);
X	LineTo (h + 16, v + 56);
X}
X
X
Xstatic DrawMan ()
X{
X	_DrawMan (hMid - 80, vMan);
X	_DrawMan (hMid + 80, vMan);
X}
X
X
Xstatic Update (resized)
XBoolean	resized;
X{
X	DrawBlobSet (word);
X	DrawBlobSet (letters);
X	StatusMesg (statusStr);
X	DrawControls (hangPort);
X	DrawMan ();
X}
X
X
Xstatic Mouse (pt, t, mods)
XPoint	pt;
Xlong	t;
Xint		mods;
X{
XBlobHandle		b, r;
XControlHandle	ctl;
Xint				matches = 0;
X
X	if (FindControl (pt, hangPort, &ctl))
X	{
X		if (TrackControl (ctl, pt, nil))	/* button hit? */
X		{
X			NextProblem ();
X		}
X	}
X	else if (!pause && FindBlob (pt, letters, &b) != 0)
X	{
X		if (!BTrackMouse (b, pt, inDragBlob))
X			return;
X		for (r = FirstBlob (word); r != nil; r = NextBlob (r))
X		{
X			if (b == FirstBMatch (r))
X			{
X				ZGlueGlob (b, r);
X				++matches;
X			}
X		}
X		HiliteBlob (b, inFullBlob, dimDraw);	/* force used letter dim */
X		if (matches > 0)	/* letter correct */
X		{
X			if (BlobSetQuiet (word))	/* find answer? */
X				HangPause ("\pCorrect");
X		}
X		else				/* letter incorrect */
X		{
X			++wrongMoves;
X			DrawMan ();
X			if (wrongMoves == 7)
X			{
X				HangPause ("\pYou Lose");
X				for (r = FirstBlob (word); r != nil; r = NextBlob (r))
X				{
X					if (BGlob (r) == nil)	/* show not-found letters */
X						ZGlueGlob (FirstBMatch (r), r);
X				}
X			}
X		}
X	}
X}
X
X
XHangInit ()
X{
XRect	r;
Xint		i;
X
X	SkelWindow (hangPort = GetDemoWind (hangWindRes),
X				Mouse,			/* mouse clicks */
X				nil,			/* key clicks */
X				Update,			/* updates */
X				nil,			/* activate/deactivate events */
X				nil,			/* close window */
X				DoWClobber,		/* dispose of window */
X				nil,			/* idle proc */
X				false);			/* irrelevant, since no idle proc */
X
X	hMid = hangPort->portRect.right / 2;
X	SetRect (&r, 0, 0, 80, 20);
X	OffsetRect (&r, hMid - 40, hangPort->portRect.bottom - 25);
X	button = NewControl (hangPort, &r, "\pNext", true, 0, 0, 0,
X							pushButProc, nil);
X
X	SetCharBlobSize (letterSize);
X	MakeDonors ();
X	NextProblem ();
X}
SHAR_EOF
exit