		exeobj
		objfile "van"
		incdir	"ainc:"

		relax		;converts non specific opcodes
		MC68000		;my CPU chip (DRAT! I want a 30)
		odderror	;ODD address's are an error

*
*  $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
*  $$                             $$
*  $$ 'van'ish ( screen blanker ) $$
*  $$                             $$
*  $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
*
* by:
*          Robin Luiten
*          10 Chartwell St
*          Aspley 4034
*          Brisbane QLD Australia
*
* Assembler: 'Macro68' by DigiSoft
*
* Please do not distribute modified versions of this code using the
* the name 'VAN' or 'vanish' as I plan to release further updates and
* improvements in the future.
*
* If anyone out there does something neat with this I would appreciate
* hearing about it. I also gladly take bug reports and or comments
* on the code.
*
* This source is one of the examples included in the release of
* 'Macro68' by DigiSoft.
*
* See van.doc if you want to see what this beast does without having
* to wade through all the code.
*
* History:
*
* 26/05/90 working version v1.0
*          afternoon added LAmiga-Z 2nd Front Screen to front.
*          FIXED: if screen blanked and something runs van without
*                 unblanking screen will never unblank.
*     v1.1 EVENING
*          fixed nasty bug when uninstalling, would always die
*          this bug caused by previous bug fix
*          Optimised and simplified LeftAmiga-(key) handling
*
* 02/06/90 v1.2 BUG with new window shuffling routine
*          if had backdrop window on screen (eg workbench)
*          would only "try" to move it to front. (impossible)
*
* 06/06/90 v1.3 added new features tidied up some comments
*
* 09/07/90 v1.4 added new features.
*
* 10/07/90 v1.5 rewrite of new features cause of some problems involved.
*
* 11/07/90 v1.6 Forgot to exclude multitasking while I was looking around
*          and examining structures.
*
* 12/07/90 v1.7 No longer swaps to tagged window if tagged = current window.
*
* 21/07/90 v1.8 Rewrote the order and procedural break down of the functions
*          involved in VAN. Much tidier and more modular now.
*          Also stopped extraneous repeating of functions if key
*          held down to long. Also added exiting message.
*
* 25/07/90 Added switches -e escape key, and -q for qualifier
*
* 04/08/90 v1.9 Finished switches added on 25/07/90.
*          Also fixed bug in input handler that it would not
*          look at the the event pointed to by 'ie_NextEvent'
*          field in the input event structure. It does now.
*          Dont know how I possibly missed this in first version.
*
* 22/08/90 v2.0 fixed bug in escape key for bypassing vans handling of
*          a command key.
*          Removed the Command LeftAmiga-W for workbench to front
*          as it annoyed some friends using van and I found that
*          I have not used it yet since I added it.
*          To add it again search for string 'removed WBTOFRONT' and
*          fix up the Function table to include it again.
*

*
* Uncomment if you dont use resident maclibs.
* If you havn't tried out resident maclibs yet, then try 'em
* cause they speed up assembling stuff that uses include files
* by so much you will not have time to drink your coffee anymore.
*
*		macfile "offsets/exec.i"
*		macfile "offsets/dos.i"
*		macfile "offsets/intuition.i"
*		macfile "offsets/graphics.i"
*		macfile	"exec/types.i"
*		macfile	"exec/execbase.i"
*		macfile "exec/exec.i"
*		macfile	"devices/inputevent.i"
*		macfile	"devices/input.i"
*		macfile	"hardware/dmabits.i"
*		macfile	"hardware/custom.i"
*		macfile	"graphics/clip.i"
*		macfile	"graphics/layers.i"
*		macfile	"intuition/intuitionbase.i"
*		macfile	"intuition/screens.i"
*		macfile	"intuition/intuition.i"
*		macfile	"libraries/dos.i"
*		macfile	"libraries/dosextens.i"

		macfile	"rawkeys.i"	/* NOT standard commodore include */

;--------------------------
; Some Extra system stuff
BACKDROP_B	equ	8			;backdrop window bit in wd_Flags

;--------------------------
; Character DEFS
DQUOTE		equ	'"'			;double quote char

;----------------------------------
; Input Handler event definitions.
; Offsets in words as is used to
; directly look up function in
; offset table.
INVALID		equ	0
BLANK		equ	2
UNBLANK		equ	4
SCREENTOBACK	equ	6
NEWCLI		equ	8
WINDOWTOBACK	equ	10
WINDOWTOFRONT	equ	12
SWAPACTIVEWIN	equ	14
ACTIVATE_FWIN	equ	16
SCREENTOFRONT	equ	18
WBTOFRONT	equ	20
TAGWINDOW	equ	22
ESCAPE_NEXT	equ	24

TICKSPERSEC	equ	10

; Event Info limits
SHFTOUT		equ	3
TIMEOUT		equ	60		; 60 seconds
MIN_TIME	equ	10		; 10 seconds

*****************
* Start Of Code *
*****************
DT:						;DataBase
		bra	vanish			;Get to start

Me.MSG:		db	" "
		db	$1B
		db	"[32mVAN"
		db	$1B
		db	"[0m v2.0 22-08-90 : Robin Luiten",10
Me.END:
SIZEME		equ	Me.END-Me.MSG

Exit.MSG:	db	" VAN Exiting...",10
Exit.END:
SIZEEXIT	equ	Exit.END-Exit.MSG

Help.MSG	db	"USAGE : 'VAN [switches] [command string]'",10
		db	9,"Switches are :",10
		db	9," -qxxxx : command qualifier",10
		db	9," -txxxx : timeout in seconds",10
		db	9," -e     : move command execution key to ESCAPE",10
Help.END	cnop	0,2
SIZEHELP	equ	Help.END-Help.MSG

vanish:		movem.l	d0/a0,-(sp)
		lea	(DXSPACE,pc),a1
		moveq	#(((ENDDX-DXSPACE)+3)/4)-1,d1
		moveq	#0,d2
clr_dx		move.l	d2,(a1)+
		dbra	d1,clr_dx

		lea	(DT,pc),a4			;Relative Data Base
		move.l	(4).w,a6			;EXEC

******************************************************** ? Van Exists *********
* Check for existence of existing 'van'
* If old 'van' exists then send it a
* message to make it quit.
*
		lea	(IPort_name.MSG,pc),a1
		jsr	(_LVOFindPort,a6)
		tst.l	d0
		beq.b	InstallVan

