; maile2/asm - kjw/bqsd - version 2.00 - 01/83
;
; revised 02/10/83 - kjw
;
	SUBTTL	'<maile2/asm - file/mask I/O>'
;
	PAGE
;
;	specify search flags with + -
;
FLAGMSK	LD	IX,TABLEB	;lower video table
	LD	IY,TABLEB2	;offset table
;
GETFLP	PUSH	IY		;save
	PUSH	IX		;save
	CALL	SHOWFM		;display flag mask
	POP	IX		;unstack
	POP	IY
;
	LD	L,(IX+0)	;lsb video address
	LD	H,(IX+1)	;msb video address
	LD	A,95		;cursor
	LD	(CURCHR),A	;save it
	CALL	KEY		;wait for a key
	RET	C		;return on BREAK
	JP	Z,GETFNX	;go next if ENTER
	CP	ESCAPE		;escape key?
	RET	Z		;yes, go!
;
	LD	HL,TABLE4M	;edit table
	LD	C,0		;init counter
	CALL	UCASE		;make upper case
	CALL	GOTABLE		;see if valid command
	JR	GETFLP		;nope, wait more
;
RFLAG	INC	C		;+3 = right
LFLAG	INC	C		;+2 = left
DFLAG	INC	C		;+1 = down
UFLAG	EQU	$		;+0 = up
	LD	A,C		;fetch offset
	LD	(FDISY),A	;save into code
	LD	C,(IY+0)	;fetch table entry
FDISY	EQU	$-1
	LD	B,0		;BC = offset
	LD	IX,TABLEB	;video table
	LD	IY,TABLEB2	;start offset table
FDISZ	ADD	IX,BC		;offset to next
	ADD	IY,BC		;add offset
;
;	check for terminator
;
	LD	A,(IX+0)	;fetch a byte
	OR	(IX+1)		;terminator?
	JR	NZ,GETFLP	;go next flag
	JP	SHOWFM		;display results
;
;	set flag
;
SETF	INC	C		;C = 1
;
;	reset flag
;
RESETF	LD	A,(IX+2)	;get flag #
	LD	DE,BUFFER+125	;start of flags
GOTF0	LD	B,1		;test bit
GOTF1	DEC	A		;less flag #
	JR	Z,GOTF2		;go if found
	SLA	B		;shift test bit
	JR	NC,GOTF1	;go for byte
	INC	DE		;bump flag byte
	JR	GOTF0		;go next byte
GOTF2	LD	A,B		;fetch test bit
	CPL			;reverse bits
	LD	B,A		;re-save it
	LD	A,(DE)		;read current flag
	AND	B		;reset bit
	LD	(DE),A		;save result
	DEC	C		;reset?
	JR	NZ,GETFNX	;go next if yes
	LD	A,B		;fetch mask
	CPL			;reverse back
	LD	B,A		;save temp
	LD	A,(DE)		;fetch byte
	OR	B		;set bit
	LD	(DE),A		;save result
;
GETFNX	LD	BC,4		;offset to next entry
	JR	FDISZ		;go next entry
;
	PAGE
;
;	get information from user
;
GETINFO	LD	IX,TABLET	;top video table
	LD	IY,TABLET2	;editor vector table
;
;	special inkeyed editor
;
GETINLP	LD	E,(IX+3)	;data offset
	LD	D,BUFFER<-8	;page data
	LD	B,(IX+2)	;length of input
	LD	L,(IX+0)	;fetch lsb video
	LD	H,(IX+1)	;fetch msb video
	LD	A,EDITCUR	;editor cursor
	LD	(CURCHR),A	;save character
	CALL	KEY		;fetch key
	RET	C		;go if BREAK
	JR	Z,EDITMOD	;go if ENTER
	CP	ESCAPE		;escape key?
	RET	Z		;yes, go!
;
;	evaluate edit command
;
	LD	C,0		;init for vector
	LD	HL,TABLE2	;jump table for arrows
	CALL	GOTABLE		;go if arrow else right
