;
; sculptrix.s
;
; Draws pretty 3D boxes
;
;  1994 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.

;----- Change history -------------------------------------------------------
;
; Version	By	Change
; ~~~~~~~	~~	~~~~~~
; 1.00		MDW	Initial version written
;
; 1.01		MDW	Added support for group boxes
;			Fixed validation string parser -- will now search
;			all `X' commands instead of just the first one
;
; 1.02		MDW	Fixed problem with multiple unslab ops in one poll
;
; 1.03		MDW	Stopped excessive redrawing in group box rendering
;
; 1.04		MDW	Done strange things to make text+sprite icons nice
;			Any contortions required are due solely to TMA.
;
; 1.05		MDW	Filled in group box types 0 and 2 (ridge'n'plinth)
;
; 1.06		MDW	Allowed user-changing of the 3D colours and things
;			Also included different colours for shaded borders
;
; 1.07		MDW	Fixed bug in Sculptrix_SlabIcon, which corrupted R0
;			on exit.  Nothing has been affected by this, but we
;			may as well get it right.
;
; 1.08		MDW	Made colour change before toggling slab on slab ops
;			Integrated colour change with toggle slab, now
;			box_toggle does all Sculptrix_DoSlab needs to, so
;			renamed box_toggle as swi_doslab.  Module therefore
;			slightly smaller!
;
; 1.09		TMA	Added type 7 border -- a writable type with its own
;			black border. Less flickery than a Wimp type,
;			however, the border is always 4 OS units.
;
; 		MDW	Fixed writable border being black when it gets shaded
;
; 1.10		MDW	Made writable border read colours from icon, and fill
;			the whole icon with the background colour, rather
;			than just the outside.  Basically, rewrote the
;			border 7 rendering code.
;
; 1.11		MDW	Fixed Sculptrix_SetSpriteArea bug -- I `found' my
;			workspace twice.  Ooops.
;		MDW	Changed to use new Acorn-allocated SWI chunk number
;
; 1.12		MDW	Improved shaded-icon checking to avoid branch.
;			Added 10cs delay to unslab with window open in line
;			with STASIS requirements.
;
; 1.13		MDW	Fixed bug in mitre start position -- inserted RSB
;			to make it go in the right direction.
;
; 1.14		MDW	Removed filling in groupbox type 0 to allow dbx
;			controls to be within group boxes.
;
; 1.15		MDW	Modified rendering of `xs' icons to match new STEEL
;			and Sapphire icon shading habits.  Added a 256-byte
;			static buffer for group titles, to avoid dynamic
;			allocation in mid-redraw,  Changed lots of signed
;			compares to unsigned, which removes some redundancy.
;			Fixed text+sprite handling to look in Wimp area
;			if not in user area.  Added messages support.  Added
;			border type 8 for partitions that fade properly
;			(suggested by Alex Thoukydides).

;----- Standard header ------------------------------------------------------

		GET	libs:header
		GET	libs:swis

		GET	sh.messages
		IMPORT	s_help

;----- PLOT code numbers ----------------------------------------------------

plot_MOVE	EQU	0
plot_FORE	EQU	1
plot_INVERSE	EQU	2
plot_BACK	EQU	3

plot_RELATIVE	EQU	0
plot_ABSOLUTE	EQU	4

plot_RECTFILL	EQU	96
plot_LINE	EQU	0

;----- VDU variable numbers -------------------------------------------------

vdu_XEIG	EQU	4
vdu_YEIG	EQU	5

;----- Module header --------------------------------------------------------

		AREA	|!!!Module$$Header|,CODE,READONLY

		DCD	0			;Module start code
		DCD	s_init			;Initialisation
		DCD	s_die			;Finalisation
		DCD	s_service		;Service call
		DCD	s_title			;Module title string
		DCD	s_help			;Module help string
		DCD	s_command		;Command table
		DCD	&4A2C0			;SWI chunk (temporary)
		DCD	s_swic			;SWI handling
		DCD	s_swin			;SWI names table
		DCD	0			;SWI names code

;----- Module strings -------------------------------------------------------

s_title		DCB	"Sculptrix",0

;----- SWI name table -------------------------------------------------------

s_swin		DCB	"Sculptrix",0

		DCB	"RedrawWindow",0
		DCB	"DoSlab",0
		DCB	"SlabIcon",0
		DCB	"UnslabIcon",0
		DCB	"BoundingBox",0
		DCB	"PlotIcon",0
		DCB	"PlotGroupBox",0
		DCB	"SetSpriteArea",0
		DCB	"UpdateIcon",0
		DCB	"SlabColour",0

		DCB	0

;----- Command table --------------------------------------------------------

s_command	DCB	"Sculptrix_Colours",0
		DCD	cmd_colours
		DCB	0,0,1,0
		DCD	synt_colours
		DCD	help_colours

		DCB	"Sculptrix_GroupType",0
		DCD	cmd_group
		DCB	1,0,1,0
		DCD	synt_group
		DCD	help_group

		DCD	0

;----- Initialisation and finalisation --------------------------------------

s_init		ROUT

		STMFD	R13!,{R14}		;Stack link register nicely

		; --- Get some workspace ---

		MOV	R0,#6			;Allocate workspace
		MOV	R3,#s_wsize		;Make it *this* big
		SWI	XOS_Module		;Get me memory
		LDMVSFD	R13!,{PC}		;Return if it barfed
		STR	R2,[R12]		;Stash the workspace pointer
		MOV	R12,R2			;Move the pointer across

		; --- Set initial values ---

		BL	vdu_set			;Set up the graphics vars
		MOV	R0,#0			;Initial flags setting
		STR	R0,s_flags		;Store in the flags word
		MOV	R0,#1			;Start using WIMP area
		STR	R0,s_sarea		;Store in sprite area word
		MOV	R0,#&0400		;Default colours
		ORR	R0,R0,R0,LSL #16	;Propagate to top half
		MOV	R1,#&0200		;Default colours
		ORR	R1,R1,R1,LSL #16	;Propagate to top half
		MOV	R2,#&0C00
		ORR	R2,R2,#&000E
		ADR	R3,s_colours
		STMIA	R3,{R0-R2}

		; --- I think that's it ---

		LDMFD	R13!,{PC}^		;Return to caller happy

		LTORG

s_die		ROUT

		STMFD	R13!,{R11,R14}
		MOV	R11,R12			;Keep the private word ptr
		LDR	R12,[R12]		;Find my workspace

		; --- Free my workspace ---

		MOV	R0,#7			;Free RMA space
		MOV	R2,R12			;Point to workspace
		SWI	XOS_Module		;Try to free the memory
		MOV	R0,#0			;Gonna zero the private word
		STR	R0,[R11]		;Then zero it
		LDMFD	R13!,{R11,PC}^		;A happy bunny

		LTORG

;----- Service call handling ------------------------------------------------

s_service	ROUT

		CMP	R1,#&46			;Is it a mode change?
		MOVNES	PC,R14			;No -- return

		LDR	R12,[R12]		;Get my workspaxe
		B	vdu_set			;Set up the VDU variables


;----- Command handlers -----------------------------------------------------

; --- Sculptrix_Colours ---

cmd_colours	ROUT

		STMFD	R13!,{R1-R5,R14}	;Save some registers
		LDR	R12,[R12]		;Locate my workspace pointer

		; --- If no argument, use the default ---

		CMP	R1,#0			;Is there an argument?
		ADREQ	R0,cmd__defCol		;No -- point to default

		; --- Read normal 3D colours ---

		LDRB	R2,[R0],#1		;Get the first digit
		BL	%50cmd_colours		;Convert to binary
		MOV	R3,R2,LSL #8		;Look after it
		LDRB	R2,[R0],#1		;Get the next digit
		BL	%50cmd_colours		;Convert to binary
		ORR	R3,R3,R2		;Mix into the word nicely
		ORR	R3,R3,R3,LSL #16	;Propagate to upper half

		; --- Read shaded 3D colours ---

		LDRB	R2,[R0],#1		;Get the first digit
		BL	%50cmd_colours		;Convert to binary
		MOV	R4,R2,LSL #8		;Look after it
		LDRB	R2,[R0],#1		;Get the next digit
		BL	%50cmd_colours		;Convert to binary
		ORR	R4,R4,R2		;Mix into the word nicely
		ORR	R4,R4,R4,LSL #16	;Propagate to upper half

		; --- Read the other colours ---

		LDRB	R2,[R0],#1		;Get a digit
		BL	%50cmd_colours		;Convert to binary
		MOV	R5,R2,LSL #8		;Look after it
		LDRB	R2,[R0],#1		;Get a digit
		BL	%50cmd_colours		;Convert to binary
		ORR	R5,R5,R2		;Look after it

		; --- Now store these away nicely ---

		ADR	R1,s_colours		;Point to base address
		STMIA	R1,{R3-R5}		;Store them in workspace
		LDMFD	R13!,{R1-R5,PC}^	;Return to caller

		; --- Convert R2 to binary ---

50cmd_colours	SUBS	R2,R2,#'0'		;Convert a digit
		CMP	R2,#10			;Is this bigger than 9?
		SUBCS	R2,R2,#7		;Yes -- convert from upper
		CMP	R2,#16			;Still out of range?
		SUBCS	R2,R2,#&20		;Yes -- must have been lower
		CMP	R2,#16			;Still out of range?
		BCS	%51cmd_colours		;Yes -- that's an error
		MOVS	PC,R14			;Return to caller

51cmd_colours	ADRL	R0,msg_errBadHex	;Point to error message
		LDMFD	R13!,{R1-R5,R14}	;Unstack the registers
		ORRS	PC,R14,#V_flag		;Return to caller

cmd__defCol	DCB	"4020CE",0

		LTORG

; --- Sculptrix_GroupType ---

cmd_group	ROUT

		LDRB	R0,[R0]			;Get the digit
		LDR	R12,[R12]		;Find my workspace
		LDR	R1,s_flags		;Load my flags word
		BIC	R1,R1,#s_CHANNEL :OR: s_FAINTCHAN
		CMP	R0,#'1'			;Is it a deep channel?
		ORREQ	R1,R1,#s_CHANNEL
		CMP	R0,#'2'			;Is it a shallow channel?
		ORREQ	R1,R1,#s_CHANNEL :OR: s_FAINTCHAN
		STR	R1,s_flags
		MOVS	PC,R14

		LTORG

;----- SWI names and numbers etc --------------------------------------------

s_swic		ROUT

		LDR	R12,[R12]		;Get my workspace neatly
		CMP	R11,#(%01s_swic-%00s_swic)/4 ;Check SWI is in range
		ADDCC	PC,PC,R11,LSL #2	;Go to correct branch instr
		B	%01s_swic		;Branch to complain thing

00s_swic	B	swi_redraw
		B	swi_doslab
		B	swi_slab
		B	swi_unslab
		B	swi_bbox
		B	swi_ploticon
		B	swi_plotgroup
		B	swi_spritearea
		B	swi_update
		B	swi_slabcol

01s_swic	ADRL	R0,msg_errBadSwi	;Point to error message
		ORRS	PC,R14,#V_flag		;Return with an error

		LTORG

;----- SWI handling ---------------------------------------------------------

; --- Sculptrix_RedrawWindow ---
;
; R1 == pointer to redraw block

swi_redraw	ROUT

		STMFD	R13!,{R0-R11,R14}	;Stack registers

		; --- Find the window origin ---

		MOV	R11,R1			;Keep the pointer nicely
		BL	box_readRectangle	;Find everything about rdrw

		; --- Now go through the icons ---

		SUB	R13,R13,#40		;Make way for an icon block
		MOV	R1,R13			;Point to the block
		LDR	R0,[R11,#0]		;Get the window handle
		MOV	R2,#0			;Start at icon 0
		STMIA	R1,{R0,R2}		;Store them in the block

		; --- Main loop -- go through each icon and plot ---

00swi_redraw	SWI	XWimp_GetIconState	;Read info into block
		ADDVS	R13,R13,#44		;Error -- reclaim stack space
		LDMVSFD	R13!,{R1-R11,PC}	;And return to caller
		LDR	R0,[R1,#24]		;Get the flags word
		CMP	R0,#1<<23		;Is it only deleted?
		ADDEQ	R13,R13,#40		;Yes -- reclaim stack space
		LDMEQFD	R13!,{R0-R11,PC}^	;And return to caller

		; --- Find out whether the icon is visible ---

		ADD	R0,R1,#8		;Point to coords block
		LDMIA	R0,{R0,R2-R4}		;Load the icon coordinates
		CMP	R0,R7
		CMPLE	R2,R8
		CMPLE	R5,R3
		CMPLE	R6,R4
		BGT	%01swi_redraw		;Not visible -- skip it

		ADD	R0,R1,#8		;Point to icon block
		BL	box_ploticon

		; --- Ho-hum.  Now do the next one ---

01swi_redraw	LDR	R0,[R1,#4]		;Get the icon handle
		ADD	R0,R0,#1		;Bump it up a little
		STR	R0,[R1,#4]		;Store it back again
		B	%00swi_redraw		;And go round for another

		LTORG

; --- Sculptrix_DoSlab ---
;
; On entry:	R0 == window handle
;		R1 == icon number
;		R2 == colour to slab to
;
; On exit:	R2 == old colour of icon, or -1 if icon couldn't be slabbed

swi_doslab	ROUT

		STMFD	R13!,{R0-R11,R14}	;Stack registers
		MOV	R9,R2			;Look after the colour
		MOV	R2,#-1			;Store -1 in stacked R2
		STR	R2,[R13,#8]		;Return no colour currently

		; --- Find out if we need to do anything ---

		SUB	R13,R13,#44		;Make way for an icon def
		STMIA	R13,{R0,R1}		;Store icon handle and stuff
		MOV	R1,R13			;Point to icon block
		SWI	XWimp_GetIconState	;Get the icon information
		ADDVS	R13,R13,#48		;If it failed, reclaim stack
		LDMVSFD	R13!,{R1-R11,PC}	;And return the error

		MOV	R3,#0			;Start from the beginning
90swi_doslab	ADD	R0,R1,#8		;Point to actual icon def
		MOV	R2,#'X'			;Get the validation command
		BL	box_findValid		;Find the validation string
		CMP	R2,#0			;Did it work?
		ADDEQ	R13,R13,#44		;No -- reclaim used stack
		LDMEQFD	R13!,{R0-R11,PC}^	;And return to caller

		; --- Get the border type -- only 0 and 2 slab ---

		LDRB	R0,[R2,#1]		;Get the border type number
		CMP	R0,#'0'			;Is it a normal action type?
		CMPNE	R0,#'2'			;Or a default action type?
		MOVNE	R3,R2			;No -- point to this place
		BNE	%90swi_doslab		;And loop back

		; --- It's a worthwhile icon ---

		LDMIA	R1,{R0,R1}		;Load window and icon handles
		MOV	R8,R2			;Look after this pointer
		MOV	R2,R9			;Get the colour wanted
		BL	box_setcolour		;Set the colour properly
		STR	R2,[R13,#44+8]		;Store it nicely away again
		MOV	R1,R13			;Point at the block again

		; --- Update the border ---

		LDRB	R0,[R8,#0]		;Get the border command
		EOR	R0,R0,#&20		;Toggle its case
		STRB	R0,[R8,#0]		;Store it back again

		LDR	R3,[R1,#24]		;Load the icon flags
		EOR	R3,R3,#&005F0000	;Toggle ESG and shaded bit
		TST	R3,#1<<22		;Is the icon shaded?
		TSTNE	R3,#&001F0000		;No -- test the ESG bits
		ADRNE	R11,s_colours		;No -- use normal colours
		ADREQ	R11,s_shadeCols		;Yes -- use shaded colours

		TST	R0,#&20			;Is it set now?
		ADDEQ	R11,R11,#1		;No -- use offset colours

		ADD	R0,R1,#8		;Point to icon def again
		LDMIA	R0,{R3-R6}		;Get icon coords
		SUB	R3,R3,#4		;Make space for border around
		SUB	R4,R4,#4
		ADD	R5,R5,#4
		ADD	R6,R6,#4
		STMIB	R1,{R3-R6}		;That's now our update block
		SWI	XWimp_UpdateWindow	;Try and update it then
		BVS	%01swi_doslab		;If it failed skip this bit
		CMP	R0,#0			;Is there anything to do?
		BEQ	%01swi_doslab		;No -- skip it too

		ADD	R2,R1,#16		;Point to y1
		LDMIA	R2,{R8-R10}		;Get coordinates from block
		SUB	R10,R8,R10		;Get y origin position
		LDR	R8,[R2,#-12]		;Get x0 value from block
		SUB	R9,R8,R9		;Get x origin position

		ADD	R3,R3,#4		;Point back to the icon block
		ADD	R3,R3,R9
		ADD	R4,R4,#4
		ADD	R4,R4,R10
		SUB	R5,R5,#4
		ADD	R5,R5,R9
		SUB	R6,R6,#4
		ADD	R6,R6,R10

00swi_doslab	; --- Draw box (inline copy) ---
		;
		; We only draw the inner slabbed bit -- the rest doesn't
		; change even in the default type.

		ADD	R2,R1,#4
		STMIA	R2,{R3-R6}		;Store adjusted coords away

		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R2
		BL	prim_left
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R2
		BL	prim_right
		BL	prim_bottom
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R2
		BL	prim_top

		; --- Get another rectangle ---

		SWI	XWimp_GetRectangle
		CMP	R0,#0			;Have we anything to do?
		BNE	%00swi_doslab		;Yes -- do it then, dummy

01swi_doslab	ADD	R13,R13,#44
		LDMFD	R13!,{R0-R11,PC}^

		LTORG

; --- Sculptrix_SlabIcon ---
;
; On entry:	R0 == window handle
;		R1 == icon handle
;		R2 == pointer to 4 word slab descriptor to be filled in
; On exit:	--

swi_slab	ROUT

		STMFD	R13!,{R0-R2,R10,R14}	;Keep link register safe

		; --- Fill in the caller's descriptor block ---

		MOV	R10,R2			;Keep the pointer safe
		STMIA	R10,{R0,R1}		;Stash the icon info away
		SWI	XOS_ReadMonotonicTime	;Read the current time
		CMP	R1,#0			;Are mouse buttons pressed?
		ADDEQ	R0,R0,#5		;No -- then bump time on 5
		STR	R0,[R10,#12]		;Store in the descriptor

		; --- Slab the border in or out ---

		LDR	R0,[R10,#0]		;Reload window handle
		LDRB	R2,s_slabcol		;Get the slab colour nicely
		BL	swi_doslab		;Do the slabbing operation
		LDMVSFD	R13!,{R0-R2,R10,PC}	;If it failed, return error

		SUB	R13,R13,#20		;Space for a pointer block
		MOV	R1,R13			;Point to the block
		SWI	XWimp_GetPointerInfo	;Read current mouse state
		LDR	R1,[R13,#8]		;Load the button state
		ADD	R13,R13,#20		;Restore the stack pointer
		CMP	R1,#0			;Are there buttons pressed?
		ORREQ	R2,R2,#256		;Yes -- set a flag bit then
		STR	R2,[R10,#8]		;Store the old icon colour

		; --- Say to pause on unslabs in flags ---

		LDR	R14,s_flags		;Get the flags word
		BIC	R14,R14,#s_UNSLAB	;Clear unslab bit
		STR	R14,s_flags		;Store flags word back

		; --- Return to caller ---

		LDMFD	R13!,{R0-R2,R10,PC}^	;Return to caller

		LTORG

; --- Sculptrix_UnslabIcon ---
;
; On entry:	R2 == pointer to descriptor filled in by Sculptrix_SlabIcon
; On exit:	--

swi_unslab	ROUT

		STMFD	R13!,{R0-R2,R10,R14}	;Stack my registers

		; --- Find out if we need to do any slabbing ---

		LDR	R14,[R2,#8]		;Get the icon colour
		CMP	R14,#-1			;Is it nonslabbed?
		LDMEQFD	R13!,{R0-R2,R10,PC}^

		; --- Do we unslab quickly? ---

		MOV	R10,R2			;Look after slab block
		SUB	R13,R13,#36		;To read the window state
		LDR	R0,s_flags		;Get the flags word
		TST	R0,#s_UNSLAB		;Is the unslab bit set?
		BNE	%03swi_unslab		;Yes -- skip past the wait

		; --- Wait the requisite quantity of time ---

		LDR	R0,[R10,#0]		;Get the window handle
		MOV	R1,R13			;Point to the block
		STR	R0,[R1,#0]		;Store in the block
		SWI	XWimp_GetWindowState	;Get info about the window
		BVS	%01swi_unslab		;It must have been deleted

		LDR	R0,[R1,#32]		;Get the window flags
		TST	R0,#1<<16		;Is the window open?
		BEQ	%01swi_unslab		;And just wait the time out

		; --- Wait for the mouse to be released ---

		LDR	R14,[R10,#8]		;Load colour and flags bits
		TST	R14,#256		;Is the `no mouse' bit set?
		BNE	%01swi_unslab		;And do the wait operation