******************************************************** UnInstall Vanish ****
* USES:
* a3.l - the addr of the old copy of van running.
* a2.l - our temporary reply port for killing old 'van'.
*
		addq	#8,sp				;dump argument stuff
		move.l	d0,a3				;old 'van' port

		moveq	#0,d0
		move.l	d0,a0				;temp port no name
		bsr	CreatePort
		tst.l	d0
		beq.b	NoMurderToday

		move.l	d0,a2				;our murder port
		moveq	#MN_SIZE,d0
		bsr	AllocMemCP
		beq.b	DelPort

		move.l	d0,a1				;message
		move.b	#NT_MESSAGE,(LN_TYPE,a1)	;initialise message
		move.l	a2,(MN_REPLYPORT,a1)
;;
;; If I set length then I get a memory freed twice GURU.
;; Since I am sending to my process message port does this
;; mean that this memory is freed for me if length set.
;; Anyone out there care to enlighten me.
;;
;;		move.w	#MN_SIZE,(MN_LENGTH,a1)
;;
		move.l	a3,a0				;To our old port
		jsr	(_LVOPutMsg,a6)			;STAB STAB STAB!

		move.l	a2,a0
		jsr	(_LVOWaitPort,a6)
		move.l	a2,a0
		jsr	(_LVOGetMsg,a6)

		move.l	d0,a1
		moveq	#MN_SIZE,d0
		jsr	(_LVOFreeMem,a6)		;free message mem

DelPort:	move.l	a2,a0
		bsr	DeletePort			;Remove Murder Port

******************************************************** Exit Message *******
		bsr	OpenDOSLib
		beq.b	.dosfail			;who cares at this point.
		move.l	d0,a6				;DOS base

		lea	(Exit.MSG,pc),a0
		moveq	#SIZEEXIT,d0
		bsr	OnceOffMessage

		move.l	a6,a1
		move.l	(4).w,a6
		move.l	(DosBase,pc),a1
		jsr	(_LVOCloseLibrary,a6)

.dosfail:	moveq	#0,d0
NoMurderToday:	rts

******************************************************** Install Vanish ******
* 'van' is not currently in the system so lets install it.
*
InstallVan:
		* Set Default qualifier.
		move.w	#IEQUALIFIER_LCOMMAND,(command_qualifier-DT,a4)
		movem.l	(sp)+,d0/a0			;CLI arguments
		bsr	ExtractArgs
		bne	end

		move.w	#SHFTOUT,(shftcount-DT,a4)	;Initialise variables
		move.w	(timeout,pc),(timecount-DT,a4)
		clr.w	(ihevent-DT,a4)

		move.l	(ThisTask,a6),a1
		move.l	a1,(VanishProcess-DT,a4)
		moveq	#10,d0				;Task Pri = 10
		jsr	(_LVOSetTaskPri,a6)

		lea	(input_int,pc),a0
		move.l	#InputHandler,(IS_CODE,a0)	;Interrupt Structure
		move.b	#52,(LN_PRI,a0)
		move.l	a4,(IS_DATA,a0)
		bsr	InstallInputHandler
		bne.b	end				;FAIL

		bsr	OpenINTLib			;Intuition
		beq.b	RemoveHandler

		bsr	OpenDOSLib			;DOS
		beq.b	CloseINT
		move.l	d0,a6

		lea	(Me.MSG,pc),a0
		moveq	#SIZEME,d0
		bsr	OnceOffMessage			;Feed EGO.
		beq.b	CloseDOS			;Error on Open '*'

		move.l	#nilname.MSG,d1
		move.l	#MODE_NEWFILE,d2
		jsr	(_LVOOpen,a6)
		move.l	d0,(nilhandle-DT,a4)
		beq.b	CloseDOS
		move.l	(4).w,a6			;restore EXEC

*******************************************************************************
		bsr.b	main
*******************************************************************************

		move.l	(DosBase,pc),a6
		move.l	(nilhandle,pc),d1
		jsr	(_LVOClose,a6)

CloseDOS:	move.l	(4).w,a6
		move.l	(DosBase,pc),a1
		jsr	(_LVOCloseLibrary,a6)

CloseINT:	move.l	(IntBase,pc),a1
		jsr	(_LVOCloseLibrary,a6)

RemoveHandler:
		lea	(input_int,pc),a0
		bsr	RemoveInputHandler

end:		moveq	#0,d0
		rts


******************************************************** MAIN *****************
* Hangs around and does all those things that the input
* event handler tells us to do.
*
* USES:
* d7.l - input handler signal + vanish message port signal
* a3.l - custom hardware address
* a4.l - Relative Data Base
*
* Wait for a signal from our input handler also
* Wait for a message from another running of VAN.
*
main:		lea	($dff000).l,a3			;custom base
		move.l	(input_Port,pc),a0
		moveq	#0,d0
		moveq	#0,d1
		move.b	(MP_SIGBIT,a0),d0		;the signal bit for PORT
		bset	d0,d1				;message port signal

		move.l	(ihsignal).l,d7			;interrupt handler signal
		or.l	d1,d7				;wait for both

WaitSig:	move.l	d7,d0				;input handler event
		jsr	(_LVOWait,a6)

		move.l	(input_Port,pc),a0
		jsr	(_LVOGetMsg,a6)
		tst.l	d0
		bne.b	EndVanish			;YES go back and QUIT

		jsr	(_LVOForbid,a6)			;stop multitasking

		move.w	(ihevent,pc),d0			;Peform function.
		move.w	(TB,pc,d0.w),d1			;look up code address
		jsr	(TB,pc,d1.w)			;go to it.

		jsr	(_LVOPermit,a6)			;OK multitask again
		bra.b	WaitSig
*
* We just got a die message on our message port
* so do the write thing and salute our MURDERER.
* And then we DIE...
*
EndVanish	move.l	d0,a1
		jsr	(_LVOReplyMsg,a6)
		bsr	UnVanishScreen		;make sure dont die while BLANKED
Invalid		rts

TB:
TableBase:	dw	Invalid-TB			;invalid event OOPS!
		dw	VanishScreen-TB			;BLANK
		dw	UnVanishScreen-TB		;UNBLANK
		dw	ScrToBack-TB			;SCREENTOBACK
		dw	Newcli-TB			;NEWCLI
		dw	WinToBack-TB			;WINDOWTOBACK
		dw	WinToFront-TB			;WINDOWTOFRONT
		dw	SwapActiveWindow-TB		;SWAPACTIVEWIN
		dw	Activate_Fwin-TB		;ACTIVATE_FWIN
		dw	ScrToFront-TB			;SCREENTOFRONT
		dw	WBtoFront-TB			;WBTOFRONT
		dw	TagWindow-TB			;TAGWINDOW
		dw	EscapeNextKey-TB		;ESCAPE_NEXT

*--------------------
EscapeNextKey:	move.b	#1,(escapekey-DT,a4)
		rts