;
;	not an edit key, go next entry
;
	PUSH	AF		;save key
	LD	A,CHARCUR	;character cursor
	LD	(CURCHR),A	;save it
	POP	AF		;restore key
	LD	C,0		;init count
	LD	L,(IX+0)	;fetch LSB video
	LD	H,(IX+1)	;fetch MSB video
	CALL	ONEKEY		;intercept keyboard drvr
	RET	C		;go on BREAK
	JR	ADVNX		;continue
;
EDITMOD	LD	L,(IX+0)	;lsb video
	LD	H,(IX+1)	;msb video
	CALL	SPGET		;special inkey
	RET	C		;go on BREAK
;
ADVNX	LD	BC,4		;offset to next entry
	JR	DISPZ		;continue
;
ADVR	INC	C		;+3 - right
ADVL	INC	C		;+2 - left
ADVD	INC	C		;+1 - down
ADVU	EQU	$		;+0 - up
;
	LD	A,C		;fetch offset
	LD	(DISPY),A	;save for load
	LD	C,(IY+0)	;fetch offset value
DISPY	EQU	$-1
	LD	B,0		;BC = table offset
	LD	IX,TABLET	;top table start
	LD	IY,TABLET2	;top arrow vectors
DISPZ	ADD	IX,BC		;IX => new location
	ADD	IY,BC		;IY => new vectors
;
;	check for completed
;
	LD	A,(IX+0)	;fetch table entry
	OR	(IX+1)		;=0000H?
	JR	NZ,GETINLP	;go if more to do
	RET
;
;	display current file data to video
;
SHOW	LD	IX,TABLET	;top video table
;
	IF	MOD2
	CALL	@VIDON		;enable video memory
	ENDIF
;
SHOWLP	LD	E,(IX+0)	;lsb video address
	LD	D,(IX+1)	;msb video address
	LD	C,(IX+2)	;length this field
	LD	L,(IX+3)	;offset into data
	LD	H,BUFFER<-8	;MSB page of data
	LD	B,0		;BC = length of field
	LDIR			;move into video memory
	LD	BC,4		;offset to next entry
	ADD	IX,BC		;IX => next entry
	LD	A,(IX+0)	;check for 0000 term
	OR	(IX+1)		;=000H?
	JR	NZ,SHOWLP	;go if more
;
	IF	MOD2
	CALL	@VIDOFF		;disable video memory
	ENDIF
;
	RET			;done!
;
;	clear out record buffer for new
;
CLRDATA	LD	A,' '		;load blank
CLRDAT0	LD	HL,BUFFER	;start of data
	LD	DE,BUFFER+1	;start +1
	LD	BC,125		;data length
	LD	(HL),A		;load nil data
	LDIR			;fill record
	LD	(HL),0		;clear flag 0
	LD	C,5		;5 more to do
	LDIR			;3 flag bytes + 3 mask
	RET			;temp buffer cleared
;
;	get user information about mask
;
GETSTUF	CALL	SHOW		;display file
	CALL	SHOWFM		;display flags
GTMST	CALL	GETINFO		;get user info
	JR	C,GTSF		;go flags on BREAK
	CP	ESCAPE		;escape key?
	JR	Z,GTNMS		;go if yes!
GTSF	CALL	FLAGMSK		;get user flags mask
	JR	C,GTMST		;go if BREAK
GTNMS	RET			;done!
;
;	display flags as ON/OFF
;
SHOWF	LD	A,-1		;set flags ON
	LD	HL,BUFFER+125	;start flag data
	JR	SHOWFCM		;go common
;
;	display flags with + - .
;
SHOWFM	XOR	A		;set flags +/-
	LD	HL,BUFFER+128	;start flag mask
;
SHOWFCM	LD	IX,TABLEB	;lower video table
	LD	C,1		;mask test bit
	LD	(FLAGTYP),A	;save flag type
;
	IF	MOD2
	CALL	@VIDON		;enable video
	ENDIF
;
SHOWMLP	LD	A,'$'		;get flag type
FLAGTYP	EQU	$-1
	OR	A		;00?
	LD	A,(HL)		;read flag
	LD	E,(IX+0)	;fetch LSB video
	LD	D,(IX+1)	;fetch MSB video
	JR	NZ,SHOWFOF	;yes, display ON/OFF
	AND	C		;compare mask
	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
