; mail/asm - kjw/bqsd - version 2.00 - 01/83
;
; revised 02/23/83 - kjw
;
	TITLE	'<PowerMAIL - 2.00 source code>'
;
	SUBTTL	'<mail/asm - system equates>'
;
*GET	MAILEQU			;logical equivalences
;
;	local equivalences
;
	IF	MOD1.OR.MOD3.OR.LDOSSVC
TLCORN	EQU	0BCH		;graphic corners
MLCORN	EQU	0BFH
BLCORN	EQU	08FH
TRCORN	EQU	0BCH
MRCORN	EQU	0BFH
BRCORN	EQU	08FH
THBAR	EQU	083H		;horiz bar
MHBAR	EQU	08CH
LHBAR	EQU	0B0H
VBAR	EQU	0BFH		;vert bar
	ENDIF
;
	IF	MOD2
TLCORN	EQU	000H		;corner graphics
MLCORN	EQU	007H
BLCORN	EQU	003H
TRCORN	EQU	001H
MRCORN	EQU	005H
BRCORN	EQU	002H
THBAR	EQU	016H		;horiz bar
MHBAR	EQU	016H
LHBAR	EQU	016H
VBAR	EQU	014H		;vert bar
;
@INITIO	EQU	00		;init I/O devices
@SETBRK	EQU	03		;break processor
@SCROLL	EQU	27		;scroll protect
@HLDKEY	EQU	29		;hold key processor
	ENDIF
;
	SUBTTL	'<mail/asm - memory assignments>'
;
;	begin actual data tables
;
	ORG	DATA
;
FCBTBL	DEFW	BLOCK0		;drive 0
	DEFW	BLOCK1		;drive 1
	DEFW	BLOCK2		;drive 2
	DEFW	BLOCK3		;drive 3
	DEFW	BLOCK4		;drive 4
	DEFW	BLOCK5		;drive 5
	DEFW	BLOCK6		;drive 6
	DEFW	BLOCK7		;drive 7
;
;	data blocks for each file
;
;	+0	7 = 1 = file OPEN
;		6 = 1 = file SORTED
;		5 = 1 = recovery mode on file
;		4 = 1 = drive specified to be opened
;		3 = unused
;		2,1,0 = binary drive number
;	+1,2,3	= ending record number for file
;	+4,5,6	= start record number for data
;	+7,8,9	= # records available
;	+10,11,12 = # records used
;	+13	= sort field #1 for index
;	+14	= sort field #2 for index
;	+15,16	= address of FCB
;	+17,18	= address of I/O buffer
;
BLOCK0	DEFB	0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0
	DEFW	FCB0
	DEFW	BUFF0
BLOCK1	DEFB	1
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0
	DEFW	FCB1
	DEFW	BUFF1
BLOCK2	DEFB	2
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0
	DEFW	FCB2
	DEFW	BUFF2
BLOCK3	DEFB	3
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0
	DEFW	FCB3
	DEFW	BUFF3
BLOCK4	DEFB	4
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0
	DEFW	FCB4
	DEFW	BUFF4
BLOCK5	DEFB	5
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0
	DEFW	FCB5
	DEFW	BUFF5
BLOCK6	DEFB	6
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0
	DEFW	FCB6
	DEFW	BUFF6
BLOCK7	DEFB	7
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0,0
	DEFB	0,0
	DEFW	FCB7
	DEFW	BUFF7
;
;	string input and temporary FCB
;
STRING	DEFM	'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
	DEFM	'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
;
;	resident system data (IY always points here)
;
SYSTEM	DEFB	0		;+0 - system flags
; 7 = 1 = PMAIL/ADD available
; 6 = 1 = PMAIL/DAT available
; 5 = 1 = recovery mode issued
; 4 = 1 = command line issued
; 3 = used by sub-modules
; 2 = used by sub-modules
; 1 = keys input current $GETSTR call
; 0 = used by sub-modules
	DEFB	0		;+1 - system flags
	DEFW	0		;+2,3 - stack pointer
	DEFB	0,0,0		;+4,5,6 - # recs in adder
	DEFB	0,0,0		;+7,8,9 - available
	DEFB	0,0,0		;+10,11,12 - available
	DEFB	0,0,0		;+13,14,15 - available
	DEFB	0,0,0		;+16,17,18 - available
	DEFB	0,0,0		;+19,20,21 - available
	DEFB	0,0,0		;+22,23,24 - available
	DEFB	0,0,0		;+25,26,27 - available
	DEFB	0,0,0		;+28,29,30 - available
	DEFB	0		;+32	- init flag (*)
	DEFB	0,0,0		;+33,34,35 - extra
	DEFB	0,0,0		;+36,37,38 - extra
	DEFB	0		;+39	   - extra