*
* Activate Front Window on front screen.
*
* Save the Screen and Window pointers, of the last activated
* window before activating the Front Window. Also store the
* the Screen and Window pointers of the newly Activated Window.
*
Activate_Fwin:	move.l	a6,-(sp)
		bsr	UnVanishScreen
		move.l	(IntBase,pc),a6
		move.l	(ib_FirstScreen,a6),a0
		moveq	#1,d0				;Single Windows
		bsr	SmartTWindow
		beq.b	.end

		move.l	d0,a0
		jsr	(_LVOActivateWindow,a6)
.end		move.l	(sp)+,a6
		rts

*
* Tag the currently active window as being the one to swap back
* to on using SwapActiveWindow command. (LeftAmiga-z) 
*
TagWindow:	bsr	UnVanishScreen
		movem.l	a6,-(sp)
		move.l	(IntBase,pc),a6
		move.l	(ib_ActiveWindow,a6),a0
		move.l	a0,(TaggedWindow-DT,a4)
		move.l	(wd_WScreen,a0),(TaggedScreen-DT,a4)
		move.l	(sp)+,a6
		rts

*----------------------------------------------
WBtoFront:	bsr	UnVanishScreen
		move.l	a6,-(sp)
		move.l	(IntBase,pc),a6
		jsr	(_LVOWBenchToFront,a6)
		move.l	(sp)+,a6
		rts

*----------------------------------------------
ScrToBack:	bsr	UnVanishScreen
		move.l	a6,-(sp)
		move.l	(IntBase,pc),a6
		move.l	(ib_FirstScreen,a6),a0
		jsr	(_LVOScreenToBack,a6)
		move.l	(sp)+,a6
		rts

*----------------------------------------------
ScrToFront:	bsr	UnVanishScreen
		move.l	a6,-(sp)
		move.l	(IntBase,pc),a6
		move.l	(ib_FirstScreen,a6),a0

nextscreen:	move.l	(sc_NextScreen,a0),d0
		beq.b	movetofront

		move.l	d0,a0
		bra.b	nextscreen

movetofront:	jsr	(_LVOScreenToFront,a6)
		move.l	(sp)+,a6
		rts

*----------------------------------------------
Newcli:		bsr	UnVanishScreen
		movem.l	d2/d3/a6,-(sp)
		move.l	(IntBase,pc),a6
		jsr	(_LVOWBenchToFront,a6)
		move.l	(DosBase,pc),a6
		move.l	(PopStringPtr,pc),d1		;command string
		move.l	(nilhandle,pc),d2		;input
		move.l	d2,d3				;output
		jsr	(_LVOExecute,a6)
		movem.l	(sp)+,d2/d3/a6
		rts

*----------------------------------------------
WinToBack:	movem.l	a2/a6,-(sp)
		bsr	UnVanishScreen
		move.l	(IntBase,pc),a6
		move.l	(ib_FirstScreen,a6),a0
		moveq	#0,d0				;NO Single Windows
		bsr	SmartTWindow
		beq.b	.end

		move.l	d0,a0				;top window to back
		jsr	(_LVOWindowToBack,a6)
.end		movem.l	(sp)+,a2/a6
		rts

*----------------------------------------------
WinToFront:	bsr	UnVanishScreen
		move.l	a6,-(sp)
		move.l	(IntBase,pc),a6
		move.l	(ib_FirstScreen,a6),a0
		bsr	BottomWindow
		beq.b	.end

.check_next	move.l	d0,a0				;bottom window to front

*******		btst	#BACKDROP_B,(wd_Flags,a0)	;WHAT I MEAN
		btst	#BACKDROP_B-8,(wd_Flags+2,a0)	;what assembler wants
		beq.b	.tofront

		bsr	PrevWindow			;Cant move BackDrops
		beq.b	.end				;ran outa window layers.
		bra.b	.check_next

.tofront	jsr	(_LVOWindowToFront,a6)
.end		move.l	(sp)+,a6
		rts

*----------------------------------------------
SwapActiveWindow:
		bsr	UnVanishScreen
		movem.l	d2/d3/a6,-(sp)
		move.l	(IntBase,pc),a6

		move.l	(TaggedWindow,pc),d2
		beq.b	no_swap				;no tagged window

		cmp.l	(ib_ActiveWindow,a6),d2
		beq.b	no_swap				;tagged = current

		move.l	(TaggedScreen,pc),d3
		move.l	d2,a1				;old tagged window
		move.l	d3,a0				;old tagged screen
		bsr.b	ScrWinExists
		bne.b	SwapScrWin

		moveq	#0,d0				;somebody stole our window
		move.l	d0,(TaggedWindow-DT,a4)
		move.l	d0,(TaggedScreen-DT,a4)
		bra.b	no_swap

SwapScrWin:	move.l	(ib_ActiveWindow,a6),a0		;swap active to tagged
		move.l	a0,(TaggedWindow-DT,a4)
		move.l	(wd_WScreen,a0),(TaggedScreen-DT,a4)

		move.l	d3,a0				;Make old Tagged Active
		jsr	(_LVOScreenToFront,a6)

		move.l	d3,a0				;screen.
		bsr.b	NumberWindows
		cmp.b	#1,d0				; ? more than one window.
		bls.b	activate_only

		move.l	d2,a0
		jsr	(_LVOWindowToFront,a6)

activate_only:	move.l	d2,a0				;activate the window.
		jsr	(_LVOActivateWindow,a6)
no_swap:	movem.l	(sp)+,d2/d3/a6
		rts

*----------------------
* INPUTS:
* a0 - screen ptr.
* OUTPUTS:
* d0 - number windows on screen.
NumberWindows:	moveq	#0,d0				;Count of Windows
		move.l	(sc_FirstWindow,a0),d1		;first window
		beq.b	.end

		addq	#1,d0				;OK got first window
.nextwindow:	move.l	d1,a0
		move.l	(wd_NextWindow,a0),d1
		beq.b	.end

		addq	#1,d0
		bra.b	.nextwindow
.end		tst.l	d0				;set Z flag on count.
		rts

*
* INPUTS:
* a0 - old screen pointer
* a1 - old window pointer ( window was on the old screen pointer )
* a6 - assumed is intuition Base. ( INTBase )
*
* OUTPUTS:
* d0 - boolean ( FALSE = 0 ) also Z flag set on exit
*      False if the old screen & window no longer exist in system.
*
ScrWinExists:	move.l	a2,-(sp)
		move.l	(ib_FirstScreen,a6),a2

.nextscreen:	cmp.l	a0,a2				; ? the old screen
		beq.b	.CheckWindow			;found Screen

		move.l	(sc_NextScreen,a2),d0
		beq.b	.dontexist
		move.l	d0,a2
		bra.b	.nextscreen

