maci...@felix.uucp
unread,Jan 30, 1987, 2:00:06 AM1/30/87You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# BlobDemo/DemoHeb.c
# BlobDemo/DemoLib.c
# BlobDemo/DemoMagicSquare.c
# BlobDemo/DemoMain.c
# BlobDemo/DemoMenu.c
# BlobDemo/DemoPeg.c
mkdir BlobDemo
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoHeb.c
X/*
X Blob Manager Demonstration: Hebrew Alephbet module
X
X 26 July 1986 Paul DuBois
X*/
X
X
X# include "BlobDemo.h"
X# include <ControlMgr.h>
X# include <ResourceMgr.h>
X
X
X# define nLetters 22 /* 22 letters in Hebrew alephbet */
X# define iconSize 32 /* standard icon is 32x32 */
X# define sitmSize 16 /* sicn item is 16 x 16 */
X# define rWidth 76 /* receptor blob width and height */
X# define rHeight 22
X# define rHGap 2 /* horizontal and vertical gaps */
X# define rVGap 5 /* between receptor blobs */
X# define dWidth sitmSize /* ditto for donors */
X# define dHeight sitmSize
X# define dHGap 12
X# define dVGap 4
X
X# define pauseAns 1 /* what kind of pause? */
X# define pauseMatch 2
X
Xtypedef int Sitm[sitmSize];
Xtypedef Sitm Sicn[1];
Xtypedef Sicn **SicnHandle;
X
Xstatic GrafPtr hebPort;
Xstatic BlobSetHandle hebDonors;
Xstatic BlobSetHandle hebReceptors;
X
Xstatic ControlHandle matchCtl;
Xstatic ControlHandle resumeCtl;
Xstatic ControlHandle resetCtl;
Xstatic ControlHandle shuffleCtl;
Xstatic ControlHandle ansCtl;
X
Xstatic Boolean paused = false;
Xstatic int pauseType;
X
X
X/*
X Plot sicn item in given rectangle.
X This is exactly analogous to the ToolBox PlotIcon routine,
X except that the item number within the sicn must be specified.
X*/
X
X
XPlotSicn (r, s, i)
XRect *r;
XSicnHandle s;
Xint i;
X{
XGrafPtr thePort;
XBitMap bm;
XSitm tmpSitm;
X
X /* create a small bitmap */
X BlockMove (&((**s)[i]), &tmpSitm, (long) sizeof (Sitm));
X bm.baseAddr = (Ptr) &tmpSitm;
X bm.rowBytes = 2; /* items are 16 bits wide */
X SetRect (&bm.bounds, 0, 0, sitmSize, sitmSize);
X GetPort (&thePort);
X CopyBits (&bm, &thePort->portBits, &bm.bounds, r, srcCopy, nil);
X}
X
X
XHebActivate (active)
XBoolean active;
X{
X if (active)
X {
X SetDragRects (hebPort);
X SetBCPermissions (true, true, false, true, true);
X }
X}
X
X
XHebUpdate (resized)
XBoolean resized;
X{
Xint mode;
XPattern p;
X
X DrawControls (hebPort);
X DrawBlobSet (hebDonors);
X GetBDimInfo (&p, &mode);
X if (paused && pauseType == pauseMatch)
X SetBDimInfo (black, patXor);
X DrawBlobSet (hebReceptors);
X SetBDimInfo (p, mode);
X}
X
X
XLightControls ()
X{
Xint i;
X
X i = (paused ? 0 : 255);
X HiliteControl (matchCtl, 255 - i);
X HiliteControl (resetCtl, 255 - i);
X HiliteControl (ansCtl, 255 - i);
X HiliteControl (resumeCtl, i);
X}
X
X
XHebMoveBlobs (bSet, n1, n2, x, y, xd)
XBlobSetHandle bSet;
Xint n1, n2, x, y, xd;
X{
X for ( ; n1 <= n2; ++n1)
X {
X MoveBlob (GetBlobHandle (bSet, n1), inFullBlob, x, y);
X x += xd;
X }
X}
X
X
XHebMakeBlobs ()
X{
Xint i;
Xint h, v;
XRect tRect, lRect, sitmRect;
XSicnHandle letterSicn;
XStr255 rName;
XBlobHandle b1, b2;
Xint hMid;
Xint x, y, delta;
X
X hMid = hebPort->portRect.right / 2 - 4;
X
X letterSicn = (SicnHandle) GetResource ('SICN', letrSicnNo);
X hebDonors = NewBlobSet ();
X hebReceptors = NewBlobSet ();
X for (i = 0; i < nLetters; ++i)
X {
X b1 = NewBlob (hebDonors, false, 1, false, 0L);
X b2 = NewBlob (hebReceptors, false, 0, true, 0L);
X NewBlobMatch (b1, b2); /* assign donor -> receptor mapping */
X GetIndString (&rName, nameStrNo, i+1);
X OpenBlob (); /* draw source blob */
X SetRect (&sitmRect, 0, 0, sitmSize, sitmSize);
X PlotSicn (&sitmRect, letterSicn, i);
X CloseRectBlob (b1, &sitmRect, &sitmRect);
X
X OpenBlob ();
X SetRect (&tRect, 0, 5, rWidth-sitmSize-1, rHeight);
X OffsetRect (&sitmRect, rWidth-sitmSize, 5);
X TextBox (rName + 1, (long) rName[0], &tRect, 1);
X EraseRect (&sitmRect);
X FrameRect (&sitmRect);
X CloseRectBlob (b2, &sitmRect, &tRect);
X
X }
X ReleaseResource (letterSicn);
X
X/*
X now arrange the blobs on the board.
X*/
X x = hMid - 5*(dWidth+dHGap) - dWidth/2;
X delta = dWidth + dHGap;
X y = 5;
X HebMoveBlobs (hebDonors, 0, 10, x, y, delta);
X y += dHeight + dVGap;
X HebMoveBlobs (hebDonors, 11, 21, x, y, delta);
X
X x = hMid - 3*(rWidth+rHGap);
X y += dHeight + dVGap + 5;
X delta = rWidth + rHGap;
X HebMoveBlobs (hebReceptors, 0, 5, x, y, delta);
X y += rHeight + rVGap;
X HebMoveBlobs (hebReceptors, 6, 11, x, y, delta);
X y += rHeight + rVGap;
X HebMoveBlobs (hebReceptors, 12, 17, x, y, delta);
X x = hMid - 2*(rWidth+rHGap);
X y += rHeight + rVGap;
X HebMoveBlobs (hebReceptors, 18, 21, x, y, delta);
X /*ShuffleBlobSet (hebDonors);*/
X}
X
X
XHebMouse (thePt, t, mods)
XPoint thePt;
Xlong t;
Xint mods;
X{
XControlHandle ctl;
XBlobHandle b, g;
Xint mode;
XPattern p;
X
X if (!paused)
X {
X BlobClick (thePt, t, hebDonors, hebReceptors);
X if (BlobSetQuiet (hebReceptors)) /* if all correct */
X { /* override normal */
X paused = true; /* control display */
X pauseType = pauseAns;
X LightControls ();
X HiliteControl (resumeCtl, 255);
X HiliteControl (resetCtl, 0);
X FreezeBlobSet (hebReceptors);
X }
X }
X if (FindControl (thePt, hebPort, &ctl))
X {
X if (TrackControl (ctl, thePt, nil))
X {
X if (ctl == matchCtl)
X {
X paused = true;
X pauseType = pauseMatch;
X GetBDimInfo (&p, &mode); /* hilite by inverting */
X SetBDimInfo (black, patXor);
X BlobFeedback (hebReceptors, normalDraw, dimDraw);
X SetBDimInfo (p, mode);
X LightControls ();
X if (BlobSetQuiet (hebReceptors)) /* if all correct */
X { /* override normal */
X HiliteControl (resumeCtl, 255); /* control display */
X HiliteControl (resetCtl, 0);
X }
X }
X else if (ctl == ansCtl)
X {
X paused = true;
X pauseType = pauseAns;
X LightControls ();
X for (b = FirstBlob (hebReceptors); b != nil; b = NextBlob (b))
X {
X SetBRefCon (b, BGlob (b)); /* save current glob setting */
X g = FirstBMatch (b); /* attach real answer */
X if (g != BGlob (b))
X {
X ZGlueGlob (g, b);
X }
X }
X }
X else if (ctl == resumeCtl)
X {
X paused = false;
X LightControls ();
X if (pauseType == pauseMatch)
X ThawBlobSet (hebReceptors);
X else
X {
X /* restore previous attachments */
X for (b = FirstBlob (hebReceptors); b != nil; b = NextBlob (b))
X {
X g = (BlobHandle) GetBRefCon (b);
X if (g != BGlob (b))
X {
X ZUnglueGlob (b);
X GlueGlob (g, b);
X }
X }
X }
X }
X else if (ctl == resetCtl)
X {
X paused = false;
X LightControls ();
X ThawBlobSet (hebReceptors);
X ZUnglueGlobSet (hebReceptors); /* clear and redraw */
X }
X else if (ctl == shuffleCtl)
X {
X ShuffleBlobSet (hebDonors); /* shuffle letters */
X ValidRect (&hebPort->portRect);
X }
X }
X }
X}
X
X
XHebInit ()
X{
XRect r;
Xint i, j;
X
X SkelWindow (hebPort = GetDemoWind (hebWindRes),
X HebMouse, /* mouse clicks */
X nil, /* key clicks */
X HebUpdate, /* updates */
X HebActivate, /* 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 HebMakeBlobs ();
X i = hebPort->portRect.bottom - 25;
X j = hebPort->portRect.right/2 - 205;
X SetRect (&r, j, i, j+70, i+20);
X matchCtl =
X NewControl (hebPort, &r, "\pCheck", true, 0, 0, 0, pushButProc, nil);
X OffsetRect (&r, 85, 0);
X resumeCtl =
X NewControl (hebPort, &r, "\pResume", true, 0, 0, 0, pushButProc, nil);
X OffsetRect (&r, 85, 0);
X ansCtl =
X NewControl (hebPort, &r, "\pAnswer", true, 0, 0, 0, pushButProc, nil);
X OffsetRect (&r, 85, 0);
X resetCtl =
X NewControl (hebPort, &r, "\pReset", true, 0, 0, 0, pushButProc, nil);
X OffsetRect (&r, 85, 0);
X shuffleCtl =
X NewControl (hebPort, &r, "\pShuffle", true, 0, 0, 0, pushButProc, nil);
X
X LightControls ();
X
X EnableBlobSet (hebDonors);
X EnableBlobSet (hebReceptors);
X HebUpdate ();
X ValidRect (&hebPort->portRect);
X}
X
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoLib.c
X/*
X Blob Manager Demonstration: library routines
X*/
X
X# include <QuickDraw.h>
X# include "BlobDemo.h"
X
Xstatic int charBlobSize = 18;
X
X
X
X/*
X StrCpy copies the second argument into the first.
X StrCat appends the second argument to the first.
X MovesLeft creates a string that says "n Moves Left"
X
X Both assume Pascal-style strings.
X*/
X
X
XStrCpy (dst, src)
XStringPtr dst, src;
X{
Xint i;
X
X for (i = 0; i <= src[0]; ++i)
X dst[i] = src[i];
X}
X
X
XStrCat (dst, src)
XStringPtr dst, src;
X{
Xint i, dlen, slen;
X
X slen = src[0];
X dlen = dst[0];
X for (i = 1; slen > 0; ++i, --slen)
X dst[dlen + i] = src[i];
X dst[0] += src[0];
X}
X
X
XMovesLeft (n, s)
Xint n;
XStringPtr s;
X{
X NumToString (n, s);
X StrCat (s, (n == 1 ? "\p Move Left" : "\p Moves Left"));
X}
X
X
X/*
X Create and dispose of offscreen port
X*/
X
XGrafPtr NewOffPort (r)
XRect r;
X{
XGrafPtr thePort, tmpPort;
XBitMap *theMap;
Xlong bitCount;
Xint rowBytes;
XPtr bits;
X
X rowBytes = ((r.right-r.left + 15) / 8) & (~1);
X bitCount = rowBytes * (r.bottom - r.top);
X bits = NewPtr (bitCount);
X if (bits)
X {
X thePort = (GrafPtr) NewPtr ((long) sizeof (GrafPort));
X if (thePort)
X {
X theMap = (BitMap *) NewPtr ((long) sizeof (BitMap));
X if (theMap)
X {
X theMap->bounds = r;
X theMap->rowBytes = rowBytes;
X theMap->baseAddr = bits;
X GetPort (&tmpPort);
X OpenPort (thePort);
X SetPortBits (theMap);
X PortSize (r.right - r.left, r.bottom - r.top);
X RectRgn (thePort->visRgn, &thePort->portRect);
X ClipRect (&thePort->portRect);
X EraseRect (&thePort->portRect);
X SetPort (tmpPort);
X return (thePort);
X }
X DisposPtr (thePort);
X }
X DisposPtr (bits);
X }
X return (nil);
X}
X
X
XDisposeOffPort (thePort)
XGrafPtr thePort;
X{
X ClosePort (thePort);
X DisposPtr (thePort->portBits.baseAddr);
X DisposPtr (&thePort->portBits);
X DisposPtr (thePort);
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 bSet is the blob set to add the button blob to, r defines the
X bounds rect, and title is a string containing the text to be drawn
X in the blob.
X
X The glueMax and mustMatch fields are assumed to be zero and false.
X
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
XBlobHandle NewVButtonBlob (bSet, r, title, visible, refCon)
XBlobSetHandle bSet;
XRect *r;
XStringPtr title;
Xlong refCon;
X{
XBlobHandle b;
XRgnHandle rgn, rgn2;
XFontInfo fInfo;
Xint cHeight; /* character height */
Xint tHeight; /* title height */
Xint h, v;
Xint i;
X
X/*
X Make the regions defining the blob first. The drag region is inset
X by one so that the text in the middle can be dimmed without dimming
X the frame.
X*/
X
X rgn = NewRgn ();
X OpenRgn ();
X FrameRoundRect (r, 10, 10);
X CloseRgn (rgn);
X rgn2 = NewRgn ();
X CopyRgn (rgn, rgn2);
X InsetRgn (rgn2, 1, 1);
X
X /* Now make the blob and define its image */
X
X b = NewBlob (bSet, visible, 0, false, refCon);
X GetFontInfo (&fInfo);
X cHeight = fInfo.ascent + fInfo.descent;
X tHeight = title[0] * (cHeight + fInfo.leading) - fInfo.leading;
X OpenBlob ();
X v = (r->top + r->bottom - tHeight ) / 2 + fInfo.ascent;
X FillRgn (rgn2, white);
X for (i = 1; i <= title[0]; ++i)
X {
X h = (r->left + r->right - CharWidth (title[i])) / 2;
X MoveTo (h, v);
X DrawChar (title[i]);
X v += cHeight + fInfo.leading;
X }
X FrameRoundRect (r, 10, 10);
X CloseRgnBlob (b, rgn2, rgn);
X DisposeRgn (rgn);
X DisposeRgn (rgn2);
X return (b);
X}
X
X
X/*
X Determine the rectangle that defines each element of a grid,
X and pass the rectangle to a blob-drawing proc. The proc draws
X whatever goes into the element. Creates blobs a row at a time.
X*/
X
XMakeBlobGrid (rows, cols, hOff, vOff, hWidth, vHeight, hGap, vGap, p)
Xint rows, cols, hOff, vOff, hWidth, vHeight, hGap, vGap;
XProcPtr p;
X{
Xint i, j;
Xint h, v;
XRect r;
X
X for (j = 0; j < rows; ++j)
X {
X for (i = 0; i < cols; ++i)
X {
X h = hOff + i * (hGap + hWidth);
X v = vOff + j * (vGap + vHeight);
X SetRect (&r, h, v, h + hWidth, v + vHeight);
X (*p) (&r);
X }
X }
X}
X
X
X/*
X Draw a grid with the given number of rows and columns. The upper
X left-hand corner of the top element is at (hoff, voff). The
X height and width of each element is vHeight and hWidth. The horizontal
X and vertical gaps between elements are hGap and vGap. A border is
X also drawn around the whole grid.
X*/
X
XDrawGrid (rows, cols, hOff, vOff, hWidth, vHeight, hGap, vGap)
Xint rows, cols, hOff, vOff, hWidth, vHeight, hGap, vGap;
X{
Xint i;
Xint h, v;
Xint len;
XRect r;
X
X hOff -= hGap;
X vOff -= vGap;
X PenSize (hGap, vGap);
X /* draw vertical lines */
X len = rows * (vGap + vHeight);
X for (i = 0; i <= cols; ++i)
X {
X h = hOff + i * (hGap + hWidth);
X MoveTo (h, vOff);
X LineTo (h, vOff + len);
X }
X /* draw horizontal lines */
X len = cols * (hGap + hWidth);
X for (i = 0; i <= rows; ++i)
X {
X v = vOff + i * (vGap + vHeight);
X MoveTo (hOff, v);
X LineTo (hOff + len, v);
X }
X PenNormal ();
X}
X
X
X/*
X Drawing proc for character blobs
X*/
X
XDrawCharBlob (bDst, bSrc, partCode)
XBlobHandle bDst, bSrc;
Xint partCode;
X{
XRect r;
Xchar c;
X
X r = BDragBox (bDst);
X c = (char) LoWord (GetBRefCon (bSrc));
X if (c == ' ')
X {
X EraseRoundRect (&r, 10, 10);
X FrameRoundRect (&r, 10, 10);
X }
X else
X {
X TextBox (&c, 1L, &r, 1);
X }
X}
X
X
X/*
X Make a blob with a character in the middle (or a frame if the
X character is a space). Pass all the normal NewBlob parameters
X except the reference constant, plus the horizontal and vertical
X coordinates, and the character to be drawn in the blob.
X
X The char is stored as the low word of the reference value. The
X application can put whatever it wants in the high word.
X*/
X
X
XBlobHandle MakeCharBlob (bSet, enable, glueMVal, mustMatch, h, v, c)
XBlobSetHandle bSet;
XBoolean enable;
Xint glueMVal;
XBoolean mustMatch;
Xint h, v;
Xchar c;
X{
XBlobHandle b;
XRect r;
X
X b = NewBlob (bSet, enable, glueMVal, mustMatch, (long) c);
X SetRect (&r, h, v, h + charBlobSize, v + charBlobSize);
X SetProcRectBlob (b, DrawCharBlob, &r, &r);
X return (b);
X}
X
X
X/*
X Set the size in which character blobs are created
X*/
X
XSetCharBlobSize (size)
Xint size;
X{
X charBlobSize = size;
X}SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoMagicSquare.c
X/*
X Blob Manager Demonstration: Magic Square
X
X All rows, columns and diagonals of a square must add up to 15.
X
X This is a donorless scenario. The receptors are created, then glued
X to themselves initially so that they will each have a glob to drag
X around.
X
X 26 July 1986 Paul DuBois
X*/
X
X# include "BlobDemo.h"
X# include <ControlMgr.h>
X
X
X# define vButton 5
X# define vBoard 30 /* offset of top of board */
X# define hGap 2
X# define vGap 2
X# define bSqSize 30 /* board square size */
X
X
Xstatic GrafPtr magicPort;
Xstatic BlobSetHandle receptors;
X
Xstatic Boolean wait;
Xstatic ControlHandle button;
Xstatic int hMid;
Xstatic int hBoard;
X
X
Xstatic Restart ()
X{
X
X HiliteControl (button, 255);
X ShuffleGlobSet (receptors);
X wait = false;
X}
X
X
Xstatic Boolean TestConfig (pos1, pos2, pos3)
Xint pos1, pos2, pos3;
X{
Xint sum;
X
X sum = GetBRefCon (BGlob (GetBlobHandle (receptors, pos1)))
X + GetBRefCon (BGlob (GetBlobHandle (receptors, pos2)))
X + GetBRefCon (BGlob (GetBlobHandle (receptors, pos3)));
X return (sum == 15);
X}
X
X
Xstatic CheckStatus ()
X{
X if (TestConfig (0, 1, 2) /* top row */
X && TestConfig (3, 4, 5) /* middle row */
X && TestConfig (6, 7, 8) /* bottom row */
X && TestConfig (0, 3, 6) /* left column */
X && TestConfig (1, 4, 7) /* middle column */
X && TestConfig (2, 5, 8) /* right column */
X && TestConfig (0, 4, 8) /* diagonal */
X && TestConfig (2, 4, 6) ) /* diagonal */
X {
X HiliteControl (button, 0);
X wait = true;
X }
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, magicPort, &ctl))
X {
X if (TrackControl (ctl, pt, nil))
X Restart ();
X }
X else if (!wait)
X BlobClick (pt, t, nil, receptors);
X/*
X Check status even if user just restarted, since the square may
X by chance fall into a correct configuration. In that case,
X the CheckStatus will again enable the restart button.
X*/
X CheckStatus ();
X}
X
X
Xstatic Update (resized)
XBoolean resized;
X{
X DrawControls (magicPort);
X DrawBlobSet (receptors);
X}
X
X
Xstatic Activate (active)
XBoolean active;
X{
X if (active)
X {
X SetDragRects (magicPort);
X SetBCPermissions (false, false, false, true, true);
X }
X}
X
X
X/*
X Make receptor blob
X*/
X
Xstatic MakeRBlob (r)
XRect *r;
X{
XBlobHandle b;
Xchar c;
Xstatic long rno = 0L;
X
X b = NewBlob (receptors, false, infiniteGlue, false, ++rno);
X OpenBlob ();
X EraseRect (r);
X FrameRect (r);
X InsetRect (r, 5, 7);
X c = rno + '0';
X TextBox (&c, 1L, r, 1);
X InsetRect (r, -3, -5);
X InvertRect (r);
X InsetRect (r, -2, -2);
X CloseRectBlob (b, r, r);
X GlueGlob (b, b);
X}
X
X
Xstatic MakeReceptors ()
X{
X receptors = NewBlobSet ();
X MakeBlobGrid (3, 3, hBoard, vBoard, bSqSize, bSqSize,
X hGap, vGap, MakeRBlob);
X}
X
X
XMagicInit ()
X{
XRect r;
X
X magicPort = GetDemoWind (magicWindRes);
X SkelWindow (magicPort,
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 = magicPort->portRect.right / 2;
X hBoard = hMid - (3 * (bSqSize + hGap) - hGap) / 2;
X SetRect (&r, hMid - 40, vButton, hMid + 40, vButton + 20);
X button = NewControl (magicPort, &r, "\pReset", true, 0, 0, 0,
X pushButProc, nil);
X
X MakeReceptors ();
X ShowBlobSet (receptors);
X Restart ();
X ValidRect (&magicPort->portRect);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoMain.c
X/*
X Blob Manager Demonstration: Main module
X
X 25 June 1986 Paul DuBois
X*/
X
X# include <QuickDraw.h>
X
X
Xlong diskInfoKludge;
X
X
X
Xmain ()
X{
Xint i;
X
X SkelInit (); /* initialize TransSkel */
X
X randSeed = TickCount ();
X
X SetupMenus ();
X
X/*
X Initialize the various scenarios. Any of them may be entirely
X disabled simply by commenting out the initialization line.
X*/
X
X WolfInit ();
X TohInit ();
X TttInit ();
X StatesInit ();
X PyrInit ();
X PongInit ();
X PegInit ();
X MagicInit ();
X HebInit ();
X HangInit ();
X FggInit ();
X FshInit ();
X FarInit ();
X SwapInit ();
X RadixInit ();
X AnagramInit ();
X
X AddWindowTitles (); /* add window names to Windows menu */
X
X SkelMain (); /* loop 'til Quit selected */
X
X DisposeBlobSets (); /* shut down the Blob Manager */
X SkelClobber (); /* and TransSkel */
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoMenu.c
X/*
X Blob Manager Demonstration: Handlers for standard menus (those
X that stick around all the time). Menus that exist only when
X are particular window is in front are installed and removed by
X the handler for that window.
X
X 12 July 1986 Paul DuBois
X*/
X
X# include "BlobDemo.h"
X# include <WindowMgr.h>
X# include <MenuMgr.h>
X# include <FontMgr.h>
X
X
Xstatic MenuHandle fileMenu;
Xstatic MenuHandle editMenu;
Xstatic MenuHandle windMenu;
X
X
X/*
X wPtr is used to map Windows menu items onto the windows associated
X with each item.
X*/
X
Xstatic WindowPtr wPtr[lastWindRes-firstWindRes];
Xstatic int wCount = 0;
X
X
XDoAbout ()
X{
X (void) Alert (aboutAlrtRes, nil);
X}
X
X
XDoFileMenu (item)
Xint item;
X{
XHandle h;
X
X switch (item)
X {
X case getInfo:
X {
X h = GetResource ('TEXT', helpTextRes);
X HLock (h);
X TextDialog (textDlogRes, h, 0, 0, true);
X HUnlock (h);
X ReleaseResource (h);
X break;
X }
X case quit:
X {
X SkelWhoa (); /* tell SkelMain to quit */
X break;
X }
X }
X}
X
X
XDoEditMenu (item)
Xint item;
X{
X (void) SystemEdit (item - 1); /* route to DA if appropriate */
X}
X
X
X/*
X The Windows menu is used to select a given window and bring it
X to the front. It also makes it visible if it wasn't already.
X*/
X
XDoWindMenu (item)
Xint item;
X{
X SelectWindow (wPtr[item-1]);
X ShowWindow (wPtr[item-1]);
X}
X
X
X/*
X Add title of each window to the Windows menu. Save the WindowPtr for
X use later if the window is selected from the menu.
X*/
X
X
X
XAddWindowTitles ()
X{
XWindowPeek theWind;
XStr255 title;
X
X theWind = (WindowPeek) FrontWindow ();
X while (theWind != nil)
X {
X GetWTitle (theWind, &title);
X AppendMenu (windMenu, title);
X wPtr[wCount++] = (WindowPtr) theWind;
X theWind = theWind->nextWindow;
X }
X}
X
X
X/*
X Clobber proc for menu handlers
X*/
X
XDoMClobber (theMenu)
XHandle theMenu;
X{
X ReleaseResource (theMenu);
X}
X
X
X/*
X Background task: enable Edit menu when a DA window is in front.
X Disable it when a demo window is in front. Since this procedure
X is executed continually, only mess with the menu bar on a change
X of state.
X*/
X
XBackground ()
X{
Xstatic Boolean editEnable = false;
XWindowPeek wPeek;
X
X if ( (wPeek = (WindowPeek) FrontWindow ()) == nil
X || wPeek->windowKind >= 0) /* DA not in front */
X {
X if (editEnable)
X {
X DisableItem (editMenu, 0);
X DrawMenuBar ();
X editEnable = false;
X };
X }
X else if (!editEnable) /* DA window in front */
X {
X EnableItem (editMenu, 0);
X DrawMenuBar ();
X editEnable = true;
X }
X}
X
X
X/*
X Set up menus: Tell LightSkel to make a default Apple menu handler,
X create handlers for the File, Edit and Windows menus. Install
X background task that enables/disables Edit menu.
X*/
X
XSetupMenus ()
X{
X
X SkelApple ("\pAbout BlobMgr DemoI", DoAbout);
X fileMenu = GetMenu (fileMenuRes);
X SkelMenu (fileMenu, DoFileMenu, DoMClobber);
X editMenu = GetMenu (editMenuRes);
X SkelMenu (editMenu, DoEditMenu, DoMClobber);
X windMenu = GetMenu (windMenuRes);
X SkelMenu (windMenu, DoWindMenu, DoMClobber);
X SkelBackground (Background);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BlobDemo/DemoPeg.c
X/*
X Blob Manager Demonstration: Peg Solitaire module
X
X 31 July 1986 Paul DuBois
X*/
X
X
X# include "BlobDemo.h"
X# include <MenuMgr.h>
X
X
X# define rows 7 /* number of rows on board */
X# define columns 7 /* number of columns on board */
X# define pieceSize 20 /* size of each piece */
X# define vMessage 141 /* vertical position of message */
X
X/*
X bits used in configuration information
X
X bit 0 0 board position unused
X 1 board position used
X bit 1 0 position does not have marble at start
X 1 position has marble at start
X bit 2 0 position does not have marble at end
X 1 position has marble at end
X
X bits 1 and 2 are irrelevant unless bit 0 is on
X*/
X
X# define posUsedMask 1
X# define inStartMask 2
X# define inFinalMask 4
X
X
Xstatic GrafPtr pegPort;
Xstatic MenuHandle cnfgMenu;
X
X
Xstatic BlobSetHandle boardBlobs = nil; /* receptors */
Xstatic BlobHandle board[columns][rows];
X
Xstatic int hMid;
Xstatic int cnfgNo; /* current configuration */
Xstatic int moves; /* number of moves left */
Xstatic Boolean pause;
Xstatic Str255 statusStr = "\p";
X
X
Xtypedef struct
X{
X char *lName; /* name of configuration */
X char lCnfg[columns][rows]; /* board positions */
X} Layout;
X
X
Xstatic Layout centerToCenter =
X{
X "\pCenter To Center",
X {
X { 0, 0, 3, 3, 3, 0, 0 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 3, 3, 3, 3, 3, 3, 3 },
X { 3, 3, 3, 5, 3, 3, 3 },
X { 3, 3, 3, 3, 3, 3, 3 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 0, 0, 3, 3, 3, 0, 0 }
X }
X};
X
X
Xstatic Layout cornerToCorner =
X{
X "\pCorner To Corner",
X {
X { 0, 0, 1, 3, 3, 0, 0 },
X { 0, 3, 3, 3, 3, 3, 0 },
X { 3, 3, 3, 3, 3, 3, 3 },
X { 3, 3, 3, 3, 3, 3, 3 },
X { 3, 3, 3, 3, 3, 3, 3 },
X { 0, 3, 3, 3, 3, 3, 0 },
X { 0, 0, 3, 3, 7, 0, 0 }
X }
X};
X
X
Xstatic Layout doubleCross =
X{
X "\pDouble Cross",
X {
X { 0, 0, 1, 3, 1, 0, 0 },
X { 0, 3, 1, 3, 1, 3, 0 },
X { 1, 1, 3, 3, 3, 1, 1 },
X { 3, 3, 3, 7, 3, 3, 3 },
X { 1, 1, 3, 3, 3, 1, 1 },
X { 0, 3, 1, 3, 1, 3, 0 },
X { 0, 0, 1, 3, 1, 0, 0 }
X }
X};
X
X
Xstatic Layout finalScore =
X{
X "\pFinal Score",
X {
X { 0, 0, 7, 7, 7, 0, 0 },
X { 0, 7, 3, 3, 3, 7, 0 },
X { 7, 3, 7, 3, 7, 3, 7 },
X { 7, 3, 3, 5, 3, 3, 7 },
X { 7, 3, 3, 3, 3, 3, 7 },
X { 0, 7, 3, 7, 3, 7, 0 },
X { 0, 0, 7, 7, 7, 0, 0 }
X }
X};
X
X
Xstatic Layout fiveCrosses =
X{
X "\pFive Crosses",
X {
X { 0, 0, 1, 3, 1, 0, 0 },
X { 0, 1, 3, 3, 3, 1, 0 },
X { 1, 3, 1, 3, 1, 3, 1 },
X { 3, 3, 3, 7, 3, 3, 3 },
X { 1, 3, 1, 3, 1, 3, 1 },
X { 0, 1, 3, 3, 3, 1, 0 },
X { 0, 0, 1, 3, 1, 0, 0 }
X }
X};
X
X
Xstatic Layout footballTeam =
X{
X "\pFootball Team",
X {
X { 0, 0, 3, 3, 3, 0, 0 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 1, 1, 3, 3, 3, 1, 1 },
X { 1, 1, 3, 5, 3, 1, 1 },
X { 1, 1, 1, 1, 1, 1, 1 },
X { 0, 0, 1, 1, 1, 0, 0 },
X { 0, 0, 1, 1, 1, 0, 0 }
X }
X};
X
X
Xstatic Layout greekCross =
X{
X "\pGreek Cross",
X {
X { 0, 0, 1, 1, 1, 0, 0 },
X { 0, 0, 1, 3, 1, 0, 0 },
X { 1, 1, 1, 3, 1, 1, 1 },
X { 1, 3, 3, 7, 3, 3, 1 },
X { 1, 1, 1, 3, 1, 1, 1 },
X { 0, 0, 1, 3, 1, 0, 0 },
X { 0, 0, 1, 1, 1, 0, 0 }
X }
X};
X
X
Xstatic Layout latinCross =
X{
X "\pLatin Cross",
X {
X { 0, 0, 1, 1, 1, 0, 0 },
X { 0, 0, 1, 3, 1, 0, 0 },
X { 1, 1, 3, 3, 3, 1, 1 },
X { 1, 1, 1, 7, 1, 1, 1 },
X { 1, 1, 1, 3, 1, 1, 1 },
X { 0, 0, 1, 1, 1, 0, 0 },
X { 0, 0, 1, 1, 1, 0, 0 },
X }
X};
X
X
Xstatic Layout leTricolet =
X{
X "\pLe Tricolet",
X {
X { 0, 0, 7, 3, 7, 0, 0 },
X { 0, 3, 3, 7, 3, 3, 0 },
X { 7, 3, 3, 7, 3, 3, 7 },
X { 3, 7, 7, 1, 7, 7, 3 },
X { 7, 3, 3, 7, 3, 3, 7 },
X { 0, 3, 3, 7, 3, 3, 0 },
X { 0, 0, 7, 3, 7, 0, 0 }
X }
X};
X
X
Xstatic Layout lonelyCross =
X{
X "\pLonely Cross",
X {
X { 0, 0, 7, 7, 7, 0, 0 },
X { 0, 7, 3, 3, 3, 7, 0 },
X { 7, 3, 3, 7, 3, 3, 7 },
X { 7, 3, 7, 5, 7, 3, 7 },
X { 7, 3, 3, 7, 3, 3, 7 },
X { 0, 7, 3, 3, 3, 7, 0 },
X { 0, 0, 7, 7, 7, 0, 0 }
X }
X};
X
X
Xstatic Layout octagon =
X{
X "\pOctagon",
X {
X { 0, 0, 1, 3, 1, 0, 0 },
X { 0, 3, 3, 3, 3, 3, 0 },
X { 1, 3, 3, 3, 3, 3, 1 },
X { 3, 3, 3, 7, 3, 3, 3 },
X { 1, 3, 3, 3, 3, 3, 1 },
X { 0, 3, 3, 3, 3, 3, 0 },
X { 0, 0, 1, 3, 1, 0, 0 }
X }
X};
X
X
Xstatic Layout pentagon =
X{
X "\pPentagon",
X {
X { 0, 0, 1, 3, 1, 0, 0 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 1, 3, 3, 3, 3, 3, 1 },
X { 3, 3, 3, 7, 3, 3, 3 },
X { 1, 3, 3, 3, 3, 3, 1 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 0, 0, 1, 1, 1, 0, 0 }
X }
X};
X
X
Xstatic Layout pyramidChefren =
X{
X "\pPyramid of Chefren",
X {
X { 0, 0, 1, 1, 1, 0, 0 },
X { 0, 1, 1, 1, 1, 1, 0 },
X { 1, 1, 1, 3, 1, 1, 1 },
X { 1, 1, 3, 7, 3, 1, 1 },
X { 1, 3, 3, 3, 3, 3, 1 },
X { 0, 1, 1, 1, 1, 1, 0 },
X { 0, 0, 1, 1, 1, 0, 0 },
X }
X};
X
X
Xstatic Layout pyramidCheops =
X{
X "\pPyramid of Cheops",
X {
X { 0, 0, 1, 1, 1, 0, 0 },
X { 0, 1, 1, 3, 1, 1, 0 },
X { 1, 1, 3, 3, 3, 1, 1 },
X { 1, 3, 3, 7, 3, 3, 1 },
X { 3, 3, 3, 3, 3, 3, 3 },
X { 0, 1, 1, 1, 1, 1, 0 },
X { 0, 0, 1, 1, 1, 0, 0 },
X }
X};
X
X
Xstatic Layout shrine =
X{
X "\pShrine",
X {
X { 0, 0, 1, 3, 1, 0, 0 },
X { 0, 1, 1, 3, 1, 1, 0 },
X { 1, 3, 3, 7, 3, 3, 1 },
X { 1, 1, 1, 3, 1, 1, 1 },
X { 1, 1, 1, 3, 1, 1, 1 },
X { 0, 1, 3, 3, 3, 1, 0 },
X { 0, 0, 3, 3, 3, 0, 0 },
X }
X};
X
X
Xstatic Layout tiffanyLamp =
X{
X "\pTiffany Lamp",
X {
X { 0, 0, 1, 3, 1, 0, 0 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 1, 3, 3, 3, 3, 3, 1 },
X { 1, 1, 1, 7, 1, 1, 1 },
X { 1, 1, 1, 3, 1, 1, 1 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 0, 0, 3, 3, 3, 0, 0 },
X }
X};
X
X
Xstatic Layout tiltedSquare =
X{
X "\pTilted Square",
X {
X { 0, 0, 1, 3, 1, 0, 0 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 1, 3, 3, 3, 3, 3, 1 },
X { 3, 3, 3, 5, 3, 3, 3 },
X { 1, 3, 3, 3, 3, 3, 1 },
X { 0, 0, 3, 3, 3, 0, 0 },
X { 0, 0, 1, 3, 1, 0, 0 }
X }
X};
X
X
Xstatic Layout nullLayout =
X{
X nil
X};
X
X
Xstatic Layout *configurations [] =
X{
X ¢erToCenter,
X &cornerToCorner,
X &doubleCross,
X &finalScore,
X &fiveCrosses,
X &footballTeam,
X &greekCross,
X &latinCross,
X &leTricolet,
X &lonelyCross,
X &octagon,
X &pentagon,
X &pyramidChefren,
X &pyramidCheops,
X &shrine,
X &tiffanyLamp,
X &tiltedSquare,
X &nullLayout
X};
X
X
Xstatic StatusMesg (s)
XStr255 s;
X{
XRect r;
X
X SetRect (&r, 0, vMessage, pegPort->portRect.right, vMessage + 12);
X TextBox (s+1, (long) s[0], &r, 1);
X StrCpy (statusStr, s);
X}
X
X
X/*
X Board position drawing procedure. This draws a blank for those
X positions that are unused. For used positions, the blob is filled
X with light gray if a peg should be in the position at the end of
X play. In the drag region, a hole is drawn if there is no glob,
X otherwise a peg is drawn. It does not matter what glob is attached,
X only whether there is one.
X*/
X
Xstatic DrawBoardPos (bDst, bSrc, partCode)
XBlobHandle bDst, bSrc;
Xint partCode; /* ignored - always draw entire blob */
X{
Xint blobType;
XRect r;
X
X blobType = GetBRefCon (bDst); /* indicates unused, used and present
X in final, or used and not present
X in final */
X r = BStatBox (bDst); /* blob outline */
X EraseRect (&r);
X if (blobType & posUsedMask)
X {
X if (blobType & inFinalMask)
X FillRect (&r, gray);
X if (BGlob (bDst) == nil) /* no peg, just draw hole */
X {
X InsetRect (&r, 7, 7);
X PaintOval (&r);
X }
X else
X {
X InsetRect (&r, 2, 2); /* draw peg */
X EraseOval (&r);
X PenSize (2, 2);
X FrameOval (&r);
X PenNormal ();
X }
X }
X}
X
X
X/*
X Build the board. All positions are initially given a reference
X value of 0, meaning an unused position. This means that the board
X is blank until a configuration is set up. The blobs are built by
X contructing the static and drag regions, without drawing anything,
X since they are drawn by procedure.
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, infiniteGlue, true, (long) 0);
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, 2, 2);
X SetProcRectBlob (b, DrawBoardPos, &r2, &r);
X }
X }
X
X EnableBlobSet (boardBlobs);
X}
X
X
X/*
X Set the board to a given configuration. The first board blob is
X used as the general glob and as the match for final positions.
X*/
X
Xstatic SetupBoard (layout)
XLayout *layout;
X{
Xint h, v, val;
Xint startCount = 0;
Xint finalCount = 0;
XBlobHandle b;
XStr255 s;
X
X DisableBlobSet (boardBlobs); /* turn off drawing temporarily */
X for (v = 0; v < rows; v++)
X {
X for (h = 0; h < columns; h++)
X {
X b = board[h][v];
X val = (int) layout->lCnfg[v][h];
X SetBRefCon (b, val);
X UnglueGlob (b); /* clear any glob and match set */
X DisposeBlobMatchSet (b); /* from previous configuration */
X if (val & posUsedMask) /* check that position is used */
X {
X if (val & inStartMask) /* position has marble at start */
X {
X startCount++;
X GlueGlob (FirstBlob (boardBlobs), b);
X }
X if (val & inFinalMask) /* position has marble at end */
X {
X finalCount++;
X NewBlobMatch (FirstBlob (boardBlobs), b);
X }
X }
X }
X }
X
X ShowBlobSet (boardBlobs);
X moves = startCount - finalCount;
X MovesLeft (moves, s);
X StatusMesg (s);
X pause = false;
X}
X
X
Xstatic PegPause (msg)
XStringPtr msg;
X{
X StatusMesg (msg);
X pause = true;
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 && (GetBRefCon (board[h][v]) & posUsedMask)
X && BGlob (board[h][v]) == nil);
X}
X
X
Xstatic Boolean BoardPosFilled (h, v)
Xint h, v;
X{
X return (h >= 0 && h < columns && v >= 0 && v < rows
X && (GetBRefCon (board[h][v]) & posUsedMask)
X && BGlob (board[h][v]) != nil);
X}
X
X
X/*
X Test whether a piece can move or not
X*/
X
Xstatic Boolean CanMove (h, v)
Xint h, v;
X{
X return ((BoardPosEmpty (h - 2, v) && BoardPosFilled (h - 1, v))
X || (BoardPosEmpty (h + 2, v) && BoardPosFilled (h + 1, v))
X || (BoardPosEmpty (h, v - 2) && BoardPosFilled (h, v - 1))
X || (BoardPosEmpty (h, v + 2) && BoardPosFilled (h, v + 1)));
X}
X
X
X/*
X See if any more moves can be made. True if stalemated.
X*/
X
Xstatic Boolean HaveStaleMate ()
X{
XBlobHandle b;
Xint h, v;
X
X for (v = 0; v < rows; v++)
X {
X for (h = 0; h < columns; h++)
X {
X b = board[h][v];
X if (GetBRefCon (b) & posUsedMask)
X {
X if (BGlob (b) != nil && CanMove (h, v))
X return (false); /* at least 1 move can be made */
X }
X }
X }
X return (true);
X}
X
X
Xstatic Mouse (pt, t, mods)
XPoint pt;
Xlong t;
Xint mods;
X{
XStr255 s;
Xint i;
X
X
X if (!pause)
X {
X BlobClick (pt, t, nil, boardBlobs);
X if (BClickResult () == bcXfer)
X {
X --moves;
X if (BlobSetQuiet (boardBlobs))
X PegPause ("\pYou Win");
X else if (moves == 0)
X PegPause ("\pYou Lose");
X else if (HaveStaleMate ())
X PegPause ("\pYou Can't Move");
X else
X {
X MovesLeft (moves, s);
X StatusMesg (s);
X }
X }
X }
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 FindBoardPos (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/*
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. If it is, the piece that was jumped is removed from the
X board, and true is returned, so that BlobClick will complete the
X tranfer of the dragged piece to its new position.
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;
X
X switch (mesg)
X {
X
X case advRClick: /* first click on piece */
X
X FindBoardPos (b, &h, &v); /* find where it is */
X return (CanMove (h, v));
X
X case advXfer: /* Mouse released after dragging piece */
X
X FindBoardPos (b, &h2, &v2);
X if ( ( (h2 == h - 2 && v2 == v)
X || (h2 == h + 2 && v2 == v)
X || (h2 == h && v2 == v - 2)
X || (h2 == h && v2 == v + 2) )
X && BoardPosFilled ((h + h2) / 2, (v + v2) / 2))
X {
X UnglueGlob (board[(h + h2) / 2][(v + v2) / 2]);
X return (true);
X }
X return (false);
X
X }
X}
X
X
Xstatic DoConfiguration (item)
Xint item;
X{
X CheckItem (cnfgMenu, cnfgNo + 1, false);
X SetupBoard (configurations [cnfgNo = item-1]);
X CheckItem (cnfgMenu, cnfgNo + 1, true);
X}
X
X
Xstatic Activate (active)
XBoolean active;
X{
XLayout *l;
X
X if (active)
X {
X SetDragRects (pegPort);
X SetBCPermissions (false, true, false, false, false); /* xfer only */
X SetBCAdvisory (Advisory);
X cnfgMenu = GetMenu (pegCnfgMenuRes);
X for (l = configurations[0]; l->lName != nil; ++l)
X {
X AppendMenu (cnfgMenu, l->lName);
X }
X SkelMenu (cnfgMenu, DoConfiguration, DoMClobber);
X CheckItem (cnfgMenu, cnfgNo+1, true);
X }
X else
X {
X SkelRmveMenu (cnfgMenu);
X SetBCAdvisory (nil);
X }
X}
X
X
Xstatic Update (resized)
XBoolean resized;
X{
X DrawBlobSet (boardBlobs);
X StatusMesg (statusStr);
X}
X
X
XPegInit ()
X{
XRect r;
X
X SkelWindow (pegPort = GetDemoWind (pegWindRes),
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 = pegPort->portRect.right / 2;
X
X/*
X Make blobs and set initial configuration to the Latin Cross, which
X is good for learning some of the problems of peg solitaire.
X*/
X InitBoard ();
X SetupBoard (configurations[cnfgNo = 7]);
X ValidRect (&pegPort->portRect);
X}
SHAR_EOF
exit