שתשת                                        	incdir	"include:"
	include	"exec/execbase.i"
	include	"libraries/gadtools.i"
	include	"libraries/gadutil.i"
	include	"libraries/gadutil_lib.i"
	include	"LVOs.i"

start:
	move.l	_AbsExecBase.w,a6
	lea.l	libdatas(pc),a2		; Open all needed libraries
	move.w	(a2)+,d2
.openlib:
	move.l	(a2),a1			; Get library name pointer
	moveq.l	#36,d0
	CallLib	OpenLibrary
	move.l	d0,(a2)+		; Save base address
	dbeq	d2,.openlib		; Continue until done or error
	beq.s	.closelibs

	bsr.w	TestProgram

.closelibs:
	lea.l	libdatas(pc),a2		; Close all opened libraries
	move.w	(a2)+,d2
.closelib:
	move.l	(a2)+,d0		; Get base address for library
	beq.s	.closedone
	move.l	d0,a1
	CallLib	CloseLibrary
	dbra	d2,.closelib
.closedone:
	moveq.l	#0,d0
	rts

;----------------------------- library data ----------------------------------
libdatas:	dc.w	5-1

dosbase:	dc.l	dosname
GUtilBase:	dc.l	gadutilname
GfxBase:	dc.l	gfxname
IntuiBase:	dc.l	intuiname
UtilBase:	dc.l	utilname

dosname:	dc.b	'dos.library',0
gadutilname:	dc.b	'gadutil.library',0
gfxname:	dc.b	'graphics.library',0
intuiname:	dc.b	'intuition.library',0
utilname:	dc.b	'utility.library',0
	even

;------------------------------ The test program -----------------------------

TestProgram:
	movem.l	d0-a6,-(sp)
;	move.l	LibList(a6),LVGTTags+4 ; Set list pointer for ListView gadget
	move.l	GUtilBase(pc),a6

	move.l	a6,a0
	moveq.l	#GADUTIL_VER,d0		; Check for latest version of GadUtil
	moveq.l	#GADUTIL_REV,d1
	CallLib	GU_CheckVersion
	beq.w	.wrongver
.verok:	
	lea.l	mybss,a5		; Get pointer to BSS
	suba.l	a0,a0			; Lock the default public screen
	CallLib	LockPubScreen,IntuiBase(pc)
	move.l	d0,screen(a5)
	beq.w	.noscreen

	lea.l	glist(pc),a0		; Pointer to gadget list pointer
	lea.l	gadgets(pc),a1		; LayoutGadget structures
	move.l	d0,a2			; Screen pointer
	lea.l	LayoutTags(pc),a3	; Tags for LayoutGadgetsA

	move.l	sc_Font(a2),textattr	; Use the screen's font
	move.l	GUtilBase(pc),a6
	CallLib	GU_LayoutGadgetsA	; Lay out the gadgets
	move.l	a0,priv_info(a5)	; Save pointer to PrivateInfo
	beq.w	.unlocksc

	lea.l	window_tags(pc),a1	; Get window tags

	move.l	screen(a5),a0		; WA_Top = screen->Font->ta_YSize + 3
	move.l	sc_Font(a0),a0
	moveq.l	#0,d0
	move.w	ta_YSize(a0),d0
	addq.w	#3,d0
	move.l	d0,WinTop(a1)
	
	move.l	farright(pc),d0		; WA_InnerWidth = farright+LEFT_OFFSET
	addq.l	#LEFT_OFFSET,d0
	move.l	d0,InnerWidth(a1)

	move.l	farbottom(pc),d0	; WA_InnerHeight = farbotton+TOP_OFFSET
	addq.l	#TOP_OFFSET*2,d0
	move.l	d0,InnerHeight(a1)

	suba.l	a0,a0			; Open the window
	CallLib	OpenWindowTagList,IntuiBase(pc)
	move.l	d0,main_win(a5)
	beq.s	.freegads		; Error opening the window

	move.l	d0,a0			; Refresh everything in the window
	move.l	priv_info(a5),a1
	CallLib	GU_RefreshWindow,GUtilBase(pc)

	move.l	main_win(a5),a0
	bsr.b	process_window_events	; Wait for and process all events
	
;------------------------------- Exit routines -------------------------------
.closewin:
	move.l	main_win(a5),a0
	CallLib	CloseWindow,IntuiBase(pc)	
