;
; I/OS LINE EDITOR
;	BASED ON CLASSY FROM DR. DOBBS J/J 1976
;
; REV 01.00 2/28/78 RLR
; REV 01.01 3/23/78 RLR (FIX STACK HANDLING)
; REV 01.03 02/20/81 RLR ADD USER DEFINE CASE FUNCTION
; REV 01.04 02/24/81 RLR ADD BUFFERED LINE EDIT 
; 01.05 11/15/81 RLR - CLEAN UP MISC
;
; PART A - EDITING FUNCTIONS & DATA AREAS
;
	NAM	EDITA
	LST	NASC
;
	ENT	KILL,RUBO,TABC
	ENT	ERRMSG,SCNB
;
	ENT	NCHR,TEMP,TEM1
	ENT	MODE,MMAX,ADDS,IPNT,TOPL
	ENT	EFPN,PNTR,MVAD,BUFF,IBUF,IBUFA
	ENT	WHAT,BOTM,INSL
	ENT	RXFCB,IXFCB,OXFCB,STAK
	ENT	OKMSG			;01.05
;
	EXT	MSCR,PRTN,LNOT
	EXT	LIST,LCHR,DBCV,IFFC
	EXT	OUTR,DTIN,TVTO,CRLF
	EXT	NDON,LMOD,DFILE
	EXT	LOAD,SAVE,LEDIT,QUIT
	EXT	FSTOP,FHOME
;
; FOR USE AS A SUB-SYSTEM
;
	ENT	EDIT,EINIT
	EXT	RUN,OPS,DOS
;
BS	EQU	8
TAB	EQU	9	;CONT I
CMAX	EQU	80
LF	EQU	10
CR	EQU	13
SPC	EQU	20H
	EJECT
;
;	STARTUP EDITOR
;
;		BC = DEF TABLE (KILL, RUBO, TAB, MODE)
;		DE = START MEMORY
;		HL = TOP OF STACK
;
EINIT:	LDAX	B		; *** BC == CHAR TABLE
	STA	KILL	; LINE KILL
	INX	B
	LDAX	B
	STA	RUBO	; BS-BACKSPACE
	INX	B
	LDAX	B
	STA	TABC
	INX	B
	LDAX	B
	STA	MODE	; MODE:=PAGE SIZE
;
	SHLD	STAK		; *** HL == TOP OF MEMORY
	LXI	B,-256
	DAD	B
	SHLD	MMAX	; MAX MEMORY
;
	XCHG			; *** DE == START OF MEMORY
	MVI	M,0	; (SOT MARK)	; CLEAR TEXT FILE
	INX	H
	MVI	M,1	; (EOF MARK)
	SHLD	TOPL
	SHLD	EFPN
	SHLD	PNTR
;
	CALL	CRLF
	RET
 	EJECT

;
; GET NEXT COMMAND
;
EDIT:
CMRT:	LXI	H,PROMPT
	CALL	OUTR
	CALL	DTIN	; GET LINE
	CALL	SCNB
	CPI	1AH
	JNE	SCRH
; CTRL-Z <STMT> CAUSES IMMEDIATE EXEC
	INX	H	; HL^=IMMED STMT
	CALL	OPS
	JMP	EDIT
;
PROMPT:	DB	'-----',80H+')'
;
SCRH:	PUSH	B
	LXI	D,CTB4
	LHLD	IPNT
	SHLD	ADDS
	MOV	A,M
	CPI	CR
	JNZ	SCRHA
	MVI	C,2	; IF NUL
	CALL	NXUP	; THEN 'M 1'
	POP	B
	JMP	EDIT
;
SCRHA:	MVI	A,4	; LOOK AT 4 CHAR CMDS
	STA	NCHR
	CALL	CTSH
	JZ	MTCH
;
	MVI	A,1	; LOOK AT 1 CHAR CMDS
	STA	NCHR
	CALL	CTSH
	JNZ	WHAT
