;	C/;/	;/
;	C/	;/;/
;
; the following	are mpp	macros
;
;
        $MACRO TTY A B C D E ...
        ** TTY1	#@1 #@2	#@3 #@4	#@5 #@6	#@7 #@8	#@9 #@A	#@B #@C	
        $ENDM 
;
        $MACRO TTY1
        I%IN <#@1> END <<JSR PC,TTYNLL>> <TTY2 <#@1>>
        $ENDM 
;
        $MACRO TTY2
        S%SW 21
        I%IN <#@1> <R1 R2 R3 @R0 @R1 @R2 @R3>	<> <S%SW -21>
        I%SW 21	<MOV #@1,R0> <I%DF <#@1> R0 <MOV ##@1,R0>>
        CALL TTYCC
        $ENDM 
;
        $MACRO FUNCTION	set to parm3
        I%IDN	R0 <#@2> <I%ERR	<Cant use	r0 here>>
        TTY ESC	'R
        I%DF R0	<#@3>	<mov #@3,r0>
        call ttycc
        $ENDM 
;
        $MACRO CURSOR TO X,Y
        MOV #@2,-(SP)
        MOV #@3,-(SP)
        CALL CURSR2
        $ENDM 
;
;;;	$MACRO CURSOR	TO LINE	COL
;;;	I%IDN	R0 <#@2> <I%ERR	<Cant use	r0 here>>
;;;	TTY ESC	'Y
;;;	MOV #@2,R0
;;;	ADD #31.,R0
;;;	TTY R0
;;;	MOV #@3,R0
;;;	ADD #31.,R0
;;;	TTY R0
;;;	$ENDM
/
        PROGRAM	 v7. SCREEN EDIT	;just sets up op tables inside mpp
        .PSECT EDI07
        .TITLE EDI07
        .IDENT /V1/
         
        .enabl lc
        .mcall wtse$,mrkt$,dir$,callr
         
; - - -	   local macros	inside macro -11
         
         
         
        .MACRO return
        rts pc
        .ENDM 
         
        .MACRO push this
        mov this,-(sp)
        .ENDM 
         
        .MACRO pop that
        mov (sp)+,that
        .ENDM 
         
; - - -	   Global declarations
         
         
         
         
        .globl ttynll
        .globl cursl
        .globl cursr2
        .globl ceol
        .globl fixscn
        .globl bcom		;entry for	b command
        .globl bcom1		;alt entry for b command
        .globl smode		;variable	to determine screen/line mode
        .globl prescn
        .globl postscn
        .globl bottom		;the line # of	the bottom line
        .globl fpage
        .globl fdot
         
; - - -	   global data
         
smode:  .word	0		;0= not screen	mode,	<>0 = in screen	mode
         
