Google
 

Trailing-Edge - PDP-10 Archives - steco_19840320_1er_E35 - 10,5676/teco/newsrc/tececm.mac
There are 5 other files named tececm.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==1164		; Edit level
	TECWHO==0		; Last editor


	PROLOGUE(ECM,<TECO E command processing>)	; Generate the TITLE and other stuff
	SUBTTL	Table of Contents

;+
;.pag.lit

;		Table of Contents for TECECM - E command processing
;
;
;			   Section			      Page
;   1. Introduction . . . . . . . . . . . . . . . . . . . . .    1
;   2. Table of Contents. . . . . . . . . . . . . . . . . . .    2
;   3. Revision History . . . . . . . . . . . . . . . . . . .    3
;   4. Misc symbol definitions. . . . . . . . . . . . . . . .    4
;   5. E Commands
;        5.1.   Initialization. . . . . . . . . . . . . . . .    5
;        5.2.   E. - Switch editing buffers . . . . . . . . .    6
;        5.3.   E<(Q-reg) - Type input file name into buffer.    7
;        5.4.   E>(Q-reg) - Type output file name into buffer    8
;        5.5.   EL
;             5.5.1.     LOGCHR . . . . . . . . . . . . . . .    9
;             5.5.2.     MAKLOG . . . . . . . . . . . . . . .   10
;        5.6.   EE - Write out a save file. . . . . . . . . .   12
;        5.7.   EE - Restart code . . . . . . . . . . . . . .   14
;        5.8.   EE
;             5.8.1.     RST - Restart routine. . . . . . . .   15
;        5.9.   EC - Perform a garbege collection . . . . . .   16
;        5.10.  EI and EP - Read into a Q-register. . . . . .   17
;        5.11.  EQ - Write out Q-register . . . . . . . . . .   20
;        5.12.  EG - Exit closing all files & run COMPIL. . .   21
;        5.13.  EX
;             5.13.1.    Exit closing all files . . . . . . .   22
;             5.13.2.    Common routines
;                  5.13.2.1.      FINI.0. . . . . . . . . . .   23
;                  5.13.2.2.      CLSFIL. . . . . . . . . . .   24
;                  5.13.2.3.      FIN.EB. . . . . . . . . . .   25
;        5.14.  ED (Run a program on exit). . . . . . . . . .   26
;        5.15.  ET - Set type out mode. . . . . . . . . . . .   29
;        5.16.  EO. . . . . . . . . . . . . . . . . . . . . .   30
;        5.17.  EU command. . . . . . . . . . . . . . . . . .   31
;        5.18.  ES. . . . . . . . . . . . . . . . . . . . . .   32
;        5.19.  EH - Change error message level . . . . . . .   33
;        5.20.  EK - Kill off the output file . . . . . . . .   34
;        5.21.  EN - rename the input file. . . . . . . . . .   35
;        5.22.  ER - Read a file. . . . . . . . . . . . . . .   36
;        5.23.  EB - Edit and backup command. . . . . . . . .   37
;        5.24.  EW - Write a file . . . . . . . . . . . . . .   39
;        5.25.  EA - Append to a file . . . . . . . . . . . .   39
;        5.26.  EZ and EF . . . . . . . . . . . . . . . . . .   41
;        5.27.  EM - MTAPE UUO's. . . . . . . . . . . . . . .   43
;        5.28.  Subroutines
;             5.28.1.    E$DFLT . . . . . . . . . . . . . . .   44
;   6. Low segment. . . . . . . . . . . . . . . . . . . . . .   45
;   7. End of TECECM. . . . . . . . . . . . . . . . . . . . .   46

;.end lit.pag
;-
	SUBTTL	Revision History
COMMENT	|

1000	Start of this version

1006	By: Nick Bush		On: 28-July-1980
	1. EE files get "Not a save file" from monitor. The byte size specified in
	   TECUNV was getting expanded as 36 octal, not decimal.
	
	2. EW was using the wrong address for calling F$RSET when there already was
	   an output file. Make it use the FDB address, not the text buffer address.
	Modules: TECUNV,TECECM

1014	By: Nick Bush		On: 11-August-1980
	1) Don't do the AUTO-BUFFER command if we had a error on the last command.
	   This avoids losing info for the error messages.
	2) Make an EB/ER/EX sequence end up renaming the correct files, not
	   trying to rename the ER'ed file to the EB'ed file.BAK, ...
	3) Make TEC file=file work the way it is supposed to.
	Modules: TECPRS,TECFIL,TECECM,TECINI

1016	By: Robert McQueen		On: 12-August-1980
	- Log files do not work for /NOOUTPUT and /NOINPUT
	- Make :E< and :E> work.
	Modules: TECECM

1017	By: Robert McQueen		On: 12-August-1980
	- The ENQ'd path was wrong sometimes, test backwards.
	- ^Z command caused files to be renamed for EB'd files.
	Modules: TECTRM,TECECM

1030	By: Robert McQueen		On: 21-August-1980
	- Clean up defaulting routines
	- Prevent EB files from always seeming to be /INPLACE.
	Modules: TECFIL,TECECM

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

1071	By: Nick Bush		On: 10-January-1981
	Add F$RBUF and F$WBUF routines to improve I/O performance.
	Also add /MODE:DUMP for all file commands.
	Modules: TECUNV,TECFIL,TECCMD,TECECM

1074	By: Nick Bush		On: 23-January-1981
	Make TECONC ask for an initial command string for TECINI. This can be
	any set of TECO commands terminated by two altmodes.
	Also make TECECM do a physical-only GETSEG during an EE file restart if
	the original run-from info was gotten from the GETTAB's.
	Modules: TECINI,TECONC,TECECM

1076	By: Nick Bush		On: 30-January-1981
	Add a default mode to be mode type 0. This will allow /MODE:ASCII
	to really be such with LSA files. Also make /MODE: properly default
	from ER/EW to EB and vice versa.
	Modules: TECUNV,TECCMD,TECFIL,TECECM

1077	By: Nick Bush		On: 6-Febuary-1981
	1) Add routine do delete all tags for a given text buffer, and have it
	   called anytime the buffer becomes editable, or is destroyed.
	
	2) Reset CUREDT to point at TXTBUF anytime the q-register which it points
	   at becomes disassociated with it.
	Modules: TECUNV,TECPRS,TECCMD,TECECM,TECSYM

1100	By: Robert McQueen		On: 8-Febuary-1981
	- Issue a ?TECNFO error message if there are no files for output on an EX
	  command or anything else that runs through FINI.0.
	- Cause the ?TECNFO error message from the above to only print one.  U$WW??
	  should not save TY.OBY on the stack, but use the ^X feature of $STRING.
	Modules: TECECM,TECUUO

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

1125	By: Robert McQueen		On: 29-September-1981
	- Make symbol table entries movable blocks.
	- Use the new linked list processing.
	- Initial work to make TECSYM run in non-zero section.
	Modules: TECUNV,TECECM,TECSYM,TECMEM

Start of Version 200A(1126)

1127	By: Nick Bush@SIT, Robert C. McQueen@SIT		On: 15-October-1981
	Add the following new features:
	- String arguments.  {...} is a string argument.
	- Make I take them, = and == return them.
	- Implement the FC command to define immediate command tables
	- Implement the E? command to return various items.
	- Start doing some work so that TECO will work on TOPS-20
	- Start doing some work so that TECO some day may run in a section
	  besides zero.
	Modules: TECUNV,TECERR,TECPRS,TECCMD,TECSRH,TECMEM,TECUUO,TECECM,TECMVM,TECCOM,TECINI

1132	By: Nick Bush		On: 10-December-1981
	1) Add Q-register data types for the sake of FC(Q-reg)SAVE$ and
	FC(Q-reg)RESTORE$ commands.
	2) Fix FC(q-reg)REPLACE$ to correctly replace the ALWAYS and OTHER options.
	Modules: TECUNV,TECCMD,TECECM,TECMEM,TECPRS,TECMVM

1135	By: Nick Bush		On: 21-December-1981
	Add /YANK and /NOYANK switches to ER and EB commands.  These will
	cause an EY command to be done along with the ER/EB command.
	The switch will have a single default for both ER and EB.
	Modules: TECECM

1140	By: Nick Bush		On: 1-January-1982
	Fix E?TERMINAL-TYPE$ to not put a CRLF after the terminal name.
	Modules: TECECM

1141	By: Nick Bush		On: 1-January-1982
	Fix EW/EA command to correctly turn off the "output open" flag when
	reseting the previous file.
	Modules: TECECM

1142	By: Nick Bush		On: 3-January-1982
	Fix SETWIN to properly copy the VIN block when it had to be expanded
	and moved.  It was not copying the last word of the old block.
	Modules: TECECM

1147	By: Nick Bush		On: 17-March-1982
	Fix control-C code to correctly restore T1-3 before saving them on the stack.
	This got broken when the check for DDT was put in.
	Modules: TECECM

1151	By: Nick Bush		On: 24-March-1982
	Add Q-register 'EXIT-BUFFER' to be executed whenever TECO is exiting.
	Also remove the string to set VT-100's to smooth scroll on exit.  This
	can now be done by putting the correct macro in 'EXIT-BUFFER'.
	Modules: TECUNV,TECECM,TECPRS,TECTBL,TECDEC

1162	By: Nick Bush		On: 14-May-1982
	Add a new flag for Q-regs to indicate that the Q-reg may not become the
	current editing buffer with the E. command.  This keeps TERMINAL-INPUT-BUFFER
	from causing problems
	Modules: TECUNV,TECECM,TECCMD

1164	By: Nick Bush		On: 29-May-1982
	Last edit broke redefining the screen without intervening update.
	In SETWIN, always call SC$CLS, whether the Q-reg claims to be displayed
	or not.
	Modules: TECECM
|
	SUBTTL	Misc symbol definitions

; The following symbols are not defined in UUOSYM.  These are the GETSEG
; and RUN arguments

TOPS10<
	$RNDEV==0		; Offset to the device name
	$RNNAM==1		; Offset to the name
	$RNEXT==2		; Offset to the extension
	$RNPPN==4		; Offset to the PPN
	$RNCOR==5		; Offset to the core argument (Right half)
>; End of TOPS10
	SUBTTL	E Commands -- Initialization

;+
;.HL1 E$INIT
;Here to initialize the E command processing.
;-

	$CODE			; In the CODE PSECT


; First define the permanent default file specs.

PDF$EW:
PDF$ER:
;PDF$EB:
	$BUILD	FDB,.FDLEN	; Initialize the macro
	$SET	DEV,<SIXBIT |DSK|> ; Default device name
	$EOB			; End of the block

PDF$EL:	$BUILD	FDB,.FDLEN	; Prime the macro
TOPS10<
	$SET	DEV,<SIXBIT |DSK|> ; Default the device name
	$SET	NAM,<SIXBIT |TECO|> ; Default the name
	$SET	EXT,'LOG'	; Default the extension
>; End of TOPS10
TOPS20<
	$SET	FIL,<ASCIZ |DSK:TECO.LOG|>
>; End of TOPS20
	$SET	FLG,FD.HEX	; And the flags
	$EOB			; End the block

PDF$EQ:	$BUILD	FDB,.FDLEN	; Prime the macro
	$SET	NAM,<SIXBIT |TECO|> ; Default the name
	$SET	EXT,'TEC'	; Default the extension
	$SET	FLG,FD.HEX	; And the flags
	$EOB			; End the block

PDF$EE:	$BUILD	FDB,.FDLEN	; Prime the macro
TOPS10<
	$SET	DEV,<SIXBIT |DSK|> ; Default the device name
	$SET	NAM,<SIXBIT |TECO|> ; Default the name
	$SET	EXT,'SAV'	; Default the extension
>; End of TOPS10 conditional
TOPS20<
	$SET	FIL,<ASCIZ |DSK:TECO.EXE|>
>; End of TOPS20
	$SET	FLG,FD.HEX	; And the flags
	$EOB			; End the block


E$INIT:	STORE	T1,E$ZBEG,E$ZEND,0 ; Clear the data
	STORE	T1,E$OBEG,E$OEND,-1 ; And initialize the default switches
	MOVE	T1,[XWD RUNCOD,ED$COD] ; Get set to move the code
	BLT	T1,ED$COD+RUNLEN-1 ; Move all the RUN UUO code

DEFINE ..DFT(NAME),<IRP <NAME>,<
	MOVE	T1,[XWD PDF$'NAME,DEF$'NAME] ;; Get the BLT pointer
	BLT	T1,DEF$'NAME+.FDLEN-1 ;; And copy the block
>> ; End of ..DFT(NAME)

; Now set up the defaults

	..DFT(<EW,EL,ER,EE,EQ>)

; Set up the default switch tables

	STORE	T1,ER$DFS,ER$DFS+<ER$END-ER$BEG>,-1 ; All defaults in ER

; Set up the EO instruction table.

	MOVX	A1,EOVAL	; Get the value
	PJRST	OLD.0		; And go set it
	SUBTTL	E Commands -- E. - Switch editing buffers

;+
;.HL1 SWTBUF
; This routine will cause the editing buffer to be changed to the given
;Q-register.  The editing buffer initially the "." Q-register.
;.literal
;
; Command format:
;
;	E.(Q-register)
;
; Q-register - This is the new editing buffer.
;.end literal
;-

SWTBUF:	SETZ	T1,		; Clear the default Q-register
	PUSHJ	P,SCNQRG	; Scan off the Q-reg names
	  ERROR	E.IQN		; ++ Invalid Q-reg name
	MOVE	T2,$QRFLG(T1)	; Get the flags
	TXNE	T2,QR$WRT	; Allowed to write into this?
	 ERROR	E.DOQ		; No, display only
	TXNE	T2,QR$TXT!QR$EDT ; Allowed to have text in this?
	 ERROR	E.VOQ		; No, value only
	MOVE	P1,T1		; Copy the index
	MOVEI	T1,TXTBUF+$QRTPT ; Get the address of the TPT
	SKIPE	$TPADR(T1)	; If not text then skip this
	 PUSHJ	P,M$RELB	; Release the block

	LOAD.	T1,QRGDTP,(P1)	; Get the Q-register data type
	CAXN	T1,$DTTXT	; Is there text in it?
	 JRST	SWTB.0		; Yes, leave it alone
	MOVX	T2,$DTTXT	; Get the new type
	XCT	RQRGTB(T1)	; And change types

	MOVX	T1,D.TXTS	; Get the default text size
	PUSHJ	P,M$GTXT	; Allocate a text buffer
	MOVEI	T2,$QRTPT(P1)	; Get the address
	PUSHJ	P,M$USEB	; Store it

; Now release the current text buffer

SWTB.0:	MOVEM	P1,CUREDT	; Save the QRG address we are currently editing
	LOAD.	T1,TPTADR,+$QRTPT(P1) ; Get the buffer address
	PUSHJ	P,S$TAGC	; Clean up any tags laying around
	LOAD.	T1,TPTADR,+$QRTPT(P1) ; Get the address of the block
	MOVEI	T2,TXTBUF+$QRTPT ; And the new text buffer
	PJRST	M$USEB		; Set it as the new text buffer
	SUBTTL	E Commands -- E$ - Set window items.

;+
;.HL1 E$
;This command will set which q-registers are typed on the screen for the
;screen editing.  It will require two arguments.
;.literal
;
; Command format:
;
;	m,nE$(q-register)
;
; m - Starting line number.
; n - Ending line number.
; q-register - Item to be displayed.
;
;.end literal
;-

SETWIN:	SETZ	T1,		; No default
	PUSHJ	P,SCNQRG	; Scan the q-register name
	 ERROR	E.IQN		; Illegal Q-register name
	LOAD	T2,$QRFLG(T1),QR$DIS ; Can we display this one ?
	JMPT	T2,[ERROR E.VOQ] ; No, Value only Q-register
	PUSHJ	P,QTXTEI	; Have any text in the Q-register ?
				;  Does not return if not
	MOVE	P1,T2		; Copy the address to a safe place
	SKIPN	$CRXYP(CRT)	; Have a terminal which supports this?
	 ERROR	E.NSM		; No, punt
	CAMLE	A1,A2		; Are they in the correct order
	 EXCH	A1,A2		; No - Put them in the correct order
	JUMPLE	A1,ERRLOR	; This one valid?
	JUMPLE	A2,ERRLOR	; How about this one
	CAMG	A1,$CRLIN(CRT)	; Within range ?
	 CAMLE	A2,$CRLIN(CRT)	; . . .
ERRLOR:	  ERROR	E.LOR		; ++ Line number out of range
	SOJ	A1,		; Decrement to internal form