;
*GET	MAILDISK		;machine dependent I/O
*GET	MAILDVRS		;char I/O drivers
*GET	MAILMATH		;math subroutines
;
;	begin actual program data
;
ENTRY	LD	IY,SYSTEM	;init system data pointer
	CALL	INTEG		;check sys integrety
	EX	DE,HL		;DE => input pointer
	LD	HL,0		;init HL
	ADD	HL,SP		;HL = stack pointer
	LD	(IY+2),L	;save stack pointer
	LD	(IY+3),H	;IY+2,3 = entry stack
;
	RES	0,(IY+0)	;abort if invalid cmd
ALTENT	LD	(IY+31),'*'	;set as inited
	RES	4,(IY+0)	;set NO commands issued
	LD	A,ETX		;end of text
	LD	(AFILEA-1),A	;set global ADDER file
	CALL	PARSE		;parse command line
;
;	init mod II specifics
;
	IF	MOD2
	LD	A,@INITIO	;SVC #
	RST	SVC		;reset I/O drivers
	LD	HL,0		;load zero
	LD	A,@SETBRK	;SVC #
	RST	SVC		;disable break processor
	LD	B,0		;lines to protect
	LD	A,@SCROLL	;SVC #
	RST	SVC		;protect 0 lines
	LD	B,0		;disable processor
	LD	A,@HLDKEY	;SVC #
	RST	SVC		;disable hold processor
	LD	A,CUROFF	;cursor off char
	CALL	VOUT		;to display
	ENDIF
;
	LD	HL,MSG00	;header
	CALL	DISPLAY		;display
	LD	HL,MSG0		;titles
	CALL	DISPLAY		;header
	CALL	BORDER		;display border
	CALL	OPEN		;open all files
	BIT	6,(IY+0)	;any data available?
	JP	Z,NODATA	;nope, go INIT!
	BIT	5,(IY+0)	;recovery mode issued?
	JP	NZ,RECOVER	;yes, go!
	LD	HL,MSG13	;'all files opened'
	CALL	DISPLAY		;display
	CALL	INKEY		;get a key
;
;	display menu and fetch options
;
MENU	LD	IY,SYSTEM	;reset data pointer
	LD	L,(IY+2)	;init stack
	LD	H,(IY+3)
	LD	SP,HL		;inited
	LD	HL,MSG1		;menu options
	CALL	DISPLAY		;display options
	LD	B,1		;one key input
	CALL	GETSTR		;fetch from keyboard
	JR	C,MENU		;go if BREAK
	JR	Z,MENU		;go on nil input
	LD	HL,TABLE1	;menu jump table
	LD	BC,MERROR	;error exit vector
	CALL	GOTABLE		;go vector if valid entry
	JR	MENU		;invalid, ask again
;
;	redraw video
;
REDRAW	LD	HL,MSG00	;header
	CALL	DISPLAY		;display it
	LD	HL,MSG0		;fields
	CALL	DISPLAY		;display them
	CALL	BORDER		;display graphic border
	JR	MENU		;back to menu
;
;	no data files, run init program
;
NODATA	LD	HL,MSG2		;'no data available'
	CALL	DISPLAY		;display message
	CALL	INKEY		;get a key
	JR	C,MENU		;go if BREAK
	LD	BC,MERROR	;error exit
;
;	run INIT module
;
INIT	LD	HL,PGM1		;INIT module
	JP	RUNPGM		;run module
;
;	run ADD module
;
ENTER	BIT	7,(IY+0)	;ADDER available?
	LD	HL,PGM2		;ADD module
	JP	NZ,RUNPGM	;run program if yes
	LD	HL,MSG3		;'adder not available'
	JR	CANTRUN		;cannot run module!
;
;	run EDIT module
;
EDIT	BIT	6,(IY+0)	;DATA available?
	LD	HL,PGM3		;EDIT module
	JP	NZ,RUNPGM	;run program if yes
NOTDATA	LD	HL,MSG4		;'data not available'
;
;	data file not available for function
;
CANTRUN	CALL	CLS		;clear lower video
	CALL	DISPLAY		;display message
	LD	HL,MSG34	;'not available'
	CALL	DISPLAY		;display it
	CALL	INKEY		;wait for key
	JR	MENU		;go back to menu
