🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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)
#34
Author: macintosh
Date: Wed, 28 Jan 1987 07:00
1429 lines
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