;*******************************************************************************
; Director - Icons
;
; Copyright (C) 2003, Nick Craig-Wood and Philip Ludlam
;
;This program 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 of the License, or (at your option) any later
;version.
;
;This program 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
;this program; if not, write to the Free Software Foundation, Inc., 59 Temple
;Place - Suite 330, Boston, MA 02111-1307, USA
;
;*******************************************************************************
;----h- Director.s.Icons
; Name
;   Icons
;
; Purpose
;   Handle icons; their creation, destruction and mouse clicks.
;------
;*******************************************************************************


		TTL	> Icons

		GET	OSLib:oslib.hdr.OS
		GET	OSLib:oslib.hdr.OSFSControl
		GET	OSLib:oslib.hdr.OSWord
		GET	OSLib:oslib.hdr.Wimp
		GET	OSLib:oslib.hdr.WimpSpriteOp
		GET	AsmLib2:hdr.RegsBoth
		GET	AsmLib2:hdr.MacrosBoth
		GET	h.Constants
		GET	h.WorkSpace
		GET	h.ListMacros
		GET	AsmLib2:hdr.DebugBoth
		GET	h.Memory
		GET	h.Messages
		GET	h.Menus
		GET	h.ModuleHead
		GET	h.BMG
		GET	h.Task

		AREA	|Icons|, CODE, READONLY


;*******************************************************************************
;----s- Director.s.Icons.IconBlock
; Name
;   IconBlock
;
; Purpose
;   IconBlock structure
;
; Source


			^	0
IconBlock_link		#	4
IconBlock_name		#	4
IconBlock_create_block	#	Wimp_IconCreate
IconBlock_created	#	4
IconBlock_destroy	#	4
IconBlock_priority	#	4
IconBlock_text		#	4
IconBlock_texttype	#	4	; What does it display for text?
IconBlock_textdetail	#	4	; i.e. drive spec: e.g. IDEFS::4.$ or time format
IconBlock_textval1	#	4	; for efficiency, store the current
IconBlock_textval2	#	4	;   value -> can skip recalc & redraw
IconBlock_textsize	#	4	; holds size defined for icon text
IconBlock_validation	#	4
IconBlock_handle	#	4
IconBlock_adjust	#	4	; These must be in this order and together
IconBlock_menu		#	4	;
IconBlock_select	#	4	;
IconBlock_dragto	#	4	;
IconBlock_dragfrom	#	4	;
IconBlock		EQU	:INDEX: @

;------
;*******************************************************************************


;*******************************************************************************
;Variables local to Icons
;These are allocated from a block in the main workspace
;*******************************************************************************


			^	(:INDEX: IconsVars), wp

			ASSERT	@ <= EndIconsVars


;*******************************************************************************
;----f- Director.s.Icons.IconBlockFind
; Name
;   IconBlockFind
;
; Purpose
;   This finds the given icon block in the icon list or returns a pointer
;   to the previous item
;
; Entry
;   r0  name of menu
;
; Exit
;   r0  IconBlock
;   r1  previous menu block (if found)
;   Flags
;     EQ means found
;     NE means not found
;------
;*******************************************************************************


IconBlockFind	ROUTINE	"r2-r4"

		ADR	r4, IconsAnchor			; r4  list anchor

