; TopIconBar module v2.03 by Vincent Lefvre - 10/08/1997
; (Public Domain)

; Requires RISC OS 3.

; When the mouse reaches the bottom of the screen (Y = 0):
;   * if all the buttons are released and there is no open menu,
;     the icon bar is automatically brought to the front;
;   * if only the menu button is pressed, the icon bar is sent to the back.

; Here a menu is a window that:
;   * is in front of the icon bar (in the window stack),
;   * has a title bar, no back icon and no close icon;
;   * has a button type equal to 0.
;   * has a work area maximum x >= 2^18.

; Change TEST_WAMX to {FALSE} if you want to remove the last condition.

		GET	h:RegNames
		GET	h:SWINames

INTERVAL	EQU	10		;Interval in cs for Wimp_PollIdle.

		^	0
		#	4		;Task handle.
BUFFER		#	256		;Buffer.
SIZE		#	0

		GBLL	TEST_WAMX
TEST_WAMX	SETL	{TRUE}		;TRUE: test work area maximum x.

		AREA	TopIconBar, CODE, PIC, READONLY
		ENTRY

BaseAddr	DCD	RM_Start  -BaseAddr
		DCD	RM_Init   -BaseAddr
		DCD	RM_Die    -BaseAddr
		DCD	0
		DCD	RM_Title  -BaseAddr
		DCD	RM_Help   -BaseAddr
		DCD	RM_HCtable-BaseAddr

task		DCB	"TASK"

RM_Title	DCB	"TopIconBar",0

RM_Help		DCB	"TopIconBar",9,"2.03 (10 Aug 1997) by Vincent Lefvre",0

Help_Desktop	DCB	"Do not use *",27,0,", use *Desktop instead.",0

RM_HCtable	DCB	"Desktop_TopIconBar",0
		ALIGN
		DCD	Desktop-BaseAddr,0,0,Help_Desktop-BaseAddr
		DCD	0

Desktop		STMFD	SP!, {LR}
		MOV	R2, R0
		ADR	R1, RM_Title
		MOV	R0, #2
		SWI	XOS_Module	;Enter TopIconBar.
		LDMFD	SP!, {PC}

RM_Start	LDR	R6, [R12]	;Pointer to workspace.

		LDR	R0, [R6]	;Task handle or 0.
		TEQ	R0, #0
		LDRNE	R1, task	;"TASK".
		SWINE	Wimp_CloseDown
		MOVNE	R0, #0
		STRNE	R0, [R6]	;Reset task handle.

		MOV	R0, #300	;Minimum RISC OS 3.
		LDR	R1, task	;"TASK".
		ADR	R2, RM_Title
		SWI	XWimp_Initialise
		ADRVS	R3, RM_Title
		SWIVS	OS_ExitAndDie
		STR	R1, [R6]	;Store task handle.

loop0		MOV	R7, #0
loop		SWI	OS_ReadMonotonicTime
		ADD	R2, R0, #INTERVAL
		MOV	R0, #0		;Mask.
		ADD	R1, R6, #BUFFER	;256-byte block.
		SWI	Wimp_PollIdle

		TEQ	R0, #17		;UserMessage?
		TEQNE	R0, #18		;UserMessage_Recorded?
		LDREQ	R0, [R1, #16]	;Message code.
		TEQEQ	R0, #0		;Quit?
		ADREQ	R3, RM_Title
		SWIEQ	OS_ExitAndDie	;Die if quit.

		SWI	Wimp_GetPointerInfo
		LDMIB	R1, {R0,R2}	;Mouse y and button state.
		TEQ	R0, #0
		MOVNE	R7, #0		;R7 = 0 if y != 0. Loop if y != 0
		EOREQS	R0, R2, R7	;or a button except menu is pressed
		BNE	loop		;or (menu is pressed iff R7 == 0).

		MOV	R0, #-2
		STR	R0, [R1]	;Window handle: -2 (icon bar).
		SWI	Wimp_GetWindowState
		LDR	R0, [R1, #32]	;Window flags.
		MOV	R7, #2		;R7 = 2.
		AND	R0, R0, #1<<17	;Icon bar fully visible?
		TEQ	R2, R0, LSR #16	;Branch if the icon bar depth
		BNE	loop		;doesn't need to be changed.

		TST	R2, #2
		BNE	shift_f12	;Branch if click on menu button.
		ORR	R1, R1, #1	;Set bit 0 of R1 for Wimp_GetWindowInfo.
		B	next_win

loop_win	STR	R0, [R1, #-1]	;Info about the next window...
		SWI	Wimp_GetWindowInfo
		[	TEST_WAMX
		LDR	R0, [R1, #51]
		CMP	R0, #1<<18	;Branch if work area maximum x < 1<<18
		BLT	next_win	;(not a menu).
		]
		LDR	R0, [R1, #31]	;Window flags.
		EOR	R0, R0, #1<<26	;Z = 1 if window has a title bar,
		TST	R0, #7<<24	;no back icon and no close icon.
		LDREQ	R0, [R1, #63]	;Window button type.
		TSTEQ	R0, #&F000
		BEQ	loop0		;Branch if window is a menu.
next_win	LDR	R0, [R1, #27]	;Handle of window in front of current.
		CMP	R0, #-1		;Loop if current isn't at the top,
		BNE	loop_win	;otherwise there is no open menu.

shift_f12	MOV	R0, #&1DC	;Insert a Shift-F12.
		SWI	Wimp_ProcessKey
		B	loop		;Loop.

RM_Init		STMFD	SP!, {LR}
		LDR	R2, [R12]	;R2: pointer to workspace or 0.
		TEQ	R2, #0
		MOVEQ	R0, #6		;Executed unless re-init.
		MOVEQ	R3, #SIZE
		SWIEQ	XOS_Module	;Claim.
		LDMVSFD	SP!, {PC}	;Return with V=1 if not enough memory.
		STREQ	R2, [R12]	;Pointer to workspace.
reset_taskh	MOV	R0, #0
		STR	R0, [R2]	;Reset task handle.
		LDMFD	SP!, {PC}^

RM_Die		STMFD	SP!, {LR}
		LDR	R2, [R12]
		LDR	R0, [R2]	;Task handle or 0.
		TEQ	R0, #0
		LDMEQFD	SP, {PC}^	;Return if 0.
		LDR	R1, task	;"TASK".
		SWI	XWimp_CloseDown
		B	reset_taskh	;Reset task handle and return.

		END
