
		***************************************************
		***						***
		***		     Notify 1.0			***
		***						***
		***************************************************
		***   © 19.12.94 by Marc Heuler (Data Design)	***
		***************************************************

		INCDIR	"Include:"
		INCLUDE	"exec/types.i"
		INCLUDE	"exec/libraries.i"
		INCLUDE	"exec/ports.i"
		INCLUDE	"exec/execbase.i"
		INCLUDE	"utility/tagitem.i"
		INCLUDE	"dos/dosextens.i"
		INCLUDE	"dos/notify.i"
		INCLUDE	"devices/timer.i"
		INCLUDE	"LVO.i"

CALLEXE		MACRO
		move.l	_SysBase(pc),a6
		jsr	_LVO\1(a6)
		ENDM

CALLDOS		MACRO
		move.l	_DosBase(pc),a6
		jsr	_LVO\1(a6)
		ENDM

NAME		MACRO
		dc.b	"Notify"
		ENDM

VERSION		MACRO
		dc.b	"1.00"
		ENDM

DATE		MACRO
		dc.b	"19.12.94"
		ENDM


Start		bra.s	RStart

		dc.b	"$VER: "
		NAME
		dc.b	" "
		VERSION
		dc.b	" ("
		DATE
		dc.b	") © 1994 by Marc 'Nepomuk' Heuler <marc@aargh.incubus.sub.org>",0
		even

		***************************************************
		***						***
		***			Start			***
		***						***
		***************************************************

RStart		movem.l	d1-d7/a0-a6,-(a7)
		move.l	4,_SysBase
		moveq	#-1,d4
		moveq	#0,d5
		moveq	#0,d6
		moveq	#0,d7

		lea	_DosName(pc),a1			; Open DOS
		moveq	#33,d0
		CALLEXE	OpenLibrary
		move.l	d0,_DosBase
		beq	.Error

		move.l	d0,a0				; DOS 37+ required
		cmp.w	#37,LIB_VERSION(a0)
		blt	.Error_Kick

		move.l	#_Template,d1			; Get arguments
		move.l	#_Name,d2
		moveq	#0,d3
		CALLDOS	ReadArgs
		move.l	d0,_Args
		beq	.Error_DOS

		***************************************************
		***		Open timer.device		***
		***************************************************

		tst.l	_Delay				; Do we need the timer?
		beq	.StartNotify

		CALLEXE	CreateMsgPort			; Get message port
		move.l	d0,d6
		beq	.Error

		lea	TimerIOB(pc),a1			; Open device
		move.l	d6,MN_REPLYPORT(a1)
		lea	_TimerName(pc),a0
		moveq	#UNIT_VBLANK,d0
		moveq	#0,d1
		CALLEXE	OpenDevice
		tst.l	d0
		bne	.Error
		st	d7

.StartNotify	***************************************************
		***		 Expand filename		***
		***************************************************

		move.l	_SysBase(pc),a0			; Suppress requesters
		move.l	ThisTask(a0),a0
		move.l	pr_WindowPtr(a0),d0
		movem.l	d0/a0,-(sp)
		move.l	#-1,pr_WindowPtr(a0)

		move.l	_Name(pc),d1			; Lock file
		move.l	#ACCESS_READ,d2
		CALLDOS	Lock
		move.l	d0,d4

		movem.l	(sp)+,d0/a0			; Re-allow requesters
		move.l	d0,pr_WindowPtr(a0)

		tst.l	d4				; Lock succeeded?
		beq.s	.CopyName

		move.l	d4,d1				; Get name
		move.l	#Buffer,d2
		move.l	#BufferEnd-Buffer,d3
		CALLDOS	NameFromLock
		move.l	d0,-(sp)

		move.l	d4,d1				; Unlock file
		CALLDOS	UnLock

		moveq	#0,d4				; Check success
		tst.l	(sp)+
		beq	.Error_DOS
		bra.s	.DoNotification

.CopyName	move.l	_Name(pc),a0			; Copy supplied name
		lea	Buffer,a1
		move.l	#BufferEnd-Buffer,d0
.CopyLoop	subq.l	#1,d0
		bmi.s	.CopyError
		move.b	(a0)+,(a1)+
		bne.s	.CopyLoop
		bra.s	.DoNotification
.CopyError	move.l	#ERROR_LINE_TOO_LONG,d1
		CALLDOS	SetIoErr
		bra	.Error_DOS

.DoNotification	***************************************************
		***		Start notification		***
		***************************************************

		moveq	#-1,d0				; Allocate signal bit
		CALLEXE	AllocSignal
		move.l	d0,d4
		tst.b	d4
		beq	.Error

		lea	NotifyReq(pc),a1		; Fill in notify request
		move.l	_Name(pc),nr_Name(a1)
		beq	.Error
		move.l	ThisTask(a6),nr_Task(a1)
		move.b	d4,nr_SignalNum(a1)
		move.l	#NRF_SEND_SIGNAL,nr_Flags(a1)

		move.l	a1,d1				; Activate
		CALLDOS	StartNotify
		tst.l	d0
		beq	.Error_DOS
		st	d5

		***************************************************
		***		Wait for activity		***
		***************************************************

.Loop		move.l	#SIGBREAKF_CTRL_C,d0		; Wait
		bset	d4,d0
		CALLEXE	Wait
		moveq	#SIGBREAKB_CTRL_C,d1
		btst	d1,d0
		bne	.Break