00swi_unslab	SWI	XOS_Mouse		;Read mouse information
		CMP	R2,#0			;Are the buttons released?
		BNE	%00swi_unslab		;No -- keep waiting
		B	%03swi_unslab		;Do the actual unslab

		; --- Wait for the timer to elapse ---

01swi_unslab	LDR	R1,[R10,#12]		;Load the slab time
		ADD	R1,R1,#10		;Work out unslab time
02swi_unslab	SWI	XOS_ReadMonotonicTime	;Get the current time
		CMP	R1,R0			;How do they compare?
		BPL	%02swi_unslab		;Too low -- go round again

		; --- Actually unslab the icon ---

03swi_unslab	ADD	R13,R13,#36		;Reclaim the stack space
		LDMIA	R10,{R0-R2}		;Get window, icon and colour
		AND	R2,R2,#255		;Clear flags bits etc.
		BL	swi_doslab		;Unslab the icon

		; --- Remember we've done this now ---

		LDR	R0,s_flags		;Get the flags word again
		ORR	R0,R0,#s_UNSLAB		;Set the unslab bit
		STR	R0,s_flags		;Store the flags word away

		; --- Return to caller ---

		LDMFD	R13!,{R0-R2,R10,PC}^	;Return to caller

		LTORG

; --- Sculptrix_BoundingBox ---
;
; On entry:	R1 == pointer to an icon block
; On exit:	R0 == 0 if there was no border
;		block updated to reflect border width

swi_bbox	ROUT

		STMFD	R13!,{R1-R6,R14}	;Stash registers
		MOV	R3,#0			;Start from the beginning
00swi_bbox	MOV	R0,R1			;Point to block
		MOV	R2,#'X'			;The correct magic command
		BL	box_findValid		;Find the validation string
		CMP	R2,#0			;Was it not there?
		MOVEQ	R0,#0			;Mark as nonpresent
		LDMEQFD	R13!,{R1-R6,PC}^	;Then return
		LDRB	R0,[R2,#1]		;Get the border type
		CMP	R0,#'g'			;It could be a group box
		CMPNE	R0,#'G'			;Try both cases
		BEQ	%02swi_bbox		;If so, be clever

		SUBS	R0,R0,#'0'		;Turn into a number
		CMP	R0,#6			;Is it type 6?
		BEQ	%01swi_bbox		;Yes -- be clever
		CMP	R0,#9			;Is it too big?
		MOVCS	R3,R2			;Not there if too high
		BCS	%00swi_bbox		;So try for another one
		LDMIA	R1,{R3-R6}		;Load the bounding box regs
		ADR	R2,box_borders		;Get the border size table
		LDRB	R0,[R2,R0]		;Load the border width
		SUB	R3,R3,R0
		SUB	R4,R4,R0
		ADD	R5,R5,R0
		ADD	R6,R6,R0
		STMIA	R1,{R3-R6}		;Store the sizes back
		LDMFD	R13!,{R1-R6,PC}^	;Return happy

01swi_bbox	LDMIA	R1,{R3-R6}		;Load the bounding box regs
		SUB	R3,R3,#4
		ADD	R5,R5,#4
		STMIA	R1,{R3-R6}
		MOV	R0,#1
		LDMFD	R13!,{R1-R6,PC}^	;Return happy

02swi_bbox	LDMIA	R1,{R3-R6}		;Load the bounding box regs
		SUB	R3,R3,#8
		SUB	R4,R4,#8
		ADD	R5,R5,#8
		ADD	R6,R6,#32
		STMIA	R1,{R3-R6}
		MOV	R0,#1
		LDMFD	R13!,{R1-R6,PC}^	;Return happy

box_borders	DCB	4,8,12,8,4,4,0,12,4

		ROUT

; --- Sculptrix_PlotIcon ---
;
; On entry:	R0 == pointer to icon block
;		R1 == pointer to redraw block

swi_ploticon	ROUT

		STMFD	R13!,{R0-R11,R14}	;Stash loads of registers
		LDMIA	R0,{R0,R2-R8}		;Load the icon coordinates
		STMFD	R13!,{R0,R2-R8}		;Store them on the stack
		BL	box_readRectangle	;Get the graphics window size
		MOV	R0,R13			;Point to the icon block
		BL	box_ploticon		;Plot the icon
		ADD	R13,R13,#32		;Reclaim the space
		LDMFD	R13!,{R0-R11,PC}^	;Return to caller

		LTORG

; --- Sculptrix_PlotGroup ---
;
; On entry:	R0 == pointer to icon block
;		R1 == pointer to redraw block
;		R2 == border type
;		R3 == pointer to title string

swi_plotgroup	ROUT

		STMFD	R13!,{R0-R11,R14}	;Stash loads of registers
		LDMIA	R0,{R0,R4-R10}		;Load the icon coordinates
		STMFD	R13!,{R0,R4-R10}	;Store them on the stack
		BL	box_readRectangle	;Get the graphics window size
		MOV	R0,R13			;Point to the icon block
		MOV	R1,R2			;Get border type number
		MOV	R2,R3			;Get pointer to group string
		BL	box_dogroup		;Plot the icon
		ADD	R13,R13,#32		;Reclaim the space
		LDMFD	R13!,{R0-R11,PC}^	;Return to caller

		LTORG

; --- Sculptrix_SetSpriteArea ---
;
; On entry:	R0 == pointer to sprite area to use

swi_spritearea	ROUT

		STR	R0,s_sarea		;Save it as sprite area ptr
		MOVS	PC,R14			;Return to caller

; --- Sculptrix_UpdateIcon ---
;
; On entry:	R0 == window handle
;		R1 == icon handle to update

swi_update	ROUT

		STMFD	R13!,{R0-R4,R14}	;Save some registers
		SUB	R13,R13,#84		;For icon and redraw blocks
		STMIA	R13,{R0,R1}		;Save the bits at the bottom
		MOV	R1,R13			;Point to the icon block
		SWI	XWimp_GetIconState	;Find the icon's bits out
		BVS	%99swi_update		;If it failed, go ahead
		ADD	R2,R13,#40		;Point to the redraw block
		LDR	R0,[R13,#0]		;Get the window handle again
		STR	R0,[R2,#0]		;Store window handle at base
		ADD	R0,R1,#8		;Point to icon coordinates
		LDMIA	R0,{R0,R1,R3,R14}	;Load the coordinates
		SUB	R0,R0,#16		;Include the border nicely
		SUB	R1,R1,#16
		ADD	R3,R3,#16
		ADD	R14,R14,#16
		STMIB	R2,{R0,R1,R3,R14}	;Save them out again
		MOV	R1,R2			;Point to this block
		SWI	XWimp_UpdateWindow	;Start the window redraw
		BVS	%99swi_update		;If it failed, go ahead

00swi_update	CMP	R0,#0			;Is this the end yet?
		BEQ	%80swi_update		;Yes -- finish up nicely
		ADD	R0,R13,#8		;Point to the icon block
		BL	swi_ploticon		;Plot the icon on the screen
		SWI	XWimp_GetRectangle	;Get the next redraw rect
		B	%00swi_update		;And draw that one too

80swi_update	ADD	R13,R13,#84		;Reclaim all that stack
		LDMFD	R13!,{R0-R4,PC}^	;Return to caller

99swi_update	ADD	R13,R13,#88		;Reclaim stack + R0
		LDMFD	R13!,{R1-R4,PC}		;Return with V still set

		LTORG

; --- Scultrix_SlabColour ---
;
; On entry:	--
;
; On exit:	R2 == standard slabbing-in colour

swi_slabcol	LDRB	R2,s_slabcol
		MOVS	PC,R14

;----- Icon box redrawing ---------------------------------------------------

; --- box_readRectangle ---
;
; On entry:	R1 == pointer to a Wimp redraw block
; On exit:	R1 corrupted
;		R5-R8 == adjusted, window-relative mouse rectangle
;		R9,R10 == screen coords of window origin

box_readRectangle ROUT

		CMP	R1,#0			;Is there a redraw block?
		MOVEQ	R9,#0			;Yes -- don't translate box
		MOVEQ	R10,#0
		MOVEQS	PC,R14			;And return
		ADD	R1,R1,#16		;Point to y1
		LDMIA	R1,{R8-R10}		;Get coordinates from block
		SUB	R10,R8,R10		;Get y origin position
		LDR	R8,[R1,#-12]		;Get x0 value from block
		SUB	R9,R8,R9		;Get x origin position

		; --- Mangle the graphics rectangle ---

		ADD	R1,R1,#12		;Point to the graphics window
		LDMIA	R1,{R5-R8}		;Load the window posn
		SUB	R5,R5,R9		;Convert to window coords
		SUB	R6,R6,R10
		SUB	R7,R7,R9
		SUB	R8,R8,R10

		SUB	R5,R5,#16		;Add a little bit of leeway
		SUB	R6,R6,#32
		ADD	R7,R7,#16
		ADD	R8,R8,#16

		MOVS	PC,R14

		LTORG

; --- box_ploticon ---
;
; On entry:	R0 == pointer to an icon block (writable)
;		R5-R10 == as set by box_readRectangle
; On exit:	R2-R4,R11 corrupted

box_ploticon	ROUT

		MOV	R3,#0
00box_ploticon	STMFD	R13!,{R14}
		MOV	R2,#'X'			;Find X commands in valid
		BL	box_findValid		;Is it there?
		LDMFD	R13!,{R14}		;Get return address back
		CMP	R2,#0			;Check
		MOVEQS	PC,R14			;No -- return to caller

		; --- If the border has a capital letter, invert ---
		;
		; Also, choose the right colours for shaded boxes

		LDR	R11,[R0,#16]		;Get the icon flags word
		EOR	R11,R11,#&005F0000	;Toggle ESG and shaded bits
		TST	R11,#1<<22		;Is the icon shaded?
		TSTNE	R11,#&001F0000		;Or is ESG all set?
		ADRNE	R11,s_colours		;No -- use normal colours
		ADREQ	R11,s_shadeCols		;Yes -- use shaded colours

		LDRB	R4,[R2,#0]		;Get the command letter
		TST	R4,#&20			;Is it upper case?
		ADDEQ	R11,R11,#1		;Yes -- use offset colours

		; --- Get the render type, and handle as required ---

		LDRB	R3,[R2,#1]		;Get the border type number
		ORR	R4,R3,#&20		;Convert to lower case

		CMP	R4,#'g'			;Is it a group box type?
		BEQ	box_plotgroup		;Yes -- plot a group box

		CMP	R4,#'s'			;Is it a gadget text/sprite?
		BEQ	box_plottns		;Yes -- plot cunningly

		; --- Dispatch normal group border numbers ---

		SUB	R3,R3,#'0'		;Convert to a digit
		CMP	R3,#(%02box_ploticon-%01box_ploticon)/4
		ADDCC	PC,PC,R3,LSL #2		;Go to branch table
		B	%03box_ploticon		;Not found -- try next valid

01box_ploticon	B	brd0			;Standard plinth
		B	brd1			;Group ridge/channel
		B	brd2			;Default action button
		B	brd3			;Writable wide border
		B	brd0			;Nonslabbing standard plinth
		B	brd5			;Plinth with ridge intersect
		B	brd6			;Channel terminators
		B	brd7			;Writable with black border
		B	brd8			;Like 4, only different
02box_ploticon

03box_ploticon	MOV	R3,R2			;Point to that command
		B	%00box_ploticon		;And find the next string

		LTORG

; --- box_setcolour ---
;
; On entry:	R0 == window handle
;		R1 == icon handle
;		R2 == colour to set
; On exit:	R2 == old colour of icon

box_setcolour	ROUT

		STMFD	R13!,{R0,R1,R3-R5,R14}	;Stack registers
		MOV	R5,R2			;Keep the colour safe
		SUB	R13,R13,#40		;Make way for icon block
		STMIA	R13,{R0,R1}		;Set up icon block
		MOV	R1,R13			;Point to block
		SWI	XWimp_GetIconState	;Get info about icon
		ADDVS	R13,R13,#44		;If it failed, reset stack
		LDMVSFD	R13!,{R1,R3-R5,PC}	;And return the error

		; --- Check for fonts ---

		LDR	R0,[R1,#24]		;Get icon flags word
		TST	R0,#1<<6		;Check anti-aliased bit
		BEQ	%00box_setcolour	;Reset -- do it normally
		ADD	R0,R1,#8		;Point to icon definition
		MOV	R2,#'F'			;Find F validation string
		MOV	R3,#0			;Start from the beginning
		BL	box_findValid		;Find it
		CMP	R2,#0			;Was it not there?
		ADDEQ	R13,R13,#40		;No -- reset stack ptr
		LDMEQFD	R13!,{R0,R1,R3-R5,PC}^	;We did all we could
		ADR	R0,box_hexdigits	;Point to hex digits table
		LDRB	R0,[R0,R5]		;Get the right digit
		LDRB	R5,[R2,#1]		;Get the old colour
		STRB	R0,[R2,#1]		;Store in validation string
		SUB	R2,R5,#'0'		;Turn into a digit
		CMP	R2,#10			;Is it a hex digit?
		SUBCS	R2,R2,#7		;Yes -- get the number
		CMP	R2,#16			;Is it still too big?
		SUBCS	R2,R2,#&20		;It must have been lower case

		; --- Prod the icon into redrawing ---

		MOV	R0,#0			;Don't set either flags mask
		STR	R0,[R1,#8]		;Set XOR mask
		STR	R0,[R1,#12]		;Set BIC mask
		SWI	XWimp_SetIconState	;Give the icon a little prod
		ADDVC	R13,R13,#40		;It worked fine
		LDMVCFD	R13!,{R0,R1,R3-R5,PC}^	;So return happily
		ADD	R13,R13,#44		;If it failed, reset stack
		LDMFD	R13!,{R1,R3-R5,PC}	;And return the error

		; --- Just set the colours in the time-honoured way ---

00box_setcolour	MOV	R2,#&F			;Only want 4 bits
		AND	R2,R2,R0,LSR #28	;Get old colour in R2
		MOV	R0,R5,LSL #28		;Shift colour into position
		STR	R0,[R1,#8]		;This is our XOR mask
		MOV	R0,#&F0000000		;Only change the colour
		STR	R0,[R1,#12]		;This is our BIC mask
		SWI	XWimp_SetIconState	;Give the icon a little prod
		ADDVC	R13,R13,#40		;It worked fine
		LDMVCFD	R13!,{R0,R1,R3-R5,PC}^	;So return happily
		ADD	R13,R13,#44		;If it failed, reset stack
		LDMFD	R13!,{R1,R3-R5,PC}	;And return the error

box_hexdigits	DCB	"0123456789ABCDEF",0

		LTORG

;----- Messing with validation strings --------------------------------------

; --- box_findValid ---
;
; On entry:	R0 == pointer to icon block
; 		R2 == character to find in block (not case-sensitive)
;		R3 == old pointer to search from, or 0
; On exit:	R3,R4 corrupted
;		R2 points to command string if found, or 0

box_findValid	ROUT

		STMFD	R13!,{R3}		;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	R4,#&100		;Can't put 101 in one instr
		ORREQ	R4,R4,#&01		;Check indirect and text
		ANDEQ	R3,R3,R4		;Mask the bits off
		CMPEQ	R3,R4			;Were they both set?
		MOVNE	R2,#0			;Couldn't find it
		ADDNE	R13,R13,#4
		MOVNES	PC,R14			;No -- return huffily

		; --- Find the validation string ---

		LDR	R3,[R0,#24]		;Get pointer to valid string
		CMP	R3,#-1			;Is it empty?
		MOVEQ	R2,#0			;Yes -- not found
		ADDEQ	R13,R13,#4
		MOVEQS	PC,R14

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

		ORR	R2,R2,#&20		;Make valid char lower case
		LDMFD	R13!,{R4}		;Get search index
		STMFD	R13!,{R14}		;Need another register
		CMP	R4,#0			;Is it the start?
		MOVNE	R3,R4			;No -- start from old pos
		BNE	%02box_findValid	;And skip this command

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

00box_findValid	LDRB	R14,[R3],#1		;Get a byte from string
		ORR	R4,R14,#&20		;Make lower case
		CMP	R4,R2			;Is it a match?
		SUBEQ	R2,R3,#1		;Point back to character
		LDMEQFD	R13!,{PC}^		;And return
		MOV	R4,#0			;Not an excaped character

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

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

		LTORG

;----- Plot text+sprite icons -----------------------------------------------

; --- box_plottns ---
;
; On entry:	R0 == pointer to an icon block (writable)
;		R2 == pointer to the validation string command
;		R5-R10 == set up by box_readRectangle

box_plottns	ROUT

		STMFD	R13!,{R0-R4,R14}	;Stack some registers

		; --- Now copy the sprite name into the buffer ---

		LDR	R0,[R13,#0]		;Find the icon pointer
		MOV	R2,#'s'			;Find the sprite name
		MOV	R3,#0			;Search from the beginning
		BL	box_findValid		;Find the string
		CMP	R2,#0			;Did it find anything?
		BEQ	%99box_plottns		;No -- nothing to do then

		; --- Copy the sprite name into the buffer ---

		ADR	R0,s_buffer		;Point to my buffer
		ADD	R2,R2,#1		;Point to first sprite char
00box_plottns	LDRB	R14,[R2],#1		;Get the character
		CMP	R14,#';'		;Is it the string end?
		CMPNE	R14,#','		;Or the sprite name end?
		CMPNE	R14,#&1F		;Or the validation string end
		MOVLS	R14,#0			;Yes -- null terminate
		STRB	R14,[R0],#1		;Store in the buffer
		BHI	%00box_plottns		;No -- loop round again

		; --- Now read the sprite information ---

		STMFD	R13!,{R5,R6}		;Save some registers
		MOV	R0,#40			;Read sprite information
		LDR	R1,s_sarea		;Find the user's sprite area
		ADR	R2,s_buffer		;Point to the block
		CMP	R1,#1			;Is it the wimp area
		BEQ	%f05			;Yes -- skip on then
		ORR	R0,R0,#&100		;No -- say user sprite area
		SWI	XOS_SpriteOp		;So try to cope with that
		BVC	%f06			;If OK skip onwards

05		MOV	R0,#40			;Read sprite information
		ADR	R2,s_buffer		;Point to the block
		SWI	XWimp_SpriteOp

06		MOV	R0,R6			;Get the sprite's mode number
		LDMFD	R13!,{R5,R6}		;Unstack the registers
		BVS	%99box_plottns		;No sprite, no text

		; --- Find the width of the sprite, then ---

		MOV	R1,#4			;Read XEigFactor
		SWI	XOS_ReadModeVariable	;Read the value then
		BVS	%99box_plottns		;No sprite mode, no text
		MOV	R4,R3,LSL R2		;Get sprite width in OS units

		; --- Plot the icon to avoid strangeness ---

		LDR	R1,[R13,#0]		;Get the icon block pointer
		SWI	XWimp_PlotIcon		;Plot the icon onto screen

		; --- Copy the text string into the buffer ---

		LDR	R2,[R13,#8]		;Find the validation string
		ADD	R0,R2,#2		;Point to the text string
		ADR	R1,s_buffer		;Point to the buffer start

10box_plottns	LDRB	R14,[R0],#1		;Get a byte from the string
		CMP	R14,#'\'		;Is it an escape?
		BEQ	%11box_plottns		;Yes -- handle it specially
		CMP	R14,#';'		;Or the next command?
		CMPNE	R14,#&1F		;Is it a control character
		MOVLS	R14,#0			;Yes -- store a null byte
		STRB	R14,[R1],#1		;Store the character away
		BHI	%10box_plottns		;No -- loop round again
		B	%12box_plottns		;Yes -- branch away

11box_plottns	LDRB	R14,[R0],#1		;Get the escaped byte
		CMP	R14,#32			;Is it a control character?
		MOVCC	R14,#0			;Yes -- store a real term
		STRB	R14,[R1],#1		;Store the character away
		BCS	%10box_plottns		;And get another one

		; --- Now plot the text part ---

12box_plottns	MOV	R0,#8			;Get the current font handle
		SWI	XWimp_ReadSysInfo	;Go and do that then
		MOVVS	R0,#0			;If failed, assume system
		CMP	R0,#0			;Is there a magic font?
		LDR	R1,[R13,#0]		;Find the icon block again
		LDR	R0,[R1,#16]		;Find the icon flags word
		MOV	R14,#&FF000000		;Mask for the old flags
		ORRNE	R14,R14,#&00400000	;If antialiased, copy shade
		LDR	R2,=&00000111		;Magic flags for text part
		AND	R0,R0,R14		;Keep original colours
		ORR	R0,R0,R2		;Mix 'n' match the icon flags
		STR	R0,[R1,#16]		;Store that back again
		LDR	R0,[R1,#0]		;Get left icon edge
		ADD	R0,R0,R4		;Offset by the right amount
		STR	R0,[R1,#0]		;Store it back again
		ADR	R14,s_buffer		;Find the buffer pointer
		STR	R14,[R1,#20]		;Point to the text string
		MOV	R0,#-1			;No validation string pliz
		STR	R0,[R1,#24]		;Store it in the buffer
		SWI	XWimp_PlotIcon		;And stick it on the screen

		; --- Tidy up and leave ---

99box_plottns	LDMFD	R13!,{R0-R4,PC}^	;Return to caller if OK

		LTORG

;----- Plot group boxes -----------------------------------------------------

; --- box_plotgroup ---
;
; On entry:	R0 == pointer to an icon block (writable)
;		R2 == pointer to the validation string command
;		R5-R10 == set up by box_readRectangle

box_plotgroup	ROUT

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

		; --- Copy the string into the buffer ---

		LDR	R2,[R13,#8]		;Find the validation string
		ADD	R0,R2,#3		;Point to the text string
		ADR	R1,s_buffer		;Point to the buffer start

00box_plotgroup	LDRB	R14,[R0],#1		;Get a byte from the string
		CMP	R14,#'\'		;Is it an escape?
		BEQ	%01box_plotgroup	;Yes -- handle it specially
		CMP	R14,#';'		;Or the next command?
		CMPNE	R14,#&1F		;Is it a control character
		MOVLS	R14,#0			;Yes -- terminate string
		STRB	R14,[R1],#1		;Store the character away
		BHI	%00box_plotgroup	;No -- loop round again
		B	%02box_plotgroup	;Yes -- branch away

01box_plotgroup	LDRB	R14,[R0],#1		;Get the escaped byte
		CMP	R14,#32			;Is it a control character?
		MOVCC	R14,#0			;Yes -- store a real term
		STRB	R14,[R1],#1		;Store the character away
		BCS	%00box_plotgroup	;And get another one

		; --- Now plot the group border ---

02box_plotgroup	LDR	R0,[R13,#0]		;Get the icon block pointer
		LDRB	R1,[R2,#2]		;Get the border type
		SUB	R1,R1,#'0'		;Convert to an integer
		ADR	R2,s_buffer		;Point to the string
		BL	box_dogroup		;Handle the actual plotting

		; --- Tidy up and leave ---

03box_plotgroup	LDMFD	R13!,{R0-R2,PC}^	;Return to caller if OK

		LTORG

; --- box_dogroup ---
;
; On entry:	R0 == pointer to coordinates box
;		R1 == group border type number
;		R2 == pointer to group title string

box_dogroup	ROUT

		STMFD	R13!,{R11,R14}		;Store registers
		LDR	R14,s_flags		;Get the flags word
		TST	R14,#s_CHANNEL		;Does the user want channels?
		EORNE	R1,R1,#1		;Yes -- toggle channelness
		ADR	R14,%02box_dogroup
		CMP	R1,#(%02box_dogroup-%01box_dogroup)/4
		ADDCC	PC,PC,R1,LSL #2		;Go to branch table
		LDMFD	R13!,{R11,PC}^		;Return to caller

01box_dogroup	B	grp0			;Standard ridge and plinth
		B	grp1			;Acorn channel and gap
		B	grp2			;Standard ridge and plinth
		B	grp3			;Acorn channel and gap

02box_dogroup	LDMFD	R13!,{R11,PC}		;Return to caller

;----- Drawing group borders ------------------------------------------------

; --- grp_titleicon ---
;
; On entry:	R0 == pointer to icon coordinates to bodge
;		R1 == left gap for icon title
;		R2 == pointer to title string
; On exit:	R0 == pointer to adjusted box

grp_titleicon	ROUT

		STMFD	R13!,{R0-R5,R14}	;Stash registers away nicely

		; --- Work out the length of the string ---

		MOV	R5,#0			;Nothing counted yet
00grp_titleicon	LDRB	R14,[R2,R5]		;Get the next character
		CMP	R14,#32			;Is it a control char?
		ADD	R5,R5,#1		;If not, bump the length
		BCS	%00grp_titleicon	;And loop round again

		MOV	R0,#8			;Read the Wimp font handle
		SWI	XWimp_ReadSysInfo	;Try and find it
		MOVVS	R5,R5,LSL #4		;Multiply by 16
		BVS	%01grp_titleicon	;If not supported, ignore
		CMP	R0,#0			;Is there a font used?
		MOVEQ	R5,R5,LSL #4		;Multiply by 16
		BEQ	%01grp_titleicon	;If not, skip ahead a bit

		; --- Work out the width of the string ---

		MOV	R1,#1000		;Just something big
		MOV	R2,#1000		;Something else big :-)
		SWI	XFont_Converttopoints	;Convert them to millipts
		SWI	XFont_SetFont		;Set this as the current font
		MOV	R3,R2			;Move these coords now
		MOV	R2,R1
		LDR	R1,[R13,#8]		;Find the string pointer
		MOV	R4,#-1			;Don't split the string
		SWI	XFont_StringWidth	;Find the width of the string
		MOV	R1,R2			;Move the coords back again
		MOV	R2,R3
		SWI	XFont_ConverttoOS	;Convert back to OS units
		ADD	R5,R1,#16		;Get the string width

		; --- Now bodge the icon block ---

01grp_titleicon	LDMIA	R13,{R0,R1}		;Get block ptr and offset
		LDMIA	R0,{R2,R3,R4,R14}	;Get the icon coords
		ADD	R2,R2,R1		;Offset the left side
		SUB	R3,R14,#20		;Find bottom of group box
		ADD	R4,R2,R5		;Add on the string width
		ADD	R14,R14,#28		;Find the top of the icon
		STMIA	R0,{R2,R3,R4,R14}	;Store the modified coords

		; --- Bodge the rest of the icon ---

		LDR	R2,[R13,#8]		;Find the string pointer
		STR	R2,[R0,#20]		;Store this as data
		MOV	R2,#-1			;No validation string
		STR	R2,[R0,#24]		;Store this away too
		MOV	R2,#1			;It doesn't care about this
		STR	R2,[R0,#28]		;Store this as the length
		LDR	R2,=&17000139		;Icon flags word
		STR	R2,[R0,#16]		;Store this as icon flags

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

; --- grp_fillBorder ---
;
; On entry:	R5-R8 == box coordinates (!)
;		R9,R10 == window origin coordinates on the screen
;
; Removed in version 1.14

 [ {FALSE}

grp_fillBorder	ROUT

 		STMFD	R13!,{R0-R4,R14}	;Save some registers
 		MOV	R0,#1			;Grey background
 		SWI	XWimp_SetColour		;Set up the background
 		MOV	R0,#4			;Move absolute
 		ADD	R1,R5,R9		;Translate left hand side
 		ADD	R2,R6,R10		;Translate bottom edge
 		SWI	XOS_Plot		;Move there
 		MOV	R0,#101			;Filled rectangle, absolute
 		ADD	R1,R7,R9		;Translate right hand side
 		ADD	R2,R8,R10		;Translate top edge
		LDMIA	R12,{R3,R4}		;Get the pixel sizes
		SUB	R1,R1,R3		;Chop a bit off the right
		SUB	R2,R2,R4		;Chop a bit off the top
		SWI	XOS_Plot		;Fill in the background
		LDMFD	R13!,{R0-R4,PC}^	;Restore the registers

		LTORG
 ]

; --- grp 0 ---

grp0		STMFD	R13!,{R1-R8,R14}	;Stash registers

		LDMIA	R0,{R5-R8}		;Get the border coordinates
		STMFD	R13!,{R5-R8}		;Save them on the stack
		MOV	R3,R0			;Keep this pointer safe
;		BL	grp_fillBorder		;Don't fill in 1.14

		; --- Translate the icon block ---

		MOV	R1,#16			;Small offset here
		BL	grp_titleicon		;Find the icon position

		; --- Now display the main border ---

		LDMIA	R0,{R5-R8}		;Save this position
		MOV	R0,R13			;Point to border position
		MOV	R1,R3			;Point to title position
		ADR	R11,s_colours		;Point to colour table
		BL	gborder			;Plot the group border

		; --- Now display the main title border ---

		STMIA	R3,{R5-R8}		;Restore saved position
		MOV	R0,R3			;Point to the position
		BL	brd5			;Plot the top plinth
		STMIA	R0,{R5-R8}		;Restore that again
		MOV	R1,R0			;Point to the icon block
		SWI	XWimp_PlotIcon		;Now plot the icon on top
		ADD	R13,R13,#16		;Restore stack pointer
		LDMFD	R13!,{R1-R8,PC}		;Return to caller

; --- grp 1 ---

grp1		STMFD	R13!,{R1-R8,R14}	;Stash registers

		LDMIA	R0,{R5-R8}		;Get the border coordinates
		STMFD	R13!,{R5-R8}		;Save them on the stack
		MOV	R3,R0			;Keep this pointer safe

		; --- Translate the icon block ---

		MOV	R1,#16			;Small offset here
		BL	grp_titleicon		;Find the icon position

		; --- Now display the main border ---

		LDMIA	R0,{R5-R8}		;Save this position
		MOV	R0,R13			;Point to border position
		MOV	R1,R3			;Point to title position
		LDR	R11,s_flags		;Get the flags word
		TST	R11,#s_FAINTCHAN	;Is it meant to be faint
		ADREQ	R11,s_colours+1		;Point to colour table
		ADRNE	R11,s_shadeCols+1
		BL	gborder			;Plot the group border

		; --- Now display the main title border ---

		STMIA	R3,{R5-R8}		;Restore saved position
		MOV	R0,R3			;Point to the position
		BL	brd6			;Plot the top thingy
		STMIA	R0,{R5-R8}		;Restore that again
		MOV	R1,R0			;Point to the icon block

		; --- Stop the top bit from being filled ---

		LDR	R0,[R1,#16]
		BIC	R0,R0,#(1<<5)		;Clear filled flag
		STR	R0,[R1,#16]

		SWI	XWimp_PlotIcon		;Now plot the icon on top
		ADD	R13,R13,#16		;Restore stack pointer
		LDMFD	R13!,{R1-R8,PC}		;Return to caller

; --- grp 2 ---

grp2		STMFD	R13!,{R1-R8,R14}	;Stash registers

		LDMIA	R0,{R5-R8}		;Get the border coordinates
		STMFD	R13!,{R5-R8}		;Save them on the stack
		MOV	R3,R0			;Keep this pointer safe
;		BL	grp_fillBorder		;Don't fill in 1.14

		; --- Translate the icon block ---

		MOV	R1,#32			;Large offset here
		BL	grp_titleicon		;Find the icon position

		; --- Now display the main border ---

		LDMIA	R0,{R5-R8}		;Save this position
		MOV	R0,R13			;Point to border position
		MOV	R1,R3			;Point to title position
		ADR	R11,s_colours		;Point to colour table
		BL	gborder			;Plot the group border

		; --- Now display the main title border ---

		STMIA	R3,{R5-R8}		;Restore saved position
		MOV	R0,R3			;Point to the position
		BL	brd5			;Plot the top plinth
		STMIA	R0,{R5-R8}		;Restore that again
		MOV	R1,R0			;Point to the icon block
		SWI	XWimp_PlotIcon		;Now plot the icon on top
		ADD	R13,R13,#16		;Restore stack pointer
		LDMFD	R13!,{R1-R8,PC}		;Return to caller

; --- grp 3 ---

grp3		STMFD	R13!,{R1-R8,R14}	;Stash registers

		LDMIA	R0,{R5-R8}		;Get the border coordinates
		STMFD	R13!,{R5-R8}		;Save them on the stack
		MOV	R3,R0			;Keep this pointer safe

		; --- Translate the icon block ---

		MOV	R1,#32			;Small offset here
		BL	grp_titleicon		;Find the icon position

		; --- Now display the main border ---

		LDMIA	R0,{R5-R8}		;Save this position
		MOV	R0,R13			;Point to border position
		MOV	R1,R3			;Point to title position
		LDR	R11,s_flags		;Get the flags word
		TST	R11,#s_FAINTCHAN	;Is it meant to be faint
		ADREQ	R11,s_colours+1		;Point to colour table
		ADRNE	R11,s_shadeCols+1
		BL	gborder			;Plot the group border

		; --- Now display the main title border ---

		STMIA	R3,{R5-R8}		;Restore saved position
		MOV	R0,R3			;Point to the position
		BL	brd6			;Plot the top thingy
		STMIA	R0,{R5-R8}		;Restore that again
		MOV	R1,R0			;Point to the icon block

		; --- Stop the top bit from being filled ---

		LDR	R0,[R1,#16]
		BIC	R0,R0,#(1<<5)		;Clear filled flag
		STR	R0,[R1,#16]

		SWI	XWimp_PlotIcon		;Now plot the icon on top
		ADD	R13,R13,#16		;Restore stack pointer
		LDMFD	R13!,{R1-R8,PC}		;Return to caller

; --- gborder ---
;
; On entry:	R0 == pointer to icon coordinates block (writable)
;		R1 == pointer to title icon coordinate
;		R9 == x coord of window origin on screen
;		R10 == y coord of window origin on screen
;
; Plots a group border such that it doesn't overlap the title icon at all.

gborder		ROUT

		STMFD	R13!,{R0-R5,R8,R14}	;Stack registers away
		MOV	R8,R1			;Keep this pointer safe

		; --- Now convert all the boxes to screen coords ---

		LDMIA	R0,{R1-R4}		;Get the straight box
		BL	box_convert
		STMIA	R0,{R1-R4}		;Write it back nicely

		SUB	R1,R1,#4		;Now expand it a little
		SUB	R2,R2,#4
		ADD	R3,R3,#4
		ADD	R4,R4,#4
		STMFD	R13!,{R1-R4}		;Stash them on the stack

		LDMIA	R8,{R1-R4}		;Get the title position
		BL	box_convert

		STMFD	R13!,{R1-R4}		;Save them on the stack too

		; --- Now render all the parts except for the top ---

		MOV	R1,R0
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		ADD	R0,R13,#16
		BL	prim_left
		MOV	R0,R1
		BL	prim_right
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		ADD	R0,R13,#16
		BL	prim_right
		BL	prim_bottom
		MOV	R0,R1
		BL	prim_left
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_bottom

		; --- Now fix up the top coordinates ---

		LDR	R0,[R13,#8]		;Get right side of title box
		ADD	R0,R0,#8		;Move it clear of the group
		LDR	R5,[R1,#0]		;Get the old left hand side
		STR	R0,[R1,#0]		;Store as left side here
		STR	R0,[R13,#16]		;And left side for other one

		; --- Now render the left top sides ---

		ADD	R0,R13,#16
		BL	prim_top
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_top

		; --- Now get the right top sides ---

		STR	R5,[R1,#0]		;Store it back again
		SUB	R5,R5,#4		;Fiddle for outer border
		STR	R5,[R13,#16]		;Save in outer border block

		LDR	R0,[R13,#0]		;Get right hand side of this
		SUB	R0,R0,#4		;Move it over a little
		STR	R0,[R1,#8]		;Store as rightside here
		STR	R0,[R13,#24]		;And right side for other one

		; --- Now render the right top sides ---

		MOV	R0,R1
		BL	prim_top
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		ADD	R0,R13,#16
		BL	prim_top

		; --- Return -- it's all over ---

                ADD	R13,R13,#32		;Restore the stack pointer

		LDMFD	R13!,{R0-R5,R8,PC}^	;Return to caller

		LTORG

;----- Draw the border types ------------------------------------------------
;
; All entry:	R0 == pointer to icon coordinates block (writable)
;		R9 == x coord of window origin on screen
;		R10 == y coord of window origin on screen

; --- brd8 ---

brd8		ROUT

		STMFD	R13!,{R14}
		LDR	R14,s_flags
		TST	R14,#s_FAINTCHAN
		ANDNE	R14,R11,#3
		ADRNE	R11,s_shadeCols
		ADDNE	R11,R11,R14
		LDMFD	R13!,{R14}

; --- brd0 ---

brd0		ROUT

		STMFD	R13!,{R0-R4,R14}	;Stack registers away
		LDMIA	R0,{R1-R4}		;Load the coordinates
		BL	box_convert
		STMIA	R0,{R1-R4}
		MOV	R1,R0			;Keep pointer to box

		; --- Draw bits of the border ---

		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_left
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_right
		BL	prim_bottom
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_top

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

		LTORG

; --- brd1 ---

brd1		ROUT

		STMFD	R13!,{R0-R4,R14}	;Stack registers away
		SUB	R13,R13,#16		;Make space for another blk
		LDMIA	R0,{R1-R4}		;Load the coordinates
		BL	box_convert
		STMIA	R0,{R1-R4}
		SUB	R1,R1,#4
		SUB	R2,R2,#4
		ADD	R3,R3,#4
		ADD	R4,R4,#4
		STMIA	R13,{R1-R4}
		MOV	R1,R0			;Keep pointer to box

		; --- Draw bits of the border ---

		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_left
		MOV	R0,R1
		BL	prim_right
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_right
		BL	prim_bottom
		MOV	R0,R1
		BL	prim_left
		BL	prim_top
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_top
		MOV	R0,R1
		BL	prim_bottom

		ADD	R13,R13,#16
		LDMFD	R13!,{R0-R4,PC}^	;Return to caller

		LTORG

; --- brd2 ---

brd2		ROUT

		STMFD	R13!,{R0-R4,R14}	;Stack registers away
		LDMIA	R0,{R1-R4}		;Load the coordinates
		BL	box_convert
		STMIA	R0,{R1-R4}
		SUB	R1,R1,#4
		SUB	R2,R2,#4
		ADD	R3,R3,#4
		ADD	R4,R4,#4
		STMFD	R13!,{R1-R4}
		SUB	R1,R1,#4
		SUB	R2,R2,#4
		ADD	R3,R3,#4
		ADD	R4,R4,#4
		STMFD	R13!,{R1-R4}
		MOV	R1,R0			;Keep pointer to box

		; --- Draw inside border ---

		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_left
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_right
		BL	prim_bottom
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_top

		; --- Draw rim around the middle ---
		;
		; It's overkill, but I'll use the calls below for this

		LDR	R0,s_rimcol
		SWI	XWimp_SetColour
		ADD	R0,R13,#16
		BL	prim_left
		BL	prim_right
		BL	prim_top
		BL	prim_bottom

		; --- Draw surrounding border ---

		BIC	R11,R11,#1		;Round pointer downwards
		LDR	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_left
		LDR	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_right
		BL	prim_bottom
		LDR	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_top

		ADD	R13,R13,#32
		LDMFD	R13!,{R0-R4,PC}^	;Return to caller

		LTORG
; --- brd3 ---

brd3		ROUT

		STMFD	R13!,{R0-R4,R14}	;Stack registers away
		LDMIA	R0,{R1-R4}		;Load the coordinates
		BL	box_convert
		STMIA	R0,{R1-R4}
		MOV	R1,R0			;Save this away

		; --- Fill in the inside section to overwrite marbling ---

		MOV	R0,#1
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_left
		BL	prim_right
		BL	prim_bottom
		BL	prim_top

		LDMIA	R0,{R1-R4}
		SUB	R1,R1,#4
		SUB	R2,R2,#4
		ADD	R3,R3,#4
		ADD	R4,R4,#4
		STMIA	R0,{R1-R4}
		MOV	R1,R0			;Keep pointer to box

		; --- Draw bits of the border ---

		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_left
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_right
		BL	prim_bottom
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_top

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

		LTORG

; --- brd5 ---

brd5		ROUT

		STMFD	R13!,{R0-R4,R14}	;Stack registers away
		LDMIA	R0,{R1-R4}		;Load the coordinates
		BL	box_convert
		STMIA	R0,{R1-R4}
		SUB	R14,R4,R2		;Get height of box
		ADD	R2,R2,R14,LSR #1	;Centre R2 in box
		SUB	R4,R2,#4		;Move thing to right place
		ADD	R2,R2,#4		;And copy across
		SUB	R3,R1,#4		;Set up the nick width
		STMFD	R13!,{R1-R4}		;Stash them on the stack
		MOV	R1,R0			;Keep pointer to box

		; --- Draw bits of the border ---

		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_left
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_right
		BL	prim_bottom
		MOV	R0,R13
		BL	prim_top
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R1
		BL	prim_top
		LDMIA	R1,{R1-R3}
		LDR	R2,[R13,#4]
		ADD	R1,R3,#4
		STMIA	R13,{R1-R3}
		MOV	R0,R13
		BL	prim_bottom

		ADD	R13,R13,#16
		LDMFD	R13!,{R0-R4,PC}^	;Return to caller

		LTORG

; --- brd6 ---

brd6		ROUT

		STMFD	R13!,{R0-R4,R14}	;Stack registers away
		LDMIA	R0,{R1-R4}		;Load the coordinates
		BL	box_convert
		STMIA	R0,{R1-R4}
		SUB	R14,R4,R2		;Get height of box
		ADD	R2,R2,R14,LSR #1	;Centre R2 in box
		MOV	R4,R2			;Move thing to right place
		SUB	R3,R1,#4		;Set up the nick width
		STMFD	R13!,{R1-R4}		;Stash them on the stack
		MOV	R1,R0			;Keep pointer to box

		; --- Draw bits of the border ---

		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_left
		LDRB	R0,[R11,#0]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_top

		LDMIA	R1,{R1-R3}
		LDR	R2,[R13,#4]
		ADD	R1,R3,#4
		STMIA	R13,{R1-R3}

		BL	prim_right
		LDRB	R0,[R11,#1]
		SWI	XWimp_SetColour
		MOV	R0,R13
		BL	prim_bottom

		ADD	R13,R13,#16
		LDMFD	R13!,{R0-R4,PC}^	;Return to caller

		LTORG

; --- brd7 ---

brd7		ROUT

		STMFD	R13!,{R0-R10,R14}	;Stack registers away
		LDMIA	R0,{R1-R4}		;Load the coordinates
		BL	box_convert
		STMFD	R13!,{R1-R4}
		MOV	R10,R0			;Save this away
		LDR	R9,[R10,#16]		;Load the icon's flags

		; --- Find out about the icon's colours ---

		TST	R9,#1<<6		;Is it anti-aliased?
		BEQ	%10brd7			;No -- skip this bit out then

		BIC	R9,R9,#&ff000000	;Clear out the font handle
		MOV	R2,#'F'			;Find font validation strings
		MOV	R3,#0			;Start from the beginning
		BL	box_findValid		;Find the colour command
		CMP	R2,#0			;Was it not there at all?
		ORREQ	R9,R9,#&07000000	;No -- use default colours
		BEQ	%10brd7			;And skip to the end

		LDRB	R0,[R2,#1]		;Load a byte from the string
		SUB	R0,R0,#'0'		;Turn it into a number
		CMP	R0,#10			;Is it a letter, not a digit?
		SUBCS	R0,R0,#7		;Yes -- compensate for that
		CMP	R0,#16			;Is it lowercase?
		SUBCS	R0,R0,#&20		;Yes -- deal with that case

		LDRB	R1,[R2,#2]		;Load the next byte too
		SUB	R1,R1,#'0'		;Turn it into a number
		CMP	R1,#10			;Is it a letter, not a digit?
		SUBCS	R1,R1,#7		;Yes -- compensate for that
		CMP	R1,#16			;Is it lowercase?
		SUBCS	R1,R1,#&20		;Yes -- deal with that case

		ORR	R9,R9,R0,LSL #28	;Fit the background colour in
		ORR	R9,R9,R1,LSL #24	;And the foreground colour

		; --- First plot the whole background ---

10brd7		ADR	R14,s_dx		;Point to the pixel sizes
		LDMIA	R14,{R7,R8}		;Load them out nicely
		LDMFD	R13!,{R3-R6}		;Load the coordinates out

		TST	R9,#1<<5		;Is the icon filled?
		BEQ	%20brd7			;No -- skip this bit out

		MOV	R0,R9,LSR #28		;Get the background colour
		AND	R0,R0,#&f		;Clear all the other bits
		SWI	XWimp_SetColour		;Set the bit's colour

		MOV	R0,#plot_MOVE+plot_ABSOLUTE
		SUB	R1,R3,#4
		SUB	R2,R4,#4
		ADD	R1,R1,R7		;Don't overlap the border
		ADD	R2,R2,R8
		SWI	XOS_Plot		;Move to the bottom left

		MOV	R0,#plot_RECTFILL+plot_ABSOLUTE+plot_FORE
		ADD	R1,R5,#4
		ADD	R2,R6,#4
		SUB	R1,R1,R7,LSL #1
		SUB	R2,R2,R8,LSL #1
		SWI	XOS_Plot		;Fill in the background

		; --- Plot the foreground border now ---

20brd7		MOV	R0,R9,LSR #24		;Get the foreground colour
		AND	R0,R0,#&f		;Clear all the other bits
		SWI	XWimp_SetColour		;Set the bit's colour

		MOV	R0,#plot_MOVE+plot_ABSOLUTE
		SUB	R1,R3,#4
		SUB	R2,R4,#4
		SWI	XOS_Plot		;Move to the bottom left

		MOV	R0,#plot_LINE+plot_ABSOLUTE+plot_FORE
		ADD	R1,R5,#4
		SUB	R1,R1,R7
		SUB	R2,R4,#4
		SWI	XOS_Plot		;Plot the left hand side

		MOV	R0,#plot_LINE+plot_ABSOLUTE+plot_FORE
		ADD	R1,R5,#4
		SUB	R1,R1,R7
		ADD	R2,R6,#4
		SUB	R2,R2,R8
		SWI	XOS_Plot		;Plot the top edge

		MOV	R0,#plot_LINE+plot_ABSOLUTE+plot_FORE
		SUB	R1,R3,#4
		ADD	R2,R6,#4
		SUB	R2,R2,R8
		SWI	XOS_Plot		;Plot the right hand side

		MOV	R0,#plot_LINE+plot_ABSOLUTE+plot_FORE
		SUB	R1,R3,#4
		SUB	R2,R4,#4
		SWI	XOS_Plot		;Plot the bottom edge

		; --- Now plot a writable border (type 3) ---

		LDMIA	R10,{R0-R3}		;Load the coordinates
		SUB	R0,R0,#4		;Modify for the extra border
		SUB	R1,R1,#4
		ADD	R2,R2,#4
		ADD	R3,R3,#4
		STMIA	R10,{R0-R3}

		LDMFD	R13!,{R0-R10,R14}	;Restore all the registers
		B	brd3			;And plot the writable border

		LTORG


;----- Mangle coordinates for the mode --------------------------------------

; --- box_convert ---
;
; Converts box given in R1-R4 by translating to screen coords and rounding
; down to pixel boundaries

box_convert	ROUT

		STMFD	R13!,{R0,R14}		;Stash registers

		; --- Convert to screen coordinates ---

		ADD	R1,R1,R9
		ADD	R2,R2,R10
		ADD	R3,R3,R9
		ADD	R4,R4,R10

		; --- Round off to whole pixel sizes ---

		LDR	R0,s_dx
		LDR	R14,s_dy
		SUB	R0,R0,#1
		SUB	R14,R14,#1
		BIC	R1,R1,R0
		BIC	R2,R2,R14
		BIC	R3,R3,R0
		BIC	R4,R4,R14
		LDMFD	R13!,{R0,PC}

;----- Set up the VDU variables in the buffer -------------------------------

; --- vdu_set ---

vdu_set		ROUT

		STMFD	R13!,{R0-R3,R14}	;Stack some registers
		ADR	R0,vdu_wanted		;Which ones do we want?
		ADR	R1,s_dx			;Where do we want them?
		SWI	XOS_ReadVduVariables	;Read the values
		LDMIA	R1,{R0,R2}		;Read their values into regs
		CMP	R2,#2			;Is this a high-pixel mode?
		MOVEQ	R3,#2			;Yes -- use a default value
		MOVNE	R3,#4
		MOVNE	R3,R3,LSR R2		;No -- divide up border
		RSBNE	R3,R3,#4
		MOV	R14,#1
		MOV	R0,R14,LSL R0		;Convert these to pixel sizes
		MOV	R2,R14,LSL R2
		STMIA	R1,{R0,R2,R3}		;Store back in workspace
		LDMFD	R13!,{R0-R3,PC}^	;Return to caller

vdu_wanted	DCD	vdu_XEIG
		DCD	vdu_YEIG
		DCD	-1

		LTORG

;----- Plot primitives ------------------------------------------------------

; --- prim_left ---
;
; Plots a vertical strip in the current foreground colour on the left of an
; icon box.
;
; On entry:	R0 == pointer to the icon bounding box

prim_left	ROUT

		STMFD	R13!,{R0-R3,R14}	;Keep the stack pointer busy
		MOV	R3,R0			;Keep the pointer safe
		LDMIA	R3!,{R1,R2}		;Get the bottom left coord
		SUB	R1,R1,#4		;Make way for the border
		SUB	R2,R2,#4		;Make way for the border
		MOV	R0,#plot_MOVE+plot_ABSOLUTE
		SWI	XOS_Plot		;Move to first corner
		LDR	R1,s_dx			;Get the pixel width
		RSB	R1,R1,#4		;Trim the width a little
		LDR	R3,[R3,#4]		;Get the top coordinate
		SUB	R2,R3,R2		;Find the height of the strip
		LDR	R3,s_dy			;Get the y pixel size
		SUB	R2,R2,R3		;And add that in too
		ADD	R2,R2,#4		;And add the border width
		MOV	R0,#plot_RECTFILL+plot_FORE+plot_RELATIVE
		SWI	XOS_Plot		;Plot the rectangle
		LDMFD	R13!,{R0-R3,PC}^	;Return to caller

		LTORG

; --- prim_right ---
;
; Plots a vertical strip in the current foreground colour on the right of an
; icon box.
;
; On entry:	R0 == pointer to the icon bounding box

prim_right	ROUT

		STMFD	R13!,{R0-R3,R14}	;Keep the stack pointer busy
		ADD	R3,R0,#16		;Point to the top of the box
		LDMDB	R3!,{R1,R2}		;Get the top right coord
		LDR	R0,s_dy			;Get the y pixel size
		SUB	R2,R2,R0
		ADD	R2,R2,#4		;Make way for the border
		MOV	R0,#plot_MOVE+plot_ABSOLUTE
		SWI	XOS_Plot		;Move to first corner
		LDR	R1,s_dx			;Get the pixel width
		RSB	R1,R1,#4		;Trim the width a little
		LDR	R3,[R3,#-4]		;Get the bottom coordinate
		SUB	R2,R3,R2		;Find the height of the strip
		SUB	R2,R2,#4		;And add the border width
		MOV	R0,#plot_RECTFILL+plot_FORE+plot_RELATIVE
		SWI	XOS_Plot		;Plot the rectangle
		LDMFD	R13!,{R0-R3,PC}^	;Return to caller

		LTORG

; --- prim_bottom ---
;
; Plots a horizontal strip in the current foreground colour along the bottom
; of an icon, with a little jagged bit on the left hand side.
;
; On entry:	R0 == pointer to icon block


prim_bottom	ROUT

		STMFD	R13!,{R0-R2,R7-R11,R14}	;Keep stack pointer moving

		; --- Load the variables we need ---

		LDMIA	R0,{R9-R11}		;Get useful coordinates out
		LDR	R1,s_dx			;Get x pixel width
		LDR	R8,s_dy			;Get y pixel width
		LDR	R2,s_start		;Get start X offset

		; --- Initialise variables for first loop ---

		SUB	R9,R9,R2		;Shift x0 back a little
		SUB	R11,R11,R1		;Shift x1 past icon edge
		SUB	R2,R10,R8		;Move y below the icon
		ADD	R11,R11,#4		;And make space for border
		RSB	R7,R8,#4		;Loop stops when R7==0

		; --- Draw a line (loop body) ---

00prim_bottom	MOV	R0,#plot_MOVE+plot_ABSOLUTE
		MOV	R1,R9
		SWI	XOS_Plot		;Move to the left of the line
		MOV	R0,#plot_LINE+plot_FORE+plot_ABSOLUTE
		MOV	R1,R11
		SWI	XOS_Plot		;Draw the line

		; --- Check if we've done (loop termination) ---

		SUBS	R7,R7,R8		;Decrement the counter
		LDMLTFD	R13!,{R0-R2,R7-R11,PC}^	;Return to caller

		; --- Update coordinates (loop update) ---

		SUB	R9,R9,R8		;Move x coordinate back a bit
		SUB	R2,R2,R8		;Move y coordinate down a bit
		B	%00prim_bottom		;And do it all again

		LTORG

; --- prim_top ---
;
; Plots a horizontal strip in the current foreground colour along the top
; of an icon, with a little jagged bit on the right hand side.
;
; On entry:	R0 == pointer to icon block


prim_top	ROUT

		STMFD	R13!,{R0-R2,R7-R11,R14}	;Keep stack pointer moving

		; --- Load the variables we need ---

		LDMIA	R0,{R8-R11}		;Get useful coordinates out
		MOV	R9,R8			;Don't want y0
		LDR	R1,s_dx			;Get x pixel width
		LDR	R8,s_dy			;Get y pixel width
		LDR	R2,s_start		;Get start X offset

		; --- Initialise variables for first loop ---

		SUB	R9,R9,#4		;Make space for border
		SUB	R10,R10,R1		;Shift x1 past icon edge
		ADD	R10,R10,R2		;And add on the little bitty
		MOV	R2,R11			;Move y above the icon
		RSB	R7,R8,#4		;Loop stops when R7==0

		; --- Draw a line (loop body) ---

00prim_top	MOV	R0,#plot_MOVE+plot_ABSOLUTE
		MOV	R1,R9
		SWI	XOS_Plot		;Move to the left of the line
		MOV	R0,#plot_LINE+plot_FORE+plot_ABSOLUTE
		MOV	R1,R10
		SWI	XOS_Plot		;Draw the line

		; --- Check if we've done (loop termination) ---

		SUBS	R7,R7,R8		;Decrement the counter
		LDMLTFD	R13!,{R0-R2,R7-R11,PC}^	;Return to caller

		; --- Update coordinates (loop update) ---

		ADD	R10,R10,R8		;Move x coordinate on a bit
		ADD	R2,R2,R8		;Move y coordinate up a bit
		B	%00prim_top		;And do it all again

		LTORG

;----- Workspace layout -----------------------------------------------------

		^	0,R12

s_wstart	#	0

		; --- Graphics variables ---

s_dx		#	4			;Horizontal pixel size (OS)
s_dy		#	4			;Vertical pixel size (OS)
s_start		#	4			;Offset into corner for plot

		; --- Various other things ---

s_flags		#	4			;Various Sculptix flags
s_sarea		#	4			;The sprite area in tns icons

		; --- Colours ---

s_colours	#	4			;Colours for the 3D bits
s_shadeCols	#	4			;Colours for shaded 3D boxes
s_slabcol	#	1			;Slabbing in colour
s_rimcol	#	1			;Inner rim colour for type 2
		#	2			;Padding to align

		; --- Misc buffers ---

s_buffer	#	256			;A big buffer for things

s_wend		#	0

s_UNSLAB	EQU	(1<<0)			;We've unslabbed this poll
s_CHANNEL	EQU	(1<<1)			;Use channels, not ridges
s_FAINTCHAN	EQU	(1<<2)			;Draw channel boxes faintly

s_wsize		EQU	s_wend-s_wstart

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

		END
