Google
 

Trailing-Edge - PDP-10 Archives - bb-bt99m-bb - scnser.x19
There are no other files named scnser.x19 in the archive.
TITLE	SCNSER - TERMINAL SCANNER SERVICE  V1017
SUBTTL	R CLEMENTS/RCC/DAL/PMW/EJW/WRS/RCB	30 JUL 86
	SEARCH	F,S
IFN FTNET,<SEARCH NETPRM>
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1973,1986>
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;ALL RIGHTS RESERVED.


;
;
XP VSCNSR,1017
ENTRY SCNSER
SCNSER::
;               TABLE OF CONTENTS FOR SCNSER
;
;
;                        SECTION                                   PAGE
;    1. PARAMETER AND CONFIG DEFINITIONS..........................   3
;    2. DATA STRUCTURES
;         2.1   LINTAB AND DSCTAB.................................   5
;         2.2   LINE DATA BLOCK (LDB).............................   6
;         2.3   TTY DEVICE DATA BLOCK (DDB).......................  19
;    3. TRANSMIT INTERRUPT ROUTINE................................  20
;    4. RECEIVE INTERRUPT ROUTINE.................................  36
;    5. KI10 CONSOLE TERMINAL SERVICE.............................  70
;    6. KS10 CTY AND KLINIK TERMINAL SERVICE......................  71
;    7. FILLERS AND SIMULATION ROUTINES...........................  72
;    8. FILL CHARACTER DATA.......................................  81
;    9. TIMING ROUTINE............................................  84
;   10. CHUNK HANDLERS............................................  97
;   11. CHUNK HANDLERS
;        11.1   ALLOCATION AND DEALLOCATION....................... 100
;        11.2   CLEAR BUFFERS..................................... 102
;   12. UUO LEVEL ROUTINES FOR BUFFERED I/O....................... 103
;   13. DDT MODE CALLI'S.......................................... 110
;   14. TTCALL AND TRMOP.
;        14.1   TTCALL DISPATCH................................... 111
;        14.2   OUTCHR AND IMAGE OUTCHR........................... 113
;        14.3   OUTSTR AND RESCAN................................. 114
;        14.4   SKPINL AND SKPINC................................. 115
;        14.5   GETLIN............................................ 116
;        14.6   SETLIN, INCHSL, INCHWL, INCHRS & INCHRW........... 117
;        14.7   TRMNO. UUO........................................ 118
;        14.8   TRMOP. DISPATCH................................... 119
;        14.9   SKIPS AND CLEARS.................................. 131
;        14.10  TRMOP. I/O........................................ 132
;        14.11  TRMOP. I/O SUBROUTINES............................ 134
;        14.12  TRMOP. DATASET FUNCTIONS.......................... 135
;        14.13  TYPE INTO TTY ON BEHALF OF A USER................. 139
;        14.14  MIC  --  SET/CLEAR LDBMIC......................... 140
;        14.15  MIC  --  RETURN MIC STATUS........................ 141
;        14.16  MIC  --  READ ERROR RESPONSE TEXT................. 142
;        14.17  MIC  --  LOG ALL TERMINAL OUTPUT.................. 143
;        14.18  MIC  --  MISCELLANEOUS MIC SUBROUTINES............ 144
;   15. SUBROUTINES FOR I/O....................................... 148
;   16. COMMAND LEVEL ROUTINES.................................... 156
;   17. SUBROUTINES FOR COMCON OR UUO LEVEL....................... 171
;   18. CTY ROUTINES.............................................. 175
;   19. DDB ROUTINES.............................................. 178
;   20. ROUTINES FOR PTY.......................................... 194
;   21. IMPURE DATA............................................... 200
	SUBTTL	PARAMETER AND CONFIG DEFINITIONS

XP STTYBF,20

;DATASET TRANSACTION CODES FROM SCNSER TO/FROM XXXINT'S

XP DSTOFF,1		;DSCREC OR DSCTYP
XP DSTON,2		;DSCREC OR DSCTYP
XP DSTRNG,3		;DSCREC
XP DSTREQ,3		;DSCTYP
XP DSTINI,4		;TO AND FROM. SENDING COMPUTER WAS RESTARTED.
XP DSTSTS,5		;REQUEST DATA SET STATUS
XP DSTCRQ,10		;CALL REQUEST TO MODEM. WANT TO DIAL OUT.
XP DSTPND,20		;PRESENT NEXT DIGIT, TO AND FROM.
; NOTE - TO MODEM, 20-37 MEAN SEND DIGIT N-20
; WHERE DIGIT 17 MEANS END OF NUMBER (TO BOTH HARDWARE AND SOFTWARE)
; AND DIGIT 16 MEANS 5-SECOND DELAY TO SOFTWARE, FOR SECOND DIAL TONE.
XP DSTNAC,40		;NO ACTION -SYSINI (ONLY USER OF DSTREQ) SHOULD
			; NOT MODIFY LINE STATUS CODES (CARRIER ON/OFF)

;LINE CONTROL TRANSACTION CODES

XP LNTEHC,1	;ENABLE HUNG CHECK
XP LNTDHC,2	;DISABLE HUNG CHECK
ND	STDALT,033		;VALUE OF STANDARD ALTMODE
ND	VTAB,10			;VERTICAL TAB SPACING (MUST BE POWER OF 2)
ND	RCQMAX,^D32		;RECINT QUEUE SIZE

IFNDEF FTMLOG,<XP FTMLOG,-1>	;NON-ZERO TO INCLUDE MIC LOG CODE

;SIZE OF CHUNKS

XP IMGTIM,^D10			;MUST FIT IN LDPTIM FIELD. HUNG TIME FOR IMI


;HARDWARE PARAMETERS OTHER THAN THOSE IN THE XXXINT ROUTINES

CTY=120		;HARDWARE DEVICE NUMBER OF THE KA10 CONSOLE TERMINAL
	SUBTTL	DATA STRUCTURES -- LINTAB AND DSCTAB


;DATA STRUCTURES IN COMMON

;LINTAB:	BLOCK # OF LINES INCLUDING SCANNER,CTY AND PTY'S
;EACH WORD=	FULLWORD LDB ADDRESS

;DSCTAB:	BLOCK # OF DATASETS NEEDING TIMING
;		RH= LINKED TERMINAL LINE NUMBER FOR DATA
;		LH= TIME IN 14-17, ALSO DSCHWC,DSCSWC,DSCFAI

XP DSCHWC,400000	;WHEN LAST HEARD FROM, THE HARDWARE CARRIER WAS ON
XP DSCSWC,200000	;THE SOFTWARE CONSIDERS THE CARRIER TO BE ON OR
			; TO BE COMING ON IMMINENTLY
XP DSCFAI,100000	;CARRIER WENT OFF, BUT MAY BE BRIEF FAILURE
			; EXCEPT FOR GPO 2B MODEM, MUST QUIT IMMEDIATELY
XP DSCNCR,040000	;NEW CARRIER FLAG, ON FOR FRACTION OF SECOND FOR CLOCK SYNC
XP DSCBLI,020000	;BLIND FLAG - IGNORE EVERYTHING FOR 1 SEC AFTER CARRIER ON
XP DSCDLW,010000	;DIALLER WAIT. WAITING FOR RESULTS FROM DIALLER
XP DSCDLF,004000	;DIALLER FAIL. UNSUCCESSFUL DIALLER ATTEMPT
XP DSCDLC,002000	;DIALLER COMPLETE. SUCCESSFUL DIALLER ACTION.
XP DSCEON,001000	;END OF NUMBER. SENT ALL DIGITS TO DIALLER.
XP DSCTMM,777		;TIME MASK. MUST AGREE WITH DSTIMP POINTER.

;DEFINITIONS FOR INITIALIZATION ROUTINE IN SYSINI

XP DSCICL,DSCHWC!DSCSWC!DSCFAI!DSCDLW!DSCDLF!DSCDLC!DSCEON!DSCTMM
XP DSCIC1,DSCHWC!DSCSWC
XP DSCIC2,DSCTMM!DSCFAI!DSCDLW!DSCDLF!DSCDLC!DSCEON

	SUBTTL	DATA STRUCTURES -- LINE DATA BLOCK (LDB)

;PROTOTYPE LINE DATA BLOCK FOR A TTY (OR PTY) LINE

SCNLDB::
PHASE 0

LDBDDB::!XWD	ZERO5,0	;ADDRESS OF LINE'S ATTACHED DDB, IF ANY
LDBCOM::!0		;BITS WHICH USED TO BE IN LH OF LDBDDB
XP LDBCMR,400000	;SIGN BIT OF LDBCOM IS COMMAND REQUEST BIT
			; MUST BE IN WORD ZERO, FOR @U, 13-17 MUST BE ZERO
XP LDBCMF,200000	;COMMAND FORCED. MEANS TYI ATE A CONTROL C
			; WHICH WAS DESTINED FOR COMCON, OR SOME OTHER COMMAND
			; IS TO BE FORCED, VIA LDPCMX. MUST BE IN SAME
			; WORD AS LDBCMR
XP LDBCMK,100000	;FORCING KJOB COMMAND
XP LDBDET,40000		;JOB DETACHED FROM THIS LINE DURING COMMAND
			;PROCESSING.  FORCE CLEANUP OF JOB/COMMAND
			;AT NEXT TICK.
XP LDBFDX,20000		;PROCESSING A FILDAE EXIT MESSAGE. LEAVE LDBCMF ALONE.
			;BITS 9-12 ARE INDEX FOR FORCED COMMAND,
			; POINTER = LDPCMX

LDICLR::!		;ON RESTART, START CLEARING HERE
LDBATR::!0		;TERMINAL ATTRIBUTES
LAL8BT==:400000		;EIGHT-BIT TERMINAL.  MUST BE SIGN BIT.  TERMINAL
			; CAN ACCEPT AND GENERATE ASCII CODES 200-377.
LALCOS==200000		;CAN OVERSTRIKE.  USED WHEN LAL8BT OFF TO GENERATE
			; 7-BIT EQUIVALENTS FOR 8-BIT CHARACTERS.
LALDIS==:100000		;TERMINAL IS A DISPLAY.  AT A MINIMUM, THIS IMPLIES
			; THAT BACKSPACE GOES BACKWARD ON THE SCREEN, AND
			; THERE IS A WAY TO HOME AND CLEAR THE SCREEN.
			; (FORMERLY LPLDIS)
LDBOST::!0		;OUTPUT SPECIAL STATES BIT TABLE
			;BITS ARE DEFINED AT XMTDSP
LDBIST::!0		;INPUT STATE WORD
			;LH STORES THE CHARACTER BEING DEFERRED,
			;RH STORES THE REASON FOR DEFERRING IT:
	LISDCI==1	;DEFERRED CLEAR INTERRUPT
	LISQOT==2	;QUOTING A CHARACTER
	LISSWI==3	;EVALUATING A POSSIBLE SWITCH SEQUENCE
LDBBKU:!0		;COPY OF LDBECT AT LAST BREAK XMTECH
LDBBKI:!0		;COPY OF LDBTIP AT LAST BREAK RECINT
LDBTIP::!0		;T2 TO PUT CHARACTERS IN INPUT BUFFER
LDBTIT::!0		;T2 TO TAKE CHARACTERS FROM INPUT BUFFER
LDBTIC::!0		;COUNT OF ECHOED CHARACTERS IN INPUT BUFFER
LDBBKC::!0		;COUNT OF BREAK CHARACTERS IN INPUT BUFFER
LDBTOP::!0		;T3 TO PUT CHARACTERS IN OUTPUT BUFFER
LDBTOT::!0		;T2 TO TAKE CHARACTERS FROM OUTPUT BUFFER
LDBTOC::!0		;COUNT OF CHARACTERS IN OUTPUT BUFFER
LDBECT::!0		;T2 TO TAKE CHARACTERS FROM INPUT FOR ECHOING
LDBECC::!0		;COUNT OF CHARACTERS TO ECHO
LDBIEC::!0		;INVISIBLE (NOT-IN-STREAM) CHARACTERS YET TO BE ECHOED
LDBIIC::!0		;INVISIBLE (NOT-IN-STREAM) CHARACTERS ECHOED AND PENDING
LDBEOP::!0		;T3 TO PUT CHARACTERS IN ECHO OUTPUT BUFFER
LDBEOT::!0		;T2 TO TAKE CHARACTERS FROM ECHO OUTPUT BUFFER
LDBEOC::!0		;COUNT OF ECHO STREAM CHARACTERS TO OUTPUT
IFN FTPI,<
LDBOOP::!0		;BYTE POINTER TO ENQUEUE OUT-OF-BAND CHARACTERS
LDBOOT::!0		;B.P. TO DEQUEUE OUT-OF-BAND CHARACTERS
LDBOOC::!0		;COUNT OF ENQUEUED OUT-OF-BAND CHARACTERS
>
LDBCLP::!0		;COMMAND LINE POINTER (FOR COMCON)
LDBXNP::!0		;XON CLASS CHARACTER POINTER FOR OUTPUT
IFN FTXMON,<
	 0		;TWO WORD GLOBAL BYTE POINTER
>
LDBFLP::!0		;FILLER CHARACTER POINTER FOR OUTPUT
IFN FTXMON,<
	 0		;TWO WORD GLOBAL BYTE POINTER
>
LDBNNP:!0		;FILLER POINTER FOR 'NOT NOW' TEXT (BUSY/GOAWAY)
IFN FTXMON,<
	0		;TWO WORD GLOBAL BYTE POINTER
>
LDBPBK::!0		;WORD OF UP TO 4 BREAK CHARACTERS (8 BIT)
			;FOR PACKED IMAGE MODE (PIM); SET WITH TRMOP 2037
LDBHPS::!0		;HORIZONTAL POSITION COUNTER.  COUNTS UP FROM
			;MINUS CARRIAGE WIDTH TO ZERO.
LDBBCT::!0		;TOTAL COMMAND,,BREAK CHARACTER COUNT
LDBICT:!0		;TOTAL INPUT CHARACTER COUNT
LDBOCT:!0		;TOTAL OUTPUT CHARACTER COUNT
LDICLE==:.-1		;ON RESTART, CLEAR THRU HERE
;MORE OF THE PROTOTYPE LINE DATA BLOCK
LDBDCH::!0		;DEVICE CHARACTERISTICS BITS

;BITS IN LH OF LDBDCH (CARRIED IN LH OF U DURING INTERRUPT ROUTINE)
LDLIDL==:400000		;LINE IS IDLE.  IF CLEAR, WE ARE EXPECTING
			;A TRANSMIT INTERRUPT
			; MUST BE SIGN BIT.
LDLPPS==:200000		;PROMPT POSITION SET THIS LINE
LDLCRP==100000		;CONTROL-R PENDING (FOR XMTECH SYNCH PLUG)
LDLDIP==040000		;DELETE IN PROGRESS IN XMTECH (BLOCK TYICC4)
LDLCNE==:020000		;COMMAND-LEVEL NO ECHO
LDL8BI==:010000		;8-BIT INPUT MODE, DUE TO PROGRAM
LDLDLR==004000		;SUPPRESS DOLLAR SIGN ON ALTMODES.
LDLNEC==:002000		;NO ECHO, DUE TO PROGRAM
LDLFCS==:001000		;LINE INITED IN FULL CHAR SET MODE
LDLIMI==:000400		;IMAGE INPUT (KEEP NULLS)
XP LDLCOM,000200	;LINE IS AT COMMAND LEVEL
LDLBKA==:000100		;BREAK ON ALL CHARACTERS (DDTIN, TTCALL)

;*** BEGINNING OF GROUP OF BITS POINTED TO BY LDPVR1 ***
;*** BEGINNING OF 4 BITS POINTED TO BY GETLP1 FOR GETLIN ****
XP LDLSLV,000040	;SLAVE. THIS TERMINAL MAY BE ASSIGNED.
XP LDLLCT,000020	;LOWER CASE TRANSLATE TO UPPER
XP LDLTAB,000010	;LINE ACCEPTS TABS, NOT SPACES.
XP LDLLCP,000004	;LOCAL COPY (NO ECHO)
;*** END OF BITS POINTED TO BY GETLP1 ***
XP LDLFRM,000002	;LINE ACCEPTS FF AND VT (ELSE USE LF'S)
XP LDLNFC,000001	;NO FREE CARRIAGE RETURN AT 72 COLUMNS
;*** END OF GROUP FOR LDPVR1 ***
XP LDLECH,LDLNEC!LDLBKA!LDLLCP

;BITS TO BE CLEARED ON A 140 RESTART
ZZL==LDLIDL+LDLIMI+LDLNEC+LDLDLR+LDLBKA+LDLFCS+LDLCRP+LDL8BI+LDLDIP+LDLCNE
XP LDLIIF,LDLIMI+LDLFCS		;IMAGE INPUT OR FULL CHAR SET MODE
;RH OF LDBDCH - BITS 27-35 = LINE NUMBER, POINTER = LDPLNO

LDRPTY==:400000		;PSEUDO-TERMINAL
LDRCTY==:200000		;CONSOLE TERMINAL
;*** START OF GROUP OF BITS POINTED TO BY LDPVR2 ***
LDROSU==:100000		;OUTPUT SUPPRESS (^O)
LDRDSD==:040000		;DATASET DATA LINE
LDR274==:020000		;LINE IS A 2741
LDRHLF==010000		;HALF DUPLEX LINE (TWX OR DC10C)
LDRRMT==:004000		;REMOTE NON-DATASET LINE
XP LDRDSR,LDRDSD+LDRRMT	;REMOTE OR DATA SET LINE (FOR PATCH)
			; SO CAN'T ATTACH TO PROJECT 1 #
;*** END OF GROUP FOR LDPVR2 ***
;	002000		;FREE
LDRSHC==:001000		;SUPPRESS HUNG CHECK -I.E. DON'T FORCE CHAR'S OUT
			;  WHEN NO XMIT FLAG.--SET BY 680 FOR SPECIAL
			;  DEVICES (E.G. 2741) & ITS OPR. TERMINAL

;BITS TO BE CLEARED ON A 400 RESTART
ZZR==LDRPTY+LDRCTY+LDRSHC+LDROSU

;DEFINITIONS OF BITS FOR GETLIN UUO, CLOSELY ASSOCIATED WITH ABOVE

GTLRDY==100		;BIT FOR GETLIN TO INDICATE WAITING BREAK CHAR
GTLT37==20		;MODEL 37 BIT (COPY OF LDLLCT)
GTLT35==10		;MODEL 35 BIT (COPY OF LDLTAB)
GTLLCP==4		;LOCAL COPY (OLD FULTWX) (COPY OF LDLLCP)
GTLXON==2		;XON IS TRUE (COPY OF L2RXON)
GTLMSK==LDR274!777	;BITS TO CLEAR ON GETLIN
LGLSET==GTLT37+GTLT35+GTLLCP+GTLXON	;MAY BE SET BY SETLIN


;BITS THAT ARE TESTED ON A CALL TO XMTCHR TO SEPARATE OUT
;THE NORMAL CASE FROM THE SPECIAL CASES.

DCHSPC==LDLIDL,,LDRHLF
;MORE OF THE PROTOTYPE LINE DATA BLOCK

LDBOFL::!
LDBBYT::!0		;A WORD OF BYTES FOR THIS LINE

;BITS	POINTER	USE
;35-28	LDPECK	ECHO CHECK FOR HALF DUPLEX LINES
;27	L1RDEM	DEFERRED ECHO BIT.  SET BY SET TERMINAL DEFER
;26	L1RDEC	ECHO MAY ECHO 1 CHARACTER IF DEFERRED
;25	L1RDEL	ECHO MAY ECHO 1 LINE IF DEFERRED
;24-22	LDPCPU	CPU NUMBER--
;21	L1RCHP	CHANGE HARDWARE PARAMETERS FLAG (MEANINGUL EVEN FOR PTYS!)
;20	L1RMIF	MIC INTERLOCK FLAG
;19-15	LDPTIM	TIMEOUT ON IMAGE INPUT
;14	L1LDEM	DEFERRED ECHO BIT FOR XMTECH.  SET/CLEARED BY XMTECH
;13	L1LQOT	TTY QUOTE ENABLED
;12	L1LQTC	QUOTE NEXT CHARACTER IN XMTECH
;11	L1LQNC	QUOTE NEXT CHARACTER IN TYICC4
;10	L1LQCC	QUOTE NEXT CHARACTER IN CCTYI
;09	L1LUNR	UNREAD IN PROGRESS
;08-06		FREE
;05-03	POHPOS	OLD HORIZONTAL POSITION. NEEDED FOR TAB SIMULATION
;02-01	LDPFLC	COUNT OF NUMBER OF FILLERS BY CLASS
;0		1 IF FRONT END FOR THIS LINE IS DOWN.
;		 USE LDBOFL AS THE SYMBOL TO SKIPGE/SKIPL ON.
L1LOFL==:400000		;THE OFF-LINE BIT
L1RDEM==:1B27		;DEFERRED ECHO MODE
L1RDEC==:1B26		;MAY ECHO ONE CHARACTER (DEFERRED ECHO ONLY)
L1RDEL==:1B25		;MAY ECHO ONE LINE (DEFERRED ECHO ONLY)
L1RCHP==:1B21		;CHANGE HDW PARMS
L1RMIF==:1B20		;MIC INTERLOCK FLAG
L1LDEM==(1B14)		;XMTECH'S DEFERRED ECHO FLAG
L1LQOT==:(1B13)		;TTY QUOTE ENABLED FLAG
L1LQTC==(1B12)		;QUOTE FLAG FOR XMTECH
L1LQNC==(1B11)		;QUOTE FLAG FOR TYICC4
L1LQCC==(1B10)		;QUOTE FLAG FOR CCTYI
L1LUNR==:(1B9)		;UNREAD IN PROGRESS
LDIBCM==477777,,600000+L1RDEM+L1RDEC+L1RDEL+L1RCHP+L1RMIF+377 ;MASK TO CLEAR
			;LDBBYT AT TTYINI. ALL ARE CLEARED EXCEPT LDPFLC
;ANOTHER BYTE WORD, FLAGS AT LEFT.
LDBBY2::!0
;BITS	POINTER	USE
;32-35		FREE
;28-31	LDPAPC	ASYNCHRONOUS PORT CHARACTERISTIC
;20-27	LDPWID	WIDTH OF TERMINAL CARRIAGE
;18-19	BITS - SEE BELOW
;9-17	LDPDSC	DATASET CONTROL TABLE INDEX BACK POINTER
;0-8	BITS - SEE BELOW

L2LDEL==:400000		;LAST CHAR IN WAS A DELETE (MUST BE SIGN BIT)
L2LCCS==200000		;LAST CHAR IN WAS A ^C
L2LHD1==100000		;XMT DONE FLAG SEEN THIS CHAR ON HDX LINE
L2LHD2==040000		;RCV DONE FLAG SEEN THIS CHAR ON HDX LINE
L2LHD3==020000		;IGNORING RCV INTS DUE TO ECHO CHECK ERR ON HDX LINE
L2LHD4==010000		;NEXT RCV INT WILL BE CUE AFTER ECHO CHK
L2LHD5==004000		;RECEIVE ECHO WAS IN FACT NOT SAME AS XMT CHAR
L2LSND==:002000		;SEND ALLOWED WHILE BUSY
L2LTAP==:001000		;^Q FROM KEYBOARD TURNS ON L2RXON. SET BY .TERMINAL TAPE COMMAND

L2LHDM==L2LHD1!L2LHD2!L2LHD3!L2LHD4!L2LHD5

L2LCLR==L2LDEL!L2LCCS!L2LHDM!L2LSND!L2LTAP
			;CLEARED ON INITIALIZATION

L2RXON==:400000		;XON IS TRUE (PAPER TAPE INPUT)
L2RECS==200000		;EAT COMMAND SYNC, FOR TTCALL 10
L2RWID==177400		;FIELD FOR CARRIAGE WIDTH
L2RAPC==000360		;FIELD FOR ASYNCHRONOUS PORT CHARACTERISTIC
;FREE== 000017		;FREE BITS
;ANOTHER BYTE WORD, FLAGS AT LEFT.
LDBBY3::!0
;BITS	POINTER	USE
;27-35	LDPTMR	COUNT-UP TIMER FOR AUTO-DISCONNECT
;27	L3RTMO	OVERFLOW FOR ABOVE (AUTO-DISCONNECT TIMER EXPIRED)
;19-26	LDPMXT	MAXIMUM IDLE TIME FOR AUTO-DISCONNECT LOGIC
;10	L3LCHD	COMMAND HALF-DONE (TWO-PART CHARACTER TO BE COMPLETED)
;9	L3LIHD	INPUT HALF-DONE (TWO-PART CHARACTER TO BE COMPLETED)
;8	L3LEHD	ECHO HALF-DONE (TWO-PART CHARACTER TO BE COMPLETED)
;7	L3LOHD	OUTPUT HALF-DONE (TWO-PART CHARACTER TO BE COMPLETED)
;6	L3LFHD	FILL HALF-DONE (TWO-PART CHARACTER TO BE COMPLETED)
;5	L3LCPD	COMMAND PART-DONE (THREE-PART CHARACTER TO BE COMPLETED)
;4	L3LIPD	INPUT PART-DONE (THREE-PART CHARACTER TO BE COMPLETED)
;3	L3LEPD	ECHO PART-DONE (THREE-PART CHARACTER TO BE COMPLETED)
;2	L3LOPD	OUTPUT PART-DONE (THREE-PART CHARACTER TO BE COMPLETED)
;1	L3LFPD	FILL PART-DONE (THREE-PART CHARACTER TO BE COMPLETED)
;0	L3LDMC	DEFERRED ECHO MODE CHANGED (MUST BE SIGN BIT)

L3RTMO==1B27		;AUTO-DISCONNECT LOGIC TIMEOUT FLAG

L3LCHD==(1B10)		;COMMAND HALF-DONE (TWO-PART CHARACTER)
L3LIHD==(1B9)		;INPUT HALF-DONE (TWO-PART CHARACTER)
L3LEHD==(1B8)		;ECHO HALF-DONE (TWO-PART CHARACTER)
L3LOHD==(1B7)		;OUTPUT HALF-DONE (TWO-PART CHARACTER)
L3LFHD==(1B6)		;FILL HALF-DONE (TWO-PART CHARACTER)
L3LCPD==(1B5)		;COMMAND PART DONE (THREE-PART CHARACTER)
L3LIPD==(1B4)		;INPUT PART-DONE (THREE-PART CHARACTER)
L3LEPD==(1B3)		;ECHO PART-DONE (THREE-PART CHARACTER)
L3LOPD==(1B2)		;OUTPUT PART-DONE (THREE-PART CHARACTER)
L3LFPD==(1B1)		;FILL PART-DONE (THREE-PART CHARACTER)
TPCLSH==5		;OFFSET FROM TWO-PART TO THREE-PART BITS
L3LDMC==:(1B0)		;DEFERRED ECHO MODE HAS CHANGED (FLAG FOR RECINT)
;LENGTH AND STOP SIZE AND COUNTERS

LDBLSW::!0

;BITS	POINTER	USE
;00-08	LDPLNB	PAGE (OR "FORMS") LENGTH (BASE VALUE)
;09-17	LDPSTB	STOP (AFTER N LINES) SIZE (BASE VALUE)
;18-26	LDPLNC	PAGE (OR "FORMS") COUNTER (COUNTED UP TO 0)
;27-35	LDPSTC	STOP (AFTER N LINES) COUNTER (COUNTED UP TO 0)
;
;		ABOVE ARE 8-BIT FIELDS WITH ONE-BIT OVERFLOW.
;		LDPLNC AND LDPSTC MUST BE IN RIGHT HALF WORD!
LPRLC0== 400000		;LENGTH COUNTER OVERFLOWED
LPRSC0== 000400		;STOP COUNTER OVERFLOWED



;PAGE COUNTER WORD AND PAGE FLAGS

LDBPAG::!0

;BITS	POINTER USE
;3	LDPALT	ALTMODE CONVERSION (SET TERMINAL ALT)
;16-17		FREE
;18-26	LDPPFF	#LF'S REMAINING ON F.F. SIMULATION
;27-35	LDPACR	AUTO CRLF COUNTER

LPLIRM== 400000		;LOST TRANSMIT INTERRUPT BIT
LPLXNF==:200000		;PROCESS XON/XOFF
LPLXOF== 100000		;SENT XOFF, ALWAYS SEND AN XON LATER
LPLALT==:040000		;ALTMODE CONV. (1:CONVERT 175,176 TO 033)
LPLBLK==:020000		;SUPPRESS BLANK LINES
LPLSLF== 010000		;SUPPRESS LINE FEEDS
;(FREE)==004000		;FREE BIT
;(FREE)==002000		;FREE BIT
LPLPOK== 001000		;WE ARE FORCING XMIT START VIA TOPOKE (PREVENT RACE)
LPLSTP==:000400		;AUTOMATICALLY STOP EVERY (LDPSTB) LINES OF OUTPUT
LPLSST==:000200		;NO CLRPCT ON RECEIPT OF "FREE" XON
LPLFFS==:000100		;STOP ON FORM-FEEDS
LPLSBL==:000040		;UTTER FORTH A STUPID BELL ON AUTO STOP
LPLFFF==:000020		;SIMULATE FORMFEEDS WITH MANY LINEFEEDS
LPLFFH==:000010		;SIMULATE FORMFEEDS AS HOME/ERASE SEQUENCE
;(FREE)==000004		;FREE BIT
;(FREE)==000002		;FREE BIT
;(FREE)==000001		;FREE BIT
LPRPFF== 777000		;FORM FEED SIMULATION LF COUNTER
LPRACR== 000777		;AUTO-CRLF COUNTER

LPGCLK==LPLIRM!LPLXOF!LPLBLK!LPLSLF,,LPRPFF!LPRACR ;CLEARED BY TTYKIL
LPGCLI==LPGCLK!<LPLSTP!LPLSST!LPLFFS!LPLSBL!LPLFFF!LPLFFH,,0>  ;CLEARED BY LDBINI
;FLAGS AND POINTER TO INTERRUPT SERVICE ROUTINES
LDBISR::!BLOCK	1
;13-17	CONTAIN T1 FOR @LDBISR(U)
;18-35	ADDRESS OF ISR DISPATCH TABLE
LDBISB::!BLOCK	1
;BITS	POINTER	USE
;0	N/A	1 IF THE FRONT END IS CLEVER, 0 IF DUMB
;1-4	LDPTSP	TRANSMIT SPEED
;5-8	LDPRSP	RECEIVE SPEED
;9	LDPAPL	APL MODE
;10	LDPDBK	DEBREAK FEATURE EXISTS
;11	LDPRTC	CONTROL-R, CONTROL-T COMPATIBILITY
;12	LDPTDY	USER SAID "SET TERMINAL TIDY"

LILCFE==:(1B0)		;CLEVER FRONT END
LILRSP==:(17B4)		;RECEIVE SPEED
LILTSP==:(17B8)		;TRANSMIT SPEED
LILAPL==:(1B9)		;APL MODE
LILDBK==:(1B10)		;LINE HAS DEBREAK
LILRTC==:(1B11)		;CONTROL-R, CONTROL-T ARE PASSED TO PGM
LILTDY==:(1B12)		;DO NOT EXPAND OUTPUT

;FUNCTIONS ARE DEFINED IN S.MAC (ISR??? AND IRR???)
;LDBQUE -- QUEUED PROTOCOL WORDS

LDBQUE::BLOCK	1
LDBQUH::BLOCK	1

;BITS
;WORD	1	NEXT LDB IN THE QUEUE (0 TERMINATES)
;WORD	2
;	0-17	ADDRESS OF THE QUEUE HEADER
;	18-35	NOT CURRENTLY USED

;TERMINAL TYPE WORD

LDBTTW::BLOCK	1
;0	LTLANF	ANF-10 NETWORK VIRTUAL TERMINAL (MUST BE SIGN BIT)
;1	LTLNRT	DECNET NRT/CTERM VIRTUAL TERMINAL
;2	LTLLAT	LAT-SERVER TERMINAL LINE
;3	LTLUSE	ALLOCATABLE LDB IN USE
;4-8		FREE
;9	LDLFSP	FULL SCNSER PTY
;10	LDLVDC	'VISIBLE' DELETE CHARACTER PROCESSING BIT (FOR XMTECH)
;11	LDLIDC	'INVISIBLE' DELETE CHARACTER PROCESSING BIT (FOR RICW)
;12		FREE
;13-20	LDPLCH	LAST CHAR READ BY COMCON.
;21-28	LDPPRP	POSITION OF PROMPT
;29-35	LDPTTT	TERMINAL TYPE AS SPECIFIED BY TTY TYPE COMMAND

LTLANF==:400000	;ANF NETWORK VIRTUAL TERMINAL
LTLNRT==:200000	;DECNET NRT/CTERM TTY
LTLLAT==:100000	;LAT-SERVER TTY
LTLREM==LTLANF!LTLNRT!LTLLAT	;SOME FORM OF "REMOTE" TERMINAL SERVER
LTLUSE==:040000	;ALLOCATABLE LDB IS IN USE (SEE GETLDB/FRELDB)
		; NOTE: LTLUSE ALWAYS ON FOR 'LOCAL' (E.G., CTY) LDBS

LDLFSP==:000400	;FULL SCNSER PTY
LDLVDC== 000200	;CONTROL R IN PROGRESS
LDLIDC== 000100	;CONTROL W IN PROGRESS
;FIVE WORDS FOR REMOTE STATION TERMINAL STATUS

IFN FTNET,<			;NETWORK RELATED LDB FIELDS

LDBREM::BLOCK	5		;WORDS REQUIRED FOR REMOTE TERMINALS

;			LAYOUT OF LDBREM FIELDS
;
; +0	BYTE (20)BITS-USED-BY-NETTTY, (16)LAST-DAP-STATUS-MESSAGE-SENT
; +1	BYTE (36)LAST-CHARACTERISTICS-MESSAGE-SENT
; +2	BYTE (14)SLA, (14)DLA, (8)REMOTE-LINE-NUMBER
; +3	BYTE (4)2741-ELEMENT-NUMBER, (8)DRQ-COUNT, (8)EPM-SERIAL, (16)NODE-#
; +4MCR	BYTE (9)NEXT-CHAR-TO-OUTPUT, (9)JOB, (9)REMOTE-NCL-VERSION, (9)LAST-TTY-TYPE
; +4VTM	BYTE (16)DELAYED-STATUS-MESSAGE, (2)0, (18)VTM-QUEUE-LINK


;DEFINE SYMBOLS FOR SOME LDBREM ENTRIES
LDBCCH==:LDBREM+1		;COMPRESSED CHARACTERISTICS WORD
LDBVTQ==:LDBREM+4		;NETVTM'S QUEUE LINK HALF-WORD

;			BITS USED IN LDBREM

;BITS USED BY BOTH NETVTM(LOCAL SET HOST) AND NETMCR(REMOTE TERMINALS)

LRLVTM==:(1B0)			;*** MUST BE SIGN BIT ***
				;  IF SET, THEN THIS IS A "LOCAL TERMINAL"
				;  THAT HAS "SET HOSTED" TO ANOTHER HOST.
LRLCON==:(1B1)			;IF SET, THEN TERMINAL IS "CONNECTED"
				;  (I.E. NCL CONNECT SEQUENCE IS COMPLETE)
LRLSTS==:(1B2)			;IF SET, THEN A "STATUS" MESSAGE IS REQUIRED
				;  SAME BIT, BUT DIFFERENT MSGS FOR VTM & MCR

;BITS USED ONLY BY NETVTM (LOCAL "SET HOST")

LRLSCH==:(1B3)			;IF SET, THEN A "CHARACTERISTICS" MESSAGE
				;  IS REQUIRED (WORKS LIKE "LRLSTS")
LRLDST==:(1B4)			;A "DELAYED" STATUS MESSAGE IS REQUIRED
				;  (USED TO OPTIMIZE MESSAGE TRAFFIC.
				;  THIS BIT HAS PRIORITY OVER LRLSTS)
LRLQED==:(1B5)			;IF SET, THEN VTM LINE HAS BEEN "QUEUED"
				;  BY "VTMENQ"
LRLDIP==:(1B6)			;IF SET, THEN WE HAVE/WANT-TO INITIATE A
				; DISCONNECT ON THIS LINE
LRLVTF==:(1B7)			;VTM TERMINAL NEEDS TO BE "FREED" (A LA FRELDB)
LRLVTZ==:(1B8)			;VTM TERMINAL IS ZAPPED
;LDBREM (CONTINUED)

;BITS USED ONLY BY NETMCR ("NORMAL" REMOTE TERMINALS .. ALA DN87)

LRLTTO==:(1B3)			;LDPCHR HAS THE NEXT CHAR TO OUTPUT. THIS IS
				; NECESSARY SINCE THERE IS NO WAY TO TELL IF
				; XMTCHR WILL GIVE A CHAR WITH OUT GETTING IT.
LRLTTW==:(1B4)			;LINE IS WAITING FOR A DATA-REQUEST
LRLSCG==:(1B5)			;^O ACTION REQUESTED (SEND CHAR GOBBLER)
LRLEPW==:(1B6)			;ECHO PIPELINE MARKER WAITING TO GO.
LRLIMO==:(1B7)			;INDICATES THAT REMOTE IS IN IMAGE MODE OUTPUT
LRLADR==:(1B8)			;USE OF THE AUTO-DIALER HAS BEEN REQUESTED
LRLXOF==:(1B9)			;AN XOFF (^S) MESSAGE HAS BEEN REQUESTED
LRLCHR==:(1B10)			;THIS TERMINAL HAS RECEIVED AT LEAST 1
				; CHARACTERISTICS MSG.  (SEE NETTTY.MAC, ROUTINE
				; SCNMCR FOR DETAILS OF THE RACES INVOLVED...)
LRLHUR==:(1B11)			;HANG-UP THE PHONE REQUESTED
LRLDSR==:(1B12)			;THE -10'S COPY OF WHAT IT THINKS CARRIER
				; SHOULD BE.  (KEPT SO WE CAN TELL IF THE -11
				; CHANGED IT WHILE WE WEREN'T LOOKING)
LRLGRT==:(1B13)			;NEED TO "GREET" THE TERMINAL (E.G., RUN INITIA)
LRLATO==:(1B14)			;INDICATES THAT THIS LINE POSSESSES THE AUTO-
				; BAUD CAPABILITY.  (SET/CLEARED BY THE ATTRIB
				; FIELD OF THE CONNECT MESSAGE)
LRLADL==:(1B15)			;INDICATES THAT THIS LINE POSSESES AN AUTO-
				; DIALER (ALSO SET BY CONNECT MESSAGE)
LRLTMO==:(1B16)			;HANG-UP REQUESTED BY AUTO-DISCONNECT TIMEOUT
;FREE==:(1B17)			;FREE BIT (FORMERLY LRLTIW, FOR 2741)
LRRSHC==:1B18			;SAYS THAT THE LINE AT THE OTHER END HAS
				;  "SET HOST CAPABILITY".  (I.E. IT CAN
				;  RESPOND TO DISCONNECT MESSAGES).  NOT
				;  SET FOR DC72 LINES. SET FOR ALL OTHERS.
LRRXFF==:1B19			;WANT TO SEND XON/XOFF STATE IN STATUS
				; MESSAGE.
LRLCLR==:LRLDSR			;BITS THAT ARE OFF ON "VIRGIN" LINES
>;END OF IFN FTNET


;DEFINITIONS FOR SUPPORT OF RSX-20F TERMINALS

IFN FTKL10!FTDECNET!FTENET,<	;TTD'S ONLY ON A KL, NRT AND LAT VIA DECnet
LDBLAT::!		;REDEFINES BELOW, USED ONLY FOR LAT LINES
LDBNRT::!		;REDEFINES LDBTTD, USED ONLY FOR NRT LINES
LDBTTD::!0		;LINE INFO FOR -20F LINES
;	740000		;REMEMBERED TRANSMIT SPEED
;	036000		;REMEMBERED RECEIVE SPEED
LTLXOF==:1000		;SENT XOFF TO -20F
LTLRBS==:400		;REMOTE BIT SENT FOR -20F DATASETS
LTLCTO==:200		;NEED TO SEND FLUSH OUTPUT TO -20F
LTLAXF==:100		;AUTO-XOFF ENABLE SENT TO -20F
LTLACK==:40		;LINE WAITING FOR AN ACK
LTLXFF==:20		;SEND XON/XOFF STATUS TO -20F
LTLTIM==:17		;TIMEOUT FIELD FOR LTLACK
	TTDTIM==:6	  ;HOW LONG TO WAIT FOR LTLACK TO BE CLEARED
>;END FTKL10!FTDECNET
IFN FTMIC,<		;IF MIC INCLUDED
;WORD FOR MIC TO USE
LDBMIC::0

;0	SET IF SOME BIT 1-14 IS SET
;1	SET IF A ^C HAS BEEN TYPED
;2	SET IF OPERATOR CHAR SEEN IN COLUMN1
;3	SET IF ERROR CHAR SEEN IN COLUMN 1
;4	SET IF A ^P HAS BEEN TYPED
;5	SET IF A ^B HAS BEEN TYPED
;6	SILENCE THIS LINE
;7	LINE IN MONITOR MODE
;		NOT SET IN LDBMIC BUT IS SET ON A MICGET
;8	LINE IN USER MODE AND IN TI WAIT OR IN MONITOR MODE
;	AND CAN ACCEPT A COMMAND
;		NOT SET IN LDBMIC BUT IS SET ON A MICGET
;9	LINE IS IN COLUMN 1 ON OUTPUT
;	USED FOR ERROR AND OPERATOR CHECKING
;10	SET IF A ^A HAS BEEN TYPED (ABORT)
;11	SET IF ERROR OUTPUT IS AVAILABLE
;12	SET IF ERROR OUTPUT IS BEING TAKEN
;13	SET IF MIC IS LOGGING
;14	SET IF MORE INFORMATION IS AVAILABLE VIA JOBSTS UUO
;15-21	ASCII CHAR TO BE TREATED AS OPERATOR CHAR
;		SET IN RESPONSE TO OPERATOR COMMAND
;		CLEARED IN RESPONSE TO NOOPERATOR COMMAND
;		OR ON LOGOUT
;22-28	ASCII CHAR TO BE TREATED AS ERROR CHAR
;		SET IN RESPONSE TO ERROR COMMAND
;		CLEARED IN RESPONSE TO NOERROR COMMAND
;		OR ON LOGOUT
;29-35	MIC MASTER JOB NUMBER - ENABLES MORE THAN ONE MIC TO RUN

LDLCHK==400000		;SOMETHING EXCITING HAPPENED
LDLMCC==200000		;^C TYPED
LDLOPC==100000		;OPERATOR CHARACTER SEEN IN COLUMN 1
LDLERC==40000		;ERROR CHARACTER SEEN IN COLUMN 1
LDLMCP==20000		;^P TYPED
LDLMCB==:10000		;^B TYPED
LDLSIL==4000		;THIS LINE IS .SILENCE'D
LDLMMM==2000		;LINE IN MONITOR MODE (MICGET)
LDLMTI==1000		;LINE IN INPUT READY STATE
LDLCL1==400		;CARRIAGE IS IN COLUMN 1
LDLMCA==200		;^A TYPED
LDLRSP==100		;ERROR RESPONSE
LDLRSY==:40		;RESPONSE CODE SYNC
IFN FTMLOG,<
LDLLOG==20		;MIC IS LOGGING
>
LDLMUI==10		;USER IS INTERESTING, BUT YOU NEED TO ASK JOBSTS WHY

IFN FTMLOG,<
LDBLOT::0		;LOG TAKER,,COUNT OF CHARS TO LOG
LDBLOC::0		;COUNT OF CHARACTERS TO LOG
> ;END OF FTMLOG CONDITIONAL
> ;END OF MIC CONDITIONAL
;SPECIAL CHARACTER STATUS STORAGE

;BITS IN LDBBKB
;UNUSED BITS LEFT HALF BITS = 100040
LDBBKB::0		;FIELD WIDTH AND BITS CONTROLLING USE OF BREAK SET
LDLBKM==400000		;LINE IS IN BREAK CHARACTER SET MODE (MUST BE SIGN BIT)

XP LDBCSL,<CK.CHR/<^D36/CC.WID>>+1 ;NUMBER OF WORDS REQUIRED TO STORE THE BYTES

;***KEEP TOGETHER (FOR ZEROING)***
LDBCSB::! BLOCK	LDBCSL		;RESERVE SPACE FOR SPECIAL CHARACTER CODING
LDBCC1::! BLOCK	1		;'CLEAR' OOB FLAGS FOR LOW-ORDER CONTROL CHARS
LDBCC2::! BLOCK	1		;DITTO FOR HIGH-ORDER CONTROL CHARACTERS
;***END OF KEEP TOGETHER***

LDBCHM::!0		;CHARACTERS MAPPED BY RECMAP
LMLNDS==:400000		;THE NON-DEFAULT SEQUENCE BIT (MUST BE SIGN)
LMLSSE==200000		;SWITCH SEQUENCE ENABLED

DEPHASE

LDBLEN==:<.-SCNLDB>+M.LCST##	;SIZE OF DATA BLOCK FOR A LINE
;DISPATCH TABLE FOR PTYS AND CTYS.

IFN FTKS10,<
CTYDSP::JRST	CTYTYO		;TYPEOUT
	POPJ	P,0		;MODEM CONTROL
	POPJ	P,0		;ONCE A SECOND
	POPJ	P,0		;INITIALIZATION
	POPJ	P,0		;CHANGE HARDWARE PARMS
	POPJ	P,		;LINE PARM CONTROL
	POPJ	P,		;SET ELEMENT
	POPJ	P,		;REMOTE STUFF
	JRST	CPOPJ1##	;IS LINE UP?
>

ERRDSP::POPJ	P,0		;TYPEOUT
	POPJ	P,0		;MODEM CONTROL
	POPJ	P,0		;ONCE A SECOND
	POPJ	P,0		;INITIALIZATION
	POPJ	P,0		;CHANGE HARDWARE PARMS
	POPJ	P,		;LINE PARM CONTROL
	POPJ	P,		;SET ELEMENT
	POPJ	P,		;REMOTE STUFF
	JRST	CPOPJ1##	;IS LINE UP?

;LINE SPEED MNEMONICS

LS0000==:0	;ZERO BAUD
LS0050==:1	;50 BAUD
LS0075==:2	;75 BAUD
LS0110==:3	;110 BAUD
LS0134==:4	;134.5 BAUD
LS0150==:5	;150 BAUD
LS0200==:6	;200 BAUD
LS0300==:7	;300 BAUD
LS0600==:10	;600 BAUD
LS1200==:11	;1200 BAUD
LS1800==:12	;1800 BAUD
LS2400==:13	;2400 BAUD
LS4800==:14	;4800 BAUD
LS9600==:15	;9600 BAUD
;DATA POINTERS INTO LDB

LDPLCH:	POINT	8,LDBTTW(U),20		;POINTER TO LAST CHAR COMCON READ
LDPPRP:	POINT	8,LDBTTW(U),28		;POINTER TO POSITION AFTER PROMPT
LDPTTT::POINT	7,LDBTTW(U),35		;POINTER TO TTY TYPE
LDPCPU::POINT	3,LDBBYT(U),24
LDPFLC::POINT	2,LDBBYT(U),2		;POINTER TO INDEX OF FILLER CLASSES
LDPLNO::POINT	9,LDBDCH(U),35		;POINTER TO HARDWARE LINE NUMBER
LDPTIM::POINT	5,LDBBYT(U),19		;POINTER TO FIELD WHICH TIMES OUT
					; IMAGE MODE INPUT
LDPDEM::POINT	1,LDBBYT(U),^L<L1RDEM>	;POINTER TO L1RDEM BIT
LDPSTP: POINT   1,LDBOST(U),^L<(LOLSTP)>;POINTER TO OUTPUT STOPPED BIT
;LDPSSO:POINT	1,LDBOST(U),^L<(LOLSSO)>;POINTER TO SCNSER STOPPED OUTPUT BIT
LDPFRM::POINT	1,LDBDCH(U),^L<(LDLFRM)>;POINTER TO HARDWARE FORM FEED BIT
LDPTAB::POINT	1,LDBDCH(U),^L<(LDLTAB)>;POINTER TO HARDWARE TABS BIT
LDPLCT::POINT	1,LDBDCH(U),^L<(LDLLCT)>;POINTER TO LOWER CASE BIT
LDPIMI::POINT	1,LDBDCH(U),^L<(LDLIMI)>;POINTER TO IMAGE MODE FLAG
LDPPIM::POINT	1,LDBOST(U),^L<(LOLPIM)>;POINTER TO PIM MODE FLAG
LDPFCS::POINT	1,LDBDCH(U),^L<(LDLFCS)>;POINTER TO FULL CHAR SET FLAG
LDPBKA::POINT	1,LDBDCH(U),^L<(LDLBKA)>;POINTER TO BREAK ON ALL CHARS FLAG
LDPOSU:	POINT	1,LDBDCH(U),^L<LDROSU>	;POINTER TO OUTPUT SUPPRESSION (^O) BIT
LDPNFC::POINT	1,LDBDCH(U),^L<(LDLNFC)>;POINTER TO NO FREE CRLF BIT
LDPECH::POINT	1,LDBDCH(U),^L<(LDLNEC)>;POINTER TO NO ECHO BY PROGRAM BIT
LDPCOM::POINT	1,LDBDCH(U),^L<(LDLCOM)>;POINTER TO COMMAND-LEVEL BIT
LDPRMT::POINT	1,LDBDCH(U),^L<LDRRMT>	;POINTER TO REMOTE BIT
LDPXNF::POINT	1,LDBPAG(U),^L<(LPLXNF)>;POINTER TO XOFFON BIT
LDPALT:	POINT	1,LDBPAG(U),^L<(LPLALT)>;POINTER TO ALTMODE CONVERSION BIT
LDPDIS::POINT	1,LDBATR(U),^L<(LALDIS)>;POINTER TO DISPLAY TERMINAL BIT
LDP8BT::POINT	1,LDBATR(U),^L<(LAL8BT)>;POINTER TO 8-BIT TERMINAL BIT
POHPOS:	POINT	3,LDBBYT(U),5		;POINTER TO LOW 3 BITS OF HPOS
					; BEFORE A TAB (FOR TAB SIMULATION)
LDPVR1:	POINT	6,LDBDCH(U),17		;POINTER TO STORE SOME OF INITIAL BITS
LDPVR2:	POINT	5,LDBDCH(U),24		;POINTER TO STORE SOME MORE OF ABOVE.
LDPCMX::POINT	4,LDBCOM(U),12		;POINTER TO INDEX OF FORCED COMMANDS
LDPWID::POINT	8,LDBBY2(U),27		;POINTER TO WIDTH OF TERMINAL CARRIAGE
LDPDSC::POINT	9,LDBBY2(U),17		;POINTER TO DATASET CONTROL TABLE INDEX
LDPAPC::POINT	4,LDBBY2(U),31		;POINTER TO APC
LDPLNB::POINT	8,LDBLSW(U),8		;TTY LENGTH BASE VALUE
LDPSTB::POINT	8,LDBLSW(U),17		;TTY STOP BASE VALUE
LDPLNC:	POINT	9,LDBLSW(U),26		;CURRENT LENGTH COUNTER
LDPSTC:	POINT	9,LDBLSW(U),35		;CURRENT STOP COUNTER
LDPSST::POINT	1,LDBPAG(U),^L<(LPLSST)>;TTY SSTOP
LDPSPE::POINT	1,LDBPAG(U),^L<(LPLSTP)>;TTY STOP (ON/OFF)

LDPPFF:	POINT	9,LDBPAG(U),26		;L.F. COUNTER FOR SIMULATION OF VT & FF
LDPDEB::POINT	2,LDBBYT(U),26		;POINTER TO DEFERRED ECHO BITS
LDPSPD::POINT	8,LDBISB(U),8		;BOTH SPEEDS
LDPRTC::POINT	1,LDBISB(U),11		;^R, ^T COMPATIBILITY
LDPRSP::POINT	4,LDBISB(U),8		;RECEIVE SPEED
LDPTSP::POINT	4,LDBISB(U),4		;TRANSMIT SPEED
LDPAPL::POINT	1,LDBISB(U),9		;APL MODE BIT
LDPDBK::POINT	1,LDBISB(U),10		;DEBREAK FEATURE EXISTS
LDP274::POINT	1,LDBDCH(U),22		;LINE IS A 2741
LDPTDY::POINT	1,LDBISB(U),12		;DO NOT EXPAND OUTPUT
LDPACR::POINT	9,LDBPAG(U),35		;AUTO CRLF POINT


IFN FTNET,<
;FIELDS IN THE LDBREM AREA.  (USED BY NETWORK LINES)

LDPSTS::POINT	16,LDBREM+0(U),35	;CONTAINS THE LAST DAP STATUS MESSAGE
LDPSLA::POINT	13,LDBREM+2(U),12	;CONTAINS OUR SOURCE LINK ADDRESS
LDPDLA::POINT	13,LDBREM+2(U),25	;CONTAINS OUR DESTINATION LINK ADDRESS
LDPRLN::POINT	10,LDBREM+2(U),35	;LINE NUMBER AT REMOTE STATION
LDPELE::POINT	4,LDBREM+3(U),3		;2741 ELEMENT NUMBER
LDPDRQ::POINT	8,LDBREM+3(U),11	;NUMBER OF DATA-REQUESTS FROM REMOTE
LDPEPM::POINT	8,LDBREM+3(U),19	;SERIAL NUMBER OF LAST EPM FROM REMOTE
LDPRNN::POINT	16,LDBREM+3(U),35	;NUMBER OF NODE OWNING THIS TTY
LDPRNF::POINT	16,LDBREM+3(F),35	; SAME AS ABOVE, EXCEPT INDEXED BY "F"

LDPCHR::POINT	9,LDBREM+4(U),8		;IF LRLTTO =1, THIS CONTAINS THE NEXT
					; OUTPUT CHARACTER
LDPJOB::POINT	9,LDBREM+4(U),17	;POINTER TO JOB (ONLY FOR CONNECTS)
LDPNVR::POINT	9,LDBREM+4(U),26	;NCL VERSION OF NODE OWNING TTY
LDPLTT::POINT	9,LDBREM+4(U),35	;LAST TTY TYPE SENT TO REMOTE
LDPDST::POINT	18,LDBVTQ(U),17		;"DELAYED" STATUS FOR VTM
>;END OF IFN FTNET
IFN FTMIC,<
LDP.OP:	POINT	7,LDBMIC(U),21		;OPERATOR CHARACTER
LDP.ER:	POINT	7,LDBMIC(U),28		;ERROR CHARACTER
LDPMJN::POINT	7,LDBMIC(U),35		;MIC MASTER JOB NUMBER
> ;END IFN FTMIC
LDPFWD:	POINT	9,LDBBKB(U),11		;BREAK FIELD WIDTH
LDPQOT::POINT	1,LDBBYT(U),^L<(L1LQOT)>;TTY QUOTE
LDPDTC:	POINT	CK.WID,LDBIST(U),17	;CHARACTER DEFERRED BY SETDCS
LDPDCS:	POINT	18,LDBIST(U),35		;SPECIAL INPUT STATE CODE
LDPUNP::POINT	8,LDBCHM(U),9		;TTY UNPAUSE CHARACTER
LDPESC::POINT	8,LDBCHM(U),17		;TTY ESCAPE CHARACTER
LDPSW1::POINT	8,LDBCHM(U),25		;SWITCH SEQUENCE ONE
LDPSW2::POINT	8,LDBCHM(U),33		;SWITCH SEQUENCE TWO
LDPSWI:	POINT	16,LDBCHM(U),33		;POINTER TO BOTH OF ABOVE
LDPLCP::POINT	1,LDBDCH(U),^L<(LDLLCP)>;LOCAL COPY BIT
LDPMXT:	POINT	8,LDBBY3(U),26		;AUTO-DISCONNECT MAX. IDLE TIME
LDPTMR:	POINT	9,LDBBY3(U),35		;COUNT-UP TIMER FOR AUTO-DISCONNECT
LDP8BI:	POINT	1,LDBDCH(U),^L<(LDL8BI)>;POINTER TO 8-BIT I/O BIT
LDPCNE::POINT	1,LDBDCH(U),^L<(LDLCNE)>;POINTER TO COMMAND-LEVEL NO ECHO BIT
IFN FTKL10,<
LDPTDT::POINT	4,LDBTTD(U),17		;POINTER TO TTDINT IRMA-LIKE TIMEOUT
>

;BITS TO BE CLEARED ON A 140 RESTART

LDIDCM:	XWD	ZZL,ZZR			;TO CLEAR BITS IN LDBDCH
	SUBTTL	DATA STRUCTURES -- TTY DEVICE DATA BLOCK (DDB)

;PROTOTYPE SCANNER DDB. REPLICATED BY ONCE. ONE FOR EACH JOB.

	$LOW
TTYLST::			;LABEL FOR FIRST TTY DDB IN CHAIN

SCNDDB::			;GLOBAL LABEL
PHASE 0

	SIXBIT	/TTY0/		;DEVNAM (PHYSICAL NAME)
	XWD	0,STTYBF+1	;DEVCHR. SIZE OF USER BUFFER
	0			;DEVIOS
	XWD	0,SCNDSP	;DEVSER
	XWD	DVTTY+DVIN+DVOUT,<<1_A>+<1_AL>+<1_A8>+<1_PIMMOD>+<1_I>>	;DEVMOD
	0			;DEVLOG (LOGICAL NAME)
	0			;DEVBUF
	0			;DEVIAD
	0			;DEVOAD
	0			;DEVSTS
	XWD	.TYTTY,0	;DEVSTA
	0			;DEVXTR
	0			;DEVEVM
	0			;DEVPSI
	0			;DEVESE
	0			;DEVHCW
	707000,,0		;DEVCPU
	0			;DEVISN	- SPACE HELD EVEN IF XMON OFF
	0			;DEVJOB
DDBLDB::!0			;DDBLDB LINKS TO THE LDB.
DEPHASE
XP SCNDDS,.-SCNDDB
	$HIGH
BYTCNT:	POINT	12,DEVOAD(F),12

;DATA WITHIN THE DDB

;USE OF DEVIOS

;LEFT HALF
XP TTYOUW,400000	;REMEMBERS THAT IF IN IOW, IT IS FOR OUTPUT, AS
			; OPPOSED TO INPUT. I.E., WHICH INT WAKES JOB
FRCEND==:200000		;IN IMAGE INPUT, FORCE END OF FILE DUE TO TIMING
IOLBKA==100000		;TEMP INTERNAL BIT TO PRESERVE BKA OVER ^C/CONT

;RIGHT HALF
IOSABS==2000		;BREAK ON CHARACTERS SPECIFIED IN BREAK MASK TABLE
IOSBKA==1000		;BREAK ON ALL CHARACTERS
IOSTEC==400		;SUPPRESS ECHO OF DOLLAR SIGN ON ALTMOD
IOSNEC==:200		;USER (E.G. LOGIN) SUPPRESSING ECHO
IOSFCS==100		;USER WANTS ALL CHARACTERS.
	SUBTTL	TRANSMIT INTERRUPT ROUTINE

;ENTRY FROM DEVICE-DEPENDENT INTERRUPT SERVICE ROUTINE ON A
; TRANSMIT-DONE INTERRUPT. THE HARDWARE LINE NUMBER IS
; IN AC U.  ENTER AT XMTIN1 IF U IS SETUP TO THE LDB ADDRESS.


XMTINT::MOVE	U,LINTAB##(U)	;GET LINE DATA BLOCK ADDRESS
XMTIN1::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,L1LOFL
	ANDCAM	T1,LDBOFL(U)
	SKIPGE	LDBDCH(U)	;ARE WE EXPECTING THIS?
	JRST	XMTDMC		;NO, GO UNLOCK KEYBOARD
	PUSHJ	P,XMTCHR	;GET A CHARACTER FROM THE CHUNKS
	  POPJ	P,		;END OF STRING
	MOVSI	T1,LPLIRM	;IRMA BIT
	ANDCAM	T1,LDBPAG(U)	;CLEAR SINCE JUST SENT A CHARACTER
	MOVEI	T1,ISRTYP	;FUNCTION DESIRED FROM DEVICE DRIVER
	PJRST	@LDBISR(U)	;GO DO IT
;XMTCHR -- ROUTINE TO RETURN THE NEXT CHARACTER TO SEND FROM
;	   A TERMINAL OUTPUT BUFFER
;
;CALL
;	MOVE	U,LDB ADDRESS
;	PUSHJ	P,XMTCHR
;	  <IDLE CONDITION>
;	<CHARACTER IN T3>

XMTCHR::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,LDLIDL	;CLEAR THIS NOW, XMTIDL WILL SET IF NEEDED
	ANDCAM	T1,LDBDCH(U)	;DON'T LET REMOTES ECHO
	MOVE	T1,.CPTMF##	;GET COUNT OF CLOCK TICKS
	CAIL	T1,7		;IF TOO MANY,
	POPJ	P,		;GET OUT OF HERE BEFORE WE KAF
				; (IRMA WILL GET US BACK HERE)
XMTCH1:	SCNOFF			;MAKE SURE BITS ARE CONSISTENT
	SKIPE	T1,LDBOST(U)	;GET STATES WORD
	JFFO	T1,[JRST @XMTDSP(T2)] ;DISPATCH ON SPECIAL CONDITIONS
XMTCH2:	SOSGE	T4,LDBTOC(U)	;COUNT DOWN LENGTH OF OUTPUT STREAM
	JRST	ZAPBUF		;IF EMPTY STREAM.  GO RESET COUNT
	LDCHKR	T3,LDBTOT(U),XMTABO  ;TAKE NEXT CHARACTER FROM STREAM
	PUSHJ	P,TPCOUT	;FUDGE FOR TWO-PART CHARACTERS
XMTCH3:	SCNON			;HAVE CHARACTER, ALLOW OTHERS TO ACCESS
XMTCH5:	CAIN	T4,^D50		;HAVE WE REACHED THE WAKE THRESHOLD?
	PUSHJ	P,XMTWAK	;YES, GO WAKE JOB IF WAITING
XMTCH4:	TRNE	T3,CK.MET	;IS THIS A META CHARACTER?
	JRST	XMTMET		;YES, GO DISPATCH THE FUNCTION
	TRNE	T3,CK.IMG	;IS THIS AN IMAGE MODE CHARACTER?
	JRST	XMTCN7		;YES, COUNT IT AND RETURN
	ANDI	T3,CK.CHR	;CLEAR POSSIBLE PARITY BIT
	SKIPGE	T1,CHTABL(T3)	;GET SPECIAL BITS, TEST FOR UNUSUAL CHAR
	JRST	XMTSPO		;THIS MAY REQUIRE FILL OR BLANK SUPPRESS
	AOSG	LDBHPS(U)	;INCREMENT HORIZONTAL POSITION
	JRST	XMTCN7		;RETURN IF NOT END OF CARRIAGE
	PUSHJ	P,PTBTCH##	;CHECK FOR REGULAR PTY
	  JRST	XMTCN7		;NO FREE CRLF FOR LOG FILES
	MOVE	T2,LDBDCH(U)	;GET CHARACTERISTICS WORD
	TLNE	T2,LDLNFC	;USER WANT FREE <CR><LF>?
	JRST	XMTCN7		;NO, JUST SEND THE CHARACTER
	TLZ	T1,CHALT!CHUAE!CHCRE  ;OUTPUT CHARACTERS GO STRAIGHT
	TLO	T1,CHFILO	;OUTPUT FILL
	PUSHJ	P,SETCRF	;YES, GO SETUP A CRLF FILLER
	  JRST	XMTCH1		; AND SEND THE FILLER INSTEAD
	JRST	XMTCN7		;GO SEND THE CHARACTER AFTER ALL!
;COUNT UP THE CHARACTERS PHYSICALLY OUTPUT AND RETURN

XMTCNT:	CAIN	T3,12		;LINEFEED?
	PUSHJ	P,INCPCT	;BUMP PAGE COUNTER

XMTCN4:	ANDI	T3,CK.CHR!CK.IMG ;TRIM OFF FUNNY BITS
XMTCN7:
IFN	FTMIC,<
	MOVE	T4,LDBMIC(U)	;GET MIC BITS
	TLNE	T4,LDLSIL	;LINE SILENCED
	JRST	XMTCH1		;YES, EAT THE CHARACTER
>
XMTCN8:	AOS	LDBOCT(U)	;COUNT CHARACTERS OUTPUT THIS LINE
	AOS	%SCNXI		;AND TOTAL CHARACTERS OUTPUT BY SYSTEM
IFN FTRSP,<AOS	.CPNXI##>	;PER CPU AS WELL
	PJRST	CPOPJ1##	;RETURN THE CHARACTER


;HERE FOR UNUSUAL CHARACTER ON OUTPUT

XMTSPO:	MOVSI	T2,LPLBLK
	TDNE	T2,LDBPAG(U)
	PUSHJ	P,BLSUPO	;CHECK FOR TERMINAL NO BLANKS

	PUSHJ	P,ADJHP
	PUSHJ	P,SETFLO	;SETUP FILLERS IF ANY NEEDED
	  JRST	XMTCH1		;FILLS NEEDED, GO SEND THEM FIRST
	CAIN	T3,12		;IF LINE FEED
	PUSHJ	P,INCPCT	; INCREMENT PAGE COUNT
	JRST	XMTCN7		;NONE NEEDED, JUST RETURN IT
;HERE WHEN AN IMBEDDED FUNCTION (META) CHARACTER IS FOUND IN THE OUTPUT STREAM
;TO DISPATCH UPON IT AND RETURN VIA SETCHP

XMTMET:	TRNE	T3,CK.NIS	;IS THIS REALLY HERE?
	JRST	XMTCH1		;NO, SKIP IT
	CAIL	T3,CK.MET	;IS THIS IN RANGE?
	CAIL	T3,CK.MET+METLEN ;BOTH WAYS?
	JRST	XMTCH1		;NO, SKIP IT ** MAYBE STOPCD HERE? **
	PUSHJ	P,XMTME1	;CALL WORKHORSE (FOR SAVING ACS)
	  JRST	SETCHP		;GIVE NON-SKIP AFTER REQUEUEING LINE
	JRST	XMTCH1		;KEEP LOOKING FOR A CHARACTER

XMTME1:	PUSHJ	P,SAVE2##	;PRESERVE OUR REGISTERS
	MOVE	P1,METABL-CK.MET(T3)	;GET DISPATCH VALUE
	TLNN	P1,CH2PC	;NEED AN ARGUMENT?
	PJRST	(P1)		;NO, JUST DISPATCH IT
	SCNOFF			;FOR LDCHK'ING
	SOSGE	LDBTOC(U)	;IS THE ARGUMENT STILL THERE?
	JRST	ZAPBUF		;NO, GIVE UP
	LDCHKR	P2,LDBTOT(U),XMTABO	;YES, GET IT
	SCNON			;CAN ALLOW OTHERS AGAIN
	PJRST	(P1)		;NOW CALL THE ROUTINE (AND RETURN A LEVEL)


;ROUTINE TO SET USER'S VALUE OF LDLTAB DURING OUTPUT

METTAB:	LDB	T2,LDPTAB	;GET PREVIOUS VALUE
	CAMN	T2,P2		;IF NO CHANGE,
	JRST	CPOPJ1##	;DON'T BOTHER ANYBODY
	DPB	P2,LDPTAB	;STORE IN LDB
	POPJ	P,		;GIVE SETCHP RETURN

;ROUTINE TO SET USER'S VALUE OF LDLFRM DURING OUTPUT

METFRM:	LDB	T2,LDPFRM	;GET PREVIOUS VALUE
	CAMN	T2,P2		;IF NO CHANGE,
	JRST	CPOPJ1##	;DON'T BOTHER ANYBODY
	DPB	P2,LDPFRM	;STORE IN LDB
	POPJ	P,		;GIVE SETCHP RETURN

;ROUTINE TO SET USER'S VALUE OF LDLNFC DURING OUTPUT

METNFC:	LDB	T2,LDPNFC	;GET PREVIOUS VALUE
	CAMN	T2,P2		;IF NO CHANGE,
	JRST	CPOPJ1##	;DON'T BOTHER ANYBODY
	DPB	P2,LDPNFC	;STORE IN LDB
	POPJ	P,		;GIVE SETCHP RETURN

;ROUTINE TO SET USER'S VALUE OF LDPWID DURING OUTPUT

METWID:	LDB	T2,LDPWID	;GET PREVIOUS VALUE
	CAMN	T2,P2		;IF NO CHANGE,
	JRST	CPOPJ1##	;DON'T BOTHER ANYBODY
	PUSHJ	P,HPOS		;GET CURRENT HPOS
	DPB	P2,LDPWID	;STORE NEW WIDTH IN LDB
	MOVE	P2,T2		;MOVE HPOS FOR METHPS
	;PJRST	METHPS		;FALL INTO METHPS TO RESTORE HPOS

;ROUTINE TO SET USER'S VALUE OF HPOS DURING OUTPUT

METHPS:	PUSHJ	P,HPOS		;GET PREVIOUS VALUE
	CAMN	T2,P2		;IF NO CHANGE,
	JRST	CPOPJ1##	;DON'T BOTHER ANYBODY
	LDB	T2,LDPWID	;GET CARRIAGE WIDTH
	SUB	T2,P2		;FORM COLUMNS TO GO UNTIL RIGHT MARGIN
	MOVNM	T2,LDBHPS(U)	;STORE AS COUNT UP VALUE
	POPJ	P,		;GIVE SETCHP RETURN

;ROUTINE TO FORCE LEFT MARGIN DURING OUTPUT

METFLM:	PUSHJ	P,HPOS		;GET HPOS
	JUMPE	T2,CPOPJ1##	;DONE IF ALREADY THERE
	AOS	(P)		;SET FOR SKIP RETURN
	PJRST	METNLF		;ELSE, TYPE OUT A NEWLINE

;ROUTINE TO SET L1LDEM

METDEN:	SKIPA	T2,[IORM T1,LDBBYT(U)]	;INSTRUCTION TO SET THE BIT
METDEF:	MOVE	T2,[ANDCAM T1,LDBBYT(U)] ;INSTRUCTION TO CLEAR IT
	SCNOFF			;FIGHT RACES
	MOVSI	T1,L1LDEM	;THE BIT IN QUESTION
	XCT	T2		;SET OR CLEAR AS REQUESTED
	SCNON			;ALLOW OTHERS AGAIN
	JRST	XMTECD		;DELETE CHARACTER AND GET ANOTHER TO ECHO

;ROUTINE TO CALL SETCHP SYNCHRONOUSLY WITH OUTPUT

METCHP:	MOVSI	T1,LDLIDL	;GET IDLE BIT
	IORM	T1,LDBDCH(U)	;LIGHT IT SO FE'S WILL CALL US AGAIN
	PJRST	SETCHP		;RE-QUEUE LINE & RETURN NON-SKIP FROM XMTCHR

;ROUTINE TO START UP A CONTROL-R (RE-TYPE) FOR XMTECH

METRTS:	PUSHJ	P,METRT1	;CALL WORKHORSE
	JRST	XMTCH1		;LOOK FOR MORE OUTPUT
METRT1:	PUSHJ	P,SAVE3##	;NEED SOME EXTRA ACS
	SCNOFF			;NO INTERRUPTS
	TRC	T3,MC.RTS^!MC.RTE ;ALTER THE CHARACTER
	DPB	T3,LDBECT(U)	;SAVE FOR TURNING OFF ^R MODE WHEN DONE
	SETZB	P1,P2		;CLEAR COUNTS OF CHARACTERS PASSED
	SKIPN	T4,LDBBKU(U)	;POINT TO LAST LINE BREAK
	MOVE	T4,LDBTIT(U)	;OR BEGINNING IF NO BREAK
	MOVE	P3,T4		;SAVE BEGIN POINTER
	EXCH	T4,LDBECT(U)	;RESET TAKER, GET STOP POINTER
METRT2:	CAMN	T4,LDBECT(U)	;HAVE WE CAUGHT UP?
	JRST	METRT3		;YES, CLEAN UP
	LDCHK	T3,LDBECT(U),SONPJ1 ;GET A CHARACTER
	TRNE	T3,CK.NIS	;IF MISSING,
	AOS	P2		;COUNT ANOTHER INVISIBLE
	AOS	P1		;AND ANOTHER CHARACTER IN ANY CASE
	JRST	METRT2		;LOOP OVER ALL CHARACTERS TO BE RETYPED
METRT3:	MOVEM	P3,LDBECT(U)	;RESET ECHO TAKER AGAIN
	ADDM	P1,LDBECC(U)	;COUNT HOW MANY CHARACTERS TO RE-ECHO
	ADDM	P2,LDBIEC(U)	;AND HOW MANY WERE INVISIBLE
	MOVNS	P1		;NEGATE BECAUSE SUBM GOES WRONG WAY FOR THIS
	MOVNS	P2		; ...
	ADDM	P1,LDBTIC(U)	;THIS MANY FEWER FOR READ-IN
	ADDM	P2,LDBIIC(U)	;AND SIMILARLY FOR HOW MANY ARE INVISIBLE
	MOVSI	T1,LDLCRP	;CONTROL-R PENDING BIT
	IORM	T1,LDBDCH(U)	;LIGHT IT FOR TYICC4 & XMTECH
	SCNON			;SAFE TO ALLOW OTHERS NOW
	PUSHJ	P,PRSKL		;SPACE OVER PROMPT AND CLEAR THE LINE
	  JRST	METRT4		;NOT A DISPLAY, DO IT THE OLD WAY
	MOVEI	T3,MC.CHP	;SET TO TELL FE'S ABOUT HPOS
	PJRST	SETFCE		;STUFF IN FILL CHUNKS AND RETURN

METRT4:	MOVE	T2,FLLBSC	;BACKSLASH-THEN-CRLF
	MOVSI	T1,L2LDEL	;DELETE SEQUENCE BIT
	TDNN	T1,LDBBY2(U)	;WAS THERE AN OPENING BACKSLASH?
	IBP	T2		;NO, DON'T TYPE A CLOSING ONE
	ANDCAM	T1,LDBBY2(U)	;MAKE SURE FOR LATER
	PJRST	SETFLE		;STUFF THE SEQUENCE IN THE CHUNKS & GO

;ROUTINE TO SHUT OFF CONTROL-R PROCESSING FOR TYICC4 & XMTECH

METRTE:	MOVSI	T1,LDLCRP	;CONTROL-R PENDING BIT
	ANDCAM	T1,LDBDCH(U)	;CLEAR IT
	MOVEI	T3,"R"-100	;THIS WAS A CONTROL-R
	PJRST	XMTECD		;CHANGE TO DELETED CHARACTER AND TRY FOR XMT'S
;HERE WHEN A SPECIAL CONDITION BIT IS SET IN THE LDB.  THESE BITS
;ARE PLACED IN LDBOST IN SUCH A WAY THAT A JFFO INSTRUCTION CAN
;BE USED TO FIND THE CONDITION THAT NEEDS ATTENTION FIRST.

;HERE TO TYPE XOFF/XON STRINGS
XMTXFP:	SCNON			;RELEASE INTERLOCK
	ILDB	T3,LDBXNP(U)	;GET NEXT CHARACTER FROM XON/XOFF FILL POINTER
	JUMPN	T3,XMTCN8	;RETURN IT IF IT'S THERE
	MOVSI	T3,LOLXFP	;NO, GET BIT THAT BROUGHT US HERE
	ANDCAM	T3,LDBOST(U)	;CLEAR IT
	SETZM	LDBXNP(U)	;AND THE POINTER
	JRST	XMTCH1		;AND TRY AGAIN

;HERE TO TYPE A BELL (TTY SBELL OR INPUT LOST)
XMTNBS:	SCNON			;RELEASE INTERLOCK
	MOVSI	T3,LOLNBS	;CLEAR BIT THAT GOT US HERE
	ANDCAM	T3,LDBOST(U)	;IN THE LDB
	MOVEI	T3,007		;GET A BELL (SANS PARITY)
	JRST	XMTCN8		;AND RETURN IT

;HERE FOR ECHO/FILL OUTPUT TO BE TYPED
XMTESP:	;SCNOFF			;NO INTERRUPTS FOR A FEW INSTRUCTIONS
	SOSGE	LDBEOC(U)	;COUNT ANOTHER ECHO OUTPUT
	JRST	XMTES1		;DO SANITY CHECK WHEN STREAM LOOKS EMPTY
	LDCHKR	T3,LDBEOT(U),XMTES2	;GET NEXT CHARACTER FOR ECHO
	PUSHJ	P,TPCFIL	;CHECK FOR FILL EXPANSION
XMTES0:	SCNON			;ALLOW INTERRUPTS AGAIN
	TRNN	T3,CK.MET	;UNLESS A FUNCTION CHARACTER
	JRST	XMTCNT		;COUNT IT AND RETURN
	MOVE	T1,T3		;YES, COPY IT
	ANDI	T1,CK.CHR	;KEEP ONLY THE FUNCTION INDEX
	MOVE	T1,METABL(T1)	;GET THE DISPATCH
	PJRST	(T1)		;CALL THE FUNCTION

XMTES1:	SETZM	LDBEOC(U)	;DON'T GO NEGATIVE
	MOVE	T3,LDBEOT(U)	;GET TAKER
	CAME	T3,LDBEOP(U)	;MUST MATCH PUTTER
	PUSHJ	P,RCDSTP	;ERROR IF NOT EQUAL
XMTES2:	MOVSI	T3,LOLESP	;CLEAR BIT THAT GOT US HERE
	ANDCAM	T3,LDBOST(U)	;IN THE LDB
	SCNON			;ALLOW INTERRUPTS AGAIN
	JRST	XMTCH1		;TRY FOR NEXT CHARACTER

;HERE FOR 'NOT NOW' OUTPUT
XMTNNP:	SCNON			;RELEASE INTERLOCK
	ILDB	T3,LDBNNP(U)	;GET NEXT CHARACTER FROM FILL POINTER
	CAILE	T3,FLLFLG	;IS IT A REAL CHARACTER
	JRST	XMTCH4		;YES, USE IT
	SCNOFF			;AVOID RACES
	MOVSI	T2,LOLNNP	;CLEAR BIT THAT BROUGHT US HERE
	ANDCAM	T2,LDBOST(U)	;FROM THE LDB
	SETZM	LDBNNP(U)	;AND THE BYTE POINTER
	SCNON			;END OF POSSIBLE RACE
	JUMPE	T3,XMTCH1	;TRY AGAIN IF END OF STRING
	PUSHJ	P,METNLF	;TYPE CRLF IF WAS FILLER FLAG
	JRST	XMTCH1		;THEN TRY AGAIN

;HERE TO RE-EAT OUTPUT
XMTREO:	;SCNOFF			;FIGHT RACES
	MOVSI	T1,LOLREO	;BIT THAT BROUGHT US HERE
	ANDCAM	T1,LDBOST(U)	;CLEAR IT
	LDB	T3,LDBTOT(U)	;GET CHARACTER TO RE-DO
	SCNON			;ALLOW OTHERS AGAIN
	PJRST	XMTCH4		;AND USE IT AGAIN

;HERE TO RE-EAT ECHO
XMTREE:	;SCNOFF			;FIGHT RACES
	MOVSI	T1,LOLREE	;BIT THAT BROUGHT US HERE
	ANDCAM	T1,LDBOST(U)	;CLEAR IT
	LDB	T3,LDBECT(U)	;GET CHARACTER TO RE-DO
	MOVE	T1,T3		;COPY CHARACTER
	ANDI	T1,CK.CHR	;MASK DOWN
	MOVE	T1,CHTABL(T1)	;GET BITS
	SCNON			;ALLOW OTHERS AGAIN
	PJRST	XMTEC4		;AND USE CHARACTER AGAIN

;HERE FOR FORCED STRING OUTPUT (USED ONLY BY SEND ALL)
XMTFSP:	SCNON			;RELEASE INTERLOCK
	ILDB	T3,LDBFLP(U)	;GET NEXT CHARACTER FROM FILL POINTER
	CAILE	T3,FLLFLG	;IS IT A REAL CHARACTER?
	JRST	XMTCH4		;YES, USE IT
	SCNOFF			;AVOID RACES
	MOVSI	T2,LOLFSP!LOLSAP ;CLEAR BITS THAT BROUGHT US HERE
	ANDCAM	T2,LDBOST(U)	;FROM THE LDB
	SETZM	LDBFLP(U)	;AND THE BYTE POINTER
	SCNON			;END OF POSSIBLE RACE
	JUMPE	T3,XMTCH1	;IF NULL, JUST TRY FOR NEXT CHARACTER
	PUSHJ	P,METNLF	;TYPE A CRLF VIA THE ECHO STREAM
	MOVEI	T3,"."		;GET A DOT JUST IN CASE
	MOVSI	T2,LDLCOM	;COMMAND LEVEL BIT	
	TDNE	T2,LDBDCH(U)	;USER AT COMMAND LEVEL?
	PUSHJ	P,SETFCE	;YES, TYPE THE DOT AS WELL
	JRST	XMTCH1		;TRY FOR NEXT CHARACTER TO OUTPUT

;HERE WHEN NEW SEND ALL STRING TO BE SENT (COMCON HAD TO DEFER THE SEND)
XMTSAP:	;SCNOFF			;AVOID RACES
;	MOVSI	T2,LOLSAP	;CLEAR BIT THAT BROUGHT US HERE
;	ANDCAM	T2,LDBOST(U)	;FROM THE LDB
	SOSGE	SNDCTR##	;ONE FEWER LINE WAITING
	SETZM	SNDCTR##	;DON'T LET THE COUNT GO NEGATIVE!
	MOVE	T2,SNDPTR##	;GET FILL POINTER FROM COMCON
	PUSHJ	P,SETFPT	;SET THE FILL POINTER (DOES A SCNON)
	JRST	XMTCH1		;AND TYPE FROM THE FILL POINTER


...OST==1B0	;START OF STATE BITS

DEFINE	OSTAT(NM,RTN)<
	XP LOL'NM,(...OST)
	...OST==...OST_-1
IFB<RTN>,<	IFIW	XMT'NM>
IFNB<RTN>,<	IFIW	XMT'RTN>
IF1,<IFG 1B17-...OST,<PRINTX % LDBOST LH IS FULL WITH LOL'NM>>
>

XMTDSP:
	OSTAT	XFP		;XOFF PENDING
	OSTAT	NBS		;NEED BELL SENT
	OSTAT	ESP		;ECHO STREAM PENDING
	OSTAT	FSP		;FORCED STRING PENDING
	OSTAT	SAP		;SEND ALL PENDING
	OSTAT	STP,IDL		;XOFF ON LINE
	OSTAT	SSO,IDL		;SCNSER STOPPED OUTPUT
	OSTAT	NNP		;'NOT NOW' POINTER
	OSTAT	REO		;RE-EAT OUTPUT
	OSTAT	REE		;RE-EAT ECHO
	OSTAT	PIM,CH2		;IN PIM MODE
	OSTAT	MIC		;CONTROLLED BY MIC
;HERE WHEN CHUNKS MESSED UP, TIME TO IDLE THE LINE

XMTABO:!
;HERE TO IDLE THE LINE SINCE IT HAS NO MORE CHARACTERS LEFT TO OUTPUT

XMTIDL:	MOVSI	T1,LDLIDL	;LINE IS IDLE BIT
	IORM	T1,LDBDCH(U)	; SET IN LDB
	MOVSI	T1,LPLIRM	;IRMA BIT
	ANDCAM	T1,LDBPAG(U)	; CLEAR
	SCNON			;RELEASE TERMINAL SERVICE INTERLOCK
	HRRZ	F,LDBDDB(U)	;ADDRESS OF LINKED DDB
	JUMPE	F,CPOPJ##	;JUMP IF NO DDB
	PUSH	P,J		;SAVE J
	LDB	J,PJOBN##	;GET JOB NUMBER
	MOVE	T1,JBTSTS##(J)	;GET JOB STATUS
	TRNE	T1,JS.NTO	;HIBERING FOR NON-BLOCKING TTY OUTPUT?
	PUSHJ	P,WAKEJB##	;YES--WAKE HIM UP
	POP	P,J		;RESTORE J

XMTDMC:	HRRZ	F,LDBDDB(U)	;IF NO DDB ALL DONE
	JUMPE	F,CPOPJ##	;IF NO DDB.

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

XMTWAK:
IFN FTNET,<
	SKIPGE	LDBREM(U)	;IF THIS IS A VTM LINE
	PJRST	VTMENQ##	;  QUEUE THE LINE SO WE SEND MORE DATA-REQUESTS
>
IFN FTMIC,<
	SKIPN	T1,LDBMIC(U)	;CONTROLLED BY MIC?
	JRST	XMTWK1		;IF NOT
IFN FTMLOG,<
	TLNE	T1,LDLLOG	;LOGGING
	PUSHJ	P,MLOGOF	;TIDY UP
> ;END IFN FTMLOG
	PUSHJ	P,MICWAK	;WAKE MIC
> ;END IFN FTMIC
XMTWK1:	HRRZ	F,LDBDDB(U)
	JUMPE	F,CPOPJ##
	MOVE	S,DEVIOS(F)
	TLNE	S,IOW		;IO WAIT?
	JUMPL	S,TTWAKE	;IF OUTPUT, GO WAKE JOB
	POPJ	P,		;IF INPUT, RETURN
;PACKED IMAGE MODE (PIM) TRANSMIT INTERRUPT.

REPEAT 0,<
XMTPIM:	SCNOFF
	SOSGE	T4,LDBTOC(U)	;COUNT DOWN
	PJRST	ZAPPI1		;IF EXHAUSTED
	LDCHKR	T3,LDBTOT(U),XMTABO  ;TAKE A CHARACTER, RETURN STALE CHUNKS
	SCNON			;ALLOW INTERRUPTS
	CAIN	T4,^D50		;IF LESS THAN 50. CHARS LEFT
	PUSHJ	P,XMTWAK	;WAKE UP THE ATTACHED JOB
	TRNE	T3,CK.MET	;IF META,
	JRST	XMTMET		;THEN DO THE FUNCTION
	JRST	XMTCN7		;ELSE, COUNT AND RETURN THE CHARACTER
> ;END OF REPEAT 0

;HERE WHEN THE OUTPUT STREAM COUNT IS EXHAUSTED.  RESET IT TO ZERO
;AND SET THE LINE IDLE.  COME HERE ONLY WITH SCANNER INTERLOCK SET.

ZAPPI1:	SETZM	LDBTOC(U)	;COUNT IS PROBABLY NEGATIVE NOW
	MOVE	T2,LDBTOT(U)	;MAKE SURE PUTTER MATCHES TAKER
	CAME	T2,LDBTOP(U)	;MAKE SURE BOTH POINTERS MATCH
	PUSHJ	P,RCDSTP	;NO, DIE NOW
	PJRST	XMTIDL		;IDLE THE LINE
;HERE ON A TRANSMIT DONE INTERRUPT WHEN LDBMIC IS NON-ZERO

XMTMIC:
IFN FTMIC,<			;IF MIC
IFN FTMLOG,<
	MOVE	T2,LDBMIC(U)
	TLNE	T2,LDLLOG	;HAS HE ASKED FOR LOG
	SKIPE	LDBLOT(U)	;HAS HE GOT A LOG TAKER
	JRST	MICLG3
	MOVE	T2,LDBTOT(U)	;MAKE COPY OF TAKER
	MOVEM	T2,LDBLOT(U)
MICLG3:
> ;END OF FTMLOG CONDITIONAL
	PUSHJ	P,HPOS		;GET HORZONTAL POSITION ON LINE
	JUMPN	T2,XMTOK	;IN COLUMN 1?
	SKIPE	T2,LDBMIC(U)	;IS HE RUNNING MIC OR
	TLNN	T2,LDLRSP!LDLRSY	;WANTS RESPONSE FEATURE
	JRST	XMTOK1		;NO - MUST NOT INTERFERE
	TLNE	T2,LDLERC	;HAS HE HAD ERROR?
	TLNE	T2,LDLMCC	;AND NOT ^C
	JRST	XMTOK1		;NO - IGNORE
	SKIPN	LDBTOC(U)	;IS THERE A CHARACTER WAITING?
	JRST	XMTOK1		;NO, IGNORE
	MOVE	T4,LDBTOT(U)	;COPY OF OUTPUT TAKER
	LDCHK	T3,LDBTOT(U),XMTABO	;PREVIEW NEXT CHARACTER
	MOVEM	T4,LDBTOT(U)	;RESTORE POINTER
	LDB	T2,LDP.ER	;GET ERROR CHAR
	JUMPE	T2,XMTOK	;MUST BE ONE
	ANDI	T3,CK.CHR	;JUST 7 BITS
	CAIE	T3,"?"		;IS IT A "?"
	CAMN	T3,T2		; OR THE ERROR CHARACTER
	CAIA			;YES, HANDLE MIC'S RESPONSE
	JRST	XMTOK		;NO IGNORE
	MOVSI	T2,LDLRSY!LDLCHK;SET THE SYNC
	IORB	T2,LDBMIC(U)
	TLNN	T2,LDLRSP	;BEEN THIS WAY BEFORE
	JRST	XMTECH		;YES JUST DO ECHOING
	HRRZ	F,LDBDDB(U)
	JUMPE	F,XMTECH	;NO ATTACHED DDB
	MOVE	S,DEVIOS(F)
	MOVE	T2,LDBDCH(U)	;GET WORD WITH COMMAND WAIT BIT
	TLNN	S,IOW		;IN IO WAIT?
	TLNE	T2,LDLCOM	;OR IN COMMAND WAIT
	SKIPA			;YES TO EITHER
	JRST	XMTECH		;NO FORGET IT
	MOVSI	T2,LDLRSP
	ANDCAM	T2,LDBMIC(U)	;SAY SYNC
	PUSHJ	P,MICWAK
	JRST	XMTECH		;AND PUT THE PLUG IN
XMTOK:	MOVE	T2,LDBMIC(U)	;GET MIC BITS
XMTOK1:	TLNE	T2,LDLRSY	;WAITING FOR MIC TO TAKE RESPONCE
	JRST	XMTECH		;YES, KEEP THE PLUG IN

IFN FTMLOG,<
	SKIPN	LDBLOT(U)	;ARE WE LOGGING THIS?
	JRST	XMTCH2		;NO, GO TAKE CHARACTER NORMALLY
	SOSGE	LDBTOC(U)	;DECREMENT COUNT OF CHARACTERS AND TEST
	JRST	ZAPBUF		;IF OUTPUT STREAM NOW EMPTY
	LDCHK	T3,LDBTOT(U),XMTABO  ;TAKE A CHARACTER OUT OF THE STREAM
	AOS	LDBLOC(U)	;COUNT UP THE NUMBER TO BE LOGGED
	JRST	XMTCH3		; AND JOIN PROCESSING
> ;END IFN FTMLOG
> ;END OF IF MIC

;ENTER HERE WITH SCNOFF TO CLEAR LDBTOC AND CHECK FOR ECHO

ZAPBUF:	MOVSI	T1,LOLPIM	;PIM TEST
	TDNE	T1,LDBOST(U)	;IF IN PIM,
	JRST	ZAPPI1		;DON'T BOTHER WITH XMTECH
	SETZM	LDBTOC(U)	;ZERO COUNT
	MOVE	T1,LDBTOP(U)	;GET PUTTER
	CAME	T1,LDBTOT(U)	;MUST MATCH TAKER
	PUSHJ	P,RCDSTP	; OOPS, SOMETHING IS WRONG
IFN FTNET,<
	SKIPL	LDBREM(U)	;IS THIS A VTM LINE?
	JRST	XMTECH		;NO, LOOK FOR ECHO TO OUTPUT
	PUSHJ	P,XMTIDL	;YES, MARK LINE IDLE AND RELEASE INTERLOCK
	PJRST	VTMENQ##	;  WE MUST BE SURE TO SEND DATA-REQUESTS
				;  NOW THAT WE'RE OUT OF DATA.
> ;END IFN FTNET
		;FALL INTO XMTECH
;HERE WHEN BUFFERED AND FILLER OUTPUT DONE, AND LDBECT IS NON-ZERO
;NEED TO ECHO A CHARACTER THAT HAS BEEN TYPED IN.
XMTECH:	MOVE	T1,LDBDCH(U)	;SEE IF SHOULD DEFER ECHOING
	TLNE	T1,LDLCRP	;CONTROL-R SYNCH BIT SET?
	JRST	ECHCNR		;YES, GO CHECK OUT ^R THINGS
	MOVE	T1,LDBBYT(U)	;NO, GET WORD CONTAINING DEFERRED ECHO BITS
	TLNN	T1,L1LDEM	;IF NOT IN LH DEFERRED ECHO,
	TRZ	T1,L1RDEM	;THEN GIVE RH BIT TIME TO CATCH UP TO US
	SKIPL	LDBBKB(U)	;IF BREAK SET SPECIFIED, ALWAYS DEFERRED ECHO
	TRNE	T1,L1RDEM	;DEFERRED ECHO MODE SELECTED?
	TRNE	T1,L1RDEL!L1RDEC; HAS AN INPUT REQUEST BEEN MADE YET?
	TLNE	T1,L1LUNR	;AND NOT BLOCKED BY UNREAD?
	CAIA			;DEFERRED AND NOT REQUESTED YET, MAYBE IDLE LINE
	JRST	ECHCNR		;NO, IT'S FINE TO ECHO
	HLLZ	T1,LDBOST(U)	;GET STATE BITS
	TLZ	T1,LOLMIC	;CLEAR WHAT MIGHT HAVE BROUGHT US HERE
	JUMPE	T1,XMTIDL	;RETURN EMPTY-HANDED IF NOTHING TO SEND
XMTREQ:	SCNON			;YES, RELEASE INTERLOCK
	JRST	XMTCH1		;AND TRY AGAIN
ECHCNR:	SOSGE	LDBECC(U)	;ANY LEFT TO ECHO?
	JRST	ZAPECH		;NO, FINISH UP
	LDCHK	T3,LDBECT(U),XMTABO  ;TAKE CHARACTER FROM INPUT, SAVE CHUNKS
	TRNE	T3,CK.NIS	;INIVISIBLE CHARACTER?
	JRST	[SOS	LDBIEC(U) ;YES, COUNT ONE LESS TO ECHO
		 AOS	LDBIIC(U) ;AND ONE MORE FOR INPUT
		 JRST	XMTECI]	;REJOIN MAIN STREAM
	MOVE	T1,T3		;COPY CHARACTER
	ANDI	T1,CK.CHR	;MASK IT DOWN
	CAIN	T1,40		;A SPACE?
	PUSHJ	P,XMTACR	;YES, CHECK OUT ACR CONDITION
	PUSHJ	P,TPCECH	;SEE IF NEED TO DO EXPANSION AT THIS LEVEL
XMTECI:	MOVE	T2,LDBECT(U)	;GET ECHO TAKER
	CAMN	T2,LDBBKI(U)	;TAKING LAST BREAK?
	SETZM	LDBBKI(U)	;YES, ZAP ITS POINTER
	AOS	T2,LDBTIC(U)	;COUNT THE INPUT CHARACTERS
XMTECX:	SCNON			;ALLOW INTERRUPTS
	TRNE	T3,CK.NIS	;IS THIS STILL A REAL CHARACTER?
	JRST	XMTCH1		;NO, TRY AGAIN
	AOS	%SCNEI		;COUNT CHARACTERS ECHOED
IFN FTRSP,<AOS	.CPNEI##>	;PER CPU AS WELL
	MOVE	T4,LDBBYT(U)	;GET WORD WITH ECHO BITS AGAIN
	TRNE	T3,CK.MET	;IF NOT AN IMBEDDED FUNCTION, AND
	JRST	XMTECE		;NO, DON'T WORRY ABOUT RECEIVE ROUTINES
	PUSHJ	P,SPCHEK	;YES, GET THE CHARACTER'S CONTROL BITS
	  JRST	XMTECU		;NOT SPECIAL, GO CHECK FOR LDLLCT
	TLNE	T1,CHRIA	;DOES THIS CHARACTER HAVE A RECEIVE ROUTINE?
	TLNE	T1,CHNDFR	;AND WAS IT DEFERRED?
	JRST	XMTECE		;NO TO EITHER, DON'T CALL ITS PREPROCESSOR
	PUSHJ	P,(T1)		;YES, CALL ITS PROCESSOR NOW
	  JRST	XMTECD		;IT DIDN'T WANT TO BE STORED, GO DELETE IT
	MOVSI	T4,L3LEHD	;ECHO HALF-DONE FLAG
	TDNE	T4,LDBBY3(U)	;HAVE WE ALREADY CALLED TPCECH?
	JRST	XMTECE		;YES, DON'T STORE INTO DECREMENTED B.P.
	SCNOFF			;DON'T ALLOW OTHERS IN THE CHUNKS
	DPB	T3,LDBECT(U)	;STORE THE (POSSIBLY CHANGED) CHARACTER
	PUSHJ	P,TPCECH	;CHECK FOR EXPANSION (AGAIN)
	SCNON			;ALLOW OTHERS AGAIN
	JRST	XMTECE		;IT WANTS TO BE KEPT, SO ECHO IT
XMTECU:	MOVE	T1,T3		;COPY CHARACTER
	ANDI	T1,CK.CHR	;ISOLATE IT
	MOVE	T1,CHTABL(T1)	;GET ALL OF ITS BITS
	TLNE	T1,CHPUNC	;IF PUNCTUATION,
	TRNN	T3,CK.PAR	;THEN CAN'T RAISE 8-BIT
	TRNE	T3,CK.IMG	;IF IMAGE MODE,
	JRST	XMTECE		;THEN CAN'T RAISE ITS CASE
	MOVE	T4,LDBDCH(U)	;GET BITS FOR TTY UC
	TLNN	T4,LDLLCT	;DOES USER WANT US TO RAISE CASE?
	JRST	XMTECE		;NO, JUST GO ECHO
	MOVE	T4,T3		;COPY CHARACTER
	ANDI	T4,CK.CH7	;QUICKLY MASK IT DOWN
	CAIGE	T4,140		;IS IT LOWER CASE?
	JRST	XMTECE		;NO, DON'T CHANGE IT
	TRC	T3,040		;YES, CHANGE ITS CASE
	MOVSI	T4,L3LEHD	;ECHO HALF-DONE FLAG
	TDNN	T4,LDBBY3(U)	;DON'T CLOBBER CHUNKS IF SET
	DPB	T3,LDBECT(U)	;AND ALTER IT IN THE CHUNKS
XMTECE:	MOVSI	T1,LDLPPS	;PROMPT POS SET BIT
	TDNN	T1,LDBDCH(U)	;SET YET THIS LINE?
	JRST	[IORM	T1,LDBDCH(U)	;NO, BUT WE'RE ABOUT TO
		 MOVE	T1,T2	;SAVE INPUT COUNT
		 PUSHJ	P,HPOS	;GET CARRIAGE POSITION
		 DPB	T2,LDPPRP ;STORE AS PROMPT POSITION
		 MOVE	T2,T1	;RESTORE T2
		 JRST	.+1]	;REJOIN MAIN STREAM
	MOVEI	T4,L1RDEC	;CHARACTER REQUEST BIT
	PUSHJ	P,SPCHEK	;SEE IF IT'S SPECIAL.
	  JRST	XMTEC1		;NO, A SINGLE MUNDANE CHARACTER
	TRNE	T3,CK.MET	;IF AN IMBEDDED FUNCTION,
	JRST	(T1)		;GO DO IT
	TLNN	T1,CHBRK	;YES. IS IT A BREAK CHAR?
	JRST	XMTEC1		;NOT A BREAK
	SCNOFF			;FIGHT RACE
	MOVE	T4,LDBECT(U)	;GET CURRENT POINTER
	MOVEM	T4,LDBBKU(U)	;SAVE FOR BACK-UP LIMIT
	CAMN	T4,LDBBKI(U)	;LAST BREAK FROM OTHER SIDE?
	SETZM	LDBBKI(U)	;YES, FORGET ABOUT IT
	AOS	LDBBKC(U)	;COUNT LINES IN THE LDB
	AOS	LDBBCT(U)	;COUNT BREAK CHARACTERS INPUT
	SCNON			;ALLOW OTHERS AGAIN
	PUSHJ	P,CPRPOS	;CLEAR LDLPPS SO CAN GET NEW PROMPT POSITION
	MOVEI	T4,L1RDEC!L1RDEL;GET LINE REQUESTED BIT
XMTEC1:	ANDCAM	T4,LDBBYT(U)	;CLEAR, SINCE WE ECHOED A CHARACTER
	PUSH	P,T1		;SAVE CHARACTER BITS
	PUSH	P,T3		;AND CHARACTER
	MOVSI	T4,LDLBKA+LDLIMI;BREAK ON ALL CHARACTERS?
	TDNE	T4,LDBDCH(U)	; ..
	JRST	[PUSHJ	P,RCVWKQ	;YES, WAKE JOB
		 PUSHJ	P,CPRPOS	;CLEAR PROMPT POS AS IF BREAK
		 JRST	XMTEC2]		;AVOID EXTRA WAKE IF BREAK TOO
	PUSHJ	P,CHKTIB	;ARE THERE OVER 72. OF THEM?
	TLNE	T1,CHBRK	;OR IS IT A BREAK CHARACTER?
	PUSHJ	P,ECHBRK	;YES. WAKE THE JOB, IF ANY
XMTEC2: POP	P,T3
	POP	P,T1		;RESTORE CHARACTER BITS INTO T1
IFN FTMIC,<
	SKIPE	LDBMIC(U)	;IF MIC-CONTROLLED,
	PUSHJ	P,MICECH	;LET MIC KNOW ABOUT <CR> AND SUCH
>
	MOVSI	T2,LDLCRP	;ARE WE IN A CONTROL-R?
	TDNE	T2,LDBDCH(U)	;TEST
	JRST	XMTEC3		;YES, KEEP ECHOING
	TLNE	T1,CHBRK	;A BREAK?
	SKIPL	LDBBKB(U)	;AND A BREAK MASK SPECIFIED?
	CAIA			;NO TO EITHER
	JRST	XMTCH1		;BREAK CHARACTERS DON'T ECHO

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

XMTEC3:	TRNE	T3,CK.IMG	;IS IT IMAGE?
	TRNE	T3,CK.MET	;YES, BUT IS IT QUOTED?
	TRNA			;NO OR YES, KEEP GOING
	JRST	XMTEC7		;IMAGE, LEAVE ALONE
	MOVE	T2,LDBDCH(U)	;NO, GET LINE CHARACTERISTICS
	TLNE	T2,LDLNEC	;IS IT NON-ECHOING?
	TLNE	T2,LDLCRP	;AND NOT IN A CONTROL-R?
	TRNA			;NO, USE FILL
	JRST	XMTEC7		;YES, LEAVE ALONE
	TDNN	T2,[XWD LDLLCP,LDRHLF]	;LOCAL COPY?
	JRST	XMTEC4		;NO, COUNT UP NORMAL CHARACTER
	MOVEI	T2,L2RXON	;PAPER TAPE?
	TDNE	T2,LDBBY2(U)	;...
	JRST	XMTEC7		;YES.  NO FILLERS, ELSE GARBLE.
XMTEC4:	MOVSI	T2,L2LDEL	;DELETE SEQUENCE BIT
	TDNE	T2,LDBBY2(U)	;BACKSLASH NEEDED?
	TLOA	T1,CHSPO!CHFIL	;YES, SAY FILL REQUIRED
	TLNE	T1,CHSPO	;SPECIAL CHARACTER OF SOME FLAVOR?
	JRST	XMTEC5		;YES, MORE EXTENSIVE HANDLING REQUIRED
	AOSG	LDBHPS(U)	;NORMAL CHARACTER, ECHO ONE CHAR POSITION
	JRST	XMTEC7		;GO DO IT
	SOS	LDBHPS(U)	;UNDO AOSG (ADJHP WILL RE-DO IT)
XMTEC5:	MOVSI	T2,LPLBLK	;THE SUPPRESS-BLANK-LINES BIT
	TDNE	T2,LDBPAG(U)	;"TTY NO BLANK" SET?
	PUSHJ	P,BLSUPI	;YES, NOTE PASSING <LF>S ET AL
	PUSHJ	P,ADJHP		;ADJUST CARRIAGE POSITION FOR ECHOED CHARACTER
	TRZ	T3,CK.MET!CK.IMG ;WE WANT TO SEE ECHOING CORRECTLY
	PUSHJ	P,SETFLI	;SET FILLERS FOR ECHOING
	  JRST XMTCH1		;OUTPUT FROM FILLER POSITION.

XMTEC7:	PUSHJ	P,ECHTST	;SEE IF CHARACTER NEEDS ECHOING
	  JRST	XMTCN4		;NOT ECHOED YET, RETURN IT
	JRST	XMTCH1		;ALREADY DONE, GET THE NEXT

;HERE TO DELETE AN INPUT CHARACTER AND TRY AGAIN
XMTECD:	TRO	T3,CK.NIS	;THIS IS NO LONGER A CHARACTER
	MOVSI	T4,L3LEHD	;ECHO EXPANSION IN PROGRESS?
	TDNE	T4,LDBBY3(U)	;CHECK
	JRST	XMTCH1		;YES--JUST TRY THIS AGAIN
	SCNOFF			;FIGHT RACES
	DPB	T3,LDBECT(U)	;FUDGE THE CHARACTER
	SKIPE	LDBTIC(U)	;UNLESS TSETBI'D
	AOS	LDBIIC(U)	;THERE'S ANOTHER ECHOED INVISIBLE CHARACTER
	SCNON			;ALLOW OTHERS AGAIN
	JRST	XMTCH1		;LOOK FOR ANOTHER CHARACTER TO SEND
;SUBROUTINE TO DETERMINE WHETHER CHARACTER NEEDS ECHOING
;RETURNS NON-SKIP IF NEEDS ECHO,
;SKIP RETURN IF NOT NEEDED

ECHTST:	MOVE	T1,LDBDCH(U)	;GET LEFT AND RIGHT HALF BITS
	TLNE	T1,LDLCRP	;ARE WE IN A CONTROL-R?
	POPJ	P,		;YES, ALL CHARACTERS ECHO
	TDNN	T1,[XWD LDLLCP,LDRHLF!LDR2741]	;NO, EITHER TYPE OF LOCAL COPY?
	JRST	ECHTS2		;NO, DO NORMAL CHECKS
IFN FTMIC,<
	SKIPE	T1,LDBMIC(U)	;RUNNING MIC?
	TLNE	T1,LDLMCB	;IN MIC BREAK?
	JRST	CPOPJ1##	;MIC BREAK AND LOCAL COPY, DON'T ECHO AGAIN
	JRST	ECHTS1		;NO, MIC CHARACTERS ALWAYS ECHO
> ;END IFN FTMIC
ECHTS2:
IFN FTNET,<
	TRNE	T3,CK.IMG	;IF IMAGE,
	JRST	ECHTS1		;THEN NO ECHO WAS DONE
	TRNE	T3,CK.FDE	;ONLY ECHO IF FRONT-END DIDN'T
	JRST	CPOPJ1##	;IF NOT VTM, DON'T ECHO, IF VTM, MUST ECHO HERE
> ;END IFN FTNET		;ECHO THE CHARACTER NOW
ECHTS1:	MOVE	T1,LDBDCH(U)	;BITS
	TLNN	T1,LDLCNE	;SKIP LEVEL CHECK IF NO-ECHO BY COMMAND
	TLNN	T1,LDLCOM	;CHARACTER ITSELF SHOULD BE ECHOED
	TLNN	T1,LDLNEC	;UNLESS USER LEVEL AND HE SAID NO
	POPJ	P,		;RETURN CHARACTER
	JRST	CPOPJ1##	;NO, STEP TO NEXT CHARACTER
;META-CHARACTER FUNCTION ROUTINES

;SUBROUTINE TO TYPE A CRLF VIA THE ECHO STREAM
METNLF:	MOVE	T2,FLLCRF	;GET CRLF FILL POINTER
	PJRST	SETFLE		;FORCE A CRLF TO BE OUTPUT

;ROUTINE TO ECHO A DELETE-LINE (^U) OPERATION
METDL:	PUSHJ	P,METDL1	;CALL WORKHORSE
	JRST	XMTCH1		;TYPE ANYTHING WE QUEUED UP
METDL1:	PUSHJ	P,SAVE4##	;PRESERVE A FEW
	MOVSI	T1,L2LDEL	;BACKSLASH BIT
	ANDCM	T1,LDBBY2(U)	;GET COMPLEMENT OF PREVIOUS STATE
	PUSH	P,T1		;SAVE IT FOR AFTER SETTING UP
	MOVEI	T3,CK.NIS+"U"-100	;REPLACE MC.DL WITH USED ^U
	PUSHJ	P,DELPRE	;PERFORM DELETION PREAMBLE
	POP	P,T1		;GET COMPLEMENT OF PREVIOUS L2LDEL SETTING
	ANDCAM	T1,LDBBY2(U)	;CLEAR IT IF IT WAS OFF BEFORE
	PUSHJ	P,PRSKL		;SKIP PROMPT AND KILL REST OF LINE
	  SKIPA	T3,["U"-100]	;NOT A DISPLAY, ECHO OLD WAY WITH ^U<CRLF>
	JRST	METDL2		;DONE WITH PROMPT, GO PERFORM DELETION
	PUSHJ	P,ECHTST	;OLD WAY, SEE IF WE WERE ECHOING
	  SKIPA	T2,FILXUP	;YES, GET POINTER TO \^U<CRLF>
	JRST	METDL2		;NO, DON'T BOTHER
	MOVSI	T1,L2LDEL	;THE BACKSLASH BIT
	TDNN	T1,LDBBY2(U)	;WAS IT ON?
	IBP	T2		;NO, DON'T NEED BACKSLASHES
	PUSHJ	P,SETFLE	;SEND ^U<CRLF>
METDL2:	CAIE	P1,DELEND	;DO WE OWN THE INPUT STREAM?
	JRST	METDL3		;NO, MUST DO THIS THE HARD WAY
	PUSHJ	P,RIDLN		;YES, JUST DUMP THE LINE
	JRST	METDL5		;AND GO HANDLE CLEAN-UP
METDL3:	PUSHJ	P,DELSFX	;FIND ANOTHER TO DELETE
	  JRST	METDL5		;DONE WITH THE LINE, GO CLEAN UP
	SCNOFF			;EXCLUDE OTHERS WHILE WE TWIDDLE CHUNKS
	SKIPLE	LDBTIC(U)	;AVOID CONFLICT WITH TSETBI
	PUSHJ	P,DELMID	;DELETE IT
	SCNON			;SAFE TO ALLOW OTHERS FOR A WHILE
	JRST	METDL3		;LOOP UNTIL THE LINE IS GONE
METDL5:	MOVSI	T1,L2LDEL	;GET DELETION BIT
	ANDCAM	T1,LDBBY2(U)	;DON'T CONFUSE ANYONE ELSE, WE'RE DONE
	MOVSI	T1,LDLVDC	;VISIBLE DELETE CHARACTER FLAG
	ANDCAM	T1,LDBTTW(U)	;YES, OUR DELETE WAS VISIBLE
	PJRST	DELFIN		;FINISH UP DELETION AND RETURN


;SUBROUTINE TO SKIP OVER THE PROMPT (IF ANY) AND KILL THE LINE
PRSKL:	PUSHJ	P,TTVID		;SEE IF A VIDEO TERMINAL
	  POPJ	P,		;NO, CAN'T DO IT
	HLRZ	T1,TCRTAB##+1(T1)	;GET ERASE TO EOL TABLE
	JUMPE	T1,CPOPJ##	;IF NOT THERE, CAN'T DO IT
	PUSH	P,T1		;SAVE TABLE ADDRESS
	PUSHJ	P,HPOS		;GET CURRENT POSITION
	LDB	T3,LDPPRP	;AND POSITION TO MATCH
	MOVSI	T1,LDLPPS	;PROMPT POS SET BIT
	TDNN	T1,LDBDCH(U)	;PROMPT FOUND FOR THIS LINE YET?
	CAIN	T2,(T3)		;AND POSITIONS DON'T MATCH?
	CAIA			;PROMPT IS OK
	SETZ	T3,		;NO, FAKE IT AS ZERO
	PUSH	P,T3		;SAVE COUNT OF POSITIONS TO SKIP
	MOVE	T1,-1(P)	;RETRIEVE TABLE ADDRESS
	MOVE	T2,(T1)		;GET <CR> POINTER
	PUSHJ	P,SETFLE	;AND PUT THAT IN THE CHUNKS
	PUSHJ	P,SCNBOL	;MAKE SURE AT LEFT MARGIN
	ADDM	T3,LDBHPS(U)	;ACCOUNT FOR CHARACTERS TO SKIP
PRSKL1:	SOSG	(P)		;AT LEAST ONE MORE TO SKIP?
	JRST	PRSKL2		;NO, FINISH UP
	MOVE	T1,-1(P)	;YES, GET TABLE ADDRESS
	MOVE	T2,1(T1)	;GET CURSOR RIGHT SEQUENCE
	PUSHJ	P,SETFLE	;ENTER IT INTO THE STREAM
	JRST	PRSKL1		;LOOP OVER PROMPT LENGTH
PRSKL2:	POP	P,T2		;RESTORE COUNT
	POP	P,T1		;AND TABLE ADDRESS
	SKIPN	T2		;IF ONE LEFT OF PROMPT POSITION
	SKIPA	T2,2(T1)	;YES, GET CURSOR RIGHT + KILL LINE
PRSKL3:	MOVE	T2,3(T1)	;NO, GET KILL LINE ONLY
	AOS	(P)		;SET UP SKIP RETURN FOR CALLER
	PJRST	SETFLE		;STORE STRING IN CHUNKS AND RETURN SUCCESS

;HERE TO DELETE A WORD (^W)
METDW:	MOVEI	T3,CK.NIS+"W"-100	;GET A USED ^W FOR REPLACEMENT
	PUSHJ	P,METDW1	;DELETE THE WORD
	JRST	XMTCH1		;AND TRY FOR ANOTHER CHARACTER
METDW1:	PUSHJ	P,SAVE4##	;PRESERVE OUR DISPATCH REGISTERS
	PUSHJ	P,DELPRE	;TAKE CARE OF DELETE CHARACTER PREAMBLE
	TLNN	T1,-1		;CAN WE ERASE TO EOL?
	JRST	METDW2		;NO, LEAVE ECHO DISPATCH ALONE
	MOVEI	P2,METDWE	;YES, USE DIFFERENT ECHO ROUTINE
	PUSHJ	P,SETFLC	;GET OUR FILLER CLASS
	MOVE	P3,FILLHP(T2)	;KEEP ITS FILL POINTER AROUND
METDW2:	PUSHJ	P,DELSFX	;ZAP ANY TRAILING NIS CHARACTERS
	  JRST	METDWX		;NOTHING TO DELETE
	CAIE	T3,11		;IS IT A TAB
	CAIN	T3,40		;OR A SPACE?
	JRST	[PUSHJ	P,DELONE	;YES, ZAP THE CHARACTER
		 JRST	METDW2]	;AND LOOP OVER TRAILING WHITESPACE
	TLNE	T1,CHPUNC	;IS IT ALPHANUMERIC?
	JRST	METDW4		;NO, GO TEST TERMINATION
METDW3:	PUSHJ	P,DELONE	;DELETE THE CHARACTER
	PUSHJ	P,DELSFX	;TRIM ANY NIS CHARACTERS
	  JRST	METDWX		;NOTHING MORE TO DELETE
	TLNN	T1,CHPUNC	;IF IT'S STILL ALPHANUMERIC,
	JRST	METDW3		;THEN KEEP DELETING FROM WORD
METDW4:	MOVSI	T2,LDLVDC	;VISIBLE DELETE CHARACTER FLAG
	TDNE	T2,LDBTTW(U)	;STILL ON?
	PUSHJ	P,DELONE	;YES, SO HAVEN'T DONE ANYTHING YET, GET THIS ONE
METDWX:	CAIE	P2,METDWE	;DID ECHO DELETION USE OUR SPECIAL ROUTINE?
	PJRST	DELFIN		;NO, GO FINISH UP
	PUSHJ	P,TTVID		;YES, GET CHARACTERISTICS AGAIN
	  TDZA	T2,T2		;CLEAR AC IF NONE
	HLRZ	T2,TCRTAB##+1(T1)	;OTHERWISE GET EOL TABLE ADDRESS
	MOVE	T2,3(T2)	;GET KILL TO EOL BYTE POINTER
	PUSHJ	P,SETFLE	;STORE IN ECHO/FILL STREAM
	PJRST	DELFIN		;NOW GO FINISH UP

;HERE TO DELETE A CHARACTER (BACKSPACE)
METBS:	MOVEI	T3,CK.NIS+"H"-100	;GET A USED BACKSPACE
	PUSHJ	P,METBS1	;CALL WORKHORSE ROUTINE
	JRST	XMTCH1		;AND TRY FOR MORE CHARACTERS TO OUTPUT
METBS1:	PUSHJ	P,SAVE4##	;PRESERVE OUR DISPATCH REGISTERS
	PUSHJ	P,DELPRE	;SETUP DELETE ROUTINE
	MOVEI	P2,METDWE	;USE BACKSPACING ECHO ROUTINE
	PUSHJ	P,SETFLC	;GET OUR FILL CLASS
	MOVE	P3,FILLHP(T2)	;AND SET BACKSPACE STRING FOR ECHO ROUTINE
	PJRST	METDC2		;NOW ACT LIKE RUBOUT

;HERE TO DELETE A CHARACTER (RUBOUT)
METDC:	MOVEI	T3,CK.NIS+177	;GET A USED RUBOUT
	PUSHJ	P,METDC1	;CALL WORKHORSE ROUTINE
	JRST	XMTCH1		;AND TRY FOR MORE CHARACTERS TO OUTPUT
METDC1:	PUSHJ	P,SAVE4##	;PRESERVE OUR DISPATCH REGISTERS
	PUSHJ	P,DELPRE	;SETUP DELETE AND ECHO ROUTINES
METDC2:	PUSHJ	P,DELSFX	;ZAP ANY NIS CHARACTERS
	  PJRST	DELFIN		;NOTHING TO DELETE
	PUSHJ	P,DELONE	;GOT ONE, DELETE IT
	PJRST	DELFIN		;CLEAN UP
;ECHO ROUTINES FOR DELETE WORD/CHARACTER

;SUBROUTINE TO USE BACKSPACES, MUST EVENTUALLY BE FOLLOWED BY AN ERASE TO EOL
METDWE:	MOVEI	T3,010		;LOAD A BACKSPACE
	PUSHJ	P,SETFCE	;SET FOR CHARACTER ECHO
	MOVE	T2,P3		;GET OUR BACKSPACE FILLER
	PUSHJ	P,SETFLE	;PUT INTO FILL/ECHO STREAM
	SOJG	P4,METDWE	;LOOP FOR WIDTH OF CHARACTER
	POPJ	P,		;RETURN TO DELONE

;SUBROUTINE TO USE TCRTAB BACKSPACE TABLE
METDCT:	HRRZI	T2,8(P3)	;COPY TABLE POINTER
	SUB	T2,P4		;POINT TO RIGHT ENTRY
	MOVE	T2,(T2)		;PICK UP BYTE POINTER
	PJRST	SETFLE		;PUT INTO FILL/ECHO STREAM AND RETURN

;SUBROUTINE TO ECHO DELETION FOR HARDCOPY TERMINALS
METDCR:	MOVSI	T1,L2LDEL	;BIT FOR DELETION IN PROGRESS
	TDNN	T1,LDBBY2(U)	;FIRST DELETION ECHO?
	JRST	[IORM	T1,LDBBY2(U)	;YES, SET BIT
		 MOVE	T2,FLLBSP	;GET BACKSLASH POINTER
		 PUSHJ	P,SETFLE	;SEND A BACKSLASH
		 JRST	.+1]	;REJOIN
	PUSHJ	P,SETFCE	;OUTPUT CHARACTER VIA ECHO STREAM
	SOJG	P4,.-1		;LOOP FOR WIDTH OF CHARACTER
	POPJ	P,		;RETURN TO DELONE
;SPECIAL ROUTINES FOR DELETE WORD/CHARACTER

;SUBROUTINE TO SET UP FOR DELETE WORD/CHARACTER
DELPRE:	SCNOFF			;MUSN'T LET ANYONE ELSE IN
	MOVSI	T1,LDLDIP	;DELETE-IN-PROGRESS FLAG
	IORM	T1,LDBDCH(U)	;LIGHT FOR TYICC4
	DPB	T3,LDBECT(U)	;SAVE ALTERED CHARACTER FOR READERS
	SKIPE	LDBTIC(U)	;MAKE SURE THERE'S STILL A STREAM
	AOS	LDBIIC(U)	;COUNT ANOTHER INVISIBLE CHARACTER
	MOVEI	P1,DELMID	;ROUTINE TO DELETE FROM THE MIDDLE
	MOVE	T1,LDBECT(U)	;SEE WHERE WE ARE
	CAME	T1,LDBTIP(U)	;ARE WE AT THE END?
	JRST	DELPR1		;NO, WE GUESSED RIGHT
	MOVEI	T1,L1RMIF	;YES, GET THE RECINT INTERLOCK FLAG
	TDNE	T1,LDBBYT(U)	;IS IT IN USE?
	JRST	DELPR1		;YES, STILL CAN'T DELETE FOR REAL
	IORM	T1,LDBBYT(U)	;NO, OBTAIN IT
	MOVEI	P1,DELEND	;AND USE ROUTINE TO DELETE FROM THE END
DELPR1:	SCNON			;ALLOW OTHERS IN AGAIN
	PUSHJ	P,STOPCM	;STOP COMCON FROM INTERFERING
	MOVSI	T1,LDLVDC	;VISIBLE DELETE CHARACTER BIT
	IORM	T1,LDBTTW(U)	;LIGHT IT FOR LATER
	PUSHJ	P,TTVID		;SEE IF VIDEO TERMINAL
	  TDZA	T1,T1		;NO, HAS NO TABLES
	MOVE	T1,TCRTAB##+1(T1) ;YES, GET ITS TABLES
	MOVEI	P2,METDCR	;ASSUME HARDCOPY ECHO
	TRNN	T1,-1		;DO WE HAVE A DELETE SEQUENCE?
	POPJ	P,		;NO, WE'RE ALL DONE
	MOVEI	P2,METDCT	;YES, USE THE TABLE TO DELETE
	HRRZ	P3,T1		;AND COPY THE TABLE ADDRESS
	POPJ	P,		;NOW WE'RE DONE

;SUBROUTINE TO BACK UP OVER ANY NOT-IN-STREAM CHARACTERS
;ON SKIP RETURN, HAS CHAR TO BE DELETED IN T3 AND CHTABL BITS IN T1
;ON NON-SKIP, THERE ARE NO MORE CHARACTERS AVAILABLE TO DELETE
DELSFX:	SKIPN	LDBTIC(U)	;ANY MORE TO BE DELETED?
	JRST	[PUSHJ	P,INPCHK	;MAYBE NOT, DO SANITY CHECK
		   JRST	DELSFX		;THERE'S ANOTHER
		 POPJ	P,]		;NO, GIVE DEPLETION RETURN
	LDB	T3,LDBECT(U)	;YES, GET CHARACTER TO ZAP
	TRNE	T3,CK.NIS	;IF NOT A REAL CHARACTER
	JRST	[PUSHJ	P,DELONE	;DELETE IT
		 JRST	DELSFX]	;AND LOOK FOR NEXT
	PUSHJ	P,SPCHEK	;SEE IF SPECIAL TO SOMEONE
	  JFCL			;OK IF NOT
	TLNE	T1,CHBRK	;IF A BREAK,
	POPJ	P,		;WE CAN'T DELETE IT
	TRC	T3,CK.IMG!CK.MET ;IMAGE OR META
	TRCN	T3,CK.IMG!CK.MET ;IS IT BOTH?
	JRST	DELSF1		;YES, GET DIFFERENT BITS
	TRZ	T3,CK.FDE!CK.IMG	;CLEAR MISLEADING BITS
	TRNE	T3,CK.MET	;META CHARACTER?
	SKIPA	T1,METABL-CK.MET(T3)	;YES, GET META BITS
	MOVE	T1,CHTABL(T3)	;NO, GET ALL ITS BITS
	JRST	CPOPJ1##	;AND RETURN GOODNESS

DELSF1:	TRZ	T3,CK.FDE	;CLEAR BIT WE DON'T CARE ABOUT
	JRST	CPOPJ1##	;RETURN GOODNESS
;SUBROUTINE TO DELETE ONE CHARACTER FROM THE END OF THE INPUT STREAM
;PRESERVES T3
;CALLED UNDER SCNOFF
DELEND:	PUSH	P,T3		;AS ADVERTISED
	PUSHJ	P,DELCHR	;REMOVE A CHARACTER
	  PUSHJ	P,RCDSTP	;SHOULDN'T GET THIS FAR IF NO CHARACTER IN STREAM
	JRST	T3POPJ##	;RESTORE CHARACTER JUST DELETED AND RETURN

;SUBROUTINE TO DELETE ONE CHARACTER FROM THE MIDDLE OF THE INPUT STREAM
;PRESERVES T3 MODULO THE CK.NIS BIT
;CALLED UNDER SCNOFF
DELMID:	SOSGE	LDBTIC(U)	;ONE LESS ECHOED CHARACTER
	PJRST	RCDSTP		;SHOULDN'T GET THIS FAR IF NONE
	TROE	T3,CK.NIS	;WE'RE MAKING AN INVISIBLE CHARACTER
	SOSA	LDBIIC(U)	;IF WAS, IS ONE LESS ECHOED
	DPB	T3,LDBECT(U)	;ELSE UPDATE IN CHUNKS
	AOS	LDBECC(U)	;ONE MORE TO ECHO
	AOS	LDBIEC(U)	;AND IT'S INVISIBLE
	SETO	T1,		;AMOUNT TO BACKSPACE ECHO TAKER
	ADJBP	T1,LDBECT(U)	;GET A BACKSPACED POINTER
	HRRZI	T2,CK.BDY##(T1)	;SEE IF BACKED INTO HEADER WORD
	TRNE	T2,CK.BDY##	;DID WE?
	JRST	DELMD1		;NO, ALMOST DONE
	SSX	T2,MS.SCN	;YES, SET SCNSER DATA SECTION
	HLRZ	T1,CK.BTH##(T2)	;GET BACK POINTER
	JUMPE	T1,DELMD2	;BETTER BE THERE
	ADD	T1,[POINT CK.WID,CK.BDY##,35]	;POINT TO END OF PREVIOUS CHUNK
DELMD1:	MOVEM	T1,LDBECT(U)	;STORE BACKSPACED POINTER
	POPJ	P,		;DONE WITH DELETION

;HERE TO CHECK IF DELETING TOO FAR
DELMD2:	MOVE	T1,LDBTIT(U)	;GET TYPEIN TAKER
	IBP	T1		;BUMP IT
	CAME	T1,LDBECT(U)	;ARE WE BACKING UP TO A PLACE WE UNDERSTAND?
	STOPCD	CLRSTP,DEBUG,DELMBD,	;++DELMID WENT BAD
	MOVE	T1,LDBTIT(U)	;YES, GET POINTER AGAIN
	JRST	DELMD1		;AND GO FOR IT

;CLEAN UP AFTER DELETION
DELFIN:	PUSHJ	P,DELSFX	;MAKE SURE OF SUFFIX
	  TRN			;DON'T CARE IF NO MORE
	MOVSI	T1,LDLVDC	;VISIBLE DELETE CHARACTER FLAG
	TDNE	T1,LDBTTW(U)	;IS IT ON?
	CAIE	P2,METDCR	;AND WAS THIS HARDCOPY DELETION?
	JRST	DELFN1		;NO TO EITHER, PRESS ON
	MOVE	T2,FLLBSC	;YES, GET POINTER TO BACKSLASH - CRLF
	MOVSI	T1,L2LDEL	;BIT FOR DELETION SEQUENCE
	TDNN	T1,LDBBY2(U)	;OPENING BACKSLASH TYPED?
	IBP	T2		;NO, SO DON'T TYPE A CLOSING ONE
	PUSHJ	P,SETFLE	;TYPE END OF DELETION STRING
	ANDCAM	T1,LDBBY2(U)	;CLEAR BACKSLASH FLAG FOR NEXT TIME
DELFN1:	MOVSI	T1,LDLDIP	;DELETE-IN-PROGRESS FLAG
	ANDCAM	T1,LDBDCH(U)	;NOT ANY MORE
	MOVEI	T3,MC.CHP	;THE SETCHP CHARACTER
	PUSHJ	P,SETFCE	;TELL FE'S ABOUT HPOS CHANGE AFTER WE'RE DONE
	CAIE	P1,DELEND	;DID WE GET THE "MIC" INTERLOCK?
	POPJ	P,		;NO, WE'RE DONE
	PJRST	RECINU		;YES, GIVE UP THE INTERLOCK AND RETURN
;SUBROUTINE TO DELETE ONE CHARACTER, COMPLETE WITH ECHO/FILL
;CALLED WITH CHARACTER TO BE DELETED IN T3
DELONE:	SCNOFF			;DELETION ROUTINES NEED THIS
	SKIPG	LDBTIC(U)	;DID TSETBI SNEAK IN?
	JRST	SONPPJ		;YES, WE HAVE NOTHING LEFT TO DO
	TRNE	T3,CK.NIS	;IF ALREADY A NON-CHARACTER,	
	JRST	[PUSHJ	P,(P1)	;DELETE IT FROM THE CHUNKS
		 JRST	SONPPJ]	;AND WE'RE DONE
	PUSHJ	P,(P1)		;REAL CHARACTER, REMOVE IT FROM THE STREAM
	SCNON			;ALLOW OTHERS AGAIN
	MOVSI	T2,LDLVDC	;VISIBLE DELETE CHARACTER FLAG
	ANDCAM	T2,LDBTTW(U)	;NOTE WE DELETED SOMETHING REAL
	TRC	T3,CK.MET!CK.IMG ;QUOTE BITS
	TRCN	T3,CK.MET!CK.IMG ;IS IT QUOTED?
	JRST	DEL1Q		;YES, HANDLE DELETION OF QUOTED CHARACTER
	ANDI	T3,CK.CHR	;TRIM FUNNY BITS
	CAIN	T3,11		;IS IT A TAB?
	JRST	DEL1T		;YES, TABS GET SPECIAL HANDLING
	MOVEI	P4,1		;ASSUME A WIDTH OF ONE
	CAIL	T3,40		;IS IT A PRINTING
	CAIL	T3,177		; CHARACTER?
	JRST	DEL1C		;NO, CONTROL CHARACTERS ARE DIFFERENT
DEL1A:	PUSH	P,T3		;SAVE CHARACTER TO ECHO
	MOVE	T2,P4		;COPY WIDTH
	PUSHJ	P,BACKUP	;ADJUST HPOS
	POP	P,T3		;RESTORE CHARACTER
DEL1EX:	MOVE	T2,LDBDCH(U)	;GET CHARACTERISTIC BITS
	TLNE	T2,LDLNEC	;IF USER SAID NO ECHO,
	TLNE	T2,LDLCOM	;AND AT USER LEVEL,
	PJRST	(P2)		;NO, SIMPLE CASE, JUST CALL ECHOER AND RETURN
	POPJ	P,		;YES, DON'T ECHO THIS

DEL1C:	TRNE	T3,CK.PAR	;REGULAR CONTROL CHARACTER?
	JRST	DEL1E		;NO, GO HANDLE EIGHT-BIT
	MOVE	T1,CHTABL(T3)	;GET CONTROL BITS
	MOVE	T2,LDBDCH(U)	;GET CHARACTERISTICS
	CAIE	T3,STDALT	;UNLESS IT'S ESCAPE,
	TLZ	T1,CHALT	;IT'S NOT AN ALTMODE
	TLNE	T2,LDLDLR	;USER SUPPRESSING THIS CRUFT?
	TLZ	T1,CHUAE!CHALT!CHCRE ;YES, CLEAR IT OUT
	TLNN	T1,CHUAE!CHCRE!CHALT	;EITHER FORM OF UPARROW ECHO INVOLVED?
	POPJ	P,		;NO, DIDN'T ECHO BEFORE, SO DON'T NOW
DEL1C1:	PUSH	P,T3		;SAVE ACTUAL CHARACTER
	MOVEI	T2,2		;THIS HAS A WIDTH OF TWO,
	TLNE	T1,CHALT	;UNLESS IT'S ESCAPE
	MOVEI	T2,1		;THEN IT HAS A WIDTH OF ONE
	PUSHJ	P,BACKUP	;SO ADJUST HPOS THAT MANY
	TLNE	T1,CHALT	;IF THIS IS ESCAPE,
	JRST	DEL1CE		;ECHO AS DOLLAR
	MOVEI	T3,"^"		;GET AN UPARROW TO ECHO
	PUSHJ	P,DEL1EX	;SHOW ITS DELETION
	POP	P,T3		;RESTORE CONTROL CHARACTER
	TRC	T3,100		;CONVERT TO PRINTABLE FORM
	MOVEI	P4,1		;WIDTH OF ONE
	PJRST	DEL1EX		;ECHO THIS AND RETURN

DEL1CE:	POP	P,T3		;RESTORE THE ESCAPE
	MOVEI	T3,"$"		;GET ITS DOLLARSIGN
	PJRST	DEL1EX		;ECHO IT AND RETURN

DEL1T:	SCNOFF			;FIGHT RACES
	SKIPN	T4,LDBBKU(U)	;START FROM LAST BREAK
	MOVE	T4,LDBTIT(U)	;CLOSE ENOUGH
	LDB	P4,LDPPRP	;ASSUME THIS WAS THE PROMPT
	EXCH	T4,LDBECT(U)	;STORE NEW START POINTER, REMEMBER END
DEL1T1:	CAMN	T4,LDBECT(U)	;HIT THE END YET?
	JRST	DEL1T3		;YES, QUIT COUNTING
	LDCHK	T3,LDBECT(U),DEL1T3	;GET ANOTHER CHARACTER
	TRNE	T3,CK.NIS	;REAL CHARACTER?
	JRST	DEL1T1		;NO, IGNORE
	ANDI	T3,CK.CHR	;TRIM FUNNY BITS
	CAIE	T3,11		;A TAB?
	JRST	DEL1T2		;NO, GO COUNT NORMAL CHARACTER
	TRZ	P4,7		;YES, CLEAR FRACTIONAL TAB STOP
	ADDI	P4,10		;BUMP TO NEXT TAB STOP
	JRST	DEL1T1		;LOOP OVER LINE CONTENTS
DEL1T2:	MOVE	T1,CHTABL(T3)	;GET CONTROL BITS OF NORMAL CHARACTER
	TRNE	T1,CHUAE	;IF ^X FORM
	ADDI	P4,1		;THEN COUNT THE UPARROW
	AOJA	P4,DEL1T1	;COUNT ANOTHER COLUMN AND LOOP
DEL1T3:	SCNON			;ALLOW OTHERS AGAIN
	MOVEI	T2,10(P4)	;GET NEXT TAB STOP VALUE
	TRZ	T2,7		;BACK OFF TO TAB STOP
	SUBB	T2,P4		;GET COUNT FOR BACKSPACING
	PUSHJ	P,BACKUP	;ADJUST HPOS THAT MANY
	MOVEI	T3," "		;LOAD A SPACE FOR ECHO ROUTINES
	PJRST	DEL1EX		;ECHO DELETION OF (P4) SPACES AND RETURN

DEL1E:	MOVE	T1,CHTABL(T3)	;GET CHARACTER BITS
	MOVSI	T2,LDL8BI	;8-BIT INPUT MODE (DUE TO PROGRAM)?
	TDNN	T2,LDBDCH(U)	;TEST IT
	TLNN	T1,CH2PC	;OR NOT AN EXPANDABLE CHARACTER?
	JRST	DEL1A		;YES, BACK TO NORMAL CASE AFTER ALL
	MOVE	T2,CHREQV-200(T3) ;GET CHARACTER EXPANSION STRING
	TLNN	T2,-1		;THREE CHARACTER EXPANSION?
	AOJA	P4,DEL1E1	;NO, IT'S EXACTLY TWO
	TRNN	T2,767000	;YES, IS ITS MIDDLE A BACKSPACE?
	JRST	[HLRZ	T3,T2	;YES, THE LAST CHARACTER IS ALL WE ECHOED,
		 JRST	DEL1A]	;SO PRETEND THAT'S WHAT WE'RE DELETING
	ADDI	P4,2		;NO, IT'S A THREE-WIDE CHARACTER
DEL1E1:	MOVE	T2,P4		;COPY THE WIDTH
	PUSH	P,T3		;SAVE THE CHARACTER
	PUSHJ	P,BACKUP	;ADJUST HPOS
	POP	P,T3		;RESTORE CHARACTER
	CAIN	P2,METDCR	;IF HARDCOPY ECHO,
	MOVEI	P4,1		;THEN ONLY TYPE THE CHARACTER ONCE (IT EXPANDS)
	PJRST	DEL1EX		;ECHO A (P4) WIDTH DELETION AND RETURN

DEL1Q:	CAIE	P2,METDCR	;IF NOT HARDCOPY ECHO,
	JRST	DEL1Q1		;THEN JUST DELETE BY WIDTH
	MOVE	T2,LDBDCH(U)	;GET CHARACTERISTICS BITS
	PUSH	P,T3		;SAVE THE REAL CHARACTER
	MOVEI	T3,26		;GET AN ^V
	SETZ	T1,		;THIS IS NOT ESCAPE
	TLNN	T2,LDLDLR	;UNLESS USER SUPPRESSED UPARROW ECHO,
	PUSHJ	P,DEL1C1	;ECHO THE ^V
	POP	P,T3		;RESTORE OUR CHARACTER
	PUSHJ	P,SPCHEK	;GET ITS BITS
	TRZ	T3,CK.MET	;CLEAR THE META BIT
	MOVEI	P4,1		;ASSUME A WIDTH OF ONE
	TLNN	T1,CHUAE	;IS IT A CONTROL CHARACTER?
	JRST	DEL1A		;NO, HANDLE LIKE A NORMAL CHARACTER
	MOVE	T2,LDBDCH(U)	;YES, GET DOLLAR BIT AGAIN
	TLNE	T2,LDLDLR	;ARE WE DOING UPARROW ECHO?
	PJRST	DEL1C1		;YES, DO IT
	POPJ	P,		;NO, DON'T BOTHER ME

DEL1Q1:	SETZ	P4,		;ASSUME IT WAS INVISIBLE
	MOVE	T2,LDBDCH(U)	;GET CHARACTERISTICS WORD
	TLNN	T2,LDLDLR	;DID THE ^V ECHO?
	ADDI	P4,2		;YES, COUNT TWO CHARACTERS
	PUSHJ	P,SPCHEK	;GET BITS FOR OUR CHARACTER
	TLNN	T1,CHUAE	;IS IT A CONTROL CHARACTER?
	AOJA	P4,DEL1A	;NO, JUST DELETE (P4) CHARACTERS AND RETURN
	TLNE	T2,LDLDLR	;YES, DID IT ECHO?
	POPJ	P,		;NO, NOTHING DID, DON'T BOTHER ME
	ADDI	P4,2		;YES, WE ECHOED 4 WIDE
	PJRST	DEL1A		;DELETE (P4) CHARACTERS AND RETURN
;SUBROUTINE TO HANDLE AUTO-CRLF
XMTACR:	MOVSI	T1,LDLCOM	;SEE IF USER AT COMMAND LEVEL
	TDNE	T1,LDBDCH(U)	;AND IF SO,
	POPJ	P,		;IGNORE ACR
	LDB	T4,LDPACR	;GET AUTO-CRLF SETTING
	JUMPE	T4,CPOPJ##	;DO NOTHING IF NOT SET
	PUSHJ	P,HPOS		;GET CURRENT HPOS
	CAIGE	T2,(T4)		;SEE IF HIT MARGIN
	POPJ	P,		;NO, IGNORE
	MOVEI	T1,40		;GET A SPACE AGAIN
	PUSHJ	P,TOPGCB	;READ OUR STATUS BYTE
	TRNE	T2,CC.NSA	;IF NO SPECIAL ACTION,
	POPJ	P,		;IGNORE
	TRC	T3,040^!015	;CONVERT TO CR
	DPB	T3,LDBECT(U)	;STUFF BACK FOR READERS
	POPJ	P,		;RETURN AFTER MUNGING

;ROUTINE TO CHECK IDLENESS WHEN OUT OF CHARACTERS TO ECHO
ZAPECH:	SETZM	LDBECC(U)	;FIX UP
	MOVE	T2,LDBTIP(U)	;MESSED UP
	CAME	T2,LDBECT(U)	;CHECK POINTERS
	PUSHJ	P,RCDSTP	;SOMETHING IS WRONG
	JRST	XMTIDL

;SUBROUTINE TO CHECK IF WAKEUP SHOULD OCCUR BECAUSE OF NUMBER OF CHARS

CHKTIB:	CAILE	T2,TTIBRK##	;EXCEEDED ARBITRARY MAX?
	JRST	CPOPJ1##	;YES, ALWAYS BREAK
CHKTIF:	SKIPL	LDBBKB(U)	;BREAK SET SPECIFIED?
	POPJ	P,		;NO, DON'T BREAK BECAUSE OF NUMBER OF CHARS
	PUSH	P,T2		;SAVE POSITION
	LDB	T2,LDPFWD	;GET FIELD WIDTH
	SKIPN	T2		;WIDTH SET?
	MOVEI	T2,1		;NO, USE ONE
	CAMG	T2,(P)		;AT END OF FIELD
	AOS	-1(P)		;YES, WAKEUP
	JRST	T2POPJ##	;RETURN

ECHBRK:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  PJRST RCVWAK		;NO. WAKE JOB IF ANY.
	PJRST	COMSET		;YES. SET COMMAND REQUEST.

RCVWKQ:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  PJRST	RCVWAK		;NO. WAKE JOB.
	POPJ	P,0		;YES. DON'T MAKE COMMAND FOR LDLBKA


;ROUTINE TO QUEUE FOR A CHANGE HARDWARE PARAMETER MESSAGE

SETCH1:	AOS	(P)		;SKIPPING SETCHP
SETCHP::SE1ENT			;ENTER SECTION 1
	MOVEI	T1,L1RCHP
	IORM	T1,LDBBYT(U)	;MARK THAT ISRCHP MUST BE CALLED
	PJRST	TOPOKE		;ADD TO QUEUE

CLRIRM::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,LPLIRM	;IRMA BIT
	ANDCAM	T1,LDBPAG(U)	;CLEAR IN LDB
	POPJ	P,		;RETURN
TOREQ::	SE1ENT			;ENTER SECTION 1
	MOVSI	T1,LDLIDL
	IORM	T1,LDBDCH(U)
;;	PJRST	TOPOKE

;ROUTINE TO PLACE AN LDB INTO THE START OUTPUT QUEUE.  SCANNED
;AT CLOCK LEVEL ONCE PER TICK.
;CALL
;	MOVEI	U,LDB ADDRESS
;	PUSHJ	P,TOPOKE
;	<RETURN HERE ALWAYS>
;USES T1,T2

TOPOKE::SE1ENT			;ENTER SECTION 1
	MOVEI	T1,LDRPTY	;PTY BIT
	TDNE	T1,LDBDCH(U)	;IS THIS A PTY?
	PJRST	PTYPE##		;YES, DON'T QUEUE OUTPUT
	MOVSI	T1,LPLPOK	;OUTPUT BEING STARTED BIT
	TDNE	T1,LDBPAG(U)	;CHECK BEFORE WE GET THE INTERLOCK
	POPJ	P,		;  JUST FOR EFFICIENCY'S SAKE
	SCNOFF			;NO INTERRUPTS
	TDNE	T1,LDBPAG(U)	;...
	JRST	SONPPJ		;YES, BY SOMEONE ELSE
	SKIPL	LDBDCH(U)	;LINE ALREADY ACTIVE?
	JRST	[MOVEI T2,L1RCHP ;YES, DON'T QUEUE UNLESS
		 TDNN T2,LDBBYT(U) ;A A HARDWARE PARAMETER HAS CHANGED
		 JRST SONPPJ
		 JRST .+1]
	IORM	T1,LDBPAG(U)	;NO.  INDICATE LDB IS GOING INTO THE QUEUE
	HLRZ	T1,LDBQUH(U)	;GET THE QUEUE HEADER ADDRESS
	MOVE	T2,1(T1)	;LAST ENTRY OF CURRENT QUEUE
	SKIPN	T2		;NON-NULL QUEUE?
	MOVEI	T2,-LDBQUE(T1)	;POINT TO QUEUE HEADER WORD
	MOVEM	U,LDBQUE(T2)	;STORE ADDRESS OF ARGUMENT LDB AT END
	MOVEM	U,1(T1)		;UPDATE LATEST ENTRY
	SETZM	LDBQUE(U)	;MAKE SURE LIST TERMINATESS
	JRST	SONPPJ		;ALLOW INTERRUPTS AND RETURN
;ROUTINE TO TAKE AN LDB OUT OF THE 'START OUTPUT' QUEUE
;CALLED FROM DEVICE DRIVERS TO FIND LINES THAT ARE WAITING TO DO OUTPUT.
;CALL
;	MOVE	T1,ADDRESS OF LIST HEADER
;	PUSHJ	P,TOTAKE
;	  <IF EMPTY QUEUE>
;	<LDB ADDRESS IN U>
;
;USES T2.

TOTAKE::SE1ENT			;ENTER SECTION 1
	SKIPN	0(T1)		;IF QUEUE IS EMPTY NOW
	POPJ	P,		; AVOID INTERLOCK
	SCNOFF
TOTAK1:	MOVSI	T2,LPLPOK	;HAS OUTPUT BEEN STARTED?
	MOVE	U,0(T1)		;POINT TO FIRST LDB IN LIST
	JUMPE	U,SONPPJ	;IF NONE
	ANDCAM	T2,LDBPAG(U)	;CLEAR 'IN QUEUE' BIT
	SKIPN	T2,LDBQUE(U)	;NEXT LDB IN LIST, END OF LIST?
	SETZM	1(T1)		;YES, CLEAR TAIL POINTER TOO
	MOVEM	T2,0(T1)	;ADVANCE LIST
	SKIPGE	LDBDCH(U)	;IS OUTPUT ALREADY GOING?
	JRST	SONPJ1		;LINE IDLE, GIVE GOOD RETURN
	MOVEI	T2,L1RCHP
	TDNN	T2,LDBBYT(U)	;NEED TO SEND CHANGE PARAMETER MESSAGE?
	JRST	TOTAK1		;NO, SKIP TO NEXT
;	JRST	SONPJ1		;YES, RETURN THE LINE
;
;ROUTINE TO ALLOW SCANNER INTERRUPTS AGAIN AND SKIP RETURN

SONPJ1::AOSA	0(P)		;SKIP RETURN
SONTPJ::POP	P,T1		;ADJUST THE STACK (RESTORE T1?)
SONPPJ::SCNON			;ALLOW SCANNER INTERRUPTS
	POPJ	P,		;AND RETURN
	SUBTTL	RECEIVE INTERRUPT ROUTINE

;HERE FROM DEVICE-DEPENDENT INTERRUPT ROUTINE ON A RECEIVE INTERRUPT.
;AT THIS POINT, T3(28-35) HAS RECEIVED CHARACTER, U HAS PHYSICAL LINE #
;AS INDEX INTO LINTAB

RECINT::SE1ENT			;ENTER SECTION 1
	MOVE	U,LINTAB##(U)	;LOAD LDB ADDRESS
RECPTY::MOVEI	T2,L1RMIF	;MIC INTERLOCK FLAG
	SCNOFF			;LOCK OTHER CPU
	TDNE	T2,LDBBYT(U)	;IS MIC TYPING ON THIS LINE?
	JRST	RECQUE		;LINE INTERLOCKED, QUEUE THE CHARACTER
	IORM	T2,LDBBYT(U)	;SET THE INTERLOCK BIT
	SCNON			;ALLOW INTERRUPTS
	PUSHJ	P,RECINI	;PROCESS THE INTERRUPT
RECINU:	SCNOFF			;SIGH. GOTTA DO THIS INTERLOCKED
	SKIPE	RCQCNT		;ANY CHARACTERS QUEUED UP?
	PJRST	RECUNQ		;YES, TRY TO UN-QUEUE THEM
	MOVEI	T2,L1RMIF	;"MIC" INTERLOCK FLAG
	ANDCAM	T2,LDBBYT(U)	;CLEAR INTERLOCK
	JRST	SONPPJ		;RELEASE SCNSER AND DISMISS INTERRUPT
;RECQUE - QUEUE UP AN INPUT CHARACTER FOR A LINE THAT IS INTERLOCKED
;
;CALLED WITH CHAR IN T3 AND SCNSER INTERLOCK

RECQUE:	AOS	RCQHIT		;COUNT TOTAL INTERLOCKS HIT
	AOS	T2,RCQPTR	;ADVANCE THE QUEUE PUTTER
	CAIG	T2,RCQEND	;FALLEN OFF THE END?
	JRST	.+3		;NO, STILL WITHIN THE QUEUE BUFFER
	MOVEI	T2,RCQBEG	;YES, WRAP THE PUTTER AROUND TO THE START
	MOVEM	T2,RCQPTR	;OF THE QUEUED CHARACTER BUFFER
	CAMN	T2,RCQTKR	;HIT THE TAKER YET?
	JRST	RECQU9		;YES, BUTTS, GO FALL OVER
	HRRZM	T3,(T2)		;NO, STILL ROOM, STASH THE CHARACTER
	HRLM	U,(T2)		;AND THE LDB WHICH OWNS IT
	AOS	RCQCNT		;COUNT UP CHARACTERS QUEUED
	JRST	SONPPJ		;AND GET OUT OF HERE

;CHARACTER QUEUE FULL

RECQU9:	SOS	RCQPTR		;BACK UP THE PUTTER
	AOS	T2,RQFCNT	;COUNT OF TIMES HERE
	CAIE	T2,1		;FIRST TIME HERE
	JRST	SONPPJ		;NO, DON'T CLUTTER UP THE DISK SPACE
	STOPCD	SONPPJ,DEBUG,RQF;++ RECINT QUEUE FULL
;RECUNQ - UN-QUEUE THE QUEUED CHARACTERS FROM RECINT
;
;CALLED WITH BOTH SCNSER AND MIC (L1RMIF) INTERLOCK SET

RECUNP:	SCNOFF			;GET SCNSER INTERLOCK
	SKIPG	RCQCNT		;REALLY ANYTHING QUEUED?
	JRST	RECUSZ		;NAW, NOTHING TO DO

;TRY TO PROCESS CHARACTER QUEUE

RECUNQ:	MOVE	T2,RCQTKR	;COPY OF QUEUE TAKER
	ADDI	T2,1		;ADVANCE TO NEXT ENTRY
	CAILE	T2,RCQEND	;FALLEN OFF OF END YET?
	MOVEI	T2,RCQBEG	;YES, WRAP THE TAKER BACK TO THE BEGINING
	SKIPN	T1,(T2)		;GET FIRST ENTRY IN CHARACTER QUEUE
	JRST	RECUNX		;EMPTY, TOSS IT AND LOOK FOR MORE
	HLRZ	T1,T1		;POSITION LDB ADDRESS
	CAIE	T1,(U)		;THE LDB WE'RE INTERESTED IN?
	JRST	RECUSQ		;NO (BLETCH) SCAN THE QUEUE THEN
	PUSH	P,T3		;SAVE ORIGINAL CALLER'S CHARACTER
	HRRZ	T3,(T2)		;GET QUEUED CHARACTER
	SETZM	(T2)		;CLEAR OUT SO WE NEVER SEE IT AGAIN
	MOVEM	T2,RCQTKR	;ADVANCE THE QUEUE TAKER
	SOS	RCQCNT		;ONE LESS CHARACTER IN THE QUEUE

;PROCESS THE QUEUED CHARACTER (L1RMIF STILL SET)

RECUNT:	SCNON			;WE CAN SAFELY ALLOW INTERRUPTS NOW
	PUSHJ	P,RECINI	;PROCESS QUEUED CHARACTER
	POP	P,T3		;RESTORE STACK
	JRST	RECUNP		;AND CHECK REST OF THE QUEUE

;HERE WHEN THE QUEUE STARTS OFF WITH A HOLE

RECUNX:	MOVEM	T2,RCQTKR	;ADVANCE THE QUEUE TAKER
	SOSE	RCQCNT		;COUNT DOWN THE CHARACTERS QUEUED
	JRST	RECUNQ		;AND CHECK THE REST OF THE QUEUE
				;EMPTY, FALL INTO RECUNZ

;JUST EMPTIED THE QUEUE, VALIDITY CHECK IT

RECUNZ:	MOVEI	T2,L1RMIF	;"MIC" INTERLOCK
	ANDCAM	T2,LDBBYT(U)	;CLEAR LINE INTERLOCK
	MOVE	T2,RCQPTR	;THE QUEUE PUTTER
	CAIGE	T2,RCQBEG	;SOSED AT UNFORTUNATE MOMENT?
	MOVEI	T2,RCQEND	;YES, REALLY STILL AT END THEN
	CAMN	T2,RCQTKR	;PUTTER MATCH TAKER?
	JRST	SONPPJ		;YES, ALL SET, JUST GO AWAY
	STOPCD	.+1,DEBUG,RQD	;++ RECINT QUEUE DISCREPANCY
	MOVE	T2,RCQTKR	;GET THE TAKER
	MOVEM	T2,RCQPTR	;AND MAKE THE PUTTER MATCH
	JRST	SONPPJ		;AND SEE WHAT HAPPENS
;STILL SCNOFF'ED

;HERE WHEN FIRST ENTRY IN RECINT'S QUEUE IS NOT FOR THIS LINE. THE
;QUEUE MUST BE SCANNED FOR CHARACTERS WHICH DO BELONG TO THIS LINE
;IN ORDER TO PRESERVE CHARACTER SYNCHRONY.

RECUSQ:	PUSH	P,RCQCNT	;COUNT OF CHARACTERS QUEUED UP
RECUSS:	SOSG	0(P)		;MORE TO CHECK?
	JRST	RECUSY		;NO, NOTHING FOR THIS LINE, GET OUT
	ADDI	T2,1		;YES, ADVANCE TAKER TO NEXT CANDIDATE
	CAILE	T2,RCQEND	;FALLEN OFF THE END YET?
	MOVEI	T2,RCQBEG	;YES, WRAP AROUND TO THE FRONT
	SKIPN	T1,(T2)		;FETCH COPY OF THIS QUEUE ENTRY
	JRST	RECUSS		;EMPTY ENTRY, CHECK REST OF QUEUE
	HLRZ	T1,T1		;POSITION ADDRESS OF LDB
	CAIE	T1,(U)		;OUR LDB?
	JRST	RECUSS		;NOPE, SKIP THIS ENTRY THEN TOO

;AN EMBEDDED QUEUE ENTRY FOR THIS LINE, GET AND DELETE IT

	MOVEM	T3,0(P)		;SAVE REAL T3 FOR CALLER
	HRRZ	T3,(T2)		;FETCH QUEUED CHARACTER TO BE RECINT'ED
	SETZM	(T2)		;NOTE THE CHARACTER PROCESSED
	JRST	RECUNT		;PROCESS QUEUED CHARACTER

;NOTHING TO DO, RELEASE INTERLOCK AND DISMISS "INTERRUPT"

RECUSY:	POP	P,T1		;UNWIND THE STACK BY 1
RECUSZ:	MOVEI	T2,L1RMIF	;THE "MIC" INTERLOCK FLAG
	ANDCAM	T2,LDBBYT(U)	;CLEAR THE INTERLOCK
	JRST	SONPPJ		;AND RELEASE SCNSER INTERLOCK
;RECINI - DO THE ACTUAL INPUT CHARACTER PROCESSING

RECINI:				;PROCESS ONE INPUT CHARACTER
	AOS	LDBICT(U)	;COUNT INPUT CHARACTERS THIS LINE
	AOS	%SCNRI		;AND INPUT CHARACTERS FOR THE SYSTEM
IFN FTRSP,<AOS	.CPNRI##>	;PER CPU AS WELL

RECINM:	ANDI	T3,CK.CHR!CK.FDE ;JUST 8 BITS OF CHARACTER.
				; CLEAR ANY DEVICE DEPENDENT BITS
IFN FTNET,<			;IF NETWORK
	SKIPGE	LDBREM(U)	;IF THIS IS AN ACTIVE VTM LINE,
	JRST	VTMREC##	;  GO HANDLE NVT CHARS SPECIAL
>
	MOVSI	T1,L1LOFL	;PUT TERMINAL ON LINE
	ANDCAM	T1,LDBOFL(U)	;SINCE SOMEONE IS THERE
	MOVE	T1,LDBDCH(U)	;GET LINE CHARACTERISTICS
	SKIPL	LDBTTW(U)	;ANF-10 KNOWS WHAT IT IS DOING, PROCESS CHAR
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	TRNN	T1,LDRDSD	;IS IT A DATASET LINE?
	JRST	RECINN		;NO.  PROCESS CHARACTER
	LDB	T1,LDPDSC	;GET DATASET TABLE INDEX
	MOVE	T1,DSCTAB##(T1)	;GET DATASET DATA
	TLNE	T1,DSCBLI	;WANT TO IGNORE INTERRUPTS?
	  POPJ	P,		;YES,
RECINN:
	MOVEI	T1,ST.NRT	;THE STAND ALONE (NO REMOTE) BIT
	TDNE	T1,STATES##	;IS THE SYSTEM STAND ALONE?
	JRST	[HRR	T1,LDBDCH(U)	;YES, GET CHARACTERISTICS
		TRNN	T1,LDRDSR	;IS THE TERMINAL REMOTE/DATASET?
		JRST	RECIN1		;NO, LOCAL, ALLOW IT
		HRRZ	T1,LDBDDB(U)	;REMOTE, BUT IS IT ALREADY IN USE?
		JUMPN	T1,RECIN1	;YES, ALLOW IT TO CONTINUE TO WORK
		JRST	BEATIT]		;NO, DUMP IT

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

RECIN1:	SKIPN	LDBIST(U)	;ARE WE DOING SOMETHING SPECIAL?
	JRST	RECIN2		;NO, SKIP OVERHEAD
	PUSHJ	P,RECDCS	;YES, HANDLE IT
	  POPJ	P,		;DON'T STORE
RECIN2:	MOVE	T1,LDBOST(U)	;GET STATE BITS IN LH.
	TLNE	T1,LOLPIM	;PIM MODE?
	JRST	REPIM		;YES, GO TO PIM CODE
	MOVE	T1,LDBDCH(U)	;CARRY DEVICE BITS IN LH.
	SKIPG	TTFREN##	;ANY SPACE FOR CHARACTERS?
	JRST	RCHLT1		;NO. SHUT IT DOWN.
	TLNN	T1,LDLIMI	;IN IMAGE INPUT MODE?
	JRST	RECIN3		;NO.
	MOVEI	T1,IMGTIM	;YES. RESET TIMEOUT FIELD TO MAX
	DPB	T1,LDPTIM	; ..
	TRO	T3,CK.IMG	;MARK IN NINTH BIT.
	JRST	RECINA		;AND GO STORE IN BUFFER. NO BREAK.
RECIN3:	SKIPL	LDBBY3(U)	;NEED TO TOGGLE DEFERRED ECHO?
		.CREF	L3LDMC		;SHOW BIT WE TESTED
	JRST	RECIN4		;NO, GO CHECK FOR SPECIAL CHARACTERS
	PUSH	P,T3		;YES, SAVE INCOMING CHARACTER
	MOVEI	T3,L1RDEM	;THE CURRENT (DESIRED) STATE OF L1LDEM
	TDNN	T3,LDBBYT(U)	;IS IT ON?
	SKIPA	T3,[MC.DEF]	;NO, SET TO TURN IT OFF
	MOVEI	T3,MC.DEN	;YES, SET TO TURN IT ON
	PUSHJ	P,RECINA	;STORE IN INPUT BUFFER
	MOVSI	T3,L3LDMC	;THE FLAG THAT GOT US HERE
	ANDCAM	T3,LDBBY3(U)	;CLEAR IT TO AVOID THIS CODE NEXT TIME THROUGH
	POP	P,T3		;RESTORE CHARACTER TO BE PROCESSED
RECIN4:	SKIPL	LDBATR(U)	;EIGHT-BIT TERMINAL?
	TRZ	T3,CK.PAR	;NO, CLEAR PARITY FOR SEVEN-BIT ASCII
	PUSHJ	P,RECMAP	;MAP CHARACTERS IF NECESSARY
	  POPJ	P,		;DON'T STORE
IFN FTPI,<
	PUSHJ	P,RECOOB	;SEE IF AN OUT-OF-BAND CHARACTER OF SOME SORT
	  POPJ	P,		;YES, AND COMPLETELY PROCESSED
>
RECIN5:	PUSHJ	P,SPCHEK	;SEE IF IT'S SPECIAL. SET T1 UP.
	  JRST RECINA		;NON-SPECIAL. GO STORE
	TLNE	T1,CHRIA	;DOES THIS CHAR NEED SPECIAL RCV HANDLING?
	TLNN	T1,CHNDFR	;CAN CHARACTER BE DEFERRED?
	JRST	RECINA		;YES, JUST STORE NORMALLY FOR NOW
	PUSHJ	P,(T1)		;CALL CHARACTER'S SPECIAL PROCESSOR
	  POPJ	P,		;DON'T STORE RETURN
				;FALL INTO ORDINARY CHAR HANDLER
;HERE WITH T1=CHARACTER BITS (LH=0 IF NONE), T3=CHARACTER + CK.??? BITS

RECINA:	MOVE	T2,LDBTIC(U)	;COUNT CHARACTERS LINE HAS INPUT
	ADD	T2,LDBECC(U)	;PLUS LEFT TO ECHO
	PUSH	P,T1		;SAVE CHARACTER BITS
	CAIG	T2,TTIWRN##	;TIME TO WARN HIM?
	JRST	RWARNX		;NO, STUFF CHARACTER INTO CHUNKS
	CAIGE	T2,TTIMAX##	;IF HE IS WAY OVER, OR
	SKIPG	TTFREN##	;WE ARE OUT OF CHUNKS
	JRST	RECHLT		;THROW AWAY THE INPUT CHARACTER
	PUSHJ	P,PTBTCH##	;CHECK IF OLD PTY OR BATCH
	  JRST	RWARNX		; CAN'T SEND XOFF
	PUSHJ	P,SNDXOF	;SEND XOFF
RWARNX:	SCNOFF
	STCHK	T3,LDBTIP(U),RECINE  ;STORE CHARACTER
	AOS	LDBECC(U)	;COUNT CHARACTER TO ECHO
	POP	P,T1		;RESTORE T1
	TLNE	T1,CHBRK!CHCRET	;BREAK CHARACTER (OR LIKELY TO BECOME ONE)?
	PUSHJ	P,SETBKI	;YES, NOTE PLACE FOR RIDLN
	SCNON
	SETZ	S,		;FOR RECIN6
RECIN6:	TLNN	T1,CHCNC	;IS THIS CHARACTER A CONTROL C?
	TLO	S,L2LCCS	;NO. PREPARE TO CLEAR L2LCCS BIT
	TRNN	T3,CK.IMG	;IF NOT A QUOTED CHARACTER,
	TRNN	T3,CK.MET	;SKIP THIS IF A META CHARACTER
	ANDCAM	S,LDBBY2(U)	;CLEAR DELETE AND CONTROL C FLAGS
IFN FTPI,<
	PUSHJ	P,TORCCT	;GET INPUT COUNT
	CAIE	T1,1		;ONLY DO THE FOLLOWING IF IT JUST WENT NON-ZERO
	PJRST	TOPOKE		;OTHERWISE JUST GET ECHO STARTED
	HRRZ	F,LDBDDB(U)	;GET DDB POINTER
	JUMPE	F,TOPOKE	;SKIP PSI IF NONE
	SKIPE	DEVPSI(F)	;IF WANTING INTERRUPTS,
	PUSHJ	P,PSIAVL##	;WARN THAT INPUT IS AVAILABLE
> ;END IFN FTPI
	PJRST	TOPOKE		;QUEUE TO GET ECHO STARTED

RECINE:	POP	P,T1		;ADJUST STACK
	SCNON			;RELEASE TERMINAL SERVICE INTERLOCK
	MOVSI	S,L2LCCS	;CRUFTY BIT
	JRST	RECIN6		;RETURN, CLEARING CRUFTY BIT
;ROUTINE TO REMEMBER THE BREAK CHARACTER POSITION IN LDBBKU

SETBKU:	MOVE	T2,LDBECT(U)	;LOCATION OF INPUT PUTTER
	MOVEM	T2,LDBBKU(U)	;SAVE IT
	POPJ	P,


;ROUTINE TO REMEMBER THE BREAK CHARACTER POSITION IN LDBBKI

SETBKI:	MOVE	T2,LDBTIP(U)	;LOCATION OF INPUT PUTTER
	MOVEM	T2,LDBBKI(U)	;SAVE IT
	POPJ	P,
;HERE TO SEE IF ANY INPUT CHARACTERS NEED TO BE MAPPED

RECMAP:	MOVSI	T2,LMLSSE	;SWITCH-SEQUENCE ENABLED BIT
	TDNN	T2,LDBCHM(U)	;IS IT?
	JRST	RECMP1		;NO, DON'T COMPARE AGAINST IT
	MOVEI	T2,LISSWI	;PRE-SET INPUT STATE FOR SWITCH SEQUENCE
	LDB	T1,LDPSW1	;GET SWITCH-SEQUENCE ONE
	XOR	T1,T3		;FORM DIFFERENCES
	TRNN	T1,CK.CHR	;IS THIS IT?
	PJRST	SETDCS		;YES, SET FOR RECDCS AND GIVE DON'T-STORE RETURN
RECMP1:	AOS	(P)		;NO, FROM HERE ON WE'LL SKIP-RETURN
	MOVE	T1,T3		;GET A COPY OF THE CHARACTER
	ANDI	T1,CK.CHR	;KEEP ONLY USEFUL BITS
	LDB	T2,LDPUNP	;GET THE UNPAUSE CHARACTER
	CAMN	T2,T1		;IS THIS IT?
	JRST	RECMPQ		;YES, STORE AS ^Q
	LDB	T2,LDPESC	;NOT UNPAUSE, GET THE ESCAPE CHARACTER
	CAMN	T2,T1		;IS THIS IT?
	JRST	RECMPA		;YES, STORE AS ESCAPE
;ADD ANY NEW MAPPED CHARACTER TESTS HERE
	POPJ	P,		;NOT TO BE MAPPED, RETURN IT UNCHANGED

RECMPQ:	SKIPA	T1,["Q"-100]	;UNPAUSE == ^Q
RECMPA:	MOVEI	T1,STDALT	;ESCAPE == STDALT
	DPB	T1,[POINT 8,T3,35] ;UPDATE RECEIVED CHARACTER
	POPJ	P,		;RETURN THE MAPPED VERSION
;HERE TO CHECK OUT THE POSSIBILITY OF HAVING AN OUT-OF-BAND CHARACTER

IFN FTPI,<
RECOOB:	TRNN	T3,CK.MET	;IS IT NOT A FUNCTION CHARACTER?
	SKIPL	LDBBKB(U)	;AND IS SPECIAL-CHARACTER MODE ENABLED?
	JRST	CPOPJ1##	;NO, GIVE CONTINUE RETURN
	MOVE	T1,T3		;YES, COPY THE CHARACTER
	ANDI	T1,CK.CHR	;KEEP ONLY RELEVANT BITS
	PUSHJ	P,TOPGCB	;GET THE CORRESPONDING BITS IN T2
	TRNN	T2,CC.OOB	;IS IT AN INTERRUPT CHARACTER?
	JRST	CPOPJ1##	;NO, GIVE CONTINUE RETURN
	TRNN	T2,CC.CLR	;IS IT A 'CLEAR' CHARACTER?
	JRST	RECOB2		;NO, DON'T HANDLE AS ONE
	TRNN	T2,CC.DFR	;IS IT DEFERRED CLEAR?
	JRST	RECOB1		;NO, HANDLE IMMEDIATE CLEAR
	MOVEI	T2,LISDCI	;LINE INPUT STATE=DEFERRED-CLEAR INTERRUPT
	PJRST	SETDCS		;SETUP DEFERRED CHARACTER STATE AND RETURN
				;  (NON-SKIP RETURN BECAUSE DONE WITH THIS
				;   CHARACTER FOR NOW)
RECOB1:	PUSHJ	P,TSETI1	;CLEAR TYPEAHEAD
	JRST	RECOB4		;GO ENTER CHARACTER IN OOB STREAM AND RETURN NON-SKIP
RECOB2:	TRNE	T2,CC.DFR	;IS THIS A 'HELLO' OOB?
	AOS	(P)		;YES, GIVE SKIP RETURN AS WELL AS OOB PSI
RECOB4:	SCNOFF			;MUST HAVE INTERLOCK
	HRRZ	T1,LDBDDB(U)	;GET DDB (IF ANY)
	JUMPE	T1,SONPPJ	;IT WENT AWAY
	EXCH	T1,F		;FOR BYTE POINTER
	PUSH	P,J		;PRESERVE FOR CALLER
	LDB	J,PJCHN##	;GET THE TARGET TO SIGNAL
	EXCH	T1,F		;RESTORE F
	JUMPE	J,JPOPJ##	;GIVE UP IF NO JOB/JCH FOR PSI
	STCHK	T3,LDBOOP(U),RECOB5	;STORE THE CHARACTER FOR PSISER
	AOS	LDBOOC(U)	;COUNT IT UP
	SCNON			;RETURN INTERLOCK
	SIGNAL	C$OOB		;RAISE THE INTERRUPT FOR THE USER
	  TRNA			;DON'T UNREAD IF DOESN'T WANT
	PUSHJ	P,SETUNR	;LIGHT UNREAD BIT
	JRST	JPOPJ##		;RESTORE J AND RETURN TO RECIN3

;HERE IF AN ERROR OCCURS TRYING TO STORE THE OOB CHARACTER
RECOB5:	POP	P,J		;RESTORE J
	JRST	SONPPJ		;GIVE UP
> ;END OF IFN FTPI
;HERE TO HANDLE DEFERRED CHARACTERS ON NEXT RECEIVE

RECDCS:	LDB	T2,LDPDCS	;GET THE REASON CODE
	JUMPE	T2,RECDC1	;PROCEED WITH CHARACTER IF NONE
	SETZ	T4,		;GET A ZERO
	DPB	T4,LDPDCS	;CLEAR STATUS (IN CASE IT NEEDS TO BE SET AGAIN)
	PUSHJ	P,@DCSDSP(T2)	;CALL THE ROUTINE APPROPRIATE TO OUR STATE CODE
	  POPJ	P,		;RETURN BLINDLY ON IGNORE RETURN
	JRST	RECDCS		;CHECK FOR NEW STATUS ON CONTINUE RETURN

RECDC1:	SETZM	LDBIST(U)	;CLEAR TO SPEED UP RECINT
	JRST	CPOPJ1##	;GIVE CONTINUE RETURN

DCSDSP:	IFIW	CPOPJ##		;STATE ZERO NEVER USED
	IFIW	DCSDCI		;DEFERRED CLEAR INTERRUPT
	IFIW	DCSQOT		;QUOTED CHARACTER
	IFIW	DCSSWI		;SWITCH SEQUENCE

DCSDCI:	LDB	T2,LDPDTC	;GET THE PREVIOUS CHARACTER
	XOR	T2,T3		;SEE WHAT'S DIFFERENT
	SKIPL	LDBATR(U)	;CHECK 8-BIT
		.CREF	LAL8BT	;SYMBOLIC REFERENCE
	TRZ	T2,CK.PAR	;IGNORE PARITY IF 7-BIT
	TRNN	T2,CK.CHR	;ARE THEY THE SAME?
	PJRST	RECOB1		;YES, THIS IS NOW A CLEAR OOB
	XOR	T2,T3		;NO, RESTORE PREVIOUS
	PUSH	P,T3		;AND THE CHARACTER
	MOVE	T3,T2		;MOVE PREVIOUS CHARACTER
	PUSHJ	P,RECIN5	;RECEIVE AS SOMETHING OTHER THAN OOB
	POP	P,T3		;RESTORE NEW CHARACTER
	JRST	CPOPJ1##	;GIVE SKIP RETURN

DCSQOT:	LDB	T2,LDPDTC	;GET THE PREVIOUS CHARACTER
	ANDI	T2,CK.FDE	;WANT ONLY THIS BIT
	AND	T2,T3		;KEEP ONLY IF BOTH WERE ECHOED
	ANDI	T3,CK.CHR	;MASK DOWN TO CHARACTER ALONE
	TRO	T3,CK.IMG!CK.MET(T2) ;TURN ON QUOTING BITS (AND MAYBE CK.FDE)
	PJRST	RECIN5		;STORE AND RETURN

DCSSWI:	LDB	T2,LDPDTC	;GET THE PREVIOUS CHARACTER
	XOR	T2,T3		;SEE WHAT'S DIFFERENT
	SKIPL	LDBATR(U)	;IF 7-BIT,
		.CREF	LAL8BT
	TRZ	T2,CK.PAR	;TRUNCATE
	TRNN	T2,CK.CHR	;ARE THEY THE SAME?
	PJRST	DCSSW2		;YES--GIVE IT UNLESS OTHERWISE SPECIAL
	LDB	T2,LDPSW2	;NO, GET SEQUENCE'S SECOND CHARACTER
	XOR	T2,T3		;SEE WHAT'S DIFFERENT
	SKIPL	LDBATR(U)	;IF 7-BIT,
		.CREF	LAL8BT
	TRZ	T2,CK.PAR	;TRUNCATE
	TRNN	T2,CK.CHR	;ARE THEY THE SAME?
	JRST	DCSSW1		;YES, WE HAVE A BINGO
	PUSH	P,T3		;NO, MUST DELIVER BOTH.  SAVE CURRENT
	LDB	T3,LDPDTC	;GET FIRST PORTION AGAIN
	PUSHJ	P,DCSSW2	;DELIVER IT AS APPROPRIATE
	POP	P,T3		;RESTORE CURRENT
	JRST	CPOPJ1##	;GIVE CONTINUE RETURN

DCSSW1:	PUSH	P,T3		;PRESERVE ACTUAL SW2 RECEIVED
	MOVEI	T3,CK.MET	;META FLAG USED FOR NXTOOB
	PUSHJ	P,RECOB4	;STORE AS HELLO OOB
	LDB	T3,LDPDTC	;GET ACTUAL CHARACTER DEFERRED
	PUSHJ	P,SPCHEK	;GET ITS BITS
	  TRN			;IGNORE SKIP RETURN
	PUSHJ	P,RECINA	;STORE AS NORMAL
	POP	P,T3		;RESTORE RECEIVED CHARACTER
	PUSHJ	P,SPCHEK	;GET ITS BITS
	  TRN			;IGNORE SPECIAL RETURN
	PJRST	RECINA		;STORE THIS ONE TOO AND RETURN

DCSSW2:	PUSHJ	P,RECMP1	;MAP IF NECESSARY
	  TRNA			;PROPAGATE DON'T STORE RETURN
IFN FTPI,<
	PUSHJ	P,RECOOB	;SEE IF IT'S OUT-OF-BAND
	  TRNA			;DON'T STORE
>
	PUSHJ	P,RECIN5	;STORE AS NORMAL
	POPJ	P,		;RETURN TO HANDLE NEXT CHARACTER

;HERE TO SET UP DEFERRED CHARACTER STATUS FOR SWITCH SEQUENCE, QUOTING, AND OOB

SETDCS:	DPB	T2,LDPDCS	;STORE REASON CODE
	DPB	T3,LDPDTC	;DEFERRING THIS CHARACTER (IN CASE NEEDED)
	POPJ	P,		;RETURN
;HERE ON RECEIVE INTERRUPT OF A CONTROL-A CHARACTER

IFN	FTMIC,<			;IF UNDER MIC CONTROL THEN ^A = ^C
RICA:	SKIPE	LDBMIC(U)	;GIVE NORMAL RETURN IF NOT UNDER MIC CONTROL
	PUSHJ	P,MICCHK	;DOES MIC WANT TO HEAR FROM US?
	  JRST	CPOPJ1##	;NO, GIVE 'NORMAL' RETURN
	;PJRST	RICC		;YES, FALL INTO ^C ACTION ROUTINE
> ;END IFN FTMIC


;HERE ON RECEIVE INTERRUPT OF A CONTROL-C CHARACTER

RICC:	PUSH	P,T1		;SAVE CHARACTER BITS
IFN	FTMIC,<			;IF MIC
	SKIPE	T1,LDBMIC(U)	;IS MIC RUNNING FOR US?
	PUSHJ	P,MICRIC	;YES - EXTRA GOODIES
> ;END OF IFN MIC
	PUSH	P,T3		;RIDLN CLOBBERS T3
	PUSHJ	P,RIDLN		;DO THE CONTROL-U FUNCTION
	POP	P,T3		;RECOVER ^C FOR ECHO
	HRRZ	F,LDBDDB(U)
	JUMPE	F,RICC2
	LDB	J,PJOBN##
	LDB	T1,LDPDEB	;DEFERRED ECHO BITS
	DPB	T1,JBYDEB##	;SAVE IN JOB TABLE
RICC2:	MOVSI	T1,L2LCCS	;SEE IF SECOND CONTROL C
	TDNN	T1,LDBBY2(U)	; ..
	JRST	RICC1		;NO
	MOVSI	T1,LOLSTP+LOLSSO;YES - CLEAR STOP BIT
	ANDCAM	T1,LDBOST(U)
IFN FTKL10,<
	HRRZ	T1,LDBISR(U)	;GET ISR DISPATCH
	CAIE	T1,TTDDSP##	;IS THIS A -20F LINE
	JRST	RICC2B		;NO
	MOVSI	T1,LTLXFF	;YES, SET BIT TO INFORM -20F
	IORM	T1,LDBTTD(U)	;
	JRST	RICC2A		;SKIP REMOTE CHECK
>;END IFN FTKL10
RICC2B:
IFN FTNET,<
	SKIPL	LDBTTW(U)	;ANF NETWORK VIRTUAL TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	JRST	RICC2A		; NO, DON'T SET LRRXFF
	MOVEI	T1,LRRXFF	;TELL FE ABOUT XON/XOFF STATUS
	IORM	T1,LDBREM(U)	;
>;END IFN FTNET
RICC2A:	PUSHJ	P,CNCCHK	;YES. AM I ALLOWED TO BELIEVE THE CONTROL-C?
	  JRST RICC1		;SLAVE, OR NOT SECOND. JUST STORE
	PUSHJ	P,TTHALT	;JACCT AND TWO ^C^C
	HRRZ	F,LDBDDB(U)	;GET ATTACHED JOB
	JUMPE	F,RICC3		;MAKE SURE THERE IS ONE
	MOVE	T1,DEVMOD(F)	;IS OWNING JOB ATTACHED TO TERMINAL,
	TLNE	T1,TTYATC	;OR JUST USING TERMINAL AS IO DEVICE?
	JRST	RICC3		;ATTACHED. OK TO DO CONTROL C
	MOVEI	S,IODERR	;NOT ATTACHED
	IORB	S,DEVIOS(F)	;GIVE JOB AN ERROR BIT
	PUSHJ	P,TTWAKE	;AND WAKE IT UP
	SETZM	DEVNAM(F)	;MAKE IT INVISIBLE TO DEVSRC
	PUSH	P,U		;SAVE U IN CASE DDB IS KILLED
	PUSHJ	P,PTYDET	;GET LINE FREE OF DDB
	POP	P,U		;RESTORE U
RICC3:	POP	P,T1		;RESTORE STACK LEVEL
	PUSHJ	P,TSETI1	;FORCE ACTION. CLEAR BUFFERS
	PUSHJ	P,TSETBO	;BOTH INPUT AND OUTPUT. COMCON HAS
				; BEEN FLAGGED BY CNCCHK
	MOVEI	T1,JS.NTO	;PARTIAL BUFFER REMAINING
	SKIPE	F		;MAKE SURE THERE WAS A DDB (ELSE JOB# IS JUNK)
	ANDCAM	T1,JBTSTS##(J)	;CLEAR BIT
	MOVE	T2,FILXCP	;GET ^C ECHO
	PUSHJ	P,SETFLE	;PUT INTO ECHO STREAM NOW (SO TYPES BEFORE DOT)
	POPJ	P,		;DISCARD CHARACTER

RICC1:	MOVSI	T1,L2LCCS	;SET "^C LAST IN" BIT
	IORM	T1,LDBBY2(U)	;NOT SECOND. STORE BIT.
RICC5:	POP	P,T1		;RESTORE CHARACTER FLAGS
	JRST	CPOPJ1##	;AND TREAT AS RECEIVED CHARACTER
;HERE ON RECEIPT OF A ^D CHARACTER

RICD:	MOVEI	T1,JS.BPT	;GET THE BREAKPOINT ENABLED BIT
	LDB	T2,LDPLNO	;GET LINE NUMBER
IFE FTMP,<CAIE T2,TCONLN##>
IFN FTMP,<
	CAILE	T2,FRCLIN##	;IS IT A CTY?
	CAILE	T2,TCONLN##	;...
>
	JRST	RICD1		;NO
	TDNN	T1,JBTSTS##+0	;AND SOMEONE TYPE A "SET EDDT ON" COMMAND?
	JRST	RICD1		;NO
	MOVEM	17,CDSAV+17	;SAVE 17
	MOVEI	17,CDSAV	;PLACE TO SAVE ACS
	BLT	17,CDSAV+16	;SAVE THEM
	XCT	.CPDDT##	;ENTER EDDT (MAYBE)
	MOVSI	17,CDSAV	;RESTORE ALL ACS
	BLT	17,17		;AND
CDPAT::	POPJ	P,		;PATCH TO JFCL TO PASS ^D TO COMCON

;HERE FOR RANDOM "TIMESHARING" ^D - TRY TO FORCE A .BPT COMMAND

RICD1:	HRRZ	F,LDBDDB(U)	;GET DDB
	JUMPE	F,CPOPJ1##	;MAKE SURE THERE IS ONE
	LDB	T2,PJOBN##	;GET JOB NUMBER
	JUMPE	T2,CPOPJ1##	;CAN'T BE THE NULL JOB
	TDNN	T1,JBTSTS##(T2)	;IS JS.BPT TURNED ON?
	JRST	CPOPJ1##	;NO
	MOVEI	T1,TTFCXB	; FORCE A .BPT COMMAND
	PJRST	TTFORC		;AND LET COMCON WORRY ABOUT IT


	$LOW			;MAKE CD ADDRESSABLE BEFORE HIGHIN REACHED
CDSAV:	BLOCK	20		;PLACE TO SAVE ACS AT CD BREAKPOINT
	$HIGH
;HERE ON CONTROL H (BACKSPACE) TO DETERMINE HOW TO TREAT
;IN THE VARIOUS CASES LIKE APL ETC.

RIBSP:	LDB	T2,LDPAPL	;GET APL BIT
	JUMPN	T2,CPOPJ1##	;JUST STORE IN BUFFER (THIS APL)
	JRST	RIDEL		;NOT APL, TREAT LIKE RUBOUT
;HERE ON RECEIPT OF A CARRIAGE RETURN (CONTROL M)

RICM:	MOVEI	T2,L2RXON	;IS XON TRUE?
	TDNE	T2,LDBBY2(U)	;...
	JRST	CPOPJ1##	;YES. NOTHING SPECIAL. STORE.
	TRC	T3,15^!MC.NL	;NO. CHANGE IT TO A NEWLINE
	PJRST	RICRET		;GET NEW BITS AND GIVE CONTINUE RETURN

;HERE ON RECEIVE INTERRUPT OF A CONTROL O

RICO:	MOVEI	T1,LDROSU	;COMPLEMENT STATE OF OUTPUT SUPPRESS BIT
	XORM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
	PUSHJ	P,TSETBO	;CLEAR OUTPUT BUFFER
	MOVE	T2,FILXOP	;GET ^O ECHO
	PUSHJ	P,SETFLE	;SET TO ECHO
	PJRST	TOPOKE		;DISCARD CHARACTER BUT QUEUE THE LINE
;HERE ON RECEIVE INTERRUPT OF A CONTROL Q (XON)

RICQ:	MOVSI	T2,L2LTAP	;HAS TERMINAL TAPE COMMAND BEEN TYPED?
	TDNE	T2,LDBBY2(U)	; ..
	JRST	RICQ7		;YES, HANDLE PAPER TAPE MODE
	MOVE	T2,LDBPAG(U)	;GET TERMINAL PAGING CONTROL
	TLNN	T2,LPLXNF	;PROCESSING XON/XOFF?
	PJRST	CPOPJ1##	;NO, DON'T DO ANYTHING SPECIAL WITH ^Q
	TLNN	T2,LPLSST	;IS TTY SSTOP SET?
	JRST	RICQ2		;NO, ALWAYS CLEAR STOP COUNTER ON ^Q
	MOVSI	T2,LOLSTP	;YES, BE PICKY ABOUT CURRENT STATE
	TDNE	T2,LDBOST(U)	;IS THE LINE STOPPED BY ^S?
	JRST	RICQ3		;YES, JUST CLEAR XOFF, LEAVE STOP COUNTER ALONE
	MOVSI	T2,LOLSSO	;NO. GET STOPPED-BY-SCNSER BIT
	TDNN	T2,LDBOST(U)	;IS TERMINAL OUTPUT "STOP"PED?
	JRST	RICQ4		;NO, IGNORE THE XON
RICQ2:	PUSHJ	P,CLRPCT	;RESET STOP COUNTER
	MOVSI	T2,LOLSTP+LOLSSO;CLEAR STOP BIT(S) FOR TERMINAL OUTPUT
RICQ3:	ANDCAM	T2,LDBOST(U)	;..
	MOVEI	T1,ISRCHP	;TELL REMOTE STATION ABOUT ^Q
	PUSHJ	P,@LDBISR(U)
RICQ4:	PJRST	TOPOKE		;AND GO START OUTPUT AGAIN

RICQ7:	MOVEI	T1,L2RXON	;TURN ON BIT IN LINE CHAR WORD
	IORM	T1,LDBBY2(U)	; ENTER HERE FOR OTHER BITS TOO
	MOVEI	T1,ISRCHP
	PUSHJ	P,@LDBISR(U)	;TELL REMOTE STATION ABOUT THE ^Q.
	PJRST	CHKXN1
IFN FTMIC,<			;IF MIC

;HERE ON RECEIVE INTERRUPT OF CONTROL P (PROCEED)

RICP:	SKIPN	T2,LDBMIC(U)	;IS MIC RUNNING FOR US?
	JRST	CPOPJ1##	;NO - JUST RETURN
	TLO	T2,LDLCHK!LDLMCP;YES - SET UP ^P FLAG
RICB2:	MOVEM	T2,LDBMIC(U)	;PUT WORD BACK
RICB3:	PJRST	MICWAK		;WAKE UP MIC

;HERE ON RECEIVE INTERRUPT OF CONTROL B (BREAK)

RICB:	SKIPN	T2,LDBMIC(U)	;IS MIC RUNNING FOR US?
	JRST	CPOPJ1##	;NO TREAT AS ORDINARY CHAR
	TLO	T2,LDLCHK!LDLMCB;YES - SET UP ^B FLAG
	JRST	RICB2		;AND TREAT AS ^P
> ;END OF IF MIC

;HERE ON A CONTROL T
RICT:	PUSHJ	P,DOCTLT	;PROCESS THE CONTROL-T
	  JRST	CPOPJ1##	;WE WANT TO STORE IT
	  JRST	[PUSHJ P,CLRPCT
		 JRST TTFORC]	;WE WANT TO DO USESTAT
	JRST	RIBUSY		;LINE ALREADY HAS A COMMAND

DOCTLT:	LDB	T2,LDPRTC	;GET BIT FOR TERMINAL RTCOMPAT
	JUMPN	T2,CPOPJ##	;IF IT IS =1 GIVE NON-SKIP RETURN
	MOVE	T2,LDBDCH(U)	;GET DEVICE FLAGS
	TLNE	T2,LDLSLV	;SLAVE?
	POPJ	P,		;YES--DO NOT FORCE CONTROL-T
	HRRZ	F,LDBDDB(U)	;GET LINKED DDB ADDRESS
	JUMPE	F,RICT1		;FORCE COMMAND IF ZERO
	MOVE	T2,DEVMOD(F)	;GET DEVICE BITS
	TLNN	T2,TTYATC	;CONTROLLING TERMINAL?
	JRST	CPOPJ##		;NO--JUST STORE THE CONTROL-T
RICT1:	MOVEI	T1,TTFCXW	;FORCE USESTAT
	SKIPL	LDBCOM(U)	;COMMAND ALREADY PENDING?
	JRST	CPOPJ1##	;NO--GIVE SINGLE SKIP
	JRST	CPOPJ2##	;YES--GIVE DOUBLE SKIP
;HERE ON A CONTROL R

RICR:	LDB	T2,LDPRTC	;RTCOMPATABILITY IN EFFECT?
	JUMPN	T2,CPOPJ1##	;JUMP IF SO, STORE CHARACTER IN THE INPUT BUFFER
	PUSHJ	P,FULLCQ	;COMMAND OR FULL CHARACTER SET?
	  JRST	CPOPJ1##	;YES, STORE CHARACTER
	TRC	T3,<"R"-100>^!MC.RTS	;CHANGE INTO .TYPE BEGIN FUNCTION
	PJRST	RICRET		;GET NEW BITS AND GIVE CONTINUE RETURN
;HERE ON RECEIVE INTERRUPT OF CONTROL S (XOFF)

RICS:	MOVSI	T2,L2LTAP	;HAS TERMINAL TAPE COMMAND BEEN TYPED?
	TDNE	T2,LDBBY2(U)	; ..
	JRST	RICS7		;YES, HANDLE PAPER TAPE MODE
	PUSH	P,T1		;SAVE CHARACTER BITS (FOR RICC5)

	MOVSI	T1,LOLSTP	;GET THE "STOPPED BY ^S BIT"
	PUSHJ	P,STPOIS	;STOP OUTPUT (BUT DON'T RESET STOP COUNTER YET)
	  JRST	RICC5		;TTY NO XONXOF - TREAT AS NORMAL CHARACTER
	MOVE	T1,LDBPAG(U)	;GET PAGING CONTROL
	TLNN	T1,LPLSST	;"TTY SSTOP" SET?
	PUSHJ	P,CLRPCT	;NO, RESET STOP COUNTER (IF ANY)
	JRST	TPOPJ##


RICS7:	MOVEI	T1,L2RXON	;THE "XON IS TRUE" FLAG
	ANDCAM	T1,LDBBY2(U)	;CLEAR IT
	MOVEI	T1,ISRCHP
	PJRST	@LDBISR(U)	;TELL REMOTE STATION ABOUT THE ^S.



STPOIP:				;STOP OUTPUT IN PROGRESS
	PUSHJ	P,CLRPCT
STPOIS:	MOVSI	T2,LPLXNF	;HAS "TTY XONXOF" BEEN ENABLED?
	TDNN	T2,LDBPAG(U)	;...
	POPJ	P,		;NO, DON'T DO ANYTHING SPECIAL
	IORM	T1,LDBOST(U)	;NO MORE OUTPUT UNTIL XON IS TYPED
	PJRST	SETCH1		;SKIP & TELL FE'S TO STOP NOW

BEATIT:	SKIPA	T2,[POINT 9,GAWTXT]
RIBUSY:	MOVE	T2,[POINT 9,BSYTXT]
	PJRST	SETNNP

BSYTXT:	BYTE	(9)102,165,163,171,FLLFLG
GAWTXT:	BYTE	(9)123,164,141,156,144,040,141,154,157,156,145,FLLFLG
;HERE ON RECEIVE INTERRUPT OF CONTROL V (QUOTE)

RICV:	LDB	T2,LDPQOT	;IS QUOTING ENABLED?
	JUMPE	T2,CPOPJ1##	;NO, JUST STORE NORMALLY
	MOVEI	T2,LISQOT	;LINE INPUT STATE=QUOTING
	PJRST	SETDCS		;SET DEFERRED CHARACTER STATUS
;ROUTINES TO IMPLEMENT 'TERMINAL PAGE N'

CLRPCT::SE1ENT			;ENTER SECTION 1
	LDB	T2,LDPSTB	;BASIC "STOP" SIZE
	CAIN	T2,1		;IF "TTY STOP 1",
	MOVEI	T2,2		;THEN ALLOW AT LEAST ONE LINE TO PRINT
	MOVNI	T2,-1(T2)	;NEGATIVE SO COUNTER COUNTS UP TO 0
				; ALSO OFFSET BY ONE TO ALLOW TIME TO STOP
				; FURTHER, IF NO VALUE SET (I.E., "0")
				; THEN THIS GIVES US ^D254 LINES BEFORE
				; WE MUST CHECK AGAIN
	ANDI	T2,377		;MASK TO ONLY 8-BIT'S WORTH
	DPB	T2,LDPSTC	;RESET "STOP" COUNTER
	POPJ	P,

INCPCT:	MOVEI	T2,001001	;TWO NINE-BIT INCREMENTS
	ADDB	T2,LDBLSW(U)	;INCREMENT LENGTH AND STOP COUNTERS
	TRNN	T2,LPRLC0!LPRSC0;EITHER COUNTER "OVERFLOW"?
	POPJ	P,		;NO, NOTHING SPECIAL HERE THEN

;EITHER TOP OF NEW FORM, OR TIME TO AUTOMATICALLY STOP OUTPUT

	LDB	T1,LDPLNB	;BASIC "LENGTH" SIZE
	MOVNI	T1,-1(T1)	;NEGATIVE SO COUNTER COUNTS UP TO 0
	ANDI	T1,377		;MASK TO ONLY 8-BIT'S WORTH
	TRNE	T2,LPRLC0	;LENGTH COUNTER HIT 0?
	DPB	T1,LDPLNC	;YES, RESET LENGTH COUNTER
	TRNN	T2,LPRSC0	;STOP COUNTER HIT 0?
	POPJ	P,		;NO, JUST LENGTH COUNTER, NOTHING SPECIAL

;TIME TO AUTOMATICALLY STOP OUTPUT

	MOVE	T1,LDBPAG(U)	;GET THE PAGING CONTROL FLAGS
	LDB	T2,LDPSTB	;AND THE BASIC STOP SIZE
	TLNE	T1,LPLSTP	;USER WANT TO AUTOMATICALLY STOP OUTPUT?
	CAIG	T2,0		;YES, A STOP SIZE SPECIFIED?
	PJRST	CLRPCT		;NO, IGNORE THEN

IFN FTNET,<
	SKIPL	T1,LDBREM(U)	;IF VTM + SET HOST
	.CREF	LRLVTM		;(PUT TESTED BIT IN CREF)
>
	PUSHJ	P,PTBTCH##	;CHECK FOR BATCH PTY
	  PJRST	CLRPCT		;DISABLE AUTO STOP FOR BATCH OR VTM LINES
	MOVSI	T1,LOLSSO	;GET "SCNSER STOPPED OUTPUT" BIT
	PUSHJ	P,STPOIP	;IF AT LIMIT, STOP OUTPUT, CLEAR COUNT
	  PJRST	CLRPCT		;STPOIP NON-SKIPS IF TERMINAL NO PAGE
	MOVSI	T2,LOLNBS	;NEED BELL SENT STATE BIT
	MOVE	T1,LDBPAG(U)	;GET PAGE CONTROL
	TLNN	T1,LPLSBL	;WANT BELL ON AUTO STOP?
	POPJ	P,		;NO BELL
	IORM	T2,LDBOST(U)	;SET THE STATE BIT
	PJRST	TOPOKE		;ENSURE OUTPUT WILL BE DONE
;PACKED IMAGE MODE (PIM) RECEIVE CHARACTER PROCESSING

REPIM:	MOVSI	T2,LPLXNF	;THE PROCESS XON/XOFF BIT
	TDNN	T2,LDBPAG(U)	;HAS SET TERMINAL XONXOF BEEN SET?
	JRST	REPIM0		;NO, DON'T LOOK FOR XON/XOFF
	MOVE	T2,T3		;SAVE CHARACTER
	ANDI	T3,CK.CHR	;CLEAR POSSIBLE JUNK BITS
	SKIPL	LDBATR(U)	;8-BIT TERMINAL?
	ANDI	T3,CK.CH7	;NO, ONLY 7 VALID DATA BITS
	CAIN	T3,21		;IS CHARACTER AN XON?
	JRST	RICQ		;YES, TREAT AS NON PIM XON
	CAIN	T3,23		;IS CHARACTER AN XOFF?
	JRST	RICS		;TREAT AS NON PIM XOFF IF SO
	MOVE	T3,T2		;RESTORE CHARACTER AS RECEIVED
REPIM0:	MOVE	T2,LDBTIC(U)	;# OF CHARS INPUT
	CAIL	T2,TTPWRN##	;TIME TO WARN HIM?
	JRST	[CAIL	T2,TTPMAX##	;YES, OVER MAXIMUM LIMIT?
		JRST	RCHLT1		;YES, PIM LIMIT EXCEEDED
		PUSHJ	P,SNDXOF	;NO, STILL HOPE, SEND XOFF
		PUSHJ	P,RCVWAK	;AND GET USER'S ATTENTION
		JRST	REPIM2]		;ACCEPT THIS CHARACTER
	CAIL	T2,TTPBRK##	;TIME TO WAKE UP USER?
	PUSHJ	P,RCVWAK	;YES, NUDGE HIM
REPIM2:	MOVE	T2,TTFREN##	;COUNT OF FREE CHUNKS IN SYSTEM
	CAIGE	T2,5		;STILL WITHIN REASONABLE LIMITS?
	JRST	RCHLT1		;NO, SHUT IT DOWN
	TRO	T3,CK.IMG	;MARK IMAGE-CHARACTER BIT
	SCNOFF			;NO INTERRUPTS
	STCHK	T3,LDBTIP(U),SONPPJ  ;PLACE CHARACTER IN BUFFER
	AOS	LDBTIC(U)	;INCREMENT COUNT
	MOVE	T2,LDBTIP(U)
	MOVEM	T2,LDBECT(U)	;MAKE CHAR LOOK ECHOED
	SCNON			;ALLOW INTERRUPTS
	SKIPN	T2,LDBPBK(U)	;GET AND TEST BREAK CHARACTER WORD
	JRST	RCVWAK		;NOTHING SPECIFIED, BREAK ON ALL
	ANDI	T3,CK.CHR	;CLEAR IMAGE-CHARACTER BIT FOR TEST
REPIM5:	LSHC	T1,9		;GET TEST CHARACTER
	XOR	T1,T3		;XOR WITH RECEIVED CHAR
	TRNE	T1,400		;7 OR 8 BIT COMPARE?
	 TRNE	T1,177		;7 BIT, MATCH?
	  TRNN	T1,377		;8 BIT, MATCH?
	   JRST	RCVWAK		;YES, BREAK CHAR, WAKE AND DISMISS
	JUMPN	T2,REPIM5	;NO, TRY NEXT
	JRST	CPOPJ##		;DONE, DISMISS INTERRUPT.
SNDXOF::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,LPLXOF	;GET THE "XOFF HAS BEEN SENT" BIT
	TDNN	T1,LDBPAG(U)	;HAVE WE SENT ONE?
	JRST	SNDXF2		;NO, ALWAYS SEND THE FIRST XOFF
	MOVE	T1,LDBTIC(U)	;INPUT CHARACTER COUNT
	ADD	T1,LDBECC(U)	;PLUS THOSE NOT-QUITE-FULLY-INPUT
	IDIVI	T1,TTYMIC##	;ROUGHLY-MODULO TTYMIC?
	JUMPN	T2,CPOPJ##	;NO, DON'T SEND GOBS OF XOFFS
	MOVSI	T1,LPLXOF	;YES, SEND ANOTHER XOFF
				; (IN CASE THE UGLY RACE BIT US THE FIRST
				;  TIME AND THE PREVIOUS XOFF(S) GOT LOST)
SNDXF2:	IORM	T1,LDBPAG(U)	;SET THE BIT SO WE DON'T SEND TOO MANY
	PUSH	P,T3		;ISR WILL CLOBBER THIS
	MOVEI	T3,IRRCSL	;CODE TO SAY BUFFER LOW
	MOVEI	T1,ISRREM	;
	PUSHJ	P,@LDBISR(U)	;NOW CALL ISR
	  SKIPA	T2,FLPPXF	;ISR DID'T SEND IT. WE MUST
	JRST	T3POPJ##	;XOFF SENT, POP T3 AND RETURN
	PUSHJ	P,SETXNP	;SET FILLER
	PUSHJ	P,TOPOKE	;MAKE SURE IT GETS OUT
	JRST	T3POPJ##	;RESTORE T3 AND RETURN
;HERE ON A CONTROL U AT INTERRUPT LEVEL ONLY

RICU:	PUSHJ	P,FULLCQ	;BREAK ON ALL CHARACTERS?
	  JRST	CPOPJ1##	;YES. STORE THE ^U IN BUFFER
	TRC	T3,<"U"-100>^!MC.DL	;CONVERT TO DELETE-LINE
	PJRST	RICRET		;GET NEW BITS AND GIVE CONTINUE RETURN
RIDLN:	PUSHJ	P,STOPCM	;STOP COMCON
	SCNOFF			;NO INTERRUPTS
RIDLN1:	SKIPN	T1,LDBBKI(U)	;ANY BREAK POSITION SAVED?
	JRST	RIDLN3		;NONE THERE. CHECK FOR ECHOED CHARS
	CAME	T1,LDBTIP(U)	;ANYTHING TO DELETE ?
	PUSHJ	P,DELCHR	;DELETE 1 CHAR
	  JRST	SONPPJ		;NOTHING LEFT TO DELETE
	JRST	RIDLN1		;LOOP OVER LINE
RIDLN3:	SKIPN	T1,LDBBKU(U)	;ANY BREAK POSITION SAVED?
	JRST	TSETI2		;NONE THERE.  JUST CLEAR THE BUFFER
	CAME	T1,LDBTIP(U)	;ANYTHING TO DELETE?
	PUSHJ	P,DELCHR	;DELETE 1 CHAR
	  JRST	SONPPJ		;NOTHING LEFT
	JRST	RIDLN3		;LOOP OVER LINE

DELCHR:	SOSGE	T3,LDBECC(U)	;ANY LEFT TO ECHO?
	JRST	[SETZM	LDBECC(U)	;CLEAR ECHO COUNT
		MOVSI	T1,L3LEHD!L3LEPD ;BITS THAT MIGHT BE ON FOR OUR CHAR
		ANDCAM	T1,LDBBY3(U)	;MAKE SURE THEY'RE NOT
		SOSL	LDBTIC(U)	;CHECK FOR ECHOED INPUT
		JRST	[SETO	T4,	;SET VISIBILITY FLAG
			JRST	DELCH3]	;ERASE THESE TOO
		SETZB	T3,LDBTIC(U)	;CLEAR INPUT COUNT
		SETZM	LDBIIC(U)	;CLEAR INVISIBLE COUNT
		SETZM	LDBIEC(U)	;FOR BOTH SIDES
		MOVE	T1,LDBTIP(U)
		MOVEM	T1,LDBECT(U)	;ENSURE EMPTY ECHO STREAM
		PUSHJ	P,INPCHI	;MAKE SURE IT'S CONSISTENT
		  JRST	DELCHR		;TRY SOME MORE IF NOT
		POPJ	P,]		;RETURN
DELCH3:	LDB	T1,LDBTIP(U)	;GET CHARACTER TO BE WIPED
	TRNE	T1,CK.NIS	;IF INVISIBLE CHARACTER
	JRST	[SKIPL	T3	;YES, DOING ECHO STREAM?
		SOSA	LDBIEC(U)	;YES, DECREMENT INVISIBLE CHAR COUNT
		SOS	LDBIIC(U)	;NO, INPUT, DECREMENT ITS COUNT
		JRST	DELCH4]	;REJOIN
	TRNE	T1,CK.FDE	;NOT INVISIBLE, NEED TO ECHO?
	SETO	T4,		;ECHOED CHARACTER, SET FLAG
DELCH4:	SETO	T1,		;AMOUNT TO BACK UP
	ADJBP	T1,LDBTIP(U)	;GET NEW COPY OF BYTE POINTER
	MOVEI	T2,CK.BDY##(T1)	;SEE IF HIT HEADER WORD
	TRNN	T2,CK.BDY##	;WELL...
	JRST	[SSX	T2,MS.SCN	;SET SECTION NUMBER
		HLRZ	T1,CK.BTH##(T2)	;BACKUP
		JUMPE	T1,DELCH6	;TEST FOR ERROR ON ZERO POINTER
		ADD 	T1,[POINT CK.WID,CK.BDY##,35] ;MAKE INTO BYTE POINTER
		JRST	.+1]
DELCH5:	MOVEM	T1,LDBTIP(U)	;STORE ADJUSTED POINTER
	JUMPG	T3,CPOPJ1##	;IF NO ECHO STREAM INTACT
	MOVEM	T1,LDBECT(U)	;NO, MAKE SURE IT STARTS CORRECTLY
	JRST	CPOPJ1##

DELCH6:	SKIPG	T3		;IF ECHO STREAM IS OK,
	SKIPA	T1,LDBTIT(U)	;NO, GET TYPEIN TAKER
	MOVE	T1,LDBECT(U)	;YES, GET ECHO TAKER
	MOVE	T2,T1		;COPY IT
	IBP	T2		;GET BUMPED COPY
	CAME	T2,LDBTIP(U)	;BACKING UP TO A PLACE WE UNDERSTAND?
	STOPCD	CLRSTP,DEBUG,DELCBD,	;++DELCHR WENT BAD
	JRST	DELCH5		;YES, GO FOR IT
RECHLT:	POP	P,T1		;RESTORE T1
RCHLT1::SE1ENT			;ENTER SECTION 1
	MOVEI	T3,IRRCNS	;CODE FOR CHAR NOT STORED
	MOVEI	T1,ISRREM
	PUSHJ	P,@LDBISR(U)	;TELL THE ISR CHAR NOT STORED
	  TRNA			;FE WANTS BELL SENT
	JRST	RCHLT2		;FE WANTS NO BELL
	MOVSI	T2,LOLNBS	;NEED BELL SENT FLAG
	IORM	T2,LDBOST(U)	;LIGHT STATUS FLAG (LEAVE POSSIBLE XOFF POINTER ALONE)
RCHLT2:	PUSHJ	P,TOPOKE	;START TYPING IF NEEDED (USUALLY NOT NEEDED)
	PJRST	ECHBRK		;TRY TO WAKE JOB, THEN
				;DISMISS INTERRUPT, JUNKING CHARACTER
;HERE ON A RUBOUT OR CONTROL W AT INTERRUPT LEVEL

RICW:	PUSHJ	P,FULLCQ	;BKA OR FCS?
	  JRST	CPOPJ1##	;YES. STORE FOR READER
	TRC	T3,<"W"-100>^!MC.DW	;CONVERT TO DELETE-WORD
	PJRST	RICRET		;GET NEW BITS AND GIVE CONTINUE RETURN


RIDEL:	PUSHJ	P,FULLCQ	;BKA OR FCS?
	  JRST	CPOPJ1##	;YES. STORE FOR READER
	MOVEI	T2,L2RXON	;PAPER TAPE IN EFFECT?
	TDNE	T2,LDBBY2(U)	;YES, DISCARD RUBOUT
	POPJ	P,		;YES. DISCARD RUBOUT
	MOVE	T1,T3		;COPY CHARACTER THAT BROUGHT US HERE
	ANDI	T1,CK.CHR	;MASK OFF CRUFTY BITS
	CAIE	T1,010		;WAS IT BACKSPACE?
	TRCA	T3,177^!MC.DC	;NO, MAKE IT META-RUBOUT
	TRC	T3,010^!MC.BS	;YES, MAKE IT META-BS
	JRST	RICRET		;MUST DEFER TO XMTECH

;SUBROUTINE TO ADJUST HORIZONTAL POSITION WHEN ERASING CHARACTERS
;CALL WITH T2 = NUMBER OF POSITIONS TO BACKUP, RETURNS CPOPJ, T2 INTACT

BACKUP:	PUSH	P,T2		;SAVE T2
	MOVEI	T3,10		;BACKSPACE
BACKU1:	PUSHJ	P,ADJHP		;BACKUP 1 CHARACTER
	SOJG	T2,BACKU1	;LOOP FOR ALL
	JRST	T2POPJ		;RESTORE T2 AND RETURN

;SUBROUTINE TO DETERMINE IF THE CURRENT TERMINAL IS A VIDEO TERMINAL
; I.E., SPECIFIED AS SUCH BY THE USER TYPING A TTY TYPE COMMAND
; RETURNS CPOPJ IF NOT, CPOPJ1 IF SO, T1 POINTS AT CHARACTERISTICS TABLE
; ENTRY FOR THE TERMINAL TYPE

TTVID:	MOVSI	T1,LDLLCP	;LOCAL COPY BIT
	TDZE	T1,LDBDCH(U)	;LINE DOING OWN ECHOING
	POPJ	P,		;YES, AVOID VIDEO STUFF (T1=0)
	LDB	T1,LDPTTT	;GET TERMINAL TYPE AS SET BY COMMAND
	JUMPE	T1,CPOPJ##	;GO IF NONE SPECIFIED
	TRZE	T1,100		;CUSTOMER DEFINED TERMINAL TYPE ?
	MOVNI	T1,(T1)		;YES, NEGATIVE TABLE INDEX
	LSH	T1,1		;2 WORDS PER ENTRY
	SKIPE	TCRTAB##+1(T1)	;SKIP IF NOT A VIDEO TERMINAL
	AOS	(P)		;IT IS!
	POPJ	P,		;RETURN
;HERE ON ANY OF THE THREE ALTMODES, TO DECIDE ON CONVERSION TO STDALT
RIALT:	PUSHJ	P,RIALTO
	JRST	CPOPJ1##

RIALTO:	PUSH	P,T2		;SAVE T2
	MOVEI	T2,(T3)		;GET A COPY OF THE CHAR.
	ANDI	T2,CK.CHR	;ISOLATE CHAR (REMOVE IMAGE/ECHO BITS)
	CAIN	T2,STDALT	;CHECK FOR TRUE ESC
	JRST	T2POPJ##	;DON'T ALTER
	MOVEI	T1,0		;NO, ASSUME DATA CHAR
	MOVSI	T2,LPLALT	;CONVERT OLD ALTMODES?
	TDNN	T2,LDBPAG(U)	;TEST IT
	JRST	RIALT2		;YES, SO GO DO IT
	MOVE	T2,LDBDCH(U)	;LINE FLAG BITS
	TLNE	T2,LDLLCT	;NO, BUT SHOULD WE CONVERT TTY UC?
	TRC	T3,040		;YES, SO CHANGE IT
	JRST	T2POPJ##	;ALL DONE
RIALT2:	MOVEI	T3,STDALT	;YES USE THE STANDARD ALTMODE
	MOVE	T1,CHTABL(T3)	;NOW A BREAK, SO GET ITS BITS
	JRST	T2POPJ##	;STORE WHATEVER THIS DECIDED ON
;RECEIVE INTERRUPT ROUTINE FOR LINE CONTROL TRANSACTIONS

;ENTER HERE FROM DEVICE-DEPENDENT ROUTINE WITH
;  TRANSACTION CODE IN T3,
;  PHYSICAL LINE # IN U (IDX FOR LINTAB, LDBDCH, ETC)
;    U'S RANGE CHECKED BY INTERRUPT ROUTINE
;  AC'S & PDL SETUP


LNCREC::SE1ENT			;ENTER SECTION 1
	MOVE	U,LINTAB##(U)
	CAIN	T3,LNTEHC	;DISPATCH ON CHARACTER CODE IN T3
	JRST	LNREHC		;ENABLE HUNG CHECK
	CAIE	T3,LNTDHC
	POPJ	P,		;ILLEGAL CODE--IGNORE

	MOVEI	T3,LDRSHC	;DISABLE HUNG CHECK
	IORM	T3,LDBDCH(U)	;  TURN ON LDRSHC
	POPJ	P,

LNREHC:	MOVEI	T3,LDRSHC	;TURN OFF LDRSHC
	ANDCAM	T3,LDBDCH(U)
	POPJ	P,
;RECEIVE INTERRUPT ROUTINE FOR DATASET TRANSACTIONS

;ENTER HERE FROM DEVICE-DEPENDENT ROUTINE WITH TRANSACTION CODE IN
; T3, DSCTAB INDEX IN U, RANGE ALREADY CHECKED BY INTERRUPT
; ROUTINE, AC'S AND PDL SET UP.


DSCREC::SE1ENT			;ENTER SECTION 1
	MOVE	T2,DSCTAB##(U)	;GET TABLE ENTRY FIRST
	TLNE	T2,DSCBLI	;IGNORE INTERRUPTS?
	POPJ	P,0		;YES. DO SO.
IFN FTPI,<PUSHJ P,SIGDSC>	;SIGNAL, DATA SET STATUS CHANGE
	CAIN	T3,DSTRNG	;DISPATCH ON CODES
	JRST	DSRRNG		;RING FROM DATAPHONE
	CAIN	T3,DSTON	;CARRIER ON?
	JRST	DSRON		;YES.
	CAIN	T3,DSTPND	;DIALLER WANT ANOTHER DIGIT
	JRST	DSRPND		;YES

	CAIN	T3,DSTOFF	;OFF INTERRUPT?
	TLNN	T2,DSCHWC	;YES. DID I THINK HE WAS ON?
	POPJ	P,0		;NO. FORGET IT.
	TLNN	T2,DSCSWC	;DO I THINK HE SHOULD BE ON?
	JRST	DSROF1		;NO. JUST GO CLEAR HIM OUT.
	MOVEI	T1,5		;YES. TIME OUT IN CASE OF BRIEF FAILURE
	DPB	T1,DSTMPL	;STORE IN TIME BYTE.
	MOVSI	T1,DSCHWC	;CLEAR THE CARRIER BIT
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCFAI	;AND FLAG POSSIBLE FAILURE CONDITION
	IORM	T1,DSCTAB##(U)	; ..
	POPJ	P,0		;LET CLOCK TIME HIM OUT NOW.
DSROF1::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,DSCHWC!DSCSWC!DSCIC2
	ANDCAM	T1,DSCTAB##(U)	;CLEAR ALL THESE BITS IN TABLE
	HRRZ	T1,DSCTAB##(U)	;GET TERMINAL NUMBER FOR THIS MODEM
	CAMN	T1,DSDUNI##	;DIALLER CODE USED BY IT?
	SETOM	TTYDDL##	;YES. CLEAR INTERLOCK TO FREE IT.

	MOVEI	T3,DSTOFF	;AND SEND OFF-COMMAND TO DEVICE
DSCCAL::SE1ENT			;ENTER SECTION 1
	HRRZ	T2,DSCTAB##(U)	;T2 := LINE NUMBER
	MOVEI	T1,ISRDSC	;DATASET CONTROL FUNCTION
	MOVE	T2,LINTAB##(T2)	;LDB ADDRESS
	PJRST	@LDBISR(T2)	;DISPATCH TO INTERRUPT SERVICE

;SUBROUTINE TO SIGNAL DATA SET STATUS CHANGE
; ENTER T3=TRANSACTION CODE
IFN FTPI,<
SIGDSC::SE1ENT			;ENTER SECTION 1
	HRRZ	T1,T2		;T1 := LINE NUMBER
	MOVE	T1,LINTAB##(T1)	;GET LDB ADDRESS
	HRRZ	F,LDBDDB(T1)	;GET ADDRESS OF DDB
	MOVE	T4,J		;SAVE J
	JUMPE	F,SIGDS1	;ALL DONE IF ZERO
	LDB	J,PJOBN##	;GET JOB NUMBER
	JUMPE	J,SIGDS1	;JUMP IF JOB 0 (CAN THAT HAPPEN?)
	HRROI	T1,C$DSET	;GET CONDITION TO SIGNAL
	PUSHJ	P,PSIJOB##	;NOTIFY ENTIRE JOB OF CONDITION (EACH JCH)
SIGDS1:	MOVE	J,T4		;RESTORE J
	POPJ	P,		;RETURN
> ;END IFN FTPI
;STILL IN FTMODM
DSRON:
	TLNN	T2,DSCDLW	;IN DIALLER WAIT?
	JRST	DSRON1		;NO.
	MOVSI	T1,DSCDLW!DSCEON	;YES. CLEAR FLAGS FOR DIALLER
	ANDCAM	T1,DSCTAB##(U)	;IN TABLE IN CORE
	SETOM	TTYDDL##	;FREE UP DIALLER CODE
	MOVSI	T1,DSCDLC	;SET SUCCESSFUL COMPLETION BIT
	IORB	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
	PUSH	P,T2		;SAVE OLD STATUS
	PUSHJ	P,DSCWAK	;WAKE THE JOB, IF ANY STILL THERE.
	POP	P,T2		;RESTORE OLD BITS
DSRON1:
;		LOCAL LINES. THIS ALLOWS USER TO GET SIGN ON MESSAGE
	HRRZ	T1,DSCTAB##(U)	;GET REAL LINE NUMBER
	MOVE	T1,LINTAB##(T1)	;GET ADDRESS OF LDB
	MOVE	T1,LDBDCH(T1)	;GET DEVICE BITS
	TRNN	T1,LDRDSD	;IS THIS A REAL DATASET LINE?
	JRST	DSRON2		;NO--LOCAL TERMINAL JUST CAME UP
	TLNE	T2,DSCHWC	;HE CAME ON. IS THAT NEWS TO ME?
	POPJ	P,0		;I THOUGHT HE WAS ON. FORGET IT.
	TLNN	T2,DSCSWC	;DO I WANT HIM ON?
	JRST	DSROF1		;NO. GO FORCE HIM OFF.

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

	MOVSI	T1,DSCTMM+DSCFAI;YES. CLEAR TIME AND FAILURE BITS
	ANDCAM	T1,DSCTAB##(U)	;IN THE TABLE (STILL IN T2)
	MOVSI	T1,DSCHWC	;MARK THAT HE CAME ON
	IORM	T1,DSCTAB##(U)	;IN TABLE
	TLNE	T2,DSCFAI+DSCDLW;WAS ALL THIS A BRIEF FAILURE?
	POPJ	P,0		;YES. JUST DISMISS, HE'S BACK.
	MOVSI	T1,DSCBLI+DSCNCR;NO. NEW GUY. SET BLIND AND DELAY BITS
	HRRZ	F,T2		;GET JUST LINTAB INDEX
	MOVE	F,LINTAB##(F)	;LDB
	HRRZ	F,LDBDDB(F)	;DDB
	JUMPE	F,DSRN1A	;GO IF NO DDB
	MOVE	T4,DEVMOD(F)	;CHARACTERS
	TLNN	T4,TTYATC	;IF CONSOLE
	TRNN	T4,ASSCON!ASSPRG;AND NOT ASSIGNED
DSRN1A:	TLO	T1,^D60		;SET TIME OUT
	IORM	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
DSRON2:	HRRZ	U,T2		;GET JUST LINTAB INDEX
	MOVE	U,LINTAB##(U)	;GET LDB ADDRESS FOR LINE
	PUSHJ	P,TSETBI	;CLEAR INPUT BUFFER
IFN FTNET,<
	SKIPGE	LDBREM(U)	;IF THIS IS A VTM LINE,
	PUSHJ	P,VTMDSO##	;  TURN CARRIER AND QUEUE LINE FOR SERVICE
>
	MOVSI	T1,L1LOFL
	ANDCAM	T1,LDBOFL(U)
	SKIPGE	DEBUGF##
	POPJ	P,
	HRRZ	F,LDBDDB(U)	;GET DDB
	JUMPN	F,CPOPJ##	;DO NOT RUN INITIA IF THERE IS A
				; JOB ON THE LINE
	MOVEI	T1,TTFCXH	;GET HELLO COMMAND INDEX
	JRST	TTFORC		;FORCE HELLO COMMAND
DSRRNG:	MOVE	T1,STATES##	;PHONE RINGING. MAY I ANSWER?
	TRNE	T1,ST.NRL	;CHECK THE SCHEDULE COMMAND WORD
	POPJ	P,0		;NOT ALLOWED. IGNORE.
	PUSH	P,U		;SAVE PTR TO DSCTAB
	HRRZ	U,DSCTAB##(U)	;GET REAL LINE NUMBER
	MOVE	U,LINTAB##(U)	;GET ADR OF LDB
	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNN	T1,LDRDSD	;IS THIS A DATASET LINE?
	JRST	UPOPJ##		;NO
	HRRZ	F,LDBDDB(U)	;DDB PTR
	JUMPE	F,DSRRN2	;NO JOB, ALL OK
	MOVE	T1,DEVMOD(F)	;DEVICE BITS
	TLNN	T1,TTYATC	;CONTROLLING TTY?
	JRST	DSRRN2		;NO, SO NO JOB
				;IF WE GET HERE, WE HAVE RING ON LINE
				; WITH A JOB, WHICH IS NOT SUPPOSED TO
				; HAPPEN.  TO PREVENT SECURITY PROBLEMS,
				; WE DETATCH THE JOB
	PUSHJ	P,DSCDET	;DETACH OR KILL IF NOT LOGGED IN.
DSRRN2:	POP	P,U		;RESTORE DSCTAB PTR
	MOVEI	T3,0		;CLEAR VARIOUS
	DPB	T3,DSTMPL	; TIMERS
	MOVSI	T1,DSCFAI+DSCTMM;CLEAR THE MOMENTARY FAILURE BIT
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCSWC+^D30	;TURN ON ALLOW BIT, AND TIME.
DSRRN1:	IORM	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
	MOVEI	T3,DSTON	;SEND A TURN-ON COMMAND TO DEVICE-
	PJRST	DSCCAL		; DEPENDENT ROUTINE, AND DISMISS


DSCDET:	MOVEI	T1,TTFCXD	;DO THE DETACH BY
	PJRST	TTFORC		; FORCING A .BYE
DSRPND:	TLNE	T2,DSCEON	;SENT ALL DIGITS?
	POPJ	P,0		;YES. IGNORE REQUEST
	MOVEI	T1,^D60		;ONE MINUTE FROM SENDING DIGIT
	DPB	T1,DSTMPL	;INTO TIME-OUT OF DATASET
	MOVSI	T1,DSCEON	;FLAG END OF NUMBER SENT, IF TRUE.
	ILDB	T3,TTYDDA##	;GET ANOTHER DIGIT
	CAIN	T3,17		;END OF NUMBER CODE?
	JRST	DSRPN1		;YES
	ADDI	T3,DSTPND	;CONVERT TO TRANSACTION CODE FOR XXXINT
	PJRST	DSCCAL		;AND SEND IT OUT


DSRPN1:	IORM	T1,DSCTAB##(U)	;SET FLAG IN TABLE
	POPJ	P,0		;DON'T SEND NUMBER

	SUBTTL	KS10 CTY AND KLINIK TERMINAL SERVICE

IFN FTKS10,<
CT0INT::SKIPN	.CPFEF##	;HAS FRONT END INTERRUPTED ?
	JRST	.-1		;ON THROUGH SKIP CHAIN
	WRPI	CLRCTY##	;CLEAR THE INTERRUPT
	SETZM	.CPFEF##	;CLEAR THE FLAG
	JSR	SCNSAV##	;SAVE AC'S ETC.
	MOVE	T3,KLIIWD	;GET KLINIK INPUT WORD
	TRNN	T3,KLIIVL	;IS THERE INPUT?
	  JRST	CTYIN1		;NO--PROCEED
	SETZM	KLIIWD		;YES--CLEAR IT
	MOVEI	U,KLILIN##	;GET KLINIK LINE NUMBER
	PUSHJ 	P,RECINT	;PASS TO SCNSER
CTYIN1:	MOVE	U,LINTAB+KLILIN## ;LDB FOR KLINIK LINE
	SKIPL	LDBDCH(U)	;IS KLINIK OUTPUT ACTIVE?
	SKIPE	KLIOWD		;YES--IS OUTPUT WORD AVAILABLE?
	JRST	CTYIN2		;NO--PROCEED
	MOVEI	U,KLILIN##	;KLINIK LINE NUMBER
	PUSHJ	P,XMTINT	;SEE IF MORE TO TYPE
CTYIN2:	SKIPN	T3,CTYIWD	;ANY CTY INPUT?
	  JRST	CTYIN3		;NO--PROCEED
	SETZM	CTYIWD		;YES--CLEAR IT
	MOVEI	U,CTYLIN##	;CTY LINE NUMBER
	PUSHJ	P,RECINT	;PASS TO SCNSER
CTYIN3:	MOVE	U,LINTAB+CTYLIN## ;GET LDB ADR FOR CTY
	SKIPL	LDBDCH(U)	;IS CTY TYPING ?
	SKIPE	CTYOWD		;AND IS OUTPUT WORD FREE ?
	JRST	CTYIN4		;NOT TYPING OR STILL BUSY
	MOVEI	U,CTYLIN##	;LINE NUMBER FOR CTY
	PUSHJ	P,XMTINT	;TRY TO TYPE MORE STUFF
CTYIN4:	POPJ	P,		;RETURN
>;END IFN FTKS10
	SUBTTL	FILLERS AND SIMULATION ROUTINES

;ROUTINE TO SET UP FILLERS FOR OUTPUT CHARACTERS
;CALL WITH
;	MOVE	T3,CHARACTER
;	MOVE	T1,CHTABL(T3)
;	PUSHJ	P,SETFLO
;	  <CHARACTER NEEDS FILLERS, ALREADY SETUP>
;	<CHARACTER NEEDS NO FILL>


SETFLO:	TLZ	T1,CHUAE+CHALT+CHCRE	;THESE ECHO MODES NOT USED ON OUTPUT
	TLO	T1,CHFILO	;FLAG OUTPUT-FILLER REQUEST
	JRST	SETFL2		;REST OF ROUTINE SAME AS ON INPUT

;ROUTINE TO SET FILLER POINTER FOR INPUT CHARACTERS (ECHOING)

SETFLI:	TLNE	T1,CHALT	;IS THIS A POSSIBLE ALTMODE?
	PUSHJ	P,RIALTO	;YES, SEE IF IT IS A REAL ALTMODE

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;COMMON CODE FOR SETFLI/SETFLO

SETFL2:	MOVSI	T2,L2LDEL	;BACKSLASH BIT
	TDNE	T2,LDBBY2(U)	;NEED ONE?
	JRST	[ANDCAM	T2,LDBBY2(U)	;YES, CLEAR BIT
		 MOVE	T2,FLLBSP	;GET BACKSLASH POINTER
		 PUSHJ	P,SETFLE	;PUT INTO ECHO/FILL STREAM
		 AOS	LDBHPS(U)	;COUNT UP FOR HPOS
		 JRST	.+1]	;REJOIN
	MOVE	T2,LDBHPS(U)	;GET HORIZONTAL POSITION COUNTER
	MOVE	T4,LDBDCH(U)	;GET DEVICE BITS
	TLNE	T4,LDLDLR	;USER WANT DOLLAR SUPPRESSED?
	TLZ	T1,CHALT+CHUAE+CHCRE	;YES. DO SO.
	TLNE	T1,CHUAE	;WILL ^X BE ADDED?
	ADDI	T2,2		;YES. ADD 2 TO HPOS
	TLNE	T1,CHALT	;IS IT GETTING A DOLLARSIGN?
	ADDI	T2,1		;YES. COUNT IT.
	JUMPLE	T2,SETFI1	;IF NOT AT END OF SCREEN
	PUSHJ	P,PTBTCH##	;CHECK FOR REGULAR PTY
	  JRST	SETFI1		;IT IS, NO FREE CRLF
	MOVE	T2,LDBDCH(U)	;GET THE CHARACTERISTICS WORD
	TLNE	T2,LDLNFC	;USER WANT FREE <CR><LF>?
	JRST	SETFI1		;NO. FORGET IT.
;	PJRST	SETCRF		;YES, FALL INTO SETCRF

;SETCRF -- ROUTINE TO SETUP A FREE CRLF POINTER

SETCRF:	PUSHJ	P,SCNBOL	;RESET LINE COUNTERS IN ANY CASE
	SKIPGE	LDBTTW(U)	;IS THIS AN ANF NETWORK VIRTUAL TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	JRST	SETCR5		;YES, THEN NO FILLER (THE REMOTE COMPUTER
				; WILL SUPPLY THE FREE <CR><LF>, WE NEED
				; MERELY NOTE THAT A NEW LINE IS STARTING)
	MOVE	T2,FLLCRF	;GET CRLF FILL POINTER
SETCR3:	PUSHJ	P,SETFLE	;SETUP THE APPROPRIATE FILLER POINTER
	MOVSI	T2,LDLLCP	;DON'T ECHO INPUT CHARACTER AFTER FREE CRLF
	TLNN	T1,CHFILO	; BUT IF OUTPUT, DON'T EAT A CHARACTER
	TDNN	T2,LDBDCH(U)	;IF LOCAL COPY IS SET
	PUSHJ	P,REEAT		;YES, RE-EAT THIS CHARACTER
	POPJ	P,		;NON-SKIP RETURN (NEEDED CRLF)

SETCR5:	MOVE	T2,T3		;SCRATCH COPY OF CHARACTER
	ANDI	T2,CK.CH7	;JUST SEVEN-BIT ASCII
	CAIL	T2,40		;IS CHARACTER A
	CAIL	T2,177		; NORMAL PRINTING ASCII GRAPHIC?
	TLNE	T1,CHALT!CHUAE	;NO, CONTROL, IF EITHER "$" OR "^X" FORM
	AOS	LDBHPS(U)	;THEN COUNTS AS A PRINTING CHARACTER
	TLNE	T1,CHUAE	;IN ADDITION, IF "^X" FORM
	AOS	LDBHPS(U)	; THEN COUNTS AS TWO PRINTING CHARACTERS
	PUSHJ	P,INCPCT	;COUNT LINES OUTPUT FOR TTY PAGE N
	MOVE	T4,LDBOST(U)	;GET LEFT-HALF CHARACTERISTICS
	TLNN	T4,LOLSSO	;DID INCPCT HIT A PAGE BREAK?
	JRST	CPOPJ1##	;NO, JUST OUTPUT THE FIRST CHARACTER
;HERE IF THE FREE <CR><LF> THAT WE KNOW THE REMOTE IS ABOUT TO OUTPUT
;(AS SOON AS IT SEES THE CHARACTER IN T3) WILL ALSO BREAK THE PAGE LIMIT.
;WE MUST SUPPLY THE FREE <CR><LF> AND THEN STOP IN ORDER TO MAKE THE
;REMOTE BEHAVE THE SAME AS LOCALLY-OWNED TERMINALS. THIS RELYS ON THE
;FACT THAT XMTSPC WILL FORCE OUT THE FILLER POINTER EVEN IF THE LINE
;IS XOFFED - A DUBIOUS FEATURE AT BEST.

	PUSHJ	P,SCNBOL	;OOPS - RE-CLEAR HORIZONTAL POSITION

;TECHNICALLY, INCPCT SHOULD BE UNDONE, SINCE THE <CR><LF> COMING WILL
;LEAVE IT OFF BY ONE, BUT THE XON NEEDED TO GET OUT OF THE STUCK STATE
;WILL RESET THE PAGE COUNTER, SO . . .

	MOVE	T2,FLLCRP	;WANT JUST A <CR><LF> - THE
				; -11 WILL PROVIDE ANY FILL NEEDED.
	JRST	SETCR3		;GO OUTPUT A NEW LINE


;HERE TO FORCE THE RE-EAT OF A CHARACTER AFTER FREE CRLF

REEAT:	MOVSI	T2,LOLREO	;ASSUME FOR OUTPUT
	TLNN	T1,CHFILO	;WAS IT?
	MOVSI	T2,LOLREE	;NO, FOR ECHO
	IORM	T2,LDBOST(U)	;SET FOR AFTER WE COME BACK
	POPJ	P,		;AND RETURN TO CALLER
SETFI1:	TLNN	T1,CHFIL	;THIS CHAR NEED FILLERS?
	JRST	SETFI2		;NO.
	MOVE	T2,T3		;SAVE CHARACTER
	ANDI	T2,CK.CHR	;MASK DOWN
	MOVE	T2,CHTABL(T2)	;ORIGINAL BITS
	TLNN	T2,CHFIL	;CHARACTER REALLY NEED FILL?
	PJRST	SETFCE		;NO, JUST TYPE VIA FILL/ECHO STREAM AND RETURN
	PUSH	P,T3		;SAVE THE CHARACTER
				;*** CHAR MUST BE AT 0(P) FOR SIMULATORS ***
				;*** EVEN THOUGH THIS IS BAD PRACTICE
	ANDI	T3,CK.CHR	;TRIM FUNNY BITS
	MOVE	T4,LDBDCH(U)	;GET DEVICE BITS (USED BY MOST FILL ROUTINES)
	CAIG	T3,15		;NEED TO CALL ROUTINE FOR IT?
	JRST	@SETFLD-10(T3)	;YES. GO DO IT.
	CAIL	T3,21		;CONTROL Q THRU T?
	JRST	SETFI6		;YES. THEY HAVE SPECIAL HANDLERS TOO
	PUSHJ	P,SETFLC	;GET FILL CLASS
	JUMPE	T2,ZFLPOP	;NO. USER WANT FILLER SUPPRESSED?
	SKIPA	T2,FILLP1	;NO. ASSUME ONE FILLER IS ENOUGH
ZFLPOP:	MOVEI	T2,0		;POINTER FOR NO FILLERS
FLLPOP:	PUSHJ	P,FLLCHO	;CHARACTER TO TYPE BEFORE STRING
SCCHPJ:	POP	P,T3		;RESTORE CHARACTER (MAYBE WITHOUT TYPING IT)
	PJRST	SETFLE		;TYPE THE FILLER POINTER AND RETURN NON-SKIP
				; TO SHOW FILL WAS NEEDED

SETFI2:	TLNN	T1,CHUAE+CHALT+CHCRE	;ECHO AS ^X OR $ ?
	JRST	CPOPJ1##	;NO. NOTHING SPECIAL. JUST SEND.
	TLNE	T1,CHALT	;ALTMODE?
	JRST	SETFI3		;YES.
	MOVE	T2,FLLUPA	;GET POINTER TO UPARROW CONST
	PUSHJ	P,SETFLE	;TYPE IT
	TRC	T3,100		;CONVERT TO PRINTABLE FORM
	MOVEI	T2,2		;WIDTH OF ^X
	ADDM	T2,LDBHPS(U)	;UPDATE HPOS
	TLNN	T1,CHCRE	;ALSO NEED <CR><LF>?
	PJRST	SETFCE		;NO, JUST TYPE ADJUSTED CHARACTER
	PUSHJ	P,SETFCE	;YES, TYPE MODIFIED CHARACTER
	PJRST	METNLF		;TYPE CRLF FILL AND RETURN

SETFI3:	MOVE	T2,FLLDLR	;GET POINTER TO DOLLARSIGN GRAPHIC
	AOS	LDBHPS(U)	;ADVANCE HORIZONTAL POSITION
	PJRST	SETFLE		;SET FILLER POINTER AND RETURN
SETFI6:	TLNN	T4,LDLDLR	;ECHOING GRAPHICS INHIBITED?
	TLNE	T1,CHFILO	;IS THIS FOR INPUT OR OUTPUT OF ^Q-^T?
	JRST	SETFI7		;NO GRAPHICS. JUST THROW ON A RUBOUT.
	MOVEI	T2,2		;LENGTH OF PRINT REPRESENTATION
	ADDM	T2,LDBHPS(U)	;ADD TO HORIZONTAL POSITION COUNTER
	MOVE	T2,STFLT2-21(T3);GET ECHO POINTER FOR CONTROL Q-T
	JRST	FLLPOP		;STORE FILLER AND RETURN

SETFI7:	PUSHJ	P,SETFLC	;GET FILL CLASS
	SKIPE	T2		;FILL 0?
	MOVE	T2,FILLP1	;NO, USE A FILLER
	PJRST	FLLPOP		;STORE FILLER AND GO HOME

FLLCHO:	TLNE	T1,CHFILO	;IS THIS FOR OUTPUT?
	PJRST	SETFCE		;YES, ALWAYS TYPE IT
	PUSH	P,T1		;NO, SAVE FLAGS
	MOVE	T1,-2(P)	;GET PREVIOUS CHARACTER
	ANDI	T1,CK.IMG!CK.FDE;KEEP ONLY BITS WE CARE ABOUT
	IOR	T3,T1		;MERGE INTO OUR CHARACTER
	PUSHJ	P,ECHTST	;DOES CHARACTER NEED ECHO?
	  PUSHJ	P,SETFCE	;YES, TYPE IT
	JRST	TPOPJ##		;AND RETURN, RESTORING FLAGS
;SETFLC -- ROUTINE TO SETUP THE FILLER CLASS FOR A LINE

SETFLC:
IFN FTNET,<
	SKIPL	LDBTTW(U)	;ANF NETWORK TERMINAL DOES ITS OWN FILL
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
>
	PUSHJ	P,PTBTCH##	;ELSE, CHECK FOR REGULAR PTY
	  TDZA	T2,T2		;IT IS, USE FILLER CLASS 0
	LDB	T2,LDPFLC	;ELSE GET FILL CLASS FROM LDB
	POPJ	P,		; AND RETURN



;ROUTINE TO SETUP AN "XON CLASS" FILLER POINTER
;CALL
;	MOVE	T2,FILL POINTER
;	PUSHJ	P,SETXNP
;	<ALWAYS RETURN HERE>

SETXNP::SE1ENT			;ENTER SECTION 1
	SCNOFF			;GET SCNSER INTERLOCK
IFN FTXMON,<
	TLNE	T2,-1		;IF REAL BYTE POINTER
	TLO	T2,(1B12)	;INDICATE EXTENDED BYTE POINTER
	HLLZM	T2,LDBXNP(U)	;STORE FIRST WORD
	HRRZM	T2,LDBXNP+1(U)	;STORE SECOND WORD TO ACCESS SECTION 0
>
IFE FTXMON,<
	MOVEM	T2,LDBXNP(U)	;JUST STORE
>
	JUMPE	T2,SONPPJ	;IGNORE IF NULL
	MOVSI	T2,LOLXFP	;XOFF PENDING BIT
	IORM	T2,LDBOST(U)	;SET IN STATES WORD
	JRST	SONPPJ		;RELEASE INTERLOCK AND RETURN


;ROUTINE TO SETUP A FILLER POINTER. SETS LOLFSP IF APPROPRIATE.
;CALL
;	MOVE	T2,FILLER POINTER
;	PUSHJ	P,SETFLP
;	<ALWAYS RETURNS HERE>
;ENTER AT SETFPT IF SCNOFF

SETFLP::SCNOFF
SETFPT::SE1ENT			;ENTER SECTION 1
IFN FTXMON,<
	TLNE	T2,-1		;IF REAL BYTE POINTER
	TLO	T2,(1B12)	;INDICATE EXTENDED BYTE POINTER
	HLLZM	T2,LDBFLP(U)	;STORE FIRST WORD
	HRRZM	T2,LDBFLP+1(U)	;STORE SECOND WORD TO ACCESS SECTION 0
>
IFE FTXMON,<
	MOVEM	T2,LDBFLP(U)	;JUST STORE
>
	JUMPE	T2,SONPPJ	;CLEARED WORD, JUST RETURN
SETFP1:	MOVSI	T2,LOLFSP
	IORM	T2,LDBOST(U)	;SET FLAG FOR XMTCHR
	JRST	SONPPJ		;NON-SKIP RETURN, TO FORCE OUT


;ROUTINE TO SETUP A 'NOT NOW' POINTER. SETS LOLNNP IF APPROPRIATE.
;CALL
;	MOVE	T2,FILLER POINTER
;	PUSHJ	P,SETNNP
;	<ALWAYS RETURNS HERE>

SETNNP:	SCNOFF
	SE1ENT			;ENTER SECTION 1
IFN FTXMON,<
	TLNE	T2,-1		;IF REAL BYTE POINTER
	TLO	T2,(1B12)	;INDICATE EXTENDED BYTE POINTER
	HLLZM	T2,LDBNNP(U)	;STORE FIRST WORD
	HRRZM	T2,LDBNNP+1(U)	;STORE SECOND WORD TO ACCESS SECTION 0
>
IFE FTXMON,<
	MOVEM	T2,LDBNNP(U)	;JUST STORE
>
	JUMPE	T2,SONPPJ	;CLEARED WORD, JUST RETURN
SETNN1:	MOVSI	T2,LOLNNP
	IORM	T2,LDBOST(U)	;SET FLAG FOR XMTCHR
	SCNON			;ALLOW OTHERS AGAIN
	PJRST	TOPOKE		;MAKE SURE OUTPUT WILL HAPPEN
;ROUTINE TO OUTPUT A CHARACTER VIA ECHO/FILL STREAM

SETFCE:	PUSHJ	P,SAVT##	;PRESERVE REGISTERS
	SCNOFF			;FOR STCHK
	STCHK	T3,LDBEOP(U),SETFE4	;STUFF IN ECHO OUTPUT STREAM
	AOS	LDBEOC(U)	;COUNT SPECIAL OUTPUT CHARACTER
	SCNON			;ALLOW INTERRUPTS AGAIN
	JRST	SETFE3		;SET LOLESP AND RETURN


;ROUTINE TO OUTPUT A FILL SEQUENCE
;CALLED LIKE SETFLP, BUT WRITES INTO THE ECHO OUTPUT STREAM

SETFLE:	JUMPE	T2,CPOPJ##	;IGNORE NON-POINTERS
	PUSHJ	P,SAVT##	;PRESERVE THESE FOR CALLERS (EXCEPT T2)
SETFE1:	ILDB	T3,-2(P)	;GET NEXT CHARACTER OF SEQUENCE
	CAIG	T3,FLLFLG	;TERMINATOR? (NULL OR CRLF)
	JRST	SETFE2		;YES, TERMINATE
	SCNOFF			;NO, DISALLOW INTERRUPTS
	STCHK	T3,LDBEOP(U),SETFE4	;STUFF IN ECHO OUTPUT STREAM
	AOS	LDBEOC(U)	;COUNT SPECIAL OUTPUT CHARS
	SCNON			;ALLOW INTERRUPTS AGAIN
	JRST	SETFE1		;LOOP UNTIL EXHAUST POINTER

;HERE WHEN POINTER EXHAUSTED FOR CRLF CHECK
SETFE2:	JUMPE	T3,SETFE3	;NULL MEANS REALLY DONE
	PUSHJ	P,SCNBOL	;ELSE IS CRLF, SO BE SURE AT LEFT MARGIN
	PUSHJ	P,SETFLC	;GET OUR FILLER CLASS
	MOVE	T2,FLLCRP(T2)	;GET MATCHING CRLF POINTER
	MOVEM	T2,-2(P)	;SAVE AS CALLER'S BYTE POINTER
	JRST	SETFE1		;AND REENTER LOOP
SETFE3:	MOVSI	T2,LOLESP	;ECHO STREAM PENDING
	IORM	T2,LDBOST(U)	;SET IN STATES WORD
	POPJ	P,		;RETURN TO CALLER

;HERE WHEN NO MORE ROOM IN CHUNKS FOR ECHO STREAM
SETFE4:	SCNON			;INTERRUPTS AGAIN
	PUSHJ	P,ECHBRK	;WAKE UP THE OWNER
	PUSHJ	P,SNDXOF	;STOP INPUT UNTIL ROOM IN CHUNKS
	MOVSI	T2,LOLNBS!LOLESP;SEND BELL+XOFF, ECHO STREAM PENDING
	IORM	T2,LDBOST(U)	;SET IN STATES WORD
	POPJ	P,		;RETURN TO CALLER
;DISPATCH TO SET FILLERS FOR SOME CHARACTERS

SETFLD:	IFIW	FILLH		;010  BACKSPACE
	IFIW	FILLI		;011  HORIZONTAL TAB
	IFIW	FILLJ		;012  LINEFEED
	IFIW	FILLK		;013  VERTICAL TAB
	IFIW	FILLL		;014  FORMFEED
	IFIW	FILLM		;015  CARRIAGE RETURN

;POINTERS, CODE AND DATA FOR FILLER CHARACTERS

;HERE FOR A BACKSPACE AND HARDWARE VERTICAL TAB

FILLH:
FILLK2:	PUSHJ	P,SETFLC	;GET FILLER CLASS FOR LINE
	MOVE	T2,FILLHP(T2)	;GET FILLER BYTE POINTER
	JRST	FLLPOP		;GO STORE AND RETURN.
;HERE TO GENERATE FILLERS OR SIMULATION FOR HORIZONTAL TAB
;PHPOS IS UPDATED ALREADY, BUT POHPOS HAS THE PREVIOUS POSITION,
;LOW ORDER THREE BITS, SO THE TAB SIMULATION CAN BE DONE FROM IT.

FILLI:
IFN FTNET,<
	SKIPGE	LDBTTW(U)	;ANF NETWORK TERMINAL DOES ITS OWN FILL
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	JRST	ZFLPOP		;SO NO FILLERS
>
	PUSHJ	P,SETFLC	;GET FILLER CLASS
	TLNN	T4,LDLTAB	;USE TAB, OR MAKE IT OUT OF SPACES?
	JRST	FILLI1		;SPACES.
	TRNN	T2,1		;FILL CLASS 0 OR 2?
	JRST	ZFLPOP		;YES, NO FILLERS
	LDB	T1,POHPOS	;GET OLD POSITION ON LINE.
	MOVE	T2,FILLP2	; ASSUME UNDER HALFWAY TO TAB STOP
	TRNE	T1,4		;TRUE?
	MOVE	T2,FILLP1	;NO. NEED JUST ONE FILLERS.
	JRST	FLLPOP		;GO STORE FILLER POINTER, SEND
				; TAB, AND RETURN.

;HERE TO MAKE A TAB OUT OF SOME SPACES.

FILLI1:	MOVEI	T3,CK.IMG+040	;WILL USE SPACES. DISCARD SAVED
				; TAB ON STACK.
				; IMAGE BIT BECAUSE HPOS NOW RIGHT
	LDB	T1,POHPOS	;GET LOW 3 BITS OF OLD HPOS
	MOVE	T2,FILLIP(T1)	;GET CORRESPONDING POINTER TO SPACES
	JRST	SCCHPJ		;TYPE FILLERS AND RETURN



;HERE TO HANDLE LINE FEED

FILLJ:	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FILLJP(T2)	;GET THE CORRESPONDING FILLERS
	JRST	FLLPOP		;FOR A LINEFEED, AND RETURN.
;HERE TO HANDLE VERTICAL TAB

FILLK:	TLNE	T4,LDLFRM	;THIS LINE HAVE FORM MOTION?
	JRST	FILLK2		;YES. USE SAME FILLERS AS BACKSPACE
	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FLLKSP(T2)	;GET SIMULATION POINTER
	PJRST	SCCHPJ		;TYPE STRING BUT NOT CHARACTER



;HERE TO HANDLE FORM FEED

FILLL:	TLNE	T4,LDLFRM	;THIS LINE HAVE FORM MOTION?
	JRST	FILLL1		;YES. GO SET FILLERS.
	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FLLLSP(T2)	;GET POINTER TO LINEFEEDS AND FILLERS
	PJRST	SCCHPJ		;GO TO COMMON CODE

FILLL1:	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FILLLP(T2)	;AND FILLER POINTER
	JRST	FLLPOP		;GO STORE THIS POINTER AND RETURN

FILLM:	TLNE	T1,CHFILO	;NO, IS THIS FOR IN OR OUTPUT?
	JRST	FILLM1		;OUTPUT.
	MOVEI	T2,L2RXON	;XON BIT
	TDNE	T2,LDBBY2(U)	;XON IN EFFECT?
	JRST	ZFLPOP		;NO LOCAL, OR XON TRUE. THEREFORE,
	MOVE	T2,LDBDCH(U)	;GET DCH BITS BACK
	TDNN	T2,[XWD LDLLCP,LDRHLF]	;EITHER TYPE OF LOCAL COPY?
					; NO FREE CRLF, OR IT WILL BE ECHOED
	JRST	FILLM1		;NO LOCAL COPY
	PUSHJ	P,SETFLC	;GET FILL CLASS
	MOVE	T2,FLLCRP(T2)	;NEED A FREE LINEFEED.GET CRLF
	IBP	T2		;AND COUNT IT PAST CR
	JRST	FLLPOP		;AND GO STORE RESULT

FILLM1:	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FLLCOP(T2)	;GET FILLERS FOR CR OUTPUT
	JRST	FLLPOP		;GO STORE AND RETURN
;HERE FOR CONTROL-R COMMAND

RETYPE::SE1ENT			;ENTER SECTION 1
IFN FTNET,<			;IF WE HAVE THE NETWORK, WE
	SKIPGE	LDBREM(U)	; BETTER MAKE SURE THAT THIS ISN'T A VTM
	POPJ	P,		; CAUSE IF IT IS, THE CHUNKS ARE ALL
>				; MESSED UP AND WE WILL "RCC"
	MOVEI	T1,L1RMIF	;WE WANT THE 'MIC' (RECINT) INTERLOCK
	MOVSI	T2,LOLPIM	;BIT THAT MEANS THIS WON'T WORK
	SCNOFF			;ONLY ONE AT A TIME...
	TDNE	T1,LDBBYT(U)	;CAN WE HAVE IT?
	JRST	[SCNON		;NO, ALLOW OTHERS
		 JRST	DLYCM1##] ; AND WAIT UNTIL WE CAN HAVE THE INTERLOCK
	TDNE	T2,LDBOST(U)	;YES, BUT ARE WE IN PACKED IMAGE MODE?
	JRST	SONPPJ		;OOPS, THIS WON'T WORK, JUST PRETEND
	IORM	T1,LDBBYT(U)	;IT'S OK, GET IT
	SCNON			;SAFE TO ALLOW OTHERS NOW
	MOVEI	T3,MC.RTS	;GET THE FUNCTION CHARACTER TO START IT GOING
	SETZ	T1,		;PRETEND IT HAS NO FLAGS
	PUSHJ	P,RECINA	;STORE IT IN THE INPUT CHUNKS
	PJRST	RECINU		;GIVE AWAY THE INTERLOCK AND RETURN


STOPCM:	PUSH	P,T1		;SAVE T1
	MOVEI	T1,0		;GET A ZERO AND USE IT TO
	SCNOFF			;INTERLOCK W.R.T. CCTYI
	PUSHJ	P,CTISBP	;  SAY THERE IS NO COMMAND ON THIS LINE
	MOVSI	T1,L1LQCC	;COMMAND CHARACTER QUOTE BIT
	ANDCAM	T1,LDBBYT(U)	;CLEAR IT
	MOVSI	T1,L3LCHD!L3LCPD ;8-BIT TRANSLATION BITS
	ANDCAM	T1,LDBBY3(U)	;NO MORE EXPANSION IN PROGRESS
	SCNON			;RETURN INTERLOCK
	JRST	TPOPJ##		;RESTORE T1 AND RETURN
	SUBTTL	FILL CHARACTER DATA

FILLER:	BYTE	(9) 177,177,177,177	;BLOCK OF 23 RUBOUTS
	BYTE	(9) 177,177,177,177
FILLRX:	BYTE	(9) 177,177,177,177
	BYTE	(9) 177,177,177,177
FILLRY:	BYTE	(9) 177,177,177,177
FILLRZ:	BYTE	(9) 177,177,177,0	;ZERO TERMINATES THE STRING

KSPACE:	BYTE	(9) 040,040,040,040	;BLOCK OF 8 SPACES.
	BYTE	(9) 040,040,040,040
	BYTE	(9) 0

FILLIP:	POINT	9,KSPACE	;POINTERS FOR TAB SIMULATION
	POINT	9,KSPACE,8
	POINT	9,KSPACE,17
	POINT	9,KSPACE,26
	POINT	9,KSPACE,35
	POINT	9,KSPACE+1,8
	POINT	9,KSPACE+1,17
	POINT	9,KSPACE+1,26

FLSLD0:	BYTE	(9) 12,12,12,12	;LINEFEEDS W/O FILLERS.
FLSKD0:	BYTE	(9) 12,12,12,12	; ..
	BYTE	(9) 0

FLSLD1:	BYTE	(9) 177,177,12,177	;LINEFEEDS WITH 2 FILLERS.
	BYTE	(9) 177,12,177,177
	BYTE	(9) 12,177,177,12
FLSKD1:	BYTE	(9) 177,177,12,177
	BYTE	(9) 177,12,177,177
	BYTE	(9) 12,177,177,12
	BYTE	(9) 177,177,0
FLLKSP:	POINT	9,FLSKD0	;POINTERS TO SIMULATE ^K
	POINT	9,FLSKD0
	POINT	9,FLSKD1
	POINT	9,FLSKD1

FLLLSP:	POINT	9,FLSLD0	;POINTERS TO SIMULATE ^L
	POINT	9,FLSLD0
	POINT	9,FLSLD1
	POINT	9,FLSLD1

FLBLXF:	BYTE	(9) 007,023,177,0	;DATA - BELL,XOFF,RUBOUT
FLPBEL::POINT	9,FLBLXF	;POINTER TO BELL-XOFF-RUBOUT
FLBPXF:	BYTE	(9) 023,0,0,0	;DATA - XOFF SANS FILL
FLPPXF::POINT	9,FLBPXF	;POINTER TO XOFF WITH NO FILL
FLLXON:	BYTE	(9) 21,177,0	;DATA - XON,RUBOUT
FLPXON:	POINT	9,FLLXON	;POINTER TO XON-RUBOUT
FLLFLG==:1			;FLAG TO ADD A CRLF AFTER THIS FILLER

FILXCP:	POINT	9,FILXCD	;CONTROL C ECHO
FILXCD:	BYTE	(9) 136,103,FLLFLG	;^C CRLF
FILXUP:	POINT	9,FILXUD	;CONTROL U ECHO
FILXUD:	BYTE	(9) 134,136,125,FLLFLG	;BACKSLASH ^U CRLF
FILXOP:	POINT	9,FILXOD	;CONTROL O ECHO
FILXOD:	BYTE	(9) 136,117,FLLFLG	;^O CRLF
FILXZP:	POINT	9,FILXZD	;POINTER TO CONTROL Z ECHO
FILXZD:	BYTE	(9) 136,132,FLLFLG	;^Z CRLF

;DISPATCH FOR ^Q TO ^T ECHOES

STFLT2:	POINT	9,FILXQD
	POINT	9,FILXRD
	POINT	9,FILXSD
	POINT	9,FILXTD

FILXQD:	BYTE	(9) 136,121,21,177,0	;^Q
FILXRD:	BYTE	(9) 136,122,22,177,0	;^R
FILXSD:	BYTE	(9) 023,136,123,0	;^S
FILXTD:	BYTE	(9) 24,136,124,0	;^T
					;POINTERS FOR BS AND VT
FILLHP:	0				;NO FILLERS
FILLP2:	POINT	9,FILLRZ,8	;2 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS

FILLLP:					;POINTERS FOR FORMFEED
	0				;NO FILLERS
	POINT	9,FILLRX,26	;12 FILLERS
	POINT	9,FILLER,17	;21 FILLERS
	POINT	9,FILLER,17	;21 FILLERS

FILLJP:					;POINTERS FOR LINEFEED
	0				;NO FILLERS
FILLP1:	POINT	9,FILLRZ,17	;1 FILLER
	POINT	9,FILLRY,8	;6 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS

FLLCRP::POINT	9,FLLCR0	;TABLE OF POINTERS FOR FREE CRLF'S
	POINT	9,FLLCR1
	POINT	9,FLLCR2
	POINT	9,FLLCR2

FLLCR0:	BYTE	(9) 015,12,0	;DATA FOR FREE CRLF'S
FLLCR1:	BYTE	(9) 015,015,12,177,0
FLLCR2:	BYTE	(9) 015,015,12,177,177,177,177,177,0

FLLUPA:	POINT	9,FLLUP1	;POINTER TO UPARROW
FLLDLR:	POINT	9,FLLUP1,17	;POINTER TO DOLLARSIGN
FLLUP1:	BYTE	(9) 136,0,44,0	;UPARROW AND $
FLLBSP:	POINT	9,FLLBS1	;POINTER TO BACKSLASH
FLLBS1:	BYTE	(9) 134,0,134,FLLFLG	;BACKSLASH DATA
FLLBSC:	POINT	9,FLLBS1,17	;POINTER TO BACKSLASH - CRLF
FLLCRF:	POINT	9,FLLBS1,26	;POINTER FOR CRLF IN FILL STREAM

FLLCOP:	0				;FILLERS FOR OUTPUT CR
	POINT	9,FLLCO1,17	;ONE EXTRA CR
	POINT	9,FLLCO1
	POINT	9,FLLCO1
FLLCO1:	BYTE	(9) 015,015,015,0	;EXTRA CARRIAGE RETURNS
	SUBTTL	TIMING ROUTINE

;SUBROUTINE CALLED EVERY SECOND AT CLOCK LEVEL.
;CHECKS FOR IRMA. TIMES IMAGE INPUT. RUNS MODEMS.

SCNSEC::SE1ENT			;ENTER SECTION 1
	MOVEI	J,TCONLN##	;PREPARE TO SEARCH LINE TABLE
	PUSHJ	P,SAVE2##
IFN FTMP,<MOVE P2,.CPCPN##>	;CPU #
	SETZM	%SCNAL
SCNSIL:	MOVE	U,LINTAB##(J)	;GET ADR OF LDB
	MOVE	T1,LDBDCH(U)	;GET THE CHARACTERISTICS
IFN FTMP,<			;IF SMP, CHECK WHICH CPU WE'RE ON
	LDB	T2,LDPCPU	;GET # OF LINE'S OWNER
	CAIN	T2,PCLCP0##	;BOOT CPU?
	MOVE	T2,BOOTCP##	;YES, GET REAL BOOT CPU NUMBER
	CAIE	T2,(P2)		;ARE WE ON RIGHT CPU
	JRST	SCNSIS		;IF WRONG CPU, SKIP THIS LINE
>
	TLNE	T1,LDLIMI	;IMAGE INPUT STATE?
	PUSHJ	P,SCSIMG	;YES. GO TIME IT
	MOVE	T1,LDBDCH(U)	;SCSIMG CAN CLOBBER THIS
IFN FTKL10,<
	HRRZ	T2,LDBISR(U)	;GET ISR DISPATCH
	CAIN	T2,TTDDSP##	;RSX20F LINE?
	PUSHJ	P,TTDSIN##	;YES, DO HUNG CHECKING FOR -20F LINES
> ;END IFN FTKL10
	JUMPL	T1,SCNSIN	;IF IDLE?
	AOS	%SCNAL
	TRNE	T1,LDRSHC!LDR2741 ;YES - HUNG CHECKING?
	JRST	SCNSIN		;NO
	MOVSI	T1,LPLIRM	;SET UP SYNC BIT
	TDNE	T1,LDBPAG(U)	;ON FROM 1 SECOND AGO?
	JRST	[PUSHJ P,TOREQ	;REQUEUE SO OUTPUT STARTS
		 MOVSI	P1,L1LOFL
		 MOVEI	T1,ISROFL
		 PUSHJ	P,@LDBISR(U)
		   IORM	P1,LDBOFL(U)
		 JRST   SCNSIN]	;LOOK AT NEXT LINE
	IORM	T1,LDBPAG(U)	;TURN ON SYNC BIT FOR THIS SECOND
SCNSIN:	MOVE	T1,LDBTIC(U)
	ADD	T1,LDBECC(U)
	SKIPE	T1
	AOS	%SCNAL
	SKIPL	LDBOFL(U)
	JRST	SCNSIT
	MOVSI	P1,L1LOFL
	MOVEI	T1,ISROFL
	PUSHJ	P,@LDBISR(U)
	  SKIPA
	ANDCAM	P1,LDBOFL(U)
SCNSIT:	PUSHJ	P,TMRIDL	;IS THIS LINE IDLE?
	JRST	SCNSIR		;NO, RESET ADT AND LOOK AT NEXT LINE
	AOS	T1,LDBBY3(U)	;YES, BUMP THE COUNTER (COUNT-UP VALUE)
	TRNN	T1,L3RTMO	;DID IT TIME OUT?
	JRST	SCNSIS		;NO, JUST LOOP ON
	MOVEI	T3,IRRTMO	;YES, WANT TIMEOUT FUNCTION
	MOVEI	T1,ISRREM	;OF REMOTE HANDLER
	PUSHJ	P,@LDBISR(U)	;TRY TO FORCE THE DISCONNECT
	  JRST	SCNSIR		;WE DECIDED TO RESET THE TIMER
	SETZ	T1,		;IT WORKED.  GET A ZERO
	PUSHJ	P,SCNADT	;CLEAR THE TIMER SO WE DON'T KEEP TRYING
	PUSHJ	P,TTYOPR	;RESET DEVOPR IF NECESSARY
SCNSIS:	SOJGE	J,SCNSIL
IFN FTMP,<
	SKPCPU	(0)		;ONLY ON MASTER
	PJRST	@.CPISR##
>
	SOSGE	SNDCTR##
	SETZM	SNDCTR##
	AOS	T2,%SCNAL
	CAIGE	T2,20
	MOVEI	T2,20
	MOVE	T1,TTFREN##
	IMULI	T1,CK.CPC##
	IDIV	T1,T2
	CAIGE	T1,TTIBRK##	;AT LEAST TTIBRK MINIMUM LEVEL?
	MOVEI	T1,TTIBRK##	;NO, PEG IT AT TTIBRK LEVEL
	MOVEM	T1,TIWRNN	;STORE NEW LIMIT
				;FALL THRU INTO DATASET ROUTINE
;ROUTINE TO DO ONCE-A-SECOND TIMING OF MODEMS. TIMES OUT INTERVALS
;FROM RING TO CARRIER ON, FROM CARRIER ON TO LEGAL COMMAND,
; AND FROM CARRIER OFF TO HANG UP.
;IF LINE IS IDLE (IDLE DEFINED AS NO ASSOCIATED DDB, AND NOT HOSTED AWAY)
;A DISCONNECT TIMER (IDLSEC) IS STARTED. WHEN IT TIMES OUT, THE DATASET
;IS HUNG UP

	SKIPL	J,DSCPTR##	;GET DATASET CONTROL POINTER
	JRST	DSCSC1		;THERE ARE NONE IN THIS CONFIGURATION
	HLLZS	J		;CLEAR RIGHT HALF FOR INDEXING
DSCSLP:	MOVE	T1,DSCTAB##(J)	;GET TABLE ENTRY
	TLNE	T1,DSCBLI	;BLIND STILL ON?
	JRST	DSCSC3		;YES.
	TLNN	T1,DSCHWC!DSCTMM;CARRIER OR TIMER SET?
	JRST	DSCSNY		;NO, SKIP SCN OFF
	SCNOFF			;CAN'T ALLOW INTERRUPTS HERE
	HRRZ	U,T1		;GET LINE NUMBER
	MOVE	U,LINTAB##(U)	;GET LDB ADDRESS
	HLRZ	T3,T1		;GET CONTROL BITS
	ANDI	T3,DSCHWC!DSCSWC!DSCFAI!DSCNCR!DSCBLI ;MASK TO RELEVANT BITS
	CAIE	T3,DSCHWC!DSCSWC ;NORMAL SIGNAL STATE?
	JRST	DSCSL0		;NO, DON'T CHECK FOR JOB (TIMER'S SIGNIFICANT)
	HRRZ	F,LDBDDB(U)	;GET DDB ADDRESS
	SKIPN	F		;IS THERE A DDB?
	JRST	DSCSL0		;NO, CHECK TIMING
	MOVE	T1,DEVMOD(F)	;YES, GET MODE WORD
	TRNE	T1,ASSCON!ASSPRG ;THIS TTY ASSIGNED?
	JRST	[SETZM T3	;YES, CLEAR TIMER,
		 DPB T3,DSTIMP	; STORE NEW VALUE,
		 SCNON		; ALLOW INTERRUPTS
		 JRST DSCSNY]	; AND DON'T TURN OFF DATASET
	MOVE	T1,DSCTAB##(J)	;NO, GET BACK TABLE ENTRY
	LDB	T3,DSTIMP	;GET TIMER WE'RE EXPIRING
	JRST	DSCSL1		; AND CONTINUE TIMING
DSCSL0:	LDB	T3,DSTIMP	;GET THE TIME SINCE RING OR CARRIER FAILURE
	JUMPN	T3,DSCSL1	;JUMP IF STILL TIMING
	TLNN	T1,DSCHWC	;SEE IF HARDWARE CARRIER
	JRST	DSCSL1		;NO, KEEP GOING
IFN FTNET,<
	SKIPL	LDBREM(U)	;SKIP IF VTM SET HOSTED AWAY
>
	MOVEI	T3,M.DIDL##	;LINE IDLE, START DISCONNECT TIMER
DSCSL1:	SOSL	T3		;COUNT IT DOWN. WAS IT 0?
	DPB	T3,DSTIMP	;NO. STORE NEW VALUE
	JUMPN	T3,[SCNON	;UNLESS NEWLY 0, ALLOW INTERRUPTS
		    JRST DSCSNY]; AND GO TO NEXT
	MOVSI	T3,DSCFAI+DSCSWC;CLEAR FAIL AND SOFTWARE BITS
	ANDCAB	T3,DSCTAB##(J)	; IN CORE
	SCNON			;OK FOR INTERRUPTS NOW.
	TLNE	T3,DSCDLW	;IN DIALLER WAIT?
	JRST	DSCSDF		;YES. DIALLER HAS FAILED.

	HRRZ	U,T1		;GET LINTAB INDEX
	MOVE	U,LINTAB##(U)	;GET THE LDB ADDRESS
				; OF THE RELATED TERMINAL LINE
IFN FTNET,<
	SKIPGE	LDBREM(U)	;IF THIS IS A VTM LINE,
	PUSHJ	P,VTMDSF##	;  SIGNAL CARRIER OFF TO THE REMOTE
>
	PUSHJ	P,LDBCLR	;CLEAR OUT LDB STATUS
	HRRZ	F,LDBDDB(U)	;SEE IF THERE'S A JOB.
	JUMPE	F,DSCSC2	;SKIP THIS IF NO JOB
	MOVE	T1,DEVMOD(F)	;MAY BE A JOB. GET MODE WORD.
	TLNN	T1,TTYATC	;CONTROLLING A JOB.
	JRST	DSCSC2		;NOT A CONTROLLING TERMINAL. NO COMMAND

	PUSHJ	P,DSCDET	;DETACH THE GUY (.BYE)
DSCSC2:	MOVEI	T3,DSTOFF	;SOFTWARE CODE TO TURN OFF DATASET
	MOVEI	U,0(J)		;TABLE ADDRESS AS LINE NUMBER
	PUSHJ	P,DSCCAL	;SEND TO APPROPRIATE HARDWARE DEVICE
DSCSNY:	AOBJN	J,DSCSLP	;COUNT THROUGH ALL LINES
DSCSC1:	PJRST	@.CPISR##	;DO ISR TIMING
;STILL IN FTMODM
DSCSC3:	MOVSI	T3,DSCBLI	;SET FOR BLIND BIT
	TLNE	T1,DSCNCR	;NEW CARRIER BIT STILL ON?
	MOVSI	T3,DSCNCR	;YES. CLEAR IT INSTEAD
	ANDCAM	T3,DSCTAB##(J)	;CLEAR BIT IN TABLE
	JRST	DSCSNY		;AND GO ON TO NEXT MODEM

DSCSDF:	SETOM	TTYDDL##	;CLEAR DIALLER CODE INTERLOCK
	MOVEI	U,0(J)		;COPY TABLE INDEX
	PUSHJ	P,DSROF1	;CLEAR OUT THE HARDWARE FOR THIS LINE.
	MOVSI	T1,DSCDLF	;FLAG THAT DIALLING LOST
	IORB	T1,DSCTAB##(J)	; ..
	PUSHJ	P,DSCWAK	;WAKE THE SLEEPING JOB, IF ANY
	JRST	DSCSNY		;LOOK FURTHER THRU DSCTAB

DSCWAK:	HRRZS	T1		;TOSS JUNK
	MOVE	T1,LINTAB##(T1)	;GET THE LDB ADDRESS FOR THIS DATASET'S TERMINAL
	HRRZ	F,LDBDDB(T1)	;GET THE DDB, IF ANY
	SKIPE	T1		;ANY?
	LDB	T1,PJOBN##	;YES. GET JOB NUMBER
	JUMPE	T1,CPOPJ##	;ANY?
	PJRST	WAKJOB##	;YES. WAKE IT.

DSTIMP:	POINT	9,DSCTAB##(J),17	;POINTERS TO TIME BYTE
DSTMPL:	POINT	9,DSCTAB##(U),17	;SAME BUT DIFFERENT AC INDEX
				;MUST AGREE WITH DSCTMM
;SUBROUTINE TO TIME THE IMAGE MODE INPUT STATE, SET END OF FILE IF
;IT TIMES OUT, AND FORCE CONTROL C UNLESS SLAVED ON SECOND TIME-OUT


SCSIMG:	PUSH	P,J		;SAVE COUNTER. WILL BE CLOBBERED.
	LDB	T3,LDPTIM	;GET THE IMAGE TIME BYTE
	SOSL	T3		;COUNT IT DOWN. TOO LOW?
	DPB	T3,LDPTIM	;NO STORE NEW VALUE.
	JUMPG	T3,IPOPJ##	;IF NO TIMEOUT YET, GO BACK TO LOOP
	HRRZ	F,LDBDDB(U)	;GET LINE'S JOB DATA BLOCK
	JUMPE	F,SCSIM2	;NO JOB? TIME AGAIN
	MOVSI	S,FRCEND	;CAUSE UUO ROUTINE TO FORCE END
	TDNE	S,DEVIOS(F)	;ON YET?
	JRST	SCSIM1		;ON ALREADY. PANIC.
	IORB	S,DEVIOS(F)	;NO. SET IT NOW AND TIME OUT AGAIN
SCSIM2:	MOVEI	T3,IMGTIM	;SET TIME TO NEXT PANIC
	DPB	T3,LDPTIM	;STORE IN TIME BYTE
	PUSHJ	P,RCVWAK	;AND WAKE UP JOB
	JRST	IPOPJ##		;GO RESTORE J AND RETURN

SCSIM1:	MOVSI	S,TTYATC	;GET A BIT
	TDNE	S,DEVMOD(F)	;IS THIS AN I/O DEVICE?
	TLNE	T1,LDLSLV	;IS THIS A SLAVE TERMINAL?
	JRST	SCSIM2		;YES. CAN'T DO CONTROL C
	PUSHJ	P,CNCMOD	;NO. SET TO COMMAND LEVEL
	MOVSI	T1,LDBCMF	;FORCE COMMAND
	DPB	T1,LDPCMX	;CONTROL C INDEX
	IORM	T1,LDBCOM(U)	;AND FLAG COMMAND DECODER
	PUSHJ	P,COMSET	;WAKE UP COMMAND ROUTINE,
	JRST	IPOPJ##		;RESTORE AC AND RETURN
;ROUTINES TO HANDLE THE AUTO-DISCONNECT TIMER

SCNADT::SKIPL	T1		;IF TIMER IS OUT OF RANGE,
	CAILE	T1,377		;IN EITHER DIRECTION,
	MOVEI	T1,377		;JUST USE OUR MAXIMUM
	DPB	T1,LDPMXT	;STORE THE MAXIMUM IDLE TIME
SCNAD1:	MOVNS	T1		;MAKE NEGATIVE FOR COUNT-UP LOGIN
	ANDI	T1,377		;KEEP ONLY 8 BITS (9-BIT FIELD FOR OVERFLOW)
	DPB	T1,LDPTMR	;STORE FOR SCNSIT
	POPJ	P,		;RETURN TO CALLER

RSTTMR:	LDB	T1,LDPMXT	;GET ADT VALUE
	JUMPN	T1,SCNAD1	;RE-SET COUNTER IF WE CARE
	POPJ	P,		;JUST RETURN IF WE DON'T

;HERE FROM SCNSIT WHEN WE WANT TO RESET THE TIMER

SCNSIR:	PUSHJ	P,RSTTMR	;RESET THE TIMER
	JRST	SCNSIS		;LOOP THROUGH LINTAB

;HERE FROM SCNSIT TO SEE IF WE WANT TO TIME THIS LINE

TMRIDL:	LDB	T1,LDPMXT	;GET THE ADT INITIAL VALUE
	JUMPE	T1,CPOPJ##	;IF NO TIMING, WE DON'T CARE
	SCNOFF			;MUSN'T ALLOW OTHERS TO CONFUSE US
	SKIPN	F,LDBDDB(U)	;SEE IF WE HAVE A DDB
	JRST	TMRID1		;SOME CHECKS DON'T APPLY IF NOT
	MOVE	T1,DEVMOD(F)	;YES, GET MODE BITS
	TRNE	T1,ASSCON!ASSPRG ;IS IT IN USE?
	JRST	SONPPJ		;YES, DON'T TIME IT OUT
TMRID1:	MOVE	T1,LDBDCH(U)	;GET CHARACTERISTICS WORD
IFN FTNET,<
	SKIPL	LDBREM(U)	;DON'T TIME IT IF IT'S HOSTED AWAY
		.CREF	LRLVTM	;NOTE BIT WE TESTED
>
	TLNE	T1,LDLSLV	;IS IT A SLAVE?
	JRST	SONPPJ		;YES, DON'T TIME IT OUT
	SKIPGE	LDBCOM(U)	;ANY COMMANDS PENDING?
	JRST	SONPPJ		;YES, IT'S NOT IDLE AFTER ALL
;ADD POSSIBLE FUTURE CHECKS HERE
	JRST	SONPJ1		;NO SAVING ATTRIBUTES, TIME IT OUT
;OUTPUT SERVICE ROUTINE FOR CTY

IFN FTKS10,<
CTYSTO::MOVEI	T1,.CPCTQ##	;POINT TO CTY OUTPUT QUEUE HEADER
	PUSHJ	P,TOTAKE	;GET A LINE NUMBER (CHECK QUEUE)
	  POPJ	P,		;NONE WAITING
	SKIPGE	LDBDCH(U)
	PUSHJ	P,XMTCHR	;GET NEXT OUTPUT CHARACTER
	  POPJ	P,		;LINE IS NOW IDLE
	PUSHJ	P,CLRIRM	;CLEAR IRMA BIT
CTYTYO:	ANDI	T3,377		;REMOVE JUNK
	MOVE	T1,LINTAB##+KLILIN##
	CAIN	T1,(U)		;KLINIK LINE?
	JRST	KLITYO		;YES--GO TO IT
	IORI	T3,CTYOVL	;SET VALID FLAG
	MOVEM	T3,CTYOWD	;PUT IN OUTPUT WORD
CTYTY1:	RDAPR	T1		;GET CPU PI LEVEL
	ANDI	T1,SP.PIA	; AND ONLY THE PI LEVEL
	WRAPR	SP.SSF+SP.IFE(T1) ;INTERRUPT THE 8080
	POPJ	P,0		;AND RETURN
KLITYO:	IORI	T3,KLIOVL	;SET VALID BIT
	MOVEM	T3,KLIOWD	;PUT CHAR IN OUTPUT WORD
	JRST	CTYTY1		;GO INTERRUPT 8080
>;END IFN FTKS10
;ROUTINE TO ADJUST HORIZONTAL POSITION COUNT FOR CHARACTER TO
;OUTPUT FROM BUFFER. CALL WITH T3, U SET UP.

ADJHP:	PUSH	P,T3		;SAVE CHARACTER
	ANDI	T3,CK.CHR	;JUST CHARACTER BITS
	CAIN	T3,177		;RUBOUT
	JRST	T3POPJ##	;DOESN'T SPACE
	CAIL	T3,40		;NON-IMAGE CONTROL CHARACTER?
	JRST	ADJHP1		;NO, SIZE IS ONE
	PUSH	P,T2
	MOVE	T2,-1(P)	;GET FULL CHARACTER AGAIN
	TRNE	T2,CK.MET	;WERE WE CALLED FOR A QUOTED CHARACTER?
	JRST	T23PPJ		;YES, IT'S NOT SIGNIFICANT TO US
	CAIN	T3,11		;IS THIS A TAB?
	JRST	ADJHP2		;YES, GO FIGURE OUT HOW BIG IT IS
	CAIN	T3,15		;CARRIAGE RETURN?
	JRST	ADJHP3		;SETS HPOS BACK TO START
	CAIE	T3,10		;BACKSPACE?
	JRST	T23PPJ		;NO, OTHER DON'T CHANGE HPOS
	PUSHJ	P,HPOS		;GET CURRENT POSITION
	JUMPE	T2,T23PPJ	;IF AT START OF LINE
	SOS	LDBHPS(U)	;ELSE DECREMENT POSITION BY ONE
	JRST	T23PPJ		;AND RETURN

;HERE FOR CARRIAGE RETURN

ADJHP3:	PUSHJ	P,SCNBOL	;BACK TO START OF LINE
	JRST	T23PPJ		;AND RETURN

;HERE FOR TAB

ADJHP2:	PUSHJ	P,HPOS		;CURRENT HORIZONTAL POSITION
	DPB	T2,POHPOS	;SAVE LOW 3 BITS FOR SIMULATION
	ANDI	T2,7		;ISOLATE (POSITION MOD 8)
	MOVN	T2,T2		; -(POSITION MOD 8)
	ADDI	T2,10		; 8-(POSITION MOD 8)
	ADDM	T2,LDBHPS(U)	;FIX HPOS COUNTER
	JRST	T23PPJ		;AND RETURN

;HERE FOR PRINTING CHARACTER

ADJHP1:	AOSA	LDBHPS(U)	;INCREMENT POSITION
T23PPJ:	POP	P,T2
	JRST	T3POPJ##
;HPOS -- SUBROUTINE TO FETCH THE CURRENT HORIZONTAL POSITION ON A LINE
;CALL
;	PUSHJ	P,HPOS
;	<ALWAYS RETURN HERE>
;EXIT WITH T2 = HORIZONTAL POSITION.  PRESERVES ALL OTHERS AC'S.

HPOS::	SE1ENT			;ENTER SECTION 1
	LDB	T2,LDPWID	;GET CARRIAGE WIDTH
	ADD	T2,LDBHPS(U)	;COMPUTE HORIZONTAL POSITION
	POPJ	P,		;AND RETURN IT


;ROUTINE TO SET A LINE BACK TO THE BEGINNING

SCNBOL:	PUSH	P,T2		;SAVE ALL AC'S
	LDB	T2,LDPWID	;GET WIDTH
	MOVNM	T2,LDBHPS(U)	;INITIAL VALUE OF HORIZONTAL POS COUNTER
	MOVEI	T2,0
	DPB	T2,POHPOS	;INITIAL LOW ORDER 3 BIT COUNTER
	JRST	T2POPJ##	;RESTORE T2 AND RETURN


;ROUTINE TO CLEAR PROMPT POS FOR THIS LINE

CPRPOS:	PUSH	P,T2		;SAVE ALL AC'S
	MOVSI	T2,LDLPPS	;PROMPT POS SET BIT
	ANDCAM	T2,LDBDCH(U)	;CLEAR IT
	JRST	T2POPJ##	;RESTORE T2 AND RETURN
;ROUTINE TO SUPPRESS BLANK LINES

BLSUPI:	PUSHJ	P,HPOS		;GET HORIZONTAL POSITION
	HRLI	T2,LPLSLF	;  (LPLSLF BIT IN LH)
	TRZE	T2,-1		;ANYTHING ON THIS LINE?
	ANDCAM	T2,LDBPAG(U)	;YES - CLEAR BIT TO ALLOW L.F.
	PUSH	P,T3		;SAVE CHARACTER
	ANDI	T3,CK.CHR	;REDUCE TO ASCII
	CAIL	T3,12		;IS CHARACTER LF, VT, OR FF?
	CAILE	T3,14		; . . .
	JRST	T3POPJ##	;NO
	IORM	T2,LDBPAG(U)	;SET BIT TO SUPPRESS LF'S
	JRST	T3POPJ##	;BUT ALWAYS ECHO INPUT <CR><LF>S

BLSUPO:	PUSHJ	P,HPOS		;GET HORIZONTAL POSITION
	HRLI	T2,LPLSLF	;  (LPLSLF BIT IN LH)
	TRZE	T2,-1		;ANYTHING ON THIS LINE?
	ANDCAM	T2,LDBPAG(U)	;YES - CLEAR BIT TO ALLOW L.F.
	PUSH	P,T3		;SAVE CHARACTER
	ANDI	T3,CK.CHR	;REDUCE TO ASCII
	CAIL	T3,12		;IS CHARACTER LF, VT, OR FF?
	CAILE	T3,14		; . . .
	JRST	[CAIN	T3,15		;IS IT A CR
		TDNN	T2,LDBPAG(U)	;YES, ARE WE SUPPRESSING LF'S
		JRST	T3POPJ##	;NO, JUST RETURN
		JRST	BLSUP1]		;YES, SUPPRESS CR'S TOO
	CAIN	T3,12		;YES-SUPPRESS LF?
	TDNN	T2,LDBPAG(U)
	SKIPA	T3,[12]		;NO-TURN VT OR FF INTO LF
BLSUP1:	MOVEI	T3,0		;YES-TURN LF INTO NULL
	IORM	T2,LDBPAG(U)	;SET BIT TO SUPPRESS LF'S
	MOVE	T1,CHTABL(T3)	;GET BITS FOR NEW CHARACTER
	PJRST	T2POPJ##	;DISCARD OLDE CHARACTER, RETURN
;SUBROUTINE TO WAKE UP JOB IF IT IS IN TERMINAL INPUT WAIT. CALL WITH
;LINE SET UP. IT WILL SET DDB AND S AS NEEDED.

RCVWAK:	HRRZ	F,LDBDDB(U)	;GET ADDRESS OF ATTACHED DDB
	JUMPE	F,CPOPJ##	;IF NONE,SKIP THIS CODE
	PUSH	P,T1		;SAVE T1
	LDB	T1,PJOBN##	;GET JOB NUMBER OF TERMINAL OWNER
	MOVSI	S,TTILCE##	;IS JOB ENABLED FOR WAKE UP
	TDNE	S,JBTRTD##(T1)	;DURING A HIBERNATE
	JRST	WAKJB		;YES, GO WAKE JOB
WAKJBR:	POP	P,T1		;RESTORE T1

	MOVE	S,DEVIOS(F)	;GET STATUS OF TERMINAL FROM DDB
IFN FTPI,<TLZ S,IO>		;MAKE SURE BIT IS RIGHT
	TLNE	S,IOW		;JOB IN I/O WAIT FOR TERMINAL?
	TLNE	S,TTYOUW	;YES. FOR INPUT WAIT?
IFN FTPI,<JRST PSIIOD##>	;GENERATE PSI SO USER WILL KNOW I/O IS DONE
IFE FTPI,<POPJ P,0>		;NO--DON'T WAKE JOB.

TTWAKE::SE1ENT			;ENTER SECTION 1
	PUSH	P,T1		;SAVE VOLATILE AC'S
	PUSH	P,T2		; ..
	LDB	T1,PJOBN##	;IS JOB # IN DDB ZERO?
	JUMPE	T1,TTWAKX	;EXIT IF ZERO
	MOVE	S,DEVIOS(F)	;MAKE SURE S IS CORRECT
IFN FTPSCD,<
	MOVE	T1,LDBDCH(U)	;LINE CHARACTERISTICS
	JUMPL	S,TTWAKO	;OUTPUT?
	TRNE	T1,LDRPTY	;INPUT. PTY?
	AOSA	%PISJB##	;YES
	  AOS	%TISJB##	;NO
	JRST	TTWAKB
TTWAKO:	TRNE	T1,LDRPTY	;OUTPUT. PTY?
	AOSA	%POSJB##	;YES
	  AOS	%TOSJB##	;NO
TTWAKB:>
	MOVEI	S,IOACT		;CLEAR I/O ACTIVE
	ANDCAB	S,DEVIOS(F)	;IN DDB FOR THIS JOB
	PUSHJ	P,STTIOD##	;CALL STTIOD FOR TERMINALS, PTYS
TTWAKX:	POP	P,T2		;RESTORE AC'S
	PJRST	TPOPJ##		;RETURN FROM RCVWAK

;ROUTINE TO SEE IF CHARACTER SPECIAL HANDLING SHOULD BE SUPPRESSED
;PRESERVES T1

FULLCQ:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  TLNN	T2,LDLBKA+LDLFCS ; NO. DOES USER WANT ALL CHACTERS?
	AOS	(P)		;NO. COMMAND OR NOT SMART USER
	POPJ	P,		;SMART USER. NON-SKIP RETURN.
WAKJB:	PUSH	P,T2		;SAVE AC'S
	PUSH	P,T3
	MOVSI	T2,(JS.HIB)	;IS JOB SLEEPING
	TDNE	T2,JBTST2##(T1)	;OR HIBERNATING?
	PUSHJ	P,WAKJOB##	;HIBERNATING: WAKE THE JOB
	POP	P,T3		;RESTORE THE AC'S
	POP	P,T2
	JRST	WAKJBR		;RETURN TO NORMAL PROGRAM FLOW

;THE FOLLOWING ROUTINE IS CALLED BY THE HIBERNATE UUO TO
;PUT THE TERMINAL INTO CHARACTER MODE.  T1 IS PRESERVED.

HIBTTY::SE1ENT			;ENTER SECTION 1
	PUSH	P,T1		;SAVE T1
	PUSHJ	P,TTYFND	;FIND THIS JOB'S TTY
	JUMPE	U,TPOPJ##	;NO TERMINAL FOR THIS JOB
	MOVSI	T1,TTIACE##	;HIBERNATE IN CHARACTER MODE?
	TDNN	T1,JBTRTD##(J)
	JRST	HIBTTL		;NO, IT MUST BE LINE MODE
	PUSHJ	P,TTCCHK	;CHECK IF A CHARACTER IS ALREADY PRESENT
	  JRST	TPOPJ##		;NO LINE, ECHO STARTED
HIBSET:	MOVSI	T1,WAKEB##	;LINE OR CHARACTER PRESENT
	IORM	T1,JBTRTD##(J)	;DON'T HIBERNATE
	PJRST	TPOPJ##		;RESTORE T1 AND RETURN (TO UUOCON)
HIBTTL:	PUSHJ	P,TTLCHK	;CHECK FOR A LINE PRESENT
	  JRST	TPOPJ##		;NO LINE, ECHO STARTED
	JRST	HIBSET		;YES, DON'T GO TO SLEEP
SUBTTL	CHTRN. UUO

;CALL:	XMOVEI	AC,LOCN
;		-OR-
;	MOVE	AC,[IFIW LOCN]
;
;	CALLI	AC,223
;	  <ERROR>
;	<SUCCESS>
;
;LOCN:	XWD	FLAGS,SOURCE-COUNT
;	SOURCE	BYTE POINTER WORD 1
;	SOURCE	BYTE POINTER WORD 2
;	XWD	MBZ,DEST-COUNT
;	DEST	BYTE POINTER WORD 1
;	DEST 	BYTE POINTER WORD 2

;THE BITS THAT CAN BE IN LH(SOURCE-COUNT-WORD)

CH.FBR==(1B0)		;FALLBACK REPRESENTATION (8-TO-7-BIT)
CH.OVR==(1B1)		;OVERSTRIKING ALLOWED
CH.RAI==(1B2)		;FOLD LOWER CASE TO UPPER
CH.6BT==(1B3)		;CONVERT ASCII TO SIXBIT
CH.IGN==(1B4)		;IGNORE EXCESS BITS
CH.ESC==(1B5)		;MAP 7-BIT ESCAPE SEQUENCES TO 8-BIT
CH.X6B==(1B6)		;EXPAND FROM SIXBIT TO ASCII

CH.INV==<(1B6)>-1	;UNKNOWN BITS

;THE ERRORS THAT CAN OCCUR

CHADC%==1		;ILLEGAL ADDRESS ENCOUNTERED
CHBYP%==2		;INVALID BYTE POINTER SUPPLIED
CHINV%==3		;UNKNOWN OR RESERVED FLAG BIT SPECIFIED
CHILC%==4		;ILLEGAL CHARACTER ENCOUNTERED DURING TRANSLATION
CHDCE%==5		;DESTINATION COUNT EXHAUSTED
CHIBC%==6		;INVALID BIT COMBINATION SPECIFIED

ERCODX	CHTADC,CHADC%
ERCODX	CHTIBP,CHBYP%
ERCODX	CHTILB,CHINV%
ERCODX	CHTILC,CHILC%
ERCODX	CHTDCE,CHDCE%
ERCODX	CHTIBC,CHIBC%
UCHTRN::PUSHJ	P,SAVUM##	;PRESERVE SOME ACS THAT WE USE
	PUSHJ	P,SAVE4##	;AND SOME MORE
	PUSHJ	P,SAVR##	;AND ANOTHER
IFN FTXMON,<
	PUSHJ	P,SSPCS##	;PRESERVE PCS (IN CASE WE CHANGE IT)
>
	MOVEI	T2,6		;OUR ARG BLOCK IS SIX WORDS LONG
	PUSHJ	P,ARNGE##	;VALIDATE THE ARG BLOCK
	  TRN			;INVALID ADDRESS AND ILLEGAL FOR I/O EQUALLY BAD
	  JRST	CHTADC		;ADDRESS CHECK ERROR FOR THESE
	PUSHJ	P,SXPCS##	;SET UP FOR READING ARGUMENTS
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	M,T1		;MOVE POINTER FOR GETEWD/GETEW1
	PUSHJ	P,GETEWD##	;GET THE FLAGS & SOURCE COUNT WORD
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	TLNE	T1,CH.INV	;ARE ANY UNKNOWN BITS SET?
	JRST	CHTILB		;ILLEGAL BITS ERROR
	TLC	T1,CH.6BT!CH.X6B	;CHECK SIXBIT BITS
	TLCN	T1,CH.6BT!CH.X6B	;WERE BOTH ON?
	JRST	CHTIBC		;YES--ILLEGAL BIT COMBINATION
	TLNE	T1,CH.6BT	;IF DEALING WITH SIXBIT,
	TLNN	T1,CH.ESC	;IT'S AN ERROR TO TRY TO COMPRESS ESCAPE
	TRNA			;NOT TRYING
	JRST	CHTIBC		;YES--ILLEGAL BIT COMBINATION
	TLNE	T1,CH.6BT	;GOING TO SIXBIT?
	TLO	T1,CH.FBR!CH.RAI;YES, TRY TO FORCE IT TO BE IN RANGE
	TLNE	T1,CH.6BT	;STILL GOING TO SIXBIT?
	TLZ	T1,CH.OVR	;YES, EXCLUDE BACKSPACE
	TLNE	T1,CH.X6B	;EXPANDING FROM SIXBIT?
	TLZ	T1,CH.ESC	;YES, NOT COMPRESSING ESCAPES IF NO ESCAPE
	MOVE	U,T1		;SAVE BITS & COUNT
	PUSHJ	P,GETEW1##	;GET FIRST HALF OF SOURCE BYTE POINTER
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	P1,T1		;SAVE IT
	PUSHJ	P,GETEW1##	;SET SECOND HALF
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	P2,T1		;SAVE IT
	PUSHJ	P,GETEW1##	;GET DESTINATION COUNT WORD
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	TLNE	T1,-1		;ANYTHING IN THE RESERVED FIELD?
	JRST	CHTILB		;ILLEGAL BITS ERROR
	MOVE	R,T1		;SAVE DEST COUNT
;HERE WHEN BITS CHECK OUT--GET BYTE POINTERS

	PUSHJ	P,GETEW1##	;GET FIRST HALF OF DESTINATION BYTE POINTER
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	P3,T1		;SAVE IT
	PUSHJ	P,GETEW1##	;GET SECOND HALF
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	P4,T1		;SAVE IT
	LDB	T1,[POINT 6,P1,5] ;GET P/P&S FIELD OF SOURCE B.P.
	CAIL	T1,77		;WITHIN RANGE OF VALID P FIELDS?
	JRST	CHTIBP		;ILLEGAL BYTE POINTER ERROR
	CAIG	T1,44		;IS IT A OWGBP?
	LDB	T1,[POINT 6,P1,11] ;NO, GET S FIELD
	SKIPN	T1		;DON'T BOTHER ME WITH NO-OPS
	JRST	CHTIBP		;BE NASTY ABOUT IT
	DMOVE	T1,P1		;COPY SOURCE B.P.
	HRRZ	T3,U		;AND SOURCE COUNT
	SUBI	M,3		;UPDATE CORRECT WORD
	PUSHJ	P,QRNGE##	;RANGE CHECK THE ADDRESSES
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	  TRN			;DON'T CARE IF CAN'T WRITE THIS ONE
	DMOVE	P1,T1		;GET MASSAGED B.P.
	ADDI	M,3		;POINT BACK TO THE END OF THE BLOCK
	LDB	T1,[POINT 6,P3,5] ;GET P/P&S FIELD OF DEST B.P.
	CAIL	T1,77		;WITHIN RANGE OF VALID P FIELDS?
	JRST	CHTIBP		;ILLEGAL BYTE POINTER ERROR
	CAIG	T1,44		;IS IT A OWGBP?
	LDB	T1,[POINT 6,P3,11] ;NO, GET S FIELD
	CAIGE	T1,6		;IS IT OF A MINIMUM REASONABLE SIZE?
	JRST	CHTIBP		;COMPLAIN IF NOT
	DMOVE	T1,P3		;COPY DEST B.P.
	HRRZ	T3,R		;AND DEST COUNT
	PUSHJ	P,QRNGE##	;RANGE CHECK
	  TRN			;INVALID PAGE(S) OR ILLEGAL FOR I/O ARE BOTH BAD
	  JRST	CHTADC		;SO GIVE ADDRESS CHECK ERROR FOR THESE
	DMOVE	P3,T1		;COPY MASSAGED B.P.
	TLNE	U,CH.IGN	;IF WE DON'T CARE ABOUT EXTRA BITS,
	JRST	CHTRNQ		;DON'T CHECK BYTE SIZES
	LDB	T1,[POINT 6,P1,11] ;GET SOURCE BYTE SIZE
	LDB	T2,[POINT 6,P3,11] ;GET DEST. BYTE SIZE
	CAIL	T2,8		;ALL CHARACTERS FIT INTO EIGHT BITS,
	JRST	CHTRNQ		;SO DON'T CHECK
	TLNE	U,CH.ESC	;IF COMPRESSING ESCAPES,
	JRST	CHTIBP		;WE NEED EIGHT BITS
	CAIL	T2,7		;IF WE HAVE SEVEN,
	JRST	CHTRNQ		;JUST TRY IT
	TLNN	U,CH.6BT	;UNLESS GOING TO SIXBIT,
	JRST	CHTIBP		;WE NEED MORE THAN 6-BIT BYTES
CHTRNQ:	PUSHJ	P,CHTRNP	;PRE-FETCH THE SOURCE AND DEST WORDS
	  POPJ	P,		;PROPAGATE ERROR

;HERE WHEN THE ARG LISTS SEEM TO CHECK OUT.  TIME TO START TRANSLATING.
;TRANSLATION LOOP

CHTRN1:	PUSHJ	P,CHTRNR	;READ NEXT SOURCE BYTE
	  JRST	CHTRNE		;ERROR ALREADY STORED--UPDATE BLOCK
	TLNE	U,CH.X6B	;EXPANDING SIXBIT?
	JRST	[TLNE	U,CH.IGN	;YES, IGNORING EXTRA BITS?
		 ANDI	T1,77		;YES, DO SO
		 CAIL	T1,0		;IN RANGE?
		 CAILE	T1,77		;EITHER WAY?
		 JRST	CHTIVC		;NO--ILLEGAL CHARACTER
		 ADDI	T1,40		;YES, MAKE ASCII
		 JRST	CHTRN2]		;AND GO STORE
CHTRN6:	TLNE	U,CH.IGN	;IGNORE EXTRA BITS?
	ANDI	T1,CK.CHR	;YES, DO SO
	CAIN	T1,33		;IF THIS IS ESCAPE,
	TLNN	U,CH.ESC	;AND WE CARE
	JRST	CHTRN4		; (NO TO EITHER)
	TRNN	U,-1		;IF NO MORE TO READ,
	JRST	CHTRN4		;CAN'T COMPRESS
	PUSHJ	P,CHTRNR	;GET NEXT CHARACTER
	  JRST	CHTRNE		;PROPAGATE ERRORS
	CAIL	T1,100		;IS IT IN RANGE
	CAILE	T1,137		;OF COMPRESSIBLE ESCAPES?
	JRST	CHTRN5		;NO, MUST DO THIS THE HARD WAY
	TRC	T1,300		;YES, FUDGE IT
	JRST	CHTRN4		;AND GO STORE IT
CHTRN5:	PUSH	P,T1		;SAVE NEW CHARACTER
	MOVEI	T1,33		;GET THE ESCAPE
	PUSHJ	P,CHTRNW	;WRITE IT OUT
	  JRST	[POP	P,T1	;BALANCE STACK
		 JRST	CHTRNE]	;ERROR RETURN
	POP	P,T1		;RETRIEVE NEW CHARACTER
	JRST	CHTRN6		;AND GO STORE IT
CHTRN4:	TLNE	U,CH.IGN	;IGNORE EXTRA BITS?
	ANDI	T1,CK.CHR	;YES, DO SO
	CAIL	T1,0		;IS THIS A VALID CHARACTER?
	CAILE	T1,CK.CHR	;EITHER WAY?
	JRST	CHTIVC		;INVALID CHARACTER ERROR
	MOVE	T2,CHTABL(T1)	;GET BITS
	TLNE	T2,CHINVL	;IS THIS A RESERVED CHARACTER CODE?
	JRST	CHTIVC		;YES, GIVE INVALID CHARACTER ERROR
	TLNE	U,CH.RAI	;RAISE LETTERS?
	TLNE	T2,CHPUNC	;AND IS THIS ONE?
	JRST	CHTRN8		;NO OR NO, DON'T
	TRNE	T1,100		;ONLY IF ALPHA, AND NOT NUMERIC,
	TRZ	T1,40		;YES, FORCE UPPER CASE
CHTRN8:	CAILE	T1,CK.CH7	;IS THIS AN 8-BIT CHARACTER AND
	TLNN	U,CH.FBR	;ARE WE COMPRESSING TO 7-BIT?
	JRST	CHTRN2		;NO, DON'T BOTHER
	MOVE	T1,CHREQV-200(T1)	;YES, GET EQUIVALENCE STRING
	TLNN	T2,CH2PC	;IS IT MULTI-CHARACTER?
	JRST	CHTRN2		;NO, DON'T CHECK FOR BACKSPACE
	TLNN	U,CH.OVR	;ARE WE ALLOWING OVERPRINTING?
	TRNE	T1,767000	;NO, DOES THIS STRING CONTAIN BACKSPACE?
	JRST	CHTRN2		;YES OR NO, PASS IT
	HLRZS	T1		;NO AND YES, KEEP ONLY THE LAST CHARACTER
;	PJRST	CHTRN2		;FALL INTO WRITE LOOP, NEXT PAGE
;HERE TO LOOP OVER TRANSLATION STRING, STORING IN DEST. STRING BLOCK

CHTRN2:	MOVE	T2,T1		;COPY STRING
	ANDI	T2,CK.CHR	;KEEP ONLY CURRENT CHARACTER
	HLL	T2,CHTABL(T2)	;GET BITS FOR CHARACTER
	TLNE	U,CH.RAI	;IF UPCASING,
	TLNE	T2,CHPUNC	;AND THIS IS ALPHANUMERIC
	JRST	CHTRN7		;(NO OR NO)
	TRNE	T2,100		;ONLY IF ALPHA,
	TRZ	T2,40		;YES, ENFORCE UPPER CASE
CHTRN7:	ANDI	T2,CK.CHR	;MASK DOWN TO CHARACTER AGAIN
	TLNN	U,CH.6BT	;CONVERTING TO SIXBIT?
	JRST	CHTRN3		;NO, DON'T RANGE CHECK
	CAIL	T2,40		;YES, IS THIS IN RANGE?
	CAILE	T2,137		;EITHER WAY?
	JRST	CHTIVC		;NO, GIVE INVALID CHARACTER RETURN
	SUBI	T2,40		;YES, MAKE IT SIXBIT
CHTRN3:	PUSHJ	P,CHTRNW	;WRITE CURRENT BYTE
	  JRST	CHTRNE		;ERROR RETURN ALREADY STORED--UPDATE BLOCK
	LSH	T1,-9		;GET TO NEXT CHARACTER OF STRING
	JUMPN	T1,CHTRN2	;LOOP OVER ENTIRE TRANSLATION STRING
	TRNE	U,-1		;DONE WITH THIS INPUT BYTE,
	JRST	CHTRN1		;LOOP OVER ALL SOURCE BYTES
;	PJRST	CHTRNS		;FALL INTO ARG BLOCK UPDATE ROUTINE
;HERE TO STORE UPDATED BYTE POINTERS FOR THE USER

CHTRNS:	SUBI	M,5		;BACK UP TO START OF ARG BLOCK
	MOVE	T1,U		;FLAGS AND SOURCE COUNT
	PUSHJ	P,PUTEWD##	;STUFF FOR USER
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	T1,P1		;SOURCE B.P. WORD 1
	TLNE	T1,(1B12)	;GLOBAL B.P.?
	TRZA	T1,-1		;YES, CLEAR OUR JUNK
	HRR	T1,P2		;NO, FORM LOCAL B.P.
	PUSHJ	P,PUTEW1##	;STUFF FOR USER
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	T1,P2		;SOURCE B.P. WORD 2
	PUSHJ	P,PUTEW1##	;STUFF INTO BLOCK
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	T1,R		;DEST. COUNT
	PUSHJ	P,PUTEW1##	;STUFF INTO BLOCK
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	T1,P3		;DEST. B.P. WORD 1
	TLNE	T1,(1B12)	;GLOBAL B.P.?
	TRZA	T1,-1		;YES, CLEAR OUR JUNK
	HRR	T1,P4		;NO, FORM LOCAL B.P.
	PUSHJ	P,PUTEW1##	;PUT BACK FOR USER
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	T1,P4		;DEST. B.P. WORD 2
	PUSHJ	P,PUTEW1##	;WRITE TO ARG BLOCK
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	PUSHJ	P,CHTRW2	;ATTEMPT TO FINISH STORING THE DEST. STRING
	  POPJ	P,		;PROPAGATE ERROR (ALREADY STORED)
	JRST	CPOPJ1##	;RETURN SUCCESS TO USER
;HERE TO READ NEXT BYTE FROM USER'S ARG LIST

CHTRNR:	HRRI	U,-1(U)		;DECREMENT SOURCE COUNT
	HLLZS	P1		;CLEAR OLD JUNK FROM BYTE POINTER
	IBP	P1		;BUMP IT
	TRNN	P1,-1		;DID IT FLOW INTO NEXT WORD?
	JRST	CHTRR1		;NO, DON'T NEED TO FETCH
	PUSHJ	P,SAVUM##	;PRESERVE M
IFN FTXMON,<
	PUSHJ	P,SSPCS##	;AND PCS
>
	AOS	M,P2		;GOING TO FETCH FROM NEXT ADDRESS
IFN FTXMON,<
	PUSHJ	P,SMPCS##	;SETUP FOR RETRIEVAL
	  JRST	CHTADC		;ERROR IF CAN'T
>
	PUSHJ	P,GETEWD##	;FETCH FROM ARBITRARY SECTION
	  JRST	CHTADC		;ADDRESS CHECK ERROR RETURN
	MOVE	T4,T1		;PUT SOURCE WORD WHERE WE WANT IT
	PUSHJ	P,SCDCHK##	;AVOID KAF
CHTRR1:	HRRI	P1,T4		;POINT OUR B.P. TO OUR SOURCE WORD
	LDB	T1,P1		;FETCH NEXT (CURRENT) BYTE
	JRST	CPOPJ1##	;RETURN TO CALLER

;HERE TO WRITE NEXT BYTE TO USER'S DEST. STRING

CHTRNW:	TRNN	R,-1		;IS THERE ENOUGH ROOM TO STORE?
	JRST	CHTDCE		;NO, GIVE APPROPRIATE ERROR
	HRRI	R,-1(R)		;YES, DECREMENT DEST. COUNT
	HLLZS	P3		;CLEAR B.P. JUNK FROM LAST TIME
	IBP	P3		;BUMP DEST. POINTER
	TRNN	P3,-1		;DID WE ADVANCE TO NEXT WORD?
	JRST	CHTRW1		;NO, DON'T DEAL WITH WORD
	PUSHJ	P,SAVUM##	;PRESERVE M
IFN FTXMON,<
	PUSHJ	P,SSPCS##	;PRESERVE PCS
>
	MOVE	M,P4		;FOR STORING
IFN FTXMON,<
	PUSHJ	P,SMPCS##	;SETUP PCS
	  JRST	CHTADC		;GIVE UP IF CAN'T
>
	EXCH	T3,T1		;SETUP SOME ACS
	PUSHJ	P,PUTEWD##	;STORE THE WORD
	  JRST	[EXCH	T1,T3	;RESTORE ACS
		 JRST	CHTADC]	;ADDRESS CHECK ERROR
	PUSHJ	P,GETEW1##	;READ THE NEXT WORD WE'LL USE
	  JRST	[EXCH	T1,T3	;RESTORE ACS
		 JRST	CHTADC]	;ADDRESS CHECK ERROR
	EXCH	T3,T1		;RESTORE OUR ACS
	MOVE	P4,M		;SAVE UPDATED DEST. POINTER
CHTRW1:	HRRI	P3,T3		;POINT OUR B.P. TO OUR DEST. WORD
	DPB	T2,P3		;STORE CURRENT BYTE
	JRST	CPOPJ1##	;RETURN TO CALLER
;HERE TO STORE THE ILLEGAL CHARACTER ERROR AND UPDATE THE BLOCK

CHTIVC:	PUSHJ	P,[PUSHJ P,SAVUM##	;PRESERVE M
		   PJRST CHTILC]	;STORE ILLEGAL CHARACTER ERROR CODE
	;PJRST	CHTRNE		;UPDATE THE BLOCK AND GIVE AN ERROR RETURN

;HERE TO UPDATE THE ARG BLOCK ON AN ERROR RETURN

CHTRNE:	PUSHJ	P,CHTRNS	;STORE THE UPDATED ARGS IN THE BLOCK
	  POPJ	P,		;RETURN NON-SKIP
	POPJ	P,		;EVEN IF UPDATE SUCCEEDS

;HERE TO STORE CURRENT DEST. WORD FOR CHTRNS

CHTRW2:	PUSHJ	P,SAVUM##	;PRESERVE M
IFN FTXMON,<
	PUSHJ	P,SSPCS##	;AND PCS
	MOVE	T1,P4		;GET DEST. WORD
	PUSHJ	P,SXPCS##	;TRY TO GET THERE
	  JRST	CHTADC		;ADDRESS CHECK IF CAN'T
>
	MOVE	M,P4		;GET DEST WORD POINTER
	MOVE	T1,T3		;AND DEST. WORD
	PUSHJ	P,PUTEWD##	;TRY TO STORE
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	JRST	CPOPJ1##	;SUCCESS RETURN TO CHTRNS

;HERE WHEN THE ARGUMENTS LOOK GOOD.  PRE-FETCH THE SOURCE AND DEST WORDS.

CHTRNP:	PUSHJ	P,SAVUM##	;PRESERVE M
IFN FTXMON,<
	PUSHJ	P,SSPCS##	;AND PCS
>
	MOVE	T1,P2		;GET ADDRESS OF SOURCE WORD
	PUSHJ	P,SXPCS##	;SET FOR FETCHING
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	M,T1		;POINT TO IT
	PUSHJ	P,GETEWD##	;FETCH IT
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	T4,T1		;PUT IT IN OUR SOURCE WORD
	MOVE	T1,P4		;GET ADDRESS OF DEST. WORD
	PUSHJ	P,SXPCS##	;SET FOR FETCHING
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	M,T1		;POINT TO IT
	PUSHJ	P,GETEWD##	;FETCH IT
	  JRST	CHTADC		;ADDRESS CHECK ERROR
	MOVE	T3,T1		;SAVE IN OUR DEST. TEMP WORD
	JRST	CPOPJ1##	;RETURN SUCCESS
;TABLE OF CONTROL AND META CHARACTERS - LH=BITS, RH=DISP ADDR ON RCV INT

;DEFINITION OF BITS IN THESE TABLES
CHBRK==:1	;THIS IS A BREAK CHARACTER
CHUAE==:2	;THIS CHARACTER ECHOES AS ^X
CHFIL==4	;THIS CHARACTER REQUIRES FILLERS AT SOME SPEEDS
CHALT==:10	;THIS CHARACTER IS ONE OF THE THREE ALTMODES.
CHRIA==:20	;THIS CHARACTER REQUIRES RCV INT LEVEL ACTION
CHCRET==40	;THIS IS A CARRIAGE RETURN (NEEDED FOR SETFLO)
CHCNC==100	;THIS IS CONTROL C
CHINVL==:200	;THIS CHARACTER IS INVALID (RESERVED 8-BIT GRAPHIC)
CHFILO==400	;BIT ADDED FOR OUTPUT FILLER ROUTINE (NOT IN TABLE)
CHCRE==:1000	;THIS CHARACTER GETS CRLF AFTER ITS ^ X ECHO
CHVPOS==2000	;VERT. POSITIONING SIMULATED WITH FORM FEEDS
CHEPAR==:4000	;THIS BIT SET IF CHARACTER IS EVEN PARITY
CH2PC==10000	;THIS IS A 2-PART CHARACTER (META AND 8-BIT ONLY) (ALSO 3-PART)
CHPUNC==20000	;THIS IS A PUNCTUATION CHARACTER
CHNDFR==:40000	;THIS CHARACTER CANNOT BE DEFERRED (EVEN IF IN DEFERRED ECHO)
CHDEL==100000	;THIS IS DELETE (RUBOUT)
CHOOB==:200000	;OUT-OF-BAND CHARACTER (NOT IN TABLE)
CHSPO==400000	;REQUIRES SPECIAL CHECKING ON OUTPUT.  MUST BE THE
		;SIGN BIT.

CHTABL:	XWD	CHSPO+CHRIA+CHEPAR+CHPUNC,CPOPJ##		;^@ NUL 000
IFN FTMIC,<
	XWD	CHSPO+CHRIA+CHUAE+CHPUNC+CHNDFR,RICA		;^A SOH 001
>
IFE FTMIC,<
	XWD	CHSPO+CHUAE+CHPUNC,0				;^A SOH 001
>
IFN FTMIC,<
	XWD	CHSPO+CHRIA+CHUAE+CHPUNC+CHNDFR,RICB		;^B STX 002
>
IFE FTMIC,<
	XWD	CHSPO+CHUAE+CHPUNC,0				;^B STX 002
>
	XWD	CHSPO+CHUAE+CHBRK+CHRIA+CHCRE+CHCNC+CHEPAR+CHPUNC+CHNDFR,RICC	;^C ETX 003
	XWD	CHSPO+CHUAE!CHRIA+CHPUNC+CHNDFR,RICD		;^D EOT 004
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;^E ENQ 005
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;^F ACK 006
	XWD	CHSPO+CHBRK+CHPUNC,0				;^G BEL 007
	XWD	CHSPO+CHBRK+CHRIA+CHPUNC,RIBSP			;^H BS 010
	XWD	CHSPO+CHFIL+CHEPAR+CHPUNC,0			;^I HT  011
	XWD	CHSPO+CHFIL+CHBRK+CHEPAR+CHPUNC,0		;^J LF  012
	XWD	CHSPO+CHFIL+CHBRK+CHVPOS+CHPUNC,0		;^K VT  013
	XWD	CHSPO+CHFIL+CHBRK+CHVPOS+CHEPAR+CHPUNC,0	;^L FF  014
	XWD	CHSPO+CHRIA+CHFIL+CHCRET+CHPUNC,RICM		;^M CR  015
	XWD	CHSPO+CHUAE+CHPUNC,0				;^N SO  016
	XWD	CHSPO+CHNDFR+CHUAE+CHRIA+CHCRE+CHEPAR+CHPUNC,RICO ;^O SI  017
IFN FTMIC,<
	XWD	CHSPO+CHRIA+CHUAE+CHPUNC+CHNDFR,RICP		;^P DLE 020
>
IFE FTMIC,<
	XWD	CHSPO+CHUAE+CHPUNC,0				;^P DLE 020
>
	XWD	CHSPO+CHUAE+CHFIL+CHRIA+CHEPAR+CHPUNC+CHNDFR,RICQ ;^Q XON 021
	XWD	CHSPO+CHUAE+CHFIL+CHRIA+CHBRK+CHEPAR+CHPUNC,RICR;^R TAPE 022
	XWD	CHSPO+CHUAE+CHRIA+CHFIL+CHPUNC+CHNDFR,RICS	;^S XOFF 023
	XWD	CHSPO+CHUAE+CHFIL+CHRIA+CHBRK+CHEPAR+CHPUNC+CHNDFR,RICT ;^T- NTAPE 024
	XWD	CHSPO+CHRIA+CHBRK+CHPUNC,RICU			;^U NAK 025
	XWD	CHSPO+CHUAE+CHRIA+CHPUNC+CHNDFR,RICV		;^V SYN 026
	XWD	CHSPO+CHUAE+CHRIA+CHEPAR+CHPUNC+CHBRK,RICW	;^W ETB 027
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;^X CAN 030
	XWD	CHSPO+CHUAE+CHPUNC,0				;^Y EM  031
	XWD	CHSPO+CHUAE+CHBRK+CHCRE+CHPUNC,0		;^Z SUB 032
	XWD	CHSPO+CHBRK+CHALT+CHRIA+CHEPAR+CHPUNC,RIALT	;^[ ESC 033
	XWD	CHSPO+CHUAE+CHPUNC,0				;^\ FS  034
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;^] GS  035
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;^^ RS  036
	XWD	CHSPO+CHUAE+CHPUNC,0				;^_ US  037

	XWD	CHPUNC,0					;SPACE	040
	XWD	CHEPAR+CHPUNC,0					;!	041
	XWD	CHEPAR+CHPUNC,0					;"	042
	XWD	CHPUNC,0					;#	043
	XWD	CHEPAR+CHPUNC,0					;$	044
	XWD	CHPUNC,0					;%	045
	XWD	CHPUNC,0					;&	046
	XWD	CHEPAR+CHPUNC,0					;'	047
	XWD	CHEPAR+CHPUNC,0					;(	050
	XWD	CHPUNC,0					;)	051
	XWD	CHPUNC,0					;*	052
	XWD	CHEPAR+CHPUNC,0					;+	053
	XWD	CHPUNC,0					;,	054
	XWD	CHEPAR+CHPUNC,0					;-	055
	XWD	CHEPAR+CHPUNC,0					;.	056
	XWD	CHPUNC,0					;/	057
	XWD	CHEPAR,0					;0	060
		0						;1	061
		0						;2	062
	XWD	CHEPAR,0					;3	063
		0						;4	064
	XWD	CHEPAR,0					;5	065
	XWD	CHEPAR,0					;6	066
		0						;7	067
		0						;8	070
	XWD	CHEPAR,0					;9	071
	XWD	CHEPAR+CHPUNC,0					;:	072
	XWD	CHPUNC,0					;;	073
	XWD	CHEPAR+CHPUNC,0					;<	074
	XWD	CHPUNC,0					;=	075
	XWD	CHPUNC,0					;>	076
	XWD	CHEPAR+CHPUNC,0					;?	077
	XWD	CHPUNC,0					;@	100
	XWD	CHEPAR,0					;A	101
	XWD	CHEPAR,0					;B	102
		0						;C	103
	XWD	CHEPAR,0					;D	104
		0						;E	105
		0						;F	106
	XWD	CHEPAR,0					;G	107
	XWD	CHEPAR,0					;H	110
		0						;I	111
		0						;J	112
	XWD	CHEPAR,0					;K	113
		0						;L	114
	XWD	CHEPAR,0					;M	115
	XWD	CHEPAR,0					;N	116
		0						;O	117
	XWD	CHEPAR,0					;P	120
		0						;Q	121
		0						;R	122
	XWD	CHEPAR,0					;S	123
		0						;T	124
	XWD	CHEPAR,0					;U	125
	XWD	CHEPAR,0					;V	126
		0						;W	127
		0						;X	130
	XWD	CHEPAR,0					;Y	131
	XWD	CHEPAR,0					;Z	132
	XWD	CHPUNC,0					;[	133
	XWD	CHEPAR+CHPUNC,0					;/	134
	XWD	CHPUNC,0					;]	135
	XWD	CHPUNC,0					;^	136
	XWD	CHEPAR+CHPUNC,0					;_	137

;THESE LETTERS ARE LOWER-CASE
	XWD	CHEPAR+CHPUNC,0					;`	140
		0						;a	141
		0						;b	142
	XWD	CHEPAR,0					;c	143
		0						;d	144
	XWD	CHEPAR,0					;e	145
	XWD	CHEPAR,0					;f	146
		0						;g	147
		0						;h	150
	XWD	CHEPAR,0					;i	151
	XWD	CHEPAR,0					;j	152
		0						;k	153
	XWD	CHEPAR,0					;l	154
		0						;m	155
		0						;n	156
	XWD	CHEPAR,0					;o	157
		0						;p	160
	XWD	CHEPAR,0					;q	161
	XWD	CHEPAR,0					;r	162
		0						;s	163
	XWD	CHEPAR,0					;t	164
		0						;u	165
		0						;v	166
	XWD	CHEPAR,0					;w	167
	XWD	CHEPAR,0					;x	170
		0						;y	171
		0						;z	172
	XWD	CHEPAR+CHPUNC,0					;{	173
	XWD	CHPUNC,0					;|	174

;THE 3 HIGH SPECIALS
	XWD	CHSPO+CHRIA+CHEPAR+CHALT+CHPUNC,RIALT		;}      175
	XWD	CHSPO+CHRIA+CHEPAR+CHALT+CHPUNC,RIALT		;~      176
	XWD	CHSPO+CHBRK+CHRIA+CHPUNC+CHDEL,RIDEL		;   DEL 177
;HERE WE START THE 8-BIT CHARACTER EXTENSION

;DEFINE A COMMON SET OF BITS FOR INVALID GRAPHICS
CH8INV==CHSPO+CHBRK+CHPUNC+CHINVL

;NOW, DO THE TABLE
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;RESERVED 200
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;RESERVED 201
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;RESERVED 202
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;RESERVED 203
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;IND	204
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;NEL	205
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;SSA	206
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;ESA	207
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;HTS	210
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;HTJ	211
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;VTS	212
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;PLD	213
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;PLU	214
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;RI	215
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;SS2	216
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;SS3	217
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;DCS	220
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;PU1	221
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;PU2	222
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;STS	223
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;CCH	224
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;MW	225
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;SPA	226
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;EPA	227
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;RESERVED 230
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;RESERVED 231
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;RESERVED 232
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;CSI	233
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;ST	234
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;OSC	235
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;PM	236
	XWD	CHSPO+CHBRK+CHPUNC+CH2PC,0		;APC	237
	XWD	CH8INV,0				;RESERVED 240
	XWD	CHPUNC,0				;SP03	241
	XWD	CHPUNC+CH2PC,0				;SC04	242
	XWD	CHPUNC+CH2PC,0				;SC02	243
	XWD	CH8INV,0				;RESERVED 244
	XWD	CHPUNC+CH2PC,0				;SC05	245
	XWD	CH8INV,0				;RESERVED 246
	XWD	CHPUNC+CH2PC,0				;SM24	247
	XWD	CHPUNC+CH2PC,0				;SC01	250
	XWD	CHPUNC+CH2PC,0				;SM52	251
	XWD	CHPUNC+CH2PC,0				;SM21	252
	XWD	CHPUNC+CH2PC,0				;SP17	253
	XWD	CH8INV,0				;RESERVED 254
	XWD	CH8INV,0				;RESERVED 255
	XWD	CH8INV,0				;RESERVED 256
	XWD	CH8INV,0				;RESERVED 257
	XWD	CHPUNC,0				;SM19	260
	XWD	CHPUNC+CH2PC,0				;SA02	261
	XWD	CHPUNC,0				;NS02	262
	XWD	CHPUNC,0				;NS03	263
	XWD	CH8INV,0				;RESERVED 264
	XWD	CHPUNC,0				;SM17	265
	XWD	CHPUNC+CH2PC,0				;SM25	266
	XWD	CHPUNC,0				;SM26	267
	XWD	CH8INV,0				;RESERVED 270
	XWD	CHPUNC,0				;NS01	271
	XWD	CHPUNC+CH2PC,0				;SM20	272
	XWD	CHPUNC+CH2PC,0				;SP18	273
	XWD	CHPUNC+CH2PC,0				;NF04	274
	XWD	CHPUNC+CH2PC,0				;NF01	275
	XWD	CH8INV,0				;RESERVED 276
	XWD	CHPUNC,0				;SP16	277
	XWD	0,0					;LA14	300
	XWD	0,0					;LA12	301
	XWD	0,0					;LA16	302
	XWD	0,0					;LA20	303
	XWD	0,0					;LA18	304
	XWD	0,0					;LA28	305
	XWD	CH2PC,0					;LA52	306
	XWD	CH2PC,0					;LC42	307
	XWD	0,0					;LE14	310
	XWD	0,0					;LE12	311
	XWD	0,0					;LE16	312
	XWD	0,0					;LE18	313
	XWD	0,0					;LI14	314
	XWD	0,0					;LI12	315
	XWD	0,0					;LI16	316
	XWD	0,0					;LI18	317
	XWD	CH8INV,0				;RESERVED 320
	XWD	0,0					;LN20	321
	XWD	0,0					;LO14	322
	XWD	0,0					;LO12	323
	XWD	0,0					;LO16	324
	XWD	0,0					;LO20	325
	XWD	0,0					;LO18	326
	XWD	CH2PC,0					;LO52	327
	XWD	CH2PC,0					;LO62	330
	XWD	0,0					;LU14	331
	XWD	0,0					;LU12	332
	XWD	0,0					;LU16	333
	XWD	0,0					;LU18	334
	XWD	0,0					;LY18	335
	XWD	CH8INV,0				;RESERVED 336
	XWD	CH2PC,0					;LS61	337
	XWD	CH2PC,0					;LA13	340
	XWD	CH2PC,0					;LA11	341
	XWD	CH2PC,0					;LA15	342
	XWD	CH2PC,0					;LA19	343
	XWD	CH2PC,0					;LA17	344
	XWD	0,0					;LA27	345
	XWD	CH2PC,0					;LA51	346
	XWD	CH2PC,0					;LC41	347
	XWD	CH2PC,0					;LE13	350
	XWD	CH2PC,0					;LE11	351
	XWD	CH2PC,0					;LE15	352
	XWD	CH2PC,0					;LE17	353
	XWD	CH2PC,0					;LI13	354
	XWD	CH2PC,0					;LI11	355
	XWD	CH2PC,0					;LI15	356
	XWD	CH2PC,0					;LI17	357
	XWD	CH8INV,0				;RESERVED 360
	XWD	CH2PC,0					;LN19	361
	XWD	CH2PC,0					;LO13	362
	XWD	CH2PC,0					;LO11	363
	XWD	CH2PC,0					;LO15	364
	XWD	CH2PC,0					;LO19	365
	XWD	CH2PC,0					;LO17	366
	XWD	CH2PC,0					;LO51	367
	XWD	CH2PC,0					;LO61	370
	XWD	CH2PC,0					;LU13	371
	XWD	CH2PC,0					;LU11	372
	XWD	CH2PC,0					;LU15	373
	XWD	CH2PC,0					;LU17	374
	XWD	CH2PC,0					;LY17	375
	XWD	CH8INV,0				;RESERVED 376
	XWD	CH8INV,0				;RESERVED 377
;THE META-CHARACTERS (THE IMBEDDED FUNCTIONS)

	DEFINE	META(NM,BITS)<
MC.'NM==CK.MET+<.-METABL>
	XWD	CHSPO!BITS,MET'NM
>

METABL:
	META	NL,CHBRK+CHPUNC+CHFIL+CHCRET+CH2PC		;ACR
;*** BE SURE THAT ALL REAL 2-PART META CHARACTERS ARE ABOVE THIS LINE
	MAX2PM==.-METABL			;MAX INDEX OF REAL 2-PART METAS
	META	DL,CHPUNC+CHUAE+CHCRE				;^U
	META	DW,CHPUNC+CHUAE					;^W
	META	DC,CHPUNC					;DEL
	META	BS,CHPUNC+CHFIL					;^H
	META	NFC,CHPUNC+CH2PC				;.TONFC
	META	HPS,CHPUNC+CH2PC				;.TOHPS
	META	FLM,CHPUNC+CHCRET				;.TOFLM
	META	DEN,CHPUNC					;.TODEM ON
	META	DEF,CHPUNC					;.TODEM OFF
	META	CHP,CHPUNC					;SETCHP
	META	RTS,CHPUNC					;^R START
	META	RTE,CHPUNC					;^R END
	META	FRM,CHPUNC+CH2PC				;.TOFRM
	META	TAB,CHPUNC+CH2PC				;.TOTAB
	META	WID,CHPUNC+CH2PC				;.TOWID
  METLEN==.-METABL		;LENGTH OF METABL (FOR VALIDITY TESTS)

;SINCE WE SHOULD NEVER BE TRYING TO DISPATCH FOR EXPANDABLE META-CHARACTERS,
; DEFINE THEM HERE TO BE STOPCODES

METNL:	STOPCD	.,STOP,MCCWNE,	;++ META CHARACTER CALLED WHEN NOT EXPECTED
;HERE WE START THE CHARACTER EQUIVALENCE TABLES

;DEFINE A HELPER MACRO FOR BUILDING THE REPLACEMENT STRINGS
DEFINE	CHS(A,B,C,D),<BYTE (9) D,C,B,A>

;FIRST, THE TABLE FOR 'NORMAL' 8-BIT CHARACTERS (IE, TOP HALF OF ASCII SET)
CHREQV:
	CHS	033,100					;RESERVED 200
	CHS	033,101					;RESERVED 201
	CHS	033,102					;RESERVED 202
	CHS	033,103					;RESERVED 203
	CHS	033,104					;IND	204
	CHS	033,105					;NEL	205
	CHS	033,106					;SSA	206
	CHS	033,107					;ESA	207
	CHS	033,110					;HTS	210
	CHS	033,111					;HTJ	211
	CHS	033,112					;VTS	212
	CHS	033,113					;PLD	213
	CHS	033,114					;PLU	214
	CHS	033,115					;RI	215
	CHS	033,116					;SS2	216
	CHS	033,117					;SS3	217
	CHS	033,120					;DCS	220
	CHS	033,121					;PU1	221
	CHS	033,122					;PU2	222
	CHS	033,123					;STS	223
	CHS	033,124					;CCH	224
	CHS	033,125					;MW	225
	CHS	033,126					;SPA	226
	CHS	033,127					;EPA	227
	CHS	033,130					;RESERVED 230
	CHS	033,131					;RESERVED 231
	CHS	033,132					;RESERVED 232
	CHS	033,133					;CSI	233
	CHS	033,134					;ST	234
	CHS	033,135					;OSC	235
	CHS	033,136					;PM	236
	CHS	033,137					;APC	237
	CHS	137					;RESERVED 240
	CHS	041					;SP03	241
	CHS	174,010,143				;SC04	242
	CHS	075,010,114				;SC02	243
	CHS	137					;RESERVED 244
	CHS	075,010,131				;SC05	245
	CHS	137					;RESERVED 246
	CHS	123,143					;SM24	247
	CHS	170,010,117				;SC01	250
	CHS	050,103,51				;SM52	251
	CHS	137,010,141				;SM21	252
	CHS	074,074					;SP17	253
	CHS	137					;RESERVED 254
	CHS	137					;RESERVED 255
	CHS	137					;RESERVED 256
	CHS	137					;RESERVED 257
	CHS	157					;SM19	260
	CHS	137,010,053				;SA02	261
	CHS	062					;NS02	262
	CHS	063					;NS03	263
	CHS	137					;RESERVED 264
	CHS	165					;SM17	265
	CHS	120,162					;SM25	266
	CHS	056					;SM26	267
	CHS	137					;RESERVED 270
	CHS	061					;NS01	271
	CHS	137,010,157				;SM20	272
	CHS	076,076					;SP18	273
	CHS	061,057,064				;NF04	274
	CHS	061,057,062				;NF01	275
	CHS	137					;RESERVED 276
	CHS	077					;SP16	277
	CHS	101					;LA14	300
	CHS	101					;LA12	301
	CHS	101					;LA16	302
	CHS	101					;LA20	303
	CHS	101					;LA18	304
	CHS	101					;LA28	305
	CHS	101,105					;LA52	306
	CHS	054,010,103				;LC42	307
	CHS	105					;LE14	310
	CHS	105					;LE12	311
	CHS	105					;LE16	312
	CHS	105					;LE18	313
	CHS	111					;LI14	314
	CHS	111					;LI12	315
	CHS	111					;LI16	316
	CHS	111					;LI18	317
	CHS	137					;RESERVED 320
	CHS	116					;LN20	321
	CHS	117					;LO14	322
	CHS	117					;LO12	323
	CHS	117					;LO16	324
	CHS	117					;LO20	325
	CHS	117					;LO18	326
	CHS	117,105					;LO52	327
	CHS	057,010,117				;LO62	330
	CHS	125					;LU14	331
	CHS	125					;LU12	332
	CHS	125					;LU16	333
	CHS	125					;LU18	334
	CHS	131					;LY18	335
	CHS	137					;RESERVED 336
	CHS	163,163					;LS61	337
	CHS	140,010,141				;LA13	340
	CHS	047,010,141				;LA11	341
	CHS	136,010,141				;LA15	342
	CHS	176,010,141				;LA19	343
	CHS	042,010,141				;LA17	344
	CHS	141					;LA27	345
	CHS	141,145					;LA51	346
	CHS	054,010,143				;LC41	347
	CHS	140,010,145				;LE13	350
	CHS	047,010,145				;LE11	351
	CHS	136,010,145				;LE15	352
	CHS	042,010,145				;LE17	353
	CHS	140,010,151				;LI13	354
	CHS	047,010,151				;LI11	355
	CHS	136,010,151				;LI15	356
	CHS	042,010,151				;LI17	357
	CHS	137					;RESERVED 360
	CHS	176,010,156				;LN19	361
	CHS	140,010,157				;LO13	362
	CHS	047,010,157				;LO11	363
	CHS	136,010,157				;LO15	364
	CHS	176,010,157				;LO19	365
	CHS	042,010,157				;LO17	366
	CHS	157,145					;LO51	367
	CHS	057,010,157				;LO61	370
	CHS	140,010,165				;LU13	371
	CHS	047,010,165				;LU11	372
	CHS	136,010,165				;LU15	373
	CHS	042,010,165				;LU17	374
	CHS	042,010,171				;LY17	375
	CHS	137					;RESERVED 376
	CHS	137					;RESERVED 377

;AND HERE, THE ONE FOR META CHARACTERS
MCHEQV:
	CHS	015,012					;ACR	MC.NL
IFN <.-MCHEQV>-MAX2PM,<PRINTX ? PHASE ERROR BETWEEN METABL AND MCHEQV>
;ROUTINES TO CHECK IF NEED TO SET UP FOR CHARACTER EXPANSION
;CALL WITH CHARACTER ABOUT TO PROCESS IN T3.
;ON RETURN, WILL LEAVE CHARACTER UNCHANGED IF NO NEED TO EXPAND,
;OR WILL LIGHT THE APPROPRIATE EXPANSION BITS (IF ANY) AND RETURN THE
;FIRST CHARACTER OF THE EXPANSION IN T3.

;HERE FOR INPUT

TPCINP:	MOVSI	T1,L3LIHD	;GET INPUT BIT
	PUSHJ	P,TPCIE1	;SEE IF WE NEED TO DO ANYTHING
	  POPJ	P,		;NO, WE'RE DONE HERE
	SETO	T1,		;YES, WE NEED TO BACK UP BY ONE
	ADJBP	T1,LDBTIT(U)	;BACKSPACE OUR CHARACTER POINTER
	MOVEM	T1,LDBTIT(U)	;STORE BACK IN LDB
	AOS	LDBTIC(U)	;AND THERE'S ANOTHER TO BE READ
	POPJ	P,		;RETURN TO TYICC5

;HERE FOR ECHO

TPCECH:	PUSH	P,T2		;WE NEED T2 PRESERVED
	MOVSI	T1,L3LEHD	;GET ECHO BIT
	PUSHJ	P,TPCIE1	;SEE IF WE NEED TO DO ANYTHING
	  JRST	T2POPJ##	;NO, WE'RE DONE HERE
	SETO	T1,		;YES, WE NEED TO BACK UP BY ONE
	ADJBP	T1,LDBECT(U)	;BACKSPACE OUR CHARACTER POINTER
	MOVEM	T1,LDBECT(U)	;STORE BACK IN LDB
	AOS	LDBECC(U)	;THERE'S ANOTHER TO BE ECHOED
	POP	P,T2		;THIS NEXT IS WHAT T2 IS FOR
	SOS	T2,LDBTIC(U)	;AND ONE LESS TO BE READ
	POPJ	P,		;RETURN TO XMTECI

TPCIE1:	TDNE	T1,LDBBY3(U)	;ARE WE ALREADY DOING THIS?
	JRST	TPCNXT		;YES, GO SEE HOW FAR ALONG
	TRNE	T3,CK.NIS	;NO.  IF NOT IN STREAM,
	POPJ	P,		;THEN DON'T EXPAND IT
	TRNE	T3,CK.MET	;IF META CHARACTER,
	JRST	TPCINM		;THEN CHECK DIFFERENTLY
	TRNN	T3,CK.IMG	;IF IMAGE CHARACTER,
	SKIPL	LDBATR(U)	;OR 7-BIT TERMINAL,
	POPJ	P,		;THEN NO NEED TO EXPAND
	TLNE	T1,L3LEHD	;IF ECHOING,
	TRNN	T3,CK.FDE	;AND DONE BY REMOTE,
	TRNN	T3,CK.PAR	;OR IF 7-BIT CHARACTER,
	POPJ	P,		;THEN NO NEED TO EXPAND
	MOVSI	T4,LDL8BI	;8-BIT INPUT BY PROGRAM
	TDNE	T4,LDBDCH(U)	;CONVERSION NEEDED?
	POPJ	P,		;NO, RETURN UNCHANGED

;HERE, WE KNOW WE'RE GOING TO DO CONVERSION.  IT'S ONLY A MATTER OF HOW.

TPCALT:	ANDI	T3,CK.CHR	;MASK OFF FUNNY BITS
	MOVE	T2,CHTABL(T3)	;GET BITS FROM TABLE
	TLNN	T2,CH2PC	;TWO-PART CHARACTER?
	JRST	TPCALX		;NO, RETURN JUST ONE CHARACTER
	TLNE	T1,L3LEHD!L3LIHD!L3LCHD ;CHECKING FOR INPUT?
	JRST	TPCAL0		;YES, DON'T PASS OVERSTRIKE SEQUENCES
;	MOVSI	T2,LALCOS	;CAN OVERSTRIKE ATTRIBUTE
;	TDNE	T2,LDBATR(U)	;SET FOR THIS TERMINAL?
	MOVSI	T2,LALDIS	;DISPLAY TERMINAL BIT
	TDNN	T2,LDBATR(U)	;IF HARDCOPY, ASSUME LALCOS
	JRST	TPCAL1		;DON'T CHECK OVERSTRIKE SEQUENCE
TPCAL0:	MOVEI	T2,367000	;GET MASK TO TEST FOR BACKSPACE IN THE MIDDLE
	TDNN	T2,CHREQV-200(T3) ;IS THIS AN OVERSTRIKE SEQUENCE?
	JRST	TPCALQ		;YES, GIVE THIRD CHARACTER ALONE
TPCAL1:	IORM	T1,LDBBY3(U)	;SET PROGRESS BITS FOR MULTI-PART CHARACTER
	AOS	(P)		;SKIP RETURN MEANS TO CONTINUE
TPCALX:	MOVE	T3,CHREQV-200(T3) ;GET EQUIVALENCE SEQUENCE
	ANDI	T3,CK.CHR	;MASK DOWN TO FIRST FOR THIS CALL
	POPJ	P,		;RETURN THE ALTERED CHARACTER

TPCALQ:	HLRZ	T3,CHREQV-200(T3)	;LAST OF REGULAR CHARACTER ONLY
	POPJ	P,		;JUST RETURN ALTERED CHARACTER

;HERE FOR COMCON

TPCCOM:	MOVSI	T1,L3LCHD	;COMMAND (COMCON) PROGRESS BIT
	PUSHJ	P,TPCCO1	;SEE IF WE NEED TO DO ANYTHING
	  POPJ	P,		;NO, WE'RE DONE HERE
	SETO	T1,		;YES, GET B.P. DECREMENT
	ADJBP	T1,LDBCLP(U)	;BACK UP COMMAND POINTER
	MOVEM	T1,LDBCLP(U)	;STORE BACK IN LDB
	POPJ	P,		;RETURN TO CCTYI0

TPCCO1:	TDNE	T1,LDBBY3(U)	;HAVE WE BEEN HERE BEFORE?
	JRST	TPCNXT		;YES, GET NEXT BYTE OF EXPANSION
	TRNE	T3,CK.MET	;IF META,
	JRST	TPCINM		;CHECK DIFFERENTLY
	TRNN	T3,CK.IMG	;NO.  IF IMAGE OR
	TRNE	T3,CK.NIS	;IF NOT IN STREAM,
	POPJ	P,		;RETURN UNCHANGED
	TRNN	T3,CK.PAR	;IF 7-BIT CHARACTER,
	POPJ	P,		;THEN WE DON'T NEED CONVERSION
	JRST	TPCALT		;NEEDS CONVERSION, GO ALTER IT

;HERE FOR OUTPUT

TPCOUT:	MOVSI	T1,L3LOHD	;OUTPUT PROGRESS BIT
	PUSHJ	P,TPCOF1	;SEE IF ANYTHING NEEDS TO BE DONE
	  POPJ	P,		;NO, WE'RE ALL DONE HERE
	SETO	T1,		;YES, WE NEED TO BACK UP OUR POINTER
	ADJBP	T1,LDBTOT(U)	;SUBTRACT ONE
	MOVEM	T1,LDBTOT(U)	;STORE BACK IN LDB
	AOS	T4,LDBTOC(U)	;AND THERE'S ANOTHER TO BE TYPED
	POPJ	P,		;RETURN TO XMTCH1

;HERE FOR FILL

TPCFIL:	MOVSI	T1,L3LFHD	;FILL PROGRESS BIT
	PUSHJ	P,TPCOF1	;SEE IF ANYTHING NEEDS TO BE DONE
	  POPJ	P,		;NO, WE'RE ALL DONE HERE
	SETO	T1,		;YES, GET B.P. DECREMENT
	ADJBP	T1,LDBEOT(U)	;BACK UP OUR POINTER
	MOVEM	T1,LDBEOT(U)	;STORE BACK IN LDB
	AOS	LDBEOC(U)	;THERE'S ANOTHER TO GO
	POPJ	P,		;RETURN TO XMTESP

TPCOF1:	TDNE	T1,LDBBY3(U)	;ARE WE ALREADY DOING THIS?
	JRST	TPCNXT		;YES, GET NEXT BYTE FROM THE SEQUENCE
	TRNN	T3,CK.IMG	;NO.  IF IMAGE OR
	TRNE	T3,CK.NIS	;IF NOT IN STREAM,
	POPJ	P,		;RETURN UNCHANGED
	TRNE	T3,CK.MET	;IF META,
	JRST	TPCINM		;CHECK DIFFERENTLY
	SKIPL	LDBATR(U)	;IF 8-BIT TERMINAL,
	TRNN	T3,CK.PAR	;OR 7-BIT CHARACTER,
	POPJ	P,		;THEN DON'T NEED CONVERSION
	JRST	TPCALT		;NEEDS CONVERSION, GO ALTER IT

;HERE FOR META CHARACTER IN ANY MODE

TPCINM:	TRNE	T3,CK.IMG	;IS THIS FOR A QUOTED CHARACTER?
	JRST	TPCINQ		;YES, IT'S NOT REALLY META
	MOVE	T2,T3		;GET COPY OF CHARACTER
	ANDI	T2,CK.CHR	;MASK OFF FUNNY BITS
	CAIL	T2,MAX2PM	;IN RANGE OF REAL 2-PART METAS?
	POPJ	P,		;NO, DON'T TRANSLATE
	HLL	T2,METABL(T2)	;GET TABLE BITS IN LEFT HALF
	TLNN	T2,CH2PC	;EXPANDABLE CHARACTER?
	POPJ	P,		;NO, RETURN UNCHANGED
	IORM	T1,LDBBY3(U)	;YES, ALL TRANSLATABLE METAS ARE MULTIPLE
	MOVE	T2,MCHEQV(T2)	;SET PROGRESS BIT AND GET TRANSLATION
	ANDI	T2,CK.CHR	;MASK DOWN TO FIRST FOR THIS CALL
	ANDI	T3,CK.FDE	;PRESERVE ONLY THIS BIT FROM ORIGINAL
	IORI	T3,(T2)		;MERGE TO NEW CHARACTER TO RETURN
	JRST	CPOPJ1##	;GIVE BACK AN ALTERED CHARACTER

;HERE TO CHECK FOR QUOTING CHARACTER

TPCINQ:	TLNN	T1,L3LIHD!L3LCHD!L3LEHD ;WERE WE CALLED BY SOMEONE WHO CARES?
	POPJ	P,		;NO, FORGET ABOUT TRANSLATING IT
	IORM	T1,LDBBY3(U)	;SET FOR READING THE NEXT CHARACTER
	TLNN	T1,L3LEHD	;UNLESS THIS WAS FOR XMTECH,
	TRZ	T3,CK.MET	;CLEAR THE META BIT
	TRZ	T3,CK.CHR	;GET RID OF THE CHARACTER VALUE
	TRO	T3,26		;TURN INTO AN IMAGE-MODE ^V
	JRST	CPOPJ1##	;RETURN THE CHARACTER FOR TRANSLATION

;HERE TO GET THE NEXT VALUE FROM THE EQUIVALENCE STRING FOR THE CHARACTER IN T3.
;CONTROLLING PROGRESS BIT IS IN T1.  USES T2.

TPCNXT:	TRNE	T3,CK.IMG	;IS THIS FOR A QUOTED CHARACTER?
	JRST	TPCNXQ		;YES, GO DO IT
	MOVE	T2,T1		;NO, COPY PROGRESS BIT
	LSH	T1,TPCLSH	;CONVERT TO THIRD-PART BIT
	ANDI	T3,CK.MET+CK.FDE+CK.CHR;KEEP ONLY IMPORTANT BITS
	TDNE	T1,LDBBY3(U)	;NEED THIRD CHARACTER?
	JRST	TPCNX3		;YES, GO GET IT
	IOR	T1,T2		;GET BOTH CONTROL BITS IN ONE AC
	MOVE	T2,T3		;COPY CHARACTER
	ANDI	T2,CK.CHR	;MASK DOWN TO INDEX
	TRNE	T3,CK.MET	;META CHARACTER?
	SKIPA	T2,MCHEQV(T2)	;YES, GET META EQUIVALENCE
	MOVE	T2,CHREQV-200(T2) ;NO, GET CHARACTER EQUIVALENCE
	LSH	T2,-9		;DROP THE FIRST CHARACTER (ALREADY DONE)
	ANDCAM	T1,LDBBY3(U)	;CLEAR CONTROL BIT THAT BRINGS US HERE
	TRZN	T2,777000	;IF A THIRD CHARACTER,
	JRST	TPCALM		;(NO)
	IORM	T1,LDBBY3(U)	; THEN LIGHT PART-2 AND PART-3 BITS
	AOS	(P)		;SKIP RETURN MEANS TO CONTINUE
TPCALM:	ANDI	T3,CK.FDE	;KEEP THE ONLY IMPORTANT BIT
	IORI	T3,(T2)		;BUILD A NEW CHARACTER
	POPJ	P,		;RETURN THE NEXT CHARACTER IN SEQUENCE

TPCNX3:	IOR	T1,T2		;COMBINE PROGRESS BITS
	ANDCAM	T1,LDBBY3(U)	;DONE EXPANDING THIS CHARACTER
	MOVE	T2,T3		;COPY CHARACTER
	ANDI	T2,CK.CHR	;MASK DOWN TO INDEX
	TRNE	T3,CK.MET	;IF META,
	SKIPA	T2,MCHEQV(T2)	;THEN GET META EQUIVALENCE
TPCNXY:	MOVE	T2,CHREQV-200(T2) ;ELSE GET CHARACTER EQUIVALENCE
	HLRZS	T2		;POSITION THIRD (AND KNOWN LAST) CHARACTER
	JRST	TPCALM		;FIX UP FOR CK.FDE AND RETURN NEW CHARACTER

TPCNXQ:	ANDCAM	T1,LDBBY3(U)	;CLEAR BIT THAT BROUGHT US HERE
	TLNN	T1,L3LEHD	;UNLESS THIS WAS FOR XMTECH,
	TRZ	T3,CK.MET	;CLEAR THE CONFUSING BIT
	POPJ	P,		;GIVE DONE RETURN
;ROUTINE TO CHECK FOR A SPECIAL CHARACTER AND SET T1 TO ITS DESCRIPTOR
;ENTER WITH T3 SET UP
;SKIPS IF CHAR IS 0-37 OR 175-177
;IGNORES AND DOES NOT RETURN PARITY BIT (CHEPAR)


SPCHEK::SE1ENT			;ENTER SECTION 1
	TRNE	T3,CK.MET	;IMBEDDED FUNCTION CHARACTER?
	JRST	SPCHE3		;YES, HANDLE DIFFERENTLY
	TRNE	T3,CK.IMG	;IF IMAGE,
	JRST	SPCHE1		;THEN ALWAYS HANDLE NORMALLY
	MOVE	T1,T3		;COPY CHAR
	ANDI	T1,CK.CHR	;CLEAR BITS
	SKIPN	DINITF##	;U NOT SETUP IN ONCE ONLY
	SKIPL	LDBBKB(U)	;BREAK MASK SPECIFIED?
	JRST	SPCHE1		;NO, NORMAL PROCESSING
	PUSH	P,T2		;SAVE VOLATILE AC
	MOVSI	T2,LDLCOM	;COMMAND LEVEL BIT
	TDNE	T2,LDBDCH(U)	;ARE WE AT COMMAND LEVEL?
	JRST	[POP	P,T2	;YES, RESTORE AC
		 JRST	SPCHE1]	;HANDLE NORMALLY
	PUSHJ	P,TOPGCB	;NO, GET CHARACTER STATUS BYTE
	MOVE	T1,CHTABL(T1)	;GET THE CHARACTER'S BITS
	TRNE	T2,CC.BRK	;SHOULD IT BREAK?
	TLOA	T1,CHBRK	;YES,
	TLZ	T1,CHBRK	;OR NOT
	TRNE	T2,CC.NSA	;STOP ANY SPECIAL ACTION?
	TDZ	T1,[CHRIA!CHCRET!CHCNC!CHALT,,-1]	;YES
	TRNE	T2,CC.OOB	;IS IT OUT-OF-BAND?
	TLO	T1,CHOOB	;YES, LIGHT O-O-B FLAG
	POP	P,T2		;RESTORE T2
	JRST	SPCHE2		;AND GET OUT
SPCHE1:	TRNE	T3,CK.IMG	;IF IMAGE,
	TDZA	T1,T1		;NEVER SPECIAL
	MOVE	T1,CHTABL(T1)	;GET TABLE ENTRY
SPCHE2:	TLZ	T1,CHEPAR+CH2PC+CHPUNC ;CLEAR PARITY AND PUNCTUATION BIT
	SKIPE	T1		;SPECIAL?
	AOS	(P)		;YES--SKIP
	POPJ	P,		;RETURN

SPCHE3:	TRNN	T3,CK.IMG	;IS THIS A QUOTED CHARACTER?
	PJRST	RICRET		;NO, JUST RETURN META BITS
	MOVE	T1,T3		;YES, GET COPY OF CHARACTER
	ANDI	T1,CK.CHR	;KEEP ONLY RELEVANT PORTION
	HLLZ	T1,CHTABL(T1)	;GET ITS BITS
	TLZ	T1,CHRIA!CHFIL!CHCRE!CHALT!CHNDFR!CHBRK!CHCRET!CHCNC!CHVPOS!CHEPAR!CH2PC ;CLEAR CRUFTY BITS
	TRNE	T3,CK.CH7^!37	;IS IT A CONTROL CHARACTER?
	TLZE	T1,CHDEL	;OF EITHER FLAVOR?
	TLO	T1,CHUAE	;YES, ECHO IN UPARROW FORM
	POPJ	P,		;GIVE MUNDANE RETURN

RICRET:	MOVE	T1,T3		;GET COPY OF CHARACTER
	ANDI	T1,CK.CHR	;REDUCE TO JUST FUNCTION CODE
	MOVE	T1,METABL(T1)	;GET CHARACTER BITS
	JRST	CPOPJ1##	;THESE ARE ALWAYS SPECIAL
;SUBROUTINE TO GET EVEN PARITY USING CHEPAR BIT OF CHTABL
;CALLED FROM SCNSER,PTPSER AND IN ONCE

;CALLING SEQUENCE:  PUSHJ	P,PEVEN8

;ON ENTRY, T3 CONTAINS A CHARACTER IN BITS 28 TO 35,
; BITS 0 TO 27 ARE IGNORED

;ON EXIT, BIT 28 IS CHANGED IF NECESSARY SUCH THAT THE PARITY
; OF BITS 28 TO 35 IS EVEN, AND BITS
; 0 TO 27 ARE ALL 0

PEVEN8::ANDI	T3,CK.CH7	;CLEAR TO 7 BITS FOR INDEX
	PUSH	P,T1		;SAVE T1
	MOVE	T1,CHTABL(T3)	;GET CHARACTER TABLE ENTRY
	TLNN	T1,CHEPAR	;ALREADY EVEN
	TRO	T3,CK.PAR	;WAS NOT, PUT IN PARITY BIT
	JRST	TPOPJ##		;RESTORE T1 AND RETURN
	SUBTTL	CHUNK HANDLERS

;The routines NEWCKI and NEWCKO are provided only to support the
;macros LDCHK, LDCHKR, and STCHK.

;NEWCKO -- ROUTINE TO ADVANCE TO THE NEXT CHUNK WHEN PUTTING CHARACTERS
;	  INTO THE TERMINAL BUFFER CHUNKS.

NEWCKO::JUMPE	T1,NWCKO8	;NO CHUNKS AT ALL, INITIALIZE
	SSX	T1,MS.SCN	;GET SECTION NUMBER
	HRRZ	T2,CK.BTH##(T1)	;ADDRESS OF NEXT CHUNK IN CHAIN, IF ANY
	JUMPE	T2,NWCKO3	;ALLOCATE NEW CHUNK IF NONE THERE YET
	PUSHJ	P,RCCTST	;RANGE CHECK ALLEGED NEXT CHUNK ADDRESS
	  POPJ	P,		;WHOA - A BAD CHUNK ADDRESS
	JRST	NWCKO6		;SET BYTE POINTER AND RETURN

NWCKO3:	MOVEI	T2,CK.BTH##(T1)	;ADDRESS OF CURRENT CHUNK
	PUSHJ	P,GETCHK	;ALLOCATE A CHUNK FROM FREE LIST
	SSX	T1,MS.SCN	;GET SECTION NUMBER
	HRLZM	T2,(T1)		;BACK POINTER TO EXISTING LIST
	SSX	T2,MS.SCN	;GET SECTION NUMBER
	HRRM	T1,(T2)		;FORWARD POINTER TO NEW CHUNK
NWCKO5:	HRRZS	T2,T1		;POSITION NEW CHUNK INTO T2, AND
NWCKO6:	ADD	T2,[POINT CK.WID,1]	;MAKE A BYTE POINTER
	AOS	(P)		;INLINE FOR SPEED
	POPJ	P,		;AND RETURN

NWCKO8:	PUSHJ	P,GETCKZ	;GET A NEW CHUNK
	JRST	NWCKO5		;CONVERT TO BYTE POINTER AND RETURN


;NEWCKI -- ROUTINE TO ADVANCE TO THE NEXT CHUNK WHEN TAKING CHARACTERS
;	   OUT OF THE TERMINAL CHUNKS.  USES T1 - T3.

NEWCKI::SSX	T1,MS.SCN	;SET SECTION NUMBER
	HRRZ	T2,CK.BTH##(T1)	;ADDRESS OF NEXT CHUNK IN CHAIN
	PUSHJ	P,RCCTST	;RANGE CHECK ALLEGED CHUNK
	  POPJ	P,		;WHOA - BAD CHUNK ADDRESS
	SSX	T2,MS.SCN	;SET SECTION NUMBER
	HRRZS	(T2)		;CLEAR BACK POINTER
	HRRZS	T2		;BACK TO SECTION RELATIVE
	MOVEI	T1,CK.BTH##(T1)	;ADDRESS OF OLD (EMPTY) CHUNK
	PUSHJ	P,FRECHK	;FREE UP THE STALE CHUNK
	ADD	T2,[POINT CK.WID,1]	;MAKE FORWARD POINTER INTO A BYTE PTR
	AOS	(P)		;INLINE FOR SPEED
	POPJ	P,		;AND RETURN



;NEWCKS -- ROUTINE TO ADVANCE TO THE NEXT CHUNK WHEN TAKING CHARACTERS
;	   OUT OF THE TERMINAL CHUNKS.  DIFFERS FROM NEWCKI IN THAT THE
;	   STALE CHUNKS ARE NOT DELETED.

NEWCKS::SSX	T1,MS.SCN	;SET SECTION NUMBER
	HRRZ	T2,CK.BTH##(T1)	; ADDRESS OF NEXT CHUNK IN CHAIN
	PUSHJ	P,RCCTST	;GOODNESS-CHECK THE NEXT CHUNK
	  POPJ	P,		;WHOA - A JUNK CHUNK
	ADD	T2,[POINT CK.WID,1]	;MAKE FORWARD POINTER INTO A BYTE PTR
	AOS	(P)		;INLINE FOR SPEED
	POPJ	P,		;AND RETURN
;RCCTST  --  RANGE CHECK AND VERIFY CHUNK ADDRESS
;CALL IS:
;
;	MOVX	T2,<ADR>
;	PUSHJ	P,RCCTST
;	 ERROR (RCC STOPCD MESSAGE ISSUED)
;	OK
;
;PRESERVES ALL ACS

RCCTST:	JUMPE	T2,CL0STP	;DIFFERENTIATE CL0 AND RCC STOPCDS
	PUSH	P,T2		;SAVE ALL
	CAML	T2,TTBASE	;IF TOO LARGE
	CAMLE	T2,RCCMAX##	; OR TOO SMALL
	PUSHJ	P,RCCERR	;
	ANDI	T2,CK.BDY##	;JUST OFFSET WITHIN CHUNK
	CAIE	T2,1		;MUST BE ONE
	PUSHJ	P,RCCERR	;ISN'T, DIE
	SSX	T2,MS.SCN	;SECTION NUMBER
	HLLM	T2,(P)		;STORE SO CAN ADDRESS AND FOR COMPARE
	HLR	T2,@(P)		;ADDRESS OF PREDECESSOR
	HRR	T2,(T2)		; SHOULD POINT TO US
	CAME	T2,(P)		;...
	PUSHJ	P,RCCERR	;DOESN'T, CHUNKS ARE MESSED UP
	POP	P,T2		;INLINE
	HRRZS	T2		;MAKE BACK INTO SECTION RELATIVE
	AOS	(P)		; FOR
	POPJ	P,		;  SPEED

RCCERR:	PUSHJ	P,RCCSTP	;DIE
	POP	P,T2		;ADJUST STACK
	POP	P,T2		;RESTORE ORIGINAL T2
	POPJ	P,		;ERROR RETURN
;ASSORTED SCNSER STOPCD'S OF NOTE

CL0STP:	STOPCD	CLRSTP,DEBUG,CL0,  ;++CHUNK LINKS TO 0

RCCSTP:	STOPCD	CLRSTP,DEBUG,RCC,  ;++RANGE CHECKED CHUNK

RCDSTP:	STOPCD	CLRSTP,DEBUG,RCD,  ;++RANDOM CHUNK DISCREPANCY



;HERE AFTER A STOPCD TO RESET AN LDB TO A NEW VIRGIN STATE SINCE
;WE CAN'T TRUST ANY OF ITS POINTERS/COUNTERS

CLRSTP:	PUSH	P,T1		;PRESERVE ALL AC'S ON G.P.'S
	SETZM	LDBTIT(U)	;ZAPPETH ANY INPUT CHUNK STREAM
	PUSHJ	P,TYIVRG	;AND RESET ALL INPUT COUNTS/POINTERS
	SETZM	LDBTOT(U)	;ZAPPETH ANY OUTPUT CHUNK STREAMS
	PUSHJ	P,TYOVRG	;AND RESET ALL OUTPUT COUNTS/POINTERS
	SETZM	LDBEOT(U)	;ZAPPETH ANY ECHO CHUNK STREAMS
	PUSHJ	P,TYEVRG	;AND RESET ALL ECHO COUNTS/POINTERS
	SETZM	LDBOOT(U)	;ZAPPETH ANY OOB CHUNK STREAMS
	PUSHJ	P,TYBVRG	;AND RESET ALL OOB COUNTS/POINTERS
	JRST	TPOPJ##		;RESTORE T1 AND RETURN
	SUBTTL	CHUNK HANDLERS -- ALLOCATION AND DEALLOCATION

TYIVRG:	SKIPE	T1,LDBTIT(U)	;IF ANY POINTER
	JRST	TYIVR1		;IF POINTER ALREADY EXISTS
	PUSHJ	P,GETCKZ	;GET A FREELIST CHUNK
	ADD	T1,[POINT CK.WID,1,CK.WID-1]	;MAKE BYTE POINTER
	MOVEM	T1,LDBTIT(U)	;SET TAKER
TYIVR1:	MOVEM	T1,LDBTIP(U)	;SET PUTTER BACK TO TAKER
	MOVEM	T1,LDBECT(U)	;AND THE ECHO POINTER
	SETZM	LDBBKU(U)	;BREAK LOCATION
	SETZM	LDBBKI(U)	;BREAK LOCATION
	SETZM	LDBTIC(U)	;NO CHARACTERS BUFFERED
	SETZM	LDBBKC(U)	;WHICH MEANS NO BREAK CHARACTERS BUFFERED
	SETZM	LDBECC(U)	;AND NO CHARACTERS WAITING TO BE ECHOED
	SETZM	LDBIIC(U)	;AND NO INIVISIBLE INPUT CHARACTERS
	SETZM	LDBIEC(U)	;AND NO INIVISIBLE CHARACTERS TO BE ECHOED
	POPJ	P,		;INPUT CHUNK STREAM ALL SET


TYOVRG:	SKIPE	T1,LDBTOT(U)	;IF ALREADY A GOOD POINTER
	JRST	TYOVR1		;DON'T WASTE A GOOD CHUNK
	PUSHJ	P,GETCKZ	;GET A CHUNK FROM FREELIST
	ADD	T1,[POINT CK.WID,1]	;MAKE INTO A BYTE POINTER
	MOVEM	T1,LDBTOT(U)
TYOVR1:	MOVEM	T1,LDBTOP(U)	;PUT IN TYPEOUT STRING ADDRESSES
	SETZM	LDBTOC(U)	;MAKE SURE COUNT IS ZERO
	POPJ	P,		;OUTPUT CHUNK STREAM ALL SET


TYEVRG:	SKIPE	T1,LDBEOT(U)	;IF ALREADY A GOOD POINTER
	JRST	TYEVR1		;DON'T WASTE A GOOD CHUNK
	PUSHJ	P,GETCKZ	;GET A CHUNK FROM FREELIST
	ADD	T1,[POINT CK.WID,1]	;MAKE INTO A BYTE POINTER
	MOVEM	T1,LDBEOT(U)
TYEVR1:	MOVEM	T1,LDBEOP(U)	;PUT IN ECHO OUTPUT STRING ADDRESSES
	SETZM	LDBEOC(U)	;MAKE SURE COUNT IS ZERO
	POPJ	P,		;ECHO CHUNK STREAM ALL SET


TYBVRG:	SKIPE	T1,LDBOOT(U)	;IF ALREADY A GOOD POINTER
	JRST	TYBVR1		;DON'T WASTE A GOOD CHUNK
	PUSHJ	P,GETCKZ	;GET A CHUNK FROM FREELIST
	ADD	T1,[POINT CK.WID,1]	;MAKE INTO A BYTE POINTER
	MOVEM	T1,LDBOOT(U)
TYBVR1:	MOVEM	T1,LDBOOP(U)	;PUT IN OOB OUTPUT STRING ADDRESSES
	SETZM	LDBOOC(U)	;MAKE SURE COUNT IS ZERO
	HRRZ	T3,T1		;ADDRESS PART OF POINTER
	TRZN	T3,CK.BDY	;ADDRESS OF CHUNK HEADER MINUS ONE.
	SUBI	T3,TTCHKS##	;WELL, NOW IT IS
	SSX	T3,MS.SCN	;SET SECTION NUMBER
	HRRZ	T1,1(T3)	;ADDRESS OF FIRST CHUNK IN CHAIN TO DELETE
	JUMPE	T1,TYBVR3	;IF NULL CHAIN
	SETZM	1(T3)		;CLEAR POINTER TO CHAIN BEFORE DELETION
TYBVR2:	SSX	T1,MS.SCN	;SET SECTION POINTER
	HRRZ	T3,(T1)		;POINTER TO CHUNK FOLLOWING CURRENT
	PUSHJ	P,FRECHK	;DELETE ONE CHUNK
	MOVEI	T1,(T3)		;NEXT CHUNK ON CHAIN
	JUMPN	T1,TYBVR2	;LOOP TO END OF CHAIN
TYBVR3:	POPJ	P,		;OOB CHUNK STREAM ALL SET
;FRECHK and GETCHK are called to return and fetch chunks from the
;SCNSER chunk free chain.  The chain is maintained in first-in first-out
;order in order to preserve as much information for crash analysis as
;possible.  The oldest chunk is pointed to by TTFTAK, while the youngest
;is pointed to by TTFPUT.  To aid in reconstruction of the events
;leading to a crash, the left half of each chunk header contains the LDB
;address of the line that last used it.

GETCKZ:	PUSHJ	P,GETCHK	;GET A FREE CHUNK
	SETZM	(T1)		;ZERO THE LINK WORD
	HRRZS	T1		;MAKE SECTION RELATIVE ADDRESS
	POPJ	P,		; AND RETURN

GETCHK:	MOVE	T1,TTFTAK	;GET NEXT FROM FREE LIST
	TRNN	T1,-1		;CHECK IT
	STOPCD	.,STOP,FLE,	;++FREE LIST EMPTY
	PUSH	P,T2		;SAVE T2
	HRRZ	T2,(T1)		;TO NEXT CHUNK
	HRRM	T2,TTFTAK	;STORE POINTER TO NEW FIRST CHUNK
	SOSN	TTFREN##	;COUNT DOWN NUMBER OF FREE CHUNKS
	STOPCD	.,STOP,EXFCHK	;++EXHAUSTED FREE CHUNKS
	JUMPN	T2,T2POPJ##	;IF NOT LAST CHUNK, RETURN
	MOVEI	T2,TTFTAK	;MAKE TTFPUT POINT AT TTFTAK SO
	MOVEM	T2,TTFPUT	; FRECHK WILL RELINK THE POINTERS CORRECTLY
	JRST	T2POPJ##	; AND RETURN

FRECHK:	SSX	T1,MS.SCN	;GET SECTION NUMBER
	HRLZM	U,(T1)		;MARK LINE NUMBER IN CHUNK
	HRRM	T1,@TTFPUT	;STORE CHUNK AT END
	MOVEM	T1,TTFPUT	;POINT TO NEW ENTRY.
	AOS	TTFREN##	;COUNT UP NUMBER OF CHUNKS
	POPJ	P,
	SUBTTL	CHUNK HANDLERS -- CLEAR BUFFERS

;ROUTINES TO CLEAR INPUT AND OUTPUT BUFFERS

TSETBI::SE1ENT			;ENTER SECTION 1
	TRNN	U,-1
	STOPCD	.,STOP,LNS,	;++LINE NOT SETUP
	MOVEI	T1,ISRREM	;CODE FOR REMOTE HANDLERS
	MOVEI	T3,IRRCIB	;ISRREM CODE TO CLEAR INPUT BUFFER
	PUSHJ	P,@LDBISR(U)	;POKE THE FRONT END
TSETI1:	PUSHJ	P,STOPCM
	SCNOFF
TSETI2:	SETZM	LDBTIC(U)	;CLEAR COUNTS
	SETZM	LDBECC(U)	;OF INPUT CHARACTERS
	SETZM	LDBIIC(U)	;ALSO OF
	SETZM	LDBIEC(U)	;INVISIBLE CHARACTERS
	MOVE	T1,LDBTIT(U)	;MOVE PUTTERS BACK TO TAKER
	MOVEM	T1,LDBTIP(U)
	MOVEM	T1,LDBECT(U)	;NO ECHOING EITHER
	SETZM	LDBBKU(U)
	SETZM	LDBBKI(U)
	SETZM	LDBBKC(U)	; ..
	MOVEI	T1,L2RECS	;CLEAR BIT IN LDB WHICH
	ANDCAM	T1,LDBBY2(U)	; MIGHT CAUSE A LINE TO BE SKIPPED
	MOVSI	T1,L3LIHD!L3LIPD!L3LEHD!L3LEPD!L3LCHD!L3LCPD	;CHARACTER EXPANSION BITS
	ANDCAM	T1,LDBBY3(U)	;ABORT 8-BIT CHARACTERS IN PROGRESS
	MOVSI	T1,L1LQTC!L1LQNC!L1LQCC	;QUOTE IN PROGRESS BITS
	ANDCAM	T1,LDBBYT(U)	;NOT QUOTING NOW
	MOVSI	T1,LOLREE	;RE-EAT ECHO
	ANDCAM	T1,LDBOST(U)	;CLEAR SINCE NONE THERE TO RE-EAT
	MOVSI	T1,LDLCRP!LDLDIP	;GET ^R SYNCH BITS
	ANDCAM	T1,LDBDCH(U)	;CLEAR THESE TOO, SINCE ^R WAS TYPEIN
	SETZM	LDBIST(U)	;RESET INPUT STATE MACHINE
	LDB	T1,LDPDEM	;RECINT'S DEFERRED ECHO MODE
	DPB	T1,[POINT 1,LDBBYT(U),^L<(L1LDEM)>] ;KEEP IN SYNCH WITH XMTECH
	SCNON
	PJRST	CHKXON		;CHECK IF AN XON MUST BE SENT OUT AND EXIT

TSETBO::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,LOLSTP+LOLSSO+LOLREO	;CLEAR OUTPUT STOP AND RE-EAT BITS
	ANDCAM	T1,LDBOST(U)	;OUTPUT CAN NOW HAPPEN AGAIN
	SCNOFF			;NO PI'S HERE
IFN FTMIC&FTMLOG,<
	SKIPE	LDBLOT(U)
	JRST	MICLGC
> ;END OF FTMLOG CONDITIONAL
	SETZM	LDBTOC(U)	;NO OUTPUT CHARACTERS LEFT
	MOVE	T1,LDBTOT(U)	;PUT PUTTER BACK AT TAKER
	MOVEM	T1,LDBTOP(U)	; ..
	HRRZ	T3,T1		;ADDRESS PART OF POINTER
	TRZN	T3,CK.BDY	;ADDRESS OF CHUNK HEADER MINUS ONE.
	SUBI	T3,TTCHKS##	;WELL, NOW IT IS
	SSX	T3,MS.SCN	;SET SECTION NUMBER
	HRRZ	T1,1(T3)	;ADDRESS OF FIRST CHUNK IN CHAIN TO DELETE
	JUMPE	T1,TSETB2	;IF NULL CHAIN
	SETZM	1(T3)		;CLEAR POINTER TO CHAIN BEFORE DELETION
TSETB1:	SSX	T1,MS.SCN	;SET SECTION POINTER
	HRRZ	T3,(T1)		;POINTER TO CHUNK FOLLOWING CURRENT
	PUSHJ	P,FRECHK	;DELETE ONE CHUNK
	MOVEI	T1,(T3)		;NEXT CHUNK ON CHAIN
	JUMPN	T1,TSETB1	;LOOP TO END OF CHAIN
TSETB2:	MOVSI	T1,L2LDEL!L2LCCS	;SOME CRUFTY BITS
	ANDCAM	T1,LDBBY2(U)	;CLEAR THEM
	MOVSI	T1,L3LOHD!L3LOPD!L3LFHD!L3LFPD	;CHARACTER EXPANSION BITS
	ANDCAM	T1,LDBBY3(U)	;CLEAR 8-BIT CHARACTERS IN PROGRESS
	SCNON			;ALL'S CLEAR NOW
	MOVEI	T3,IRRSCG	;ISR CODE FOR CHAR GOBBLER
	MOVEI	T1,ISRREM	;SPECIAL ISR ENTRY FOR REMOTES
	PJRST	@LDBISR(U)	;SEND MESSAGE TO CLEAR OUTPUT BUFFER IN REMOTE
	SUBTTL	UUO LEVEL ROUTINES FOR BUFFERED I/O

;DISPATCH TABLE FOR UUO'S AND INITIALIZATION

	JRST	ECOD2##		;NO DEVOP FUNCTIONS
	JRST	REGSIZ##	;BUFFER SIZE CAN BE GOTTEN FROM DDB
	JRST	TTYINI##(P2)	;INITIALIZATION (140 RESTART)
	JRST	CPOPJ1##	;HUNG DEVICE (NEVER USED)
SCNDSP::JRST	TTYREL		;RELEASE
	JRST	OUT##		;CLOSE OUTPUT
	JRST	TTYOUT		;TTY OUTPUT UUO
;	JRST	TTYIN		;TTY INPUT UUO
;FALL INTO TTYIN
;INPUT UUO PROCESSOR - CALLED FROM UUOCON ON INPUT UUO, DDB SET UP


TTYIN:	SE1ENT			;ENTER SECTION 1
	HRRZS	F		;CLEAR LEFT HALF BITS (I/O OPERATIONS DONE SO FAR)
	PUSHJ	P,SAVE3##	;SAVE P1-P3
	PUSHJ	P,CKATTI	;MAKE SURE ATTACHED. SET S.
	TRNN	S,I		;IMAGE MODE?
	JRST	TTYIN0		;NO. SKIP SETUP STUFF
	TRNN	S,IODERR	;EOF DUE TO ^C ON UNATTACHED LINE?
	TLNE	S,FRCEND	;CLOCK ROUTINE WANT IT FINISHED?
	JRST	TTYIN9		;YES. GO DO SO.
	MOVE	T1,DEVMOD(F)	;IS THIS GUY ALLOWED IMAGE MODE INPUT?
	TRNN	T1,ASSCON	;I.E., HE HAS TERMINAL ASSIGNED?
	JRST	TTYINE		;NO. ERROR BIT TO USER.
	MOVSI	T1,LDLIMI	;YES. SET IMAGE INPUT IN LINE DATA
	IORM	T1,LDBDCH(U)	; ..
	PUSHJ	P,SETCHP	;MAKE SURE THAT THE FRONT END KNOWS
TTYIN0:	MOVEI	T1,DEPAIO	;IS THIS TERMINAL IN ASYNC INPUT
	TDNN	T1,DEVAIO(F)	; MODE?
	JRST	TTYINA		;NO--FORGE AHEAD
	PUSHJ	P,TTICHK	;IS THERE ANY INPUT AVAILABLE?
	  POPJ	P,0		;NO--RETURN NOW
TTYINA:	MOVSI	T1,L1LUNR	;UNREAD WAITING BIT
	TDNN	T1,LDBBYT(U)	;DON'T BLOCK DURING UNREAD
	PUSHJ	P,TWAITI	;BECOME ATTACHED, WAIT FOR INPUT
				; OR FULL BUFFER CONDITION
	TLNE	S,FRCEND	;DID WE TIME OUT AT CLOCK
	JRST	TTYIN9		;LEVEL WHILE WAITING ?
TTYIN5:	HRRZ	T1,DEVIAD(F)	;PREPARE AND ADDR CHECK THE
	PUSHJ	P,BUFCLR##	; USER'S BUFFER
	  JRST ADRERR##		;OUT OF BOUNDS. STOP JOB.
	HRRZ	P1,DEVIAD(F)	;USER VIRTUAL ADDRESS OF BUFFER
	EXCTUX	<LDB P2,[POINT 17,(P1),17]>  ;SIZE OF BUFFER (DATA + 1)
	SUBI	P2,1		;LESS THE .BFCNT WORD
	MOVE	U,DDBLDB(F)	;RESTORE LINE, CLOBBERED IN UUOCON
	PUSHJ	P,SRLPTR	;SETUP BYTE COUNT AND POINTER
	PUSH	P,P2		;SAVE BYTE COUNT
				;FALL INTO MAIN PART OF ROUTINE
TTYIN1:	PUSHJ	P,TYICC		;GET A CHARACTER
	  JRST TTYIN3		; END OF BUFFER.
	MOVE	P3,T3		;COPY CHARACTER
	ANDI	P3,CK.CHR	;STRIP IMAGE BIT
	EXCTUU	<IDPB P3,P1>	;AND STORE IN USER AREA
	TRNN	S,I!PIMMOD	;SKIP IF IMAGE MODE OF SOME SORT
	JRST	TTYIN2		;NO, ASCII MODE
	SOJG	P2,TTYIN1	;YES, JUST FILL BUFFER
	JRST	TTYIN3		;BUFFER FULL, GIVE IT TO THE USER

TTYIN2:	TLNE	T1,CHBRK	;A BREAK?
	SOSA	P2		;YES, COUNT IT AND TERMINATE
	SOJG	P2,TTYIN1	;NO. LOOP FOR MORE, IF ROOM.
	MOVSI	S,IOEND		;COUNTED OUT, OR BREAK.
	MOVE	T1,DEVIOS(F)	;GET USER MODE BITS
	TRNN	T1,IOSTEC	;TRUTH-IN-ECHOING MODE AND
	CAIE	P3,"Z"-100	;END OF FILE CHARACTER?
	MOVEI	S,0		;NO. NOT EOF.
	IORB	S,DEVIOS(F)	;STORE IN DDB S WORD
TTYIN3:	POP	P,T1		;GET BACK ORIGINAL MAX BYTE COUNT
	TRNN	S,PIMMOD!A8	;BYTE COUNT IF PIM OR 8-BIT
	SKIPA	P2,DEVIAD(F)	;NOT PIM - BUFFER PTR IN P2
	SKIPA			;PIM - DON'T DESTROY BYTE COUNT
	JRST	TTYINC		;NOT PIM-WORD COUNT
	MOVN	P1,P2		;COUNT OF BYTES LEFT
	ADD	P1,T1		;FROM MAX = COUNT OF BYTES DEPOSITED
	SKIPA	P2,DEVIAD(F)	;ALREADY HAVE COUNT IN P1
TTYINC:	SUBI	P1,1(P2)	;COMPUTE WORD COUNT FOR UUOCON
	EXCTUU	<HRRM P1,1(P2)>	;STORE WITH DATA IN RING
	SKIPN	P1		;DID WE RETURN AN EMPTY BUFFER?
	PUSHJ	P,CLRUNR	;YES - DONE WITH UNREAD
	PUSHJ	P,ADVBFI##	;ON TO NEXT BUFFER
	  JRST	TTYIN8		;NO MORE BUFFERS AVAILABLE
	TRNE	S,I!PIMMOD	;IMAGE MODE?
	SKIPG	LDBTIC(U)	;AND MORE CHARACTERS TO READ?
	JRST	TTYIN8		;NO - ASCII, ONLY PASS ONE LINE AT A TIME
	JRST	TTYIN5		;YES. GO PASS SOME MORE

TTYIN8:	MOVSI	S,IOFST		;SET VIRGIN BUFFER BIT
TTYINX:	IORB	S,DEVIOS(F)	;IN DEV S WORD IN DDB
	MOVE	U,DDBLDB(F)
	JUMPE	U,CPOPJ##
	PJRST	NOCTRO		;CLEAR CONTROL O. END OF UUO

;HERE IF ATTEMPT TO PUT UNASSIGNED TERMINAL IN IMAGE INPUT STATE

TTYINE:	MOVEI	S,IOIMPM
	JRST	TTYINX		; AND RETURN

TTYIN9:	MOVSI	S,IOEND		;SET END OF FILE BIT IN S
	JRST	TTYINX
;OUTPUT UUO CALLS HERE

;CALLED ON OUTPUT OR OUTPUT CLOSE, FROM UUOCON, WITH DDB SET UP.


TTYOUT:	SE1ENT			;ENTER SECTION 1
	HRRZS	F		;CLEAR LEFT HALF (I/O OPERATIONS DONE SO FAR)
	PUSHJ	P,SAVE2##	;SAVE P1-P2
IFN FTRSP,<PUSHJ P,RSPTOR##>	;RECORD RESPONSE SATISFIED BY TERMINAL OUTPUT
	TRNE	S,IODERR	;^C TYPED AT TTYNNN
	JRST	TTOUT3		;YES, RETURN
	PUSHJ	P,CKATOU	;FIRST, MAKE SURE THERE'S A
				; PHYSICAL LINE ATTACHED TO JOB, AT USER LEVEL
	TRNN	S,I		;UNLESS IMAGE MODE,
	PUSHJ	P,CLRIMI	;CLEAR IMAGE INPUT STATE
	MOVSI	S,IOBEG		;IS THIS THE FIRST BUFFER AFTER INIT?
	TDNN	S,DEVIOS(F)	;CHECK DDB
	JRST	TTOUT1		;NO.
	ANDCAM	S,DEVIOS(F)	;YES. CLEAR BEG BIT,
	PUSHJ	P,NOCTRO	; AND CONTROL O
TTOUT0:	SETZM	DEVSTS(F)	;CLEAR OLD PARTIAL BYTE POINTER IF ANY

;OUTPUT A BUFFER OF TEXT. AT THIS POINT WE COULD CHECK FOR ^O IN EFFECT
;AND JUST EAT THE BUFFER, BUT WE DON'T WANT ^O TO BE TOO FAST . . .

TTOUT1:	MOVE	S,[IO!IOFST,,IOACT]	;MARK START OF NEW OUTPUT
	IORB	S,DEVIOS(F)	;IN DEVICE DATA BLOCK
	HRRZ	P1,DEVOAD(F)	;USER VIRTUAL ADDRESS OF OUTPUT BUFFER
	HRRZ	T1,P1		;CHECK ADDRESSES OF OUTPUT BLOCK
	PUSHJ	P,BRNGE##	;MAKE SURE BUFFER IS ADDRESSABLE
	EXCTUX	<HRRZ P2,1(P1)>	;SIZE OF DATA AREA (WORDS) TO BE OUTPUT
	JUMPE	P2,TTOUT6	;SKIP THIS BUFFER IF EMPTY
	EXCTUX	<LDB T1,[POINT 17,(P1),17]>  ;GET TOTAL BUFFER SIZE
	MOVE	T4,P2		;SAVE BYTE/WORD COUNT
	TRNN	S,PIMMOD!A8	;OR NOT IN PACKED IMAGE MODE OR 8-BIT MODE?
	TDZA	T4,T4		;YES, INDICATE USE WORD COUNT
	LSH	T1,2		;ELSE, FOUR BYTES PER WORD
	CAML	P2,T1		;DATA CONTAINED WITHIN BUFFER?
	JRST	TTYINE		;NO, USER BLEW IT
				; (IT ALSO MIGHT IME US!)
	PUSHJ	P,SRLPTR	;GET BYTE COUNT AND POINTER
	SKIPE	T4		;WAS THERE AN EXACT BYTE COUNT?
	MOVE	P2,T4		;YES, USE IT INSTEAD
	SKIPN	DEVSTS(F)	;OUTPUT PENDING?
	JRST	TTOUT2		;NO, NEW BUFFER
	MOVE	P1,DEVSTS(F)	;YES, GET LAST OUTPUT POINTER
	LDB	P2,BYTCNT	;AND REMAINING BYTE COUNT
				; AND FINISH (MAYBE) OUTPUTTING THE BUFFER

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;LOOP OUTPUTTING CHARACTER FROM THE USER BUFFER

TTOUT2:	PUSHJ	P,CKROOM	;SEE IF WE SHOULD CALL TYO
	  JRST	TTOUT7		;IO WAIT WOULD HAPPEN
	MOVE	T3,P1		;COPY BYTE POINTER
	EXCTUX	<ILDB T3,T3>	;INCREMENT THIS COPY, GET USER'S CHAR
	ANDI	T3,CK.CHR	;KEEP JUST THE CHARACTER
	TRNE	S,I!PIMMOD	;SEE IF IMAGE MODE OR PIM
	TRO	T3,CK.IMG	;YES. SET BIT FOR SUPPRESSING FILLERS
	TRNN	S,I!PIMMOD!A8	;IF 7-BIT ASCII,
	JUMPE	T3,TTOUT4	;DON'T OUTPUT NULLS
	MOVEI	T1,DEPAIO	;IF DOING ASYNCHRONOUS I/O,
	TDNE	T1,DEVAIO(F)	; TELL TYO NOT TO BLOCK SINCE
	TLO	T3,(1B0)	; WE MAY BE HERE FORM TTMORE
	TRNE	S,IODERR	;^C TYPED ON TTYNNN
	JRST	TTOUT3		;YES, RETURN
	PUSHJ	P,TYO9W		;OUTPUT THIS CHARACTER (WAIT IF NEEDED)
	JUMPL	T3,TTOUT7
TTOUT4:	IBP	P1
TTOUT5:	SOJG	P2,TTOUT2	;COUNT USER'S ITEMS.
TTOUT6:	PUSHJ	P,ADVBFO##	;ADVANCE HIS BUFFERS
	  JRST	TTOUT3		;JUST SINGLE BUFFER FOR NOW
	MOVEI	T1,DEPAIO	;NON-BLOCKING I/O BIT
	TDNE	T1,DEVAIO(F)	;DOING NON-BLOCKING I/O
	JRST	TTOUT0		;YES, START THE NEXT BUFFER OUT
TTOUT3:	SETZM	DEVSTS(F)
	MOVEI	S,IOACT		;CLEAR ACTIVE BIT.
	ANDCAB	S,DEVIOS(F)	;IN DEVICE DATA BLOCK FOR THE JOB
	POPJ	P,0		;END OF UUO. RETURN TO USER

TTOUT7:	MOVEM	P1,DEVSTS(F)	;SAVE THE INTERRUPTED BYTE POINTER
	DPB	P2,BYTCNT	; AND ITS COUNTER
TTOUT8:	MOVEI	T1,JS.NTO	;SET THE MAGIC
	IORM	T1,JBTSTS##(J)	; BIT IN JBTSTS
	MOVEI	S,IOACT		;CLEAR I/O ACTIVE BIT
	ANDCAB	S,DEVIOS(F)	;..
	POPJ	P,0		;RETURN
TTMORE::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE2##	;SAVE P1-P2
	MOVEI	F,SCNDDB	;FIRST DDB
	MOVEI	P2,JS.NTO	;FLAG RESET
MORE10:	LDB	T1,PJOBN##	;GET OWNER
	CAIN	T1,(J)		;IS IT THIS JOB?
	SKIPN	DEVSTS(F)	;IS OUTPUT WAITING?
	JRST	MORE20		;NO, TRY NEXT DDB
	MOVEI	T1,DEPAIO
	TDNN	T1,DEVAIO(F)	;NON-BLOCKING I/O ON THIS TERMINAL?
	JRST	MORE20		;NO, LOOK AT OTHER TERMINALS
	PUSHJ	P,MORE30	;GO TRY OUTPUT
	MOVEI	P2,0		;FLAG ONE ACTIVE
MORE20:	HLRZ	F,DEVSER(F)	;PICK UP NEXT DDB
	MOVSI	T1,DVTTY	;IS THIS A TTY?
	TDNE	T1,DEVMOD(F)	; ..
	JUMPN	F,MORE10	;YES--LOOK AT IT TOO
	ANDCAM	P2,JBTSTS##(J)	;CLEAR THE STATUS
	POPJ	P,0		;RETURN
MORE30:	MOVE	U,DDBLDB(F)	;GET ADDRESS OF LDB
	JUMPE	U,CPOPJ##	;PUNT IF DETACHED
	MOVE	S,DEVIOS(F)	;SET UP S FOR TYO
	PUSHJ	P,SSPCS##	;SAVE PCS
	PUSHJ	P,SPCS##	;SETUP PCS BASED ON DEVISN IN THIS DDB
	LDB	P1,BYTCNT	;GET THE BYTE COUNT
	JUMPE	P1,MORE41	;IF BYTE COUNT=0 AND DEVSTS NON-0, BUFFER WASN'T ADVANCED
				; BECAUSE WHAT DEVOAD POINTED TO WAS PAGED OUT

MORE40:	PUSHJ	P,CKROOM	;ROOM FOR MORE DATA?
	  JRST	[DPB P1,BYTCNT	;NO--SAVE BYTE COUNT
		 POPJ P,0]	;RETURN
	MOVE	T1,DEVSTS(F)	;GET POINTER
	IBP	T1		;UPDATE POINTER
	MOVE	T3,T1
	TLZ	T1,-1		;CLEAR JUNK
	PUSHJ	P,IADRCK##	;MAKE SURE ITS LEGAL AND IN CORE
	  JRST	MORE50
	  JRST	MORE50
	EXCTUX	<LDB T3,T3>	;GET NEXT BYTE
	ANDI	T3,CK.CHR	;DON'T ALLOW USER TO GIVE US META-CHARACTERS
	TRNE	S,I!PIMMOD	;IF IMAGE OR PIM
	TRO	T3,CK.IMG	;FLAG IT
	TRNN	S,I!PIMMOD!A8	;IF 7-BIT ASCII
	JUMPE	T3,MOR405	;DON'T TYPE NULLS
	TLO	T3,(1B0)	;DON'T BLOCK IN TYO
	PUSHJ	P,TYO9W		;TYPE IT
	JUMPGE	T3,MOR405	;PROCEED IF CHAR OUTPUT
	DPB	P1,BYTCNT	;ELSE REMEMBER WHERE
	JRST	TTOUT8		;WE WERE & RETURN
MOR405: IBP	DEVSTS(F)	;INCREMENT PRIME COPY
	SOJG	P1,MORE40	;DO THE NEXT BYTE
MORE41:	HRRZ	T1,DEVOAD(F)	;BUF APR
	SOS	T2,T1		;WORD-1
	ADDI	T2,3		;THRU WORD1
	PUSHJ	P,ZRNGE##	;IN CORE?
	  JRST	MORE50		;NO

IFN FTPI,<
	TLO	S,IO		;FORCE FLAG TO OUTPUT
	PUSHJ	P,PSIIOD##
>
	JRST	TTOUT6		;ALL DONE

MORE50:	MOVEI	M,(T1)		;FOR ROUTINE (PCS DOES SECTION WORK)
	PUSHJ	P,PFHGWD##	;TRY TO FAULT IT INTO CORE
	  JRST	UADERR##	;BOMB USER IF CAN'T
	JUMPN	P1,MORE40	;CONTINUE IF JUST WANTED A BYTE
	HRRI	M,3(M)		;NO, BUMP PAST HEADER
	PUSHJ	P,PFHGWD##	;MAKE SURE THIS IS ALSO IN CORE
	  JRST	UADERR##	;BOMB USER IF NOT A VALID ADDRESS
	JRST	MORE41		;GO ADVANCE BUFFER NOW

CKROOM:	MOVEI	T1,DEPAIO	;IF THIS JOB IS NOT USING
	TDNN	T1,DEVAIO(F)	; ASYNCHRONOUS I/O THEN
	JRST	CPOPJ1##	; JUST GIVE THE SKIP RETURN
	SKIPLE	T1,TTFREN##	;GET THE FREE CHUNK COUNT
	CAIG	T1,5		;ENOUGH ROOM?
	POPJ	P,0		;NO--QUIT NOW
	MOVE	T1,LDBTOC(U)	;GET OUTPUT BYTE COUNT
	ADDI	T1,^D25		;REDUCE ODDS OF LOSSAGE
	CAMG	T1,TIWRNN	;TOO MUCH STUFF?
	AOS	(P)		;NO--CALL TYO
	POPJ	P,0		;RETURN
	SUBTTL	DDT MODE CALLI'S

;INPUT TO DDT	- CALL AC,[SIXBIT /DDTIN/]  WHERE AC/ ADDR
;ADDR GETS UP TO 21 WORDS OF ASCIZ, BREAKING ON ANY CHARACTER

DDTIN::	PUSHJ	P,SAVE3##	;SAVE P1-P3 (TYICC KRUMPS P3)
	PUSHJ	P,TTYFNU	;SET LINE AND DDB FOR THIS TTY
	PUSHJ	P,CKATTI	;MAKE SURE TERMINAL ATTACHED
	PUSHJ	P,GETWDU##	;DO ADDRESS CHECKING FIRST
	HRRZS	P1,T1		;GET AND SAVE STARTING ADDRESS OF AREA
	HRLI	T1,(IFIW)	;OLD-STYLE UUO USES SECTION RELATIVE ADDRESSING
	MOVEI	T2,21		;WORD COUNT
	PUSHJ	P,ARNGE##	;RANGE CHECK
	  JRST	UADERR##	;ADDRESS CHECK
	  JRST	UADERR##	;ADDRESS OK BUT ILLEGAL FOR I/O
	HRLI	P1,440700	;SEVEN BIT BYTES, RELOCATED.
	MOVEI	P2,<21*5>-1	;NUMBER OF BYTES ALLOWED
	PUSHJ	P,TWAITC	;GET AT LEAST ONE CHARACTER
DDTINL:	SKIPG	LDBTIC(U)	;ANY MORE TO COME?
	JRST	DDTINX		;NO.
	PUSHJ	P,TYICC		;YES. GO GET ONE
	  JRST	DDTINX		;WASNT ANY. I'M CONFUSED.
	TRNE	T3,CK.CH7	;NULL?
	EXCTUU	<IDPB T3,P1>	;NO. STORE IN USER AREA
	SOJG	P2,DDTINL	;IF MORE SPACE, GET ANOTHER CHARACTER
DDTINX:	MOVEI	T3,0		;FLAG END OF STRING
	EXCTUU	<IDPB T3,P1>	; IN USER AREA
	PJRST	NOCTRO		;AND RETURN TO USER, CLEARING ^O FLAG

;DDTOUT - CALL AC,[SIXBIT /DDTOUT/], AC/ ADDR, ADDR/ ASCIZ /XXX/

DDTOUT::HRR	M,T1		;USER ADR. OF TEXT TO M
	PUSHJ	P,TTYFNU	;GET USER'S CONSOLE
	PUSHJ	P,CKATOU	;MAKE SURE AT USER LEVEL AND ATTACHED
	JRST	OUTSTR		;SAME AS THE CORRESPONDING TTCALL
	SUBTTL	TTCALL AND TRMOP. -- TTCALL DISPATCH

;TTCALL AC,E - VALUE OF AC DETERMINES ACTION OF UUO (051)

TTYUUO::PUSHJ	P,SAVE2##	;SAVE P1,P2
	PUSHJ	P,TTYFNU	;FIND CURRENT USER'S TTY
	MOVE	P2,TTUUOT(P1)	;GET PRE-CHECK BITS
	TLNE	P2,TC.ATW	;ATTACH OR WAIT?
	PUSHJ	P,CKATTO	;YES.  WAIT TILL ATTACHED
	TLNN	P2,TC.ATR	;ATTACH OR RETURN?
	JRST	TTUUB		;NO
	TRNN	U,-1		;YES.  LINE NON-ZERO?
	POPJ	P,0		;NO.  RETURN, NO TERMINAL

TTUUB:	JUMPE	U,TTUUD		;ONE UUO-GETLCH-CAN BE HERE DETACHED
	MOVE	T1,LDBDCH(U)	;GET LINE DESCRIPTION
	TLNN	P2,TC.USR	;USER OR RETURN?
	JRST	TTUUC		;NO
	TLNE	T1,LDLCOM	;YES.  USER LEVEL?
	POPJ	P,0		;NO.  RETURN.

TTUUC:	TLNE	P2,TC.USW	;USER OR WAIT?
	TLNN	T1,LDLCOM	;YES.  AT USER LEVEL
	JRST	TTUUD		;USER LEVEL, OR NOT NEEDED
	PUSHJ	P,CKATOU	;TOP LEVEL.WAIT FOR USER.
	JRST	TTYUUO		;RESTART UUO IN CASE OF
				;ATTACH.
TTUUD:	TLNN	P2,TC.ADC	;ADDRESS CHECK NEEDED?
	JRST	TTUUE		;NO.  GO DISPATCH.
	HRRZ	T1,M		;ADDRESS TO P1, WHICH IS P1
	PUSHJ	P,UADCK1##	;CHECK THE ADDRESS
TTUUE:	TLNE	P2,TC.ECS	;INPUT OPERATION?
	PUSHJ	P,TYIEAT	;YES, EAT COMMAND IF LEFT OVER
	SSX	P2,MCSEC1	;ISOLATE DISPATCH ADDRESS
	JRST	(P2)		;DISPATCH TO ROUTINE
;THE FOLLOWING TABLE IS USED TO PRE-CHECK AND DISPATCH THE TTCALL'S.
;BITS IN THE LEFT ARE CHECKED BEFORE DISPATCHING.
;INDIRECT AND INDEX MUST BE ZERO, FOR JRST INDIRECT, BUT THIS COULD
;EASILY BE CHANGED IF THE BITS RUN OUT.


TC.ADC==400000		;THIS FUNCTION MUST BE ADDRESS CHECKED
TC.USR==200000		;THIS FUNCTION MUST BE AT USER LEVEL, ELSE POPJ
TC.USW==100000		;THIS FUNCTION MUST BE AT USER LEVEL, ELSE WAIT
TC.ATW==040000		;THIS FUNCTION MUST BE ATTACHED, ELSE WAIT
TC.ATR==020000		;THIS FUNCTION MUST BE ATTACHED, ELSE POPJ
TC.ECS==010000		;EAT COMMAND SYNC (CALL TYIEAT)
;DON'T ASSIGN BITS 13-17 WITHOUT CHANGING DISPATCH CODE

TTUUOT:	XWD	TC.ATW+TC.USW+TC.ADC+TC.ECS,INCHRW	;(00) INPUT CHARACTER, WAIT
	XWD	TC.ATW+TC.USW,ONEOUT		;(01) OUTPUT CHARACTER
	XWD	TC.ATR+TC.USR+TC.ADC+TC.ECS,INCHRS	;(02) INPUT CHARACTER, SKIP
	XWD	TC.ATW+TC.USW,OUTSTR		;(03) OUTPUT AN ASCIZ STRING
	XWD	TC.ATW+TC.USW+TC.ADC+TC.ECS,INCHWL	;(04) INPUT CHARACTER, WAIT LINE MODE
	XWD	TC.ATR+TC.USR+TC.ADC+TC.ECS,INCHSL	;(05) INPUT CHARACTER, SKIP LINE MODE
	XWD	TC.ADC,GETLIN			;(06) GET LINE CHARACTERISTICS
	XWD	TC.ATW+TC.ADC,SETLIN		;(07) SET LINE CHARACTERISTICS
	XWD	TC.ATR,TRESCU			;(10) RESCAN COMMAND LINE
	XWD	TC.ATR,TSETBI			;(11) CLEAR INPUT BUFFER
	XWD	TC.ATR,TSETBO			;(12) CLEAR OUTPUT BUFFER
	XWD	TC.ATR+TC.USR+TC.ECS,SKPINC	;(13) SKIP IF A CHAR TO BE INPUT
	XWD	TC.ATR+TC.USR+TC.ECS,SKPINL	;(14) SKIP IF A LINE TO BE INPUT
	XWD	TC.ATW+TC.USW,IONEOU		;(15) IMAGE ONE-CHARACTER OUTPUT
	XWD	0,CPOPJ##			;(16) NOT IMPLEMENTED
	XWD	0,CPOPJ##			;(17) NOT IMPLEMENTED
	SUBTTL	TTCALL AND TRMOP. -- OUTCHR AND IMAGE OUTCHR

;ONEOUT OUTPUTS ONE CHARACTER FROM C(E)

ONEOUT:	PUSHJ	P,SAVE2##	;SAVE P2
	SKIPN	F		;ANY DDB?
	SKIPA	P2,[CCTYO]	;NO--MUST BE SLOPPY
	MOVEI	P2,TYO7W	;YES--BE NEAT
IFN FTRSP,<PUSHJ P,RSPTOR##>	;RECORD RESPONSE SATISFIED BY TERMINAL OUTPUT
ONEOU1:	PUSHJ	P,GETWDU##	;PICK UP USER'S WORD
	MOVE	T3,T1		;PUT IN RIGHT AC
	ANDI	T3,CK.CHR	;MASK OUT ANY JUNK
	MOVSI	T1,LDL8BI	;8-BIT I/O
	TDNN	T1,LDBDCH(U)	;USER SET .IOAS8?
	ANDI	T3,CK.CH7	;NO, KEEP ONLY 7-BIT
	JUMPE	T3,CPOPJ##	;IF NOT NULL,
	PJRST	(P2)		;TYPE OUT, WAIT IF NEEDED

;IONEOU OUTPUTS ONE CHARACTER FROM LOW 8 BITS OF C(E)
IONEOU:
IFN FTRSP,<PUSHJ P,RSPTOR##>	;RECORD RESPONSE SATISFIED BY TERMINAL OUTPUT
	PUSHJ	P,CLRIIQ	;NOT IN INPUT WAIT ANY MORE
	JUMPE	F,ONEOU1	;IF NO DDB, SEND 7 BITS
	PUSHJ	P,GETWDU##	;GET USER'S DATUM
	HRRZ	T3,T1		;INTO RIGHT AC
	ANDI	T3,CK.CHR	;IGNORE POSSIBLE GARBAGE
	TRO	T3,CK.IMG	;FLAG AS IMAGE CHARACTER (NO FILLER)
	PJRST	TYO9W		;SEND IMAGE CHARACTER (WAIT IF NEEDED)
	SUBTTL	TTCALL AND TRMOP. -- OUTSTR AND RESCAN

;OUTSTR OUTPUTS A STRING OF ASCIZ CHARACTERS

OUTSTR:
IFN FTRSP,<PUSHJ P,RSPTOR##>	;RECORD RESPONSE SATISFIED BY TERMINAL OUTPUT
	PUSHJ	P,SAVE4##	;SAVE P1-P4
	MOVEI	P3,TYO7W
OUTST3:	LDB	T1,[POINT 9,M,26] ;PAGE #
	PUSHJ	P,TPSHS##	;IS PAGE SHARED?
	  JRST	OUTST6		;YES -- JUST USE
	HRROI	T1,(M)		;LEFT JUSTIFIED ASCIZ STRING
	PUSHJ	P,CKSTR##	;MAKE SURE ITS IN CORE AND LEGAL
	  JRST	UADERR##	;ADDRESS CHECK
OUTST6:	HRRI	M,-1(M)		;COMPENSATE FOR GETWD1
OUTST5:	MOVEI	P4,200		;MAXIMUM # OF WORDS IN ONE SHOT
OUTST2:	MOVE	P1,[POINT 7,P2]	;PREPARE TO READ BYTES
	PUSHJ	P,GETWD1##	;GET A USER'S WORD
	MOVE	P2,T1		;PUT WORD IN A SAFE AC
OUTST1:	TLNN	P1,760000	;ANY BYTES LEFT?
	JRST	OUTST4		;NO. GET ANOTHER WORD
	ILDB	T3,P1		;YES. GET ONE
	JUMPE	T3,CPOPJ##	;NULL MARKS END OF STRING
	HLL	T3,P3		;PROPAGATE SIGN-BIT STATE
	PUSHJ	P,(P3)		;TYPE OUT CHARACTER
	JRST	OUTST1		;AND GO BACK FOR MORE.

OUTST4:	SOJG	P4,OUTST2	;GO BACK FOR MORE. IS MESSAGE LONG?
	PUSHJ	P,SCDCHK##	;GIVE THE REST OF THE WORLD A CHANCE
	JRST	OUTST5

;TRESCU IS RESCAN FUNCTION FOR PROGRAM TO READ COMMAND THAT STARTED IT

TRESCU:	MOVE	T2,LDBBY2(U)	;SAVE OLD BIT FOR TEST
	MOVEI	T1,L2RECS	;CLEAR BIT IN LINE DATA BLOCK WHICH
	ANDCAM	T1,LDBBY2(U)	; WOULD CAUSE COMMAND TO BE SKIPPED
	TDNN	T2,T1		;SEE IF ANYTHING THERE
	TRNN	M,1		;NO--SEE IF USER WANTS TO KNOW
	POPJ	P,0		;NO--JUST RETURN
	JRST	CPOPJ1##	;YES--GIVE SKIP RETURN
SUBTTL	TTCALL AND TRMOP. -- TRMOP. UUO FUNCTION .TOISO (IMAGE STRING OUTPUT)


; OUTPUT A FIXED LENGTH STRING OF CHARACTERS IN IMAGE MODE
; CALL:	MOVE	AC,[4,,ARG]
;	TRMOP.	AC,
;	  <ERROR RETURN>
;	<NORMAL RETURN>
;
; ARG:	EXP	.TOISO/.TOASO
;	EXP	UDX
;	XWD	BYTE-SIZE,BYTE-COUNT
;	EXP	STRING-ADDRESS
;
TOPASO:	TDZA	T4,T4		;KEEP TRACK OF ENTRY POINT
TOPISO:	MOVEI	T4,CK.IMG	;DITTO
	PUSHJ	P,SAVE4##	;SAVE ACS P1-P4
	PUSHJ	P,GETWRD##	;GET BYTE SIZE,,BYTE COUNT
	  JRST	TOPX3		;ADDRESS CHECK
	HRRZ	P1,T1		;GET THE BYTE COUNT
	JUMPE	P1,CPOPJ1##	;RETURN IF NO CHARACTERS TO OUTPUT
	HLRZ	T2,T1		;GET BYTE SIZE
	CAIL	T2,^D1		;CHECK BYTE SIZE
	CAILE	T2,^D36		;1 TO 36 BIT BYTES ARE OK
	JRST	TOPX10		;ALL OTHERS ARE NO GOOD
	MOVSI	P3,(POINT 0,(P));START TO BUILD BYTE POINTER
	DPB	T2,[POINT 6,P3,11] ;STORE THE BYTE SIZE
	MOVEI	T1,^D36		;BITS PER WORD
	IDIVI	T1,(T2)		;GET BYTES PER WORD
	PUSH	P,T4		;SAVE BIT FOR CHARACTER TYPER
	PUSH	P,T1		;SAVE BYTES PER WORD FOR LATER
	PUSH	P,[200]		;COUNT OF WORDS TO PROCESS BEFORE RESCHEDULE
	PUSH	P,[0]		;RESERVE SPACE FOR A WORD OF BYTES
	PUSHJ	P,GETWR1##	;GET ADDRESS OF STRING TO OUTPUT
	  JRST	TOPX3		;ADDRESS CHECK
	MOVEI	M,-1(T1)	;SET UP SUBSEQUENT CALLS TO GETWR1

IFN FTRSP,<
	HRRZ	T1,TTYTAB##(J)	;GET CONTROLLING TTY DDB
	CAIN	T1,(F)		;IS THIS IT?
	PUSHJ	P,RSPTOR##	;YES--RECORD RESPONSE SATISFIED BY TTY OUTPUT
>
;	JRST	IMGSTR		;GO OUTPUT THE STRING
; HERE TO OUTPUT THE STRING IN IMAGE MODE
; PDL:	-3(P) - CK.IMG OR ZERO FOR MARKING CHARACTER IN CHUNKS
;	-2(P) - BYTES PER WORD
;	-1(P) - COUNT OF WORDS PROCESSED BEFORE RESCHEDULE JOB
;	  (P) - WORD STORAGE
; AC:	P1 - BYTE COUNT
;	P2 - WORKING BYTE POINTER
;	P3 - ORIGINAL BYTE POINTER
;	P4 - CHARACTER COUNT PER WORD
;
IMGSTR:	MOVE	T1,P3		;GET BYTE POINTER
	TLZ	T1,(@(17))	;CLEAR OUR INDEXING AND INDIRECTION
	HRRI	T1,(M)		;GET USER ADDRESS OF START OF STRING
	MOVE	T2,P1		;GET NUMBER OF BYTES IN STRING
	PUSHJ	P,PRNGE##	;RANGE CHECK
	  JRST	TOPX3		;ADDRESS CHECK
	  JFCL			;ADDRESS OK BUT IGNORE ILLEGAL FOR I/O

IMGS1:	SOSLE	-1(P)		;COUNT WORDS PROCESSED
	JRST	IMGS2		;GET MORE TEXT
	MOVEI	T1,200		;GET WORD COUNT
	MOVEM	T1,-1(P)	;RESET IT
	PUSHJ	P,SCDCHK##	;GIVE SOMEONE ELSE A CHANCE TO RUN

IMGS2:	MOVE	P2,P3		;RESET BYTE POINTER
	MOVE	P4,-2(P)	;RESET BYTES PER WORD
	PUSHJ	P,GETWR1##	;GET A WORD OF TEXT
	  JRST	TOPX3		;ADDRESS CHECK
	MOVEM	T1,(P)		;SAVE IT

IMGS3:	SOJL	P1,IMGS4	;COUNT BYTES
	ILDB	T3,P2		;GET A CHARACTER
	ANDI	T3,CK.CHR	;FEND OFF SMART-ALECKS WITH CK.MET LIT
	TDO	T3,-3(P)	;FLAG AS IMAGE IF .TOISO FUNCTION
	PUSHJ	P,TYO9W		;OUTPUT IT
	SOJG	P4,IMGS3	;COUNT BYTES IN THIS WORD
	JRST	IMGS1		;GET ANOTHER WORD OF TEXT

IMGS4:	ADJSP	P,-4		;PHASE STACK
	JRST	CPOPJ1##	;AND RETURN
SUBTTL	TTCALL AND TRMOP. -- TRMOP. UUO FUNCTION .TOFLM (FORCE LEFT MARGIN)


; FORCE TERMINAL TO LEFT MARGIN IF NOT ALREADY THERE
; CALL:	MOVE	AC,[2,,ARG]
;	TRMOP.	AC,
;	  <ERROR RETURN>
;	<NORMAL RETURN>
;
; ARG:	EXP	.TOFLM
;	EXP	UDX
;
TOPFLM:	MOVE	T3,[1B0!MC.FLM]	;CHARACTER TO FORCE LEFT MARGIN
	PUSHJ	P,CCTYO8	;TRY TO TYPE IT
	JUMPGE	T3,CPOPJ1##	;WIN IF TYPED
	PUSHJ	P,OUTSTS	;SLEEP FOR A TICK
	JRST	TOPFLM		;AND TRY AGAIN
	SUBTTL	TTCALL AND TRMOP. -- SKPINL AND SKPINC

;SKIP IF A LINE MAY BE INPUT

SKPINL:	PUSHJ	P,TYIEAT	;MAKE SURE NOT FAKED BY COMMAND
	PUSHJ	P,NOCTRO	;CLEAR THE ^O BIT
	PJRST	TTLCHK		;CHECK FOR LINE READY
				; AND RETURN SKIP/NON-SKIP

;SKIP IF A CHARACTER MAY BE INPUT

SKPINC:	PUSHJ	P,TYIEAT	;MAKE SURE NOT FAKED BY COMMAND
	PUSHJ	P,NOCTRO	;CLEAR THE ^O BIT
	PUSHJ	P,SETBKA	;SET BREAK-ON-ALL
	PUSHJ	P,TICAVL	;ANY AVAILABLE CHARACTERS ECHOED?
	  CAIA			;YEP
	PUSHJ	P,ECCAVL	;OR IN TO-BE-ECHOED STREAM?
	AOS	(P)		;YUP
	POPJ	P,		;RETURN

NOCTRO::MOVEI	T1,LDROSU	;CLEAR OUTPUT SUPPRESS BIT
	ANDCAM	T1,LDBDCH(U)	; IN LINE DATA BLOCK
	POPJ	P,0		;AND RETURN

STCTRO::MOVEI	T1,LDROSU	;THE OUTPUT SUPPRESS BIT
	IORM	T1,LDBDCH(U)	;SET OUTPUT SUPPRESSION
	PJRST	TSETBO		;CLEAR OUTPUT BUFFER
	SUBTTL	TTCALL AND TRMOP. -- GETLIN


;DEFINE THE BITS FOR THE USER ARGUMENT TO GETLIN AND SETLIN

	GL.ITY==400000		;PTY
	GL.CTY==200000		;CTY
	GL.DSP==100000		;TTY DISPLAY
	GL.DSL==040000		;DATA SET LINE
	GL.CNE==020000		;COMMAND-LEVEL NO ECHO
	GL.HDP==010000		;HALF DUPLEX
	GL.REM==004000		;REMOTE TTY, NO [1,2] LOGIN
	GL.RBS==002000		;NETWORK LINE
	GL.8BM==000200		;8-BIT I/O MODE BY PROGRAM
	GL.LIN==000100		;LINE OF INPUT READY
	GL.SLV==000040		;TTY SLAVE
	GL.LCM==000020		;TTY LOWER CASE
	GL.TAB==000010		;TTY TAB
	GL.LCP==000004		;TTY LOCAL COPY
	GL.PTM==000002		;TTY PAPER TAPE
	GL.NEC==000001		;NO ECHO BY PROGRAM

;GETLIN RETURNS A WORD OF INFORMATION ABOUT A LINE

GETLIN:	PUSHJ	P,GETWDU##	;GET "ADDR"
	JUMPL	T1,GETLN1	;DOES HE WANT HIS OWN LINE
	TRZ	T1,.UXTRM	;CLEAR THE TTY IO INDEX BIT
	CAIL	T1,TTPLEN##	;LEGAL TTY?
	JRST	GETLNZ		;NO, RETURN A ZERO
	MOVE	U,LINTAB##(T1)	;GET THE LDB ADDRESS

GETLN1:	JUMPE	U,GETLNZ	;NO LDB, NO BITS!
	LDB	T1,LDPLNO	;COPY THE LINE # FROM THE LDB
	TRO	T1,.UXTRM	;SET THE TERMINAL INDEX BIT

;SET BITS FROM THE (RH) OF LDBDCH(U)

	MOVE	T2,LDBDCH(U)	;GET THE CHARACTERISTICS WORD
	TRNE	T2,LDRPTY	;PTY LINE?
	TLO	T1,GL.ITY	;YES
	TRNE	T2,LDRCTY	;CTY LINE?
	TLO	T1,GL.CTY	;YES
	TRNE	T2,LDRDSD	;DATA SET LINE?
	TLO	T1,GL.DSL	;YES
	TRNE	T2,LDRHLF	;HALF DUPLEX?
	TLO	T1,GL.HDP	;YES
	TRNE	T2,LDRRMT	;"REMOTE" LINE?
	TLO	T1,GL.REM	;YES

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;SET BITS FROM THE (LH) OF LDBCH(U)

	TLNE	T2,LDLSLV	;SLAVE?
	TLO	T1,GL.SLV	;YES
	TLNN	T2,LDLLCT	;LOWER CASE TRANSLATION?
	TLO	T1,GL.LCM	;YES
	TLNE	T2,LDLTAB	;TTY TAB?
	TLO	T1,GL.TAB	;YES
	TLNE	T2,LDLLCP	;LOCAL COPY?
	TLO	T1,GL.LCP	;YES
	TLNE	T2,LDLCNE	;COMMAND NO ECHO?
	TLO	T1,GL.CNE	;YES
	TLNE	T2,LDL8BI	;8-BIT I/O MODE?
	TLO	T1,GL.8BM	;YES
	HRRZ	F,LDBDDB(U)	;ADDRESS OF TTY DDB
	JUMPE	F,GETLN3	;SKIP IF NONE
	MOVE	T2,DEVIOS(F)	;TTY'S NO STATUS
	TRNE	T2,IOSNEC	;NO ECHO SET BY PROGRAM?
	TLO	T1,GL.NEC	;YES

;SET BITS FROM LDBTTW

	MOVE	T2,LDBTTW(U)	;LINE TYPE WORD
	TLNE	T2,LTLANF!LTLNRT!LTLLAT	;REMOTE STATION LINE?
	TLO	T1,GL.RBS	;YES

;SET BITS FROM THE (LH) OF LDBATR(U)

GETLN3:	MOVE	T2,LDBATR(U)	;GET THE TTY MODE WORD
	TLNE	T2,LALDIS	;DISPLAY MODE?
	TLO	T1,GL.DSP	;YES

;SET BITS FROM THE (RH) OF LDBBY2

	MOVE	T2,LDBBY2(U)	;GET THE SECOND BYTE WORD
	TRNE	T2,L2RXON	;PAPTER TAPE MODE?
	TLO	T1,GL.PTM	;YES

;FIND OUT IF WE HAVE A LINE OF INPUT READY

	MOVE	T3,T1		;CLOBBERS T1
	PUSHJ	P,TTLCK2	;CHECK FOR A READY LINE
	  TDZA	T1,T1		;NO LINE READY YET
	MOVSI	T1,GL.LIN	;READY BIT
	IOR	T1,T3		;A LINE IS READY
	PJRST	PUTWDU##	;GIVE RESULT TO THE USER

;HERE WHEN WE HAVE FOUND AN ERROR TO RETURN ZERO

GETLNZ:	MOVEI	T1,0		;GET A ZERO AND
	PJRST	PUTWDU		;RETURN IT TO INDICATE AN ERROR
	SUBTTL	TTCALL AND TRMOP. -- SETLIN, INCHSL, INCHWL, INCHRS & INCHRW

;ROUTINE TO SET LINE CHARACTERISTICS FOR THE CURRENT LINE (U)

SETLIN:	PUSHJ	P,GETWDU##	;GET THE BITS
	HLRZS	T1		;GET THEM IN THE RH
	TRNN	T1,GL.PTM	;SET PAPER TAPE MODE?
	TDZA	T2,T2		;NO
	MOVEI	T2,1		;YES
	DPB	T2,L2PXON	;SET THE BIT
	TRNN	T1,GL.DSP	;DISPLAY MODE?
	TDZA	T2,T2		;NO
	MOVEI	T2,1		;YES
	DPB	T2,LDPDIS	;SET THE BIT
	HRRZ	F,LDBDDB(U)	;GET DDB
	JUMPE	F,SETLN3	;SKIP IF NONE
	TRNN	T1,GL.NEC	;NO ECHO?
	TDZA	T2,T2		;NO,
	MOVEI	T2,1		;YES
	DPB	T2,SETLP0	;SET THE BIT
	MOVE	T3,LDBDCH(U)	;OTHER FACTORS
	TLNN	T3,LDLCNE!LDLCOM ;UNLESS OVERRIDDEN,
	DPB	T2,LDPECH	;STORE IN LDB ALSO
SETLN3:	TRC	T1,GTLT37	;STORED AS COMPLEMENT
	ROT	T1,-2		;BIT DEPENDENT FOR DPB BELOW
	DPB	T1,SETLP1	;THESE THREE BITS CAN BE SET
	PJRST	SETCHP		;LET THE NETWORK KNOW IF WE
				;CHANGE ANYTHING

;BYTE POINTERS NEEDED BY SETLCH

L2PXON:	POINT	1,LDBBY2(U),18	;PAPER TAPE BIT
SETLP0: POINT	1,DEVIOS(F),^L<IOSNEC>  ;NO ECHO REQUEST BIT
SETLP1:	POINT	3,LDBDCH(U),15	;PART OF LEGAL BITS
INCHRS:	PUSHJ	P,SKPINC	;CAN I GET A CHARACTER (CLEAR ^O)
	  POPJ	P,0		;NO. GIVE NON-SKIP RETURN
	PUSHJ	P,TWAITC	;WAIT IN CASE NOT ECHOED YET
ICS3:	PUSHJ	P,TYIS		;GET A CHARACTER
	  JRST	ICS2		;NONE THERE.
	AOS	0(P)		;GIVE SKIP RETURN
	JRST	ICW1		;AND RETURN THE CHARACTER

ICS2:	PUSHJ	P,CLRUNR	;CLEAR UNREAD BIT
	PJRST	NOCTRO		;ENABLE OUTPUT AND RETURN

INCHSL:	PUSHJ	P,SKPINL	;IS THERE A LINE AVAILABLE?
	  POPJ P,0		;NO. NON-SKIP RETURN TO USER
	PUSHJ	P,TWAITL
	JRST	ICS3		;YES. GO GET A CHARACTER FOR HIM

INCHWL:	PUSHJ	P,TWAITL	;WAIT FOR A LINE TO APPEAR
ICW2:	PUSHJ	P,TYI		;GO GET A CHARACTER
	  TDZA	T3,T3		;IMPOSSIBLE. NO CHARACTERS. USER SET IODERR?
	JRST	ICW1		;GO STORE
	PUSHJ	P,CLRUNR	;CLEAR UNREAD BIT
ICW1:	ANDI	T3,CK.CHR	;MASK TO SEVEN BITS
	SKIPL	LDBATR(U)	;IF NOT 8-BIT,
	ANDI	T3,CK.CH7	;DON'T RETURN PARITY
	MOVE	T1,T3
	PUSHJ	P,PUTWDU##	;GIVE HIM THE CHARACTER
	JRST	NOCTRO		;AND NON-SKIP RETURN

INCHRW:	PUSHJ	P,TWAITC	;WAIT FOR A CHARACTER TO APPEAR
	JRST	ICW2		;GET & RETURN A CHARACTER
	SUBTTL	TTCALL AND TRMOP. -- TRMNO. UUO

;TRMNO.	CALLI, TO GET TERMINAL NUMBER
;FOR SPECIFIED JOB NUMBER.
;	MOVE	AC,JOBNUMBER
;CALL	CALLI	AC,115
;	.ERROR RETURN
;	NORMAL RETURN		;AC HAS .UXTRM+LINE#

TRMNO::	CAMN	T1,[-1]		;IS ARG -1?
	MOVEI	T1,(J)		;YES, USE THIS JOB
	JUMPLE	T1,RTZER##	;ERROR IF JOB # 0 OR LESS THAN -1
	CAMLE	T1,HIGHJB##	; OR TOO BIG
	JRST	RTZER##		;..
	HRRZ	T1,TTYTAB##(T1)	;GET DDB ADDRESS
	JUMPE	T1,RTZER##	;ERROR IF NONE
	MOVE	U,DDBLDB(T1)	;GET LDB ADDRESS
	JUMPE	U,RTZER##	;ERROR IF DETACHED
	LDB	T1,LDPLNO	;GET LINE NUMBER
	ADDI	T1,.UXTRM	;CONVERT TO UNIVERSAL
	JRST	STOTC1##	;SKIP RETURN INDEX TO USER
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. DISPATCH

;TRMOP. UUO, OR CALLI 116.
;UUO TO PERFORM MISCELLANEOUS FUNCTIONS FOR
;A SPECIFIED TERMINAL.
;
;CALL:	MOVE	AC,[XWD N,ADR]
;	CALLI	AC,116
;	  ERROR	RETURN
;	NORMAL	RETURN
;

TRMOP::	PUSHJ	P,SAVE4##	;SAVE THE PRESERVED AC'S
	MOVE	P4,T1		;USER'S ARGUMENT TO P4
	HRRM	T1,M		;ADDRESS OF ARGUMENT LIST
	HLRZ	T2,T1		;CHECK FOR LENGTH AT LEAST 2
	CAIL	T2,2
	PUSHJ	P,GETWRD##	;GET USER'S ARG AT M
	  JRST	TOPX3		;ERROR CODE 3, ILLEGAL ADDRESS
	TLNE	T1,-1		;IF BITS IN L.H.
	JRST	RTZER##		; THEN BAD FUNCTION
	HRRZ	P1,T1		;COPY USER ARGUMENT
	JUMPLE	P1,RTZER##	;ZERO ERROR IF BAD ARGUMENT CODE
	PUSHJ	P,GETWR1##	;GET IT, IF POSSIBLE
	  JRST	TOPX3		;NOT A LEGAL ADDRESS
	SUBI	T1,.UXTRM	;REMOVE TERMINAL OFFSET
	CAME	T1,[-1-.UXTRM]	;WANTS CONTROLLING TTY?
	JRST	TRMNRM		;NO
	HRRZ	T1,TTYTAB##(J)	;YES, GET DDB ADDRESS
	JUMPE	T1,RTZER##	;ERROR IF NONE
	MOVE	U,DDBLDB(T1)	;GET LDB ADDRESS
	JUMPE	U,RTZER##	;DETACHED
	LDB	T1,LDPLNO	;GET LINE NUMBER
TRMNRM:	JUMPL	T1,RTZER##	;RANGE CHECK THE TERMINAL #
	CAIL	T1,TTPLEN##	;..
	JRST	RTZER##		;BAD LINE NUMBER
	MOVE	U,LINTAB##(T1)	;OK. GET THE LDB ADDRESS
IFN FTNET,<
	SKIPGE	LDBREM(U)	;IF LOCAL LINE SET HOSTING AWAY,
	JRST	TOPX6		;THEN DISALLLOW ACCESS
>;END IFN FTNET
	MOVE	T2,LDBTTW(U)	;GET SOME BITS
	TLNN	T2,LTLUSE	;IS THIS LINE IN USE?
	JRST	TOPX6		;NO--DISALLOW ACCESS
	MOVE	F,LDBDDB(U)	;AND DDB, IF ANY.
	JUMPN	F,TRMO1		;DID WE FIND A DDB?
	HRLZ	T2,LDBDCH(U)	;NO, GET LINE STATUS
	JUMPGE	T2,TRMO1	;PTY?
	SUBI	T1,TCONLN##+1	;YES, GET NUMBER
	HRRZ	F,PTYTAB(T1)	;GET DDB ADDR


;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

TRMO1:	MOVE	T1,P1		;GET USER'S FUNCTION CODE
	TRNE	T1,3000		;READ/SET CODE?
	JRST	TOPRSQ		;PROBABLY. GO SEE.
	CAILE	T1,TOPLN0	;IS IT AN ACTION CODE?
	JRST	RTZER##		;NO. NO SUCH CODE
	HRRI	M,1(M)		;ADVANCE M
	MOVE	P3,TOPTB0-1(T1)	;PICK UP DISPATCH WORD
	LDB	T1,[POINT 3,P3,17]	;GET MIN LENGTH OF ARG LIST
	HLRZ	T2,P4		;AND LENGTH USER SUPPLIED
	CAIGE	T2,(T1)		;DID HE GIVE US ENOUGH?
	 JRST	TOPX3		;NOPE
IFN FTMIC,<
	MOVSI	P2,(JB.LSY)	;PROGRAM FROM SYS BIT
	TLNE	P3,(TOP.MC)	;MIC TRMOP?
	TDNN	P2,JBTLIM##(J)	;AND DID THIS PROGRAM COME FROM SYS?
	JRST	CHKRED		;NO TO EITHER
	MOVSI	P2,'MIC'	;RUNNING MIC?
	CAMN	P2,JBTNAM##(J)	;SKIP IF NO
	JRST	CHKDDB		;RUNNING MIC, NO FUTHER CHECKING REQUIRED
CHKRED:	MOVSI	T1,JP.POK
	TLNE	P3,(TOP.MR)
	PUSHJ	P,PRVBIT
	  SKIPA
	JRST	TOPX1
>
	TLNN	P3,(TOP.RP)	;DO WE NEED READ PRIVS?
	JRST	CHKWRT		;NO--SEE IF WE NEED WRITE PRIVS
	PUSHJ	P,TREDOK	;YES--DO WE HAVE READ PRIVS?
	  JRST	TOPX1		;NO--GIVE ERROR RETURN
CHKWRT:	TLNN	P3,(TOP.WP)	;DO WE NEED WRITE PRIVS?
	JRST	CHKDDB		;NO--DISPATCH
	PUSHJ	P,TWRTOK	;YES--DO WE HAVE READ PRIVS?
	  JRST	TOPX1		;NO--GIVE ERROR RETURN
CHKDDB:	TLNN	P3,(TOP.NF)	;NEED F?
	JRST	CHKDD1		;NO--ALLSET
	PUSHJ	P,TOPDDB	;YES--GET DDB
	  JRST	TOPX6		;CAN'T GIVE ERROR
CHKDD1:	SSX	P3,MCSEC1	;STAY IN SECTION 1
	JRST	(P3)		;YES--DO THE TRMOP.
;HERE IF REQUESTED FUNCTION NOT FROM 1 THRU TOPLN0-1
;F AND U ARE SET UP TO THE DESIRED LINE.

TOPRSQ:	SETZ	P3,		;SETUP P3 FOR MYTTY1 ROUTINE (PRIV CHECKS)
	ANDI	P1,777		;JUST THE ITEM NUMBER
	TRZE	T1,1000		;READ CODE?
	JRST	TOPRED		;PROBABLY
	CAIL	T1,2000+TOPLN1	;NO. SET CODE?
	JRST	RTZER##		;NOT A LEGAL CODE
	HLRZ	T2,P4		;IS THERE ANOTHER DATUM?
	CAIGE	T2,3		;..
	JRST	TOPX3		;NO. CAN'T DO THE SET.
	PUSHJ	P,GETWR1##	;YES. GO GET IT
	  JRST	TOPX3		;NOT A LEGAL ADDRESS
	MOVE	P2,T1		;SAVE ARGUMENT
	PUSHJ	P,TWRTOK	;DOES HE HAVE WRITE PRIVS?
	  JRST	TOPX1		;NO. ERROR CODE 1.
	LDB	T1,TOPSYR	;LEGAL TO TRY SETTING.
	JUMPE	T1,TOPST2	;RANGE CHECK REQUIRED?
	HLRZ	T2,TOPSRT-1(T1)	;YES. GET MINIMUM VALUE
	CAMGE	P2,T2		;SUPPLIED .GE. MINIMUM?
	JRST	TOPX2		;NO. BAD ARG, TOO SMALL
	HRRZ	T2,TOPSRT-1(T1)	;OK. CHECK MAXIMUM
	CAMLE	P2,T2		;..
	JRST	TOPX2		;BAD. ARG TOO BIG.
TOPST2:	SKIPN	T2,TOPTB1(P1)	;SET ALLOWED?
	PJRST	RTZER##		;ILLEGAL/UNKNOWN FUNCTION
	TLNE	T2,(TOP.SA)	;OK TO SET?
	JRST	TOPST4		;YES--DO SO
	TLNN	T2,(TOP.PS)	;NEED PRIVS?
	JRST	TOPX1		;NO--CAN NOT SET
	MOVSI	T1,JP.POK	;POKE BIT
	PUSHJ	P,PRVBIT##	;IS IT SET?
	  JRST	TOPST4		;YES--DO SET
	JRST	TOPX1		;NO. NOT ALLOWED.
TOPST4:	TLNN	T2,(TOP.IF)	;THIS FUNCTION ILLEGAL FOR FRCLIN?
	JRST	TOPST5		;NO, CONTINUE
	LDB	T1,LDPLNO	;GET LINE NUMBER
	CAIN	T1,FRCLIN##	;IS IT FRCLIN?
	JRST	TOPX1		;YES, ILLEGAL
TOPST5:	MOVE	T1,T2		;COPY BITS
	SSX	T2,MCSEC1	;MAKE INTO A SECTION 1 ADDRESS FOR INDEXING
	TLNN	T1,(TOP.RT)	;NEED A ROUTINE TO SET?
	JRST	TOPST6		;NO, GO HANDLE BYTE POINTERS
	AOS	T2		;YES, INCREMENT ADDRESS
	TLNE	T1,(TOP.BP)	;DOES READ FUNCTION USE A BYTE POINTER?
	HRR	T2,(T2)		;YES, INDIRECT ROUTINE ADDRESS
	PJRST	(T2)		;LET ROUTINE HANDLE IT
TOPST6:	MOVE	T3,T2		;COPY B.P. ADDRESS
	TLNE	T1,(TOP.BP)	;IF DUAL FLAVOR,
	MOVE	T3,(T3)		;INDIRECT IT
	LDB	T3,0(T3)	;FETCH WHAT THE STATE IS CURRENTLY
	CAMN	T3,P2		;WILL IT CHANGE?
	JRST	CPOPJ1##	;NO, DON'T SEND STATUS CHANGE THEN
	MOVEI	T3,LDRPTY	;THE LINE-IS-A-PTY BIT
	CAIN	P1,4		;SET SLAVE?
	TDNN	T3,LDBDCH(U)	; ON PTY?
	TRNA			;NO
	JRST	TOPX1		;YES, ILLEGAL FUNCTION FOR PTY
	TLNN	T1,(TOP.BP)	;IS THIS A DUAL-B.P. FUNCTION?
	JRST	TOPST7		;NO--HANDLE SINGE-B.P.
	MOVE	T3,(T2)		;YES--GET FIRST BYTE POINTER
	DPB	P2,(T3)		;SET IN IT
	MOVE	T3,1(T2)	;GET SECOND BYTE POINTER
	DPB	P2,(T3)		;SET IN BOTH POINTERS
	TRNA			;SKIP SINGLE-B.P. CASE
TOPST7:	DPB	P2,0(T2)	;OK. CHANGE ITEM.
	TLNE	T1,(TOP.PE)	;DO WE NEED TO NOTIFY THE FE?
	PUSHJ	P,SETCHP	;YES, DO SO
	JRST	CPOPJ1##	;RETURN SUCCESS
TOPRED:	CAIL	T1,TOPLN1	;LEGAL ITEM NUMBER?
	JRST	RTZER##		;NO. ERROR RETURN
	PUSHJ	P,TREDOK	;OK TO DO A READ?
	  JRST	TOPX1		;NO. PROTECTION FAILURE.
	SKIPN	T1,TOPTB1(P1)	;OK. GET TABLE ENTRY.
	JRST	RTZER##		;ILLEGAL/UNKNOWN FUNCTION
	HRRZ	T2,T1		;GET JUST DISPATCH OR BYTE POINTER ADDRESS
	TLNE	T1,(TOP.RT)	;NEED A ROUTINE
	TLNE	T1,(TOP.BP)	;AND NOT JUST FOR SET?
	JRST	TOPRD1		;NO, USE B.P.
	PUSHJ	P,0(T2)		;ZERO OFFSET TO READ
	PJRST	STOTC1##	;RETURN RESULT TO USER AND SKIP RETURN

TOPRD1:	TLNE	T1,(TOP.BP)	;DUAL-B.P. FUNCTION?
	MOVE	T2,(T2)		;YES--INDIRECT BYTE POINTER
	LDB	T1,0(T2)	;GET BYTE POINTED TO
	PJRST	STOTC1##	;AND RETURN IT TO USER


;ROUTINE TO RETURN OUTPUT-IN-PROGRESS

TOROIP:	PUSHJ	P,TOPSOP	;SKIP IF OUTPUT IN PROGRESS
	  TDZA	T1,T1		;CLEAR BUSY IF NO OUTPUT
	MOVEI	T1,1		;NO, SET BUSY FLAG
	POPJ	P,		;...


;ROUTINE TO HANDLE FUNCTION 2022 (SET XOFF)
TOPXFF:	DPB	P2,LDPSTP	;STORE USERS VALUE
IFN FTNET,<
	SKIPL	LDBTTW(U)	;ANF NETWORK TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	JRST	TOPXF1		;NO, DON'T SET LRRXFF
	MOVEI	T1,LRRXFF	;TELL FRONT END ABOUT XON/XOFF IN STATUS MSG.
	IORM	T1,LDBREM(U)	;
	JRST	TOPXF2		;GO TO COMMON CODE
>;END IFN FTNET
TOPXF1:
IFN FTKL10,<
	HRRZ	T1,LDBISR(U)	;GET ISR DISPATCH
	CAIE	T1,TTDDSP##	;IS THIS A -20F LINE
	 JRST	CPOPJ1##	;NO
	MOVSI	T1,LTLXFF	;YES, SET BIT TO INFORM -20F
	IORM	T1,LDBTTD(U)	;
>;END IFN FTKL10
TOPXF2:	PJRST	SETCH1		;SUCCEED AFTER NOTIFYING FE
;ROUTINE TO SET THE VALUE OF LDLFRM

TOPFRM:	MOVEI	T3,MC.FRM	;HERE TO SET .TOFRM.  LOAD FUNCTION
	PUSHJ	P,OUTSTB	;QUEUE IT UP FOR SYNCHRONICITY
	PJRST	CPOPJ1##	;AND SIGNAL GOOD RETURN

;ROUTINE TO SET THE VALUE OF LDLTAB

TOPTAB:	MOVEI	T3,MC.TAB	;HERE TO SET .TOTAB.  LOAD FUNCTION
	PUSHJ	P,OUTSTB	;QUEUE IT UP FOR SYNCHRONICITY
	PJRST	CPOPJ1##	;AND SIGNAL GOOD RETURN

;ROUTINE TO SET THE VALUE OF LDLNFC

TOPNFC:	MOVEI	T3,MC.NFC	;HERE TO SET .TONFC.  LOAD FUNCTION TO PERFORM
	PUSHJ	P,OUTSTB	;QUEUE IT UP FOR SYNCHRONICITY
	JRST	CPOPJ1##	;AND SIGNAL GOOD RETURN


;ROUTINE TO FETCH/SET THE VALUE OF HPOS

TOPHPS:	JRST	TORHPS		;HERE FOR READ
	MOVEI	T3,MC.HPS	;GET FUNCTION TO USE IN XMTCHR
	PUSHJ	P,OUTSTF	;QUEUE UP THE FUNCTION
	JRST	CPOPJ1##	;AND SIGNAL GOOD RETURN

TORHPS:	PUSHJ	P,HPOS		;GET POSITION
	MOVE	T1,T2		;GET INTO CORRECT AC
	POPJ	P,

;ROUTINE TO HANDLE SET OF LDRRMT
TOPRMT:	ANDI	P2,1		;NORMALIZE ARGUMENT
	LDB	T2,LDPRMT	;GET CURRENT SETTING
	CAMN	T2,P2		;IF NO CHANGE,
	JRST	CPOPJ1##	;SUCCEED VACUOUSLY
	JUMPE	P2,TOPRM1	;ELSEWHERE IF WANTING TO CLEAR
	MOVSI	T1,JP.POK	;POKE PRIVS REQUIRED TO SET
	PUSHJ	P,PRVBIT##	;CHECK FOR THEM
	  JRST	TOPRM2		;IT'S COOL
	JRST	TOPX1		;PRIVILEGE ERROR
TOPRM1:	LDB	T2,LDPLNO	;LINE NUMBER
	CAIL	T2,FRCLIN##	;MAKE SURE IT'S A REASONABLE TERMINAL
	CAILE	T2,TCONLN##	;IS IT FRCLIN OR A CTY?
	JRST	TOPRM2		;NO, SO ALLOW IT
	JRST	TOPX1		;PRIVILEGE ERROR
TOPRM2:	DPB	P2,LDPRMT	;MAKE THE CHANGE
	JRST	CPOPJ1##	;AND RETURN SUCCESS


;ROUTINE TO SET THE VALUE OF LDPWID

TOPWID:	MOVEI	T3,MC.WID	;GET FUNCTION TO USE IN XMTCHR
	PUSHJ	P,OUTSTF	;QUEUE UP THE FUNCTION
	JRST	CPOPJ1##	;AND SIGNAL GOOD RETURN

;ROUTINE TO HANDLE SET OF L1RDEM
TOPDEM:	LDB	T2,LDPDEM	;GET OLD VALUE
	ANDI	P2,1		;KEEP ONLY THE BIT WE'LL USE
	CAMN	T2,P2		;CHANGING IT?
	JRST	CPOPJ1##	;NO, IGNORE
	DPB	P2,LDPDEM	;STORE OUR NEW VALUE
	MOVSI	T2,L3LDMC	;GET THE CHANGE BIT
	IORM	T2,LDBBY3(U)	;LIGHT IT FOR RECINT
	PJRST	SETCH1		;POKE THE FRONT END AND RETURN GOODNESS

;ROUTINE TO HANDLE .TOPSZ (TTY PAGE N)

TOPPSZ:	DPB	P2,LDPLNB	;SET PAGE LENGTH
	DPB	P2,LDPSTB	;SET STOP BASE
	MOVSI	T2,LPLXNF!LPLSTP!LPLSBL  ;GET THE "STOP" BITS
	IORM	T2,LDBPAG(U)	;AND SET AUTO STOP
	PUSHJ	P,CLRPCT
	JRST	CPOPJ1##	;SUCCESSFUL RETURN


;SUBROUTINE TO QUEUE UP A SYNCHRONOUS OUTPUT FUNCTION.
;CALL:	MOVE	T3,MC.XXX	;FUNCTION CHARACTER TO BE PERFORMED
;	MOVE	P2,USER VALUE	;ARGUMENT TO THE FUNCTION
;	PUSHJ	P,OUTSTF	;QUEUE UP TWO CHARACTERS
;	ALWAYS RETURN CPOPJ

OUTSTB:	ANDI	P2,1		;ENTRY FOR ON-BIT VALUES

OUTSTF:	SKIPG	TTFREN##	;ANY FREE CHUNKS?
	JRST	OUTSF2		;NO, WAIT FOR SOME
	SCNOFF			;FOR STCHK'ING
	MOVE	P1,LDBTOP(U)	;SAVE POINTER FOR BACKING OUT
	SKIPG	TTFREN##	;CHECK FREE POOL AGAIN
	JRST	OUTSF1		;WAIT FOR SOME TO APPEAR
	STCHK	T3,LDBTOP(U),OUTSF1	;STUFF AWAY THE FUNCTION
	STCHK	P2,LDBTOP(U),OUTSF1	;AND ITS ARGUMENT
	MOVEI	P1,2		;NUMBER OF BYTES ADDED
	ADDM	P1,LDBTOC(U)	;UPDATE CHARACTER COUNT
	SCNON			;ALLOW OTHERS AGAIN
	PJRST	TOPOKE		;BE SURE THE LINE IS QUEUED

OUTSF1:	MOVEM	P1,LDBTOP(U)	;RESTORE POINTER
	SCNON			;ALLOW OTHERS
OUTSF2:	PUSHJ	P,OUTSTS	;WAIT A TICK
	JRST	OUTSTF		;AND TRY, TRY, AGAIN

OUTSTS:	PUSH	P,T3		;SAVE THE CHARACTER
	SETZ	T1,		;A SHORT TIME
	S0PSHJ	SLEEPF##	;WAIT IT OUT
	POP	P,T3		;RESTORE THE CHARACTER
	POPJ	P,		;RETURN TO TRY AGAIN


REPEAT 0,<
;SUBROUTINE TO QUEUE UP A SYNCHRONOUS INPUT FUNCTION.
;CALL:	MOVE	T3,MC.XXX	;FUNCTION CHARACTER TO BE PERFORMED
;	MOVE	P2,USER VALUE	;ARGUMENT TO THE FUNCTION
;	PUSHJ	P,INPSTF	;QUEUE UP TWO CHARACTERS
;	ALWAYS RETURN CPOPJ

INPSTF:	SKIPG	TTFREN##	;ANY FREE CHUNKS?
	JRST	INPSF2		;NO, WAIT FOR SOME
	SCNOFF			;FOR STCHK'ING
	MOVE	P1,LDBTIP(U)	;SAVE POINTER FOR BACKING OUT
	SKIPG	TTFREN##	;CHECK FREE POOL AGAIN
	JRST	INPSF1		;WAIT FOR SOME TO APPEAR
	STCHK	T3,LDBTIP(U),INPSF1	;STUFF AWAY THE FUNCTION
	STCHK	P2,LDBTIP(U),INPSF1	;AND ITS ARGUMENT
	MOVEI	P1,2		;NUMBER OF BYTES ADDED
	ADDM	P1,LDBECC(U)	;UPDATE CHARACTER COUNT
	JRST	SONPPJ		;RETURN ALLOWING OTHERS AGAIN

INPSF1:	MOVEM	P1,LDBTIP(U)	;RESTORE POINTER
	SCNON			;ALLOW OTHERS
INPSF2:	PUSHJ	P,OUTSTS	;WAIT A TICK
	JRST	INPSTF		;AND TRY, TRY, AGAIN
> ;END REPEAT 0
;ROUTINE TO GET/SET TERMINAL TYPE

TOPTTC:	JRST	TORTTC		;GET TERMINAL TYPE
	MOVE	T2,P2		;GET USER'S ARGUMENT
	PUSHJ	P,TTUTYP##	;SET TERMINAL CHARACTERISTICS
	  JRST	TOPX2		;UNKNOWN TERMINAL TYPE
	JRST	CPOPJ1##	;GOOD RETURN

TORTTC::LDB	T1,LDPTTT	;GET TERMINAL TYPE
	TRZE	T1,100		;CUSTOMER DEFINED TERMINAL TYPE ?
	MOVNS	T1		;YES
	MOVE	T1,TTTWDT##(T1)	;GET TERMINAL NAME
	POPJ	P,		;STORE ANSWER FOR THE USER AND RETURN



;ROUTINE TO SET OUTPUT SUPPRESSION (^O) STATE

TOPSUP:	TRNE	P2,1		;SET OR CLEAR ^O?
	JRST	TOPSU2		;SET IT
	PUSHJ	P,NOCTRO	;CLEAR IT
	JRST	CPOPJ1##	;RETURN HAPPILY

TOPSU2:	PUSHJ	P,STCTRO	;SET ^O STATE
	JRST	CPOPJ1##	;RETURN SUCCESSFULLY


; ROUTINE TO SET FULL CHARACTER SET

TOPFCS:	JUMPE	F,TOPX6		;NEED A DDB
	DPB	P2,LDPFCS	;STORE IN LDB
	DPB	P2,[POINT 1,DEVIOS(F),^L<IOSFCS>] ;YES--SET IN DDB
	PUSHJ	P,SETBMC	;POKE THE FRONT END
	JRST	CPOPJ1##	;AND RETURN

; ROUTINE TO SET BREAK ON ALL CHARACTERS

TOPBKA:	JUMPE	F,TOPX6		;NEED A DDB
	DPB	P2,LDPBKA	;STORE IN LDB
	DPB	P2,[POINT 1,DEVIOS(F),^L<IOSBKA>] ;YES--SET IN DDB
	PUSHJ	P,SETBMC	;POKE THE FRONT END
	JRST	CPOPJ1##	;AND RETURN


;ROUTINE TO RETURN TOTAL INPUT CHARACTER COUNT

TORCCT:	MOVE	T1,LDBTIC(U)	;INPUT CHARACTER COUNT AVAILABLE TO USER
	ADD	T1,LDBECC(U)	;PLUS THOSE NOT YET ECHOED
	SUB	T1,LDBIIC(U)	;MINUS DELETIONS
	SUB	T1,LDBIEC(U)	;OF BOTH SORTS
	POPJ	P,		;RETURN TOTAL MONITOR CHARACTER COUNT
;HERE TO READ/SET TERMINAL LENGTH COUNTER

TOPLNC:	JRST	TORLNC		;GO HANDLE READ REQUEST
	MOVN	T2,P2		;NEGATIVE SINCE COUNTS UP TO 0
	ANDI	T2,377		;ONLY 8-BITS WORTH
	DPB	T2,LDPLNC	;BUT A 9-BIT POINTER (FOR OVERFLOW)
	JRST	CPOPJ1##	;SUCCESSFUL RETURN

TORLNC:	LDB	T1,LDPLNB	;GET BASE SIZE
	JUMPE	T1,CPOPJ##	;IF NO LENGTH THEN COUNTER IS 0 BY DEFINITION
	LDB	T1,LDPLNC	;ELSTWISE PICKUP CURRENT LENGTH COUNTER
	IOR	T1,[777777,,777400]  ;"SIGN EXTEND" THE FIELD
	MOVN	T1,T1		;GET POSITIVE LINES LEFT
	POPJ	P,		;AND RETURN



;HERE TO READ/SET TERMINAL STOP COUNTER

TOPSTC:	JRST	TORSTC		;GO HANDLE READ REQUEST
	MOVN	T2,P2		;NEGATIVE SINCE COUNTS UP TO 0
	ANDI	T2,377		;ONLY 8-BITS WORTH
	DPB	T2,LDPSTC	;BUT A 9-BIT POINTER (FOR OVERFLOW)
	JRST	CPOPJ1##	;SUCCESSFUL RETURN

TORSTC:	LDB	T1,LDPSTB	;GET BASE SIZE
	JUMPE	T1,CPOPJ##	;IF NO STOP SIZE THEN COUNTER IS 0 BY DEFINITION
	MOVSI	T1,LPLSTP	;THE AUTO STOP BIT
	AND	T1,LDBPAG(U)	;SEE IF AUTO STOP IS ENABLED
	JUMPE	T1,CPOPJ##	;IF NOT, THEN COUNTER IS 0 BY DEFINITION
	LDB	T1,LDPSTC	;ELSTWISE PICKUP CURRENT STOP COUNTER
	IOR	T1,[777777,,777400]  ;"SIGN EXTEND" THE FIELD
	MOVN	T1,T1		;GET POSITIVE LINES LEFT
	POPJ	P,		;AND RETURN


; ROUTINE TO SET/READ ECHO STATUS
TOPECH:	JRST	TORECH		;GO HANDLE READ REQUEST
	JUMPE	F,TOPX6		;NEED A DDB
	TRC	P2,1		;CORRECT SENSE
	MOVE	T2,LDBDCH(U)	;GET DCH BITS
	TLNN	T2,LDLCNE!LDLCOM ;IF NOT OVERRIDDEN,
	DPB	P2,LDPECH	;STORE IN LDB
	DPB	P2,SETLP0	;YES--SET IN DDB
	PJRST	SETCH1		;POKE THE FRONT END AND RETURN SUCCESS

TORECH:	LDB	T1,LDPECH	;GET ECHO STATUS FROM LDB
	TRC	T1,1		;CORRECT SENSE SO USER NOT CONFUSED
	POPJ	P,		;AND RETURN


;ROUTINE TO SET UNPAUSE CHARACTER

TOPUNP:	CAMN	P2,[-1]		;WANT TO DEFAULT IT?
	MOVEI	P2,"Q"-100	;YES, MAKE IT ^Q
	LDB	T2,LDPUNP	;GET PREVIOUS SETTING
	CAMN	T2,P2		;CHANGING IT?
	JRST	CPOPJ1##	;NO, SUCCEED VACUUOUSLY
	DPB	P2,LDPUNP	;YES, DO SO
	PUSHJ	P,TOPNDS	;SET LMLNDS APPROPRIATELY
	PUSHJ	P,SETOBC	;POKE THE FRONT END
	JRST	CPOPJ1##	;SUCCESS


;ROUTINE TO SET ESCAPE CHARACTER

TOPESC:	CAMN	P2,[-1]		;WANT TO DEFAULT IT?
	MOVEI	P2,STDALT	;YES, MAKE IT ESCAPE
	LDB	T1,LDPESC	;GET PREVIOUS SETTING
	CAMN	T1,P2		;CHANGING ANYTHING?
	JRST	CPOPJ1##	;NO, JUST SUCCEED
	DPB	P2,LDPESC	;YES, CHANGE IT
	PUSHJ	P,TOPNDS	;SET LMLNDS CORRESPONDINGLY
	PUSHJ	P,SETOBC	;POKE THE FRONT END
	JRST	CPOPJ1##	;RETURN TO USER

;ROUTINE TO SET/READ SWITCH SEQUENCE (FOR CTERM)

TOPSWI:	JRST	TORSWI		;HANDLE READ
	CAMN	P2,[-1]		;REQUESTING DEFAULT?
	MOVSI	P2,(<BYTE(8)34,15>) ;YES, LOAD UP ASCII8 "^\^M"
	TDNE	P2,[BYTE(16)0(20)-1]	;CHECK FOR BITS BESIDES THE CHARACTERS
	JRST	TOPX2		;GIVE A RANGE ERROR IF SO
	LSH	P2,-^D20	;RIGHT-JUSTIFY USER ARG
	LDB	T1,LDPSWI	;GET PREVIOUS SETTING
	CAMN	T1,P2		;CHANGING ANYTHING?
	JRST	CPOPJ1##	;NO, SUCCEED VACUOUSLY
	MOVE	T2,P2		;COPY USER ARG
	LSH	T2,-8		;ISOLATE HIGH CHARACTER
	XOR	T2,P2		;TEST FOR IDENTITY
	TRNN	T2,CK.CHR	;ARE THE CHARACTERS DIFFERENT?
	JUMPN	P2,TOPX2	;NO, ERROR UNLESS CLEARING THE SEQUENCE
	DPB	P2,LDPSWI	;OK, SET THE NEW VALUE
	MOVSI	T2,LMLSSE	;SWITCH-SEQUENCE ENABLED BIT
	IORM	T2,LDBCHM(U)	;ASSUME WE JUST ENABLED
	SKIPN	P2		;VALID ASSUMPTION?
	ANDCAM	T2,LDBCHM(U)	;NO, CLEAR THE BIT WHEN DISABLING
	PUSHJ	P,TOPNDS	;SET LMLNDS CORRESPONDINGLY
	PUSHJ	P,SETOBC	;NOTIFY THE FRONT END
	JRST	CPOPJ1##	;RETURN SUCCESS

TORSWI:	LDB	T1,LDPSWI	;FETCH THE SEQUENCE
	LSH	T1,^D20		;MAKE IT MATCH A USER ARGUMENT
	POPJ	P,		;RETURN IT


;ROUTINE TO SET/CLEAR LMLNDS AS APPROPRIATE

TOPNDS::MOVSI	T2,LMLNDS	;NON-DEFAULT SEQUENCE BIT
	IORM	T2,LDBCHM(U)	;ASSUME THE MAP IS NON-STANDARD
	LDB	T1,LDPUNP	;GET THE UNPAUSE CHARACTER
	PUSHJ	P,TOPND1	;SEE IF ITS OK
	POPJ	P,		;NO, OUR ASSUMPTION IS VERIFIED
	LDB	T1,LDPESC	;IT WAS, GET THE ESCAPE CHARACTER
	PUSHJ	P,TOPND1	;IS IT STANDARD?
	POPJ	P,		;NO
	MOVSI	T1,LMLSSE	;YES, CHECK FOR SWITCH SEQUENCE
	TDNN	T1,LDBCHM(U)	;IS IT ENABLED?
	JRST	TOPND2		;NO, THIS IS A STANDARD MAP
	LDB	T1,LDPSW1	;YES, GET SWITCH-1
	PUSHJ	P,TOPND1	;IS IT STANDARD?
	POPJ	P,		;NO
	LDB	T1,LDPSW2	;YES, HOW ABOUT SWITCH-2
	PUSHJ	P,TOPND1	;CHECK IT
	POPJ	P,		;NON-STANDARD
TOPND2:	ANDCAM	T2,LDBCHM(U)	;STANDARD SEQUENCE AFTER ALL
	POPJ	P,		;RETURN TO CALLER

TOPND1:	TRNE	T1,CK.CH7^!37	;IS IT A CONTROL CHARACTER?
	POPJ	P,		;NO, IT'S NON-STANDARD
	CAIE	T1,11		;YES, IF IT'S NOT A TAB
	JUMPN	T1,CPOPJ1##	;AND NOT NULL, IT'S STANDARD
	POPJ	P,		;NOPE, NON-STANDARD
;ROUTINE TO SET THE 8-BIT I/O MODE BIT
TOP8BI:	JUMPE	F,TOPX6		;MUST HAVE A DDB TO DO THIS
	DPB	P2,LDP8BI	;STORE IN LDB
	LDB	T1,[POINT 4,DEVIOS(F),35] ;GET THE I/O MODE CURRENTLY SET
	CAILE	T1,A8		;IS IT SOMETHING WE SHOULD CHANGE?
	JRST	CPOPJ1##	;NO, JUST SUCCEED
	MOVEI	T1,A8		;YES, GET NEW MODE
	TRNN	P2,1		;UNLESS TURNING IT OFF,
	MOVEI	T1,AL		;THEN GET OTHER NEW MODE
	DPB	T1,[POINT 4,DEVIOS(F),35] ;SAVE IT AWAY IN THE DDB
	JRST	CPOPJ1##	;NOW SUCCEED


;ROUTINE TO SET THE MAXIMUM IDLE TIME FOR THE AUTO-DISCONNECT FEATURE
TOPMXT:	AOS	(P)		;WE'RE GOING TO SUCCEED
	MOVE	T1,P2		;PUT THE ARGUMENT WHERE IT BELONGS
	PJRST	SCNADT		;SET THE TIMER AND RETURN


;ROUTINE TO READ THE REMAINING LIMIT ON THE AUTO-DISCONNECT TIMER
TORADT:	LDB	T2,LDPTMR	;GET THE COUNT-UP VALUE
	SETO	T1,		;AND THE VALUE FOR AN EXPIRED TIMER
	TRNE	T2,L3RTMO	;IF IT'S TIMED-OUT,
	POPJ	P,		;RETURN MINUS ONE
	LDB	T2,LDPMXT	;GET THE ORIGINAL LIMIT
	HRLOI	T1,377777	;LOAD UP A POSITIVE INFINITY
	JUMPE	T2,CPOPJ##	;RETURN INFINITY IF NO TIMING
	LDB	T1,LDPTMR	;GET COUNT-UP VALUE AGAIN
	MOVNS	T1		;ACCOUNT FOR ITS NEGATION
	ANDI	T1,377		;KEEP ONLY RELEVANT BITS
	POPJ	P,		;RETURN THE REMAINING TIME LIMIT

TOPCNE:	JRST	TORCNE		;READ ROUTINE
	ANDI	P2,1		;NORMALIZE THE ARGUMENT
	JUMPN	P2,TOPCN1	;ELSEWHERE IF 'CLEARING'
	MOVSI	T2,LDLCNE!LDLNEC ;SETTING, EASY CASE
	IORM	T2,LDBDCH(U)	;JUST LIGHT THE NO-ECHO BITS
	PJRST	SETCH1		;POKE FRONT END AND RETURN GOODNESS
TOPCN1:	MOVSI	T2,LDLCNE	;GET BIT WE'RE CLEARING
	ANDCAM	T2,LDBDCH(U)	;WIPE IT
	JUMPE	F,TOPCN2	;ALSO CLEAR LDLNEC IF NO DDB
	MOVE	T1,DEVIOS(F)	;GET STATUS BITS
	TRNE	T1,IOSNEC	;IF STILL WANT NO ECHO,
	JRST	SETCH1		;JUST POKE FE AND SUCCEED
TOPCN2:	MOVSI	T1,LDLNEC	;ANOTHER NO-ECHO BIT
	ANDCAM	T1,LDBDCH(U)	;CLEAR IT, TOO
	PJRST	SETCH1		;POKE FE AND SUCCEED

TORCNE:	MOVSI	T1,LDLCNE	;GET BIT TO TEST
	TDNE	T1,LDBDCH(U)	;SEE IF CLEAR
	TDZA	T1,T1		;NO, RETURN ZERO
	MOVEI	T1,1		;YES, RETURN ONE
	POPJ	P,		;RETURN IT TO THE USER
;SUBROUTINE TO CHECK FOR READ PRIVS
;CALL WITH:
;	F = DDB OF TARGET OR 0
;	PUSHJ	P,TREDOK
;	  RETURN HERE IF ERROR
;	RETURN HERE IF OK TO READ

TREDOK:	PUSHJ	P,SAVE3##	;SAVE P1,P2 AND P3
	MOVSI	P1,PVSPYM!PVSPYA;LOAD UP THE SPY BIT
	JRST	MYTTY		;JUMP TO COMMON CODE

;SUBROUTINE TO CHECK FOR WRITE PRIVS
;CALL WITH:
;	F = DDB OF TARGET OR 0
;	PUSHJ	P,TWRTOK
;	  RETURN HERE IF ERROR
;	RETURN HERE IF OK
;PRESERVES ALL AC'S

TWRTOK:	PUSHJ	P,SAVE3##	;SAVE P1,P2 AND P3
	MOVSI	P1,JP.POK	;FALL INTO COMMON CODE
MYTTY:	SKIPE	P2,F		;IS THERE A DDB?
	LDB	P2,PJOBN##	;YES--GET THE OWNERS JOB NUMBER
	CAMN	P2,J		;DO I OWN THIS TERMINAL
	JRST	MYTTY1		;CHECK PRIVS FOR MIC STYLE TRMOP
MYTTY2:	EXCH	P1,T1		;SAVE T1 AND SET UP PRIV BIT
	PUSHJ	P,PRVBIT##	;CHECK THE BIT
	  AOS	(P)		;OK TO READ OR SET
	MOVE	T1,P1		;RESTORE T1
	POPJ	P,0		;RETURN

MYTTY1:
IFE FTMIC,<JRST CPOPJ1##>	;OK TO DO YOUR THING
IFN FTMIC,<
	TLNN	P3,(TOP.MC)	;MIC TRMOP?
	JRST	CPOPJ1##	;NO--OK TO DO YOUR THING
	MOVE	P2,DEVMOD(F)	;IS THE TARGET TTY...
	TLNE	P2,TTYATC	;CONTROLLING HIS JOB?
	JRST	CPOPJ1##	;YES--OK TO DO MIC TRMOP
	MOVE	P2,LDBDCH(U)	;NO--IS THE TARGET TTY...
	TRNE	P2,LDRCTY	;A CTY?
	JRST	MYTTY2		;YES--CHECK PRIVS
	CAMN	U,OPRLDB##	;IS THIS "OPR"?
	JRST	MYTTY2		;YES--CHECK PRIVS
	HRRZ	P3,TTYTAB##(J)	;GET USER'S TTY DDB ADDRESS
	JUMPE	P3,MYTTY2	;ERROR IF NONE
	MOVE	P3,DDBLDB(P3)	;USER'S LDB ADDRESS
	JUMPE	P3,MYTTY2	;DETACHED
	MOVE	P3,LDBDCH(P3)	;USER'S TTY CHARACTERISTICS BITS
	TRNN	P3,LDRDSR	;IS HE A LOCAL TTY?
	JRST	CPOPJ1##	;YES--LET HIM DO MIC TRMOP TO EITHER REMOTE OR LOCAL TTY'S
	TRNE	P2,LDRDSR	;NO--TARGET TTY ANOTHER REMOTE TTY?
	JRST	CPOPJ1##	;YES--DO IT
	JRST	MYTTY2		;NO--CHECK PRIVS
>
;ERROR RETURNS

ERCODE	TOPX1,TRMNP%		;(1) ERROR CODE FOR PROT CHECK
ERCODE	TOPX2,TRMBR%		;(2) ERROR CODE FOR RANGE BAD
ERCODE	TOPX3,TRMIA%		;(3) ERROR CODE FOR ADDRESS BAD.
ERCODE	TOPX4,TRMCD%		;(4) ERROR CODE FOR NOT POSSIBLE TO DO
ERCODE	TOPX5,TRMDO%		;(5) ERROR IN DIALLER OPERATION
ERCODE	TOPX6,TRMND%		;(6) CAN NOT GET DDB
ERCODE	TOPX7,TRMNB%		;(7) ATTEMPT TO SET BREAK MASK WHEN NOT IN BREAK MODE
ERCODE	TOPX10,TRMIB%		;(10) ILLEGAL BYTE SIZE
ERCODE	TOPX11,TRMNT%		;(11) NOT A NETWORK TERMINAL
;TOPTB0 - TRMOP. ACTION FUNCTIONS LESS THAN 1000

	TOP.RP==1B1		;NEED READ PRIVS TO DO THIS FUNCTION
	TOP.WP==1B2		;NEED WRITE PRIVS TO DO THIS FUNCTION
	TOP.NF==1B3		;NEED F SETUP TO DO THIS FUNCTION
IFN FTMIC,<
	TOP.MC==1B4		;THIS FUNCTION IS LEGAL IF RUNNING MIC
	TOP.MR==1B5		;FUNCTION REQUIRES MIC
>
;FIELD WHICH CONTAINS THE MINIMUM NUMBER OF ARGS WHICH A USER MUST
;SUPPLY FOR A PARTICULAR FUNCTION.  THIS FIELD ONLY NEEDS TO BE FILLED
;IN IF THE ARG COUNT IS GREATER THAN 2.  IF THE FUNCTION TAKES A VERY
;LONG ARG LIST (LIKE TOPRBS) THEN IT SHOULD DO ITS OWN CHECKING

	TOP.CT==7B17

IF2,<
IFNDEF	TOPABR,<TOPABR==RTZER##>
IFNDEF	TOPELE,<TOPELE==RTZER##>
> ;END IF2 CONDITIONAL

TOPTB0:	EXP	TOP.RP+TOPSIP			;1 - SKIP IF INPUT PRESENT
	EXP	TOP.RP+TOPSOP			;2 - SKIP IF OUTPUT PRESENT
	EXP	TOP.WP+TOPCIB			;3 - CLEAR INPUT BUFFER
	EXP	TOP.WP+TOPCOB			;4 - CLEAR OUTPUT BUFFER
	EXP	<3B17>+TOP.RP+TOP.WP+TOPOUC	;5 - OUTPUT CHAR
	EXP	<3B17>+TOP.RP+TOP.WP+TOP.NF+TOPOIC	;6 - OUTPUT IMAGE CHAR
	EXP	<3B17>+TOP.RP+TOP.WP+TOPOUS	;7 - OUTPUT STRING
	EXP	TOP.RP+TOP.WP+TOPINC		;10 - INPUT CHAR
	EXP	TOP.RP+TOP.WP+TOPIIC		;11 - INPUT IMAGE CHAR
	EXP	TOP.WP+TOPDSE			;12 - DATASET ENABLE
	EXP	<4B17>+TOP.WP+TOPDSC		;13 - DATASET CALL
	EXP	TOP.WP+TOPDSF			;14 - DATASET OFF
	EXP	TOP.RP+TOP.WP+TOPRES		;15 - RESCAN
	EXP	<3B17>+TOP.WP+TOPELE		;16 - SET TYPE ELEMENT
	EXP	TOP.WP+TOPABR			;17 - ENABLE AUTO BAUD DETECT
	EXP	TOP.RP+TOP.WP+TOPISC		;20 - INPUT CHAR.
	EXP	<3B17>+TOP.RP+TOP.WP+IFN FTMIC,<TOP.MC>+TOPMTY	;21 - MICTYP
IFN FTMIC,<
	EXP	<3B17>+TOP.RP+TOP.WP+TOP.MC+TOPMGT	;22 - MICGET
	EXP	<3B17>+TOP.RP+TOP.WP+TOP.MC+TOP.MR+TOPMST;23 - MICSET
	EXP	<3B17>+TOP.RP+TOP.WP+TOP.MC+TOPMCL	;24 - MICCLR
>
IFE FTMIC,<
	EXP	RTZER##				;22 - NOT IMPLEMENTED
	EXP	RTZER##				;23 - NOT IMPLEMENTED
	EXP	RTZER##				;24 - NOT IMPLEMENTED
>
	EXP	<3B17>+TOP.RP+TOP.WP+IFN FTMIC,<TOP.MC>+TOPMDP	;25 - MICDPY
IFN FTMIC,<
	EXP	<3B17>+TOP.RP+TOP.WP+TOP.MC+TOPMRS	;26 - MICDSP
IFN FTMLOG,<
	EXP	<3B17>+TOP.MC+TOP.RP+TOP.WP+TOPMLG	;27 - MICLOG
>
IFE FTMLOG,<
	EXP	RTZER##				;27 - NOT IMPLEMENTED
>
>
IFE FTMIC,<
	EXP	RTZER##				;26 - NOT IMPLEMEMTED
	EXP	RTZER##				;27 - NOT IMPLEMENTED
>
	EXP	TOPDSS				;30 - RETURN DATA SET STATUS
	EXP	TOP.NF+TOPSBS			;31 - SET BREAK SET MASK TABLE
	EXP	TOP.NF+TOPRBS			;32 - READ BREAK MASK TABLE
	EXP	<3B17>+TOP.NF+TOPISO		;33 - IMAGE STRING OUTPUT
	EXP	TOP.WP+TOPFLM			;34 - FORCE LEFT MARGIN
	EXP	TOP.NF+TOP.RP+TOPGCS		;35 - GET CHARACTER STATUS
	EXP	TOP.NF+TOP.WP+TOPSCS		;36 - SET CHARACTER STATUS
	EXP	TOP.NF+TOP.WP+TOPUNR		;37 - UNREAD
	EXP	<3B17>+TOP.NF+TOP.WP+TOPASO	;40 - ASCII STRING OUTPUT
	EXP	TOP.WP+TOPDNT			;41 - DISCONNECT [NETWORK] TTY

IFN FTPATT,<
	EXP	RTZER##				;   - FOR PATCHING
>
TOPLN0==.-TOPTB0
;TOPTB1 - TRMOP. READ/SET FUNCTIONS GREATER THAN 1000
;CONTENTS OF TOPTB1 ARE AS FOLLOWS
;BITS 0-5 ARE RANGE TABLE INDEX FOR RANGE CHECK ON SET.
;BITS 6-17 ARE FLAGS FOR DETERMINING LEGALITY OF TRMOP UUO
;RH IS ADDRESS OF BYTE POINTER.

TOP.SA==1B6	;SET ALLOWED
TOP.PS==1B7	;SET ALLOWED FOR PRIVILEGED JOB ONLY
TOP.PE==1B8	;POKE THE FRONT END IF SET
TOP.RT==1B9	;FETCH/SET REQUIRES A ROUTINE.  ENTERED AT ADDRESS+0
		;FOR FETCH, ADDRESS+1 FOR SET.  FETCH ROUTINE MUST
		;RETURN VALUE IN T1.  SET ROUTINE'S RETURN IS PROPAGATED
		;BACK TO USER.
TOP.IF==1B10	;THIS FUNCTION IS ILLEGAL FOR FRCLIN NO MATTER IF
		;THE JOB IS PRIVILEGED OR NOT
TOP.BP==1B11	;THIS FUNCTION TAKES EITHER TWO B.P.S OR A B.P. AND A ROUTINE

;NOTE: THESE DEFINITIONS MUST AGREE WITH LDB DEFINITIONS
TOPTB1::EXP	<0>B5+<TOP.RT>+<TOROIP>					;1000
	EXP	<0>B5+<0>+<LDPCOM>					;1001
	EXP	<0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBBY2(U),^L<L2RXON>]>	;1002
	EXP	<0>B5+<TOP.SA+TOP.PE+TOP.IF>+<LDPLCT>			;1003
	EXP	<0>B5+<TOP.SA+TOP.IF>+<[POINT 1,LDBDCH(U),^L<(LDLSLV)>]> ;1004
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.BP>+<[EXP LDPTAB,TOPTAB]>	;1005
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.BP>+<[EXP LDPFRM,TOPFRM]>	;1006
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPLCP>				;1007
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.BP>+<[EXP LDPNFC,TOPNFC]>	;1010
	EXP	<0>B5+<TOP.SA+TOP.RT>+<TOPHPS>				;1011
	EXP	<1>B5+<TOP.SA+TOP.RT+TOP.BP>+<[EXP LDPWID,TOPWID]>	;1012
	EXP	<0>B5+<TOP.SA>+<[POINT 1,LDBBY2(U),^L<(L2LSND)>]>	;1013
	EXP	<0>B5+<TOP.PS+TOP.IF>+<[POINT 1,LDBDCH(U),^L<LDRHLF>]>	;1014
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.IF+TOP.BP>+<[EXP LDPRMT,TOPRMT]> ;1015
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPDIS>				;1016
	EXP	<2>B5+<TOP.SA+TOP.PE>+<LDPFLC>				;1017
	EXP	<0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBBY2(U),^L<(L2LTAP)>]>;1020
	EXP	<0>B5+<TOP.SA+TOP.PE+TOP.IF>+<LDPXNF>			;1021
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.IF+TOP.BP>+<[EXP LDPSTP,TOPXFF]> ;1022
	EXP	<3>B5+<TOP.SA+TOP.RT+TOP.IF+TOP.BP>+<[EXP LDPSTB,TOPPSZ]> ;1023
	EXP	<3>B5+<TOP.SA+TOP.RT>+<TOPSTC>				;1024
	EXP	<0>B5+<TOP.SA>+<[POINT 1,LDBPAG(U),^L<(LPLBLK)>]>	;1025
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPALT>				;1026
	EXP	<0>B5+<TOP.SA+TOP.PE+TOP.IF>+<LDPAPL>			;1027
	EXP	<4>B5+<TOP.SA+TOP.PE>+<LDPRSP>				;1030
	EXP	<4>B5+<TOP.SA+TOP.PE>+<LDPTSP>				;1031
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPDBK>				;1032
	EXP	<0>B5+<TOP.PS+TOP.PE+TOP.IF>+<LDP274>			;1033
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPTDY>				;1034
	EXP	<5>B5+<TOP.SA+TOP.PE+TOP.IF>+<LDPACR>			;1035
	EXP	<TOP.SA+TOP.PE>+LDPRTC					;1036
	EXP	<0>B5+<TOP.SA>+<[POINT 36,LDBPBK(U),35]>		;1037
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.PE+TOP.BP>+<[EXP LDPDEM,TOPDEM]> ;1040
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.IF>+<TOPTTC>			;1041
	EXP	<0>B5+<TOP.IF>+<[POINT 36,LDBBCT(U),35]>		;1042
	EXP	<0>B5+<TOP.IF>+<[POINT 36,LDBICT(U),35]>		;1043
	EXP	<0>B5+<TOP.IF>+<[POINT 36,LDBOCT(U),35]>		;1044
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.BP>+<[EXP LDPOSU,TOPSUP]>	;1045
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.IF+TOP.BP>+<[EXP LDPFCS,TOPFCS]> ;1046
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.IF+TOP.BP>+<[EXP LDPBKA,TOPBKA]> ;1047
	EXP	0							;1050
	EXP	0							;1051
	<0>B5+<[POINT 36,LDBTIC(U),35]>					;1052
	EXP	0							;1053
	<0>B5+<[POINT 36,LDBBKC(U),35]>					;1054
	<0>B5+<[POINT 36,LDBECC(U),35]>					;1055
	<0>B5+<TOP.RT>+<TORCCT>						;1056
	<0>B5+<[POINT 36,LDBTOC(U),35]>					;1057
	<3>B5+<TOP.SA+TOP.IF>+<LDPLNB>					;1060
	<3>B5+<TOP.SA+TOP.RT+TOP.IF>+<TOPLNC>				;1061
	<3>B5+<TOP.SA+TOP.IF>+<LDPSTB>					;1062
	<3>B5+<TOP.SA+TOP.RT+TOP.IF>+<TOPSTC>				;1063
	<0>B5+<TOP.SA+TOP.IF>+<[POINT 1,LDBPAG(U),^L<(LPLFFH)>]>	;1064
	<0>B5+<TOP.SA+TOP.IF>+<[POINT 1,LDBPAG(U),^L<(LPLFFF)>]>	;1065
	<0>B5+<TOP.SA+TOP.IF>+<[POINT 1,LDBPAG(U),^L<(LPLFFS)>]>	;1066
	<0>B5+<TOP.SA+TOP.IF>+<LDPSPE>					;1067
	<0>B5+<TOP.SA+TOP.IF>+<LDPSST>					;1070
	<0>B5+<TOP.SA+TOP.IF>+<[POINT 1,LDBPAG(U),^L<(LPLSBL)>]>	;1071
	<0>B5+<0>+<[POINT 1,LDBTTW(U),^L<(LDLFSP)>]>			;1072
	<0>B5+<0>+<[POINT 1,LDBOFL(U),^L<(L1LOFL)>]>			;1073
	<0>B5+<TOP.SA+TOP.RT+TOP.IF>+<TOPECH>				;1074
	<0>B5+<LDPAPC>							;1075
	<6>B5+<TOP.SA+TOP.IF+TOP.RT+TOP.BP>+<[EXP LDPUNP,TOPUNP]>	;1076
	<6>B5+<TOP.SA+TOP.IF+TOP.RT+TOP.BP>+<[EXP LDPESC,TOPESC]>	;1077
	<0>B5+<TOP.SA+TOP.IF+TOP.RT>+<TOPSWI>				;1100
	<0>B5+<TOP.SA+TOP.IF+TOP.PE>+<LDP8BT>				;1101
	<0>B5+<TOP.SA+TOP.RT+TOP.BP>+<[EXP LDP8BI,TOP8BI]>		;1102
	<0>B5+<TOP.SA+TOP.PE+TOP.IF>+<LDPQOT>				;1103
	<3>B5+<TOP.PS+TOP.IF+TOP.RT+TOP.BP>+<[EXP LDPMXT,TOPMXT]>	;1104
	<0>B5+<TOP.RT>+<TORADT>						;1105
	<0>B5+<TOP.IF+TOP.SA+TOP.RT>+<TOPCNE>				;1106
IFN FTPATT,<
	EXP	0		;FOR PATCHING
	EXP	0		;FOR PATCHING
>
TOPLN1==:.-TOPTB1
TOPSYR:	POINT	6,TOPTB1(P1),5	;POINTER TO RANGE TABLE INDEX

;THIS IS THE RANGE TABLE
TOPSRT:	XWD	^D16,^D255	;(1)MIN AND MAX WIDTHS
	XWD	0,3		;(2)MIN AND MAX FILLER CLASSES
	XWD	0,^D255		;(3)MIN AND MAX PAGE LENGTH
	XWD	0,17		;(4)MIN AND MAX SPEED
	XWD	0,^D200		;(5)AUTO C.R. TABLE
	XWD	0,CK.CHR	;(6)CHARACTER MAP DEFINITION TABLE
IFN FTPATT,<BLOCK 1>	;FOR PATCHING
	SUBTTL	TTCALL AND TRMOP. -- SKIPS AND CLEARS

TOPSIP==SKPINC

TOPSOP::SE1ENT			;ENTER SECTION 1
	PUSH	P,T1		;SAVE T1 FOR JOBSTS UUO
	MOVSI	T2,LPLPOK	;THE TTY QUEUED-BY-TOPOKE BIT
	TDNN	T2,LDBPAG(U)	;IS THE TERMINAL QUEUED FOR SERVICE?
	SKIPL	T2,LDBDCH(U)	;NO, IS SERVICE CURRENTLY ACTIVE?
		.CREF LDLIDL	; (CREF REFERENCE TO SYMBOLIC NAME)
	JRST	TPOPJ1##	;OUTPUT ACTIVE OR TEMINAL QUEUED
	SKIPLE	LDBTOC(U)	;REAL CHARACTERS AVAILABLE?
	  JRST	TPOPJ1##	;YES, SKIP RETURN
	MOVE	T2,LDBOST(U)	;GET OUTPUT STATE BITS
	TLNE	T2,LOLXFP!LOLNBS!LOLFSP!LOLESP!LOLSAP	;ANYTHING PENDING?
	JRST	TPOPJ1##	;YES, SKIP RETURN
	MOVE	T2,LDBBYT(U)	;GET DEFER BITS
	SKIPL	LDBBKB(U)	;BREAK MASK IS ALWAYS DEFERRED
	TRNE	T2,L1RDEM	;IF DEFERRED ECHO,
	TRNE	T2,L1RDEC!L1RDEL ;  ONLY IF WANTS INPUT
	CAIA			;YES, TEST
	JRST	TPOPJ##		;NO, IDLE
	PUSHJ	P,ECCAVL	;ANYTHING YET TO BE ECHOED?
	  JRST	TPOPJ1##	;YES, SKIP RETURN
	JRST	TPOPJ##		;NO, LINE IS IDLE RETURN

TOPCIB:	AOS	0(P)		;SUCCESS RETURN
	PJRST	TSETBI		;CLEAR INPUT BUFFER

TOPCOB:	AOS	0(P)		;SUCCESS RETURN
	PJRST	TSETBO		;CLEAR OUTPUT BUFFER

;FOLLOWING NOT DONE YET
	TOPIIC==RTZER##

	SUBTTL	TTCALL AND TRMOP. -- TRMOP. I/O

;OUTPUT 1 CHAR

TOPOUC:	AOS	(P)
	PUSHJ	P,TOPDDB	;GET A DDB
	  SETZM	F		;NO--DON'T NEED IT BADLY
	JRST	ONEOUT		;TYPE

;OUTPUT A STRING

TOPMDP:	MOVEI	T1,LDROSU	;CLEAR CONTROL O BIT
	ANDCAM	T1,LDBDCH(U)	;SO DATA WILL BE SEEN
	TDZA	F,F		;SO CCTYO WILL BE USED (AVOID TIOW)
TOPOUS:	SETOM	F		;SEARCH FOR A DDB
	AOS	(P)
	PUSHJ	P,GETWDU##	;GET POINTER
	HRRZ	M,T1		;PUT IN RIGHT AC
	JUMPE	F,TOPOU1	;USE CCTYO FOR MIC TYPEOUT
	PUSHJ	P,TOPDDB	;GET DDB
	  JRST	TOPOU1		;IF NO DDB
	HRRZ	T1,TTYTAB##(J)	;CONTROLLING TTY
	CAIN	T1,(F)		;IS THIS IT?
	PJRST	OUTSTR		;YES, THEN TOPOUS IS SAME AS OUTSTR
	PUSHJ	P,SAVE4##	;SET TO JOIN OUTSTR CODE IN MIDDLE
	MOVEI	P3,TYO7W	;TYPEOUT ROUTINE
	PJRST	OUTST3		;JOIN OUTSTR

TOPOU1:	PUSHJ	P,SAVE4##	;SET TO JOIN OUTSTR CODE IN MIDDLE
	MOVE	P3,[1B0!CCTYO8]	;NON-BLOCKING OUTPUT
	PJRST	OUTST3		;JOIN OUTSTR

;OUTPUT IMAGE CHAR

TOPOIC::AOS	(P)		;SKIP RETURN
	JRST	IONEOU		;TYPE IT
;INPUT A CHAR

TOPISC:	SKIPA	P1,[EXP INCHRW]
TOPINC:	MOVEI	P1,INCHWL
	AOS	(P)
	LDB	T1,PUUOAC##	;WHERE TO PUT ANSWER
	HRR	M,T1
	PUSHJ	P,TOPDDB
	  SETZB	F,S		;NO DDB, NO I/O STATUS
	PUSHJ	P,TYIEAT	;EAT ANY LEFT-OVER COMMAND
	PJUMPN	F,(P1)		;INPUT AND BLOCK IF A DDB AVAILABLE
	PUSHJ	P,TYI		;NO DDB, CAN'T BLOCK, GET CHAR
	  MOVEI	T3,0		;NONE THERE--RETURN NULL
	MOVE	T1,T3		;COPY CHAR
	JRST	STOTAC##	;STORE FOR USER

;INPUT IMAGE CHAR

TOPIIC==RTZER##

;DO A RESCAN

TOPRES:	PUSHJ	P,TRESCU	;DO IT
	  JRST	CPOPJ1##	;WIN
	JRST	CPOPJ1##	;WIN
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. I/O SUBROUTINES

;GET A DDB FOR TRMOP. I/O

TOPDDB:	SETZ	S,		;IN CASE NO I/O STATUS AVAILABLE
	HRRZ	F,LDBDDB(U)	;GET DDB POINTER
	JUMPN	F,TOPDD2	;FIND A DDB?
	HRLZ	T2,LDBDCH(U)	;NO, GET THE LINE STATUS
	JUMPGE	T2,TOPDD2	;IS IT A PTY?
	LDB	T1,LDPLNO	;YES, GET THE TTY NUMBER
	HRRZ	F,PTYTAB##-PTYOFS##(T1)	;GET DDB ADDRESS, IF ANY
TOPDD2:	JUMPE	F,TOPDD1	;ANY DDB THERE?
	MOVE	S,DEVIOS(F)	;AH - A DDB, GET I/O STATUS
	LDB	T1,PJOBN##	;YES--IS IT MINE?
	CAMN	T1,.CPJOB##	; ..
	AOSA	(P)		;YES--USE IT
	SETZ	S,		;NO, THEN NO I/O STATUS AFTER ALL
	POPJ	P,		;RETURN AS APPROPRIATE

TOPDD1:	PUSHJ	P,TTYNAM	;GET SIXBIT NAME
	MOVE	T1,T2		;PUT IN T1
	PUSHJ	P,GETDDJ	;GET A DDB
	  POPJ	P,		;NONE LEFT
	MOVEI	T1,ASSPRG	;INIT THE DDB SO
	IORM	T1,DEVMOD(F)	; IT WILL STICK
	MOVE	T1,.CPJCH##	; AROUND AND WE
	DPB	T1,PJCHN##	; CAN WAKE OWNER
	MOVE	S,DEVIOS(F)	;LOAD UP I/O STATUS WORD
	AOS	(P)		;SKIP RETURN (CALL?)
	PUSHJ	P,@0(P)		;CALL OUR CALLER
	  JRST	.+2		;NON-SKIP
	AOS	-1(P)		;SKIP
	PUSHJ	P,TTYREL	;KILL OFF DDB
	JRST	TPOPJ##		;AND RETURN
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. DATASET FUNCTIONS

;MORE SUBROUTINES FOR TRMOP

TOPDSE:	MOVE	T1,LDBDCH(U)	;GET DEVICE CHARACTERISTICS
IFN FTNET,<
	SKIPGE	LDBTTW(U)	;ANF NETWORK TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	PJRST	NETDSE		;YES, LET NETSER DO IT
>
	TRNN	T1,LDRDSD	;IS IT A DATASET?
	JRST	TOPX4		;NO. ERROR CODE 4
	LDB	U,LDPDSC	;GET THE TABLE OFFSET INTO U
	MOVSI	T1,DSCIC2	;CLEAR FAILURE, DIALLER FLAGS AND TIMER
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCSWC	;SET TO ALLOW HIM ON
	PUSHJ	P,DSRRN1	;SEND TO MODEM HANDLER
	JRST	CPOPJ1##	;AND SKIP RETURN



TOPDSF::MOVE	T1,LDBDCH(U)	;GET DEV CHARACTERISTICS
IFN FTNET,<
	SKIPGE	LDBTTW(U)	;ANF NETWORK TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	PJRST	NETDSF		;YES, LET NETSER DO IT
>
	TRNN	T1,LDRDSD	;IS IT A MODEM
	JRST	TOPX4		;NO. CAN'T DO THIS.
	PUSHJ	P,LDBCLR	;CLEAR OUT LDB
	HRRZ	F,LDBDDB(U)	;DDB?
	JUMPE	F,TOPDF1	;NOT CONTROLLING JOB
	MOVE	T1,DEVMOD(F)
	TLNN	T1,TTYATC	;CONTROLLING TTY?
	JRST	TOPDF1		;NOPE
	PUSHJ	P,DSCDET	;DETACH IT
TOPDF1:	PUSH	P,U		;SAVE U
	LDB	U,LDPDSC	;GET TABLE INDEX
	MOVSI	T1,DSCHWC	;CLEAR
	ANDCAM	T1,DSCTAB##(U)
	PUSHJ	P,DSROF1	;HANG IT UP
	JRST	UPOPJ1##	;AND SKIP RETURN
TOPDSS:	MOVE	T1,LDBDCH(U)	;CHARACTERISTICS
IFN FTNET,<
	SKIPGE	LDBTTW(U)	;ANF NETWORK TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	JRST	NETDSS		;YES, LET NETSER DO IT
>
	TRNN	T1,LDRDSD	;DATASET?
	JRST	TOPX4		;NO, LOSE
	LDB	U,LDPDSC	;DSCTAB OFFSET
	SKIPL	DSCTAB##(U)	;HARDWARE CARRIER?
	TDZA	T1,T1		;NO
	MOVSI	T1,DSCHWC	;YES
	JRST	STOTC1##	;STORE ANSWER FOR USER



IFN FTNET,<
	;CODE TO CONTROL REMOTE DATASET LINES
NETDSS:	MOVEI	T3,DSTSTS	;STATUS
	JRST	NETISR		;CALL NETSER
NETDSE:	MOVEI	T3,DSTON	;SET DATASET ON
	JRST	NETISR		;CALL NETSER
NETDSF:	MOVEI	T3,DSTOFF	;SET DATASET OFF
	JRST	NETISR		;CALL NETSER
NETDSC:	MOVEI	T3,DSTCRQ	;DIALER REQUEST
NETISR:	MOVEI	T1,ISRDSC	;DATASET CONTROL FUNCTION
	PJRST	D85DSC##	;CALL NETSER DIRECTLY SINCE NO DATASET TIMING
>
TOPDSC:	MOVE	T1,LDBDCH(U)	;DEVICE CHARACTERISTICS
IFN FTNET,<
	SKIPGE	LDBTTW(U)	;ANF NETWORK TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	JRST	NETDSC		;YES, LET NETSER DO IT
>
	TRNN	T1,LDRDSD	;DATASET?
	JRST	TOPX4		;NO. CAN'T DIAL THEN.
IFN FTMP,<
	PUSHJ	P,ONCPUL##	;MUST BE ON DEVICES OWN CPU
>
	LDB	U,LDPDSC	;GET DSCTAB INDEX
	MOVE	T1,DSCTAB##(U)	;AND BITS
	TLNE	T1,DSCHWC!DSCSWC	;ALREADY IN USE?
	JRST	TOPX5		;YES. CAN'T DIAL ON IT.
TOPDC1:	HRRZ	T1,DSCTAB##(U)	;GET TERMINAL NUMBER FOR MODEM
	CAME	T1,DSDUNI##	;BUSY FOR SAME UNIT, OR
	AOSN	TTYDDL##	;DIALLER FREE?
	JRST	TOPDC2		;YES
	MOVEI	T1,5		;NO. WAIT FOR IT.
	S0PSHJ	SLEEP##		; ..
	JRST	TOPDC1		;TRY AGAIN
TOPDC2:	MOVEM	T1,DSDUNI##	;SAVE LINE BEING DIALLED
	PUSHJ	P,GETWRD##	;FROM USER CORE
	  JRST	TOPX3		;ADDRESS CHECK
	MOVEM	T1,DSCNUM	;STORE FOR DIALLER CODE
	PUSHJ	P,GETWR1##	;AND SECOND WORD
	  JRST TOPX1		;ADDRESS CHECK
	TRO	T1,17		;GUARANTEE AN END OF NUMBER CODE
	MOVEM	T1,DSCNUM+1	;STORE SECOND WORD
	MOVSI	T1,DSCIC2	;CLEAR OUT THESE BITS
	ANDCAM	T1,DSCTAB##(U)	;IN CONTROL TABLE
	MOVSI	T1,DSCSWC!DSCDLW!^D30
	IORM	T1,DSCTAB##(U)	;AND SET UP TO WAIT FOR DIALLER
	MOVE	T1,[POINT 4,DSCNUM]
	MOVEM	T1,TTYDDA##	;STORE INITIAL POINTER TO NUMBER
	MOVEI	T3,DSTCRQ	;CALL REQUEST CODE
	PUSHJ	P,DSCCAL	;TO THE DEVICE HANDLER
TOPDC3:	MOVEI	T1,^D15		;SLEEP FOR FIFTEEN SECONDS
	S0PSHJ	SLEEP##		; ..
	MOVE	T1,DSCTAB##(U)	;SEE WHAT HAPPENED.
	TLNE	T1,DSCDLF	;FAIL?
	JRST	TOPX5		;YES.
	TLNE	T1,DSCDLC	;COMPLETED OK?
	JRST	CPOPJ1##	;YES. SKIP RETURN TO USER
	JRST	TOPDC3		;NEITHER YET. LOOP.
	SUBTTL	TTCALL AND TRMOP. -- AUTOBAUD DETECT, NETWORK DISCONNECT

TOPABR:	MOVEI	T3,<LPCABR>B27!1 ;SET UP FUNCTION AND ENABLE BIT
	MOVEI	T1,ISRLPC	;FUNCTION CODE
	SKIPGE	LDBISB(U)	;SKIP IF NOT DC76
	PUSHJ	P,@LDBISR(U)	;CALL SERVICE ROUTINE
	JRST	CPOPJ1##	;GIVE GOOD RETURN



;HERE FOR A DISCONNECT NETWORK TERMINAL REQUEST

TOPDNT::
IFE FTNET,<JRST TOPX11>		;NEED NETWORKS
IFN FTNET,<
	MOVEI	T1,ISRREM	;REMOTE HANDLER FUNCTION
	MOVEI	T3,IRRDSC	;DISCONNECT CODE
	PUSHJ	P,@LDBISR(U)	;TRY TO DISCONNECT IN CANONICAL FASHION
	 JRST	TOPX11		;POOR CHOICE FOR GENERIC ERROR RETURN
	JRST	CPOPJ1##	;PROPAGATE SUCCESS
>
	SUBTTL	TTCALL AND TRMOP. -- SET/READ BREAK FIELD WIDTH/BREAK MASKS

TOPSBS:	PUSHJ	P,CHKABS	;MUST BE IN BREAK MASK MODE
	  JRST	TOPX7		;VERY CONFUSED
	PUSHJ	P,SAVE3##	;SAVE SOME ACS
	HLRZ	P1,P4		;GET LENGTH OF USER'S ORIGINAL ARGUMENT
	SUBI	P1,2		;ACCOUNT FOR FUNCTION/UDX
	JUMPLE	P1,CPOPJ1##	;SKIPPING NOOP IF NO MORE ARGUMENTS
	PUSHJ	P,GETWRD##	;GET BREAK FIELD WIDTH
	  JRST	TOPX3		;ADDRESS CHECK
	CAIL	T1,^D1		;RANGE CHECK ARGUMENT
	CAILE	T1,^D255	;MUST BE IN THE RANGE 1-255
	JRST	TOPX2		;ARGUMENT OUT OF RANGE
	DPB	T1,LDPFWD	;STORE FIELD WIDTH
	SOJLE	P1,CPOPJ1##	;SKIP RETURN IF ONLY CHANGING FIELD WIDTH
	MOVEI	P2,10		;MAX. LENGTH OF USER TABLE
	MOVE	P3,[POINT CC.WID,LDBCSB(U)] ;POINTER TO STATUS BYTES
TOPSB2:	MOVEI	T1,0		;STORE A ZERO IF USER DOESN'T SPECIFY
	MOVEI	T2,^D32		;NUMBER OF CHARACTERS DESCRIBED PER WORD
	SOJL	P1,TOPSB3	;GO IF EXHAUSTED USER ARGUMENT LENGTH
	PUSHJ	P,GETWR1##	;GET NEXT WORD OF BREAK MASK
	  JRST	TOPX3		;ADDRESS CHECK
TOPSB3:	ILDB	T3,P3		;GET STATUS BYTE
	SKIPL	T1		;DO WE WANT THIS ONE TO BREAK?
	TRZA	T3,CC.BRK!CC.NSA;NO, DON'T LET IT
	TRO	T3,CC.BRK!CC.NSA;YES, LIGHT THE BITS
	CAMN	P3,[POINT CC.WID,LDBCSB(U),CC.WID*4-1] ;IS THIS ^C?
	JRST	[TRO	T3,CC.BRK	;YES, IT'S A BREAK
		 TRZ	T3,CC.NSA	;AND GETS ITS SPECIAL ACTION
		 JRST	.+1]	;RE-JOIN MAIN LINE
	DPB	T3,P3		;STORE IT BACK
	LSH	T1,1		;POSITION FOR NEXT CHARACTER
	SOJG	T2,TOPSB3	;NEXT BIT IN USER'S WORD
	SOJG	P2,TOPSB2	;GET NEXT WORD OF MASK FROM USER
	AOS	(P)		;TELL HIM HE DID GOOD
	PJRST	CHKBKC		;SET LDBBKC CORRECTLY
TOPRBS:	PUSHJ	P,CHKABS	;INSURE IN BREAK SET MODE
	  JRST	TOPX7		;NOT, ALLOWING CONTINUATION COULD BE A DISTASTER
	PUSHJ	P,SAVE3##	;SAVE SOME WORKING ACS
	HLRZ	P1,P4		;LENGTH OF ARGUMENT
	SUBI	P1,2		;ACCOUNT FOR FUNCTION/UDX
	JUMPLE	P1,CPOPJ1##	;RETURN IF NO ROOM TO STORE ANYTHING
	LDB	T1,LDPFWD	;GET FIELD WIDTH
	SKIPN	T1		;IS THERE ONE?
	MOVEI	T1,1		;NO, FIELD WIDTH IS 1 (BKA)
	PUSHJ	P,PUTWRD##	;STORE FIELD WIDTH FOR THE USER
	  JRST	TOPX3		;ADDRESS CHECK
	SOJLE	P1,CPOPJ1##	;RETURN IF THAT'S ALL HE WANTED
	MOVEI	P4,10		;LENGTH OF THE TABLE
	MOVE	P3,[POINT CC.WID,LDBCSB(U)] ;POINTER TO MONITOR'S TABLE
TOPRB1:	MOVSI	T2,(1B0)	;BEGINNING BIT (PER WORD) FOR CHARACTER
	SETZ	T1,		;FOR ACCUMULATING THE MASK
	MOVEI	T3,^D32		;NUMBER OF CHARACTERS PER WORD OF MASK
TOPRB2:	ILDB	T4,P3		;GET CHARACTER'S STATUS BYTE
	TRNE	T4,CC.BRK	;IS IT A BREAK?
	TDO	T1,T2		;YES, LIGHT ITS BIT
	LSH	T2,-1		;POSITION BIT FOR NEXT CHARACTER
	SOJG	T3,TOPRB2	;LOOP FOR ENTIRE WORD
	PUSHJ	P,PUTWR1##	;STORE THIS ENTRY FOR THE USER
	  JRST	TOPX3		;ADDRESS CHECK
	SOJLE	P1,CPOPJ1##	;GO IF THAT'S ALL THE USER WANTS TO SEE
	SOJG	P2,TOPRB1	;LOOP IF THE ENTIRE TABLE HASN'T BEEN SCANNED
	JRST	CPOPJ1##	;AND GOOD RETURN

;SUBROUTINE TO SEE IF A DDB IS IN BREAK SET MODE - CPOPJ IF NOT, CPOPJ1 IF SO

CHKABS:	MOVE	T1,DEVIOS(F)	;GET DEVICE STATUS
	TRNE	T1,IOSABS	;IN BREAK SET MODE?
	AOS	(P)		;YES, SKIP RETURN
	POPJ	P,		;RETURN
	SUBTTL	TTCALL AND TRMOP. -- SET/READ SPECIAL CHARACTER STATUS

TOPGCS:	PUSHJ	P,TOPCSS	;SET UP TO LOOP OVER THE ARG BLOCK
	  POPJ	P,		;PROPAGATE ERRORS
TOPGC1:	PUSHJ	P,GETWR1##	;GET NEXT CHARACTER REQUESTED
	  JRST	TOPX3		;ADDRESS CHECK
	ANDI	T1,CK.CHR	;IGNORE LEFT-OVER CRUFT FROM PREVIOUS TIMES
	PUSHJ	P,TOPGCB	;GET THE CORRESPONDING BITS IN T2
	DPB	T2,[POINT 36-8,T1,35-8]	;MERGE INTO ANSWER
	PUSHJ	P,PUTWRD##	;STORE THE ANSWER BACK
	  JRST	TOPX3		;ADDRESS CHECK
	SOJG	P1,TOPGC1	;LOOP OVER ENTIRE LIST
	JRST	CPOPJ1##	;RETURN GOODNESS

TOPGCB::MOVE	T2,T1		;COPY THE CHARACTER
	ADJBP	T2,[POINT CC.WID,LDBCSB(U),CC.WID-1] ;FORM POINTER TO ITS BYTE
	LDB	T2,T2		;FETCH THE BYTE
	TRNE	T1,CK.CH7^!37	;IS IT A CONTROL CHARACTER?
	POPJ	P,		;NO, RETURN THE REQUESTED BITS
	PUSH	P,T1		;YES, SAVE ORIGINAL CHARACTER
	PUSH	P,T2		;SAVE BITS SO FAR
	TRNN	T1,CK.PAR	;IS IT 7-BIT?
	SKIPA	T2,LDBCC1(U)	;YES, USE LOW-ORDER 'CLEAR' MASK
	MOVE	T2,LDBCC2(U)	;NO, USE 8-BIT MASK
	ANDI	T1,CK.CH7	;ISOLATE CONTROL PORTION OF CHARACTER
	MOVE	T1,BITTBL##(T1)	;GET THE CORRESPONDING BIT
	TDNN	T1,T2		;IS IT A 'CLEAR' OOB CHARACTER?
	JRST	TTPOPJ##	;NO, JUST RETURN THE MASK FROM ABOVE
	POP	P,T2		;YES, RESTORE MASK
	TRO	T2,CC.CLR	;FLAG THE SPECIAL STATE
	JRST	TPOPJ##		;RESTORE ORIGINAL CHARACTER AND RETURN
CC.INV==<<1_^D14>-1>^!CC.MSK	;MASK FOR INVALID SELECT BITS

TOPSCS:	PUSHJ	P,TOPCSS	;SET UP FOR PROCESSING CHARACTER STATUS BLOCK
	  POPJ	P,		;PROPAGATE ERROR
	SETZ	P3,		;CLEAR FLAGS FOR STATUS MESSAGES
	PUSHJ	P,TOPSC1	;PERFORM THE LOOP
	  SOS	(P)		;CANCEL THE COMING SKIP RETURN
	TRNE	P3,1		;DID WE CHANGE THE BREAK MASK?
	PUSHJ	P,CHKBKC	;YES, EXAMINE THE SIDE-EFFECTS
	TLNN	P3,1		;DID WE CHANGE ANYTHING ELSE?
	JRST	CPOPJ1##	;NO, JUST RETURN TO USER
	AOS	(P)		;WE'LL RETURN SUCCESS
SETOBC:	MOVEI	T3,IRROOB	;YES, GET OUT-OF-BAND CHANGE CODE
	MOVEI	T1,ISRREM	;FOR REMOTE HANDLERS
	PUSHJ	P,@LDBISR(U)	;ATTEMPT TO NOTIFY THEM
	  PJRST	SETCHP		;IT DIDN'T UNDERSTAND, USE GENERAL NOTIFIER
	POPJ	P,		;AND RETURN

TOPSC1:	PUSHJ	P,GETWR1##	;GET NEXT CHARACTER TO SET
	  JRST	TOPX3		;ADDRESS CHECK
	TLNN	T1,(-1B13)	;ANY 'SELECT' BITS ON?
	JRST	TOPSC2		;NO, DON'T BOTHER
	TLNE	T1,(<CC.INV>B13);YES, ARE THEY ALL LEGAL?
	JRST	TOPX2		;NO, GIVE RANGE ERROR
	MOVE	T3,T1		;COPY THE ARGUMENT (TO KEEP IT SAFE)
	ANDI	T1,CK.CHR	;ISOLATE THE AFFECTED CHARACTER
	PUSHJ	P,TOPGCB	;GET THE CHARACTER'S BYTE
	MOVE	T4,T3		;COPY ORIGINAL ARGUMENT AGAIN
	LSH	T4,-8		;RIGHT-JUSTIFY NEW VALUE SECTION
	LSH	T3,^D<14-36>	;AND SELECTOR MASK
	AND	T4,T3		;KEEP ONLY BITS WE CARE ABOUT
	ANDCA	T3,T2		;ISOLATE BITS WE WANT TO KEEP
	IORB	T3,T4		;INCLUDE THE NEW ONES
	CAMN	T2,T3		;ARE WE CHANGING ANYTHING?
	JRST	TOPSC2		;NO, SKIP SOME OVERHEAD
	XOR	T4,T2		;YES, GET MASK OF REAL CHANGES
	TRNE	T1,CK.CH7^!37	;YES, IS IT A CONTROL CHARACTER?
	TRZ	T4,CC.CLR	;NO, CAN'T BE A CLEAR CHARACTER
	JUMPE	T4,TOPSC2	;SKIP AROUND IF NOT CHANGING ANYTHING AFTER ALL
	TRNE	T4,CC.BRK	;CHANGING BREAK STATUS?
	TRO	P3,1		;YES, FLAG FOR EXIT ROUTINE
	TRNE	T4,^-CC.BRK	;CHANGING ANYTHING ELSE?
	TLO	P3,1		;YES, FLAG THAT TOO
	MOVE	T2,T1		;COPY CHARACTER WE'RE AFFECTING
	ADJBP	T2,[POINT CC.WID,LDBCSB(U),CC.WID-1] ;POINT TO ITS BYTE
	DPB	T3,T2		;STORE THE NEW BITS
	TRNN	T4,CC.CLR	;WANT TO CHANGE 'CLEAR' STATUS?
	JRST	TOPSC2		;NO, SO DON'T
	TRNN	T3,CC.CLR	;WANT IT ON?
	SKIPA	T2,[ANDCAM T1,LDBCC1(U)] ;NO, WE'LL CLEAR IT
	MOVE	T2,[IORM T1,LDBCC1(U)]	;YES, WE'LL LIGHT IT
	TRZE	T1,CK.PAR	;IS IT EIGHT-BIT?
	HRRI	T2,LDBCC2	;YES, AFFECT RIGHT WORD
	MOVE	T1,BITTBL##(T1)	;GET THE CORRESPONDING BIT
	XCT	T2		;TWIDDLE APPROPRIATELY
TOPSC2:	SOJG	P1,TOPSC1	;LOOP OVER ENTIRE ARGUMENT LIST
	JRST	CPOPJ1##	;SUCCESS RETURN


;HERE TO SET UP TO LOOP OVER THE CHARACTER STATUS BLOCK FOR .TOGCS & .TOSCS
;RETURNS NON-SKIP WITH ERROR CODE ALREADY DELIVERED,
;OR SKIP WITH M SETUP FOR GETWR1 & P1 WITH THE BLOCK LENGTH

TOPCSS:	PUSHJ	P,CHKABS	;MUST BE IN BREAK-SET MODE
	  JRST	TOPX7		;NOT, SO CAN'T SET STATUS OF CHARACTERS
	HLRZ	T1,P4		;GET LENGTH AGAIN
	CAIL	T1,3		;DO WE HAVE OUR POINTER?
	PUSHJ	P,GETWRD##	;YES, FETCH IT
	  JRST	TOPX3		;NO, GIVE ADDRESS CHECK
	HLRZ	T2,T1		;ISOLATE LENGTH
	CAILE	T2,0		;IS IT IN RANGE
	CAILE	T2,CK.CHR+1	;OF REASONABLE VALUES?
	JRST	TOPX2		;NO, GIVE RANGE ERROR
	HRLI	T1,(IFIW)	;USE SECTION-LOCAL ADDRESSING
	PUSHJ	P,ARNGE##	;SEE IF IT LOOKS LIKELY
	  JRST	TOPX3		;ADDRESS CHECK
	  JFCL			;IGNORE ILLEGAL FOR I/O HERE
	HRRI	M,-1(T1)	;POINT TO TABLE (OFFSET FOR GETWR1)
	MOVE	P1,T2		;COPY THE LENGTH
	JRST	CPOPJ1##	;RETURN SUCCESS

CLRCSB:	SETZM	LDBBKB(U)	;NO BREAK MASK STATUS
	SETZM	LDBCSB(U)	;STORE A ZERO IN SPECIAL STATUS AREA
IFN FTXMON,<
	MOVEI	T1,LDBCSL+2-1	;NUMBER OF WORDS TO ZERO
	XMOVEI	T2,LDBCSB(U)	;SOURCE
	XMOVEI	T3,LDBCSB+1(U)	;DESTINATION
	EXTEND	T1,[XBLT]	;ZERO THE STATUS BYTES
>
IFE FTXMON,<
	MOVSI	T1,LDBCSB(U)	;SOURCE
	HRRI	T1,LDBCSB+1(U)	;DESTINATION
	BLT	T1,LDBCC2(U)	;CLEAR OUT THE STATUS BYTES
>
	SCNOFF			;FOR CHUNK HANDLING
	MOVSI	T1,LMLSSE	;SWITCH SEQUENCE ENABLED BIT
	ANDCAM	T1,LDBCHM(U)	;NOT IF YOU CAN'T TAKE THE PSI
	DPB	T1,LDPSWI	;AND CLEAR THE CHARACTERS
	PUSHJ	P,TYBVRG	;MAKE A VIRGIN OOB STREAM
	JRST	SONPPJ		;RETURN, ALLOWING OTHERS AGAIN
	SUBTTL	TTCALL AND TRMOP. -- UNREAD FUNCTION

TOPUNR:	AOS	(P)		;WE WILL SUCCEED
SETUNR:	MOVSI	T2,L1LUNR	;UNREAD IN PROGRESS BIT
	IORM	T2,LDBBYT(U)	;SET IT
	MOVEI	T2,L1RDEL!L1RDEC ;DEFERRED ECHO ALLOWED BITS
	ANDCAM	T2,LDBBYT(U)	;CLEAR
	PJRST	RCVWKQ		;RETURN TRYING TO FORCE A WAKEUP

CLRUNR:	PUSH	P,T1		;SAVE SOME ACS
	PUSH	P,T2		;THAT GET USED
	MOVSI	T1,L1LUNR	;UNREAD BIT
	ANDCAM	T1,LDBBYT(U)	;CLEAR IT
	PUSHJ	P,TOPOKE	;MAKE SURE ECHOING CAN BE RESTARTED IF DESIRED
	JRST	TTPOPJ##	;RESTORE ACS & RETURN
	SUBTTL	TTCALL AND TRMOP. -- TYPE INTO TTY ON BEHALF OF A USER

;	TOPMTY	TYPE A STRING ON BEHALF OF USER

;ADDR:	LINE NO.
;	[ASCIZ/STRING/]

TOPMTY:	PUSHJ	P,SAVE4##	;SAVE AN AC
	LDB	P1,LDPLNO	;LINE NUMBER
	PUSHJ	P,GETWRD##	;GET ADDRESS OF STRING
	  JRST	TOPX3		;ADDRESS CHECK
	HRRI	M,-1(T1)	;AND PUT IT IN M FOR FUTURE GETWD1'S
	HRROS	T1		;LEFT JUSTIFIED ASCIZ STRING
	PUSHJ	P,CKSTRL##	;MAKE SURE ITS IN CORE AND LEGAL
	  JRST	TOPX3		;ADDRESS CHECK
	CAIL	T2,TTIMAX##	;WILL IT EVER FIT?
	JRST	TOPX2		;NO, GIVE RANGE ERROR
	JUMPE	T2,CPOPJ1##	;SUCCEED VACUOUSLY IF NO CHARACTERS TO TYPE
	MOVE	P4,T2		;SAVE STRING LENGTH
	AOS	(P)		;GIVE GOOD RETURN
	MOVEI	T4,10000	;MAXIMUM LOOP COUNT IF TOO FEW CHUNKS
	MOVEI	T1,L1RMIF	;THE MIC INTERLOCK FLAG
TOPMT0:	SCNOFF			;GET THE GLOBAL INTERLOCK
	TDNE	T1,LDBBYT(U)	;IS THE INTERLOCK AVAILABLE?
	JRST	TOPMT3		;NO, WAIT FOR IT
	MOVE	T2,LDBTIC(U)	;YES, GET INPUT COUNT
	ADD	T2,LDBECC(U)	;AND ECHO COUNT
	ADD	T2,P4		;PLUS OUR STRING COUNT
	CAIL	T2,TTIMAX##	;CAN WE DO IT?
	SOJG	T4,TOPMT3	;NO, WAIT A WHILE
	IDIVI	T2,CK.CPC##	;YES SO FAR, BUT SEE HOW MANY CHUNKS WE NEED
	CAML	T2,TTFREN##	;DO WE HAVE THEM AVAILABLE?
	SOJG	T4,TOPMT3	;NO, WAIT A WHILE
	IORM	T1,LDBBYT(U)	;YES, GET THE INPUT INTERLOCK
	SCNON			;AND ALLOW OTHERS AGAIN

TOPMT1:	MOVE	P3,[POINT 7,P2]	;SET UP BYTE POINTER
	PUSHJ	P,GETWD1##	;GET NEXT WORD OF ASCIZ STRING
	MOVE	P2,T1		;AND SAVE IT
TOPMT2:	TLNN	P3,760000	;END OF CURRENT WORD?
	JRST	TOPMT1		;YES - GET NEXT ONE
	ILDB	T3,P3		;GET NEXT CHAR
	JUMPE	T3,TOPMT4	;END OF STRING, WAKE CONTROLLER
	MOVE	U,LINTAB##(P1)	;SET LDB ADDRESS
	PUSHJ	P,RECINM	;TYPE IT
	JRST	TOPMT2		;NEXT CHAR

TOPMT3:	SCNON			;ALLOW OTHERS AGAIN
	PUSHJ	P,SCDCHK##	;SEE IF SCHEDULAR WANTS TO DO ANYTHING
	JRST	TOPMT0		;AND TRY AGAIN

TOPMT4:	PUSHJ	P,RECINU	;RETURN THE MIC INTERLOCK
	JRST	PTSTRT		;START CONTROLLER


;TOPTYP  --  TYPE ONE CHARACTER FOR USER
;CALL WITH CHARACTER IN T3, LDB IN U

MICLOK:	SE1ENT			;MUST BE IN PROPER SECTION
	PUSH	P,T1		;PRESERVE A REGISTER
	MOVEI	T1,L1RMIF	;MIC INTERLOCK BIT
MICLK1:	SCNOFF			;NO INTERRUPTS WHILE SETTING LOCK
	TDNE	T1,LDBBYT(U)	;CHECK INTERLOCK
	JRST	[SCNON		;ALLOW PENDING INTERRUPTS
		 JRST MICLK1]	;TRY AGAIN
	IORM	T1,LDBBYT(U)	;SET THE INTERLOCK BIT
	JRST	SONTPJ		;RESTORE T1, RETURN INTERLOCK AND RETURN

MICULK:	SE1ENT			;RUN IN PROPER SECTION
	PJRST	RECINU		;RETURN 'MIC' INTERLOCK

MICREC:	SE1ENT			;RUN IN PROPER SECTION
	PJRST	RECINM		;RECEIVE A CHARACTER FOR MIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  SET/CLEAR LDBMIC

IFN FTMIC, <
;	MICCLR - CLEAR DOWN LDBMIC
;ADDR:	LINE NO.

;	MICSET - SET UP LDBMIC
;ADDR:	LINE NO.
;	STATUS
;
;	BOTH GIVE OLD CONTENTS OF LDBMIC IN ADDR+1

TOPMCL:	MOVEI	T1,LDRPTY	;A PTY?
	TDNE	T1,LDBDCH(U)
	PUSHJ	P,PTYOW##	;YES, TELL BATCON
	SETZ	T1,		;SET IMPLIED ZERO ARGUMENT
	JRST	TOPMS1		;JOIN MIC SET CODE

TOPMST:	PUSHJ	P,GETWRD##	;GET THE ARGUMENT
	  JRST	TOPX3		;ADDRESS CHECK
	PUSH	P,T1
	ANDI	T1,177		;MASK DOWN TO JOB NUMBER
	CAMLE	T1,HIGHJB##	;ISOLATE JOB NUMBER
	  JRST	[POP P,T1
		 PJRST ECOD2##]	;RETURN ERROR CODE 2 (OUT OF RANGE)
	POP	P,T1
	TLZ	T1,LDLMTI!LDLMMM;CLEAR INTERNAL BITS
TOPMS1:	MOVSI	T2,LOLMIC	;GET THE MIC ACTIVE BIT
	SKIPE	T1		;...
	IORM	T2,LDBOST(U)	; SET OR
	SKIPN	T1		;...
	ANDCAM	T2,LDBOST(U)	; CLEAR AS NEEDED
	EXCH	T1,LDBMIC(U)	;SET NEW VALUE, RETURN OLD
	AOS	(P)		;GOOD RETURN
	PJRST	PUTWDU##	;GIVE USER OLD MIC WORD
;STILL IN IFN FTMIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  RETURN MIC STATUS

;	MICGET - GET STATUS
;ADDR:	LINE
;	RETURN RESULT TO ADDR+1

TOPMGT:	PUSHJ	P,SAVE1##	;SAVE AN AC
	SKIPN	P1,LDBMIC(U)	;IS MIC RUNNING US?
	JRST	TOPMG1		;NO FAIL RETURN
	HRRZ	F,LDBDDB(U)	;SET UP F
	JUMPE	F,TOPMG1	;ZERO MEANS HE LOGGED OUT -LOOSE HIM
	LDB	J,PJOBN##	;OTHERWISE - GET HIS JOB NO
IFN FTMP,<
	CAMN	J,COMJOB##	;ON THE SAME CPU AS US
	PUSHJ	P,ONCPU0##	;NO, GET HIM THERE
>
	PUSHJ	P,UJBSTX##	;GO GET JBTSTS
	TLZ	P1,LDLMMM!LDLMTI!LDLMUI!LDLCL1	;CLEAR VOLATILE BITS
	TLNE	T1,(JB.UML)	;IN MONITOR MODE?
	TLO	P1,LDLCHK!LDLMMM;YES - SET FLAGS
	TLNE	T1,(JB.UDI)	;READY FOR I/P?
	TLO	P1,LDLCHK!LDLMTI;YES - SET FLAGS
	TLNE	T1,(JB.UHI)	;JOB HIBERING FOR INPUT?
	TLO	P1,LDLCHK!LDLMUI;YES - SET FLAGS
IFN FTMLOG,<
	HRRZ	T1,LDBLOC(U)
	SKIPE	T1
	TLO	P1,LDLCHK!LDLCL1;SET TO FLAG
> ;END OF FTMLOG CONDITIONAL
	SKIPGE	LDBCOM(U)	;COMMAND WAITING?
	TLZ	P1,LDLMTI!LDLMUI;YES - CLEAR TI BITS
	MOVE	T1,P1		;PUT LDBMIC INTO T1 FOR
	AOS	(P)		;GOOD RETURN
	PJRST	PUTWDU##	;RETURNING TO USER

TOPMG1:	MOVSI	T1,LOLMIC	;THE CONTROLLED-BY-MIC BIT
	ANDCAM	T1,LDBOST(U)	;CLEAR FOR XMTCHR
	SETZB	T1,LDBMIC(U)	;CLEAR DOWN LDBMIC
	PJRST	PUTWDU##	;AND EXIT
;STILL IN IFN FTMIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  READ ERROR RESPONSE TEXT

;	MICRSP : RECORD ERROR MESSAGE
;ADDR:	LINE NO.
;	ADDRESS OF SPACE TO RETRIEVE RESPONSE

TOPMRS:	SKIPE	T2,LDBMIC(U)	;RUNNING MIC
	TLNN	T2,LDLERC	;ERROR?
	JRST	TOPX4		;NO
	TLNN	T2,LDLRSY	;MAKE SURE GOT TO INT LEVEL WITH SYNC
	JRST	TOPX4		;NO

	PUSHJ	P,GETWRD##	;GET ADDRESS OF RESPONSE BUFFER
	  JRST	TOPX3		;ADDRESS CHECK
	PUSHJ	P,MICADC
	  JRST	TOPX3		;ADDRESS CHECK OF BUFFER
	PUSHJ	P,SAVE3##	;SAVE WORKING ACS
	MOVSI	P1,(<POINT 7,>)
	ADDI	P1,(T1)
	MOVEI	P2,<21*5>-1	;MAX SPACE IN BUFFER
	CAMLE	P2,LDBTOC(U)	;GOT THIS MANY?
	MOVE	P2,LDBTOC(U)	;NO - USE LESSER
	JUMPLE	P2,TOPX4	;NO CHARACTERS
	SKIPN	P3,LDBTOT(U)	;GET CHAR ADDRESS OF ERROR LINE
	JRST	TOPX4		;HASN'T GOT ONE?
	SCNOFF			;PROTECT CHUNK LIST

TOPMR1:	LDCHK	T3,LDBTOT(U),TOPMR3	;GET NEXT CHARACTER
TOPMR2:	EXCTUU	<IDPB T3,P1>
	JUMPE	T3,TOPMR3	;EXIT HAVING MADE ASCIZ
	SOJG	P2,TOPMR1	;GET NEXT CHAR
	SETZ	T3,		;MAKE ASCIZ
	JRST	TOPMR2

TOPMR3:	MOVEM	P3,LDBTOT(U)	;RESTORE POINTER
	SCNON			;THE CHUNKS ARE SAFE ONCE AGAIN
	MOVSI	T1,LDLRSP!LDLRSY;CLEAR RESPONSE FLAG
	ANDCAM	T1,LDBMIC(U)
	AOS	(P)		;GOOD RETURN TO THE USER
	PJRST	TOPOKE		;START UP TERMINAL OUTPUT - GOOD EXIT
;STILL IN IFN FTMIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  LOG ALL TERMINAL OUTPUT

IFN FTMLOG,<

;	MICLOG: RECORD ALL UUO LEVEL OUTPUT
;ADDR:	LINE NUMBER
;	ADDR LOG BUFFER

TOPMLG:	SKIPE	T2,LDBMIC(U)	;RUNNING MIC?
	TLNN	T2,LDLLOG	;WANT LOG FEATURE?
	JRST	TOPX4

	PUSHJ	P,GETWRD##
	  JRST	TOPX3		;ADDRESS CHECK
	PUSHJ	P,MICADC	;ADDRRESS CHECK ALL OF BUFFER
	  JRST	TOPX3		;ADDRESS CHECK
	AOS	(P)		;SET FOR GOOD RETURN TO THE USER
	PUSHJ	P,SAVE2##	;SAVE WORKING ACS
	MOVSI	P1,440700
	HRRI	P1,(T1)
	MOVEI	P2,<21*5>-1

TOPML1:	SCNOFF			;DOWN PI SYSTEM
	SOSGE	LDBLOC(U)	;CHECK COUNT
	JRST	[SETZB T3,LDBLOC(U) ;FIX COUNT
		 JRST TOPML2]	;JOIN PROCESSING
	LDCHKR	T3,LDBLOT(U),TOPML9  ;TAKE A BYTE
TOPML2:	SCNON			;TURN PI'S BACK ON
TOPML3:	EXCTUU	<IDPB T3,P1>
	JUMPE	T3,XMTWAK
	SOJG	P2,TOPML1
	SETZ	T3,
	JRST	TOPML3		;LOOP UNTIL COUNT EXHAUSTED OR END BUFFER

TOPML9:	SETZB	T3,P2		;TERMINATE THE UUO
	JRST	TOPML2		;AND RESTORE THE TERMINAL SERVICE INTERLOCK
> ;END OF FTMLOG CONDITIONAL
;STILL IN IFN FTMIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  MISCELLANEOUS MIC SUBROUTINES

IFN FTMLOG,<

; HERE WITH SCANNER INTERRUPTS DISABLED

MICLGC:	MOVE	T1,LDBMIC(U)	;GET MIC STATUS
	TLNN	T1,LDLLOG	;LOGGING?
	JRST	MICLG1		;NO-MIC HAS GIVEN UP MUST TIDY

	MOVE	T1,LDBTOP(U)	;MOVE TAKER TO PUTTER
	MOVEM	T1,LDBTOT(U)	;SO MIC CAN CATCH UP WITH PUTPUT
	MOVE	T1,LDBTOC(U)	;REMEMBER HOW MANY
	ADDM	T1,LDBLOC(U)	;KEEP TRACK FOR MIC
	JRST	MICLG2
;MIC HAS GONE AWAY MUST TIDY UP LOG BUFFER

MICLG1:	MOVE	T1,LDBLOT(U)	;MOVE PUTTER AND TAKER
	MOVEM	T1,LDBTOT(U)
	MOVEM	T1,LDBTOP(U)	;BACK UP
	SETZM	LDBLOT(U)	;ZAP LOG BUFFER
MICLG2:	SETZM	LDBTOC(U)	;ZAP COUNT
	JRST	SONPPJ		;AND EXIT
> ;END OF FTMLOG CONDITIONAL
;STILL IN IFN FTMIC

;SUBROUTINE TO ADDRESS CHECK A USER BUFFER

MICADC:	PUSH	P,M
	PUSH	P,T1
	HRRI	M,(T1)
	PUSHJ	P,GETWRD##
	  JRST	MICAD1
	HRRI	M,21(M)
	PUSHJ	P,GETWRD##
	TRNA
	AOS	-2(P)
MICAD1:	POP	P,T1
	JRST	MPOPJ##
;STILL FTMIC

;SUBROUTINE TO SET UP HORIZONTAL POSITION FOR MIC AND TO CHECK FOR
;OPERATOR AND ERROR CHARS IN COLUMN 1

MICPOS:	SKIPN	T2,LDBMIC(U)	;MIC RUNNING FOR THIS LINE?
	POPJ	P,		;NO, RETURN IMMEDIATELY
	PUSH	P,T3		;PRESERVE CHAR
	TRNN	T3,CK.IMG	;IF NOT IMAGE,
	TRNN	T3,CK.MET	;UNLESS META-CHARACTER,
	ANDI	T3,CK.CHR	;MASK OFF BITS
	PUSHJ	P,SPCHEK	;GET CHARACTERISTICS OF CHAR
	  JRST	MICPS2		;NOT SPECIAL
	TLNN	T1,CHCRET	;IS IT <CR>?
	JRST	MICPS1		;NOT - MUST CHECK OTHERS
	TLO	T2,LDLCL1	;SET COL 1 FLAG IN MICLDB
	MOVEM	T2,LDBMIC(U)
	JRST	T3POPJ##	;AND RETURN

MICPS1:	CAIE	T3,177		;IS IT A RUBOUT
	CAIN	T3,12		;OR LINE-FEED
	JRST	T3POPJ##	;YES - NO CHECKING
MICPS2:	TLZN	T2,LDLCL1	;ARE WE IN COLUMN 1?
	JRST	T3POPJ##	;NO - RETURN
	LDB	T1,LDP.OP	;GET OPERATOR CHAR
	JUMPE	T1,MICPS4	;JUMP IF NOT SET
	CAMN	T1,T3		;HAVE WE FOUND ONE?
	TLO	T2,LDLCHK!LDLOPC;YES - SET BITS
MICPS4:	LDB	T1,LDP.ER	;GET ERROR CHAR
	JUMPE	T1,MICPS3	;IF NO ERROR
	CAIE	T3,"?"		;"?" ERROR CHARACTER
	CAMN	T1,T3		;ONE OF THOSE?
	TLO	T2,LDLCHK!LDLERC;YES - SET ITS FLAGS
MICPS3:	MOVEM	T2,LDBMIC(U)	;STORE MIC WORD
	JRST	T3POPJ##	;RESTORE T3, AND RETURN
;STILL IN IFN FTMIC
;STILL FTMIC

IFN FTMLOG,<
;A ROUTINE TO FREE THE MIC LOG BUFFER IF REQUIRED

MLOGOF:	SKIPN	LDBLOT(U)	;HAS NOT GOT ONE
	POPJ	P,0
	SCNOFF			;SNEAKY PEEK
	SKIPE	LDBTOC(U)	;OUTPUT BUFFER IDLE
	JRST	SONPPJ		;NO FORGET IT
	JRST	MICLG1		;YES-GO ZAP LOG BUFFER AND TURN ON PI
> ;END OF FTMLOG CONDITIONAL

;ROUTINE TO WAKE MIC UP WHEN CONTROLLED JOB REQUIRES INPUT
MICWAK:	LDB	T1,LDPMJN	;LOAD MASTER JOB NO.
	CAMLE	T1,HIGHJB##	;JOB NUMBER TOO BIG?
	  JRST	MICWA1		;YES JUST RETURN
	MOVE	T2,JBTSTS##(T1)	;CHECK JOB STATUS
	TLNN	T2,JLOG		;LOGGED IN?
	  JRST	MICWA1		;NO JUST RETURN
	PUSH	P,T3		;SAVE CHARACTER
	PUSHJ	P,WAKJOB##	;GO WAKE MIC
	POP	P,T3		;RESTORE CHARACTER
MICWA1:	MOVE	T1,LDBDCH(U)	;RESTORE C(U)
	POPJ	P,		;AND RETURN

MICECH:	TLNN	T1,CHCRET	;IS IT A <CR>?
	POPJ	P,		;NO, RETURN
	PUSH	P,T1		;SAVE T1
	MOVSI	T1,LDLCL1	;YES, SET COL 1 BIT
	IORM	T1,LDBMIC(U)	; IN LDBMIC
	JRST	TPOPJ##		;RETURN

MICCHK:	PUSHJ	P,UUOLVL##	;IS .CPJOB EVEN MEANINGFUL HERE?
	  JRST	CPOPJ1##	;NO, DO THINGS FOR MIC
	PUSH	P,T1		;SAVE A REGISTER
	LDB	T1,LDPMJN	;GET MIC MASTER JOB FOR THIS LDB
	CAMN	T1,.CPJOB##	;IS MIC TYPING THIS?
	SKIPN	LDBMIC(U)	;I MEAN REALLY?
	AOS	-1(P)		;NO, DO THINGS FOR MIC
	JRST	TPOPJ##		;RESTORE & RETURN

MICRIC:	PUSHJ	P,MICCHK	;IS MIC TYPING THIS?
	  POPJ	P,		;YES, IGNORE IT
MICPRC:	CAIN	T3,1		;IS THE CHAR A ^A
	JRST	MICRIA		;YES - GO DEAL WITH ^A
	TLO	T1,LDLCHK!LDLMCC;SAY THAT ^C WAS TYPED
	MOVEM	T1,LDBMIC(U)	;PUT IT BACK
	POPJ	P,		;AND RETURN
;STILL FTMIC

MICRIA:	TLO	T1,LDLCHK!LDLMCA;SAY ^A
	MOVEM	T1,LDBMIC(U)	;PUT IT AWAY!
	TRC	T3,2		;CONVERT CHAR INTO A ^C
	MOVSI	T1,CHBRK!CHCRE!CHCNC
	IORM	T1,-1(P)	;AND SET UP BITS TO LOOK LIKE ^C
	POPJ	P,

PTYMCK:	CAIN	T3,20
	TLO	T2,LDLCHK!LDLMCP
	CAIN	T3,2
	TLO	T2,LDLCHK!LDLMCB
	MOVEM	T2,LDBMIC(U)
	TLNE	T2,LDLMCP
	JRST	RICB3
	JRST	PTYPT1
> ;END IFN FTMIC

;CO-ROUTINE TO SETUP U AND .CPTOA SO THAT THE MONITOR CAN TYPE
; A COMMAND AT ITSELF.  USES LDB CORRESPONDING TO FRCLIN

FRCSET::EXCH	U,(P)		;GET CALLER'S PC, SAVE U
	PUSH	P,.CPTOA##	;SAVE .CPTOA
	PUSH	P,U		;WHERE TO RETURN TO CALLER
	MOVE	U,LINTAB##+FRCLIN## ;LDB
	PUSHJ	P,MICLOK	;GET 'MIC' INTERLOCK FOR FRCLIN
	MOVEI	U,MICREC	;PUT CHARS INTO INPUT
	MOVEM	U,.CPTOA##	; STREAM
	MOVE	U,LINTAB##+FRCLIN## ;LDB
	POP	P,(P)		;ADJUST STACK
	PUSHJ	P,@1(P)		;CALL CALLER AS A SUBROUTINE
	  CAIA			;NON-SKIP
	AOS	-2(P)		;PROPAGATE SKIP
	MOVE	U,LINTAB##+FRCLIN## ;LDB
	PUSHJ	P,MICULK	;RETURN FRCLIN'S 'MIC' INTERLOCK
	POP	P,.CPTOA##	;RESTORE .CPTOA
	JRST	UPOPJ##		;RESTORE U AND RETURN
	SUBTTL	SUBROUTINES FOR I/O

;SUBROUTINE TO READ A CHARACTER AND KEEP THE BREAK COUNT RIGHT
;
;IT IS ASSUMED THAT THE CALLER HAS DONE ANY NECESSARY WAITING. THERE
;ARE TWO UNUSUAL CASES: FIRST, IF THERE ARE NO CHARACTERS IN THE
;BUFFER, TYI WILL NON-SKIP RETURN. IF THE CHARACTER READ IS A
;CONTROL C, AND IF THE TERMINAL IS IN USER MODE, NOT SLAVED, NOT
;IN IMAGE INPUT STATE, AND NOT RUNNING UNDER JACCT, THEN TYI CALLS
;ROUTINES TO PUT CONSOLE AT MONITOR LEVEL, AND GOES BACK INTO I/O
;WAIT UNTIL A POSSIBLE CONTINUE COMMAND.
;
;IT IS THE CALLER'S RESPONSIBILITY TO EAT ANY POSSIBLE COMMAND LEFT
;LYING AROUND (I.E., CALL TYIEAT).
;
;TYICC USES P3! BE WARNED!

TYIS:	PUSHJ	P,SAVE3##	;REALLY SHOULD DO IT
	SETOM	P3		;FLAG DON'T WAIT IF NOTHING THERE
	JRST	TYICC2

TYI:	PUSHJ	P,SAVE3##
	TDZA	P3,P3		;FLAG WAIT ON ^C, CONTINUE
TYICC:	TDZA	P3,P3		;FLAG WAIT ON ^C, CONTINUE SEQUENCE
TYICC2:	SETZB	P1,P2		;INDICATE NO BUFFER
TYICC3:	TRNE	S,IODERR	;HAS HE GOTTEN A ^C?
	POPJ	P,		;YES, FORGET IT
TYICC4:	SCNOFF			;NO RACES
	MOVSI	T1,LDLCRP!LDLDIP	;GET CONTROL-R BITS
	TDNN	T1,LDBDCH(U)	;IN COMPETITION WITH COMCON?
	JRST	TYICC5		;NO, GO READ A CHARACTER
	SCNON			;YES, RELEASE INTERLOCK
	JUMPN	P3,CPOPJ##	;RETURN IF ASYNCH
	SETZ	T1,		;NOT, SO SLEEP
	S0PSHJ	SLEEPF##	;FOR A JIFFY
	JRST	TYICC4		;AND TRY AGAIN
TYICC5:	MOVE	T1,LDBTIT(U)	;GET INPUT TAKER
	CAME	T1,LDBECT(U)	;AVOID TIC STOPCDS
	SOSGE	LDBTIC(U)	;ANY LEFT TO INPUT?
	JRST	TYICCZ		;FIX INPUT COUNT AND RESTORE PI
	LDCHKR	T3,LDBTIT(U),TYICCZ  ;GET CHARACTER
	PUSHJ	P,TPCINP	;FUDGE 2-PART INPUT CHARACTERS
	MOVE	T2,LDBTIT(U)	;INPUT TAKER POINTER
	CAMN	T2,LDBBKU(U)	;TAKEN LAST BREAK?
	SETZM	LDBBKU(U)	;YES, ZAP POINTER TO IT
TYICC6:	SCNON			;ALLOW INTERRUPTS
	PUSH	P,T3		;PRESERVE CHAR.
	SKIPG	LDBTIC(U)	;IS THIS THE LAST CHARACTER IN THE BUFFER
	PUSHJ	P,CHKXON	;YES, GO CHECK IF XON IS NEEDED
	POP	P,T3		;RESTORE CHAR.
	SETZ	T1,		;FOR TTYIN2
	TRNE	T3,CK.NIS	;NON-REAL CHARACTER?
	JRST	[SOS	LDBIIC(U)	;YES, COUNT ANOTHER GONE
		 JRST	TYICC4]	;AND TRY FOR A REAL ONE
	TRNE	T3,CK.IMG	;IMAGE CHARACTER?
	JRST	CPOPJ1##	;YES, DONE HERE
	TRNE	T3,CK.MET	;LEFT-OVER TRASH CHARACTER?
	JRST	TYICC4		;YES, TRY FOR A BETTER ONE

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

	PUSHJ	P,SPCHEK	;SEE WHAT KIND OF CHARACTER IT IS
	  JRST	CPOPJ1##	;NOTHING SPECIAL
	TLNE	T1,CHRIA	;UNLESS CC.NSA,
	JUMPE	T3,TYICC4	;IF NULL, SKIP IT.
	MOVE	T4,LDBDCH(U)	;GET LINE BITS
	TLNE	T1,CHALT	;SOME ALT CHAR?
	TLNE	T4,LDLFCS	;FULL CHR SET?
	CAIA			;NO CONVERSION
	PUSHJ	P,RIALTO	;CONVERT
	TLNE	T1,CHBRK	;BREAK CHARACTER?
	SOS	LDBBKC(U)	;COUNT IT DOWN
	JUMPE	F,CPOPJ1##	;GOOD RETURN IF NO DDB
	TLNN	T1,CHCNC	;CONTROL C CHARACTER?
	JRST	CPOPJ1##	;NO JUST RETURN TO CALLER
	MOVE	T4,DEVMOD(F)	;GET SOME BITS
	TLNN	T4,TTYATC	;IS TTY CONTROLLING A JOB?
	JRST	CPOPJ1##	;NO, RETURN CHAR
	PUSHJ	P,CNCCHK	;SEE IF IT IS A CONTROL C
	  JFCL			;YES, STORE
	  JRST	CPOPJ1##	;YES, BUT IT SHOULD BE STORED.
	MOVE	S,[XWD	IOW,IOACT]
	IORB	S,DEVIOS(F)
	SKIPN	P3		;WAIT?
	PUSHJ	P,TIWAIT	;NOW WAIT IN CASE TYPE CONTINUE
	PUSHJ	P,TYIEAT	;EAT THE CONTINUE COMMAND
	JUMPE	P1,TYICC3	;DONE IF NO PTR
	DMOVE	T1,P1		;SETUP BYTE POINTER AND COUNT SO PRNGE CAN
	PUSHJ	P,PRNGE##	;MAKE SURE BUFFER DIDN'T GO AWAY
	  			; (USER TYPED .CORE <SMALLER-VALUE> AND
				;  ZAPPED THE END OF HIS BUFFER)
	  JRST	UADERR##	;ADDRESS CHECK
	  JRST	UADERR##	;ADDRESS OK BUT ILLEGAL FOR I/O
	JRST	TYICC3		;LOOP AROUND AGAIN.


;HERE WITH THE PI SYSTEM TURNED OFF AFTER INPUT COUNT HAS BEEN
;FOUND EXHAUSTED.  (PROBABLY BY A SOSGE THAT DID NOT SKIP).

TYICCZ:	SETZM	LDBTIC(U)	;FIX CHARACTER COUNT
	SETZM	LDBIIC(U)	; AND INVISIBLE CHARACTER COUNT
	SETZM	LDBBKU(U)	;CLEAR BREAK POSITION
	SETZM	LDBBKC(U)	; AND COUNT, SINCE EMPTY
	PUSHJ	P,INPCHI	;SEE IF LDBTIT AND LDBECT MATCH
	  JRST	TYICC5		;NO, TRY AGAIN
	JRST	SONPPJ		;RESTORE PI AND NON-SKIP RETURN
;SUBROUTINE TO DISCARD A COMMAND FROM INPUT BUFFER IF L2RECS STILL ON

TYIEAT::MOVEI	T1,L2RECS	;GET EAT CHARACTER SYNC BIT
	TDNN	T1,LDBBY2(U)	;STILL WANT COMMAND EATEN?
	POPJ	P,0		;NO. RETURN.
TYIL:	SCNOFF			;NO RACES
	SOSGE	LDBTIC(U)	;ANY CHARACTERS LEFT?
	JRST	TYILZP		;FIX COUNT AND RETURN
	LDCHKR	T3,LDBTIT(U),TYILZP  ;TAKE A CHARACTER
	PUSHJ	P,TPCINP	;MAKE SURE WE GET THE RIGHT BREAK CHARACTERS
	MOVE	T2,LDBTIT(U)
	CAMN	T2,LDBBKU(U)	;TAKEN LAST BREAK?
	SETZM	LDBBKU(U)	;ZAP POINTER
	SCNON			;ALLOW INTERRUPTS
	TRNE	T3,CK.NIS	;IF NOT IN STREAM,
	SOSA	LDBIIC(U)	;COUNT ANOTHER INVISIBLE CHARACTER AND LOOP
	PUSHJ	P,SPCHEK	;GET CHARACTER DESCRIPTORS
	  JRST TYIL		;ORDINARY
	TLNE	T1,CHBRK	;BREAK CHAR?
	SOSA	LDBBKC(U)	;YES. COUNT IT AND QUIT
	JUMPN	T3,TYIL		;NO. LOOP IF STILL SOME TO GO
TYID:	MOVEI	T1,L2RECS	;NOW CLEAR THE BIT
	ANDCAM	T1,LDBBY2(U)	;IN THE DEVICE WORD
	POPJ	P,0

TYILZP:	SETZM	LDBTIC(U)	;FIX COUNT
	SETZM	LDBIIC(U)	;ALSO NO INVISIBLE CHARACTERS LEFT
	PUSHJ	P,INPCHI	;MAKE SURE EVERYTHING MATCHES UP
	  JRST	[SCNON		;DIDN'T, ALLOW INTERRUPTS AGAIN
		 JRST	TYIL]	;AND TRY FOR ONE MORE CHARACTER
	SCNON			;LET WORLD BACK IN
	JRST	TYID		; AND GIVE UP


;ROUTINE TO CHECK THAT INPUT TAKERS MATCH WHEN LDBTIC IS ZERO
;CALL/	MOVE	U,LINE
;	PUSHJ	P,INPCHK
;	  HERE IF DIDN'T MATCH (IE, ANOTHER CHARACTER IS THERE)
;	HERE IF MATCHED UP
;
;CLOBBERS T1

INPCHK:	SCNOFF			;LET NOONE ELSE DO THIS WHILE WE'RE LOOKING
	SKIPG	LDBTIC(U)	;COUNT BACK UP?
INPCH1:	PUSHJ	P,INPCHI	;NO, CHECK
	  JRST	SONPPJ		;AND PROPAGATE
	JRST	SONPJ1		; EITHER RETURN

INPCHI:	SETZM	LDBIIC(U)	;SINCE LDBTIC IS ZERO, THIS SHOULD BE
	SETZM	LDBBKC(U)	;AND THIS
	SETZM	LDBBKU(U)	;AND THIS
	MOVSI	T1,L3LIHD!L3LIPD ;INPUT EXPANSION BITS
	ANDCAM	T1,LDBBY3(U)	;AND THESE
	MOVE	T1,LDBTIT(U)	;GET INPUT TAKER
	CAMN	T1,LDBECT(U)	;SEE IF MATCHES
	JRST	CPOPJ1##	;YES, GIVE GOODNESS RETURN
	MOVSI	T1,L3LEHD!L3LEPD ;GET TPCECH PROGRESS BITS
	TDNE	T1,LDBBY3(U)	;WAS THE POINTER BACKSPACED?
	JRST	CPOPJ1##	;YES, TRUST IT
	SKIPN	TICCNT		;NO, SEE IF FIRST SUCH ERROR
	STOPCD	.+1,DEBUG,TIC,	;++LDBTIC WRONG
	AOS	LDBTIC(U)	;COUNT ANOTHER CHARACTER TO READ
	AOS	TICCNT		;COUNT TIC STOPCD ERRORS
	POPJ	P,		;AND RETURN BADNESS
;HERE ARE THE ROUTINES TO PERFORM VARIOUS "TTY INPUT" FUNCTIONS

CTIGNC::PUSHJ	P,CTICOM	;GET THE NEXT CHARACTER (IN T3)
CTIGLC::PUSHJ	P,CTICOM	;GET THE "LAST CHAR COMCON READ" (IN T3)
CTISLC::PUSHJ	P,CTICOM	;SET THE "LAST CHAR" (FROM T3)
CTIGBP::PUSHJ	P,CTICOM	;GET THE BYTE POINTER BEING USED (IN T1)
CTISBP::PUSHJ	P,CTICOM	;SET THE BYTE POINTER TO USE (FROM T1)

CTICOM:	EXCH	T4,(P)		;SAVE "T4" GET OFFSET
	ANDI	T4,-1		;GET JUST THE ADDRESS
	SUBI	T4,CTIGNC+1	;MAKE IT 0 ORIGINED
	ADD	T4,.CPTIV##	;GET ADDRESS OF TTY INPUT VECTOR TO USE
	SE1XCT	<XCT (T4)>	;CALL EITHER COMCON OR ONCE
	POP	P,T4		;RESTORE T4
	POPJ	P,		;  AND RETURN

;HERE IS THE "NORMAL" TTY INPUT VECTOR
COMTIV::PUSHJ	P,CCTYI		;CCTYI GETS NEXT CHAR
	LDB	T3,LDPLCH	;LAST CHAR IS HERE
	DPB	T3,LDPLCH	; STILL HERE...
	MOVE	T1,LDBCLP(U)	;BYTE POINTER IS HERE
	MOVEM	T1,LDBCLP(U)	; STILL HERE...

;ROUTINE TO "GET NEXT CHAR" FROM NORMAL LINES
CCTYI::	SE1ENT			;ENTER SECTION 1
	SCNOFF			;NO RACES
CCTYI0:	SKIPE	T2,LDBCLP(U)	;ADDRESS THERE TO USE?
	CAMN	T2,LDBTIP(U)	;YES. CAUGHT UP TO PUTTER?
	JRST	CCTYI1		;YES.  RETURN END OF LINE CHARACTER
	LDCHK	T3,LDBCLP(U),CCTYI1  ;LOAD CHARACTER FROM TTCMCA POINTER
	TRNE	T3,CK.NIS	;IF NOT A REAL CHARACTER,
	JRST	CCTYI0		;TRY FOR A REAL ONE
	PUSHJ	P,TPCCOM	;CHECK IF NEED TO TRANSLATE CHARACTER
	TRNE	T3,CK.MET	;IF A SPECIAL FUNCTION,
	JRST	CCTYI1		;RETURN A BREAK
	JRST	SONPPJ		;ALLOW INTERRUPTS AND RETURN

CCTYI1:	MOVSI	T3,L3LCHD!L3LCPD ;COMMAND PROGRESS BITS
	ANDCAM	T3,LDBBY3(U)	;NOT EXPANDING A COMMAND CHARACTER ANY MORE
	MOVSI	T3,L1LQCC	;QUOTE FLAG
	ANDCAM	T3,LDBBYT(U)	;ALSO NOT QUOTING ANY MORE
	MOVEI	T3,12		;RETURN BREAK CHAR
	JRST	SONPPJ
;SUBROUTINE TO SEE IF A CONTROL C SHOULD BE ACTED ON OR STORED.
;NON-SKIP MEANS STORE IT.
;SKIP MEANS JACCT SET
;DOUBLE SKIP MEANS .HALT DONE.

CNCCHK:	PUSH	P,T1		;SAVE T1
	MOVE	T1,LDBDCH(U)	;DEVICE FLAGS
	TLNE	T1,LDLSLV+LDLIMI	;SHOULD ^C BE RETURNED?
	JRST	TPOPJ##		;YES.
	AOS	-1(P)		;ADVANCE RETURN
	HRRZ	F,LDBDDB(U)	;GET LINE'S JOB
	JUMPE	F,CNCCK1	;IF NO DDB ATTACHED, ASSUME SHOULD DO ^C
	LDB	T1,PJOBN##	; ..
	MOVE	T1,JBTSTS##(T1)	;GET JOB STATUS WORD
	TDNE	T1,[XWD JACCT,JS.DEP]	;IS ^C LEGAL? (PRIVILEGED PROG OR
				; DAEMON ERROR PAUSE)
	JRST	TPOPJ##		;NO. GIVE IT TO CUSP

	PUSHJ	P,CNCMOD
CNCCK1:	PUSHJ	P,TTHALT	;FORCE CONTROL C
	JRST	TPOPJ1##	;RESTORE T1, SKIP RETURN

CLRIIQ:	HRRZ	F,LDBDDB(U)	;GET DDB, IF ANY.
	JUMPE	F,CLRIM1	;CLEAR BIT IF NO DDB
	MOVE	S,DEVIOS(F)	;GET STATUS WORD.
	TRNE	S,I		;IF STILL IMAGE, DON'T CLEAR BIT
	POPJ	P,0		;IMAGE. JUST RETURN
CLRIMI:	HRRZ	F,LDBDDB(U)	;GET ATTACHED JOB, IF ANY
	JUMPE	F,CLRIM1	;IF NONE, SKIP PART OF THIS
	MOVSI	S,FRCEND	;ALSO CLEAR FORCED END OF FILE BIT
	ANDCAB	S,DEVIOS(F)
CLRIM1:	MOVSI	T1,LDLIMI	;NO. CLEAR IMAGE BIT AND TIME
	DPB	T1,LDPTIM	; ..
	ANDCAM	T1,LDBDCH(U)	; ..
	PJRST	SETCHP		;TELL THE FRONT END AND RETURN
;ROUTINE TO SCAN THE CHARACTERS ALREADY ECHOED IN THE INPUT STREAM
;AND SET LDBBKC CORRECTLY ACCORDING TO THE NUMBER OF BREAK CHARACTERS FOUND.
;USES T1-T3	AND LDBBKU

CHKBKC:	PUSHJ	P,SAVE2##
	SCNOFF				;DON'T LET THINGS CHANGE
	SETZM	LDBBKC(U)		;START FROM SCRATCH
	SETZM	LDBBKU(U)
	SETZM	LDBBKI(U)
	MOVSI	P1,LOLPIM		;PIM STAUS BIT
	TDNE	P1,LDBOST(U)		;ARE WE IN PACKED IMAGE MODE?
	JRST	SONPPJ			;YES, WE CAN'T CHANGE ANYTHING
	SKIPN	P1,LDBTIC(U)		;ANY CHARACTERS ALREADY ECHOED?
	JRST	CHKBK1			;NOPE
	MOVE	P2,LDBTIT(U)		;GET CURRENT INPUT STREAM
CHKBKL:	LDCHK	T3,LDBTIT(U),CHKBK1	;SCAN NEXT CHARACTER, GIVE UP ON ERROR
	TRNN	T3,CK.NIS		;IF STILL THERE,
	PUSHJ	P,SPCHEK		;SEE IF IT'S SPECIAL
	  JRST	CHKBKE			;CAN'T BE
	TLNN	T1,CHBRK		;BREAK?
	JRST	CHKBKE			;NO
	AOS	LDBBKC(U)		;YES, COUNT IT
	MOVE	T3,LDBTIT(U)		;GET POINTER TO BREAK
	MOVEM	T3,LDBBKU(U)		;STORE IT
CHKBKE:	SOJG	P1,CHKBKL
	MOVEM	P2,LDBTIT(U)		;RESTORE STREAM POINTER
CHKBK1:	SKIPN	P1,LDBECC(U)		;ANY UNECHOED CHARACTERS?
	JRST	CHKBK4			;NO, RETURN
	MOVE	P2,LDBECT(U)		;YES, GET STREAM POINTER
CHKBK2:	LDCHK	T3,LDBECT(U),CHKBK4	;GET NEXT CHARACTER TO EXAMINE
	TRNN	T3,CK.NIS		;IF STILL THERE,
	PUSHJ	P,SPCHEK		;SEE IF IT'S SPECIAL
	  JRST	CHKBK3			;CAN'T BE
	TLNN	T1,CHBRK		;BREAK?
	JRST	CHKBK3			;NO
	MOVE	T3,LDBECT(U)		;GET POINTER TO IT
	MOVEM	T3,LDBBKI(U)		;STORE IT
CHKBK3:	SOJG	P1,CHKBK2		;LOOP OVER ALL SUCH CHARACTERS
	MOVEM	P2,LDBECT(U)		;RESTORE POINTER
CHKBK4:	SCNON				;ALLOW OTHERS AGAIN
	SKIPLE	LDBBKC(U)		;ANY BREAK CHARACTERS READY FOR READS?
	PUSHJ	P,RCVWKQ		;YES, TRY TO WAKE THE JOB
SETBMC:	MOVEI	T3,IRRBMC		;BREAK-MASK-CHANGED CODE
	MOVEI	T1,ISRREM		;OF REMOTE ISR VECTOR ENTRY
	PUSHJ	P,@LDBISR(U)		;TRY TO NOTIFY HANDLER
	  PJRST	SETCHP			;TRY HARDER IF IT DOESN'T UNDERSTAND
	POPJ	P,			;RETURN
;ROUTINE TO PUT TERMINAL INTO MONITOR COMMAND MODE. DON'T CALL THIS
;ROUTINE IF TERMINAL IS A SLAVE, UNLESS YOU WANT SLAVE BIT CLEARED TOO.
;CALL WITH LINE SET.

CNCMOD::SE1ENT			;ENTER SECTION 1
	SKIPG	LDBTOC(U)	;UNLESS OUTPUT IS ACTIVE,
	PUSHJ	P,CLRPCT	;RESET THE "STOP" LINE COUNTER
	PUSHJ	P,STRTDL	;LET ONE DEFERRED LINE ECHO
	MOVEI	T1,L2RECS	;EAT RACE SYNC BIT
	ANDCAM	T1,LDBBY2(U)
	HRRZ	T1,LDBDDB(U)	;DDB ADDRESS
	JUMPE	T1,CNCMO2	;IF NO DDB, DON'T TRY TO TOUCH IT
	MOVSI	T2,LDLBKA	;THE VOLATILE BREAK-ON-ALL-CHARACTERS BIT
	TDNN	T2,LDBDCH(U)	;IN CHARACTER MODE?
	TDZA	T2,T2		;NO
	MOVSI	T2,IOLBKA	;YES, REMEMBER THAT FACT
	IORM	T2,DEVIOS(T1)	;FOR TTYUSR TO FIND LATER
CNCMO2:	MOVSI	T1,L1LUNR	;UNREAD BIT
	ANDCAM	T1,LDBBYT(U)	;CLEAR IT SO COMCON GETS CHARACTERS
	MOVE	T1,[LDLIMI+LDLNEC+LDLDLR+LDLBKA,,LDROSU]
	MOVSI	T2,LDLCNE	;COMMAND-LEVEL NO ECHO
	TDNE	T2,LDBDCH(U)	;IF SET,
	TLZ	T1,LDLNEC	;DON'T CLEAR THIS ONE
	ANDCAM	T1,LDBDCH(U)	;CLEAR ALL THESE BITS
	MOVSI	T1,LOLPIM	;AND THIS ONE
	ANDCAM	T1,LDBOST(U)	;IN STATES WORD
	MOVSI	T1,LDLBKM
	ANDCAM	T1,LDBBKB(U)
	MOVSI	T1,LDLCOM	;AND SET THIS ONE
	IORB	T1,LDBDCH(U)	; ..
	TRNE	T1,LDRPTY	;IS THIS LINE PTY-DRIVEN?
	PUSHJ	P,PTMNMD##	;YES. TELL PTYSER ABOUT IT.
	PUSHJ	P,SETCHP	;BE SURE REMOTES ARE INFORMED
	PUSHJ	P,CHKBKC	;FIX BREAK CHARACTERS AFTER LDLBKM
	PJRST	NOCTRO		;CLEAR ^O AND RETURN


;SUBROUTINE TO SKIP IF TERMINAL IS AT COMMAND LEVEL AND NOT SLAVED
; RETURNS LDBDCH IN T2

COMQ:	MOVE	T2,LDBDCH(U)	;GET LINE STATE
	TLNE	T2,LDLCOM	;AT TOP LEVEL?
	TLNE	T2,LDLSLV	;AND NOT SLAVED?
	POPJ	P,0		;NO. JUST RETURN
	HRRZ	F,LDBDDB(U)	;IS LINE ATTACHED TO A JOB?
	JUMPE	F,CPOPJ1##	;JUMP IF NOT
	PUSH	P,T1		;SAVE AN AC
	MOVE	T1,DEVMOD(F)	;GET DEVICE ASSIGN BITS
	TLNE	T1,TTYATC	;ATTACHED TO JOB?
	JRST	TPOPJ1##	;YES. SKIP RETURN
	LDB	T1,PJOBN##	;IS JOB NUMBER ZERO?
	JUMPE	T1,TPOPJ1##	;IF SO,SKIP RETURN
	JRST	TPOPJ##		;IF NOT ATTACHED, CAN'T DO COMMAND
;ROUTINE TO MAKE THIS TERMINAL VISIBLE TO COMMAND DECODER, IF AT COM LEVEL
;CALL WITH LINE SET UP

COMSET::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  POPJ	P,0		;NO. JUST RETURN
	SKIPG	LDBTOC(U)	;UNLESS OUTPUT IS ACTIVE,
	PUSHJ	P,CLRPCT	;RESET THE "STOP" LINE COUNTER
	MOVSI	T1,LDBCMR	;OK. SET REQUEST BIT
COMST1:	SCNOFF			;CAN'T LOOK AT LDBDDB(U) HERE
COMSTF::SE1ENT			;ENTER SECTION 1
	SKIPL	LDBCOM(U)	;WAS COMMAND REQUEST ON?
	AOS	COMCNT##	;NO. WAKE COMCON
	IORM	T1,LDBCOM(U)	;SET THE BITS IN LDBCOM(U)
	SCNON			;FALL INTO CMDSET

;SUBROUTINE TO SET/CLEAR BIT IN COMMAND MAP

CMDSET::SKIPA	T1,[IORM T3,CMDMAP##(T2)]
CMDCLR::MOVE	T1,[ANDCAM T3,CMDMAP##(T2)]
	SE1ENT			;ENTER SECTION 1
	PUSH	P,T3		;SAVE T3
	SETZM	T3
	LDB	T2,LDPLNO	;GET LINE #
	LSHC	T2,-5		;SET TO WORD ADDRESS
	ROT	T3,5		;BIT WITHIN WORD
	MOVE	T3,BITTBL##(T3)	;GET THE BIT
	XCT	T1		;SET OR CLEAR
	PJRST	T3POPJ##	;RETURN
;HERE TO "GREET" A TERMINAL ON SYSTEM RE/START OR NETWORK CONNECT
;CALL IS:
;
;	PUSHJ	P,TTFGRT
;	RETURN
;
;USES T1


;HERE TO FORCE A GENERAL COMMAND
;CALL IS:
;
;	MOVX	T1,<CMD>
;	PUSHJ	P,TTFORC
;	RETURN
;
;USES T1

TTFRC1:	AOSA	(P)
TTFGRT::MOVEI	T1,TTFCXH	;DO A .HELLO COMMAND
TTFORC::SE1ENT			;ENTER SECTION 1
	DPB	T1,LDPCMX	;STORE FORCED COMMAND INDEX
	MOVSI	T1,LDBCMR+LDBCMF;FORCED COMMAND REQUEST.
	JRST	COMST1		;SET COMMAND COUNT, IF NEEDED
TTFCOM::				;FORCED COMMAND TABLE
PHASE 0
TTFCXC:!SIXBIT /.HALT/			;CONTROL C
TTFCXD::!SIXBIT /.BYE/			;DATAPHONE DISCONNECT
TTFCXH::!SIXBIT /.HELLO/		;DATAPHONE CONNECT
TTFCXR::!SIXBIT /.RESTA/		;SYSTEM RESTART
TTFCXK:!SIXBIT /KJOB/			;FORCED KILL JOB
TTFCXI::!SIXBIT /INITIA/		;INITIALIZING CUSP CALL

TTFCXJ::!SIXBIT /.FCONT/		;FORCED CONTINUE

TTFCXT:!SIXBIT	/.TYPE/			;RETYPE LINE
TTFCXW:!SIXBIT	/USESTA/		;1 LINE SYSTAT

IFN FTNET,<
TTFCXL::!SIXBIT	/.NETLD/		;AUTO DOWN LINE LOAD OF DAS80'S SERIES.
>
TTFCXS:!SIXBIT	/HALT/			;STOP JOB REGARDLESS OF ^C TRAPPING
TTFCXB:!SIXBIT	/.BPT/			;^D BREAKPOINT TRAP

IFN FTPATT,<
TTFCXX:!SIXBIT /CTEST/			;FOR PATCHING
>
DEPHASE
TTFCML==:.-TTFCOM
MTTFCM==:-TTFCML				;MINUS LENGTH OF FORCED COMMAND TABLE
IFG TTFCML -20,<PRINTX ?TOO MANY FORCED COMMANDS!>
	SUBTTL	COMMAND LEVEL ROUTINES

;ROUTINE TO SET UP TO READ A COMMAND FROM ANY REQUESTING LINE
;CALL FROM CLOCK LEVEL:
;	PUSHJ P,TTYCOM
;	  NONE FOUND
;	FOUND ONE	;F, U SET UP. J HAS JOB # IF ANY,
;			;T2 HAS TYPEIN T2
;MUST BE CALLED IN SECTION 1

TTYCOM::MOVE	T1,BITTBL##+<FRCLIN##-<FRCLIN##/^D32>*^D32>
	TDNN	T1,CMDMAP##+<FRCLIN##/^D32>
	SKIPA	T1,LINSAV##
	MOVEI	T1,FRCLIN##	;DO SYSTEM COMMANDS FIRST
	MOVEM	T1,LINSAV##
	CAIL	T1,TTPLEN##	;GREATER THAN HIGHEST LINE #?
TTYCM0:	SETZB	T1,LINSAV##	;YES, START AT LINE 0
	LSH	T1,-5		;SHIFT TO RIGHT PLACE
	HRLI	T1,TTCMPT##(T1)	;FORM AN AOBJN POINTER
TTYCM1:	SKIPE	T2,CMDMAP##(T1)	;GET A WORD OF BITS
TTYCM2:	JFFO	T2,TTYCM3	;FIND FIRST ONE BIT
	AOBJN	T1,TTYCM1	;LOOP TO TOP OF TABLE
	SKIPE	LINSAV##	;LOOKED AT THE ENTIRE TABLE?
	JRST	TTYCM0		;NO, START AT THE BEGINNING
	POPJ	P,0		;GIVE FAIL RETURN
TTYCM3:	MOVEI	T4,(T1)		;COPY WORD #
	LSH	T4,5		;SHIFT TO RIGHT PLACE
	ADDI	T4,(T3)		;ADD IN BIT NUMBER
	CAML	T4,LINSAV##	;SKIP IF LINE IS TOO SMALL
	JRST	TTYCM4		;ELSE FIX # AND PROCESS
	TDZ	T2,BITTBL##(T3)	;CLEAR BIT
	JRST	TTYCM2		;AND TRY NEXT
TTYCM4:	MOVEM	T4,LINSAV##	;SAVE THIS LINE #
	AOS	(P)		;GIVE SKIP RETURN
TTCM4A:	MOVE	U,LINTAB##(T4)	;PICK UP LDB POINTER
TRESCN::SE1ENT			;ENTER SECTION 1
	HRRZ	F,LDBDDB(U)	;GET DDB ADDRESS IF ANY
	JUMPE	F,TRESC1	;JUMP IF NO DDB
	MOVE	T3,DEVMOD(F)
	TLNN	T3,TTYATC
TRESC1:	TDZA	J,J
	LDB	J,PJOBN##
	PUSHJ	P,RSTTMR	;RESET THE ADT
	MOVE	T3,LDBCOM(U)	;KILL OR COMMAND?
	TLNN	T3,LDBCMF!LDBDET;FORCED COMMAND OR CLEANUP REQUIRED?
	TLNN	T3,LDBCMK	;NO, FORCED KJOB?
	JRST	TTYCM7		;NO.
	JRST	TTYCM5		;FORCED KJOB!
;DO FORCED COMMANDS OR CLEANUP 1ST, THEN FORCED KJOBS, THEN TYPED-IN COMMANDS

TTYCM7:	MOVEM	U,.CPCML##	;MUST BE SAVED WHEN TTCMCA IS USED
	SCNOFF
	MOVE	T1,LDBTIT(U)	;GET TYPEIN CHAR ADR
	PUSHJ	P,CTISBP	; AND DEFINE IT AS THE INPUT BYTE POINTER
	SCNON
	HRRI	T3," "		;PRIME THE TYI ROUTINE
	TLNE	T3,LDBCMF	;FORCED COMMAND?
	MOVEI	T3,12		;YES. PREVENT EXTRA ARGUMENTS
	PUSHJ	P,CTISLC	;SAY IT IS LAST CHAR READ
	PUSHJ	P,FNDPDB##	;ADDRESS OF PDB
	  JFCL
	POPJ	P,0

TTYCM5:	MOVEI	T1,TTFCXC	;FORCE HALT 1ST SINCE IF TTKJOB IS CALLED DURING A COMMAND
	SKIPGE	JBTSTS##(J)	;MUST BE A JOB.  IS IT RUNNING
	JRST	TTYCM6		;NO.  JUST KILL IT
	MOVSI	T1,LDBCMK	;CLEAR KILL
	ANDCAM	T1,LDBCOM(U)	;FLAG
	MOVEI	T1,TTFCXK
TTYCM6:	PUSHJ	P,TTFORC	;FORCE COMMAND

;DON'T CALL CMDCLR, OR DELAYED COMMAND WILL NEVER BE SEEN AGAIN

	MOVE	T4,LINSAV##	;FIND LINE
	JRST	TTCM4A		;AGAIN
TTKJOB::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,CNCMOD	;CONSOLE TO COMMAND LEVEL
	MOVSI	T1,LDBCMK	;SET KILL REQUEST
	IORM	T1,LDBCOM(U)	;IN LDB
	HRRZ	F,LDBDDB(U)
	SKIPE	J,F
	LDB	J,PJOBN##
	AOS	COMCNT##	;MAKE COMCON SEE IT
	SKIPL	JBTSTS##(J)	;SKIP IF JOB IS IN RUN STATE
				; THIS DEPENDS UPON:
				; 1. RUN BIT BEING SIGN OF JBTSTS
				; 2. J=0 IF NO JOB
				; 3. JBTSTS+0 = 0
	PJRST	CMDSET


;TTHALT  --  HALT THE JOB ATTACHED TO THE TERMINAL
;
;THIS ROUTINE DOES NOT SET TERMINAL TO COMMAND LEVEL BECAUSE JACCT
;PROGRAMS MAY STILL NEED TO TYPEOUT AND THAT WOULD BLOCK THEM IN TO STATE.

TTHALT:	MOVEI	T1,TTFCXC	;HALT COMMAND INDEX
	PJRST	TTFORC		;FORCE THE ^C
;ROUTINES TO ATTACH TERMINAL TO A JOB

;1) CALL WHEN COMMAND DECODER DECIDES TO CREATE A JOB DUE TO
;A COMMAND BEING TYPED IN. THE LDB WILL ALREADY HAVE BEEN
;SET UP, BUT IT IS NOT YET LINKED TO A DDB
;
;CALL:	MOVE LINE,ADDRESS OF LDB
;	MOVE J,NEW JOB NUMBER
;	PUSHJ P,TTYATI
;	  ERROR RETURN	;ALREADY SOMEONE THERE (DDB POINTS AT HIM), OR
;			;NO MORE FREE DDB'S (DDB CONTAINS 0)
;	OK RETURN	;DDB, DDBLDB, AND LDBDDB SET UP
;
;2) CALL FROM COMMAND DECODER ON AN ATTACH COMMAND.
;
;CALL:	MOVE LINE,ADDRESS OF LDB
;	MOVE J,JOB TO ATTACH TO
;	PUSHJ P,TTYATT
;	  ERROR RETURN	;SOMEONE ALREADY ATTACHED (DDB POINTS TO HIM) OR
;			;NO SUCH DDB (DDB=0)
;	OK RETURN	;DDB, LDBDDB, NEW DDBLDB SET UP. OLD DDBLDB CLEARED


TTYATT::SE1ENT			;ENTER SECTION 1
	PUSH	P,U
	PUSHJ	P,TTYISA	;SEE IF DDB FOR TARGET JOB CAN BE ATTACHED
	  JRST	LPOPJ##		;NO, CAN'T DO IT
IFE FTPI,<JUMPE T1,TTYAT2>	;JUMP IF NO JOB IS ATTACHED TO LINE
IFN FTPI,<JUMPE T1,TTYAT1>	;JUMP IF DETACHED BUT SIGNAL DETACHING
	MOVEM	T1,(P)		;SAVE LDB OF TARGET JOB
	LDB	T1,LDPLNO	;OPERATOR DOING PREEMPTIVE ATTACH
				; GET OPERATOR'S LINE NUMBER
	EXCH	U,0(P)		;GET LDB OF OBJECT JOB
	LDB	T3,LDPLNO	;GET ITS LINE NUMBER TOO
	CAIE	T3,0(T1)	;ARE THEY THE SAME? (OPR ATTACHING
				; TO HIMSELF?)
	PUSHJ	P,PTYDET	;NO. DETACH OBJECT JOB, NOW IN LINE.
				; MUST RESPECT F
				;F NOW POINTS TO JOB BEING
				;PICKED UP BY TERMINAL IN 0(P)
	JRST	TTYAT2		;GO DO THE ATTACH
IFN FTPI,<
TTYAT1:	PUSHJ	P,SIGDET	;SIGNAL DETACHING
	JRST	TTYAT2		;GO DO THE ATTACH
>
TTYATI::SE1ENT			;ENTER SECTION 1
IFN FTMP,<
	PUSHJ	P,INTLVL##	;IF AT UUO LEVEL
	  PUSHJ	P,ONCPU0##	;AVOID RACES WITH COMCON
>
	PUSH	P,U		;SAVE LINE DATA BLOCK ADDRESS
	PUSHJ	P,TTYSRC	;SEE IF THERE'S ALREADY A DDB. SHOULDNT BE.
	  PUSHJ P,DDBSRC	;OK. GET A NEW DDB.
	    JRST LPOPJ##	;ERROR. EITHER TTYSRC WON OR DDBSRC LOST
TTYAT2:	MOVE	U,0(P)		;GET LDB ADDR FROM STACK
	PUSH	P,F		;AND SAVE NEW DDB ADDRESS
	HRRZ	F,LDBDDB(U)	;GET OLD DDB IF ANY
	SKIPE	F		;ANY THERE?
	PUSHJ	P,TTYDT1	;YES. DETACH FROM IT BUT DON'T SET MONITOR CODE
	SKIPN	U		;SKIP IF LDB WAS FOUND
	PUSHJ	P,TTYKLQ	;NO, KILL OFF DDB
	MOVE	F,0(P)		;RESTORE NEW DDB ADDRESS
	MOVE	U,-1(P)		;GET LDB ADDRESS, FOR DS POINTER
	MOVSI	T1,LDBCMF
	TDNE	T1,LDBCOM(U)
	JRST	TTYAT3
	MOVE	T1,LDBDCH(U)	;LOOK AT DATA SET BIT
	SKIPL	LDBTTW(U)	;ANF NETWORK TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	TRNN	T1,LDRDSD	;OR IF NOT A DATA SET
	JRST	TTYAT3		;NO DSCTAB ENTRY
	LDB	U,LDPDSC	;GET DATASET TABLE INDEX
	MOVEI	T1,0		;CLEAR TIME FIELD OF DATASET ENTRY
	DPB	T1,DSTMPL	; ..

TTYAT3:	MOVE	U,-1(P)		;ATTACH LDB FROM STACK TO DDB
	MOVE	T1,[XWD TTYATC,ASSCON]	;SET ATTACHED AND ASSIGNED BITS
	IORM	T1,DEVMOD(F)	;IN THE DEV DATA BLOCK
	HRRM	F,LDBDDB(U)	;SET LINK FROM DDB TO LDB
	MOVEM	U,DDBLDB(F)	;AND LINK FROM LDB TO DDB
	DPB	J,PJCHN##	;STORE JOB NUMBER IN DDB
	HRRZM	F,TTYTAB##(J)	;STORE CONTROLLING DDB BY JOB NUMBER
	PUSHJ	P,SCNNAM	;SET UP PHYSICAL LINE NAME AND PUNIT
IFN FTNET,<PUSHJ P,SETSTA>	;SET CORRECT STATION NUMBER

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;THIS CODE MAKES SURE BATCH BIT STAYS CORRECT

	PUSHJ	P,CTLJBU##	;GET PTY DDB IF ANY
	JUMPL	T1,TTYAT5
	MOVSI	T1,DVDIBP	;GET BATCH PTY BIT
	MOVE	T2,JBTLIM##(J)	;GET JBTLIM
	TDNN	T1,DEVCHR(F)	;IS IT A BATCH PTY?
	JRST	TTYAT4		;NO
	TLON	T2,(JB.LBT)	;YES, MAKE IT A BATCH JOB
	AOS	BATNUM##	;INCREMENT # OF BATCH JOBS
	MOVEM	T2,JBTLIM##(J)	;RESTORE JBTLIM
TTYAT4:

IFN FTPI,<PUSHJ	P,SIGDET>	;SIGNAL ATTACH (SAME AS DETACH)

TTYAT5:	POP	P,F
	MOVSI	T1,(JB.LTL)	;GET DETACH TIME UNIT BIT
	TDNN	T1,JBTLIM##(J)	;SEE IF SET
	JRST	UPOPJ1##	;NO -- LEAVE ALONE
	ANDCAM	T1,JBTLIM##(J)	;YES -- CLEAR IT
	MOVEI	T1,0		;NO TIME UNIT NOW
	DPB	T1,JBYLTM##	;CLEAR
	JRST	UPOPJ1##	;SKIP RETURN TO COMCON.
;SUBROUTINE TO LOOK FOR POSSIBLE LINE ALREADY ATTACHED TO TARGET JOB
;ARGS	U=LINE ATTACH WAS TYPED OR
;	J=JOB NUMBER OF TARGET JOB
;VALUES	T1=ADDR OF LDB ATTACHED TO TARGET JOB OR 0 IF NONE
;NON-SKIP RETURN IF NO DDB FOR TARGET JOB OR DDB FOUND BUT MANY NOT ATTACH
;SKIP RETURN IF DDB FOUND AND MAY ATTACH TO IT

TTYISA::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	PUSH	P,U		;SAVE LINE BLOCK ADR OF GUY TYPING COMMAND
	PUSHJ	P,TTYSRC	;FIND THE DDB CONTROLLING THAT JOB
	  JRST LPOPJ##		;THERE ISN'T ANY. COMCON HAS GOOFED?
	SETZ	T1,
	JUMPE	U,LPOPJ1##	;IF NONE ATTACHED, GO ATTACH.
	EXCH	U,0(P)		;SOMEONE IS ATTACHED. ONLY THE OPERATOR
				;MAY USURP THE EXISTING CONNECTION
	PUSH	P,F		;SAVE NEW DDB
	HRRZ	F,LDBDDB(U)	;DDB OF OLD USER
	SKIPE	T1,F		;IF F=0, MAKE T1 0, SINCE PJOBN IS MEANINGLESS IF F=0
	LDB	T1,PJOBN##	;HIS JOB NUMBER
	LDB	P1,LDPLNO	;GET TERMINAL LINE # IN P1
	SUBI	P1,PTYOFS##	;SUBTRACT OFFSET OF PTY0
	JUMPL	P1,TTYIS1	;SEE IF A PTY
	CAIGE	P1,PTYN##	; ..
	SKIPA	F,PTYTAB##(P1)	;IT IS A PTY, GET DDB
TTYIS1:	TDZA	P1,P1		;NOT A PTY, USE JOB 0
	LDB	P1,PJOBN##	;GET JOB OWNING PTY
	POP	P,F		;RESTORE F
	MOVE	P2,FFAPPN##	;GET [1,2]
	CAME	P2,JBTPPN##(T1)	;IS JOB THAT TYPED COMMAND [1,2]?
	CAMN	P2,JBTPPN##(P1)	;OR COMMAND TYPED BY SON OF OPR?
	JRST	TPOPJ1##	;YES, ATTACH IS LEGAL

	CAME	U,OPRLDB##	;IS THIS THE OPR?
	JRST	TPOPJ##		;NO. DISCARD OBJECT JOB'S LDB FROM
	JRST	TPOPJ1##	;STACK, AND GIVE ERROR RETURN TO COMCON
				;WITH DDB POINTING AT GUY ALREADY ATTACHED
;ROUTINE TO DETACH TERMINAL FROM A JOB.
;CALL:	MOVE F,ADDRESS OF TTY DDB TO BE DETACHED
;	MOVE U,LDB  ADDRESS IF ENTRY AT PTYDTC
;	PUSHJ P,TTYDET
;	ALWAYS RETURN HERE

;CALLED FROM TTYATT AND COMCON (DETACH COMMAND)
;KILLS DDB IF NOT ATTACHED, ASSIGNED, OR INITED
;CLEARS LINKS TO DDB
;RESPECTS DDB


TTYDTC::TDZA	T2,T2		;FLAG TTYDTC ENTRY
TTYDET::MOVEI	T2,1		;SAME FOR TTYDET
	SE1ENT
IFN FTPI,<
	PUSH	P,T2		;SAVE T2
	PUSHJ	P,SIGDET
	POP	P,T2		;RESTORE IT
>
	MOVE	U,DDBLDB(F)	;GET LDB ADDRESS
	LDB	T1,LDPLNO	;GET LINE NUMBER
	CAIN	T1,FRCLIN##	;RUNNING ON FRCLIN?
	JRST	@[IFIW	PTYDTC
		  IFIW	PTYDET](T2)  ;YES, SKIP LOGGED OUT CHECK
	LDB	T1,PJOBN##	;GET JOB NUMBER
	MOVE	T1,JBTSTS##(T1)	;IS HE LOGGED IN?
	TLNE	T1,JLOG		; ..
	JRST	@[IFIW	PTYDTC
		  IFIW	PTYDET](T2) ;YES, DISPATCH TO PTYDET
	LDB	T2,PJOBN##	;GET JOB NUM
	MOVE	T1,LGONAM##	;DON'T CLEAR
	CAMN	T1,JBTNAM##(T2)	;FOR LOGOUT SINCE USER COULD
	JRST	TTKJOB		;THEN GET OUT OVER QUOTA
	MOVSI	T1,JACCT	;CLEAR JACCT
	ANDCAM	T1,JBTSTS##(T2)	;IN STATUS
	JRST	TTKJOB		;GO KILL HIM
PTYDTC::SE1ENT			;ENTER SECTION 1
	LDB	T1,PJOBN##	;GET JOB NUMBER FROM DDB
	MOVSI	T2,CMWB		;AND COMMAND WAIT BIT
IFN FTMP,<CAME T1,COMJOB##>	;CURRENT JOB IN COMCON?
	TDNE	T2,JBTSTS##(T1)	;OR JOB IN COMMAND WAIT?
	JRST	[MOVSI	T1,LDBDET ;TELL COMRET TO CLEAN UP
		 IORM	T1,LDBCOM(U) ;JOB/COMMAND AT COMMAND EXIT
		 PJRST	DETCHK]	;WAIT FOR DETACH AND RETURN
PTYDET::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,TTYDT1	;DISCONNECT DDB FROM LDB
	JUMPE	U,TTYKLQ	;IF NO LDB KILL OFF DDB
	PUSH	P,F		;PRESERVE DDB (LDB LINK GONE AFTER TTYDT1)
	PUSHJ	P,CNCMOD	;MAKE SURE LDB AT TOP LEVEL
	POP	P,F		;RESTORE DDB POINTER
;ROUTINE TO KILL DDB IF IT IS AN IDLE TTY DDB

TTYKLQ::PUSH	P,T1		;RESPECT T1
	MOVE	T1,DEVMOD(F)	;GET DEVICE MODE AND USE BITS
	TLNE	T1,DVTTY	;IS IT A TTY DDB?
	TDNE	T1,[XWD TTYATC,ASSPRG]	;YES, ANY REASON TO KEEP DDB?
	JRST	TPOPJ##		;YES.
	PUSHJ	P,TTYRL3	;ANY OTHER REASON TO KEEP DDB?
	  PUSHJ	P,TTYKIL	;NO. GO KILL THE DDB
	JRST	TPOPJ##		;AND RESTORE T1 ON RETURN
;SUBROUTINE TO DISCONNECT A TERMINAL FROM A JOB WITHOUT SETTING TERMINAL TO MONITOR LEVEL
;THIS IS SO ATTACH UUO WILL LEAVE TERMINAL AT ITS ORIGINAL LEVEL (MONITOR OR USER MODE)

TTYDT1:	MOVE	U,DDBLDB(F)	;GET LINKED LINE ADDRESS
	SETZM	DDBLDB(F)	;DISCONNECT LDB FROM DDB
	JUMPE	U,TTYDTX	;IF NO LDB, KILL OFF DDB
	HLLZS	LDBDDB(U)	;DISCONNECT DDB FROM LDB
	HRRZS	DEVNAM(F)	;CLEAR LH OF DEVNAM TO NOT CONFUSE DEVCHR, ETC.
				;KEEP RH FOR SYSTAT, ETC.
	LDB	T1,PJOBN##	;SEE IF THIS JOB WAITING FOR DAEMON
	MOVSI	T2,(JB.LBT)	;BATCH BIT
	TDNE	T2,JBTLIM##(T1)	;IF WAS BATCH JOB
	SOS	BATNUM##	;DECR. BATCH JOB COUNT
	ANDCAM	T2,JBTLIM##(T1)	;CLEAR BIT SO OPERATOR CAN DETACH

	MOVE	T1,JBTSTS##(T1)	;GET JOB STATUS WORD
	TRNN	T1,JDC		;DCORE COMMAND WAITING?

	PUSHJ	P,TYIEAT	;NO. CLEAR ANY PENDING COMMAND
	MOVE	T1,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TRNE	T1,LDRPTY	;A PTY LINE?
	PUSHJ	P,PTMNMD##	;YES. WAKE CONTROLLER
TTYDTX:	POPJ	P,

IFN FTPI,<
SIGDET:	HRROI	T1,C$DATT	;GET CONDITION TO BE SIGNALLED
	PJRST	PSIJOB##	;NOTIFY EACH JCH IN JOB AND RETURN
>

;ROUTINE TO MAKE SURE A LINE IS DETACHED BEFORE PROCEEDING
;CALL WITH U POINTING AT THE LDB IN QUESTION
DETCHK:	PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##	;SET TO CURRENT JOB
DETCH1:	MOVSI	T1,LDBDET	;WAITING FOR COMMAND
	TDNN	T1,LDBCOM(U)	; TO COMPLETE?
	JRST	JPOPJ##		;NO
	S0PSHJ	SLEEPF##	;YES, WAIT UNTIL ITS DONE
	JRST	DETCH1		;TRY AGAIN
;ROUTINE TO RELEASE A TTY DDB. CALL WITH DDB SET UP.


TTYREL::SE1ENT			;ENTER SECTION 1
	MOVE	T1,[XWD IOW,IOACT]	;CLEAR OUT S
	HRRZS	F		;CLEAR LEFT HALF BITS (OUTPB, INPTB, ETC.)
	ANDM	T1,DEVIOS(F)	; IN CORE
	SKIPE	DINITF##	;IN SYSINI?
	JRST	TTYRL2		;YES--SKIP THIS
	PUSHJ	P,SAVE1##	;SAVE CHANNEL NUMBER
	MOVEI	P1,0		;START AT CHANNEL ZERO
TTYRL0:	S0PSHJ	NXTCH##		;NEXT CHANNEL (MUST BE CALLED IN SECTION 0, LH F BITS)
	  JRST	TTYRL1		;ALL CHANNELS HAVE BEEN LOOKED AT
	SOS	P1		;ADJUST P1
	CAIN	P1,@-1(P)	;CHANNEL BEING RELEASED
	AOJA	P1,TTYRL0	;YES
	CAIE	T1,(F)		;NO SAME DDB OPEN ON ANOTHER CHANNEL?
	AOJA	P1,TTYRL0	;NO
	JRST	TTYRS1		;YES, DON'T MAKE THE DDB GO AWAY
TTYRL1:
TTYRL2:	PUSHJ	P,TTYRL3	;SEE IF SHOULD KEEP DDB AROUND
	  JRST	TTYKIL		;NO. GO DISCARD DDB.
	JRST	TTYRS1		;YES. KEEP DDB AROUND. RETURN.

TTYRL3:	MOVE	T1,DEVMOD(F)	;GET MODE BITS
	TLNE	T1,TTYATC	;IS TTY ATTACHED?
	JRST	CPOPJ1##	;YES, KEEP DDB AROUND. RETURN+2.
	TRNN	T1,ASSCON	;IS IT ASSIGNED?
	POPJ	P,		;NO, DISCARD DDB.  RETURN+1.
	HLRZ	T1,DEVNAM(F)	;GET LH OF PHYSICAL NAME
	CAIE	T1,'TTY'	;STILL AN ACCESSIBLE NAME?
	SKIPE	DEVLOG(F)	;OR HAS A LOGICAL NAME?
	AOS	(P)		;YES TO EITHER.  KEEP DDB.
	POPJ	P,		;NOT REACHABLE. DISCARD.
;ROUTINE TO CLEAR A TTY DDB AND MAKE IT AVAILABLE TO THE POOL
;CALL:	MOVE F,ADDRESS OF DEVICE DATA BLOCK KNOWN TO BE THROUGH USE.
;	PUSHJ P,TTYKIL
;	ALWAYS RETURN HERE
;RESPECTS F & S, CLOBBERS T1


TTYKIL::SE1ENT			;ENTER SECTION 1
	SETZM	DEVLOG(F)	;CLEAR LOGICAL NAME
	MOVSI	T1,IOFST	;INITIAL STATE OF S WORD
	MOVEM	T1,DEVIOS(F)	;PLACE IN CORE STATUS WORD
IFN FTPI,<
	SKIPE	DEVPSI(F)	;USER INTERRUPTING ON THIS
	PUSHJ	P,PSIRMV##	;YES, REMOVE PSI LINKS
>
	PUSH	P,W		;SOME CALLERS EXPECT THIS TO BE PRESERVED
	PUSHJ	P,CLRDVL##	;NO JOB OWNS IT ANY MORE.
	POP	P,W		;RESTORE BLOWN AC
	PUSH	P,U
	MOVE	U,DDBLDB(F)	;GET LINK TO LINE DATA BLOCK
	JUMPE	U,TTYKL1	;BYPASS IF NO LINK.
	PUSHJ	P,TTYSTC	;PUT LINE AT COMMAND LEVEL
	PUSHJ	P,TTYCPT	;CLEAR PAPER TAPE BITS
	MOVE	T1,[LPGCLK]	;CLEAR PAGE BITS
	ANDCAM	T1,LDBPAG(U)	;SO XON AND XOFF ARE ECHOED PROPERLY
	MOVSI	T1,LDLBKA	;CLEAR THE BREAK-ON-ALL BIT
	ANDCAM	T1,LDBDCH(U)	;IN THE DCH WORD
	MOVSI	T1,LOLSSO	;CLEAR THE STOPPED OUTPUT BIT
	ANDCAM	T1,LDBOST(U)	;IN THE STATES WORD
	PUSHJ	P,CLRIM1	;MAKE SURE NOT IN IMAGE MODE
	PUSH	P,S		;IN CASE SOME CALLER SOMEWHERE CARES
	MOVEI	S,0		;CLEAR ALL THOSE BITS IN LDBDCH
	PUSHJ	P,UUOLDB	;CLEAR OUT LDB
	POP	P,S		;THIS IS REALLY SUPERCAUTION
TTYKL1:	MOVSI	T1,DEPRAS	;TEST FOR DDB RESTRICTED
	TDNE	T1,DEVSTA(F)	;IS IT A RESTRICTED TTY?
	JRST	[POP P,U
		 JRST TTYRS1]	;YES, SO KEEP DDB
	SETZM	DEVNAM(F)	;CLEAR PHYSICAL NAME
	HLLZS	LDBDDB(U)	;REMOVE LINK TO DEAD DDB
	SETZM	DDBLDB(F)	;REMOVE LINK FROM DDB TO LINE DATA BLOCK
	MOVE	T1,[XWD TTYUSE+TTYATC,ASSCON+ASSPRG]
	ANDCAB	T1,DEVMOD(F)	;LAST CLEAR THESE, MAKING DDB AVAILABLE
	JRST	UPOPJ##		;AND RETURN TO CALLER.
;SUBROUTINE CALLED ON RESET FROM UUOCON


TTYRES::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##
	MOVEI	P1,JS.NTO
	TDNE	P1,JBTSTS##(J)
	XORB	P1,JBTSTS##(J)
	ANDI	P1,JS.NTO
	MOVEI	F,SCNDDB
TTYRSA:	LDB	T1,PJOBN##
	CAIE	T1,(J)
	JRST	TTYRSB
	JUMPN	P1,TTYRSC
	SETZB	T1,DEVSTS(F)
	DPB	T1,BYTCNT
TTYRSC:	PUSHJ	P,TTYRL3	;SEE IF ANY REASON TO KEEP DDB.
	  PUSHJ	P,TTYKIL	;NO, DISCARD DDB.
TTYRSB:	HLRZ	F,DEVSER(F)
	MOVE	T1,DEVMOD(F)
	TLNE	T1,DVTTY
	JRST	TTYRSA
	HRRZ	F,TTYTAB##(J)	;GET CONTROLLING DDB ADDRESS
	JUMPE	F,CPOPJ##	;REALLY HAS TO BE ONE
TTYRS1:	MOVE	S,[IOLBKA,,IOSBKA!IOSTEC!IOSFCS!IOSABS+D] ;GET BITS

;THE FOLLOWING CHECK FOR NOT LOGGED IN, RUNNING "LOGIN"
; IS TO AVOID BREAKING ANCIENT "FEATURE" OF NOECHO GETTING
; SET BY LOGIN COMMAND.

	MOVE	U,DDBLDB(F)	;LINK TO LDB
	JUMPE	U,TTYRS2	;NOT BATCH IS DETACHED
	PUSHJ	P,PTBTCH##
	  JRST	TTYRS2
	MOVE	T1,JBTSTS##(J)	;GET THIS STATUS
	MOVE	T2,JBTPRG##(J)	; AND PROGRAM NAME
	TLNN	T1,JLOG		;IS HE NOT LOGGED IN?
	CAME	T2,[SIXBIT/LOGIN/] ; AND RUNNING LOGIN
TTYRS2:	IORI	S,IOSNEC	;NOT BOTH, WE CAN CLEAR NOECHO
	ANDCAB	S,DEVIOS(F)	;CLEAR THESE BITS ON RESET
	JUMPE	U,CPOPJ##	;SKIP IT IF DETACHED
	MOVEI	T1,0		;CLEAR THE AUTO
	DPB	T1,LDPACR	;CRLF COUNTER
	PUSHJ	P,CLRCSB	;CLEAR THE CHARACTER STATUS BYTES
	PUSHJ	P,CLRIM1	;CLEAR IMAGE MODE
	MOVSI	T1,LDLBKA	;THE BREAK-ON-ALL-CHARACTERS BIT
	ANDCAM	T1,LDBDCH(U)	;CLEAR IN LDB SINCE TTYUSR ALREADY CALLED
				; AND WILL HAVE SET IT IF IOLBKA WAS SET
	PUSHJ	P,UUOLDB	;AND MAKE LDB AGREE
	PJRST	SETCHP		;FORCE CHANGE OF CHARACTERISTICS
;ROUTINE TO RETURN NEXT OUT-OF-BAND STATUS TO PSISER
;RETURNED IN T2

IFN FTPI,<
NXTOOB::SE1ENT			;MUST RUN IN SECTION ONE
	PUSH	P,U		;FOR LDBS
	PUSH	P,F		;FOR DDBS
	SETZ	T2,		;FOR FLAGGING WHEN WE FIND STATUS
	HRRZ	F,TTYTAB##(J)	;GET CONTROLLING TERMINAL
	SKIPE	U,DDBLDB(F)	;IS HE ATTACHED?
	SKIPN	LDBOOC(U)	;AND ARE THERE OOB CHARS HERE?
	JRST	NXTOB1		;NO SUCH LUCK, MUST LOOP OVER TTYS
	PUSHJ	P,NXTOBC	;YES, GET A CHARACTER
	  JRST	NXTOB1		;COULDN'T AFTER ALL
	SETZ	F,		;FLAG FOR TTY LOOP
	JRST	NXTOB3		;GET STATUS AND RETURN IT

NXTOB1:	MOVEI	F,SCNDDB	;POINT TO FIRST TTY DDB
NXTOB4:	SKIPN	U,DDBLDB(F)	;IS IT FOR REAL?
	JRST	NXTOB2		;NO, LOOK FOR ANOTHER
	LDB	T1,PJCHN##	;YES, GET ITS OWNER
	CAME	T1,.CPJCH##	;IS IT FOR US?
	JRST	NXTOB2		;NO, LOOK FOR ANOTHER
	SKIPN	LDBOOC(U)	;ARE THERE ANY OOB CHARS HERE?
	JRST	NXTOB2		;NO, KEEP LOOKING
	JUMPN	T2,NXTOB5	;DON'T GET IT IF ALREADY HAVE STATUS
	PUSHJ	P,NXTOBC	;NEED ONE, GET IT
	  JRST	NXTOB2		;OH, WELL
	JRST	NXTOB3		;NOW FIGURE UP THE STATUS
NXTOB2:	HLRZ	F,DEVSER(F)	;FIND NEXT DDB
	MOVSI	T1,DVTTY	;BIT TO TEST
	TDNE	T1,DEVMOD(F)	;IS IT STILL A TTY?
	JRST	NXTOB4		;YES, LOOP
	JRST	FUPOPJ##	;NO, JUST RETURN THE STATUS WE HAVE

NXTOB3:	LDB	T2,LDPLNO	;GET THE LINE NUMBER
	TRO	T2,.UXTRM	;MAKE INTO A UDX
	TRNN	T3,CK.MET	;IS THIS FOR THE SWITCH CHARACTER?
	TRZA	T3,^-CK.CHR	;NO, KEEP ONLY CHARACTER BITS
	MOVEI	T3,400000	;YES, KEEP ONLY A SIGN BIT
	HRL	T2,T3		;CHARACTER,,UDX IS STATUS
	SKIPE	LDBOOC(U)	;ARE THERE MORE ON THIS LINE?
	JRST	NXTOB5		;YES, SIGNAL THE CONDITION AGAIN
	JUMPE	F,NXTOB1	;NO, LOOK FOR MORE ON OTHER LINES
	JRST	NXTOB2		;(NO MATTER WHICH LINE CALLED US)

NXTOB5:	PUSH	P,T2		;PRESERVE THE STATUS TO RETURN
	SIGNAL	C$OOB		;THERE'S ANOTHER OOB CHAR TO RECEIVE
	  JFCL			;IGNORE DOESN'T WANT RETURN
	PUSHJ	P,SETUNR	;MAKE SURE WE STAY AWAKE HERE
	POP	P,T2		;RESTORE STATUS TO RETURN
	JRST	FUPOPJ##	;RESTORE STACK ITEMS AND RETURN

NXTOBC:	SCNOFF			;AVOID RACES
	SOSGE	LDBOOC(U)	;ARE THERE STILL MORE TO GIVE?
	JRST	NXTOBQ		;NO, CLEAN UP
	LDCHKR	T3,LDBOOT(U),SONPPJ ;FETCH THE CHARACTER
	JRST	SONPJ1		;RETURN SUCCESS
NXTOBQ:	SETZM	LDBOOC(U)	;DON'T LET COUNT GO NEGATIVE
	JRST	SONPPJ		;GIVE ERROR RETURN
> ;END IFN FTPI
;SUBROUTINE TO RETURN ONE CHARACTER FROM THE INPUT BUFFER. CHARACTER
;RETURNED IN T3.

COMTYI::PUSH	P,T2		;SAVE AC FOR OUTSIDE WORLD
	PUSHJ	P,CTIGLC	;GET THE LAST CHARACTER
	SKIPN	T3		;IS ANYTHING THERE FROM BEFORE?
	MOVEI	T3,12		;NO. ASSUME END OF LINE
	PUSHJ	P,SPCHEK	;YES. WAS IT A BREAK?
	  JFCL
	TLNN	T1,CHBRK	; ..
COMTI1:	PUSHJ	P,CTIGNC	;NO. GET ANOTHER CHARACTER (CCTYI OR ONCE)
	ANDI	T3,CK.CH7	;COMCON DOESN'T WANT PARITY
	PUSHJ	P,SPCHEK	;CONVERT TO CONSISTENT BREAKS
	  JFCL			;ORDINARY CHARACTER
	TLNE	T1,CHCRET	;CARRIAGE RETURN?
	JRST	COMTI1		;YES. GO GET LINEFEED INSTEAD
	TLNE	T1,CHBRK	;BREAK?
	MOVEI	T3,12		;YES--MAKE INTO LINE FEED
	TLNE	T1,CHCNC	;IS THIS A CONTROL-C?
	MOVEI	T3,3		;YES--CONTROL-C IS STRONGER THAN LF
	PUSHJ	P,CTISLC	;SAY THAT THIS IS THE "LAST CHAR"
	PJRST	T2POPJ##	;RESTORE AC T2 AND RETURN


;SUBROUTINE TO SEND 1 CHAR, SENDING CONTROL CHARS AS ^X
;OTHERWISE, SAME AS COMTYO

USEARO::PUSHJ	P,SPCHEK	;SPECIAL CHAR?
	  JRST	COMTYO		;NO, FORGET IT
	TLNN	T1,CHUAE	;ECHO AS ^X?
	  JRST	COMTYO		;NO, GO ECHO NORMALLY
	PUSH	P,T3		;SAVE THE CHAR
	MOVEI	T3,136		;GET AN ARROW
	PUSHJ	P,COMTYO	;SEND IT
	POP	P,T3		;RESTORE CHAR
	TRC	T3,100		;CONVERT TO LETTER
;;	JRST	COMTYO		;AND GO TYPE IT


;SUBROUTINE TO SEND 1 CHARACTER, CHARACTER IN T3.
;PRESERVES T2 & T3

COMTYO::PUSH	P,T2		;SAVE AC
	PUSH	P,T3
	HRRZ	T2,.CPTOA##	;MAKE DISPATCH ADDRESS
	PUSHJ	P,(T2)		;CALL  CCTYO, CTYWAT, OR ONCE ROUTINE
	POP	P,T3		;RESTORE
	JRST	T2POPJ##	; AC'S AND RETURN

;SUBROUTINE FOR FORCE LEFT MARGIN FOR COMCON

COMFLM::HRRZ	T3,.CPTOA##	;GET DISPATCH ADDRESS
	CAIE	T3,CCTYO	;FULL-BLOWN SCNSER DISPATCH?
	JRST	CRLF##		;NO, JUST TYPE A CRLF ALWAYS
	MOVEI	T3,MC.FLM	;YES, GET FORCE-LEFT-MARGIN FUNCTION CHAR
	SE1ENT			;MUST RUN IN SECTION 1 TO CALL CCTYO8
	PUSH	P,T2		;PROTECT T2
	PUSHJ	P,CCTYO8	;TYPE META CHARACTER
	JRST	T2POPJ##	;RESTORE AC AND RETURN
;ROUTINE TO SET LDLBKA IN LDBDCH AND INFORM FE IF NECESSARY

SETBKA:	MOVSI	T1,LDLBKA	;GET THE BIT
	TDNE	T1,LDBDCH(U)	;IS IT SET ALREADY?
	POPJ	P,		;YES
	IORM	T1,LDBDCH(U)	;NO, SET IT
	PJRST	SETBMC		;AND GO TELL FE

;ROUTINE TO CLEAR LDLBKA IN LDBDCH AND INFORM FE IF NECESSARY

CLRBKA:	MOVSI	T1,LDLBKA	;GET THE BIT
	TDNN	T1,LDBDCH(U)	;IS IT CLEAR ALREADY?
	POPJ	P,		;YES
	ANDCAM	T1,LDBDCH(U)	;NO, CLEAR IT
	PJRST	SETBMC		;AND GO TELL FE

;ROUTINE TO SWITCH TERMINAL TO USER PROGRAM LEVEL AND START USER RUNNING

TTYUSW::TDZA	S,S		;DON'T CLEAR WAIT BITS
TTYUSR::MOVE	S,[XWD IOW,IOACT]	;CLEAR WAIT BITS
	SE1ENT			;ENTER SECTION 1
	HRRZ	F,LDBDDB(U)	;GET ATTACHED DDB IF ANY
	JUMPE	F,TTYUS1	;JUMP IF NOT ATTACHED
	ANDCAB	S,DEVIOS(F)	; ..
	TLNE	S,IOLBKA	;NEED TO RE-SET BREAK ON ALL BIT?
	 PUSHJ	P,SETBKA	;YES, GO SET IT
	MOVSI	S,IOLBKA	;NOW CLEAR OUT
	ANDCAB	S,DEVIOS(F)	; ANNOYING TEMP BIT
	PUSHJ	P,UUOLDB	;MAKE LINE AND DEVIOS AGREE
TTYUS1:	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS THIS A PTY?
	PUSHJ	P,PTMNMZ##	;YES. TELL CONTROLLER
	MOVSI	T1,LDLCOM	;PUT TERMINAL IN USER MODE
	ANDCAM	T1,LDBDCH(U)	;MAY BE DETACHED, BUT WILL WAIT
				; AT UUO LEVEL IF NEEDED
	PJRST	SETRUN##	;SET USER'S RUN BIT AND RETURN
;ROUTINE TO SET TERMINAL TO COMMAND LEVEL

TTYSTC::SE1ENT			;ENTER SECTION 1
	MOVE	T2,LDBDCH(U)	;SEE IF THIS LINE IS SLAVED
	TLNE	T2,LDLSLV	;SLAVED?
	JRST	TTYST1		;YES, DON'T REALLY SET COMMAND MODE
	PUSH	P,LDBBY2(U)	;PRESERVE L2RECS AROUND CNCMOD
	PUSHJ	P,CNCMOD	;AND GET TO COMMAND LEVEL
	POP	P,T1		;GET L2RECS WORD BACK
	ANDI	T1,L2RECS	;WE ONLY CARE ABOUT THIS BIT
	IORM	T1,LDBBY2(U)	;RESTORE IF WAS SET
TTYST1:
IFN FTMIC,<PUSHJ P,MICWAK>	;WAKE MIC IF NECESSARY
IFE FTMIC,<MOVE T1,LDBDCH(U)>	;GET DCH BITS AGAIN
	TRNN	T1,LDRPTY	;PTY-DRIVEN LINE?
	JRST	TTYST3		;NO, DON'T DO PTY STUFF
	PUSHJ	P,PTMNMD##	;YES. TELL CONTROLLER
	JRST	TTYST2		;AND GO POKE IT FOR OUTPUT
TTYSTR::SE1ENT			;ENTER SECTION 1
	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS IT A PTY?
TTYST2:	PUSHJ	P,PTYPE##	;YES. WAKE THE PTY CONTROLLER
TTYST3:	PUSHJ	P,COMQ		;AT COMMAND LEVEL?
	  PJRST NOCTRO		;NO. JUST CLEAR ^O BIT
	PUSHJ	P,TYIEAT	;YES. CLEAR THE COMMAND IN CASE MORE
	PUSHJ	P,STRTDL	;ECHO ONE DEFERRED LINE IF NECESSARY
	SKIPLE	LDBBKC(U)	;ANY MORE COMMANDS?
	PUSHJ	P,COMSET	;MAYBE. SET BIT IF AT COM LEVEL
	PJRST	NOCTRO		;CLEAR OSU AND RETURN
;HERE AT COMPLETION OF A COMMAND

TTYCMR::SE1ENT			;ENTER SECTION 1
	PUSH	P,T1		;SAVE PREVIOUS LDPCMX
	TRNN	F,-1		;ANY JOB?
	PUSHJ	P,TTYCPT	;NO. CLEAR PAPER-TAPE BITS
	AOS	T1,LINSAV##
	CAIL	T1,TTPLEN##
	SETZM	LINSAV##
	HLL	T2,LDBCOM(U)	;GET COMMAND REQUEST BITS
	POP	P,T1		;COMMAND JUST FINISHED
	LDB	T3,LDPCMX	;CURRENT
	CAME	T1,T3		;CHANGED?
	TLNN	T2,LDBCMF	;FORCED
	SKIPA			;NO CHANGE OR NOT FORCED
	POPJ	P,		;NEW FORCED-DO IT
	MOVEI	T1,L2RECS	;SET EAT-COMMAND-SYNC BIT
	TLNN	T2,LDBCMF	;(UNLESS FORCED COMMAND)
	IORM	T1,LDBBY2(U)	;IN LINE DATA BLOCK
	MOVSI	T1,LDBCMR+LDBCMF;CLEAR COMMAND REQUEST BITS
IFN FTFDAE,<
	TLNE	T2,LDBFDX	;DOING FILDAE EXIT PROCESSING?
	TLZ	T1,LDBCMF	;YES, LEAVE LDBCMF ALONE
>
	ANDCAB	T1,LDBCOM(U)	;IN BASE WORD OF LDB
	MOVE	T1,LDBDCH(U)	;GET THE LINE'S CHARACTERISTIC
	TLNN	T1,LDLBKA+LDLIMI;ARE WE BREAKING ON ALL CHARACTERS
				; OR IN IMAGE MODE?
	JRST	TTCMR1		;NO, CONTINUE ON
	SKIPLE	LDBTIC(U)	;YES, DO WE HAVE ANY CHARACTERS
				; IN THE INPUT BUFFER?
	PUSHJ	P,RCVWAK	;YES, WAKE THE JOB
				;NO,...
TTCMR1::SE1ENT			;ENTER SECTION 1
	MOVE	T1,LDBCOM(U)	;GET THE LINES LDBCOM & CONTINUE
	TLNN	T1,LDBCMK	;FORCED KJOB PENDING?
IFN FTMIC,<			;IF MIC
	PUSHJ	P,CMDCLR	;NO, CLEAR COMMAND BIT
	PJRST	MICWAK		;WAKE MIC UP IF NEC & RETURN TO COMCON
> ;END OF IF MIC
IFE FTMIC,<			;IF NOT MIC
	PJRST	CMDCLR		;NO, CLEAR COMMAND BIT
	POPJ	P,0		;YES, DO NOT CLEAR COMMAND BIT
> ;END OF IF NOT MIC
	SUBTTL	SUBROUTINES FOR COMCON OR UUO LEVEL

;COMMON UUO LEVEL ROUTINES
;TYO7W IS USED TO TAKE A 7-BIT CHARACTER IN T3
; GO INTO I/O WAIT IF JOB DETACHED OR IF THE LINE'S
; OUTPUT BUFFER IS RATHER BIG, THEN PLACE THE CHARACTER IN OUTPUT
; STREAM, AND START OUTPUT IF NEEDED.
;TYO9W IS SAME, BUT ASSUMES PARITY AND NINTH BIT ARE AS DESIRED.
;TYO CHOOSES ONE OF THE ABOVE, DEPENDING ON MODE IN S
;CALL TYO9W WITH SIGN BIT OF T3 SET TO AVOID BLOCKING. SIGN BIT CLEARED IF CHAR ACTUALLY OUTPUT

; (USED TO AVOID WTP STOPED ON CALL FROM TTMORE)
;CALL WITH DDB SET UP, CHARACTER IN T3.
;IF CALLED AT TYO, S MUST BE SET UP ALSO

TYO:	TRNN	S,I!PIMMOD	;IMAGE MODE USE OWN PARITY
TYO7W:	ANDI	T3,CK.CHR
TYO9W:	MOVE	S,DEVIOS(F)
	TRNE	S,IODERR	;^C TYPED ON TTYNNN
	JRST	[TLZ T3,(1B0)	;FLAG WE GOT CHAR
		 POPJ  P,]
	MOVSI	S,IO		;INDICATE OUTPUT
	IORB	S,DEVIOS(F)	;..
	MOVE	U,DDBLDB(F)	;GET LINE ADDR IF ANY
	JUMPN	U,TYOX		;ATTACHED, PROCEED
	JUMPL	T3,CPOPJ	;IF ASYNCHRONOUS RETURN
	PUSHJ	P,CKATOW	;WAIT FOR ATTACH
	SKIPA
TYOX:	PUSHJ	P,UUOLDB
	MOVE	T1,TTFREN##	;MAKE SURE THERE'S SOME CHARACTER SPACE LEFT
	CAIGE	T1,3		;LEAVE 3 CHUNKS FOR SAFETY
	JRST	[JUMPGE T3,TYONFC ;NO,WAIT
		 POPJ P, ]	;UNLESS ASYNCH
	MOVE	T1,LDBTOC(U)	;GET OUTPUT STREAM LENGTH
	CAML	T1,TIWRNN	;IS HE OVER QUOTA?
	JRST	[JUMPGE T3,TYOOBF ;WAIT IF ATTACHED
		 POPJ P, ]
IFN FTMIC,<
IFN FTMLOG,<
	SKIPN	LDBLOT(U)	;IS HE LOGGING
	JRST	TYO9M		;NO
	ADD	T1,LDBLOC(U)
	CAIL	T1,^D100
	JRST	MICLGX		;GO WAKE UP MIC
TYO9M:>	;END OF FTMLOG CONDITIONAL
>;END IFN FTMIC
	TLZ	T3,(1B0)	;FLAG WE GOT CHARACTER
	MOVE	T1,LDBDCH(U)	;CHECK FOR OUTPUT SUPPRESS
	SKIPL	LDBOFL(U)
	TRNE	T1,LDROSU	; ..
	POPJ	P,0		;NO. JUST RETURN DUE TO ^O
TYO9A:	SCNOFF			;NO RACES
	STCHK	T3,LDBTOP(U),SONPPJ  ;STORE CHARACTER IN CHUNKS
	AOS	LDBTOC(U)	;COUNT UP OUTPUT STREAM LENGTH
	SCNON			;ALLOW INTERRUPTS
IFN FTMIC,<			;IF MIC
	PUSHJ	P,MICPOS	;YES SET UP AND CHECK POSITION
> ;END OF IF MIC
	PJRST	TOPOKE		;START OUTPUT FOR THE LINE
;HERE IF NO FREE CHUNKS
TYONFC:	PUSH	P,T3		;ACS USED BY SETSLP
	PUSH	P,U
	MOVEI	T1,5		;SLEEP FOR 5 SEC.
	S0PSHJ	SLEEP##		; ..
	POP	P,U		;RESTORE ACS
	HRRZ	F,LDBDDB(U)
	POP	P,T3
	JRST	TYO9W


IFN FTMIC&FTMLOG,<
MICLGX:	PUSHJ	P,MICWAK
	JUMPL	T3,TYO9M		;DON'T BLOCK IF FROM TTMORE
> ;END OF FTMLOG CONDITIONAL

;HERE IF OUTPUT BUFFER FULL
TYOOBF:	PUSHJ	P,TOWAT1
	JRST	TYO9W
;SUBROUTINE TO SETUP A BYTE COUNT AND POINTER TO A USER'S BUFFER
;CALLING SEQUENCE:
;	MOVE	S,DEVIOS(F)
;	HRRZ	P1,USER VIRTUAL ADDRESS OF BUFFER
;	PUSHJ	P,SRLPTR
;
;ON RETURN P1 IS A BYTE POINTER TO THE USER BUFFER AND P2 IS THE MAXIMUM
;BYTE COUNT FOR THE BUFFER.  PRESERVES T1-T4.

SRLPTR::ADD	P1,[POINT 7,1,35] ;ASSUME ASCII MODE (AND SKIP .BFCNT WORD)
	TRNE	S,PIMMOD!A8	;PACKED IMAGE OR 8-BIT MODE?
	HRLI	P1,(POINT 8,,35)	;YES, USE 8-BIT BYTES
	TRNE	S,I		;REGULAR IMAGE MODE?
	HRLI	P1,(POINT 36,,35)	;YES, USE 36-BIT BYTES
	TRNN	S,I!PIMMOD!A8	;ASCII MODE?
	IMULI	P2,5		;YES, 5 BYTES PER WORD
	TRNE	S,PIMMOD!A8	;PACKED IMAGE OR 8-BIT MODE?
	LSH	P2,2		;YES, 4 BYTES PER WORD
	POPJ	P,
;SUBROUTINE FOR COMMAND LEVEL OUTPUT

CCTYO::	SE1ENT			;ENTER SECTION 1
	ANDI	T3,CK.CHR	;CCTYO DOESN'T DO IMAGE
;CCTYO8 IS LIKE TYO9W, BUT FOR LDB NOT DDB
CCTYO8:	JUMPE	U,CPOPJ##	;U MUST BE SET UP
	SKIPG	T2,TTFREN##	;SPACE IN STRINGS?
	JRST	CCTYO2		;NO. QUIT.
	CAIL	T2,20
	SKIPN	TTFTAK		;IS THERE A FREE LIST?
	JRST	CCTYO2		;NO--PUNT
	PUSHJ	P,UUOLVL##	;ARE WE WILLING TO BLOCK?
	  JRST	CCTYO1		;NO, LET IT GO BY
	HRRZ	T1,LDBDDB(U)	;CHECK DDB
	JUMPE	T1,CCTYO1	;CAN'T WAIT IF NONE
	MOVE	T1,LDBTOC(U)	;GET COUNT
	CAML	T1,TIWRNN	;YES. SPACE IN THIS GUY'S AREA?
	JRST	CCTYO3		;NO
CCTYO1:	TLZ	T3,(1B0)	;GOT CHARACTER
	JRST	TYO9A		;YES. GO TYPE IT.

CCTYO2:	PUSHJ	P,UUOLVL##	;MAKE SURE IT'S OK TO BLOCK
	  POPJ	P,		;FORGET ABOUT OUTPUT IF NOT
CCTYO3:	JUMPL	T3,CPOPJ##	;DON'T BLOCK IF REQUESTED ASYNCHRONOUS
	PUSH	P,T3		;YES, PRESERVE CHARACTER
	PUSH	P,U		;AND LINE
	MOVEI	T1,2		;TWO SECONDS
	S0PSHJ	SLEEPF##	;WAIT FOR SOME SPACE TO APPEAR
	POP	P,U		;RESTORE LINE
	POP	P,T3		;AND CHARACTER
	JRST	CCTYO8		;AND TRY IT AGAIN



;SUBROUTINE TO CLEAR PAPER TAPE INPUT BITS, RETURNS LDBDCH IN T1

TTYCPT::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,L2LTAP	;CLEAR TTY TAPE COMMAND BIT
	ANDCAM	T1,LDBBY2(U)	;IN BY2
	MOVEI	T1,L2RXON	;CLEAR XON IN EFFECT
	ANDCAB	T1,LDBBY2(U)	;AND RETURN NEW STATUS
	POPJ	P,		;RETURN
	SUBTTL	CTY ROUTINES

	$LOW			;MUST BE IN THE LOW SEGMENT FOR ONCE-ONLY

;SUBROUTINE TO PRINT ON CTY IN EMERGENCY OR ONCE-ONLY
; WHEN INTERRUPT SYSTEM CANNOT BE USED OR TRUSTED
;CALL:	MOVEI	T1,ADR OF ASCIZ MESSAGE
;	PUSHJ	P,CTYTYP
;	ALWAYS	RETURN

CTYTYP::HRLI	T1,440700	;FORM BYTE POINTER
CTYTYL:	ILDB	T3,T1		;GET NEXT CHARACTER
	JUMPE	T3,LCPOPJ	;END OF MESSAGE?
				;(CPOPJ IS IN HISEG, SO DON'T USE IT)
	PUSHJ	P,CTYWAT	;NO, PRINT IT ON CTY AND WAIT
	JRST	CTYTYL		;GO GET NEXT CHAR.




;ROUTINE RESIDING IN LOSEG TO COMPUTE PARITY.
; USED ONLY FOR EMERGENCY CTY OUTPUT ROUTINES.
; USES T1

CTYPAR:	MOVEI	T1,(T3)
	LSH	T1,-4		;FOLD INTO LOW 4 BITS
	XORI	T1,(T3)
	TRCE	T1,14		;CHECK BITS 32 AND 33
	TRNN	T1,14
	TRC	T3,200		;IF EVEN PARITY COMPLEMENT RESULTS
	TRCE	T1,3
	TRNN	T1,3
	TRC	T3,200		;IF EVEN PARITY COMPLEMENT RESULTS
	POPJ	P,		;RETURN
;STILL IN $LOW

;SUBROUTINE FOR ERROR MESSAGE TO CTY DURING PARITY ERROR STOP
;CALL:	MOVEI	T3,CHARACTER
;	PUSHJ	P,CTYWAT
;	RETURN AFTER CHARACTER HAS BEEN TYPED
;NOTE:  DOES NOT USE INTERRUPT SYSTEM SO MESSAGE WILL GET OUT BEFORE HALT
;THIS SUB CALLED BY COMTYO WHEN COMTOA PATCHED

CTYWAT::PUSH	P,T1
	PUSHJ	P,CTYPAR	;COMPUTE PARITY WITH LOSEG ROUTINE


IFN FTKS10,<
	SKIPE	CTYOWD		;CAN WE TYPE YET ?
	JRST	.-1		;WAIT A WHILE
	TRO	T3,CTYOVL	;VALID FLAG
	MOVEM	T3,CTYOWD	;PUT UP FOR FRONT END TO SEE IT
	RDAPR	T1		;GET PROCESSOR PIA
	ANDI	T1,SP.PIA	;LEAVE ONLY THE PIA
	WRAPR	SP.SSF+SP.IFE(T1) ;INTERRUPT THE FRONTEND
	SKIPE	CTYOWD		;WAIT FOR CTY TO BE IDLE
	JRST	.-1		;OTHERWISE HALT OR RESET WILL CLOBBER LAST CHAR
	JRST	OPRFI2		;OK TO RETURN
>;IFN FTKS10

IFN FTKL10,<
	PUSHJ	P,SPCTYO##	;SEND CHAR OVER
	PUSHJ	P,SPCWTO##	;WAIT FOR OUTPUT TO COMPLETE
	  JRST	.-1
	JRST	OPRFI2		;RESTORE T1 AND RETURN
>;END IFN FTKL10
;STILL IN $LOW

;SUBROUTINE TO ADD A DELAY FOR SLOW CTY'S
;CALL WITH:
;	MOVEI	T3,CHAR
;	PUSHJ	P,OPRFIL
;USED ONLY WITH PI SYSTEM OFF

OPRFIL::ANDI	T3,CK.CH7	;ONLY CHAR BITS
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,0		;ASSUME NO FILLERS
	CAIN	T3,12		;LF GETS
	MOVEI	T1,CTYDLF##	;8 TICKS
	CAIN	T3,15		;CR GETS
	MOVEI	T1,CTYDCR##	;18 TICKS
	JUMPE	T1,OPRFI2	;RETURN
	ADDM	T1,TIME##	;UPDATE TIME
	PUSH	P,T2		;SAVE T2 FOR APR STATUS


IFN FTKS10,<
OPRFI1:	RDAPR	T2		;GET CLOCK FLAG
	TRNN	T2,SP.ITI	;DID CLOCK TICK ?
	JRST	OPRFI1		;NOT YET
	ANDI	T2,77		;REDUCE TO PI ASSIGNMENTS
	WRAPR	SP.CSF+SP.ITI(T2)  ;CLEAR CLOCK FLAG
>;IFN FTKS10

IFN FTKL10,<
OPRFI1:	CONSO	TIM,TI.ITD	;CLOCK "TICK" ?
	JRST	OPRFI1		;NOT YET
	CONO	TIM,@ONCKLT##	;YES, CLEAR AND SET FOR ANOTHER "TICK"
>;END IFN FTKL10

	SOJG	T1,OPRFI1	;LOOP FOR WHOLE TIME
	POP	P,T2		;ADJUST STACK
OPRFI2:	POP	P,T1		;--
LCPOPJ:	POPJ	P,		;LOCAL CPOPJ FOR USE WHEN HISEG ISN'T MAPPED

	$HIGH			;BACK TO THE HIGH SEGMENT
	SUBTTL	DDB ROUTINES

;ROUTINE TO FIND A FREE TTY DEVICE DATA BLOCK

;CALL FROM CLOCK LEVEL TO DO AN ATTACH ON A NEW JOB, OR
;FROM UUO LEVEL ON AN INIT OF A NEW LINE.

;CALL:	NO ARGUMENTS
;	PUSHJ P,DDBSRC
;	  ERROR RETURN		;NONE AVAILABLE. F=0. T1 CLOBBERED
;	OK RETURN		;ADDRESS IN F, TTYUSE SET IN DEVMOD
;				;RESPECTS J,U,T2.
;				;IF YOU DECIDE NOT TO USE DDB, YOU BETTER
;				;FREE IT UP AGAIN.


DDBSRC:	PUSHJ	P,DDBSR0	;TRY TO GET A DDB
	  SKIPA			;LOST -- TRY AGAIN
	PJRST	CPOPJ1##	;WE WON
DDBSR0:	MOVEI	F,TTYLST	;START OF THE TTY DDB'S
DDBSRA:	MOVSI	T1,TTYUSE	;FLAG THAT A DDB ISN'T FREE
	SCNOFF			;MAKE SURE NO CONFLICT HERE
	TDNN	T1,DEVMOD(F)	;IS THIS DDB FREE?
	JRST	DDBSR1		;YES. GO GRAB IT.
	SCNON			;NO. REENABLE PI SYSTEM
	HLRZ	F,DEVSER(F)	;LINK DOWN THE DDB CHAIN
	MOVE	T1,DEVMOD(F)	;MAKE SURE STILL A TTY DDB
	TLNE	T1,DVTTY	;IS IT?
	JUMPN	F,DDBSRA	;YES. (UNLESS END OF CHAIN)
	MOVEI	F,0		;NO MORE TTY DDB'S. WE LOSE.
	POPJ	P,0		;RETURN NON-SKIP, WITH 0 IN DDB

DDBSR1:	IORM	T1,DEVMOD(F)	;SET BIT SO WE HAVE THE DDB
	SCNON			;NOW PI'S CAN HAPPEN AGAIN
	PUSHJ	P,CLRDVL##	;CLEAR JOB NO. IN CASE OF JUNK
	MOVE	T1,[XWD TTYATC,ASSCON+ASSPRG]	;LIKEWISE MODE BITS
	ANDCAM	T1,DEVMOD(F)	; ..
	MOVSI	T1,DEPRAS	;GET THE RESTRICTED ASSIGN BIT
	ANDCAM	T1,DEVSTA(F)	;MAKE SURE IT'S CLEARED
	SETZM	DEVLOG(F)	;AND LOGICAL NAME
	MOVSI	T1,IOFST	;AND INITIAL S WORD
	MOVEM	T1,DEVIOS(F)	;WHICH SHOULD LEAVE IT PRETTY CLEAN
	JRST	CPOPJ1##	;SKIP RETURN. WE HAVE A DDB.
;ROUTINE TO FIND A TTY DDB WHICH IS ATTACHED TO, I.E.
;CONTROLLING, A PARTICULAR JOB NUMBER.
;
;CALLED AT COMMAND LEVEL BY ATTACH COMMAND, AND AT UUO LEVEL
;BY REFERENCES TO DEVICE "TTY" OR TTCALLS, ETC.
;
;CALL:	MOVE J,JOB NUMBER DESIRED
;	PUSHJ P,TTYSRC
;	  ERROR RETURN.	;NOT FOUND. AC'S U,F,S NOT GUARANTEED
;	NORMAL RETURN	;U, S AND F SET UP. NOTE THAT THIS DOES
;			;!NOT! IMPLY THAT ANYONE IS ATTACHED. THAT IS,
;			; U MAY CONTAIN A ZERO
;
;			;CLOBBERS T1

TTYSRC::JUMPLE	J,CPOPJ##	;NOBODY CONTROLS JOB ZERO. YOU ARE CONFUSED.
	HRRZ	F,TTYTAB##(J)	;GET CONTROLLING TTY DDB ADDRESS
	JUMPE	F,CPOPJ##	;RETURN IF NONE
	MOVE	T1,DEVMOD(F)	;GET DEVICE BITS FROM DDB
	TLNN	T1,TTYATC	;IS THIS THE CONTROLLING TTY?
	POPJ	P,0		;NO. IT WAS A SLAVE OR SOMETHING.
	MOVE	U,DDBLDB(F)	;YES. GET THE LDB LINK (MAY BE 0)
	MOVE	S,DEVIOS(F)	;AND I/O STATUS WORD
	JRST	CPOPJ1##	;GIVE SUCCESS RETURN.
;ROUTINE CALLED WHEN DEVSRC CAN'T FIND DEVICE XXX (IN T1), AND
; IT WANTS TO SEE IF IT IS A PHYSICAL TTY. GETDDB CHECKS NAME,
; AND IF IT SHOULD BE A TTY, LOOKS FOR ITS DDB, OR MAKES ONE.
;
;CALL:	MOVE J,JOBNUMBER OR JCH
;	PUSH P,J
;	MOVE T1,SIXBIT DEVICE NAME, ALLEGEDLY A PHYSICAL TTY NAME
;	PUSHJ P,GETDDB
;	  ERROR RETURN, NOT A TTY OR THERE ARE NO DDB'S AVAILABLE.
;	OK RETURN. IT IS A TTY, AND F AND U ARE NOW SET TO IT.
;RESPECTS T1 ON THE OK RETURN ONLY
;J WILL BE POPPED ON EITHER RETURN.
;CALL AT GETDDJ IF J HAS NOT YET BEEN PUSHED.
;
;CALLED FROM DEVSRC, SO MAY BE AT UUO OR CLOCK LEVEL

GETDDB::POP	P,J		;BALANCE STACK (RESTORE JCH)
GETDDJ::SE1ENT			;ENTER SECTION 1
	PUSH	P,J		;SAVE JCH FOR CALLERS WHO CARE
	ANDI	J,JOBMSK##	;MAKE SURE OF JOB NUMBER FOR US

IFN FTMP,<
	PUSHJ	P,INTLVL##	;IF AT UUO LEVEL
	  PUSHJ	P,ONCPU0##	;AVOID RACES WITH COMCON
>
	PUSHJ	P,TTYPHY	;LOOK FOR THIS PHYSICAL NAME
	  JRST	JPOPJ##		;IT ISNT A TTY
	JUMPN	F,GETDB5	;IS THERE A DDB ALREADY?
				;IF SO, SOMEONE HAS CALLED GETDDB WHO
				; COULD HAVE CALLED DEVSRC.
	PUSHJ	P,CHKFLN	;CHECK FOR LEGAL ACCESS TO FRCLIN
	PUSHJ	P,DDBSRC	;NO. NEED A NEW DDB. TRY TO GET ONE.
	  JRST	JPOPJ##		;NONE AVAILABLE. FAIL RETURN
	HRRM	F,LDBDDB(U)	;SUCCESS. SET LINKS TO AND FROM DDB
	MOVEM	U,DDBLDB(F)	; AND LINE DATA BLOCK.
	PUSHJ	P,SCNNAM	;FILL IN REAL NAME AND PUNIT
IFN FTNET,<PUSHJ P,SETSTA>	;PUT STA # IN DDB
GETDB5:	MOVE	T1,DEVNAM(F)	;RESTORE REAL NAME TO T1
	JRST	JPOPJ1##	;AND GIVE SUCCESSFUL RETURN FROM GETDDB


;ROUTINE TO CHECK FOR LEGAL ACCESS TO FRCLIN.
;CALL:	MOVE	U,LDB ADDRESS
;	PUSHJ	P,CHKFLN
;	  RETURN HERE IF NOT FRCLIN OR LEGAL ACCESS
;	  RETURN HERE IF ACCESS NOT LEGAL
;DESTROYS T1

CHKFLN:	LDB	T1,LDPLNO	;GET LINE NUMBER
	CAIE	T1,FRCLIN##	;IS IT FRCLIN?
	POPJ	P,		;NO, GIVE OK RETURN
	PUSHJ	P,SAVT##	;SAVE T1-T4 FOR SAFETY
	MOVSI	T1,JP.POK	;MUST HAVE POKE PRIVILEGE OR BE
	PJRST	PRVBIT##	;BE LOGGED INTO [1,2] OR JACCT
;SUBROUTINE TO PUT PHYSICAL NAME INTO T2 FOR U WHOSE LDB IS IN U
;EVEN THOUGH THERE MAY BE NOTHING IN F OR LDBDDB

TTYNAM::SE1ENT			;ENTER SECTION 1
	PUSH	P,[SIXBIT /CTY/];SEE IF CTY
	MOVEI	T1,LDRCTY
	TDNE	T1,LDBDCH(U)
	JRST	T2POPJ##	;YES.
	LDB	T1,LDPLNO
	MOVSI	T3,'TTY'	;NO. CHANGE TO TTY
	MOVEM	T3,0(P)		;ON STACK
	MOVSI	T3,(POINT 6,0,17) ;SETUP SIXBIT BYTE POINTER TO
	HRRI	T3,0(P)		;NAME ON THE STACK
	S0PSHJ	SCNNMR		;AND CALL SAME ROUTINE AS SCNNAM DOES
	PJRST	T2POPJ##	;PUT ANSWER IN T2
				;AND RETURN FROM TTYNAM
;SUBROUTINE TO FIND LDB FOR A PHYSICAL NAME, IF ITS A TTY
;AND LOAD F WITH LINKED DATA BLOCK, IF ANY, BUT DON'T MAKE ONE IF NONE YET
;SKIP RETURN IF ITS A TTY


TTYPHX:	PUSHJ	P,TSTOPR##	;SEE IF OPR AND FUDGE T1
	PUSHJ	P,SAVE2##
	PUSH	P,T1		;SAVE NAME
	MOVE	P1,BOOTCT##
	CAMN	T1,[SIXBIT /CTY/] ;IS CTY WANTED?
	JRST	TTYPH1		;YES. GO USE TCONLN
	HLLZ	P1,T1		;GET FIRST THREE CHARACTERS
	CAMN	P1,[SIXBIT /TTY/] ;ARE THEY TTY?
	TRNN	T1,770000	;AND ALSO IS FOURTH CHAR NON-BLANK?
	PJRST	TPOPJ##		;NO. NOT A LEGAL NAME.
	MOVSI	P2,(<POINT 6,0(P),17>)	;POINTER TO READ CHARS
	MOVEI	P1,0		;INITIALIZE LINE TO 0
TTYPH4:	ILDB	T1,P2		;GET A SIXBIT CHARACTER FROM NAME
	JUMPE	T1,TTYPH2	;JUMP IF END OF NAME.
	TRC	T1,"0"-40	;CONVERT SIXBIT TO BINARY
	CAILE	T1,7		;IS IT AN OCTAL DIGIT?
	JRST	TPOPJ##		;NO. BAD CHAR IN NAME
	ASH	P1,3		;MULTIPLY BY 8
	ADDI	P1,0(T1)	;ADD IN THIS DIGIT
	TLNE	P2,770000	;CHECK FOR MORE DIGITS
	JRST	TTYPH4		;LOOP FOR MORE DIGITS
TTYPH2:	CAMLE	P1,P3		;IS IT A LEGAL HARDWARE LINE #?
	JRST	TPOPJ##		;NO. TOO BAD.
TTYPH1:	MOVE	U,LINTAB##(P1)	;GET LINE DATA BLOCK ADDRESS
	SE1XCT	<HRRZ F,LDBDDB(U)> ;GET ATTACHED DDB, IF ANY.
	JRST	TPOPJ1##	;GOOD RETURN

TTYPHY::PUSH	P,P3		;SET UP FOR PHYSICAL ONLY
	MOVEI	P3,TCONLN##
TTYPHZ:	PUSHJ	P,TTYPHX	;CALL COMMON SUBROUTINE
	  SOS	-1(P)		;REMEMBER NON-SKIP RETURN
	POP	P,P3		;BY PROPAGATING IT
	JRST	CPOPJ1##

TTYALL::PUSH	P,P3		;TRY ALLL-PHYSICAL & VIRTUAL
	MOVEI	P3,TTPLEN##-1
	JRST	TTYPHZ
;SUBROUTINE TO FIND TTY FOR A JOB IN J (TTYFND) OR FOR
; CURRENT JOB (TTYFNU)
;RETURN WITH F AND U SET UP.
;GOES TO ERROR IF NO TTYDDB FOR THE JOB.


TTYFNU::MOVE	J,.CPJOB##	;GET CURRENT UUO LEVEL JOB NUMBER
TTYFND::PUSHJ	P,TTYSRC	;FIND THE JOB'S TTY DDB, ALSO U AND S
	  STOPCD CPOPJ##,DEBUG,NDJ,	;++NO DDB FOR JOB
	POPJ	P,0		;SUCCESS. RETURN.

;SUBROUTINE TTYFUW (TELETYPE FIND FOR CURRENT USER AND WAIT), TO
;FIND CURRENT USER'S TTY AND WAIT FOR IT TO COME OUT OF OUTPUT
;WAIT, AND BE ATTACHED.
;SUBROUTINE TOWAIT, TO WAIT FOR TYPEOUT ACTIVITY TO (NEARLY) COMPLETE,
;IF NECESSARY.


TTYFUW::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,TTYFNU	;FIND USER'S TTY
	PUSHJ	P,CKATTO	;CHECK THAT IT'S ATTACH. WAIT IF NOT.
IFN FTMIC,<			;IF MIC
	MOVE	T1,LDBMIC(U)	;CHECK FOR ERROR RESPONSE OR RESPONSE CODE SYNC
	TLNE	T1,LDLRSP!LDLRSY
	POPJ	P,0		;IF HE WANTS RESPONSE STUFF DO NOT TO
> ;END OF IF MIC
;ROUTINE TO WAIT FOR NEARLY EMPTY OUTPUT BUFFER. CALL ONLY AT UUO LEVEL
TOWAIT:	MOVE	S,[XWD	TTYOUW+IO+IOW,IOACT]	;SET ACTIVE & WAITING FIRST TO AVOID COMPLETION
	IORM	S,DEVIOS(F)	;BETWEEN TEST FOR COMPLETION & IOACT SET
	MOVE	T1,LDBTOC(U)	;GET COUNT OF TYPE-OUT CHARACTERS WAITING.
	CAIL	T1,10		;OVER 7?
	JRST	TOWAT2		;YES. HAVE TO WAIT
	ANDCAB	S,DEVIOS(F)	;NO. NOT WAITING, SO TURN OFF BITS
	POPJ	P,		;& RETURN
TOWAT1:	MOVE	S,[XWD TTYOUW+IO,IOACT]	;FLAG OUTPUT WAIT ACTIVITY
TOWAT2:	IORB	S,DEVIOS(F)	;IN THE DEVICE DATA BLOCK
	PUSHJ	P,PTSTRT	;WAKE UP SUBJOB, IF ANY
	S0PSHJ	WSYNC##		;WAIT FOR IO TO COMPLETE
	MOVE	U,DDBLDB(F)	;SET UP LDB IN CASE DETACH/ATTACHAPPENED WHILE WAITING
	JUMPE	U,[MOVE U,DEVMOD(F) ;LDB PTR GONE, GET STATUS WORD
		   TLNE U,TTYATC ;WAS THIS THE CONTROLLING TTY?
		   JRST TTYFUW	;YES, GO LOOK FOR IT
		   MOVSI S,TTYOUW+IO+IOW ;GET IO WAIT BITS
		   ANDCAB S,DEVIOS(F)	;AND CLEAR THEM
		   SETZ U,	;NOTE NO TTY FOR THE DDB
		   POPJ P,]	;NO, AN I/O DEVICE RETURN WITH IODERR SET
	POPJ	P,		;AND RETURN

PTSTRT:	JUMPE	U,CPOPJ##	;IN CASE U NOT SET UP
	MOVEI	T1,LDRPTY	;GET PTY BIT
	TDNE	T1,LDBDCH(U)	;IS THIS ONE
	PJRST	PTYPE##		;YES, WAKE UP CONTROLLER
	POPJ	P,		;NO, RETURN
;CO-ROUTINE TO SET FOR ERROR MESSAGES TO CTY DURING ONCE OR NORMAL
;TIMESHARING.  PRESERVES .CPTOA AND ALL ACS EXCEPT T1.

CTYERM::PUSH	P,U		;SAVE AC'S LIKE ADVERTISED
	PUSH	P,F
	PUSHJ	P,TTYERC	;SET UP U FOR CTY OUTPUT
	PUSH	P,.CPTOA##	;SAVE TYPEOUT ROUTINE ADDRESS
	MOVEI	T1,CTYWAT	;ASSUME SYSTEM STARTUP
	SKIPN	DINITF##	;ONCE-ONLY CHECK
	MOVEI	T1,CCTYO	;TIMESHARING
	MOVEM	T1,.CPTOA##	;SET TYPEOUT ROUTINE
	PUSHJ	P,@-3(P)	;CALL THE CALLER
	  SKIPA			;NON-SKIP RETURN
	AOS	-4(P)		;SKIP RETURN
	POP	P,.CPTOA##	;RESTORE TYPEOUT ROUTINE
	POP	P,F		;RESTORE AC'S
	POP	P,U
	ADJSP	P,-1		;REMOVE CALLER'S PC
	POPJ	P,		;RETURN TO CALLER'S CALLER
;SUBROUTINE TTYERP TO FIND TTY DDB FOR A MONITOR ERROR MESSAGE.
;CALL WITH J SET TO JOB NUMBER TO BE TYPED AT.
;IF JOB IS ZERO, OR IF DESIRED JOB IS DETACHED, TTYERP RETURNS
;WITH U SET TO OPERATOR'S CONSOLE, AND F SET FROM IT,
;BUT OF COURSE THAT DDB MAY BE ZERO, SINCE MAY BE NO JOB AT OPR.


TTYERP::PUSHJ	P,TTYSRC	;FIND THE TTY DDB IF POSSIBLE
	  JRST TTYERO		;NONE THERE. MAYBE JOB 0. GO FIND OPR
	JUMPN	U,CPOPJ1##	;SKIP RETURN TO SIGNAL LDB FOUND
TTYERO::SKIPE	U,OPRLDB##	;GET OPERATOR LINE FROM ONCE
	JRST	TTYERX		;FINISH UP
TTYERC::			;SETUP FOR CTY TYPEOUT
IFN FTMP,<
	SKIPGE	U,BOOTCP##	;GET BOOT CPU NUMBER
	MOVE	U,.CPCPN##	;US IF NOT YET SETUP
	LSH	U,.CPSOF##	;MAKE CDB OFFSET FROM CPU0
	HRRZ	U,.C0CTN##(U)	;GET BOOT CTY LINE NUMBER
> ;END IFN FTMP
IFE FTMP,<
	HRRZ	U,.CPCTN##	;USE THE CTY LINE NUMBER
>
	MOVE	U,LINTAB##(U)	;AND POINT TO ITS LDB
TTYERX:	SE1ENT			;ENTER SECTION 1
	SKIPE	F,U		;U MAY BE ZERO IF LINTAB NOT SET UP
	HRRZ	F,LDBDDB(U)	;GET DDB ADR, IF ANY.
	POPJ	P,0		;AND RETURN FROM TTYERP


;SUBROUTINES TO SET UP LINE AND MAKE SURE ATTACHED.
;CALL WITH DDB SET UP, FROM UUO LEVEL ONLY.
;RETURN WHEN ATTACHED AND AT USER LEVEL, WITH LINE SET UP.

;ONE ROUTINE FOR INPUT, ONE FOR OUTPUT, ONE FOR OUTPUT AND USER LEVEL

CKATTI:
IFN FTRSP,<PUSHJ P,RSPTIR##>	;RECORD RESPONSE SATISFIED BY TTY INPUT UUO
CKATT0:	MOVSI	S,IO		;INDICATE INPUT
	ANDCAB	S,DEVIOS(F)	;SET UP STATUS WORD
	MOVE	U,DDBLDB(F)	;GET LINE BLOCK ADDR
	JUMPN	U,CKATI1	;IF THERE, GO ON
CKATIW:	MOVSI	S,IO+TTYOUW	;MUST WAIT FOR ATTACH
	ANDCAM	S,DEVIOS(F)	;CLEAR DIRECTION BIT
	MOVEI	S,IOACT		;AND SET WAIT BIT FOR INPUT
	IORB	S,DEVIOS(F)	; ..
	S0PSHJ	WSYNC##		;WAIT FOR ATTACH
	JRST	CKATT0		;GET LINE SET UP AND RETURN.

CKATI1:	MOVE	T1,DEVMOD(F)	;SEE IF TTY IS CONTROLLING JOB.
	TLNE	T1,TTYATC
	JRST	CKATI2		;YES.
	MOVSI	T1,LDLCOM	;NO. MAKE IT BE
	ANDCAM	T1,LDBDCH(U)	;AT USER LEVEL
CKATI2:	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TLNE	T1,LDLCOM	;AT COMMAND LEVEL?
	JRST	CKATIW		;YES. CAN'T DO INPUT.
	PUSHJ	P,TYIEAT	;NO. SKIP ANY COMMANDS
	PJRST	UUOLDB		;AND GO ADJUST LINE BITS.
CKATOU:	PUSHJ	P,CKATTO	;FIRST MAKE SURE A LINE ATTACHED TO DDB
	MOVE	T1,LDBDCH(U)	;DEVICE BITS
	TLNN	T1,LDLCOM	;IS LINE AT COMMAND LEVEL?
	POPJ	P,0		;NO. USER LEVEL. RETURN.
	MOVE	T1,DEVMOD(F)	;COMMAND LEVEL.  SEE IF CONTROLLER OR I/O DEVICE
	TLNN	T1,TTYATC	;..
	POPJ	P,0		;I/O DEVICE.  LET IT THROUGH.
	PUSHJ	P,TOWAT1	;CONTROLLER.  WAIT SO DON'T CLOBBER COMMANDS
	JRST	CKATOU		;THEN TRY AGAIN FOR USER LEVEL

CKATTO:	MOVSI	S,IO		;INDICATE OUTPUT
	IORB	S,DEVIOS(F)	;SET UP STATUS WORD
	MOVE	U,DDBLDB(F)	;GET LINE ADDR IF ANY
	JUMPN	U,UUOLDB	;IF HAVE ONE, SEE IF TOP LEVEL
CKATOW:	PUSHJ	P,TOWAT1	;WAIT FOR OUTPUT DONE. (WHICH
				; IS FORCED ON ATTACH)
	JRST	CKATTO		;AND SET UP LINE, TO RETURN.

UUOLDB::SE1ENT			;ENTER SECTION 1
	MOVE	T2,LDBOST(U)	;FOR TRACKING CHANGES
	MOVSI	T1,LOLPIM	;GET PIM MODE BIT
	TRNN	S,PIMMOD	;IS THIS PACKED IMAGE MODE?
	JRST	[ANDCAM	T1,LDBOST(U)	;NO, CLEAR BIT IN THE LDB
		 JRST	UUOLD2]		;AND CONTINUE
	TRZ	S,IOSABS	;NO BREAK SETS IF PIM
	TDNE	T1,LDBOST(U)	;IS IT ALREADY SET?
	JRST	UUOLD2		;YES, DON'T NEED TO DO THIS AGAIN
	SCNOFF			;NO, KEEP OTHERS OUT WHILE WE SET UP FOR PIM
	IORM	T1,LDBOST(U)	;YES, SET IN STATES WORD
	MOVE	T1,LDBTIP(U)	;GET PUTTER
	MOVEM	T1,LDBECT(U)	;ADVANCE ECHO TAKER
	MOVE	T1,LDBECC(U)	;COUNT OF UNECHOED CHARACTERS
	ADDM	T1,LDBTIC(U)	;UPDATE AS IF ECHOED
	MOVE	T1,LDBIEC(U)	;NOT-IN-STREAM UNECHOED CHARACTERS
	ADDM	T1,LDBIIC(U)	;UPDATE AS IF ECHOED
	SETZM	LDBECC(U)	;NO MORE TO BE ECHOED
	SETZM	LDBIEC(U)	;AND NO MORE CK.NIS TO BE ECHOED
	SCNON			;ALLOW OTHERS AGAIN
UUOLD2:	XOR	T2,LDBOST(U)	;GET CHANGE MASK
	TLNE	T2,LOLPIM	;DID WE CHANGE PIM STATUS?
	PUSHJ	P,SETCHP	;YES, POKE THE FRONT END
	MOVSI	T1,LDLBKM	;USER DEFINED BREAK SET IN USE BIT
	MOVE	T2,LDBBKB(U)	;FOR TRACKING CHANGES
	TRNE	S,IOSABS	;TERMINAL IN BREAK SET SPECIFIED MODE?
	JRST	[IORM	T1,LDBBKB(U)	;YES, LITE THE BIT IN THE LDB
		 JRST	UUOLD1]		; AND CONTINUE
	ANDCAM	T1,LDBBKB(U)	;CLEAR THE BIT IN THE LDB
UUOLD1:	XOR	T2,LDBBKB(U)	;GET CHANGE MASK
	TLNE	T2,LDLBKM	;DID WE CHANGE THE BREAK-SET BIT?
	PUSHJ	P,CHKBKC	;YES, GET BREAK COUNTS RIGHT
	MOVEI	T1,0		;MAKE LDB AGREE WITH S
	MOVE	T2,LDBDCH(U)	;REMEMBER OLD CHARACTERISTICS
	TLNE	T2,LDLCNE	;IF COMMAND-LEVEL NO ECHO,
	TLO	T1,LDLNEC	;SUPPRESS ECHOING
	TRNE	S,A8		;8-BIT ASCII MODE?
	TLO	T1,LDL8BI	;YES, 8-BIT INPUT MODE
	TRNE	S,IOSTEC	;TRUTH-IN-ECHOING SET?
	TLO	T1,LDLDLR	; YES
	TRNE	S,IOSFCS	;FULL-CHARACTER-SET SET?
	TLO	T1,LDLFCS	; YES
	TRNN	S,PIMMOD	;IS THIS PACKED IMAGE MODE?
	TRNE	S,IOSNEC	;OR NO ECHO BY PROGRAM?
	TLO	T1,LDLNEC	; YES
;THIS SHOULD NO LONGER BE NEEDED, ONLY TT?CHK SHOULD SET/CLEAR IT
;	TRNE	S,IOSBKA	;SINGLE CHARACTER MODE?
;	TLO	T1,LDLBKA	; YES
	IORM	T1,LDBDCH(U)	;SET THOSE NEEDING SETTING
;	TLC	T1,LDLNEC+LDLFCS+LDLDLR+LDLBKA+LDL8BI
	TLC	T1,LDLNEC+LDLFCS+LDLDLR+LDL8BI
	ANDCAB	T1,LDBDCH(U)	;AND CLEAR THE OTHERS
	CAME	T2,T1		;DON'T SEND STATUS IF NO CHANGE
	PJRST	SETCHP		;NOTE THAT TERMINAL CHARACTERISTICS CHANGED
	POPJ	P,		;NO CHANGE
;HERE FROM UUOCON WHEN A TTY HAS BEEN INITED.

TTYOPN::MOVE	U,DDBLDB(F)	;GET LDB ADDRESS
	JUMPE	U,TPOPJ1##	;FORGET IT IF DETACHED
	SE1JRST			;CAN'T USE SE1ENT BECAUSE OF CROCK
				; OF BEING CALLED WITH T1 ON THE STACK
	MOVSI	T2,LDLCOM	;GET COMMAND LEVEL BIT
	MOVSI	T1,TTYATC	;IS TTY CONTROLLING THE JOB?
	TDNN	T1,DEVMOD(F)	;OR IS IT AN I/O DEVICE?
	ANDCAM	T2,LDBDCH(U)	;I/O PUT IT AT USER LEVEL
	PUSHJ	P,UUOLDB	;SETUP THE LDB FROM S
	PUSHJ	P,SETCHP	;MAKE SURE THE FRONT END KNOWS ABOUT THIS
	JRST	@[0,,TPOPJ1##]	;AND RETURN IN SECTION 0 ALWAYS
;TWAITI  --  WAIT FOR INPUT (CHARACTER OR LINE MODE)

TWAITI:	TRNE	S,IOSBKA	;BREAK ON ALL CHARACTERS?
	JRST	TWAITC		;YES, WAIT FOR A SINGLE CHARACTER
				;FALL INTO TWAITL (EVEN FOR IMAGE MODES)

;TWAITL  --  WAIT FOR AN INPUT LINE

TWAITL:
	SKIPE	LDBTOC(U)	;IF NO OUTPUT IN PROGRESS,
	PUSHJ	P,PTBTCH##	;AND THIS IS NOT A PTY
	TRNA
	PUSHJ	P,TOWAT1
	PUSHJ	P,CLRPCT	;RESET THE "STOP" LINE COUNTER
	PUSHJ	P,CKATTI	;FIRST WAIT FOR ATTACH. SET DDB AND LINE
	PUSHJ	P,TTLCHK	;CHECK FOR A LINE BEING PRESENT
	  JRST	TWATLK		;BE SURE
	POPJ	P,		;LINE PRESENT, RETURN

TWATL1:	PUSHJ	P,TIWAIT	;NO. GO WAIT FOR ONE.
	TRNE	S,IODERR	;GOT A ^C?
	POPJ	P,		;YES, LINE PRESENT
	PUSHJ	P,CKATTI	;MAKE SURE DIDN'T DETACH DURING WAIT
	PUSHJ	P,TTLCHK
	  JRST	TWATLK
	POPJ	P,

TWATLK:	MOVE	S,[XWD IOW,IOACT]	;FLAG ACTIVE AND WAITING SO
	IORB	S,DEVIOS(F)	;INTERRUPT WILL NOT FIND HIM ACTIVE
	PUSHJ	P,TTLCHK	;BUT NOT WAITING.  THEN LOOK AGAIN
	  JRST	TWATL1		;NOTHING ARRIVED SINCE LAST TEST
	MOVE	S,[XWD IOW,IOACT]	;SOMETHING DID SNEAK IN!
	ANDCAB	S,DEVIOS(F)	;SO FORGET ABOUT WAITING
	POPJ	P,



;SUBROUTINE TO WAIT FOR SINGLE CHARACTER INPUT

TWAITC:
	SKIPG	LDBTOC(U)	;IF NO OUTPUT IN PROGRESS,
	PUSHJ	P,CLRPCT	;RESET THE "STOP" LINE COUNTER
	PUSHJ	P,CKATTI	;MAKE SURE ATTACHED
	PUSHJ	P,TTCCHK	;CHECK FOR A INPUT BEING PRESENT
	  JRST	TWATCK		;BE SURE
	POPJ	P,		;INPUT PRESENT, RETURN

TWATC1:	PUSHJ	P,TIWAIT	;NO. GO WAIT FOR ONE.
	TRNE	S,IODERR	;GOT A ^C?
	POPJ	P,		;YES, INPUT PRESENT
	PUSHJ	P,CKATTI	;MAKE SURE DIDN'T DETACH DURING WAIT
	PUSHJ	P,TTCCHK
	  JRST	TWATCK
	POPJ	P,

TWATCK:	MOVE	S,[XWD IOW,IOACT]	;FLAG ACTIVE AND WAITING SO
	IORB	S,DEVIOS(F)	;INTERRUPT WILL NOT FIND HIM ACTIVE
	PUSHJ	P,TTCCHK	;BUT NOT WAITING.  THEN LOOK AGAIN
	  JRST	TWATC1		;NOTHING ARRIVED SINCE LAST TEST
	MOVE	S,[XWD IOW,IOACT]	;SOMETHING DID SNEAK IN!
	ANDCAB	S,DEVIOS(F)	;SO FORGET ABOUT WAITING
	POPJ	P,
;TTICHK  --  CHECK IF ANY INPUT IS AVAILABLE, LINE OR CHARACTER MODE
;CALL IS:
;
;	PUSHJ	P,TTICHK
;	  NO INPUT AVAILABLE
;	INPUT IS AVAILABLE
;
;THE CALLER MUST SETUP U, F, AND S APPROPRIATELY (TTLCHK AND TTCCHK
;DON'T REQUIRE F AND S, BUT TTICHK DOES).
;
;TTLCHK IS THE ROUTINE THAT HANDLES REGULAR ASCII LINE MODE, AS
;AS THE IMAGE MODES, TTCCHK HANDLES ASCII CHARACTER MODE.

TTICHK:	TRNE	S,IOSBKA	;BREAK ON ALL CHARACTERS MODE?
	JRST	TTCCHK		;YES, LOOK FOR JUST A SINGLE CHARACTER
				;NO, FALL INTO TTLCHK (EVEN FOR IMAGE MODES)

;TTLCHK  --  CHECK IF AN INPUT "LINE" IS AVAILABLE

TTLCHK::PUSHJ	P,CLRBKA	;CLEAR BREAK ON ALL CHARACTERS BIT
TTLCK2:	TRNN	F,-1		;DO WE REALLY HAVE A DDB?
	SETZ	S,		;NO DDB, NO I/O STATUS
	SE1ENT			;ENTER SECTION 1
	PUSHJ	P,TICAVL	;ANY INPUTTABLE CHARACTERS?
	  TRNN	S,I!PIMMOD	;YES, IMAGE MODE OF SOME SORT?
	SKIPLE	LDBBKC(U)	;LINE MODE, ANY LINES AVAILABLE?
	JRST	CPOPJ1##	;INPUT AVAILABLE
	MOVE	T2,LDBTIC(U)	;GET CHARACTERS
	SUB	T2,LDBIIC(U)	;IGNORE THOSE NOT PRESENT
	PUSHJ	P,CHKTIF	;AT THE END OF A FIELD (USER SPECIFIED LINE)?
	  CAIL	T2,^D70		;NO, NO LINES, GOT LOTS OF CHARACTERS?
	JRST	CPOPJ1##	;YES, CLOSE ENOUGH, WAKE UP USER
	MOVSI	T2,L1LUNR	;UNREAD WAITING BIT
	TDNE	T2,LDBBYT(U)	;SEE IF TEMPORARILY ASYNCH
	JRST	CPOPJ1##	;YES, INPUT IS AVAILABLE
	MOVE	T2,LDBDCH(U)	;DEVICE BITS
	TLNE	T2,LDLIMI	;NO. IMAGE INPUT STATE?
	TLNN	S,FRCEND	;YES. ALSO TIMED OUT?
	PJRST	TTLWAK		;START DEFERED ECHO AND WAKE MIC IF NEEDED
	JRST	CPOPJ1##	;IMAGE TIME OUT, WAKE UP HIGHER-UPS

;TTCCHK  --  CHECK IF  AN ASCII CHARACTER IS AVAILABLE

TTCCHK:	PUSHJ	P,SETBKA	;SET "BREAK ON ALL CHARACTERS" IN LDB
	PUSHJ	P,TICAVL	;ANY REAL CHARACTERS AVAILABLE?
	JRST	CPOPJ1##	;YES, SKIP RETURN
	MOVSI	T1,L1LUNR	;UNREAD WAITING BIT
	TDNE	T1,LDBBYT(U)	;SEE IF TEMPORARILY ASYNCH
	JRST	CPOPJ1##	;YES, INPUT IS AVAILABLE
;	PJRST	TTCWAK		;START DEFERRED ECHO AND WAKE MIC IF NEEED

;TTCWAK -- WAKE MIC FOR CHARACTER MODE
;TTLWAK -- WAKE MIC FOR LINE MODE

TTCWAK:	TDZA	T1,T1		; CHARACTER MODE
TTLWAK:	MOVEI	T1,1		;LINE MODE
	PUSHJ	P,@[EXP <IFIW STRTDC>,<IFIW STRTDL>](T1) ;START DEFERRED ECHO
IFN FTMIC,<
	SKIPE	LDBMIC(U)	;MIC CONTROLLED TTY?
	PUSHJ	P,MICWAK	;WAKE UP MASTER MIC
>
	POPJ	P,		;RETURN

;TICAVL -- CHECK FOR AVAILABLE CHARACTERS IN LDBTIC
;NON-SKIP FOR YES,
;SKIP FOR DELAY
;USES T1

TICAVL::SE1ENT			;ENTER SECTION ONE
	SCNOFF			;NO INTERRUPTS WHILE LOOKING
	MOVE	T1,LDBTIC(U)	;GET INPUT COUNT
	CAMLE	T1,LDBIIC(U)	;MORE THAN DELETED?
	JRST	SONPPJ		;YES, RETURN SUCCESS IMMEDIATELY
	CAMN	T1,LDBIIC(U)	;SANITY CHECK, DO THEY MATCH?
	JRST	TICAV1		;STILL MIGHT BE SOME EXPANDING
	JUMPE	T1,INPCH1	;IF SHOULD BE ZERO, DO ALTERNATE SANITY CHECK
	STOPCD	.+1,INFO,TMDELI, ;++ TOO MANY <DEL>S IN INPUT
	MOVEM	T1,LDBIIC(U)	;MAKE COUNTS MATCH
	JRST	SONPJ1		;AND SEE WHAT HAPPENS
TICAV1:	MOVE	T1,LDBBY3(U)	;GET EXPANSION BITS
	TLNN	T1,L3LIHD!L3LIPD ;ARE WE EXPANDING INPUT?
	JRST	SONPJ1		;NO, NOTHING AVAILABLE
	JRST	SONPPJ		;YES, SOMETHING'S STILL THERE

;ECCAVL -- CHECK FOR INPUT AVAILABLE FROM ECHO STREAM
;NON-SKIP FOR YES,
;SKIP FOR DELAY
;USES T2

ECCAVL::SCNOFF			;NO INTERRUPTS WHILE LOOKING
	MOVE	T2,LDBECC(U)	;GET COUNT OF UNECHOED CHARACTERS
	CAMLE	T2,LDBIEC(U)	;MORE THAN DELETIONS?
	JRST	SONPPJ		;YES, GIVE AVAILABLE RETURN
	CAME	T2,LDBIEC(U)	;DO THEY MATCH?
	STOPCD	.+1,INFO,TMDELE, ;++ TOO MANY DELETIONS FROM ECHO
	MOVEM	T2,LDBIEC(U)	;MAKE THEM MATCH
	MOVE	T2,LDBBY3(U)	;GET EXPANSION BITS
	TLNE	T2,L3LEHD!L3LEPD ;ARE WE EXPANDING?
	JRST	SONPPJ		;STILL HAVE SOME IF SO
	JRST	SONPJ1		;SAY NONE AVAILABLE
;SUBROUTINE TIWAIT TO WAIT FOR SOME INPUT, AND SEND XON IF NEEDED.

TIWAIT:
IFN FTMIC,<			;IF MIC
	SKIPE	LDBMIC(U)	;MIC RUNNING FOR THIS LINE?
	PUSHJ	P,MICWAK	;YES, WAKE MIC IF NECESSARY
> ;END OF IF MIC
	MOVEI	T1,LDRPTY	;IS THIS LINE PTY-DRIVEN?
	TDNE	T1,LDBDCH(U)	;CHECK	IN THE LDB CHARACTERISTICS
	PUSHJ	P,PTYOW##	;YES. GO MARK THIS WAIT.
	MOVSI	S,IO+TTYOUW	;MARK DIRECTION AS INPUT.
	ANDCAB	S,DEVIOS(F)	;CLEAR IN CORE
	MOVEI	T1,IMGTIM	;TIMEOUT FOR IMAGE MODE
	TRNE	S,I		;TERMINAL IN IMAGE MODE?
	DPB	T1,LDPTIM	;YES. STORE TIMEOUT TIME
	PUSHJ	P,CHKXON	;SEND X-ON IF NEEDED
	S0JRST	WSYNC##		;WAIT FOR INPUT



;SUBROUTINE TO START DEFERRED ECHO
;CALL
;	MOVEI	T2,BIT (EITHER L1RDEL FOR LINE OR L1RDEC FOR CHARACTER)
;	PUSHJ	P,STRTDE
;	<ALWAYS RETURNS HERE>

STRTDC::SE1ENT			;ENTER SECTION 1
	MOVE	T2,[L1LUNR,,L1RDEC]	;THE ALLOW-ONE-CHARACTER-TO-ECHO BIT
	TDNN	T2,LDBBYT(U)	;IS BIT ALREADY SET, OR
	PUSHJ	P,TICAVL	;IF SOME CHARACTER(S) ALREADY ECHOED
	  POPJ	P,		;YES, DON'T ECHO ANY MORE
	JRST	STRTDE		;COMMON CODE

STRTDL::SE1ENT			;ENTER SECTION 1
	MOVE	T2,[L1LUNR,,L1RDEL]	;THE ALLOW-ONE-LINE-TO-ECHO BIT
	TDNN	T2,LDBBYT(U)	;IS IT ALREADY SET, OR
	SKIPLE	LDBBKC(U)	;ARE ANY LINES AVAILABLE?
	POPJ	P,		;YES, DON'T ECHO ANY MORE

STRTDE::SE1ENT			;ENTER SECTION 1
	HRRZS	T2		;GET RID OF L1LUNR
	IORM	T2,LDBBYT(U)	;SET BIT ALLOWING LINE OR CHARACTER
	MOVEI	T2,L1RDEM	;GET DEFERRED ECHO MODE BIT
	SKIPL	LDBBKB(U)	;BREAK MASK IS ALWAYS DEFERRED
	TDNE	T2,LDBBYT(U)	;DEFERRED?
	SKIPG	LDBECC(U)	;AND INPUT WAITING?
	PJRST	CHKXON		;NOT DEFERRED, OR NO INPUT WAITING
				; MAKE SURE WE ARE ACCEPTING INPUT
	PJRST	TOPOKE		;GET OUTPUT STARTED
;ROUTINE TO CHECK IF AN XOFF HAS BEEN SENT OUT
;AND IF SO, TO SEND AN XON.
;CALLED BY:
;	PUSHJ	P,CHKXON
;	RETURN HERE ALWAYS (CLOBBERS T1,T3)


CHKXON::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,LPLXOF	;IS PAGE MODE ENABLED?
	TDNN	T1,LDBPAG(U)	;GUARANTEE XON IF TALKING TO
				;ANOTHER COMPUTER
	POPJ	P,		;XON IS NOT NEEDED

CHKXN1:	MOVE	T1,LDBTIC(U)	;GET # OF INPUT CHARS
	ADD	T1,LDBECC(U)	;PLUS THOSE TO BE ECHOED
	CAILE	T1,^D80		;TOO MANY?
	POPJ	P,		;YES, GO AWAY
	MOVSI	T1,LPLXOF	;CLEAR XOFF BIT
	ANDCAM	T1,LDBPAG(U)	;SO ONLY ONE XON IS SENT
	MOVEI	T3,IRRCSA	;CODE FOR CHUNK SPACE AVAILABLE (SEND XON)
	MOVEI	T1,ISRREM	;INDEX FOR REMOTE HANDLER
	PUSHJ	P,@LDBISR(U)	;TRY TO CRANK IT UP AGAIN
	  SKIPA	T2,FLPXON	;NON-SKIP MEANS WE MUST SEND THE XON
	PJRST	TOPOKE		;XON ALREADY SENT, JUST QUEUE THE TERMINAL
	PUSHJ	P,SETXNP	;SET THE XON FILLER
	PJRST	TOPOKE		;START TERMINAL MOVING

;ROUTINE TO GET DDB OUT OF TI WAIT IF NEEDED
;CALLED BY:
;	MOVE	J,JOB #
;	PUSHJ	P,CLRTI
;	RETURN	HERE
;RESPECTS	T1,T2
CLRTI::	PUSH	P,T1		;SAVE SOME AC'S
	PUSH	P,T2
	LDB	T1,PJBSTS##	;GET WAIT STATE CODE
	CAIE	T1,TIOWQ##	;IN TI WAIT?
	JRST	CLRTI1		;NO--EXIT
	PUSHJ	P,TTYSRC	;FIND TTY DDB
	  JRST	CLRTI1		;NO DDB?
	MOVE	T1,[IOW,,IOACT]
	ANDCAM	T1,DEVIOS(F)
CLRTI1:	POP	P,T2
	JRST	TPOPJ##
IFN FTMSGSER,<
;SUBROUTINE TO RETURN TTY OUTPUT FEASIBILITY FOR A MPX-CONTROLLED TTY
;CALL WITH F/ADDRESS OF TTY DDB
;RETURN WITH T1/0 IF NO OUTPUT OR 1 IF OK TO OUTPUT

TTYOFE::SE1ENT			;ENTER SECTION 1
	MOVE	T2,DDBLDB(F)	;ADDRESS OF TTY LDB
	MOVE	T1,LDBTOC(T2)	;COUNT OF OUTPUT CHARACTERS STILL WAITING
	HLL	T1,LDBOST(T2)	;STATE BITS
	TDNE	T1,[LOLSTP+777740]  ;IF ^S'ED OR MORE THAN 32 CHARACTERS
	TDZA	T1,T1		;SAY OUTPUT NOT FEASIBLE
	MOVEI	T1,1		;OTHERWISE GIVE GO AHEAD
	POPJ	P,		;RETURN TO MSGSER


;SUBROUTINE TO INITIALIZE TTY-SPECIFIC VALUES WHEN CONNECTING A TTY TO AN
;MPX CHANNEL
;CALL WITH F/ADDRESS OF TTY DDB
;RETURN CPOPJ ALWAYS

TTYMPX::SE1ENT			;MAY NEED TO REFERENCE LDB
	PUSH	P,U		;PRESERVE LDB AC
	PUSH	P,F		;AND DDB AC (LH JUNK)
	HRRZS	F		;CLEAR LH FOR NZS INDEXING
	SETZM	DEVXTR(F)	;DISCARD PARTIAL OUTPUT BUFFER
	MOVE	S,DEVIOS(F)	;GET I/O MODE
	TRNN	S,I		;IMAGE MODE?
	JRST	FUPOPJ##	;NO, NOTHING ELSE TO DO
	MOVEI	T1,ASSCON	;ASSIGNED-BY-CONSOLE BIT
	TDNN	T1,DEVCHR(F)	;IS IT LIT?
	JRST	TTYMPE		;NO, DON'T LIGHT LDLIMI (IMAGE NOT ALLOWED)
	MOVE	U,DDBLDB(U)	;POINT TO LDB
	MOVSI	T1,LDLIMI	;GET IMAGE MODE BIT
	IORM	T1,LDBDCH(U)	;SET IN LDB
	PUSHJ	P,SETCHP	;INFORM FE'S
	JRST	FUPOPJ##	;RETURN TO MSGSER

TTYMPE:	MOVEI	S,IOIMPM	;ERROR FOR IMAGE MODE NOT ALLOWED (SEE TTYINE)
	IORB	S,DEVIOS(F)	;SET IT FOR MSGSER TO SEE
	JRST	FUPOPJ##	;RETURN TO MSGSER
> ;END IFN FTMSGSER
;ROUTINE TO PUT SIXBIT NAME IN DEVNAM(DDB), AND TO SET PUNIT.

;CALL:	SET DDB TO DEVICE DATA BLOCK TO RECEIVE THE NAME AND UNIT
;	SET LINE TO LINE DATA BLOCK WHERE LINE NUMBER WILL BE FOUND
;	AND SET OR CLEAR IMAGE BIT IN DEVMOD DEPENDING ON
;	WHETHER THIS LINE WILL BE PTY-DRIVEN OR NOT
;	PUSHJ P,SCNNAM
;	RETURN
;CLOBBERS T1 AND T3


SCNNAM:	PUSH	P,T2		;SAVE T2
	PUSHJ	P,TTYNAM	;BUILD NAME OF DEVICE
	MOVEM	T2,DEVNAM(F)	;STORE IN DDB
	POP	P,T2		;RESTORE T2
	LDB	T1,LDPLNO	;GET PHYSICAL LINE NUMBER
	DPB	T1,PUNIT##	;AND STORE IT IN THE DDB
	SETZM	DEVSTS(F)
	MOVEI	T3,<1_I>	;GET IMAGE MODE BIT.
	IORM	T3,DEVMOD(F)	;SET IT IN THE DDB
	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS THIS A PTY?
	ANDCAM	T3,DEVMOD(F)	;YES. CLEAR THE BIT.
	POPJ	P,0		;RETURN FROM SCNNAM


;SUBSIDIARY ROUTINE TO DO RADIX PRINT TO CORE.

SCNNMR:	IDIVI	T1,10		;DEVICE NAMES ARE OCTAL
	HRLM	T1+1,0(P)	;STORE A DIGIT ON STACK
	SKIPE	T1		;NEED MORE DIGITS?
	S0PSHJ	SCNNMR		;YES. GO MAKE THEM.
	HLRZ	T1,0(P)		;RETRIEVE A DIGIT FROM STACK
	ADDI	T1,"0"-40	;CONVERT TO SIXBIT
	IDPB	T1,T3		;STORE IN OBJECT WORD (DEVNAM)
	POPJ	P,0		;POP UP TO SCNNMR OR BACK TO SCNNAM
IFN FTNET,<

;ROUTINE TO LOCATE A NEW TTY DDB

SETSTA:	PUSHJ	P,FNDSTA	;FIND STATION
	DPB	T1,PDVSTA##	;PUT STA # IN DEVICE LOC FIELD
	POPJ	P,		;RETURN

FNDSTA::SE1ENT			;ENTER SECTION 1
	MOVE	T1,LDBDCH(U)	;GET TTY BITS
	TRNN	T1,LDRPTY	;TERMINAL A PTY LINE?
	JRST	DDBRL		;NO - BRANCH FOR REAL TERMINAL
	LDB	T1,LDPLNO	;YES, GET LINE NUMBER ONLY
	SUBI	T1,PTYOFS##	;DECREMENT TO PTY LINE NUMBER
	PUSH	P,F		;SAVE TTY DDB FOR A SECOND
	MOVE	F,PTYTAB##(T1)	;GET PTY DDB
	LDB	T1,PDVSTA##	;GET LOCATION OF PTY
	JRST	FPOPJ##		;RESTORE TTY DDB AND RETURN TO CALLER

DDBRL:	SKIPL	LDBTTW(U)	;ANF NETWORK TERMINAL?
		.CREF	LTLANF	;(CREF REFERENCE TO REAL SYMBOL)
	JRST	DDBRL1		;NO, MUST BE A LOCAL TERMINAL
	LDB	T1,LDPRNN	;YES, GET THE REMOTE NODE NUMBER
	JUMPE	T1,DDBRL1	;LOCAL(?)
	POPJ	P,		;RETURN.

DDBRL1:	MOVEI	T1,LOCSTA##	;LOCAL STATION
	POPJ	P,		;RETURN


>
;ROUTINE TO RESET DEVOPR TO THE CTY IF A REMOTE LINE
;THIS IS USED BY ROUTINES WHICH MIGHT DETACH OR HOST
;AWAY A REMOTE LINE WHEN THAT LINE WAS DEVOPR.
;CALL:	MOVE	U, LDB ADDRESS
;	PUSHJ	P,TTYOPR
;PRESERVES ALL ACS EXCEPT T1

TTYOPR::JUMPE	U,CPOPJ##	;RETURN IF NO LDB
	MOVSI	T1,LTLREM	;REMOTE BITS
	CAMN	U,OPRLDB##	;CURRENT LINE DEVOPR?
	TDNN	T1,LDBTTW(U)	;AND REMOTE?
	POPJ	P,		;NOT OPR OR HARDWIRED LINE
	PUSH	P,U		;SAVE U
	PUSH	P,T2		;SAVE T2
	MOVE	U,BOOTCT##	;CURRENT CTY LINE NUMBER
	MOVE	U,LINTAB##(U)	;GET ITS LDB ADDRESS
	MOVE	T1,@LDBDDB(U)	;AND DEVICE NAME
	PUSHJ	P,STDOPR	;SET DEVOPR, NETOPR
	  JFCL			;CAN'T FAIL
	POP	P,T2		;RESTORE T2
	POP	P,U		;RESTORE U
	POPJ	P,		;RETURN


;ROUTINE TO ESTABLISH DEVICE OPR IF POSSIBLE
;CALL:	MOVE	T1,DEVICE NAME
;	PUSHJ	P,STDOPR
;RETURN CPOPJ IF ILLEGAL
;SKIP RETURN WITH DEVICE CHANGED
STDOPR::PUSHJ	P,TTYPHY	;LOOK FOR THIS PHYSICAL NAME
	  POPJ	P,		;FAILED IF NOT POSSIBLE
	MOVEM	U,OPRLDB##	;SAVE NEW LDB ADDRESS
	MOVEM	T1,DEVOPR##	;SAVE NEW NAME
	JRST	NETOPR##	;TELL NETWORK THAT OPR CHANGED
	SUBTTL	ROUTINES FOR PTY

;PTYPUT IS CALLED FROM PTYSER TO PLACE A CHARACTER IN A TERMINAL INPUT
;BUFFER AS THOUGH THE TERMINAL HAD BEEN TYPED ON. NO ECHOING IS ALLOWED,
;THOUGH AND THIS ROUTINE IS A SIMPLIFIED VERSION OF RECINT AND
;XMTECH, TO MAKE THE CHARACTERS VISIBLE TO THE CONTROLLED JOB WITHOUT ECHOING
;CALL
;	MOVE	T3,CHAR
;	MOVE	T1,CHAR BITS FROM SPCHEK
;	PUSHJ	P,PTYPUT
;	  ERROR	RETURN
;	  NORMAL RETURN

CNTRLO==17
PTYPUT::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##	;PRESERVE P1
	MOVSI	P1,LDLFSP	;THE FULL-SCNSER-SERVICE BIT
	TDNE	P1,LDBTTW(U)	;IS THIS PTY BEING A TTY?
	JRST	PTYPT1		;YES, LET SCNSER DO CHARACTER HANDLING
	TLNE	T1,CHALT	;POSSIBLE ALTMODE?
	PUSHJ	P,RIALTO	;YES, CONVERT IF WANTED
	MOVE	P1,T1		;SAVE BITS IN P1
	CAIN	T3,CNTRLO
	PJRST	FLPCNO
IFN FTMIC,<			;IF MIC
	SKIPE	LDBMIC(U)
	CAIE	T3,1		;CONTROL A COUNTS AS ^C TO MIC
> ;END OF IF MIC
	CAIN	T3,3		;CONTROL C?
	JRST	PTYCC		;YES. SPECIAL CHECKING
	CAIN	T3,"T"-100
	JRST	PTYCT
PTYINA:
	MOVSI	T2,L2LCCS	;NOT CONTROL C, SO
	ANDCAM	T2,LDBBY2(U)	;CLEAR SYNC BIT
IFN FTMIC,<			;IF MIC
	SKIPE	T2,LDBMIC(U)
	JRST	PTYMCK
> ;END OF IF MIC


;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

PTYPT1:	MOVE	T2,LDBTIC(U)	;IS THIS LINE ALREADY FULL?
	CAIG	T2,^D200	; ..
	SKIPG	TTFREN##	;OR LISTS EXHAUSTED?
	POPJ	P,0		;YES. DISCARD CHAR
	SKIPN	TTFTAK		;ANY FREELIST
	POPJ	P,0		;NO--PUNT
	AOS	(P)		;GOING TO GIVE GOOD RETURN NOW
	MOVSI	T2,LDLFSP	;THE FULL-SCNSER-PTY BIT
	TDNE	T2,LDBTTW(U)	;IS THIS UNDER FULL SCNSER CONTROL?
	PJRST	RECPTY		;YES, ENTER AT THE TOP
IFN FTMIC,<			;IF MIC
	MOVE	T1,P1		;SETUP CHARACTER BITS FOR MICECH
	SKIPE	LDBMIC(U)
	PUSHJ	P,MICECH	;SAY COL1 TO MIC
> ;END OF IF MIC
	SCNOFF			;NO INTERRUPTION
	STCHK	T3,LDBTIP(U),SONPPJ  ;STORE CHARACTER
	TLNE	P1,CHBRK	;IS THIS A BREAK CHARACTER?
	PUSHJ	P,SETBKU	;YES, STORE LAST BREAK POINTER
	LDCHK	T3,LDBECT(U),PTYPT5  ;TAKE CHARACTER NEEDING ECHO
	TLNE	P1,CHBRK	;BREAK CHAR?
	AOS	LDBBKC(U)	;YES. COUNT BREAKS
	AOS	T2,LDBTIC(U)	;ADVANCE TYPEIN COUNT
PTYPT5:	SCNON			;ALLOW INTERRUPTS AGAIN
	MOVE	T4,LDBDCH(U)	;GET DEVICE FLAGS
	TLNE	T4,LDLBKA	;TERMINAL IN BREAK-ON-ALL MODE?
	PUSHJ	P,RCVWKQ	;YES. WAKE JOB IF WAITING
	PUSHJ	P,CHKTIB	;ENOUGH TO WAKE ON?
	  TLNE	P1,CHBRK	;OR A BREAK CHARACTER?
	PUSHJ	P,ECHBRK	;YES. WAKE THE JOB
	POPJ	P,		;SUCCESSFUL RETURN TO PTYSER
;MORE OF PTYPUT. SPECIAL CODE FOR CONTROL C

PTYCC:
IFN FTMIC,<			;IF MIC
	PUSH	P,P1		;SAVE CHARACTER BITS (USED BY MICPRC)
	SKIPE	T1,LDBMIC(U)	;MIC CONTROLLED?
	PUSHJ	P,MICPRC	;YES. LET MIC KNOW
	POP	P,P1		;RESTORE POSSIBLY UPDATED CHARACTER BITS
> ;END OF IF MIC
	PUSHJ	P,RIDLN		;YES. DO SO.
	  JFCL			;DON'T CARE IF ANY WERE ECHOED
	MOVSI	T1,L2LCCS	;SECOND CONTROL C?
	TDNE	T1,LDBBY2(U)	; ..
	PUSHJ	P,CNCCHK	;YES. FORCE CONTROL C IF POSSIBLE
	  JRST	PTYCC1		;NOT SECOND--GO SET BIT
	  JRST	PTYCC4		;NO. (JACCT) JUST PASS THE CHARACTER
	PUSHJ	P,TSETI1	;YES. CLEAR BUFFERS
	PUSHJ	P,TSETBO	; ..
	JRST	CPOPJ1##

PTYCC4:	PUSHJ	P,TTHALT	;FORCE .HALT COMMAND
PTYCC1:	MOVSI	T1,L2LCCS	;SET "^C LAST IN" BIT
	IORM	T1,LDBBY2(U)	;SET BIT FOR NEXT TIME
	JRST	PTYPT1		;AND GO STORE CONTROL C IN INPUT BUFFER


;HERE ON ^O TO PTY

FLPCNO:	MOVEI	T1,LDROSU	;FLIP THE ^O BIT WHEN PTY OR REMOTE
	XORM	T1,LDBDCH(U)	;SENDS ^O
	PUSHJ	P,TSETBO	;CLEAR THE OUTPUT BUFFER
	PJRST	XMTWAK		;WAKE JOB IF IN OUTPUT WAIT
PTYCT:	PUSHJ	P,DOCTLT
	  JRST	PTYINA
	  JRST	TTFRC1
	JRST	CPOPJ1##
;SUBROUTINE TO SET DEFAULT TERMINAL CHARACTERSTICS
;CALLING SEQUENCE:
;	MOVEI	T1,TERMINAL TYPE
;	MOVE	U,ADDRESS OF THE LDB
;	PUSHJ	P,SETTTC
;	ALWAYS RETURN HERE

SETTTC::SE1ENT			;ENTER SECTION 1
	MOVE	T2,T1
	JUMPGE	T1,SETTT1	;CUSTOMER DEFINED TYPE ?
	MOVNS	T2		;YES
	TRO	T2,100		;CUSTOMER TYPES ARE 101-177
SETTT1:	DPB	T2,LDPTTT	;STORE TERMINAL TYPE
	LSH	T1,1		;2 WORDS PER ENTRY
	LDB	T2,TTPWID##	;WIDTH
	DPB	T2,LDPWID	;STORE THAT
	LDB	T2,TTPLNB##	;LENGTH
	DPB	T2,LDPLNB	;SET TTY LENGTH NN
	DPB	T2,LDPSTB	;SET TTY STOP NN
	MOVSI	T3,LPLSBL	;TTY SBELL
	CAIE	T2,0		;IF A PAGE SIZE SPECIFIED,
	IORM	T3,LDBPAG(U)	;THEN SET SBELL
	LDB	T2,TTPFLC##	;FILLER CLASS
	DPB	T2,LDPFLC	;STORE THAT
	LDB	T2,TTPFRM##	;FORM FEED
	DPB	T2,LDPFRM	;STORE THAT
	LDB	T2,TTPTAB##	;TABS
	DPB	T2,LDPTAB	;STORE THAT
	LDB	T2,TTPLCT##	;LOWER CASE
	DPB	T2,LDPLCT	;STORE THAT
	LDB	T2,TTPALT##	;ALTMODE CONVERSION
	DPB	T2,LDPALT	;STORE THAT
	LDB	T2,TTPDIS##	;GET DISPLAY SETTING
	DPB	T2,LDPDIS	;STORE THAT
	LDB	T2,TTPXNF##	;XONOFF
	DPB	T2,LDPXNF	;STORE THAT
	LDB	T2,TTP8BT##	;EIGHTBIT
	DPB	T2,LDP8BT	;STORE THAT
	LDB	T2,TTPNFC##	;NO CRLF
	DPB	T2,LDPNFC	;STORE THAT
	POPJ	P,		;RETURN
;NET-RELATED LDB MANAGEMENT

IFN FTNET,<

;GETLDB ROUTINE TO SEARCH FOR A FREE DDB/LDB FOR ANF/NRT/LAT/ETC.
;CALL	MOVSI	T1,LTL???	;SERVER-TYPE (LTLREM-BITS)
;	MOVEI	T3,<ADDRESS OF ISR DISPATCH TABLE>
;	PUSHJ	P,GETLDB
;RETURN	CPOPJ			;NO TERMINALS FREE
;	CPOPJ1			;FOUND A FREE LDB/DDB U=LDB

GETLDB::MOVSI	T2,LTLUSE	;THE LINE-IN-USE FLAG
	SKIPA	T4,NETRTY##	;GET THE POINTER TO THE REMOTE LDBS

;LOOP LOOKING FOR A FREE LDB

GETLD0:	SCNON			;FREE UP THE INTERLOCK
GETLD1:	MOVE	U,LINTAB##(T4)	;GET THE LDB POINTER
	TDNN	T2,LDBTTW(U)	;IS THIS LINE IN USE?
	JRST	GETLD4		;NO, TRY TO GRAB IT
	AOBJN	T4,GETLD1	;YES, KEEP LOOKING FOR A FREE LINE
	POPJ	P,		;FAILURE RETURN, NO FREE LDBS

GETLD4:	SCNOFF			;NOW IS A GOOD TIME TO INTERLOCK THIS
	TDNE	T2,LDBTTW(U)	;IS LDB REALLY HONESTLY AND TRULY FREE?
	JRST	GETLD0		;NO - FOOLED YOU!
	IOR	T1,T2		;MAKE NEW OWNERSHIP FLAGS
	MOVSI	T2,LTLREM	;ALL FORMS OF POSSIBLE OWNERS
	ANDCAM	T2,LDBTTW(U)	;CLEAR OUT OLDE OWNERSHIP INFO
	IORM	T1,LDBTTW(U)	;MARK IN USE BY NEW OWNER
	HRRM	T3,LDBISR(U)	;NEW DISPATCH TABLE
	SCNON			;CLEAR INTERLOCK
	SETZM	LDBREM(U)	;CLEAR ANF WORDS
	SETZM	LDBREM+1(U)	;..
	SETZM	LDBREM+2(U)	;..
	SETZM	LDBREM+3(U)	;..
	SETZM	LDBREM+4(U)	;..
IFN FTDECN!FTENET,<SETZM LDBNRT(U)>	;CLEAR NRT/CTERM/LAT WORD
	SETZM	LDBPBK(U)	;CLEAR THE PIM BREAK SET TOO!
	SETZM	LDBISB(U)	;CLEAR THE BAUD SPEED AND FLAGS
	SETO	T1,		;WE CAN RUN ON ANY CPU.  USE -1 FOR NOW
	DPB	T1,LDPCPU	;IN LDB
	PUSHJ	P,LDBCLR	;CLEAR OUT MOST OF THE REST OF THE LDB
	PJRST	CPOPJ1##	;SUCCESS RETURN WITH U=LDB
;STILL IFN FTNET

;FRELDB ROUTINE TO RETURN ANF/NRT/LAT/ETC. LDB TO FREE POOL

FRELDB::MOVEI	T1,APCUNK	;GET UNKNOWN STATUS CODE
	DPB	T1,LDPAPC	;SET ASYNC PORT CHARACTERISTICS
	MOVSI	T1,LTLUSE	;THE LDB-IN-USE FLAG
	TDNN	T1,LDBTTW(U)	;WAS LDB REALLY IN USE?
	STOPCD	.+1,DEBUG,LDBNIU;++LDB NOT IN USE

;BEFORE BLASTING THE LDB, MAKE SURE NO ONE ELSE IS TRYING TO USE IT FOR
;ANYTHING - E.G., THAT A LAT TERMINAL IS NOT ANF-SET-HOSTED AWAY

	SKIPGE	LDBREM(U)	;IS THIS TERMINAL VTM'ED AWAY?
	PJRST	VTMFRE##	;YES, MUST ALLOW NETVTM TO CLEAN UP FIRST
				; (AFTER NETVTM HAS DISCONNECTED IT WILL
				;  COME BACK TO FRELDB AGAIN)

;LDB HAS NO OUTSTANDING LIENS, MARK IT AS DEFUNCT

	ANDCAM	T1,LDBTTW(U)	;MARK THE LDB AS FREE NOW
	POPJ	P,		;AND THAT'S THAT

> ;END IFN FTNET
;DETLDB ROUTINE TO DETACH A TERMINAL FROM THE JOB
;	(USUALLY CALLED PREPARATORY TO CALLING FRELDB)
;CALL	MOVEI	U,LDB
;	MOVEI	T1,ERRORCODE
;	PUSHJ	P,DETLDB
;RETURN	CPOPJ

DETLDB::PUSH	P,F		;SAVE F
	HRRZ	F,LDBDDB(U)	;GET THE DDB
	JUMPE	F,DETLD3	;EXIT IF NO DDB
	LDB	J,PJOBN##	;GET THE JOB NUMBER
	MOVE	T2,DEVMOD(F)	;CHARACTERISTICS
	TLNE	T2,TTYATC	;CONSOLE TERMINAL?
	JRST	DETLD1		;YES, DETACH IT
	MOVEI	S,IOIMPM!IODERR!IODTER!IOBKTL	;ERROR BITS
	IORB	S,DEVIOS(F)	;LITE THEM FOR THE OWNER OF THIS TERMINAL
	DPB	T1,PDVESE##	;STORE EXTENDED I/O STATUS CODE
	JRST	DETLD2		;DON'T DETACH TERMINAL USED AS AN I/O DEVICE

DETLD1:	MOVEI	T1,TTFCXD	;NOW FORCE A
	PUSHJ	P,TTFORC	;.BYE COMMAND
DETLD2:
IFN FTPI,<PUSHJ	P,PSIDWN##>	;SIGNAL DEVICE DOWN
DETLD3:	PUSHJ	P,TSETBI	;CLEAR OUT INPUT CHUNK STREAM
	PUSHJ	P,TSETBO	;CLEAR OUT OUTPUT CHUNK STREAM
	JRST	FPOPJ##		;EXIT
;HERE TO CLEAR OUT CHARACTER AND CHUNK PARAMETERS FOR LDBINI AND VTMLOC

LDBVRS::SCNOFF			;SET INTERLOCK WHILE MUNGING ON THE CHUNKS
	PUSHJ	P,TYIVRG	;INITIALIZE INPUT CHUNK STREAM
	PUSHJ	P,TYEVRG	;INITIALIZE ECHO CHUNK STREAM
	PUSHJ	P,TYOVRG	;INITIALIZE OUTPUT CHUNK STREAM
	SCNON			;ALL SET
	PUSHJ	P,TSETBI	;CLEAR INPUT BUFFER
IFN FTMIC,<SETZM LDBMIC(U)>	;CLEAR MIC WORD
	PUSHJ	P,CLRCSB	;NO SPECIAL CHARACTER STATUS
	SETZM	LDBCHM(U)	;CLEAR OUT ANY OLD VALUES
	MOVEI	T1,21		;CTRL-Q
	DPB	T1,LDPUNP	;UNPAUSE CHARACTER
	MOVEI	T1,33		;ESCAPE
	DPB	T1,LDPESC	;THE ESCAPE CHARACTER
	MOVEI	T1,34_8!15	;^\^M
	DPB	LDPSWI		;THE DEFAULT SWITCH SEQUENCE
	POPJ	P,		;RETURN
;TWO SUBROUTINES TO INITIALIZE THE LDB. LDBCLR SETS UP THE BITS FROM
;INITIAL STATE FOUND IN LINTAB, THEN FALLS INTO LDBINI. LDBINI JUST
;CLEARS AS REQUIRED ON 140 RESTART.
;BOTH SHOULD BE CALLED WITH LINE SET UP.

LDBCLR::SE1ENT			;ENTER SECTION 1
	LDB	T2,LDPLNO	;GET LINE NUMBER
	MOVEI	T1,PTYLTB##	;GET PTY 'LINTAB' BITS
	CAIG	T2,TCONLN##	;IF NOT A PTY,
	MOVEI	T1,CTYLTB##	;GET CTY 'LINTAB' BITS
	CAIGE	T2,FRCLIN##	;IF NOT FORCELINE, A CTY, OR A PTY,
	MOVEI	T1,TTYLTB##	;THEN GET TTY 'LINTAB' BITS
	CAIN	T2,FRCLIN##	;IF FORCELINE,
	SETZ	T1,		;SET NO BITS
	CAIL	T2,M.TLTL##	;IS IT A LOCAL LINE?
	JRST	LDBCL1		;NO, DON'T CHECK FOR DATASETS
	LSHC	T2,-5		;YES, SPLIT APART WORD & BIT NUMBERS
	LSH	T3,-^D<36-5>	;RIGHT-JUSTIFY BIT INDEX
	MOVE	T3,BITTBL##(T3)	;GET ACTUAL BIT
	TDNE	T3,DSDTAB##(T2)	;IS THIS LINE A DATASET?
	TRO	T1,TTVDSD##	;YES, TURN ON 'LINTAB' DATASET BIT
LDBCL1:	DPB	T1,LDPVR2	;STORE THEM AROUND THE LDB
	LSH	T1,-5		; ..
	DPB	T1,LDPVR1	; ..
	LSH	T1,-6		; ..
	DPB	T1,LDPFLC	;LAST IS THE FILLER CLASS
	MOVSI	T1,LTLREM!LTLUSE!LDLFSP	;INITIALLY UNKNOWN TERMINAL TYPE
	ANDM	T1,LDBTTW(U)
	MOVEI	T1,APCUNK	;WITH UNKNOWN APC CHARACTERISTICS
	DPB	T1,LDPAPC	; . . .
	SETZM	LDBATR(U)	;AND NO KNOWN ATTRIBUTES
LDBINI::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,LDBCMR+LDBCMK;CLEAR COMMAND REQUEST BITS
	ANDCAM	T1,LDBCOM(U)	;IN LINE DATA BLOCK
	MOVE	T1,[LDIBCM]
	ANDCAM	T1,LDBBYT(U)	;CLEAR MOST BYTES
	MOVE	T1,LDIDCM	;CLEAR DEVICE CHARACTERISTICS
	ANDCAM	T1,LDBDCH(U)	; AS APPROPRIATE
	MOVSI	T1,LDLIDL	;GET THE IDLE BIT
	IORM	T1,LDBDCH(U)	;WHICH SHOULD NORMALLY BE SET
	MOVEI	T1,TTYWID##	;INITIAL VALUE OF TERMINAL WIDTH
	DPB	T1,LDPWID	;STORE IN LDB
	MOVSI	T1,L2LCLR	;CLEAR NECESSARY BITS IN LDBBY2
	ANDCAM	T1,LDBBY2(U)	; ..
	SETZM	LDBBY3(U)	;KEEP NOTHING HERE
	LDB	T3,LDPLNO	;COPY LINE NUMBER
	MOVSI	T1,LDLCOM	;ASSUME AT COMMAND LEVEL
IFN FTKS10,<
	MOVSI	T2,LILCFE	;CLEVER BIT
	CAIGE	T3,M.DZNL##	;IS THIS A DZ11 LINE ?
	IORM	T2,LDBISB(U)	;IS DZ11 LINE
>;IFN FTKS10

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

	CAMN	T3,BOOTCT##	;THIS THE CTY
	TRO	T1,LDRCTY	;YES--SET CTY BIT
	CAILE	T3,TCONLN##	;ABOVE TCONLN?
	TRO	T1,LDRPTY	;YES. SET PTY BIT
	IORM	T1,LDBDCH(U)	;PUT THESE BITS IN THE LDB
	MOVEI	T1,TTYLCT##	;GET APPROPRIATE LCT BIT
	CAIL	T3,FRCLIN##	;IS IT A TTY?
	MOVEI	T1,CTYLCT##	;NO, USE CTY BIT
	CAILE	T3,TCONLN##	;A PTY?
	MOVEI	T1,PTYLCT##	;YES, USE PTY DEFAULT
	CAIE	T3,FRCLIN##	;UNLESS FORCELINE,
	DPB	T1,LDPLCT	;MAYBE SET TTY UC
	MOVE	T1,[LPGCLI]	;LDBPAG BITS TO BE CLEARED
	ANDCAM	T1,LDBPAG(U)	;...
	MOVSI	T1,LPLXNF	;INITIALIZE TERMINAL TO HANDLE XON/XOFF
	IORM	T1,LDBPAG(U)	;...
	SETZM	LDBLSW(U)	;NO IDEA OF TERMINAL LENGTH/STOP PARAMETERS
	MOVSI	T1,LPLALT	;THE ALTMODE-CONVERSION BIT
	XCT	TTDALT##	;IORM OR ANDCAM DEPENDING ON DEFAULT
				; FOR TERMINAL ALT (SEE COMDEV)
	MOVSI	T3,L1LOFL	;OFF LINE BIT
	MOVEI	T1,ISROFL
	PUSHJ	P,@LDBISR(U)
	IORM	T3,LDBOFL(U)
	PUSHJ	P,LDBVRS	;CLEAR OUT SOME CHUNK AND CHARACTER PARAMETERS
	;PJRST	APCSET		;SET THE ASYNC PORT CHARACTERISTICS AND RETURN
	SUBTTL	SET THE ASYNCHRONOUS PORT CHARACTERISTIC (APC)

; APC CODES
	APCUNK==:0	;UNKNOWN
	APCHWD==:1	;HARDWIRED
	APCDSD==:2	;DATASET LINE
	APCTSN==:3	;TSN
	APCGAN==:4	;GANDALF
	APCADL==:5	;AUTODIALER
	APCMCM==:6	;MICOM
	APCNRT==:7	;DECNET NRTSER LINE
	APCLAT==:10	;LAT-SERVER LINE
	APCCTM==:11	;DECNET CTERM LINE
	APCMAX==:11	;HIGHEST KNOWN APC TYPE


; SET THE APC FOR NON-ANF10/DECNET LINES

APCSET::SE1ENT			;ENTER SECTION 1
	LDB	T1,LDPAPC	;GET CURRENT APC SETTING
	JUMPN	T1,CPOPJ##	;RETURN IF ALREADY HAVE APC
	MOVEI	T1,APCHWD	;ASSUME A HARDWIRED LINE
	MOVEI	T2,LDRDSD	;DATA SET BIT
	TDNE	T2,LDBDCH(U)	;SET?
	MOVEI	T1,APCDSD	;YES
	DPB	T1,LDPAPC	;STORE APC
	POPJ	P,		;RETURN
	SUBTTL	IMPURE DATA

	$LOW
ECHCNT:	0			;CLOCK REQUEST QUEUE COUNTER
TTBASE::0			;FIRST WORD IN TERMINAL BUFFER SPACE
DSCNUM:	BLOCK	2		;PHONE NUMBER BEING DIALLED, OR LAST DIALLED


.GTSCN::
;SCNSER RESPONSE DATA
%SCNRI::0			;(0)  NUMBER OF CHARS (EXCLUDES MIC) RECEIVED
%SCNXI::0			;(1)  NUMBER OF CHARS (INCLUDES FILL) XMITTED
%SCNEI::0			;(2)  NUMBER OF CHARS ECHOED (SUBSET OF %SCNXI)
TIWRNN::EXP	TTIBRK##	;(3)  MAX BUFFER SIZE
%SCNAL::0			;(4)  NUMBER OF ACTIVE LINES
RPIMWN::EXP	TTPWRN##	;(5)  PIM BUFFER SIZE
	EXP	RECINT		;(6)  FOR MONITOR TEST
	EXP	XMTINT		;(7)  PROGRAMS
	EXP	0		;(10) WAS TYPEX
TTFTAK::0			;(11) FIRST FREE CHUNK
TTFPUT::0			;(12) LAST FREE CHUNK
RCQHIT:	EXP	0		;(13) TOTAL RECINT CONFLICTS
RQFCNT:	EXP	0		;(14) CHARACTERS LOST DUE TO QUEUE OVERFLOW
TICCNT:	EXP	0		;(15) TIMES WE COULD HAVE DONE TIC STOPCD
SCNMXL==:<<.-.GTSCN-1>B26>

TIWRN1:	^D80			;WORD TO SAVE OLD BUFFER LIMIT

;THE CHARACTER QUEUE FOR RECINT (GLOBAL FOR SYSINI)

RCQCNT::EXP	0		;COUNT OF CHARACTERS IN QUEUE
RCQPTR::EXP	0		;QUEUE PUTTER
RCQTKR::EXP	0		;QUEUE TAKER

RCQBEG::BLOCK	RCQMAX		;THE CHARACTER QUEUE
RCQEND:	BLOCK	1		;THE END OF THE CHARACTER QUEUE

	XLIST			;LITERALS UNDER XLIST
	$LIT
	LIST

SCNEND:	END