;
;	display flags as on/off
;
SHOWFOF	AND	C		;compare with mask
	LD	A,FLON		;flag ON
	JR	NZ,$+4		;go if on
	LD	A,FLOFF		;flag OFF
	JR	SHOWM2		;to video & continue
;
;	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,GETFNX	;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
;
;	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
;
;**
;
;	fetch file block into IX
;
LOCFILE	AND	7		;assure in range!
	ADD	A,A		;*2
	ADD	A,A		;*4
	ADD	A,A		;*8
	ADD	A,A		;*16
	PUSH	BC		;save
	LD	C,A		;pass LSB
	LD	B,0		;BC = offset
	LD	IX,FTABLE	;file table
	ADD	IX,BC		;IX => entry
	POP	BC		;restore
	RET			;done!
;
;	fetch memory from TOPMEM
;	NC = out of memory!
;
GETHIGH	TOPMEM$			;get topmem
	RET			;HL = topmem
;
;	get new buffer position
;
GETBUFF	LD	DE,$		;get current topmem
HIGH	EQU	$-2
	DEC	D		;less one page
	LD	(HIGH),DE	;update high$
	LD	HL,PGMEND	;end of program
	OR	A		;clear carry
	SBC	HL,DE		;compare free memory
	RET			;NC = out of memory!
;
;	fetch a sorted record from all active files
;
FETCH	LD	HL,SORTBUF	;sorting buffer
	LD	(POSIT),HL	;save position in memory
	LD	(IY+38),0	;set # recs in memory
	LD	(IY+21),0	;set no error condition
	LD	HL,FETCH1	;fetch a record
	CALL	COMMON		;do all drives
	LD	A,(IY+21)	;any errors?
	OR	A		;return with flags
	RET	NZ		;go if any errors
	LD	A,(IY+38)	;get # recs in memory
	OR	A		;any?
	RET	Z		;nope, go!
;
;	sort temp records in memory
;
	LD	HL,SORTBUF	;start sort buffer
	LD	B,A		;B = # records
	LD	D,H		;pass to DE
	LD	E,L		;HL = DE
	LD	(BASE),HL	;save start
;
SRTLP	CALL	SCOMP		;compare index's
	JR	NC,SRTLP1	;go if not less
	LD	(BASE),DE	;save new low address
;
SRTLP1	PUSH	HL		;save
	LD	HL,24		;length of each entry
	ADD	HL,DE		;HL => next entry
	EX	DE,HL		;DE => next
	POP	HL		;restore HL
	DJNZ	SRTLP		;finish sorting!
	LD	HL,$		;get base address
BASE	EQU	$-2
	LD	DE,20
	ADD	HL,DE		;HL => record #
	PUSH	IY		;save IY
	LD	B,3		;move 3 bytes
SRTLP2	LD	A,(HL)		;get record # byte
	LD	(IY+7),A	;save as current rec #
	INC	HL		;bump pointers
	INC	IY
	DJNZ	SRTLP2		;finish record #
	POP	IY		;restore IY
	LD	A,(HL)		;get drive #
	AND	7		;force in range
	LD	(IY+14),A	;pass where record came
;
;	adjust pointers on current file
;
	CALL	LOCFILE		;locate file block
	LD	L,(IX+4)	;get buffer posit
	LD	H,(IX+5)
	LD	DE,23		;# bytes pulled out
	ADD	HL,DE		;HL => new address
	LD	(IX+4),L	;update buffer posit
	LD	(IX+5),H
	INC	(IX+9)		;bump # records pulled
	LD	B,(IX+6)	;get # records remaining
	LD	H,(IX+7)
	LD	L,(IX+8)
	CALL	DECBHL		;decrement BHL
	LD	(IX+6),B	;update count
	LD	(IX+7),H
	LD	(IX+8),L
	JP	READREC		;read record & return
;
;	compare current record
;
SCOMP	PUSH	BC		;save all
	PUSH	DE
	PUSH	HL
	LD	HL,(BASE)	;get base address
	LD	B,20		;20 char index
;
SCOMP1	LD	A,(DE)		;get a byte
	CP	(HL)		;match?
	JR	NZ,SCOMP2	;go if not
	INC	DE		;bump pointers
	INC	HL
	DJNZ	SCOMP1		;go for length
