*	Sticky Mouse
*	by Damien M. Jones
*	December 26, 1991
*	Written for Sean P. Price.
*
*	This program allows you to switch the left mouse button on
*	by clicking the right button.  Click the right button again
*	(or left) to turn it off.  This does, of course, prevent you
*	from using the right mouse button.  Oh well... other than that,
*	it is compatible with ALL programs that do not use their own
*	mouse driver.  Thus it should work with all GEM programs,
*	and I *know* it works with DMJ GIF 3.0.
*
*	You may freely copy or modify this program; that's why this
*	source code is included.  Once installed this uses only 512
*	bytes of memory.
*
*	Don't forget the config program, STKYMCFG.PRG, which allows you
*	to turn StickyMouse on and off, and save the configuration.

*	First of all, skip the main routines and go to the init.

	bra init

*	Some variables...

id	dc.b 'StickyMouse!'	; 12-byte ID string (used by Cfg!)

leftb	dc.w 0			; Left mouse button "sticky" flag.
lastb	dc.w 0			; Last mouse status.
sticky	dc.w $FFFF		; StickyMouse enable flag.

vblvec	dc.l 0			; Address to clear VBL vector from.
mvec	dc.l 0			; Address of mouse vector.
oldvec	dc.l 0			; The original mouse vector.

*	The mouse interrupt routine.

mint	move.l a1,-(a7)		; Save registers.
	lea leftb(pc),a1	; Address of variables.

	tst.w 4(a1)		; StickyMouse active?
	beq done		; No, bail now.

	btst.b #1,(a0)		; Left mouse button pressed?
	beq skip		; No, skip this.

	clr.w (a1)		; Clear leftb flag.

skip	btst.b #0,(a0)		; Check right mouse button.
	beq noright		; Not down, clear flag & check sticky.

	bclr.b #0,(a0)		; Clear right button flag.

	tst.w 2(a1)		; Was right mouse button just down?
	bne mstick		; Yes, ignore for now & check sticky.

	st 2(a1)		; Else set lastb flag...
	not.w (a1)		; And toggle leftb flag.
	bra mstick		; Now check sticky.

noright	clr.w 2(a1)		; Clear lastb flag.

mstick	tst.w (a1)		; Sticky flag set?
	beq done		; No, bail.

	bset.b #1,(a0)		; Set left mouse button flag.

done	move.l (a7)+,a1		; Restore registers.
jump	jmp $11111111		; Jump to original interrupt.

*	The VBL caught-the-change installation routine.

vbl	movem.l a0-a2,-(a7)	; Save registers.
	move.l #vblvec,a0	; Address of VBL variables.
	move.l 4(a0),a1		; Address of mouse vector.
	move.l (a1),a2		; Get the vector's current value.
	cmp.l 8(a0),a2		; Is it what it was?

	beq vexit		; Yes, do nothing for now.

	move.l (a0),$70.w	; Reset VBL.

	move.l #jump+2,a2	; Address of address in jmp instruction.
	move.l (a1),(a2)	; Install address.
	move.l #mint,(a1)	; New interrupt.

vexit	movem.l (a7)+,a0-a2	; Restore registers.
vjump	jmp $11111111		; All done.

*	The actual interrupt init routine, which must be called in super-
*	visor mode.  Since supexec (Xbios(38)) does not allow system calls,
*	the address of kbdvbas is stored in leftb.  I'd use the Gemdos(32)
*	call, but I don't have a good definition of how to use it.

*	The heart of this is that Xbios(34) returns the address of the
*	keyboard vector table; this table contains the address of some
*	keyboard handling routines.  At Xbios(34)+16 is the address of
*	the mouse routine; I simply redirect this to my own routine...

*	Of course, if that were all there was to it, it would be easy!
*	On bootup, the mouse hasn't been initialized, so I use the VBL
*	to wait for a change in the mouse vector.  As soon as there is
*	one, I switch it over to my routine.  So all this routine does
*	is install the VBL...

minit	move.l #vjump+2,a2	; Address of address of jmp instruction.
	move.l $70.w,(a2)	; Save old VBL address.
	move.l (a2),vblvec	; Save it here too.

	move.l mvec,a1		; Address of mouse vector.
	move.l (a1),oldvec	; Save old one.
	move.l #vbl,$70.w	; Store new VBL.

mexit	rts			; All done.

*	The initialization routine.

init	pea msg			; Address of init text.
	move.w #9,-(a7)		; cconws
	trap #1			; GEMDOS(9)
	addq.l #6,a7		; Adjust stack.

	move.w #34,-(a7)	; kbdvbas
	trap #14		; XBIOS(34)
	addq.l #2,a7		; Adjust stack.
	add.l #16,d0		; Get mouse vector from kbdvbas.
	move.l d0,mvec		; Store mouse vector.

	pea minit		; Address of init routine.
	move.w #38,-(a7)	; supexec
	trap #14		; XBIOS(38)
	addq.l #6,-(a7)		; Adjust stack.

	clr.w -(a7)		; Return 0.
	move.l #512,-(a7)	; Save 512 bytes.
	move.w #49,-(a7)	; ptermres
	trap #1			; GEMDOS(49) - no return.

*	Text & stuff:

msg	dc.b $0D,$0A,$1B,'p StickyMouse ',$1B,'q',$0D,$0A
	dc.b ' v1.0 by dmj ',$0D,$0A,$0D,$0A,$00

