Google
 

Trailing-Edge - PDP-10 Archives - steco_19840320_1er_E35 - 10,5676/teco/newsrc/tecvid.mac
There are 3 other files named tecvid.mac in the archive. Click here to see a list.
	SUBTTL	Introduction

; Copyright (c) 1980, 1981 Stevens Institute of Technology, Hoboken, New Jersey
; 07030.

; This software may be used and copied provided that this copyright notice
;is included, and provided that copies of all modifications are sent to:
;
;	TECO Project
;	Computer Center
;	Stevens Institute of Technology
;	Castle Point Station
;	Hoboken, New Jersey    07030
;
;
; The information in this software is subject to change without notice
; and should not be construed as a commitment by Stevens Institute of
; Technology.

  ; Search needed universals

	SEARCH	TECUNV		; TECO universal file

  ; Generate the prologue


	TECVER==200		; Major version number
	TECMIN==1		; Minor version number
	TECEDT==1174		; Edit level
	TECWHO==0		; Last editor


	PROLOGUE(VID,<TECO Video processing>)	; Generate the TITLE and other stuff
	SUBTTL	Table of Contents

	SUBTTL	Revision History
COMMENT	|

1000	Start of this version

1005	By: Nick Bush		On: 21-July-1980
	Add capability for scrolling the screen downwards on terminals with
	the function. This currently works only for VT-52's, but provides
	the necessary support for any terminal with a scrolling region.
	Modules: TECDEC,TECVID

1007	By: Nick Bush		On: 30-July-1980
	1) Make CHKTYI work a little better on slow speed (<=600 baud) 
	   terminals. It will now wait until the output buffer is empty before
	   returning the no input return.
	
	2) Put the cursor in a better position to indicate the location of PT
	   when PT = Z. The only time the cursor will now be over the prompt
	   is when PT = Z and the last line of the buffer is terminated by an
	   end of line character, and is on the last line of the window.
	Modules: TECUNV,TECVID,TECTRM

1013	By: Nick Bush		On: 6-August-1980
	Make UPDLIN use SC$WLN to write out a line if the line on the screen is
	blank, and we didn't have a function block for the replacement.
	
	Make FS and FN searches only move the text in the text buffer once, not
	do a delete and an insert. It will now only delete characters if the
	new string is shorter, and only insert space if the new string is longer.
	Modules: TECVID,TECSRH

1015	By: Nick Bush		On: 11-August-1980
	Don't give the NSM message until after we have parsed the Q-register name.
	Otherwise, we a end up executing the Q-register name.
	Modules: TECVID

1024	By: Robert McQueen		On: 19-August-1980
	Clear the executing flag in V$ASK and turn in back on after the character
	input has been done.
	Modules: TECVID

1026	By: Nick Bush		On: 21-August-1980
	When the command buffer is not the last thing on the screen on a terminal
	without insert/delete line or scrolling, if type in extends past the
	end of the section, various errors can result (ill mem ref's, looping,
	...).
	Modules: TECVID

1047	By: Robert McQueen		On: 24-October-1980
	79 Character lines would cause the 79th charcter to print twice, the
	second time on the wrapped around line if there was no CRLF ending the
	line.
	Modules: TECVID

1061	By: Nick Bush		On: 18-December-1980
	1) Finish and debug Tektronix 4025 support.
	2) Add FW command.
	3) Add capability of logging screen update info in log file.
	Modules: TECUNV,TECTEK,TECSRH,TECTBL,TECECM,TECVID,TECERR

1064	By: Robert McQueen		On: 23-December-1980
	VT100s are strange in that after clearing the screen the cursor is left on
	the bottom of the screen.  Add a new word to the $CRxxx blocks $CRERY to
	be the Y position after the screen is erased.
	Modules: TECUNV,TECDEC,TECVID

