[comp.sys.mac.programmer] Journaling

time@ice.com (Tim Endres) (06/26/91)

In article <1991Jun26.162909.22605@newcastle.ac.uk>, S.W.L.Yip@newcastle.ac.uk (S.W.Yip) writes:
> I am stuck, desperate ... please HELP !
> 
> I am trying to use the "Journaling Mechanism" ,

Here's some code... BE WARNED IT IS OLD AND PROBABLY BUGGY!!!!!!!

tim.


# include <types.h>
# include <osutils.h>				/* for devices.h */
# include <memory.h>				/* for THz */
# include <devices.h>				/* for DCtlPtr */
# include <events.h>				/* for EventRecord */
# include <quickdraw.h> 			/* for Rect */
# include <fonts.h> 				/* for monaco */
# include <windows.h>				/* for WindowPtr */
# include <menus.h> 				/* for MenuHandle */
# include <files.h> 				/* for GetVolInfo() */
# include <errors.h> 				/* for GetVolInfo() */


#define DEBUG 1
pascal void DebugStr(aStr)
	char *aStr;
	extern 0xABFF;

#define P_String 1
#define C_String 0

# define noErr	0			/* in lieu of <errors.h> */
#define  jcTickCount		0
#define  jcGetMouse		1
#define  jcButton			2
#define  jcGetKeys		3
#define  jcEvent			4

#define	jPlayCtl			16
#define	jRecordCtl		17

/*extern int JournalFlag : 0x8DE;*/
/*extern int JournalRef : 0x8E8;*/
#define JournalFlag (* (short *) 0x8DE)
#define JournalRef (* (short *) 0x8E8)


#define jRecordItem 1
#define jOffItem 3
#define jPlayItem 5

# define OWNEDRSRCID(id)	(0xC000 | (((-(id)) - 1) << 5)) /* Computes owned resource id */

/*
 * String constant indexes for STR# resource
 */
# define	EVENTSTR 1
# define	DEBUG_RECORD 2
# define	DEBUG_ENABLED 3
# define	DEBUG_RECORD 4
# define	DEBUG_PLAY 5
# define	DEBUG_UPDATE 6
# define	COUNTSTR 7
# define	FILE_NAME 8
# define	WRITE_TICK 9
# define	WRITE_MOUSE 10
# define	WRITE_BUTTON 11
# define	WRITE_EVENT 12
# define	WRITE_KEYS 13
# define	FILE_CLOSE_ERR 14
# define	FILE_OPEN_ERR 15
# define	FILE_WRITE_ERR 16
# define	WHAT_STR 17
# define	MESSAGE_STR 18
# define	WHERE_STR 19
# define	MODIFIERS_STR 20
# define	TRUE_STR 21
# define	FALSE_STR 22
# define	MENU_TITLE 23
# define	MENU_STR 24
# define PLAY_DEBUG_STR 25

# define	NUMBER_TICK 0
# define	NUMBER_MOUSE 1
# define	NUMBER_BUTTON 2
# define	NUMBER_KEYS 3
# define	NUMBER_EVENT 4

/* This structure type holdstthe global variables used by this desk accessory */

typedef struct {
	short drvrref; 		/* Driver's reference number */
	short rsrcID; 			/* Computed rsrc id of STR# and WIND resources */
	int	lastevent;		/* Last journaled event number. */
	int	count;			/* Number of events recorded */
	char	*eventptr;		/* Pointer to event storage */
	short	refnum;			/* debug file's refnum. */
	short	vrefnum;			/* debug file's volume refnum */
	MenuHandle accmenu;	/* The Desk Accessory's menu. */
	short	menuid;			/* The Desk Accessory's menu id. */
	char	strBuf[256];	/* Buffer to read strings into */
	char	inline[256];	/* Buffer to read events into */
	int	index;			/* index into inline for getting values */
	int	playeof;			/* indicates eof on input file */
	} Globals;

static char *text();

