; WhatIs v1.0: Smaller and better version of FileID.library 'WhatIs'
; by Kyzer/CSG
; $VER: WhatIs 1.0 (13.07.98)
;
	incdir	include:
	include	lvo/exec_lib.i
	include	lvo/dos_lib.i
	include	lvo/fileid_lib.i
	include	exec/libraries.i
	include	libraries/FileID.i
	include	dos/dos.i
	include	dos/dosasl.i

AP_STRLEN	equ	256	; maximum length of name
ERROR_NONE	equ	0

ficall	MACRO
	exg.l	a4,a6
	jsr	_LVOFI\1(a6)
	exg.l	a4,a6
	ENDM

error	MACRO
	IFLT	ERROR_\1 - 127
	moveq	#ERROR_\1,d1
	ELSE
	move.l	#ERROR_\1,d1
	ENDC
	jsr	_LVOSetIoErr(a6)
	ENDM

stackf	MACRO	; stack_symbol, stackelement_symbol, [size=4]
	IFND	\1
\1	set	0
	ENDC
	IFGE	NARG-3
\1	set	\1-\3
	ELSE
\1	set	\1-4
	ENDC
\2	equ	\1
	ENDM

	stackf	stk, files		; filled in by ReadArgs()
	stackf	stk, rdargs
	stackf	stk, finf
args=files

	stackf	stk, desc		; ^ and description
	stackf	stk, packmode		; | and ansi code if packed
	stackf	stk, size		; | and size
	stackf	stk, name		; | name of file
printargs=name

	stackf	stk, ap_name, AP_STRLEN	; ^ followed by room for filename
	stackf	stk, ap, ap_SIZEOF	; | AnchorPath struct

	link	a5,#stk			; A5 = variables

	move.l	4.w,a6
	lea	fidname(pc),a1
	moveq	#2,d0
	jsr	_LVOOpenLibrary(a6)
	tst.l	d0
	beq.s	.nofid
	move.l	d0,a4			; A4 = FIDBase
	move.l	FI_DosBase(a4),a6
	cmp.w	#37,LIB_VERSION(a6)	; A6 = DOSBase
	bcs.s	.nodos

	lea	templat(pc),a0
	move.l	a0,d1
	lea	args(a5),a0
	move.l	a0,d2
	clr.l	(a0)
	moveq	#0,d3
	jsr	_LVOReadArgs(a6)
	move.l	d0,rdargs(a5)
	beq.s	.noargs

	ficall	AllocFileInfo
	move.l	d0,finf(a5)
	beq.s	.nomem

	move.l	files(a5),d1
	beq.s	.defdir		; do simply '#?' for no args
	move.l	d1,a2		; otherwise go through each arg
.again	move.l	(a2)+,d1
	beq.s	.done
	bsr.s	ListFiles
	bra.s	.again

.done	move.l	finf(a5),a1
	ficall	FreeFileInfo(a6)
	bra.s	.ok
.nomem	error	NO_FREE_STORE
.ok	move.l	rdargs(a5),d1
	jsr	_LVOFreeArgs(a6)
.noargs	jsr	_LVOIoErr(a6)	; print any error
	move.l	d0,d1
	moveq	#0,d2
	jsr	_LVOPrintFault(a6)
.nodos	move.l	a4,a1
	move.l	4.w,a6
	jsr	_LVOCloseLibrary(a6)
.nofid	unlk	a5
	moveq	#0,d0
	rts

.defdir	lea	pattern(pc),a0	; called when run with no arguments
	move.l	a0,d1		; do 'WhatIs #?'
	bsr.s	ListFiles
	bra.s	.done

; D1 = pattern/file
ListFiles
	lea	ap(a5),a3			; A3 = AnchorPath
	move.l	a3,a0
	move.w	#fib_SIZEOF+AP_STRLEN-1,d0
.clr	clr.b	(a0)+
	dbra	d0,.clr
	move.l	#SIGBREAKF_CTRL_C,ap_BreakBits(a3)
	move.w	#AP_STRLEN,ap_Strlen(a3)

	move.l	a3,d2
	jsr	_LVOMatchFirst(a6)

	tst.l	d0
	bne.s	.done
	tst.l	ap_Info+fib_DirEntryType(a3)
	blt.s	.notdir				; if first entry is a directory
	bset.b	#APB_DODIR,ap_Flags(a3)		; then show its contents
	bra.s	.skip
.notdir

.again	tst.l	d0
	bne.s	.done

	btst.b	#APB_DIDDIR,ap_Flags(a3)	; set when finished reading
	bne.s	.done				; the DODIR directory

	tst.l	ap_Info+fib_DirEntryType(a3)
	bgt.s	.skip				; avoid listing directories

;----------
	move.l	ap_Info+fib_Size(a3),size(a5)	; setup size
	lea	ap_Info+fib_FileName(a3),a0
	move.l	a0,name(a5)			; setup name

	lea	ap_name(a5),a0
	move.l	a0,d1
	move.l	finf(a5),a1
	ficall	IdentifyFromName(a6)
	move.l	(a1)+,desc(a5)			; setup dest

	move.l	(a1)+,d0	; gets ID and GlobalFileClass
	lea	unpack(pc),a0
	move.l	a0,packmode(a5)
        btst	#FIGFCB_PACKED,d0
	beq.s	.nopack
	lea	packed(pc),a0
	move.l	a0,packmode(a5)			; setup packmode

.nopack	lea	print(pc),a0
	move.l	a0,d1
	lea	printargs(a5),a0
	move.l	a0,d2
	jsr	_LVOVPrintf(a6)
;----------

.skip	move.l	a3,d1
	jsr	_LVOMatchNext(a6)
	bra.s	.again

.done	cmp.w	#ERROR_NO_MORE_ENTRIES,d0
	bne.s	.err
	error	NONE
.err	move.l	a3,d1
	jmp	_LVOMatchEnd(a6)

fidname	FILEIDNAME
templat	dc.b	'/M',0

print	dc.b	'%-34s%9ld %s%s',$9b,'0m',10,0
packed	dc.b	$9B,'1m'
pattern
unpack	dc.b	0