;
SCOMP2	POP	HL		;unstack
	POP	DE
	POP	BC
	RET			;done
;
;	fetch a single record from current file
;
FETCH1	LD	A,(IY+21)	;any errors on a file?
	OR	A		;yes?
	RET	NZ		;yes, abort operation!
;
	LD	A,C		;get drive #
	AND	7		;force in range
	LD	(FETDRV),A	;save drive #
	CALL	LOCFILE		;IX => file block
	LD	A,(IX+0)	;file available?
	AND	(IX+1)
	INC	A		;= FFFFH?
	RET	Z		;yes, skip drive!
;
	LD	A,(IX+6)	;any records here?
	OR	(IX+7)
	OR	(IX+8)
	RET	Z		;nope, all pulled out!
;
	LD	A,(IX+9)	;# records pulled
	CP	11		;max pulled?
	JR	C,RECINM	;nope, record in memory!
;
;	preserve contents of current I/O buffer
;	in case of immediate record update!
;
	PUSH	IX		;save file block
	LD	A,(FETDRV)	;get drive #
	CALL	LOCFCB		;locate FCB block
	LD	L,(IX+17)	;get I/O buff address
	LD	H,(IX+18)	;HL => buffer
	POP	IX		;restore file block
;
	LD	(RDADD),HL	;save I/O buffer addr
	LD	E,(IX+2)	;get temp buffer storage
	LD	D,(IX+3)
	LD	(TMADD),DE	;save temp buffer
	LD	BC,100H		;buffer length
	LDIR			;move it in!
;
	LD	E,(IX+2)	;get I/O buffer address
	LD	D,(IX+3)
	LD	(IX+4),E	;update new posit
	LD	(IX+5),D
	LD	(IX+9),0	;# records pulled
	LD	E,(IX+0)	;get FCB address
	LD	D,(IX+1)
	LD	B,(IX+12)	;get physical sector #
	LD	H,(IX+13)
	LD	L,(IX+14)
	CALL	INCBHL		;increment phys sector
	LD	(IX+12),B	;update new posit
	LD	(IX+13),H
	LD	(IX+14),L
;
	PUSH	IX		;pass IX => HL
	POP	HL		;HL => IX
	LD	BC,12		;offset to physical sect
	ADD	HL,BC		;HL => sector #
	LD	B,H		;pass to BC
	LD	C,L		;BC => sector #
	POSN$			;position to record
	JR	NZ,FETERR	;go on error!
	READ$			;read next sector
;
FETERR	PUSH	AF		;save error code
	LD	HL,$		;get I/O buffer address
RDADD	EQU	$-2
	LD	DE,$		;get temp buffer addr
TMADD	EQU	$-2
	LD	B,0		;go for 256 bytes
;
;	swap buffers!
;
SWPLP	LD	C,(HL)		;get first
	LD	A,(DE)		;get second
	LD	(HL),A		;to first
	LD	A,C		;get first
	LD	(DE),A		;to second
	INC	HL		;bump pointers
	INC	DE
	DJNZ	SWPLP		;go for 256 bytes
	POP	AF		;restore I/O status
	JR	NZ,ERRFET	;go if error!
;
;	move current record into memory sort buffer
;
RECINM	LD	L,(IX+4)	;get buffer posit
	LD	H,(IX+5)	;HL => record
	LD	DE,$		;fetch current position
POSIT	EQU	$-2
	LD	BC,23		;length of record
	LDIR			;move it in
	LD	A,'$'		;fetch drive #
FETDRV	EQU	$-1
	LD	(DE),A		;to buffer
	INC	DE		;bump pointer
	LD	(POSIT),DE	;update position
	INC	(IY+38)		;bump # records in memory
	RET			;done!
;
;	error on fetch, save error code
;
ERRFET	LD	(IY+21),A	;save error code
	RET			;done!
;
;	setup indicated files to be used
;
OPENIT	LD	A,(IY+21)	;any errors?
	OR	A		;yes?
	RET	NZ		;yes, go!
;
	LD	A,C		;get drive #
	LD	(OPEND),A	;save it
;
	PUSH	IX		;save IX
	CALL	LOCFILE		;locate file block
	LD	(IX+0),-1	;set as inactive
	LD	(IX+1),-1
	LD	(FTST),IX	;pass table start
	POP	IX		;restore IX
