;
; wimp.s
;
; Starting and ending of Wimp tasks (TMA)
;
;  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:except
		GET	sapphire:libOpts
		GET	sapphire:roVersion
		GET	sapphire:sapphire

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

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- wimp_init ---
;
; On entry:	R0 == pointer to application name
;
; On exit:	--
;
; Use:		Initialises the WindowManager, and stores away useful
;		snippets of information, like the task handle we've been
;		given.  It also registers an exit handler so that the Wimp
;		gets closed down.

		EXPORT	wimp_init
wimp_init	ROUT

		STMFD	R13!,{R0-R3,R12,R14}	;Stash some registers
		WSPACE	wimp__wSpace		;Find my workspace

		; --- Make sure I'm not already running ---

		LDR	R0,wimp__taskh		;What's my task handle?
		CMP	R0,#0			;0 is a silly task handle
		LDMNEFD	R13!,{R0-R3,R12,PC}^	;If not silly, quit now

		; --- Find what WIMP version we're set for ---

		LDR	R0,wimp__optName	;Find the option name
		BL	libOpts_find		;Try to find the option block
		LDRCS	R3,[R0,#0]		;If found, load version
		MOVCC	R3,#0			;Otherwise use a default

		; --- Suss out the Wimp version from the OS version ---

		BL	rov_init		;Initialise RISC OS version
		BL	rov_version		;Work out the RISC OS version
		LDR	R14,=310		;Get the number 310
		CMP	R0,R14			;Is it version 3.10 yet?
		MOVLT	R0,#200			;No -- use RISC OS 2
		MOVGE	R0,R14			;Otherwise use RISC OS 3.10

		; --- Now use whichever is bigger ---
		;
		; Woe betides a foolish person who sets wimp_minVersion to
		; be 350 :-)

		CMP	R0,R3			;Which is the biggest?
		MOVLT	R0,R3			;If the user's, use that

		; --- Initialise the Wimp ---

		LDR	R1,=&4B534154		;The traditional magic no.
		LDR	R2,[R13,#0]		;Get the app name pointer
		MOV	R3,#-1			;Give me *all* messages
		SWI	Wimp_Initialise		;Crank up the WindowMangler

		; --- Store useful stuff away ---

		STR	R0,wimp__version	;Store WIMP's real version
		STR	R1,wimp__taskh		;Store my task handle too

		; --- Set me up to close down at the end ---

		BL	except_init		;Make sure except is going
		ADR	R0,wimp__die		;Point to my exit handler
		MOV	R1,R12			;Get my workspace pointer
		BL	except_atExit		;Set it up nicely then

		; --- Return with the knowledge of a job well done ---

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

wimp__optName	DCB	"WIMP"

		LTORG

wimp__wSpace	DCD	0

; --- wimp__die ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Closes down the WindowManager nicely, just so that it
;		doesn't have to do it itself.

wimp__die	ROUT

		STMFD	R13!,{R0,R1,R14}	;Stash my registers
		LDR	R0,wimp__taskh		;Get my task handle
		LDR	R1,=&4B534154		;The magic number again
		SWI	XWimp_CloseDown		;Close down the WIMP then
		LDMFD	R13!,{R0,R1,PC}^	;Return to caller

		LTORG

; --- wimp_taskHandle ---
;
; On entry:	--
;
; On exit:	R0 == the application's task handle
;
; Use:		Returns the application's task handle.

		EXPORT	wimp_taskHandle
wimp_taskHandle	ROUT

		STMFD	R13!,{R14}		;Save a register
		LDR	R0,wimp__wSpace		;Find my workspace offset
		LDR	R14,sapph_workspace	;Load workspace block base
		LDR	R0,[R0,R14]		;Load WIMP version number
		LDMFD	R13!,{PC}^		;Return to caller

		LTORG

; --- wimp_version ---
;
; On entry:	--
;
; On exit:	R0 == the WIMP's version number (may not be the one the
;		      client asked for)
;
; Use:		Returns the WindowManager's version number.

		EXPORT	wimp_version
