	.TITLE	EDI02
	.PSECT EDI02
	.IDENT	/X01/
mutask=1
	.ENABL LC
        .ENABL ama
;
; EDITOR (TEMP FILE VERSION)
;
; VERSION X01
;
; DAVID G. CONROY	05-JAN-78
;
;
; as modified by Eric Levy
;
			.if df mutask
				.macro pure
                                .psect pur,ro
				.endm

				.macro impure
                                .psect ipur,rw
				.endm
			
			.iff
			
				.macro pure
				.endm
				.macro impure
				.endm
			
			.endc
	.GLOBL	ACOM
	.GLOBL	CCOM
	.GLOBL	DCOM
	.GLOBL	ECOM
	.GLOBL	FCOM
	.GLOBL	GCOM
	.GLOBL	ICOM
	.GLOBL	JCOM
	.GLOBL	KCOM
	.GLOBL	MCOM
	.GLOBL	OCOM
	.GLOBL	PCOM
	.GLOBL	PCOM1
	.GLOBL	QCOM
	.GLOBL	RCOM
	.GLOBL	SCOM
	.GLOBL	UCOM
	.GLOBL	VCOM
	.GLOBL	WCOM
	.GLOBL	XCOM
	.GLOBL	ZCOM
	.GLOBL	DEFDOT
	.GLOBL	DEFall
	.GLOBL NONZER
	.GLOBL NOADDR
	.globl sstore

	.MCALL	CALL
	.MCALL	CALLR
	.MCALL	RETURN
	.MCALL	FDAT$R
 	.MCALL	OPEN$
	.MCALL	OPEN$W
	.MCALL	PUT$S
	.MCALL	EXIT$S
        .mcall dir$,qiow$

	.MACRO POP A
	MOV (SP)+,A
	.ENDM

	.MACRO PUSH A
	MOV A,-(SP)
	.ENDM


;
; LOCAL DATA
;


                        impure

wattr:  qiow$   io.wat,2,7,,pios,,<0,alist> ;write attributes
alist:  .byte    2,2                    ;write protection of output file
        .word protec                    ;and get it from here

pios::   .word 0,0               ;write attr status
last.s:	.word -1		;last sub's address (seek)
last.d:	.word -1		;and the dot value at the time
ABUFR:	.BLKB	100.		;TEMP FOR APPEND CMD
ABUFRE:	.BLKB	2		;END OF BUF AND SPARE FOR SAFETY.
mes1:	.asciz / <- temp    f.err-> /
NOTRAIL: .ASCII /P/<12>		;P AND NEWLINE
APLINE:	.ASCII	<1>/$/<1>	;CONTROL A AS A DELIMETER
INLINE:	.ASCII	<1>/^/<1>	;LIKEWISE
	.EVEN
FUDGE:	.BLKW	1		;DELTA ADDRESS FOR K
VFLAG:	.BLKW	1		;GLOBAL/EXCLUDE FLAG
SANY:	.BLKW	1		;ANYTHING AT ALL FOR SUBSTITUTE
FP:	.BLKW	1		;FILE I/O POINTER
SFLAG:	.BLKW	1		;ONCE FLAG FOR SUBSTITUTE
FC:	.BLKW	1		;RECORD COUNT
SNUM:	.BLKW	1		;NUMBER IN S#
SWNUM:	.BLKW	1		;PER LINE COPY OF SNUM
P1FLAG:	.WORD	0		;MARK ON LINE PRINT


                        pure

;+
; ** COMMAND PROCESSORS
;
; THESE ROUTINES ARE CALLED BY THE COMMAND DISPATCHER TO EXECUTE THE
; USER'S COMMANDS. THEY EITHER RETURN TO THE DISPATCHER SUCCESSFULLY
; OR JUMP DIRECTLY TO ERROR.
;-

;
; APPEND
;

ACOM:
	CALL	DEFDOT		;DEFAULTS
	CALL GETC		;ANY THING ON THE LINE
	CMP R0,#NL		;NOT IF NL
	BEQ 10$			;SO CONTINUE AS USUAL
	MOV R0,PEEK		;PUT IT BACK FOR LATER
	MOV #APLINE,R0		;ELSE CONSTRUCT A SUB CMD
	CALLR ONLINE		;AND GO DO IT.
10$:	CLR	OLDCMD		;CLEAR COMMAND ON LINE FLAG
	MOV	#GETTY,R4	;ROUTINE
	MOV	ADR2,R5		;WHERE TO APPEND
	CALLR	APPEND		;GO APPEND
;
; ONLINE -- ON LINE APPEND OR INSERT, CONSTRUCT THE SUB COMMAND.
;           R0=ADDR OF STRING TO PUT BACK
;	       THE LENGTH IS 3. USED ONLY BY INSERT AND APPEND
;
ONLINE:
	MOV #ABUFR,R1		;ADDR OF TEMP BUFFER
	MOVB (R0)+,(R1)+	;MOVE A CHAR
	MOVB (R0)+,(R1)+	;MOVE A CHAR
	MOVB (R0)+,(R1)+	;MOVE A CHAR
