;
; setrix.s
;
; Setup program for Sculptrix
;
;  1995-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's Sculptrix.
;
; Sculptrix 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.
;
; Sculptrix 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 Sculptrix.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

;----- Revision history -----------------------------------------------------
;
; Version	By	Change
;
; 1.00		MDW	Initial version written to accompany Sculptrix 2.00

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

		GET	libs:header
		GET	libs:swis

		GET	libs:stream

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

		GET	sapphire:buttons
		GET	sapphire:dbox
		GET	sapphire:defHandler
		GET	sapphire:errorBox
		GET	sapphire:fastMove
		GET	sapphire:flex
		GET	sapphire:event
		GET	sapphire:help
		GET	sapphire:hour
		GET	sapphire:ibicon
		GET	sapphire:menu
		GET	sapphire:menuDefs
		GET	sapphire:msgs
		GET	sapphire:progInfo
		GET	sapphire:ptr
		GET	sapphire:report
		GET	sapphire:res
		GET	sapphire:resources
		GET	sapphire:sapphire
		GET	sapphire:screen
		GET	sapphire:seh
		GET	sapphire:string
		GET	sapphire:warning

		GET	sapphire:choices.choices

		GET	sapphire:dbx.colourPot
		GET	sapphire:dbx.dbx

		GET	sapphire:xfer.load
		GET	sapphire:xfer.save
		GET	sapphire:xfer.saveAs

		IMPORT	cright
		IMPORT	version

;----- Icon handles ---------------------------------------------------------

sxIcon__cols	EQU	12			;Main colour table
sxIcon__hilite	EQU	22			;Highlight colour
sxIcon__slab	EQU	24			;Slabbed background
sxIcon__ccGrp	EQU	26			;CC-style group box
sxIcon__acGrp	EQU	27			;Acorn-style group box
sxIcon__ok	EQU	28			;OK button
sxIcon__save	EQU	29			;Save button
sxIcon__cancel	EQU	30			;Cancel button

;----- Configuration blocks -------------------------------------------------

		^	0
sxConf__magic	#	4			;Magic identifier word
sxConf__flags	#	4			;Various flags
sxConf__stdCols	#	2			;Standard colour pair
sxConf__grpCols	#	2			;Group colour pair
sxConf__shdCols	#	2			;Shaded normal colours
sxConf__shgCols	#	2			;Shaded group colours
sxConf__hilite	#	1			;The highlight colour
sxConf__slab	#	1			;The slabbing colour
		#	2			;Alignment padding
sxConf__size	#	0

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

		^	0,R12
sx__wStart	#	0

sx__flags	#	4			;Various usefule flags
sx__dbox	#	4			;The dialogue box handle
sx__anchor	#	4			;A flex anchor for loading
sx__config	#	sxConf__size		;Configuration buffer
sx__filename	#	256			;Filename buffer
sx__pollBlk	#	256			;Block for Wimp_Poll

sx__wSize	EQU	{VAR}-sx__wStart

sxFlag__safe	EQU	(1<<0)			;File has been saved
sxFlag__saving	EQU	(1<<1)			;We're saving a file

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

		AREA	|Client$$Code|,CODE,READONLY
		ENTRY

; --- main ---
;
; On entry:	--
;
; On exit:	Via OS_Exit
;
; Use:		Starts up the application.

main		ROUT

		ADR	R0,sx__appName		;Point to the app name
		LDR	R1,=sx__wSize		;Get the workspace size
		MOV	R2,#0			;Standard stack size
		BL	sapphire_init		;Set up the memory map
		BL	sx__preInit		;Do pre-initialisation
		BL	sapphire_libInit	;Crank up the library
		BL	sx__init		;Do other initialisation

		BL	seh_throwErrors		;Throw errors at ne, please
		BL	report_catchAll		;Install last error handler

00		MOV	R0,#0			;Don't get idle events
		ADR	R1,sx__pollBlk		;Point to the poll block
		BL	event_poll		;Do some polling
		BLCC	sx__unknowns		;Handle unknowns ourselves
		BLCC	defHandler		;Do default handling
		B	%b00			;And keep looping

sx__appName	DCB	"Setrix",0

		LTORG

; --- sx__preInit ---
;
; On entry:	--
;
; On exit:	R0-R10 corrupted
;
; Use:		Does any initialisation required before Sapphire is started,

sx__preInit	ROUT

		STMFD	R13!,{R14}		;Save return address
		BL	hour_init		;Initialise hourglass
		BL	hour_on			;Turn on the hourglass
		BL	resources_init		;Fetch shared resources
		LDMFD	R13!,{PC}^		;And return to caller

		LTORG

