
;*========================================================================
;*
;* AESFAST Public Domain GEM bindings.
;*	Maintenance:
;*	 02/11/89 v1.1: This source file is new with this version.
;*
;*	 04/07/89 v1.2:
;*			  The calculation of the location of the prompt on the
;*			  screen has been changed.	It was placed one boxchar height
;*			  down on the screen, putting it right below the menu bar.
;*			  This didn't look too good on a big-monitor system, so now
;*			  it is calculated by centering the box, then subtracting a
;*			  fixed offset from the centered Y to make it appear right
;*			  above the fsel'er box.  The offset is 9 character heights,
;*			  (plus 2 extra char heights for the prompt itself), less
;*			  2 pixels (just to line everything up real neat).
;*
;*	 07/22/89 v1.3:
;*			  Bugfix...A 'bra.s' instruction was missing just before the
;*			  'strcpy' routine, causing 4 bombs on a pre-1.4 machine.
;*========================================================================

;*************************************************************************
;*
;* Extended fsel manager routine.
;*	(Including simulation routines for pre-TOS 1.4 systems).
;*
;*************************************************************************

;-------------------------------------------------------------------------
; fsel_exinput
;  This function is new with TOS 1.4, but this binding supports it in all
;  TOS/AES versions with a simulation of the new routine's actions if the
;  AES version we're running under is pre-TOS 1.4
;-------------------------------------------------------------------------

		  globl 	_fsel_exinput
_fsel_exinput:

;		  .cargs	#8,pinpath.l,pinsel.l,pbutton.l,plabel.l

pinpath 		=	8
pinsel			=	12
pbutton 		=	16
plabel			=	20

		  link		a6,#-4

		  move.w	_gl_apversion,d0		 ; Check the AES version.  If
		  cmp.w 	#$0104,d0				 ; it's $0104, we're running
		  beq.b 	ramaes					 ; on the RAM-based TOS 1.4
		  cmp.w 	#$0130,d0				 ; Else, if it's less than $0130
		  blt		simu_exinput			 ; we have to simulate exinput.
ramaes:
		  move.l	plabel(a6),d0			 ; Swap the button and prompt
		  move.l	pbutton(a6),plabel(a6)	 ; string pointers to make the
		  move.l	d0,pbutton(a6)			 ; addrin stuff contiguous.

		  move.l	#$5B000203,d0			 ; AControl  91,0,2,3				  ; AES v1.3 & up: fsel_exinput
		  moveq.l	#-4,d1					 ; is a legal function, do it.
		  lea		pinpath(a6),a0			 ; a0 -> addrin
		  jsr		aes_call				 ; Call AES.

		  move.l	plabel(a6),d0			 ; Swap the prompt string and
		  move.l	pbutton(a6),plabel(a6)	 ; button pointers back to how
		  move.l	d0,pbutton(a6)			 ; they were on entry.

		  moveq.l	#-4,d1					 ; Return values from
		  lea		pbutton(a6),a1			 ; intout[] array to caller
		  jmp		(a0)					 ; via aes_return routine.

;*************************************************************************
; The following code and data supports the exinput simulation routines.
;
; The simulator supports *most* of the TOS 1.4 features, to wit:
;
;  - A prompt string of up to 30 chars is displayed with the file selector.
;  - The file selector handles <CR> like TOS 1.4 does (see comments below).
;  - If the caller passes in a path with a leading '\' it will be appended
;	 to the current default drive & path (and the whole resulting string
;	 will be returned upon exit).
;  - The current DTA is preserved.
;  - The current drive and path is preserved.
;
; These are differences between the simulator and TOS 1.4:
;
;  - There are no drive buttons in the dialog.
;  - There is still a static limit of 100 files that can be displayed.
;  - Long pathnames are NOT handled correctly.
;  - Multiple abort/continue situations will still give problems.
;  - The redraw sequence of the dialog is still the same.
;
; The things not supported are, of course, things I can't affect without
; completely re-writing the fsel_input handler.
;*************************************************************************

;-------------------------------------------------------------------------
; Define variables which will be accessed as offsets from a3.
;  (Storage for these things will be allocated from the stack at runtime).
;-------------------------------------------------------------------------