;
	BIT	7,(IX+0)	;file open?
	RET	Z		;nope, go!
	BIT	4,(IX+0)	;flagged to be opened?
	RET	Z		;nope, go!
	BIT	6,(IX+0)	;file sorted?
	RET	Z		;cannot use!
	LD	A,'$'		;get sort mask
SORTF	EQU	$-1
	OR	A		;anything yet?
	JR	Z,PUTSR		;go if no field
	CP	(IX+13)		;same field?
	RET	NZ		;go if not!
PUTSR	LD	(SORTF),A	;save it!
;
;	read first sector to fetch flags
;
	LD	E,(IX+15)	;get FCB address
	LD	D,(IX+16)
	LD	BC,REWIND	;3 00's
;
	POSN$			;rewind file!
	JR	NZ,OPNERR	;go if error!
	READ$			;read first record
	JR	NZ,OPNERR	;go if any errors
;
;	setup activity block
;
;	+0,1	- FCB address
;	+2,3	- I/O buffer start address
;	+4,5	- I/O buffer position
;	+6,7,8	- # records remaining in file
;	+9	- # records pulled current buffer
;	+10,11	- address of flags in memory
;	+12,13,14 - physical sector #
;	+15	- work byte
;
	PUSH	IY		;save IY
	LD	IY,$		;get table address
FTST	EQU	$-2
	LD	E,(IX+15)	;get FCB address
	LD	D,(IX+16)
	LD	(IY+0),E	;pass to table
	LD	(IY+1),D
	CALL	GETBUFF		;allocate I/O buffer
	JP	NC,OUTMEM	;out of memory!
	LD	(IY+2),E	;pass buffer
	LD	(IY+3),D
	LD	(IY+4),E	;pass current posit
	LD	(IY+5),D
	LD	B,(IX+10)	;get # records used
	LD	H,(IX+11)
	LD	L,(IX+12)
	LD	(IY+6),B	;pass # left
	LD	(IY+7),H
	LD	(IY+8),L
	LD	(IY+9),-1	;# pulled curr buff
	LD	(IY+12),0	;set physical sector #
	LD	(IY+13),0
	LD	(IY+14),0
;
;	move flag names into storage buffer
;
	LD	L,'$'		;get drive #
OPEND	EQU	$-1
	LD	H,0		;HL = drive #
	ADD	HL,HL		;*2
	LD	D,H		;pass to DE
	LD	E,L
	ADD	HL,HL		;*4
	ADD	HL,DE		;*6
	ADD	HL,HL		;*12
	ADD	HL,HL		;*24
	ADD	HL,HL		;*48
	ADD	HL,HL		;*96
	ADD	HL,HL		;*192
	LD	DE,FLAGBUF	;start flag buffer
	ADD	HL,DE		;HL => this drive store
	EX	DE,HL		;DE => drive storage
	LD	(IY+10),E	;pass address
	LD	(IY+11),D
	LD	L,(IX+17)	;get buff address
	LD	H,(IX+18)
	LD	BC,40H		;offset to flag names
	ADD	HL,BC		;HL => names
	LD	BC,24*8		;length of flags
	LDIR			;move into buffer
	POP	IY		;restore sys pointer
	INC	(IY+22)		;bump # active files
	XOR	A		;return no error
	RET			;done!
;
;	open error!
;
OPNERR	LD	(IY+21),A	;save error condition
	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
;
;	check if mask matches buffer
;
MATCH	BIT	2,(IY+1)	;any conditions?
	RET	Z		;nope, match!
;
	LD	DE,BUFFER	;DE => current record
	LD	BC,CONDBUF	;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
;
;	read current record from file
;
READREC	LD	A,(IY+14)	;get drive #
	CALL	LOCFCB		;locate FCB block
;
	LD	B,(IY+7)	;MSB record #
	LD	H,(IY+8)	;NSB
	LD	L,(IY+9)	;LSB
	CALL	COMPSEC		;compute sector offset
	LD	(IY+13),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
