[comp.sources.amiga] v02i014: Cancel! source

bryce%cogsci.Berkeley.EDU@ucbvax.berkeley.edu (Bryce Nesbitt) (08/09/87)

;Cancel! V1.0  Copyright 1987 Bryce Nesbitt.  Free, revokable license
;granted to use this code in any way provided all copyright notices remain
;intact and it is NOT used by or for or by any entity that has been commonly
;referred to as Robert W. Skyles, Skyles Electric Works, Jim Drew, Regie
;Warren or by any organization founded by, controlled, employing or
;profiting any such entity.  FISH use ok.  Send bugs (or bug reports :-),
;threats, suggestions or requests for permanent license to:
;	1712 Marin Ave.
;	Berkeley, Ca 94707-2902
;	bryce@cogsci.berkeley.EDU -or- ucbvax!cogsci!bryce
;
;USAGE
;	CLI - Cancel!		;Disable *ALL* system requesters & alerts.
;	    - Cancel! off	;Enable requesters.
;	WB  - Brings up requester
;
;	Sometimes there is no human available to push "Cancel" on a
;	requester that might be generated.  Imagine a "disk full"
;	requester while running a unattended system!
;	This "Auto Human" sits dormant until it gets it's big chance
;	to press "Cancel" for you.
;
;BUGS
;	Cancel! refuses to install itself multiple times.  However, since
;	there is no such thing as a SetFunction() lock, OTHER tasks can
;	muddle things considerably.
;
;	This program features intellegent multitasking arbitration.  You,
;	the intellegent human, must not try to run two copies of this
;	program simultaneously.
;
;	"Software error, Task held" requesters may cause headaches.
;
;	Alerts really should be handled also.
;
;ADDITIONS
;	It would be useful in some cases to have a log of the text of
;	all the aborted requesters.  Perhaps allocate a `N' byte
;	file in a recoverable ram disk and record the latest `N' bytes
;	of requester messages.
;
;IMPLEMENTATION
;	Uses SetFunction to lobotomize AutoRequest() and BuildSysRequest(),
;
;NOTES
;	Should come to 812 bytes when assembled with Metacomco and Blink'ed
;	with the NODEBUG option set.
********************
	NOLIST
	INCLUDE 'exec/types.i'
;	INCLUDE 'exec/memory.i'
	BITDEF	MEM,PUBLIC,0
	BITDEF	MEM,CHIP,1
	BITDEF	MEM,FAST,2
	BITDEF	MEM,CLEAR,16
	IFND	EXEC_ABLES_I
	INCLUDE 'exec/ables.i'
	ENDC
	IFND	EXEC_DOSEXTENS_I
	INCLUDE 'libraries/dosextens.i'
	ENDC
;	INCLUDE 'intuition/intuitionbase.i'
ib_ActiveWindow EQU $34
ib_ActiveScreen EQU $38
ib_FirstScreen	EQU $3C
	LIST
 STRUCTURE	SetFunctionLock,0
		BYTE   sfl_Start	;Must be set to $60. BRA.S in 68000
		BYTE   sfl_Branch	;Branch offset, value will vary
		WORD   sfl_Magic_Cookie ;Must be $4AFC
		APTR   sfl_OldVector	;Function this lock displaced
		APTR   sfl_Semaphore	;Used to arbitrate this structure
		WORD   sfl_MSize	;Size to use with FreeMem()
		WORD   sfl_Flags	;See bit definitions...
		BYTE   sfl_IDString	;The actual string, *NOT* a pointer
		;No SIZEOF because it keeps going...
jsrlib	MACRO
	xref _LVO\1
	jsr  _LVO\1(a6)
	ENDM
jmplib	MACRO
	xref _LVO\1
	jmp  _LVO\1(a6)
	ENDM
blink	MACRO
	bchg.b #1,$bfe001
	ENDM
********************
		xref	_LVOAutoRequest
		xref	_LVOBuildSysRequest

IBase		equr	d6
DOSBase 	equr	d5
linelen 	equr	d4

		CODE
startup:	move.l	d0,linelen
		move.l	4,a6
		move.l	ThisTask(a6),a5
		moveq	#0,d0		;Set zero for later
		move.l	pr_CLI(a5),d1	;Pointer to CLI only structure
		bne.s	fromCLI 	;If not zero, then flag zero...
		lea.l	pr_MsgPort(a5),a0
		jsrlib	WaitPort	;Wait for Workbench's Message
fromCLI 	move.l	d0,-(a7)	;Save message/flag for later...
******************* [A6=ExecBase][a5=this task]

		moveq	#20,d7
		lea.l	DOSName(pc),a1
		jsrlib	OldOpenLibrary	;V1.0 Compatible :-)
		move.l	d0,DOSBase
		beq	e_dos
		lea.l	IntuiName(pc),a1
		jsrlib	OldOpenLibrary	;V1.0 Compatible :-)
		move.l	d0,IBase
		beq	e_intui

		tst.l	(a7)		;Test CLI flag on stack
		beq.s	fromtheCLI
