;
; tspr.s
;
; Toolsprite hacking for things like border sizes (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:screen
		GET	sapphire:wimp

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

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- tspr_getSprAddr ---
;
; On entry:	--
;
; On exit:	R0 == pointer to tool sprites, or 0 if none
;
; Use:		Returns a pointer to the toolsprites. If the user is using
;		RISC OS 2, or there are no toolsprites defined, then
;		0 is returned.

		EXPORT	tspr_getSprAddr
tspr_getSprAddr	ROUT

		STMFD	R13!,{R1,R2,R14}	;Stack some registers

		BL	wimp_version		;Get the wimp version number
		CMP	R0,#300			;Are we using RISC OS 2?
		MOVLT	R0,#0			;Yes -- no sprites then
		BLT	%90tspr_getSprAddr	;...and return
		SWIEQ	Wimp_BaseOfSprites	;We want this for 3.00
		MOVEQ	R0,R1			;...RAM resident part please
		BEQ	%90tspr_getSprAddr	;...and return
		MOV	R1,#94			;We need to test with 350...
		ADD	R1,R1,#256		;...so create the number
		CMP	R0,R1			;Is version < 3.50?
		BLT	%10			;Yes -- deal with it then

		; --- We are using RISC OS 3.50 or higher ---

		MOV	R0,#9			;Read toolsprite control blk
		SWI	Wimp_ReadSysInfo	;Find it then
		B	%90tspr_getSprAddr	;And return

		; --- We are using RISC OS 3.01 - 3.49 ---

10		ADR	R1,tspr__versionList	;Point to the version list
20		LDR	R2,[R1],#4		;Load the version number
		CMP	R0,R2			;Is it the one we want?
		BLT	%90tspr_getSprAddr	;It isn't in list -- return
		BEQ	%30tspr_getSprAddr	;It is -- deal with it
		CMP	R2,#-1			;Are we at the end?
		MOVEQ	R0,#0			;Yes -- no sprite then
		BEQ	%90tspr_getSprAddr	;...return
		ADD	R1,R1,#4		;Skip past address field
		B	%20tspr_getSprAddr	;And keep searching

		; --- We have located the version number ---

30		STMFD	R13!,{R3-R5}		;Stack some more registers
		LDR	R14,[R1]		;Get the address offset
		MOV	R0,#18			;Look-up module name
		ADR	R1,tspr__moduleName	;Point to the module name
		SWI	OS_Module		;Get information then
		LDR	R0,[R4,R14]		;Get the toolsprite address
		SUB	R0,R0,#4		;Correct it nicely
		LDMFD	R13!,{R3-R5}		;Get registers back

		; --- Return to caller ---

90		LDMFD	R13!,{R1,R2,PC}^	;Unstack registers and return

tspr__moduleName
		DCB	"WindowManager",0
		ALIGN

tspr__versionList
		DCD	316,1676
		DCD	322,1708
		DCD	-1

		LTORG

; --- tspr_borderWidths ---
;
; On entry:	--
;
; On exit:	R0 == title bar height
;		R1 == vertical scroll bar width
;		R2 == horizontal scroll bar height
;
; Use:		Return the width of window tools by looking at the
;		sprites associated with them, rather than creating
;		a temporary window.

		EXPORT	tspr_borderWidths
tspr_borderWidths ROUT

		STMFD	R13!,{R3-R10,R14}	;Stack some registers

		; --- Find out about the current mode ---

		BL	screen_getInfo		;Get some screen information
		MOV	R7,#0			;Flags word so far
		LDR	R9,[R0,#screen_xEig]	;Get the xEig Factor
		LDR	R10,[R0,#screen_yEig]	;and the yEig Factor
		CMP	R9,#1			;Are we in a high...
		CMPEQ	R10,#1			;...resolution mode?
		ORREQ	R7,R7,#1		;Yes -- remember this
		LDR	R1,[R0,#screen_bpp]	;Get the bpp
		CMP	R1,#1			;Monochrome mode?
		ORREQ	R7,R7,#2		;Yes -- remember this too

		; --- Are we using tool sprites? ---

		BL	tspr_getSprAddr		;Find the address of sprites
		CMP	R0,#0			;Are there any?
		BEQ	%80tspr_borderWidths	;No -- get RISC OS 2 defaults
		MOV	R8,R0			;Put sprite block in R8

		; --- Use sprites to get the border widths ---
		;
		; First, find out about the title bar

		ADR	R3,tspr__titleName	;Point to title bar sprite ^
		BL	%50tspr_borderWidths	;Get sprite information
		MOV	R0,R4			;The returned height
		BVC	%20tspr_borderWidths	;All OK -- now vertical
		TST	R7,#1			;Are we in a high res mode?
		MOVNE	R0,#42			;Yes -- use this height
		MOVEQ	R0,#44			;No -- use this height

		; --- Now the vertical scroll bar ---

20		ADR	R3,tspr__vertName	;Point to vert bar sprite ^
		BL	%50tspr_borderWidths	;Get sprite information
		MOVVC	R1,R3			;The returned height
		MOVVS	R1,#42			;The default width

		; --- Finally the horizontal scroll bar height ---

30		ADR	R3,tspr__horzName	;Point to horz bar sprite ^
		BL	%50tspr_borderWidths	;Get sprite information
		MOV	R2,R4			;The returned height
		BVC	%90tspr_borderWidths	;All OK -- now return
		TST	R7,#1			;Are we in a high res mode?
		MOVNE	R2,#42			;Yes -- use this height
		MOVEQ	R2,#44			;No -- use this height
		B	%90tspr_borderWidths	;Return to caller

		; --- Find out about the given sprite ---

50		BIC	R14,R14,#V_flag		;No error yet
		STMFD	R13!,{R0-R2,R14}	;Preserve these values
		MOV	R14,R3			;Remember this pointer
		LDR	R2,[R3,R7,LSL#2]	;Actually point to the name
		MOV	R1,R8			;The sprite block
		MOV	R0,#256+40		;Read sprite information
		SWI	XOS_SpriteOp		;Read info
		LDRVS	R2,[R14]		;Error -- get default name
		MOVVS	R0,#256+40		;...read sprite information
		SWIVS	XOS_SpriteOp		;...try again
		MOVVC	R3,R3,LSL R9		;Calculate width in OS units
		MOVVC	R4,R4,LSL R10		;Calculate height in OS units
		LDMFD	R13!,{R0-R2,R14}	;Get registers back
		ORRVSS	PC,R14,#V_flag		;Return with error
		BICVCS	PC,R14,#V_flag		;Or maybe without

		; --- Use RISC OS 2 defaults ---

80		MOV	R1,#42			;This is width in all modes
		TST	R7,#1			;Are we in a high res mode?
		MOVNE	R0,#42			;Yes -- use this height
		MOVEQ	R0,#44			;No -- use this height
		MOV	R2,R0			;This height is the same

		; --- Return to the caller ---

90		LDMFD	R13!,{R3-R10,PC}^	;Return

tspr__titleName	DCD	tbarlcap
		DCD	tbarlcap22
		DCD	tbarlcap0
		DCD	tbarlcap23

tspr__vertName	DCD	vwellbcap
		DCD	vwellbcap22
		DCD	vwellbcap0
		DCD	vwellbcap23

tspr__horzName	DCD	hwelllcap
		DCD	hwelllcap22
		DCD	hwelllcap0
		DCD	hwelllcap23

tbarlcap	DCB	"tbarlcap",0
tbarlcap22	DCB	"tbarlcap22",0
tbarlcap0	DCB	"tbarlcap0",0
tbarlcap23	DCB	"tbarlcap23",0

vwellbcap	DCB	"vwellbcap",0
vwellbcap22	DCB	"vwellbcap22",0
vwellbcap0	DCB	"vwellbcap0",0
vwellbcap23	DCB	"vwellbcap23",0

hwelllcap	DCB	"hwelllcap",0
hwelllcap22	DCB	"hwelllcap22",0
hwelllcap0	DCB	"hwelllcap0",0
hwelllcap23	DCB	"hwelllcap23",0

		LTORG

; --- tspr_adjustBox ---
;
; On entry:	R1 == pointer to Wimp_OpenWindow block to modify
;
; On exit:	Block updated in place
;
; Use:		Updates the open block to ensure that the window is opened
;		on the screen.

		EXPORT	tspr_adjustBox
tspr_adjustBox	ROUT

		; --- Find out which gadgets the window has ---

		STMFD	R13!,{R0-R11,R14}	;Save a job load of regs
		SUB	R13,R13,#36		;Space for a window state
		LDR	R0,[R1,#0]		;Load the caller's handle
		STR	R0,[R13,#0]		;Save it in my block
		MOV	R1,R13			;Point to my state block
		SWI	Wimp_GetWindowState	;Find the window information
		LDR	R3,[R13,#32]		;Load the window flags out
		ADD	R13,R13,#36		;Reclaim the stack space

		; --- Now mangle the window block ---

		BL	tspr_borderWidths	;Get the border widths
		LDR	R4,[R13,#4]		;Load his pointer back again
		LDMIB	R4,{R5-R8}		;Load the coordinates out
		TST	R3,#&0f000000		;Is there a top-row gadget?
		ADDNE	R8,R8,R0		;Yes -- add title bar height
		TST	R3,#&10000000		;Is there a vert. scrollbar?
		ADDNE	R7,R7,R1		;Yes -- add scrollbar width
		TST	R3,#&40000000		;Is there a horiz. one?
		SUBNE	R6,R6,R2		;Yes -- sub scrollbar height

		; --- Get the screen dimensions ---

		BL	screen_getInfo		;Find the screen information
		MOV	R11,R0			;Remember this block's pos
		ADD	R0,R0,#screen_width	;Find the screen width
		LDMIA	R0,{R9,R10}		;Load width and height

		; --- Now load the original coords again ---

		LDMIB	R4,{R0-R3}		;Load the coordinates out

		; --- Mangle the x coordinates first ---

		SUB	R14,R7,R5		;Get the window width
		CMP	R14,R9			;Is this wider than screen?
		SUBGT	R0,R0,R5		;Yes -- fit it exactly then
		SUBGT	R2,R7,R2		;And fit right edge to screen
		SUBGT	R2,R9,R2

		SUBS	R14,R7,R9		;Is the right edge on?
		SUBGT	R2,R2,R14		;No -- shift it back on then
		SUBGT	R0,R0,R14		;Ensure the width is constant

		SUBS	R14,R5,#0		;Is the left edge on?
		SUBLT	R0,R0,R14		;No -- shift it back on
		SUBLT	R2,R2,R14		;Ensure constant width again

		; --- Now mangle the y coordinates ---

		SUBS	R14,R8,R6		;Get the window height
		CMP	R14,R10			;Is this higher than screen?
		SUBGT	R1,R1,R6		;Yes -- fit it exactly then
		SUBGT	R3,R8,R3		;And fit top edge to screen
		SUBGT	R3,R10,R3

		SUBS	R14,R8,R10		;Is the top edge on?
		SUBGT	R3,R3,R14		;No -- shift it back on then
		SUBGT	R1,R1,R14		;Ensure height is constant

		LDR	R14,[R11,#screen_dy]	;Get screen dy value
		SUBS	R14,R6,R14		;Is the bottom edge on?
		SUBLT	R1,R1,R14		;No -- shift it back on
		SUBLT	R3,R3,R14		;Ensure constant height again

		; --- Store it back and return ---

		STMIB	R4,{R0-R3}		;Store coordinates back again
		LDMFD	R13!,{R0-R11,PC}^	;Return to caller

		LTORG

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

		END
