
;****************************************************************
;*								*
;*			TEXT EDITOR SUBROUTINES			*
;*								*
;****************************************************************

;			OSCOR-2
;			21 NOVEMBER 1980
;			R. DAVID POGGE

			NAME EDTSUB
			ORG 3C00H

;	GLOBAL ADDRESSES

	OUTPUT	EQU	0043H

;	VARIABLES

	EDTPTR	EQU	0H
	LOMEM	EQU	0H
	STRING	EQU	0H
	STRPTR	EQU	0H
	TXTPTR	EQU	0H

;	CONSTANTS

	CR	EQU	0DH
	ESC	EQU	01BH























;****************************************************************
;* SCR:								*
;*			SCRATCH					*
;*								*
;****************************************************************

;	THERE ARE TWO BUFFERS IN MEMORY USED BY THE TEXT EDITOR,
;	THE TEXT BUFFER AND THE EDIT BUFFER. EACH HAS A BEGINNING
;	MARKER CONSISTING OF THE BYTE "FF" AND ENDS WITH THE BYTE "00".
;	THE BEGINNING OF THE EDIT BUFFER IS ALWAYS LOCATED IMMEDIATELY
;	AFTER THE END OF THE TEXT BUFFER. THE "SCRATCH" SUBROUTINE
;	ERASES THE TEXT BUFFER AND USES THE "EEB" SUBROUTINE TO
;	ESTABLISH AN EMPTY EDIT BUFFER IMMEDIATELY AFTER IT.

SCR:	LHLD LOMEM	; LET H/L POINT TO BOTTOM OF RAM MEMORY
	MVI A,0FFH	; AVALABLE FOR TEXT EDITING.
	MOV M,A		; WRITE BEGINNING OF FILE MARKER "FF"
	INX H		; ADVANCE H/L POINTER
	XRA A
	MOV M,A		; WRITE END OF FILE MARKER "00"
	SHLD TXTPTR	; SET TEXT POINTER TO END OF TEXT BUFFER
	JMP EEB		; ESTABLISH EDIT BUFFER


;****************************************************************
;* EEB:								*
;*			ESTABLISH EDIT BUFFER			*
;*								*
;****************************************************************

;	THIS SUBROUTINE ESTABLISHES AN EMPTY EDIT BUFFER IMMEDIATELY
;	FOLLOWING THE TEXT BUFFER.

EEB:	CALL ET		; CALL "END TEXT" SUBROUTINE TO MAKE SURE THE
	LHLD TXTPTR	; TEXT POINTER IS AT THE END OF THE FILE.
	INX H		; MOVE POINTER PAST END OF TEXT BUFFER
	MVI A,0FFH	; WRITE BEGINNING OF FILE MARK "FF"
	MOV M,A
	INX H		; ADVANCE POINTER ONE MORE BYTE
	XRA A		; WRITE END OF FILE MARK "00"
	MOV M,A
	SHLD EDTPTR	; SET EDIT POINTER TO END OF EDIT BUFFER
	RET











;****************************************************************
;* ET:								*
;*			END TEXT				*
;*								*
;****************************************************************

;	THIS SUBROUTINE MOVES THE TEXT POINTER TO THE END OF THE
;	TEXT BUFFER.

ET:	LHLD TXTPTR	; FETCH CURRENT TEXT POINTER
ETA:	MOV A,M		; READ CHARACTER STORED THERE
	ANA A
	JZ ETB		; IF NOT END OF FILE MARKER "00"
	INX H		; THEN INCREMENT POINTER
	JMP ETA		; AND READ NEXT CHARACTER
ETB:	SHLD TXTPTR	; IF END OF FILE, STORE NEW TEXT POINTER
	RET		; AND RETURN

;****************************************************************
;* BT:								*
;*			BEGINNING TEXT				*
;*								*
;****************************************************************

;	THIS SUBROUTINE MOVES THE TEXT POINTER TO THE BEGINNING
;	OF THE FILE.

BT:	LHLD TXTPTR	; FETCH CURRENT TEXT POINTER
BTA:	MOV A,M		; READ CHARACTER STORED THERE
	INR A
	JZ BTB		; IF NOT BEGINNING MARKER "FF"
	DCX H		; THEN DECREMENT POINTER
	JMP BTA		; AND READ NEXT LOCATION
BTB:	INX H		; MOVE POINTER PAST BEGINNING MARKER
	SHLD TXTPTR	; AND STORE
	RET

;*****************************************************************
;* BE:								*
;*			BEGINNING EDIT				*
;*								*
;****************************************************************

;	THIS SUBROUTINE MOVES THE EDIT POINTER TO THE BEGINNING
;	OF THE FILE.

BE:	LHLD EDTPTR	; FETCH CURRENT EDIT POINTER
BEA:	MOV A,M		; READ CHARACTER STORED THERE
	INR A
	JZ BEB		; IF NOT BEGINNING MARKER "FF"
	DCX H		; THEN DECREMENT POINTER
	JMP BEA		; AND READ NEXT LOCATION
BEB:	INX H		; MOVE POINTER PAST BEGINNING MARKER
	SHLD EDTPTR	; AND STORE
	RET

