maci...@felix.uucp
unread,Jan 27, 1987, 10:25:16 AM1/27/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:
# BMgr/BlobMgr.h
# BMgr/BMgrCalcRegion.c
# BMgr/BMgrClick.c
# BMgr/BMgrDrag.c
# BMgr/BMgrDraw.c
# BMgr/BMgrFlags.c
# BMgr/BMgrFreeze.c
# BMgr/BMgrHideShow.c
mkdir BMgr
sed 's/^X//' << 'SHAR_EOF' > BMgr/BlobMgr.h
X/* Blob Manager global types and constants */
X
X# ifndef _BlobMgr_
X
X# define _BlobMgr_
X
X# ifndef _Quickdraw_
X#include <QuickDraw.h> /* brings in MacTypes.h as well */
X# endif
X
X# ifndef nil
X# define nil 0L
X# endif
X
X
X/* blob flag masks */
X
Xenum
X{
X bEnableMask = 1,
X bFreezeMask = 2,
X bStatModeMask = 4,
X bDragModeMask = 8,
X bDrawModeMask = 12, /* two bits, derived: bStatModeMask + bDragModeMask */
X bNeedGlobMask = 16,
X bScaleMask = 32,
X bHJustMask = 192, /* two bits: 64 + 128 */
X bVJustMask = 768, /* two bits: 256 + 512 */
X bPicMask = 1024
X};
X
X
X/* blob drawing modes */
X
Xenum
X{
X normalDraw = 1, /* draw blob normally */
X dimDraw = 2 /* draw dimmed blob */
X};
X
X/* blob part codes */
X
Xenum
X{
X inStatBlob = 1, /* static region */
X inDragBlob = 2, /* drag region */
X inFullBlob = 3 /* entire blob */
X};
X
X/*
X special max glue count - no limit
X*/
X
X# define infiniteGlue 0x8000
X
X
X/*
X BlobClick return codes
X*/
X
Xenum
X{
X /* 0 = nothing done */
X bcGlue = 1, /* donor blob glued to receptor */
X bcUnglue, /* glob unglued from receptor */
X bcXfer, /* glob transferred from one receptor to another */
X bcDup, /* glob duplicated from one receptor onto another */
X bcSwap /* globs of two receptors swapped */
X};
X
X
X/*
X Messages passed by BlobClick to advisory functions
X*/
X
Xenum
X{
X advDClick, /* click in donor */
X advRClick, /* click in receptor */
X advGlue, /* glue transaction proposed */
X advUnglue, /* unglue transaction proposed */
X advXfer, /* transfer transaction proposed */
X advDup, /* duplicate transaction proposed */
X advSwap /* swap transaction proposed */
X};
X
X
X/* DragGrayRgn result code for bad drag - Inside Mac is wrong! */
X
X# define badDragResult 0x80008000L
X
X
X/*
X BlobRecord structure
X
X flags:
X bit 0: 1 = enabled, 0 = disabled
X bit 1: 1 = frozen, 0 = thawed (1/0)
X bit 2: 1 = static region is dimmed, 0 = normal
X bit 3: 1 = drag region is dimmed, 0 = normal
X bit 4: 1 = need explicit match, 0 = don't
X
X fzflags:
X bit 2: 1 = static region was dimmed before freeze, 0 = was normal
X bit 3: 1 = drag region was dimmed before freeze, 0 = was normal
X
X*/
X
Xtypedef struct BlobRecord
X{
X int flags; /* flags word */
X int fzFlags; /* freeze flags word */
X union /* pic if bPicMask flag word bit set*/
X { /* proc if bit clear */
X PicHandle bPic; /* blob picture (and original frame) */
X ProcPtr bDrawProc; /* blob drawing procedure */
X } bPicProc;
X RgnHandle statRgn; /* current static region */
X RgnHandle dragRgn; /* current drag region */
X Rect statRect; /* original static region frame */
X Rect dragRect; /* original drag region frame */
X int glueMax; /* maximum times can glue to others */
X int glueCount; /* number of times glued to others */
X struct MatchRecord **matches; /* set of valid matches */
X struct BlobRecord **glob; /* currently glued blob */
X long bRefCon; /* reference value */
X struct BlobRecord **nextBlob; /* next blob in set */
X} BlobRecord, *BlobPtr, **BlobHandle;
X
X
Xtypedef struct MatchRecord
X{
X BlobHandle mBlob; /* blob that matches */
X struct MatchRecord **nextMatch; /* next match record */
X} MatchRecord, *MatchPtr, **MatchHandle;
X
X
Xtypedef struct BlobSetRecord
X{
X BlobHandle firstBlob; /* first Blob of set */
X BlobHandle lastBlob; /* last Blob of set */
X struct BlobSetRecord **nextBlobSet; /* next blob set */
X} BlobSetRecord, *BlobSetPtr, **BlobSetHandle;
X
X
X/*
X Pseudo-functions
X*/
X
X# define FirstBlob(bSet) ((**(bSet)).firstBlob)
X# define LastBlob(bSet) ((**(bSet)).lastBlob)
X# define NextBlob(b) ((**(b)).nextBlob)
X# define SetBRefCon(b,val) ((**(b)).bRefCon = (long) (val))
X# define GetBRefCon(b) ((long) (**(b)).bRefCon)
X# define BStatBox(b) ((**((**(b)).statRgn)).rgnBBox)
X# define BDragBox(b) ((**((**(b)).dragRgn)).rgnBBox)
X# define BGlob(b) ((**(b)).glob)
X# define FirstBMatch(b) ((**((**(b)).matches)).mBlob)
X
X
X/*
X Functions returning non-integral values
X*/
X
XBlobHandle GetBlobHandle ();
XBlobHandle NewBlob ();
XBlobSetHandle NewBlobSet ();
XBoolean BlobQuiet ();
XBoolean BlobSetQuiet ();
XBoolean InBlobMatchSet ();
Xlong DTrackBlob ();
Xlong TrackBlob ();
XBoolean BlobDimmed ();
XBoolean BlobActive ();
XBoolean BlobFrozen ();
XBoolean BlobEnabled ();
XBoolean CanGlue ();
XBoolean PicBlob ();
XRgnHandle BCalcRegion ();
XBoolean BTrackMouse ();
X
X# endifSHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrCalcRegion.c
X# include "BlobMgr.h"
X
X
X/*
X Return copy of the region corresponding to the part code. The
X caller is responsible for disposing of the region that is returned.
X*/
X
XRgnHandle BCalcRegion (b, partCode)
XBlobHandle b;
Xint partCode;
X{
XRgnHandle rgn;
X
X rgn = NewRgn ();
X if (partCode == inDragBlob)
X CopyRgn ((**b).dragRgn, rgn);
X else
X {
X CopyRgn ((**b).statRgn, rgn);
X if (partCode == inFullBlob)
X UnionRgn ((**b).dragRgn, rgn, rgn);
X }
X return (rgn);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrClick.c
X/*
X BlobClick and support routines. BlobClick is the basic blob
X transaction handler. Other routines and variables are used
X to modify the way BlobClick functions.
X
X
X unglueZoom determines whether BlobClick will zoom an outline of the
X receptor drag region back to the donor when a donor is unglued
X from a receptor by double-clicking.
X
X badDragZoom determines whether the outline of a dragged donor will
X be zoomed back where it was dragged from if it's not dragged
X somewhere it can be glued to.
X
X The permission booleans control the types of transactions that
X BlobClick is allowed to perform:
X
X ungluePerm is true if double-clicking detaches globs from receptors.
X xferPerm is true if globs can be transferred between receptors.
X swapPerm is true if globs can be swapped between receptors.
X dupPerm is true if globs can be duplicated onto other receptors.
X replacePerm is true if transfers, swaps and duplications can cause
X a receptor's glob to be replaced by another. Note that if
X replacePerm is false, transfers and duplications can only be made
X to empty receptors, and swaps fail altogether.
X
X Swaps take precedence over duplications, and both take precedence
X over transfers, if two or more of these flags are on. All are
X subject to the value of the replacement flag, as noted above.
X
X lastWhen and lastWhere are for double-click detection.
X If lastWhen is set to 0, the next click will not be interpreted
X as a double-click. Since that's how it's initialized, BlobClick
X never mistakes the first click passed to it for a double-click.
X
X BlobClick only saves the click time and location when the user
X clicks in a receptor blob drag region and releases the mouse without
X moving it, since that's the only time a double-click is relevant.
X
X bcAdvise is the BlobClick filter function. If it's nil, BlobClick
X does all the work itself. If bcFilter is set to the address of
X some function, that function is consulted in certain circumstances
X to see whether to continue processing or not. If the filter returns
X false, BlobClick terminates early.
X
X bcResult holds the result of the last call to BlobClick. db1,
X db2, rb1 and rb2 are set to indicate which blobs were involved in
X any transaction that occurs (these are known as the cast (as in
X cast of thousands) of the transaction). The result code and the
X cast may be obtained by the host program with the BClickResult
X routine, and have meanings as follows:
X
X Glue: db1 = donor glued, rb1 = receptor glued to, db2 = donor replaced by
X db1 (nil if none), rb2 nil.
X Unglue: db1 = donor unglued, rb1 = receptor unglued from, db2, rb2 nil.
X Transfer: db1 = donor transferred, rb1 = source receptor,
X rb2 = destination receptor, db2 = donor replaced by db1 (nil if none).
X Duplication: same as transfer, except db1 = donor duplicated.
X Swap: db1 = donor originally on rb1, db2 = donor originally on rb2,
X rb1 = source receptor, rb2 = dest receptor.
X
X The result code and the cast are undefined if a filter function
X causes BlobClick to terminate early.
X
X srcRect and dstRect are used by BlobClick and BadDrag to keep
X track of how to do zoomback on bad drags.
X*/
X
X# include "BlobMgr.h"
X
X
Xstatic Boolean unglueZoom = true;
Xstatic Boolean badDragZoom = true;
X
Xstatic Boolean ungluePerm = true;
Xstatic Boolean xferPerm = true;
Xstatic Boolean replacePerm = true;
Xstatic Boolean dupPerm = false;
Xstatic Boolean swapPerm = true;
X
X
Xstatic long lastWhen = 0L;
Xstatic Point lastWhere;
X
Xstatic Boolean (*bcAdvise)() = nil;
X
Xstatic int bcResult;
Xstatic BlobHandle db1;
Xstatic BlobHandle db2;
Xstatic BlobHandle rb1;
Xstatic BlobHandle rb2;
X
Xstatic Rect srcRect, dstRect;
X
X
X/*
X Set or get the flags determining zoomback behavior on bad drags
X and unglue transactions
X*/
X
XSetBCZoomFlags (uGlueZoom, bDragZoom)
XBoolean uGlueZoom, bDragZoom;
X{
X unglueZoom = uGlueZoom;
X badDragZoom = bDragZoom;
X}
X
X
XGetBCZoomFlags (uGlueZoom, bDragZoom)
XBoolean *uGlueZoom, *bDragZoom;
X{
X *uGlueZoom = unglueZoom;
X *bDragZoom = badDragZoom;
X}
X
X
X/*
X Set or get the flags determining transaction permissions
X*/
X
XSetBCPermissions (canUnglue, canXfer, canDup, canSwap, canRep)
XBoolean canUnglue, canXfer, canDup, canSwap, canRep;
X{
X ungluePerm = canUnglue;
X xferPerm = canXfer;
X dupPerm = canDup;
X swapPerm = canSwap;
X replacePerm = canRep;
X}
X
X
XGetBCPermissions (canUnglue, canXfer, canDup, canSwap, canRep)
XBoolean *canUnglue, *canXfer, *canDup, *canSwap, *canRep;
X{
X *canUnglue = ungluePerm;
X *canXfer = xferPerm;
X *canDup = dupPerm;
X *canSwap = swapPerm;
X *canRep = replacePerm;
X}
X
X
X/*
X Set or get the address of the BlobClick advisory filter routine.
X Pass nil to SetBCFilter to turn the filter off.
X*/
X
XSetBCAdvisory (p)
XBoolean (*p)();
X{
X bcAdvise = p;
X}
X
X
XGetBCAdvisory (p)
XBoolean (**p)();
X{
X *p = bcAdvise;
X}
X
X
X/*
X FindReceptor is called with the point at which the mouse was released
X after a donor or a receptor's glob was dragged. It returns true if
X the mouse was released in a receptor that has an undimmed drag region
X and either (i) has no glob, or (ii) has a glob but replacement
X permission is on. Otherwise it returns false.
X*/
X
Xstatic Boolean FindReceptor (thePoint, rSet, r)
XPoint thePoint; /* point at which mouse released */
XBlobSetHandle rSet; /* receptor set */
XBlobHandle *r; /* return receptor hit in this */
X{
X return (FindBlob (thePoint, rSet, r)
X && GetBDrawMode (*r, inDragBlob) == normalDraw
X && (BGlob (*r) == nil || replacePerm));
X}
X
X
X/*
X BlobClick blob transaction handler
X*/
X
XBlobClick (thePt, t, dSet, rSet)
XPoint thePt;
Xlong t;
XBlobSetHandle dSet, rSet;
X{
XBlobHandle d, r1, r2;
XPoint thePoint;
Xregister long dragDelta;
Xregister Boolean badDrag = true; /* assume the worst */
X
X thePoint = thePt; /* do setup: make local copy of point */
X bcResult = 0; /* and initialize status variables */
X db1 = db2 = rb1 = rb2 = nil;
X
X/*
X Check for double-click if unglue permission is on. If so and both
X clicks were in drag region of a non-dim receptor that has a glob
X glued to it, unglue the glob. (Note that the hit-tests only work
X if the blob is not dimmed - which is as things should be.)
X*/
X if (ungluePerm && t - lastWhen <= GetDblTime ())
X {
X if (rSet != nil
X && FindBlob (thePoint, rSet, &r1) == inDragBlob
X && TestBlob (r1, lastWhere) == inDragBlob)
X {
X if (bcAdvise == nil || (*bcAdvise) (advUnglue, r1))
X {
X db1 = BGlob (r1);
X rb1 = r1;
X bcResult = bcUnglue;
X
X if (unglueZoom)
X ZUnglueGlob (r1);
X else
X UnglueGlob (r1);
X }
X }
X lastWhen = 0L;
X return;
X }
X
X lastWhen = 0L;
X
X/*
X See if the mouse was clicked in a donor blob. If so, drag an
X outline around. If the dragged outline ends up somewhere it
X can be glued to, do so, else zoom the outline back if appropriate.
X*/
X
X if (dSet != nil && FindBlob (thePoint, dSet, &d) == inDragBlob)
X {
X if (bcAdvise != nil && (*bcAdvise) (advDClick, d) == false)
X return; /* advisory says "quit" */
X
X dragDelta = DTrackBlob (d, inDragBlob, thePoint);
X if (dragDelta != badDragResult && dragDelta != 0)
X {
X thePoint.h += LoWord (dragDelta);
X thePoint.v += HiWord (dragDelta);
X srcRect = dstRect = BDragBox (d);
X OffsetRect (&dstRect, LoWord (dragDelta), HiWord (dragDelta));
X if (rSet != nil && FindReceptor (thePoint, rSet, &r1))
X {
X if (bcAdvise == nil || (*bcAdvise) (advGlue, r1))
X {
X db1 = d;
X db2 = BGlob (r1);
X rb1 = r1;
X bcResult = bcGlue;
X GlueGlob (d, r1);
X badDrag = false;
X }
X }
X if (badDrag && badDragZoom)
X ZoomRect (&dstRect, &srcRect);
X }
X }
X
X/*
X Mouse was not clicked in a donor. If it was clicked in a receptor,
X a glob may have been dragged back to the donor, or to another
X receptor, so get ready to process possible unglue or inter-receptor
X transaction. Can quit early if no receptor set was given
X (rSet = nil) or no inter-receptor or unglue transactions are allowed.
X*/
X else if (rSet != nil && (ungluePerm || xferPerm || swapPerm || dupPerm))
X {
X if (FindBlob (thePoint, rSet, &r1) == inDragBlob && BGlob (r1) != nil)
X {
X if (bcAdvise != nil && (*bcAdvise) (advRClick, r1) == false)
X return; /* advisory says "quit" */
X
X/*
X If the mouse is released without being moved, then save the click
X info, since it might be the first click of a double-click. There's
X no need to check any further for a possible transaction since the
X glob wasn't dragged anywhere.
X*/
X if ((dragDelta = DTrackBlob (r1, inDragBlob, thePoint)) == 0L)
X {
X lastWhen = t; /* save click info for possible */
X lastWhere = thePt; /* double-click next time */
X }
X else if (dragDelta != badDragResult)
X {
X thePoint.h += LoWord (dragDelta);
X thePoint.v += HiWord (dragDelta);
X
X/*
X Was the glob dragged back to it's owner? If so, unglue it if
X unglue permission is on. Can't use TestBlob, 'cause that'll
X be false if the donor is dimmed.
X*/
X d = BGlob (r1);
X if (ungluePerm && BlobActive (d)
X && (PtInRgn (thePoint, (**d).dragRgn)
X || PtInRgn (thePoint, (**d).statRgn)))
X {
X if (bcAdvise == nil || (*bcAdvise) (advUnglue, r1))
X {
X db1 = d;
X rb1 = r1;
X bcResult = bcUnglue;
X UnglueGlob (r1); /* no zooming */
X }
X return;
X }
X
X srcRect = dstRect = BDragBox (r1);
X OffsetRect (&dstRect, LoWord (dragDelta), HiWord (dragDelta));
X
X if (FindReceptor (thePoint, rSet, &r2) && r1 != r2)
X {
X
X /*
X Now know where the glob was dragged, so possibly have some kind
X of inter-receptor transaction. If replaces aren't allowed, then
X don't continue unless the receptor that was dragged to has no glob.
X Otherwise do whichever of swapping, duplicating or transferring is
X allowed. Precedence is in that order if more than one of them is
X allowed.
X */
X rb1 = r1; /* set cast now, but they */
X rb2 = r2; /* won't be meaningful if */
X db1 = BGlob (r1); /* no transaction is performed */
X db2 = BGlob (r2);
X if (db2 != nil && swapPerm)
X {
X if (bcAdvise == nil || (*bcAdvise) (advSwap, r2))
X {
X SwapGlob (r1, r2);
X bcResult = bcSwap;
X badDrag = false;
X }
X }
X else if (dupPerm)
X {
X if (CanGlue (db1))
X {
X if (bcAdvise == nil || (*bcAdvise) (advDup, r2))
X {
X DupGlob (r1, r2); /* duplicate blob */
X bcResult = bcDup;
X badDrag = false;
X }
X }
X }
X else if (xferPerm)
X {
X if (bcAdvise == nil || (*bcAdvise) (advXfer, r2))
X {
X TransferGlob (r1, r2); /* transfer blob */
X bcResult = bcXfer;
X badDrag = false;
X }
X }
X }
X if (badDrag && badDragZoom)
X ZoomRect (&dstRect, &srcRect);
X }
X }
X }
X}
X
X
X/*
X Result result code of last call to BlobClick.
X*/
X
XBClickResult ()
X{
X return (bcResult);
X}
X
X
X/*
X Result cast of characters involved in last call to BlobClick.
X*/
X
XBClickCast (d1, d2, r1, r2)
XBlobHandle *d1, *d2, *r1, *r2;
X{
X *d1 = db1;
X *d2 = db2;
X *r1 = rb1;
X *r2 = rb2;
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrDrag.c
X# include <WindowMgr.h>
X# include "BlobMgr.h"
X
X
X/* -------------------------------------------------------------------- */
X/* Blob Tracking and Dragging Routines */
X/* -------------------------------------------------------------------- */
X
X
X/*
X Blob dragging variables. See discussion of DragGrayRgn in
X the WIndow Manager section of Inside Mac. The defaults for the
X limit and slop rects are inappropriate and really should be set
X by the application.
X*/
X
XRect blobLimitRect = { -30000, -30000, 30000, 30000 };
XRect blobSlopRect = { -30000, -30000, 30000, 30000 };
Xint blobAxis = noConstraint;
X
X
X/* Set blob dragging limit and slop rectangles */
X
XSetBDragRects (limitRect, slopRect)
XRect *limitRect, *slopRect;
X{
X blobLimitRect = *limitRect;
X blobSlopRect = *slopRect;
X}
X
X
X/* get current blob dragging limit and slop rectangles */
X
XGetBDragRects (limitRect, slopRect)
XRect *limitRect, *slopRect;
X{
X *limitRect = blobLimitRect;
X *slopRect = blobSlopRect;
X}
X
X
X/* Set blob dragging axis constraints */
X
XSetBDragAxis (axis)
Xint axis;
X{
X blobAxis = axis;
X}
X
X
X/* Get current blob dragging axis constraints */
X
XGetBDragAxis ()
X{
X return (blobAxis);
X}
X
X
X/*
X Track blob by dragging an outline of the indicated part around
X until the mouse button is released. Return the difference between
X the starting and ending x and y coordinates in the low and high
X order words of the result.
X*/
X
X
Xlong TrackBlob (b, partCode, startPoint, limitRect, slopRect, axis)
XBlobHandle b;
Xint partCode;
XPoint startPoint;
XRect *limitRect, *slopRect;
Xint axis;
X{
XRgnHandle rgn;
XRect limit, bounds;
Xlong result;
X
X rgn = BCalcRegion (b, partCode);
X/*
X adjust the limit rectangle so the outline of the dragged regiopn
X always fits completely within the bounds rectangle
X*/
X limit = *limitRect;
X bounds = (**rgn).rgnBBox;
X limit.left += startPoint.h - bounds.left;
X limit.top += startPoint.v - bounds.top;
X limit.right -= bounds.right - startPoint.h - 1;
X limit.bottom -= bounds.bottom - startPoint.v - 1;
X
X result = DragGrayRgn (rgn, startPoint, &limit, slopRect, axis, nil);
X DisposeRgn (rgn);
X return (result);
X}
X
X
X/*
X Track a blob, using the default limit and slop rects
X*/
X
Xlong DTrackBlob (b, partCode, startPoint)
XBlobHandle b;
Xint partCode;
XPoint startPoint;
X{
X
X return (TrackBlob (b, partCode, startPoint,
X &blobLimitRect, &blobSlopRect, blobAxis));
X}
X
X
X/*
X Drag a blob by tracking it, and then moving it to the point
X where the mouse button was released.
X*/
X
XDragBlob (b, startPoint, limitRect, slopRect, axis)
XBlobHandle b;
XPoint startPoint;
XRect *limitRect, *slopRect;
Xint axis;
X{
Xlong result;
X
X result = TrackBlob (b, inFullBlob, startPoint,
X limitRect, slopRect, axis);
X
X if ((result != badDragResult) && (result != 0))
X OffsetBlob (b, inFullBlob, LoWord (result), HiWord (result));
X}
X
X
XDDragBlob (b, startPoint)
XBlobHandle b;
XPoint startPoint;
X{
X DragBlob (b, startPoint, &blobLimitRect, &blobSlopRect, blobAxis);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrDraw.c
X/* --------------------------------------------------------------------- */
X/* Blob Manager Low-level Drawing Routines */
X/* --------------------------------------------------------------------- */
X
X# include "BlobMgr.h"
X
X
X
X/*
X Blob dimming parameters. dimPat and dimMode are the pattern and
X drawing mode used to dim out blobs. The initial pattern is gray.
X*/
X
Xstatic Pattern dimPat = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };
Xstatic int dimMode = patBic;
X
Xstatic RgnHandle oldClipRgn;
X
X
X/*
X Set or get the pattern to be used to dim blobs
X*/
X
XSetBDimInfo (p, mode)
XPattern *p;
Xint mode;
X{
X BlockMove (p, &dimPat, sizeof (Pattern));
X dimMode = mode;
X}
X
XGetBDimInfo (p, mode)
XPattern *p;
Xint *mode;
X{
X BlockMove (&dimPat, p, sizeof (Pattern));
X *mode = dimMode;
X}
X
X
X/*
X Set the clipping to the given region of the given blob. Return
X a handle to the region, or nil if the region is empty and doesn't
X need to be drawn. The handle should not be disposed of by the
X caller - it's a copy of the handle, not a copy of the region.
X If the handle returned is not nil, call RestoreDrawClip after doing
X the drawing to restore the clipping properly.
X*/
X
Xstatic RgnHandle SetDrawClip (b, partCode)
XBlobHandle b;
Xint partCode;
X{
Xregister RgnHandle drawRgn, newClipRgn;
X
X drawRgn = (partCode == inDragBlob ? (**b).dragRgn : (**b).statRgn);
X if (EmptyRgn (drawRgn)) /* don't bother if fail here! */
X return (nil);
X
X oldClipRgn = NewRgn ();
X newClipRgn = NewRgn ();
X GetClip (oldClipRgn);
X SectRgn (drawRgn, oldClipRgn, newClipRgn);
X SetClip (newClipRgn);
X DisposeRgn (newClipRgn);
X return (drawRgn);
X}
X
X
Xstatic RestoreDrawClip ()
X{
X SetClip (oldClipRgn); /* restore original clipping */
X DisposeRgn (oldClipRgn);
X}
X
X
X/*
X Dim the given region.
X*/
X
Xstatic DimRgn (rgn)
XRgnHandle rgn;
X{
XPenState ps;
X
X GetPenState (&ps); /* save current pen state */
X PenPat (dimPat);
X PenMode (dimMode);
X PaintRgn (rgn);
X SetPenState (&ps); /* restore pen state */
X}
X
X
X/*
X Given a picture and a rectangle corresponding to a portion of the picture
X frame DrawBlobPic draws the picture in the given part of the given blob,
X accounting for size and location differences. Any portion of sRect
X lying outside of the picture's frame will not be drawn.
X The partCode must be inDragBlob or inFullBlob.
X
X The drawing is clipped to the region the be drawn
X (respecting current clipping).
X*/
X
Xstatic DrawBlobPic (b, partCode, p, srcRect)
XBlobHandle b;
Xint partCode;
XPicHandle p;
XRect *srcRect;
X
X{
Xregister RgnHandle rgn;
XRect dstRect, pFrame;
X
X rgn = SetDrawClip (b, partCode);
X if (p != nil && rgn != nil) /* don't bother if fail here! */
X {
X pFrame = (**p).picFrame; /* map frame to correct size */
X dstRect = (**rgn).rgnBBox; /* and location in relation */
X MapRect (&pFrame, srcRect, &dstRect); /* to region to be drawn */
X DrawPicture (p, &pFrame);
X if (GetBDrawMode (b, partCode) == dimDraw) /* region is dimmed */
X DimRgn (rgn);
X }
X if (rgn != nil)
X RestoreDrawClip (); /* restore original clipping */
X}
X
X
X/*
X Draw a blob using a drawing procedure. bDst is the blob to be drawn,
X partCode specifies the region of bDst to draw (either inDragBlob or
X inStatBlob). bSrc is the blob whose region is to be drawn in the
X specified region of bDst, and proc is the drawing procedure to use.
X bSrc is different than bDst if partCode is inDragBlob and bDst has
X a glob.
X*/
X
Xstatic CallBDrawProc (bDst, bSrc, proc, partCode)
XBlobHandle bDst, bSrc;
XProcPtr proc;
Xint partCode;
X{
Xregister RgnHandle rgn;
X
X rgn = SetDrawClip (bDst, partCode);
X if (proc != nil && rgn != nil)
X {
X (*proc) (bDst, bSrc, partCode);
X if (GetBDrawMode (bDst, partCode) == dimDraw) /* region is dimmed */
X DimRgn (rgn);
X }
X if (rgn != nil)
X RestoreDrawClip (); /* restore original clipping */
X}
X
X
X/*
X DrawBlob draws the indicated part of the blob (the entire blob
X if partCode is inFullBlob).
X
X The blob must be enabled. If draw mode is dimDraw then draw
X it dimmed.
X*/
X
X
XDrawBlob (b, partCode)
XBlobHandle b;
Xint partCode;
X
X{
Xregister BlobHandle b2;
Xregister PicHandle pic;
XRect srcFrame;
X
X if (BlobEnabled (b))
X {
X if ((partCode == inStatBlob) || (partCode == inFullBlob))
X {
X if (PicBlob (b))
X {
X srcFrame = (**b).statRect;
X DrawBlobPic (b, inStatBlob, (**b).bPicProc.bPic, &srcFrame);
X }
X else
X CallBDrawProc (b, b, (**b).bPicProc.bDrawProc, inStatBlob);
X }
X
X if ((partCode == inDragBlob) || (partCode == inFullBlob))
X {
X /*
X Set b2 to the blob that should have it's drag region drawn
X in b's drag region. If b has no glob, then it's b.
X */
X if ((b2 = BGlob (b)) == nil)
X b2 = b;
X if (PicBlob (b2))
X {
X pic = (**b2).bPicProc.bPic; /* picture to draw */
X srcFrame = (**b2).dragRect; /* part of picture to draw */
X DrawBlobPic (b, inDragBlob, pic, &srcFrame);
X }
X else
X CallBDrawProc (b, b2, (**b2).bPicProc.bDrawProc, inDragBlob);
X }
X }
X}
X
X
XDrawBlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc2 (&DrawBlob, bSet, inFullBlob);
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrFlags.c
X# include "BlobMgr.h"
X
X
X/* -------------------------------------------------------------------- */
X/* Blob Flag Manipulation Routines */
X/* */
X/* These routines operate only on the content of the blob state fields.*/
X/* They do NOT do any redrawing or change the display in any way. */
X/* */
X/* -------------------------------------------------------------------- */
X
X
XSetBlobFlags (b, bitMask)
XBlobHandle b;
Xint bitMask;
X{
X (**b).flags |= bitMask;
X}
X
X
XClearBlobFlags (b, bitMask)
XBlobHandle b;
Xint bitMask;
X{
X (**b).flags &= ~bitMask; /* what's the operator here? */
X}
X
X
X/*
X Test the function result to be sure it's equal to the bitMask
X passed in, if exact match is required.
X*/
X
XTestBlobFlags (b, bitMask)
XBlobHandle b;
Xint bitMask;
X{
X return ((**b).flags & bitMask);
X}
X
X
XEnableBlob (b)
XBlobHandle b;
X{
X SetBlobFlags (b, bEnableMask);
X}
X
X
XEnableBlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc1 (&EnableBlob, bSet);
X}
X
X
XDisableBlob (b)
XBlobHandle b;
X{
X ClearBlobFlags (b, bEnableMask);
X}
X
X
XDisableBlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc1 (&DisableBlob, bSet);
X}
X
X
X
XGetBDrawMode (b, partCode)
XBlobHandle b;
Xint partCode;
X{
Xint mask;
X
X mask = 0;
X switch (partCode)
X {
X case inDragBlob: mask = bDragModeMask; break;
X case inStatBlob: mask = bStatModeMask; break;
X }
X return (TestBlobFlags (b, mask) == mask ? dimDraw : normalDraw);
X}
X
X
XSetBDrawMode (b, partCode, mode)
XBlobHandle b;
Xint partCode;
Xint mode;
X{
Xint mask;
X
X switch (partCode)
X {
X case inFullBlob: mask = bDrawModeMask; break;
X case inDragBlob: mask = bDragModeMask; break;
X case inStatBlob: mask = bStatModeMask; break;
X }
X if (mode == dimDraw)
X SetBlobFlags (b, mask);
X else
X ClearBlobFlags (b, mask);
X}
X
X
XGetFzBDrawMode (b, partCode)
XBlobHandle b;
Xint partCode;
X{
Xint mask;
X
X mask = 0;
X switch (partCode)
X {
X case inDragBlob: mask = bDragModeMask; break;
X case inStatBlob: mask = bStatModeMask; break;
X }
X return (((**b).fzFlags & mask) == mask ? dimDraw : normalDraw);
X}
X
X
X
XBoolean BlobDimmed (b, partCode)
XBlobHandle b;
Xint partCode;
X{
Xint bitMask;
X
X switch (partCode)
X {
X case inFullBlob: bitMask = bDrawModeMask; break;
X case inStatBlob: bitMask = bStatModeMask; break;
X case inDragBlob: bitMask = bDragModeMask; break;
X }
X return (TestBlobFlags (b, bitMask) == bitMask);
X}
X
X
XBoolean BlobEnabled (b)
XBlobHandle b;
X{
X return (TestBlobFlags (b, bEnableMask) == bEnableMask);
X}
X
X
XBoolean BlobFrozen (b)
XBlobHandle b;
X{
X return (TestBlobFlags (b, bFreezeMask) == bFreezeMask);
X}
X
X
X/*
X Active = enabled, but not frozen.
X*/
X
XBoolean BlobActive (b)
XBlobHandle b;
X{
X return (TestBlobFlags (b, bEnableMask | bFreezeMask) == bEnableMask);
X}
X
X
X/*
X Return true if the blob can be glued to another blob. This is true
X if the blob is infinitely gluable or the current glue count is less
X than the blob's maximum glue count.
X*/
X
XBoolean CanGlue (b)
XBlobHandle b;
X{
Xint glueMax;
X
X glueMax = GetBGlueMax (b);
X return (glueMax == infiniteGlue || glueMax > (**b).glueCount);
X}
X
X
X/*
X Return true if the blob is a picture blob, false if it's a
X procedure blob
X*/
X
XBoolean PicBlob (b)
XBlobHandle b;
X{
X return (TestBlobFlags (b, bPicMask) == bPicMask);
X}SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrFreeze.c
X# include "BlobMgr.h"
X
X
XFreezeBlob (b)
XBlobHandle b;
X{
X if (!BlobFrozen (b))
X {
X SetBlobFlags (b, bFreezeMask);
X (**b).fzFlags = ((**b).flags & (bDrawModeMask));
X }
X}
X
X
XFreezeBlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc1 (&FreezeBlob, bSet);
X}
X
X
XThawBlob (b)
XBlobHandle b;
X{
X if (BlobFrozen (b))
X {
X ClearBlobFlags (b, bFreezeMask); /* unfreeze blob */
X HiliteBlob (b, inStatBlob, GetFzBDrawMode (b, inStatBlob));
X HiliteBlob (b, inDragBlob, GetFzBDrawMode (b, inDragBlob));
X }
X}
X
X
XThawBlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc1 (&ThawBlob, bSet);
X}
X
X
X/*
X Display enabled quiet blobs with drawing mode quietMode, display
X enabled noisy blobs with drawing mode noisyMode. Freezes all enabled
X blobs, so should be balanced with a call to ThawBlobs.
X*/
X
X
XBlobFeedback (bSet, quietMode, noisyMode)
XBlobSetHandle bSet;
Xint quietMode, noisyMode;
X{
XBlobHandle b;
X
X for (b = FirstBlob (bSet); b != nil; b = NextBlob (b))
X {
X FreezeBlob (b);
X HiliteBlob (b, inFullBlob, (BlobQuiet (b) ? quietMode : noisyMode));
X }
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > BMgr/BMgrHideShow.c
X# include "BlobMgr.h"
X
X
X
X/*
X If blob not already hidden, hide it by filling both the bounds
X box of each region with current grafport's background pattern,
X and accumulate the boxes into the update region.
X*/
X
XHideBlob (b)
XBlobHandle b;
X{
XGrafPtr thePort;
XRect r;
X
X if (BlobEnabled (b)) /* ignore if already disabled */
X {
X DisableBlob (b);
X GetPort (&thePort);
X
X r = BStatBox (b);
X FillRect (&r, &thePort->bkPat);
X InvalRect (&r);
X
X r = BDragBox (b);
X FillRect (&r, &thePort->bkPat);
X InvalRect (&r);
X }
X}
X
X
XHideBlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc1 (&HideBlob, bSet);
X}
X
X
X/*
X If blob is not already enabled, show it.
X*/
X
XShowBlob (b)
XBlobHandle b;
X{
X if (BlobEnabled (b) == false) /* ignore if already enabled */
X {
X EnableBlob (b);
X DrawBlob (b, inFullBlob);
X }
X}
X
X
XShowBlobSet (bSet)
XBlobSetHandle bSet;
X{
X BlobLoopProc1 (&ShowBlob, bSet);
X}
SHAR_EOF
exit