wimp_version	ROUT

		STMFD	R13!,{R14}		;Save a register
		WSPACE	wimp__wSpace,R0		;Find workspace
		LDR	R0,[R0,#:INDEX: wimp__version]
		LDMFD	R13!,{PC}^		;Return to caller

		LTORG

; --- wimp_strWidth ---
;
; On entry:	R0 == pointer to a string
;
; On exit:	R0 == width of the string in OS units
;
; Use:		Returns the width of a string, as it would be displayed in
;		an icon (i.e. taking into account things like the current
;		desktop font etc.)  The width is exact, so if you want to
;		e.g. draw a box round it, you'll have to add on a little
;		clearance at each end.  8 OS units seems to be a good size
;		for the clearance (so the total width you'd use is given by
;		wimp_strWidth(string)+16, because it has two ends).

		EXPORT	wimp_strWidth
wimp_strWidth	ROUT

		; --- We need to find the string length anyway ---
		;
		; This length calculation is done inline to avoid a
		; dependency on string.  It's not very long, anyway, and
		; it *does* save a MOV R5,R0 :-)

		STMFD	R13!,{R1-R7,R14}	;Save a bunch of registers
		MOV	R5,#0			;Length counter starts at 0
		MOV	R7,#0			;Width so far
		MOV	R6,R0			;Keep string pointer
00wimp_strWidth	LDRB	R14,[R0,R5]		;Get a byte from the string
		CMP	R14,#' '		;Is it a control char?
		ADDCS	R5,R5,#1		;Bump on *anyway* (see above)
		BCS	%00wimp_strWidth	;If more to go, loop back

		; --- Now try to find the current font handle ---

		MOV	R0,#8			;Read Wimp font handle
		SWI	XWimp_ReadSysInfo	;Find out from WindowMangler
		BVS	%01wimp_strWidth	;If Wimp too old/buggy, skip
		CMP	R0,#0			;Is there there a real font?
		BEQ	%01wimp_strWidth	;No -- skip ahead too

		; --- Now suss out the width of the string ---
		;
		; There maybe a shift character on the beginning, so
		; treat that seperately ;-)

		LDRB	R14,[R6,#0]		;Load the first character
		CMP	R14,#&8B		;Is it a shift character
		BNE	%10wimp_strWidth	;No -- jump on a bit
		ADD	R6,R6,#1		;Yes -- point past this char
		MOV	R5,R0			;Look after font handle
		BL	wimp_version		;Get the wimp version
		CMP	R0,#340			;RISC OS 3.5 or higher?
		CMPGE	R1,#1			;Is there a symbol font?
		MOVGE	R0,R1			;Yes -- use this
		MOVGE	R1,R14			;And the shift character
		MOVLT	R0,R5			;Otherwise use current hnd
		MOVLT	R1,#'M'			;...and be generous
		MOV	R2,#(1<<4)		;Return OS coords
		SWI	Font_CharBBox		;Get bounding box
		MOV	R0,R5			;Put normal handle back in R0
		SUB	R7,R3,R1		;Put width in R7

10wimp_strWidth	SWI	Font_SetFont		;Set up the desktop font
		MOV	R1,#1000		;A nice big round number
		MOV	R2,R1			;And another nice big number
		SWI	Font_Converttopoints	;Font_StringWidth is weird
		MOV	R3,R2			;Move coords to right regs
		MOV	R2,R1			;That means both of them
		MOV	R1,R6			;Retreive string pointer
		MOV	R4,#-1			;Don't split the string
		ADD	R5,R5,#1		;Move this counter on one
		SWI	Font_StringWidth	;Find the width of the string
		MOV	R1,R2			;Move coordinates back again
		MOV	R2,R3			;Again, that means both
		SWI	Font_ConverttoOS	;Convert to OS units now
		MOV	R0,R1			;Put the width in R0
		ADD	R0,R0,R7		;Add on previous width
		LDMFD	R13!,{R1-R7,PC}^	;Return to caller, then

		; --- Just normal system font ---

01wimp_strWidth	MOV	R0,R5,LSL #4		;Multiply by character width
		LDMFD	R13!,{R1-R7,PC}^	;Return to caller

		LTORG

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

		^	0,R12
wimp__wStart	#	0

wimp__taskh	#	4			;Wimp task handle
wimp__version	#	4			;Wimp version number

wimp__wSize	EQU	{VAR}-wimp__wStart

		AREA	|Sapphire$$LibData|,CODE,READONLY

		DCD	wimp__wSize
		DCD	wimp__wSpace
		DCD	0
		DCD	wimp_init

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

		END