pascal short
DRVROpen(ctlPB, dCtl)
CntrlParam *ctlPB;
DCtlPtr dCtl;
{
GrafPtr savePort;
WindowPeek myWindow;
long heapGrow;
Globals *globals;
char *strptr;
	/*
	 * If the windowPtr is non-nil, we already have a window open.
	 * This desk accessory ignores multiple opens.
	 */
	if (dCtl->dCtlWindow != nil) return(noErr);

	GetPort(&savePort);
	
	/*
	 * Get a handle to some storage that will hold our pseudo-global
	 * variables.  Save the handle in a location accessible by
	 * all the driver routines.
	 */
	dCtl->dCtlStorage = NewHandle(sizeof(Globals));
	/*
	 * Compute the resource id of the owned 'STR#' resource that
	 * contains all of the programs text strings.  The id is saved
	 * in one place that can be accessed by all the driver routines.
	 */
	HLock(dCtl->dCtlStorage);
	globals = (Globals *) *dCtl->dCtlStorage;

	globals->rsrcID = OWNEDRSRCID(dCtl->dCtlRefNum);
	
	/*
	 * wStorage = nil (allocate on the heap)
	 * visible = false, behind = -1, goAway = true, refCon = 0
	 */
	myWindow = GetNewWindow(globals->rsrcID, nil, (WindowPtr) -1);
	/*
	 * Set windowKind to the DA refNum, which is negative.
	 */
	myWindow->windowKind = dCtl->dCtlRefNum;
	/*
	 * Store the windowPtr in the Device Control Entry
	 */
	dCtl->dCtlWindow = myWindow;
	SetPort(savePort);
	
	dCtl->dCtlMenu = dCtl->dCtlRefNum;
	strptr = text(MENU_TITLE, globals, C_String);
	globals->accmenu = NewMenu((short) dCtl->dCtlRefNum, strptr);
	strptr = text(MENU_STR, globals, C_String);
	AppendMenu(globals->accmenu, strptr);
	InsertMenu(globals->accmenu, (short)0);
	DrawMenuBar();
	
	globals->count = 0;
	globals->lastevent = 0;
	globals->drvrref = dCtl->dCtlRefNum;

	HUnlock(dCtl->dCtlStorage);
	
	return(noErr);
	}

pascal short
DRVRPrime(ctlPB, dCtl)
CntrlParam *ctlPB;
DCtlPtr dCtl;
{
	return(noErr);			/* Not used in this desk accessory */
	}

pascal short
DRVRStatus(ctlPB, dCtl)
CntrlParam *ctlPB;
DCtlPtr dCtl;
{
	return(noErr);			/* Not used in this desk accessory */
	}

pascal short
DRVRControl(ctlPB, dCtl)
CntrlParam *ctlPB;
DCtlPtr dCtl;
{
GrafPtr saveport;
Globals *globals;
	extern void doCtlEvent(), doPeriodic(), drawWindow();
	/*
	 * The current grafPort is saved & restored bytthe Desk Manager
	 */
	HLock(dCtl->dCtlStorage);	/* Lock handle since it will be dereferenced */
	globals = (Globals *) *dCtl->dCtlStorage;
	switch (ctlPB->csCode) {
		default:
			break;
		case 64:				/* accEvent */
			doCtlEvent(*((EventRecord **) &ctlPB->csParam[0]), globals);
			break;
		case 67:				/* accMenu */
			switch (ctlPB->csParam[1]) {
				casejjRecordItem: RecordEnable(globals); break;
				case jPlayItem: PlayEnable(globals); break;
				case jOffItem:
					DisAble(globals);
					SetPort(dCtl->dCtlWindow);
					drawWindow(dCtl->dCtlWindow, globals);
					break;
				}
			HiliteMenu(0);
			break;
		case 65:				/* periodicEvent */
			/* doPeriodic(dCtl); */
			break;
		case jRecordCtl:	/* Recording mode */
#if DEBUG > 3
			DebugStr(text(DEBUG_RECORD, globals, P_String));
#endif
			/* The journalled event is at csParam+4 or csParam[2], since int[] */
			globals->lastevent = ctlPB->csParam[2];
			globals->eventptr = * ((char **) &ctlPB->csParam[0]);
			globals->count++;
			/* if (CmdPeriod()) DisAble(ctlPB, dCtl); */
			WriteRecord(globals);
			/* save event to journal */
			/* GetPort(&saveport); */
			/* SetPort(dCtl->dCtlWindow); */
			/* drawWindow(dCtl->dCtlWindow, globals); */
			/* SetPort(saveport); */
			break;
		case jPlayCtl:	/* PlayBack mode */
#if DEBUG > 3
			DebugStr(text(DEBUG_PLAY, globals, P_String));
#endif
			globals->eventptr = * ((char **) &ctlPB->csParam[0]);
			globals->count++;
			/* if (CmdPeriod()) DisAble(ctlPB, dCtl); */
			if (globals->lastevent = ctlPB->csParam[2]) PlayRecord(globals);
			if (globals->playeof) DisAble(globals);
			break;
		}
	HUnlock(dCtl->dCtlStorage);
	return(0);
	}