.CheckWindow:	move.l	(sc_FirstWindow,a2),a2
.nextwindow:	cmp.l	a2,a1				; ? the old window
		beq.b	.exist				;found window

		move.l	(wd_NextWindow,a2),d0
		beq.b	.dontexist
		move.l	d0,a2
		bra.b	.nextwindow

.exist:		moveq	#1,d0
.dontexist:	move.l	(sp)+,a2
		rts

*
* Totaly black out the display
*
VanishScreen:	move.w	#DMAF_RASTER|DMAF_COPPER,(dmacon,a3)	;Clear em.
		move.w	#0,(color,a3)				;BLACK
		rts

*
* Restore visual display.
* NOTE this is currently visually jarring, add wait for Beam Position.
*
UnVanishScreen:
.wait_high:	btst	#0,(vposr+1,a3)		;highest order bit of V beam pos
		beq.b	.wait_high
.wait_low:	btst	#0,(vposr+1,a3)		;highest order bit of V beam pos
		bne.b	.wait_low
		move.w	#DMAF_SETCLR|DMAF_RASTER|DMAF_COPPER,(dmacon,a3)
		rts

*
* Smart TopWindow.
*
* Does not return address if only one window on the front screen, unless
* d0.l input is FALSE.
*
* There is an exception to this rule, if the one window is called
* 'Uedit V'.etc then the address of this window is returned anyway
* as this allows access to the screens Drag bar and front back
* gadgets (dont know why yet) but I love this "accidental" feature.
*
* INPUTS:
* a0.l - screen on which we want the front window pointer.
* d0.l - Boolean, if TRUE a single window on a screen
*        is considered 'important' and its address is returned.
*
* OUTPUTS:
* d0.l - address of front window.
*
* USES:
* d2.l - address of current window
* d3.l - flag single window important
*
Title.MSG	db	'Uedit V'
Title.END	db	0			;NULL end string
TITLE_SIZE	equ	Title.END-Title.MSG
		cnop	0,2

SmartTWindow:	movem.l	d2/d3,-(sp)
		move.l	d0,d3			;FLAG single window important
		bsr.b	TopWindow
		beq.b	.end			;NO windows bye bye

.CheckNext	move.l	d0,d2			;save Top Window
		move.l	d0,a0
		bsr	NextWindow
		bne.b	.checkheight		;not the only window 

						;SINGLE WINDOW ON SCREEN
		tst.l	d3			;single window important
		bne.b	.thiswin		;YES

		move.l	d2,a0			;only one window on screen,
		move.l	(wd_Title,a0),a0	;now check if the name
		lea	(Title.MSG,pc),a1	;starts with the
		moveq	#TITLE_SIZE-1,d0	;string 'Uedit V'.
.CompareName	cmp.b	(a0)+,(a1)+
		dbne	d0,.CompareName

		tst.b	(a1)			;match whole string
		beq.b	.thiswin		;OK Uedit Window Pass Out
		moveq	#0,d0
		bra.b	.end

.checkheight	move.l	d2,a0			;TopWindow
		cmp.w	#12,(wd_Height,a0)
		bhs.b	.thiswin		;Window Height > 12
						;a0 - current window
		bsr	NextWindow		;Check Next Window
		move.l	d0,d2			;save window address.
		bne.b	.checkheight

.thiswin	move.l	d2,d0
.end		movem.l	(sp)+,d2/d3
		rts

*
* Find the top window on the given screen.
*
* INPUTS:
* a0.l - screen on which we want the front window pointer.
*
* OUTPUTS:
* d0.l - address of front window. ( Null if no window )
*
* USES:
* a1.l - current layer address
*
TopWindow:	move.l	(sc_LayerInfo+li_top_layer,a0),d0 ;first screen layer
		beq.b	.end

.nextlayer	move.l	d0,a1
		move.l	(lr_Window,a1),d0		;?is window
		bne.b	.end				;YES got front window

		move.l	(lr_back,a1),d0			;look next layer
		bne.b	.nextlayer			;check next layer

.end		rts

*
* Find the bottom window on the given screen.
*
* INPUTS:
* a0.l - screen on which we want the bottom window pointer.
*
* OUTPUTS:
* d0.l - address of bottom window. ( Null if no window )
*        SETS Z flag as neccessary
*
* USES:
* a1.l - current layer address
* d1.l - the bottom window so far found
*
BottomWindow:	moveq	#0,d1				;init no window
		move.l	(sc_LayerInfo+li_top_layer,a0),d0 ;first screen layer
		beq.b	.end

.nextlayer	move.l	d0,a1
		tst.l	(lr_Window,a1)			;? is window
		beq.b	.notwin

		move.l	(lr_Window,a1),d1		; save window

.notwin		move.l	(lr_back,a1),d0			;look next layer
		bne.b	.nextlayer			;check next layer

		move.l	d1,d0				;bottom window
.end		rts

*
* INPUTS:
* a0.l - address of window
*
* OUTPUTS:
* d0.l - address of the next window behind this one. NULL if no more.
*
* USES:
* a1.l - layer address
*
NextWindow:	move.l	(wd_WLayer,a0),a0
		move.l	(lr_back,a0),d0			;check next layer
		beq.b	.end				;NO more layers

.iswindow	move.l	d0,a0
		move.l	(lr_Window,a0),d0		;? next layer window
		bne.b	.end				;YES next window

		move.l	(lr_back,a0),d0
		bne.b	.iswindow

.end		rts

*
* INPUTS:
* a0.l - address of window
*
* OUTPUTS:
* d0.l - address of the previous window directly in front of this one.
*      NULL if no previous window
*
* USES:
* a1.l - layer address
*
PrevWindow:	move.l	(wd_WLayer,a0),a0
		move.l	(lr_front,a0),d0		;check prev layer
		beq.b	.end

.iswindow	move.l	d0,a0
		move.l	(lr_Window,a0),d0		;? prev layer window
		bne.b	.end				;YES prev window

		move.l	(lr_front,a0),d0
		bne.b	.iswindow

.end		rts

******************************************************** InputHandler *********
* InputHandler
*
* The shiftcount and timecount are both reset for any event encountered
* except for timer events, and left shift keys.
*
* Key up events are totally ignored.
*
* INPUTS:
* a0.l - input event (SYSTEM)
* a1.l - relative data base (SYSTEM)
*
* OUTPUTS:
* d0.l - input event after processing (SYSTEM)
*
* USES:
* d0.b - input event class
* d2.w - the key qualifier for the current event if it is a raw key.
* d3.w - shftcount
* a2.l - address of input event
*
InputHandler	movem.l	d2/d3/a2/a4,-(sp)
		move.l	a1,a4				;regular data base reg
		move.w	(shftcount-DT,a4),d3
		move.l	(4).w,a6
		moveq	#0,d0
		move.l	a0,a2				;input event ptr
		move.l	a0,-(sp)			;save event ptr for later