15$:
	PUSH R1
	CALL GETC
	POP R1
	MOVB R0,(R1)+		;MOVE USER STRING TO TEMP BUFFER TOO.
	CMP R0,#EOF		;TEST FOR GLOBAL EOF
	BNE 16$			;SKIP IF NOT
	MOV #NL,R0		;ELSE USE NL
16$:	CMP R0,#NL		;LAST CHAR TO MOVE?
	BEQ 17$			;YEP IF EQ
	CMP R1,#ABUFRE		;TOO LONG A STRING TO FIT IN TEMP BUFF?
	BHI 20$			;YES IF HI
	BR 15$			;ELSE BACK FOR MORE
17$:
	SUB #ABUFR,R1		;COMPUTE LENGTH OF LINE
	MOV #ABUFR,R0		;SET UP PUTBACK PARMS
	CALL PUTBAK
	CALLR SCOM		;NOW GO DO THE SUB CMD
20$:	CLR R1			;ERROR 0
	JMP ERROR
;
; PUTR0 -- PUTBACK R0
;
PUTR0:
	PUSH R1
	PUSH R0
	MOV SP,R0		;ADDRESS OF THE CHAR
	MOV #1,R1		;LENGTH
	CALL PUTBAK		;GO DO IT
	POP R0
	POP R1
	RETURN


;
; CHANGE
;

CCOM:	CALL	NONZER		;DEFAULTS
	CALL	TDELIM		;
	CLR	OLDCMD		;CLEAR COMMAND ON LINE FLAG
	CALL	DELETE		;MAKE TEXT GO AWAY
	MOV	#GETTY,R4	;ROUTINE
	MOV	ADR1,R5		;APPEND PLACE
	TST	-(R5)		;
	CALLR	APPEND		;

;
; DELETE
;

DCOM:	CALL	NONZER		;DEFAULTS
	tst guptr		;in global (0=no)
	bne 5$			;yes, skip bounce check
	push r0
	call getc		;safe guard against bounce problems
	cmp r0,#'p
	beq 3$
	cmp r0,#'P
	beq 3$
	cmp r0,#nl
	bne 10$			;only 1 d command on a line (unless global)
3$:	mov r0,peek		;put it back
	pop r0
5$:	CALLR	DELETE		;
10$:	mov #2,r1
	jmp error

;
; EDIT
;

ECOM:	CALL	NOADDR		;NO ADDRESS IS LEGAL
	CALL FILE
	MOV	ZERO,DOL	;CLEAR TEXT
	MOV	ZERO,DOT	;
	CLR	TPTR		;START AT TEMPFILE BLOCK 0
	MOV	ZERO,R5		;READ IN STUFF FROM FILE
	CALL SAVEFN	;SAVE THE NAME IF SYNTAX OK
	CALL READN2	;GO DO THE INPUT NOW
	MOV ZERO,DOT		;GO TO LINE 1
	ADD #2,DOT
	CMP DOT,DOL		;MAKE SURE NOT ZERO FILE
	BLOS 10$
	MOV DOL,DOT		;IF SO, SET DOL TO DOT
10$:
	call autostart          ;execute line 1 if its auto execute
	RETURN

;
; FACTS
;

FCOM:                           ;now - ADDRESS IS ALLOWED
10$:	CALL	GETC		;SKIP OVER BLANKS
	CMP	R0,#' 		;
	BEQ	10$		;
	CMP	R0,#NL		;BR IF NO FILENAME
	BEQ	50$		;
	CMP	R0,#EOF		;
	BEQ	50$		;
	MOV	#SFN,R1		;GET POINTER TO SAVE FILE BUFFER
20$:	CMP	R1,#SFN+FNS-1	;DOES IT FIT
	BHIS	30$		;NO, IGNORE
	MOVB	R0,(R1)+	;SAVE THE CHARACTER
30$:	CALL	GETC		;CONTINUE TILL NEWLINE
	CMP	R0,#NL		;
	BEQ	40$		;
	CMP	R0,#EOF		;
	BNE	20$		;
40$:	CLRB	(R1)		;THEN APPEND A NULL
50$:	TSTB	SFN		;IS THERE A FILE NAME
	BEQ	80$		;NO
	MOV	#SFN,R1		;YES, POINT AT IT
60$:	MOVB	(R1)+,R0	;PRINT TILL THE NULL
	BEQ	70$		;
	CALL	TTYC		;
	BR	60$		;
70$:	CALL	TTYNL		;APPEND A NEWLINE, AND
80$:	RETURN			;DONE

;
; GLOBAL
; EXCLUDE
;

GCOM:	CLR	VFLAG		;GLOBAL
	BR	GV		;

VCOM:	MOV	#1,VFLAG	;EXCLUDE
GV:	CALL	DEFALL		;DEFAULT TO 1,$
	TST	GUPTR		;IN A GLOBAL
	BEQ	20$		;NO
	MOV	#9.,R1		;CANNOT NEST GLOBALS
	JMP	ERROR		;