;
;	run UTILITY section
;
UTILITY	LD	A,(IY+0)	;get sys flags
	AND	0C0H		;bit 7 or 6?
	JR	Z,NOTDATA	;no data available!
	RES	5,(IY+0)	;set NOT recovery
;
RECOVER	LD	HL,PGM4		;utility module
	JP	RUNPGM		;run program
;
;	run PRINT module
;
PRINT	BIT	6,(IY+0)	;DATA available?
	JR	Z,NOTDATA	;no data available
	LD	HL,PGM5		;print module
	JP	RUNPGM		;run program
;
;	error encountered
;
MERROR	PUSH	AF		;save error code
	CALL	CLS		;clear lower video
	POP	AF		;A = error code
;
	CALL	ERROR		;display error
	LD	HL,MSG5		;'key to continue'
	CALL	DISPLAY		;display error
	CALL	INKEY		;get from keyboard
	JP	MENU		;back to menu
;
;	display error message
;
ERROR	ERROR$			;display error message
	RET
;
;	remount new diskettes
;
MOUNT	SET	0,(IY+0)	;set MOUNT flag
	JR	EXITCM		;continue
;
;	exit program vector
;
EXIT	RES	0,(IY+0)	;set EXIT flag
EXITCM	CALL	CLS		;clear lower video
	LD	(IY+31),0	;clear re-init flag
	LD	HL,GAPPER	;adder + gap
	CALL	DISPLAY		;display header
	BIT	7,(IY+0)	;adder file available?
	LD	HL,MSG12	;not available
	JP	Z,ACLSCNT	;nope, continue
;
;	update information to adder
;
	LD	DE,FCBA		;adder FCB
	LD	BC,REWIND	;3 byte record
	POSN$			;position to record
	JR	NZ,ACLSER	;error!
	READ$			;read next record
	JR	NZ,ACLSER	;error!
	LD	A,(IY+4)	;MSB adder records
	LD	(BUFFA),A	;to I/O buffer
	LD	A,(IY+5)	;get NSB
	LD	(BUFFA+1),A	;to buffer
	LD	A,(IY+6)	;get LSB
	LD	(BUFFA+2),A	;to buffer
	LD	BC,REWIND	;first record
	POSN$			;position to record
	JR	NZ,ACLSER	;error!
	WRITE$			;write first record
	JR	NZ,ACLSER	;go if error
;
;	close adder file
;
	CLOSE$			;close file
	RES	7,(IY+0)	;set not available
	JR	NZ,ACLSER	;go if error
	LD	HL,MSG11	;'closed'
;
ACLSCNT	CALL	DISPLAY		;display it
	LD	A,CR		;send carriage return
	CALL	VOUT		;to video
	JR	CLSDATA		;continue
;
ACLSER	CALL	ERROR		;display error
;
;	close all data files
;
CLSDATA	LD	HL,MSG8		;data file text
	CALL	DISPLAY		;display header
	BIT	6,(IY+0)	;any data available?
	LD	HL,MSG12	;'not available'
	JR	Z,NDATCLS	;go if no data
;
	RES	3,(IY+0)	;reset close error flag
	LD	HL,CLSLOOP	;subroutine
	CALL	COMMON		;go common
;
;	check for errors
;
	BIT	3,(IY+0)	;any errors?
	LD	HL,MSG11	;'closed'
	JR	Z,NDATCLS	;go if OK
	LD	HL,MSG14	;'close error(s)'
NDATCLS	CALL	DISPLAY		;display
	RES	6,(IY+0)	;set NO data
	BIT	0,(IY+0)	;MOUNT?
	JR	NZ,MOUNTIT	;yes, go!
	LD	HL,MSG5		;key to continue
	CALL	DISPLAY		;display prompt
	CALL	INKEY		;wait for a key
;
;	re-draw header and clear screen
;
ABORT	LD	HL,MSG00	;header message
	CALL	DISPLAY		;display it
;
GODOS	EXIT$			;exit to dos
	JP	MENU		;returned!?
;
;	mount new diskettes
;
MOUNTIT	LD	HL,PARCLR	;subroutine
	CALL	COMMON		;do all drives
	LD	HL,MSG15	;'mount new disk, key'
	CALL	DISPLAY		;display
	LD	B,20		;input length
	CALL	GETSTR		;get from keyboard
	JP	C,ABORT		;bail to EXIT with BREAK
	LD	IY,SYSTEM	;init system
	EX	DE,HL		;DE => input
	LD	L,(IY+2)	;init stack
	LD	H,(IY+3)
	LD	SP,HL		;inited
	JP	ALTENT		;go entry!