;---Do Workbench user interface---
		FORBID
		bsr	CHECKIF
		move.l	d0,-(a7)	;save flag
		jsrlib	Permit
		bsr	REMOVEIT	;We wanna put up a requester
		moveq	#0,d0
		moveq	#0,d1
		move.l	#320,d2
		moveq	#68,d3
		suba.l	a0,a0
		suba.l	a2,a2
		lea.l	ITextOk(pc),a3
		tst.l	(a7)
		bne.s	sayremove
		lea.l	ITextId(pc),a1
		bra.s	displayit
sayremove	lea.l	ITextRemoved(pc),a1
displayit	move.l	IBase,a6
		jsrlib	AutoRequest
		move.l	4,a6
		move.l	(a7)+,d0
		bne.s	RemoveIt
		beq.s	DoItDude

;---Do CLI UI---
fromtheCLI:	subq.l	#1,linelen
		beq.s	DoItDude

;---Do the actual work---
RemoveIt:	bsr	REMOVEIT
		tst.l	(a7)		;check CLI flag
		bne.s	ExitOk
		lea.l	Sremoved(pc),a0
		moveq	#Eremoved-Sremoved,d3
		bsr	WRITEIT
		bra.s	ExitOk

DoItDude:	bsr	ADDIT
		beq.s	e_nomem
		tst.l	(a7)		;check CLI flag
		bne.s	ExitOk
		lea.l	Sinstall(pc),a0
		moveq	#Einstall-Sinstall,d3
		bsr.s	WRITEIT
		bne.s	ExitOk

;--no memory, no fun--
e_nomem 	move.l	ThisTask(a6),a1
		moveq	#ERROR_NO_FREE_STORE,d0
		move.l	d0,pr_Result2(a1)
ExitError	moveq	#20,d7	    ;return code of "fail"
		bra.s	Exit

ExitOk		moveq	#0,d7
Exit		move.l	IBase,a1
		jsrlib	CloseLibrary
e_intui 	move.l	DOSBase,a1
		jsrlib	CloseLibrary
e_dos
******************************* (a7)+=message d7=return code a6=exec
ExitToDOS:	move.l	(a7)+,d2
		beq.s	NotWB	    ;If saved pointer is zero, exit to CLI...
		FORBID
		move.l	d2,a1	    ;Return message to WB.  Use FORBID so
		jsrlib	ReplyMsg    ;we won't be UnLoadSeg()'ed too early.
NotWB		move.l	d7,d0	    ;Set "failat" code
		rts
*******************

;SYNOPSIS
;   error=WRITEIT(string,length),anything
;   z		  a0	 d3	 a6
;
;GLOBALS
;   DOSBase

WRITEIT:	move.l	a6,-(a7)
		move.l	DOSBase,a6
		move.l	a0,d2
		jsrlib	Output
		move.l	d0,d1
		move.l	d1,-(a7)
		jsrlib	Write
		lea.l	linefeed(pc),a0
		move.l	(a7)+,d1
		move.l	a0,d2
		moveq	#1,d3
		jsrlib	Write
		move.l	(a7)+,a6
		cmp.l	d0,d3
		rts

;SYNOPSIS
;   result=ADDIT(),exec
;   z
;
;FUNCTION
;   Add the functions, if they are not already added
;
;NOTES
;    Since the handler code is SHARED by any process that cares to call
;    the requester function, it must be copied to PUBLIC memory.  It must
;    also be re-entrant.

ADDIT		bsr	CHECKIF
		beq	InPlace     ;Already there...
		move.l	#HandlersEnd-HandlersStart,d0
		move.l	#MEMF_PUBLIC+MEMF_CLEAR,d1
		jsrlib	AllocMem
		tst.l	d0		;grumble.
		bne.s	ok_mem
		rts

;---Copy to new location---
ok_mem		;[d0=memblock]
		move.l	a2,-(a7)
		move.l	d0,a1
		lea.l	HandlersStart(pc),a0
		moveq	#((HandlersEnd-HandlersStart)/4)-1,d1
copylp		move.l	(a0)+,(a1)+	;Copy handler to PUBLIC Memory
		dbra	d1,copylp

;---Try to add the newly prepared request ---
		;[d0=memblock]
		move.l	d0,a2