;
;	read record from disk
;
	LD	(IY+10),B	;set new rec in buffer
	LD	(IY+11),H
	LD	(IY+12),L
	LD	E,(IX+15)	;fetch FCB pointer
	LD	D,(IX+16)	;DE => fcb
	LD	BC,SYSTEM+10	;point to rec #
;
	POSN$			;position to record
	RET	NZ		;go if error
	READ$			;read record
	RET	NZ		;go if any errors!
;
;	move current I/O buff => buffer
;
	LD	L,(IX+17)	;get buffer address
	LD	H,(IX+18)
	LD	E,(IY+13)	;get data offset
	LD	D,0		;DE = offset
	ADD	HL,DE		;HL => record data
	LD	DE,BUFFER	;move it here
	LD	BC,128		;length
	LDIR			;move it in
	XOR	A		;set Z status
	RET			;done
;
;	write current record to disk
;
WRITREC	LD	A,(IY+14)	;get drive #
	CALL	LOCFCB		;locate FCB block
	LD	BC,SYSTEM+10	;point to rec #
	LD	E,(IX+15)	;lsb FCB pointer
	LD	D,(IX+16)	;DE => fcb
;
	POSN$			;position to record
	RET	NZ		;go if error
	WRITE$			;write the record
	RET			;return with status
;
;	new page, display header
;
NEWPAGE	BIT	7,(IY+1)	;counting?
	RET	NZ		;yes, skip pagenation
	BIT	6,(IY+1)	;labels?
	RET	Z		;yes, skip
;
	LD	A,(IY+20)	;get line counter
	OR	A		;at top of page?
	CALL	NZ,FORM		;go to top of form
	LD	HL,MESSAGE	;message text
	CALL	LPRINT		;print it
	LD	A,80-11		;cols - page #
	BIT	5,(IY+1)	;80 col printer?
	JR	Z,$+4		;go if yes
	LD	A,132-11	;cols - page #
	CALL	POSPRT		;position printer here
	LD	HL,MSG13	;'page'
	CALL	LPRINT		;print it
	LD	HL,0		;get page counter
PAGE	EQU	$-2
	INC	HL		;+1
	LD	(PAGE),HL	;update
	LD	B,0		;BHL = page number
	LD	DE,TEXT		;dummy storage
	PUSH	DE		;save start
	CALL	BINASC		;binary => ascii
	POP	HL		;HL => start
	INC	HL		;strip 3 digits
	INC	HL
	INC	HL		;page count to 65536
	CALL	LPRINT		;print the line
	CALL	LINE		;print line
	CALL	LINE		;print blank line
	JP	DASHES		;line of dashes & return
;
;	move printer to top of next form
;
FORM	LD	A,(IY+20)	;get line counter
	CP	66		;at top of page
	JR	NC,FORME	;yes, done!
	CALL	LINE		;advance a line
	JR	FORM		;go again
;
FORME	LD	(IY+20),0	;at top of form
	RET			;done!
;
;	flush printer or advance blank line
;
LINE	LD	A,(IY+19)	;get char counter
	OR	A		;any chars in buffer?
	JR	NZ,LINEE	;go if chars there
	LD	A,' '		;else send blank
	CALL	POUT		;to printer
LINEE	LD	A,CR		;send carriage return
	JP	POUT		;to printer
;
;	send string to printer
;
LPRINT	LD	A,(HL)		;get string byte
	CP	ETX		;done?
	RET	Z		;yes, go!
	INC	HL		;bump pointer
	CALL	POUT		;send to printer
	JR	LPRINT		;go more
;
;	position printer to column specified in A
;
POSPRT	CP	(IY+19)		;compare to char counter
	RET	C		;go if < char count
	RET	Z		;go if = char count
	PUSH	AF		;save
	LD	A,' '		;load blank
	CALL	POUT		;to printer
	POP	AF		;restore count
	JR	POSPRT		;continue
;
;##
;
;	table of locations for file data
;
;	+0,1	= video memory for field
;	+2	= length of entry
;	+3	= offset into data field
;
	IF	MOD1.OR.MOD3.OR.LDOSSVC