.freegads:
	move.l	priv_info(a5),a0	; Free all gadgets
	move.l	GUtilBase(pc),a6
	CallLib	GU_FreeLayoutGadgets
.unlocksc:
	suba.l	a0,a0			; No name pointer
	move.l	screen(a5),a1		; Pointer to the locked screen
	CallLib	UnlockPubScreen,IntuiBase(pc)
.noscreen:
.wrongver:
	movem.l	(sp)+,d0-a6
	rts

;------------------ Wait for and process window events -----------------------
; Inputs: A0 - Window pointer
;
process_window_events:
	movem.l	d0-a6,-(sp)
	lea.l	MyList(a5),a0		; Initialize list structure
	CallLib	GU_NewList,GUtilBase(pc)

	moveq.l	#FILENAME_GAD,d0	; Get address of filename string gad
	lea.l	gadgets(pc),a0
	CallLib	GU_GetGadgetPtr
	beq.w	.Exit			; Don't continue if no gadget
	move.l	d0,a0
	move.l	gg_SpecialInfo(a0),a0	; Get gadget->SpecialInfo->Buffer
	move.l	si_Buffer(a0),a0
	move.l	a0,StringBuff(a5)
	move.w	#-1,selected(a5)	; Clear selected item
.WaitEvent:
	move.l	_AbsExecBase.w,a6
	move.l	32(sp),a0		; Get pointer to window
	move.l	wd_UserPort(a0),a0	; Get UserPort
	CallLib	WaitPort		; Wait for a message
.GetEvent:
	move.l	32(sp),a0		; Get window pointer
	bsr.w	GetIMessage		; Get the message and process REFRESH
	bmi.s	.GetEvent		; Get next event if IDCMP_REFRESHWIN
	beq.s	.WaitEvent		; Continue waiting if no message

.checkgadup:
	cmp.l	#IDCMP_GADGETUP,d3	; Any gadget released ?
	bne.w	.CheckClose		; Nope!
	move.w	gg_GadgetID(a2),d1	; Get GadgetID
	bchg	#1,$bfe001

	cmp.w	#LISTVIEW_GAD,d1	; Selected any item from list ?
	bne.b	.checkname
	move.w	d2,selected(a5)		; Save selected node number
	bra.b	.GetEvent
	
.checkname:
	cmp.w	#FILENAME_GAD,d1	; Button 1 pressed ?
	bne.s	.CheckNext		; Nope! Check more gadgets

	move.l	lvgad(pc),d0		; Get pointer to the ListView gadget
	move.l	d0,d2			; Store gadget pointer

	move.l	main_win(a5),a0		; Detach the list from the ListView
	CallLib	GU_DetachList

	move.l	d2,d0			; Get gadget pointer
	move.l	StringBuff(a5),a0	; Get string to add
	lea.l	MyList(a5),a1		; Get list pointer
	CallLib	GU_AddTail

	move.l	d2,d0			; Get gadget pointer
	move.l	main_win(a5),a0
	lea.l	MyList(a5),a1
	CallLib	GU_AttachList		; Put back the list in the listview
	
.nogadget:
	bra.b	.GetEvent
.CheckNext:
	cmp.w	#UP_GAD,d1		; UP gadget ?
	beq.b	.nodeup
	cmp.w	#DOWN_GAD,d1		; DOWN gadget ?
	bne.w	.CheckFile
.nodeup:
	move.w	d1,d2			; Save gadget ID
	
	cmp.w	#-1,selected(a5)	; Check for no selected item
	beq.b	.nonode
	
	lea.l	MyList(a5),a2		; Get list pointer
	move.l	a2,a0
	move.w	selected(a5),d0		; Get the selected node number
	bsr.w	GU_FindNode		; Find the node
	beq.b	.nonode
	move.l	d0,a3			; Save node pointer

	move.l	lvgad(pc),d0		; Get pointer to the ListView gadget
	move.l	main_win(a5),a0		; Detach the list from the ListView
	CallLib	GU_DetachList

	move.l	a3,a0			; Node to move
	move.l	a2,a1			; The node's list
	cmp.w	#DOWN_GAD,d2		; Check for down gadget
	beq.b	.nodedown
	bsr.w	GU_NodeUp		; Move the node one step up
	beq.b	.movedone		; Don't move it down again
	subq.w	#1,selected(a5)
	bra.b	.movedone