20$:	CALL	GETC		;GET PATTERN
	CALL	COMPIL		;

;
; MARK ALL LINES FOR WHICH THE COMMAND LINE
; WILL BE EXECUTED.
;

	MOV	ZERO,R1		;MARK THE LINES
30$:	TST	(R1)+		;
	CMP	R1,DOL		;SEE IF DONE
	BHI	60$		;YES
	BIC	#1,(R1)		;REMOVE OLD MARK
	CMP	R1,ADR1		;DUCK OUT IF NOT IN RANGE
	BLO	30$		;
	CMP	R1,ADR2		;
	BHI	30$		;
	MOV	(R1),R0		;MATCH HERE
	CALL	GETLIN		;
	MOV	#LBUF1,R0	;
	CALL	AMATCH		;
	BCS	40$		;BR IF NOT
	TST	VFLAG		;MARK LINE IF GLOBAL
	BNE	30$		;
	INC	(R1)		;
	BR	30$		;
40$:	TST	VFLAG		;NO MATCH, MARK IF EXCLUDE
	BEQ	30$		;
	INC	(R1)		;
	BR	30$		;

;
; COLLECT UP COMMAND LINE
;

60$:	MOV	#GUBUF,R1	;COLLECT UP THE LINE
70$:	CALL	GETC		;UNTIL NEWLINE
	CMP	R0,#'\		;ESCAPE
	BNE	72$		;NO
	CALL	GETC		;GET ACTUAL CHARACTER
	cmp r0,#nl		;fix \\ in
	beq 74$			;pass nl's only (else \ is literal)
	mov r0,peek		;put back next char
	mov #'\,r0		;restore the \ and copy it
	BR	74$		;
72$:	CMP	R0,#NL		;
	BEQ	80$		;
74$:	CMP	R1,#GUBUF+GUBS-1;GIVE ?0 IF THE LINE IS TOO LONG
	BHIS	90$		;
	MOVB	R0,(R1)+	;
	BR	70$		;

;
; SET GLOBAL I/O
; RETURN TO COMMAND SCANNER
;

80$:	CLRB	(R1)		;MARK END
	MOV	R1,GUPTR	;WILL GET EOF IMMEDIATELY
	RETURN			;

90$:	CLR	R1		;?0
	JMP	ERROR		;

;
; INSERT
;

ICOM:
	CALL GETC		;SEE IF ANYTHING ON LINE
	CMP R0,#NL		;IS IT A NEW LINE
	BEQ 5$			;IF IT IS, CONTINUE AS USUAL
	MOV R0,PEEK		;PUT IT BACK FOR LATER
	MOV #INLINE,R0		;ELSE MAKE UP A SUB CMD
	CALLR ONLINE		;GO DO IT
5$:	MOV R0,PEEK		;PUT BACK THE TERMINATOR
	CMP	ZERO,DOL	;EMPTY BUFFER
	BNE	10$		;NO
	MOV	ZERO,ADR2	;ITS JUST A 0A
	BR	20$		;
10$:	CALL	NONZER		;DEFAULTS
	SUB	#2,ADR2		;
20$:	CALL	TDELIM		;
	CLR	OLDCMD		;CLEAR OLD COMMAND FLAG
	MOV	#GETTY,R4	;ROUTINE
	MOV	ADR2,R5		;INSERT TEXT
	CALLR	APPEND		;

;
; COPY (KOPY)
;

KCOM:	CALL	NONZER		;DEFAULTS
	CALL	ADDRES		;GET THE COPY DESTINATION
	MOV	R0,PEEK		;PUT THE DELIMITER BACK
	call defd.t	;accept a default of dot here
	TST	R2		;MUST GET AN ADDRESS (unless nl delimeter)
	BEQ	20$		;OR ?9
	CLR	FUDGE		;ADDRESS ADJUSTMENT FUDGE
	CMP	R2,ADR2		;EASY
	BHIS	10$		;YES
	CMP	R2,ADR1		;IMBEDDED
	BHIS	20$		;YES, ?9
	MOV	#2,FUDGE	;MUST FUDGE ADDRESSES
10$:	MOV	#30$,R4		;GET ROUTINE
	MOV	R2,R5		;APPEND PLACE
	CALLR	APPEND		;APPEND TEXT AND RETURN
20$:	MOV	#9.,R1		;?9
	JMP	ERROR		;

30$:	CMP	ADR1,ADR2	;ANY MORE
	BHI	40$		;NO
	MOV	ADR1,R1		;GET SOURCE
	ADD	#2,ADR1		;FIX
	ADD	FUDGE,ADR1	;THE
	ADD	FUDGE,ADR2	;ADDRESSES
	MOV	(R1),R0		;PICK UP SEEK ADDRESS
	CALL	GETLIN		;PULL LINE
	CLC			;GOT ONE
	RETURN			;

40$:	SEC			;NO MORE LINES
	RETURN			;

;
; MOVE
;

