; mailcc/asm - kjw/bqsd - version 2.00 - 01/83
;
; revised 02/24/83 - kjw
;
	SUBTTL	'<mailcc/asm - edit records>'
;
	PAGE
;
;	re-edit existing mask
;
REEDIT	LD	HL,MASK		;mask area
	LD	DE,BUFFER	;edit buffer
	LD	BC,131		;length
	LDIR			;move it in
	JR	EDITR0		;continue
;
;	edit record
;
EDITR	CALL	CLRDATA		;clear data buffer
EDITR0	PUSH	IY		;save
	CALL	CLS		;clear lower video
	LD	HL,MSG9		;'enter search mask'
	CALL	DISPLAY		;display prompt
	CALL	SHOW		;display file
	CALL	SHOWFM		;display flags
EDRAGN	CALL	GETINFO		;get user info
	JR	C,EDRF		;continue on BREAK
	CP	ESCAPE		;escape key?
	JR	Z,EDRNAG	;yes, abort edit!
EDRF	CALL	FLAGMSK		;get user flags mask
	JR	C,EDRAGN	;go on BREAK
EDRNAG	POP	IY		;restore sys pointer
	LD	HL,BUFFER	;edited data
	LD	DE,MASK		;mask area
	LD	BC,131		;length of mask
	LDIR			;move it in
;
EDITR1	LD	HL,MSG4		;'find/edit/cancel?/
	CALL	DISPLAY		;display prompt
	LD	B,1		;one key input
	CALL	GETSTR		;from keyboard
	JP	C,MENU		;go if BREAK
	JR	Z,EDITR2	;default FIND
	CALL	UCASE		;make upper case
	CP	'C'		;cancel?
	JP	Z,MENU		;go if yes
	CP	'E'		;edit?
	JR	Z,EDITR0	;go if yes
	CP	'F'		;find?
	JR	Z,EDITR2	;go if yes
;
;	check if digit 0-7 specified for search
;
	SUB	'0'		;remove ascii
	JR	C,EDITR1	;invalid, ask again
	CP	DRIVES		;in range?
	JR	NC,EDITR1	;invalid
	LD	(IY+1),A	;set current drive #
	CALL	LOOKREC		;look for record
	JR	EDITND		;edit end!
;
;	locate record from mask
;
EDITR2	LD	(IY+1),0	;set current drive 0
;
EDITR3	CALL	LOOKREC		;look for record
	LD	A,(IY+1)	;fetch current drive
	AND	7		;low 3 bits only
	INC	A		;+1
	LD	(IY+1),A	;update
	CP	DRIVES		;in range?
	JR	C,EDITR3	;go for all drives
;
EDITND	LD	HL,MSG5		;end of file
	CALL	DISPLAY		;display message
	CALL	INKEY		;wait for a key
	JP	REEDIT		;reedit mask
;
;	locate record on drive (iy+0) low 3 bits
;
LOOKREC	LD	A,(IY+1)	;fetch drive #
	CALL	LOCFCB		;locate fcb block
	BIT	7,(IX+0)	;file open this drive?
	JR	NZ,LOOKR0	;go if available
;
NOTREC	OR	-1		;set NOT FOUND
	RET			;return not-available
;
;	check if data in file
;
LOOKR0	LD	A,(IX+10)	;MSB used
	OR	(IX+11)		;NSB
	OR	(IX+12)		;LSB
	JR	Z,NOTREC	;go if empty file
;
;	display drive specifics
;
	LD	B,(IX+7)	;msb records available
	LD	H,(IX+8)
	LD	L,(IX+9)
	PUSH	BC		;save
	PUSH	HL
	LD	DE,MSG8A	;text to place it
	CALL	BINASC		;binary => ascii
	LD	B,(IX+10)	;msb # records used
	LD	H,(IX+11)
	LD	L,(IX+12)	;BHL = records used
	PUSH	BC		;save on stack
	PUSH	HL
	LD	DE,MSG8B	;text
	CALL	BINASC		;to ascii
	POP	DE		;NSB,LSB used
	POP	AF		;A = msb used
	POP	HL		;NSB,LSB available
	POP	BC		;B = msb available
	LD	C,A		;BHL=total, CDE=used
	CALL	SUBIT		;sub CDE from BHL
	LD	DE,MSG8C	;text
	CALL	BINASC		;to ascii
	LD	A,(IY+1)	;fetch system flag
	AND	7		;A = drive #
	ADD	A,'0'		;add ascii
	LD	(MSG8D),A	;to text
;
;	load flag descriptions
;
	LD	E,(IX+15)	;get fcb
	LD	D,(IX+16)	;DE => file control block
	LD	BC,REWIND	;record 0
;
	POSN$			;position to record
	RET	NZ		;go if error
	READ$			;read first record
	RET	NZ		;go if error
	LD	E,(IX+17)	;get buff pointer
	LD	D,(IX+18)
	LD	HL,20H		;offset to disk name
	ADD	HL,DE		;HL => file name
	LD	DE,MSG8X	;text for file name
	LD	BC,10H		;name length
	LDIR			;move into string
	LD	DE,10H		;offset to flag names
	ADD	HL,DE		;HL => names
	LD	DE,FLAGBUF	;flag name buffer
	LD	BC,24*8		;flag name length
	LDIR			;move names into buffer
	LD	HL,MSG8		;specifics text
	CALL	DISPLAY		;display it
;
;	init type of search to use
;
	BIT	6,(IX+0)	;file sorted?
	JR	Z,LOOKRS	;nope, look sequential
;
;	determine if search mask matches sorted field
;
	LD	A,(IX+13)	;fetch sort field
	ADD	A,A		;*2
	ADD	A,A		;*4
	LD	C,A		;pass to C
	LD	B,0		;BC = table offset
	LD	HL,TABLET+3	;start + data offset
	ADD	HL,BC		;HL => offset of data
	LD	A,(HL)		;fetch offset
	LD	L,A		;L = lsb offset
	LD	H,MASK<-8	;H = msb offset
	LD	A,(HL)		;fetch a char
	CP	' '		;blank?
	JR	Z,LOOKRS	;nil, look sequential