MTCH	SHLD	TEMP	; DO COMMAND
	LDA	NCHR
	MOV	C,A
	MVI	B,0
	LHLD	IPNT
	DAD	B
	SHLD	IPNT
MTG:	CALL	SCNB
	LHLD	TEMP
	POP	B
EXCT:	LXI	D,EDIT
	PUSH	D
	PCHL
;
; ENTER COMMAND WITH 'IPNT' AT 1ST NON-SPACE
;  C= # OF CHARS ON LINE
;  CY = (CHAR < SPACE NEXT)

	EJECT
;
;---------------------------------------COMMAND--------------
; 'MOVE' COMMAND (I.E. NEXT LINE)
;
;
;
NXTC	LXI	B,2
	JC	NXUP
	PUSH	B
	CPI	'-'
	JNZ	CNVV
	POP	B
	MVI	B,1
	PUSH	B
	LHLD	IPNT
	INX	H
	SHLD	IPNT
CNVV	LHLD	IPNT
	MOV	B,H
	MOV	C,L
	CALL	DBCV
	DCR	H
	JP	WHAT
	POP	B
	MOV	C,L
	INR	C
	MOV	A,B
	ORA	A
	JZ	NXUP
;
; MOVE TOWARDS TOP
;
	MOV	A,L
NXBK	STA	TEMP
	LHLD	TOPL
	XCHG
	LHLD	PNTR
NATP	DCX	H
	DCX	H
	CALL	OVTS
	JC	NAOK
	XCHG
	SHLD	PNTR
	JMP	NDON
;
; BACK TO START OF CURRENT LINE
;
NAOK	MOV	A,M
	CPI	CR
	JNZ	NATP+1
	INX	H
	SHLD	PNTR
	LDA	TEMP
	DCR	A
	JNZ	NXBK
	JMP	NDON
;
; TOWARDS EOF
;
NXUP	DCR	C
	JZ	NDON
	CALL	NLST
	JC	BOTM
	SHLD	PNTR
	JMP	NXUP
;
;---------------------------------------COMMAND--------------
; POINT TO TOP OF TEXT	- TOP
;
TOPR	LHLD	TOPL
	SHLD	PNTR
	JMP	LMOD
;
; GET NEXT LINE ADDRESS
;
NLST:	LHLD	PNTR
	MOV	A,M	; CHECK FOR EOT
	CPI	1
	STC		; SAY SO WITH CY=1
	REQ		; YES - EOT
;
NLSTA:	MOV	A,M
	INX	H
	CPI	CR
	RZ
	CPI	1	; UNTIL
	JNZ	NLSTA	; EOT
; EOT - WITHOUT PROPER CR  (HL AT EOT)
	INX	H	; ADD FOR NEW CR
	XCHG		; AND COMPARE FOR ENOUGH ROOM
	LHLD	MMAX	; TO ADD AN EXTRA CHAR
	CALL	OVTS
	XCHG		; IF NO ROOM
	DCX	H
	DCX	H
	DCX	H	; POINT BEFORE EOT
	RNC		;   GIVE UP THE GOOD EFFORT
; AT LAST - WE CAN BE A GOOD GUY, AND FIXUP LINE
	INX	H	; PT AT OLD EOT
	MVI	M,CR	; PUT CR THERE
	INX	H
	MVI	M,1	; AND PUT NEW EOT
	SHLD	EFPN	; CORRECT EOF PTR
	DCX	H	; AND POINT AT CR
	RET
;
; GET CURRENT LINE ADDRESS
;
CLST:	LHLD	PNTR
	JMP	PLSTA	; SKIP BACK
;
; GET PREVIOUS LINE ADDRESS
;
PLST:	LHLD	PNTR
	CALL	PLSTA	; GET START OF THIS LINE
	ORA	A
	RZ		; SOF-START
	DCX	H	; BACK PAST CR
	DCX	H