MCOM:	CALL	NONZER		;CHECK OUT ADDRESES
	CALL	ADDRES		;GET WHERE TO MOVE TO
	MOV	R0,PEEK		;
	call defd.t	;accept a default of dot here
	TST	R2		;MUST GET ONE (unless nl delimeter)
	BEQ	50$		;

	CMP	R2,ADR2		;MOVING UP
	BHI	10$		;BR IF YES
	CMP	R2,ADR1		;MOVING INTO THE MIDDLE
	BHIS	50$		;NOT LEGAL

	MOV	R2,R1		;SET UP FOR THE MOVE
	TST	(R1)+		;
	MOV	ADR2,R2		;
	MOV	ADR1,R5		;
	MOV	ADR2,DOT	;RESET CURRENT LINE
	SUB	R5,DOT		;
	ADD	R1,DOT		;

	CMP	R5,R1		;QUICK CHECK FOR NO WORK
	BEQ	40$		;EXIT
	TST	-(R5)		;
	BR	20$		;GO DO THE MOVE

10$:	
	MOV	ADR1,R1		;UPWARDS MOVE
	MOV	ADR2,R5		;
	MOV	R2,DOT		;RESET CURRENT LINE

20$:	call marktg
25$:	MOV	R5,R3		;DO THE MOVE
	TST	(R3)+		;
	MOV	R3,R4		;
	TST	(R4)+		;
	MOV	(R3),R0		;SAVE BOUNDRY
30$:	MOV	-(R3),-(R4)	;MOVE
	CMP	R3,R1		;
	BHI	30$		;
	MOV	R0,(R3)		;PUT DOWN THE BOUNDRY LINE
	TST	(R1)+		;MOVE FORWARD
	TST	(R5)+		;
	CMP	R5,R2		;DONE
	BLO	25$		;NO
40$:	 call retag
	RETURN			;DONE

50$:	MOV	#9.,R1		;?9 FOR FUNNY STUFF
	JMP	ERROR		;

;
; OPTIONS
;

OCOM:	CALL	NOADDR		;NO ADDRESS FOR OPTIONS COMMAND

10$:	CALL	GETC		;GET OPTION CHARACTER
	CMP	R0,#NL		;NEWLINE
	BEQ	60$		;YES, DONE
        CMP     R0,#'?          ;PRINT TEMP FILE POINTER VALUE
        BNE     140$            ;NOPE
        MOV     $TPTR,R1        ;GET IT
        CALL    TTYNUM          ;PRINT IT
;;      CALL    TTYNL           ;AND A NEWLINE
        mov      #mes1,r0
        call     ttystr
        movb     f.err+fdb,r1   ;get last error code
        call     ttynum
        call     ttynl
        BR      10$             ;THATS ALL


140$:   CMP R0,#'*              ;reset all toggles         o*
	BNE 15$
	clr oa                  ;clear toggles
	mov #-1,ol
        clr ob
        mov #177770,tabmsk
	BR 10$


15$:	BIC	#' ,R0		;FORCE UPPER CASE
	CMP	R0,#'T		;OT
        BNE     16$             ;NO
	CLR	OV		;CLEAR OPTIONS VERBOSE
	BR	10$		;



16$:
	CMP     R0,#'H          ;OH     half tab           oh
        BNE     17$             ;NO
	cmp tabmsk,#177770      ;was it full
	bne oc1                 ;ne so make it full
        mov #177774,tabmsk      ;yes, so make it half tab
	br  oc4
oc1=.
        mov #177770,tabmsk
oc4=.
	BR	10$		;



17$:    CMP     R0,#'L          ;OL                        ol
        BNE     18$             ;NO
        com     ol              ;automatic clear of centerline going into lmode
	BR	10$		;



18$:    CMP     R0,#'B          ;ob                        ob
	BNE	20$		;NO
        com     ob              ;don't replace blanks with tabs
	BR	10$		;



20$:    CMP     R0,#'V          ;OV                        ov
	BNE	30$		;NO
	INC	OV		;SET OPTIONS VERBOSE
	BR	10$		;



30$:    CMP     R0,#'S          ;OS                        os
	BNE	40$		;NO
	INC	OS		;SET OPTIONS SENSITIVE
	CALL	REKILL		;KILL OFF SAVED R.E.
	BR	10$		;



40$:    CMP     R0,#'I          ;OI                        oi
	BNE	45$		;NO
	CLR	OS		;SET OPTIONS INSENSITIVE
	BR	10$		;NEXT OPTION


45$:    CMP R0,#'E              ;oe  OPTION                oe
	BNE 48$
	TST OE			;ALLREADY DID IT?
	BLT 47$			;YES IF LT, SO NO NEED TO DO AGAIN
	DEC OE			;ELSE SET FLAG
	MOV S100,-(SP)
	MOV C100,S100		;SWAP C AND S COMMANDS
	MOV (SP)+,C100
47$:
	BR	10$		;




48$:    CMP R0,#'F              ;OFF LINE NUM OPTION  of
	BNE 49$
	CLR ONUM		;ELSE TURN OFF OPTION
	BR 10$


49$:    CMP R0,#'N              ;ON LINE NUM OPT       on
	BNE 490$
	MOV #-1,ONUM		;TURN ON OPTION
	BR 10$


