;
; banner.s
;
; A startup banner window
;
;  1994-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:alloc
		GET	sapphire:dbox
		GET	sapphire:divide
		GET	sapphire:event
		GET	sapphire:flex
		GET	sapphire:heap
		GET	sapphire:hour
		GET	sapphire:nopoll
		GET	sapphire:res
		GET	sapphire:sapphire
		GET	sapphire:screen
		GET	sapphire:wimp

		GET	sapphire:dbx.dbx
		GET	sapphire:dbx.slider

		[	:LNOT::DEF: bnr__dynaLink

		IMPORT  |Image$$RW$$Base|,WEAK
		IMPORT  |Image$$RW$$Limit|,WEAK
		IMPORT  |Sapphire$$ClientData$$Base|,WEAK
		IMPORT  |Sapphire$$ClientData$$Limit|,WEAK
		IMPORT  |Sapphire$$ExtTable$$Base|,WEAK
		IMPORT  |Sapphire$$ExtTable$$Limit|,WEAK

		]

		IMPORT	|Sapphire$$LibData$$Base|,WEAK
		IMPORT	|Sapphire$$LibData$$Limit|,WEAK

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

		AREA	|Sapphire$$Code|,CODE,READONLY

		[	:LNOT::DEF: bnr__dynaLink

; --- banner ---
;
; On entry:	R0 == pointer to definition block, or 0
;		R1 == R12 value to pass to setup routine, if present
;
; On exit:	--
;
; Use:		Displays a startup banner and initialises the library and
;		client.  This call should be used as a replacement for
;		sapphire_libInit.
;
;		If R0 is 0 on entry, no banner window is used; instead
;		an hourglass percentage is displayed to indicate the
;		amount of initialisation performed so far.
;
;		Alternatively, it should point to a table consisting of
;		a flags word and optional arguments specified by the flags
;		in order.  The options you can specify are a slider and
;		percentage count icon (used to display current progress),
;		a setup routine, and the leafname of a sprites file to
;		attach to the banner window.
;
;		The setup routine is passed the banner dialogue handle in
;		R0.  It should fill in parts of the banner window, such as
;		the licencee name and serial number that can't be determined
;		until runtime (for safeness), and maybe version information
;		too.

		EXPORT	banner
banner		ROUT

		STMFD	R13!,{R2,R14}		;Save some registers
		ADR	R2,bnr__initList	;Point to the list
		BL	bnr_doBanner		;Do the job
		LDMFD	R13!,{R2,PC}^		;And return to caller

bnr__initList	DCD	|Image$$RW$$Limit|
		DCD	|Sapphire$$ClientData$$Base|
		DCD	|Sapphire$$ClientData$$Limit|
		DCD	-1
		DCD	|Sapphire$$ExtTable$$Base|
		DCD	|Sapphire$$ExtTable$$Limit|

		LTORG

		]

; --- bnr_doBanner ---
;
; On entry:	R0 == pointer to definition block, or 0
;		R1 == R12 value to pass to setup routine, if present
;		R2 == pointer to library initialisation table
;
; On exit:	--
;
; Use:		Displays a startup banner and initialises the library and
;		client.

		EXPORT	bnr_doBanner