PLSTA:	MOV	A,M
	CPI	CR
	INX	H	; CR IS END OF LAST LINE
	RZ
	ORA	A
	RZ		; SOF-START
	DCX	H
	DCX	H
	JMP	PLSTA
;
; GENERAL ERROR AND DONE MSG'S
;
OKMSG:	XCHG		;GIVE MSG AND DO NEXT
	LHLD	STAK
	SPHL
	XCHG
	CALL	LNOT	;01.05 HL=MSG
	JMP	EDIT	;01.05
;
ERRMSG:	XCHG		;GIVE MSG, "WHAT" AND DO NEXT
	LHLD	STAK
	SPHL
	XCHG
	CALL	LNOT	; HL HAS SECOND MSG
;
WHAT:	LHLD	STAK
	SPHL
	LXI	H,WTMS
	CALL	OUTR
	JMP	EDIT
;
WTMS	DB	'WHAT?',8DH
;
	EJECT
;---------------------------------------COMMAND--------------
; SINGLE LINE INSERT	- INSERT
;
INSLT:	CPI	CR	; IF ONLY A CR
	JEQ	INMD	; THEN BULK INPUT
	CALL	CKDELM
; SINGLE LINE ACTION
INSL:	DCR	C
	DCR	C
	LXI	H,IBUF+2
	SHLD	IPNT
	CALL	CLST
	SHLD	MVAD	; GET ADDRESS OF CURR LINE
	SHLD	PNTR
	CALL	CENT	; DO INSERT
	CALL	NLST	; GET NEXT LINE ADDRESS 
	SHLD	PNTR	; SKIP LINE JUST ENTERED
	RET
;
; BULK INSERT COMMAND
;
INMD:	LHLD	STAK
	SPHL
	LXI	H,INMS
	CALL	OUTR
;
; INSET ONE LINE AT A TIME
;
INLP:	CALL	DTIN
	LXI	H,IBUF
	MOV	A,M
	CPI	'.'	; exit bulk
	JNZ	USW
	INX	H
	MOV	A,M
	CPI	CR
	JZ	EDIT
USW:	CALL	CLST	; GET START OF LINE
	SHLD	PNTR
	SHLD	MVAD
	CALL	CENT
	CALL	NLST
	SHLD	PNTR	; SKIP LINE JUST ADDED
	JMP	INLP
;
INMS:	DB	'Bulk Input - <"." return> to exit',CR+80H
;
; LINE INSERT ROUTINE
;			C==LENGTH
CENT	LHLD	EFPN
	INR	C
	MVI	B,0
	DAD	B
	XCHG
	LHLD	MMAX
	CALL	OVTS
	JNC	MOFL
MSOK	LHLD	EFPN
	CALL	RMOV
	LHLD	EFPN
	DAD	B
	SHLD	EFPN
	LHLD	IPNT
	DCR	C
	DAD	B
	SHLD	MVAD
	LHLD	IPNT
	XCHG
	LHLD	PNTR
	CALL	LMOV
	RET
;
; RIGHT MOVE (UP)
;
RMOV	PUSH	B
	MOV	B,H
	MOV	C,L
	LHLD	MVAD
NXRM	LDAX	B
	STAX	D
	MOV	A,L
	CMP	C
	JNZ	RMCT
	MOV	A,H
	CMP	B
	JZ	RDON
RMCT	DCX	B
	DCX	D
	JMP	NXRM
RDON	POP	B
	RET
;
; COMPARE HL & DE
;
OVTS	MOV	A,E
	SUB	L
	MOV	A,D
	SBB	H
	RET
	EJECT
;---------------------------------------COMMAND--------------
; DELETE COMMAND
;
DELE:	MVI	C,2
	JC	DLOC
	LHLD	IPNT
	MOV	B,H	
	MOV	C,L
	CALL	DBCV	; Get lines to Delete
	MOV	C,L
   	INR	C
	DCR	H
	JP	WHAT