;****************************************************************
;* T2E:								*
;*		MOVE TEXT TO EDIT BUFFER			*
;*								*
;****************************************************************

;	THIS SUBROUTINE COPIES THE TEXT FROM THE CURRENT TEXT POINTER
;	TO THE END OF THE FILE INTO THE EDIT BUFFER. THE TEXT POINTER
;	REMAINS UNCHANGED, BUT THE EDIT POINTER IS AT THE END OF THE
;	EDIT FILE.

T2E:	LHLD TXTPTR
	XCHG		; LET D/E = TEXT POINTER
	LHLD EDTPTR	; LET H/L = EDIT POINTER
T2EA:	LDAX D		; LET A = BYTE FROM TEXT BUFFER
	MOV M,A		; TRANSFER IT TO THE EDIT BUFFER
	ANA A
	JZ T2EB		; IF NOT END OF FILE MARK "00"
	INX D		; THEN INCREMENT TEXT POINTER
	INX H		; AND INCREMENT EDIT POINTER
	JMP T2EA	; AND TRANSFER ANOTHER BYTE
T2EB:	SHLD EDTPTR	; IF END OF FILE MARK TRANSFERED, THEN SET EDIT POINTER
	RET		; AND RETURN.




;****************************************************************
;* E2T:								*
;*		    MOVE EDIT TO TEXT BUFFER			*
;*								*
;****************************************************************

;	THIS SUBROUTINE COPIES THE TEXT FROM THE EDIT BUFFER TO
;	THE TEXT BUFFER, BEGINNING AT THE TEXT POINTER. A NEW EDIT
;	BUFFER IS ESTABLISHED AT THE END OF THE TEXT BUFFER, AND
;	THE TEXT POINTER IS LEFT AT THE END OF THE TEXT FILE.

E2T:	CALL BE		; MOVE EDIT POINTER TO THE BEGINNING OF THE EDIT FILE
	LHLD EDTPTR
	XCHG		; LET D/E = EDIT POINTER
	LHLD TXTPTR	; LET H/L = TEXT POINTER
E2TA:	LDAX D		; LET A = BYTE FROM EDIT BUFFER
	MOV M,A		; TRANSFER IT TO THE TEXT BUFFER
	ANA A
	JZ E2TB		; IF NOT END OF FILE MARK "00"
	INX D		; THEN INCREMENT EDIT POINTER
	INX H		; AND INCREMENT TEXT POINTER
	JMP E2TA	; AND TRANSFER ANOTHER BYTE
E2TB:	SHLD TXTPTR	; IF DONE, STORE NEW TEXT POINTER
	JMP EEB		; ESTABLISH EMPTY EDIT BUFFER AND RETURN




;****************************************************************
;* D2E:								*
;*		MOVE D/E STRING TO EDIT BUFFER			*
;*								*
;****************************************************************

;	THIS SUBROUTINE COPIES THE STRING DESIGNATED BY THE D/E PAIR
;	INTO THE EDIT BUFFER, BEGINNING AT THE CURRENT VALUE OF
;	THE EDIT POINTER. THE SUBROUTINE RETURNS WITH THE EDIT
;	POINTER AT THE END OF THE EDIT FILE.

D2E:	LHLD EDTPTR	; LET H/L = EDIT POINTER
	DCX D		; PRE-DECREMENT POINTERS
	DCX H
D2E1:	INX D		; INCREMENT POINTERS
	INX H
	LDAX D		; TRANSFER BYTE FROM D/E PAIR TO EDIT BUFFER
	MOV M,A
	ANA A		; CHECK FOR END OF FILE MARK "00"
	JNZ D2E1
D2E2:	SHLD EDTPTR	; STORE EDIT POINTER IF DONE
	RET




;****************************************************************
;* IT:								*
;*			INSERT TEXT				*
;*								*
;****************************************************************

;	THIS SUBROUTINE INSERTS THE CONTENTS OF THE EDIT BUFFER
;	INTO THE TEXT BUFFER AT THE CURRENT POSITION OF THE TEXT
;	POINTER. THE LAST PART OF THE TEXT BUFFER IS MOVED BACK
;	TO MAKE ROOM FOR THE NEW TEXT, AND THE TEXT POINTER IS
;	LEFT AT THE END OF THE NEWLY INSERTED TEXT.

IT:	CALL BE		; MOVE EDIT POINTER TO BEGINNING OF EDIT BUFFER
	XCHG		; LET D/E = BEGINNING OF EDIT BUFFER
	CALL LDE	; LET B/C = LENGTH OF TEXT, D/E = END OF EDIT BUFFER
	XCHG		; LET H/L = END OF EDIT BUFFER
	SHLD EDTPTR	; LET EDIT POINTER = END OF EDIT BUFFER
	LHLD TXTPTR	; FETCH TEXT POINTER
	DAD B		; ADVANCE TEXT POINTER BY LENGTH OF NEW TEXT
	PUSH H		; SAVE NEW TEXT POINTER ON STACK
	CALL T2E	; APPEND TEXT FROM OLD TEXT POINTER TO END OF EDIT BUFFER
	CALL E2T	; MOVE EDIT BUFFER TO TEXT BUFFER, STARTING AT OLD TXTPTR
	POP H		; FETCH NEW TEXT POINTER
	SHLD TXTPTR	; AND STORE
	RET