bnr_doBanner	ROUT

		STMFD	R13!,{R0-R10,R12,R14}	;Save some registers

		; --- Initialise required parts of library ---

		LDR	R0,sapph_appName	;Find the application name
		BL	hour_init		;Initialise hourglass
		BL	hour_on			;Turn on the hourglass
		BL	alloc_init		;Initialise heap functions
		BL	wimp_init		;Initialise WindowManager
		BL	screen_init		;Initialise screen info
		BL	res_init		;Find our resources
		BL	nopoll_init		;We need nonpolling dialogues
		BL	dbox_init		;Initialise dialogue boxes
		BL	flex_init		;Initialise nemory manager
		BL	heap_init		;And the heap manager too

		; --- Unpack the definition block ---

		SUB	R13,R13,#36		;Make a bit of workspace
		MOV	R1,#0			;Clear two words
		MOV	R2,#0
		STMFD	R13!,{R1,R2}		;Make two flex anchors
		STR	R1,[R13,#40]		;Initial percentage is 0
		MOV	R10,#0			;Not created the block yet
		LDR	R9,[R13,#44]		;Load the block pointer
		CMP	R9,#0			;Is there a block?
		BEQ	%05bnr_doBanner		;No -- don't bother then

		; --- Load the template file ---

		MOV	R0,R13			;Point to this anchor
		MOV	R1,#2048		;Guess the size of the file
		BL	flex_alloc		;Try to allocate
		BCS	%05bnr_doBanner		;If it failed, ignore window

		ADRL	R0,bnr__tfile		;Point to template file name
		MOV	R1,R11			;Build name in scratchpad
		BL	res_find		;Try to find the file
		BCC	%05bnr_doBanner		;If it failed, ignore window
		MOV	R1,R0			;Point to the name
		SWI	XWimp_OpenTemplate	;Try to open the file
		LDRVC	R1,[R13,#0]		;Load the base of this block
		ADDVC	R2,R1,#1024		;Indirected data in 2nd K
		ADDVC	R3,R1,#2048		;And stop at the end please
		MOVVC	R4,#-1			;Pray there's no fonts
		ADRVCL	R5,bnr__template	;Point to the template name
		LDMVCIA	R5,{R6-R8}		;Load 3 words of data
		ADDVC	R14,R13,#8		;Point to some free space
		STMVCIA	R14,{R6-R8}		;It writes back the name!
		MOVVC	R5,R14			;So point to a copy
		MOVVC	R6,#0			;Start from beginning
		SWIVC	XWimp_LoadTemplate	;Try to load the template
		MOVVS	R7,R0			;If error, remember pointer
		MOVVC	R7,#0			;Otherwise clear this
		SWI	Wimp_CloseTemplate	;Close the template file
		MOVS	R0,R7			;Get the error back
		BNE	%05bnr_doBanner		;And go off somewhere else

		; --- Now load options from the block ---

		MOV	R1,R9			;Move this around a bit
		LDR	R0,[R1],#4		;Load the flags word

		TST	R0,#bFlag_slider	;Does he want a slider?
		LDRNE	R9,[R1],#4		;Yes -- load the icon number
		MOVEQ	R9,#-1			;Otherwise remember this

		TST	R0,#bFlag_counter	;Does he have a counter?
		LDRNE	R8,[R1],#4		;Yes -- load the icon number
		MOVEQ	R8,#-1			;Otherwise remember this

		TST	R0,#bFlag_setup		;Does he have a setup routine
		LDRNE	R7,[R1],#4		;Yes -- load the address
		MOVEQ	R7,#0			;Otherwise remember this

		TST	R0,#bFlag_sprites	;Does he have a sprite file
		BEQ	%03bnr_doBanner		;No -- don't load it then

		; --- Load the sprite file ---

		MOV	R0,R1			;Point to the leafname
		MOV	R1,R11			;Build name in scratchpad
		BL	res_find		;Try to get a good name
		BCC	%03bnr_doBanner		;If not there, don't worry
		MOV	R1,R0			;Put name in right register
		MOV	R0,#17			;Read information on file
		SWI	XOS_File		;Try to get the information
		BVS	%03bnr_doBanner		;Failed -- don't bother then
		TST	R0,#1			;Is this a file?
		BEQ	%03bnr_doBanner		;No -- ignore it then
		ADD	R0,R13,#4		;Point to other anchor
		ADD	R1,R4,#8		;Get the file size
		BL	flex_alloc		;Allocate the memory
		BCS	%03bnr_doBanner		;Failed -- ignore it then
		MOV	R0,#16			;Load the file
		MOV	R1,R11			;Point to the filename
		LDR	R2,[R13,#4]		;Load the block address
		ADD	R14,R4,#8		;Get this block size
		STR	R14,[R2],#4		;Save it in the block
		MOV	R3,#0			;Load where I said to load it
		SWI	OS_File			;Load the file then

		LDMIA	R13,{R0,R1}		;Load the two anchors
		STR	R1,[R0,#64]		;Save the sprite pointer

		; --- Now create a dialogue box ---

03bnr_doBanner	LDR	R0,[R13,#0]		;Load the window base address
		BL	dbox_fromDefn		;Try to create a dialogue
		BVS	%05bnr_doBanner		;If we couldn't, don't care
		MOV	R10,R0			;Get the dialogue handle

		; --- If we need to, build a dbx block ---

		CMP	R9,#-1			;Do we have a slider icon?
		ADRNE	R14,bnr__dbx		;Yes -- point to dbx skeleton
		ADDNE	R1,R13,#8		;Point to some spare memory
		LDMNEIA	R14!,{R3-R5}		;Load some values out
		MOVNE	R2,R9			;Get the icon handle
		STMNEIA	R1!,{R2-R5}		;Store them away
		LDMNEIA	R14!,{R2-R5}		;Load some more values
		STMNEIA	R1!,{R2-R5}		;Save them away too
		ADDNE	R1,R13,#8		;Point to the dbx block
		BLNE	dbx_declare		;And attach the definition

		; --- Set up an event handler ---

		MOV	R1,#0			;I don't have a handler
		ADD	R2,R13,#40		;Point to spare word
		MOV	R3,#0			;Don't care about R12
		BL	dbox_eventHandler	;Set up the event handler

		; --- Now set up the dialogue box ---

		CMP	R7,#0			;Does he have a setup routine
		LDRNE	R12,[R13,#48]		;Load caller's R12 value
		MOVNE	R14,PC			;Set up return address
		MOVNE	PC,R7			;And call his routine

		ADD	R7,R13,#40		;Point to count word
		BL	bnr__count		;Update the counter

		; --- Display the dialogue box ---
		;
		; This is a horrible hack, but I don't care.

		MOV	R1,#dbOpen_centre+dbOpen_persist+dbOpen_nonSub
		BL	dbox_open		;Set up the position nicely
		BL	dbox_window		;Get the window handle
		ORR	R0,R0,#1<<31		;Don't constrain the mouse
		BL	nopoll_open		;Set up a fake redraw request
		MOV	R1,R11			;Do this in the scratchpad
		MOV	R0,#1			;Don't care about event mask
		BL	event_poll		;Send that fake event
		BL	nopoll_close		;Shut nopoll up now

		; --- Now we need to count the things to initialise ---

05bnr_doBanner	ADD	R7,R13,#40		;Point to count word (again)
		LDR	R5,[R13,#52]		;Load the lib init block
		ADD	R5,R5,#4		;Skip past program end

		ADR	R0,bnr__ownTable	;Point to our own init table
		LDMIA	R0,{R0,R1}		;Load the base and limit
		SUB	R0,R1,R0		;Find the table size
		MOV	R6,R0,LSR #4		;Divide by size of entry

		MOV	R2,R5			;Get a copy of his table
10bnr_doBanner	LDMIA	R2!,{R0,R1}		;Load the base and limit
		CMP	R0,#-1			;Is this the end yet?
		SUBNE	R0,R1,R0		;Find the table size
		ADDNE	R6,R6,R0,LSR #4		;Add on number in this table
		BNE	%10bnr_doBanner		;And carry on going

		SUB	R2,R2,#4		;We overshot a bit
		LDMIA	R2,{R3,R4}		;Load extension table values
12bnr_doBanner	CMP	R3,R4			;Reached the end yet?
		BCS	%15bnr_doBanner		;Yes -- phew!
		MOV	R14,PC			;Set up return address
		LDR	PC,[R3],#4		;Call finding routine
		SUB	R0,R1,R0		;Find the table size
		ADD	R6,R6,R0,LSR #4		;Add on number in this table
		B	%12bnr_doBanner		;And carry on going

		; --- Now actually initialise things ---


15bnr_doBanner	MOV	R4,#0			;Nothing initialised yet
		LDR	R2,sapph_workspace	;Load the main workspace base
		ADR	R0,bnr__ownTable	;Point to our own init table
		LDMIA	R0,{R0,R1}		;Load the base and limit
		BL	bnr__init		;Initialise these bits

20bnr_doBanner	LDMIA	R5!,{R0,R1}		;Load base and limit from tbl
		CMP	R0,#-1			;Is this the end yet?
		BLNE	bnr__init		;No -- initialise from here
		BNE	%20bnr_doBanner		;And carry on going

		SUB	R5,R5,#4		;We went a little too far
		LDMIA	R5,{R3,R5}		;Find the extension table
25bnr_doBanner	CMP	R3,R5			;Have we finished yet?
		BCS	%30bnr_doBanner		;Yes -- better stop then
		MOV	R14,PC			;Set up return address
		LDR	PC,[R3],#4		;Call this routine
		LDR	R2,[R11,-R2]		;Load the workspace base
		BL	bnr__init		;Do some initialisation
		B	%25bnr_doBanner		;And keep on going

		; --- Ahhh -- finished ---

		CMP	R10,#0			;Do we have a dialogue box?
		BEQ	%32bnr_doBanner		;No -- don't wait then
30bnr_doBanner	SWI	OS_ReadMonotonicTime	;What's the time, Mr Computer
		ADD	R1,R0,#50		;Wait for a second
31bnr_doBanner	SWI	OS_ReadMonotonicTime	;What's the time, Mr Computer
		CMP	R0,R1			;Waited long enough?
		BMI	%31bnr_doBanner		;No -- keep waiting then

32bnr_doBanner	MOVS	R0,R10			;Get the dialogue handle
		BLNE	dbox_destroy		;Trash it if I created it
		LDR	R14,[R13,#0]		;Load the dialogue anchor
		CMP	R14,#0			;Did I create it?
		ADDNE	R0,R13,#0		;Yes -- point to the anchor
		BLNE	flex_free		;And free the block
		LDR	R14,[R13,#4]		;Load the sprite anchor
		CMP	R14,#0			;Did I create it?
		ADDNE	R0,R13,#4		;Yes -- point to the anchor
		BLNE	flex_free		;And free the block

		BL	hour_off		;Turn off the hourglass now

		ADD	R13,R13,#44		;Restore the stack pointer
		LDMFD	R13!,{R0-R10,R12,PC}^	;And return to caller

bnr__template	DCB	"banner",0
bnr__tfile	DCB	"Templates",0

bnr__dbx	DCD	slider
		DCD	dbxFlag_dataR10+slFlag_horizontal
		DCD	28
		DCD	0
		DCB	8,1,1,0
		DCD	100
		DCD	-1

bnr__ownTable	DCD	|Sapphire$$LibData$$Base|
		DCD	|Sapphire$$LibData$$Limit|

		LTORG

; --- bnr__init ---
;
; On entry:	R0 == base of initialisation table
;		R1 == limit of initialisation table
;		R2 == pointer to workspace base
;		R4 == number of units initialised so far
;		R6 == number of items to initialise
;		R7 == address of count word
;		R8 == counter icon number
;		R9 == slider icon number
;		R10 == banner dialogue handle
;
; On exit:	--
;
; Use:		Initialises a load of library units.

bnr__init	ROUT

		STMFD	R13!,{R0-R3,R5,R14}	;Save some registers
		MOV	R3,R0			;Look after this pointer
		LDR	R0,sapph_appName	;Find application's name
00bnr__init	CMP	R3,R1			;Have we finished yet?
		LDMCSFD	R13!,{R0-R3,R5,PC}^	;Yes -- then return
		LDR	R5,[R3,#12]		;Load the init routine addr
		ADD	R3,R3,#16		;Move the pointer on a bit
		CMP	R5,#0			;Is there an init routine?
		MOVNE	R14,PC			;Yes -- set up return address
		MOVNE	PC,R5			;And call the routine

		STMFD	R13!,{R0,R1}		;Save some registers
		ADD	R4,R4,#100		;Initialised another one
		MOV	R0,R4			;Get the value in R0
		MOV	R1,R6			;How many there actually are
		BL	div_round		;Work out the percentage
		STR	R0,[R7,#0]		;Save the count word away
		BL	bnr__count		;Update the counter
		LDMFD	R13!,{R0,R1}		;And restore the registers

		B	%00bnr__init		;And go round again

		LTORG

; --- bnr__count ---
;
; On entry:	R7 == address of current percentage
;		R8 == count icon number
;		R9 == slider icon number
;		R10 == dialogue box handle
;
; On exit:	--
;
; Use:		Displays the count of how much we've done in some cunning
;		way.

bnr__count	ROUT

		STMFD	R13!,{R0-R2,R14}	;Save some registers
		CMP	R10,#0			;Do we have a dialogue box?
		BEQ	%50bnr__count		;Yes -- handle that then

		CMP	R9,#-1			;Do we have a slider?
		MOVNE	R0,R10			;Yes -- get the dialogue
		MOVNE	R1,R9			;And the icon handle
		BLNE	dbx_update		;And redraw the slider

		CMP	R8,#-1			;Do we have a count icon?
		LDRNE	R0,[R7,#0]		;Yes -- get the current value
		MOVNE	R1,R11			;Point to the scratchpad
		MOVNE	R2,#256			;Give the size of the buffer
		SWINE	OS_ConvertInteger4	;Convert it to an integer
		MOVNE	R2,R0			;Point to this text
		MOVNE	R0,R10			;Get the dialogue handle
		MOVNE	R1,R8			;And the icon handle
		BLNE	dbox_setField		;And write in the data
		LDMFD	R13!,{R0-R2,PC}^	;Return to caller

50bnr__count	LDR	R0,[R7,#0]		;Get the current value
		SWI	Hourglass_Percentage	;Put it in the hourglass
		LDMFD	R13!,{R0-R2,PC}^	;And return to caller

		LTORG

; --- Flags ---

bFlag_slider	EQU	(1<<0)			;Has a progress slider
						;+0 icon number for slider
						;+4

bFlag_counter	EQU	(1<<1)			;Has a percentage indicator
						;+0 icon number for indicator
						;+4

bFlag_setup	EQU	(1<<2)			;Needs a setup routine
						;+0 == address of routine
						;+4

bFlag_sprites	EQU	(1<<3)			;Load a sprite file
						;+0 == name of sprite file
						;+n

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

		END
