; PUBLIC - SET AND CLEAR PUBLIC FILE ATTRIBUTE 3/6/85


FALSE		EQU	0
TRUE		EQU	NOT FALSE

LISTPUBBIT	EQU	0
MAKPUBBIT	EQU	1
FENCE		EQU	'|'

NULL		EQU	0
BELL		EQU	7
CR		EQU	0DH
LF		EQU	0AH
ESC		EQU	1BH
SPACE		EQU	' '
DEL		EQU	7FH

drivefn		equ	14
openfn		equ	15
closefn		equ	16
srchfstfn	equ	17
srchnxtfn	equ	18
deletefn	equ	19
readfn		equ	20
writefn		equ	21
makefn		equ	22
renamefn	equ	23
logvecfn	equ	24
curdskfn	equ	25
dmafn		equ	26
setattrfn	equ	30
getaddrfn	equ	31
userfn		equ	32
readrfn		equ	33
writerfn	equ	34
sizefn		equ	35

reccnt		equ	15
currec		equ	32
r0		equ	33
tbuff		equ	80h
fcb		equ	5ch
fcb2		equ	fcb+16

boot		equ	0000h
bdos		equ	0005h
bdoslen		equ	0e00h

	org	100h
top:
	jmp	start

usage:
	db	CR,LF,'Usage:  PUBLIC [d:]           -- list PUBLIC files [on d:]'
	db	CR,LF,'        PUBLIC [d:]file.ext   -- make file PUBLIC'
	db	CR,LF,'        PUBLIC [d:]file.ext X -- make file private'
	db	CR,LF,'$'
header:
	db	CR,LF,'The currently PUBLIC files are:',CR,LF,'$'
tomsg:
	db	'  set to ==> $'
pubnam:
	db	'PUBLIC   $'
privnam:
	db	'PRIVATE  $'
ismsg:
	db	'  ==> is already $'
nopubs:
	db	CR,LF,'(There are no PUBLIC files.)$'

multimsg:
	db	CR,LF,LF,BELL,"*** Multiple copies, can't change!$"
nonemsg:
	db	CR,LF,BELL,'*** No File!$'
cantmsg:
	db	CR,LF,BELL,"*** Can't make file $"

start:
	sspd	ustack
	lxi	sp,stack

	lxi	h,fcb+1
	mov	a,m
	cpi	SPACE
	lxi	h,flags
	res	LISTPUBBIT,m
	jrnz	setup

	bset	LISTPUBBIT,m
	lxi	d,header
	call	printde
setup:
	mvi	c,dmafn		; set directory buffer
	lxi	d,buf
	call	bdos

	mvi	c,curdskfn	; save current drive
	call	bdos
	sta	drive
	sta	udrive

	lda	fcb		; check for specified drive
	ora	a
	jrz	savusr

	dcr	a
	sta	drive		; login specified drive
	mov	e,a
	mvi	c,drivefn
	call	bdos
savusr:
	mvi	c,userfn	; save user number
	lxi	d,0ffh
	call	bdos
	sta	uuser

	mvi	c,getaddrfn	; get extent mask for this drive
	call	bdos
	inx	h
	inx	h
	inx	h
	inx	h
	mov	a,m
	sta	EXTMASK

	xra	a
	sta	count

	lda	fcb2+1
	cpi	'X'
	lxi	h,flags
	res	MAKPUBBIT,m
	jrz	find

	bset	MAKPUBBIT,m

;
; find all filename entries in all user numbers
;

find:
	lxi	h,fcb
	mvi	m,'?'		; match ALL dir entries
	xchg
	mvi	c,srchfstfn
	call	bdos
	sta	indx		; save position in buffer
	inr	a
	jrz	done		; no entries at all
findall:
	call	chknxt		; is entry PUBLIC or specified filename?
	jrnz	findnxt

	call	savefcb		; yes -- save it
	call	setcol
	call	printentry	; list it
	lxi	h,count		; and count it
	inr	m
findnxt:
	mvi	c,srchnxtfn	;
	lxi	d,fcb
	call	bdos

	sta	indx
	inr	a
	jrnz	findall
nomore:
	lxi	h,flags
	bit	LISTPUBBIT,m
	lda	count
	jrz	nom0

	ora	a
	jrnz	done

	lxi	d,nopubs
	call	printde
	jr	done
nom0:
	sui	1
	jrc	none
	jrnz	nochanges

	lxi	h,flags		; exactly 1 file found
	bit	MAKPUBBIT,m
	jrz	nom1

	call	setpub
	jr	done
nom1:
	call	setpriv
	jr	done


;
; can't be PUBLIC if > 1 match on drive
;

nochanges:
	lxi	d,multimsg
	call	printde
	jr	done
none:
	lxi	d,nonemsg
	call	printde
	jr	done
nopub:
	lxi	d,pubnam
	call	cant

;
; all done -- restore drive/user and return
;

done:
	call	crlf
	lxi	h,flags
	bit	LISTPUBBIT,m
	jrz	done0

	lxi	d,usage
	call	printde
done0:
	lda	udrive		; relogin user's drive
	mov	e,a
	mvi	c,drivefn
	call	bdos
done1:
	lda	uuser
	mov	e,a
	mvi	c,userfn
	call	bdos
	call	crlf
xit:
	lspd	ustack
	ret

;
; set the PUBLIC attribute bit
;