pascal short
DRVRClose(ctlPB, dCtl)
char *ctlPB;
DCtlPtr dCtl;
{						/* Save & Restore current grafPort? */
WindowPtr window;
Globals *globals;
	HLock(dCtl->dCtlStorage);
	globals = (Globals *) *dCtl->dCtlStorage;
	DeleteMenu(dCtl->dCtlMenu);
	DrawMenuBar();
	DisposeMenu(globals->accmenu);
	HUnlock(dCtl->dCtlStorage);
	window = (WindowPtr) dCtl->dCtlWindow;
	if (window != NULL) {
		dCtl->dCtlWindow = NULL;
		DisposeWindow(window);
		}
	return 0;
	}

PlayRecord(globals)
Globals *globas;
{
#if DEBUG > 3
	DebugStr(text(PLAY_DEBUG_STR, globals, P_String));
	DebugNum(globals->lastevent);
#endif
	SysBeep(1);
	switch (globals->lastevent) {
		case jcTickCount: PlayTick(globals); break;
		case jcGetMouse: PlayMouse(globals); break;
		case jcButton: PlayButton(globals); break;
		case jcGetKeys: PlayKeys(globals); break;
		case jcEvent: PlayEvent(globals); break;
		}
	ReadLine(globals);
	if (globals->playeof)
		globals->lastevent = 0;
		else globals->lastevent = GetNumber(globals);
	}

PlayTick(globals)
Globals *globals;
{
	*((long *)globals->eventptr) = GetNumber(globals);
	}

PlayMouse(globals)
Globals *globals;
{
#if DEBUG > 0
	DebugPtr(globals->eventptr);
#endif
	((Point *)globals->eventptr)->h = GetNumber(globals);
	((Point *)globals->eventptr)->v = GetNumber(globals);
	}

PlayKeys(globals)
Globals *globals;
{
	((long *)globals->eventptr)[0] = GetNumber(globals);
	((long *)globals->eventptr)[1] = GetNumber(globals);
	((long *)globals->eventptr)[2] = GetNumber(globals);
	((long *)globals->eventptr)[3] = GetNumber(globals);
	}

PlayButton(globals)
Globals *globals;
{
	*((Boolean *)globals->eventptr) = (Boolean) GetNumber(globals);
	}

PlayEvent(globals)
Globals *globals;
{
#if DEBUG > 0
	DebugPtr(globals->eventptr);
#endif
	((EventRecord *)globals->eventptr)->what = GetNumber(globals);
	((EventRecord *)globals->eventptr)->message = GetNumber(globals);
	((EventRecord *)globals->eventptr)->where.h = GetNumber(globals);
	((EventRecord *)globals->eventptr)->where.v = GetNumber(globals);
	((EventRecord *)globals->eventptr)->modifiers = GetNumber(globals);
	}

GetNumber(globals)
Globals *globals;
{
long mynum;
int i;
char mystr[50];
	for(i=globals->index;
		 globals->inline[i] && (globals->inline[i] != ' ') && (i < 256);
		 i++) mystr[i] = globals->inline[i];
	mystr[i++] = 0;
	StringToNum(mystr, &mynum);
	globals->index = i;
	return mynum;
	}

ReadLine(globals)
Globals *globals;
{
long count;
short myerr, i, tmp;
	i = 0;
	do {
		count = 1;
		myerr = FSRead(globals->refnum, &count, &globals->inline[i]);
		if (globals->inline[i] == 0x0D) 
			{ myerr = 0x0D; globals->inline[i] = 0; }
			else i++;
		} while (myerr == noErr);
	if (myerr == eofErr) globals->playeof = true;
	globals->index = 0;
#if DEBUG > 3
	tmp = globals->inline[0]; globals->inline[0] = i;
	DebugStr(globals->inline); globals->inline[0] = tmp;
#endif
	}

#define jOffFlag 0
#define jPlayFlag -1
#define jRecordFlag 1

RecordEnable(globals)
Globals *globals;
{
	if (JournalFlag != jOffFlag) { SysBeep(60); return; }
	OpenFile(globals);
	SetEOF(globals->refnum, (long) 0);
	JournalRef = globals->drvrref;
	JournalFlag = jRecordFlag;
	globals->count = 0;
	}