490$:   CMP R0,#'A              ;ON automatic indenting  oa
	BNE 50$
	com oa                  ;toggle  OPTION
	BR 10$


50$:	MOV	#9.,R1		;?9 IF BAD OPTION
	JMP	ERROR		;

60$:	MOV #NL,PEEK			;DONE
	RETURN

;
; PRINT
;

PCOM:	CALL	NONZER		;DEFAULTS
PCOM1:	MOV	ADR1,R1		;GET POINTER TO
	MOV	(R1),R0		;TEXT
	CALL	GETLIN		;
	TST ONUM		;LINE NUM OPTION?
	BEQ 10$			;NOT IF ZERO
	PUSH R0			;PLAY IT SAFE
	PUSH R1
	MOV ADR1,R1		;GET THIS LINE #
	SUB ZERO,R1		;COMPUTE ACTUAL LINE #
	ASR R1
	CALL TTYNUM		;OUTPUT LINE #
	MOV #'),R0		;MAKE LISTING NICE
	CALL TTYC		;OUTPUT ) AND TAB
	CMP ADR1,DOT
	BNE 5$			;SEE IF WE CAN MARK LINE 'DOT'
	TST P1FLAG		;BUT ONLY IF FROM THE Z COMMAND
	BEQ 5$
	MOV #'-,R0		;
	CALL TTYC
	MOV #'-,R0		;MARK WITH --
	CALL TTYC
5$:	MOV #11,R0		; A TAB
	CALL TTYC		;TYPE IT OUT
	POP R1
	POP R0
10$:
	MOV	#LBUF1,R0	;PUT OUT TO THE TTY
	CALL	TTYSTR		;
	ADD	#2,ADR1		;GET NEXT LINE
	CMP	ADR1,ADR2	;
	BLOS	PCOM1		;STILL MORE TO DO
	MOV	ADR2,DOT	;RESET CURRENT LINE
	RETURN			;

;
; QUIT
;

QCOM:	TST WDONE		;DID HE W YET (someday this should be smarter)
	BEQ NOTYET
qcom1:	CALL	NOADDR		;NO ADDRESS ALLOWED
	EXIT$S			;
NOTYET: INC WDONE		;IF HE WANTS, HE MAY RE-ISSUE Q.
	call getc
	cmp r0,#'q
	beq qcom1		;let a qq do a direct exit
	cmp r0,#'Q		;check both cases
	beq qcom1		;let a qq do a direct exit
	mov r0,peek		;put back the char
	MOV #13.,R1		;DID NOT WRITE YET ERROR.
	JMP ERROR

;
; READ
;

RCOM:	CALL	DEFDOT		;DEFAULTS
	MOV	ADR2,R5		;READ STUFF FROM FILE
	CALL	READIN		;
	TSTB	SFN		;IF NO SAVED NAME
	BNE	10$		;THEN
	CALL	SAVEFN		;SAVE THE NAME
10$:	RETURN			;

;
; SUBSTITUTE
;

SCOM:	CALL	NONZER		;DEFAULTS

;	CLR	SNUM		;SET WHICH ONE TO DO
	MOV #1,SNUM		;USE DEFAULT OF 1
	CALL	GETC		;ZERO MEANS ALL
	CMP	R0,#'0		;
	BLO	10$		;
	CMP	R0,#'9		;
	BHI	10$		;
	CALL	GETNUM		;
	MOV	R1,SNUM		;
	CALL	GETC		;

10$:	MOV	R0,R2		;SAVE R.E. DELIMITER
	CALL	COMPIL		;THE PATTERN

;
; COPY RHS TO BUFFER 2.
;

	MOV	#LBUF2,R1	;COPY OVER R.H.S.
20$:	CALL	GETC		;GET CHARACTER
	CMP	R0,#NL		;ERROR FOR NEWLINE
	BEQ	37$		;
	CMP	R0,#EOF		;OR GLOBAL EOF
	BEQ	37$		;
	CMP	R0,#'\		;ESCAPE
	BNE	30$		;NO
	CALL	RSTORE		;SAVE THE ESCAPE
	CALL	GETC		;GET THE ACTUAL CHARACTER
	CMP	R0,#EOF		;CANNOT BE GLOBAL EOF
	BEQ	35$		;
	CALL	RSTORE		;
	BR	20$		;

30$:	CMP	R0,R2		;END OF R.H.S.
	BEQ	40$		;YES
	CALL	RSTORE		;SAVE THE CHARACTER
	BR	20$		;

35$:	MOV	#9.,R1		;?9 IS HERE SO IT REACHES
	JMP	ERROR		;
37$:
	PUSH R0			;PUT BACK THE P AND <NL>
	PUSH R1
	MOV #NOTRAIL,R0		;ADDR OF PUTBACK STRING
	MOV #2,R1			;LEN OF PUTBACK STRING
	CALL PUTBAK
	POP R1
	POP R0
;	BR 40$			;CONTINUE