; Now we must update the VIN block to include this QRG, remove any conflicting
;QRG, and update the max screen length seen so far.

	SKIPE	VINADR+$TPADR	; Already have the block?
	 JRST	SETW.1		; Yes, must go do all the checks
	MOVE	T1,A2		; Get the last line number
	ADDX	T1,$VIQRG-.BKLEN ; Get the correct length needed
	MOVX	T2,.BTMOV	; And the block type
	PUSHJ	P,M$ZBLK	; Get a block
	SUBX	T1,.BKLEN	; Point to the start of the block
	XMOVEI	T2,VINADR	; Get the address of the pointer
	PUSHJ	P,M$USEB	; Set it up
	MOVE	P2,T1		; Get a copy
	STOR.	A2,VINNLN,(P2)	; Store the number of lines
	JRST	SETW.3		; And go setup the QRG

; Here if we already have a VIN block.  Check to see if we are conflicting
;with any of the entries.
;First check to see if this QRG is already displayed.

SETW.1:	LOAD.	P2,TPTADR,+VINADR ; Get the address of the VIN block
	MOVE	T1,P1		; Get the address of the QRG
	PUSHJ	P,SC$CLS	; Clear out that section of video info

; See if we need to expand the block

SETW.2:	LOAD.	T2,VINNLN,(P2)	; Get the number of lines in the block
	CAML	T2,A2		; Enough?
	 JRST	SETW.3		; Yes, skip the expansion

	SUBM	A2,T2		; Get the amount we need to add
	MOVE	T1,P2		; Get the address of the block
	PUSHJ	P,M$APPD	; And expand the block
	 JRST	.+2		; Need to copy the data
	  JRST	SETW.3		; Nothing to copy

	MOVE	P2,T3		; Here also
	XMOVEI	T2,$VINLN(T1)	; Get the old address
	XMOVEI	T3,$VINLN(T3)	; And the new
	LOAD.	T1,VINNLN,(T1)	; And the old size
	AOJ	T1,		; Plus one word for the number of lines
	PUSHJ	P,M$MCOR	; Move the data

; Now set up the correct lines with the QRG address.  If there already is
;something displayed there, remove the display attributes.

SETW.3:	LOAD.	P2,TPTADR,+VINADR ; Get the address of the info
	CFMGE.	,VINNLN,(P2),A2	; This a new max?
	 STOR.	A2,VINNLN,(P2)	; Yes, save it
	MOVE	P3,A1		; Get the first line number
	ADD	P3,P2		; And point to the VIN info
	SUB	A2,A1		; Get the number of lines
	MOVE	P4,A2		; Get a copy

SETW.4:	LOAD.	T1,VINQRG,(P3)	; Get the QRG address
	JUMPE	T1,SETW.5	; If nothing was displayed here, try the next
	PUSHJ	P,SC$CLS	; Clear out this QRG display info

SETW.5:	STOR.	P1,VINQRG,(P3)	; Store the info
	AOJ	P3,		; Advance to the next line
	SOJG	P4,SETW.4	; And go do it

	BITON	T1,QR$VLU!QR$FCT,$QRFLG(P1) ; Flag this is displayed
	POPJ	P,		; And return
	SUBTTL	E Commands -- EV processing -- General command

;+
;.HL1 EV command
; The EV command is handled by the VIDEO routine.  This routine will set
;various terminal parameters, return information or set the terminal type
;for the user.  This command has the format of one of the following:
;.literal
;
;	arg1,arg2EV$		- Set parameter arg2 to have the value arg1
;	EVterminal$		- Set the terminal type to be 'terminal'
;	EVparameter$		- Return a value of a parameter
;	argEVparameter$		- Set the parameter to be ARG
;.end literal
;-

VIDEO:	MOVEI	T1,[ERROR E.UTK] ; Get the error name
	PUSHJ	P,F$SETI	; Set the input routine
	PUSHJ	P,F$SXBT	; Input a sixbit token
	TXNE	F,F.ARG		; An argument seen ?
	 JRST	VIDCHG		; Yes - Other type of processing
	MOVE	T2,CRTPTR	; Set up for the matching routine
	PUSHJ	P,LOKNAM	; Look for this in the table
	 JRST	[JUMPE	T2,VIDE.0	; If unknown see if parameter
		ERROR	E.ABT]		; Not - Ambig
	MOVEI	T2,-CRTTAB(T2)	; Calculate the offset

	MOVE	CRT,CRTDSP(T2)	; Get the first parameter
	MOVEM	CRT,CRTTYP	; Store the flags
; Check if there is an initialization string and if we are in video mode.
;If so, do the initialization now.

	JMPNS	.POPJ		; If not screen mode, just return
	PJRST	INTCRT		; Initialize the terminal

; Here if it was not a terminal type to set.  Try for a parameter

VIDE.0:	MOVE	T2,PARPTR	; Get the pointer to the parameter table
	PUSHJ	P,LOKNAM	; Lookup the value
	  JRST	[SKIPE	T2		; Unkown ?
		  ERROR	E.ABV		; Ambiguous parameter
		  ERROR	E.UTP]		; Unknown video parameter
	MOVEI	T1,-VPRMTB(T2)	; Get the offset into the table
	SKIPE	VPRMVAL(T1)	; Have something to do??
	 XCT	VPRMVAL(T1)	; Yes, do it
	SKIPE	T1,VPRMOFS(T1)	; Get the offset into the CRT block
	 MOVE	T1,CRTFNC(T1)	; And get the value
	PJRST	VALRET		; Go return the value

CRTPTR:	XWD -NUMCRT,CRTTAB	; Pointer to the table of CRT names
PARPTR:	XWD -VPRMLN,VPRMTB	; Pointer to the table of video parameters
	SUBTTL	E Commands -- EV processing -- Parameter setting

; Here if the EV command had numerical arguments

VIDCHG:	JUMPN	T1,VIDPRM	; Try for a keyword
	SUBI	A1,1		; Correct the offset (So symbols work)
	TXZE	F,F.ARG2	; Only one argument ?
	 ERROR	E.ROP		; ++ Read only parameter
	SKIPL	A1		; Check the range
	CAILE	A1,$CRMAX	; . . .
	ERROR	E.VOR		; ++ Value out of range
	MOVE	A1,CRTTYP(A1)	; Get the value
	JRST	VALRET		; Return the value
	SUBTTL	E Commands -- EV processing -- Parameter keywords

;VIDPRM - Routine to handle VIDEO terminals parameters.
;This routine will dispatch to the correct routine to handle the video
;parameters.

VIDPRM:	MOVE	T2,[XWD -VPRMLN,VPRMTB] ; Get the table offset
	PUSHJ	P,LOKNAM	; Lookup in the table
	  JRST	[SKIPE	T2		; Unknown ?
		 ERROR	E.ABV		; ++ Ambigous video parameter
		ERROR	E.UVP]		; ++ Unknown video parameter
	MOVEI	T2,-VPRMTB(T2)	; Get the offset
	SKIPE	VPRMRT(T2)	; Have a routine??
	 JRST	@VPRMRT(T2)	; Dispatch to the routine
	ERROR	E.ROP		; Read-only video parameter
	SUBTTL	E Commands -- EV processing -- Keyword table

DEFINE	VIDPR.,<
VPRM	LINE,,,RTLINE
VPRM	MODE,,,RTMODE
VPRM	NODE,,,RTNODE
VPRM	OFF,,,VPOFF
VPRM	ON,,,VPON
VPRM	REFRESH,,,VPREFRESH
VPRM	SCREEN,VPSCREEN,,RTSCREEN
VPRM	SCROLL,VPSCRL,,RTSCRL
VPRM	TRMOP,RTTRMP
VPRM	UPDATE,VPUP.0,,VPUPDATE
VPRM	WINDOW,VPWINDOW,,RTWINDOW
>; End of the VIDPR. definition

DEFINE	VPRM(A,B,C,D),<EXP SIXBIT |A| >

VPRMTB:	VIDPR.
	VPRMLN==.-VPRMTB

DEFINE	VPRM(A,B,C,D),<EXP B>
VPRMRT:	VIDPR.

DEFINE	VPRM(A,B,C,D),<EXP C>

VPRMOFS:
	VIDPR.			; Generate the offsets

DEFINE	VPRM(A,B,C,D),<IFNB <D>,<JRST D ;> 0>

VPRMVAL:
	VIDPR.			; Generate the instructions
	SUBTTL	E Commands -- EV processing -- SCROLL parameter

; This parameter is used to determine whether the command section of the screen
;should be scrolled or not.

VPSCRL:	TXZ	S,S.SCRL	; Assume no scrolling
	JUMPE	A1,.POPJ	; If zero, don't scroll
	TXO	S,S.SCRL	; Otherwise flag we should scroll if possible
	POPJ	P,		; And return

RTSCRL:	TXNE	S,S.SCRL	; Check the flag
	 PJRST	RTONES		; Return -1
	PJRST	RETZER		; Return 0
	SUBTTL	E Commands -- EV processing -- ON command

; This command will turn on OLD video mode.

VPON:	SKIPN	$CRXYP(CRT)	; Can we do this?
	 POPJ	P,		; No, just return
	TXOE	S,S.SCRN	; Flag we are in complete video mode now
	 POPJ	P,		; Already were, skip this
	SETZM	OUTFLG		; Clear the flag to avoid an unnecessary --cont--
	PUSHJ	P,INTCRT	; Initialize the terminal
	PUSHJ	P,T$SRTN	; And set up the typein/out routines
	SKIPE	T1,$CRERS(CRT)	; Have a way to erase the screen?
	 PUSHJ	P,SC$STR	; Yes, do it
	SETZM	CURPOS+$OFSX	; Remember where we are
	SETZM	CURPOS+$OFSY	;  .  .  .
	POPJ	P,		; And return

INTCRT:	SKIPE	$CRINT(CRT)	; Need to do this?
	 XCT	$CRINT(CRT)	; Initialize the terminal
	POPJ	P,		; And return

	SUBTTL	E Commands -- EV processing -- OFF command

; Here to clear video mode

VPOFF:	TXZN	S,S.SCRN	; Clear the flags
	 POPJ	P,		; Return
	PUSHJ	P,SC$ERS	; Erase the whole screen
	XCT	$CRFIN(CRT)	; Cause the terminal to be put in reasonable state
	PUSHJ	P,SC$RVD	; Return the video info
	PUSHJ	P,T$SRTN	; Set the typein routines
	PJRST	.TCRLF		; And type a CRLF

	SUBTTL	E Commands -- EV processing -- MODE command
;+
;.hl2 RTMODE
; This command will return the state of the video mode flags.
;It returns values as follows: 0 for video processing turned off
;(version 124A terminal I/O), -1 for video processing turned on in
;version 125 mode, 1 for video processing turned on in IMMEDIATE
;(MAGIC) mode.
;-

RTMODE:	JMPNS	RETZER		; Return a zero if not on at all
	MOVX	A1,-1		; No, get the correct value
	PJRST	VALRET		; And return it
	SUBTTL	E Commands -- EV processing -- WINDOW command
	SUBTTL	E Commands -- EV processing -- SCREEN command

;+
;.HL2 RTWINDOW
;Return the widow size of the window.
;-

RTWINDOW:
RTSCREEN:
	SKIPN	T1,SCRNLN	; Have the screen set up yet?
	 SKIPE	T1,CRTLEN	; Have the length set by the user yet?
	  JRST	RTWI.1		; Yes, go return it
	SKIPN	T1,TRMLEN	; No, get the length from the TRMOP
	 MOVE	T1,$CRLIN(CRT)	; Wasn't one, get the default
RTWI.1:	SKIPN	A1,SCRWID	; Get the width of the screen
	 SKIPE	A1,CRTWID	; Isn't one yet, get that set by user
	  JRST	.+2		; We have the width
	   MOVE	A1,TRMWID	; Otherwise use width from TRMOP.
	HRL	A1,T1		; Set up the values
	AOJA	A1,VALRET	; And return the value



; Here for EVSCREEN and EVWINDOW commands which had arguments
; A1 will contain the new width, and A2 the new length (if given)

VPWINDOW:
VPSCREEN:
	JUMPL	A1,[MOVE A1,$CRWID(CRT)	; Negative value means use default
		JRST	VPWI.1]		;  .  .  .
	SOJGE	A1,.+2		; Convert to internal width
	 SETZ	A1,		; Zero or one means use default
VPWI.1:	ANDX	A1,777		; Keep it reasonable
	MOVEM	A1,CRTWID	; Save the width
	TXNN	F,F.ARG2	; Second argument given?
	 POPJ	P,		; No, just return now
	JUMPGE	A2,.+2		; Want default value?
	 MOVE	A2,$CRLIN(CRT)	; Yes, get it
	ANDX	A2,777		; Keep the length reasonable
	MOVEM	A2,CRTLEN	; Save the value
	POPJ	P,		; And return
	SUBTTL	E Commands -- EV processing -- Refresh command

VPREFRESH:
SC$REF:	PUSHJ	P,SC$ERS	; Erase the screen
	POPJ	P,		; Return


	SUBTTL	E Commands -- EV processing -- Update command

;.hl2 VPUPDATE
; This routine is called when a EVUPDATE$ command is given. It will
;cause the screen to be updated.
;-

VPUP.0:	$SAVE	<NOTYIA>	; Save the type-ahead flag
	MOVEM	A1,NOTYIA	; Save the new value

VPUPDATE:
	MOVX	T1,.TRUE	; SC$UPD should use new user info if any
	JRST	SC$UPD		; Call the update routine
	SUBTTL	E Commands -- EV processing -- NODE command

;+
;.HL1 EVNODE
; This command will return the value of the node number to which the
;controlling terminal is attached.
;-

RTNODE:	MOVE	A1,TRMUDX	; Get our UDX
	GTNTN.	A1,		; Get the node number
	 JRST	RETZER		; Not a network system
	HLRZ	A1,A1		; Get the node number for our terminal
	JRST	VALRET		; And return it


	SUBTTL	E Commands -- EV processing -- LINE command

;+
;.HL1 EVLINE
; This command returns the line number on the node on which the terminal
;controlling this job is connected.
;-

RTLINE:	MOVE	A1,TRMUDX	; Get the teminal UDX
	MOVE	T1,A1		; Get a copy
	SUBX	T1,.UXTRM	; And convert to line number
	GTNTN.	A1,		; Get the node and line on node
	 MOVE	A1,T1		; Not a network system, return the line number
				; from TRMNO.
	HRRZ	A1,A1		; Clear the node number
	JRST	VALRET		; And return the value
	SUBTTL	E Commands -- EV processing -- TRMOP command

;+
;.HL1 EVTRMOP
; This command will perform a TRMOP. for the users terminal.  A1 will
;contain the TRMOP. function, and A2 will contain the argument (if any).
;It will return the value from the TRMOP. if it returns one.
;-

RTTRMP:	MOVE	T2,A1		; Get the function code
	MOVE	T3,TRMUDX	; And the UDX
	MOVE	T4,A2		; Get the argument (maybe)
	MOVX	T1,<XWD 3,T2>	; Get the pointer
	CAXL	A1,^O1000	; Legal function?
	 TRMOP.	T1,		; Yes, do it
	  ERROR	E.ITT		; Illegal function
	MOVE	A1,T1		; Get the return value
	CAXE	T1,<XWD 3,T2>	; Did we get our arg pointer back?
	 PJRST	VALRET		; No, return the value
	POPJ	P,		; Yes, no value
	SUBTTL	E Commands -- E<(Q-reg) - Type input file name into buffer

;+
;.HL1 E<
;This command will type the input file specification into the current editing
;buffer.
;.literal
; Command usage:
;	E<(Q-register)$
;
;.end literal
;-

E$LANG:	SETZ	T1,		; No default
	PUSHJ	P,SCNQRG	; Scan for the Q-register name
	 ERROR	E.IQN		; Missing Q-register name
	PUSHJ	P,QTXTEI	; Have any text in the Q-register ?
	PUSHJ	P,GETFDI	; Get the FD assoicated with the input file
	 ERROR	E.NFI		; No file for input

; Here for the typing of the FD into the current editing buffer.  Set up
; a $STRING to type the information into the buffer and return

LANG.0:	MOVE	P1,T1		; Copy the information to a safer place
	MOVEI	T1,TXTBUF+$QRTPT ; Get the current editing buffer
	MOVEI	T2,[$STRING(<^F/P1/^N>)] ; Get the string to type
	PJRST	.INSRT		; Insert it into the buffer
	SUBTTL	E Commands -- E>(Q-reg) - Type output file name into buffer

;+
;.HL1 E>(Q-reg)
;This command will cause the output file specification associated with
;the named Q-register to be typed into the current editing buffer.
;.literal
; Command Usage:
;
;	E>(Q-register-name)$
;
;.end literal
;-

E$RANG:	SETZ	T1,		; No default name
	PUSHJ	P,SCNQRG	; Scan for the Q-register name
	 ERROR	E.IQN		; Failed, Issue an error message
	PUSHJ	P,QTXTEI	; Have any text in the Q-register ?
	PUSHJ	P,GETFDO	; Get the output FD block
	  ERROR	E.NFO		; No file for output
	PJRST	LANG.0		; Join the common type out routine
	SUBTTL	E commands -- EJ - Set pointer for other than current buffer

