;
; plot.s
;
; Plots border types
;
;  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.border
		GET	sh.rules
		GET	sh.utils
		GET	sh.vString

		GET	sh.wSpace

;----- Macros ---------------------------------------------------------------

		MACRO
$label		DCO	$addr
$label		DCD	$addr-{PC}
		MEND

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

		AREA	|Module$$Code|,CODE,READONLY

; --- plot_border ---
;
; On entry:	R0 == pointer to border type
;		R1 == pointer to icon block
;		R2,R3 == window origin position
;
; On exit:	May return an error
;
; Use:		Plots the given border type.

		EXPORT	plot_border
plot_border	ROUT

		STMFD	R13!,{R14}		;Save a register
		AND	R14,R0,#&0000FF00	;Extract the general code
		CMP	R14,#(%10-%00)<<6	;Check it's in range
		ADDCC	PC,PC,R14,LSR #6	;Yes -- dispatch it then
		LDMFD	R13!,{PC}		;Otherwise ignore it

00		B	plot__simple		;Plot something simple
		B	plot__group		;Plot a group box
		B	plot__tns		;Plot a text+sprite icon
10
		LTORG

; --- plot__simple ---
;
; On entry:	R0 == pointer to border type
;		R1 == pointer to icon block
;		R2,R3 == window origin position
;
; On exit:	May return an error
;
; Use:		Plots a simple border type.