;****************************************************************
;* MBD2H:							*
;*		MOVE B/C BYTES FROM D/E TO H/L			*
;*								*
;****************************************************************

;	THIS SUBROUTINE TRANSFERS THE NUMBER OF BYTES SPECIFIED BY
;	THE B/C PAIR FROM THE LOCATION SPECIFIED BY THE D/E PAIR
;	TO THE LOCATION SPECIFIED BY THE H/L PAIR. IT ASSUMES THAT
;	THE TWO AREAS OF MEMORY ARE NOT OVERLAPPING. THE B/C PAIR
;	IS CLEARED IN THE PROCESS, AND THE D/E AND H/L PAIRS ARE
;	BOTH INCREASED BY THE ORIGINAL VALUE IN B/C.

MBD2H:	XRA A		; CHECK VALUE OF B/C
	ORA C
	JNZ MBD2H1
	ORA B
	RZ		; END IF B/C = 0
MBD2H1:	LDAX D		; GET BYTE USING D/E
	MOV M,A		; STORE BYTE USING H/L
	INX D		; INCREMENT POINTERS
	INX H
	DCX B		; DECREMENT COUNTER
	JMP MBD2H


;****************************************************************
;* CCF:								*
;*		COUNT CHARACTERS FORWARD			*
;*								*
;****************************************************************

;	THIS SUBROUTINE COMPUTES HOW MANY BYTES THE TEXT POINTER MUST
;	BE MOVED TO ADVANCE THE POINTER "E" TOLKENS. THE NUMBER OF
;	CHARACTERS BETWEEN THE CURRENT POINTER AND THE END OF THE
;	Eth TOLKEN (UP TO 32,767) IS STORED IN THE B/C PAIR. THE SUBROUTINE
;	WILL RECOGNIZE THE END OF TEXT AND TERMINATE THERE IF THE
;	NUMBER OF TOLKENS LEFT IN THE TEXT IS LESS THAN THE NUMBER OF
;	TOLKENS TO BE ADVANCED. THE TOLKEN IS STORED IN THE D REGISTER.

CCF:	LXI B,-1	; LET B/C COUNTER = -1 INITIALLY
CCF1:	LHLD TXTPTR	; PRE-DECREMENT TEXT POINTER TO COMPENSATE
	DCX H		; FOR FIRST INCREMENT.
CCF2:	INX B		; INCREMENT CHARACTER CHARACTER COUNTER
	INX H		; INCREMENT TEXT POINTER
	MOV A,M		; READ BYTE FROM TEXT BUFFER
	ANA A
	RZ		; RETURN IF END OF FILE MARK "00"
	CMP D
	JNZ CCF2	; IF NOT TOLKEN, THEN READ NEXT BYTE
	DCR E		; IF TOLKEN, THEN DECREMENT TOLKEN COUNTER
	JNZ CCF2	; IF NOT DONE, CONTINUE READING CHARACTERS
CCF3:	INX B		; MOVE POINTER PAST TOLKEN
	RET		; RETURN WITH NUMBER OF BYTES IN B/C PAIR

;****************************************************************
;* CCB:								*
;*		    COUNT CHARACTERS BACKWARDS			*
;*								*
;****************************************************************

;	THIS SUBROUTINE IS EQUIVALENT TO THE ONE ABOVE, EXCEPT IT IS
;	USED WHEN THE NUMBER OF TOLKENS TO ADVANCE IS ZERO OR NEGATIVE.
;	(ADVANCING ZERO TOLKENS COUNTS THE CHARCTERS BACK TO THE
;	FIRST TOLKEN.)

CCB:	LXI B,1		; LET B/C COUNTER = 1 INITIALLY
	INR D		; INCREMENT TOLKEN (SINCE BYTE IS INCREMENTED)
	DCR E		; PRE-DECREMENT LINE COUNTER
CCB1:	LHLD TXTPTR	; PRE-INCREMENT TEXT POINTER
	INX H
CCB2:	DCX B		; DECREMENT CHARACTER COUNTER
	DCX H		; DECREMENT TEXT POINTER
	MOV A,M		; FETCH NEXT BYTE
	INR A
	JZ CCB3		; STOP IF AT BEGINNING OF TEXT BUFFER
	CMP D
	JNZ CCB2	; IF NOT TOLKEN, THEN CONTINUE CHECKING BYTES
	INR E		; IF TOLKEN, THEN INCREMENT COUNTER
	JNZ CCB2	; CONTINUE IF MORE TOLKENS TO BE FOUND
CCB3:	INX B		; MOVE POINTER PAST TOLKEN OR BEGINNING OF FILE MARK
	RET		; RETURN WITH NEGATIVE NUMBER OF CHARACTERS IN B/C



;****************************************************************
;* TBC:								*
;*			TYPE B/C CHARACTERS			*
;*								*
;****************************************************************