; --- sx__init ---
;
; On entry:	--
;
; On exit:	R0-R10 corrupted
;
; Use:		Initialises the rest of the application.

sx__init	ROUT

		STMFD	R13!,{R14}		;Save return address
		BL	sx__initWork		;Initialise the workspace
		BL	sx__loadConf		;Load the config file
		BL	ptr_blinkOn		;Turn on the blinking cursor
		BL	sx__iconBar		;Set up the icon bar
		LDMFD	R13!,{PC}^		;And return to caller

		LTORG

; --- sx__initWork ---
;
; On entry:	--
;
; On exit:	R0-R10 corrupted
;
; Use:		Sets up the workspace.

sx__initWork	ROUT

		STMFD	R13!,{R14}		;Save a register

		; --- Set up some odd bits ---

		MOV	R14,#0			;Clear the handle
		STR	R14,sx__dbox		;Store in the workspace

		MOV	R14,#sxFlag__safe	;The file is safe currently
		STR	R14,sx__flags		;Store the flags away

		; --- Set up default filename ---

		MOV	R0,#0			;Use a default filename
		BL	sx__setFilename		;Set the filename, please

		; --- Set up the config buffer ---

		LDR	R14,sx__magic		;Load the magic number
		ADR	R0,sx__config		;Point to the config buffer
		STR	R14,[R0],#4		;Store it in there
		MOV	R1,#sxConf__size-4	;Size of my buffer
		SWI	Sculptrix_ReadConfig	;Read the configuration
		LDMFD	R13!,{PC}^		;And return to caller

		LTORG

; --- sx__loadConf ---
;
; On entry:	--
;
; On exit:	R0-R10 corrupted
;
; Use:		Loads the default config file, if there is one.

sx__loadConf	ROUT

		STMFD	R13!,{R14}		;Save the return address

		MOV	R0,#1			;Enable use of `Choices'
		BL	choices_useChoices	;So do that, then

		ADR	R0,sx__confFile		;Point to the file name
		MOV	R1,R11			;Build name in scratchpad
		MOV	R2,#0			;Not going to write to it
		BL	choices_find		;Find the filename
		BCC	%90sx__loadConf		;If not there, skip on

		MOV	R1,R0			;Point to the filename
		ADR	R10,sx__config		;Point to config block
		BL	sx__ldFile		;Try to load the file
		BLVC	sx__ldDone		;If OK, set it up nicely

90sx__loadConf	LDMFD	R13!,{PC}^		;And return to caller

sx__magic	DCB	"SXCF"
sx__confFile	DCB	"Config",0

		LTORG

; --- sx__iconBar ---
;
; On entry:	--
;
; On exit:	R0-R10 corrupted
;
; Use:		Creates the icon bar icon.

sx__iconBar	ROUT

		STMFD	R13!,{R14}		;Save a register
		ADR	R0,sx__ibSprite		;Point to the sprite name
		MOV	R1,#0			;No text, please
		MOV	R2,#-1			;Put icon on the right
		MOV	R3,#0			;No priority things, please
		ADR	R4,sx__ibHandler	;Point to the handler
		ADR	R5,sx__config		;No document passed in R10
		MOV	R6,R12			;Pass workspace in R12
		BL	ibicon_create		;Create the icon, please
		SWIVS	OS_GenerateError	;If failed, raise an error
		LDMFD	R13!,{PC}^		;And return to caller

sx__ibSprite	DCB	"!setrix",0

		LTORG

; --- sx__ibHandler ---
;
; On entry:	R0 == event code
;
; On exit:	--
;
; Use:		Handles events for the icon bar icon.

sx__ibHandler	ROUT

		CMP	R0,#(%10-%00)/4		;Is the event in range?
		ADDCC	PC,PC,R0,LSL #2		;Yes -- dispatch it then
		MOVS	PC,R14			;Otherwise return now

00		B	sx__showDbox
		B	sx__ibCrtMenu
		MOVS	PC,R14
		B	sx__load
		B	sx__load
		B	sx__ibHelp
10
		; --- Display the icon bar menu ---

sx__ibCrtMenu	STMFD	R13!,{R0-R3,R14}	;Save some registers
		ADR	R0,sx__ibMenu		;Point to the menu block
		ADR	R1,sx__mnHandler	;Point to the handler
		MOV	R2,R10			;Pass R10 to handler
		MOV	R3,R12			;Pass R12 to handler
		BL	menu_create		;Create the menu, please
		LDMFD	R13!,{R0-R3,PC}^	;And return to caller

sx__ibMenu	MENU	"Setrix"
		ITEM	"sxINF"
		SUBWARN
		ITEM	"sxQUT"
		MENUEND

		; --- Give help to a user ---

