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

	FILE	VISTA  -- VIRTUAL SCREEN EDITOR
	TITLE	VISTA--VERSION 01.37
DEBUG	EQU	0		DEBUG SPACE ON EACH PAGE
	FREE	DEBUG		DEBUG SPACE
/
/
/		******************************************
/		**					**
/		**	        V I S T A		**
/		**					**
/		**	 PDP-8 FULL-SCREEN EDITOR	**
/		**					**
/		**		CODED BY		**
/		**	   C. E. STEUART DEWAR		**
/		**	      MARCH, 1980		**
/		**					**
/		**					**
/		******************************************
/
/
/	COPYRIGHT  (c) 1980 Under BERNE and UNIVERSAL COPYRIGHT LAW
/		By: DEWAR INFORMATION SYSTEMS CORPORATION
/
/	The information in this document  is subject to change without
/	notice  and  should  not be construed as a commitment by DEWAR
/	INFORMATION SYSTEMS  CORPORATION.   DEWAR  INFORMATION SYSTEMS
/	assumes no  responsibility  for  any errors that may appear in
/	this document  other  than providing  corrections for any such
/	errors when brought to the attention of DEWAR INFORMATION SYS-
/	TEMS CORPORATION.
/
/	The SOFTWARE  described  in  this document is furnished to the
/	purchaser under a license for use on a  single computer system
/	and can be copied  (with inclusion of DISC's copyright notice)
/	only for use in such system.
/
/ 	Licensees  of the  SOFTWARE  may make changes to the  software
/ 	with the understanding that the warranty for the SOFTWARE only
/ 	applies  to the original  unmodified version  delivered to the
/ 	licensee.  The fact that licensee may have modified or changed
/ 	the  SOFTWARE  in no way alters or detracts from the copyright
/ 	protection and proprietary rights due to DISC for the SOFTWARE
	TITLE	REVISION LEVEL HISTORY
/
/	ALL REVISIONS MADE TO VISTA STARTING WITH THE INITIAL PRE-RELEAS
/	VERSION ARE DOCUMENTED HERE
/
/ DATE		BY		CHANGES
/ ----		--		-------
/
/ 5-APR-80	C.E.S.D		CORRECTED PROBLEM OF UNESTABLISHED LINE
/				...AFTER PUTDOWN FUNCTION
/				ADDED INSERT BLOCK COMMAND
/				CHANGED SCROLL UP/DOWN TO RESTORE
/				...CURSOR POSITION AFTER PREMATURE
/				...STOP AT TOP/BOTTOM OF FILE.
/				CHANGED DELETE TO END OF LINE SO THAT
/				...CURSOR DROPS TO END OF FOLLOWING LINE
/				CORRECTED PROBLEM OF ADDING A BLANK LINE
/				...AT END OF MEMORY ON SCROLL UP.
/				ALLOWED INSERT LINE/BLOCK AND STARTUP
/				...TO DO HEURISTICS CHECK AT LINE START
/ 				ADDED THE 'MARK-ALL-LINES' COMMAND
/
/ 6-MAY-80	C.E.S.D		MODIFIED KEYBOARD DEBOUNCE CIRCUIT FOR
/ 				...INCREASED COMPATIBILITY WITH
/ 				...DECSTATION AND TIME-SHARE SYSTEMS.
/ 				FIXED PROBLEM OF PUTDOWN IMMEDIATELY
/ 				...AFTER CLOSE PICKUP FILE COMMAND.
/ 				CORRECTED TEST IN INITIALIZATION
/ 				...CIRCUIT FOR BLANKING 7200 PAGE
/ 				...CODE.
/ 				MADE PICKUP/PUTDOWN SET ROW-MODIFIED
/ 				...FLAG
/
/ 7-MAY-80	C.E.S.D		OPTIMIZED SOME ERASE TO END OF LINE
/ 				...SEQUENCES (HELPS HAZELTINE CRT)
/ 				CORRECTED PROBLEM OF SCROLLING DOWN
/ 				...ON A NEWLY CREATED FILE
/ 				AVOIDED MOVING CURSOR ON SCROLL DOWN
/ 				...AT TOP OF FILE
/ 				ALLOWED CLOSE COMMAND TO CLOSE OUT
/ 				...A LOOKED-UP PICKUP AREA WITHOUT
/ 				...DELETING IT.
/ 				MADE SEVERAL MINOR SPACE-SAVING CHANGES
/
/ 8-MAY-80	C.E.S.D		CORRECTED PROBLEM OF LOSING VCM RESET
/ 				...AFTER FILE CLOSURE.
/
/ 9-MAY-80	C.E.S.D		CORRECTED PROBLEM OF WORD LEFT AT HOME
/ 				...POSITION AT TOP OF FILE WITH ONLY
/ 				...1 WORD ON THE LINE(!)
/ 				CORRECTED PROBLEM OF SCROLLING MARKED
/ 				...LINES ONTO THE SCREEN.
/ 				PERFORMED SOME CODE COMPRESSION
/ 				CHANGED WORD LEFT/RIGHT/DELETE TO USE
/ 				...DEFINITION OF WORD AS ONLY LETTERS
/ 				...AND DIGITS
	TITLE	INTRODUCTION
/
/	VISTA IS A SCREEN ORIENTED TEXT EDITOR FOR A VISUAL DISPLAY
/	TERMINAL.
/
/	FUNCTION KEYS ON A TERMINAL ARE HANDLED THROUGH THE USE OF
/	A VIDEO CHARACTERISTICS MODULE (VCM), THAT PROCESSES ALL INPUT TO THE
/	MAIN PORTION OF THE VISTA PROGRAM. IN THE SAME WAY, ALL OUTPUT FROM
/	THE VISTA PROGRAM IS ENCODED AND IT IS THE FUNCTION OF THE
/	'VCM' PROGRAM TO RETRANSLATE THIS OUTPUT INTO A FORM
/	SUITABLE FOR THE SPECIFIC TERMINAL IN USE.
/
/	THE VCM PROVIDED STANDARDLY PROVIDED WITH
/	VISTA HAS BEEN DESIGNED AROUND THE VT52/VT100 TERMINALS SINCE
/	IT IS EXPECTED THAT THESE ARE THE MOST COMMON DISPLAY TERMINALS
/	TO BE FOUND ON PDP8 SYSTEMS.
/
/	IMPLEMENTATION OF OTHER VIDEO DISPLAY TERMINALS IS EXTREMELY
/	SIMPLE SINCE THE MAIN CORE OF THE VISTA PROGRAM IS NEVER
/	CHANGED.
/
/	CONSULT THE 'VISTA' PROGRAM MANUAL FOR DETAILS ON THE USE OF THIS
/				EDITING PROGRAM.
/
/	PROGRAM ADHERES TO THE FOLLOWING RESTRICTIONS:
/
/	1.	MUST RUN IN 8-K OF MEMORY.
/	2.	ALLOW 2-PAGE DEVICE HANDLERS FOR INPUT AND OUTPUT FILES
/	3.	RUN WITHOUT INTERRUPTS (FOR ADAPTABILITY TO TIME-SHARE
/		SYSTEMS).
/	4.	READ AND WRITE STANDARD OS/8 ASCII FILES
/	5.	HANDLE LINES UP TO TWICE THE SCREEN WIDTH WITHOUT
/		CORRUPTING THE ORIGINAL LINE BREAKS.
/	6.	HANDLE FILES WHICH HAVE NO CR/LF'S EMBEDDED IN THEM
	TITLE	SCREEN FORMAT LAYOUT
/
/	IN ORDER TO UNDERSTAND HOW VISTA WORKS IT IS ESSENTIAL TO
/	KNOW THE MEMORY LAYOUT.
/
/	A COPY OF EACH LINE ON THE VIDEO SCREEN IS MAINTAINED IN A
/	FIELD 1 BUFFER CALLED 'SCREEN'. EACH BYTE ON THE SCREEN OCCUPIES
/	ONE WORD IN THIS BUFFER.
/
/	A ROW TABLE IS MAINTAINED WHICH CONSISTS OF A ONE WORD ADDRESS
/	FOR EACH LINE ON THE SCREEN. THE ROW TABLE IS SIMPLY A SET OF
/	POINTERS TO THE FIRST WORD ON EACH LINE. THIS FIRST WORD IS
/	A STATUS/COUNT WORD FOR THE LINE WHICH IMMEDIATELY FOLLOWS.
/
/	THE FUNCTION OF THE ROW TABLE IS TO AVOID MOVING THE SCREEN MEMORY
/	AROUND DURING INSERTION AND DELETION OF LINES. IN THIS CASE, ONLY
/	THE ROW TABLE ITSELF HAS TO BE ADJUSTED. FOR THIS REASON, THE
/	POINTER ADDRESSES IN THE ROW TABLE ARE NOT NECESSARY IN ANY ORDER.
/
/	THE FORMAT OF THE STATUS/COUNT WORD FOR EACH LINE IS:
/
/		ABC DEE EEE EEE
/
/	A = 0	CURRENT LINE EXISTS
/	    1	CURRENT LINE DOES NOT EXIST (AT END OF FILE OR UNESTABLISHED)
/
/	B = 0	LINE ENDS WITH CR/LF
/	    1	LINE ENDS WITHOUT CR/LF
/
/	C = 0	LINE NOT MARKED
/	    1	LINE MARKED AS PART OF BLOCK (FOR SAVE/DELETION)
/
/	D = 0	CURRENT LINE HAS NOT BEEN MODIFIED ON THIS EDIT
/	    1   HAS BEEN MODIFIED ON THIS EDIT CYCLE
/
/	EEE..E	LINE LENGTH IN THE RANGE 0-255
/
/
/	END OF FILE IS INDICATED BY 'BOF' FLAG BEING SET AND BY ROWS
/	WITH A BIT 0 STATUS OF 1.
/
/	THERE ARE TWO ONE-BLOCK BUFFERS 'FEEDING' THE SCREEN WINDOW:
/	THE ABOVE SCREEN BUFFER (ABUF) AND THE BELOW SCREEN BUFFER
/	(BBUF). THESE BUFFERS ARE IN OS/8 FORMAT AND ARE READ AND
/	WRITTEN FROM THE OS/8 DEVICE AS NEEDED.
/
/	NOTE:	BECAUSE OF THE USE OF OS/8 DEVICE HANDLERS, BI-DIRECTIONAL
/		SCROLLING ON NON-DIRECTORY DEVICES OR READ/ONLY//WRITE
/		ONLY DEVICES WILL CAUSE I/O ERRORS THAT CAN ABORT THE EDIT
	EJECT
/
/	THE BI-DIRECTIONAL SCROLLING ALGORITHM IS VERY SIMPLE AND HAS
/	APPARENTLY ESCAPED MANY PROGRAMMERS ATTEMPTING TO WRITE VIRTUAL
/	SCREEN EDITORS.
/
/	ON STARTUP, VISTA OPENS UP A TEMPORARY FILE ON THE OUTPUT DEVICE
/	AND TAKES NOTE OF BOTH THE STARTING AND ENDING BLOCK ADDRESSES
/	OF THE ALLOCATED SPACE.
/
/	ASSUMING NO PRIOR BACKWARDS MOTION,
/	WHEN TRAVERSING THE FILE IN THE FORWARD DIRECTION, BLOCKS ARE
/	READ FROM THE INPUT FILE INTO THE BELOW SCREEN BUFFER, SCROLLED
/	ONTO THE SCREEN AND SCROLLED OFF THE TOP INTO THE ABOVE SCREEN
/	BUFFER. THE ABOVE SCREEN BUFFER IS THEN WRITTEN TO THE START
/	OF THE TEMPORARY OUTPUT FILE WHENEVER IT FILLS.
/
/	WHEN TRAVERSING THE FILE IN THE BACKWARDS DIRECTION, BLOCKS ARE
/	READ IN THE BACKWARDS DIRECTION FROM THE CURRENT POSITION IN
/	THE TEMPORARY OUTPUT FILE AND SCROLLED ONTO THE SCREEN. 
/	LINES SCROLLED OFF THE TOP OF THE SCREEN ARE WRITTEN IN
/	DESCENDING BLOCK NUMBERS TO THE  E N D  OF THE TEMPORARY FILE.
/
/	NOTICE NOW THAT THE FORWARD TRAVERSE ALGORITHM HAS AN EXTRA STEP
/	NOT MENTIONED IN THE FIRST DESCRIPTION: BEFORE READING BLOCKS
/	FROM THE INPUT FILE, WE WANT TO FIRST CHECK THAT THERE AREN'T ANY
/	BLOCKS WAITING TO BE READ AT THE END OF THE TEMPORARY FILE--THESE
/	HAVE TO BE READ FIRST.
/
/	ON END OF FILE, ALL WE HAVE TO DO IS TO FLUSH OUT THE SCREEN
/	BUFFER AND BELOW SCREEN BUFFER INTO THE OUTPUT FILE AND THEN
/	COPY OVER ANY REMAINING BLOCKS AT THE END OF THE TEMPORARY
/	FILE TO THE START OF THE TEMPORARY FILE, AND THEN COPY OVER
/	ANY REMAINING BLOCKS IN THE INPUT FILE.
/
/	VISTA WILL BLOCK ALIGN THE INPUT AND OUTPUT FILES BY PADDING
/	THE BUFFERS WITH ASCII NULL CODES (OCTAL 200). THIS MAKES
/	IT POSSIBLE TO COPY BLOCKS 15 AT A TIME SO THAT THE FILE CLOSURE
/	IS ALMOST INSTANTANEOUS.
/
/	AS WITH THE ICE EDITOR, THERE IS A RUN-TIME OPTION TO SUPRESS
/	THIS HIGH SPEED CLOSE AND REPLACE IT WITH A FILE PACKING CLOSE
/	THAT IS NOT AS FAST.
	TITLE	MACRO DEFINITIONS
/
/	MACRO TO OPTIMIZE THE USE OF THE PAGE8 'SUB' AND 'RET' DIRECTIVES
/	IN THIS CASE, THE '.SUB' DIRECTIVE PROVIDES AN
/	ESTIMATE OF THE AMOUNT OF PAGE ROOM NEEDED BY THE ROUTINE.
/	IF THE END OF THE ROUTINE WILL LIE BELOW LOCATION 140
/	(AN ARBITRARY ADDRESS, BUT USUALLY SAFE), THEN A 'DC 0'
/	INSTRUCTION IS GENERATED INSTEAD OF THE 'SUB'.
/
/	THE '.RET' DIRECTIVE ALWAYS GENERATES A 'JMPI' IF THE
/	ENTRY POINT IS ON PAGE
/
	MACRO
	.SUB	<CT><VAL=07402>
	ROOM	2
	AIF	((*&0177)+<CT>).LT.0140,.FIT
!<>	SUB	<VAL>
	MEXIT
.FIT	ANOP
!<>	DC	07402			; SHOULD FIT ON PAGE
	MEND
/
/	OPTIMIZED SUBROUTINE RETURN
/
	MACRO
	.RET	<LABEL>
	ROOM	2		; ENSURE ROOM ON PAGE
	AIF	(*&07600).EQ.(<LABEL>&07600),.ONPAGE
!<>	RET	<LABEL>		; NOT ON PAGE
	MEXIT
.ONPAGE	ANOP
!<>	JMPI	<LABEL>		; ON PAGE
	MSKIP
	MEND
	TITLE	ASSEMBLY AND LOADING PROCEDURE
/
/ THE NORMAL PROCEDURE FOR ASSEMBLING THE VISTA PROGRAM IS AS FOLLOWS:
/
/ 	.R PAGE8
/ 	*VISTA,LPT:VISTA<DEV:VISTA,VISTB,VISTC(IG)
/
/ THE NORMAL PROCEDURE FOR ASSEMBLING THE VCM FILE IS:
/
/ 	.R PAGE8
/ 	*VCM0,LPT:<VISTA.SD,DEV:VCM52(IY)
/
/ ALTERNATIVELY, THE VCM FILES CAN BE ASSEMBLED WITH PAL8:
/
/ 	.R PAL8
/ 	*VCM0,LPT:<VISTA.EQ,DEV:VCM52.PA
/
/ THE NORMAL PROCEDURE FOR LOADING THE BINARY FILES IS:
/
/ 	.R ABSLDR
/ 	*CL0.BN,CL1.BN
/ 	*VISTA.BN/R$
/ 	.SAVE SYS VISTA;1=0
/
/ AND FOR THE VCM FILE:
/
/ 	.R ABSLDR
/ 	*CL0.BN
/ 	*VCM0.BN/R$
/ 	.SAVE SYS VCM0 6000-6577;7605
/
/
/ IN THIS CASE, 'CL0.BN' AND 'CL1.BN' ARE TRIVIAL LITTLE BINARY FILES
/ THAT FILL ALL OF FIELD 0 AND FIELD 1 RESPECTIVELY WITH ZEROES. THIS
/ MAINTAINS THE DISC CONVENTION THAT ALL UNUSED MEMORY LOCATIONS ARE
/ SET TO ZERO.
/
/ THE VISTA MANUAL CAN BE GENERATED WITH ACID AS FOLLOWS:
/
/ 	.R ACID
/ 	*LPT:<DEV:VDOCT(INZL)=5
/
/ 	.R ACID
/ 	*LPT:<DEV:VDOCA,VDOCB,VDOCC(ZL)=7
	TITLE	EQUIVALENCES
/
/		ASCII CHARACTERS:
/
$CR	EQU	0215		CARRIAGE RETURN
$LF	EQU	0212		LINE  FEED
TAB	EQU	0211		TABULATION CODE
$NULL	EQU	0200		NULL
DELETE	EQU	0377		DELETE/RUBOUT CODE
BELL	EQU	0207		ASCII BELL
ESC	EQU	0233		ASCII ESCAPE CODE
EOF	EQU	0232		ASCII END OF FILE CODE
EFLAG	EQU	0201		EDIT FLAG IS A CONTROL/A
MFLAG	EQU	1		MARK FLAG IS 'IMPOSSIBLE' ASCII VALUE OF 1
CTLC	EQU	0203		CONTROL/C CODE
FF	EQU	0214		FORM FEED
$XON	EQU	0221		CONTROL/Q IS XON CODE
$XOFF	EQU	0223		CONTROL/S IS XOFF CODE
$CTRLO	EQU	0217		CONTRO/O TURNS OFF SCREEN I/O
/
/ MANY SECTIONS OF CODE DEPEND UPON A VALUE OF 2 IN 'PAD'. THERE IS NO
/ REASON WHY THIS VALUE SHOULD EVER BE CHANGED.
/
$PAD	EQU	2		TABULATION PAD CHARACTER IN BUFFER
/
/		SPECIAL ENCODED CHARACTERS FOR VCM FILE
/		(VCM FILE TAKES THESE CODES AND PERFORMS
/		 WHATEVER FUNCTION IS REQUIRED ON THE VDT TO IMPLEMENT
/		 THESE FUNCTIONS.)
/
$X:POS	EQU	0		POSITION CURSOR BASED ON ROW AND COLUMN
X:INIT	EQU	1		INITIALIZE VIDEO SCREEN (IF NECESSARY)
/		2		CODE 2 IS RESERVED FOR PAD CODE
$X:CRLF	EQU	3		PERFORM CR/LF ON SCREEN (GO TO COL 0, NEXT ROW)
$X:EOL	EQU	4		ERASE FROM CURSOR POSITION TO END OF ROW
$X:CLSC	EQU	5		CLEAR SCREEN AND HOME CURSOR
$X:INS	EQU	6		MOVE CURRENT LINE AND ALL LINES BELOW CURSOR
/				LINE DOWN ONE LINE, LEAVE CURRENT LINE BLANK
$X:DEL	EQU	7		DELETE AND REMOVE ROW WITH CURSOR
$X:BEL	EQU	8		RING BELL/BUZZER ETC.
$X:BKSP	EQU	9		BACK SPACE ONE POSITION
$X:SPV1	EQU	10		SET SPECIAL VIDEO MODE 1 (IF POSSIBLE)
$X:SPV2	EQU	11		SET SPECIAL VIDEO MODE 2 (IF POSSIBLE)
$X:NMV	EQU	12		SET BACK TO NORMAL VIDEO MODE
$X:END	EQU	13		FLAG CHAR FOR NO-END-OF-LINE
$X:RTN	EQU	14		RETURNING TO OS/8 (RESET TERMINAL MODE E
/
/	FOLLOWING DEFINITION MUST BE THE LAST DEFINED CONTROL CODE
/	IF YOU INSERT MORE CONTROL CODES, INSERT BEFORE THIS ONE
/	(AND UPDATE THE VALUE FOR THIS CODE).
/
$X:CTRL	EQU	15		CONTROL CODE: NON-DISPLAYABLE
/
/		SCREEN CONTROL EQUIVALENCES
/
LMASK	EQU	0377		ROW LENGTH MASK (ASSUME 0-255 CHARS)
$BUF	EQU	1		FIELD OF SCREEN BUFFER
/
/		ADDRESS CONSTANTS
/
USR	QUT	1,0200		RESIDENT ENTRY POINT TO OS/8 USR ROUTINE
NRUSR	QUT	1,07700		NON-RESIDENT ENTRY POINT TO OS/8 USR
/
$KIO	QUT	0,06000		KEYBOARD I/O ADDRESS
$SIO	QUT	0,06002		SCREEN I/O ADDRESS
$VMCMNT	QUT	0,06004		MINUS ASCII CODE FOR COMMENT DELIMITER
$VMTAG	QUT	0,06005		MINUS ASCII CODE FOR TAG FIELD DELIMITER
$VROWS	QUT	0,06006		POSITIVE COUNT OF # OF ROWS ON VDT
$VCOLS	QUT	0,06007		POSITIVE COUNT OF # OF COLUMNS ON VDT
$VAUCOL	QUT	0,06010		COLUMN FOR AUDIT TRAIL (ON /A OPTION)
$VSTAT	QUT	0,06011		STATUS: BIT0=XON/XOFF; BIT1=CTRL/O
	TITLE	INTERPRETER FUNCTION CODE DEFINITIONS.
/
/	FUNCTION CODES RETURNED BY THE INTERPRETER IN THE VCM PROGRAM
/	SHOULD BE IN THE RANGE 100-177. THE FOLLOWING SET OF
/	EQUIVALENCES DEFINES THE MEANINGS OF THESE CODES. NOTE THAT
/	THE JOB OF THE VCM PROGRAM IS TO TAKE SOME ARBITRARY SET
/	OF KEY STROKE(S) ON THE KEYBOARD AND THEN CHANGE THEM TO
/	A SINGLE PRE-DEFINED CHARACTER ACCORDING TO THE FOLLOWING LIST
/
/
/$Y:IGNORE	EQU	0100
/$Y:IGNORE	EQU	0101
/$Y:IGNORE	EQU	0102
/$Y:IGNORE	EQU	0103
/$Y:IGNORE	EQU	0104
/$Y:IGNORE	EQU	0105
/$Y:IGNORE	EQU	0106
/$Y:IGNORE	EQU	0107
/$Y:IGNORE	EQU	0110
/$Y:IGNORE	EQU	0111
/$Y:IGNORE	EQU	0112
/$Y:IGNORE	EQU	0113
/$Y:IGNORE	EQU	0114
/$Y:IGNORE	EQU	0115
/$Y:IGNORE	EQU	0116
/$Y:IGNORE	EQU	0117
/$Y:IGNORE	EQU	0120
/$Y:IGNORE	EQU	0121
/$Y:IGNORE	EQU	0122
/$Y:IGNORE	EQU	0123
$Y:CSTART	EQU	0124	CURSOR TO START OF ROW
$Y:CASE		EQU	0125	INVERT CASE
$Y:TRUNCF	EQU	0126	TRUNCATE FILE WITH CURRENT PAGE
$Y:TRANSP	EQU	0127	TRANSPARENT CHAR ENTRY
$Y:BKDEL	EQU	0130	BACKSPACE DELETE
$Y:TABR		EQU	0131	TAB RIGHT
$Y:INSTOG	EQU	0132	INSERT CHAR ON/OFF
$Y:DELWD	EQU	0133	DELETE WORD
$Y:RETURN	EQU	0134	RETURN CODE
$Y:DLETLN	EQU	0135	DELETE LINE
$Y:XEDIT	EQU	0136	EXIT FROM EDIT MODE
$Y:QUIT		EQU	0137	QUIT TO OS/8 MONITOR
$Y:CEOL		EQU	0140	CURSOR TO END OF LINE
$Y:RSTEP	EQU	0141	REPLACEMENT STEP
$Y:RCONT	EQU	0142	REPLACEMENT CONTINUOUS
$Y:SEARCH	EQU	0143	SEARCH NEXT
$Y:CAPTOG	EQU	0144	CAPS LOCK TOGGLE
$Y:AWAY		EQU	0145	END OF SCREEN
$Y:BOFC		EQU	0146	MOVE TO LAST PAGE
$Y:TOFC		EQU	0147	MOVE TO FIRST PAGE
$Y:HOME		EQU	0150	HOME CURSOR
$Y:NEWCMD	EQU	0151	ENTER/LEAVE COMMAND MODE
$Y:PAGEDN	EQU	0152	PAGE DOWN
$Y:PAGEUP	EQU	0153	PAGE UP
$Y:SCRLDN	EQU	0154	SCROLL DOWN
$Y:SCRLUP	EQU	0155	SCROLL UP
$Y:ROWINS	EQU	0156	INSERT LINE
$Y:PUTDN	EQU	0157	PUT DOWN SAVED LINES
$Y:PICKUP	EQU	0160	PICKUP MARKED LINES
$Y:UNMKROW	EQU	0161	UNMARK ROW
$Y:MKROW	EQU	0162	MARK ROW
$Y:DISMOD	EQU	0163	DISPLAY MODIFIED LINES
$Y:DOSCRN	EQU	0164	RESTORE SCREEN
$Y:DELSCR	EQU	0165	DELETE SCREEN
$Y:CNEXTL	EQU	0166	CURSOR TO NEXT LINE
$Y:WRIGHT	EQU	0167	WORD CURSOR RIGHT
$Y:WLEFT	EQU	0170	WORD CURSOR LEFT
$Y:TABL		EQU	0171	TAB LEFT
$Y:INSBLK	EQU	0172	INSERT BLOCK
$Y:DELEWD	EQU	0173	DELETE TO END OF WORD
$Y:CRIGHT	EQU	0174	CURSOR RIGHT
$Y:CLEFT	EQU	0175	CURSOR LEFT
$Y:CDOWN	EQU	0176	CURSOR DOWN
$Y:CUP		EQU	0177	CURSOR UP
	TITLE	PAGE ZERO CELLS
/
/	LOCATIONS 0,1,2 ARE RESERVED FOR POSSIBLE VCM FILE USAGE
/	ALSO USED FOR INITIAL ENTRY INTO THE VISTA PROGRAM
/
	ORG	1
/
	LDI	1		SET FLAG: NEED TO CALL COMMAND DECODER
	JMPI	TEMP		OFF FOR INITIALIZATION NOW
/
$ROW	DC	0		MAIN POINTER INTO THE ROW TABLE
/
	ORG	7		RESERVE 4,5,6 FOR ODT USAGE
/
$COL	DC	0		CURRENT CURSOR COLUMN NUMBER
/
TXR1	EQU	*		(DEFINED IN ALL FIELDS)
	DC	0		TEMPORARY INDEX REGISTER 1
TXR2	EQU	*		(DEFINED IN ALL FIELDS)
	DC	0		TEMPORARY INDEX REGISTER 2
ROWXR	DC	0		XR FOR USE WITH ROW TABLE ONLY
FXR	DC	0		XR FOR USE BY 'FLAGLN' ROUTINE
KXR1	DC	0		XR FOR USE BY KEYBOARD ROUTINES ONLY
KXR2	DC	0		...
PXR	DC	0		XR FOR USE IN 'ROWIN' ETC.
GXR	DC	0		...
/
	ORG	020
TEMP	EQU	*		TEMPORARY CELLS DEFINED IN ALL FIELDS
	DC	INIT0		...(ALSO POINTS TO INITIALIZATION CODE)
TEMP1	EQU	*		...
	DC	0		...
TEMP2	EQU	*		...
	DC	0		...
TEMP3	EQU	*		...
	DC	0		...
CNTR	EQU	*		TEMPORARY LOOP COUNTER
	DC	0		...
/
$ROWTAB	DC	0		STARTING ADDRESS OF ROW TABLE
$LASTROW DC	0		ADDRESS OF LAST ROW IN ROW TABLE
$ROWSIZ	DC	0		SET TO # OF ROWS ON SCREEN
/
	ORG	030		LEAVE ROOM HERE OS/78 SYMBIONT ETC.??
	ORG	032		...
/
$PKBD	DC	KBD		POINTER TO KEYBOARD ROUTINE (FOR INTERPRETER)
$PSCR	DC	SCROUT		SCREEN OUTPUT
COLSIZ	DC	0		SET TO MAXIMUM # OF COLUMNS ON SCREEN
ROWPTR	DC	0		POINTER CELL
ROWPTR2	DC	0		AS ABOVE
RSAVE	DC	0		SAVE CELL
	EJECT
/
CHARP	DC	0		POINTER INTO SCREEN BUFFER SET BY 'LOADC'
THISC	DC	0		CURRENT CHARACTER FROM KEYBOARD
LASTC	DC	0		LAST CHARACTER FROM KEYBOARD
TARCOL	DC	0		TARGET COLUMN ON CURSOR UP/DOWN
PSETX	DC	SCRCK		COMMON EXIT PATH FROM ROUTINES
EXTER	DC	XTER		POINTER TO EXTERPRETER MODULE
DCHAR	DC	0		SAVE CELL FOR DISPLAY CHAR
RCNTR	DC	0		COUNTER CELL
ROWCTR	DC	0		SECOND COUNTER CELL
SCROFF	DC	04000		SCREEN I/O IS OFF IF SET TO 4000, 0=SCREEN ON
PSUB	DC	0		SUBROUTINE POINTER FOR PAGE UP/DOWN
FLAG	DC	0		GENERAL FLAG CELL
SHOWMOD	DC	0		SET TO 04000 TO DISPLAY MODIFIED ROWS
CFLAG	DC	0		FLAG FOR CURSOR ROUTINES
COLSAVE	DC	0		SAVE AREA FOR COLUMN NUMBER
COLSV2	DC	0		2ND LEVEL SAVE FOR COLUMN NUMBER
/
TXTCOL	DC	0		SAVE COLUMN NUMBER DURING COMMAND MODE
TXTROW	DC	0		SAVE ROW POSITION DURING COMMAND MODE
ABMARK	DC	0		COUNT OF MARKED ROWS IN ABOVE SCREEN BUFFER
BEMARK	DC	0		COUNT OF MARKED ROWS IN BELOW SCREEN BUFFER
MAXF	CDF	0		'CDF' SET TO HIGHEST MEMORY FIELD BY 'CORE'
REPCTR	DC	0		REPLACEMENT COUNTER (SEE SEARCH AND REPLACE)
RCHAR	DC	0		LAST CHARACTER READ IN SCROLLING ROUTINES
RFCTR	DC	0		COUNTER TO CHECK FOR ROW OVERFLOW IN RFI
RFMAX	DC	0		RESET VALUE FOR 'RFCTR'
STEMP	DC	0		TEMPORARY STORAGE FOR STROUT/FILSCR ROUTINES
BLOCKCT	DC	2		# OF BLOCKS IN SCREEN AND I/O BUFFERS
PRPTR	DC	0		POINTER FOR 'PRLINE' ROUTINE
PRCNTR	DC	0		COUNTER FOR THE 'PRLINE' ROUTINE
/
/	STATUS FLAGS FOR THE SYSTEM
/
CMND	DC	0		SET TO 1 WHEN IN COMMAND MODE
INSF	DC	0		SET TO 1 WHEN IN INSERT CHARACTER MODE
CAPSLK	DC	0		SET TO 04000 WHEN 'CAPSLOCK' MODE IS SET
MODF	DC	0		SET TO 0400 IF POSTING ^A CORRECTION FLAGS
WORD	DC	0		SET TO 1 IF WORD DELIMITER ON STRING SEARCH
ASEMH	DC	0		SET TO 020 IF ASSEMBLER/COMPILER HEURISTICS ON
WFLAG	DC	02000		CLEARED IF /W OPTION IS SET ON
FFLAG	DC	04000		SET TO -0214 TO STRIP FORM FEEDS ON INPUT
MCMNT	DC	0		MINUS ASCII CODE OF COMMENT CHAR (SET BY
AUCOL	DC	0		COLUMN NUMBER FOR AUDIT TRAIL (SET BY VCM)
AUDIT	DC	0		SET TO 400 IF /A OPTION (AUDIT TRAIL ON)
XFLAG	DC	0		SET TO 4000 WHEN 'XOFF' IN EFFECT
MTAG	DC	0		MINUS ASCII CODE OF TAG CHAR (SET BY VCM
RFLAG	DC	0		FLAG CELL
SPLIT	DC	0		SPLIT POINT SET BY 'SIZE' ROUTINE
SPLITSV	DC	0		SPLIT POINT SAVE CELL
TCHAR	DC	0		SAVE CELL FOR CHAR TO OUTPUT TO TERMINAL
KCHAR	DC	0		SAVE CELL FOR NEW KEYBOARD CHARACTER
/
/	FILE/BUFFER POINTERS AND CELLS
/
TOF	DC	1		SET TO 1 AT TOP OF FILE
BOF	DC	0		SET TO 1 AT BOTTOM OF FILE
IFVBLK	DC	0		INPUT FILE VIRTUAL BLOCK NUMBER
IFSBLK	DC	0		INPUT FILE STARTING BLOCK NUMBER
IFMLEN	DC	0		INPUT FILE MINUS BLOCK LENGTH
/
TFFVBLK	DC	0		TEMPORARY FILE FORWARD VIRTUAL BLOCK
TFBVBLK	DC	0		TEMPORARY FILE BACKWARD VIRTUAL BLOCK
TFSBLK	DC	0		TEMPORARY FILE STARTING BLOCK NUMBER
TFMLEN	DC	0		TEMPORARY FILE MINUS BLOCK LENGTH
/
/
ABSW	DC	0		ABOVE SCREEN BUFFER PACKING SWITCH
BESW	DC	0		BELOW SCREEN BUFFER PACKING SWITCH
PUTC	DC	0		SAVE FOR CHARACTER TO STORE INTO BUFFER
ABPTR	DC	ABUF		ABOVE SCREEN BUFFER POINTER
BEPTR	DC	BBUFE+1		BELOW SCREEN BUFFER POINTER
BSPTR	DC	0		BLOCK SAVE POINTER
SUBRC	DC	0		SUBROUTINE ADDRESS SET BY 'ROWIN'
SUBR2	DC	0		SUBROUTINE ADDRESS ALSO FOR 'ROWIN'
/
IDEV	DC	0		INPUT DEVICE HANDLER ADDRESS
ODEV	DC	0		OUTPUT DEVICE HANDLER ADDRESS
BSVBLK	DC	0		BLOCK SAVE VIRTUAL BLOCK
TESTWD	DC	WDTEST		POINTER TO WORD CHECK ROUTINE
/
/	GET STATUS OF ROW POINTED TO BY 'ROW'
/
ROWSTAT	DC	0		GET STATUS/LENGTH OF CURRENT ROW
	TADI	ROW		GET ADDRESS OF STATUS/LENGTH
	DCA	TEMP		...
	TADI	TEMP		GET ACTUAL STATUS/LENGTH
	JMPI	ROWSTAT		RETURN IT IN THE AC
/
/	GET STATUS OF ROW POINTED TO BY 'ROWPTR'
/
ROWPST	DC	0		GET STATUS/LENGTH OF CURRENT ROW
	TADI	ROWPTR		GET ADDRESS OF STATUS/LENGTH
	DCA	TEMP		...
	TADI	TEMP		GET ACTUAL STATUS/LENGTH
	JMPI	ROWPST		RETURN IT IN THE AC
/
/
/ ALL PAGE ZERO CELLS FROM NOW ON AVAILABLE FOR USE BY VCM
/
$XT	DC	0		TEMPORARY CELL
$XT2	DC	0		...
	TITLE	MAIN PROCESSING DISPATCH CIRCUIT
/
	ORG	0200
	ISEC	0		ENABLE AUTO-PAGING
	AFIELD	BUF		DEFAULT DATA FIELD IN CODE IS 'BUF'
/
/ THIS IS THE MAIN PROCESSING/DISPATCH CIRCUIT FOR VISTA.
/
/ COME HERE AFTER A CONTROL FUNCTION WHERE WE NEED TO DEBOUNCE
/ THE KEYBOARD BUFFER.
/ FOR EXAMPLE, IF SCROLL OPERATION IS ABORTED WHEN THE SCROLL
/ UP KEY IS PRESSED, WE MIGHT HAVE QUIT ON THE ESCAPE CODE, AND WILL
/ THEN READ THE NEXT CHARACTER AS A TEXT CHARACTER. WE PREVENT THIS FROM
/ HAPPENING BY FLUSHING THE KEYBOARD BUFFER.
/
IDLP	JMS	KCK		CHECK ON KEYBOARD NOW
	TADI	=KBUF		GET FIRST WORD IN KEYBOARD LINE BUFFER
	SNA CLA			IS THE BUFFER EMPTY NOW?
	JMP	CHARD		YES: SO OFF TO READ CHARACTER NOW
	JMS	KIO		NO: SO READ KEYBOARD
	CLA			IGNORE THE CHARACTER
	JMP	IDLP		BACK TO FLUSH OUT ANY MORE CHARACTERS
/
/ COME HERE TO READ NEXT CHARACTER
/
CHARD	TAD	THISC		CURRENT CHARACTER NOW BECOMES LAST CHARACTER
	DCA	LASTC		...
	DCA	SCROFF		ENSURE FLAG CLEARED (IN CASE SET BY ^O)
/
/ IN CASE WE ARE AT END OF FILE, ENSURE THAT AT LEAST THE TOP ROW
/ IS MARKED AS ESTABLISHED SO THAT WE HAVE SOMEWHERE TO PUT THE
/ CURSOR. THIS ALSO HANDLES THE STARTUP PROBLEM WHERE THERE IS
/ NO INPUT FILE.
/
	TADI	ROWTAB		GET ADDRESS OF TOP ROW
	DCA	TEMP		SAVE POINTER
	LDI	03777		ENSURE ROW-ESTABLISHED FLAG IS CLEARED
	ANDI	TEMP		...
	DCAI	TEMP		...
/
/ HERE TO READ THE NEXT CHARACTER
/
	JMS	KIO		CALL VCM FOR NEXT CHARACTER
	DCA	THISC		SET AS NEW CURRENT CHARACTER
	TAD	THISC		...
	TAD	=-' 		ASCII CONTROL OR INTERPRETER FUNCTION CODE?
	SPA			SKIP IF NOT
	JMP	CTRLCHR		YES: HANDLE THIS
	TAD	=' -DELETE	DELETE CODE?
	SNA CLA			SKIP IF NOT
	JMP	DELCHR		YES: OFF TO HANDLE DELETE CHARACTER
/
/	HERE WE HAVE A NORMAL ASCII CHARACTER IN THE RANGE 240-376 OCTAL.
/	CHECK SOFTWARE CAPS LOCK KEY (SOME VIDEO TERMINALS DO NOT HAVE
/	A CAPS LOCK).
/
	TAD	CAPSLK		GET CAPS LOCK FLAG
	SPA CLA			SKIP IF NOT ON
	JMP	FOLDIT		CAPS LOCK ON: FORCE CHAR FOLD
/
	TAD	ASEMH		ASSEMBLER/COMPILER EDITING HEURISTICS ON?
SLASHC	SNA CLA			SKIP IF SO (###CLA### IF /C OPTION SET)
	JMP	NOFOLD		NO: SO NO CHAR FOLDING HERE
/
	ROOM	4
	JMS 	TCMNT		ARE WE IN A COMMENT FIELD?
	JMP	NOFOLD		<1> YES: SO NEVER FOLD THEN
/
/	<2> HERE WE EITHER HAVE CAPS LOCK ON, OR HEURISTICS
/	ARE ENABLED AND WE ARE NOT IN A COMMENT FIELD, SO FOLD THE CHARACTER
/
FOLDIT	TAD	THISC		GET THE CURRENT CHARACTER
	JMS	FOLD		FOLD LOWER CASE TO UPPER CASE
STORC	DCA	THISC		SAVE CHARACTER
/
NOFOLD	TAD	THISC		REGET CHARACTER
/
/	MERGE HERE FROM OTHER PLACES TO CALL DISPLAY CHARACTER ROUTINE
/	WITH CHARACTER IN AC.
/
STAC	JMS	DISCHR		DISPLAY CHARACTER/STORE INTO MEMORY
	JMS	FLAGLN		FLAG THAT WE HAVE MODIFIED THE CURRENT LINE
/
	TAD	AUDIT		ARE WE HANDLING AUDIT TRAIL HERE?
	SNA CLA			SKIP IF SO
	JMP	2F		NO: SO CONTINUE NOW
/
/	WE ARE HANDLING MODIFICATION/DELETION FLAGS WHICH MEANS THAT WE
/	SHOULD LEAVE 6 CHARACTERS AT THE END OF EACH LINE FOR THE FLAG
/	(THE FLAG CONSISTS OF A COMMENT CHARACTER, FOLLOWED BY TWO DIGITS,
/	A PERIOD AND TWO MORE DIGITS: FOR EXAMPLE: WITH PAL8 OR PAGE8:
/
/
	LDI	6		WITHIN 6 COLUMNS OF END OF LINE?
	TAD	COL		...
	CMA			NEGATE AND COMPARE WITH
	TAD	COLSIZ		COLUMN SIZE
	SMA SZA CLA		SKIP IF WE DO NOT HAVE ROOM
	JMP	2F		ENOUGH ROOM: CONTINUE
/
	TAD	=X:BEL		WARN USER THERE IS NO ROOM FOR FLAG
	JMSI	EXTER		BY RINGING BELL
/
/	WAS THE /H OPTION SELECTED? (AND WAS THERE ROOM FOR THE CODE)
/
2H	TAD	ASEMH		ASSEMBLER/COMPILER HEURISTICS ENABLED?
	SNA CLA			SKIP IF SO
	JMP	CHARD		ELSE ALL DONE HERE (NO DEBOUNCE)
	JMP	ODEVH		OFF TO HANDLE HEURISTICS NOW
	TITLE	DISPATCH ON CONTROL/FUNCTION CODES
/
/	COME HERE TO HANDLE ASCII CONTROL CODES
/	AND VCM FUNCTION CODES. LATTER CODES START
/	AT 177 AND WORK DOWNWARDS. OBVIOUSLY WE MUST HAVE
/	AN ASSOCIATED TABLE MATCH IN 'DISTAB' FOR THIS TO
/	WORK PROPERLY.
/
CTRLCHR	TAD	=040		TEST FOR CODE IN RANGE 200-237
	SMA CLA			SKIP IF VCM FUNCTION CODE
	JMP	IGNORE		IGNORE ASCII CONTROL CODES
	TAD	THISC		REGET THE CHARACTER
	TAD	=DISTAB-0100	BIAS CODE TO RANGE 0-77 OFFSET
/
/	MERGE HERE FROM OTHER PLACES TO TRANSFER CONTROL
/	INDIRECTLY TO THE ADDRESS IN THE AC, DATA FIELD
/	SHOULD BE SET TO FIELD OF TABLE
/
IAC	DCA	TEMP		STORE ADDRESS OF ADDRESS
	TADI	TEMP		GET THE ACTUAL JUMP ADDRESS
	DCA	TEMP		SAVE IT
	CDF	BUF		ENSURE BUFFER FIELD SET NOW
	JMPI	TEMP		AND THEN PASS CONTROL TO IT
	TITLE	INSERT BLOCK
/
/	HERE FOR THE INSERT BLOCK FUNCTION. DUMP ALL LINES FROM
/	THE CURRENT LINE TO THE END OF THE SCREEN TO THE BELOW SCREEN
/	BUFFER. THEN RESTORE THE SCREEN (JUST THE TOP HALF)
/
INSBLK	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
/
/	LOOP HERE UNTIL CURRENT ROW BECOMES UNESTABLISHED
/
1H	JMS	BLINO		MOVE OUT THE CURRENT LOGICAL BOTTOM ROW
	JMS	ROWSTAT		GET STATUS OF CURRENT ROW
	SMA CLA			IS THIS ROW STILL ESTABLISHED?
	JMP	1B		YES: SO  LOOP BACK NOW
/
	JMS	TRUNCLN		SET 0 LENGTH AND MARK ESTABLISHED
	JMS	RESCRN		RESTORE ABOVE PART OF SCREEN
	JMP	ASMCHK		OFF NOW TO CHECK HEURISTICS MODE
	TITLE	INSERT CHARACTER - CAPS LOCK - TRANSPARENT ENTRY
/
/	HERE TO TOGGLE THE STATE OF THE CAPS LOCK KEY
/
CAPTOG	LDI	04000		TOGGLE BIT 0 WHICH IS THE FLAG BIT
	TAD	CAPSLK		...
	DCA	CAPSLK		...
	JMP	ONOFF		BEEP IF GOING ON NOW
/
/	HERE TO TOGGLE THE STATE OF THE INSERT CHARACTER MODE LATCH
/
INSTOG	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
	LDI	04000		SET TO TOGGLE INSERT CHARACTER LATCH
	TAD	INSF		...
	DCA	INSF		AND STORE IT BACK
/
/	MERGE HERE FROM CAPS LOCK TO SEE IF GOING ON OR OFF
/
ONOFF	SZL			SKIP IF LATCH JUST WENT ON
	JMP	IDLP		JUST WENT OFF: DO NOTHING
	JMP	IGNORE		JUST WENT ON: BEEP BELL
/
/	HERE FOR TRANSPARENT ENTRY OF A CHARACTER. THE NEXT CHARACTER
/	IS READ AND STORED INTO THE BUFFER WITH  N O  CHECKING. THIS
/	MAKES IT POSSIBLE TO INSERT ALL KINDS OF CONTROL CODES (FORM-FEEDS,
/	ETC.) CARE SHOULD BE TAKEN, HOWEVER, INSERTING CARRIAGE RETURNS,
/	LINE FEEDS ETC. MIGHT CAUSE UNEXPECTED RESULTS (HOWEVER, VISTA
/	SHOULD NOT LOSE CONTROL).
/
TRANSP	IOS	3,1		WAIT ON KEYBOARD DIRECTLY
	JMP	TRANSP		...
	JMS	RDCHR		READ THE CHARACTER
	JMP	STAC		STORE WITHOUT CHECKING
/
/	SUBROUTINE TO CHECK FOR COMMAND MODE. THIS ROUTINE WILL PASS
/	CONTROL DIRECTLY TO 'IGNORE' IF COMMAND MODE IS SET.
/
NOCOM	.SUB	5
	TAD	CMND		GET MODE FLAG
	SNA CLA			ARE WE IN COMMAND MODE?
	.RET	NOCOM		NO: SO ALL DONE HERE
	JMSI	EXTER		ENSURE CURSOR PROPERLY RE-POSITIONED
/
/ COME HERE FROM SEVERAL PLACES TO BEEP THE BELL AND RETURN TO THE
/ MAIN DISPATCH/PROCESSING CIRCUIT.
/
IGNORE	TAD	=X:BEL		YES: SO BEEP BELL AND RETURN TO MAIN LOOP
	JMP	SETX		...
	TITLE	CURSOR LEFT -- CURSOR UP
/
/	HERE TO MOVE THE CURSOR ONE POSITION TO THE LEFT
/
CLEFT	DCA	CFLAG		CLEAR CURSOR FLAG
	JMS	LEFTC		CALL ROUTINE TO PERFORM FUNCTION
	TAD	CFLAG		REGET CURSOR FLAG
	SNA CLA			DID WE HAVE A SIMPLE MOVEMENT TO THE LEFT
	TAD	=X:BKSP		YES: SO POSITION CURSOR BY BACKSPACE
	JMP	SETX		DONE HERE
/
/	SUBROUTINE TO MOVE THE CURSOR LEFT. IF CURSOR IS IN COLUMN 0,
/	IT IS MOVED TO THE END OF THE PRIOR LINE. IF THE CURRENT LINE
/	IS THE TOP LINE ON THE SCREEN, A SCROLL DOWN FUNCTION IS PERFORMED
/	NOTE THAT THE CURSOR IS MOVED IN MEMORY ONLY AND  N O T  ON THE
/	SCREEN.
/
	JMS	INROW		CHECK THAT CURSOR IS PROPERLY IN ROW
LEFTC	SUB
	LDI	-1		MOVE CURSOR TO THE LEFT
	TAD	COL		...
	DCA	COL		...
	SZL			SKIP IF CURSOR WAS IN COLUMN 0
	JMP	LEFTC-2		CHECK FOR PAD CHARACTER, THEN EXIT
/
/	CURSOR WAS IN COLUMN 0. MOVE TO END OF PRIOR LINE.
/
	INC	CFLAG		SET FLAG: CANNOT USE SIMPLE CURSOR MOVEMENT
	LDI	2047		SET 'RIDICULOUS' CURSOR POSITION
	DCA	COL		...
	JMS	UPC		DO CURSOR UP FUNCTION
	RET	LEFTC		ALL DONE HERE
/
/	HERE FOR CURSOR UP. IF ON TOP LINE, SCROLL DOWN.
/
CUP	JMS	SETCOL		SET TARGET COLUMN FOR REPETITIVE MOVEMENT
	JMS	UPC		PERFORM CURSOR UP FUNCTION
	JMPI	PSETX		ALL DONE HERE
/
/	SUBROUTINE TO PERFORM ACTUAL CURSOR UP FUNCTION.
/
UPC	.SUB	16
	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
	TAD	ROW		GET CURRENT ROW ADDRESS
	CMA IAC			NEGATE AND COMPARE WITH
	TAD	ROWTAB		THE TOP ROW
	SNA CLA			ON TOP ROW?
	JMP	1F		YES: MUST SCROLL DOWN THEN
/
	LDI	-1		NO: SO MOVE TO PRIOR ROW
	TAD	ROW		...
	DCA	ROW		...
/
/	NOW, IF CURRENT COLUMN IS BEYOND END OF THIS LINE, MOVE IT TO
/	END OF THIS LINE.
/
0H	JMS	INROW		ENSURE CURSOR LOCATED IN THAT ROW
	.RET	UPC		ALL DONE HERE
/
/	HERE WHEN CURSOR WAS LOCATED IN FIRST ROW: SCROLL DOWN
/
1H	JMS	DNSCRL		SCROLL DOWN ONE ROW
	JMP	0B		BACK NOW TO ENSURE CURSOR IN THE ROW
/
/	SUBROUTINE TO SETUP COLUMN FOR CURSOR UP/DOWN. IF LAST CHARACTER
/	IS MARKED AS A -1, THEN THE LAST CHARACTER WAS A CURSOR UP/DOWN
/	IN THAT CASE, WE WANT TO TRY AND POSITION THE CURSOR AT
/	THE COLUMN THAT THE CURSOR WAS IN WHEN WE FIRST STRUCK THE
/	CURSOR UP/DOWN KEYS. THIS IS CALLED 'TARGET COLUMNING'.
/
SETCOL	.SUB	14
	TAD	LASTC		GET THE LAST CHARACTER
	SMA CLA			SKIP IF LAST WAS CURSOR UP/DOWN
	JMP	2F		THIS IS THE FIRST TIME THROUGH
/
/	CURSOR UP/DOWN IS BEING REPEATED: REMEMBER TARGET COLUMN
/
	TAD	TARCOL		SET TARGET COLUMN AS COLUMN TO FIND
	DCA	COL		...
	JMP	3F		NOW SET 'THISC' AGAIN
/
/	FIRST TIME: SET CURRENT COLUMN AS THE TARGET COLUMN
/
2H	TAD	COL		FIRST TIME: SO CURRENT COLUMN BECOMES TARGET
	DCA	TARCOL		...
/
3H	LDI	-1		SET FLAG FOR CURSOR UP/DOWN CODE
	DCA	THISC		...
	.RET	SETCOL		ALL DONE HERE
	TITLE	CURSOR RIGHT
/
/	HERE FOR CURSOR RIGHT. IF AT END OF ROW, MOVE DOWN TO FOLLOWING ROW.
/
CRIGHT	DCA	CFLAG		CLEAR FLAG TO CHECK FOR SIMPLE CURSOR RIGHT
	JMS	LOADC		GET CHARACTER UNDER CURSOR
	DCA	DCHAR		SAVE IN CASE SIMPLE CURSOR MOVEMENT
	JMS	RIGHTC		DO CURSOR RIGHT FUNCTION
/
/	OPTIMIZE FOR VCM FILE: IF CURSOR IS JUST MOVING ONE POSITION
/	TO THE RIGHT, AVOID UNNECESSARY X/Y CURSOR POSITIONING
/
	TAD	CFLAG		GET CURSOR FLAG
	SNA CLA			DID WE HAVE A SIMPLE MOVE TO THE RIGHT?
	TAD	DCHAR		YES: SO OUTPUT CHAR FOR CURSOR RIGHT
	JMP	SETX		DONE HERE
/
/	SUBROUTINE TO PERFORM ACTUAL CURSOR RIGHT ROUTINE (IN MEMORY ONLY)
/
RIGHTC	.SUB	20
	ROOM	4
	JMS	ROWCK		TEST FOR END OF ROW
	JMP	2F		<1> AT END OF ROW: DO CURSOR DOWN
	INC	COL		<2> NOT AT END OF ROW: MOVE TO THE RIGHT
/
/	CHECK FOR BEING ON TOP OF A PAD CHARACTER, AND IF SO, MOVE
/	THE CURSOR AGAIN.
/
	JMS	LOADC		GET CHARACTER UNDER THE CURSOR
	SNA			AT END OF ROW?
	.RET	RIGHTC		YES: SO RETURN NOW
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SZA CLA			SKIP IF SO
	.RET	RIGHTC		NO: SO RETURN NOW
	INC	CFLAG		YES: SET FLAG: NO SIMPLE CURSOR MOVEMENT
	JMP	RIGHTC+1	MOVE CURSOR AGAIN TO THE RIGHT
/
2H	DCA	COL		MOVE INTO COLUMN 0 ON THAT LINE
	JMS	DOWNC		MOVE CURSOR DOWN
	INC	CFLAG		MARK: WE DID NOT JUST MOVE TO THE RIGHT
	.RET	RIGHTC		BACK NOW TO CHECK FOR CURSOR ON PAD CODE
	TITLE	CURSOR TO NEXT LINE -- CURSOR DOWN
/
/	PERFORM CURSOR TO START OF NEXT ROW FUNCTION
/
CNEXTL	DCA	COL		SET NOW TO COLUMN 0
	DCA	TARCOL		RESET THIS IN CASE LAST WAS UP/DOWN
/
/	MERGE HERE NOW FOR CURSOR DOWN.
/
CDOWN	JMS	SETCOL		SET TARGET COLUMN FOR REPETITIVE MOTION
	JMS	DOWNC		CALL CURSOR DOWN ROUTINE
	JMPI	PSETX		POSITION CURSOR AND ALL DONE
/
/ HERE FOR CURSOR DOWN FUNCTION. FIRST CHECK FOR BEING ON LAST ROW
/ SINCE WE MUST SCROLL UP IF SO.
/
/ NOTE THAT WE TAKE A GLOBAL ABORT TO THE 'AWAY' ROUTINE IF WE ARE AT
/ BOTTOM OF FILE. THIS PREVENTS THE POSSIBILITY OF A LOCKUP IF WE DO
/ A WORD RIGHT AT END OF FILE ON A LINE THAT ONLY HAS ONE WORD.
/
1H	JMS	INROW		MAKE SURE CURSOR IS LOCATED WITHIN THE ROW
DOWNC	SUB			ENTRY AND EXIT POINT
	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
	TAD	ROW		GET ROW POINTER
	CMA IAC			NEGATE AND COMPARE
	TAD	LASTROW		LAST ROW IN TABLE
	SNA CLA			SKIP IF NOT IN THE LAST ROW
	JMP	3F		LAST ROW: MUST SCROLL UP
/
/	WE HAVE ANOTHER ROW. HOWEVER, WE MAY BE AT END OF FILE IN WHICH
/	CASE THIS ROW WILL HAVE BIT 0 SET ON
/
	INC	ROW		YES: STEP POINTER TO THAT ROW
2H	JMS	ROWSTAT		GET ROW STATUS/LENGTH
	SPA CLA			DOES THIS ROW EXIST?
	JMP	AWAY		NO: TAKE GLOBAL ABORT TO 'AWAY'
	JMP	1B		ALL DONE HERE
/
3H	JMS	UPSCRL		SCROLL UP THE SCREEN BY ONE ROW
	JMP	2B		LOOP BACK NOW TO POSITION CURSOR
	TITLE	CURSOR TO END OF LINE/HOME CURSOR
/
/ HERE TO PLACE CURSOR AT EXTREME END OF SCREEN
/ NOTE THAT BECAUSE OF DUMMY ROW AT END OF ROW TABLE, WE CANNOT
/ 'FALL OFF' THE END OF THE TABLE
/
0H	INC	ROW		MOVE TO THE FOLLOWING ROW
AWAY	JMS	NOCOM		NOT ALLOWED IN COMAMND MODE
	JMS	ROWSTAT		GET STATUS FOR THIS ROW
	SMA CLA			DOES THIS ROW EXIST?
	JMP	0B		YES: SO BACK TO CHECK ON STATUS OF THIS ROW
	LDI	-1		NO: SO MOVE TO PRIOR ROW
	TAD	ROW		...
	DCA	ROW		...
/
/ HERE TO PLACE CURSOR AT END OF CURRENT ROW
/
CEOL	JMS	GLEN		GET LENGTH OF CURRENT ROW
	JMP	CSTART		MERGE WITH START OF ROW ROUTINE
/
/ HERE TO HOME THE CURSOR ON THE SCREEN.
/
HOME	TAD	ROWTAB		GET ADDRESS OF FIRST SLOT IN ROW TABLE
	DCA	ROW		...
/
/ HERE TO MOVE THE CURSOR TO THE START OF THE CURRENT ROW
/
CSTART	DCA	COL		SET COLUMN TO COLUMN 0
/
/ EXIT VIA PSETX IN CASE DNSCRL FROM PAGE DOWN BLANKED THE SCREEN AND
/ AND DNSCRL ABORTED TO THE HOME ROUTINE WITH IT STILL BLANKED
/
	JMPI	PSETX		OFF TO POSITION CURSOR NOW
/
/ COME HERE FROM MANY PLACES TO SET CURSOR TO CURRENT COLUMN
/ AND ROW AND THEN RETURN TO MAIN IDLING LOOP
/ ON ENTRY HERE, THE CONTROL FUNCTION IN THE AC WILL BE EXECUTED. NOTE
/ THAT IF THE AC IS 0, A POSITION CURSOR FUNCTION WILL BE PERFORMED.
/
SETX	JMSI	EXTER		PERFORM APPROPRIATE FUNCTION
	JMP	IDLP		AND RETURN TO THE MAIN CIRCUIT
	TITLE	WORD LEFT
/
/ HERE TO MOVE THE CURSOR ONE WORD POSITION TO THE LEFT.
/ THE CURSOR IS MOVED TO THE LEFT FIRST.
/ A WORD IS DELIMITED AT EITHER END BY CHARACTERS OTHER THAN LETTERS
/ OR DIGITS
/
WLEFT	JMS	LEFTC		MOVE CURSOR TO THE LEFT
/
/ IF CURSOR IS STILL ON A BLANK/TAB, MOVE IT AGAIN TO THE LEFT
/
	JMSI	TESTWD		TEST WORD UNDER CURSOR
	SNL CLA			DO WE HAVE A WORD DELIMITER?
	JMP	WLEFT		YES: SO KEEP MOVING THE CURSOR
	JMS	WSTART		NO: FIND START OF THIS WORD
	JMPI	PSETX		POSITION CURSOR THERE: ALL DONE
	TITLE	WORD RIGHT
/
/	HERE TO MOVE THE CURSOR TO THE START OF THE WORD IMMEDIATELY
/	TO THE RIGHT OF THE CURRENT WORD.
/
WR2	JMS	RIGHTC		LOOP BACK HERE TO MOVE CURSOR TO THE RIGHT
/
/ SEE IF CURSOR LOCATED UNDER A WORD DELIMITER FIRST
/
WRIGHT	JMSI	TESTWD		TEST WORD UNDER CURSOR
	SZL CLA 		IS THIS A WORD DELIMITER?
	JMP	WR2		NO: MOVE CURSOR RIGHT AND TRY AGAIN
/
/	HERE WHEN WE HAVE FOUND THE END OF THE WORD. SKIP NOW PAST ANY
/	MORE DELIMitERS THAT WE MAY HAVE.
/
WR3	JMS	RIGHTC		MOVE CURSOR TO THE RIGHT
	JMSI	TESTWD		TEST WORD UNDER CURSOR
	SNL CLA			IS THIS A WORD DELIMITER?
	JMP	WR3		DELIMITER: KEEP MOVING THE CURSOR THEN
	JMPI	PSETX		SOMETHING ELSE: SO DONE HERE
	TITLE	TAB RIGHT
/
/	HERE FOR TAB RIGHT. MOVE CURSOR TO THE RIGHT UNTIL WE FIND
/	A TAB STOP. HOWEVER WE HAVE TWO SPECIAL CASES TO DEAL WITH:
/
/	1. WE ARE IN INSERT CHARACTER MODE. IN THIS CASE WE ACTUALLY WANT
/	   TO STORE THE TAB CHARACTER INTO SCREEN MEMORY, AS WELL AS PERFORM
/	   A TAB FUNCTION ON THE SCREEN. NOTE THAT IF WE ARE AT THE END
/	   OF A ROW, WE CAN CALL THE 'RTAB' ROUTINE
/
/	2. WE ARE AT THE END OF THE ROW. IN THIS CASE WE MUST SUPPLY
/	   TAB AND PAD CODES TO GET TO THE COLUMN POSITION CONTAINING THE
/	   TAB AND, ADDITIONALLY OUTPUT SPACES TO GET THERE ON THE SCREEN
/
	ROOM	4
TABR	JMS	ROWCK		ARE WE AT THE END OF A ROW?
	JMP	1F		<1> YES: SO ALWAYS CALL 'RTAB'
	TAD	INSF		<2> NO: ARE WE IN INSERT CHARACTER MODE?
	SPA CLA			SKIP IF NOT
	JMP	2F		YES: SO STORE THE CHARACTER NORMALLY
/
1H	JMS	RTAB		DO THE TAB RIGHT FUNCTION
	JMPI	PSETX		POSITION CURSOR: ALL DONE
/
2H	TAD	=TAB		USE ASCII TAB CODE (INSTEAD OF FUNCTION)
	JMP	STORC		OFF NOW TO STORE CHARACTER
	EJECT
/
/	SUBROUTINE TO PERFORM TAB RIGHT FUNCTION
/	DO NOT ALLOW TAB FUNCTION TO BE PERFORMED IF WE ARE WITHIN 8 CHARACTERS
/	OF THE END OF THE LINE.
/
RTAB	.SUB	40
	TAD	COL		GET CURRENT COLUMN POSITION
	TAD	=8		+8
	CMA IAC			NEGATE AND SUBTRACT FROM THE
	TAD	COLSIZ		FULL COLUMN WIDTH
	SPA SNA CLA		SKIP IF NOT WITHIN 8 COLUMNS OF END OF LINE
	.RET	RTAB		TOO CLOSE TO END OF LINE: RETURN IMMEDIATELY
	TAD	=TAB		START OFF WITH TABULATION CODE
	DCA	DCHAR		(CHANGED LATER TO A PAD CODE)
/
/	LOOP BACK HERE TO SET A PAD CODE AND CHECK FOR BEING AT END OF LINE
/
	ROOM	4
0H	JMS	ROWCK		CHECK FOR END OF ROW
	JMP	1F		<1> AT END OF ROW: CONTINUE
	JMP	3F		<2> NOT AT END OF ROW: JUMP AHEAD
/
/	HERE WHEN AT END OF ROW. MUST STORE TAB CODE AND MOVE TO COLUMN
/	ON SCREEN TOO.
/
1H	TAD	DCHAR		START BY STORING TAB/PAD CODE
	JMS	DISCHR		...
	LDI	PAD		SET FOR PAD CODE NEXT TIME
	DCA	DCHAR		...
	JMP	4F		(DISCHR ADVANCED THE COLUMN NUMBER)
/
/	ADVANCE POINTER, LOOK FOR TAB STOP
/
3H	JMS	LOADC		GET CHARACTER UNDER CURSOR
	JMSI	EXTER		...OUTPUT (TO STEP CURSOR TO THE RIGHT)
	INC	COL		STEP COLUMN POSITION
/
4H	TAD	COL		GET CURRENT COLUMN POSITION
	AND	=7		TAB STOPS EVERY 8 POSITIONS
	SNA CLA			SKIP IF NOT AT A TAB STOP
	.RET	RTAB		FOUND TAB STOP: ALL DONE
	JMP	0B		LOOP BACK NOW
	TITLE	BACKSPACE DELETE - DELETE CHARACTER
/
/	HERE FOR THE DELETE CHARACTER FUNCTION
/
	ROOM	4
DELCHR	JMS	ROWCK		ARE WE AT THE END OF THE LINE?
/
/	HERE FOR THE BACKSPACE DELETE FUNCTION
/	ALSO MERGE BACK HERE FOR RUBOUT/DELETE AT END OF LINE
/
BKDEL	JMS	LEFTC		<1> MOVE THE CURSOR TO THE LEFT
/
/	<2> DELETE CHARACTER UNDER THE CURSOR NOW
/
	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
	JMS	LOADC		LOAD CURRENT CHARACTER TO SET 'CURP'
	LDI	PAD		IGNORE AND OVERWRITE WITH PAD CODE
	DCAI	CHARP		...
	JMS	FLAGLN		FLAG THIS LINE AS MODIFIED
	JMS	REDOLN		FIX UP LINE AND TAB STOPS
	JMP	CHARD		ALL DONE HERE
	TITLE	DELETE WORD
/
/ HERE FOR DELETE WORD FUNCTION. IF THE CURSOR IS
/ AT END OF ROW, MOVE THE CURSOR TO THE LEFT FIRST.
/ NOTE THAT DELETE WORD ERASES ALL CHARACTERS LYING BETWEEN SPACES/TABS
/ OR CONTROL CHARACTERS, WHILE DELETE TO END OF WORD ERASES ONLY
/ ALPHABETIC AND NUMERIC CHARACTERS.
/
	ROOM	4
DELWD	JMS	ROWCK		ARE WE AT THE END OF A ROW?
	JMS	LEFTC		<1> YES: SO MOVE THE CURSOR TO THE LEFT
1H	JMS	LEFTC		<2> MOVE THE CURSOR TO THE LEFT
	JMS	LOADC		CHAR UNDER CURSOR
	TAD	=-' 		CHECK OUT ASCII CODE VALUE
	SMA SZA CLA		DO WE HAVE A TAB OR SPACE?
	JMP	1B		NO: SO MOVE CURSOR LEFT AND TRY AGAIN
	JMS	RIGHTC		YES: SO MOVE TO START OF 'WORD' NOW
	LDI	-1		SET FLAG FOR DELETE WORD FUNCTION
/
/	HERE FOR THE DELETE TO END OF WORD FUNCTION. CLEAR THE FLAG
/	SO WE WILL AVOID REMOVING THE DELIMITER THAT FOLLOWS THE WORD
/	NOTE THAT 'TARCOL' IS SAFELY USED AS A FLAG HERE
/
DELEWD	DCA	TARCOL		CLEAR FLAG FOR DELETE TO END OF WORD
	TAD	COL		SAVE CURRENT COLUMN POSITION
	DCA	COLSAVE		...
	JMS	NOCOM		CAN'T CONTINUE NOW IF IN COMMAND MODE
	JMS	FLAGLN		FLAG CHANGE TO CURRENT LINE
/
/	OVERWRITE ALL CHARACTERS WITH PAD CODES UNTIL WE FIND A
/	WORD DELIMITER OR END OF ROW.
/
	ROOM	4
DELWLP	JMS	ROWCK		SKIP IF NOT AT END OF ROW
	JMP	DLWEND		<1> ALL DONE AT END OF ROW
	JMSI	TESTWD		<2> OK: TEST WORD UNDER CURSOR
	SNL CLA 		IS THIS A WORD DELIMITER?
	JMP	DLWD2		YES: MAY BE DONE NOW
/
/ COME BACK HERE IF DELETE WORD AND THE DELIMITER WAS NOT A TAB/SPACE
/ OR CONTROL CODE.
/
DLWD1	LDI	PAD		OVERWRITE THIS CHAR WITH PAD CODE
	DCAI	CHARP		('CHARP' STILL SET OK BY 'TESTWD'
	INC	COL		STEP COLUMN NUMBER
	JMP	DELWLP		LOOP FOR NEXT CHARACTER
/
/ HERE ON DELIMITER. IF THIS IS DELETE WORD, SEE IF WE HAVE FOUND
/ A TAB/SPACE/CONTROL CODE. IF NOT, LOOP BACK TO THE DELETE WORD LOOP
/
DLWD2	TAD	TARCOL		YES: FLAG TO SORT OUT WHICH ROUTINE
	SNA CLA			WHICH FUNCTION WERE WE PERFORMING?
	JMP	DLWEND		DELETE TO END OF WORD: WE ARE DONE HERE
	TADI	CHARP		GET CHARACTER UNDER CURSOR
	TAD	=-' 		TEST ASCII CODE
	SMA SZA CLA		IS THIS A SPACE/TAB/CONTROL CODE?
	JMP	DLWD1		NO: SOMETHING ELSE: ALWAYS DELETE IT
	LDI	PAD		TAB/SPACE/CONTROL CODE: REMOVE IT
	DCAI	CHARP		...
/
/	HERE AT END OF WORD BEING DELETED.
/
DLWEND	TAD	COLSAVE		RESTORE PRIOR COLUMN POSITION
	DCA	COL		...
	JMSI	EXTER		POSITION CURSOR NOW AT START OF WORD
	JMS	REDOLN		FIX UP LINE ON SCREEN AND MEMORY
	ISZ	TARCOL		TEST FLAG AGAIN
	JMP	WRIGHT		DELETE TO END OF WORD: EXIT VIA WORD RIGHT
	JMP	CHARD		ALL DONE HERE.
/
/ SUBROUTINE TO MOVE CURSOR TO START OF WORD IN WHICH CURSOR IS
/ LOCATED (ALSO USED BY WORD DELETE/CASE SHIFT).
/
WSTART	.SUB	20
1H	TAD	COL		...
	SNA CLA			SKIP IF NOT IN COLUMN 1 OR 0
	.RET	WSTART		OK: TREAT COLUMN 0 AS START OF WORD
	JMS	LEFTC		MOVE CURSOR LEFT
	JMSI	TESTWD		TEST WORD UNDER CURSOR
	SZL CLA			IS THIS A WORD DELIMITER?
	JMP	1B		NO:, SO KEEP MOVING TO THE LEFT
/
	JMS	RIGHTC		YES, STEP BACK NOW TO START OF WORD
	.RET	WSTART		ALL DONE HERE
	TITLE	DELETE LINE FUNCTION
/
/	HERE FOR DELETE LINE FUNCTION. THREE DIFFERENT OPERATIONS HERE:
/
/	CURSOR	IN COL 0	DELETE WHOLE LINE
/		NOT COL 0	ERASE TO END OF LINE.
/		END OF ROW	DELETE END OF ROW STATUS
/
DLETLN	TAD	COL		GET THE CURRENT COLUMN
	SNA CLA			SKIP IF NOT AT START OF LINE
	JMP	1F		COLUMN 0 REMOVE THE LINE
/
	ROOM	4
	JMS	ROWCK		ARE WE AT THE END OF THE ROW?
	JMP	DELEOL		<1> YES: SO HANDLE THIS NOW
	JMS	TRUNCLN		<2> NO: TRUNCATE LINE AT CURRENT COLUMN
	JMS	FLAGLN		FLAG LINE AS MODIFIED
	JMP	IDLP		ALL DONE HERE (TO IDLP TO DEBOUNCE)
/
/	HERE TO DELETE THE LINE FROM THE SCREEN.
/
1H	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
	TAD	ROW		GET ADDRESS OF CURRENT ROW
	JMS	RMVLN		REMOVE LINE FROM MEMORY
	JMS	BLINI		MOVE IN NEW ROW AT BOTTOM NOW
	JMS	FLAGLN		FLAG LINE AS HAVING BEEN MODIFIED
/
/ CHECK: IF THE CURRENT ROW IS UNESTABLISHED, MOVE CURSOR ONTO THE
/ PRIOR ROW (WE JUST DELETED THE LAST ROW). ALSO MERGE HERE FROM
/ OTHER PLACES TO MOVE THE CURSOR UP IF THE CURRENT ROW IS NOT
/ AN ESTABLISHED ROW
/
ESTCK	JMS	ROWSTAT		GET STATUS OF CURRENT ROW
	SPA CLA			DOES THIS ROW EXIST?
	JMS	UPC		NO: SO MOVE THE CURSOR UP NOW
	JMPI	PSETX		RE-POSITION CURSOR NOW
/
/	HERE TO HANDLE DELETION OF THE END OF A LINE. IN THIS CASE,
/	WE WOULD LIKE TO TRY AND MOVE UP AS MANY WORDS
/	AS POSSIBLE FROM THE FOLLOWING
/	LINE ONTO THE CURRENT LINE.
/
/	BECAUSE OF SEVERE SPACE LIMITATIONS, ALL WE DO IS FLAG THE
/	CURRENT ROW SO THAT WHEN IT IS SCROLLED OFF, IT WILL MERGE
/	WITH THE ROW BELOW.
/
DELEOL	JMS	NOCOM		CANNOT ALLOW THIS IN COMMAND MODE
	STL			SET TO FORCE THE NO-CRLF BIT ON
	TADI	ROW		ADDRESS OF LENGTH/STATUS WORD
	JMS	NOCRLF		...
	TAD	=X:END		FLAG WITH SPECIAL GRAPHIC ON SCREEN
	JMSI	EXTER		...
	JMS	DOWNC		MOVE THE CURSOR DOWN ONE LINE
	JMP	CEOL		MOVE CURSOR NOW TO END OF THIS LINE
	EJECT
/
/	SUBROUTINE TO TRUNCATE THE CURRENT LINE AT THE CURRENT COLUMN
/	CURSOR MUST BE IN THE CORRECT PLACE ON THE SCREEN BEFORE
/	CALLING THIS ROUTINE, OR THE ERASE TO END OF LINE WILL
/	NOT APPEAR AT THE CORRECT SPOT ON THE SCREEN.
/
TRUNCLN	.SUB	8
	TAD	COL		USE CURRENT COLUMN AS NEW COUNT
	JMS	PLEN		FOR THIS LINE.
	TAD	=X:EOL		ERASE TO END OF LINE ON TERMINAL NOW
	JMSI	EXTER		...
	.RET	TRUNCLN		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO REMOVE SPECIFIED LINE FROM MEMORY. DOES NOT
/	AFFECT THE VIDEO TERMINAL'S SCREEN. ROW TABLE IS OF COURSE
/	ADJUSTED TO SHOW THE DELETED LINE.
/
/	AC CONTAINS ADDRESS OF ROW TO BE REMOVED
/	ROUTINE CALLED AS PART OF DELETE LINE FUNCTION AND ALSO AS
/	SCROLL FUNCTION (AFTER TOP LINE ROLLED OFF)
/
/	FUNCTION HERE IS TO MOVE UP ALL ROW TABLE ADDRESSES FROM CURRENT
/	ROW TO END OF ROW TABLE AND THEN PLACE THE ADDRESS OF THE ROW
/	WHICH WAS REMOVED AT THE END OF THE ROW TABLE.
/
RMVLN	.SUB	35
	DCA	ROWPTR		SAVE POINTER INTO ROW TABLE
	TADI	ROWPTR		GET ADDRESS OF LINE TO BE REMOVED
	DCA	ROWPTR2		SAVE FOR LATER USE
/
	LDI	-1		SET POINTER JUST BEFORE ROW SLOT
	TAD	ROWPTR		...
	DCA	TXR2		...
	TAD	ROWPTR		SET POINTER TO NEXT ROW
	DCA	TXR1		...
	TAD	LASTROW		GET ADDRESS OF LAST ROW IN TABLE
	CMA			NEGATE AND SUBTRACT FROM
	TAD	ROWPTR		CURRENT ROW ADDRESS
	DCA	CNTR		SET LOOP COUNTER FOR MOVING ROW TABLE
	JMP	2F		JUMP INTO END OF LOOP (IN CASE LAST ROW)
/
/	LOOP HERE COLLAPSING THE ROW TABLE UP ON ITSELF
/
1H	TADI	TXR1		MOVE UP A WORD
	DCAI	TXR2		...
2H	ISZ	CNTR		MORE WORDS TO MOVE?
	JMP	1B		YES: LOOP ON THEM
/
	TAD	ROWPTR2		GET ADDRESS OF REMOVED ROW
	DCAI	LASTROW		SET AS LAST ROW IN TABLE
	LDI	04000		MARK LAST ROW NOW AS NOT ESTABLISHED
	DCAI	ROWPTR2		...SINCE IT DOESN'T EXIST NOW
	EJECT
/
/ NOW POSITION CURSOR ON SCREEN FOR DELETE LINE FUNCTION
/ NOTE THAT ROW AND COLUMN MUST BE SET PROPERLY FOR VCM DELETE FUNCTION
/
	TAD	ROWPTR		POSITION SCREEN CURSOR AT 'ROWPTR'
	JMS	POSROW		...
	TAD	=X:DEL		DELETE CURRENT ROW FROM SCREEN
	JMSI	EXTER		...
	JMS	RESCOL		RESTORE ROW AND COLUMN NOW
	.RET	RMVLN		ALL DONE HERE
	TITLE	DELETE SCREEN
/
/	HERE TO DELETE THE ENTIRE SCREEN.
/
DELSCR	JMS	NOCOM		NOT ALLOWED IN COMMAND MODE
/
/	NOW DO THE DELETE SCREEN FUNCTION
/	MERGE HERE FROM ABORT ON 'TOF' AND 'BOF' FUNCTIONS
/
SCRFIL	JMS	FILSCR		FILL UP THE SCREEN NOW
	JMP	DOSCRN		RESTORE SCREEN NOW (AC=0, NO SPECIAL VIDEO)
/
/	COME HERE ON STARTUP. WE FILL UP THE SCREEN AND THEN JUMP
/	BACK INTO THE INITIALIZATION CODE IN ORDER TO PROCESS
/	THE VERSION NUMBER (IF PRESENT).
/
STARTUP	JMS	FILSCR		FILL UP THE SCREEN
	TAD	=X:INIT+04000	GOOD TIME TO INITIALIZE DISPLAY TERMINAL
	JMSI	EXTER		...(+4000 TO DEFEAT CHECK ON 'SCROFF')
	JMPX	VERPRO		OFF TO PROCESS VERSION NOW
/
/	SUBROUTINE TO FILL UP THE SCREEN BY ZEROING SCREEN AND THEN
/	MAKING REPEATED CALLS TO 'BLINI' TO BRING IN THE NEW ROWS.
/
FILSCR	.SUB	25
	LDI	04000		TURN SCREEN I/O OFF NOW
	DCA	SCROFF		...
/
/	NOW ROLL IN 'ROWSIZ' ROWS TO THE SCREEN.
/	NOTE:	'STEMP' USED AS A ROW POINTER HERE (IT'S SAFE)
/
	TAD	ROWSIZ		GET CURRENT ROW SIZE
	CMA			NEGATE AND SET AS
	DCA	ROWCTR		LOOP COUNTER (+1 TO SET UP DUMMY ROW TOO)
	TAD	ROWTAB		SET POINTER NOW TO FIRST ROW
	DCA	STEMP		...
/
/	LOOP HERE TO ROLL IN THE NEW ROWS
/	CLEAR THE ROW-ESTABLISHED FLAG SO THAT 'BLINI' FINDS THE CORRECT
/	ROW TO FILL IN.
/
1H	TADI	STEMP		GET ADDRESS OF CURRENT ROW
	DCA	TEMP		POINT AT LENGTH/STATUS WORD
	LDI	04000		MARK ROW AS UNESTABLISHED NOW
	DCAI	TEMP		...
	ISZ	ROWCTR		MORE ROWS NEEDED?
	JMP	*+2		YES: KEEP GOING
	.RET	FILSCR		ALL DONE HERE
/
	JMS	BLINI		ROLL IN NEW ROW AT BOTTOM OF SCREEN
	INC	STEMP		STEP POINTER TO NEXT ROW NOW
	JMP	1B		KEEP GOING
	TITLE	RESTORE SCREEN FUNCTION
/
/	HERE FOR RESTORE SCREEN. THIS CAN BE CALLED ANYTIME WE NEED TO
/	RESTORE THE SCREEN.
/
/	ON ENTRY, AC IS 0 TO AVOID DISPLAYING MODIFIED LINES IN SPECIAL
/	VIDEO, AND IS 0400 TO ALLOW THEM TO BE DISPLAYED.
/
DISMOD	TAD	=0400		SET TO DISPLAY MODIFIED LINES
DOSCRN	JMS	RESCRN		RE-DISPLAY SCREEN
	JMP	HOME		ALL DONE HERE
/
/	SUBROUTINE TO PERFORM ACTUAL SCREEN RESTORE FUNCTION
/
RESCRN	.SUB	21
	DCA	SHOWMOD		SAVE SWITCH SETTING
	DCA	SCROFF		ENSURE SCREEN I/O SWITCHED BACK ON
	TAD	=X:CLSC		CLEAR SCREEN FOR AESTHETIC REASONS
	JMSI	EXTER		...
	TAD	ROWTAB		SET POINTER TO START OF ROW TABLE
	DCA	ROWPTR		...
/
/	LOOP HERE RESTORING LINES TO THE SCREEN.
/	NOTE THAT WE MUST BE CAREFUL NOT TO DO A CR/LF AT THE END OF THE LINE
/	UNLESS WE KNOW ANOTHER LINE IS THERE. WHY? BECAUSE IF WE DO A CR/LF
/	AFTER THE LAST LINE ON THE SCREEN, SOME VIDEO TERMINALS WILL
/	SCROLL UP AND DROP THE TOP LINE.
/
1H	TADI	ROWPTR		GET THE NEXT ENTRY IN THE ROW TABLE
 	JMS	PRLINE		OUTPUT LINE TO SCREEN
	INC	ROWPTR		STEP ROW POINTER FOR NEXT TIME
	JMS	ROWPST		GET STATUS OF THAT ROW
	SPA CLA			HAS THIS LINE BEEN ESTABLISHED?
	JMP	2F		NO: SO ALL DONE HERE
/
	TAD	=X:CRLF		YES: SO MOVE TO NEXT LINE ON SCREEN NOW
	JMSI	EXTER		...
	JMP	1B		AND LOOP BACK FOR IT
/
2H	DCA	SHOWMOD		RESET TO 0 (IN CASE 'PRLINE' CALLED DIRECTLY)
	.RET	RESCRN		NO: SO ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO OUTPUT A LINE TO THE TERMINAL. ADDRESS-1 OF
/	LINE TO OUTPUT IS IN THE AC ON ENTRY.
/	SUBROUTINE ALSO GENERATES SPECIAL/NORMAL VIDEO CODES AT
/	START/END OF EACH LINE DEPENDING UPON FLAG SETTING IN STATUS BIT
/
/	ALSO, IF 'SHOWMOD' IS SET TO 400, DISPLAY MODIFIED LINES TOO.
/
$PRLINE	SUB
	DCA	TXR1		SAVE POINTER TO ROW
	TAD	TXR1		COPY POINTER TO COUNT FIELD
	DCA	PRPTR		...
	TADI	PRPTR		GET THE ROW COUNT
	AND	=LMASK		ISOLATE THE COUNT FIELD
	CMA			NEGATE AND SET AS A LOOP COUNT
	DCA	PRCNTR		...
/
/	CHECK FOR MODIFIED FLAGS AND DISPLAYING MODIFIED FLAGS
/
	TADI	PRPTR		GET STATUS REGISTER
	AND	SHOWMOD		TEST FOR MODIFIED LINE
	SZA CLA			IS THIS A MODIFIED LINE & ARE WE SHOWING THEM?
	TAD	=X:SPV1-X:NMV	YES: SO SET FOR VIDEO MODE 1
	TAD	=X:NMV		NO: SO SET FOR NORMAL VIDEO
	JMSI	EXTER		OUTPUT THAT CODE
/
/	NOW CHECK TO SEE IF THE CURRENT LINE HAS BEEN MARKED.
/
	TADI	PRPTR		REGET THE STATUS REGISTER AGAIN
	RTL			SHIFT MARK CONDITION TO AC0
	SMA CLA			IS THIS A MARKED LINE?
	JMP	4F		NO: SO NOTHING TO DO
	TAD	=X:SPV2		YES: OVERRIDE PRIOR VIDEO WITH MODE 2 VIDEO!
	JMP	3F		JUMP INTO LOOP BELOW (COUNT COULD HAVE BEEN 0)
/
/	LOOP HERE OUTPUTTING CHARACTERS TO THE VCM FILE
/
2H	TADI	TXR1		NEXT CHARACTER FROM ROW
3H	JMSI	EXTER		OUTPUT IT
4H	ISZ	PRCNTR		TEST LOOP COUNTER
	JMP	2B		LOOP BACK NOW
	TAD	=X:NMV		ALWAYS RESET BACK TO NORMAL VIDEO MODE
	JMSI	EXTER		AT END OF LINE
	TADI	PRPTR		GET STATUS WORD
	JMS	ENDCK		CHECK FOR END OF ROW AND NO-CRLF BIT SET
	RET	PRLINE		ALL DONE HERE
/
/	SUBROUTINE TO CHECK WHETHER THE CURRENT ROW HAS THE NO-CRLF
/	STATUS BIT SET. IF SO, WE GENERATE THE END-OF-ROW GRAPHIC
/	CHARACTER
/
ENDCK	.SUB	9
	RAL			SHIFT NO-CRLF BIT TO AC0
	SMA CLA			SKIP IF NO-CRLF BIT IS SET
	.RET	ENDCK		ALL DONE HERE
	TAD	=X:END		SET: SO FLAG WITH SPECIAL GRAPHIC
	JMSI	EXTER		...
	TAD	=X:BKSP		BACKSPACE NOW OVER THE CHARACTER
	JMSI	EXTER		SINCE IT DOES NOT REALLY 'EXIST'
	.RET	ENDCK		ALL DONE HERE
	TITLE	MARK/UNMARK ROW
/
/	HERE TO MARK/UNMARK A ROW FOR SUBSEQUENT PICKUP.
/	WE MARK THE ROW BY SETTING THE FLAG BIT, THEN WE DROP THE
/	CURSOR DOWN ONE ROW, MAKING IT CONVENIENT TO MARK ROWS
/	QUICKLY. ROUTINE ALSO REMOVES THE 'NO-CRLF' AND 'MODIFIED'
/	STATUS BITS
/
MKROW	TAD	=01000		SET TO MARK THIS ROW
UNMKROW	DCA	FLAG		SET TO CLEAR THIS ROW
	JMS	NOCOM		DO NOT ALLOW MARK FUNCTION IN COMMAND MODE
	JMS	ROWSTAT		GET STATUS WORD
	AND	=03400.XO.-1	TRIM OFF OLD BITS
	TAD	FLAG		ADD IN NEW SETTING (ON/OFF)
	DCAI	TEMP		AND STORE IT BACK
	DCA	COL		SET FOR COLUMN 0 ON LINE
	JMSI	EXTER		POSITION CURSOR
	TADI	ROW		GET THE ROW WE JUST MARKED
	JMS	PRLINE		REDISPLAY LINE WITH VIDEO ENHANCEMENT
	TAD	=X:EOL		ENSURE NO CHARACTERS FURTHER ON LINE
	JMSI	EXTER		...
	JMP	CDOWN		END UP WITH CURSOR DOWN
	TITLE	PICKUP ROUTINE
/
/	THIS IS THE BLOCK PICKUP ROUTINE. FUNCTION HERE IS TO FIND
/	ALL MARKED ROWS IN THE FILE AND MOVE THOSE ROWS INTO THE
/	BLOCK SAVE BUFFER. THIS BUFFER IS 1 OS/8 BLOCK LONG IN MEMORY
/	BUT WILL MOVE OUT ONTO THE SYSTEM AREA OF THE DISK IN A .TM
/	FILE IF WE HAVE MORE THAN 384 CHARS IN THIS SAVE AREA.
/
/	NOTE THAT 'ABMARK' AND 'BEMARK' GREATLY OPTIMIZE THE SEARCH
/	FOR THE MARKED ROWS AND AVOID UNSUCCESSFUL SEARCHES FOR
/	THESE ROWS.
/
/	FIRST STEP IS TO SCROLL BACKWARDS UNTIL WE FIND THE FIRST
/	MARKED ROW IN THE FILE.
/
PICKUP	DCA	COL		SET FOR COLUMN 0
	TAD	ROWTAB		IN ROW 0
	DCA	ROW		...
	CDF	%*		TO CURRENT FIELD FOR A MOMENT
	AFIELD	%*		...
	TAD	=SAV1		RESET COROUTINE LINK FOR 'SAVEC'
	DCA	SAVECX+0	...
	DCA	BSVBLK		RESET VIRTUAL BLOCK AS A FLAG
	TAD	=BSBUF		RESET BUFFER POINTER TO FORCE
	DCA	BSPTR		...WRITE AT START OF BUFFER
	CDF	BUF		RESET BUFFER FIELD NOW
	AFIELD	BUF		...
/
/	NOTE THAT IF A MARKED ROW WAS DELETED WE DON'T KNOW ABOUT IT, SO TO
/	BE SURE, ALWAYS CHECK TO SEE IF WE HAVE REACHED THE TOP OR BOTTOM OF
/	THE FILE, ABMARK AND BEMARK ARE NOT INFALLIBLE GUIDES (BECAUSE
/	IF WE READ A 'BAD' FILE THE 'BEMARK' COUNT COULD GO NEGATIVE
/	AND RESULT IN A SPURIOUS COUNT).
/
0H	TAD	TOF		GET TOP OF FILE STATUS FLAG
	SNA CLA			IF AT TOP OF FILE, DEFINITELY ALL DONE
	TAD	ABMARK		COUNT OF MARKED ROWS
	SNA CLA			ANY ROWS IN ABOVE SCREEN BUFFER?
	JMP	2F		TOP OF FILE OR NO MARKED ROWS: CONTINUE
/
/	HERE WE HAVE AT LEAST ONE ROW IN THE ABOVE SCREEN BUFFER, SO
/	KEEP SCROLLING UNTIL WE FIND IT.
/
	LDI	04000		TURN OFF SCREEN I/O
	DCA	SCROFF		...
	JMS	DNSCRL		SCROLL DOWN ONE ROW
	JMP	0B		BACK TO SEE IF FOUND THE FIRST ONE YET
/
/	STARTING WITH THE FIRST ROW, SCAN FORWARD UNTIL A MARKED ROW IS
/	FOUND.
/
2H	JMS	ROWSTAT		STATUS/LENGTH OF THIS ROW
	SPA			REACHED END OF SCREEN YET?
	JMP	3F		YES: CHECK BELOW SCREEN BUFFER NOW
/
	CLL RTL			SHIFT THE MARK BIT TO AC0
	SPA CLA			IS THIS ROW MARKED?
	JMP	5F		YES: THIS ROW IS MARKED
/
	TAD	ROW		NO: GET CURRENT ROW ADDRESS
	CMA IAC			SUBTRACT FROM
	TAD	LASTROW		LAST ROW ADDRESS
	SNA CLA			ARE WE ON THE LAST ROW HERE?
	JMP	3F		YES: SCREEN IS DONE
/
	INC	ROW		NO: STEP TO NEXT ROW IN ROW TABLE
	JMP	2B		BACK TO CHECK IT OUT
/
/	HERE WHEN WE HAVE REACHED THE END OF THE SCREEN: ARE THERE ANY
/	MORE ROWS IN THE BELOW SCREEN BUFFER?
/
3H	CLA			REMOVE LENGTH/STATUS FROM AC
	TAD	BOF		GET BOTTOM OF FILE STATUS FLAG
	SNA CLA			IF AT BOTTOM OF FILE, DEFINITELY NO MORE ROWS
	TAD	BEMARK		GET COUNT OF BELOW SCREEN MARKED ROWS
	SNA CLA			ANY MARKED ROWS WAITING TO BE READ?
	JMP	8F		NO MARKED ROWS OR NOW AT BOTTOM OF FILE
/
	LDI	04000		TURN OFF SCREEN I/O
	DCA	SCROFF		...
	JMS	UPSCRL		YES: SO SCROLL UP ONE ROW
	JMP	2B		SEE IF JUST SCROLLED IN A MARKED ROW NOW
/
/	COME HERE WHEN WE HAVE FOUND A MARKED ROW.
/
5H	JMS	GLEN		GET LENGTH OF THE MARKED ROW
	CMA			1'S COMPLEMENT IN CASE NULL ROW
	DCA	RCNTR		STORE AS LOOP COUNTER
	TADI	ROW		SET ADDRESS-1 OF FIRST CHAR IN ROW
	DCA	ROWXR		...
	JMP	7F		JUMP INTO LOOP BELOW
/
/	LOOP HERE COPYING OVER CHARACTERS INTO THE BLOCK SAVE BUFFER
/
6H	TADI	ROWXR		NEXT CHARACTER FROM ROW
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SNA			SKIP IF NOT
	JMP	7F		YES: STRIP THE PAD CODES COMPLETELY
	RTL			NO: RESTORE CHARACTER
	JMS	SAVEC		PUT INTO BLOCK SAVE BUFFER
7H	ISZ	RCNTR		MORE CHARS IN THIS ROW?
	JMP	6B		YES: OFF TO STORE THEM
/
/	HERE AT END OF ROW
/
	TAD	=CR		END UP LINE WITH CR/LF LIKE AN ASCII FILE
	JMS	SAVEC		NO: 0 IS THE ROW SENTINEL
	TAD	=LF		...
	JMS	SAVEC		...
	TAD	ROW		GET ADDRESS OF THIS ROW
	JMS	RMVLN		REMOVE NOW FROM THE SCREEN
	TAD	ROW		SAVE ROW POSITION
	DCA	TXTROW		...
	JMS	BLINI		MOVE IN A NEW ROW AT SCREEN END
	JMP	2B		BACK NOW TO SCAN FOR MORE MARKED ROWS.
/
/	COME HERE WHEN WE HAVE MOVED IN THE LAST MARKED ROW.
/
8H	TAD	=EOF		EOF CODE IS SENTINEL ON BLOCK SAVE AREA
	JMS	SAVEC		...
	STL			WRITE OUT FINAL BLOCK IF NECESSARY
	JMS	RBSPTR		...
	TAD	TXTROW		RESTORE ROW POSITION OF LAST PICKED UP ROW
	DCA	ROW		...
	JMS	FLAGLN		FLAG CURRENT ROW FOR 'DELETION' ABOVE
	DCA	BEMARK		(RESET TO 0 IN CASE COUNT GOT OFF FROM DELETE
	DCA	ABMARK		OF MARKED ROWS)
	TAD	=07700-07610	RESET POSSIBLE 'MARK-ALL-LINES' COMMAND'
/
/ MERGE HERE FROM 'M' COMMAND TO SET MARK-ALL-LINES CONDITION
/
MALL,	TAD	=07610		SET TO MARK ALL SCROLLED LINES
	CDF	%MARKALL	ADJUST DATA FIELD
	DCAI	=MARKALL	STORE APPROPRIATE INSTRUCTION THERE
	CDF	BUF		RESET TO MAIN DATA FIELD
	JMPI	PSETX		ALL DONE HERE
/
/ HERE FOR THE 'M' COMMAND. SET STATUS TO MARK ALL SCROLLED LINES
/
M:CMND	JMS	EXCOM		EXIT COMMAND MODE, RESTORE TOP ROW
	JMP	MALL		BACK TO SET STATUS TO MARK ALL ROWS
	PART
	TITLE	PUTDOWN - BLOCK RESTORE ROUTINE
/
/	HERE TO PUT DOWN THE BLOCK SAVE AREA AT THE CURRENT CURSOR
/	POSITION. WHEN THE PUTDOWN KEY IS PRESSED, THE FIRST LINE
/	IN THE SAVE AREA IS PLACED IMMEDIATELY ABOVE THE LINE IN WHICH
/	THE CURSOR IS LOCATED. SUBSEQUENT LINES ARE THEN INSERTED
/	IN ORDER BELOW THAT INSERTED LINE.
/	NOTE THAT WE USE TLINO AND RMVLN RATHER THAN CALLING 'UPSCRL' TO AVOID
/	UNNECESSARILY READING IN THE BOTTOM LINE.
/
0H	JMS	TLINO		ROLL OFF THE TOP LINE
	TAD	ROWTAB		REMOVE THE TOP LINE FROM THE SCREEN
	JMS	RMVLN		...
/
/	INITIAL ENTRY TO THE PUTDOWN FUNCTION IS HERE
/
PUTDN	DCA	COL		SET COLUMN TO 0 NOW
	JMS	KCK		CHECK FOR NEW CHARACTER FROM KEYBOARD
	TADI	=KBUF		CHECK FOR KEYBOARD ABORT
	SZA CLA			SKIP IF KEYBOARD NOT STRUCK
	JMPI	PSETX		KEYBOARD STRUCK: SO ABORT NOW
	JMS	RESTC		GET CHARACTER FROM BLOCK SAVE AREA
	TAD	=-EOF		COMPARE WITH SENTINEL CODE
	SNA			IS THIS THE SENTINEL CODE ON THE SAVE AREA?
	JMP	4F		YES: SO ALL DONE HERE
/
	TAD	=EOF		NO: RESTORE THE CHARACTER
	DCA	DCHAR		AND SAVE IT
/
	TAD	ROW		INSERT A BLANK ROW ABOVE CURRENT ROW
	JMS	INSROW		...
	JMS	FLAGLN		FLAG CURRENT ROW
	TAD	DCHAR		GET SAVED CHARACTER
	JMP	2F		JUMP INTO LOOP BELOW
/
/	LOOP HERE RESTORING CHARACTERS FROM THE BLOCK SAVE AREA
/
1H	JMS	RESTC		GET NEXT CHARACTER FROM SAVE AREA
2H	TAD	=-CR		END OF THIS ROW?
	SNA			SKIP IF NOT
	JMP	1B		YES: IGNORE CARRIAGE RETURN
	TAD	=CR-LF		LINE FEED CODE?
	SNA			SKIP IF NOT
	JMP	0B		YES: SET UP FOR NEXT LINE NOW
	TAD	=LF-TAB		TAB CODE?
	SNA			SKIP IF NOT
	JMP	3F		YES: STORE EXPLICIT TAB CODE
	TAD	=TAB		RESTORE CHARACTER
	JMS	DISCHR		DISPLAY THIS CHARACTER
	JMP	1B		LOOP BACK FOR NEXT CHARACTER
/
/	HERE ON TAB CODE. MUST CALL 'RTAB' ROUTINE TO GENERATE PAD CODES
/
3H	JMS	RTAB		GENERATE THE PAD CODES NOW
	JMP	1B		LOOP BACK FOR NEXT CHARACTER
/
/	HERE AT END OF SAVE AREA. RESET POINTERS TO START OVER
/	AGAIN AT THE BEGINNING. NOTE TOO THAT IF WE READ ANYTHING FROM
/	THE PICKUP AREA, THE BOTTOM ROW OF THE SCREEN IS CURRENTLY
/	UNESTABLISHED, AND MUST BE RESET. IF WE READ NOTHING, HOWEVER,
/	THE BOTTOM ROW IS INTACT AND MUST BE LEFT ALONE.
/
4H	CLL			LINK = 0: NO WRITE NEEDED
	JMS	RBSPTR		RESET BUFFER POINTERS
	TADI	LASTROW		GET ADDRESS OF LAST ROW IN ROW TABLE
	DCA	TEMP		...
	TADI	TEMP		GET LENGTH/STATUS OF LAST ROW
	SPA CLA			DOES THE LAST ROW EXIST?
	JMS	BLINI		NO: SO TRY AND READ A ROW IN NOW
	JMPI	PSETX		ALL DONE HERE

	TITLE	SAVEC - SAVE CHAR IN BLOCK BUFFER
/
/	HERE TO SAVE THE CHARACTER IN THE AC IN THE BLOCK SAVE BUFFER
/	NOTE THAT WE ONLY GO TO THE DISC IF THE BUFFER OVERFLOWS. THIS
/	MAKES IT MORE CONVENIENT FOR USERS WITH WRITE-LOCKED SYSTEM DEVICES
/	(AS WITH ETOS AND SOME OTHER TIME-SHARE SYSTEMS).
/
SAVEC	.SUB	8
	DCA	PUTC		SAVE CHARACTER TO GO OUT
SAVECX	SUB	SAV1		CO-ROUTINE LINKAGE
	.RET	SAVEC		ALL DONE HERE
/
/	HERE TO STORE THE FIRST CHARACTER POSITION INTO THE BUFFER
/
SAV1	TAD	PUTC		GET THE CHARACTER
	DCAI	BSPTR		STORE INTO BLOCK SAVE BUFFER
	INC	BSPTR		STEP POINTER TO NEXT WORD
	JMS	SAVECX		EXIT NOW
/
	TAD	PUTC		DO THE SECOND CHARACTER
	DCAI	BSPTR		AND STORE INTO THE BUFFER
	JMS	SAVECX		EXIT NOW
/
	LDI	-1		POINT BACK AT FIRST WORD OF PAIR
	TAD	BSPTR		...
	JMS	PUTB		PUT THE BYTE IN NOW
	JMS	SAVECX		EXIT NOW
/
	STL			SET FOR WRITE IF AT END OF BLOCK
	JMS	BSIO		CHECK IT OUT NOW
	JMP	SAV1		BACK NOW FOR FIRST CHARACTER
	EJECT
/
/	SUBROUTINE TO RESET THE BLOCK SAVE POINTERS TO RE-READ
/	THE BLOCK SAVE AREA.
/	DID WE WRITE ANY BLOCKS TO THE DISC? IF NOT, JUST RESET THE
/	POINTER TO RE-READ FROM THE START OF THE BLOCK. THIS AVOIDS
/	ALL DISC I/O. OTHERWISE, IF WE EVER WROTE A BLOCK, MUST WRITE
/	OUT THE CURRENT BLOCK IF THE LINK WAS 1 ON ENTRY. IF THE LINK
/	WAS 0 ON ENTRY, THEN WE NEVER HAVE TO WRITE THE BLOCK
/
RBSPTR	.SUB	35
	CDF	%*		<LINK> TO CURRENT FIELD FOR A MOMENT
	AFIELD	%*		...
	TAD	=BSBUF		<LINK> RESET POINTER TO START OF BUFFER
	DCA	BSPTR		...
	TAD	BSVBLK		<LINK> BLOCK SAVE VIRTUAL BLOCK NUMBER
	SNA CLA			<LINK> HAVE WE WRITTEN A BLOCK YET?
	JMP	0F		NO: SO NOTHING TO WRITE THEN
/
	TAD	=BSBUFE		<LINK> RESET POINTER TO FORCE 'BSIO'
	DCA	BSPTR		<LINK> ...TO WRITE OUT BLOCK
	SZL			ARE WE TO WRITE OUT THIS BLOCK?
	JMS	BSIO		YES: WRITE OUT THE BLOCK
	CDF	%*		(BSIO RESETS 'BUF' FIELD ON EXIT)
	TAD	BSVBLK		SAVE FULL FILE LENGTH
	DCA	BSLEN		...FOR SUBSEQUENT 'C' COMMAND
	DCA	BSVBLK		RESET VIRTUAL BLOCK BACK TO 0
	TAD	=BSBUFE		RESET POINTER AGAIN TO FORCE INITIAL READ
	DCA	BSPTR		...
	TAD	=SREAD-SAVFST	SET TO READ BLOCK ON CO-ROUTINE LINKAGE
0H	TAD	=SAVFST		SET TO READ FIRST CHAR ON CO-ROUTINE LINKAGE
	DCA	RESTCX+0		...
	CDF	BUF		RESET BUFFER FIELD NOW
	AFIELD	BUF		...
	.RET	RBSPTR		ALL DONE HERE
	TITLE	RESTC - RESTORE CHAR FROM BLOCK BUFFER
/
/	HERE TO EXTRACT THE NEXT CHARACTER OUT OF THE BLOCK SAVE BUFFER
/	NOTE THAT CO-ROUTINE LINKAGE AT 'RESTCX' WILL BE SET UP TO
/	READ FROM A PRIOR 'SAVE.TM' FILE IF A LOOKUP COMMAND
/	FOUND SUCH A FILE ON THE SYSTEM DEVICE.
/
RESTC	.SUB	8		ENTRY POINT
RESTCX	SUB	SAVFST		CO-ROUTINE LINKAGE
	AND	=0377		TRIM DOWN TO 8 BITS NOW
	.RET	RESTC		ALL DONE HERE
/
/	HERE FOR THE FIRST CHARACTER POSITION
/
SAVFST	TADI	BSPTR		GET THE WORD WITH THE CHAR
	JMS	RESTCX		RETURN IT
/
	INC	BSPTR		STEP TO NEXT WORD
	TADI	BSPTR		GET THE WORD WITH THE SECOND CHAR
	JMS	RESTCX		RETURN IT
/
	LDI	-1		POINT BACK NOW BEFORE HIGH NIBBLE
	TAD	BSPTR		...
	JMS	GETB		GET THE THIRD BYTE AS TWO NIBBLES
	JMS	RESTCX		ALL DONE HERE
/
/	ALSO COME HERE INITIALLY TO READ FROM THE BLOCK SAVE BUFFER
/	AFTER ONE HAS BEEN SAVED ON THE DISC.
/
SREAD	CLL			IF AT END OF BLOCK, SET TO READ NEW BLOCK
	JMS	BSIO		...
	JMP	SAVFST		BACK FOR FIRST CHARACTER NOW
	TITLE	BLOCK SAVE BUFFER READ/WRITE
/
/	COME HERE AFTER READING/WRITING THE THIRD OS/8 PACKED CHARACTER
/	POSITION.
/
/			LINK = 0 TO READ IF AT END OF BUFFER
/			LINK = 1 TO WRITE IF AT END OF BUFFER
/
	CDF	BUF		RESET FIELD ON EXIT
BSIO	SUB
	CDF	%*		RESET CURRENT FIELD HERE
	AFIELD	%*		...
	TAD	7F		GET OS/8 DRIVER FUNCTION WORD
	AND	=03777		TRIM OFF THE R/W BIT
	SZL			READING OR WRITING?
	TAD	=04000		WRITING: SET THE BIT ON
	DCA	7F		STORE FUNCTION WORD BACK
/
	INC	BSPTR		STEP BUFFER POINTER
	TAD	BSPTR		GET BUFFER POINTER
	TAD	=-(BSBUFE+1)	COMPARE WITH END OF BUFFER?
	SZA CLA			ARE WE PAST END OF BUFFER
	JMP	BSIO-2		NO: RESET FIELD AND EXIT
/
	TAD	=BSBUF		YES: RESET BUFFER POINTER
	DCA	BSPTR		...
/
	TAD	BSSBLK		GET STARTING BLOCK NUMBER
	SZA CLA			HAVE WE EVER OPENED A TEMPORARY FILE?
	JMP	5F		YES: CONTINUE NOW
/
/	THIS IS THE FIRST TIME, AND WE MUST OPEN UP A TEMPORARY FILE FOR
/	THE BLOCK SAVE. WE NEVER CLOSE THE FILE-THAT WAY IT DISAPPEARS
/	AUTOMATICALLY WHEN WE EXIT.
/
/	IF A FILE IS BEING EDITED ON SYS, THE OPEN WILL FAIL AND WE
/	TREAT THIS JUST LIKE RUNNING OUT OF ROOM IN THE SAVE AREA.
/	'OPFILE' IS INSTRUCTION MODIFIED BY INITIALIZATION CODE TO AN LDI 3
/	(FOR A USER ENTER FUNCTION) IF THE OUTPUT FILE IS NOT ALSO ON THE
/	SYSTEM DEVICE).
/
OPFILE	JMP	BSERR		#CHANGED TO 'LDI 3' IF AVAILABLE#
	JMS	OTEMP		...
/
/	COME HERE TO READ/WRITE THE NEXT BLOCK IN THE BUFFER
/
5H	TAD	BSMLEN		GET MINUS FILE LENGTH
	TAD	BSVBLK		COMPARE WITH VIRTUAL BLOCK IN FILE
	SNA CLA			IS THERE ROOM FOR THIS NEW BLOCK?
	JMP	BSERR		NO: (MUST BE WRITE OPERATION)
/
	TAD	BSVBLK		REGET VIRTUAL BLOCK NUMBER
	INC	BSVBLK		STEP BLOCK NUMBER FOR NEXT TIME
	TAD	BSSBLK		ADD IN STARTING BLOCK NUMBER
	DCA	8F		STORE INTO DRIVER AREA
/
	ROOM	11
6H	JMS	$07607		READ/WRITE THE BUFFER
7H	DC	0200+(%BSBUF.LS.3)	ONE BLOCK
	DC	BSBUF		BLOCK SAVE BUFFER ADDRESS
8H	DC	0		OS/8 BLOCK NUMBER
	SMA CLA			<1> SKIP IF FATAL I/O ERROR
	JMP	BSIO-2		<2> OK, OR NON-FATAL ERROR
/
	ROOM	4
	JMS	IOER		SIGNAL I/O ERROR TO USER
	JMP	BSIO-2		<1> IGNORE I/O ERROR AND RETURN
	JMP	6B		<2> REPEAT I/O OPERATION
/
/	SUBROUTINE TO OPEN UP EITHER A TEMPORARY OUTPUT FILE (AC=3), OR
/	TO LOOKUP AN EXISTING FILE (AC=2) FOR THE PICKUP TEXT.
/	DATA FIELD MUST BE %* ON ENTRY HERE
/
OTEMP	.SUB	20
	DCA	OSFUN		STORE 'USR' FUNCTION WORD (EITHER 2 OR 3)
	TAD	=TNAME		RESET POINTER TO FILE NAME
	DCA	BSSBLK		...
	LDI	1		DEVICE # 1 IS 'SYS:' DEVICE
	ROOM	8
	JMSX	NRUSR		CALL NON-RESIDENT USR
OSFUN	DC	0		FILE ENTER OR LOOKUP FUNCTION
BSSBLK	DC	0		POINTER TO FILENAME
BSMLEN	DC	0		REPLACED BY MINUS FILE LENGTH
	JMP	BSERR		<1> INDICATE BLOCK SAVE AREA FULL
	DCA	BSVBLK		<2> RESET VIRTUAL BLOCK TO 0
	.RET	OTEMP		ALL DONE HERE
/
TNAME	TEXT	/PIKUPATM/	TEMPORARY FILE FOR BLOCK SAVE
	TITLE	BLOCK SAVE CLOSE/OPEN COMMANDS
/
/ COME HERE AFTER A COMMAND MODE 'C' COMMAND TO CLOSE OUT THE
/ CURRENT BLOCK SAVE BUFFER. THERE IS REALLY NOTHING TO DO IF
/ THE FILE WAS LOOKED UP. IF ENTERED, WE MUST ISSUE THE OS/8 CLOSE
/ FUNCTION TO CREATE A PERMAMENT FILE.
/
C:CMND	CDF	%*		TO CURRENT FIELD
	AFIELD	%*		...
	LDI	-2		WHAT WAS THE LAST OS/ 8 FUNCTION?
	TAD	OSFUN		...
	SNA CLA			SKIP IF ENTER FUNCTION
	JMP	NOCLOS		ELSE LOOK UP FUNCTION: NO CLOSE NEEDED
	TAD	BSLEN		GET BLOCK LENGTH
	SZA CLA			DID WE WRITE ANY BLOCKS?
	JMP	1F		YES: SO DONE HERE
/
	INC	BSLEN		NO: MARK LENGTH AT 1 BLOCK
	TAD	=BSBUFE		SET POINTER TO FORCE WRITE
	DCA	BSPTR		...
	STL			WRITE OUT THE ONLY BLOCK NOW
	JMS	BSIO		...
/
1H	LDI	1		DEVICE IS SYSTEM DEVICE
	CDF	%*		ENSURE CURRENT FIELD SET
	ROOM	8
	JMSX	NRUSR		CALL 'USR' ROUTINE
	DC	4		CLOSE OPERATION
	DC	TNAME		LOCATION OF FILENAME
BSLEN	DC	0		LENGTH OF OUTPUT FILE
	JMP	BSERR		<1> ERROR ON BLOCK SAVE
NOCLOS	DCA	BSSBLK		<2> CLEAR BLOCK # TO FORCE NEW ENTER
	DCA	OSFUN		RESET OS/8 FUNCTION WORD FOR NEXT CLOSE
	DCA	BSLEN		CLEAR LENGTH FOR NEXT CLOSE OPERATION
	INC	TNAME+2		STEP FROM PIKUPA TO PIKUPB ETC.
/
	CDF	BUF		RESET DATA FIELD
	AFIELD	BUF		...
	JMS	EXCOM		EXIT FROM COMMAND MODE
/
/ COME HERE AFTER OUTPUTTING 'PICKUP/PUTDOWN ERROR' MESSAGE TO
/ RESET EVERYTHING ASSOCIATED WITH THE PICKUP/PUTDOWN FUNCTION
/
CCMD2	TAD	=EOF		FIND EOF CODE AT START OF BUFFER NOW
	DCAI	=BSBUF		...
	DCA	BSVBLK		ZERO VIRTUAL BLOCK FOR 'RBSPTR' CALL
	JMS	RBSPTR		RESET POINTER AND CO-ROUTINE LINKAGE
	JMP	IDLP		ALL DONE WITH COMMAND
/
/	HERE FOR THE COMMAND MODE 'L' COMMAND WHICH LOOKS UP A SPECIFIED
/	PICKUP FILE WITH THE NAME 'PIKUP' PLUS THE LETTER WHICH IMMEDIATELY
/	FOLLOWS THE 'L' COMMAND.
/
L:CMND	INC	COL		STEP COLUMN NUMBER (CHAR AFTER 'L')
	JMS	LOADC		GET LETTER FOR PICKUP FILE
	AND	=037		TRIM TO 5-BIT ASCII (U/L CASE)
	TAD	="P@		'P' IN LEFT BYTE
	CDF	%*		SET CURRENT FIELD NOW
	AFIELD	%*		...
	DCA	TNAME+2		SET PICKUP FILE NAME
	LDI	2		SET TO LOOKUP THE PICKUP FILE
	JMS	OTEMP		...
	INC	BSVBLK		SET NON-ZERO FOR 'RBSPTR' CALL
	CLL			LINK=0 TO AVOID WRITING ANYTHING
	JMS	RBSPTR		RESET 'BSPTR', CO-ROUTINE LINKAGE, DF
	JMP	RESTOR		OFF NOW TO RESTORE TOP ROW
	AFIELD	BUF		(DATA FIELD RESET FOR PAGE8)
/
/ COME HERE ON ALL CASES OF AN ERROR ON PICKUP/PUTDOWN. MUST RESET
/ ALL POINTERS SO THAT SUBSEQUENT PUTDOWN OPERATION WILL ALWAYS FAIL
/ (ALSO WILL RESET AFTER CONTINUOUS REPLACEMENT FUNCTION--BUT THIS
/ IS CERTAINLY ALL RIGHT)
/
BSERR	TAD	=BSMSG		INDICATE BLOCK SAVE FUNCTION FAILED
/
/ MERGE HERE FROM REPLACEMENT FUNCTION WITH MESSAGE ADDRESS
/ IN AC TO CALL 'STROUT' AND THEN RETURN TO THE MAIN IDLE LOOP
/
STRIDL	JMS	STROUT		...
	JMP	CCMD2		END UP NOW WITH CLOSE ROUTINE
	TITLE	I/O ERROR POINT
/
/	COME HERE ON ALL I/O ERRORS. INDICATE AN ERROR OCCURRED, THEN
/	ASK THE USER IF THEY WANT TO REPEAT THE OPERATION OR JUST
/	SKIP IT. REPLIES FROM USER ARE:
/
/		^C	QUIT AND RETURN TO OS/8
/		N	1ST RETURN:	DF=0, JUST AS IF IT WORKED
/		OTHER	2ND RETURN: 	DF=0, TRY THE OPERATION AGAIN
/
	ROOM	6
	INC	IOER		HERE TO TRY THE OPERATION AGAIN
IOER	SUB
	TAD	=IOMSG		INFORM USER OF I/O ERROR
	JMS	STROUT		...(ALSO RESETS FIELD TO 'BUF')
	JMSI	PKBD		READ KEYBOARD DIRECTLY (BYPASS VCM)
	JMS	FOLD		FOLD OVER POSSIBLE LOWER CASE LETTER
	CDF	%*		RESET DATA FIELD FOR EXIT
	TAD	=-CTLC		^C?
	SNA			SKIP IF NOT
	JMP	QUIT		...
	TAD	=CTLC-'N	'N' REPLY?
	SNA CLA			SKIP IF NOT
	RET	IOER		DON'T REPEAT THE OPERATION
	JMP	IOER-2		TAKE 2ND RETURN TO REPEAT OPERATION
	TITLE	MISCELLANEOUS ROUTINES
/
/	SUBROUTINE TO ENSURE THAT CURSOR IS LOCATED WITHIN THE CURRENT
/	ROW. ONE ADDITIONAL TASK IS TO CHECK THAT THE CURSOR IS NOT BE LOCATED
/	ON A PAD CHARACTER WHICH FOLLOWS A TABULATION CODE.
/
INROW	.SUB	20
1H	JMS	LOADC		LOAD CHARACTER UNDER CURSOR
	SNA			ARE WE AT THE END OF THE ROW?
	JMP	2F		<1> AT OR PAST END OF ROW
	CLL RTR			TEST FOR PAD CODE (AC=0 NOW IF PAD)
	SZA CLA			SKIP IF SO
	.RET	INROW		ELSE ALL DONE HERE
/
/	ON PAD CODE MOVE CURSOR ONE POSITION TO THE LEFT.
/
	LDI	-1		DECREMENT CURRENT COLUMN POSITION
	TAD	COL		...
	DCA	COL		...
	INC	CFLAG		SET FLAG: CANNOT USE SIMPLE CURSOR MOVEMENT
	JMP	1B		LOOP BACK NOW
/
/	HERE WHEN PAST THE END OF THE ROW
/
2H	JMS	GLEN		GET CURRENT ROW LENGTH
	DCA	COL		SET AS NEW COLUMN POSITION
	.RET	INROW		ALL DONE (ROW CANNOT END WITH PAD CODE)
	EJECT	20
/
/	SUBROUTINE TO FOLD OVER LOWER CASE CHARACTERS TO UPPER CASE.
/	THIS ROUTINE WILL ONLY FOLD ALPHABETIC CHARACTERS
/
/	ON EXIT,	LINK = 0	WAS LOWER CASE
/			LINK = 1	WAS NOT LOWER CASE
/
FOLD	.SUB	14
	TAD	=-('Z+040)-1	TEST FOR LOWER CASE A-Z (TO LEAVE BRACES/TILDE
	CLL			ETC. ALONE)
	TAD	='Z-'A+1	...
	SZL			SKIP IF NOT LOWER CASE A-Z
	TAD	=-040		LOWER CASE ALPHA: FOLD TO UPPER CASE
	TAD	='A+040		ELSE RESTORE ORIGINAL CHARACTER
	.RET	FOLD		RETURN CHARACTER IN AC
	EJECT	20
/
/ SUBROUTINE TO LOAD THE CHARACTER UNDER THE CURSOR INTO THE AC.
/ ON EXIT, LEAVES CHARACTER IN AC, AND POINTER IN 'CHARP'
/ IF CURSOR IS AT END OF ROW, THE AC IS RETURNED CLEAR.
/
LOADC	.SUB	12
	LDI	1		SET TO SKIP OVER COUNT/STATUS BYTE
	TADI	ROW		GET ADDRESS OF COUNT/STATUS BYTE
	TAD	COL		ADD IN CURRENT COLUMN POSITION
	DCA	CHARP		SAVE POINTER INTO BUFFER
	ROOM	4
	JMS	ROWCK		ARE WE AT THE END OF THE ROW
	.RET	LOADC		<1> YES: SO RETURN AC = 0
	TADI	CHARP		<2> NO: GET CHARACTER UNDER CURSOR
	.RET	LOADC		RETURN WITH CHAR IN AC
	EJECT	20
/
/	SUBROUTINE TO GET THE LENGTH OF THE CURRENT LINE INTO THE AC.
/	LEAVES A POINTER TO THE COUNT/STATUS BYTE IN 'TEMP'.
/
$GLEN	.SUB	6
	JMS	ROWSTAT		GET ROW STATUS/LENGTH
	AND	=LMASK		ISOLATE THE LENGTH FIELD OF THE WORD
	.RET	GLEN		RETURN IT IN THE AC
	EJECT	20
/
/	SUBROUTINE TO CHANGE THE LENGTH OF THE CURRENT LINE BASED UPON
/	THE NEW LINE LENGTH IN THE AC. LEAVES STATUS FIELD UNCHANGED.
/
PLEN	.SUB	10
	DCA	TEMP1		SAVE NEW LENGTH FIELD
	JMS	ROWSTAT		GET COUNT/STATUS FIELD
	AND	=(04000+LMASK).XO.-1	STRIP COUNT AND MARK ESTABLISHED
	TAD	TEMP1		ADD IN THE NEW COUNT FIELD
	DCAI	TEMP		STORE IT BACK
	.RET	PLEN		ALL DONE HERE
	EJECT	20
/
/	SUBROUTINE TO TEST FOR BEING AT THE END OF THE CURRENT ROW:
/
/		ROOM	4
/		JMS	ROWCK		CALL TEST ROUTINE
/		<RETURN>		<1> WAS AT END OF ROW
/		<RETURN>		<2> WAS NOT AT END OF ROW
/
	ROOM	10		ROUTINE MUST LIE ON A PAGE
ROWCK	DC	0		RETURN ADDRESS IS CHANGED
	JMS	GLEN		GET CURRENT LINE LENGTH
	CMA IAC			NEGATE AND COMPARE WITH
	TAD	COL		CURRENT COLUMN POSITION
	SPA CLA			SKIP IF AT OR PAST END OF ROW
	INC	ROWCK		ELSE STEP TO SECOND RETURN
	JMPI	ROWCK		ALL DONE HERE
	EJECT	20
	TITLE	FLAG CURRENT ROW
/
/ SUBROUTINE TO FLAG THE CURRENT ROW AS HAVING BEEN MODIFIED.
/ THIS IS USED TO ESTABLISH THE AUDIT TRAIL FEATURE.
/ IF THE CURRENT ROW ALREADY HAS BIT 3 SET, THEN THE ROW HAS
/ ALREADY BEEN TAGGED AND THERE IS NOTHING TO DO.
/
/ NOTE THAT WE MUST BE CAREFUL NOT TO FLAG THE CURRENT ROW IF WE ARE
/ IN COMMAND MODE. OTHERWISE WHEN WE RESTORE THE TOP ROW, IT WILL
/ BE FLAGGED AS HAVING BEEN MODIFIED WHEN IN FACT IT HAS NOT.
/
FLAGLN	.SUB	12
	TAD	CMND		GET COMMAND MODE FLAG
	SZA CLA			ARE WE IN COMMAND MODE?
	.RET	FLAGLN		YES: SO RETURN NOW WITHOUT FLAGGING
	JMS	ROWSTAT		GET THE CURRENT ROW STATUS/LENGTH
	AND	=0400.XO.-1	REMOVE THE 'ROW-MODIFIED' BIT
	TAD	=0400		SET THE 'ROW-MODIFIED' BIT ON NOW
	DCAI	TEMP		AND STORE IT BACK
	.RET	FLAGLN		ALL DONE HERE
	TITLE	BUFFERED KEYBOARD INPUT
/
/	SUBROUTINE TO READ A CHARACTER FROM THE KEYBOARD. PRIMARILY,
/	THIS ROUTINE IS CALLED FROM THE INTERPRETER.
/	NOTE THAT THIS ROUTINE TAKES A CHARACTER FROM THE KEYBOARD
/	INPUT LINE BUFFER IF ONE IS AVAILABLE. IF THE BUFFER IS
/	EMPTY, IT CALLS 'KCK' TO BUFFER IN MORE CHARACTERS. NOTE
/	THAT THE 'KCK' ROUTINE IS CALLED FROM THE OUTPUT ROUTINE
/	AND ANYWHERE ELSE WHERE THE PROGRAM MIGHT BE TIED UP FOR
/	A SUBSTANTIAL AMOUNT OF TIME WHEN KEYBOARD INPUT IS
/	ALLOWED. BUFFERING THE KEYBOARD IN THIS MANNER PROVIDES
/	THE REQUIRED OVERLAPPED I/O WITHOUT THE NEED FOR ENABLING
/	INTERRUPTS.
/
/	THE TIMEOUT COUNTERS ARE USED TO REMOVE TARGET COLUMNING
/	FEATURE: IF MORE THAN APPROXIMATELY 500 MSEC PASS BY, WE
/	REMOVE TARGET COLUMNING (OTHERWISE, AFTER A PAUSE IT LOOKS
/	STRANGE IF THE CURSOR DOES NOT MOVE UP/DOWN PRECISELY)
/
KBD	SUB
	DCA	TEMP1		SET TIMEOUT COUNTERS
	TAD	=-8		FOR CLEARING TARGET COLUMNING
	DCA	TEMP2		...
/
0H	TADI	=KBUF		GET FIRST SLOT IN KEYBOARD BUFFER
	SNA			DO WE HAVE A CHARACTER HERE?
	JMP	3F		NO: MUST WAIT FOR ONE
	DCA	KCHAR		YES: SAVE THIS CHARACTER
/
/	COLLAPSE UP THE KEYBOARD BUFFER BY ONE SLOT AND MOVE
/	ALL SUBSEQUENT CHARACTERS UP FOLLOWED BY NEW SENTINEL
/	CODE.
/
	TAD	=KBUF-1		SET POINTER TO FIRST SLOT
	DCA	KXR1		...
	TAD	=KBUF		SET POINTER TO SECOND SLOT
	DCA	KXR2		...
/
/	LOOP HERE TO MOVE THE CHARS UP
/
1H	TADI	KXR2		GET A WORD
	SPA SNA			ZERO OR MAIN SENTINEL ON BUFFER?
	JMP	2F		YES: SO DONE HERE
	DCAI	KXR1		NO: STORE THE WORD
	JMP	1B		AND LOOP FOR NEXT
/
2H	CLA			INSTALL ZERO SENTINEL ON BUFFER
	DCAI	KXR1		...
	TAD	KCHAR		GET THE NEW CHARACTER
	RET	KBD		AND RETURN IT IN THE AC
/
/	HERE WHEN THE KEYBOARD BUFFER WAS EMPTY
/
3H	JMS	KCK		CHECK ON KEYBOARD
	ISZ	TEMP1		CHECK FIRST TIMER
	JMP	0B		LOOP BACK NOW
	ISZ	TEMP2		CHECK SECOND TIMER
	JMP	0B		LOOP BACK NOW
/
/	500 MSEC (VERY APPROX) PASSED BY, SO REMOVE TARGETING NOW
/
	TAD	COL		SET CURRENT COLUMN AS TARGET COLUMN
	DCA	TARCOL		...
	JMP	0B		AND LOOP BACK NOW
	EJECT
/
/	HERE TO CHECK ON THE KEYBOARD. IF THE FLAG IS NOT UP, WE RETURN
/	INSTANTLY. OTHERWISE WE MOVE THE CHARACTER INTO THE NEXT SLOT
/	IN THE BUFFER. IF THE BUFFER IS FULL WE TOSS THE CHARACTER
/	AND DO A TIMING CHECK FOR ESCAPED SEQUENCES.
/
/	THIS ROUTINE ALSO INTERCEPTS XON/XOFF SEQUENCES AND SETS
/	XFLAG TO 4000 IF XOFF IS FOUND, AND JUST CLEARS IT ON XON.
/
/	ROUTINE MUST <NOT> USE TEMPORARY STORAGE
/
KCK	.SUB	45
	IOS	3,1		IS THE KEYBOARD FLAG UP?
	.RET	KCK		NO: SO RETURN IMMEDIATELY
	JMS	RDCHR		READ THE CHARACTER
	DCA	KCHAR		SAVE IT
	TAD	=KBUF-1		SET POINTER TO KEYBOARD BUFFER
	DCA	KXR1		...
/
/	TEST FOR XON AND XOFF CODES IF 'VSTAT' BIT 0 = 1 (INITIALIZATION
/	CODE REMOVED THIS CHECK IF BIT 0 = 0
/
XONCK	TAD	KCHAR		GET THE CHAR WE JUST READ (NOP IF DISABLED)
	TAD	=-XOFF		XOFF CODE?
	SNA			SKIP IF NOT
	JMP	4F		YES: SET 'XFLAG' ON NOW
	TAD	=XOFF-XON	OR XON CODE HERE?
	SNA CLA			SKIP IF SOMETHING ELSE
	JMP	5F		OK, TURN 'XFLAG' OFF NOW
/
/	CHECK NOW FOR CONTROL/O WHICH INVERTS THE 'SCROFF' FLAG. IF SCREEN
/	I/O WAS ON, IT TURNS IT OFF. IF OFF, IT TURNS IT BACK ON.
/
CTLOCK	TAD	KCHAR		GET CHAR (NOP IF VSTAT BIT 1 = 0)
	TAD	=-CTRLO		WAS THIS A CONTROL/O CODE?
	SZA CLA			SKIP IF SO
	JMP	1F		ELSE JUMP AHEAD ON SOMETHING ELSE
	LDI	04000		YES: SO INVERT THE SCREEN I/O FLAG
	TAD	SCROFF		...
	DCA	SCROFF		...
	.RET	KCK		DO NOT STORE CONTROL/O INTO THE BUFFER
/
/	SEARCH HERE FOR AN EMPTY SLOT IN THE KEYBOARD BUFFER
/
1H	TADI	KXR1		NEXT SLOT IN BUFFER
	SNA			EMPTY SLOT?
	JMP	3F		YES: OFF TO INSERT CHARACTER
	SMA CLA			NO. ARE WE AT MAIN SENTINEL?
	JMP	1B		NO: SO KEEP LOOKING FOR FREE SLOT
/
/	HERE THE KEYBOARD BUFFER IS FULL.
/	TOSS THIS CHARACTER. WE COULD HAVE A PROBLEM HERE IF WE TOSS
/	AN ESCAPE CHARACTER FROM AN ESCAPE SEQUENCE. I.E. NEXT CHARACTER
/	(IF THE KEYBOARD BUFFER THEN EMPTIES) COULD BE READ AS A SINGLE
/	CHARACTER. CONVERSELY, WE COULD BE TOSSING THE SECOND CHARACTER
/	OF AN ESCAPE SEQUENCE. HOPEFULLY, HOWEVER, THE KEYBOARD BUFFER
/	IS LARGE ENOUGH THAT WE SHOULD NEVER OVERRUN IT.
/
	.RET	KCK		RETURN AS IF BUFFER EMPTY
/
/	HERE TO PLACE CHARACTER IN KEYBOARD BUFFER
/
3H	LDI	-1		POINT BACK TO EMPTY SLOT
	TAD	KXR1		...
	DCA	KXR1		...
	TAD	KCHAR		GET NEW CHARACTER
	DCAI	KXR1		AND STORE INTO KEYBOARD BUFFER
/
	.RET	KCK		ALL DONE HERE
/
/	HERE TO SET/CLEAR THE XON/XOFF FLAG
/
4H	LDI	04000		TURN FLAG ON WITH 'XOFF'
5H	DCA	XFLAG		TURN FLAG OFF WITH 'XON'
	.RET	KCK		ALL DONE HERE
/
/	SUBROUTINE TO READ CHARACTER AND NORMALIZE PARITY BIT. ASSUMES
/	THAT KEYBOARD FLAG IS UP
/
RDCHR	.SUB	5
	IOT	3,6		YES: READ IN THE CHARACTER
	AND	=0177		NORMALIZE THE PARITY BIT
	TAD	=0200		...
	.RET	RDCHR
/
/	SUBROUTINE TO OUTPUT CHARACTER IN THE AC DIRECTLY TO TERMINAL.
/	ROUTINE WILL HANG IF 'XFLAG' IS SET INDICATING THAT TERMINAL
/	HAS SENT AN XOFF CODE
/
SCROUT	.SUB	15
	DCA	TCHAR		SAVE CHARACTER
1H	JMS	KCK		CHECK ON KEYBOARD WHILE WAITING
	IOS	4,1		IS THE FLAG UP?
	JMP	1B		NO: SO WAIT FOR IT
	TAD	XFLAG		IS AN 'XOFF' IN EFFECT HERE?
	SPA CLA			SKIP IF NOT
	JMP	1B		YES: SO HANG UNTIL 'XON' RECEIVED
/
	TAD	TCHAR		REGET CHARACTER
	IOT	4,6		OUTPUT CHARACTER
	CLA			REMOVE FROM AC
	.RET	SCROUT		ALL DONE HERE
	EJECT
/
/	HERE TO CALL THE OUTPUT MODULE IN VCM. CHECK FOR SCREEN I/O
/	BEING OFF, AND ALSO CHANGE TAB CODE TO A PAD FUNCTION CODE
/	AND ANY OTHER CONTROL CODES MAKE THEM A X:CTRL CODE
/
/	TEMPORARY STORAGE SHOULD NOT BE USED
/
	CLA			CLEAR AC FOR EXIT
$XTER	SUB
	TAD	SCROFF		LOAD SCREEN ON/OFF FLAG
	SPA			IS SCREEN I/O OFF?
	JMP	XTER-2		YES: CLEAR AC AND RETURN NOW
/
	TAD	=-X:CTRL	COMPARE WITH LAST FUNCTION CODE
	SPA SNA			IS THIS A FUNCTION CODE?
	JMP	1F		YES: HANDLE FUNCTION CODE
/
	TAD	=X:CTRL-0377	DELETE CODE (INSERTED IN TRANSPARENT MODE)
	SNA			SKIP IF NOT
	JMP	1F		YES: SET FOR CONTROL CODE GRAPHIC THEN
	TAD	=0377-0240	IS THIS A CONTROL CODE?
	SMA			SKIP IF SO
	JMP	2F		NO: NORMAL CHARACTER
	TAD	=0240-TAB	TEST FOR A TAB CODE
	SZA CLA			TAB CODE?
1H	TAD	=X:CTRL-PAD	NO: CHANGE TO SPECIAL CONTROL CODE
	TAD	=PAD-0240	YES: GET PAD CODE
2H	TAD	=0240		HERE TO RESTORE CHARACTER
	JMS	SIO		OUTPUT TO SCREEN EXTERPRETER
	RET	XTER		ALL DONE HERE
	EJECT
/
/	SUBROUTINE TO OUTPUT PACKED 6-BIT CHARACTER STRING. CHARACTER
/	POINTER IN AC. UP-ARROW CHARACTER INDICATES WE WISH TO PERFORM
/	A CLEAR SCREEN FUNCTION FIRST. UNDERLINE GENERATES CR/LF CODE
/
/	ROUTINE MAY NOT USE TEMPORARY STORAGE
/
STROUT	SUB
	DCA	STEMP		SAVE POINTER TO THE SCREEN
	CDF	BUF		ENSURE DATA FIELD SET PROPERLY
/
/	LOOP HERE TO GET THE NEXT PAIR OF CHARACTERS
/
1H	TADI	STEMP		GET NEXT WORD
	RTR			SHIFT LEFT BYTE TO RIGHT HALF OF AC
	RTR			...
	RTR			...
	JMS	STR2		OUTPUT RIGHT HALF OF AC
	TADI	STEMP		GET WORD AGAIN
	JMS	STR2		OUTPUT RIGHT HALF OF AC
	INC	STEMP		STEP POINTER TO NEXT PAIR OF CHARACTERS
	JMP	1B		LOOP BACK FOR THEM NOW
/
/	HERE TO OUTPUT THE RIGHT HALF OF THE AC AS A FULL 8-BIT CODE
/	CHECK ALSO FOR UP-ARROW WHICH CAUSES A CLEAR SCREEN FUNCTION
/	TO BE EXECUTED
/
STR2	.SUB	25
	AND	=077		TRIM OFF HIGH PART OF AC
	TAD	=-"@^		UP-ARROW CODE?
	SNA			SKIP IF NOT
	JMP	3F		YES: HANDLE THIS
/
	TAD	="@^-"@\	BACKSLASH: FOR END OF MESSAGE?
	SNA			SKIP IF NOT
	RET	STROUT		YES: RETURN DIRECTLY FROM 'STROUT'
/
	TAD	="@\-040	RESTORE AND TEST FOR 0-37 VS. 40-77 CODE
	SPA			SKIP IF IN RANGE 40-77
	TAD	=0100		1-37 RANGE: ADD IN 7TH BIT
	TAD	=0240-X:CLSC	BUILD FULL CODE NOW
3H	TAD	=X:CLSC		UP-ARROW: DO CLEAR SCREEN
	TAD	SCROFF		FORCE CHARACTER TO APPEAR ON SCREEN (NEAT!)
	JMSI	EXTER		OUTPUT TO SCREEN VIA 'VCM'
	.RET	STR2		DONE HERE