;
;	looking through the file via INDEX
;
LOOKRWI	CALL	POSITS		;position sorted
	JP	NZ,NOTREC	;go next drive if not mat
	SET	5,(IY+1)	;set INDEX search
	RES	4,(IY+1)	;set forward search
	LD	(IY+17),0	;set NO COMPARE
	JR	LOOKING		;continue
;
;	looking through the file via DATA
;
LOOKRS	XOR	A		;load zero
	LD	(IY+7),A	;init current record msb
	LD	(IY+8),A	;nsb
	LD	(IY+9),A	;lsb
	RES	5,(IY+1)	;set SEQUENTIAL
	RES	4,(IY+1)	;set forward search
	LD	(IY+17),-1	;set COMPARE
;
;	begin search, params initialized
;
LOOKING	PUSH	IX		;save it
	CALL	READREC		;read current record
	POP	IX		;restore
	JR	Z,LOOKMAT	;check for match
;
	CALL	LERROR		;load error
	JP	C,MENU		;go on BREAK
	JR	NZ,LOOKING	;go if RETRY
;
LOOKMAT	CALL	STROBE		;strobe keyboard
	CP	BREAK		;break key?
	JP	Z,ABORT		;abort it yes
;
	LD	A,(IY+17)	;get compare flag
	OR	A		;no?
	JR	Z,LOOKED	;go direct record!
	PUSH	IX		;save it
	CALL	MATCH		;matching record?
	POP	IX		;restore
	JP	NZ,LOOKNXT	;go next if not
;
;	move data from buffer into editor buffer
;
LOOKED	LD	E,(IX+17)	;lsb buffer
	LD	D,(IX+18)	;DE => I/O buffer
	LD	L,(IY+16)	;data offset
	LD	H,0		;HL = offset
	ADD	HL,DE		;HL => offset
	LD	DE,BUFFER	;editor buffer
	LD	BC,128		;record length
	LDIR			;move into edit buffer
;
;	check if to be edited
;
	BIT	3,(IY+1)	;file out of range?
	CALL	NZ,CLRDATA	;yes, clear out buffer
	PUSH	IX		;save
	PUSH	IY		;save sys pointer
	CALL	SHOW		;show data
	CALL	SHOWF		;show flags
	POP	IY		;unstack
	POP	IX
;
;	display current record #
;
	LD	HL,MSG18	;'out of range'
	BIT	3,(IY+1)	;yes?
	JR	NZ,LOOKNFD	;yes, go!
	LD	B,(IY+7)	;get record #
	LD	H,(IY+8)
	LD	L,(IY+9)
	CALL	INCBHL		;adjust to actual
	LD	DE,MSG17A	;text
	CALL	BINASC		;binary => ascii
	LD	HL,MSG17	;start message
LOOKNFD	CALL	DISPLAY		;current record #
	LD	HL,MSG6		;'edit/next/back/rwnd/?'
	CALL	DISPLAY		;display prompt
	CALL	INKEY		;read keyboard
	JP	C,MENU		;go on BREAK
	JR	Z,LOOKE		;edit record default
	CALL	UCASE		;make upper case
	CP	'S'		;next drive ?
	RET	Z		;yes, continue
	CP	'F'		;go forward?
	JP	Z,LOOKUP	;yes, go!
	CP	UP
	JP	Z,LOOKUP
	CP	RIGHT
	JP	Z,LOOKFOR
	CP	'B'		;backspace?
	JP	Z,LOOKDN	;yes, go!
	CP	DOWN
	JP	Z,LOOKDN
	CP	LEFT
	JP	Z,LOOKBAK
	CP	'R'		;rewind file?
	JP	Z,LOOKREW	;yes, go!
	CP	'Q'		;quit?
	JP	Z,MENU		;yes, abort
	CP	'K'		;kill?
	JP	Z,LOOKKIL
	CP	'U'		;unkill?
	JP	Z,LOOKUNK
	CP	'1'		;first record?
	JP	Z,REC1
	CP	'L'		;last record?
	JP	Z,RECL
	CP	'E'		;edit?
	JP	NZ,LOOKED	;none, go!
;
;	edit current record
;
LOOKE	CALL	EDIT		;edit the record
LOOKEE	LD	HL,MSG7		;'save/cancel/quit?'
	CALL	DISPLAY		;display prompt
	LD	B,1		;one key
	CALL	GETSTR		;from keyboard
	JP	C,LOOKED	;go on BREAK
	JR	Z,LOOKES	;save record
	CALL	UCASE		;make char upper case
	CP	'C'		;cancel?
	JP	Z,LOOKED	;yes, back to paging
	CP	'Q'		;quit?
	JP	Z,MENU		;yes, back to menu
	CP	'S'		;save?
	JR	NZ,LOOKEE	;neither, ask again
	JR	LOOKES		;save it!
;
;	kill current record
;
LOOKKIL	LD	A,(BUFFER)	;get first char
	INC	A		;FF dead?
	JR	Z,LOOKES	;alread dead!
	LD	HL,BUFFER+13	;end -1
	LD	DE,BUFFER+14	;end
	LD	BC,14		;length -1
	LDDR			;move it up
	LD	A,-1		;delete char
	LD	(DE),A		;to last char
	JR	LOOKES		;save it!
;
;	unkill current record
;
LOOKUNK	LD	A,(BUFFER)	;get first byte
	INC	A		;killed?
	JR	NZ,LOOKES	;go if not dead!
;
	LD	DE,BUFFER	;start buffer
	LD	HL,BUFFER+1	;start +1
	LD	BC,14		;length -1
	LDIR			;move it down
	LD	A,' '		;load space
	LD	(DE),A		;to last char
