;
; winUtils.s
;
; Various window utility functions (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:screen

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

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- winUtils_setTitle ---
;
; On entry:	R0 == pointer to string to set in title
;		R1 == pointer to title bar buffer
;		R2 == window handle to write to
;
; On exit:	--
;
; Use:		Sets a window's title string.  If the string is different,
;		the title is redrawn.  The contortion to do this is
;		unpleasant, and is not to be performed in public.

		EXPORT	winUtils_setTitle
winUtils_setTitle ROUT

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

		; --- Copy the string over nicely ---

		MOV	R3,#0			;Not changed anything yet
00		LDRB	R4,[R0],#1		;Get a byte from new string
		LDRB	R5,[R1],#1		;Get a byte from old string

		CMP	R4,#' '			;Convert control chars...
		MOVLT	R4,#0			;... to null bytes
		CMP	R5,#' '			;And again for the other char
		MOVLT	R5,#0

		CMP	R4,R5			;Are they different?
		MOVNE	R3,#1			;Yes -- set the flag
		STRNEB	R4,[R1,#-1]		;And store in the buffer

		CMP	R4,#0			;Is this the end of it all?
		BNE	%00winUtils_setTitle	;No -- go round for another
		STRB	R4,[R1,#-1]		;Terminate string with NULL

		; --- Return if it was the same ---

		CMP	R3,#0			;Did we do anything?
		LDMEQFD	R13!,{R0-R6,PC}^	;No -- return right now

		; --- Read the window coordinates (yuk) ---

		SUB	R13,R13,#36		;Make way for a window block
		STR	R2,[R13,#0]		;Store the handle in there
		MOV	R1,R13			;Point to the block
		SWI	Wimp_GetWindowState	;Get the window information

		LDR	R14,[R13,#32]		;Get the window flags
		TST	R14,#&00010000		;Check that it's open
		ADDEQ	R13,R13,#36		;No -- reclaim stack space
		LDMEQFD	R13!,{R0-R6,PC}^	;No -- return right now

		LDMIB	R13,{R2-R5}		;Load the coordinates out
		SWI	Wimp_GetWindowOutline	;Now find the real position
		LDR	R6,[R13,#16]		;Load the top coordinate

		MOV	R0,#-1			;Redraw everything (yuk)
		MOV	R1,R2			;The left hand side to do
		MOV	R2,R5			;The bottom part to do
		MOV	R3,R4			;The right hand side to do
		MOV	R4,R6			;And the top part to do
		SWI	Wimp_ForceRedraw	;Force the screen update

		ADD	R13,R13,#36		;Restore the stack again
		LDMFD	R13!,{R0-R6,PC}^	;Return to caller

		LTORG

; --- winUtils_setPosition ---
;
; On entry:	R0 == window opening style
;		R1 == pointer to window state block
;		R2,R3 == extra arguments for displaying the window
;
; On exit:	R2,R3 contain position for opening with Wimp_CreateMenu
;
; Use:		Modifies the window state block pointed to by R0 so that the
;		window appears as required in the given opening style.  The
;		window is always moved to the top.

		EXPORT	winUtils_setPosition
winUtils_setPosition ROUT

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

		; --- Set up values in registers ---

		LDMIB	R1,{R4-R7}		;Load the window position
		SUB	R6,R6,R4		;Get window width in R6
		SUB	R7,R7,R5		;And window height in R7

		; --- Dispatch to display style handler ---

		CMP	R0,#(%10-%00)/4		;Is the opening style known?
		MOV	R8,PC			;Set up return address
		ADDCC	PC,PC,R0,LSL #2		;Call positioning routine
		B	%50winUtils_setPosition	;And write values back

		; --- Branch table for window positioning ---

00		MOVS	PC,R8			;Do nothing -- leave as is
		B	%15winUtils_setPosition	;Centre window on the screen
		B	%20winUtils_setPosition	;Centre window over pointer
		B	%25winUtils_setPosition	;Set y position as given
		B	%30winUtils_setPosition	;Set top left as given
10
		; --- Centre a window on the screen ---

15		BL	screen_getInfo		;Find the screen information
		ADD	R14,R0,#screen_width	;Point to width/height info
		LDMIA	R14,{R2,R3}		;Load the values out
		SUB	R4,R2,R6		;Centre the window...
		MOV	R4,R4,LSR #1		;... horizontally
		SUB	R5,R3,R7		;Also centre it...
		MOV	R5,R5,LSR #1		;... vertically
		MOVS	PC,R8			;And return to set the state

		; --- Centre a window over the pointer ---

20		SWI	OS_Mouse		;Find immediate pointer pos
		SUB	R4,R0,R6,LSR #1		;Centre the x position
		SUB	R5,R1,R7,LSR #1		;And the y position
		LDR	R1,[R13,#4]		;Reload the block pointer
		MOVS	PC,R8			;And return to caller

		; --- Open window at given y position ---

25		SUB	R5,R2,R7		;Sort out the y positioning
		MOVS	PC,R8			;And return to caller

		; --- Open window at given position ---

30		MOV	R4,R2			;Set up the left hand side
		SUB	R5,R3,R7		;And set up the *top*
		MOVS	PC,R8			;Return to main program

		; --- Now sort out all the return values ---

50		ADD	R6,R4,R6		;Work out window right pos
		ADD	R7,R5,R7		;And the window top position
		STMIB	R1,{R4-R7}		;Save all the values in there
		MOV	R14,#-1			;Ensure window opens on top
		STR	R14,[R1,#28]		;Save in `behind' field
		MOV	R2,R4			;Return left side in R2
		MOV	R3,R7			;And top edge in R3
		LDMFD	R13!,{R0,R1,R4-R8,PC}^	;And return to caller

		LTORG

; --- winUtils_findValid ---
;
; On entry:	R0 == pointer to icon block
; 		R1 == character to find in block (not case-sensitive)
;		R2 == old pointer to search from, or 0
;
; On exit:	R1 == character forced to lower case
;		CS if found, and
;		  R2 points to command string
;		else CC and
;		  R2 corrupted
;
; Use:		Tries to find a validation string command in the given
;		icon block.

		EXPORT	winUtils_findValid
winUtils_findValid ROUT

		BIC	R14,R14,#C_flag		;Assume we won't find it
		STMFD	R13!,{R3,R14}		;Preserve for later use

		; --- Ensure the icon is text and indirected ---

		LDR	R3,[R0,#16]		;Get flags word
		TST	R3,#1<<23		;Is it deleted?
		MOVEQ	R14,#&100		;Can't put 101 in one instr
		ORREQ	R14,R14,#&01		;Check indirect and text
		ANDEQ	R3,R3,R14		;Mask the bits off
		CMPEQ	R3,R14			;Were they both set?
		LDMNEFD	R13!,{R3,PC}^		;No -- return huffily

		; --- Find the validation string ---

		LDR	R3,[R0,#24]		;Get pointer to valid string
		CMP	R3,#-1			;Is it empty?
		LDMEQFD	R13!,{R3,PC}^		;No -- return huffily

		; --- Start from the right index ---

		ORR	R1,R1,#&20		;Make valid char lower case
		CMP	R2,#0			;Is it the start?
		ADDNE	R2,R2,#1		;No -- miss out one char
		BNE	%02winUtils_findValid	;And skip this command
		MOV	R2,R3			;Start at the beginning

		; --- Check the first char of a validation string ---

00		LDRB	R14,[R2],#1		;Get a byte from string
		ORR	R3,R14,#&20		;Make lower case
		CMP	R3,R1			;Is it a match?
		SUBEQ	R2,R2,#1		;Point back to character
		LDMEQFD	R13!,{R3,R14}		;And return
		ORREQS	PC,R14,#C_flag		;Set C on exit for this
		MOV	R3,#0			;Not an excaped character

		; --- Skip ahead to the next validation string ---

01		CMP	R14,#' '		;Is it a control char?
		LDMLTFD	R13!,{R3,PC}^		;Yes -- return
		CMP	R3,#1			;Are we escaping?
		MOVEQ	R3,#0			;Yes -- done that now
		BEQ	%02winUtils_findValid	;So skip this bit
		CMP	R14,#';'		;Is it a semicolon?
		BEQ	%00winUtils_findValid	;Yes -- try a new command
		CMP	R14,#'\'		;Is it a backslash?
		MOVEQ	R3,#1			;Yes -- escape next char
02		LDRB	R14,[R2],#1		;Get another character
		B	%01winUtils_findValid	;And try again

		LTORG

; --- winUtils_shaded ---
;
; On entry:	R0 == window handle
;		R1 == icon handle
;
; On exit:	CS if icon is shaded, CC otherwise
;
; Use:		Informs caller whether an icon is shaded in the Sapphire
;		sense (ESG 31 or shaded bit set).

		EXPORT	winUtils_shaded
winUtils_shaded	ROUT

		STMFD	R13!,{R0,R1,R14}	;Save some registers
		SUB	R13,R13,#40		;Make an icon block
		STMIA	R13,{R0,R1}		;Save icons in the block
		MOV	R1,R13			;Point to the block
		SWI	Wimp_GetIconState	;Read the icon information
		LDR	R14,[R13,#24]		;Load the icon flags
		EOR	R14,R14,#&005F0000	;Toggle shaded and ESG bits
		TST	R14,#&00400000		;Was the shaded bit set?
		TSTNE	R14,#&001F0000		;No -- test the ESG bits
		ADD	R13,R13,#40		;Restore the stack pointer
		LDMFD	R13!,{R0,R1,R14}	;Unstack loads of registers
		ORREQS	PC,R14,#C_flag		;Set C if icon is shaded
		BICNES	PC,R14,#C_flag		;Clear C if not shaded

		LTORG

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

		END