;
CLSLOOP	BIT	7,(IX+0)	;file open?
	RET	Z		;nope, skip it
	RES	7,(IX+0)	;set NOT open
;
;	update data count to file
;
	LD	BC,REWIND	;3 00's
	POSN$			;position to first record
	JR	NZ,CLSERR	;go if error
;
	READ$			;read first sector
	JR	NZ,CLSERR	;go if error
;
;	move file block into first sector
;
	PUSH	IX		;pass IX to HL
	POP	HL		;HL => file block
	PUSH	DE		;save FCB address
	LD	E,(IX+17)	;get buffer
	LD	D,(IX+18)	;DE => I/O buffer
	LD	BC,15		;length to move
	LDIR			;move block into sector
	POP	DE		;get FCB back
;
	LD	BC,REWIND	;first record
	POSN$			;position to record
	JR	NZ,CLSERR	;go if error
	WRITE$			;write first sector
	JR	NZ,CLSERR	;go if error
;
	CLOSE$			;close file
	RET	Z		;return if no error
;
CLSERR	SET	3,(IY+0)	;set close error
;
;	display error and wait to continue
;
ERRWAIT	CALL	ERROR		;display error
	LD	HL,MSG5		;key to continue
	CALL	DISPLAY		;display message
	CALL	INKEY		;wait for a key
	LD	HL,MSG8		;redraw text
	JP	DISPLAY		;display & return
;
	SUBTTL	'<mail/asm - subroutines>'
;
	PAGE
;
;	parse command line
;
PARSE	LD	A,(DE)		;read byte command line
	INC	DE		;bump pointer
	CP	SPACE		;separator?
	JR	Z,PARSE		;yes, ignore
	CP	COMMA		;separator?
	JR	Z,PARSE		;yes, ignore
	CP	CR		;terminator?
	JR	Z,PARSEND	;yes, completed!
	CP	':'		;drive specifier?
	CALL	Z,PARCOL	;yes, parse it out
	SUB	'0'		;remove ascii
	JR	C,INVALID	;invalid command line
	CP	8		;0-7?
	JR	NC,INVALID	;invalid command line
	LD	C,A		;save drive #
;
;	drive # issued, set drive block and flags
;
	CALL	LOCFCB		;point to drive block
	LD	A,(DE)		;get next char
	CP	'+'		;adder file?
	JR	Z,PARADD	;yes, set it up!
	SET	4,(IX+0)	;set open flag
	SET	4,(IY+0)	;set command issued
	CP	'*'		;recovery mode?
	JR	NZ,PARSE	;nope, continue parse
	SET	5,(IX+0)	;set recovery mode
PARCNT	INC	DE		;bump command line
	JR	PARSE		;continue parsing
;
;	command line completed
;
PARSEND	BIT	4,(IY+0)	;command line issued?
	RET	NZ		;yes, completed
;
;	no drives issued, flag all for mounting
;
	LD	HL,PARSET	;subroutine
	JP	COMMON		;do all drives
;
PARADD	LD	A,C		;get drive #
	ADD	A,'0'		;add ascii back
	LD	(AFILEA),A	;save drive #
	LD	A,':'		;set colon
	LD	(AFILEA-1),A	;to text
	JR	PARCNT		;continue!
;
PARCOL	LD	A,(DE)		;get next char
	INC	DE		;bump pointer
	RET			;go with drive #
;
PARSET	SET	4,(IX+0)	;tag drive to be mounted
	RET			;done, drive tagged
;
PARCLR	RES	4,(IX+0)	;set NOT to be mounted
	RET
;
;	invalid command line passed
;
INVALID	BIT	0,(IY+0)	;MOUNTing new disks?
	JP	NZ,MOUNTIT	;new command if yes
	LD	HL,MSG00	;header message
	CALL	DISPLAY		;display it
	LD	HL,MSG10	;'invalid commands'
	CALL	DISPLAY		;display message
	JP	GODOS		;abort program
;
;	open all drives set to be mounted + adder
;
OPEN	CALL	CLS		;clear lower video
	LD	HL,GAPPER	;adder + gap
	CALL	DISPLAY		;display filename
	LD	HL,AFILE	;adder name
	LD	DE,FCBA		;adder FCB
	LD	BC,32		;max size
	PUSH	DE		;save FCB start
	LDIR			;move name into FCB
	POP	DE		;DE => FCB
	LD	HL,BUFFA	;adder I/O buffer