loop$l		ListWalk	r4, r2			; r2  previous, r4  current
		BEQ	notfound$l

		LDR	lr, [r4, #IconBlock_destroy]
		CMP	lr, #0
		BNE	loop$l				; block is not here if marked for destruction

		LDR	r1, [r4, #IconBlock_name]
		BL	strcmpi				; to_find - current
		BGT	loop$l				; continue until alphabetical place found
		BNE	notfound$l

found$l		MOV	r0, r4				; point to current IconBlock
		MOV	r1, r2
		SetZ
		EXIT

notfound$l	MOV	r0, r4				; point to current IconBlock
		MOV	r1, r2
		ClearZ
		EXIT


;*******************************************************************************
;----f- Director.s.Icons.IconBlockCreate
; Name
;   IconBlockCreate
;
; Purpose
;   This creates a new menu block and links it into the end of the list supplied
;   It initialises all the fields in the menu block
;
; Entry
;   r0  name for icon
;   r1  sprite for icon (not 0)
;   r2  text for icon (0 means don't create a new icon)
;   r3 = handle
;   r4 = icon priority
;   r5 = draggable
;
; Exit
;   If an error occured:
;     r0 = pointer to valid error block
;     VS
;   Otherwise
;     VC
;     r0  icon block
;------
;*******************************************************************************


IconBlockCreate	ROUTINE	"r1-r11", EXPORT

		MOV	r7, r1				; r7  sprite name
		MOV	r8, r2				; r8  text
		MOV	r10, r0				; r10  name

kill$l		MOV	r0, r10				; name
		BL	IconBlockFind
		MOVEQ	lr, #1
		STREQ	lr, [r0, #IconBlock_destroy]	; if found mark for destruction
		BEQ	kill$l
		MOV	r4, r1				; r4  link

		TEQ	r8, #0
		MOVEQ	r11, #0				; show no block created
		BEQ	exit$l				; end if we are deleting only

		MOV	r0, #IconBlock
		BL	malloc
		BVS	error$l
		MOV	r11, r0				; r11  IconBlock
		MOV	r1, #IconBlock
		BL	memclear			; clear the icon block to 0

		MOV	r0, r10
		BL	strdup
		BVS	error$l
		MOV	r10, r0				; r10  dup-ed name of icon
		STR	r10, [r11, #IconBlock_name]	; store the name of the icon
		BL	strlen
		STR	r0, [r11, #IconBlock_textsize]

		MOV	r1, r4				; r1  link
		Link	r11, r1, lr			; link the block into the correct place in the list

		MOV	r0, #WimpSpriteOp_ReadSpriteSize
		MOV	r2, r7
		SWI	XWimp_SpriteOp
		BVS	error$l				; r3 = width, r4 = height (in pixels)

		MOV	r0, r6				; screen mode
		MOV	r1, #OS_ModevarXEigFactor
		SWI	XOS_ReadModeVariable
		BVS	ErrorReturn
		MOV	r3, r3, LSL r2			; convert to OS units

		MOV	r1, #OS_ModevarYEigFactor
		SWI	XOS_ReadModeVariable
		BVS	ErrorReturn
		MOV	r4, r4, LSL r2			; convert to OS units

		LDRSP	lr, r4
		STR	lr, [r11, #IconBlock_priority]

		MOV	r0, r8
		BL	strdup
		BVS	error$l
		STR	r0, [r11, #IconBlock_text]
		MOV	r8, r0				; r8  text

		;Fill in Wimp_IconCreate

		LDRSP	lr, r3
		STR	lr, [r11, #IconBlock_create_block + Wimp_IconCreate_w] ; handle

base_icon$l	EQU	Wimp_IconText + Wimp_IconSprite + Wimp_IconHCentred + Wimp_IconIndirected + (Wimp_ColourBlack << Wimp_IconFGColourShift) + (Wimp_ColourVeryLightGrey << Wimp_IconBGColourShift)

		LDRSP	lr, r5				; draggable?
		CMP	lr, #0				; if we have to drag from then
		LDREQ	r0, =base_icon$l + (Wimp_ButtonClick << Wimp_IconButtonTypeShift)
		LDRNE	r0, =base_icon$l + (Wimp_ButtonClickDrag << Wimp_IconButtonTypeShift)
		STR	r0, [r11, #IconBlock_create_block + Wimp_IconCreate_icon + Wimp_Icon_flags]

		STR	r8, [r11, #IconBlock_create_block + Wimp_IconCreate_icon + Wimp_Icon_data + Wimp_IconData_indirected_text_and_sprite_text]
		MOV	r0, r8
		BL	strlen
		MOV	r2, r0, LSL#4			; r2 is width of text in OS units
		ADD	r0, r0, #1
		STR	r0, [r11, #IconBlock_create_block + Wimp_IconCreate_icon + Wimp_Icon_data + Wimp_IconData_indirected_text_and_sprite_size]

		CMP	r2, r3
		MOVGT	r3, r2				; r3 = max(string_width, sprite_width)

		MOV	r0, #0
		STR	r0, [r11, #IconBlock_create_block + Wimp_IconCreate_icon + Wimp_Icon_extent + OS_Box_x0]
		STR	r3, [r11, #IconBlock_create_block + Wimp_IconCreate_icon + Wimp_Icon_extent + OS_Box_x1]

		CMP	r2, #0				; was there a string?
		ADDNE	r4, r4, #36			; add in height of string
		MOVNE	r0, #-16
		MOVEQ	r0, #0
		STR	r0, [r11, #IconBlock_create_block + Wimp_IconCreate_icon + Wimp_Icon_extent + OS_Box_y0]
		ADD	r0, r0, r4
		STR	r0, [r11, #IconBlock_create_block + Wimp_IconCreate_icon + Wimp_Icon_extent + OS_Box_y1]

		MOV	r0, r7
		BL	strlen1
		ADD	r0, r0, #1			; +s
		BL	malloc
		BVS	error$l
		MOV	r2, r0
		MOV	r1, r2
		MOV	r0, #'s'			; write s
		STRB	r0, [r1], #1
		MOV	r0, r7				; copy sprite name on
		BL	strcpy
		STR	r2, [r11, #IconBlock_create_block + Wimp_IconCreate_icon + Wimp_Icon_data + Wimp_IconData_indirected_text_and_sprite_validation]
		STR	r2, [r11, #IconBlock_validation]
		MOV	r0, #-1
		STR	r2, [r11, #IconBlock_handle]	; show that the icon hasn'e been created yet

exit$l		MOV	r0, #$Name._PollWord_CreateIcon
		BL	ORR_PollWord

		MOV	r0, r11				; r0  menu block
		ClearV
error$l		EXIT					; exit with or without error


;*******************************************************************************
;----f- Director.s.Icons.IconBlockDestroy
; Name
;   IconBlockDestroy
;
; Purpose
;   This destroys a icon block and unlinks it from the list
;   It releases any memory attached also
;
; Entry
;   r0  menu block
;   r1  previous menu block
;
; Exit
;   none
;------
;*******************************************************************************


IconBlockDestroy	ROUTINE	"r0-r3", EXPORT

		MOV	r3, r0				; r3  IconBlock
		UnLink	r3, r1, lr			; unlink the IconBlock

		LDR	r0, [r3, #IconBlock_name]	; free attached items
		BL	free
		LDR	r0, [r3, #IconBlock_text]
		BL	free
		LDR	r0, [r3, #IconBlock_textdetail]
		BL	free
		LDR	r0, [r3, #IconBlock_validation]
		BL	free
		LDR	r0, [r3, #IconBlock_adjust]
		BL	free
		LDR	r0, [r3, #IconBlock_menu]
		BL	free
		LDR	r0, [r3, #IconBlock_select]
		BL	free
		LDR	r0, [r3, #IconBlock_dragto]
		BL	free
		LDR	r0, [r3, #IconBlock_dragfrom]
		BL	free

		MOV	r0, r3				; free block
		BL	free

		EXIT


;*******************************************************************************
;----f- Director.s.Icons.IconBlockListDestroy
; Name
;   IconBlockListDestroy
;
; Purpose
;   This destroys all the icon blocks in the list
;
; Entry
;   none
;
; Exit
;   none
;------
;*******************************************************************************


IconBlockListDestroy	ROUTINE	"r0-r3", EXPORT

		ADR	r0, IconsAnchor
loop$l		ListWalkForDestruction	r0, r1, r2
		BEQ	exitloop$l
		BL	IconBlockDestroy
		B	loop$l

exitloop$l	EXIT


;*******************************************************************************
;----f- Director.s.Icons.IconBlockListCreateIcons
; Name
;   IconBlockListCreateIcons
;
; Purpose
;   This creates any uncreated icons in the list and
;   destroys any to be destroyed.
;   It is called when the appropriate bit in the PollWord is set.
;
; Entry
;   none
;
; Exit
;   If an error occured:
;     r0 = pointer to valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


IconBlockListCreateIcons	ROUTINE_SF	"", EXPORT
delete_icon$l	#	8
		END_SF

		MOV	r0, #$Name._PollWord_CreateIcon
		BL	BIC_PollWord

		ADR	r11, IconsAnchor

loop$l		ListWalkForDestruction	r11, r10, r9
		BEQ	ok$l

		LDR	r0, [r11, #IconBlock_destroy]
		CMP	r0, #0
		BEQ	nodestroy$l

		LDR	r3, [r11, #IconBlock_handle]
		CMP	r3, #-1                  	; has the icon been given a handle yet?
		MOVNE	r2, #Wimp_IconBar
		ADRNE	r1, delete_icon$l
		STMNEIA	r1, {r2, r3}
		SWINE	XWimp_DeleteIcon		; delete the icon from the icon bar
		BVS	error$l

		MOV	r0, r11				; current
		MOV	r1, r10				; previous
		BL	IconBlockDestroy		; and destroy the block associated with it
		B	loop$l
nodestroy$l

		LDR	r0, [r11, #IconBlock_created]
		CMP	r0, #0
		BNE	nocreate$l
		MOV	r0, #1
		STR	r0, [r11, #IconBlock_created]

		LDR	r0, [r11, #IconBlock_priority]
		ADD	r1, r11, #IconBlock_create_block
		SWI	XWimp_CreateIcon
		BVS	error$l
		STR	r0, [r11, #IconBlock_handle]
nocreate$l

		MOV	r10, r11			; update previous
		B	loop$l

ok$l		ClearV
error$l		EXIT					; exit with or without error


;*******************************************************************************
;----f- Director.s.Icons.Convert64
; Name
;   Convert64
;
; Purpose
;   Converts a 64 bit file size (as returned by OS_FSControl 55) and
;   outputs a string in the form of 512Mb etc.
;
; Entry
;   r0 } 64-bit value { least significant word
;   r1 }              { most  significant word
;   r2  to output buffer
;
; Exit
;   r0, r1 r2 corrupted.
;------
;*******************************************************************************


Convert64	ROUTINE "r4-r7"

		CMP	r0, #0			; is r0 = 0
		CMPEQ	r1, #0			; is r1 = 0 as well
		BEQ	zero$l

;		MOV	r8, r2			; r8  output buffer
		MOV	r4, r0			; r4 = lsw of 64-bit value
		MOV	r5, r1			; r5 = msw of 64-bit value
		MOV	r6, #5			; r6 = Petabytes

		LDR	r7, =&FFE00000

while$l
		AND	r1, r5, r7		; r1 = msw AND &FFF00000
		CMP	r1, #0			; are the top 12 bits 0?
		BNE	exit$l			; so we have a value - lets print it
		CMP	r6, #0			; can we go any lower?
		BEQ	exit$l			; no, so print value

		MOV	r1, r5, LSL #&A		; r1 = msw << &A
		MOV	r0, r4, LSR #&16	; r0 = lsw >>> &16
		ADD	r1, r1, r0		; r1 = (msw << &A) + (lsw >>> &16)
		MOV	r0, r4, LSL #&A		; r0 = lsw << &A

		MOV	r4, r0			; lsw = r0	; store current values
		MOV	r5, r1			; msw = r1
		SUB	r6, r6, #1		; decrement suffix
		B	while$l

exit$l
		MOV	r0, r5, LSR #&12	; r0 = (msw >>> &12)
		MOV	r1, r2			; r1  output buffer
		MOV	r2, #8			; size of buffer
		SWI	XOS_ConvertInteger4	; convert number to string
		BVS	error$l
						; r1  to where to continue from
		CMP	r6, #0
		BEQ	nosuffix$l		; skip if there is no suffix to add

 		ADR	r2, suffix$l
 		LDRB	r0, [r2, r6]		; which suffix to use?
 		STRB	r0, [r1]!		; write it to the buffer

nosuffix$l
		MOV	r0, #0
		STRB	r0, [r1, #1]		; write null after it.
		ClearV

error$l		EXIT

suffix$l	DCB	" KMGTP"
		ALIGN

zero$l
		MOV	r0, #"0"
		STRB	r0, [r2]
 		MOV	r0, #0
 		STRB	r0, [r2, #1]		; write null after it.

		EXIT


;*******************************************************************************
;----f- Director.s.Icons.IconBlockListNull
; Name
;   IconBlockListNull
;
; Purpose
;   This updates any time/memory icons.
;   It is called when we get a Null event from Wimp_Poll.
;
; Entry
;   none
;
; Exit
;   If an error occured:
;     r0 = pointer to valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


IconBlockListNull	ROUTINE_SF	"", EXPORT
utc$l		#	OSWordReadClock_UTCBlock
		AlignSpace
state$l		#	Wimp_IconState
output$l	#	StringSize
		END_SF

		ADR	r11, IconsAnchor

loop$l		ListWalk	r11, lr
		BEQ	ok$l

		LDR	r3, [r11, #IconBlock_texttype]
		CMP	r3, #$Name._IconBlock_Text_BlankText
		BEQ	loop$l
		CMP	r3, #$Name._IconBlock_Text_FreeDisc
		BEQ	dofreedisc$l
		CMP	r3, #$Name._IconBlock_Text_FreeMem
		BEQ	dofreemem$l
		CMP	r3, #$Name._IconBlock_Text_Time
		BNE	loop$l

dotime$l
		LDR	r3, [r11, #IconBlock_textdetail] ; r3  format string
;		CMP	r3, #0
;		BEQ	loop$l

		MOV	r0, #OSWordReadClock_OpUTC
		STRB	r0, utc$l + OSWordReadClock_UTCBlock_op

		MOV	r0, #OSWord_ReadClock
		ADR	r1, utc$l
		SWI	XOS_Word
		BVS	error$l

		ADR	r0, utc$l
		ADR	r1, output$l
		MOV	r2, #StringSize			; size of buffer
		SWI	XOS_ConvertDateAndTime
		BVS	error$l
		B	updateicon$l

dofreedisc$l
;		LDR	r3, [r11, #IconBlock_textdetail] ; r3  format string
;		CMP	r3, #0
;		BEQ	loop$l

		MOV	r0, #OSFSControl_FreeSpace64	; = 55
		LDR	r1, [r11, #IconBlock_textdetail] ; r1  disc spec.
		SWI	XOS_FSControl
		BVC	dofreedisc2$l			; it executed OK. skip RISC OS 3.5 or earlier code

		MOV	r0, #OSFSControl_FreeSpace	; = 49
;		LDR	r1, [r11, #IconBlock_textdetail] ; r1  disc spec.
		SWI	XOS_FSControl
		BVS	error$l
		MOV	r1, #0

dofreedisc2$l
		LDR	r2, [r11, #IconBlock_textval1]	; does the existing lsw
		CMP	r0, r2				; = the current one
		LDREQ	r2, [r11, #IconBlock_textval1]	; and does the existing msw
		CMPEQ	r1, r2				; = the current one
		BEQ	loop$l				; if so, loop
		STR	r0, [r11, #IconBlock_textval1]	; store result
		STR	r1, [r11, #IconBlock_textval2]

		ADR	r2, output$l			;  output buffer
		BL	Convert64
		B	updateicon$l

dofreemem$l
		MOV	r0, #-1				; read current slot
		MOV	r1, #-1				; read next slot
		SWI	XWimp_SlotSize
		MOV	r0, r2				; r0 = size of freel pool
		LDR	r2, [r11, #IconBlock_textval1]	; does the existing free mem
		CMP	r0, r2				; = the current one
		BEQ	loop$l				; if so, loop
		STR	r0, [r11, #IconBlock_textval1]	; store result
		MOV	r1, #0

		ADR	r2, output$l			;  output buffer
		BL	Convert64

updateicon$l
		ADR	r0, output$l
		LDR	r1, [r11, #IconBlock_text]
		BL	strcmpi
		BEQ	loop$l				; continue round loop if not changed
		LDR	r2, [r1, #IconBlock_textsize]	; r2 = max charsblock 
		BL	strcpyl0			; write in new time string

		MOV	r2, #Wimp_IconBar
		LDR	r3, [r11, #IconBlock_handle]
		ADR	r1, state$l
		STMIA	r1, {r2, r3}
		SWI	XWimp_GetIconState		; get the position of the icon
		BVS	error$l

                ADR	r0, state$l + Wimp_IconState_icon + Wimp_Icon_extent
		LDMIA	r0, {r1, r2, r3}		; mix.x, min.y, max.x
		ADD	r4, r2, #Wimp_CharYSize		; max.y
		MOV	r0, #Wimp_IconBar
		SWI	XWimp_ForceRedraw		; force redraw the icon text only
		BVS	error$l

		B	loop$l

ok$l		ClearV
error$l		EXIT					; exit with or without error


;*******************************************************************************
;----f- Director.s.Icons.set_menu
; Name
;   set_menu
;
; Purpose
;   This duplicates a menu string if necessary and stores it
;
; Entry
;   r1  menu arg
;   r2  location to store menu
;
; Exit
;   r1  next arg
;   r2  next location
;------
;*******************************************************************************


set_menu	ROUTINE

		LDR	r0, [r1], #4
		BL	sort_out_gstrans
		CMP	r0, #0
		BEQ	none$l
		BL	strdup
		BVS	ErrorReturn
none$l		STR	r0, [r2], #4

		EXIT


;*******************************************************************************
;----f- Director.s.Icons.Star_DirectorIcons
; Name
;   Star_DirectorIcons
;
; Purpose
;   This creates a new iconbar icon.
;
; Entry
;   none
;
; Exit
;   none
;------
;*******************************************************************************


Help_$Name.Icon	FOREXPORT
		[	OSVersion = 310
		DCB	"Create a new icon bar icon with attached menus. "
		DCB	"The icon is referred to by the name of its sprite or "
		DCB	"the alias name if supplied.", 13
		|
		DCB	"Help_Director_Icon", 0
		]

Syntax_$Name.Icon	FOREXPORT
		[	OSVersion = 310
		DCB	"Syntax: *$Name.Icon <sprite> "
		DCB	"[-alias <name>] [-text <text>] [-left|-right] [-priority <priority>] "
		DCB	"[-time <format> | -free <drive spec> | -freemem] "
		DCB	"[-menu <menu>] [-select <menu>] [-adjust <menu>] "
		DCB	"[-dragto <menu>] [-dragfrom <path>|*<menu>] "
		DCB	"[-remove]", 0
		|
		DCB	"Syntax_DirectorIcon", 0
		]
		ALIGN


Args_$Name.Icon	DCB	"/g,text/g,alias/g,left/s,right/s,priority/e,"
		DCB	"time/g,free/g,freemem/s,"
		DCB	"adjust/g,menu/g,select/g,dragto/g,dragfrom/g,"
		DCB	"remove/s", 0
		ALIGN

Star_$Name.Icon	FOREXPORT
		LDR	wp, [r12]
Do$Name.Icon	SaveRegs
		ROUTINE_SF	NONE
scratch$l	#	0
arg_sprite$l	#	4
arg_text$l	#	4
arg_alias$l	#	4
arg_left$l	#	4
arg_right$l	#	4
arg_priority$l	#	4
arg_time$l	#	4
arg_free$l	#	4
arg_freemem$l	#	4

arg_adjust$l	#	4				; These
arg_menu$l	#	4				; must be in
arg_select$l	#	4				; this order
arg_dragto$l	#	4				; and
arg_dragfrom$l	#	4				; together

arg_remove$l	#	4
space$l		#	scratch_size - :INDEX: @
		END_SF

		MOV	r1, r0				; translate given string
		ADR	r0, Args_$Name.Icon
		ADR	r2, scratch$l
		MOV	r3, #scratch_size
		SWI	XOS_ReadArgs
		BVS	ErrorReturn

		LDR	r0, arg_sprite$l
		BL	sort_out_gstrans
		LDR	r0, arg_alias$l
		BL	sort_out_gstrans
		LDR	r0, arg_text$l
		BL	sort_out_gstrans
		LDR	r0, arg_time$l
		BL	sort_out_gstrans
		LDR	r0, arg_free$l
		BL	sort_out_gstrans
		;menus are done later

		LDR	r3, arg_left$l
		LDR	r4, arg_right$l
		CMP	r3, #0
		CMPNE	r4, #0
		BNE	not_left_and_right$l

		CMP	r4, #0
		MOVEQ	r3, #Wimp_IconBarLeftLowPriority ; default to left side
		MOVNE	r3, #Wimp_IconBarRightLowPriority ; r3 = handle

		LDR	r0, arg_priority$l
		CMP	r0, #0				; default priority is 0
		BLNE	read_eval
		MOV	r4, r0				; r4 = priority

		LDR	r1, arg_sprite$l
		CMP	r1, #0
		BEQ	must_supply_sprite$l		; r1  sprite

		LDR	r2, arg_text$l
		CMP	r2, #0
		LDREQ	r2, arg_time$l			; use time string as text if available
		CMPEQ	r2, #0
		ADREQ	r2, null_string$l		; r2  text

		LDR	lr, arg_remove$l		; send a 0 if we are deleting the icon
		TEQ	lr, #0
		MOVNE	r2, #0

		LDR	r0, arg_alias$l			; r0  name
		CMP	r0, #0
		MOVEQ	r0, r1				; name is sprite name if no alias supplied

		LDR	r5, arg_dragfrom$l		; if we want our icon draggable
		BL	IconBlockCreate
		BVS	ErrorReturn
		MOVS	r11, r0				; r11  IconBlock
		BEQ	exit$l				; r11 = 0 => no block created

;;;; could add time to set_menu (rename to set_string)
		MOV	r0, #$Name._IconBlock_Text_BlankText
		STR	r0, [r11, #IconBlock_texttype]

		LDR	r0, arg_time$l
		CMP	r0, #0
		BEQ	notime$l
		BL	strdup
		BVS	ErrorReturn
		STR	r0, [r11, #IconBlock_textdetail] ; time string
		MOV	r0, #$Name._IconBlock_Text_Time
		STR	r0, [r11, #IconBlock_texttype]

notime$l
		LDR	r0, arg_free$l
		CMP	r0, #0
                BEQ	nofreedisc$l
		BL	strdup
		BVS	ErrorReturn
		STR	r0, [r11, #IconBlock_textdetail] ; drive spec
		MOV	r0, #$Name._IconBlock_Text_FreeDisc
		STR	r0, [r11, #IconBlock_texttype]

nofreedisc$l
		LDR	r0, arg_freemem$l
		CMP	r0, #0
                BEQ	nofreemem$l
		MOV	r0, #$Name._IconBlock_Text_FreeMem
		STR	r0, [r11, #IconBlock_texttype]

nofreemem$l
		ADR	r1, arg_adjust$l		; pointer to first argument
		ADD	r2, r11, #IconBlock_adjust
		BL	set_menu			; adjust
		BL	set_menu			; menu
		BL	set_menu			; select
		BL	set_menu			; dragto
		BL	set_menu			; dragfrom

exit$l		B	NormalReturn

must_supply_sprite$l	ReportErrorMT	"$NoSprite", Error_NoSprite
not_left_and_right$l	ReportErrorMT	"$NotLeftAndRight", Error_NotLeftAndRight
null_string$l		EQUS0A		""
		ALIGN


;*******************************************************************************
;----f- Director.s.Icons.IconBarClick
; Name
;   IconBarClick
;
; Purpose
;   This is called when a click on an icon bar icon is detected
;
; Entry
;   r0 = icon number
;   r1 = buttons
;   r11  Wimp_Pointer
;
; Exit
;   If an error occured:
;     r0 = pointer to valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


IconBarClick	ROUTINE	"", EXPORT

		; First find the icon we are talking about

		ADR	r10, IconsAnchor		; r10  IconBlock
find$l		ListWalk	r10, lr
		BEQ	notfound$l
		LDR	lr, [r10, #IconBlock_handle]
		CMP	r0, lr
		BNE	find$l

		TST	r1, #Wimp_DragAdjust + Wimp_DragSelect
		BEQ	nodrag$l
		MOV	r1, r0				; icon handle
		MOV	r0, #Wimp_IconBar		; window handle
		LDR	r2, [r10, #IconBlock_dragfrom]	; menu to open
		BL	StartDrag
		ClearV
		EXIT

nodrag$l	TST	r1, #Wimp_ClickAdjust
		LDRNE	r0, [r10, #IconBlock_adjust]

		TST	r1, #Wimp_ClickSelect
		LDRNE	r0, [r10, #IconBlock_select]

		TST	r1, #Wimp_ClickMenu
		LDRNE	r0, [r10, #IconBlock_menu]

		TST	r1, #&1000			; drag to
		LDRNE	r0, [r10, #IconBlock_dragto]

		CMP	r0, #0
		BEQ	ok$l				; no menu ignore

		BL	RunMenu
		BVS	error$l

ok$l		ClearV
error$l		EXIT

notfound$l	ADR	r0, notfoundmsg$l
		BL	MessageErrorLookup
		EXIT

notfoundmsg$l	ERROR	"$IconNotFound", Error_IconNotFound

;*******************************************************************************

		END