40$:
	push r0
	call getc	;SEE IF NEXt char is a g
	mov r0,peek	;put back if its not
	bic #40,r0	;map to upper
	cmp r0,#'G	;is it a global substitute the old way
	bne 44$		;not if ne
	clr snum	;else make it global
	mov #-1,peek	;and kill the putback
44$:	pop r0
	CLRB	(R1)		;PUT NULL ON R.H.S. END
	CLR	SANY		;SET NO MATCHES AT ALL

;
; TOP OF THE ONCE PER LINE LOOP.
;

50$:	MOV	SNUM,SWNUM	;RESET SOME VARIABLES
	CLR	SFLAG		;
	MOV	@ADR1,R0	;GET SOURCE LINE
	CALL	GETLIN		;
	MOV	#LBUF1,R2	;POINT AT ORIGINAL TEXT
	MOV	R2,ORG		;FOR MATCH
	MOV	#PBUF,R1	;FOR MATCH
	MOV	#LBUF3,R3	;DESTINATION POINTER

;
; TOP OF THE NEXT MATCH LOOP.
;

60$:	TSTB	(R2)		;ANY MORE
	BEQ	160$		;NO
	MOV	R2,R0		;TRY FOR A MATCH
	CALL	MATCH		;
	BCS	85$		;NO

	TST	SNUM		;DO THEM ALL
	BEQ	80$		;YES
	DEC	SWNUM		;NO, DO THIS ONE
	BNE	85$		;BR IF NO
80$:	CMP	R0,R2		;IS THIS A ZERO LENGTH MATCH
	BNE	90$		;NO
	TST	SFLAG		;DO IT
	BEQ	90$		;BR IF YES

85$:	MOVB	(R2)+,R5	;JUST MOVE ALONG
	CALL	SSTORE		;
	BR	60$		;

90$:	MOV	#LBUF2,R4	;GET POINTER TO R.H.S.
100$:	MOVB	(R4)+,R5	;PICK UP CHARACTER
	BEQ	150$		;DONE
	CMP	R5,#'\		;ESCAPE
	BNE	110$		;NO
	MOVB	(R4)+,R5	;MOVE NEXT CHARACTER
	BR	140$		;

110$:	CMP	R5,#'&		;REPLACE TEXT
	BNE	140$		;NO
	call caseck		;check for & options such as case
	bcs 100$		;cs means its been done for us by caseck.
	MOV	R4,-(SP)	;SAVE R.H.S. POINTER
	MOV	R2,R4		;GET POINTER TO WHAT GOT MATCHES
120$:	CMP	R4,R0		;COPY OVER
	BHIS	130$		;
	MOVB	(R4)+,R5	;
	CALL	SSTORE		;
	BR	120$		;
130$:	MOV	(SP)+,R4	;RESTORE R.H.S.
	BR	100$		;

140$:	CALL	SSTORE		;STORE DOWN THE CHARACTER
	BR	100$		;

150$:	INC	SFLAG		;SET WE DID ONE
	INC	SANY		;SET WE DID ONE AT ALL
	MOV	R0,R2		;MOVE ALONG
	BR	60$		;

;
; END OF LINE.
;

160$:	TST	SFLAG		;ANY CHANGES ON THIS LINE
	BEQ	165$		;NO, GO ON

	CLR	R5		;APPEND A NULL
	CALL	SSTORE		;

	MOV	#LBUF1,R0	;COPY BUF3 TO BUF1
	MOV	#LBUF3,R1	;
162$:	MOVB	(R1)+,(R0)+	;
	BNE	162$		;

	CALL	PUTLIN		;WRITE NEW LINE TO TEMPFILE
	mov @adr1,last.s	;save for the undo command
	MOV	R0,@ADR1	;AND UPDATE THE POINTER TO IT
	MOV	ADR1,DOT	;MOVE DOT TO LAST LINE CHANGED
	mov dot,last.d		;save dot too

;
; ADVANCE TO NEXT LINE.
;

165$:	ADD	#2,ADR1		;ANY MORE
	CMP	ADR1,ADR2	;
	BHI	170$		;NO
	JMP	50$		;GO DO ANOTHER LINE

170$:	TST	GUPTR		;IN A GLOBAL
	BNE	180$		;YES
	tst macflg		;in a macro
	BNE	180$		;YES
	TST	SANY		;NO, DID ANYTHING CHANGE
	BNE	180$		;YES, OK
	MOV	#1,R1		;?1
	JMP	ERROR		;

180$:	RETURN			;DONE
;
; undo
;
ucom:
	call noaddr	;no addresses
	cmp last.s,#-1		;is it setup yet
	beq 10$		;skip if not
	cmp dot,last.d	;compare dot's
	bne 10$
	mov last.s,@dot	;restore it
	return
10$:	mov #4.,r1
	jmp error	;bad address error is good enuf


;
; WRITE
; JOIN
; NEW VERSION (X COMMAND)
;
	.ENABL LSB