;+
;.HL1 EJCMD (EJ command)
; This command will perform a "J" command for a Q-reg other than the current
;editing buffer.
;Command format:
;.b.c;nEJ(Q-register name)
;-

EJCMD:	SETZ	T1,		; Clear T1
	PUSHJ	P,SCNQRG	; Scan off the Q-register name
	 ERROR	E.IQN		; Illegal Q-register name
	PUSHJ	P,QTXTEI	; Have any text in the Q-register ?
	PJRST	JMP1		; And go set it
	SUBTTL E Commands -- EL -- LOGCHR

;+
;.hl1 EL command
;.hl2 LOGCHR
; This routine is called to write the current character into the log
;file.
;.b.literal
; Usage:
;	MOVEI	CH,Character
;	PUSHJ	P,LOGCHR
;	 (return always)
;
;.end literal
;-


LOGCHR:	TXNN	S,S.SLOG	; Suppressing the log file?
LOGC.0:	 SKIPN	FDB$EL		; Have a log file?
	  POPJ	P,		; No, return
	$SAVE	<T1,T2,T3,T4,LASFDB> ; Save the Tx ac's
	MOVE	T1,FDB$EL	; Get the fdb address
	PUSHJ	P,F$WRIT	; And write the character
	 PJRST	F$ERR		; Give up
	SKIPE	T1,L$COUNT	; Want checkpoints at all?
	 SOSLE	L$CNTR		; Yes, want one now?
	  POPJ	P,		; No, return
	MOVEM	T1,L$CNTR	; Reset the counter
	MOVE	T1,FDB$EL	; Yes, get the FDB address again
	PUSHJ	P,F$CHKP	; Checkpoint it
	POPJ	P,		; All done
	SUBTTL	E Commands -- EL -- MAKLOG

;+
;.hl2 MAKLOG
; This routine will handle the EL command. If no argument is given
;this will start the log file. If an argument is given it will change
;whether input or output or both are written to the log file. If the
;argument is negative it will close the log file.
;-


MAKLOG:	TXNE	F,F.ARG		; Argument given?
	 JRST	CHANGL		; Yes, go change what we are doing
	SKIPN	T1,FDB$EL	; Have a log file already?
	 JRST	MAKL.1		; No, skip this
	PUSHJ	P,F$CLOS	; Yes, close the file
	 PJRST	F$ERR		; Go give up
	SETZ	T1,		; Clear T1
	EXCH	T1,FDB$EL	; Get the address back
	JRST	MAKL.2		; And skip getting an FDB

MAKL.1:	MOVX	T1,.FDLEN	; Get the length
	MOVX	T2,.BTFDB	; Get the block type
	PUSHJ	P,M$GBLK	; Get the block

MAKL.2:	$SAVE	<P1>		; Save P1
	MOVE	P1,T1		; Get the FDB address
	STORE	T2,SL$BEG,SL$END,-1 ; Clear the switches
	MOVEI	T2,LOGSWT	; Get the switch pointer
	PUSHJ	P,F$PARS	; Parse the file spec
	 PJRST	F$ERR		; Give an error message

	MOVEI	T3,PDF$EL	; Get the permanent default address
	MOVEI	T2,DEF$EL	; Get the default FDB
	MOVE	T1,P1		; And the FDB address
	PUSHJ	P,F$DFLT	; And default it
	TXO	S,S.LIN!S.LOUT	; Flag input and output logged
	SKIPL	LS$NOI		; /NOINPUT given?
	 TXZ	S,S.LIN		; Flag he wants input
	SKIPL	LS$NOO		;  .  .  .
	 TXZ	S,S.LOUT	; Flag he wants output
	SKIPL	LS$VID		; Want video info?
	 TXO	S,S.LVID	; Yes, flag that
	SKIPL	LS$IIN		; Image type in wanted?
	 TXO	S,S.LIIN	; Yes, flag that
	MOVE	T2,P1		; Get the FDB address
	SKIPGE	T1,LS$CHK	; Get the frequency of checkpoints
	 SETZ	T1,		; 0 and -1 mean never
	MOVEM	T1,L$COUN	; Save for reseting the counter
	MOVEM	T1,L$CNTR	; And save in the counter
	MOVX	T1,$IOWRI	; Get the code
	SKIPL	LS$APP		; Or should it be append
	 MOVX	T1,$IOAPP	; Yes, get the right code
	PUSHJ	P,F$OPEN	; And open the file
	 JRST	MAKL.5		; Skip
	MOVEM	P1,FDB$EL	; Save the FDB address
	POPJ	P,		; And return

MAKL.5:	SETZM	FDB$EL		; Clear the pointer
	TXZ	S,S.LIN!S.LOUT	; And flag no logging
	PJRST	F$ERR		; And go give the error

DEFINE SWT$EL,<
SW	APPEND,LS$APP,,1,
SW	CHECKP,LS$CHK,.IDECW,^D640,
SW	IMGINP,LS$IIN,,1,
SW	NOINPUT,LS$NOI,,1,
SW	NOOUTPUT,LS$NOO,,1,
SW	VIDEO,LS$VID,,1,
> ; End of SWT$EL definition
	DOSWTCH(LOG,SWT$EL)	; Generate the switch tables
LOGSWT:	SWTPTR(LOG)		; Generate the pointers to the switch table


; Here when :nEL is given. Reset the /NOINPUT or /NOOUTPUT flags
; Argument bits:
	AB$OUT==1		; Output wanted
	AB$INP==2		; Input wanted
	AB$VID==4		; Video wanted
	AB$IIN==10		; Image input wanted

CHANGL:	PUSHJ	P,SKRCH		; Get the next character
	 ERROR	E.NAL		; Must have the altmode
	CAXE	CH,.CHESC	; Is it one?
	 ERROR	E.NAL		; No, complain
	SKIPE	T1,FDB$EL	; Do we have one?
	 SKPOPN	0(T1)		; Yes, is it open?
	  ERROR	E.NLF		; No log file open
	TXNE	A1,AB$INP	; Want input?
	 TXO	S,S.LIN		; Yes, flag he wants input
	TXNE	A1,AB$OUT	; Want output?
	 TXO	S,S.LOUT	; Flag he wants output
	TXNE	A1,AB$VID	; Want video logged?
	 TXO	S,S.LVID	; Yes, flag it
	TXNE	A1,AB$IIN	; Want image of input?
	 TXO	S,S.LIIN	; Yes, flag that
	JUMPGE	A1,.POPJ	; If the arg is negative close the file
	TXZ	S,S.LIN!S.LOUT!S.LVID ; Flag no more logging
	PUSHJ	P,F$CLOS	; Close the file
	 PJRST	F$ERR		; Couldn't?
	MOVE	T1,FDB$EL	; Get the FDB
	SETZM	FDB$EL		; Clear the pointer
	PJRST	M$RBLK		; And return the FDB
	SUBTTL E Commands -- EE -- Write out a save file

;+
;.hl1 EECMD
; The EE command causes TECO to write out its low segment into a save
;file which is set up so that when the save file is run it will
;GETSEG TECO's high segment and continue execution with the command
;after the EE command.
;-

EECMD:	MOVEM	17,EEACS+17	; Save 17 for restart
	MOVEI	17,EEACS	; And set up to save the world
	BLT	17,EEACS+16	; Save the rest
	MOVE	17,EEACS+17	; And restore 17
	MOVX	T1,.FDLEN	; Get the length
	MOVX	T2,.BTFDB	; And the block type
	PUSHJ	P,M$GBLK	; Get the FDB
	MOVE	P1,T1		; Save in safe place
	SETZ	T2,		; No switches
	PUSHJ	P,F$PARS	; Parse the file spec
	 PJRST	F$ERR		; Couldn't

	MOVE	T1,P1		; Get the FDB address
	MOVEI	T2,DEF$EE	; Get the default block
	MOVEI	T3,PDF$EE	; Get the perm defaults
	PUSHJ	P,F$DFLT	; And default it
	STORI.	$FMBIN,T1,FDBMOD,(P1) ; store the mode
	MOVX	T1,$IOWRI	; Get the functin
	MOVE	T2,P1		; And the FDB address
	PUSHJ	P,F$OPEN	; And open the file
	 PJRST	F$ERR		; Couldn't, give an error

	MOVE	T1,[XWD GETBLK,STARTL] ; Move the restart code into the
	BLT	T1,STARTL+STR.LN-1 ; low segment
	$SAVE	<.JBSA,.JBCOR,FDB$EL> ; Save the locs we must change
	SETZM	FDB$EL		; Clear the log file pointer
	MOVEI	T1,STARTL	; And set up the new start address
	HRL	T1,.JBFF	; And first free
	MOVEM	T1,.JBSA	; Save it
	HRR	T1,.JBREL	; Get the end of core address
	MOVEM	T1,.JBCOR	; And store it
	MOVEI	P2,.JBHRL+1	; Start after HRL
EECM.3:	SKIPE	(P2)		; Word zero?
	 JRST	EECM.4		; No, first non-zero word
	CAMGE	P2,FSTBLK	; Into free core yet?
	 AOJA	P2,EECM.3	; No, bump to the next word

EECM.4:	MOVE	P3,P2		; Get the address of first non-zero word
EECM.B:	SKIPN	(P2)		; Is this word zero?
	 JRST	EECM.5		; Yes, end of non-zero block
	CAMGE	P2,FSTBLK	; Hit allocated section yet?
	 AOJA	P2,EECM.B	; No, try next word
	MOVE	P4,P3		; Get the address
	SETZ	P3,		; Clear the junk address
	JRST	EECM.7		; And go handle free core

EECM.5:	SUBM	P3,P2		; Get the different
	JUMPE	P2,[MOVE P2,FSTBLK	; If nothing to write, go handle
		JRST	EECM.A]		; Go handle allocated core
	MOVSI	P2,(P2)		; Get the count into the left half
	HRRI	P2,-1(P3)	; And make the IOWD
	MOVE	CH,P2		; First write the IOWD
	MOVE	T1,P1		; Get the address of the FDB
	PUSHJ	P,F$WRIT	; And write the word
	 PJRST	F$ERR		; Give up

EECM.6:	MOVE	CH,1(P2)	; Get the next word
	MOVE	T1,P1		; Reset the FDB address
	PUSHJ	P,F$WRIT	; Write the word
	 PJRST	F$ERR		; Give up
	AOBJN	P2,EECM.6	; Loop for all the words
	AOJ	P2,		; Point to the next word to check
	CAMGE	P2,FSTBLK	; Are we into allocated core?
	 JRST	EECM.3		; No, go look for next non-zero word

IFN FTDEBUG,<
	CAME	P2,FSTBLK	; Is this the right value?
	 STOPCD	NFB,<EE loop stopped after FSTBLK>
> ; End of IFN FTDEBUG

EECM.A:	SETZB	P3,P4		; Flag we haven't seen anything yet
EECM.7:	LOAD.	T1,BLKTYP,(P2)	; Get the block type
	PUSHJ	P,@EETBL(T1)	; Do the correct thing for this block type
	LOAD.	T1,BLKSIZ,(P2)	; Get the size of this block
	MOVX	T2,BF.LST	; Make sure not last on page
	TDNN	T2,.BKFLG(P2)	;  .  .  .
	 JRST	EECM.8		; It isn't
	LOAD.	T2,BLKNXT,(P2)	; Get the pointer to the next page
	JUMPE	T2,EECM.9	; If no more we are done
	PG2ADR	T2		; And convert to an address
	SKIPA	P2,T2		; Get the address
EECM.8:	ADD	P2,T1		; Point to the next block
	JRST	EECM.7		; And loop

EECM.9:	ADD	P2,T1		; Point to the end
	SKIPE	P3		; End a junk block?
	 PUSHJ	P,ENDJNK	; Yes, end the block
	SKIPE	P4		; Any non-zero block to end?
	 PUSHJ	P,ENDBLK	; Yes, end it
	MOVE	CH,[JRST STARTL] ; Get the start instruction
	MOVE	T1,P1		; And the FDB address
	PUSHJ	P,F$WRIT	; Write it
	 PJRST	F$ERR		; Give up
	MOVE	T1,P1		; Get the address
	PUSHJ	P,F$CLOS	; And close the file
	 PJRST	F$ERR		; Couldn't
	MOVE	T1,P1		; Get the address again
	PJRST	M$RBLK		; And return it


TABDEF	EE,.BT,EETXT		; Generate the dispatch table
	TABENT	JNK,EEJNK	; Do different things for junk
	TABENT	FDB,EEJNK	; and FDB's
	TABENT	BUF,EEJNK	; And buffers
TABEND

; Here for a block which is neither junk or an FDB

EETXT:	SKIPE	P3		; Have a previous junk block?
	 PUSHJ	P,ENDJNK	; Yes, end it
	LOAD.	T1,BLKSIZ,(P2)	; Get the size of this block
	MOVN	T1,T1		; And make an loop counter
	MOVSI	T1,(T1)		;  .  .  .
	HRRI	T1,(P2)		;  .  .  .

EETX.2:	SKIPN	(T1)		; Zero word?
	 JRST	EETX.4		; Yes, go handle it
	JUMPN	P4,EETX.3	; First non-zero word?
	MOVEI	P4,(T1)		; Yes, get the address
EETX.3:	AOBJN	T1,EETX.2	; Loop through the block
	POPJ	P,		; Return

EETX.4:	JUMPE	P4,EETX.3	; If not first zero word, just loop
	PUSH	P,P2		; Save P2
	MOVEI	P2,(T1)		; Get the address of the word
	PUSHJ	P,ENDBLK	; No, end the current block
	POP	P,P2		; Restore P2
	AOBJN	T1,EETX.2	; And loop
	POPJ	P,		; Return since we are done

ENDBLK:	$SAVE	<T1,P2>		; Save P2
	SUBM	P4,P2		; And get the number to read
	HRLI	P4,(P2)		; Make the IOWD
	SOJ	P4,		;  .  .  .
	MOVE	CH,P4		; And write
	MOVE	T1,P1		; it into the file
	PUSHJ	P,F$WRIT	;  .  .  .
	 PJRST	F$ERR		; And give the error

ENDB.1:	MOVE	CH,1(P4)	; Get the word
	MOVE	T1,P1		; And reset the FDB
	PUSHJ	P,F$WRIT	; Write out the word
	 PJRST	F$ERR		; Give the error
	AOBJN	P4,ENDB.1	; Loop for the whole block
	SETZ	P4,		; In a zero block now
	POPJ	P,		; Return

; Here for an FDB or a junk block

EEJNK:	JUMPN	P4,EEJN.1	; In a good section already?
	JUMPN	P3,.POPJ	; Already in a junk section?
	MOVE	P3,P2		; No, remember where this one is
	POPJ	P,		; And return
EEJN.1:	$SAVE	<P2>		; Save P2
	AOJ	P2,		; And bump it
	PJRST	ENDBLK		; And end the current block


; Here to end a junk section. P2 contains address after the section, P3
;the address of the start of the section.

ENDJNK:	CAIN	P3,-1(P2)	; Was this right before this block?
	 JRST	[MOVE	P4,P3		; Yes, get the address for later
		SETZ	P3,		; Flag no junk
		POPJ	P,]		; And return
	MOVEI	CH,-1(P3)	; Get the address for the IOWD
	HRLI	CH,-1		; And the count
	MOVE	T1,P1		; Get the FDB address
	PUSHJ	P,F$WRIT	; And write the IOWD
	 PJRST	F$ERR		; Couldn't
	MOVE	CH,P2		; Get the end address
	SUBI	CH,(P3)		; And get the length
IFN <ALIGN.(BK.SIZ)>,LSH CH,<ALIGN.(BK.SIZ)> ; Put in correct place
	STORI.	.BTJNK,T1,BLKTYP,+CH ; Store the block type
	CAML	P2,.JBFF	; Is this the last block?
	 TXO	CH,BF.LST	; Yes, flag it
	MOVE	T1,P1		; Get the FDB address
	PUSHJ	P,F$WRIT	; And write the word
	 PJRST	F$ERR		; Couldn't
	SETZ	P3,		; Not in a junk section anymore
	POPJ	P,		; Return
	SUBTTL E Commands -- EE - Restart code

GETBLK:	TDZA	1,1		; Remember not CCL entry
	 SETO	1,		; Flag CCL
	MOVEM	T1,CCLSW	; Flag whether CCL entry or not
	MOVE	2+$RNDEV,RUNDEV	; Get the device
	MOVE	2+$RNNAM,RUNNAM	; And the name
	MOVEI	2+$RNPPN,RUNPTH	; And the path block address
	SETZB	2+$RNEXT,2+$RNCOR ; clear the rest
	MOVEI	0,2		; Get the address of the GETSEG block
	SETZ	1,		; Assume non-physical
	SKIPE	PHYSON		; Should we do physical only GETSEG?
	 TRO	1,UU.PHY	; Yes, flag it
	GETSEG	0,(1)		; Get back our original segment
	 HALT
	MOVEI	P1,%TECOV	; Get the normal low segment version
	MOVEI	P2,%TECTV	; And the terminal dependent section
	HRRZ	T1,.JBREL	; Get the end of the low seg
	TXNN	T1,1B18		; Over 128k??
	 MOVEI	T1,400000-1	; No, use 400000 as default
	HRLI	T2,-2		; Get it from monitor
	HRRI	T2,.GTUPM	; If we can
	GETTAB	T2,		;  .  .  .
	 HRLI	T2,1(T1)	; Can't, use our default
	HLRZ	T2,T2		; Get the offset
	ANDI	T2,777000	; Clear low order bits
	JRST	.JBHDA(T2)	; And go restart