.nodedown:
	bsr.w	GU_NodeDown		; Move the node one step up
	beq.b	.movedone
	addq.w	#1,selected(a5)
.movedone:
	move.l	lvgad(pc),d0		; Put back the list in the listview
	move.l	main_win(a5),a0
	lea.l	MyList(a5),a1
	CallLib	GU_AttachList,GUtilBase(pc)

	move.l	lvgad(pc),a0
	move.l	main_win(a5),a1
	suba.l	a2,a2
	clr.l	-(sp)			; TAG_DONE
	moveq.l	#0,d0
	move.w	selected(a5),d0
	move.l	d0,-(sp)		; New selected item number
	move.l	#GTLV_Selected,-(sp)
	move.l	sp,a3
	CallLib	GU_SetGadgetAttrsA
	lea.l	12(sp),sp		; Adjust stack
.nonode:
	bra.w	.GetEvent


.CheckFile:
	cmp.w	#FILE_GAD,d1		; FILE_KIND gadget ?
	bne.w	.GetEvent

	move.l	lvgad(pc),d0		; Get listview gadget
	move.l	main_win(a5),a0
	lea.l	MyList(a5),a1
	CallLib	GU_ClearList
	move.w	#-1,selected(a5)	; Clear selected item
	bra.w	.nogadget

.CheckClose:
	cmp.l	#IDCMP_CLOSEWINDOW,d3	; Close gadget pressed ?
	bne.w	.GetEvent		; Nope! Get next message
.Exit
	movem.l	(sp)+,d0-a6
	rts

;---------------------- Get a message from the window ------------------------
; Input:
;	A0 = pointer to window
; Output:
;	A2 = Message IAddress
;	D2 = Message Code
;	D3 = Message Class
; Flags:
;	 Z =  1 for no message (use BEQ)
;	 Z =  0 for a valid message other than IDCMP_REFRESHWINDOW
;	 N =  1 for a IDCMP_REFRESHWINDOW message (use BMI)
;
;------------------------------------------------------------------------------
GetIMessage:
	move.l	a0,-(sp)		; Save window pointer
	move.l	wd_UserPort(a0),a0	; Get UserPort

	CallLib	GU_GetIMsg,GUtilBase(pc)
	beq.s	.NoMessage		; No message - return
	move.l	d0,a1
	move.l	im_IAddress(a1),a2	; IAddress to A2
	moveq.l	#0,d2			; Clear code longword
	move.w	im_Code(a1),d2		; Code to D2
	move.l	im_Class(a1),d3		; Class to D3
	move.l	im_MouseX(a1),msgcoords(a5)
	CallLib	GU_ReplyIMsg		; Reply the message

	cmp.l	#IDCMP_REFRESHWINDOW,d3	; Do window need to be refreshed ?
	bne.b	.NoMessage		; Nope! Check next message!
	move.l	(sp),a0
	CallLib	GU_BeginRefresh		; Start refreshing window
	move.l	(sp),a0
	moveq.l	#TRUE,d0
	CallLib	GU_EndRefresh		; Refreshing done
	moveq.l	#-1,d0			; Set N flag
.NoMessage:
	move.l	(sp)+,a0
	rts

******************* Find a specified node number in a list *******************
*
* Inputs:
*	A0 - struct List *
*	D0 - Number of the node to find (counting from 0)
*
* Result:
*   D0, A0 - Address to the node structure
*   SR (Z) - 0 for success, 1 for failure
*
******************************************************************************
GU_FindNode:
	move.l	(a0),d1		; Get pointer to first node
.findnode:
	move.l	d1,a0
	move.l	(a0),d1		; Check for end of list
	dbeq	d0,.findnode
	beq.b	.endoflist	; Not enough nodes in the list
	move.l	a0,d0		; Return pointer to node
	rts
.endoflist:
	moveq.l	#0,d0
	rts	

****************** Move a node in a list one step up/down ********************
*
* Inputs:
*	A0 - The node to move
*	A1 - The list that the node is a part of
*
* Result:
*	D0 - TRUE if the node could be moved, else FALSE
*   SR (Z) - 0 if node could be moved, else 1
*
******************************************************************************
GU_NodeDown:
	moveq.l	#FALSE,d0		; Return FALSE if at end of list
	move.l	(a0),a0			; Get next node
	tst.l	(a0)			; Check for end of list
	bne.b	GU_NodeUp		; Move next node up to move this one
	rts				;  down