XCOM:	INC WDONE		;INDICATE DONE
	MOV #FO.WRT,R5		;FOR WRITE NEW FILE
	CALL DEFALL		;DEF TO ENT FILE NAME
	CALL FILE		;GET NAME
	OPEN$ #FDB,R5		;OPEN WITH NEW VERSION
	BCC W5$			;IF NO ERROR FINISH UP IN "W" CODE
	JMP OPERR		;Cannot open error with code

WCOM:	MOV	#FO.UPD,R5	;WRITE, FIRST TEST IS UPDATE
	INC WDONE		;INDICATE A WRITE HAS BEEN DONE
	BR	WJ		;

JCOM:	MOV	#FO.APD,R5	;JOIN, FIRST TEST IS APPEND

WJ:	CALL	DEFALL		;DEFAULT TO ENTIRE FILE
	CALL	FILE		;GET THE FILE NAME
	OPEN$	#FDB,R5		;TRY TO OPEN THE FILE
	BCC	10$		;OK
	CMPB	F.ERR(R0),#IE.NSF ;IS THE ERROR NO FILE
	BNE	60$		;NO, HARD ERROR
	OPEN$W			;OPEN FOR PLAIN WRITING
	BCS	60$		;ERROR

W5$:				;ENTRY FOR X COMMAND
        tst pflg                ;do we write protection attributes
        beq 10$                 ;only write protection on control-z
        dir$ #wattr

10$:	FDAT$R	,#R.VAR,#FD.CR	;MAKE SURE ATTRIBUTES ARE OK
	CLR	FC		;RECORD COUNT
	MOV	#LBUF2,FP	;WORK POINTER

20$:	MOV	@ADR1,R0	;GET ADDRESS OF LINE
	CALL	GETLIN		;GET TEXT
	MOV	#LBUF1,R2	;

30$:	MOVB	(R2)+,R0	;PUT OUT ALL THE CHARACTERS
	BEQ	40$		;
	CALL	70$		;
	BR	30$		;

40$:	ADD	#2,ADR1		;BUMP TO NEXT LINE
	CMP	ADR1,ADR2	;DONE
	BLOS	20$		;BR IF NOT

	MOV	#FDB,R0		;CLOSE FILE WITH TRUNCATION
	CALL	.TRNCL		;

	TST	GUPTR		;IN GLOBAL
	BNE	50$		;YES
	MOV	FC,R1		;PUT OUT THE COUNT
	CALL	TTYNUM		;
	CALL	TTYNL		;

50$:	TSTB	SFN		;IS THERE A SAVED NAME
	BNE	55$		;YES
	CALL	SAVEFN		;NO, SAVE THE NAME
55$:	RETURN			;

60$:				;OPEN FILE ERROR
OPERR=.
	MOVB F.ERR(R0),R1	;OUTPUT THE ERROR CODE
	BIS #177400,R1
	CALL TTYNUM
	MOV #40,R0
	CALL TTYC		;AND A SPACER, THEN
	MOV	#8.,R1		;FILE OPEN ERROR
	JMP	ERROR		;

70$:	CMP	R0,#NL		;NEWLINE
	BEQ	80$		;YES
	CMP	FP,#LBUF2+LBS	;NO, DOES IT FIT
	BHIS	100$		;NO  ?10
	MOVB	R0,@FP		;PUT IN THE BUFFER
	INC	FP		;
	BR	90$		;

80$:	MOV	FP,R1		;COMPUTE RECORD SIZE
	SUB	#LBUF2,R1	;
	PUT$S	#FDB,#LBUF2,R1	;PUT OUT THE RECORD
	BCS	100$		;ERROR
	INC	FC		;COUNT UP 1 RECORD
	MOV	#LBUF2,FP	;BACK UP POINTER

90$:	RETURN			;DONE

100$:	CALL	.TRNCL		;ERROR, CLOSE THE FILE
	MOVB F.ERR(R0),R1	;OUTPUT THE ERROR CODE
	BIS #177400,R1
	CALL TTYNUM
	MOV #40,R0
	CALL TTYC		;AND A SPACER, THEN
	MOV	#10.,R1		;?10
	JMP	ERROR		;
	.DSABL LSB

;+
;
; ** ZCOM    Z COMMAND
;
;-
ZCOM:	CALL DEFDOT		;DEFAULT TO DOT
	MOV ADR2,ADR1		;USE ONLY ONE ADDRESS
	CALL GETC		;NEXT CHAR->R1
	CMP #'+,R0		;Z+N?
	BNE 20$
	CALL NCHK		;R1 = NUMBER OR 20 (DEF)
	ADD R1,ADR2		;LIST DOWN PART
	BR 50$
20$:	CMP #'-,R0		;Z-N
	BNE 30$
	CALL NCHK
	SUB R1,ADR1		;BACKWARD LIST
	BR 50$
30$:
	CMP #'Z,R0
	BEQ 32$
	CMP #'z,R0
	BEQ 32$
	BR 33$
32$:
	MOV #4000.,R1
	BR 40$
33$:	CALL NCHK1		;DON'T GET CHAR, ALLREADY HAVE IT
	ASR R1
	BIC #1,R1		;MUST BE EVEN