;--Add the new ones--
		lea.l	NewAutoRequest-HS(a2),a0 ;our new function
		move.l	a0,d0
		move.w	#_LVOAutoRequest,a0	;offset
		move.l	IBase,a1		;library
		jsrlib	SetFunction
		move.l	d0,NewAutoRequest+sfl_OldVector-HS(a2)

		lea.l	NewBuildSysRequest-HS(a2),a0 ;our new function
		move.l	a0,d0
		move.w	#_LVOBuildSysRequest,a0 ;offset
		move.l	IBase,a1		;library
		jsrlib	SetFunction
		move.l	d0,NewBuildSysRequest+sfl_OldVector-HS(a2)

		move.l	(a7)+,a2
InPlace 	moveq	#-1,d0
		rts


;SYNOPSIS
;   result=REMOVEIT(),exec
;   z		      a6
;
;FUNCTION
;   Remove the handlers if they are not already gone

REMOVEIT	FORBID
		move.w	#_LVOBuildSysRequest,a0 ;offset
		move.l	IBase,a1		;library
		bsr	ISIT
		bne.s	notthere1
		jsrlib	SetFunction

notthere1	move.w	#_LVOAutoRequest,a0	;offset
		move.l	IBase,a1		;library
		bsr	ISIT
		bne.s	notthere2
		move.l	d1,-(a7)
		jsrlib	SetFunction

;There is a finite chance that some code is still running in my
;SetFunction'ed code.  Oh, well.

		jsrlib	Permit
		move.l	(a7)+,a1
		move.l	#HandlersEnd-HandlersStart,d0
		jmplib	FreeMem
nothingtofree	rts
notthere2	jmplib	Permit

;SYNOPSIS
;   result,offset,library,OldVector,Vector=ISIT(offset,library),exec
;   z	   a0	  a1	  d0	    d1		a0     a1      a6
;
;FUNCTION
;   Check if we are already installed.	CALL WHILE FORBID'ed
;
;RESULT
;   Z=1 if found
;   d0=OldVector, if found.  zero otherwise.
;   d1=Vector, if found.  Garbage otherwise.

CHECKIF 	move.w	#_LVOAutoRequest,a0	;offset
		move.l	IBase,a1		;library
ISIT		movem.l a0/a1/d2,-(a7)
		move.l	2(a1,a0.w),a0
		move.l	a0,d1		;Get Vector
		addq.l	#4,a0		;Skip branch & cookie
		move.l	(a0)+,d0	;Get OldVector
		addq.l	#8,a0		;Skip Semaphore, etc.
		lea.l	HandlersStart+16(pc),a1
		moveq	#compareend-comparestart-1,d2
namechk 	cmpm.b	(a0)+,(a1)+
		dbne	d2,namechk
		beq.s	foundit
		moveq	#0,d0
		moveq	#-1,d1
foundit 	movem.l (a7)+,a0/a1/d2
		rts

**************************** text area *************************************

ITextId:	dc.b 0,1,1,0	     ;pens, drawmode and filler
		dc.w 20,6	     ;XY
		dc.l 0		     ;NULL for default font
		dc.l Sid	     ;pointer to text
		dc.l ITextId2	     ;next IntuitText structure
ITextId2	dc.b 0,1,1,0
		dc.w 20,17
		dc.l 0
		dc.l Sinstall
		dc.l 0

ITextRemoved:	dc.b 0,1,1,0
		dc.w 20,6
		dc.l 0
		dc.l Sid
		dc.l ITextId3
ITextId3	dc.b 0,1,1,0
		dc.w 20,17
		dc.l 0
		dc.l Sremoved
		dc.l 0

ITextOk:	dc.b 0,1,1,0
		dc.w 6,3
		dc.l 0
		dc.l SOk
		dc.l 0

Sid		dc.b 'Cancel!, ',$a9,'1987 Bryce Nesbitt',0
	       ;dc.b 'Cancel!, +1987 Bryce Nesbitt',0
Sinstall	dc.b 'Requesters will be Canceled!',0
Einstall
Sremoved	dc.b 'Requesters are now enabled.',0
Eremoved
SOk		dc.b 'Ok',0
IntuiName	dc.b 'intuition.library',0
DOSName 	dc.b 'dos.library',0
linefeed	dc.b 10

****************************** handlers ************************************

;These are the parts that gets installed to do the actual 'dirty work'.
;The header provides a format for the name of this module, the pointer
;to the old function, and information on how to remove it.

		cnop	0,4
HandlersStart:
HS:
NewAutoRequest: bra.s	TheCode1
		dc.w	$4afc
		dc.l	0
		dc.l	0
		dc.w	0
		dc.w	1
comparestart
		dc.b	'Cancel!',0
		cnop	0,2
compareend
NewBuildSysRequest: bra.s   TheCode1
		dc.w	$4afc
		dc.l	0
		dc.l	0
		dc.w	0
		dc.w	1
		dc.b	'Cancel!',0

		cnop   0,2
TheCode1:	moveq	#0,d0	    ;FALSE
		rts

		cnop	0,4
HandlersEnd:
********************
		END

----
    Craig Norborg
    comp.sources.amiga moderator