home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
develop, the CD; issue 1
/
Apple_Develop_1989.bin
/
Compatibility
/
compatibility.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-10-16
|
4KB
|
133 lines
#include <Events.h>
#include <OSEvents.h>
#include <OSUtils.h>
#include <Dialogs.h>
#include <Packages.h>
#include <Retrace.h>
#include <Traps.h>
#define INTERVAL 6
#define rInfoDialog 140
#define rStatTextItem 2
/*
* These are globals which will be referenced from our VBL Task
*/
long gCounter; /* Counter incremented each time our VBL gets called */
/*
* Define a struct to keep track of what we need. Put theVBLTask into the
* struct first because its address will be passed to our VBL task in A0
*/
struct VBLRec {
VBLTask theVBLTask; /* the VBL task itself */
long VBLA5; /* saved CurrentA5 where we can find it */
};
typedef struct VBLRec VBLRec, *VBLRecPtr;
/*
* GetVBLRec returns the address of the VBLRec associated with our VBL task.
* This works because on entry into the VBL task, A0 points to the theVBLTask
* field in the VBLRec record, which is the first field in the record and
* is the address we return. Note that this method works whether the VBLRec
* is allocated globally, in the heap (as long as the record is locked in
* memory) or if it is allocated on the stack as is the case in this example.
* In the latter case this is OK as long as the procedure which installed the
* task does not exit while the task is running. This trick allows us to get
* to the saved A5, but it could also be used to get to anything we wanted to
* store in the record.
*/
VBLRecPtr GetVBLRec ()
= 0x2008; /* MOVE.L A0,D0 */
/*
* DoVBL is called only by StartVBL ()
*/
void DoVBL (VRP)
VBLRecPtr VRP;
{
gCounter++; /* Show we can set a global */
VRP->theVBLTask.vblCount = INTERVAL; /* Set ourselves to run again */
}
/*
* This is the actual VBL task code. It uses GetVBLRec to get our VBL record
* and properly set up A5. Having done that, it calls DoVBL to increment a
* global counter and sets itself to run again. Because of the vagaries of
* MPW C 3.0 optimization, it calls a separate routine to actually access
* global variables. See Tech Note #208 - "Setting and Restoring A5" for the
* reasons for this, as well as for a description of SetA5.
*/
void StartVBL ()
{
long curA5;
VBLRecPtr recPtr;
recPtr = GetVBLRec (); /* First get our record */
curA5 = SetA5 (recPtr->VBLA5);/* Get the saved A5 */
/* Now we can access globals */
DoVBL (recPtr); /* Call another routine to do actual work */
(void) SetA5 (curA5); /* Restore old A5 */
}
/*
* InstallVBL creates a dialog just to demonstrate that the global variable
* is being updated by the VBL Task. Before installing the VBL, we store
* our A5 in the actual VBL Task record, using SetCurrentA5 described in
* Tech Note #208. We'll run the VBL, showing the counter being incremented,
* until the mouse button is clicked. Then we remove the VBL Task, close the
* dialog, and remove the mouse down events to prevent the application from
* being inadvertently switched by MultiFinder.
*/
void InstallCVBL ()
{
VBLRec theVBLRec;
DialogPtr infoDPtr;
DialogRecord infoDStorage;
Str255 numStr;
OSErr theErr;
Handle theItemHandle;
short theItemType;
long lCounter;
Rect theRect;
gCounter = 0; /* Initialize our global counter */
infoDPtr = GetNewDialog (rInfoDialog, (Ptr) &infoDStorage, (WindowPtr) -1);
DrawDialog (infoDPtr);
GetDItem (infoDPtr, rStatTextItem, &theItemType, &theItemHandle,
&theRect);
/*
* Store the current value of A5 in the MyA5 field. For more
* information on SetCurrentA5, see Tech Note #208 - "Setting and
* Restoring A5".
*/
theVBLRec.VBLA5 = SetCurrentA5 ();
/* Set the address of our routine */
theVBLRec.theVBLTask.vblAddr = (VBLProcPtr) StartVBL;
theVBLRec.theVBLTask.vblCount = INTERVAL; /* Frequency of task, in ticks */
theVBLRec.theVBLTask.qType = vType; /* qElement is a VBL task */
theVBLRec.theVBLTask.vblPhase = 0;
/* Now install the VBL task */
theErr = VInstall ((QElemPtr)&theVBLRec.theVBLTask);
if (!theErr) {
lCounter = -1; /* Force the initial update */
do {
if (lCounter != gCounter) {
NumToString (gCounter, numStr);
SetIText (theItemHandle, numStr);
lCounter = gCounter;
}
} while (!Button ());
theErr = VRemove ((QElemPtr)&theVBLRec.theVBLTask); /* Remove it when done */
}
/* Finish up */
CloseDialog (infoDPtr); /* Get rid of our dialog */
FlushEvents (mDownMask, 0); /* Flush all mouse down events */
}