; - - -	   local symbolics
         
        tab	=	11
        esc	=	33
        linefd	=	12
        sdel	=	123
        home	=	110
        bottom	=	24.
        insert	=	114
        delete	=	115
        ceol	=	113
        ceop	=	'J
        rightmost =	80.
        screen	=	1
        line	=	0
        blank	=	40
        lbrk	=	133	;a [
        langle	=	74	;a <
         
; - - -	   local data
         
olddot: .word	0		;previous dot value
I:      .word	0		;local	index
K:      .word	0		;local	index
flag1:  .word	0		;used by dot	checker
cursl:  .word	13.
cursc:  .word	1.
fpage:  .word	'@
fdot:   .word	'H
nocmd:  .word	0		;0= bypass the	regular	ued command
smacro: .word	0		;the a	and i commands	may be s	macros
        multadr:.word	0		;set to 0 if a	multi address cmd in process
         
         
         
mark:   mrkt$	30.,4,1
wait:   wtse$	30.
; - - -	   Entries for the pre-command and post-command	screen editor dispatcher
         
         
         
prescn:  
        clr nocmd
        call fixscn			;keep the	cursor in the right place
        IF smode = #screen
            mov	r0,-(sp)
            call @pretbl(r0)
            mov	(sp)+,r0
            IF nocmd NE	#0
                add #10,(sp)		;bump return past	the subroutine	call
            FI 
        FI 
        return 
postscn: 
        IF smode = #screen
            mov	r0,-(sp)
            call @psttbl(r0)
            CURSOR to	#bottom-2,#1
            TTY	END
            mov	(sp)+,r0
        FI 
        return 
         
; - - -	   the pre table
         
pretbl: .WORD	Apre		;APPEND
        .WORD	no.op		;B
        .WORD	Cpre		;CHANGE
        .WORD	Dpre		;DELETE
        .WORD	Epre		;EDIT
        .WORD	Fpre		;FACTS
        .WORD	Gpre		;GLOBAL
        .WORD	ERR2		;H
        .WORD	Ipre		;INSERT
        .WORD	Jpre		;JOIN
        .WORD	Kpre		;KOPY
        .WORD   NO.OP           ;L
        .WORD	Mpre		;MOVE
        .WORD   no.op           ;N
        .WORD	Opre		;OPTIONS
        .WORD	Ppre		;PRINT
        .WORD	Qpre		;QUIT
        .WORD	Rpre		;READ
        .WORD	Spre		;SUBSTITUTE
        .WORD	no.op		;T
        .WORD	upre		;U
        .WORD	Vpre		;EXCLUDE
        .WORD	Wpre		;WRITE
        .WORD	Xpre		;WRITE WITH	NEW VERSION
        .WORD	NO.OP		;Y
        .WORD	Zpre		;Z COMMAND			
         
         
         
; - - -	   the post table
         
         
psttbl: .WORD	Apst		;APPEND
        .WORD	no.op		;B
        .WORD	Cpst		;CHANGE
        .WORD	Dpst		;DELETE
        .WORD	Epst		;EDIT
        .WORD	Fpst		;FACTS
        .WORD	Gpst		;GLOBAL
        .WORD	ERR2		;H
        .WORD	Ipst		;INSERT
        .WORD	Jpst		;JOIN
        .WORD	Kpst		;KOPY
        .WORD   NO.OP           ;L
        .WORD	Mpst		;MOVE
        .WORD   no.op           ;N
        .WORD	Opst		;OPTIONS
        .WORD	Ppst		;PRINT
        .WORD	Qpst		;QUIT
        .WORD	Rpst		;READ
        .WORD	Spst		;SUBSTITUTE
        .WORD	no.op		;T
        .WORD	upst		;U
        .WORD	Vpst		;EXCLUDE
        .WORD	Wpst		;WRITE
        .WORD	Xpst		;WRITE WITH	NEW VERSION
        .WORD	NO.OP		;Y
        .WORD	Zpst		;Z COMMAND			
         
         
; - - -	   dispatched routines
         
Apre:   				;APPEND 
        mov cursl,r1			;if its not an	s	macro, clear bottom
        br app1
        Ipre=.				;INSERT
        mov cursl,r1
        dec r1
app1:   clr smacro			;assume not a macro
        call getc			;look ahead	one character
        mov r0,peek			;and put it back
        IF r0	NE #nl
            inc	smacro			;its	a	macro
            call cmultadr		;so we then check mult adresses
        ELSE 
            inc r1
            CURSOR to	R1,#1
            TTY	 esc	ceop 	;clear bottom half of screen
            CURSOR TO	R1,#1
            TTY	END
        FI 
        return 
        				;B 
Cpre:   				;CHANGE 
        IF oe	NE #0			;test option e
            jmp	spre1			;and its really	an s command
        FI 
cpre1:   
         
Dpre:   				;DELETE 
        return 
Epre:   				;EDIT 
        clr smode
        return 
Fpre:   				;FACTS 
        return 
Vpre:   				;EXCLUDE 
Gpre:   				;GLOBAL 
        clr smode			;out of screen mode
        mov #1,onum			;turn on line numbers
        return 
        				;H 
Jpre:   				;JOIN 
Kpre:   				;KOPY 
        				;L 
Mpre:   				;MOVE 
        				;N 
Opre:   				;OPTIONS 
        return 
         
         
         
         
Ppre:   				;PRINT 
        IF adr1	NE adr2			;what	mode do	we want
            clr	smode			;out	of	screen mode and	print
        ELSE 
            inc	nocmd			;we do it all
            call nonzer			;check it out
            LET	R0 = adr1 - dot		;how far is	it
            IF r0 LT #0
                neg r0
            FI 
            mov	dot,olddot		;save it
            mov	adr1,dot		;set new dot
            IF r0 GT #24.
                call bcom1		;too far, use b command
            ELSE 
                IF adr1	= olddot	;not	moving?
                    call redisp		;re display the center	line
                ELSE 
                    IF adr1 HI olddot	;which way to go
                        call upit
                    ELSE 
                        call downit	;down
                    FI 
                FI 
            FI 
        FI 
        return 
         
         
         
upit:   				;scroll up until dot reaches adr1
        mov olddot,dot
        LOOP FOR I = #1	TO #24.
            add	#2,dot
;	    dir$ #mark			;display is too slow
;	    dir$ #wait			;must	give it	some time
            call upscroll
            BREAK	IF dot HIS adr1
        NEXT I
        return 
downit: 				;scroll down until dot gets	to adr1
        mov olddot,dot			;need this again
        LOOP for I = #1	TO #24.		;for	loop safety, max=24
            sub	#2,dot			;back	a line
;	    dir$ #mark			;display is too slow
;	    dir$ #wait			;must	give it	some time
            call downscroll		;and scroll
            BREAK IF dot LOS adr1	;and check for done
        NEXT I
        return 
Qpre:   				;QUIT 
Rpre:   				;READ 
        return 
Spre:   				;SUBSTITUTE 
        IF oe	NE #0
            jmp	cpre1
        FI 
spre1:   
        call cmultadr			;check for multiple addresses
        return 
        				;T 
upre:   				;U 
Wpre:   				;WRITE 
Xpre:   				;WRITE WITH	NEW VERSION
        				;Y 
        return 
Zpre:   				;Z COMMAND			
        clr smode
no.op:  return 
         
         
         
Apst:   				;APPEND 
Ipst:   				;INSERT 
        IF smacro = #0			;if it	was a macro
            mov	dot,adr1		;it requires this
            mov	dot,adr2		;and this
            call bcom1			;re-display
        ELSE 
            jmp	spst1
        FI 
        return 
        				;B 
Cpst:   				;CHANGE 
        IF oe	NE #0
            jmp	spst1
        FI 
cpst1:   
        return 
Dpst:   				;DELETE 
        mov dot,adr1			;it requires this
        mov dot,adr2			;and this
        call bcom1
        return 
Epst:   				;EDIT 
        return 
Fpst:   				;FACTS 
        callr	sfacts			;in screen mode
Gpst:   				;GLOBAL 
        				;H 
        return 
Jpst:   				;JOIN 
        return 
Kpst:   				;KOPY 
        				;L 
Mpst:   				;MOVE 
        jmp dpst			;new	display	needed
        				;N 
Opst:   				;OPTIONS 
Ppst:   				;PRINT 
Qpst:   				;QUIT 
        return 
Rpst:   				;READ 
        jmp dpst
        return 
Spst:   				;SUBSTITUTE 
        IF oe	NE #0
            jmp	spst1
        FI 
spst1:  				;This is the sub entry
        IF multadr NE	#0		;there were multiple addresses
            jmp	dpst			;new display
        ELSE 
            call redisp			;update center-line
            call getc			;get	next char
            mov	r0,peek			;put it back
            bic	#40,r0			;make it upper	case
            IF r0 = #'P
                mov #-1,peek		;clear	peek char
            FI 
        FI 
        return 
         
        				;T 
upst:   				;U 
        call redisp
Vpst:   				;EXCLUDE 
Wpst:   				;WRITE 
Xpst:   				;WRITE WITH	NEW VERSION
        				;Y 
Zpst:   				;Z COMMAND			
        return 
         
         
; - - -	fix up the cursor if in	screen mode
fixscn:  
        IF smode = #screen
            PUSH R0
            TTY	esc 'Y '6 blank	esc ceop END	;clear bottom two lines
            POP	R0
        FI 
        return 
         
; - - -	B command processor
         
         
bcom:   				;The b command does	the BEGIN SCREEN mode
        TTY esc lbrk '? '2 'l		;out of ascii mode
;;;	PUSH R1
;;;	PUSH R0
;;;	CURSOR TO #1,#1
;;;	TTY esc	'G
;;;	mov #2,r1
;;;	LOOP FOR I = #1	to #17.
;;;	    IF I GT #9.
;;;		inc r1
;;;	    ELSE
;;;		add #8.,r1
;;;		FI
;;;	    CURSOR TO	#1,R1
;;;	    TTY	esc  'F			;set	tab
;;;	    NEXT I
;;;	TTY END
;;;	POP R0
;;;	POP R1
;;;	call setfld			;get new	field functions
bcom1:  PUSH R0				;entry to not set screen fields
        PUSH R2
        mov #screen,smode		;into screen	mode
        IF adr2	NE #0
            mov	adr2,dot		;set dot
        FI 
        LET r2 = dot - #24.		;start at	dot - 12	lines
        TTY esc 'H esc 'J END			;output an escape j -	clr page	& home
        LOOP FOR I = #1	TO #22.
            CURSOR TO	I,#1
            IF i = cursl
                call uline1
            FI 
            call get.line		;get	the input line	(our routine)
            mov	#lbuf1,r0		;its	put into lbuf1	null terminated
            call xttystr			;THE string has a nl inbedded	in it
            IF i = cursl
                call uline2
            FI 
            add	#2,r2			;go to next location
        NEXT I
        POP R2
        POP R0
        RTS PC
         
         
; - - -	 errors
         
         
err2:   mov #2,r1
        jmp error
         
; - - -	 just a	new line output	hook (non implemented)
         
         
         
ttynll: jmp ttynl
         
         
         
;+
;
; get.line - get line but range	check
;
;	r2 = line pointer (like a dot, or zero, dol etc)
;
; output lbuf1 is an asciz string which	is either the
;	 line	from the temp file or a	line with one blank
;-
get.line: 				;get line	but check	range	of dot
        PUSH R0
        clr flag1		;assume ok
        IF r2	LOS zero	;range	check it and get a blank line if bad
            inc	flag1
        FI 
         
        IF r2	HI dol		;must be higher than zero, lower or= dol
            inc	flag1
        FI 
         
        IF flag1 = #0
            mov	(r2),r0		;contents of	pointer	to line
            call getlin		;get from the	temp file
             
        ELSE 
            movb #' ,lbuf1	;simulate a blank line
            clrb lbuf1+1	;and	null terminate it
        FI 
        POP R0
        return 
upscroll:  
        LET R2 = dot + #18.
        call get.line		;get it now, makes smoother screen transition
        CURSOR to #bottom,#1		;prepare to scroll up 1 line
        TTY esc langle esc 'D esc lbrk
        TTY '? '2 'l END		;scroll up using the index command in ascii
        LET r1 = cursl 
        CURSOR to r1,#1			;redraw line dot with underlining
        LET r2 = dot 
        call get.line			;get dot
        IF lmode = #0
            call uline1			;set for underlining
            mov #lbuf1,r0
            call xttystr
            call uline2			;end underlining
        FI 
        LET r1 = cursl  - #1
        CURSOR to r1,#1			;and redo the next line
        LET r2 = dot  - #2
        call get.line
        mov #lbuf1,r0
        call xttystr
         
        LET  R2	= dot	+	#18.	;now do the bottom line
        CURSOR to #bottom-2,#1			;to the bottom line
        call get.line			;this appears at the bottom 
        mov #lbuf1,r0
        call xttystr			;and output it
        CURSOR to #bottom-1,#rightmost	;down to	our place in the sun
        TTY  esc ceop	END	;and clear a spot for	ourselves
        return 
Downscroll:  
        TTY esc home esc 'I		;scroll screen down 1 line
        LET r1 = cursl
        CURSOR to r1,#1			;redraw line dot with underlining
        mov dot,r2
        call get.line			;get dot
         
        IF lmode = #0
            call uline1			;set for underlining
            mov #lbuf1,r0
            call xttystr
            call uline2			;end underlining
        FI 
        LET r1 = cursl + #1
        CURSOR to r1,#1			;and redo the next line
        LET r2 = dot + #2
        call get.line
        mov #lbuf1,r0
        call xttystr
         
        LET  R2	= dot	-	#24.	;now do the top line
        TTY esc home			;to the top
        call get.line			;this appears at the top 
        mov #lbuf1,r0
        call xttystr			;and output it
        CURSOR to #bottom-2,#rightmost	;down to	our place in the sun
        TTY  esc ceop	END	;and clear a spot for	ourselves
        return 
         
; - - -	redisp	re display the center line
         
redisp:  
        push r0
        push r2
        CURSOR to cursl,#1		;go	there
        TTY esc	ceol END		;clear the line
        mov dot,r2
        call get.line
        mov #lbuf1,r0
        call uline1
        call xttystr
        call uline2
        pop r2
        pop r0
        return 
         
; - - -	 set default field parms
         
setfld:  
        PUSH R0
        call getcx
        IF R0	NE #nl			;by pass	if new	line
            mov	r0,fpage		;and set page	function
        FI 
         
        call getcx
        IF R0	NE #nl
            mov	r0,fdot			;set	dot function
        FI 
        POP R0
        return 
         
         
         
; - - -	 getcx
getcx:  				;get char, check for newline, correct case
        				;and clear protect bit. Make a space an '@'
        call getc			;get a char
        IF R0	NE #nl
            IF R0 = #40			;check for space
                mov #'@,r0		;and make it an '@'
            FI 
            bic	#60,r0			;map to upper	and clear protect bit
        ELSE 
            mov	r0,peek			;put	it back
        FI 
        return 
         
; - - - cmultadr check	for multiple address, set/reset	mlflag
         
         
cmultadr: 				;check for multiple	addresses
        clr multadr			;assume single address
        IF adr1	NE adr2
            inc	multadr			;note	fact
        FI 
        return 
uline1: 				;underline begin
        push r0
        TTY esc langle esc lbrk '4 'm		;into ascii mode and under line
        TTY END
        pop r0
        return 
uline2:  
        push r0
        TTY esc lbrk 'm esc lbrk 	;end under line, out of ascii
        TTY '? '2 'l END
        pop r0
        return 
;
;
; xttystr - output string, but at least one blank line
;
;
xttystr:				;do a ttystr but at least 1 char
        IFB (r0) = #nl
            push r0
            TTY blank
            pop r0
        FI 
        call ttystr
        return 
         
;+
; cursr2 - routine to output cursor movement (used by the CURSOR macro)
;
; input:        tos=return address
;               nos=y cord of cursor position (1-24.)
;               3os=x cord of cursor position (1-80.)
;       i.e. push x
;            push y
;            call cursr2
;
; output
;               the x,y cursor positioning is performed
; uses    r0
;-
         
cursr2:  
        TTY esc 'Y
        mov (sp),r0                     ; get ret address
        mov 4(sp),(sp)                  ; replace tos with x cord
        mov r0,4(sp)                    ; replace 3os with return address
        pop r0                          ; pop x into r0
        add #31.,r0                     ; convert to teleray cord's
        call ttycc                      ; output it
        pop r0                          ; pop y into r0
        add #31.,r0                     ; convert
        call ttycc                      ; output it
        rts pc
         
        .end 
