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

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

#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	BlobDemo/DemoWolf.c
#	BlobDemo/PickWord.c
#	BlobDemo/TextDlog.c
#	BlobDemo/Demo.helptext
mkdir BlobDemo
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoWolf.c
X/*
X	Blob Manager Demonstration:  Wolf & Goats module
X
X	This is played on a checkerboard.  The wolf starts in one corner,
X	the four goats on the opposite row.  All moves are into adjoining
X	diagonal squares.  The wolf can move forward or backward, the goats
X	only forward.  The goats try to trap the wolf so he can't move,
X	while the wolf tries to get past the goats to the other side.
X
X	This game is a variant of fox & geese.
X
X	1 August 1986		Paul DuBois
X*/
X
X
X# include	"BlobDemo.h"
X
X
X# define	rows		8		/* number of rows on board */
X# define	columns		8		/* number of columns on board */
X# define	pieceSize	20		/* size of each piece */
X# define	vMessage	165		/* vertical position of message */
X
X
X
X
Xstatic GrafPtr			wolfPort;
X
X
Xstatic BlobSetHandle	boardBlobs = nil;
Xstatic BlobHandle		board[columns][rows];
Xstatic BlobSetHandle	donors = nil;
Xstatic BlobHandle		wolf;
Xstatic BlobHandle		goat;
Xstatic BlobHandle		current;
Xstatic BlobSetHandle	misc;
Xstatic BlobHandle		resetBlob;	/* simulated control */
Xstatic int				hWolf;
Xstatic int				vWolf;
X
Xstatic int				hMid;
Xstatic Boolean			pause;
Xstatic Str255			statusStr = "\p";
X
X
X
Xstatic StatusMesg (s)
XStr255	s;
X{
XRect	r;
X
X	SetRect (&r, 0, vMessage, wolfPort->portRect.right - 25, vMessage + 12);
X	TextBox	(s+1, (long) s[0], &r, 1);
X	StrCpy (statusStr, s);
X}
X
X
X/*
X	The donor set consists of two blobs:  the wolf blob and the
X	goat blob.
X*/
X
Xstatic MakeDonors ()
X{
XRect		r;
X
X	donors = NewBlobSet ();
X	SetRect (&r, 0, 0, pieceSize - 1, pieceSize - 1);
X	wolf = NewBlob (donors, false, infiniteGlue, false, 0L);
X	OpenBlob ();
X	PaintRect (&r);
X	PenMode (patBic);
X	PenSize (2, 2);
X	FrameOval (&r);
X	PenNormal ();
X	CloseRectBlob (wolf, &r, &r);
X	goat = NewBlob (donors, false, infiniteGlue, false, 0L);
X	OpenBlob ();
X	PaintRect (&r);
X	EraseOval (&r);
X	CloseRectBlob (goat, &r, &r);
X}
X
X
X
X/*
X	Make a simulated push button.  It looks like a regular button,
X	except that it's oriented vertically rather than horizontally.
X	The ShowPen call is necessary since both OpenBlob and OpenRgn
X	perform implicit HidePen's - without ShowPen, nothing will
X	be drawn!  Then must balance with HidePen after drawing.
X*/
X
Xstatic MakeButton ()
X{
XRect		r;
X
X	misc = NewBlobSet ();
X	SetRect (&r, 0, 0, 20, 90);
X	OffsetRect (&r, wolfPort->portRect.right - 25,
X					(wolfPort->portRect.bottom - 90 - 25) / 2);
X	resetBlob = NewVButtonBlob (misc, &r, "\pReset", true, 0L);
X}
X
X
X/*
X	Board position drawing procedure.  All positions are drawn the
X	same - a black rectangle.  However, the unused positions are set
X	dimmed by InitBoard, so the drawing mechanisms make them gray.
X	For the drag region of used positions,
X	this proc is only called if the position has no piece (i.e., no
X	glob) because the pieces are picture blobs.
X
X	For these reasons, bSrc and bDst are always equal when
X	DrawBoardPos is called.
X*/
X
Xstatic DrawBoardPos (bSrc, bDst, partCode)
XBlobHandle	bSrc, bDst;
Xint			partCode;		/* ignored - always draw entire blob */
X{
XRect	r;
X
X	r = BStatBox (bDst);
X	PaintRect (&r);
X}
X
X
X/*
X	Build the board, which consists of alternating black and gray
X	squares.  They are actually the same as far as the drawing proc
X	goes, but the gray squares are set to be dimmed so that the
X	normal drawing mechanisms do the work of making the two types
X	of square look distinct.  The fact that the gray squares are
X	dimmed also makes the hit-testing mechanisms ignore them.
X*/
X
Xstatic InitBoard ()
X{
Xint			h, v;
XRect		r, r2;
XBlobHandle	b;
X
X	boardBlobs = NewBlobSet ();
X	for (v = 0; v < rows; v++)
X	{
X		for (h = 0; h < columns; h++)
X		{
X			b = NewBlob (boardBlobs, false, 0, false, 0L);
X			board[h][v] = b;
X			SetRect (&r, 0, 0, pieceSize, pieceSize);
X			OffsetRect (&r, h * pieceSize, v * pieceSize);
X			r2 = r;
X			InsetRect (&r2, 1, 1);
X			SetProcRectBlob (b, DrawBoardPos, &r2, &r);
X
X			/*
X				All unused postions have coordinates that sum to an
X				odd number.
X			*/
X
X			if ((h + v) % 2 == 1)
X				SetBDrawMode (b, inFullBlob, dimDraw);
X		}
X	}
X	ShowBlobSet (boardBlobs);
X}
X
X
X/*
X	Set the board to the initial configuration
X*/
X
Xstatic Reset ()
X{
Xint		i;
X
X	UnglueGlobSet (boardBlobs);		/* clear all globs */
X	GlueGlob (wolf, board[hWolf = 0][vWolf = 0]);
X	for (i = 1; i < columns; i += 2)
X		GlueGlob (goat, board[i][rows - 1]);
X	current = wolf;
X	StatusMesg ("\pWolf's Move");
X	pause = false;
X}
X
X
Xstatic WolfPause (msg)
XStringPtr	msg;
X{
X	StatusMesg (msg);
X	pause = true;
X}
X
X
X/*
X	Given a blob handle, find the board position that corresponds to it.
X	This is used to map hits in the blob set (a list) to the position in
X	the board (a 2-d array).
X*/
X
Xstatic BoardPos (b, h, v)
XBlobHandle	b;
Xint			*h, *v;
X{
Xint		i, j;
X
X	for (i = 0; i < columns; ++i)
X	{
X		for (j = 0; j < rows; ++j)
X		{
X			if (board[i][j] == b)
X			{
X				*h = i;
X				*v = j;
X				return;
X			}
X		}
X	}
X	/* shouldn't ever get here */
X}
X
X
X/*
X	Check whether a board position is empty.  The coordinates must be
X	legal, the position must be used in the current configuration,
X	and the position must have a marble in it.
X*/
X
Xstatic Boolean BoardPosEmpty (h, v)
Xint		h, v;
X{
X	return (h >= 0 && h < columns && v >= 0 && v < rows
X			&& (h + v) % 2 == 0
X			&& BGlob (board[h][v]) == nil);
X}
X
X
X/*
X	Test whether a piece can move or not.  The goats can only move
X	forward (which for them means to a lower-numbered row), while the
X	wolf can move forward or backward.
X*/
X
Xstatic Boolean CanMove (h, v)
Xint		h, v;
X{
XBlobHandle	g;
X
X	g = BGlob (board[h][v]);
X	if (g == goat && v == 0)
X		return (false);		/* goats can't move from row zero */
X	return (BoardPosEmpty (h - 1, v - 1)
X			|| BoardPosEmpty (h + 1, v - 1)
X			|| (g == wolf
X				&& (BoardPosEmpty (h - 1, v + 1)
X					|| BoardPosEmpty (h + 1, v + 1))));
X}
X
X
X
Xstatic Mouse (pt, t, mods)
XPoint	pt;
Xlong	t;
Xint		mods;
X{
XStr255			s;
Xint				i;
X
X
X	if (TestBlob (resetBlob, pt))
X	{
X		if (BTrackMouse (resetBlob, pt, inFullBlob))
X			Reset ();
X	}
X	else if (!pause)
X	{
X		BlobClick (pt, t, nil, boardBlobs);
X		if (BClickResult () == bcXfer)
X		{
X			if (!CanMove (hWolf, vWolf))	/* wolf locked in? */
X				WolfPause ("\pGoats Win");
X			else if (vWolf == rows - 1)	/* wolf made it */
X				WolfPause ("\pWolf Wins");
X			else
X			{
X				current = (current == wolf ? goat : wolf);
X				StatusMesg (current == wolf ?
X								"\pWolf's Move" : "\pGoats' Move");
X			}
X		}
X	}
X}
X
X
X
X/*
X	When a piece is clicked on, the advisory checks whether the piece has
X	any legal moves available to it.  If so, it returns true, so that
X	BlobClick is allowed to drag the piece.  After the piece has been
X	dragged, the advisory checks whether the position it was dragged to
X	is legal, and returns true if so.
X
X	Messages passed to the advisory follow the pattern
X
X	{ { advRClick advRClick* } advXfer* }*
X
X	where * means 0 or more instances of the thing *'ed.  In particular,
X	the advXfer message is never seen without a preceding advRClick.
X*/
X
Xstatic Boolean Advisory (mesg, b)
Xint			mesg;
XBlobHandle	b;
X{
Xstatic int	h, v;	/* static to save board position of click on piece */
Xint			h2, v2;
XBoolean		result;
X
X	switch (mesg)
X	{
X
X	case advRClick:	/* first click on piece */
X		if (BGlob (b) != current)
X			return (false);			/* can only move current piece(s) */
X		BoardPos (b, &h, &v);	/* find where it is */
X		return (CanMove (h, v));
X
X	case advXfer:	/* Mouse released after dragging piece */
X
X		BoardPos (b, &h2, &v2);
X		result = ((h2 == h - 1 && v2 == v - 1)
X			|| (h2 == h + 1 && v2 == v - 1)
X			|| (current == wolf
X				&& ((h2 == h - 1 && v2 == v + 1)
X					|| (h2 == h + 1 && v2 == v + 1))));
X		if (result == true && current == wolf)
X		{
X			hWolf = h2;		/* update wolf's position */
X			vWolf = v2;
X		}
X		return (result);
X	}
X}
X
X
X
X/*
X	Activate the window:  Set the advisory function and set the permissions
X	to transfer-only.  Clear, replace, duplication and swap are off.
X	Since replace is off, the advisory doesn't have to check whether
X	the dragged piece was dragged onto a blob that already has a glob.
X
X	Deactivate the window:  Clear the advisory.
X*/
X
Xstatic Activate (active)
XBoolean	active;
X{
X
X	if (active)
X	{
X		SetDragRects (wolfPort);
X		SetBCPermissions (false, true, false, false, false);	/* xfer only */
X		SetBCAdvisory (Advisory);
X	}
X	else
X	{
X		SetBCAdvisory (nil);
X	}
X}
X
X
Xstatic Update (resized)
XBoolean	resized;
X{
X	DrawBlobSet (boardBlobs);
X	DrawBlob (resetBlob, inFullBlob);
X	StatusMesg (statusStr);
X}
X
X
XWolfInit	()
X{
XRect	r;
X
X	SkelWindow (wolfPort = GetDemoWind (wolfWindRes),
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 = wolfPort->portRect.right / 2;
X
X	MakeDonors ();
X	InitBoard ();
X	MakeButton ();
X	Reset ();
X	ValidRect (&wolfPort->portRect);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/PickWord.c
X/*
X	Blob ManagerDemo:  Random word picker
X*/
X
X
X# define	maxWords	700
X
X
Xstatic char    *word[] =
X{
X"\paback",
X"\pabalone",
X"\pabandon",
X"\pabase",
X"\paccent",
X"\paccentuate",
X"\paccept",
X"\pacerbic",
X"\pacrobat",
X"\padage",
X"\padagio",
X"\padamant",
X"\padapt",
X"\padaptation",
X"\paegis",
X"\paeolian",
X"\paerate",
X"\paerial",
X"\paerobic",
X"\pairborne",
X"\paircraft",
X"\pallied",
X"\palligator",
X"\palliterate",
X"\pallocate",
X"\pambuscade",
X"\pambush",
X"\pameliorate",
X"\pamen",
X"\pamend",
X"\pangelfish",
X"\pangelic",
X"\panger",
X"\pangiosperm",
X"\pangle",
X"\pantler",
X"\panvil",
X"\panxiety",
X"\panxious",
X"\papproximate",
X"\papricot",
X"\papron",
X"\papropos",
X"\papse",
X"\parrangeable",
X"\parray",
X"\parrear",
X"\parrest",
X"\parrival",
X"\passignation",
X"\passignee",
X"\passimilate",
X"\passist",
X"\paudible",
X"\paudience",
X"\paudio",
X"\paudiotape",
X"\paudiovisual",
X"\paxiomatic",
X"\paxis",
X"\paxisymmetric",
X"\paxle",
X"\paxon",
X"\pbamboo",
X"\pbanal",
X"\pbanana",
X"\pband",
X"\pbasilar",
X"\pbasilisk",
X"\pbasin",
X"\pbasis",
X"\pbask",
X"\pbedroom",
X"\pbedside",
X"\pbedspread",
X"\pbedspring",
X"\pbedstraw",
X"\pbenevolent",
X"\pbenight",
X"\pbenign",
X"\pbent",
X"\pbenthic",
X"\pbifocal",
X"\pbifurcate",
X"\pbigotry",
X"\pbivalve",
X"\pbivouac",
X"\pbizarre",
X"\pbluebill",
X"\pbluebird",
X"\pbluebonnet",
X"\pbluebook",
X"\pbluebush",
X"\pbookish",
X"\pbookkeep",
X"\pbooklet",
X"\pbookplate",
X"\pbookseller",
X"\pbrae",
X"\pbrag",
X"\pbragging",
X"\pbraid",
X"\pbrain",
X"\pbring",
X"\pbrink",
X"\pbriny",
X"\pbrisk",
X"\pbugle",
X"\pbuild",
X"\pbuildup",
X"\pbuilt",
X"\pbuiltin",
X"\pbutene",
X"\pbutler",
X"\pbutte",
X"\pcaliph",
X"\pcalisthenic",
X"\pcall",
X"\pcalumny",
X"\pcalypso",
X"\pcamera",
X"\pcamouflage",
X"\pcandlestick",
X"\pcapacitive",
X"\pcapacity",
X"\pcape",
X"\pcapella",
X"\pcartwheel",
X"\pcarve",
X"\pcascade",
X"\pcedilla",
X"\pceil",
X"\pcelandine",
X"\pcelebrant",
X"\pcelebrate",
X"\pchangeable",
X"\pchangeover",
X"\pchannel",
X"\pchant",
X"\pchicory",
X"\pchide",
X"\pchief",
X"\pchiefdom",
X"\pchieftain",
X"\pclassmate",
X"\pclassroom",
X"\pclassy",
X"\pclatter",
X"\pclattery",
X"\pcoachwork",
X"\pcoadjutor",
X"\pcoagulable",
X"\pcola",
X"\pcolander",
X"\pcolatitude",
X"\pcold",
X"\pcoleus",
X"\pcommit",
X"\pcommittable",
X"\pconceal",
X"\pconcede",
X"\pconceit",
X"\pconceive",
X"\pconcentrate",
X"\pcongener",
X"\pcongenital",
X"\pcongest",
X"\pcongestion",
X"\pcontaminant",
X"\pcontemplate",
X"\pcontemporary",
X"\pcontempt",
X"\pcool",
X"\pcoolant",
X"\pcoolheaded",
X"\pcoon",
X"\pcoop",
X"\pcosine",
X"\pcosmetic",
X"\pcosmic",
X"\pcosmology",
X"\pcowlick",
X"\pcoworker",
X"\pcowpea",
X"\pcrevice",
X"\pcrew",
X"\pcrewcut",
X"\pcrewel",
X"\pcrewman",
X"\pcubbyhole",
X"\pcube",
X"\pcubic",
X"\pcybernetics",
X"\pcycle",
X"\pcyclic",
X"\pcyclist",
X"\pdeadwood",
X"\pdeaf",
X"\pdeafen",
X"\pdeal",
X"\pdeallocate",
X"\pdeduce",
X"\pdeducible",
X"\pdeduct",
X"\pdeductible",
X"\pdeed",
X"\pdelusive",
X"\pdeluxe",
X"\pdelve",
X"\pdemagnify",
X"\pdemagogue",
X"\pdepute",
X"\pdeputy",
X"\pderail",
X"\pderange",
X"\pderate",
X"\pdeviate",
X"\pdevice",
X"\pdevil",
X"\pdevilish",
X"\pdevious",
X"\pdiffusive",
X"\pdifluoride",
X"\pdigest",
X"\pdigestible",
X"\pdisembowel",
X"\pdisgruntle",
X"\pdisgustful",
X"\pdish",
X"\pdishevel",
X"\pdockyard",
X"\pdoctor",
X"\pdoctoral",
X"\pdoctorate",
X"\pdoctrinaire",
X"\pdowitcher",
X"\pdown",
X"\pdowncast",
X"\pdowndraft",
X"\pdrought",
X"\pdrove",
X"\pdrown",
X"\pdrowse",
X"\pdrowsy",
X"\pdyspeptic",
X"\pdysplasia",
X"\pdysprosium",
X"\pdystrophy",
X"\peffluent",
X"\peffort",
X"\peffusive",
X"\pelution",
X"\pelves",
X"\pelysian",
X"\pemaciate",
X"\pencompass",
X"\pencore",
X"\pencounter",
X"\pencourage",
X"\pencroach",
X"\pentrap",
X"\pentrapping",
X"\pentreat",
X"\pentreaty",
X"\pentree",
X"\pergodic",
X"\perode",
X"\perodible",
X"\perosible",
X"\perosion",
X"\pevaporate",
X"\pevasion",
X"\pevasive",
X"\peven",
X"\pexempt",
X"\pexemption",
X"\pexercisable",
X"\pexercise",
X"\pexert",
X"\pexpressway",
X"\pexpropriate",
X"\pexpulsion",
X"\pexpunge",
X"\pexpurgate",
X"\pfair",
X"\pfairgoer",
X"\pfairway",
X"\pfairy",
X"\pfaith",
X"\pfederal",
X"\pfibula",
X"\pfiesta",
X"\pfife",
X"\pfifteen",
X"\pfifth",
X"\pfixate",
X"\pfixture",
X"\pfloor",
X"\pfloorboard",
X"\pfloppy",
X"\pfoolproof",
X"\pfootball",
X"\pfootbridge",
X"\pfootfall",
X"\pfoothill",
X"\pfootman",
X"\pfountain",
X"\pfountainhead",
X"\pfour",
X"\pfourfold",
X"\pfoursome",
X"\pfritillary",
X"\pfritter",
X"\pfrivolity",
X"\pgabardine",
X"\pgastronomy",
X"\pgate",
X"\pgesticulate",
X"\pgesture",
X"\pgetaway",
X"\pgetting",
X"\pgloat",
X"\pglob",
X"\pglobal",
X"\pgorilla",
X"\pgoshawk",
X"\pgreater",
X"\pgrebe",
X"\pgreed",
X"\pgreedy",
X"\pgreen",
X"\pguidance",
X"\pguide",
X"\pguidebook",
X"\pguideline",
X"\pguidepost",
X"\phailstorm",
X"\phair",
X"\phaircut",
X"\phairdo",
X"\phairpin",
X"\pharem",
X"\phark",
X"\pharm",
X"\pharmful",
X"\pharmonic",
X"\pheave",
X"\pheaven",
X"\pheavenward",
X"\pheavy",
X"\pheavyweight",
X"\phero",
X"\pheroic",
X"\phistorian",
X"\phistory",
X"\phood",
X"\phoodlum",
X"\phoofmark",
X"\phook",
X"\phubby",
X"\phymnal",
X"\phyperbola",
X"\pillustrious",
X"\pimage",
X"\pimaginary",
X"\pimposition",
X"\pimpossible",
X"\pimposture",
X"\pimpotent",
X"\pinclude",
X"\pincoherent",
X"\pincome",
X"\pineducable",
X"\pineffable",
X"\pineffective",
X"\pineffectual",
X"\pinfringe",
X"\pinfuriate",
X"\pinfuse",
X"\pinsightful",
X"\pinsignia",
X"\pinsincere",
X"\pinsinuate",
X"\pinsipid",
X"\pinterstitial",
X"\pinterval",
X"\pionosphere",
X"\piota",
X"\pjalopy",
X"\pjamboree",
X"\pjudge",
X"\pjudicature",
X"\pjudicial",
X"\pkeyword",
X"\pkhaki",
X"\pkibbutzim",
X"\plark",
X"\plarkspur",
X"\plarva",
X"\pleatherwork",
X"\pleave",
X"\pleaven",
X"\pliberal",
X"\pliberate",
X"\pliberty",
X"\pliquidate",
X"\plist",
X"\plonesome",
X"\plong",
X"\plongevity",
X"\plonghand",
X"\plonghorn",
X"\plunar",
X"\plunatic",
X"\plunch",
X"\pmaidservant",
X"\pmail",
X"\pmailbox",
X"\pmalice",
X"\pmansion",
X"\pmastiff",
X"\pmastodon",
X"\pmatch",
X"\pmatchbook",
X"\pmegalomaniac",
X"\pmetalwork",
X"\pmetamorphic",
X"\pmetaphor",
X"\pmillennium",
X"\pmiller",
X"\pmillet",
X"\pmoan",
X"\pmoat",
X"\pmonth",
X"\pmonument",
X"\pmood",
X"\pmuffin",
X"\pmuffle",
X"\pmyocardium",
X"\pmyopia",
X"\pneedful",
X"\pneedle",
X"\pneedlepoint",
X"\pnightmare",
X"\pnightshirt",
X"\pnighttime",
X"\pnihilism",
X"\pnoteworthy",
X"\pnothing",
X"\pnotice",
X"\pnoticeable",
X"\pnotify",
X"\pobjector",
X"\pobligatory",
X"\poblige",
X"\pofficious",
X"\poffset",
X"\popposition",
X"\poppress",
X"\postentatious",
X"\posteology",
X"\ppalette",
X"\ppalindrome",
X"\ppalisade",
X"\pparaxial",
X"\pparboil",
X"\pparcel",
X"\pparch",
X"\ppardon",
X"\ppathology",
X"\ppathway",
X"\ppatient",
X"\ppellagra",
X"\ppellet",
X"\ppelt",
X"\ppelvic",
X"\pperiwinkle",
X"\pperjure",
X"\pperjury",
X"\pperk",
X"\pphantom",
X"\ppharmacist",
X"\ppiety",
X"\ppigeon",
X"\pplacebo",
X"\pplaceholder",
X"\pplacenta",
X"\pplowshare",
X"\ppluck",
X"\pplug",
X"\ppolymorphic",
X"\ppolynomial",
X"\ppolyphony",
X"\ppolytechnic",
X"\ppostman",
X"\ppostmark",
X"\ppostmortem",
X"\ppreen",
X"\pprefabricate",
X"\ppreface",
X"\pprincess",
X"\pprinciple",
X"\pprint",
X"\pprompt",
X"\ppromulgate",
X"\pprone",
X"\pprong",
X"\pprovidential",
X"\pprovince",
X"\pprovision",
X"\ppunt",
X"\ppuny",
X"\ppupal",
X"\pquantum",
X"\pquarantine",
X"\pquark",
X"\pquarrel",
X"\pquiet",
X"\pradio",
X"\pradioactive",
X"\pradiocarbon",
X"\praucous",
X"\pravel",
X"\praven",
X"\predactor",
X"\predcoat",
X"\predden",
X"\preliant",
X"\prelic",
X"\prelieve",
X"\prescind",
X"\prescue",
X"\presemble",
X"\present",
X"\pretrovision",
X"\preturn",
X"\preveal",
X"\prevelation",
X"\prightward",
X"\prigid",
X"\prigorous",
X"\prill",
X"\prose",
X"\prosebud",
X"\prosebush",
X"\prosette",
X"\prusset",
X"\prust",
X"\prustic",
X"\prustle",
X"\psalvo",
X"\psame",
X"\psaxophone",
X"\pscabbard",
X"\pscout",
X"\pscowl",
X"\pscraggly",
X"\pscram",
X"\psecrecy",
X"\psecret",
X"\psecretarial",
X"\pseparate",
X"\pshaky",
X"\pshale",
X"\pshallot",
X"\pshoemaker",
X"\pshoestring",
X"\pshone",
X"\psideboard",
X"\psidecar",
X"\psidelight",
X"\psideline",
X"\psingsong",
X"\psingular",
X"\psinistral",
X"\pslander",
X"\pslang",
X"\pslant",
X"\pslap",
X"\psmile",
X"\psmirk",
X"\psmithereens",
X"\psmithy",
X"\psocial",
X"\psociety",
X"\psophistry",
X"\psophomore",
X"\psoprano",
X"\pspecify",
X"\pspecimen",
X"\pspecious",
X"\pspeckle",
X"\pspokesmen",
X"\psponge",
X"\psponsor",
X"\pspontaneity",
X"\pstable",
X"\pstableman",
X"\pstaccato",
X"\pstealthy",
X"\psteam",
X"\psteamboat",
X"\psteed",
X"\pstonewall",
X"\pstoneware",
X"\pstonewort",
X"\pstony",
X"\pstrontium",
X"\pstrophe",
X"\pstrove",
X"\psuccumb",
X"\psuch",
X"\psuckling",
X"\psuperstition",
X"\psupervene",
X"\psupervisory",
X"\psupine",
X"\psweepstake",
X"\psweetheart",
X"\pswell",
X"\psystematic",
X"\psystemic",
X"\ptapping",
X"\ptarantula",
X"\pteleost",
X"\ptelepathic",
X"\ptelephone",
X"\ptestimony",
X"\ptesty",
X"\pthieves",
X"\pthigh",
X"\pthimble",
X"\pthreadbare",
X"\ptiara",
X"\ptibia",
X"\ptick",
X"\pticket",
X"\ptickle",
X"\ptolerant",
X"\ptoll",
X"\ptollhouse",
X"\ptownhouse",
X"\ptownsman",
X"\ptoxic",
X"\ptoxicology",
X"\ptrap",
X"\ptrapezium",
X"\ptrapezoid",
X"\ptrip",
X"\ptripartite",
X"\ptripe",
X"\ptriple",
X"\ptriplet",
X"\ptumultuous",
X"\ptuna",
X"\ptundra",
X"\ptune",
X"\ptyranny",
X"\pupshot",
X"\pupstair",
X"\pvanguard",
X"\pvanilla",
X"\pvanish",
X"\pvanity",
X"\pvanquish",
X"\pvertical",
X"\pvertices",
X"\pvertigo",
X"\pvery",
X"\pvirtue",
X"\pviscount",
X"\pviscous",
X"\pvise",
X"\pvisible",
X"\pwail",
X"\pwaist",
X"\pwaistcoat",
X"\pwaistline",
X"\pwaterproof",
X"\pwatershed",
X"\pwaterway",
X"\pwatery",
X"\pwheat",
X"\pwheedle",
X"\pwheel",
X"\pwheelbase",
X"\pwield",
X"\pwiener",
X"\pwife",
X"\pwindbag",
X"\pwoebegone",
X"\pwoke",
X"\pwring",
X"\pwrinkle",
X"\pwrist",
X"\pyule",
X"\pzero",
X"\pzinc",
X"\pzucchini",
X"\pzygodactyl"
X};
X
Xstatic int	wOrder[maxWords];
Xstatic int	wIndex = maxWords;
X
X
Xchar *PickWord ()
X{
Xint		i, j, n;
X
X	if (wIndex >= maxWords)
X	{
X/*
X	Initialize the array with the values 0 .. maxWords-1.
X	Randomize it by walking through it one element at a time,
X	swapping the contents of each element with a randomly chosen
X	other element.  This pretty much ensures that each element
X	is swapped at least once (though not necessarily), and takes
X	time linearly related to the length of the array.
X*/
X
X		for (i = 0; i < maxWords; ++i)
X			wOrder[i] = i;
X		for (i = 0; i < maxWords; ++i)
X		{
X			j = BlobRand (maxWords - 1);
X			n = wOrder[i];
X			wOrder[i] = wOrder[j];
X			wOrder[j] = n;
X		}
X
X		wIndex = 0;
X	}
X
X	return (word[wOrder[wIndex++]]);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/TextDlog.c
X/*
X	Present a dialog box with a text rectangle, a scroll bar, and an OK
X	button.  This can be used as a help dialog.  Pass in a dialog
X	resource number and a handle to the text.  The dialog should
X	have the OK button as the first item, and user items for the
X	second and third items.  The second is the rect in which the
X	control is drawn, the third is the rect in which text is drawn.
X	Only the OK button should be enabled.
X
X	The text handle should be locked before calling TextDlog and
X	unlocked after.
X*/
X
X# include	<EventMgr.h>
X# include	<DialogMgr.h>
X# include	<ControlMgr.h>
X
X# define	nil		0L
X
Xenum		/* item numbers */
X{
X	okBut = 1,
X	scrollBarUser,
X	textRectUser
X};
X
Xstatic ControlHandle	theScroll;
Xstatic Boolean			needScroll;	/* true if need scroll bar */
Xstatic int				curLine;
Xstatic int				halfPage;
Xstatic TEHandle			teHand;
X
X
X/*
X	Proc for drawing scroll bar user item.
X*/
X
Xstatic pascal void DrawScroll (theDialog, itemNo)
XDialogPtr	theDialog;
Xint			itemNo;
X{
X	if (needScroll)
X		ShowControl (theScroll);
X}
X
X
X/*
X	Proc for drawing text display user item.
X*/
X
Xstatic pascal void DrawTextRect (theDialog, itemNo)
XDialogPtr	theDialog;
Xint			itemNo;
X{
XRect	r;
Xint		itemType;
XHandle	itemHandle;
X
X	GetDItem (theDialog, textRectUser, &itemType, &itemHandle, &r);
X	if (needScroll)
X		FrameRect (&r);
X	r = (**teHand).viewRect;
X	TEUpdate (&r, teHand);
X}
X
X
X/*
X	Scroll to the correct position.  lDelta is the
X	amount to CHANGE the current scroll setting by.
X*/
X
Xstatic DoScroll (lDelta)
Xint		lDelta;
X{
Xint	newLine;
X
X	newLine = curLine + lDelta;
X	if (newLine < 0) newLine = 0;
X	if (newLine > GetCtlMax (theScroll)) newLine = GetCtlMax (theScroll);
X	SetCtlValue (theScroll, newLine);
X	lDelta = (curLine - newLine ) * (**teHand).lineHeight;
X	TEScroll (0, lDelta, teHand);
X	curLine = newLine;
X}
X
X
Xstatic pascal void __TrackScroll (theScroll, partCode)
XControlHandle	theScroll;
Xint				partCode;
X{
Xint	lDelta;
X
X	if (partCode == GetCRefCon (theScroll))	/* still in same part? */
X	{
X		switch (partCode)
X		{
X			case inUpButton: lDelta = -1; break;
X			case inDownButton: lDelta = 1; break;
X			case inPageUp: lDelta = -halfPage; break;
X			case inPageDown: lDelta = halfPage; break;
X		}
X		DoScroll (lDelta);
X	}
X}
X
X
X/*
X	Filter to handle hits in scroll bar
X*/
X
Xstatic pascal Boolean TextFilter (theDialog, theEvent, itemHit)
XDialogPtr	theDialog;
XEventRecord	*theEvent;
Xint			*itemHit;
X{
XPoint	thePoint;
Xint		thePart;
X
X	if (theEvent->what == mouseDown)
X	{
X		thePoint = theEvent->where;
X		GlobalToLocal (&thePoint);
X		thePart = TestControl (theScroll, thePoint);
X		if (thePart == inThumb)
X		{
X			(void) TrackControl (theScroll, thePoint, nil);
X			DoScroll (GetCtlValue (theScroll) - curLine);
X		}
X		else if (thePart != 0)
X		{
X			SetCRefCon (theScroll, (long) thePart);
X			(void) TrackControl (theScroll, thePoint, __TrackScroll);
X		}
X	}
X	return (false);
X}
X
X
XTextDialog (dlogNum, textHandle, fontNum, fontSize, wrap)
Xint		dlogNum;
XHandle	textHandle;
Xint		fontNum;
Xint		fontSize;
XBoolean	wrap;
X{
XGrafPtr		oldPort;
XDialogPtr	theDialog;
Xint			itemNo;
Xint			itemType;
XHandle		itemHandle;
XRect		r;
Xint			scrollLines;
Xint			viewLines;
XHandle		oldHText;
XProcPtr		filterProc = nil;
X
X	GetPort (&oldPort);
X	theDialog = GetNewDialog (dlogNum, nil, -1L);
X	GetDItem (theDialog, textRectUser, &itemType, &itemHandle, &r);
X	SetDItem (theDialog, textRectUser, itemType, DrawTextRect, &r);
X/*
X	incorporate text into a TERec.
X*/
X	SetPort (theDialog);
X	TextFont (fontNum);
X	TextSize (fontSize);
X	InsetRect (&r, 4, 4);
X	teHand = TENew (&r, &r);
X	if (!wrap)
X		(**teHand).crOnly = -1;
X	oldHText = (**teHand).hText;		/* save this.  restore later */
X	(**teHand).hText = textHandle;
X	TECalText (teHand);
X	viewLines = (r.bottom - r.top) / (**teHand).lineHeight;
X	scrollLines = (**teHand).nLines - viewLines;
X	needScroll = (scrollLines > 0);
X	GetDItem (theDialog, scrollBarUser, &itemType, &itemHandle, &r);
X	SetDItem (theDialog, scrollBarUser, itemType, DrawScroll, &r);
X	if (needScroll)
X	{
X		theScroll = NewControl (theDialog, &r, "\p", false, 0, 0, 0,
X						scrollBarProc, nil);
X		SetCtlMax (theScroll, scrollLines);
X		halfPage = viewLines / 2;
X		curLine = 0;
X		filterProc = (ProcPtr) TextFilter;
X	}
X
X	ShowWindow (theDialog);
X	/*do {*/
X		ModalDialog (filterProc, &itemNo);
X	/*} while (itemNo != okBut);*/
X
X/*
X	restore hText field of TE record before disposing of it.
X*/
X	(**teHand).hText = oldHText;
X	TEDispose (teHand);
X	/*ReleaseResource (textHandle);*/
X	if (needScroll)
X		DisposeControl (theScroll);
X	SetPort (oldPort);
X	DisposDialog(theDialog);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/Demo.helptext
XThis program demonstrates the Macintosh Blob Manager.  Each of the several windows contains a different scenario.  Some scenarios have auxiliary menus, which appear whenever the appropriate window is in front.  A window may be hidden by clicking its close box, and made to reappear with the Windows menu.  The Windows menu may also be used to bring a window to the front. 
X
XGeneral Instructions 
X
XAll scenarios are entirely mouse-based.  Most share the characteristic that to do something, you click on a likely-looking object and drag it onto another likely-looking object.  The dragged object then becomes glued to the dragged-to object.  Often connections can be severed by double-clicking on the dragged-to object, or by dragging a glued object onto another object.  These instructions are deliberately vague; if you don't know what to do, experiment.  Below are some hints. 
X
XAnagrams 
X
XUnscramble the letters to make a word.  If you don't know, push the Answer button. 
X
XArithmetic 
X
XSimple arithmetic problems.  Drag digits onto the appropriate positions of the sum.  You can also drag digits into the carry positions.  Digits may be dragged from any existing digit into the sum or the carry digits. 
X
XUse the Radix menu to change the base of the numbering system in which the problems are presented - anywhere from base 2 (binary) to base 10 (decimal). 
X
XTo see your progress during a problem, click Check.  Continue by clicking Resume.  To see the answer, click Uncle.  To skip a problem, click Next. The scenario detects when you complete a problem correctly by disallowing blob transactions and highlighting only the Next button. 
X
XCoin Swap
X
XThe object is to switch the positions of the white coins and the black coins.  You must do it in the specified number of moves to win.  A coin can be slid into an empty position next to it, or can jump over one coin into an empty space.  To restart, select a configuration from the Configuration menu.
X
XFifteen-A-Row 
X
XDrag digits onto the star so that the three digits along every axis of the star sum to fifteen.  There are many solutions, but they all share one central characteristic.  When you solve the problem correctly, a Restart button appears. 
X
XFish Sticks 
X
XSwitch the pieces of the picture around to reassemble the image of the fish.
X
XFox, Goose, Grain 
X
XA classical problem.  The farmer wants to move the fox, the goose and the grain to the other side of the river.  He can use his boat to ferry things from one side of the river to the other, but he can only put one thing in the boat at a time.  The fox will eat the goose if they are left alone together, and the goose will eat the grain if they are left alone.  To move, drag something into the boat and hit the Move Left/Move Right button to make the boat move.  Then drag the object out of the boat onto the 
opposite bank.  If you make a mistake, the scenario gloats.  If you complete the mission successfully, the scenario announces it.  In either case, hit the Restart button to continue. 
X
XHangman 
X
XA word-guessing game.  Click on a letter to choose it.  You get seven misses before the man hangs.  Click Next to go to the next word. 
X
XHebrew Alephbet 
X
XLearn the Hebrew alphabet.  The object is to match the letters with their names. Initially the letters are in the same order as the names.  To destroy this correspondence, click Shuffle.  To see which letters you've got correct, click Check:  the letters that are incorrect go dim.  To see the answer, click Answer.  (When you click Resume, the display reverts to its previous state, so you don't lose your work).  When you get all the letters right, all buttons but Shuffle and Reset go dim.  Click Reset to s
tart over. 
X
XMagic Square
X
XArrange the numbers within the square so that every column, row and diagonal sums to fifteen.
X
XPeg Solitaire
X
XAll moves are made by jumping a peg over another.  The jumped peg is removed from the board.  The object is to get the pegs into the gray slots in the specified number of moves.  To restart, select a configuration from the Configuration menu.
X
XPong hau k'i
X
XA simple oriental board game.  Moves are allowed only between circles connected by a line.  Each player tries to position his pieces so that the other player cannot move.
X
XPyramid
X
XEach player tries to reassemble the pyramid formed by the pieces, on the opposite side of the board.  Pieces can move into adjacent diagonal spaces, or jump over other pieces, in any direction.  A piece may make more than one jump in a single turn (but you must click on it for each jump).
X
XState Capitals 
X
XNames of the original thirteen United States must be matched with the names of their capitals. 
X
XTic-Tac-Toe 
X
XThe rules for this are the same as you'd expect.  After a game is played, the loser goes first on the next game.  For cat's game, whoever went second in the previous game goes first. 
X
XOn your first move, you must drag the playing piece from the top of the scenario onto the board.  On subsequent moves, you can drag that piece, or duplicate one of the pieces already on the board, by dragging it to another board position. 
X
XTower of Hanoi 
X
XThe object is to move the set of rings from one post to another.  Only one ring may be moved at a time, and a larger ring may not be placed on a smaller one. 
X
XWolf & Goats
X
XAll moves are into adjoining diagonal squares.  The wolf can move forward or backward, the goats only forward.  The goats try to trap the wolf so he can't move, while the wolf tries to get past the goats to the other side of the board.
X
X
XThis application was implemented using the Macintosh Blob Manager and the TransSkel transportable application skeleton, both of which were written by Paul DuBois (to whom comment should be directed). 
X
XU.S. Mail:
X  Paul DuBois
X  1220 Capitol Court
X  Madison, WI  53706 
X
XElectronic mail: 
X
X  UUCP: {allegra, ihnp4, seismo}!uwvax!uwmacc!dubois
X  ARPA: dubois@easter
X             dubois@unix.macc.wisc.edu
SHAR_EOF
exit