;
; errorBox.s
;
; Reports errors in an error box (MDW)
;
;  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:buttons
		GET	sapphire:dbox
		GET	sapphire:msgs
		GET	sapphire:nopoll
		GET	sapphire:sapphire
		GET	sapphire:string
		GET	sapphire:template
		GET	sapphire:wimp

;----- Icon numbers ---------------------------------------------------------

ebIcon__title	EQU	3
ebIcon__error	EQU	4
ebIcon__buttons	EQU	5

eb__buts	EQU	4

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

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- errorBox_init ---
;
; On entry:	R0 == pointer to application name
;
; On exit:	--
;
; Use:		Initialises the errorBox system nicely.  It creates the
;		dialogue box now, and just uses it for the rest of the
;		time.

		EXPORT	errorBox_init
errorBox_init	ROUT

		STMFD	R13!,{R0-R3,R12,R14}	;Save some registers
		WSPACE	eb__wSpace		;Load my workspace pointer

		; --- Am I running yet? ---

		LDR	R14,eb__dbox		;Load the dialogue box handle
		CMP	R14,#0			;Has it been defined yet?
		LDMNEFD	R13!,{R0-R3,R12,PC}^	;Yes -- return right now

		; --- Initialise other useful things ---

		BL	wimp_init		;Initialise the WindowMangler
		BL	template_init		;Load lots of templates
		BL	dbox_init		;Allow me to make dboxes
		BL	nopoll_init		;I'll want to use nopoll too

		; --- Create my dialogue box ---

		ADR	R0,eb__dbName		;Point to the dialogue name
		BL	dbox_create		;Create the dialogue box
		SWIVS	OS_GenerateError	;If it failed, abort nastily
		STR	R0,eb__dbox		;Store the handle away

		; --- Fill in the dialogue box title ---

		ADR	R0,eb__errorFrom	;Point to the skeleton
		BL	msgs_lookup		;Translate the string
		MOV	R1,R11			;Fill it in the scratchpad
		LDR	R2,[R13,#0]		;Find the application name
		BL	str_subst		;Substitute the string then
		MOV	R2,R0			;Point to the string
		LDR	R0,eb__dbox		;Get the dialogue handle
		MOV	R1,#-1			;Fill in the title bar
		BL	dbox_setField		;Actually write the string

		; --- Set up the rest of the dialogue box ---

		MOV	R1,#ebIcon__title	;Icon for the embedded title
		BL	dbox_setEmbeddedTitle	;Set up the embedded title
		ADR	R1,eb__dbHandler	;Point to my event handler
		MOV	R2,R0			;Pass dbox handle in R10
		MOV	R3,R12			;Pass workspace in R12
		BL	dbox_eventHandler	;Set up the event handler

		LDMFD	R13!,{R0-R3,R12,PC}^	;Return to the caller

eb__dbName	DCB	"error",0
eb__errorFrom	DCB	"ebERRFRM",0

		LTORG

eb__wSpace	DCD	0

; --- eb__dbHandler ---
;
; On entry:	R0 == reason code
;		R1-... dependant on reason code
;		R10 == dialogue box handle
;		R12 == pointer to workspace
;
; On exit:	Registers preserved
;
; Use:		Handles events for the error box

eb__dbHandler	ROUT

		STMFD	R13!,{R14}		;Save a register
		CMP	R0,#dbEvent_OK		;Is it a return press?
		MOVEQ	R0,#ebIcon__buttons	;Yes -- use the default
		CMP	R0,#dbEvent_cancel	;Is it a cancel?
		LDREQ	R0,eb__cancel		;Yes -- load the button
		CMPEQ	R0,#-1			;Was that defined?
		MOVEQ	R0,#ebIcon__buttons	;No -- use default here too

		SUB	R14,R0,#ebIcon__buttons	;Get the button index
		CMP	R14,#eb__buts		;Is it in range?
		LDMCSFD	R13!,{PC}^		;No -- return

		STMFD	R13!,{R0,R1}		;Save some more registers
		LDR	R1,eb__butFlags		;Which buttons are there?
		MOV	R14,#1			;Use a bit to test
		TST	R1,R14,LSL R0		;Test the correct bit
		LDMEQFD	R13!,{R0,R1,PC}^	;Not created -- return

		MOV	R1,R0			;Put icon into R1
		LDR	R0,eb__dbox		;Find the dialogue handle
		BL	dbox_slab		;Slab the icon in
		BL	dbox_close		;Close the window
		BL	dbox_unslab		;Unslab the icon cunningly
		MOV	R0,R1			;Return the icon number
		BL	nopoll_close		;Return that to errorBox
		LDMFD	R13!,{R0,R1,PC}^	;And return to caller

		LTORG

; --- errorBox_beep ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Sounds the bell (VDU 7) if the CMOS settings dictate that
;		error boxes should cause a beep.

		EXPORT	errorBox_beep
errorBox_beep	ROUT

		STMFD	R13!,{R0-R2,R14}	;Save some registers
		MOV	R0,#161			;Read CMOS locations nicely
		MOV	R1,#197			;Read WimpFlags location
		SWI	OS_Byte			;Do the read operation
		TST	R2,#1<<4		;Do we make noises then?
		SWIEQ	OS_WriteI+7		;Yes -- bleep
		LDMFD	R13!,{R0-R2,PC}^	;Return to caller

		LTORG

; --- errorBox ---
;
; On entry:	R0 == pointer to error block
;		R1 == button style code, or pointer to buttons block
;
; On exit:	R0 == icon number clicked (ordered from the right)
;		CS if R0 == 0, else CC
;
; Use:		Displays an error box on the screen.  The error block
;		doesn't have to have a sensible error number, and doesn't
;		have to	be word aligned, either.
;
;		Since errorBox claims a dialogue box handle on
;		initialisation, it isn't possible for this call to fail.
;		Hence it is ideal for reporting problems like `Out of
;		memory' or `Too many windows'.
;
;		The buttons in the error box may be given either by a code
;		or by a pointer to a buttons block (these may easily be
;		distinguished, since the codes are lower than &8000).
;
;		Standard button arrangements are given by codes, as follows:
;
;		0 == Cancel
;		1 == OK
;		2 == OK, Cancel
;		4 == OK, Help
;		5 == OK, Cancel, Help

		EXPORT	errorBox
errorBox	ROUT

		STMFD	R13!,{R1-R4,R12,R14}	;Save some registers away
		WSPACE	eb__wSpace		;Find my workspace address
		MOV	R4,R0			;Look after error pointer
		LDR	R0,eb__dbox		;Load the dbox handle

		; --- Deal with button codes ---

		CMP	R1,#eb__endButs-eb__stdButs
		ADRCC	R14,eb__stdButs		;If it's a code, find the tbl
		LDRCCB	R1,[R14,R1]		;Load the offset of the block
		ADDCC	R1,R14,R1		;And find the button block

		; --- Set up the buttons ---

		MOV	R2,#ebIcon__buttons	;Find icon base
		MOV	R3,#eb__buts		;Get the number allowed
		BL	buttons_setup		;Set up the dialogue box
		STR	R2,eb__butFlags		;Save the button flags
		STR	R3,eb__cancel		;Save the cancel button

		; --- Set the string in the dbox ---

		MOV	R1,#ebIcon__error	;The right icon for the job
		ADD	R2,R4,#4		;Find the error string
		BL	dbox_setField		;Write the string in nicely

		; --- Display the dialogue ---

		BL	errorBox_beep		;Sound the bell if we need to
		MOV	R1,#dbOpen_centre+dbOpen_persist+dbOpen_nonSub
		BL	dbox_open		;Open centred on the screen

		; --- Handle the dialogue properly ---

		BL	dbox_window		;Find the window handle again
		BL	nopoll_open		;Stop polling for a while
		BL	nopoll_process		;Let nopoll take over
		LDMFD	R13!,{R1-R4,R12,R14}	;Return to caller
		SUBS	R0,R0,#ebIcon__buttons	;Was it the default?
		ORREQS	PC,R14,#C_flag		;Yes -- set C on exit
		BICNES	PC,R14,#C_flag		;No -- clear C then

eb__stdButs	DCB	eb__type0-eb__stdButs
		DCB	eb__type1-eb__stdButs
		DCB	eb__type2-eb__stdButs
		DCB	eb__type3-eb__stdButs
		DCB	eb__type4-eb__stdButs
eb__endButs

eb__type1	BOK
		BUTEND
eb__type2	BOK
eb__type0	BCANCEL
		BUTEND
eb__type3	BOK
		BHELP
		BUTEND
eb__type4	BOK
		BCANCEL
		BHELP
		BUTEND

		LTORG

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

		^	0,R12
eb__wStart	#	0

eb__dbox	#	4			;The dialogue box handle
eb__cancel	#	4			;The cancel button, or none
eb__butFlags	#	4			;Which buttons are available

eb__wSize	EQU	{VAR}-eb__wStart

		AREA	|Sapphire$$LibData|,CODE,READONLY

		DCD	eb__wSize
		DCD	eb__wSpace
		DCD	0
		DCD	errorBox_init

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

		END