TABLET	DEFW	@VIDEO+192+8	;last
	DEFB	15,0
	DEFW	@VIDEO+192+32	;first
	DEFB	10,15
	DEFW	@VIDEO+256+11	;company
	DEFB	20,25
	DEFW	@VIDEO+320+12	;addr 1
	DEFB	20,45
	DEFW	@VIDEO+320+48	;addr 2
	DEFB	10,65
	DEFW	@VIDEO+384+8	;city
	DEFB	15,75
	DEFW	@VIDEO+384+33	;state
	DEFB	8,90
	DEFW	@VIDEO+384+48	;zip
	DEFB	10,98
	DEFW	@VIDEO+192+50	;data 1
	DEFB	5,108
	DEFW	@VIDEO+256+50	;data 2
	DEFB	12,113
	DEFW	0000H		;terminator
	ENDIF
;
	IF	MOD2
TABLET	DEFW	@VIDEO+240+9	;last
	DEFB	15,0
	DEFW	@VIDEO+240+36	;first
	DEFB	10,15
	DEFW	@VIDEO+320+12	;company
	DEFB	20,25
	DEFW	@VIDEO+400+13	;addr 1
	DEFB	20,45
	DEFW	@VIDEO+400+52	;addr 2
	DEFB	10,65
	DEFW	@VIDEO+480+9	;city
	DEFB	15,75
	DEFW	@VIDEO+480+37	;state
	DEFB	8,90
	DEFW	@VIDEO+480+58	;zip
	DEFB	10,98
	DEFW	@VIDEO+240+60	;data 1
	DEFB	5,108
	DEFW	@VIDEO+320+60	;data 2
	DEFB	12,113
	DEFW	0000H		;terminator
	ENDIF
;
;	lookup table for editing commands
;
;	each entry is offset for UP/DOWN/LEFT/RIGHT
;
TABLET2	DEFB	00,08,28,04	;last
	DEFB	04,08,00,32	;first
	DEFB	00,12,32,36	;company
	DEFB	08,20,36,16	;addr 1
	DEFB	36,28,12,20	;addr 2
	DEFB	12,20,16,24	;city
	DEFB	12,24,20,28	;state
	DEFB	16,28,24,00	;zip
	DEFB	32,36,04,08	;data 1
	DEFB	32,16,08,12	;data 2
	DEFB	00,00,00,00	;terminator
;
;	video tables for flag placement
;
	IF	MOD1.OR.MOD3.OR.LDOSSVC
TABLEB	DEFW	@VIDEO+512+12	;1
	DEFB	1,-1
	DEFW	@VIDEO+512+18	;2
	DEFB	2,-1
	DEFW	@VIDEO+512+24	;3
	DEFB	3,-1
	DEFW	@VIDEO+512+30	;4
	DEFB	4,-1
	DEFW	@VIDEO+512+36	;5
	DEFB	5,-1
	DEFW	@VIDEO+512+42	;6
	DEFB	6,-1
	DEFW	@VIDEO+512+48	;7
	DEFB	7,-1
	DEFW	@VIDEO+512+54	;8
	DEFB	8,-1
	DEFW	@VIDEO+576+12	;9
	DEFB	9,-1
	DEFW	@VIDEO+576+18	;10
	DEFB	10,-1
	DEFW	@VIDEO+576+24	;11
	DEFB	11,-1
	DEFW	@VIDEO+576+30	;12
	DEFB	12,-1
	DEFW	@VIDEO+576+36	;13
	DEFB	13,-1
	DEFW	@VIDEO+576+42	;14
	DEFB	14,-1
	DEFW	@VIDEO+576+48	;15
	DEFB	15,-1
	DEFW	@VIDEO+576+54	;16
	DEFB	16,-1
	DEFW	@VIDEO+640+12	;17
	DEFB	17,-1
	DEFW	@VIDEO+640+18	;18
	DEFB	18,-1
	DEFW	@VIDEO+640+24	;19
	DEFB	19,-1
	DEFW	@VIDEO+640+30	;20
	DEFB	20,-1
	DEFW	@VIDEO+640+36	;21
	DEFB	21,-1
	DEFW	@VIDEO+640+42	;22
	DEFB	22,-1
	DEFW	@VIDEO+640+48	;23
	DEFB	23,-1
	DEFW	@VIDEO+640+54	;24
	DEFB	24,-1
	DEFW	0000H		;terminator
	ENDIF
;
	IF	MOD2