;
	OPEN$			;open the file
	JR	NZ,DOPEN	;go if error
;
;	read first record for # of entries present
;
	READ$			;read first record
	JR	NZ,DOPEN	;error, go!
;
;	read header to be sure file is valid
;
	LD	HL,BUFFA+030H	;start of header
	LD	DE,HEADER	;header text
	LD	B,16		;header length
	CALL	COMPARE		;compare 'em
	LD	A,34		;'file format error'
	JR	NZ,DOPEN	;go if no compare
;
	LD	A,(BUFFA)	;read MSB # records
	LD	(IY+4),A	;save into system table
	LD	A,(BUFFA+1)	;get NSB
	LD	(IY+5),A	;to data
	LD	A,(BUFFA+2)	;get LSB
	LD	(IY+6),A	;to data
	SET	7,(IY+0)	;ADDER available
	XOR	A		;set no error
;
DOPEN	LD	(IY+16),A	;save any errors
	LD	B,(IY+4)	;fetch # records in file
	LD	H,(IY+5)
	LD	L,(IY+6)
	LD	DE,MSG6A	;# records
	CALL	BINASC		;binary => ascii
	LD	HL,MSG6		;'file open'
	BIT	7,(IY+0)	;adder open?
	JR	NZ,$+5		;go if yes
	LD	HL,MSG7		;'not open'
	CALL	DISPLAY		;display which
	LD	A,(IY+16)	;fetch error #
	OR	A		;any errors?
	CALL	NZ,ERROR	;display if yes
;
;	open data files on specified drives
;
	LD	HL,OPENIT	;subroutine
	CALL	COMMON		;do all drives
;
;	display data files available
;
	LD	HL,MSG8		;'data files'
	CALL	DISPLAY		;display message
	XOR	A		;load zero
	LD	(IY+7),A	;init # records total
	LD	(IY+8),A
	LD	(IY+9),A
	LD	(IY+10),A	;init # records used
	LD	(IY+11),A
	LD	(IY+12),A
;
	LD	HL,ADDOPEN	;subroutine
	CALL	COMMON		;do all drives
;
;	display total # records available
;
	LD	B,(IY+7)	;MSB total records
	LD	H,(IY+8)	;NSB
	LD	L,(IY+9)	;LSB
	PUSH	BC		;save
	PUSH	HL		;total records on stack
	LD	DE,MSG9A	;text
	CALL	BINASC		;binary to ascii
	LD	B,(IY+10)	;MSB used records
	LD	H,(IY+11)	;NSB
	LD	L,(IY+12)	;LSB
	PUSH	BC		;save
	PUSH	HL		;used records on stack
	LD	DE,MSG9B	;text
	CALL	BINASC		;binary to ascii
	POP	DE		;fetch NSB,LSB used
	POP	AF		;A = MSB used
	POP	HL		;fetch NSB,LSB available
	POP	BC		;B = MSB used
	LD	C,A		;BHL=total, CDE=used
	CALL	SUBIT		;compute result into BHL
	LD	DE,MSG9C	;total records available
	CALL	BINASC		;to message
;
	LD	HL,MSG9		;# records available
	JP	DISPLAY		;display # records & RET
;
;	open file, add total # records
;
ADDOPEN	BIT	7,(IX+0)	;file open?
	RET	Z		;nope, skip
	LD	A,':'		;separator
	CALL	VOUT		;to display
	LD	A,C		;fetch drive #
	ADD	A,'0'		;add ascii
	CALL	VOUT		;to display
	LD	A,SPACE		;a blank
	CALL	VOUT		;to separate entries
	LD	A,SPACE		;two of 'em
	CALL	VOUT
;
;	add total records to running subtotal
;
	LD	A,(IX+9)	;LSB avail
	ADD	A,(IY+9)	;add to subtotal
	LD	(IY+9),A	;update
	LD	A,(IX+8)	;NSB avail
	ADC	A,(IY+8)	;add
	LD	(IY+8),A	;update
	LD	A,(IX+7)	;MSB avail
	ADC	A,(IY+7)	;add
	LD	(IY+7),A	;update
