; This here code is for a process started up by CLImax which has the job of
; actually carrying out the creation of the new CLI process and then waiting
; for it to finish and then closing the screen it used.
;
; Written for the Manx assembler, hopefully
; portable.  Use the -n flag for one-pass assembly.  Link with the +a flag.
;
; This code is incorporated into the program CLImax, which then copies it into
; an allocated block of public memory.  It copies everything found between
; the two symbols _beginning and _ending.  The new process adds this area of
; memory into its tc_MemEntry list for automatic cleanup.


		xdef		_beginning
		xdef		_ending
		xdef		_StuffOffs
		xdef		_CommandOffs
		xdef		_CloseStuff
		xdef		_NameOffs
		xdef		_FakeOffs

		nolist
		  include 	"exec/types.i"  	; nobody pulls this in!
		  include 	"exec/memory.i"
		  include 	"exec/tasks.i"
		  include 	"exec/execbase.i"
		  include 	"intuition/screens.i"
		  include	"libraries/dosextens.i"
		  include	"libraries/dos_lib.i"
		list

		STRUCTURE	stufff,0
		  CPTR		ibase
		  CPTR		gbase
		  CPTR		dosbase
		  CPTR		fawnt
		  CPTR		scr
		  CPTR		win
		  BPTR		wandle
		  BPTR		ceedee
		LABEL		stuffsize


stuf		equr		a5		; the stuff struct
clap		equr		a4		; our struct CLI
me		equr		a3		; FindTask(null)
mist		equr		a2		; tc_MemEntry addition
pathlist	equr		d7		; the command path bptr-list

memlistsize	equ		ML_SIZE+ME_SIZE		; size of MemList
							;   with one MemEntry
codesize	equ		8+_ending-_beginning	; size of our "seglist"


; I'm getting my _LVO symbol definitions from Manx c.lib; I don't know where
; you get yours.
;;;; AAAAAAGH!  As of Aztec 5.0d1, all of a sudden c.lib has INCORRECT VALUES
;;;; for the _LVO symbols for dos.library!  They're POSITIVE!!  So, we get the
;;;; correct values from libraries/dos_lib.i and check here:

lcall:  	macro				; call whatever library is in a6
		ifd		_LVO\1
		else
		  xref		_LVO\1  	; (few dublications)
		endc
		jsr		_LVO\1(a6)
		endm


xcall:  	macro			; make an exec library call
		move.l 		4,a6
		lcall		\1
		endm

		cseg
		cnop		0,4	; USE LN'S +A OPTION to make this work


; ============================ The first word copied is also the entry point:

_beginning:	lea		stuff(pc),stuf
		sub.l		a1,a1
		xcall		FindTask
		move.l		d0,me
		move.l  	#MEMF_PUBLIC|MEMF_CLEAR,d1
		move.l  	#memlistsize,d0
		xcall		AllocMem	; make a MemList with one entry
		move.l  	d0,mist
		tst.l		d0
		beq		DOit(pc)	; low ram? then we'll lose more!
						; (this code won't deallocate)
		  move.l  	#codesize,ML_ME+ME_LENGTH(mist)
		  lea		_beginning(pc),a0
		  moveq		#8,d0
		  sub.l		d0,a0
		  move.l  	a0,ML_ME+ME_ADDR(mist)
		  move.w  	#1,ML_NUMENTRIES(mist)  ; the memlist points
		  lea		TC_MEMENTRY(me),a0	;   to our code
		  move.l  	mist,a1
		  lcall		AddTail 	; plug in where RemTask looks.

DOit:		move.l		wandle(stuf),d0
		asl.l		#2,d0
		move.l		d0,a0
		move.l		fh_Type(a0),pr_ConsoleTask(me)
		move.l		win(stuf),pr_WindowPtr(me)
		move.l		ceedee(stuf),pr_CurrentDir(me)
		lea		fakli(pc),a0
		move.l		a0,d0
		asr.l		#2,d0
		move.l		d0,pr_CLI(me)

		move.l		dosbase(stuf),a6
		moveq		#0,d3
		move.l		wandle(stuf),d2
		lea		command(pc),a0
		move.l		a0,d1
		lcall		Execute				; TA DA!

		move.l		wandle(stuf),d1
		lcall		Close

		clr.l		pr_CLI(me)
		lea		fakli(pc),clap
		move.l		pr_CurrentDir(me),d1
		beq		nounlock(pc)
		  lcall		UnLock
		  clr.l		pr_CurrentDir(me)
nounlock:	move.l		cli_CommandDir(clap),pathlist
		asl.l		#2,pathlist
		beq		die(pc)

getapode:	  move.l	pathlist,a2
		  move.l	(a2),pathlist		; bptr to next
		  move.l	4(a2),d1		; lock
		  beq		nounlick(pc)
		    move.l	dosbase(stuf),a6
		    lcall	UnLock
nounlick:	  move.l	a2,a1
		  moveq		#8,d0
		  xcall		FreeMem
		  asl.l		#2,pathlist
		  bne		getapode(pc)

die:		move.l		stuf,-(sp)		; C style parm
		bsr		_CloseStuff
		addq		#4,sp
		moveq		#0,d1
		move.l		dosbase(stuf),a6
		lcall		Exit			; bye bye


; this routine can be called both from the main program and from the bud
; process.  In the former case the copy of stuff that we need to use is not
; the one we can find at stuff(pc).  So we pass the stuff pointer as a C arg.

_CloseStuff:	move.l		4(sp),stuf
		tst.l		wandle(stuf)
		bne		nocloseW(pc)
		  tst.l		win(stuf)
		  beq		nocloseW(pc)
		    move.l	ibase(stuf),a6
		    move.l	win(stuf),a0
		    lcall	CloseWindow
; call CloseWindow only if wandle has NEVER been nonzero

nocloseW:	tst.l		scr(stuf)
		beq		nocloseS(pc)
		  xcall		Forbid			; fuck the macro
wait:		    move.l	scr(stuf),a0
		    tst.l	sc_FirstWindow(a0)
		    beq		closeS(pc)
		      move.l	dosbase(stuf),a6
		      moveq	#50,d1
		      lcall	Delay
		      bra	wait(pc)
closeS:		  move.l	ibase(stuf),a6
		  lcall		CloseScreen	; stuff->scr already in a0
		  xcall		Permit

nocloseS:	tst.l		fawnt(stuf)
		beq		nocloseF(pc)
		  move.l	fawnt(stuf),a1
		  move.l	gbase(stuf),a6
		  lcall		CloseFont
nocloseF:	move.l  	ibase(stuf),a1
		xcall		CloseLibrary
		move.l		gbase(stuf),a1
		lcall		CloseLibrary
		rts


command:	ds.b		88
_CommandOffs:	dc.w		command-_beginning
stuff:		ds.b		stuffsize
_StuffOffs:	dc.w		stuff-_beginning
procname:	dc.b		"CLImax",0
_NameOffs:	dc.w		procname-_beginning

		cnop		0,4
fakli:		ds.b		cli_SIZEOF
prompt:		dc.b		4,"%N> ",0,0,0
		ds.b		56
setname:	dc.b		4,"SYS:",0,0,0
		ds.b		80
_FakeOffs:	dc.w		fakli-_beginning

		cnop		0,4
_ending:	dc.l		0		; safety pad

		end