;	THIS SUBROUTINE TYPES THE NUMBER OF CHARACTERS FOUND IN
;	THE B/C PAIR (MUST BE A POSITIVE NUMBER) STARTING AT THE
;	ADDRESS FOUND IN THE H/L PAIR.

TBC:	XRA A		; RETURN IF B/C PAIR = 0
TBC1:	ORA C
	JNZ TBC2
	ORA B
	RZ
TBC2:	MOV A,M		; FETCH CHARACTER FROM TEXT BUFFER
	PUSH H		; PROTECT H/L & B/C PAIRS
	PUSH B		; FROM OUTPUT SUBROUTINE
	CALL OUTPUT	; OUTPUT CHARACTER
	POP B		; RESTORE B/C PAIR
	POP H		; RESTORE H/L PAIR
TBC3:	INX H		; INCREMENT TEXT POINTER
	DCX B		; DECREMENT CHARACTER COUNTER
	JMP TBC		; DO AGAIN

;****************************************************************
;* TEL:								*
;*			TYPE "E" LINES				*
;*								*
;****************************************************************

TEL:	MVI D,CR	; LET TOLKEN = <CR>
	MOV A,E		; CHECK POLARITY OF REGISTER E
	
TEL1:	DCR A
	JP TEL1B
TEL1A:	CALL CCB	; IF REG E NEGATIVE OR ZERO, THEN COUNT BACKWARDS
	LHLD TXTPTR	; "CCB" RETURNS WITH A NEGATIVE NUMBER OF CHARACTERS IN B/C
	DAD B		; LET H/L = TEXT POINTER - B/C CHARACTERS
	XRA A		; COMPLEMENT B/C PAIR
	SUB C
	MOV C,A
	MVI A,0
	SBB B
	MOV B,A		; B/C = POSITIVE NUMBER OF CHARACTERS
	JMP TEL2	; TYPE B/C CHARACTERS
TEL1B:	CALL CCF	; IF REG E POSITIVE, COUNT FORWRD
	LHLD TXTPTR	; H/L = TEXT POINTER, B/C = NUMBER OF CHARACTERS
TEL2:	JMP TBC		; TYPE B/C CHARACTERS




;****************************************************************
;* AET:								*
;*			ADVANCE "E" TOLKENS			*
;*								*
;****************************************************************

AET:	MOV A,E		; CHECK POLARITY OF REGISTER E
	
AET1:	DCR A
	JP AET1B
AET1A:	CALL CCB	; IF NEGATIVE, THEN COUNT CHARACTERS BACKWARDS
	JMP AET2
AET1B:	CALL CCF	; IF POSITIVE, THEN COUNT CHARACTERS FORWARDS
AET2:	LHLD TXTPTR
	DAD B		; LET TEXT POINTER = TEXT POINTER +/- B/C CHARACTERS
	SHLD TXTPTR
	RET










;****************************************************************
;* JFD:								*
;*		JUMP FORWARD "E" CHARACTERS			*
;*								*
;****************************************************************

;	THIS SUBROUTINE WILL ADVANCE THE TEXT POINTER E BYTES,
;	OR TO THE END OF THE BUFFER, WHICHEVER COMES FIRST.

JFD:	LHLD TXTPTR	; LET H/L = TEXT POINTER
JFD1:	MOV A,M		; READ BYTE AT THAT LOCATION
	ANA A
	JZ JFD2		; END IF END OF FILE MARKER "00"
	INX H		; ADVANCE TEXT POINTER
	DCR E		; DECREMENT E COUNTER
	JNZ JFD1	; END IF E = 0
JFD2:	SHLD TXTPTR	; STORE ADVANCED TEXT POINTER
	RET

;****************************************************************
;* JBD:								*
;*		JUMP BACKWARDS "E" CHARACTERS			*
;*								*
;****************************************************************

;	THIS SUBROUTINE WILL DECREMENT THE TEXT POINTER E BYTES
;	OR TO THE BEGINING OF THE BUFFER, WHICHEVER COMES FIRST.

JBD:	LHLD TXTPTR	; LET H/L = TEXT POINTER
JBD1:	MOV A,M		; READ BYTE AT THAT LOCATION
	INR A
	JZ JBD2		; END IF BEGINNING OF FILE MARKER "FF"
	DCX H		; DECREMENT TEXT POINTER
	INR E		; INCREMENT E COUNTER
	JNZ JBD1	; END IF E = 0
	DCX H		; DECREMENT POINTER PAST DESIRED LOCATION
JBD2:	INX H		; ADVANCE POINTER PAST BEGINNING OF FILE MARKER
	SHLD TXTPTR	; STORE CORRECTED TEXT POINTER
	RET

;****************************************************************
;* JE:								*
;*			JUMP "E" CHARACTERS			*
;*								*
;****************************************************************

;	THIS SUBROUTINE SELECTS JDF OR JDB DEPENDING UPON THE
;	POLARITY OF THE E REGISTER.