plot__simple	ROUT

		STMFD	R13!,{R4}		;Save some registers

		; --- Sort out which colour to use ---

		ADR	R4,sculpt_colours	;Point to colour tables
		LDR	R14,[R1,#16]		;Load the icon flags
		EOR	R14,R14,#&005F0000	;Toggle shade and ESG bits
		TST	R14,#&00400000		;Test the shaded bit
		TSTNE	R14,#&001F0000		;And then the ESG bits
		ADDEQ	R4,R4,#8		;If shaded, select table
		TST	R0,#vsFlag_fade		;Is the icon faded?
		ADDNE	R4,R4,#4		;Yes -- then fade it
		TST	R0,#vsFlag_invert	;Is the icon inverted?
		ADDNE	R4,R4,#1		;Yes -- invert it

		; --- Now plot the thing ---

		ADR	R14,plot__table		;Point to the table
		AND	R0,R0,#&FF		;Extract the subtype
		LDR	R0,[R14,R0,LSL #2]!	;Load the offset out
		ADD	R0,R14,R0		;Add on to find the address
		BL	border_plot		;Go and plot it then
		LDMFD	R13!,{R4,PC}		;Return when finished

plot__table	DCO	plot__action
		DCO	plot__default
		DCO	plot__ridge
		DCO	plot__write
		DCO	plot__offset

		LTORG

; --- plot_group ---
;
; On entry:	R0 == pointer to border type
;		R1 == pointer to icon block
;		R2,R3 == window origin position
;		R6 == pointer to group title
;
; On exit:	May return an error
;
; Use:		Plots a group box.

		EXPORT	plot_group
plot_group	ROUT

		STMFD	R13!,{R4-R6,R14}	;Save some registers
		B	%f00			;And skip on...

plot__group	STMFD	R13!,{R4-R6}		;Save some registers
		ADR	R6,sculpt_misc		;Point to string in buffer

		; --- Sort out the text width ---

00		MOV	R0,R6			;Point to the text string
		BL	utils_strWidth		;Work out the width, please
		ADD	R5,R0,#16		;Add some extra each side

		; --- Work out the group colours ---

		ADR	R4,sculpt_groupCol	;Point to group colour table
		LDR	R14,[R1,#16]		;Load the icon flags
		EOR	R14,R14,#&005F0000	;Toggle shade and ESG bits
		TST	R14,#&00400000		;Test the shaded bit
		TSTNE	R14,#&001F0000		;And then the ESG bits
		ADDEQ	R4,R4,#8		;If shaded, select table
		LDR	R14,sculpt_flags	;Load the flags word
		TST	R14,#scFlag_acorn	;Acorn style group box?
		ADDNE	R4,R4,#1		;Yes -- invert colours then
		ADREQ	R0,plot__stdGroup	;No -- point to standard rtn
		ADRNE	R0,plot__acnGroup	;Yes -- use Acorn one
		BL	border_plot		;Plot the group box
		LDMFD	R13!,{R4-R6,PC}		;Return when done

		LTORG

; --- plot__tns ---
;
; On entry:	R0 == pointer to border type
;		R1 == pointer to icon block
;		R2,R3 == window origin position
;
; On exit:	--
;
; Use:		Plots a text+sprite icon.

plot__tns	ROUT

		STMFD	R13!,{R0-R6}		;Save lots of registers
		SWI	XWimp_PlotIcon		;Plot the sprite
		BL	plot_tnsBBox		;Find the icon bounding box
		BCC	%90plot__tns		;If that failed, return now

		; --- Now plot the icon ---

70plot__tns	SUB	R13,R13,#32		;Make space for icon block
		STMIA	R13,{R0-R3}		;Save them away, please

		BIC	R4,R4,#&00000006	;Clear border and sprite bits
		BIC	R4,R4,#&00200000	;Clear selected bit

		MOV	R0,#8			;Get the current font handle
		SWI	XWimp_ReadSysInfo	;Do that, please
		MOVVS	R0,#0			;If not known, assume none
		CMP	R0,#0			;Do we have a font?
		TSTEQ	R4,#&60			;Is the icon anti-aliased?
		BEQ	%80plot__tns		;No -- skip ahead then

		; --- See if the icon's shaded ---
		;
		; If it is, fix it so that it looks right.  In keeping with
		; the WindowManager's simpleminded view of colour selection,
		; this just involves clearing some bits.

		MVN	R14,R4			;Invert all the bits, please
		TST	R14,#&00400000		;Test the shaded bit
		TSTNE	R14,#&001F0000		;And then the ESG bits
		BICEQ	R4,R4,#&0B000000	;If shaded, change colour

		; --- Now fill in the rest of the data ---

80plot__tns	BIC	R4,R4,#&00400000	;Clear shaded bit anyway
		ADR	R5,sculpt_misc		;Point to the text buffer
		MOV	R6,#-1			;No validation string
		MOV	R14,#1			;A random string length

		ADD	R0,R13,#16		;Point into the buffer
		STMIA	R0,{R4-R6,R14}		;Store them away
		MOV	R1,R13			;Point to the icon block
		SWI	XWimp_PlotIcon		;Plot the icon, please
		ADD	R13,R13,#32		;Restore the stack pointer

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

		LTORG

; --- plot_tnsBBox ---
;
; On entry:	R1 == pointer to an icon block
;
; On exit:	CS if sprite found, and
;		  R0-R3 == bounding box of icon
;		  R4 == icon flags word (modified)
;		else CC and registers preserved
;
; Use:		Works out where the text of the icon ought to be.  (Actually
;		the box returned is too wide, although this will probably
;		be good enough for most purposes.)

		EXPORT	plot_tnsBBox
plot_tnsBBox	ROUT

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

		LDR	R4,[R1,#16]		;Load the icon flags
		AND	R14,R4,#&218		;Extract the position bits
		CMP	R14,#&010		;Only vertical centring?
		BEQ	%50plot_tnsBBox		;Yes -- this is trickier

		LDMIA	R1,{R0-R3}		;Load the icon data

		; --- Work out where to put the icon ---

		MOV	R14,R14,LSR #3		;Shift the bits down
		TST	R4,#&200		;Is it right aligned?
		EORNE	R14,R14,#&44		;Yes -- move the bit down
		ADR	R6,plot__alignTbl	;Point to a table
		LDRB	R6,[R6,R14]		;Load the entry we want
		EOR	R4,R4,R6,LSL #2		;And jiggle the bits

		ADR	R6,plot__psnTbl		;Point to position table
		LDRB	R6,[R6,R14]		;Load the magic number
		CMP	R6,#1			;Which is it?
		ADDEQ	R1,R1,R3		;Centre -- add them up
		MOVEQ	R1,R1,ASR #1		;Divide by two
		SUBEQ	R1,R1,#18		;And move down a bit
		ADDLE	R3,R1,#36		;Bottom -- sort it
		SUBGT	R1,R3,#36		;Top -- sort it

		B	%90plot_tnsBBox		;Return because it worked

		; --- Handle the sprite data ---

50plot_tnsBBox	MOV	R0,#'s'			;Search for an `s' command
		MOV	R2,#0			;Start from the beginning
		BL	vString_find		;Find the validation string
		BCC	%99plot_tnsBBox		;If not found, ignore it

		ADR	R1,sculpt_small		;Point to a buffer
		ADD	R2,R2,#1		;Skip past the `s'
00		LDRB	R14,[R2],#1		;Load a byte
		CMP	R14,#','		;A different sprite?
		CMPNE	R14,#';'		;A different command?
		CMPNE	R14,#&1F		;Or the end of the string?
		MOVLS	R14,#0			;Any of them -- take a zero
		STRB	R14,[R1],#1		;Store that away
		BHI	%b00			;And keep looping until done

		; --- Read the sprite information ---

		ADR	R2,sculpt_small		;Point to small buffer
		LDR	R1,sculpt_sprArea	;Load the area pointer
		CMP	R1,#1			;Is this the Wimp area?
		BEQ	%f00			;Yes -- skip onwards

		MOV	R0,#40			;Read sprite information
		ORR	R0,R0,#&100		;Set the user area bit
		SWI	XOS_SpriteOp		;Read the information
		BVC	%f01			;If OK, skip onwards

00		MOV	R0,#40			;Read sprite information
		SWI	XWimp_SpriteOp		;Read the information
		BVS	%99plot_tnsBBox		;If failed quit now

		; --- Sort out the sprite width ---

01		MOV	R0,R6			;Get the sprite mode
		MOV	R1,#4			;Read the x EIG factor
		SWI	XOS_ReadModeVariable	;Try to do that
		BVS	%99plot_tnsBBox		;If failed quit now
		BCS	%99plot_tnsBBox		;If failed quit now
		MOV	R5,R3,LSL R2		;Work out the width now

		; --- Play with the icon data now ---

		LDR	R1,[R13,#4]		;Load the icon address
		LDMIA	R1,{R0-R4}		;Load all that information
		ADD	R0,R0,R5		;Move the left hand side over

		ADD	R1,R1,R3		;Centre -- add them up
		MOV	R1,R1,ASR #1		;Divide by two
		SUB	R1,R1,#18		;And move down a bit
		ADD	R3,R1,#36		;Sort out the upper limit

		; --- Return to caller ---

90plot_tnsBBox	ADD	R13,R13,#20		;Don't restore R0-R4
		LDMFD	R13!,{R5,R6,R14}	;Restore other registers
		ORRS	PC,R14,#C_flag		;And return C set on exit

99plot_tnsBBox	LDMFD	R13!,{R0-R6,R14}	;Restore other registers
		BICS	PC,R14,#C_flag		;And return a failed result

		; --- Alignment table ---
		;
		; Each entry contains an EOR mask which should be applied to
		; the icon flags for the text icon.  In order to make them
		; fit into single bytes, they're all shifted right two
		; places.  This lets me know whether the text needs to be
		; centred or whatever in those cases where it's not actually
		; obvious from the original flags.

plot__alignTbl	DCB	0,0,0,&80
		DCB	0,0,&80,&02

		; --- Position table ---
		;
		; Each entry contains a value used to position the icon
		; vertically.  Zero means that the text is at the bottom of
		; the icon, one means that it's in the middle, and two means
		; that it's at the top.

plot__psnTbl	DCB	0,0,0,1
		DCB	0,2,1,1

		LTORG

;----- Group box routines ---------------------------------------------------

; --- plot__stdGroup ---

plot__stdGroup	ROUT

		BCALL	plot__gBorder
		BCALL	plot__findPlinth
		BCALL	plot__plinth

		BDARK
		BLDIY1
		BSTY1
		BLDIX0
		BSTX0
		BADD	16-4
		BSTX1
		BPLOT	rule_top

		BLIGHT
		BLDIY1
		BADD	8
		BSTY0
		BLDIX0
		BADD	16+4
		BSKIPT
		BSTX0
		BSTX1
		BPLOT	rule_bottom

		BCALL	plot__findPlinth
		BGROUP	&17000139
		BRET

		LTORG

; --- plot__acnGroup ---

plot__acnGroup	ROUT

		BCALL	plot__gBorder

		BLDIY1
		BADD	4
		BSTY0
		BSTY1
		BLDIX0
		BADD	16-4
		BSTX0
		BSTX1
		BDARK
		BPLOT	rule_right
		BLIGHT
		BPLOT	rule_top

		BLDIX0
		BADD	16+4
		BSKIPT
		BSTX0
		BSTX1
		BLIGHT
		BPLOT	rule_left
		BDARK
		BPLOT	rule_bottom

		BCALL	plot__findPlinth
		BGROUP	&17000119
		BRET

		LTORG

; --- plot__gBorder ---

plot__gBorder	ROUT

		BDARK
		BPLOT	rule_left
		BLIGHT
		BPLOT	rule_right
		BPLOT	rule_bottom

		BCALL	plot__stepOut
		BPLOT	rule_left
		BDARK
		BPLOT	rule_right
		BPLOT	rule_bottom

		BLDIX0
		BSTX0
		BADD	16-4
		BSTX1
		BLDIY1
		BSTY1
		BPLOT	rule_pTop
		BADD	4
		BSTY1
		BLDX0
		BSUB	4
		BSTX0
		BLIGHT
		BPLOT	rule_pTop

		BADD	16+4+4
		BSKIPT
		BSTX0
		BLDIX1
		BADD	4
		BSTX1
		BPLOT	rule_top
		BSUB	4
		BSTX1
		BLDIY1
		BSTY1
		BDARK
		BPLOT	rule_top
		BRET

		LTORG

; --- plot__findPlinth ---

plot__findPlinth ROUT

		BLDIX0
		BADD	16
		BSTX0
		BSKIPT
		BSTX1
		BLDIY1
		BSUB	20
		BSTY0
		BADD	48
		BSTY1
		BRET

		LTORG

;----- Border definition routines -------------------------------------------

; --- plot__plinth ---

plot__plinth	ROUT

		BLIGHT
		BPLOT	rule_left
		BDARK
		BPLOT	rule_right
		BPLOT	rule_bottom
		BLIGHT
		BPLOT	rule_top
		BRET

		LTORG

; --- plot__invPlinth ---

plot__invPlinth	ROUT

		BDARK
		BPLOT	rule_left
		BLIGHT
		BPLOT	rule_right
		BPLOT	rule_bottom
		BDARK
		BPLOT	rule_top
		BRET

		LTORG

; --- plot__ring ---

plot__ring	ROUT

		BPLOT	rule_left
		BPLOT	rule_right
		BPLOT	rule_pTop
		BPLOT	rule_pBottom
		BRET

		LTORG

; --- plot__stepOut ---

plot__stepOut	ROUT

		BLDX0
		BSUB	4
		BSTX0
		BLDY0
		BSUB	4
		BSTY0
		BLDX1
		BADD	4
		BSTX1
		BLDY1
		BADD	4
		BSTY1
		BRET

		LTORG

; --- plot__action ---

plot__action	ROUT

		BJMP	plot__plinth

		LTORG

; --- plot__default ---

plot__default	ROUT

		BCALL	plot__plinth
		BCALL	plot__stepOut
		BINDCOL	sculpt_hilight
		BCALL	plot__ring
		BCALL	plot__stepOut
		BRAW
		BCALL	plot__invPlinth
		BRET

		LTORG

; --- plot__ridge ---

plot__ridge	ROUT

		BCALL	plot__invPlinth
		BCALL	plot__stepOut
		BCALL	plot__plinth
		BRET

		LTORG

; --- plot__write ---

plot__write	ROUT

		BCALL	plot__stepOut
		BICON
		BPLOT	rule_border
;		BJMP	plot__offset		;Redundant

; --- plot__offset ---

plot__offset	ROUT

		BLITCOL	1
		BCALL	plot__ring
		BCALL	plot__stepOut
		BCALL	plot__invPlinth
		BRET

		LTORG

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

		END