.process_event	move.b	(ie_Class,a2),d0
		cmp.b	#IECLASS_TIMER,d0
		bne.b	.ih_caserawkey

.ih_timer	sub.w	#1,(timecount-DT,a4)
		bne.b	.ih_end

		moveq	#0,d3				;FLAG blanked screen
.ih_smartvan	move.w	d3,(shftcount-DT,a4)
		bne.b	.ih_end

		moveq	#BLANK,D0
		bra.b	.ih_signalproc			;dont reset state

.ih_caserawkey	cmp.b	#IECLASS_RAWKEY,d0
		beq.b	.ih_rawkey

.ih_smartunvan	move.w	(timeout,pc),(timecount-DT,a4)	;reset state
		move.w	#SHFTOUT,(shftcount-DT,a4)
		tst.w	d3				;? screen ON
		bgt	.ih_end
		moveq	#UNBLANK,d0

.ih_signalproc	move.w	d0,(ihevent-DT,a4)
		move.l	(VanishProcess,pc),a1
		move.l	(ihsignal,pc),d0
		jsr	(_LVOSignal,a6)
.ih_end
		move.l	(ie_NextEvent,a2),d0		; ? any more events
		beq.s	.done_chain
		move.l	d0,a2
		bra.b	.process_event			;process next event

.done_chain	move.l	(sp)+,d0			;input event output ptr
		movem.l	(sp)+,d2/d3/a2/a4
		rts


******************************************************** raw key handler ****
.ih_rawkey	move.b	(ie_Code+1,a2),d0
		bmi.b	.ih_end				;IECODEB_UP_PREFIX

		move.w	(ie_Qualifier,a2),d2
		bclr	#IEQUALIFIERB_CAPSLOCK,d2	;ignore capslock state
		cmp.b	#IEQUALIFIER_LSHIFT,d2
		bne.b	.ih_rkcaseLA1

		cmp.b	#rk_leftshift,d0
		bne.b	.ih_smartunvan

.ih_gotlshift	subq.w	#1,d3				;decrease shift count
		bmi.b	.ih_end

		bra.b	.ih_smartvan

.ih_rkcaseLA1	cmp.b	(command_qualifier+1,pc),d2	;? command qualifier
		bne.b	.ih_smartunvan

******************************************************** Command Handler ****
		lea	(IH_table,pc),a0
		move.b	(0,a0,d0.w),d0			;get action
		beq.b	.ih_smartunvan			;non event skip it.

		btst	#IEQUALIFIERB_REPEAT,d2		;is this repeat
		bne.b	.eat_event			;ZAP if repeat

.check_escape:	tst.b	(escapekey-DT,a4)		;Check if escaped Key
		beq.b	.ih_use_command

		moveq	#0,d0
		move.b	d0,(escapekey-DT,a4)		;used up escape
		bra.b	.ih_smartunvan			;pass on this key.

.eat_event:	moveq	#0,d0
		move.b	d0,(ie_Class,a2)		; ZAP event IECLASS_NULL
		bra.b	.ih_smartunvan

.ih_use_command:
		moveq	#IECLASS_NULL,d1		;just any register
		move.b	d1,(ie_Class,a2)		;clobber input event
		move.w	(timeout,pc),(timecount-DT,a4)	;reset state
		move.w	#SHFTOUT,(shftcount-DT,a4)
		bra.b	.ih_signalproc

*
* Lookup table to see what LeftAmiga-(code) keys do
* length table = 0-127 as we are ignoring keyupstrokes.
* LeftAmiga function look up table. RawKey Lookup table
*
IH_table	db	NEWCLI		; $00; rk_opensinglequote
		db	0		; $01; rk_1
		db	0		; $02; rk_2
		db	0		; $03; rk_3
		db	0		; $04; rk_4
		db	0		; $05; rk_5
		db	0		; $06; rk_6
		db	0		; $07; rk_7
		db	0		; $08; rk_8
		db	0		; $09; rk_9
		db	0		; $0A; rk_0
		db	0		; $0B; rk_minus
		db	0		; $0C; rk_equals
		db	0		; $0D; rk_backslash
		db	0		; $0E;
		db	0		; $0F; rk_kp0
		db	0		; $10; rk_q
		db	0 ; removed WBTOFRONT	; $11; rk_w
		db	0		; $12; rk_e
		db	0		; $13; rk_r
		db	TAGWINDOW	; $14; rk_t
		db	0		; $15; rk_y
		db	0		; $16; rk_u
		db	0		; $17; rk_i
		db	0		; $18; rk_o
		db	0		; $19; rk_p
		db	0		; $1A; rk_opensqrbracket
		db	0		; $1B; rk_closesqrbracket
		db	0		; $1C;
		db	0		; $1D; rk_kp1
		db	0		; $1E; rk_kp2
		db	0		; $1F; rk_kp3
		db	ACTIVATE_FWIN	; $20; rk_a
		db	0		; $21; rk_s
		db	0		; $22; rk_d
		db	0		; $23; rk_f
		db	0		; $24; rk_g
		db	0		; $25; rk_h
		db	WINDOWTOFRONT	; $26; rk_j
		db	WINDOWTOBACK	; $27; rk_k
		db	0		; $28; rk_l
		db	0		; $29; rk_semicolon
		db	0		; $2A; rk_closesinglequote
		db	0		; $2B; rk_return
		db	0		; $2C;
		db	0		; $2D; rk_kp4
		db	0		; $2E; rk_kp5
		db	0		; $2F; rk_kp6
		db	0		; $30;
		db	SWAPACTIVEWIN	; $31; rk_z
		db	0		; $32; rk_x
		db	0		; $33; rk_c
		db	0		; $34; rk_v
		db	0		; $35; rk_b
		db	SCREENTOFRONT	; $36; rk_n
		db	SCREENTOBACK	; $37; rk_m
		db	0		; $38; rk_comma
		db	0		; $39; rk_fullstop
		db	0		; $3A
		db	0		; $3B
		db	0		; $3C; rk_kpdot
		db	0		; $3D;
		db	0		; $3E; rk_capslock
		db	0		; $3F
		db	0		; $40; rk_space
		db	0		; $41; rk_backspace
		db	0		; $42; rk_tab
		db	0		; $43; rk_kpenter
		db	0		; $44;
		db	0		; $45; rk_esc
		db	ESCAPE_NEXT	; $46; rk_del
		db	0		; $47
		db	0		; $48
		db	0		; $49
		db	0		; $4A; rk_kpminus
		db	0		; $4B
		db	0		; $4C; rk_uparrow
		db	0		; $4D; rk_downarrow
		db	0		; $4E; rk_rightarrow
		db	0		; $4F; rk_leftarrow
		db	0		; $50; rk_F1
		db	0		; $51; rk_F2
		db	0		; $52; rk_F3
		db	0		; $53; rk_F4
		db	0		; $54; rk_F5
		db	0		; $55; rk_F6
		db	0		; $56; rk_F7
		db	0		; $57; rk_F8
		db	0		; $58; rk_F9
		db	0		; $59; rk_F10
		db	0		; $5A
		db	0		; $5B
		db	0		; $5C
		db	0		; $5D
		db	0		; $5E
		db	0		; $5F; rk_help
		db	0		; $60; rk_leftshift
		db	0		; $61; rk_rightshift
		db	0		; $62
		db	0		; $63; rk_ctl
		db	0		; $64; rk_leftalt
		db	0		; $65; rk_rightalt
		db	0		; $66; rk_leftamiga
		db	0		; $67; rk_rightamiga