savddrv   = 		0
savdpath  = 		2+savddrv
savipath  = 		128+savdpath
savdta	  = 		128+savipath
tmpdta	  = 		4+savdta
SAV_SZ	  = 		44+tmpdta

;-------------------------------------------------------------------------
; Define variables.
;-------------------------------------------------------------------------

		  bss

lastkeyCR: ds.w 	1		  ; Flag: was last keystroke during fsel a <CR>?
oldbios:   ds.l 	1		  ; Old BIOS vector address.

		  text

;-------------------------------------------------------------------------
; This routine is installed as a hook in the BIOS vector for the duration
; of the the fsel_input call.  It watches for a Bconin(2) call (which will
; be the AES asking for a character).  The Bconin call is done from in
; here such that we get the character back from the real BIOS and examine
; it.  If the character is a <CR>, we set the flag to say so and return
; the character to the caller.	If not a <CR> we clear the flag and
; return the character.
;
; The whole reason for this is a bug in the pre-TOS 1.4 AES: If the user
; edited the path but didn't click the mouse on anything or change the
; filename field, then hit <CR>, the system returned a CANCEL status. This
; BIOS hook is the only way to tell for sure that the exit was via <CR>.
;-------------------------------------------------------------------------

bioshook:
		  lea		6(sp),a0			; Assume super mode caller.
		  btst.b	#5,(sp) 			; Were we in super mode?
		  bne.b 	supermode			; No, user mode...
		  move.l	usp,a0				; So look at parms on user stack.
supermode:
		  move.l	#$00020002,d0		; Bconin(2) function...
		  cmp.l 	(a0),d0 			; Is it that?
		  bne.b 	biospunt			; Nope, punt.

		  move.l	d0,-(sp)			; Stack Bconin(2) function code,
		  bsr.b 	bioscall			; Go get the character.
		  addq.l	#4,sp

		  cmp.b 	#$0D,d0 		   ; Is the char a <CR>? If so set the
		  seq		lastkeyCR			; flag, either way, return the char.
biosreturn:
		  rte							; Return the char to the caller.

bioscall:								; Call original BIOS, with return
		  move.w	sr,-(sp)			; to caller of 'bioscall'.
biospunt:
		  move.l	oldbios,-(sp)		; Not a BIOS function we handle,
		  rts							; punt control to the real BIOS.

;-----------------------------------------------------------------------------
; a couple mundane things...
;-----------------------------------------------------------------------------

strcpy:
		  move.b	(a0)+,(a1)+
		  bne.b 	strcpy
		  rts

strcmp:
		  move.b	(a0)+,d0
		  beq.b 	checkdone
		  cmp.b 	(a1)+,d0
		  beq.b 	strcmp
		  rts
checkdone:
		  tst.b 	(a1)
		  rts

;-------------------------------------------------------------------------
; simu_exinput - Simulate an exinput call on pre-TOS 1.4 systems.
;-------------------------------------------------------------------------

simu_exinput:

		  movem.l	d2/a2-a3,-(sp)		   ; Save registers.

;-------------------------------------------------------------------------
; Once the one-time stuff is done (and on all subsequent calls...) do
; the actual simulation of the TOS 1.4 exinput:
;
;  - The current default drive and path is saved.
;  - The current DTA address is saved, and a temporary DTA is installed.
;  - If the pathname passed to exinput starts with a '\', the passed-in
;	 path is appended to the current default path.
;  - A hook is placed into the BIOS vector to watch for <CR> being hit,
;	 so that we can mimick the new fsel's actions when just the pathname
;	 is edited, and the user hits <CR> (to move to the filename field).
;  - Call fsel_input() (the simulator routine that puts up a prompt box)
;  - Check to see if our BIOS hook set the flag saying a <CR> was the last
;	 key hit.  If so, see if the pathname in the fsel dialog was changed.
;	 If so, the user probably hit <CR> after typing the path (I always do),
;	 so we loop back to do the fsel dialog again.  If the user clicked on
;	 OK instead of hitting return, this won't happen.  Also, if the user
;	 doesn't change the path (but perhaps does change the filename), then
;	 hits return, we will not repeat the dialog.
;  - Restore the current drive & path, and the old DTA.
;  - De-install the BIOS hook.
;  - Return to caller.
;-------------------------------------------------------------------------

do_simulation:

;		  .cargs	#8,pinpath.l,pinsel.l,pbutton.l,plabel.l