.TimerLoop	move.l	_Delay(pc),d0			; Delay specified?
		beq	.Command
		move.l	d0,a0

		lea	TimerIOB(pc),a1			; Start timer
		move.w	#TR_ADDREQUEST,IO_COMMAND(a1)
		move.l	(a0),IOTV_TIME+TV_SECS(a1)
		clr.l	IOTV_TIME+TV_MICRO(a1)
		CALLEXE	SendIO

		move.l	#SIGBREAKF_CTRL_C,d0		; Wait again
		bset	d4,d0
		move.l	TimerIOB+MN_REPLYPORT(pc),a0
		move.b	MP_SIGBIT(a0),d1
		bset	d1,d0
		CALLEXE	Wait

		move.l	d0,-(sp)
		lea	TimerIOB(pc),a1			; Abort timer
		CALLEXE	AbortIO
		lea	TimerIOB(pc),a1
		CALLEXE	WaitIO
		move.l	TimerIOB+MN_REPLYPORT(pc),a0	; Clear timer signal
		move.b	MP_SIGBIT(a0),d0
		bset	d0,d1
		moveq	#0,d0
		CALLEXE	SetSignal
		move.l	(sp)+,d0

		moveq	#SIGBREAKB_CTRL_C,d1		; Examine signals
		btst	d1,d0
		bne	.Break
		btst	d4,d0				; Another notification?
		bne.s	.TimerLoop

		***************************************************
		***		   Start command		***
		***************************************************

.Command	move.l	_Command(pc),d1			; Script mode?
		beq.s	.NoCMD

		move.l	#.Tags,d2			; Execute command
		CALLDOS	SystemTagList

		tst.l	_Stay				; Stay in memory?
		bne	.Loop

.NoCMD		moveq	#0,d0
		bra.s	.Cleanup

.Tags		dc.l	TAG_DONE,0

		***************************************************
		***		  Error handling		***
		***************************************************

.Break		lea	.tx_Break(pc),a0
		bsr	Print
		moveq	#10,d0
		bra.s	.Cleanup

.Error_Kick	lea	.tx_Kick(pc),a0			; Wrong Kickstart
		bsr	Print
		bra.s	.Error

.Error_DOS	CALLDOS	IoErr				; DOS error
		move.l	d0,d1
		move.l	#.tx_Name,d2
		CALLDOS	PrintFault

.Error		moveq	#20,d0
		bra.s	.Cleanup

.tx_Break	dc.b	"***Break",$a,0
.tx_Name	NAME
		dc.b	0
.tx_Kick	dc.b	"You need at least Kickstart 2.04 (v37)"
.tx_CR		dc.b	$a,0
		even

		***************************************************
		***		      Cleanup			***
		***************************************************

.Cleanup	move.l	d0,-(a7)

		tst.b	d7				; Close timer.device
		beq.s	.NoTimer
		lea	TimerIOB(pc),a1
		CALLEXE	CloseDevice
.NoTimer	tst.l	d6				; Remove msg port
		beq.s	.NoPort
		move.l	d6,a0
		CALLEXE	DeleteMsgPort
.NoPort		tst.b	d5				; Stop notification
		beq.s	.NoNotify
		move.l	#NotifyReq,d1
		CALLDOS	EndNotify
.NoNotify	tst.b	d4				; Free signal bit
		bmi.s	.NoSignal
		move.l	d4,d0
		CALLEXE	FreeSignal
.NoSignal	move.l	_Args(pc),d1			; Free Args
		beq.s	.NoArgs
		CALLDOS	FreeArgs
.NoArgs		move.l	_DosBase(pc),d0			; Close DOS
		beq.s	.NoDos
		move.l	d0,a1
		CALLEXE	CloseLibrary
.NoDos		move.l	(a7)+,d0
		movem.l	(a7)+,d1-d7/a0-a6
		rts

		***************************************************
		***						***
		***		Print To StdOutput		***
		***						***
		***************************************************
		*** >>> A0	String (0-terminated)		***
		*** <<< FLAGS	BNE ERROR			***
		***************************************************

Print		movem.l	d1-d3/a0-a1,-(a7)
		move.l	_DosBase(pc),d0
		beq.s	.Print_Skip
		move.l	a0,-(a7)
		CALLDOS	Output
		move.l	d0,d1
		move.l	(a7)+,a0
		move.l	a0,d2
.Print_Loop	tst.b	(a0)+
		bne.s	.Print_Loop
		move.l	a0,d3
		subq.l	#1,d3
		sub.l	d2,d3
		beq.s	.Print_Skip
		move.l	d3,-(a7)
		CALLDOS	Write
		sub.l	(a7)+,d0
.Print_Skip	movem.l	(a7)+,d1-d3/a0-a1
		rts

		***************************************************
		***						***
		***		     Variables			***
		***						***
		***************************************************

_Args		dc.l	0
_SysBase	dc.l	0
_DosBase	dc.l	0

_Name		dc.l	0
_Command	dc.l	0
_Delay		dc.l	0
_Stay		dc.l	0

NotifyReq	dcb.b	NotifyRequest_SIZEOF,0

TimerIOB	dcb.b	IOTV_SIZE,0


_TimerName	dc.b	"timer.device",0
_DosName	dc.b	"dos.library",0
_Template	dc.b	"NAME/A,COMMAND,DELAY/N,STAY/S",0
		even

		SECTION	Buf,bss

Buffer		ds.b	1024
BufferEnd

		END

