;
; tmsMain.s
;
; The Straylight Tearoff Menu Segment (TMA)
;
;  1994 Straylight
;

;----- Don't forget to do these things --------------------------------------
;
; Do a good checksum

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

		GET	libs:header
		GET	libs:swis

;----- External Dependencies ------------------------------------------------

		GET	libs:tearSupt.sh.tearsupt

		GET	sapphire:errorBox
		GET	sapphire:help
		GET	sapphire:idle
		GET	sapphire:keyString
		GET	sapphire:msgs
		GET	sapphire:resspr
		GET	sapphire:sapphire
		GET	sapphire:screen
		GET	sapphire:string
		GET	sapphire:tspr
		GET	sapphire:wimp
		GET	sapphire:win

		; --- Internal header files ---

		GET	sapphire:_tms.tmsCreate
		GET	sapphire:_tms.tmsGlobal
		GET	sapphire:_tms.tmsGlue

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

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- tms__closeMenu ---
;
; On entry:	R2 == pointer to menu to close
;		R10 == pointer to the menu we are currently over
;
; On exit:	--
;
; Use:		Closes the menu structure pointed to, and destroys it

		EXPORT	tms__closeMenu
tms__closeMenu	ROUT

		CMP	R2,#0			;Is there menu?
		MOVEQS	PC,R14			;No -- return

		STMFD	R13!,{R0-R4,R14}	;Stack some registers
		LDR	R14,tms__currDbox	;Get the current dbox
		CMP	R14,R2			;Is this what we are closing?
		BEQ	%20tms__closeMenu	;Yes -- close it then

		LDR	R0,[R2,#hPrevMenu]	;Get the previous menu
		CMP	R0,#0			;Is there one?
		BEQ	%03tms__closeMenu	;No -- skip this bit then
		CMP	R0,R10			;Are we over previous menu?
		BLNE	tms__deselect		;No -- deselect the item
		LDREQ	R1,[R0,#hFlags]		;Yes -- get its flags
		BICEQ	R1,R1,#hFlag__warned	;...clear the warned flag
		STREQ	R1,[R0,#hFlags]		;...store flags back again
		MOV	R0,#0			;A NULL pointer

		; --- Tell the previous menu that we have closed ---

		LDR	R1,[R2,#hFromItem]	;Get the item we are from
		CMP	R1,#0			;Is there one?
		STRNE	R0,[R1,#iSubMenu]	;Yes -- no submenu now

		; --- Update some globals ---

03		STR	R0,tms__prevLevel	;No previous level
		STR	R0,tms__orgTearoff	;No originating tearoff

		; --- Clear the previous field of torn menus ---

		LDR	R1,tms__tornoffs	;Get the head of the list
		CMP	R1,#0			;Are we at the end?
		BEQ	%05tms__closeMenu	;Yes -- jump
04		LDR	R4,[R1,#hPrevMenu]	;Get the 'previous' field
		CMP	R2,R4			;Does it point to this menu?
		STREQ	R0,[R1,#hPrevMenu]	;Yes -- make it NULL
		LDR	R1,[R1,#hNextTorn]	;Get the next torn menu
		CMP	R1,#0			;Are we at the end?
		BNE	%04tms__closeMenu	;No -- keep looking

		; --- If we are closing the current transient, do this ---

05		LDR	R0,tms__current		;Point to current transient
		CMP	R0,R2			;Are we closing it?
		BNE	%09tms__closeMenu	;No -- jump ahead
		MOV	R0,#0			;Yes -- A NULL pointer
		STR	R0,tms__current		;...no current any more
		BL	tearSupport_closed	;Stop tearoffsupt sending

		; --- If dbox came from this menu, do this ---

		LDR	R0,tms__dboxPrev	;Get dbox parent
		CMP	R0,R2			;Are we closing it?
		MOVEQ	R0,#0			;Yes -- get a NULL word
		STREQ	R0,tms__dboxPrev	;And store that as the parent

		; --- Now close down the menu structure ---

09		LDR	R3,tms__oldHandle	;Get the old handle
10		MOV	R0,R2			;Destroy this menu
		LDR	R1,[R0,#hFlags]		;Get the flags word
		TST	R1,#hFlag__torn		;Is the menu torn off?
		LDMNEFD	R13!,{R0-R4,PC}^	;Yes -- return
		LDR	R2,[R0,#hSubMenu]	;Get the submenu pointer

		; --- Inform the owner about deletion ---

		STMFD	R13!,{R0-R2,R10,R12}	;Stack some registers
		ADD	R0,R0,#hHandler		;Point to the handler
		LDMIA	R0,{R2,R10,R12}		;Get values out
		MOV	R0,#mEvent_deleted	;The menu has been deleted
		MOV	R1,#0			;No item in question
		CMP	R2,#0			;Sanity check
		MOV	R14,PC			;Set up return address
		MOVNE	PC,R2			;Call the handler
		LDMFD	R13!,{R0-R2,R10,R12}	;Get registers back

		; --- Destroy the menu ---

		BL	tms__destroy		;Destroy the menu
		CMP	R0,R3			;Were we over this menu?
		BLEQ	tms__cleanUp		;Yes -- clean up then

		TST	R1,#hFlag__warned	;Has there been a warning
		LDMEQFD	R13!,{R0-R4,PC}^	;No -- return
		CMP	R2,#0			;Is there a submenu?
		LDMEQFD	R13!,{R0-R4,PC}^	;No -- Return to caller
		TST	R1,#hFlag__dbox		;Is this a dbox?
		BEQ	%10tms__closeMenu	;No -- keep going then

		; --- Its a window then ---

20		LDR	R0,tms__dboxPrev	;Get the previous menu
		CMP	R0,#0			;Is there one?
		BEQ	%25tms__closeMenu	;No -- skip this bit then
		CMP	R0,R10			;Are we over previous menu?
		BLNE	tms__deselect		;No -- deselect the item
		LDREQ	R1,[R0,#hFlags]		;Yes -- get its flags
		BICEQ	R1,R1,#hFlag__warned	;...clear the warned flag
		STREQ	R1,[R0,#hFlags]		;...store flags back again
		MOV	R0,#0			;A NULL pointer

		; --- Tell the previous menu that we have closed ---

		LDR	R1,tms__dboxPrev	;Get the item we are from
		CMP	R1,#0			;Is there one?
		STRNE	R0,[R1,#iSubMenu]	;Yes -- no submenu now

		; --- Now close the dialogue box ---

25		LDR	R2,tms__currDbox	;Load the dbox handle
		STR	R2,[R13,#-4]!		;Put handle on the stack
		MOV	R1,R13			;Point to it
		SWI	Wimp_CloseWindow	;And close the window
		ADD	R13,R13,#4		;Reclaim my stack
		MOV	R0,#0			;No current dbox
		STR	R0,tms__currDbox	;Make that clear
		LDR	R1,tms__current		;Get the current transient
		CMP	R1,#0			;Is this what we are closing?
		STREQ	R0,tms__current		;Yes -- no transient now then
		BLEQ	tearSupport_closed	;Stop the messages please
		LDR	R0,tms__flags		;Load the main flags
		ORR	R0,R0,#tFlag__doFake	;Do a fake NULL event
		STR	R0,tms__flags		;Store the flags back again
		LDMFD	R13!,{R0-R4,PC}^	;Return to caller

		LTORG

; --- tms__alarm1 ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		The first alarm to be called when waiting on an item.

tms__alarm1	ROUT
		STMFD	R13!,{R0-R2,R7,R8,R14}	;Stack registers nicley

		; --- Set up the next alarm ---

		MOV	R0,#161			;Read the CMOS ram
		MOV	R1,#23			;Read the delay time
		SWI	OS_Byte			;Read the delay then
		LDR	R0,tms__flags		;Load the tms flags
		ORR	R0,R0,#tFlag__nActive	;Menus are not active
		STR	R0,tms__flags		;Save the new flags
		ADD	R2,R2,R2,LSL #2		;Multiply delay by 5
		MOV	R2,R2,LSL #1		;And then by 2
		SWI	OS_ReadMonotonicTime	;Read the current time
		ADD	R0,R0,R2		;Set alarm for this time
		ADR	R1,tms__alarm2		;Call this handler
		ADR	R2,tms__alarm1		;Use this handle
		MOV	R3,R12			;And pass workspace in R12
		BL	idle_setAlarm		;Set the alarm

		; --- Open the sub menu ---

		LDR	R10,tms__alarmMenu	;Get the menu alarm is for
		LDR	R0,[R10,#hHandle]	;Load the window handle
		STR	R0,[R13,#-36]!		;Store in a block
		MOV	R1,R13			;Point to the block
		SWI	Wimp_GetWindowState	;Get the window state

		LDR	R7,tms__alarmItem	;Get the alarm item
		LDR	R8,tms__itemBlock	;Get item block address
		BL	tms__subMenu		;And open the menu

		ADD	R13,R13,#36		;Get the stack back
		LDMFD	R13!,{R0-R2,R7,R8,PC}^	;Return to caller

		LTORG

; --- tms__alarm2 ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Called as the second alarm, allowing selection of other
;		items in the menu.

tms__alarm2	ROUT

		STMFD	R13!,{R14}		;Stack some registers

		LDR	R14,tms__flags		;Load the tms flags
		BIC	R14,R14,#tFlag__nActive	;Menus are not active
		STR	R14,tms__flags		;Save the new flags

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

; --- tms__findItem ---
;
; On entry:	R0 == x coordinate (menu relative)
;		R1 == y coordinate (menu relative)
;		R10 == pointer to the menu
;
; On exit:	R8 == pointer to the item block
;		R7 == pointer to the actual item

tms__findItem	ROUT

		STMFD	R13!,{R0-R4,R14}	;Stack some registers
		MOV	R2,#0			;The y coordinate so far
		LDR	R3,[R10,#hFlags]	;Get the menu flags
		TST	R3,#hFlag__tearable	;Is there a tearoff bar?
		SUBNE	R2,R2,#tms__barHeight	;Yes -- move y position down
		LDR	R8,[R10,#hItems]	;Point to the items
00tms__findItem	ADD	R7,R8,#iHdrSize		;Point to the first item
		LDR	R4,[R8,#iNumber]	;Get the item count
01tms__findItem	CMP	R1,R2			;Compare y coordinates
		BGE	%90tms__findItem	;If greater -- no item found
		SUB	R2,R2,#44		;The bottom of the item
		CMP	R1,R2			;Compare y coordinates
		BGE	%10tms__findItem	;We've found it -- jump a bit
		LDR	R3,[R7,#iFlags]		;Get the item flags
		TST	R3,#iFlag__dotted	;Is there a dotted line?
		SUBNE	R2,R2,#24		;Subract that from y
		SUBS	R4,R4,#1		;Subtract the item count
		ADDNE	R7,R7,#iItemSize	;If some left, point to them
		BNE	%01tms__findItem	;...and try them
		LDR	R8,[R8,#iItems]		;Point to the next batch
		CMP	R8,#0			;Are there any left
		BNE	%00tms__findItem	;Yes -- check them
		B	%90tms__findItem	;No -- return

		; --- We have found the item ---

10tms__findItem	LDR	R1,[R8,#iDefinition]	;Point to packed definition
		LDR	R0,[R8,#iNumber]	;Get the number of items
		SUBS	R0,R0,R4		;Get the index of item
		STR	R0,tms__itemIndex	;Store this index value
		BEQ	%15tms__findItem	;If we have found it -- jump
11tms__findItem	LDR	R2,[R1],#4		;Get the item flags
		TST	R2,#mFlag_indirect	;Is this item indirected?
		ADDNE	R1,R1,#4		;Yes -- skip the offset word
		BNE	%13tms__findItem	;And skip past the loop

		; --- Skip inline text string ---

12tms__findItem	LDRB	R14,[R1],#1		;Get a message string byte
		CMP	R14,#' '		;Is it a terminator?
		BGE	%12tms__findItem	;No -- get another one
		ADD	R1,R1,#3		;Add 3
		BIC	R1,R1,#3		;And word align the pointer

		; --- Skip over shortcut word ---

13tms__findItem	TST	R2,#mFlag_shortcut	;It there a shortcut?
		TSTEQ	R2,#mFlag_iShortcut	;Even an indirected one?
		ADDNE	R1,R1,#4		;Yes -- skip over value

		; --- Now skip other optional blocks ---

		SKPITEM	R2,R1			;Skip this item
		SUBS	R0,R0,#1		;Decrement my count
		BGT	%11tms__findItem	;Keep trying if some left
15tms__findItem	STR	R1,tms__itemOver	;Store this pointer
		STR	R8,tms__itemBlock	;And this one too
		LDMFD	R13!,{R0-R4,PC}^	;And return to caller

		; --- The pointer wasn't over an item ---

90tms__findItem	MOV	R8,#0			;No item block found
		MOV	R7,#0			;No item found either
		LDMFD	R13!,{R0-R4,PC}^	;Return now

		LTORG

; --- tms__updateItem ---
;
; On entry:	R7 == pointer to the item to highlight
;		R10 == pointer to the menu
;
; On exit:	--
;
; Use:		Forces an update of the textual part of an item.

		EXPORT	tms__updateItem
tms__updateItem	ROUT

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

		SUB	R13,R13,#44		;Get a redraw block
		LDR	R4,[R7,#iyCoord]	;Get the y coordinate
		LDR	R11,[R7,#iFlags]	;Get the item flags

		LDR	R0,[R10,#hHandle]	;Get the window handle
		MOV	R1,#24			;x0
		LDR	R3,[R10,#hTotWidth]	;Get the total width
		ADD	R3,R3,#24		;x1
		SUB	R2,R4,#44		;y0
		STMIA	R13,{R0-R4}		;Fill in the block
		MOV	R1,R13			;Point to it
		SUB	R13,R13,#32		;Get another block
		SWI	Wimp_UpdateWindow	;Start the redraw
00		CMP	R0,#0			;More to do?
		ADDEQ	R13,R13,#(44+32)	;Get the stack back
		LDMEQFD	R13!,{R0-R4,R11,PC}^	;No -- return
		BL	tms__redrawText		;Perform the redrawing
		BL	tms__redrawSprite	;.,.,.,.,
		BL	tms__redrawKey		;...
		SWI	Wimp_GetRectangle	;Get another rectangle
		B	%00tms__updateItem	;And keep redrawing

		LTORG

; --- tms__highlight ---
;
; On entry:	R2 == pointer to item to highlight
;		R10 == pointer to the menu for these items
;
; On exit:	--
;
; Use:		Highlights the item pointed to on entry

tms__highlight	ROUT

		STMFD	R13!,{R0,R7,R14}	;Stack some registers
		LDR	R0,[R10,#hSelected]	;Get the selected item
		CMP	R2,R0			;Are they the same
		STMEQFD	R13!,{R0-R4,R7,PC}^	;Yes -- return
		MOV	R7,R2			;Point to the item
		STR	R7,[R10,#hSelected]	;This is now selected item
		LDR	R0,[R7,#iFlags]		;Get the item flags
		TST	R0,#iFlag__shaded	;Is the item shaded?
		BLEQ	tms__updateItem		;No -- update it
		LDMFD	R13!,{R0,R7,PC}^	;And return

		LTORG

; --- tms__unHighlight ---
;
; On entry:	R2 == pointer to item to un-highlight
;		R10 == pointer to the menu for these items
;
; On exit:	--
;
; Use:		un-highlights the item pointed to on entry

tms__unHighlight ROUT

		STMFD	R13!,{R0,R7,R14}	;Stack some registers
		LDR	R0,[R10,#hSelected]	;Get the selected item
		CMP	R2,R0			;Are they the same?
		LDMNEFD	R13!,{R0,R7,PC}^	;No -- return
		MOV	R7,R2			;Point to the item
		MOV	R0,#0			;No selected item
		STR	R0,[R10,#hSelected]	;Store the NULL pointer
		LDR	R0,[R7,#iFlags]		;Get the item flags
		TST	R0,#iFlag__shaded	;Is the item shaded?
		BLEQ	tms__updateItem		;No -- update it
		LDMFD	R13!,{R0,R7,PC}^	;And return

		LTORG

; --- tms__deselect ---
;
; On entry:	R0 == pointer to the menu
;
; On exit:	--
;
; Use:		Deselects the highlighted item in the given menu

tms__deselect	ROUT

		STMFD	R13!,{R2,R10,R14}	;Stack some registers
		LDR	R2,[R0,#hSelected]	;Point to the selected item
		CMP	R2,#0			;Is there one?
		LDMEQFD	R13!,{R2,R10,PC}^	;No -- return then

		MOV	R10,R0			;We need menu in R10
		BL	tms__unHighlight	;Unhighlight it then
		LDR	R14,[R0,#hFlags]	;Get the flags word
		BIC	R14,R14,#hFlag__warned	;We are no longer warned
		STR	R14,[R0,#hFlags]	;Store back modified flags
		LDMFD	R13!,{R2,R10,PC}^	;Return to caller

		LTORG

; --- tmsh__subWaiting ---
;
; On entry:	--
;
; On exit:	CS if we're waiting for a submenu, CC otherwise
;
; Use:		Informs transWin if a submenu is expected.

		EXPORT	tmsh__subWaiting
tmsh__subWaiting ROUT

		STMFD	R13!,{R12,R14}		;Save some registers
		WSPACE	tms__wSpace		;Load my workspace address
		LDR	R14,tms__flags		;Load the flags word
		TST	R14,#tFlag__subWait	;Are we waiting for a submenu
		LDMFD	R13!,{R12,R14}		;Unstack the registers
		ORRNES	PC,R14,#C_flag		;Yes -- return CS then
		BICEQS	PC,R14,#C_flag		;No -- return CC then

		LTORG

; --- tmsh__openSub ---
;
; On entry:	R0 == window handle to open
;
; On exit:	--
;
; Use:		Opens the given window as a submenu from a tms menu.

		EXPORT	tmsh__openSub
tmsh__openSub	ROUT

		STMFD	R13!,{R0-R3,R12,R14}	;Save registers
		WSPACE	tms__wSpace		;Load my workspace address
		STR	R0,[R13,#-36]!		;Get a block
		LDR	R1,tms__currItem	;Point to the current item
		STR	R0,[R1,#iDbox]		;Store the window handle
		LDR	R14,[R1,#iFlags]	;Load the flags word
		ORR	R14,R14,#iFlag__dbox	;Say this is a dbox
		STR	R14,[R1,#iFlags]	;Save the flags back
		STR	R0,tms__currDbox	;Store it here too
		LDR	R1,tms__orgTearoff	;Load the originating tearoff
		STR	R0,[R1,#hDbox]		;Store the window handle
		LDR	R14,[R1,#hFlags]	;Load the flags word
		ORR	R14,R14,#hFlag__dbox	;Say this is a dbox
		STR	R14,[R1,#hFlags]	;Save the flags back
		STR	R0,[R1,#hSubMenu]	;Store as submenu
		STR	R1,tms__dboxPrev	;This is menu dbox came from

		LDR	R14,tms__current	;Load the current transient
		CMP	R14,#0			;Is there one?
		BLEQ	wimp_taskHandle		;No -- get task handle	
		BLEQ	tearSupport_opened	;...start tearSupt then
		
		MOV	R1,R13			;Point to it
		SWI	Wimp_GetWindowState	;Get the window state
		LDMIB	R1,{R0-R3}		;Get the current coords
		SUB	R2,R2,R0		;Get the current width
		SUB	R1,R3,R1		;And its height
		ADR	R0,tms__coords		;Get coords to open at
		LDMIA	R0,{R0,R3}		;Load some coords then
		SUB	R1,R3,R1		;Calculate y0 coord
		ADD	R2,R0,R2		;And then x1
		STMIB	R13,{R0-R3}		;Store them back nicely
		MOV	R0,#-1			;Open at the front please
		STR	R0,[R13,#28]		;Store this in the block
		MOV	R1,R13			;Point back to the block
		BL	tspr_adjustBox		;Fit on screen properly
		SWI	Wimp_OpenWindow		;Open the window
		ADD	R13,R13,#36		;Restore stack
		LDMFD	R13!,{R0-R3,R12,PC}^	;Return to caller

		LTORG

; --- tms__subMenu ---
;
; On entry:	R1 == pointer to a window state for the menu
;		R7 == pointer to the item
;		R8 == pointer to item header block
;		R10 == pointer to the menu
;		R12 == workspace pointer
;
; On exit:	--
;
; Use:		Opens the sub menu correctly for the given item.

tms__subMenu	ROUT
		STMFD	R13!,{R0-R6,R14}	;Stack some registers

		; --- Store the coords to open next menu ---

		LDR	R4,[R1,#12]		;Get the x1 coordinate
		LDR	R5,[R1,#16]		;...and y1
		ADD	R4,R4,#2		;Correct x1 a bit
		LDR	R6,[R7,#iyCoord]	;Get the y coord of item
		ADD	R5,R5,R6		;Calculate next y to open at
		LDR	R6,[R1,#24]		;Don't forget scroll offset
		SUB	R5,R5,R6		;No siree
		ADR	R6,tms__coords		;Point to the coords
		STMIA	R6,{R4,R5}		;Store the coordinates

		; --- Warn the user/open the menu if we need to ---

		LDR	R6,[R10,#hFlags]	;Get the menu flags
		TST	R6,#hFlag__warned	;Have we already been warned?
		BNE	%35tms__subMenu		;Yes -- skip this bit
		ORR	R6,R6,#hFlag__warned	;We have been now
		STR	R6,[R10,#hFlags]	;Store back the flags
		LDR	R4,[R7,#iSubMenu]	;Get the submenu ptr
		CMP	R4,#0			;Is there one?
		BLNE	tms__locateMenu		;Yes -- try to find it
		CMP	R4,#0			;Has it been returned?
		BNE	%37tms__subMenu		;Yes -- bring it back to us
		STR	R6,[R10,#hFlags]	;Store the flags back
		TST	R6,#hFlag__torn		;Is menu torn off?
		STRNE	R10,tms__orgTearoff	;Yes -- remember this fact
		MOV	R5,#0			;A NULL pointer
		STR	R5,[R10,#hSubMenu]	;No current sub menu
		STR	R10,tms__prevLevel	;This is the previous menu
		LDR	R4,tms__itemOver	;Get packed defn for item
		LDR	R3,[R4],#4		;Get the flags word
		TST	R3,#mFlag_subWarn	;Do we require a warning?
		BNE	%33tms__subMenu		;Yes -- deal with it
		TST	R3,#mFlag_indirect	;Is this item indirected?
		ADDNE	R4,R4,#4		;Yes -- skip the offset word
		BNE	%32tms__subMenu		;And skip past the loop

		; --- Skip inline text string ---

31tms__subMenu	LDRB	R14,[R4],#1		;Get a message string byte
		CMP	R14,#' '		;Is it a terminator?
		BGE	%31tms__subMenu		;No -- get another one
		ADD	R4,R4,#3		;Add 3
		BIC	R4,R4,#3		;And word align the pointer

		; --- Now skip other optional blocks ---

32tms__subMenu	TST	R3,#mFlag_shortcut	;Is there a normal...
		TSTEQ	R3,#mFlag_iShortcut	;...or indirected shortcut?
		ADDNE	R4,R4,#4		;Yes -- skip over it
		SKIP	mFlag_shade,4,R3,R4
		SKIP	mFlag_iShade,4,R3,R4
		SKIP	mFlag_switch,4,R3,R4
		SKIP	mFlag_radio,8,R3,R4
		SKIP	mFlag_sprite,8,R3,R4

		; --- We are now pointing at submenu information ---

		LDR	R0,[R4,#0]		;Point to packed definition
		LDR	R1,[R4,#4]		;Point to the event handler
		LDR	R2,[R8,#iR10]		;Use R10 from previous item
		LDR	R3,[R8,#iR12]		;Use R12 from previous item
		BL	tms__searchForMenu	;Does this menu exist?
		BCS	%37tms__subMenu		;Yes -- get it back then
		BL	tms_create		;Create the menu
		STR	R0,[R7,#iSubMenu]	;Store this in item defn
		STR	R7,[R0,#hFromItem]	;We came from this item
		B	%40tms__subMenu		;Now deal with real clicks

		; --- The user requires a submenu warning ---

33tms__subMenu	LDR	R0,[R7,#iFlags]		;Get the item flags
		TST	R0,#iFlag__shaded	;Is the item shaded?
		TSTNE	R0,#iFlag__noWarn	;And we don't want warning?
		BNE	%40tms__subMenu		;Both -- return
		MOV	R0,#mEvent_arrow	;Send this event type
		LDR	R1,tms__itemIndex	;With this index
		STR	R7,tms__currItem	;Save the current item
		STR	R10,tms__orgTearoff	;The originating menu
		LDR	R14,tms__flags		;Load my current flags
		ORR	R14,R14,#tFlag__subWait	;We're waiting for a submenu
		STR	R14,tms__flags		;Save the flags back
		STMFD	R13!,{R10,R12}		;Save these registers
		ADD	R3,R8,#iHandler		;Point to the handler
		LDMIA	R3,{R3,R10,R12}		;Load the values
		ADDS	R0,R0,#0		;Clear the carry flag
		TEQ	R3,#0			;Sanity check
		MOV	R14,PC			;Set up the return address
		MOVNE	PC,R3			;Call the handler
		LDMFD	R13!,{R10,R12}		;Get my registers back
		LDR	R14,tms__flags		;Load my current flags
		BIC	R14,R14,#tFlag__subWait	;Stopped waiting for submenu
		STR	R14,tms__flags		;Save the flags back

		; --- Use must return with menu in R0, and carry set if
		;     menu is already open.

		STR	R0,[R7,#iSubMenu]	;Store this in item defn
		TEQ	R0,#0			;Has user returned NULL?
		STRNE	R7,[R0,#hFromItem]	;No -- we came from this item

		MOVCS	R4,R0			;If carry set...
		BCS	%37tms__subMenu		;...reposition given menu
		B	%40tms__subMenu		;Return to caller

		; --- There has already been a warning ---

35tms__subMenu	LDR	R4,[R10,#hSubMenu]	;Get the submenu pointer
		CMP	R4,#0			;Is there one?
		BEQ	%40tms__subMenu		;No -- return to caller
		LDR	R14,[R7,#iFlags]	;Get the item flags
		TST	R14,#iFlag__dbox	;Is this a dbox?
		BNE	%40tms__subMenu		;Yes -- return to caller
		LDR	R5,[R4,#hFlags]		;Get flags for sub menu
		TST	R5,#hFlag__warned	;Does submenu have submenu?
		BEQ	%36tms__subMenu		;No -- jump this bit
		LDR	R2,[R4,#hSubMenu]	;Point to the submenu's sub
		BL	tms__closeMenu		;Close it down
		MOV	R0,R4			;Point to the submenu
		BL	tms__deselect		;Deselect highlighted item

		; --- Reposition the sub menu ---

36tms__subMenu	SUB	R13,R13,#36		;Get me a block
		LDR	R5,[R4,#hHandle]	;Get the window handle
		STR	R5,[R13,#0]		;Store it in the block
		MOV	R1,R13			;Point to the block
		SWI	Wimp_GetWindowState	;Get the window state then
		LDR	R5,[R13,#12]		;Get x1
		LDR	R1,[R13,#4]		;Get x0
		SUB	R5,R5,R1		;Get the window width
		LDR	R1,tms__coords		;Get the x position to open
		STR	R1,[R13,#4]		;Store this in the block
		ADD	R5,R5,R1		;Get new x1 position
		STR	R5,[R13,#12]		;Store this too

		LDR	R5,[R13,#16]		;Get y1
		LDR	R1,[R13,#8]		;Get y0
		SUB	R5,R5,R1		;Get the window height
		LDR	R1,tms__coords+4	;Get the y position to open
		LDR	R3,[R4,#hFlags]		;Get the menu flags
		TST	R3,#hFlag__tearable	;Is there a bar?
		ADDNE	R1,R1,#tms__barHeight	;Yes -- add this on
		STR	R1,[R13,#16]		;Store this in the block
		SUB	R5,R1,R5		;Get new y0 position
		STR	R5,[R13,#8]		;Store this too
		MOV	R1,#-1			;Open in front
		STR	R1,[R13,#28]		;Store this value too
		MOV	R1,R13			;Point to the block
		BL	tspr_adjustBox		;Mangle to fit on screen
		SWI	Wimp_OpenWindow		;Open the window
		ADD	R13,R13,#36		;Get my stack back
		B	%40tms__subMenu		;Deal with real clicks

		; --- We need to 'bring back' a torn off menu ---

37tms__subMenu	MOV	R5,R10			;Remember R10 value
		MOV	R10,R4			;Point at found menu
		BL	tms__unTearMenu		;Un-tear it
		BL	tms__updateBar		;Update the tearoff bar
		MOV	R10,R5			;Get R10 value back
		STR	R4,[R7,#iSubMenu]	;Store submenu pointer back
		STR	R4,[R10,#hSubMenu]	;...in places good
		STR	R10,[R4,#hPrevMenu]	;Store previous menu
		STR	R7,[R4,#hFromItem]	;Item menu was from
		LDR	R5,tms__current		;Get the current menu
		CMP	R5,#0			;Is there one?
		STREQ	R4,tms__current		;No -- store this one then
		BLEQ	wimp_taskHandle		;...get the task handle
		BLEQ	tearSupport_opened	;...start tearoffsupt sending

		B	%36tms__subMenu		;And reposition it

40tms__subMenu	LDMFD	R13!,{R0-R6,PC}^	;Return to caller

		LTORG

; --- tms__buttons ---
;
; On entry:	R1 == pointer to mousepointer info block
;		R10 == pointer to the menu
;
; On exit:	--
;
; Use:		Called when a button event is detected on a menu, or
;		for NULL events (with button type 0)

tms__buttons	ROUT

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

		LDR	R14,tms__flags		;Get the current flags
		TST	R14,#tFlag__nActive	;Are we active?
		BNE	%99tms__buttons		;No -- return

		; --- First we deal with *any* button type ---

		MOV	R9,R1			;Keep a pointer to the block
		SUB	R13,R13,#36		;Get a small block
		MOV	R1,R13			;Point to the block
		LDR	R2,[R10,#hHandle]	;Get the window handle
		STR	R2,[R1,#0]		;Store the window handle
		SWI	Wimp_GetWindowState	;Get the window state
		MOV	R8,R1			;Remember this pointer
		LDR	R0,[R9,#0]		;Get the mouse x coord
		LDR	R2,[R8,#20]		;Get the scroll x position
		LDR	R3,[R8,#4]		;Get the x0 position
		ADD	R0,R0,R2		;Calculate workarea relative
		SUB	R0,R0,R3		;...x position
		LDR	R1,[R9,#4]		;Get the mouse y coord
		LDR	R2,[R8,#24]		;Get the scroll y position
		LDR	R3,[R8,#16]		;Get the y1 position
		ADD	R1,R1,R2		;Calculate workarea relative
		SUB	R1,R1,R3		;...y position
		STMIA	R9,{R0,R1}		;Store back updated positions
		LDR	R6,tms__flags		;Get the flags
		BL	tms__findItem		;Find the item we are over
		CMP	R8,#0			;Did we find an item
		BEQ	%12tms__buttons		;No -- jump ahead a bit
		LDR	R5,[R10,#hTotWidth]	;Get the width
		SUB	R5,R5,#24		;The right hand edge
		CMP	R0,R5			;Are we over it?

		; --- Complex condition time ---
		;
		; The following code should only be executed if:
		;    we're over a sub menu arrow AND we were
		;    not over it before
		;  OR
		;    we are not over a submenu arrow at all AND the
		;    item isn't the alarm item

		BIC	R6,R6,#tFlag__overArrow	;We are not over an arrow
		BLT	%10tms__buttons		;We cannot be over an arrow
		LDR	R5,tms__itemOver	;Get a pointer to the item
		LDR	R5,[R5,#0]		;Get the item flags
		MVN	R5,R5			;Invert them!
		AND	R5,R5,#mFlag_subMenu+mFlag_subWarn ; Keep these bits
		CMP	R5,#mFlag_subMenu+mFlag_subWarn ;Is there no arrow?

		; Here, EQ if we are not over an arrow, NE otherwise ---

		BEQ	%10tms__buttons		;Jump if we're not over arrow
		ORR	R6,R6,#tFlag__overArrow	;We are over an arrow
		STR	R6,tms__flags		;Store the flags
		LDR	R5,[R10,#hSelected]	;Get the selected item
		CMP	R7,R5			;Are they the same?
		BEQ	%30tms__buttons		;Yes -- jump this section

		; --- Well, the condition has been met at this point ---

10tms__buttons  STR	R6,tms__flags		;Store the flags
		LDR	R0,tms__alarmItem	;Get item alarm is for
		CMP	R0,R7			;Are they the same?
		BEQ	%30tms__buttons		;Yes -- jump this section
		LDR	R0,tms__alarmItem	;Get item alarm is for
		CMP	R0,R7			;Are they the same?
		BEQ	%30tms__buttons		;Yes -- jump this section

	;	LDR	R6,[R10,#hFlags]	;Get the menu flags
	;	TST	R6,#hFlag__tearable	;Is there a bar?
	;	BEQ	%11tms__buttons		;No -- jump ahead
	;	CMP	R1,#-tms__barHeight	;Is it in the bar
	;	BGE	%12tms__buttons		;Yes -- jump past this bit

		; --- Close the current RISCOS menu using tearoff support ---

11tms__buttons	STMFD	R13!,{R0-R1}		;Stack these now
		MOV	R0,#1			;Switch off SWI vectoring
		BL	tearSupport_switch	;Yes siree bob matey
		MOV	R1,#-1			;No menu please Mr. Wimp
		SWI	XWimp_CreateMenu	;La de dar do
		MOVVC	R0,#0			;Switch vectoring back on
		BLVC	tearSupport_switch	;Please
		LDMFD	R13!,{R0-R1}		;Get coords back back

		; --- If the menu is torn off, then close transient ---

		LDR	R5,[R10,#hFlags]	;Get the menu flags
		TST	R5,#hFlag__torn		;Has menu been torn off?
		BEQ	%12tms__buttons		;No -- skip ahead
		LDR	R2,tms__current		;Point to current transient
		CMP	R2,#0			;Is there one?
		LDREQ	R2,tms__currDbox	;No -- load dbox handle
		BL	tms__closeMenu		;Close the menu
		B	%13tms__buttons		;Skip the next bit

		; --- If there is already a menu open from here, close it ---

12tms__buttons	LDR	R5,[R10,#hFlags]	;Get the menu flags
		TST	R5,#hFlag__warned	;Has there been a warning?
		BEQ	%13tms__buttons		;No -- skip ahead
		LDR	R2,[R10,#hSubMenu]	;Get its submenu
		BL	tms__closeMenu		;Close the submenu
		BIC	R5,R5,#hFlag__dbox	;There is no dbox now
		STR	R5,[R10,#hFlags]	;Store the flags back
		CMP	R7,#0			;Is there an item?
		LDRNE	R6,[R7,#iFlags]		;Yes -- get the menu flags
		BICNE	R6,R6,#iFlag__dbox      ;...not a dbox
		STRNE	R6,[R7,#iFlags]		;...store flags back again
		MOV	R2,#0			;A NULL pointer
		STR	R2,[R10,#hSubMenu]	;No sub menu any more

		; --- Cause a fake event if we just closed a dbox ---

13tms__buttons	LDR	R0,tms__flags		;Load the flags word
		TST	R0,#tFlag__doFake	;Should we do a fake?
		BNE	%90tms__buttons		;Yes -- return to caller

		; --- Do the selecting/deselecting ---

		LDR	R5,[R10,#hSelected]	;Get the selected item
		CMP	R7,R5			;Are they the same?
		BEQ	%15tms__buttons		;Yes -- do nothing here
		CMP	R5,#0			;Is there a selected item
		BEQ	%14tms__buttons		;No -- skipitty jump
		LDR	R6,[R5,#iFlags]		;Get the flags for this item
		TST	R6,#iFlag__shaded	;Is it shaded?
		BNE	%14tms__buttons		;Yes -- skipitty jump
		MOV	R2,R5			;Unhighlight this item
		BL	tms__unHighlight	;Unhighlight it then
14tms__buttons	MOVS	R2,R7			;Point to the item
		BLNE	tms__highlight		;Yes -- highlight the item
		STR	R2,[R10,#hSelected]	;Store pointer to item
		ADRL	R0,tms__alarm1		;Remove alarms with this hnd
		BL	idle_removeAllAlarms	;Do it then
		MOV	R0,#-1			;No alarm set
		STR	R0,tms__alarmItem	;So say that

		; --- Do we need to set an alarm? ---

15tms__buttons	CMP	R7,#0			;Is there an item?
		BEQ	%20tms__buttons		;No -- don't set an alarm
		LDR	R6,[R7,#iFlags]		;Get the flags word
		TST	R6,#iFlag__arrow	;Are we over an arrow?
		BEQ	%20tms__buttons		;No -- don't set an alarm

		LDR	R0,tms__alarmItem	;Get the current alarm item
		CMP	R0,#-1			;Is there one?
		BNE	%20tms__buttons		;Yes -- skip ahead
		BL	wimp_version		;Get the wimp version
		CMP	R0,#300			;Higher than RISC OS 2?
		BLT	%20tms__buttons		;No -- don't do this then

		; --- Check with the CMOS setting ---

		MOV	R0,#161			;Read CMOS
		MOV	R1,#197			;The wimp flags
		SWI	XOS_Byte		;Read them then
		TST	R2,#&80			;Is the bit set?
		BEQ	%20tms__buttons		;No -- don't do this then
		MOV	R0,#161			;Read CMOS
		MOV	R1,#23			;Read the delay time
		SWI	XOS_Byte		;Read it then
		CMP	R2,#0			;Is there a sensible time?
		BEQ	%20tms__buttons		;No -- don't do this then

		; --- Right, set the alarm ---

		STR	R10,tms__alarmMenu	;Alarm is for this menu
		STR	R7,tms__alarmItem	;And for this item
		ADD	R1,R2,R2,LSL #2		;Multiply time by 5
		MOV	R1,R1,LSL #1		;And then by 2 (10 in all)
		SWI	OS_ReadMonotonicTime	;Read the current time
		ADD	R0,R0,R1		;Set alarm for this time
		ADRL	R1,tms__alarm1		;Point to handler function
		MOV	R2,R0			;Use that as the handle
		MOV	R3,R12			;Pass workspace in R12
		BL	idle_setAlarm		;And set the alarm

		; --- Correct some 'variables' ---

20tms__buttons	LDR	R6,[R10,#hFlags]	;Get the menu flags
		BIC	R6,R6,#hFlag__warned	;We haven't been warned
		BIC	R6,R6,#hFlag__dbox	;And there is not a dbox
		STR	R6,[R10,#hFlags]	;Store the flags back again
		CMP	R7,#0			;Is there an item?
		MOV	R6,#0			;A NULL pointer
		STR	R6,tms__prevLevel	;No previous level
		STR	R6,tms__orgTearoff	;No originating tearoff

		; --- Well, that lots over, no where near finished though ---

		; --- Are we over a sub menu arrow? ---

30tms__buttons	CMP	R7,#0			;Is there an item?
		BEQ	%40tms__buttons		;No -- deal with real clicks
		LDR	R6,tms__flags		;Get the flags word
		TST	R6,#tFlag__overArrow	;Are we over an arrow?
		BEQ	%40tms__buttons		;No -- skip this bit

		; --- The pointer is over an arrow ---

		MOV	R1,R13			;Point to the window state
		BL	tms__subMenu		;Open the sub menu

		; --- Deal with real buttons clicks ---

40tms__buttons	LDR	R2,[R9,#8]		;Get the button status
		CMP	R2,#0			;Was a button pressed?
		BEQ	%90tms__buttons		;No -- return

		; --- Was the click on the tearoff bar? ---

		LDR	R0,tms__flags		;Get the flags word
		TST	R2,#6			;Select or menu pressed?
		ORRNE	R0,R0,#tFlag__close	;Yes -- close the transient
		BICEQ	R0,R0,#tFlag__close	;No -- keep it open
		STR	R0,tms__flags		;Store the flags back
		LDMIA	R9,{R0,R1}		;Get the coordiantes
		LDR	R2,[R10,#hFlags]	;Get the menu flags
		TST	R2,#hFlag__tearable	;Is there a bar?
		BEQ	%50tms__buttons		;No -- branch ahead
		CMP	R1,#-tms__barHeight	;Did we click in the bar?
		BLT	%50tms__buttons		;No -- branch ahead
		CMP	R1,#-4			;The top of the icon
		BGT	%90tms__buttons		;Not in icon -- return
		CMP	R1,#-(tms__barHeight-4)	;The bottom level
		BLT	%90tms__buttons		;Not in icon -- return
		TST	R2,#hFlag__torn		;Has the menu been torn off
		BNE	%45tms__buttons		;Yes -- deal with that

		; --- Was the click in the tear icon? ---

		CMP	R0,#4			;The left hand side
		BLT	%90tms__buttons		;Not in icon -- return
		CMP	R0,#68			;The right hand side
		BGT	%90tms__buttons		;Not in icon -- return
		BL	tms__tearMenu		;Tear the menu off
		B	%90tms__buttons		;Return to caller

		; --- The menu is torn off -- what did we click in? ---

45tms__buttons  CMP	R0,#4			;The left hand side
		BLT	%90tms__buttons		;Not in icon -- return
		CMP	R0,#70			;The right hand side
		BLLE	tms__closeTornMenu	;Tear the menu off
		BLE	%90tms__buttons		;Return to caller

		; --- Was it in the fold icon ---

46tms__buttons	LDR	R2,[R10,#hTotWidth]	;The total menu width
		SUB	R2,R2,#60		;LHS of tear icon
		CMP	R0,R2			;Where did we click?
		BLT	%90tms__buttons		;Not in it, that's for sure
		ADD	R2,R2,#56		;RHS of tear icon
		CMP	R0,R2			;Where did we click?
		BGT	%90tms__buttons		;Not in it, that's for sure
		BL	tms__foldMenu		;Fold the menu then
		B	%90tms__buttons		;Return to caller

		; --- The click was on an item ---

50tms__buttons	CMP	R7,#0			;Is there an item here?
		BEQ	%90tms__buttons		;No -- return
		LDR	R0,[R7,#iFlags]		;Get the item flags
		TST	R0,#iFlag__shaded	;Is the item shaded
		BNE	%90tms__buttons		;Yes -- return then

		MOV	R3,#3			;Flash this many times
		MOV	R0,#19			;VSync
51tms__buttons	SWI	OS_Byte			;Wait for it
		SWI	OS_Byte			;Wait for it again
		MOV	R2,R7			;Point to the item
		BL	tms__unHighlight	;Unhighlight item
		SWI	OS_Byte			;Wait for VSync
		SWI	OS_Byte			;Wait for it again
		MOV	R2,R7			;Point to the item
		BL	tms__highlight		;Highlight item
		SUBS	R3,R3,#1		;Decrement counter
		BNE	%51tms__buttons		;Flash more times if needed

		; --- Close the menu structure if we need to ---

		LDR	R0,tms__flags		;Get the flags word
		TST	R0,#tFlag__close	;Should I close the menu?
		LDRNE	R2,tms__current		;Yes -- point to current menu
		BLNE	tms__closeMenu		;...and close the transient

		; --- Finally, report event to the user ---

		STMFD	R13!,{R10,R12}		;Save these registers
		MOV	R0,#mEvent_select	;Item has been selected
		LDR	R1,tms__itemIndex	;The items index
		ADD	R3,R8,#iHandler		;Point to the handler
		LDMIA	R3,{R3,R10,R12}		;Load the values
		ADDS	R0,R0,#0		;Clear the carry flag
		TEQ	R3,#0			;Sanity check
		MOV	R14,PC			;Set up the return address
		MOVNE	PC,R3			;Call the handler
		LDMFD	R13!,{R10,R12}		;Get my registers back

		BL	tms_recreate		;Recreate the existing menus

		; --- Return to the user ---

90tms__buttons	ADD	R13,R13,#36		;Reclaim my stack
99tms__buttons	LDMFD	R13!,{R0-R9,PC}^	;And return to caller

		LTORG

; --- tms__cleanUp ---
;
; On entry:	R0 == handle idle handler is called with (the menu)
;
; On exit:	--
;
; Use:		Called to clean up the system when the pointer has left
;		a menu.

		EXPORT	tms__cleanUp
tms__cleanUp	ROUT

		STMFD	R13!,{R0-R3,R14}	;Stack some registers
		MOV	R2,R0			;The R10 value
		ADRL	R1,tms__idleHandler	;The routine that is called
		MOV	R0,#0			;How frequently it was called
		MOV	R3,R12			;The R12 value passed
		BL	idle_removeHandler	;Remove the handler
		MOV	R0,#0			;No handler set up
		STR	R0,tms__oldHandle	;Store that fact
		ADRL	R0,tms__alarm1		;Remove alarms with this hnd
		BL	idle_removeAllAlarms	;Do it then
		MOV	R0,#-1			;No alarm set
		STR	R0,tms__alarmItem	;So say that
		BL	tms__alarm2		;Allow item selection

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

		LTORG


; --- tms__updateBar ---
;
; On entry:	R10 == pointer to the menu
;
; On exit:	--
;
; Use:		Update the tearoff bar of the given menu

tms__updateBar	ROUT

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

		SUB	R13,R13,#44		;Get me a block
		LDR	R0,[R10,#hHandle]	;Get the window handle
		MOV	R1,#0			;x0
		LDR	R3,[R10,#hTotWidth]	;Get the total width
		ADD	R3,R3,#48		;x1
		MOV	R2,#-tms__barHeight	;y0
		MOV	R4,#0			;y1
		STMIA	R13,{R0-R4}		;Fill in the block
		MOV	R1,R13			;Point to it
		MOV	R4,R2			;The y coordinate
		SUB	R13,R13,#32		;Get another block
		SWI	Wimp_UpdateWindow	;Start the redraw
00		CMP	R0,#0			;More to do?
		BEQ	%10tms__updateBar	;No -- return
		BL	tms__redrawBar		;Perform the redrawing
		SWI	Wimp_GetRectangle	;Get another rectangle
		B	%00tms__updateBar	;And keep redrawing

10		ADD	R13,R13,#(44+32)	;Get the stack back
		LDMFD	R13!,{R0-R4,PC}^	;Return to caller

		LTORG

; --- tms__tearMenu ---
;
; On entry:	R10 == pointer to menu to tear off
;
; On exit:	--
;
; Use:		Called when the user clicks on the tear icon

tms__tearMenu	ROUT

		STMFD	R13!,{R0-R2,R4,R14}	;Stack some registers
		LDR	R0,[R10,#hFlags]	;Get the menu flags
		ORR	R0,R0,#hFlag__torn	;The menu is now torn
		STR	R0,[R10,#hFlags]	;Store back the flags
		LDR	R0,[R10,#hPrevMenu]	;Get the previous menu
		CMP	R0,#0			;Is there one?
		BLNE	tms__deselect		;Yes -- deselect it

		; --- Start the drag operaton ---

		SUB	R13,R13,#28		;Get me a block
		LDR	R0,[R10,#hHandle]	;Get the window handle
		MOV	R1,#1			;Drag window position
		STMIA	R13,{R0,R1}		;Store them in the block
		MOV	R1,R13			;Point to the block
		SWI	Wimp_DragBox		;Start the drag
		ADD	R13,R13,#28		;Get the stack back

		; --- Alter the icons on the bar ---

		BL	tms__updateBar		;Update the bar

		; --- Add the menu to the list of torn menus ---

10tms__tearMenu	LDR	R0,tms__tornoffs	;Get the list head
		STR	R0,[R10,#hNextTorn]	;Put pointer in menu header
		STR	R10,tms__tornoffs	;Store this as the head
		LDR	R0,tms__current		;Get the current transient
		CMP	R0,R10			;Are we tearing it?
		BNE	%15tms__tearMenu	;No -- jump ahead
		MOV	R0,#0			;A NULL pointer
		STR	R0,tms__current		;No current transient
		BL	tearSupport_closed	;TearoffSupt_Closed

		; --- Close the transient if we need to ---

15tms__tearMenu	LDR	R0,tms__flags		;Get the program flags
		TST	R0,#tFlag__close	;Do we close transients?
		LDRNE	R2,tms__current		;Point to current transient
		BLNE	tms__closeMenu		;And close the transient

		; --- Return to the caller ---

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

		LTORG

; --- tms__unTearMenu ---
;
; On entry:	R10 == pointer to menu to untear
;
; On exit:	--
;
; Use:		'Un-tears' the give menu. Note that the bar is NOT redrawn

tms__unTearMenu	ROUT

		STMFD	R13!,{R0-R2,R14}	;Stack some registers
		LDR	R0,tms__tornoffs	;Get the torn off list
		MOV	R1,#0			;The previous menu
00		CMP	R0,R10			;Is this the menu
		BEQ	%10tms__unTearMenu	;Yes -- deal with it
		MOV	R1,R0			;This is now the previous
		LDR	R0,[R0,#hNextTorn]	;Get the next in the list
		CMP	R0,#0			;Is there one?
		BNE	%00tms__unTearMenu	;Yes -- deal with it

		; --- Cant find it, werg! ---

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

		; -- Right, we've found it now ---

10		LDR	R2,[R0,#hNextTorn]	;Get the pointer to next
		CMP	R1,#0			;Is it the first in list?
		STREQ	R2,tms__tornoffs	;Yes -- store next as head
		STRNE	R2,[R1,#hNextTorn]	;No -- store in prev ptr
		LDR	R0,[R10,#hFlags]	;Get the menu flags
		BIC	R0,R0,#hFlag__torn	;We are not torn now
		STR	R0,[R10,#hFlags]	;Store the flags back
		TST	R0,#hFlag__warned	;Have we been warned?
		BEQ	%15tms__unTearMenu	;No -- jump ahead
		LDR	R2,[R10,#hSubMenu]	;Get the sub menu
		BL	tms__closeMenu		;Close it
		MOV	R0,R10			;Point to my menu
		BL	tms__deselect		;Deselect it

		; --- Unfold the menu if we need to ---

15		LDR	R0,[R10,#hFlags]	;Get the menu flags
		TST	R0,#hFlag__folded	;Is the menu folded
		BLNE	tms__foldMenu		;Yes -- unfold it

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

		LTORG

; --- tms__closeTornMenu ---
;
; On entry:	R10 == pointer to torn off menu to close
;
; On exit:	--
;
; Use:		Closes a torn off menu.

tms__closeTornMenu ROUT

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

		BL	tms__unTearMenu		;'Un-tear' the menu
		MOV	R2,R10			;Close this menu
		BL	tms__closeMenu		;Now close the menu
		LDR	R0,tms__flags		;Get the program flags
		TST	R0,#tFlag__close	;Do we close transients?
		LDRNE	R2,tms__current		;Point to current transient
		BLNE	tms__closeMenu		;And close the transient

		; --- Return to the caller ---

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

		LTORG

; --- tms__locateMenu ---
;
; On entry:	R4 == pointer to menu to find
;
; On exit:	R4 preserved if it exists, 0 otherwise
;
; Use:		Attempt to find the given menu in the torn off
;		list. It is returned in R4 if it is found

tms__locateMenu	ROUT

		STMFD	R13!,{R14}		;Stack some registers
		LDR	R14,tms__tornoffs	;Get the torn off list
		CMP	R14,#0			;Are there any
		BEQ	%99tms__locateMenu	;No -- return failure
00		CMP	R14,R4			;Have we found it?
		LDMEQFD	R13!,{PC}^		;Yes -- return
		LDR	R14,[R14,#hNextTorn]	;Get the next in the list
		CMP	R14,#0			;Is there one
		BNE	%00tms__locateMenu	;Yes -- try it

		; --- We didn't find it ---

99		MOV	R4,#0			;Return failure
		LDMFD	R13!,{PC}^		;Return to caller

		LTORG

; --- tms__searchForMenu ---
;
; On entry:	R0 == pointer to packed definition
;		R1 == pointer to event handler
;		R2 == R10 value passed to handler
;		R3 == R12 value passed to handler
;
; On exit:	C set and R4 points to menu if found, C clear otherwise
;
; Use:		Searches the tornoff menus for a menu with characteristics
;		matching the search required

tms__searchForMenu ROUT

		BIC	R14,R14,#C_flag		;We haven't found it
		STMFD	R13!,{R5-R7,R12,R14}	;Stack some registers
		WSPACE	tms__wSpace		;Locate my workspace
		LDR	R14,tms__tornoffs	;Get the torn off list
		CMP	R14,#0			;Are there any
		BEQ	%99tms__searchForMenu	;No -- return failure
00		ADD	R4,R14,#hHandler	;Point to useful values
		LDMIA	R4,{R4-R7}		;Get them out
		CMP	R0,R7			;Packed definition the same?
		CMPEQ	R1,R4			;...and the handler?
		CMPEQ	R2,R5			;...and R10 value?
		CMPEQ	R3,R6			;...and R12 value?
		MOVEQ	R4,R14			;We've found it
		LDMEQFD	R13!,{R5-R7,R12,R14}	;Get back registers
		ORREQS	PC,R14,#C_flag		;And return happy
		LDR	R14,[R14,#hNextTorn]	;Get the next in the list
		CMP	R14,#0			;Is there one
		BNE	%00tms__searchForMenu	;Yes -- try it

		; --- We didn't find it ---

99		MOV	R4,#0			;Return failure
		LDMFD	R13!,{R5-R7,R12,PC}^	;Return to caller

		LTORG

; --- tms_closeMenu ---
;
; On entry:	R0 == pointer to menu definition
; 		R1 == pointer to event handler
;		R2 == R10 value to look for
;		R3 == R12 value to look for
;
; On exit:	--
;
; Use:		Searches through the menus which have been torn off for a
;		menu which matches the specifications given, and closes
;		it if it is found.

		EXPORT	tms_closeMenu
tms_closeMenu	ROUT

		STMFD	R13!,{R4,R10,R12,R14}	;Stack registers
		WSPACE	tms__wSpace		;Locate my workspace
		BL	tms__searchForMenu	;Try to find the menu
		MOVCS	R10,R4			;Found it -- put in R10
		BLCS	tms__closeTornMenu	;And close it
		LDMFD	R13!,{R4,R10,R12,PC}^	;Return to caller
		
		LTORG

; --- tms_closeAll ---
;
; On entry:	R0 == R10 value to search for
;
; On exit:	--
;
; Use:		Closes all the torn off menus with the given r10
;		value.

		EXPORT	tms_closeAll
tms_closeAll	ROUT

		STMFD	R13!,{R10,R12,R14}	;Stack registers
		WSPACE	tms__wSpace		;Locate my workspace
		LDR	R10,tms__tornoffs	;Get the torn off list
		CMP	R10,#0			;Are there any
		BEQ	%90tms_closeAll		;No -- return
00		LDR	R14,[R10,#hR10]		;Get the R10 value
		CMP	R0,R14			;Is R10 value the same?
		BLEQ	tms__closeTornMenu	;Yes -- close that menu
		LDR	R10,[R10,#hNextTorn]	;Get the next in the list
		CMP	R10,#0			;Is there one
		BNE	%00tms_closeAll		;Yes -- try it

90tms_closeAll	LDMFD	R13!,{R10,R12,PC}^	;Return to caller

		LTORG	

; --- tms__foldMenu ---
;
; On entry:	R10 == pointer to menu to fold
;
; On exit:	--
;
; Use:		Folds or unfolds the menu, as appropriate

tms__foldMenu	ROUT

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

		; --- Get the window state ---

		SUB	R13,R13,#88		;Get me a block
		LDR	R0,[R10,#hHandle]	;Get the window handle
		STR	R0,[R13,#0]		;Store it in the block
		MOV	R1,R13			;Point to the block
		SWI	Wimp_GetWindowState	;Get the window state

		; --- First, close the current transient menu ---

		LDR	R0,tms__flags		;Get the program flags
		TST	R0,#tFlag__close	;Do we close transients?
		LDRNE	R2,tms__current		;Point to current transient
		BLNE	tms__closeMenu		;And close the transient

		LDR	R0,[R10,#hFlags]	;Get the menu flags
		EOR	R0,R0,#hFlag__folded	;Toggle the foldedness
		STR	R0,[R10,#hFlags]	;Store back modified flags
		TST	R0,#hFlag__folded	;Test that bit now
		BEQ	%50tms__foldMenu	;No longer folded -- jump

		; --- We must now fold up the menu ---

		TST	R0,#hFlag__scrBar	;Is there a scroll bar?
		BEQ	%25tms__foldMenu	;No -- do quick fold

		ADD	R1,R10,#hHandle		;Point to the window handle
		SWI	Wimp_CloseWindow	;Close the window
		SWI	Wimp_DeleteWindow	;And then delete it
		LDR	R0,[R10,#hHandle]	;The window handle
		ADRL	R1,tms__eventHandler	;Point to the handler
		MOV	R2,R10			;The handle passed
		MOV	R3,R12			;Workspace passed in R3
		BL	win_removeEventHandler	;Remove the event handler
		LDR	R1,tms__oldHandle	;Get the old handle
		CMP	R0,R1			;Are they the same?
		BLEQ	tms__cleanUp		;Yes -- clean up a bit
		LDR	R0,[R10,#hHeight]	;Get the menu height
		BL	tms__createWindow	;Create the window
		MOVVS	R1,#1			;On error -- show 1 icon
		BLVS	errorBox		;...display the error
		BVS	%99tms__foldMenu	;...and return to caller
		ADRL	R1,tms__eventHandler	;Point to the handler
		MOV	R2,R10			;The handle passed
		MOV	R3,R12			;Workspace passed in R3
		BL	win_eventHandler	;Remove the event handler
		MOV	R1,R13			;Point to window state
		STR	R0,[R1,#0]		;Store in the block
		LDR	R4,[R1,#16]		;Get y1
		SUB	R0,R4,#24		;No -- y0-y1-actual height
		STR	R0,[R1,#8]		;Store new y0
		BL	tspr_adjustBox		;Mangle to fit on the screen
		SWI	Wimp_OpenWindow		;Open the window
		B	%99tms__foldMenu	;Return to caller

		; --- The menu has no scrollbar ---

25tms__foldMenu	MOV	R1,R13			;Point to state
		LDR	R0,[R1,#16]		;Get y1
		SUB	R0,R0,#24		;New y0 value
		STR	R0,[R1,#8]		;Store it in the block
		SWI	Wimp_OpenWindow		;Open the window
		B	%99tms__foldMenu	;And return

		; --- The menu must be 'un-folded' ---

50tms__foldMenu	BL	screen_getInfo		;Get the screen information
		LDR	R1,[R0,#screen_height]	;Get the screen height
		LDR	R2,[R10,#hMaxHeight]	;Get the maximum menu height
		LDR	R3,[R10,#hHeight]	;And the actual menu height

		; --- We add a scroll bar if h>maxH or h+50>screen height ---

		CMP	R2,#0			;Is there a maximum height?
		BEQ	%55tms__foldMenu	;No try next condition
		CMP	R3,R2			;Is height > maxHeight?
		BGT	%60tms__foldMenu	;Yes -- unfold with scrll bar
55tms__foldMenu	ADD	R3,R3,#50		;Add a little to the height
		CMP	R3,R1			;Compare to the screen height
		BLE	%75tms__foldMenu	;Unfold without scroll bar

		; --- Unfold with a scroll bar ---

60tms__foldMenu	ADD	R1,R10,#hHandle		;Point to the window handle
		SWI	Wimp_CloseWindow	;Close the window
		SWI	Wimp_DeleteWindow	;And then delete it
		LDR	R0,[R10,#hHandle]	;The window handle
		ADRL	R1,tms__eventHandler	;Point to the handler
		MOV	R2,R10			;The handle passed
		MOV	R3,R12			;Workspace passed in R3
		BL	win_removeEventHandler	;Remove the event handler
		LDR	R1,tms__oldHandle	;Get the old handle
		CMP	R0,R1			;Are they the same?
		BLEQ	tms__cleanUp		;Yes -- clean up a bit
		LDR	R0,[R10,#hHeight]	;Get the menu height
		BL	tms__createWindow	;Create the window
		MOVVS	R1,#1			;On error -- show 1 icon
		BLVS	errorBox		;...display the error
		BVS	%99tms__foldMenu	;...and return to caller
		ADRL	R1,tms__eventHandler	;Point to the handler
		MOV	R2,R10			;The handle passed
		MOV	R3,R12			;Workspace passed in R3
		BL	win_eventHandler	;Remove the event handler
		MOV	R1,R13			;Point to window state
		STR	R0,[R1,#0]		;Store in the block
		LDR	R4,[R1,#16]		;Get y1
		LDR	R3,[R10,#hHeight]	;And actual height
		LDR	R2,[R10,#hMaxHeight]	;Get the maximum height
		CMP	R2,#0			;Is there one?
		SUBNE	R0,R4,R2		;Yes -- y0=y1-maxHeight
		SUBEQ	R0,R4,R3		;No -- y0-y1-actual height
		STR	R0,[R1,#8]		;Store new y0
		BL	tspr_adjustBox		;Mangle to fit on the screen
		MOV	R14,#-1			;To open at the front
		STR	R14,[R1,#28]		;We alter the behind value
		SWI	Wimp_OpenWindow		;Open the window
		B	%99tms__foldMenu	;Return to caller

		; --- We must unfold without a scroll bar ---

75tms__foldMenu	MOV	R1,R13			;Point to state
		LDR	R0,[R1,#16]		;Get y1
		LDR	R2,[R10,#hHeight]	;Get actual height
		SUB	R0,R0,R2		;New y0 value
		STR	R0,[R1,#8]		;Store it in the block	
		MOV	R14,#-1			;To open at the front
		STR	R14,[R1,#28]		;We alter the behind value
		SWI	Wimp_OpenWindow		;Open the window

99tms__foldMenu	ADD	R13,R13,#88		;Get the block back
		LDMFD	R13!,{R0-R5,PC}^	;Return to caller

; --- tms__ensureWindowOK ---
;
; On entry:	R1 == pointer to window state
;		R10 == ponter to the menu
;
; On exit:	--
;
; Use:		Called after a mode change, to make sure that the menu still
;		fits on the screen, and to make appropriate changes
;		if the font has changed, etc.

tms__ensureWindowOK ROUT

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

		LDR	R0,[R10,#hFlags]	;Get the menu flags
		TST	R0,#hFlag__folded	;Is the menu folded
		BNE	%98tms__ensureWindowOK	;Yes -- return
		BL	screen_getInfo		;Get the screen info
		LDR	R4,[R0,#screen_height]	;Get screen height
		LDR	R3,[R10,#hHeight]	;Get menu height
		ADD	R3,R3,#50		;Add 50 for luck
		LDR	R2,[R10,#hFlags]	;Get the menu flags

		; --- Check to see if we should remove scroll bar ---

		TST	R2,#hFlag__scrBar	;Is there a scroll bar
		BEQ	%40tms__ensureWindowOK	;No -- jump ahead
		CMP	R3,R4			;Is actual < screen height?
		BGT	%40tms__ensureWindowOK	;No -- jump ahead
		LDR	R14,[R10,#hMaxHeight]	;Get max height
		CMP	R14,#0			;Is there one?
		BEQ	%10tms__ensureWindowOK	;No -- remove scroll bar
		CMP	R3,R14			;Is actual < max height?
		BGT	%40tms__ensureWindowOK	;No -- jump ahead

		; --- Remove the scroll bar then ---

10		BL	%80tms__ensureWindowOK	;Create a new window
		LDR	R0,[R1,#8]		;Get y0
		ADD	R0,R0,R3		;Calculate y1
		STR	R0,[R1,#16]		;Store it in the block
		SWI	Wimp_OpenWindow		;Open the window
		B	%99tms__ensureWindowOK	;And return to caller

		; --- Check if we should add a scroll bar ---

40		TST	R2,#hFlag__scrBar	;Is there a scroll bar
		BNE	%98tms__ensureWindowOK	;Yes -- return
		CMP	R3,R4			;Is actual > screen height?
		BLT	%98tms__ensureWindowOK	;No -- return

		; --- Rebuild the window ---

50		BL	%80tms__ensureWindowOK	;Create a new window
		LDR	R0,[R1,#4]		;Get old x0
		LDR	R2,[R10,#hTotWidth]	;Get the menu width
		ADD	R0,R0,R2		;Calculate x1
		STR	R0,[R1,#12]		;Store it in the block
		SWI	Wimp_OpenWindow		;Open the window
		BL	tms__width		;Check the width
		B	%99tms__ensureWindowOK	;And return to caller

		; --- Create a new window ---

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

		ADD	R1,R10,#hHandle		;Point to the window handle
		SWI	Wimp_CloseWindow	;Close the window
		SWI	Wimp_DeleteWindow	;And then delete it
		LDR	R0,[R10,#hHandle]	;The window handle
		ADRL	R1,tms__eventHandler	;Point to the handler
		MOV	R2,R10			;The handle passed
		MOV	R3,R12			;Workspace passed in R3
		BL	win_removeEventHandler	;Remove the event handler
		LDR	R1,tms__oldHandle	;Get the old handle
		CMP	R0,R1			;Are they the same?
		BLEQ	tms__cleanUp		;Yes -- clean up a bit
		LDR	R0,[R10,#hHeight]	;Get the menu height
		BL	tms__createWindow	;Create the window
		MOVVS	R1,#1			;On error -- show 1 icon
		BLVS	errorBox		;...display the error
		BVS	%99tms__ensureWindowOK	;...and return to caller
		ADRL	R1,tms__eventHandler	;Point to the handler
		MOV	R2,R10			;The handle passed
		MOV	R3,R12			;Workspace passed in R3
		BL	win_eventHandler	;Remove the event handler
		LDMFD	R13!,{R1-R3,R14}	;Get registers back
		STR	R0,[R1,#0]		;Store in the block
		MOV	R0,#-1			;The behind value
		STR	R0,[R1,#28]		;Store in the block

		MOVS	PC,R14			;Return to caller

		; --- Return to caller ---

98		MOV	R0,#-1			;Open in front
		STR	R0,[R1,#28]		;Store this fact
		SWI	Wimp_OpenWindow		;Open the window
		LDR	R14,tms__flags		;Get the main flags word
		TST	R14,#tFlag__newFont	;Has the font changed?
		BL	tms__width		;Yes -- check the width

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

		LTORG

; --- tms__idleHandler ---
;
; On entry:	R10 == pointer to menu
;
; On exit:	--
;
; Use:		Called on NULL events. R10 points to the menu that the
;		pointer is currently over

tms__idleHandler ROUT

		STMFD	R13!,{R1,R14}		;Stack some registers
		LDR	R1,tms__flags		;Get the flags word
		TST	R1,#tFlag__doFake	;Are we about to fake a NULL?
		LDMNEFD	R13!,{R1,PC}^		;Yes -- return then
		TST	R1,#tFlag__faking	;Are we fakingone now?
		BNE	%10tms__idleHandler	;Yes -- jump ahead then
		SUB	R13,R13,#20		;Get a block
		MOV	R1,R13			;Point to the block
		SWI	Wimp_GetPointerInfo	;Get the pointer position
		MOV	R14,#0			;Clear the button state
		STR	R14,[R1,#8]		;Put value in the bbits
		BL	tms__buttons		;Call the buttons routine
		ADD	R13,R13,#20		;Get the stack back
		LDMFD	R13!,{R1,PC}^		;Return to caller

		; --- Clear the 'faking' bit ---

10		BIC	R1,R1,#tFlag__faking	;Clear the flag
		STR	R1,tms__flags		;Store the new flags
		LDMFD	R13!,{R1,PC}^		;Return to caller

		LTORG

; --- tms__makeDashPattern ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Programs the VDU dot pattern, for sheer prettiness.

tms__makeDashPattern ROUT

		STMFD	R13!,{R0-R2,R14}	;Stack some registers
		MOV	R0,#163			;General OS_Byte
		MOV	R1,#242			;242 is the only valid value
		MOV	R2,#8			;Repeat length
		SWI	OS_Byte			;Set dash pattern length

		ADR	R0,tms__dashPtn		;Point to the pattern spec
		MOV	R1,#?tms__dashPtn	;Size of the string
		SWI	OS_WriteN		;Write 'em all to VDU drivers
		LDMFD	R13!,{R0-R2,PC}^	;Return to caller

tms__dashPtn	DCB	23,6,&f0,&f0,&f0,&f0,&f0,&f0,&f0,&f0

		LTORG

; --- tms__redrawTick ---
;
; On entry:	R4 == the y coordinate
;		R11 == item flags
;		R13 == pointer to a block to use
;
; On exit:	--
;
; Use:		Redraw the tick/splodge on the left hand side of a menu

tms__redrawTick	ROUT

		STMFD	R13!,{R0-R3,R5,R14}	;Stack the link
		ADD	R5,R13,#24		;Point to the block
		MOV	R0,#0			;x0
		MOV	R2,#24			;x1
		SUB	R1,R4,#44		;y0
		MOV	R3,R4			;y1
		STMIA	R5!,{R0-R3}		;Store this in the block
		LDR	R0,=&07000038		;Icon flags so far

		TST	R11,#iFlag__ticked	;Is there a tick
		TSTEQ	R11,#iFlag__radio	;Or a splodge?
		MOVEQ	R1,#&20			;Neither -- plot nothing
		BEQ	%00tms__redrawTick	;And plot it

		TST	R11,#iFlag__shaded	;Is the item shaded?
		ORRNE	R0,R0,#&00400000	;Yes -- shade icon
		TST	R11,#iFlag__ticked	;Are we plotting a tick?
		MOVEQ	R1,#&8F			;Nope -- must be a splodge
		BEQ	%00tms__redrawTick	;And plot it
		LDR	R1,tms__flags		;Get the flags word
		TST	R1,#tFlag__riscos3	;Is this RISC OS 3?
		BNE	%01tms__redrawTick	;Yes -- jump a bit
		MOV	R1,#&80			;No -- plot a tick

00		ORR	R0,R0,#1		;Text icon
		STMIA	R5,{R0,R1}		;Fill in the rest of block
		B	%02tms__redrawTick	;And jump this bit

		; --- Plot tick RISCOS 3 style ---

01		MOV	R2,#1			;Point R2 at it
		ORR	R0,R0,#&100		;Indirected icon
		ORR	R0,R0,#&2		;Sprite icon
		ADR	R1,tms__sprTickName	;Point to the sprite name
		MOV	R3,#2			;The buffer length
		STMIA	R5,{R0-R3}		;Fill in the rest of block

02		ADD	R1,R13,#24		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon

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

		LTORG

tms__sprTickName DCB	&80,0

		EXPORT	tms__wSpace
tms__wSpace	DCD	0

; --- tms__redrawSprite ---
;
; On entry:	R4 == the y coordinate
;		R11 == item flags
;		R13 == pointer to a block to use
;
; On exit:	--
;
; Use:		Redraw the tick/splodge on the left hand side of a menu

tms__redrawSprite ROUT

		STMFD	R13!,{R0-R3,R5,R14}	;Stack the link
		ADD	R5,R13,#24		;Point to the block
		MOV	R0,#24+8		;x0
		LDR	R2,[R10,#hSprWidth]	;Get maximum sprite width
		ADD	R2,R2,R0		;Add on to get x1
		SUB	R1,R4,#44		;y0
		MOV	R3,R4			;y1
		STMIA	R5!,{R0-R3}		;Store this in the block
		LDR	R0,=&07000112		;Icon flags so far
		TST	R11,#iFlag__sprite	;Is there a sprite?
		BICEQ	R0,R0,#2		;No -- plot no sprite then

		TST	R11,#iFlag__shaded	;Is the item shaded?
		ORRNE	R0,R0,#&00400000	;Yes -- shade icon
		TST	R11,#iFlag__halfSize	;Is it a small one?
		ORRNE	R0,R0,#&00000800	;Yes -- set the half-size bit
		STR	R0,[R5],#4		;Stash the flags away

		LDR	R0,[R7,#iSprName]	;Find the sprite name string
		LDR	R1,[R7,#iSprArea]	;Get the sprite area too
		MOV	R2,#1			;Not a number, it's a name
		STMIA	R5!,{R0-R2}		;Stash the data away too

02		ADD	R1,R13,#24		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon

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

		LTORG

; --- tms__redrawText ---
;
; On entry:	R4 == the y coordinate
;		R7 == pointer to the icon
;		R10 == the menu pointer
;		R11 == item flags
;		R13 == pointer to a block to use
;
; On exit:	--
;
; Use:		Redraw the text part of the menu

tms__redrawText	ROUT

		STMFD	R13!,{R0-R3,R14}	;Stack the link

		ADD	R14,R13,#20		;Point to the block

		; --- Plot a dirty great bar across the item ---

		MOV	R0,#24			;x0
		LDR	R2,[R10,#hTotWidth]	;The menu width
		SUB	R2,R2,#24		;Calculate x1
		SUB	R1,R4,#44		;y0
		MOV	R3,R4			;y1
		STMIA	R14!,{R0-R3}		;Store this in the block
		LDR	R0,=&07000030		;Get some base flags
		TST	R11,#iFlag__shaded	;Is the item shaded?
		ORRNE	R0,R0,#&00400000	;Yes -- set the shaded bitty
		LDREQ	R2,[R10,#hSelected]	;Get the selected item
		CMPEQ	R7,R2			;Is it this item?
		EOREQ	R0,R0,#&77000000	;Yes -- invert it then
		STR	R0,[R14],#4		;Save these flags away
		ADD	R1,R13,#20		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon

		; --- Now plot the text transparently over this ---

		LDR	R14,[R10,#hSprWidth]	;Load sprite column width
		ADD	R14,R14,#24		;Bump in a little
		STR	R14,[R1,#0]		;Save as the x0 position
		LDR	R0,=&07000131		;The icon flags
		TST	R11,#iFlag__shaded	;Is the item shaded?
		ORRNE	R0,R0,#&00400000	;Yes -- shade icon
		LDREQ	R2,[R10,#hSelected]	;Get the selected item
		CMPEQ	R7,R2			;Is it this item?
		EOREQ	R0,R0,#&77000000	;No -- use these colours
		LDR	R1,[R7,#iText]		;Point to the text
		MOV	R2,#-1			;No validation string
		MOV	R3,#&ff			;Buffer length
		ADD	R14,R13,#36		;Point to the right bit
		STMIA	R14,{R0-R3}		;Fill in the rest of block
		ADD	R1,R13,#20		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon

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

		LTORG

; --- tms__redrawKey ---
;
; On entry:	R4 == the y coordinate
;		R7 == pointer to the icon
;		R10 == the menu pointer
;		R11 == item flags
;		R13 == pointer to a block to use
;
; On exit:	--
;
; Use:		Redraw the text part of the menu

tms__redrawKey	ROUT

		STMFD	R13!,{R0-R3,R5,R11,R14}	;Stack the link

		ADD	R5,R13,#28		;Point to the block
		LDR	R2,[R7,#iKeyCode]	;Get the string to print
		CMP	R2,#-1			;Is there one?
		BEQ	%99tms__redrawKey	;No -- return
		LDR	R2,[R10,#hTotWidth]	;The menu width
		LDR	R0,[R10,#hKeyWidth]	;Get the shortcut width
		SUB	R2,R2,#24		;Calculate x1
		SUB	R0,R2,R0		;And then x0
		SUB	R1,R4,#44		;y0
		MOV	R3,R4			;y1
		STMIA	R5!,{R0-R3}		;Store this in the block
		LDR	R3,=&00000131		;The icon flags
		TST	R11,#iFlag__shaded	;Is the item shaded?
		ORRNE	R3,R3,#&007400000	;Yes -- shade icon
		BNE	%00tms__redrawKey	;...forget this next bit
		LDR	R2,[R10,#hSelected]	;Get the selected item
		CMP	R7,R2			;Is it this item?
		ORRNE	R3,R3,#&07000000	;No -- use these colours
		ORREQ	R3,R3,#&70000000	;Yep -- use these colours
00		LDR	R0,[R7,#iKeyCode]	;Point to the text
		MOV	R1,#1			;Covert to a short string
		LDR	R11,tms__R11		;Get scratchpad address
		BL	keyString		;Do the conversion
		MOV	R1,R0			;Put string in R1
		MOV	R0,R3			;And flags in R0
		MOV	R2,#-1			;No validation string
		MOV	R3,#&ff			;Buffer length
		STMIA	R5,{R0-R3}		;Fill in the rest of block
		ADD	R1,R13,#28		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon

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

		LTORG

; --- tms__redrawArrow ---
;
; On entry:	R4 == the y coordinate
;		R10 == pointer to the menu
;		R11 == item flags
;		R13 == pointer to a block to use
;
; On exit:	--
;
; Use:		Redraw the arrow on the right hand side of a menu

tms__redrawArrow ROUT

		TST	R11,#iFlag__arrow	;Is there an arrow?
		MOVEQS	PC,R14			;No -- return

		STMFD	R13!,{R0-R3,R5,R14}	;Stack the link
		ADD	R5,R13,#24		;Point to the block
		LDR	R2,[R10,#hTotWidth]	;x1
		SUB	R0,R2,#24		;x0
		SUB	R1,R4,#44		;y0
		MOV	R3,R4			;y1
		STMIA	R5!,{R0-R3}		;Store this in the block
		LDR	R0,=&07000038		;Icon flags so far
		TST	R11,#iFlag__shaded	;Is the item shaded?
		ORRNE	R0,R0,#&00400000	;Yes -- shade icon
		LDR	R1,tms__flags		;Get the flags word
		TST	R1,#tFlag__riscos3	;Is this RISC OS 3?
		BNE	%01tms__redrawArrow	;Yes -- jump a bit
		MOV	R1,#&89			;No -- plot a tick
		ORR	R0,R0,#1		;Text icon
		STMIA	R5,{R0,R1}		;Fill in the rest of block
		B	%02tms__redrawArrow	;And jump this bit

		; --- Plot tick RISCOS 3 style ---

01		MOV	R2,#1			;The WIMP area
		ORR	R0,R0,#&100		;Indirected icon
		ORR	R0,R0,#&2		;Sprite icon
		ADR	R1,tms__sprArrowName	;Point to the sprite name
		MOV	R3,#2			;The buffer length
		STMIA	R5,{R0-R3}		;Fill in the rest of block

02		ADD	R1,R13,#24		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon

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

		LTORG

tms__sprArrowName DCB &89,0

; --- tms__redrawBar ---
;
; On entry:	R4 == the y coordinate
;		R10 == the menu pointer
;		R13 == pointer to a block to use
;
; On exit:	--
;
; Use:		Redraw the tearoff bar in a menu. Notice that this is
;		different to the steel version, which uses icons here

tms__redrawBar	ROUT

		STMFD	R13!,{R0-R3,R5,R14}	;Stack the link

		ADD	R5,R13,#24		;Point to the block
		MOV	R0,#0			;x0
		LDR	R2,[R10,#hTotWidth]	;x1
		MOV	R1,R4			;y0
		MOV	R3,#0			;y1
		STMIA	R5!,{R0-R3}		;Store this in the block
		LDR	R14,[R10,#hFlags]	;Get the menu flags
		LDR	R0,=&07000031		;The icon flags
		TST	R14,#hFlag__global	;Is this a `global' menu?
		ORREQ	R0,R0,#&30000000	;No -- grey bar then
		ORRNE	R0,R0,#&80000000	;Yes -- blie bar then
		MOV	R1,#0			;No text
		STMIA	R5,{R0-R1}		;Fill in the rest of block
		ADD	R1,R13,#24		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon
		LDR	R5,[R10,#hFlags]	;Get the menu flags
		TST	R5,#hFlag__torn		;Has menu been torn?
		BNE	%50tms__redrawBar	;Yes -- draw that bit

		; --- Draw just the tear icon ---

		ADD	R5,R13,#24		;Point to the block
		MOV	R0,#4			;x0
		MOV	R2,#68			;x1
		MOV	R1,#-20			;y0
		MOV	R3,#-4			;y1
		STMIA	R5!,{R0-R3}		;Store this in the block
		LDR	R0,=&00000112		;The icon flags
		MOV	R1,R0			;Hark -- R0 to be corrupted
		BL	resspr_area		;Get the sprite area
		MOV	R2,R0			;Point R2 at it
		MOV	R0,R1			;Get flags back in R0
		ADR	R1,tms__sprTearName	;Point to the sprite name
		MOV	R3,#5			;The buffer length
		STMIA	R5,{R0-R3}		;Fill in the rest of block

		ADD	R1,R13,#24		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon
		LDMFD	R13!,{R0-R3,R5,PC}^	;Return to caller

		; --- Plot the icons in a torn menu ---

50		ADD	R5,R13,#24		;Point to the block
		MOV	R0,#4			;x0
		MOV	R2,#70			;x1
		MOV	R1,#-20			;y0
		MOV	R3,#-4			;y1
		STMIA	R5!,{R0-R3}		;Store this in the block
		LDR	R0,=&00000112		;The icon flags
		MOV	R1,R0			;Hark -- R0 to be corrupted
		BL	resspr_area		;Get the sprite area
		MOV	R2,R0			;Point R2 at it
		MOV	R0,R1			;Get flags back in R0
		ADR	R1,tms__sprCloseName	;Point to the sprite name
		MOV	R3,#6			;The buffer length
		STMIA	R5,{R0-R3}		;Fill in the rest of block

		ADD	R1,R13,#24		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon

		ADD	R5,R13,#24		;Point to the block
		LDR	R2,[R10,#hTotWidth]	;Get the width
		SUB	R0,R2,#60		;x0
		SUB	R2,R2,#4		;x1
		MOV	R1,#-20			;y0
		MOV	R3,#-4			;y1
		STMIA	R5!,{R0-R3}		;Store this in the block
		LDR	R0,=&00000112		;The icon flags
		MOV	R1,R0			;Hark -- R0 to be corrupted
		BL	resspr_area		;Get the sprite area
		MOV	R2,R0			;Point R2 at it
		MOV	R0,R1			;Get flags back in R0
		ADR	R1,tms__sprFoldName	;Point to the sprite name
		MOV	R3,#6			;The buffer length
		STMIA	R5,{R0-R3}		;Fill in the rest of block

		ADD	R1,R13,#24		;Point to the block
		SWI	Wimp_PlotIcon		;Plot the icon

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

		LTORG

tms__sprTearName DCB	"tear",0
tms__sprCloseName DCB	"close",0
tms__sprFoldName DCB	"fold",0

; --- tms__doRedraw ---
;
; On entry:	R0 == flags:
;		      bit 0 == don't only plot queued items
;		R1 == pointer to the redraw block
;
; On exit:	--
;
; Use:		Actually redraws a menu, given the redraw block

tms__doRedraw	ROUT

		STMFD	R13!,{R0-R11,R14}	;Stack some registers
		MOV	R3,R0			;Keep flags safe nicely

		; --- Set up some pointers ---

		SUB	R13,R13,#32		;Get a nice block
		MOV	R6,R1			;Remember the redraw block
		LDR	R5,[R10,#hFlags]	;Get the flags word
		MOV	R4,#0			;The y coordinate
		TST	R5,#hFlag__tearable	;Is there a tearoff bar?
		SUBNE	R4,R4,#tms__barHeight	;Yes -- Allow for it

		; --- Draw the tearoff bar ---

		TSTNE	R3,#1			;Does it need redrawing?
		BLNE	tms__redrawBar		;Yeap...

		; --- Now deal with items ---

		LDR	R9,[R10,#hItems]	;Point to the first item
00tms__doRedraw	LDR	R8,[R9,#iNumber]	;Get the number of items
		ADD	R7,R9,#iHdrSize		;And point to the first item

		; --- Now redraw each item ---

01tms__doRedraw	LDR	R11,[R7,#iFlags]	;Get the item flags
		TST	R3,#1			;Are we only doing queued?
		ORRNE	R11,R11,#&FF000000	;No -- pretend it wa queued

		; --- Redraw the tick/splodge on the left ---

		TST	R11,#iFlag__newTick	;Has the tick changed?
		BLNE	tms__redrawTick		;Yes -- plot the tick thing

		; --- Plot the main text part ---

09tms__doRedraw	TST	R11,#iFlag__newText	;Has the text changed?
		BLNE	tms__redrawText		;Yes -- redraw the text bit

		; --- Now the sprite, if there is one ---

08tms__doRedraw	TST	R11,#iFlag__newSpr	;Does sprite need rendering?
		BLNE	tms__redrawSprite	;Yes -- render it then

		; --- The keyboard shortcut ---

		TST	R11,#iFlag__newKey	;Has shortcut changed?
		BLNE	tms__redrawKey		;Yes -- redraw it then

		; --- The arrow ---

		TST	R11,#iFlag__newArrow	;Has the arrow changed?
		BLNE	tms__redrawArrow	;Yes -- draw it then

		; --- And finally, plot the dotted line ---

		TST	R11,#iFlag__dotted	;Is there a dotted line here?
		BEQ	%90tms__doRedraw	;No -- jump this code then
		MOV	R0,#4			;Move cursor
		LDR	R1,[R6,#4]		;To r.box->x0
		LDR	R2,[R6,#16]		;r.box->y1
		ADD	R2,R2,R4		;r.box->y1+y
		SUB	R2,R2,#56		;r.box->y1+y-(44+12)
		LDR	R14,[R6,#24]		;Don't neglect scroll offset
		SUB	R2,R2,R14		;No way bob...
		SWI	OS_Plot			;Do the move
		BL	tms__makeDashPattern	;Program the dash pattern
		MOV	R0,#7			;Colour 7
		SWI	Wimp_SetColour		;Thus let it be
		MOV	R0,#17			;Dotted line -- both ends
		LDR	R1,[R10,#hTotWidth]	;Get the width to draw
		MOV	R2,#0			;Relative y offset
		SWI	OS_Plot			;Plot the line

		; --- Alter the y coordinate ---

90tms__doRedraw	TST	R11,#iFlag__dotted	;Is there a dotted line
		SUBNE	R4,R4,#68		;Yes -- take into account
		SUBEQ	R4,R4,#44		;No -- just sub item height

		; --- Do next item ---

		SUBS	R8,R8,#1		;Decrement item count
		ADDNE	R7,R7,#iItemSize	;Point to the next item
		BNE	%01tms__doRedraw	;...and redraw it
		LDR	R9,[R9,#iItems]		;If at end -- point to next
		CMP	R9,#0			;Any more items?
		BNE	%00tms__doRedraw	;Yes -- redraw them
		ADD	R13,R13,#32		;Get my block back
		LDMFD	R13!,{R0-R11,PC}^	;Return to caller

		LTORG

; --- tms__redraw ---
;
; On entry:	R0 == event from wimp
;		R1 == pointer to the wimp block
;		R10 == pointer to the menu
;
; On exit:	--
;
; Use:		Called to perform the redraw loop when redrawing a menu

tms__redraw	ROUT

		STMFD	R13!,{R0,R1,R14}	;Stack some registers
		SWI	Wimp_RedrawWindow	;Start the redraw
00tms__redraw	CMP	R0,#0			;More to do?
		LDMEQFD	R13!,{R0,R1,PC}^	;No -- return
		MOV	R0,#1			;Redraw everything please
		BL	tms__doRedraw		;Perform the redrawing
		SWI	Wimp_GetRectangle	;Get another rectangle
		B	%00tms__redraw		;And keep redrawing

		LTORG

; --- tms__update ---
;
; On entry:	R0 == flags (as for doRedraw)
;		R10 == pointer to the menu
;
; On exit:	--
;
; Use:		Updates the entire menu.

		EXPORT	tms__update
tms__update	ROUT

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

		LDR	R14,[R10,#hHandle]	;Load the window handle
		STR	R14,[R13,#-44]!		;Create a block
		MOV	R0,#0			;Minimum x coord
		LDR	R1,[R10,#hHeight]	;Load out the height
		RSB	R1,R1,#0		;Minimum y coordinate
		LDR	R2,[R10,#hTotWidth]	;Get the total width
		MOV	R3,#0			;Maximum y coordinate
		STMIB	R13,{R0-R3}		;Store in the block
		MOV	R1,R13			;Point to the block

		SWI	Wimp_UpdateWindow	;Start the redraw
00tms__update	CMP	R0,#0			;More to do?
		ADDEQ	R13,R13,#44		;No -- get stack back
		LDMEQFD	R13!,{R0-R3,PC}^	;...and return
		LDR	R0,[R13,#44]		;Load the caller's flags
		BL	tms__doRedraw		;Perform the redrawing
		SWI	Wimp_GetRectangle	;Get another rectangle
		B	%00tms__update		;And keep redrawing

		LTORG

; --- tms__eventHandler ---
;
; On entry:	R0 == event, as returned from Wimp_Poll
;		R1 == pointer to the event block
;		R10 == pointer to the menu
;
; On exit:	--
;
; Use:		Deals with the event that has been sent to my window

		EXPORT tms__eventHandler
tms__eventHandler ROUT

		ORR	R14,R14,#C_flag		;Set carry flag on return
		CMP	R0,#8			;Is it a low-numbered event?
		ADDLE	PC,PC,R0,LSL #2		;Yes -- dispatch
		B	%00tms__eventHandler	;No -- handle specially

		; --- The event dispatch table ---

		BICS	PC,R14,#C_flag		;Null events are ignored
		B	tms__redraw		;Call this to redraw menu
		B	%10tms__eventHandler	;Open unopened windows
		B	%20tms__eventHandler	;Close unclosed windows
		B	%30tms__eventHandler	;Pointer's left a window
		B	%40tms__eventHandler	;Gone back inside again
		B	tms__buttons		;Call the button handler
		BICS	PC,R14,#C_flag		;Drag returned -- so what
		BICS	PC,R14,#C_flag		;Key press

		; --- Handle high-numbered events ---

00		CMP	R0,#17			;Is it a message?
		CMPNE	R0,#18			;Or another message?
		BICNES	PC,R14,#C_flag		;No -- nothing we can do

		; --- Deal with a help message ---

		STMFD	R13!,{R0-R4,R14}	;Stack registers
		LDR	R14,[R1,#16]		;Get the message number
		LDR	R2,=&502		;Load the constant number
		CMP	R14,R2			;Is it a help message
		LDMNEFD	R13!,{R0-R3,R14}	;No -- load registers
		BICNES	PC,R14,#C_flag		;...couldn't understand

		; --- Find the item that we are over ---

 		ADD	R4,R1,#20		;Point to the coordinates
		SUB	R13,R13,#36		;Get a small block
		MOV	R1,R13			;Point to the block
		LDR	R2,[R10,#hHandle]	;Get the window handle
		STR	R2,[R1,#0]		;Store the window handle
		SWI	Wimp_GetWindowState	;Get the window state
		LDR	R0,[R4,#0]		;Get the mouse x coord
		LDR	R2,[R13,#20]		;Get the scroll x position
		LDR	R3,[R13,#4]		;Get the x0 position
		ADD	R0,R0,R2		;Calculate workarea relative
		SUB	R0,R0,R3		;...x position
		LDR	R1,[R4,#4]		;Get the mouse y coord
		LDR	R2,[R13,#24]		;Get the scroll y position
		LDR	R3,[R13,#16]		;Get the y1 position
		ADD	R1,R1,R2		;Calculate workarea relative
		SUB	R1,R1,R3		;...y position
		ADD	R13,R13,#36		;Get the block back
		STMFD	R13!,{R0,R1}		;Stack the coordinates
		BL	tms__findItem		;Find the associated icon

		CMP	R8,#0			;Were we over an item?
		BEQ	%05tms__eventHandler	;No -- try the tearoff bar

		; --- Send the help event to the users handler ---

		STMFD	R13!,{R10,R12}		;Save these registers
		MOV	R0,#mEvent_help		;Help on item required
		LDR	R1,tms__itemIndex	;The items index
		LDR	R2,tms__itemOver	;Point to packed item def.
		ADD	R3,R8,#iHandler		;Point to the handler
		LDMIA	R3,{R3,R10,R12}		;Load the values
		TEQ	R3,#0			;Sanity check
		MOV	R14,PC			;Set up the return address
		MOVNE	PC,R3			;Call the handler
		LDMFD	R13!,{R10,R12}		;Get my registers back
		ADD	R13,R13,#8		;Skip over the coordinates
		B	%09tms__eventHandler	;And return

		; --- Was the click on the tearoff bar? ---

05		LDR	R0,tms__flags		;Get the flags word
		LDMFD	R13!,{R0,R1}		;Get the coordiantes
		LDR	R2,[R10,#hFlags]	;Get the menu flags
		TST	R2,#hFlag__tearable	;Is there a bar?
		BEQ	%09tms__eventHandler	;No -- branch ahead
		CMP	R1,#-tms__barHeight	;Did we click in the bar?
		BLT	%09tms__eventHandler	;No -- branch ahead
		CMP	R1,#-4			;The top of the icon
		BGT	%09tms__eventHandler	;Not in icon -- return
		CMP	R1,#-(tms__barHeight-4)	;The bottom level
		BLT	%09tms__eventHandler	;Not in icon -- return
		TST	R2,#hFlag__torn		;Has the menu been torn off
		BNE	%06tms__eventHandler	;Yes -- deal with that

		; --- Was the click in the tear icon? ---

		CMP	R0,#4			;The left hand side
		BLT	%09tms__eventHandler	;Not in icon -- return
		CMP	R0,#68			;The right hand side
		BGT	%09tms__eventHandler	;Not in icon -- return
		ADRL	R0,tms__helpTear	;Point to the tear message
		BL	msgs_lookup		;Look it up in messages file
		BL	help_add		;And send it to help
		B	%09tms__eventHandler	;Return to caller

		; --- The menu is torn off -- what did we click in? ---

06		CMP	R0,#4			;The left hand side
		BLT	%09tms__eventHandler	;Not in icon -- return
		CMP	R0,#70			;The right hand side
		ADRLEL	R0,tms__helpClose	;Point to the close message
		BLLE	msgs_lookup		;Look it up in messages file
		BLLE	help_add		;And send it to help
		BLE	%09tms__eventHandler	;Return to caller

		; --- Was it in the fold icon ---

07		LDR	R2,[R10,#hTotWidth]	;The total menu width
		SUB	R2,R2,#60		;LHS of tear icon
		CMP	R0,R2			;Where did we click?
		BLT	%09tms__eventHandler	;Not in it, that's for sure
		ADD	R2,R2,#56		;RHS of tear icon
		CMP	R0,R2			;Where did we click?
		ADRLEL	R0,tms__helpFold	;Point to the fold message
		BLLE	msgs_lookup		;Look it up in messages file
		BLLE	help_add		;And send it to help

09		LDMFD	R13!,{R0-R4,R14}	;Load back registers
		ORRS	PC,R14,#C_flag		;Return with carry set

		; --- OpenWindow request ---

10		STMFD	R13!,{R14}		;Stack some registers
		BL	screen_justChangedMode	;Has there been a mode change
		SWICC	Wimp_OpenWindow		;No -- open the window
		LDMCCFD	R13!,{PC}^		;...and return to caller
		STMFD	R13!,{R0-R3}		;Stack some more registers
		BL	tms__ensureWindowOK	;Ensure window is OK
		SUB	R13,R13,#20		;Get me a block
		MOV	R1,R13			;Point to it
		SWI	Wimp_GetPointerInfo	;Get the pointer information
		LDR	R0,[R1,#12]		;Get the window ptr is over
		LDR	R1,[R10,#hHandle]	;And window handle of menu
		CMP	R0,R1			;Are they the same?
		BNE	%15tms__eventHandler	;No -- return
		LDR	R0,tms__oldHandle	;Get the idle handler handle
		CMP	R0,#0			;Is there one?
		BNE	%15tms__eventHandler	;Yes -- return
		MOV	R0,#0			;Frequency -- quick please
		ADRL	R1,tms__idleHandler	;Point to the handler
		MOV	R2,R10			;Pass menu in R10
		MOV	R3,R12			;And workspace in R12
		BL	idle_handler		;Add in the handler
		STR	R10,tms__oldHandle	;And store away new handle

15		ADD	R13,R13,#20		;Get the stack back
		LDMFD	R13!,{R0-R3,PC}^	;Return to caller

		; --- CloseWindow request ---

20		SWI	Wimp_CloseWindow	;Close the window
		MOVS	PC,R14			;And return

		; --- Pointer leaving ---

30		STMFD	R13!,{R0,R2,R10,R14}	;Stack some registers
		LDR	R0,tms__oldHandle	;Is there an idle handle hnd
		CMP	R0,#0			;Is there one?
		LDMEQFD	R13!,{R0,R2,R10,PC}^	;No -- return
		BL	tms__cleanUp		;Yes -- clean up a bit
		MOV	R10,R0			;Point to the menu
		LDR	R2,[R10,#hFlags]	;Get the flags for the menu
		TST	R2,#hFlag__warned	;Have we be warned?
		LDMNEFD	R13!,{R0,R2,R10,PC}^	;Yes -- return
		LDR	R2,[R0,#hSelected]	;Point to the selected item
		CMP	R2,#0			;Is there one?
		BLNE	tms__unHighlight	;Un-highlight the item
		LDMFD	R13!,{R0,R2,R10,PC}^	;And return to caller

		; --- Pointer entering ---

40		STMFD	R13!,{R0-R3,R14}	;Stack some registers
		LDR	R0,tms__oldHandle	;Is there an idle handle hnd
		CMP	R0,#0			;Is there one?
		BLNE	tms__cleanUp		;Yes -- clean up a bit
		MOV	R0,#0			;Frequency -- quick please
		ADRL	R1,tms__idleHandler	;Point to the handler
		MOV	R2,R10			;Pass menu in R10
		MOV	R3,R12			;And workspace in R12
		BL	idle_handler		;Add in the handler
		STR	R2,tms__oldHandle	;We have an idle handler
		BL	tms__alarm2		;Allow item selection
		LDMFD	R13!,{R0-R3,PC}^	;And return to caller

tms__helpTear	DCB	"TMST",0
tms__helpClose	DCB	"TMSC",0
tms__helpFold	DCB	"TMSF",0

		LTORG

; --- tms_help ---
;
; On entry:	R0 == pointer to base message tag
;		R1 == index of menu item
;
; On exit:	--
;
; Use:		Adds a string to the help message found by adding the menu
;		item number to the base message tag.

		EXPORT	tms_help
tms_help	ROUT

		CMP	R1,#0			;Is the menu item sane?
		MOVLTS	PC,R14			;No -- don't trust Tim
		STMFD	R13!,{R0-R2,R14}	;Save some registers
		MOV	R1,R0			;Point to base message tag
		MOV	R0,R11			;Point to scratchpad
		BL	str_cpy			;Add the string in there
		MOV	R1,R0			;Point to terminating null
		MOV	R2,#25			;Should be 25 bytes left over
		LDR	R0,[R13,#4]		;Get his item number
		SWI	OS_ConvertInteger4	;Tack it on the end
		MOV	R0,R11			;Point to the message tag
		BL	msgs_lookup		;Translate it nicely
		BL	help_add		;Add it to the help string
		LDMFD	R13!,{R0-R2,PC}^	;Return to caller

		LTORG

;----- Workspace ------------------------------------------------------------

		AREA	|Sapphire$$LibData|,CODE,READONLY

		DCD	tms__wSize		;Workspace size
		DCD	tms__wSpace		;Workspace pointer
		DCD	0			;Scratchpad size
		DCD	tms_init		;Initialisation

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

		END