sx__ibHelp	STMFD	R13!,{R0,R14}		;Save some registers
		ADR	R0,sx__ibHelpTag	;Point to help tag
		BL	msgs_lookup		;Translate the tag
		BL	help_add		;Add it to the help message
		LDMFD	R13!,{R0,PC}^		;And return to caller

sx__ibHelpTag	DCB	"sxhIB",0

		LTORG

; --- sx__mnHandler ---
;
; On entry:	R0 == event code
;		R1 == menu item number
;
; On exit:	--
;
; Use:		Handles events on the program menu.

sx__mnHandler	ROUT

		CMP	R0,#mEvent_help		;A help request?
		BEQ	sx__mnHelp		;Yes -- give some help then

		CMP	R0,#mEvent_select	;Is it a click event?
		CMPNE	R0,#mEvent_subMenu	;Or a submenu warning?
		MOVNES	PC,R14			;No -- ignore it then

		CMP	R1,#(%10-%00)/4		;Is the item known?
		ADDCC	PC,PC,R1,LSL #2		;Yes -- dispatch
		MOVS	PC,R14			;Otherwise ignore the event

00		B	sx__showInfo		;Show program information
		B	sx__quit		;Quit the application
10
		; --- Display the Info box ---

sx__showInfo	STMFD	R13!,{R0-R2,R14}	;Save some registers
		ADR	R0,sx__purpose		;Point to the purpose string
		BL	msgs_lookup		;Translate the message
		LDR	R1,=cright		;Point to copyright message
		LDR	R2,=version		;Point to version string
		BL	progInfo		;Display the dialogue
		MOVVS	R1,#1			;If error, get button layout
		BLVS	errorBox		;And report to the user
		LDMFD	R13!,{R0-R2,PC}^	;Return to caller

sx__purpose	DCB	"sxPUR",0

		; --- Try to quit the program ---

sx__quit	STMFD	R13!,{R14}		;Save a register
		BL	sx__okToQuit		;Is it all right to quit?
		SWICS	OS_Exit			;Yes -- do it then
		LDMFD	R13!,{PC}^		;Otherwise return

		; --- Give some help to the user ---

sx__mnHelp	STMFD	R13!,{R0,R14}		;Save some registers
		ADR	R0,sx__mnHelpTag	;Point to the message tag
		BL	menu_help		;Translate and add
		LDMFD	R13!,{R0,PC}^		;Return when done

sx__mnHelpTag	DCB	"sxhMN",0

		LTORG

; --- sx__unknowns ---
;
; On entry:	R0 == event code
;		R1 == pointer to event data
;
; On exit:	R2-R10 corrupted
;		CS to claim
;
; Use:		Handles unknown events.  Specifically, it looks at PreQuit
;		messages, and asks the user if it's OK to quit.

