;
; report.s
;
; A simple report box handler (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

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

		GET	sapphire:buttons
		GET	sapphire:errorBox
		GET	sapphire:except
		GET	sapphire:msgs
		GET	sapphire:sapphire
		GET	sapphire:seh
		GET	sapphire:string

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

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- report_register ---
;
; On entry:	R0 == pointer to routine to use
;		R1 == R12 to pass to the routine
;		R2 == stack pointer to set when it gets control
;
; On exit:	--
;
; Use:		Registers a resume point so that the application can recover
;		from errors.  Error messages are reported using errorBox.

		EXPORT	report_register
report_register	ROUT

		STMFD	R13!,{R0,R1,R12,R14}	;Save some registers
		WSPACE	report__wspace		;Get my workspace pointer
		STMIA	R12,{R0,R1}		;Save these for later
		ADR	R0,report__report	;Point to my own resumer
		MOV	R1,R12			;And set up my workspace
		BL	except_returnPt		;Set this up as the handler
		LDMFD	R13!,{R0,R1,R12,PC}^	;Return to the caller

; --- report__report ---
;
; On entry:	R0 == pointer to an error block
;
; On exit:	R0 == pointer to user-supplied resume point
;		R1 == value of R12 to pass to the resume point
;
; Use:		Pops up an error box reporting the error in a `OK to
;		continue, Cancel to cancel program' type way.

report__report	ROUT

		STMFD	R13!,{R14}		;Save some registers
		BL	report_error		;Ask the user about quitting
		LDMIA	R12,{R0,R1}		;Get the resume point out
		LDMFD	R13!,{PC}^		;Return to caller

		LTORG

; --- report_catchAll ---
;
; On entry:	--
;
; On exit:	R13 modified
;
; Use:		Sets up an exception handler to catch errors and other SEH
;		exceptions.  Errors are reported in the usual way, and the
;		user is given the option to close the application.  Other
;		exceptions are reported as errors.

		EXPORT	report_catchAll
report_catchAll	ROUT

		STMFD	R13!,{R0-R12,R14}	;Save some registers
report__resume	MOV	R12,R13			;Remember where this lot is
		ADR	R0,report__catch	;Point to the try block
		BL	seh_try			;Register it with SEH
		LDMIA	R12,{R0-R12,PC}^	;And return to caller

report__catch	MOVS	PC,R14
		DCW	&FFFF,1
		B	report__catchErr
		DCD	-1
		B	report__catchUK
		DCD	0

report__catchUK	ADR	R0,report__special	;Point to emergency try block
		BL	seh_try			;Register that nicely
		MOV	R2,R0			;Put the exception in R2
		ADR	R0,report__ukExc	;Point to error skeleton
		BL	msgs_error		;Translate the message
		MOV	R1,R0			;And move error to R1
		B	%f00			;Skip emergency handler

report__catchErr
		ADR	R0,report__special	;Point to emergency try block
		BL	seh_try			;Register that nicely
00		MOV	R0,R1			;Point to the error block
		BL	report_error		;Report it to the user
		BL	seh_unTry		;Remove emergency handler
		B	report__resume		;And resume the application

report__ukExc	DCD	1
		DCB	"rptUKEXC",0

report__special	MOVS	PC,R14
		DCD	-1
		B	report__abort
		DCD	0

report__abort	ADR	R0,report__badExc	;Point to the error message
		B	except_fatal		;And report it, and die

report__badExc	DCD	&80000000
		DCB	"Fatal error: couldn't recover from error",0

		LTORG

; --- report_error ---
;
; On entry:	R0 == pointer to error
;
; On exit:	--
;
; Use:		Prompts the user about quitting the application in response
;		to a really bad error.  If the user decides to quit, we
;		quit.  Otherwise we return.

		EXPORT	report_error
report_error	ROUT

		STMFD	R13!,{R0-R4,R14}	;Save lots of registers

		; --- Set up the message to display in the box ---

		ADD	R3,R0,#4		;Point to error message
		LDR	R4,[R0,#-4]		;Get PC when error happened
		BIC	R4,R4,#&FC000003	;Clear off nasty PSR bits
		LDR	R2,sapph_appName	;Keep this name pointer
		ADR	R0,report__msg1		;Point to the error skeleton
		BL	msgs_error		;Construct the error message

		; --- Display the message and get a response ---

		ADR	R1,report__buttons	;Point to buttons block
		BL	errorBox		;Do all the real business
		BCS	%10report_error		;If OK, skip ahead

		; --- If the user pressed Cancel, we give another go ---

		ADR	R0,report__msg2		;Point to confirm message
		BL	msgs_error		;Construct the error message
		ADR	R1,report__buttons	;Point to buttons block
		BL	errorBox		;Get another response
		SWICC	OS_Exit			;If `Quit' then we die

10report_error	LDMFD	R13!,{R0-R4,PC}^	;Return to caller

report__msg1	DCD	1
		DCB	"rptERR",0

report__msg2	DCD	1
		DCB	"rptCONF",0

report__buttons	BUTTON	"rptCONT"
		BCANCEL	"rptQUIT"
		BUTEND

		LTORG

report__wspace	DCD	0			;Workspace pointer

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

		^	0,R12
report_wstart	#	0

report_routine	#	4			;Pointer to resume routine
report_R12	#	4			;Value of R12 it wants

report_wsize	EQU	{VAR}-report_wstart

		AREA	|Sapphire$$LibData|,CODE,READONLY

		DCD	report_wsize		;Workspace size I want
		DCD	report__wspace		;Pointer to my pointer :-/
		DCD	0			;No scratchpad required
		DCD	0			;No initialisation either

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

		END
