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