;
; dbx.fileIcon.s
;
; Draggable file icons as dbx controls (MDW)
;
;  1994 Straylight
;

;----- Standard header ------------------------------------------------------

		GET	libs:header
		GET	libs:swis

;----- External dependencies ------------------------------------------------

		GET	sapphire:dbox
		GET	sapphire:sapphire
		GET	sapphire:screen
		GET	sapphire:string
		GET	sapphire:win

		GET	sapphire:dbx.dbx
		GET	sapphire:dbx._dbxMacs

;----- Main code ------------------------------------------------------------

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- fileIcon_sprName ---
;
; On entry:	R0 == filetype
;		R1 == pointer to filename
;
; On exit:	R0 == pointer to sprite name to use
;
; Use:		Works out the sprite name to use for the given filetype and
;		name pair.

		EXPORT	fileIcon_sprName
fileIcon_sprName ROUT

		STMFD	R13!,{R1-R3,R14}	;Save some registers

		; --- Get some easy cases out the way ---

		CMP	R0,#&3000		;Is it untyped?
		ADREQ	R0,fi__xxx		;Yes -- point to the default
		BEQ	%90fileIcon_sprName	;And skip to the end
		CMP	R0,#&1000		;Is it a directory?
		ADREQ	R0,fi__dir		;Point to the sprite name
		BEQ	%90fileIcon_sprName	;And skip to the end
		CMP	R0,#&2000		;Is this an application?
		BEQ	%50fileIcon_sprName	;Yes -- handle that nicely

		; --- It's just a simple file ---

		MOV	R3,R0			;Look after the filetype
		MOV	R0,R11			;Use scratchpad for name
		ADR	R1,fi__file		;Point to sprite name prefix
		BL	str_cpy			;Copy the string over
		MOV	R2,#2			;Three characters to write

		; --- Write the hex number on the end ---