sx__unknowns	ROUT

		CMP	R0,#17			;Is this a message?
		CMPNE	R0,#18			;Check both types
		MOVNES	PC,R14			;No -- ignore it then

		LDR	R2,[R1,#16]		;Load the message code
		CMP	R2,#8			;Is this a PreQuit message?
		MOVNES	PC,R14			;No -- ignore it then

		; --- Handle a PreQuit message ---

		STMFD	R13!,{R0,R1,R14}	;Save a register
		BL	sx__okToQuit		;Ask the user if this is OK
		BCS	%90sx__unknowns		;Yes -- then return now

		; --- Acknowledge the message to prevent quitting ---

		MOV	R0,R11			;Point to scratchpad
		LDR	R2,[R1,#0]		;Load the message size
		BL	fastMove		;Copy the message over

		LDR	R14,[R11,#8]		;This is a reply
		STR	R14,[R11,#12]		;Store the ref away
		MOV	R0,#19			;Send as an acknowledgement
		MOV	R1,R11			;Point to copied message
		LDR	R2,[R11,#4]		;Load the task handle
		SWI	Wimp_SendMessage	;Send the message on

		; --- Now return, claiming the event ---

90sx__unknowns	LDMFD	R13!,{R0,R1,R14}	;Restore registers
		ORRS	PC,R14,#C_flag		;And return, claiming it

		LTORG

; --- sx__okToQuit ---
;
; On entry:	--
;
; On exit:	CS if we're allowed to quit
;
; Use:		Ensures that we're allowed to quit.  If we're in possession
;		of unsaved data, we ask the user first.

sx__okToQuit	ROUT

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

		; --- Check whether the data needs saving ---

		LDR	R14,sx__flags		;Load my flags word
		TST	R14,#sxFlag__safe	;Is the flag set?
		BNE	%90sx__okToQuit		;Yes -- then return OK

		; --- Now ask the user before we go any further ---

		ADR	R0,sx__quitMsg		;Point to the message
		BL	msgs_lookup		;Translate into English
		ADR	R1,sx__quitButts	;Point to button block
		BL	warning			;Ask the user nicely
		BCS	%90sx__okToQuit		;If OK, return this

		LDMFD	R13!,{R0,R1,R14}	;Restore registers
		BICS	PC,R14,#C_flag		;And return not OK

90sx__okToQuit	LDMFD	R13!,{R0,R1,R14}	;Restore registers
		ORRS	PC,R14,#C_flag		;And return OK

sx__quitButts	BUTTON	"sxQTB"
		BCANCEL
		BUTEND

sx__quitMsg	DCB	"sxOTQ",0

		LTORG

;----- Dialogue box handling ------------------------------------------------

; --- sx__showDbox ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Opens the main dialogue box, and sets it up.

sx__showDbox	ROUT

		STMFD	R13!,{R0-R3,R14}	;Save some registers
		LDR	R0,sx__dbox		;Load dialogue box handle
		CMP	R0,#0			;Is the dialogue box open?
		BNE	%80sx__showDbox		;Yes -- just bring it forward

		; --- Create the dialogue box ---

		ADR	R0,sx__dbName		;Point to the dialogue name
		BL	dbox_create		;Create the dialogue box
		BVS	%90sx__showDbox		;If failed, tidy up
		STR	R0,sx__dbox		;Store the new handle

		ADR	R1,sx__dbHandler	;Point to the handler
		ADR	R2,sx__config		;Point to config buffer
		MOV	R3,R12			;Pass R12 pointer on
		BL	dbox_eventHandler	;Set up the event handler

		ADR	R1,sx__dbControls	;Point to dbx defs block
		BL	dbx_declare		;Set up the controls
		BL	sx__dbReset		;Reset the dialogue settings

		; --- Finally, display the dialogue on-screen ---

80sx__showDbox	MOV	R1,#dbOpen_current+dbOpen_persist
		BL	dbox_open		;Display the dialogue box
		LDMFD	R13!,{R0-R3,PC}^	;And return to caller

		; --- Handle an error ---

90sx__showDbox	MOV	R1,#1			;Just an OK button
		BL	errorBox		;Display the error
		LDMFD	R13!,{R0-R3,PC}^	;And return

sx__dbName	DCB	"setrix",0

sx__dbControls	COLPOT	sxIcon__cols+0,R10,sxConf__stdCols+0,0
		COLPOT	sxIcon__cols+1,R10,sxConf__stdCols+1,0
		COLPOT	sxIcon__cols+2,R10,sxConf__grpCols+0,0
		COLPOT	sxIcon__cols+3,R10,sxConf__grpCols+1,0
		COLPOT	sxIcon__cols+4,R10,sxConf__shdCols+0,0
		COLPOT	sxIcon__cols+5,R10,sxConf__shdCols+1,0
		COLPOT	sxIcon__cols+6,R10,sxConf__shgCols+0,0
		COLPOT	sxIcon__cols+7,R10,sxConf__shgCols+1,0

		COLPOT	sxIcon__hilite,R10,sxConf__hilite,0
		COLPOT	sxIcon__slab,R10,sxConf__slab,0

		DBXEND

		LTORG

; --- sx__dbClose ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Closes the dialogue box.

sx__dbClose	ROUT

		STMFD	R13!,{R0,R14}		;Save some registers
		LDR	R0,sx__dbox		;Load the dialogue handle
		BL	dbox_writePos		;Save the position back
		BL	dbox_destroy		;Get rid of the dialogue
		MOV	R14,#0			;Clear the handle in wspace
		STR	R14,sx__dbox		;Store that away
		LDMFD	R13!,{R0,PC}^		;And return to caller

		LTORG

; --- sx__dbHandler ---
;
; On entry:	R0 == dialogue box event code
;		R1-R7 == dependent on the event
;
; On exit:	--
;
; Use:		Handles events in the main dialogue box.

sx__dbHandler	ROUT

		CMP	R0,#sxIcon__ok		;Is this an OK event?
		CMPNE	R0,#dbEvent_OK		;Check for a return press
		BEQ	sx__dbOK		;Yes -- handle the event

		CMP	R0,#sxIcon__save	;Is it the save icon?
		BEQ	sx__dbSave		;Yes -- handle that

		CMP	R0,#sxIcon__cancel	;Is this a cancel event
		CMPNE	R0,#dbEvent_cancel	;Check for an escape
		BEQ	sx__dbCancel		;Yes -- handle it

		CMP	R0,#dbEvent_load	;Is it a load event
		CMPNE	R0,#dbEvent_save	;Or a save -- I don't mind
		BEQ	sx__load		;Load the file

		CMP	R0,#dbEvent_help	;Is it a help event?
		BEQ	sx__dbHelp		;Yes -- give some help then

		MOVS	PC,R14			;Otherwise, do nothing

		; --- Handle a click on the OK button ---

sx__dbOK	STMFD	R13!,{R0-R2,R14}	;Save some registers
		MOV	R2,R1			;Remember this value
		LDR	R0,sx__dbox		;Load the dialogue handle
		MOV	R1,#sxIcon__ok		;Get the icon handle
		BL	dbox_slab		;Pop the icon in
		BL	sx__dbRead		;Read the icon settings
		TST	R2,#1			;Is the adjust button down?
		BLEQ	sx__dbClose		;Maybe close the dialogue
		BL	dbox_unslab		;Unslab the button
		LDMFD	R13!,{R0-R2,PC}^	;And return to caller

		; --- Handle a click on the Save button ---

sx__dbSave	STMFD	R13!,{R0,R1,R14}	;Save some registers
		LDR	R0,sx__dbox		;Load the dialogue handle
		MOV	R1,#sxIcon__save	;Get the icon handle
		BL	dbox_slab		;Pop the icon in
		BL	sx__dbRead		;Read the icon settings
		BL	sx__save		;Start the save box
		BL	dbox_unslab		;Unslab the button
		LDMFD	R13!,{R0,R1,PC}^	;And return to caller

		; --- Handle a click on the cancel button ---

sx__dbCancel	STMFD	R13!,{R0-R2,R14}	;Save some registers
		MOV	R2,R1			;Remember this value
		LDR	R0,sx__dbox		;Load the dialogue handle
		MOV	R1,#sxIcon__cancel	;Get the icon handle
		BL	dbox_slab		;Pop the icon in

		ADD	R0,R10,#sxConf__flags	;Point past the magic number
		SWI	Sculptrix_ReadConfig	;Read the config back

		TST	R2,#1			;Is the adjust button down?
		BLEQ	sx__dbClose		;Maybe close the dialogue
		BLNE	sx__dbReset		;Maybe reset the settings

		BL	dbox_unslab		;Unslab the button
		LDMFD	R13!,{R0-R2,PC}^	;And return to caller

		; --- Give some help to a user ---

sx__dbHelp	STMFD	R13!,{R0,R14}		;Save some registers
		ADR	R0,sx__dbHelpTag	;Point to the message tag
		BL	msgs_lookup		;Translate the message
		BL	help_add		;Add it to the help message
		BL	dbox_help		;Read help from an icon
		LDMFD	R13!,{R0,PC}^		;Return when done

sx__dbHelpTag	DCB	"sxhDB",0

		LTORG

; --- sx__dbReset ---
;
; On entry:	R0 == dialogue box handle
;		R10 == pointer to config buffer
;
; On exit:	--
;
; Use:		Resets the settings shown in the dialogue box.

sx__dbReset	ROUT

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

		; --- Do the colour box ---

		LDR	R0,sx__dbox		;Load the dialogue handle
		ADR	R2,sx__dbxList		;Point to the icon number tbl
00		LDRB	R1,[R2],#1		;Load the next number out
		CMP	R1,#&FF			;Is this the end?
		BLNE	dbx_update		;No -- update the icon
		BNE	%b00			;And loop back

		; --- Set the radio buttons ---

		LDR	R14,[R10,#sxConf__flags] ;Load the flags word
		TST	R14,#1			;Is the `Acorn style' bit on?
		MOVEQ	R1,#sxIcon__ccGrp	;No -- turn on CC icon
		MOVNE	R1,#sxIcon__acGrp	;Yes -- turn on Acorn icon
		BL	dbox_radio		;Select the right one

		LDMFD	R13!,{R0-R2,PC}^	;And return to caller

sx__dbxList	DCB	sxIcon__cols+0
		DCB	sxIcon__cols+1
		DCB	sxIcon__cols+2
		DCB	sxIcon__cols+3
		DCB	sxIcon__cols+4
		DCB	sxIcon__cols+5
		DCB	sxIcon__cols+6
		DCB	sxIcon__cols+7
		DCB	sxIcon__hilite
		DCB	sxIcon__slab
		DCB	&FF

		LTORG

; --- sx__dbRead ---
;
; On entry:	R0 == dialogue box handle
;
; On exit:	--
;
; Use:		Reads the settings in the dialogue box, and maybe updates
;		the screen.

sx__dbRead	ROUT

		STMFD	R13!,{R0,R1,R14}	;Save some registers
		MOV	R1,#sxIcon__acGrp	;Find the Acorn button
		BL	dbox_isSelected		;Is the icon selected?
		LDR	R14,[R10,#sxConf__flags] ;Load the flags word
		ORRCS	R14,R14,#1		;If on, set the flag
		BICCC	R14,R14,#1		;Otherwise clear it
		STR	R14,[R10,#sxConf__flags] ;Store the flags back
		LDR	R14,sx__flags		;Load the main flags word
		BIC	R14,R14,#sxFlag__safe	;We've modified the file
		STR	R14,sx__flags		;Save them back now
		BL	sx__update		;Send it off to the module
		LDMFD	R13!,{R0,R1,PC}^	;Return to caller

		LTORG

; --- sx__update ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Updates the Sculptrix configuration.

sx__update	ROUT

		STMFD	R13!,{R0-R4,R14}	;Save some registers
		ADD	R0,R10,#sxConf__flags	;Find the main block
		SWI	Sculptrix_SetConfig	;Set the configuration
		BCC	%90sx__update		;If nothing changed, return
		BL	screen_getInfo		;Read the information
		ADD	R14,R0,#screen_width	;Find the dimensions
		LDMIA	R14,{R3,R4}		;Load them out
		MOV	R0,#-1			;Redraw the whole screen
		MOV	R1,#0			;Start at the left
		MOV	R2,#0			;And the bottom
		SWI	Wimp_ForceRedraw	;Refresh the screen
90sx__update	LDMFD	R13!,{R0-R4,PC}^	;And return to caller

		LTORG

;----- Data transfer --------------------------------------------------------

; --- sx__setFilename ---
;
; On entry:	R0 == pointer to filename, or 0
;
; On exit:	--
;
; Use:		Sets the filename used for saving.

sx__setFilename	ROUT

		STMFD	R13!,{R0-R2,R14}	;Save some registers
		CMP	R0,#0			;Do we want the default?
		ADREQL	R0,sx__confFile		;Yes -- use that then
		ADR	R1,sx__filename		;Point to output buffer
		MOV	R2,#256			;Size of the buffer
		ORR	R2,r2,#&C0000000	;Suppress nasty transforms
		SWI	OS_GSTrans		;Do the copy
		LDMFD	R13!,{R0-R2,PC}^	;And return to caller

		LTORG

; --- sx__replace ---
;
; On entry:	R0 == pointer to filename
;		R1 == safeness flag
;		R2 == pointer to old filename, or 0
;
; On exit:	CS if we can replace the file
;
; Use:		Finds out if it's safe to replace a file.

sx__replace	ROUT

		STMFD	R13!,{R0-R2,R14}	;Save some registers
		CMP	R1,#0			;Is the file safe?
		BEQ	%90sx__replace		;No -- then it's OK

		MOVS	R1,R2			;Point to old filename
		BEQ	%f00			;If none, we must ask
		BL	str_icmp		;Compare the strings
		BEQ	%90sx__replace		;If they match, carry on

00		BL	res_exists		;Does the file exist?
		BCC	%90sx__replace		;No -- then we can proceed

		MOV	R2,R0			;Point to the filename
		ADR	R0,sx__replMsg		;Point to message skeleton
		BL	msgs_lookup		;Translate that for me
		BL	str_buffer		;Find a handy buffer
		BL	str_subst		;And build me a message
		ADR	R1,sx__replButts	;Point to buttons
		BL	warning			;Ask the user about this
		BCS	%90sx__replace		;OK -- carry on then

		LDMFD	R13!,{R0-R2,R14}	;Restore registers
		BICS	PC,R14,#C_flag		;And say we mustn't do this

90sx__replace	LDMFD	R13!,{R0-R2,R14}	;Restore registers
		ORRS	PC,R14,#C_flag		;And say we can carry on

sx__replButts	BUTTON	"sxRPLB"
		BCANCEL
		BUTEND

sx__replMsg	DCB	"sxRPLF",0

		LTORG

; --- sx__save ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Starts a save operation.

sx__save	ROUT

		STMFD	R13!,{R0-R5,R14}	;Save some registers
		MOV	R0,#sxConf__size	;Size of the block
		LDR	R1,=&FFD		;Get the filetype (data)
		ADR	R2,sx__filename		;Point to filename buffer
		ADR	R3,sx__savers		;Point to saver block
		MOV	R4,R10			;Point to block to save
		MOV	R5,R12			;Pass workspace along too
		BL	saveAs			;Save the file then
		BVS	%80sx__save		;If it failed, tidy up
		LDR	R14,sx__flags		;Load our flags word
		ORR	R14,R14,#sxFlag__saving	;Set the saving flag
		STR	R14,sx__flags		;Save the flags back
		B	%90sx__save		;And return to caller

80sx__save	MOV	R1,#1			;If it failed, get an OK box
		BL	errorBox		;And report the error
90sx__save	LDMFD	R13!,{R0-R5,PC}^	;Return when finished

sx__savers	DCB	"sxSVT",0
		B	sx__svClose
		B	sx__svFile
		B	sx__svSend
		B	sx__svDone
		B	sx__svFail

		LTORG

; --- sx__svClose ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Notes that the dialogue box has been closed.

		EXPORT	sx__svClose
sx__svClose	ROUT

		STMFD	R13!,{R14}		;Save a register
		LDR	R14,sx__flags		;Load our flags word
		BIC	R14,R14,#sxFlag__saving	;Clear the saving flag
		STR	R14,sx__flags		;Save the flags back
		LDMFD	R13!,{PC}^		;And return to caller

		LTORG

; --- sx__svFile ---
;
; On entry:	R0 == pointer to filename
;		R1 == safeness flag
;
; On exit:	May return an error
;
; Use:		Saves the configuration to a file.

sx__svFile	ROUT

		STMFD	R13!,{R0-R5,R14}	;Save some registers
		ADR	R2,sx__filename		;Point to current name
		BL	sx__replace		;Make sure we can replace
		MOVCC	R0,#0			;If not, get null error
		BCC	%90sx__svFile		;And skip onwards

		MOV	R1,R0			;Point to the filename
		MOV	R0,#10			;Save whole file, please
		LDR	R2,=&FFD		;Get the filetype
		MOV	R4,R10			;Point to the file info
		ADD	R5,R4,#sxConf__size	;Get the size information
		SWI	XOS_File		;Save the file, please
		BVS	%90sx__svFile		;If failed, skip on
		LDMFD	R13!,{R0-R5,PC}^	;Return to caller

90sx__svFile	ADD	R13,R13,#4		;Don't restore R0
		LDMFD	R13!,{R1-R5,PC}		;Restore other registers

		LTORG

; --- sx__svSend ---
;
; On entry:	--
;
; On exit:	R0 == pointer to base
;		R1 == length of data
;		CS if this is the last block
;
; Use:		Sends data via RAM transfer.

sx__svSend	ROUT

		MOV	R0,R10			;Point to the data
		MOV	R1,#sxConf__size	;Get the size of the data
		ORRS	PC,R14,#C_flag		;And return with C set

		LTORG

; --- sx__svDone ---
;
; On entry:	R0 == pointer to filename, if file is safe
;		R1 == safeness flag
;
; On exit:	--
;
; Use:		Sets up various nice things, if the file is saved properly.

sx__svDone	ROUT

		CMP	R1,#0			;Is the file safe?
		MOVEQS	PC,R14			;No -- do nothing then

		STMFD	R13!,{R1,R14}		;Save some registers
		BL	sx__setFilename		;Change the filename
		LDR	R14,sx__flags		;Load the flags word
		ORR	R14,R14,#sxFlag__safe	;The file is safe, now
		STR	R14,sx__flags		;Store the flags back
		LDMFD	R13!,{R1,PC}^		;Return when done

		LTORG

; --- sx__svFail ---
;
; On entry:	R0 == pointer to error, or 0
;
; On exit:	--
;
; Use:		Tidies up after a botched save.

sx__svFail	ROUT

		CMP	R0,#0			;Is there something here?
		MOVEQS	PC,R14			;No -- return then

		STMFD	R13!,{R0-R2,R14}	;Save some registers
		ADD	R2,R0,#4		;Point to error text
		ADR	R0,sx__svError		;Point to a skeleton thing
		BL	msgs_error		;Translate the error
		MOV	R1,#1			;Just an OK box, please
		BL	errorBox		;Report the error
		LDMFD	R13!,{R0-R2,PC}^	;And return to caller

sx__svError	DCD	1
		DCB	"sxSVERR",0

		LTORG

; --- sx__load ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Starts a load operation for a configuration file.

sx__load	ROUT

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

		; --- Make sure we're not the saver ---

		LDR	R14,sx__flags		;Load the flags word
		TST	R14,#sxFlag__saving	;Are we the saver?
		BNE	%80sx__load		;Yes -- oops

		; --- Start the load operation ---

		ADR	R0,sx__loaders		;Point to loaders block
		MOV	R1,R10			;Pass data pointer
		MOV	R2,R12			;Pass workspace in R12
		BL	load			;Start the load operation
		B	%90sx__load		;And return to caller

		; --- Report error about saving into ourselves ---

80sx__load	ADR	R0,sx__cantSave		;Point to the error
		BL	msgs_error		;Translate the nastygram
		MOV	R1,#1			;Just an OK button, please
		BL	errorBox		;Report the error
90sx__load	LDMFD	R13!,{R0-R2,PC}^	;Return when done

sx__cantSave	DCD	1
		DCB	"sxCSI",0

sx__loaders	B	sx__ldInitBuf
		B	load_killBuf
		B	load_extendBuf
		B	load_doneBuf
		B	sx__ldFile
		B	sx__ldDone
		B	sx__ldFail

		LTORG

; --- sx__ldInitBuf ---
;
; On entry:	R0 == pointer to `filename'
;		R1 == extimated size
;		R2 == 0
;
; On exit:	R0 == pointer to buffer base
;		R1 == pointer to buffer limit
;		R2 == pointer to anchor
;
; Use:		Creates a buffer for the load job.

sx__ldInitBuf	ROUT

		MOV	R2,#0			;Clear the flex anchor
		STR	R2,sx__anchor		;Store this over the top
		ADR	R2,sx__anchor		;Point to the anchor
		B	load_initBuf		;And initialise the buffer

		LTORG

; --- sx__ldFile ---
;
; On entry:	R0 == pointer to `filename'
;		R1 == pointer to real filename
;		R2 == safeness indicator
;
; On exit:	--
;
; Use:		Loads a file into a buffer.

sx__ldFile	ROUT

		STMFD	R13!,{R0,R2,R14}	;Save some registers
		MOV	R2,#0			;Clear the flex anchor
		STR	R2,sx__anchor		;Store this over the top
		ADR	R2,sx__anchor		;Point to the anchor
		BL	load_file		;Load the file, please
		STRVS	R0,[R13,#0]		;If failed, return error
		LDMFD	R13!,{R0,R2,PC}		;And return to caller

		LTORG

; --- sx__ldDone ---
;
; On entry:	R0 == pointer to `filename'
;		R1 == safeness indicator
;
; On exit:	--
;
; Use:		Handles a newly loaded file.

sx__ldDone	ROUT

		STMFD	R13!,{R0-R2,R14}	;Save some registers
		LDR	R1,sx__anchor		;Load the base of the file
		LDR	R2,[R1,#sxConf__magic]	;Load the first word out
		LDR	R14,sx__magic		;Load the magic number
		CMP	R2,R14			;Do these match up?
		BNE	%80sx__ldDone		;No -- complain then

		; --- Accept the data from the file ---

		ADR	R0,sx__config		;Point to my config buffer
		MOV	R2,#sxConf__size	;Get the block size
		BL	fastMove		;Copy the data over

		ADR	R0,sx__anchor		;Point to the anchor
		BL	flex_free		;Don't want it any more

		; --- Change information about the file ---

		LDR	R0,[R13,#0]		;Load the filename used
		BL	sx__setFilename		;Set this up nicely
		LDR	R14,sx__flags		;Load the flags word
		ORR	R14,R14,#sxFlag__safe	;The file is safe, now
		STR	R14,sx__flags		;Store the flags back

		; --- Update the dialogue box and screen ---

		LDR	R0,sx__dbox		;Load the dialogue handle
		CMP	R0,#0			;Is it defined?
		BLNE	sx__dbReset		;Yes -- reset the settings
		BL	sx__update		;And update Sculptrix too
		B	%90sx__ldDone		;Finally return to caller

		; --- Not all was well with the world ---

80sx__ldDone	ADR	R0,sx__anchor		;Point to the anchor
		BL	flex_free		;Don't want it any more
		ADR	R0,sx__badConfig	;Point to error block
		BL	msgs_error		;Translate the message
		MOV	R1,#1			;Just an OK box, please
		BL	errorBox		;And report the error

90sx__ldDone	LDMFD	R13!,{R0-R2,PC}^	;Return when done

sx__badConfig	DCD	1
		DCB	"sxBDCFG",0

		LTORG

; --- sx__ldFail ---
;
; On entry:	R0 == pointer to error
;
; On exit:	--
;
; Use:		Reports errors after a botched load.

sx__ldFail	ROUT

		CMP	R0,#0			;Is there anything to do?
		MOVEQS	PC,R14			;No -- return then

		STMFD	R13!,{R0-R2,R14}	;Save some registers
		ADD	R2,R0,#4		;Point to the error text
		ADR	R0,sx__ldErr		;Point to error block
		BL	msgs_error		;Translate the error
		MOV	R1,#1			;Report with an OK box
		BL	errorBox		;Report it to the user
		LDMFD	R13!,{R0-R2,PC}^	;And return to caller

sx__ldErr	DCD	1
		DCB	"sxLDERR",0

		LTORG

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

		END