STR.LN==.-GETBLK
	SUBTTL	E Commands -- EE -- RST - Restart routine

;+
;.HL1 RST
; This routine is called from the low segment after TECO's high
;segment has been GETSEG'ed from an EE'ed file. It is entered
;with P1= %TECOV and P2=%TECTV from the copy which wrote the EE'ed file, and
;T2= the base address of the high segment.
;-

RST:	CAIN	P1,%TECOV	; Check if this is the correct version of the low segment
	 CAIE	P2,%TECTV	; Terminal low segment version the same?
	  JRST	.+2		; One or the other wrong, give the error
	   JRST	RST1		; Yes, all is okay
	OUTSTR	[ASCIZ	.?TECWVT Wrong version of TECO GETSEG'd
.]
	MONRT.			; Exit to the monitor
	JRST	.-1		; Can't really continue

RST1:	MOVE	T1,.JBHSA(T2)	; Get the starting address
	MOVEM	T1,.JBSA	; Reset it
	MOVE	T1,.JBHCR(T2)	; Get the copy of .JBCOR
	MOVEM	T1,.JBCOR	; Reset it
	MOVE	T1,.JBH41(T2)	; And get the error instruction
	MOVEM	T1,.JB41	; Save it
	MOVE	T1,.JBHRN(T2)	; Get the values to fix .JBHRL and .JBREN
	HLLM	T1,.JBHRL	; Fix .JBHRL
	HRRZM	T1,.JBREN	; And .JBREN
	MOVSI	17,EEACS	; Set up to restore the registers
	BLT	17,17		; Do it