******************************************************** Install IH handler ***
* INPUTS:
* a0.l - interrupt structure with CODE, PRIORITY and DATA fields filled in.
* a6.l - ExecBase
*
* OUTPUTS:
* d0.l - ZERO return is success.
*
* INDIRECT OUTPUTS:
* input_Port, input_IOReq, ihsignal, ihsignum, IPort_name.MSG
*
InstallInputHandler:
		movem.l	d2/a5,-(sp)
		movea.l	a0,a5				;save input struc address

		moveq	#0,d0				;priority
		lea	(IPort_name.MSG,pc),a0		;name
		bsr	CreatePort
		move.l	d0,(input_Port-DT,a4)		;? got port Message Port
		beq	TOTALFAIL

		movea.l	d0,a0				; GET IO REQUEST
		moveq	#IOSTD_SIZE,d0
		bsr	CreateIOReq
		move.l	d0,(input_IOReq-DT,a4)		;? got IO request
		move.l	d0,d2				;save IORequest.
		beq.b	KillPort
							; OPEN INPUT DEVICE
		lea	(input.device.MSG,pc),a0	;input device name
		movea.l	d0,a1				;input request block
		moveq	#0,d0				;unit number
		moveq	#0,d1				;device flags
		jsr	(_LVOOpenDevice,a6)
		tst.l	d0
		bne.b	KillIOReq

		moveq	#-1,d0
		jsr	(_LVOAllocSignal,a6)		;input handler signal
		cmp.b	#$ff,d0
		beq.b	KillDevice

		moveq	#0,d1
		bset	d0,d1
		move.l	d1,(ihsignal-DT,a4)
		move.b	d0,(ihsignum-DT,a4)
							;INSTALL INPUT HANDLER.
		move.l	d2,a1				;IORequest
		move.w	#IND_ADDHANDLER,(IO_COMMAND,a1)	;IO Req Block struct
		move.l	a5,(IO_DATA,a1)			;install interrupt struc
		jsr	(_LVODoIO,a6)
		tst.l	d0
		bne.b	FreeIHsignal

.end		movem.l	(sp)+,d2/a5
		rts

******************************************************** Remove IH handler ****
* INPUTS:
* a0 - input structure for input handler to remove.
* a6 - Exec Base
*
* INDIRECT INPUTS:
* input_IOReq, ihsignal, input_Port
RemoveInputHandler:
		move.l	(input_IOReq,pc),a1
		move.l	a0,(IO_DATA,a1)
		move.w	#IND_REMHANDLER,(IO_COMMAND,a1)
		jsr	(_LVODoIO,a6)			;remove Input Handler

FreeIHsignal:	move.l	d7,d0
		jsr	(_LVOFreeSignal,a6)

KillDevice:	move.l	(input_IOReq,pc),a1
		jsr	(_LVOCloseDevice,a6)

KillIOReq:	moveq	#IOSTD_SIZE,d0
		move.l	(input_IOReq,pc),a0
		bsr	DeleteIOReq

KillPort:	move.l	(input_Port,pc),a0
		bsr	DeletePort

TOTALFAIL:	moveq	#1,d0				;Return NON-ZERO fail.
							;return only counts 
		rts					;for InstallInputHandler


******************************************************** CreatePort ***********
* INPUTS:
* a0.l - optional name string for port
* d0.l - priority of message port
* a6.l - ExecBase
*
* OUTPUTS:
* d0.b - addr of initialised message port
*
CreatePort	movem.l	d6/d7/a2/a3,-(sp)
		move.l	a0,a2
		move.l	d0,d7
		moveq	#-1,d0
		jsr	(_LVOAllocSignal,a6)
		cmp.b	#-1,d0
		beq.b	.cpnosignal

		move.l	d0,d6
		moveq	#MP_SIZE,d0
		bsr	AllocMemCP
		beq.b	.cpfreesignal

		move.l	d0,a3
		move.b	#MP_SIGTASK,(MP_FLAGS,a3)	;MP_SIGTASK=0
		move.b	d6,(MP_SIGBIT,a3)
		move.l	(ThisTask,a6),(MP_SIGTASK,a3)
		move.b	d7,(LN_PRI,a3)
		move.b	#NT_MSGPORT,(LN_TYPE,a3)
		move.l	a2,(LN_NAME,a3)
		beq.b	.cpanonport

		move.l	a3,a1
		jsr	(_LVOAddPort,a6)
		bra.b	.cpreturn

.cpanonport	lea	(MP_MSGLIST,a3),a0
		NEWLIST a0

		move.b	#NT_INTERRUPT,(LH_TYPE,a0)
		bra.b	.cpreturn

.cpfreesignal	move.l	d6,d0
		jsr	(_LVOFreeSignal,a6)
.cpnosignal	move.l	#0,a3
.cpreturn	move.l	a3,d0
.cpend		movem.l	(sp)+,d6/d7/a2/a3
		rts

******************************************************** DeletePort ***********
* INPUTS:
* a0.l - address of message port to delete		
* a6.l - ExecBase
*
DeletePort	move.l	a2,-(sp)
		move.l	a0,a2
		tst.l	(LN_NAME,a2)
		beq.b	.dpfreesignal

		move.l	a2,a1
		jsr	(_LVORemPort,a6)

.dpfreesignal	moveq	#0,d0
		move.b	(MP_SIGBIT,a2),d0
		jsr	(_LVOFreeSignal,a6)
		moveq	#MP_SIZE,d0
		move.l	a2,a1
		jsr	(_LVOFreeMem,a6)
		move.l	(sp)+,a2
		rts

******************************************************** CreateIOReq **********
* INPUTS:
* d0.l - size of the IO request
* a0.l - reply port for this IO request
* a6.l - ExecBase
*
* OUTPUTS:
* d0.l - addr of intialised IO request. ( or null )
*
CreateIOReq	movem.l	d2/a2,-(sp)
		move.l	a0,a2
		move.l	d0,d2
		bsr	AllocMemCP
		beq.b	.ceioend

		move.l	d0,a1
		move.b	#NT_MESSAGE,(LN_TYPE,a1)
		clr.b	(LN_PRI,a1)
		move.l	d2,(MN_LENGTH,a1)
		move.l	a2,(MN_REPLYPORT,a1)