JE:	INR E		; INCREMENT AND DECREMENT TO SET FLAGS
	DCR E
	RZ		; DO NOTHING IF E = 0
	JP JFD		; JUMP FORWARD IF E IS POSITIVE
	JM JBD		; JUMP BACKWARDS IF E IS NEGATIVE

;****************************************************************
;* DP:								*
;*		    DELETE POSITIVE CHARACTERS			*
;*								*
;****************************************************************

;	THIS SUBROUTINE ASSUMES THAT THE B/C PAIR CONTAINS A POSITIVE
;	NUMBER OF CHARACTERS TO BE DELETED. IT DELETES CHARACTERS
;	BY MOVING THE LAST PORTION OF THE FILE FORWARD.

DP:	LHLD TXTPTR	; FETCH CURRENT TEXT POINTER
	PUSH H		; SAVE IT ON THE STACK
	DAD B		; ADVANCE TEXT POINTER B/C CHARACTERS
	SHLD TXTPTR
	CALL T2E	; WRITE REMAINDER OF FILE TO EDIT BUFFER
	POP H		; FETCH OLD TEXT POINTER
	PUSH H		; AND STILL SAVE IT ON THE STACK
	SHLD TXTPTR
	CALL E2T	; WRITE EDIT BUFFER TO TEXT BUFFER (OVERWRITING
			; B/C CHARACTERS)
	POP H		; RESTORE TEXT POINTER TO ORIGINAL POSITION
	SHLD TXTPTR
	RET




;****************************************************************
;* DN:								*
;*		    DELETE NEGATIVE CHARACTERS			*
;*								*
;****************************************************************

;	THIS SUBROUTINE ASSUMES THAT B/C CONTAINS A NEGATIVE
;	NUMBER OF CHARACTERS TO BE DELETED,

DN:	CALL T2E	; WRITE REMAINDER OF FILE TO EDIT BUFFER
	LHLD TXTPTR	; MOVE POINTER -B/C CHARACTERS
	DAD B
	SHLD TXTPTR
	PUSH H		; SAVE NEW TEXT POINTER ON STACK
	CALL E2T	; WRITE EDIT BUFFER TO TEXT BUFFER (OVERWRITING
			; -B/C CHARACTERS)
	POP H
	SHLD TXTPTR	; SAVE NEW TEXT POINTER
	RET









;****************************************************************
;* DEC:								*
;*			DELETE "E" CHARACTERS			*
;*								*
;****************************************************************

DEC:	MOV A,E		; DETERMINE POLARITY OF REGISTER E
	DCR A
	JM DEC2
DEC1:	LXI B,-1	; IF POSITIVE, LET B/C = -1
DEC1A:	LHLD TXTPTR	; LET H/L = TEXT POINTER - 1
	DCX H
DEC1B:	INX B		; INCREMENT B/C COUNTER
	INX H		; INCREMENT TEXT POINTER
	MOV A,M		; CHECK FOR END OF FILE MARK "00"
	ANA A		; IF END OF FILE, THEN DELETE B/C CHARACTERS
	JZ DP
	DCR E		; DECREMENT COUNTER E
	JNZ DEC1B	; IF MORE CHARACTERS, CONTINUE
	INX B		; IF DONE, ADJUST B/C COUNTER
	JMP DP		; AND DELETE B/C CHARACTERS
DEC2:	LXI B,1		; IF REG E NEGATIVE, THEN LET B/C = 1
	DCR E		; PRE-DECREMENT REGISTER E
DEC2A:	LHLD TXTPTR	; LET H/L = TEXT POINTER + 1
	INX H
DEC2B:	DCX B		; DECREMENT B/C COUNTER
	DCX H		; DECREMENT TEXT POINTER
	MOV A,M		; CHECK FOR BEGINNING OF FILE MARK "FF"
	INR A		; IF BEGINNING OF FILE, THEN DELETE B/C CHARACTERS
	JZ DEC2C
	INR E		; OTHERWISE INCREMENT COUNTER E
	JNZ DEC2B	; IF MORE CHARACTERS, CONTINUE
	DCX B		; IF DONE, ADJUST COUNTER B/C
DEC2C:	INX B		; ADJUST B/C COUNTER
	JMP DN		; AND DELETE B/C CHARACTERS




;****************************************************************
;* KEL:								*
;*			KILL "E" LINES				*
;*								*
;****************************************************************

KEL:	MVI D,CR	; LET TOLKEN = <CR>
	MOV A,E		; CHECK POLARITY OF E
	DCR A
	JM KEL2
KEL1:	CALL CCF	; IF POSITIVE, COUNT CHARACTERS FORWARD
	JMP DP		; THEN DELETE B/C CHARACTERS
KEL2:	CALL CCB	; IF NEGATIVE, COUNT CHARACTERS BACKWARDS
	JMP DN		; THEN DELETE B/C CHARACTERS


;****************************************************************
;* FPDS:							*
;*		    FIND POSITIVE D/E STRING			*
;*								*
;****************************************************************