DLOC	DCR	C
	RZ
	LHLD	EFPN
	SHLD	MVAD
	CALL	NLST	; Get next Line
	JC	BOTM
	XCHG
	LHLD	PNTR
	CALL	LMOV	; Move next line over curr line
	SHLD	EFPN
	JMP	DLOC
;
; LEFT MOVE (DOWN)
;
LMOV	PUSH	B
	MOV	B,D
	MOV	C,E
	XCHG
	LHLD	MVAD
	XCHG
LMLP	LDAX	B
	MOV	M,A
	MOV	A,C
	CMP	E
	JNZ	LMCT
	MOV	A,B
	CMP	D
	JZ	LDON
LMCT	INX	H
	INX	B
	JMP	LMLP
LDON	POP	B
	RET
;
; MEMORY OVERFLOW ERRR
;
MOFL:	CALL	CRLF	;01.05
	LXI	H,OFMS	;01.05
	JMP	OKMSG	;01.05
;
OFMS:	DB	'*** Text Area FULL ***',CR
	EJECT
;---------------------------------------COMMAND--------------
; APPEND COMMAND
;
APND:	MOV	A,C
	SUI	3
	JC	WHAT	; check for >2 chars
	CALL	CKDELM
	DCR	C
	DCR	C
	CALL	NLST
	JC	BOTM
	DCX	H
	SHLD	TEMP
	LXI	H,IBUF+1
	SHLD	TEM1
	MVI	B,0
	JMP	CNGO
;
;---------------------------------------COMMAND--------------
; CHANGE COMMAND
;
CCRT:	CAÿÿ¢ìÿÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLINE	B,0
; FIND FIRST VALUE
CCR1	INX	H
	MOV	A,M
	CPI	CR
	JZ	WHAT
	CMP	D
	JZ	LSTR
	INR	B
	JMP	CCR1
; FIND NEW VALUE
LSTR	SHLD	TEM1
	LHLD	IPNT
	INX	H
	SHLD	IPNT
	LHLD	PNTR
STSH:	MOV	C,B	; B HOLDS SEARCH LENGTH
	SHLD	TEMP
	XCHG
	LHLD	IPNT
	CALL	CSEAR
	JZ	STMT
	LHLD	TEMP
	MOV	A,M
	CPI	CR
	JZ	CCDN
	CPI	1	; IF EOF
	JZ	BOTM
	INX	H
	JMP	STSH
STMT	LHLD	TEM1
	MVI	C,0
STM1	INX	H
	MOV	A,M
	CPI	CR
	JZ	CNGO
	INR	C
	JMP	STM1
;
;---------------------------------------COMMAND--------------
;  LINE EDIT COMMAND
;
LNEDIT:	LXI	D,EBUF
	LHLD	PNTR
	SHLD	TEMP	; OLD PTR
	MVI	B,0
    .DO
	MOV	A,M
	STAX	D
	CPI	1
	JEQ	BOTM	; FAIL ON EOT
	CPI	CR
	JEQ	.BREAK	; DONE ON CR, DON'T COUNT IT
	INR	B	
	INX	D	; ADVANCE
	INX	H
    .LOOP
	PUSH	B
	LXI	H,EBUF	; SHOW INITIAL LINE
	CALL	LNOT
	LXI	D,EBUFA
	INX	D
	MOV	A,B	
	STAX	D	; ORIGINAL LEN
	DCX	D	; *DE == ORIG BUFFER
	CALL	LEDIT	; HL=EDIT OUTPUT BUFFER
	LXI	H,..S	; SHOW EDIT DONE
	CALL	LNOT
;
; MOVE BACK USING 'CNGO' ROUTINE
;
	LXI	H,EBUFA
	INX	H
	POP	B	; RECOVER B=OLD LEN
	MOV	C,M	; GET NEW LENGTH
	SHLD	TEM1	; SAVE PTR TO NEW-1
	JMP	CNGO	; DO CHANGE	