;
;	add used records to subtotal
;
	LD	A,(IX+12)	;LSB used
	ADD	A,(IY+12)	;add
	LD	(IY+12),A	;update
	LD	A,(IX+11)	;NSB
	ADC	A,(IY+11)	;add
	LD	(IY+11),A	;update
	LD	A,(IX+10)	;MSB
	ADC	A,(IY+10)	;add
	LD	(IY+10),A	;update
	RET			;done
;
;	open single file, C=drive #
;
OPENIT	LD	A,(IX+0)	;read first flag
	BIT	4,A		;drive set?
	RET	Z		;nope, skip it
	LD	A,C		;fetch drive #
	ADD	A,'0'		;add ascii to drive #
	LD	(DFILEA),A	;save into text
	PUSH	HL		;save I/O buffer
	LD	HL,DFILE	;point to name text
	LD	BC,32		;max length
	PUSH	DE		;save FCB
	LDIR			;move name into FCB
	POP	DE		;DE => unopen FCB
	POP	HL		;HL => I/O buffer
;
	OPEN$			;open the file
	RET	NZ		;file not open, continue
;
;	read first record to fetch specifics
;
	READ$			;read first sector
	RET	NZ		;error, continue
;
;	read header to assure valid file
;
	LD	L,(IX+17)	;fetch I/O buffer
	LD	H,(IX+18)	;HL => I/O buffer
	LD	DE,030H		;offset to header
	ADD	HL,DE		;HL => file header
	LD	DE,HEADER	;DE => header text
	LD	B,16		;length of header
	CALL	COMPARE		;match?
	RET	NZ		;nope, skip
;
;	move specifics into FCB block
;
	PUSH	IX		;pass pointer to DE
	POP	DE		;DE => fcb block
	LD	L,(IX+17)	;fetch buffer pointer
	LD	H,(IX+18)	;HL => I/O buffer
	LD	A,(IX+0)	;fetch flags
	BIT	6,(HL)		;file sorted?
	LD	BC,15		;15 byte block
	LDIR			;move it in
	RES	6,A		;set file NOT sorted
	SET	7,A		;set file OPEN
	LD	(IX+0),A	;update flags
;
	PUSH	AF		;save flags
	BIT	5,A		;recovery mode issued?
	JR	Z,$+6		;go if not
	SET	5,(IY+0)	;set recovery flag
	POP	AF		;restore stack
;
	SET	6,(IY+0)	;set file OPEN
	RET	Z		;return if NOT sorted
	SET	6,(IX+0)	;set file SORTED
	RET			;done, return
;
;	compare strings at (HL) & (DE) for B
;
COMPARE	LD	A,(DE)		;fetch first byte
	CP	(HL)		;string match?
	RET	NZ		;return if not
	INC	DE		;bump strings
	INC	HL		;bump test
	DJNZ	COMPARE		;go for length
	RET			;return with Z flag
;
;	display graphic border
;
BORDER	EQU	$
	IF	MOD2
	CALL	@VIDON		;enable video
	ENDIF
;
	LD	HL,COLS*2+@VIDEO
	LD	B,COLS-2
	LD	(HL),TLCORN	;corner
	INC	HL		;bump video
	LD	A,MHBAR		;horiz bar
	CALL	FILL		;draw line
	LD	(HL),TRCORN	;corner
;
	LD	HL,COLS*7+@VIDEO
	LD	B,COLS-2
	LD	(HL),MLCORN	;corner
	INC	HL		;bump video
	LD	A,MHBAR		;horiz bar
	CALL	FILL		;draw line
	LD	(HL),MRCORN	;corner
;
	LD	HL,COLS*11+@VIDEO
	LD	B,COLS-2
	LD	(HL),BLCORN	;corner
	INC	HL		;bump video
	LD	A,MHBAR		;horiz bar
	CALL	FILL		;draw line
	LD	(HL),BRCORN	;corner
;
	LD	HL,COLS*3+@VIDEO
	LD	B,4		;4 lines
	LD	DE,COLS-1	;offset to next row
	CALL	FILSID		;draw top sides
	ADD	HL,DE		;to next row
	INC	HL		;adjust for DE = -1
	LD	B,3		;3 lines
	CALL	FILSID		;draw bottom sides
;
	IF	MOD2
	CALL	@VIDOFF		;de-select video
	ENDIF
	RET
;
FILSID	LD	(HL),VBAR	;vert bar
	ADD	HL,DE		;offset to next side
	LD	(HL),VBAR	;vert bar
	INC	HL		;to next side
	DJNZ	FILSID		;for B rows
	RET			;done
