;-*-MIDAS-*-

TTYVRS==.IFNM2

OVHMTR TTY	;MISC TTY CODE

SUBTTL SPY DEVICE

;FIRST FILE NAME MUST BE TTY NUMBER (NOT CHARACTERS)

SPYO:	JUMPN D,OPNL12		;ONLY UNIT ASCII INPUT ALLOWED
	JUMPL A,OPNL11
	CAIL A,NCT
	 JRST OPNL11
	MOVE E,TIIP(A)
	MOVEM E,IOCHST-IOCHNM(R)
	MOVEI C,ISPY
	HRL C,A
	MOVEM C,(R)
	JRST POPJ1

;A HAS LH OF IOCHNM =TTY #

SPYI:	MOVE T,IOCHST-IOCHNM(R)	;POINTER TO INPUT BUFFER
	HRRZ B,TIBEP(A)
	CAIL B,(T)
	 CAILE B,TIBL(T)
	  JRST SPYIL
SPYILL:	CAMN T,TIIP(A)
	 PUSHJ P,UFLS
	CAMN T,TIBEP(A)
	 SUBI T,TIBL
	HRRM T,IOCHST-IOCHNM(R)
	ILDB W,IOCHST-IOCHNM(R)
	POPJ P,

SPYIL:	MOVE T,TIIP(A)
	MOVEM T,IOCHST-IOCHNM(R)
	JRST SPYILL

;.CALL RFNAME on a SPY channel.  A contains LH(IOCHNM) = TTY #
SPYRCH:	MOVEI B,(A)		;FN1 is TTY #
	POPJ P,			;easy!

SUBTTL STY DEVICE

;STY OPEN

;MODE BITS (LH)
;3.1=0 => INPUT   =1 => OUTPUT  (FROM PROGRAM POINT OF VIEW)
;3.2=0 => UNIT    =1 => BLOCK
;INPUT
;3.3=0 => FULL DUPLEX	=1 => HALF DUPLEX
;3.4=1 => DON'T HANG ON INPUT IOTS, INPUT -1 INSTEAD (IGNORED ON OUTPUT OPEN)
;3.5=1 => WANT TO GET %TDORS ON OUTPUT RESET.
	;BIT 3.5 NOTICED ON OUTPUT, TOO, BUT THAT'S NO FEATURE?

STTYO:	HRRZ I,USTYN(U)
	JUMPN I,STTYO3	;JUMP IF STY ALREADY OPEN
	PUSHJ P,SWTL	;LOCK STY OPEN SWITCH
	    STYOSW
	MOVE I,[-NSTTYS,,NFSTTY]
	MOVSI TT,%SSUSE
STTYO1:	TDNE TT,STYSTS-NFSTTY(I)	;SKIP ON FREE SLOT
STTYO5:	 AOBJN I,STTYO1
	JUMPGE I,OPNL6		;NO SLOTS.  GIVE DEVICE FULL
	SKIPGE TTYSTA(I)	;SKIP IF CONSOLE FREE MSG NOT TYPED.
	 SKIPE TTNTO(I)		;SKIP IF NOT OPEN.
	  JRST STTYO5
	MOVEI I,(I)		;We want to compare left half
	CAMLE I,STYMAX		;If we're limiting STY's, is this over our
	 JRST OPNL6		;  limit?  If so, give DEVICE FULL
	HRRM I,USTYN(U)		;STORE TTY NUMBER OF STY
STTYO4:	ANDI I,-1
	SETZM STYNTO-NFSTTY(I)
	SETZM STYMSK-NFSTTY(I)
	MOVSI TT,%SSUSE
	MOVEM TT,STYSTS-NFSTTY(I)	;SET IN USE BIT
	MOVSI TT,(<.BM ($TTISP)>+<.BM ($TTOSP)>)
	ANDCAM TT,TTYTYP(I)	;RESET SPEEDS TO ZERO
	PUSH P,C
	PUSHJ P,NCNSSP	;MAKE THE TTY A PRINTING TTY.
	PUSHJ P,TTYIN1	;INIT THE TTYOPT AND TTYCOM USER OPTION BITS.
	PUSHJ P,STYIR1	;FLUSH TTY'S OUTPUT BUFFER.
	PUSHJ P,STYOR1	;AND ITS INPUT BUFFER.
	PUSHJ P,LSWPOP	;UNLOCK STY OPEN SWITCH
	POP P,C
	HRRM U,STYSTS-NFSTTY(I)
	MOVE T,UTMPTR(U)	;Check out this tree
	CAIE T,SYSRCE-1		;Is this a top-level non-console tree,
	 CAIN T,SYSRCE		;or a system demon?
	  JRST STTYO3		;  Yes, don't print on console.
				;  since TELSER, etc., logs in
	MOVEI T,(I)		;Get TTY number
	HRLI T,[ASCIZ / STYOPN /]
	PUSHJ P,SGWAIT		;Ask SYSJOB to print the info
	MOVE T,JNAME(U)		;Add the JNAME to the info
	MOVEM T,SLGIV+2		;to be printed

STTYO3:	JUMPL D,[MOVSI TT,%SSOHG	;JUMP IF OPENING FOR OUTPUT
		 JRST STTYO2]
	LDB TT,[240100,,C]
	DPB TT,[400100,,STYSTS-NFSTTY(I)] .SEE %SSHDX
	DPB TT,[$TOHDX,,TTYOPT(I)]
	MOVSI TT,%SSHNG
STTYO2:	TLNE C,10
	 IORM TT,STYSTS-NFSTTY(I)
	MOVSI TT,%SSORS
	TLNE C,20
	 IORM TT,STYSTS-NFSTTY(I)
	MOVE J,R
	SUBI J,IOCHNM(U)	;CHANNEL BEING OPENED FOR INPUT ON
	MOVE J,CHNBIT(J)
	SKIPL D	;SKIP IF OUTPUT
	 IORM J,STYMSK-NFSTTY(I)
	SKIPGE D	;SKIP IF INPUT
	 IORM J,STYOMS-NFSTTY(I)
	AOS STYNTO-NFSTTY(I)
	HRLZ A,I	;LH OF IOCHNM GETS STY NUMBER
	MOVSS C
	JSP Q,OPSLC3
	    STYDUI,,STYDUO
	    STYDBI,,STYDBO


;ENTRY FOR OPEN OF PSEUDO-TTY AS SNM OR STN
STTYOA:	JUMPL I,OPNL1
	CAIL I,NSTTYS
	 JRST OPNL1
	ADDI I,NFSTTY
	PUSHJ P,SWTL
	    STYOSW
	MOVE TT,STYSTS-NFSTTY(I)	;SKIP IF IN USE
	TLNN TT,%SSUSE
	 JRST STTYO4	;OK TO OPEN IF FREE
	CAIE U,(TT)
	 JRST OPNL10	;DIFFERENT USER HAS IT OPEN
	PUSHJ P,LSWPOP
	JRST STTYO3

	JRST STTS		;STY INPUT SIOT ROUTINE.
;PSEUDO-TTY INPUT ROUTINE.  RETURNS CHAR WITHOUT PARITY BIT
STTYI:	MOVE I,A
STTYIA:	SKIPGE TTYOAC(I)	;SKIP IF ANY CHARS AVAIL (MAYBE)
	 JRST STTYI1
STTYI4:	PUSH P,C
	PUSH P,E
	CONO PI,TTYOFF
	PUSHJ P,TYPSC
	POP P,E
	POP P,C
	MOVE U,USER
	MOVE W,STYICH
	SKIPGE DBBBP
	 JRST STTYI2	;REALLY NO CHARS AVAIL
	CONO PI,TTYON
	MOVSI R,%SSONT	;FOR TTYO INT TO STYI
	JRST STTYIC	;INT CLEAR

STTYI2:	CONO PI,TTYON
STTYI1:	SKIPGE STYSTS-NFSTTY(I)
	 JRST STTYI3	;DON'T HANG
	SKIPGE TTYOAC(I)
	 PUSHJ P,UFLS
	JRST STTYIA

STTYI3:	MOVNI W,1
	TLO E,100000	.SEE INBTCH ;UNHANG BLOCK MD IOT IMMEDIATELY.
	JRST POPJ1	;UNHANG SIOT IMMEDIATELY.

;STY INPUT SIOT; GOES 1 WORD AT A TIME, WHATEVER THE USER'S BYTE SIZE.
STTS:	XCTR XRW,[SKIPG E,(C)]
	 JRST POPJ1	;RETURN AT ONCE IF NO CHARS WANTED BY USER.
	PUSH P,B	;SAVE ADDRS OF USER'S B.P. AND COUNT.
	PUSH P,C
STTSA:	SKIPGE TTYOAC(I)
	 JRST STTS4	;NO INPUT AVAILABLE.
STTS2:	UMOVE B,@-1(P)
STTS1:	XCTR XRW,[MOVES D,(B)]
;IT IS ASSUMED THAT E HAS THE # OF CHARS THE USER WANTS.
	CONO PI,TTYOFF
	MOVEM D,STYICH	;STORE THE WORD THE USER'S B.P. POINTS AT.
	LDB C,[360600,,B]
	LDB D,[300600,,B]
	IDIV C,D	;HOW MANY MORE CHARS GO IN THIS WORD?
	JUMPE C,STTS7
	PUSH P,B	;SAVE STARTING B.P. AND # CHARS FITTING IN WORD.
	HRRI B,STYICH	;SET UP TO STORE CHARS AT APPRO. PLACE IN STYICH.
	MOVEM B,DBBBP
	CAML C,E
	 MOVE C,E	;GET MIN OF # CAHRS FITTING IN WORD AND # CHARS USER WANTS.
	MOVEM C,DBBCC	;THAT'S HOW MANY CHARS WE CAN ACCEPT THIS TIME.
	MOVEM C,DBBCC1
	PUSHJ P,TYP	;FILL UP STYICH WITH CHARS, VIA DBBBP.
	POP P,B		;NOTE E HAS -<# CHARS GOBBLED>
	MOVE D,STYICH	;GET USER'S WORD, WITH CHARS STUCK IN IT.
	UMOVEM D,(B)	;STORE IT WHERE IT CAME FROM.
	XCTR XRW,[ADDB E,@(P)]	;UPDATE COUNT BY -<# CHARS OBTAINED>.
	HLL B,DBBBP	;UPDATE B.P. TO THE L.H. CORRESP. TO CHARS STORED IN STYICH.
	UMOVEM B,@-1(P)
	SKIPE DBBCC	;DID WE GET AS MANY CHARS AS WE WANTED?
	 JRST STTS3	;NO, SO EITHER RETURN OR HANG UP.
	CONO PI,TTYON
	JUMPG E,STTS7	;USER WANTS MORE CHARS => TRANSFER ANOTHER WORD.
STTS5:	MOVE U,USER
	MOVSI R,%SSONT
	SUB P,[2,,2]
	AOS (P)
	JRST STTYIC

;COME HERE DURING STY INPUT SIOT IF USER WANTS CHARS BUT THERE ARE NONE.
STTS3:	CONO PI,TTYON
STTS4:	SKIPGE STYSTS-NFSTTY(I)
	 JRST STTS5	;DON'T HANG MODE.
	SKIPGE TTYOAC(I)
	 PUSHJ P,UFLS
	JRST STTSA

STTS7:	AOS B
STTS6:	TLZ B,770000
	TLO B,440000
	JRST STTS1

;PSEUDO-TTY OUTPUT
STTYW:	MOVE I,A
	SKIPGE C
	 SKIPA A,(C)
	  UMOVE A,(C)
BSTTYW:	MOVSI T,%SSOHG	;BIT ON SAYS DONT HANG
	TDNE T,STYSTS-NFSTTY(I)
	 JRST BSTTYX	;J TO NOT HANG. CHARS MAY BE LOST
	MOVEI T,TIBS
	CAMG T,TICC(I)
	 PUSHJ P,UFLS	;HANG UNTIL ROOM IN INPUT BUFFER
BSTTYX:	CONO PI,TTYOFF
	PUSH P,I
	PUSHJ P,NTYI5
	POP P,I
	MOVE U,USER
	MOVSI R,%SSINT
STTYIC:	ANDCAM R,STYSTS-NFSTTY(I)	;CALLED BY STTYI ABOVE ALSO
	HRRZ R,UUAC(U)
	MOVE R,CHNBIT(R)
	ANDCAM R,IFPIR(U)	;FLUSH ANY OUTPUT INTERRUPT
	CONO PI,TTYON
	POPJ P,

STTBI:	JSP E,INBTCH
	JRST STTYI

STTBO:	JSP E,NBTOCH
	CAIN A,EOFCH
	 POPJ P,
	HLRZ I,(R)
	PUSH P,R
	PUSH P,D
	PUSH P,TT
	PUSH P,E
	PUSH P,C
	PUSHJ P,BSTTYW
	POP P,C
	POP P,E
	POP P,TT
	POP P,D
	POP P,R
	POPJ P,

;STY OUTPUT CLOSE.
STYOCL:	SUBI R,IOCHNM(U)
	MOVE B,CHNBIT(R)
	ANDCAM B,STYOMS-NFSTTY(A)
	JRST STYCL

;STY INPUT CLOSE
STYICL:	SUBI R,IOCHNM(U)
	MOVE B,CHNBIT(R)
	ANDCAM B,STYMSK-NFSTTY(A)
STYCL:	SOSE STYNTO-NFSTTY(A)
	 POPJ P,
STYCL1:	PUSHJ P,TTYLFC	;LEAVE COM. MODE, PUT TTY # IN I.
IFN NETP,[
	PUSHJ P,NSTYN0	;DISCONNECT ANY NET SOCKETS FROM THE STY
	 JFCL
]
	CONO PI,TTYON#200_<-APRCHN> ;LEAVE CLOCK OFF.
	SKIPGE C,TTYSTS(I)
	 JRST STYOC8	;TTY NOT IN USE.
	TLNN C,%TSCNS
	 JRST STYOC9	;OPEN AS DEVICE, NOT AS CONSOLE.
	PUSH P,U
STYOC3:	HRRZ U,C
	SKIPL C,SUPPRO(U)
	 JRST STYOC3	;NOT TOP LEVEL
	MOVE C,USER
STYC4A:	HRRZ TT,C
	SKIPL C,SUPPRO(TT)
	 JRST STYC4A
	AOS STYNTO-NFSTTY(I)	;IN CASE WE PCLSR, PREVENT JRST 4,.
	PUSH P,I
	CAME U,USER	;DON'T GET INTO LOOP AT ALOGO1
	 PUSHJ P,ALOGOUT	;TELL SYS JOB TO FLUSH THE TREE UNDER THE STY.
	POP P,I
	POP P,U
	SOS STYNTO-NFSTTY(I)
STYOC5:	PUSHJ P,STYIR1	;FLUSH TTY OUTPUT BUFFER.
STYOC9:	SETZM STYSTS-NFSTTY(I)
	CAIN I,@USTYN(U)	;IF HE'S CLOSING HIS STY:, SAY HE HAS NONE.
	 HLLZS USTYN(U)
	JRST CLKONJ

STYOC8:	SKIPGE TTYSTA(I) ;IN TRANSIENT STATE BETWEEN USAGE AND NOT?
	 JRST STYOC5	;NO, REALLY FREE, SIMPLE.
	CONO PI,CLKON
	AOS STYNTO-NFSTTY(I)
	MOVE T,I
	PUSHJ P,STYOCF
	PUSHJ P,UFLS
	MOVE A,I
	JRST STYCL

STYOCF:	SKIPGE TTYSTS(T)	;IF NOW IN USE
	 SKIPGE TTYSTA(T)	;OR COMPLETELY FREE,
	  AOS (P)		;THEN NO LONGER IN TRANSIENT STATE.
	POPJ P,

;STY OUTPUT .CALL FINISH
STYFIN:	SKIPE TICC(A)		;WAIT UNTIL CORRESPONDING INPUT BUFFER IS EMPTY
	 PUSHJ P,UFLS
	JRST POPJ1

;STY OUTPUT .CALL WHYINT
STOWHY:	MOVEI A,%WYSTO		;NULL ROUTINE FOR NOW
	JRST POPJ1

;STY INPUT .CALL WHYINT
STIWHY:	MOVEI A,%WYSTI		;NULL ROUTINE FOR NOW
	JRST POPJ1

;STY INPUT RESET. DOES TTY OUTPUT RESET, WITH THE TTY'S OWNER STOPPED.
STYIRS:	HLRZ I,(R)
STYIR1:	CONO PI,TTYOFF
	SKIPGE B,TTYSTS(I)
	 JRST STYIR2	;TTY IS FREE => NO PROBLEM.
	HRRZ A,B
	PUSHJ P,RPCLSR	;ELSE MUST MAKE SURE ITS OWNER ISN'T TYPING OUT.
	CONO PI,TTYOFF
	XOR B,TTYSTS(I)	;WE MIGHT HAVE BEEN DELAYED - HAS TTY MOVED AROUND?
	TRNN B,-1
	 JRST STYIR4	;NO; THE GUY WAS STOPPED WHILE STILL ITS OWNER.
	PUSHJ P,UPCLSR	;YES; UNSTOP GUY WE STOPPED,
	JRST STYIR1	;THEN GO STOP THE NEW OWNER.

STYIR4:	PUSH P,A	;SAVE JOB STOPPED
	PUSHJ P,STYIR2	;ACTUALLY DO THE RESET OF TTY OUTPUT
	POP P,A
	JRST UPCLSR	;THEN UNSTOP THE TTY'S OWNER

STYIR2:	SETOM TTYOAC(I)	;WE WILL NO LONGER BE LOOKING FOR TTY'S OUTPUT.
	JRST TYORS1	;DO THE TTY OUTPUT RESET AND TURN ON PI CHANNELS.

;STY OUTPUT RESET.
STYORS:	HLRZ I,(R)
STYOR1:	CONO PI,TTYOFF
	PUSHJ P,TYIRS1	;TURNS INTO TTY INPUT RESET.
	JRST TTYONJ

;STY OUTPUT STATUS - BIT 2.1 => BUFFER FULL, 2.2 => EMPTY.
STASTO:	ANDI A,77
	SKIPN B,TICC(A)
	 IORI D,1_<9+1>	;BUFFER EMPTY.
	CAIL B,TIBS-10.
	 IORI D,1_9	;ALMOST FULL.
	POPJ P,

;STY INPUT STATUS - THE SAME 2 BITS.
STASTI:	ANDI A,77
	SKIPG B,TORM(A)
	 IORI D,1_9	;FULL.
	CAIN B,TOBS
	 IORI D,1_<9+1>	;EMPTY.
	POPJ P,

;"STYGET" SYSTEM CALL. 1 ARG, A TTY SPECIFYER.
;1ST VALUE IS STYSTS WORD (RH IS JOB NUMBER OF OWNER OF STY). 0 FOR FREE STY.
;	%SSHNG AND %SSOHG BITS MAY BE INTERESTING.
;2ND VALUE IS JOB THAT OWNS CORRESP. TTY (OR -1 IF TTY FREE).
;3RD VALUE IS -1 IF TTY NOT CONSOLE; ELSE JOB NUMBER OF TOP OF TREE IN RH
;				AND BIT 4.8 SET IFF IT IS LOGGING OUT.
;				AND BIT 4.7 SET IF IT IS LOGGED IN.
;4TH VALUE BITS ARE:
;	1 IF TTY OWNER IS IN TYO WAIT
;	SIGN IF HE'S IN TYI WAIT.
;5TH VALUE BITS ARE:
;	4.9 => TTY INPUT AVAILABLE
;	4.8 => TTY OUTPUT BUFFER HAS ROOM
;6TH VALUE IS TTYSTA WORD

NSTYGT:	JSP J,ATTYCI	;DECODE A TTY-SPECIFYER IN A.
	CONO PI,CLKOFF
	SETZ A,
	MOVE TT,TTYTYP(I)
	TRNN TT,%TYSTY	;IF SPEC'D TTY ISN'T ASSOCIATED WITH A STY, IT HAS NO STYSTS WORD.
	 JRST NSTYG3
	HRRZ A,STYSTS-NFSTTY(I)
	IDIVI A,LUBLK		;NUMBER OF JOB USING THE STY.
	HLL A,STYSTS-NFSTTY(I)	;AND SOME RANDOM BITS.
NSTYG3:	SETOB B,C	;B GETS # OF JOB THAT HAS TTY, OR -1.
			;C GETS (IF TTY IS CONSOLE, JOB # OF TOP OF TRREE, ELSE -1).
	SETZB D,E		;D, E SHOULD GET 0 IF NO JOB HAS TTY.
	HRRE B,TTYSTS(I)
	JUMPL B,NSTYG1	;JUMP IF CONSOLE NOT IN USE.
	IDIVI B,LUBLK	;ELSE GET JOB NUMBER OF JOB USING IT.
	MOVE D,TTYSTS(I)
	TLNN D,%TSCNS	;TTY NOT CONSOLE => DON'T REPLACE THE -1 IN C WITH ANYTHING.
	 JRST NSTYG2
	HRRZ C,TTYSTS(I)
	SKIPL D,SUPPRO(C)	;ELSE TRACE SUPPRO'S TO TOP OF TREE.
	 JRST [	HRRZ C,D
		JRST .-1]
	MOVE TT,APRC(C)
	HLRE W,UNAME(C)
	IDIVI C,LUBLK	;GET JOB # OF TOP OF TREE.
	TLNE TT,BULGOS
	 TLO C,200000
	AOSE W
	 TLO C,100000
NSTYG2:	SETZ D,
	MOVE TT,TTYSTS(I)
	HRRZ TT,FLSINS(TT) ;WHAT VARIABLE IS FLSINS OF JOB OWNING TTY WAITING ON?
	CAIE TT,TICC(I)	;RETURN IN D SETZ IFF JOB IS IN TYI WAIT,
	 CAIN TT,TACC(I)
	  MOVSI D,(SETZ)
	CAIN TT,TORM(I)
	 MOVEI D,1	;OR 1 IF JOB IS IN TYO WAIT; ELSE 0.
NSTYG1:	SKIPE TICC(I)
	 TLO E,400000
	MOVE TT,TORM(I)
	CAIL TT,TYOWNC
	 TLO E,200000
	MOVE TT,TTYSTA(I)
	CONO PI,CLKON
	JRST POPJ1

;.CALL STLGET - GET INFO FROM SERVER TELNET

; Arg 1:  a TTY
; Val 1:  XJNAME of server telnet
; Val 2:  TRMNAM of server telnet (has sixbit name of host)
; Val 3:  SNAME of server telnet
; Val 4:  STY control bits,,STY owner idx

NSTLGT:	JSP J,ATTYCI
	SETZB A,B
	SETZB C,D
	MOVE TT,TTYTYP(I)
	TRNN TT,%TYSTY
	 JRST OPNL34
	SKIPN T,STYSTS-NFSTTY(I)	;Get STY status bits,,STY user.
	 JRST POPJ1
	MOVE A,XJNAME(T)
	MOVE B,TRMNAM(T)
	MOVE C,USYSNM(T)	
	HRRZ D,T
	IDIVI D,LUBLK		;Make it into user index.
	HLL D,T			;Stuff STY status bits in LH.
	JRST POPJ1


SUBTTL .ATTY, .DTTY - PASS CONTROL OF TTY

NATTY:	MOVE J,A		;.CALL ATTY
	JSP T,NCRUI2		;DECODE JOBSPEC BUT DON'T SET DIELOK
	 JFCL
IFN PDP6P,[
	CAIN J,-1
	 JRST OPNL34		;SORRY, I/O BUS MPXR IS NOT THAT HAIRY
]
	HRRZ B,SUPPRO(J)
	CAME B,U
	 JRST OPNL31		;NOT DIRECT INFERIOR (CAN'T MODIFY JOB)
	MOVE A,J
	JRST NATTY1

;	.ATTY USR,		OPER 11

AATTY:	HLRZ A,(R)	;A HAS INFERIOR'S USER INDEX
	HRRZ B,(R)
	SKIPL CLSTB(B) .SEE %CLSU ;SKIP IF USER OPEN ON CHANNEL
	 JRST OPNL34
NATTY1:	MOVE TT,APRC(A)
	TLNE TT,BULGOS	;REFUSE TO GIVE TTY TO A DYING JOB.
	 JRST OPNL42	;JOB GOING AWAY
	CONO PI,CLKOFF
	MOVE I,TTYTBL(U)
	JUMPL I,AATT1	;DOESNT HAVE TTY NOW
	HLLZS TTYTBL(U)
	HRLI A,%TBNOT
	IORM A,TTYTBL(U)	;NO LONGER HAS TTY.  STORE USER INDEX GIVEN TO
	PUSHJ P,AATT6	;A _ IDX OF USER TO RECEIVE TTY,
			;ALSO CHANGE ALL TTYTBL VARS THAT NEED IT.
	EXCH A,U
	PUSHJ P,AGBLT6	;TAKE TTY FROM USER IN A (ME),
			;GIVE TO USER IN U (HIM)
			;CHANGES TTY VARS AND TTSTSV VARS.
			;ALSO SETS CHANNELS-OPEN MASKS.
			;TURNS ON ALL PI CHNLS.
	EXCH A,U
	JRST POPJ1

AATT1:	TLZN I,%TBDTY	;SAY OUR INFERIOR HAD IT WHEN TAKEN
	 JRST OPNL10	;DEVICE NOT AVAILABLE, ALREADY GAVE TTY AWAY
	HRRI I,(A)
	MOVEM I,TTYTBL(U)
	PUSHJ P,AATT6	;SET UP HIS VARS
	JRST CLKOJ1

;CHANGE TTYTBL VARS OF ALL JOBS DOWN TO THE ONE GETTING THE TTY.
;RETURN IN A, T, TT THE TTYSTS, TTYST1, TTYST2 SETTINGS FOR THAT JOB.
;IF THAT JOB NEVER HAD THE TTY, INIT HIS TTSTSV VARS.
;I HAS TTY #, U HAS RUNNING JOB.
AATT6:	MOVE E,TTYTBL(A)
	MOVSI T,%TSATY	;TELL THIS GUY TTY WAS TAKEN FROM HIM & RETURNED.
	IORM T,TTSTSV+2(A)
	TLNE E,%TBDTY	;SKIP IF NOT TAKEN FROM ME
	 JRST AATT3	;GUY IT WAS TAKEN FROM (I.E. HE HADN'T GIVEN IT TO SOMEONE ELSE)
	HRRZ A,TTYTBL(A)
	JRST AATT6

AATT3:	HRRZS I		;TTY NUMBER
	HLL A,TTSTSV+2(A)
	TLZ A,%TSFRE+%TSLCZ	;CLEAR TTY NOT OPEN AND ^Z BITS
	MOVEM A,TTSTSV+2(A)	;UPDATE SAVED TTY STATUS
	POPJ P,

;SET UP TYIMSK AND TYOMSK. ARGS: TTY # IN I,
;D -> 1ST IOCHNM WORD OF USER TO SET UP FOR.
;MAKE LAST CHAR IN INPUT BFR AN ACTIVATION CHAR. TURN ON TTYCHN.
AATT8:	SETZM TYOMSK(I)
	SETZM TYIMSK(I)
	CONO PI,TTYOFF
	HRLI D,A	;INDIRECTION POINTER TO INFERIOR'S IO CHANNELS
	MOVSI A,-20	;AOBJN POINTER
AATT9:	MOVE B,@D	;GET IOCHNM IN B
	JUMPGE B,AATT10	;IF CHANNEL HAS CONSOLE BIT SET,
	ANDI B,-1
	MOVE C,CHNBIT(A)	;GET THE BIT WE MIGHT WANT TO SET.
	CAIE B,TYODN
	CAIN B,TYOBN	;IF TTY OUTPUT CHNL,
	 IORM C,TYOMSK(I)	;SET BIT IN OUTPUT MASK.
	CAIE B,TYIDN
	CAIN B,TYIBN	;IF INPUT, SET IN INPUT MASK.
	 IORM C,TYIMSK(I)
AATT10:	AOBJN A,AATT9	;TRY NEXT CHANNEL OR CONTINUE IF DONE
	JRST ATTYS1	;ALL CHRS SO FAR ARE ACTIVATION CHRS

ADTTY:			;DON'T CLOBBER R (SEE AUCL2)
SDTTY:	CONO PI,CLKOFF
	MOVE A,TTYTBL(U)
	JUMPGE A,CLKOJ1	;I ALREADY HAVE IT
	TLNE A,%TBDTY
	JRST CLKOJ1	;I ALREADY DID A .DTTY AND SO DID MY SUPERIOR

;LOOK FOR SUBJOB THAT HAS TTY, OR DOESN'T WANT TO GIVE TTY
;AWAY IF IT GETS THE TTY.
AGBLT3:	MOVE I,TTYTBL(A)
	TLNE I,%TBDTY	;REACHED A JOB THAT DIDN'T GIVE TTY AWAY
	 JRST AGBLT1	;THIS IMPLIES OUR SUPERIOR TOOK TTY AWAY.
	JUMPL I,AGBLT2	;IF THIS GUY GAVE IT AWAY THEN TRY THE ONE HE GAVE IT TO
	HRRZS A		;A HAS IDX OF TTY OWNER; TAKE TTY FROM HIM.
	PUSHJ P,RPCLSR	;TURNS CLOCK ON!
	CONO PI,CLKOFF
	SKIPGE TTYTBL(A)	;DID TTY MOVE WHILE CLOCK WAS ON?
	 JRST [PUSHJ P,UPCLSR	;IF SO, START OVER
		JRST SDTTY]
	HLLZ D,TTYTBL(A)
	TLZ D,%TBCLR		;DON'T ALTER USER-SETTABLE BITS, BUT
	TLO D,%TBNOT+%TBDTY	;TELL HIM HE HASN'T GOT TTY.
	MOVEM D,TTYTBL(A)
	AOS (P)		;THE .DTTY SHOULD SKIP.
	PUSH P,[UPCLSR]	;AFTER RESTARTING THE SUBJOB.
AGBLT6:	ANDI I,-1	;LH(TTYTBL) MAY BE NONZERO EVEN IF JOB HAS TTY!
	MOVSI D,%TCLED
	TDNE D,TTYCOM(I)	;IF OLD JOB WAS WANTING LOCAL EDITING,
	 PUSHJ P,AGBLT5		;TELL TERMINAL TO STOP IMMEDIATELY.
	ANDCAM D,TTYCOM(I)	;ASSUME NEW JOB DOES NOT WANT LOCAL EDITING
				;AND SHOULD NOT SEE RESYNCHS (TOP-S).
	MOVEI D,TTSTSV-1(A)	;SAVE CURRENT TTY STATUS IN
	PUSH D,TTYST1(I)	;USER VARS OF USER GIVING AWAY THE TTY.
	PUSH D,TTYST2(I)
	PUSH D,TTYSTS(I)
	MOVE TT,I
	IMULI TT,TPLEN*2
	MOVE D,TPVB+TPLEN(TT)
	SUB D,TCMXV(I)
	MOVNS D
	DPB D,[$TBECL,,TTYTBL(A)]
IFN N11TYS,[
	EXCH U,A	;GET USER GIVING AWAY TTY IN U
	MOVE D,TVVBN(U)	;SAVE THIS
	PUSHJ P,TVBNCL	;CLEAR OUT CURRENT GUY (MAYBE CLEARING RUN GLITCH ON SCREEN)
	MOVEM D,TVVBN(A);PASS THE BALL TO HIM
	EXCH U,A
]
;ENTRY FROM "ATTACH". GIVE TTY TO JOB W/ IDX IN U, WITHOUT
;"TAKING" IT FROM ANY JOB. USED WHEN TTY HAD BEEN FREE; JOB, DISOWNED.
AGBLT4:	HRROI D,TTSTSV+2(U)
	POP D,TTYSTS(I)	;RESTORE THE TTY STATUS OF JOB GIVING TTY TO.
	POP D,TTYST2(I)
	POP D,TTYST1(I)
	HRRM I,TTYTBL(U)	;INDICATE THAT IT HAS THE TTY
	LDB H,[$TBECL,,TTYTBL(U)]
	HRLOI D,#%TBCLR
	ANDM D,TTYTBL(U)
	PUSHJ P,ASCML1	;SET # COMMAND LINES FROM H
	MOVSI D,%PJATY
	AND D,MSKST(U)
	IORM D,PIRQC(U)
	MOVEI D,IOCHNM(U)
	PUSH P,A	;GENERATE CHNLS-OPEN MASKS, CREATE AN
	PUSHJ P,AATT8	;ACTIVATION CHAR IF NEC, TURN ON PI.
	JRST POPAJ

AGBLT2:	HRRZ A,TTYTBL(A)
	JRST AGBLT3

AGBLT1:	MOVSI A,%TBDTY	;TTY WAS TAKEN AWAY FROM US,
	IORM A,TTYTBL(U)	;WHEN GIVEN BACK WILL STOP WITH THIS JOB.
	JRST CLKOJ1

;TELL TERMINAL TO STOP DOING LOCAL EDITING IMMEDIATELY.
AGBLT5:	MOVE H,TTYOPT(I)
	TRNE H,%TP11T
	 POPJ P,	;DON'T EVEN TRY ON A TV -- TORM DOESN'T MEAN ANYTHING.
	SKIPG TORM(I)	;WAIT FOR ROOM IN OUTPUT BUFFER.
	 PUSHJ P,UFLS
	PUSH P,A
	MOVE Q,TOIP(I)
	MOVEI A,%TDNLE
	PUSHJ P,TYOOU1	;PUT CMD IN OUTPUT BFR,
	MOVEM Q,TOIP(I)
	AOSN TTYOAC(I)
	 XCT TTYST(I)	;AND TELL INT. LVL. ABOUT IT.
	JRST POPAJ

SUBTTL CNSSET, TTYSET, ETC.  .CALLS FOR TTYS

;DECODING TTY SPECIFIERS.  CALL WITH JSP,J.  MAY RETURN TO (J),
;OR POPJ AND REPORT AN ERROR.

;DECODE A TTY SPECIFIER, BUT DON'T CHECK FOR PERMISSION TO
;USE THE TTY.  ALWAYS RETURN IMMEDIATELY WITH LEGAL TTY SPECIFIER.
ATTYCI:	MOVEI Q,CPOPJ
	JRST ATTYC8

;DECODE A TTY SPECIFIER.
;IF W IS GREATER THAN ONE, DO NOT ALLOW RANDOM TTY NUMBERS.
;ALWAYS WAIT FOR PERMISSION TO OUTPUT.
;IF THE SPECIFIED TTY IS OUR CONSOLE AND OUTPUT IS BEING IGNORED,
;CLOBBER W TO ONE, SO THAT ITS PARAMETERS WILL NOT BE CHANGED (FOR SCPOS).
ATTYCW:	JSP Q,[	CAIGE W,2
		 JRST ATTYC8
		JRST ATTYC7 ]
	PUSHJ P,TTYWO2
	 MOVEI W,1
	POPJ P,

;DECODE A TTY SPEC.
;IF THERE ARE TWO OR MORE ARGS, AND IT IS OUR CONSOLE,
;WAIT UNTIL WE OWN IT, OR MAYBE INTERRUPT.
ATTYC:	CAIGE W,2
	 JRST ATTYCI
;DECODE A TTY SPEC.
;IF IT IS OUR CONSOLE, WAIT TILL WE OWN IT, OR MAYBE INTERRUPT.
ATTYC2:	MOVEI Q,TTYWC2
	JRST ATTYC7

;DECODE A TTY SPEC.
;IF IT IS OUR CONSOLE, WAIT TILL WE CAN DO INPUT,
;OR INTERRUPT IF DOING INPUT WOULD.
ATTYCR:	MOVEI Q,TTYWI2
	JRST ATTYC7

;DECODE A TTY SPEC.  SKIP IF IT REFERS TO OUR CONSOLE.
;DO NOT ALLOW RANDOM TTY NUMBERS.
ATTYCM:	MOVEI Q,[AOJA J,CPOPJ]
	JRST ATTYC7

;DECODE A TTY SPEC.  SKIP IF IT REFERS TO OUR CONSOLE.
ATTYC9:	MOVEI Q,[AOJA J,CPOPJ]
;DECODE CHNL # (IF < 400000) OR TTY # (OTHERWISE) IN A.  -1 MEANS TREE'S CONSOLE.
;IF CHNL # BAD, POPJ WITH OPNL. IF NOT STY OR TTY, POPJ WITH OPNL.
;IF OUR CONSOLE, CALL THE ROUTINE Q POINTS TO.
;THEN RETURN WITH TTY # IN I.
ATTYC8:	TDZE A,[-400000]	;IS IT A TTY NUMBER?
	 JRST ATTYC3	;YES, DECODE THAT.
;DECODE CHNL #, TTY # NOT ALLOWED.
ATTYC7:	HRRE T,A
	AOJE T,ATTYC6
	HRLI J,ATTYC5	;RETURN THERE IF NORMAL, OPEN CHANNEL
	MOVEI T,AIOCAL	;USE JOB DEVICE CHECKER
	JRST CHNDCD	;DECODE CHANNEL AND HANDLE JOB DEVICE SPECIALLY.

;CHNDCD RETURNS HERE WITH IOCHNM WORD CONTENTS IN H.
ATTYC5:	HRRZ T,H
	LDB I,[$TIIDX,,H] ;FOR EITHER TTY CHNL OR STY CHNL, GET TTY #.
	CAIN I,%TINON	;TREE HAS NO TTY => RETURN "DEVICE NOT AVAILABLE".
	 JRST OPNL10
	CAIG T,4	;TTY CHNL => GOOD.
	 JUMPG T,ATTYC4
	CAIL T,STYDUI
	CAILE T,STYDBO
	 JRST OPNL34	;NOT STY => BAD.
	JRST (J)	;STY => GOOD.

ATTYC4:	LDB T,[.BP <%TICNS,,>,H]	;GET DEVICE/CONSOLE BIT
	JUMPE T,ATTYC1			;JUMP IF IT'S A DEVICE.
	PUSHJ P,(Q)	;AWAIT TTY OR INTERRUPT
	LDB I,[$TIIDX,,(R)]
	SKIPGE T,TTYTBL(U)
	 JRST (J)	;USER DOESN'T HAVE THE TTY (^P), ERROR CHECKS DON'T APPLY
	CAIE I,(T)
	 BUG		;USER HAS TWO DIFFERENT CONSOLE TTYS
ATTYC1:	HRRZ T,TTYSTS(I)	;USER INDEX THAT HAS THIS TTY
	CAME T,U
	 BUG		;USER HAS TTY BUT TTY DOESN'T HAVE THAT USER
	JRST (J)

ATTYC3:	MOVEI I,(A)
	CAIGE I,NCT	;IS THE ARG THE # OF A REAL TTY?
	 JRST (J)	;YES, OK.
	CAIE I,377777	;SKIP IF ARG WAS -1
	 JRST OPNL1	;"NO SUCH DEVICE" ERROR.
ATTYC6:	PUSHJ P,(Q)	;"MY OWN CONSOLE" SPECIFIED; WAIT OR INTERRUPT.
	HRRZ I,TTYTBL(U);NOW GET TTY NUMBER
	CAIN I,%TINON	;TREE HAS NO TTY => RETURN "DEVICE NOT AVAILABLE".
	 JRST OPNL10
	JRST ATTYC1

;TTYSET SYSTEM CALL
;SETS TTYST1, TTYST2, TTYSTS, WHEN THE USER HAS THE TTY
;HANGS UNTIL HE GETS IT
ATTYST:	JSP J,ATTYCM	;GET TTY NUMBER IN I; SKIP IF IT'S OUR CONSOLE.
	 JRST ATTYS6
	SKIPGE TTYTBL(U)
	 JRST ATTYS5	;JUMP IF OUR CONSOLE AND WE DON'T OWN IT.
ATTYS6:	CONO PI,TTYOFF
	MOVEM B,TTYST1(I)
	MOVEM C,TTYST2(I)
	CAIGE W,4
	 JRST ATTYS0	;NO 4TH ARG => DON'T SET TTYSTS.
	TLNE D,%TSINT	;SETTING "INT ON NEXT CHAR REGARDLESS"?
	 PUSHJ P,ATTYS3	;MAYBE THE "NEXT CHAR" HAS ALREADY BEEN READ.
	HRLOI B,%TSFRE+%TSCNS+%TSLCZ+%TSHDX	;DON'T CHANGE THESE.
	TLZ D,%TSFRE+%TSCNS+%TSLCZ+%TSHDX
	ANDCMI D,-1
	ANDM B,TTYSTS(I)
	IORM D,TTYSTS(I)
ATTYS0:	AOS (P)	;MAKE ALL CHRS IN BUFFER ACTIVATION CHARS
ATTYS1:	SKIPG TICC(I)
	 JRST TTYONJ
	LDB E,TIIP(I)	;MAKE LAST CHAR AN ACTIVATION CHAR
	TRON E,%TXACT
	 AOS TACC(I)	;IF IT WASN'T ONE, IS ONE MORE ACT CHAR NOW
	DPB E,TIIP(I)
	JRST TTYONJ

ATTYS3:	SKIPE B,TINTP(I)
ATTYS4:	 CAMN B,TIIP(I)	;ANY MORE CHARS TO CHECK?
	  POPJ P,
	CAMN B,TIBEP(I)
	 SUBI B,TIBL
	ILDB E,B	;YES, CHECK THE NEXT ONE.
	TRNE E,%TXIGN	;IF IT ISN'T REALLY THERE, IT SHOULDN'T
	 JRST ATTYS4	;INTERRUPT.
	TLZ D,%TSINT	;ELSE THIS CHAR IS THE "NEXT CHAR" THAT
	TROE E,%TXINT	;SHOULD INTERRUPT REGARDLESS.
	 POPJ P,
	AOS TINTC(I)	;SO MAKE IT AN INT. CHAR IF IT ISN'T.
	DPB E,B
	MOVE B,TYIMSK(I)
	AND B,MSKST2(U)
	MOVN C,B
	AND B,C
	IORM B,IFPIR(U)
	MOVEI A,%PITYI
	TDNE A,MSKST(U)
	 IORM A,PIRQC(U)
	POPJ P,

;TTYSET WHEN WE DON'T OWN OUR CONSOLE.
ATTYS5:	MOVEM B,TTSTSV(U)
	MOVEM C,TTSTSV+1(U)
	CAIGE W,4
	 JRST POPJ1
	HRLOI B,%TSFRE+%TSCNS+%TSLCZ+%TSHDX	;DON'T CHANGE THESE.
	TLZ D,%TSFRE+%TSCNS+%TSLCZ+%TSHDX	;CHANGE ONLY CERTAIN LH BITS.
	ANDCMI D,-1
	ANDM B,TTSTSV+2(U)
	IORM D,TTSTSV+2(U)
	JRST POPJ1

;TTYGET SYSTEM CALL
;GETS TTYST1, TTYST2 AND TTYSTS WHEN THE USER HAS THE TTY
;HANGS UNTIL HE GETS IT, IF IT'S HIS CONSOLE.
;ALSO RETURNS HIS TTYTYP, TCTYP.
;THE RH OF TTYSTS AS RETURNED IS PRE-DIVIDED BY LUBLK
ATTYGT:	JSP J,ATTYC9	;GET TTY NUMBER NOW IN I; SKIP IF IT'S OUR CONSOLE.
	 CAIA
	  SKIPL TTYTBL(U)
	   JRST ATTYG1
;OUR CONSOLE AND WE DON'T CURRENTLY OWN IT.
	MOVE A,TTSTSV(U)
	MOVE B,TTSTSV+1(U)
	MOVE C,TTSTSV+2(U)
	JRST ATTYG2

;EITHER NOT OUR CONSOLE OR WE OWN IT.
ATTYG1:	MOVE A,TTYST1(I)
	MOVE B,TTYST2(I)
	HLLZ C,TTYSTS(I)
ATTYG2:	HRRZ D,TTYSTS(I) ;GET IDX OF TTY'S OWNER
	CAIE D,-1	;(BUT MAY BE NO OWNER IF WE SPECIFIED RANDOM TTY)
	 IDIVI D,LUBLK	;RETURN IN EASY-TO-DIGEST FORM.
	HRR C,D
	MOVE D,TTYOPT(I)
	TLNE D,%TOHDX	;THE %TSHDX BIT REFLECTS THE %TOHDX BIT.
	 TLO C,%TSHDX
	MOVE D,TTYTYP(I)
	MOVE E,TCTYP(I)
	JRST POPJ1

;SCML SYSTEM CALL. 1ST ARG TTY OR STY CHNL,
;2ND ARG IS DESIRED # COMMAND LINES(FOR ECHOING AT BOTTOM OF SCREEN)
;2ND ARG 0 => NO ECHO REGION.
ASCML:	JSP J,ATTYCM
	 JRST ASCML3
	SKIPL TTYTBL(U)
	 JRST ASCML3
	DPB B,[$TBECL,,TTYTBL(U)]	;IT'S OUR CONSOLE AND WE DON'T OWN IT.
	JRST POPJ1

ASCML3:	PUSH P,[TTYOJ1]
	CONO PI,TTYOFF
	MOVEI H,(B)
;I HAS TTY #, H HAS # CMD LINES, TTY CHANNEL OFF (TURNED BACK ON).
ASCML1:	MOVE TT,TCMXV(I)
	CAMN TT,[MOVE]
	 JRST [	MOVE H,TT	;PRINTING TERMINALS (INFINITE SCREEN) ARE A SPECIAL CASE
		JRST ASCML2 ]
	CAML H,TT
	 SOS H,TT
	SUB H,TCMXV(I)
	MOVMS H		;VPOS OF START OF ECHO AREA.
	CAIL H,117.
	 MOVEI H,117.	;IF TCMXV GARBAGE, AVOID GETTING GARBAGE INTO TPVP
ASCML2:	MOVE TT,I
	IMULI TT,TPLEN*2
	ADDI TT,TPLEN
	CAMN TT,TTYLPP(I) ;MAKE SURE TTY ISN'T ASSOCIATED WITH PC OF PPR
	 PUSHJ P,TYOMVC	;WHILE THE LATTER'S SIZE IS CHANGING.
	SUBI TT,TPLEN
	MOVEM H,TPVB+TPLEN(TT)
	MOVEM H,TPVP+TPLEN(TT)
	HRLM H,TPSP+TPLEN(TT)
	JRST NCNSSG

;RCPOS SYSTEM CALL. (READ CURSOR POSITION)
;1 ARG - TTY OR STY CHNL.
;1ST VALUE <ECHO VERT POS>,,<ECHO HORIZ POS>
;2ND VALUE <MAIN PRGM VERT POS>,,<MAIN PRGM HORIZ POS>
;1ST VALUE IRRELEVANT IF NO ECHO LINES.
ARCPOS:	JSP J,ATTYCW
	HRRZ B,H
	CAILE B,4
	 JRST NRCPO1
	SKIPL TTOALC(I)
	 PUSHJ P,UFLS
NRCPO1:	MOVE TT,I
	IMULI TT,TPLEN*2
	HRRZ B,TPVP+TPLEN(TT)
	SUB B,TPVB+TPLEN(TT)
	HRLZS B
	HRR B,TPHP+TPLEN(TT)
	HRLZ A,TPVP(TT)
	HRR A,TPHP(TT)
	JRST POPJ1

;SCPOS SYSTEM CALL GETS OR SETS THE SYSTEM'S IDEA OF WHERE THE TTY'S
;CURSOR IS REALLY LOCATED (AT THE M.P. SIDE OF THE OUTPUT BUFFER).
;TO BE USED AFTER OUTPUTTING IN SUPERIMAGE MODE, TO TELL THE SYSTEM
;WHAT THE CHARS ALREADY OUTPUT WILL DO TO THE TTY. MAY ALSO BE USED
;BY A STY PROGRAM LOOKING AT A SOFTWARE TTY, TO TELL THE SYSTEM HOW
;IT HAS INTERPRETED THE CURSOR-MOVING DISPLAY CODES, PROVIDED THE
;OUTPUT BUFFER IS EMPTY (AS IT WILL BE AFTER AN OUTPUT RESET).
;FOR THAT APPLICATION, A WAY TO SET TTOALC IS PROVIDED.
;3 VALUES - VPOS, HPOS AND TTOALC.
;1 ARG (TTY SPEC) => JUST READ THEM.
;2 MORE ARGS => THEY ARE NEW VPOS AND HPOS.
;A FOURTH ARG WILL SET TTOALC.
NSCPOS:	JSP J,ATTYCW
	HRRZ T,H
	CAILE T,4	;IF WE'RE HACKING A TTY CHANNEL
	 JRST NSCPO4
	SKIPL TTOALC(I)	;THEN MAYBE THE TTY WANTS TO HACK IT FIRST.
	 PUSHJ P,UFLS
NSCPO4:	SOJE W,NSCPO2
	JUMPL B,OPNL33
	JUMPL C,OPNL33
	CAIG B,118.	;DON'T ALLOW GARBAGE TO GET INTO TPVP
	 CAIGE W,2
	  JRST OPNL33	;NOT 3 ARGS??
	CAMGE B,TCMXV(I)
	 ;CAML C,TCMXH(I) 
	 CAIL C,400	;PREVIOUS LINE MESSES UP ON !-CONTINUED LINES
	  JRST OPNL33
NSCPO2:	MOVSI TT,%TCLED	;CONTROL BIT SET => SET %TCLED, ALLOWING THIS JOB TO
	SKIPE CTLBTS(U)	;READ TOP-E AND TOP-S CHARS.  NORMALLY, ITS DISCARDS THEM.
	 IORM TT,TTYCOM(I)
	CONO PI,TTYOFF
	SKIPL TT,TTYLPP(I)
	 JRST NSCPO1	;WHERE POS LIVES DEPENDS ON WHETHER TTY IS ASSOCIATED.
	HRRZ T,C
	HRL T,B		;FOR DISSOCIATED TTYS, TTYLPS HAS POS, MUST BE SET.
	CAIE W,
	 MOVEM T,TTYLPS(I)
	SETCA TT,	;MAKE SURE TT HAS THE PC PPR #, UNCOMPLEMENTED.
NSCPO1:	MOVE A,TPVP(TT)	;FOR ASSOCIATED TTY, POS LIVES IN TPVP AND TPHP OF PC PPR.
	CAIE W,
	 MOVEM B,TPVP(TT)
	MOVE B,TPHP(TT)
	CAIE W,
	 MOVEM C,TPHP(TT)
NSCPO3:	MOVE C,TTOALC(I) ;NOW GET OLD TTOALC, AND SET IT IF THERE WERE 4 ARGS.
	CAIGE W,3
	 JRST TTYOJ1
	MOVEM D,TTOALC(I)
	CONO PI,TTYON
	AOSN TTYOAC(I)	;MAY BE RESTARTING FROM ZERO ALLOCATION
	 XCT TTYST(I)
	JRST POPJ1

;CNSGET OR RSSIZE SYSTEM CALL. 1 ARG - TTY OR STY CHNL.
;RETURNS THE SAME VARS THAT CNSSET SETS, IN THE SAME ORDER.
NCNSGET:	;RETURN PERMANENT AND SEMIPERMANENT TTY INFO.
ARSSIZ:	JSP J,ATTYCI
	MOVE TT,TTYTYP(I)
	MOVE E,TTYOPT(I)
	MOVE D,TTYCOM(I)
	MOVE C,TCTYP(I)
	MOVE B,TCMXH(I)	;NOTE TCMXH IS LINEL INCLUDING THE CONTIN. COLUMN,
	MOVE A,TCMXV(I)
	MOVE I,TTYSMT(I)
	SOJA B,POPJ1

;CNSSET SYSTEM CALL.
;1ST ARG TTY OR STY CHNL. NEXT ARGS SET
;VERT SIZE, HORIZ SIZE, TCTYP, TTYCOM, TTYOPT VARS RESPECTIVELY.
;TCTYP CAN'T BE SET TO A NONSENSE VALUE, SOME TTYCOM BITS CAN'T BE SET.
;IF 2ND, 3RD OR 4TH ARG IS NEGATIVE, ITS VALUE ISNT CHANGED
NCNSSET:
	JSP J,ATTYC
	MOVE H,TT
;.CALL TTYVAR ENTERS HERE WITH B/TCMXV, C/TCMXH-1, D/TCTYP, E/TTYCOM, H/TTYOPT
;AND I/TTY#, W/6
NCNSS0:	SKIPL D		;MAKE SURE D HAS NEW VALUE OF TCTYP,
	 CAIG W,3	;WHETHER WE'RE CHANGING IT NOW OR NOT.
	  MOVE D,TCTYP(I)
	CAIL D,%TNMAX	;DON'T LET TCTYP BE SET TO ILLEGAL VALUE.
	 JRST OPNL33
	CONO PI,TTYOFF
	MOVE T,TTYTYP(I) ;DON'T LET %TPORS BE SET FOR PDP11 TV.
	TRNE T,%TY11T
	 TRZA H,%TPORS+7*%TPPCR+%TPCBS
	TRZA H,%TP11T	;%TP11T MUST REFLECT %TY11T.
	 IORI H,%TP11T
	TRNE T,%TY11T
	 JRST [	MOVEI B,37.	;DON'T ALLOW A TV TO BE CALLED ANYTHING BUT.
		MOVEI C,95.
		MOVEI D,%TNTV
		JRST NCNSS3]
	CAIN D,%TNTV	;NOT A PDP11 LINE => DON'T LET IT BE TREATED AS ONE.
	 MOVEI D,%TNDP
NCNSS3:	CAIGE W,6
	 MOVE H,TTYOPT(I)
	SKIPE D
	 TLZ H,%TORAW	;"RAW" MODE EXISTS ONLY ON PRINTING TTYS.
	SKIPGE TYMDTB(D)
	 TLZ H,%TOMVU+%TOERS ;DON'T CLAIM TO DO SOMETHING WE DON'T KNOW HOW TO DO
	MOVEI T,1
	TLNN H,%TOMVU
	 MOVEM T,TTYROL(I)	;ON PRINTING TTYS TTYROL MUST BE 1
	TRNN H,%TPCBS	;IF ^\ ISN'T TO BE HANDLED SPECIALLY, MAKE SURE ALL OF
	 SETOM TTOALC(I) ;THE FEATURES IT PROVIDES ARE IN THEIR NORMAL STATES.
	MOVEI TT,TYBN
	TRNN H,%TPCBS+%TPTEL
	 MOVEM TT,TYBPC(I)
	MOVE TT,I
	IMULI TT,TPLEN*2	;TT HAS IDX OF MAIN PC PPR OF TTY.
	XORI W,-1	;EACH OF THE INSNS AFTER THE JRST SETS ONE PARAMETER.
	CAIL W,#6	;>6 ARGS SAME AS 6 ARGS.
	 JRST NCNSS1+2(W) ;ELSE DON'T SET VARS WE DIDN'T GET ARGS FOR.
	MOVEM H,TTYOPT(I)
	PUSHJ P,NCNSSC		;SET TTYCOM
	MOVEM D,TCTYP(I)	;SET TCTYP.
	PUSHJ P,[CAIL C,3		;DON'T ALLOW SCREEN WIDTH LESS THAN 3.
		  CAIL C,377777		;DON'T ALLOW AN HPOS THAT WON'T FIT IN HALFWORD.
		   POPJ P,		;SPEC NO GOOD, IGNORE
		 JRST NCNSSH ]		;SET TCMXH.
	PUSHJ P,[CAMN B,[200000,,]	;200000,, IS SPECIAL (PRINTING TTY).
		  JRST NCNSSV
		 CAIL B,3		;DON'T ALLOW SCREEN HEIGHT LESS THAN 3.
		  CAIL B,120.		;VPOS MUST FIT IN ASCII CHARACTER, USUALLY.
		   POPJ P,		;NO GOOD, IGNORE
		 JRST NCNSSV ]		;SET TCMXV
NCNSS1:	PUSHJ P,NCNSSG	;COMPUTE TTYEPP FROM NEW SETTINGS OF TTY VARS.
	JRST TTYOJ1

;SET TTY WIDTH (NOT INCLUDING THE SPACE FOR THE "!") TO ARG IN C.
;TTY # IN I, MAIN PC PPR IDX IN TT.
NCNSSH:	ADDI C,1
	MOVEM C,TCMXH(I)
	CAMG C,TTYIHP(I) ;DON'T ALLOW TTYIHP TO HAVE ILLEGAL VALUE.
	 SETZM TTYIHP(I)
.SEE TPHE	;	MOVEM C,TPHE(TT)
.SEE TPHE	;	MOVEM C,TPHE+TPLEN(TT)
	CAMG C,TPHP(TT)
	 MOVEM C,TPHP(TT)
	CAMG C,TPHP+TPLEN(TT)
	 MOVEM C,TPHP+TPLEN(TT)
	POPJ P,

;SET TTY SCREEN HEIGHT FROM VALUE IN B.
NCNSSV:	MOVEM B,TCMXV(I)
	CAMG B,TTYIVP(I) ;DON'T ALLOW TTYIVP TO GET ILLEGAL VALUE.
	 SETZM TTYIVP(I)
.SEE TPVE	;	MOVEM B,TPVE(TT)
.SEE TPVE	;	MOVEM B,TPVE+TPLEN(TT)
	HRLM B,TPSP+TPLEN(TT)	;CLOBBER THE 2ND PC PPR TO NULL STATE.
	MOVEM B,TPVP+TPLEN(TT)
	MOVEM B,TPVB+TPLEN(TT)
	CAMG B,TPVP(TT)
	 SETZM TPVP(TT)
	HRRZS TPSP(TT)
	POPJ P,

;MAKE A TTY INTO AN ORDINARY PRINTING TTY.
;TTY # IN I; CLOBBERS TT,B,C.
NCNSSP:	SETZM TCTYP(I)
	MOVE TT,[%TOMVB+%TOOVR+%TOLWR,,%TPORS]
	MOVE B,TTYTYP(I)
	TRNN B,%TYSTY
	 IORI TT,%TPPCR
	LDB B,[$TTOSP,,B]
	CAIN B,2
	 TLC TT,%TOALT+%TOMVB+%TOLWR	;10CPS => ASSUME TELETYPE.
IFN 0,[		;THIS WOULD TURN THE MOTOR OF A CRTSTY DISPLAY ON AND OFF.
	CAIN B,5		;120CPS => ASSUME TERMINET.
	 JRST [	TRC TT,%TPPCR+5*%TPPLF
		MOVEI C,%TNTRM
		MOVEM C,TCTYP(I)
		JRST .+1 ]
];IFN 0
	MOVEM TT,TTYOPT(I)
	SETZM TTYSMT(I)		;NO GRAPHICS, NO LOCAL EDITING.
	SETOM TTOALC(I)		;%TPCBS TURNED OFF
	MOVEI TT,1		;SCROLLS A LINE AT A TIME (THIS IS
	MOVEM TT,TTYROL(I)	; MAINLY FOR THE BENEFIT OF TYIFLS)
	HRRZ TT,I
	IMULI TT,TPLEN*2
	MOVEM TT,TTYEPP(I)
	MOVEI C,71.
	CAIE B,2		;10 CPS => TELETYPE
	 MOVEI C,79.		;ANYTHING ELSE IS AT LEAST 80 WIDE
IFN 0,[
	CAIN B,5
	 MOVEI C,119.
]
	MOVSI B,(MOVE)
	PUSHJ P,NCNSSH
	JRST NCNSSV

;SET TTYEPP OF TTY # IN I, MAIN PC PPR # IN TT. CLOBBER H,TT.
;HAD BETTER ALWAYS BE CONO PI,CLKOFF HERE, OR SYSTEM MAY CRASH IN ECHOING CODE.
NCNSSG:	MOVE H,TTYOPT(I)
	TLNE H,%TOMVU	;NOT DISPLAY OR
	TLNN H,%TOERS	;ARDS-LIKE (CAN'T ERASE)
	 JRST NCNSSF	; => CAN'T HAVE ECHO AREA.
	MOVE H,TPLEN+TPVB(TT)
	CAMGE H,TCMXV(I)	;NO ECHO LINES => CAN'T USE ECHO AREA.
	 ADDI TT,TPLEN	;ELSE USE IT.
NCNSSF:	MOVEM TT,TTYEPP(I)
	POPJ P,

IFN N11TYS,[
;RE-INIT THE PARAMETERS OF A T.V. WHEN IT BECOMES FREE.
NCNSST:	HRRZ TT,I
	IMULI TT,TPLEN*2
	MOVEI B,%TNTV
	MOVEM B,TCTYP(I)
	MOVE B,[%TOMVB+%TOMVU+%TOERS+%TOSAI+%TOLWR+%TOOVR+%TOFCI+%TOLID+%TOCID,,%TP11T+%TPRSC]
	MOVEM B,TTYOPT(I)
	MOVEI B,4		;TV'S SCROLL BY 4 LINES PER GLITCH
	MOVEM B,TTYROL(I)
	MOVEI B,37.
	MOVEI C,95.
	PUSHJ P,NCNSSH
	JRST NCNSSV
];N11TYS

NCNSSC:	XOR E,TTYCOM(I) ;DON'T CHANGE TTYCOM BITS EXCEPT THESE.
	AND E,[%TCQRY+%TCRFS+%TCICO+%TCOCO,,]
	XORM E,TTYCOM(I)
	POPJ P,

TYVSRO:	JUMPL A,OPNL33	;CAN'T BE NEGATIVE
	;CAME D,%TNTV	;CAN'T SET NON-ZERO ON TVS
	 CAML A,TCMXV(I);CAN'T BE BIGGER THAN SCREEN SIZE
	  JUMPN A,OPNL33
	TLNN H,%TOMVU	;ON PRINTING TTYS, TTYROL MUST BE 1 OR GET INTO
	 CAIN A,1	; INFINITE RECURSION AT TYOLF3/TYOCLR/TYOCRL
	  CAIA
	   JRST OPNL33
	MOVEM A,TTYROL(I)
	JRST TTYOJ1

;TTYVAR SYSTEM CALL - READ AND WRITE VARIOUS TTY VARIABLES

;TABLES OF TTY VARIABLES.
;THE NEXT 3 TABLES ARE PARALLEL, IF YOU CHANGE ONE CHANGE THEM ALL.

;TTY VARIABLE NAMES.  MUST BE SORTED IN SIXBIT ORDER.

TYVTAB:	SIXBIT/HEIGHT/
	SIXBIT/IDLTIM/
	SIXBIT/ISPEED/		;IN BITS PER SECOND
	SIXBIT/OSPEED/		;IN BITS PER SECOND
	SIXBIT/SMARTS/
	SIXBIT/TCTYP/
	SIXBIT/TTYCOM/
	SIXBIT/TTYOPT/
	SIXBIT/TTYROL/
	SIXBIT/TTYSMT/
	SIXBIT/TTYTYP/
	SIXBIT/WIDTH/
LTYVTA==:.-TYVTAB
TYVTL2==.RADIX 2,CONC [.LENGTH/]\.-TYVTAB-1,/	;BASE 2 LOG-1 OF TABLE SIZE
REPEAT 1_<TYVTL2>-<.-TYVTAB-1>-1, <SETZ>-1	;PAD OUT TO POWER OF 2 SIZE

;INSTRUCTIONS TO GET VARIABLE INTO A

TYVGET:	MOVE A,TCMXV(I)
	PUSHJ P,[MOVE A,TIME ? SUB A,TTITM(I) ? POPJ P,]
	PUSHJ P,[LDB A,[$TTISP,,TTYTYP(I)] ? MOVE A,BAUDRT(A) ? POPJ P,]
	PUSHJ P,[LDB A,[$TTOSP,,TTYTYP(I)] ? MOVE A,BAUDRT(A) ? POPJ P,]
	MOVE A,TTYSMT(I)
	MOVE A,TCTYP(I)
	MOVE A,TTYCOM(I)
	MOVE A,TTYOPT(I)
	MOVE A,TTYROL(I)
	MOVE A,TTYSMT(I)
	MOVE A,TTYTYP(I)
	PUSHJ P,[MOVE A,TCMXH(I) ? SOJA A,CPOPJ]

;INSTRUCTIONS TO SET VARIABLE FROM A.  OPNL33 IF VALUE BAD.  OPNL26 IF CAN'T WRITE.
;OTHERWISE, IF GOES VIA .CALL CNSSET, MOVE A INTO APPROPRIATE AC (SEE COMMENT AT NCNSS0).
;FOR OTHER VARIABLES, JRST TO ROUTINE TO STORE A INTO VARIABLE.

TYVSET:	MOVE B,A	;HEIGHT
	JRST [SUB A,TIME ? MOVNM A,TTITM(I) ? JRST TTYOJ1] ;IDLTIM
	JRST TYSISP	;ISPEED
	JRST TYSOSP	;OSPEED
	JRST TYVSSM	;SMARTS
	MOVE D,A	;TCTYP
	MOVE E,A	;TTYCOM
	MOVE H,A	;TTYOPT
	JRST TYVSRO	;TTYROL
	JRST TYVSSM	;TTYSMT
	JRST OPNL26	;TTYTYP
	MOVE C,A	;WIDTH

TYVSSM:	MOVEM A,TTYSMT(I)
	JRST TTYOJ1

;SET SPEED.  MAYBE THIS SHOULD CHANGE IT IN HARDWARE ALSO?
TYSISP:	SKIPA B,[$TTISP,,TTYTYP(I)]
TYSOSP:	 MOVE B,[$TTOSP,,TTYTYP(I)]
	MOVEI C,17	;FIND CODE
	CAME A,BAUDRT(C)
	 SOJGE C,.-1
	JUMPL C,OPNL33	;NON-EXISTENT
	DPB C,B
	JRST TTYOJ1

;TRANSLATION FROM INTERNAL SPEED CODES TO BAUDS
BAUDRT:	0 ? 600. ? 110. ? 150.
	300. ? 1200. ? 1800. ? 2400.
	4800. ? 9600. ? 25000. ? 40000.
	50000. ? 80000. ? -1 ? -2

;CODE FOR TTYVAR SYS CALL BEGINS HERE

NTTYVA:	HRRE E,A
	JSP J,ATTYC9	;I TTY NUMBER
	 SKIPA J,[1]
	  SETO J,	;J GETS -1 IF IT'S OUR CONSOLE, 1 IF OTHER TTY CHNL.
	AOSGE E		;SKIP IF ARG WAS -1 (OWN CNSL) OR CHANNEL NUMBER
	 MOVEI J,0	;J ZERO IF TTY SPECIFIED BY NUMBER.
	PUSHJ P,VARCAL	;RETURN WITH SUITABLE STUFF IN E,D,W
	JUMPE W,NTTYV1
	JUMPE J,OPNL26	;ERR OUT IF WRITE LOCKED (SOMEONE ELSE'S TTY)
	JUMPG J,NTTYV1	;IF IT'S OUR CONSOLE, WAIT TILL WE OWN IT, OR INTERRUPT.
	PUSHJ P,TTYWC2
NTTYV1:	TLNN E,-1	;DEFAULT LH OF SIXBIT VARIABLE NAME TO 'TTY'
	 HRLI E,'TTY	;SO CALLER CAN USE IMMEDIATE ARGUMENT -- PRETTY RANDOM
	MOVEI B,0	;LOOK UP IN TABLE OF TTY VARIABLES (TYVTAB)
	REPEAT TYVTL2,[CAML E,TYVTAB+1_<TYVTL2-.RPCNT-1>(B)
	 ADDI B,1_<TYVTL2-.RPCNT-1>
	]
	CAME E,[<SETZ>-1]
	 CAME E,TYVTAB(B)
	  JRST OPNL11	;IILEGAL TTY VARIABLE NAME
	CONO PI,TTYOFF
	XCT TYVGET(B)	;GET VALUE OF VARIABLE INTO A
	JUMPE W,TTYOJ1	;RETURN IF READING
	HRRI W,A
	XCT W		;PUT NEW VALUE INTO A
	MOVE W,TYVSET(B) ;GET INSTRUCTION TO PUT A IN PROPER PLACE
	MOVE B,TCMXV(I)	;SET UP OLD VARIABLES FOR NCNSS0
	MOVE C,TCMXH(I)
	SUBI C,1
	MOVE D,TCTYP(I)
	MOVE E,TTYCOM(I)
	MOVE H,TTYOPT(I)
	XCT W		;CHANGE THE AC CONTAINING THE VARIABLE TO BE CHANGED
	MOVEI W,6	;TELL CNSSET TO CHANGE EVERYTHING
	JRST NCNSS0	;MAKE THE CHANGES, THEN TTYOJ1.

;.CALL TTYFLS
;  ARG 1 - <TTY>
;WITH CONTROL BITS 0, MARKS LAST INTERRUPT CHARACTER ITYIC'ED
; TO BE IGNORED AT MAIN PROGRAM LEVEL.
;WITH CONTROL BIT 1, DISCARDS ALL INPUT THROUGH LAST CHARACTER ITYIC'ED.
NTTYFLS:JSP J,TTYNGT
	MOVE A,CTLBTS(U)
	TRNN A,1
	 JRST NTTYF2
	CONO PI,TTYOFF
NTTYF1:	MOVE C,TIOP(I)
	CAMN C,TINTP(I)
	 JRST TTYOJ1
	PUSHJ P,TYIREM
	JRST NTTYF1

NTTYF2:	LDB A,TINTP(I)
	TRO A,%TXIGN
	DPB A,TINTP(I)
	JRST POPJ1

NTTYESC:			;SIMULATES TYPING OF ^_
	JSP J,ATTYC2		;DECODE TTY SPEC.  IF OUR CONSOLE, WAIT TILL WE CAN INPUT.
	CONO PI,TTYOFF
	HRRZ A,TTYIPC(I)
	CAIE A,TTYI
	 JRST OPNL7		;DEVICE NOT READY
	MOVEI A,TYCI
	MOVEM A,TTYIPC(I)
	JRST TTYOJ1

;WHOLINE SYSTEM CALL.
;TAKES A MANDATORY 1ST ARGUMENT SPECIFYING A TTY.
;RETURNS TWO VALUES - THE OLD SETTINGS OF WHMODE AND WHJOB
;FOR THAT TTY.
;OPTIONAL 2ND AND 3RD ARGUMENTS SET WHMODE AND WHJOB. IF THEY
;ARE PRESENT, THE RETURNED VALUES ARE THE OLD SETTINGS.
;THE CALL FAILS FOR TTY'S OTHER THAN TV'S.

NWHOLI:	JSP J,ATTYC		;DECODE THE TTY SPEC.
	MOVE H,TTYOPT(I)
IFN N11TYS,TRNN H,%TP11T	;FAIL IF NOT PDP11 TV.
	 JRST OPNL34
IFN N11TYS,[
	SKIPL TT11P		;TV PDP11 DOWN => DON'T USE IT.
	 JRST OPNL10
	CAIGE W,2		;IF THERE ARE OPTIONAL ARGS, DECODE THEM.
	 JRST NWHOL2
	CAIE B,1		;DECODE 3RD ARG ONLY IF RELEVANT.
	 JRST NWHOL2
	MOVE J,C		;IT SHOULD BE A JOB SPEC.
	CAIGE W,3
	 SETO J,		;USE -1 (SELF) AS THE DEFAULT.
	JSP T,NCRUI2
	 JFCL
	JUMPL J,OPNL34		;PDP6 IS NO GOOD.
	MOVE C,J
	IDIVI C,LUBLK		;CONVERT USER IDX TO JOB #.
NWHOL2:	ADD I,TT11HD
	ADD I,TT1111
	ADD I,TT1111
	LDB TT,[$11AD0,,1-NF11TY(I)]
	ADDI TT,TT11LO		;TT HAS PDP10 ADDR OF TTY'S WHOLINE VARS.
	CONO PI,TTYOFF
	MOVE T,WHMODE(TT)	;FIRST, GET THE CURRENT SETTINGS.
	LDB Q,[$11WD0,,WHJOB(TT)]
	CAIGE W,2
	 JRST NWHOL3
	DPB B,[$11WD0,,WHMODE(TT)] ;THEN, SET TO NEW VALUES IF REQUIRED.
	DPB C,[$11WD0,,WHJOB(TT)]
NWHOL3:	CONO PI,TTYON
	MOVE A,T		;PUT RETURN VALUES IN APPRO. ACS
	ASH A,-24
	MOVE B,Q
	JRST POPJ1
]

;TVWHER SYSTEM CALL.
;TAKES 1 ARG SPECIFYING A TTY, WHICH MUST BE A TV TTY.
;RETURNS 2 VALUES.
;1ST VALUE: THE KEYBOARD NUMBER OF THE PHYSICAL TERMINAL IN USE.
;2ND VALUE: THE NUMBER OF THE DISPLAY BUFFER IN USE ON THIS TTY.

NTVWHE:	JSP J,ATTYCI
	MOVE H,TTYOPT(I)
IFN N11TYS,	TRNN H,%TP11T
	JRST OPNL34
IFN N11TYS,[
NTVWH1:	LDB A,[$11AD0,,TT11HA]
	ADDI A,TT11LO(I)
	LDB B,[$11BY3,,1-NF11TY(A)]
	LDB A,[$11BY2,,1-NF11TY(A)]
	JRST POPJ1
]

SUBTTL .ITYIC, .LISTEN, TTY WHYINT

;.CALL ITYIC. 1 ARG, A TTY INPUT CHANNEL; 1 VALUE, THE INTERRUPT CHAR.
;FAILS IF THERE ARE NO INTERRUPT CHARACTERS.
NITYIC:	JSP J,TTYNGT
AITYI1:	SKIPG D,TINTC(I)
	 POPJ P,
	MOVE A,TINTP(I)	;SAVE SOME INFO FOR DEBUGGING
	MOVE J,TICC(I)
	MOVE C,TIIP(I)	;GET THE END OF FILLED PART OF BUFFER
AITYI2:	CAMN C,TINTP(I)	;IF OUR MOVING POINTER PASSES THERE, THERE ARE REALLY
	 BUG		;NO INT CHARS IN THE BUFFER.  BUT TINTC NON-ZERO??
	MOVE B,TINTP(I)
	CAMN B,TIBEP(I)	;WRAP AROUND AT END OF BUFFER
	 SUBI B,TIBL
	HRRM B,TINTP(I)	;ADVANCE TINTP TO NEXT CHARACTER.
	ILDB B,TINTP(I)
	TRZN B,%TXINT	;KEEP LOOKING TILL FIND NEXT INT. CHAR.
	 JRST AITYI2
	DPB B,TINTP(I)
	SOS TINTC(I)
	HLRZ R,H	;GET IOCHNM BITS IN R. UNLESS %TIFUL IS SET,
	MOVE A,B
	AOS (P)
	JRST TYINRM	;NORMALIZE PDP-11 12-BIT CHARACTERS TO 7-BIT.

;.CALL WHYINT ON TTY INPUT CHANNEL IS SIMILAR TO ITYIC
TYIWHY:	JSP J,TTYNG1
	PUSHJ P,AITYI1
	 SOS (P)	;DON'T SKIP-RETURN IF NO INTERRUPT CHARS
	MOVE B,A	;SECOND RESULT IS INTERRUPT CHARACTER
	MOVEI A,%WYTYI	;FIRST RESULT IS DEVICE CODE
	JRST POPJ1

AITYI:	SETO A,		;.ITYI   OBSOLETE.
	TDZA H,H
AITYIC:	 UMOVE A,(J)		;.ITYIC
	PUSH P,J		;TURN INTO NEW SYSTEM CALL ITYIC
	MOVE B,[SIXBIT /ITYIC/]
	MOVEM B,LSCALL(U)	;FOR JOB DEVICES' SAKE.
	MOVEI W,1
	PUSHJ P,NITYIC
	 JRST POP1J
	UMOVEM A,@(P)
	JRST POP1J1

ALISTEN:SKIPGE I,TTYTBL(U)	;.LISTEN
	 JRST ALIS1
	PUSHJ P,TYOWC
	SKIPA B,TICC(I)
ALIS1:	 SETZ B,
	MOVE A,PIRQC(U)
	TRNE A,%PIC.Z
	 JRST UDELAY
	UMOVEM B,(J)
	POPJ P,

TTYFIN:	JSP J,TTYNG1	;HERE FOR .CALL FINISH ON TTY OUTPUT CHANNEL
	PUSHJ P,TYOWC
	JRST POPJ1

NLISTE:	JSP J,TTYNGT	;HERE FOR .CALL LISTEN
	PUSHJ P,TYOWC
	MOVE A,TICC(I)
	JRST POPJ1

TTYNGT:	TRC A,-1	;RH(A)=-1 => TREE'S CONSOLE
	TRCN A,-1
	 JRST TTYNG2
	MOVEI T,AIOCAL	;OTHERWISE MUST BE CHANNEL NUMBER
	HRLI J,.+2
	JRST CHNDCD
	TLNN R,%CLSTI	;CHNDCD RETURNS CLSTB BITS IN R, IOCHNM WD CONTENTS IN H
	 JRST OPNL34
TTYNG1:	HLRZ I,H
	TRZ I,377700
	TRZE I,400000	;SKIP IF DEVICE (RATHER THAN CONSOLE)
TTYNG2:	 SKIPL I,TTYTBL(U)
	  JRST (J)
	JRST OPNL10

TYOWHY:	MOVEI A,%WYTYO	;.CALL WHYINT ON TTY OUTPUT CHANNEL
	MOVSI B,(SETZ)	;FOR NOW, JUST ASSUME REASON IS **MORE**
	JRST POPJ1

SUBTTL TTY OPEN

;LH TTY OPEN
;3.1 0 -> IN 1 -> OUT
;3.2 0 -> UNIT 1 -> BLOCK

;OUTPUT
;3.3 => IMAGE MODE (SET ALL %TGIMG BITS IN TTYST1 AND TTYST2)
;3.4 0 -> NORMAL 1 -> ECHO MODE OUTPUT (SET %TJECH, %TJPP2, %TJMOR).
;3.5 0 -> NORMAL 1 -> DISPLAYMODE, LOOK FOR ^P (SET %TJDIS).
;3.6 0 -> NORMAL 1 -> SUPER-IMAGE OUTPUT (SET %TJSIO).

;INPUT
;3.3 => IMAGE MODE (CLEAR ALL ECHO BITS IN TTYST1, TTYST2).
;3.4 => "DDT" (DON'T ECHO CR, LF, TAB)
;3.5 => CONVERT LOWER TO UPPER CASE
;3.6 => WANT 3 LINES IN ECHO AREA.

;BITS 3.4 AND 3.6 ON INPUT, AND BIT 3.3, HAVE EFFECT
;ONLY ON THE FIRST OPEN IN EITHER DIRECTION.
;(THEY ARE OBSOLETED BY THE TTYSET SYSTEM CALL)

;LH OF IOCHNM WD
;(SHOWS UP IN RH OF A ON .IOT, .CLOSE, ETC)

%TICNS==400000	;4.9 1-> CONSOLE 0 -> DEVICE. THIS BIT EXIST IN INPUT AND OUTPUT CHNLS.
%TJCNS==400000	;4.9 1-> CONSOLE 0 -> DEVICE

;OUTPUT:
%TJCP1==200000	;^P-CODE ANTICIPATION STATE.
%TJCP2==100000	; ".  0=>NORMAL, 1=> CHAR AFTER ^P, 2=> ^PH, 3=>^PV.
%TJECH==40000	;SET => ECHO MODE OUTPUT.-MODE OUTPUT (ALL CHARS OUTPUT THE
		;WAY THEY WOULD BE ECHOED)
%TJCTN==20000	;SET => DON'T DO LINE-CONTINUATION.
%TJSTP==10000	;SET => THIS CHANNEL IS HUNG IN **MORE**.
%TJDIS==4000	;SET => LOOK FOR ^P CODES.
%TJSIO==2000	;SET => SUPERIMAGE OUTPUT, NO PADDING OR CURSOR CTL.
%TJMOR==1000	;SET => DON'T DO **MORE** PROCESSING.
%TJPP2==400	;SET => USE ALTERNATE PC PPR (THE ECHO AREA)
%TJINK==200	;SET => NEXT CHAR ASSUMED TO BE 1-POSITION PRINTING.
%TJHDE==100	;SET => ACCOUTING FOR CURSOR MOTION DUE TO
		;CHAR ECHOED ON A HALF-DUPLEX TTY.

;INPUT
;3.3 => NO ECHO.
%TIECH==40000	;CAN READ EVEN IF CHAR NEEDS PI ECHOING.
%TIPEK==20000	;DON'T REMOVE CHAR FROM BUFFER.
%TIACT==4000	;SET => DON'T WAIT FOR ACTIVATION CHARACTER.
%TIINT==2000	;SET => CAN READ A CHAR EVEN IF IT IS SUPPOSED TO INTERRUPT & HASN'T YET.
%TINWT==1000	;SET => IF NO INPUT AVAILABLE, DON'T WAIT, JUST RETURN -1.
%TIFUL==400	;SET => GIVE FULL CHARACTER (SIGNIFICANT ON IMLAX, TVS)

$TIIDX==220600	;3.6-3.1 CONSOLE #, OR 77 FOR A "DISOWNED" CONSOLE TTY CHNL
;IE, ONE THAT CORRESPONDS TO NO REAL TTY. THEY EXIST ONLY IN
;TREES WITH NO TTY, IN JOBS THAT CAM FROM TREES WITH TTYS.
%TINON==77	;"TTY #" FOR A CHANNEL WITH NO REAL TTY.

;ENTRY FOR OPEN OF TTY AS DEVICE TYN OR TNM


IFN TTLPTP,[
LPTO:	MOVE J,TIME
	SUB J,LPTTIME	;"LPT" INPUTS EVERY ONCE IN A WHILE IF IT IS UP
	CAIL J,60.	;2 SECONDS
	JRST OPNL7
	SKIPA I,LPTTTY
]
TTYO:	PUSHJ P,TTYFD	;TEST FOR FILE NAME OF .FILE. (DIR)
	CAIL I,NCT
	 JRST OPNL1	;TTY NUM TOO LARGE
TTYO3C:
IFN NNVTTS,[
	.ERR Shouldn't this be using NFNVTY instead?
	CAIGE I,NOTYS+NNTYS+NNVTTS
	 CAIGE I,NOTYS+NNTYS	;SKIP ON NOVA TTY
	  JRST TTYO3A
	SKIPGE NOVATT
	 JRST OPNL10	;NOVA LINK NOT ACTIVE
TTYO3A:	CAMN I,NOVATT
	 JRST OPNL10	;CANT OPEN TTY USED AS CNHL TO NOVA
]
	MOVEI A,0	;MARK AS A DEVICE
	CONO PI,TTYOFF	;INTERLOCK WITH OTHER TTY OPENS, AND ^Z'S.
	SKIPGE TT,TTYSTS(I)	;SKIP IF TTY OPEN
	 JRST TTYO3B	;OK IF TTY NOT OPEN
	CAIE U,(TT)	;SAME USER THAT HAS IT?
	 JRST OPNL10	;TTY ALREADY OPEN AS DEVICE BY SOMEONE ELSE.
	TLNN TT,%TSCNS	;OPEN AS CONSOLE?
	 JRST TTYO8	;NO, AS DEVICE
	CONO PI,TTYON
	JRST TTYO7	;OPEN, THIS TIME AS CONSOLE.

TTYO3B:	SKIPGE TTYSTA(I) ;TTY IS FREE: IS IT IN TRANSITION TO OR FROM BEING IN USE?
	 JRST TTYO8	;OK IF NOT;
	MOVE T,I	;STYOCF TAKES TTY # IN T.
	PUSHJ P,STYOCF	;AND WAIT TILL TTY IS NO LONGER IN TRANSITION
	 PUSHJ P,UFLS
	JRST TTYO3C	;THEN TRY AGAIN TO OPEN IT.

;TTY IS AVAIL. TO OPEN AS A DEVICE.
TTYO8:	SKIPN TTNTO(I)	;IF TTY USED TO BE FREE, INIT. IT.
	 PUSHJ P,TTYINI
	MOVSI TT,%TSFRE
	ANDCAM TT,TTYSTS(I)
	JRST TTYO3

TTYFD:	PUSHJ P,FLDRCK	;SKIP IF FILE DIR BEING OPENED
	JRST TTYFD1	;FILE NAMES NOT SPECIAL
	SUB P,[1,,1]
	MOVEI J,6
	JRST LISTF7	;GO GET DIRCTORY

TTYFD1:	JUMPE W,CPOPJ	;0 IS THE ONLY DEFINED MODE FOR ANY TTY OPEN
	SUB P,[1,,1]
	JRST OPNL12

FLDRCK:	CAMN A,[SIXBIT /.FILE./]
	CAME B,[SIXBIT /(DIR)/]
	POPJ P,
	JRST POPJ1

;INIT A TTY WHEN IT CEASES TO BE FREE. (ZFLAG7 FOR TTY, TTYO8 FOR TNM)
;CHNL 3 (TTYCHN) MUST BE OFF OR IN PROGRESS.
TTYINI:	SETZM TTYST1(I)
	SETZM TTYST2(I)
	MOVSI J,%TACFM	;TTY NEEDS A CONSOLE FREE MESSAGE.
	ANDCAM J,TTYSTA(I)
	MOVE J,TTYTYP(I)
	TRNN J,%TYSTY	;EXCEPT ON STY TTYS,
	 PUSHJ P,TTYIN1	;INIT THE USER OPTIONS IN TTYOPT, TTYCOM.
	MOVE J,TTYOPT(I)
	HRLOI H,%TSFRE	;INITIALIZE TTYSTS FROM TTYOPT
	TLNE J,%TOROL
	 TLO H,%TSROL
	TLNN J,%TOMOR	;NOTE %TOMOR SAYS DO **MORE** PROC,
	 TLO H,%TSMOR	;%TSMOR SAYS INHIBIT **MORE** PROC.
	TLNE J,%TOSA1
	 TLO H,%TSSAI
	MOVEM H,TTYSTS(I)
	HRRZ TT,I
	IMULI TT,TPLEN*2
	SETZM TPFLAG(TT)
	SETZM TPFLAG+TPLEN(TT)
	SETZ H,		;START OUT WITH NO ECHO LINES.
	JRST ASCML1

;INIT A FEW BITS IN TTYOPT, TTYCOM THAT ARE CONSIDERED USER OPTIONS.
;NORMALLY DONE WHENEVER A TTY BECOMES IN USE, BUT ON STY TTY'S
;DONE ONLY WHEN THE STY IS INITIALIZED (SO STY-USER CAN SET THESE OPTIONS).
TTYIN1:	MOVE J,TTYCOM(I)
	TLZ J,%TCRFS+%TCQRY+%TCOCO+%TCICO
	MOVEM J,TTYCOM(I)
	MOVE J,TTYOPT(I)	;INIT SOME TTYOPT BITS.
	TLZ J,%TOUSR
	TRZ J,%TPUSR
	TLO J,%TOMOR		;DO **MORE**
	HLLM J,TTYOPT(I)
	POPJ P,

;TELETYPE OPEN ROUTINES

;ENTRY FOR OPEN OF "TTY" AS A CONSOLE

TTYO1:	PUSHJ P,TTYFD	;TEST FOR FILE NAME OF .FILE. (DIR)
TTYO7:	MOVE I,TTYTBL(U)
	JUMPGE I,TTYO2	;JUMP IF HAS TTY NOW
	TLNE I,%TBWAT
	 JRST TTYO2A
	TLNN I,%TBNVR	;IF I SHOULD FAIL IF TRY TO OPEN TTY WHEN DON'T HAVE IT,
	 TLNN I,%TBDTY	;OR IF I HAVE DONE A .ATTY,
	  JRST OPNL10	;THE OPEN SHOULD FAIL.
TTYO2A:	PCLT
	SKIPGE TTYTBL(U)
	 PUSHJ P,UFLS	;HANG UNTIL HAS TTY
	MOVE I,TTYTBL(U)
TTYO2:	HRRZS I	;TTY NUMBER
	CAIL I,NCT
	 JRST 4,OPNL1	;TTY NUM TOO LARGE
	MOVSI A,%TICNS	;SAY TTY CHNL WILL BE OPEN AS CONSOLE.
	CONO PI,TTYOFF
TTYO3:	HRLZI J,(D)	;SET IOCHNM BITS (IN A) FROM OPEN MODE.
	LSH J,1
	TLZ J,700077	;BUT DON'T USE PARTS OF OPEN WD USED FOR OTHER THINGS.
	IOR A,J
IFN TTLPTP,[
	CAMN I,LPTTTY	;SKIP IF OT TTY
	HRRZM U,LPTUSR
]
	DPB I,[$TIIDX,,A]	;LH OF A WILL BE STORED IN LH OF IOCHNM WORD
	HRRZ TT,UUAC(U)	;TT HAS CHNL # BEING OPENED.
	JUMPGE D,TTYO4	;J IF INPUT OPEN.
	TRNE D,20
	 TLO A,%TJSIO	;SUPER IMAGE OUT.
	TRNE D,4
	 TLO A,%TJECH+%TJPP2+%TJMOR	;ECHO OUTPUT
	TRNE D,10
	 TLO A,%TJDIS	;DISPLAY OUTPUT MODE.
	MOVE J,TYOMSK(I)
	IOR J,CHNBIT(TT)	;UPDATE CHANNELS-OPEN MASK
	EXCH J,TYOMSK(I)	;FOR THE NEW OUTPUT CHANNEL.
	JUMPN J,TTYO5	;FOR 1ST OUTPUT OPEN, INIT TTYST1,2.
	MOVE J,[101010,,101010]
	IORM J,TTYST1(I)
	IORM J,TTYST2(I)	;SET ALL THE OUTPUT-IN-IMAGE-MODE BITS.
	TRNN D,2
	 ANDCAM J,TTYST1(I)	;IF NOT IMAGE, CLEAR THEM.
	TRNN D,2
	 ANDCAM J,TTYST2(I)
	JRST TTYO5

TTYO4:	MOVE J,TYIMSK(I)
	IOR J,CHNBIT(TT)	;UPDATE INPUT-CHNLS-OPEN MASK
	EXCH J,TYIMSK(I)	;FOR NEWLY OPENED INPUT CHANNEL.
	JUMPN J,TTYO5	;THE 1ST INPUT CHNL OPEN, INIT ECHO BITS...
	MOVEI H,0	;INPUT
	TRNE D,20
	 MOVEI H,3	;# COMMAND LINES
	PUSHJ P,ASCML1
	MOVE J,TTYST1(I)
	AND J,[101010,,101010]	;SAVE IMAGE MODE OUTPUT BITS
	TRNN D,2	;SKIP ON IMAGE MODE INPUT
	 IOR J,[202020,,202020]	;ASCII MODE INPUT
	IOR J,[030303,,030303]	;ENABLE INTERRUPT AND ACTIVATE ON ANY CHARACTER
	MOVEM J,TTYST1(I)	;STORE BACK
	MOVE J,TTYST2(I)
	AND J,[101010,,101010]	;SAVE IMAGE MODE OUTPUT BITS
	TRNN D,2	;SKIP ON IMAGE MODE INPUT
	 IOR J,[202020,,200020]	;SAY ALL CHARS EXCEPT RUBOUT SHOULD ECHO.
	TRNE D,4	;SKIP ON NOT DDT MODE
	 ANDCM J,[006000,,606000]	;DDT MODE
	IOR J,[030303,,030303]	;ENABLE INTERRUPT AND ACTIVATE ON ANY CHARACTER
	MOVEM J,TTYST2(I)	;STORE BACK
TTYO5:	HRRM U,TTYSTS(I)
	AOS TTNTO(I)	;INCREMENT NUMBER OF CHNLS THIS TTY OPEN ON.
	CONO PI,TTYON
	MOVSS C
	JSP Q,OPSLC3	;SET UP IO CHNM WORD AND RETURN
	TYIDN,,TYODN
	TYIBN,,TYOBN

SUBTTL WAITING FOR ACCESS TO TTY

;HERE WHEN WANT TO DO TTY INPUT, TO CHECK FOR PERMISSION.
TTYWI:	HLRZ I,(R)
	ANDI I,%TICNS+(.BM $TIIDX)
	TRZN I,%TICNS	;CLEAR AND CHECK CONSOLE/DEVICE BIT
	 POPJ P,	;RETURN RIGHT AWAY IF DEVICE
;CALL FROM ATTYCR.
TTYWI2:	MOVE T,TTYTBL(U)
	TLNN T,%TBNOT	;RETURN RIGHT AWAY IF WE OWN THE TTY.
	 POPJ P,
	TLNE T,%TBIIN	;ELSE INTERRUPT IF %TBIIN IS SET.
	 JRST TTYLOS
TTYWC3:	TLC T,%TBINT	;ELSE INTERRUPT IF %TBINT IS SET AND NOT %TBWAT.
	TLNN T,%TBINT+%TBWAT
	 JRST TTYLOS
	PCLT
	SKIPGE TTYTBL(U)
	 PUSHJ P,UFLS	;WAIT TILL HAS TTY (CANT HAVE TTY IF DISOWNED)
	POPJ P,

;CALL FROM ATTYC, ATTYC2.  WAIT TILL WE OWN THE TTY.
TTYWC2:	MOVE T,TTYTBL(U)
	TLNN T,%TBNOT	;RETURN RIGHT AWAY IF WE OWN THE TTY.
	 POPJ P,
	JRST TTYWC3

;HERE WHEN WANT TO DO A TTY RESET.
;SKIP IF THE RESET SHOULD REALLY BE DONE.
TTYWR:	HLRZ I,(R)
	ANDI I,%TICNS+(.BM $TIIDX)
	TRZN I,%TICNS	;CLEAR AND CHECK CONSOLE/DEVICE BIT
	 JRST POPJ1	;RETURN YES IF DEVICE
	MOVE T,TTYTBL(U)
	TLNN T,%TBNOT	;RETURN YES IF WE OWN THE TTY.
	 JRST POPJ1
	POPJ P,		;OTHERWISE IGNORE THE RESET.

;HERE TO WAIT FOR OUTPUT PERMISSION FOR TTY
;RETURN WITHOUT SKIP IF THE OUTPUT SHOULD BE THROWN AWAY
;AND REPORTED TO THE USER AS DONE.
TTYWO:	HLRZ I,(R)
	ANDI I,%TICNS+(.BM $TIIDX)
	TRZN I,%TICNS
	 JRST POPJ1	;ALWAYS HAVE PERMISSION IF TTY IS A DEVICE.
;CALL FROM ATTYC, ETC.
TTYWO2:	MOVE A,U
	HRRZ T,I
	CAIN T,%TINON	;NEVER HAVE PERMISSION FOR CONSOLE IF WE'RE DISOWNED.
	 JRST TTYWO1
	MOVE T,TTYTBL(U)	;WE HAVE OUTPUT PERMISSION IFF ALL OUR SUPERIORS
				;HAVE PERMISSION AND WE HAVE %TBOUT
				;AND THE TREE HAS A TTY.
;THE NEXT INSN IS TEMPORARY, UNTIL DDT ETC. ARE CHANGED TO WIN FULLY.
TTYWO3:	JUMPGE T,TTYWO4		;IF WE HAVE THE TTY, WE CAN TYPE ON IT.
	SKIPGE SUPPRO(A)	;ALL OK TO TOP OF TREE => SEE IF TREE HAS A TTY.
	 JRST TTYWO4
	TLNN T,%TBOUT		;NOT AT TREE TOP => DOES THIS JOB HAVE PERMISSION
	 JRST TTYWO1		;FROM ITS SUPERIOR?
	MOVE A,SUPPRO(A)	;AND IS THE SUPERIOR ALLOWING ANY INFERIORS PERMISSION?
	MOVE T,TTYTBL(A)
	TLNE T,%TBINF		;SUPERIOR SAYS WE'RE OK => SEE IF SUPERIOR HAS PERMISSION.
	 JRST TTYWO3
TTYWO1:	MOVE T,TTYTBL(U)	;HERE IF WE DON'T HAVE PERMISSION.
	TLNE T,%TBOIG		;IF OUTPUT IS TO BE IGNORED,
	 POPJ P,		;TELL OUR CALLER TO THROW IT AWAY, RIGHT NOW.
	TLNE T,%TBWAT+%TBOUT
	 JRST TTYWO6
	TLNE T,%TBINT
	 JRST TTYLOS
	TLNE T,%TBNVR+%TBDTY
	 JUMPL I,[ SUB P,[1,,1] ? JRST OPNL10 ]
TTYWO6:	MOVE T,TTYTBL(A)	;ELSE MUST WAIT.  WAIT FOR A CHANGE IN THE
	CAMN T,TTYTBL(A)	;TTYTBL OF THE SUPERIOR DENYING US PERMISSION.
	 PUSHJ P,UFLS
	JRST TTYWO		;NOW RE-CHECK EVERYTHING.

;WE HAVE PERMISSION, BUT MAYBE WAIT ANYWAY TO AVOID MIXING JOBS' OUTPUT.
TTYWO4:	SKIPGE TTYTBL(U)	;NO NEED TO WAIT IF WE OWN THE TTY
	 CAMN U,TTYLJB(I)	;OR WE WERE LAST JOB TO USE IT.
	  JRST TTYWO5
	MOVEI T,TOBS		;ELSE WAIT FOR BUFFER TO BE EMPTY
	CAMN T,TORM(I)
	 JRST TTYWO5
	CAME T,TORM(I)
	 PUSHJ P,UFLS
	JRST TTYWO		;RECHECK EVERYTHING, SINCE WE MAY HAVE LOST PERMISSION.

;WE ARE ALLOWED TO OUTPUT RIGHT AWAY.
TTYWO5:	MOVEM U,TTYLJB(I)	;MAKE SURE WE DON'T HAVE TO WAIT AGAIN.
	JRST POPJ1

;TURN TTY OFF, THEN WAIT UNTIL EITHER TTY ISN'T IN COM MODE OR
;ONE OF THE BITS IN T IS SET IN TTYCOM(I).
TTYCMW:	CONO PI,TTYOFF
	TDNN T,TTYCOM(I)
	 SKIPL TTYCOM(I)
	  POPJ P,
	SKIPN USER
	 POPJ P,	;SYS JOB TRYING TO HACK
	HRR T,I		;WAIT UNTIL NOT COM MODE OR IN COM MODE BUT ONE OR MORE BITS IN LH OF T
	PUSHJ P,LWAIT1	;COME ON.  WAIT UNTIL OUT OF COM MODE WITH UTCOFF
	    PUSHJ P,TTYSCM
	POPJ P,

TTYSCM:	SKIPL TTYCOM(T)
	 JRST POPJ1	;NOT COM MODE
	PUSH P,A
	HLLZ A,TTYCOM(T)
	TDNE A,T
	 AOS -1(P)	;MASKED BIT(S) ON
	POP P,A
	POPJ P,


;ECHOIN SYSTEM CALL.  ASK FOR ECHOING OF CERTAIN CHARACTERS
;UNTIL A BREAK CONDITION OCCURS.
;A BREAK CONDITION IS WHEN EITHER A NON-ECHOED CHARACTER IS TYPED IN
;OR A CERTAIN NUMBER OF CHARACTERS HAVE BEEN TYPED IN.
;CHARACTERS ECHOED BY THE ECHOIN ARE STORED INTO THE USER'S
;MEMORY BY THE INTERRUPT LEVEL.  IF THE NECESSARY AREAS OF MEMORY
;ARE SWAPPED OUT, THAT CONSTITUTES A BREAK CONDITION.

;THE BREAK TABLE IS 128 BITS (DIVIDED INTO 4 WORDS THE LOW 4 BITS OF EACH UNUSED)
;ONE BIT FOR EACH ASCII CHARACTER.  A 1 INDICATES A CHARACTER THAT
;IS A BREAK CONDITION.  A 0 INDICATES A CHARACTER THAT CAN BE ECHOED.
;A CHARACTER WITH THE CONTROL OR META BIT IS ALWAYS A BREAK.

;ARG 1	TTY INPUT CHANNEL
;ARG 2  B.P. TO WHERE IN USER'S MEMORY TO STORE CHARACTERS.
;ARG 3	NUMBER OF CHARACTERS TO ALLOW
;ARG 4	ADDRESS OF BREAK TABLE.
;ARG 5	ADDRESS OF BLOCK OF COUNTERS TO BE INCREMENTED OR DECREMENTED FOR EACH CHARACTER.
;	IF THE ADDRESS IS ZERO, ALL THIS IS OMITTED.
;	THE BLOCK HAS SEVEN WORDS.
;	  THE FIRST TWO WORDS ARE LEFT ALONE.
;	  THE NEXT FOUR ARE INCREMENTED.
;	  THE SEVENTH IS DECREMENTED.

;THE WORDS OF THE BREAK TABLE RESIDE IN ACS Q, J, R AND W.
;SIMILARLY, THE ADDRESS OF THE COUNT RESIDES IN AC C,
;THE ADDRESS OF THE BYTE POINTER IN B,
;AND THE ADDRESS OF THE BLOCK OF COUNTERS IN E.
;THEY ARE LOOKED AT BY THE INTERRUPT LEVEL,
;WHICH KNOWS THAT THE PROGRAM IS EXECUTING AN ECHOIN
;BY THE FACT THAT THE PC IS NECHO1.  IT IS IMPORTANT THAT WE
;NOT LOCK ANY SWITCHES SO THAT SWAPPING OUT A PAGE WON'T PCLSR
;US UNTIL WE ARE AWAKENED BY THE INTERRUPT LEVEL WHEN IT SEES
;THAT THE PAGES IT NEEDS ARE NOT IN CORE.

NECHOIN:
	JSP J,ATTYCR		;DECODE CHANNEL.  GET TTY NUMBER IN I.
	XCTR XRW,[MOVES A,(C)]	;MAKE SURE COUNT IS IN CORE AND WRITABLE.
	JUMPLE A,POPJ1		;IF WANT ZERO OR FEWER CHARACTERS, RETURN IMMEDIATELY.
	XCTR XRW,[MOVES A,(B)]	;MAKE SURE BYTE POINTER IS IN CORE AND WRITABLE.
	IBP A			;MAKE SURE BYTE BUFFER IS IN CORE AND WRITABLE.
	XCTR XRW,[MOVES (A)]	; (NO LOSSAGE IF IT ISN'T, BUT MIGHT AS WELL SWAP IT IN NOW.)
	XCTR XRW,[MOVES (E)]	;MAKE SURE BLOCK OF COUNTERS IS IN CORE AND WRITABLE.
	XCTR XRW,[MOVES 6(E)]
	UMOVE Q,(D)		;LOAD BREAK TABLE WORDS INTO Q, J, R, W.
	UMOVE J,1(D)
	UMOVE R,2(D)
	UMOVE W,3(D)
	SKIPE TICC(I)		;IF TYPE-AHEAD AVAILABLE, WE CAN'T DO ANYTHING.
	 JRST POPJ1
	SKIPG TACC(I)		;WAIT FOR AN ACTIVATION (PROBABLY NON-ECHOED) CHARACTER.
	 PUSHJ P,TYIFL2		;CALL TYIFL2 INSTEAD OF UFLS TO PREVENT IMPENDING **MORE**.
NECHO1:	JRST POPJ1		;THE JOB IS INSIDE AN ECHOIN IF ITS PC IS HERE.

SUBTTL TTY INPUT IOT

;BLOCK MODE INPUT IOT.
TTYBI:	JSP E,INBTCH

;UNIT MODE INPUT IOT.
;R HAS THE ADDRESS OF THE IOCHNM WORD.
;VALUE RETURNED IN W.
TYI:	PUSHJ P,TTYWI	;WAIT FOR THE TTY IF ITS A CONSOLE.  TTY NUMBER IN I
	HLRZ R,(R)	;GET IOCHNM WORD FLAGS, MODIFIED BY CTL BITS
	XOR R,CTLBTS(U)	;R HAS CHANNEL FLAGS
	PUSH P,E
	PUSHJ P,TYI0	;GET THE CHAR IN D.
	POP P,E
	JUMPL D,UNIEOF	;TYI0 RETURN -1 => DON'T FLUSH THE SIGN BIT, AND TERMINATE BLOCK IOT.
	ANDI D,%TXPIE+%TXMPE+%TXECI+%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC
	CAIN A,^C
	 AOS (P)	;EOF, SKIP RETURN
	MOVE W,D
	POPJ P,

;ASSUMING I HAS TTY NUMBER AND R HAS IOCHNM BITS.
;READ A CHARACTER FROM THE TERMINAL AND RETURN IT IN D.
TYI0:	MOVE D,TTYTYP(I)
	TRNN D,%TYSTY	;SKIP IF TTY IS ALTER EGO OF STY.
	 JRST TYI1B1
	MOVSI D,%SSINT
	TDNE D,STYSTS-NFSTTY(I)
	 JRST TYI1B1	;HAVE ALREADY GIVEN INT
	SKIPE TICC(I)
	 JRST TYI1B1
	IORB D,STYSTS-NFSTTY(I)
	MOVE TT,STYOMS-NFSTTY(I)	;CHANNELS OPEN FOR OUTPUT ON
	AND TT,MSKST2(D)
	MOVN B,TT
	AND TT,B
	IORM TT,IFPIR(D)	;GIVE INT ON LOWEST-NUMBERED CHANNEL.
	JRST TYI1B1

TYI1B1:	TRNE R,%TIACT
	 JRST TYI1B	;GOBBLE NEXT CHR REGARDLESS OF ACTIVATION
	MOVE TT,TTYSTS(I)
	TLNE TT,%TSACT
	 JRST TYI1B
	PCLT
	SKIPG TACC(I)
	 PUSHJ P,TYIFLS
TYI1B:	PCLT	;WAIT TILL THERE'S A CHAR TO READ.
	SKIPG TICC(I)
	 PUSHJ P,TYIFLS
	CONO PI,CLKOFF	;PREVENT ECHOING WHILE WE'RE MESSING WITH POINTERS.
	MOVE B,TIOP(I)
	MOVE T,B
	CAMN B,TIBEP(I)
	SUBI B,TIBL
	ILDB D,B
	SKIPN TT,TICC(I)	;CHECK FOR CHAR FLUSHED BY ECHO BEFORE WE TURNED OFF CLOCK.
	 JRST TYI1A
	TRNN D,%TXIGN
	 JRST TYI1
	TRNN R,%TIECH
	 TRNN D,%TXPIE
	  JRST [ PUSHJ P,TYIREM
		 JRST TYI1A ]
	PCLT
	CAMN T,TIOP(I)	;WAIT FOR ECHOING TO FLUSH THIS CHAR FROM BUFFER,
	 PUSHJ P,UFLS
TYI1A:	CONO PI,CLKON	;ALLOW ECHOING.
	JRST TYI1B1	;THEN TRY AGAIN TO READ CHAR.

TYI1:	CONO PI,CLKON	;ALLOW ECHOING.
	MOVE T,TTYSTS(I)
	TLNN T,%TSNOE	;ECHOING BEING DEFERRED OR
	TRNE R,%TIECH	;THIS CHANNEL NEEDN'T WAIT FOR ECHO
	 ANDCMI D,%TXPIE ;=> DON'T.
	SKIPE PICLR(U)	;AT INT LVL IN USER PRGM OR
	TRNE R,%TIINT	;THIS CHNL NEEDN'T WAIT FOR CHAR TO INTERRUPT
	 ANDCMI D,%TXINT ;=> DON'T WAIT FOR THAT.
	MOVEI T,(D)
	ANDI T,%TXINT+%TXPIE ;WAIT FOR THESE BITS TO CLEAR.
	TRNE T,%TXINT	;IF ABOUT TO WAIT FOR %TXINT TO CLEAR,
	 PUSHJ P,TYIIWT	;TAKE CARE OF SEVERAL POSSIBLE SCREWS - MAY SET T.
	LDB D,[360600,,B]
	LSH T,(D)
	PCLT
	TDNE T,@B
	 PUSHJ P,UFLS	;HANG UNTIL PI ECHO BIT FOR THIS CHAR IS TURNED OFF
	LDB D,B		;GET CHARACTER
	TRNN R,%TIECH	;IF WE AREN'T SUPPRESSING ECHOING,
	TRNN D,%TXMPE	;AND M.P. ECHOING NEEDED BUT NOT YET DONE,
	 JRST TYI2
	MOVE T,TTYSTS(I)
	TLNE T,%TSNOE
	 JRST TYI2
	JRST TYIMP1	;GO DO IT.

TYIMP1:	PUSH P,R	;DO MAIN-PRGM ECHO IF NECESSARY.
	PUSH P,C
	PUSHJ P,[MOVEI J,1(P)
		ADD P,[3,,3]
		HRRZM P,(P)
		MOVE TT,TTYEPP(I)
		PUSHJ P,NULSET	;NO LOSSET OF IOCHNM
		JSP E,TYOSE1
		MOVEI R,%TJECH+%TJMOR
		MOVE A,D
		ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC
		JRST TYO6]
	POP P,C
	POP P,R
	CONO PI,TTYOFF
	MOVE B,TIOP(I)
	CAMN B,TIBEP(I)
	 SUBI B,TIBL
	ILDB D,B
	TRZ D,%TXMPE	;M.P. ECHOING NO LONGER PENDING FOR THIS CHAR.
	DPB D,B
	CONO PI,TTYON
TYI2:	TRNN R,%TIPEK	;DON'T REMOVE IF CHNL SAYS DON'T.
	 PUSHJ P,TYIREM ;FINALLY REMOVE CHAR FROM BUFFER.
	MOVE TT,TTYCOM(I)
	TLNE TT,%TCLED		;DOES THIS JOB WANT TO SEE LOCAL EDITING PROTOCOL
	 JRST TYI2Z		;REPLIES, ETC.?
	MOVE TT,D
	ANDI TT,%TXTOP+%TXASC	;NO.  DISCARD THEM.
	CAIE TT,%TXTOP+"S	;TOP-S AND TOP-E ARE SPECIAL COMMANDS SENT
	 CAIN TT,%TXTOP+"E	;BY LOCAL EDITING TTYS.
	  JRST [SKIPG TICC(I)	;IGNORE THE TOP-E OR TOP-S,
		 PUSHJ P,UFLS	;AND THE CHARACTER AFTER IT AS WELL.
		PUSHJ P,TYIREM
		JRST TYI1B1]
	CAIN TT,%TXTOP+"T	;TOP-T MEANS "LABEL FAILURE" IN LINE SAVING PROTOCOL.
	 JRST [	MOVEI T,3	;IGNORE COMMAND AND THREE ARGS.
		CAMLE T,TICC(I)
		 PUSHJ P,UFLS
		PUSHJ P,TYIREM
		PUSHJ P,TYIREM
		PUSHJ P,TYIREM
		JRST TYI1B1]
TYI2Z:	MOVE T,TTYSTS(I)
	TLNE T,%TSCNS
	 SKIPGE SUPPRO(U)
	  JRST TYI3		;DEFERRED CALL IGNORED IF TOP-LEVEL, OR NOT A CONSOLE
	CAIN TT,%TXTOP+"Z
	 JRST [	TRNE R,%TIPEK	;DEFERRED CALL
		 PUSHJ P,TYIREM	;REMOVE IT IF DIDN'T ALREADY
		MOVSI T,(%PIDCL)
		JRST UUOER1 ]
TYI3:	MOVSI TT,%TSACT
	ANDCAM TT,TTYSTS(I)
;TYIFLS CAN COME HERE AFTER THROWING AWAY 1 WORD FROM STACK, FOR NO CHARS AVAIL WITH %TINWT.
TYI4:	MOVSI TT,%SSINT	;IF TTY IS STY'S, MAKE SURE NEXT TTY IOT GIVES STY OUTPUT INT.
	MOVE B,TTYTYP(I)
	TRNE B,%TYSTY
	 ANDCAM TT,STYSTS-NFSTTY(I)
	SKIPGE A,D		;CHAR IN A FOR TYINRM
	 POPJ P,		;DON'T CANONICALIZE A -1 (NO CHARS AVAILABLE) TO A RUBOUT!
	PUSHJ P,TYINRM		;CANONICALIZE TO ASCII UNLESS %TIFUL IS SET.
	ANDI D,%TXPIE\%TXMPE\%TXECI	;BUT PRESERVE THE EXTRA INFO BITS
	IOR D,A			;WHICH ARE NOT REALLY PART OF THE CHARACTER.
	ANDI A,%TXASC
	POPJ P,

;ASSUME R HAS IOCHNM BITS (OR AT LEAST THE %TIFUL BIT).
;TURN CHAR. IN A TO 7-BIT ASCII CHAR IF %TIFUL IS OFF.
TYINRM:	ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC
	TRNE R,%TIFUL
	 POPJ P,
	MOVE TT,A		;LEAVE THE HELP CHARACTER ALONE
	ANDI TT,%TXTOP+%TXASC	;(THIS USED TO FLUSH THE SUPER ("SHIFT") BIT
	CAIN TT,%TXTOP+"H	; PERHAPS IT SHOULD FLUSH ALL OF CTL/MTA/SUP?)
	 POPJ P,
TYINR2:	ANDI A,%TXCTL+%TXASC	;FLUSH THE EXTRA BITS.
	TRZE A,%TXCTL	;DON'T WANT FULL CHAR SET: TURN CTL+X INTO ASCII CTL-X
	 CAIN A,177	;BUT LEAVE CTL-RUBOUT AS RUBOUT, FOR TECO'S SAKE.
	  POPJ P,
	CAIGE A,77		;CTL-? => RUBOUT
	 JRST [	CAIN A,40	;CTL-SPACE => CTL-@
		 MOVEI A,^@	;41-76 STAY THE SAME
		POPJ P, ]	;LETTERS TURN INTO ASCII CONTROLS
	CAIL A,140	;TO CONTROLIFY, FIRST TURN LOWER CASE TO UPPER,
	 SUBI A,40
	XORI A,100	;THEN TOGGLE 100 BIT, TURNING A INTO ^A AND ? INTO RUBOUT.
	POPJ P,

;REMOVE THE FIRST CHAR. FROM THE INPUT BUFFER, AND RETURN IT IN D.
;UPDATES ALL COUNTS AND POINTERS. HALTS IF BUFFER EMPTY.
;CLOBBERS B,TT.
TYIREM:	CONO PI,TTYOFF
	PUSHJ P,TYIRE1
	JRST TTYONJ

TYIRE1:	SOSGE TICC(I)	;ENTRY WHEN TTYCHN IS OFF.
	 BUG PAUSE,[TTY: BUFFER EMPTY AT TYIREM]
	MOVE B,TIOP(I)	;SAVE COPY OF BUFFER-EMPTYING POINTER IN TT.
	MOVE TT,B
	CAMN B,TIBEP(I)	;ADVANCE THE POINTER, FETCHING THE CHARACTER.
	 SUBI B,TIBL
	ILDB D,B
	MOVEM B,TIOP(I)
	TRNE D,%TXACT	;IF CHAR SAYS IT WAS AN ACTIVATION CHAR, UPDATE # OF ACTIVATION
	 SOS TACC(I)	;CHARS STILL INB THE BUFFER.
	TRNE D,%TXPIE	;IF IT NEEDED PI ECHO,
	 SOS ECHOC(I)	;ONE FEWER CHAR AWAITS PI ECHO.
	TRNE D,%TXINT
	 SOS TINTC(I)	;SIMILAR FOR INT. TO PROGM.
	SKIPL TINTC(I)
	 SKIPGE ECHOC(I)
	  BUG PAUSE,[TTY: TINTC OR ECHOC OVER-DECREMENTED]
	CAMN TT,ECHOP(I) ;IF ECHOP POINTED AT THIS CHAR,
	 MOVEM B,ECHOP(I) ;ADVANCE IT.
	CAMN TT,TINTP(I) ;SIMILAR FOR TINTP
	 MOVEM B,TINTP(I)
	POPJ P,

;COME HERE WHEN ABOUT TO WAIT FOR A CHAR'S %TXINT TO CLEAR OUT.
;CLOBBERS D, TT; MAY ZERO %TXINT IN T, IN WHICH CASE CALLER SHOULD
;NOT BOTHER TO WAIT FOR %TXINT TO CLEAR.
TYIIWT:	MOVE D,MSKST2(U)
	AND D,TYIMSK(I)	;D GETS ENABLED TTY INPUT CHANNELS.
	MOVE TT,D
	ANDCM TT,IDF2(U) ;TT GETS ENABLED, UNDEFERRED TTY INPUT CHANNELS.
	TDNE TT,IFPIR(U) ;IF AN INTERRUPT IS PENDING ON ONE OF THEM, %TXINT
	 POPJ P,	;WILL CLEAR IF WE LET THE INT. HAPPEN.
	MOVN TT,D	;ELSE GET LOWEST NUMBERED ENABLED INPUT CHANNEL'S BIT
	AND D,TT
	AND D,IDF2(U)	;IF THAT CHANNEL ISN'T DEFFERED,
	IORM D,IFPIR(U)	;REQUEST AN INTERRUPT ON IT, AND WE CAN STILL WIN.
	JUMPN D,CPOPJ
	ANDCMI T,%TXINT	;CAN'T RQ AN INT, SO BIT WON'T BE CLEARED, IT IS CERTAIN,
	POPJ P,		;SO GIVE UP ON WAIITING FOR IT TO CLEAR.

;COME HERE TO HANG UP FOR INPUT. LIKE UFLS BUT PREVENTS
;A **MORE** THIS TIME AROUND THE SCREEN, ON GROUNDS THAT USER
;HAS COMMANDED THE OUTPUT FOR 1 MORE PAGE AT LEAST.
;IF %TINWT IS SET, INSTEAD OF HANGING, THROW AWAY RETURN ADDRESS
;AND JUMP TO TYI4, TO RETURN -1 FROM THE IOT.
;CLOBBERS A,D,H.
TYIFLS:	TRNE R,%TINWT
	 JRST [	SUB P,[1,,1]
		SETO D,
		JRST TYI4]
;ENTER HERE FROM ECHOIN - R IS NOT MEANINGFUL.
TYIFL2:	MOVE H,TTYOPT(I)
	TLNE H,%TOMVU	;THIS DOESNT APPLY TO ARDS-LIKE DISPLAYS
	 TLNE H,%TOERS
	  SKIPA D,I
	   JRST UFLS
	IMULI D,TPLEN*2
	MOVEI A,%TFEOP
	ANDCAM A,TPFLAG(D)	;CLEAR PENDING MORE
	HLL D,TTYSTS(I)
	MOVE A,TCMXV(I) .SEE TPVE;(D)
	TLNE H,%TOMVU		;PRINTING TTY'S AND DISPLAYS IN SCROLL MODE
	 TLNE D,%TSROL		;DO ONE THING.
	  JRST TYIFL1
	CAME A,TPVB+TPLEN(D)	;FOR WRAP-AROUND DISPLAYS,
	 JRST UFLS		;IF NOT USING AN ECHO AREA,
	MOVEI A,6		;PREVENT MORES FOR THE NEXT 6 LINES.
	MOVEM A,TPVM(D)
	JRST UFLS

TYIFL1:	SUB A,TTYROL(I)	;IN SCROLL MODE, **MORE** WHEN THIS LINE GOES OFF THE SCREEN.
	MOVEM A,TPVM(D)
	JRST UFLS

SUBTTL TTY OUTPUT IOT

;THESE PUSHED BY TYOSET, REFERENCED INDEX OF J.
TYOPV0==0	;COUNT OF NUMBER OF CHARACTERS THAT WE CAN TAKE A SHORTCUT FOR,
		 ;IN SUPERIMAGE MODE SIOT.
;TYOPV1 UNUSED, BUT SPACE ALLOCATED.
TYOPV2==2	;-> IOCHNM WORD OF CHANNEL IOT IS ON.
TYOPV3==3	;PC PPR IDX,,TTY #.


;TO OUTPUT TO A TTY (R -> IOCHNM WD OF TTY CHNL)
;	JSP E,TYOSET	;WAIT TILL JOB HAS TTY AND OUT OF COM MODE,
;			;INIT FOR PCLSRING, PUSH VARS ON STACK.
;	 JRST IGNORE	;TYOSET RETURNS HERE IF THIS OUTPUT SHOULD BE DISCARDED.
;	 ...		;OUTPUT 1 OR MORE CHARS TO TTY
;			;MEANWHILE, J -> BLOCK OF 4 STACK VARS.
;	POPJ P,		;RETURNS TO TYOUNS TO FLUSH STACK, ETC.

TYOSET:	PUSHJ P,TTYWO	;WAIT TILL THIS JOB HAS OUTPUT PERMISSION.
	 JRST (E)	;RETURN IF OUTPUT BEING IGNORED.
	AOS E		;SKIP THAT RETURN IF WE ARE GOING TO DO THE OUTPUT.
	JUMPN U,TYOSE3
	MOVEI T,TYOWNC	;FOR SYSTEM JOB, CHECK TTOALC WITH A TIMEOUT IN CASE
	SKIPL TTOALC(I)	;THE TTY IS FORGETTING TO TURN TYPEOUT BACK ON.
	 PUSHJ P,TYOW2
	JRST TYOSE4	;NOTE THAT TYOW2 CAN POP1J.

TYOSE3:	SKIPL TTOALC(I)	;^\ CAN DELAY TYPEOUT AT M.P. LEVEL THROUGH SIGN OF TTOALC.
	 PUSHJ P,UFLS	;ALSO USED BY OUTPUT RESET ON SOFTWARE TTY.
TYOSE4:	MOVEI J,1(P)	;PROVIDE SPACE FOR TEMPS, WHERE FINSET CAN FIND THEM.
	ADD P,[2,,2]
	PUSH P,R	.SEE TYOPV2
	MOVE H,TTYOPT(I)
	MOVSI T,%TCLFT+%TCOCO+%TCICO
	SKIPGE TTYCOM(I)
	 PUSHJ P,TTYCMW	;WAIT TILL TTY IS NOT IN COM MODE, OR OVER-RIDDEN.
	CONO PI,TTYON
	MOVEI A,%TJCNS+77+%TJCP1+%TJCP2+%TJSTP+%TJINK ;DON'T LET THESE IOCHNM BITS BE CHANGED
	ANDCAB A,CTLBTS(U) ;EVEN TEMPORARILY.
	HRLZS A		;ELSE, IF A BIT IS SET IN THE CTL BITS,
	XORB A,(R)	;CHANGE IT (TEMPORARILY) IN IOCHNM WORD.
	PUSHJ P,LOSSET	;SET UP ROUTINE TO UNDO THAT TEMPORARY CHANGE
	 [MOVE A,AC0S+J(U)	;IF WE SHOULD PCLSR OUT
	  HLRZ T,@TYOPV2(A)
	  XOR T,CTLBTS(U)
	  HRLM T,@TYOPV2(A)
	  POPJ P,]
	HLRZS A
	TRNE A,%TJSTP	;IF WE ARE HUNG IN A **MORE**, WAIT TILL THERE'S A CHARACTER
	 PUSHJ P,TYOSMR	;IT'S IMPORTANT WE WAIT WITOUT TYOSW SET - ELSE NO ECHOING!
	MOVE TT,I	;NOW MAKE TT -> APPRO. PC PPR FOR THIS CHNL.
	IMULI TT,TPLEN*2
	TRNE A,%TJPP2
	 MOVE TT,TTYEPP(I)
TYOSE1:	PCLT		;ENTER HERE FROM INPUT IOT WHEN DOING M.P. ECHOING
	AOSE TYOSW(I)	;SEIZE THIS TTY FOR MP LEVEL.
	 JRST [SKIPL TYOSW(I)
		PUSHJ P,UFLS
		JRST .-1]
	PUSHJ P,LSWDEL	;THEN SET UP LOSSET ROUTINE FOR BOTH TYOSW AND 
	PUSHJ P,LOSSET	;PREVIOUSLY-LOSSET'ED CHANGE TO IOCHNM BITS.
	 [MOVE A,AC0S+J(U)
	  HLRZ T,@TYOPV2(A)
	  XOR T,CTLBTS(U)
	  HRLM T,@TYOPV2(A)
	  MOVE A,TYOPV3(A)
	  SETOM TYOSW(A)
	  POPJ P,]
	CAMN TT,TTYLPP(I) ;IF TTY IS ASSOCIATED W/ ANOTHER PC PPR,
	 JRST TYOSE2
	PUSH P,TT
	SKIPL TT,TTYLPP(I)
	 PUSHJ P,TYOMVC	;DISASSOCIATE THEM.
	POP P,TT
	SETCAM TT,TTYLPP(I)
TYOSE2:	PUSH P,I	.SEE TYOPV3
	HRLM TT,(P)
	MOVE Q,TTYCOM(I)
	TLNE Q,%TCECH	;IF THERE'S ECHOING OUTPUT IN OUTPUT BUFFER,
	 JRST [	PCLT	;WAIT FOR IT TO GET PRINTED. MUSTN'T HAVE ECHO AND
		PUSHJ P,TYOWC	;OUTPUT IN THE OUTPUT BUFFER AT ONE TIME.
		MOVSI Q,%TCECH
		ANDCAB Q,TTYCOM(I)
		JRST .+1]
	TLNE Q,%TCMTR	;IF THIS TTY IS A TERMINET & ITS MOTOR IS OFF,
	 PUSHJ P,TTTMTO	;TURN THE MOTOR ON BEFORE OUTPUT.
	PUSHJ P,(E)

TYOUNS:	CAIA		;IF WE ARE SKIPPED INTO, PROPAGATE THE SKIP.
	 AOS -4(P)
	SUB P,[4,,4]

TYOUN1:	HRLZ R,CTLBTS(U) ;UNDO TEMPORARY CHANGES IN IOCHNM WD.
	XORM R,@TYOPV2(J)
	PUSHJ P,LSWDEL
	SKIPGE TTYERQ(I) ;IF ECHOING ISN'T ALREADY REQUESTED,
	SKIPL TTYLPP(I)	;AND THERE IS BUFFERED CURSOR POSITIONING,
	 JRST TYOUN3
	CONO PI,TTYOFF
	MOVEI J,TTEDMY	;SO TYOFNR WON'T CLOBBER RANDOMNESS.
	SETCM TT,TTYLPP(I) ;TT -> PC PPR TTY WAS DISSOCIATED FROM.
	MOVE H,TTYOPT(I)
	MOVE A,TORM(I)
	CAIN A,TOBS	;AND IT CAN BE DONE NOW,
	 PUSHJ P,TYOFRC	;FORCE OUT BUFFERED CURSOR MOTION.
	SETOM TYOSW(I)
	JRST TTYONJ

TYOUN3:	SETOM TYOSW(I)	;RELEASE TTY.
	POPJ P,

;WAIT TILL THERE'S A TTY INPUT CHARACTER.
TYOSMR:	PUSH P,A
	PUSH P,R
	MOVEI R,%TIACT+%TIECH+%TIPEK
	PUSHJ P,TYI0
	POP P,R
	JRST POPAJ

;OUTPUT IOT

;BLOCK MODE.
TTYBO:	JSP E,TYOSET
	 JRST TTYBOI
	JSP E,NBTOCH
TTYBO3:	CAIN A,EOFCH
	 POPJ P,
	PUSH P,TT
	PUSHJ P,TTYBO1
	POP P,TT
	MOVEI E,TTYBO3
	POPJ P,

;IGNORE SOME BLOCK MODE OUTPUT.
TTYBOI:	XCTR XRW,[MOVES D,(C)]
	TLO D,700000
	HLRE A,D
	MOVNS A
	HRLS A
	ADD D,A		;COUNT THE AOBJN POINTER ALL THE WAY OUT.
	XCTR XRW,[MOVEM D,(C)]
	POPJ P,

	JRST TYOBP	;SIOT DISPATCH IS -1 + ADDR. OF UNIT MODE ROUTINE.
;UNIT MODE TTY OUTPUT.
TYO:	JSP E,TYOSET
	 POPJ P,	;JUST RETURN IF WE ARE SUPPOSED TO DISCARD THE OUTPUT.
	SKIPGE C
	 SKIPA A,(C)
	  UMOVE A,(C)
;MUSTN'T CLOBBER C OR D.
TTYBO1:	HLRZ R,@TYOPV2(J) ;RH(R) GETS LH(IOCHNM WD)
	HRRZ I,TYOPV3(J)
	HLRZ TT,TYOPV3(J)
TYOBP2:	ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC
	SKIPGE E,TTYCOM(I);IN COM MODE W/ LOCAL FEED THRU,
	TLNN E,%TCLFT
	 JRST TYO6
	PUSH P,C
	PUSH P,D
	PUSH P,U
	PUSH P,TT	;ECHO CHAR ON ALL TTYS IN LOOP
	PUSH P,R	;THAT HAVE REMOTE-FEED-THRU.
	PUSHJ P,TYCREP	;DO FOLLOWING INSN FOR EACH TTY IN LOOP.
	    PUSHJ P,TYO7 ;(# OF TTY DOING IT FOR PUT IN I)
	 JFCL		 ;(TYCREP WILL SKIP IF THAT INSN ALWAYS DOES)
	POP P,R
	POP P,TT
	POP P,U
	POP P,D
	POP P,C
	JRST TYO6

TYO7:	MOVE D,TTYCOM(I) ;IF THIS TTY WANTS MY TYPEOUT.
	TLNE D,%TCRFT
	CAMN I,-2(P)	;AND IF IT ISN'T ME,
	 JRST POPJ1
	PUSHJ P,TYCSET	;SET UP ACS Q,R,U FOR TTY TO ECHO ON.
	CONO PI,TTYOFF
	PUSH P,A
	PUSHJ P,TTYI13	;ECHO CHAR ON THIS TTY.
	CONO PI,TTYON
	JRST POPAJ1

;SIOT ROUTINE FOR TTY OUTPUT - JUST LIKE REPEATED UNIT MODE,
;BUT MOVES THE TYOSET OUTSIDE THE LOOP TO SAVE TIME.
TYOBP:	MOVEM B,SRN3(U)	;SAVE B, C; CAN'T USE STACK SINCE TYOSET PUSHES.
	MOVEM C,SRN4(U)
	JSP E,TYOSET	;SET UP FOR DOING TTY OUTPUT.
	 JRST TYOBPI	;RETURN HERE IF WE SHOULD DISCARD THE OUTPUT
	HLRZ R,@TYOPV2(J)	;FOR TYOFRC
	CAME TT,TTYLPP(I)
	 TRNN R,%TJSIO	;ONLY IN SUPER-IMAGE MODE,
	  CAIA
	   PUSHJ P,TYOFRC	;FORCE OUT ALL PREVIOUS MAIN PROGRAM CURSOR MOTION
	MOVE B,SRN3(U)	;BE JUST LIKE ORDINARY REPEATED-UNIT-MODE SIOT,
	MOVE C,SRN4(U)	;EXCEPT THAT THE TYOSET IS OUTSIDE THE LOOP.
	SETOM TYOPV0(J)	;CAN'T TAKE SHORTCUT AT FIRST.
	MOVE D,[%IOTOT,,.+2]
	JRST NSIOT1	;SIOT ROUTINE WILL COME BACK FOR EACH CHAR, PRESERVING I,J,TT
	HLRZ R,@TYOPV2(J)
	MOVE A,D	;PUSHJ HERE FOR EACH CHARACTER.
	SOSG TYOPV0(J)	;PERHAPS THE PREVIOUS CHARACTER DISCOVERED WE CAN
			 ;START TAKING THE SHORTCUT.
	 JRST TYOBP2	;IF NOT, DO THE WHOLE PILE OF WORK.
	ANDI A,%TXDIS+%TXASC
	SKIPGE E,TTYCOM(I)
	 TLNN E,%TCLFT	;SHORT CUT IS TO PUT THE CHARACTER RIGHT IN THE OUTPUT BUFFER.
	  JRST TYONCC	;MAY BE USED ONLY FOR SUPERIMAGE OUTPUT.
	JRST TYOBP2	;AND BETTER NOT BE IN COM MODE WITH LOCAL FEED THRU.

;IGNORE THIS STRING OF OUTPUT; TELL THE USER WE OUTPUT IT.
TYOBPI:	MOVE B,SRN3(U)
	MOVE C,SRN3(U)
	UMOVE T,(B)
	UMOVE TT,(C)
	JUMPE C,POPJ1
	IBP T
	SOJG TT,.-1
	XCTR XRW,[MOVEM T,(B)]
	XCTR XRW,[MOVEM TT,(C)]
	JRST POPJ1


;A USUALLY HOLDS THE CHAR BEING IOTTED, OR THE CHAR TO BE PUT IN BUFFER.
;B IS A TEMP.
;C IS USUALLY UNUSED, AND MUSTN'T BE CLOBBER BY IOT RTN.
;D "
;E IS A TEMP.
;TT HOLDS THE INDEX OF THE PC PPR BEING USED.
;I HOLDS THE TTY NUMBER.
;H HOLDS THE TTY'S TTYOPT WORD.
;J HOLDS THE INDEX OF A 4-WORD BLOCK USUALLY ON THE STACK
;	INDEX USING TYOPV0, TYOPV1, TYOPV2, TYOPV3.
;T IS A TEMP.
;R'S RH HOLDS THE IOCHNM WORD'S LH.
;Q HOLDS THE BP FOR STORING IN OUTPUT BUFFER.
;	INITTED FROM TOIP, AND STORED BACK IN TOIP WHEN FINALIZED.

TYO6:	PCLT
	MOVEI T,TYOWNC ;MAKE SURE AT LEAST TYOWNC
	CAML T,TORM(I)	;CHARS OF SPACE LEFT IN OUTPUT BUFFER.
	 PUSHJ P,TYOW2	;NOTE THIS CAN POP1J. SO CAN TYOWN.
	MOVE H,TTYOPT(I)
IFN N11TYS,[
	TRNN H,%TP11T	;FOR A PDP11 TV TTY,
	 JRST TYO8
	SKIPL TT11P	;IGNORE IT IF PDP11 ISN'T UP.
	 POPJ P,
	PUSHJ P,TYOWN	;WAIT TILL AT LEAST TYOWNC CHARS SPACE.
]			;(TORM HAS NO INFO ON TV TTYS).
;A,R,I,TT,H,J SET UP AT THIS POINT.
;ENTER HERE FROM PI LEVEL TO ECHO CHARS
TYO8:	MOVE Q,TOIP(I)	;GET COPY OF BP TO STORE WITH.
		;WHEN OUTPUTTING CHARS, WILL UPDATE Q INSTEAD TOIP.
		;THEN, WHEN CAN NO LONGER PCLSR, DO TOIP(I)_Q.
	MOVE B,TPFLAG(TT)
TYOIG1:	TRNE B,%TFEOP+%TFIGL	;ANY EXCEPTIONAL CONDITION FOR THIS PC PPR?
	 JRST TYOIGL	;IF SO, HANDLE IT.
TYOEO9:	TRNE R,%TJCP1+%TJCP2+%TJSTP+%TJSIO+%TJINK
	 JRST TYOCP1	;HANDLE ANY EXCEPTIONAL CONDITION FOR CHANNEL.
	TRNE A,%TXCTL+%TXMTA+%TXSUP+%TXTOP
	 JRST TYOMTA	;TAKE CARE OF FUNNY BITS IN CHARACTER.
TYOMT9:	CAILE A,40
	 JRST TYONRM	;PRINTING CHARS AND RUBOUT.
	CAIN A,40
	 JRST TYOSPC	;SPACE MAY BE EITHER PRINTING OR CURSOR MOTION.
	CAIL A,^G	;< ^G OR > ^S => NORMAL CTL CHAR,
IFE 0,	CAIL A,^Q	;RIGHT NOW, ^S USES %TGIMG OF GROUP 0.
IFN 0,	CAIL A,^T	;BUT FOR INPUT, IT USES GROUP 6. THIS INSN MAKES IT USE GROUP 6 FOR OUTPUT TOO.
	 JRST TYOCTL
	JRST @.+1-^G(A) ;ELSE DO WHAT THIS PARTICULAR ONE WANTS.

	TYOBEL		;^G DOESN'T MOVE CURSOR.
	TYOBS		;^H MOVES BACKWARDS.
	TYOTAB		;^I MOVES TO TAB STOP.
	TYOLF		;^J IS LINEFEED.
	TYOCTL		;^K IS NORMAL.
	TYOFF		;^L MAY CAUSE A **MORE**
	TYOCR		;^M IS A CARRET
	TYOCTL		;^N IS NORMAL
	TYOCTL		;^O IS NORMAL
	TYOCTP		;^P MAY SIGNIFY A CURSOR CTL CODE.
	TYOCTL		;^Q IS NORMAL
	TYOCTL		;^R IS NORMAL
	TYOCTS		;^S IS NORMAL EXCEPT USES A DIFFERENT GROUP'S %TGIMG.

;OUTPUT CHARACTER IN SUPERIMAGE MODE.
TYOSIO:	ANDI A,377
	MOVEI B,TYOWNC	;IF WE'VE GOT THIS FAR, THEN THERE'S AT LEAST TYOWNC CHARS OF SPACE,
	CAME TT,TTYLPP(I)	;IF DISSOCIATED,
	 PUSHJ P,[
		PUSH P,Q
		PUSHJ P,TYOASS	;ASSOCIATE,
		POP P,T
		CAME T,Q	;AND IF THAT REQUIRED OUTPUT,
		 SUBI B,5	;THAT'S SO MANY FEWER CHARS BEFORE TIME TO CHECK TORM AGAIN.
		POPJ P,]
	MOVEM B,TYOPV0(J) ;AND NO UNUSUAL CONDITIONS, SO SIOT CAN GO FAST FOR A WHILE.
;OUTPUT A CHAR WITH NO CURSOR CONTROL.
;ASSUMES ITS POSITION DOESN'T MATTER.
TYONCC:	PUSHJ P,TYOOUT
	JRST TYOFN2

;COME HERE WHEN ^P IS OUTPUT.
TYOCTP:	TRNN R,%TJDIS	;IS THIS OUTPUT CHNL TREATING ^P SPECIALLY?
	 JRST TYOCTL	;NO, TREAT ^P AS NORMAL CTL CHAR.
	TRO R,%TJCP1	;YES, SAY TREAT NEXT CHAR AS CURSOR CODE.
	JRST TYOFNR

;COME HERE TO OUTPUT A ^S.
TYOCTS:	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOASS	;PREPARE TO OUTPUT PRINTING CHARACTERS.
	HLLZ T,TTYST2(I) ;GET THE RELEVANT %TGIMG BIT.
	TLZ T,#<%TGIMG_12.>
	JRST TYORU2

;HERE TO OUTPUT ^G
TYOBEL:	MOVEI A,%TDBEL
	JRST TYONCC

;COME HERE FOR ^PP - OUTPUT A ^P.
TYOCPP:	SKIPA A,[^P]

;COME HERE FOR ^PQ TO OUTPUT A ^C.
TYOCPQ:	 MOVEI A,^C

;COME HERE FOR NORMAL (NON-FORMATTING) CONTROLS.
TYOCTL:	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOASS	;PREPARE TO OUTPUT PRINTING CHARACTERS.
	CAIN A,33
	 JRST TYOALT	;CHECK FOR ALTMODE.
	HLLZ T,TTYST1(I) ;GET THE "OUTPUT IN IMAGE MODE" BIT THAT'S RELEVANT.
	TLZ T,#<%TGIMG_12.>
TYORU2:	TRNE R,%TJECH	;ECHO-MODE OUT => PRINT IN ASCII MODE.
	 JRST TYOCT1
	MOVE B,TTYSTS(I)
	TLNE B,%TSSAI	;SHOULD USE SAIL CHAR SET FOR OUTPUT => DO SO.
	 JRST TYONR0
	JUMPN T,TYOAL1	;IF "OUTPUT IN IMAGE" IS SET, GO DO SO.
TYOCT1:	HRLM A,(P)	;ELSE OUTPUT CTL CHAR IN ASCII MODE,
	MOVEI A,"^	;AS "^" FOLLOWED BY UN-CTL'ED CHAR.
	TLNE H,%TOSAI
	 MOVEI A,13	;IF TTY HAS SAIL MODE, USE A SAIL UPARROW.
	PUSHJ P,TYONR1
	HLRZ A,(P)
	XORI A,100
	JRST TYONR0

TYOAL1:	TLNN H,%TOSAI
	 JRST TYORU1
	JRST TYONR0

;HANDLE CHARACTERS WHICH HAVE %TXCTL, %TXMTA, %TXSUP OR %TXTOP SET.
TYOMTA:	MOVE B,TTYSTS(I)
	TLNN B,%TSFCO		;IF USER DOESN'T WANT FULL CHAR SET OUTPUT,
	 JRST TYOMT4		;IGNORE THE META BITS (USUALLY).
	TRNE A,%TXCTL
	 PUSHJ P,TYOMT1		;ECHO AN ALPHA FOR %TXCTL.
	TRZE A,%TXMTA
	 PUSHJ P,TYOMT2		;TYPE A BETA FOR %TXMTA
	TRZE A,%TXSUP
	 PUSHJ P,TYOMT5
	TRZN A,%TXCTL+%TXTOP	;IF CTL OR TOP IS SET, THE CHARACTER
	 JRST TYOMT9
	CAIN A,40		;ISN'T AN ASCII CONTROL CHAR EVEN IF < 40
	 JRST TYOSPC		;(BTW, SPACE IS STILL SPACE)
	CAIE A,177
	 CAIG A,40
TYOMT3:	  TLNE H,%TOSAI
	   JRST TYONRM
	CAME TT,TTYLPP(I)	;WE HAVE WHAT WOULD OTHERWISE BE AN ASCII CTL CHAR.
	 PUSHJ P,TYOASS
	CAIN A,33
	 JRST TYOAL3
	JRST TYOCT1

TYOMT5:	MOVEI B,6		; EPSILON
	JRST TYOMT6

TYOMT1:	SKIPA B,[2]		; ALPHA
TYOMT2:	 MOVEI B,3		; BETA
TYOMT6:	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOASS
	PUSH P,A
	MOVE A,B
	PUSHJ P,TYONR1
	JRST POPAJ

TYOMT4:	TRNN R,%TJECH	;FOR OUTPUT, IGNORE THE META BITS.  FOR ECHO,
	 ANDI A,%TXASC	; TRY TO ECHO WHAT THE GUY TYPED.
	TRNE A,%TXTOP	;IF TOP IS ON,
	 TLNN H,%TOSAI	;AND THE TTY HAS THE SAIL CHAR SET,
	  TRZA A,%TXMTA+%TXSUP+%TXTOP
	   JRST TYONR3	;ECHO THE CHAR USING SAIL CHAR SET.
	PUSHJ P,TYINR2	;ECHO AS WHAT PROGRAM SEES
	JRST TYOMT9	;ALSO HACKS SUCH AS ^L MAY CLEAR THE SCREEN

;HANDLE SPACE: ON OVERPRINTING TERMINALS, SPACE = ^PF.
;ON IMLACS, SPACE = SPACE BECAUSE THE IMLAC PROGRAM LOSES FOR ^PF AT END OF LINE.
;ON RAW TERMINALS, SPACE OF COURSE GOES OUT AS SPACE.
;ON OTHER TERMINALS, SPACE = SPACE.  THIS IS A CROCK, BUT IT IS NECESSARY
;BECAUSE ^PF TAKES 6 TIMES AS LONG ON DATAPOINTS BECAUSE OF PADDING,
;AND TWICE AS LONG ON VT52S BECAUSE IT TAKES TWO CHARACTERS.

TYOSPC:	TLNN H,%TOOVR		;NON-OVERPRINTING => OUTPUT A REAL SPACE.
	 JRST [	TLNE H,%TOMVU
		 JRST TYONRM
		HLRE B,TTYLPS(I) ;BUT ON GLASS TTY'S (NON-OVERPRINTING, NO UPWARD MOTION)
		CAMGE B,TPVP(TT)
		 JUMPGE B,.+1	;IT IS SAFE TO TREAT SPACES AS CURSOR MOTION
		JRST TYONRM]	;IF THEY ARE GOING TO FOLLOW DOWNWARD MOTION ANYWAY.
	TLNE H,%TORAW+%TOIML	;IMLAC, OR NO OPTIMIZATION => OUTPUT A REAL SPACE.
	 JRST TYONRM	;NORMAL CHARACTER.
	CAMN TT,TTYLPP(I)
	 PUSHJ P,TYOMVC	;PREPARE FOR CURSOR MOTION.
	AOS B,TPHP(TT)	;MOVE FORWARD 1 POS.
	CAML B,TCMXH(I)	.SEE TPHE;(TT)
	TRNE R,%TJCTN
	 JRST TYOFNR
	SOS TPHP(TT)	;IF NECESSARY, CONTINUE TO NEXT LINE AND RETRY.
	PUSHJ P,TYOCTN
	JRST TYOSPC

TYONR3:	ANDI A,%TXASC
;OUTPUT A NORMAL CHARACTER, AND FINALIZE. COME HERE FOR
;NORMAL CHAR ACTUALLY IOTTED.
TYONRM:	CAME TT,TTYLPP(I) ;ABOUT TO OUTPUT PRINTING CHARS SO
	 PUSHJ P,TYOASS	;FORCE ANY CURSOR MOTION INTO OUTPUT BFR
	CAIN A,177
	 JRST TYORUB

;CALL HERE TO OUTPUT NORMAL CHAR, IF CURSOR POSITIONING KNOWN
;NOT TO BE NECESSARY.
TYONR0:	PUSH P,[TYOFNA]	;CAUSE FINALIZATION WHEN FINISHED.

;CALL HERE TO OUTPUT NORMAL CHAR AS PART OF TASK OF OUTPUTTING
;SOME LARGER GROUP. DOESN'T FINALIZE, IN CASE WE PCLSR LATER.
TYONR1:	AOS B,TPHP(TT)	;ADVANCE CURSOR OF PC PPR 1 SPACE.
	CAML B,TCMXH(I)	.SEE TPHE;(TT)	;NOT YET AT END OF LINE => OUTPUT CHAR.
	TRNE R,%TJCTN	;AT END: NO CONTIN => OUTPUT,
	 JRST TYOOUT
	PUSHJ P,TYONR2	;CONTINUE THE LINE (NOTE CURSOR POS FOR
	CAME TT,TTYLPP(I)	;THE "!" WAS ALREADY DONE)
	 PUSHJ P,TYOASS	;TYONR2 DISSOCIATED THE TTY
	JRST TYONR1	;BUT TYONR1 NEEDS IT ASSOCIATED.

;TYPE "!<CR><LF>" TO CONTINUE A LINE.
;THIS FINALIZES THE !CRLF BUT ALSO REMOVES THE CONDITIONS WHICH
;CAUSED IT TO BE CALLED; SO PCLSRING IS NO PROBLEM.
;LEAVES TTY DISSOCIATED FROM PC PPR.
TYOCTN:	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOASS
	AOS TPHP(TT)	;ACCOUNT FOR THE "!".
TYONR2:	PUSH P,A
	MOVEI A,"!	;PUT "!" IN OUTPUT BUFFER,
	PUSHJ P,TYOOUT
	PUSHJ P,TYORCR	;AND GO TO NEXT LINE.
	PUSHJ P,TYOLF
	MOVE B,TPFLAG(TT) ;IF THAT LF TOOK US TO LAST LINE,
	TRNE B,%TFEOP
	 JRST TYOEO5	;DO **MORE** PROCESSING IF NEC.
	JRST POPAJ	;AND RETRY WHATEVER CAUSED CONTINUATION.

;COME HERE TO OUTPUT A RUBOUT.
TYORUB:	TRNN R,%TJECH
	 JRST TYORU3
	TLNN H,%TOERS	;RUBOUT ON A DISPLAY CONSOLE ECHOES AS DELETE BACKWARDS.
	 TLNN H,%TOOVR	;LIKEWISE ON A GLASS TTY
 	  JRST TYODLB
TYORU3:	MOVE T,TTYST2(I)
	ANDI T,%TGIMG_6	;GET RUBOUT'S "OUTPUT IN IMAGE MODE" BIT.
	JRST TYORU2

;COME HERE TO OUTPUT A LF. FINALIZES. LEAVES TTY DISSOCIATED.
TYOLF:	CAMN TT,TTYLPP(I) ;BEFORE MUNGING PC PPR'S CURSOR POS,
	 PUSHJ P,TYOMVC	;MUST DISASSOCIATE TTY'S POS FROM PC PPR.
	SOS TPVM(TT)	;COUNT DOWN # LINES TILL NEXT **MORE**.
	AOS B,TPVP(TT)	;MOVE PC PPR'S CURSOR 1 LINE DOWN.
	CAIG B,118.	;DON'T LET VPOS ON PRINTING TTY GET TOO BIG.
	CAML B,TCMXV(I) .SEE TPVE;(TT)	;END OF RANGE => GO TO TOP OR SCROLL.
	 JRST TYOLFE
TYOLF0:	MOVE A,TTYSTS(I)
	TLNE A,%TSMOR	;IF **MORE** DESIRED,
	 JRST TYOLF1
	ADDI B,1	;THEN IF ENTERING LAST LINE OF RANGE,
	CAME B,TCMXV(I) .SEE TPVE;(TT)
	 JRST TYOLF1
	SKIPGE TPVM(TT)	;UNLESS NOT TIME YET,
	 SKIPA B,[%TFEOP] ;TELL NEXT OUTPUT ATTEMPT TO CAUSE **MORE**.
TYOLF1:	  SETZ B,
	PUSH P,B
	TLNE H,%TORAW
	 JRST [	MOVEI A,%TDLF	;NO OPTIMIZATION =>
		PUSHJ P,TYOOUT	;OUTPUT A REAL LF (PLUS PADDING)
		PUSHJ P,TYOMVC
		JRST TYOLF5]
	TLNN H,%TOERS	;IF TTY HAS SELECTIVE ERASE,
	 JRST TYOLF5
	PUSH P,TPHP(TT)
	PUSHJ P,TYORCR	;GO TO BEGINNING OF LINE
	HLRZ B,TTYLPS(I) ;IF CR AND LF AND CLR-EOL ARE EXACTLY
	ADDI B,1	;WHAT WE NEED,
	CAMN B,TPVP(TT)
	 SKIPN TTYROL(I)	;AND TTY CAN DO IT, DO THEM ALL AT ONCE.
	  SKIPA A,[%TDEOL]	;OTHERWISE, OUTPUT MOVE-CURSOR AND %TDEOL.
	   SKIPA A,[%TDCRL]	;OUTPUT %TDCRL = %TDMOV AND %TDEOL TOGETHER.
	     PUSHJ P,TYOASS
	PUSHJ P,TYOOUT
	PUSHJ P,TYOMVC
	POP P,TPHP(TT)
TYOLF5:	POP P,B
	IORM B,TPFLAG(TT)
	JRST TYOFND

;LINEFEED THAT WRAPS AROUND.
TYOLFE:	MOVE A,TTYSTS(I)
	TLNN H,%TOMVU		;END OF SCREEN ON PRINTING TTY => SCROLL BY 1.
	 JRST TYOLF2
	TLNE A,%TSROL		;DISPLAY IN SCROLL MODE?
	SKIPE TPVB(TT)		;CAN'T SCROLL UNLESS PC PPR IS WHOLE SCREEN.
	 JRST TYOLF3
TYOLF2:	MOVN A,TTYROL(I)	;A GETS - # LINES TO SCROLL AT ONCE.
	JUMPE A,TYOLF3		;JUMP IF THIS TTY CAN'T SCROLL
	SOS TPVP(TT)
	PUSH P,TPHP(TT)
	HRRZ B,TTYLPS(I)
	MOVEM B,TPHP(TT)
	PUSHJ P,TYOASS		;MOVE CURSOR DOWN TO LAST LINE ON SCREEN, PREPARING FOR SCROLL
	PUSHJ P,TYOMVC
	POP P,TPHP(TT)
	AOS TPVP(TT)
;SCROLL: A HAS -<# LINES TO ADJUST ALL VPOS'S BY>.
TYOLF6:	HLRZ B,TTYLPS(I) ;COMPUTE NEW TTYLPS LH.
	ADD B,A
	JUMPGE B,TYOLF7	;IF IT WOULD BE NEGATIVE,
	TLNN H,%TORAW		;ON DISPLAY WRAP AROUND INSTEAD (LOSSAGE HAPPENING).
	 JRST TYOLF3
	SETZ B,			;IN RAW MODE, DON'T WORRY ABOUT IT.
TYOLF7:	HRLM B,TTYLPS(I) ;STORE UPDATED M.P. VPOS.
	ADDM A,TPVP(TT)	;CHANGE OTHER MAIN PRGM VPOS'S.
	MOVE B,TPVP(TT)	;IF SCROLLING 1 LINE AT A TIME,
	JRST TYOLF0	;MAY NEED TO SET %TFEOP.
		;IN ANY CASE, CLEAR NEXT LINE & FINALIZE.

;HERE TO WRAP AROUND TO TOP OF SCREEN.
TYOLF3:	SETZM TPVM(TT)	;TURN OFF ANY SUPPRESSION OF MORES BY INPUT
	TLNN H,%TOERS	;ON DISPLAYS WITHOUT SELECTIVE ERASE,
	 JRST [	PUSHJ P,TYOCLR	;MUST CLEAR SCREEN WHEN WRAP AROUND.
		JRST TYOMVC]	;MUST LEAVE TTY DISSOCIATED.
TYOLF4:	MOVE B,TPVB(TT)	;ELSE JUST MOVE TO TOP OF PC PPR
	MOVEM B,TPVP(TT)
	JRST TYOLF1	;AND CLEAR THE TOP LINE.

;HANDLE BACKSPACE.
TYOBS:	TLNN H,%TOIML	;BACKSPACE ON IMLAC ISN'T SAME AS MOVE BACK.
	 JRST TYOBS1
	MOVE B,TPHP(TT)	;ON IMLAC, FIRST, IF AT LEFT MARGIN,
	SKIPG B	.SEE TPHB;(TT)	;DO NOTHING.
	 JRST TYOFN2
TYOBS2:	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOASS	;IF WE SHOULD BACKSPACE,
	SOSGE TPHP(TT)
	 SETZM TPHP(TT)
	JRST TYORU1	;DO IT BY SENDING A ^H.

TYOBS1:	TLNE H,%TOMVB	;ARE WE ECHOING ^H ON TTY THAT CAN'T BS?
	 JRST TYOBS4
	TRNN R,%TJECH
	 JRST TYOBS3
	JRST TYOCTL	;ECHO "^H" RATHER THAN CR AND SPACE FWD.

TYOBS4:	TLNE H,%TORAW	;IN RAW MODE ON TTY THAT CAN BS?
	 JRST [	MOVEI A,%TDBS	;IF NO OPTIMIZATION,
		JRST TYOBS2 ]	;ARRANGE TO OUTPUT REAL BS.
TYOBS3:	CAMN TT,TTYLPP(I) ;BS ON TTY THAT ISN'T AN IMLAC.
	 PUSHJ P,TYOMVC	;PREPARE TO DO CURSOR MOTION.
	SOS B,TPHP(TT)	;MOVE BACK 1 POS.
	SKIPGE B	.SEE TPHB;(TT)
	 AOS TPHP(TT)	;AT LEFT MARGIN, DO NOTHING.
	JRST TYOFNX

;COME HERE WHEN TAB OUTPUT (AT TOP LEVEL ONLY)
TYOTAB:	TRNE R,%TJECH
	 JRST TYOTA1
	MOVE B,TTYST2(I)	;MAYBE TABS SHOULD BE OUTPUT IN IMAGE MODE.
	TLNE B,%TGIMG_6
	 JRST TYONMV
TYOTA1:	MOVE A,TPHP(TT)
	ADDI A,10
	TRZ A,7		;HPOS OF NEXT TAB STOP.
	MOVE B,TCMXH(I)	.SEE TPHE;(TT)
	TRNN R,%TJCTN
	 SUBI B,1	;B HAS EFFECTIVE LINEL.
	CAML A,B
	 MOVE A,B	;A HAS PLACE TAB MOVES TO.
	SUB A,TPHP(TT)	;HOW FAR TO MOVE RIGHT?
	TRNN R,%TJCTN
	 JUMPE A,[PUSHJ P,TYOCTN
		  JRST TYOTAB]
	CAMN TT,TTYLPP(I)
	 PUSHJ P,TYOMVC	;PREPARE FOR CURSOR CTL.
	ADDM A,TPHP(TT)	;MOVE CURSOR TO TAB STOP.
	JRST TYOFNX

;HANDLE ^L.
TYOFF:	TRNN R,%TJECH	;ECHOING?
	 JRST TYOCTL
	MOVE B,TTYSTS(I) ;YES; ^L ECHOES AS UPARROW-L
	TLNE H,%TOMVU	;EXCEPT ON DISPLAYS, UNLESS PRGM HAS DISABLED.
	 TLNE B,%TSCLE
	  JRST TYOCTL	;ECHO AS UPARROW L
	JRST TYOCLR	;ECHO AS CLEAR SCREEN.

;^M IOTTED - MAYBE DO CR AND LF.
TYOCR:	TRNE R,%TJECH	;IF ECHO MODE OUT, CR DOES CRLF.
	 JRST TYOCRL
	MOVE B,TTYST2(I)
	TRNE B,%TGIMG_12. ;ELSE OUTPUT-CR-IN-IMAGE PREVENTS LF.
	 JRST TYOCR1
	PUSHJ P,TYOCRL	;DO CR AND LF,
	MOVEI B,%TFIGL	;THEN SAY IGNORE NEXT CHAR IF IT'S A LF.
	IORM B,TPFLAG(TT)
	POPJ P,

TYOCRL:	PUSHJ P,TYORCR
	PUSHJ P,TYOLF
	JRST TYOFND

TYOCR1:	PUSHJ P,TYORCR
	JRST TYOFND

;ALTMODE IOTTED - SHOULD WE OUTPUT DOLLARSIGN?
TYOALT:	MOVE B,TTYST2(I)
	TRNN R,%TJECH	;ECHO MODE => YES.
	 TLNN B,%TGIMG	;OUTPUT ALT IN ASCII MODE SAYS YES.
	  JRST TYOAL4
	JRST TYOAL1	;NO, OUTPUT AN ALTMODE, WHETHER IT PRINTS OR NOT.

TYOAL4:	TLNN H,%TOSAI	;IF ALTMODE IS A GRAPHIC, USE IT;
TYOAL3:	 MOVEI A,"$	;ELSE USE DOLLARSIGN.
	JRST TYONR0	;EITHER WAY IT'S A NORMAL PRINTING CHAR.

;IF ABOUT TO CHANGE PC PPR'S CURSOR POS WITHOUT PUTTING
;ANYTHING IN THE OUTPUT BUFFER THAT WILL CHANGE THE TTY'S
;REAL CURSOR POS THE SAME WAY, MUST DISASSOCIATE TTY'S
;CURSOR POS FROM THIS PC PPR. TTYLPS WILL THEN
;SAY WHERE THE TTY'S CURSOR WILL BE AFTER CHARS IN OUTPUT
;BUFFER ARE ALL OUTPUT.
TYOMVC:	HRLZ B,TPVP(TT)
	HRR B,TPHP(TT)
	MOVEM B,TTYLPS(I)
	SETCAM TT,TTYLPP(I) ;TTY NO LONGER ASSOCIATED.
	POPJ P,

;BEFORE PUTTING ANYTHING IN OUTPUT BUFFER USING A PC PPR,
;TTY'S CURSOR MUST BE ASSOCIATED WITH PC PPR (THAT IS,
;THE TTY'S CURSOR MUST BE WHERE THE PC PPR'S CURSOR IS)
;WHEN A TTY IS ASSOCIATED WITH A PC PPR, TTYLPS
;IS NONSENSE, AND IT IS NECESSARY FOR OUPUT RTNS
;TO UPDATE PC PPR'S CURSOR IN ACCORDANCE WITH WHAT
;IS PUT IN THE OUTPUT BUFFER.
;THIS ROUTINE ASSOCIATES TTY IN I WITH PC PPR IN TT.
TYOASS:	TRNE R,%TJHDE
	 POPJ P,
	PUSH P,A
	HLRZ T,TTYLPS(I) ;CURRENT VERTICAL POS
	HRRZ A,TTYLPS(I) ;CURRENT HORIZONTAL POS
	CAMN T,TPVP(TT) ;IF CURSOR IS WHERE WE WANT IT,
	 CAME A,TPHP(TT)
	  AOSA A
	   JRST TYOAS3	;JUST SAY WE'RE ASSOCIATED.
	SKIPGE TTYLPS(I)
	 BUG		;TTY ALREADY ASSOCIATED WITH A PC PPR?
	CAMN T,TPVP(TT)	;SEE IF JUST MOVING ONE SPACE TO THE RIGHT
	 CAME A,TPHP(TT)
	  JRST TYOAS6	;NO, NEED FULLY GENERAL CURSOR MOTION
	MOVEI A,%TDFS	;SAVE BUFFER SPACE IN THIS COMMON CASE
	TLNE H,%TOOVR
	 MOVEI A,40	;IF SPACE OVERPRINTS, IT IS BETTER THAN %TDFS SINCE FEWER CHARS 
	PUSHJ P,TYOOUT	;IF SENT TO A SOFTWARE TTY OVER HARDWARE LINE.
	JRST TYOAS3

TYOAS6:	MOVEI A,%TDMV0	;TELL THE TTY TO PUT ITS CURSOR
	TLNE H,%TOMVU
	 JRST TYOAS7
	MOVEI A,%TDMOV
	PUSHJ P,TYOOUT	;WHERE THIS PC PPR WANTS IT.
	HLRZ A,TTYLPS(I)
	PUSHJ P,TYOOUT
	HRRZ A,TTYLPS(I)
TYOAS7:	PUSHJ P,TYOOUT
	MOVE A,TPVP(TT)
	CAML A,TCMXV(I)	;ATTEMPT TO GO BELOW SCREEN BOTTOM?
	 BUG
	PUSHJ P,TYOOUT	;AND THE NEW POSITION.
	MOVE A,TPHP(TT)
	PUSHJ P,TYOOUT
TYOAS3:	MOVEM TT,TTYLPP(I) ;TELL TTY IT IS ASSOCIATED.
	SETOM TTYLPS(I)
	JRST POPAJ

TYOAS5:	PUSH P,A	;REGARD TTY AS ASSOCIATED WITHOUT ACTUALLY
	JRST TYOAS3	;MOVING ITS CURSOR.

;FORCE OUT BUFFERED CURSOR MOTION.
;CALL ONLY IF TTY DISSOCIATED, FROM M.P. OR CLOCK LEVEL.
;H MUST BE SET UP ALREADY
TYOFRC:	MOVE Q,TOIP(I)
	PUSHJ P,TYOASS
	JRST TYOFN2

;PUT CHAR IN OUTPUT BFR (BUT IT DOESN'T BECOME VISIBLE
;TO INT. LEVEL UNTIL WE FINALIZE - IN CASE WE PCLSR)
TYOOUT:	TRNE R,%TJHDE
	 POPJ P,
TYOOU1:	CAMN Q,TOBEP(I)		;Going to deposit past end of buffer?
	 MOVE Q,TOBBP(I)	; Yes, make wrap around instead.
	HRRZI T,(Q)		;Get addr part of the buffer pointer.
	CAILE T,@TOBEP(I)	;Reasonable buffer pointer?
				;  CANT HAVE BEEN DUE TO 11 DOWN
	 BUG HALT,[TTY: OUTPUT BUFFER POINTER PAST END OF BUFFER]
	IDPB A,Q		;Stuff char into output buffer.
IFN N11TYS, TRNN H,%TP11T	;TV-11 ttys dont have TORM.
	 SOSL TORM(I)		; One less space available in buffer.
	  POPJ P,
	BUG HALT,[TTY: OUTPUT BUFFER OVERFLOWED, TYOWNC IS TOO SMALL]

;FINALIZE, UPDATING TOIP, TORM AND FLAGS.
;ALSO RESET Q FOR ANOTHER BUNCH OF OUTPUT.
TYOFNX:	;FINALIZE WHEN TTY DISSOCIATED AND NOTHING PUT IN BFR.
TYOFND:	;SIMILAR, WHEN SOMETHING MIGHT HAVE BEEN PUT IN BFR.
TYOFNA:	;FINALIZE WHEN TTY ASSOCIATED W/ PC PPR.
TYOFN2:	MOVEM Q,TOIP(I)
	AOSN TTYOAC(I)	;START THE TTY.
	 XCT TTYST(I)
	JRST TYOFNR

;ON ORDINARY TTY, CALL WHEN BUFFER FULL.
;WAIT TILL AT LEAST 3/4 EMPTY. T HAS MINIMUM # CHARS NEEDED.
;IF RUNNING SYS JOB, POP1J IF TTY SEEMS TO BE HUNG.
TYOW1:	CAIGE T,TOBS*3/4	;DON'T UNBLOCK TILL BUFFER AT LEAST 3/4 EMPTY.
	 MOVEI T,TOBS*3/4
TYOW2:	MOVEM I,EPDL3(U)	;MAY TRAP OUT ON SYSTEM JOB
	CAME U,USER
	 BUG
	JUMPN U,TYOW4
	JRST TYOW5	;HANG UP SYS JOB FOR MAX OF 5 SEC

	PUSHJ P,TYOW6
TYOW5:	 PUSHJ P,UFLS
	MOVE T,TTYCOM(I)
	TLNE T,%TCHNG
	 SUB P,[1,,1]	;TIMED OUT
	POPJ P,

	CAMLE T,TORM(I)
TYOW4:	 PUSHJ P,UFLS
	POPJ P,

TYOW6:	MOVE A,AC0S+U(U)	;(IN CASE U DIDN'T EQUAL USER AT TYOW1)
	MOVE A,EPDL3(A)		;IF SYS JOB, FLUSH IF NO CHR PROCESSED FOR 15 SEC
	MOVE Q,TTYTYP(A)
	SKIPL TTOALC(A)		;TIME OUT ON SOFTWARE TTY'S WITHOUT ALLOCATION.
	 JRST TYOW6A		;IF THIS IS A PDP-11 TV,
	TRNE Q,%TY11T		;TEST FOR ROOM IN BUFFER IS DIFFERENT ON TV'S
	 JRST TYOW7
	CAMG T,TORM(A)		;FOR NON-TV'S, TORM IS VALID.
	 JRST TYOW6B		;THERES ROOM NOW
TYOW6A:	MOVSI T,%TCHNG
	MOVE Q,TIME
	SUB Q,TTLTM(A)
	CAIG Q,5.*30.
	 JRST TYOW6C		;NO NEW TIMEOUT YET
	IORM T,TTYCOM(A)	;MARK THIS TTY AS HUNG FOR SYS JOB
	JRST POPJ1

TYOW6C:	CAILE Q,3
	 TDNN T,TTYCOM(A)	;SKIP ON CONSOLE WAS LOSING RECENTLY
	  POPJ P,
	JRST POPJ1		;TIME OUT MUCH SHORTER IF CONSOLE DETERMINED TO BE A LOSER

TYOW7:	LDB Q,T
	CAIE Q,1_TT11BY-1
	 JRST TYOW6A
TYOW6B:	MOVSI T,%TCHNG		;GET HERE WHEN ROOM EXISTS IN BUFFER
	ANDCAM T,TTYCOM(A)	;ITS NOT HUNG NOW
	JRST POPJ1

IFN N11TYS,[
;ON A PDP-11 TV, CALL HERE TO WAIT UNTIL THERE ARE AT LEAST
;TYOWNC CHARS OF SPACE IN THE OUTPUT BUFFER.
;CAN POP1J FOR THE SYS JOB.
TYOWN:	PUSHJ P,TYOWN1
	LDB B,T		;IS THE POS. 20. CHARS UP VACANT?
	CAIN B,1_TT11BY-1
	 POPJ P,	;YES, NO NEED TO WAIT.
	JUMPN U,TYOWN2	;IF SYS JOB, TIME OUT BEFORE TOO LONG.
	MOVEM I,EPDL3(U)
	MOVE B,TIME
	MOVEM B,TTLTM(I)
	JRST TYOW5

TYOWN2:	PUSH P,A	;SEEMS TO BE NO SPACE, CHECK AGAIN
	MOVE B,(T)	;DOING THINGS IN THE RIGHT ORDER THIS TIME
	LDB A,T		;TO AVOID GETTING HUNG BY A TIMING ERROR
	CAIN A,1_TT11BY-1
	 JRST POPAJ	;SOME SPACE APPEARED IN THE MEANTIME
	POP P,A
	EXCH B,T
	CAMN T,(B)	;WAIT FOR THIS WORD TO CHANGE
	 PUSHJ P,UFLS
	JRST TYOWN	;THEN CHECK IT AGAIN

TYOWN1:	MOVE T,TOIP(I)
	ADDI T,TYOWNC/<36./TT11BY>
	HRRZ B,TOBEP(I)
	CAIGE B,(T)
	 SUB T,TT11OL
	HRLI T,040000+TT11BY_6	;BP TO WHOLE OF RIGHTMOST BYTE IN WORD
	POPJ P,
]

;COME HERE WHEN DETECT THAT %TFEOP OR %TFIGL IS SET.
TYOIGL:	TRZN B,%TFIGL	;%TFIGL TAKES PRIORITY.
	 JRST TYOEOP
	MOVEM B,TPFLAG(TT) ;CLEAR IT, AND IGNORE THIS CHAR
	CAIE A,^J
	 JRST TYOIG1
	POPJ P,

;%TFEOP IS SET AND OUTPUT IS DONE: DO **MORE** PROC.
TYOEOP:	PUSH P,[TYOEO9]
	PUSH P,A
TYOEO5:	SKIPE USER	;DON'T DO MORES IF SYSTEM JOB IS TYPING
	 TRNE R,%TJMOR+%TJECH	;OR THIS CHANNEL DOESN'T WANT TO
	  JRST TYOEO7
	MOVSI B,%TSMOR
	TDNE B,TTYSTS(I)	;OR THIS JOB DOESN'T WANT TO
	 JRST TYOEO7
	HRRZ B,TTYSTS(I)	;DON'T **MORE** AN $$^P'ED JOB'S OUTPUT
	CAME B,U
	 JRST POPAJ
	MOVE B,TCMXV(I)	.SEE TPVE;(TT)
	MOVEM B,TPVM(TT)
	HRRZ B,UUAC(U)	;GET INTERRUPT BIT FOR CHANNEL THIS IOT IS ON
	MOVE B,CHNBIT(B)
	AND B,MSKST2(U) ;HAS USER ENABLED OUTPUT INTERRUPT?
	JUMPE B,TYOEO1	;NO, SYSTEM DOES **MORE** PROC.
	IORM B,IFPIR(U)	;YES, JUST GIVE USER INT
	MOVEI B,%TFEOP	;HE CAN TYPE **MORE** IF HE WANTS TO.
	ANDCAM B,TPFLAG(TT) ;INT. HAS BEEN GIVEN.
	PUSHJ P,TYOUN1	;LSWPOP THE FINSET, ETC.
	SKIPA
	 SKIPA
	 PUSHJ P,UFLS	;MAKE HIM TAKE THE INT. RIGHT NOW.
TYOEO6:	PUSHJ P,LSWCLR
	SOS UUOH	;HIS PICLR IS SET? RETRY THE UUO.
	JRST URET

TYOEO7:	MOVEI B,%TFEOP	;MORE SUPPRESSED, TURN OFF THE FLAG
	ANDCAM B,TPFLAG(TT)
	JRST POPAJ

;COME HERE AT END OF PAGE IF PROGRAM ISN'T SMART.
TYOEO1:	PUSH P,TPHP(TT)
	MOVE A,TPHP(TT)
	ADDI A,10
	CAML A,TCMXH(I)
	 PUSHJ P,TYORCR
	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOASS
	IRPC X,,**MORE**
	MOVEI A,"X
	PUSHJ P,TYONR1
	TERMIN		;OUTPUT THE STRING "**MORE**"
	IORI R,%TJSTP	;MAKE ALL OUTPUT ON THIS CHNL HANG.
	MOVEI B,%TFEOP	;NO LONGER WANT NEXT CHAR TO DO **MORE**
	ANDCAM B,TPFLAG(TT)
	POP P,A		;REMEMBER VALUE TO RESET HPOS TO LATER.
	HRLM A,TPFLAG(TT)
	PUSHJ P,TYOFNA	;FINALIZE SO "**MORE**" WILL TYPE OUT;
	 ;PCLSRING NO PROBLEM; SINCE %TJSTP IS SET THE IOT
	 ;WILL COME TO TYOEO3.
TYOEO3:
IFN N11TYS,[
	TRNE H,%TP11T	;WAIT FOR BUFFER SPACE ON TV.
	 PUSHJ P,TYOWN	;NOTE THIS CAN POP1J
]
	PCLT
	MOVEI T,TOBS	;WAIT FOR ALL OF "**MORE**" TO GET OUT.
	CAME T,TORM(I)
	 PUSHJ P,TYOW1
	PUSH P,C
	PUSH P,D
	PUSH P,R
	PUSH P,TT
	MOVEI R,%TIPEK+%TIACT+%TIECH+%TINWT
	PUSHJ P,TYI0	;LOOK AHEAD AT NEXT INPUT CHAR.
	JUMPL D,TYOEO6	;IS NONE => RETRY UUO AND WAIT IN TYOSET.
	EXCH TT,(P)
	EXCH R,-1(P)
	MOVE Q,TOIP(I)
	MOVE C,TTYSTS(I)
	TLNE C,%TSROL	;IN SCROLL MODE, MAKE NEXT LINE OF OUTPUT OVERWRITE **MORE**.
	 JRST [	PUSHJ P,TYORCR
		PUSHJ P,TYOCEL
		SOS TPVM(TT)	;MORE AGAIN BEFORE THIS LINE GOES OFF SCREEN
		JRST TYOEO4]
	TRZN R,%TJCP1	;UNLESS THIS IS ^PN
	 PUSHJ P,TYOHD1	;HOME UP (BY HOMING DOWN AND LF'ING)
	PUSHJ P,TYOLF	;OTHERWISE (FOR ^PN) JUST LF.
TYOEO4:	CAMN TT,TTYLPP(I)
	 PUSHJ P,TYOMVC	;PREPARE FOR CURSOR MOTION.
	HLRZ A,TPFLAG(TT) ;SET HPOS TO WHAT IT WAS BEFORE THE **MORE**.
	MOVEM A,TPHP(TT)
	HRRZS TPFLAG(TT)
	EXCH TT,(P)
	EXCH R,-1(P)
	ANDI D,177
	CAIE D,177
	 CAIN D,40	;IF A SPACE, FLUSH IT FROM INPUT BFR
	  PUSHJ P,TYIREM
	POP P,TT
	POP P,R
	POP P,D
	POP P,C
	ANDCMI R,%TJSTP	;RETURN CHANNEL TO NORMAL.
	MOVE Q,TOIP(I)
	PUSHJ P,TYOFNR
	POP P,A		;RESTORE THE CHAR BEING IOTTED
	POPJ P,		;AND TRY AGAIN TO IOT IT.

TYOEO2:	PUSH P,[TYOEO9]
	PUSH P,A	;COME HERE IF PCLSR OUT OF TYOEO3, ETC.
	JRST TYOEO3	;WHEN THE IOT IS RETRIED.

TYOCP1:	TRZE R,%TJINK	;IF THIS IS THE CHAR AFTER A ^PI, TREAT IT AS
	 JRST TYONR3	;NORMAL PRINTING CHARACTER.
	TRNE R,%TJSTP
	 JRST TYOEO2	;CHANNEL HUNG IN **MORE**.
;HANDLE CURSOR CONTROL CODES. COME HERE WITH IOTTED CHAR IN A.
;IF WE ARE IN THE MIDDLE OF A ^P CODE.
;OR IF THE CHANNEL IS A SUPERIMAGE OUTPUT CHANNEL.
	TRZE R,%TJCP2	;AFTER A ^PV OR ^PH ?
	 JRST TYOCP2
	TRZN R,%TJCP1	;NO, NEXT CHAR ISN'T IN THE ^P CODE.
	 JRST TYOSIO	;MUST BE %TJSIO THAT WAS SET.
TYOCP4:	CAIL A,"A	;IF ^P CODE IS A LETTER,
	CAILE A,"_
	 JRST TYOCP3
	MOVE B,TYOCPT-"A(A) ;GET THE DISPATCH ENTRY FOR IT,
	TLNN H,%TOMVU
	 JUMPL B,TYOCPA	    ;TURN SOME CURSOR OPERATIONS INTO CRLF ON PRINTING TTY
	TLNE B,200000
	 PUSH P,[TYOCPR]    ;SOME OPERATIONS RETURN HERE FOR FINALIZATION
	JRST (B)	;FINALLY, DISPATCH

TYOCPR:	MOVEI B,%TFEOP
	ANDCAM B,TPFLAG(TT)
	JRST TYOFNX

TYOCP3:	CAIL A,140	;LOWERCASE LETTERS ACT LIKE UPPERCASE
	 JRST [	SUBI A,40
		JRST TYOCP4]
	HRLM R,@TYOPV2(J)
	PUSHJ P,TYOUN1	;OR IT'S ILLEGAL.
	JRST IOCR11	;IOC ERROR.

TYOCPV:	IORI R,%TJCP1	;HERE FOR ^PV
TYOCPH:	IORI R,%TJCP2	;SAME FOR ^PH. SAY NEXT CHAR IS THE CURSOR POS.
TYOFNR:	HRLM R,@TYOPV2(J)
	POPJ P,

TYOCP2:	CAMN TT,TTYLPP(I) ;INTERPRET THE CHAR AFTER ^PH OR ^PV.
	 PUSHJ P,TYOMVC
	ANDI A,177
	TRZN R,%TJCP1	;WHICH OF THOSE 2 WAS IT?
	 JRST TYOCH1	;IT WAS ^PH
	ADD A,TPVB(TT)
	SUBI A,10
	CAML A,TCMXV(I) .SEE TPVE;(TT)	;DON'T PUT CURSOR PAST END.
	 JRST [	MOVE A,TCMXV(I) .SEE TPVE;(TT)
		SOJA A,.+1]
	CAMGE A,TPVB(TT)	;OR BEFORE BEGINNING.
	 MOVE A,TPVB(TT)
	MOVEM A,TPVP(TT)
	JRST TYOCPR

TYOCH1:	.SEE ADD A,TPHB;(TT)
	SUBI A,10
	CAML A,TCMXH(I) .SEE TPHE;(TT)	;DON'T PUT CURSOR PAST END.
	 JRST [	MOVE A,TCMXH(I) .SEE TPHE;(TT)
		SOJA A,.+1]
	SKIPGE A	.SEE TPHB;(TT)	;OR BEFORE BEGINNING.
	 SETZ A,	.SEE TPHB;(TT)
	MOVEM A,TPHP(TT)
	JRST TYOCPR

;DISPATCH TABLE FOR ^P CODES.
;SIGN => TURN INTO ^PA ON PRINTING TTY.
;4.8 => PUSHJ, ELSE JRST
TYOCPT:		TYOCPA	;A - ADVANCE TO FRESH LINE.
	200000,,TYOMVB	;B - MOVE BACK.
		TYOCLR	;C - CLEAR SCREEN.
	200000,,TYOMVD	;D - MOVE DOWN.
		TYOCEF	;E - CLEAR TO END OF SCREEN.
	200000,,TYOMVF	;F - MOVE FORWARD.
		TYOCP3	;G - ILLEGAL.
		TYOCPH	;H - NEXT CHAR IS DESIRED HPOS.
		TYOCPI	;I - NEXT CHARACTER TREATED AS NORMAL PRINTING.
		TYOCP3	;J - ILLEGAL.
	200000,,TYODLF	;K - DELETE FORWARD.
		TYOCEL	;L - CLEAR REST OF LINE.
		TYOMOR	;M - DO **MORE**.
		TYOMO1	;N - SIMILAR BUT DON'T HOME UP.
		TYOCP3	;O - ILLEGAL.
		TYOCPP	;P - TYPE "^P".
		TYOCPQ	;Q - TYPE "^C".
	600000,,TYORPS	;R - RESTORE SAVED POS.
	200000,,TYOSPS	;S - SAVE POSITION (FOR A ^PR).
	600000,,TYOHMU	;T - HOME UP.
	200000,,TYOMVU	;U - MOVE UP.
		TYOCPV	;V - NEXT CHAR IS DESIRED VPOS.
		TYOCP3	;W - ILLEGAL.
	200000,,TYODLB	;X - DELETE BACKWARDS.
		TYOCP3	;Y - ILLEGAL.
	600000,,TYOHMD	;Z - HOME DOWN.
	200000,,TYOILP	;[ - INSERT LINE POSITION
	200000,,TYODLP	;\ - DELETE LINE POSITION
		TYOCEL	;] - CLEAR TO END OF LINE (USE ^PL IT'S BETTER)
	200000,,TYOICP	;^ - INSERT CHARACTER POSITION
	200000,,TYODCP	;_ - DELETE CHARACTER POSITION
IFN .-31.-TYOCPT,.ERR WRONG LENGTH TABLE.

;^PM AND ^PN DON'T WORK IN PROGRAMS THAT TAKE **MORE**
;INTERRUPTS - OR, PRECISELY, THEY ALWAYS ENTER
;THE STATE OF A CHANNEL THAT HAS JUST TYPED OUT "**MORE**".
TYOMO1:	IORI R,%TJCP1	.SEE TYOEO3	;^PN - ENTER **MORE** STATE.
TYOMOR:	IORI R,%TJSTP			;^PM.
	HRRZS TPFLAG(TT)
	JRST TYOFNR

TYOCPI:	IORI R,%TJINK
	JRST TYOFNR

;INSERT AND DELETE CHARACTERS AND LINES
TYOILP:	SKIPA A,[%TDILP]
TYODLP:	 MOVEI A,%TDDLP
	TLNN H,%TOLID
	 POPJ P,
	PUSH P,A		;SUPPOSED TO BE AT LEFT MARGIN
	PUSHJ P,TYORCR		;MAKE SURE
	POP P,A
	JRST TYOIL1

TYOICP:	SKIPA A,[%TDICP]
TYODCP:	 MOVEI A,%TDDCP
	TLNN H,%TOCID
	 POPJ P,
TYOIL1:	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOASS
	PUSHJ P,TYOOUT
	MOVEI A,1	;SUPPLY PARAMETER OF 1
	JRST TYORU1	;IF YOU WANT TO OPTIMIZE CONSECUTIVE ONES
			; USE SUPER-IMAGE OUTPUT, AT LEAST FOR NOW

;RTNS FOR VARIOUS ^P CODES.
;THE FIRST FOUR DON'T FINALIZE ANYTHING.
TYOMVF:	CAMN TT,TTYLPP(I) ;^PF
	 PUSHJ P,TYOMVC	;PREPARE FOR CURSOR MOTION.
	AOS B,TPHP(TT)
	CAMGE B,TCMXH(I) .SEE TPHE;(TT)
	 POPJ P,
	;SETZ A,	.SEE TPHB;(TT)	;WRAP AROUND FROM LAST POS. TO FIRST.
	SETZM TPHP(TT)
TYOMVD:	CAMN TT,TTYLPP(I) ;^PD
	 PUSHJ P,TYOMVC	;PREPARE FOR CURSOR MOTION.
	AOS B,TPVP(TT)
	MOVE A,TPVB(TT)
	CAIGE B,119.
	CAML B,TCMXV(I)	.SEE TPVE;(TT)	;WRAP AROUND FROM LAST POS. TO FIRST.
	 MOVEM A,TPVP(TT)
	POPJ P,

TYOMVB:	CAMN TT,TTYLPP(I)	;^PB - MOVE BACK.
	 PUSHJ P,TYOMVC
	SOSL B,TPHP(TT)	.SEE TPHB;(TT)
	 POPJ P,
	MOVE A,TCMXH(I)	.SEE TPHE;(TT)	;WRAP AROUND FROM FIRST TO LAST.
	SUBI A,2
	MOVMM A,TPHP(TT)
TYOMVU:	CAMN TT,TTYLPP(I)	;^PU - MOVE UP.
	 PUSHJ P,TYOMVC
	SOS B,TPVP(TT)
	MOVE A,TCMXV(I)	.SEE TPVE;(TT)	;WRAP AROUND FROM FIRST TO LAST.
	SUBI A,1
	CAIL A,119.
	 MOVEI A,118.
	CAMGE B,TPVB(TT)
	 MOVEM A,TPVP(TT)
	POPJ P,

TYOSPS:	MOVE B,TPHP(TT)	;^PS - SAVE CURSOR POS.
	HRL B,TPVP(TT)
	MOVEM B,TPSP(TT)
	POPJ P,

TYORPS:	CAMN TT,TTYLPP(I) ;^PR - RESTORE CURSOR POS FROM SAVED.
	 PUSHJ P,TYOMVC
	MOVE B,TPSP(TT)
	HRRZM B,TPHP(TT)
	HLRZM B,TPVP(TT)
	POPJ P,

TYOCPA:	CAMN TT,TTYLPP(I) ;ADVANCE TO FRESH LINE, IN ANY CASE CLEAR REST OF LINE
	 PUSHJ P,TYOMVC
	SKIPE TPHP(TT)	;IF NOT AT THE BEGINNING OF A LINE,
	 JRST TYOCRL	;CRLF.  MAYBE SOMEDAY THIS WILL CHECK
	JRST TYOCEL	;WHETHER ANYTHING HAS YET BEEN TYPED ON THIS LINE.

TYOCLR:	TLNN H,%TOMVU	;^PC - CLEAR SCREEN.
	 JRST [	MOVE A,TCMXV(I)	;ON PRINTING TTYS, JUST CRLF.
		SUB A,TTYROL(I)	;BUT DON'T --MORE-- UNTIL THIS LINE
		MOVEM A,TPVM(TT);GOES OFF THE SCREEN
		JRST TYOCRL ]
	SKIPN TPVB(TT)	;USE FAST METHOD IF REALLY CLEARING WHOLE SCREEN
	 JRST TYOCIM
TYOCI1:	PUSHJ P,TYOHMU
TYOCEF:	SKIPA A,[%TDEOF] ;^PE CLEAR EOF
TYOCEL:	 MOVEI A,%TDEOL	;[  ^P] - CLEAR EOL.
	TLNN H,%TOERS
	 JRST TYOFNR
TYONMV:	CAME TT,TTYLPP(I) ;HERE FOR CHARS THAT DON'T MOVE THE CURSOR
	 PUSHJ P,TYOASS	;BUT DO DEPEND ON BEING PRINTED AT THE RIGHT PLACE ON THE SCREEN
TYORU1:	PUSHJ P,TYOOUT
	JRST TYOFNA

TYOCIM:	PUSHJ P,TYOHMU	;CLEAR WHOLE SCREEN
	MOVEM TT,TTYLPP(I)
	SETOM TTYLPS(I)
	MOVEI A,%TDCLR
	JRST TYONMV

TYOHMU:	SETZM TPVM(TT)	;^PT - HOME UP
	CAMN TT,TTYLPP(I)
	 PUSHJ P,TYOMVC	;GO TO COLUMN 0,
	MOVE B,TPVB(TT)	;LINE 0.
	MOVEM B,TPVP(TT)

TYORCR:	TLNE H,%TORAW 	;GO TO COLUMN 0 -  CR IN IMAGE MODE.
	 JRST [	CAME TT,TTYLPP(I)
		 PUSHJ P,TYOASS	;NO OPTIMIZATION =>
		SETZM TPHP(TT)
		MOVEI A,%TDRCR	;ARRANGE TO SEND REAL CR.
		PUSHJ P,TYONCC
		JRST TYOMVC]
	CAMN TT,TTYLPP(I)
	 PUSHJ P,TYOMVC		;ELSE DO CURSOR-MOTION.
	SETZ B,	.SEE TPHB;(TT)
	MOVEM B,TPHP(TT)
	POPJ P,

TYOHMD:	PUSHJ P,TYORCR	;^PZ - HOME DOWN.
TYOHD1:	MOVE B,TCMXV(I)	.SEE TPVE;(TT)
	SUBI B,1
	CAIGE B,119.
	 MOVEM B,TPVP(TT)
	POPJ P,

TYODLB:	SKIPN TPHP(TT)	;^PX - DELETE BACKWARD.
	 PUSHJ P,.+1	;IN COLUMN 0, DO IT TWICE SO AS TO ERASE THE "!" AND CHAR BEFORE IT
	PUSH P,TPHP(TT)
	PUSHJ P,TYOMVB
	POP P,B
	SKIPN B
	 AOS TPHP(TT)	;IF WRAPPED AROUND, SET TO TCMXH-1
TYODLF:	MOVE B,TPHP(TT)	;^PK - ERASE 1 CHARACTER.
	CAML B,TCMXH(I)	.SEE TPHE;(TT)	;DO NOTHING AT END OF LINE.
	 POPJ P,
	TLNE H,%TOOVR	;IF CAN'T OVERPRINT, USE SPACE TO ERASE
	 JRST [	TLNN H,%TOERS
		 POPJ P,	;OTHERWISE, USE SPECIAL CONTROL SEQUENCE IF KNOWN
		MOVEI A,%TDDLF
		JRST TYONMV ]
	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOASS
	AOS TPHP(TT)
	MOVEI A,40		;USE REALLY SPACE, NOT CURSOR MOTION!
	PUSHJ P,TYOOUT
	PUSHJ P,TYOMVB		;THEN BACKSPACE OVER IT
	JRST TYOFNX

SUBTTL .STATUS AND IOPDL FOR TTY

;2.4 HAS "TTY"
;2.3 DDT MODE ON INPUT
;(STATYI);2.5 CHRS HAVE BEEN ITYI'ED BUT NOT .IOT'ED (STATYI)
	;2.8 TELETYPE NEXT TO 340 OR 340 SLAVE
	;2.9  TELETYPE IS LOCAL, NOT DIAL IN

STATYO:	ANDI A,77
	CAIN A,%TINON	;IF CHANNEL HAS NO REAL TTY,
	 POPJ P,	;THERE ARE NO SPECIFICS WE CAN SAY.
	SKIPN B,TORM(A)
	TRO D,1_9.	;BUF CAP FULL
	CAIN B,TOBS
	TRO D,1_<9.+1>	;BUFFER CAP EMPTY
STATY1:	SKIPL TTYTBL(U)
	TRO D,1_<9.+3>	;HAS TTY
	IORI D,SNTTY
	MOVE H,TTYOPT(A)
	TLNE H,%TOERS
	 TRC D,SNTTY#SNTDS
	POPJ P,

STATYI:	ANDI A,77
	CAIN A,%TINON	;CATCH "DISOWNED" TTY CHNLS.
	 POPJ P,
	TRO D,1_<9+1>	;ASSUME BUF CAP EMPTY
	SKIPN B,TICC(A)	;SEE IF THERE ARE ANY INPUT CHARACTERS
	 JRST STATY2	;NOT INCLUDING COM MODE ECHO
	MOVE E,TIOP(A)
STATY3:	CAMN E,TIBEP(A)
	 SUBI E,TIBL
	ILDB TT,E
	TLNN TT,%TXIGN
	 TRZA D,1_<9+1>	;INPUT SEEN, BUF CAP NOT EMPTY
	  SOJG B,STATY3
STATY2:	CAIL B,TIBS-10.
	 TRO D,1_9.	;BUF CAP NEARLY FULL
	LDB B,[400400,,TTYTYP(A)]	;GET LOCAL AND 340 MDS
	DPB B,[160400,,D]	;DEPOSIT IN STATUS WORD
	CONO PI,TTYOFF
	MOVE TT,TICC(A)
	CAMLE TT,TINTC(A)
	 TRO D,20000	;MORE CHRS HAVE BEEN ITYI'ED THAN .IOT'ED
	CONO PI,TTYON
	JRST STATY1

;TELETYPE IO PUSHDOWN ROUTINES

TYOIOP:	TDZA A,A		;OUUTPUT CHNL.
TYIIOP:	 MOVEI A,TYIMSK-TYOMSK	;INPUT CHNL, SET TYIMSK INSTEAD TYOMSK.
	CONO PI,CLKOFF	;TO PREVENT TELETYPE (IF CONSOLE) FROM MOVING AROUND
	JUMPGE B,TYIOP1	;JUMP IF OPEN AS DEVICE
	SKIPGE TTYTBL(U)	;IF PROCEDURE DOESN'T HAVE CONSOLE,
	 JRST CLKONJ	;THEN THAT'S ALL
TYIOP1:	LDB E,[$TIIDX,,B]	;GET TTY NUMBER IN E
	ADDI E,(A)		;IF INPUT, TYOMSK(E) WILL BE TYIMSK VAR.
	HRRZ R,UUAC(U)	;GET "AC FIELD" (IO PUSHDOWN ROUTINES RESTORE R)
	MOVE A,CHNBIT(R)	;GET RELEVANT CHANNEL INTERRUPT BIT
	XCT TYIOPT(I)	;IORM OR ANDCAM A TO TYOMSK(E)
	JRST CLKONJ	;RETURN

TYIOPT:	ANDCAM A,TYOMSK(E)	;IOPUSH (PSEUDO-CLOSE)
	IORM A,TYOMSK(E)	;IOPOP (PSEUDO-OPEN)

;STY IO PDL ROUTINES

STYOIP:	TDZA A,A
STYIIP:	 MOVEI A,STYMSK-STYOMS
	ADDI A,STYOMS-NFSTTY-TYOMSK
	JRST TYIOP1

SUBTTL TTY CLOSE ROUTINES

;INPUT CLOSE

TYICLS:	JSP E,TYCLOS	;IGNORE FOR DISOWNED CONSOLE
	ANDCAM B,TYIMSK(A)	;INDICATE CHANNEL CLOSURE
	JRST TYICL2

TYCLOS:	LDB I,[210100,,A]
	ANDI A,77	;THROW AWAY TOP BITS OF IOCHNM WD, GET TTY #.
	CAIN A,%TINON	;FOR A CHNL IN A TTYLESS TREE,
	 POPJ P,	;DON'T SOS ANYONE'S TTNTO.
	SKIPGE APRC(U)	;SKIP UNLESS DISOWNED
	 JUMPN I,[JRST 4,.] ;DISOWNED JOB HAS REAL CONSOLE TTY?
	SKIPGE TTYTBL(U);IF IT'S A CONSOLE AND THIS JOB DOESN'T
	 JUMPN I,TYICL2	;HAVE TTY, DON'T CHANGE TYIMSK OR TYOMSK.
	HRRZ R,UUAC(U)
	MOVE B,CHNBIT(R) ;GET THE BIT TO CLEAR IN TYIMSK OR TYOMSK.
	JRST (E)	;RETURN & CLEAR IT.

;OUTPUT CLOSE

TYOCLS:	JSP E,TYCLOS	;IGNORE FOR DISOWNED CONSOLE
	MOVE I,A
	SKIPE USER
	 PUSHJ P,TYOWC	;WAIT A WHILE FOR OUTPUT TO FINISH
	ANDCAM B,TYOMSK(A)	;SET OF OUTPUT CHNLS OPEN.
TYICL2:	SOSLE TTNTO(A)
	 POPJ P,		;MORE OPENS ON TTY
	SKIPE TTNTO(A)
	 BUG
	MOVE B,TTYSTS(A)
	TLNE B,%TSCNS
	 POPJ P,		;OPEN AS CONSOLE
	JRST TTYLO1

;WAIT FOR TTY OUTPUT BUFFER TO BE EMPTY,
;BUT TIME OUT IF TTY DOESN'T TYPE OUT FOR 5 SEC.
TYOWC:	MOVEM I,EPDL3(U) ;SAVE TTY # FOR TYOW5.
IFN N11TYS,[
	MOVE T,TTYTYP(I)
	TRNE T,%TY11T
	 POPJ P,
]
	MOVEI T,TOBS	;WAIT TILL OUTPUT BUFFER EMPTY
	PUSHJ P,TYOW5	;BUT DON'T WAIT TOO LONG.
	POPJ P,		;TYOW5 MAY POP1J.

;TTY # IN A - MAKE THE TTY FREE.
TTYLO1:	SETZM TTNTO(A)
	SETZM TYIMSK(A)
	SETZM TYOMSK(A)
	HRLOI B,%TSFRE
	IORB B,TTYSTS(A) ;SAY TTY FREE (BUT TTYSTA OFF SO CAN'T ^Z)
	PUSHJ P,TTYLFC	;REMOVE TTY FROM COM MODE AND
	PUSHJ P,TYIRS0	;RESET INPUT BUFFER
IFN TTLPTP,[
	CAMN I,LPTTTY	;IF TTY'S THE LPT, IT'S NOT IN USE.
	 SETOM LPTUSR
]
	MOVE T,TTYTYP(I)
	TRNN T,%TYSTY
	 PUSHJ P,TTYIN1	;RE-INIT USER OPTIONS
	TRNE T,%TYDIL\%TYRLM	;DIALUP LINE => MAKE IT PRINTING.
	 TRNE T,%TYMDM	;UNLESS WE CAN DETECT DISCONNECTS, IN WHICH CASE DO IT THEN.
	  CAIA
	   PUSHJ P,NCNSSP
IFN N11TYS,[
	TRNE T,%TY11T
	 PUSHJ P,NCNSST
]
	MOVEI B,SCRCFM
	SKIPL TTYSTA(I)
	 IORM B,SUPCOR	;REQUEST A CONSOLE-FREE MESSAGE.
	MOVE A,I	;IN CASE OUR CALLER WANTS TTY # IN A.
	POPJ P,

IFN N11TYS,[
TTYLO2:	MOVE B,TTYTYP(A) ;TTY BEING CLOSED & CNSL FREE MSG NOT NEEDED,
	SKIPGE TT11P	;IF IT'S A PDP11-TV TTY
	 TRNN B,%TY11T
	  POPJ P,
	MOVE I,A	;MAKE ALL JOBS CEASE TO HACK THIS SCREEN
	PUSHJ P,NTVWH1	;B := VIDEO BUFFER NUMBER
	 BUG
	SETZ A,
TTYLO3:	LDB C,[$11BY0,,TVCREG(A)] ;VIDEO BUFFER HACKED BY THIS JOB OR 377
	CAMN C,B
	 SETOM TVCREG(A) ;IF JOB HACKING THIS VIDEO BUFFER, MAKE IT STOP.
	ADDI A,LUBLK
	CAMGE A,USRHI
	 JRST TTYLO3
	MOVE B,TT11HD	;TELL THE 11 THE TTY IS FREE.
	ADDI B,1-NF11TY(I)
	ADD B,TT1111
	HRROI T,-1_4+10	;SET TTY'S PHYSLC WORD TO -1.
	MOVEM T,(B)
	MOVE T,TOBBP(I)	;RESET OUTPUT BUFFER POINTER TO BEGINNING OF
	MOVEM T,TOIP(I)	; BUFFER.  THE 11 DOES ALSO.
	POPJ P,
]

;REMOVE A TTY FROM COM MODE IF IT IS COM MODE.
;CALLED WHEN TTY BECOMES FREE, ETC.
;TAKES TTY # IN A; LEAVES IT IN A AND I.
TTYLFC:	HRRZ I,A
	CONO PI,TTYOFF
	SKIPL Q,TTYCOM(I)
	 JRST TTLFC1
	PUSH P,I
	PUSH P,U
	PUSHJ P,TYCSET
	TLZ Q,%TCCBK+%TCTPN+%TCCBS
	MOVEM Q,TTYCOM(I)	;FLUSH COM MODE TEMP FLAGS.
	PUSHJ P,TYCGTM		;REMOVE THE TTY FROM COM LINKS.
	POP P,U
	POP P,I
TTLFC1:	MOVE A,I
	MOVEI B,TTYI
	MOVEM B,TTYIPC(A)
	POPJ P,

SUBTTL TTY RESET ROUTINES

;TTY INPUT RESET

TYIRS:	PUSHJ P,TTYWR
	 POPJ P,		;IGNORE IF WE DON'T OWN THE TTY.
TYIRS0:	MOVSI T,%TCLFT+%TCICO
	PUSHJ P,TTYCMW		;MAYBE WAIT FOR COM LINK TO FINISH.  RETURN WITH TTYCHN OFF.
	PUSHJ P,TYIRS1		;DISCARD THE INPUT.
	JRST TTYONJ

;; DISCARD THE CONTENTS OF THE TTY INPUT BUFFER.  TTY NUMBER IN I.
TYIRS1:	MOVE B,TIIP(I)		;Get input pointer.
	MOVEM B,TIOP(I)		;Bash output ptr to it.
	MOVEM B,TINTP(I)	;Bash interrupt-peeked ptr to it.
	MOVEM B,ECHOP(I)	;Bash echo ptr to it.
	SETZM ECHOC(I)		;Nothing to echo.
	CLEARM TICC(I)		;Nothing has been input.
	CLEARM TACC(I)		;No activation chars either.
	CLEARM TINTC(I)		;Nothing to ITYIC either.
	POPJ P,

;OUTPUT RESET

TYORS:	PUSHJ P,TTYWR	;CHECK FOR OWNING TTY.  TTY NUMBER IN I.
	 POPJ P,	;NON-SKIP MEANS NO; IGNORE THE .RESET.
	SKIPL TTOALC(I)
	 PUSHJ P,UFLS
	MOVSI T,%TCLFT+%TCOCO+%TCICO+%TCFPD	;ALSO WAIT FOR OUTPUT SEQ TO FINISH.
	PUSHJ P,TTYCMW	;HANG UNTIL OUT OF COM MODE, OR OVER-RIDDEN. MAY UTCOFF.
	MOVSI B,%TJCP1+%TJCP2+%TJSTP	;IF LAST CHAR THIS CHNL WAS ^P,
	ANDCAM B,(R)	;FORGET IT. ALSO UNHANG CHANNEL FROM **MORE**.
	MOVE TT,I
	IMULI TT,TPLEN*2
	MOVEI B,%TFEOP+%TFIGL ;RESTORE BOTH PCS OF PPR TO NORMAL STATE.
	ANDCAM B,TPFLAG(TT)
	ANDCAM B,TPFLAG+TPLEN(TT)
	MOVE B,TTYOPT(I) ;IS OUTPUT RESET SUPPOSED TO DO SOMETHING?
	TRNN B,%TPORS	;(ON FAST TTYSS IT DOESN'T)
	 JRST UTCONJ
	MOVE B,TTYCOM(I)
	TLNE B,%TCECH
	 JRST UTCONJ
TYORS1:	MOVE B,TOOP(I)	;SCAN BACKWARD 4 CHARS FROM TOOP TO SEE IF A %TDMOV
	MOVEM B,TOIP(I)
	MOVEI TT,TOBS-4	;HAS BEEN PARTIALLY REMOVED FROM THE BUFFER.
	MOVEM TT,TORM(I) ;TORM HAS THE RIGHT VALUE ASSUMING A %TDMOV APPEARS
			;JUST BEFORE TOOP - THE FIRST PLACE WE WILL LOOK FOR ONE.
TYORS4:	LDB T,B
	CAIE T,%TDMV0
	CAIN T,%TDMV1
	 JRST TYORS8
	CAIN T,%TDMOV	;IF ONE IS FOUND IN THOSE 4 CHARS, IT MUST EXTEND PAST TOOP,
	 JRST TYORS5	;SO TAKE TOOP AND INCREMENT IT TO GET NEW TOIP.
	IBP B		;DBP B - KNOWING THAT THERE ARE 4 BYTES/WORD.
	IBP B
	IBP B
	SUBI B,1
	CAMN B,TOBBP(I)
	 MOVE B,TOBEP(I)
	AOS TT,TORM(I)	;AS THE %TDMOV GETS FARTHER BACK, ITS REMNANT OCCUPIES LESS SPACE.
	CAIE TT,TOBS	;IF ITS REMNANT TAKES NO SPACE, FORGET ABOUT IT.
	 JRST TYORS4
	JRST TYORS6

TYORS8:	ADDI TT,2	;THIS REMNANT IS TWO CHARS LONG
	CAIL TT,TOBS
	 JRST [	MOVEI TT,TOBS
		MOVEM TT,TORM(I)
		JRST TYORS6 ]
	MOVEM TT,TORM(I)
TYORS5:	SUBI TT,TOBS	;TT GETS -<LENGTH OF REMNANT>
	MOVE B,TOOP(I)
TYORS7:	CAMN B,TOBEP(I)	;SCAN FORWARD FROM TOOP TO FIND END OF REMNANT
	 MOVE B,TOBBP(I)
	IBP B
	AOJL TT,TYORS7
	MOVEM B,TOIP(I)	;AND FLUSH FROM BUFFER ALL BUT THAT REMNANT.
;DROPS THROUGH
;DROPS IN
TYORS6:	MOVE B,TCTYP(I)	;IF A "SOFTWARE" TTY, SEND A %TDORS.
	CAIE B,%TNSFW
	 JRST [	MOVE B,TTYTYP(I)
		TRNN B,%TYSTY	;ELSE, ON A STY, IF %SSORS
		 JRST TYORS2
		MOVE B,STYSTS-NFSTTY(I)
		TLNN B,%SSORS
		 JRST TYORS2
		JRST .+1]	;THEN SEND %TDORS
	SOS TORM(I)
	MOVE B,TOIP(I)
	CAMN B,TOBEP(I)
	 MOVE B,TOBBP(I)
	MOVEM B,TOIP(I)	;CHECK FOR WRAP
	MOVEI B,%TDORS	;RESET CODE
	IDPB B,TOIP(I)
	PUSHJ P,TYORS2	;FINISH RESETTING, TURN TTYCHN BACK ON,
	AOSN TTYOAC(I)	;AND ACTIVATE INT. LEVEL, SO %TDORS WILL BE SENT.
	 XCT TTYST(I)	;(THIS MAY TURN TTYCHN OFF AND ON AGAIN).
	MOVE B,TTYOPT(I)
	TRNN B,%TPCBS	;ON SOFTWARE TTY WITH ^\ TURNED ON, STOP TYPEOUT AT M.P.
	 POPJ P,	;LEVEL UNTIL THE TTY SAYS WHAT ITS CURSOR POSITION IS NOW,
	HRRZS TTOALC(I)	;USING ^\^P... OR SCPOS
	POPJ P,

TYORS2:	SKIPGE TT,TTYLPP(I)
	 SETCMB TT,TTYLPP(I)
	SKIPL B,TTYIHP(I)	;AND UNDO MAIN PRGM CURSOR POS MVT
	CAMGE B,TCMXH(I)
	 JRST TYORS3
	MOVE B,TCMXH(I)
	SUBI B,1
	MOVEM B,TTYIHP(I)
TYORS3:	MOVEM B,TPHP(TT)
	MOVE B,TTYIVP(I)
	CAML B,TCMXV(I)
	 BUG
	MOVEM B,TPVP(TT)
	SETOM TTYLPS(I)
	JRST UTCONJ

;SEND A %TDINI TO ALL TTYS.  CALLED AT SYSTEM STARTUP.
TTRSAL:	MOVSI I,-NCT
TTRSA1:	MOVE T,TCTYP(I)
	MOVE H,TTYOPT(I)
	MOVE Q,TOIP(I)
	CONO PI,TTYOFF
	MOVEI A,%TDINI
	PUSHJ P,TYOOU1	;YES, SEND IT A REINIT CHARACTER
	MOVEM Q,TOIP(I)
	CONO PI,TTYON
	AOSN TTYOAC(I)
	 XCT TTYST(I)	;AND MAKE SURE IT GETS SENT TO THE TTY
TTRSA2:	AOBJN I,TTRSA1
	POPJ P,

SUBTTL TV-11 INPUT PROCESSOR

IFN N11TYS,[
;CALL HERE FROM CLOCK LEVEL WHEN THERE IS INPUT FROM THE PDP-11.
;TAKE CHARACTERS FROM THE PDP11 AND CALL THE TTY INPUT INT. LVL.
;ROUTINES WITH THEM ONE AT A TIME. MAY CLOBBER ANY ACS.
TT11IN:	SKIPL TT11P	;IF 11 DOWN, DON'T LOOK FOR INPUT FROM IT.
	 JRST TT11D1
	LDB TT,[$11WD0,,@TT11HD]
	SETZM @TT11HD	;GET AND RESET CHAIN OF INPUT BUFFERS.
;HANDLE THE NEXT INPUT BUFFERFULL. PDP11 ADDRESS IN TT.
TT11I1:	LSH TT,-2	;CONVERT PDP11 ADDRESS TO PDP10 ADDR.
	ADDI TT,TT11LO
	MOVE A,(TT) ;GET -<# CHARS IN BUFFER>
	ASH A,-24
	LDB I,[$11WD0,,2(TT)] ;GET # OF TTY THE CHARS ARE FOR.
	CAML A,[-400]	;IF A OR I IS RIDICULOUS,
	 CAML I,TT1111
	  JRST TT11LS	;ASSUME 11 HAS CRASHED.
	JUMPG A,TT11LS
	ADDI I,NF11TY
	MOVEI B,3(TT)	;SET UP BP TO DATA AREA OF BUFFER.
	HRLI B,$11WD1	;EACH CHAR IS 16. BITS - A PDP11 WORD.
	PUSH P,TT	;SAVE BUFFER ADDR SO CAN FIND NEXT BFR.
	CAIL I,NF11TY+N11TYS
	 JRST [	MOVE A,I	;IF 11 KNOWS MORE TV'S THAN 10, IGNORE THOSE 10 ISN'T USING.
		PUSHJ P,TTYLO2	;AND IF THE 11 STARTS USING ONE, FREE IT SO USER ISN'T CONFUSED.
		JRST TT11I3]
	CONO PI,TTYOFF-1
	JUMPE A,TT11I4
	PUSH P,I
	PUSH P,A
	PUSH P,B
TT11I2:	ILDB A,(P)	;GET NEXT CHAR FROM BFR,
	MOVE I,-2(P)
	PUSHJ P,NTYI5	;PRETEND IT CAME FROM A TTY CONTROLLER INT.,
	AOSE -1(P)
	 JRST TT11I2	;MORE CHARS => HANDLE THEM.
	SUB P,[3,,3]
TT11I3:	CONO PI,TTYON-1
	POP P,A		;ADDR. OF BUFFER JUST EMPTIED.
	LDB TT,[$11WD1,,1(A)] ;GET ADDR OF NEXT BUFFER.
	SETZB B,(A)	;THIS BUFFER NOW FREE.
	DPB B,[$11WD1,,1(A)]
	JUMPN TT,TT11I1	;LOOK AT NEXT ONE, IF ANY.
	POPJ P,

TT11I4:	PUSHJ P,TYPEND	;INPUT BUFFER WITH 0 CHARS SAYS OUTPUT BUFFER
	JRST TT11I3	;IS EMPTY, SO MAYBE REQUEST ECHOING.

TT11LS:	MOVEM A,TT11ER	;LEAVE DIAGNOSTIC INFO BEHIND
	MOVEM I,TT11ER+1
	MOVEM TT,TT11ER+2
	MOVE A,(TT)
	MOVEM A,TT11ER+3
	MOVE A,1(TT)
	MOVEM A,TT11ER+4
	MOVE A,2(TT)
	MOVEM A,TT11ER+5
TT1LS1:	SETZM TT11P	;MARK 11 DOWN AND DONT TRY TO COME BACK UP FOR NOW
	MOVEI A,SCR11D	;MAKE SYS JOB PRINT "11 WENT DOWN" MESSAGE.
	IORM A,SUPCOR
TT11D1:	MOVEI A,TT11HD+1 ;MAKE SURE CLOCK LEVEL DOESN'T THINK
	MOVEM A,TT11HD	;THAT THE 11 IS SENDING INPUT.
	POPJ P,
]

SUBTTL TERMINET MOTOR CONTROL

;COME HERE FROM VERY SLOW CLOCK (2 MIN.), RUNNING IN SYS JOB.
;TURN OFF MOTORS OF ALL TERMINETS THAT HAVE BEEN IDLE 30. SEC.
;MAY CLOBBER ANY ACS.
TTTMNT:	MOVE TT,TIME
	SUBI TT,900.	;TT=30. SECONDS AGO.
	CAIA
TTTMN2:	 MOVE TT,TIME	;TURN OFF ALL TERMINETS AT SYSTEM STARTUP.
	MOVSI I,-NCT
TTTMN0:	MOVE T,TCTYP(I)
	CONO PI,TTYOFF
	SKIPL SHUTDN
	CAML TT,TTLTM(I) ;IF TTY HAS OUTPUT RECENTLY
	CAIE T,%TNTRM	;OR ISN'T A TERMINET,
	 JRST TTTMN1	;NOTHING TO DO.
	MOVSI T,%TCMTR
	TDNE T,TTYCOM(I) ;DITTO IF MOTOR ALREADY OFF.
	 JRST TTTMN1
	IORM T,TTYCOM(I)
	MOVE H,TTYOPT(I)
	MOVE Q,TOIP(I)
	MOVEI A,%TDMTF	;PUT A MOTOR-OFF COMMAND IN OUTPUT BFR
	PUSHJ P,TYOOU1
	MOVEM Q,TOIP(I)
	CONO PI,TTYON
	AOSN TTYOAC(I)
	 XCT TTYST(I)	;AND TELL INT. LVL. ABOUT IT.
TTTMN1:	CONO PI,TTYON
	AOBJN I,TTTMN0
	POPJ P,

;CALL HERE WHEN ABOUT TO OUTPUT TO A TERMINET WHOSE MOTOR IS OFF
;TTY # IN I. LEAVES TTY'S TTYCOM IN Q.
TTTMTO:	MOVE Q,TOIP(I)
	MOVEI A,%TDMTN
	MOVE H,TTYOPT(I)
	PUSHJ P,TYOOU1	;PUT MOTOR-ON CMD IN OUTPUT BFR,
	MOVEM Q,TOIP(I)
	MOVSI Q,%TCMTR	;MOTOR NOW ON AS FAR AS MAIN PRGM
	ANDCAB Q,TTYCOM(I) ;IS CONCERNED.
	POPJ P,

SUBTTL PI-LEVEL ECHOING

;ECHOING - CALLED AT CLOCK LEVEL. MAY CLOBBER ANY AC.
;ECHOES CHARS BY COPYING THEM FROM INPUT BFR TO OUTPUT BFR.
TTECH:	MOVSI I,200000	;GET LIST OF TTYS NEEDING ECHO, AND REINIT IT.
	EXCH I,TTERQS
TTELUP:	AOS NTTELU	;TAKE STATISTICS.
	CAIL I,-1
	 POPJ P,	;NO MORE TTYS NEED ECHOING.
		;I HAS IDX OF A TTY NEEDING ECHOING.
IFN N11TYS,[
	MOVE T,TTYTYP(I)
	TRNE T,%TY11T
	 JRST TTELU3
TTELU4:	]
	MOVEI A,TOBS
	MOVSI T,%TCECH
	TDNE T,TTYCOM(I);CAN'T ECHO UNLESS OUTPUT BUFFER HAS ENOUGH ROOM,
	 MOVEI A,TYOWNC+1
	CAMG A,TORM(I)	;NO MAIN PROGRAM OUTPUT IN IT,
	 SKIPL TTOALC(I);OUTPUT NOT BLOCKED AT M.P. LEVEL,
	  JRST TTEDU4
	SKIPL TYOSW(I)	;AND NO MORE OUTPUT COMING SOON.
	 JRST TTEWAT	;PUT TTY BACK ON LIST.
	MOVE H,TTYOPT(I)
	MOVE Q,TTYCOM(I)
	TLNE Q,%TCMTR	;IF TTY'S MOTOR IS OFF, TURN IT ON.
	 PUSHJ P,TTTMTO
	MOVEI J,TTEDMY	;PROVIDE IOT RTNS WITH VARIABLE-BLOCK.
	SKIPGE TT,TTYLPP(I) ;TT HAS IDX OF MOST RECENTLY USED PC PPR
	 SETCM TT,TTYLPP(I) ;WHETHER NOW ASSOCIATED OR NOT.
	MOVE A,TPVB(TT)	;PERHAPS MOST RECENT PC PPR IS ECHO AREA,
	CAMN A,TCMXV(I)	;BUT THERE'S NO ECHO AREA NOW. IN THAT CASE,
	 SUBI TT,TPLEN	;MAKE SURE DON'T TRY TO FORCE OUT BUFFERED CURSOR POS IN THAT PC PPR.
TTEDU2:	TLZE Q,%TCDNG	;SHOULD BELL BE TYPED BECAUSE INPUT BFR FULL?
	 PUSHJ P,[MOVEM Q,TTYCOM(I)
		MOVEI R,%TJECH+%TJMOR
		MOVEI A,^G	;DING ON TTY IF DESIRED.
		JRST TYO8]
TTELP1:	SKIPN T,ECHOC(I)	;ANY CHARS TO BE ECHOED NOW IN INPUT BFR?
	 JRST TTEDUN	;NO, FINISHED ECHOING.
	SKIPG T
	 BUG			;ECHOED MORE CHARS THAN THERE WERE?
	AOS NTTEL1
;NOW FIND NEXT CHARACTER NEEDING PI ECHO,
;AND MARK IT AS NO LONGER NEEDING IT.
;CAN EXIT TO TTEDU5 IF MUST STOP ECHOING BECAUSE ECHOING IS DEFERRED.
	CONO PI,TTYOFF-1	;PREVENT INTERACTION WITH INPUT INTERRUPTS.
	MOVE B,ECHOP(I)
TTELP2:	MOVE C,TICC(I)
	CAMN B,TIIP(I)
	 JRST TTELBG
	MOVE C,B
	CAMN B,TIBEP(I)	;LOOK FOR 1ST CHAR NEEDING PI ECHO.
	 SUBI B,TIBL
	ILDB A,B
	TRZN A,%TXPIE
	 JRST TTELP2
	TRNN A,%TXIGN	;DON'T ECHO NON-COM-MODE CHARS
	 JRST [	MOVE T,TTYSTS(I)	;IF ECHOING BEING DEFERRED.
		TLNE T,%TSNOE
		TLNE H,%TOHDX	;BUT IF HALF-DUPLEX, IT ECHOES IN ANY CASE.
		 JRST .+1
		JRST TTEDU5]
	SOSGE ECHOC(I)	;FOUND ONE; NOW ECHO IT.
	 BUG
	MOVEM B,ECHOP(I)
	DPB A,B		;MARK IT AS ECHOED.
	LDB A,B		;CHECK FOR HARDWARE LOSSAGE.
	TRNE A,%TXPIE
	 BUG		;DPB OR TRZN LOST??
	TRNN A,%TXIGN	;IF CHAR IS IN BFR ONLY TO BE ECHOED,
	 JRST TTELP5
	CAMN C,TIOP(I)	;IF IT'S 1ST CHAR IN CUFFER,
	 JRST [	PUSHJ P,TYIRE1	;REMOVE IT THE NORMAL WAY.
		JRST TTELP5]
	CAMN B,TIIP(I)	;IF CHAR IS LAST CHAR IN BFR,
	 PUSHJ P,TTEBAK	;DELETE IT, & MAYBE OTHERS BEFORE IT.
TTELP5:	CONO PI,TTYON-1
;DECIDE WHICH PC PPR TO USE.
	MOVE T,I
	IMULI T,2*TPLEN		;COMPUTE INDEX OF M.P. PC-PPR.
	SKIPGE Q,TTYCOM(I)	;COM MODE, UNLESS %TCICO OR %TCLFT, MEANS USE M.P. AREA.
	 TDNE Q,[%TCICO+%TCLFT,,400000]
	  MOVE T,TTYEPP(I)	;OTHERWISE USE THE ECHO AREA IF ANY.
	MOVE B,TTYSTS(I)
	TRNN A,%TXECI
	 TRNN A,%TXIGN		; FOR ^_ COMMANDS, DON'T OBEY %TSNEA.
	  TLNN B,%TSNEA		; %TSNEA SAYS USE M.P. AREA.
	   JRST TTELP4
	MOVE T,I
	IMULI T,2*TPLEN
TTELP4:	SKIPGE TT,TTYLPP(I)	;TT GETS LAST PC PPR HACKED WITH THIS TTY.
	 SETCA TT,
	CAMN TT,T	;IF WE ARE SWITCHING TO A DIFFERENT PC PPR,
	 JRST TTELU1
	SKIPL TTYLPP(I)	;DISASSOCIATE THE OLD ONE IF NEC.
	 PUSHJ P,TYOMVC
TTELU1:	MOVE TT,T	;MOST RECENT PC PPR NOW ECHOING PC PPR.
	MOVSI Q,%TCECH	;NOW DEFINITELY GOING TO PUT CHARS IN OUTPUT BUFFER
	IORB Q,TTYCOM(I)
	MOVEI R,%TJECH+%TJMOR
	TLNN H,%TOHDX	;ON HALF-DUPLEX TTYS, EXCEPT FOR
	 JRST TTELP3
	TRNN A,%TXCOM	;CHARS PRODUCED BY COM LINKS,
	 PUSHJ P,[IORI R,%TJHDE
		JRST TYOAS5]	;MOVE CURSOR BUT DON'T REALLY OUTPUT.
		;THUS, CURSOR MOTION DUE TO ECHOING BY TTY
		;IS ACCOUNTED FOR.
TTELP3:	LDB B,[.BP %TXASC,A]
	TRNE A,%TXECI
	 JRST TTELP6
	TRZE A,%TXIGN
	 CAIE B,^L	;^L ECHOED IN COM MODE SHOULD CLEAR SCREEN.
	  TRZA R,%TJCP1
	   JRST [ MOVEI A,"C	;(BY SIMULATING A ^PC).
		  IORI R,%TJCP1
		  JRST .+1]
TTELP6:	ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC
	PUSHJ P,TYO8
	TRZE R,%TJHDE
	 PUSHJ P,TYOMVC
	SKIPN ECHOC(I)
	 JRST TTEDUN
IFN N11TYS,[
	TRNE H,%TP11T
	 JRST [	PUSHJ P,TYOWN1
		LDB B,T
		CAIE B,1_TT11BY-1
		 JRST TTEDU6 ;LESS THAN 20. FREE SPACES IN BFR => GIVE UP.
		JRST TTELP1]
]
	MOVE A,TORM(I)
	CAIGE A,TYOWNC	;IS THERE A CHANCE OUTPUT WOULD HANG UP?
	 JRST TTEDU4	;YES, WAIT UNTIL LATER TO ECHO THE REST.
	JRST TTELP1	;NO, ECHO MORE

TTELBG:	BUG PAUSE,[ECHOC is ],OCT,T,[ but ECHOP equals TIIP.  TICC=],OCT,C,[.  TTY ],OCT,I
	SETZM ECHOC(I)
;COME HERE WHEN ALL ECHOING DESIRED ON THIS TTY WAS DONE.
TTEDUN:	CONO PI,TTYOFF-1
	SKIPE ECHOC(I)
	 JRST TTEDU1
TTEDU5:	MOVE Q,TTYCOM(I)
	TLNE Q,%TCDNG	;HAS ANOTHER REASON TO ECHO ARISEN AFTER WE CHECKED?
	 JRST TTEDU1	;YES, GO PROCESS IT.
	PUSH P,TTYERQ(I);SAVE NEXT TTY TO ECHO ON
	SETOM TTYERQ(I)	;AND TURN OFF THIS ONE'S ECHO REQUEST
	CONO PI,TTYON-1
	SETZ R,
	CAME TT,TTYLPP(I)
	 PUSHJ P,TYOFRC	;FORCE OUT BUFFERED CURSOR MOTION.
	POP P,I
	JRST TTELUP

TTEDU4:
TTEDU3:	SETO A,		;NO, MOVE TO NEXT TTY ON LIST.
	EXCH A,TTYERQ(I)
	MOVE I,A
	JRST TTELUP

TTEDU1:	CONO PI,TTYON-1
	JRST TTEDU2

;COME HERE WHEN CAN'T ECHO BECAUSE TYOSW IS LOCKED.
TTEWAT:	AOS NTTEWA
	MOVE A,I	;IF WE CAN'T DO ANY.
	CONO PI,TTYOFF-1
	EXCH A,TTERQS	;PUT THIS TTY BACK ON LIST,
	EXCH A,TTYERQ(I) ;SO IT WIL BE REEXAMINED NEXT TICK.
	CONO PI,TTYON-1
	MOVE I,A	;MOVE TO NEXT TTY ON OLD LIST.
	JRST TTELUP

IFN N11TYS,[
TTELU3:	SKIPL TT11P
	 JRST TTEDU4	;DON'T ECHO ON PDP11 TTYS IF PDP11 DOWN.
	LDB A,TOIP(I)	;DEFER ECHOING UNLESS OUTPUT BFR EMPTY.
	CAIN A,1_TT11BY-1
	 JRST TTELU4	;JUMP IF BUFFER EMPTY (LAST CHAR OUTPUT CHANGED TO -1)
TTEDU6:	JRST TTEWAT	;TEMPORARY PATCH
.ERR IS THIS PATCH TEMPORARY OR PERMANENT?
	MOVE A,TT11HD	;BFR NOT EMPTY: TELL 11
	ADDI A,1-NF11TY(I) ;(BY SETTING ECOFLG)
	ADD A,TT1111
	MOVSI B,400000	;TO SIGNAL TEN WHEN THE BUFFER BECOMES EMPTY.
	IORM B,(A)	.SEE TT11I4
	JRST TTEDU4
]
;COME HERE WHEN ARE JUST ABOUT TO ECHO THE LAST CHAR
;IN THE INPUT BUFFER, AND ITS %TXIGN IS SET.
;TRY TO FLUSH THE CHARACTER FROM THE INPUT BFR,
;AND ALSO THE CHARS BEFORE IT, IF THEY TOO HAVE %TXIGN.
TTEBAK:	SKIPE C,ECHOC(I)
	 BUG PAUSE,[ECHOING LAST CHAR BUT ECHOC IS ],OCT,C,[.  TTY ],OCT,I
	SETZM ECHOC(I)
	IBP B		;THIS DEPENDS ON 18-BIT BYTES IN INPUT BUFFER.
	SUBI B,1
	CAMN B,TIBEP-1(I)
	 ADDI B,TIBL
	SOSN TICC(I)
	 JRST TTEBA1
	LDB C,B
	TRNE C,%TXIGN
	 JRST TTEBAK
TTEBA1:	MOVE C,TIIP(I)
	CAMN C,TINTP(I)
	 MOVEM B,TINTP(I)
	CAME C,ECHOP(I)
	 BUG
	MOVEM B,ECHOP(I)
	MOVEM B,TIIP(I)
	POPJ P,

SUBTTL TTY INTERRUPT HANDLING

;MACRO TO SAVE ACS AND CONI APR ON ENTERING A TTYCHN INTERRUPT ROUTINE.
;PCLOC SHOULD BE THE ADDRESS OF THE STORED PC, WHICH IS MOVED TO TTYBRK.
DEFINE TTYSAV PCLOC=TTYBRK
IFN KL10P,[
	CONSO PI,1_<7-TTYCHN>
	 JRST 4,.		;HARDWARE BUG ALLEGEDLY FIXED
]
IFN KA10P, CONI TTYAPC
	MOVEM A,TTYA
	MOVE A,[B,,TTYACS]
	BLT A,TTYACS+17-B+1-1	;SAVE ALL ACS BUT 0
IFSN PCLOC,TTYBRK,[
	MOVE A,PCLOC
	MOVEM A,TTYBRK
]
	MOVE P,TTYPDP
	PUSH P,[TTYRET]
TERMIN

EBLK

TTYBRK:	0

BBLK
	TTYSAV		;SAVE ACS AND SET UP P.
IFN KL10P,[
	CONSZ DTE,%DBL10+560
	 JRST TTDTE1	;DTE20 INTERRUPTED (DOORBELL OR BYTE TRANSFER ERROR OR DONE)
] ;KL10P
IFN DL10P,[
	CONSZ DLC,10
	 JRST TTDLB0	;DL10 INTERRUPTED
]
IFN TK10P,[
	CONSZ NTY,200000
	 JRST NTY1	;NEW TELETYPE KLUDGE
]
IFN MTYP,[
	CONSZ MTY,50
	 JRST MTY1	;MORTON BOX
]
IFN DPKPP,[
	CONSZ DPK,60
	 JRST DPKPE	;PARITY ERROR OR NXM
	CONSZ DPK,10
	 JRST DPTI1	;CHAR AVAIL DPK
	CONSZ DPK,400
	JRST DPTO1	;OUTPUT BUFFER FIN DPK
]
IFN NOTYS,[
	MOVEI I,0
	CONSZ TTY,50
	 JRST GOTTY
]
IFN NDZTYS,[		
;DZ-11 Code The only place that emulates an interrupt on the TTY interrupt
; channel is the DTE code, handled above, so there should never be a
; need for a DZ11 entry here.
]
;	MOVEI J,TTYCHN	;KNIGHT TTY KLUDGE GENERATES SPUR INTS
;	JSP E,SPUR	;SPURIOUS INT
TTYRET:
TTYRT3:
IFN KA10P,[
	CONI A
	ANDCM A,TTYAPC
	TRNE A,220000	;DID MPV OR PDL OV COME ON DURING THIS INT?
	 BUG PAUSE,[MPV OR PDL OV IN TTY INT HANDLER, APR CONI=],OCT,A
] ;KA10P
	MOVS A,[B,,TTYACS]
	BLT A,17
	MOVE A,TTYA
	JRST 12,@TTYBRK

IFN DPKPP,[
DPKPE:	AOS NDPKPE
	CONO DPK,60+TTYCHN	;PARITY ERROR OR NXM
	JRST TTYRT3
]

IFN DZ11P,[			;DZ-11 Code

IFE KS10P, .ERR DZ11 code only works on a KS-10.

$INSRT DZ11

REPEAT DZ11NB,[

EBLK
CONC DZ,\.RPCNT,RB: 0
BBLK
	MOVEM U,TTYACS-B+U
	JSP U,DZRBK
	;; <first line>,,<bus address>:
	NFDZTY+<DZNLN*.RPCNT>,,CONC DZ,\.RPCNT,BA

EBLK
CONC DZ,\.RPCNT,XB: 0
BBLK
	MOVEM U,TTYACS-B+U
	JSP U,DZXBK
	;; <first line>,,<bus address>:
	NFDZTY+<DZNLN*.RPCNT>,,CONC DZ,\.RPCNT,BA

];DZ11NB

DEFINE DZSAV
	MOVEM A,TTYA
	MOVE A,[B,,TTYACS]
	BLT A,TTYACS-B+<U-1>	;SAVE ALL ACS BUT 0, A AND U...
	MOVE A,-3(U)		;Get return address
	MOVEM A,TTYBRK		;Save it in TTYBRK
	MOVE P,TTYPDP		;Stack
	PUSH P,[TTYRET]		;Set up return address
	HRRZ C,(U)		;Get Unibus address
	HLRZ I,(U)		;Get ITS TTY # of first DZtty on this board
TERMIN

; DZ11 receiver interrupts (actually silo overflow)
DZRBK:  DZSAV			;Save ACs and setup parameters
	IORDI A,%DZRCS(C)
	TRNN A,%DZCRD		;Character ready?
	 JRST [ AOS DZRSPR	;Count spurious interrupts
		POPJ P, ]
DZRBK1:	IORDI A,%DZRDR(C)
	TRNN A,%DZDDV		;Data valid?
	 POPJ P,		;Nope, got it all
	; If parity must be hacked, it should be done here
	LDB D,[.BP %DZLM,A]	;Get line number
	ANDI A,%DZTCM		;Get character
	ADD I,D			;Get TTY number
	CAIL I,NFDZTY+NDZTYS
	 BUG
	JRST NTYI1

; The following code can't work because I found the place where NTYI1
; clobbers U (Alan 3/26/86):
; 
;	PUSHJ P,NTYI1		;Process the input
;	HRRZ C,(U)		;Get Unibus address
;	HLRZ I,(U)		;Get ITS TTY # of first DZtty on this board
;	JRST DZRBK1

; DZ11 transmitter interrupts
DZXBK:  DZSAV			;Save ACs and setup
	AOS DZXINC		;Count interrupts
DZXBK1:	IORDI A,%DZRCS(C)
	TRNN A,%DZCTR		;Transmitter ready?
	 POPJ P,
	LDB D,[.BP %DZLM,A]	;Get line number
	ADD I,D			;ITS terminal number of this line
	CAIL I,NFDZTY+NDZTYS
	 BUG
	AOS DZXCHC		;Count characters sent
	PUSHJ P,TYPSC		;Merge with the rest of the world
	HRRZ C,(U)		;Get UB address of board again
	HLRZ I,(U)		;Get ITS TTY # of first DZtty on this board
	JRST DZXBK1		;Try to send another, maybe we'll get lucky

];DZ11P

IFN KL10P,[
;HANDLE INTERRUPTS FROM THE CONSOLE PDP11 VIA THE DTE20
;CODE FOR HANDLING MULTIPLE CONSOLES, BLOCK TTY OUTPUT, ETC.
;IN THE FUTURE ETHERNET STUFF WILL GET ADDED HERE.

TTDTE1:	CONI DTE,DTECNI		;SAVE FOR DEBUGGING
	CONSZ DTE,460		;TO11 ERROR OR TO10 DONE OR TO10 ERROR
	 BUG PAUSE,[DTE20 ERROR, CONI=],OCT,DTECNI
	CONSZ DTE,100		;TO11 TRANSFER COMPLETE
	 JRST [	CONO DTE,100	;CLEAR TO11 TRANSFER COMPLETE
		SETZM DTEBBY	;BUFFER NO LONGER BUSY
		JRST .+1 ]
	CONO DTE,%DBL10+40	;CLEAR DTE20 INTERRUPTING STATE
	SKIPGE A,DTETYI		;CHECK FOR TTY INPUT AVAILABLE
	 JRST TTDTE2
	SETOM DTETYI		;AVAILABLE.  INDICATE HAS BEEN GOTTEN.
	CONO DTE,%DBL11		;SIGNAL 11 THAT WE'RE READY FOR MORE.
	HLRZ I,A		;GET LINE NUMBER
	CAIL I,NFETY		;CHECK IT
	 CAIL I,NFETY+NETYS
	  BUG PAUSE,[BAD TTY NUMBER ],OCT,I,[FROM PDP-11]
	PUSHJ P,NTYI1		;PROCESS THE INPUT
	JRST TTDTE1		;CHECK FOR MORE

TTDTE2:	MOVEI A,SCRHNG		;IF HANGUP/DIALIN, SIGNAL SYSTEM JOB TO HANDLE IT
	SKIPL DTEHNG
	 IORM A,SUPCOR
	SKIPN DTEBBY		;DON'T CHECK FOR OUTPUT DONE IF BUFFER BUSY
	 SKIPGE A,DTEODN	;CHECK FOR TTY OUTPUT DONE
	  POPJ P,		;NOTHING, DISMISS INTERRUPT
	SETOM DTEODN		;INDICATE SIGNAL HAS BEEN RECEIVED
	HLRZ I,A		;GET LINE NUMBER
	CAIL I,NFETY		;CHECK IT
	 CAIL I,NFETY+NETYS
	  BUG PAUSE,[BAD TTY NUMBER ],OCT,I,[FROM PDP-11]
	HRRZS A			;SET UP MULTI-CHARACTER TRANSFER,
	HRRZ B,TTOALC(I)	;SETTING MAX# CHARACTERS FROM ELEVEN'S BUFFER SIZE
	CAIGE B,(A)		;DON'T SEND MORE CHARACTERS THAN ALLOCATED
	 MOVE A,B
	CAILE A,DTEOBL		;DON'T EXCEED SIZE OF OUR BUFFER
	 MOVEI A,DTEOBL
	MOVEM A,DBBCC
	MOVEM A,DBBCC1
	MOVE A,[441000,,DTEOBF]
	MOVEM A,DBBBP
	JRST TYP		;GO FILL OUTPUT BUFFER
];KL10P

IFN DL10P,[
;HANDLE THE DL-10 (A PDP-11 FRONT END FOR THE KL-10).
;ALL INTERRUPTS FROM DL-10 COME HERE.

TTDLB0:	CONO DLC,10+TTYCHN ;CLEAR INTERRUPT FLAG
	SKIPN DL10F	;IGNORE DL10 IF IT IS MARKED OUT OF SERVICE.
	 POPJ P,
IFN CHAOSP, IFN DLCP,	PUSHJ P,DLCWAK	;SEE IF INTR IS FOR CHAOS NET
IFN T300P,[		;CHECK FOR T-300 INTERRUPT, PASS TO DISK LEVEL IF SO
	SKIPE DSCDON
	 CONO PI,DSKRQ
];T300P
	SKIPE I,DL10IL	;IS INPUT AVAIL? IF SO, READ WHICH LINE
	 PUSHJ P,TTDLIN	;AND PROCESS THE CHARACTER.
	MOVEI A,SCRHNG	;DOES THE 11 SAY A MODEM WAS DISCONNECTED?
	SKIPE DL10CL
	 IORM A,SUPCOR	;IF SO, TELL SYS JOB TO TAKE APPROPRIATE ACTION.
	SKIPN DL10LN	;DON'T CHECK OUTPUT-DONE IF OUTPUT BUFFER IS BUSY
	 SKIPN I,DL10OD	;OUTPUT DONE ON SOME TTY?
	  POPJ P,
	MOVE A,DL10BS	;YES, GET 11'S BUFFER SIZE AND
	SETZM DL10OD	;MAKE COMMUNICATION CHANNEL FREE FOR -11 AGAIN
	HRRZ B,TTOALC(I)
	CAMLE A,B
	 MOVE A,B	;DON'T SEND MORE CHARACTERS THAN TERMINAL HAS ALLOCATION FOR
	MOVEM A,DBBCC	;INIT CHARACTER COUNTERS TO SIZE OF BUFFER IN 11
	MOVEM A,DBBCC1
	MOVE A,[441000,,DL10BF]
	MOVEM A,DBBBP	;INIT B.P. USED BY 10 TO STORE INTO BUFFER.
	JRST TYP	;GO FILL UP THE OUTPUT BUFFER

TTDLIN:	MOVE A,DL10IC	;GET THE CHARACTER TYPED IN
	SETZM DL10IL	;FREE THE INPUT CHANNEL SO 11 CAN USE IT AGAIN.
	CONO DLC,100040+TTYCHN	;INTERRUPT 11
	JRST NTYI1	;AND PROCESS THE INPUT.
]

IFN DPKPP,[
DPTO1:	CONI DPK,A
	LDB I,[220400,,A]
	ADDI I,NFDPTY
	SKIPL @DPKC-NFDPTY(I)
	SETOM @DPKC-NFDPTY(I)
	LDB J,[$TTOSP,,TTYTYP(I)] ;GET OUTPUT SPEED CODE.
	CAIL J,LDPSPT
	 MOVEI J,LDPSPT-1
	HRRZ A,TTOALC(I)
	CAMLE A,DPSPT(J)
	 MOVE A,DPSPT(J)	;# CHARS BUFFER SPACE FOR THAT SPEED.
	MOVEM A,DBBCC
	MOVEM A,DBBCC1
	MOVE A,DBBFP-NFDPTY(I)
	MOVEM A,DBBBP	;BP FOR STORING CHARS.
	MOVSM A,@DPKP-NFDPTY(I)
	JRST TYP0

DPTI1:	DATAI DPK,A
	LDB I,[220400,,A]
	ADDI I,NFDPTY
	JRST NTYI1
]
IFN TK10P,[
NTY1:	CONSZ NTY,400000
	 POPJ P,	;SCANNER NOT STOPPED
	CONI NTY,I	;READ IN TTY #
IFE NNTYS-10,LDB I,[110300,,I]
IFE NNTYS-20,LDB I,[100400,,I]
IFN <NNTYS-10>*<NNTYS-20>,.ERR
	CAIL I,NNTYS
	 BUG
	ADDI I,NFNTY	;CALCULATE CONSOLE #
	CONO NTY,@TTYLT(I)	;SELECT APPROPRIATE TTY
	CONSZ NTY,20
	 JRST TYPSC	;DONE FLAG ON TYPEOUT
	CONSO NTY,40
	 JRST TTYRT2	;THIS TTY NOT REALLY UNHAPPY
	DATAI NTY,A
	JRST NTYI1

TTYRT2:	CONO NTY,200000+TTYCHN
	JRST TTYRET
]

IFN MTYP,[
MTY1:	CONI MTY,I
	LDB I,[140500,,I]	;GET SUBDEVICE
	CAIL I,NMTYS
	 JRST MTY2	;NOT A VALID #
	ADDI I,NFMTY
	CONO MTY,@TTYLT(I)
	CONSO MTY,40	;INPUT DONE
	 JRST MTY6
	DATAI MTY,A
	JRST NTYI1

MTY6:	CONSO MTY,10	;OUTPUT DONE
	 POPJ P,
	HRRZ A,TTOALC(I)
	CAILE A,MTYNC
	 MOVEI A,MTYNC
	MOVEM A,DBBCC	;# CHARS CAN GIVE AT ONCE.
	MOVEM A,DBBCC1
	SETZM MTYOW	;SET UP WORD TO FILL WITH OUTPUT CHARS.
	MOVE A,[440700,,MTYOW]
	MOVEM A,DBBBP	;SET UP BP FOR STUFFING THAT WORD.
	JRST TYP

MTY2:	CONSZ MTY,10
	 JRST MTY3	;OUTPUT
	CONSZ MTY,40
	DATAI MTY,A	;INPUT
	POPJ P,		;AND IGNORE

MTY3:	LSH I,12.
	CONO MTY,200+TTYCHN(I)	;CLEAR OUTPUT DONE FLAG
	POPJ P,
]

IFN NOTYS,[
GOTTY:	CONSZ TTY,10
	 JRST TYPSC	;TTO DONE
	CONSO TTY,40
	 POPJ P,	;NONE
	DATAI TTY,A	;TTI DONE, READ CHR
	JRST NTYI1
]

;PROCESS INPUT INTERRUPT WITH CHARACTER IN A, TTY # IN I

OVHMTR TTI	;TTY INPUT INTERRUPT LEVEL

;ENTER HERE FOR "HARDWARE" TTYS, LOW 8 BITS OF A ARE THE INPUT, OTHER BITS ARE GARBAGE
NTYI1:
IFN NNVTTS,[
	CAME I,NOVATT	;SKIP IF THIS TTY IS NOVA
	 JRST NTYI3
	TRZE A,200	;SKIP IF DATA  AND NOT TTY #
	 JRST NTYI2	;SET TTY #
	SKIPGE I,NVIPTT	;CURRENTLY SELECTED  CONSOLE ON INPUT
	 POPJ P,	;NONE SELECTED
NTYI3:]
IFN TTLPTP,[
	CAMN I,LPTTTY
	 JRST INLPT
]
	ANDI A,377	;FLUSH EXTRANEOUS BITS, KEEP LOW 7
	MOVE H,TTYOPT(I)
	TRNN H,%TPMTA	; OR KEEP LOW 8 IF 8TH IS HARDWARE META KEY
	 ANDI A,177
;ENTER HERE FOR TTYS WHICH MAY INPUT IN FULL-CHARACTER-SET
NTYI5:	MOVEM I,LOCTTY	;TTY CHAR ACTUALLY TYPED ON
	MOVSI U,%TSLCZ
	ANDCAB U,TTYSTS(I)	;CLEAR LAST CHR ^Z BIT
	MOVE Q,TTYCOM(I)
	MOVE R,TTYTYP(I)
	MOVE H,TTYOPT(I)
	TRNE H,%TPMTA	;PROCESS HARDWARE META KEY IF PRESENT
	 TRZN A,200
	  CAIA
	   IORI A,%TXMTA
	ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC ;FLUSH MEANINGLESS BITS.
	TLNE H,%TOALT	;IF THIS TTY WANTS IT, MAYBE STANDARDIZE ALTMODES
	 PUSHJ P,TTYSAM
	HRRZ D,TTYIPC(I)
	MOVEM D,LTTYIPC	;REMEMBER INPUT RTN FOR DEBUGGING
	MOVE D,TYBPC(I)
	MOVEM D,LTYBPC
	JRST (D)	;PROCESS THE CHARACTER AND RETURN.

IFN NNVTTS,[
NTYI2:	JUMPE A,CPOPJ
	ADDI A,NFNVTY
	CAIGE A,NFNVTY+NNVTTS
	MOVEM A,NVIPTT	;SELECT CONSOLE
	POPJ P,
]

IFN TTLPTP,[INLPT:	MOVE A,TIME
	MOVEM A,LPTTIME
	POPJ P,
]

SUBTTL HANDLE ^\ CODES
;OR PASS CHARACTERS ON TO NEXT LEVEL OF INPUT
;PROCESSING IF NO ^\ CODE IS IN PROGRESS.

;THIS IS THE NORMAL VALUE OF TYBPC FOR ALL TTY'S; IT IS THE ONLY POSSIBLE VALUE
;FOR A TTY WHOSE %TPCBS AND %TPTEL ARE 0.
TYBN:	TRNE H,%TPPRN
	 PUSHJ P,TYBPRN
	TRNN H,%TPCBS+%TPTEL
	 JRST TYBRT2	;IF NOT ENABLED, JUST PASS CHAR TO NORMAL INPUT LEVEL.
; USED TO CLEAR %TXSFT (NOW %TXSUP) BEFORE CHECKING FOR ^\
;	MOVEI E,(A)
;	ANDCMI E,%TXSUP
	CAIN A,^\
	 TRNN H,%TPCBS
	  JRST TYBCR1	;IF NOT AN ENABLED ^\, GO CHECK FOR SPECIAL CR HANDLING
	JSP D,TYBRED	;READ THE CHARACTER AFTER THE ^\
	CAIGE A,100	;^\ FOLLOWED BY @ THROUGH _ IS THE HIGH BITS FOR THE NEXT CHARACTER.
	 JRST TYBCTL	;^\ FOLLOWED BY A CONTROL CHAR, ETC. IS A SPECIAL HACK.
	ANDI A,<%TXCTL+%TXMTA+%TXSUP+%TXTOP>_-7
	LSH A,7+18.	;GET THE EXCESS OVER 100 AND SHIFT BY 7,
	HRRI A,TYBPFX	;AND STORE IN LH OF TYBPC
	MOVEM A,TYBPC(I)
	POPJ P,		;RETURN. NEXT CHAR COMES TO TYBPFX

TYBPFX:	HLRZ D,TYBPC(I)	;GET THE HIGH BITS READ IN LAST TIME
	IOR A,D		;AND MERGE INTO THE CHAR JUST READ IN
TYBRET:	MOVEI D,TYBN	;RESET ^\ STATUS TO NORMAL
TYBRT1:	MOVEM D,TYBPC(I)
TYBRT2:	MOVE E,TIME
	MOVEM E,TTITM(I) ;UPDATE TIME OF LAST INPUT ON THIS TTY.
;NOW DETECT SPECIAL TOP-CHARS THAT SHOULD NOT ECHO
;AND SHOULD BE IGNORED IN COM MODE OR IN ^_ COMMANDS.
	SETZ E,			;WE SET E TO -1 BELOW FOR THOSE CHARACTERS.
	MOVE D,TTYSTA(I)
	TLNE D,%TANEC		;IF COUNT OF DON'T-ECHO CHARS IS >0,
	 JRST [	SUB D,[<.DPB 1,.BP %TANEC>,,]	;DECREMENT IT
		SETO E,		;AND DON'T ECHO THIS ONE.
		JRST TYBRT3]
	MOVE E,A	;IS THIS INPUT REALLY FOR LOCAL EDITING PROTOCOL?
	ANDI E,%TXTOP+%TXASC	;THAT IS, TOP-E OR TOP-S, OR THE CHARACTER FOLLOWING ONE?
	CAIE E,%TXTOP+"E
	 CAIN E,%TXTOP+"S	;DON'T ECHO OR INTERRUPT FOR TOP-S OR TOP-E,
	  TLO D,<.DPB 1,.BP %TANEC>	;OR THE CHAR THAT FOLLOWS IT.
	CAIN E,%TXTOP+"T	;DON'T ECHO OR INT FOR TOP-T, OR FOLLOWING 3 CHARS.
	 TLO D,<.DPB 3,.BP %TANEC>
	CAIE E,%TXTOP+"Y	;GRAPHICS INPUT CMDS TAKE 5 ARG CHARS.
	 CAIN E,%TXTOP+"X
	  TLO D,<.DPB 5,.BP %TANEC>
	SETZ E,
	TLNE D,%TANEC
	 SETO E,
TYBRT3:	MOVEM D,TTYSTA(I)
	MOVEM E,LEPCHR		;LEPCHR IS -1 FOR SPECIAL CHARS THAT SHOULD USUALLY BE IGNORED.
	HRRZ D,TTYIPC(I)
	JUMPE E,(D)		;IN WHICH CASE, DROP THIS CHAR ENTIRELY
	CAIN D,TTYI		;IF IT IS NOT THE NORMAL SORT OF INPUT.
	 JRST (D)
	POPJ P,

;COME HERE FOR ^\ FOLLOWED BY A CHARACTER < 100.
TYBCTL:	CAIN A,^A	;^\^A => ALLOCATE OUTPUT CHARS.
	 JRST TYBA
	CAIN A,^Z	;^\^Z => ZERO ALLOCATION
	 JRST TYBZ
	CAIN A,^I	;^\^I => INFINITY ALLOCATION
	 JRST TYBI
	CAIN A,^R	;^\^R => RESTART OUTPUT AT M.P. LEVEL.
	 JRST TYBR
	CAIN A,^P	;^\^P => SET CURSOR POSITION AND RESTART OUTPUT AT M.P. LEVEL.
	 JRST TYBP
	CAIN A,^\	;^\^\ => INPUT A ^\.
	 JRST TYBRET
	CAIN A,^C	;^\^C => SCREEN HAS BEEN SURREPTITIOUSLY CHANGED
	 PUSHJ P,TYBC
;RETURN TO NORMAL ^\ STATUS BUT DON'T PASS ANY INPUT UP TO NORMAL INPUT LEVEL.
TYBXIT:	MOVEI D,TYBN
TYBRED:	MOVEM D,TYBPC(I)	;JSP D,TYBRED TO WAIT FOR NEXT CHARACTER
	POPJ P,

TYBC:	MOVSI D,%TSATY
	IORB D,TTYSTS(I)
	JUMPL D,CPOPJ
	HLLZ E,MSKST(D)
	TLZ E,#%PJATY
	TLNE D,%TSCNS
	 IORM E,PIRQC(D)
	POPJ P,

TYBCR1:	CAIN A,15		;SEE IF ENABLED CR
	 TRNN H,%TPTEL
	  JRST TYBRT2		;NO, JUST PASS CHAR TO NORMAL INPUT LEVEL
	JSP D,TYBRT1		;PASS CHAR TO NORMAL INPUT LEVEL BUT HACK NEXT CHAR
	CAIE A,12		;IF IT IS LF OR NULL IGNORE IT
	 JUMPN A,TYBRET		;BUT OTHERWISE PASS IT TO NORMAL INPUT LEVEL
	JRST TYBXIT		;IN ANY CASE RESET TYBPC TO NORMAL

TYBPRN:	LDB E,[.BP %TXASC,A]
	CAIE E,"(
	 CAIN E,"[
	  XORI A,"(#"[
	CAIE E,")
	 CAIN E,"]
	  XORI A,")#"]
	POPJ P,

;^\^P<VPOS><HPOS> - SET CURSOR POS, THEN RESTART OUTPUT AT M.P. LEVEL.
;THIS IS THE WAY TO RESPOND TO A %TDORS CHARACTER ON A SOFTWARE TTY,
;SINCE OUTPUT RESET WILL STOP OUTPUT AT M.P. LEVEL ON SOFTWARE TTY'S
;WHICH HAVE ^\ TURNED ON.
TYBP:	JSP D,TYBRED	;WAIT FOR VPOS TO COME IN
	CAML A,TCMXV(I)
	 SETZ A,
	MOVEM A,TTYIVP(I)
	SKIPGE TT,TTYLPP(I)
	 SETCA TT,
	MOVEM A,TPVP(TT)
	SKIPGE TTYLPP(I)
	 HRLM A,TTYLPS(I)
	JSP D,TYBRED	;NOW WAIT FOR HPOS TO COME IN
	CAML A,TCMXH(I)
	 SETZ A,
	MOVEM A,TTYIHP(I)
	SKIPGE TT,TTYLPP(I)
	 SETCA TT,
	MOVEM A,TPHP(TT)
	SKIPGE TTYLPP(I)
	 HRRM A,TTYLPS(I)
TYBR:	HRROS TTOALC(I)	;RESTART AT M.P. LEVEL.
	PUSHJ P,TYPEN2	;REQUEUE ECHOING IF NECESSARY
	JRST TYBXIT

TYBZ:	HLLZS TTOALC(I)	;SET ALLOCATION TO 0.
	JRST TYBXIT

TYBI:	HLLOS TTOALC(I)	;SET ALLOCATION TO INFINITY.
	JRST TYBST	;NOW MUST START THE TTY IN CASE IT WAS STOPPED DUE TO NO ALLOC.

TYBA:	JSP D,TYBRED	;^\^A<NUM> => INCREMENT ALLOCATION BY <NUM>
	MOVE D,TTOALC(I)
	TRNN D,400000	;SKIP IF ALLOCATION = INFINITY
	 ADD D,A
	HRRM D,TTOALC(I)
TYBST:	AOSN TTYOAC(I)
	 XCT TTYST(I)
	JRST TYBXIT

SUBTTL NORMAL TTY INPUT HANDLER
;CLOBBERS A - E, EXPECTS R, U,  I SET UP.
;R HAS TTYTYP, U HAS TTYSTS, I HAS # OF TTY.
;Also seems to expect Q/ TTYCOM and perhaps H/ TTYOPT  -Alan 12/18/85

TTYI:	CAIN A,^_
	 JRST TTYICB	;CHAR IS ^_, MAYBE ENTER COM MODE.
TTYI2:	CAIN A,^Z	;TEST FOR ^Z
	 JRST ZFLAG	;^Z TYPED
TTYI2A:	JUMPL U,CPOPJ	;IGNORE CHAR IF NO USER.
	TLNE U,%TSSII	;If in superimage input mode,
	 JRST TTYI2B	; don't check for magic chars.
	CAIN A,%TXCTL+^Z	;Control-CALL is Deferred-Call
	 JRST [	MOVEI A,%TXACT+%TXPIE+%TXCTL+%TXTOP+"Z	;DEFERRED CALL
		JRST TTYI19 ]
	CAIN A,%TXTOP+"C	; CLEAR-INPUT does like TYCFLS, flushes
				; input buffer of TTY in I.
	 JRST TYIRS1		; TYIRS1 does a POPJ P, for us:  Hear no
				; evil, see no evil, echo no evil...
TTYI2B:	TLZ A,-1	;IF WE WERE CALLED FROM ^_-QUOTING RTN,  BIT 3.1 WAS
			;SET TO FAKE OUT ABOVE JUNK. FLUSH FAKEOUT BIT.
	MOVE E,TIME
	MOVEM E,TTITM(I) ;REMEMBER TIME OF LAST TYPE-IN ON TTY.
TTYI11:	MOVE E,TICC(I)
	CAIL E,TIBS	;SKIP IF ANY ROOM LEFT IN INPUT BUFFER
	 JRST DING1
	MOVE C,A
	ANDI C,%TXTOP+%TXASC
	CAIL C,141	;IF A LOWER CASE CHAR,
	 CAILE C,172
	  JRST TTYI15
	MOVE C,TTYOPT(I)
	TLNE C,%TOCLC	;CONVERT TO UPPER CASE IF WANTED
	 XORI A,40
TTYI15:	MOVE E,UPC(U)
	TLZ E,#%PCUSR
	CAIN E,NECHO1	;IS THE JOB EXECUTING AN ECHOIN RIGHT NOW?
	 SKIPE E,TACC(I)  ;IF SO, AND IF IT HASN'T HAD A BREAK CONDITION YET,
	  JRST TTYI12
	PUSHJ P,TTECIN	;MAYBE STORE CHAR IN USER MEMORY, AND JUST ECHO IT.
	MOVEI E,0	;E 0 IF CALLED TTECIN, NON-0 IF DIDN'T
TTYI12:	TRNN A,%TXACT	;IF TTECIN DIDN'T ACTIVATE IT, THEN IGNORE TTYSET BITS
	 JUMPE E,TTYI19	;AND DON'T ACTIVATE OR INTERRUPT NO MATTER WHAT.
	MOVE C,LEPCHR
	JUMPL C,TTYI19	;JUMP IF LOCAL EDITING PROTOCOL COMMAND CHAR.
	PUSHJ P,GETGRP	;GET 6 BIT BYTE FOR GROUP THIS CHARACTER IS IN
	TLZE U,%TSINT	;IF WANT THIS CHAR TO INT. WHATEVER IT IS,
	 IORI B,%TGINT	;PRETEND IT'S AN INT. CHAR.
	MOVEM U,TTYSTS(I)
	LSH B,14	;PUT %TXACT, %TXPIE, AND %TXMPE IN.
	TRNN A,%TXECI
	 IORI A,(B)
	ANDCMI A,%TXIGN+%TXINT+%TXCOM
	TRNN B,%TXINT	;TEST INTERRUPT BIT FOR THIS GROUP
	 JRST TTYI19	;OFF.  DON'T INTERRUPT
	HRRE B,U	;RH OF B IS USER INDEX
	JUMPL B,[JRST 4,.]	;SHOULDN'T BE NO USER
	HRL B,MSKST(B)	;LH OF B IS USER'S INTERRUPT MASK
	TLNN B,%PITYI	;SKIP IF INTERRUPTS ON TYPE IN ENABLED
	 JRST TTYI5	;DISABLED
	MOVEI C,%PITYI
	IORM C,PIRQC(B)	;GENERATE TYPE IN INTERRUPT REQUEST
	TRO A,%TXINT		;INDICATE INTERRUPT
TTYI5:	MOVE C,TYIMSK(I)	;GET TTY CHANNELS OPEN MASK
	AND C,MSKST2(B)	;MASK OFF CHANNELS NOT ENABLED
	JUMPE C,TTYI19	;JUMP IF NO OPEN CHANNELS HAVE INTERRUPTS ENABLED
	MOVN D,C
	AND C,D		;ISOLATE LEAST SIGNIFICANT BIT
	IORM C,IFPIR(B)	;GENERATE SECOND WORD INTERRUPT REQUEST
	IORI A,%TXINT	;INDICATE INTERRUPT
	JRST TTYI19

;LIKE TTYI18 BUT FOR A CHAR THAT WASN'T REALLY TYPED IN.
TTYI13:	IORI A,%TXCOM

;ECHO BUT DON'T USE AS INPUT THE CHAR IN A,
;ASSUMING IT WAS ACTUALLY TYPED IN BY USER. MUST NOT CLOBBER H, TT.
TTYI18:	IORI A,%TXPIE+%TXIGN	;THIS CHAR WILL ECHO & BE IGNORED.

;PUT CHARACTER IN A IN INPUT BUFFER, ADJUSTING ALL COUNTS AND POINTERS.
TTYI19:	MOVE C,TICC(I)
	CAIL C,TIBS
	 JRST DING1	;NO ROOM IN INPUT BFR => COMPLAIN.
	TRNE A,%TXACT	;IF ACTIVATION CHAR, COUNT IT.
	 AOS TACC(I)
	TRNE A,%TXPIE	;IF PI ECHO CHAR, COUNT IT.
	 AOS ECHOC(I)
	TRNE A,%TXINT	;SIMILAR FOR TINTC, TINTP IF INT. CHAR.
	 AOS TINTC(I)
	MOVE E,TICC(I)
	CAIL E,MICBAA
	 SKIPLE TACC(I)	;BUFFER FULL+ NO ACTV CHRS, GEN ONE
	  JRST TTYIS5
	AOS TACC(I)
	IORI A,%TXACT
TTYIS5:	MOVE E,TIIP(I)
	CAMN E,TIBEP(I)	;SKIP IF NOT OFF THE END OF THE CIRCULAR BUFFER
	 SUBI E,TIBL	;RESET TIIP
	HRRM E,TIIP(I)	;STORE BACK IN RH
	IDPB A,TIIP(I)	;STORE CHARACTER IN INPUT BUFFER
	AOS TICC(I)
	TRNN A,%TXPIE	;IF PI ECHO NEEDED,
	 POPJ P,
TTYI7:	MOVE C,TORM(I)
	CAIL C,TOBS
	 SKIPL TTYERQ(I);PUT THIS TTY ON LIST OF THOSE NEEDING ECHO
	  POPJ P,	;UNLESS IT'S ALREADY ON.
	TLNE I,-1
	 BUG
	MOVE C,TTERQS
	MOVEM I,TTERQS
	MOVEM C,TTYERQ(I)
	POPJ P,

DING1:	TLNE R,%TTDDI	;SKIP IF WANT TO DING ON EXCESS INPUT
	 POPJ P,
	MOVSI C,%TCDNG
	IORM C,TTYCOM(I)
	JRST TTYI7	;TELL CLOCK LEVEL TO LOOK AT THIS TTY.

TYCLWR:	PUSHJ P,TCNRM
	CAIL E,141	;CONVERT LOWER CASE LTRS TO UPPER
	CAILE E,172
	 POPJ P,
	SUBI E,40
	POPJ P,

TTYSAM:			;STANDARDIZE ALT MODE (IF APPRO)
	TLNE U,%TSALT+%TSSII	;SKIP IF ALT MODE NOT TO BE STANDARDIZED
	POPJ P,		;DON'T STANDARDIZE ALT MODE
	CAIE A,176	;ALT MODE CAN BE 176 OR
	CAIN A,175	;175
	MOVEI A,33	;CHANGE EITHER TO 33
	POPJ P,

;GETS BYTE IN B, GROUP NUMBER IN C, BYTE POINTER IN D
GETGRP:	PUSH P,A
	PUSHJ P,TYINR2	;NORMALIZE CHARACTER TO FIND CORRECT GROUP.
	MOVE B,A
	IDIVI B,5
	POP P,A
	LDB C,GRPBPT(C)	;GET GROUP BITS
	MOVEI D,TTYST1(I)
	CAIL C,6
	 JRST GETGR2
	LDB E,[301400,,SBTBL(C)]	;LOAD LH OF BYTE PTR
GETGR1:	DPB E,[301400,,D]	;MAKE TTYST1 OR TTYST2 APPROPRIATE BYTE POINTER
	LDB B,D
	POPJ P,

GETGR2:	LDB E,[301400,,SBTBL-6(C)]
	MOVEI D,TTYST2(I)
	JRST GETGR1

DEFINE	GGRPTB A,B,C,D,E
A_29.+B_22.+C_15.+D_8+E_1
TERMIN

GRPTBL:	GGRPTB 0,0,0,0,0
	GGRPTB 0,0,6,13,7
	GGRPTB 7,0,0,11,0
	GGRPTB 0,0,0,0,6
	GGRPTB 0,0,0,0,0
	GGRPTB 0,0,10,0,0
	GGRPTB 0,0,13,3,3
	GGRPTB 3,3,3,3,3
	GGRPTB 5,5,4,4,3
	GGRPTB 4,3,4,2,2
	GGRPTB 2,2,2,2,2
	GGRPTB 2,2,2,3,3
	GGRPTB 5,4,5,3,3
	REPEAT 5,GGRPTB 1,1,1,1,1
	GGRPTB 1,5,3,5,4
	GGRPTB 4,3,1,1,1
	REPEAT 4,GGRPTB 1,1,1,1,1
	GGRPTB 1,1,1,5,3
	GGRPTB 5,3,12,0,0

GRPBPT:	350700,,GRPTBL(B)
	260700,,GRPTBL(B)
	170700,,GRPTBL(B)
	100700,,GRPTBL(B)
	010700,,GRPTBL(B)

;HANDLE A CHARACTER TYPED WHILE THE TTY OWNER IS DOING AN ECHOIN.
;A HOLDS THE CHARACTER, U HOLDS THE JOB INDEX.  CLOBBERS B, C, E.
;IF THE CHARACTER IS A BREAK, ACTIVATE ON IT.
;OTHERWISE, STORE IT IN THE USER'S BUFFER AND JUST ECHO IT AND DISCARD IT;
;BUT IF THAT IS IMPOSSIBLE BECAUSE PAGES HAVE BEEN SWAPPED OUT,
;JUST ACTIVATE INSTEAD.
TTECIN:	HRRZ B,U		;PREVENT TIMING ERRORS BY NOT CONSIDERING
				; HIM INSIDE THE ECHOIN IF HE HAS THE
				; PROCESSOR, SINCE UPC NOT VALID.
IFE KA10P,[			;IF HIS USER-MODE ACS ARE IN AC BLOCK 1, WE
				; HAVE TO GIVE UP SINCE THEY MIGHT BE SAVED
				; IN TTYACS OR SOME PLACE.
	MOVEI C,UUOACS(U)
	CAME C,AC1PTR
] ;IFE KA10P
IFN KA10P,[			;ON KA10, DON'T DO THIS IF MPV IS SET
	CONSO 20000		;INTERRUPT OUT OF XCTR WITH PI TRAP SET
] ;KA10P			;GETS THE MACHINE VERY CONFUSED, I SUSPECT
	 CAMN B,USER
	  JRST TTECI9
	TRNN A,%TXCTL+%TXMTA+%TXSUP	;DECIDE WHETHER THIS CHAR ECHOES OR
					; BREAKS.
	 CAIGE A,40		;CONTROL CHARS, EITHER 9-BIT OR ASCII, BREAK.
	  JRST TTECI9		;NOTE THAT SAIL CHARS WILL HAVE %TXTOP.
	CAIN A,%TXTOP+"H	;DON'T ECHO HELP CHAR.
	 JRST TTECI9
	LDB B,[050200,,A]	;WHICH WORD OF BREAK TABLE IS THIS CHARACTER IN?
	ADD B,U			;JOB OWNING TTY
	MOVE B,AC0S+Q(B) .SEE NECHOIN  ;GET THAT WORD.
	LDB E,[0500,,A]
	LSH B,(E)		;GET THE BIT FOR THIS CHARACTER INTO THE SIGN BIT.
	JUMPL B,TTECI9		;IF BIT IS SET, THIS IS A BREAK CHARACTER.
	SPM TTECIM		;SAVE PAGE MAP AND LOAD UP TTY-OWNING JOB'S MAP.
	LPMR UPGML(U)
IFE KA10P,[
	JRST 2,@[%PSPCU,,.+1]	;XCTR DOESN'T WORK IF THIS BIT NOT SET
	DATAI PAG,TTECIX	;SAVE ACS CONTEXT ALSO, SET PREVIOUS AC
				; CONTEXT TO AC BLOCK 2, BUT DON'T CHANGE
				; CURRENT CONTEXT WHICH MAY BE 0 OR 1.
	MOVE B,[600200,,400000]	.SEE SPCCTX ;THIS DATAO PAG, IS SAME AS IN
					    ; AC2CTX.  (ALTHOUGH THERE ARE
					    ; A FEW SPURIOUS BITS SET ON
					    ; THE KS-10.)
	LDB C,[330300,,TTECIX]	;BUT TRANSFER CURRENT AC BLOCK INTO IT
	DPB C,[330300,,B]
	DATAO PAG,B
	MOVSI B,UUOACS(U)	;COPY THE JOB'S USER MODE ACS INTO THAT BLOCK.
	XCTR XBW,[BLT B,17]
] ;IFE KA10P
	MOVE C,AC0S+C(U)
	XCTRI XRW,[MOVES E,(C)]	;MAKE SURE THE COUNT IS STILL IN CORE AND > 0.
	 CAIG E,0
	  JRST TTECIL
	MOVE B,AC0S+B(U)
	XCTRI XRW,[MOVES E,(B)]	;MAKE SURE BYTE POINTER STILL IN CORE,
	 CAIA
	  JRST TTECIL
	IBP E
	XCTRI XRW,[MOVES (E)]	;AND THAT THE WORD THE CHARACTER WILL GO IN IS IN CORE
	 SKIPA E,AC0S+E(U)	; AND WRITABLE
	  JRST TTECIL
	XCTRI XRW,[MOVES (E)]	;MAKE SURE THE BLOCK OF COUNTERS IS STILL IN CORE.
	 CAIA
	  JRST TTECIL
	XCTRI XRW,[MOVES 6(E)]
	 CAIA
	  JRST TTECIL
	XCTRI XBYTE,[IDPB A,(B)]	;STORE THE CHARACTER.
	 CAIA
	  BUG
	XCTRI XRW,[SOS (C)]	;DECREMENT THE COUNT OF CHARS TO ECHO.
	 CAIA
	  BUG
	JUMPE E,TTECI2		;UPDATE THE BLOCK OF COUNTERS, IF THERE IS ONE.
	ADDI E,2		;THE FIRST TWO ARE IGNORED.
	HRLI E,-4		;THE NEXT FOUR ARE INCREMENTED.
TTECI1:	XCTRI XRW,[AOS (E)]
	 CAIA
	  BUG
	AOBJN E,TTECI1
	XCTRI XRW,[SOS (E)]	;THE SEVENTH IS DECREMENTED.
	 CAIA
	  BUG
;GOOD.  CHARACTER HAS BEEN STORED IN THE USER'S MEMORY.
TTECI2:	TRO A,%TXIGN\%TXPIE\%TXECI	;NOW MAKE IT ECHO.
	PUSHJ P,TTECIR
	POPJ P,

;WE CAN'T HANDLE A CHARACTER, SO MAKE IT ACTIVATE SO THE ECHOIN WILL RETURN.
;TTECIL IS FOR AFTER THE MAP HAS BEEN SWITCHED.  TTECI9 IS FOR BEFORE THEN.
TTECIL:	PUSHJ P,TTECIR
TTECI9:	IORI A,%TXACT
	POPJ P,

;RESTORE THE PAGE MAP THAT WE SAVED.
TTECIR:
IFE KA10P,[
	MOVEI B,UUOACS(U)	;COPY POSSIBLY ALTERED USER ACS BACK INTO
				; THE JOB.
	XCTR XBR,[BLT B,UUOACS+17(U)]
	DATAO PAG,TTECIX
] ;IFE KA10P
	LPMR TTECIM
	POPJ P,

EBLK

TTECIM:	BLOCK 10		;OUTER LEVEL MAP SAVED HERE AND RESTORED AT EXIT.
IF2 IFG UPGMLE-UPGML-10,.ERR TTECIM too short.
IFE KA10P,[
TTECIX:	0			;SAVED DATAI PAG VALUE.
]

BBLK

SUBTTL HANDLE ^Z

ZFLAG:	MOVSI U,%TSLCZ	;EVEN IF THIS BIT IN TTYSTS IS OFF, TTY MAY BE FREE
	IORB U,TTYSTS(I)	;GET TTYSTS
	JUMPGE U,ZFLAG2		;(TTY IS IN USE)
	SKIPGE TTYSTA(I)	;CONSOLE FREE MSG COMING OUT OR ALREADY TRYING TO ^Z
	 SKIPGE DEDTIM		;OR SYSTEM IS DOWN.  DON'T CREATE A NEW JOB TREE.
	  POPJ P,
	MOVN B,SYSDBG
	SKIPGE SYSDBG	;IF NOT ALLOWING USERS,
	 CAMN I,B	;ALLOW ONLY THE SPEC'D TTY (= -C(SYSDBG) )
	  JRST ZFLAG7
	MOVE B,TTYTYP(I) ;AND STY TTY'S, AS WELL AS TTY 0.
	TRNN B,%TYSTY	;NOTE STELNT WILL REFUSE NETWORK LOGINS WHEN SYS BEING DEBUGGED.
	 JUMPN I,CPOPJ
ZFLAG7:	CONO PI,PICOFF\<200_-UTCCHN>	.SEE NUJBST
	MOVE A,UTTYCT	;SET UP NEW USER
	CAIL A,MXCZS	;BUT DON'T OVERFILL BUFFER
	 JRST [ CONO PI,PICON\<200_-UTCCHN> ? POPJ P,]
	AOS UTTYCT
	HRRZM I,@UTTYI
	AOS A,UTTYI
	CAIL A,UTTYS+MXCZS
	 MOVEI A,UTTYS
	MOVEM A,UTTYI
	CONO PI,PICON\<200_-UTCCHN>
	MOVSI A,%TACTZ ;SAY TTY BEING ^Z'D - ELSE SYS JOB MIGHT TYPE CONSOLE-FREE MSG,
	IORM A,TTYSTA(I) ;SINCE TTY IS FREE AND %TACFM IS OFF (OR WILL BE AFTER TTYINI)
	JRST TTYINI

ZFLAG4:	HRR U,SUPPRO(U)
ZFLAG2:	SKIPL SUPPRO(U)
	 TLNE U,%TSSII
	  JRST ZFLAG3	;SUPER IMAGE INPUT MODE OR TOP LEVEL JOB
	TLNN U,%TSCNS	;OR IN USE AS A DEVICE => DON'T TREAT ^Z SPECIALLY
	 JRST ZFLAG3
	MOVEI E,%PIC.Z
	TDNE E,PIRQC(U)	;IF IMMEDIATE SUPERIOR DOESN'T RESPOND TO ^Z BY TAKING
	 JRST ZFLAG4	;THE TTY FROM THE ^Z'ED JOB, TRY FOR HIS SUPERIOR.
	IORM E,PIRQC(U) ;OTHERWISE GIVE ^Z INTERRUPT TO JOB
	PUSHJ P,TYIRS1	;DISCARD ALL PENDING INPUT BEFORE THE ^Z.
	MOVEI A,^Z+%TXPIE+%TXIGN
	JRST TTYI19	;ARRANGE FOR THE ^Z TO BE ECHOED.

ZFLAG3:	MOVSI U,%TSLCZ	;CLEAR <LAST CH WAS ^Z> BIT
	ANDCAB U,TTYSTS(I)
	JRST TTYI2A	;TREAT ^Z AS ANY OTHER CHAR.

SUBTTL HANDLE ^_

TTYICB:	TLNE U,%TSSII	;^_ NOT SPECIAL IF TTY IS IN USE, IN SUPERIMAGE INPUT.
	 JUMPGE U,TTYI2
	SKIPGE DEDTIM	;DON'T ALLOW ^_ IF ITS IS DOWN
	 POPJ P,
	JUMPGE U,TYCGTN	;DO ALLOW THEM ON ANY TTY THAT'S IN USE
	SKIPGE SYSDBG	;IF ITS BEING DEBUGGED, ALLOW ^_ IN SAME CASES ^Z IS ALLOWED.
	 TRNE R,%TYSTY
	  JRST TYCGTN
	MOVN B,SYSDBG
	CAME B,I
	 JUMPN I,CPOPJ
TYCGTN:	JSP D,TYCRDE	;ECHO IT, RETURN WITH NEXT CHAR TYPED.
TYCI:	SETOM COMT1(I)	;CHR AFTER ^_
	PUSHJ P,TCNRM
	CAIE E,^_
	 CAIN E,^Z
	  JRST TYCI3A	;GIVE EITHER CHARACTER TO MAIN PROGRAM
	CAIL E,^B
	 CAILE E,^D	;^B, ^C, ^D, ^F SIGNIFY META BITS BEING SPEC'D.
	  CAIN E,^F
	   JRST TYCMB
	CAIL E,"0	;DIGIT => CHARATER BEING TYPED IN BY ITS ASCII CODE.
	 CAILE E,"9
	  JRST TYCI7	;JUMP IF NOT A DIGIT.
	MOVEI B,-"0(E)
	MOVEM B,COMT1(I)	;STORE FIRST DIGIT
	JSP D,TYCRDE	;ECHO DIGIT, READ ANOTHR. (TTYIPC LEFT -> TYCI4)
TYCI4:	PUSHJ P,TYCI22	;READ NUM AFTER FIRST DIGIT
	 JRST TYCI6	;CHARACTER IS NON-NUMERIC
	JRST TTYI18	;ECHO THE DIGIT - IT'S ALREADY HANDLED.

TYCI3A:	TRNN H,%TP11T		;ON NON-TV TERMINALS,
	 MOVEI A,%TXCTL+100(E)	;MAKE QUOTED ^Z LOOK LIKE "CONTROL" AND "Z" IN FULL
TYCI3:	PUSHJ P,TYCI17	;RESTORE TTYIPC TO NORMAL,
	HRLI A,1	;PREVENT CHAR FROM BEING TAKEN AS ^Z OR ^_.
	JRST @TTYIPC(I)	;HANDLE CHAR (BUT QUOTE ^_ AND ^Z)


TYCI22:	LDB E,[700,,A]
	CAIL E,"0
	 CAILE E,"9
	  POPJ P,	;RETURN WITHOUT SKIPPING IF NON-NUMERIC
	MOVE B,COMT1(I)
	LSH B,3
	ADDI B,-"0(E)
	MOVEM B,COMT1(I)	;UPDATE VALUE SO FAR
	JRST POPJ1	;SKIP RETURN

TYCMB:	SETZM COMT1(I)	;^A THRU ^F SEEN - INITIALIZE, AND DECODE THE CHARACTER.
	JRST TYCMB2

TYCMB1:	IORM D,COMT1(I)	;SET THE SPEC'D META-BIT AND READ ANOTHER CHAR.
	JSP D,TYCRDE	;WHICH WE THEN DECODE ...
TYCMB2:	SETZ D,
	PUSHJ P,TCNRM
	CAIN E,^B
	 IORI D,%TXCTL
	CAIN E,^C
	 IORI D,%TXMTA
	CAIN E,^D
	 IORI D,%TXTOP
	CAIN E,^F
	 IORI D,%TXSUP
	JUMPN D,TYCMB1	;IF CHAR WAS ^B THRU ^F, SET APPRO META-BIT AND LOOP.
	CAIN E,^Q
	 JSP D,TYCRDE	;OTHERWISE, ^Q QUOTES,
	IOR A,COMT1(I)	;JUST READ THE CHARACTER, WITH SPEC'D META-BITS MERGED IN.
	JRST TYCI3

TYCI2:	PUSHJ P,TTYI18	;ECHO CHAR, RESET TTYIPC TO NORMAL.
TYCI17:	MOVEI B,TYCG
	SKIPL Q
	 MOVEI B,TTYI
	MOVEM B,TTYIPC(I)
	TLZ Q,%TCCBS+%TCCBK	;ALSO FLUSH TEMPORARY STATUS INFO.
	MOVEM Q,TTYCOM(I)
	POPJ P,

TYCI6:	EXCH A,COMT1(I)	;A NOW HAS CHAR REPRESENTED BY DIGITS; COMT1 HAS THE NON-DIGIT JUST TYPED IN.
	ANDI A,7777
	PUSH P,I	;IF IN COME MODE, TYCI3 CALLS TYCG AND SMASHES I
	PUSHJ P,TYCI3	;SIMULATE ITS TYPE IN
	POP P,I
	MOVE A,COMT1(I)	;GET LAST CHARACTER TYPED
	CAIN A,40	;A SPACE GETS FLUSHED FOLLOWING DIGITS
	 POPJ P,
	MOVE Q,TTYCOM(I) ;RESTORE ACS BASHED BY TYCG
	MOVE R,TTYTYP(I)
	MOVE H,TTYOPT(I) ;THIS ONE MAY BE SUPERFLUOUS
	MOVE U,TTYSTS(I)
	JRST @TTYIPC(I)	;PROCESS IT NORMALLY

TCNRM:	MOVE E,A
	PUSHJ P,TYINR2
	EXCH E,A
	POPJ P,

TYCI7:	PUSHJ P,TYCLWR	;NON-DIGIT, NON-^Z, NON-^_ AFTER ^_.
	CAIN E,^U	;^U is CLEAR INPUT.
	 JRST TYCFLS
	CAIL E,"A	;IF IT'S A LETTER,
	CAILE E,"Z
	 JRST TYCI7A
	XCT TYIQT-"A(E)	;JUST DISPATCH ON IT.
	MOVEM H,TTYOPT(I)
TYCI7D:	MOVEM U,TTYSTS(I)
	JRST TYCI2

TYCI7A:	CAIE E,""	;ASIDE FROM LETTERS, " AND ^ ARE OK.
	CAIN E,"^
	 JRST TYCI7B
TYCI7F:	MOVEI A,"?	;OTHER CHARS ARE ERRORS.
TYCI2A:	PUSHJ P,TTYI13	;ECHO A CHARACTER THAT WASN'T INPUT, AND RESET TTYCOM AND TTYIPC.
	JRST TYCI17

TYCI7B:	CAIE E,""
	 TLCA U,%TSROL	;^_^ COMPLEMENTS SCROLL MODE.
	  TLC U,%TSSAI	;^_" COMPLEMENTS SAIL CHAR SET USAGE.
	JRST TYCI7D

TYIQT:	JRST TYCA	;A => ACCEPT COM LINKS.
	JRST TYCB	;B => TRIGGER A **MORE** (BLOCK TYPEOUT).
	JRST TYCC	;C => CREATE COM LINK.
	JRST TYCD	;D => DEFERRED CALL
	JRST TYCRFT	;E => ENTER REMOTE FEED-THRU.
	JRST TYCI7F	;F => ERROR.
	TLC U,%TSMOR	;G => COMPLEMENT MORE-PROCESSING.
	JRST TYCH	;H => HELP KEY.
	TLC Q,%TCICO	;I => COMPLEMENT INPUT OVERRIDE.
	JRST TYCJ	;J => Cause %PIJST interrupt.
	JRST TYCK	;K => FLUSH SPEC'D TTY FROM COM LINK.
	MOVEI A,^L+%TXIGN+%TXCOM	;L => CLEAR SCREEN.
	TLC U,%TSMOR	;M => COMPLEMENT MORE-PROCESSING.
	JRST TYCN	;N => BREAK COM LINK.
	TLC Q,%TCOCO	;O => COMPLEMENT OUTPUT COM OVERRIDE.
	JRST TYCI7F	;P => ERROR.
	JRST TYCQ	;Q => ENTER QUERY MODE.
	JRST TYCR	;R => ENTER REFUSE MODE.
	JRST TYCS	;S => SLAVE ANOTHER TTY.
	JRST TYCI7F	;T => ERROR.
	TLC H,%TOCLC	;U => COMPLEMENT CASE-CONVERSION.
	JRST TYCI7F	;V => ERROR.
	JRST TYCI7F	;W => ERROR.
	JRST TYCI7F	;X => ERROR.
	JRST TYCQA	;Y => ACCEPT PENDING QUERIES FOR COM LINKS
	JRST TYCQR	;Z => REJECT PENDING QUERIES.

IFN .-TYIQT-26.,.ERR WRONG LENGTH TABLE.

;PUT IN A DEFERRED CALL
TYCD:	PUSHJ P,TTYI18	;ECHO THE D
	MOVEI A,%TXACT+%TXCTL+%TXTOP+"Z
	PUSHJ P,TTYI19	;PUT A DEFERRED CALL IN THE BUFFER
	JRST TYCI17	;RESET ^_ STATE

;HELP KEY
TYCH:	PUSHJ P,TTYI18	;ECHO THE H
	MOVEI A,%TXACT+%TXTOP+"H
	PUSHJ P,TTYI19	;PUT A [HELP] IN THE BUFFER
	JRST TYCI17	;RESET ^_ STATE

;Cause %PIJST interrupt.
TYCJ:	SKIPA B,[%PIJST]
TYCJ1:	 MOVE U,SUPPRO(U)
	JUMPL U,TYCI7F		; Error if tty not in use or nobody enabled
				; for it.
	TDNN B,MSKST(U)
	 JRST TYCJ1
	IORM B,PIRQC(U)
	JRST TYCI2		; Echo the J and reset ^_ state.

;CLEAR INPUT
TYCFLS:	CONO PI,TTYOFF	;No touching buffer while I'm frobbing it.
	PUSHJ P,TYIRS1  ;Completely flush input buffer of TTY in I.
	CONO PI,TTYON
	MOVEI A,^U
	PUSHJ P,TTYI13	;Can echo the ^U now.
	JRST TYCI17	;Reset ^_ state.


TYCB:	HRRZ B,I	;COME HERE FOR ^_B.
	IMULI B,TPLEN*2
	MOVEI C,%TFEOP
	IORM C,TPFLAG(B)
	JRST TYCI2

TYCRFT:	PUSH P,A	;COME HERE FOR ^_E.
	MOVE A,TTYTYP(I)      ;ARE WE A LOCAL TTY?
	TRNN A,%TYDIL\%TYRLM\%TYSTY
	  JRST TYCRF0	;LOCAL TTYS ARE ALLOWED TO SLAVE W/O LOGIN
	TRNN A,%TYSTY	;Is it a STY?
	  JRST TYCRFA	;  Nope
	HRRZ A,STYSTS-NFSTTY(I)	   ;Special Check for TARAKA demons linking
	MOVE A,UNAME(A)		   ;Is the UNAME of the owner of this STY
	CAMN A,[SIXBIT /TARAKA/]   ;TARAKA?
	  JRST TYCRF0		   ;Yes, let it hack all it wants.
TYCRFA:	HRRE A,TTYSTS(I)       ;GET OWNER OF THIS TTY
	AOJE A,TYCRF2	       ;IF THIS IS A FREE TTY, DON'T LET HIM
	HLRE A,UNAME-1(A)      ;IS HE LOGGED IN?
	AOJE A,TYCRF2	;  IF NOT, FAIL
TYCRF0:	SETZ B,		;COMPLEMENT OUR %TCRFT BIT.
	PUSHJ P,TYCREP	;1ST, COUNT # TTYS IN LOOP.
	    PUSHJ P,[
		MOVE A,TTYCOM(I)
		TLNE A,%TCLFT	;IF ANY TTY IN LOOP HAS %TCLFT SET
		 POPJ P,	;THEN IT'S OK FOR OUR %TCRFT TO BE.
		AOJA B,POPJ1]
	 JRST TYCRF1	;SOME TTY IN LOOP HAS %TCLFT => OK TO SET %TCRFT.
	CAIE B,2	;ONLY 1 OTHER TTY => SET ITS %TCLFT, THEN OUR %TCRFT.
	 JRST TYCRF2	;FAIL TO SET %TCRFT IF CAN'T FIND OTHER WITH %TCLFT.
	MOVE A,TTYCOM(I)
	MOVSI B,%TCLFT
	IORM B,TTYCOM(A)
TYCRF1:	TLC Q,%TCRFT
	POP P,A
	JRST TYCI7D

TYCRF2:	SUB P,[1,,1]
	JRST TYCI7F

;COME HERE AFTER READING UNAME FOR ^_S. B HAS IDX OF SPEC'D TTY.
;SET THAT TTY'S %TCLFT, ENSLAVING IT. CLEAR %TCLFT OF ALL OTHER TTYS
;IN THE SAME LOOP AS SPEC'D TTY.
TYCS1:	PUSHJ P,TYCREP
	    CAIN B,(I)	;IF SPEC'D TTY NOT IN COM WITH US
	 CAIA
	  JRST TYCI7F	;THEN IT'S AN ERROR.
	MOVSI A,%TCLFT
	PUSHJ P,TYCREP	;CLEAR %TCLFT OF ALL TTY'S LINKED TO US,
	    ANDCAM A,TTYCOM(I)
	 JFCL
	IORM A,TTYCOM(B) ;THEN SET IT FOR HIM.
	POPJ P,

;CALL WITH JSP D,  ECHO CHAR IN A, RETURN WITH NEXT CHAR.
TYCRDE:	HRRZM D,TTYIPC(I)
	JRST TTYI18

;LIKE TYCRDE BUT DON'T ECHO THE CHARACTER IN A.
TYCRED:	HRRZM D,TTYIPC(I)
	POPJ P,

;T -> ASCIZ STRING, ECHO ON TTY # IN I (MUST HAVE DONE TYCSET)
TYCI40:	HRLI T,440700
TYCI39:	ILDB A,T
	JUMPE A,CPOPJ
	PUSHJ P,TTYI13	;ECHO CHARACTER ON TTY
	JRST TYCI39

;SET UP ACS FOR ECHOING ON TTY # IN I.
TYCSET:	MOVE R,TTYTYP(I)
	MOVE Q,TTYCOM(I)
	MOVE U,TTYSTS(I)
	POPJ P,

;PUT TTY IN COM MODE IF IT ISN'T. TTY # IN I.
TYCI63:	TLON Q,400000
	 TLZ Q,%TCLFT+%TCRFT
	MOVEM Q,TTYCOM(I)
	JRST TYBC

;TTY # IN I, REPEAT OVER THAT TTY AND ALL LINKED TO IT.
;INSN TO BE REPEATED FOLLOWS CALL.
;IF THE INSN DOESN'T SKIP, IMMEDIATELY RERURNS
;SKIPPING ONLY THAT INSN. ELSE RETURNS SKIPPING 2 WHEN ALL TTYS DONE.
TYCREP:	PUSH P,I	;PUSH TTY STARTING WITH.
	PUSH P,I	;PUSH TTY DOING NEXT.
TYCRE0:	XCT @-2(P)	;(THE INSN AFTER THE PUSHJ)
	 JRST TYCRE1	 ;IT DIDN'T SKIP, GIVE UP RIGHT AWAY.
	MOVE I,(P)	;ELSE KEEP GOING,
	SKIPL I,TTYCOM(I)
	 JRST TYCRE2	;LAST TTY DONE NOT LINKED, THRU.
	ANDI I,-1
	CAIE I,-1	;IN COM MD BUT NOT LINKED OR
	CAMN I,-1(P)	;HAVE GONE ALL AROUND CIRCULAR LIST
	 JRST TYCRE2	 ;=> DONE.
	MOVEM I,(P)	;ELSE DO THE NEXT ONE.
	JRST TYCRE0

TYCRE2:	AOS -2(P)	;RETURN SKIPPING 2.
TYCRE1:	SUB P,[1,,1]
	POP P,I
	JRST POPJ1

;^_A - ACCEPT ALL PENDING AND FUTURE REQUESTS FOR COM LINKS.
TYCA:	TLZ Q,%TCRFS+%TCQRY

;^_Y - ACCEPT ALL PENDING REQUESTS FOR COM LINKS.
TYCQA:	PUSHJ P,TYCI2		;ECHO THE A OR Y.
	PUSHJ P,TYCQRP		;FIND ALL PENDING QUERIES
	    PUSHJ P,TYCQAC	;ACCEPT EACH ONE.
	POPJ P,

TYCQAC:	PUSHJ P,TYCREP		;DON'T ACCEPT A RQ FROM SOMEONE ALREADY LINKED TO US.
	    CAIN B,(I)
	 POPJ P,
	MOVE H,B		;HIS TTY # IN H FOR TYCI43
	PUSHJ P,TYCSET
	PUSHJ P,TYCI43		;LINK HIM AND ME; ECHANGE I AND H.
	MOVE B,I
	MOVE I,H		;GET HIS # BACK IN B AND MINE IN I.
	POPJ P,

;^_R - REFUSE ALL PENDING AND FUTURE REQUESTS FOR COM LINKS.
TYCR:	TLO Q,%TCRFS
	TLZ Q,%TCQRY

;^_Z - REFUSE ALL PENDING REQUESTS FOR COM LINKS.
TYCQR:	PUSHJ P,TYCI2		;ECHO THE R OR Z.
	PUSHJ P,TYCQRP		;FIND ALL PENDING QUERIES
	    PUSHJ P,TYCQRF	;AND REFUSE EACH ONE.
	POPJ P,

TYCQRF:	EXCH B,I
	PUSHJ P,TYCSET		;TYPE ON REQUESTING TTY
	PUSHJ P,TYCI36		;THAT IT IS BEING REJECTED
	EXCH B,I		;AND REMOVE IT FROM A QUERYING STATE.
	POPJ P,

;^_Q - ALL REQUESTS FOR COM LINKS SHOULD REMAIN PENDING UNTIL ANSWERED
;WITH ^_Y, ^_Z OR AN INVERSE ^_C.
;ALSO, LIST ALL REQUESTS THAT ARE NOW PENDING.
TYCQ:	TLZ Q,%TCRFS
	TLO Q,%TCQRY
	PUSHJ P,TYCI2		;ECHO THE "Q" AND RESET ALL STATUS INFO.
	PUSHJ P,TYCSET
	SETZ T,			;INDICATE NOTHING HAS BEEN TYPED YET.
	PUSHJ P,TYCQRP		;FIND THE PENDING REQUESTS
	    PUSHJ P,TYCQLS	;SAY WHO EACH IS FROM.
	POPJ P,

TYCQLS:	JUMPE T,TYCQL1		;IF THIS ISN'T THE FIRST NAME MENTIONED,
	MOVEI T,[ASCIZ/, /]	;SEPARATE FROM THE PREVIOUS NAME.
	PUSHJ P,TYCI40
TYCQL1:	MOVE C,B		;THIS IS TTY NUMBER QUERYING US
	PUSH P,C	.SEE TYCI92
	PUSH P,[POPCJ-1]	;TYCI67 ALWAYS SKIP-RETURNS.
	JRST TYCI67		;TYPE THE USER'S NAME OR THE TTY NUMBER.

;	PUSHJ P,TYCQRP
;	    INSN
;EXECUTES INSN ONCE FOR EACH TTY QHICH IS QUERYING THE TTY IN I.
;THE QUERYING TTY'S NUMBER IS IN B. INSN MUST PRESERVE B AND I.
;A IS CLOBBERED BY TYCQRP. OTHER ACS ARE UNTOUCHED.

TYCQRP:	SETZ B,
TYCQR1:	MOVE A,TTYIPC(B)
	CAIE A,TYCRW
	 CAIN A,TYCRW2
	  CAME I,COMT1(B)
	   JRST TYCQR2	;TTY IN B ISN'T QUERYING TTY IN I.
	XCT @(P)	;EXECUTE INSN.
TYCQR2:	CAIE B,NCT-1
	 AOJA B,TYCQR1
	JRST POPJ1	;SKIP OVER INSN WHEN RETURN.

SUBTTL HANDLE COM-LINKS

TYCC:	TLOA Q,%TCTPN	;^_C - WHEN LEAVE COM MODE MUST TYPE ^_N.
TYCK:	 TLO Q,%TCCBK	;SAY WE'RE DOING ^_K.
	JRST TYCI19

TYCS:	TLO Q,%TCCBS	;^_S - ENSLAVE SPEC'D TTY.
TYCI19:	MOVEM Q,TTYCOM(I)
	JSP D,TYCRDE	;ECHO, RETURN, COME BACK WITH NEXT CHAR.
	PUSHJ P,TCNRM
	CAIE E,15	;SPACE OR CR IS 1ST CHAR, IGNORE.
	 CAIN E,40
	  JRST TTYI18
	MOVEI B,TYCI27
	MOVEM B,TTYIPC(I)
	SETZM COMT3(I)	;INIT. ACCUMULATED #.
	SETZM COMT1(I)	;AND ACCUM UNAME.

;READING CHARS AFTER ^_C (AFTER A NON-SPACE HAS BEEN SEEN)
;COMT1 ACCUMULATES SIXBIT, COMT3 OCTAL NUMBER.
;SIGN OF COMT3 SET => NONDIGIT WAS SEEN, USE THE SIXBIT.
TYCI27:	PUSHJ P,TYCLWR	;CONVERT TO UPPER CASE.
	CAIN E,^_
	 JRST TYCI7F	;ANOTHER ^_ IS NO GOOD.
	CAIE E,15
	 CAIN E,40
	  JRST TYCI28	;SPACE DELIMITS UNAME OR NUMBER
	CAIN E,^^
	 JRST TYCI28
	CAIN E,177
	 JRST TYCI7F	;RUBOUT => TYPE ? AND GIVE UP.
	MOVE B,COMT3(I)	;ACCUM NUMBER IN RH OF COMT3.
	LSH B,3
	ADDI B,-"0(E)
	HRRM B,COMT3(I)
	CAIL E,"0
	CAILE E,"9	;NON-DIGIT SEEN => SET SIGN OF COMT3 SAYING
	 SETOM COMT3(I)	;CERTAINLY NOT NUMBER.
	MOVE B,COMT1(I)
	LSH B,6
	IORI B,-40(E)
	MOVEM B,COMT1(I)	;ADD NEW CHARACTER ONTO THE END OF THE NAME
	JRST TTYI18	;EXIT TO ECHO THE CHARACTER

TYCI28:	MOVE H,Q	;SAVE SETTINGS OF %TCCBS, %TCCBK, SINCE TYCI2 WILL CLEAR THEM.
	PUSH P,E
	PUSHJ P,TYCI2	;ECHO TERMINATING CHAR IN A, AND RESET ALL TO NORMAL.
	POP P,E
	SKIPGE B,COMT3(I)
	 JRST TYCI52	;TYPEIN WASN'T NUMBER.
	CAIGE B,NCT	;IS NUMBER THAT OF A TTY THAT EXISTS?
	 JRST TYCI53
TYCI52:	MOVE D,COMT1(I)
TYCI29:	TLNE D,770000	;LEFT ADJUST THE UNAME
	 JRST TYCI30
	LSH D,6
	JRST TYCI29

TYCI30:	MOVEI U,LUBLK	;START LOOKING AT USER NUMBER 2
	MOVSI A,%TCRFS
	SETO B,		;NO REFUSE-MODE TTY FOUND YET
TYCI31:	ADDI U,LUBLK
	CAML U,USRHI
	 JRST [	JUMPGE B,TYCI36	;REFUSED
		JRST TYCI7F ]	;OUT OF USERS SO GIVE ? AND RETURN
	CAMN D,UNAME(U)	;SKIP IF UNAME DOESN'T MATCH
	 SKIPGE C,TTYTBL(U)	;SKIP IF PROCEDURE HAS THE TTY
	  JRST TYCI31	;TRY NEXT PROCEDURE
	HRRZ B,C	;TTY NUMBER
	TDNE A,TTYCOM(B)	;IN REFUSE MODE?
	 JRST TYCI31	;YES, MAY BE CRTSTY, TRY TO FIND A BETTER TTY WITH THIS UNAME
TYCI53:	MOVEM B,COMT1(I) ;# OF TTY TRYING TO HACK
	SETZM COMT3(I)	;IEC FLAG FOR QUERY MODE
	CAIN E,^^
	 SETOM COMT3(I)
	TLZE H,%TCCBK	;JUMP IF DOING ^_K.
	 JRST TYCK1
IFG APL,[
	CAIN B,APL	;DON'T SEND MESSAGE TO A.P. LINE
	 JRST TYCI7F	;(OK NOW TO SEND TO SYSTEM CONSOLE, HAS O.C.O. ANYWAY)
]
	TLZE H,%TCCBS
	 JRST TYCS1	;ALSO CHECK FOR ^_S.
	PUSHJ P,TYCREP	;NO, IT'S ^_C.
	    CAIN B,(I)	;DON'T LET LINK TO SELF OR SOMEONE ALREADY LINKED TO.
	 JRST TYCI7F
	HRRE C,TTYSTS(B)
	AOJN C,TYCI34	;TTY HAS A USER
	MOVEI A,"F	;TTY IS FREE
	PUSHJ P,TTYI13	;TYPE AN F
	MOVEI A,40
	PUSHJ P,TTYI13	;FOLLOWED BY A SPACE
	MOVE B,COMT1(I)	;RESTORE THAT TTY'S NUMBER.
	JRST TYCI32

TYCI34:	MOVE C,TTYSTS(B) ;TTY IN USE: AS A DEVICE?
	TLNN C,%TSCNS
	 JRST TYCI7F	;^_C NOT ALLOWED TO TTY OPEN AS DEVICE.
TYCI32:	MOVE A,TTYIPC(B)
	CAIE A,TYCRW2
	 CAIN A,TYCRW	;IF HE'S QUERYING ME, THEN HE AUTOMATICALLY ACCEPTS
	  JRST [CAME I,COMT1(B)	;REGARDLESS OF HIS %TCRFS AND %TCQRY.
		 JRST TYCI37	;IF HE'S QUERYING SOMEONE ELSE, HE'S BUSY.
		JRST TYCI33]
	MOVE C,TTYCOM(B)
	TLNE C,%TCRFS	;GIVE UP IF HE IS REFUSING ^_C'S.
	 JRST TYCI36
	CAIN A,TTYI	;MUNGING IPC WHILE NOT NORMAL WOULD LEAVE
	 JRST TYCI44	;WHAT HE'S DOING UNFINISHED - CAUSING BUGS.
	CAIE A,TYCG
	 JRST TYCI37	;IPC NOT NORMAL.
	MOVEM B,COMT1(I) ;IPC NORMAL BUT HE'S IN A COM LINK.
	MOVE TT,I
	MOVE H,B	;MY TTY # IN TT AND I, HIS IN H.
	MOVEI T,[ASCIZ/ IN COM: /]
	PUSHJ P,TYCI71	;LIST ALL TTYS IN COM WITH HIM.
	 JFCL
	MOVEI T,[ASCIZ/
BREAK IN? /]
	PUSHJ P,TYCI40	;PRINT STRING ON MY TTY.
	JSP D,TYCRED	;READ THE ANSWER
	PUSHJ P,TTYI18	;AND ECHO IT.
	PUSHJ P,TYCLWR	;NORMALIZE IT AND CONVERT TO UPPER CASE IN E.
	CAIE E,"Y
	 JRST TYCI17	;NO => RESET US TO NORMAL AND GIVE UP.
	MOVE B,COMT1(I)	;ANSWER IS YES, GO AHEAD.
	MOVE A,TTYIPC(B)
	CAIE A,TTYI
	CAIN A,TYCG
	CAIA
	 JRST TYCI37	;CAN'T MUNG HIM IF IPC NOT NORMAL.
	MOVE C,TTYCOM(B)
	TLNE C,%TCRFS
	 JRST TYCI36	;HE'S REFUSING.
TYCI33:	PUSHJ P,TYCREP
	    CAIN B,(I)	;MAYBE HE ENTERED OUR LOOP WHILE WE WAITED.
	 JRST TYCI7F	;LINKING TO SOMEONE ALREADY LINKED TO CAUSES BUGS.
	JRST TYCI44	;GO AHEAD AND LINK UP.

TYCI37:	SKIPA T,[[ASCIZ/BUSY /]]	;TARGET IS BUSY.
TYCI36:	 MOVEI T,[ASCIZ/REFUSED /]	;TARGET IS REFUSING.
	PUSHJ P,TYCI40
	JRST TYCI17

;NOW WE KNOW IT'S OK TO TRY TO ^_C HIM. HIS TTY # IN B, MINE IN I.
TYCI44:	MOVE H,I	;PUT MY TTY # IN H, HIS IN I.
	MOVE I,B
	SETO TT,
	PUSHJ P,TYCSET	;GET HIS TTYCOM IN Q FOR TYCI63
	PUSHJ P,TYCI64	;TYPE MSG FROM ME ON HIM.
	 JFCL
	MOVE A,TTYIPC(I)
	CAIE A,TYCRW2	;IF HE'S QUERYING US, NO NEED TO QUERY HIM;
	 CAIN A,TYCRW	;JUST PRETEND HE'S IN ACCEPT MODE.
	  JRST TYCI43
	MOVSI A,%TCQRY
	TDNN A,TTYCOM(I) 		;SKIP IF HE MUST BE ASKED
	 JRST TYCI43	 		;HE'S IN ACCEPT MODE.
	MOVEI T,[ASCIZ /- QUERYING/]	;ELSE JUST MENTION TO HIM THAT WE'RE QUERYING
	SKIPL COMT3(H)
	 PUSHJ P,TYCI40
	MOVEM I,COMT1(H)		;AND SETTLE DOWN FOR HIM TO DO SOMETHING ABOUT IT.
	MOVEI A,TYCRW
	MOVEM A,TTYIPC(H)
	MOVE I,H
	PUSHJ P,TYCSET
	MOVEI T,[ASCIZ /QUERYING /]	;TELL OUR USER THAT WE'RE WAITING FOR ANSWER.
	JRST TYCI40

TYCI68:	CAIN TT,(I)	;ENTRY TO DO FOR ALL LINKED TO HIM BUT NOT HIM.
	 JRST POPJ1
TYCI64:	MOVEI T,[ASCIZ /
MESSAGE FROM /]
	MOVE R,LOCTTY
	MOVE R,TTYTYP(R)
	TRNN R,%TYSTY
	 JRST TYCI62
	MOVE R,LOCTTY
	MOVE R,STYSTS-NFSTTY(R)
	MOVE R,JNAME(R)
	CAME R,[SIXBIT /PEEK/]	;THIS SEEMS TO BE A CROCK --RG
TYCI62:	 MOVEI T,[ASCIZ /
LINK FROM /]
TYCI71:	PUSHJ P,TYCSET	;SET UP Q,R,U,W FOR HIS TTY (# IN I)
	PUSHJ P,TYCI40	;PRINT MSG <- T ON IT.
	PUSH P,I	;SAVE HIS TTY #,
	MOVE I,H	;GET MINE (ARG TO TYCREP)
	PUSHJ P,TYCREP	;LOOP OVER ME AND ALL ALREADY LINKED TO ME.
	    PUSHJ P,TYCI66
	 JFCL
TYCI41:	POP P,I
	MOVEI A,40
	PUSHJ P,TTYI13
	JRST POPJ1

;TYPE UNAME OF 1 OF MY TTYS ON 1 OF HIS.
TYCI66:	HRRZ C,TTYCOM(H)
	CAIE C,-1
	 JRST TYCI72
	CAIN H,(I)	;BUT DON'T TYPE MY NAME ON HIM.
	 CAME TT,-4(P)
	  CAIA
	   JRST POPJ1
TYCI72:	MOVEI C,(I)	;PUT THIS TTY # IN C,
	MOVE I,-4(P)	;GET HIS BACK IN I SINCE STILL TYPING ON HIM.
	CAMN C,-2(P)	;IF THIS ISN'T MY TTY,
	 JRST TYCI67
	MOVEI T,[ASCIZ/ AND /] ;THEN IT'S SOMEONE LINKED TO ME
	PUSHJ P,TYCI40	;AND MY NAME WAS ALREADY TYPED
	MOVE C,-1(P)
TYCI67:	HRRE C,TTYSTS(C)	;MY USER INDEX
	JUMPL C,TYCI92
	MOVE C,UNAME(C)
	HLRE A,C
	AOJE A,TYCI92
TYCI91:	PUSH P,C
	MOVSI T,(440600,,(P))
TYCI42:	ILDB A,T
	JUMPE A,POP1J1
	ADDI A,40	;CONVERT MY UNAME FROM SIXBIT TO ASCII
	PUSHJ P,TTYI13	;ECHO CHARACTER ON HIS TTY
	TLNE T,770000
	JRST TYCI42
	JRST POP1J1


TYCI92:	MOVSI C,(SIXBIT /T/)
	LDB T,[030300,,-1(P)]
	ADDI T,20
	DPB T,[300600,,C]
	LDB T,[000300,,-1(P)]
	ADDI T,20
	DPB T,[220600,,C]
	JRST TYCI91

;ACTUALLY JOIN MY TTY AND HIS IN COM LINK.
;ENTER WITH HIS TTY # IN I AND MINE IN H.
;LEAVE WITH MINE IN I AND HIS IN H, TT.
TYCI43:	TLO Q,%TCTPN	;WHEN HE LEAVES COM MODE TYPE ^_N AT HIM.
	PUSHJ P,TYCI63	;PUT HIM IN COM MODE IF HE ISN'T ALREADY.
	MOVE TT,I	;HIS TTY # IN TT, MINE IN H.
	PUSHJ P,TYCREP	;LOOP OVER TTYS LINKED TO HIM.
	    PUSHJ P,TYCI68	;PRINT OUT MSG FROM ON ALL LINKED TO HIM, NOT HIM.
	 JFCL
	EXCH TT,H	;INTERCHANGE HIS AND MINE.
	MOVE I,TT	;LOOK AT ALL LINKED TO ME.
	PUSHJ P,TYCSET	;WHEN I CHANGES, RELATED ACS SHOULD ALSO CHANGE.
	TLO Q,%TCTPN	;WHEN HE LEAVES COM MODE TYPE ^_N AT HIM.
	PUSHJ P,TYCI63	;PUT HIM IN COM MODE IF HE ISN'T ALREADY.
	PUSHJ P,TYCREP	;ON EACH OF MINE, GIVE NAMES OF HIS.
	    PUSHJ P,TYCI69
	 JFCL
	MOVE TT,H
	MOVE A,TTYCOM(TT)	;SET UP LINK
	MOVE B,TTYCOM(I)	;LINK TTYCOM WORDS
	HRRE E,A
	AOJN E,TYCI45
	HRRM TT,A
TYCI45:	HRRE E,B
	AOJN E,TYCI46
	HRRM I,B
TYCI46:	HRRZ D,A
	HRRZ E,B
	HRRM E,A
	HRRM D,B
	MOVEM A,TTYCOM(TT)
	MOVEM B,TTYCOM(I)
	MOVEI A,TYCG
	MOVEM A,TTYIPC(I)
	MOVEM A,TTYIPC(TT)
	POPJ P,

TYCI69:	CAIE I,(TT)	;PRINT MSG ON ONE OF MY TTYS.
	 JRST TYCI70
	SKIPA T,[[ASCIZ/OK /]]	;MY TTY, SAY "G".
TYCI70:	 MOVEI T,[ASCIZ/
LINK TO /]
	JRST TYCI71	;DUE TO EXCH'S IN TYCI43,
			;EXCHANGE "ME" AND "HIM" IN COMMENTS IN TYCI71.

;TTYIPC FOR A ^_C'ER WHO IS QUERYING IS EITHER TYCRW OR TYCRW2.
;THAT IS DEPENDED ON.
TYCRW:	PUSHJ P,TCNRM
	CAIE E,^G	;^_C'ER MAY USE ^G TO GET ATTENTION.
	 SKIPGE COMT3(I);IN IEC MODE CAN ALSO SAY THE NAME
	  JRST TYCRW4
	CAIE E,^_	;IGNORE ALL TYPEIN EXCEPT ^G AND ^_N.
	 POPJ P,
	JSP D,TYCRDE	;^_, ECHO IT AND GET NEXT CHAR.
TYCRW2:	PUSHJ P,TYCLWR
	CAIN E,"N
	 JRST TYCI2
	MOVEI A,"?	;^_ FOLLOWED BY OTHER THAN N.
	MOVEI B,TYCRW
	MOVEM B,TTYIPC(I)
	JRST TTYI13	;ECHO ? AND GO BACK TO TYCRW

TYCRW4:	PUSHJ P,TTYI18	;^_C'ER TYPED ^G - ECHO ON HIS TTY
	MOVE I,COMT1(I)	;AND ^_C'D TTY.
	PUSHJ P,TYCSET
	JRST TTYI13

;THE TTYIPC FOR A TTY IN A COM LINK NORMALLY POINTS HERE.
;ECHO OR INPUT THE CHAR ON ALL TTYS IN THE LOOP ACCORDING TO SETTINGS
;OF THE RELEVANT %TCICO, %TCLFT AND %TCRFT BITS.
TYCG:	MOVE E,A
	ANDCMI E,#177	.SEE TYCI3
	CAIN E,^_	;REC CHRS IN COM MODE
	 JRST TYCGTN
TYCG21:	PUSH P,TTYCOM(I)	;SAVE COMMUNICATE WORD.
	PUSH P,I	;SAVE MY CONSOLE NUMBER
	PUSH P,A	;SAVE THE CHARACTER
	TLNE Q,%TCICO	;SKIP IF INPUT COM OVERRIDE OFF
	 PUSHJ P,TTYI2	;PROCESS INPUT OVERRIDE
	TLNN Q,%TCICO
	 PUSHJ P,TTYI18	;ECHO CHR ON MY TTY IF %TCICO NOT SET, OTHERWISE GIVE TO PROGRAM
	MOVE A,(P)	;RESTORE CHARACTER
TYCG5:	HRRE B,TTYCOM(I)	;FIRST TTY IN CHAIN
	JUMPL B,[JRST 4,.]	;I'M NOT COMMUNICATING WITH ANYONE
	CAME B,-1(P)	;SKIP IF I'M COMMUNICATING WITH MYSELF
TYCG3:	 SKIPL C,TTYCOM(B)	;SKIP IF HE IS IN COMMUNICATE MODE (THIS POINT IS "COM IN")
	  BUG		;LOSSAGE
	MOVE I,B	;GET HIS TTY NUMBER IN I
	MOVE R,TTYTYP(I)
	MOVE B,-2(P)
	TLNE B,%TCRFT	;IF MY %TCRFT AND HIS %TCLFT SET,
	TLNN C,%TCLFT
	 JRST TYCG1
	MOVSI U,%TSLCZ	;GIVE CHAR TO HIS PROGM.
	ANDCAB U,TTYSTS(I)
	PUSHJ P,TTYI2	;TREAT CHAR AS INPUT FROM HIS TTY.
	JRST TYCG2	;PROCESS NEXT TTY IN CHAIN

TYCG1:	PUSHJ P,TTYI13	;OUTPUT CHAR ON HIS CONSOLE
TYCG2:	MOVE A,(P)	;RESTORE CHARACTER
	HRRE B,TTYCOM(I)	;NEXT TTY IN CHAIN
	JUMPL B,[JRST 4,.]	;CHAIN ENDS STRANGELY
	CAME B,-1(P)	;SKIP IF DONE
	JRST TYCG3	;PROCESS NEXT TTY
	SUB P,[3,,3]
	POPJ P,

;COME AFTER READING UNAME AFTER ^_K, HIS TTY # IN B.
TYCK1:	PUSHJ P,TYCREP	;NO GOOD IF THAT TTY ISN'T LINKED TO ME.
	    CAIN B,(I)
	 CAIN B,(I)	;BUT NO GOOD IF IT IS ME.
	  JRST TYCK2	;NO GOOD, COMPLAIN.
	MOVE I,B
	PUSHJ P,TYCSET	;GET HIS TTYCOM IN Q.
	JRST TYCGTM	;NOW PRETEND HE DID ^_N (READ "HIM" FOR "ME")

TYCK2:	MOVE A,TTYIPC(B)
	CAIE A,TYCRW
	 CAIN A,TYCRW2
	  CAME I,COMT1(B)
	   JRST TYCI7F	;NOT LINKED TO THIS GUY, GIVE "?"
	    JRST TYCQRF	;FLUSH GUY WHO WAS QUERYING

;^_N TYPED IN.
TYCN:	TLZ Q,%TCTPN	;I DON'T NEED ^_N SUPPLIED IF I JUST TYPED IT IN MYSELF.
	PUSHJ P,TYCI2	;ECHO THE N AND STORE Q. ALSO RESTORE TTYIPC AND TTYCOM TO NORMAL.
	SKIPL TTYCOM(I)
	 POPJ P,

;ASSUMING THAT TTY IN I IS IN A COM LINK, UNLINK IT.
;IF ONLY ONE OTHER TTY IS IN THE LINK, REMOVE IT FROM COM MODE TOO.
TYCGTM:	HRRE B,TTYCOM(I)	.SEE TTYLFC
	JUMPL B,[JRST 4,.]	;WASN'T COMMUNICATING WITH ANYONE
	CAMN B,I
	 BUG		;COMMUNICATING WITH SELF
TYCGT3:	HRRE C,TTYCOM(B)
	JUMPL C,[JRST 4,.]	;LIST NOT CIRCULAR
	CAMN C,I
	JRST TYCGT4	;B HAS TTY NUMBER OF GUY POINTING TO ME
	MOVE B,C
	JRST TYCGT3

TYCGT4:	HRRZ C,TTYCOM(I)
	PUSH P,B
	PUSH P,C
	PUSHJ P,TYCGT2	;TAKE ME OUT OF COM MODE.
	POP P,C
	POP P,B
	EXCH I,B
	PUSHJ P,TYCSET
	CAME C,I	;SKIP IF ONLY 1 IN LOOP BESIDES ME. IF SO, HE'S UNLINKED TOO.
	 JRST TYCGT5
;MARK TTY IN I AS UNLINKED AND NOT N COM MODE. TYPE ^_N ON IT IF NECESSARY.
TYCGT2:	HRRI Q,-1
	TLZ Q,400000+%TCLFT+%TCRFT
	TLZN Q,%TCTPN
	 JRST TYCI17
	MOVEI T,[ASCIZ/N/]
	PUSHJ P,TYCI40
	JRST TYCI17

TYCGT5:	HRRM C,TTYCOM(I)	;TAKE ME OUT OF THE CIRCULAR LIST
	MOVEI H,(B)
	SETO TT,	;FOOL TEST AT TYCI66
	PUSHJ P,TYCREP	;TELL ALL THE OTHERS THAT I'VE LEFT.
	    PUSHJ P,TYCI73
	 JFCL
	POPJ P,

TYCI73:	JSP T,TYCI71	;PRINT MSG AND MY UNAME ON TTY # IN I.
	ASCIZ/
BYE FROM /

SUBTTL TTY OUTPUT INTERRUPT LEVEL

OVHMTR TTO	;TTY OUTPUT INTERRUPT LEVEL

;HANDLE AN OUTPUT INTERRUPT FROM A CHAR-AT-A-TIME CONTROLLER.
TYPSC:	MOVEI B,1
	MOVEM B,DBBCC
	MOVEM B,DBBCC1
	MOVE B,[444400,,STYICH]
	MOVEM B,DBBBP
;HANDLE AN OUTPUT INT. ON A MULTI-CHAR CONTROLLER, ASSUMING
;COUNT AND B.P. ARE ALREADY SET UP.
TYP:	LDB J,[220300,,TTYTYP(I)] ;GET TTY OUTPUT SPEED.
TYP0:			;COME HERE FOR DPK; J ALREADY SET UP.
IFN NNVTTS,[
	CAMN I,NOVATT
	 JRST TYP0N
]
	HRRZ W,TCTYP(I)
	MOVE T,TTYTYP(I)
	MOVE H,TTYOPT(I)
	HRRZ A,TTOALC(I)
	JUMPE A,[SETOM TTYOAC(I)
		 JRST TYP1C]	;IF TTY HAS NO SPACE FOR ANY OUTPUT, STOP SENDING.
	MOVE A,TIME
	MOVEM A,TTLTM(I) ;UPDATE TIME OF LAST OUTPUT THIS TTY.
TYP0F:	PUSHJ P,TYPLUP	;OUTPUT AT LEAST 1 CHAR.
	SKIPGE TTYOAC(I)
	 JRST TYP1C
	SKIPLE DBBCC	;SKIP IF OUT OF ROOM
	 JRST TYP0F	;CONTINUE MESSAGE
TYP1B:	SKIPGE A,DBBCC
	 BUG		;CONTROLLER'S BUFFER OVERFILLED?
	SUB A,DBBCC1	;GET -<# CHARS WE ARE SENDING>
	SKIPL E,A
	 BUG		;SENDING NO CHARS OR NEGATIVELY MANY?
	ADD A,TTOALC(I)	;IF THE ALLOCATION ISN'T INFINITE,
	TRNN A,400000
	 HRRM A,TTOALC(I) ;DECREMENT IT BY # CHARS JUST OUTPUT.
IFN MTYP,[
	TRNN T,%TYMTY	;IF MTY ISN'T THE ONLY CONTROLLER, CHECK FOR THE OTHERS
	 JRST TYP1D
	CONO MTY,@TTYLT(I)
	DATAO MTY,MTYOW
	POPJ P,

TYP1D:	]
IFN DPKPP,[
	TRNN T,%TYDPK
	 JRST TYP1E
	MOVN A,E		;- - # CHARS OUTPUT
	ADDM A,@DPKC-NFDPTY(I)	;GIVES # OF CHARS FOR CONTROLLER.
	XCT TTYST(I)		;TELL THE DPK THEY'RE THERE.
	POPJ P,

TYP1E:]
IFN DL10P,[
	TRNN T,%TYDL
	 JRST TYP1G
	MOVNM E,DL10CC	;STORE # CHARS BEING SENT.
	MOVE A,[340000,,DL10BF-1]
	MOVEM A,DL10BP	;GIVE THE 11 ITS MAGIC POINTER TO SNARF THE BUFFER.
	MOVEM I,DL10LN	;STORE LINE # OF TTY, THUS TELLING 11 TO GO AHEAD.
	CONO DLC,100040+TTYCHN	;INTERRUPT 11
	POPJ P,
TYP1G:]
IFN KL10P,[
	TRNN T,%TYETY
	 JRST TYP1I
	SKIPL DTEOUT
	 BUG		;OVER-RUNNING PREVIOUS TRANSFER
	MOVE A,[441000,,DTEOBF]	;SET UP BYTE POINTER FOR 10-11 CHANNEL
	MOVEM A,DTEBPO
	MOVN A,E	;NUMBER OF CHARACTERS BEING SENT
	HRLI A,%DCTYO(I);SEND TYPE-OUT COMMAND, AND LINE NUMBER
	MOVEM A,DTEOUT	;GIVE COMMAND TO 11
	MOVEM A,DTEBBY	;FLAG BUFFER BUSY (AND REMEMBER WHICH COMMAND FOR DEBUGGING)
	MOVEI A,10.	;5-SECOND TIMEOUT FOR LOST TO-11 XFER DONE INTERRUPT
	MOVEM A,DTEBBT	;WHICH SEEMS TO HAPPEN NOW & THEN FOR SOME REASON
	CONO DTE,%DBL11	;AND GIVE INTERRUPT
	POPJ P,
TYP1I:];KL10P
	TRNN T,%TYSTY
	 JRST TYP1H
	MOVEI A,TOBS
	CAML A,TORM(I)
	 POPJ P,
	MOVE A,TTYBYP(I)
	ILDB B,A
	JUMPE B,TYPEND
	POPJ P,

TYP1H:	MOVE A,STYICH	;HANDLE CHAR-AT-A-TIME CONTROLLERS.
	TLNN T,%TTPAR	;GENERATE A PARITY BIT IF NECESSARY.
	 JRST TYPDA1
	IMUL A,[2010040201]
	AND A,[21042104377]
	IDIVI A,17_7
	MOVE A,B
TYPDA1:	CAIL I,NFDPTY
	 BUG
	XCT TTYDO(I)	;DATAO XXX,A
	POPJ P,

TYP1C:	MOVE E,DBBCC
	CAME E,DBBCC1	;SKIP IF NOTHING TO SEND
	 JRST TYP1F	;SEND WHAT THERE IS
	XCT TTYDFF(I)	;CLEAR OUTPUT DONE
	POPJ P,

TYP1F:	AOS TTYOAC(I)
	JRST TYP1B

IFN NNVTTS,[
TYP0N:	AOSE NVTSIP	;CHAR PENDING?
	JRST TYP0A	;NO
	DATAO NTY,NVTSSC	;SEND CHR AFTER SELECT
	POPJ P,

TYP0A:	SKIPN A,NVOPTT
	.ERR Shouldn't this be using NFNVTY Instead?
	MOVEI A,NOTYS+NNTYS+NNVTTS-1
	MOVEM A,NNVSEC	;SET UP END CHECK
	SKIPN I,NVOPTT
	MOVEI I,NOTYS+NNTYS	;INITIALIZE
	SETOM NNVSFL	;SET FIRST TIME THRU FLAG
	MOVE A,NVTCC
	CAIGE A,10	;SENT TOO MANY CHRS TO THIS CONSOLE W/O LOOKING AT OTHERS?
	JRST TYP	;NO, LOOK AT CONSOLE
	SETZM NVOPTT
	SETZM NVTCC	;YES LOOK AT OTHERS
TYP0C:	AOS I
	CAIL I,NOTYS+NNTYS+NNVTTS
	SUBI I,NNVTTS
	AOS NNVSFL
	JRST TYP
]

;FEED SOME CHARACTERS FROM OUTPUT BUFFER TO THE TTY.
TYPLUP:	SKIPE TTYBYP(I)
	 JRST TYPBP
	MOVE Q,TOOP(I)
	MOVE E,TORM(I)
TYPLU1:	CAIL E,TOBS
	 JRST [	MOVEM E,TORM(I)	;OUTPUT BUFFER EMPTY
		MOVEM Q,TOOP(I)
		JRST TYPEND ]
	MOVE D,Q
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	ILDB A,Q	;GET NEXT CHARACTER FROM OUTPUT BUFFER
	CAIL A,%TXDIS-1	;IF DISPLAY OR CURSOR MOTION, DISPATCH.
	 JRST [	MOVEM E,TORM(I)	;LEAVING THE FAST LOOP
		MOVEM D,TOOP(I)	;WITHOUT EATING THIS CHAR YET
		CAIN W,%TNSFW	;"SOFTWARE" TTY GETS THE CODES
		 JRST TYPSFW	;AS THEY APPEAR IN THE BUFFER.
		CAIL A,%TDMAX
		 JRST TYEEO1
		JRST @TYPDTB-%TXDIS(A)]
	TLNN H,%TOSAI	;CTL CHARS ARE SPACING IFF SAIL CHAR SET;
	 CAIL A,40	;NON-CONTROLS ARE SPACING.
	  AOS TTYIHP(I)
IFN MTYP,[
	JUMPE A,[ TRNE T,%TYMTY ;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD
		   PUSHJ P,MNULLO
		    JRST .+1	;OUTPUT IT NOW
		   MOVE Q,D	;BACKUP BYTE POINTER AND OUTPUT IT LATER
		   JRST TYPLU2]
];MTYP
	IDPB A,DBBBP	;PUT INTO DEVICE BUFFER
	SOSLE DBBCC
	 AOJA E,TYPLU1
	AOS E		;MAXIMUM AMOUNT OF CRUFT GENERATED
TYPLU2:	MOVEM E,TORM(I)
	MOVEM Q,TOOP(I)
	POPJ P,

IFN MTYP,[
MNULLO:	MOVE A,DBBCC	;SKIPS IF NULL MAY NOT BE OUTPUT TO MTY NOW
	SETZM DBBCC
	SUBM A,DBBCC1
	MOVNS DBBCC1
	CAIE A,MTYNC
	 JRST POPJ1
	SETZB A,MTYOW
	AOS DBBCC
	AOS DBBCC1
	POPJ P,
];MTYP

;HERE TO OUTPUT CHARACTER WHEN NOT IN FAST LOOP
TYPSIO:
IFN MTYP,[
	JUMPE A,[ TRNE T,%TYMTY ;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD
		   PUSHJ P,MNULLO
		    JRST .+1	;OUTPUT IT NOW
		   POPJ P, ]	;WAIT
];MTYP
	MOVEM Q,TOOP(I)	;REMOVE CHAR FROM OUTPUT BUFFER.
	AOS TORM(I)

;OUTPUT CHAR IN A TO TTY, AND LOOP BACK TO TYPLUP IF THERE IS
;ROOM FOR MORE CHARS. (OTHERWISE POPJ OUT OF TYPLUP).
TYPOU2:	IDPB A,DBBBP	;FOR FAST CONTROLLERS, STICK CHAR IN LOW LVL BUFFER.
	SOSLE DBBCC
	  JRST TYPLUP	;ROOM FOR MORE CHARS.
	POPJ P,

;ACTUALLY OUTPUT A CHAR TO THE TTY (AND POPJ).
TYPOUT:
IFN MTYP,[
	TRNE T,%TYMTY
	 JUMPE A,CPOPJ	;MTY CAN'T HANDLE NULLS.
]
	IDPB A,DBBBP
	SOSGE DBBCC
	 BUG
	POPJ P,

TYPSFW:	TRNE T,%TYSTY	;STY TTY IN SOFTWARE MODE =>
	 JRST TYPSFS	;SEND THE 8-BIT FROB
	SUBI A,%TXDIS-2	;ELSE SEND IT, ESCAPED BY A RUBOUT, WITH 176
	CAIE A,%TDMV0-%TXDIS+2	;  SUBTRACTED FROM IT SO FITS IN 7 BITS
	CAIN A,%TDMV1-%TXDIS+2
	 JRST [	MOVE E,TORM(I)	;FOR %TDMV1, MUST INCREMENT THE 2 ARGS.
		CAILE E,TOBS-3
		 JRST TYPEND
		JRST TYPSF2]
	CAIE A,%TDMOV-%TXDIS+2
	 JRST TYPSF0
	MOVE E,TORM(I)	;AND FOR %TDMOV, MUST INCREMENT THE 4 ARGS SO THEY'RE NOT 0.
	CAILE E,TOBS-5	;IF NOT ALL IN BUFFER, WAIT FOR THEM. TTY WILL BE STARTED AGAIN.
	 JRST TYPEND
IRPS TYPSF1,,TYPSF4:TYPSF3:TYPSF2:TYPSF1:		;DIGIT MANY CHARS FOLLOW
TYPSF1:	DPB A,Q		;STORE PREV. CHAR, FIXED UP.
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	ILDB A,Q
	ADDI A,1	;UPDATE %TDMOV ARGS BY ADDING 1.
TERMIN
TYPSF0:	DPB A,Q		;OK, THE COMMANDS ARE ALTERED, SO SEND THE 177.
	MOVEI A,%TXDIS-1
	JRST TYPOU2

IFE NETP,TYPSFS==<TYPORS==TYPSIO>
IFN NETP,[
;HERE FOR OUTPUT OF 8-BIT FROB TO A SOFTWARE TTY THAT IS A STY
TYPSFS:	CAIN A,%TDORS		;SKIPS INTO TYPORS
;HERE FOR %TDORS IN OUTPUT BUFFER
TYPORS:	 SKIPN TYPNTF
	  JRST TYPSIO
;HERE FOR %TDORS OUTPUT BY STY DIRECTLY INTO A NET SOCKET
IFN CHAOSP\TCPP, MOVE T,STYSTS-NFSTTY(I)	; Get flags for STY
IFN CHAOSP,[
	TLNE T,%SSCHA		; If Chaosnet,
	 JRST TYPOR1		; don't send "INS"
];CHAOSP
IFN TCPP,[
	TLNN T,%SSTCP		; If TCP, send magic chars in URGENT mode.
	 JRST TYPOR2
	HRRZ A,STYNTI-NFSTTY(I)	; Get TCB index
	SKIPL XBSTAT(A)		; Verify that COS is locked down
	 BUG HALT,[TCP: Buff not locked]
	HLRZ T,XBOCOS(A)	; Find orig val of XBOBC
	SUB T,XBOBC(A)		; Find # bytes already in buffer
	CAIGE T,
	 BUG HALT		; Just-in-case check
	MOVE H,STYORC-NFSTTY(I)	; Get magic 8-bit chars to send
	TLNE H,(377_<<8.*3>+4>)	; Check 1st char
	 AOJA T,[TLNE H,(377_<<8.*2>+4>)	; Check 2nd char
		  AOJA T,[	TDNE H,[377_<8.+4>]	; Check 3rd char
				 AOJA T,.+1
				JRST .+1]
		JRST .+1]
	MOVEM T,XBSUP(A)	; Store # chars up to # including magic chars
				; as the TCP URGENT pointer.
	JRST TYPOR1
TYPOR2:
];TCPP
IFN NCPP,[
	HRRZ A,STYNTI-NFSTTY(I)	;GET NET INDEX
	PI2SAF
	MOVE T,IMFCQL		;IF INSUFFICIENT SPACE IN
	CAIG T,2		; THE CONTROL QUEUE,
	 JRST [	MOVSI T,200000	; DEFER SENDING THIS
		IORM T,IMSOC5(A) ;AND REQUEST TTY WAKEUP LATER
		AOS IMNAS	;TELL 1/2 SECOND CLOCK
		AOS IMNORH
		MOVE T,TTYTYP(I)	;NEEDED BY TTY ROUTINES
		JRST TYPEN1 ]
	EXCH A,I		;A TTY IDX, I NET IDX
	PUSH P,Q
	PUSH P,IMPCSH
	LDB T,IMSCFH
	MOVEM T,IMPCSH		;SECRET ARGUMENT TO IMSTCM
	JSP T,IMSTCM
	    2,,1
	 BUG PAUSE,[TTY: NO IMP BUFFERS AVAILABLE FOR "INS" MSG]
	MOVSI B,8_10.		;INS
	LDB C,IMSCLN		;LINK #
	DPB C,[241000,,B]
	MOVEM B,10(Q)
	PUSHJ P,IMWCQ
	POP P,IMPCSH
	POP P,Q
	MOVE I,A
] ;IFN NCPP
TYPOR1:	MOVE H,TTYOPT(I)
	MOVE T,TTYTYP(I)
	MOVE W,TCTYP(I)
	MOVEI A,STYORC-NFSTTY(I)	;TYPE OUT THE MAGIC CHARACTERS
	HRLI A,440800
	JRST TYEEO2
];NETP

;COME HERE FROM TYPLUP WHEN THERE'S NOTHING TO TYPE OUT.
;CALL ALSO FROM TT11I4 WHEN THE PDP11 SAYS THE OUTPUT BUFFER IS EMPTY.
TYPEND:	PUSHJ P,TYPEN2
TYPEN1:	SETOM TTYOAC(I)
	POPJ P,

;SUBROUTINE TO ACTIVATE ANY ECHOING ETC. THAT MAY NEED TO BE DONE
TYPEN2:	SKIPGE TYOSW(I)	;IF ECHOING CAN BE DONE NOW,
	 SKIPL TTOALC(I)
	  POPJ P,
	MOVE Q,TTYCOM(I)
	TLNN Q,%TCDNG	;IS THERE ECHOING NEEDING TO BE DONE?
	 SKIPE ECHOC(I)
	  PUSHJ P,TTYI7	;IF SO, QUEUE IT.
	SKIPGE TTYLPP(I)
	 PUSHJ P,TTYI7	;ALSO FORCE OUT BUFFERED CURSOR MVT.
	POPJ P,

IFN NNVTTS,[
TYP5:	CAMN I,NNVSEC	;REACHED END
	 AOSG NNVSFL	;AND NOT FIRST TIME
	  JRST TYP0C	;LOOK AT OTHER NOVA CONSOLES
	MOVE I,NOVATT
	JRST TYP1C
]

;IF TTYBYP ISN'T 0, IT IS B.P. TO ASCIZ STRING TO TYPE.
;COME HERE TO OUTPUT THE NEXT CHAR OF THE STRING OR CLEAR TTYBYP.
TYPBP:	ILDB A,TTYBYP(I)
	TRZE A,400		;KLUDGE FOR C-100 (and others) TO GET NULLS OUT
IFE MTYP,JRST TYPOU2
.ELSE [	 JRST [	TRNE T,%TYMTY
		 PUSHJ P,MNULLO	;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD
		  JRST TYPOU2	;OUTPUT THE NULL NOW
		MOVSI A,100000	;BACK UP BYTE POINTER
		ADDM A,TTYBYP(I)
		POPJ P, ]	;OUTPUT PARTIAL WORD THEN SEND NULL NEXT TIME
];MTYP
	JUMPN A,TYPOU2		;NOT END => OUTPUT THE CHAR.
	MOVE A,@TTYBYP(I)	;AT END, CHECK FOR SPECIAL
	TRNE A,1		; TEKTRONIX DELAY KLUDGE
	 JRST TYPBP1
TYPBP2:	CLEARM TTYBYP(I) 	;END OF ASCIZ STRING.
	JRST TYPLUP

TYPBP1:	MOVSI B,7700		;CLEAR SIZE FIELD
	ANDCAB B,TTYBYP(I)
	LDB A,[$TTOSP,,TTYTYP(I)]
	MOVM A,BAUDRT(A)	;GET BITS PER SECOND
	MOVE B,1(B)		;GET SPECIFICATION WORD SAYING WHAT PADDING WE WANT.
	CAMN B,[SETZ]
	 JRST TYPBP3		;JUMP IF SPECIAL KLUDGE FOR TEKTRONIX
	JUMPG B,TYPBP4		;JUMP IF PADDING INDEPENDENT OF VPOS.
; this is fixed elsewhere now.
;	MOVE Q,TCTYP(I)		;IS THIS AN H19
;	CAIN Q,%TNH19		;H19'S HAVE TO BE PADDED WITH NUL's
;	 JRST TYPBP8		;  SO HANDLE THEM SPECIALLY
	PUSHJ P,TYPBP6		;CALCULATE NUMBER OF CHARACTERS OF PADDING NEEDED
	JRST TYPBP5

TYPBP4: IMUL B,A		;1000. * NUMBER OF BITS PADDING
	IDIVI B,10000.		;NUMBER OF CHARACTERS PADDING (NOTE ROUND-DOWN)
TYPBP5:	SETZM TTYBYP(I)		;IN CASE NO PADDING REQUIRED
	PUSHJ P,TYMPAD		;PUT THE PADDING BYTE POINTER INTO TTYBYP
	JRST TYPLUP

TYPBP3:	IDIVI A,9		;GET CHARACTERS PER 1.1 SECOND
	SKIPL TTYIHP(I)		;KLUDGE KLUDGE
	 MOVNM A,TTYIHP(I)	;BUT IT'S GOTTA BE STORED SOMEPLACE
	AOSL TTYIHP(I)
	 JRST TYPBP2		;SIGH, DELAY COMPLETED
	MOVEI A,^V		;NOT YET COMPLETED, SEND ANOTHER PAD
	JRST TYPOU2

TYPBP6:	MOVMS B
	IMUL A,B		;IF NEGATIVE, TAKE ABS VALUE
	MOVE B,TCMXV(I)		;TIMES NUMBER OF LINES AT AND BELOW THE CURSOR.
	SUB B,TTYIVP(I)
	IMUL B,A		; 1000.* NUMBER OF BITS OF PADDING
	IDIVI B,10000.*8.	; DIVIDE BY 10000. TO GET NO. OF CHARS OF PADDING
				; AND THEN BY 8 BECAUSE PER LINE TIMES ARE EXPRESSED
	POPJ P,			; IN TERMS OF 1/8 MS FOR BETTER RESOLUTION

;once upon a time someone thought that this might cause padding with nulls to
;happen.  It didn't work.
;TYPBP8:	SKIPL TTYIHP(I)		;TO EXPAND UPON A KLUDGE
;	 JRST [	PUSHJ P,TYPBP6		;CALCULATE THE # OF CHARS NEEDED
;		MOVNM B,TTYIHP(I)	;AND SAVE THEM AWAY TO BE COUNTED
;		JRST .+1 ]
;	AOSL TTYIHP(I)		;COUNT THIS CHARACTER
;	 JRST TYPBP2		;  DELAY COMPLETED, RESET WORLD
;	SETZ A,			;NUL!
;	JRST TYPOU2		;STUFF IT IN THE BUFFER, AND FIND WAY BACK HERE

;COME HERE TO DO CURSOR MOTION ON PRINTING TTYS.
;TT HAS DESIRED HPOS; D HAS DESIRED VPOS.
TYMPRR:	MOVE B,TCMXH(I)
	SUBI B,1
	CAMGE B,TTYIHP(I)
	 MOVEM B,TTYIHP(I)
TYMPRT:	CAIN W,%TNMEM
	 JRST [	CAMLE D,TTYIVP(I) ;VERTICAL MOTION NEEDED, AND CURSOR NOT AT LEFT MARGIN?
		 SKIPN TTYIHP(I)
		  JRST .+1	;(PREVENT INFINITE CR LOOP).
		SETZ TT,	;START WITH A CR.
		JRST TYMPH1]	;MEMOWRECK LOSES LF'ING IN MID-LINE.
	CAMGE TT,TTYIHP(I) ;BACKWARD MOTION TAKES PRIORITY.
	 JRST TYMPH1
	CAMLE D,TTYIVP(I) ;THEN DOWNWARD MOTION.
	 JRST TYMPV2
	CAMLE TT,TTYIHP(I) ;THEN FORWARD MOION.
	 JRST TYMPHF
	MOVEM D,TTYIVP(I) ;MUST BE UPWARD MOTION
	JRST TYMOV8	;WHICH IS A NO-OP ON PRINTING TTYS.

TYMPV2:	AOS TTYIVP(I)	;MOVING DOWN: DO ONE LF
	MOVEI A,^J
	PUSHJ P,TYPOUT
	PUSHJ P,TYMOVX	;IF REACHED GOAL, SAY FINISHED.
	LDB B,[$TPPLF,,TTYOPT(I)]
	CAIN W,%TNTRM
	 ADDI B,TYMTVT-TYMPVT
	CAIN W,%TNMEM
	 ADDI B,TYMMVT-TYMPVT
	HRRZ B,TYMPVT(B) ;# PADDING AFTER LF.
	JUMPN B,TYMPAD
	POPJ P,

TYMPVT:	0	;NORMAL
	2	;2741, MEMOWRECK
REPEAT 6,2+.RPCNT ;EXTRA
TYMTVT:	0	;UNPADDED TERMINET
	3	;10CPS TERMINET
	4	;15CPS TERMINET
	10	;30CPS TERMINET
	17	;60CPS TERMINET
	35	;120CPS TERMINET (MAX SPEED)
	0
	0
TYMMVT:	0	;UNPADDED WRECK
	0
	0
	1	;30CPS WRECK
	2	;60CPS
REPEAT 3,0

TYMPHF:	LDB B,[$TPPTB,,TTYOPT(I)] ;FORWARD: CAN WE DO IT WITH TABS?
	JUMPE B,TYMPH6	;TABS NOT ALLOWED ON THIS TTY.
	MOVE A,TTYIHP(I)
	ANDCMI A,7	;SEE WHERE A TAB WOULD BRING US.
	ADDI A,10
	CAILE A,(TT)	;BEYOND WHERE WE WANT TO GO?
	 JRST TYMPH6
	SUBI A,(B)	;A HAS TAB STOP - <# PADDING>-1
	CAMG A,TTYIHP(I) ;TAB FASTER THAN SPACES (INCLUDING PADDING)?
	 JRST TYMPH6	;NO, USE SPACES.
	ADDI A,(B)	;A HAS TAB STOP.
	MOVEM A,TTYIHP(I)
	MOVEI A,^I
	SOJA B,TYMPT1	;B HAS # PADDING AFTER TAB.

TYMPH6:	MOVEI A,40	;GO FORWARD WITH SPACES
	MOVE C,[AOS TTYIHP(I)]
	JRST TYMPH7

TYMPH2:	MOVEI A,^H	;GO BACKWARD WITH BACKSPACES
	MOVE C,[SOS TTYIHP(I)]
TYMPH7:	MOVE B,TT
	SUB B,TTYIHP(I)
	MOVMS B		;HOW MANY TIMES TO PUT CHAR
TYMPH8:	XCT C
	IDPB A,DBBBP
	SOSG DBBCC
	 JRST TYMOVY
	SOJG B,TYMPH8
	JRST TYMOVX

;COME HERE TO MOVE BACKWARDS.
TYMPH1:	MOVE A,TTYIHP(I)
	SUB A,TT	;A HAS # CHARS IF WE BACKSPACE.
	LDB B,[$TPPCR,,TTYOPT(I)]
	JUMPE B,TYMPH9
	MOVE E,B	;E HAS PADDING TYPE OF TTY,
	MOVE B,TTYIHP(I) ;B HAS CURRENT HPOS.
	CAIL E,<.BM $TPPCR,_-.TZ .BM $TPPCR>-TYMPHL+1	;THIS ONE A SPECIAL $TPPCR CODE?
	 JRST @TYMPHT-<.BM $TPPCR,_-.TZ .BM $TPPCR>-1(E)
	LDB C,[$TTOSP,,TTYTYP(I)]
	SUBI C,2	;(THIS ONLY WORKS FOR SPEED CODES 2,3,4,5)
	ANDI C,3		;(= 110, 150, 300, 1200 BAUD).
	MOVE C,(C)[33. ? 20. ? 10. ? 5]
	IDIV B,C	;1 PAD CHAR FOR EACH (33./20./10./5) SPACES TO MOVE.
	ADDI B,1	;I.E. MOVES AT 300/PADCODE COLUMNS PER SECOND
	IMULI B,(E)	; OR 600/PADCODE COLUMNS PER SECOND AT 1200 BAUD
	ADDI B,-1(E)
TYMPH9:	MOVE C,D
	SUB C,TTYIVP(I)	;IF WE'RE MOVING DOWN AFTER THE CR, HOW MANY LF'S?
	JUMPLE C,TYMPH5
	SUB B,C		;EACH LF REDUCES # PADDING NEEDED BY CR.
	CAIGE B,	;BUT CAN'T NEED LESS THAN 0 PADDING.
	 SETZ B,
;B HAS # CHARS PADDING NEEDED AFTER CR, IF WE DECIDE TO CR.
TYMPH5:	TLNN H,%TOMVB	;HOW DO WE MOVE BACKWARD?
	 JRST TYMPH3	;CAN'T BS => MUST CR AND SPACE FWD.
	JUMPE TT,TYMPH3	;GOING TO COLUMN 0 => ALWAYS CR
	TLNN H,%TOOVR	;ON A GLASS TTY, IF STAYING ON THE SAME LINE, HAVE TO
	 JUMPLE C,TYMPH2 ; USE BACKSPACES TO NOT OBLITERATE PREVIOUS OUTPUT
	LDB E,[$TPPTB,,TTYOPT(I)]
	JUMPE E,[MOVE C,TT ;CAN'T USE TABS: C _ TIME IF MOVE FWD.
		JRST TYMPT2]
	PUSH P,B	;CAN USE TABS: SEE HOW LONG TO GO FWD
	MOVE B,TT	;USING TABS.
	IDIVI B,10	;NEED C(B) TABS AND C(C) SPACES.
	IMULI B,(E)	;B _ TIME NEEDED FOR TABS & PADDING.
	ADDI C,(B)	;C _ TIME NEEDED TO GO FWD.
	POP P,B
TYMPT2:	ADDI C,1(B)	;ADD IN TIME TO CR, + PADDING.
	CAMLE C,A
	 JRST TYMPH2	;FASTER TO BACKSPACE.
TYMPH3:	MOVEI A,^M	;OUTPUT A CR (WILL SPACE FORWARD LATER)
	SETZM TTYIHP(I)	;WHEN WE COME BACK WE'LL SEE WE
TYMPT1:	PUSH P,B	;NEED TO GO FORWARD.
	PUSHJ P,TYPOUT
	PUSHJ P,TYMOVX
	POP P,B
	JRST TYMPAD	;PAD THE TTY (# CHARS PADDING IN B)

;DISPATCH TABLE FOR SPECIAL %TPPCR CODES.
TYMPHZ:	TYMPEX	;EXECUPORT.
	TYMP27	;2741.
	TYMPMW	;MEMOWRECK.
	TYMPH5	;CODE 7 NOT USED.
TYMPHT:	TYMPHL==.-TYMPHZ

TYMP27:	IDIVI B,10.
	CAILE B,14.
	MOVEI B,14.
	AOJA B,TYMPH5

TYMPMW:	LDB E,[$TPPLF,,TTYOPT(I)]
	JUMPE B,TYMPM1	;NO CHRS
	MOVNS B
	ADD B,TYMPMT(E)
	CAMGE B,TYMMVT(E)
TYMPM1:	 MOVE B,TYMMVT(E)
	CAMLE D,TTYIVP(I)	;BEFORE LF'ING, MEMOWRECK
	 JRST TYMPH3	;MUST CR RATHER THAN BS.
	JRST TYMPH5

TYMPMT:	0		;MEMOWRECK MIMIMUM LINE SIZE, AS FUNCTION OF SPEED
	8		;VIA THE $TPPLF CODE.
	11.
	22.
	43.
REPEAT 3,0

TYMPEX:	IDIVI B,10.	;EXECUPORT: 1 PAD CHAR FOR EVERY 10 POSITIONS TO CR THRU.
	ADDI B,5
	JRST TYMPH9

;COME HERE TO PAD A PRINTING TERMINAL: # CHARS OF PADDING IN B.
TYMPAD:	AOSG A,B	;AOS COMPENSATES FOR ILDB
	 POPJ P,
	MOVE Q,TCTYP(I)	;is this an H19?
	CAIN Q,%TNH19	;H19's have to be nullified. I mean, padded with nulls.
	 JRST TYMPNL
	CAILE A,199.	;DON'T TRY TO PAD MORE THAN 199 TIMES, WOULD
	 MOVEI A,199.	; BLOW OUT AT TYPBP1
	IDIVI A,5
	MOVNS A
	ADD A,TYMPA1(B)	;CREATE A BP TO A STRING WITH THE RIGHT # OF RUBOUTS.
	MOVEM A,TTYBYP(I)
	POPJ P,
TYMPNL:	CAILE A,399.	;we make an exception for H19's, which need a lot of
	 MOVEI A,399.	;padding.
	IDIVI A,4	;This works same as with rubouts, but for 9 bits
	MOVNS A
	ADD A,TYPNL1(B)
	MOVEM A,TTYBYP(I)
	POPJ P,

;THIS IS AN ASCIZ STRING OF 199. RUBOUTS.
;SOME FINAL SEGMENT OF IT WILL BE TYPED OUT.
TYMPA0:	REPEAT 199./5,  -2
TYMPA2:	-400

TYMPA1:	010700,,TYMPA2
	100700,,TYMPA2
	170700,,TYMPA2
	260700,,TYMPA2
	350700,,TYMPA2

;This is a not-quite ASCIZ string of 399. pseudo-nulls.  They are 9 bits long so
;that the typeout loop will spot the high bit and see that we're not at the end.
;This is used by things that want to be padded with nulls, like h19s.
TYPNL0:	REPEAT 399./4,<.BYTE 9 ? 400 ? 400 ? 400 ? 400>
TYPNL2:	400400400000

TYPNL1:	001100,,TYPNL2
	111100,,TYPNL2
	221100,,TYPNL2
	331100,,TYPNL2

;DISPATCH TABLE FOR CURSOR CONTROL CMDS AND RUBOUT
	TYPSIO	;RUBOUT DISPATCHES HERE
TYPDTB:	OFFSET %TDMOV-.
%TDMOV::TYMOV	;MOVE CURSOR
%TDMV1::TYMOV2	;DUMMY COMMAND CREATED BY TYMOV.
		;MAKES IT POSSIBLE FOR TYMOV TO STOP WHEN BUFFER FULL
		;AND BE REENTERED NEXT INTERRUPT.
%TDEOF::TYEEOF	;CLEAR REST OF PAGE
%TDEOL::TYEEOL	;CLEAR REST OF LINE
%TDDLF::TYEDLF	;DELETE FORWARD (FOR ERASABLE OVERPRINTING TTYS)
%TDMTF::TYEMTF	;MOTOR OFF (FOR TERMINETS)
%TDMTN::TYEMTN	;MOTOR ON (FOR TERMINETS)
%TDCRL::TYECRL	;CRLF ON DATAPOINTS, IMLACS.
%TDNOP::TYEEO1	;NO-OP FOR SUPERDUPERIMAGE MODE.
%TDBS::	TYEBS	;BACKSPACE (FOR TTY'S WITH %TORAW SET).
%TDLF::	TYELF	;LINEFEED (").
%TDRCR::TYERCR	;CARRET (").
%TDORS::TYPORS	;"OUTPUT RESET" FOR SAKE OF SOFTWARE TTYS & STYS
%TDQOT::TYEQOT	;DEVICE-DEPENDENT DATA IN NEXT BYTE.
%TDFS::	TYEFS	;FORWARD ONE SPACE
%TDMV0::TYMV0	;REPLACEMENT FOR %TDMOV
%TDCLR::TYECLR	;CLEAR THE SCREEN
%TDBEL::TYEBEL	;DING THE BELL.
%TDINI::TYEINI	;REINITIALIZE INTELLIGENT TERMINAL
%TDILP::TYEILP	;INSERT LINE POSITION, FOLLOW BY COUNT
%TDDLP::TYEDLP	;DELETE LINE POSITION, FOLLOW BY COUNT
%TDICP::TYEICP	;INSERT CHARACTER POSITION, FOLLOW BY COUNT
%TDDCP::TYEDCP	;DELETE CHARACTER POSITION, FOLLOW BY COUNT
%TDBOW::TYEBOW	;ENTER INVERSE VIDEO MODE
%TDRST::TYERST	;CLEAR ALL SPECIAL MODES (SUCH AS INVERSE VIDEO).
%TDGRF::TYEEO1	;GRAPHICS, FLUSH IT
%TDRSU::TYERSU	;REGION SCROLL UP
%TDRSD::TYERSD	;REGION SCROLL DOWN
	TYEEO1	;NEXT 4 CODES ARE USED FOR SOME WEIRD FORM OF GRAPHICS OUTPUT
	TYEEO1	;THAT WILL EVENTUALLY BE FLUSHED.
	TYEEO1
	TYEEO1
;FOLLOWING CODES ARE FOR LOCAL EDITING TERMINALS
;NON-SOTFWARE TERMINALS DON'T HANDLE THEM, SO IGNORE THEM.
%TDSYN::TYEIG1	;RESYNCH REPLY TO LOCAL EDITING TERMINAL.  IGNORE 1 ARG.
%TDECO::TYEEO1	;ASK TERMINAL TO TRY LOCAL EDITING BY SENDING A RESYNCH.  IGNORE.
%TDEDF::TYEIG2	;SET LOCAL EDITING TERMINAL COMMAND DEFINITION.  IGNORE 2 ARGS.
%TDNLE::TYEEO1	;STOP DOING LOCAL EDITING.  IGNORE.
%TDTSP::TYEEO1	;DISPLAYS LIKE SPACE, BUT IS PART OF A TAB.  IGNORE.  SHOULDN'T HAPPEN.
%TDCTB::TYEEO1	;THIS LINE IS CONTINUED AT THE BEGINNING.
%TDCTE::TYEEO1	;THIS LINE IS CONTINUED AT THE END.
%TDMLT::TYEIG2	;DECLARE MULTI-POSITION CHAR FOR LOCAL EDITING.  IGNORE 2 ARGS.
%TDSVL::TYEIG3	;SAVE LINE CONTENTS.  IGNORE 3 ARGS.
%TDRSL::TYEIG3	;RESTORE LINE CONTENTS.  IGNORE 3 ARGS.
%TDSSR::TYEIG2	;SET RANGE OF COLUMNS TO SAVE.  IGNORE 2 ARGS.
%TDSLL::TYEIG2	;SET LABEL FOR LOCAL LINE SAVING.  IGNORE 2 ARGS.
%TDMAX::OFFSET 0


;IGNORE THIS COMMAND AND 3 ARGS.
TYEIG3:	MOVE A,TORM(I)
	CAILE A,TOBS-4
	 JRST TYPEND
	AOS A,TORM(I)
	IBP Q
;IGNORE THIS COMMAND AND 2 ARGS.
TYEIG2:	MOVE A,TORM(I)
	CAILE A,TOBS-3
	 JRST TYPEND
	AOS A,TORM(I)
	IBP Q
;IGNORE THIS COMMAND AND 1 ARG.
TYEIG1:	MOVE A,TORM(I)
	CAILE A,TOBS-2
	 JRST TYPEND
	AOS A,TORM(I)
	IBP Q
	JRST TYEEO1

TYEQOT:	MOVE A,TORM(I)
	CAILE A,TOBS-2
	 JRST TYPEND
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	ILDB A,Q
	AOS TORM(I)
	JRST TYPSIO

TYEBEL:	MOVEI A,7
	JRST TYPSIO

;%TDMOV MOVE CURSOR COMMAND DISPATCHES HERE.
TYMOV:	MOVE A,TORM(I)
	CAILE A,TOBS-5	;IF THE 4 ARGUMENT CHARS AREN'T IN THE BUFFER YET,
	 JRST TYPEND	;GO AWAY; WILL COME BACK WHEN THEY ARE OUTPUT.
	CAMN Q,TOBEP(I)	;FETCH THE NEXT 2 CHARS WHICH
	 MOVE Q,TOBBP(I)	;HOLD THE "OLD" POSITION
	ILDB A,Q
	MOVEM Q,TOOP(I)		;FLUSH FIRST TWO CHARS (AS IF WAS %TDMV0)
	MOVEI C,2
	ADDM C,TORM(I)
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	ILDB B,Q
	CAMGE A,TCMXV(I)
	 MOVEM A,TTYIVP(I)	;SET INITIAL STARTING PLACE
	MOVEM B,TTYIHP(I)
	JRST TYMV0A

TYMV0:	MOVE A,TORM(I)	;MAKE SURE THE TWO ARG CHARS ARE IN THE BUFFER
	CAILE A,TOBS-3
	 JRST TYPEND	;GO AWAY; WILL COME BACK WHEN THEY ARE OUTPUT.
;DROPS THROUGH
;DROPS IN
;%TDMOV COMMAND ON ALL TERMINALS.
TYMV0A:	MOVSI C,%TCPAD+%TCFPD	;FOR DATAPOINTS, PADDING WILL BE NECESSARY NOW.
	ANDCAM C,TTYCOM(I)	; ALSO, CLEAR FPD IF IT GOT LEFT ON SOMEHOW
	MOVEI A,%TDMV1		;PUT A NEW COMMAND IN OUTPUT BUFFER
	DPB A,Q			; IN CASE WE FILL UP BUFFER AND HAVE TO COME BACK.
				; IN THAT CASE WILL RETURN TO TYMOV2.
;BUFFER NOW HOLDS:
; %TDMV1 ? NEW VPOS ? NEW HPOS
TYMOV2:	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)	;FETCH DESIRED POS. FROM BUFFER.
	ILDB D,Q
	CAML D,TCMXV(I)
	 SETZ D,
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	ILDB TT,Q
	CAIGE W,%TNMAX		;If pointer to routine is within range,
	 JUMPGE W,@TYMDTB(W)	;GO TO DEVICE-DEPENDENT CURSOR POSITIONING ROUTINE
	BUG

TYMDTB:	OFFSET -.
%TNPRT::SETZ TYMPRT		;PRINTING
%TNDP::	TYMDP		;DATAPOINT
%TNODP::TYMDP		;LOSING DATAPOINT
%TNIML::TYMIML		;IMLAC
%TNTEK::TYMDP		;TEKTRONIX
%TNTV::	[JRST 4,.+TYMDTB]
%TNMEM::SETZ TYMPRT	;MEMOWRECK
%TNSFW::[JRST 4,.+TYMDTB]
%TNTRM::SETZ TYMPRT	;TERMINET
%TNESC::TYMDP		;ASCII ESCAPE SEQUENCES TTY
%TNDTM::TYMIML		;DATAMEDIA
%TNRAY::TYMDP		;TELERAY 1061
%TNHDS::TYMDP		;HDS CONCEPT-100
%TNH19::TYMH19		;H19
%TNAAA::TYMAAA		;Ann Arbor Ambassador
%TNMAX::OFFSET 0

;DISPLAY TERMINALS THAT HAVE RELATIVE CURSOR POSITIONING
TYMDP:	MOVE A,TTYIVP(I)	;CURRENT HARDWARE VERTICAL POSITION
	SUB A,D		;SUBTRACT VERTICAL POSITION OF WHERE WE WANT TO BE
	MOVMS A		;A IS HOW FAR WE HAVE TO GO UP OR DOWN
	CAML TT,TCMXH(I) ;IF TRYING TO MOVE OFF RIGHT MARGIN,
	 JRST [	MOVE TT,TCMXH(I) ;CODE JUST BELOW CAUSES INFINITE LOOP
		SOJA TT,.+1 ]	 ;SO PRETEND MOVING TO MARGIN
	MOVE B,TTYIHP(I) ;COMPUTE NET CHRS TO POSITION
	CAML B,TCMXH(I)	;IF WE THINK WE MOVED OFF THE END OF THE LINE,
	 JRST [	MOVE B,TCMXH(I) ;PRESUMABLY BY PRINTING IN THE LAST COLUMN,
		SUBI B,1	;THE CURSOR ACTUALLY STUCK IN THE LAST COLUMN
		MOVEM B,TTYIHP(I)
		JRST .+1 ]
	SUB B,TT
	MOVM C,B	;C IS HOW FAR WE HAVE TO GO HORIZONTALLY
	TRNE H,%TPPTB	;IF TERMINAL HAS TABS
	 JRST TYMTB1	;USE DIFFERENT CURSOR POSITIONING ROUTINE
	CAMLE B,TT	;SKIP IF NOT SHORTER TO CR FIRST
	 MOVEI C,1(TT)	;# CHARS IF CR FIRST.
	ADD A,C		;A NOW HAS TOTAL NUMBER OF CHARS TO SEND TO GET THERE
	JUMPE A,TYMOV8	;WE'RE THERE
	MOVE C,D
	ADDI C,1(TT)	;C HAS NUMBER OF CHARS IT WOULD TAKE IF WE HOMED UP FIRST
	MOVE E,TCMXV(I)
	SUBI E,1
	SUB E,D		;E HAS NUMBER IF HOME DOWN FIRST
	JUMPL E,TYPCPG
	ADD E,TT
	CAMGE C,A
	 JRST TYMHU	;HOME UP SHORTER
	CAMGE E,A
	 JSP A,TYMHD	;HOME DOWN SHORTER
TYPCPG:	JUMPL B,TYMDP3	;H POS TOO SMALL, MOVE FWD
	JUMPG B,TYMDP6	;MOVE BACKWARD (EITHER BS OR CR).
TYMDPL:	MOVE B,TTYIVP(I)
	SUB B,D
	JUMPG B,TYMDP2	;MOVE UP IF NECESSARY
	JUMPL B,TYMDP1	;OR DOWN.
	JRST TYMOV8	;OR WE'RE DONE.

TYMDP3:	JSP E,TYMDPP	;PAD IF NEC.
	MOVE C,[AOS TTYIHP(I)]
	SKIPL A,CCFS(W)	;GET FORWARD SPACE CHARACTER
	 JRST TYMDP7	;IS ONE CHAR
	HRRZS A
	JRST TYMVT7	;IS TWO CHARS

TYMDP6:	CAMG B,TT
	 JRST TYMDP8
TYMTB6:	MOVEI A,15	;BETTER TO CR FIRST
	CAIE W,%TNODP
	 CLEARM TTYIHP(I)
	MOVEI B,1
	MOVSI C,(JFCL)
	CAIE W,%TNODP
	 JRST TYMDP5
	MOVE E,TCMXV(I)
	SUBI E,1
	CAMN E,TTYIVP(I) ;ON LOSERS, AFTER CR MUST GO LF TO TURN OFF SPOW MODE.
	 JRST TYMDP2	;IF ON BOTTOM LINE, GO UP BEFORE CR SO CAN GO DOWN AFTER.
	MOVE E,TTYCOM(I)
	TLCN E,%TCFPD
	 MOVEM E,TTYCOM(I)
	TLNE E,%TCFPD
	 JRST TYMDP5	;JUMP IF HAVEN'T DONE CR YET
	JSP E,TYMDPP	;AFTER CR, PAD
	JRST TYMHU3	;THEN GO SETZM TTYIHP(I) AND TURN OFF SPOW LATCH

TYMDP8:	JSP E,TYMDPP
	MOVE C,[SOS TTYIHP(I)]
	MOVEI A,%DPBS	;DATAPOINT BACK-SPACE.
	JRST TYMDP7

TYMDP1:	JSP E,TYMDPP
	MOVEI A,%DPDN	;DATAPOINT LINEFEED.
	MOVE C,[AOS TTYIVP(I)]
	JRST TYMDP7

TYMDP2:	JSP E,TYMDPP
	MOVE C,[SOS TTYIVP(I)]
	SKIPL A,CCUP(W)	;GET LINE-STARVE CHARACTER
	 JRST TYMDP5
	HRRZS A
	JRST TYMVT7	;IT'S TWO CHARS LONG

TYMHU:	SKIPN CCHUP(W)	;SKIP IF TTY CAN HOME UP
	 JRST TYPCPG
	CAMLE C,E	;HOME UP IS BETTER THAN DIRECT ROUTE.
	 JSP A,TYMHD	;MAYBE HOME DOWN IS EVEN BETTER
	CAIN W,%TNODP
	 JRST TYMHU1
	CLEARM TTYIVP(I) ;NO, HOME UP IS BEST.
	CLEARM TTYIHP(I)
TYMHU2:	MOVE A,CCHUP(W)
	MOVEM A,TTYBYP(I)
	JRST TYMOVX

TYMHU1:	MOVE E,TTYCOM(I)	;HERE FOR HOME UP ON DISAPPOINT
	TLCN E,%TCFPD
	 MOVEM E,TTYCOM(I)
	TLNE E,%TCFPD
	 JRST TYMHU2		;JUMP IF HAVEN'T HOMED UP YET
	MOVSI E,%TCPAD		;DON'T PAD AFTER HOME UP
	IORM E,TTYCOM(I)
	SETZM TTYIVP(I)		;AND TURN OFF THE SPOW LATCH
TYMHU3:	MOVSI E,%TCFPD		;FIRST PART WILL HAVE BEEN DONE WHEN
	ANDCAM E,TTYCOM(I)	; WE PUT OUT THE ONE CHAR TO GO DOWN ONE LINE
	SETZM TTYIHP(I)
	MOVEI B,1		;GO DOWN ONE LINE TO RESET SPOW
	JRST TYMDP1

TYMDP7:	MOVMS B
TYMDP5:	JUMPE A,[JRST 4,.]
TYMDP4:	XCT C
	IDPB A,DBBBP
	SOSG DBBCC
	 JRST TYMOVY
	SOJG B,TYMDP4
	JRST TYMOVC

;CAN'T OUTPUT ANY MORE: IF REACHED DESIRED POS, FLUSH THE
;%TDMV1; OTHERWISE RETURN LEAVING IT TO COME BACK HERE WHEN
;TTY CAN ACCEPT MORE OUTPUT.
TYMOVY:	SOJG B,TYMOVP
TYMOVX:	CAMN D,TTYIVP(I)
	CAME TT,TTYIHP(I)
	 POPJ P,
;WE USED UP ALL THE SPACE BUT GOT WHERE WE'RE GOING.
TYMOV9:	MOVEM Q,TOOP(I)	;FLUSH THE %TDMV1 COMMAND.
	MOVEI B,3
	ADDM B,TORM(I)
	POPJ P,

;WE FINISHED ONE SET OF OUTPUT CHARS, & HAVE ROOM FOR MORE.
;EITHER CONTINUE MOVING CURSOR, OR LOOK FOR NEXT THING TO DO.
TYMOVC:	CAME TT,TTYIHP(I)
	 JRST TYMDP	;HORIZ POS STILL NEEDS CHANGING.
	CAME D,TTYIVP(I)
	 JRST TYMDPL	;VERT POS STILL NEEDS CHANGING.
TYMOV8:	MOVEM Q,TOOP(I)	;FLUSH THE %TDMV1 COMMAND
	MOVEI B,3
	ADDM B,TORM(I)
	JRST TYPLUP	;AND GO GET NEXT THING FROM BUFFER.

;COME HERE TO PAD DATAPOINT IF NECESSARY.
;CALL WITH JSP E,. CLOBBERS A, C.
;MAY JUMP AWAY TO PAD, IN WHICH CASE TYMDP WILL BE RE-ENTERED LATER.
TYMDPP:	MOVSI C,%TCPAD
	TDNE C,TTYCOM(I) ;PADDING ALREADY DONE FOR THIS COMMAND => RETURN.
	 JRST (E)
	LDB A,[$TPPCR,,TTYOPT(I)]
	JUMPE A,(E)	;RETURN IF THIS TTY NOT PADDED.
	MOVE B,A
	IORM C,TTYCOM(I) ;AFTER WE PAD, PADDING WON'T BE NECESSARY.
	MOVEI A,177
	MOVSI C,(JFCL)
	JRST TYMDP5	;GO OUTPUT THEM.

TYMOVP:	CAIE A,177
	 POPJ P,
	JRST TYMPAD

;JSP A,TYMHD IF HOME-DOWN LOOKS BEST
TYMHD:	CAIE W,%TNDP
	 JRST (A)	;BUT HOME-DOWN ONLY WORKS ON DATAPOINTS
	SETZM TTYIHP(I)	;HOME DOWN IS BEST.
	MOVE C,TCMXV(I)
	SUBI C,1
	MOVEM C,TTYIVP(I)
	MOVE A,CCHDP
	MOVEM A,TTYBYP(I)
	JRST TYPLUP

;HERE TO SEND ONE OR MORE COPIES OF AN ESCAPE SEQUENCE.
;ESCAPED CHAR IN A. # TIMES IN B. INSN TO ADJUST TTYIVP,TTYIHP IN C.
TYMVT7:	MOVMS B
TYMVT5:	MOVE E,TTYCOM(I)	;STOPPED IN MIDDLE OF ESC SEQ?
	TLZN E,%TCFPD
	 JRST TYMVT4
	MOVEM E,TTYCOM(I)	;YES, SKIP INITIAL ESC
	JRST TYMVT6

TYMVT4:	MOVEI E,33
	IDPB E,DBBBP
	SOSG DBBCC		;NO MORE ROOM =>
	 JRST TYMVT3		;STOPPED WITHIN ESC SEQUENCE
TYMVT6:	XCT C			;ELSE SEND THE ESCAPED CHAR
	IDPB A,DBBBP
	SOSG DBBCC
	 JRST TYMOVY		;NO ROOM => DISMISS
	SOJG B,TYMVT4		;ELSE SEND NEXT ESC SEQ
	JRST TYMOVC		;FLUSH THE %TDMOV AND RETURN

TYMVT3:	MOVSI E,%TCFPD
	IORM E,TTYCOM(I)
	POPJ P,

;CURSOR POSITIONING ON A DISPLAY TTY WITH TABS
TYMTB1:	MOVE R,TT
	IDIVI R,8
	ADD R,TYMTBC(W)		;COST OF TABBING TO DEST FROM LEFT MARGIN
	MOVE W,TCTYP(I)		;RESTORE W, CLOBBERED BY IDIVI
	JUMPG B,TYMTB2		;JUMP IF MOVING BACKWARDS
	JUMPE B,TYMTB3		;JUMP IF NOT MOVING HORIZONTALLY
	SKIPGE CCFS(W)
	 ADD C,C		;MOVING FORWARDS IS SLOW ON ESCAPE-C TYPE TERMINAL
	MOVE E,TTYIHP(I)
	LSH E,-3
	SUBM R,E		;COST OF TABBING FROM WHERE WE ARE NOW
	CAMLE C,E
	 MOVE C,E		;FASTER IF TABS ARE USED
	JRST TYMTB3		;MOVING FORWARD, SO CR CAN'T HELP

TYMTB2:	CAILE C,1(R)
	 MOVEI C,1(R)		;BETTER TO CR FIRST
TYMTB3:	ADD A,C			;TOTAL # CHARS TO BE SENT IF RELATIVE POSITIONING USED
	JUMPE A,TYMOV8		;WE'RE THERE
	MOVE E,D
	ADDI E,2(R)		;COST IF HOME-UP FIRST (ASSUMING HOME-UP IS 2 CHARS)
	CAMG E,A
	 MOVE A,E		;RELATIVE POSITIONING SHOULD START WITH HOME-UP
	CAILE A,4		;COMPARE RELATIVE AND ABSOLUTE POSITIONING
	 TRNN H,2*%TPPTB
	  JRST TYMTB8		;RELATIVE POSITIONING BETTER OR ONLY CHOICE
;USE ABSOLUTE POSITIONING, DROP INTO STRAIGHT ABS POS CODE.
;HERE FOR DIRECT POSITIONING ON IMLAC AND DATA MEDIA.  SEND MAGIC CHARACTER
;FOLLOWED BY HORIZONTAL AND VERTICAL POSITION, OFFSET BY SUITABLE AMOUNT
;D FOR THE VERTICAL, TT FOR THE HORIZONTAL
TYMIML:	MOVE Q,TOOP(I)		;CLOBBER OVER THE 3 CHARS IN OUTPUT BUFFER
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	HLRZ A,CCDPSO(W)	;GET ABS-POSITIONING CHARACTER, IT WILL
	IDPB A,Q		; BE FOLLOWED WITH VERTICAL, HORIZONTAL COORDS
	MOVEM D,TTYIVP(I)	;CURSOR WILL END UP HERE
	MOVEM TT,TTYIHP(I)
	TRNE A,200000
	 EXCH D,TT		;SEND HORIZONTAL THEN VERTICAL
	HRRZ E,CCDPSO(W)	;GET TABLE INDEX
	MOVE B,D		;FIRST COORD TO SEND
	XCT CCDPSM(E)		;MUNG B APPROPRIATELY
	ANDI B,177		;EXTRA BITS CAUSE TROUBLE LATER
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	IDPB B,Q
	MOVE C,B		;SAVE
	MOVE B,TT		;SECOND COORD TO SEND
	XCT CCDPSM(E)		;MUNG B APPROPRIATELY
	ANDI B,177		;EXTRA BITS CAUSE TROUBLE LATER
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	IDPB B,Q
	ANDI A,177		;DON'T LET TYPLUP THINK THESE CHARACTERS PRINT
	TLNN H,%TOSAI
	 CAIL A,40
	  SOS TTYIHP(I)
	TLNN H,%TOSAI
	 CAIL B,40
	  SOS TTYIHP(I)
	TLNN H,%TOSAI
	 CAIL C,40
	  SOS TTYIHP(I)
	SKIPL A,CCDPSO(W)
	 JRST TYPLUP
	MOVEI A,33		;PUT AN ESC BEFORE IT
	JRST TYPOU2

TYMTB8:	CAMN E,A
	 JRST TYMHU		;HOME-UP FIRST
	JUMPL B,TYMTB4		;JUMP IF MOVING TO THE RIGHT
	JUMPE B,TYMDPL		;JUMP IF NOT MOVING HORIZONTALLY
	CAIE C,1(R)		;MOVING TO THE LEFT, SKIP IF SHOULD CR FIRST
	 JRST TYMDP8		;NO, JUST BS
	JRST TYMTB6		;GO CR

TYMTB4:	MOVE E,TT		;DESTINATION COLUMN
	TRO E,7			;ENSURE NO BORROW
	MOVEI A,1(E)		;COLUMN TO TAB TO THEN BACKSPACE BACK
	CAMGE A,TCMXH(I)	;BE SURE NOT TO TAB OFF THE RIGHT MARGIN
	 TRNN TT,4		;SKIP IF FASTER TO TAB PAST AND BACKSPACE BACK
	  JRST TYMTB5		;JUMP IF BETTER TO TAB THEN FORWARD-SPACE
	CAMN B,[-1]
	 JRST TYMDP3		;MOVING A SHORT WAY, JUST SEND A FORWARD-SPACE
	MOVEI B,8(E)
	SUB B,TTYIHP(I)
	LSH B,-3		;# TABS TO GET PAST DESTINATION
TYMTB7:	MOVEI A,^I
	MOVEI E,7
	ANDCAM E,TTYIHP(I)	;ALIGN TTYIHP WITH TAB STOPS
	MOVE C,[ADDM E,TTYIHP(I)] ;EACH TAB ADVANCES TTYIHP BY 8
	AOJA E,TYMDP5		;GO TAB

TYMTB5:	SUB E,TTYIHP(I)		;COMPUTE # TABS TO GET JUST TO
	LSH E,-3		; THE LEFT OF THE DESTINATION
	JUMPE E,TYMDP3		;WE'RE CLOSE, DO FORWARD SPACES
	MOVE B,E		;TAB FIRST
	JRST TYMTB7

TYMTBC:	0 ? 2 ? 4 ? 6		;COST OF MOVING RIGHT FROM A TAB STOP
	1+4 ? 1+3 ? 1+2 ? 1+1	;COST OF TABBING ONE MORE AND BACKSPACING BACK

;setup routine for TYMH19, TYMAAA.  Gets magnitude of horizontal and vertical
;motion in B and A, destinations in TT and D respectively, sets TTYIHP and
;TTYIVP.
TYMPOS:	MOVE A,TTYIVP(I)	;current hardware vertical position
	SUBM D,A		;subtract from vertical destination
	CAML TT,TCMXH(I)	;if trying to move off right margin,
	 JRST [	MOVE TT,TCMXH(I)	;pretend moving to margin
		SOJA TT,.+1 ]
	MOVE B,TTYIHP(I)	;compute net chrs to position
	CAML B,TCMXH(I)	;if we think we moved off the end of the line,
	 JRST [	MOVE B,TCMXH(I)	;presumably by printing in the last column,
		SUBI B,1	;the cursor actually stuck in the last column
		MOVEM B,TTYIHP(I)
		JRST .+1 ]
	SUBM TT,B	;now we have horizontal motion in B
	MOVEM D,TTYIVP(I)	;put vertical, horizontal destination
	MOVEM TT,TTYIHP(I)	;into registers (we'll be there soon).
	POPJ P,

;cursor positioning on an H19.  TYMDP occasionally stuffs rubouts into the
;buffer to do its own padding, thereby resulting in ^S ^Q lossage on H19s.  I
;could patch TYMDP up, but it's too silly.  Generates HCUF, HCUB, HCUD, HCUU,
;or HDCA.
TYMH19:	PUSHJ P,TYMPOS		;get horizontal and vertical destinations, etc.
	MOVEI C,2	;now flush the first two chars of cursor
	ADDM C,TORM(I)	;motion command (TYEEO2 will flush last)
	MOVE C,TOCMBF(I)	;get byte pointer to tty command buffer in C
	MOVEI E,33
	IDPB E,C		;send esc
	JUMPE A,TYMHOX		;if vertical magnitude 0, only moving in X
	JUMPE B,TYMHOY		;same for horizontal and Y
TYMABS:	MOVEI E,"Y		;neither is 0, abs. positioning faster
	IDPB E,C
	ADDI D,40		;convert line # to H19 coord system.
	IDPB D,C
	ADDI TT,40		;convert column # to H19 coord system
	IDPB TT,C
TYMHDN:	MOVEI E,0		;top it off with a null
	IDPB E,C
	MOVE A,TOCMBF(I)	;TYEEO2 wants bp in A
	JRST TYEEO2		;noone seems to think it's necessary to pad

TYMHOX:	CAIN B,1		;if 1 or -1, then relative positioning is
	 JRST TYMHX2		;plenty fast
	CAIN B,-1
	 JRST TYMHX3
	JRST TYMABS		;otherwise absolute positioning is faster
TYMHX2:	MOVEI E,"C		;moving forward one space
	IDPB E,C
	JRST TYMHDN
TYMHX3:	MOVEI E,"D		;moving backwards one space
	IDPB E,C
	JRST TYMHDN

TYMHOY:	CAIN A,1		;if 1 or -1, then relative positioning is
	 JRST TYMHY2		;plenty fast
	CAIN A,-1
	 JRST TYMHY3
	JRST TYMABS		;otherwise absolute positioning is faster
TYMHY2:	MOVEI E,"B		;moving down one line
	IDPB E,C
	JRST TYMHDN
TYMHY3:	MOVEI E,"A		;moving up one line
	IDPB E,C
	JRST TYMHDN

;cursor positioning on an AAA.  Generates either CUP, HPA, or VPA,
;whichever involves fewest chars.
TYMAAA:	PUSHJ P,TYMPOS		;get X-Y motion and set dests.
	MOVEI C,2	;now flush the first two chars of cursor
	ADDM C,TORM(I)	;motion command (TYEEO2 will flush last)
	MOVE C,TOCMBF(I)	;get byte pointer to tty command buffer in C
	MOVEI E,33
	IDPB E,C	;send esc
	MOVEI E,"[	;[
	IDPB E,C
	JUMPE B,TYMAVT	;going vertically only
	JUMPE A,TYMAHZ	;horizontally only
	JUMPE D,TYMAP3	;if going to top line, optimize out 1st coord
	MOVE E,D
	PUSHJ P,SNDNUM	;send vertical coord
	JUMPE TT,TYMAP5	;if moving to leftmost col no second coord
TYMAP3:	MOVEI A,73	;or semicolon
	IDPB A,C
	MOVE E,TT
	PUSHJ P,SNDNUM	;send horizontal coord
TYMAP5:	MOVEI A,"H	;absolute positioning char
	JRST TYMADN
;going vertically only, use vertical absolute positioning
TYMAVT:	MOVE E,D
	PUSHJ P,SNDNUM
	MOVEI A,"d	;vertical absolute positioning char
	JRST TYMADN
;going horizontally only, horizontal absolute positioning
TYMAHZ:	MOVE E,TT
	PUSHJ P,SNDNUM
	MOVEI A,"`	;horizontal absolute positioning char
;fall through into done code

TYMADN:	IDPB A,C	    ;send that last char
	MOVEI A,4	    ;padding is A*TT in ms
	MOVEI TT,1	    ;4 ms of padding ought to be enough
	JRST TYDAPD	    ;go set it up

;Add one to the number in E, convert it to ASCII decimal, and idpb it
;in the location pointed to by the bp in C.  Assumes no more than 2
;digits in E.  Bashes A, B, E (B because of the IDIVI).
SNDNUM:	AOS E		;bump
	MOVE A,E
	IDIVI A,10.	;divide by 10 for high digit
	JUMPE A,SNDNM2	;only one digit
	ADDI A,"0	;make high digit ascii
	IDPB A,C	;put in buffer
	SUBI A,"0	;un-ascii high digit
	IMULI A,10.	;find out what we printed
	SUB E,A		;take it from what we had to get low digit
SNDNM2:	ADDI E,"0	;make low digit ascii
	IDPB E,C	;put in buffer
	POPJ P,

TYEBS:	SOSGE TTYIHP(I)	;%TDBS: OUTPUT BS.
	 SETZM TTYIHP(I)
	MOVEI A,^H
	JRST TYPSIO

TYERCR:	MOVE D,TTYIVP(I)	;%TDRCR: OUTPUT A CR (PLUS PADDING)
	SETZ TT,
	SKIPN TTYIHP(I)
	 AOS TTYIHP(I)
TYERC1:	SOS TORM(I)	.SEE TYMOVX ;WHICH WILL ADD 3 TO TORM.
	SOS TORM(I)
	JRST TYMPRR

TYELF:	MOVE TT,TTYIHP(I)	;%TDLF: OUTPUT LF (PLUS PADDING)
	MOVE D,TTYIVP(I)
	AOS D
	CAIG D,118.
	 CAML D,TCMXV(I)
	  JRST TYELFE		;DETECT A LF THAT SCROLLS.
	JRST TYERC1

TYELFE: SKIPN TTYROL(I)		;IF NOT A SCROLLING TTY, RESET VPOS TO 0
	 TDZA D,D
	  SUB D,TTYROL(I)	;OTHERWISE, GLITCH UP
	MOVEM D,TTYIVP(I)	;STORE VPOS AFTER SCROLLING.
	SOS TTYIVP(I)		;MAKE SURE 1 LF IS OUTPUT.
	JRST TYERC1

TYEFS:	CAIN W,%TNAAA		;AAA's use a different format
	 JRST TYFSAA
	MOVSI E,%TCFPD		;ON SOME TTYS, IS TWO PARTS
	TDNE E,TTYCOM(I)
	 JRST TYEFS2		;FIRST PART DONE, DO SECOND
	IORM E,TTYCOM(I)	;ABOUT TO DO FIRST PART
	CAIE W,%TNDP		;DATAPOINTS NEED PADDING
	 CAIN W,%TNODP
	  JRST TYEFSD		;SO GO DO IT
	MOVEI A,33		;VT52S ETC. NEED ALTMODE PREFIX
	SKIPGE CCFS(W)
	 JRST TYPOU2		;SO GO DO THAT
TYEFS2:	ANDCAM E,TTYCOM(I)	;ABOUT TO DO SECOND PART
	HRRZ A,CCFS(W)		;GET CHARACTER TO SEND
	AOS TTYIHP(I)		;IT WILL MOVE THE CURSOR
	JRST TYPSIO		;SEND IT, AND ABSORB THE %TDFS

TYEFSD:	LDB B,[$TPPCR,,TTYOPT(I)]
	PUSHJ P,TYMPAD		;SET UP TTYBYP TO PAD
	JRST TYPLUP		;PAD THEN COME BACK HERE

;handle forward-space on AAA's
TYFSAA:	MOVE A,CCFS(W)
	JRST TYEEO2

;HANDLE CLEAR-EOL:
TYEEOL:	SKIPA A,CCEOLP(W)

;HANDLE CLEAR-EOF
TYEEOF:	 MOVE A,CCEOFP(W)
TYEEO2:	CAILE A,0
	 PUSHJ P,TYEEO3		;JUMP IF OUTPUT SEQ IS mn,,TABLE
TYEEO4:	MOVEM A,TTYBYP(I)	;STORE BYTE POINTER OR ZERO
TYEEO1:	AOS TORM(I)		;FLUSH THE CURSOR CTL CMD FROM OUTPUT BFR.
	MOVEM Q,TOOP(I)
	JRST TYPLUP

;OUTPUT SEQUENCE SPECIFIED AS mn,,TABLE
;m=LOWEST PAD CODE IN TABLE, n=HIGHEST
TYEEO3:	LDB B,[$TPPCR,,TTYOPT(I)]
	LDB C,[220300,,A]	;n
	CAMLE B,C
	 MOVE B,C
	LDB C,[250300,,A]	;m
	SUB B,C
	SKIPLE B
	 ADD A,B
	MOVE A,(A)	;PICK UP BYTE POINTER OUT OF TABLE
	POPJ P,

;HANDLE CLEAR THE SCREEN
TYECLR:	SETZM TTYIHP(I)	;AFTER CLEARING, CURSOR WILL BE AT TOP LEFT
	SETZM TTYIVP(I)
	SKIPA A,CCCLRP(W)
;HANDLE DELETE FWD, ON OVERPRINTING ERASABLE DISPLAYS, AND IMLACS (ACC TO %TOIML).
TYEDLF:	 MOVE A,CCDLFP(W)
	JRST TYEEO2

;HANDLE ENTER-INVERSE-VIDEO AND LEAVE-ALL-SUCH-MODES
TYEBOW:	SKIPA A,CCBOWP(W)
TYERST:	 MOVE A,CCRSTP(W)
	JRST TYEEO2

TYEINI: MOVE A,CCINIP(W)
	JRST TYEEO2

;REGION-SCROLL UP AND REGION-SCROLL DOWN HANDLED ONLY ON DM2500
;FOR NOW.  REAL DM2500'S CAN'T DO IT, BUT CERTAIN FAKE ONES CAN.
;SOMEDAY HAIRY CODE COULD BE ADDED TO DO IT ON C100 AND VT100.
TYERSU:
TYERSD:	SUBI A,%TDRSU-^U	;SEND ^U OR ^V
;	CAIE W,%TNDTM
;	 JRST TYEEO1
	MOVE B,TORM(I)		;MAKE SURE ARGS IN BUFFER
	CAILE B,TOBS-3
	 JRST TYPEND		;NO, COME BACK LATER
	DPB A,Q
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	ILDB A,Q		;XOR 140 INTO ARGS
	XORI A,140
	DPB A,Q
	CAMN Q,TOBEP(I)
	 MOVE Q,TOBBP(I)
	ILDB A,Q
	XORI A,140
	DPB A,Q
	MOVNI A,2		;COMPENSATE FOR "PRINTING" CHARS
	ADDM A,TTYIHP(I)
	JRST TYPLUP

;HANDLE DELETE AND INSERT CHARACTERS AND LINES
;DOESN'T TRY TO BE TOTALLY HAIRY ABOUT MULTIPLE INSERT/DELETES.
TYEILP:	SKIPA A,CCILPP(W)
TYEDLP:	 MOVE A,CCDLPP(W)
	JRST TYEIL1

;if we're on an H19 we don't want to call TYDH19 from TYEICP, because
;no multiple insert char.
TYEICP:	MOVE A,CCICPP(W)
	CAIE W,%TNH19	;if we're on an H19, no multiple insert char
	 JRST TYEIL1	;so hack locally, else go to main routine
	MOVE B,TORM(I)	;MAKE SURE REPEAT-COUNT ARGUMENT IS IN THE BUFFER
	CAILE B,TOBS-2
	 JRST TYPEND	;if it's not, come back when it is
	CAMN Q,TOBEP(I)
  	 MOVE Q,TOBBP(I)
	ILDB B,Q	;GET IT
	JRST TYEIL2
TYEDCP:	MOVE A,CCDCPP(W)
TYEIL1:	MOVE B,TORM(I)	;MAKE SURE REPEAT-COUNT ARGUMENT IS IN THE BUFFER
	CAILE B,TOBS-2
	 JRST TYPEND	;IT'S NOT, COME BACK WHEN IT IS
	CAMN Q,TOBEP(I)
  	 MOVE Q,TOBBP(I)
	ILDB B,Q	;GET IT
	CAIN W,%TNAAA	;AAA's have a better way of doing this
	 JRST TYIDAA
	CAIN W,%TNH19	;so do H19's
	 JRST TYDH19
TYEIL2:	SOJG B,[DPB B,Q	;NOT LAST TIME, LEAVE DECREMENTED REQUEST IN BUFFER
		CAILE A,0
		 PUSHJ P,TYEEO3
		MOVEM A,TTYBYP(I)	;AND DO ONCE
		JRST TYPLUP]
	AOS TORM(I)	;OTHERWISE, REMOVE FROM BUFFER
	JRST TYEEO2	;AND GO DO

;Handle insert/delete line, delete char on an H19, without weenie
;weenie.  Actually enters ANSI mode for multiple insert/deletes.
TYDH19:	CAIG B,6		;if we're doing < 6, non-hairy way is faster.
	 JRST [ MOVE A,1(A)	;format of table is
		JRST TYEIL2 ]	; [ansicommand ? zdscommand]
	MOVE A,@A		;get the command char
	AOS TORM(I)		;flush the arg
	MOVE C,TOCMBF(I)	;pointer to comand buffer
	MOVEI E,33		;send esc and
	IDPB E,C
	MOVEI E,"<		;< to enter ANSI mode
	IDPB E,C
	PUSHJ P,TYIDA2		;send the command and set TT to arg
	MOVEI A,19.		;19 ms padding per operation.
	MOVE D,H19ZDS		;copy command to enter ZDS mode
	 ILDB E,D		;into buffer
	 JUMPE E,TYDAPD		;when done, go do padding
	 IDPB E,C
	 JRST .-3

H19ZDS:	440700,,[ASCIZ /[?2h/]	;command to enter ZDS mode

;Handle insert/delete chars/lines on an AAA. This code avoids the
;"weenie weenie" syndrome, where lines get deleted one at a time
;(weenie weenie), and then get inserted one at a time (weenie weenie).
TYIDAA:	AOS TORM(I)		;flush arg from buffer
	MOVE C,TOCMBF(I)	;get pointer to command buffer
	PUSHJ P,TYIDA2		;send command and set TT to arg
	MOVEI A,4		;4 ms padding per operation
	JRST TYDAPD		;send the padding

TYIDA2:	MOVEI E,33		;send esc
	IDPB E,C
	MOVEI E,"[		;send [
	IDPB E,C
	MOVE E,B		;SNDNUM takes arg in E
	MOVE D,A		;and bashes A
	MOVE TT,B		;and B - so save 'em
	SOS E			;SNDNUM also adds 1 to its arg.
	PUSHJ P,SNDNUM		;send arg
	IDPB D,C		;send command char, which is now in D
	POPJ P,

;TYDAPD sets up the end of TOCMBF to include a null and the amount of
;padding needed, and then jumps to TYEEO2.  TT contains a number that
;is multiplied by the contents of A to get the number of ms of padding
;desired.  TT usually has the number of inserts or deletes in it, and
;A usually has the pad factor.
TYDAPD:	MOVEI D,0		;put a null at end
	IDPB D,C		;now do padding - set up for TYEEO2
	HLRZ D,C		;did we just deposit in the lowest
	CAIN D,010700		;byte in this word?
	 JRST [ HRRZ D,C	;yes, put a 1 in the next
		AOS D
		MOVEI E,1
		MOVEM E,@D
		JRST .+2 ]
	JRST [ HRRZ D,C		;turn on the low bit in this one
	       MOVEI E,1
	       IORM E,@D
	       JRST .+1 ]
	AOS D
	IMUL TT,A		;ms padding = TT * A
	MOVEM TT,@D		;TT usually has arg to command
	MOVE A,TOCMBF(I)	;pointer to beginning of buffer
	JRST TYEEO2		;goes in A, where TYEEO2 wants it

;HANDLE TURN-ON-MOTOR COMMAND.
TYEMTN:	CAIE W,%TNTRM
	 JRST TYEEO1	;NO-OP EXCEPT ON TERMINETS
	LDB B,[$TPPLF,,TTYOPT(I)]
	JUMPE B,TYEEO1	;PADDING CODE 0 => DON'T HACK THE MOTOR.
	HRRZ A,TYMTVT(B)
	LSH A,1
	IDIVI A,5
	MOVNS A
	ADD A,TYEMT1(B)	;CREATE A BP TO A STRING WITH THE RIGHT # OF RUBOUTS.
	JRST TYEEO4

;THIS IS AN ASCIZ STRING OF 90. RUBOUTS.
;SOME FINAL SEGMENT OF IT WILL BE TYPED OUT.
TYEMT0:	REPEAT 90./5,  -2
TYEMT2:	ASCIZ /H/

TYEMT1:	010700,,TYEMT2-1
	100700,,TYEMT2-1
	170700,,TYEMT2-1
	260700,,TYEMT2-1
	350700,,TYEMT2-1

;HANDLE TURN-MOTOR-OFF COMMAND.
TYEMTF:	CAIE W,%TNTRM
	 JRST TYEEO1
	LDB B,[$TPPLF,,TTYOPT(I)]
	JUMPE B,TYEEO1
	MOVE A,[440700,,[ASCIZ/J/]]
	JRST TYEEO2

;CRLF AND CLEAR EOL.
TYECRL:	SETZM TTYIHP(I)
	AOS B,TTYIVP(I)
	MOVN A,TTYROL(I)
	CAML B,TCMXV(I)
	 ADDM A,TTYIVP(I)
	MOVE A,CCROLP(W)	;HOW TO SCROLL THIS KIND OF TTY?
	JRST TYEEO2

SUBTTL TABLES OF CURSOR-CONTROL SEQUENCES

;Note that a table entry can be (for those tables which are strings):
;	mn,,TABLE - m is lowest pad code in table, n is highest
;		    These pad codes from the $TPPCR.  The appropriate
;		    table entry is selected, indexed by pad code.
;		    The table entry should look like 440700,,string.
;	440700,,string - the string is output.  If the low-order
;		    bit of the last word in the string is set, the
;		    following word contains the number of milliseconds
;		    of padding required.  (max is 200 ms at 9600 baud,
;		    see TYMPAD), or if this word is SETZ, a special kludge
;		    for Tektronix screen-clear is invoked.
;		    A negative number is the number of 1/8 msec of padding
;		    per line below the cursor.  Note carefully that is in
;		    1/8 msec units!
;	0 - output nothing
;
; (for those tables which are characters):
;	"ch - output the character
;	SETZ "ch - output esc (033) followed by the character

;DATAPOINT CURSOR CONTROL CHARACTERS
%DPFS==30	;30 => FORWARD SPACE
		;31 => (NON-EXISTANT)
%DPUP==32	;32 => MOVE UP
		;33 => (NON-EXISTANT)
%DPHD==34	;34 => HOME DOWN (DOESN'T WORK ON OLD DATAPOINTS ABOVE 300 BAUD)
%DPHU==35	;35 => HOME UP
		;36 => CLEAR EOL
		;37 => CLEAR EOF
%DPBS==10	;BACKSPACE
%DPDN==12	;LINEFEED.

CCDPSO:	0	;PRT	;LH DIRECT POSITIONING CHAR, RH INDEX INTO CCDPSM
	0	;DPT	;4.9 ESC BEFORE CHAR, 4.8 HORIZONTAL THEN VERTICAL
	0		;LSR
	200016,,0	;IMLAC
	0		;TEK
	0		;TV
	0		;MEM
	0		;SFW
	0		;TRM
	400131,,2	;ESC
	200014,,1	;DTM
	400131,,2	;RAY
	400141,,2	;HDS
	0		;H19's have their own routine
	0		;AAA's have their own routine
IFN .-CCDPSO-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCDPSO

;INSTRUCTION TO MUNG B TO CONVERT TO TERMINAL'S COORDINATE SYSTEM
CCDPSM:	ADDI B,1	;IMLAC
	XORI B,140	;DATAMEDIA
	ADDI B,40	;VT52, TELERAY, CONCEPT-100, ETC.

CCFS:	40	;FORWARD-SPACE CHARACTER, 4.9 => IT NEEDS AN ESC IN FRONT OF IT
	%DPFS	;DPT
	%DPFS	;LSR
	^Y	;IMLAC
	40	;TEK
	0	;TV
	40	;MEM
	0	;SFW
	40	;TRM
	SETZ "C	;ESC
	34	;DTM
	SETZ "C	;RAY
	SETZ "=	;HDS
	SETZ "C	;H19
;the AAA entry looks strange here, but it's the right thing. TYEFS
;checks for AAA's specially, and AAA's don't use TYMDP.
	440700,,[.BYTE 7 ? 33 ? "[ ? "C ]	;AAA
IFN .-CCFS-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCFS

CCUP:	0	;LINE-STARVE CHARACTER, - => IT NEEDS AN ESC IN FRONT OF IT
	%DPUP	;DPT
	%DPUP	;LSR
	0	;IMLAC
	13	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	SETZ "A	;ESC
	32	;DTM
	SETZ "A	;RAY
	SETZ ";	;HDS
	SETZ "A	;H19
	0	;AAA
;this entry isn't here because this is a stupid word table instead
;of a winning string table.
;       440700,,[.BYTE 7 ? 33 ? "[ ? "A ]	;AAA
IFN .-CCUP-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCUP

CCHUP:	0	;HOME-UP SEQUENCE POINTER
	440700,,[.BYTE 7 ? %DPHU]	;DPT
	440700,,[.BYTE 7 ? %DPHU ? %DPHU ? %DPHU]	;LSR
	0	;IMLAC
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	440700,,[.BYTE 7 ? 33 ? "H] ;ESC
	440700,,[.BYTE 7 ? 2]	;DTM
	440700,,[.BYTE 7 ? 33 ? "H] ;RAY
	440700,,[.BYTE 7 ? 33 ? "?] ;HDS
	440700,,[.BYTE 7 ? 33 ? "H] ;H19
	440700,,[.BYTE 7 ? 33 ? "[ ? "H]	;AAA
IFN .-CCHUP-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCHUP

CCHDP:	440700,,CCHD
CCHD:	34_29.+177_22.+177_15.+177_8

CCEOLP:	0	;PRT
	440700,,[.BYTE 7 ? 36 ? 177 ? 177 ? 177]	;DPT
	440700,,[.BYTE 7 ? 36 ? 36 ? 36 ? 36]	;LSR
	440700,,[.BYTE 7 ? ^Q]	;IMLAC
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	440700,,[.BYTE 7 ? 33 ? "K]	;ESC
	440700,,[.BYTE 7 ? 27]	;DTM
	440700,,[.BYTE 7 ? 33 ? "K] ;RAY
	01,,[ 440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 8.]	;HDS 300/1200
	      440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 16.] ]	;HDS 9600
	440700,,[.BYTE 7 ? 33 ? "K]	;H19
	440700,,[.BYTE 7 ? 33 ? "[ ? "K]	;AAA
IFN .-CCEOLP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDEOL

CCEOFP:	0	;PRT
	440700,,[.BYTE 7 ? 37 ? 177 ? 177 ? 177]	;DPT
	440700,,[.BYTE 7 ? 37 ? 37 ? 37 ? 37 ? 37 ? 0]	;LSR
	440700,,[.BYTE 7 ? ^P]	;IMLAC
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	440700,,[.BYTE 7 ? 33 ? "J]	;ESC
	440700,,[.BYTE 7 ? 27]	;DTM (CAN'T CLEAR TO EOF, SO CLEAR TO EOL)
	440700,,[<.BYTE 7 ? 33 ? "J>+1 ? 90.]	;RAY
		;HDS PAD CODES ARE 0 1200 OR LESS, 1 9600 OR MORE
		; AT 9600 OR ABOVE, USE ERASE EOL INSTEAD OF ERASE EOS
	01,,[	; DUE TO INABILITY TO SEND 340 (!!) MILLISECONDS OF PADDING
	    440700,,[<.BYTE 7 ? 33 ? 3>+1 ? 170.] ;HDS 300/1200
	    440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 16.] ] ;HDS 9600
	440700,,[.BYTE 7 ? 33 ? "J]	;H19
	440700,,[<.BYTE 7 ? 33 ? "[ ? "J>+1 ? 5.]	;AAA 5 ms padding
IFN .-CCEOFP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDEOF

CCDLFP:	0	;PRT
	440700,,[.BYTE 7 ? 31]	;(DPT) FOR BENEFIT OF GT40
	0	;LSR
	440700,,[.BYTE 7 ? ^X]	;IMLAC
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	0	;ESC
	0	;DTM
	0	;RAY
	0	;HDS
	0	;H19
	0	;AAA
IFN .-CCDLFP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDDLF

CCROLP:	0	;PRT
	25,,CCCRLP	;DPT
	25,,CCCRL1	;LSR
	440700,,[.BYTE 7 ? ^M ? ^K ? ^Q]	;IMLAC
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K]	;ESC
	440700,,[.BYTE 7 ? ^M ? ^J ? 27]	;DTM
			;NOTE: REAL DATAMEDIAS IGNORE THE ^J BUT IMITATION ONES MIGHT NOT
	440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K]	;RAY
	440700,,[<.BYTE 7 ? ^M ? ^J ? 33 ? 23>+1 ? 16.]	;HDS
	440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K]	;H19
	440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "[ ? "K ? 0]	;AAA
IFN .-CCROLP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDCRL

;CRLF ON DATAPOINTS, DEPENDING ON LOSER-NESS AND SPEED.
CCCRLP:	440700,,[.BYTE 7 ? ^M ? ^J ? 36]
	440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 36]
REPEAT 2,440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 177 ? 36]

CCCRL1:	440700,,[.BYTE 7 ? ^M ? ^J ? 36 ? 36 ? 36 ? 36]
	440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 36 ? 36 ? 36 ? 36]
REPEAT 2,440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 177 ? 36 ? 36 ? 36 ? 36 ? 0]

CCCLRP:	0		;CLEAR THE SCREEN SEQUENCE POINTER
	440700,,[.BYTE 7 ? %DPHU ? 37 ? 177 ? 177 ? 177 ? 0]	;DPT
	440700,,[.BYTE 7 ? %DPHU ? %DPHU ? %DPHU ? 37 ? 37 ? 37 ? 37 ? 37 ? 0]	;LSR
	440700,,[.BYTE 7 ? ^L]	;IMLAC
	440700,,[<.BYTE 7 ? 33 ? 14>+1 ? SETZ] .SEE TYPBP	;TEKTRONIX
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	440700,,[.BYTE 7 ? 33 ? "H ? 33 ? "J ? 0]	;ESC
	34,,[440700,,[.BYTE 7 ? 36]	;DTM
	     440700,,[.BYTE 7 ? 36 ? 36]]
	440700,,[<.BYTE 7 ? 33 ? "j>+1 ? 90.]	;RAY
	440700,,[<.BYTE 7 ? 14>+1 ? 48.] ;HDS (RIGHT FOR 9600 BAUD, NEED HALF AS MUCH AT 300)
	440700,,[.BYTE 7 ? 33 ? "H ? 33 ? "J ? 0]	;H19
	440700,,[<.BYTE 7 ? 33 ? "[ ? "H ? 33 ? "[ >
		 <.BYTE 7 ? "J>+1 ? 5.]		;AAA needs 5 ms padding

IFN .-CCCLRP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDCLR

CCILPP:	0	;PRT
	0	;DPT
	0	;LSR
	0	;IML
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	01,,[	;ESC padding mainly based on H19 - CBF
	    440700,,[<.BYTE 7 ? 33 ? "L>]	; no padding at all at 1200 baud
	    440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -6.]]	; .75 ms/line at higher
	04,,[440700,,[.BYTE 7 ? ^P ? ^J ? ^X ? 0]	;DTM
	     440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 3,[177 ? ] ^X ? 0]
	     440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 5,[177 ? ] ? ^X ? 0]
	     440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 10.,[177 ? ] ^X ? 0]
	     440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 20.,[177 ? ] ^X ? 0]]
	440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -20.]	;RAY (2.5ms/line)
	01,,[
	    440700,,[<.BYTE 7 ? 33 ? ^R>+1 ? -14.]	;HDS AT 300/1200 (1.75ms/line)
	    440700,,[<.byte 7 ? 33 ? ^R>+1 ? -3.*8]]	;HDS AT 9600 (3ms/line)
	["L ? 01,,[			;H19's use this table differently
		    440700,,[<.BYTE 7 ? 33 ? "L>]	; no padding at all at 1200 baud
		    440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -6.]]]	; .75 ms/line at higher
	"L			;AAA (AAA's use this table differently)

IFN .-CCILPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDILP

CCDLPP:	0	;PRT
	0	;DPT
	0	;LSR
	0	;IML
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	01,,[	;ESC padding mainly based on H19 - CBF
	    440700,,[<.BYTE 7 ? 33 ? "M>]	; no padding at all at 1200 baud
	    440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -6.]]	; .75 ms/line at higher
	34,,[440700,,[.BYTE 7 ? ^P ? ^Z ? ^X]	;DTM
	     440700,,[.BYTE 7 ? ^P ? ^Z ? 177 ? ^X]]
	440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -20.]	;RAY (2.5ms/line)
	01,,[
	    440700,,[<.BYTE 7 ? 33 ? ^B>+1 ? -14.]	;HDS AT 300/1200 (1.75ms/line)
	    440700,,[<.byte 7 ? 33 ? ^B>+1 ? -3.*8.]]	;HDS AT 9600 (3ms/line)
	["M ? 01,,[			;H19's use this table differently
		    440700,,[<.BYTE 7 ? 33 ? "M>]	; no padding at all at 1200 baud
		    440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -6.]]]	; .75 ms/line at higher
	"M			;AAA (AAA's use this table differently)
IFN .-CCDLPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDDLP

CCICPP:	0	;PRT
	0	;DPT
	0	;LSR
	0	;IML
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	440700,,[.BYTE 7 ? 33 ? "Q ? 40 ? 10 ? 33 ? "R]	;ESC
	34,,[440700,,[.BYTE 7 ? ^P ? ^\ ? ^X]	;DTM
	     440700,,[.BYTE 7 ? ^P ? 40 ? 177 ? ^X ? ^H ? 40 ? ^H ? 0]]
	440700,,[.BYTE 7 ? 33 ? "P]	;RAY
		; The HDS requires a null in its insert char sequence so we
		; resort to non 7 bit char so the typeout loop won't think its
		; the end of an ASCIZ string.
	01,,[	;HDS
	    441100,,[<.byte 9 ? 33 ? 20 ? 40 ? 10 > ?
	             <.byte 9 ? 33 ? 400 >]	; no padding 1200 or under
	    441100,,[<.byte 9 ? 33 ? 20 ? 40 ? 10 > ?
	             <.byte 9 ? 33 ? 400 >+1 ? 16.]]	; 16 ms per insert >1200
	440700,,[.BYTE 7 ? 33 ? "@ ? 40 ? 10 ? 33 ? "O]	;H19
	"@			;AAA's use this table differently
IFN .-CCICPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDICP

CCDCPP:	0	;PRT
	0	;DPT
	0	;LSR
	0	;IML
	0	;TEK
	0	;TV
	0	;MEM
	0	;SFW
	0	;TRM
	440700,,[.BYTE 7 ? 33 ? "P]	;ESC
	34,,[440700,,[.BYTE 7 ? ^P ? ^H ? ^X]	;DTM
	     440700,,[.BYTE 7 ? ^P ? ^H ? 177 ? ^X]]
	440700,,[.BYTE 7 ? 33 ? "Q]	;RAY
	01,,[	;HDS
	    440700,,[.byte 7 ? 33 ? 21]	; no padding 1200 or under
	    440700,,[<.byte 7 ? 33 ? 21>+1 ? 16.]]	; 16 ms per del at >1200
	["P ? 440700,,[.BYTE 7 ? 33 ? "N]]	;H19's also use this table differently
	"P			;AAA's use this table differently
IFN .-CCDCPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDDCP

CCBOWP:
 REPEAT %TNDTM,0
	440700,,[.BYTE 7 ? 16]	;DTM
	0	;RAY
	440700,,[.BYTE 7 ? 33 ? "D]	;HDS
	440700,,[.BYTE 7 ? 33 ? "p]	;H19
	440700,,[.BYTE 7 ? 33 ? "[ ? "7 ? "m]	;AAA
IFN .-CCBOWP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDBOW

CCRSTP:
 REPEAT %TNESC,0
	440700,,[.BYTE 7 ? 33 ? "G]	;VT52, ETC.
	440700,,[.BYTE 7 ? 30]		;DTM
	0	;RAY
	440700,,[.BYTE 7 ? 33 ? "d]	;HDS
	440700,,[.BYTE 7 ? 33 ? "q]	;H19
	440700,,[.BYTE 7 ? 33 ? "[ ? "m]	;AAA - this is not RIS,
;which could screw you over if your default state were a bad one. It's
;just SGR 0.
IFN .-CCRSTP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDRST

CCINIP:			    ;initialize an intelligent terminal
 REPEAT %TNESC,0
	440700,,[.BYTE 7 ? 33 ? "G]	;VT52, ETC.
	440700,,[.BYTE 7 ? 30]		;DTM
	0	;RAY
	440700,,[.BYTE 7 ? 33 ? "d]	;HDS
	440700,,[.BYTE 7 ? 33 ? "q]	;H19
;all sorts of ways the AAA can be messed up. We fix just a few.
	440700,,[ASCII "[4;18;20l[6;12h[1Q[>27;29;30;33;34;35;37;40;46;51l[>52h[H["
		 <ASCIZ "J">+1 ? 5.]	;First line must be multiple of 5 chars!
;does: turn off insert char, LF is LF, CR is CR, no destructive BS, no
;wrap forward, no wrap backward, no AUTO XON/XOFF, no half-duplex, no
;auto kbd disable(!), no alternate cursor mode. Let us clear entire
;screen, enable sending to host, turn off delete display, turn on META
;key. Finally, clears the screen, about 5 ms padding.
IFN .-CCINIP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDINI


SUBTTL TTY CONTROL TABLES

;TOTAL NUMBER OF TTYS
NCT==NOTYS+NKSTYS+NETYS+NNTYS+NNVTTS+NDZTYS+NDPTYS+NMTYS+NDLTYS+NSTTYS+N11TYS

IFGE NCT-%TINON, .ERR EXCESSIVE NUMBER OF TTYS

IFG NOTYS-1, .ERR MORE THAN ONE KA-10 CONSOLE TTY?
IFG NKSTYS-1, .ERR MORE THAN ONE KS-10 CONSOLE TTY?

NFKSTY==NOTYS		;# OF FIRST KS-10 (BETTER BE ONLY) 8080 CONSOLE TTY
NFETY==NFKSTY+NKSTYS	;# OF FIRST DTE20 TTY
NFNTY==NFETY+NETYS	;# OF FIRST TK-10 TTY
NFNVTY==NFNTY+NNTYS	;# OF FIRST NOVA TTY
NFDZTY==NFNVTY+NNVTTS	;# OF FIRST DZ11 TTY.
; Terminals above this line have slow (char at a time) controllers
; below they have fast controllers.  (Check TYPDA1: and TTYDO:)
NFDPTY==NFDZTY+NDZTYS	;# OF FIRST DATAPOINT LINE
NFMTY==NFDPTY+NDPTYS	;# OF FIRST MORTON TTY
NFDLTY==NFMTY+NMTYS	;# OF FIRST DL10 TTY.
NFSTTY==NFDLTY+NDLTYS	;# OF FIRST PSEUDO-TTY
NF11TY==NFSTTY+NSTTYS	;# OF FIRST PDP11-TV TTY.

IFG NKSTYS, IFN NFKSTY, .ERR KS-10 CONSOLE TTY NOT ZERO?
IFG NETYS, IFN NFETY, .ERR FIRST DTE20 TTY NOT ZERO?

;INSTRUCTION TO OUTPUT 1 CHAR TO A CHAR-AT-A-TIME CONTROLLER.
;INSNS NEED NOT EXIST FOR FAST CONTROLLERS.
TTYDO:	REPEAT NOTYS,DATAO TTY,A
	REPEAT NKSTYS, PUSHJ P,TTKSDO
	REPEAT NETYS,JFCL
	REPEAT NNTYS,DATAO NTY,A
	REPEAT NNVTTS,PUSHJ P,TTNDO
	REPEAT NDZTYS,PUSHJ P,TTDZDO

IFN NKSTYS,[
TTKSDO:	ANDI A,177		; Be sure it is ASCII
	TRO A,400		; Tell 8080 there is something there.
	MOVEM A,8CTYOT		; Here is where it looks.
	CONO 80INT\APRCHN	; Wake up!
	POPJ P,
] ;NKSTYS

IFN NDZTYS,[			;DZ-11 Code
TTDZDO:	PUSH P,C
	ANDI A,177		;Be sure it is ASCII, and no break bits set
	HRRZ C,TTYLT(I)		;Unibus address
	IOWRBI A,%DZRTD(C)	;Send it
	POP P,C
	POPJ P,
] ;NDZTYS

IFN NNVTTS,[
TTNDO:	ANDI A,177
	CAME I,NVOPTT
	JRST TTNDO1
	AOS NVTCC
	DATAO NTY,A
	POPJ P,

TTNDO1:	MOVEM I,NVOPTT	;MUST SELECT NEW CONSOLE
	SETOM NVTSIP	;SIGNAL
	MOVEM A,NVTSSC	;SAVE CHR
	PUSH P,I
	SUBI I,NFNVTY-1
	TRO I,200
	DATAO NTY,I
	CLEARM NVTCC
	POP P,I
	POPJ P,
]

;INSTRUCTION TO TELL A TTY'S CONTROLLER TO STOP INTERRUPTING FOR IT.
;(BECAUSE THERE IS NO OUTPUT TO BE SENT)
TTYDFF:	REPEAT NOTYS,CONO TTY,200+TTYCHN
	REPEAT NKSTYS, JFCL
	REPEAT NETYS,JFCL
	REPEAT NNTYS,CONO NTY,20+TTYCHN
	REPEAT NNVTTS,JRST TYP5
	REPEAT NDZTYS,PUSHJ P,DZTYDF
	REPEAT NDPTYS,CONO DPK,.RPCNT_12.+400+TTYCHN
	REPEAT NMTYS,CONO MTY,.RPCNT_12.+200+TTYCHN
	REPEAT NDLTYS,JFCL
	REPEAT NSTTYS,JFCL

;LINE-SPECIFIC INFORMATION
TTYLT:	REPEAT NOTYS,500000+TTYCHN
	REPEAT NKSTYS, 0
	REPEAT NETYS,0
	REPEAT NNTYS,.RPCNT_12.+400000+TTYCHN
	REPEAT NNVTTS,0
	REPEAT NDZTYS, <.RPCNT&DZLNM>,,<CONC DZ,\<.RPCNT_-DZLNLN>,BA>
	REPEAT NDPTYS,0
	REPEAT NMTYS,.RPCNT_12.+TTYCHN

;INSN TO EXECUTE TO SIGNAL THAT OUTPUT IS AVAILABLE ON A PREVIOUSLY
;IDLE TTY - TELLS THE CONTROLLER TO CAUSE AN "OUTPUT DONE" INTERRUPT.
TTYST:	REPEAT NOTYS,CONO TTY,10+TTYCHN
	REPEAT NKSTYS, CONO 10020\APRCHN
	REPEAT NETYS,PUSHJ P,TTYSTE
	REPEAT NNTYS,PUSHJ P,NTYST
	REPEAT NNVTTS,PUSHJ P,NVTYST
	REPEAT NDZTYS,PUSHJ P,DZTYST
	REPEAT NDPTYS,CONO DPK,.RPCNT_12.+100+TTYCHN
	REPEAT NMTYS,CONO MTY,.RPCNT_12.+10+TTYCHN
	REPEAT NDLTYS,PUSHJ P,TTYSTD
	REPEAT NSTTYS,PUSHJ P,TTYPT
	REPEAT N11TYS,JFCL

IFN DZ11P,[			;DZ-11 Code
; Disable transmitter ready interrupts from this line
DZTYDF: PUSH P,[ANDCM B,DZLBIT(A)]	;Clear this line's bit
	JRST DZTYDS

; Enable transmitter ready interrupts from this line
DZTYST: PUSH P,[IOR B,DZLBIT(A)]	;Set this line's bit
DZTYDS:	PUSH P,A
	PUSH P,B
	PUSH P,C
	HRRZ C,TTYLT(I)		;Unibus address
	HLRZ A,TTYLT(I)		;Line number
	IORDBI B,%DZRTC(C)
	XCT -3(P)		;Frob bit
	IOWRBI B,%DZRTC(C)	;Write new state
	POP P,C
	POP P,B
	POP P,A
	SUB P,[1,,1]
	POPJ P,

; DZ11 initialization.
; No parity, character length = 8 bits, stop-code = 1 bit.
DZINIT: MOVEI C,NDZTYS-1	;Relative last DZ TTY
	SKIPGE C		;Don't do anything if there aren't any
	 POPJ P,
DZINI1: LDB A,[$TTOSP,,NFDZTY+TTYTYP(C)] ;Ospeed (assume it is = Ispeed)
	HLRZ D,NFDZTY+TTYLT(C)	; Line number on board.
	HRRZ B,NFDZTY+TTYLT(C)	; Bus address of controller.
	SOSL A			;Is speed = 0?
	 CAILE A,10		;Is speed > 9600?
	  BUG HALT,[BAD SPEED CODE FOR DZ-11. LINE],OCT,C
	LSH A,32.		;Assemble byte pointer
	IOR A,[400,,[.BYTE 4 ? 16 ? 14 ? 12 ? 10 ? 7 ? 5 ? 4 ? 2 ? 6]]
	LDB A,A			;Obtain DZ11 speed code
	LSH A,%DZLSS		;Assemble LPR code
	IORI A,%DZLRO+3*%DZLCL(D)	;Line # to write and various bits
	XCTRI [IOWRI A,%DZRLP(B)]	;Initialize this line
	 CAIA
	  BUG HALT,[DZ11 NOT RESPONDING (CHECK THE BREAKER ON THE UNIBUS). LINE],OCT,C
	SOJGE C,DZINI1		;Loop over all DZ TTYs.

IFN <NDZTYS&DZLNM>,[
	MOVEI C,<NDZTYS&DZLNM>	;First unused line on last used board
DZINI2: IOWRI C,%DZRLP+<CONC DZ,\<NDZTYS_-DZLNLN>,BA>	; Disable line
	CAIGE C,DZNLN-1		;Only disable lines on last used board
	  AOJA C,DZINI2		;Loop
]
	MOVEI C,%DZCTE+%DZCRE+%DZCSE+%DZCMS	;Turn board on
	MOVEI D,377_8		; Set all DTR bits, clear enable bits
REPEAT <<NDZTYS+DZNLN-1>_-DZLNLN>,[
	IOWRI C,%DZRCS+<CONC DZ,\.RPCNT,BA>
	IOWRI D,%DZRTC+<CONC DZ,\.RPCNT,BA>
]
	POPJ P,

;CALLED AT CLOCK LEVEL TO EMPTY DZ INPUT SILOS TO TTY CODE
; What you really want to do is measure the average interrupt rate of
; each DZ and use this scanning approach only when the DZ is heavily
; active. What fun.
DZSCAN:	CONO PI,TTYOFF-1	;No TTY or lower ints, leave clock on
	PUSH P,I		;Just in case
REPEAT <<NDZTYS+DZNLN-1>_-DZLNLN>,[
	IORDI A,%DZRCS+<CONC DZ,\.RPCNT,BA>
	TRNN A,%DZCRD		;Character in silo?
	 JRST CONC DZS,\.RPCNT,EN
CONC DZS,\.RPCNT,LP:
	IORDI A,%DZRDR+<CONC DZ,\.RPCNT,BA>	;Get character from silo
	TRNN A,%DZDDV		;Valid character?
	 JRST CONC DZS,\.RPCNT,EN	;Nope, done with this DZ
				;Check parity?
	LDB I,[.BP %DZLM,A]	;Get line # on DZ
	ADDI I,<DZNLN*.RPCNT>+NFDZTY
	CAIL I,NFDZTY+NDZTYS
	 BUG
	PUSHJ P,NTYI1		;Send char to TTY code
	JRST CONC DZS,\.RPCNT,LP
CONC DZS,\.RPCNT,EN:
]
	POP P,I
	CONO PI,TTYON-1		;Turn ints back on
	POPJ P,
];DZ11P

IFN TK10P,[
NTYST:	PUSH P,C	;START A TK10 TTY
	CONI PI,C
	ANDI C,177	;SAVE WHICH PI CHANNELS ARE ON
	CONO PI,TTYOFF
	CONO NTY,@TTYLT(I)
	CONO NTY,10+TTYCHN
	CONO PI,2000(C)	;RESTORE PI STATUS
	POP P,C
	POPJ P,
]

IFN NNVTTS,[
NVTYST:	PUSH P,I
	SKIPL I,NOVATT
	PUSHJ P,NTYST
	POP P,I
	POPJ P,
]

TTYPT:	PUSH P,B	;TTYST ROUTINE FOR STY TTYS.
	PUSH P,C
	MOVE B,STYSTS-NFSTTY(I)	;USER
IFN NETP,[
	TLNE B,%SSNET
	 JRST TTYPT2
TTYPT3:
];NETP
	MOVE C,STYMSK-NFSTTY(I)	;CHANNELS OPEN MASK
	AND C,MSKST2(B)
	JUMPE C,POPCBJ	;JUMP IF INTS NOT ENABLED
	MOVN B,C
	AND C,B
	MOVE B,STYSTS-NFSTTY(I)
	IORM C,IFPIR(B)
	JRST POPCBJ

IFN NETP,[	;START STY THAT'S DIRECT CONNECTED TO NETWORK
TTYPT2:	CONI PI,C
	ANDI C,177	;SAVE WHICH PI CHANNELS ARE ON
	CONO PI,NETOFF
	MOVSI B,%SSNET
	TDNN B,STYSTS-NFSTTY(I)
	 JRST [ CONO PI,2000(C) ? JRST TTYPT3 ]
	SKIPL STYNTL-NFSTTY(I)
	 JRST TTYPT4	;ALREADY ON ACTIVATE LIST
	MOVE B,STYNTA
	MOVEM B,STYNTL-NFSTTY(I)
	MOVEM I,STYNTA
TTYPT4:	CONO PI,2000(C)	;RESTORE PI STATUS
	JRST POPCBJ
];NETP

IFN NETYS,[
TTYSTE:	CONO PI,400	;PI OFF
	SKIPL DTEOST
	 JRST TYSTE1
	HRRZM I,DTEOST	;TELL 11 TO SET OUTPUT DONE
	CONO PI,200	;PI ON
	CONO DTE,%DBL11	;INTERRUPT 11
	POPJ P,

TYSTE1:	CONO PI,200	;PI ON
	CONO DTE,%DBL11	;INTERRUPT 11
	AOS DTEHC	;COUNT NUMBER OF TIMES HAD TO WAIT
	SKIPL DTEOST	;THERE'S NO WAY TO AVOID HAVING TO WAIT ONE PLACE
	 JRST .-2	; OR ANOTHER.  THE -11 TRIES TO PICK UP OUTPUT-DONE FAST.
	JRST TTYSTE
];NETYS

IFN DL10P,[
TTYSTD:	SKIPN DL10F
	 JRST TYPEN1
	CONO PI,400	;PI OFF
	SKIPE DL10SO
	 JRST TTYSD1
	HRRZM I,DL10SO	;TELL 11 TO SET OUTPUT DONE
	CONO PI,200	;PI ON
	CONO DLC,100040+TTYCHN	;INTERRUPT 11
	POPJ P,

TTYSD1:	CONO PI,200	;PI ON
	CONO DLC,100040+TTYCHN	;INTERRUPT 11
	AOS DL10HC	;COUNT NUMBER OF TIMES HAD TO WAIT
	SKIPE DL10SO	;THERE'S NO WAY TO AVOID HAVING TO WAIT ONE PLACE
	 JRST .-2	;OR ANOTHER.  THE -11 TRIES TO PICK UP OUTPUT-DONE FAST.
	JRST TTYSTD
]

EBLK

DEFINE TTYREP WRD
.CRFOFF
REPEAT NCT,CONC T,\.RPCNT,$!WRD
.CRFON
TERMIN

IFNDEF TIBL,TIBL==41
IFNDEF TOBL,TOBL==101
TIBS==TIBL*2-1
TOBS==TOBL*4

IFNDEF MICBAA,MICBAA==50.	;MAXIMUM NUMBER OF INPUT BUFFER CHARACTERS BEFORE AUTOMATIC ACTIVATION

IFNDEF TYOWNC,TYOWNC==20.	;MIN # BYTES OF SPACE THERE MUST BE
	;IN OUTPUT BUFFER BEFORE IT IS OK TO TRY TO OUTPUT ANYTHING.

TIB:	BLOCK TIBL*NCT		;TTY INPUT BUFFERS (18 BITS PER CHARACTER)
TOB:	BLOCK TOBL*<NCT-N11TYS>	;TTY OUTPUT BUFFERS (8 BITS PER CHARACTER)

;INPUT BUFFER BITS:
%TXMPE==400000	;MAIN PROGRAM ECHO CHARACTER
%TXPIE==200000	;PI ECHO CHARACTER
%TXCOM==100000	;COM MODE ECHO CHAR; DO PI ECHO EVEN IF HDX TTY.
%TXIGN==40000	;IGNORE THIS CHAR AT .IOT TIME.
%TXACT==20000	;THIS IS AN ACTIVATION CHAR.
%TXINT==10000	;THIS CHAR SHOULD INTERRUPT THE USER.

;NOW COME THE BITS OF THE CHARACTER ITSELF:
%TXTOP==4000	;"TOP" KEY.
%TXECI==2000	;ECHOED DUE TO ECHOIN SYSTEM CALL
;%TXSFT==1000	;"SHIFT" KEY.
%TXSUP==1000	;"SUPER" KEY.
%TXMTA==400	;"META" KEY.
%TXCTL==200	;"CONTROL" KEY.
%TXASC==177	;THE ASCII PART OF THE CHARACTER.
	;%TXTOP+CERTAIN LETTERS ARE MAGIC KEYS.  %TXTOP+"Z IS DEFERRED CALL.

;OUTPUT BUFFER BIT:
%TXDIS==200	;1 => THIS IS A %TD CHARACTER.
IF2 EXPUNGE %TXDIS ;SO %TX BIT TYPEOUT MODE LOOKS NICE.

TIIP:	REPEAT NCT,  (002200)TIB-1+.RPCNT*TIBL+TIBL	;INPUT BUFFER INPUT POINTER
TIOP:	REPEAT NCT,  (002200)TIB-1+.RPCNT*TIBL+TIBL	;INPUT BUFFER OUTPUT POINTER
		     (002200)TIB-1			.SEE TTEBAK
TIBEP:	REPEAT NCT,  (002200)TIB-1+.RPCNT*TIBL+TIBL	;END OF INPUT BUFFER POINTER
TOIP:	REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL	;OUTPUT BUFFER INPUT POINTER
	REPEAT N11TYS,0
TOOP:	REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL	;OUTPUT BUFFER OUTPUT POINTER
	REPEAT N11TYS,0
TOBEP:	REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL+TOBL	;END OF OUTPUT BUFFER POINTER
	REPEAT N11TYS,1
TOBBP:	REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL	;BEG OF OUTPUT BUFFER POINTER
	REPEAT N11TYS,1
TINTP:	REPEAT NCT,2200,,TIB-1+.RPCNT*TIBL+TIBL	;INTERRUPT CHARACTER POINTER
ECHOC:	REPEAT NCT,0	;COUNT OF ECHO BUF CHARS THAT ARE REALLY ECHO CHARS
ECHOP:	REPEAT NCT,2200,,TIB-1+.RPCNT*TIBL+TIBL	;POINTER TO INPUT CHARACTER TO BE ECHOED NEXT
TINTC:	REPEAT NCT,0	;COUNT OF CHARACTERS AVAILABLE FOR .ITYIC'ING.
TICC:	REPEAT NCT,0	;TYPE IN CHARACTER COUNT
TACC:	REPEAT NCT,0	;ACTIVATION CHARACTER COUNT
TORM:	REPEAT NCT,TOBS	;# CHARS ROOM LEFT IN OUTPUT BUFFER.
TOCMBF:	REPEAT NCT,440700,,TCMBLK+.RPCNT*5	;5-word string buffer for each
TCMBLK:	BLOCK NCT*5	;tty for outputting commands that are longer than a few chars.

TTYERQ:	REPEAT NCT,-1	;LIST OF TTYS NEEDING ECHO LINKED THRU THESE WDS. (NIL = 200000,,)
			;-1 FOR TTY NOT NEEDING ECHO.
TYOSW:	REPEAT NCT,-1	;AOSE-STYLE SWITCH FOR MP USE OF TTY.
TTNTO:	REPEAT NCT,0	;# CHANNELS TTY IS OPEN ON (IN ALL JOBS.)
TYIMSK:	REPEAT NCT,0	;BIT SET FOR EACH CHANNEL THE TTY IS OPEN FOR
			;INPUT ON IN THE JOB THAT OWNS THE TTY NOW.
TYOMSK:	REPEAT NCT,0	;SIMILAR, BUT FOR OUTPUT CHANNELS.
TTYBYP:	BLOCK NCT	;NOT 0 => B.P. TO ASCIZ STRING TO OUTPUT AT INT. LVL.
TTLTM:	REPEAT NCT,0	;TIME LAST CHRWAS REMOVED FROM OUTPUT BUFFER.
TTYOAC:	REPEAT NCT,-1	;-1 IF TTY OUTPUT INACTIVE 
TTITM:	REPEAT NCT,0	;TIME OF LAST TYPE-IN ON TTY (NOT USED BY SYSTEM).
TTYLJB:	REPEAT NCT,0	;LAST JOB TO OUTPUT TO THIS TTY.  DOES NO HARM IF ABSURD.

TTYIPC:	REPEAT NCT,[
IFG APL,IFE APL-.RPCNT, TTYIS5	;JUST STORE AND EXIT FOR AP LINE.
	.ELSE TTYI	;TTY INPUT PC
]
TYBPC:	REPEAT NCT,TYBN	;PC OF ^\-HANDLING CO-ROUTINE.
TTOALC:	REPEAT NCT,-1	;LH IS -1 TO ALLOW M.P. TYPEOUT, OR 0 TO DELAY IT.
			;RH IS OUTPUT ALLOCATION: -1 => INFINITY (THE NORMAL CASE),
			;ELSE # OF CHARS ALLOWED TO BE OUTPUT. ^\ COMMANDS ARE
			;USED BY THE TTY TO ALLOCATE FOR OUTPUT.

TCMXV:	TTYREP VER	;MAX LINES VERT
TCMXH:	TTYREP HOR	;MAX CHR HORZ
TTYROL:	TTYREP ROL	;# LINES PER GLITCH WHEN SCROLLING.
TTYIHP:	REPEAT NCT,30.	;INT LVL HPOS
TTYIVP:	REPEAT NCT,5	;INT LVL VPOS
TTYLPP:	REPEAT NCT,<TPLEN*2*.RPCNT>#-1
		;IDX OF PC PPR ASSOCIATED WITH TTY,
		;OR NEGATIVE => NONE NOW ASSOCIATED,
		;AND IS 1'S COMP. OF IDX OF PC PPR
		;FORMERLY ASSOCIATED.
TTYEPP:	REPEAT NCT,<TPLEN*2*.RPCNT>	;IDX OF PC PPR TO USE FOR ECHO.
TTYLPS:	REPEAT NCT,5,,30.	;IF TTYLPP <0, THIS IS MAIN PRGM VPOS,,HPOS.

TPBEG:	;BEGINNING OF PC PPR VARS.
TPHB:	;USE 0		;HPOS OF LEFT MARGIN.
TPVB:	BLOCK 1		;VPOS OF TOP MARGIN (1ST LINE OF PC PPR)
TPHE:	;USE TCMXH	;HPOS OF 1ST COLUMN AFTER RIGHT MARGIN
TPVE:	;USE TCMXV	;VPOS OF 1ST LINE BELOW BOTTOM MARGIN
TPHP:	BLOCK 1		;HORIZONTAL POSITION OF CURSOR
TPVP:	BLOCK 1		;VERTICAL POSITION OF CURSOR
TPVM:	BLOCK 1		;NUMBER OF LINES BEFORE A **MORE** IS ALLOWED
TPSP:	BLOCK 1		;SAVED CURSOR POS (FOR ^PS AND ^PR)
TPFLAG:	BLOCK 1		;HOLDS RANDOM FLAGS.
%TF==0,,777775
%TFEOP==1	;1 => HAVE JUST ENTERED LAST LINE OF PC PPR.
		;NEXT ATTEMPT TO OUTPUT SHOULD DO **MORE** PROC.
%TFIGL==2	;1 => LAST CHAR WAS CR NOT IN IMAGE MODE.
		;IF NEXT CHAR IS LF, IGNORE IT.

	TPLEN==.-TPBEG
	.=TPBEG

REPEAT 2*NCT,[		;NOW ASSEMBLE INITIAL CONTENTS OF PC PPR VARS.
	0
	0+IFE .RPCNT&1,30.	;TPHP & TPVP: NONZERO FOR MAIN PRGM.
	0+IFE .RPCNT&1,5
	0 ? 0 ? 0
]
EXPUNG TPHB,TPHE,TPVE

IFN .-TPBEG-NCT*TPLEN*2,.ERR

COMT1:	BLOCK NCT	;COM TEMPORARY STORAGE
COMT3:	BLOCK NCT	;DITTO.  WHILE QUERYING FOR A LINK, THIS IS -1 IF
			;IN IEC MODE, WHICH MEANS OK TO PASS TYPEIN THROUGH
DZLBIT::	; Also Line number bits for DZ11
CHNBIT:	REPEAT 20,1_<.RPCNT>

;DATA POINT CONTROLLER LINE VARIABLES
;THIS ARRAY LOOKED AT BY HARDWARE

IFNDEF LDBFF,LDBFF==10.	;LENGTH OF OUTPUT BUFFER^2 (PER LINE)

IFN DPKPP,[
DPKBAS:	REPEAT NDPTYS,[
	-1	;CHR CNT
	(440701,,0)	;BYTE PNTR
]

DBBFP:	REPEAT NDPTYS,	440700,,DBBF+.RPCNT*LDBFF	;PNTRS TO OUTPUT BUFFER
DPKC:	REPEAT NDPTYS,	DPKBAS+2*.RPCNT	;PNTR TO HARDWARE COUNT WORD
DPKP:	REPEAT NDPTYS,	DPKBAS+2*.RPCNT+1	;PNTR TO BUFFER PNTR WD
DBBF:	BLOCK LDBFF*NDPTYS	;OUTPUT BUFFER

DPSPT:	2	;134
	6	;600
	1	;110
	2	;150
	3	;300
	24.	;1200
	36.	;1800
	48.	;2400
	48.	;4800
LDPSPT==.-DPSPT
]
DBBCC:	0	;CHRS REMAINING IN CURRENT BLOCK
	;FOR DPK, SET ACC. TO OUTPUT SPEED, TO
	;REPRESENT APPROX. 100MS TYPEOUT TIME.
	;FOR MTY, SET TO 5.

DBBCC1:	0	;INITTED LIKE DBBCC, BUT NOT DECREMENTED.

DBBBP:	0	;BYTE PNTR TO DBBF BUFFER OR MTYOW.

;MORTON BOX LINE VARIABLES
IFN MTYP,[
MTYOW:	0	;UP TO 5 CHARS TO BE OUTPUT PUT IN THIS WD.
MTYNC==5	;NUMBER OF CHARS PACKED IN ABOVE WORD.
]

;DTE20 VARIABLES OTHER THAN THOSE IN LOW CORE
;I.E. NOT (DIRECTLY) REFERENCED BY 11
IFN NETYS,[
DTEHC:	0	;NUMBER OF TIMES LOOPING AT TTYSTE
DTECNI:	0	;CONI DTE, AT LAST INTERRUPT
DTEBBY:	0	;NON-ZERO => BUFFER BUSY WITH TRANSFER IN PROGRESS
		; FOR DEBUGGING, THE NON-ZERO VALUE IS THE DTEOUT COMMAND.
DTEBBT:	0	;TIME-OUT IN HALF-SECOND UNITS
DTEOBL==200	;NUMBER OF CHARACTERS IN OUTPUT BUFFER
DTEOBF:	BLOCK <DTEOBL+3>/4	;TTY OUTPUT BUFFER
];NETYS

IFN NNVTTS,[
NOVATT:	-1	;TTY # NOVA CONNECTED TO -1 IF NONE
NVIPTT:	-1	;CURRENT NOVA PSEUDO TTY ON INPUT
NVOPTT:	0	;CURRENT NOVA PSEUDO TTY ON OUTPUT
NVTSIP:	0	;-1 IF NOVA TTY SELECT IN PROGRESS (OUTPUT)
NVTSSC:	0	;CHAR SAVED HERE DURING NVTSIP -1
NVTCC:	0	;# CHARS SENT TO CURRENT TTY SINCE RESCANING OTHER PSEUDO TTYS
NNVSEC:	0	;LAST CONSOLE TO CHECK IN TYP0 SEARCH
NNVSFL:	0	;-1 IF SERVING PREV SELECTED 
		;IE IF IT CRAPS OUT, SEARCH EVEN THO IT = NNVSEC
]

IFN N11TYS,[
;PDP11-TV COMMUNICATION VARIABLES:

TT11HD:	.+1	;ADDR (IN PDP10 ADDRESS SPACE) OF PDP11 CHANNEL
	0	;HEADER AREA. IF @TT11HD IS NONZERO, THERE
		;IS INPUT TO BE PROCESSED.

TT1111:	0	;# TV'S THE 11 IS SET UP FOR
TT11RL:	0	;# TV'S IN USE = MIN (TT1111, N11TYS).
TT11OL:	0	;# PDP10 WORDS IN A PDP11-TV OUTPUT BUFFER.
TT11ER:	BLOCK 6	;FILLED WHEN BAD DATA COMMING FROM PDP11
		.SEE TT11LS

TT11LO=400000+TTPG0*2000	;BEGINNING OF PDP11 MEMORY IN PDP10 ADDRESS SPACE.
TT11HA==10+TT11LO	;PDP10 ADDR OF PDP11'S 40 (CHNL HDR AREA ADDR)
TT11UP==TT11HA+2	;PDP10 ADDR OF "11 UP" FLAG.
TT11DN==TT11UP+1	;PDP10 ADDR OF "11 ABOUT TO GO DOWN" FLAG.

$11==1,,777700		;DEFINE B.P.'S TO PDP11 FIELDS OF A PDP10 WORD.
$11WD0==242000		;LOW (EVEN) 11 WORD
$11WD1==042000		;HIGH (ODD) 11 WORD

$11AD0==261600		;LOW 11 WORD, SHIFTED DOWN 2 (FOR CONVERTING 11-ADDRESS TO 10 ADDRESS).
$11AD1==061600		;HIGH 11 WORD, SHIFTED DOWN 2

$11BY0==241000		;LOWEST 11 BYTE.  EACH 10-WORD HOLDS 4 11-BYTES.
$11BY1==341000		;NEXT 11 BYTE
$11BY2==041000		;THIRD BYTE
$11BY3==141000		;FOURTH BYTE

;FORMAT OF AN INPUT BUFFER: (ALL POINTERS ARE PDP11 ADDRS)
;PDP11 WORD #,	...	  MEANING.
;	0	...	0 => FREE, ELSE -<# DATA CHARS>.
;	1	...	ZERO, ALWAYS.
;	2	...	-> NEXT BUFFER FOR THIS TTY.
;	3	...	-> NEXT ACTIVE BUFFER.
;	4	...	KEYBOARD NUMBER (= <TTY #>-NF11TY)
;	5+	...	DATA CHARS, 1 PER PDP11 WORD.

;FORMAT OF AN OUTPUT BUFFER:
;STARTS AT A MULTIPLE-OF-FOUR PDP11 ADDRESS, HAS A BUNCH OF BYTES,
;TT11BY BITS PER BYTE (USED TO BE 16, NOW 8).  BYTES ARE IN PDP10 ORDER.
;AFTER THE PDP11 PICKS UP A BYTE OUT OF THE BUFFER, IT STORES BACK -1,
;WHICH TELLS THE 10 THAT IT IS OK TO STORE ANOTHER BYTE THERE.
];N11TYS

IFN DZ11P,[
;DZ11 STORAGE
;Temp metering locs
DZXINC:	0		;Count of DZ transmit interrupts
DZXCHC:	0		;Count of DZ transmit characters
;
DZDCRQ:	0		;Disconnect requests
DZCORQ: 0		;Connect requests.
IFG NDZTYS-36.,.ERR Too many DZ TTYS, fix code using DZDCRQ or DZCORQ
];DZ11P

LOCTTY:	0	;CONSOLE INPUT CHAR READ FROM
LTTYIPC:0	;TTYIPC USED IN LAST INPUT INT (DEBUGGING ONLY)
LTYBPC:	0	;TYBPC USED IN LAST INPUT INT (DEBUGGING ONLY)
LEPCHR:	0	;-1 IF CURRENT INPUT CHAR IS A LOCAL EDITING PROTOCOL COMMAND CHAR.

TTYA:	0
TTYACS:	BLOCK 17-B+1
IFN KA10P, TTYAPC:	0	;APR CONI AT TTYBRK.
TTYPDP:	-LTTYP,,TTYPDL-1
TTYPDL:	BLOCK LTTYP

IFN TTLPTP,[
LPTTTY:		TTLPTP	;TTY# THAT IS REALLY LPT
LPTTIME:	0	;LAST TIME SYSTEM GOT INPUT FROM LPT
]

STYMAX:	NCT	;Highest-numbered STY to be allocated (for limiting load)
STYOSW:	-1	;PSEUDO TTY OPEN SWITCH
	0

TTERQS:	MOVE	;LIST (THREADED THRU TTYERQ) OF TTYS NEEDING ECHOING.
		;"MOVE" (= 200000,,) IS THE END OF THE LIST.
		;OTHERWISE, A POINTER IS THE NUMBER OF A TTY
		;WHOSE TTYERQ VAR. HOLDS THE NEXT POINTER.

TTEDMY:	0	.SEE TYOPV0	;DUMMY VARIABLE BLOCK
	0	.SEE TYOPV1	;PASSED BY ECHO ROUTINE
	TTEDMY	.SEE TYOPV2	;TO .IOT RTNS.
	0	.SEE TYOPV3,TTELUP

NTTELU:	0	.SEE TTELUP	;ECHOING STATISTICS.
NTTEWA:	0	.SEE TTEWAT
NTTEL1:	0	.SEE TTELP1

STYNTO:	BLOCK NSTTYS	;NUMBER TIMES PSEUDO TTY OPEN
STYMSK:	REPEAT NSTTYS,0	;BIT FOR EACH CHNL STY OPEN FOR INPUT ON
STYOMS:	REPEAT NSTTYS,0	;OUTPUT
STYSTS:	REPEAT NSTTYS,0	;STY STATUS   0 => FREE SLOT
			;RH = USER INDEX THAT HAS IT OPEN
%SSHNG==400000		;4.9 = 1 => DON'T HANG ON INPUT IOTS
%SSUSE==200000		;4.8 = 1 => IN USE
%SSINT==100000		;4.7 = 1 => HAVE GIVEN INT ON STY OUTPUT CHNS ALREADY
%SSONT==040000		;4.6 = 1 => DITTO FOR STY INPUT (TTY OUTPUT)
%SSOHG==20000		;4.5 = 1 => DON'T HANG ON OUTPUT IOT
%SSORS==10000		;4.4 = 1 => THIS STY WANTS %TDORS WHEN A
			;TTY OUTPUT RESET IS DONE.
IFN NETP,[
%SSNET==4000		;4.3 = 1 => THIS STY CONNECTED TO SOME NET SOCKETS.
%SSCHA==2000		;4.2 = 0 FOR ARPANET, 1 FOR CHAOS NET
%SSTCP==1000		;4.1 = 1 for TCP internet (%SSCHA must be 0)

STYNTI:	REPEAT NSTTYS,-1; If %SSNET set, holds net connection identifier.
			;   NCP: Input IMSOC idx,,Output IMSOC idx
			;   CHA: connection index
			;   TCP: TCB (connection) index
			;   Otherwise -1
STYNTA:	0		;HEAD OF LIST OF DIRECT-CONNECTED STYS NEEDING DATA XFER.
			;0 IS NIL;  A TTY # POINTS TO A STY.
STYNTB:	0 .SEE STYNTC	;COPIED STYNTA LIST USED INSIDE STYNTC ONLY
STYNTL:	REPEAT NSTTYS,-1;STYNTA LIST THREADED THROUGH THIS TABLE.
			;+ NEXT TTY IN LIST, 0 END OF LIST, - NOT IN LIST
STYORC:	REPEAT NSTTYS,0	;OUTPUT-RESET CHARACTERS, 8-BIT BYTES TERMINATED BY 0
TYPNTF:	0		;-1 WHILE TYP BEING CALLED FROM STYNT0
NTORFU:	0		.SEE TYPOR3
] ;NETP

STYICH:	0		;TEMP STORAGE FOR PSEUDO-TTY INPUT CHAR

TCTYP:	TTYREP TCT	;THIS WORD SAYS HOW TO PERFORM
	;CURSOR CTL FUNCTIONS ON TTY.
%TNPRT==0	;PRINTING TTY.
%TNDP==1	;TTY USES DATAPOINT CURSOR CTL CODES.
%TNODP==2	;LOSING DATAPOINT (ML-KA HAS SOME).
%TNIML==3	;TTY USES IMLAC CURSOR CODES.
%TNTEK==4	;TEKTRONIX 4000 SERIES
%TNTV==5	;TTY IS A KNIGHT TV DISPLAY.
%TNMEM==6	;MEMOWRECK
%TNSFW==7	;"SOFTWARE" TTY THAT WANTS I.T.S. CURSOR-MOTION CODES.
%TNTRM==10	;TERMINET
%TNESC==11	;TTY WANTING STANDARD ASCII ESCAPE SEQUENCES
%TNDTM==12	;DATAMEDIA
%TNRAY==13	;TELERAY 1061
%TNHDS==14	;HDS CONCEPT-100
%TNH19==15	;H19/Z19
%TNAAA==16	;AAA
%TNMAX==17

;TTYOPT WORD DESCRIBES CHARACTERISTICS OF THE PARTICULAR
;TERMINAL ATTACHED TO EACH LINE.
TTYOPT:	TTYREP OPT

;LEFT HALF BITS ARE:
%TOALT==200000	;4.8 => STANDARDIZE ALTMODES.
%TOCLC==100000	;4.7 => CONVERT LOWER CASE TO UPPER.
%TOERS==40000	;4.6 => THIS TTY CAN SELECTIVELY ERASE.
%TOHDX==20000	;4.5 => THIS TTY IS HALF-DUPLEX.
$TOHDX==370100
%TOMVB==10000	;4.4 => THIS TTY CAN BACKSPACE.
%TOSAI==4000	;4.3 => THIS TTY HAS SAIL CHAR SET ON OUTPUT.
%TOSA1==2000	;4.2 INIT %TSSAI OF NEW JOBS.
%TOOVR==1000	;4.1 => THIS TTY CAN OVERPRINT SUCCESSFULLY.
%TOMVU==400	;3.9 => THIS TTY CAN MOVE CURSOR UP (IS A DISPLAY).
%TOMOR==200	;3.8 => DO **MORE** PROCESSING ON THIS TTY
		;(ACTUALLY JUST USED TO INIT %TSMOR FOR NEW JOBS).
%TOROL==100	;3.7 SIMILARLY, INIT %TSROL FOR NEW JOBS.
%TORAW==40	;3.6 => SUPPRESS CURSOR MOTION OPTIMIZATION.
%TOLWR==20	;3.5 => THIS TTY HAS LOWER CASE KEYBOARD.
%TOFCI==10	;3.4 => THIS TTY CAN INPUT 12-BIT CHARACTERS (HAS FULL KEYBOARD).
%TOIML==4	;3.3 => IMLAC, HANDLES CURSOR MOTION STRANGELY.
%TOLID==2	;3.2 => LINE INSERT AND DELETE WORK
%TOCID==1	;3.1 => CHARACTER INSERT AND DELETE WORK

;RIGHT HALF:
%TPPLF==100000
$TPPLF==170300	;3-BIT FIELD SAYING HOW TO PAD LF.
	;0 - DON'T. 1 - MEMOWRECK, 2741. 2 - TERMINET.
%TPPCR==10000
$TPPCR==140300	;3-BIT FIELD SAYING HOW TO PAD CR.
	;7 - UNUSED. 6 - MEMOWRECK. 5 - 2741. 4 - EXECUPORT.
	;0 - DON'T. 1 - NORMAL. 2 - DOUBLE.
	;ON DATAPOINTS, = # CHARS PADDING NEEDED FOR ALL CURSOR MOTION.
	;4 IS RIGHT FOR 2400 BAUD; 3, FOR 1200.
	;ON TERMINETS, 0 => NO PADDING, OTHER CODES ARE
	;1 FOR 10CPS, 2 FOR 15CPS, 3, 4, 5 FOR 30, 60, 120 CPS.
%TPPCW==6	;FOR MEMO WRECK.
%TPPTB==1000
$TPPTB==110300	;3 BIT FIELD SAYING HOW MUCH PADDING NEEDED AFTER TAB.
	;0 => TABS NOT ALLOWED; ELSE 1 +<# PADDING CHARS NEEDED>
%TPMTA==400	;1.9 => HARDWARE META KEY SETS 8TH BIT
%TPPRN==200	;1.8 => INTERCHANGE () WITH [] ON INPUT
%TPTEL==100	;1.7 => TREAT CRLF INPUT AS CR FOR TELNET PROTOCOL
%TPCBS==40	;1.6 => ENABLE SPECIAL TREATMENT OF 034 ("CONTROL BACK SLASH") ON INPUT.
		 ;(THE "INTELLIGENT TERMINAL PROTOCOL").
%TP11T==20	;1.5 => PDP-11 TV TTY. REFLECTS %TY11T.
		 ;NOT SETTABLE BY USER.
%TPORS==10	;1.4 => OUTPUT RESET ON THIS TTY SHOULD REALLY DO SOMETHING.
%TPRSC==4	;1.3 => THIS TTY SUPPORTS %TDRSU, %TDRSD

;SMARTS VARIABLE, %TQ IN LH, %TR IN RH, BIT DEFINITIONS IN BITS >
TTYSMT:	TTYREP SMT
.SEE %TQ
.SEE %TR

TTYST1:	REPEAT NCT,0	;FIRST SIX GROUPT (SIX BITS PER GROUP)
TTYST2:	REPEAT NCT,0	;SECOND SIX GROUPS (SIX BITS PER GROUP)
TTYSTS:	REPEAT NCT,%TSFRE,,-1	;MODE BITS FOR TTY

;GROUP NUMBER		   CHARACTERS
;[	0		^A-^F ^K-^L ^N-^R ^T-^Z ^] ^^ ^_ ^@ ^\
;	1		A-Z   LOWER CASE A-Z
;	2		0-9
;	3		!"#$(DOLLAR)%&',.:;?@\ (ACCENT GRAVE) (VERTICAL BAR) (TILDE)
;	4		*+-/=^_
;	5		<>[]() (LEFT BRACE) (RIGHT BRACE)
;	6		^G ^S (^S IS IN GROUP 0 AS FAR AS %TGIMG IS CONCERNED)
;	7		LF ^I(TAB)
;	10		(ALTMODE)
;	11		CR
;	12		RUBOUT
;	13		SPACE ^H(BACKSPACE)

;TTYST1 HAS GROUPS 0 THROUGH 5 FROM LEFT TO RIGHT
;TTYST2 HAS 6 THROUGH 13
;EACH GROUP HAS SIX BITS AS FOLLOWS:
%TGINT==1	;N.1 => INTERRUPT ON THIS GROUP
%TGACT==2	;N.2 => ACTIVATE ON THIS GROUP (FOR SWAPPING)
%TGSPC==4	;N.3 => SPECIAL HACKS. (THIS SET ON GROUP 1 => CONVERT LOWER CASE INPUT)
%TGIMG==10	;N.4 => IMAGE MODE OUTPUT (N.4=0  => ASCII MODE)
		;N.6-N.5 => ECHO MODE
		;	00 => NO ECHO
%TGPIE==20	;	01 => PI  ECHO (ECHO CHARACTER WHEN TYPED)
%TGMPE==40	;	10 => MAIN PROGRAM ECHO (ECHO WHEN MAIN PROGRAM RECEIVES CHARACTER)

;TTYSTS HAS RANDOM BITS ASSOCIATED WITH THE TELETYPE
%TSFRE==400000	;4.9 => TTY FREE
%TSCLE==200000	;4.8 => ECHO ^L AS UPARROW-L EVEN ON DISPLAYS
		;(OTHERWISE WOULD ECHO AS CLEAR SCREEN)
%TSHDX==100000	;4.7 REFLECTS %TOHDX BIT.
%TSFCO==040000	;4.6 => HANDLE 9-BIT CHARS ON OUTPUT, USING ALPHA, BETA.
%TSALT==020000	;4.5 => DON'T STANDARDIZE ALTMODE.
%TSROL==010000	;4.4 => SCROLL MODE.
%TSSAI==004000	;4.3 => ECHO AND ASCII MODE SHOULD USE SAIL CHAR SET.
%TSACT==002000	;4.2 => GOBBLE NEXT CHAR REGARDLESS OF ACTIVATION STATUS
%TSNEA==001000	;4.1 => DON'T ECHO IN THE ECHO AREA.  ECHO IN M.P. AREA.
%TSINT==000400	;3.9 => INT ON NEXT CHAR REGARDLESS
%TSMOR==000200	;3.8 => INHIBIT **MORE**.
%TSATY==000100	;3.7 SET BY .ATTY, SAYS TTY WAS TAKEN AWAY & RETURNED.
		;3.6-3.5 UNUSED.
%TSNOE==000010	;3.4 => DEFER ECHOING, AND MAKE INPUT IOT'S ACT AS IF %TIECH=1.
%TSLCZ==000004	;3.3 => LAST CHARACTER TYPED WAS ^Z (NOT PRECEEDED BY ^_)
%TSSII==000002	;3.2 => SUPER IMAGE INPUT MODE
%TSCNS==000001	;3.1 => CONSOLE
$TSCNS==220100
		;RH => USER INDEX
		;	-1 => NO USER

TTYSTA:	REPEAT NCT,%TACFM,,	;NOT SAVED AT ATTY
%TACFM==400000	;4.9 = 0 => NEEDS TO HAVE CONSOLE FREE MSG EVENTUALLY TYPED
		;	CLEARED BY OPEN OR ZFLAG WHEN INITIALIZING CONSOLE PROCEDURE
		;	SET BY SYS JOB AFTER TYPING CONSOLE FREE MSG
		;WHEN THIS BIT IS 0, TTY ISN'T AVAILABLE FOR BEING GOBBLED DOWN
		;FOR ANY NEW USE.
%TACTZ==200000	;4.8 ON => TTY IS FREE AND BEING ^Z'D, SO EVEN THOUGH IT APPEARS
		;OTHERWISE TO NEED A CONSOLE-FREE MESSAGE IT SHOULDN'T GET ONE.
%TANJS==100000	;4.7 ON => TTY IS BEING ^Z'D, BUT THERE ARE NO JOB SLOTS.
		;4.8 WILL BE ON AND 4.9 OFF. SYS JOB WILL RESTORE ALL TO NORMAL
		;AFTER TYPING "SYSTEM FULL" ON THE TTY.
%TANEC==070000	;4.6-4.3 NUMBER OF FOLLOWING CHARS TO INHIBIT ECHO AND INTS FOR.
		;THIS IS USED FOR THE ARG CHARS THAT FOLLOW TOP-E, TOP-S, TOP-Y, ETC.

TTYCOM:	REPEAT NCT,0,,-1	;COMMUNICATE WORD
;4.9 => TTY IN COMMUNICATE MODE
%TCLFT==200000	;4.8 => LOCAL FEED THROUGH (SET IF MY PRGM RECIEVING HIS CHRS)
%TCRFT==100000	;4.7 => REMOTE FEED THROUGH (SET IF HIS PRGM RECIEVING MY CHRS)
%TCICO==40000	;4.6 => INPUT COMMUNICATE OVERRIDE (SET IF MY CONSOLE FEEDING MY
		; PRGM EVEN THO IN COMM MODE).  ALSO IMPLIES OUTPUT OVER-RIDE.
%TCOCO==20000	;4.5 => OUTPUT COMMUNICATE OVERRIDE (SET IF MY PRGM'S OUTPUT TO APPEAR ON MY CONSOLE ONLY EVEN THO IN COM MODE)
;4.4-4.3 => MESSAGE RECEIPT SWITCH
		;00 => ACCEPT
%TCRFS==10000	;10 => REFUSE
%TCQRY==4000	;01 => INTERROGATE
%TCMTR==2000	;4.2  SET FOR TTY WHOSE MOTOR IS OFF & MUST BE TURNED
;ON BEFORE ANY OTHER OUTPUT IS DONE.
;(ONLY TERMINETS HAVE THEIR MOTORS SHUT OFF BY ITS).
%TCECH==1000	;4.1 THE OUTPUT BUFFER CONTAINS ECHOING OUTPUT.
		;THIS MAKES OUTPUT RESET DO NOTHING.
		;THE BUFFER MUST NOT CONTAIN ECHO OUTPUT AND NORMAL OUTPUT AT ONE TIME.
%TCDET==200	;3.8 CONSOLE'S TREE DETACHED BY TOP LEVEL INTERRUPT.
	;SET BY NDETAC AS SIGNAL TO SYSCFM (CNSL-FREE-MSG TYPER)
%TCDNG==100	;3.7 => TYPE BELL ON TTY (BECAUSE INPUT BFR FULL).
%TCCBK==40	;3.6 => READING UNAME OR TTY # AFTER ^_K.
%TCCBS==20	;3.5 => READING UNAME OR TTY # AFTER ^_S.
%TCFPD==10	;3.4 => FIRST PART DONE (USED FOR %TNESC ESCAPE SEQUENCES, %TNODP CR)
%TCTPN==4	;3.3 TYPE ^_N ON LEAVING COM MODE (UNLESS USER EXPLICITLY TYPES ^_N)
%TCPAD==2	;3.2  0 => PADDING NECESSARY ON DATAPOINT.
%TCHNG==1	;3.1 TTY'S DONE FLAG APPEARS TO BE FRIED, TIME OUT QUICKLY
;RH => USER INDEX COMMUNICATING WITH (-1 NONE)


;TTYTYP TABLE
;THIS TABLE HOLDS BITS THAT DESCRIBE THE LINE
;AND ITS CONTROLLER, RATHER THAN THE TTY ATTACHED TO THE LINE.

%TTLCL==400000	;BIT 4.9 ONE => LOCAL TTY
%TT340==200000	;BIT 4.8 ONE => CONSOLE NEXT TO 340 OR A 340 SLAVE
%TT3HP==100000	;BIT 4.7 HIGH PRIORITY ON 340
%TTPAR==004000	;BIT 4.3 THIS TTY NEEDS PARITY BIT SENT.
%TTDDI==002000	;BIT 4.2 DONT DING ON EXCESS INPUT
$TTISP==260400	;3.8-3.5 INPUT SPEED CODE
$TTOSP==220400	;3.4-3.1 OUTPUT SPEED CODE

%TYDPK==400000	;BIT 2.9 DATAPOINT KLUDGE TERMINAL
%TYSTY==200000	;BIT 2.8 PSEUDO TTY
%TYNVA==100000	;BIT 2.7 NOVA TTY
%TYMTY==040000	;BIT 2.6 MORTON BOX
%TYDIL==020000	;BIT 2.5 DIAL UP
%TY11T==010000	;BIT 2.4 PDP-11 TV TTY.
%TYDL== 004000	;BIT 2.3 DL10 TTY
%TYOTY==002000	;BIT 2.2 ORDINARY KA-10 CONSOLE TTY
%TYETY==001000	;BIT 2.1 DTE-20 TTY (KL-10 CONSOLE)
%TYNTY==000400	;BIT 1.9 TK-10 TTY.
%TYMDM==000200	;BIT 1.8 LINE HAS MODEM CONTROL, DETECTS DIALINS AND HANGUPS
%TYKST==000100	;BIT 1.7 KS-10 CONSOLE TTY
%TYDZT==000040	;BIT 1.6 DZ-11 TTY ON KS-10
%TYRLM==000020	;BIT 1.5 ROLM DATA SWITCH

TTYTYP:	TTYREP TYP	;PART OF TTYTYP MAY BE WRITEABLE.
BBLK
	0	;DISOWNED JOBS CANT HAVE LPT
	%TTLCL,,;SYSTEM JOB CAN GET LPT

.CRFOFF
IRPS X,,TYP OPT HOR VER TCT ROL SMT
REPEAT NCT,[
CONC EXPUNG T,\.RPCNT,$!X
]
TERMIN
.CRFON

OVHMTR UUO	;YET MORE RANDOM UUOS