;
;	save edited record
;
LOOKES	LD	E,(IX+17)	;get LSB buffer
	LD	D,(IX+18)	;get MSB buffer
	LD	L,(IY+16)	;get data offset
	LD	H,0		;HL = offset
	ADD	HL,DE		;HL = buffer offset
	EX	DE,HL		;DE = offset
	LD	HL,BUFFER	;input data here
	LD	BC,128		;data length
	LDIR			;move into I/O buffer
;
LOOKAGN	CALL	WRITREC		;write current record
	JP	Z,LOOKED	;go if no error
	CALL	WERROR		;save error!
	JP	C,MENU		;go on BREAK
	JR	NZ,LOOKAGN	;write again if retry
	JP	LOOKED		;else skip
;
;	rewind file to beginning
;
LOOKREW	BIT	5,(IY+1)	;sorted search?
	JP	NZ,LOOKRWI	;rewind index
	JP	LOOKRS		;look through sequential
;
;	look forward through file
;
LOOKUP	LD	(IY+17),-1	;set YES compare mask
	JR	LKUF		;go common
;
LOOKFOR	LD	(IY+17),0	;set NO compare
LKUF	RES	4,(IY+1)	;set forward
	JR	LOOKNXT		;go next record
;
;	look backward through file
;
LOOKDN	LD	(IY+17),-1	;set YES compare
	JR	LKDB		;go common
;
LOOKBAK	LD	(IY+17),0	;set NO compare
;
LKDB	SET	4,(IY+1)	;set backward
;
LOOKNXT	BIT	5,(IY+1)	;use index to search?
	RES	3,(IY+1)	;set file in range
	JP	NZ,LKNIN	;yes, go index record
;
	LD	B,(IY+7)	;fetch current data rec #
	LD	H,(IY+8)
	LD	L,(IY+9)	;BHL = record #
	BIT	4,(IY+1)	;forward or backward?
	JR	Z,LOOKNF	;go forward
;
;	moving backward
;
	LD	A,B		;fetch MSB
	OR	H		;at record 0?
	OR	L		;BHL = 0?
	SET	3,(IY+1)	;set OUT OF RANGE
	JP	Z,LOOKED	;cannot go back from here
	CALL	DECBHL		;decrement BHL
	JR	LOOKNC		;go common
;
;	moving forward
;
LOOKNF	CALL	INCBHL		;increment BHL
	LD	C,(IX+10)	;get # records used
	LD	D,(IX+11)
	LD	E,(IX+12)	;CDE = # records in file
	CALL	CMPBHL		;compare BHL <> CDE
	SET	3,(IY+1)	;set OUT OF RANGE
	JP	Z,LOOKED	;go if end of file
;
LOOKNC	LD	(IY+7),B	;update pointer
	LD	(IY+8),H
	LD	(IY+9),L
	RES	3,(IY+1)	;set IN RANGE
	JP	LOOKING		;go next record
;
;	looking through index file
;
LKNIN	LD	B,(IY+10)	;get current record
	LD	H,(IY+11)
	LD	L,(IY+12)
	BIT	4,(IY+1)	;forward or backward?
	JR	Z,LOOKIF	;go index forward
;
;	move back
;
	LD	A,B		;check for 000000H
	OR	H
	OR	L		;BHL = 0?
	SET	3,(IY+1)	;set out of range
	JP	Z,LOOKED	;cannot go back!
	CALL	DECBHL		;decrement BHL
	JR	LOOKIC		;continue
;
;	moveing forward
;
LOOKIF	CALL	INCBHL		;increment BHL
	LD	C,(IX+10)	;get total # records
	LD	D,(IX+11)
	LD	E,(IX+12)
	CALL	CMPBHL		;at end
	SET	3,(IY+1)	;set out of range
	JP	Z,LOOKED	;go if at end now
;
LOOKIC	LD	(IY+10),B	;update current record
	LD	(IY+11),H
	LD	(IY+12),L
	CALL	READIND		;read index record
	JP	NZ,LOOKED	;go on disk error
	LD	C,(IY+16)	;get data offset
	LD	B,0		;BC = offset
	LD	L,(IX+17)	;get buff pointer
	LD	H,(IX+18)
	ADD	HL,BC		;HL => record
	LD	C,20		;offset to index
	ADD	HL,BC		;HL => record #
	LD	B,3		;3 bytes to move in
	PUSH	IY		;save sys pointer
MRCIN	LD	A,(HL)		;get record address
	LD	(IY+7),A	;to pointer
	INC	HL		;bump
	INC	IY		;bump
	DJNZ	MRCIN		;continue
	POP	IY		;restore pointer
	RES	3,(IY+1)	;set new record
	JP	LOOKING		;found the record
;
;	position to first record
;
REC1	LD	B,0		;load BHL with 000000
	LD	H,B
	LD	L,B
	JR	REC1L		;go common
;
;	position to last record
;
RECL	LD	B,(IX+10)	;get # records used
	LD	H,(IX+11)
	LD	L,(IX+12)
	CALL	DECBHL		;last logical record #
;
REC1L	BIT	5,(IY+1)	;index or sequential?
	LD	(IY+17),0	;set NO compare
	JP	Z,LOOKNC	;go sequential
	JP	LOOKIC		;go indexed
;
	PAGE
;
;	edit current record
;
EDIT	PUSH	IY		;save
	PUSH	IX		;save
EDZAGN	CALL	GETINFO		;get name/add etc info
	JR	C,EDZF		;go on BREAK
	CP	ESCAPE		;escape key?
	JR	Z,EDZNAG	;yes, go!
EDZF	CALL	GETFLAG		;get flags
	JR	C,EDZAGN	;go on BREAK
EDZNAG	POP	IX		;restore
	POP	IY		;unstack
	RET			;done with edit!
;
;	edit flag mask for drive merge
;
EDITFM	SET	7,(IY+1)	;set mask edit
	LD	HL,MSG10B	;'editing flag mask'
	JR	EDITFCM		;go common
;
;	flag editing error vector
;
FERROR	PUSH	AF		;save error
	CALL	CLS		;clear lower video
	POP	AF		;restore error
	CALL	ERROR		;display error message
	LD	HL,MSG2		;<KEY> to continue
	CALL	DISPLAY		;display message
	CALL	INKEY		;wait for a key
