[comp.sources.mac] Dial CDEF 1.0 Sources

duggie@jessica.stanford.edu (Doug Felt) (10/17/88)

[Dial CDEF 1.0 Sources]

This is LSC 3.0 source to a CDEF resource that displays a 'dial'
control.  It handles dragging a needle and showing the value of the
control in a box, and most of the standard Control Manager stuff.

Doug Felt

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#
#	DialSRC/about_dial_cdef
#	DialSRC/cdef.h
#	DialSRC/cdef.c
#	DialSRC/bitmap.h
#	DialSRC/bitmap.c
#	DialSRC/rectutils.h
#	DialSRC/rectutils.c
#	DialSRC/sincos.h
#	DialSRC/sincos.c
#	DialSRC/main.c
#
# This archive created: Sun Oct 16 09:13:45 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
#
export PATH; PATH=/bin:$PATH
echo shar: making directory "'DialSRC'"
mkdir DialSRC
echo shar: extracting "'DialSRC/about_dial_cdef'" '(2809 characters)'
if test -f 'DialSRC/about_dial_cdef'
then
	echo shar: will not over-write existing file "'DialSRC/about_dial_cdef'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/about_dial_cdef'
XSeptember 15, 1988
XDial CDEF version 1.0
X
XAbout the Dial CDEF sources...
X
XThe Dial CDEF comes in two stuffit'd packages.  One contains the LSC 3.0 source,
Xthe other a small sample application which uses the CDEF resource in its
Xresource fork, and illustrates the standard ControlManager calls.  If you
Xclick on the white-on-black title area at the bottom of the CDEF, you can
Xdrag the control around on the screen.  (I didn't bother to include source
Xfor the sample application since it is so small, hope that's ok).
X
XI hacked the Dial CDEF together over a few days to see whether it was worth
Xthe trouble, after reading the artitle in MacTutor.  As I stated in my posting,
XI really don't see any advantage in using CDEF's rather than a library, but I 
Xpromptly got half a dozen letters asking me to post it anyway-- maybe other
Xpeople can see advantages where I can't.  Tell me if you do!
X
XCDEFs are poorly documented.  After rolling the code into CDEF form I put a
XDebugger call just inside the entry point to see the order of messages and the
Xvalue of param, and traced what routines got called.  This clarified some
Xthings and left others murky.  The biggest problem was that param contains
Xa short int value with garbage in the high word on two calls, which was not
Xdocumented.  If you blithely test the whole long word for non-zero values, as
XI did at first, you almost always get a non-zero value and do the wrong thing.
X
XThis is not guaranteed to be robust code.  I made a minimal attempt to make sure
Xthings behave reasonably under low memory conditions, but have not tested it
Xthoroughly (with heap scramble, low memory, etc).  Use it as an example and be
Xprepared to fix bugs.
X
XAlso note that you may need to change the include statements in some files.  My
Xfile organization has lots of utility source in a separate folder.  Just edit
Xaccordingly.  Other than that, to build the CDEF just link with MacTraps.
X
XThe main thing missing in my opinion is no numbers on the dial itself.  I wrote
Xnumbers into a dial-like library that I will use instead of a CDEF (among other
Xthings, I get to use floating point values this way) and it is pretty easy to
Xdo.  All the floating point code is slow on a plus (I develop on a II) and even
Xredrawing the dials to deactivate them on a II takes a noticable amount of time.
XI haven't bothered to speed things up.  Besides these improvements, you can always
Xadd color too, but you will have to replace the offscreen drawing code.
X
XSo here it is.  I hope it's useful as an example, and perhaps you can find some
Xreal use for it.  Enjoy!
X
XDoug Felt
XCourseware Authoring Tools Project
XSweet Hall 3rd Floor
XStanford University
XStanford, CA 94305
Xduggie@jessica.stanford.edu
X
X
XP.S. And you get my b/w offscreen drawing code (also not debugged) for free! 
XWhat a deal!
SHAR_EOF
if test 2809 -ne "`wc -c < 'DialSRC/about_dial_cdef'`"
then
	echo shar: error transmitting "'DialSRC/about_dial_cdef'" '(should have been 2809 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/cdef.h'" '(227 characters)'
if test -f 'DialSRC/cdef.h'
then
	echo shar: will not over-write existing file "'DialSRC/cdef.h'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/cdef.h'
X/*
X * header for cdev.c
X */
X
Xlong MyControl(int varCode, ControlHandle theControl, int message, long param);
X
Xtypedef enum {
X	CInNothing = 0,CInTitle,CInNumBox,CInDial = 129
X} CPartNumber;
X
X#define kMinWid 75
X#define kMinHt 75
SHAR_EOF
if test 227 -ne "`wc -c < 'DialSRC/cdef.h'`"
then
	echo shar: error transmitting "'DialSRC/cdef.h'" '(should have been 227 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/cdef.c'" '(15642 characters)'
if test -f 'DialSRC/cdef.c'
then
	echo shar: will not over-write existing file "'DialSRC/cdef.c'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/cdef.c'
X/*
X * Doug Felt, 9/5/88 creation.
X *
X * the cdev routines
X *
X * varcodes:
X *
X * if the low bit of the varcode is 1, do not show the number box in the middle of
X * the dial.
X * 
X * bugs:
X *
X * there may be memory problems involving allocation of the offscreen bitmaps during
X * drawing.  this is just a quick hack so I don't know.
X *
X * possible modifications:
X *
X * -- more varcodes to number the ticks, and to toggle whether the name shows.
X *
X * -- changing to 'inactive' state is slow since I redraw the whole image.  it would
X * probably be better to keep a region of the dial background and redraw it in
X * white.  
X *
X * -- what really slows this down on the plus is the floating point calculations,
X * so if this were to run on the plus it might be better to use fixed point.
X * 
X * -- support for color, real grays, pixmaps instead of bitmaps, etc.
X */
X
X#include "cdef.h"
X
X#include "sincos.h"
X#include "rectutils.h"
X#include "bitmap.h"
X
Xstatic void cDraw(ControlHandle theControl, long param);
Xstatic long cTest(ControlHandle theControl, long param);
Xstatic void cCalcRgns(ControlHandle theControl, long param);
Xstatic void cInit(int varCode, ControlHandle theControl);
Xstatic void cDispose(ControlHandle theControl);
Xstatic void cPos(ControlHandle theControl, long param);
Xstatic void cThumb(ControlHandle theControl, long param);
Xstatic long cDrag(ControlHandle theControl, long param);
Xstatic long cAutoTrack(ControlHandle theControl, long param);
X
Xstatic void redrawPict(ControlHandle ch);
Xstatic void calcValue(ControlHandle ch);
Xstatic void drawValue(ControlHandle ch);
Xstatic int  pointToValue(ControlHandle ch, Point pt);
Xstatic void xdrawValue(ControlHandle ch);
Xstatic void drawRectImage(ControlHandle ch, Rect *r);
Xstatic void setNewValue(ControlHandle ch, int v);
Xstatic Boolean checkAndUpdate(ControlHandle ch);
X
X/* 
X * try to accomodate the system we are running on a little bit, in case it has
X * a wierd selection of fonts.
X */
X#define kNumFontName "\pGeneva"
X#define kNameFontName "\pNew York"
X#define kNameFontMax 16
X#define kNameFontMin 12
X#define kNumFontMax 10
X#define kNumFontMin 8
X
X/* 
X * needle image ranges between -kNeedleMax and kNeedleMax degrees.
X * ticks are in increments of kTickIncrement degrees, should evenly divide
X * 2 * kNeedleMax
X */
X#define kNeedleMax 80
X#define kTickIncrement 10
X
Xtypedef struct {
X	Rect limitRect;
X	Rect slopRect;
X	int axis;
X} CThumbRec, *PCThumbRec;
X
Xtypedef struct {
X	Rect lastR;
X	Rect trackR;
X	Rect titleR;
X	Rect numR;
X	Boolean inactive;
X	Boolean doNum;
X	int numFont;
X	int numSize;
X	int numBase;
X	Point cp,ep;
X	PBMap buffer;
X	PBMap image;
X} IData, *PIData, **HIData;
X
Xlong
XMyControl(varCode, theControl, message, param)
Xint varCode;
XControlHandle theControl;
Xint message;
Xlong int param;
X{
Xlong int res = 0L;
XGrafPtr port;
X
X	GetPort(&port);	/* I'm chicken */
X	SetPort((**theControl).contrlOwner);
X	switch (message) {
X		case drawCntl: cDraw(theControl,param); break;
X		case testCntl: res = cTest(theControl,param); break;
X		case calcCRgns: cCalcRgns(theControl,param); break;
X		case initCntl: cInit(varCode,theControl); break;
X		case dispCntl: cDispose(theControl); break;
X		case dragCntl: res = cDrag(theControl,param); break;
X		case posCntl: cPos(theControl,param); break;
X		case thumbCntl: cThumb(theControl,param); break;
X		case autoTrack: res = cAutoTrack(theControl,param); break;
X		default: break;
X	}
X	SetPort(port);
X	return res;
X}
X
Xstatic void
XcDraw(ch,param)
XControlHandle ch;
Xlong param;
X{
XHIData idh;
XRect r;
XBoolean newpict;
X
X	if ((**ch).contrlVis) {
X		param &= 0xffff;	/* apparently, garbage in high word!!! */
X		idh = (HIData)(**ch).contrlData;
X		r = (**ch).contrlRect;
X		if (idh) {
X			newpict = checkAndUpdate(ch);
X			if ((param != 129) || newpict) {
X				if (newpict)
X					calcValue(ch);
X				drawRectImage(ch,&r);
X			} else {
X				setNewValue(ch,(**ch).contrlValue);	/* only track indicator */
X			}
X		} else {
X			PenNormal();	/* couldn't allocate offscreen buffers, etc */
X			FrameRect(&r);
X			SysBeep(3);
X		}
X	}
X}
X
X/*
X * return the number of the control part
X */
Xstatic long
XcTest(ch,param)
XControlHandle ch;
Xlong param;
X{
XCPartNumber res = CInNothing;
XHIData idh;
Xint bot;
XPoint pt;
X
X	if ((**ch).contrlHilite != 255) {
X		pt = *(Point *)&param;
X		if (PtInRect(pt,&(**ch).contrlRect)) {
X			idh = (HIData)(**ch).contrlData;
X			if (idh) {
X				bot = (**idh).titleR.top;
X				if (pt.v > bot)
X					res = CInTitle;
X				else {
X					if ((**idh).doNum && PtInRect(pt,&(**idh).numR)) {
X						res = CInNumBox;
X					} else {
X						res = CInDial;
X					}
X				}
X			}
X		}
X	}
X	return (long)res;
X}
X
X/*
X * This Control Manager hack will break when the mac moves to 32-bit memory
X * management.  To be a bit safer, I only mess with param when iOnly is set.
X * Apple has only themselves to blame.
X */
Xstatic void 
XcCalcRgns(ch,param)
XControlHandle ch;
Xlong param;
X{
XBoolean iOnly;
XRect r;
X
X	iOnly = (param & 0x80000000) != 0;
X	if (iOnly) {
X	/* 
X	 * essentially ignore iOnly since the Control Manager should never call it.  But
X	 * then you never know what kinds of ugly madness lurk within the toolbox.
X	 */
X		SysBeep(3);
X		param &= 0x00ffffff;
X		SetEmptyRgn((RgnHandle)param);
X	} else {
X		/*
X		 * gets called when I free, move the control.  Make sure this is a solid
X		 * region since the CM apparently uses InvalRgn to clear us!!!
X		 */
X		OpenRgn();
X			r = (**ch).contrlRect;
X			FrameRect(&r);
X		CloseRgn((RgnHandle)param);
X	}
X}
X
Xstatic void
XcInit(vc,ch)
Xint vc;
XControlHandle ch;
X{
XHIData idh = 0;
XPIData idp;
X
X	idh = (HIData)NewHandle(sizeof(IData));
X	if (idh) {
X		HLock(idh);
X		idp = *idh;
X		SetRect(&idp->lastR,0,0,0,0);
X		idp->trackR = idp->lastR;
X		idp->titleR = idp->lastR;
X		idp->numR = idp->lastR;
X		idp->inactive = false;
X		idp->doNum = (vc & 0x01) == 0; /* default is to show number box */
X		idp->numFont = 0;
X		idp->numSize = 0;
X		idp->numBase = 0;
X		SetPt(&idp->cp,0,0);
X		SetPt(&idp->ep,0,0);
X		idp->buffer = BMNew();
X		idp->image = BMNew();
X		
X		if (!(idp->buffer && idp->image)) {
X			if (idp->buffer)
X				BMDispose(idp->buffer);
X			if (idp->image)
X				BMDispose(idp->image);
X			DisposHandle(idh);
X			idh = 0L;
X		} else {
X			HUnlock(idh);
X		}
X	}
X	(**ch).contrlData = (Handle)idh;
X	(**ch).contrlAction = 0L;
X}
X
Xstatic void
XcDispose(ch)
XControlHandle ch;
X{
XHIData idh;
X
X	idh = (HIData)(**ch).contrlData;
X	if (idh) {
X		BMDispose((**idh).image);
X		BMDispose((**idh).buffer);
X		DisposHandle(idh);
X		(**ch).contrlData = 0L;
X	}
X}
X
Xstatic long
XcDrag(ch,param)
XControlHandle ch;
Xlong param;
X{
Xlong res;
XPoint pt;
XRect oldr,newr;
X
X	if (!(**ch).contrlData) {
X		res = -1;			/* better safe than sorry */
X	} else {
X		param &= 0xffff;		/* garbage in high word again */
X		if (param != 0) {
X			int v;
X			while (StillDown()) {
X				GetMouse(&pt);
X				v = pointToValue(ch,pt);
X				if (v != (**ch).contrlValue) {
X					setNewValue(ch,v);
X				}
X			}
X			/* 
X			 * pass -1 to keep cPos from being called.  just passing 1 doesn't work,
X			 * obviously it expects some other byte to be non zero, so I use -1
X			 * to get all four
X			 */
X			res = -1;
X		} else {
X			res = 0;	/* let control manager drag us */
X		}
X	}
X	return res;
X}
X
X/*
X * since I drag the indicator when I move it, and never restore the
X * previous position, this need never be called.  In case it does get
X * called, here it is, but it does nothing.
X */
Xstatic void
XcPos(ch,param)
XControlHandle ch;
Xlong param;
X{
X}
X
X/*
X * This is clearly a hack for scroll bars to call DragGrayRgn.  Why even make 
X * this part of the CDEF interface? This will get called before I drag the
X * indicator, but I don't use it, nor do I see how to usefully do so.
X */
Xstatic void
XcThumb(ch,param)
XControlHandle ch;
Xlong param;
X{
XPCThumbRec p;
X
X	p = (PCThumbRec)param;
X	p->limitRect = (**ch).contrlRect;
X	p->slopRect = (**ch).contrlRect;
X	p->axis = noConstraint; /* from window manager */
X}
X
X/*
X * again, this should never be called.
X */
Xstatic long
XcAutoTrack(ch,param)
XControlHandle ch;
Xlong param;
X{
Xlong res = 0L;
X
X	SysBeep(3);
X	return res;
X}
X
X/*
X *************************************************************************
X */
X
Xstatic void
XredrawPict(ch)
XControlHandle ch;
X{
XGrafPtr port;
XHIData idh;
XRect b,r,r2,r3;
Xint oldFont,oldFace,oldSize;
Xint fnum,i,space,base,ht,wid,xwid;
Xint minang,maxang;
XPoint c,p;
XFontInfo finfo;
Xchar *str;
Xdouble pi80,fh,fv;
XBoolean active;
XRgnHandle oclip,ovis;
XPattern backpat;
X
X	GetPort(&port);
X
X	oclip = NewRgn();
X	ovis = NewRgn();
X	if (oclip && ovis) {
X		GetClip(oclip);
X		ClipRect(&(**ch).contrlRect);	/* in case we're off the window when drawing */
X		CopyRgn(port->visRgn,ovis);
X		RectRgn(port->visRgn,&(**ch).contrlRect);
X	} else {
X		if (ovis) DisposeRgn(ovis);
X		if (oclip) DisposeRgn(oclip);
X		ovis = oclip = 0L;
X	}
X	pi80 = PI / 180.0;
X
X	b = (**ch).contrlRect;
X	idh = (HIData)(**ch).contrlData;
X	r = b;
X	r.right -= 2;
X	r.bottom -= 2;
X	
X	str = (char *)&(**ch).contrlTitle;
X	active = (**ch).contrlHilite != 255;
X	
X	PenNormal();
X	FrameRect(&r);
X	PenSize(2,2);
X	MoveTo(r.right,r.top+2);
X	LineTo(r.right,r.bottom);
X	LineTo(r.left+2,r.bottom);
X	
X	oldFont = port->txFont;
X	oldFace = port->txFace;
X	oldSize = port->txSize;
X	
X	GetFNum(kNameFontName,&fnum);
X	TextFont(fnum);
X	TextFace((Style)bold);
X	for (i=kNameFontMax; i>=kNameFontMin; --i)
X		if (RealFont(fnum,i)) break;
X	TextSize(i);
X	
X	GetFontInfo(&finfo);
X	space = 2;
X	base = finfo.descent + finfo.leading + space;
X	ht = finfo.ascent + base + space;
X	wid = StringWidth(str);
X	
X	r2.left = r.left + 2;
X	r2.right = r.right - 2;
X	r2.bottom = r.bottom - 2;
X	r2.top = r2.bottom - ht;
X	
X	xwid = r2.right-r2.left-2;
X	if (wid > xwid) {
X		if (oclip) {
X			r3 = r2;
X			InsetRect(&r3,1,0);
X			ClipRect(&r3);
X			MoveTo(r3.left,r.bottom-base);
X			DrawString(str);
X			ClipRect(&(**ch).contrlRect);
X		}
X	} else {
X		MoveTo((r.right+r.left-wid) >> 1,r.bottom-base);
X		DrawString(str);
X	}
X	
X	if (active) {
X		InvertRect(&r2);
X	}
X	(**idh).titleR = r2;
X	
X	PenSize(1,1);
X	MoveTo(r.left,r2.top - 2);
X	LineTo(r.right,r2.top - 2);
X	
X	r3 = r;
X	r3.bottom = r2.top;
X	InsetRect(&r3,2,2);
X	if (active) {
X		StuffHex(&backpat,"\pAA55AA55AA55AA55");
X		FillRect(&r3,&backpat);
X	}
X	
X	c.h = (r.right + r.left) >> 1;
X	c.v = r2.top - 10;
X	
X	wid = c.h - (r.left+7);
X	ht = c.v - (r.top+7);
X	SetRect(&r2,c.h-wid,c.v-ht,c.h+wid,c.v+ht);
X	PenSize(3,1);
X	minang = -kNeedleMax-5;
X	maxang = kNeedleMax+5;
X	EraseArc(&r2,minang,170);
X	FrameArc(&r2,minang,170);
X	fh = wid * sin(minang * pi80);
X	fv = ht * -cos(minang * pi80);
X	p.h = c.h + fh;
X	p.v = c.v + fv;
X	MoveTo(p.h,p.v);
X	LineTo(c.h,c.v);
X	p.h = c.h - fh;		/* dial is symmetric around vertical axis */
X	LineTo(p.h,p.v);
X	PenNormal();
X	
X	InsetRect(&r2,7,7);
X	(**idh).trackR = r2;
X	SetPt(&(**idh).cp,c.h,c.v);
X	
X	for (i=-kNeedleMax; i<=kNeedleMax; i+=kTickIncrement) {
X		fh = sin(i * pi80);
X		fv = -cos(i * pi80);
X		p.h = c.h + wid * fh;
X		p.v = c.v + ht * fv;
X		MoveTo(p.h,p.v);
X		p.h = c.h + (wid-4) * fh;
X		p.v = c.v + (ht-4) * fv;
X		LineTo(p.h,p.v);
X	}
X	
X	GetFNum(kNumFontName,&fnum);
X	TextFont(fnum);
X	TextFace((Style)bold);
X	for (i=kNumFontMax; i>=kNumFontMin; --i)
X		if (RealFont(fnum,i)) break;
X	TextSize(i);
X	
X	GetFontInfo(&finfo);
X	base = finfo.descent + finfo.leading;
X	ht = finfo.ascent + base;
X	wid = finfo.widMax * 3;
X	r3.left = c.h - (wid >> 1);
X	r3.right = r3.left + wid;
X	r3.bottom = c.v - 7;
X	r3.top = r3.bottom - ht;
X	(**idh).numR = r3;
X	(**idh).numFont = fnum;
X	(**idh).numSize = i;
X	(**idh).numBase = base;
X	
X	TextFont(oldFont);
X	TextFace(oldFace);
X	TextSize(oldSize);
X	
X	if (oclip) {
X		SetClip(oclip);
X		DisposeRgn(oclip);
X	}
X	if (ovis) {
X		CopyRgn(ovis,port->visRgn);
X		DisposeRgn(ovis);
X	}
X}
X
X/*
X * calculate the needle position
X */
Xstatic void
XcalcValue(ch)
XControlHandle ch;
X{
Xdouble pi80,fv,nrange,range;
Xint v,max,min;
XHIData id;
X
X	pi80 = PI / 180.0;
X	v = (**ch).contrlValue;
X	max = (**ch).contrlMax;
X	min = (**ch).contrlMin;
X	range = max-min;
X	nrange = kNeedleMax * 2;
X	id = (HIData)(**ch).contrlData;
X	if (v < min)
X		v = min;
X	else if (v > max)
X		v = max;
X	fv = pi80 * (-kNeedleMax + ((v-min) * nrange / range));
X	(**id).ep.h = ((**id).cp.h - (**id).trackR.left) * sin(fv);
X	(**id).ep.v = ((**id).cp.v - (**id).trackR.top) * -cos(fv);
X}
X
Xstatic void
XdrawValue(ch)
XControlHandle ch;
X{
XRect r;
XStr255 str;
Xint wid,v;
XHIData idh;
XPIData idp;
XSignedByte state;
X
X	PenNormal();
X	idh = (HIData)(**ch).contrlData;
X	state = HGetState(idh);
X	HLock(idh);
X	idp = *idh;
X	
X	MoveTo(idp->cp.h,idp->cp.v);
X	Line(idp->ep.h,idp->ep.v);
X	SetRect(&r,idp->cp.h-3,idp->cp.v-3,idp->cp.h+3,idp->cp.v+3);
X	PaintOval(&r);
X	if (idp->doNum) {
X		r = idp->numR;
X		FrameRect(&r);
X		InsetRect(&r,1,1);
X		EraseRect(&r);
X		TextFont(idp->numFont);
X		TextSize(idp->numSize);
X		TextFace((Style)0);
X		v = (**ch).contrlValue;
X		NumToString(v,&str);
X		wid = StringWidth(&str);
X		MoveTo((idp->numR.right + idp->numR.left - wid) >> 1,idp->numR.bottom - idp->numBase);
X		DrawString(&str);
X	}
X	HSetState(idh,state);
X}
X
Xstatic int
XpointToValue(ch,pt)
XControlHandle ch;
XPoint pt;
X{
Xint v,min,max;
XRect r;
XHIData idh;
Xdouble val,range,nrange;
X
X	r = (**ch).contrlRect;
X	idh = (HIData)(**ch).contrlData;
X	if (PtInRect(pt,&r)) {
X		r = (**idh).trackR;
X		PtToAngle(&r,pt,&v);
X		if (v > 180)
X			v -= 360;
X		if (v > kNeedleMax)
X			v = kNeedleMax;
X		else if (v < -kNeedleMax)
X			v = -kNeedleMax;
X		min = (**ch).contrlMin;
X		max = (**ch).contrlMax;
X		nrange = kNeedleMax * 2;
X		range = max-min;
X		val = v + kNeedleMax;
X		v = min + (val * range / nrange);
X		return v;
X	} else {
X		return (**ch).contrlValue;
X	}
X}
X
Xstatic void
Xxdrawvalue(ch)
XControlHandle ch;
X{
XHIData idh;
X
X	idh = (HIData)(**ch).contrlData;
X	BMDraw((**idh).image);
X	drawValue(ch);
X}
X
X/*
X * might be memory problems here if I can't size the buffer.  I haven't bothered
X * to check.
X */
Xstatic void
XdrawRectImage(ch,r)
XControlHandle ch;
XRect *r;
X{
XHIData idh;
X
X	idh = (HIData)(**ch).contrlData;
X	BMSize((**idh).buffer,r);
X	BMInBitMapDo((**idh).buffer,xdrawvalue,ch);
X	BMDraw((**idh).buffer);
X}
X
X/*
X * calculates the new value of the needle and updates immediately
X */
Xstatic void
XsetNewValue(ch,v)
XControlHandle ch;
Xint v;
X{
XRect r,r2;
XPoint pt;
XHIData idh;
XPIData idp;
XSignedByte state;
X
X	idh = (HIData)(**ch).contrlData;
X	state = HGetState(idh);
X	HLock(idh);
X	idp = *idh;
X	
X	RUMakeDeltaRect(idp->cp,idp->ep,&r);
X	InsetRect(&r,-1,-1);
X	(**ch).contrlValue = v;
X	calcValue(ch);
X	RUMakeDeltaRect(idp->cp,idp->ep,&r2);
X	InsetRect(&r2,-1,-1);
X	UnionRect(&r2,&r,&r);
X	if (idp->doNum)
X		UnionRect(&idp->numR,&r,&r);
X	drawRectImage(ch,&r);
X	
X	HSetState(idh,state);
X}
X
X/*
X * see whether I need to update the offscreen image, either because
X * it changed size, or because it changed highlight state, and
X * redraw the image if so.
X * return true if the image was redrawn.
X */
Xstatic Boolean
XcheckAndUpdate(ch)
XControlHandle ch;
X{
XBoolean inactive,newactive,newsize,newpict;
XPoint owh,wh,d;
XRect r;
XSignedByte state;
XHIData idh;
XPIData idp;
X
X	r = (**ch).contrlRect;
X	idh = (HIData)(**ch).contrlData;
X	state = HGetState(idh);
X	HLock(idh);
X	idp = *idh;
X	
X	inactive = (**ch).contrlHilite == 255;
X	newactive = idp->inactive != inactive;
X	owh.h = r.right-r.left;
X	owh.v = r.bottom-r.top;
X	wh.h = idp->lastR.right - idp->lastR.left;
X	wh.v = idp->lastR.bottom - idp->lastR.top;
X	newsize = (owh.h != wh.h) || (owh.v != wh.v);
X	newpict = newsize || newactive;
X	if (newpict) {
X		idp->inactive = inactive;
X		idp->lastR = r;
X		BMSize(idp->image,&r);
X		BMErase(idp->image);
X		BMInBitMapDo(idp->image,redrawPict,ch);
X	} else if (!EqualRect(&r,&idp->lastR)) {
X		d.h = r.left - idp->lastR.left;
X		d.v = r.top - idp->lastR.top;
X		BMSize(idp->image,&r);
X		idp->lastR = r;
X		OffsetRect(&idp->titleR,d.h,d.v);
X		OffsetRect(&idp->numR,d.h,d.v);
X		OffsetRect(&idp->trackR,d.h,d.v);
X		AddPt(d,&idp->cp);
X	}
X	HSetState(idh,state);
X	
X	return newpict;
X}
SHAR_EOF
if test 15642 -ne "`wc -c < 'DialSRC/cdef.c'`"
then
	echo shar: error transmitting "'DialSRC/cdef.c'" '(should have been 15642 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/bitmap.h'" '(565 characters)'
if test -f 'DialSRC/bitmap.h'
then
	echo shar: will not over-write existing file "'DialSRC/bitmap.h'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/bitmap.h'
X/*
X * quick and dirty bitmap stuff
X * black and white bitmaps only
X */
X
X#ifndef _bitmap_
X#define _bitmap_
X
X#include <Quickdraw.h>
X
X#define nil ((void *)0L)
X
Xtypedef struct {
X	BitMap bm;
X	Handle data;
X} Bmap, *PBMap;
X
Xextern PBMap BMNew();
Xextern void BMDispose(PBMap p);
Xextern void BMSize(PBMap p, Rect *r);
Xextern void BMMoveTo(PBMap p, int x, int y);
Xextern void BMCopyBits(PBMap p, BitMap *pdbm, Rect *sr, Rect *dr, int m, RgnHandle c);
Xextern void BMErase(PBMap p);
Xextern void BMDraw(PBMap p);
Xextern void BMInBitMapDo(PBMap p, void (*f)(), void *d);
X
X#endif
SHAR_EOF
if test 565 -ne "`wc -c < 'DialSRC/bitmap.h'`"
then
	echo shar: error transmitting "'DialSRC/bitmap.h'" '(should have been 565 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/bitmap.c'" '(2770 characters)'
if test -f 'DialSRC/bitmap.c'
then
	echo shar: will not over-write existing file "'DialSRC/bitmap.c'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/bitmap.c'
X/*
X * resizable bitmaps
X */
X
X#include "bitmap.h"
X
XPBMap
XBMNew()
X{
XPBMap p;
X
X	if (p = (PBMap)NewPtr(sizeof(Bmap))) {
X		if (p->data = NewHandle(0)) {
X			p->bm.baseAddr = 0;
X			p->bm.rowBytes = 0;
X			SetRect(&p->bm.bounds,0,0,0,0);
X		} else {
X			DisposPtr(p);
X			p = nil;
X		}
X	}
X	return p;
X}
X
Xvoid
XBMDispose(p)
XPBMap p;
X{
X	if (p) {
X		if (p->data)
X			DisposHandle(p->data);
X		DisposPtr(p);
X	}
X}
X
X/*
X * expand bitmap to fit rect.  do not shrink bitmap unless rect has a zero width
X * or height, in which case zero it.
X * black and white bitmaps only.
X * if rect has just translated, just change the bounds record of the bitmap.
X */
Xvoid
XBMSize(p,r)
XPBMap p;
XRect *r;
X{
Xint ht,wid,oht,owid,rb;
Xlong int len;
X
X	if (p) {
X		ht = r->bottom - r->top;
X		wid = r->right - r->left;
X		oht = p->bm.bounds.bottom - p->bm.bounds.top;
X		owid = p->bm.bounds.right - p->bm.bounds.left;
X		if ((ht == oht) && (wid == owid)) {
X			p->bm.bounds = *r;
X		} else {
X			if ((ht>0) && (wid>0)) {
X				rb = ((wid+15) >> 3) & 0xfffe;
X				len = rb * ht;
X				if (len>GetHandleSize(p->data))
X					SetHandleSize(p->data,len);
X				if (!MemError()) {
X					p->bm.bounds = *r;
X					p->bm.rowBytes = rb;
X				}
X			} else {
X				SetHandleSize(p->data,0);
X				SetRect(&p->bm.bounds,0,0,0,0);
X				p->bm.rowBytes = 0;
X			}
X		}
X	}
X}
X
X/*
X * just offset the bitmap
X */
Xvoid 
XBMMoveTo(p,x,y)
XPBMap p;
Xint x,y;
X{
X	if (p) {
X		OffsetRect(&p->bm.bounds,x-p->bm.bounds.left,y-p->bm.bounds.top);
X	}
X}
X
X/*
X * basically, call copybits with this bitmap.  all copybits calls should go through
X * here since here is where we ensure that the bitmap address is that of
X * our locked data.
X */
Xvoid
XBMCopyBits(p,pdbm,sr,dr,m,c)
XPBMap p;
XBitMap *pdbm;
XRect *sr;
XRect *dr;
Xint m;
XRgnHandle c;
X{
Xchar state;
X
X	if (p) {
X		state = HGetState(p->data);
X		HLock(p->data);
X		
X		p->bm.baseAddr = *p->data;
X		CopyBits(&p->bm,pdbm,sr,dr,m,c);
X		
X		HSetState(p->data,state);
X	}
X}
X
X/*
X * clear all the data
X */
Xvoid 
XBMErase(p)
XPBMap p;
X{
Xlong int len;
Xregister int *s,*t;
X
X	if (p && (len = GetHandleSize(p->data))) {
X		for (s = (int *)(*p->data), t = s + len/sizeof(int); s != t; *s++ = 0){};
X	}
X}
X
X/*
X * copy the whole bitmap
X */
Xvoid
XBMDraw(p)
XPBMap p;
X{
XGrafPtr thePort;
X
X	if (p) {
X		GetPort(&thePort);
X		BMCopyBits(p,&thePort->portBits,&p->bm.bounds,&p->bm.bounds,srcCopy,0L);
X	}
X}
X
X/*
X * draw something in the bitmap.
X * the function gets called with the pointer d.
X */
Xvoid
XBMInBitMapDo(p,f,d)
XPBMap p;
Xvoid (*f)();
Xvoid *d;
X{
XGrafPtr temPort;
XGrafPort port;
Xchar state;
X
X	if (p) {
X		GetPort(&temPort);
X		OpenPort(&port);
X		if (!MemError()) {
X			state = HGetState(p->data);
X			HLock(p->data);
X			p->bm.baseAddr = *p->data;
X			SetPortBits(&p->bm);
X			
X			(*f)(d);
X			
X			HSetState(p->data,state);
X		}
X		ClosePort(&port);
X		SetPort(temPort);
X	}
X}
SHAR_EOF
if test 2770 -ne "`wc -c < 'DialSRC/bitmap.c'`"
then
	echo shar: error transmitting "'DialSRC/bitmap.c'" '(should have been 2770 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/rectutils.h'" '(128 characters)'
if test -f 'DialSRC/rectutils.h'
then
	echo shar: will not over-write existing file "'DialSRC/rectutils.h'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/rectutils.h'
X/*
X * header for rect utils
X */
Xvoid RUMakeRect(Point p1, Point p2, Rect *r);
Xvoid RUMakeDeltaRect(Point p1, Point d, Rect *r);
SHAR_EOF
if test 128 -ne "`wc -c < 'DialSRC/rectutils.h'`"
then
	echo shar: error transmitting "'DialSRC/rectutils.h'" '(should have been 128 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/rectutils.c'" '(716 characters)'
if test -f 'DialSRC/rectutils.c'
then
	echo shar: will not over-write existing file "'DialSRC/rectutils.c'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/rectutils.c'
X/*
X * rectangle utilities
X */
X 
X#include "rectutils.h"
X
X/*
X * make a rectangle from the two points.  If the coordinates would
X * produce an invalid rectangle, switch them so that the rect is
X * always valid.
X */
Xvoid
XRUMakeRect(p1,p2,r)
XPoint p1,p2;
XRect *r;
X{
X	if (p1.h < p2.h) {
X		r->left = p1.h;
X		r->right = p2.h;
X	} else {
X		r->left = p2.h;
X		r->right = p1.h;
X	}
X	if (p1.v < p2.v) {
X		r->top = p1.v;
X		r->bottom = p2.v;
X	} else {
X		r->top = p2.v;
X		r->bottom = p1.v;
X	}
X}
X
X/*
X * like makerect except takes a width/height value in the second
X * point rather than an actual point.
X */
Xvoid
XRUMakeDeltaRect(p1,d,r)
XPoint p1,d;
XRect *r;
X{
XPoint p2;
X
X	p2.h = p1.h + d.h;
X	p2.v = p1.v + d.v;
X	RUMakeRect(p1,p2,r);
X}
X
SHAR_EOF
if test 716 -ne "`wc -c < 'DialSRC/rectutils.c'`"
then
	echo shar: error transmitting "'DialSRC/rectutils.c'" '(should have been 716 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/sincos.h'" '(138 characters)'
if test -f 'DialSRC/sincos.h'
then
	echo shar: will not over-write existing file "'DialSRC/sincos.h'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/sincos.h'
X/*
X * header to replace math.h
X */
X
X#include "sane.h"
X
X#define	PI		(3.14159265358979323846)
X
Xdouble	sin(double x);
Xdouble	cos(double x);
X
SHAR_EOF
if test 138 -ne "`wc -c < 'DialSRC/sincos.h'`"
then
	echo shar: error transmitting "'DialSRC/sincos.h'" '(should have been 138 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/sincos.c'" '(260 characters)'
if test -f 'DialSRC/sincos.c'
then
	echo shar: will not over-write existing file "'DialSRC/sincos.c'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/sincos.c'
X/*
X * sine and cosine from math.c
X */
X
X/*
X *  sin - circular sine
X *
X */
X
X#include "sincos.h"
X
Xdouble sin(x)
Xdouble x;
X{
X	elems68k(&x, FOSINX);
X	return(x);
X}
X
X/*
X *  cos - circular cosine
X *
X */
X
Xdouble cos(x)
Xdouble x;
X{	
X	elems68k(&x, FOCOSX);
X	return(x);
X}
SHAR_EOF
if test 260 -ne "`wc -c < 'DialSRC/sincos.c'`"
then
	echo shar: error transmitting "'DialSRC/sincos.c'" '(should have been 260 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'DialSRC/main.c'" '(318 characters)'
if test -f 'DialSRC/main.c'
then
	echo shar: will not over-write existing file "'DialSRC/main.c'"
else
sed 's/^X//' << \SHAR_EOF > 'DialSRC/main.c'
X#include "::utilities:cdef.h"
X#include <SetUpA4.h>
X
Xpascal long
Xmain(varCode, theControl, message, param)
Xint varCode;
XControlHandle theControl;
Xint message;
Xlong int param;
X{
Xlong int result = 0;
X
X	RememberA0();
X	SetUpA4();
X	
X	result = MyControl(varCode,theControl,message,param);
X	
X	RestoreA4();
X	
X	return result;
X}
SHAR_EOF
if test 318 -ne "`wc -c < 'DialSRC/main.c'`"
then
	echo shar: error transmitting "'DialSRC/main.c'" '(should have been 318 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
---