1065	By: Robert McQueen		On: 29-December-1980
	Remove the previous edit since it is easier to just add a home sequence
	after the erase function.  The erase sequence is now: <esc>[2J<esc>[H
	Modules: TECUNV,TECDEC,TECVID

1066	By: Robert McQueen		On: 6-January-1981
	Fix various problems with TECVID processing of VT100s.  FFD stopcodes
	and illegal memory references.
	Modules: TECVID

1102	By: Nick Bush		On: 23-Febuary-1981
	Fix VIDPOS to handle wrapped around lines correctly.  It was using the
	wrong value to check if it had found the correct line.
	Modules: TECVID

1106	By: Nick Bush		On: 13-May-1981
	Improve screen updating for times when the new screen has portions which
	are identical with the old.  This will also fix most cases of wrapped
	around lines on the top of the section of the screen.
	Also fix some random /MODE:DUMP bugs.
	Modules: TECUNV,TECVID,TECCMD,TECECM,TECUUO,TECMEM

1107	By: Nick Bush		On: 15-May-1981
	PTD stopcodes if screen update is aborted during a scroll down operation.
	Modules: TECVID

1110	By: Nick Bush		On: 30-June-1981
	Fix a couple bugs in updating.  Make sure that all lines which
	get destroyed as a result of scroll operations actually get marked
	that way.  Also do not just assume that if the first and last
	lines are valid that all lines in between are.  Check that all
	lines are valid before using the current screen.
	Modules: TECVID

1112	By: Robert McQueen		On: 10-July-1981
	Half the screen would disappear on ADM3As and other types of messed up
	screen updates.  This would only happen if it was cheaper to clear the
	screen and then write the data.  Clear LD$SME in the new LDBs in this case.
	Modules: TECVID

1113	By: Nick Bush		On: 12-July-1981
	Fix a backwards compare in SC$WRS.  The update will now correctly
	fix the bottom line when that should be more efficient.
	Modules: TECVID

1116	By: Nick Bush		On: 10-August-1981
	More work on VT-100's.  Get size of scrolling region right, and also make
	sure the region is properly set when we do a LF in the command echoing
	section.
	Modules: TECVID,TECDEC

1117	By: Robert McQueen		On: 14-August-1981
	- Scroll up didn't work correctly at all times.
	- Correct the cursor position after you scroll the screen up.
	Modules: TECVID

1120	By: Robert McQueen		On: 14-August-1981
	NRC stopcodes from control U processing on VT100s if you have a two line
	COMMAND-BUFFER.
	Modules: TECVID

1121	By: Nick Bush		On: 17-August-1981
	Control-U's in three line command buffers did not work.  More
	checks were needed in DISPLY.
	
	Fix defaulting of file spec paths to work correctly.  A previous edit
	had broken it.
	Modules: TECVID,TECFIL

1122	By: nb		On: 21-August-1981
	Fix DISPLY to not ill mem ref with extremely long lines. (>15000 characters).
	DISP.4 was referencing the previously found BEG (or thought it was) without
	first checking if there were any lines left on the top of the screen.
	Modules: TECVID

Start of Version 200A(1126)

1130	By: Nick Bush@SIT		On: 5-November-1981
	Split TECVID into two files:  TECVID and TECUPD.
	Redo how command editing is do in video mode to make the ^W editing
	character easier to implement.
	Add a new format for the V command when in video mode to allow the
	user more control over the position of text on the screen.
	Modules: TECVID,TECUPD,TECMVM

1131	By: Nick Bush		On: 6-November-1981
	Fix V$OCHR and V$ASK to work when the screen buffer has not been set up.
	This is mainly for errors which occur during the initial command processing.
	Modules: TECVID

1145	By: Nick Bush		On: 8-Febuary-1982
	Re-write command input routines to implement FI command. As part of this
	allow user to set prompt by storing the prompt text for normal commands in
	the Q-register 'COMMAND-PROMPT'.
	Modules: TECUNV,TECPRS,TECCIN,TECFCM,TECVID,TECUPD

1153	By: Nick Bush		On: 2-April-1982
	Fix problem with update not choosing most efficient end of screen to fix.
	V$CINI was smashing info that it shouldn't have been.
	Modules: TECVID

1161	By: Nick Bush		On: 13-May-1982
	Add new code to support peek-ahead for immediate (FC table) commands and
	for a new form of the control-T command.
	Add the new form of the control-T command to allow macros to peek at
	input, and to make use of timed input.  Also add the Q-register
	TERMINAL-INPUT-BUFFER to hold the text being peeked at, with the side
	effect of allowing macros to store text into the Q-register, and have
	it be treated as input typed on the terminal.
	Also change the space command to just pass through the arguments unless
	EO is set to 4 or less.
	Modules: TECUNV,TECVID,TECUPD,TECMVM,TECPRS,TECTRM,TECCMD,TECTBL

1165	By: Nick Bush		On: 6-June-1982
	Try yet again to get rid of the PTD stopcodes that occur with the command
	buffer updates associated with type-ahead.  Hopefully this will be the
	last fix required for this problem.
	Modules: TECVID

1174	By: Nick Bush		On: 11-August-1982
	When running terminal in image mode, tack the parity bit on correctly.
	
	Don't smash the Q-reg in the LDB to terminate the command buffer section
	unless absolutely necessary.
	Modules: TECTRM,TECVID
|
	SUBTTL	Macro definitions

; The following macros are for use in checking for type-ahead

	DEFINE $CHTYI(FLAG),<
	IFB <FLAG>,<PUSHJ P,CHKTYI>
	IFIDN <FLAG>,<SEEN>,<SKIPN TYIFLG>
	IFIDN <FLAG>,<NOWAIT>,<PUSHJ P,CHTYI0>
	> ; End of $CHTYI definition
	SUBTTL	V$CINI - Per command initialization

;+
;.HL1 V$CINI
; This routine is called before command input for each command
;-

	$CODE			; Put into code PSECT

V$CINI:	JMPNS	T$SRTN		; If turned off, go reset routines
	$SAVE	<P1>		; Save P1
	MOVE	P1,CINQRG	; Get the QRG address
	XMOVEI	T1,$QRPDB(P1)	; Get the previous buffer word
	SKIPE	$TPADR(T1)	; Anything there?
	 PUSHJ	P,M$RELB	; Yes, release it

; Set up the update screen buffer for the command buffer location.

	LOAD.	T1,QRGOFS,(P1)	; Get the offset to the first line
	LOAD.	T2,QRGNLN,(P1)	; And the number of lines
	DMOVE	T3,T1		; Get a copy of the display info

	IMULX	T1,$LDLEN	; Convert to LDB address
	ADD	T1,SCRNAD	;  .  .  .
	JUMPE	T3,VCIN.2	; If QRG starts on first line, skip this
	CFMN.	T4,LDBQRG,-$LDLEN(T1),P1 ; Previous line marked as part of this?
	 ZERO.	,LDBQRG,-$LDLEN(T1) ; Yes, make sure it doesn't count
	MOVE	T4,T2		; Get the number of lines back

VCIN.2:	STOR.	P1,LDBQRG,(T1)	; Store the QRG address of the line
	ADDX	T1,$LDLEN	; Advance to the next line
	SOJG	T2,VCIN.2	; If any
	ADD	T3,T4		; Get the last line number+1
	CAMGE	T3,SCRNLN	; End of screen?
	 JRST	[CFMN.	T2,LDBQRG,(T1),P1	; Same Q-reg?
		  ZERO.	,LDBQRG,(T1)		; No, make sure this QRG stops here
		JRST	.+1]			; And continue

	MOVE	T1,CINQRG	; Get the address of the QRG we are using
	ZERO.	,QRGVAL,(T1)	; Clear out the value (fixed pos)
	BITOFF	T2,QR$FIX!QR$SHF,$QRFLG(T1) ; And clear the fixed flags
	TXNE	F,F.INFI	; Doing an FI command?
	 SKIPA	T1,[EXP .TRUE]	; Yes, put cursor where it needs to be
	  MOVX	T1,.FALSE	; No, leave things where they are
	PUSHJ	P,UPDCMD	; Update the command section with not type-ahead
	TXZ	F,F.DUJ!F.CREC	; Clear the echoing flags
	MOVEI	T1,V$OCHR	; Get the output routine
	MOVEM	T1,TY.OBY	; Store the output routine
	MOVEI	T1,VCIN.0	; Get the routine to call for the first char
	MOVEM	T1,TY.IBY	; Save the address
	POPJ	P,		; And return

; Here when first character is wanted

VCIN.0:	$SAVE	<P1,P2>		; Save P1
	MOVEI	P1,V$ICHR	; Get the routine to get chars from now on
	MOVEM	P1,TY.IBY	; Save for top level
	MOVE	P2,CINQRG	; Get the address of the QRG
	LOAD.	P1,QRGOFS,(P2)	; Get the first line of the command buffer
	IMULX	P1,$LDLEN	; And get the first LDB address
	ADD	P1,SCRNAD	;  .  .  .
	STOR.	P2,LDBQRG,(P1) ; Store the Q-reg address
	BITON	P2,LD$FSC!LD$CMD,$LDFLG(P1) ; Flag this is the first command line
	FALL	V$ICHR		; And go get first character
	SUBTTL	V$ICHR - Input a character video mode



;+
;.HL1 V$ICHR
;This routine will input a character in video mode.
;.literal
;
; Usage:
;	PUSHJ	P,@TY.IBY	; Input a byte
;	(Return)
;
; Returns:
;	CH - Character input from the terminal
;.end literal
;-

V$ICHR:	TXZE	F,F.TYOF	; Have buffered chars to type?
	 PUSHJ	P,TTYOUT	; Yes, output them first
	PUSHJ	P,T$READ	; Get a character
	TXNE	S,S.LIIN	; Want image of input?
	 PUSHJ	P,LOGC.0	; Yes, log this character
	SETZM	TYIFLG		; Flag that we got the type ahead (now must check with montior)
	PUSHJ	P,ALTCNV	; Do any necessary altmode conversion
	SKIPN	ECHOFF		; User turn echo off?
	 TXON	F,F.ECHO	; Or caller requesting no echo?
	  POPJ	P,		; Don't need to echo the character
	FALL	V$ECHO		; Echo the character
	SUBTTL	V$ECHO - Echo an input character

;+
;.hl1 V$ECHO
; This routine will echo a character which was input from the terminal.
;The character is echoed on the screen in the current position of the
;command string. If the character causes vertical motion (either because
;it is a line feed, or because the character caused wrap around), the
;terminal dependent scroll routine will be called to cause a new line
;to be used.
;.b.lit
;
; Usage:
;	MOVE	CH,Character
;	PUSHJ	P,V$ECHO
;	 (return, character still in CH)
;
;.end literal
;-

V$ECHO:	SKIPGE	ASKPOS		; CMDBUF displayed?
	 POPJ	P, 		; No, forget it
	CAIE	CH,.CHCNH	; Backspace?
	 CAIN	CH,.CHDEL	; Is this a delete?
	  POPJ	P,		; Yes, just return
	$SAVE	<X,Y>		; Save some room
	$SAVE	<CH>		; And the character
	$SAVE	<T1,T2,T3,T4>	; Save some working room
	DMOVE	X,CMDPOS	; Get the position for the command
VECH.4:	MOVE	T4,Y		; Get the line number
	IMULX	T4,$LDLEN	; Make the offset to the LDB
	ADD	T4,SCRNAD	; And get the address
	CAXE	CH,.CHLFD	; Is this a line feed
	 JRST	VECH.2		; No, then skip this mess
	TXC	F,F.DUJ!F.CREC	; Complement the flags
	TXCN	F,F.DUJ!F.CREC	; Check if ^M is on the screen before this
	 JRST	[TXZ	F,F.DUJ!F.CREC	; No, but last char was CR so just return
		POPJ	P,]		;  .  .  .
	TXZN	F,F.CREC	; Was the last a CR ?
	 JRST	VECCRL		; No, check if we need ^J
	JRST	VECH.3		; Continue processing

VECH.2:	TXZE	F,F.CREC	; Was the last character a CR ?
	 PUSHJ	P,VECECR	; Yes, then echo the CR
VECH.3:	TXZ	F,F.CREC!F.DUJ	; Clear the flags
	CAXL	CH," "		; Character being echoed a control character ?
	 JRST	VECH.0		; Yes, single position
; Here for control characters. First character for special chars that
;should be printed as something other than ^char.

	MOVEI	T1,ECHDSP	; Get the dispatch table address
	PUSHJ	P,NDISPT	; And dispatch to the correct routine
VECH.1:	PUSH	P,CH		; No a special character
	MOVEI	CH,"^"		; Print as ^char
	PUSHJ	P,VECH.0	; Print the up-arrow
	POP	P,CH		; Restore the character
	ADDX	CH,"A"-.CHCNA	; Make the printing equivalent
	JRST	VECH.A		; And echo it

; Here for printing characters. Make sure we don't need to do a free
;crlf first.

VECH.0:	CAML	X,SCRWID	; Room for this character yet?
	 PUSHJ	P,VECFCR	; No, do a CRLF
VECH.A:	LOAD.	T1,LDBNUM,(T4)	; Any characters on the line?
	LOAD	T2,$LDFLG(T4),LD$FSC ; Get the first command line flag
	JMPF	T2,VECH.8	; Is this the first line?
	JUMPN	T1,.+2		; Any characters on the line?
	 SETZ	X,		; No, start from column 0
VECH.8:	INCR.	,LDBNUM,(T4)	; Increment the number of characters on the line
	SUB	T1,X		; Get the number of characters beyond the cursor
	JUMPLE	T1,VECH.9	; Are there any?
	PUSHJ	P,SC$POS	; Position to the correct place
	XCT	$CRDEL(CRT)	; Yes, delete them
	MOVE	T1,CINQRG	; Get the QRG we are reading
	STOR.	T1,LDBQRG,(T4)	; Flag this is part of the command buffer
VECH.9:	MOVE	T2,CINQRG	; Get the QRG
	LOAD.	T2,TPTADR,+$QRTPT(T2) ; Get the command buffer addres
	LOAD.	T3,BLKPT,(T2)	; And get the pointer
	STOR.	T3,LDBEND,(T4)	; Store the end pointer
	CFMGE.	,BLKOED,(T2),T3	; New highest end?
	 STOR.	T3,BLKOED,(T2)	; Yes, save it
	MOVE	T2,X		; Get the position on the line
	IDIVX	T2,D$CPW	; Get the index to make a byte pointer
	LOAD.	T1,LDBTXT,(T4)	; Get the text address
	HLL	T1,BTAB(T3)	; Get the byte pointer
	ADD	T1,T2		; And point to the correct word
	DPB	CH,T1		; Store the character
	PUSHJ	P,SC$CHR	; Type the character
	DMOVEM	X,CMDPOS	; Save the new position
	POPJ	P,		; And return

; Dispatch table for special control characters

ECHDSP:	XWD	VECESC,.CHESC	; Escapes echo as $ and put cursor at current pointer
	XWD	VECLFD,.CHLFD	; Line feed causes a scroll(maybe)
	XWD	VECCRT,.CHCRT	; Carriage returns put cursor in column 0
	XWD	VECTAB,.CHTAB	; Tabs cause positioning
	XWD	.POPJ,.CHCNU	; Control-U does nothing
	XWD	.POPJ,.CHCNW	; Control-W also does nothing
	XWD	VECVTB,.CHVTB	; Vertical tab
	XWD	VECFFD,.CHFFD	; Form feed
	XWD	0,0		; End of table
; Here to echo a tab

VECTAB:	CAML	X,SCRWID	; Past right margin yet?
	 PUSHJ	P,VECFCR	; Yes, do the crlf
	LOAD.	T1,LDBNUM,(T4)	; Get the current character count
	JUMPN	T1,.+2		; Anything here?
	 SETZ	X,		; No, make sure we are at left margin
	SUB	T1,X		; Get the number of characters left past cursor
	JUMPLE	T1,VTAB.2	; Are there any?
	PUSHJ	P,SC$POS	; Position to the correct place
	XCT	$CRDEL(CRT)	; Yes, delete them first
	MOVE	T1,CINQRG	; Get the QRG address
	STOR.	T1,LDBQRG,(T4)	; Flag this is part of the command buffer
VTAB.2:	MOVE	T1,X		; Get the old position
	IORX	X,7		; And then move to next tab stop
	AOJ	X,		; Add one
	DMOVEM	X,CMDPOS	; Save the position
	SUBM	X,T1		; Get the number of characters we are moving
	MOVE	T2,CINQRG	; Get the QRG address
	LOAD.	T2,TPTADR,+$QRTPT(T2) ; Get the buffer address
	LOAD.	T3,BLKPT,(T2)	; Get the current pointer
	STOR.	T3,LDBEND,(T4)	; Store it
	CFMGE.	,BLKOED,(T2),T3	; This the new highest end?
	 STOR.	T3,BLKOED,(T2)	; Yes, save it
	LOAD.	T3,LDBNUM,(T4)	; Get the number already there

	MOVE	T2,T3		; Get the number
	ADD	T3,T1		; Plus the amount the tab is adding
	STOR.	T3,LDBNUM,(T4)	; Store the new number of characters
	IDIVX	T2,D$CPW	; Convert to word and byte offset
	HLL	T2,BTAB-1(T3)	; Get the byte pointer
	LOAD.	T3,LDBTXT,(T4)	; Get the text buffer address
	ADDI	T2,(T3)		; And make the absolute byte pointer
	MOVX	CH," "		; Get a space
	IDPB	CH,T2		; Store the character
	SOJG	T1,.-1		; Loop for all the spaces the tab creates
	PJRST	SC$POS		; And do the positioning

; Here to echo an escape

VECESC:	MOVX	CH,"$"		; Get the character to echo as
	PUSHJ	P,VECH.0	; Echo it
	TXNE	F,F.INFI	; Doing an FI command?
	 POPJ	P,		; Yes, just return
	SKIPL	PTPOS+$OFSY	; Real Y position?
	 SKIPGE	PTPOS+$OFSX	; Should we really move it?
	  POPJ	P,		; No, just return
	$CHTYI			; Check for type-ahead
	 JRST	.+2		; None, continue on
	  POPJ	P,		; Have some, just return now
	MOVX	T1,HB.RTC!HB.RWJ+^D500 ; Wait half a second for more type in
	HIBER	T1,		;  .  .  .
	 JFCL			; Ignore the error
	$CHTYI			; Check for more input
	 PJRST	SC$PT		; Put cursor at correct point
	POPJ	P,		; More type in, don't bother moving the cursor

; Here to echo the carriage return.  This may be part of a carriage
; return line feed.

VECCRT:	TXO	F,F.CREC	; Flag that a carriage return was 'echoed'
	POPJ	P,		; And return to the caller

; Here to echo the carriage return after the next character has been gotten
; from the input source.

VECECR:	$SAVE	<CH>		; Save the character
	BITON	T1,LD$CR,$LDFLG(T4) ; Flag that we have an ^M on this line
	MOVX	CH,.CHCRT	; Convert to a CR
	PJRST	VECFFD		; Join a common routine
; Here to echo a line feed

VECLFD:	SETZ	X,		; Clear the X position
	MOVE	T1,CINQRG	; Get the QRG address
	BITON	T2,LD$CRLF,$LDFLG(T4) ; Flag this line ended with a CRLF
	PUSHJ	P,SC$GSC	; And scroll the screen
VLFD.0:	MOVE	T4,Y		; Get the lne number
	IMULX	T4,$LDLEN	; Make the correct LDB address
	ADD	T4,SCRNAD	;  .  .  .
	DMOVEM	X,CMDPOS	; Store the position
	BITON	T2,LD$CMD,$LDFLG(T4) ; Light the flags
	MOVE	T2,CINQRG	; Get the QRG address
	STOR.	T2,LDBQRG,(T4)	; Remember who this is
	LOAD.	T2,TPTADR,+$QRTPT(T2) ; Get the text buffer pointer
	LOAD.	T2,BLKPT,(T2)	; get the current pointer
	AOJ	T2,		; Make it the next character
	STOR.	T2,LDBBEG,(T4)	; Save it
	POPJ	P,		; And return


; Here to perform a free crlf when we are at the right margin of the screen

VECFCR:	MOVX	T2,LD$WAP	; Flag this line is wrapping around
VFCR.0:	IORM	T2,$LDFLG(T4)	; And flag that this line wraps around
	SETZ	X,		; Next character is in column 0
	MOVE	T1,CINQRG	; Get the QRG address
	PUSHJ	P,SC$GSC	; And scroll if needed
	PUSHJ	P,VLFD.0	; Fix up the beg for the next line
	DECR.	,LDBBEG,(T4)	; To be what we want
	POPJ	P,		; And return

; Here for a form feed or a vertical tab. We will print the character
;out as ^K or ^L but then do a CRLF. This makes type in look like the screen
;display.

VECVTB:
VECFFD:	PUSHJ	P,VECH.1	; Echo the control character first
	SETZ	T2,		; No flags to add to the line
	PUSHJ	P,VFCR.0	; And then give a free CRLF
	PUSHJ	P,VLFD.0	; Fix up the beg pointer
	INCR.	,LDBBEG,(T4)	; To be correct
	POPJ	P,		; And return
; Here for a line feed. Check if last char was a CR that is on the
;screen as ^M. If so, we must delete the ^M and position ourselves correctly.

VECCRL:	TXZN	F,F.DUJ		; Is there an ^M there?
	 JRST	VECFFD		; No, echo as ^J
	SUBX	T4,$LDLEN	; Yes, back up a line (must be line before this one)
	SOJ	Y,		; Back this up also
	LOAD.	X,LDBNUM,(T4)	; Get the number of chars on the line
	SUBI	X,2		; Get the correct position
	STOR.	X,LDBNUM,(T4)	; Update LDBNUM
	PUSHJ	P,SC$POS	; Put us there
	MOVEI	T1,2		; Get the number of chars to use
	XCT	$CRDEL(CRT)	; And delete to the end of line
	LOAD.	X,LDBNUM,(T4)	; Get the number back again
	SUBI	X,2		; Fix it
	JUMPN	X,VCRL.1	; Hit column 0?
	MOVE	T1,CINQRG	; Get the address of the QRG
	LOAD.	T1,TPTADR,+$QRTPT(T2) ; Yes, must check if last line wrapped
	LOAD.	T2,BLKPT,(T1)	; Get the pointer
	SUBI	T2,2		; Point the char before CR
	IDIVI	T2,5		; Convert to word/byte
	HLL	T2,BTAB(T3)	; And get the byte pointer
	ADDI	T2,.BKTLN(T1)	; Get the address
	LDB	CH,T2		; Get the character
	PUSHJ	P,CKTRM		; Check if terminator
VCRL.1:	 TDZA	T2,T2		; No, remember that
	  SETO	T2,		; Flag this was a terminator
	BITON	T1,LD$CRLF,$LDFLG(T4) ; Flag line now ends with a CRLF
	BITOFF	T1,LD$CR,$LDFLG(T4) ; And not a CR
	JUMPL	T2,VECLFD	; Previous char terminator?
	AOJ	Y,		; No, bump the line number back
	SETZ	X,		; And set to first column
	DMOVEM	X,CMDPOS	; Make sure CMDPOS is ok
	PJRST	SC$POS		; And position in correct place
	SUBTTL	V$OCHR - Output a video mode character

;+
;.hl1 V$OCHR
; This routine is called from the output routines in TECTRM to output
;a single character to the screen.
;-

V$OCHR:	TXNN	S,S.SLOG	; Want this output?
	 TXNN	S,S.LOUT	; Maybe, logging output?
	  JRST	.+2		; Don't log it
	PUSHJ	P,LOGCHR	; Yes, log the character
	SKIPL	ASKPOS		; If CMDBUF not displayed, just put it anywhere
	 SKIPN	SCRNAD		; If no screen buffer, just type the character
	  JRST	[OUTCHR	CH		; If no screen buffer, just type it
		SETOM	OUTFLG		; Flag there is some output to wait for
		SETOM	MESFLG		; Screen messed up now
		POPJ	P,]		; Return
	CAXN	CH,.CHBEL	; Is this a bell?
	 PJRST	SC$IMG		; Yes, just output it

; Here to check to see if the --more-- should be typed on the screen

	$SAVE	<X,Y>		; Save the X and Y position
	$SAVE	<CH>		; Save the character register
	$SAVE	<T1,T2,T3,T4>	; Save the Tx registers
	DMOVE	X,CMDPOS	; Get the command position
	SKIPN	OUTFLG		; Any chars output yet?
	 CAXE	CH,.CHLFD	; Line feed
	  JRST	VOCH.0		; No, skip this
	TXZE	F,F.CREC	; Thing which caused the break a CR?
	 POPJ	P,		; Yes, just return
VOCH.0:	SETOM	OUTFLG		; Flag we have output. Need continue before prompting
	CAME	Y,ASKPOS+$OFSY	; . . .
	 JRST	VOCH.3		; No, continue processing
	PUSHJ	P,CKTRM		; Terminating character ?
	 JRST	[CAMG	X,ASKPOS+$OFSX	; Or more than the offset
		  JRST	VOCH.3		; Not the right line, just continue
		JRST	VOCH.1]		; It is, type the --More--
VOCH.1:	MOVEI	T1,[ASCIZ |--More--|] ; Get the text to type
	PUSH	P,CH		; Save the character
	PUSHJ	P,V$ASKA	; Ask the user if they want more
	DMOVE	X,CMDPOS	; Get the command position
	POP	P,CH		; Restore the character
	CAXN	CH,.CHCRT	; This a carriage return?
	 TXO	F,F.CREC	; Yes, flag that was last thing seen
	PUSHJ	P,CKTRM		; Terminating character?
	 JRST	.+2		; No, must print it
	  JRST	VOCH.2		; Go clear the flag and return
	MOVE	T1,TY.OBY	; Get the output routine
	CAIE	T1,.POPJ	; Did it change ?
	 PJRST	VOCH.3		; No, echo the character
VOCH.2:	SETZM	OUTFLG		; Flag no output left
	POPJ	P,		; And return


; Here if we can just output the character

VOCH.3:	PUSHJ	P,VECH.4	; Output the character
	TXNE	F,F.TYOF	; Anything to output?
	 PUSHJ	P,CKTRM		; And is it a line terminator?
	  POPJ	P,		; No, just return
	PJRST	TTYOUT		; Output the buffers
	SUBTTL	Screen editing -- V$ASK - Ask a question and wait for response

;+
;.hl1 V$ASK
;This routine will type some text in the ASKPOS position and then wait
;for a response from the user.  If the user gives an invalid response the
;routine will given the help message to the user.
;.literal
;
; Usage:
;	MOVEI	T1,[ASCIZ |String to type|]
;	PUSHJ	P,V$ASK
;	(Return)
;
;.end literal
; If the user gives a no (N) response the routine will set the output
;routine to be just a .POPJ, else it will leave everything alone.
;-

V$ASK:	$SAVE	<X,Y>		; Save X and Y
	$SAVE	<T1,T2,T3,T4>	; Save T1 to T4

; Alternate entry point for V$OCHR

V$ASKA:	SKIPGE	ASKPOS		; Should we just return?
	 POPJ	P,		; Yes, he doesn't have CMDBUF displayed
	CLRBFI			; Clear any type ahead
	SETZM	TYIFLG		; And remember there is none
	$SAVE	<P1,P2,P3>	; Save P1
	MOVE	P1,T1		; Copy the address
	SKIPN	SCRNAD		; Have the screen data yet?
	 JRST	VASK.T		; No, do things different
	DMOVE	X,ASKPOS	; Get the position
	MOVE 	P2,Y		; Get the address
	IMULX	P2,$LDLEN	; Compute the LDB address
	ADD	P2,SCRNAD	;  . . .
	PUSHJ	P,SC$POS	; Position to there
	HRLI	P1,(POINT 7)	; Build the byte pointer
	STOR.	X,LDBNUM,(P2)	; Store the number of characters
	MOVE	T1,X		; Get the number of chars
	IDIVX	T1,D$CPW	; Convert to word/byte offset
	LOAD.	P3,LDBTXT,(P2)	; Get the text buffer address
	HLL	P3,BTAB-1(T2)	; Get the byte pointer
	ADDI	P3,(T1)		; And point to correct word

VASK.0:	ILDB	CH,P1		; Get a character
	JUMPE	CH,VASK.1	; If finished
	IDPB	CH,P3		; Store the character
	XCT	$CRTCH(CRT)	; Type the character
	INCR.	T1,LDBNUM,(P2)	; Count the character that is being displayed
	JRST	VASK.0		; Loop until done

VASK.T:	OUTSTR	[BYTE (7).CHCRT,.CHLFD,0] ; Do the CRLF
	OUTSTR	(P1)		; And type the prompt

VASK.1:	TXZ	F,F.ECHO	; Turn off echoing for a character
	SETZM	XCTING		; Flag not executing now
	PUSHJ	P,V$ICHR	; Get a character
	CAXE	CH,.CHCRT	; Carriage return?
	 JRST	VASK.3		; No, continue
	TXZ	F,F.ECHO	; Yes, clear echo for this one
	PUSHJ	P,V$ICHR	; And get te line feed
	MOVX	CH,.CHCRT	; Get the character back
VASK.3:	SETOM	XCTING		; Flag executing now
	MOVEI	T1,ASKDSP	; Get the dispatch table
	PUSHJ	P,NDISPT	; Call the non-returning dispatch
	JRST	ASKHLP		; Give the help message

; Dispatch table for the answer from the user

ASKDSP:	XWD	ASKHLP,"?"	; If the user typed a question mark
	XWD	ASKHLP,"H"	; If the user typed a "H"
	XWD	ASKYES,"Y"	; If the user typed a "Y"
	XWD	ASKNO, "N"	; If the user typed a "N"
	XWD	ASKYES," "	; Space is also a yes
	XWD	ASKYES,.CHCRT	; As is carriage return
	XWD	ASKNO,.CHDEL	; Delete is same as no
	XWD	0,	0	; End of the list

; Help message for the message processing

ASKTXT:	ASCIZ	|Type "Y" to continue, "N" to abort, "?" for this message --|

; Here for typing the help message

ASKHLP:	SKIPN	SCRNAD		; Have the buffer?
	 JRST	ASKH.T		; No, just type it
	MOVE	Y,ASKPOS+$OFSY	; Get the Y position
	SETZ	X,		; Clear the X position
	PUSHJ	P,SC$POS	; Position to the beginning of the line
	MOVE	P1,[POINT 7,ASKTXT] ; Get the text pointer
	LOAD.	P3,LDBTXT,(P2)	; Get the text address
	HRLI	P3,(POINT 7,)	; And make the pointer

ASKH.0:	ILDB	CH,P1		; Get a character
	JUMPE	CH,ASKH.1	; Have one?
	IDPB	CH,P3		; Store the character
	XCT	$CRTCH(CRT)	; Type the character
	JRST	ASKH.0		; Loop for the next

ASKH.1:	LOAD.	T1,LDBNUM,(P2)	; Get the number of positions
	SUB	T1,X		; Get the number left
	STOR.	X,LDBNUM,(P2)	; Save the number of chars
	XCT	$CRDEL(CRT)	; Delete to the end of the line
	PJRST	VASK.1		; And loop back

; Here if we don't have the screen buffer yet

ASKH.T:	OUTSTR	[BYTE(7).CHCRT,.CHLFD] ; Output a CRLF
	OUTSTR	ASKTXT		; And the text
	PJRST	VASK.1		; Try again

; Here for aborting the type out

ASKNO:	MOVEI	T1,.POPJ	; Get the new output routine
	MOVEM	T1,TY.OBY	; Store as the new routine
	POPJ	P,		; Return to the caller

; Here to continue processing

ASKYES:	MOVE	T2,CINQRG	; Get the QRG address
	LOAD.	T1,QRGOFS,(T2)	; Get the offset to the first line
	LOAD.	T2,QRGNLN,(T2)	; Get the number of lines
	PUSHJ	P,SC$CLR	; Clear the section of the screen
	MOVE	Y,CINQRG	; Get the QRG address
	LOAD.	Y,QRGOFS,(Y)	; Get the line number again
	SETZ	X,		; Get the X position
	DMOVEM	X,CMDPOS	; Store the new command position
	PJRST	SC$POS		; And position to that place on the screen
	SUBTTL	V$CTRG - Handle ^G. input command

;+
;.hl1 V$CTRG
; This routine will handle a control-G "." command while the
;command is being input. This will clear the screen and cause all
;lines which were part of the command to be reprinted.
;-

V$CTRG:	$SAVE	<P1,P2>		; Save some ac's
	MOVE	P1,SCRNAD	; Get the address of the LDB's
	MOVE	P2,SCRNLN	; And the size

VCTG.1:	LOAD.	T1,LDBTXT,(P1)	; Get the address of the text
	PUSHJ	P,CLRL.0	; Clear it out
	LOAD.	T1,LDBQRG,(P1)	; Get what is displayed here
	CAMN	T1,CINQRG	; Is it the command buffer?
	 JRST	VCTG.2		; Yes, skip clearing the positions
	ONES.	,LDBBEG,(P1)	; Clear out the beg
	ONES.	,LDBEND,(P1)	; And the end
VCTG.2:	ZERO.	,LDBNUM,(P1)	; And say we have nothing here
	ADDX	P1,$LDLEN	; Advance to the next block
	SOJG	P2,VCTG.1	;  .  .  .

	MOVE	T1,$CRERS(CRT)	; Erase the screen
	PUSHJ	P,SC$STR	;  .  .  .
	SETZM	CURPOS+$OFSX	; Flag we are home
	SETZM	CURPOS+$OFSY	;  .  .  .
	MOVX	T1,.TRUE	; Flag we want cursor at end of QRG
	PJRST	UPDCMD		; And update the command portion

	SUBTTL	V$DELC - Handle a delete or backspace

;+
;.hl1 V$DELC
; This routine is called during command input if the user typed
;a backspace or a delete.
;-


V$DELC:	PUSHJ	P,BACKUP	; Delete the character from the command buffer
	 PJRST	.POPJ1		; If all done, give the skip return
	MOVE	T1,CINQRG	; Get the QRG address
	LOAD.	T1,TPTADR,+$QRTPT(T1) ; Get the command buffer address
	CFMG.	T2,BLKPT,(T1),PMTLEN ; Are we back to the prompt?
	 PJRST	.POPJ1		; Yes, all done
	LOAD.	T2,BLKPT,(T1)	; Get the current position
	MOVE	T3,T2		; Get a copy
	AOJ	T3,		; Plus one
	PUSHJ	P,UPDBND	; Update the bounds
	MOVX	T1,.TRUE	; Flag we want cursor at end of command
	FALL	UPDCMD		; Fall into the routine to update the section
	SUBTTL	V$UPCM - Update the command buffer on the screen

;+
;.hl1 V$UPCM
; This routine will update the command buffers section of the screen.
;It will do so without changing what is currently where on the screen
;if desired.
;-

V$UPCM:
UPDCMD:	$SAVE	<NOTYIA,P1>	; Save the flag
	MOVE	P1,T1		; Get the flag
	SETOM	NOTYIA		; Flag don't abort on type-ahead
	SETZM	TYIFLG		; Flag nothing seen so far
	MOVX	T2,QR$UPD	; If we have fancy stuff then do full update
	TXNE	CRT,CR$DIL!CR$SCR ; Have insert/delete line or scrolling?
	 TXNN	S,S.SCRL	; If scrolling wanted
	  MOVX	T2,QR$FIX	; Get the bit to turn on
	MOVE	T1,CINQRG	; Get the QRG address
	IORM	T2,$QRFLG(T1)	; must do silly things
	PUSHJ	P,SC$UPS	; Update it
	DMOVEM	T1,CMDPOS	; Store the position of the next character
	MOVE	T1,CINQRG	; Get the QRG address
	BITOFF	T2,QR$FIX,$QRFLG(T1) ; Turn off the fixed flag

	TXZ	F,F.DUJ!F.CREC	; Clear the flags
	$SAVE	<X,Y>		; Save X and Y
	DMOVE	X,CMDPOS	; Set up for correct place
	JMPF	P1,.+2		; Want the cursor moved to end of command?
	 PUSHJ	P,SC$POS	; Yes, do it
	MOVE	T1,CINQRG	; Get the QRG address
	LOAD.	T1,TPTADR,+$QRTPT(T1) ; Get the command buffer address
	LOAD.	T2,BLKPT,(T1)	; Get the pointer
	SOJ	T2,		; Back off to look at the previous character
	IDIVI	T2,5		; Get the address and byte position
	HLL	T2,BTAB(T3)	; Set up the byte pointer
	ADDI	T2,.BKTLN(T1)	; Get the absolute address
	LDB	T1,T2		; Get te character
	CAXE	T1,.CHCRT	; Is it a carriage return
	 POPJ	P,		; No, return
	MOVE	T1,Y		; Get the current line number
	IMULX	T1,$LDLEN	; Make into LDB offset
	ADD	T1,SCRNAD	; And make it the LDB address
	TXO	F,F.DUJ!F.CREC	; Flag previous char was CR
	JUMPE	Y,.POPJ		; First line of screen?
	LOAD.	T2,LDBQRG,(T1)	; Get the Q-reg address
	CAMN	T2,CINQRG	; Is this the command buffer?
	 TXZ	F,F.CREC	; Previous line was part of command, remember ^M is on screen
	POPJ	P,		; And return
	SUBTTL	Screen editing -- SC$GSC - General scroll routine

;+
;.hl1 SC$GSC
; This routine is the general routine called to scroll a region of the
;screen on terminals without insert/delete line functions. It will
;simply scroll the whole screen when necessary.
;-

SC$GSC:	$SAVE	<CH>		; Save CH
	MOVE	T2,SCRNLN	; Get the number of lines on the screen
	CAIL	Y,-1(T2)	; Will this line cause the whole screen to scroll?
	 JRST	SGSC.1		; Yes, go fix up the LDB's
	LOAD.	T2,QRGOFS,(T1)	; No, get the first line number
	LOAD.	T3,QRGNLN,(T1)	; And the number of lines
	ADDI	T2,-1(T3)	; Get the number of the last line
	CAMGE	Y,T2		; Still within this region
	 JRST	SGSC.0		; Yes, just output the line feed
	TXNE	S,S.SCRL	; Scrolling allowed?
	 CAIE	T3,1		; Only one line?
	  JRST	.+2		; Don't scroll
	   JRST	SGSC.4		; Yes, just do a delete to end of line
	TXNE	CRT,CR$DIL!CR$SCR ; Have a scrolling region or can fake one?
	 TXNN	S,S.SCRL	; Scrolling requested?
	  JRST	.+2		; Don't scroll
	   JRST	SGSC.2		; Yes, go do it
	PUSH	P,X		; Save X position
	SETZ	X,		; And put on first character of next line
	AOS	T2,Y		; Get the next line number
	IMULX	T2,$LDLEN	; Get the LDB address
	ADD	T2,SCRNAD	;  .  .  .
	STOR.	T1,LDBQRG,(T2)	; Store the QRG that this line now belongs to
	LOAD.	T1,LDBNUM,(T2)	; Get the number of characters on this line
	PUSHJ	P,SC$POS	; Position the cursor
	XCT	$CRDEL(CRT)	; And delete the line
	MOVE	T1,T2		; Get the LDB address
	PUSHJ	P,FLSLDB	; Clear it out
	POP	P,X		; Get the X position back
	PJRST	SC$POS		; Position to the currect place and return

; Here if we just need a line feed

SGSC.0:	MOVX	CH,.CHLFD	; Get a line feed
	TXNN	CRT,CR$SCR	; Have scroll thingys?
	 PJRST	SC$CHR		; And output it
	PUSH	P,Y		; Save Y
	LOAD.	T2,QRGOFS,(T1)	; Get the top line number
	LOAD.	Y,QRGNLN,(T1)	; And the number of lines
	ADDI	Y,(T2)		; Get the bottom
	SOJ	Y,		;  .  .  .
	SETZ	T1,		; Don't move anything
	XCT	$CRSUP(CRT)	;  .  .  .
	POP	P,Y		; Restore Y
	PJRST	SC$CHR		; And output the character

; Here if we are falling off the bottom of the screen. Move the LDB's
;up to account for the scrolling

SGSC.1:	TXNE	CRT,CR$DIL!CR$SCR ; Have a scrolling region or can fake one?
	 TXNN	S,S.SCRL	; Want scrolling?
	  JRST	.+2		; No scrolling, do whole screen
	   JRST	SGSC.2		; Yes, go do it
	MOVE	T1,SCRNAD	; Get the address of the first LDB
	MOVE	T2,SCRNLN	; And get the length
	SOJ	T2,		; Get the last line
	IMULX	T2,$LDLEN	; Get the offset to the last
	ADD	T2,T1		; And make the last LDB
	PUSHJ	P,SC$SCR	; Move the LDB's around
	PUSHJ	P,SC$POS	; Put into correct place
	SOS	PTPOS+$OFSY	; Will move the line up one
	MOVX	CH,.CHLFD	; Get a line feed
	TXNN	CRT,CR$SCR	; Have scrolling region?
	 PJRST	SC$IMG		; And output it, causing the screen to scroll
	PUSH	P,Y		; Save Y
	SETZB	T1,T2		; Set up the correct region
	MOVE	Y,SCRNLN	; Get the screen length
	SOJ	Y,		; Minus one
	XCT	$CRSUP(CRT)	; Set up the region to be the whole screen
	POP	P,Y		; Restore Y
	PJRST	SC$IMG		; And output the LF

; Here if we must scroll a section of the screen, and the terminal is
;capable of doing it reasonably.

SGSC.2:	$SAVE	<P1>		; Save P1
	MOVE	P1,T1		; And remember the address
	LOAD.	T1,QRGOFS,(P1)	; Get the offset to the first line
	LOAD.	T2,QRGNLN,(P1)	; And the number of lines
	CAIN	T2,1		; Only one line in this section?
	 JRST	SGSC.4		; Yes, just do the delete to end of line
	IMULX	T1,$LDLEN	; Get the offset to the LDB
	SOJ	T2,		; Make it the offset from the first to the last
	IMULX	T2,$LDLEN	; Make this the LDB offset also
	ADD	T1,SCRNAD	; Get the address of the first LDB
	ADD	T2,T1		; This also
	PUSHJ	P,SC$SCR	; Move the LDB info around
	TXNN	CRT,CR$SCR	; Have a scrolling region?
	 JRST	SGSC.3		; No, fake it
	LOAD.	T2,QRGNLN,(P1)	; Get the number of lines back
	SOJ	T2,		; Make it the offset backwards
	SUBM	Y,T2		; Get the top line number
	MOVEI	T1,1		; Get the number of lines to scroll up
	PUSH	P,X		; Save the current position
	XCT	$CRSUP(CRT)	; Scroll it up
	POP	P,X		; Restore the current X pos
	PJRST	SC$POS		; Position correctly

; Here to perform the functions of a scrolling region using insert/delete
;line functions

SGSC.3:	PUSH	P,X		; Save the current X pos
	PUSH	P,Y		; Save the line number
	LOAD.	Y,QRGOFS,(P1)	; Get the first line number of this section
	PUSHJ	P,SC$POS	; Position to correct place
	MOVEI	T1,1		; One line
	XCT	$CRDLL(CRT)	; Delete the line
	POP	P,Y		; Get the line number back
	MOVE	T1,SCRNLN	; Get the number of lines this has
	CAIN	T1,1(Y)		; Is this the last line of the screen?
	 JRST	SGSC.A		; Yes, just go position to the new line
	PUSHJ	P,SC$POS	; No, position to the right place
	MOVEI	T1,1		; One line
	XCT	$CRINL(CRT)	; And insert the line
SGSC.A:	POP	P,X		; Restore the current X pos
	PJRST	SC$POS		; And reposition to correct place

; Here if the section is only one line long. Just do a delete to end
;of line function.

SGSC.4:	SETZ	X,		; Clear the X position
	PUSHJ	P,SC$POS	; Position us there
	MOVE	T1,Y		; Get the line number
	IMULX	T1,$LDLEN	; And get the LDB address
	ADD	T1,SCRNAD	;  .  .  .
	PUSH	P,T1		; Save it
	LOAD.	T1,LDBNUM,(T1)	; Get the number of chars on this line
	XCT	$CRDEL(CRT)	; And delete the line
	POP	P,T1		; Get the LDB address back
	SETZ	X,		; Clear the X position again
	PUSHJ	P,SC$POS	; And reposition the cursor
	PJRST	FLSLDB		; And clear it
	SUBTTL	Screen editing -- SC$SCR - Scroll a region of the screen

;+
;.hl1 SC$SCR
; This routine is called to update the LDB's when a region of the screen
;is being scrolled.
;.b.lit
;
; Usage:
;	MOVEI	T1,First.LDB
;	MOVEI	T2,Last.LDB
;	PUSHJ	P,SC$SCR
;	 (return here, LDB's updated)
;
;.end literal
;-

SC$SCR:	$SAVE	<P1,P2,P3>	; Save some room
	DMOVE	P1,T1		; Get the args
	LOAD.	P3,LDBTXT,(P1)	; Get the text address of the first LDB
	CAIN	P1,(P2)		; Only one line?
	 JRST	SSCR.2		; Yes, skip the loop

SSCR.0:	LOAD.	T1,LDBTXT,+$LDLEN(P1) ; Get the text from the next line
	STOR.	T1,LDBTXT,(P1)	; And move it up
	LOAD.	T1,LDBNUM,+$LDLEN(P1) ; Get the number of characters
	STOR.	T1,LDBNUM,(P1)	; Store it
	LOAD.	T1,LDBFLG,+$LDLEN(P1) ; Get the flags
	STOR.	T1,LDBFLG,(P1)	; Store it
	LOAD.	T1,LDBBEG,+$LDLEN(P1) ; Yes, get the start pointer
	STOR.	T1,LDBBEG,(P1)	; Store it
	LOAD.	T1,LDBEND,+$LDLEN(P1) ; Get the end pointer
	STOR.	T1,LDBEND,(P1)	; And store it
	LOAD.	T1,LDBQRG,+$LDLEN(P1) ; Get the Q-register address
	STOR.	T1,LDBQRG,(P1)	; Store the QRG address also

; Here to check if we are done with the loop

SSCR.2:	ADDX	P1,$LDLEN	; Bump to the next
	CAIGE	P1,(P2)		; Done yet?
	 JRST	SSCR.0		; No, loop

; Here after the text pointers have been moved. P3 contains the address
;of the text block we will use for the new line, P2 contains the new LDB
;address. Note that T1 is left with the address of the QRG of the previous line


SSCR.3:	STOR.	T1,LDBQRG,(P2)	; Store the QRG address
	STOR.	P3,LDBTXT,(P2)	; Store the text address
	ZERO.	,LDBNUM,(P2)	; No characters on the line
	ZERO.	T1,LDBFLG,(P2)	; Clear the flags
	ONES.	,LDBBEG,(P2)	; Clear the BEG
	ONES.	,LDBEND,(P2)	; And end
	MOVE	T1,P3		; Get the text address
	PJRST	CLRL.0		; And go clear the LDB
REPEAT 0,<
	SUBTTL	Screen editing -- SC$SDN - Scroll a region of the screen

;+
;.hl1 SC$SDN
; This routine is called to update the LDB's when a region of the screen
;is being scrolled down.
;.b.lit
;
; Usage:
;	MOVEI	T1,Bottom line
;	MOVEI	T2,Top line
;	PUSHJ	P,SC$SDN
;	 (return here, LDB's updated)
;
;.end literal
;-

SC$SDN:	$SAVE	<P1,P2,P3>		; Save some room
	DMOVE	P1,T1		; Get the args
	LOAD.	P3,LDBTXT,(P1)	; Get the text address of the bottom LDB
	CAIN	P1,(P2)		; Only one line?
	 JRST	SSDN.2		; Yes, skip the loop

SSDN.0:	LOAD.	T1,LDBTXT,-$LDLEN(P1) ; Get the text from the next line
	STOR.	T1,LDBTXT,(P1)	; And move it down
	LOAD.	T1,LDBNUM,-$LDLEN(P1) ; Get the number of characters
	STOR.	T1,LDBNUM,(P1)	; Store it
	LOAD.	T1,LDBFLG,-$LDLEN(P1) ; Get the flags
	STOR.	T1,LDBFLG,(P1)	; Store it
	LOAD.	T1,LDBQRG,-$LDLEN(P1) ; Get the Q-register address
	STOR.	T1,LDBQRG,-$LDLEN(P1) ; Store the address
	LOAD.	T1,LDBBEG,-$LDLEN(P1) ; Get the start pointer
	STOR.	T1,LDBBEG,(P1)	; Store it
	LOAD.	T1,LDBEND,-$LDLEN(P1) ; Get the end pointer
	STOR.	T1,LDBEND,(P1)	; And store it

; Here to check if we are done with the loop

SSDN.2:	SUBX	P1,$LDLEN	; Bump to the next
	CAILE	P1,(P2)		; Done yet?
	 JRST	SSDN.0		; No, loop

; Here after the text pointers have been moved. P3 contains the address
;of the text block we will use for the new line, P2 contains the new LDB
;address.

SSDN.3:	STOR.	P3,LDBTXT,(P2)	; Store the text address
	ZERO.	,LDBNUM,(P2)	; No characters on the line
	ONES.	,LDBBEG,(P2)	; Clear the BEG
	ONES.	,LDBEND,(P2)	; And end
	ZERO.	T1,LDBFLG,(P2)	; Clear the flags
	MOVE	T1,P3		; Get the text address
	PJRST	CLRL.0		; And go clear the LDB
> ; End of REPEAT 0 for SC$SDN
	SUBTTL	Screen editing -- SC$VID - Allocate the screen buffer


;+
;.hl2 SC$VID
; This routine will set up to use the screen editing features. It will
;allocate the buffer for the screen and initialize it to spaces.
;-


SC$VID:	MOVE	T1,SCRNAD	; Get the screen address
	JUMPN	T1,SVID.0	; Have one already - Skip the setup
	TXZN	S,S.SCRN	; Clear the flag
	 POPJ	P,		; Not on yet anyway
	SKIPN	$CRXYP(CRT)	; Have an X-Y address string?
	 PJRST	T$SRTN		; Set the terminal input routines
	SKIPN	T2,CRTLEN	; Have a length set?
	 SKIPE	T2,TRMLEN	; No, have one from the TRMOP?
	  JRST	.+2		; Have a length
	   JRST	T$SRTN		; No, just reset the terminal routines
	SKIPN	T1,CRTWID	; Have a width set?
	 SKIPE	T1,TRMWID	; No, have one from the TRMOP?
	  JRST	.+2		; Yes, go set things up
	   JRST	T$SRTN		; No, just set up the terminal routines

; Set up the screen buffer address here

	TXO	S,S.SCRN	; Flag we now have screen mode
	$SAVE	<P1,P2,P3,P4>	; Save P1 to P3
	MOVEM	T2,SCRNLN	; Store the number of lines
	MOVEM	T1,SCRWID	; Save the width
	AOJ	T1,		; Plus one
	IDIVX	T1,D$CPW	; Convert to number of words
	SKIPE	T2		; Any extra needed?
	 AOJ	T1,		; Yes, count it
	MOVEM	T1,LINWDS	; Save the number of words
	PUSHJ	P,SVID.A	; Allocate the first set
	MOVEM	T1,SCRNAD	; Save as normal address
	PUSHJ	P,SVID.A	; Allocate the update set
	MOVEM	T1,SUPDAD	; Store it
	MOVE	T1,SCRNLN	; Get the number of lines on the CRT
	MOVX	T2,.BTGEN	; Allocation from general storage
	PUSHJ	P,M$ZBLK	; Allocate a zero block
	MOVEM	T1,FNCLST	; Store as the function list block
	MOVE	T1,SCRNLN	; Get the number of lines on the CRT
	MOVX	T2,.BTGEN	; Allocation from general storage
	PUSHJ	P,M$ZBLK	; Allocate a zero block
	MOVEM	T1,CSTLST	; Save the list address
	MOVE	T1,SCRNLN	; Get the number of lines
	ASH	T1,1		; Make the max function length
	MOVX	T2,.BTGEN	; Get the block type
	PUSHJ	P,M$GBLK	; Get the block
	MOVEM	T1,FNCBLK	; Save it
SVID.4:	MOVE	T1,$CRERS(CRT)	; Have an erase string?
	PUSHJ	P,SC$STR	; Yes, do it
	SETZM	CURPOS+$OFSX	; Flag we are at 0,0
	SETZM	CURPOS+$OFSY	;  .  .  .
	SKIPN	T1,CRTWID	; Get the current width
	 MOVE	T1,TRMWID	;  .  .  .
	CAMN	T1,SCRWID	; Did it change?
	 POPJ	P,		; No, all is fine
	MOVEM	T1,SCRWID	; Yes, save the current width
	SETOM	MESFLG		; And flag things need some help
	POPJ	P,		; And return

; Here to allocate the update buffers

SVID.A:	MOVE	T1,SCRNLN	; Get the length
	IMULX	T1,$LDLEN	; Compute the number of words
	MOVEI	P4,(T1)		; Get the offset to the first line of text
	MOVE	T2,LINWDS	; Get the number of words per line
	IMUL	T2,SCRNLN	; Get the total
	ADD	T1,T2		;  .  .  .
	MOVX	T2,.BTGEN	; Get the general thingy for the video
	PUSHJ	P,M$ZBLK	; Allocate a zero block
	MOVE	P1,T1		; Get the address
	ADD	P4,T1		; Fix the other pointer
	MOVN	P2,SCRNLN	; Get the number of lines
	MOVSI	P2,(P2)		; Move it into the other half
	HRR	P2,P1		; Get the address
	SETZ	P3,		; Start labeling at line 0

SVID.1:	MOVEI	T1,(P4)		; Get the address
	STOR.	T1,LDBTXT,(P2)	; Store the block
	STOR.	P3,LDBLIN,(P2)	; Store the line number
	PUSHJ	P,CLRL.0	; Clear the line
	ADDI	P3,1		; Increment the line number
	ADD	P4,LINWDS	; Plus the length of the line
	ADDX	P2,$LDLEN-1	; Point to the next entry
	AOBJN	P2,SVID.1	; Loop for all entries

	MOVE	T1,P1		; Get the address back
	POPJ	P,		; And return it
; Here if there was a screen buffer

SVID.0:	SKIPN	T1,CRTLEN	; Have a length set?
	 MOVE	T1,TRMLEN	; Get the number of lines
	CAME	T1,SCRNLN	; Is it the same as what we have?
	 JRST	SVID.2		; No, must reallocate the buffer
	SKIPN	T1,CRTWID	; Get the width
	 MOVE	T1,TRMWID	; Get the width of the lines
	IDIVX	T1,D$CPW	; And get the number of words required for each
	JUMPE	T2,.+2		; Need an extra?
	 AOJ	T1,		; Yes, count it
	CAMN	T1,LINWDS	; Same number of words needed?
	 JRST	SVID.4		; Yes, skip the whole bit

SVID.2:	PUSHJ	P,SC$RVD	; Return the video info
	JRST	SC$VID		; Try again from the top
	SUBTTL	SC$RVD - Return video information allocated by SC$VID

;+
;.HL1 SC$RVD
; This routine will return the information that was allocated by SC$VID.
;It will also clear the display info in the Q-registers.
;-

SC$RVD:	SKIPN	SCRNAD		; Have the screen data?
	 POPJ	P,		; No, just return
	$SAVE	<P1>		; Save P1
	MOVN	P1,SCRNLN	; Get the number of lines
	MOVSI	P1,(P1)		; Build the AOBJx pointer
	HRR	P1,SCRNAD	; Get the screen address

SRVD.3:	LOAD.	T1,LDBQRG,(P1)	; Get the Q-register associated with this
	JUMPE	T1,SRVD.9	; Have one?
	BITOFF	T2,QR$VID!QR$VLU!QR$FCT,$QRFLG(T1) ; Yes, flag it is no longer being displayed
	ZERO.	T2,QRGOFS,(T1)	; Clear the offset
	ZERO.	T2,QRGNLN,(T1)	; And the number of lines
SRVD.9:	ADDX	P1,$LDLEN-1	; Compute the address of the next block
	AOBJN	P1,SRVD.3	; Loop deleting the blocks
	MOVE	T1,SCRNAD	; Get the address
	PUSHJ	P,M$RBLK	; Return it
	MOVE	T1,SUPDAD	; Get the update block address
	PUSHJ	P,M$RBLK	; Return it
	MOVE	T1,FNCLST	; Get rid of the function list
	PUSHJ	P,M$RBLK	; Return it
	MOVE	T1,CSTLST	; Get the cost list address
	PUSHJ	P,M$RBLK	; And return it
	MOVE	T1,FNCBLK	; Get the function block address
	PUSHJ	P,M$RBLK	; Return it
	SETZ	T1,		; Clear SCRNAD
	EXCH	T1,SCRNAD	; Get the address of the old block
	PUSHJ	P,M$RBLK	; Return the old block
	SETZM	SCRNLN		; Nothing on the screen at the moment
	SETZM	SCRWID		;  .  .  .
	POPJ	P,		; And return
	SUBTTL	Screen editing -- SC$FIN - Finish up

;+
;.hl2 SC$FIN
; This routine will output the string to put the cursor at the
;lower left hand corner of the screen. It will also perform
;any reseting of the terminal that is needed.
;-


SC$FIN:	MOVE	Y,SCRNLN	; Get the number of lines on the screen
	SOJ	Y,		; Make it the correct line number
	SETZ	X,		; Want cursor in column 0
	PUSHJ	P,SC$POS	; Position to the correct place
	XCT	$CRFIN(CRT)	; Cause the terminal to be put in reasonable state
	POPJ	P,		; And return
	SUBTTL	Screen editing -- SC$POS - Position the cursor

;+
;.HL2 SC$POS
;This routine will position the cursor to the position that is described
;by the X and Y positions in A1 and A2.
;.literal
;
; Usage:
;	DMOVE	X,X and Y positions
;	PUSHJ	P,SC$POS
;	(Return)
;.end literal
;-

SC$POS:	CAMN	X,CURPOS+$OFSX	; Are we already there?
	 CAME	Y,CURPOS+$OFSY	;  .  .  .
	  JRST	.+2		; No, must position
	   POPJ	P,		; Yes, just return
	$SAVE	<X,Y,T1,T2,T3>	; Save the positions
	XCT	$CRXYP(CRT)	; No, do the positioning
	POPJ	P,		; And return
	SUBTTL	Screen editing -- SC$DEL - Delete to end of line

;+
;.hl1 SC$DEL
; This routine is called to delete from the current position to the end
;of the line. This is used for terminals which do not have a delete to
;end of line function. It will use blanks to delete the characters that
;are actually on the screen.
;.b.lit
;
; Usage:
;	MOVE	T1,Number of characters left on screen line
;	DMOVE	X,Position
;	PUSHJ	P,SC$DEL	(usually from XCT $CRDEL(CRT))
;	 (return here)
;
;.end literal
;-

SC$DEL:	$SAVE	<P1>		; Save room for the count
	$SAVE	<CH>		; Save the current character
	MOVE	CH,$CRDSP(CRT)	; Get the destructive space
	MOVE	P1,T1		; Get the count

SDEL.0:	SOJL	P1,.POPJ	; Return if done
	XCT	$CRTCH(CRT)	; Else output the character
	JRST	SDEL.0		; Loop
	SUBTTL	Screen editing -- SC$STR - Write a string


;+
;.HL2 SC$STR
; This routine will write out a string of up to 5 characters on the
;screen.
;.literal
;
; Usage:
;	MOVE	T1,$CRxxx(CRT)	; Get the string to output
;	PUSHJ	P,SC$STR	; Output the string
;	(Return)
;
;.end literal
;-


SC$STR:	JUMPE	T1,.POPJ	; Just return if nothing to type
	$SAVE	<CH>		; Save the current character
	TXNE	F,F.TYOF	; Need to output first?
	 PUSHJ	P,TTYOUT	; Yes, force the other out
	TXNN	T1,177B6	; Have anything in the left half?
	 JRST	SC$S.2		; No, is this a TECO defined string?
	PUSH	P,T1		; Save the string
	MOVX	T1,<POINT 7,(P)> ; Get the byte pointer
SC$S.1:	ILDB	CH,T1		; Get a character
	JUMPE	CH,.T1PJ	; Return if null
	PUSHJ	P,SC$IMG	; Type the character
	TXNE	T1,<INSVL.(70,BP.PFL)> ; Only do one word
	 JRST	SC$S.1		; Loop for all chars
	PJRST	.T1PJ		; Return

SC$S.2:	$SAVE	<T1,T2>		; Save T1 and T2
	HRRZ	T2,T1		; Get the string address
	MOVEI	T1,[$STRING(<^X/SC$IMG/^N^S/(T2)/>)] ; Set up to type the string
	PJRST	T$TYPE		; Do it

	SUBTTL	Screen editing -- SC$MES - Write a non-image string

;+
;.HL1 SC$MES
; This routine will write out a screen control string in non-image mode.
;.literal
;
; Usage:
;	MOVE	T1,$CRxxx(CRT)
;	PUSHJ	P,SC$MES
;	(Return)
;.end literal
;-

SC$MES:	JUMPE	T1,.POPJ	; Just return if nothing
	$SAVE	<CH>		; Save the current character
	TXNE	F,F.TYOF	; Need to output first?
	 PUSHJ	P,TTYOUT	; Yes, force the other out
	TXNN	T1,177B6	; Have something in the left half?
	 JRST	SC$M.2		; No, if not user string go type it
	PUSH	P,T1		; Save the string
	MOVX	T1,<POINT 7,(P)> ; Get the byte pointer

SC$M.0:	ILDB	CH,T1		; Get a character
	JUMPE	CH,.T1PJ	; Return if null
	OUTCHR	CH		; Output the character
	TXNE	T1,<INSVL.(70,BP.PFL)> ; Check if done with the word
	 JRST	SC$M.0		; No, loop
	JRST	.T1PJ		; Yes, return
SC$M.2:	$SAVE	<T1,T2>		; Save P1 and P2
	HRRZ	T2,T1		; Get the string address
	MOVEI	T1,[$STRING(<^X/SC$M.3/^N^S/(T2)/>)] ; Set up to type the string
	PJRST	T$TYPE		; Do it

SC$M.3:	OUTCHR	CH		; Output the character
	POPJ	P,		; And return
	SUBTTL	Screen editing -- SC$PT - Move cursor to PT

;+
;.HL2 SC$PT
; This routine will position he cursor to PT on the screen.
;.literal
;
; Usage:
;	PUSHJ	P,SC$PT
;	(Return)
;
;.end literal
;-

SC$PT:	DMOVE	X,PTPOS		; get the position of PT
	JUMPL	X,.POPJ		; Just return if no place to go
	PJRST	SC$POS		; Go to that position
	SUBTTL	Screen editing -- SC$IMG - output a character to the screen

;+
;.hl 1 SC$IMG
; This routie will output a character to the terminal in image mode.
;This routine will output the character with the correct parity.
;.literal
;
; Usage:
;	MOVE	CH,Character to output
;	PUSHJ	P,SC$IMG
;	(Return)
;
;.end literal
;-

SC$IMG:	SKIPL	CHRFLG(CH)	; Need the parity bit on for this one?
	 TRO	CH,200		; Yes, turn it on (even parity)
SC$IM0:	MOVEM	CH,TRMOCH+2	; Save the character
	MOVE	CH,[XWD 3,TRMOCH] ; Get the pointer
	TRMOP.	CH,		; And output the character
	 IONEOU	TRMOCH+2	; Couldn't
	MOVE	CH,TRMOCH+2	; Get the character back
	TRZ	CH,200		; Clear the bit
	TXNE	S,S.LVID	; Want video logged?
	 PJRST	LOGC.0		; Yes, go do it
	POPJ	P,		; And return
	SUBTTL	Screen Editing -- SC$FIL - Output fill characters


;+
;.HL 1 SC$FIL
; This routine is called to output enough fill characters to give
;the terminal enough time to perform a function. It is called with
;the time the terminal requires to perform the function in milliseconds.
;It will output enough nulls as fill characters to account for that much
;time.
;.b.lit
;
; Usage:
;	MOVE	T1,Number of milli-seconds to fill
;	PUSHJ	P,SC$FIL
;	 (Return, terminal ready for next output)
;
;.end literal
;-

SC$FIL:	MOVE	T2,TRMSPD	; Get the terminal speed
	MUL	T1,CPSTBL(T2)	; Get the number of chars we need to send
	DIVX	T1,^D1000	;  .  .  .
	JUMPE	T1,.POPJ	; Just return if no fill necessary
	$SAVE	<CH>		; Else save the current character
	MOVX	CH,.CHNUL	; Get a null
	PUSHJ	P,SC$IMG	; And fill
	SOJG	T1,.-1		; Keep filling long enough for the terminal to finish
	POPJ	P,		; And return

	SUBTTL	Screen Editing -- SC$CFL - Calculate fill cost


;+
;.HL 1 SC$CFL
; This routine is called to calculate the number of fill chars
;which are required by an operation. These characters are included
;in any cost calculation for a given terminal.
;.b.lit
;
; Usage:
;	MOVE	T1,Number of milli-seconds to fill
;	PUSHJ	P,SC$CFL
;	 (Return, T1= number of fill chars)
;
;.end literal
;-

SC$CFL:	MOVE	T2,TRMSPD	; Get the terminal speed
	MUL	T1,CPSTBL(T2)	; Get the number of chars we need to send
	DIVX	T1,^D1000	;  .  .  .
	POPJ	P,		; And return

	SUBTTL	Screen Editing -- CPSTBL - Character per second table

; This table contains the number of characters which can be output
;per second at the standard baud rates. It is indexed by the .TSxxx
;symbol.

	DEFINE ENT(SPEED,CPS,INDEX)<TABENT(SPEED,^D<CPS>)>

TABDEF	CPS,.TS
	TSPEED		; Generate the table
TABEND
	SUBTTL	Screen editing -- SC$CHR - Output a character at a given posisiton

;+
;.HL1 SC$CHR
; This routine will output a character at a given place on the screen. It
;will keep track of where the current position is.
;.b.literal
; Usage:
;	MOVEI	CH,character
;	DMOVE	X,position
;	PUSHJ	P,SC$CHR
;	 (return with X, Y and CURPOS updated)
;
;.end literal
;-

SC$CHR:	PUSHJ	P,SC$POS	; Position us on the screen
	PUSHJ	P,SC$IMG	; Output the character in image mode
	CAXGE	CH," "		; Printing character?
	 JRST	SC$C.1		; No, check what type of control character it is
	AOJ	X,		; Bump the position
	JRST	SC$C.R		; Go return

SC$C.5:	AOJ	Y,		; And bump the Y position
	CAML	Y,SCRNLN	; Did this cause the screen to scroll?
	 STOPCD	SCR,<Screen was scrolled by SC$CHR>
SC$C.R:	DMOVEM	X,CURPOS	; Update the current position
	POPJ	P,		; And return

; Here if the character was a control character.

SC$C.1:	CAXE	CH,.CHTAB	; Is this a tab?
	 JRST	SC$C.2		; No, check for other motion chars
	AOJ	X,		; Bump the position
	TXO	X,7		; And round up to the next tab stop
	TXNN	CRT,CR$TAB	; Terminal have hardware tab stops?
	 PUSHJ	P,SC$POS	; No, move the cursor
	DMOVEM	X,CURPOS	; And save the position
	POPJ	P,		; Return

SC$C.2:	CAXE	CH,.CHCNH	; Backspace?
	 JRST	SC$C.3		; No, try other chars
	SOJGE	X,SC$C.R	; Just return if still okay
	TXNN	CRT,CR$NWP	; Does this terminal go backwards?
	 AOJA	X,SC$C.R	; No, we stayed at column 0
	MOVE	X,SCRWID	; Otherwise we are now at the end of a line
	SOJGE	Y,SC$C.R	; On the previous line
	SETZ	Y,		; Don't go above screen
	JRST	SC$C.R		; And return

SC$C.3:	CAXE	CH,.CHCRT	; Carriage return?
	 JRST	SC$C.4		; No, check line feed
	SETZ	X,		; Yes, just clears the X position
	PJRST	SC$C.R		; And return

SC$C.4:	CAXE	CH,.CHLFD	; Line feed?
	 JRST	SC$C.R		; No, assume non-printing
	JRST	SC$C.5		; Otherwise bump the line and check for scrolling
	SUBTTL	Screen editing -- SC$CLS - Clear a section
	SUBTTL	Screen editing -- SC$CLR - Clear a section

;+
;.HL1 SC$CLS and SC$CLR
;These routines will clear a section of the screen and clear the text
;block that the LDBs point to.  If SC$CLS is called the QRG pointer
;in the LDB will be cleared.
;.literal
;
; Usage:
;	MOVEI	T1,QRG.block.address
;	PUSHJ	P,SC$CLS
;	(Return)
;
;	MOVEI	T1,Offset.into.screen.buffer
;	MOVEI	T2,Number.of.lines
;	PUSHJ	P,SC$CLR
;	(Return)
;
;.end literal
;-

SC$CLS:	$SAVE	<P1>		; Save P1
	MOVE	P1,T1		; Get the arg
	BITOFF	T2,QR$VID!QR$VLU!QR$FCT,$QRFLG(P1) ; Flag not displaying this anymore
	ZERO.	T1,QRGOFS,(P1)	; Clear the offset and
	ZERO.	T1,QRGNLN,(P1)	;  the number of lines
	SKIPN	VINADR		; If we have a screen address
	 JRST	SCLS.1		; Else just clear out previous pointer
	LOAD.	T1,TPTADR,+VINADR ; Get the address of the info
	LOAD.	T2,VINNLN,(T1)	; Get the number of lines

SCLS.0:	CFMN.	,VINQRG,(T1),P1	; Is this this Q-reg?
	 ZERO.	,VINQRG,(T1)	; Yes, clear it
	AOJ	T1,		; Advance to the next
	SOJG	T2,SCLS.0	; And loop for all items

SCLS.1:	MOVEI	T1,$QRPDB(P1)	; Get the address of the previous pointer
	SKIPE	(T1)		; Is there any?
	 PUSHJ	P,M$RELB	; Yes, release it
	SETZM	$QRPDB(P1)	; Make sure it is clear
	POPJ	P,		; Return to the caller


SC$CLR:	SKIPN	SCRNAD		; If we have a screen address
	 POPJ	P,		; Else just return
	$SAVE	<P1,P2,P3,P4>	; Clear P1
	$SAVE	<X,Y>		; Save the X and Y addresses
	$SAVE	<CH>		; And save CH
	MOVX	P1,$LDLEN	; Get the length of the LDB
	IMUL	P1,T1		; Compute the word offset
	ADD	P1,SCRNAD	; Compute the address
	MOVNS	T2		; Compute the number of words
	HRL	P1,T2		; For an AOBJN pointer

SCLR.0:	SETZ	X,		; Clear the X offset
	LOAD.	Y,LDBLIN,(P1)	; Get the line number from the Y offset
	LOAD.	T1,LDBNUM,(P1)	; Get the number of characters on the line
	JUMPE	T1,SCLR.1	; Anything to delete?
	TXNN	CRT,CR$CTU	; Terminal know how to do real delete to end of lines?
	 JRST	SCLR.2		; No, go simualte it
	PUSHJ	P,SC$POS	; Go to that position on the screen
	XCT	$CRDEL(CRT)	; Delete the line

SCLR.1:	MOVEI	T1,(P1)		; Get the address of the LDB
	PUSHJ	P,FLSLDB	; Clear the counters and fill with spaces

	ADDX	P1,$LDLEN-1	; Advance to the next LDB
	AOBJN	P1,SCLR.0	; Loop for all the LDBs
	POPJ	P,		; Return to the caller

; Here to simulate a delete to end of line for terminals without it

SCLR.2:	LOAD.	P4,LDBTXT,(P1)	; Get the pointer to the text
	HRLI	P4,(POINT 7,)	; And make the byte pointer
	SETZ	P3,		; Clear the count of spaces
	MOVE	P2,T1		; Get the number of chars on the line

SCLR.3:	SOJL	P2,SCLR.1	; Done yet?
	ILDB	T1,P4		; Get a character
	JUMPE	T1,.+2		; Is it a null?
	 CAIN	T1," "		; Is it a space?
	  AOJA	P3,SCLR.3	; Yes, just count it
	JUMPE	P3,SCLR.4	; Any previous spaces ?
	HRLI	T1,(X)		; Yes, get the current X pos
	HRRI	T1,(Y)		; And the current Y
	MOVSI	T2,(P3)		; Get where we are going
	ADD	T2,T1		;  .  .  .
	XCT	$CRCPP(CRT)	; Get the cost of getting there with positioning
	CAMLE	T1,P3		; Cheaper to do the position or write the spaces?
	 AOJA	P3,SCLR.4	; Cheaper to write the spaces out
	ADD	X,P3		; Get where we want to be
	MOVEI	P3,1		; Get the number of space to output

SCLR.4:	MOVEI	CH," "		; Get a space
	XCT	$CRTCH(CRT)	; Type it
	SOJG	P3,SCLR.4	; And tyxe all that are necessary
	SETZ	P3,		; Clear the count of skipped chars
	JRST	SCLR.3		; Go for the next line
	SUBTTL	Screen editing -- SC$ERS - Clear the whole screen

;+
;.hl1 SC$ERS
; This routine will clear the whole screen and the LDB's. It will leave
;the cursor at X=0 Y=0.
;.b.literal
;
;	PUSHJ	P,SC$ERS
;	 (return here)
;.end literal
;-

SC$ERS:	JMPNS	.POPJ		; Just return if not on
	$SAVE	<P1>		; Save P1
	MOVE	T1,$CRERS(CRT)	; Clear the screen
	PUSHJ	P,SC$STR	; Output the string
	MOVN	P1,SCRNLN	; Get the number of lines on the screen
	MOVSI	P1,(P1)		; Into the left half
	HRR	P1,SCRNAD	; Get the LDB addresses

; Loop clearing the displayed text for all the LDB's

SERS.0:	MOVEI	T1,(P1)		; Get the address of the LDB
	PUSHJ	P,FLSLDB	; Clear the counters and moves spaces into it
	ADDX	P1,$LDLEN-1	; Bump to the next LDB
	AOBJN	P1,SERS.0	; Loop for all the lines

	SETZM	CURPOS+$OFSX	; Clear the X position
	SETZM	CURPOS+$OFSY	; Clear the Y position
	POPJ	P,		; And return
	SUBTTL	SC$SSR - Set screen regions

;+
;.hl1 SC$SSR
; This routine is called to set up the update LDB with the current
;screen regions.
;-

SC$SSR:	$SAVE	<P1,P2,P3,P4>	; Save some ac's
	SKIPN	VINADR+$TPADR	; Have one allocated?
	 JRST	[TXZ	S,S.SCRN	; No, turn off screen mode
		POPJ	P,]		; And return
	SKIPN	T1,CRTWID	; Have a width set?
	 MOVE	T1,TRMWID	; Get the current terminal width
	SKIPN	T2,CRTLEN	; Have a length set?
	 MOVE	T2,TRMLEN	; Get the length of the screen
	CAMN	T2,SCRNLN	; Same as current?
	 CAME	T1,SCRWID	; Same as what had last time?
	  PUSHJ	P,SC$VID	; No, allocate new LDB's
	LOAD.	P1,TPTADR,+VINADR ; Get the address of the block
	LOAD.	P2,VINNLN,(P1)	; Get the number of lines

	MOVE	P3,SUPDAD	; Get the address of the update LDB's
	MOVE	P4,SCRNLN	; Get the length of the screen
	SETZB	T2,T3		; Clear the QRG lines
	LOAD.	T4,VINQRG,(P1)	; Get the QRG address
	SETZ	P1,		; Start with first line

SSSR.1:	LOAD.	T1,TPTADR,+VINADR ; Get the address of the VIN
	ADD	T1,P1		; Get the correct offset
	LOAD.	T1,VINQRG,(T1)	; Get the QRG address
	SKIPE	T4		; Any QRG currently?
	 CAMN	T1,T4		; Still in same QRG?
	  AOJA	T3,SSSR.2	; Yes, keep looping
	PUSHJ	P,SSSR.S	; Set up the Q-reg info
	LOAD.	T2,LDBLIN,(P3)	; Get the current line number
	MOVEI	T3,1		; One line already in current QRG
	MOVE	T4,T1		; Get the address of the current QRG

SSSR.2:	STOR.	T1,LDBQRG,(P3)	; Store it
	AOJ	P1,		; Advance to next line
	ADDX	P3,$LDLEN	;  .  .  .
	SOJLE	P4,SSSR.4	; If this is the end of the screen, stop now
	SOJG	P2,SSSR.1	; Loop for all lines

SSSR.3:	ZERO.	,LDBQRG,(P3)	; Clear out the LDB since nothing is here
	ADDX	P3,$LDLEN	; Advance to next LDB
	SOJG	P4,SSSR.3	;  .  .  .
	JUMPN	T4,SSSR.S	; If we have a QRG left, go set it
	POPJ	P,		; Otherwise just return

; When we get here, if T4 is non-zero, we have a region to set.
;Then we must fix up the rest of the Q-regs (if any) in the display list
;to indicate that they aren't actually displayed at this point.

SSSR.4:	JUMPE	T4,SSSR.5	; If nothing to set, skip it
	PUSHJ	P,SSSR.S	; Set up this Q-reg with the current lines

; Skip the rest of the lines which claim to be here.

SSSR.5:	SOJLE	P2,SSSR.8	; Return if nothing left
	LOAD.	T1,TPTADR,+VINADR ; Get the address of the block
	ADD	T1,P1		; Point to correct line
	LOAD.	T1,VINQRG,(T1)	; Get the QRG address
	CAMN	T1,T4		; Same as current one?
	 AOJA	P1,SSSR.5	; Yes, loop through it
	MOVE	T4,T1		; Get the address of the next QRG

; Here to clear out the display info for the reset of the QRG's

SSSR.6:	JUMPE	T4,SSSR.7	; If no QRG here, try the next
	BITOFF	T2,QR$VID,$QRFLG(T4) ; Clear the displayed flag
	ZERO.	T2,QRGOFS,(T4)	; Clear the offset to the first
	ZERO.	T2,QRGNLN,(T4)	; And the number of lines
SSSR.7:	AOJA	P1,SSSR.5	; Loop for all lines left

; Now determine if CMDBUF is displayed and set up the correct place for
;ASKPOS.

SSSR.8:	MOVX	T1,QR$VID	; Check if CMDBUF is displayed
	SETOM	ASKPOS		; Assume it isn't
	TDNN	T1,$QRFLG+CMDBUF ; Is it?
	 POPJ	P,		; No, just return
	LOAD.	T1,QRGNLN,+CMDBUF ; Get the number of lines it has
	LOAD.	T2,QRGOFS,+CMDBUF ; Get the offset to the first line
	ADDI	T2,-1(T1)	; Get the last line number
	MOVEM	T2,ASKPOS+$OFSY	; Save as Y position
	SKIPN	T1,SCRWID	; Have a width set yet?
	 SKIPE	T1,CRTWID	; User set one?
	  JRST	.+2		; Yes, use that
	   MOVE	T1,$CRWID(CRT)	; Get the width of the terminal
	SUBI	T1,^D14		; Find where the X position should be
	JUMPGE	T1,.+2		; If positive, all is fine
	 SETZ	T1,		; Not 14 characters wide, use whole line
	MOVEM	T1,ASKPOS+$OFSX	; Save the X position
	POPJ	P,		; And return

; Subroutine to set up the display info into the Q-reg

SSSR.S:	$SAVE	<T1,T2,T3,T4,P1> ; Save some ac's
	MOVE	P1,T4		; Get the QRG address
	STOR.	T2,QRGOFS,(P1)	; Store the line number
	STOR.	T3,QRGNLN,(P1)	; And number of lines
	LOAD.	T1,QRGDTP,(P1)	; Get the data type
	CAXN	T1,$DTTXT	; Is there text here?
	 JRST	SSSR.T		; Yes, skip this
	MOVX	T2,$DTTXT	; No, get the new data type
	XCT	RQRGTB(T1)	; Set the new datatype
	SETZ	T1,		; No, get a null buffer
	PUSHJ	P,M$GTXT	;  .  .  .
	XMOVEI	T2,$QRTPT(P1)	; Get the address of the pointer
	PUSHJ	P,M$USEB	; And set it up
	BITOFF	T1,QR$FIX!QR$SHF,$QRFLG(P1) ; Flag no particular position wanted

SSSR.T:	BITON	T1,QR$VLU!QR$VID!QR$FCT,$QRFLG(P1) ; Flag this is displayed
	POPJ	P,		; And return
	SUBTTL	Low segment for TECVID

	$IMPURE			; Do the impure storage
	LOWVER(VID,4)		; Low segment version number of this module


; CRT data

VINADR:	BLOCK	$TPLEN		; Address of VIN block
SCRNAD:	BLOCK	1		; Address of the list of LDB entries
SUPDAD:	BLOCK	1		; Update LDB's
				;  for the screen
SCRNLN:	BLOCK	1		; Number of lines
SCRWID:	BLOCK	1		; Width of screen
CRTWID:	BLOCK	1		; Width of screen as set by user
CRTLEN:	BLOCK	1		; Length of screen as set by user
LINWDS:	BLOCK	1		; Number of words per line buffer
MESFLG:	BLOCK	1		; Screen messed up
OUTFLG:	BLOCK	1		; Flag that output has been done. This means
				; that --Cont-- needs to be done before prompting

PTPOS:	BLOCK	2		; Position of PT
CMDPOS:	BLOCK	2		; Position to echo commands at
CURPOS:	BLOCK	2		; Current position

; The following two items must be in this order

CRTTYP:	BLOCK	1		; Type of CRT in use (index into CRT table)
CRTFNC:	BLOCK	$CRMAX+1	; Max CRT block


; For V$OCHR

ASKPOS:	BLOCK	2		; Position at which the '--More--' should be
				;  typed to the user
	SUBTTL	End of TECVID

	END			; End of TECVID