PlayEnable(globals)
Globals *globals;
{
	if (JournalFlag != jOffFlag) { SysBeep(60); return; }
	globals->playeof = false;
	OpenFile(globals);
	ReadLine(globals); /* Prime the inline */
	globals->lastevent = GetNumber(globals);
#if DEBUG > 3
	DebugNum(globals->lastevent);
#endif
	JournalRef = globals->drvrref;
	JournalFlag = jPlayFlag;
	globals->count = 0;
	}

DisAble(globals)
Globals *globals;
{
	if (JournalFlag == jOffFlag) { SysBeep(60); return; }
	JournalFlag = jOffFlag;
	CloseFile(globals);
	}

WriteRecord(globals)
Globals *globals;
{
	switch (globals->lastevent) {
		case jcTickCount: WriteTick(globals); break;
		case jcGetMouse: WriteMouse(globals); break;
		case jcButton: WriteButton(globals); break;
		case jcGetKeys: WriteKeys(globals); break;
		case jcEvent: WriteEvent(globals); break;
		}
	}

WriteTick(globals)
Globals *globals;
{
char *title;
long count;
char mystr[50];
short myerr;
	NumToString(NUMBER_TICK, mystr);
	count = strlen(mystr); mystr[count++] = ' ';
	NumToString(*((long *)globals->eventptr), &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = 0x0D;
	myerr = FSWrite(globals->refnum, &count, mystr);
#if DEBUG > 0
	if (myerr != noErr)
		DebugStr(text(FILE_WRITE_ERR, globals, P_String));
#endif
	}
	
WriteEvent(globals)
Globals *globals;
{
char *title;
long count;
char mystr[128];
EventRecord *myevent;
short myerr;
	myevent = (EventRecord *) globals->eventptr;
	if (myevent->what == nullEvent) return;
	NumToString(NUMBER_EVENT, mystr);
	count = strlen(mystr); mystr[count++] = ' ';
	NumToString(myevent->what, &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = ' ';
	NumToString(myevent->message, &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = ' ';
	NumToString(myevent->where.h, &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = ' ';
	NumToString(myevent->where.v, &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = ' '; mystr[count] = 0;
	NumToString(myevent->modifiers, &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = 0x0D;
	myerr = FSWrite(globals->refnum, &count, mystr);
#if DEBUG > 0
	if (myerr != noErr)
		DebugStr(text(FILE_WRITE_ERR, globals, P_String));
#endif
	}

WriteMouse(globals)
Globals *globals;
{
char *title;
long count;
char mystr[128];
Point *mypt;
short myerr;
	NumToString(NUMBER_MOUSE, mystr);
	count = strlen(mystr); mystr[count++] = ' ';
	mypt = (Point *) globals->eventptr;
	NumToString(mypt->h, &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = ' ';
	NumToString(mypt->v, &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = 0x0D;
	myerr = FSWrite(globals->refnum, &count, mystr);
#if DEBUG > 0
	if (myerr != noErr)
		DebugStr(text(FILE_WRITE_ERR, globals, P_String));
#endif
	}

WriteButton(globals)
Globals *globals;
{
char mystr[128];
long count;
Boolean *mybool;
short myerr;
	NumToString(NUMBER_BUTTON, mystr);
	count = strlen(mystr); mystr[count++] = ' ';
	mybool = (Boolean *) globals->eventptr;
	NumToString((int) *mybool, &mystr[count]);	/* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = 0x0D;
	myerr = FSWrite(globals->refnum, &count, mystr);
#if DEBUG > 0
	if (myerr != noErr)
		DebugStr(text(FILE_WRITE_ERR, globals, P_String));
#endif
	}

WriteKeys(globals)
Globals *globals;
{
char *title;
long count;
char mystr[128];
long *mykeys;
short myerr;
	NumToString(NUMBER_KEYS, mystr);
	count = strlen(mystr); mystr[count++] = ' ';
	mykeys = (long *) globals->eventptr;
	NumToString(mykeys[0], &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = ' ';
	NumToString(mykeys[1], &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = ' ';
	NumToString(mykeys[2], &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = ' ';
	NumToString(mykeys[3], &mystr[count]); /* Returns C string */
	count += strlen(&mystr[count]); mystr[count++] = 0x0D;
	myerr = FSWrite(globals->refnum, &count, mystr);
#if DEBUG > 0
	if (myerr != noErr)
		DebugStr(text(FILE_WRITE_ERR, globals, P_String));
#endif
	}

/*******
WriteReturn(globals)
Globals *globals;
{
long count;
char mystr[50];
	count = 1; mystr[0] = 0x0D;
	FSWrite(globals->refnum, &count, mystr);
	}
***********/

OpenFile(globals)
Globals *globals;
{
short myerr;
char *filename, volname[30];
	filename = text(FILE_NAME, globals, C_String);
	myerr = FSOpen(filename, 0, &globals->refnum);
	if (myerr != noErr) {
		DebugStr(text(FILE_OPEN_ERR, globals, P_String));
		globals->refnum = 0;
		}
	GetVol(volname, &globals->vrefnum);
#if DEBUG > 3
	DebugStr(text(FILE_NAME, globals, P_String));
#endif
#if DEBUG > 3
	DebugNum(globals->refnum);
	DebugNum(globals->vrefnum);
#endif
	}

CloseFile(globals)
Globals *globals;
{
short myerr;
	myerr = FSClose(globals->refnum);
	if (myerr != noErr) {
		DebugStr(text(FILE_CLOSE_ERR, globals, P_String));
		}
	FlushVol(NULL, globals->vrefnum);
	}

static int
strlen(astr)
register char *astr;
{
register int i;
	for (i=0; astr[i]; i++);
	return i;
	}

static void
doCtlEvent(theEvent, globals)
register EventRecord *theEvent;
Globals *globals;	/* Pointer to globals passed along the procedure call chain */
{
	extern void drawWindow();
	register WindowPtr myWindow;

	switch (theEvent->what) {
		default:
			break;
		case updateEvt:
			myWindow = (WindowPtr) theEvent->message;
			SetPort(myWindow);
			BeginUpdate(myWindow);
			drawWindow(myWindow, globals);
			EndUpdate(myWindow);
			break;
		}

	return;
	}

/*
 * Display the contents of the window.
 * The current port is assumed to be set to the window.
 */
static void
drawWindow(window, globals)
WindowPtr window;
Globals *globals;	/* Pointer to globals passed along the procedure call chain */
{
Rect myrect;
#if DEBUG > 3
	DebugStr(text(DEBUG_UPDATE, globals, P_String));
#endif
	if (window == nil) return;		/* "can't happen" */
	
	myrect = window->portRect;
	
	PenNormal();
	EraseRect(&myrect);
/*	InsetRect(&myrect, (short)5, (short)5);*/
/*	PaintRect(&myrect);*/
	
	TextMode(srcCopy);
	TextFont(monaco);
	TextSize(9);

	TextFace(bold);
/****
	MoveTo(10, 15);
	DrawString(text(EVENTSTR, globals, C_String));
	printNum(globals->lastevent);
	*****/
	MoveTo(10, 15);
	DrawString(text(COUNTSTR, globals, C_String));
	printNum((int) globals->count);

	return;
	}

static
printNum(num)
int num;
{
	char numStr[32];

	TextFace(normal);
	NumToString(num, numStr); /* Returns C string */
	DrawString(numStr);
	TextFace(bold);

	return;
	}

#if DEBUG > 0

static
DebugNum(num)
int num;
{
char numStr[30];
	NumToString(num, numStr); /* Returns C String */
	c2pstr(numStr); DebugStr(numStr);
	return;
	}

static
DebugPtr(ptr)
char *ptr;
{
char numStr[30];
	if (! Option()) return;
	NumToString((long)ptr, numStr); /* Returns C String */
	c2pstr(numStr); DebugStr(numStr);
	return;
	}
	
#endif

strcat(str1, str2)
register char *str1, *str2;
{
	while (*str1) str1++;
	while (*str2) *str1++ = *str2++;
	*str1 = 0;
	}

c2pstr(str)
register char *str;
{
register int i;
int length;
	for (i=0; str[i]; i++);
	for (length=i; i; i--) str[i] = str[i-1];
	str[0] = (unsigned char) length;
	}

static char *
text(index, globals, pstrflag)
int index;
Globals *globals;	/* Pointer to globals passed along the procedure call chain */
int pstrflag;	/* T - Pascal string. C - C String. */
{
	GetIndString(globals->strBuf, globals->rsrcID, index); /* Returns C String */
	if (pstrflag) c2pstr(globals->strBuf); 
	return(globals->strBuf);
	}

#define PeriodDown (*((char *)0x179) == 0x80)
#define AppleDown (*((char *)0x17A) == 0x80)
#define OptionDown (*((char *)0x17B) == 0x04)

CmdPeriod(globals)
Globals *globals;
{
	if (AppleDown && PeriodDown)
		return true;
		else return false;
	}

Option()
{
	return OptionDown;
	}

-------------------------------------------------------------
Tim Endres                |  time@ice.com
ICE Engineering           |  uupsi!ice.com!time
8840 Main Street          |  Voice            FAX
Whitmore Lake MI. 48189   |  (313) 449 8288   (313) 449 9208
-------- USENET: A slow moving self parody.....

S.W.L.Yip@newcastle.ac.uk (S.W.Yip) (06/26/91)

I am stuck, desperate ... please HELP !

I am trying to use the "Journaling Mechanism" ,
as described on page I-261 in Vol.1 of Inside Macintosh.
I need to record user inputs (keyboard, mouse inputs) 
onto a journal file and then play it back as a kind of
automation.  I have tried to set JournalFlag and JournalRef
with suitable values, with no effect. 

I have written a DeskAccessory /driver for this, using
ThinkPascal.(I don't have MWP or assembler.) I have to trust
the {$J+} compiler directive of ThinkPascal to access external
globals (i.e. JournalFlag, JournalRef). I have all volumes
of Inside Macintosh and have read chapters about DA, drivers,
low memory global variables. My DA only seems to receive Control
calls from the DA manager, but NOT the event manager ! 

How do I know the event manager knows the existence of my
DA/driver? The only link seems to be the JournalFlag global
variable. I have now found out the location for JournalFlag
is $8DE, and tried to change its value to 16 (playback) or
17 (record) using the in-line assembler within a C program, 
but failed (its value remains as 0 after move.w #17, 0x8DE).

Any advice will be appreciated!
Stephen Yip, University of Durham, England, Uk.  
S.W.L.Yip@durham.ac.uk

wombat@claris.com (Scott Lindsey) (06/28/91)

In article <1991Jun26.162909.22605@newcastle.ac.uk> S.W.L.Yip@newcastle.ac.uk
(S.W.Yip) writes:

>I am stuck, desperate ... please HELP !

>How do I know the event manager knows the existence of my
>DA/driver? The only link seems to be the JournalFlag global
>variable. I have now found out the location for JournalFlag
>is $8DE, and tried to change its value to 16 (playback) or
>17 (record) using the in-line assembler within a C program, 
>but failed (its value remains as 0 after move.w #17, 0x8DE).

Here's an exchange I had with Apple DTS:

-I haven't found any documentation relating journaling and MultiFinder.

-Here's the behavior I've observed:  I open my driver and begin journaling. 
-During the process of a GetNextEvent (or WaitNextEvent), a background
-program (e.g., FileMaker Pro) swaps in, having returned from
-WaitNextEvent.  Wanting to know whether or not it's time to flush its
-internal disk cache, it calls TickCount.  Either WaitNextEvent or
-TickCount (probably the latter) CLEARS the journaling flag and doesn't
-restore it.  Is this expected behavior?  While I don't expect to receive
-journaling information for other applications, I do expect that the state
-of the journaling flag to be restored by any who change it.

To which DTS responded:
-Scott,
-This is one of the things that the MultiFInder hack missed.  What you're
-doing is the correct way to work around the problem.  There are little
-gems like this scattered about in MultiFinder, since MF is basically a
-large patch on top of the system and the Finder.  And we try and
-document them when we can (Programmers Guide to MF and the tech notes) but
-some of them only come up when a developer is using something, as in this
-case, and we have to look at the source for the specific example.

So, you may have to keep punching your control value into JournalFlag.
JournalRef is 0x8E8, and that's how you tell the event mgr about your
driver: you put the driver's refnum there.  Note that you don't want to put
16 (specifically) into JournalFlag.  According to p. I-261, "You control
whether the journaling mechanism is playing or recording by setting the
global variable JournalFlag to a negative or positive value [respectively]
... If you set the value of JournalFlag to 0, the Control call won't be
made at all.  16 and 17 are jPlayCtl and jRecordCtl, values which can be
passed in csCode in the Control call to your DA/driver.

-- Scott Lindsey <wombat@claris.com>