Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!rutgers!lll-lcc!pyramid!hplabs!felix!macintosh From: macintosh@felix.UUCP Newsgroups: mod.mac.sources Subject: BMgr - Blob Manager source (part 1 of 2) Message-ID: <2190@felix.UUCP> Date: Tue, 27-Jan-87 10:25:16 EST Article-I.D.: felix.2190 Posted: Tue Jan 27 10:25:16 1987 Date-Received: Wed, 28-Jan-87 21:34:04 EST Sender: macintosh@felix.UUCP Reply-To: macintosh@felix.UUCP (The Moderator) Organization: FileNet Corp., Costa Mesa, Ca. Lines: 1285 Approved: bytebug@felix.UUCP (Roger L. Long) #!/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 /* 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 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