GU_NodeUp:		
	movem.l	a0-a2,-(sp)
	moveq.l	#FALSE,d0		; Return FALSE if at top of list
	move.l	LN_PRED(a0),d1		; Get previous node
	cmp.l	4(sp),d1		; Check if at top of list
	beq.b	.nonode			; Can't move node higher!

	move.l	d1,a0
	move.l	LN_PRED(a0),a2		; Save node to insert other after

	move.l	(sp),a1			; Remove the node to move
	CallLib	Remove,_AbsExecBase.w

	move.l	4(sp),a0		; Get list to insert node in
	move.l	(sp),a1			; Node to insert
	CallLib	Insert
	moveq.l	#TRUE,d0
.nonode:	
	movem.l	(sp)+,a0-a2
	rts

;------------------------ Datas for LayoutGadgetsA ---------------------------
LayoutTags:
	dc.l	GU_RightExtreme,	farright
	dc.l	GU_LowerExtreme,	farbottom
	dc.l	GU_MinimumIDCMP,	MinimumIDCMP
ta:	dc.l	GU_DefTextAttr,		0
cat:	dc.l	GU_Catalog,		0
	dc.l	TAG_DONE

textattr:	equ	ta+4	

farright:	dc.l	0
farbottom:	dc.l	0

FILENAME_GAD:	equ	1
LISTVIEW_GAD:	equ	2
FILE_GAD:	equ	3
SHOWSEL_GAD:	equ	4
BOXAROUND_GAD:	equ	5
UP_GAD:		equ	6
DOWN_GAD:	equ	7

addtxt:		dc.b	'_Add',0
uptxt:		dc.b	'_Up',0
downtxt:	dc.b	'_Down',0

filenametxt:	dc.b	'_Filename:',0
listviewtxt:	dc.b	'_Select an item:',0

	even

;------------------------------- Window datas --------------------------------

INTUIIDCMP:	equ	IDCMP_REFRESHWINDOW!IDCMP_CLOSEWINDOW
WINGADS:	equ	WFLG_DRAGBAR!WFLG_DEPTHGADGET!WFLG_CLOSEGADGET

window_tags:
	dc.l	WA_Left,	0,	WA_Top
WinTop:	equ	*-window_tags
	dc.l	0,		WA_InnerWidth
InnerWidth:EQU	*-window_tags
	dc.l	0,		WA_InnerHeight
InnerHeight:EQU	*-window_tags
	dc.l	0,		WA_IDCMP,INTUIIDCMP
MinimumIDCMP:	equ	*-4
	dc.l	WA_Flags,	WINGADS!WFLG_ACTIVATE!WFLG_SMART_REFRESH!WFLG_REPORTMOUSE
	dc.l	WA_RMBTrap,	TRUE
	dc.l	WA_Gadgets
glist:	dc.l	0
	dc.l	WA_Title,WinTitle
emptytag:
	dc.l	TAG_DONE

mytextattr:	dc.l	fontname
		dc.w	6
		dc.b	0
		dc.b	FPF_DISKFONT

WinTitle:	dc.b	"GadUtil library test",0
fontname:	dc.b	"mini6.font",0
bordertxt:	dc.b	"Test all gadgets",0
	even

;----------------------------- Gadget datas ----------------------------------
LEFT_OFFSET:	equ	6
TOP_OFFSET:	equ	3

StdGTTags:
	dc.l	GT_Underscore,	'_',		TAG_DONE
	
BoxAround:
;	dc.l	GU_TextAttr,	mytextattr
	dc.l	GU_GadgetKind,	BEVELBOX_KIND,	GU_Left,	LEFT_OFFSET
	dc.l	GU_Top,		TOP_OFFSET,	GU_AlignBottom,	LISTVIEW_GAD
	dc.l	GU_AddHeiLines,	1,		GU_AlignRight,	LISTVIEW_GAD
	dc.l	GU_AddWidth,	LEFT_OFFSET*2,	GU_GadgetText,	bordertxt
	dc.l	GUBB_FrameType,	BFT_RIDGE,	GUBB_Recessed,	TRUE
	dc.l	GUBB_TextPen,	SHINEPEN,	GUBB_Flags,	BB_TEXT_IN
	dc.l	TAG_DONE