EDITFF	BIT	7,(IY+1)	;flags or mask?
	JR	NZ,EDITFM	;go mask
;
;	edit flags entry
;
EDITF	RES	7,(IY+1)	;set flag edit
	LD	HL,MSG10A	;'editing flags'
;
EDITFCM	CALL	DISPLAY		;display prompt
	LD	HL,MSG10	;'drive #?'
	CALL	DISPLAY		;display prompt
	LD	B,1		;one key input
	CALL	GETSTR		;from keyboard
	JP	C,MENU		;go on BREAK
	JR	Z,EDITFF	;no default
	CALL	UCASE		;make upper case
	CP	'X'		;alternate BREAK?
	JP	Z,MENU		;yes, go!
	SUB	'0'		;remove ascii
	JR	C,EDITFF	;invalid drive #
	CP	DRIVES		;in range?
	JR	NC,EDITFF	;invalid, ask again
	LD	(IY+7),A	;save drive #
	CALL	LOCFCB		;locate FCB block
	BIT	7,(IX+0)	;file open?
	JR	Z,EDITFF	;go if not available
;
;	read first sector to get flag information
;
	LD	E,(IX+15)	;lsb FCB
	LD	D,(IX+16)	;msb FCB
	LD	BC,REWIND	;3 00's
;
	POSN$			;rewind file
	JR	NZ,FERROR	;flag error!
	READ$			;read first record
	JR	NZ,FERROR	;go if error
	LD	L,(IX+17)	;get buffer pointer
	LD	H,(IX+18)	;HL => I/O buffer
;
	PUSH	HL		;save HL
	LD	DE,40H		;offset to flag names
	ADD	HL,DE		;HL => names
	LD	DE,FLAGBUF	;temp buffer
	LD	BC,24*8		;flags * length
	LDIR			;move flag names
	POP	HL		;HL => I/O buffer
;
	BIT	7,(IY+1)	;editing mask or names?
	JP	NZ,EDITFME	;mask, go!
;
	LD	(IY+8),1	;set current flag #
;
FLAGLP	PUSH	IY		;save
	CALL	SHOWF		;clear flags on video
	POP	IY		;restore
	LD	A,(IY+8)	;fetch flag #
	DEC	A		;adjust to 0-23
	ADD	A,A		;*2
	ADD	A,A		;*4
	LD	C,A		;pass offset
	LD	B,0		;BC = table offset
	LD	IX,TABLEB	;flag table
	ADD	IX,BC		;IX => flag entry
	LD	L,(IX+0)	;fetch LSB video
	LD	H,(IX+1)	;msb video
;
	IF	MOD2
	CALL	@VIDON		;select video
	ENDIF
;
	LD	(HL),FLON	;set flag byte on
;
	IF	MOD2
	CALL	@VIDOFF		;de-select video
	ENDIF
;
	LD	A,(IY+8)	;get flag #
	CALL	NAMEF		;display flag name
	LD	A,EDITCUR	;editor cursor
	LD	(CURCHR),A	;save it
	CALL	CURADD		;fetch cursor address HL
	CALL	KEY		;fetch input key
	JP	C,PUTFLAG	;go on BREAK
	JR	Z,ADVFLG	;go next if ENTER
;
;	check for positioning command
;
	LD	C,0		;init position
	CP	RIGHT		;right arrow?
	JR	Z,FLFR		;yes, go!
	CP	LEFT		;left arrow?
	JR	Z,FLFL		;yes, go!
	CP	DOWN		;down arrow?
	JR	Z,FLFD		;yes, go!
	CP	UP		;up arrow?
	JR	Z,FLFU		;yes, go!
;
;	edit current flag
;
	PUSH	AF		;save input key
	LD	A,CHARCUR	;character cursor
	LD	(CURCHR),A	;save it
	POP	AF		;restore input key
	LD	B,8		;length of flag
	CALL	ONEKEY		;edit current flag
	JP	C,MENU		;go on BREAK
;
ADVFLG	INC	(IY+8)		;bump current flag
	LD	A,(IY+8)	;fetch result
	CP	25		;1-24?
	JR	C,FLAGLP	;go next flag
;
;	write flags back to buffer
;
PUTFLAG	PUSH	IY		;save
	CALL	SHOWF		;clear display flags
	POP	IY		;restore
	LD	HL,MSG11	;'writing flags'
	CALL	DISPLAY		;display message
	LD	A,(IY+7)	;get drive #
	CALL	LOCFCB		;locate file block
	LD	L,(IX+17)	;i/o buffer
	LD	H,(IX+18)	;HL => buffer
	LD	DE,40H		;offset to names
	ADD	HL,DE		;HL => names in buffer
	EX	DE,HL		;DE => I/O buffer
	LD	HL,FLAGBUF	;edited names
	LD	BC,24*8		;flags * length
	LDIR			;move into buffer
;
PUTFLG	LD	A,(IY+7)	;get drive #
	CALL	LOCFCB		;locate fcb block
	LD	E,(IX+15)	;lsb fcb pointer
	LD	D,(IX+16)	;msb fcb
	LD	BC,REWIND	;3 00's
;
	POSN$			;position to record
	JP	NZ,FERROR	;go if error
	WRITE$			;write buffer
	JP	NZ,FERROR	;go if error
	LD	HL,MSG12	;written
	CALL	DISPLAY		;display message
	CALL	INKEY		;wait for a key
	JP	MENU		;back to menu!
;
;	edit flags cursor positioning
;
FLFR	INC	C		;+3
FLFL	INC	C		;+2
FLFD	INC	C		;+1
FLFU	EQU	$		;+0
	LD	A,C		;get offset
	LD	(FLFC),A	;save into code
	LD	A,(IY+8)	;get current flag
	DEC	A		;adjust 0-23
	ADD	A,A		;*2
	ADD	A,A		;*4
	LD	C,A		;pass to C
	LD	B,0		;BC = offset
	LD	IX,TABLEB2	;flag edit table
	ADD	IX,BC		;IX+x = table offset
	LD	C,(IX+0)	;fetch offset