;	THIS SUBROUTINE FINDS THE STRING DESIGNATED BY THE D/E PAIR.
;	AFTER THE STRING IS FOUND, TEXT POINTER IS SET TO THE FIRST
;	CHARACTER AFTER THE DESIRED STRING. THE H/L PAIR IS POINTING
;	TO THE FIRST CHARACTER OF THE STRING. THE CARRY FLAG IS
;	CLEARED TO INDICATE THAT THE STRING HAS BEEN SUCCESSFULLY
;	FOUND.

;	IF THE STRING IS NOT FOUND, THE TEXT POINTER IS NOT CHANGED.
;	THE CARRY FLAG IS SET TO INDICATE AN UNSUCCESSFUL SEARCH.

;	IN EITHER CASE THE D/E PAIR REMAINS UNCHANGED.

FPDS:	DCX D		; SAVE STRING POINTER - 1 ON THE STACK
FPDS1:	PUSH D
	LHLD TXTPTR	; SAVE TEXT POINTER - 1 ON THE STACK
	DCX H
	PUSH H
FPDS2A:	INX D		; INCREMENT TEMPORARY STRING POINTER
	INX H		; INCREMENT TEMPORARY TEXT POINTER
FPDS2B:	LDAX D		; FETCH NEXT STRING CHARACTER
	ANA A		; CHECK FOR END OF STRING
	JZ FPDS4	; IF FOUND, EXIT TO FPDS4 (CARRY CLEARED)
FPDS2C:	CMP M		; COMPARE TEXT CHARACTER TO STRING CHARACTER
	JZ FPDS2A	; IF SAME, CHECK NEXT CHARACTER
PDS2C1:	POP H		; PULL STRING POINTER AND TEXT POINTER FROM THE STACK
	POP D		; INCREMENT THE TEXT POINTER, AND RETURN BOTH TO THE STACK
	PUSH D
	INX H
	PUSH H
	MOV A,M		; CHECK FOR END OF TEXT BUFFER
	ANA A
	JNZ FPDS2A	; END IF END OF FILE
FPDS3:	STC		; SET CARRY TO INDICATE STRING NOT FOUND
	JMP FPDS4A	; GO TO FPDS4A TO RESTORE STACK AND RETURN
FPDS4:	SHLD TXTPTR	; MOVE TEXT POINTER TO FIRST CHARACTER AFTER DESIRED STRING
FPDS4A:	POP H		; PULL DATA OFF STACK SO RETURN ADDRESS IS AVAILABLE
	INX H		; LET H/L = FIRST CHARCTER OF STRING IF SUCCESSFUL
	POP D
	INX D		; LET D/E = ORIGINAL VALUE OF D/E
	RET		; RETURN









;****************************************************************
;* FNDS:							*
;*		    FIND NEGATIVE D/E STRING			*
;*								*
;****************************************************************

;	THIS SUBROUTINE SEACHES BACKWARDS THROUGH THE TEXT BUFFER TO
;	FIND THE STRING OF INTEREST.

FNDS:	DCX D		; SAVE STRING POINTER - 1 ON THE STACK
FNDS1:	PUSH D
	LHLD TXTPTR	; SAVE TEXT POINTER -2 ON THE STACK
	DCX H
	DCX H
	PUSH H
FNDS2A:	INX D		; INCREMENT TEMPORARY STRING POINTER
	INX H		; INCREMENT TEMPORARY TEXT POINTER
FNDS2B:	LDAX D		; FETCH NEXT STRING CHARACTER
	ANA A		; CHECK FOR END OF STRING (CLEAR CARRY)
	JZ FNDS4A	; IF FOUND, EXIT TO FNDS4A
FNDS2C:	CMP M		; COMPARE TEXT CHARACTER TO STRING CHARACTER
	JZ FNDS2A	; IF SAME, CHECK NEXT CHARACTER
NDS2C1:	POP H		; PULL STRING POINTER AND TEXT POINTER FROM THE STACK
	POP D
	PUSH D		; DECREMENT TEXT POINTER AND RETURN BOTH TO THE STACK
	DCX H
	PUSH H
	MOV A,M		; CHECK FOR BEGINNING OF TEXT BUFFER
	INR A
	JNZ FNDS2A	; END IF BEGINNING OF FILE
FNDS3:	STC		; SET CARRY TO INDICATE STRING NOT FOUND
	JMP FNDS4A
FNDS4:	SHLD TXTPTR	; MOVE TEXT POINTER TO FIRST CHARACTER AFTER DESIRED STRING
FNDS4A:	POP H		; PULL DATA OFF STACK SO RETURN ADDRESS IS ACCESSABLE
	INX H		; LET H/L = FIRST CHARACTER OF STRING (IF SUCCESSFUL)
	POP D
	INX D		; LET D/E = ORIGINAL VALUE OF D/E
	RET		; RETURN




;****************************************************************
;* FS:								*
;*			FIND STRING				*
;*								*
;****************************************************************

FS:	MOV A,E		; DETERMINE POLARITY OF ITERATION COUNTER E
	DCR A
	JP MPF		; IF POSITIVE, FIND MULTIPLE POSITIVE STRINGS
	JM MNF		; IF 0 OR NEGATIVE, FIND MULTIPLE NEGATIVE STRINGS



;****************************************************************
;* MPF:								*
;*			MULTIPLE POSITIVE FIND			*
;*								*
;****************************************************************

;	THIS SUBROUTINE FINDS THE Eth OCCURANCE OF THE TEXT SPECIFIED
;	IN THE TEXT STRING (ASSUMING E IS A POSITIVE NUMBER). THE
;	STRING POINTER IS LEFT AT THE ESCAPE CHARACTER AT THE END
;	OF THE DESIRED STRING. THE TEXT POINTER IS LEFT AT THE END
;	OF THE Eth OCCURANCE OF THE STRING IN THE TEXT. IF THE STRING
;	IS NOT FOUND E TIMES, THE SUBROUTINE RETURNS WITH THE CARRY
;	FLAG SET.

MPF:	PUSH D		; SAVE ITERATION COUNTER "E" ON THE STACK
	CALL FT		; FETCH TEXT FROM THE EDIT STRING
	POP D		; RECALL ITERATION COUNTER
MPF1:	PUSH D		; SAVE ITERATION COUNTER
	LXI D,STRING	; LET D/E POINT TO STRING VARIABLE
	CALL FPDS	; FIND STRING (MOVING POSITIVE)
	POP D
	RC		; RETURN WITH CARRY SET IF UNSUCCESSFUL
	DCR E		; DECREMENT INTERATION COUNTER
	JNZ MPF1	; CONTINUE IF NOT DONE
	RET		; RETURN WITH CARRY CLEARED IF SUCCESSFUL




;****************************************************************
;* MNF:								*
;*			MULTIPLE NEGATIVE FIND			*
;*								*
;****************************************************************

;	THIS SUBROUTINE FINDS THE Eth OCCURANCE OF THE DESIRED
;	TEXT STRING, WORKING FROM THE TEXT POINTER BACKWARDS.

MNF:	PUSH D		; SAVE ITERATION COUNTER E ON THE STACK
	CALL FT		; FETCH TEXT FROM EDIT STRING
	POP D		; RECALL ITERATION COUNTER
	DCR E		; PRE-DECREMENT COUNTER
MNF1:	PUSH D		; SAVE ITERATION COUNTER
	LXI D,STRING	; LET D/E POINT TO STRING VARIABLE
	CALL FNDS	; FIND STRING (WORKING IN THE NEGATIVE DIRECTION)
	POP D		; RECALL ITERATION COUNTER
	RC		; RETURN WITH CARRY SET IF UNSUCCESSFUL
	INR E		; INCREMENT ITERATION COUNTER
	JNZ MNF1	; CONTINUE IF NOT DONE
	RET		; RETURN WITH CARRY CLEARED IF SUCCESSFUL





;****************************************************************
;* FT:								*
;*			FETCH TEXT				*
;*								*
;****************************************************************

;	THIS SUBROUTINE EXTRACTS THE DEIRED TEXT STRING FROM THE
;	EDIT COMMAND STRING AND STORES IT IN THE VARIABLE "STRING".
;	THE STRING POINTER IS LEFT POINTING TO THE ESCAPE CHARACTER
;	AT THE END OF THE DESIRED TEXT STRING.

FT:	LXI D,STRING-1
	LHLD STRPTR
FT1:	INX D		; MOVE NEXT BYTE FROM EDIT STRING INTO "STRING"
	INX H
	MOV A,M
	CPI ESC
	JZ FT2
	STAX D
	JMP FT1
FT2:	XRA A		; WHEN THE ESCAPE CHARACTER IS ENCOUNTERED
	STAX D		; STORE A NULL BYTE INSTEAD (END OF FILE MARK)
	SHLD STRPTR	; SET STRING POINTER TO THE ESCAPE CHARACTER
	RET



;****************************************************************
;* FE:								*
;*			FILL EDIT BUFFER			*
;*								*
;****************************************************************

;	THIS SUBROUTINE MOVES THE TEXT DESIGNATED BY THE D/E STRING
;	TO THE EDIT BUFFER. THE D/E POINTER ENDS UP AT THE END OF
;	THE STRING, AND H/L IS LEFT AT THE END OF THE EDIT BUFFER.

FE:	LHLD EDTPTR	; LET H/L = EDIT POINTER
	DCX H		; PREDECREMENT BOTH POINTERS
	DCX D
FE1:	INX H		; INCREMENT BOTH POINTERS
	INX D
	LDAX D		; MOVE BYTE FROM D/E
	MOV M,A		; TO EDIT BUFFER
	ANA A		; CHECK FOR END OF FILE MARK "00"
	JNZ FE1		; IF END OF FILE
	SHLD EDTPTR	; THEN SET EDIT POINTER TO END OF EDIT BUFFER
	RET		; AND RETURN







;****************************************************************
;* LDE:								*
;*		    FIND LENGTH OF STRING D/E			*
;*								*
;****************************************************************

;	THIS SUBROUTINE COUNTS THE NUMBER OF CHARACTERS IN THE STRING
;	DESIGNATED BY THE D/E PAIR, AND STORES THE RESULT IN THE
;	B/C REGISTER PAIR. THE D/E PAIR IS LEFT AT THE END OF THE STRING.