TABLEB	DEFW	@VIDEO+640+13	;1
	DEFB	1,-1
	DEFW	@VIDEO+640+20	;2
	DEFB	2,-1
	DEFW	@VIDEO+640+27	;3
	DEFB	3,-1
	DEFW	@VIDEO+640+34	;4
	DEFB	4,-1
	DEFW	@VIDEO+640+41	;5
	DEFB	5,-1
	DEFW	@VIDEO+640+48	;6
	DEFB	6,-1
	DEFW	@VIDEO+640+55	;7
	DEFB	7,-1
	DEFW	@VIDEO+640+62	;8
	DEFB	8,-1
	DEFW	@VIDEO+720+13	;9
	DEFB	9,-1
	DEFW	@VIDEO+720+20	;10
	DEFB	10,-1
	DEFW	@VIDEO+720+27	;11
	DEFB	11,-1
	DEFW	@VIDEO+720+34	;12
	DEFB	12,-1
	DEFW	@VIDEO+720+41	;13
	DEFB	13,-1
	DEFW	@VIDEO+720+48	;14
	DEFB	14,-1
	DEFW	@VIDEO+720+55	;15
	DEFB	15,-1
	DEFW	@VIDEO+720+62	;16
	DEFB	16,-1
	DEFW	@VIDEO+800+13	;17
	DEFB	17,-1
	DEFW	@VIDEO+800+20	;18
	DEFB	18,-1
	DEFW	@VIDEO+800+27	;19
	DEFB	19,-1
	DEFW	@VIDEO+800+34	;20
	DEFB	20,-1
	DEFW	@VIDEO+800+41	;21
	DEFB	21,-1
	DEFW	@VIDEO+800+48	;22
	DEFB	22,-1
	DEFW	@VIDEO+800+55	;23
	DEFB	23,-1
	DEFW	@VIDEO+800+62	;24
	DEFB	24,-1
	DEFW	0000H		;terminator
	ENDIF
;
;	lookup table for editing flags
;
TABLEB2	DEFB	00,32,92,04	;1	-00
	DEFB	04,36,00,08	;2	-04
	DEFB	08,40,04,12	;3	-08
	DEFB	12,44,08,16	;4	-12
	DEFB	16,48,12,20	;5	-16
	DEFB	20,52,16,24	;6	-20
	DEFB	24,56,20,28	;7	-24
	DEFB	28,60,24,32	;8	-28
;
	DEFB	00,64,28,36	;9	-32
	DEFB	04,68,32,40	;10	-36
	DEFB	08,72,36,44	;11	-40
	DEFB	12,76,40,48	;12	-44
	DEFB	16,80,44,52	;13	-48
	DEFB	20,84,48,56	;14	-52
	DEFB	24,88,52,60	;15	-56
	DEFB	28,92,56,64	;16	-60
;
	DEFB	32,64,60,68	;17	-64
	DEFB	36,68,64,72	;18	-68
	DEFB	40,72,68,76	;19	-72
	DEFB	44,76,72,80	;20	-76
	DEFB	48,80,76,84	;21	-80
	DEFB	52,84,80,88	;22	-84
	DEFB	56,88,84,92	;23	-88
	DEFB	60,92,88,00	;24	-92
	DEFB	00,00,00,00	;terminator
;
;	lookup table for screen editing arrows
;
TABLE2	DEFB	LEFT		;left arrow
	DEFW	ADVL
	DEFB	RIGHT		;right arrow
	DEFW	ADVR
	DEFB	UP		;up arrow
	DEFW	ADVU
	DEFB	DOWN		;down arrow
	DEFW	ADVD
	DEFB	ETBL		;end of table
;
;	table for flag command vectors
;
TABLE4	DEFB	'Y'		;turn flag on?
	DEFW	SETF
	DEFB	'S'		;set flag?
	DEFW	SETF
	DEFB	'+'		;set flag?
	DEFW	SETF
	DEFB	'N'		;turn flag off?
	DEFW	RESETF
	DEFB	'R'		;reset flag?
	DEFW	RESETF
	DEFB	'-'
	DEFW	RESETF
	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
;
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
;
TEXT	DEFM	'xxxxxxxx'
	DEFB	ETX
;