FLFC	EQU	$-1
	LD	B,0		;offset
	LD	IX,TABLEB	;lower table
	ADD	IX,BC		;IX+2 = flag #
	LD	A,(IX+2)	;fetch flag #
	LD	(IY+8),A	;save flag #
	JP	FLAGLP		;continue loop
;
;	edit flag mask
;
EDITFME	LD	DE,15H		;offset to flag mask
	ADD	HL,DE		;HL => data
	LD	DE,BUFFER+125	;offset to buffer
	LD	BC,6		;flag mask length
	PUSH	HL		;save offset
	LDIR			;save it
	PUSH	IY		;save
	CALL	FLAGMSP		;edit mask
	POP	IY		;restore
	POP	DE		;DE => mask offset in buf
	LD	HL,BUFFER+125	;edited flags here
	LD	BC,6		;mask length
	LDIR			;move it in
	LD	HL,MSG13	;updating flag mask
	CALL	DISPLAY		;display it
	JP	PUTFLG		;write back to disk
;
;	check if index record is in range
;
RANGE	PUSH	BC		;save
	PUSH	DE		;save
	PUSH	HL		;save
	LD	B,(IX+7)	;get # recs avail
	LD	H,(IX+8)
	LD	L,(IX+9)
	LD	C,(IY+10)	;get current rec #
	LD	D,(IY+11)
	LD	E,(IY+12)
	CALL	CMPBHL		;compare BHL => CDE
	POP	HL		;unstack
	POP	DE
	POP	BC		;restore
	RET			;done
;
;	compare index file to search mask
;
INDCOMP	LD	C,(IY+16)	;data offset in buffer
	PUSH	HL		;save again
	PUSH	DE
	LD	L,(IX+17)	;get buffer pointer
	LD	H,(IX+18)
	LD	B,0		;BC = offset
	ADD	HL,BC		;HL => index record
	LD	B,D		;field length
	LD	D,MASK<-8	;set msb mask field
;
POSCOMP	LD	A,(DE)		;get a byte
	CP	'?'		;wildcard?
	JR	Z,POSNXT	;yes, assume match
	CP	'*'		;match remaining?
	JR	Z,POSMAT	;yes, continue
	CALL	UCASE		;make upper case
	CP	(HL)		;test to index
	JR	NZ,POSMAT	;nope, done!
;
POSNXT	INC	HL		;bump pointers
	INC	DE		;mask
	DJNZ	POSCOMP		;complete compare
;
POSMAT	POP	DE		;unstack
	POP	HL		;I/O buff and mask
	RET			;return Z,C,NC
;
;	display current flag name
;
NAMEF	DEC	A		;adjust 0-23
	LD	L,A		;pass to L
	LD	H,0		;HL = flag #
	ADD	HL,HL		;*2
	ADD	HL,HL		;*4
	ADD	HL,HL		;*8
	LD	BC,FLAGBUF	;start of flag names
	ADD	HL,BC		;HL => name
	LD	DE,FLAGTXT	;move into text buffer
	LD	BC,8		;flag desc length
	PUSH	HL		;save text pointer
	LDIR			;move into string
	LD	HL,FLAGTX	;start of message
	CALL	DISPLAY		;display it
	POP	DE		;DE => name in buffer
	RET			;done, displayed
;
;	display flags with + - .
;
SHOWFM	LD	IX,TABLEB	;lower video table
	LD	HL,BUFFER+128	;offset to flag mask
	LD	C,1		;mask test bit
;
	IF	MOD2
	CALL	@VIDON		;enable video
	ENDIF
;
SHOWMLP	LD	A,(HL)		;read flag
	AND	C		;test for set
	LD	E,(IX+0)	;fetch LSB video
	LD	D,(IX+1)	;fetch MSB video
	LD	A,'.'		;blank flag
	JR	Z,SHOWM2	;go if blank
	DEC	HL		;move back 3
	DEC	HL
	DEC	HL
	LD	A,(HL)		;read flag
	INC	HL		;bump thrice
	INC	HL
	INC	HL
	AND	C		;test bit
	LD	A,'+'		;yes?
	JR	NZ,SHOWM2	;go if yes
	LD	A,'-'		;no!
SHOWM2	LD	(DE),A		;to video
	SLA	C		;shift left test bit
	JR	NC,SHOWMF	;go if not byte end
	LD	C,1		;reset test bit
	INC	HL		;bump buffer
SHOWMF	INC	IX		;bump table by 4
	INC	IX
	INC	IX
	INC	IX
	LD	A,(IX+0)	;fetch first byte
	OR	(IX+1)		;terminator 0000H?
	JR	NZ,SHOWMLP	;go till table end
;
	IF	MOD2
	CALL	@VIDOFF		;de-select video
	ENDIF
;
	RET			;done
;
;	vectors for fetch of flag mask
;
XFLG	DEC	C		;C = -1
	JR	NOFLG		;continue
