bin@primate.wisc.edu (Brain in Neutral) (01/09/90)
This is a TransSkel application that demonstrates marquee rectangles.
It was written for TransSkel v1, so the SkelInit() call (at least)
will need a slight diddle, I suppose.
Click and drag the mouse repeatedly to select various rects that are
marqueed. This happens on a Mondrian background to demonstrate that
the algorithm is non-destructive.
Paul DuBois
dubois@primate.wisc.edu
/*
Marquee 1.1 - simple demonstration to draw rectangle which is outlined
by a moving marquee. Click and drag the mouse to select the
rectangle to be outlined. This version is non-destructive, unlike
a version I released earlier.
The project should include MacTraps, TransSkel.c (or a project built
from TransSkel.c) and this file, Marquee.c.
21 July 1986 Paul DuBois
*/
# include <WindowMgr.h>
# define nil 0L
WindowPtr theWind;
Rect mRect = { 0, 0, 0, 0 };
Pattern marqueePat = { 0x0f, 0x87, 0xc3, 0xe1, 0xf0, 0x78, 0x3c, 0x1e };
Pattern shiftPat = { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 };
/*
Frame rectangle, using marquee pattern. The rect is drawn in xor mode.
This procedure should be called to draw the marquee initially, then
MoveMarqueeRect should be called repeatedly to move the pattern.
Finally, call MarqueeRect again to erase the marquee. The display
will end up the same as it was before.
*/
MarqueeRect (r)
Rect *r;
{
PenState p;
GetPenState (&p);
PenPat (marqueePat);
PenMode (patXor);
FrameRect (r);
SetPenState (&p);
}
/*
Frame rectangle, using pattern that moves the marquee. Then shift
the pattern and the marquee pattern, to keep the two in sync.
This procedure must be called repeatedly to achieve the effect of
motion.
*/
MoveMarqueeRect (r)
Rect *r;
{
PenState p;
Byte c1, c2;
int i;
GetPenState (&p);
PenPat (shiftPat);
PenMode (patXor);
FrameRect (r);
SetPenState (&p);
c1 = marqueePat[0]; /* shift patterns up for next call */
c2 = shiftPat[0];
for (i = 0; i < 7; ++i) /* (could shift sideways instead) */
{
marqueePat[i] = marqueePat[i+1];
shiftPat[i] = shiftPat[i+1];
}
marqueePat[7] = c1;
shiftPat[7] = c2;
}
/*
While mouse is down, draw selection rectangle in the current
port. Return the resultant rect in dstRect. The rect is always
clipped to the current portRect.
*/
DoSelectRect (startPoint, dstRect)
Point startPoint;
Rect *dstRect;
{
Point pt, dragPt;
Rect rClip;
GrafPtr thePort;
PenState ps;
int i, count = 0;
GetPort (&thePort);
rClip = thePort->portRect;
GetPenState (&ps);
PenPat (marqueePat);
PenMode (patXor);
dragPt = startPoint;
Pt2Rect (dragPt, dragPt, dstRect);
FrameRect (dstRect);
for (;;)
{
GetMouse (&pt);
if (!EqualPt (pt, dragPt)) /* mouse has moved, change rect */
{
FrameRect (dstRect);
dragPt = pt;
Pt2Rect (dragPt, startPoint, dstRect);
(void) SectRect (dstRect, &rClip, dstRect);
FrameRect (dstRect);
for (i = 0; i < 1000; ++i) { /* delay to avoid flicker */ }
count = 5;
}
if (++count > 5) /* make marquee move every so often */
{
MoveMarqueeRect (dstRect);
PenPat (marqueePat);
count = 0;
}
if (!StillDown ()) break;
}
FrameRect (dstRect); /* erase last rect */
SetPenState (&ps);
}
/*
Draw selection rectangle as long as mouse is held down. Use it
for the marquee rectangle.
*/
Mouse (thePt, t, mods)
Point thePt;
long t;
int mods;
{
MarqueeRect (&mRect); /* erase previous marquee */
DoSelectRect (thePt, &mRect); /* draw selection rectangle */
MarqueeRect (&mRect); /* draw new marquee */
}
Idle ()
{
MoveMarqueeRect (&mRect); /* make marquee move */
}
Clobber ()
{
DisposeWindow (theWind);
}
/*
Install window handler
*/
MarqueeInit ()
{
Rect r;
int SkelWhoa();
SetRect (&r, 80, 60, 430, 250);
theWind = NewWindow (nil, &r, "\pMarquee", true, noGrowDocProc, -1L,
true, 0L);
SkelWindow (theWind,
Mouse, /* select rectangle */
nil, /* ignore keyclicks */
nil, /* update proc */
nil, /* activate proc */
SkelWhoa, /* quit on click in close box */
Clobber, /* disposal proc */
Idle, /* idle proc */
true); /* idle only when frontmost */
}
/*
return integer between zero and max (inclusive). assumes max is
non-negative.
*/
Rand (max)
int max;
{
register int t;
t = Random ();
if (t < 0) t = -t;
return (t % (max + 1));
}
/*
Draw some stuff so there is background - makes it obvious that
the marquee stuff is non-destructive.
*/
DrawRects ()
{
int i, sizeX, sizeY;
Point pt1, pt2;
Rect dstRect;
sizeX = theWind->portRect.right;
sizeY = theWind->portRect.bottom;
for (i = 0; i < 20; ++i)
{
SetPt (&pt1, Rand (sizeX), Rand (sizeY));
SetPt (&pt2, Rand (sizeX), Rand (sizeY));
Pt2Rect (pt1, pt2, &dstRect);
InvertRect (&dstRect);
}
}
main ()
{
SkelInit (); /* initialize TransSkel */
MarqueeInit (); /* install window handler */
DrawRects (); /* draw some background */
SkelMain (); /* handle events */
SkelClobber (); /* throw away handlers */
}