pinpath 		 =	 8
pinsel			 =	 12
pbutton 		 =	 16
plabel			 =	 20

		  sub.w 	#SAV_SZ,sp			; Allocate save area from stack,
		  move.l	sp,a3				; load save area base register.

		  move.w	#$19,-(sp)			; get/save current drive.
		  trap		#1
		  addq.l	#2,sp
		  move.w	d0,savddrv(a3)
		  add.b 	#$41,d0
		  move.b	d0,savdpath(a3)
		  move.b	#$3A,1+savdpath(a3)

		  clr.w 	-(sp)				; get/save current path.
		  pea		2+savdpath(a3)
		  move.w	#$47,-(sp)
		  trap		#1
		  addq.l	#8,sp

		  tst.b 	2+savdpath(a3)
		  bne.b 	gotpath
		  move.w	#$5C00,2+savdpath(a3)		  ; 5C00 == "\<NULL>"

gotpath:

		  move.w	#$2F,-(sp)					  ; get the process's
		  trap		#1							  ; current dta; save it.
		  move.l	d0,savdta(a3)
		  addq.l	#2,sp

		  pea		tmpdta(a3)					  ; switch to a private dta.
		  move.w	#$1A,-(sp)
		  trap		#1
		  addq.l	#6,sp

		  move.l	pinpath(a6),a0		; a0 -> input path
		  lea		savipath(a3),a1 	; a0 -> path save area
		  cmp.b 	#$5C,(a0)		   ; Leading '\' in input path?
		  bne.b 	copypath			; Nope, go do straight copy.
		  lea		savdpath(a3),a0 	; Yep, so copy the current
		  bsr		strcpy				; default path to the save
		  cmp.b 	#$5C,-2(a1)
		  bne.b 	noterm
		  subq.l	#1,a1
noterm:
		  move.l	pinpath(a6),a0		; area first, then concat
		  subq.l	#1,a1				; the input path onto the
		  bsr		strcpy				; end of it.  Since we changed
		  lea		savipath(a3),a0 	; it in the save area, we need to
		  move.l	pinpath(a6),a1		; copy it back to the input area.
copypath:
		  bsr		strcpy

		  pea		bioshook(pc)		; install bios hook
		  move.w	#$2D,-(sp)
		  move.w	#5,-(sp)
		  trap		#13
		  addq.l	#8,sp
		  move.l	d0,oldbios

fsel_loop:

		  clr.w 	lastkeyCR			; Clear <CR> flag.

		  jsr		FselSimu		  ; go do prompted fsel

		  tst.w 	lastkeyCR			; Hack to fix an AES bug: If our
		  beq.b 	fsel_done			; BIOS hook says the last key was
		  move.w	#1,-2(a6)			; a CR, force the button to OK.

		  move.l	pinpath(a6),a0		; see if the user changed the path;
		  lea		savipath(a3),a1 	; if not, we're done.
		  bsr		strcmp
		  beq.b 	fsel_done

		  move.l	pinpath(a6),a0		; user changed path, save the new
		  lea		savipath(a3),a1 	; path (so we can detect another
		  bsr		strcpy				; change) and loop to do the fsel
		  bra.b 	fsel_loop			; again.

fsel_done:

		  move.w	savddrv(a3),-(sp)	; restore default drive
		  move.w	#$0E,-(sp)
		  trap		#1
		  addq.l	#4,sp

		  pea		savdpath(a3)		; restore default path
		  move.w	#$3B,-(sp)
		  trap		#1
		  addq.l	#6,sp

		  move.l	savdta(a3),-(sp)	; restore process's dta
		  move.w	#$1A,-(sp)
		  trap		#1
		  addq.l	#6,sp

		  move.l	oldbios,-(sp)		; remove bios hook
		  move.w	#$2D,-(sp)
		  move.w	#5,-(sp)
		  trap		#13
		  addq.l	#8,sp

		  add.w 	#SAV_SZ,sp			; Deallocate save area from stack.
		  movem.l	(sp)+,d2/a2-a3		; Restore working regs.

		  move.l	pbutton(a6),a1		; Return the values from
		  move.w	-2(a6),(a1) 		; intout to the caller.
		  move.w	-4(a6),d0
		  unlk		a6
		  rts

;		  end of code