.ceioend	movem.l	(sp)+,d2/a2
		rts

******************************************************** DeleteIOReq **********
* INPUTS:
* d0.l - size of IO request to free
* a0.l - address of IO request to free
* a6.l - ExecBase
*
DeleteIOReq	move.l	a0,a1
		jsr	(_LVOFreeMem,a6)
		rts

******************************************************** ExtractArgs **********
* ExtractArgs
*
* Extracts two parameters from command line
* "Usage: van [switches] [command string]
*
* Any switches must precede the command string.
*
* -qxxxx  : use 'xxxx' as qualifier for all commands
*           note 'xxxx' is the hexadecimal qualifier.
* -e      : make popcli command key be  QUALIFIER-ESC
* -txxxxx : xxxxx is number seconds inactive to blank
*
*
* INPUTS:
* a0.l - cli command line pointer
* d0.l - length of cli command line
*
* OUTPUTS:
* d0.l - 0 if success. ( Z flag is set )
*      - 1 if fail ( Z flag not set )
*
* USES
* d2.l - count of number of args left to parse
* d3.l - the timeout to be used
* d4.l - address of command string
* a2.l - ptr to current position in argv.
* a3.l - ptr to current word being examined
*
ExtractArgs:
		movem.l	d2-d4/a2/a3,-(sp)
		moveq	#TIMEOUT,d3		;Set Default Values
		move.l	#PopString.MSG,d4	;initially

		lea	(-16,sp),sp		;stack space for arg ptrs
		clr.b	(-1,a0,d0.w)		;null end CLI args
		moveq	#4,d0			;space for 4 arguments
		move.l	sp,a1			;argv buffer
		bsr	WordStr
		beq.b	SetVals			;Use default values

		tst.b	(a0)			;any unparsed CLI string
		bne	NoInstall		;to many words

		move.l	d0,d2			;save number words found
		move.l	sp,a2			;current argv position

		move.l	(a2),a3
		cmpi.b	#'?',(a3)		;Help ?
		bne.b	NextArgument

************************************************ Output Help Message ********
		bsr	OpenDOSLib
		beq.b	NoInstall		;who cares at this point.
		move.l	d0,a6			;DOS base

		lea	(Help.MSG,pc),a0
		move.l	#SIZEHELP,d0
		bsr	OnceOffMessage

		move.l	a6,a1
		move.l	(4).w,a6
		move.l	(DosBase,pc),a1
		jsr	(_LVOCloseLibrary,a6)
		bra.b	NoInstall

************************************************ Process Install Args *******
NextArgument:
		subq.l	#1,d2			;used one more argument
		bmi.b	SetVals			;All arguments parsed split.

		move.l	(a2)+,a3		;get word ptr
		cmp.b	#'-',(a3)
		bne.b	command_arg

************************************************ Got A switch *****************
		cmp.b	#'q',(1,a3)
		beq	qualifier_key
		cmp.b	#'e',(1,a3)
		beq	popcli_key
		cmp.b	#'t',(1,a3)
		beq	time_arg
		bra	NoInstall		;switch illegal dont install

* NOTE: assume all switch args appear before Command Arg.
command_arg:	subq.l	#1,d2			;use this arg for command
		bgt	NoInstall		;if more args ERROR
		move.l	a3,d4			;setup argument string

SetVals		move.l	d4,(PopStringPtr-DT,a4)	;set defaults
		mulu.w	#TICKSPERSEC,d3
		move.w	d3,(timeout-DT,a4)
		move	#0,d0			;ALL OK flag install

ba_end		lea	(16,sp),sp		;restore stack
		movem.l	(sp)+,d2-d4/a2/a3
		rts

NoInstall	moveq	#1,d0
		bra.b	ba_end

*
* Time out argument got switch '-t'
*
time_arg:
		addq	#2,a3			;skip past '-t'
		move.l	a3,a0
		bsr.b	atoi			;Value of timeout
		tst.b	(a0)			;? see if all number
		bne.b	NoInstall		;Not all number Error.

		cmp.w	#MIN_TIME,d0		;Low bound check time interval.
		blo.b	NoInstall
		move.l	d0,d3			;OK set this as TIME arg
		bra.b	NextArgument

*
* Got switch -q
* INPUTS:
* a2 - ptr to string witch points at q in switch
qualifier_key:
		addq	#2,a3			;skip past '-q'
		move.l	a3,a0
		bsr	xtoi			;NOTE this is restricted version
		tst.b	(a0)			;any remaining characters
		bne.b	NoInstall

		move.w	d0,(command_qualifier-DT,a4)
		bra.b	NextArgument

*
* Got switch input -e
*
* Change which key executes the given command.
*
popcli_key:
		lea	(IH_table,pc),a0
		move.b	#INVALID,(rk_opensinglequote,a0)
		move.b	#NEWCLI,(rk_esc,a0)
		bra	NextArgument

******************************************************** xtoi *****************
* INPUTS:
* a0.l - address of ascii number string.
*
* OUTPUTS:
* d0.l - long word value of ascii string
* a0.l - point at first unused char
*
xtoi:
		move.l	d3,-(sp)
		moveq	#0,d0			;converted number
		moveq	#0,d1			;get char variable
		moveq	#4-1,d3			;only look at 4 digits

.nextchar	move.b	(a0)+,d1		;get next char

		cmp.b	#'9',d1
		bhi.b	.check_A_F		;check 'a'..'f' if d1 > '9'

		sub.b	#'0',d1			;d1-'0' convert to number
		bmi.b	.not_hex

		bra.s	.got_hex

.check_A_F:	cmp.b	#'F',d1
		bhi.s	.check_a_f		;go check lower case hex

		sub.b	#'A',d1
		bmi.s	.not_hex
		bra.s	.got_hex

.check_a_f:	cmp.b	#'f',d1
		bhi.s	.not_hex

		sub.b	#'a',d1
		bmi.s	.not_hex

.got_hex:	lsl.l	#4,d0
		add.b	d1,d0
		dbf	d3,.nextchar
		bra.b	.end

.not_hex:	subq	#1,a0			;point at char we stopped on.
.end		move.l	(sp)+,d3
		rts