;
YESFLG	INC	C		;C = 1
;
NOFLG	LD	A,(IX+2)	;C = 0, get flag #
	LD	DE,BUFFER+128	;start flag mask (3 bytes
YNFLG0	LD	B,1		;test bit
;
YNFLG1	DEC	A		;less flag #
	JR	Z,YNFLG2	;go if found
	SLA	B		;shift left test bit
	JR	NC,YNFLG1	;go for 8 bits
	INC	DE		;bump buffer
	JR	YNFLG0		;reset and continue
;
YNFLG2	CALL	RESBIT		;reset bit B (DE)
	INC	C		;C = remove mask?
	JP	Z,GETFNZ	;done, get next flag
	CALL	SETBIT		;set bit B (DE)
	DEC	DE		;move to data byte
	DEC	DE		;offset by -3
	DEC	DE
	CALL	RESBIT		;reset bit
	DEC	C		;C = 0?
	JP	Z,GETFNX	;no, bit is reset
	CALL	SETBIT		;else set bit B (DE)
	JP	GETFNX		;continue
;
GETFNZ	DEC	DE		;move to data byte
	DEC	DE
	DEC	DE
	CALL	RESBIT		;reset bit
	JP	GETFNX		;continue
;
;	reset bit mask B at (DE)
;
RESBIT	LD	A,B		;get mask
	CPL			;reverse it
	EX	DE,HL		;HL => flag
	AND	(HL)		;reset bit
	LD	(HL),A		;back to buffer
	EX	DE,HL		;reverse back
	RET			;done, bit reset
;
;	set bit mask B at (DE)
;
SETBIT	LD	A,(DE)		;get mask
	OR	B		;set bit
	LD	(DE),A		;update
	RET			;done
;
;	compute physical sector data file (RS/2 = PS)
;
COMPSEC	SRL	B		;B/2
	RR	H		;H/2
	RR	L		;L/2
	LD	A,0		;first record offset
	RET	NC		;go if even page
	LD	A,80H		;offset to second record
	RET
;
;	divide BHL in half, and increment if odd number
;
HALF	PUSH	BC		;must save
	PUSH	HL
	LD	BC,$		;get B
HALBC	EQU	$-2
	LD	HL,$		;get HL
HALHL	EQU	$-2
	CALL	HALFIT		;divide in half
	LD	(HALBC),BC	;update BC
	LD	(HALHL),HL	;update HL
	LD	A,B		;pass to CDE
	LD	D,H
	LD	E,L
	POP	HL		;restore original
	POP	BC
	LD	C,A		;CDE
	RET			;CDE = HALF/2
;
HALFIT	CALL	COMPSEC		;divide in half
	JR	C,HALFC		;go if carry
	LD	A,B		;check for BHL = 000000H
	OR	H
	OR	L
	RET	NZ		;go if not zero
HALFD	DEC	(IY+30)		;less counter
	JP	INCBHL		;else increment to one
;
HALFC	JP	NZ,INCBHL	;go if not zero
	JR	HALFD		;dec counter and cont
;
;	compute physical sector index file (11 / sector)
;
COMPIND	LD	A,11		;11 entries / sector
	CALL	TDIVD		;divide it out
	LD	C,A		;pass remainder
	OR	A		;remainder=0?
	RET	Z		;yes, done!
	XOR	A		;init offset
COMPINL	ADD	A,23		;offset to next index
	DEC	C		;go for remainder
	JR	NZ,COMPINL	;finish
	RET			;A = offset
;
;	error on load of current record
;
LERROR	LD	HL,MSG14	;'load error'
	JR	WERROR+3	;go common
;
;	error on write of current record
;
WERROR	LD	HL,MSG15	;'save error'
	PUSH	AF		;save error code
	CALL	DISPLAY		;display message
	POP	AF		;restore error
	CALL	ERROR		;display error
;
LWERR	LD	HL,MSG16	;'retry/skip/cancel?'
	CALL	DISPLAY		;display prompt
	LD	B,1		;one key input
	CALL	GETSTR		;from keyboard
	RET	C		;go if BREAK
	JR	Z,LWRETR	;retry is default
	CALL	UCASE		;make upper case
	CP	'S'		;skip?
	RET	Z		;yes, return Z
	CP	'Q'		;quit?
	SCF			;carry = yes
	RET	Z		;yes, return
	CP	'R'		;retry?
	JR	NZ,LWERR	;invalid, ask again
LWRETR	OR	-1		;return NZ
	RET			;retry
;
;	check if mask matches buffer
;
MATCH	LD	E,(IX+17)	;get buffer pointer
	LD	D,(IX+18)	;DE => I/O buffer
	LD	L,(IY+16)	;get data offset
	LD	H,0		;HL = offset
	ADD	HL,DE		;point to data start
	EX	DE,HL		;DE => data
	LD	BC,MASK		;mask storage
	LD	IX,TABLET	;top offset table
;
MATCHLP	LD	L,(IX+3)	;get data offset
	LD	H,0		;HL = offset
	ADD	HL,BC		;HL => mask for field
	LD	A,(HL)		;fetch offset
	CP	' '		;blank?
	JR	Z,MATCHNX	;yes, continue
;
;	compare fields
;
	PUSH	BC		;save
	PUSH	DE		;offsets on stack
	PUSH	HL		;save mask start
	LD	L,(IX+3)	;get offset again
	LD	H,0		;HL = offset
	ADD	HL,DE		;HL => data field
	POP	DE		;DE => mask field
	LD	B,(IX+2)	;B = field length
;
COMPLP	LD	A,(DE)		;get mask byte
	CP	'?'		;wildcard?
	JR	Z,COMPNX	;yes, force match
	CP	'*'		;wildcard?
	JR	Z,COMPRET	;yes, match remaining!
	CALL	UCASE		;make upper case
	LD	C,A		;save it
	LD	A,(HL)		;fetch data byte
	CALL	UCASE		;make upper case
	CP	C		;match?
	JR	NZ,COMPRET	;nope, return NZ
;
COMPNX	INC	HL		;bump data
	INC	DE		;bump mask
	DJNZ	COMPLP		;finish for length
;
COMPRET	POP	DE		;unstack
	POP	BC
	RET	NZ		;return if no match
;
;	bump to next field position
;
MATCHNX	INC	IX		;4 bytes / entry
	INC	IX
	INC	IX
	INC	IX
	LD	A,(IX+0)	;check for terminator
	OR	(IX+1)		;0000H term?
	JP	NZ,MATCHLP	;go next table entry
;
;	check if flags match also
;
	LD	IX,125		;offset to flags
	ADD	IX,BC		;IX => mask
	LD	A,(IX+3)	;read first flag
	OR	(IX+4)
	OR	(IX+5)		;any flags specified?
	RET	Z		;nope, records match!
;
	LD	HL,125		;offset to data flags
	ADD	HL,DE		;HL => data flags
	LD	B,3		;3 flags to check
;
CKFLGLP	LD	A,(IX+3)	;get mask
	AND	(HL)		;combine with mask
	CP	(IX+0)		;match?
	RET	NZ		;return if no match
	INC	IX		;bump mask
	INC	HL		;bump data
	DJNZ	CKFLGLP		;go for 3 flag bytes
	RET			;return with Z flag
;
;	position index file to correct record
;
POSITS	LD	B,(IX+10)	;get # records available
	LD	H,(IX+11)
	LD	L,(IX+12)	;BHL = # records
	CALL	COMPSEC		;divide in half
	CALL	C,INCBHL	;+1 one if any carry
	LD	(HALBC),BC	;save B
	LD	(HALHL),HL	;save HL
	LD	(IY+30),10	;init scan counter
	LD	(IY+10),B	;save as current record
	LD	(IY+11),H
	LD	(IY+12),L
;
;	setup loop to examine index file for name
;
	CALL	SORTPAR		;get sorted params
;
POSITLP	CALL	RANGE		;record in range?
	RET	C		;go if not
	PUSH	HL		;save buffer
	PUSH	DE		;save mask
	CALL	READIND		;read index record
	POP	DE		;unstack
	POP	HL
	RET	NZ		;go if out of range
;
	CALL	STROBE		;strobe keyboard
	CP	BREAK		;break key?
	JP	Z,ABORT		;abort operation!
;
	CALL	INDCOMP		;compare index data
	JP	Z,POSBEG	;found! posit to first
	LD	A,(IY+1)	;fetch flags
	RES	4,A		;set forward search
	JR	NC,$+4		;go if data > mask
	SET	4,A		;set backward search
	LD	(IY+1),A	;update flags
;
;	compute next record to access
;
	LD	B,(IY+10)	;get current record #
	LD	H,(IY+11)
	LD	L,(IY+12)
	PUSH	DE		;save mask info
	CALL	HALF		;divide in half
	BIT	4,(IY+1)	;forward or back?
	JR	Z,POSFOR	;go forward
	CALL	SUBIT		;backward
	JR	POSBAK		;continue
POSFOR	CALL	ADDIT		;forward
POSBAK	LD	(IY+10),B	;update record
	LD	(IY+11),H
	LD	(IY+12),L	;current record stored
	POP	DE		;restore pointers
	LD	A,(IY+30)	;check rec counter
	OR	A		;at zero?
	JP	NZ,POSITLP	;go next record if not
	OR	-1		;set NOT found
	RET			;go!
;
;	position to first matching record
;
POSBEG	PUSH	HL		;save
	PUSH	DE		;save
	CALL	INDCOMP		;compare index
	LD	B,(IY+10)	;get index record
	LD	H,(IY+11)
	LD	L,(IY+12)
	JR	NZ,POSBEGX	;go if no more matches
	CALL	DECBHL		;decrement record
	LD	(IY+10),B	;update
	LD	(IY+11),H
	LD	(IY+12),L
	CALL	RANGE		;in range?
	JR	C,POSBEGX	;go if not
	CALL	READIND		;read index
	POP	DE		;unstack
	POP	HL
	RET	NZ		;go if error
	JR	POSBEG		;continue
;
POSBEGX	CALL	INCBHL		;reset record
	LD	(IY+10),B	;update record #
	LD	(IY+11),H
	LD	(IY+12),L
	CALL	READIND		;read index record
	POP	DE		;unstack
	POP	HL
	RET	NZ		;go if error
;
	LD	C,(IY+16)	;get data offset
	LD	B,0		;BC = offset
	LD	L,(IX+17)	;get buff pointer
	LD	H,(IX+18)
	ADD	HL,BC		;point to index record
	LD	C,20		;offset to record #
	ADD	HL,BC		;HL => data record #
	LD	B,3		;3 loops
	PUSH	IY		;save
SETLPP	LD	A,(HL)		;get byte
	LD	(IY+7),A	;save into block
	INC	HL		;bump pointers
	INC	IY		;bump block pointer
	DJNZ	SETLPP		;finish
	POP	IY		;restore
	XOR	A		;set record found
	RET			;done
;
;	read current record from file
;
READREC	LD	B,(IY+7)	;MSB record #
	LD	H,(IY+8)	;NSB
	LD	L,(IY+9)	;LSB
	CALL	COMPSEC		;compute sector offset
	LD	(IY+16),A	;save data offset
	LD	C,(IX+4)	;get start rec # data
	LD	D,(IX+5)
	LD	E,(IX+6)	;CDE = start sector
	CALL	ADDIT		;add BHL + CDE
	BIT	7,(IY+1)	;record in memory?
	RES	7,(IY+1)	;set no data
	RES	6,(IY+1)	;set no index
	JR	Z,READRC1	;go if no record
;
;	check if record in memory is one desired
;
	LD	C,(IY+13)	;MSB rec in buffer
	LD	D,(IY+14)	;NSB
	LD	E,(IY+15)	;LSB
	CALL	CMPBHL		;compare
	JR	Z,READRC2	;go if in memory
;
;	read record from disk
;
READRC1	LD	(IY+13),B	;set new rec in buffer
	LD	(IY+14),H
	LD	(IY+15),L
	LD	E,(IX+15)	;fetch FCB pointer
	LD	D,(IX+16)	;DE => fcb
	LD	BC,SYSTEM+13	;point to record #
;
	POSN$			;position to record
	RET	NZ		;go if error
	READ$			;read record
	RET	NZ		;return if disk error
;
READRC2	SET	7,(IY+1)	;set buffer in memory
	XOR	A		;set no error
	RET			;record loaded
;
;	read index record
;
READIND	LD	B,(IY+10)	;get current record #
	LD	H,(IY+11)
	LD	L,(IY+12)
	CALL	COMPIND		;compute sector #
	LD	(IY+16),A	;save data offset
	CALL	INCBHL		;increment BHL
	BIT	6,(IY+1)	;sector in memory?
	RES	7,(IY+1)	;set no DATA
	RES	6,(IY+1)	;set no INDEX
	JR	Z,READIN1	;go if no record
;
;	check if record in memory is current
;
	LD	C,(IY+13)	;msb rec in memory
	LD	D,(IY+14)
	LD	E,(IY+15)
	CALL	CMPBHL		;compare BHL <> CDE
	JR	Z,READIN2	;go if in memory
;
;	read index record from disk
;
READIN1	LD	(IY+13),B	;set new rec in memory
	LD	(IY+14),H
	LD	(IY+15),L
	LD	E,(IX+15)	;fetch fcb pointer
	LD	D,(IX+16)	;de => fcb
	LD	BC,SYSTEM+13	;point to rec address
;
	POSN$			;position to record
	RET	NZ		;go if error
	READ$			;read the record
	RET	NZ		;go if error
;
READIN2	SET	6,(IY+1)	;set index in buffer
	XOR	A		;set no error
	RET			;return with buffer
;
;	write current record to disk
;
WRITREC	LD	E,(IX+15)	;lsb FCB pointer
	LD	D,(IX+16)	;DE => fcb
	LD	BC,SYSTEM+13	;point to rec #
;
	POSN$			;position to record
	RET	NZ		;go if error
	WRITE$			;write the sector
	RET			;return with status
;
;	fetch sort parameters
;
SORTPAR	LD	A,(IX+13)	;get sort field
	ADD	A,A		;*2
	ADD	A,A		;*4
	LD	E,A		;pass to E
	LD	D,0		;DE = offset
	PUSH	IX		;save IX
	LD	IX,TABLET	;lookup table
	ADD	IX,DE		;IX => field entry
	LD	E,(IX+3)	;get field offset
	LD	D,(IX+2)	;get field length
	POP	IX		;restore IX
	RET			;done
;
	SUBTTL	'<mailcc/asm - text section>'
;
	PAGE
;
MSG4	DEFB	SETCUR
	DEFB	14,00
	DEFM	')F(ind, (E)dit mask, '
	DEFM	'(C)ancel, (0)drive ? '
	DEFB	ETX
;
MSG5	DEFB	SETCUR
	DEFB	12,00
	DEFB	EOF
	DEFM	'End of File(s), (KEY):'
	DEFB	ETX
;
MSG6	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
	DEFM	')E(dit, (K)ill, (U)nkill, (Q)uit, '
	DEFM	'(1)first, (L)ast, (arrows)'
	DEFB	CR
	DEFM	'(R)ewind, (F)orward, (B)ackward, '
	DEFM	'(S)earch next drive ? '
	DEFB	ETX
;
MSG7	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
	DEFM	')S(ave, (C)ancel, (Q)uit ? '
	DEFB	ETX
;
MSG8	DEFB	SETCUR
	DEFB	12,00
	DEFB	EOF
	DEFM	':'
MSG8D	DEFM	'x - '
MSG8X	DEFM	'xxxxxxxxxxxxxxxx'
	DEFB	CR
MSG8A	DEFM	'xxxxxxxx Records - '
MSG8B	DEFM	'xxxxxxxx Used - '
MSG8C	DEFM	'xxxxxxxx Available'
	DEFB	CR
	DEFB	ETX
;
MSG9	DEFB	SETCUR
	DEFB	14,00
	DEFM	'Enter Search Mask'
	DEFB	ETX
;
MSG10A	DEFB	SETCUR
	DEFB	12,00
	DEFB	EOF
	DEFM	'Edit Flags'
	DEFB	ETX
;
MSG10B	DEFB	SETCUR
	DEFB	12,00
	DEFB	EOF
	DEFM	'Edit Flag Mask'
	DEFB	ETX
;
MSG10	DEFB	CR
	DEFB	CR
	DEFM	'Drive Number (0-7) ? '
	DEFB	ETX
;
MSG11	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
	DEFM	'Updating Flags to Disk - '
	DEFB	ETX
;
MSG12	DEFM	'Done, (KEY):'
	DEFB	ETX
;
MSG13	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
	DEFM	'Updating Flag Mask to Disk - '
	DEFB	ETX
;
MSG14	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
	DEFM	'Load Error - '
	DEFB	ETX
;
MSG15	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
	DEFM	'Save Error - '
	DEFB	ETX
;
MSG16	DEFB	SETCUR
	DEFB	15,00
	DEFB	EOF
	DEFM	')R(etry, (S)kip, (Q)uit ? '
	DEFB	ETX
;
MSG17	DEFB	SETCUR
	DEFB	13,00
	DEFB	EOF
	DEFM	'Record # '
MSG17A	DEFM	'xxxxxxxx'
	DEFB	ETX
;
MSG18	DEFB	SETCUR
	DEFB	13,00
	DEFB	EOF
	DEFM	'Record OUT OF RANGE'
	DEFB	ETX
;
FLAGTX	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
;
FLAGTXT	DEFM	'xxxxxxxx'
	DEFB	SETCUR
	DEFB	14,00
	DEFB	ETX
;
;
;	3 00's for rewind
;
REWIND	DEFB	00,00,00
;
TABLE4M	DEFB	'Y'		;turn flag on?
	DEFW	YESFLG
	DEFB	'N'		;turn flag off?
	DEFW	NOFLG
	DEFB	'+'		;set?
	DEFW	YESFLG
	DEFB	'-'		;reset?
	DEFW	NOFLG
	DEFB	'S'		;set?
	DEFW	YESFLG
	DEFB	'R'		;reset?
	DEFW	NOFLG
	DEFB	'X'		;scratch?
	DEFW	XFLG
	DEFB	UP		;up arrow?
	DEFW	UFLAG
	DEFB	DOWN		;down arrow?
	DEFW	DFLAG
	DEFB	LEFT		;left arrow?
	DEFW	LFLAG
	DEFB	RIGHT		;right arrow?
	DEFW	RFLAG
	DEFB	ETBL		;end of table
;
