[comp.sys.mac.programmer] Writing INIT resources. Part 1, the INIT source

jmunkki@santra.UUCP (Juri Munkki) (04/22/88)

/*
		SampleInit.c
		April 22, 1988
		Written by Juri Munkki

		This source code is in the public domain.
		The author makes no guarantees.

Instructions

	I wrote this INIT as a sample to one of my clients.
	They wished to monitor what the user does and generate
	statistics on frequently used actions.
	
	This INIT does nothing useful. It modifies GetNextEvent
	so that instead of returning autoKey events with the
	spacebar, the # character is returned. It should be
	quite a surprise to people who are used to using spaces
	instead of tabs. :-) The INIT has no effect on DAs.

	You should have Lightspeed C to use this INIT. The
	structure of an INIT depends highly on the development
	system being used. Lightspeed C places global data
	storage after the program code. This means that you
	can't have more than 32K of code AND static variables.
		
	The INIT resource itself should have the "System Heap"
	flag set or it will bomb sooner or later. (usually soon)

	Please remember to put a 'sysz' resource into your
	INIT, if you're going to need a lot of space. Also
	remember that any dynamic storage that should live
	through launches should be in the system heap.
	
	I hope this helps those who are desperately trying to
	patch the system.
	
		Juri Munkki
		jmunkki@santra.hut.fi
		jmunkki@fingate.bitnet
*/

#include <MacTypes.h>
#include <OSUtil.h>
#include <EventMgr.h>

#define  NextEventNum	0x970

		long	OldNextEvent;
		long	ticker;
	EventRecord	*theEvent;

void	DoEvent(doIt)
int			doIt;
{
	if(doIt)
		if(theEvent->what==autoKey)
			if((theEvent->message & 0xFF) == ' ')
				theEvent->message+='#'-' ';
}

void		NewGetEvent()
{
asm	{
	move.l	(sp)+,A0	/*	Return address			*/
	move.l	(sp)+,A1	/*	Pointer to an EventRecord	*/
	move.w	(sp)+,D0	/*	EventMask			*/

	move.l	A0,-(sp)	/*	Push return address for RTS	*/
	move.l	A4,-(sp)	/*	Save A4.			*/
	move.l	@1,A4		/*	Set A4 (static base reg)	*/

	move.l	A1,theEvent	/*	Save the ER pointer		*/

	clr.w	-(sp)		/*	Space for returned value	*/
	move.w  D0,-(sp)	/*	Push EventMask			*/
	move.l	A1,-(sp)	/*	Push ER pointer			*/
	move.l	OldNextEvent,A0	/*	Get ready to jsr		*/
	jsr	(A0)		/*	Do the old GetNextEvent		*/
	move.w	(sp),10(sp)	/*	Result to REAL result.
					Leave the result in the stack
					as a parameter for DoEvent	*/
	jsr	DoEvent		/*	Do our stuff			*/
	addq.l	#2,sp		/*	Remove parameter		*/
	move.l	(sp)+,A4	/*	Restore A4			*/
	rts

	@1	nop		/*	"Variable" space		*/
	}
}
/*	Save base reg at the end of the previous routine.
**	This is clearly a kludge...
*/
void	sa0()
{
asm	{
@0	lea	@0-4,A1	
	move.l	A0,(A1)
	}
}
/*	Would you like to close a file before the system
**	goes down? Would you like to play a sound before
**	rebooting? This is where you place the code.
*/
void	MyShutDown()
{
	SysBeep(10);
	SysBeep(10);
}
/*	This part gets called once. It saves the pointer
**	to us (our static storage), installs the patch and
**	puts us in the shutdown queue.
*/
void	main()
{
	Handle		myhandle;

	sa0();
asm	{	movem.l		A0-A4,-(A7)
		move.l		A0,A4
		_RecoverHandle
		move.l		A0,myhandle
	}
	if(Button())
		SysBeep(10);	/*	Beep, if install was cancelled	*/
	else
	{	DetachResource(myhandle);
		HLock(myhandle);

		OldNextEvent=NGetTrapAddress(NextEventNum,ToolTrap);
		NSetTrapAddress(NewGetEvent,NextEventNum,ToolTrap);

		ShutDwnInstall(MyShutDown,8);
	}

asm	{	movem.l		(A7)+,A0-A4		}
}
	/*		File ends here!		*/