00		AND	R14,R3,#&F		;Get the bottom nibble
		MOV	R3,R3,LSR #4		;And shift down the type
		ADD	R14,R14,#'0'		;Convert to a digit
		CMP	R14,#'9'		;Is it a letter, really?
		ADDGT	R14,R14,#'a'-'9'-1	;Yes -- make it so
		STRB	R14,[R0,R2]		;Store the letter then
		SUBS	R2,R2,#1		;Do the next character
		BGE	%00fileIcon_sprName	;If more -- do them
		MOV	R2,#0			;A NULL byte
		STRB	R2,[R0,#3]		;Terminate the string
		MOV	R0,R11			;Point to the string
		BL	fi__sExist		;Does it exist?
		ADRCC	R0,fi__xxx		;No -- use default sprite
		B	%90fileIcon_sprName	;And return to caller

		; --- The thingy is an application ---

50		MOV	R0,R1			;Point to start of filename
51		LDRB	R14,[R1],#1		;Get a character
		CMP	R14,#'.'		;Is it a dot?
		MOVEQ	R0,R1			;Yes -- remember position
		CMP	R14,#32			;Is it a control char?
		BGE	%51fileIcon_sprName	;No -- keep looping
		BL	fi__sExist		;Does it exist?
		ADRCC	R0,fi__app		;No -- use default sprite

90		LDMFD	R13!,{R1-R3,PC}^	;Return to caller

fi__xxx		DCB	"file_xxx",0
fi__app		DCB	"application",0
fi__file	DCB	"file_",0
fi__dir		DCB	"directory",0

		LTORG

; --- fi__sExist ---
;
; On entry:	R0 == pointer to sprite name
;
; On exit:	CS if the sprite exists, CC if it doesn't
;
; Use:		Informs you whether a sprite exists

fi__sExist	ROUT

		STMFD	R13!,{R0-R6,R14}	;Save some registers
		MOV	R2,R0			;Point to the sprite name
		MOV	R0,#40			;Read sprite information
		SWI	XWimp_SpriteOp		;Get the information
		LDMFD	R13!,{R0-R6,R14}	;Restore registers
		ORRVCS	PC,R14,#C_flag		;If it exists, set C
		BICVSS	PC,R14,#C_flag		;Otherwise clear C

		LTORG

; --- fileIcon ---
;
; Control data:	+0
;
; Workspace:	+0 == filetype of object to display
;		+4 == address of filename
;		+8
;
; Flags:	--
;
; Use:		Control which displays a filetype icon, and allows it to
;		be dragged.

		EXPORT	fileIcon
fileIcon	ROUT

		DBXWS	fi__wSpace
		DCD	dbxMask_click+dbxMask_redraw

		CMP	R0,#dbxEvent_click	;Is it a click event?
		BEQ	%50fileIcon		;Yes -- deal with it

		; --- We must have a redraw event then ---

		STMFD	R13!,{R0-R3,R14}	;Stack some registers

		; --- Find out if it should be invisible ---

		LDMIA	R12,{R0,R14}		;Get vanished dbox,icon
		CMP	R0,R10			;Check dialogues match
		CMPEQ	R1,R14			;And the icon handles
		LDMEQFD	R13!,{R0-R3,PC}^	;Yes -- leave icon blank

		; --- Just fill in the sprite ---

		SUB	R13,R13,#40		;Get me a block, please
		MOV	R0,R10			;The dialogue box
		BL	dbox_window		;Get the window handle
		STMIA	R13,{R0,R1}		;Store window, icon handle
		MOV	R1,R13			;Point to the block
		SWI	Wimp_GetIconState	;Get the icon state
		LDMIA	R8,{R0,R1}		;Load filetype/name
		BL	fileIcon_sprName	;Get the sprite name
		MOV	R1,R0			;Put spritename in R1
		MOV	R0,#&1A			;The icon flags
		ORR	R0,R0,#&100		;...continued
		LDR	R14,[R13,#24]		;Load the icon flags word
		EOR	R14,R14,#&005F0000	;Toggle ESG and shaded bits
		TST	R14,#&00400000		;Is the shaded bit set?
		TSTNE	R14,#&001F0000		;No -- check the ESG then
		ORREQ	R0,R0,#&00400000	;Yes -- set the shaded bit
		MOV	R2,#1			;Use Wimp sprite area
		MOV	R3,#12			;Size of indirected buffer
		ADD	R14,R13,#24		;Point into the block
		STMIA	R14,{R0-R3}		;Store into the block
		ADD	R1,R13,#8		;For use with PlotIcon
		SWI	Wimp_PlotIcon		;Plot the icon
		ADD	R13,R13,#40		;Reclaim the block
		LDMFD	R13!,{R0-R3,PC}^	;Return to the caller

		; --- We have been given a click event ---

50		TST	R2,#&F0			;Was it a drag event?
		MOVEQS	PC,R14			;No -- return

		STMFD	R13!,{R0-R7,R14}	;Save some registers away

		; --- Find out if we can use DragAYum ---

		MOV	R0,#161			;Read CMOS locations
		MOV	R1,#28			;Various strange status flags
		SWI	OS_Byte			;Get the CMOS value there
		TST	R2,#2			;Is the bit set?
		BEQ	%60fileIcon		;No -- use normal drag box

		; --- Set things up for DragALuvvley ---

		MOV	R0,R10			;Get the dialogue box handle
		LDR	R1,[R13,#4]		;Get the icon handle to use
		BL	dbx_controlBBox		;Get the icon bounding box
		BL	screen_getInfo		;Get some screen information
		ADD	R0,R0,#screen_dx	;Point to the pixel sizes
		LDMIA	R0,{R0,R1}		;Get the pixel sizes
		ADD	R4,R4,R0		;Make the coordinates...
		ADD	R5,R5,R1		;... inclusive again
		STMFD	R13!,{R2-R5}		;Store these on the stack
		LDMIA	R8,{R0,R1}		;Get the filetype and name
		BL	fileIcon_sprName	;Convert into a sprite name
		MOV	R2,R0			;Point to it in R2
		MOV	R3,R13			;Point to my coords block
		MOV	R1,#1			;Sprite area containing icon
		MOV	R0,#&C5			;Various gadgetty flags
		SWI	XDragASprite_Start	;Start the drag up
		ADD	R13,R13,#16		;Clear up the coords block
		BVS	%60fileIcon		;If it failed, use normal box

		; --- Make the file icon `vanish' ---

		MOV	R0,R10			;Get the dialogue handle
		LDR	R1,[R13,#4]		;Get the icon handle too
		STMIA	R12,{R0,R1}		;Save them as having vanished
		BL	dbox_window		;Get the dialogue handle
		MOV	R2,#0			;Don't fiddle the flags
		MOV	R3,#0			;Really don't do this
		STMFD	R13!,{R0-R3}		;Save them on the stack
		MOV	R1,R13			;Point to the block
		SWI	Wimp_SetIconState	;Prod icon into redrawing
		ADD	R13,R13,#16		;Recover the stack space
		B	%80fileIcon		;Skip to setting up unknowns

		; --- Use an old-fashioned type drag box ---

60		SUB	R13,R13,#56		;Make way for a drag block
		MOV	R0,R10			;Get the dialogue handle
		LDR	R1,[R13,#60]		;Get the icon handle to use
		BL	dbx_controlBBox		;Get the icon bounding box
		BL	screen_getInfo		;Get some screen information
		ADD	R14,R0,#screen_width	;Point to screen dimensions
		LDMIA	R14,{R6,R7}		;Load them out of the block

		; --- Convert the coordinates ---

		LDMIA	R0,{R0,R1}		;Get the eigen factors
		MOV	R14,#1			;For shifting about a bit
		MOV	R0,R14,LSL R0		;Get the x pixel size
		MOV	R1,R14,LSL R1		;And the y pixel size
		ADD	R4,R4,R0		;Convert back to exclusive...
		ADD	R5,R5,R1		;... coordinates (grr...)

		; --- Now build the main drag block ---

		MOV	R0,R10			;Get the dialogue handle
		BL	dbox_window		;Convert to a window handle
		MOV	R1,#5			;Fixed-size drag box
		MOV	R14,R13			;Point to the block
		STMIA	R14!,{R0-R5}		;Save window, type and box
		MOV	R4,#0			;Set boundaries to the...
		MOV	R5,#0			;... whole screen
		STMIA	R14!,{R4-R7}		;Save the boundaries too
		MOV	R1,R13			;Point to the drag block
		SWI	Wimp_DragBox		;Start up the drag
		ADD	R13,R13,#56		;Restore the stack again

		; --- Set up the unknown handler and return ---

80		ADR	R0,fi__unknown		;Point to my handler proc
		LDR	R1,[R13,#4]		;Pass icon handle in R4
						;See, it does have use!
		MOV	R2,R10			;Pass dialogue handle in R10
		MOV	R3,R12			;And my workspace in R12
		BL	win_unknownHandler	;Register the magic handler
		LDMFD	R13!,{R0-R7,R14}	;Unstack a load of registers
		ORRS	PC,R14,#C_flag		;Return and claim the click

fi__wSpace	DCD	0

		LTORG

; --- fi__unknown ---
;
; On entry:	R0 == an event code
;		R1 == pointer to any associated event data
;
; On exit:	CS if I handled it
;
; Use:		Stops the drag and sends a drag finished event to the
;		dialogue box.

fi__unknown	ROUT

		CMP	R0,#7			;Is this a drag finished?
		MOVNES	PC,R14			;No -- not interested then

		; --- Send the mouse position to the dialogue ---

		STMFD	R13!,{R0-R3,R14}	;Save some registers away
		SWI	XDragASprite_Stop	;Stop thy silly dragging
		SUB	R13,R13,#24		;Make some space
		MOV	R1,R13			;Point to the block created
		SWI	Wimp_GetPointerInfo	;Get the current position
		MOV	R0,#fIcon_event		;Get the event code
		MOV	R1,R4			;Send to the correct icon
		ADD	R14,R13,#12		;Get window and icon handles
		LDMIA	R14,{R2,R3}		;Load them from the block
		ADD	R13,R13,#24		;Restore the stack pointer
		BL	dbx_sendEvent		;Deliver the event then

		; --- Now disable the unknown handler ---

		ADR	R0,fi__unknown		;Point to my handler proc
		MOV	R1,R4			;Pass icon handle in R4
		MOV	R2,R10			;Pass dialogue handle in R10
		MOV	R3,R12			;And my workspace in R12
		BL	win_removeUnknownHandler ;Deregister the handler
		LDMFD	R13!,{R0-R3,R14}	;Unstack a load of registers
		ORRS	PC,R14,#C_flag		;Return and claim the click

		LTORG

; --- fileIcon_reAppear ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Makes the currently vanished file icon reappear.

		EXPORT	fileIcon_reAppear
fileIcon_reAppear

		STMFD	R13!,{R0-R3,R12,R14}	;Save some registers
		WSPACE	fi__wSpace		;Locate my workspace
		LDMIA	R12,{R0,R1}		;Get the vanished dbox/icon
		CMP	R0,#0			;Is the dialogue null?
		LDMEQFD	R13!,{R0-R3,R12,PC}^	;Yes -- ignore this call
		MOV	R14,#0			;Zero out the vanished dbox
		STR	R14,fi__dbox		;Save it over the old one
		BL	dbox_window		;Get the dialogue handle
		MOV	R2,#0			;Don't fiddle the flags
		MOV	R3,#0			;Really don't do this
		STMFD	R13!,{R0-R3}		;Save them on the stack
		MOV	R1,R13			;Point to the block
		SWI	Wimp_SetIconState	;Prod icon into redrawing
		ADD	R13,R13,#16		;Recover the stack space
		LDMFD	R13!,{R0-R3,R12,PC}^	;Return to caller

		LTORG

; --- fileIcon_closed ---
;
; On entry:	R0 == dialogue box handle
;
; On exit:	--
;
; Use:		Informs fileIcon that the specified dialogue box has closed.

		EXPORT	fileIcon_closed
fileIcon_closed	ROUT

		STMFD	R13!,{R12,R14}		;Save some registers
		WSPACE	fi__wSpace		;Find my workspace pointer
		LDR	R14,fi__dbox		;Load the current dbox handle
		CMP	R14,R0			;Is it a match?
		MOVEQ	R14,#0			;Yes -- get a dummy handle
		STREQ	R14,fi__dbox		;And store in its place
		LDMFD	R13!,{R12,PC}^		;Return to caller

		LTORG

fIcon_event	EQU	&80000003

;----- Workspace ------------------------------------------------------------

		^	0,R12
fi__wStart	#	0

fi__dbox	#	4			;Dbox with vanished icon
fi__icon	#	4			;The vanished icon

fi__wSize	EQU	{VAR}-fi__wStart

		AREA	|Sapphire$$LibData|,CODE,READONLY

		DCD	fi__wSize
		DCD	fi__wSpace
		DCD	16
		DCD	0

;----- That's all, folks ----------------------------------------------------

		END
