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