setpub:
	lxi	h,pubfcb+2	; test attr bit 2
	bit	7,m
	jrnz	ispub		; quit if already PUBLIC

	bset	7,m		; set attr bit 2
	lda	pubfcb		; save user number for output
	mov	e,a		; set user number for this file
	mvi	c,userfn	;
	call	bdos		;

	lxi	h,pubfcb
	mvi	m,0		; put default drive into fcb
	xchg
	mvi	c,setattrfn	;
	call	bdos
	inr	a
	jrz	nopub

	lxi	d,tomsg
	call	printde

	lxi	d,pubnam
	call	printde
setpend:
	lxi	h,pubfcb
	jmp	prnent1
ispub:
	lxi	d,pubnam
	jmp	istype

;
; reset the public attribute bit
;

setpriv:
	lda	pubfcb		; save file user number
	mov	e,a		; set user number of fcb
	mvi	c,userfn
	call	bdos

	lxi	h,pubfcb+2	; reset PUBLIC attr bit
	bit	7,m		;
	jrz	ispriv		; quit if it's alread private

	res	7,m
	lxi	h,pubfcb
	mvi	m,0		; default drive
	xchg
	mvi	c,setattrfn	;
	call	bdos
	inr	a
	jrz	nopriv

	lxi	d,tomsg
	call	printde

	lxi	d,privnam
	call	printde
	jr	setpend

nopriv:
	lxi	d,privnam
	jmp	cant

ispriv:
	lxi	d,privnam
istype:
	push	d
	lxi	d,ismsg
	call	printde
	pop	d
printde:
	mvi	c,9
	jmp	bdos

cant:
	push	d
	lxi	d,cantmsg
	call	printde
	pop	d
	jr	printde

;
; check next directory entry
; if listing PUBLIC files, ret Z if PUBLIC and 0th extent.
; if matching a filename, ret Z if same name, type and extent
; else ret NZ
;

chknxt:
	call	findentry
	mov	a,m
	cpi	0e5h		; don't match erased entries
	jrnz	chkn0

	ora	a		; set NZ
	ret
chkn0:
	inx	h
	lda	flags
	bit	LISTPUBBIT,a
	jrz	chkn1

;
; list all PUBLIC files
;

	inx	h		; point at 2nd char of filename
	mov	a,m
	cma
	ani	80h		; check complement of attr bit
	rnz			; not PUBLIC -- ret NZ

	lxi	d,12-2		; have a PUBLIC file
	dad	d		; point at its extent byte
	xra	a		; and check for extent 0
	jr	chkn3

;
; check for match with specified filename / extent 0
;
; note: doesn't allow wiled cards.
;

chkn1:
	lxi	d,fcb+1
	mvi	b,11		; name & type
chkn2:
	ldax	d
	sub	m
	ani	7fh		; don't test attr bits
	inx	h
	inx	d
	rnz			: NZ if no match
	djnz	chkn2

	ldax	d		; now check the extent
chkn3:
	mov	c,m

;
; check for same extent in a,c
;

samext:
	push	psw
extmask	equ	$+1
	mvi	a,0
	cma
	mov	b,a		; save mask
	mov	a,c		; mask c
	ana	b
	mov	c,a		; save in c
	pop	psw		;
	ana	b
	sub	c
	ani	1fh		; check only legal bits 0..4
	ret

savefcb:
	call	findentry
	mov	a,m		; save the user number
	sta	fileuserno
	lxi	d,pubfcb
	lxi	b,32
	ldir
	ret

;
; find entry in buffer
;

findentry:
	lda	indx		; point to fcb found
	add	a		; * 32
	add	a
	add	a
	add	a
	add	a
	lxi	h,buf
	add	l
	mov	l,a
	rnc

	inr	h
	ret


setcol:
	lda	count
	ani	3
	jz	crlf

	call	twosp
	mvi	c,fence
	call	charout
twosp:
	mvi	c,SPACE
	call	charout
	mvi	c,SPACE
	jmp	charout

;
; print drive/user/filename
;

printentry:
	call	findentry
prnent1:
	push	h
	call	printdrv
fileuserno	equ	$+1
	mvi	a,0
	call	printuser
	pop	h
print$fn:
	inx	h		; print finename.ext
	mvi	b,8
	call	prfn
	mvi	c,'.'
	call	charout
	mvi	b,3
prfn:
	mov	a,m		; print filename char, lowercase if attr bit set
	ani	7fh		; kill attr bit when printing
	cmp	m		;
	jrz	prfn1

	ori	20h		; set lower case
prfn1:
	mov	c,a
	call	charout
	inx	h
	djnz	prfn
	ret

printdrv:
	lda	drive		; print drive
	adi	'A'
	mov	c,a
	jr	charout

crlf:
	mvi	c,CR
	call	charout
	mvi	c,LF
charout:
	push	h
	push	b
	push	d
	mov	e,c
	mvi	c,2
	call	bdos
	pop	d
	pop	b
	pop	h
	ret

printuser:
	cpi	10		; print A as user number
	jrnc	printu1

	push	psw		; 1 space if single digit
	mvi	c,SPACE
	call	charout
	pop	psw
printu1:
	mov	l,a
	mvi	h,0
	call	printdec
	mvi	c,':'
	jr	charout

printdec:
decout:
	push	psw
	push	b
	push	d
	push	h
	lxi	b,-10
	lxi	d,-1
decou2:
	dad	b
	inx	d
	jc	decou2

	lxi	b,10
	dad	b
	xchg
	mov	a,h
	ora	l
	cnz	decout		; recursive

	mov	a,e
	adi	'0'
	mov	c,a
	call	charout
	pop	h
	pop	d
	pop	b
	pop	psw
	ret


flags	db	0
indx	db	0
drive	db	0
count	db	0
udrive	db	0
uuser	db	0
ustack	dw	0
pubfcb	equ	$
stack	equ	pubfcb+32+48
buf	equ	stack
	end