UpGad:
	dc.l	GU_GadgetKind,	BUTTON_KIND,	GU_GadgetText,	uptxt
	dc.l	GU_Left,	LEFT_OFFSET*3,	GU_Top,		TOP_OFFSET
	dc.l	GU_AdjustTop,	0
	dc.l	GU_Columns,	10,		GU_DupeHeight,	FILENAME_GAD
StdButtonTags:
	dc.l	GU_Flags,	PLACETEXT_IN
StdGadTags:
	dc.l	GU_LabelHotkey,	TRUE
	dc.l	TAG_DONE

DownGad:
	dc.l	GU_GadgetKind,	BUTTON_KIND,	GU_GadgetText,	downtxt
	dc.l	GU_AlignLeft,	UP_GAD,		GU_TopRel,	UP_GAD
	dc.l	GU_AddTop,	1
	dc.l	GU_DupeWidth,	UP_GAD,		GU_DupeHeight,	UP_GAD
	dc.l	TAG_MORE,	StdButtonTags

FileNameGad:
	dc.l	GU_GadgetKind,	STRING_KIND,	GU_LeftRel,	UP_GAD
	dc.l	GU_GadgetText,	filenametxt,	GU_AutoHeight,	4
	dc.l	GU_Flags,	PLACETEXT_LEFT,	GU_AdjustLeft,	10
	dc.l	GU_Hotkey,	"F",		GU_HotkeyCase,	TRUE
	dc.l	GU_Columns,	40,		TAG_MORE,	StdGadTags

ListViewGad:
	dc.l	GU_GadgetKind,	LISTVIEW_KIND,	GU_TopRel,	UP_GAD
	dc.l	GU_HeightFactor,14,		GU_GadgetText,	listviewtxt
	dc.l	GU_AlignLeft,	UP_GAD,	GU_AlignRight,	FILE_GAD
	dc.l	GU_AdjustTop,	INTERHEIGHT*2
	dc.l	GU_Flags,	PLACETEXT_ABOVE!NG_HIGHLABEL
	dc.l	TAG_MORE,	StdGadTags

LVGTTags:
	dc.l	GTLV_Labels,	NULL,		GTLV_ShowSelected,	-1
	dc.l	TAG_MORE,	StdGTTags

ShowSelGad:
	dc.l	GU_GadgetKind,	STRING_KIND,	GU_DupeWidth,	LISTVIEW_GAD
	dc.l	GU_AlignLeft,	LISTVIEW_GAD,	GU_AutoHeight,	4
	dc.l	GU_GadgetText,	NULL,		TAG_DONE

FileGad:
	dc.l	GU_GadgetKind,	FILE_KIND,	GU_GadgetText,	NULL
	dc.l	GU_AlignTop,	FILENAME_GAD,	GU_LeftRel,	FILENAME_GAD
	dc.l	GU_DupeHeight,	FILENAME_GAD,	GU_Width,	20
	dc.l	GU_Hotkey,	'f',		GU_HotkeyCase,	TRUE
	dc.l	GU_Flags,	PLACETEXT_LEFT
	dc.l	TAG_DONE

gadgets:
		GADGET	BOXAROUND_GAD,	BoxAround,	NULL
		GADGET	UP_GAD,		UpGad,		StdGTTags
		GADGET	DOWN_GAD,	DownGad,	StdGTTags
		GADGET	FILENAME_GAD,	FileNameGad,	StdGTTags
;		GADGET	SHOWSEL_GAD,	ShowSelGad,	StdGTTags
		GADGET	LISTVIEW_GAD,	ListViewGad,	LVGTTags
lvgad:		equ	*-4
		GADGET	FILE_GAD,	FileGad,	NULL
		GADGET	-1,NULL,NULL

;------------------------------- BSS ----------------------------

	STRUCTURE	MyBSS,0
		LONG	StringBuff
		LONG	screen
		LONG	main_win
		LONG	priv_info
		LONG	menustrip
		LONG	msgcoords
		STRUCT	MyList,MLH_SIZE
		WORD	selected
	LABEL	MyBSS_SIZEOF

	SECTION	TestProg,BSS
mybss:	ds.b	MyBSS_SIZEOF