;
..S:	DB	'------------------------',CR
;
	EJECT
;
; BEGIN CHANGE
; B=LEN OF STR 1, C=LEN OF STR 2
;
;    *TEMP == OLD TEXT LINE (STR1)   LEN=B
;    *TEM1 == NEW TEXT LINE (STR2-1) LEN=C
;
CNGO	MOV	A,B
	CMP	C
	JZ	EQUL
	JNC	LESS
;
; FILE LENGTH INCREASES
;
	LHLD	TEMP
	ADD	L
	MOV	L,A
	MOV	A,H
	ACI	0
	MOV	H,A
	MOV	A,C
	SUB	B
	SHLD	MVAD
	LHLD	EFPN
	PUSH	B
	MOV	C,A
	MVI	B,0
	DAD	B
	XCHG
	LHLD	MMAX
	CALL	OVTS
	JNC	MOFL
	LHLD	EFPN
	CALL	RMOV
	LHLD	EFPN
	DAD	B
	SHLD	EFPN
	POP	B
	JMP	EQUL
;
; FILE SIZE DECREASES
;
LESS	LHLD	TEMP
	MOV	A,L
	ADD	C
	MOV	L,A
	MOV	A,H
	ACI	0
	MOV	H,A
	XCHG
	LHLD	EFPN
	SHLD	MVAD
	LHLD	TEMP
	MOV	A,L
	ADD	B
	MOV	L,A
	MOV	A,H
	ACI	0
	MOV	H,A
	XCHG
	CALL	LMOV
	SHLD	EFPN
;
; NO CHANGE IN LENGTH
;
EQUL	LHLD	TEMP
	XCHG
	LHLD	TEM1
	INX	H
EQLP	DCR	C
	JM	CCDN
	MOV	A,M
	STAX	D
	INX	H
	INX	D
	JMP	EQLP
CCDN	LHLD	PNTR
	LDA	MODE
	ORA	A
	JZ	LNOT
	JMP	LMOD
;
;
; FOR SINGLE STRING: (L)OCATE & (F)IND
; B:=LENGTH OF STRING IN COLM 2 OF IBUF
;
LOC1:	CALL	CKDELM
	LXI	H,IBUF+1
	MVI	B,-2
LNCX	MOV	A,M
	CPI	CR
	JZ	LOC2
	INR	B
	INX	H
	JMP	LNCX
LOC2	MOV	A,B
	ORA	A
	JM	WHAT
	INR	B
	RET
	EJECT
;
;---------------------------------------COMMAND--------------
; LOCATE COMMAND
;
LOCT:	CALL	LOC1
	LXI	H,IBUF+2
	SHLD	IPNT
	CALL	NLST
	JC	BOTM
LNCH:	MOV	C,B	; B HOLDS LENGTH
	MOV	A,M
	CPI	2
	JC	BTMP
	SHLD	TEMP
	XCHG
	LHLD	IPNT
	CALL	CSEAR
	JZ	LMTH
	LHLD	TEMP
	INX	H
	JMP	LNCH
LMTH	LHLD	TEMP
LMTH1:	DCX	H
	MOV	A,M
	CPI	CR
	JNZ	LMTH1
	INX	H
	SHLD	PNTR
	JMP	LMOD
;
; BOTTOM OF FILE: ERROR OR CMD
;
BTMP:	SHLD	PNTR
BOTM:	LXI	H,BTMS
	JMP	OKMSG	;01.05
BTMS:	DB	'*** Bottom of Text ***',CR
	EJECT
;---------------------------------------COMMAND--------------
; FIND COMMAND
;
FIND:	CALL	LOC1
	LXI	H,IBUF+2
	SHLD	IPNT
FIN1:	CALL	NLST	; B HOLDS SEARCH LEN
	SHLD	PNTR
	JC	BOTM
	M