;
FILL	LD	(HL),A		;char to video
	INC	HL		;bump pointer
	DJNZ	FILL		;for B bytes
	RET			;done
;
	SUBTTL	'<mail/asm - text area>'
;
;##
;
MSG00	DEFB	HOME
	DEFB	EOF
;
	DEFM	'** '
HEADER	DEFM	' PowerMAIL PLUS  **  '
	DEFM	'by Kim Watt  **  '
	DEFM	'Version 2.1  **'
	DEFB	CR
;
	DEFM	'(c)(p) Copyright 1983 Breeze/QSD, Inc.'
	DEFM	'  -  Dallas, Texas'
;
	DEFB	CR
	DEFB	CR
	DEFB	ETX
;
MSG0	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	03,002
	ENDIF
	IF	MOD2
	DEFB	03,003
	ENDIF
	DEFM	'Last :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	03,23
	ENDIF
	IF	MOD2
	DEFB	03,024
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	03,025
	ENDIF
	IF	MOD2
	DEFB	03,029
	ENDIF
	DEFM	'First :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	03,42
	ENDIF
	IF	MOD2
	DEFB	03,46
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	03,043
	ENDIF
	IF	MOD2
	DEFB	03,053
	ENDIF
	DEFM	'Data1 :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	03,55
	ENDIF
	IF	MOD2
	DEFB	03,65
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	04,002
	ENDIF
	IF	MOD2
	DEFB	04,003
	ENDIF
	DEFM	'Company :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	04,31
	ENDIF
	IF	MOD2
	DEFB	04,32
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	04,043
	ENDIF
	IF	MOD2
	DEFB	04,053
	ENDIF
	DEFM	'Data2 :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	04,62
	ENDIF
	IF	MOD2
	DEFB	04,72
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	05,002
	ENDIF
	IF	MOD2
	DEFB	05,003
	ENDIF
	DEFM	'Address1 :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	05,32
	ENDIF
	IF	MOD2
	DEFB	05,33
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	05,038
	ENDIF
	IF	MOD2
	DEFB	05,042
	ENDIF
	DEFM	'Address2 :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	05,58
	ENDIF
	IF	MOD2
	DEFB	05,62
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	06,002
	ENDIF
	IF	MOD2
	DEFB	06,003
	ENDIF
	DEFM	'City :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	06,23
	ENDIF
	IF	MOD2
	DEFB	06,24
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	06,026
	ENDIF
	IF	MOD2
	DEFB	06,030
	ENDIF
	DEFM	'State :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	06,41
	ENDIF
	IF	MOD2
	DEFB	06,45
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	06,043
	ENDIF
	IF	MOD2
	DEFB	06,053
	ENDIF
	DEFM	'Zip :'
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	06,58
	ENDIF
	IF	MOD2
	DEFB	06,68
	ENDIF
	DEFM	':'
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	08,002
	DEFM	'Flags: 01=.  02=.  03=.  '
	DEFM	'04=.  05=.  06=.  07=.  08=.'
	ENDIF
	IF	MOD2
	DEFB	08,003
	DEFM	'Flags: 01=.   02=.   03=.   04=.   '
	DEFM	'05=.   06=.   07=.   08=.'
	ENDIF
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	09,002
	DEFM	'Flags: 09=.  10=.  11=.  '
	DEFM	'12=.  13=.  14=.  15=.  16=.'
	ENDIF
	IF	MOD2
	DEFB	09,003
	DEFM	'Flags: 09=.   10=.   11=.   12=.   '
	DEFM	'13=.   14=.   15=.   16=.'
	ENDIF
;
	DEFB	SETCUR
	IF	MOD1.OR.MOD3
	DEFB	10,002
	DEFM	'Flags: 17=.  18=.  19=.  '
	DEFM	'20=.  21=.  22=.  23=.  24=.'
	ENDIF
	IF	MOD2
	DEFB	10,003
	DEFM	'Flags: 17=.   18=.   19=.   20=.   '
	DEFM	'21=.   22=.   23=.   24=.'
	ENDIF
;
	DEFB	SETCUR
	DEFB	12,000
	DEFB	ETX
;
MSG1	DEFB	SETCUR
	DEFB	12,000
	DEFB	EOF
;
	DEFM	'(1) Initialize Files'
	DEFB	SETCUR
	DEFB	12,COLS/2
	DEFM	'(5) Utilities'
	DEFB	CR
;
	DEFB	'(2) Add Records'
	DEFB	SETCUR
	DEFB	13,COLS/2
	DEFM	'(6) Mount New Disks'
	DEFB	CR
