;
; gallery.s
;
; Background-drawing viewers
;
;  1995-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's Sapphire library.
;
; Sapphire is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
;
; Sapphire is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Sapphire.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

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

		GET	libs:header
		GET	libs:swis

		GET	libs:stream

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

		GET	sapphire:idle
		GET	sapphire:screen
		GET	sapphire:viewer

		IMPORT	vw__intSimple
		IMPORT	vw__enum
		IMPORT	vw__doUpdate
		IMPORT	vw__callShape

;----- Main code ------------------------------------------------------------
;
; Some of this makes deep assumptions about the way viewer works and which
; registers we /can/ corrupt even though the docs say otherwise.  That's OK
; though.  We don't care.

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- gallery_eventHandler ---
;
; On entry:	R0 == viewer handle
;		R1 == pointer to handler routine
;		R2 == R10 value to pass to handler
;		R3 == R12 value to pass to handler
;
; On exit:	--
;
; Use:		Sets up an event handler for the viewer, and adds in
;		gallery's own special processing for background drawing.

		EXPORT	gallery_eventHandler
gallery_eventHandler ROUT

		STMFD	R13!,{R4,R14}		;Save some registers
		ADD	R14,R0,#vw__handler+4	;Find some spare space
		MOV	R4,R1			;And get R10 value in R4
		STMIA	R14,{R2-R4}		;Store the new handler
		ADR	R4,gl__events		;Point to our handler
		STR	R4,[R0,#vw__handler]	;And store that away
		LDMFD	R13!,{R4,PC}^		;And return to caller

		LTORG

; --- gallery_drawBox ---
;
; On entry:	R0-R3 == window relative coords of box to plot
;
; On exit:	--
;
; Use:		Draws a box to indicate tht this item hasn't been
;		displayed yet.  Use this routine to give a consistant
;		look to applications which use the gallery.

		EXPORT	gallery_drawBox
gallery_drawBox	ROUT

		STMFD	R13!,{R0,R1,R14}	;Stack some registers
		SUB	R13,R13,#32		;Get room for an icon block
		STMIA	R13,{R0-R3}		;Store away the coordinates
		MOV	R0,#&00000024		;The icon flags
		ORR	R0,R0,#&27000000	;Compete them
		STR	R0,[R13,#16]		;Store the icon flags
		MOV	R1,R13			;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon
		ADD	R13,R13,#32		;Increment the stack again
		LDMFD	R13!,{R0,R1,PC}^	;Return to caller

		LTORG

; --- gallery_removeBox ---
;
; On entry:	R0-R3 == window relative coords of box to remove
;
; On exit:	--
;
; Use:		Removes a previously draw temporary box.  It is assumed that
;		the background colour of the viewere is 1.

		EXPORT	gallery_removeBox
gallery_removeBox ROUT

		STMFD	R13!,{R0,R1,R14}	;Stack some registers
		SUB	R13,R13,#32		;Get room for an icon block
		STMIA	R13,{R0-R3}		;Store away the coordinates
		MOV	R0,#&00000024		;The icon flags
		ORR	R0,R0,#&11000000	;Compete them
		STR	R0,[R13,#16]		;Store the icon flags
		MOV	R1,R13			;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon
		ADD	R13,R13,#32		;Increment the stack again
		LDMFD	R13!,{R0,R1,PC}^	;Return to caller

		LTORG

; --- gl__events ---
;
; On entry:	R0 == event code
;		R1-R7 == information from viewer
;
; On exit:	exits via user handler
;
; Use:		Intercepts viewer events to do background redraw.

gl__events	ROUT

		CMP	R0,#vwEvent_redraw	;Is this a redraw request?
		LDRNE	PC,[R9,#gl__handler]	;No --pass it on then

		STMFD	R13!,{R0-R3,R10,R14}	;Save some registers
		MOV	R10,R9			;Point to viewer block
		MOV	R0,#vwShape_slowBit	;Is this intersecting?
		BL	vw__callShape		;Call the shape function
		BCC	%10gl__events		;No -- then skip round

		MOV	R0,#0			;This icon is not drawn yet
		BL	gl__drawn		;So set the flag up nicely

		LDR	R14,[R10,#vw__flags]	;Load the flags word
		TST	R14,#glFlag__drawing	;Do we have the idle going?
		BNE	%10gl__events		;Yes -- then skip on

		ORR	R14,R14,#glFlag__drawing;No -- set the flag then
		STR	R14,[R10,#vw__flags]	;And store them back again
		MOV	R0,#0			;Call me all the time
		ADR	R1,gl__idles		;No -- point to the handler
		MOV	R2,R10			;Point to the viewer block
		MOV	R3,R12			;Point to someone else's wsp
		BL	idle_handler		;Register the handler

10gl__events	LDMFD	R13!,{R0-R3,R10,R14}	;And return to caller
		LDR	PC,[R9,#gl__handler]	;Continue processing event

		LTORG

; --- gallery_reset ---
;
; On entry:	R0 == viewer handle
;
; On exit:	--
;
; Use:		Resets all the icons in the gallery to their `undrawn' state.
;		Use this before opening the window etc.

		EXPORT	gallery_reset
gallery_reset	ROUT

		STMFD	R13!,{R0-R4,R10,R14}	;Save some registers
		MOV	R10,R0			;Get the viewer handle
		MOV	R1,#0			;Start at the beginning
		LDR	R4,[R10,#vw__listDef]	;Find the list definition
00		LDR	R0,[R10,#vw__list]	;Find the list base address
		MOV	R2,#2			;Match drawn icons
		MOV	R3,#2			;And only the drawn ones
		MOV	R14,PC			;Set up the return address
		ADD	PC,R4,#vw__enumerate	;Find the next item
		BCC	%f00			;When finished, skip out
		MOV	R3,#0			;Clear the bit now
		MOV	R14,PC			;Set up return address
		ADD	PC,R4,#vw__setFlags	;Set up the flags nicely
		B	%b00			;And loop back round again
00		LDMFD	R13!,{R0-R4,R10,PC}^	;And return to caller

		LTORG

; --- gl__idles ---
;
; On entry:	R10 == pointer to viewer block
;
; On exit:	--
;
; Use:		Redraws the first unredrawn item in the viewer.

gl__idles	ROUT

		STMFD	R13!,{R0-R4,R14}	;Save some registers
		SUB	R13,R13,#36		;Make space for a window blk
		LDR	R14,[R10,#vw__window]	;Load the window handle
		STR	R14,[R13,#0]		;Store it in the block
		MOV	R1,R13			;Point to the block
		SWI	Wimp_GetWindowState	;Get the window information
		MOV	R3,R13			;And again please
		BL	gl__clipBlock		;Build the clipping info

		MOV	R1,#0			;Start at the beginning
00		ADD	R2,R13,#16		;Point to a spare bit of blk
		BL	vw__enum		;Get another icon to do
		BCC	%50gl__idles		;No icons -- remove handler
		BL	vw__intSimple		;Do the boxes intersect?
		BLCS	gl__isDrawn		;Is the thing drawn yet?
		BCC	%b00			;No -- then skip back

		; --- Draw this item ---

		MOV	R0,#1			;It's now drawn (well, soon)
		BL	gl__drawn		;So remember this
		MOV	R0,R10			;Point to the viewer block
		MOV	R2,#vwEvent_unDraw	;Undraw the temporary bit
		BL	vw__doUpdate		;Go and do the update
		MOV	R2,#vwEvent_draw	;Now draw it properly
		BL	vw__doUpdate		;And then draw it properly
		ADD	R13,R13,#36		;Restore the stack pointer
		LDMFD	R13!,{R0-R4,PC}^	;Return to caller

		; --- Remove this handler ---

50gl__idles	MOV	R0,#0			;Call me all the time
		ADR	R1,gl__idles		;No -- point to the handler
		MOV	R2,R10			;Point to the viewer block
		MOV	R3,R12			;Point to someone else's wsp
		BL	idle_removeHandler	;Remove the handler thing
		LDR	R14,[R10,#vw__flags]	;Load the flags word
		BIC	R14,R14,#glFlag__drawing;Not drawing any more
		STR	R14,[R10,#vw__flags]	;Store the flags away
		ADD	R13,R13,#36		;Restore the stack pointer
		LDMFD	R13!,{R0-R4,PC}^	;And return to caller

		LTORG

; --- gl__clipBlock ---
;
; On entry:	R1 == pointer to window-state block
;		R3 == pointer to output block
;
; On exit:	--
;
; Use:		Replaces the window-state block with a block containing the
;		window-relative coordinates of the visible part of the
;		window.

gl__clipBlock	ROUT

		STMFD	R13!,{R0-R2,R4,R5,R14}	;Save some registers
		LDMIB	R1,{R0-R2,R4,R5,R14}	;Load window position/scroll
		SUB	R2,R2,R0		;Find the window width
		SUB	R1,R4,R1		;And the window height
		MOV	R0,R5			;This is the x0 position
		ADD	R5,R5,R2		;And this is the x1 position
		SUB	R1,R14,R1		;This is y0
		STMIA	R3,{R0,R1,R5,R14}	;Save that lot away now
		LDMFD	R13!,{R0-R2,R4,R5,PC}^	;And return to caller

		LTORG

; --- gl__drawn ---
;
; On entry:	R0 == 0 to say `undrawn', 1 to say `drawn'
;		R1 == item handle
;
; On exit:	--
;
; Use:		Sets or resets an icon's drawn flag.

gl__drawn	ROUT

		STMFD	R13!,{R0,R2-R4,R14}	;Save some registers
		MOV	R2,#2			;Set the drawn flag
		MOV	R3,R0,LSL #1		;Do with it what he said
		LDR	R0,[R10,#vw__list]	;Load the list pointer
		LDR	R4,[R10,#vw__listDef]	;And the list defintion
		MOV	R14,PC			;Set up the return address
		ADD	PC,R4,#vw__setFlags	;Read the item's flags
		LDMFD	R13!,{R0,R2-R4,PC}^	;Restore registers

		LTORG

; --- gl__isDrawn ---
;
; On entry:	R1 == item handle
;
; On exit:	CC if item has been drawn, else CS
;
; Use:		Tells you quickly whether an item has been drawn.

gl__isDrawn	ROUT

		STMFD	R13!,{R0,R2-R4,R14}	;Save some registers
		LDR	R0,[R10,#vw__list]	;Load the list pointer
		LDR	R4,[R10,#vw__listDef]	;And the list defintion
		MOV	R2,#0			;Read the flags please
		MOV	R3,#0			;Don't change them, no missus
		MOV	R14,PC			;Set up the return address
		ADD	PC,R4,#vw__setFlags	;Read the item's flags
		TST	R2,#2			;Is the flag set?
		LDMFD	R13!,{R0,R2-R4,R14}	;Restore registers
		ORREQS	PC,R14,#C_flag		;If not set, return CS
		BICNES	PC,R14,#C_flag		;Else return CC

		LTORG

;----- List definition format -----------------------------------------------

		^	0
vw__itemToIndex	#	4			;Item to index routine
						;Entry:	R0 == pointer to list
						;	R1 == pointer to item
						;Exit:	R1 == index, or -1

vw__indexToItem	#	4			;Index to item routine
						;Entry:	R0 == pointer to list
						;	R1 == index of item
						;Exit:	R1 == item ptr, or 0

vw__enumerate	#	4			;Enumeration function
						;Entry:	R0 == list pointer
						;	R1 == item, or 0
						;	R2 == BIC mask
						;	R3 == test mask
						;Exit:	CS if match, and
						;	R1 == item ptr

vw__items	#	4			;Function to return items
						;Entry:	R0 == list pointer
						;Exit:	R1 == number of items

vw__setFlags	#	4			;Function to set/read flags
						;Entry:	R1 == pointer to item
						;	R2 == BIC mask
						;	R3 == EOR mask
						;Exit:	R2 == new flags

;----- Viewer's icky bits which we poke around in ---------------------------

		^	0

		; --- Information about the window ---

vw__window	#	4			;Window handle
vw__extent	#	16			;Current window extent
vw__flags	#	4			;Any flags of interest
vw__list	#	4			;Pointer to list head
vw__listDef	#	4			;Pointer to list handler
vw__handler	#	12			;Viewer's event handler
gl__handler	#	8			;Gallery's event handler(YUK)
vw__shape	#	4			;Shape handler function
vw__banner	#	4			;Pointer to banner string
vw__fixedWidth	#	4			;Width of banner/title

		; --- Icon sizing information ---

vw__icons	#	4			;Cache number of icons
vw__stdDimens	#	8			;`Standard' width and height
vw__iconWidth	#	4			;Width of icons currently
vw__iconHeight	#	4			;Height of icons currently
vw__across	#	4			;Number of icons across
vw__down	#	4			;Number of icons down

		; --- Data for default selection model ---

vw__tempSel	#	4			;Temporary selected icon

		; --- Big buffers at the end ---

vw__title	#	256			;Title bar buffer

vw__size	#	0			;Size of a viewer block

		; --- Flags bits ---
		;
		; We only have the top-end bits.

glFlag__drawing	EQU	(1<<31)			;We have idle handler running

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

		END
