;
; slab.s
;
; Icon slabbing for Sculptrix
;
;  1995-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's Sculptrix.
;
; Sculptrix 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.
;
; Sculptrix 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 Sculptrix.  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	sh.colours
		GET	sh.plot
		GET	sh.vString
		GET	sh.wSpace

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

		AREA	|Module$$Code|,CODE,READONLY

; --- slab_doSlab ---
;
; On entry:	R0 == window handle
;		R1 == icon handle
;		R2 == new background colour for icon
;
; On exit:	R2 == old background colour, or -1
;
; Use:		Low-level slabbing operation.

		EXPORT	slab_doSlab
slab_doSlab	ROUT

		STMFD	R13!,{R0-R5,R14}	;Save some registers
		MOV	R14,#-1			;Nothing achieved yet
		STR	R14,[R13,#8]		;Store as old colour

		; --- Read the icon information ---

		SUB	R13,R13,#84		;Enough for a redraw block
		STMIA	R13,{R0,R1}		;Store the window and icon
		MOV	R1,R13			;Point to this block
		SWI	XWimp_GetIconState	;Read the icon information
		BVS	%99slab_doSlab		;If that failed, return

		ADD	R1,R13,#8		;Point to the icon data
		BL	vString_read		;Read the border information
		BCC	%90slab_doSlab		;No border -- return now
		TST	R0,#vsFlag_slab		;Is the border slabbable?
		BEQ	%90slab_doSlab		;Not slabbable -- return
		BIC	R5,R0,#&FF		;Clear to raw plinth

		; --- Swap the colours over ---

		MOV	R1,R13			;Point to the full block
		BL	colours_set		;Set the background colour
		STR	R2,[R13,#84+8]		;Store this to return in R2

		; --- Now toggle the border ---

		LDRB	R14,[R4,#0]		;Load the invert character
		EOR	R14,R14,#&20		;Change its case
		STRB	R14,[R4,#0]		;Store the character back

		ADD	R14,R13,#8		;Point to the bounding box
		LDMIA	R14,{R2-R4,R14}		;Load these values out
		SUB	R2,R2,#4		;Expand to allow for border
		SUB	R3,R3,#4
		ADD	R4,R4,#4
		ADD	R14,R14,#4
		LDR	R0,[R13,#0]		;Load the window handle
		ADD	R1,R13,#40		;Point to the update block
		STMIA	R1,{R0,R2-R4,R14}	;Store them back again

		SWI	XWimp_UpdateWindow	;Start the update operation
		BVS	%99slab_doSlab		;If that failed, return
		CMP	R0,#0			;Is there anything to do?
		BEQ	%90slab_doSlab		;No -- do nothing then

		; --- Read the window origin position ---

		LDR	R2,[R1,#4]		;Load the x0 coordinate
		ADD	R14,R1,#16		;Find the others
		LDMIA	R14,{R3,R4,R14}		;Load them from the block
		SUB	R2,R2,R4		;Find the x origin
		SUB	R3,R3,R14		;And find the y origin

		; --- Do the update loop ---

00		EOR	R0,R5,#vsFlag_invert	;Get the border type word
		ADD	R1,R13,#8		;Point to the icon data
		BL	plot_border		;Go and plot the border
		ADDVC	R1,R13,#40		;Point to the update block
		SWIVC	XWimp_GetRectangle	;Get another rectangle
		BVS	%99slab_doSlab		;If that failed, return
		CMP	R0,#0			;Is that all there is?
		BNE	%b00			;No -- loop back then

		; --- Tidy up and return ---

90slab_doSlab	ADD	R13,R13,#84		;Restore the stack pointer
		LDMFD	R13!,{R0-R5,R14}	;Restore registers
		BICS	PC,R14,#V_flag		;And return without error

99slab_doSlab	ADD	R13,R13,#84+4		;Restore the stack pointer
		LDMFD	R13!,{R1-R5,R14}	;Restore registers except R0
		ORRS	PC,R14,#V_flag		;And return the error

		LTORG

; --- slab_slab ---
;
; On entry:	R0 == window handle
;		R1 == icon handle
;		R2 == pointer to slab descriptor block
;
; On exit:	--
;
; Use:		Slabs an icon in, and records information for unslabbing.

		EXPORT	slab_slab
slab_slab	ROUT

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

		; --- Fill in the descriptor block ---

		MOV	R3,R2			;Remember this pointer
		STMIA	R3,{R0,R1}		;Store them away
		SWI	XOS_ReadMonotonicTime	;Read the time
		STR	R0,[R3,#12]		;Store it in the block

		; --- Do the slabness ---

		LDR	R0,[R3,#0]		;Load the window handle
		LDR	R2,sculpt_slab		;Get the slab colour
		BL	slab_doSlab		;Do the slabbing op
		BVS	%99slab_slab

		SUB	R13,R13,#20		;Allow some space for block
		MOV	R1,R13			;Point to the block
		SWI	XWimp_GetPointerInfo	;Fetch the mouse status
		LDR	R14,[R13,#8]		;Fetch the button state
		ADD	R13,R13,#20		;Restore the stack pointer
		CMP	R14,#0			;Are any buttons pressed?
		ORREQ	R2,R2,#&100		;No -- set a flag then
		STR	R2,[R3,#8]		;Store in the descriptor

		; --- Clear the `immediate unslab' flag ---

		LDR	R14,sculpt_flags	;Load the flags word
		BIC	R14,R14,#scFlag_unslab	;Clear the flag
		STR	R14,sculpt_flags	;Store the flags back
		LDMFD	R13!,{R0-R3,PC}^	;Return when done

99		ADD	R13,R13,#4		;Don't restore R0 on exit
		LDMFD	R13!,{R1-R3,R14}	;Restore other registers
		ORRS	PC,R14,#V_flag		;And return with V set

		LTORG

; --- slab_unslab ---
;
; On entry:	R2 == pointer to descriptor block
;
; On exit:	--
;
; Use:		Unslabs an icon which was slabbed.

		EXPORT	slab_unslab
slab_unslab	ROUT

		STMFD	R13!,{R0-R4,R14}	;Save some registers
		MOV	R4,R2			;Move this somewhere nice

		; --- Quick check to see if anything needs doing ---

		LDR	R14,[R4,#8]		;Load the colour word
		CMP	R14,#-1			;Is this unset?
		BEQ	%90slab_unslab		;Yes -- return then

		; --- Do we do this quickly? ---

		LDR	R14,sculpt_flags	;Load the flags word
		TST	R14,#scFlag_unslab	;Have we recently unslabbed?
		BNE	%50slab_unslab		;Yes -- skip the delay
		ORR	R14,R14,#scFlag_unslab	;Set the flag now
		STR	R14,sculpt_flags	;Save the flags back

		; --- Work out how long to wait ---

		SUB	R13,R13,#36		;Make space for a block
		LDR	R14,[R4,#0]		;Load the window handle
		STR	R14,[R13,#0]		;Store in the block
		MOV	R1,R13			;Point to my block
		SWI	XWimp_GetWindowState	;Read the window state
		MOVVS	R14,#0			;If failed, assume deleted
		LDRVC	R14,[R13,#32]		;Else load the window flags
		ADD	R13,R13,#36		;Restore the stack pointer
		TST	R14,#&00010000		;Is the window open?
		BEQ	%10slab_unslab		;Yes -- wait for timer then

		LDR	R14,[R4,#8]		;Load the flags/colour word
		TST	R14,#&100		;Is the `no mouse' bit set?
		BNE	%10slab_unslab		;Yes -- wait for timer then

		; --- Check for the mouse then ---

00		SWI	XOS_Mouse		;Read the mouse position
		CMP	R2,#0			;Are the buttons released?
		BNE	%b00			;No -- skip round
		B	%50slab_unslab		;Now skip onwards for unslab

		; --- Check for the timer ---

10slab_unslab	LDR	R1,[R4,#12]		;Load the targt time
		ADD	R1,R1,#10		;Allow a tenth of a second
00		SWI	XOS_ReadMonotonicTime	;Read the current time
		CMP	R0,R1			;Have we waited long enough?
		BMI	%b00			;No -- loop back then

		; --- Now we can unslab the icon ---

50slab_unslab	LDMIA	R4,{R0-R2}		;Load the information out
		AND	R2,R2,#&FF		;Only use the colour bits
		BL	slab_doSlab		;Do the unslabbing

90		LDMFD	R13!,{R0-R4,PC}^	;Return to caller when done

99		ADD	R13,R13,#4		;Don't restore R0 on exit
		LDMFD	R13!,{R1-R4,R14}	;Restore registers
		ORRS	PC,R14,#V_flag		;And return to caller

		LTORG

; --- slab_colour ---
;
; On entry:	--
;
; On exit:	R2 == slab colour
;
; Use:		Returns the current slabbing colour.

		EXPORT	slab_colour
slab_colour	ROUT

		LDR	R2,sculpt_slab		;Load the slabbing colour
		MOVS	PC,R14			;And return to caller

		LTORG

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

		END