******************************************************** atoi *****************
* Decimal ascii string conversion to word binary format.
* Only looks at 5 decimal digits.
*
* INPUTS:
* a0.l - address of ascii number string.
*
* OUTPUTS:
* d0.l - long word value of ascii string
* a0.l - point at first unused char
*
* USES:
* d0.l - the converted value
* d1.b - character under scrutiny
* d2.l - temp for mul 10
* d3.b - constant ascii '0'
*
* NOTES:
* assumes got valid chars
*
atoi:		movem.l	d2/d3,-(sp)
		moveq	#0,d0			;converted number
		moveq	#0,d1			;get char var
		moveq	#5-1,d3			;only look at 5 digits

.nextchar	move.b	(a0)+,d1		;get next char

		cmp.b	#'9',d1
		bhi.b	.not_dec		;exit d1 > '9'

		sub.b	#'0',d1			;d1-'0' convert to number
		bmi.b	.not_dec		;exit d1 < '0'

* MULTIPLY long by 10.
		add.l	d0,d0			;*2
		move.l	d0,d2
		add.l	d0,d0			;*4
		add.l	d0,d0			;*8
		add.l	d2,d0			;*2 + *8 = *10
		add.l	d1,d0			;add on decimal digit

		dbra	d3,.nextchar
		bra.b	.end

.not_dec	subq	#1,a0			;point at char we stopped on.
.end		movem.l	(sp)+,d2/d3
		rts

******************************************************** WordStr **************
* WordStr
*
* Takes input string and breaks it up into words with Null seperators.
* Each word gets a pointer to it in the input char ptr array.
* Words are delimited by white spaces or by Matching Quotes.
* White Space = ascii SPACE or less.
*
* example:	'"fred"' "fred's ".
*	word 1 = ("fred")
*	word 2 = (fred's)
*
* One really nice thing I like is if you only put in leading quote it will
* recognise the whole line spaces and all as one Word.
*
* INPUTS:
* d0.w - number of places in *argv[].
* a0.l - ptr to C string ( ie null ended )
* a1.l - *argv[] - array of char ptrs to words in string. Is Filled in.
*
* OUTPUTS:
* d0.l - number words found
* a0.l - remaining ptr of string. NULL if all fitted in *argv[] array.
*
* USES:
* d0.w - count of remaining spaces in argv array
* d1.l - current word delimiting character
* d2.l - word count
*
* a0.l - current character upto in string
* a1.l - current save word location in argv array ( NOT really useful )
*
* RETURNS
* Equal condition code set on exit for number of words
*
WordStr:	moveq	#0,d2			;Word count = 0
		bra.b	NextWord		;Start Loop

SkipWSpace:	tst.b	(a0)			;? any string left
		beq.b	EndStr

		cmp.b	#' ',(a0)+		;skip lead white space
		bls.b	SkipWSpace		; a0 <= SPACE

		move.b	(-1,a0),d1		;Get start of this word
		cmp.b	#'"',d1			;quote type 1 (")
		beq.b	KillQuote

		cmp.b	#'''',d1		;quote type 2 (')
		beq.b	KillQuote

		move.b	#' ',d1			;SPACE is word delimiter.
		lea	(-1,a0),a0		;repair overshoot
		bra.b	SaveWord		;OK got next word

KillQuote:	clr.b	(-1,a0)			;clobber Quote
SaveWord:	move.l	a0,(a1)+		;save ptr to word
		addq	#1,d2			;count words
SkipWord:	tst.b	(a0)			;? any string left
		beq.b	EndStr

		cmp.b	(a0)+,d1		;find end of this word
		bne.b	SkipWord		;Next Char

ClrSeperator:	clr.b	(-1,a0)			; NULL seperate words
NextWord:	dbra	d0,SkipWSpace

EndStr:		move.l	d2,d0			;return number words
		rts

******************************************************** AllocMemCP ***********
* Allocate Clear Public Memory
*
* INPUTS:
* d0 - size of mem to allocate 
* a6 - ExecBase
*
* OUTPUTS:
* d0 - address of memory. With Condition tested
*
AllocMemCP:	move.l	#(MEMF_PUBLIC|MEMF_CLEAR),d1
		jsr	(_LVOAllocMem,a6)		;get message mem
		tst.l	d0
		rts

******************************************************** Open Lib Stuff ********
* Open Lib routines expect a6 = Exec Base
*
OpenINTLib:	moveq	#32,d0
		lea	(intname.MSG,pc),a1
		jsr	(_LVOOpenLibrary,a6)
		move.l	d0,(IntBase-DT,a4)
		rts
OpenDOSLib:	moveq	#32,d0
		lea	(dosname.MSG,pc),a1
		jsr	(_LVOOpenLibrary,a6)
		move.l	d0,(DosBase-DT,a4)		;Hello Library
		rts

******************************************************** OnceOffMesage *********
* INPUTS:
* d0 - length of string to output
* a0 - string to output
* a6 - DOSBase
*
* OUTPUTS:
* d0 - 0 if FAIL ( not Z flag also set )
*
OnceOffMessage:
		movem.l	d2-d3/d7/a5,-(sp)
		
		move.l	d0,d7				;save length string
		movea.l	a0,a5				;save string pointer
		move.l	#Asterix.MSG,d1
		move.l	#MODE_OLDFILE,d2
		jsr	(_LVOOpen,a6)			;cli CLI handle
		tst.l	d0
		beq.b	.end

		move.l	d0,d4
		move.l	d0,d1
		move.l	a5,d2				;message
		move.l	d7,d3				;length of message
		jsr	(_LVOWrite,a6)			;spit it out

		move.l	d4,d1
		jsr	(_LVOClose,a6)			;close CLI handle
		moveq	#1,d0				; ALL OK.
.end		movem.l	(sp)+,d2-d3/d7/a5
		rts

*
* Data Area
*
Asterix.MSG	db	'*',0
nilname.MSG	db	'nil:',0
dosname.MSG	db	'dos.library',0
intname.MSG	db	'intuition.library',0
input.device.MSG db	'input.device',0
IPort_name.MSG	db	'Vanish-IPort',0
PopString.MSG	db	'newcli',0
		cnop	0,2

DXSPACE
command_qualifier:
		dx.w	1		;command key qualifier
timeout:	dx.w	1			;timeout interval value
TaggedWindow:	dx.l	1
TaggedScreen:	dx.l	1
PopStringPtr:	dx.l	1			;ptr to command
timecount:	dx.w	1			;timer tick count
shftcount:	dx.w	1			;lshift count
nilhandle:	dx.l	1
DosBase:	dx.l	1
IntBase:	dx.l	1
input_int:	dx.b	IS_SIZE			;input handler interrupt
input_Port:	dx.l	1
input_IOReq:	dx.l	1
VanishProcess:	dx.l	1

ihsignal:	dx.l	1
ihevent:	dx.w	1

ihsignum:	dx.b	1
escapekey:	dx.b	1
		dx.b	1			;padding.
		dx.b	1

ENDDX
		END
