Thread View: mod.mac.sources
1 messages
1 total messages
Started by macintosh
Wed, 28 Jan 1987 07:00
BMgr - Blob Manager source (part 2 of 2)
Author: macintosh
Date: Wed, 28 Jan 1987 07:00
Date: Wed, 28 Jan 1987 07:00
1429 lines
33559 bytes
33559 bytes
References:
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# BMgr/BMgrHilite.c
# BMgr/BMgrHitTest.c
# BMgr/BMgrIndex.c
# BMgr/BMgrLoop.c
# BMgr/BMgrMatch.c
# BMgr/BMgrMove.c
# BMgr/BMgrNew.c
# BMgr/BMgrPict.c
# BMgr/BMgrRand.c
# BMgr/BMgrSetProc.c
# BMgr/BMgrSetRgns.c
# BMgr/BMgrShuffle.c
# BMgr/BMgrTrackMouse.c
# BMgr/BMgrTrans.c
# BMgr/BMgrZTrans.c
# BMgr/BMgrZoom.c
mkdir BMgr
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrHilite.c
X# include "BlobMgr.h"
X
X
X/* -------------------------------------------------------------------- */
X/* Blob State Change Display Routines */
X/* -------------------------------------------------------------------- */
X
X
X
X/*
X Set the drawing mode for the given part of the blob.
X Redraw if it changes.
X*/
X
XHiliteBlob (b, partCode, mode)
XBlobHandle b;
Xint partCode;
Xint mode;
X{
X
X if ((partCode == inDragBlob) || (partCode == inFullBlob))
X {
X if (GetBDrawMode (b, inDragBlob) != mode)
X {
X SetBDrawMode (b, inDragBlob, mode);
X DrawBlob (b, inDragBlob);
X }
X }
X if ((partCode == inStatBlob) || (partCode == inFullBlob))
X {
X if (GetBDrawMode (b, inStatBlob) != mode)
X {
X SetBDrawMode (b, inStatBlob, mode);
X DrawBlob (b, inStatBlob);
X }
X }
X}
X
X
XHiliteBlobSet (bSet, partCode, mode)
XBlobSetHandle bSet;
Xint partCode;
Xint mode;
X
X{
Xregister BlobHandle b;
X
X for (b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X {
X HiliteBlob (b, partCode, mode);
X }
X}
X
X
X/*
X Increment use count of blob and dim drag area if at or above maximum
X glue count.
X*/
X
XIncBlobGlue (b)
XBlobHandle b;
X{
X if ((**b).glueMax != infiniteGlue)
X {
X ++((**b).glueCount);
X if ((**b).glueCount >= (**b).glueMax)
X HiliteBlob (b, inDragBlob, dimDraw);
X }
X}
X
X
X/*
X Decrement use count of blob and undim drag area if less than maximum
X glue count.
X*/
X
XDecBlobGlue (b)
XBlobHandle b;
X{
X if ((**b).glueMax != infiniteGlue)
X {
X --((**b).glueCount);
X if ((**b).glueCount < (**b).glueMax)
X HiliteBlob (b, inDragBlob, normalDraw);
X }
X}
X
X
XSetBGlueMax (b, max)
XBlobHandle b;
Xint max;
X{
X (**b).glueMax = max;
X
X/* dim or undim appropriately */
X
X if ((**b).glueCount < max || max == infiniteGlue)
X HiliteBlob (b, inDragBlob, normalDraw);
X else
X HiliteBlob (b, inDragBlob, dimDraw);
X}
X
X
XGetBGlueMax (b)
XBlobHandle b;
X{
X return ((**b).glueMax);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrHitTest.c
X# include "BlobMgr.h"
X
X
X
X
X/* -------------------------------------------------------------------- */
X/* Blob Hit Testing Routines */
X/* -------------------------------------------------------------------- */
X
X
X/*
X Test whether the blob contains the point, and if so, return a part
X of the part of the blob that the point is in. Does not consider
X dimmed parts of blobs. Blob must be active (enabled, not frozen).
X Return zero if no hit.
X*/
X
XTestBlob (b, thePoint)
XBlobHandle b;
XPoint thePoint;
X{
Xint result;
X
X result = 0;
X if (BlobActive (b))
X {
X if (!BlobDimmed (b, inDragBlob) && PtInRgn (thePoint, (**b).dragRgn))
X result = inDragBlob;
X else if (!BlobDimmed (b, inStatBlob)
X && PtInRgn (thePoint, (**b).statRgn))
X result = inStatBlob;
X }
X return (result);
X}
X
X
X/*
X If the point is in an undimmed region of any active blob of the set,
X return a handle to the blob in b and the part code as the function
X result.
X*/
X
XFindBlob (thePoint, bSet, bPtr)
XPoint thePoint;
XBlobSetHandle bSet;
XBlobHandle *bPtr; /* pointer to blobhandle */
X
X{
XBlobHandle b;
Xint partCode;
Xint result;
X
X result = 0;
X for (b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X {
X partCode = TestBlob (b, thePoint);
X if (partCode != 0)
X {
X result = partCode;
X *bPtr = b;
X break;
X }
X }
X return (result);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrIndex.c
X# include "BlobMgr.h"
X
X
X/*
X Get the handle of the (i)th blob in the list. The first
X blob is numbered 0.
X*/
X
XBlobHandle GetBlobHandle (bSet, i)
XBlobSetHandle bSet;
Xint i;
X{
Xregister BlobHandle b;
X
X for (b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X {
X --i;
X if (i < 0) break; /* found it */
X }
X return (b);
X}
X
X
X/*
X Get the index of the given blob in the list, given its handle.
X The blob is assumed to be in the set. Returns a number from
X 0 to BlobSetSize (bSet)-1.
X*/
X
XGetBlobIndex (b, bSet)
XBlobHandle b;
XBlobSetHandle bSet;
X{
Xregister BlobHandle b2;
Xregister int i;
X
X i = 0;
X for (b2 = FirstBlob (bSet); b2 != nil; b2 = NextBlob (b2))
X {
X if (b == b2) break; /* found it */
X ++i;
X }
X return (i);
X}
X
X
XBlobSetSize (bSet)
XBlobSetHandle bSet;
X{
Xregister BlobHandle b;
Xregister int i;
X
X for (i = 0, b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X {
X ++i;
X }
X return (i);
X}SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrLoop.c
X# include "BlobMgr.h"
X
X
X/* -------------------------------------------------------------------- */
X/* Blob Loop Routines */
X/* */
X/* These routines loop through the given blob set, calling the given */
X/* procedure for every element of the set. */
X/* -------------------------------------------------------------------- */
X
X
XBlobLoopProc1 (p, bSet)
XProcPtr p;
XBlobSetHandle bSet;
X{
Xregister BlobHandle b;
X
X if (bSet != nil)
X {
X for (b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X (*p) (b);
X }
X}
X
X
XBlobLoopProc2 (p, bSet, partCode)
XProcPtr p;
XBlobSetHandle bSet;
Xint partCode;
X{
Xregister BlobHandle b;
X
X if (bSet != nil)
X {
X for (b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X (*p) (b, partCode);
X }
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrMatch.c
X# include "BlobMgr.h"
X
X
X/* -------------------------------------------------------------------- */
X/* Blob Match Testing Operations */
X/* -------------------------------------------------------------------- */
X
X
X/*
X Return true if b1 is in b2's match set.
X*/
X
XBoolean InBlobMatchSet (b1, b2)
XBlobHandle b1, b2;
X{
XMatchHandle m;
XBoolean result;
X
X result = false;
X for (m = (**b2).matches; m != nil; m = (**m).nextMatch)
X {
X if ((**m).mBlob == b1)
X {
X result = true; /* found it */
X break;
X }
X }
X return (result);
X}
X
X
X/*
X Default quiet test procedure.
X
X A blob requiring an explicit match is quiet if it has a glob and
X the glob is a member of the match set, or, if the match set is
X empty, it has no glob. A blob not requiring an
X explicit match is quiet if it has an explicit match, or if it
X has a glob but an empty match set, or if it has no glob.
X
X Otherwise the blob is noisy.
X*/
X
Xstatic Boolean DefaultQuietTest (b)
XBlobHandle b;
X{
XBlobHandle g;
XBoolean needGlob;
XBoolean result;
X
X g = (**b).glob;
X needGlob = (TestBlobFlags (b, bNeedGlobMask) != 0);
X/*
X if the blob has no glob, it is matched if it's a non-explicit
X blob. If it's an explicit blob, it's matched if the match set
X is empty.
X*/
X if (g == nil)
X result = (needGlob ? (**b).matches == nil : true);
X else /* has a glob - is it ok? */
X {
X/*
X if the blob doesn't need a glob but has one, then it's still
X quiet if the match set is empty ("any glob will do").
X*/
X if (!needGlob && ((**b).matches == nil))
X result = true;
X else
X result = InBlobMatchSet (g, b); /* see if in match set */
X }
X return (result);
X}
X
X
Xstatic Boolean (*bQuietTest) () = DefaultQuietTest;
X
X
XBoolean BlobQuiet (b)
XBlobHandle b;
X{
X return ((*bQuietTest) (b));
X}
X
X
X/*
X Install quiet test function for BlobQuiet. Pass nil to restore
X default.
X*/
X
XSetBQuietTest (f)
XBoolean (*f)();
X{
X bQuietTest = (f == nil ? DefaultQuietTest : f);
X}
X
X
XBoolean BlobSetQuiet (bSet)
XBlobSetHandle bSet;
X{
XBlobHandle b;
XBoolean result;
X
X result = true;
X for (b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X {
X if (!BlobQuiet (b))
X {
X result = false;
X break;
X }
X }
X return (result);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrMove.c
X# include "BlobMgr.h"
X
X
X/* -------------------------------------------------------------------- */
X/* Blob Movement Operations */
X/* -------------------------------------------------------------------- */
X
X
X/*
X Offset a blob or part of a blob by (hoff, voff). If the blob is enabled,
X hide it and redraw at the new location.
X*/
X
XOffsetBlob (b, partCode, hoff, voff)
XBlobHandle b;
Xint partCode, hoff, voff;
X{
XBoolean vis;
X
X if ((hoff == 0) && (voff == 0)) return; /* avoid unnecessary redraw */
X
X vis = false;
X if (BlobEnabled (b))
X {
X vis = true;
X HideBlob (b);
X }
X
X if ((partCode == inDragBlob) || (partCode == inFullBlob))
X OffsetRgn ((**b).dragRgn, hoff, voff);
X if ((partCode == inStatBlob) || (partCode == inFullBlob))
X OffsetRgn ((**b).statRgn, hoff, voff);
X
X if (vis)
X ShowBlob (b);
X}
X
X
X/*
X Move a blob or part of a blob to (h, v). If the blob is enabled,
X hide it and redraw at the new location. If partCode is inDragBlob
X or inStatBlob, move the appropriate region to the location. If
X inFullBlob, move both regions in synchrony so static region is at
X given location, drag region is at same location relative to the
X static region as it was before.
X*/
X
XMoveBlob (b, partCode, h, v)
XBlobHandle b;
Xint partCode, h, v;
X{
X if (partCode == inDragBlob)
X {
X h -= (**((**b).dragRgn)).rgnBBox.left; /* convert to offsets */
X v -= (**((**b).dragRgn)).rgnBBox.top;
X }
X else /* it's inStatBlob or inFullBLob */
X {
X h -= (**((**b).statRgn)).rgnBBox.left;
X v -= (**((**b).statRgn)).rgnBBox.top;
X }
X OffsetBlob (b, partCode, h, v);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrNew.c
X# include "BlobMgr.h"
X
X
X
X# define New(x) (x **) NewHandle ((Size) sizeof (x))
X
X/*
X Handle to list of all existing blob sets - empty initially
X*/
X
Xstatic BlobSetHandle blobSetMaster = nil;
X
X
X/* ---------------------------------------------------------------------- */
X/* Object Creation Routines */
X/* ---------------------------------------------------------------------- */
X
X
X
XNewBlobMatch (b1, b2)
XBlobHandle b1, b2;
X{
XMatchHandle m;
X
X m = New (MatchRecord);
X if (m != nil)
X {
X (**m).mBlob = b1;
X (**m).nextMatch = (**b2).matches;
X (**b2).matches = m;
X }
X}
X
X
X/* Add a blob to (the END of) a blob set */
X
XAddBlob (b, bSet)
XBlobHandle b;
XBlobSetHandle bSet;
X{
X
X if (FirstBlob (bSet) == nil)
X {
X FirstBlob (bSet) = b;
X LastBlob (bSet) = b;
X }
X else
X {
X NextBlob (LastBlob (bSet)) = b;
X LastBlob (bSet) = b;
X }
X NextBlob (b) = nil;
X}
X
X
X/*
X Create a new blob, adding it to the given set. The blob is enabled
X or not according to the enable parameter. The blob is given empty
X static and drag regions and rectangles, nil picture, match set, and
X glob handles. The drawing modes are set according to statDraw
X and dragDraw. The blob is set to be single-use or not by the
X glueMax parameter. mustMatch determines whether the blob must
X have a glue blob to be matched. The refCon is installed in the
X record.
X*/
X
XBlobHandle NewBlob (bSet, /* set to add blob to */
X enable, /* whether blob is enabled or not */
X glueMVal, /* maximum glue count */
X mustMatch, /* whether must have glob to be matched */
X refCon) /* reference constant */
X
XBlobSetHandle bSet;
XBoolean enable;
Xint glueMVal;
XBoolean mustMatch;
Xlong refCon;
X{
XBlobHandle bHand;
XBlobPtr b;
XRect r;
X
X bHand = New (BlobRecord);
X if (bHand != nil)
X {
X AddBlob (bHand, bSet); /* sets nextBlob field */
X b = *bHand;
X b->flags = 0 | bPicMask; /* clear flags, then set appropriate fields */
X if (enable)
X EnableBlob (bHand);
X if (mustMatch)
X SetBlobFlags (bHand, bNeedGlobMask);
X b->bPicProc.bPic = nil; /* no picture or drawing proc */
X SetRect (&r, 0, 0, 0, 0);
X b->statRect = r; /* empty rects */
X b->dragRect = r;
X b->statRgn = NewRgn (); /* empty regions */
X b->dragRgn = NewRgn ();
X b->glueMax = glueMVal;
X b->glueCount = 0;
X b->glob = nil;
X b->matches = nil;
X b->bRefCon = refCon;
X
X }
X
X return (bHand);
X}
X
X
X/*
X Create a new, empty blob set. Add it to the master blob set list.
X Return a handle to it.
X*/
X
XBlobSetHandle NewBlobSet ()
X{
XBlobSetHandle bSet;
X
X bSet = New (BlobSetRecord);
X if (bSet != nil)
X {
X FirstBlob (bSet) = nil; /* initialize to empty set */
X LastBlob (bSet) = nil;
X (**bSet).nextBlobSet = blobSetMaster; /* add to master list */
X blobSetMaster = bSet;
X }
X
X return (bSet);
X}
X
X
X/* ---------------------------------------------------------------------- */
X/* Object Disposal Routines */
X/* ---------------------------------------------------------------------- */
X
X
XDisposeBlobPic (b)
XBlobHandle b;
X{
X if (PicBlob (b) && (**b).bPicProc.bPic != nil)
X {
X KillPicture ((**b).bPicProc.bPic);
X (**b).bPicProc.bPic = nil;
X }
X}
X
X
XDisposeBlobMatchSet (b)
XBlobHandle b;
X{
XMatchHandle m1, m2;
X
X m1 = (**b).matches;
X (**b).matches = nil;
X for (;;)
X {
X if (m1 == nil) return;
X m2 = (**m1).nextMatch;
X DisposHandle (m1);
X m1 = m2;
X }
X}
X
X
XDisposeBlob (b)
XBlobHandle b;
X{
X DisposeRgn ((**b).statRgn);
X DisposeRgn ((**b).dragRgn);
X DisposeBlobPic (b);
X DisposeBlobMatchSet (b);
X DisposHandle (b);
X}
X
X
X/*
X Remove blob set from the master blob set list, then dispose of
X everything in the list. All handles to the set or elements in
X it become invalid.
X*/
X
XDisposeBlobSet (bSet)
XBlobSetHandle bSet;
X{
XBlobHandle b1, b2;
XBlobSetHandle bSet2;
X
X/*
X remove set from master list
X*/
X if (bSet == blobSetMaster) /* first set in list */
X blobSetMaster = (**blobSetMaster).nextBlobSet;
X else
X {
X bSet2 = blobSetMaster;
X for (;;)
X {
X if (bSet2 == nil) return; /* set isn't in master list */
X if ((**bSet2).nextBlobSet == bSet) /* found it */
X {
X (**bSet2).nextBlobSet = (**bSet).nextBlobSet;
X break;
X }
X bSet2 = (**bSet2).nextBlobSet; /* try next one */
X }
X }
X/*
X toss elements of set
X*/
X b1 = (**bSet).firstBlob;
X for (;;)
X {
X if (b1 == nil) break;
X b2 = (**b1).nextBlob;
X DisposeBlob (b1);
X b1 = b2;
X }
X/*
X toss set header
X*/
X DisposHandle (bSet);
X}
X
X
X/*
X Dispose of all existing sets. This is the routine to call at
X the end of the host program to dispose of all Blob Manager
X structures.
X*/
X
XDisposeBlobSets ()
X{
X for (;;)
X {
X if (blobSetMaster == nil) break; /* no more sets */
X DisposeBlobSet (blobSetMaster); /* changes the master list */
X }
X}
X
X
X/*
X Delete a blob from a blob list. Should not be done lightly, e.g.,
X if the blob is some other blob's glob. Check to be sure that the
X current glueCount is zero first. All handles to the blob become
X invalid.
X*/
X
XClobberBlob (b, bSet)
XBlobHandle b;
XBlobSetHandle bSet;
X{
XBlobHandle b2;
X
X if ((**bSet).firstBlob == b) /* special case - first in list */
X {
X (**bSet).firstBlob = (**b).nextBlob;
X if ((**bSet).lastBlob == b) /* if true, set is now empty */
X (**bSet).lastBlob = nil;
X }
X else
X {
X b2 = (**bSet).firstBlob;
X for (;;)
X {
X if (b2 == nil) return; /* NOT break! */
X if ((**b2).nextBlob == b)
X {
X (**b2).nextBlob = (**b).nextBlob;
X if ((**bSet).lastBlob == b) /* clobbering last one */
X (**bSet).lastBlob = b2; /* back pointer up */
X break;
X }
X b2 = (**b2).nextBlob;
X }
X }
X DisposeBlob (b);
X}
X
X
X/*
X Delete s from the match set of d
X*/
X
XClobberBlobMatch (b1, b2)
XBlobHandle b1, b2;
X{
XMatchHandle m1, m2;
X
X m1 = (**b2).matches;
X if (m1 != nil) /* don't look if match set empty */
X {
X if ((**m1).mBlob == b1) /* is it the first one in the list? */
X {
X (**b2).matches = (**m1).nextMatch;
X }
X else /* it's not first one */
X {
X for (;;)
X {
X m2 = (**m1).nextMatch;
X if (m2 == nil) return; /* NOT break! */
X if ((**m2).mBlob == b1) /* found it */
X {
X (**m1).nextMatch = (**m2).nextMatch;
X break;
X }
X m1 = m2;
X }
X }
X DisposHandle (m2);
X }
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrPict.c
X/* -------------------------------------------------------------------- */
X/* Blob Picture Creation Routines */
X/* -------------------------------------------------------------------- */
X
X
X# include "BlobMgr.h"
X
X
X/*
X Internal picture drawing scratch variables
X*/
X
Xstatic PicHandle picHand;
Xstatic Rect picRect = { -30000, -30000, 30000, 30000 };
X
X
XOpenBlob ()
X{
X picHand = OpenPicture (&picRect);
X}
X
X
X/*
X Close a picture blob. The picture that was begin with OpenBlob is
X installed in the blob record and the blob type is set to picture
X (as opposed to proc) blob. The picture is replayed with a frame
X that is the union of the bounding boxes of the static and drag regions.
X This will usually be sufficiently reasonable to avoid the problem
X of overflow that sometimes results from scaling the clipping region
X when a picture is drawn in a different size than the original.
X The dragRect and statRect fields are set to those rects bounding
X the parts of the picture corresponding to the two regions. These
X are used to cope in the event that the blob is moved or resized.
X (See DrawBlob and DrawBlobPic.)
X
X ClosePicBlob does NOT set the blob's regions. That must be done
X by the caller after calling ClosePicBlob.
X*/
X
Xstatic ClosePicBlob (b, dragRect, statRect)
XBlobHandle b;
XRect *dragRect, *statRect;
X{
XRect pRect;
XPicHandle p;
XRgnHandle oldClip;
X
X ClosePicture (); /* stop saving picture definition */
X DisposeBlobPic (b); /* toss any pic the blob might have had */
X UnionRect (dragRect, statRect, &pRect);
X oldClip = NewRgn ();
X GetClip (oldClip);
X ClipRect (&pRect); /* avoid clipping problem on picture */
X p = OpenPicture (&pRect); /* replay later on - this prevents */
X DrawPicture (picHand, &picRect); /* overflow if pic is scaled up */
X ClosePicture ();
X KillPicture (picHand); /* don't need original picture now */
X SetClip (oldClip);
X DisposeRgn (oldClip);
X (**b).bPicProc.bPic = p;
X
X (**b).dragRect = *dragRect; /* install original drag Rect */
X (**b).statRect = *statRect; /* install original static Rect */
X
X SetBlobFlags (b, bPicMask); /* set type as picture blob */
X}
X
X
X/*
X Close a blob whose regions are defined by rectangles.
X*/
X
XCloseRectBlob (b, dragRect, statRect)
XBlobHandle b;
XRect *dragRect, *statRect;
X{
X ClosePicBlob (b, dragRect, statRect);
X SetBlobRects (b, dragRect, statRect);
X if (BlobEnabled (b))
X DrawBlob (b, inFullBlob);
X
X}
X
X
X/*
X Close a blob.
X*/
X
XCloseRgnBlob (b, dragRgn, statRgn)
XBlobHandle b;
XRgnHandle dragRgn, statRgn;
X{
XRect dragRect, statRect;
X
X dragRect = (**dragRgn).rgnBBox;
X statRect = (**statRgn).rgnBBox;
X ClosePicBlob (b, &dragRect, &statRect);
X SetBlobRgns (b, dragRgn, statRgn);
X if (BlobEnabled (b))
X DrawBlob (b, inFullBlob);
X
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrRand.c
X/*
X Blob random number routines
X*/
X
X# include <MacTypes.h>
X# define nil 0L
X
X
Xstatic DefaultRand (max)
Xint max;
X{
Xregister int t;
X
X t = Random ();
X if (t < 0) t = -t;
X return (t % (max + 1));
X}
X
X
Xstatic ProcPtr bRandProc = DefaultRand;
X
X
X/*
X return integer between zero and max (inclusive). assumes max is
X non-negative.
X*/
X
X
XBlobRand (max)
Xint max;
X{
X return ((*bRandProc) (max));
X}
X
X
X/*
X Install procedure as random number generator for BlobRand
X*/
X
XSetBlobRand (f)
XProcPtr f;
X{
X bRandProc = (f == nil ? DefaultRand : f);
X}SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrSetProc.c
X/* -------------------------------------------------------------------- */
X/* Blob Draw Proc Installation */
X/* -------------------------------------------------------------------- */
X
X
X# include "BlobMgr.h"
X
X
X
X/*
X Set a blob's draw procedure and regions. This routine makes COPIES
X of the regions passed in, so the caller should dispose of the regions
X it passes in itself.
X*/
X
XSetProcRgnBlob (b, proc, dragRgn, statRgn)
XBlobHandle b;
XProcPtr proc;
XRgnHandle dragRgn, statRgn;
X{
X DisposeBlobPic (b); /* toss any pic the blob might have */
X (**b).bPicProc.bDrawProc = proc;/* install drawing procedure */
X ClearBlobFlags (b, bPicMask); /* set blob type to proc blob */
X SetBlobRgns (b, dragRgn, statRgn);
X if (BlobEnabled (b))
X DrawBlob (b, inFullBlob);
X}
X
X
X/*
X Set a blob's draw procedure and regions, where the regions are
X defined by rectangles.
X*/
X
XSetProcRectBlob (b, proc, dragRect, statRect)
XBlobHandle b;
XProcPtr proc;
XRect *dragRect, *statRect;
X{
X DisposeBlobPic (b); /* toss any pic the blob might have */
X (**b).bPicProc.bDrawProc = proc;/* install drawing procedure */
X ClearBlobFlags (b, bPicMask); /* set blob type to proc blob */
X SetBlobRects (b, dragRect, statRect);
X if (BlobEnabled (b))
X DrawBlob (b, inFullBlob);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrSetRgns.c
X/* -------------------------------------------------------------------- */
X/* Blob Rect/Rgn Installation */
X/* -------------------------------------------------------------------- */
X
X
X# include "BlobMgr.h"
X
X
X
X
X/*
X Set a blob's regions. This routine makes COPIES of the regions
X passed in, so the caller should dispose of the regions it passes
X in itself. This routine relies on the fact that a blob should
X never have nil handles for its regions (NewBlob installs empty
X regions, so those regions are just changed here, not created).
X
X The drag region is set equal to the drag region passed in. The
X static region is set to the difference of the static and drag
X regions passed in.
X*/
X
XSetBlobRgns (b, dragRgn, statRgn)
XBlobHandle b;
XRgnHandle dragRgn, statRgn;
X{
X
X CopyRgn (dragRgn, (**b).dragRgn);
X DiffRgn (statRgn, dragRgn, (**b).statRgn);
X}
X
X
X/*
X Set a blob's regions, where the regions are defined by rectangles.
X*/
X
XSetBlobRects (b, dragRect, statRect)
XBlobHandle b;
XRect *dragRect, *statRect;
X{
XRgnHandle dragRgn, statRgn;
X
X dragRgn = NewRgn ();
X statRgn = NewRgn ();
X RectRgn (dragRgn, dragRect);
X RectRgn (statRgn, statRect);
X SetBlobRgns (b, dragRgn, statRgn);
X DisposeRgn (dragRgn);
X DisposeRgn (statRgn);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrShuffle.c
X# include "BlobMgr.h"
X
X
X/*
X Shuffle the locations of the blobs in the given set. If it is
X undesirable to show all the redrawing that takes place during
X this, HideBlobSet should be called before ShuffleBlobSet, and
X ShowBlobSet after.
X
X ShuffleBlobSet deals with the following problem. Suppose two blobs
X to be switched are both visible. The first is moved, i.e., hidden
X and redrawn at the location of the second. Then the second is moved,
X i.e., hidden and redrawn at the previous location of the first.
X But moving the second blob erases the newly drawn first blob! To
X avoid this, ShuffleBlobset hides the first blob before moving them,
X and redraws it afterward.
X
X ShuffleBlobSet usually results in an update event being generated
X since hiding a blob adds its region to the update region for the
X window. ValidRect can be called (with the window's portRect)
X to defeat it.
X
X The static region is often empty, which is why the drag regions are used
X to determine the offsets.
X*/
X
X
XShuffleBlobSet (bSet)
XBlobSetHandle bSet;
X{
Xregister BlobHandle b1, b2;
Xregister int size, h, v;
XBoolean vis1 = false;
X
X size = BlobSetSize (bSet);
X for (b1 = FirstBlob (bSet); b1 != nil; b1 = NextBlob (b1))
X {
X b2 = GetBlobHandle (bSet, BlobRand (size - 1));
X h = BDragBox (b1).left - BDragBox (b2).left;
X v = BDragBox (b1).top - BDragBox (b2).top;
X if (BlobEnabled (b1))
X {
X HideBlob (b1);
X vis1 = true;
X }
X OffsetBlob (b1, inFullBlob, -h, -v);
X OffsetBlob (b2, inFullBlob, h, v);
X if (vis1)
X ShowBlob (b1);
X }
X}
X
X
X/*
X Shuffle the globs attached to the blobs in the given set.
X*/
X
X
XShuffleGlobSet (bSet)
XBlobSetHandle bSet;
X{
Xregister BlobHandle b;
Xregister int size;
X
X size = BlobSetSize (bSet);
X for (b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X {
X SwapGlob (b, GetBlobHandle (bSet, BlobRand (size-1)));
X }
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrTrackMouse.c
X# include "BlobMgr.h"
X
X
X/*
X Track the mouse while the button is held down. Invert the given
X blob region whenever the mouse is in the region. Return true if
X the mouse is released inside of the region, false otherwise.
X*/
X
XBoolean BTrackMouse (b, startPt, partCode)
XBlobHandle b;
XPoint startPt;
Xint partCode;
X{
XBoolean inBlob;
XRgnHandle rgn;
XPoint pt;
X
X rgn = BCalcRegion (b, partCode);
X pt = startPt;
X inBlob = false;
X for (;;)
X {
X if (PtInRgn (pt, rgn) != inBlob) /* invert on change of state */
X {
X InvertRgn (rgn);
X inBlob = !inBlob;
X }
X if (!StillDown ())
X break;
X GetMouse (&pt);
X }
X if (inBlob) /* leave region uninverted */
X InvertRgn (rgn);
X DisposeRgn (rgn);
X return (inBlob);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrTrans.c
X# include "BlobMgr.h"
X
X
X/* ---------------------------------------------------------------------- */
X/* Blob Transaction Routines */
X/* ---------------------------------------------------------------------- */
X
X
X/*
X If the blob has a blob glued to its drag area, dissociate the glued blob.
X Redraw the drag area. Decrement the use count of the glued blob,
X undimming it if necessary.
X*/
X
XUnglueGlob (b)
XBlobHandle b;
X{
XBlobHandle g;
X
X g = (**b).glob;
X if (g != nil) /* skip if don't really have glued blob */
X {
X (**b).glob = nil;
X DrawBlob (b, inDragBlob);
X DecBlobGlue (g); /* dec use count and undim if necessary */
X }
X}
X
X
XUnglueGlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc1 (&UnglueGlob, bSet);
X}
X
X
X/*
X Glue donor blob d to receptor r. Redraw the drag area of r.
X Increment the use count of d, dimming it if necessary. If r
X already has a glue blob, unglue it first (undimming if necessary).
X*/
X
X
XGlueGlob (d, r)
XBlobHandle d, r;
X{
XBlobHandle g;
X
X g = (**r).glob; /* currently glued blob */
X if (g != d) /* ignore if has a glob and it's same */
X {
X if (g != nil) /* if it has a glob already, then */
X DecBlobGlue (g); /* detach and undim if necessary */
X (**r).glob = d;
X IncBlobGlue (d); /* increment use and dim if necessary */
X DrawBlob (r, inDragBlob); /* now have source in drag area - redraw */
X }
X}
X
X
X/*
X Transfer a glued blob from one blob to another (r1 -> r2). Redraw
X the drag areas of the blob losing the glued blob, and the one
X receiving it, but the use count of the transferred blob does not
X change, so it's not necessary to redraw it.
X*/
X
XTransferGlob (r1, r2)
XBlobHandle r1, r2;
X{
XBlobHandle g1, g2;
X
X if (r1 != r2) /* ignore unless different */
X {
X g1 = BGlob (r1);
X g2 = BGlob (r2);
X if (g1 != nil) /* can't transfer if nothing there! */
X {
X BGlob (r1) = nil; /* detach and redraw drag area */
X DrawBlob (r1, inDragBlob);
X if (g2 != nil) /* toss this first if something there */
X DecBlobGlue (g2); /* undim if necessary */
X BGlob (r2) = g1;
X DrawBlob (r2, inDragBlob); /* new donor in drag area - redraw */
X }
X }
X}
X
X
X/*
X Swap the globs glued to r1 and r2. If one of them doesn't actually
X have a glob, this is equivalent to a transfer.
X*/
X
XSwapGlob (r1, r2)
XBlobHandle r1, r2;
X{
XBlobHandle g1, g2;
X
X if (r1 != r2) /* ignore unless different */
X {
X g1 = BGlob (r1);
X g2 = BGlob (r2);
X if (g1 != g2) /* ignore if both have same glob */
X {
X BGlob (r1) = g2;
X BGlob (r2) = g1;
X DrawBlob (r1, inDragBlob);
X DrawBlob (r2, inDragBlob);
X }
X }
X}
X
X
X/*
X Glue the glob that's glued to r1 onto r2 as well. No check
X is made whether it's really gluable another time or not.
X*/
X
XDupGlob (r1, r2)
XBlobHandle r1, r2;
X{
XBlobHandle g;
X
X if ((g = BGlob (r1)) != nil)
X GlueGlob (g, r2); /* duplicate blob */
X}
X
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrZTrans.c
X# include "BlobMgr.h"
X
X
X/* -------------------------------------------------------------------- */
X/* Blob Transaction Routines - with zooming */
X/* -------------------------------------------------------------------- */
X
X
X/*
X Same as UnglueGlob, except that a rectangle is zoomed
X from the destination blob back to the source blob.
X*/
X
XZUnglueGlob (b)
XBlobHandle b;
X{
XBlobHandle g;
XRect r1, r2;
X
X g = (**b).glob;
X if (g != nil) /* skip if don't really have glued blob */
X {
X (**b).glob = nil;
X DrawBlob (b, inDragBlob);
X r1 = BDragBox (b);
X r2 = BDragBox (g);
X ZoomRect (&r1, &r2);
X DecBlobGlue (g); /* dec use count and undim if necessary */
X }
X}
X
X
XZUnglueGlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc1 (&ZUnglueGlob, bSet);
X}
X
X
X/*
X Same as GlueGlob, but zooms the donor to the receptor first
X*/
X
XZGlueGlob (d, r)
XBlobHandle d, r;
X{
XRect r1, r2;
X
X r1 = BDragBox (d);
X r2 = BDragBox (r);
X ZoomRect (&r1, &r2);
X GlueGlob (d, r);
X}
X
X
X/*
X Same as DupGlob, but zooms from the first receptor to the second
X before duplicating.
X
X This really should use the drag region of the first receptor's glob,
X mapped to the shape and position of the receptor, rather than the
X receptor's drag region - since it's the glob that's being transferred.
X But that requires mapping (and scaling when it's put in).
X*/
X
XZDupGlob (r1, r2)
XBlobHandle r1, r2;
X{
XRect rect1, rect2;
X
X if (BGlob (r1) != nil)
X {
X rect1 = BDragBox (r1);
X rect2 = BDragBox (r2);
X ZoomRect (&rect1, &rect2);
X DupGlob (r1, r2);
X }
X}
X
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrZoom.c
X# include <QuickDraw.h>
X
X/*
X Zooming parameters. zoomSteps is the number of steps in the
X interpolative series. It must not be zero. zoomShow is the number
X of steps that show at any one time in the series. It must be less
X than or equal to zoomSteps.
X*/
X
X# define zoomSteps 10
X# define zoomShow 3
X
X
X/*
X ZoomRect zooms a dotted rectangle from r1 to r2. The effect is
X transparent (screen no different afterwards). The shape of the zoomed
X rectangles changes for smooth interpolation.
X*/
X
XZoomRect (r1, r2)
XRect *r1, *r2;
X{
Xregister int r1left, r1top;
Xint hDiff, vDiff, widDiff, htDiff;
Xint l, t, r, b;
Xint rWid, rHt;
Xint i, j;
XRect zoomRect[zoomSteps];
XPenState ps;
X
X r1left = r1->left; /* these two statements make code shorter and */
X r1top = r1->top; /* impervious to mem mgr if rects passed by handle */
X hDiff = r2->left - r1left; /* positive if moving to right */
X vDiff = r2->top - r1top; /* positive if moving down */
X rWid = r1->right - r1left;
X rHt = r1->bottom - r1top;
X widDiff = (r2->right - r2->left) - rWid;
X htDiff = (r2->bottom - r2->top) - rHt;
X /* set pen gray, mode xor */
X GetPenState (&ps); /* save current pen state */
X PenPat (gray);
X PenMode (patXor);
X for (i = 0; i < zoomSteps; ++i)
X {
X j = i + 1;
X l = r1left + (hDiff * j) / zoomSteps;
X t = r1top + (vDiff * j) / zoomSteps;
X r = l + rWid + (widDiff * j) / zoomSteps;
X b = t + rHt + (htDiff * j) / zoomSteps;
X SetRect (&zoomRect[i], l, t, r, b);
X FrameRect (&zoomRect[i]); /* draw in xor */
X if (i >= zoomShow)
X FrameRect (&zoomRect[i-zoomShow]);
X }
X for (i = zoomSteps - zoomShow; i < zoomSteps; ++i)
X {
X FrameRect (&zoomRect[i]);
X }
X /* set pen normal */
X SetPenState (&ps); /* restore pen state */
X
X}
SHAR_EOF
exit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads