File: VISTB.PG of Tape: Sources/Other/new-21-vista-page8
(Source file text) 

	FILE	VISTB - VISTA EDITOR
	TITLE	VERSION 01.21. REVISION LEVEL HISTORY
/
/
/
	TITLE	VERSION 01.17 -- DISPLAY CHARACTER
/
/	COME HERE TO DISPLAY THE CHARACTER IN THE AC. THIS ROUTINE
/	WILL PLACE THE CHARACTER AT THE CURSOR POSITION ON THE SCREEN
/	AND ALSO MOVE THE CHARACTER INTO THE MEMORY 'SCREEN'. THIS
/	ROUTINE ALSO HANDLES THE TRICKY PROBLEM OF A LINE EXCEEDING
/	THE LINE LENGTH OF THE SCREEN.
/
/	NOTE THAT BECAUSE WE HAVE TAB STOPS IT IS POSSIBLE THAT ADDING
/	A SINGLE CHARACTER IN INSERT CHARACTER MODE CAN
/	'OVERSET' THE SCREEN WIDTH.
/	ALTHOUGH UNLIKELY, WE MUST PROTECT AGAINST THIS EVENTUALITY.
/
DISCHR	SUB
	DCA	DCHAR		SAVE CHARACTER TO INSERT
	ROOM	4
	JMS	ROWCK		AT END OF ROW?
	JMP	1F		<1> YES: OK IF ROW HAS ROOM NOW
/
	TAD	INSF		<2> NO: ARE WE INSERT CHARACTER MODE?
	SPA CLA			SKIP IF NOT
	JMP	INSDIS		YES: HANDLE INSERT CHARACTER MODE
	JMP	2F		JUMP AHEAD NOW
/
/	HERE FOR INSERT AT END OF ROW.
/
1H	TADI	ROW		SET POINTER TO LENGTH/STATUS OF ROW
	DCA	TEMP		...
	INCI	TEMP		CHARACTER AT END OF ROW INCREASES COUNT
	EJECT
/
/	NOW INSERT THE CHARACTER AT THE CURRENT COLUMN POSITION
/
2H	INC	COL		+1 TO COLUMN POSITION
	TADI	ROW		...
	TAD	COL		...
	DCA	CHARP		...
	TAD	DCHAR		GET CHARACTER TO DISPLAY
	DCAI	CHARP		AND STORE IT
/
/	OVERWROTE CHARACTER IN MIDDLE OF LINE. IF WE OVERWROTE A TAB
/	STOP, TRY AND MOVE THE TAB STOP OVER (UNLESS IT ONLY PROVIDED
/	ONE SPACE POSITION ON THE SCREEN).
/
	JMS	LOADC		NOT AT END OF ROW: GET NEXT CHARACTER
	SNA			DID WE ADD THIS CHAR AT END OF ROW?
	JMP	4F		YES: CHECK FOR OVERSET ROW NOW
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SZA CLA			SKIP IF SO
	JMP	3F		NO: SO NOTHING MORE TO DO HERE
/
	TAD	=TAB		YES: SO REPLACE PAD CODE WITH TAB CODE
	DCAI	CHARP		...
3H	TAD	DCHAR		REGET CHARACTER AGAIN
	JMSI	EXTER		DISPLAY CHARACTER ON VIDEO SCREEN
	RET	DISCHR		ALL DONE HERE
/
/	HERE WE ADDED A CHARACTER AT THE END OF A ROW AND
/	MUST CHECK FOR AN OVERSET ROW NOW
/
4H	JMS	GLEN		GET LENGTH OF CURRENT ROW
	CMA			NEGATE AND COMPARE WITH
	TAD	COLSIZ		LAST COLUMN ON SCREEN (WHICH IS NOT USED)
	SPA CLA			SKIP IF NOT ABOUT TO ENTER LAST COLUMN
	JMP	6F		ROW FULL: HANDLE THIS
	TAD	DCHAR		REGET CHARACTER AGAIN
	JMSI	EXTER		DISPLAY CHARACTER ON VIDEO SCREEN
/
/	HERE TO CHECK FOR NO-CRLF CONDITION. IF SO, WE GENERATE
/	THE NO-CRLF GRAPHIC CHARACTER
/
5H	JMS	ROWSTAT		GET CURRENT ROW STATUS
	JMS	ENDCK		GENERATE GRAPHIC IF NO-CRLF BIT SET
	RET	DISCHR		ALL DONE HERE
/
6H	JMS	REDOLN		RE-DO THE ROW ON THE SCREEN
	JMP	5B		LOOP BACK NOW
	EJECT
/
/	HERE FOR INSERT CHARACTER MODE. AT THIS POINT WE CANNOT TELL
/	WHETHER THE ROW WILL FIT OR NOT. FIRST JOB IS TO PHYSICALLY
/	INSERT THE CHARACTER INTO THE CORRECT SPOT ON THE ROW, MOVING
/	ALL CHARACTERS FROM THE CURSOR POSITION TO THE END OF THE ROW
/	TO THE RIGHT ONE POSITION TO MAKE ROOM FOR THE NEW CHARACTER.
/	NOTE THAT ALLOCATED ROW SPACE ALLOWS FOR THIS CHARACTER EVEN
/	IF ROW IS NOW COMPLETELY FULL.
/
INSDIS	JMS	GLEN		GET LENGTH OF CURRENT ROW
	DCA	TEMP1		AND SAVE IT
	TAD	TEMP1		REGET ROW LENGTH
	CMA IAC			SUBTRACT FROM
	TAD	COL		CURRENT CURSOR POSITION
	DCA	CNTR		TO GET NEGATIVE COUNT OF CHARS TO MOVE
	TADI	ROW		START OF ROW ADDRESS-1
/
/	LOOP HERE PUSHING ALL THE CHARACTERS DOWN BY ONE POSITION. WE
/	ARE MOVING CHARS ONE AT A TIME STARTING WITH THE LAST CHAR ON THE
/	ROW AND MOVING LEFTWARDS, TOWARDS THE CURSOR POSITION.
/
1H	TAD	TEMP1		ADJUST POINTER
	DCA	TEMP1		...
	TAD	TEMP1		COPY POINTER TO INDEXING CELL
	DCA	TXR1		...
/
	TADI	TEMP1		PUSH ONE CHARACTER DOWN
	DCAI	TXR1		...
	LDI	-1		DECREMENT BOTH POINTERS NOW
	ISZ	CNTR		MORE CHARS TO MOVE?
	JMP	1B		YES: SO DO THEM
/
	CLA			AC WAS NON-ZERO HERE
	TAD	DCHAR		GET NEW CHARACTER
	DCAI	TEMP1		INSERT DIRECTLY AT CURSOR POSITION
	TADI	ROW		POINT AT LENGTH/STATUS WORD
	DCA	TEMP		...
	INCI	TEMP		UPDATE THE ROW COUNT
	JMS	REDOLN		RECOMPUTE ALL TAB STOPS/CHECK FOR OVERSET ROW
	JMS	RIGHTC		MOVE CURSOR TO RIGHT (ESP. IF TAB JUST ENTERED)
	JMSI	EXTER		RE-POSITION CURSOR
	RET	DISCHR		ALL DONE HERE
	TITLE	REDOLN - REDO THE CURRENT ROW
/
/	THIS ROUTINE TAKES THE CURRENT ROW AND RECALCULATES ALL TAB STOPS
/	IN THE ROW. IT IS CALLED WHENEVER A CHARACTER IS DELETED ON A ROW,
/	OR WHEN WE HAVE INSERTED A NEW CHARACTER INTO AN OVERSET ROW, OR
/	WHENEVER A CHARACTER IS INSERTED IN INSERT CHARACTER MODE.
/
/	ROW IS CORRECTED BY COPYING TO 'SAVBUF' AND THEN MOVING BACK
/	TO ORIGINAL ROW.
/
REDOLN	SUB
	JMS	COPYROW		COPY THIS ROW INTO THE SAVE BUFFER
	ROOM	4
	JMS	SIZE		CHECK ON SIZE OF THIS ROW
	NOP			<1> ONE ROW, SO OK HERE
/
/	NOW COPY THE CURRENT ROW BACK TO THE SCREEN. WE NEED TO COPY
/	FROM THE EARLIER OF THE SPLIT POSITION OR THE ORIGINAL CURSOR
/	POSITION.
/
	TAD	COL		<2> SAVE CURRENT COLUMN POSITION
	DCA	COLSV2		...
	TAD	SPLIT		GET POSSIBLE SPLIT POINT
	SNA			DID WE SPLIT THE ROW IN TWO?
	JMP	2F		NO, SO USE 'COL' FOR COLUMN POSITION
	TAD	=-SAVBUF	YES: AT WHAT COLUMN DID WE SPLIT THE ROW?
	CMA IAC			COMPARE WITH CURSOR COLUMN
	TAD	COL		...
	SPA CLA			WHERE WAS THE SPLIT POINT?
	JMP	2F		AFTER THE CURSOR COLUMN
/
	TAD	SPLIT		BEFORE CURSOR COLUMN: COMPUTE COLUMN
	TAD	=-SAVBUF	FROM WHICH TOP ROW MUST BE RE-DONE
	DCA	COL		...
/
	TAD	COL		COMPUTE
	CMA			COLUMN POSITION FOR 2ND ROW NOW
	TAD	COLSV2		...
/
/	COME HERE WHEN WE ARE USING THE 'COL' POSITION. 'RFLAG' REMEMBERS
/	WHERE THE BREAKPOINT IS.
/
2H	DCA	RFLAG		SET/CLEAR FLAG
	JMSI	EXTER		POSITION CURSOR NOW
	TAD	ROW		SET 'ROWPTR' FOR 'COPYSV' CALL
	DCA	ROWPTR		...
	JMS	COPYSV		COPY OUT THE FIRST ROW NOW
	TAD	COLSV2		RESTORE PROPER COLUMN POSITION NOW
	DCA	COL		...
	EJECT
/
/	TOP ROW IS NOW ALL RIGHT IN MEMORY AND ON THE SCREEN. SEE NOW
/	IF WE HAD ANOTHER ROW TO DEAL WITH
/
	TAD	SPLIT		GET POSSIBLE ROW-SPLIT ADDRESS
	SNA CLA			DID WE SPLIT THIS ROW IN TWO?
	JMP	3F		NO: SO ALL DONE HERE
/
	ROOM	4
	JMS	ENDROW		CHECK FOR END OF ROW
	JMS	DO2ND		<1> ON BOTTOM ROW: JUST COPY TO BLANK ROW NOW
/
/	WHERE DO WE RE-POSITION THE CURSOR WITH TWO ROWS?
/
	TAD	RFLAG		<2> WAS SPLIT PRIOR TO CURSOR COLUMN?
	SNA			SKIP IF SO
	JMP	3F		SPLIT AFTER CURSOR COLUMN, STAY ON SAME ROW
/
	DCA	COL		SET COLUMN FOR SECOND ROW
	INC	ROW		STEP TO THAT ROW NOW
/
3H	JMSI	EXTER		POSITION CURSOR NOW PROPERLY
	RET	REDOLN		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO CHECK FOR BEING ON THE LAST ROW.
/
/		ROOM	4
/		JMS	ENDROW
/		<RETURN>		WAS ON LAST ROW
/		<RETURN>		NOT ON LAST ROW
/
/	IF WE WERE ON THE LAST ROW, THIS ROUTINE WILL MOVE THE TOP ROW
/	OUT, AND DELETE IT LEAVING A BLANK ROW AT THE LAST ROW
/	'ROW' IS THEN SET TO THE ROW JUST ABOVE THAT ROW.
/	NOTE THAT 'SAVBUF' HAS BEEN DESTROYED BY OUR CALL TO 'TLINO'
/	SO CALLING ROUTINE SHOULD CALL 'COPYROW' IF NECESSARY TO
/	RESTORE THE SAVE BUFFER.
/
/	IF WE WERE NOT ON THE LAST ROW, AN INSERT ROW FUNCTION IS
/	PERFORMED AND THE CURSOR IS MOVED JUST ABOVE THAT BLANK ROW
/
	ROOM	4
	INC	ENDROW		STEP POINTER FOR 2ND EXIT
ENDROW	SUB
	TAD	COL		SAVE COLUMN FOR LATER RESTORATION
	DCA	COLSV2		...
	TAD	ROW		GET CURRENT ROW
	CMA IAC			NEGATE AND COMPARE WITH
	TAD	LASTROW		LAST ROW IN TABLE
	SZA CLA			WHICH ROW ARE WE ON?
	JMP	2F		NOT ON LAST ROW
/
/	HERE WE ARE ON THE LAST ROW. MOVE OUT THE TOP ROW
/
	JMS	TLINO		MOVE OUT THE TOP ROW
	TAD	ROWTAB		DELETE THE TOP ROW
	JMS	RMVLN		...
	TADI	LASTROW		GET ADDRESS OF LAST ROW
	DCA	TEMP		...
	DCAI	TEMP		REMOVE 'ROW-UNESTABLISHED' FLAG
	LDI	-1		DECREMENT ROW POSITION
	TAD	ROW		...
	DCA	ROW		...
	RET	ENDROW		ALL DONE HERE
	EJECT
/
/	NOT ON LAST ROW. CHECK TO SEE IF WE SHOULD TRY AND MERGE
/	THE OVERSET WORD(S) WITH THE FOLLOWING ROW. WE DO THIS
/	IF /W IS SET (WORDWRAP MODE), OR IF THE CURRENT ROW IS
/	FLAGGED WITH NO-CRLF. OTHERWISE WE UNCONDITIONALLY OPEN
/	UP A NEW ROW (IF NOT /W, WE DON'T WANT TO MERGE STATEMENTS
/	TOGETHER!).
/
2H	TAD	SPLIT		GET POSSIBLE SAVED SPLIT POINT FOR ROW
	SNA			WHO CALLED THIS ROUTINE?
	JMP	6F		'RETURN' FUNCTION: DON'T MERGE ROW!
	DCA	GXR		SAVE AS ADDRESS FOR COPYING OVERSET TEXT
/
/	WE WANT TO MERGE THE TWO ROWS. COPY THE SECOND HALF OF THE ROW
/	WE SPLIT INTO THE BEGINNING OF THE SAVE BUFFER. THEN CALL 'COPYROW'
/	TO APPEND THE REMAINDER OF THE ROW BELOW THE ROW WE SPLIT.
/
	TAD	=PUTXR		SET SUBROUTINE CALL FOR 'TABEX'
	DCA	SUBR2		...
	TAD	=SAVBUF-1	POINTER TO WHERE WE MOVE THE REMAINDER TO
	DCA	PXR		...
	TAD	=GETXR		SET TO READ FROM OVERSET TEXT
	JMS	TABEX		READ AND EXPAND TAB STOPS
	TAD	PXR		GET POSITION OF SENTINEL CODE
	DCA	SPLITSV		SAVE AS THE OLD SPLIT POINT
/
/	IF /W SET, ALWAYS TRY AND MERGE THE ROWS. IF NOT, THEN CHECK
/	THE STATUS WORD. IF THE NO-CRLF BIT IS SET, THEN MERGE, OTHERWISE
/	WE WILL ALWAYS OPEN UP A NEW ROW
/
	TAD	RFLAG		FLAG TO INDICATE WHERE ROW WAS SPLIT
	SZA CLA			WHERE WAS THIS ROW SPLIT?
	JMP	5F		SPLIT BEFORE CURSOR COLUMN, NEVER MERGE
	TADI	ROW		SAVE POINTER TO LENGTH/STATUS WORD
	DCA	TEMP		...
	TAD	WFLAG		GET THE /W FLAG
	SNA			WAS /W OPTION SELECTED?
	JMP	3F		YES: SO TRY AND MERGE ROWS
	ANDI	TEMP		NO: HAS NO-CRLF BIT BEEN SET ON THIS ROW?
	SNA CLA			SKIP IF SO
	JMP	5F		NO: SO FORCE A NEW ROW BELOW THIS ONE
/
/	CONTINUE HERE WHEN WE ARE DEFINITELY GOING TO TRY AND MERGE
/	THE TWO ROWS TOGETHER
/
3H	TAD	=' 		SUPPLY BLANK BETWEEN MERGE ROWS
	DCAI	SPLITSV		(I.E. END OF ROW IS LIKE A BLANK)
	TAD	PXR		GET POSITION OF BLANK WE JUST STORED
	INC	ROW		DROP 'ROW' FOR 'COPYROW' CALL
	JMS	COPYROW		COPY OUT THE SECOND ROW AT END
	ROOM	4
	JMS	SIZE		CAN WE MERGE THESE TWO ROWS (IS THERE ROOM)
	JMP	*+2		<1> YES: IT WILL FIT IN ONE ROW
	JMP	4F		<2> NO: SO MUST USE BLANK ROW
	DCA	COL		<2> YES: SET FOR COPYING MERGED ROW
	TAD	ROW		SET ROW POINTER FOR 'COPYSV' CALL
	DCA	ROWPTR		...
	JMSI	EXTER		POSITION CURSOR ON SCREEN
	JMS	COPYSV		COPY MERGED ROW BACK TO SCREEN
	LDI	-1		MOVE ROW POINTER BACK NOW
	TAD	ROW		...
	DCA	ROW		...
	DCA	SPLIT		CLEAR THIS TO AVOID 'DO2ND' CALL AT 7H
	JMP	7F		RESTORE PROPER COLUMN: WE ARE DONE
/
/	HERE WHEN WE WERE UNABLE TO MERGE THE TWO ROWS TOGETHER.
/	WE HAVE A PROBLEM: TO MAKE ROOM FOR THE SECOND HALF OF THE ROW
/	WE ARE GOING TO HAVE TO INSERT A ROW BELOW THE CURRENT ROW. HOWEVER
/	WHEN WE CALL THE 'INSROW' ROUTINE, THE SAVE BUFFER WILL BE
/	OVERWRITTEN. RATHER THAN ALLOCATING ANOTHER BUFFER JUST TO HANDLE
/.	THIS SINGLE CASE, WE WILL COPY THE FIRST PART OF THE SAVE BUFFER
/	(WHICH HAS THE SECOND PART OF THE ORIGINAL ROW) TO THE END OF
/	THE SAVE BUFFER (MUST BE SAFE BECAUSE THE LAST ROW BY DEFINITION
/	CANNOT EXCEED ONE HALF THE LENGTH OF THE SAVE BUFFER)
/
4H	LDI	-1		FIRST RESET ROW POINTER
	TAD	ROW		...
	DCA	ROW		...
/
/	NOTE THAT WE COPY THE 2ND PART OF THE ROW JUSTIFIED TO THE END
/	OF 'SAVBUF' WHICH ALSO HAS A SENTINEL CODE STORED THERE
/
5H	CLL			MARK THIS ROW AS NOT HAVING A CR/LF AFTER IT
	TADI	ROW		(NOCRLF NEEDS ROW STATUS ADDRESS IN AC)
	JMS	NOCRLF		...
	TAD	SPLITSV		GET SAVED SPLIT POINT
	CMA IAC			SUBTRACT FROM START OF BUFFER
	TAD	=SAVBUF		YIELDS NEGATIVE COUNT OF SIZE OF 2ND PART
	DCA	CNTR		SAVE AS LOOP COUNTER
	TAD	CNTR		REGET AND NOW
	TAD	=SAVBUF+LMASK-1	COMPUTE WHERE TO PLACE THE 2ND PART OF ROW
	DCA	TXR2		...(AT END OF SAVE BUFFER)
	TAD	TXR2		RESET NOW AS THE NEW SPLIT POINT
	DCA	SPLIT		...
	TAD	=SAVBUF-1	POINTER TO WHERE THE PART OF THE ROW IS NOW
	DCA	TXR1		...
/
/	LOOP HERE TO MOVE THE PART OF THE ROW OVER
/
	TADI	TXR1		COPY OVER A WORD
	DCAI	TXR2		...
	ISZ	CNTR		LOOP UNTIL ALL COPIED
	JMP	*-3		...
/
/	HERE WHEN WE DEFINITELY WANT TO OPEN UP A BLANK ROW
/	BELOW THE CURRENT ROW
/
6H	TAD	ROW		GET CURRENT ROW ADDRESS
	IAC			+1 FOR NEXT ROW
	JMS	INSROW		INSERT ROW THERE
7H	TAD	COLSV2		RESTORE COLUMN POSITION
	DCA	COL		...
	TAD	SPLIT		DID WE SPLIT THE ROWS?
	SZA CLA			SKIP IF NOT (OR DONE ALREADY)
	JMS	DO2ND		NO: SO DO THE 2ND PART OF THE ROW NOW
	JMP	ENDROW-2	TAKE 2ND RETURN NOW
	EJECT
/
/	SUBROUTINE TO COPY THE CURRENT ROW OUT TO THE SAVE BUFFER. USES
/	CALL TO 'TABEX' ROUTINE WHICH ACTUALLY DOES THE WORK. ONLY FUNCTION
/	OF THIS ROUTINE IS TO SET UP THE ARGUMENTS FOR A CALL TO 'TABEX'
/	IF AC IS NO-ZERO ON ENTRY, ASSUME THAT WE HAVE THE ADDRESS
/	SET FOR 'PXR' SO WE CAN APPEND TEXT TO THE SAVE BUFFER
/
COPYROW	.SUB	22
	SNA			SKIP IF WE HAVE A POINTER IN THE AC
	TAD	=SAVBUF-1	SET 'PUT-CHARACTER' POINTER
	DCA	PXR		...
	JMS	GLEN		GET LENGTH OF CURRENT ROW
	IAC			+1 TO ACCOUNT FOR LENGTH/STATUS WORD
	TADI	ROW		+STARTING ADDRESS OF CURRENT ROW
	DCA	TEMP		SAVE POINT TO THAT ROW
	DCAI	TEMP		INSTALL SENTINEL (NEEEDED BY 'TABEX')
	TADI	ROW		REGET POINTER TO START OF ROW
	DCA	GXR		SET 'GET-CHARACTER' POINTER
	TAD	=PUTXR		SET SUBROUTINE POINTER FOR 'TABEX'
	DCA	SUBR2		...
	TAD	=GETXR		SET POINTER FOR GET-CHARACTER ROUTINE
	JMS	TABEX		COPY ROW AND EXPAND TAB STOPS
	.RET	COPYROW		ALL DONE HERE
	EJECT
/
/	DO THE SECOND OF THE TWO ROWS CREATED BY SPLITTING A SINGLE
/	ROW IN 'SAVBUF'. ON ENTRY HERE, 'SPLIT' MARKS THE POINT
/	TO SPLIT THE ROW IN 'SAVBUF'. ROW TO BE FILLED IS BELOW
/	THE CURRENT ROW.
/
DO2ND	.SUB	20
	TAD	ROW		ADDRESS OF CURRENT ROW
	IAC			+1 IS ADDRESS OF NEXT ROW
	DCA	ROWPTR		SET THAT FOR THE 'COPYSV' ROUTINE
	TAD	COL		SAVE CURRENT COLUMN POSITION
	DCA	COLSV2		...
	TAD	ROWPTR		POSITION CURSOR ON 'ROWPTR' ROW
	JMS	POSROW		...
	JMS	RESCOL		RESTORE ROW (AND COL ANWAY)
	DCA	COL		ZERO COL (FOR 'COPYSV' CALL)
	TAD	SPLIT		GET THE SPLIT POINT FOR THE ROW
	JMS	COPYSV		COPY 2ND HALF OF ROW NOW
	TAD	COLSV2		RESTORE ORIGINAL COLUMN POSITION
	DCA	COL		...
	.RET	DO2ND		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO FLAG THE CURRENT ROW AS NOT BEING FOLLOWED BY
/	A CR/LF. THIS IS DONE SO THAT WE DO NOT CORRUPT THE ORIGINAL
/	LINE BREAKS. NOTE THAT IF THE /W OPTION IS SET, WE CANNOT
/	AVOID A CR/LF AFTER BREAKING A LINE (WHICH IS WHAT WE WANT TO DO)
/
/	ENTRY:
/		AC	ADDRESS OF ROW WE WANT TO MARK
/		LINK	0	ONLY SET BIT IF NOT /W
/		LINK	1	FORCE NO-CRLF BIT ON REGARDLESS
/
NOCRLF	.SUB	12
	DCA	TEMP		SAVE ADDRESS OF ROW LENGTH/STATUS WORD
	RTR			SHIFT LINK TO POSITION OF NO-CRLF BIT
	SNA			IF 2000 IN AC, LEAVE IT THERE
	TAD	WFLAG		ELSE GET CURRENT FLAG SETTING
	DCA	TEMP2		SAVE FOR A MOMENT
	LDI	02000.XO.-1	STRIP OFF THE CR/LF BIT IN CASE SET
	ANDI	TEMP		...
	TAD	TEMP2		SET BIT NOW (UNLESS /W SELECTED)
	DCAI	TEMP		AND STORE IT BACK
	.RET	NOCRLF		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO SIZE UP THE ROW IN 'SAVBUF'. IF THE ROW IS
/	LONGER THAN THE COLUMN WIDTH, THIS ROUTINE WILL FIND
/	WHERE TO BREAK THE ROW AND SET THAT POSITION IN 'SPLIT'
/
/		ROOM	4
/		JMS	SIZE
/		<RETURN>	<1> FIT WITHIN ONE ROW
/		<RETURN>	<2> SPLIT INTO TWO ROWS
/			'PXR'	POINTS AT SENTINEL
/			'SPLIT'	POINTS AT SPLIT POINT
/
/	ON ENTRY TO THIS ROUTINE, 'PXR' POINTS AT THE SENTINEL WORD
/	ON THE ROW THAT WE ARE TESTING.
/
	ROOM	4
	INC	SIZE		SET FOR 2ND EXIT
SIZE	SUB
	DCA	SPLIT		ZERO THIS (AS A FLAG IN CASE NO SPLIT)
	TAD	=SAVBUF-1	STARTING ADDRESS OF SAVE BUFFER
	TAD	COLSIZ		+ COLUMN SIZE ON SCREEN
	CMA 			NEGATE AND COMPARE WITH
	TAD	PXR		POSITION OF SENTINEL ON ROW THERE
	SPA CLA			IS THERE ROOM FOR THIS ROW?
	RET	SIZE		YES: SO TAKE THE FIRST RETURN
/
/	THE ROW IS TOO LARGE. BACKSPACE NOW LOOKING FOR A
/	SPACE CODE WHERE WE CAN BREAK THE ROW.
/
	LDI	-1		ESTABLISH POINTER INTO ROW
	TAD	PXR		...
	DCA	SPLIT		...
/
/	LOOP HERE SEARCHING FOR PLACE TO BREAK ROW
/
1H	TAD	SPLIT		CURRENT ADDRESS INTO SAVE BUFFER
	TAD	=-SAVBUF	COMPARE WITH START ADDRESS OF BUFFER
	SNA			HAVE WE WORKED OUR WAY BACK TO START?
	JMP	NOBRAK		YES: SO THERE WAS NO BREAKPOINT
	TAD	=SAVBUF-1	NO: DECREMENT POINTER
	DCA	SPLIT		...
/
	TADI	SPLIT		LOAD CHARACTER AT THAT POSITION
	TAD	=-' 		SPACE?
	SZA CLA			SKIP IF SPACE
	JMP	1B		SOMETHING ELSE, LOOP BACK
	EJECT
/
/	WE HAVE FOUND A SPLIT POINT. SURPRISINGLY ENOUGH HOWEVER, THIS
/	MAY NOT DO THE TRICK. WHY? BECAUSE AN USUAL SPACING OF TAB
/	STOPS COULD (ON A SINGLE KEYSTROKE) HAVE RADICALLY ALTERED
/	THE LENGTH OF THE ROW. TO BE SURE, CHECK AGAIN ON THE ROW
/	FITTING.
/
	TAD	=SAVBUF		START OF ROW
	TAD	COLSIZ		+ COLUMN SIZE
	CMA IAC			NEGATE AND COMPARE AGAIN
	TAD	SPLIT		WITH THE SPLIT POINT
	SMA CLA			DOES THE ROW NOW FIT?
	JMP	1B		NO. SO IT WAS JUST AS WELL WE CHECKED.
/
2H	DCAI	SPLIT		YES: OVERWRITE SPACE WITH SENTINEL CODE
	JMP	SIZE-2		AND TAKE THE 2ND RETURN NOW
/
/	HERE THERE IS NO SPACE ON THE ROW. JUST ARBITRARILY OVERWRITE
/	A CHARACTER NEAR THE END OF THE ROW. WE COULD GO TO THE
/	TROUBLE OF INSERTING A SENTINEL BUT WHY BOTHER? VISTA IS FOR
/	EDITING TEXT AND THERE AREN'T MANY WORDS IN ANY LANGUAGE THAT
/	EXCEED THE COLUMN WIDTH. BESIDES WHICH, AT 8-K WE MUST SAVE
/	MEMORY FOR MORE USEFUL FEATURES
/
NOBRAK	LDI	-2		BREAK JUST BEFORE END OF ROW
	TAD	COLSIZ		...
	TAD	=SAVBUF		...
	DCA	SPLIT		SET ARBITRARY SPLIT POINT
	TAD	=X:BEL		RING BELL
	JMSI	EXTER		TO ALERT USER TO LOST CHARACTER
	JMP	2B		LOOP BACK NOW
	EJECT
/
/ SUBROUTINE TO COPY OVER CHARACTERS EXTRACTED VIA CALLS TO
/ A SUBROUTINE WHOSE ADDRESS IS PASSED IN THE AC ON ENTRY.
/ CHARACTERS ARE STORED VIA 'PXR' WHICH SHOULD BE SET
/ TO THE ADDRESS-1 OF WHERE THE CHARACTERS ARE TO BE
/ STORED. THE PRIMARY FUNCTION OF THIS ROUTINE IS TO TAKE
/ A STREAM OF CHARACTERS, AND EXPAND THE TAB STOPS PROPERLY
/ INSERTING AN APPROPRIATE NUMBER OF PAD CODES.
/
/ ON EXIT, 'PXR' POINTS AT THE ZERO SENTINEL CODE STORED
/ AFTER THE POINT WHERE THE CHARACTERS WERE PLACED.
/
/ ALSO ON EXIT, 'COLSV2' HAS THE VALUE THAT 'COL' HAD ON ENTRY (THIS
/ FACT IS USED BY SEVERAL ROUTINES THAT CALL 'TABEX').
/
TABEX	.SUB	45
	DCA	SUBRC		SAVE ADDRESS OF ROUTINE TO CALL
	TAD	COL		SAVE CURRENT COLUMN FOR LATER RESTORATION
	DCA	COLSV2		...(WE NEED 'COL' FOR TAB STOPS)
	DCA	COL		ZERO COLUMN NOW
/
/	LOOP HERE COPYING CHARACTERS OVER VIA 'PXR' AT THIS POINT,
/	STRIP ALL PAD CODES COMPLETELY AND WHEN A TAB CODE IS FOUND,
/	RECALCULATE THE PAD CODES TO GO AFTER IT.
/
5H	DCA	FLAG		SET/CLEAR FLAG ON MARKED ROW FOUND
0H	JMSI	SUBRC		NEXT CHAR FROM INPUT ROUTINE
	SPA			TEST FOR -1 (MARKED ROW FOUND)
	JMP	5B		HANDLE MARKED ROW
	SNA			0 IS SENTINEL ON STRING
	JMP	4F		ALL DONE HERE
	TAD	=-TAB		TAB CODE HERE?
	SZA			SKIP IF SO
	JMP	2F		NO: OFF TO CHECK FOR PAD CODE
/
/	HERE FOR TAB CODE: STORE TAB CODE AND THEN PAD CODES TILL TAB
/	STOP REACHED.
/
	TAD	=TAB		STORE TAB CODE FIRST TIME THROUGH
/
/	LOOP BACK HERE TO STORE A PAD CODE.
/
1H	DCAI	PXR		STORE TAB/PAD CODE
	INC	COL		STEP COLUMN POSITION
	TAD	COL		GET CURRENT COLUMN POSITION
	AND	=7		TAB STOPS EVERY 8 POSITIONS
	SNA CLA			SKIP IF NOT AT TAB STOP
	JMP	0B		ALL DONE WHEN TAB-STOP FOUND
	LDI	PAD		ELSE STORE A PAD CODE AND LOOP BACK
	JMP	1B		...
/
2H	TAD	=TAB-PAD	PAD CODE FROM TAB?
	SNA			SKIP IF NOT
	JMP	0B		PAD CODES ARE STRIPPED
/
	TAD	=PAD		RESTORE ORIGINAL CHARACTER
	DCAI	PXR		AND STORE INTO BUFFER
	INC	COL		STEP COLUMN POSITION
	JMP	0B		YES: OFF TO HANDLE THEM
/
/	HERE AT THE END OF THE ROW. INSTALL A SENTINEL
/
4H	DCAI	PXR		ZERO SENTINEL ON 'SAVBUF'
	TAD	COLSV2		RESTORE PRIOR COLUMN POSITION
	DCA	COL		...
	TAD	FLAG		RETURN FLAG IN AC
	.RET	TABEX		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO COPY THE LINE IN THE SAVE BUFFER ('SAVBUF') WHICH
/	IS TERMINATED WITH A ZERO SENTINEL WORD TO THE ROW SPECIFIED
/	IN 'ROWPTR' STARTING AT THE COLUMN SPECIFIED IN 'COL'.
/
/	IF THE AC IS ZERO ON ENTRY, IT IS ASSUMED THAT THE OFFSET
/	INTO 'SAVBUF' IS IN THE AC.
/
COPYSV	.SUB	40
	SNA			DO WE HAVE AN ADDRESS HERE?
	TAD	=SAVBUF-1	NO, SO SET FOR SAVE BUFFER
	TAD	COL		ADD COLUMN OFFSET
	DCA	TXR1		AND SET IN INDEXING CELL
	TADI	ROWPTR		ROW ADDRESS AGAIN
	TAD	COL		PLUS CURRENT COLUMN POSITION
	DCA	TEMP2		POINTS JUST BEFORE CURRENT COLUMN
	TADI	ROWPTR		SET CURRENT ROW ADDRESS
	DCA	ROWPTR		...
	TADI	ROWPTR		GET ROW STATUS/LENGTH
	AND	=(LMASK+04000).XO.-1	CLEAR COUNT/ESTABLISHED BIT
	TAD	COL		ADD IN COLUMN AS LENGTH
	DCAI	ROWPTR		AND STORE IT BACK NOW
/
/ HANDLE CASE NOW OF BEING IN COLUMN 0 WHEN WE ARE REGENERATING THEN
/ ENTIRE ROW. WE WANT TO HANDLE THE VIDEO CODE (IN PARTICULAR TO HANDLE
/ THE CASE OF A MARKED ROW JUST SCROLLED ONTO THE SCREEN)
/
	TAD	COL		GET CURRENT COLUMN
	SZA CLA			WHAT COLUMN ARE WE IN?
	JMP	1F		NOT COLUMN 0: CONTINUE
/
	TADI	ROWPTR		GET CURRENT STATUS FOR ROW
	CLL RTL			SHIFT MARKED BIT INTO AC0
	SPA CLA			WAS THIS A MARKED ROW?
	TAD	=X:SPV2-X:NMV	YES: SO FLAG IT WITH VIDEO
	TAD	=X:NMV		NO: RESTORE NORMAL VIDEO
	JMSI	EXTER		...
/
/	LOOP HERE TO COPY REMAINDER OF COLUMN TO MEMORY AND TO VIDEO SCREEN.
/
1H	TADI	TXR1		NEXT CHARACTER FROM SAVE BUFFER
	SNA			TEST FOR SENTINEL ON SAVE BUFFER
	JMP	2F		DONE HERE
	INC	TEMP2		STEP POINTER TO NEXT ROW SLOT
	DCAI	TEMP2		STORE INTO THE CURRENT ROW
	INCI	ROWPTR		STEP COUNT FOR THIS LINE
	TADI	TEMP2		REGET CURRENT CHARACTER
	JMSI	EXTER		OUTPUT TO SCREEN TOO
	JMP	1B		LOOP BACK FOR NEXT CHARACTER
/
2H	TAD	=X:EOL		ERASE TO END OF ROW NOW
	JMSI	EXTER		...
	TADI	ROWPTR		GET STATUS WORD AGAIN
	JMS	ENDCK		GENERATE GRAPHIC IF NO-CRLF BIT IS SET
	.RET	COPYSV		ALL DONE HERE
	TITLE	INSROW - INSERT ROW
/
/	HERE TO INSERT A BLANK ROW AT ROW ADDRESS IN AC
/	ACTUAL ACTION IS TO TAKE ALL ROW TABLE SLOTS FROM
/	THAT ROW TO THE END OF THE TABLE AND MOVE THEM DOWN
/	BY ONE WORD.. THE BOTTOM ROW IS SCROLLED OFF INTO THE BELOW
/	SCREEN BUFFER. THE ROW IN WHICH THE CURSOR WAS LOCATED IS
/	THEN MADE INTO A BLANK ROW AND THE CURSOR IS MOVED TO COLUMN
/	0 IN THAT ROW.
/
/	NOTE THAT THE VIDEO SCREEN IS ASSUMED TO HAVE A HARDWARE METHOD
/	OF IMPLEMENTING THIS FUNCTION. IF NOT, THEN THE EXTERPRETER MODULE
/	MUST IMPLEMENT THIS IN SOFTWARE BY RECOPYING ALL ROWS FROM
/	THE CURSOR ROW TO THE END OF THE SCREEN.
/
ROWINS	JMS	NOCOM		INSERT ROW NOT ALLOWED IN CMND MODE
	TAD	ROW		INSERT AT CURRENT ROW
	JMS	INSROW		DO INSERT ROW FUNCTION
	JMP	ASMCHK		CHECK NOW FOR HEURISTICS MODE
/
/	ACTUAL SUBROUTINE TO PERFORM INSERT ROW FUNCTION
/
INSROW	.SUB	40
	DCA	ROWPTR2		SAVE POINTER TO THIS ROW
/
/	PUSH OUT BOTTOM ROW ONLY IF IT IS MARKED AS BEING ESTABLISHED.
/
	TADI	LASTROW		POINT AT LENGTH/STATUS OF LAST ROW
	DCA	RSAVE		...
	TADI	RSAVE		GET LENGTH/STATUS WORD
	SMA CLA			IS THIS ROW AN ESTABLISHED ROW?
	JMS	BLINO		YES: SO MOVE IT OUT NOW
/
/	NOTE THAT THE SCREEN ITSELF IS QUITE INTACT SINCE EACH LINE
/	IN PHYSICAL MEMORY HAS A FULL COLUMN WIDTH ALLOCATED FOR IT.
/	FOR THIS REASON, IT IS ONLY THE ROW TABLE THAT HAS TO BE MOVED.
/
	TAD	LASTROW		GET ADDRESS OF LAST ROW
	CMA			SUBTRACT FROM
	TAD	ROWPTR2		ROW WE ARE GOING TO INSERT ON
	DCA	CNTR		SET AS NEGATIVE LOOP COUNTER
	LDI	-1		SET POINTER NOW TO ROW BEFORE LAST ROW
	TAD	LASTROW		...
	DCA	TEMP		...
	JMP	2F		JUMP INTO MIDDLE OF LOOP NOW
	EJECT
/
/	LOOP HERE PUSHING THE ROWS DOWN ONE BY ONE.
/
1H	TAD	TEMP		GET CURRENT ROW ADDRESS
	DCA	TXR1		COPY TO INDEXING REGISTER
	TADI	TEMP		WORD FROM ROW TABLE
	DCAI	TXR1		MOVE INTO FOLLOWING SLOT
	LDI	-1		DECREMENT ROW TABLE POINTER
	TAD	TEMP		...
	DCA	TEMP		...
2H	ISZ	CNTR		MORE ROWS TO MOVE?
	JMP	1B		YES: BACK TO MOVE THEN
/
/	HERE WHEN DONE-RESTORE ROW FROM PRIOR LAST ROW AND SET AS NULL
/	ROW AT CURRENT ROW.
/
	TAD	RSAVE		GET SAVED ROW ADDRESS
	DCAI	ROWPTR2		SET AS ADDRESS OF CURRENT ROW
	DCAI	RSAVE		CLEAR OUT LENGTH/STATUS WORD
	TAD	ROWPTR2		GET ADDRESS OF CURRENT ROW
	JMS	POSROW		POSITION SCREEN CURSOR
	TAD	=X:INS		DO INSERT LINE FUNCTION ON VIDEO SCREEN
	JMSI	EXTER		...(NOTE: ROW/COL SET PROPERLY)
	JMS	RESCOL		RESTORE ORIGINAL ROW AND COLUMN NOW
	.RET	INSROW		ALL DONE HERE
	TITLE	RETURN CODE FUNCTION
/
/	HERE TO HANDLE THE RETURN CODE. IF WE ARE AT THE END OF THE LINE,
/	JUST MOVE DOWN AND CREATE A NEW LINE BELOW THE CURRENT LINE.
/	IF WE ARE IN THE MIDDLE OF A LINE, SPLIT THE LINE AT THAT POINT.
/
RETURN	TAD	CMND		LOAD MODE FLAG
	SZA CLA			WHAT MODE ARE WE IN?
	JMP	CMEXEC		COMMAND MODE: HANDLE THIS
/
/	CANNOT SPLIT THE ROW ON A TAB STOP (OTHERWISE THE PAD CODES
/	AFTER ARE NOT HANDLED PROPERLY)
/
	JMS	LOADC		NO: GET CHARACTER UNDER THE CURSOR
	SNA			ARE WE AT THE END OF THE ROW?
	JMP	0F		YES: SO NO PROBLEM WITH TAB CODE
	TAD	=-TAB		TABULATION CODE?
	SNA CLA			SKIP IF NOT
	JMP	IGNORE		TAB CODE: DISALLOW ROW BREAK HERE
/
0H	DCA	SPLIT		CLEAR THIS FOR 'ENDROW' CALL
	ROOM	4
	JMS	ENDROW		ARE WE ON THE LAST ROW HERE?
	NOP			<1> YES: (ALL SET HERE)
	ROOM	4
	JMS	ROWCK		<2> ARE WE AT THE END OF A ROW?
	JMP	1F		<1> YES: SO DROP TO NEXT ROW NOW
/
/	IN MIDDLE OF ROW: SPLIT ROW AT CURSOR POSITION.
/
	JMS	COPYROW		COPY ENTIRE ROW OUT TO SAVE BUFFER
	JMSI	EXTER		ENSURE CURSOR POSITIONED PROPERLY
	JMS	TRUNCLN		TRUNCATE ROW AT COLUMN POSITION
	TAD	COL		COMPUTE SPLIT POSITION
	TAD	=SAVBUF		...
	DCA	SPLIT		AND SET SPLIT ADDRESS
	DCAI	SPLIT		MARK THE SPLIT POINT FOR THE ROW
	JMS	DO2ND		DROP DOWN AND OUTPUT 2ND HALF OF ROW
	JMP	CNEXTL		DROP DOWN NOW TO THAT SECOND ROW
/
/	HERE TO DROP TO NEXT ROW. IF ASSEMBLER/COMPILER HEURISTICS
/	IN EFFECT, WE WANT TO START THE ROW WITH A TAB RIGHT
/
1H	JMS	DOWNC		DROP CURSOR DOWN TO NEXT ROW
/
/	COME HERE FROM INSERT LINE AND INSERT BLOCK TO SEE IF WE SHOULD
/	START OFF IN COLUMN 0 (NORMAL CASE) OR AT COLUMN 8 (HEURISTICS
/	MODE ENABLED). ALSO COME HERE ON INITIAL ENTRY.
/
ASMCHK	DCA	COL		SET NOW FOR COLUMN ZERO
	TAD	ASEMH		GET HEURISTICS FLAG
	SNA CLA			HEURISTICS ENABLED?
	JMPI	PSETX		NO: SO START IN COLUMN 0
	JMP	TABR		YES: START WITH TAB RIGHT
	TITLE 	COMMAND MODE DISPATCH POINT
/
/	HERE WHEN WE HAVE THE RETURN CODE STRUCK WHEN WE ARE IN COMMAND
/	MODE. ASSUME THAT WE HAVE A COMMAND ON THE TOP LINE.
/
CMEXEC	JMS	TRUNCLN		TRUNCATE ROW AT CURSOR COLUMN
	DCA	COL		SET COLUMN BACK TO 0 (HOME POSITION)
	JMS	LOADC		LOAD FIRST CHARACTER ON THE LINE
	JMS	FOLD		FOLD OVER POSSIBLE LOWER CASE
	DCA	TEMP		SAVE CHARACTER OF COMMAND
	TAD	=CTABLE-2	SET POINTER TO COMMAND TABLE
	DCA	TXR1		...
/
/	LOOP HERE LOOKING FOR A MATCH ON AN ENTRY IN THE COMMAND TABLE.
/	IN THE COMMAND TABLE, THE FIRST WORD IS THE MINUS ASCII CODE
/	OF THE COMMAND LETTER, AND THE SECOND WORD IS THE ADDRESS OF
/	THE ROUTINE THAT HANDLES THAT COMMAND.
/
1H	INC	TXR1		STEP OVER ADDRESS OF LAST ENTRY
	TADI	TXR1		GET NEXT MINUS COMMAND LETTER
	SNA			ARE WE AT THE SENTINEL ON THE TABLE?
	JMP	IGNORE		YES: BEEP TO SHOW COMMAND IGNORED
	TAD	TEMP		NO: COMPARE WITH COMMAND LETTER
	SZA CLA			SKIP IF WE HAVE A MATCH
	JMP	1B		NO MATCH: KEEP LOOKING
/
	TADI	TXR1		GET ADDRESS OF ROUTINE
	DCA	TEMP		STORE AND THEN
	JMPI	TEMP		TRANSFER CONTROL THERE,
	TITLE	XEDIT - EXIT FROM EDIT MODE
/
/	HERE TO TRUNCATE THE FILE AT THE CURRENT SCREEN.
/	(EVEN IF IN COMMAND MODE, 'BOF' CONDITION WILL CLEAR
/	ON SCROLL, SO IT'S HARDLY WORTH CHECKING HERE)
/
TRUNCF	INC	BOF		MARK AT BOTTOM OF FILE
	JMS	ROWSTAT		GET STATUS OF CURRENT ROW (SETS POINTER)
	LDI	04000		ROW ABOVE IS THE LAST ROW IN THE NEW FILE
	DCAI	TEMP		(WE MARKED CURRENT ROW AS UNESTABLISHED)
/
/	HERE TO EXIT FROM EDIT MODE AND CLOSE OUT THE FILE
/
XEDIT	JMS	NOCOM		CAN'T CLOSE FILE IN COMMAND MODE
	TAD	=CLMSG		CLEAR SCREEN AND OUTPUT CLOSE
	JMS	STROUT		MESSAGE SO CLOSE IS OBVIOUS
	JMS	DUMPSCR		DUMP OUT SCREEN TO ABOVE SCREEN BUFFER
/
/	HERE FOR THE SLOW, BUT OPTIMALLY PACKED CLOSE
/
1H	TAD	BOF		GET BOTTOM OF FILE FLAG
	SZA CLA			AT END OF FILE?
	JMP	2F		YES: SO ALL DONE HERE
/
SLASHP	JMP	FASTCL		## NOP ## IF /P OR 7400 OVERWRITTEN
	JMS	GETBE		NO: GET CHAR FROM BELOW SCREEN BUFFER
	JMS	PUTAB		COPY TO ABOVE SCREEN BUFFER
	JMP	1B		LOOP BACK NOW TO CHECK FOR EOF
/
/	HERE WHEN THE ENTIRE INPUT FILE HAS BEEN COPIED TO THE OUTPUT
/	FILE
/
2H	TAD	=EOF		APPEND EOF CODE TO END OF INPUT FILE
	JMS	PUTAB		...
	JMS	WAB		WRITE OUT FINAL BLOCK IN ABOVE SCREEN BUFFER
	JMPX	ICLOSE		FINISH OUT NOW WITH CLOSE FUNCTION
	TITLE	TOP-OF-FILE / BOTTOM-OF-FILE
/
/	HERE TO MOVE TO THE TOP (I.E. START) OF THE INPUT FILE.
/
/	LOOP BACK HERE
/
1H	JMS	BLINO		MOVE BOTTOM LINE OUT
/
/	ACTUAL ENTRY POINT JUST BELOW
/
TOFC	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
	TADI	ROWTAB		ADDRESS OF FIRST ROW IN TABLE
	DCA	TEMP		SAVE POINTER TO LENGTH/STATUS WORD
	TADI	TEMP		LOAD LENGTH/STATUS WORD
	SMA CLA			IS THE TOP ROW UNESTABLISHED?
	JMP	1B		NO: SO MORE ROWS TO DUMP
/
/	MOVE CHARACTERS NOW DIRECTLY FROM ABOVE SCREEN BUFFER TO BELOW
/	SCREEN BUFFER (MUCH FASTER THAN SCROLLING THEM THROUGH).
/
2H	TAD	TOF		GET TOP-OF-FILE FLAG
	SZA CLA			HAVE WE REACHED THE START YET?
	JMP	3F		YES: SO DONE HERE
/
	JMS	GETAB		NO: GET CHAR FROM ABOVE SCREEN BUFFER
	JMS	PUTBE		MOVE TO BELOW SCREEN BUFFER
	JMP	2B		LOOP BACK NOW TO CHECK FOR FILE START
/
/	CAUTION HERE. NOTE THAT WE MUST ADJUST THE COUNT OF
/	MARKED ROWS--THEY ARE ALL IN THE BELOW SCREEN BUFFER NOW
/
3H	TAD	ABMARK		GET COUNT OF ABOVE SCREEN MARKED ROWS
	TAD	BEMARK		ADD TO BELOW SCREEN COUNT
	DCA	BEMARK		...
	DCA	ABMARK		THEN ZERO THE ABOVE SCREEN COUNT
	JMS	GETBE		FLUSH THE 0 SENTINEL CODE WE JUST STORED
	SZA			ASSUMING IT WAS ZERO, OF COURSE
	JMS	PUTBE		IT WASN'T! (AT TOF WHEN INVOKED)
	JMP	SCRFIL		HERE AT END: FILL UP SCREEN FROM ABOVE SCREEN
/
/	MOVE TO BOTTOM (I.E. END) OF FILE.
/
BOFC	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
	JMS	DUMPSCR		FLUSH OUT SCREEN TO ABOVE SCREEN BUFFER
	TAD	BEMARK		ALL BELOW SCREEN MARKED ROWS ARE NOW
	TAD	ABMARK		IN THE ABOVE SCREEN BUFFER
	DCA	ABMARK		...
	DCA	BEMARK		AND NONE ARE IN THE BELOW SCREEN BUFFER
/
1H	TAD	BOF		GET BOTTOM-OF-FILE FLAG
	SZA CLA			ARE WE AT THE END OF THE FILE?
	JMP	PAGEDN		YES: MERGE WITH PAGE DOWN TO RESTORE SCREEN
/
	JMS	GETBE		NO: GET CHAR FROM BELOW SCREEN BUFFER
	SZA			BINARY ZERO MEANS AT END OF FILE
	JMS	PUTAB		MOVE TO ABOVE SCREEN BUFFER
	JMP	1B		LOOP BACK NOW TO CHECK FOR BOTTOM OF FILE
	EJECT
/
/	SUBROUTINE TO DUMP OUT THE SCREEN MEMORY TO THE ABOVE SCREEN BUFFER
/
DUMPSCR	.SUB	15
	LDI	04000		TURN OFF ALL SCREEN I/O
	DCA	SCROFF		...
/
/	LOOP HERE MOVING THE ROWS OUT ONE BY ONE
/
1H	TADI	ROWTAB		ADDRESS OF FIRST ROW
	DCA	TEMP		SAVE POINTER TO LENGTH/STATUS WORD
	TADI	TEMP		LOAD LENGTH/STATUS WORD
	SPA CLA			IS THE TOP ROW ESTABLISHED?
	.RET	DUMPSCR		NO: SO RETURN NOW
	JMS	TLINO		YES: SO MOVE OUT THE TOP ROW
	TAD	ROWTAB		REMOVE TOP LINE NOW
	JMS	RMVLN		...
	JMP	1B		YES: BACK TO DO IT
	TITLE	SCRLUP/SCRLDN - UPWARDS/DOWNWARDS SCROLL
/
/	HERE FOR THE SCROLL UP FUNCTION. THIS ROUTINE LEAVES THE CURSOR
/	AT THE SAME PHYSICAL SPOT ON THE SCREEN BUT MOVES ALL ROWS ON
/	THE SCREEN UP BY ONE POSITION.
/
/	LOOP BACK HERE WAITING FOR KEYBOARD ABORT
/
SCRLUP	JMS	UPSCRL		CALL SUBROUTINE TO PERFORM FUNCTION
/
/	IF CURSOR IS NOT ON TOP ROW, MOVE IT UP ONE ROW. THAT WAY THE
/	CURSOR WILL FLOAT WITH THE ROW UP TO THE TOP OF THE SCREEN
/	AS WE SCROLL UP.
/
	TAD	ROW		GET CURRENT ROW
	CMA IAC			COMPARE WITH THE
	TAD	ROWTAB		TOP ROW ON THE SCREEN
	SZA CLA			SKIP IF WE ARE ON THE TOP ROW
	LDI	-1		ELSE MOVE CURSOR UP BY ONE ROW
	TAD	ROW		...
	DCA	ROW		...
/
	JMS	KCK		CHECK ON KEYBOARD BUFFER
	TADI	=KBUF		EXAMINE FIRST WORD IN KEYBOARD BUFFER
	SNA 			ANYTHING IN THE KEYBOARD BUFFER?
	TAD	BOF		NO: ARE WE AT BOTTOM OF FILE?
	SZA CLA			...
	JMP	SCRDUN		BOTTOM OF FILE.OR.KEYBOARD ACTIVE
	JMP	SCRLUP		LOOP BACK NOW
/
/	SUBROUTINE TO PERFORM THE ACTUAL SCROLL UP FUNCTION. THIS INVOLVES
/	ROLLING OUT THE TOP ROW TO THE ABOVE SCREEN BUFFER, PERFORMING
/	A DELETE ROW FUNCTION FOLLOWED BY ROLLING IN A NEW ROW AT THE
/	BOTTOM OF THE SCREEN.
/
/	FOR CONVENIENCE, WE WILL ALLOW THE SCREEN TO SCROLL UP UNTIL
/	THE LAST EXISTING ROW IS ON THE TOP ROW ON THE SCREEN.
/
UPSCRL	.SUB	25
	JMS	NOCOM		DISALLOW SCROLLING IN COMMAND MODE
	DCA	INSF		REMOVE INSERT CHARACTER
	TAD	ROWTAB		COPY FIRST ROW TO INDEX
	DCA	TXR1		...
	TADI	TXR1		GET ROW ADDRESS FOR ROW 2
	DCA	TEMP		SAVE POINTER TO LENGTH/STATUS WORD
	TADI	TEMP		LOAD LENGTH/STATUS WORD
	SPA CLA			DOES THIS ROW EXIST?
	.RET	UPSCRL		NO: SO NOTHING TO DO HERE
/
/ TO HANDLE INSERT BLOCK CASE, DO NOT MOVE TOP ROW OUT IF
/ LAST ROW ON THE SCREEN IS MARKED AS UNESTABLISHED AND WE ARE
/ NOT AT BOTTOM OF FILE (THOSE CONDITIONS INDICATE WE MUST HAVE
/ HAD A BLOCK INSERT).
/
	TADI	LASTROW		SET POINTER TO LENGTH/STATUS
	DCA	TEMP		...
	TAD	BOF		GET BOTTOM OF FILE FLAG
	SNA CLA			ARE WE AT THE BOTTOM OF FILE?
	TADI	TEMP		NO: SO GET THE LENGTH/STATUS WORD
	SPA CLA			IS THE LAST ROW ESTABLISHED?
	JMP	1F		NO: SO DON'T MOVE OUT THE TOP ROW THEN
/
	JMS	TLINO		YES: MOVE THE TOP ROW OUT
	TAD	ROWTAB		GET ADDRESS OF TOP ROW IN ROW TABLE
	JMS	RMVLN		REMOVE TOP ROW FROM MEMORY
/
1H	JMS	BLINI		MOVE IN NEW ROW AT BOTTOM NOW
	.RET	UPSCRL		DONE HERE
	EJECT
/
/	HERE FOR SCROLL DOWN FUNCTION. THIS ROUTINE LEAVES THE CURSOR
/	AT THE SAME PHYSICAL SPOT ON THE SCREEN BUT MOVES ALL ROWS ON
/	THE SCREEN DOWN BY ONE POSITION.
/
SCRLDN	JMS	KCK		CHECK ON KEYBOARD BUFFER
	TADI	=KBUF		EXAMINE FIRST WORD IN KEYBOARD BUFFER
	SZA CLA			IS KEYBOARD BUFFER ACTIVE?
	JMP	SCRDUN		YES: ALL DONE WITH SCROLL NOW
	JMS	DNSCRL		CALL SUBROUTINE TO PERFORM FUNCTION
/
/	IF CURSOR IS NOT ON THE BOTTOM ROW, MOVE THE CURSOR DOWN ONE
/	ROW SO THAT IT WILL FLOAT AS THE SCREEN MOVES.
/
	TAD	ROW		GET CURRENT ROW
	CMA IAC			COMPARE WITH THE
	TAD	LASTROW		BOTTOM ROW ON THE SCREEN
	SZA CLA			SKIP IF WE ARE ON THE BOTTOM ROW
	INC	ROW		NOT ON BOTTOM ROW: MOVE DOWN ONE ROW
	JMP	SCRLDN		LOOP BACK NOW
/
/	COME HERE AT END. MUST RESET CURSOR POSITION
/
SCRDUN	JMS	INROW		YES: ENSURE CURSOR LOCATED WITHIN NEW ROW
	JMP	ESTCK		ENSURE THAT CURRENT ROW IS ESTABLISHED
/
/ SUBROUTINE TO PERFORM THE ACTUAL SCROLL DOWN FUNCTION. THIS
/ INVOLVES ROLLING THE BOTTOM ROW TO THE BELOW SCREEN BUFFER,
/ PERFORMING AN INSERT ROW FUNCTION ON THE TOP ROW FOLLOWED
/ BY ROLLING IN A NEW ROW AT THE TOP OF THE SCREEN.
/
/ NOTE THAT WE TAKE A GLOBAL ABORT TOP OF FILE. THIS AVOIDS POSSIBLE
/ LOCKUP PROBLEM ON WORD LEFT AND OTHER ROUTINES.
/
DNSCRL	.SUB	14
	JMS	NOCOM		NO SCROLLING IN COMMAND MODE
	TAD	TOF		AT TOP OF FILE?
	SZA CLA			SKIP IF NOT
	JMP	HOME		YES: TAKE GLOBAL ABORT OUT OF HERE
	TAD	ROWTAB		GET ADDRESS OF FIRST ROW IN TABLE
	JMS	INSROW		INSERT ON TOP ROW
	JMS	TLINI		ROLL IN ROW AT TOP OF SCREEN
	.RET	DNSCRL		ALL DONE HERE
	TITLE	PAGE UP/PAGE DOWN
/
/	HERE FOR PAGE DOWN
/
PAGEDN	TAD	=DNSCRL-UPSCRL	SET FOR DOWNWARDS SCROLLING
PAGEUP	TAD	=UPSCRL		SET FOR UPWARDS SCROLLING
	DCA	PSUB		SET SUBROUTINE ADDRESS
/
	LDI	04000		TURN OFF SCREEN I/O
	DCA	SCROFF		...
	TAD	ROWSIZ		GET COUNT OF NUMBER OF ROWS
	CMA IAC			NEGATE AND SET
	DCA	ROWCTR		AS LOOP COUNTER
/
/	LOOP HERE SCROLLING UP/DOWN NUMBER OF ROWS ON SCREEN
/
2H	JMSI	PSUB		SCROLL UP/DOWN
	ISZ	ROWCTR		MORE ROWS TO SCROLL?
	JMP	2B		YES: SO DO THEM
	JMP	DOSCRN		NO: SCREEN I/O BACK ON, AND RESTORE SCREEN
/
	PART
	TITLE	BLINI - MOVE BOTTOM LINE ONTO SCREEN
/
/	HERE TO MOVE IN A NEW LINE FROM BELOW SCREEN BUFFER INTO
/	THE BOTTOM LINE ON THE SCREEN.
/	GOING FORWARDS IS NICE, BECAUSE WE CAN EXPAND THE TAB
/	STOPS ON THE FLY AS WE GO ALONG. NOTE THAT WE COPY
/	THE ROW INTO SAVE BUFFER RATHER THAN DIRECTLY INTO
/	THE SCREEN AREA. WHY? BECAUSE IT GETS TOO COMPLICATED
/	HANDLING ALL THE NASTY ROW OVERFLOW PROBLEMS IF WE DON'T.
/
BLINI	SUB
	TAD	BOF		GET BOTTOM-OF-FILE FLAG
	SZA CLA			ARE WE AT THE BOTTOM OF THE FILE?
	RET	BLINI		YES: SO WE CANNOT MOVE IN A NEW LINE
/
	TAD	ROWTAB		SET TOP ROW AS ROW POINTER
	DCA	ROWPTR		...
/
/	LOOP HERE TO FIND THE FIRST NON-EXISTENT ROW ON SCREEN. CALLING
/	ROUTINE SHOULD ENSURE THAT AT LEAST THE LAST ROW HAS BEEN SET
/	AS UNESTABLISHED.
/
1H	JMS	ROWPST		GET STATUS OF THIS ROW
	SPA CLA			SKIP IF WE HAVE AN ENTRY HERE
	JMP	2F		NO ENTRY: WE HAVE FOUND THE ROW WE WANT
/
	INC	ROWPTR		ENTRY: STEP TO NEXT ROW TABLE ENTRY
	JMP	1B		BACK TO CHECK IT
/
2H	DCAI	TEMP		CLEAR 'UNESTABLISHED-ROW' FLAG
	TAD	ROWPTR		ROW TO POSITION ON
	JMS	POSROW		ENSURE CURSOR POSITIONED PROPERLY
	JMS	RESCOL		RESTORE ROW AND COLUMN
	TAD	=SAVBUF-1	PUT CHARACTERS INTO SAVE BUFFER
	DCA	PXR		...
	TAD	=GETBE		SET SUBROUTINE ADDRESS FOR 'RFILE'
	DCA	SUBR2		...
	TAD	=RFILE		WHERE TO READ CHARACTERS FROM
	JMS	TABEX		READ AND EXPAND TAB STOPS
	TAD	BEMARK		IF -1 FLAG, WE READ A MARKED ROW
	DCA	BEMARK		...
	EJECT
/
/	MUST NOW FLUSH OUT LF IF WE STOPPED ON CR
/
	TAD	RCHAR		GET TERMINATING CHARACTER
	TAD	=-CR		WAS IT A CARRIAGE RETURN?
	SNA CLA			SKIP IF NOT
	JMS	GETBE		YES, SO FLUSH OUT LINE FEED
	CLA			...
/
/	IF THIS LINE CONSISTED OF NOTHING MORE THAN A CONTROL/Z, WE WANT
/	TO IGNORE THE ENTIRE LINE HERE
/
	TAD	BOF		GET BOTTOM-OF-FILE FLAG
	SZA CLA			ARE WE AT THE BOTTOM OF THE FILE?
	TAD	PXR		YES: SO GET BUFFER POINTER
	TAD	=-SAVBUF	COMPARE WITH START OF BUFFER
	SNA CLA			ARE WE AT BOTTOM OF FILE, WITH A NULL LINE?
	JMP	6F		YES: SO EXIT NOW (WE DON'T REALLY HAVE A
/
	DCA	COL		(COLUMN STILL SAVED IN COLSV2 BY TABEX)
	ROOM	4
	JMS	SIZE		DOES THIS ROW FIT?
	JMP	3F		<1> YES: AND IN 1 ROW
	EJECT
/
/	<2> HERE WE HAVE 2 ROWS. MUST RETURN THE SECOND ROW BACK TO
/	WHENCE IT CAME.
/
	TAD	PXR		ADDRESS OF SENTINEL ON SAVE BUFFER
	DCA	GXR		COPY FOR 'GETBKWD' ROUTINE
	TAD	=GETBKWD	WHERE TO GET CHARACTERS FROM
	DCA	SUBRC		...
	TAD	RCHAR		WAS THIS ROW TRUNCATED PREMATURELY?
	SNA CLA			SKIP IF NOT
	JMP	5F		IT WAS: SO NO CR/LF TO PUT BACK
/
	TAD	=LF		PUT CR/LF IN NOW (BACKWARDS THOUGH)
	JMS	PUTBE		INTO BELOW SCREEN BUFFER
	TAD	=CR		...
	JMS	PUTBE		...
/
5H	TAD	=PUTBE		PUT THE 2ND PART OF THE ROW BAC
	JMS	ROWBAK		...
	CLL			FORCE NO-CRLF FLAG UNLESS / W ENABLED
	TADI	ROWPTR		GET ROW ADDRESS TO BE MARKED
	JMS	NOCRLF		MARK THAT ROW NOW
/
3H	JMS	COPYSV		COPY FIRST ROW BACK TO SCREEN NOW
	TAD	COLSV2		RESTORE ORIGINAL COLUMN POSITION
	DCA	COL		...
	RET	BLINI		ALL DONE HERE
/
/ HERE WHEN THE LINE WE READ WAS JUST A CONTROL/Z.
/ MUST MARK THIS ROW AS UNESTABLISHED FOR THE EXIT.
/
6H	JMS	ROWPST		GET STATUS OF ROW (JUST TO SET 'TEMP')
	LDI	04000		MARK ROW NOW AS UNESTABLISHED
	DCAI	TEMP		...
	RET	BLINI		ALL DONE HERE
/
/ SUBROUTINE TO POSITION CURSOR ONTO ROW SPECIFIED IN THE
/ AC ON ENTRY TO THIS ROUTINE.
/ THIS ROUTINE ALWAYS POSITIONS AT COLUMN 0 TOO.
/
/ NOTE:	ON EXIT FROM THIS ROUTINE, ROW HAS BEEN SAVED IN 'TXTROW' AND
/ 	COL HAS BEEN SAVED IN 'TXTCOL'. TO RESTORE ROW AND COL, 'RESCOL'
/ 	ROUTINE SHOULD BE CALLED AFTER POSROW CALL.
/
POSROW	.SUB	12
	DCA	TEMP		SAVE ROW POSITION
	TAD	ROW		SAVE CURRENT ROW
	DCA	TXTROW		...
	TAD	TEMP		SET ARGUMENT ROW AS CURRENT ROW
	DCA	ROW		...
	TAD	COL		SAVE CURRENT COLUMN POSITION
	DCA	TXTCOL		...
	DCA	COL		ALWAYS SET FOR COLUMN 0
	JMSI	EXTER		POSITION CURSOR NOW
	.RET	POSROW		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO PUT CHARACTERS BACK INTO A BUFFER. AC
/	HAS ADDRESS OF ROUTINE TO CALL TO PUT CHARACTERS,
/	SUBRC HAS ADDRESS OF ROUTINE TO CALL FOR CHARACTERS.
/	ONLY ACTION HERE IS TO STRIP OUT PAD CODES.
/
ROWBAK	.SUB	15
	DCA	SUBR2		SAVE ADDRESS OF PUT CHAR ROUTINE
/
/	LOOP HERE MOVING CHARACTERS OVER
/
1H	JMSI	SUBRC		GET NEXT CHARACTER
	SNA			IF ZERO, WE ARE DONE HERE
	.RET	ROWBAK		AT END OF ROW
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SNA			SKIP IF NOT
	JMP	1B		YES: STRIP PAD CODES
	RTL			RESTORE ORIGINAL CODE
	JMSI	SUBR2		OUTPUT CHARACTER
	JMP	1B		ALL DONE HERE
/
/	SUBROUTINE TO GET A CHARACTER IN THE BACKWARDS DIRECTION
/	FROM THE SAVE BUFFER (TYPICALLY)
/
GETBKWD	.SUB	8
	LDI	-2		DECREMENT POINTER
	TAD	GXR		(TWICE SINCE INDEXING CELL)
	DCA	GXR		...
	TADI	GXR		GET NEXT CHARACTER
	.RET	GETBKWD		AND RETURN IT IN THE AC
/
/	HERE TO PUT A CHARACTER VIA 'PXR' POINTER
/
PUTBKWD	.SUB	8
	DCAI	PXR		STORE THE CHARACTER
	LDI	-2		NOW DECREMENT THE POINTER
	TAD	PXR		(TWICE SINCE INDEXING CELL)
	DCA	PXR		...
	.RET	PUTBKWD		ALL DONE HERE
/
/	HERE TO GET A CHARACTER VIA 'GXR' POINTER
/
GETXR	.SUB	3
	TADI	GXR		GET NEXT CHARACTER
	.RET	GETXR		ALL DONE HERE
/
/	HERE TO PUT A CHARACTER VIA 'PXR' POINTER
/
PUTXR	.SUB	3
	DCAI	PXR		STORE CHARACTER
	.RET	PUTXR		ALL DONE HERE
	TITLE	TLINI - MOVE TOP LINE ONTO SCREEN
/
/	SUBROUTINE TO MOVE IN A NEW LINE AT THE TOP OF THE SCREEN FROM
/	THE ABOVE SCREEN BUFFER. HERE WE ARE GOING BACKWARDS
/	AND THE LINE MUST BE ROLLED IN BACKWARDS
/
/	THIS ROUTINE IS GREATLY COMPLICATED BY THE DIFFICULTIES
/	OF TABS (WE CAN'T EXPAND A TAB UNTIL WE KNOW WHERE THE
/	LINE STARTS) AND ALSO IF A ROW EXCEEDS THE COLUMN WIDTH.
/	(IF WE SCROLL IN A LINE TOO LONG FOR THE SCREEN, WE WANT
/	TO SPLIT IT INTO TWO ROWS (FOR THE DISPLAY) AT THE
/	SAME POINT WHERE WE WOULD SPLIT IT IF WE WERE SCROLLING
/	IT UP FROM THE BOTTOM OF THE SCREEN. THE ONLY WAY TO
/	HANDLE THIS IS TO READ THE ENTIRE ROW BACKWARDS INTO
/	THE SAVE BUFFER, THEN RE-READ IT EXPANDING THE TAB
/	CODES, AND THEN DO THE STANDARD CHECKS FOR EXCEEDING THE
/	ROW WIDTH.
/
/	NOTE:	THIS ROUTINE MUST NOT BE CALLED IF 'TOF' FLAG IS SET
/
TLINI	SUB
	TAD	ROWTAB		ROW TO FILL IN IS THE TOP ROW
	DCA	ROWPTR		...
/
/	TEST TO SEE IF PRIOR ROW ENDED WITH CR/LF.
/	(MIGHT HAVE SCROLLED OFF FIRST PART OF LONG, LOGICAL ROW)
/
	JMS	GETAB		GET CHAR FROM ABOVE SCREEN BUFFER
	TAD	=-LF		LINE FEED HERE?
	SZA			SKIP IF SO
	JMP	1F		NO, PRIOR LINE DID NOT END WITH CR/LF
/
	JMS	GETAB		STRIP 'CR' WHICH MUST PRECEDE TOO
	CLA			...
	JMP	2F		CONTINUE NOW
/
1H	TAD	=LF		RESTORE CHARACTER WE READ
	JMS	PUTAB		...
	CLL			FLAG LINE ONLY IF /W NOT SET
	TADI	ROWTAB		GET ADDRESS OF LENGTH/STATUS WORD
	JMS	NOCRLF		FLAG CURRENT LINE: NO CR/LF AT END
/
2H	TAD	=SAVBUF+LMASK-2	SET POINTER AT END OF SAVE BUFFER
	DCA	PXR		...
	TAD	=GETAB		WHERE TO GET CHARACTERS FROM
	DCA	SUBR2		...(IN 'RFILE')
/
/	COME BACK HERE TO SET THE MARKED ROW FOUND FLAG
/
3H	TAD	ABMARK		UPDATE COUNT OF MARKED ROWS
	DCA	ABMARK		...
/
/	LOOP HERE READING CHARACTERS FROM THE FILE
/
4H	JMS	RFILE		READ CHAR FROM FILE
	SPA			SKIP IF NOT MARKED ROW
	JMP	3B		BACK TO UPDATE COUNT
	SNA			ARE WE AT START OF FILE?
	JMP	5F		YES: SO ALL DONE HERE
	JMS	PUTBKWD		NO: PUT BACKWARDS INTO SAVE BUFFER
	JMP	4B		BACK FOR NEXT CHARACTER NOW
/
/	HERE AT END OF THIS ROW
/
5H	TAD	RCHAR		GET FINAL CHARACTER OF ROW
	SNA CLA			HOW DID THIS ROW END?
	JMP	6F		AT TOP-OF-FILE/TRUNCATED: NOTHING TO DO
/
/	NORMAL ROW ENDING. MUST RESTORE CR/LF NOW
/
	TAD	=CR		PUT ROW ENDING BACK FOR ROW PRIOR
	JMS	PUTAB		...TO THE ROW WE JUST READ
	TAD	=LF		...
	JMS	PUTAB		...
/
/	NOW RECOPY THE ROW IN THE FORWARDS DIRECTION TO 'SAVBUF' AND
/	EXPAND TABS AS WE GO ALONG.
/
6H	TAD	PXR		GET BACKWARDS SENTINEL
	IAC			+1 TO POINT AT FIRST CHARACTER
	DCA	GXR		...
	TAD	=SAVBUF-1	POINT AT START OF SAVE BUFFER
	DCA	PXR		...
	TAD	=GETXR		SUBROUTINE TO GET CHARS FROM
	JMS	TABEX		EXPAND TABS NOW
/
/	NOW CHECK FOR A ROW > ROW WIDTH.
/
	DCA	COL		(TABEX SAVED 'COL' VALUE SO SAFE TO 0)
	ROOM	4
	JMS	SIZE		TEST SIZE OF THIS ROW
	JMP	7F		<1> OK, JUST ONE ROW HERE
/
/	HERE WE HAVE 2 ROWS. MUST STUFF THE FIRST ROW BACK INTO THE
/	ABOVE SCREEN BUFFER AND USE THE SECOND ROW.
/
	TAD	=SAVBUF-1	<2> SET POINTER TO SAVE BUFFER
	DCA	GXR		...
	TAD	=GETXR		SET SUBROUTINE TO GET CHARS FROM
	DCA	SUBRC		...
	TAD	=PUTAB		WHERE TO PUT CHARS BACK
	JMS	ROWBAK		MOVE ROW BACK INTO BUFFER
	TAD	SPLIT		GET POINT OF ROW SPLIT
/
/	HERE TO OUTPUT A SINGLE ROW, OR IF THERE WERE TWO ROWS,
/	THE SECOND ROW
/
7H	JMS	COPYSV		COPY FIRST/SECOND PART OF ROW
	TAD	COLSV2		RESTORE COLUMN SAVED BY 'TABEX'
	DCA	COL		...
	RET	TLINI		ALL DONE HERE
	TITLE	BLINO - MOVE BOTTOM SCREEN LINE OUT TO BUFFER
/
/	HERE TO MOVE OUT THE BOTTOM LINE TO BELOW SCREEN BUFFER
/	LINE MUST BE DUMPED IN REVERSE ORDER FROM END TO BEGINNING
/
BLINO	.SUB	30
	TAD	LASTROW		SET ROW ADDRESS OF LINE TO MOVE OUT
/
/	IF THIS ROW DOES NOT EXIST, BACKTRACK TO FIND ONE THAT DOES EXIST
/
1H	DCA	ROWPTR		...
	JMS	ROWPST		GET LENGTH/STATUS WORD FOR THIS ROW
	SMA CLA			HAS THIS ROW BEEN ESTABLISHED?
	JMP	2F		YES: SO DONE HERE
/
	LDI	-1		NO: SO DECREMENT ROW TABLE POINTER
	TAD	ROWPTR		...
	JMP	1B		...
/
2H	JMS	ROWOUT		MOVE CURRENT ROW TO SAVE BUFFER
/
/	ROWOUT RETURNS 1 IN AC IF THE LINE MOVED OUT WAS A MARKED LINE
/
	TAD	BEMARK		UPDATE COUNT OF BELOW SCREEN MARKED LINES
	DCA	BEMARK		...
	LDI	04000		MARK ROW AS UNESTABLISHED NOW
	DCAI	TEMP		...(TEMP SET BY ROWOUT)
/
/ LOOP HERE MOVING CHARACTERS INTO THE BELOW SCREEN BUFFER.
/ ('ROWXR' SET BY ROWOUT AND POINTS AT SENTINEL ON THE ROW)
/
3H	LDI	-2		DECREMENT POINTER
	TAD	ROWXR		...
	DCA	ROWXR		...
	TADI	ROWXR		NEXT CHARACTER
	SNA			PRESENTINEL ON SAVE BUFFER?
	.RET	BLINO		YES: ALL DONE HERE
	JMS	PUTBE		NO: SO STORE INTO BUFFER
	JMP	3B		LOOP BACK FOR NEXT NOW
	TITLE	TLINO - MOVE TOP SCREEN LINE OUT
/
/	SUBROUTINE TO MOVE OUT LINE AT THE TOP OF THE SCREEN TO
/	THE ABOVE SCREEN BUFFER.
/	ALSO, WE HANDLE THE ABOVE SCREEN BUFFER MARKED ROW COUNT
/
TLINO	.SUB	20
	TAD	ROWTAB		ROW TO OUTPUT IS THE TOP ROW
	DCA	ROWPTR		...
	JMS	ROWOUT		MOVE ROW TO SAVE BUFFER
	TAD	ABMARK		UPDATE COUNT OF ABOVE SCREEN BUFFER MARKED
	DCA	ABMARK		LINES (IF NECESSARY)
/
/	NOW DUMP OUT THE SAVE BUFFER TO THE ABOVE SCREEN BUFFER
/
	TAD	=SAVBUF-1	SET POINTER TO THE SAVE BUFFER
	DCA	ROWXR		...
/
/	LOOP HERE GETTING CHARACTERS FROM SAVE BUFFER AND PUTTING INTO
/	ABOVE SCREEN BUFFER.
/
2H	TADI	ROWXR		NEXT CHARACTER FROM SAVE BUFFER
	SNA			TEST FOR SENTINEL ON BUFFER
	.RET	TLINO		ALL DONE ON SENTINEL
	JMS	PUTAB		PUT INTO ABOVE SCREEN BUFFER
	JMP	2B		LOOP BACK IF MORE TO DO
	EJECT
	TITLE	RFILE - READ CHARS FROM FILE
/
/	THIS ROUTINE WILL READ CHARACTERS FROM THE INPUT
/	FILE SPECIFIED IN 'SUBR2'. A SINGLE CHARACTER
/	IS READ AND PROCESSED AND THEN RETURNED IN THE AC.
/	THIS ROUTINE RETURNS:
/
/	A REGULAR CHARACTER	
/	-1		MARKED ROW FOUND
/	0		END OF ROW FOUND
/
/	'ROWPTR' MUST POINT AT STATUS FOR ROW WE ARE WORKING ON. ALTHOUGH
/	THE ROW IS NOT FILLED BY THIS ROUTINE, IT DOES NEED TO BE ABLE
/	TO POINT AT THE LENGTH/STATUS WORD FOR THIS ROW.
/
/	ROUTINE ALSO RETURNS FINAL CHARACTER IN 'RCHAR'
/
RFILE	SUB
	DCA	RCHAR		CLEAR THIS IN CASE END OF ROW
	ISZ	RFCTR		CHECK FOR A ROW THAT IS TOO LONG
	TAD	RFCTR		GET COUNTER
	SMA CLA			SKIP IF WE STILL HAVE ROOM HERE
	JMP	5F		ROW IS TOO LONG HERE
/
/	COME BACK HERE IF IGNORING A CHARACTER
/
1H	JMSI	SUBR2		GET NEXT CHARACTER
	DCA	RCHAR		SAVE NEW CHARACTER
	TAD	RCHAR		REGET THE CHARACTER
	TAD	=-' 		ASCII CODE OF LESS THAN 240?
	SMA CLA			SKIP IF SO
	JMP	4F		NO: SO SPEEDILY SKIP ALL THE TESTS FOR < 240
/
/	CHECK OUT ASCII CODE < 240 NOW
/
	TAD	RCHAR		REGET CHARACTER
	TAD	FFLAG		COMPARE WITH FORM FEED FLAG
	SNA CLA			IS THIS A FORM FEED, AND ARE WE STRIPPING THEM?
	JMP	1B		YES: REMOVE FORM FEED
/
	TAD	RCHAR		NO: SO REGET THE CHARACTER
	SNA			IF ZERO, BUFFER WE ARE READING FROM IS EMPTY
	JMP	5F		SO TREAT AS END OF LINE
	TAD	=-LF		NO, TEST FOR LINE FEED (SHOULD NOT FIND)
	SZA			SKIP IF SO
	TAD	=LF-NULL	ASCII NULL CODE?
	SNA			SKIP IF NOT
	JMP	1B		STRIP ASCII NULL AND LINE FEED CODES
	TAD	=NULL-CR	CARRIAGE RETURN?
	SNA			SKIP IF NOT
	JMP	5F		ALL DONE ON CR
	TAD	=CR-TAB		TABULATION CODE HERE
	SZA			SKIP IF SO
	JMP	*+4		NO: SO SKIP AHEAD
/
	TAD	RFCTR		ADJUST COUNTER UPWARDS FOR NORMAL
	TAD	=8		...WORST CASE LENGTH OF TAB CODE
	DCA	RFCTR		...(NOT PERFECT BUT ADEQUATE HERE)
/
	TAD	=TAB-EFLAG	EDIT/DELETION FLAG?
	SZA			SKIP IF SO
	JMP	2F		NO: CONTINUE
/
/	HERE ON EDIT/DELETION FLAG, JUST SET STATUS ON CURRENT LINE
/
	JMS	ROWPST		GET LENGTH/STATUS FOR CURRENT ROW
	AND	=0400.XO.-1	CLEAR 'MODIFIED-ROW' FLAG IN CASE SET
	TAD	MODF		SET FLAG BIT NOW (UNLESS STRIPPING FLAGS)
	DCAI	TEMP		STORE IT BACK
	JMP	1B		LOOP BACK FOR NEXT CHARACTER
/
2H	TAD	=EFLAG-MFLAG	CHECK FOR MARKED ROW FLAG
	SZA CLA			SKIP IF MARKED ROW FLAG
	JMP	4F		ELSE CONTINUE HERE
/
	JMS	ROWPST		GET LENGTH/STATUS FOR CURRENT ROW
	TAD	=01000		...
	DCAI	TEMP		...
/
	LDI	-1		SET FLAG: WE JUST MOVED IN A MARKED ROW
	RET	RFILE		RETURN -1 AS FLAG IN AC NOW
/
4H	TAD	RCHAR		REGET CHARACTER NOW
	RET	RFILE		ALL DONE HERE
/
/	HERE AT END OF ROW
/
5H	TAD	RFMAX		RESET ROW COUNTER
	DCA	RFCTR		FOR NEXT TIME
	RET	RFILE		RETURN 0 IN AC TO SHOW END OF ROW
	TITLE	ROWOUT - OUTPUT ROW TO OUTPUT BUFFER
/
/	SUBROUTINE TO MOVE THE ROW SPECIFIED IN 'ROWPTR' ON ENTRY
/	INTO THE SAVE BUFFER. THIS ROUTINE ALSO HANDLES THE AUDIT TRAIL
/	FEATURE. IF A LINE IS MARKED AS HAVING BEEN MODIFIED. WE STORE THE
/	CURRENT VERSION NUMBER AT COLUMN 'AUCOL' INTO THE BUFFER.
/
/	RETURNS A VALUE OF 1 IN AC IF A MARKED LINE WAS MOVED OUT
/	ON EXIT 'TEMP' POINTS AT THE STATUS WORD FOR THE ROW
/
ROWOUT	SUB
	TAD	=SAVBUF-1	SET POINTER TO THE SAVE BUFFER
	DCA	ROWXR		...
	JMS	ROWPST		GET LENGTH/STATUS FOR CURRENT ROW
	AND	=LMASK		ISOLATE THE COUNT FIELD
	CMA			TAKE 1'S COMPLEMENT (IN CASE 0)
	DCA	RCNTR		SET LOOP COUNTER FOR LENGTH OF LINE
	TAD	TEMP		REGET POINTER (SET BY 'ROWPST')
	DCA	TXR2		...
	DCA	TEMP2		THIS KEEPS TRACK OF ORIGINAL COLUMN ON SCREEN
	DCA	FXR		SET TO 0 AS A FLAG
/
/ CHECK TO SEE IF CURRENT ROW IS MARKED. NOTE THAT IF THE 'M'
/ COMMAND IS IN EFFECT, THE INSTRUCTION AT 'MARKALL' IS CHANGED TO
/ A 'SKP CLA' WHICH WILL CAUSE ALL ROWS TO BE MARKED.
/
	TADI	TEMP		GET THE STATUS WORD AGAIN
	CLL RTL			SHIFT MARK BIT TO AC0
MARKALL	SMA CLA			WAS THIS ROW MARKED? (SKP CLA)
	JMP	0F		NO: SO CONTINUE
/
/	HERE ON MARKED ROW: OUTPUT 'MFLAG' CODE AS A FLAG
/
	TAD	=MFLAG		GET FLAG CODE
	DCAI	ROWXR		OUTPUT AT START OF ROW
	LDI	1		NOW SET TO TURN FLAG ON
0H	DCA	FLAG		...
/
/ CHECK FOR EDIT/DELETION FLAG ON CURRENT ROW
/
	TADI	TEMP		GET LENGTH/STATUS WORD FOR THIS ROW
	AND	MODF		ISOLATE THE 'MODIFIED-ROW' FLAG IF /M SET
	SNA CLA			HAS THIS ROW BEEN MODIFIED?
	JMP	2F		NO: CONTINUE
/
	TAD	=EFLAG		YES: OUTPUT EDIT FLAG AS 1ST CHAR
	JMP	3F		JUMP INTO LOOP BELOW IN CASE NULL ROW
/
/	LOOP HERE GETTING CHARACTERS FROM CURRENT ROW.
/
1H	INC	TEMP2		COUNT PHYSICAL POSITION ON SCREEN
	TAD	AUCOL		GET AUDIT TRAIL COLUMN
	CMA			NEGATE AND SUBTRACT FROM CURRENT COLUMN
	TAD	TEMP2		...
	SZA CLA			HAVE WE REACHED THE AUDIT TRAIL COLUMN?
	JMP	7F		NO: SO CONTINUE
/
/	HERE WE ARE AT THE AUDIT TRAIL COLUMN. REMEMBER POSITION IN
/	BUFFER FOR LATER USE
/
	TAD	ROWXR		REMEMBER POSITION
	DCA	FXR		...
7H	TADI	TXR2		NEXT CHARACTER FROM ROW
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SNA			SKIP IF NOT A PAD CODE
	JMP	2F		PAD CODE: IGNORE IT
	RTL			RESTORE ORIGINAL CODE
3H	DCAI	ROWXR		PLACE IN SAVE BUFFER
/
2H	ISZ	RCNTR
	JMP	1B		LOOP BACK FOR NEXT CHARACTER
/
/	HERE WE HAVE FOUND THE END OF THE ROW
/	CHECK NOW TO SEE IF WE HAVE TO HANDLE THE AUDIT TRAIL FEATURE.
/
	TADI	TEMP		GET THE ROW STATUS AGAIN
	AND	AUDIT		ISOLATE 'ROW-MODIFIED' BIT IF /A ALSO SET
	SNA CLA			SKIP IF AUDIT TRAIL IN EFFECT HERE
	JMP	4F		NOT IN EFFECT: HANDLE END OF ROW NOW
/
/	HERE WE MUST HANDLE THE AUDIT TRAIL FEATURE.
/	FIRST JOB IS TO SEE IF WE ARE AT, OR PAST THE AUDIT TRAIL COLUMN.
/	IF NOT, WE MUST PROVIDE TAB STOPS TILL WE GET OUT THERE.
/
/	LOOP HERE TABBING OUT UNTIL WE ARE AT OR PAST THE AUDIT TRAIL COLUMN
/
1H	TAD	TEMP2		GET CURRENT COLUMN
	CMA IAC			SUBTRACT FROM
	TAD	AUCOL		AUDIT TRAIL COLUMN
	SPA SNA CLA		SKIP IF NOT THERE YET
	JMP	2F		OK: WE ARE THERE
/
	TAD	=TAB		NO: SO STORE A TAB CODE
	DCAI	ROWXR		...
	TAD	ROWXR		REMEMBER POSITION IN THE SAVE BUFFER
	DCA	FXR		FOR LATER USE.
	TAD	TEMP2		UPDATE SCREEN COLUMN
	AND	=7.XO.-1	TRUNCATE BACK TO PRIOR TAB STOP
	TAD	=8		MOVE TO NEXT TAB STOP
	DCA	TEMP2		...
	JMP	1B		AND TRY AGAIN
/
/	NOW WE ARE AT THE CORRECT COLUMN: INSERT THE VERSION NUMBER
/	WE WILL WANT TO FORCE THE VERSION NUMBER INTO THE AUDIT TRAIL COLUMN.
/	(OTHERWISE EVERY TIME WE EDIT WE WILL GET STRINGS OF PRIOR VERSION)
/	(NUMBERS THAT WILL BECOME MORE CONFUSING THAN HELPFUL)
/
2H	TAD	FXR		GET POSITION OF AUDIT COLUMN
	SZA			(IF NEVER SET, 'ROWXR' IS OK!)
	DCA	ROWXR		...IN THE SAVE BUFFER
	TAD	=AVERS-1	SET POINTER TO VERSION NUMBER
	DCA	FXR		...
/
/	LOOP HERE GETTING CHARACTERS FROM THE VERSION NUMBER
/
3H	TADI	FXR		GET NEXT CHARACTER FROM VERSION NUMBER
	SNA			SENTINEL ON VERSION NUMBER?
	JMP	4F		YES: SO CONTINUE NOW
	DCAI	ROWXR		NO: STORE THE CHARACTER
	JMP	3B		BACK FOR NEXT CHARACTER NOW
/
/	HERE AT END OF ROW. TEST TO SEE WHETHER CR/LF ARE NEEDED OR NOT
/
4H	TADI	TEMP		GET THE STATUS BYTE AGAIN
	CLL RAL			SHIFT CR/LF BIT TO AC0
	SPA CLA			SKIP IF CR/LF INHIBIT NOT SET FOR THIS R
	JMP	5F		INHIBIT IS SET
/
	TAD	=CR		NOT SET: PLACE CR/LF
	DCAI	ROWXR		...
	TAD	=LF-' 		AND LINE FEED
5H	TAD	=' 		OR JUST A BLANK IF NO CR/LF
	DCAI	ROWXR		...
	DCAI	ROWXR		SENTINEL NOW ON THE ROW
	TAD	FLAG		GET FLAG SETTING
	RET	ROWOUT		RETURN THAT IN THE AC
	TITLE	COMMAND MODE CIRCUIT
/
/	COME HERE TO PROCESS THE COMMAND CHARACTER. IF IN COMMAND
/	MODE JUST RESTORE THE COMMAND ROW. OTHERWISE, ENTER
/	COMMAND MODE.
/
NEWCMD	TAD	CMND		GET COMMAND MODE FLAG
	SZA CLA			ARE WE IN COMMAND MODE?
	JMP	RESTOR		YES: OFF TO RESTORE TOP ROW NOW
/
/	HERE WE ARE ENTERING COMMAND MODE. WE WANT TO SET UP A STATUS
/	ROW WHICH HAS THE FOLLOWING FORMAT:
/
/			VISTA.PA-00.02    NN EXTRA BLOCKS   <CCC>
/
	TAD	IFMLEN		GET INPUT FILE MINUS BLOCK LENGTH
	TAD	IFVBLK		ADD INPUT FILE VIRTUAL BLOCK COUNT
	CMA IAC			MAKE IT A POSITIVE NUMBER
	TAD	BLOCKCT		ADD TO BLOCK COUNT
	CMA IAC			MAKE IT A NEGATIVE COUNT
	DCA	TEMP		SAVE NEGATIVE OF BLOCKS NEEDED
/
	TAD	TFFVBLK		GET OUTPUT FILE FORWARD VIRTUAL BLOCK
	CMA IAC			SUBTRACT FROM
	TAD	TFBVBLK		OUTPUT FILE BACKWARDS VIRTUAL BLOCK
	TAD	TEMP		SUBTRACT OUT PREVIOUSLY ACCUMULATED COUNT
/
	JMSX	BINASC		CONVERT TO TWO ASCII DIGITS
	DCAI	=BLOCKS		...
	TAD	TEMP		GET EITHER TWO BLANKS, OR PLUS AND A BLANK
	DCAI	=BLOCKS+1	...
/
/	DO OCTAL ASCII CODE OF CHAR UNDER CURSOR (MAY BE GRAPHIC CHARACTER)
/
	JMS	LOADC		GET CHARACTER UNDER CURSOR
	JMSX	DOASCI		CONVERT ASCII CODE TO 'ASCHR'
/
/	NOW COPY THE TOP ROW IN MEMORY INTO THE SAVE BUFFER WHICH
/	WILL NOT BE USED WHILE WE ENTER INFORMATION ON THE TOP ROW
/
	TAD	ROW		CALL 'POSROW' TO SAVE ROW/ COL
	JMS	POSROW		...(AND SET COL TO 0)
	TAD	ROWTAB		MARK CURRENT ROW IS NOW TOP ROW
	DCA	ROW		...
	JMS	COPYROW		COPY ROW OUT TO SAVE BUFFER
/
/	NOW SEND OUR CANNED MESSAGE OUT TO THE SCREEN.
/
	JMSI	EXTER		HOME THE CURSOR (COL=0, ROW=TOP)
	JMS	TRUNCLN		TRUNCATE TOP ROW
	TAD	=HEADER		SET POINTER TO STATUS ROW
	JMS	STROUT		OUTPUT THAT MESSAGE
	INC	CMND		MARK THAT WE ARE IN COMMAND MODE
	DCA	INSF		ENSURE INSERT MODE IS OFF
	JMP	HOME		HOME CURSOR: WE ARE DONE NOW
	TITLE	EXIT COMMAND MODE
/
/	HERE TO RETURN FROM COMMAND MODE BACK INTO STANDARD TEXT MODE
/
RESTOR	JMS	EXCOM		EXIT FROM COMMAND MODE
	JMP	IDLP		ALL DONE HERE
/
/	SUBROUTINE TO EXIT FROM COMMAND MODE AND RESTORE THE TOP ROW
/	ON THE SCREEN.
/
EXCOM	.SUB	15
	DCA	CMND		CLEAR COMMAND MODE FLAG
	DCA	COL		MOVE TO HOME POSITION
	TAD	ROWTAB		SET ROW POINTER FOR 'COPYSV'
	DCA	ROWPTR		...
	JMSI	EXTER		RE-POSITION CURSOR NOW
	JMS	COPYSV		COPY SAVE BUFFER BACK
	JMS	RESCOL		RESTORE ROW/COL FROM TXTROW/TXTCOL
	JMSI	EXTER		POSITION SCREEN CURSOR
	.RET	EXCOM		ALL DONE HERE
/
/ SUBROUTINE TO RESTORE ROW/COL FROM TXTROW/TXTCOL
/
RESCOL	.SUB	6
	TAD	TXTCOL		RESTORE TEXT COLUMN
	DCA	COL		...
	TAD	TXTROW		RESTORE TEXT ROW
	DCA	ROW		...
	.RET	RESCOL		ALL DONE HERE
	TITLE	READ SEARCH/REPLACE STRINGS
/
/	HERE TO READ THE SEARCH STRING FOR THE 'S' AND 'W' COMMANDS
/
W:CMND	LDI	1		SET FLAG: WORD SEARCH BEING PERFORMED
S:CMND	DCA	WORD		CLEAR FLAG AT S:CMND.
	TAD	=SSTRING-1	SET POINTER TO STRING STORAGE
	JMS	SAVSTR		READ STRING INTO THAT AREA
	JMS	EXCOM		EXIT FROM COMMAND MODE
	JMP	SEARCH2		OFF NOW TO SEARCH FOR STRING
/
/	HERE TO READ THE STRING FOR THE REPLACEMENT COMMAND.
/
R:CMND	TAD	=RSTRING-1	SET POINTER TO REPLACEMENT STRING STORAGE
	JMS	SAVSTR		READ THE STRING
	JMP	RESTOR		JUST EXIT FROM COMMAND MODE NOW
/
/	SUBROUTINE TO SAVE A STRING FOR SEARCH OR REPLACE ABOVE. ON ENTRY
/	AC HAS ADDRESS-1 OF WHERE TO PUT THE STRING.
/
SAVSTR	.SUB	20
	DCA	ROWXR		SAVE POINTER TO WHERE STRING WILL GO
	JMS	GLEN		GET LENGTH OF CURRENT ROW
	CMA IAC			NEGATE AND SET AS LOOP COUNTER
	DCA	RCNTR		...
	JMP	2F		JUMP INTO LOOP BELOW (FIRST CHAR WAS COMMAND)
/
/	LOOP HERE READING CHARACTERS FROM THE STRING
/
1H	INC	CHARP		STEP POINTER (CHARP STILL SET FROM CMEXEC)
	TADI	CHARP		GET THE NEXT CHARACTER
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SNA			SKIP IF NOT PAD CODE
	JMP	2F		STRIP PAD CODE
	RTL			RESTORE CHARACTER
	DCAI	ROWXR		STORE INTO STRING BUFFER
/
2H	ISZ	RCNTR		MORE CHARACTERS ON THE ROW?
	JMP	1B		YES, SO BACK TO GET THEM
	DCAI	ROWXR		NO: SET SENTINEL ON STRING BUFFER
	.RET	SAVSTR		ALL DONE HERE
	TITLE	REPLACEMENT FUNCTION
/
/	COME HERE TO HANDLE THE REPLACEMENT FUNCTION(S). THERE ARE
/	TWO FUNCTIONS HERE: SINGLE STEP AND CONTINUOUS. IN SINGLE
/	STEP MODE, WE PERFORM A SINGLE REPLACEMENT, AND THEN DO
/	A SEARCH AND STOP. IN THE CONTINUOUS MODE, WE JUST BLANK
/	THE SCREEN AND GO TO THE END OF THE FILE.
/
RSTEP	LDI	-1		FOR STEP MODE, JUST DO 1 REPLACEMENT
RCONT	DCA	REPCTR		SET FOR CONTINUOUS MODE (SET COUNTER=0)
/
/	COMPARE STRING AT CURSOR POSITION AGAIN WITH SEARCH STRING
/	TO BE SURE THE CURSOR WAS NOT UNEXPECTEDLY MOVED ON US (THIS
/	IS NOT ALLOWED).
/
/	COME HERE IN CONTINUOUS MODE, AFTER WE HAVE FOUND A MATCH
/
REPING	TAD	=SSTRING	SET SEARCH STRING POINTER
	DCA	ROWPTR		...
	TAD	COL		SAVE CURRENT COLUMN POSITION
	DCA	COLSAVE		...
/
/	FIND END OF SEARCH STRING. AS WE GO ALONG, CHANGE CHARS IN THE
/	ROW TO PAD CODES SO THEY CAN BE DELETED LATER.
/
1H	JMS	LOADC		GET CHARACTER UNDER CURSOR
	JMS	FOLD		COMPARE IN UPPER CASE ALPHAS ONLY
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SNA			SKIP IF NOT
	JMP	5F		IGNORE PAD CODES
	RTL			ELSE RESTORE CHARACTER
	DCA	TEMP		SAVE FOR A MOMENT
	TADI	ROWPTR		GET CURRENT CHAR FROM SEARCH STRING
	JMS	FOLD		FOLD THAT TOO
	CMA IAC			AND COMPARE
	TAD	TEMP		WITH OTHER CHARACTER
	SZA CLA			SKIP IF WE HAVE A MATCH
	JMP	IGNORE		SOMETHING WRONG: RING BELL
/
	LDI	PAD		OVERWRITE CHAR NOW WITH PAD
	DCAI	CHARP		...(WHICH EFFECTIVELY DELETES THE CHARACTER)
	INC	ROWPTR		STEP POINTER INTO SEARCH STRING
5H	INC	COL		STEP COLUMN NUMBER
	TADI	ROWPTR		GET NEXT CHAR FROM SEARCH STRING
	SZA CLA			IS NEXT CHARACTER STRING SENTINEL?
	JMP	1B		NO: SO LOOP BACK NOW
	EJECT
/
	TAD	COLSAVE		RESTORE PRIOR COLUMN POSITION NOW
	DCA	COL		...
	JMS	REDOLN		REDO THE ROW TO REMOVE OLD STRING
	LDI	04000		YES: DROP INTO INSERT CHARACTER MODE
	DCA	INSF		...
	TAD	SCROFF		FORCE 'SCROFF' OFF BUT SAVE STATUS (IN BIT 1)
	STL RAR			BIT 0 FORCED ON, OLD BIT 0 SAVED IN BIT
	DCA	SCROFF		(WE WILL RESET THE WHOLE ROW)
	TAD	=RSTRING-1	SET POINTER TO REPLACEMENT STRING
	DCA	FXR		...
	DCA	SPLITSV		THIS SETS NON-0 IF THE ROW HAS TO SPLIT
/
/	LOOP HERE COPYING THE REPLACEMENT STRING IN INSERT CHARACTER
/	MODE. ADVANTAGE OF USING THE DISPLAY CHARACTER ROUTINE IS
/	THAT IT HANDLES MANY 'GRISLY' PROBLEMS (SUCH AS THE REPLACEMENT
/	STRING IS SO LONG THAT THE ROW NOW OVERFLOWS THE COLUMN WIDTH
/	ETC.).
/	NOTE THAT THE SCREEN IS BLANKED WHILE WE CALLED DISPLAY CHARACTER
/	(THIS AVOIDS VISUALLY UPDATING THE ROW ON EACH CHARACTER
/	INSERTION). THE REASON FOR SETTING/SAVING 'SCROFF' IS THAT IT IS VERY
/	NICE TO DO ALL THE CHANGES ON THE SCREEN VISIBLY.
/
2H	TADI	FXR		NEXT CHAR FROM REPLACEMENT STRING
	SNA			IS THIS THE SENTINEL?
	JMP	3F		YES: SO DONE HERE
	JMS	DISCHR		NO: CALL DISPLAY CHARACTER ROUTINE
	JMP	2B		AND LOOP BACK FOR NEXT CHARACTER
/
/	HERE AT END OF REPLACEMENT STRING
/
3H	DCA	INSF		CLEAR INSERT CHARACTER MODE NOW
	TAD	SCROFF		RESTORE PRIOR SETTING OF 'SCROFF' FLAG
	CLL RAL			...
	DCA	SCROFF		(BIT 0 WAS SAVED IN BIT 1)
	JMS	FLAGLN		MARK ROW AS MODIFIED
	TAD	COL		GET COLUMN AT END OF STRING
	DCA	TXTCOL		SAVE FOR A MOMENT
	TAD	COLSAVE		COLUMN BACK TO WHERE STRING STARTS
	DCA	COL		...
	TAD	SPLITSV		DID WE HAVE AN OVERSET ROW?
	SZA CLA			SKIP IF NOT
	JMP	1F		YES: SO WE MUST RESTORE ENTIRE SCREEN!
	JMSI	EXTER		ENSURE CURSOR POSITIONED
	JMS	REDOLN		REDO ROW WITH CHANGES NOW
	JMP	2F		CONTINUE NOW
/
1H	JMS	RESCRN		RESTORE THE ENTIRE SCREEN
2H	TAD	TXTCOL		RESTORE OLD COLUMN NOW
	DCA	COL		...(START SEARCH AFTER REPLACED STRING)
	JMP	0F		JUMP INTO SEARCH ROUTINE NOW
	TITLE	SEARCH FUNCTION
/
/	HERE FOR THE SEARCH COMMAND TO SEARCH FROM CURRENT CURSOR
/	POSITION TO END OF FILE. NOTE THAT ON SEARCH KEY WE START SEARCH
/	ONE COLUMN OVER TO THE RIGHT (OTHERWISE WE WOULD KEEP FINDING THE
/	SAME STRING OVER AND OVER AGAIN). HOWEVER, ON INITIAL ENTRY, WE
/	DO NOT MOVE THE CURSOR (WOULD NOT FIND A STRING IN THE EXTREME
/	HOME POSITION IF WE MOVED IT BY ONE).
/
SEARCH	JMS	RIGHTC		START SEARCH 1 CHAR POSITION OVER
SEARCH2	LDI	-1		ENSURE 'SRCHROW' EXITS ON MATCH
	DCA	REPCTR		...
/
/	COME BACK HERE TO SEARCH THE NEXT ROW
/
0H	JMS	NOCOM		ENSURE WE ARE NOT IN COMMAND MODE HERE
1H	JMS	SRCHROW		SEARCH ROW, RETURN IF NO MATCH
/
	TAD	ROW		COMPARE CURRENT ROW ADDRESS
	CMA IAC			...
	TAD	LASTROW		WITH LAST ROW ADDRESS
	SNA CLA			ARE WE ON THE LAST ROW?
	JMP	2F		YES: HANDLE THIS NOW
/
	INC	ROW		STEP ROW POINTER
	JMS	ROWSTAT		GET STATUS OF THIS ROW
	SMA CLA			DOES THIS ROW EXIST?
	JMP	3F		YES: OFF TO CHECK KEYBOARD NOW
/
	JMS	UPC		NO: MOVE THE CURSOR BACK TO PRIOR LINE
	JMP	4F		WE ARE DONE HERE
/
/	HERE WHEN WE HAVE REACHED THE BOTTOM ROW. TURN OFF SCREEN I/O
/	TO SPEED UP SEARCH. WHEN WE FIND A MATCH, WE WILL RESTORE
/	THE SCREEN.
/
2H	TAD	BOF		ARE WE AT BOTTOM OF FILE?
	SZA CLA			SKIP IF NOT
	JMP	4F		YES: DONE HERE
/
	LDI	04000		NO: TURN SCREEN I/O OFF NOW
	DCA	SCROFF		...
	JMS	UPSCRL		SCROLL UP ONE ROW
/
3H	JMS	KCK		CHECK ON KEYBOARD BUFFER
	TADI	=KBUF		EXAMINE FIRST WORD IN KEYBOARD BUFFER
	SNA CLA			SKIP IF KEYBOARD BUFFER IS NOT EMPTY
	JMP	1B		EMPTY: SO LOOP BACK NOW TO CHECK THIS ROW OUT
/
/	COME HERE FROM OTHER PLACES TO RESTORE THE SCREEN IF SCREEN I/O
/	WAS TURNED OFF. OTHERWISE JUST RE-POSITION THE CURSOR

SCRCK	TAD	SCROFF		GET SCREEN I/O FLAG
	SZA CLA			HAD WE TURNED OFF SCREEN I/O?
	JMS	RESCRN		YES: RESTORE SCREEN FIRST
	JMP	SETX		ALL DONE HERE
/
/	HERE AT COMPLETE END OF FILE. IF WE WERE IN CONTINUOUS REPLACEMENT
/	MODE IT IS TIME TO RESTORE THE SCREEN.
/
4H	ISZ	REPCTR		WERE WE IN CONTINUOUS MODE?
	JMP	5F		YES: CONTINUE NOW
	JMS	RESCRN		NO: RESTORE THE ENTIRE SCREEN
	JMP	IGNORE		AND BEEP NOW ON NO MATCH
/
/	HERE IN CONTINUOUS REPLACEMENT MODE: INDICATE NUMBER OF MATCHES
/
5H	TAD	REPCTR		...
	JMSX	BINASC		IF 0-99, GET COUNT, OTHERWISE GET 99+
	DCAI	=REPCOUNT	...
	TAD	TEMP		GET REMAINING COUNT
	DCAI	=REPCOUNT+1	AND STORE THAT
	DCA	SCROFF		TURN SCREEN I/O BACK ON
	TAD	=REPMSG		OUTPUT MESSAGE TO SCREEN NOW
	JMP	STRIDL		ALL DONE HERE
	TITLE	SRCHROW - ROW SEARCH ROUTINE
/
/	COME HERE TO SEARCH THE CURRENT ROW. THIS ROUTINE DOES   N O T
/	RETURN IF WE HAVE A MATCH. IT RETURNS ONLY IF THERE IS NO MATCH
/	SEARCH STARTS AT COLUMN IN 'COL'
/
	DCA	COL		ZERO COLUMN FOR EXIT
SRCHROW	SUB
	JMS	GLEN		GET CURRENT ROW LENGTH
	IAC			+1 TO ACCOUNT FOR LENGTH/STATUS
	TADI	ROW		ADD IN STARTING ADDRESS OF ROW
	DCA	TEMP		NOW POINTS 1 CHAR PAST LAST CHAR OF ROW
	DCAI	TEMP		INSTALL ZERO SENTINEL (FACILITATES SEARCH)
	LDI	-1		ADJUST FOR 'INC' ON ROWXR
	TAD	COL		GET CURRENT COLUMN
	INC	COL		STEP FOR NEXT TIME (AVOID SEARCH/REPLACE PBLM)
	TADI	ROW		...
	DCA	ROWXR		SET STARTING POINT FOR THE SEARCH
/
	LDI	-1		TEST FOR BEING IN COLUMN 0 AT START
	TAD	COL		... OF SEARCH
	SNA CLA			ARE WE STARTING SEARCH IN COLUMN 0?
/
/	ALSO LOOP BACK HERE IF 'ROWXR' POSITIONED ON A PAD CODE
/
0H	LDI	-1		YES: SO WE HAVE A WORD DELIMITER BY DEFAULT
/
/	COME BACK HERE AFTER UNSUCCESSFUL MATCH. THE POINTER IS MOVED
/	ONLY ONE CHARACTER AT A TIME. THIS AVOIDS COMMON ERROR IN
/	STRING SEARCHES (I.E. ABAC WILL NOT MATCH ON ZZZABABACZZZ
/	BECAUSE AFTER FAIL OF 'C' WITH SECOND 'B', WE HAVE ALREADY
/	PASSED THE POINT WHERE THE MATCH WOULD HAVE SUCCEEDED. DEC'S
/	OS/8 EDITOR HAS HAD THIS SILLY ERROR FOR LONGER THAN I CARE TO THINK
/
MOVE1	DCA	FLAG		SET/CLEAR WORD DELIMITER NEEDED FLAG
	INC	ROWXR		STEP ROW POINTER BY ONE POSITION
	TAD	ROWXR		COPY NOW TO ANOTHER REGISTER
	DCA	TXR1		FOR ACTUALLY DOING COMPARISON
	TADI	TXR1		GET FIRST CHARACTER
	SNA			AT SENTINEL ON ROW?
	JMP	SRCHROW-2	YES: RETURN ON NO MATCH
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SNA CLA			SKIP IF NOT
	JMP	0B		YES: SO ADVANCE POINTER AND TRY AGAIN
	TAD	ROWXR		COPY NOW TO ANOTHER REGISTER
	DCA	TXR1		FOR ACTUALLY DOING COMPARISON
	TAD	=SSTRING-1	SET POINTER TO THE SEARCH STRING
	DCA	TXR2		...
/
	ISZ	FLAG		DO WE NEED TO DO A WORD DELIMITER CHECK?
	TAD	WORD		YES: SO GET THE WORD DELIMITER FLAG
	SNA CLA			DO WE NEED TO CHECK FOR A WORD DELIMITER?
	JMP	2F		NO: SO CONTINUE NOW
/
/	HERE WE MUST FIND A WORD DELIMITER BEFORE CHECKING FOR A MATCH
/
	TAD	TXR1		COPY INDEXING POINTER
	DCA	TEMP		...
	TADI	TEMP		LOAD CHARACTER PRIOR TO MATCH POINT
	JMS	WORDCK		CHECK FOR WORD DELIMITER
	SZL CLA			SKIP IF WE FOUND ONE
	JMP	MOVE1		ALPHA OR DIGIT: LOOP BACK
	EJECT
/
/	COMPARE CHARACTERS NOW FROM ROW AND FROM SEARCH STRING
/
2H	TADI	TXR2		NEXT CHARACTER FROM SEARCH STRING
	SNA			SENTINEL ON ROW?
	JMP	4F		YES: WE MAY/MAY NOT HAVE A MATCH THEN
	JMS	FOLD		FOLD CHARACTER TO UPPER CASE ALPHA
	CMA IAC			NEGATE AND
	DCA	TEMP		THEN SAVE FOR A MOMENT
/
3H	TADI	TXR1		GET CORRESPONDING CHARACTER FROM ROW
	SNA			TEST FOR SENTINEL ON ROW
	JMP	SRCHROW-2	ALL DONE ON SENTINEL HERE
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SNA			SKIP IF NOT
	JMP	3B		SKIP PAD CODES
	RTL			ELSE RESTORE CHARACTER
	JMS	FOLD		FOLD LOWER CASE ALPHA TO UPPER CASE
	TAD	TEMP		COMPARE WITH CHARACTER FROM ROW
	SZA CLA			DO WE HAVE A MATCH HERE?
	JMP	MOVE1		NO: SO MOVE ONE POSITION ALONG IN THE ROW
	JMP	2B		YES: SO KEEP COMPARING THEN
/
/	HERE WE HAVE A MATCH. DO FINAL CHECK FOR A WORD SEARCH
/
4H	TAD	WORD		GET WORD DELIMITER FLAG
	SNA CLA			DO WE NEED A WORD DELIMITER HERE?
	JMP	5F		NO: SO WE HAVE A PERFECT MATCH NOW
/
	TADI	TXR1		YES: GET NEXT CHARACTER FROM ROW
	JMS	WORDCK		CHECK FOR WORD DELIMITER (SENTINEL WILL WORK)
	SZL CLA			IS THIS A WORD DELIMITER?
	JMP	MOVE1		NO: SO EVEN THOUGH WE MATCH, WE MUST FAIL
/
/	HERE ON A PERFECT MATCH- SET COLUMN POSITION OF MATCH.
/
5H	TADI	ROW		GET STARTING ADDRESS OF ROW
	CMA IAC			SUBTRACT FROM
	TAD	ROWXR		POSITION OF FIRST CHARACTER OF MATCH
	DCA	COL		SET COLUMN POSITION
/
	ISZ	REPCTR		IN CONTINUOUS REPLACEMENT MODE HERE?
	JMP	REPING		YES: SO KEEP GOING
/
/	HERE AT END. IF THE SCREEN WAS BLANKED, THE MATCHING ROW
/	IS ON THE LAST ROW WHICH IS AWKWARD. THEREFORE WE SCROLL UP
/	TO THE MIDDLE OF THE SCREEN WHICH GIVES US THE CONTEXT WE WANT
/
	TAD	SCROFF		GET SCREEN I/O FLAG
	SNA CLA			HAD WE TURNED OFF SCREEN I/O?
	JMPI	PSETX		NO: POSITION CURSOR DIRECTLY: WE ARE DONE
/
	TAD	ROWSIZ		YES: GET NUMBER OF SCREEN ROWS
	STL CMA IAC RAR		NEGATE AND DIVIDE BY TWO
	DCA	ROWCTR		SET AS ROW COUNTER
	TAD	ROWCTR		COMPUTE NEW ROW ADDRESS
	TAD	ROW		...
	DCA	ROW		...
/
/	LOOP HERE SCROLLING UP UNTIL MATCHING ROW IS ON THE MIDDLE
/	OF THE SCREEN.
/
	JMS	UPSCRL		SCROLL UP ONE ROW
	ISZ	ROWCTR		AT MIDDLE OF SCREEN YET?
	JMP	*-2		NO, SO KEEP SCROLLING
	JMP	SCRCK		RESTORE SCREEN AND CURSOR POSITION
	EJECT
/
/	SUBROUTINE TO CHECK THE CHARACTER IN THE AC FOR BEING A WORD
/	DELIMITER. A WORD DELIMITER IS ANY CHARACTER OTHER THAN 
/	UPPER/LOWER CASE ALPHAS AND DIGITS.
/
/	ON EXIT:
/
/		LINK = 0	WORD DELIMITER
/		LINK = 1	ALPHA OR DIGIT
/
WORDCK	.SUB	18
	JMS	FOLD		IF LOWER CASE, MAKE IT UPPER CASE NOW
	TAD	=-'9-1		TEST FOR DIGIT
	CLL			...
	TAD	='9-'0+1	...
	SZL			SKIP IF NOT A DIGIT
	JMP	1F		DIGIT: SO DONE HERE
/
	TAD	='0-'Z-1	TEST FOR ALPHA
	CLL			...
	TAD	='Z-'A+1	...
1H	CLA			CLEAR AC
	.RET	WORDCK		LEAVE RESULT OF TEST IN LINK
/
/ SUBROUTINE TO LOAD CHARACTER UNDER CURSOR AND THEN CALL WORDCK
/ TO CHECK FOR A WORD. USED BY THE WORD CURSOR MOVEMENT AND DELETE
/ ROUTINES.
/
WDTEST	.SUB	6
	JMS	LOADC		LOAD CHARACTER UNDER CURSOR
	JMS	WORDCK		TEST FOR WORD DELIMITER
	.RET	WDTEST		RETURN NOW: ALL DONE
/
	TITLE	PUT CHARACTER INTO ABOVE SCREEN BUFFER
/
/	HERE TO PUT THE CHARACTER IN THE AC INTO THE ABOVE SCREEN
/	BUFFER. THIS BUFFER IS PACKED IN OS/8 FORMAT IN THE
/	FORWARD DIRECTION. WHEN IT FILLS IT IS WRITTEN IN THE FORWARD
/	DIRECTION TO THE START OF THE TEMPORARY FILE
/
/	ON ENTRY HERE:
/
/	ABSW 	ABPTR		FUNCTION
/	----	-----		--------
/	0	AT WORD		CHECK FOR FULL BUFFER, THEN STORE 1ST CHAR
/	1	AT WORD		STORE 2ND CHAR NEXT
/	2	PAST WORD	STORE 3RD CHAR NEXT (AS 2 NIBBLES)
/
PUTAB	.SUB	35
	DCA	PUTC		SAVE CHARACTER TO GO OUT
	DCA	TOF		CLEAR FLAG: NO LONGER AT TOP OF FILE
	INC	ABSW		ADVANCE ABOVE BUFFER SWITCH
	TAD	ABSW		GET SWITCH
	TAD	=PUTSW-1	INDEX DISPATCH TABLE
	CDF	%*		TABLE IN CURRENT FIELD
	JMP	IAC		JUMP INDIRECT THROUGH THAT ADDRESS
/
PUTSW	DC	1F,2F,3F	DISPATCH ON CHAR POSITION
/
/	HERE FOR THE FIRST CHARACTER POSITION
/
1H	TAD	ABPTR		GET ABOVE SCREEN BUFFER POINTER
	TAD	=-(ABUFE+1)	PAST END OF BUFFER?
	SNA CLA			SKIP IF NOT
	JMS	WAB		WRITE OUT ABOVE SCREEN BUFFER
/
/	HERE NOW FOR FIRST AND SECOND CHARACTER POSITIONS
/
2H	TADI	ABPTR		GET ABOVE SCREEN BUFFER POINTER
	AND	=07400		ALWAYS SAVE OLD NIBBLE THERE
	TAD	PUTC		INSERT NEW CHARACTER
	DCAI	ABPTR		STORE IT BACK
	INC	ABPTR		STEP BUFFER POINTER
	.RET	PUTAB		ALL DONE HERE
/
/	HERE FOR THE 3RD CHARACTER POSITION
/
3H	LDI	-2		BACKUP POINTER TO WORD WITH HIGH NIBBLE
	TAD	ABPTR		...
	JMS	PUTB		PUT THE BYTE
	DCA	ABSW		RESET DISPATCH SWITCH
	.RET	PUTAB		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO INSERT TWO NIBBLES INTO THE HIGH ORDER FOUR BITS
/	OF TWO 12-BIT WORDS WITHOUT DISTURBING THE LOW 8 BITS.
/
/	POINTER TO WORD IS IN AC. BYTE TO INSERT IS IN 'PUTC'
/	NOTE:	PUTC IS DESTROYED BY THIS ROUTINE
/
PUTB	.SUB	22
	DCA	TEMP		SAVE POINTER TO WHERE HIGH NIBBLE GOES
	LDI	-2		COUNTER FOR STORING TWO NIBBLES
	DCA	CNTR		...
/
/	LOOP BACK HERE TO STORE THE SECOND NIBBLE
/
1H	TAD	PUTC		GET CHARACTER TO INSERT
	RTL			SHIFT UP THE MIDDLE FOUR BITS TO HIGH END
	RTL			...
	DCA	PUTC		SAVE IT (FOR SUBSEQUENT CALL)
	TAD	PUTC		REGET THE NIBBLE
	AND	=07400		ISOLATE THE NIBBLE
	DCA	TEMP2		AND SAVE IT.
/
	TADI	TEMP		GET THE WORD WITH NIBBLE TO STRIP
	AND	=0377		REMOVE THE OLD NIBBLE
	TAD	TEMP2		INSERT THE NEW NIBBLE
	DCAI	TEMP		AND STORE IT BACK
	INC	TEMP		STEP POINTER TO THE NEXT WORD
	ISZ	CNTR		DID WE JUST STORE THE SECOND NIBBLE?
	JMP	1B		NO: SO BACK TO DO THAT NOW
	.RET	PUTB		YES: ALL DONE HERE
	TITLE	GET CHARACTER FROM ABOVE SCREEN BUFFER.
/
/	THIS ROUTINE GETS A CHARACTER FROM THE ABOVE SCREEN BUFFER.
/	CHARACTERS ARE REMOVED IN THE BACKWARDS DIRECTION. IF THE
/	BUFFER IS EMPTY, WE READ BLOCKS IN THE BACKWARDS DIRECTION
/	FROM THE BEGINNING PORTION OF THE TEMPORARY FILE.
/
/	CARE MUST BE TAKEN THAT THE PUTAB/GETAB ROUTINES ARE
/	COMPLETELY SYMMETRIC SO WE CAN ROCK BACK AND FORTH BETWEEN
/	THEM.
/
/	ABSW	ABPTR		FUNCTION
/	----	-----		--------
/	0	2 WORDS PAST	IF BUFFER EMPTY, READ, THEN GET 3RD CHAR
/	1	1 WORD PAST	GET FIRST CHAR
/	2	1 WORD PAST	GET SECOND CHAR
/
/	NOTE:	THIS ROUTINE SHOULD NOT BE CALLED IF 'TOF' (TOP-OF-FILE
/		FLAG IS SET)
/
GETAB	.SUB	50
	LDI	-1		DECREMENT SWITCH NUMBER
	TAD	ABSW		...
	DCA	ABSW		...
	SNL			SKIP IF FIRST/SECOND POSITION
	JMP	3F		ELSE HANDLE THIRD POSITION
/
/	HERE FOR FIRST AND SECOND CHARACTER POSITIONS.
/
	LDI	-1		ADJUST WORD POINTER CORRECTLY
	TAD	ABPTR		...
	DCA	ABPTR		...
	TADI	ABPTR		GET WORD WITH CHAR WE NEED
/
2H	AND	=0377		TRIM OFF GARBAGE AT HIGH END OF WORD
	.RET	GETAB		ALL DONE HERE
	EJECT	10
/
/	HERE FOR 3RD CHAR POSITION. CHECK FIRST THAT BUFFER IS NOT EMPTY.
/
3H	TAD	ABPTR		GET BUFFER POINTER
	TAD	=-ABUF		AT START OF BUFFER?
	SNA CLA			SKIP IF NOT
	JMS	RAB		YES: READ PRIOR BLOCK, RESET PTR AT END OF BUF
/
	LDI	2		FIRST: RESET THE SWITCH
	DCA	ABSW		...
	TAD	TOF		GET TOP OF FILE FLAG
	SZA CLA			ARE WE NOW AT TOP OF FILE?
	JMP	4F		YES, RETURN 0 CHAR THEN
/
	LDI	-2		NOW SET POINTER TO JUST BEFORE FIRST WORD
	TAD	ABPTR		...
	JMS	GETB		GET THAT BYTE NOW
	JMP	2B		LOOP BACK NOW WITH BYTE IN AC
/
/	HERE AT TOP OF FILE
/
4H	DCA	ABSW		RESET SWITCH BACK TO ZERO
	TAD	=ABUF		RESET BUFFER POINTER
	DCA	ABPTR		...
	.RET	GETAB		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO ASSEMBLE AN 8-BIT BYTE FROM TWO 4-BIT NIBBLES.
/	ON ENTRY TO THIS ROUTINE, AC SHOULD CONTAIN A POINTER TO
/	JUST BEFORE THE WORD CONTAINING THE HIGH ORDER NIBBLE.
/	BYTE IS NOT MASKED FOR EXIT.
/
GETB	.SUB	20
	DCA	TEMP		SAVE POINTER TO HIGH NIBBLE
	TADI	TEMP		GET THE HIGH NIBBLE
	AND	=07400		ISOLATE THE NIBBLE
	DCA	TEMP2		AND SAVE IT
	INC	TEMP		STEP POINTER
/
	TADI	TEMP		GET THE LOW NIBBLE
	AND	=07400		ISOLATE THE NIBBLE
	CLL RTR			START SHIFTING TO LOW END OF AC
	RTR			...
	TAD	TEMP2		MERGE IN THE HIGH NIBBLE NOW
	RTR			KEEP ON SHIFTING IT DOWN
	RTR			...
	.RET	GETB		RETURN NIBBLE IN AC.
	TITLE	GET CHARACTER FROM BELOW SCREEN BUFFER
/
/	HERE TO GET A CHARACTER FROM THE BELOW SCREEN BUFFER. IN THIS CASE,
/	WE ARE READING CHARACTERS IN THE FORWARD DIRECTION. WHEN THE
/	BUFFER EMPTIES WE TRY AND READ IN THE FORWARDS DIRECTION FROM THE
/	END OF THE TEMPORARY FILE (IF THERE IS ANYTHING THERE), OR FROM
/	THE END OF THE INPUT FILE.
/
/	BESW	BEPTR		FUNCTION
/	----	-----		--------
/	0	AT WORD		CHECK EMPTY BUFFER THEN READ FIRST BYTE
/	1	AT WORD		READ 2ND BYTE
/	2	PAST LOW NIB	READ THIRD BYTE.
/
/	NOTE:	THIS ROUTINE SHOULD NOT BE CALLED IF 'BOF' (BOTTOM-OF-FILE
/		FLAG IS SET)
/
GETBE	.SUB	50
	INC	BESW		TEST SWITCH
	TAD	BESW		GET THE SWITCH
	TAD	=GETSW-1	INDEX DISPATCH ADDRESSES
	CDF	%*		TABLE IN CURRENT FIELD
	JMP	IAC		DISPATCH CONTROL NOW
/
GETSW	DC	1F,2F,4F
/
/	HERE FOR THE FIRST CHARACTER POSITION.
/
1H	TAD	BEPTR		GET BELOW SCREEN BUFFER POINTER
	TAD	=-(BBUFE+1)	IS THE BUFFER EMPTY?
	SNA CLA			SKIP IF NOT
	JMS	RBE		ELSE READ TO BELOW SCREEN BUFFER
/
/	HERE FOR FIRST/SECOND CHARACTER POSITIONS.
/
2H	TADI	BEPTR		GET THE WORD CONTAINING THE BYTE WE NEED
	INC	BEPTR		STEP BUFFER POINTER FOR NEXT TIME
/
3H	AND	=0377		TRIM OFF GARBAGE AT HIGH END
	TAD	=-EOF		COMPARE WITH EOF CHARACTER
	SNA			END OF FILE CODE HERE?
SLASHZ	JMP	6F		YES: JUMP ON END OF FILE (NOP ON /Z)
	TAD	=EOF		NO: RESTORE CHARACTER
	.RET	GETBE		ALL DONE HERE
/
/	HERE FOR THE THIRD CHARACTER POSITION
/
4H	DCA	BESW		RESET SWITCH FOR NEXT TIME
	LDI	-2		POINT BACK NOW TO BEFORE HIGH NIBBLE
	TAD	BEPTR		...
	JMS	GETB		GET BYTE AT THAT POSITION
	JMP	3B		LOOP BACK NOW TO MASK IT
/
6H	TAD	=EOF		RETURN EOF CODE TO BUFFER
	JMS	PUTBE		...
	INC	BOF		MARK AT BOTTOM OF FILE NOW
	.RET	GETBE		RETURN NOW
	TITLE	PUT CHARACTER INTO BELOW SCREEN BUFFER
/
/	THIS ROUTINE WILL PUT THE CHARACTER IN THE AC INTO THE BELOW
/	SCREEN BUFFER IN OS/8 FORMAT IN THE BACKWARDS DIRECTION.
/	IF THE BELOW SCREEN BUFFER FILLS UP, IT IS
/	WRITTEN IN THE BACKWARDS DIRECTION TO THE END OF THE TEMPORARY FILE.
/
/	BESW	BEPTR		FUNCTION
/	----	-----		--------
/	0	PAST LOW NIB	IF BUFFER EMPTY, WRITE THEN PUT 3RD CHAR
/	1	AFTER WORD	PUT 1ST CHAR
/	2	AFTER WORD	PUT 2ND CHAR
/
PUTBE	.SUB	35
	DCA	PUTC		SAVE CHARACTER TO PUT INTO BUFFER
	DCA	BOF		CLEAR FLAG: CANNOT BE AT BOTTOM OF FILE
	LDI	-1		DECREMENT SWITCH SETTING
	TAD	BESW		...
	DCA	BESW		...
	SNL			SKIP IF FIRST/SECOND CHAR POSITIONS
	JMP	3F		DO THIRD POSITION
/
/	HERE FOR FIRST/SECOND CHARACTER POSITIONS.
/
	LDI	-1		SET POINTER AT WORD WITH BYTE WE WANT
	TAD	BEPTR		...
	DCA	BEPTR		...
	TADI	BEPTR		GET WORD WITH BYTE
	AND	=07400		SAVE OLD HIGH NIBBLE
	TAD	PUTC		INSERT NEW CHARACTER
	DCAI	BEPTR		STORE IT BACK
	.RET	PUTBE		ALL DONE HERE
/
/	HERE FOR THE THIRD CHAR POSITION
/
3H	TAD	BEPTR		GET BUFFER POINTER
	TAD	=-BBUF		IS THE BUFFER EMPTY?
	SNA CLA			SKIP IF NOT
	JMS	WBE		YES: SO WRITE BELOW SCREEN BUFFER
/
	LDI	-2		POINT BACK AT HIGH NIBBLE NOW
	TAD	BEPTR		...
	JMS	PUTB		INSERT THE BYTE
	LDI	2		RESET THE SWITCH
	DCA	BESW		...
	.RET	PUTBE		ALL DONE HERE
	TITLE	READ/WRITE BUFFER ROUTINES
/
/	HERE TO WRITE THE ABOVE SCREEN BUFFER IN THE FORWARD DIRECTION
/	INTO THE TEMPORARY FILE.
/
WAB	.SUB	12
	TAD	=ABUF		RESET BUFFER POINTER
	DCA	ABPTR		...
	TAD	TFFVBLK		TEMPORARY FILE, FORWARD VIRTUAL BLOCK
	STL			LINK = 1 FOR WRITE OPERATION
	JMS	BUFIO,ABUF	WRITE OUT BUFFER
	INC	TFFVBLK		STEP FORWARD VIRTUAL BLOCK NUMBER
	.RET	WAB		ALL DONE HERE
/
/	HERE TO WRITE THE BELOW SCREEN BUFFER IN THE BACKWARD DIRECTION
/	TO THE END OF THE TEMPORARY FILE
/
WBE	.SUB	14
	TAD	=BBUFE+1	RESET BUFFER POINTER
	DCA	BEPTR		(TO END, SINCE WE ARE READING IT BACKWARDS)
	LDI	-1		DECREMENT VIRTUAL BLOCK (GOING BACKWARDS)
	TAD	TFBVBLK		...
	DCA	TFBVBLK		...
	TAD	TFBVBLK		TEMPORARY FILE, BACKWARD VIRTUAL BLOCK
	STL			LINK = 1 FOR WRITE OPERATION
	JMS	BUFIO,BBUF	WRITE OUT BUFFER
	.RET	WBE		ALL DONE HERE
/
/	SUBROUTINE TO READ/WRITE OUT BUFFER CALLED BY ABOVE ROUTINES. AC HAS
/	BLOCK FOR I/O, ADDRESS FOLLOWING CALL HAS BUFFER ADDRESS.
/	LINK = 0 TO READ THE BLOCK, LINK = 1 TO WRITE THE BLOCK
/
	CDF	BUF		RESET MAIN DATA FIELD ON EXIT
	ROOM	12
BUFIO	SUB
	CDF	%*		RESET CURRENT FIELD NOW
	AFIELD	%*		...
	TAD	TFSBLK		ADD IN TEMPORARY FILE STARTING BLOCK
	DCA	3F		STORE INTO ARGUMENT SEQUENCE
	TADI	BUFIO		GET THE BUFFER ADDRESS
	INC	BUFIO		STEP OVER FOR EXIT
	DCA	4F		STORE BUFFER ADDRESS
	TAD	2F		GET I/O ARGUMENT
	AND	=03777		TRIM OFF THE R/W BIT
	SZL			SKIP IF READ OPERATION
	TAD	=04000		WRITE OPERATION: SET BIT ON
	DCA	2F		STORE INTO ARGUMENT SEQUENCE
	TAD	ODEV		DO WE HAVE AN OUTPUT DEVICE?
	SNA CLA			SKIP IF NOT
	JMP	BUFIO-2		NO: SO EXIT NOW
/
	TAD	TFBVBLK		COMPARE BACKWARD VIRTUAL BLOCK
	CMA IAC			...
	TAD	TFFVBLK		WITH THE FORWARD VIRTUAL BLOCK
	SNA CLA			IS THERE MORE ROOM IN TEMPORARY FILE?
	JMP	OFULL		NO: EXIT WITH ERROR MESSAGE
/
	ROOM	11
1H	JMSI	ODEV		WRITE OUT THE BUFFER
2H	DC	04200+(%ABUF.LS.3)	1 BLOCK FROM BUFFER FIELD
4H	DC	0		OS/8 BUFFER ADDRESS
3H	DC	0		OS/8 BLOCK NUMBER
	SMA CLA			<1> SKIP IF FATAL I/O ERROR
	JMP	BUFIO-2		<2> OK, OR NON-FATAL ERROR
/
	ROOM	4
	JMS	IOER		SIGNAL WE HAD AN I/O ERROR
	JMP	BUFIO-2		<1> USER INDICATES I/O ERROR TO BE IGNORED
	JMP	1B		<2> USER WISHES TO RETRY I/O OPERATION
	AFIELD	BUF		RESET ASSEMBLY FIELD
	TITLE	READ TO ABOVE SCREEN BUFFER
/
/	HERE TO READ IN THE BACKWARDS DIRECTION FROM THE START OF
/	THE TEMPORARY FILE INTO THE ABOVE SCREEN BUFFER.
/
RAB	.SUB	18
	TAD	=ABUFE+1	RESET BUFFER POINTER (BACKWARDS)
	DCA	ABPTR		...
	LDI	-1		SET TO DECREMENT TEMP FILE FORWARD BLOCK
	TAD	TFFVBLK		...
	SPA			IS THERE A BLOCK TO READ?
	JMP	1F		NO: WE ARE AT TOP OF FILE
	DCA	TFFVBLK		YES: STORE THAT BLOCK
	TAD	TFFVBLK		REGET THAT BLOCK NUMBER
	CLL			LINK = 0 FOR READ OPERATON
	JMS	BUFIO,ABUF	READ INTO THAT BUFFER
	.RET	RAB		ALL DONE HERE
/
/	HERE AT TOP OF FILE: JUST SET A FLAG INDICATING THERE IS NOTHING
/	TO READ.
/
1H	DCA	TOF		AC HAS -1: MARK AT TOP-OF-FILE
	.RET	RAB		ALL DONE HERE
	TITLE	READ TO BELOW SCREEN BUFFER
/
/	HERE FOR THE READ TO THE BELOW SCREEN BUFFER. FIRST JOB IS TO
/	SEE IF THERE IS ANYTHING TO READ FROM THE END OF THE TEMPORARY
/	FILE.
/
	CDF	BUF
RBE	SUB
	CDF	%*		TO CURRENT FIELD
	AFIELD	%*
	TAD	=BBUF		RESET BUFFER POINTER
	DCA	BEPTR		...
	TAD	TFBVBLK		TEMPORARY FILE BACKWARD VIRTUAL BLOCK #
	TAD	TFMLEN		COMPARE WITH MINUS FILE LENGTH
	SZA CLA			ANY BLOCKS IN THE TEMPORARY FILE?
	JMP	5F		YES: GO READ THEM
/
/	HERE THE TEMPORARY FILE IS EMPTY, SO WE MUST TRY AND READ FROM
/	THE INPUT FILE. NOTE THAT /Z OPTION CHANGES THE INSTRUCTION AT
/	'EOFCK' TO A 'NOP' WHICH AVOIDS THE CHECK FOR END OF FILE.
/
	TAD	IFVBLK		GET INPUT FILE VIRTUAL BLOCK NUMBER
	TAD	IFMLEN		SUBTRACT INPUT FILE LENGTH
	SNA CLA			ANY BLOCKS LEFT IN INPUT FILE?
EOFCK	JMP	9F		NO: WE ARE AT END-OF-FILE THEN
/
	TAD	IFVBLK		YES: ADD VIRTUAL BLOCK NUMBER
	TAD	IFSBLK		TO INPUT FILE STARTING BLOCK
	DCA	3F		AND STORE IN OS/8 CALLING SEQUENCE
	INC	IFVBLK		STEP INPUT FILE VIRTUAL BLOCK NUMBER
/
	ROOM	9
2H	JMSI	IDEV		READ IN THE NEXT BLOCK OF THE FILE
	DC	0200+(%BBUF.LS.3)	READ 1 BLOCK
	DC	BBUF		BUFFER ADDRESS
3H	DC	0		OS/8 BLOCK NUMBER
	SMA CLA			<1> SKIP ON FATAL I/O ERROR
	JMP	RBE-2		<2> OK, OR NON-FATAL ERROR: EXIT NOW
/
	ROOM	4
	JMS	IOER		SIGNAL WE HAD AN I/O ERROR
	JMP	RBE-2		<1> USER WANTS TO IGNORE ERROR
	JMP	2B		<2> USER WANTS TO REPEAT OPERATION
/
/	COME HERE TO READ IN THE NEXT BLOCK FROM THE END OF THE TEMPORARY
/	FILE.
/
5H	TAD	TFBVBLK		GET BLOCK NUMBER
	INC	TFBVBLK		STEP TEMPORARY FILE BACKWARD VIRTUAL BLOCK #
	CLL			LINK = 0 FOR READ OPERATION
	JMS	BUFIO,BBUF	READ INTO BELOW SCREEN BUFFER
	JMP	RBE-2		ALL DONE HERE
/
/	COME HERE AT COMPLETE END OF FILE.
/
9H	LDI	1		SET FLAG: AT BOTTOM OF FILE
	DCA	BOF		...
	JMP	RBE-2		ALL DONE HERE
/
	AFIELD	BUF
	TITLE	QUIT FUNCTION AND ERROR CONDITIONS
/
/	COME HERE ON ERROR OF WRITING DIRECTORY. THIS IS A SERIOUS
/	PROBLEM, SO DEFINITELY ALLOW RETRIES HERE.
/	NOTE THAT WE ENTER HERE DIRECTLY FROM FIELD 1
/
	ROOM	4
WFAIL	JMS	IOER		SIGNAL I/O ERROR
	JMP	QUIT		<1> USER WISHES TO IGNORE ERROR
	JMPX	DWRITE		<2> USER WISHES TO RETRY THE OPERATION
/
/	COME HERE WHEN TEMPORARY FILE IS COMPLETELY FULL.
/
OFULL	TAD	=TFULL-NOCLOSE	TEMPORARY FILE FULL MESSAGE
/
/	COME HERE WHEN OUTPUT FILE WILL NOT CLOSE PROPERLY
/
CLFAIL	TAD	=NOCLOSE	ALERT USER TO PROBLEM
	JMS	STROUT		...
/
/ COME HERE FROM OTHER PLACES TO UNCONDITIONALLY RETURN TO THE OS/8
/ KEYBOARD MONITOR.
/
QUIT	DCA	SCROFF		ENSURE VISTA ALLOWS FUNCTION THROUGH
	TAD	=X:RTN		ALLOW VCM FILE TO RESET TERMINAL
	JMSI	EXTER		...
	CDF	0		MUST HAVE DF=0
	JMP	$07600		RETURN TO OS/8.
/
	EJECT
	ORG	KIO		SHOULD NOT BE UP TO HERE IN FIELD 0
/
/ CODE BELOW CATERS TO THE CASE WHERE 'QUIT' TRIES TO CALL VCM WITH
/ THE EXIT FUNCTION BUT THE VCM FILE HAS NOT YET BEEN LOADED (I.E.
/ AFTER AN ERROR DURING INITIALIZATION. IF SO WE JUST RETURN (SINCE
/ THE VCM FILE HAS NOT SET ANYTHING UP YET)
/
	ORG	SIO
	DC	0		RETURN ADDRESS
	CLA			REMOVE FUNCTION CODE FROM AC
	JMPI	SIO		AND RETURN NOW