;
	DEFB	'(3) Find/Edit Records/Flags'
	DEFB	SETCUR
	DEFB	14,COLS/2
	DEFM	'(7) Exit Program'
	DEFB	CR
;
	DEFM	'(4) Print/Count Records'
	DEFB	SETCUR
	DEFB	15,COLS/2
	DEFM	'Choice ? '
	DEFB	ETX
;
MSG2	DEFM	'No Data Available, '
	DEFM	'(KEY) to init files:'
	DEFB	ETX
;
MSG3	DEFM	'Adder'
	DEFB	ETX
;
MSG4	DEFM	'Data'
	DEFB	ETX
;
MSG34	DEFM	' not available, (KEY):'
	DEFB	ETX
;
MSG5	DEFB	CR
	DEFM	'(KEY) to continue:'
	DEFB	ETX
;
MSG6	DEFM	'OPEN with '
MSG6A	DEFM	'xxxxxxxx records'
	DEFB	CR
	DEFB	ETX
;
MSG7	DEFM	'NOT OPEN - '
	DEFB	ETX
;
GAPPER	DEFM	'Adder File   - '
	DEFB	ETX
;
MSG8	DEFB	SETCUR
	DEFB	13,00
	DEFB	EOF
	DEFM	'Data File(s) - '
	DEFB	ETX
;
MSG9	DEFB	CR
MSG9A	DEFM	'xxxxxxxx Records - '
MSG9B	DEFM	'xxxxxxxx Used - '
MSG9C	DEFM	'xxxxxxxx Available'
	DEFB	CR
	DEFB	ETX
;
MSG10	DEFM	'Invalid Command Line'
	DEFB	CR
	DEFB	ETX
;
MSG11	DEFM	'Closed'
	DEFB	ETX
;
MSG12	DEFM	'Unavailable'
	DEFB	ETX
;
MSG13	DEFM	'All files opened, (KEY):'
	DEFB	ETX
;
MSG14	DEFM	'Close Error(s)'
	DEFB	CR
	DEFB	ETX
;
MSG15	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
	DEFM	'Mount New Diskettes'
	DEFB	CR
	DEFM	'Enter Drive(s) to mount or '
	DEFM	'<ENTER> for all: '
	DEFB	ETX
;
	SUBTTL	'<mail/asm - program text names>'
;
AFILE	DEFM	'PMAIL/ADD'
	DEFB	ETX
AFILEA	DEFB	'$'
	DEFB	ETX
;
DFILE	DEFM	'PMAIL/DAT:'
DFILEA	DEFM	'x'
	DEFB	ETX
;
PGM1	DEFM	'PMAILA/CMD'
	DEFB	SYSDRV
	DEFB	SYSDRVN
	DEFB	ETX
;
PGM2	DEFM	'PMAILB/CMD'
	DEFB	SYSDRV
	DEFB	SYSDRVN
	DEFB	ETX
;
PGM3	DEFM	'PMAILC/CMD'
	DEFB	SYSDRV
	DEFB	SYSDRVN
	DEFB	ETX
;
PGM4	DEFM	'PMAILD/CMD'
	DEFB	SYSDRV
	DEFB	SYSDRVN
	DEFB	ETX
;
PGM5	DEFM	'PMAILE/CMD'
	DEFB	SYSDRV
	DEFB	SYSDRVN
	DEFB	ETX
;
;	dummy pointer for REWIND positioning
;
REWIND	DEFB	00,00,00	;3 byte extended record
;
;	lookup table for menu selections
;
TABLE1	DEFB	'1'
	DEFW	INIT
	DEFB	'2'
	DEFW	ENTER
	DEFB	'3'
	DEFW	EDIT
	DEFB	'4'
	DEFW	PRINT
	DEFB	'5'
	DEFW	UTILITY
	DEFB	'6'
	DEFW	MOUNT
	DEFB	'7'
	DEFW	EXIT
	DEFB	'X'
	DEFW	REDRAW
	DEFB	'x'
	DEFW	REDRAW
	DEFB	ETBL
;
;	open param list for mod II
;
	IF	MOD2
OLIST	DEFW	0
	DEFW	0
	DEFW	0
	DEFB	'W'
	DEFB	0
	DEFB	'E'
	DEFB	0
	DEFB	00
	ENDIF
;
PGMEND	EQU	$
;
	SUBTTL	'<mail/asm - symbol table>'
;
	END	ENTRY