; Now to fix up any text blocks (or FDB's) so we don't think we have any
;open files.

	MOVE	T1,FSTBLK	; Get the first block

RST.2:	CFXE.	T2,BLKTYP,(T1),.BTTXT ; Text block?
	 JRST	RST.3		; No, go check if an FDB
	BITOFF	T2,TF.OPO!TF.OPI,.BKTFL(T1) ; Yes, clear the open file flags
	JRST	RST.4		; And try the next

RST.3:	CFXE.	T2,BLKTYP,(T1),.BTFDB ; Is this an FDB?
	 JRST	RST.4		; No, try the next block
	STORI.	.BTJNK,T2,BLKTYP,(T1) ; Yes, make it junk

RST.4:	MOVX	T2,BF.LST	; Last block?
	TDNE	T2,.BKFLG(T1)	;  .  .  .
	 JRST	RST.5		; Yes, go check page field
	LOAD.	T2,BLKSIZ,(T1)	; No, get the size
	ADD	T1,T2		; And advance to the next block
	JRST	RST.2		; Loop

RST.5:	LOAD.	T1,BLKNXT,(T1)	; Get the next block page number
	PG2ADR	T1		; Convert to address
	JUMPN	T1,RST.2	; And loop if any address
	PUSHJ	P,M$GC		; Do a garbage collection to clean up

; Now re-initialize some things

	PUSHJ	P,U$INIT	; Do the UUO initialization
	PUSHJ	P,T$INIT	; Reintialize the terminal
	PUSHJ	P,I$JOB		; Do the job initialization
	PUSHJ	P,I$INIT	; Reinitialize the immediate mode stuff
	POPJ	P,		; And return
	SUBTTL	E Commands -- EC - Perform a garbege collection

;+
;.HL1 ECCMD
;This routine will force a garbage collection to occur, so that TECO
;may shrink in size.
;-

ECCMD:	TXNE	F,F.ARG		; Have an arg?
	 JUMPG	A1,ECCM.9	; Yes, if positive expand
	MOVE	P1,.JBREL	; Get our current size
	TXO	F,F.ECMD	; Flag this is for an EC command
	PUSHJ	P,S$QRGC	; Collect all zero valued Q-registers
	LOAD.	T1,TPTADR,+$QRTPT+ERRQRG ; Get the last error message QRG
	JUMPE	T1,ECCM.7	; Anything there?
	LOAD.	T2,BLKEND,(T1)	; Get the number of chars in the buffer
	SETZ	T3,		; Delete from the first character
	PUSHJ	P,M$SRNK	; Shrink the buffer
ECCM.7:	LOAD.	T1,TPTADR,+$QRTPT+QTAB+QRGIDX(?) ; Get the address of the last error command
	JUMPE	T1,ECCM.8	; Anythin here?
	LOAD.	T2,BLKEND,(T1)	; And the size
	SETZ	T3,		; Delete from first char
	PUSHJ	P,M$SRNK	; Shrink the buffer
ECCM.8:	PUSHJ	P,M$GC		; Collect the garbage
	TXZ	F,F.ECMD	; Turn off the EC command flag
	MOVE	T1,FSTBLK	; Get the first block
	MOVX	T2,BF.LST	; And get the flag to check
	SETZ	T4,		; Flag no previous block

ECCM.1:	TDNE	T2,.BKFLG(T1)	; Is this the last block?
	 JRST	ECCM.2		; Yes, go handle it
	LOAD.	T3,BLKSIZ,(T1)	; No, get the size
	MOVE	T4,T1		; Remember the previous block
	ADD	T1,T3		; And point to he next block
	JRST	ECCM.1		; Loop

ECCM.2:	LOAD.	T2,BLKNXT,(T1)	; Get the next page number
	JUMPE	T2,ECCM.3	; If done go check if we need this block
	MOVE	T1,T2		; Otherwise get the page number
	PG2ADR	T1		; And convert to an address
	SETZ	T4,		; Remember the previous
	JRST	ECCM.1		; Try again

ECCM.3:	CFXE.	T2,BLKTYP,(T1),.BTJNK ; Is this block junk?
	 POPJ	P,		; No, can't shrink
	MOVEI	T2,-1(T1)	; Yes, get the address minus one
	CORE	T2,		; And try to shrink
	 JFCL			; Shouldn't happen
IFN FTDEBUG,<
	SKIPN	T4		; Have a previous block?
	 STOPCD	(NPB,<No previous block - no free core in use>)
> ; End of IFN FTDEBUG
	BITON	T3,BF.LST,.BKFLG(T4) ; Make the previous block the last
	MOVEM	T1,.JBFF	; Save the new first free
	MOVE	T1,.JBREL	; Get the current end
	CAML	T1,P1		; Did we really shrink?
	 POPJ	P,		; No, return
	AOJ	T1,		; Bump the number
	ADR2PG	T1		; Convert to a page number
	MOVE	P1,T1		; Get the number
	MOVEI	T1,[$STRING(<[^D/P1/P core]>)] ; Get the string to type
	TXNE	F,F.ARG		; Have an arg?
	 JUMPL	A1,.POPJ	; Yes, if negative don't type
	PJRST	T$TYPE		; Type it

ECCM.9:	PG2ADR	A1,		; Convert to a word number
	MOVE	T1,A1		; Get it
	CAMG	T1,.JBREL	; Will it really expand?
	 POPJ	P,		; No, just return
	CORE	T1,		; Try to expand
	 JFCL			; Ignore the error
	POPJ	P,		; And return
	SUBTTL	E Commands -- EI and EP - Read into a Q-register

;+
;.hl1 EI and EP commands
; These commands cause an entire file to be read into a Q-register.
;EP just reads the file, EI will cause the Q-register to be executed
;after it is read (effectively doing an M command on the Q-reg after
;reading the file).
;-


EICMD:	TXOA	S,S.DOIT	; Flag to execute after file is read
EPCMD:	 TXZ	S,S.DOIT	; Flag no execution
	MOVX	T1,"*"		; Get the default Q-register
	PUSHJ	P,SCNQRG	; Scan off the Q-register name
	 JFCL			; Shouldn't happen
	MOVE	T2,$QRFLG(T1)	; Get the flags
	CAME	T1,CUREDT	; Current buffer?
	 TXNE	T2,QR$WRT	; Allowed to write into this?
	  ERROR	E.DOQ		; No, display only
	TXNE	T2,QR$TXT	; Allowed to have text in this?
	 ERROR	E.VOQ		; No, value only
	MOVE	P1,T1		; Save the index
	MOVX	T1,.FDLEN	; Get the descriptor block
	MOVX	T2,.BTFDB	; And the block type
	PUSHJ	P,M$GBLK	; Get the block
	MOVE	P2,T1		; Remember where it is
	SETZ	T2,		; No switches
	PUSHJ	P,F$PARS	; Parse the spec
	 PJRST	F$ERR		; Couldn't
	MOVEI	T2,DEF$EQ	; Get the default block address
	MOVE	T1,P2		; Get the FDB address back
	MOVEI	T3,PDF$EQ	; Get the permanent defaults
	PUSHJ	P,F$DFLT	; And default it
;Here to LOOKUP file for EI and EP. 
;If no directory or device has been specified, then look for the
;file as follows:
;	[-]
;	[,,TEC]/SCAN
;	TED:

	MOVX	T1,FD.PTH	; Check if PPN or path given
	CFXN.	,FDBDEV,(P2),0	; Device given?
	 TDNE	T1,.FDFLG(P2)	; Or PPN or path?
	  TDZA	P3,P3		; Yes, no random searches
	   MOVX	P3,3		; No, start with sequence 3
EPILOP:	JRST	@EPITBL(P3)	; Do the right thing for this pass

EPITBL:	EXP	EPIDFT		; Default's from block
	EXP	EPITED		; TED:
	EXP	EPISFD		; DSK:[,,TEC]/SCAN
	EXP	EPIDSK		; DSK:[-]


; Here for DSK:[,,TEC]/SCAN

EPISFD:	MOVE	T1,MYPPN	; Get out PPN
	STOR.	T1,FDBPPN,(P2)	; Store it
	STORI.	<SIXBIT |TEC|>,T1,FDBSFD,(P2) ; Store the SFD name
	BITON	T1,FD.SCN!FD.PTH,.FDFLG(P2) ; And flag /SCAN
	FALL	EPIDSK		; And join common disk code

; Here to look on DSK:[-]

EPIDSK:	STORI.	<SIXBIT |DSK|>,T1,FDBDEV,(P2) ; Store the device name
	PJRST	EPIDFT		; Go join common open routine

; Here to look on TED:

EPITED:	STORI.	<SIXBIT |TED|>,T1,FDBDEV,(P2) ; Store the device name
	ZERO.	,FDBPPN,(P2)	; Clear the path
	ZERO.	,FDBSFD,(P2)	;  .  .  .
	FALL	EPIDFT		; Join common routine
; Here to open the file
EPIDFT:	MOVX	T1,<SIXBIT |DSK|> ; Get the default name
	CFXN.	,FDBDEV,(P2),0	; Have a device?
	 STOR.	T1,FDBDEV,(P2)	; No, use DSK
	MOVX	T1,$IOREA	; Get the function
	MOVE	T2,P2		; And the FDB
	PUSHJ	P,F$OPEN	; Open the file
	 JRST	.+2		; Couldn't, check if more to try
	  JRST	EPIRED		; Go it, go read the file

	SOJG	P3,[MOVE T1,P2		; Get the FDB address
		PUSHJ	P,F$RSET	; Clear the channel
		JRST	EPILOP]		; Loop if anything left
	PJRST	F$ERR		; No, give up

; Here after file has been opened.

EPIRED:	MOVX	T1,D.EPIS	; Get the default size
	PUSHJ	P,M$GTXT	; Get the text buffer
	MOVEI	T2,EPIQRG	; Get the pointer address
	PUSHJ	P,M$USEB	; And set it up
	STOR.	P2,BLKFDI,(T1)	; Store as input file
	BITON	T2,TF.OPI,.BKTFL(T1) ; And flag it
	MOVEI	T1,EPIQRG	; Get the TPT address
	MOVX	T2,.INFIN	; read the entire file
	MOVX	T3,.INFIN	;  .  .  .
	MOVX	T4,.INFIN	;  .  .  .
	PUSHJ	P,F$RBUF	; Read the data
	LOAD.	T1,TPTADR,+EPIQRG ; get the buffer address
	BITOFF	T2,TF.OPI,.BKTFL(T1) ; No input file now
	ZERO.	,BLKFDI,(T1)	;  .  .  .

; Here after file has been read in. Store the Q-register pointer and
;execute the Q-register if this was an EI command

EPIR.E:	LOAD.	T1,QRGDTP,(P1)	; Get the data type
	MOVX	T2,$DTTXT	; And the new data type
	XCT	RQRGTB(T1)	; And release the old data

EPIR.4:	LOAD.	T1,TPTADR,+EPIQRG ; Get the buffer address
	MOVEI	T2,$QRTPT(P1)	; And the pointer address
	PUSHJ	P,M$USEB	; Add the user
	MOVEI	T1,EPIQRG	; Get the old pointer
	PUSHJ	P,M$RELB	; And remove it
	MOVE	T1,P2		; Get the FDB address
	PUSHJ	P,F$CLOS	; Close the file
	 PJRST	F$ERR		; Give up
	MOVE	T1,P2		; Get it again
	PUSHJ	P,M$RBLK	; And return it
	MOVE	T2,P1		; Get the Q-register index
	TXNE	S,S.DOIT	; EI command?
	 PJRST	MAC.0		; Yes, go execute the Q-register
	POPJ	P,		; No, return

SUBTTL	E Commands -- EQ - Write out Q-register

; This command will write out the contents of the given Q-register
; to the file spec given.  The command format is EQ(q)file.ext$,
; where q is the Q-register name. If the (q) is missing it will
; use Q-register *.

EQCMD:	MOVX	T1,"*"		; Get the default
	PUSHJ	P,SCNQRG	; And try for a Q-register name
	 JFCL			; Couldn't?
	LOAD	T2,$QRFLG(T1),QR$WRT ; Get the flag
	JMPT	T2,[ERROR E.DOQ] ; Display only Q-register
	MOVE	P1,T1		; Get the index
	PUSHJ	P,QTXTEI	; And try for text
	MOVX	T1,.FDLEN	; Get an FDB
	MOVX	T2,.BTFDB	;  .  .  .
	PUSHJ	P,M$GBLK	; Get it
	MOVE	P2,T1		; Save in a safer place
	SETZ	T2,		; No switches
	PUSHJ	P,F$PARS	; Parse the spec
	 PJRST	F$ERR		; Couldn't
	MOVX	T3,<SIXBIT |DSK|> ; Get the device
	CFXN.	T4,FDBDEV,+DEF$EQ,0 ; Is this zero ?
	 STOR.	T3,FDBDEV,+DEF$EQ  ; Yes - Store a device
	MOVEI	T2,DEF$EQ	; Get the default block
	MOVE	T1,P2		; Get the other FDB address
	MOVEI	T3,PDF$EQ	; get the permanent defaults
	PUSHJ	P,F$DFLT	; And default it
	MOVX	T1,$IOWRI	; Want to write the file
	MOVE	T2,P2		;  .  .  .
	PUSHJ	P,F$OPEN	; Open up the file
	 PJRST	F$ERR		; Couldn't
	MOVE	T1,P1		; Get the index back
	PUSHJ	P,QTXTEI	; And get the block address
	MOVE	P1,T1		;  .  .  .
	MOVX	T2,.TRUE	; Set up to write entire file
	MOVX	T3,.FALSE	;  .  .  .
	MOVE	T4,P2		; Get the FDB address
	SETZ	A2,		; Start at first character
	LOAD.	A1,BLKEND,(T1)	; And write to the end
	PUSHJ	P,F$WBUF	; Write out the buffer
	MOVE	T1,P2		; Get the FDB address
	PUSHJ	P,F$CLOS	; And close the file
	 PJRST	F$ERR		; Couldn't?
	MOVE	T1,P2		; Get the FDB address again
	PJRST	M$RBLK		; And return the buffer
	SUBTTL	E Commands -- EG - Exit closing all files & run COMPIL

;+
;.HL1 EG command
; This command will cause TECO to exit copying all input files to output
;files and all files will then be closed.  It will then cause COMPIL to be run
;from SYS:
;-

EGCMD:	TXO	F,F.RUN		; Flag we are running a program
	MOVX	T1,<SIXBIT /SYS/> ; Get the default device to run from
	MOVEM	T1,ED$BLK+$RNDEV ; Store the device name
	MOVX	T1,<SIXBIT /COMPIL/> ; Get the program name
	MOVEM	T1,ED$BLK+$RNNAM ; Store the name
	SETZM	ED$BLK+$RNEXT	; Clear the extension
	SETZM	ED$BLK+$RNCOR	; Clear the core argument
	MOVEI	T1,1		; Get the run offset
	HRLM	T1,ED$COD+RNOARG ; Store the run offset
	FALL	(FINISH)	; Fall into the EX code
	SUBTTL	E Commands -- EX -- Exit closing all files

;+
;.hl1 EX command
; This command will cause TECO to exit copying all input files to output
;files and all files closed.
;.hl1 ^Z command
; This command will cause TECO to exit and close all open files. It will
;not copy input to output, nor will it write out the current buffers.
;-

FINISH:	TDZA	P1,P1		; Flag we want everything copied
DECDMP:	 SETO	P1,		; Flag no writing
	PUSHJ	P,DOXITQ	; Do the user's exit routine
	JMPNS	.+2		; Screen mode?
	 PUSHJ	P,SC$FIN	; Set up for exiting
	TXZ	S,S.SCRN	; And flag not screen mode anymore
	PUSHJ	P,T$SRTN	; Set up the correct type out routines
	MOVEI	T1,TTYFDB	; Get the terminal FDB
	PUSHJ	P,F$RSET	; Reset the channel
	MOVE	T1,P1		; Get the flag
	PUSHJ	P,FINI.0	; Call common routine
	 JRST	CONT		; He re-entered, don't exit
	TXNE	F,F.RUN		; Have something to run?
	 JRST	ED$COD		; Yes, go do it
	MONRT.			; And exit
CONT:	SETZM	XCTING		; Flag not executing
	PJRST	@.JBREN		; And fake a re-enter to re-open the world
	SUBTTL	E Commands -- EX -- Common routines -- FINI.0

;+
;.hl1 FINI.0
; This routine will do the work of the EX, EG, and ^Z commands. It will
;search through free core finding all the text buffers and closing there
;associated files. It will also close the LOG file.
;-

FINI.0:	MOVE	P4,T1		; Get the flag into a safer place
	MOVE	P1,FSTBLK	; And the start of the allocated core
	SETO	P2,		; Flag no input files seen yet

FINI.1:	CFXE.	T1,BLKTYP,(P1),.BTTXT ; Is this a text block?
	 JRST	FINI.5		; No, try the next
	MOVE	T1,P1		; Get the block address
	MOVE	T2,P4		; And get the flag
	SETZ	T3,		; Flag we want re-enters to work
	PUSHJ	P,CLSFIL	; Go close the files
	 POPJ	P,		; User typed reenter
	JUMPL	T1,FINI.5	; If no input file, continue on
	JUMPGE	P2,.+2		; Any input files yet?
	 SETZ	P2,		; No, clear for first one
	ADD	P2,T1		; And count whether this one had an output file

; Here when all files are closed.

FINI.5:	LOAD.	T1,BLKSIZ,(P1)	; Get the size of the block
	MOVX	T2,BF.LST	; Get the bit to check
	TDNN	T2,.BKFLG(P1)	; Is this the last block on the page?
	 JRST	FINI.6		; No, go advance to next one
	LOAD.	P1,BLKNXT,(P1)	; Yes, get the next page
	PG2ADR	P1		; Convert to page number
	JUMPE	P1,FINI.8	; Done?
	JRST	FINI.1		; Go try this block

FINI.6:	ADD	P1,T1		; Point to the next block
	JRST	FINI.1		; And loop for this block

FINI.8:	JUMPN	P4,FINI.9	; Don't give an error message if no writing
	JUMPN	P2,FINI.9	; Any output files?
	MOVX	T1,$IOWRI	; Get the function
	MOVEI	T2,TTYFDB	; Get the terminal FDB
	PUSHJ	P,F$OPEN	; Open it
	  JFCL			; Can not happen
	JMPNS	[ERROR E.NFO]	; Screen mode?
	SETOM	MESFLG		; Flag we need to do a complete refresh
	PUSHJ	P,SC$ERS	; Clear the lines, so everything will refresh
	ERROR	E.NFO		; No, No file for output error

FINI.9:	SKIPN	T1,FDB$EL	; Have a log file?
	 PJRST	.POPJ1		; No, give the good return
	PUSHJ	P,F$CLOS	; Yes, close the file
	 PJRST	F$ERR		; Couldn't
	MOVE	T1,FDB$EL	; Get the address again
	SETZM	FDB$EL		; No more log file
	PUSHJ	P,M$RBLK	; And return the block
	PJRST	.POPJ1		; And give the good return
	SUBTTL	E Commands -- EX -- Common routines -- CLSFIL

;+
;.hl1 CLSFIL
; This routine will close any files associated with a text buffer.
;.b.literal
; Usage:
;	MOVE	T1,Text.buffer.address
;	MOVEI	T2,(0 for EX type close, -1 for ^Z type close)
;	PUSHJ	P,CLSFIL
;	 (user typed re-enter)
;	(done)
;
;.end literal
;-

CLSFIL:	$SAVE	<P1,P2,P3,P4>	; Save the Px ac's
	MOVE	P1,T1		; Get the text buffer address
	MOVE	P4,T3		; And get the flag
	HRLI	P4,(T2)		; Also get the other flag
	PUSHJ	P,GETFDI	; And get the input FDB
	 SETZ	T1,		; Isn't any, flag it
	MOVE	P3,T1		; Copy into correct place
	MOVE	T1,P1		; Get the text buffer address again
	PUSHJ	P,GETFDO	; And get the output address
	 SETZ	T1,		; Isn't one
	MOVE	P2,T1		; Copy the address
	JUMPE	P2,CLSF.1	; If no output file, nothing to copy into
	JUMPL	P4,CLSF.0	; Need to copy stuff first?
	MOVE	T1,P1		; Get the buffer address
	SETZ	T2,		; And flag re-enter should abort
	HRRE	T3,P4		; Get the re-enter flag
	PUSHJ	P,F$COPY	; Copy the file data
	 JRST	CLSF.4		; Typed re-enter, go handle it

CLSF.0:	JUMPE	P2,CLSF.1	; Have an output file to close?
	JUMPL	P4,CLSF.2	; If control Z then don't finish EB files
	MOVX	T1,FD.EB	; Check if file is EB'ed
	TDNE	T1,.FDFLG(P2)	;   .  .  .
	 JRST	CLSF.5		; Yes, handle special
CLSF.2:	MOVE	T1,P2		; Yes, get the address
	PUSHJ	P,F$CLOS	; And close the file
	 PJRST	F$ERR		; Couldn't
	MOVE	T1,P2		; Get the FDB address again
	PUSHJ	P,M$RBLK	; And return it

CLSF.1:	JUMPE	P3,CLSF.3	; Have an input file to close?
	MOVE	T1,P3		; Yes, get the address
	PUSHJ	P,F$CLOS	; And close it
	 PJRST	F$ERR		; Couldn't, go complain
	MOVE	T1,P3		; Get the address again
	PUSHJ	P,M$RBLK	; And return the block
	JRST	CLSF.3		; Go turn off the bits

CLSF.4:	LOAD.	T1,TPTADR,+TXTBUF ; Check if we have the current text buffer
	CAIE	T1,(P1)		; No, skip this
	 POPJ	P,		; Return
	PJRST	YANK		; Pull in a new buffer and return

CLSF.5:	PUSHJ	P,FIN.EB	; Finish up the EB'ed file

; All done, flag we don't have any open files

CLSF.3:	BITOFF	T1,TF.OPO!TF.OPI,.BKTFL(P1) ; Flag no files open
	MOVX	T1,-1		; get a -1
	JUMPE	P3,.POPJ1	; If no input file, just return the -1
	SETZ	T1,		; Get a zero
	JUMPE	P2,.POPJ1	; If no output file, return 0
	AOJA	T1,.POPJ1	; And return
	SUBTTL	E Commands -- EX -- Common routines -- FIN.EB

;+
;.hl1 FIN.EB
; This routine will close the files from an EB command. It assumes that
;all data has already been written into the output file.
;.b.literal
; Usage:
;	MOVE	P1,Text.buffer.address
;	MOVE	P2,Output.FDB.address
;	MOVE	P3,Input.FDB.address
;
;.end literal
;-

FIN.EB:	$SAVE	<P1,P2,P3,P4>	; Save P1-P4
	$SAVE	<A1>		; Save A1
	LOAD.	P4,BLKTMP,(P1)	; Get the FDB address for the .BAK file
	LOAD.	A1,FDBEXT,(P4)	; Save the extension
	BITOFF	T1,TF.OPO,.BKTFL(P1) ; Flag no more input or output files
	MOVE	T1,P2		; First close the output file
	PUSHJ	P,F$CLOS	;  .  .  .
	 PJRST	F$ERR		; Couldn't?
	BITOFF	T1,TF.OPI,.BKTFL(P1) ; Flag no more input or output files
	MOVE	T1,P3		; Close the input file
	PUSHJ	P,F$CLOS	;  .  .  .
	 PJRST	F$ERR		; Couldn't
	STORI.	<'BAK'>,T1,FDBEXT,(P4) ; Store the extension
	MOVX	T1,$IODEL	; Delete the back file first
	MOVE	T2,P4		; If there is one
	PUSHJ	P,F$OPEN	; Do it
	 JRST	[CAXE	T1,ERFNF%	; File not found?
		 PJRST	F$ERR		; No, give up
		JRST	.+1]		; Yes, all is okay
	MOVEI	T1,(P3)		; Get the address of the FDB
	HRLI	T1,(P4)		; Get the other address
	BLT	T1,.FDLEN-1(P3)	; Move the data
	STOR.	A1,FDBEXT,(P3)	; And store the extension
	MOVE	T1,P3		; Set up to rename the input file
	MOVE	T2,P4		;  .  .  .
	PUSHJ	P,F$RENM	; Do it
	 PJRST	F$ERR		; Couldn't
	MOVE	T1,P2		; Now rename the output file to the correct thing
	MOVE	T2,P3		;  .  .  .
	PUSHJ	P,F$RENM	; Do it
	 PJRST	F$ERR		; Couldn't
	MOVE	T1,P2		; Get output FDB
	PUSHJ	P,M$RBLK	; And return it
	MOVE	T1,P3		; Get the input FDB
	PUSHJ	P,M$RBLK	; And return it
	MOVE	T1,P4		; Get the other
	PUSHJ	P,M$RBLK	; And return it also
	POPJ	P,		; And return
	SUBTTL	E Commands -- ED (Run a program on exit)

;+
;.HL1 ED
; The routine EDCMD will process the ED TECO command.  This routine will call
;the file specification parser to determine the file to run.  It will then move
;the information into the data segment so that the EX or EG commands will know
;what to run.
; The valid switches for this command are: /RUNOFFSET:n and /CORE:n.  These
;switches specifiy different arguments for the RUN UUO.
;-

EDCMD:	SKIPE	T1,ED$FDB	; Have an FDB (an error occured last time out)
	  JRST	[SETZM	ED$FDB		; Yes - Clear the old pointer
		JRST	EDCM.2]		; And continue processing

	MOVX	T1,.FDLEN	; Get the length of an FDB
	MOVX	T2,.BTGEN	; Core section to get it from
	PUSHJ	P,M$GBLK	; Allocate the block

EDCM.2:	MOVE	P1,T1		; Copy the address to a safer place
	MOVEI	T2,EDPTR	; Get the pointer to the ED switches
	STORE	T3,ED$BEG,ED$END,-1 ; Clear the switch area
	PUSHJ	P,F$PARS	; Parse the file input
	  JRST	EDCM.E		; Process the error

	LOAD.	T1,FDBDEV,(P1)	; Get the device specified
	SKIPN	T1		; Device specified ?
	 MOVX	T1,<SIXBIT |SYS|> ; No, Assume from SYS:
	MOVEM	T1,ED$BLK+$RNDEV ; Store it in the block
	LOAD.	T1,FDBNAM,(P1)	; Get the program name
	MOVEM	T1,ED$BLK+$RNNAM ; Store it in the block
	LOADS.	T1,FDBEXT,(P1)	; Get the extension
	MOVEM	T1,ED$BLK+$RNEXT ; Store the extension
	CFXN.	,FDBPPN,(P1),0	; Is this zero ?
	  JRST	EDCM.0		; Yes - Skip this section

; Now setup the path to run the program from

	LOAD.	T1,FDBPPN,(P1)	; Get the PPN
	MOVEM	T1,ED$PTH+.PTPPN ; Store it in the path block
	MOVEI	T1,ED$PTH	; Get the address of the path block
	MOVEM	T1,ED$BLK+$RNPPN ; Store the pinter to the path block
	MOVX	T2,<<-.PTMAX-.PTSFD>,,.PTSFD> ; Get the AOBJN pointer
	MOVEI	T3,.FDSFD(P1)		; Get the address of the SFDs

EDCM.1:	MOVE	T1,(T3)		; Get an SFD
	MOVEM	T1,ED$PTH(T2)	; Store it in the path block
	ADDI	T3,1		; Increment the pointer
	AOBJN	T2,EDCM.1	; Loop for all items
	SKIPA			; Enter the common code again

EDCM.0:	SETZM	ED$BLK+$RNPPN	; Clear the PPN
	SKIPGE	T1,LS$COR	; Have a core argument ?
	 SETZ	T1,		; No - Assume zero
	MOVEM	T1,ED$BLK+$RNCOR ; Store it in the RUN block
	SKIPGE	T1,LS$RUN	; Have a run offset ?
	 SETZ	T1,		; No - Assume zero
	HRLM	T1,ED$COD+RNOARG ; Store it in the code
	TXO	F,F.RUN		; Flag something to run on an exit
	MOVE	T1,P1		; Copy the FDB address back again
	PJRST	M$RBLK		; Return the block


; Here on an error parsing the file specification.

EDCM.E:	MOVEM	P1,ED$FDB	; Store the FDB for later
	PJRST	F$ERR		; Issue the error message


; The following are the valid switches on the ED command

DEFINE	ED$SW,<
SW	CORE,LS$COR,F$CORE,,SW.VRQ	;;/CORE:n
SW	RUNOFFSET,LS$RUN,.IOCTW,,SW.VRQ	;;/RUNOFFSET:n
> ; End of ED$SW macro definition

	DOSWTCH	(ED,ED$SW)	; Generate the switch block
EDPTR:	SWTPTR	(ED)		; Generate the pointer to the switch block
; The following is the code that is moved into the low segment to 
; do the RUN UUO.

RUNCOD:!PHASE	0		; Make this phased
	MOVSI	T1,1		; Get rid of the high segment
	CORE	T1,		; . . .
	  JFCL			; Don't care
	MOVE	T1,RNOARG+ED$COD ; Get the argument
	RUN	T1,		; Do the RUN UUO
	  HALT			; Can not continue

RNOARG:!EXP	ED$BLK		; Address of the run block
RUNLEN:!DEPHASE			; Back to normal
	SUBTTL	E Commands -- ET - Set type out mode

;ET COMMAND
;		 0 = Normal typeout
;		 1 = Literal typeout
;		 2 = Image typeout  (IONEOU)

TYOCTL:	TXNE	F,F.ARG		; Have an arg?
	 JRST	TYOCT1		; Yes, go set new value
	SKIPE	A1,ETVAL	; Get ET value
	CHKEO	EODEC,RTONES	; If EO > 2 and non-zero, return -1
	PJRST	VALRET		; Return the value

TYOCT1:	CHKEO	EODEC,TYOCT3	; Jump if old style ET
	SKIPL	A1		; Check range
	 CAILE	A1,2		; ...
	  ERROR	E.ETA		; Illegal value
TYOCT2:	MOVEM	A1,ETVAL	; Store value
	POPJ	P,		; And return

TYOCT3:	JUMPE	A1,TYOCT2	; Old ET can be only 0 or 1
	MOVEI	A1,1		; Non zero means 1
	JRST	TYOCT2		; Go store and return
	SUBTTl	E Commands -- EO

;+
;.HL1 OLDMOD
;This routine will do the processing for the EO command.
;-

OLDMOD:	TXNE	F,F.ARG		; Have an arg?
	 JRST	OLD1		; Yes, go set value of EOFLAG
	MOVE	A1,EOFLAG	; No, return the current value
	PJRST	VALRET

OLD1:	CAIG	A1,0		; Greater than zero?
	 MOVEI	A1,EOVAL	; No, use standard value
	CAILE	A1,EOVAL	; Is value within range?
	 ERROR	E.EOA		; No, give the error
	MOVEM	A1,EOFLAG	; Yes, set the value

; Now set up the instruction table for the CHKEO tables.

OLD.0:	MOVSI	T1,-<EOVAL>	; Get the loop pointer
	MOVX	T2,<JFCL>	; And get the no-op to use for things to avoid

OLD.2:	CAIN	A1,1(T1)	; Get to the correct one yet?
	 MOVX	T2,<TRNA>	; Yes, make it a skip instruction
	MOVEM	T2,EOXCTS(T1)	; Save the instruction
	AOBJN	T1,OLD.2	; And loop for all the entries.
	POPJ	P,		; And return

EOMAX:	EXP	EOVAL		; Max EO level for error message
	SUBTTL	E Commands -- EU command

;+
;.HL1 TYCASE
;This routine will execute the EU command.
;-

TYCASE:	TXNE	F,F.ARG		; Have an arg?
	 JRST	TYCAS1		; Yes, go handle it
	MOVE	A1,TYCASF	; No, return the current value
	PJRST	VALRET		; Return it

TYCAS1:	MOVEM	A1,TYCASF	; Set the flag
	CHKEO	EO124,.POPJ	; Just return if old
	CAXL	A1,-1		; Check if argument is valid
	 CAXLE	A1,1		;  Only -1, 0, and 1 are okay
	ERROR	E.EUO		; EU value out of range
	POPJ	P,		; Value is okay
	POPJ	P,		; And return
	SUBTTL E Commands -- ES

AUTOTY:	TXNE	F,F.ARG		; Arg given?
	 JRST	AUTOT1		; Yes, go set type out char
	MOVE	A1,AUTOF	; No, get the current auto type out character
	PJRST	VALRET		; And return it

AUTOT1:	MOVEI	T1,.CHLFD	; Get the default character
	CAIL	A1,1		; Is the character legal?
	 CAILE	A1,37		;  .  .  .
	  MOVE	T1,A1		; Yes, use what he gave
	MOVEM	T1,AUTOF	; Set the new value
	POPJ	P,		; And return
SUBTTL E Commands -- EH - Change error message level

ERRSET:	TXNE	F,F.ARG		;ARG SEEN?
	 JRST	ERRSE1		;YES, RESET INDICATOR
	HLLZ	T1,ERRLEN	;NO, RETURN CURRENT VALUE OF FLAG
	MOVSI	T2,-3		;NUMBER OF POSSIBILITIES
ERRS.0:	TDNE	T1,JWTABL(T2)	;BIT ON?
	 MOVEI	A1,1(T2)
	AOBJN	T2,ERRS.0	;NO, LOOP
	JRST	VALRET

JWTABL:	XWD	JW.WPR_-22,JW.WPR_-22
	XWD	JW.WFL_-22,<JW.WPR!JW.WFL>_-22
	XWD	JW.WCN_-22,<JW.WPR!JW.WFL!JW.WCN>_-22

ERRSE1:	CAILE	A1,3		;3 IS HIEST
	 MOVEI	A1,3		;FORCE IT DOWN IF GREATER
	MOVE	T1,PRMERR	;ASSUME DEFAULT
	SKIPLE	A1		;OK ASSUMPTION?
	HRLZ	T1,JWTABL-1(A1)	;NO
	MOVEM	T1,ERRLEN	;2 BECOMES 0  = MEDIUM
	POPJ	P,		; Return
SUBTTL	E Commands -- EK - Kill off the output file

EKILL:	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address
	PUSHJ	P,GETFDO	; Get the output FDB address
	 POPJ	P,		; Isn't one, just return
	MOVE	P1,T1		; Save a copy
	PUSHJ	P,F$RSET	; Close the file
	LOAD.	T1,TPTADR,+TXTBUF ; Get the buffer address back again
	BITOFF	T2,TF.OPO,.BKTFL(T1) ; Flag file is not open anymore
	PUSHJ	P,GETFDI	; Have an input file?
	 JRST	EKIL.1		; No, skip this
	BITOFF	T2,FD.EB,.FDFLG(T1) ; Yes, flag it is not EB'ed any more
	TXNE	T2,FD.ENQ	; File ENQ'ed?
	 PUSHJ	P,F$DEQ		; Yes, remove the lock

EKIL.1:	MOVE	T1,P1		; Get the address back
	PJRST	M$RBLK		; And return it
	SUBTTL	E Commands -- EN - rename the input file

;+
;.HL1 ENCMD
;This routine will execute the EN command.  This command causes a file
;to be renamed.
;-

ENCMD:	MOVX	T1,.FDLEN	; Get the size of an FDB
	MOVX	T2,.BTFDB	; And the block type
	PUSHJ	P,M$GBLK	; Get a block
	MOVE	P1,T1		; Get the address
	SETZ	T2,		; No switches
	PUSHJ	P,F$PARS	; Parse the file spec
	 PJRST	F$ERR		; Couldn't
	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address
	MOVEM	P1,LASFDB	; Save the FDB address in case of error
	PUSHJ	P,GETFDI	; Get the input file name
	 ERROR	E.ENE		; EN error
	MOVE	P2,T1		; Get the address
	MOVX	T1,FD.EB	; Check if the file is EB'ed
	TDNE	T1,.FDFLG(P2)	; Check if EB'ed?
	 ERROR	E.ENE		; Can't rename EB'ed file
	DMOVE	T1,P1		; Copy the FDBs
	PUSH	P,.FDNAM(P1)	; Save the file name
	PUSHJ	P,E$DFLT	; Cause any defaulting
	POP	P,.FDNAM(P1)	; And reset the file name
	MOVE	T1,P2		; Get the input FDB
	PUSHJ	P,F$CLOS	; And close the file
	 PJRST	F$ERR		; Couldn't
	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address again
	BITOFF	T2,TF.OPI,.BKTFL(T1) ; Clear the input flag
	MOVE	T1,P2		; Get the addresses again
	MOVE	T2,P1		;  .  .  .
	PUSHJ	P,F$RENM	; Rename the file
	 PJRST	F$ERR		; Couldn't
	MOVE	T1,P1		; Get the old input FDB
	PUSHJ	P,M$RBLK	; Return it
	MOVE	T1,P2		; Get the other FDB
	PJRST	M$RBLK		; And return it
SUBTTL	E Commands -- ER - Read a file

;+
;.hl1 ER command
; This command is used to open a file for input. It will associate the
;file with the current text buffer.
;-

OPNRD:	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address
	PUSHJ	P,GETFDI	; Have an input file already?
	 JRST	OPNR.1		; No, no worries
	MOVE	P1,T1		; Save a copy
	LOAD.	T3,TPTADR,+TXTBUF ; Get the buffer address
	BITOFF	T2,TF.OPI,.BKTFL(T3) ; Clear the open input flag
	PUSHJ	P,F$CLOS	; Close off the old input file
	 PJRST	F$ERR		; Couldn't, punt
	JRST	OPNR.2		; Already have an FDB, no need for a new one

OPNR.1:	MOVX	T1,.FDLEN	; Get the length
	MOVX	T2,.BTFDB	; And the block type
	PUSHJ	P,M$ZBLK	; get the block
	MOVE	P1,T1		; Get the address

OPNR.2:	SETOM	ER$BEG		; Clear the only switch
;	STORE	T1,ER$BEG,ER$END,-1 ; Clear the switch block
	MOVE	T1,P1		; Get the FDB address
	MOVEI	T2,ERSWT	; And the pointer to the switch block
	PUSHJ	P,F$PARS	; Parse the block
	 PJRST	F$ERR		; Give up

; Default the ER switches

	MOVE	T4,.FDFLG(P1)	; Get the flags from the FDB
	TXNE	T4,FD.DEF	; /DEFAULT given?
	 SETOM	DFTYNK		; Yes, default the /YANK value
	TXNE	T4,FD.NDF	; /NODEFAULT given?
	 JRST	OPNR.N		; Yes, skip this
	MOVE	T1,LS$YNK	; Get the switch value
	CAXN	T1,-1		; Default?
	 MOVE	T1,DFTYNK	; Get the default
	MOVEM	T1,LS$YNK	; Set the switch value
	MOVEM	T1,DFTYNK	; And save as default

OPNR.N:	XMOVEI	T1,ER$BEG	; Get the start of the ER switches
	XMOVEI	T2,ER$DFS	; And the default ER switches
	MOVEI	T3,ER$END-ER$BEG+1 ; And the length of the table
	PUSHJ	P,E$DFSW	; Default the switch values

; Now do the random defaulting

OPNR.0:	MOVEI	T1,DEF$ER	; Get the default block
	MOVEI	T2,DEF$EW	; Use the EW block forst
	PUSHJ	P,E$DFLT	; Do the defaulting

; Do the defaulting for the file specification now

	MOVEI	T3,PDF$ER	; Get the perm defaults
	MOVEI	T2,DEF$ER	; Get the default block
	MOVE	T1,P1		; Get the FDB address
	PUSHJ	P,F$DFLT	; And default the block
	MOVX	T1,$IOREA	; Set up to read the file
	MOVE	T2,P1		;  .  .  .
	PUSHJ	P,F$OPEN	; And open it up
	 PJRST	F$ERR		; Give up
	LOAD.	T1,TPTADR,+TXTBUF ; Get the buffer address again
	STOR.	P1,BLKFDI,(T1)	; Store the FDB address
	BITON	T2,TF.OPI,.BKTFL(T1) ; Flag we have a file
	SKIPLE	LS$YNK		; User want /YANK?
	 PJRST	YANK		; Yes, go do it
	POPJ	P,		; Return happy

DEFINE ER$SW,<
SW	NOYANK,LS$YNK,,0,
SW	SUPLSN,SR$SLS,,1,
SW	YANK,LS$YNK,,1,
> ; End of ER$SW macro

	DOSWTCH(ER,ER$SW)

ERSWT:	SWTPTR(ER)
	SUBTTL	E Commands -- EB - Edit and backup command

;+
;.HL1 EB command
; This command will cause the file to be edited and a backup of the orginal
;file to be created when the editing is finished.  This command will take
;both input and output modes.  The following are a list of the allowed switches.
;.literal
;
; Switches:
;	/GENLSN		Same as /OMODE:LSA
;	/IMODE:mode	Sets the input mode to the specified mode
;	/INPLACE	Edit the file in the path it was found in
;	/MODE:mode	Sets the input and output mode
;	/OMODE:mode	Sets the output mode
;	/READONLY	Set the file as only being read
;	/SUPLSN		Sets the output mode to /OMODE:ASCII
;.end literal
;-

DEFINE	EB$SW,<
SW	GENLSN,SWTOMD,,$FMLSA,
SW	IMODE,SWTIMD,F$KEY,MODPTR,SW.VRQ!SW.KEY
SW	INPLACE,LS$INP,,0,
SW	MODE,SWTIMD,F$KEY,MODPTR,SW.VRQ!SW.KEY
SW	NOYANK,LS$YNK,,0,
SW	OMODE,SWTOMD,F$KEY,MODPTR,SW.VRQ!SW.KEY
SW	READONLY,LS$RED,,0,
SW	SUPLSN,SWTOMD,,$FMASC,
SW	YANK,LS$YNK,,1,
> ; End of EB$SW macro definition

	DOSWTCH(EB,EB$SW)	; Generate the EB switches

EBPTR:	SWTPTR(EB)		; Generate the switch pointer

DEFINE	FK(A,B,C),<EXP	SIXBIT	/'B'/>
MODKEY:	FM$KEY			; Generate the key words
	MOD.L==.-MODKEY		; Generate the length

MODPTR==:<-MOD.L,,MODKEY>	; Generate a symbol
; Main routine

EBCMD:	MOVX	T1,.FDLEN	; Get the length of an FDB
	MOVX	T2,.BTFDB	; From the FDB area
	PUSHJ	P,M$GBLK	; Allocate the block
	MOVE	P1,T1		; Move to a safer place
	SETOM	SWTIMD		; Set the external values
	SETOM	SWTOMD		; . . .
	SETOM	LS$INP		; Set the local switch
	SETOM	LS$RED		; . . .
	SETOM	LS$YNK		;  .  .  .
	MOVEI	T2,EBPTR	; Get the EB switch pointer
	PUSHJ	P,F$PARS	; Parse the file specification
	  JRST	F$ERR		; Failed
	LOAD.	T1,FDBFLG,(P1)	; Get the flags
	TXNE	T1,FD.DEF	; /DEFAULT?
	 JRST	[SETOM	DFTOMD		; Forget the defaults
		SETOM	DFTIMD		;  .  .  .
		SETOM	DFTYNK		; Clear default /YANK value
		JRST	.+1]		; Continue on
	TXNE	T1,FD.NDF	; /NODEFAULT given?
	 JRST	EBCM.D		; Yes, skip defaulting
	MOVE	T1,SWTIMD	; Get the /IMODE argument
	CAXN	T1,-1		; Any given?
	 MOVE	T1,DFTIMD	; No, get the default
	MOVEM	T1,SWTIMD	; Save as current /MODE
	MOVEM	T1,DFTIMD	; And as new default
	MOVE	T1,SWTOMD	; Get the output mode
	CAXN	T1,-1		; Any given?
	 MOVE	T1,DFTOMD	; No, get the default
	MOVEM	T1,SWTOMD	; Save as current /OMODE
	MOVEM	T1,DFTOMD	; And as new default
	MOVE	T1,LS$YNK	; Get the /YANK switch
	CAXN	T1,-1		; Any given?
	 MOVE	T1,DFTYNK	; No, use default
	MOVEM	T1,LS$YNK	; Save it back
	MOVEM	T1,DFTYNK	;  .  .  .
EBCM.D:	SKIPL	T1,SWTIMD	; Get the /IMODE value
	 STOR.	T1,FDBMOD,(P1)	; There was one, store it
	SKIPGE	LS$INP		; Was /INPLACE specified ?
	  JRST	EBCM.0		; No - Skip this
	BITON	T1,FD.INP,.FDFLG(P1) ; Yes - Light the flag

; Now do the random defaulting

EBCM.0:
;	MOVEI	T1,DEF$EB	; Place to store the defaults
;	MOVEI	T2,DEF$ER	; From the ER
;	PUSHJ	P,E$DFLT	; Do it
	MOVEI	T1,DEF$ER	; Place to store the defaults
	MOVEI	T2,DEF$EW	; From the EW
	PUSHJ	P,E$DFLT	; Do it

; Now to the per file specification defaulting

	MOVE	T1,P1		; Get the FDB address
	MOVEI	T2,DEF$ER	; Get the default block
	MOVEI	T3,PDF$ER	; Get the perm defaults address
	PUSHJ	P,F$DFLT	; And default the FDB
	SKIPL	LS$RED		; Read only?
	 JRST	EBCM.9		; Yes, just do an ER command
	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address
	PUSHJ	P,GETFDI	; Get the input FDB address
	 JRST	EBCM.3		; None, try output
	MOVX	T2,FD.EB	; Check if this is an EB'ed file
	TDNN	T2,.FDFLG(T1)	;  .  .  .
	 JRST	EBCM.5		; Okay, just close the file
	MOVE	T1,P1		; Get the FDB address of the new file
	PUSHJ	P,M$RBLK	; And return it
	ERROR	E.EBO		; EB still open

EBCM.5:	PUSH	P,T1		; Save the address
	PUSHJ	P,F$CLOS	; Close the input file
	 PJRST	F$ERR		; Couldn't
	POP	P,T1		; Get the FDB address back
	PUSHJ	P,M$RBLK	; And return it

EBCM.3:	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address
	BITOFF	T2,TF.OPO!TF.OPI,.BKTFL(T1) ; Clear the open file flags
	PUSHJ	P,GETFDO	; And try for an output file
	 JRST	EBCM.4		; None, skip this
	PUSH	P,T1		; Save the address
	PUSHJ	P,F$CLOS	; Close the file
	 PJRST	F$ERR		; Couldn't
	POP	P,T1		; Get the FDB address back
	PUSHJ	P,M$RBLK	; And return it

EBCM.4:	MOVE	T1,P1		; Get the pointer to the FDB again
	PUSHJ	P,F$EB		; Make this file be in EB mode
	  JRST	F$ERR		; Failed
	LOAD.	T3,TPTADR,+TXTBUF ; Get the address of the text block
	STOR.	T1,BLKFDO,(T3)	; Store the address of the temp file
	STOR.	T2,BLKTMP,(T3)	; Store the output FDB
	STOR.	P1,BLKFDI,(T3)	; Store the input FDB
	BITON	T1,TF.OPO!TF.OPI,.BKTFL(T3) ; Flag the file is open
	SKIPLE	LS$YNK		; /YANK given?
	 PJRST	YANK		; Yes, go do it
	POPJ	P,		; Return to the caller

EBCM.9:	SETOM	SR$SLS		; Flag no /SUPLSN
	MOVE	T1,SWTOMD	; Get the output mode
	CAXN	T1,$FMASC	; Did we get the switch?
	 SETZM	SR$SLS		; Yes, flag it
	JRST	OPNR.0		; And go open for reading
SUBTTL	E Commands -- EW - Write a file
SUBTTL	E Commands -- EA - Append to a file

;+
;.hl1 EA and EW command
; This routine will open an output file. EA opens the file for appending
;EW will supersede the file. The file will be associated with the current
;buffer.
;-


OPNWRA:	SKIPA	P2,[EXP $IOAPP]	; Get the append function
OPNWR:	 MOVX	P2,$IOWRS	; Get the write function
	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address
	PUSHJ	P,GETFDO	; And get the output FDB
	 JRST	OPNW.1		; Don't have one, don't need to close it
	MOVE	P1,T1		; Copy the address
	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer
	BITOFF	T2,TF.OPO,.BKTFL(T1) ; Clear the file open flag
	MOVE	T1,P1		; Get the FDB address back
	PUSHJ	P,F$RSET	; And delete the output we were making
	JRST	OPNW.2		; Skip getting a new FDB

OPNW.1:	MOVX	T1,.FDLEN	; Get the length
	MOVX	T2,.BTFDB	; And the block type
	PUSHJ	P,M$GBLK	; Get the FDB
	MOVE	P1,T1		; Into the correct place

OPNW.2:
;	STORE	T1,EW$BEG,EW$END,-1 ; Clear the switches
	SETOM	EW$BEG		; Clear the switch
	MOVE	T1,P1		; Get the block address back
	MOVEI	T2,EWSWT	; And get the EW switches
	PUSHJ	P,F$PARS	; Parse the file spec
	 PJRST	F$ERR		; Go give the error message

; Now do the random defaulting

	MOVEI	T1,DEF$EW	; Get the place to store into
	MOVEI	T2,DEF$ER	; From
	PUSHJ	P,E$DFLT	; Default this block

; Now default the file specification just input

	MOVE	T1,P1		; Get the FDB address
	MOVEI	T2,DEF$EW	; Get the default block
	MOVEI	T3,PDF$EW	; Get the perm default block
	PUSHJ	P,F$DFLT	; Default the block
OPNW.0:	MOVE	T1,P2		; Get the function (either write or append)
	MOVE	T2,P1		; And the FDB address
	PUSHJ	P,F$OPEN	; Open the file
	 PJRST	F$ERR		; Couldn't
	MOVEI	T1,(P1)		; Get the FDB address
	PUSHJ	P,F$ENQ		; ENQ. this file
	  JRST	OPNW.4		; Couldn't forget the whole thing
	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address back
	STOR.	P1,BLKFDO,(T1)	; Store the FDB address
	BITON	T2,TF.OPO,.BKTFL(T1) ; And flag it is there
	POPJ	P,		; Return
OPNW.4:	HRRZM	P1,LASFDB	; Store the FDB address
	ERROR	E.FAE		; And give the error
DEFINE EW$SW,<
SW	GENLSN,SW$GLS,,1,
> ; End of EW$Sw

	DOSWTCH(EW,EW$SW)

EWSWT:	SWTPTR(EW)
SUBTTL	E Commands -- EZ and EF

;EZ	SELECTS THE OUTPUT DEVICE, ISSUES A REWIND COMMAND TO IT,
;	ISSUES A COMMAND TO ZERO ITS DIRECTORY, AND OPENS THE FILE
;	SPECIFIED (IF ANY).

ZERDIR:	MOVX	T1,.FDLEN	; Get the length of an FDB
	MOVX	T2,.BTFDB	; And the block type
	PUSHJ	P,M$GBLK	; Get the FDB
	MOVE	P1,T1		; Get the address
	STORE	T2,EW$BEG,EW$END,-1 ; Clear the switch block
	MOVEI	T2,EWSWT	; Get the Ew switches
	PUSHJ	P,F$PARS	; And parse the file spec
	 PJRST	F$ERR		; Couldn't
	MOVE	T1,P1		; Get the FDB address
	MOVEI	T2,DEF$EW	; Get the default block
	MOVEI	T3,PDF$EW	; Get the default block address
	PUSHJ	P,F$DFLT	; And default the block
	LOAD.	T1,FDBDEV,(P1)	; Get the device name
	IONDX.	T1,		; Get the device index
	 JRST	ZERD.1		; Couldn't, just go try to open the file
	UTPCLR	T1,		; Clear the directory for the device

ZERD.1:	MOVX	P2,$IOWRI	; Get the F$OPEN function
	PJRST	OPNW.0		; Go open the file for output
;EF	FINISHES OUTPUT ON THE CURRENT OUTPUT FILE WITHOUT
;	SELECTING A NEW OUTPUT FILE.

CLOSEF:	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address
	MOVE	P1,T1		; And get a copy
	PUSHJ	P,GETFDO	; Get the output FDB
	 POPJ	P,		; None, just return
	MOVE	P2,T1		; Get a copy
	MOVE	T1,P1		; Get the buffer address back
	PUSHJ	P,GETFDI	; And try for an input FDB
	 JRST	CLOS.1		; None, can't be an EB'ed file
	MOVE	P3,T1		; Save the address
	MOVX	T1,FD.EB	; Check if EB'ed
	TDNN	T1,.FDFLG(P2)	;  .  .  .
	 JRST	CLOS.1		; No, just close the output file
	PUSHJ	P,FIN.EB	; Finish up
	BITOFF	T1,TF.OPO!TF.OPI,.BKTFL(P1) ; Flag no files open at all
	POPJ	P,		; And return

CLOS.1:	MOVE	T1,P2		; Not EB'ed, just close the output
	PUSHJ	P,F$CLOS	; Close the file
	 PJRST	F$ERR		; Something went wrong
	BITOFF	T1,TF.OPO,.BKTFL(P1) ; Clear the output open flag
	MOVE	T1,P2		; Get the address
	PJRST	M$RBLK		; And return the core
SUBTTL	E Commands -- EM - MTAPE UUO's

	TP.MTP==777B8		; MTAPE code
	TP.ARG==777B17		; Argument for TAPOP.
	TP.TOP==777777		; Function for TAPOP.


EMTAPE:	LOAD.	T1,TPTADR,+TXTBUF ; Get the text buffer address
	PUSHJ	P,GETFDI	; Get the input FDB address
	 ERROR	E.NFI		; No file for input
	MOVE	P1,T1		; Get the address
	LOAD.	T1,FDBCHN,(P1)	; Get the channel number
	DEVCHR	T1,		; And get the bits
	TXNN	T1,DV.MTA!DV.DTA ; Only do this for magtape or DECtape
	 POPJ	P,		; No-op otherwise
	JUMPGE	A1,.+2		; Valid MTAPE?
	 ERROR	E.EMA		; No, punt it
	MOVE	T2,[XWD -MTPLEN,MTPTBL] ; Get the table pointer
	CHKEO	EO124,EMTA.1	; If EO level before 200 use MTAPE args
	JRST	EMTA.3		; Go handle TAPOP. arg

EMTA.1:	LOAD	T1,(T2),TP.MTP	; Get the MTAPE code
	CAIE	A1,(T1)		; Correct one?
	 JRST	EMTA.2		; Yes, go get it
	LOAD	A1,(T2),TP.TOP	; Convert the code to the TAPOP. equivalent
	LOAD	A2,(T2),TP.ARG	; And get the argument
	CAXE	A2,TP.ARG_-<ALIGN.(TP.ARG)> ; No argument?
	 TXO	F,F.ARG2	; No, flag we have a second arg
	JRST	EMTA.3		; And go do it

EMTA.2:	AOBJN	T2,EMTA.1	; Loop through the entire table

; Here to do the requested TAPOP.  See if it requires or returns a value

EMTA.3:	CAXGE	A1,2000		; Set function?
	 JRST	EMTA.4		; No, go read a value
	TXNN	F,F.ARG2	; Have the second arg?
	 SETZ	A2,		; No, assume zero
	MOVE	P2,[XWD 3,T2]	; Get the block pointer
	MOVE	T4,A2		; Get the argument to set
	JRST	EMTA.5		; Go do the TAPOP.

EMTA.4:	MOVE	P2,[XWD 2,T2]	; Get the pointer
EMTA.5:	LOAD.	T3,FDBCHN,(P1)	; get the channel
	MOVE	T2,A1		; Get the funcion
	TAPOP.	P2,		; And do it
	 ERROR	E.TPF		; Couldn't, TAPOP. failed
	CAXL	A1,1000		; Read function?
	 CAXL	A1,2000		;  .  .  .
	  POPJ	P,		; No, just return
	MOVE	A1,P2		; Yes, get the value
	PJRST	VALRET		; And return

MTPTBL:	INSVL.(<MTWAT.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFWAT,TP.TOP)>
	INSVL.(<MTREW.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFREW,TP.TOP)>
	INSVL.(<MTEOF.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFDSE,TP.TOP)>
	INSVL.(<MTSKR.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFFSB,TP.TOP)>
	INSVL.(<MTBSR.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFBSB,TP.TOP)>
	INSVL.(<MTEOT.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFSLE,TP.TOP)>
	INSVL.(<MTUNL.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFUNL,TP.TOP)>
	INSVL.(<MTBLK.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFWLG,TP.TOP)>
	INSVL.(<MTSKF.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFFSF,TP.TOP)>
	INSVL.(<MTBSF.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFBSF,TP.TOP)>
	INSVL.(<MTDEC.>,TP.MTP)!<INSVL.(.TFMDD,TP.ARG)>!<INSVL.(.TFMOD,TP.TOP)>
	INSVL.(<MTIND.>,TP.MTP)!<INSVL.(.TFM8B,TP.ARG)>!<INSVL.(.TFMOD,TP.TOP)>
	INSVL.(<MTLTH.>,TP.MTP)!<INSVL.(-1,TP.ARG)>!<INSVL.(.TFLTH,TP.TOP)>

MTPLEN==.-MTPTBL
	SUBTTL	E Commands -- E? command


;+
;.hl1 EQUEST
; This routine will handle the E? command.  This command is used to obtain
;information about various things.
;.b
;Command format:
;.lit
;	E?(Q-REG-NAME)KEYWORD$
;	  - or -
;	E?KEYWORD$
;
;.end lit
;-

; Definition of keyword table entry

	INTSTR	EQU,EQ,$,$SRLEN	; Generate $EQxxx
	WORD	RTN		; Routine address to call
	WORD	FLG		; Flags
		INTFLG	EQ
		FLAG	NMA		; Numeric argument allowed
	ENDSTR			; End the structure

EQUEST:	SETZ	T1,		; Flag no default name
	PUSHJ	P,SCNQRG	; Scan off a Q-register name
	 SETZ	T1,		; None, remember that
	MOVE	P1,T1		; Save the QRG address
	MOVEI	T1,XCTBUF	; Get the address of the TPT
	MOVEI	T2,SKRCH	; And the routine
	PUSHJ	P,SCNKEY	; Get the keyword
	 ERROR	E.UTK		; Not finished
	MOVE	T1,[XWD -EQULEN,EQUTBL] ; Get the table pointer
	PUSHJ	P,FNDKWD	; And look for the keyword
	 ERROR	E.IKW		; Illegal keyword
	MOVE	T2,$EQFLG(T1)	; Get the flags
	TXNE	F,F.ARG		; Is there an argument?
	 TXNE	T2,EQ$NMA	; Yes, is it allowed?
	  PJRST	@$EQRTN(T1)	; Dispatch to the correct routine
	ERROR	E.NAA		; No, no argument allowed

; Table of keywords for E?

DEFINE EQUNAM,<
STR	<CURRENT-TEXT-BUFFER>,<EQUCTB,>
;STR	<DISPLAY-BOUNDS>,<EQUDBN,>
STR	<DISPLAY-LINES>,<EQUDLN,>
STR	<INPUT-FILE>,<EQUIFL,>
STR	<LEAVE-BLANK-LINE>,<EQULBL,EQ$NMA>
STR	<LAST-SEARCH-STRING-LENGTH>,<EQULSL>
STR	<OUTPUT-FILE>,<EQUOFL,>
STR	<Q-DIRECTORY>,<EQUQDR,>
STR	<REVERSE-SEARCH-FLAG>,<EQURVS,EQ$NMA>
STR	<SCREEN-ADDRESS>,<EQUSCA,EQ$NMA>
STR	<TERMINAL-TYPE>,<EQUTTY,>
> ; End of EQUNAM

DEFINE STRSUB(RTN,FLAGS<0>),<EXP <IFIW RTN>,<FLAGS>>

	SYN	EQUNAM,STRTBL
	
	DOSTR(EQU)

	SUBTTL	E Commands -- E? command -- CURRENT-TEXT-BUFFER

;+
;.hl2 CURRENT-TEXT-BUFFER
; This routine will return the name of the Q-register that is currently being
;edited.
;-

EQUCTB:	JUMPN	P1,[ERROR E.QNN] ; Can't have a Q-reg for this command
	MOVEI	T1,1		; Get a character
	PUSHJ	P,GETSTR	; long buffer
	MOVEI	T1,SARG$1	; Get the text buffer pointer
	MOVEI	T2,[$STRING(<^G/CUREDT/^N>)] ; Get the string 
	PUSHJ	P,.INSRT	; Insert it
	PJRST	PASRET		; And return
	SUBTTL	E Commands -- E? command -- INPUT-FILE

;+
;.HL2 INPUT-FILE
; This routine will handle theE?(q-reg)INPUT-FILE$ command. This will return
;a string argument which is the file specification for the current input file
;for the Q-reg.
;-

EQUIFL:	JUMPE	P1,[ERROR E.QNR] ; If no Q-reg given, complain
	MOVE	T1,P1		; Get the Q-reg address
	PUSHJ	P,QTXTEI	; And set up for reading text
	PUSHJ	P,GETFDI	; Get the input file
	 PJRST	EQUNUL		; Return the null string
	JRST	EQUF.0		; Join common routine



	SUBTTL	E Commands -- E? command -- OUTPUT-FILE


;+
;.HL2 OUTPUT-FILE
; This routine will handle the E?(q-reg)OUTPUT-FILE$ command.  It will
;return a string which is the file specification of the output file for
;the given Q-register.
;-

EQUOFL:	JUMPE	P1,[ERROR E.QNR] ; If no Q-reg given, complain
	MOVE	T1,P1		; Get the Q-reg address
	PUSHJ	P,QTXTEI	; And set up for reading text
	PUSHJ	P,GETFDO	; Yes, get the FD address
	 PJRST	EQUNUL		; None, return the null string

EQUF.0:	MOVE	P1,T1		; Get the FDB address
	MOVEI	T1,^D20		; Probably about 20 characters
	PUSHJ	P,GETSTR	; Get the string
	MOVEI	T1,SARG$1	; Get the address of the TPT
	MOVEI	T2,[$STRING(<^F/P1/^N>)] ; Get the address of the string
	PUSHJ	P,.INSRT	; Insert the text
	PJRST	PASRET		; And return


; Here to return the null string for Q-regs which don't have a file open.

EQUNUL:	SETZ	T1,		; Get 0 characters
	PUSHJ	P,GETSTR	;  .  .  .
	PJRST	PASRET		; And return the null
	SUBTTL	E Commands -- E? command -- DISPLAY-LINES

;+
;.hl2 DISPLAY-LINES
; This routine will handle the E?(q-reg)DISPLAY-LINES$ command. It will
;return two arguments as taken by an E$ command.
;If the Q-register name is not given, it will use the current editing
;buffer.
;-

EQUDLN:	MOVX	T1,QR$VID	; Get the flag to check
	JUMPN	P1,EDLN.1	; If we have the Q-reg name, just go do it
	MOVE	P1,CUREDT	; Otherwise use the current editing buffer
	TDNN	T1,$QRFLG(P1)	; Is this displayed?
	 XMOVEI	P1,TXTBUF	; No, assume he wants TEXT-BUFFER
EDLN.1:	LOAD.	A1,QRGOFS,(P1)	; Get the offset to the first line
	LOAD.	A2,QRGNLN,(P1)	; And the number of lines
	ADD	A2,A1		; Get the last line number
	AOJ	A1,		; And the first
	TDNN	T1,$QRFLG(P1)	; Is it really displayed?
	 SETZB	A1,A2		; No, return zeros
	PJRST	VALRT2		; Return the values
	SUBTTL	E Commands -- E? command -- LEAVE-BLANK-LINE

;+
;.hl2 LEAVE-BLANK-LINE
; This routine will return or set the value of the display blank line flag
;for a Q-register.
;-

EQULBL:	JUMPE	P1,[ERROR E.QNR] ; If no Q-reg given, complain
	MOVX	T1,QR$DLC	; Get the flag to check
	TXNE	F,F.ARG		; Argument given?
	 JRST	ELBL.1		; Yes, go set the flag
	TDNN	T1,$QRFLG(P1)	; Check if it is set
	 PJRST	RETZER		; No, return a zero
	PJRST	RTONES		; Yes, return -1

ELBL.1:	CAIN	P1,CMDBUF	; Can't change command buffer flgas
	 POPJ	P,		; Just pretend we allowed it
	ANDCAM	T1,$QRFLG(P1)	; Turn off the flag
	JUMPE	A1,.POPJ	; And return if that is the desired setting
	IORM	T1,$QRFLG(P1)	; Otherwise turn it on
	POPJ	P,		; And return
	SUBTTL	E Commands -- E? command -- Q-DIRECTORY

;+
;.hl2 Q-DIRECTORY
; This routine will handle the E?Q-DIRECTORY$ command.  This will return
;a string argument which is a list of the currently active Q-register names
;and some information about each.
;-

EQUQDR:	MOVEI	T1,^D50		; Assume 50 characters for a start
	PUSHJ	P,GETSTR	; Get a text buffer for the string argument return
	SKIPN	T1,P1		; Have a specific Q-reg?
	 JRST	EQDR.0		; Go do the complete listing
	MOVEI	T2,[$STRING(<^G/LASQRG/^N>)] ; Get the $STRING for the name
	PUSHJ	P,EQDR.S	; List this QRG
	PJRST	PASRET		; And return

; First loop through the single character names, checking for Q-registers
;with either text or a non-zero value.
;

EQDR.0:	MOVSI	P1,-<"Z">	; Get the count for all possible characters (upper case)

EQDR.1:	MOVX	T1,CF.QRG	; See if a valid Q-reg name
	TDNN	T1,CHRFLG(P1)	;  .  .  .
	 JRST	EQDR.2		; No, try the next
	LOAD.	T1,CDTQRI,+CHRFLG(P1) ; Get the Q-reg index
	IMULX	T1,$QRLEN	; Make the offset
	ADDI	T1,QTAB		; Plus the base address
	MOVEI	T2,[$STRING(<^7/CH/^N>)] ; Get the name type out string
	MOVEI	CH,(P1)		; Get the character name
	LOAD.	T3,QRGDTP,(T1)	; Get the data type
	CAXN	T3,$DTNUM	; Numeric value?
	 SKIPE	$QRVAL(T1)	; Yes, non-zero?
	  PUSHJ	P,EQDR.S	; List the info for this QRG
EQDR.2:	AOBJN	P1,EQDR.1	; Loop for all of the permanent Q-registers

; Now do the special purpose long names

	MOVE	P1,[XWD -QNMLEN,QNMTBL] ; Get the pointer to the table

EQDR.3:	MOVE	CH,(P1)		; Get the address of the data
	MOVE	T1,2(CH)	; Get the QRG address
	MOVEI	T2,[$STRING(<^B/(CH)/^N>)] ; Get the string to type the name
	PUSHJ	P,EQDR.S	; Do it
	AOBJN	P1,EQDR.3	; And do the rest of the special Q-regs

; Now go down the chain of the defined Q-registers.

	LOAD.	P1,LNKNXT,+QRGLNK ; Have any Q-registers defined?
	PJUMPE	P1,PASRET	; No, all done

EQDR.4:	LOAD.	T1,SYMQRG,(P1)	; Get the address of the QRG block
	MOVE	A1,T1		; Get a safer copy
	MOVEI	T2,[$STRING(<^G/A1/^N>)] ; Get the string pointer to type out the name
	PUSHJ	P,EQDR.S	; Stuff the text
	LOAD.	P1,LNKNXT,+$SYLNK(P1) ; Get the address of the next Q-register
	JUMPN	P1,EQDR.4	; Have one?

	PJRST	PASRET		; All done, return


; Subroutine to list the information for a Q-register.
; Usage:
;	T1/ QRG block address
;	T2/ Address of $STRING to list the name
;	PUSHJ	P,EQDR.S

EQDR.S:	$SAVE	<P1,P2,P3,P4>	; Save some ac's
	DMOVE	P1,T1		; Get the arguments
	LOAD.	T1,QRGDTP,(P1)	; Get the data type
	CAXE	T1,$DTTXT	; Is this text?
	 JRST	EQDS.1		; No, just a number
	LOAD.	T1,TPTADR,+$QRTPT(P1) ; Yes, get the address of the buffer
	LOAD.	T3,BLKPT,(T1)	; Get the position
	LOAD.	T4,BLKEND,(T1)	; And the length
	XMOVEI	P3,[$STRING(<Text .=^D/T3/, Z=^D/T4/^N>)] ; Get the type out string
	JRST	EQDS.2		; Go write the text
EQDS.1:	CAXE	T1,$DTNUM	; Numeric value?
	 SKIPA	P3,[[$STRING(<FC table>)]] ; No, must be an FC table
	  XMOVEI P3,[$STRING(<Value=^D/$QRVAL(P1)/^N>)] ; For numerics, just print the value
EQDS.2:	XMOVEI	T1,SARG$1	; Get the pointer to where to put the text
	XMOVEI	T2,[$STRING(<(^S/(P2)/):	^S/(P3)/>)] ; Get the text
	PUSHJ	P,.INSRT	; Insert the text
	LOAD.	T3,QRGOFS,(P1)	; Get the offset to where this is displayed
	LOAD.	T4,QRGNLN,(P1)	; Get the number of lines
	ADD	T4,T3		; Get the final line
	AOJ	T3,		; And make them external line numbers
	MOVE	T1,$QRFLG(P1)	; Get the flags
	TXNN	T1,QR$VID	; Is this displayed?
	 SKIPA	T2,[[$STRING(<^N^M^J>)]] ; No, just do the CRLF
	  MOVEI	T2,[$STRING(<,	Displayed:^D/T3/:^D/T4/^N^M^J>)]
	MOVEI	T1,SARG$1	; Get the pointer to the buffer
	PJRST	.INSRT		; And insert the text
	SUBTTL	E Commands -- E? command -- SCREEN-ADDRESS

;+
;.HL2 SCREEN-ADDRESS
; This will return the screen coordinates of the given position.  If no
;Q-register is given it will assume the current editing buffer, and if
;no numeric argument is given it will assume the current pointer position
;for the given Q-register.  It will return two arguments, the first being
;the X position, and the second the Y position.  If the given position is
;not displayed, it will return zeros for both arguments.
;-

EQUSCA:	MOVX	T1,QR$VID	; See if current buffer is displayed
	JUMPN	P1,ESCA.1	; If a Q-reg was given skip this
	MOVE	P1,CUREDT	;  .  .  .
	TDNN	T1,$QRFLG(P1)	; Is it?
	 XMOVEI	P1,TXTBUF	; No, try text-buffer

ESCA.1:	TDNN	T1,$QRFLG(P1)	; Is it displayed?
	 JRST	[SETZB	A1,A2		; No, clear the return args
		PJRST	VALRT2]		; And return both args
	LOAD.	T1,TPTADR,+$QRTPT(P1) ; Get the address of the buffer
	TXNN	F,F.ARG		; Did we have an argument?
	 LOAD.	A1,BLKPT,(T1)	; No, use current position
	MOVE	T1,A1		; Get the position
	MOVE	T2,P1		; And the QRG
	PUSHJ	P,FNDCHP	; Find where the character is
	 SETOB	T1,T2		; Make so we return zeros
	AOS	A2,T1		; Get the X position
	AOS	A1,T2		; And the Y position
	PJRST	VALRT2		; Return the args
	SUBTTL	E Commands -- E? command -- TERMINAL-TYPE

;+
;.HL2 TERMINAL-TYPE
;This will return a string argument that is the name of the current terminal
;type that the user is connected to.
;-

EQUTTY:	JUMPN	P1,[ERROR E.QNN]	; Can't have a Q-reg for this command
	MOVEI	T1,1			; Get a character
	PUSHJ	P,GETSTR		; long buffer
	MOVEI	T1,SARG$1		; Get the text buffer pointer
TOPS10<
	MOVEI	T2,[$STRING(^W/TRMTYP/^N)] ; Get the string to use
>; End of TOPS10
TOPS20<
	MOVE	T3,TRMTYP		; Get the terminal type
	MOVEI	T2,[$STRING(^T/@TRMNAM(T3)/^N)] ; Get the string to use
>
	PUSHJ	P,.INSRT		; Insert the text
	PJRST	PASRET			; And return
	SUBTTL	E Commands -- E? command -- LAST-SEARCH-STRING-LENGTH

;+
;.HL2 LAST-SEARCH-STRING-LENGTH
; This routine will return the length of the last search string that
;was found.
;-

EQULSL:	JUMPN	P1,[ERROR E.QNN] ; Q-reg not allowed
	MOVE	A1,SRHLEN	; Get the last string length found
	PJRST	VALRET		; And return it
	SUBTTL	E Commands -- E? command -- REVERSE-SEARCH-FLAG

;+
;.hl2 REVERSE-SEARCH-FLAG
; This routine will set or clear the reverse search flag, or return the
;value of the flag.  If the reverse search flag is set, then reverse
;searches will leave the pointer immediately before the first character
;in the occurance of the search string that was found.  If the flag
;is clear, then the reverse search will leave the pointer after the
;last character of the occurance of the search string.
;-

EQURVS:	JUMPN	P1,[ERROR E.QNN]	; Complain if Q-reg name given
	TXNE	F,F.ARG			; Argument given?
	 JRST	ERVS.1			; Yes, go set or clear the flag
	TXNE	S,S.RVRS		; No, is the flag set?
	 PJRST	RTONES			; Yes, return -1
	PJRST	RETZER			; No, return 0

ERVS.1:	TXZ	S,S.RVRS		; Assume clearing the flag
	JUMPE	A1,.POPJ		; If value is zero, leave it clear
	TXO	S,S.RVRS		; Otherwise set it
	POPJ	P,			; And return
	SUBTTL	E Commands -- Subroutines -- E$DFLT

;+
;.HL2 E$DFLT
;This is a special defaulting routine for ER/EW and EB processing.
;.literal
;
; Usage:
;	MOVEI	T1,To FDB
;	MOVEI	T2,From FDB
;	PUSHJ	P,E$DFLT
;	(Return)
;.end literal
;-

DEFINE DEFFDB(FIELD,BIT,%1)<
IFNB <BIT>,<
	MOVX	T1,FD.'BIT	;; Get the bit to check
	TDNE	T1,.FDFLG(P1)	;; Check if field was given
	 JRST	%1		;; Given, leave it alone
	TDNE	T1,.FDFLG(P2)	;; Do we need it on?
	 IORM	T1,.FDFLG(P1)	;; Yes, flag it
>;; End of IFNB <BIT>
	LOAD.	T1,FDB'FIELD,(P2) ;; Get the default
IFB <BIT>,<CFXN.	T2,FDB'FIELD,(P1),0	;; Check if given>
	 STOR.	T1,FDB'FIELD,(P1) ;; Store the value
IFNB <BIT>,<%1:!>
> ; End of DEFFDB definition

DEFINE	CPYFDB(FIELD)<
	LOAD.	T1,FDB'FIELD,(P2) ;; Load the field
	STOR.	T1,FDB'FIELD,(P1) ;; Store it into the other field
>; End of CPYFDB

E$DFLT:	$SAVE	<P1,P2>		; Save P1 and P2
	DMOVE	P1,T1		; Copy the arguments
	MOVX	T1,FD.NDF	; Check if /NODEFAULT
	TDNE	T1,.FDFLG(P1)	;  given
	 POPJ	P,		; Yes, don't do any defaulting
	DEFFDB	NOD		; Default the node name
	DEFFDB	NAM		; Default the name
	DEFFDB	EXT,HEX		; Default the extension
	DEFFDB	PRO,HPR		; Default the protection
	DEFFDB	VER		; Default the version
	DEFFDB	MOD		; Default the mode
	MOVX	T1,FD.PTH	; Get the path bit
	TDNE	T1,.FDFLG(P1)	; Was the field specified ?
	  POPJ	P,		; No, just return to the caller
	TDNE	T1,.FDFLG(P2)	; Over here ?
	 IORM	T1,.FDFLG(P1)	; Light it over here too
	CPYFDB	PPN		; Default the PPN
	CPYFDB	SFD		; Default the path
	CPYFDB	SF2		; . . .
	CPYFDB	SF3		; . . .
	CPYFDB	SF4		; . . .
	CPYFDB	SF5		; . . .
	POPJ	P,		; Return to the caller
	SUBTTL	E Commands -- Subroutines -- E$DFSW

;+
;.HL1 E$DFSW
; This routine is called to default any switch values which have not
;been specified.  It will go through the tables and copy the value from
;one to the other.
;.lit
;
; Usage:
;	T1/ Address of user specified switches
;	T2/ Address of default switch block
;	T3/ Length of switch block
;	T4/ Flags from FDB
;	PUSHJ	P,E$DFSW
;	(return)
;
;.end lit
;-

E$DFSW:	TXNN	T4,FD.DEF	; Reset of defaults wanted?
	 JRST	DFSW.0		; No, skip it
	PUSH	P,T1		; Save T1
IFE FTXADR,<
	HRLI	T1,(T2)		; Set up the BLT pointer
	HRRI	T1,1(T2)	; To clear out the switches
	SETOM	(T2)		;  .  .  .
	ADD	T2,T3		; Get the final address +1
	CAIE	T3,1		; Only one word?
	 BLT	T1,-1(T2)	; No, clear the block
	SUB	T2,T3		; Get the base address back
> ; End of IFE FTXADR
IFN FTXADR,<PRINTX ? Clear default switch block in E$DFSW>
	POP	P,T1		; Restore T1

DFSW.0:	TXNE	T4,FD.NDF	; No defaults wanted?
	 POPJ	P,		; No, just return now

DFSW.2:	MOVE	T4,(T1)		; Get the user switch value?
	CAXN	T4,-1		; Want default?
	 MOVE	T4,(T2)		; Yes, get the value
	MOVEM	T4,(T1)		; Reset the value
	MOVEM	T4,(T2)		; And save as default
	AOJ	T1,		; Bump the pointers
	AOJ	T2,		;  .  .  .
	SOJG	T3,DFSW.2	; And loop for all switches
	POPJ	P,		; All done
	SUBTTL	Low segment

	$IMPURE			; Impure data area
	LOWVER(ECM,4)		; Low segment version number


E$ZBEG:!
DEF$EW:	BLOCK	.FDLEN		; Pointer to the default EW
DEF$EL:	BLOCK	.FDLEN		; Pointer to the default EL
DEF$ER:	BLOCK	.FDLEN		; Pointer to the default ER specification
;DEF$EB:	BLOCK	.FDLEN		; Pointer to the default EB specification
DEF$EQ:	BLOCK	.FDLEN		; Pointer to the default EI/EQ/EP spec
DEF$EE:	BLOCK	.FDLEN		; Pointer to default EE spec

; EB command storage

E$OBEG:!			; Start of area to be set to -1

DFTIMD:	BLOCK	1		; Default /IMODE
DFTOMD:	BLOCK	1		; Default /OMODE
DFTYNK:	BLOCK	1		; Default /YANK
E$OEND==.-1

LS$INP:	BLOCK	1		; Inplace switch
LS$RED:	BLOCK	1		; /READONLY switch
LS$YNK:	BLOCK	1		; /YANK switch

; EL command storage

FDB$EL:	BLOCK	1		; Pointer to the currently open log file
L$COUN:	BLOCK	1		; Number of characters to output between checkpoints
L$CNTR:	BLOCK	1		; Running counter
DEFINE SW(NAME,LOC,ROUTINE,VALUE,FLAGS),<LOC:	BLOCK	1>

SL$BEG:!
	SWT$EL			; Generate the storage for the switches
SL$END==.-1


; Storage for ER command


ER$BEG:!
SR$SLS:	BLOCK	1		; /SUPLSN switch
SR$YNK:	BLOCK	1		; /YANK or /NOYANK switch
ER$END==.-1

ER$DFS:	BLOCK	ER$END-ER$BEG+1	; Space for defaults

; Storage for EW command

EW$BEG:!
	DEFINE	SW(NAME,LOC,ROUTINE,VALUE,FLAGS)<LOC:	BLOCK	1>

	EW$SW

EW$END==.-1

; Storage for EI/EP commands

EPIQRG:	BLOCK	1		; Pointer to text buffer for EI/EP command
E$ZEND==.-1

; Storage for EE command

RUNDEV:	BLOCK	1		; Device we were orignally run from
RUNNAM:	BLOCK	1		; Name we were originally run with
RUNPTH:	BLOCK	.PTMAX		; Path block for GETSEG
EEACS:	BLOCK	20		; Ac's saved for restart

; Storage for ED command

ED$FDB:	BLOCK	1		; FDB for the ED command
ED$PTH:	BLOCK	.PTMAX		; Path specification for the RUN
ED$BLK:	BLOCK	6		; RUN argument block
ED$COD:	BLOCK	RUNLEN		; RUN code

ED$BEG:!			; Beginning of the switch area for ED
	ED$SW			; Expand the switch area
ED$END==.-1			; End of the switch area

; For E. command

CUREDT:	BLOCK	1		; Current QRG being edited


STARTL:	BLOCK	STR.LN		; Block for low segment restart code for EE command

; Table for EO level skip instructions. These are executed by the CHKEO
;macro. If the instruction skips, the EO is less than or equal to the
;index used.

EOXCTS:	BLOCK	EOVAL		; Allocate enough room.
	SUBTTL	End of TECECM

	END			; End of TECECM