40$:	ADD R1,ADR2
	SUB R1,ADR1
50$:
	CMP ADR2,DOL		;CHECK ADR1,2 RANGE
	BLOS 55$
	MOV DOL,ADR2		;DON'T GO PAST END
55$:
	CMP ADR1,ZERO
	BHI 60$
	MOV ZERO,ADR1
	ADD #2,ADR1
60$:
	PUSH DOT
	MOV #-1,P1FLAG		;LET IT MARK WHERE WE ARE
	CMP ADR1,ADR2		;CHECK FOR NULL BUFFER
	BHI 65$			;THIS FIXES THE ZZ + Z HANG PROBLEM
	CALL PCOM1		;LIST IT
65$:	CLR P1FLAG		;BUT NO MORE
	POP DOT
	RETURN


NCHK:	CALL GETC		;GET CHAR
NCHK1:	CMP R0,#NL		;END OF LINE
	BNE 10$
	MOV #40.,R1		;USE DEFAULT
	MOV R0,PEEK		;PUT BACK TERMINATOR
	RETURN
10$:
	CMP R0,#'0		;MAKE SURE ITS A NUMBER
	BLO 20$
	CMP R0,#'9
	BHI 20$
	CALL GETNUM
	ASL R1			;TIMES 2
	RETURN
20$:
	MOV #14.,R1		;BAD NUM ERROR
	JMP ERROR
;+
; ** DEFDOT - DEFAULT TO .,.
; ** DEFALL - DEFAULT TO 1,$
; ** TDELIM - CHECK FOR LEGAL TEXT DELIMITER
; ** NONZER - DISALLOW LINE ZERO
; ** NOADDR - DISALLOW ANY ADDRESS
;
; THESE ROUTINES ARE USED TO VALIDATE THE ADDRESSES OF COMMANDS. ALL
; JUMP DIRECTLY TO ERROR ROUTINES IF THEY MUST.
;-

DEFDOT:	TST	ADR2		;IS THERE AN ADDRESS
	BNE	10$		;YES
	MOV	DOT,ADR1	;SET BOTH TO DOT
	MOV	DOT,ADR2	;
10$:	RETURN			;

TDELIM:	CALL	GETC		;GET CHARACTER
	CMP	R0,#NL		;IS IT A NEWLINE
	BEQ	10$		;YES, OK
	CMP	R0,#' 		;IS IT A BLANK
	BNE	ERR9		;NO, ERROR
10$:	RETURN			;

NOADDR:	TST	ADR2		;ANY ADDRESS
	BNE	ERR9		;YES, ERROR
	RETURN			;

	.ENABL	LSB

DEFALL:	TST	ADR2		;IS THERE AN ADDRESS
	BNE	10$		;YES
	MOV	ZERO,ADR1	;SET 1
	ADD	#2,ADR1		;
	MOV	DOL,ADR2	;SET $
	BR	10$		;

NONZER:	CALL	DEFDOT		;DEFAULT ADDRESS

10$:	CMP	ADR1,ADR2	;CHECK FOR WRAPAROUND
	BLOS	20$		;
	MOV	#5,R1		;?5
	JMP	ERROR		;
20$:	CMP	ADR1,ZERO	;LINE ZERO
	BEQ	ERR9		;YES, ERROR
	RETURN			;

	.DSABL	LSB

ERR9:	MOV	#9.,R1		;?9
	JMP	ERROR		;

;+
; ** RSTORE - STORE R.H.S. CHARACTER
; ** SSTORE - STORE RESULT CHARACTER
;
; THESE TWO SMALL ROUTINES ARE USED BY THE SUBSTITUTE COMMAND. THEY
; PROBABLY SHOULD HAVE BEEN PUT UP WITH IT.
;-

RSTORE:	CMP	R1,#LBUF2+LBS-1	;WILL IT FIT
	BHIS	ERR0		;NO
	MOVB	R0,(R1)+	;YES
	RETURN			;

SSTORE:	CMP	R3,#LBUF3+LBS-1	;WILL IT FIT
	BHIS	ERR0		;NO
	MOVB	R5,(R3)+	;YES
	RETURN			;

ERR0:	CLR	R1		;?0 IF OVERFLOW
	JMP	ERROR		;

;+
; ** SAVEFN - SAVE THE FILE NAME
;
; THIS LITTLE ROUTINE IS CALLED FROM THE R, E AND W COMMANDS TO SAVE
; THE FILE NAME (IN FN) IN THE SAVED NAME (SFN).
;
; USES:
;	R0, R1
;-

SAVEFN:	MOV	#FN,R0		;NAME
	MOV	#SFN,R1		;SAVED NAME
10$:	MOVB	(R0)+,(R1)+	;COPY
	BNE	10$		;
	RETURN			;

defd.t:		;input =r2 output r2=dot or unchanged registers
	tst r2	;skip if address already in r2
	bne 5$
	cmp r0,#nl	;must be only thing on line
	bne 5$
	mov dot,r2	;passed all tests, its a copy or move to dot
5$:	return
	.END