LDE:	LXI B,-1	; INITIALIZE B/C TO -1
LDE1:	INX B		; INCREMENT LENGTH COUNTER
	LDAX D		; CHECK FOR END OF STRING MARKER "00"
	ANA A
	RZ		; RETURN IF END OF STRING
	INX D		; OTHERWISE ADVANCE TO NEXT CHARACTER
	JMP LDE1




;****************************************************************
;* MS:								*
;*			MULTIPLE SUBSTITUTE			*
;*								*
;****************************************************************

;	THIS SUBROUTINE SELECTS THE POSITIVE OR NEGATIVE SUBSTITUTE
;	SUBROUTINE DEPENDING UPON THE POLARITY OF THE ITERATION
;	COUNTER (REGISTER E). IF "E" IS POSITIVE IT WILL MOVE FORWARD
;	THROUGH THE TEXT AND SUBSTITUTE THE NEW TEXT FOR THE OLD TEXT
;	"E" TIMES. IF "E" IS NEGATIVE IT WILL MOVE BACKWARDS TRHOUGH
;	THE TEXT AND SUBSTITUTE NEW TEXT FOR OLD TEXT "E" TIMES.
;	IF "E" IS ZERO IT WILL RETURN WITHOUT DOING ANYTHING.

;	IF THE OLD TEXT CAN NOT BE FOUND "E" TIMES, IT WILL RETURN WITH
;	THE CARRY FLAG SET TO INDICATE THE ERROR.

MS:	MOV A,E		; FETCH ITERATION COUNTER
	ANA A
	JP PS		; USE POSITIVE SUBSTITUTE SUBROUTINE IF E > 0
	JM NS		; USE NEGATIVE SUBSTITUTE SUBROUTINE IF E < 0
	RET		; RETURN IF E=0












;****************************************************************
;* PS:								*
;*			POSITIVE SUBSTITUTE			*
;*								*
;****************************************************************

PS:	LHLD STRPTR	; LET H/L = STRING POINTER
PS1:	PUSH H		; SAVE STRING POINTER ON STACK
	SHLD STRPTR	; RESET STRING POINTER TO OLD TEXT
	PUSH D		; SAVE ITERATION COUNTER ON THE STACK
	CALL FT		; OLD TEXT GOES TO STRING VARAIBLE
	LXI D,STRING
	CALL FPDS	; FIND OLD TEXT IN POSITIVE DIRECTION
	RC		; RETURN WITH CARRY SET IF UNSUCCESSFUL
	SHLD TXTPTR	; SET TEXT POINTER TO BEGINNING OF OLD TEXT
	LXI D,STRING
	CALL LDE	; FIND LENGTH OF THE OLD TEXT
	CALL DP		; DELETE THAT NUMBER OF CHARACTERS
	CALL FT		; NEW TEXT GOES INTO STRING VARIABLE
	LXI D,STRING
	CALL FE		; MOVE STRING VARIABLE INTO EDIT BUFFER
	CALL IT		; INSERT STRING VARIABLE INTO TEXT BUFFER
	POP D		; RECALL ITERATION COUNTER
	POP H		; RECALL BEGINNING OF OLD TEXT IN EDIT STRING
	DCR E		; DECREMENT ITERATION COUNTER
	JNZ PS1		; CONTINUE IF NOT DONE
	ANA A		; WHEN FINISHED, CLEAR CARRY FLAG
	RET		; AND RETURN



























;****************************************************************
;* NS:								*
;*			NEGATIVE SUBSTITUTE			*
;*								*
;****************************************************************

NS:	LHLD STRPTR	; LET H/L = STRING POINTER
NS1:	PUSH H		; SAVE BEGINNING OF OLD TEXT STRING ON STACK
	SHLD STRPTR	; RESET STRING POINTER TO OLD TEXT
	PUSH D		; SAVE ITERATION COUNTER ON THE STACK
	CALL FT		; FETCH THE OLD TEXT FROM EDIT STRING
	LXI D,STRING
	CALL FNDS	; FIND OLD TEXT WORKING BACKWARDS IN TEXT BUFFER
	RC		; RETURN WITH CARRY SET IF UNSUCCESSFUL
	SHLD TXTPTR	; MOVE TEXT POINTER TO BEGINNING OF THE OLD TEXT
	LXI D,STRING
	CALL LDE	; FIND THE LENGTH OF THE OLD TEXT
	CALL DP		; DELETE THAT MANY CHARACTERS
	CALL FT		; FETCH THE NEW TEXT FROM THE EDIT STRING
	LXI D,STRING
	CALL FE		; MOVE NEW TEXT INTO EDIT BUFFER
	CALL IT		; INSERT NEW TEXT INTO TEXT BUFFER
	POP D		; RECALL ITERATION COUNTER
	POP H		; RESET H/L TO BEGINNING OF OLD TEXT IN EDIT STRING
	INR E		; INCREMENT ITERATION COUNTER (NEGATIVE)
	JNZ NS1		; IF NOT DONE, REPEAT
	ANA A		; WHEN FINISHED, CLEAR CARRY FLAG
	RET		; AND RETURN

	END






;******************************************