Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - mit/monitor/ttysrv.new
There are no other files named ttysrv.new in the archive.
;<BERLIN.M5>TTYSRV.MAC.20,  7-Oct-82 23:37:56, Edit by BERLIN
;Add purge at end of this module
;<BERLIN.M5>TTYSRV.MAC.16,  7-Oct-82 18:18:53, Edit by BERLIN
;3005 HSTTY routine
;<5.MITMON>TTYSRV.MAC.28,  6-Oct-82 02:21:21, Edit by JTW
;3004 Flag linked chars on per-tty basis - fix occasional no-eop-mode bug
;<5.MITMON>TTYSRV.MAC.27,  2-Oct-82 16:47:55, Edit by JTW
;3002 Finish up ITS-style page handling
;<BERLIN.M5>TTYSRV.MAC.13, 20-Sep-82 13:15:37, Edit by BERLIN
;1027 Fix for send all to CVT's (KDO)
;1026 Eliminate OKSKBG bughlt due to bad lock handling
;1010 Several fixes for TVT's
;1005 Fix typo causing TTY's to sometimes hang
;<5.MITMON>TTYSRV.MAC.22,  5-Aug-82 22:07:39, Edit by JTW
; Add MIT changes:
; Chaos, TCP, and MultiNet line types.
; ITP and full character (12 bit) input.
; VTS - Cleaned up and reworked some from Rel-4, but still the same logical
;	implementation - needs a little rethinking.
;	Changed definition of ^P codes to match ITS.
; Screw around with links so that output to linked terminals goes through
;	VTS translation and so that job won't hang if a linked terminal 
;	hits an	end-of-page.	
; Rewrote much of TTCHI to:
;	Check interrupt chars before doing anything else, so ^S/^Q
;	and the page pause/unpause characters can be used as interrupts.
;	Implement verbose end-of-page indication.
;	Implement ITS style dumb more processing as an option.
;171 Add TTIDLE
;23 Fixed link header for not logged in terminals
;17 Added static terminal types and moved links
;2  Made NORMTF reasonable for MIT
; UPD ID= 578, SNARK:<5.MONITOR>TTYSRV.MAC.73,  15-Apr-82 22:51:51 by PAETZOLD
;More TCO 5.1772 - Take out the AC reference of the JRST in TCOU6
; UPD ID= 570, SNARK:<5.MONITOR>TTYSRV.MAC.72,   6-Apr-82 15:44:41 by PAETZOLD
;TCO 5.1772 - Handle short blocks in TCOU6 and TCOU7
; UPD ID= 556, SNARK:<5.MONITOR>TTYSRV.MAC.71,  21-Mar-82 03:49:47 by PAETZOLD
;TCO 5.1767 - Make SALLI2 use LCKTT and ULKTT
; UPD ID= 494, SNARK:<5.MONITOR>TTYSRV.MAC.70,   3-Mar-82 01:24:11 by PAETZOLD
;More TCO 5.1691 - Make it better
; UPD ID= 450, SNARK:<5.MONITOR>TTYSRV.MAC.69,  29-Jan-82 15:55:06 by MILLER
;TCO 5.1678. FIX CODE AT TTYASO, TTYASC AND TTSETL TO HANDLE TTACTL BETTER
; UPD ID= 424, SNARK:<5.MONITOR>TTYSRV.MAC.68,  20-Jan-82 09:19:55 by PAETZOLD
;TCO 5.1691 - prevent Q1 and Q2 trashing in TTYQOC
; UPD ID= 417, SNARK:<5.MONITOR>TTYSRV.MAC.67,  19-Jan-82 12:05:45 by MURPHY
;TCO 5.1688 - report noisy line only once.
; UPD ID= 308, SNARK:<6.MONITOR>TTYSRV.MAC.66,  16-Jan-82 17:37:49 by MILLER
;TCO 5.1678. Add NOSKED to TTYDEA
; UPD ID= 397, SNARK:<5.MONITOR>TTYSRV.MAC.65,  14-Jan-82 04:19:21 by PAETZOLD
;More TCO 5.1665 - Fix problems with previous edit
; UPD ID= 392, SNARK:<5.MONITOR>TTYSRV.MAC.64,  12-Jan-82 21:33:19 by PAETZOLD
;TCO 5.1665 - Generate TTLOKB BUGHLT when TTLCK overdecrement detected
; detected in LCKTT, ULKTTY, and ULKTT
; UPD ID= 380, SNARK:<5.MONITOR>TTYSRV.MAC.63,   6-Jan-82 14:47:35 by PAETZOLD
;TCO 5.1655 - preserve C around the TDCALL in TTMS20
; UPD ID= 357, SNARK:<5.MONITOR>TTYSRV.MAC.62,  11-Dec-81 13:59:59 by PAETZOLD
;TCO 5.1635 - make sure we are NOINT at all times in STPAR even when we have to
;negotiate TELNET protocol options
; UPD ID= 338, SNARK:<5.MONITOR>TTYSRV.MAC.61,   3-Dec-81 10:46:24 by MURPHY
;TCO 5.1625 - Create job on CR and LF as well as ^C.
; UPD ID= 185, SNARK:<5.MONITOR>TTYSRV.MAC.60,  16-Sep-81 13:57:38 by MURPHY
;ditto
; UPD ID= 173, SNARK:<5.MONITOR>TTYSRV.MAC.59,  14-Sep-81 15:09:08 by MURPHY
;TCO 5.1507 - Allow TTMSG to single line by unpriv user.
; UPD ID= 118, SNARK:<5.MONITOR>TTYSRV.MAC.58,  24-Aug-81 15:12:49 by GRANT
;Change NLINES to NLINES-1 in TTDTPS for searching all TTY blocks
; UPD ID= 58, SNARK:<5.MONITOR>TTYSRV.MAC.57,  21-Jul-81 16:44:23 by GRANT
;TCO 5.1375 - Create ATACTT routine to be used by ATACH JSYS
; UPD ID= 42, SNARK:<5.MONITOR>TTYSRV.MAC.56,  17-Jul-81 16:12:17 by MURPHY
;REJECT SETTING OF ^S AS UNPAUSE CHARACTER (5.1390)
; UPD ID= 2306, SNARK:<5.MONITOR>TTYSRV.MAC.55,   8-Jul-81 11:18:42 by MURPHY
;MCB DEBUG CODE; CALL REQNS INSTEAD OF TNUSND
; UPD ID= 2296, SNARK:<5.MONITOR>TTYSRV.MAC.54,   6-Jul-81 13:51:21 by MURPHY
;MAKE TTYDE0 RESIDENT BECAUSE CALLED FROM SCHED (NVT SERVICE) NOW
; UPD ID= 2288, SNARK:<5.MONITOR>TTYSRV.MAC.53,   2-Jul-81 11:51:20 by PAETZOLD
;TCO 5.1392 - Make TTFLG1 and TT%SAL globals so IMPDV can use them
; UPD ID= 2189, SNARK:<5.MONITOR>TTYSRV.MAC.52,  11-Jun-81 15:58:32 by MURPHY
;CHANGE TQNx TO TMNx REFLECTING CHANGE IN MACSYM
; UPD ID= 2153, SNARK:<5.MONITOR>TTYSRV.MAC.51,   8-Jun-81 17:39:47 by MURPHY
;FIX BUG IN XON/XOFF; ADD TTYDEX ENTRY POINT
; UPD ID= 2091, SNARK:<5.MONITOR>TTYSRV.MAC.50,  27-May-81 16:09:50 by PAETZOLD
;More TCO 5.1349...make sure not nosked when we get to NVTCOB...IMPINS
;may block and cause an NSKDIS
; UPD ID= 2085, SNARK:<5.MONITOR>TTYSRV.MAC.49,  27-May-81 08:37:10 by PAETZOLD
;TCO 5.1349 Make sure SYNch gets sent for arpa NVT's when clearing output buffer
; UPD ID= 2073, SNARK:<5.MONITOR>TTYSRV.MAC.48,  25-May-81 11:32:56 by ZIMA
;TCO 5.1348 - Fix STPAR for noop conditions as documented.
; UPD ID= 2060, SNARK:<5.MONITOR>TTYSRV.MAC.47,  21-May-81 22:50:22 by ZIMA
;TCO 5.1342 - handle case of refusing links and all links are full.
; UPD ID= 2053, SNARK:<5.MONITOR>TTYSRV.MAC.46,  20-May-81 17:47:49 by MURPHY
;BE SURE TTPRM CLEARED AFTER SETHOST LINK CLOSED
; UPD ID= 2046, SNARK:<5.MONITOR>TTYSRV.MAC.45,  20-May-81 11:59:18 by MURPHY
;USER SETTABLE CHARACTERS FOR PAGE PAUSE AND UNPAUSE
;REMOVE TSALP AGAIN, MISC ^O CLEANUP
;<5.MONITOR>TTYSRV.MAC.42, 27-Apr-81 09:49:56, EDIT BY GRANT
;Double colons needed on TTPPCS and TTPPCR
; UPD ID= 1874, SNARK:<5.MONITOR>TTYSRV.MAC.40,  23-Apr-81 11:38:32 by HALL
;RESTORE TSALP DEFINITION THAT DAN REMOVED
; UPD ID= 1866, SNARK:<5.MONITOR>TTYSRV.MAC.37,  21-Apr-81 23:41:44 by MURPHY
;DITTO
; UPD ID= 1864, SNARK:<5.MONITOR>TTYSRV.MAC.36,  21-Apr-81 18:29:26 by MURPHY
;More fiddling with end-of-page
; UPD ID= 1829, SNARK:<5.MONITOR>TTYSRV.MAC.34,  17-Apr-81 14:19:17 by MURPHY
;Get sendall bfr from res free stg
;Different handling of control-O for speed.
; UPD ID= 1744, SNARK:<5.MONITOR>TTYSRV.MAC.33,  19-Mar-81 23:10:56 by MURPHY
;Fix problem with line turn-off and XOFF/XON logic.
; UPD ID= 1549, SNARK:<5.MONITOR>TTYSRV.MAC.32,  10-Feb-81 17:57:36 by MURPHY
;FIX XOFF DURING SYSTEM STARTUP PROBLEM
; UPD ID= 1490, SNARK:<5.MONITOR>TTYSRV.MAC.31,  26-Jan-81 10:58:14 by MURPHY
;FIX BUG(TTQADX)
; UPD ID= 1478, SNARK:<5.MONITOR>TTYSRV.MAC.30,  22-Jan-81 12:24:18 by MURPHY
;MAKE SPACE CONTINUE AFTER PAUSE ON END-OF-PAGE
;FIX TTQAD
;<5.MONITOR>TTYSRV.MAC.29, 17-Dec-80 15:27:57, EDIT BY MURPHY
;<5.MONITOR>TTYSRV.MAC.28, 16-Dec-80 15:00:43, EDIT BY MURPHY
;<5.MONITOR>TTYSRV.MAC.27, 12-Dec-80 10:36:56, EDIT BY MURPHY
;FLOW CONTROL CHANGE IN MCB NVT
;<5.MONITOR>TTYSRV.MAC.26,  9-Dec-80 15:08:18, EDIT BY MURPHY
;PREVENT HUNG LINES ON LOGOUT
;<5.MONITOR>TTYSRV.MAC.25, 21-Nov-80 14:57:22, EDIT BY MURPHY
; UPD ID= 1300, SNARK:<5.MONITOR>TTYSRV.MAC.24,  19-Nov-80 17:05:25 by MURPHY
;XON/XOFF OPTION FOR MCB NVT
; UPD ID= 1289, SNARK:<5.MONITOR>TTYSRV.MAC.23,  18-Nov-80 16:45:12 by MURPHY
;TIMEOUT ON TTMSG (SEND ALL)
;<5.MONITOR>TTYSRV.MAC.22, 20-Oct-80 14:46:43, EDIT BY MURPHY
;<5.MONITOR>TTYSRV.MAC.21, 10-Oct-80 14:41:44, EDIT BY MURPHY
;<5.MONITOR>TTYSRV.MAC.20,  8-Oct-80 15:13:22, EDIT BY MURPHY
;<5.MONITOR>TTYSRV.MAC.19,  8-Oct-80 14:26:52, EDIT BY MURPHY
;<5.MONITOR>TTYSRV.MAC.18,  6-Oct-80 16:00:01, EDIT BY MURPHY
;FIX TTOMX, TTOCN DEFINITIONS
;<5.MONITOR>TTYSRV.MAC.17,  6-Oct-80 11:38:16, EDIT BY MURPHY
; UPD ID= 1125, SNARK:<5.MONITOR>TTYSRV.MAC.16,   5-Oct-80 15:02:35 by MURPHY
;DITTO
;<5.MONITOR>TTYSRV.MAC.15,  3-Oct-80 14:03:25, EDIT BY MURPHY
; UPD ID= 1112, SNARK:<5.MONITOR>TTYSRV.MAC.14,   3-Oct-80 01:00:42 by MURPHY
;NVT IMPROVEMENTS
; UPD ID= 1101, SNARK:<5.MONITOR>TTYSRV.MAC.13,   2-Oct-80 09:19:24 by MURPHY
;DITTO
; UPD ID= 1078, SNARK:<5.MONITOR>TTYSRV.MAC.12,   1-Oct-80 10:38:13 by MURPHY
;ADD APPROPRIATE ENDXX STATEMENTS FOR ACVAR, STKVAR, ETC.
; UPD ID= 1062, SNARK:<5.MONITOR>TTYSRV.MAC.11,  30-Sep-80 10:16:42 by MURPHY
;NVT bugs
;Change numeric ACs 5-7 to Q1,Q2,FX
; UPD ID= 991, SNARK:<5.MONITOR>TTYSRV.MAC.10,   5-Sep-80 15:57:46 by LYONS
;Fix detach job on a carrier off message from FE
; UPD ID= 924, SNARK:<5.MONITOR>TTYSRV.MAC.9,  20-Aug-80 10:21:02 by MURPHY
;Install NVTs and network user terminal state
; UPD ID= 691, SNARK:<5.MONITOR>TTYSRV.MAC.6,  24-Jun-80 20:49:47 by MURPHY
;CHANGE LINE TYPE VECTORING
;Dispatch using line type as index rather than using function as index.
; UPD ID= 649, SNARK:<5.MONITOR>TTYSRV.MAC.5,  16-Jun-80 12:11:48 by MURPHY
;CLEAN UP VECTOR COMMENTS
;<5.MONITOR>TTYSRV.MAC.4, 21-May-80 11:25:56, EDIT BY MURPHY
;FIX LISTING FORMAT
; UPD ID= 541, SNARK:<5.MONITOR>TTYSRV.MAC.3,  20-May-80 16:08:42 by OSMAN
;MORE 4.1.1142 - Make SIBE count RSCAN characters if terminal is caller's
;controlling terminal
;ALSO, make BKJFN back up RSCAN string if in use and we're reading from
;fork's controlling terminal
; UPD ID= 404, SNARK:<5.MONITOR>TTYSRV.MAC.2,   3-Apr-80 16:04:56 by HALL
;CHANGES TO WRITE-PROTECT THE RESIDENT MONITOR:
;	CHANGE TT1LIN TO BE A RESIDENT TABLE INSTEAD OF OFFSET IN
;		TRANSFER VECTOR
;	CHANGE ALL CODE THAT USES TT1LIN
;	MAKE TTINIT INITIALIZE TT1LIN FOR DC10 LINES
; UPD ID= 318, SNARK:<4.1.MONITOR>TTYSRV.MAC.164,  11-Mar-80 15:36:34 by MILLER
;TCO 4.1.1021 AGAIN. PRESERVE T2 IN WTALL
; UPD ID= 290, SNARK:<4.1.MONITOR>TTYSRV.MAC.163,  21-Feb-80 10:59:14 by MURPHY
;NEW FKINT DEFS
; UPD ID= 184, SNARK:<4.1.MONITOR>TTYSRV.MAC.162,   3-Jan-80 15:23:43 by SCHMITT
; more tco 4.1.1048
; UPD ID= 113, SNARK:<4.1.MONITOR>TTYSRV.MAC.161,   7-Dec-79 17:08:52 by KONEN
;TCO 4.2592 -- Make sure TTCON1 does RET to avoid ILLUUO
; UPD ID= 97, SNARK:<4.1.MONITOR>TTYSRV.MAC.160,   5-Dec-79 14:06:15 by SCHMITT
; TCO 4.1.1048 - Only simulate <LF> in buffer in <CR> input in non-binary
; UPD ID= 48, SNARK:<4.1.MONITOR>TTYSRV.MAC.159,  28-Nov-79 18:02:09 by MILLER
;CHANGE TESTS ON TOWRN TO PREVENT INFINITE LOOPS
; UPD ID= 11, SNARK:<4.1.MONITOR>TTYSRV.MAC.158,  21-Nov-79 18:20:21 by MURPHY
;<4.1.MONITOR>TTYSRV.MAC.157, 16-Nov-79 13:47:19, EDIT BY MILLER
;PREVIOUS CHANGES UNDER TCO 4.1.1021
;<4.1.MONITOR>TTYSRV.MAC.156, 16-Nov-79 13:44:30, EDIT BY MILLER
;CHANGE ASGALL WAIT TIME TO 30 SECS
;<4.1.MONITOR>TTYSRV.MAC.155, 16-Nov-79 12:53:01, EDIT BY MILLER
;<4.1.MONITOR>TTYSRV.MAC.154, 16-Nov-79 12:42:58, EDIT BY MILLER
;<4.1.MONITOR>TTYSRV.MAC.153, 16-Nov-79 11:28:50, EDIT BY MILLER
;ALLOW TTMSG TO TIME OUT
;<4.1.MONITOR>TTYSRV.MAC.152,  5-Nov-79 13:38:42, EDIT BY MURPHY
;FIX TTYQO2
;<4.MONITOR>TTYSRV.MAC.151,  2-Nov-79 16:57:05, EDIT BY MURPHY
;PTY OUTPUT START LOGIC
;<4.MONITOR>TTYSRV.MAC.149, 31-Oct-79 12:39:38, EDIT BY MILLER
;MOVE DEF OF TTFPK TO STATIC DATA
;<4.MONITOR>TTYSRV.MAC.148, 28-Oct-79 09:12:06, EDIT BY R.ACE
;FIX SPELLING OF ULKTTY IN TTSSPD ROUTINE
;<4.MONITOR>TTYSRV.MAC.147, 26-Oct-79 15:13:46, EDIT BY ZIMA
;TCO 4.2557 - Change calling sequence to TTSSPD to provide error
; return for ACJ rejection.  Now nonskip on error, skip on "success".
;<4.MONITOR>TTYSRV.MAC.146, 25-Oct-79 13:53:40, EDIT BY ENGEL
;TURN OFF ECHOING ON FULL DUPLEX LINES LINKED TO HALF-DUPLEX ONES
;<4.MONITOR>TTYSRV.MAC.145, 25-Oct-79 10:17:26, EDIT BY MURPHY
;FASTER WAKEUP ON OUTPUT EVENTS
;<4.MONITOR>TTYSRV.MAC.142, 10-Oct-79 13:47:32, EDIT BY MURPHY
;<4.MONITOR>TTYSRV.MAC.141,  6-Oct-79 12:49:05, EDIT BY HALL
;FIX MURPHY'S '20.' TO BE '^D20'
;<4.MONITOR>TTYSRV.MAC.140,  5-Oct-79 16:57:37, EDIT BY MURPHY
;FIX XOFF/XON PROBLEMS
;<4.MONITOR>TTYSRV.MAC.139,  3-Oct-79 15:28:01, EDIT BY HALL
;TTCHI - RETURN SUCCESS IF WAKING PROCESS FOR BINARY LINE
;<4.MONITOR>TTYSRV.MAC.138,  1-Oct-79 14:25:35, EDIT BY HELLIWELL
;<4.MONITOR>TTYSRV.MAC.137, 28-Sep-79 18:34:48, EDIT BY HELLIWELL
;<4.MONITOR>TTYSRV.MAC.136, 28-Sep-79 18:25:10, EDIT BY HELLIWELL
;<4.MONITOR>TTYSRV.MAC.135, 28-Sep-79 18:17:17, EDIT BY HELLIWELL
;<4.MONITOR>TTYSRV.MAC.134, 28-Sep-79 17:34:04, EDIT BY HELLIWELL
;<4.MONITOR>TTYSRV.MAC.133, 25-Sep-79 13:37:58, EDIT BY HELLIWELL
;<4.MONITOR>TTYSRV.MAC.132, 25-Sep-79 12:44:13, EDIT BY MURPHY
;<4.MONITOR>TTYSRV.MAC.131, 25-Sep-79 11:43:26, EDIT BY HELLIWELL
;TCO #4.2486 - FIX .MOTPS FUNCTION OF MTOPR
;<4.MONITOR>TTYSRV.MAC.130, 24-Sep-79 14:10:24, EDIT BY MURPHY
;<4.MONITOR>TTYSRV.MAC.129, 21-Sep-79 13:32:00, EDIT BY MURPHY
;<4.MONITOR>TTYSRV.MAC.128, 20-Sep-79 16:20:51, EDIT BY MURPHY
;SUCCESS/FAILURE RETURNS FOR TTSTI
;<4.MONITOR>TTYSRV.MAC.126, 20-Sep-79 14:20:45, EDIT BY MURPHY
;CHANGE FORMAT OF DEVICE DISPATCH MACRO
;<4.MONITOR>TTYSRV.MAC.125, 19-Sep-79 14:54:32, EDIT BY MURPHY
;NEW SYMBOLS WITH MNEMONIC SIGNIFICANCE FOR LINE TYPE VECTOR OFFSETS
;<OSMAN.MON>TTYSRV.MAC.1, 10-Sep-79 16:16:34, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>TTYSRV.MAC.123, 23-Aug-79 12:42:26, Edit by LCAMPBELL
; Don't attempt sendall to inactive NVTs
;<4.MONITOR>TTYSRV.MAC.122, 16-Aug-79 14:43:33, EDIT BY TOMCZAK
;TTSET1 - TCO#4.2407 - Default to REFUSE LINKS when assigning CTY
;<4.MONITOR>TTYSRV.MAC.121, 21-May-79 12:58:35, EDIT BY HALL
;TTYDE0 - FIX INSTRUCTION REFERENCING TTFLGS
;<4.MONITOR>TTYSRV.MAC.120, 17-May-79 20:48:19, Edit by HESS
;FIX EDIT 118 (FORGOT COMMA)
;<4.MONITOR>TTYSRV.MAC.119, 15-May-79 09:39:49, Edit by MCLEAN
;REMOVE EXTRANEOUS INSTRUCTION AT TTCH10-5
;<4.MONITOR>TTYSRV.MAC.118, 12-May-79 13:49:46, EDIT BY MILLER
;FIX CODE AT TTYDE0
;<4.MONITOR>TTYSRV.MAC.117, 12-May-79 12:54:55, EDIT BY MILLER
;ADD TTGSTS FOR GETTING GDSTS BITS
;<4.MONITOR>TTYSRV.MAC.116, 11-May-79 14:34:07, EDIT BY MILLER
;<4.MONITOR>TTYSRV.MAC.115, 10-May-79 12:32:47, EDIT BY MILLER
;<4.MONITOR>TTYSRV.MAC.114, 30-Apr-79 22:51:23, Edit by MCLEAN
;<4.MONITOR>TTYSRV.MAC.113, 12-Apr-79 16:57:15, Edit by MCLEAN
;MORE XOFF FIXES SO WE WAKEUP BEFORE DOING XOFF
;<4.MONITOR>TTYSRV.MAC.112,  5-Apr-79 11:28:31, Edit by MCLEAN
;REMOVE 1ST ARG FROM GTOKM
;<4.MONITOR>TTYSRV.MAC.111, 11-Mar-79 13:19:49, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>TTYSRV.MAC.110,  7-Mar-79 14:06:14, Edit by MCLEAN
;FIX SALLI2 FOR BECOMMING ACTIVE AND BEING NOSKED ON RETURN
;<4.MONITOR>TTYSRV.MAC.109, 21-Feb-79 13:48:07, Edit by MCLEAN
;MAKE NON TERMINAL PSI'S DISABLEABLE BY -1 IN PSI
;<4.MONITOR>TTYSRV.MAC.108, 19-Feb-79 18:54:53, EDIT BY DBELL
;ADD MISSING INSTRUCTION AT TL22+11
;<4.MONITOR>TTYSRV.MAC.107, 15-Feb-79 13:43:54, EDIT BY DBELL
;FINISH TCO 4.2185
;<4.MONITOR>TTYSRV.MAC.106, 12-Feb-79 15:47:29, EDIT BY DBELL
;MAKE TCO 4.2185 BETTER BY SUPPRESSING LINK MESSAGE WHEN LINKING RANDOMLY
;<4.MONITOR>TTYSRV.MAC.105, 10-Feb-79 17:22:27, Edit by MCLEAN
;<4.MONITOR>TTYSRV.MAC.104, 10-Feb-79 17:17:33, Edit by MCLEAN
;ADD NEW XOFF CODE FOR FRONT-END
;<4.MONITOR>TTYSRV.MAC.102,  8-Feb-79 14:57:43, EDIT BY DBELL
;TCO 4.2185 - ALLOW ANY TERMINAL TO BE OBJECT FOR TLINK
;<4.MONITOR>TTYSRV.MAC.101,  2-Feb-79 23:38:41, Edit by MCLEAN
;ADD NEW VECTOR TTVT40 FOR XOFF RECOGNITION IN FRONT-END
;<4.MONITOR>TTYSRV.MAC.100, 31-Jan-79 12:23:58, Edit by MCLEAN
;REMOVE PREVIOUS EDIT
;<4.MONITOR>TTYSRV.MAC.99, 30-Jan-79 23:41:53, Edit by MCLEAN
;<4.MONITOR>TTYSRV.MAC.98, 21-Jan-79 20:11:10, Edit by MCLEAN
;MORE XON/XOFF ADJUSTMENTS
;<4.MONITOR>TTYSRV.MAC.97, 21-Jan-79 17:58:36, Edit by MCLEAN
;MORE XON/XOFF FIXES
;<4.MONITOR>TTYSRV.MAC.96, 19-Jan-79 18:09:05, Edit by MCLEAN
;FIX TTLNK3+1 TO SAVE T2
;<4.MONITOR>TTYSRV.MAC.95, 19-Jan-79 13:02:35, Edit by MCLEAN
;FIX TTCH12 TO HAVE STATIC NOT DYNAMIC ADDRESS
;<4.MONITOR>TTYSRV.MAC.94, 18-Jan-79 19:20:37, EDIT BY MILLER
;FIX TTXSET TO ALWAYS CLEAR XOFF NOW IN PROGRESS
;<4.MONITOR>TTYSRV.MAC.93, 18-Jan-79 18:23:06, Edit by MCLEAN
;FIX CONSO PI AT TTRLBF
;<4.MONITOR>TTYSRV.MAC.92, 17-Jan-79 11:37:06, EDIT BY HALL
;SUPPRESS SYMBOL FOR MSGLEN
;<4.MONITOR>TTYSRV.MAC.91, 14-Jan-79 15:07:15, Edit by MCLEAN
;MANY SPEEDUPS AND CLEANUPS
;<4.MONITOR>TTYSRV.MAC.89, 14-Jan-79 01:00:14, Edit by MCLEAN
;REMOVE JE TTSFG AT TTXON
;<4.MONITOR>TTYSRV.MAC.88, 11-Jan-79 19:59:17, Edit by MCLEAN
;FIX SENDXOFF ONCE MORE AT TTCHI9
;<4.MONITOR>TTYSRV.MAC.87,  9-Jan-79 18:10:55, Edit by MCLEAN
;<4.MONITOR>TTYSRV.MAC.86,  8-Jan-79 16:19:06, EDIT BY HALL
;AESTHETICS
;<4.MONITOR>TTYSRV.MAC.85,  7-Jan-79 19:50:31, Edit by MCLEAN
;XON/XOFF CUTOFF FIXES
;<4.MONITOR>TTYSRV.MAC.83,  5-Jan-79 09:55:46, EDIT BY ENGEL
; MAKE CHKPTY RESIDENT
;<4.MONITOR>TTYSRV.MAC.82, 28-Dec-78 22:44:26, Edit by MCLEAN
;ADD TTVT39
;<4.MONITOR>TTYSRV.MAC.81, 28-Dec-78 16:26:53, Edit by MCLEAN
;FIX PSI FOR NON-TERMINAL INTERRUPTS
;<4.MONITOR>TTYSRV.MAC.80, 27-Dec-78 15:58:42, Edit by MCLEAN
;MAKE TTSTY 3 BITS AND GET CORRECT DEFSTR FOR TTXCN
;<4.MONITOR>TTYSRV.MAC.79, 24-Dec-78 16:28:34, EDIT BY DBELL
;MAKE ALL TTVTNN DEFINITIONS BE SUPPRESSED TO DDT
;<4.MONITOR>TTYSRV.MAC.78, 21-Dec-78 16:43:32, Edit by MCLEAN
;TEMP FIX AT TTCH22+3 TO FIX LOST INPUT EMPTY BUFFER INTERRUPTS
;<4.MONITOR>TTYSRV.MAC.77, 19-Dec-78 15:22:16, EDIT BY MURPHY
;ADD BLOCK PRIORITY ARG TO SCHED CALLS FOR TCITST, TCOTST, TTOBET
;<4.MONITOR>TTYSRV.MAC.76, 16-Dec-78 21:35:04, EDIT BY ZIMA
;TCO 4.2123 - FIX TERMINAL RAISE
;<4.MONITOR>TTYSRV.MAC.75, 11-Dec-78 23:01:42, Edit by MCLEAN
;ADD EXTRA BUFFERING FOR HIGH SPEED TERMINALS WHEN NECESSARY
;ADD NON-CONTROLLING TERMINAL PSI INTERRUPTS
;<4.MONITOR>TTYSRV.MAC.73, 13-Nov-78 21:53:47, Edit by MCLEAN
;FIX TTYDEA SO IT IS CHANNEL OFF WHILE DOING DE-ASSIGNMENTS
;<4.MONITOR>TTYSRV.MAC.72, 11-Nov-78 18:27:40, Edit by MCLEAN
;FIX TTRLB1 SO CHANNEL IS NOT TURNED ON IF CALLER HAS IT OFF
;<4.MONITOR>TTYSRV.MAC.71, 28-Oct-78 12:31:13, EDIT BY MILLER
;ADD TTYAO4
;<4.MONITOR>TTYSRV.MAC.70, 27-Oct-78 15:23:41, Edit by MCLEAN
;RANDOM SPEEDUPS
;<4.MONITOR>TTYSRV.MAC.69, 27-Oct-78 15:11:12, Edit by MCLEAN
;MAKE DYNAMIC BLOCK CORRECT SIZE FOR NEW BINARY OUTPUT BUFFER ADDRESS
;<4.MONITOR>TTYSRV.MAC.68, 25-Oct-78 23:08:00, Edit by MCLEAN
;<4.MONITOR>TTYSRV.MAC.67, 25-Oct-78 14:29:00, Edit by MCLEAN
;CHANGE ALL THE PARAMETERS AS TO WHEN XOFF AND XON GET DONE.
;<2MCLEAN>TTYSRV.MAC.78, 18-Oct-78 23:11:00, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.77, 18-Oct-78 22:53:09, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.76, 13-Oct-78 16:13:25, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.75, 11-Oct-78 13:34:12, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.74, 10-Oct-78 23:34:51, Edit by MCLEAN
;MOVE TLTYP TO TTSAL1 SO HRRZ CAN BE USED IN FNXXX MACROS
;IT IS MUCH FASTER THAN A LDB INSTRUCTION...
;<2MCLEAN>TTYSRV.MAC.73,  8-Oct-78 21:56:38, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.72,  8-Oct-78 21:45:07, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.71,  8-Oct-78 21:29:24, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.70,  8-Oct-78 14:32:28, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.69,  7-Oct-78 22:24:08, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.68,  6-Oct-78 16:28:51, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.67,  5-Oct-78 23:34:01, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.66,  5-Oct-78 22:59:28, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.65,  3-Oct-78 23:43:15, Edit by MCLEAN
;<2MCLEAN>TTYSRV.MAC.64,  3-Oct-78 23:31:25, Edit by MCLEAN
;SPEEDUPS FOR OUTPUT
;<4.MONITOR>TTYSRV.MAC.65, 18-Oct-78 14:28:09, EDIT BY MURPHY
;PUT FF HANDLING MOSTLY BACK LIKE IT WAS
;<4.MONITOR>TTYSRV.MAC.64,  6-Oct-78 14:05:37, EDIT BY MILLER
;TCO 4.2034. DON'T DETACH CTY ON POWER-FAIL RECOVERY
;<4.MONITOR>TTYSRV.MAC.63,  7-Sep-78 18:02:01, Edit by LCAMPBELL
; Create new flavor of TTYSRV, TTYASM (2020T)
;<4.MONITOR>TTYSRV.MAC.62,  5-Sep-78 16:56:25, EDIT BY MURPHY
;RESET TLNCT ON INDICATED ^L
;<4.MONITOR>TTYSRV.MAC.61, 29-Aug-78 12:10:35, EDIT BY MILLER
;DON'T INIT TT%PGM ON IF LINE IS A PTY
;<4.MONITOR>TTYSRV.MAC.60, 22-Aug-78 12:58:55, EDIT BY JBORCHEK
;REMOVE SEARCH OF IMPPAR NOW IN TTNTDV
;<4.MONITOR>TTYSRV.MAC.59, 22-Aug-78 08:25:59, EDIT BY MILLER
;SWAP MEANINGS OF TT%PGM AND TTNXO. FIX UP HANDLING OF LINE COUUNTER
;<4.MONITOR>TTYSRV.MAC.58, 17-Aug-78 13:39:50, EDIT BY ENGEL
;FIX TTSFW (JUMPLE NEEDED A T1,)
;<4.MONITOR>TTYSRV.MAC.57, 15-Aug-78 10:46:26, Edit by ENGEL
;MAKE TTWAKE WAKE ONLY SEE LF AND NEVER CR 
;<OSMAN>TTYSRV.MAC.1, 10-Aug-78 16:13:14, EDIT BY OSMAN
;ADD TTLINE, TTLMAX, CODE FOR .MORLC, .MOSLC, .MORLM, .MOSLM
;<4.MONITOR>TTYSRV.MAC.55, 27-Jul-78 09:13:52, EDIT BY MILLER
;CHECK TTXNO AT TTXOFF
;<4.MONITOR>TTYSRV.MAC.54, 27-Jul-78 07:48:39, EDIT BY MILLER
;FIX TTIDON CODE
;<4.MONITOR>TTYSRV.MAC.53, 26-Jul-78 18:43:57, EDIT BY MILLER
;ADD TTRXOB
;<4.MONITOR>TTYSRV.MAC.52, 24-Jul-78 10:51:57, Edit by ENGEL
;FIX TYPEOS AT TTSW1-1
;<4.MONITOR>TTYSRV.MAC.51, 23-Jul-78 14:50:55, EDIT BY MILLER
;FIX SOME TYPEOS
;<4.MONITOR>TTYSRV.MAC.50, 23-Jul-78 14:38:28, EDIT BY MILLER
;TCO 1951. ADD MTOPR SUPPORT CODE. ADD TTNXO BIT.
;<4.MONITOR>TTYSRV.MAC.49, 21-Jul-78 16:13:11, Edit by ENGEL
;FIX HORIZONTAL TAB PROBLEM FOR WAKE-UP CLASSES
;<4.MONITOR>TTYSRV.MAC.48, 21-Jul-78 13:58:24, Edit by ENGEL
;FIX TT%IGN BEING RETURNED ON RFMOD 
;<4.MONITOR>TTYSRV.MAC.47, 18-Jul-78 16:25:29, EDIT BY MILLER
;CHECK FOR XON AND XOFF AS WITH OR WITHOUT PARITY
;<4.MONITOR>TTYSRV.MAC.46, 16-Jul-78 23:21:56, Edit by MCLEAN
;<4.MONITOR>TTYSRV.MAC.45, 16-Jul-78 22:47:52, Edit by MCLEAN
;<4.MONITOR>TTYSRV.MAC.44, 16-Jul-78 22:47:09, Edit by MCLEAN
;ADD GETOK FOR SETTING TERMINAL SPEEDS
;<3A.MONITOR>TTYSRV.MAC.43,  7-Jul-78 12:57:23, EDIT BY MILLER
;FIX TL12 TO RESTORE 5 ON FAILURE FROM CALL TO TL1C
;<2MCLEAN>TTYSRV.MAC.42, 28-Jun-78 01:13:28, Edit by MCLEAN
;FIX XOFF SO IT WILL OCCUR IMMEDIATELY
;<4.MONITOR>TTYSRV.MAC.41, 22-Jun-78 09:07:29, EDIT BY MILLER
;TCO 1924. SET TT%PGM IN STTYP JSYS IF APPROPRIATE
;<4.MONITOR>TTYSRV.MAC.40, 19-Jun-78 16:55:00, EDIT BY MURPHY
;<4.MONITOR>TTYSRV.MAC.39, 17-Jun-78 12:32:59, Edit by DBELL
;RANGE CHECK TERMINAL NUMBER IN TTMSG
;<3A.MONITOR>TTYSRV.MAC.42, 16-Jun-78 16:52:21, EDIT BY MILLER
;FIX BUG IN TCOU7 AFTER CALL TO ASGMSL
;<3A.MONITOR>TTYSRV.MAC.41, 15-Jun-78 11:56:21, EDIT BY MILLER
;ADD NOSKD1 AND OKSKD1 TO STRTOU
;<3A.MONITOR>TTYSRV.MAC.40, 14-Jun-78 13:53:11, EDIT BY MILLER
;PUT TTRLOB BACK AT TTYDEA. ADD CALL TO TTXON
;<4.MONITOR>TTYSRV.MAC.35,  9-Jun-78 14:16:10, EDIT BY MILLER
;PUT IN SAVELN AT TTEMES SO LINE NUMBER IS PRESERVED
;<4.MONITOR>TTYSRV.MAC.34,  9-Jun-78 11:11:09, EDIT BY MURPHY
;<3A.MONITOR>TTYSRV.MAC.37,  8-Jun-78 17:26:26, EDIT BY MURPHY
;TCO #1894 - QUEUE OF LINES TO START OUTPUT
;<4.MONITOR>TTYSRV.MAC.32,  6-Jun-78 01:33:58, Edit by JBORCHEK
;ADD SEARCH OF IMPPAR
;<3A.MONITOR>TTYSRV.MAC.36, 29-May-78 13:38:47, EDIT BY MILLER
;CALL TTCBF2 FROM TTYDEA INSTEAD OF CALL TTRLOB
;<4.MONITOR>TTYSRV.MAC.30, 18-May-78 13:40:02, EDIT BY MURPHY
;TCO #1911 - WAKEUP ALWAYS ON CR ON PTY
;<4.MONITOR>TTYSRV.MAC.29,  3-May-78 08:35:46, EDIT BY MILLER
;MORE FIX UPS TO TLINK
;<3A.MONITOR>TTYSRV.MAC.34,  3-May-78 08:33:03, EDIT BY MILLER
;FXI TLINK JSYS NEVER TO BLOCK WITH TTY LOCKED
;<4.MONITOR>TTYSRV.MAC.27,  2-May-78 14:54:32, EDIT BY MILLER
;DON'T NEED TO USE LINKF IN TTLNK3 ANYMORE
;<3A.MONITOR>TTYSRV.MAC.32, 24-Apr-78 08:36:19, EDIT BY MILLER
;MAKE SURE "LINK ECHOES" ARE GENERATED FOR HALF-DUPLEX LINES
;<4.MONITOR>TTYSRV.MAC.25, 22-Apr-78 15:52:47, Edit by BORCHEK
;SET UP TCJOB FOR NVT AT TTYAC4:
;<4.MONITOR>TTYSRV.MAC.24, 18-Apr-78 13:56:30, EDIT BY MURPHY
;<4.MONITOR>TTYSRV.MAC.23, 15-Apr-78 15:33:17, EDIT BY MILLER
;FIX HANDLING OF LINKF IN TTLNK3
;<3A.MONITOR>TTYSRV.MAC.29, 13-Apr-78 15:54:41, EDIT BY MURPHY
;TCO #1905 - FIX TTSTIH
;<4.MONITOR>TTYSRV.MAC.21,  5-Apr-78 16:11:11, EDIT BY MILLER
;REMOVE CHECK FOR TTLCK=0 IN TCI BLOCK ROUTINE
;<4.MONITOR>TTYSRV.MAC.20, 28-Mar-78 12:20:39, EDIT BY MILLER
;FXI TYPEO
;<3A.MONITOR>TTYSRV.MAC.26, 28-Mar-78 11:44:47, EDIT BY MILLER
;FIX UP CODE IN TTLNK3
;<4.MONITOR>TTYSRV.MAC.18, 27-Mar-78 18:23:24, EDIT BY MILLER
;FIX TTLNK3
;<3A.MONITOR>TTYSRV.MAC.24, 27-Mar-78 10:11:40, EDIT BY MILLER
;FIX TLINK NOT TO USE TTYDIS AND TTYAWK. REMOVE ROUTINES
;<4.MONITOR>TTYSRV.MAC.16, 26-Mar-78 14:38:41, EDIT BY MILLER
;CHECK FOR MESSAGE BLOCK AT CLENUP
;<4.MONITOR>TTYSRV.MAC.15, 26-Mar-78 14:32:57, EDIT BY MILLER
;FIX TYPEO
;<3A.MONITOR>TTYSRV.MAC.21, 26-Mar-78 13:11:43, EDIT BY MILLER
;FIX UP TTLNK3 TO UNLOCK TTY
;<3A.MONITOR>TTYSRV.MAC.20, 25-Mar-78 14:38:41, EDIT BY MILLER
;MORE FIX UPS
;<3A.MONITOR>TTYSRV.MAC.19, 25-Mar-78 13:43:00, EDIT BY MILLER
;MORE FIXES
;<3A.MONITOR>TTYSRV.MAC.18, 25-Mar-78 13:36:15, EDIT BY MILLER
;ALLOW TCOTST TO PROCEED WITHOUT TTY BEING LOCKED
;<4.MONITOR>TTYSRV.MAC.12, 23-Mar-78 07:55:38, EDIT BY MILLER
;CHECK FOR REQUEUE AT TTQAD
;<3.SM10-RELEASE-3>TTYSRV.MAC.9, 22-Mar-78 19:44:46, Edit by MCLEAN
;ADD TTXOC FOR 2020
;<3.SM10-RELEASE-3>TTYSRV.MAC.8, 22-Mar-78 19:38:24, Edit by MCLEAN
;<4.MONITOR>TTYSRV.MAC.10, 20-Mar-78 14:10:58, EDIT BY MILLER
;CHECK FOR SEND-ALL OR MESSAGE BLOCK AT TTSN10
;<4.MONITOR>TTYSRV.MAC.9,  9-Mar-78 09:34:49, Edit by ENGEL
;ADD SUPPORT FOR THE FULL WAKE 128-CHARACTER WAKE-UP MASK
;<4.MONITOR>TTYSRV.MAC.8,  2-Mar-78 17:49:26, EDIT BY MILLER
;GIVE TTDIBE A SKIP RETURN. +1 MEANS RETRY
;<3A.MONITOR>TTYSRV.MAC.11,  2-Mar-78 16:58:28, EDIT BY MILLER
;GIVE TTDOBE A SKIP RETURN. CALLERS MUST RETRY
;<3A.MONITOR>TTYSRV.MAC.9, 22-Feb-78 16:31:41, EDIT BY MILLER
;MAKE TTSTO BLOCK WITH TTY UNLOCKED. ADD SKIP RETURN FOR SUCCESS
;<4.MONITOR>TTYSRV.MAC.5, 22-Feb-78 08:19:01, EDIT BY MILLER
;FLUSH OUTPUT BUFFERS IN TSACT3 SCHEDULER TEST
;<4.MONITOR>TTYSRV.MAC.4, 21-Feb-78 08:42:38, EDIT BY MILLER
;CHANGE SETOBF TO USE FULL WORD TTBFRC DEFINITION
;<4.MONITOR>TTYSRV.MAC.3, 20-Feb-78 14:15:58, EDIT BY MILLER
;CHANGE TO STADYN IN TTSSPD TO CALL LCKTTY
;<4.MONITOR>TTYSRV.MAC.2, 20-Feb-78 10:29:50, EDIT BY MILLER
;FIX TYPEO IN SETOBF
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH PROLOG

   IFNDEF ARPAF,<ARPAF==0>
   IFN KLFLG&<^-ARPAF>,<
	TTITLE TTYSRV
	SEARCH PROKL
>
   IFN ARPAF&KLFLG,<
	TTITLE TTYSRV,TTYSNV
	SEARCH PROKL
>
   IFN SMFLG&<^-ARPAF>,<
	TTITLE TTYSRV,TTYSSM
	SEARCH PROKS
>

   IFN ARPAF&SMFLG,<
	TTITLE TTYSRV,TTYASM
	SEARCH PROKS
>

;SET FLAGS FOR DEVICE CODE

  IFN KLFLG,<
	.FEFLG==1>		;INCLUDE FE CODE
  IFN SMFLG,<
	.DZFLG==1>		;INCLUDE DZ CODE
  IFN ARPAF,<
	.NTFLG==1>		;INCLUDE NT CODE
	.PTFLG==1		;ALWAYS INCLUDE PT CODE

  IFNDEF DCN,<DCN==0>
  IFN DCN,<
	.MCFLG==1>

  IFNDEF CHAOS,<CHAOS==0>
  IFN CHAOS,<
	.NTFLG==1
	.CHFLG==1>

  IFNDEF TCPN,<TCPN==0>
  IFN TCPN,<
	.TVFLG==1>

  IFNDEF MNET,<MNET==0>
  IFN MNET,<
	.MLFLG==1>

.MLFLG==0			;+++ Set this to 0 for MIT

ND .FEFLG,0
ND .MCFLG,0
ND .PTFLG,1
ND .DCFLG,0
ND .NTFLG,0
ND .DZFLG,0
ND .MLFLG,0
ND .CHFLG,0
ND .TVFLG,0

ND NVTLEN,0
ND TTMCLN,0
ND MLCLEN,0
ND CVTLEN,0
ND TVTLEN,0

;TELETYPE SERVICE ROUTINES - D. MURPHY

	SUBTTL DATA DEFINITIONS

;AC DEFINITIONS USED HEREIN

DEFAC (FX,Q3)			;FORK INDEX
;This code supports a number (NLTYPS) of different types of terminals.
;The general code is in this module (TTYSRV), and there is another
;module for each terminal type which contains the device-dependent
;code for that type.  Device dependent code is called via a macro
;defined below.

;The macro accepts a list of pairs, where each pair indicates a
;line type and a routine to be called for that type.  If no
;specification is given for a line type, control passes through the
;TDCALL with no effect.

;TDCALL - Macro to do the device dependent subroutine call.
;Use:
;	TDCALL S,<list>,default
;	 or
;	TDCALL D,<list>,default
; where
;  S indicates that a static pointer is in T2,
;  D indicates that a dynamic pointer is in T2.
;  list is the list of dispatches for this function
;	where each item is a pair of the form <ty,adr>, where
;	  ty = one of the set FE, MC, PT, DC, NT, DZ, ML, CH, TV indicating
;		the line type for which the adr is relevant
;	  adr = the address of a routine to CALL for this type
;  default, if present, is the instruction to assemble in the absence
;	of the line type and/or the line case

;The macros ultimately assemble something of the form:
;	LOAD CX,line-type
;	CALL [	JRST FECASE
;		JRST MCCASE
;		..
;		JRST DZCASE](CX)
;where the literal must be exactly NLTYPS long and must be in the
;proper order.  If no specification is found for a particular
;line type, a RET (or the default) is assembled in that literal location.
;There is also a varient, TDCALX, if the line type is already in an AC.

DEFINE TDCALL (DT,VECTOR,DEFLT)<
  IFIDN <DT><S>,<
	LOAD CX,TTSTY,(T2)>
  IFIDN <DT><D>,<
	LOAD CX,TLTYP,(T2)>
	CALL [
	  ..TDC1 (<VECTOR>,<FE,MC,PT,DC,NT,DZ,ML,CH,TV>,<DEFLT>) ](CX)
  >

DEFINE ..TDC1 (VECTOR,TYLST,DEFLT)<
  IRP TYLST,<
   IFE .'TYLST'FLG,<
    IFNB <DEFLT>,<
	DEFLT>
    IFB <DEFLT>,<
	JRST TTBUGH>>		;;GO TO BUGCHK IF CODE DOESN'T EXIST
   IFN .'TYLST'FLG,<
	..F==0			;;FLAG TO SEE IF HAVE THIS TYPE
    IRP VECTOR,<
	..TDC2 (VECTOR,TYLST)>	;;SEE IF TYPES MATCH AND ASSEMBLE DISPATCH
    IFE ..F,<
     IFNB <DEFLT>,<
	DEFLT>
     IFB <DEFLT>,<
	RET>>>>>		;;RET IF NO SPEC FOR THIS TYPE

DEFINE ..TDC2 (VECTOR,LTY)<
	..TDC3 (VECTOR,LTY)>

DEFINE ..TDC3 (TY,ADR,LTY)<
  IFIDN <TY><LTY>,<
	..F=1			;;NOTE ASSEMBLED WORD HERE
	JRST ADR>>

;VARIANT MACRO USED IF LINE TYPE ALREADY IN AC

DEFINE TDCALX (AC,VECTOR,DEFLT)<
	CALL [
	  ..TDC1 (<VECTOR>,<FE,MC,PT,DC,NT,DZ,ML,CH,TV>,<DEFLT>) ](AC)>

;TABLES INDEXED BY LINE TYPE NUMBER

RS TT1LIN,NLTYPS		;PLACE FOR FIRST LINE OF THIS TYPE
				; STORED AT INITIALIZATION

;TABLE OF INSTRUCTIONS TO SET/CLEAR PARITY BIT AS FUNCTION OF LINE TYPE

PARTBL:	TRO T1,200		;FE
	TRO T1,200		;MC
	TRO T1,200		;PT
	TRO T1,200		;DC
	TRZ T1,200		;NT
	TRO T1,200		;DZ
	JFCL			;ML
	TRZ T1,200		;CH
	TRZ T1,200		;TV

IFN .-PARTBL-NLTYPS,<PRINTX %PARTBL SIZE DOES NOT AGREE WITH NLTYPS>

;SIZE OF DYNAMIC DATA BASE TO BE ALLOCATED

DDLTBL:	TTDDLN			;FE
	TTMCLN			;MC
	TTDDLN			;PT
	TTDDLN			;DC
	NVTLEN			;NT
	TTDDLN			;DZ
	MLCLEN			;ML
	CVTLEN			;CH (CHAOS)
	TVTLEN			;TV (TCP)
IFN .-DDLTBL-NLTYPS,<PRINTX %DDLTBL SIZE DOES NOT AGREE WITH NLTYPS>
;SAVELN - MACRO TO SAVE AC2 UPON ENTRY TO A ROUTINE AND RESTORE
;IT UPON EXIT. USED TO SAVE INTERNAL LINE NUMBER OR ADDRESS OF DYNAMIC
;DATA BECAUSE CALLERS ASSUME IT IS PRESERVED

;NOTE THAT IF A ROUTINE HAS BOTH SAVELN AND STKVAR, THE SAVELN MUST
;COME FIRST

	DEFINE SAVELN <
	JSP CX,.SAV22>		;SAVE T2

	RESCD

;MACRO TO GET STATIC LINE NUMBER FROM DYNAMIC DATA BASE.
;ASSUMES THAT T2/ ADDRESS OF DYNAMIC DATA
;PRESERVES ALL REGISTERS EXCEPT T2

DEFINE DYNST (AREG) <
   IFB <AREG>,<LOAD T2,TINTL,(T2)> ;;SIMPLE PROCEDURE
   IFNB <AREG>,<LOAD AREG,TINTL,(T2)> ;;FOR SPECIAL CASES
   >

;VARIENTS OF LOAD AND STOR WHICH AUTOMATICALLY CONVERT FROM
;DYNAMIC TO STATIC

DEFINE STALOD (AC,STR,XR)<
	LOAD CX,TINTL,XR	;;GET LINE NUMBER
	LOAD AC,STR,(CX)>	;;THEN DO LOAD

DEFINE STASTO (AC,STR,XR)<
	LOAD CX,TINTL,XR
	STOR AC,STR,(CX)>
;STATIC STORAGE - ONE WORD PER DEFINED LINE, WHETHER ACTIVE OR NOT
;WORDS ARE ACTUALLY DEFINED IN STG

;RS TTSTAT,NLINES
TT%FEM==1B0			;LINE IS REMOTE
TT%NTS==1B1			;DON'T SEND SYSTEM MESSAGES
TT%FXO==1B2			;LINE NEEDS XON
TT%CON==1B3			;CARRIER IS ON
TT%FSP==1B4			;LINE NEEDS SPEED SET
TT%FXF==1B5			;LINE NEEDS XOF
TT%IGI==1B6			;IGNORE INPUT WHEN LINE IS INACTIVE
TT%AUT==1B7			;LINE IS AUTO-SPEED
TT%XOC==1B8			;LINE NEEDS XON/XOFF CHARACTER (2020)
TT%FPK==1B8			; WAITING FOR FE POST (KL)
TT%SHU==1B9			;LINE IS SHUT OFF
TT%WSO==1B10			;LINE WAS SHUT OFF
MSKSTR TTFEM,TTSTAT,TT%FEM
MSKSTR TTNTS,TTSTAT,TT%NTS
MSKSTR TTFXO,TTSTAT,TT%FXO
MSKSTR TTCON,TTSTAT,TT%CON
MSKSTR TTFSP,TTSTAT,TT%FSP
MSKSTR TTFXF,TTSTAT,TT%FXF
MSKSTR TTIGI,TTSTAT,TT%IGI	;IGNORE INPUT WHEN LINE IS INACTIVE
MSKSTR TTAUT,TTSTAT,TT%AUT	;LINE IS AUTO-SPEED
MSKSTR TTXOC,TTSTAT,TT%XOC	;LINE NEEDS XON/XOFF CHARACTER OUTPUT
MSKSTR TTFPK,TTSTAT,TT%FPK	; FE TO POST
MSKSTR TTSHU,TTSTAT,TT%SHU
MSKSTR TTWSO,TTSTAT,TT%WSO	;LINE WAS SHUT OFF
; 11-14 FREE			;1010 Make that 11-13
;---DEFSTR TTXCN MISSING, WON'T FIT
DEFSTR TTSTY,TTSTAT,17,4	;1010 Need 4 bits here! LINE TYPE
DEFSTR TSFMC,TTSTAT,27,8	;MAX COUNT FOR FRONT END BUFFER
DEFSTR TTFBB,TTSTAT,35,8	;NUMBER OF ENTRIES IN TTBBUF
;RS TTSPWD,NLINES		;(INPUT SPEED,,OUTPUT SPEED
DEFSTR TTISP,TTSPWD,17,18	;INPUT SPEED
DEFSTR TTOSP,TTSPWD,35,18	;OUTPUT SPEED
;RS TTACTL,NLINES		;ADDRESS OF DYNAMIC DATA IF ACTIVE
				; OR -1 IF BECOMING ACTIVE
				; OR 0 IF INACTIVE
TTSHBK==1B0			;SHORT BLOCK
;RS TTCSAD,NLINES		;ADDRESS OF ROUTINE FOR SCHEDULER TO CALL
DEFSTR TTIME,TTCSTM,35,36
;RS TTCSTM,NLINES		;TIME FOR SCHEDULER TO CALL ROUTINE
DEFSTR TROUT,TTCSAD,35,36

;OTHER MISC STORAGE, DEFINED HERE

RS SALLCK,1			;SENDALL LOCK
RS SALCNT,1			;SENDALL COUNT
RS SALBFR,1			;SENDALL BUFFER ADDRESS
;OFFSETS IN DYNAMIC DATA

TTFLG1==:0
TT%SAL==:1B0			;SENDALL BEING DONE TO THIS LINE
TT%SHT==1B1			;THIS IS A SHORT BLOCK
TT%MES==1B2			;THIS IS A SYSTEM MESSAGE BLOCK
TT%OTP==1B3			;OUTPUT IS ENROUTE TO THE LINE
TT%FWK==1B4			;FORCED WAKEUP
TT%SFG==1B5			;STOPPED ON END-OF-PAGE
TT%RFG==1B6			;REPEAT LAST CHARACTER (BKJFN)
TT%WFG==1B7			;BLOCKED ON INPUT
TT%PRM==1B8			;DON'T DEALLOCATE DYNAMIC DATA
TT%BAC==1B9			;PERMANENT AND BECOMING ACTIVE
TT%NXO==1B10			;PAUSE ON END-OF-PAGE MODE
TT%BKO==1B11			;FORK BLOCKED FOR OUTPUT EVENT ON THIS LINE
TT%NUS==1B12			;NET USER STATE
TT%DD1==1B13			;DEVICE DEPENDENT BIT
TT%NPM==1B14			;MCB NVT OLD PAGE MODE
TT%RXF==1B15			;HAVE RECEIVED XOFF ON LINE
TT%FLO==1B16			;FLUSHING OUTPUT AT TTSND
TT%HPO==1B17			;HIGH PRIORITY OUTPUT QUEUED
TT%DAL==1B18			;DEALLOCATE OF BLOCK REQUESTED
TT%VTF==1B19			;NEXT CHAR IS VTS FUNCTION CODE
TT%VTA==1B20			;NEXT CHAR IS VTS ARGUMENT
TT%CRS==1B21			;CARRIAGE RETURN SEEN AT TCOY LEVEL
TT%CFU==1B22			;LOST TRACK OF CURSOR
TT%NAB==1B23			;DOING CURSOR RECOVERY, NO ABSOLUTE MOTION
TT%LNC==1B24			;3004 OUTPUTTING LINKED CHARACTER
;25-29 FREE
TT%LCK==77B35			;COUNT OF LOCKS ON THIS BLOCK
MSKSTR TTSAL,TTFLG1,TT%SAL
MSKSTR TTSHT,TTFLG1,TT%SHT
MSKSTR TTMES,TTFLG1,TT%MES
MSKSTR TTOTP,TTFLG1,TT%OTP
MSKSTR TTFWK,TTFLG1,TT%FWK
MSKSTR TTSFG,TTFLG1,TT%SFG
MSKSTR TTRFG,TTFLG1,TT%RFG
MSKSTR TTWFG,TTFLG1,TT%WFG
MSKSTR TTPRM,TTFLG1,TT%PRM
MSKSTR TTBAC,TTFLG1,TT%BAC
MSKSTR TTNXO,TTFLG1,TT%NXO
MSKSTR TTBKO,TTFLG1,TT%BKO
MSKSTR TTNUS,TTFLG1,TT%NUS
MSKSTR TTDD1,TTFLG1,TT%DD1	;DEVICE DEPENDENT BIT
MSKSTR TTNPM,TTFLG1,TT%NPM
MSKSTR TTRXF,TTFLG1,TT%RXF
MSKSTR TTFLO,TTFLG1,TT%FLO
MSKSTR TTHPO,TTFLG1,TT%HPO
MSKSTR TTDAL,TTFLG1,TT%DAL
MSKSTR TTVTF,TTFLG1,TT%VTF
MSKSTR TTVTA,TTFLG1,TT%VTA
MSKSTR TTCRS,TTFLG1,TT%CRS
MSKSTR TTCFU,TTFLG1,TT%CFU
MSKSTR TTNAB,TTFLG1,TT%NAB
MSKSTR TTLNC,TTFLG1,TT%LNC	;3004
MSKSTR TTLCK,TTFLG1,TT%LCK

TTDAT1==1
DEFSTR TYLMD,TTDAT1,5,2		;TERMINAL DATA MODE FOR LAST INPUT CHAR
DEFSTR TTOCN,TTDAT1,7,3		;COUNT OF EXTRA BUFFERS
DEFSTR TTOMX,TTDAT1,8,1		;EXTRA BUFFERS IN USE
DEFSTR TTTYP,TTDAT1,17,9	;TERMINAL TYPE
DEFSTR TINTL,TTDAT1,35,18	;INTERNAL LINE NUMBER (INDEX INTO STATIC DATA)

TTSAL1==2
DEFSTR TLTYP,TTSAL1,17,18	;LINE TYPE (SAME AS TTSTY)
DEFSTR TSALT,TTSAL1,23,6	;SENDALL TIMEOUT COUNT
DEFSTR TSALC,TTSAL1,35,12	;SENDALL CHARACTER COUNT
TSALCM==^D581			;MAX SENDALL CHARACTER COUNT

TTSAL2==3			;SENDALL BYTE POINTER

TTDEV==4
;DEVICE DEPENDET WORD SEE DEVICE MODULES FOR DEFINITIONS


TTBFRC==5
DEFSTR TOWRN,TTBFRC,7,8		;COUNT IN OUPUT BUFFER FOR WAKEUP
DEFSTR TTNIN,TTBFRC,11,4	;NO. INPUT BUFFERS
DEFSTR TTNOU,TTBFRC,15,4	;NUMBER OUTPUT BUFFERS
DEFSTR TIMAX,TTBFRC,25,10	;MAX BYTES IN INPUT BUFFER
DEFSTR TOMAX,TTBFRC,35,10	;MAX BYTES IN OUTPUT BUFFER

TTOCT==6			;NUMBER CHARACTERS IN OUTPUT BUFFER
TTOOUT==7			;POINTER FOR REMOVING CHAR FROM OUTPUT BUFFER
TTOIN==10			;POINTER FOR ENTERING CHAR INTO OUTPUT BUFFER

TTDAT2==11
DEFSTR TTUPC,TTDAT2,8,9		;UNPAUSE ON PAGE CHARACTER
DEFSTR TYLCH,TTDAT2,17,9	;LAST CHAR REMOVED FROM INPUT BUFFER
DEFSTR TTPPC,TTDAT2,35,9	;PAUSE/UNPAUSE ON PAGE CHARACTER

TTICT==12			;NUMBER CHARACTERS IN INPUT BUFFER
TTIOUT==13			;POINTER FOR REMOVING CHAR FROM INPUT BUFFER
TTIIN==14			;POINTER FOR ENTERING CHAR INTO INPUT BUFFER

FCMOD1==15			;CONTROL CHARACTER OUTPUT CONTROL WORDS
FCMOD2==16			; (2 BITS PER CHARACTER)
;POSSIBLE VALUES FOR EACH CHARACTER
CCNONE==0			;SEND NOTHING
CCIND==1			;INDICATE VIA ^
CCSEND==2			;SEND ACTUAL CODE
CCSIM==3			;SIMULATE FORMAT ACTION

TTDPSI==17			;BIT FOR TERMINAL CODE SET IF DEFERRED INTERRUPT
TTPSI==20			;BIT FOR TERMINAL CODE SET IF INTERRUPT
TTLINK==21			;LINES LINKED TO (9 BITS PER LINE)

TTLPOS==22
DEFSTR TLVPS,TTLPOS,17,18	;CURRENT LINE POSITION WITHIN PAGE
DEFSTR TLHPS,TTLPOS,35,18	;CURRENT CHARACTER POSITION WITHIN LINE

TTFLGS==23
MSKSTR TOFLG,TTFLGS,TT%OSP	;CTRL/O WAS TYPED
;(BITS ARE DEFINED IN MONSYM AS JFN MODE WORD)

TTFORK==24
DEFSTR TCJOB,TTFORK,17,18	;CONTROLLING JOB NUMBER
DEFSTR TWFRK,TTFORK,35,18	;NUMBER OF FORK IN INPUT WAIT ON THIS LINE

TTFRK1==25
DEFSTR TTPFK,TTFRK1,35,18	;FORK WHICH IS TOP FORK OF A SCTTY TREE
				;-1 IF NONE
DEFSTR TTPSFK,TTFRK1,17,18	;PSI FORK FOR NON CONTROL TTY PSI'S


TTCHR1==26			;WAKE UP CHARACTER MASK (ASCII CODES 0-31.)
TTCHR2==27			;WAKE UP CHARACTER MASK (ASCII CODES 32.-63.)
TTCHR3==30			;WAKE UP CHARACTER MASK (ASCII CODES 64.-95.)
TTCHR4==31			;WAKE UP CHARACTER MASK (ASCII CODES 96.-127.)

; ** TTCHR1,TTCHR2,TTCHR3  AND TTCHR4 SHOULD REMAIN TOGETHER IN THAT ORDER

TTFWTH==32			;WAKE UP FIELD WIDTH BYTE COUNT
DEFSTR TTIPSI,TTFWTH,11,6	;INPUT PSI LEVEL
DEFSTR TTOPSI,TTFWTH,17,6	;OUPUT PSI LEVEL
DEFSTR TTFCNT,TTFWTH,35,18	;BYTE COUNT FOR WAKE-UP (0=DISABLED FOR WAKE UP)
TTLINE==33			;LINE COUNTER STORAGE
DEFSTR TLNCT,TTLINE,35,18	;NUMBER OF LINES SINCE LAST PAGE STOP

TTLMAX==34			;NET USER WORD
DEFSTR TTLMX,TTLMAX,35,18	;MAX NUMBER OF LINES
DEFSTR TTULL,TTLMAX,35,18	;NET USER LOGICAL LINK - TTLMAX NOT USED
DEFSTR TTUEC,TTLMAX,17,7	;NET USER ESCAPE CHAR

TTIDLE==35			;171 TODCLK OF LAST TYPIN

TTINPP==36			; INPUT PROCESSING
DEFSTR TIRUT,TTINPP,35,18	; ROUTINE TO CALL TO PROCESS INPUT

TTINPW==37			; WORD AVAILABLE TO INPUT PROCESSING ROUTINES
; DEFINITIONS USED BY ITP
DEFSTR TISLH,TTINPW,0,1		; ^\ SEEN, WAITING FOR COMMAND CHAR
DEFSTR TICCH,TTINPW,1,1		; COMMAND CHAR SEEN, WAITING FOR ARG
DEFSTR TIALP,TTINPW,2,1		; ALLOCATION IN EFFECT
DEFSTR TIHCP,TTINPW,3,1		; A PREFIX CHAR WAS SEEN AT TCI LEVEL
DEFSTR TICHR,TTINPW,11,8	; CHAR AFTER ^\
DEFSTR TILAC,TTINPW,19,8	; LAST ASCII CHARACTER SEEN AT TTCHI LEVEL
DEFSTR TIFCH,TTINPW,35,12	; FULL INPUT CHARACTER
DEFSTR TIHCH,TTINPW,28,5	; HIGH (BUCKY) BITS OF CHARACTER
DEFSTR TILCH,TTINPW,35,7	; LOW BITS OF CHARACTER
; LH available

TTSIZE==40			;SCREEN SIZE PARAMETERS
DEFSTR TPWID,TTSIZE,35,18	;PAGE WIDTH
DEFSTR TPLEN,TTSIZE,17,18	;PAGE LENGTH

TTTMOD==41			; DISPLAY MODE WORD
  REPEAT 0,<			; FLAGS DEFINED IN MONSYM
TM%DPY==1B0			; PROCESS ^P CODES 
TM%SCR==1B1			; SCROLL MODE / WRAP MODE
TM%MOR==1B2			; MORE PROCESSING ENABLED
TM%MVR==1B3			; VERBOSE SORT OF MORE
TM%MSM==1B4			; SMART ABOUT MORE
TM%VBL==1B5			; USE VISIBLE BELL FOR ^G
TM%GRF==1B6			; PROCESS GRAPHICS FUNCTIONS

TM%ITP==1B17			; INTELLIGENT TERMINAL PROTOCOL IN USE
   >
MSKSTR TMDPY,TTTMOD,TM%DPY
MSKSTR TMSCR,TTTMOD,TM%SCR
MSKSTR TMMOR,TTTMOD,TM%MOR
MSKSTR TMMVR,TTTMOD,TM%MVR
MSKSTR TMMSM,TTTMOD,TM%MSM
MSKSTR TMVBL,TTTMOD,TM%VBL
MSKSTR TMGRF,TTTMOD,TM%GRF

TTCHAR==42			;TERMINAL CHARACTERISTICS WORD
  REPEAT 0,<			;FLAGS DEFINED IN MONSYM
TC%MOV==1B0			; ABSOLUTE OR RELATIVE CURSOR MOTION
TC%BS== 1B1			; CURSOR BACK AT LEAST (BACKSPACE)
TC%HOM==1B2			; HOME TO TOP LEFT HAND CORNER
TC%CLR==1B3			; CLEAR ENTIRE SCREEN AT LEAST
TC%SCL==1B4			; CLEAR SELECTIVE PORTIONS OF SCREEN
TC%LID==1B5			; LINE INSERT/DELETE
TC%CID==1B6			; CHARACTER INSERT/DELETE
TC%VBL==1B7			; VISIBLE BELL
TC%MET==1B8			; HAS META (8-BIT) KEY
TC%SCR==1B9			; SCROLLS ON DOWN FROM BOTTOM LINE
TC%RSC==1B10			; REVERSE-SCROLLS ON UP FROM TOP-LINE
TC%OVR==1B11			; OVERWRITES
TC%FCI==1B12			; HAS FULL 12-BIT INPUT CAPABILITY

TC%PRT==1B17			; PRINTING TERMINAL
   >

TTSCPS==43			;SAVED CURSPR POSITION 

TTPPOS==44			;PHYSICAL CURSOR POSITION
DEFSTR TPVPS,TTPPOS,17,18	;PHYSICAL VERTICAL POSITION
DEFSTR TPHPS,TTPPOS,35,18	;PHYSICAL HORIZONTAL POSITION

TTVTSF==45			; RANDOM VTS-RELATED FIELDS AND BITS
DEFSTR TTLCH,TTVTSF,22,8	; CHAR IN LAST LINE POSITION
DEFSTR TSVPS,TTVTSF,29,7	; VERTICAL POS AT TTSND LEVEL
DEFSTR TTCVT,TTVTSF,35,6	; VTS FUNCTION CODE WHICH IS WAITING FOR ARG

TTPADW==46			; PADDING INFORMATION
DEFSTR TPDCH,TTPADW,35,18	; CHAR TO PAD WITH

TTTGV==47			; DISPLAY GRAPHICS CHARACTERISTICS
  REPEAT 0,<			; FIELDS ARE IN MONSYM
TQ%GRF==:1B17			;TERMINAL UNDERSTANDS GRAPHICS PROTOCOL
TQ%SET==:1B16			;TERMINAL SUPPORTS MULTIPLE SETS
TQ%REC==:1B15			;TERMINAL IMPLEMENTS RECTANGLE COMMANDS
TQ%XOR==:1B14			;TERMINAL IMPLEMENTS XOR'ING
TQ%BNK==:1B13			;TERMINAL IMPLEMENTS A STAND-OUT MODE
TQ%VIR==:1B12			;TERMINAL IMPLEMENTS VIRTUAL COORDS
TQ%WID==:17B11			;CHARACTER WIDTH IN GRAPHIC UNITS
TQ%HGT==:76B7			;CHARACTER HEIGHT IN GRAPHIC UNITS
			; THESE NEXT TWO ARE LIKELY TO GET MOVED TO THE
			; LEFT HALFWORD SOME DAY
TR%GIN==:1B18			;TERMINAL HAS A GRAPHICS INPUT DEVICE
TR%GHC==:1B19			;TERMINAL HAS A HARDCOPY OUTPUT DEVICE
   >

TTGPOS==50			;SPACE TO KEEP THE GRAPHICS CURSOR POSITION
				; AND OTHER GOODIES LIKE WHETHER THE TERMINAL
				; IS CURRENTLY DOING GRAPHICS. THERE IS ALSO
				; A FREE LEFT HALFWORD UP ABOVE THAT IS LIKELY
				; TO GET USED FOR INFORMATION OF THAT TYPE.
				; ...NOT USED FOR ANYTHING YET

;LENGTHS OF DYNAMIC BLOCKS

TTDDLN==51			;DEFAULT DYNAMIC DATA SIZE
MSGLEN==11			;SIZE OF MESSAGE BLOCK
;FIELDS OF JFN MODE WORD AS DEFINED IN MONSYM

REPEAT 0,<
TT%OSP==:1B0			;OUTPUT SUPPRESS
TT%MFF==:1B1			;MECHANICAL FORMFEED PRESENT
TT%TAB==:1B2			;MECHANICAL TAB PRESENT
TT%LCA==:1B3			;LOWER CASE CAPABILITIES PRESENT
TT%LEN==:177B10			;PAGE LENGTH
TT%WID==:177B17			;PAGE WIDTH
TT%WAK==:17B23			;WAKEUP FIELD
TT%WK0==:1B18			;WAKEUP CLASS 0 (UNUSED)
TT%IGN==:1B19			;IGNORE THE TT%WAK BITS ON SFMOD
TT%WKF==:1B20			;WAKEUP ON FORMATING CONTROL CHARS
TT%WKN==:1B21			;WAKEUP ON NON-FORMATTING CONTROLS
TT%WKP==:1B22			;WAKEUP ON PUNCTUATION
TT%WKA==:1B23			;WAKEUP ON ALPHANUMERICS
TT%ECO==:1B24			;ECHOS ON
TT%ECM==:1B25			;ECHO MODE
TT%ALK==:1B26			;ALLOW LINKS
TT%AAD==:1B27			;ALLOW ADVICE (NOT IMPLEMENTED)
TT%DAM==:3B29			;DATA MODE
.TTBIN==:0			;BINARY
.TTASC==:1			;ASCII
.TTATO==:2			;ASCII AND TRANSLATE OUTPUT ONLY
.TTATE==:3			;ASCII AND TRANSLATE ECHOS ONLY
TT%UOC==:1B30			;UPPER CASE OUTPUT CONTROL
TT%LIC==:1B31			;LOWER CASE INPUT CONTROL
TT%DUM==:3B33			;DUPLEX MODE
.TTFDX==:0			;FULL DUPLEX
.TT0DX==:1			;NOT USED, RESERVED
.TTHDX==:2			;HALF DUPLEX (CHARACTER)
.TTLDX==:3			;LINE HALF DUPLEX
TT%PGM==:1B34			;PAGE MODE
TT%CAR==:1B35			;CARRIER STATE
>
;LOCAL PARAMETERS

MXFECC==50			;MAX CHARACTERS FOR A FE LINE IN -11

;FIELDS IN TTBBUF

DLSRCF==:400			;DLS RECEIVER FLAG, DATAI WORD
TTNCF==1B19			;FLAG - CHARACTER CAME FROM NETWORK
REPEAT 0,<
TTSCF==1B20			;FLAG - CHARACTER CAME FROM STI
>
TTPIRQ==1B23			;OUTPUT INTERRUPT REQUEST (SOFTWARE)
TTOIRQ==1B24			;OUTPUT INTERRUPT REQUEST (SOFTWARE)
DLSCXF==:1B25			;CARRIER XITION FLAG (SOFTWARE)
CARONB==:1B33

TTXECO==1B27			;INPUT STREAM - CHARACTER ALREADY ECHOED
MAXBBC==^D20			;MAX ENTRIES ALLOWED IN BIGBUF FOR THIS
				; LINE
MXBBC1==5			;WHEN AN X-ON IS ALLOWED AGAIN
MAXABC==TTBSIZ/2		;WHEN LINE IS SHUT OFF
XOFFC=="S"-100			;THE X-OFF CODE (TO SEND)
XONC=="Q"-100			;THE X-ON CODE (TO SEND)
MINICT==30			;WHEN TO SEND AN X-OFF
MINXON==20			;WHERE TO SEND XON
MINCT1==MINICT+10		;WHEN TO FORCE WAKEUP BEFORE XOFF
MINCT2==MINCT1/4+2		;LOWSPEED
MINXOS==40			;WHERE TO RESTART LOW SPEED LINES
MINXOF==4			;WHERE TO RESTART HIGH SPEED LINES

TTLIND=="'"			;UPPER CASE INDICATION CHARACTER FOR OUTPUT
TTCIND=="^"			;CONTROL INDICATION CHARACTER FOR OUTPUT
WRPCHR=="!"			;LINE WRAP INDICATOR
TTFILL==0			;FILLER CHARACTER
PGMONC=="Q"-100			;XON - RESTART OUTPUT IN PAGE MODE (RECEIVED)
PGMOFC=="S"-100			;XOFF - STOP OUTPUT IN PAGE MODE (RECEIVED)
PGMOC2=="A"-100			;RESTART OUTPUT FROM PAUSE ON END-OF-PAGE
FLOCHR=="O"-100			;FLUSH OUTPUT CHARACTER - CTRL-O
VTCESC=="P"-100			;VTS FUNCTION ESCAPE CHARACTER
MORSAF==5			;+++ # LINES TO SUPPRESS EOP STOP 

TTOESC==400			;FUNCTION ESCAPE IN OUTPUT STREAM
.TTPFC==401			;PAGE FULL CODE IN OUTPUT STREAM
.TTMRK==402			;OUTPUT STREAM MARKER, CLEAR OUTPUT FLUSHING
.TTBRK==403			;+++ MAY MARK SAFE PLACE FOR CFOBF

TABSIZ==:^D8			;STANDARD TAB SPACING
DFLWID==1			;OLD STYLE DEFAULT WIDTH
DFLLEN==1			;OLD STYLE DEFAULT LENGTH
LOWSPD==^D600			;HIGHEST SPEED WHERE NTTBL SUFFICES

SALTMO==^D<30*1000>		;145 SENDALL TIMEOUT (MSEC)
	RESCD

;INDEX TO DEV TABLES FOR TTY0

DEVTT0:: DVXTT0


;USUAL DEVICE FLAGS AND STATUS
; 66 LINES/PAGE, 80 CHARS/LINE
; WAKEUP ON ALL, ECHO ON, ECHO DEFERRED
; ACCEPT LINKS, REFUSE ADVICE
; DATA MODE ASCII, NO RAISE, FULL DUPLEX

NORMTF::^D66B10+^D80B17+17B23+1B24+1B26+1B29	;2 CHANGED FOR MIT
NORMTY:: ^D8			;NORMAL TERMINAL TYPE

TAB81::	EXP 1B0+1B8+1B16+1B24+1B32
TAB82::	EXP 1B4+1B12+1B20+1B28
TAB83:	EXP 1B0+1B8+1B16+1B24+1B32

;NORMAL CONTROL CHARACTER SETTINGS

TTICB1::BYTE (2) 0,1,1,1,1,1,1,2,1,2,3,1,1,2,1,1,1,1
TTICB2::BYTE (2) 1,1,1,1,1,1,1,1,1,3,1,1,1,1


;	DEFAULT DEFINITIONS FOR TERMINAL WAKE-UP

TTWKDF:	EXP -20			;WAKE-UP ON ALL CHARACTERS
	EXP -20
	EXP -20
	EXP -20


;OKSKD1 and NOSDK1, but callable at PI level (whence we do nothing)

NSKD1:	CONSZ PI,177B27		;PI IN PROGRESS?
	 RET			;YES, DON'T DO ANYTHING
	NOSKD1			;ELSE, GO NOSKED
	RET

OSKD1:	CONSZ PI,177B27		;PI IN PROGRESS?
	 RET			;YES, NOTHING TO DO
	OKSKD1
	RET

;POINTERS TO TERMINAL TYPE FIELDS
;ASSUME TYPE NUMBER IN T3

TTMBIT:	POINT 3,TTYPE0(T3),2	;MECHANICAL BITS
TTCRPD:	POINT 4,TTYPE0(T3),7	;CR PADDING FOR FULL LINE
TTLFPD:	POINT 4,TTYPE0(T3),11	;LF PADDING FOR ONE LINE
TTTBPD:	POINT 4,TTYPE0(T3),15	;TAB PAD FOR 4 SPACES
TTFFPD:	POINT 4,TTYPE0(T3),19	;FF PAD FOR FULL PAGE
TTTWID:	POINT 8,TTYPE0(T3),27	;WIDTH OF LINE
TTTLEN:	POINT 8,TTYPE0(T3),35	;LENGTH OF PAGE

SCNTIM==^D1000			;CONTROLLER CHECK INTERVAL (1 SEC)

CTRLOF::0			;NEW CTRL-O HANDLING POSSIBLE
	SUBTTL DEFINITIONS FOR TTYPE2 TABLE (PER TERMINAL DISPLAY INFORMATION)

;INDEXED BY TERMINAL TYPE
DEFSTR	DPTB,TTYPE2,35,18	; Address of display control table
	DPTBB==1B0		; if set, then bits 1-35 are 7 bit bytes, else
	DPTBS==1B1		; If set, then RH is address of string, else
	DPTBR==1B2		; If set, then RH is address of routine and
	DPTBP==1B3		; If set, repeat count is "parameterized"
DEFSTR  DPCNT,,17,6		; Estimated length of string or routine
DEFSTR	DPBSZ,,11,4		; Byte size for strings
; Table defining ^P codes in terms of .VT codes, and whether they take
; arguments.

; Note: NARGS can only be 0 or 1 at present

DEFINE	VT(TCOA,NARGS<0>)
   <	NARGS,,TCOA
   >

VTPTAB:	VT(VTOADV)		;ADVANCE LINE		CODE 01 "A"
	VT(VTOBCK)		;CURSOR BACK		CODE 02 "B"
	VT(VTOCLR)		;CLEAR WINDOW		CODE 03 "C"
	VT(VTODWN)		;CURSOR DOWN		CODE 04 "D"
	VT(VTOCEW)		;CLEAR TO END OF WINDOW	CODE 05 "E"
	VT(VTOFWD)		;CURSOR FORWARD		CODE 06 "F"
	VT(VTOVBL)		;VISIBLE BELL		CODE 07 "G"
	VT(VTOHRZ,1)		;HORIZONTAL POSITION	CODE 10 "H"
	VT(VTOINC)		;INSERT CHARACTER	CODE 11 "I"
	VT(VTODLC)		;DELETE CHARACTER	CODE 12 "J"
	VT(VTOERA)		;ERASE CHARACTER	CODE 13 "K"
	VT(VTOCEL)		;CLEAR TO END OF LINE	CODE 14 "L"
	VT(0)			;UNDEFINED		CODE 13 "M"
	VT(0)			;UNDEFINED		CODE 16 "N"
	VT(0)			;UNDEFINED		CODE 17 "O"
	VT(VTOSEC)		;SEND A ^P		CODE 20 "P"
	VT(VTOHMD)		;HOME DOWN		CODE 21 "Q"
	VT(VTORES)		;RESTORE CURSOR POS	CODE 22 "R"
	VT(VTOSAV)		;SAVE CURSOR POS	CODE 23 "S"
	VT(VTOHOM)		;HOME UP		CODE 24 "T"
	VT(VTOUP)		;CURSOR UP		CODE 25 "U"
	VT(VTOVRT,1)		;VERTICAL POSITION	CODE 26 "V"
	VT(0)			;UNDEFINED		CODE 27 "W"
	VT(VTOBEC)		;BACKSPACE AND ERASE CH	CODE 30 "X"
	VT(0)			;UNDEFINED		CODE 31 "Y"
	VT(VTOHMD)		;HOME DOWN		CODE 32 "Z"
	VT(VTOINL)		;INSERT LINE		CODE 33 "["
	VT(VTODLL)		;DELETE LINE		CODE 34 "\"
	VT(0)			;OBSOLETE		CODE 35 "]"
	VT(VTOINC)		;INSERT CHARACTER	CODE 36 "^"
	VT(VTODLC)		;DELETE CHARACTER	CODE 37 "_"
VTPMAX==.-VTPTAB

; Table of VTS function handling routines.

DEFINE TC (RTN)
   <	RTN
   >

VTSTAB:	TC(VTONOP)		; .VTNOP - NOP (force update)
	TC(VTOFWD)		; .VTFWD - Cursor forward
	TC(VTOBCK)		; .VTBCK - Cursor back
	TC(VTOUP)		; .VTUP - Cursor up
	TC(VTODWN)		; .VTDWN - Cursor down
	TC(VTOHRZ)		; .VTHRZ - Set horizontal pos
	TC(VTOVRT)		; .VTVRT - Set vertical pos
	TC(VTOMOV)		; .VTMOV - Move cursor (x and y)
	TC(VTOHOM)		; .VTHOM - Home up
	TC(VTOHMD)		; .VTHMD - Home down
	TC(VTOADV)		; .VTADV - Advance to next line
	TC(VTOSAV)		; .VTSAV - Save pos
	TC(VTORES)		; .VTRES - Restore pos
	TC(VTOCLR)		; .VTCLR - Clear window
	TC(VTOCEW)		; .VTCEW - Clear to end-of-window
	TC(VTOCEL)		; .VTCEL - Clear to end-of-line
	TC(VTOERA)		; .VTERA - Erase character ???
	TC(VTOBEC)		; .VTBEC - Backspace and erase
	TC(VTOLID)		; .VTLID - Line insert/delete
	TC(VTOCID)		; .VTCID - CHaracter insert/delete
	TC(VTOSEC)		; .VTESC - Output VTS escape
	TC(VTOVBL)		; .VTVBL - Visible bell
VTSMAX==VTSTAB-.
	SUBTTL ONCE-ONLY INITIALIZATION

;INITIALIZATION. CALLED FROM STG AT SYSTEM STARTUP

	RESCD			;MUST BE RESIDENT

;INITIALIZE CHAIN OF LINE BUFFERS.  LINE BUFFERS ARE OF SIZE TTSIZ.
;THIS CODE MAKES WORD 0 OF BUFFER N CONTAIN THE ADDRESS OF BUFFER N-1
;AND TTFREB CONTAIN THE ADDRESS OF THE HIGHEST-NUMBERED BUFFER

TTINIT::MOVEI T1,SCNTIM		;TIME FOR NEXT SCAN
	MOVEM T1,TTYTIM		;STASH IT
   IFN .MCFLG,<			;IF HAVE MCB CODE
   IFN CZQDBG,<			;AND IF DEBUG CODE,
	MOVEI T1,CZQBF		;INIT TRACE PTR
	MOVEM T1,CZQPTR
   >>
	MOVEI 1,TTBUFS		;COMPUTE BEGINNING OF BUFFERS
	SETOM TTQCNT		;INIT SCAN COUNT
	TRNE 1,TTSIZ-2		; TO BE N*TTSIZ+1
	ADDI 1,TTSIZ		;FIRST WORD IN BUFFER AREA
	ANDCMI 1,TTSIZ-1	;WHICH IS 0 MOD TTSIZ
	ADDI 1,1		;SUCH THAT EACH BUFFER ENDS 0 MOD ADR
	SETZM SNDALL		;FREE SEND ALL BUFFER ---
	MOVEI 2,NTTBF
	MOVEM 2,TTFREC		;FREE BUFFER COUNT
	SUBI 2,1
	MOVEM 1,TTSIZ(1)	;CONSTRUCT LIST OF FREE BUFFERS
	ADDI 1,TTSIZ
	SOJG 2,.-2
	MOVEM 1,TTFREB		;FREE BUFFER LIST

;INITIALIZE THE STATIC DATA FOR ALL LINES. TTSPWD IS DONE BY DTEINI

	SETOM SALLCK		;INIT SENDALL LOCK
	MOVEI T1,NLINES		;DO ALL LINES
	SETZ T2,		;START WITH LINE 0
TTINI1:	SETZM TTSTAT(T2)	;CLEAR STATUS WORD
	MOVEI T3,MXFECC		;GET DEFAULT LINE ALLOCATION
	STOR T3,TSFMC,(T2)	; AND SAVE IT FOR THIS LINE
	SETZM TTACTL(T2)	;NO DYNAMIC DATA YET
	AOS T2			;GO TO NEXT LINE
	SOJG T1,TTINI1		; UNTIL ALL LINES ARE DONE
	;..
;THIS CODE ESTABLISHES THE TYPE OF EACH LINE. LINES OF A TYPE ARE ASSIGNED
;CONSECUTIVELY, STARTING WITH LINES THAT ARE LOCAL TO THE MACHINE.  THIS
;CODE STORES THE LINE TYPE WITH THE LINE AND SETS UP TT1LIN
;FOR EACH TYPE TO CONTAIN THE NUMBER OF THE FIRST LINE.
;MLC LINES SHOULD BE SECOND,TNT LINES SHOULD BE THIRD
;FOR STATIC STORAGE TO BE ALLOCATED PROPERLY
;ASSEMBLING THIS WAY ALLOWS FOR EFFICIENT STATIC STORAGE
;FOR THESE TYPES, (DEC DIDN'T ALLOW FOR THAT VIA DYNAMIC ALLOCATION)

	;..
	MOVEI T2,0		;T2/ FIRST LINE IS LINE 0
	MOVEI T3,TT.FE		;T3/ CODE FOR FRONT-END LINES
	MOVEI T4,NTTFE		;T4/ NUMBER OF FRONT END LINES
	CALL SETTYP
	HRLI T4,-NTTMLC		;# MLC TYPE LINES
	HRR T4,T2		;1ST ONE
	MOVEM T4,MLCXWD		;FILL OUT USEFUL AOBJN PTR
	MOVEI T3,TT.MLC		;MLC TYPE
	MOVEI T4,NTTMLC		;HOW MANY
	CALL SETTYP
	HRLI T4,-NTTTVT		; NEG. NUMBER OF TCP VIRTUAL LINES
	HRR T4,T2		; FIRST ONE
	MOVEM T4,TVTPTR		; SET AOBJN PTR OVER TVTS
	MOVEI T3,TT.TVT		; CODE FOR TVTS
	MOVEI T4,NTTTVT		; HOW MANY OF THEM
	CALL SETTYP		; SET THEM UP
	MOVEI T3,TT.DZ		;T3/ CODE FOR DZ11 LINES
	MOVEI T4,NTTDZ		;T4/ NUMBER OF DZ11 LINES
	CALL SETTYP
	MOVEI T3,TT.MCB		;T3/ CODE FOR MCB LINES
	MOVEI T4,NTTMCB		;T4/ NUMBER OF MCB LINES
	CALL SETTYP
	MOVEI T3,TT.PTY		;T3/ CODE FOR PSEUDO-TERMINALS
	MOVEI T4,NTTPTY		;T4/ NUMBER OF PTY'S
	CALL SETTYP
	MOVEI T3,TT.D10		;T3/ CODE FOR DC10 LINES
	MOVEI T4,NTTD10		;T4/ NUMBER OF DC10 LINES
	CALL SETTYP
	MOVEI T3,TT.NVT		;T3/ CODE FOR ARPANET LINES
	HRLI T4,-NTTNVT		;SET UP NVT PAR WITH -NTTNVT,,FIRST NVT
	HRR T4,T2		;GET FIRST NVT
	MOVEM T4,NVTPTR		;STORE IT AWAY
	MOVEI T4,NTTNVT		;T4/ NUMBER OF ARPANET LINES
	CALL SETTYP
	MOVEI T3,TT.CVT		;T3/ CODE FOR CHAOS LINES
	HRLI T4,-NTTCVT		;SET UP NVT PAR WITH -NTTCVT,,FIRST CVT
	HRR T4,T2		;GET FIRST CVT
	MOVEM T4,CVTPTR		;STORE IT AWAY
	MOVEI T4,NTTCVT		;T4/ NUMBER OF CHAOS LINES
	CALL SETTYP

;INITIALIZE POINTERS TO TTBBUF

	SETZM TTBIGO
	SETZM TTBIGC
	SETZM TTBIGI

	SETZM TTCQLN		;INITIALIZE FOR TTHNG4

	SAVEAC <Q1>
	MOVSI Q1,-NLTYPS	;FIND NUMBER OF LINE TYPES
TYINLP:	TDCALX Q1,<<DZ,DZINIT>,<ML,MLCINI>,<CH,CHTINI>>,<RET>
	AOBJN Q1,TYINLP		;DO ALL TYPES
	CALLRET TTSTRT
;SETTYP - SET THE TERMINAL TYPE FOR A GROUP OF LINES

;ACCEPTS:
;	T2/ CURRENT LINE NUMBER (FIRST FOR THIS TYPE)
;	T3/ LINE TYPE
;	T4/ NUMBER OF LINES OF THIS TYPE

;	CALL SETTYP

;RETURNS +1: ALWAYS
;		T2/ UPDATED LINE NUMBER (FIRST LINE OF NEXT TYPE)

SETTYP:	JUMPG T4,SETTY2		;IF NO LINES OF THIS TYPE,
	SETOM TT1LIN(T3)	;SET FIRST LINE TO -1
	RET			; AND RETURN

SETTY2:	MOVEM T2,TT1LIN(T3)	;STORE FIRST LINE FOR THIS TYPE
SETTY1:	STOR T3,TTSTY,(T2)	;SAVE LINE TYPE FOR THIS LINE
	AOS T2			;NEXT LINE NUMBER
	SOJG T4,SETTY1		;GO DO THE NEXT LINE IN THIS TYPE
	CAMN T3,CTYTYP		;IS THIS THE LINE TYPE FOR THE CTY?
	JRST [	CALL INICTY	;YES. INITIALIZE IT
		AOS T2		;POINT TO NEXT LINE
		RET]
	RET
;INICTY - INITIALIZE THE CTY

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER
;	T3/ LINE TYPE

;	CALL INICTY

;RETURNS +1: ALWAYS

;CTY IS A SPECIAL CASE. IT IS ALWAYS LINE 'CTYLNO', AND ITS DYNAMIC DATA
;IS PERMANENTLY ALLOCATED. CTYUNT AND CTYINT WILL BE FIXED BY IDCTY.

INICTY:	SAVET
	MOVEM T2,CTYLNO		;SAVE INTERNAL LINE NUMBER
	SETOM CTYINT		;INITIALIZE INTERNAL EQUIVALENT OF ACTUAL
				; CTY LINE ON .FEDLS DEVICE
	HRRZ T1,DDLTBL(T3)	; AND FULL LENGTH BLOCK
	HRLI T1,.RESP1		;INDICATE NOT SWAPPABLE
	MOVEI T2,.RESTP
	CALL ASGRES		;GET RESIDENT SPACE
	 BUG(NOCTY)
	MOVE T2,CTYLNO		;T2/ LINE NUMBER, T1/ ADDRESS OF BLOCK
	MOVE T3,CTYTYP		;INDICATE LINE TYPE
	STOR T3,TTSTY,(T2)
	CALL TTSETL		;SET INITIAL VALUES IN DYNAMIC DATA
	SETONE TTPRM,(T1)	;DON'T DEALLOCATE THIS DYNAMIC DATA
	MOVEM T1,TTACTL(T2)	;POINT TO DYNAMIC DATA
	RET
;TTSET - SET INITIAL VALUES FOR A LINE

;ACCEPTS:
;	T1/ ADDRESS OF DYNAMIC DATA
;	T2/ LINE NUMBER

;CALL TTSET

;RETURNS +1: ALWAYS
;Leaves TTACTL unchanged to protect against state changes
; * * * *
;NEEDS WORK - CAN'T INIT TOO MANY WORDS
; * * * *

TTSETL:	LOAD T4,TTSTY,(T2)	;GET THE LINE TYPE
	MOVE T4,DDLTBL(T4)	;GET LONG BLOCK LENGTH
	JRST TTSET

TTSETS:
TTSETM:	MOVEI T4,MSGLEN		;INDICATE MESSAGE BLOCK
	JRST TTSET

TTSET:	SAVEQ
	TDCALL S,<<FE,TTSETF>>
TTSET1:	LOAD T3,TTSTY,(T2)	;GET LINE TYPE FROM STATIC
	STOR T3,TLTYP,(T1)	; AND COPY TO DYNAMIC
;17 	MOVE Q1,NORMTY		;GET NORMAL TERMINAL TYPE
	CALL GTYPP0		;17 GET TERMINAL TYPE FROM PERMANENT AREA
	STOR T3,TTTYP,(T1)	;17 SET IN DYNAMIC DATA
	STOR T2,TINTL,(T1)	;STORE LINE NUMBER IN DYNAMIC DATA
	MOVE Q1,IBFRC		;GET DEFAULT BUFFER CONTROL
	MOVEM Q1,TTBFRC(T1)	; AND STORE IN DYNAMIC DATA
	CAIN T4,MSGLEN		;IS THIS A MESSAGE-LENGTH BLOCK?
	RET			;YES. NO MORE INITIALIZATION
	CAME T2,CTYLNO		;CTY ASSIGN?
	CALL SETOBF		;NO, SET OUTPUT BUFFER COUNTS
	SETONE TTIPSI,(T1)	;SET NO PSI
	SETONE TTOPSI,(T1)	;INPUT OR OUTPUT
	SETONE TTPSFK,(T1)	;AND NO FORK	
	MOVE Q1,TTICB1		;SETUP USUAL CONTROL CHARACTER MODES
	MOVEM Q1,FCMOD1(T1)
	MOVE Q1,TTICB2
	MOVEM Q1,FCMOD2(T1)
	SETOM TTLINK(T1)	;NO LINKS TO OTHER LINES
	SETZM TTLPOS(T1)	;CLEAR LOGICAL CURSOR POSITION
	SETZM TTPPOS(T1)	;CLEAR PHYSICAL CURSOR POSITION
	SETZM TTSCPS(T1)	;CLEAR SAVED CURSOR POSITION
	SETZM TTVTSF(T1)	;CLEAR VTS FLAGS
	MOVX Q1,TM%SCR		;DEFAULT TO SCROLL MODE
	MOVEM Q1,TTTMOD(T1)

;17 BEGIN DELETION
REPEAT 0,<
	MOVE Q1,NORMTF		;USUAL DEVICE FLAGS AND STATUS
	CAMN T2,CTYLNO		;ASSIGNING CTY?
	TXZ Q1,TT%ALK		;YES - DISALLOW TALK LINKS
	LOAD T3,TLTYP,(T1)	;GET TYPE OF LINE AGAIN
	CAIN T3,TT.PTY		;IS IT A PTY?
	TXZ Q1,TT%PGM		;YES. NO XON/XOFF THEN
	LOAD T3,TT%WID,Q1	;GET STANDARD WIDTH
	LOAD T4,TT%LEN,Q1	;GET LENGTH
	SETZRO <TT%WID,TT%LEN>,Q1 ;CLEAR OUT THESE VALUES
	DPB Q1,[POINT 35,TTFLGS(T1),35] ;STORE STANDARD VALUES IN DYNAMIC DATA
	PUSH P,T2		;SAVE
	MOVE T2,T1
	TDCALL D,<<FE,TTEXF>,<MC,MCEXF>>	;ENABLE XOFF RECOGNITION IN FE
	STOR T3,TPWID,(T2)	;SET UP STANDARD WIDTH
	STOR T4,TPLEN,(T2)	;STORE PAGE LENGTH
>;17 END DELETION

;17 BEGIN ADDITION - T3/ TERMINAL TYPE FOR TTTxxx BYTEPTRS
	LDB Q1,TTTWID		;GET STANDARD WIDTH
	STOR Q1,TPWID,(T1)	;SET IT FOR THIS LINE
	LDB Q1,TTTLEN		;GET STANDARD LENGTH
	STOR Q1,TPLEN,(T1)	;SET IT FOR THIS LINE
	HRRZ Q1,NORMTF		;USUAL DEVICE FLAGS AND STATUS
	CAMN T2,CTYLNO		;ASSIGNING CTY?
	TXZ Q1,TT%ALK		;YES - DISALLOW TALK LINKS
	LDB T4,TTMBIT		;GET MECH BITS FOR THIS TERM TYPE
	DPB T4,[POINT 3,Q1,3]	;PUT WHERE NOTICED
	LOAD T3,TLTYP,(T1)	;GET TYPE OF LINE AGAIN
	CAIN T3,TT.PTY		;IS IT A PTY?
	TXZ Q1,TT%PGM		;YES. NO XON/XOFF THEN
	MOVEM Q1,TTFLGS(T1)	;SAVE FLAGS
	PUSH P,T2		;SET THINGS UP STANDARDLY (T2/ DYN DATA PTR)
	MOVE T2,T1
	TDCALL D,<<FE,TTEXF>,<MC,MCEXF>>	;ENABLE XOFF RECOGNITION IN FE
;17 END ADDITION
	MOVEI T3,PGMOC2		;SET DEFAULT PAGE UNPAUSE CHARACTER
	TDCALL D,<<MC,RSKP>>	;DECNET NVT?
	 MOVEI T3,PGMONC	;NOT NVT, USE SAME AS COMMAND UNPAUSE
	STOR T3,TTUPC,(T2)
	TDCALL D,<<MC,RSKP>>	;DECNET NVT?
	 MOVEI T3,PGMOFC	;NO, USE SAME AS COMMAND PAUSE
	STOR T3,TTPPC,(T2)
	CALL TTNTYP		;SET TYPE DEPENDANT DATA
	SETONE TWFRK,(T2)	;INDICATE NO FORK WAITING
	MOVE Q1,JOBNO		;GET THIS JOB NUMBER
	STOR Q1,TCJOB,(T2)	;INDICATE THAT IT OWNS THE TERMINAL
	SETONE TTPFK,(T2)	;NO SCTTY FORK YET
	XMOVEI T1,TTWKDF	;POINT TO DEFAULT 4-WORD MASK
	CALL TTSBM		;GO SET IT
	SETZ T1,		;TURN OFF FIELD WIDTH
	CALL TTSFW
	MOVE T1,TODCLK		;171 LAST TYPEIN IS NOW
	MOVEM T1,TTIDLE(T2)	;171 
	MOVE T1,T2		;RESTORE T1
	POP P,T2		;RESTORE T2
	RET
;TTNTYP - CALLED WHEN TTTYP IS CHANGED
; T2/ ADDRESS OF DYNAMIC DATA

TTNTYP::LOAD T1,TTTYP,(T2)
	LOAD T1,DPTB,(T1)	; GET PTR TO DISPLAY TABLE
	MOVE T3,DPYCAP(T1)	; GET TERMINAL CHARACTERISTICS
	MOVEM T3,TTCHAR(T2)	; STORE IN DYNAMIC DATA
	MOVE T4,DPYSIZ(T1)	; GET SCREEN SIZE
	TXNE T3,TC%WRP!TC%PRT	; IF A LUSING TERMINAL
	 SOJ T4,		; SUBTRACT ONE COL FOR WRAPCHAR
	MOVEM T4,TTSIZE(T2)	; AND KEEP IN DYNAMIC DATA
	CALL SETEOP		; SET MAX LINE INDICATOR
	MOVE T4,DPYPAD(T1)	; CHAR TO USE FOR PADDING
	STOR T4,TPDCH,(T2)
	SETZM TTTGV(T2)		; FOR NOW, JUST ZERO GRAPHICS VARIABLE
	RET

;SET MAX LINE VALUE DEPENDING ON TYPE OF EOP PROCESSING
;	T2/ PTR TO DYNAMIC DATA
;
SETEOP:	LOAD T3,TPLEN,(T2)	;GET PAGE LENGTH
	TMNN TMMVR,(T2)		;VERBOSE END OF PAGE?
	IFSKP.			;ADJUST MAX LINE COUNTER CORRECTLY
	  SUBI T3,2
	ELSE.
	  SUBI T3,1
	ENDIF.
	STOR T3,TTLMX,(T2)	;AND SET IT UP
	RET
;TTSTRT - ACTIVATE ALL LINES.  USED ON RESTART AS WELL AS START

TTSTRT:	SETZM TTHNGT
	SETZM TTHNGN
	SAVEQ			;SAVE REGISTERS
	MOVSI Q1,-NLTYPS	;GET THE COUNT OF TYPES
TYRSLP:	TDCALX Q1,<<DZ,DZRSTR>>,<RET>
	AOBJN Q1,TYRSLP		;DO ALL LINES
	RET


;TTRSET - RESUME RUNNING TTY'S AFTER POWER FAILURE

;* * * *
;DON'T DO THIS FOR FE LINES.  MAYBE REMOVE ALL OF IT
; * * * *

;THIS CODE HANDLES ALL LINES. IN FACT, NON-PHYSICAL LINES WON'T HAVE
;TTOTP SET, SO TTSND0 WILL NOT BE CALLED FOR THEM

TTRSET::MOVSI 2,-NLINES		;DO ALL LINES
TTRST1:	PUSH P,T2		;SAVE LINE NUMBER
	CALL STADY		;IS LINE ACTIVE?
	 JRST TTRST2		;NOT AT ALL
	JE TTOTP,(T2),TTRST2	;ACTIVE IN SOME WAY. WAS OUTPUT IN PROGRESS?
	SETZRO TTOTP,(T2)	;YES, CLEAR FLAG SO IT WILL GET RESTARTED
	CALL TTSND0		;RESTART IT
TTRST2:	POP P,T2		;RESTORE COUNTER AND LINE NUMBER
	AOBJN 2,TTRST1
	CALLRET TTSTRT		;ACTIVATE DATASETS, ETC.
;THE FOLLOWING ROUTINES PROVIDE THE MECHANISM FOR INSURING THAT A LINE
;REMAINS ACTIVE (AND THUS THE ADDRESS OF ITS DYNAMIC DATA REMAINS VALID)
;WHILE ITS DYNAMIC DATA IS BEING USED.  TO ADDRESS A LINE'S DYNAMIC DATA
;FROM PROCESS CONTEXT, DO THE FOLLOWING:

;1. CALL LCKTTY, WHICH WILL INCREMENT THE LOCK COUNT IN THE LINE'S DYNAMIC
;DATA AND RETURN NOINT.

;2. IF A DISMISS MUST BE DONE, CALL TTYDIS, WHICH WILL PLACE AN ENTRY ON THE
;JOB'S JSB STACK AND GO OKINT.  AT THIS POINT THE USER CAN CTRL/C, IN
;WHICH CASE THE PROCESSING OF THE JSB STACK WILL DECREMENT THE LINE'S
;LOCK COUNT.

;3. WHEN THE DISMISS COMPLETES, CALL TTYAWK, WHICH WILL REMOVE THE STACK
;ENTRY AND RETURN NOINT

;4. WHEN THE DYNAMIC DATA IS NOT LONGER NEEDED, CALL ULKTTY, WHICH WILL
;DECREMENT THE LOCK COUNT AND RETURN OKINT.

;WHEN ADDRESSING DYNAMIC DATA FROM SCHEDULER CONTEXT, CALLING LCKTTY
;AND ULKTTY IS LEGAL BUT DOES NOT INCREMENT THE COUNT.  IT IS ASSUMED
;THAT THE DYMAMIC DATA WILL NOT DISAPPEAR WHILE THE SCHEDULER IS RUNNING.
;THEREFORE, CALLING STADYN WILL HAVE THE SAME EFFECT; I.E. CONVERTING
;LINE NUMBER TO ADDRESS OF DYNAMIC DATA

;IF THE DYNAMIC DATA IS TO BE ADDRESSED OVER A VERY SHORT PERIOD, THE
;CALLER CAN GO NOSKED, CALL STADYN, ADDRESS THE DATA, AND THEN GO
;OKSKED
	SUBTTL LINE NUMBER/ADDRESS CONVERSION

;STADYN - CONVERT STATIC LINE NUMBER TO DYNAMIC ADDRESS

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL STADYN

;RETURNS +1: LINE DOES NOT HAVE FULL-SIZED DYNAMIC DATA BASE,
;		T2/ -1 IF LINE IS BECOMING ACTIVE
;			OR
;		T2/ 0 IF LINE IS TOTALLY INACTIVE
;			OR
;		T2/ ADDRESS OF DYNAMIC DATA BLOCK IF BLOCK IS NONSTANDARD
;	+2: LINE HAS FULL-SIZED DYNAMIC DATA BASE,
;		T2/ ADDRESS OF DYNAMIC DATA BLOCK

;CLOBBERS NO AC'S

;CALLER SHOULD INSURE THAT THE TERMINAL'S DATA CANNOT GO AWAY EITHER
;BY BEING NOSKED OR BY CALLING LCKTTY

STADYN::HRRZS T2		;BE SURE THAT
	 CAILE T2,NLINES	;LINE NUMBER IS IN ALLOWED RANGE
	  RET			;NO, RETURN UNSUCCESFULLY
	SKIPLE T2,TTACTL(T2)	;HAVE A BLOCK?
	RETSKP			;YES. FULLY ACTIVE LINE
	CAME T2,[-1]		;NO. IS IT BECOMING ACTIVE?
	TXZ T2,TTSHBK		;NO. IS MESSAGE OR SHORT. RETURN IT
	RET			;DONE

;VARIENT OF ABOVE - RETURNS +1 IF NO BLOCK PRESENT, +2 IF ANY BLOCK PRESENT

STADY::	SKIPLE T2,TTACTL(T2)	;FULL BLOCK?
	RETSKP			;YES
	CAME T2,[-1]
	TXZ T2,TTSHBK
	JUMPG T2,RSKP		;RETURN +2 IF ANY BLOCK
	RET

;DYNSTA - CONVERT ADDRESS OF STATIC DATA BASE TO INTERNAL LINE NUMBER

;ACCEPTS: T2/ ADDRESS OF STATIC DATA BASE

;	CALL DYNSTA

;RETURNS +1: ALWAYS,
;		T2/ INTERNAL LINE NUMBER

DYNSTA::LOAD T2,TINTL,(T2)	;GET FROM DYNAMIC DATA
	RET			;RETURN
;LCKTTY - GET ADDRESS OF DYNAMIC DATA AND PREVENT DEALLOCATION

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL LCKTTY

;RETURNS +1: LINE DOES NOT HAVE FULL-SIZED DYNAMIC DATA BASE,
;		T2/ -1 IF LINE IS BECOMING ACTIVE
;			OR
;		T2/ 0 IF LINE IS TOTALLY INACTIVE
;			OR
;		T2/ ADDRESS OF DYNAMIC DATA BLOCK IF BLOCK IS NONSTANDARD
;	+2: LINE HAS FULL-SIZED DYNAMIC DATA BASE,
;		T2/ ADDRESS OF DYNAMIC DATA BLOCK

;NOTE THAT THE CALLER MUST CALL ULKTTY BEFORE THE DATA BLOCK CAN BE
;DEASSIGNED. ULKTTY WILL ACCEPT ANY OUTPUT FROM LCKTTY, SO IF THE CALLER
;IS INTERESTED ONLY IN FULLY ACTIVE BLOCKS, IT SHOULD CALL ULKTTY EVEN
;IF LCKTTY TAKES A NON-SKIP RETURN

;CLOBBERS NO AC'S

LCKTTY::NOSKD1			;NO OTHER JOBS RUNNING UNTIL DATA LOCKED
	SKIPG T2,TTACTL(T2)	;ANY DATA BASE AT ALL?
	JRST [	SKIPE T2	;NOT FULLY ACTIVE. IS IT ASSIGNED?
		CAMN T2,[-1]	;OR BECOMING ACITVE?
		RETBAD (,<OKSKD1>) ;NOT A BLOCK
		TXZ T2,TTSHBK	;MESSAGE OR SHORT. MAKE IT ADDRESSABLE
		CALLRET LCKTT]	;LOCK IT
	CALL LCKTT		;LINE IS FULLY ACTIVE. DO THE LOCKING
	RETSKP			;INDICATE FULL-LENGTH BLOCK

;LCKTT - DO THE REAL LOCKING

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL LCKTT

;RETURNS +1: ALWAYS, NOINT

;PRESERVES ALL AC'S

LCKTT:	SETZRO TTDAL,(T2)	;FLUSH DEALLOCATE REQUEST IF ANY
	SKIPE INSKED		;DON'T LOCK IF IN SCHEDULER
	RET
	NOINT			;BE NOINT WHILE LINE IS LOCKED
LCKTT1:	INCR TTLCK,(T2)		;BUMP THE LOCK
	JE TTLCK,(T2),LCKTT2	;CHECK FOR BAD LOCK
	OKSKD1			;ALLOW SCHEDULING ONCE LOCKED
	RET
LCKTT2:				;HERE TO HANDLE BAD LOCK
	BUG(TTLOKB)		;KILL US
	JRST LCKTT1		;HANDLE IF WE ARE CONTINUED FROM BUGHLT
;ULKTTY - CLEAR LOCK BIT

;ACCEPTS:
;	T2/ OUTPUT FROM LCKTTY

;	CALL ULKTTY

;RETURNS +1: ALWAYS, OKINT

;CLOBBERS NO AC'S

ULKTTY::SKIPN INSKED		;DON'T DECREMENT COUNT IF IN SCHEDULER
	SKIPG T2		;NO COUNT IF INACTIVE OR BECOMING ACTIVE
	RET
	JE TTLCK,(T2),ULKTMP	;CHECK FOR OVERLY DECREMENTING
	DECR TTLCK,(T2)		;DECREMENT LINE'S LOCK COUNT
	IFQN. TTDAL,(T2)	;DID SOMEBODY TRY TO DEALLOCATE THIS?
	  CALL TTYDED		;YES, DO IT NOW
	   NOP
	ENDIF.
	OKINT			;ALLOW INTERRUPTS NOW THAT BLOCK IS UNLOCKED
	RET

ULKTMP:	SAVELN
	LOAD T2,TINTL,(T2)
	BUG(ULKBAD,<<T2,D>>)
	OKINT
	RET

;ULKTT - DECREMENT THE LOCK COUNT. CALLED ONLY FROM FREE

ULKTT::	JE TTLCK,(T2),ULKTT2	;CHECK FOR BAD UNLOCK
	DECR TTLCK,(T2)		;UNLOCK THE TTY
ULKTT1:	IFQN. TTDAL,(T2)	;DID SOMEBODY TRY TO DEALLOCATE THIS?
	  CALL TTYDED		;YES, DO IT NOW
	   NOP
	ENDIF.
	RET
ULKTT2:				;HERE ON BAD UNLOCK
	BUG(TTULKB)		;KILL US
	JRST ULKTT1		;HANDLE IF CONTINUE AFTER BUGHLT
;ROUTINES TO ADJUST LOCK STATUS BEFORE AND AFTER DISMISSING.
;THIS CODE PUTS AN ENTRY ON THE JSB STACK IN THE EVENT THE PROCESS
;IS INTERRUPTED WHILE DISMISSED.

;PUT ENTRY ON JSB STACK, AND GO OKINT
;ACCEPTS:	T2/ ADDRESS OF DYNAMIC DATA

	REPEAT 0,<		;NOT USED
TTYDIS:	JE TTLCK,(T2),R		;THIS IS A HACK TO KEEP FSIINI HAPPY.
				;SINCE THE SWAPPABLE MONITOR IS NOT
				;LOADED YET, WE CAN'T USE THE NORMAL
				;LOCKING STATEGY. THIS IS ACCEPTABLE
				;HERE SINCE NO CONFUISION CAN RESULT.
	SKIPE INSKED		;IN THE SCHEDULER?
	RET			;YES. DON'T MANIPULATE THE JSB STACK
	SAVET			;SAVE ALL REGISTERS
	LOAD T1,TINTL,(T2)	;GET INTERNAL LINE NUMBER
	MOVEI T2,STKCD3		;GET PROPER CODE
	CALL JSBSTK		;QUEUE UP THE ENTRY
	OKINT			;ALLOW INTS NOW
	RET			;AND DONE

;DISMISS WAS SATISFIED. DEQUEUE THE ENTRY AND GO NOINT

TTYAWK:	JE TTLCK,(T2),R		;THIS IS A HACK TO KEEP FSIINI HAPPY.
				;SINCE THE SWAPPABLE MONITOR IS NOT
				;LOADED YET, WE CAN'T USE THE NORMAL
				;LOCKING STATEGY. THIS IS ACCEPTABLE
				;HERE SINCE NO CONFUISION CAN RESULT.
	SKIPE INSKED		;IN THE SCHEDULER?
	RET			;YES. DON'T MANIPULATE THE JSB STACK
	SAVET			;SAVE ALL REGISTERS
	NOINT			;PREVENT INTS
	LOAD T1,TINTL,(T2)	;GET INTERNAL LINE NUMBER
	MOVEI T2,STKCD3		;GET TYPE
	CALLRET JSFRMV		;REMOVE ENTRY AND DONE
	>			;END OF REPEAT 0
	SUBTTL ALLOCATION/DEALLOCATION

;TTYASO - ASSIGN TERMINAL FOR OPENF

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL TTYASO

;RETURNS +1: FAILED,
;		T1/ 1B0 + ADDRESS OF ROUTINE IF NEED TO DISMS
;		T1/ ERROR CODE IF FAILED
;	 +2: SUCCEEDED

;PRESERVES T2

	SWAPCD
TTYASO::SAVELN
	STKVAR <TTYALN>
	MOVEM T2,TTYALN		;SAVE LINE NUMBER
	NOSKD1			;NO STATE CHANGE PLEASE
	CALL STADYN		;IS LINE FULLY ACTIVE?
	 SKIPA			;NO.
	JRST TTYAO4		;FULLY ACTIVE. HANDLE SPECIALLY
	JUMPLE T2,TTYAO1	;SEE IF SHORT OR MESSAGE BLOCK IN USE

;TTACTL>0. LINE IS TEMPORARILY ACTIVE FOR SYSTEM MESSAGE OR SENDALL
;WAIT UNTIL TTACTL<=0 OR FULL-LENGTH BLOCK HAS BEEN ASSIGNED AND TRY AGAIN.

	OKSKD1
	MOVE T1,[TSACT1]	;YES. SET UP TO WAIT
	TXO T1,1B0		;INDICATE IT'S A ROUTINE ADDRESS
	RETBAD 			;LET CALLER DO A DISMS

TTYAO1:	JUMPE T2,TTYAO2		;SEE IF LINE BECOMING ACTIVE

;TTACTL<0. LINE IS BECOMING ACTIVE (ANOTHER FORK IN THIS JOB IS
;INITIALIZING IT). WAIT UNTIL LINE IS INACTIVE OR HAS FULL-LENGTH BLOCK
;AND TRY AGAIN

	OKSKD1
	MOVE T1,[TSACT2]	;YES. SET UP TO WAIT
	TXO T1,1B0		;INDICATE IT'S A ROUTINE ADDRESS
	RETBAD 			;LET CALLER DO A DISMS

;TTACTL=0. ASSIGN A DYNAMIC BLOCK FOR THE LINE AND INITIALIZE ITS VALUES.

TTYAO2:	MOVE T2,TTYALN		;GET LINE NUMBER
	SETOM TTACTL(T2)	;INDICATE BEING INITIALIZED
	OKSKD1
	LOAD T1,TTSTY,(T2)	;GET THE LINE TYPE
	MOVE T1,DDLTBL(T1)	;GET LONG BLOCK LENGTH
	HRLI T1,.RESP3		;T1/ INDICATE PROCESS CONTEXT
	MOVEI T2,.RESTP
	CALL ASGRES		;GET SOME FREE SPACE
	 JRST TTYAO3		;NO SPACE AVAILABLE
	MOVE T2,TTYALN		;T2/ LINE NUMBER, T1/ ADDRESS OF DYNAMIC BLOCK
	CALL TTSETL		;INITIALIZE VALUES FOR TERMINAL
	MOVEM T1,TTACTL(T2)	;MAKE STATIC DATA POINT TO DYNAMIC
	RETSKP

;FAILED TO GET RESIDENT STORAGE. LET THE OPENF FAIL

TTYAO3:	MOVE T2,TTYALN		;GET LINE NUMBER
	SETZM TTACTL(T2)	;RESTORE TTACTL TO PREVIOUS VALUE
	RETBAD(MONX05)		;NO FREE SPACE AVAILABLE

;LINE WAS ALREADY ACTIVE. IF PERMANENT, IT MAY BE BECOMING
;ACTIVE. IN THAT CASE, MAKE IT ACTIVE.

TTYAO4:	OKSKD1
	JE <TTBAC,TTPRM>,(T2),RSKP	;IF NOT BECOMING ACTIVE, OK AS IS
	MOVE T3,JOBNO		;GET THIS JOB'S NUMBER
	STOR T3,TCJOB,(T2)	;INDICATE IT OWNS THIS TERMINAL
	SETZRO TTBAC,(T2)	;INDICATE NOT BECOMING ACTIVE
	RETSKP

	ENDSV.			;END STKVAR

;TSACT1 - SCHEDULER TEST TO SEE IF LINE IS AVAILABLE

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF LINE IS INACTIVE, BECOMING ACTIVE, OR HAS A FULL-LENGTH
;BLOCK

	RESCD
TSACT1::HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JUMPG T2,0(T4)		;NOT FULLY ACTIVE
	JRST 1(T4)		;FULLY ACTIVE. WAKEUP

;TSACT2 - SCHEDULER TEST TO SEE IF LINE IS AVAILABLE

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF LINE IS INACTIVE OR FULLY ACTIVE

TSACT2:	HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	JUMPN T2,0(T4)		;NOT FULLY ACTIVE
	JRST 1(T4)		;FULLY ACTIVE. WAKEUP
;TTYASC - ASSIGN TERMINAL AS CONTROLLING TERMINAL FOR A JOB

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTYASC

;RETURNS +1: FAILED,
;		T1/ ERROR CODE
;	 +2: SUCCEEDED

;PRESERVES T2

	SWAPCD
TTYASC::SAVELN
	STKVAR <TTYALN>
	MOVEM T2,TTYALN		;SAVE LINE NUMBER
	NOSKD1
	CALL STADYN		;POINT TO DYNAMIC DATA
	 SKIPA			;NOT FULLY ACTIVE
	JRST TTYAC4		;FULLY ACTIVE. GO HANDLE SPECIALLY
	JUMPLE T2,TTYAC1	;SEE IF SHORT OR MESSAGE BLOCK IN USE

;TTACTL>0. LINE IS TEMPORARILY ACTIVE FOR SYSTEM MESSAGE OR SENDALL.
;FAIL ON THE ASSUMPTION THAT THE USER WILL TYPE ANOTHER CTRL/C.

	OKSKD1
	RETBAD (TTYX01)

;TTACTL<=0. LINE IS INACTIVE OR BECOMING ACTIVE.  ASSIGN STORAGE AND
;INITIALIZE VALUES

TTYAC1:	MOVE T2,TTYALN		;GET LINE NUMBER
	SETOM TTACTL(T2)	;INDICATE BEING INITIALIZED
	OKSKD1
	LOAD T1,TTSTY,(T2)	;GET THE LINE TYPE
	MOVE T1,DDLTBL(T1)	;GET LONG BLOCK LENGTH
	HRLI T1,.RESP3		;T1/ INDICATE PROCESS CONTEXT
	MOVEI T2,.RESTP
	CALL ASGRES		;GET SOME FREE SPACE
	 JRST TTYAC3		;NO SPACE AVAILABLE
	MOVE T2,TTYALN		;T2/ LINE NUMBER, T1/ ADDRESS OF DYNAMIC BLOCK
	CALL TTSETL		;INITIALIZE VALUES FOR TERMINAL
	MOVEM T1,TTACTL(T2)	;MAKE STATIC DATA POINT TO DYNAMIC
	RETSKP

;FAILED TO GET RESIDENT STORAGE. FAIL

TTYAC3:	MOVE T2,TTYALN		;GET LINE NUMBER
	SETZM TTACTL(T2)	; INDICATE INACTIVE
	RETBAD (MONX05)		; NO FREE SPACE AVAILABLE

;LINE WAS ALREADY ACTIVE. IF PERMANENT, IT MAY BE BECOMING
;ACTIVE. IN THAT CASE, MAKE IT ACTIVE.

TTYAC4:	OKSKD1
	JE TTPRM,(T2),RSKP
	MOVE T3,JOBNO		;GET THIS JOB'S NUMBER
	STOR T3,TCJOB,(T2)	;INDICATE IT OWNS THIS TERMINAL
	SETZRO TTBAC,(T2)	;INDICATE NOT BECOMING ACTIVE
	RETSKP

	ENDSV.			;END STKVAR
;TTYDEA - DEALLOCATE A DYNAMIC BLOCK

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTYDEA

;RETURNS +1: FAILURE, (NO CASES CURRENTLY)
;	 +2: SUCCESS

	RESCD

TTYDED:	SAVELN			;ENTRY WITH T2/ DYNAMIC PTR
	STKVAR <TTYDLN,TTYDAD>
	DYNST
	JRST TTYDE4

TTYDEA::TDCALL S,<<NT,NVTDET>,<ML,MLTDAS>,<CH,CVTDET>,<TV,TVTDET>>
TTYDE0:	SAVELN
	STKVAR<TTYDLN,TTYDAD>
TTYDE4:	MOVEM T2,TTYDLN		;SAVE INTERNAL LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST TTYDE1		;NOT ACTIVE. SHOULDN'T HAPPEN
	JN TTPRM,(T2),TTYDE3	;HANDLE PERMANENT BLOCK SPECIALLY
	JN TTLCK,(T2),TTYDE2	;IF LOCKED, WAIT FOR COUNT TO GO TO 0
	JN TTSAL,(T2),TTYDE2	;IF DOING SENDALL, WAIT UNTIL DONE
	MOVEM T2,TTYDAD		;SAVE ADDRESS OF DYNAMIC DATA
	NOSKD1			;NO SCHEDULING WHILE CHNOFF IN FORCE
	CHNOFF DLSCHN		;TURN OFF TTY CHANNEL
	CALL TTRLOB		;RELEASE OUTPUT BUFFERS
	MOVE T2,TTYDAD		;T2/ ADDRESS OF DYNAMIC DATA
	CALL TTCIBF		;CLEAR INPUT, RELEASE BUFFERS IF NEEDED
	MOVE T2,TTYDAD		;DYNAMIC DATA ADDRESS AGAIN
	CALL TTXONA		;MAKE SURE IS NOT X-OFF'ED
	MOVE T2,TTYDAD		;GET DYN ADDRESS
	SETZRO TT%PGM,TTFLGS(T2) ;INSURE WE WILL TURN XOFF FLAGS OFF
	TDCALL D,<<FE,TTEXF>,<MC,MCEXF>> ;SET FE XOFF RECOGNITION
	MOVE T2,TTYDLN		;GET BACK LINE NUMBER
	SETZM TTACTL(T2)	;INDICATE NO DYNAMIC DATA
	CHNON DLSCHN		;TURN CHANNEL BACK ON
	OKSKD1			;OK TO SCHED NOW
	MOVE T1,TTYDAD		;T1/ ADDRESS OF BLOCK
	CALL RELRES		;RELEASE THE RESIDENT SPACE
	RETSKP			;SUCCESS

;LINE IS NOT ACTIVE. THIS SHOULD NOT HAPPEN

TTYDE1:	MOVE T2,TTYDLN		;GET LINE NUMBER
	BUG(TTNAC7,<<T2,D>>)
	RETSKP

;DYNAMIC DATA IS LOCKED OR SENDALL IN PROGRESS.  REQUEST DEALLOCATION
;WHEN FINISHED

TTYDE2:	SETONE TTDAL,(T2)	;REQUEST DEALLOCATION WHEN FINISHED
	RETSKP

;PERMANENT BLOCK. DON'T DEALLOCATE IN THE USUAL WAY

TTYDE3:	SETZM TTPSI(T2)		;CLEAR INTERRUPTS
	SETZM TTDPSI(T2)	; AND DEFERRED INTERRUPTS
	SETONE TCJOB,(T2)	;INDICATE NO OWNING JOB
	MOVE T1,TTYDLN		;T1/ LINE NUMBER
	CALL CHKPTY		;IS THIS A PTY?
	 RETSKP			;NO.
	CALL PTYFIN		;YES. INDICATE HUNGRY
	RETSKP

	ENDSV.			;END STKVAR
;ASGMSG - ASSIGN BLOCK FOR MESSAGE
;ASGMSL- ASSIGN FULL LENGTH MESSAGE BLOCK FOR SPECIAL PURPOSES

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL ASGMSG
;	CALL ASGMSL

;RETURNS +1: FAILURE,
;		T1/ ERROR CODE
;	 +2: SUCCESS,
;		T2/ LINE NUMBER

	RESCD
ASGMSG:	TDZA T4,T4		;EXTRA LENGTH
ASGMSL:	MOVEI T4,TTDDLN-MSGLEN	;"LONG MESSAGE BLOCK"
	STKVAR <ASGMLN>
	MOVEM T2,ASGMLN		;SAVE LINE NUMBER
	MOVSI T1,.RESP2		;INDICATE CAN'T TAKE PAGE FAULT
	HRRI T1,MSGLEN(T4)	;T1/ (SIZE,,PRIORITY)
	MOVEI T2,.RESTP
	CALL ASGRES		;GET SOME FREE SPACE
	 RETBAD (MONX05)	;FAILED
	MOVE T2,ASGMLN		;GET LINE NUMBER
	CALL TTSETM		;INITIALIZE VALUES
	SETONE TTMES,(T1)	;INDICATE MESSAGE BLOCK
	TXO T1,TTSHBK		;SAY IS A SPECIAL BLOCK
	MOVEM T1,TTACTL(T2)	;MAKE STATIC POINT TO DYNAMIC
	AOSG TTQCNT		;FIRST SPECIAL LINE?
	MOVEM T2,TTCQLN		;YES. START SCAN HERE THEN
	TXZ T1,TTSHBK		;RETURN ADDRESSABLE BLOCK
	RETSKP			;INDICATE SUCCESS

	ENDSV.			;END STKVAR
;ASHSHT - ASSIGN A SHORT (SENDALL) BLOCK

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL ASGSHT

;RETURNS +1: FAILURE,
;		T1/ ERROR CODE
;	 +2: SUCCESS,
;		T1/BUFFER ADDRESS
;		T2/ LINE NUMBER

	SWAPCD

ASGSHT:	LOAD T1,TTSTY,(T2)	; GET LINE TYPE
	CAIE T1,TT.CVT		; CHAOS...
	CAIN T1,TT.NVT		; OR ARPA NVT?
	JRST R			; YES, DON'T DO THIS THEN
	CAIN T1,TT.TVT		;1010 How about TVT?
	 JRST R			;1010 Don't do it!
	STKVAR <ASGSLN>
	MOVEM T2,ASGSLN		;SAVE LINE NUMBER
	MOVSI T1,.RESP3		;INDICATE CAN TAKE PAGE FAULT
	HRRI T1,MSGLEN		;T1/ (SIZE,,PRIORITY)
	MOVEI T2,.RESTP
	CALL ASGRES		;GET SOME FREE SPACE
	 RETBAD	(MONX05)	;FAILED
	MOVE T2,ASGSLN		;GET LINE NUMBER
	CALL TTSETS		;INITIALIZE VALUES
	SETONE TTSHT,(T1)	;INDICATE MESSAGE BLOCK
	RETSKP			;INDICATE SUCCESS

	ENDSV.			;END STKVAR
	SUBTTL JSYS SUPPORT ROUTINES

;TTCOBF - CLEAR OUTPUT BUFFER

;TTCOB1 - ENTRY POINT FOR CALLING FROM WITHIN TTYSRV

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTCOB1

;RETURNS +1: ALWAYS

;IF LINE HAS NO OUTPUT BUFFERS, RETURNS QUIETLY. IF IT HAS A MESSAGE BLOCK,
;IGNORES LINKS.  IF FULLY ACTIVE, HANDLES LINKS

	RESCD

TTCOB1:	SAVELN			;SAVE LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA
	 JRST [	JUMPLE T2,TTCOB3 ;IF BECOMING ACTIVE OR INACTIVE, NO BUFFERS
		JE TTMES,(T2),TTCOB3 ;IF NOT A MESSAGE BLOCK, NO BUFFERS
		CALL TTCBF9	;MESSAGE BLOCK (HAS NO LINKS). CLEAR
		CALLRET ULKTTY]	;ALLOW DEALLOCATION
	CALL TTCBF9		;DO IT

TTCOB3:	CALLRET ULKTTY		;ALLOW DEALLOCATION
;TTCOBF - ENTRY FOR OUTSIDE OF TTYSRV

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCOBF

;RETURNS +1: ALWAYS

;LINE MUST BE FULLY ACTIVE AND ITS DYNAMIC BLOCK LOCKED WHEN CALLED FROM OUTSIDE

TTCOBF::SAVELN
TTCOB2:	MOVE C,TTLINK(B)	;GET LINES THAT THIS LINE IS LINKED TO
	CAMN C,[-1]		;ANY LINKS?
	CALLRET TTCBF2		;NO. JUST CLEAR THIS LINE'S BUFFERS

;LINE IS LINKED TO ONE OR MORE LINES. LOOP THROUGH TTLINK, PICKING UP
;A LINE NUMBER AND CLEARING ITS OUTPUT BUFFERS UNTIL ALL LINKS ARE
;PROCESSED

	PUSH P,B		;SAVE ADDRESS OF DYNAMIC DATA
TTCBF3:	SETZ B,			;INITIALIZE TO GET LINE NUMBER
	LSHC B,^D9		;GET NEXT LINE LINKED TO
	CAIN B,777		;THIS FIELD BEING USED?
	JRST TTCBF4		;NO
	CALL LCKTTY		;GET ADDRESS OF DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY
		JRST TTCBF4]	;NOT ACTIVE. DON'T DO ANYTHING
	PUSH P,C		;SAVE LINK WORD
	CALL TTCBF2		;GO CLEAR BUFFER FOR LINKED LINE
	CALL ULKTTY		;ALLOW DEALLOCATION
	POP P,C			;RESTORE LINK WORD
TTCBF4:	JUMPN C,TTCBF3		;GO DO ALL OF THEM

;ALL LINKS HAVE BEEN PROCESSED. NOW PROCESS THE ORIGINAL LINE AND QUIT

	POP P,B			;RESTORE ADDRESS OF DYNAMIC DATA
	CALLRET TTCBF2		;CLEAR BUFFERS FOR THIS LINE
;TTCBF2 - CLEAR OUTPUT BUFFER FOR ONE LINE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCBF2

;RETURNS +1: ALWAYS

;CALLER MUST HAVE CALLED LCKTTY ON THIS LINE

TTCBF2:	CALL SKCOE		;SKIP CTRL-O INTERRUPT ENABLED
	 SKIPN CTRLOF		;NEW STYLE?
	JRST TTCBF9		;NO
	CALL OWNTTY		;YES, TTY OWNED BY THIS JOB?
	JRST TTCBF9		;NO
	JE TTFLO,(T2),R		;DO NOTHING UNLESS FLUSHING OUTPUT
	NOSKD1
	CHNOFF DLSCHN
TTCBF8:	CALL GTOCHR		;GET CHAR FROM OUTBUF
	 JRST TTCBF7		;NOW EMPTY
	CAIE T1,.TTMRK		;A MARKER?
	JRST TTCBF8		;NO, KEEP FLUSHING
	SETZRO TTFLO,(T2)	;CLEAR FLUSH FLAG
	JRST TTCBF7		;DONE

TTCBF9:	NOSKD1
	CHNOFF DLSCHN		;TURN OFF CHANNEL ALSO
	JN TTSAL,(T2),TTCBFX	; CHECK FOR SENDALL IN PROGRESS
	CALL CLRSAL		; CLEAR IT
TTCBFX:	CALL CFEOB		;CLEAR FE OUTBUF
TTCOB5:	SETZM TTOCT(2)		;ZERO OUTPUT COUNT
	SETZB 3,TTOOUT(2)	;CLEAR OUTPUT POINTER
	EXCH 3,TTOIN(2)		;CLEAR INPUT POINTER
	CALL TTRLBF		;RELEASE BUFFERS
TTCBF7:	CHNON DLSCHN
	CALL TTXONA		;REACTIVATE OUTPUT IF NECESSARY
	OKSKD1
	TDCALL D,<<NT,NVTCOB>,<ML,MLCCOB>,<CH,NVTCOB>,<TV,TVTCOB>>
				;CLEAR NVT OUTPUT BUFFER (SEND SYNCH)
	CALL CHKBKO		;PERHAPS FORK WAITING FOR OBUF EMPTY
	RET

;OWNTTY - SKIP IF THIS TTY IS OWNED BY THIS JOB
; T2/ DYNAMIC PTR

OWNTTY:	SKIPE INSKED		;SCHED?
	RET			;YES, NOT A JOB
	LOAD T1,TCJOB,(T2)	;GET CONTROLLING JOB FOR THIS TTY
	CAME T1,JOBNO		;THIS JOB?
	RET			;NO
	RETSKP			;YES

;CLEAR OUTBUF OF FE
; T2/ DYNAMIC PTR
; RETURN +1 ALWAYS

CFEOB:	TDCALL D,<<FE,TTCOB4>,<MC,MCCOBF>>
	RET
;TTCIBF - CLEAR INPUT BUFFER

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCIBF (TTCIB0 TO CLEAR RESCAN POINTER TOO)

;RETURNS +1: ALWAYS,
;		T2 PRESERVED

TTCIB0::PUSH P,2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER
	CAMN 2,CTRLTT		;CONTROLLING TTY?
	SETZM RSCNPT		;YES, CLEAR RESCAN POINTER TOO
	POP P,2			;RESTORE ADDRESS OF DYNAMIC DATA

TTCIBF::SAVELN			;SAVE LINE NUMBER
	TDCALL D,<<ML,MLCCIB>>
	NOSKD1
	SETZRO <TTRFG>,(T2)	;CLEAR BKJFN FLAG
	SETZB T1,TTICT(T2)	;CLEAR COUNT OF INPUT CHARACTERS
	STOR T1,TYLCH,(T2)	;CLOBBER LAST CH IN CASE CR
	SETZB 3,TTIOUT(T2)	;CLEAR POINTER FOR REMOVING CHARACTERS
	EXCH 3,TTIIN(2)		; AND POINTER FOR ADDING CHARACTERS
	CALL TTRLBF		;RELEASE INPUT BUFFERS
	OKSKD1
	CALL SNDXON		;SEND XON IF NEEDED
	RET
	SWAPCD
;TTSIBE - SKIP IF INPUT BUFFER IS EMPTY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ BYTE SIZE OF OPEN OR 0 IF A JFN WAS NOT GIVEN BY CALLER

;	CALL TTSIBE

;RETURNS +1: INPUT BUFFER IS NOT EMPTY
;		T1/ COUNT OF CHARACTERS
;	 +2: INPUT BUFFER IS EMPTY
;		T1/ 0

;THIS ROUTINE COUNTS NUMBER OF CHARACTERS AVAILABLE FOR INPUT FROM LINE
;IN T2.  THE COUNT IS RETURNED IN T1.  THE QUANTITIES ACCUMULATED ARE
;THE FOLLOWING:
;
;	1)	RECIRCULATED CHARACTER, LIKE IF BKJFN WAS DONE
;	2)	RSCANED DATA(*)
;	3)	TYPEAHEAD THAT'S STILL IN THE INPUT BUFFER
;	4)	PHANTOM LINEFEED, ASSUMED IF LAST READ CHARACTER WAS CR
;
;	(*)	THERE IS A BUG HERE.  THIS ROUTINE ONLY EXAMINES THE
;		RSCAN BUFFER IF THE TERMINAL IS THE PROGRAM'S
;		CONTROLLING TERMINAL.  THE CORRECT PROCEDURE IS TO
;		EXAMINE THE RSCAN BUFFER FOR WHICHEVER TERMINAL IS
;		BEING INTERRAGATED.  THIS IS A BIT TRICKY, SINCE THE
;		RSCAN STATUS IS STORED IN SOMEON'S JSB, AND YOU FIRST
;		HAVE TO FIGURE OUT WHO, THEN CALL SETJSB, ETC...

TTSIBE::LOAD T1,TTRFG,(T2)	;0 IF NO RECIRCULATED CHARACTER, 1 IF SO
	PUSH P,T3		;SAVE THE BYTE SIZE
	PUSH P,T2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER
	MOVE T3,FORKN		;GET JOB FORK NUMBER
	LOAD T3,FRKTTY,(T3)	;GET POSSIBLE FORK CONTROLLING TERMINAL
	CAIE T3,.TTDES(T2)	;IS SIBE BEING DONE ON FORK'S OWN TERMINAL?
	CAMN T2,CTRLTT		;NO, IS THIS THE CONTROLLING TERMINAL FOR THIS JOB?
	SKIPN T3,RSCNPT		;YES. GET RESCAN POINTER
	JRST TTSIB1		;NOT CONTROLLING OR POINTER IS 0
TTSIB2:	ILDB T4,T3		;PICK UP CHARACTER FROM RSCAN BUFFER
	JUMPE T4,TTSIB1		;LEAVE LOOP IF NO MORE.
	AOJA T1,TTSIB2		;COUNT LENGTH OF RSCAN BUFFER
TTSIB1:	POP P,T2		;RESTORE ADDRESS OF DYNAMIC DATA
	POP P,T4		;GET BACK BYTE SIZE
	ADD T1,TTICT(T2)	;ADD CHARACTERS IN REGULAR INPUT BUFFER
	LOAD T3,TT%DAM,TTFLGS(T2) ;GET CURRENT MODE
	CAIE T4,10		;BINARY MODE OPEN ON THE JFN?
	JUMPN T3,[LOAD T3,TYLCH,(T2) ;NOT BINARY, CHECK LAST CHAR
		  LOAD T4,TYLMD,(T2) ; GET DATA MODE OF LAST CHAR
		  CAIN T3,.CHCRT ;CR?
		  CAIN T4,.TTBIN ; YES, INPUT IN NON-BINARY?
		  JRST .+1	; NO TO EITHER, NO LF.
		  AOJA T1,.+1]	;YES TO BOTH, LF STILL AVAILABLE
	CAILE T1,0		;POSITIVE COUNT?
	RET			;YES, SO TAKE NON-SKIP RETURN
	RETSKP			;NO. SKIP
;TTSOBE - SKIP IF OUTPUT BUFFER IS EMPTY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSOBE

;RETURNS +1: OUTPUT BUFFER NOT EMPTY
;		T1/ COUNT
;	 +2: OUTPUT BUFFER IS EMPTY
;		T1/ 0
	RESCD

TTSOBE::CALL SKCOE		;SKIP IF CTRL-O INTERRUPT ENABLED
	 SKIPN CTRLOF		;NEW STYLE?
	IFSKP.
	  CALL OWNTTY		;JOB OWN TTY?
	  IFSKP.
	    MOVEI T1,.TTMRK	;YES, JUST PUT MARKER IN STREAM
	    CALL TCOUM
	    SETZ T1,
	    RETSKP		;SAY OUTBUF EMPTY
	  ENDIF.
	ENDIF.
	LOAD T1,TSALC,(T2)	;1027 Get number of bytes from TTMSG
	JN <TTSAL,TTOTP>,(T2),R	;1027 Not empty if TTMSG in progress
;1027	JN TTOTP,(T2),R		;RETURN NOSKIP IF OUTPUT IS STILL ACTIVE
	SKIPLE 1,TTOCT(2)	;BYTES STILL IN -10 MEMORY
	RET			;NO. NONSKIP
	TDCALL D,<<FE,TTSBEF>,<MC,MCSBEF>>
	 RETSKP			;DEVICE BUFFER (IF ANY) ALSO EMPTY
	RET			;DEVICE BUFFER NOT EMPTY

;TTSOBF - SKIP IF OUTPUT BUFFER IS FULL

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSOBF

;RETURNS +1: OUTPUT BUFFER IS NOT FULL
;		T1/ COUNT
;	 +2: OUTPUT BUFFER IS FULL
;		T1/ COUNT
	SWAPCD

TTSOBF::LOAD 3,TOMAX,(2)	;CAPACITY OF OUTPUT BUFFER
	MOVE 1,TTOCT(2)		;GET NUMBER OF CHARACTERS IN BUFFER
	CAIL 1,0(3)		;FULL?
	RETSKP			;YES. SKIP
	RET			;NO. NONSKIP
;TTDOBE - DISMISS UNTIL OUTPUT BUFFER IS EMPTY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTDOBE

;RETURNS +1: NEED TO RETRY
;	+2 DONE. BUFFER IS EMPTY

;WAITS UNTIL OUTPUT BUFFER IS EMPTY

TTDOBE::CALL SKCOE		;SKIP IF CTRL-O INTERRUPT ENABLED
	 SKIPN CTRLOF		;NEW STYLE?
	IFSKP.
	  MOVEI T1,.TTMRK	;YES, JUST PUT MARKER IN OUTPUT STREAM
	  CALL TCOUM
	  RETSKP
	ENDIF.
	TDCALL D,<<NT,NVTDOB>,<ML,MLCDOB>,<CH,NVTDOB>,<TV,TVTDOB>>
	CALL TSOBED		;SEE IF OUTPUT IN PIPE
	IFSKP. <RETSKP>		;NO, RETURN OK

;CHARACTERS ARE PRESENT. DISMISS UNTIL THEY ARE GONE

TTDBE1:	TDCALL D,<<PT,CHKPTA>>	;CHECK FOR INTERRUPT NEEDED
	SETONE TTBKO,(T2)	;NOTE WAITING FOR OUTPUT EVENT
	DYNST T1		;GET STATIC DATA ADDRESS
	CALL ULKTTY		;UNLOCK TTY
	HRLZS T1		;LINE # TO LH
	HRRI 1,TTOBET		;1/(LINE NUMBER,,ROUTINE TO CALL)
	MOVSI T2,FHV5		;BLOCK PRIORITY
	HDISMS
	RET			;SAY NEED TO RETRY
;TTDIBE - DISMISS UNTIL INPUT BUFFER IS EMPTY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTDIBE

;RETURNS +1: NEED TO RETRY
;	+2 DONE. BUFFER EMPTY

;WAITS UNTIL INPUT BUFFER IS EMPTY

TTDIBE::SKIPG TTICT(T2)		;BUFFER EMPTY NOW?
	RETSKP
	DYNST T1		;GET LINE NUMBER
	CALL ULKTTY		;UNLOCK TTY
	HRLZS T1		;LINE # TO LH
	HRRI 1,TTIBET		;1/(LINE NUMBER,,ROUTINE TO CALL)
	MDISMS
	RET			;NEED TO RETRY
;SCHEDULER TESTS FOR TTDOBE AND TTDIBE
	RESCD

;TTOBET - CAUSES WAKEUP IF OUTPUT BUFFER IS EMPTY (INCLUDING CHARACTERS
;EN ROUTE TO THE LINE)

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

TTOBET::PUSH P,T4		;PUT RETURN ON STACK SO RET, RETSKP WORK
	HRRZ T2,T1		;GET LINE NUMBER
	JRST TTOBE0		;DO THE WORK

;HERE FOR NORMAL CALL
; T2/ LINE NUMBER
; RETURN +1 OUT BUFFER NOT EMPTY
;	+2 OUT BUFFER EMPTY

TSOBEX:	SAVEAC <T2>
TTOBE0:	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 RETSKP			;NOT ACTIVE. THIS SHOULDN'T HAPPEN

;ENTER HERE IF DYNAMIC PTR  IN T2
; T2/ DYNAMIC PTR
; RETURN +1: NOT EMPTY
;	+2: EMPTY

TSOBED:	TDCALL D,<<ML,MLTOBE>>	; Device dependent
	SKIPE TTOCT(T2)		;IS OUTPUT BUFFER EMPTY?
	RET			;NO. DON'T WAKE UP
	JN TTOTP,(T2),R		;NO IF STILL OUTPUT ACTIVE
	TDCALL D,<<FE,TTSBEF>,<MC,MCSBEF>> ;CHECK DEVICE BUFFERING IF ANY
	IFSKP. <RET>		;SKIPS IF BUFFER *NOT* EMPTY
	SETZRO TTBKO,(T2)	;NOTE WAIT COMPLETED
	RETSKP

;TTIBET - CAUSES WAKEUP IF INPUT BUFFER IS EMPTY

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

TTIBET:	HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 JRST 1(T4)		;NOT ACTIVE. THIS SHOULDN'T HAPPEN
	SKIPE TTICT(T2)		;IS INPUT BUFFER EMPTY?
	JRST 0(4)		;NOT EMPTY. DON'T WAKE UP
	JRST 1(4)		;EMPTY. WAKE UP
;TAB GET/SET - PHASED OUT
	SWAPCD

TTGTBS::
TTSTBS::RET

;TTRMOD - CODE TO DO THE RFMOD JSYS

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS
;		T1/JFN MODE WORD

;NOTE: IF PAGE WIDTH OR LENGTH IS >177, RETURNS 1 IN THESE FIELDS.
;USER MUST THEN DO AN MTOPR TO GET THE REAL VALUE

TTRMOD::SAVELN
	MOVE 1,TTFLGS(2)	;READ MODES
	LOAD T3,TPWID,(T2)	;GET WIDTH
	LOAD T4,TPLEN,(T2)	;AND PAGE LENGTH
	CAILE T3,177		;OLD MAXIMUM VALUE
	MOVEI T3,DFLWID		;TOO BIG. GET DEFAULT WIDTH
	CAILE T4,177		;OLD MAXIMUM VALUE
	MOVEI T4,DFLLEN		;TOO BIG. GET DEFAULT LENGTH
	STOR T3,TT%WID,1	;STORE OLD STYLE WIDTH
	STOR T4,TT%LEN,1	;STORE OLD STYLE LENGTH
	CALL TTCBM		;GET A TT%WAK FROM THE BREAK MASK
	DYNST			;GET LINE NUMBER
	JE TTCON,(T2),R		;RETURN UNLESS CARRIER IS ON
	SETONE TT%CAR,T1	;INDICATE CARRIER ON
	RET
;TTSMOD - SET TERMINAL MODE

;ACCEPTS:
;	T1/ JFN MODE WORD
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS

;IMPLEMENTS SFMOD JSYS

TTSMOD::PUSH P,T1
;;;	TRNE T1,400000		;THIS BIT MUST BE ZERO
;;;	ITERR(DECRSV,<CALL ULKTTY>)	;NOT ZERO - ERROR RETURN
	XOR T1,TTFLGS(T2)	;FIND THE CHANGED BITS
	ANDX T1,TT%OSP+TT%WAK+TT%IGN+TT%ECO+TT%DAM ;CHANGE ONLY THESE BITS
	XORM T1,TTFLGS(T2)
	SKIPE CTRLOF		;NEW STYLE AND CHANGING OUTPUT SUPPRESS?
	TXNN T1,TT%OSP
	IFSKP. <
	  CALL SKCON		;SKIP IF CTRL-O NOT ENABLED
	  IFSKP. <
	  MOVEI T1,.TTMRK	;YES, PUT MARKER IN OUTPUT STREAM
	  CALL TCOUM>>
	LOAD T1,TT%DAM,TTFLGS(T2) ;GET TERMINAL DATA MODE
	STOR 1,TYLMD,(T2)	;CHANGE IT FOR PI LEV ALSO
	POP P,T1
	TXNE T1,TT%IGN		;SHOULD WE IGNORE THE TT%WAK BITS
	RET			;YES - THEN DON'T FORCE WAKE-UP
	CALL TTCFM		;COMPUTE AND SET FULL MASK
	CALLRET TTFWAK		;FORCE WAKEUP

;TTRTMW - READ THE TERMINAL MODE WORD FOR THE RTMOD JSYS
;ACCEPTS IN:	T2/	ADDRESS OF DYNAMIC DATA (LOCKED)
;RETURNS:	+1:	ALWAYS,
;			T1/ DISPLAY MODE WORD

TTRTMW::MOVE T1,TTTMOD(T2)
	RET

;TTSTMW - SET THE DISPLAY MODE WORD FOR THE STMOD JSYS
;ACCEPTS IN:	T1/	DISPLAY MODE WORD
;		T2/	ADDRESS OF DYNAMIC AREA (LOCKED)
;RETURNS:	+1:	ALWAYS

TTSTMW::MOVEM T1,TTTMOD(T2)	;SET NEW MODE WORD
	TXNN T1,TM%ITP		;SEE IF ITP WANTED
	IFSKP.
	  MOVEI T1,TTIITP	;YES. GET INPUT PROCESSING ROUTINE
	  STOR T1,TIRUT,(T2)	;SAVE ADDRESS (WATCH IT, ONLY 18 BITS)
	ELSE.
	  SETZRO TIRUT,(T2)	;NO, FLUSH INPUT PROCESSING ROUTINE
	ENDIF.
	CALL SETEOP		;SET SCREEN SIZE FOR EOP PROCESSING
	RET

;TTRTCW - READ DISPLAY CAPABILITY WORD FOR THE RTCHR JSYS
;ACCEPTS IN:	T2/	ADDRESS OF DYNAMIC DATA (LOCKED)
;RETURNS:	+1:	ALWAYS,
;			T1/ DISPLAY CAPABILITY WORD

TTRTCW::MOVE T1,TTCHAR(T2)
	RET

;TTSTCW - SET DISPLAY CAPABILTY WORD FOR STCHR JSYS
;ACCEPTS IN:	T1/	NEW DISPLAY CAPABILITY WORD
;		T2/	ADDRESS OF DYNAMIC DATA (LOCKED)
;RETURNS:	+1	ALWAYS

TTSTCW::MOVEM T1,TTCHAR(T2)
	RET

; RTGRV - RETURN GRAPHICS VARIABLE
;
;ACCEPTS IN:	T1/	TERMINAL DESIGNATOR
;
;RETURNS:	+1	ALWAYS, GRAPHICS VARIABLE IN T2,
;				OR 0 IF NOT A TERMINAL
;
;RTGRV ERRORS:		TTYX01: Line is not active

.RTGRV::MCENT
	CALL CHKTTR
	 JRST [	XCTU [SETZM 2]
		JRST MRETN]
	CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 ITERR (TTYX01,<CALL ULKTTY>) ;NOT ACTIVE. FAILED
	CALL TTRTGV		;GET THE GOODS
	CALL ULKTTY		;ALLOW DEALLOCATION
	UMOVEM 1,2
	JRST MRETN

; STGRV - SET TERMINAL GRAPHICS VARIABLE
;
;ACCEPTS IN:	T1/	TERMINAL DESIGNATOR
;		T2/	NEW GRAPHICS VARIABLE
;
;RETURNS:	+1	ALWAYS
;
;STGRV ERRORS:		TTYX01: Line is not active
;			TTYX1:	Device is not a terminal

.STGRV::MCENT
	CALL CHKTTR
	 ITERR(TTYX1)
	CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 ITERR (TTYX01,<CALL ULKTTY>) ;NOT ACTIVE. FAILED
	UMOVE 1,2		;GET THE DESIRED ARG
	CALL TTSTGV		;SET IT
	CALL ULKTTY		;ALLOW DEALLOCATION
	JRST MRETN


;TTSTGV - SET DISPLAY GRAPHICS VARIABLE FOR STGRV JSYS
;ACCEPTS IN:	T1/	NEW GRAPHICS VARIABLE
;		T2/	ADDRESS OF LOCKED DYNAMIC DATA
;RETURNS:	+1	ALWAYS

TTSTGV::MOVEM	T1,TTTGV(T2)
	RET

;TTRTGV - GET DISPLAY GRAPHICS VARIABLE FOR RTGRV JSYS
;ACCEPTS IN:	T2/	ADDRESS OF DYNAMIC DATA (LOCKED)
;RETURNS:	+1:	ALWAYS,
;			T1/ DISPLAY GRAPHICS VARIABLE

TTRTGV::MOVE T1,TTTGV(T2)
	RET
;TTRPOS - READ POSITIONS

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTRPOS

;RETURNS +1: ALWAYS,
;	T1/ (LINE POSITION WITHIN PAGE,,CHARACTER POSITION WITHIN LINE)

TTRPOS::MOVE 1,TTLPOS(2)	;READ POSITION
	RET

;TTSPOS - SET POSITION

;ACCEPTS:
;	T1/ (LINE POSITION WITHIN PAGE,,CHARACTER POSITION WITHIN LINE)
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSPOS

;RETURNS +1: ALWAYS

TTSPOS::MOVEM T1,TTLPOS(T2)	;SET LINE CHARACTER POSITION
	MOVEM T1,TTPPOS(T2)	;PHYSICAL POSITION ALSO
	SETZRO TTCFU,(T2)	;KNOW CURSOR POSITION
	RET

;TTRCOC - READ CONTROL CHARACTER OUTPUT CONTROL WORDS

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTRCOC

;RETURNS +1: ALWAYS,
;		T1/ FIRST WORD
;		T3/ SECOND WORD

TTRCOC::MOVE 1,FCMOD1(2)	;READ CONTROL CHARACTER MODES
	MOVE 3,FCMOD2(2)
	RET

;TTSCOC - SET CONTROL CHARACTER OUTPUT CONTROL WORDS

;ACCEPTS:
;	T1/ FIRST WORD
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ SECOND WORD

;	CALL TTSCOC

;RETURNS +1: ALWAYS

TTSCOC::MOVEM 1,FCMOD1(2)	;SET CONTROL CHARACTER MODES
	MOVEM 3,FCMOD2(2)
	RET
;TTBKPT - "BACKUP" INPUT POINTER - CAN ONLY BACKUP ONE

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTBKPT

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TTBKPT::MOVE C,FORKN		;GET OUR FORK NUMBER
	LOAD C,FRKTTY,(C)	;GET POSSIBLE CONTROLLING TERMINAL
	CAIE C,.TTDES(B)	;USE RSCAN BUFFER IF READING FROM CONTROLLING TERMINAL
	CAMN 2,CTRLTT		;JOB CONTROLLING TTY?
	SKIPN A,RSCNPT		;YES, USING RESCAN BUFFER?
	JRST TTBKP1		;NO, DO NORMAL THING
	MOVE C,RSCNBP		;GET POINTER TO RSCAN BUFFER
	HRLI C,(POINT 7,0,34)	;SEE IF AT START OF BUFFER
	CAMN A,C
	JRST TTBKP1		;YES, DONT BACK IT UP MORE
	CALL DBP		;BACK UP BYTE POINTER
	MOVEM A,RSCNPT		;PUT IT BACK
	RETSKP			;INDICATE SUCCESS

TTBKP1:	CALL LCKTTY		;GET DYNAMIC DATA AND LOCK DYNAMIC BLOCK
	 JRST [	CALL ULKTTY	;NOT ACTIVE. CAN'T BACKUP
		RETBAD (TTYX01)]
	TMNE TTRFG,(T2)		;HAS BACKUP ALREADY BEEN DONE?
	JRST [	CALL ULKTTY	;YES. CAN'T DO ANOTHER
		RETBAD (BKJFX1)]
	SETONE TTRFG,(T2)	;NOT SET. SET IT TO BE NOTICED AT NEXT TCI
	CALL ULKTTY		;ALLOW DEALLOCATION
	RETSKP			;SUCCESS


;GET DEVICE DEPENDENT BITS

TTGSTS::LOAD T3,TLTYP,(T2)	;GET VECTOR ADR FOR THIS TTY
	SETZ T1,
	XCT PARTBL(T3)		;SEE IF PARITY BIT WOULD GET SET
	CAIE T1,0
	MOVX T1,GD%PAR		;YES
	RET			;AND DONE
;TTSSPD - CODE TO DO A SET LINE SPEED
;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER
;	USER 3/ INPUT SPEED,,OUTPUT SPEED
;
;	CALL TTSSPD
;
;RETURNS +1:	ON ERROR (CURRENTLY ONLY FOR ACJ REJECTION)
;	 +2:	ON ALL OTHER CONDITIONS
;
;SETS SPEEDS OF FRONT END LINES ONLY. IGNORES ALL OTHERS
;IMPLEMENTS THE .MOSPD FUNCTION OF MTOPR

TTSSPD::
	STKVAR <TTSLIN,TTSVT1>	;SAVE LINE NUMBER HERE, TEMP LOCATION
	CAIL B,NLINES		;VALID LINE NUMBER?
	RETSKP			;NO. JUST RETURN QUIETLY
	MOVEM B,TTSLIN		;SAVE LINE NUMBER
	UMOVE C,C		;GET SPEED
	GTOKM (.GOTBR,<B,C>,[RETBAD ()]) ;DO GETOK IF NECESSARY AND RETBAD IF ERROR
	MOVEM T1,TTSVT1		;SAVE REG
	MOVE T1,TTSLIN		;GET LINE INDEX
	CAIGE T1,NTTFE		;SKIP CHECK IF NOT FE LINE
	 JRST [	MOVE T1,TTTYPS(T1)	;FE LINE. SEE IF LOCKED
		TXNN T1,SY%NSS
		JRST .+1	;NOT LOCKED. RETURN FROM LITERAL
		MOVE T1,CAPENB	;LOCKED. GET CAPS
		TXNE T1,SC%WHL!SC%OPR!SC%MNT!SC%CNF	;SEVERAL WILL WORK
		JRST .+1	;OK, GO DO IT
		RETSKP ]	;NO GOOD, DIE QUIETLY
	MOVE T1,TTSVT1		;GET REG BACK
	TDCALL S,<<FE,TTSSP2>,<DZ,DZSSP2>>
	MOVE B,TTSLIN		;GET BACK LINE NUMBER
	CALL LCKTTY		;GET DYNAMIC DATA ADDRESS
	 JRST [	CALL ULKTTY	;FAILED TO LOCK, NOT INTERESTING
		RETSKP]		; UNLOCK AND RETURN QUIETLY
	MOVE T1,T2		;GET DYNAMIC DATA ADDRESS
	MOVE T2,TTSLIN		;GET LINE NUMBER AGAIN
	CALL SETOBF		;SET BUFFERING
	MOVE T2,T1		;GET DYNAMIC DATA ADDRESS
	CALL ULKTTY		;DONE, UNLOCK DATA
	RETSKP			; AND RETURN SUCCESS

	ENDSV.			;END STKVAR


;TTRSPD -READ OUT THE SPEED OF A TERMINAL

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTRSPD

;RETURNS +1: ALWAYS,
;		USER T3/ (INPUT SPEED,,OUTPUT SPEED)
;			OR
;		    -1 IF NOT PHYSICAL TERMINAL OR SPEED NOT SET

;IMPLEMENTS THE .MORSP FUNCTION OF MTOPR

TTRSPD::CAIL B,NLINES		;LEGAL LINE NUMBER?
	JRST TTRSP2		;NO. RETURN NO SPEED
	TDCALL S,<<MC,RSKP>,<PT,RSKP>,<NT,RSKP>,<ML,RSKP>,<CH,RSKP>,<TV,RSKP>>
				;SKIP IF SPEED NOT KNOWN
	 SKIPA C,TTSPWD(B)	;GET SPEED SETTING
TTRSP2:	SETO C,			;NO. ASSUME UNKNOWN
	UMOVEM C,C		;RETURN IT TO THE CALLER
	SETZ C,			;GET AN ACCUMULATOR
	TMNE TTFEM,(B)		;REMOTE?
	TXO C,MO%RMT		;YES
	TMNE TTAUT,(B)		;AUTO?
	TXO C,MO%AUT		;YES
	XCTU [HLLM C,2]		;RETURN FLAGS
	RET			;AND DONE


;TTSSIG - ROUTINE TO SET THE "IGNORE INPUT ON INACTIVE LINE" BIT
;
;ACCEPTS IN T1/ NEW SETTING (0 OR 1)
;	    T2/ LINE NUMBER
;		CALL TTSSIG
;RETURNS: +1 ALWAYS

TTSSIG::STOR T1,TTIGI,(T2)	;STORE NEW SETTING OF IGNORE INPUT BIT
	RET			;DONE, RETURN
;ROUTINE TO INIT OUTPUT BUFFERING PARAMETERS.
;CALLED FROM TTSETL AND TTSSPD.
;ONLY CALLED FOR NON-CTY ASSIGNS
;	T1/ DYNAMIC DATA ADDRESS
;	T2/ LINE NUMBER
;RETURNS:	+1 ALWAYS
;ALL REGS PRESERVED

SETOBF:	SAVET			;SAVE ALL REGS
	MOVE T3,TTSPWD(T2)	;GET LINE SPEED
	CAMN T3,[-1]		;KNOWN SPEED?
	RET			;NO. GIVE UP THEN
	HRRZS T3		;YES. GET OUTPUT SPEED
	MOVE T4,IBFRC		;ASSUME SLOW SPEED
	CAILE T3,LOWSPD		;ACCEPTABLE?
	MOVE T4,IBFRC1		;NO. GET OTHER VALUE
	MOVEM T4,TTBFRC(T1)	;SET COUNT FIELDS
	SETZ T4,0		;NO BUFFER COUNT IF LOW SPEED
	CAILE T3,LOWSPD
	MOVEI T4,OVRBCT		;SET OVER QUOTA BUFFER COUNT
	STOR T4,TTOCN,(T1)	;SET COUNT
	SETZRO TTOMX,(T1)	;INDICATE OVERBUFFER NOT IN USE
	SETONE TTIPSI,(T1)	;SET NO PSI ---
	SETONE TTOPSI,(T1)	;INPUT OR OUTPUT ---
	RET			;AND DONE
; .MOTPS - ENABLE FOR PSI INTERRUPTS ON NON-CONTROLLING TERMINAL I/O

;CALL WITH:
;B/		TERMINAL NUMBER
;USER AC3/	POINTER TO USER ARGUMENT BLOCK
;BLOCK+0/	LENGTH OF BLOCK (INCLUDING THIS WORD)
;BLOCK+1/	OUTPUT PSI,,INPUT PSI

TTYNPS::ACVAR <W1>		;GET A REGISTER
	MOVE W1,B		;SAVE LINE NUMBER
	MOVEI A,1		;OFFSET 1 IN ARG BLOCK
	CALL GETWRD		;GET IT
	 RETBAD(MTOX13)		;ERROR, NO SUCH ARG
	HLRZ A,B		;GET OUTPUT PSI CHANNEL
	CALL TTNPCK		;VALIDITY CHECK IT
	 RETBAD(MTOX14)		;ILLEGAL PSI CHANNEL
	HRRZ A,B		;GET INPUT PSI CHANNEL
	CALL TTNPCK		;VALIDITY CHECK IT
	 RETBAD(MTOX14)		;ILLEGAL PSI CHANNEL
	EXCH W1,B		;GET BACK LINE NUMBER SAVE CHANNELS
	CALL LCKTTY		;LOCK TTY DATABASE
	 RETBAD(TTYX01,<CALL ULKTTY>)
	HLRZ A,W1		;GET OUTPUT PSI
	STOR A,TTOPSI,(B)	;STORE IN TTY DATABLOCK
	STOR W1,TTIPSI,(B)	;STORE INPUT PSI
	CAMN W1,[-1]		;TURNING OFF BOTH CHANNELS?
	JRST TTYNP1
	MOVE A,FORKX		;NO, GET CALLING FORK NUMBER
	STOR A,TTPSFK,(B)	;STORE IT AS WELL
	SETONE PSUTPS		;FLAG .MOTPS DONE TO THIS FORK
	JRST TTYNP2

TTYNP1:	SETONE TTPSFK,(B)
TTYNP2:	CALL ULKTTY		;RELEASE TTY DATABASE
	RETSKP			;SUCCESS

;VALIDITY CHECK AN ASSIGNABLE PSI CHANNEL

TTNPCK:	CAIE A,-1		;-1 = DEASSIGN
	CAIG A,5		;0-5 OK
	RETSKP
	CAIL A,^D24
	CAILE A,^D35
	RET			;NOT 24-35, ILLEGAL
	RETSKP			;OK

	ENDAV.			;END ACVAR W1

;TTDTPS - REMOVE CURRENT FORK FROM TTPSFK OF ALL TERMINALS

TTDTPS::SAVET
	SETZRO PSUTPS			;CLEAR BIT THAT GOT US HERE
	MOVEI T1,NLINES-1		;GET HIGHEST LINE NUMBER
TTDTP1:	MOVE T2,T1			;GET LINE NUMBER
	CALL LCKTTY			;LOCK DATABASE
	 JRST TTDTP2			;NOT FULLY ACTIVE, SKIP
	LOAD T3,TTPSFK,(T2)		;GET FORK RECEIVING INT
	CAME T3,FORKX			;SAME AS CURRENT?
	JRST TTDTP2			;NO, SKIP IT
	SETONE TTPSFK,(T2)		;YES, CLEAR IT
TTDTP2:	CALL ULKTTY			;UNLOCK DATABASE
	SOJGE T1,TTDTP1			;LOOP THRU ALL LINES
	RET
;TTSNTS - CODE TO DO A SET/RESET NON-TERMINAL STATUS FOR TTY LINE.
; THIS IS PRIMARILY FOR SUPPRESSING UNWANTED SYS MESSAGES
;ACCEPTS:
;	2/ LINE TO SET STATUS OF
;	3/ STATUS VALUE (1 TO TURN OFF MESSAGES, 0 TO TURN ON)

;	CALL TTSNTS

;RETURNS +1: ALWAYS

;IGNORES NON-FRONT END LINES

;IMPLEMENTS .MOSNT FUNCTION OF MTOPR

TTSNTS::CAIL B,NLINES		;LEGAL LINE NUMBER?
	RET			;NO. IGNORE IT THEN
	TDCALL S,<<FE,TTSNT1>,<PT,RSKP>>
	 SKIPA
	RET			;DON'T CHANGE IT
	STOR T3,TTNTS,(T2)	;SAVE THE NEW STATUS
	RET


;TTRNTS - READ TTY NON-TERMINAL DEVICE STATUS
;ACCEPTS:
;	2/ INTERNAL LINE NUMBER

;	CALL TTRNTS

;RETURNS +1 : ALWAYS,
;		3/ STATUS (0 IF SYSTEM MESSAGES ACCEPTED, 1 IF NOT)

;IMPLEMENTS .MORNT FUNCTION OF MTOPR

TTRNTS::SETZ C,			;GET DEFAULT VALUE
	CAIL B,NLINES		;A VALID TERMINAL LINE?
	RET			;NO. ASSUME DEFAULT
	LOAD T3,TTNTS,(T2)	;GET NON-TERMINAL STATUS
	RET
;TTSTIH - TEST INPUT REQUIRED

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSTIH

;RETURNS +1: ALWAYS,
;		1/ 0 IF NOT HUNGRY
;		-1 IF HUNGRY

;HUNGRY IS DEFINED AS EITHER OF THE FOLLOWING:
;	1 - THERE IS NO CONTROLLING JOB FOR THIS LINE (IE, CTRL/C
;		WILL CAUSE JOB CREATION)
;	2 - A FORK IS IN INPUT WAIT ON THE LINE AND THERE IS CURRENTLY
;		NO REASON TO WAKE IT UP (IT WILL READ A CHARACTER THAT
;		IS SENT TO THIS LINE)

;NOT HUNGRY IS RETURNED IF ANY OF THE FOLLOWING IS TRUE:
;	1. THE CONTROLLING JOB NUMBER IS INVALID
;	2. NO FORK IS IN INPUT WAIT ON THIS LINE
;	3. FORCED WAKEUP IS SET SO THAT THE WAITING FORK WILL WAKE UP SOON
;	4. THE OUTPUT BUFFER IS ABOUT TO OVERFLOW (INPUT CHARACTERS ARE THROWN
;		AWAY WHEN NOT ECHOED)
;	5. AN INTERRUPT IS PENDING FOR THE WAITING FORK

TTSTIH::LOAD T3,TCJOB,(T2)	;GET OWNING JOB IF ANY
	CAIN T3,-1		;IS THIS TERMINAL ASSIGNED?
	JRST [	JE TTBAC,(T2),TTSTI2 ;NO, HUNGRY UNLESS BECOMING ACTIVE
		JRST TTSTI1]
	CAIL T3,NJOBS		;VALID JOB NUMBER?
	JRST TTSTI1		;NO, RETURN FALSE
	LOAD T1,TWFRK,(T2)	;GET FORK IN INPUT WAIT
	CAIN T1,-1		;IS THERE ONE?
	JRST TTSTI1		;NO. SAY NOT HUNGRY
	JN TTFWK,(T2),TTSTI1	;YES. IF ABOUT TO WAKEUP BECAUSE INPUT BUFFER
	SKIPE FKINT(T1)		;IF INTERRUPT IS PENDING, SAY NOT HUNGRY
TTSTI1:	TDZA 1,1		;RETURN NOT HUNGRY
TTSTI2:	SETO 1,			;RETURN HUNGRY
	RET
;ROUTINES TO SET/READ MODE FIELDS. CALLED FROM MTOPR FUNCTIONS
;IN FILMSC

;SET/READ TERMINAL WIDTH
;ACCEPTS:	T1/ NEW WIDTH
;		T2/ ADDRESS OF DYNAMIC DATA

TTSWID::JUMPE T1,TTSWI1		;ALLOW ZERO WIDTH
	CAIL T1,10		;MUST BE GREATER THAN 10
	CAIL T1,400		;AND LESS THAN 400
	RET			;ILLEGAL WIDTH
TTSWI1:	STOR T1,TPWID,(T2)	;GOOD VALUE. STORE IT
	RETSKP			;DONE

TTRWID::LOAD T1,TPWID,(T2)	;READ WIDTH
	RET			;DONE

;SET/READ TERMINAL LENGTH
;SAME ARGS AS ABOVE

TTSLEN::JUMPE T1,TTSLE1		;ALLOW ZERO
	CAIL T1,2		;MUST BE GREATER THAN 2
	CAIL T1,400		;AND LESS THAN 400
	RET			;INVALID LENGTH
TTSLE1:	STOR T1,TPLEN,(T2)	;GOOD VALUE. STORE IT
	CALL SETEOP		;FIX UP END-OP-PAGE
	RETSKP			;DONE

TTRLEN::LOAD T1,TPLEN,(T2)	;READ LENGTH
	RET			;DONE

;SET/READ LINE COUNTER

TTSLC::	MOVEM A,TTLINE(B)	;STORE NEW VALUE
	RET

TTRLC::	MOVE A,TTLINE(B)
	RET

;SET/READ MAXIMUM LINE COUNTER

TTSLM::	MOVEM A,TTLMAX(B)
	RET

TTRLM::	MOVE A,TTLMAX(B)
	RET

;SET/CLEAR XOFF/XON PROCESSING BIT
;	T3/ 0=> HONOR XON/XOFF
;	   1=> DON'T

TTXSET::SKIPE T3		;WANT TO DO OUTPUT STOP?
	MOVEI T3,1		;YES. MAKE SURE BIT IS THERE
	STOR T3,TTNXO,(T2)	;STORE NEW VALUE
	CALLRET TTXONP		;AND START OUTPUT IF NECESSARY

;READ VALUE OF XOFF BIT

TTRXOB::LOAD T1,TTNXO,(T2)	;GET THE BIT
	RET			;DONE


;SET/READ PAGE PAUSE CHARACTER
; T1/ PAUSE CHARACTER ,, UNPAUSE CHARACTER
; T2/ DYNAMIC PTR

TTPPCS::HRRZ T3,T1		;CHECK UNPAUSE CHARACTER
	CAIN T3,PGMOFC		;CTRL-S?
	ITERR TTYX02		;YES, DOESN'T WORK
	STOR T1,TTUPC,(T2)
	HLRZ T1,T1
	STOR T1,TTPPC,(T2)
	RET

TTPPCR::LOAD T1,TTUPC,(T2)
	LOAD T3,TTPPC,(T2)
	HRL T1,T3
	RET
	SUBTTL FULL WAKE-UP CLASSES SUPPORT

	RESCD

;SET/READ FUNCTIONS FOR  FIELD WIDTH AND 128-CHARACTER MASK WAKE-UPS

;TTSBM - SET BREAK MASK
;ACCEPTS:	T1/ADDRESS OF FOUR WORD MASK
;		T2/DYNAMIC  DATA ADDRESS
;RETURNS:	+1, ALWAYS
;			DESTROYS T3 & T4

TTSBM::	DMOVE T3,(T1)		;FIRST TWO WORDS OF MASK
	DMOVEM T3,TTCHR1(T2)	;SET NEW VALUES
	DMOVE T3,2(T1)		;LAST TWO WORDS OF MASK
	DMOVEM T3,TTCHR3(T2)	;SET LAST TWO WORDS
	RET

;TTRBM - READ BREAK MASK
;ACCEPTS:	T1/ADDRESS OF FOUR WORD AREA
;		T2/DYNAMIC  DATA ADDRESS
;RETURNS:	+1, ALWAYS
;			DESTROYS T3 & T4

TTRBM::	DMOVE T3,TTCHR1(T2)	;GET MASK VALUES
	DMOVEM T3,(T1)		;FIRST TWO WORDS OF MASK
	DMOVE T3,TTCHR3(T2)	;GET LAST TWO WORDS
	DMOVEM T3,2(T1)		;AND STORE
	RET
;TTSFW - SET THE FIELD WIDTH
;ACCEPTS:	T1/FIELD WIDTH
;		T2/DYNAMIC DATA ADDRESS
;RETURNS:	+1,ALWAYS

TTSFW::	SUB T1,TTICT(T2)	;SUBTRACT NUMBER ALREADY IN BUFFER
	JUMPLE T1,[	SETZRO TTFCNT,(T2)	;YES - DISABLE FIELD WIDTH
		CALLRET TTFWAK]	;GO WAKE PROCESS
	STOR T1,TTFCNT,(T2)	;SET THE FIELD WIDTH
	RET

;TTRFW - READ THE FIELD WIDTH
;ACCEPTS:;		T2/DYNAMIC DATA ADDRESS
;RETURNS:	+1,ALWAYS
;			T1/FIELD WIDTH

TTRFW::	LOAD T1,TTFCNT,(T2)	;READ THE FIELD WIDTH
	RET
	SWAPCD
;ROUTINE TO COMPUTE TT%WAK BITS FROM FULL CHARACTER BIT MASK
;ACCEPTS:	T1/ TERMINAL MODE WORD
;		T2/ DYNAMIC DATA ADDRESS
;	CALL TTCBM
; RETURN +1,	T1/ UPDATED TERMINAL MODE WORD
;		T3/ CLOBBERED
;		T4/ CLOBBERED

TTCBM:	PUSH P,Q1		;SAVE Q1
	TXZ T1,TT%WAK		;WE SET THIS FIELD
	TXZ T1,TT%IGN		;MAKE SURE THE "IGNORE" BIT IS OFF
	MOVSI Q1,-NRPTB		;SET TO SCAN WORDS OF TABLE
	XMOVEI T4,TTCHR1(T2)	;POINT TO BREAK MASK WORD 1
TTSW1:	MOVE T3,0(T4)		;GET USER MASK
	TDNE T3,RPTB(Q1)	;ANY PUNCTUATION HERE?
	TXO T1,TT%WKP		;YES, SET WAKEUP ON PUNCT
	TDNE T3,RATB(Q1)	;ANY ALPHANUMERICS HERE?
	TXO T1,TT%WKA		;YES, SET WAKEUP ON ALPHA
	AOS T4
	AOBJN Q1,TTSW1		;SCAN ALL MAK WORDS
	POP P,Q1		;RESTORE Q1
	MOVE T3,TTCHR1(T2)	;GET USERS FIRST WORD
	TXNE T3,MO%WN1-400	;ANY FORMAT CONTROLS HERE?
	TXO T1,TT%WKN		;YES, SET WAKEUP ON NON-FORMAT CTL
	TXNE T3,MO%WF1-400	;ANY FORMAT CONTROLS HERE?
	TXO T1,TT%WKF		;YES, SET WAKEUP ON FORMAT CTL
	TXNE T1,TT%WAK		;SPECIAL CASE FOR ESCAPE AND RUBOUT
	RET			;ALL SET - ESCAPE AND RUBBOUT TAKEN CARE OF
	TXNE T3,400		;IS THERE AN ESCAPE?
	TXO T1,TT%WKF		;YES - THEN SET IN TT%WAK
	MOVE T3,TTCHR4(T2)	;SEE IF RUBOUT IS ON
	TXNE T3,20
	TXO T1,TT%WKF		;YES - THEN SET IT
	RET

;PUNCTUATION MASK TABLE

RPTB:	MO%WP1			;0-37
	MO%WP2			;40-77
	MO%WP3			;100-137
	MO%WP4-20		;140-177
NRPTB==.-RPTB

;ALPHANUMERICS MASK TABLE

RATB:	MO%WA1			;0-37
	MO%WA2			;40-77
	MO%WA3			;100-137
	MO%WA4-20		;140-177
; ROUTINE TO COMPUTE AND SET FULL BREAK MASK FROM THE TT%WAK BITS
;
;ACCEPTS:	T1/ MODE WORD
;		T2/ ADDRESS OF DYNAMIC DATA
;RETURNS: +1,	WITH MASK SET
TTCFM:	STKVAR <<TTSMH1,2>,<TTSMH2,2>,<TTMS1,4>>
	DMOVEM T3,TTSMH1	;SAVE T3 & T4
	DMOVEM Q1,TTSMH2	;SAVE Q1 & Q2
	SETZB T3,T4
	SETZB Q1,Q2
	TXNN T1,TT%WAK		;ARE ANY BITS SET?
	JRST TTMSET		;NO - THEN CLEAR WAKE-UP MASK AND GO
	TXO T3,400		;SET THE ESCAPE BIT
	TXO Q2,20		;SET THE RUBOUT
	TXNE T1,TT%WKF		;WANT FORMATTING CONTROLLS
	TXO T3,MO%WF1		;YES - SET FORMATTING CONTROLS
	TXNE T1,TT%WKN		;WANT NON-FORMATTING CONTROLS?
	TXO T3,MO%WN1		;YES - SET THEM UP
	TXNE T1,TT%WKP		;WANT PUNCTUATION?
	JRST [	TXO T3,MO%WP1
		TXO T4,MO%WP2
		TXO Q1,MO%WP3
		TXO Q2,MO%WP4
		JRST .+1]
	TXNE T1,TT%WKA		;WANT ALPHANUMERICS?
	JRST [	TXO T3,MO%WA1
		TXO T4,MO%WA2
		TXO Q1,MO%WA3
		TXO Q2,MO%WA4
		JRST .+1]
TTMSET:	DMOVEM T3,TTMS1		;SAVE FIRST TWO WORDS OF MASK
	XMOVEI T3,TTMS1		;POINT TO SECOND TWO WORDS
	ADDI T3,2
	DMOVEM Q1,(T3)		; LAST TWO WORDS
	MOVE T3,T1
	XMOVEI T1,TTMS1		;POINT TO FULL MASK
	CALL TTSBM		;SET THE MASK
	MOVE T1,T3
	DMOVE T3,TTSMH1		;RESTORE T3 AND T4
	DMOVE Q1,TTSMH2		; AND Q1 AND Q2
	RET

	ENDSV.			;END STKVAR
;ROUTINE USED BY TEXTI TO COMPUTE PARITY FOR AN EDITING
;CHARACTER.
;	T2/ THE CHARACTER.
;RETURNS +1 ALWAYS. WITH EVEN PARITY IN B

TTCMPP::SKIPGE CHITAB(T2)	;NEED PARITY ON THIS CHARACTER?
	TRO T2,200		;YES. SO DO IT
	RET			;AND DONE
	SUBTTL TTMSG JSYS

;TTMSG JSYS - SENDS MESSAGES TO ALL TTYS VIA ECHO BUFFER

;ACCEPTS:
;	T1/ (0,,400000+N) WHERE N IS TERMINAL NUMBER
;		OR
;	    -1 FOR ALL LINES

;		OR

;		0=> TIME-OUT AND ARG IN C

;	T2/ POINTER TO SOURCE STRING

;	TTMSG

;RETURNS +1: ALWAYS

;CAN ITERR, BUT RETURNS SUCCESS IF LINE REFUSES SENDALL

;NOTE: THE TTNTS BIT, WHICH PREVENTS SENDALL TO A GIVEN LINE, APPLIES
;TO TTMSG WITH T1 CONTAINING -1 (FOR ALL LINES), NOT WITH T1 CONTAINING
;A SPECIFIC LINE NUMBER
;TTMSG...

.TTMSG::MCENT
	TRVAR <TTMSBY,TTMSCT,WTFLG,TTCAPF>
	SETOM TTCAPF		;ASSUME ALL PRIVILEGES UNLESS...
	CALL CKMMOD		;IS CALLER IN MONITOR MODE?
	IFNSK.
	  MOVE D,CAPENB		;NO. GET CAPS
	  TXNN D,SC%WHL!SC%OPR ;IS HE PRIVILEGED?
	  SETZM TTCAPF		;NO, NOTE
	  MOVE D,CTRLTT		;--- MAYBE LOGGED INTO CTY?
	  CAMN D,CTYLNO		;---
	  SETOM TTCAPF		;--- YEP, TURN CAPS BACK ON
	  JFCL			;--- DON'T BREAK THE WEIRD MACRO...
	ENDIF.
	SKIPN TTCAPF		;ENABLED?
	SKIPL CTRLTT		;NO, MUST NOT BE DETACHED
	IFSKP. <ITERR GTDIX1>
	NOINT
TTMSH1:	AOSE SALLCK		;CAN GET SENDALL RESOURCES?
	IFNSK.
	  OKINT
	  MOVEI A,^D30000	;WAIT 30 SEC MAX
	  CALL SETBKT		;SETUP TIMER TEST WORD
	  HRRI A,SALTST
	  MDISMS		;WAIT FOR LOCK FREE OR 30 SEC
	  NOINT
	  AOSE SALLCK		;HAVE LOCK NOW?
	  ITERR TTMSX1		;NO, SOMETHING PROBABLY BUSTED
	ENDIF.
	MOVEI A,1		;INIT COUNT OF ACTIVE LINES, +1 WHILE HEREIN
	MOVEM A,SALCNT
	UMOVE A,1
	SETZM WTFLG		;ASSUME NO WAIT
	JUMPE A,[AOS WTFLG	;NO WAIT
		 UMOVE A,3	;GET ARG
		 JRST .+1]	;PROCEED
	CAME A,[-1]		;ALLOW -1 AS AN ARGUMENT
	IFSKP.
	  SKIPN TTCAPF		;BUT ONLY IF CAPABILITIES PRESENT
	  ITERR GTDIX1
	ELSE.
	  CAIL A,.TTDES		;MAKE SURE TTY ARGUMENT IS NOT TOO SMALL
	  CAIL A,.TTDES+NLINES	;AND NOT TOO LARGE
	  JRST [SETOM SALLCK	;CLEAR LOCK
		ITERR GTJIX2]	;REPORT INVALID
	ENDIF.
	TLC B,-1		;CHECK SOURCE PTR
	TLCN B,-1		;HAD A -1 IN LH?
	HRLI B,(POINT 7,)	;YES. GET STANDARD BYTE POINTER
	UMOVEM B,B		;RETURN BYTE POINTER
	SKIPL P3,A		;SAVE ARG, ALL LINES?
	TXZ P3,.TTDES		;NO, GET LINE NUMBER
	BLCAL. GETSAL,<<.,SALBFR>,<.,TTMSCT>,<.,TTMSBY>,TTCAPF>
				;SETUP SENDALL BFR
	 ITERR ,<SETOM SALLCK>

;BUFFER IS SET UP WITH TEXT. IF THERE ARE NO CHARACTERS,
;WE ARE DONE.

	SKIPN TTMSCT		;AT LEAST ONE BYTE?
	JRST TTMS50		;NO. GO FINISH
	JUMPL P3,[SETZ C,	;IF DOING ALL LINES, START WITH LINE TYPE 0
		JRST TTMS26]	;ENTER LOOP
	MOVE B,P3		;SINGLE LINE, GET LINE NUMBER
	TDCALL S,<<FE,TTMSSN>,<MC,MCCKSA>,<NT,TTMSNT>,<DZ,RSKP>,<ML,TTMSML>,<CH,TTMSCH>,<TV,TVMSNT>> 
				;SKIP TO SEND
	 JRST TTMS50		;SKIP THIS LINE
	CALL SALLIN		;DO THE LINE
	 JFCL			;FAILED. IGNORE IT.
	JRST TTMS50		;DONE
;GET THE FIRST LINE OF THIS LINE TYPE

TTMS26:	MOVE B,TT1LIN(C)	;GET FIRST LINE OF THIS TYPE
	JUMPL B,TTMS24		;JUMP IF NO LINES OF THIS TYPE
	JRST TTMS20		;GO DO IT

;GO TO NEXT LINE.  IF THE LINE TYPE CHANGES, DON'T PROCEED WITH THE NEW
;LINE.  INSTEAD, GO TO THE NEXT LINE TYPE AFTER THE ONE JUST PROCESSED.
;THIS CODE ASSUMES THAT ALL LINES OF A GIVEN TYPE ARE NUMBERED CONSECUTIVELY.

TTMS21:	LOAD C,TTSTY,(B)	;GET CURRENT TYPE
	ADDI B,1		;GO TO NEXT LINE
	CAIL B,NLINES		;BEYOND END OF LINES?
	JRST TTMS24		;YES. GO TO NEXT LINE TYPE
	LOAD A,TTSTY,(B)	;GET TYPE OF NEW LINE
	CAME C,A		;SAME AS PREVIOUS LINE?
	JRST TTMS24		;NO. GO TO NEXT LINE TYPE

;SAME LINE TYPE AS PREVIOUS ONE. DO ACCORDING TO DEVICE DEPENDENT CODE
;DEVICE-DEPENDENT CODE RETURNS:
;	+1: DON'T DO THIS LINE
;	+2 AND T2/-1: DON'T DO ANY LINES OF THIS TYPE
;	+2 AND T2/LINE NUMBER: DO THIS LINE

TTMS20:	MOVE A,SALBFR		;PASS BYTE PTR
	HRLI A,(POINT 8,0)
	MOVE D,C		;SAVE THE LINE TYPE FOR THE TDCALL
	MOVE C,TTMSCT		;PASS COUNT
	TDCALL S,<<FE,TTMSAL>,<MC,MCCKSA>,<PT,TTMSNO>,<NT,TTMSNT>,<DZ,DZSNDL>,<ML,TTMSML>,<CH,TTMSCH>,<TV,TVMSNT>>
	 JRST TTMS21		;DON'T DO THIS LINE. GO ON TO NEXT LINE
	MOVE C,D		;RESTORE LINE TYPE
	JUMPL B,TTMS24		;SKIP THE ENTIRE GROUP

;HERE WHEN DEVICE DEPENDENT CODE WANTS THE SENDALL DONE FOR IT

TTMS22:	JN TTNTS,(B),TTMS21	;DON'T DO IF NON-TERMINAL
	CALL SALLIN		;DO SENDALL FOR THE LINE
	 JFCL			;FAILED. IGNORE IT.
	JRST TTMS21		;THEN GO GET NEXT LINE

;FINISHED THE CURRENT LINE TYPE OR THE LINE TYPE IS NOT TO BE PROCESSED
;GO TO THE NEXT TYPE

TTMS24:	AOS C			;GO TO NEXT LINE TYPE
	CAIL C,NLTYPS		;BEYOND END OF LEGAL TYPES?
	JRST TTMS50		;YES. DONE
	JRST TTMS26		;DO NEXT TYPE
;HERE WHEN ALL LINES HAVE BEEN PROCESSED FOR CURRENT BUFFERFUL.
;WAIT UNTIL ALL ARE SENT

TTMS50:	CALL DECSAL		;SEE IF ANY LINES GOING NOW
	OKINT
	JRST MRETN

;RETURN -1 IN B TO CAUSE ALL LINES OF THIS TYPE TO BE SKIPPED

TTMSNO:	SETO B,
	RETSKP
;SALLIN - DO SENDALL TO A SINGLE LINE

;ACCEPTS:
;	T2/ LINE NUMBER

	SWAPCD

SALLIN:	SAVELN			;SAVE LINE NUMBER
	STKVAR <SALLLN>
	MOVEM T2,SALLLN		;SAVE LINE NUMBER
	JN TTSHU,(T2),R		;IF LINE SHUT OFF, FORGET IT
	NOINT
	NOSKED
	CALL STADYN		;DOES LINE ALREADY HAVE DYNAMIC DATA?
	IFSKP.
SALLI2:	  TMNN <TTSAL,TTHPO>,(T2) ;YES, SENDALL PTR FREE?
	  JRST SALLI5		;YES, GO AHEAD
	  CALL LCKTT		;LOCK THE BLOCK WHILE WE DISMISS
;1026	  OKSKED
	  OKINT			;1026 This oughta work better
	  MOVEI T1,SALWAT	;WAIT TEST FOR SENDALL PTR FREE
	  HRL T1,T2		;DYNAMIC PTR
	  MDISMS
	  NOSKED		;NOSKED AGAIN
	  CALL ULKTT		;UNLOCK THE BLOCK
	  JRST SALLI2		;TRY AGAIN
	ENDIF.
	JUMPG T2,SALLI5		;HAS A MESSAGE BLOCK. OK TO USE
	JUMPL T2,[ OKSKED	;GO OKSKED FIRST
		RET]		;LINE IS BECOMING ACTIVE. CAN'T USE IT
	MOVE T2,SALLLN		;GET LINE NUMBER
	SETOM TTACTL(T2)	;INDICATE BECOMING ACTIVE
	OKSKED
	CALL ASGSHT		;GO GET A SHORT BLOCK
	 JRST [	SETZM TTACTL(T2) ;RESET ACTIVE POINTER
		RETBAD]
	NOSKD1
	TXO T1,TTSHBK		;SAY IS A SPECAIL
	MOVEM T1,TTACTL(T2)	;SAVE DYNAMIC STORAGE ADDRESS
	AOSG TTQCNT		;FIRST SPECIAL LINE?
	MOVEM T2,TTCQLN		;YES. START SCAN HERE THEN
	TXZ T1,TTSHBK		;MAKE ADDRESSABLE BLOCK
	MOVE T2,T1
SALLI5:	AOS SALCNT		;INCREMENT COUNT OF LINES DOING SENDALL
	MOVE T1,SALBFR		;GET SENDALL BFR ADDRESS
	HRLI T1,(POINT 8,0)	;MAKE BYTE PTR
	MOVEM T1,TTSAL2(T2)	;SAVE POINTER TO SENDALL STRING
	MOVE T1,TTMSCT		;GET COUNT OF CHARACTERS
	STOR T1,TSALC,(T2)	;SAVE COUNT OF SENDALL STRING
	SETONE TTSAL,(T2)	;INDICATE LINE IS DOING A SENDALL
	SETZ T3,		;FAKE OUT STRTOU
	CALL STRTOU		;START OUTPUT IF NEEDED
	MOVE T3,TTMSCT		;GET CHAR COUNT
	IDIVI T3,^D10		;MINIMUM OUTPUT RATE, 10 CHARS/SEC
	ADDI T3,5		;PLUS A SMALL PAD
	STOR T3,TSALT,(T2)
	CALL TSENDQ		;QUEUE A CHECK OF THE LINE
	OKINT
	RETSKP

	ENDSV.			;END STKVAR
	ENDTV.			;END TRVAR
;PERIODIC ROUTINE TO UNHANG STUCK SENDALL LINES
;CALLED FROM DOLINE (TTCH7)
; T2/ LINE NUMBER

	RESCD			;RESDIENT STUFF

CKSALL:	SAVEAC <T1>
	MOVE T1,T2		; Save line number
	CALL STADY		;STILL ACTIVE?
	 RET			;NO, DONE
	JE TTSAL,(T2),R		;DONE IF NO LONGER DOING SENDALL
	JN TTSHU,(T1),[CALLRET CLRSAL] ;IF LINE SHUT OFF, CLEAR IMMED.

	DECR TSALT,(T2)		;COUNTDOWN SECONDS
	JN TSALT,(T2),[CALLRET TSENDQ] ;NOT EXPIRED, QUEUE ANOTHER CHECK
	CALLRET CLRSAL		;EXPIRED, CLEAR THE LINE

;QUEUE A CHECK OF A LINE DOING A SENDALL
; T2/ DYNAMIC PTR

TSENDQ:	SAVEAC <T2>
	MOVEI T1,^D1000		;ONE SECOND
	LOAD T2,TINTL,(T2)	;NEED LINE NUMBER HERE
	MOVEI T3,CKSALL		;ROUTINE TO CALL
	CALLRET TTQAD		;QUEUE IT

;CLEAR SENDALL STATE FOR LINE
; T2/ DYNAMIC PTR

CLRSAL:	CONI PI,CX		; Get current PI state
	PUSH	P,CX		; save
	PIOFF			; turn them off
	SETZRO <TSALC>,(T2)	;CLEAR SENDALL POINTER, COUNT
	SETZM TTSAL2(T2)
	SETZRO TTSAL,(T2)	;INDICATE NO LONGER DOING SENDALL
	POP P,CX		; Get old pi state
	ANDI CX,200		; Mask off right bit
	CONO PI,(CX)		; and restore
	IFQN. TTDAL,(T2)	;DID SOMEBODY TRY TO DEALLOCATE THIS?
	  CALL TTYDED		;YES, DO IT NOW
	   NOP
	ENDIF.
DECSAL:	SOSN SALCNT		;DECREMENT COUNT OF SENDALL LINES
	CALLRET RELSAL		;RELEASE SENDALL STORAGE
	RET

;RELEASE SENDALL STORAGE

RELSAL:	SAVEAC <T1,T2>
	MOVE T1,SALBFR
	CALL RELRES
	SETOM SALLCK		;RELEASE LOCK
	RET

;WAIT FOR LINE TO FINISH USING SENDALL PTR
;CALLED AS SCHEDULER TEST
; T1/ LINE NUMBER
;	JSP T4,SALWAT
;	 +1: STILL WAITING
;	 +2: READY

SALWAT::TMNE <TTSAL,TTHPO>,(T1)	;STILL DOING IT?
	JRST 0(T4)		;YES
	JRST 1(T4)		;NO, WAKEUP

;TEST FOR SALLCK FREE OR TIME EXPIRED
; T1/ VALUE FOR TIME TEST

SALTST::SKIPGE SALLCK		;LOCK FREE?
	JRST 1(T4)		;YES, WAKEUP
	JRST BLOCKT		;NO, CHECK TIME

	SWAPCD
;GETSAL - GET SENDALL BUFFER AND STORE LINE OF TEXT IN IT

;RETURNS +1: FAILURE
;	 +2: SUCCESS,
;		@TTMSCT/ COUNT OF BYTES
;		@TTMSBY/ LAST BYTE
;		@TTMSBF/ BUFFER ADDRESS
;		TTCAPF/ -1 IF PRIVILEGED

GETSAL:	BLSUB. <TTMSBF,TTMSCT,TTMSBY,TTCAPF>
	UMOVE B,B		;GET BYTE PTR
	SETZ C,			;INIT COUNT
GETSB2:	XCTBU [ILDB A,B]	;SCAN BYTES
	 ERJMP [RETBAD ARGX10]	;CAN'T REFERENCE IT
	JUMPE A,GETSB1		;NUL IS END OF STRING
	CAIN A,.CHLFD		;LF?
	ADDI C,4		;YES, WILL INCLUDE 4 FILLS
	AOJA C,GETSB2		;COUNT CHARS

GETSB1:	MOVEM C,@TTMSCT		;SAVE COUNT
	SKIPN TTCAPF		;PRIVILEGED?
	ADDI C,^D55		;NO, ACCOUNT FOR HEADER
	CAIL C,TSALCM		;less than max allowed?
	 RETBAD ENQX19		;no, don't allow it
	ADDI C,4		;ROUND UP
	IDIVI C,4		;COMPUTE NUMBER WORDS REQUIRED
	BLCAL. ASGRSB,<C,[.RESP3],[.RESTP]> ;GET RES STG FROM TERMINAL POOL
	 RETBAD()		;FAILED - SHOULDN'T HAPPEN
	MOVEM A,@TTMSBF		;SAVE ADDRESS
	HRLI A,(POINT 8,0)	;BUILD BYTE PTR - 8-BIT, INCLUDES PARITY BIT
	SKIPE TTCAPF		;CAPABILITIES?
	IFSKP.
	  HRROI B,[ASCIZ /From /] ;No, must prefix header
	  CALL GSALCP		;BUILD STRING IN RES STG
	  HRROI B,USRNAM+1
	  CALL GSALCP		;USER NAME
	  HRROI B,[ASCIZ / on line /]
	  CALL GSALCP
	  MOVE B,CTRLTT
	  MOVEI C,^D8		;LINE NUMBER, OCTAL
	  NOUT
	   NOP
	  MOVEI B,[ASCIZ /: /]
	  CALL GSALCP
	  HRRZ B,A		;COMPUTE NUMBER BYTES IN HEADER STRING
	  SUB B,@TTMSBF		;NUMBER FULL WORDS
	  IMULI B,4		;NUMBER BYTES
	  ADDM B,@TTMSCT	;ADJUST COUNT
	  LDB B,[POINT 3,A,2]	;P FIELD, HIGH-ORDER 3 BITS
	  MOVN B,B
	  ADDI B,4		;NUMBER BYTES IN LAST (PARTIAL) WORD
	  ADDM B,@TTMSCT	;ADJUST COUNT
	ENDIF.
	MOVE C,A		;DEST BYTE PTR
	MOVE D,@TTMSCT

;LOOP THROUGH CHARACTERS IN USER'S STRING, COPYING TO INTERNAL BUFFER.
;ADD FILL AFTER LINE FEED.  STOP AT END OF LINE OR WHEN BUFFER IS FULL,
;WHICHEVER IS FIRST

GETSA1:	XCTBUU [ILDB P1,B]	;GET NEXT BYTE
	 ERJMP [MOVE A,@TTMSBF	;FAILED, RETURN STORAGE
		CALL RELRES
		RETBAD(ARGX10)]	;AND RETURN TO CALLER
	JUMPE P1,GETSA6		;STOP ON NULL
	ANDI P1,177		;USE ONLY 7-BIT ASCII
	SKIPG CHITAB(P1)	;NEED PARITY BIT?
	TRO P1,200		;YES. APPLY IT THEN
	SOJL D,GETSA6		;COUNT CHARS
	IDPB P1,C		;USE IT
	CAIE P1,.CHLFD		;A LINE FEED?
	JRST GETSA1		;NO, LOOP

;END OF LINE. INSERT 4 FILLS

	MOVEI P4,4		;FILLS TO DO
	MOVEI P2,TTFILL		;THE FILL CHARACTER
GETSA3:	SOJL D,GETSA6		;JUMP IF BUFFER FULL
	IDPB P2,C		;INSERT A FILL
	SOJG P4,GETSA3		;DO ALL FILLS
	JRST GETSA1		;LOOP

;END OF STRING OR COUNT EXHAUSTED (COUNT CAN ONLY BE WRONG IF STRING
;IN USER SPACE CHANGED SINCE WE COUNTED IT.)

GETSA6:	MOVEM P1,@TTMSBY	;SAVE LAST BYTE COPIED
	RETSKP

;LOCAL SUBROUTINE TO COPY STRING
; A/ DEST BYTE PTR
; B/ SOURCE BYTE PTR
;	CALL GSALCP
;COPY UNTIL NULL
; RETURN +1: ALWAYS, NULL FOLLOWS END OF DEST STRING

GSALCP:	HLRZ C,B		;CHECK SOURCE PTR
	CAIN C,-1		;NEEDS INIT?
	HRLI B,(POINT 7,0)	;YES
      DO.
	ILDB T3,T2		;GET BYTE
	IDPB T3,T1		;STORE IT
	JUMPN T3,TOP.		;LOOP IF NOT NULL
      OD.
	CALLRET DBP		;DECREMENT DEST PTR OVER NULL AND RETURN

	ENDBS.
;SIMULATE TTY INPUT

;ACCEPTS:
;	T1/ CHARACTER
;	T2/ INTERNAL LINE NUMBER

;CALL TTSTI

;RETURNS +1: ALWAYS

	SWAPCD

TTSTI::	ANDI 1,377		;ISOLATE CHARACTER
	NOSKED
	CAME 2,CTYINT		;CTY ALIAS?
	CALL TTCHI		;NO. PUT CHAR INTO LINE BUFFER
	 JRST [	OKSKED		;FAILED, BUFFER FULL
		RETBAD IOX33]
	OKSKED
	RETSKP

REPEAT 0,<
;OBNFT - SCHEDULER TEST FOR OUTPUT BUFFER NOT FULL

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF OUTPUT BUFFER IS NOT FULL

	RESCD			;MUST BE RESIDENT
OBNFT:	MOVE T2,T1		;SETUP LINE
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 JRST 1(T4)		;SHOULDN'T HAPPEN. WAKE PROCESS
	LOAD T3,TOMAX,(T2)
	CAMG T3,TTOCT(T2)	;FULL?
	JRST 0(T4)		;YES
	JRST 1(T4)		;NO
>
	SUBTTL STO JSYS

	SWAPCD			;SWAPPABLE. CALLED AS A JSYS
.STO::	MCENT
STO11:	UMOVE 1,1
	CALL CHKTTY		;CHECK GIVEN DESIGNATOR
	 ITERR()		;NOT TTY
	CALL LCKTTY		;GET ADDRESS OF DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY
		ITERR (TTYX01)]	;NOT ACTIVE. RETURN ERROR
	CALL TTSTO
	 JRST STO11		;BLOCKED. TRY AGAIN
	UMOVEM 1,2		;RETURN CHAR IN 2
	CALL ULKTTY		;ALLOW DEALLOCATION OF DYNAMIC DATA
	JRST MRETN

	RESCD			;MAKE RESIDENT FOR EFFICIENCY
;TTSTO - REMOVE CHARACTER FROM OUTPUT BUFFER

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSTO

;RETURNS +1: BLOCKED, TRY AGAIN
;	+2 SUCCESS
;		T1/ CHARACTER

TTSTO::	NOSKD1
	CHNOFF DLSCHN		;CAN'T ALLOW SCANNER PI HERE
	CALL GTOCHR		;GET CHAR FROM OUT BFR
	 JRST TTSTO1		;EMPTY, BLOCK
	TXNN A,TTOESC		;A MARKER?
	IFSKP.
	  CAIE T1,.TTMRK	;SYNCH?
	  IFSKP. <
	    SETZRO TTFLO,(T2)>	;YES, CLEAR FLUSH FLAG
	  SETZ T1,		;RETURN A NUL
	ENDIF.
	CHNON DLSCHN
	OKSKD1
	RETSKP

;WAIT UNTIL BUFFER BECOMES NONEMPTY AND LINE INACTIVE

TTSTO1:	CHNON DLSCHN
	OKSKD1
	SETONE TTBKO,(T2)	;NOTE WAITING FOR OUTPUT EVENT
	DYNST T1		;GET STATIC LINE NUMBER
	CALL ULKTTY
	HRLZS T1		;LINE NUMBER TO LH
	HRRI T1,TTOAV		;TEST FOR BUFFER NOT EMPTY AND LINE INACTIVE
	MDISMS			;WAIT UNTIL SPECIFIED TEST IS SATISFIED
	RET			;SAY WE BLOCKED. TRY AGAIN

;TTOAV -  SCHEDULER TEST FOR OUTPUT AVAILABLE ON A LINE

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF OUTPUT BUFFER IS NOT EMPTY AND LINE IS INACTIVE

TTOAV::	HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 JRST 1(T4)		;NOT ACTIVE. THIS SHOULDN'T HAPPEN
	TMNN TTOTP,(T2)		;IS LINE ACTIVE?
	SKIPN TTOCT(T2)		;NO. ARE THERE CHARACTERS?
	JRST 0(T4)		;ACTIVE OR NO CHARACTERS AVAILABLE. DON'T WAKEUP
	SETZRO TTBKO,(T2)	;NOTE WAIT COMPLETED
	JRST 1(T4)		;INACTIVE AND CHARACTERS AVAILABLE. WAKEUP
	SUBTTL STTYP/GTTYP JSYS'S

;.STTYP - SET TERMINAL TYPE

;ACCEPTS:
;	T1/ TERMINAL DESIGNATOR
;	T2/ TERMINAL TYPE NUMBER

;	STTYP

;RETURNS +1: ALWAYS

	SWAPCD
.STTYP::MCENT
	CALL CHKTTY
	 ITERR ()		;ASSUME CHKTTY SET UP ERROR REASON
	MOVEI Q1,(T2)		;17 SAVE INTERNAL LINE NUMBER
	UMOVE T3,T2		;GET TERMINAL TYPE SPECIFIED
	TLZ T3,-1		;17 CLEAR OUT FLAGS FOR CHECK
	CAIL T3,0		;REASONABLE NUMBER?
	CAIL T3,NTTYPS
	ITERR (STYPX1)		;TERMINAL TYPE NOT IN RANGE
	CAIL Q1,NTTFE		;17 IF THIS ISN'T AN FE LINE,
	 JRST STTYP0		;17  SKIP THIS CHECK
	MOVE T1,TTTYPS(Q1)	;17 IT IS, PICK UP STATIC TYPE AND FLAGS
	TXNE T1,SY%NTS		;17 TYPE SETTING ALLOWED FOR THIS LINE?
	 JRST [	MOVE T1,CAPENB	;17 ONLY IF SOME CAPS ENABLED
		TXNN T1,SC%WHL!SC%OPR!SC%CNF!SC%MNT
		JRST .+1	;17 HAS SOME, GO ON
		JRST MRETN ]	;17 NOPE, BAIL OUT
STTYP0:	CALL LCKTTY		;GET DYNAMIC DATA AND PREVENT DEALLOCATION
;17	 JRST [	CALL ULKTTY	;NOT ACTIVE. ALLOW DEALLOCATION
;17		ITERR (TTYX01)]
	 JRST STTYP2		;17 NOT ACTIVE, ONLY SET PERMANENT DATA
	STOR T3,TTTYP,(T2)	;STORE NEW TERMINAL TYPE
	CALL TTNTYP		;SET TYPE DEPENDANT PARAMETERS IN DYN DATA
	LOAD T3,TTTYP,(T2)	;GET TYPE BACK
	LDB T1,TTMBIT		;GET MECH BITS
	DPB T1,[POINT 3,TTFLGS(T2),3] ;PUT WHERE NOTICED
;17 BEGIN ADDITION
STTYP2:	UMOVE T1,T2		;PICK UP FLAGS,,TYPE
	TXNN T1,SY%PRM		;TRYING TO SET THE STATIC TYPE?
	 JRST STTYP3		;NO, GO ON
	MOVE T1,CAPENB		;YES, MAKE SURE CAN DO IT
	TXNN T1,SC%WHL!SC%OPR!SC%CNF!SC%MNT
	JRST [	CALL ULKTTY
		ITERR(CAPX1) ]	;NOPE.
	CAIL Q1,NTTFE		;IF NOT A FE LINE,
	 JRST STTYP3		; DON'T DO ANYTHING TO THE STATIC TABLE
	LOAD T1,TTSTY,(Q1)	;GET LINE TYPE FOR THIS ONE
	CAIE T1,TT.PTY		;PTY?
	 CAIN T1,TT.NVT		;OR NVT?
	 JRST STTYP3		;YES, NOTHING MORE TO DO THEN
	CAIE T1,TT.TVT		;1010 TVT?
	CAIN T1,TT.CVT		;158 OR IF CVT
	 JRST STTYP3		;158 DO NOTHING
	HRRM T3,TTTYPS(Q1)	;SET TYPE NOW
	UMOVE T1,T2		;GET BACK FLAGS
	ANDX T1,<SY%NTS!SY%NSS> ;CLEAR OUT ALL BUT WHAT WE KNOW AND LOVE
	IORM T1,TTTYPS(Q1)	; AND SET THEM IN ALSO
STTYP3:
;17 END ADDITION
	CALL ULKTTY		;ALLOW DEALLOCATION
	JRST MRETN
;.GTTYP - GET TERMINAL TYPE

;ACCEPTS:
;	T1/ TERMINAL DESIGNATOR


;	GTTYP

;RETURNS +1: ALWAYS
;		T2/ TERMINAL TYPE
;		T3/ (NUMBER INPUT BUFFERS,,NUMBER OUTPUT BUFFERS)

.GTTYP::MCENT
	CALL CHKTTR
	 JRST [	XCTU [SETZM T2]	;NOT TTY, RETURN 0
		JRST MRETN]
	MOVEI Q1,(T2)		;17 SAVE INTERNAL LINE NUMER
	CALL LCKTTY		;POINT TO DYNAMIC DATA AND PREVENT DEALLOCATION
;17	 JRST [	CALL ULKTTY	;NOT ACTIVE. ALLOW DEALLOCATION
;17		ITERR (TTYX01)]
	 JRST GTTYP3		;17 NOT ACTIVE, GET DEFAULT FOR ITS LINE TYPE
	LOAD T1,TTTYP,(T2)	;GET TERMINAL TYPE
	UMOVEM T1,T2
	LOAD T1,TTNIN,(T2)	;GET NUMBER OF INPUT BUFFERS
	LOAD T3,TTNOU,(T2)	;GET NUMBER OF OUTPUT BUFFERS
	HRLI T3,0(T1)		;COMBINE THEM FOR USER
	UMOVEM T3,T3
GTTYP2:	CALL ULKTTY		;17 ALLOW DEALLOCATION OF DYNAMIC DATA
	JRST MRETN

;17 BEGIN ADDITION

GTTYP3:	EXCH T2,Q1		;SWAP INT LINE NO WITH VALUE OF LCKTTY
	CALL GTYPPE		;GET TYPE FROM PERMANENT MATRIX
	UMOVEM T3,T2		;RETURN IT TO USER
	MOVEI T2,(Q1)		;RESTORE VALUE OF LCKTTY
	JRST GTTYP2		;GO ALLOW DEALLOCATION AND RETURN

	RESCD

;GET TERMINAL TYPE FROM PERMANENT DATA
; T2/ LINE NUMBER
; T3/ LINE TYPE (FOR GTYPP0)

GTYPPE:	LOAD T3,TTSTY,(T2)	;GET LINE TYPE FROM STATIC AREA
GTYPP0:	CAIN T3,TT.PTY		;A PTY?
	 JRST GTYPP1		;YES, RETURN SYSTEM DEFAULT
	CAIE T3,TT.CVT		;158 AN NVT?
	CAIN T3,TT.NVT		;...
	 JRST GTYPP2		;YES, RETURN NVT TERMINAL TYPE
	CAIN T3,TT.TVT		;1010 TVTT?
	 JRST GTYPP2		;1010 A kind of NVT
	LOAD T3,TTFEM,(T2)	;SEE IF LINE IS REMOTE
	JUMPN T3,GTYPP1		;IF SO, USE SYSTEM DEFAULT
	CAIL T2,NTTFE		;ELSE, IF OUT OF RANGE FOR FE LINES,
	 JRST GTYPP1		; USE SYSTEM DEFAULT
	HRRZ T3,TTTYPS(T2)	;PICK UP STATIC TABLE
	JUMPN T3,R		;RETURN IT IF IT IS THERE
GTYPP1:	SKIPA T3,NORMTY		;USE SYSTEM DEFAULT
GTYPP2:	 MOVEI T3,.TTNVT	;USE NVT TYPE FOR NETWORK TERMINALS
	RET

	SWAPCD
	SUBTTL STPAR JSYS

;.STPAR - SET TERMINAL PARAMETERS

;ACCEPTS:
;	T1/ TERMINAL DESIGNATOR
;	T2/ NEW JFN MODE WORD

;	STPAR

;RETURNS +1: ALWAYS

.STPAR::MCENT
	CALL CHKTTR		;IS THIS A TTY?
	 MRETNG			; NO, THEN THIS IS A NOOP
	CALL CHKTTY		;CAN WE GET TO IT?
	 EMRETN ()		; NO, ERROR OUT WITH REASON
	CALL LCKTTY		;POINT TO DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY	;NOT ACTIVE. ALLOW DEALLOCATION
		ITERR (TTYX01)]
	NOINT			;I WILL NOT DIE
	UMOVE 1,2		;GET NEW JFN MODE WORD
	TDCALL D,<<PT,STPAR5>,<NT,NVTPAR>,<CH,NVTPAR>,<TV,TVTPAR>>
	PUSH P,1
	XOR 1,TTFLGS(2)
	ANDI 1,TT%ECM+TT%UOC+TT%LIC+TT%DUM+TT%PGM ;CHANGE THESE BITS
	XORM 1,TTFLGS(2)
	TXNE T1,TT%PGM		;DID PAGE MODE CHANGE?
	IFNSK. <TDCALL D,<<FE,TTEXF>,<MC,MCEXF>>> ;YES, FIX XOFF RECOG IN FE
	PUSH P,1
	TXNE 1,TT%PGM		;CHANGING PAGE MODE?
	CALL TTXONA		;YES, BE SURE OUTPUT NOT STOPPED
	SETZRO TLNCT,(2)	;AND RESET PAGE POSITION
	POP P,1
	LDB 1,[POINT 7,0(P),10]
	JUMPE T1,STPAR2		;ALLOW ZERO LENGTH
	CAIL 1,2		;LEGAL PAGE SIZE?
	CAIL 1,200
	JRST STPAR0		;ILLEGAL SIZE DOES NOT CHANGE SETTING
STPAR2:	STOR T1,TPLEN,(2)
	CALL SETEOP		;FIX UP END-OF-PAGE SIZE
STPAR0:	LDB 1,[POINT 7,0(P),17]
	JUMPE T1,STPAR3		;ALLOW ZERO WIDTH
	CAIL 1,10		;LEGAL WIDTH
	CAIL 1,200
	JRST STPAR1		;ILLEGAL WIDTHS DON'T CHANGE THE SETTING
STPAR3:	STOR T1,TPWID,(2)
STPAR1:	LDB 1,[POINT 3,0(P),3]
	DPB 1,[POINT 3,TTFLGS(2),3] ;LH BITS
	POP P,1
	CALL ULKTTY		;ALLOW DEALLOCATION OF DYNAMIC DATA
	OKINT			;I CAN BE KILLED NOW
	JRST MRETN
	SUBTTL TLINK JSYS

;.TLINK - ESTABLISH/REMOVE LINKS BETWEEN TERMINALS

;ACCEPTS:
;	T1/ (FLAGS,,OBJECT LINE NUMBER)
;	T2/ REMOTE LINE NUMBER OR -1 FOR ALL

;	TLINK

;RETURNS +1: FAILURE
;		T1/ ERROR CODE
;	 +2: SUCCESS

;FLAGS:
;	TL%CRO - B0 - CLEAR REMOTE TO OBJECT
;	TL%COR - B1 - CLEAR OBJECT TO REMOTE
;	TL%EOR - B2 - SET OBJECT TO REMOTE
;	TL%ERO - B3 - SET REMOTE TO OBJECT
;	TL%SAB - B4 - SET OR CLEAR ACCEPT LINKS ACCORDING TO B5
;	TL%ABS - B5 - SET ACCEPT LINKS
;	TL%STA - B6 - SET OR CLEAR ACCEPT ADVICE ACCORDING TO B7
;	TL%AAD - B7 - SET ACCEPT ADVICE

;'OBJECT' IS USUALLY THE CALLER OF THE JSYS; 'REMOTE' IS THE OTHER LINE

.TLINK::MCENT
	TRVAR <OBJNO,OBJADR,REMNO,TLSAV1,LNKWRN>
	SETOM LNKWRN		;ASSUME LINK MESSAGE IS NEEDED
	MOVEI T1,-.TTDES(T1)	;TURN OBJECT DESIGNATOR INTO LINE NUMBER
	CAIN T1,-1-.TTDES	;SPECIFIED -1 FOR OWN TERMINAL?
	SKIPL T1,CTRLTT		;YES, GET IT
	CAIL T1,NLINES		;VALIDATE LINE NUMBER
	 RETERR(DESX1)		;ILLEGAL
	MOVEM T1,OBJNO		;SAVE LINE NUMBER
	ADDI T1,.TTDES		;CREATE DESIGNATOR AGAIN
	CALL CHKDEV		;SEE IF TERMINAL IS AVAILABLE TO THIS JOB
	 SKIPA T1,CAPENB	;NO, MUST CHECK WHEEL
	JRST TLKOBG		;YES, PROCEED
	TXNN T1,SC%WHL!SC%OPR	;PRIVILEGED TO LINK RANDOM TERMINALS?
	RETERR (WHELX1)		;NO, LOSE
	SETZM LNKWRN		;NO MESSAGE IS TYPED LATER
TLKOBG:	MOVE T2,OBJNO		;GET BACK LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY	;NOT ACTIVE.
		RETERR (TTYX01)]
	MOVEM T2,OBJADR		;SAVE ADDRESS OF DYNAMIC DATA FOR OBJECT
	UMOVE 1,1		;GET BITS AND OBJECT DESIGNATOR
	TLNN 1,(74B5)		;SECOND DESIGNATOR REQUIRED?
	JRST TL1		;NO

;USER IS SETTING OR CLEARING LINKS. GET SECOND ARGUMENT, WHICH IS A LINE
;NUMBER (OR -1 FOR ALL LINES IF CLEARING LINKS)

	XCTU [HRRZ 2,2]
	CAIN 2,-1		;'ALL' ?
	JRST TL1		;YES, LEAVE AS IS
	TRZE 2,.TTDES		;4XXXXX?
	JRST TL2		;YES
	MOVE 1,2		;ASSUME REGULAR JFN
	CALL CHKTTY
	 JRST TLINK9
TL2:	CAIL 2,NLINES		;LEGAL LINE?
	JRST TL3		;NO. TOO LARGE
	CAIL 2,0		;NEGATIVE IS ILLEGAL
	CAMN T2,CTYINT		;ALIAS FOR CTY?
TL3:	JRST [	MOVEI T1,DESX1	;INVALID LINE. FAIL
		JRST TLINK9]

;T2/ LINE NUMBER FOR REMOTE OR -1

TL1:	MOVEM T2,TLSAV1		;SAVE REMOTE LINE NUMBER IF ANY
	MOVE FX,OBJNO		;GET BACK OBJECT NUMBER
	UMOVE Q2,1		;GET FUNCTION FLAGS
	TXNE Q2,TL%CRO		;CLEAR REMOTE TO OBJECT?
	CALL TLINK0		;YES. GO DO IT
	TXNE Q2,TL%COR
	 JRST [	CALL TLINK1	;CLEAR OBJECT TO REMOTE
		 JRST TLINK9	;FAILED. GO RETURN ERROR
		JRST .+1]
	TXNE Q2,TL%EOR
	JRST [	CALL TLINK2	;SET OBJECT TO REMOTE
		 JRST TLINK9	;FAILED
		JRST .+1]
	TXNE Q2,TL%ERO
	JRST [	CALL TLINK3	;SET REMOTE TO OBJECT
		 JRST TLINK9
		JRST .+1]
	TXNE Q2,TL%SAB
	CALL TLINK4		;SET ACCEPT BIT TO C(B5)
	TXNE Q2,TL%STA		;SET ADVICE BIT?
	CALL TLINK5
	MOVE T2,OBJADR		;T2/ ADDRESS OF OBJECT'S DATA
	CALL ULKTTY		;ALLOW DEALLOCATION
	SMRETN

;AN ERROR OCCURRED. UNLOCK DATA AND RETURN FAILURE

TLINK9:	SKIPE T2,OBJADR		;T2/ ADDRESS OF OBJECT'S DATA
	CALL ULKTTY		;ALLOW DEALLOCATION
	RETERR			;RETURN ERROR CODE
;CLEAR REMOTE TO OBJECT

;ACCEPTS:
;	TLSAV1/ REMOTE LINE NUMBER OR -1
;	FX/ OBJECT LINE NUMBER

;	CALL TLINK0

;RETURNS +1: ALWAYS

;DETERMINES WHETHER USER WANTS TO CLEAR ALL OR ONE. CALLS ROUTINE
;FOR EACH REMOTE LINE NUMBER

TLINK0:	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CAIE 2,-1		;ALL REMOTES?
	CALLRET TL0C		;NO, DO THE ONE SPECIFIED

;CLEAR LINKS FROM ALL REMOTES TO THIS OBJECT. LOOP THROUGH LINES

	MOVEI 2,0		;T2/ REMOTE LINE NUMBER
	CALL TL0C		;CLEAR LINKS FROM REMOTE TO OBJECT
	CAIGE 2,NLINES-1	;AT END OF LINES?
	AOJA 2,.-2		;NO. KEEP GOING
	RET			;YES. DONE

;TL0C - CLEAR ALL LINKS FROM SPECIFIED REMOTE TO OBJECT

;ACCEPTS:
;	T2/ REMOTE LINE NUMBER
;	FX/ OBJECT LINE NUMBER

;CALL TL0C

;RETURNS +1: ALWAYS

TL0C:	SAVELN
	CALL LCKTTY		;POINT TO DYNAMIC DATA FOR REMOTE
	 CALLRET ULKTTY		;NOT ACTIVE
TL0C1:	CALL TLTST1		;FIND LINK TO OBJECT IN REMOTE
	JUMPL 1,TL0C2		;DONE IF NO LINKS TO OBJ
	MOVEI 1,777		;FOUND ONE. CLEAR IT
	DPB 1,Q1		;CLEAR THE LINK JUST FOUND
	JRST TL0C1		;GO FIND ANOTHER

;DONE WITH THIS REMOTE LINE

TL0C2:	CALLRET ULKTTY		;ALLOW DEALLOCATION FOR REMOTE
;TLINK1 - CLEAR OBJECT TO REMOTE

;ACCEPTS:
;	FX/ OBJECT LINE NUMBER
;	TLSAV1/ REMOTE LINE NUMBER OR -1

;	CALL TLINK1

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TLINK1:	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CAIE 2,-1		;ALL?
	CALLRET TL1C		;NO, CLEAR SPECIFIC

;CLEAR ALL LINKS FROM THIS OBJECT. LOOP THROUGH LINK WORD

	MOVE Q1,[POINT 9,TTLINK(4),-1] ;POINT TO LINK WORD
TL12:	MOVE 4,OBJADR		;GET ADDRESS OF OBJECT'S DATA
	ILDB 2,Q1		;GET A LINE NUMBER
	CAIN 2,777		;IS THIS SLOT FREE?
	JRST TL14		;YES. SKIP IT
	PUSH P,Q1		;NO. SAVE BYTE POINTER
	CALL TL1C		;GO CLEAR ALL LINKS TO THIS REMOTE
	 RETBAD (,<POP P,Q1>)	;SOME SORT OF FAILURE
	POP P,Q1		;RESTORE BYTE POINTER
TL14:	TLNE Q1,(7B2)		;AT END OF LINK WORD?
	JRST TL12		;NO. GO TO NEXT FIELD
	RETSKP			;YES. DONE
;TL1C - CLEAR ALL LINKS FROM OBJECT TO THIS REMOTE

;ACCEPTS:
;	T2/ REMOTE LINE NUMBER
;	FX/ OBJECT LINE NUMBER

;	CALL TL1C

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TL1C:	CALL TLTST2		;FIND LINK TO REMOTE
	JUMPL 1,RSKP		;NONE, DONE

;OBJECT POINTS TO REMOTE. DON'T ALLOW CLEARING IF REMOTE ALSO POINTS
;TO OBJECT

	MOVE 1,CAPENB
	TRNE 1,SC%WHL+SC%OPR	;PRIVILEGED?
	JRST TL13		;YES, SKIP CHECK
	MOVEM T2,REMNO		;SAVE REMOTE LINE NUMBER
	CALL LCKTTY		;POINT TO REMOTE DYNAMIC DATA
	 JRST [	CALL ULKTTY
		JRST TL13]
	PUSH P,Q1
	CALL TLTST1		;SEE IF REMOTE POINTS TO OBJECT
	CALL ULKTTY		;UNLOCK REMOTE'S DATA
	POP P,Q1		;RESTORE POINTER TO REMOTE LINK WORD
	JUMPGE 1,TL15		;ERROR IF REMOTE POINTS TO OBJECT
TL13:	MOVEI 1,777
	DPB 1,Q1		;CLEAR LINK JUST FOUND
	MOVE T2,REMNO		;RESTORE REMOTE LINE NUMBER
	JRST TL1C

TL15:	RETBAD (TLNKX1)
;TLINK2 - SET OBJECT TO REMOTE

;ACCEPTS:
;	FX/ OBJECT LINE NUMBER
;	TLSAV1 / REMOTE LINE NUMBER OR -1

;	CALL TLINK2

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TLINK2:	STKVAR <TLNKT>
	MOVEI T2,5		;MAX TRIES IF REMOTE IF REFUSING
	MOVEM T2,TLNKT		;SAVE IT
TLNK2:	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CAIN 2,-1		;SPECIFIED ALL?
	RETBAD (DESX1)		;NON-SPECIFIC DESIGNATOR ILLEG HERE
	CAMN 2,FX		;LINK TO SELF?
	RETSKP			;YES, IGNORE
	CALL TLTST2		;LINK ALREADY EXISTS?
	JUMPG 1,RSKP		;IGNORE IF YES
	MOVEI T2,777		;LOOK FOR AN EMPTY SLOT
	CALL TLTST2		; THAT WE COULD ACCEPT WITH
	JUMPL T1,[RETBAD (TLNKX3)] ;ALL LINKS ARE IN USE ALREADY
	MOVE T2,TLSAV1		;GET BACK THE REMOTE LINE NUMBER

;IF REMOTE IS NOT ACCEPTING LINKS, RING THE BELL AND WAIT TO SEE IF
;USER DECIDES TO ACCEPT

	CALL LCKTTY		;POINT TO REMOTE DYNAMIC DATA
	 JRST [	CALL ULKTTY
		RETBAD (TTYX01)]

;REPEAT SEQUENCE OF CHECKING ACCEPT BIT, RINGING BELL, AND WAITING
;UNTIL EITHER REMOTE ALLOWS LINKS OR WE TIME OUT

TL21:	MOVEI 3,TT%ALK		;ACCEPT BIT
	MOVE 4,CAPENB
	TRNN 4,SC%WHL+SC%OPR	;PRIVILEGED? OR
	TDNE 3,TTFLGS(2)	;REMOTE ACCEPTING?
	JRST TL22		;YES
	SOSGE TLNKT		;TRY AGAIN?
	JRST TL24		;NO. CAN'T DO THE LINK
	CALL ULKTTY		;FREE REMOTE LOCK
	SKIPE T2,OBJADR		;GET OBJECT ADDRESS
	CALL ULKTTY		;FREE IT AS WELL
	SETZM OBJADR		;SAY NO LOCK HERE
	MOVEI 4,^D10		;A RING IS 10 BELLS

TL23:	NOSKED			;OWN MACHINE FOR A WHILE
	HRROI T1,[BYTE (7) .CHBEL] ;GET A BELL
	PUSH P,4		;SAVE COUNTER
	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CALL TTEMES		;OUTPUT A BELL
	HRROI T1,[BYTE (7) .CHBEL] ;GET A BELL AGAIN
	MOVE T2,FX		;GET OBJECT LINE NUMBER
	CALL TTEMES		;OUTPUT A BELL HERE TOO
	POP P,4			;RESTORE COUNTER
	OKSKED			;RELEASE MACHINE NOW
	SOJG 4,TL23
	;..
;WAIT A WHILE

	;..
	MOVEI 1,^D3000		;WAIT FOR 3 SECONDS, THE BELL WILL BE
	DISMS			;RINGING FOR THE FIRST SECOND OF WAIT
	MOVE T2,FX		;GET OBJECT LINE NUMBER
	CALL LCKTTY		;LOCK IT UP
	 JRST [	CALL ULKTTY	;FREE IT
		RETBAD (TTYX01)] ;AND GIVE ERROR
	MOVEM T2,OBJADR		;SAY IT IS NOW LOCKED
	JRST TLNK2		;AND TRY AGAIN

	ENDSV.			;END STKVAR

;REMOTE IS ACCEPTING LINKS


TL22:	CALL ULKTTY
	MOVEI 2,777
	CALL TLTST2		;FIND FREE FIELD IN OBJECT
	JUMPL 1,[RETBAD (TLNKX3)] ;LINKS FULL
	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	DPB 2,Q1		;DEPOSIT REMOTE NUMBER IN FIELD
	MOVE T2,OBJADR		;GET OBJECT DYNAMIC DATA
	CALL ULKTTY		;FREE IT
	SETZM OBJADR		;NO LOCK HELD
	SKIPN LNKWRN		;LINKING FROM MY OWN JOB?
	JRST TL25		;NO, SKIP MESSAGE
	MOVE T1,OBJNO		;GET TERMINAL NUMBER
	ADDI T1,.TTDES		;TURN INTO DESIGNATOR
	HRROI 2,[ASCIZ /
Link from /]			;23
	SETZ 3,
	SOUT			;MSG ON OBJECT ALSO SEEN ON REMOTE
	 ERJMP TL25
	MOVE 2,JOBNO
	HRRZ 2,JOBDIR(2)	;USER ON THIS JOB
	HRLI 2,USRLH		;TURN IT INTO A USER NUMBER
	DIRST			;TYPE HIS NAME
	 SKIPA 2,[POINT 7,[ASCIZ /TTY/]]	;23 
	HRROI 2,[ASCIZ /, TTY/]	;23 
	XCTU [HRRZ 1,1]		;23 RESTORE OBJECT DESIGNATOR
	SOUT
	 ERJMP TL25
	MOVE 2,FX		;OBJECT LINE NUMBER
	MOVEI 3,10
	NOUT
	 ERJMP TL25
	HRROI T2,[ASCIZ /
/]
	SETZ T3,
	SOUT
	 ERJMP TL25
TL25:	MOVE T2,FX		;GET OBJECT LINE NUMBER
	CALL LCKTTY		;LOCK IT AGAIN
	 JRST [	CALL ULKTTY	;OOPS. WENT AWAY
		RETBAD (TTYX01)] ;GIVE ERROR
	MOVEM T2,OBJADR		;SAY HOLD LOCK
	RETSKP

TL24:	CALL ULKTTY
	RETBAD (TLNKX2)
;TLINK3 - SET REMOTE TO OBJECT

;ACCEPTS:
;	TLSAV1/ REMOTE LINE NUMBER OR -1
;	FX/ OBJECT LINE NUMBER

;	CALL TLINK3

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TLINK3:	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CAIN 2,-1
	RETBAD (DESX1)		;MULTIPLE DESIGNATOR ILLEGAL
	CAMN 2,FX		;LINK TO SELF?
	RETSKP			;YES, IGNORE
	CALL LCKTTY
	 JRST [	CALL ULKTTY
		RETBAD (TTYX01)]
	CALL TLTST1		;SEE IF REMOTE POINTS TO OBJECT
	JUMPG 1,TL33		;IF SO, ALREADY DONE
	MOVE 1,CAPENB
	TRNE 1,SC%WHL+SC%OPR	;PRIVILEGED?
	JRST TL31		;YES, SKIP CHECK
	EXCH T2,TLSAV1		;GET REMOTE LINE NUMBER
	CALL TLTST2		;SEE IF OBJECT POINTS TO REMOTE
	JUMPL 1,[MOVEI T1,TLNKX1 ;IF NOT, ERROR
		EXCH T2,TLSAV1	;GET BACK REMOTE ADDRESS
		CALLRET ULKTTY]
	EXCH T2,TLSAV1		;GET BACK ADDRESS OF REMOTE
TL31:	PUSH P,FX
	MOVEI FX,777
	CALL TLTST1		;FIND FREE FIELD IN REMOTE
	POP P,FX
	JUMPL 1,[MOVEI T1,TLNKX3
		CALLRET ULKTTY]
	DPB FX,Q1		;DEPOSIT OBJ NUMBER IN FIELD
TL33:	CALL ULKTTY
	RETSKP
;TLINK4 - SET ACCEPT BIT

TLINK4:	MOVE T2,OBJADR
	MOVEI 1,TT%ALK		;IT IS BIT 26 IN TTFLGS
	TLNE Q2,(1B5)		;SET IT?
	IORM 1,TTFLGS(T2)	;YES
	TLNN Q2,(1B5)		;CLEAR IT?
	ANDCAM 1,TTFLGS(T2)	;YES
	RET

;SET OR CLEAR ACCEPT ADVICE

TLINK5:	MOVE T2,OBJADR
	MOVEI 1,TT%AAD		;YES, GET BIT
	TLNE Q2,(1B7)
	IORM 1,TTFLGS(T2)	;YES
	TLNN Q2,(1B7)		;CLEAR IT?
	ANDCAM 1,TTFLGS(T2)	;YES
	RET
;CHECK FOR EXISTENCE OF REMOTE TO OBJECT

;ACCEPTS:
;	T2/ ADDRESS OF REMOTE
;	FX/ OBJECT LINE NUMBER

;	CALL TLTST1

;RETURNS +1: ALWAYS,
;		T1/ NUMBER OF OBJECT
;			OR
;		   -1 IF REMOTE DOESN'T POINT TO OBJECT
;		Q1/ BYTE POINTER TO LINK WORD FOR REMOTE

;CLOBBERS NO AC'S

TLTST1:	MOVE Q1,[POINT 9,TTLINK(2),-1]
TLT1:	ILDB 1,Q1		;SCAN REMOTE
	CAMN 1,FX		;FOUND OBJECT?
	RET			;YES
	TLNE Q1,(7B2)		;NO, SCANNED ALL FIELDS?
	JRST TLT1		;NO
	SETO 1,			;YES, RETURN NEGATIVE VALUE
	RET

;TLTST2 - CHECK FOR EXISTENCE OF OBJECT TO REMOTE

;ACCEPTS:
;	T2/ REMOTE LINE NUMBER

;	CALL TLTST2

;RETURNS +1: ALWAYS,
;		T1/ NUMBER OF REMOTE
;			OR
;		    -1 IF OBJECT DOESN'T POINT TO REMOTE
;		Q1/ BYTE POINTER TO LINK WORD FOR OBJECT WHERE REMOTE WAS FOUND

;CLOBBERS NO AC'S

TLTST2:	MOVE 3,OBJADR		;GET ADDRESS OF OBJECT
	MOVE Q1,[POINT 9,TTLINK(3),-1] ;POINT TO LINK WORD IN OBJECT
TLT2:	ILDB 1,Q1		;SCAN OBJECT
	CAMN 1,2		;FOUND REMOTE?
	RET			;YES
	TLNE Q1,(7B2)		;NO, SCANNED ALL FIELDS?
	JRST TLT2		;NO
	SETO 1,			;YES, RETURN NEG VALUE
	RET

	ENDTV.			;END TRVAR
	SUBTTL MISCELLANEOUS GLOBAL ROUTINES

;NOTE: THE FOLLOWING ROUTINES WERE WRITTEN TO SOLVE A PARTICULAR PROBLEM;
;I. E., MODULES OTHER THAN TTYSRV WERE REFERENCING TELETYPE DATA. EACH
;OF THESE ROUTINES REPLACES CODE IN ONE OR MORE MODULES SO THAT THOSE
;MODULES NO LONGER REFERENCE TELETYPE DATA. ADDITIONS OF CALLS TO THESE
;ROUTINES MUST TAKE INTO ACCOUNT THE RULES ABOUT LOCKING/UNLOCKING DYNAMIC
;DATA.

;GTCJOB - GET JOB NUMBER FOR WHICH THIS IS THE CONTROLLING TERMINAL

;ACCEPTS: T2/ INTERNAL LINE NUMBER

;	CALL GTCJOB

;RETURNS +1: LINE IS NOT ACTIVE
;	 +2: LINE IS ACTIVE,
;		T3/ JOB NUMBER OF OWNING JOB

	RESCD

GTCJOB::SAVELN
	CALL STADYN		;POINT TO DYNAMIC DATA
	 RETBAD (TTYX01)	;LINE NOT FULLY ACTIVE
	LOAD T3,TCJOB,(T2)	;GET OWNING JOB
	RETSKP

;STCJOB - SET CONTROLLING JOB

;ACCEPTS:
;	T1/ JOB NUMBER
;	T2/ LINE NUMBER

;	CALL STCJOB

;RETURNS +1: ALWAYS

	SWAPCD
STCJOB::CALL LCKTTY
	CALLRET ULKTTY
	STOR T1,TCJOB,(T2)
	CALLRET ULKTTY
;GTTOPF - GET TOP FORK OF A SCTTY GROUP

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL GTTOPF

;RETURNS +1: LINE NOT ACTIVE
;	 +2: LINE IS ACTIVE,
;		T3/ FORK NUMBER OF TOP FORK (OR -1)
	RESCD

GTTOPF::SAVELN
	CALL STADYN		;POINT TO DYNAMIC DATA
	 RETBAD (TTYX01)	;LINE NOT FULLY ACTIVE
	LOAD T3,TTPFK,(T2)	;GET TOP FORK
	RETSKP

;STTOPF - SET TOP FORK OF A SCTTY GROUP

;ACCEPTS:
;	T1/ FORK NUMBER OR -1 TO STORE IN TTPFK
;	T2/ INTERNAL LINE NUMBER

;	CALL STTOPF

;RETURNS +1: ALWAYS

STTOPF::SAVELN
	CALL LCKTTY		;POINT TO DYNAMIC DATA
	 CALLRET ULKTTY		;NOT AN ACTIVE LINE
	STOR T1,TTPFK,(T2)	;STORE NEW FORK DATA
STTOPX:	CALLRET ULKTTY
	SWAPCD
;GTWFRK - GET NUMBER OF FORK IN INPUT WAIT ON THIS TERMINAL

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL GTWFRK

;RETURNS +1: ALWAYS,
;		T1/ NUMBER OF FORK OR -1 IF NONE

	RESCD

GTWFRK::SAVELN
	CALL STADYN
	 JRST GTWFR1
	LOAD T1,TWFRK,(T2)
	RET
GTWFR1:	MOVEI T1,-1
	RET

;TTCLFK - CLEAR WAITING FORK ON TERMINAL

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL TTCLFK

;RETURNS +1: ALWAYS

	SWAPCD

TTCLFK::NOSKED			;PREVENT RESCHEDULING
	CALL STADYN		;GET TTY'S DATA BASE
	 JRST TTCLF1		;NOT ACTIVE. IGNORE IT
	SETONE TWFRK,(T2)	;INDICATE NO WAITING FORK
TTCLF1:	OKSKED			;ALL DONE
	RET
;PTYTTY - CONVERT PTY NUMBER TO INTERNAL LINE NUMBER (TTY NUMBER)

;ACCEPTS:
;	T2/ PTY NUMBER

;	CALL PTYTTY

;RETURNS +1: ALWAYS
;		T2/ INTERNAL LINE NUMBER

;CLOBBERS NO ACS

	SWAPCD
PTYTTY::ADD T2,TT1LIN+TT.PTY	;ADD NUMBER OF FIRST PTY LINE TO GET LINE NO.
	RET

;TTYPTY - CONVERT INTERNAL LINE NUMBER TO PTY NUMBER

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;	CALL TTYPTY

;RETURNS +1:ALWAYS,
;		T1/ PTY NUMBER

;CLOBBERS NO ACS

	RESCD
TTYPTY::SUB T1,TT1LIN+TT.PTY		;SUBTRACT FIRST PTY LINE TO GET PTY NUMBER
	RET

;CHKPTY - SEE IF THIS LINE NUMBER IS A PTY

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;	CALL CHKPTY

;RETURNS +1: NOT A PTY
;	 +2: A PTY
;		T1/ PTY NUMBER

CHKPTY::ACVAR <W1>		;GET AN AC TO WORK WITH
	LOAD W1,TTSTY,(T1)	;GET LINE TYPE FOR THIS LINE
	CAIE W1,TT.PTY		;IS IT A PTY?
	RETBAD			;NO. FAILURE
	CALL TTYPTY		;CONVERT TO PTY NUMBER
	RETSKP			;RETURN SUCCESS
	SWAPCD

	ENDAV.			;END ACVAR
;CKPHYT - SEE IF THIS IS A PHYSICAL TERMINAL

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL CKPHYT

;RETURNS +1: A PTY
;	 +2: A PHYSICAL TERMINAL

;PRESERVES AC'S

	RESCD

CKPHYT::TDCALL S,<<PT,RSKP>>
	 RETSKP			;NOT A PTY
	RET			;A PTY

;CKPHYD - SAME AS ABOVE BUT FOR DYNAMIC PTR
; T2/ DYNAMIC PTR

CKPHYD:	TDCALL D,<<PT,RSKP>>
	 RETSKP			;NOT A PTY
	RET			;A PTY

;CLRINT - CLEAR INTERRUPT WORD FOR A GIVEN LINE

;ACCEPTS:
;	T1/ INTERRUPT BIT
;	T2/ LINE NUMBER

;	CALL CLRINT

;RETURNS +1: ALWAYS

CLRINT::CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 CALLRET ULKTTY		;NOT FULLY ACTIVE. IGNORE
	ANDCAM T1,TTPSI(T2)	;CLEAR INTERRUPT BIT
CLRIN1:	CALLRET ULKTTY		;ALLOW DEALLOCATION
;TTSINT - SET UP INTERRUPT WORD FOR TERMINAL

;ACCEPTS:
;	T1/ DESIRED CONTENTS OF TTPSI
;	T2/ INTERNAL LINE NUMBER
;	T3/ DESIRED CONTENTS OF TTDPSI

;RETURNS +1: ALWAYS
	SWAPCD

TTSINT::SAVELN
	CALL LCKTTY		;GET ADDRESS OF DYNAMIC DATA
	 CALLRET ULKTTY		;NOT FULLY ACTIVE
	MOVEM T1,TTPSI(T2)	;STORE INTERRUPT WORD
	MOVEM T3,TTDPSI(T2)	;STORE DEFERRED INTERRUPT WORD
	CALLRET ULKTTY		;ALLOW DEALLOCATION



;ROUTINE USED BY ATACH JSYS TO SEE IF AN ATTEMPTED ATACH IS LEGAL
;
;ACCEPTS:	T2/ TTY LINE NUMBER
;RETURNS:	+1  ILLEGAL ATACH
;		+2  OK TO ATACH

ATACTT::NOSKED			;INSURE INTEGRITY WHILE LOOKING AT TTY DATA
	CALL STADYN		;HAVE A FULL DATA BLOCK?
	IFNSK.			;NO
	   SKIPE T2		;BECOMING ACTIVE?
	   JRST ATACTL		;YES - LOSE
	   JRST ATACTW		;NO, SHORT BLOCK - WIN
	ENDIF.
	TMNN TTPRM,(T2)		;HAVE FULL BLOCK, IS IT PERMANENT?
	JRST ATACTL		;NO - LOSE
	TMNE TTBAC,(T2)		;YES, IS IT BECOMING ACTIVE?
	JRST ATACTL		;YES - LOSE
	LOAD T3,TCJOB,(T2)	;NO, GET ASSOCIATED JOB
	HRRES T3		;MAKE A FULL WORD
	SKIPL T3		;IS THERE CURRENTLY A JOB?
	JRST ATACTL		;YES - LOSE
ATACTW:	OKSKED			;DONE WITH DATA BASE
	RETSKP			;ATACH IS LEGAL

ATACTL:	OKSKED			;DONE WITH DATA BASE
	RET			;ATACH IS NOT LEGAL
;CKBJFN - SEE IF BKJFN HAS ALREADY BEEN DONE ON THIS LINE

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL CKBJFN

;RETURNS +1: BKJFN HAS NOT BEEN DONE
; 	 +2: BKJFN HAS ALREADY BEEN DONE

	SWAPCD
CKBJFN::SAVELN
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 RETBAD			;NOT ACTIVE. BKJFN HAS NOT BEEN DONE
	JN TTRFG,(T2),RSKP	;IF FLAG SET, BKJFN HAS BEEN DONE
	RETBAD			;OTHERWISE, HASN'T BEEN DONE

;TTCKAD - SEE IF LINE IS ACCEPTING ADVICE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCKAD

;RETURNS +1: NOT ACCEPTING ADVICE
;	 +2: ACCEPTING ADVICE

TTCKAD::JE TT%AAD,TTFLGS(T2),R	;IF NOT, NONSKIP
	RETSKP			;INDICATE ACCEPTING
;GTBPTY - GETAB ROUTINE TO GET PTY INFO

;RETURNS +1: ALWAYS
;	T1/ (NUMBER OF PTYS,,FIRST PTY NUMBER)

GTBPTY::HRLI T1,NTTPTY		;NUMBER OF PTYS
	HRR T1,TT1LIN+TT.PTY	;GET FIRST LINE NUMBER
	RET

;GTBTTF - GETAB ROUTINE FOR TTFORK TABLE

;ACCEPTS:
;	T2/ LINE NUMBER

;RETURNS +1: ALWAYS,
;	T1/ (CONTROLLING JOB,,WAITING FORK)
;		OR
;	    -1 IF LINE IS INACTIVE
;		OR
;	    (-2,,-1) IF JOB IS BEING CREATED ON THE LINE

GTBTTF::CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 JRST GTBTT1		;NOT ACTIVE.
	JN TTPRM,(T2),[	JE TTBAC,(T2),.+1 ;IF PERMANENT, AND BECOMING
			HRLOI T1,-2 ; ACTIVE, RETURN (-2,,-1)
			CALLRET ULKTTY] ;GO CLEAN UP

;LINE IS EITHER FULLY ACTIVE AND NOT PERMANENT, OR PERMANENT AND NOT BECOMING ACTIVE.
;GET OWNING JOB AND WAITING FORK AND RETURN THEM

	LOAD T1,TWFRK,(T2)	;GET WAITING FORK
	LOAD T3,TCJOB,(T2)	;GET OWNING JOB
	HRL T1,T3		;COMBINE THEM
	CALLRET ULKTTY

;LINE IS NOT FULLY ACTIVE.  RETURN -1 IF INACTIVE, (-2,,-1) IF
;BECOMING ACTIVE

GTBTT1:	SETOM T1		;NOT ACTIVE. INDICATE NO OWNER OR FORK
	SKIPGE T2		;IS JOB BEING CREATED ON THIS LINE?
	HRLI T1,-2		;YES. INDICATE THAT
	CALLRET ULKTTY		;ALLOW DEALLOCATION
;STPRM - SET THE PERMANENT BIT IN DYNAMIC DATA

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL STPRM

;RETURNS +1: ALWAYS

STPRM::	SETONE TTPRM,(T2)
	RET

;CLRPRM - CLEAR THE PERMANENT BIT

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL CLRPRM

;RETURNS +1: ALWAYS

CLRPRM::SETZRO TTPRM,(T2)
	RET

;CKINP - CHECK FOR INPUT BUFFER EMPTY

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL CKINP

;RETURNS +1: INPUT BUFFER IS EMPTY
;	 +2: INPUT BUFFER IS NOT EMPTY

	RESCD
CKINP::	CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 CALLRET ULKTTY		;NOT ACTIVE. INDICATE NO CHARACTERS
	SKIPE TTICT(T2)		;ACTIVE. ANY INPUT CHARACTERS?
	JRST [	CALL ULKTTY	;YES. ALLOW DEALLOCATION
		RETSKP]		;INDICATE NON-ZERO COUNT
	CALLRET ULKTTY		;ALLOW DEALLOCATION INDICATE ZERO COUNT
;TTCKSP - ROUTINE CALLED FROM SYSINE TO SEE IF THIS LINE NEEDS A SET SPEED
;DONE BEFORE JOB INITIALIZATION

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTCKSP

;RETURNS +1: ALWAYS

;THIS IS RELEVANT FOR REMOTE FRONT END LINES ONLY.  WHEN A JOB LOGS OFF OF A REMOTE
;LINE AND THE NEXT CARRIER-ON INTERRUPT COMES IN ON THIS LINE,
;BIT TTFSP IN TTFWED IS SET, INDICATING THAT THE SPEED MUST BE RESET
;TO THE DEFAULT. THIS ROUTINE LOOKS FOR THAT BIT
;THE (INPUT,,OUTPUT) SPEEDS ARE IN TTSPWD FOR THIS LINE

	SWAPCD
TTCKSP::JE <TTFEM,TTFSP>,(B),R	;IF NOT REMOTE, GO AWAY
				;OR IF DON'T NEED SPEED SETTING
	SETZRO TTFSP,(B)	;CLEAR SPEED SETTING REQUIRED
	TMNN TTAUT,(B)			;NON-AUTO LINE?
	SKIPG C,TTSPWD(B)	;HAVE A SPEED TO SET?
	RET			;NO. GIVE IT UP
	MOVEI A,.TTDES(B)	;A/ DEVICE DESIGNATOR FOR THIS LINE
	MOVEI B,.MOSPD		;B/ THE FUNCTION
	MTOPR			;GO SET THE SPEED
	RET			;AND DONE


;INIT SPEED WORDS
TTSPIN::MOVSI B,-NLINES		;ONLY DO THE REAL LINES
	SETOM TTSPWD(B)		;INITIALIZE THE LINE SPEEDS
	AOBJN B,.-1		;DO ALL LINES
	RET			;ALL DONE
;TTHNGU - HANG UP DATASET

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL TTHNGU

;RETURNS +1: ALWAYS

;CALLED BY THE LGOUT JSYS IF THE JOB ON THIS LINE WAS NOT LOGGED IN.

	SWAPCD
TTHNGU::CAMN 2,CTYLNO		;IS THIS THE CTY?
	RET			;YES. DON'T HANG IT UP
	PUSH P,T2		;SAVE LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 JRST TTHNG1		;NOT ACTIVE. CAN'T HAVE OUTPUT
	CALL TTDOBE		;WAIT TILL NO OUTPUT
	 JRST [	POP P,T2	;GET BACK LINE
		JRST TTHNGU]	;TRY AGAIN
TTHNG1:	CALL ULKTTY		;ALLOW DEALLOCATION
	POP P,T2		;RESTORE LINE NUMBER
	TDCALL S,<<FE,TTHU2>,<MC,MCHNGU>,<NT,NVTDTS>,<DZ,DZHU0>,<ML,MLCDE1>,<CH,NVTDTS>,<TV,TVTDTS>>
	RET
;TTABRT - ROUTINE TO ABORT JOB STARTUP

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTABRT

;RETURNS +1: ALWAYS

;THIS ROUTINE IS CALLED BY JOBSRT WHEN IT CANNOT START A JOB
;BECAUSE OF SOME FULL CONDITION.  IF THE LINE IS NOT A PERMANENT
;BLOCK, TTACTL SHOULD BE -1; THIS ROUTINE SETS IT TO 0.  IF THE LINE
;IS A PERMANENT BLOCK, TT%BAC SHOULD BE SET; THIS ROUTINE CLEARS IT
;THIS ALLOWS TTEMES TO SEND THE 'FULL' TO THE LINE

	RESCD
TTABRT::SAVELN
	SKIPG T3,TTACTL(T2)	;IS LINE ACTIVE?
	JRST [	SETZM TTACTL(T2) ;INDICATE NOT ACTIVE
		RET]
	SETZRO TTBAC,(T3)	;INDICATE NOT BECOMING ACTIVE
	RET
	SUBTTL BUFFER CONTROL

;ASSIGN AND SETUP TTY BUFFERS
; 3/ NUMBER OF BUFFERS TO GET
;  RETURNS +1 TRANSPARENT, EXCEPT
; 3/ BYTE POINTER FOR INPUT AND OUTPUT POINTER WORDS
;THIS ROUTINE ASSUMES THAT IT IS PROTECTED FROM RESCHEDULING

	RESCD

TTGTBF:	PUSH P,T1		;TRANSPARENT TO ALL AC'S EXCEPT 3
	PUSH P,T4
	PUSH P,T3		;SAVE COUNT
	SETZ T1,
TTGTB1:	CHNOFF DLSCHN
	SOSGE TTFREC		;REDUCE FREE BUFFER COUNT
	JRST TTGTB3		;NONE LEFT
	HRRZ T3,@TTFREB		;GET BUFFER FROM LIST
	EXCH T3,TTFREB
	CHNON DLSCHN
	HRRZ T4,T1
	JUMPE T1,[MOVSI T1,0(T3) ;FIRST BUFFER, REMEMBER ITS ADDRESS
		JRST .+2]
	HRRZM T3,0(T4)		;CONC NEW BUFFER ONTO LIST
	HRRI T1,0(T3)
	SOSLE 0(P)		;GOT REQUESTED NUMBER OF BUFFERS?
	JRST TTGTB1		;NO
	HLRZ T3,T1		;ADDRESS OF FIRST BUFFER IN LIST
	HRRZ T4,T1		;ADDRESS OF LAST BUFFER IN LIST
	HRRZM T3,0(T4)		;MAKE LAST POINT TO FIRST
	ADD T3,[XWD 441100,1]	;CONSTRUCT 9-BIT BYTE POINTER
	AOS -3(P)		;GIVE GOOD RETURN
TTGTB2:	ADJSP P,-1		;JUNK
	POP P,T4
	POP P,T1
	RET

TTGTB3:	BUG(TTYNTB)
	AOS TTFREC		;GIVE BACK FRUITLESS SOS
	CHNON DLSCHN		;RESTORE THE CHANNEL
	HRRZ T4,T1
	JUMPE T1,TTGTB2		;RETURN IF THERE WERE NONE
	HLRZ T3,T1		;COMPLETE THE ONES WE GOT
	HRRZM T3,0(T4)
	ADD T3,[441100,,1]
	CALL TTRLBF		;THEN GIVE THEM BACK
	JRST TTGTB2
;RELEASE LIST OF TTY BUFFERS
; 3/ BYTE POINTER ANYWHERE IN ANY BUFFER OF LIST
;  RETURNS +1, CLOBBERS 3
;	PRESERVES 1
;ASSUMES INTERRUPT PROTECTION AS ABOVE

TTRLBF:	MOVEI 3,0(3)
	JUMPE 3,R		;IN CASE NO BUFFERS
	PUSH P,1
	TDNN 3,WRPMSK		;NOW AT END OF BUFFER?
	SUBI 3,TTSIZ		;YES
	ANDCM 3,WRPMSK		;NORMALIZE POINTER TO FIRST WD OF BFR
	ADDI 3,1		;WHICH IS 1 AFTER THE 0 MOD TTSIZ
	PUSH P,3		;SAVE ADDRESS OF FIRST BUFFER
	PUSH P,[0]		;DON'T CHNOFF IF ALREADY OFF
	CONSO PI,1B<DLSCHN+^D28>
	SETOM 0(P)		;INDICATE ALREADY OFF
TTRLB1:	MOVEI 1,0(3)
	HRRZ 3,0(3)		;NEXT BUFFER IN LIST
	SKIPN 0(P)		;LEAVE CHANNEL ALONE
	CHNOFF DLSCHN
	EXCH 1,TTFREB		;PUT BUFFER ON FREE LIST
	MOVEM 1,@TTFREB
	AOS TTFREC
	SKIPN 0(P)		;NO CHANNEL ON IF ALREADY OFF
	CHNON DLSCHN
	CAME 3,-1(P)		;CIRCLED AROUND TO FIRST BUFFER?
	JRST TTRLB1		;NO
	ADJSP P,-2		;RESTORE STACK
	POP P,1
	RET

;TTRLOB - RELEASE OUTPUT BUFFERS
;ACCEPTS:
;	T1/ ADDRESS OF DYNAMIC DATA
;  RETURNS +1: ALWAYS

;CLOBBERS 3 BUT PRESERVES 1
;LINE MAY BE FULLY ACTIVE OR ACTIVE WITH A MESSAGE BLOCK
;ASSUMES INTERRUPT PROTECTION AS ABOVE

TTRLOB:	SKIPN 3,TTOOUT(2)	;OUTPUT BUFFERS TO RELEASE?
	RET			;NO
	SETZM TTOCT(T2)		;CLEAR COUNT OF BYTES
	SETZM TTOOUT(2)		;YES. CLEAR OUTPUT POINTER
	SETZM TTOIN(2)		;CLEAR INPUT POINTER
	CALL CHKBKO		;PERHAPS FORK WAITING FOR OBUF EMPTY
	CALLRET TTRLBF		;RELEASE THEM
	SUBTTL CHARACTER INFORMATION TABLE (CHITAB)

	RESCD

;CHARACTER INFORMATION TABLE
;B0 - PARITY BIT FOR CHARACTER
;B12-17 - CHARACTER WAKEUP CLASS
;B18-35 - DISPATCH ADDRESS (CONTROL CHARACTERS ONLY)

PCLASS:	POINT Q2,CHITAB(1),17	;POINTER TO CLASS BITS

AN==1				;ALPHANUMERIC CLASS BIT
PC==2				;PUNCTUATION CLASS BIT
CT==4				;CONTROL (NON-FORMATTING) CLASS BIT
FC==10				;FORMATTING CONTROL CLASS BIT

DEFINE CH(PAR,CLS,DSP)<
   IFNB <DSP>,<<PAR>B0+<CLS>B17+DSP>
   IFB <DSP>,<<PAR>B0+<CLS>B17+TCOUT>>

CHITAB::CH(0,CT)		; 0 NULL
	CH(1,CT)		; 1 ^A
	CH(1,CT)		; 2 ^B
	CH(0,CT)		; 3 ^C
	CH(1,CT)		; 4 ^D
	CH(0,CT)		; 5 ^E
	CH(0,CT)		; 6 ^F
	CH(1,CT,VTOBEL)		; 7 ^G

	CH(1,FC,VTOBSP)		; 10 ^H BACKSPACE
	CH(0,PC,VTOTAB)		; 11 ^I TAB
	CH(0,FC,VTOLFD)		; 12 ^J LF
	CH(1,CT)		; 13 ^K
	CH(0,FC,VTOFFD)		; 14 ^L FORMFEED
	CH(1,FC,VTOCRT)		; 15 ^M CR
	CH(1,CT)		; 16 ^N
	CH(0,CT)		; 17 ^O

	CH(1,CT)		; 20 ^P
	CH(0,CT)		; 21 ^Q
	CH(0,CT)		; 22 ^R
	CH(1,CT)		; 23 ^S
	CH(0,CT)		; 24 ^T
	CH(1,CT)		; 25 ^U
	CH(1,CT)		; 26 ^V
	CH(0,CT)		; 27 ^W

	CH(0,CT)		; 30 ^X
	CH(1,CT)		; 31 ^Y
	CH(1,CT)		; 32 ^Z
	CH(0,CT,VTOESC)		; 33 ^[ ESC
	CH(1,CT)		; 34 ^\
	CH(0,CT)		; 35 ^]
	CH(0,CT)		; 36 ^^
	CH(1,CT)		; 37 ^_
	CH(1,PC)		; 40 SPACE
	CH(0,PC)		; 41 !
	CH(0,PC)		; 42 "
	CH(1,PC)		; 43 #
	CH(0,PC)		; 44 $
	CH(1,PC)		; 45 %
	CH(1,PC)		; 46 &
	CH(0,PC)		; 47 '

	CH(0,PC)		; 50 (
	CH(1,PC)		; 51 )
	CH(1,PC)		; 52 *
	CH(0,PC)		; 53 +
	CH(1,PC)		; 54 ,
	CH(0,PC)		; 55 -
	CH(0,PC)		; 56 .
	CH(1,PC)		; 57 /

	CH(0,AN)		; 60 0
	CH(1,AN)		; 61 1
	CH(1,AN)		; 62 2
	CH(0,AN)		; 63 3
	CH(1,AN)		; 64 4
	CH(0,AN)		; 65 5
	CH(0,AN)		; 66 6
	CH(1,AN)		; 67 7

	CH(1,AN)		; 70 8
	CH(0,AN)		; 71 9
	CH(0,PC)		; 72 :
	CH(1,PC)		; 73 ;
	CH(0,PC)		; 74 <
	CH(1,PC)		; 75 =
	CH(1,PC)		; 76 >
	CH(0,PC)		; 77 ?

	CH(1,PC)		; 100 @
	CH(0,AN)		; 101 A
	CH(0,AN)		; 102 B
	CH(1,AN)		; 103 C
	CH(0,AN)		; 104 D
	CH(1,AN)		; 105 E
	CH(1,AN)		; 106 F
	CH(0,AN)		; 107 G

	CH(0,AN)		; 110 H
	CH(1,AN)		; 111 I
	CH(1,AN)		; 112 J
	CH(0,AN)		; 113 K
	CH(1,AN)		; 114 L
	CH(0,AN)		; 115 M
	CH(0,AN)		; 116 N
	CH(1,AN)		; 117 O
	CH(0,AN)		; 120 P
	CH(1,AN)		; 121 Q
	CH(1,AN)		; 122 R
	CH(0,AN)		; 123 S
	CH(1,AN)		; 124 T
	CH(0,AN)		; 125 U
	CH(0,AN)		; 126 V
	CH(1,AN)		; 127 W

	CH(1,AN)		; 130 X
	CH(0,AN)		; 131 Y
	CH(0,AN)		; 132 Z
	CH(1,PC)		; 133 [
	CH(0,PC)		; 134 \
	CH(1,PC)		; 135 ]
	CH(1,PC)		; 136 ^
	CH(0,PC)		; 137 _

	CH(0,PC)		; 140 `
	CH(1,AN)		; 141 a
	CH(1,AN)		; 142 b
	CH(0,AN)		; 143 c
	CH(1,AN)		; 144 d
	CH(0,AN)		; 145 e
	CH(0,AN)		; 146 f
	CH(1,AN)		; 147 g

	CH(1,AN)		; 150 h
	CH(0,AN)		; 151 i
	CH(0,AN)		; 152 j
	CH(1,AN)		; 153 k
	CH(0,AN)		; 154 l
	CH(1,AN)		; 155 m
	CH(1,AN)		; 156 n
	CH(0,AN)		; 157 o

	CH(1,AN)		; 160 p
	CH(0,AN)		; 161 q
	CH(0,AN)		; 162 r
	CH(1,AN)		; 163 s
	CH(0,AN)		; 164 t
	CH(1,AN)		; 165 u
	CH(1,AN)		; 166 v
	CH(0,AN)		; 167 w

	CH(0,AN)		; 170 x
	CH(1,AN)		; 171 y
	CH(1,AN)		; 172 z
	CH(0,PC)		; 173 {
	CH(1,PC)		; 174 |
	CH(0,PC)		; 175 }
	CH(0,PC)		; 176 ~
	CH(1,17)		; 177 RUBOUT
	SUBTTL VTSOP JSYS

; Do display dependent operation
; Call:  1/ terminal designator	
;	 2/ Flags,,.VT code
; 	 3/ Optional argument (function dependent)
;	 4/ Optional argument (function dependent)
;	VTSOP
; Returns
;	+1	always
; Errors
;	VTSX01	Invaild function code
;	VTSX02	Terminal cannot perform function
;	VTSX03	Required argument not supplied
;	TTYX01	Line is not active
; 	and some other errors (see SOUT, ie)

.VTSOP::MCENT
	CAIN 1,.NULIO		;NUL DESIGNATOR?
	JRST MRETN		;YES, ALLOW IT
	CALL CHKTTY
	 EMRETN ()		;NOT A TTY, GIVE ERROR RETURN
	CALL LCKTTY		;POINT TO DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY	;NOT ACTIVE. ALLOW DEALLOCATION
		ITERR (TTYX01)]
	MOVE T3,TTLINK(T2)	; PROCESS LINKS, IF ANY
	CAME T3,[-1]
	 CALL VTSOP1		; DO LINKS
	CALL VTSOP5		; DO ORIGINAL LINE
	CALL ULKTTY
	JRST MRETN

VTSOP1:	PUSH P,T2		; SAVE ORIGINAL LINE
;;;	SETOM LINKF		;3004
VTSOP0:	SETZ T2,		; GET NEXT FIELD OF LINK WORD
	LSHC T2,^D9
	CAIN T2,777		; ANYTHING?
	 JRST VTSOP4		; NO
	CALL LCKTTY		; YES, GO DO IT
	 JRST [	CALL ULKTTY
		JRST VTSOP4 ]
	PUSH P,T3
	SETONE TTLNC,(T2)	;3004 DOING LINKED OPERATION
	CALL VTSOP5		; DO THE LINE
	SETZRO TTLNC,(T2)	;3004 FINISHED LINKED OPERATION
	CALL ULKTTY
	POP P,T3
VTSOP4:	JUMPN T3,VTSOP0
	POP P,T2		; RESTORE ORIGINAL LINE
;;;	SETZM LINKF		;3004
	RET

VTSOP5:	JE TTCRS,(T2),VTSOP6	; PENDING CR ON LINE?
	SETZRO TTCRS,(T2)	; YES, CLEAR IT
	CALL VTOCR1		; AND DO IT
VTSOP6:	UMOVE T1,T2		; GET FLAGS AND FUNCTION CODE
	HRRZ CX,T1		; GET FUNCTION CODE
	CAILE CX,VTSMAX
	 ITERR (VTSX01,<CALL ULKTTY>) ; CODE OUT OF RANGE
	TXNN T1,DP%AG1		; FIRST ARG SPECIFIED?
	 SKIPA T3,[1]		; NO, SET TO 1 FOR CONVENIENCE
	 UMOVE T3,T3		; GET ARGS
	UMOVE T4,T4
	CALLRET @VTSTAB(CX)	; DISPATCH TO HANDLER
	SUBTTL TCO (FIRST LEVEL OUTPUT)

;OUTPUT CHARACTER TO TERMINAL
; TCO - FIRST LEVEL, TRANSLATE ACCORDING TO PROGRAM DESIRES
; TOCY- SECOND LEVEL, DO LINKS AND FORMAT FOR PARTICULAR DEVICE
; TCOUT-THIRD LEVEL, DO BUFFERING ETC.

;TCO - FIRST LEVEL OUTPUT

;ACCEPTS:
;	T1/ CHARACTER (UP TO 9 BITS)
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS

;CALLED BY BOUT CODE FOR A SINGLE CHARACTER

TCO::	LOAD T3,TT%DAM,TTFLGS(T2) ;GET TERMINAL DATA MODE
	JUMPE T3,TCOB		;GO DO BINARY MODE
	ANDI T1,177		;T1/ CHARACTER IN 7 BITS
	MOVE T4,TTFLG1(T2)	;GET TERMINAL MODE FLAGS
	TXNN T4,TT%CFU!TT%VTA!TT%VTF	;ANYTHING SPECIAL?
	 JRST TCO1		;NO, HANDLE NORMALLY
	TXNE T4,TT%CFU		;CONFUSED?
	 CALL UNCONF		;FIX IT
	TXNE T4,TT%VTA		;ARGUMENT TO VTS FUNCTION
	 JRST TCOARG		;GO GET IT
	TXNE T4,TT%VTF		;VTS FUNCTION CODE?
	 JRST TCOVTA		;YES, DISPATCH TO FUNCTION

; HERE IF NOT IN THE MIDDLE OF ^P CODE SEQUENCE
TCO1:	CAIE T1,VTCESC		;VTS ESCAPE CHARACTER
	 JRST TCO2		;NO, SKIP THIS
	MOVE T4,TTTMOD(T2)	;ARE WE PROCESSING ^P CODES?
	TXNN T4,TM%DPY
	JRST TCO2		;NOPE, TREAT NORMALLY
	CALL TTLNK3		;YES, SEND IT ON TO LINKED TERMINALS
	JE TTCRS,(T2),TCO11	;PENDING CR ON LINE?
	SETZRO TTCRS,(T2)	;YES, CLEAR IT
	CALL VTOCR1		;AND DO IT
TCO11:	SETONE TTVTF,(T2)	;FLAG NEXT CHAR AS VTS FUNCTION CODE
	RET			;POP OFF VTS ESCAPE AND EXIT

;HERE TO HANDLE NORMAL CHARACTERS
TCO2:	CAIN T3,.TTATE		;TRANSLATE ECHO ONLY?
	JRST TC1A		;YES, NO OUTPUT TRANSLATION
	JRST TC1AT		;NO. SOME OUTPUT TRANSLATION REQUIRED
;TCOE - ECHO OUTPUT

;ACCEPTS:
;	T1/ CHARACTER
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS

;THIS IS A SPECIAL ENTRY POINT USED BY TTCH7 (IN SCHEDULER CONTEXT)
;FOR IMMEDIATE ECHOING AND BY TCI FOR DEFERRED ECHOING.
;IF TCOUT IS UNABLE TO OUTPUT THE CHARACTER AND IS BEING CALLED
;FROM THE SCHEDULER, IT WILL SET TCOERR TO -1.
;THE SCHEDULER MUST CLEAR THIS WORD BEFORE CALLING AND CHECK IT UPON RETURN
;IF IN PROCESS CONTEXT AND UNABLE TO OUTPUT, IT WAITS UNTIL IT CAN DO
;THE OUTPUT

;NOTE: APPARENTLY THIS CODE IS NEVER CALLED IF TERMINAL DATA MODE IS BINARY

TCOE:	TMNN TTNXO,(T2)		;DOING PAGE STOP?
	 IFSKP. <SETZRO TLNCT,(T2)> ;YES. CLEAR LINE POSITION WITHIN PAGE
	ANDI T1,177		;T1/ CHARACTER IN 7 BITS
	CAIN T1,.CHDEL		;RUBOUT?
	JRST TC1C		;YES, DON'T ECHO
	MOVE T3,TTFLGS(T2)	;CHECK WHETHER WE SHOULD ECHO
	TXNE T3,TT%ECO		;ECHOING OFF...
	TXNE T3,TT%DUM		; OR NOT FULL DUPLEX?
	JRST TC1C		;YES, DON'T ECHO
	LOAD T3,TT%DAM,TTFLGS(T2) ;GET TERMINAL DATA MODE
	CAIE T3,.TTASC		;TRANSLATE OUTPUT AND ECHO?
	CAIN T3,.TTATE		;NO. TRANSLATE ECHO ONLY?
	JRST TC1AT		;YES. ECHO TRANSLATION REQUIRED
;TCO...
; ASCII OUTPUT MODE, BUT NO CONTROL CHAR TRANSLATION DESIRED

; NOW HERE'S A CUTE LITTLE CROCK...
; THIS MODE IS USED BY PA1050. THINGS GOING THROUGH HERE 
; WON'T GET CHANGED TO VTS OUTPUT SEQUENCES. BUT IF THEY
; WERE CONVERTED, ONE COULDN'T SEND RANDOM ^CHARS FROM -10
; PROGRAMS, WHICH BREAKS EVERYBODY'S (?) FORTRAN PLOTTER DRIVERS
; AND APL TEXT FORMATTERS.  SO... GUESS. IF THE TERMINAL IS USING 
; ITP, ASSUME IT MUST HAVE OUTPUT TRANSLATION TO WORK RIGHT, AND
; DO VTS OUTPUT TRANSLATION. IF NOT, DON'T. IF YOU HAVE A BETTER 
; IDEA, SPEAK UP...)

TC1A:	CALL TTLNK3		;DO LINKS
	MOVE T4,TTTMOD(T2)	;GET TERMINAL MODE WORD
	TXNE T4,TM%ITP		;RUNNING ITP
	JRST TC1B		;YES, CALL LEVEL 2 FOR VTS ACTION
	CALL TTCOHA		;NO, TRY TO ACCOUNT FOR CHAR'S FORMAT ACTION
	CALLRET TCOUT		;GO DO CHAR WITH PARITY

;CONTROL CHARACTER TRANSLATION IS REQUIRED (OUTPUT OR ECHOING).
;IF THIS IS A CONTROL CHARACTER, DO THE TRANSLATION. OTHERWISE,
;CALL LEVEL 2

TC1AT:	CALL TTLNK3		;SEND THE CHARACTER TO LINKED LINES
	CAIL T1,40		;CONTROL GROUP?
	JRST TC1B		;NO. GO CALL LEVEL 2 CODE
	;..
;TCO..

;TRANSLATE CONTROL CHARS ACCORDING TO CC OUTPUT CONTROL MODES IN FCMOD1/FCMOD2
; 00 - SEND NOTHING
; 01 - INDICATE, E.G. ^A
; 1X - DO FUNCTION (SECOND LEVEL HANDLES SIMULATION IF NECESSARY)
;	10 - SEND ACTUAL CODE
;	11 - SIMULATE FORMAT ACTION

	;..
	MOVE T4,FCMOD2(T2)
	MOVE T3,FCMOD1(T2)	;GET MODE BITS
	ROTC T3,0(T1)
	ROTC T3,0(T1)

;DETERMINE ACTION ACCORDING TO CONTROL CHARACTER OUTPUT CONTROL BITS

	TLNE T3,(1B0)		;DO?
	JRST TC1B		;YES. CALL LEVEL 2 TO SEND CODE
				; OR SIMULATE FORMAT ACTION
	TLNN T3,(1B1)		;FLUSH?
	JRST TC1C		;YES. DON'T SEND ANYTHING

;INDICATE CONTROL CHARACTER BY ^

TC1D:	ADDI T1,100		;CONVERT TO PRINTING EQUIV.
	PUSH P,T1
	MOVEI T1,TTCIND		;GET ^
	CALL TCOY		;PRINT INDICATOR
	POP P,T1		;GET BACK THE CHARACTER
	CALL TCOY		;OUTPUT THE CHARACTER
	JRST TC1C		;GO RETURN

;CALL LEVEL 2 TO OUTPUT THE CHARACTER. IF NECESSARY, IT WILL
;DO CONTROL CHARACTER SIMULATION

TC1B:	CALL TCOY		;CALL LEVEL 2
TC1C:	RET

;TCOB - ENTRY FOR BINARY OUTPUT. NO TRANSLATION


;ACCEPTS:
;	T1/ CHARACTER (UP TO 9 BITS)
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TCOB

;RETURNS +1: ALWAYS

TCOB::	SETONE TTCFU,(T2)	;LOSE CURSOR
	CALL TTLNK3		;17 HANDLE LINKS
	ANDI T1,377		;7 BITS OF CHARACTER + PARITY
	CALLRET TCOU1		;GO OUTPUT THE CHARACTER WITHOUT ADDING PARITY
; HANDLER FOR VTS FUNCTION CODE BYTE FROM TCO LEVEL AFTER VTCESC SEEN
;	JRST TCOVTA FROM ASCII TCO LEVEL WITH:
;		T1/ FUNCTION CODE BYTE
;		T2/ ADDRESS OF DYNAMIC DATA
;
; CODES WHICH ARE OUT OF RANGE CAUSE AN ILLEGAL FUNCTION I/O INTERRUPT

TCOVTA:	SETZRO TTVTF,(T2)	; NO LONGER EXPECTING FUNCTION CODE BYTE
	TRZ T1,40		; UPPERCASE BYTE
	CAIL T1,"A"		; CHECK RANGE
	 CAILE T1,"Z"
	  JRST TCOVTX		; OUT OF RANGE
	TRZ T1,100		; IN RANGE, ZERO BIAS IT
	CALL TTLNK3		; SEND VTS CODE TO LINKED TERMINALS
	CAIL T1,1		; RANGE-CHECK THIS FOR SAFETY'S SAKE
	 CAILE T1,"Z"-"A"+1	; IF OUT OF RANGE
	 JRST [	BUG(TTCVOR,<<T1,FUNC>>)	; COMPLAIN
		RET ]		;  AND SKIP IT
	SKIPN T4,VTPTAB-1(T1)	; GET TABLE ENTRY
	 JRST TCOVTX		; IF NOT DEFINED THEN ERROR
	TLNE T4,-1		; TAKES ARGS?
	 JRST TCOVTG		; YES
	SETZ T1,		; NO ARGS
	MOVEI T3,1		; DEFAULT COUNT
	CALLRET @T4		; DISPATCH TO ROUTINE

TCOVTX:	ITERR(VTSX01,<CALL ULKTTY>) ;VTS INVALID FUNCTION PSI

;GET ARGUMENT TO ^P CODE
;EXPECTS:	T1/ VTS FUNCTION BYTE
;		T2/ ADDRESS OF DYNAMIC AREA

TCOVTG:	STOR T1,TTCVT,(T2)	;SAVE CONTEXT FOR TCOARG
	SETONE TTVTA,(T2)	;FLAG WAITING FOR VTS ARGUMENT
	RET			;AND EXIT OUT OF TCO

;^P CODE ARG RECEIVED, DISPATCH TO CORRECT HANDLER
; EXPECTS:	T1/ DATA BYTE
;		T2/ ADDRESS OF DYNAMIC AREA

TCOARG:	SETZRO TTVTA,(T2)	; NO LONGER EXPECTING ARGUMENT
	CALL TTLNK3		; SEND ARGUMENT TO LINKED TERMINALS
	MOVEI T3,-10(T1)	; GET ARGUMENT IN THE RIGHT AC
	LOAD T1,TTCVT,(T2)	; GET BACK FUNCTION CODE CONTEXT
	TXO T1,DP%AG1		; SAY FUNCTION HAS ONE ARGUMENT
	HRR T1,VTPTAB-1(T1)
	CALLRET (T1)		; DISPATCH
	SUBTTL VTS FUNCTION HANDLERS

;EXECUTE FUNCTION REQUESTED BY VTSOP CALL OR ^P CODE
; IF THE TERMINAL CANNOT DO THE FUNCTION REQUESTED, 
;   CAUSE AN VTSX02 ERROR PSI
; REGISTERS FOR FOLLOWING ROUTINES:
;	T1/ FLAGS IN LH
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ ARGUMENT FOR FUNCTION (WILL CONTAIN 1 EVEN IF NO ARGS SET UP)
;	T4/ ARGUMENT FOR FUNCTION


;ADVANCE TO A NEW LINE IF NOT ALREADY ON ONE (ADV)
VTOADV:	PUSH P,P1		; GET A REGISTER
	MOVEI P1,-1(T3)		; SAVE ARG IN IT
	LOAD T1,TLHPS,(T2)	; GET HORIZONTAL POSITION
	JUMPE T1,VTOAD2		; IF ZERO START AT CURRENT LINE
VTOAD1:	CALL VTONL		; DO A NEWLINE
VTOAD2:	SOJGE P1,VTOAD1		; LOOP
	POP P,P1
	RET

;CURSOR FORWARD (FWD)
VTOFWD:	MOVE T4,TTCHAR(T2)	; SEE IF CAN DO CURSOR MOTION
	TXNN T4,TC%MOV
	 JRST VTOX14		; NOPE, DATA ERROR THEN.
	CALLRET VTOHWW		; DO MOVEMENT WITH WRAPPING

;CURSOR BACK (BCK)
VTOBCK:	MOVE T1,TTCHAR(T2)	; SEE IF CAN DO BACKSPACING
	TXNN T1,TC%BS!TC%MOV
	 JRST VTOX14		; NO, NOT MUCH WE CAN DO THEN
	MOVNS T3		; SET UP ARGUMENT
	CALLRET VTOHWW		; AND DO MOVEMENT WITH WRAPPING

;CURSOR UP (UP)
VTOUP:	MOVE T1,TTCHAR(T2)	; CHECK IF TERMINAL CAN DO CURSOR MOTION
	TXNN T1,TC%MOV
	 JRST VTOX14		; NO, DATA ERROR PSI THEN
	MOVNS T3		; SET UP ARGUMENT
	CALLRET VTOVWW		; AND DO MOVEMENT WITH WRAPPING

;CURSOR DOWN (DWN)
VTODWN:	CALLRET	VTOVWW		; DO MOVEMENT WITH WRAPPING

;HOME UP (HOM) - IGNORES ARGUMENT IN T3
VTOHOM: MOVE T1,TTCHAR(T2)	; CHECK IF CAN HOME
	TXNN T1,TC%HOM!TC%MOV
	 JRST VTOX14		; NOPE
	SETZM TTLPOS(T2)	; CLEAR HORIZONTAL AND VERTICAL POSITIONS
	SETZRO TLNCT,(T2)	; ZERO LINE COUNTER
	SETZRO <TTCFU,TTNAB>,(T2) ; NO LONGER CONFUSED (WON'T ALWAYS WORK)
	CALLRET VTUPD

;HOME DOWN (HMD) - IGNORES ARGUMENTS
VTOHMD: MOVE T1,TTCHAR(T2)	; POSSIBLE?
	TXNN T1,TC%MOV
	 JRST VTOX14		; NOPE
	LOAD T3,TPLEN,(T2)	; GET PAGE LENGTH
	SOJ T3,			; FIRST LINE IS 0
	HRLZM T3,TTLPOS(T2)	; GO TO START OF LAST LINE
	SETZRO <TTCFU,TTNAB>,(T2) ; NO LONGER CONFUSED (WON'T ALWAYS WORK)
	CALLRET VTUPD		; MOVE CURSOR
;CLEAR SCREEN (CLR) - IGNORES ARGUMENT IN T3
VTOCLR:	MOVE T1,TTCHAR(T2)	; SEE IF TERMINAL CAN CLEAR THE SCREEN
	TXNN T1,TC%CLR!TC%SCL
	 JRST VTOX14		; NOPE
	SETZM TTLPOS(T2)	; CLEAR HPOS AND VPOS
	SETZM TTPPOS(T2)
	SETZRO TLNCT,(T2)	; ZERO LINE COUNTER
	SETZRO <TTCFU,TTNAB>,(T2) ; NO LONGER CONFUSED
	MOVEI T1,DPYCLS		; DO TTY-DEPENDANT STUFF
	CALLRET VTOFUN

;CLEAR TO END OF WINDOW (CEW) - IGNORES ARGUMENT IN T3
VTOCEW:	MOVEI T1,DPYCES		; DPY CODE
	JRST VTOCL0		; TEST TCW AND DO TRANSLATION

;CLEAR TO END OF LINE (CEL) - IGNORES ARGUMENT IN T3
VTOCEL:	MOVEI T1,DPYCEL		; DPY CODE
VTOCL0:	MOVE T4,TTCHAR(T2)	; CAN WE DO THIS?
	TXNN T4,TC%SCL
	 JRST VTOX14		; NO
	CALLRET VTOFUN		; DO TRANSLATION

;ERASE (NEXT) CHARACTER (ERA) - IGNORES ARGUMENT IN T3
; +++ will lose in last column
VTOERA:	MOVE T1,TTCHAR(T2)	; MUST BE ABLE TO DO BS AT LEAST
	TXNN T1,TC%PRT		; PRINTER?
	TXNN T1,TC%MOV!TC%BS	; OR CAN'T BACK UP?
	  JRST VTOX14		; YES, CAN'T DO IT
VTOER2:	TXNE T1,TC%OVR		; OVERWRITER?
	 JRST VTOER1		; YES
	AOS TTPPOS(T2)		; PHYSICAL POSITION ADVANCED
	MOVEI T1," "		; SPACE
	CALL TCOUT		; OUTPUT IT
	CALLRET VTUPD		; PUT THE CURSOR BACK WHERE IT WAS

; HERE FOR OVERWRITING TERMINALS, MUST USE TTY-DEPENDANT CODES
VTOER1:	MOVEI T1,DPYERC		;ERASE CHAR FUNCTION
	CALLRET VTOFUN		;GO DO IT

;+++ rewrite this
;BACKSPACE AND ERASE CHARACTER (BEC)
VTOBEC:	MOVE T1,TTCHAR(T2)	; MUST BE ABLE TO DO BS AT LEAST
	TXNN T1,TC%MOV!TC%BS
	 JRST VTOX14
	TXNN T1,TC%SCL		; IF CAN'T CLEAR SELECTIVLY
	 JRST VTOBE1		; THEN DO IT SLOW WAY
;+++ RANGE CHECK HERE...WE WILL LOSE IF WRAP HAPPENS
	CALL VTOBCK		; MOVE BACK THE REQUISITE AMOUNT
	MOVEI T1,DPYCEL		; SEND OFF A CLEOL
	CALLRET VTOFUN

; HERE IF CAN'T USE CLEOL
VTOBE1:	PUSH P,P1		; GET A REGISTER
VTOBE2:	MOVEI T3,1
	CALL VTOBCK		; MOVE BACK
	CALL VTOERA		; ERASE THE CHARACTER WITHOUT MOVING CURSOR
	SOJG P1,VTOBE2		; LOOP
	POP P,P1
    	RET
; THESE ENTRIES ARE FROM ^P CODES ONLY

; INSERT LINE
VTOINL:	JRST VTOLID		; JOIN FUNCTION

; DELETE LINE
VTODLL:	SETO T3,
	TXO T1,DP%AG1		; THERE IS AN ARG
	JRST VTOLID		; JOIN FUNCTION

; INSERT CHAR
VTOINC:	JRST VTOCID		; JOIN FUNCTION

;DELETE CHAR
VTODLC:	SETO T3,		; MOVE LEFT ONE CHAR
	TXO T1,DP%AG1
	JRST VTOCID		; JOIN FUNCTION

;LINE INSERT/DELETE
VTOLID:	TXNN T1,DP%AG1		; ARG PRESENT?
	 MOVEI T3,1		; NO, USE DEFAULT OF ONE LINE
	PUSH P,T1		; GRAB A TEMP
	LOAD T1,TPLEN,(T2)	; LENGTH OF SCREEN
	JUMPL T3,[ MOVN T1,T1	; DELETE CASE, RANGE CHECKING
		   CAMGE T3,T1	; WITHIN SCREEN SIZE?
		    MOVE T3,T1	; NO, SET TO LIMIT
		   JRST VTOLIA]	; DONE		   
	CAMLE T3,T1		; DON'T SCROLL MORE LINES THAN SCREEN HAS
	 MOVE T3,T1		; USE LIMITING VALUE
VTOLIA:	POP P,T1		; RESTORE TEMP
	TXNE T1,DP%AG2
	 JRST VTOLI0
	LOAD T4,TPLEN,(T2)	; DEFAULT:
	SOJ T4,			; CURRENT YPOS,,SCRLEN-1
	LOAD T1,TLVPS,(T2)
	HRLI T4,(T1)
VTOLI0:	MOVE T1,TTCHAR(T2)	; HAVE TO HAVE PROPER CAPABILITY
	TXNN T1,TC%LID
	 JRST VTOX14
	LOAD T1,TTTYP,(T2)	; GET TERMINAL TABLE
	LOAD T1,DPTB,(T1)
	SKIPE DPYMVL(T1)	; DOES IT ACTUALLY HAVE SCROLL REGION?
	 JRST VTOLI1		; YES, USE THAT
	SAVEP
	MOVE P5,T1
	DMOVE P3,T3		; PUT ARGS IN SAFE PLACE
	MOVE P2,TTLPOS(T2)	; SAVE CURSOR POSITION FOR LATER RESTORE
	SKIPG P3		; IS COUNT NEGATIVE?
	 MOVSS P4		; YES, SWAP ARGS
	HRRZI T1,(P4)		; DO THE DELETE 
	LOAD T3,TPLEN,(T2)	; IF AT BOTTOM, WE CAN SKIP IT
	SUBI T3,(T1)	
	CAIN T3,1
	 JRST VTOLI2
	SKIPL P3		; GET THE CURSOR RIGHT
	 SUBI T1,-1(P3)
	HRLZM T1,TTLPOS(T2)
	CALL VTUPD
	MOVE T1,DPYDLL(P5)
	MOVM T3,P3
	CALL VTSOUR
VTOLI2:	HLRZ T1,P4		; NOW DO THE INSERT
	LOAD T3,TPLEN,(T2)	; IF AT BOTTOM, WE CAN SKIP IT
	SUBI T3,(T1)	
	CAIN T3,1
	 JRST VTOLI3
	SKIPG P3
	 ADDI T1,1(P3)		; GET THE CURSOR RIGHT
	HRLZM T1,TTLPOS(T2)
	CALL VTUPD
	MOVE T1,DPYINL(P5)
	MOVM T3,P3
	CALL VTSOUR
VTOLI3:	MOVEM P2,TTLPOS(T2)	; RESTORE OLD CURSOR POSITION
	CALLRET VTUPD		; GO DO ALL THIS STUFF

; DO A REAL REGION SCROLL
VTOLI1:	MOVE T1,DPYMVL(T1)
	CALL VTSOUT
	CALLRET VTUPD

;CHARACTER INSERT/DELETE
VTOCID:	TXNN T1,DP%AG1		; ARG PRESENT?
	 MOVEI T3,1		; NO, DEFAULT TO 1 CHAR
	TXNE T1,DP%AG2		; SECOND ARG PRESENT,
	 JRST VTOCI0
	LOAD T4,TPWID,(T2)	; CURRENT YPOS,,SCRLEN-1
	SOJ T4,
	LOAD T1,TLHPS,(T2)
	HRLI T4,(T1)
VTOCI0:	MOVE T1,TTCHAR(T2)	; HAVE TO HAVE PROPER CAPABILITY
	TXNN T1,TC%CID
	 JRST VTOX14
	LOAD T1,TTTYP,(T2)	; GET TERMINAL TABLE
	LOAD T1,DPTB,(T1)
	SAVEP
	MOVE P5,T1
	DMOVE P3,T3		; PUT ARGS IN SAFE PLACE
	MOVE P2,TTLPOS(T2)	; SAVE CURSOR POSITION FOR LATER RESTORE
	SKIPG P3		; IS COUNT NEGATIVE?
	 MOVSS P4		; YES, SWAP ARGS
	HRRZI T1,(P4)		; DO THE DELETE 
	LOAD T3,TPWID,(T2)	; IF AT END, WE CAN SKIP IT
	SUBI T3,(T1)	
	CAIN T3,1
	 JRST VTOCI2
	HRRM T1,TTLPOS(T2)	; GET THE CURSOR RIGHT
	CALL VTUPD
	MOVE T1,DPYDLC(P5)
	MOVM T3,P3
	CALL VTSOUR
VTOCI2:	HLRZ T1,P4		; NOW DO THE INSERT
	LOAD T3,TPWID,(T2)	; IF AT END, WE CAN SKIP IT
	SUBI T3,(T1)	
	CAIN T3,1
	 JRST VTOCI3
	HRRM T1,TTLPOS(T2)	; GET THE CURSOR RIGHT
	CALL VTUPD
	MOVE T1,DPYINC(P5)
	MOVM T3,P3
	CALL VTSOUR
	MOVEM P2,TTLPOS(T2)	; RESTORE OLD CURSOR POSITION
VTOCI3:	CALLRET VTUPD

;FORCE UPDATE
VTONOP:	CALLRET VTUPD

; VISIBLE BELL (VBL) - IGNORES ARG
VTOVBL:	MOVE T1,TTCHAR(T2)	; CAN DO IT?
	TXNN T1,TC%VBL
	 JRST VTOX14
VTOVB0:	CALL VTUPD		; MAY AS WELL HAVE CURSOR IN RIGHT PLACE
	MOVEI T1,DPYVBL
	CALLRET VTOFUN
;HORIZONTAL POSITION (HRZ)
VTOHRZ:	TXNN T1,DP%AG1		; ARGUMENT PRESENT?
	 ITERR(VTSX03,<CALL ULKTTY>) ; NO, LOSE
	MOVE T1,TTCHAR(T2)	; MAKE SURE WE CAN DO IT
	TXNN T1,TC%MOV
	 JRST VTOX14
; TAB JOINS HERE
VTOHR0:	LOAD T1,TPWID,(T2)	; MAX HPOS
	JUMPE T1,VTOHR1		; ZERO WIDTH-DON'T CHECK
	CAIG T1,(T3)
	 SOS T3,T1		; TRUNCATE
VTOHR1:	STOR T3,TLHPS,(T2)	; STORE NEW POSITION
	CALLRET VTUPD
	
;VERTICAL POSITION (VRT)
VTOVRT:	TXNN T1,DP%AG1		; ARGUMENT PRESENT?
	 ITERR(VTSX03,<CALL ULKTTY>) ; NO
	MOVE T1,TTCHAR(T2)	; MAKE SURE WE CAN DO IT
	TXNN T1,TC%MOV
	 JRST VTOX14
	LOAD T1,TPLEN,(T2)	; MAX VPOS
	JUMPE T1,VTOVR1
	CAIG T1,(T3)
	 SOS T3,T1		; TRUNCATE
VTOVR1:	STOR T3,TLVPS,(T2)	; STORE NEW VALUE
	CALLRET VTUPD

;ABSOLUTE CURSOR POSITION (MOV)
VTOMOV:	TXNN T1,DP%AG1		; ARGUMENT PRESENT?
	 ITERR(VTSX03,<CALL ULKTTY>) ; NO
	MOVE T1,TTCHAR(T2)	;SEE IF CAN DO CURSOR MOTION
	TXNN T1,TC%MOV
	 JRST VTOX14		;NO, NOT MUCH WE CAN DO THEN
	HRRZI T4,(T3)		; HPOS IN T4
	HLRZS T3		; VPOS IN T3
	LOAD T1,TPLEN,(T2)	; DO RANGE CHECKING AND TRUNCATE IF NECESSARY
	JUMPE T1,VTOMV1		; 0 WIDTH INHIBITS CHECKING
	CAIG T1,(T3)
	 SOS T3,T1		; TRUNCATE
VTOMV1:	LOAD T1,TPWID,(T2)
	JUMPE T1,VTOMV0		; SAME FOR LENGTH
	CAIG T1,(T4)
	 SOS T4,T1
VTOMV0:	HRLI T4,(T3)		; ASSEMBLE POSITION
	MOVEM T4,TTLPOS(T2)	;SAVE NEW CURSOR POSITION
	SETZRO <TTCFU,TTNAB>,(T2) ; NO LONGER CONFUSED (WON'T ALWAYS WORK)
	CALLRET VTUPD
; CURSOR HORIZONTAL WITH WRAP
; EXPECTS:	T3/ + OR - COLUMNS TO CHANGE
; CLOBBERS T1,T3,T4
VTOHWW:	JUMPE T3,R		; HANDLE TRIVIAL CASE
	JUMPG T3,VTOHW0
VTOHW0:	LOAD T4,TLHPS,(T2)	; GET CURRENT HPOS
	ADDI T3,(T4)
	LOAD T4,TPWID,(T2)	; GET MAX HPOS
	JUMPE T4,VTOHW2		; WIDTH OF ZERO MEANS DON'T WRAP
	MOVEI T1,(T4)		; KEEP IT SAFE
	IDIVI T3,(T1)		; DIVIDE NEW HPOS BY IT
	JUMPGE T4,VTOHW1	; IF NEGATIVE REMAINDER
	SOJ T3,			; ADJUST VERTICAL CHANGE
	ADDI T4,(T1)		; AND MAKE HPOS POSITIVE
VTOHW1:	PUSH P,T4		
	CALL VTOVWW		; DO VERTICAL ADJUSTMENT
	POP P,T3
VTOHW2:	STOR T3,TLHPS,(T2)	; STORE NEW HPOS
	CALLRET VTUPD

; MOVE VERTICALLY WITH WRAP (NO MORE PROCESSING DONE)
; EXPECTS:	T3/ + OR - LINES TO CHANGE
; CLOBBERS:	T1,T3,T4
VTOVWW:	JUMPE T3,R		; HANDLE TRIVIAL CASE
	LOAD T4,TLNCT,(T2)	; ADJUST LINE COUNTER
	ADD T4,T3
	SKIPL T4		; DON'T STORE NEGATIVE LINE COUNTER
	 STOR T4,TLNCT,(T2)
	LOAD T4,TLVPS,(T2)	; GET CURRENT VPOS
	ADD T3,T4		; MAKE NEW ONE
	LOAD T4,TPLEN,(T2)	; GET MAX VPOS+1
	JUMPE T4,VTOVW1		; 0 MEANS NO WRAP
	MOVEI T1,(T4)		; KEEP IT SAFE
	IDIVI T3,(T1)		; GET REMAINDER
	SKIPGE T4		; MAKE IT POSITIVE
	 ADDI T4,(T1)
	MOVEI T3,(T4)
VTOVW1:	STOR T3,TLVPS,(T2)	; STORE NEW VERTICAL POSITION
	CALLRET VTUPD

;SEND THE ESCAPE CHARACTER (ESC)
VTOSEC:	PUSH P,P1		;SAVE A SAFE REGISTER
	MOVEI P1,(T3)		;ITERATION COUNT
VTOSE1:	MOVEI T1,VTCESC		;GET THE ESCAPE CHARACTER
	CALL TCOUT		;AND OUTPUT IT
	SOJG P1,VTOSE1		;ITERATE DESIRED NUMBER OF TIMES
	POP P,P1		;RESTORE SAVED REGISTER
	RET			;EXIT BACK TO VTO

;RESTORE CURSOR POSITION (RES) - IGNORES ARGUMENT IN T3
VTORES:	MOVX T1,DP%AG1		;FLAG SAYING ARGUMENT PRESENT
	MOVE T3,TTSCPS(T2)	;GET SAVED CURSOR POSITION
	CALLRET VTOMOV		;AND GO TO SAVED CURSOR POSITION

;SAVE CURSOR POSITION (SAV) - IGNORES ARGUMENT IN T3
VTOSAV:	MOVE T1,TTLPOS(T2)	;CURRENT CURSOR POSITION
	MOVEM T1,TTSCPS(T2)	;SAVE IT
	RET

; NOT CAPABLE OF OPERATION, LOSE
VTOX14:	SKIPN INSKED		; IN SCHEDULER?
;;;;	SKIPE LINKF		;3004 
	TMNE TTLNC,(T2)		;3004 OR LINKED TO SOME OTHER TURKEY?
	 RET			; YES, JUST FORGET IT
	ITERR(VTSX02,<CALL ULKTTY>) ; NO, GIVE A PSI

; SKIP IF RANDOM CURSOR MOTION POSSIBLE
CANMOV:	MOVE T3,TTCHAR(T2)
	TXNE T3,TC%MOV
	AOS 0(P)
	RET
	SUBTTL VTS TABLE TRANSLATION ROUTINES

;EXECUTE TTY-DEPENDANT DISPLAY FUNCTION
;  CALL WITH:	T1/ DESIRED DPY CODE
;		T2/ DYNAMIC DATA PTR
;
VTOFUN:	LOAD T3,TTTYP,(T2)	; GET TERMINAL TYPE
	LOAD T3,DPTB,(T3)	; GET TABLE
	ADDI T1,(T3)
	MOVE T1,(T1)		; GET ENTRY
	CALLRET VTSOUT

; OUTPUT PER-TERMINAL CODES WITH A REPEAT COUNT.
; EXPECTS:	T1/ DPY TABLE ENTRY
;		T2/ POINTER TO DYNAMIC DATA
;		T3/ COUNT
;		T4/ OPTIONAL ADDITIONAL ARGS
; PRESERVES:	T4
VTSOUR:	JUMPE T3,R		; HANDLE TRIVIAL CASE RIGHT AWAY
	SAVEQ
	TXNN T1,DPTBB		; IF A ROUTINE
	 TXNN T1,DPTBP		; IS IT PARAMETERIZED?
	 CAIA
	 JRST VTSOU1		; YES
	PUSH P,P1		; NO, LOOP ON IT.  BUM COUNT REGISTER
	PUSH P,T1		; SAVE CODE
	SKIPA P1,T3
VTSOUL:	 MOVE T1,(P)
	CALL VTSOU0
	SOJG P1,VTSOUL
	POP P,T1
	POP P,P1
	RET

; OUTPUT THE PER TERMINAL DISPLAY CODES FOR THE SPECIFIED FUNCTION
; EXPECTS:	T1/ DPY TABLE ENTRY
;		T2/ DYNAMIC DATA AREA
;		T3,T4/ ARGS
VTSOUT:	SAVEQ
VTSOU0:	TXNE T1,DPTBB		; IMMEDIATE STRING?
	 JRST VTSOUB		; YES
	TXNE T1,DPTBS		; PTR TO STRING?
	 JRST VTSOUS		; YES
	TXNN T1,DPTBR		; ROUTINE?
	 JRST [	BUG(VTSOUX,<<T1,D>>) ; NO, INVALID ENTRY
		RET ]		; EXIT GIVING ERROR
VTSOU1:	HRRZS T1
	DMOVE Q1,T3		; PUT ARGS IN QREGS
	CALLRET (T1)

; HERE FOR IMMEDIATE STRING
VTSOUB:	MOVE Q1,[POINT 7,Q2,0]
	MOVE Q2,T1		; COUNTER
VTSOB1:	ILDB T1,Q1
	JUMPE T1,VTSOB2		; ZERO TERMINATES
	CALL TCOUT
	HRRZI T3,Q1		; CHECK FOR END
	CAIE T3,Q2+1		
	 JRST VTSOB1
VTSOB2:	RET	

; HERE FOR LONGER STRING
VTSOUS:	MOVE Q1,T1		; MAKE BYTE PTR
	TLZ Q1,770077
	TLO Q1,440000
VTSOS1:	ILDB T1,Q1
	JUMPE T1,R		; ZERO TERMINATES
	CALL TCOU1		; MAY BE 8-BIT STRING
	JRST VTSOS1

; STRING POINTED TO BY T3
VTSSTR::TLC T3,-1		; FIX UP -1 POINTER
	TLCN T3,-1
	 HRLI T3,440700
	PUSH P,T3
VTSST1:	ILDB T1,(P)
	JUMPE T1,[ADJSP P,-1
		  RET]
	CALL TCOUT
	JRST VTSST1
	SUBTTL UTILITY ROUTINES FOR TERMINAL-DEPENDANT CODE

; SEND CHARACTER IN T3.

VTSCHR::MOVE T1,T3
	CALLRET	TCOUT

; SEND OFF CHARACTER IN T3 PREFACED BY ESCAPE
VTSESC::MOVEI T1,.CHESC
	PUSH P,T3
	CALL TCOUT
	POP P,T1
	CALLRET TCOUT

; SEND T3 AS DECIMAL NUMBER (0-99)
VTSDEC::IDIVI T3,^D10
	JUMPE T3,VTSDE1
	PUSH P,T4
	ADDI T3,"0"
	MOVEI T1,(T3)
	CALL TCOUT
	POP P,T4
VTSDE1:	ADDI T4,"0"
	MOVEI T1,(T4)
	CALLRET TCOUT

; INFORM OF NEW PHYSICAL CURSOR POSITION (IN T3)
VTSPOS::MOVEM T3,TTPPOS(T2)
	RET

; PAD (T3) MSEC
VTSPAD::TRZE T3,777400		; EIGHT BITS?
	 BUG(VTSTMP,<<T3,D>>)	; GACK, BIGGER THAN .25 SECONDS!
	CALL TNCPAD		; CONVERT TO CHARS
	PUSH P,P1		; GET A REGISTER
	MOVEI P1,(T3)
VTSPA1:	LOAD T1,TPDCH,(T2)	; GET PAD CHAR FOR THIS TTY
	CALL TCOUT
	SOJG P1,VTSPA1
	POP P,P1
	RET

; CONVERT TIME IN MSEC IN T3 TO CHARS
TNCPAD:	LOAD T1,TINTL,(T2)	; GET OUTPUT SPEED
	HRRZ T1,TTSPWD(T1)
	CAIN T1,-1		; IF UNKNOWN
	 MOVEI T1,^D9600	; ASSUME 9600
	IMULI T3,(T1)		; COMPUTE BYTES NEEDED
	ADDI T3,^D9999		; ROUND UP ALWAYS
	IDIVI T3,^D10000
	RET
	SUBTTL CURSOR UPDATING ROUTINE
;UPDATE TTY CURSOR TO MATCH CURRENT LOGICAL POSITION
;
; CALL:		VTUPD	IF NOT SURE IF CURSOR NEEDS UPDATING
;		VTUP0	IF SURE
; EXPECTS:	T2/ DYNAMIC DATA ADDRESS
;
; METHOD CODES
CU.REL==0			;USE RELATIVE POSITIONING
CU.ABS==1			;USE ABSOLUTE POSITIONING
;
; FLAGS USED IN F
CU%ABS==1B0			; ABSOLUTE POS POSSIBLE (NCHARS IN Q2)
 CU%HOM==1B1			; USE HOME
CU%REL==1B2			; RELATIVE POSITIONING POSSIBLE
 CU%CR==1B3			; USE CR
 CU%TAB==1B4			; USE TAB(S)
 CU%UP==1B5			; USE UP
 CU%DWN==1B6			; USE DOWN
 CU%FWD==1B7			; USE FORWARD
 CU%BCK==1B8			; USE BACK
 CU%HOR==CU%BCK!CU%FWD!CU%CR!CU%TAB ; ALL RELATIVE HORIZONTAL MODES
 CU%VRT==CU%UP!CU%DWN		; ALL RELATIVE VERTICAL MODES

VTUPD:	MOVE T1,TTPPOS(T2)	; GET PHYSICAL CURSOR POSITION
	CAME T1,TTLPOS(T2)	; SAME AS VIRTUAL POSITION?
	JRST VTUP0		; NOPE, GO UPDATE
	RET

VTUP0:	
	TRVAR <SAVP1,PHPOS,PVPOS,LHPOS,LVPOS,<OMETH,2>>
	MOVEM P1,SAVP1
	LOAD P1,TTTYP,(T2)	; GET TERMINAL TYPE
	LOAD P1,DPTB,(P1)	; GET POINTER TO DPY TABLE
	SETZB F,Q2		; CLEAR FLAGS
	LOAD T3,TPWID,(T2)
	MOVE T1,TTLPOS(T2)
	JUMPE T3,VTUP1		; JUMP IF NO WRAPAROUND
	CAIN T3,(T1)		; ADJUST FOR GHOST COLUMN
	SOJ T1,

; INITIALIZE LOCAL VARIABLES
VTUP1:	HRRZM T1,LHPOS		;LOGICAL HORIZ POSITION
	HLRZM T1,LVPOS		;LOGICAL PHYSICAL POSITION
	MOVE T1,TTPPOS(T2)	;GET PHYSICAL POSITIONS
	HRRZM T1,PHPOS		;PHYSICAL HORIZ POSITION
	HLRZM T1,PVPOS		;PHYSICAL VERTICAL POSITION
	SETZM CU.ABS+OMETH	;CLEAR CHAR COUNT FOR ABS POSITIONING
	SETZM CU.REL+OMETH	;CLEAR REL POS COUNT

; CHECK WHETHER THIS IS A REAL DISPLAY TERMINAL
; IF PRINTING OR GLASS TTY, GO HANDLE DIFFERENTLY

	MOVE T1,TTCHAR(T2)	; GET TERMINAL CHARACTERISITICS
	TXNN T1,TC%MOV		; CAN MOVE CURSOR?
	JRST VTUNMV		; NO, LOSER--GO HANDLE ELSEWHERE

; HERE IF TERMINAL IS A REAL DISPLAY
; EVALUATE RELATIVE CURSOR MOTION.  

	MOVE T3,LHPOS		; NEED HORIZONTAL MOTION
	CAMN T3,PHPOS		; YES
	JRST VTUERV		; NO, GO CHECK VERTICAL MOTION
	JUMPE T3,[SKIPN DPYCRT(P1) ;IF MOTION TO LEFT EDGE, TRY A <CR>
		  JRST .+1	; DON'T HAVE IT, CAN'T DO THIS
		  TXO F,CU%CR	; HAVE IT, CAN USE <CR>
		  MOVEI T3,1	; ONE CHAR
		  MOVEM T3,CU.REL+OMETH	;SAVE CHARACTER COUNT
		  JRST VTUERV]
	SUB T3,PHPOS		; NEW POSITION FORWARD OR BACK?
	JUMPG T3,VTUERF		; FORWARD
	SKIPN T1,DPYBCK(P1)	; BACK, CAN WE DO IT?
	JRST VTUABS		; NO, CAN'T DO RELATIVE CURSOR MOTION
	TXO F,CU%BCK		; YES, FLAG POSSIBLE
	MOVNS T3		; CONVERT TO POSITIVE REPEAT COUNT
	CALL VTUCNT		; COUNT THE NUMBER OF CHARACTERS 
	MOVEM T3,CU.REL+OMETH	; AND STORE 
	JRST VTUERV		; GO CHECK VERTICAL MOTION

; HERE TO EVALUATE RELATIVE FORWARD MOTION. (T3) IS COUNT 

VTUERF:	SKIPN T1,DPYFWD(P1)	; HAVE FORWARD MOTION?
	JRST VTUETB		; NO, MAYBE USE TABS?
	TXO F,CU%FWD		; YES, MARK AS POSSIBLE
	CALL VTUCNT		; COUNT THE NUMBER OF CHARACTERS 
	MOVEM T3,CU.REL+OMETH	; AND STORE

; HERE TO SEE IF TABS CAN BE USED

VTUETB:	CALL VTUTAB		; EVALUATE TABS
	JRST VTUNTB		; CAN'T USE THEM
	CAML T3,CU.REL+OMETH	; WINNING OVER JUST FORWARDS?
	JRST VTUERV		; NO, USE REGULAR FORWARD MOTION
	TXO F,CU%TAB		; YES, MARK SUCH
	MOVEM T3,CU.REL+OMETH	; SAVE CHARACTER COUNT FOR TABS
	JRST VTUERV		; GO CHECK VERTICAL MOTION

; TABS WON'T WORK	
VTUNTB:	SKIPN CU.REL+OMETH	; SEE IF REGULAR FORWARD WON
	JRST VTUABS		; NOPE, CAN'T USE RELATIVE MOTION
				; YEP, FALL THROUGH

; EVALUATE VERTICAL MOTION

VTUERV:	MOVE T3,LVPOS		; VERTICAL POSITION CHANGED?
	CAMN T3,PVPOS
	JRST VTUEV2		; NO VERTICAL MOVEMENT NEEDED
	SUB T3,PVPOS		; GET DIFFERENCE
	JUMPG T3,VTUERD		; DOWN
	SETZRO TTNAB,(T2)	; TIME TO NOT BE CONFUSED
	SKIPN T1,DPYUP(P1)	; UP
	JRST VTUABS		; CAN'T DO CURSOR UP, TRY ABSOLUTE CURPOS
	TXO F,CU%UP		; MARK POSSIBILITY
	MOVNS T3		; MAKE REPEAT COUNT
	JRST VTUEV1

; CURSOR DOWN (T3 HAS REPEAT COUNT)

VTUERD: SKIPN T1,DPYDWN(P1)	; HAVE CURSOR DOWN FUNCTION
	JRST VTUABS		; NO, TRY ABSOLUTE CURPOS
	TXO F,CU%DWN		; YES, MARK POSSIBLE
VTUEV1:	CALL VTUCNT		; COUNT THE NUMBER OF CHARACTERS IN P1 PER ITER
	ADDM T3,CU.REL+OMETH	; ADD TO TOTAL
VTUEV2:	TXO F,CU%REL		; SAY RELATIVE POSITIONING POSSIBLE
	MOVE T1,CU.REL+OMETH	; IF RELATIVE MOTION WILL TAKE 
	CAIG T1,3		;   3 OR LESS CHARS,
	JRST VTUDR		;   DO IT WITHOUT EVALUATING ABS

; HERE TO EVALUATE ABSOLUTE CURSOR POSITIONING

VTUABS:	JN TTNAB,(T2),VTUPCK	; DON'T USE ABSOLUTE IF NOT SURE OF CURSOR
	SKIPE TTLPOS(T2)	; HOME POSSIBLE?
	JRST VTUAB1		; NO
	SKIPN T1,DPYHOM(P1)	; HOME EXIST?
	JRST VTUAB1		; NO
	TXO F,CU%HOM		; YES, MARK IT
	JRST VTUAB2		; AND COMPUTE LENGTH

; NO HOME, USE ABSOLUTE POSITIONING

VTUAB1:	SKIPN T1,DPYABS(P1)	; HAVE ABS POS SEQUENCE?
	JRST VTUPCK		; NO ABSOLUTE POSITIONING
VTUAB2:	MOVEI T3,1		; ONLY ONCE, HOPEFULLY!
	CALL VTUCNT
	MOVEM T3,CU.ABS+OMETH	; NUMBER OF CHARS NEEDED FOR ABSOLUTE
	TXO F,CU%ABS		; MARK ABSOLUTE POSITIONING POSSIBLE

; DECIDE BETWEEN ABSOLUTE AND RELATIVE POSITIONING

VTUPCK:	TXNN F,CU%ABS		; ABSOLUTE POSSIBLE?
	JRST VTUPC1		; NO
	MOVE T1,CU.ABS+OMETH	; GET COUNT FOR ABS
	TXNE F,CU%REL		; RELATIVE POSSIBLE?
	CAMGE T1,CU.REL+OMETH	; YES, DOES IT DO LESS OUTPUT
	JRST VTUDAB		; NO OR NO, GO DO ABSOLUTE
	JRST VTUDR		; REL WINS, GO DO IT THAT WAY
	
; NO ABSOLUTE POSITIONING, VERIFY RELATIVE

VTUPC1:	TXNN F,CU%REL		; RELATIVE POSITIONING POSSIBLE?
	JRST VTUERR		; NO, WE'RE IN TROUBLE
				; YES, FALL THROUGH TO REL CODE

; HERE TO DO RELATIVE CURSOR POSITIONING

VTUDR:	TXNN F,CU%HOR		; ANY HORIZONTAL REQUIRED?
	JRST VTUDRV		; NOPE
	TXNE F,CU%CR		; YES--CR POSSIBLE?
	JRST [	MOVE T1,DPYCRT(P1) ; YES, SEND ONE
		CALL VTSOUT
		SETZM PHPOS
		SKIPE LHPOS	; THAT ALL?
		JRST VTUDRF	; NO, MOVE FORWARDS
		JRST VTUDRV ]	; YES, CONTINUE TO VERTICAL
	TXNN F,CU%BCK		; BACK?
	JRST VTUDRF		; NO, DO FORWARD
	MOVE T3,PHPOS		; YES, COMPUTE REPEAT COUNT
	SUB T3,LHPOS
	SKIPN T1,DPYBCK(P1)	; GET BACKWARD TABLE ENTRY
	JRST VTUERR		;  NOT THERE
	CALL VTSOUR		; MOVE BACKWARDS
	JRST VTUDRV		; GO CHECK VERTICAL

; DO FORWARD RELATIVE
VTUDRF:	TXNN F,CU%TAB		; TAB PICKED?
	JRST VTUDF1		; NO, DO STANDARD
	MOVE T3,LHPOS		; YES, COMPUTE HOW MANY
	MOVE T4,PHPOS
	LSHC T3,-3		; BUM!
	SUBI T3,(T4)
	MOVE T1,DPYTAB(P1)
	CALL VTSOUR
	MOVE T3,LHPOS		; GET POSITION BACK
	ANDI T3,7		; NUMBER OF FORWARD SPACES TO FINISH MOTION
	JRST VTUDF2		; AND GO DO REST OF MOTION

VTUDF1:	MOVE T3,LHPOS		; FIND NUMBER OF FORWARD SPACES TO DO
	SUB T3,PHPOS
VTUDF2:	SKIPN T1,DPYFWD(P1)	; GET FORWARD FUNCTION
	JRST VTUERR		; OOPS - NOT THERE
	CALL VTSOUR		; GO DO IT

; VERTICAL
VTUDRV:	TXNN F,CU%VRT		; ANY VERTICAL REQUIRED?
	JRST VTUDON		; NOPE
	TXNN F,CU%UP		; UP?
	JRST [	MOVE T3,LVPOS	; NO, DOWN THEN
		SUB T3,PVPOS	; GET COUNT
		SKIPN T1,DPYDWN(P1)	; GET FUNCTION
		JRST VTUERR	; FUNCTION NOT THERE
		JRST VTUDV1 ]	; GO DO IT
	MOVE T3,PVPOS		; GOING UP, COMPUTE COUNT
	SUB T3,LVPOS
	SKIPN T1,DPYUP(P1)	; TABLE ENTRY
	JRST VTUERR		;  NOT PRESENT
VTUDV1:	CALL VTSOUR		; EXECUTE VERTICAL MOTION
	JRST VTUDON		; AND EXIT

; DO ABSOLUTE

VTUDAB: MOVE T3,TTLPOS(T2)	; SET UP ARG
	TXNE F,CU%HOM		; HOME POSSIBLE?
	SKIPA T1,DPYHOM(P1)	; YES, GET HOME FUNCTION
	MOVE T1,DPYABS(P1)	; NO, GET MOVE FUNCTION
	CALL VTSOUT
	JRST VTUDON

; HERE TO DO PROCESSING FOR NON-DISPLAY TERMINALS
; ORDER MUST BE CR, VERTICAL, HORIZONTAL TO LOOK RIGHT

VTUNMV:	SKIPN T3,LHPOS		; GET DESIRED HORIZONTAL POSITION
	JRST VTUNCR		; IF TO LEFT MARGIN USE CR
	CAML T3,PHPOS		; COMPARE WITH CURRENT H POS
	JRST VTUNVR		; FORWARDS, DO LATER

; HERE TO MOVE BACKWARD - COMPUTE BEST WAY

	SKIPN DPYBCK(P1)	; HAVE BACKSPACE?
	JRST VTUNCR		; NO, HAVE TO DO CR AND SPACES
	MOVE T1,TTCHAR(T2)	; IS THIS A PRINTER?
	TXNN T1,TC%PRT
	JRST VTUNVR		; NO, SO HAVE TO USE BACKSPACES

	MOVE T1,PHPOS		; COST BY BSP IS PHPOS-LHPOS
	SUBI T1,(T3)		; COST BY CR-SPACES IS LHPOS+1
	AOJ T3,
	CAILE T3,(T1)
	JRST VTUNVR		; NO CR NOW, DO VERTICAL

; DO A CR

VTUNCR:	SKIPN PHPOS		; GET CURRENT POSITION
	JRST VTUNVR		; ALREADY AT LEFT MARGIN, DON'T DO THIS
	SKIPN T1,DPYCRT(P1)	; GET <CR> ENTRY IF PRESENT 
	JRST VTUERR		; OOPS - NO FUNCTION
	CALL VTSOUT		; MOVE TO LEFT MARGIN
	SETZM PHPOS		; REMEMBER THAT WE'VE GONE BACK

; VERTICAL MOTION ON STUPID TERMINALS

VTUNVR:	MOVE T3,LVPOS		; GET DESIRED VERTICAL
	SUB T3,PVPOS		; CALCULATE DIFFERENCE
	SKIPGE T3		; BETTER BE DOWN - MAKE SURE
	SETZ T3,		; IF NOT, JUST IGNORE
	SKIPN T1,DPYDWN(P1)	; GET NEEDED SEQUENCE
	JRST VTUERR		; NO SEQUENCE, LOSE
	CALL VTSOUR		; MOVE CURSOR

; HORIZONTAL MOTION OTHER THAN CR

	MOVE T3,LHPOS		; SEE WHICH DIRECTION
	CAMGE T3,PHPOS
	JRST VTUNBB		; BACKWARDS
	CALL VTUTAB		; FORWARDS, EVALUATE TABS
	JRST VTUNDF		; NO TABS
	MOVE T1,LHPOS		; COMPUTE COST OF FORWARDS
	SUB T1,PHPOS
	EXCH T1,T3
	CAILE T1,(T3)		; WHICH IS BETTER?
	JRST VTUND1		; FORWARDS
	MOVE T3,LHPOS		; TABS, COMPUTE HOW MANY
	MOVE T4,PHPOS
	LSHC T3,-3		; BUM!
	SUBI T3,(T4)
	MOVE T1,DPYTAB(P1)	; DO SOME TABS
	CALL VTSOUR
	LSHC T3,3		; BRING LOW-ORDER BITS OF LHPOS BACK
	TRZ T3,7
	JRST VTUND1		; AND DO REST OF MOTION

; HERE TO MOVE FORWARD

VTUNDF:	MOVE T3,LHPOS		; CALCULATE DISTANCE TO MOVE
	SUB T3,PHPOS
VTUND1: SKIPN T1,DPYFWD(P1)	; TRY TO DO CURSOR FORWARD
	MOVE T1,DPYSPC		; IF NO FWDS, USE A SPACE
	CALL VTSOUR		; DO IT
	JRST VTUDON		; FINISHED, CLEAN UP

; GO BACKWARDS WITH BACKSPACES (A CLEVER IDEA...)

VTUNBB:	MOVE T3,PHPOS		; GET CURRENT POS
	SUB T3,LHPOS		; GET NUMBER OF SPACES TO DO
	SKIPN T1,DPYBCK(P1)	; ROUTINE TO DO IT
	JRST VTUERR		; OOPS, NOT THERE
	CALL VTSOUR		; DO IT

; HERE WHEN IT'S ALL DONE

VTUDON:	MOVE T3,TTLPOS(T2)	; UPDATE STORED PHYSICAL POSITION
	MOVEM T3,TTPPOS(T2)
VTUDO1:	MOVE P1,SAVP1		; RESTORE KLUDGE
	RET

; HERE WHEN WE COULDN'T UPDATE THE CURSOR CORRECTLY
; REALLY THIS OUGHTN'T EVER HAPPEN...

VTUERR: BUG(VTSUPF)		; OOPS. (HOW TO SAY WHY THIS LOST?)
	MOVE T3,TTPPOS(T2)	; GET CURRENT PHYSICAL CURSOR POSITION
	MOVEM T3,TTLPOS(T2)	; SAY THATS WHERE IT IS (YECCH)
	JRST VTUDON1		; EXIT
; SUBROUTINE TO EVALUATE TABS
; CALLED ONLY FROM VTUPD - EXPECTS A LOT OF THINGS TO BE SET UP
;
; RETURNS:	+1 CAN'T USE THEM
;		+2 COUNT IN T3

VTUTAB:	SKIPN T1,DPYTAB(P1)	; GOT TABS?
	RET			; NO
	MOVE T3,LHPOS		; YES--SEE IF THEY'LL WIN
	TRZ T3,7		; LAST TABPOS BEFORE WHERE WE WANT TO BE
	MOVNI T4,(T3)		; KEEP COPY
	SUB T3,PHPOS		; IS IT AFTER WHERE WE ARE NOW?
	JUMPL T3,R		; NO
	TRZE T3,7		; YES, SEE HOW MANY WE NEED
	ADDI T3,10
	LSH T3,-3		; THIS IS NOW # OF TABS
	CALL VTUCNT
	EXCH T3,T4		; COUNT # OF FWDS NEEDED TO GET THERE
	ADD T3,LHPOS		; THIS IS IT
	JUMPE T3,VTUTB1		; IF ZERO, NO TRUBBLE
	SKIPN T1,DPYFWD(P1)
	RET			; AFTER ALL THAT...
	CALL VTUCNT
VTUTB1:	ADDI T3,(T4)		; GET TOTAL COUNT
	RETSKP			; RETURN GOODNESS
; WE LOST TRACK OF CURSOR.  ATTEMPT A RECOVERY
; PRESERVES T1
UNCONF:	PUSH P,T1
	SETZRO TTCFU,(T2)	; NO LONGER QUITE AS CONFUSED
	MOVE CX,TTCHAR(T2)	; CAN TERMINAL SCROLL?
	TXNN CX,TC%SCR
	 JRST UNCON1
	SETZRO TLVPS,(T2)	; SHOW ME THE WAY TO GO HOME...
	SETZRO TPVPS,(T2)
	SETZRO TLNCT,(T2)	; LINE COUNTER ZERO
	MOVE T1,TTCHAR(T2)	; EXCPET ON PRINTERS
	TXNE T1,TC%PRT
	 JRST UNCON9
	SETONE TTNAB,(T2)	; AVOID ABSOLUTE CURSOR MOTION
UNCON9:	POP P,T1
	RET

; HERE IF TERMINAL CAN'T SCROLL
UNCON1:	TXNN CX,TC%MOV		; CAN WE AT LEAST MOVE?
	 JRST UNCON9		; NO, NOTHING MUCH WE CAN DO THEN
	CALL VTOHMD		; YES, HOME DOWN
	CALL VTUPD
	JRST UNCON9
REPEAT 0,<
; HANDLE ANY DEFERRED CLEOLS
TTUCEL:	JE TTCLP,(T2),R		; IF NOTHING PENDING, RETURN
	MOVEI T1,DPYCEL		; OTHERWISE DO IT
	CALL VTUOUF
	SETZRO TTCLP,(T2)	; AND CLEAR FLAG
	RET
>

;CALCULATE THE CHARACTER COUNT
;EXPECTS:	T1/ DISPLAY TABLE ENTRY
;		T3/ NUMBER OF ITERATIONS
;RETURNS:	+1  T3/ COUNT OF CHARACTERS IN ENTRY
; PRESERVES:	T4
;THIS IS OBSCURE TO SAVE TIME.
VTUCNT:	PUSH P,T4
	MOVE T4,T3
	TXNN T1,DPTBB		; IMMEDIATE BYTES?
	 JRST VTUCN0		; NO
	TXNE T1,177B<3*7>	; YES.  AT LEAST 3 BYTES?
	 JRST [	MOVEI T3,3	; YES
		TXNN T1,177B<4*7> ; AT LEAST 4?
		 JRST VTUCN1	; NO.  IT'S 3
		MOVEI T3,4	; ASSUME 4 (MIGHT BE 5 BUT...)
		JRST VTUCN1 ]
	MOVEI T3,2		; LESS THAN 3.
	TXNN T1,177B<2*7>	; HOW ABOUT 2?
	  MOVEI T3,1		; IT'S 1
	JRST VTUCN1
VTUCN0:	LOAD T3,DPCNT,T1	; NOT IMMEDIATE.  GET SIZE.
	TXNN T1,DPTBP		; IS IT PARAMETERIZED?
VTUCN1:	 IMULI T3,(T4)		; NO, MULTIPLY
	POP P,T4
	RET
	SUBTTL TCOY (SECOND LEVEL OUTPUT)

;SECOND LEVEL - HANDLE DEVICE IDEOSYNCRACIES AND CHAR ACCOUNTING

;ACCEPTS:
;	T1/CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA

;IMECHF IS -1 IF THIS CHARACTER IS BEING OUTPUT FOR IMMEDIATE ECHOING
;WHEN TAKEN OUT OF TTBBUF BY TTCH7

;CALLED FROM TCO (FIRST LEVEL OUTPUT). BY NOW, IF THIS IS A CONTROL
;CHARACTER, THE CONTROL CHARACTER OUTPUT CONTROL SPECIFIED EITHER
;	10 - SEND ACTUAL CODE
;		OR
;	11 - SIMULATE FORMAT ACTION

;WE CAN ALSO GET HERE WHEN TT%DAM HAS .TTATO SET AND WE ARE DOING ECHO
;OR TT%DAM HAS .TTATE AND WE ARE DOING OUTPUT

TCOY:	SAVEQ
	CAIN 1,.CHDEL
	JRST [	CALL TCOUT	;RUBOUT, SEND DIRECTLY
		JRST TCOY3]
	SKIPE IMECHF		;IMMED ECHO CHAR?
	JRST [	MOVE T3,TTFLGS(T2) ;YES, CHECK DUPLEX BITS
		TXNN T3,TT%ECO	;IS ECHOING OFF?
		JRST TCOY3	;YES - THEN DON'T ECHO
;;;;		SKIPN LINKF	;LINKED CHAR? OR
		TMNN TTLNC,(T2)	;3004 LINKED CHARACTER
		TRCN T3,3B33	;FULL?
		JRST .+1	;YES
		CALL TTCOHA	;ACCOUNT SPACING FOR CHAR
		CAIGE T1,40	;IS CONTROL CHAR AND MODE 2?
		TRNN T3,3B33
REPEAT 0,<	JRST [	MOVE T3,TTLINK(T2) ;17 NO. GET LINK WORD
			CAME T3,[-1] ;ANY LINKS?
			CALL TTLNK3 ;YES. DO THEM
>				;17
		 JRST TCOY3	;17 AND DONE
		JRST TTCO1 ]	;YES, ECHO CONTROL FN

;EITHER NOT IMMEDIATE ECHOING OR IMMEDIATE ON A FULL-DUPLEX TERMINAL
;IF CONTROL CHARACTER, GO HANDLE SPECIALLY

	CAIGE T1,40
	JRST TTCO1		;CONTROL GROUP

;NOT A CONTROL CHARACTER. RAISE IF NECESSARY

	JE TTCRS,(T2),TCOY1	;SAW A CR LAST TIME
	SETZRO TTCRS,(T2)	;YEP, HAVE TO REALLY DO IT
	CALL VTOCR1
TCOY1:	MOVE T3,TTFLGS(2)
	TXNE T3,TT%LCA		;TERMINAL HAS LOWER CASE?
	JRST TTCO6		;YES, NO TRANSLATION NEEDED
	CAIL T1,"A"		;UPPER CASE LETTER?
	CAILE T1,"Z"
	JRST [	CAIL T1,"A"+40	;NO, LOWER CASE LETTER?
		CAILE T1,"Z"+40
		JRST TTCO6	;NO
		SUBI T1,40	;YES, CONVERT TO UPPER CASE
		JRST TTCO6]

;CHARACTER IS UPPER CASE. IF FLAGGING IS REQUIRED, CALL THIRD LEVEL
;ROUTINE TO PRINT A '^' BEFORE PRINTING THE CHARACTER

	TXNN T3,TT%UOC		;INDICATE?
	JRST TTCO6		;NO
	PUSH P,T1		;YES, SAVE CHAR
	MOVEI T1,TTLIND		;OUTPUT INDICATOR
	CALL TCOP
	POP P,T1
TTCO6:	CALL TCOP		;OUTPUT CHAR AND ACCOUNT SPACE
TCOY3:	RET
;TCOP - SECOND LEVEL SUBROUTINE - OUTPUT SINGLE SPACING CHARACTER
;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA FOR THIS LINE

;	CALL TCOP

TCOP:	HRRZ T3,TTLPOS(T2)	;GET CURRENT CHAR POSITION ON LINE
	LOAD T4,TPWID,(T2)	;GET RIGHT MARGIN
	JUMPE T4,TCOP0		;0 MEANS NEVER WRAP
	SUBI T4,1		;CORRECT FOR 0 ORIGIN
	CAIG T4,0(T3)		;CHECK FOR OVERFLOW
	 JRST TCOPWR		;YES, GO HANDLE LINE WRAPPING

; HERE IF NO WRAP OCCURS
TCOP0:	AOS TTLPOS(T2)		;UPDATE POSITIONS
	AOS TTPPOS(T2)
	JRST TCOUT		;AND CALL 3RD LEVEL TO PRINT CHAR

;HERE TO DO WRAPPING AT EOL
TCOPWR:	SUBI T4,(T3)		; REMEMBER POSITION
	MOVE T3,TTCHAR(T2)	; GET TERMINAL CHARACTERISTICS
	TXNE T3,TC%PRT!TC%WRP	; IF PRINTER OR AUTOWRAP
	 JRST TCOPWE		; HANDLE DIFFERENTLY
	JUMPN T4,TCOPW2		; WINNING DISPLAY, WRAP ON N+1TH CHAR
	STOR T1,TTLCH,(T2)	; SAVE THIS CHAR FOR POSSIBLE RETYPING
	AOS TTLPOS(T2)		; INCREMENT LOGICAL POSITION 
	JRST TCOUT

; OVERFLOW CHAR ON WINNING DISPLAY
TCOPW2:	PUSH P,T1
	MOVEI T1,WRPCHR		; OVERPRINT WRAPCHAR IN LAST COL
	CALL TCOUT
	CALL VTONL		; DOWN A LINE
	LOAD T1,TTLCH,(T2)	; GET BACK CHAR THAT WAS OVERSTRUCK
	CALL TCOUT
	MOVE T1,TTLPOS(T2)	; FIX CURSOR POSITION
	ADDI T1,2		; LAST CHAR FROM PREVIOUS LINE + THIS ONE
	MOVEM T1,TTLPOS(T2)
	MOVEM T1,TTPPOS(T2)
	POP P,T1		; ORIGINAL CHAR, REMEMBER ME?
	CALLRET TCOUT

; PRINTER/AUTOWRAP
TCOPWE:	PUSH P,T1
	MOVEI T1,WRPCHR
	CALL TCOUT
	CALL VTONL
	AOS TTLPOS(T2)
	AOS TTPPOS(T2)
	POP P,T1
	CALLRET TCOUT
;TTCOHA - ACCOUNT FOR SPACING DUE TO INPUT ON HALF-DUPLEX TERMINALS
;TERMINAL HAS PRINTED THE CHARACTER. THIS MERELY ACCOUNTS FOR THE
;RESULTING POSITION ON THE TERMINAL

;ACCEPTS:
;	T1/ CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA

TTCOHA:	CAIGE T1,40		;SPACING CHAR?
	IFSKP. <
		INCR TLHPS,(T2)	;YES. INCREMENT POSITION ON LINE
		INCR TPHPS,(T2)
		RET>
	CAIE T1,.CHCRT		;CR?
	IFSKP. <
		SETZRO TLHPS,(T2) ;YES. RESET TO LEFT MARGIN
		SETZRO TPHPS,(T2)
		RET>
	CAIE T1,.CHLFD		;LF?
	IFSKP. < 
		INCR TLNCT,(T2)	;LINE COUNTER
		CALLRET INCLIN>	;FIX CURSOR POSITION
	CAIE T1,.CHFFD		;FF?
	IFSKP. <
		SETZRO TLNCT,(T2) ;YES. RESET TO TOP OF PAGE
		RET>
	CAIE T1,.CHBSP		;BACKSPACE?
	RET			;NO
	JE TLHPS,(T2),R		;YES. IF NOT AT LEFT MARGIN,
	DECR TLHPS,(T2)		; DECREMENT CHARACTER POSITION WITHIN PAGE
	DECR TPHPS,(T2)
	RET

; INCREMENT CURSOR VERTICAL POSITION IF NOT AT BOTTOM OF SCREEN
INCLIN:	LOAD T3,TLVPS,(T2)
	LOAD T4,TPLEN,(T2)
	JUMPE T4,INCLI1		;0 MEANS INFINITE LENGTH (OVERFLOW?)
	SUBI T4,1		;ADJUST FOR 0 ORIGIN OF LVPS
	CAIL T3,(T4)		;ON LAST LINE OF SCREEN?
	RET			;YES
INCLI1:	INCR TLVPS,(T2)		;LOGICAL POSITION
	INCR TPVPS,(T2)		;AND PHYSICAL POSITION
	RET
	SUBTTL TCOY FOR CONTROL CHARACTERS

;HERE WHEN THE CHARACTER TO BE OUTPUT IS A CONTROL CHARACTER
; AND CHARACTER TRANSLATION IS ENABLED
;
;ACCEPTS:
;	T1/CHARACTER IN 7 BITS
;	T2/INTERNAL LINE NUMBER

;THIS IS PART OF THE SECOND LEVEL OUTPUT AND IS CALLED BY TCOY.
;CHITAB CONTAINS THE ROUTINE THAT WILL PROCESS THE CHARACTER
;IN SOME CASES, IT CONTAINS TCOUT, THE THIRD LEVEL ROUTINE.
;IN OTHER CASES, IT CONTAINS A SPECIAL ROUTINE, WHICH DOES SOME TRANSLATION
;AND THEN CALLS TCOUT

;FOR EACH CHARACTER, ACTION IS CONTROLLED BY TWO BITS IN FCMOD1 OR FCMOD2:
; 00 => IGNORE, DO NOT SEND
; 01 => SEND PRINTING INDICATION (I.E. &C)
; 10 => SEND ACTUAL CODE AND ACCOUNT LINE AND PAGE POSITION
; 11 => SIMULATE FORMAT ACTION AND ACCOUNT
;WHEN THIS CODE IS CALLED, LEVEL 1 OUTPUT HAS ALREADY HANDLED THE
;TRANSLATION OF CONTROL CHARACTER IF MODE 0 OR 1 IS IN EFFECT

TTCO1:	CAIN T1,.CHLFD		;LINEFEED?
	JRST TTCO11		;YEP, FINE
	JE TTCRS,(T2),TTCO11	;NO, SEE IF HAVE SEEN A CR
	SETZRO TTCRS,(T2)	;YES, TURN OFF FLAG
	CALL VTOCR1		;AND REALLY DO IT

TTCO11:	MOVE 4,FCMOD2(2)	;SECOND CONTROL MODES WORD
	MOVE 3,FCMOD1(2)	;FIRST CONTROL MODES WORD
	ROTC 3,0(1)		;GET TWO BIT MODE FOR THIS CHAR
	ROTC 3,0(1)
	HRRZ 4,CHITAB(1)	;GET DISPATCH ADDRESS
	CALL 0(4)		;DISPATCH TO FORMAT ROUTINE
	JRST TCOY3
	SUBTTL CONTROL CHARACTER OUTPUT ROUTINES

;ROUTINES CALLED FROM 2ND LEVEL (TCOY) FOR SOME CONTROL CHARACTERS
; ALL THESE HAVE TO BE ABLE TO WIN ON ALL SUPPORTED TERMINALS.

;LINE FEED
; ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1
;
; IF CCOC SEZ SIMULATE, DO CRLF.
; IF CCOC SEZ SEND, JUST DO LF
;
VTOLFD:	MOVE T4,TTFLG1(T2)	;GET STATUS FLAGS
	TXNN T4,TT%CRS		;LAST CHAR WAS CR...
	TXNE T3,<1B1>		;  NO, MAYBE WE'RE SIMULATING
	IFNSK. <
	   SETZRO TTCRS,(T2)
	   CALLRET VTONL	;YES OR YES, TREAT AS NEWLINE
	>
; HERE TO MOVE STRAIGHT DOWN
VTOLFA:	MOVE T1,TTTMOD(T2)	; GET MODE WORD
	MOVE T3,TTCHAR(T2)	;  AND CHARACTERISTICS
	TXNE T3,TC%SCR		; CAPABLE OF SCROLLING?
	 TXNN T1,TM%SCR		; IN SCROLL MODE?
	 JRST VTOLF4		; NO OR NO, WRAP
	LOAD T3,TPLEN,(T2)	; GET PAGE LENGTH
	JUMPE T3,VTOLF1		; NO CHECK IF LENGTH 0
	LOAD T3,TTLMX,(T2)	; GET EOP POSITION
	LOAD T1,TLNCT,(T2)	; GET LINE COUNTER
	CAIG T1,(T3)		; PAGE FULL?
	 JRST VTOLF1		; NO, SKIP THIS
	SETZRO TLNCT,(T2)	; YES, RESET COUNTER
	CALL TTXOFF		; AND STOP
VTOLF1: INCR TLNCT,(T2)		; COUNT THE NEW LINE
	LOAD T3,TTTYP,(T2)	; GET TERMINAL TYPE
	LOAD T3,DPTB,(T3)	; GET TABLE
	SKIPN T1,DPYDWN(T3)	; HAVE A DOWN FUNCTION?
	JRST VTOLF2		; NO, TRY ANOTHER WAY
	CALLRET VTSOUT		; YES, DO IT

VTOLF2:	LOAD T3,TPLEN,(T2)	; GET PAGE LENGTH
	LOAD T4,TLVPS,(T2)	; VERTICAL POSITION
	SUBI T3,1		; ADJUST LENGTH FOR 0 ORIGIN
	CAIL T4,(T3)		; ON LAST LINE?
	JRST VTOLF3		; YES, NEED TO BE TRICKY
	MOVEI T3,1		; NO, MOVE DOWN ONE LINE
	CALLRET VTOVWW		; BY USING VERTICAL WITH WRAP

; AT END OF PAGE, MUST FORCE SCROLL
VTOLF3: LOAD T3,TTTYP,(T2)	; GET TERMINAL TYPE
	LOAD T3,DPTB,(T3)	; GET TABLE
	MOVE T1,DPYNL(T3)	; DO A NEWLINE
	CALL VTSOUT		; YES, DO IT
	SETZRO TPHPS,(T2)	; REAL HORIZ POS IS 0, VPOS DOESN'T CHANGE
	CALLRET VTUPD		; PUT HORIZONTAL CURSOR BACK WHERE IT WAS

; WRAP MODE
VTOLF4:
	LOAD T1,TLVPS,(T2)	; GET CURRENT VERTICAL POSITION,
	LOAD T3,TTLMX,(T2)	;  ADJUSTED PAGE LENGTH,
	LOAD T4,TLNCT,(T2)	;   AND LINE COUNTER
	CAIGE T1,(T3)		; COMPARE V POS WITH LENGTH
	JRST VTOLF5		; NOT END OF SCREEN, JUMP
	CAILE T4,MORSAF		; END OF SCREEN. IS LINE COUNTER SMALL?
	CALL TTXOFF		; NO, STOP OUTPUT IF PAGE MODE
	MOVEI T3,1		; MOVE DOWN ONE LINE
	CALL VTOVWW		; VERTICAL WITH WRAP
	SETZRO TLNCT,(T2)	; I GUESS
	JRST VTOLF7		; GO CLEAR LINE AND EXIT

;WRAP MODE, NOT AT END OF SCREEN
VTOLF5:	CAIG T4,(T3)		; LINE COUNTER EXCEEDED?
	JRST VTOLF6		; NO, DON'T WORRY
	CALL TTXOFF		; YES, DO A MIDSCREEN STOP -YECCH
	MOVEI T1,MORSAF+1	; AND RIG LINE COUNTER TO DO IT AGAIN
	STOR T1,TLNCT,(T2)	; AT SCREEN BOTTOM
VTOLF6:	INCR TLNCT,(T2)		; INCREMENT LINE COUNTER
	MOVEI T3,1		; MOVE DOWN ONE LINE
	CALL VTOVWW		; VERTICAL WITH WRAP

;DONE WRAPPING, CLEAR NEW LINE IF POSSIBLE
VTOLF7:	MOVE T1,TTCHAR(T2)
	TXNN T1,TC%SCL
	 RET
	MOVEI T1,DPYCEL		; CLEAR OUT NEW LINE
	CALLRET VTOFUN
;DO A NEWLINE
;	T2/ ADDRESS OF DYNAMIC DATA
;	T4/ STATUS FLAG WORD - TTFLG1(T2)
;
;	TRASHES ALL BUT T2

VTONL:	MOVE T1,TTTMOD(T2)	;GET TERMINAL MODES
	MOVE T3,TTCHAR(T2)	;AND CHARACTERISTICS
	TXNE T3,TC%SCR		;CAN SCROLL...
	TXNN T1,TM%SCR		;AND WANTS TO?
	JRST VTONL2		;NO OR NO, WRAP
	LOAD T3,TPLEN,(T2)	;GET PAGE LENGTH
	JUMPE T3,VTONL1		;NO CHECK IF LENGTH 0
	LOAD T3,TTLMX,(T2)	;GET EOP POSITION
	LOAD T1,TLNCT,(T2)	;GET LINE COUNTER
	CAIG T1,(T3)		;PAGE FULL?
	JRST VTONL1		;NO
	SETZRO TLNCT,(T2)	;YES. RESET COUNTER
	CALL TTXOFF		;STOP IF IN PAGE MODE
VTONL1:	INCR TLNCT,(T2)		;COUNT THE NEWLINE
	CALLRET VTONLD		;GO DO NL

; WRAP MODE
VTONL2:	LOAD T1,TLVPS,(T2)	;GET VERTICAL POSITION,
	LOAD T3,TTLMX,(T2)	; ADJUSTED SCREEN LENGTH,
	LOAD T4,TLNCT,(T2)	; LINE COUNTER
	CAIGE T1,(T3)		;END OF SCREEN?
	JRST VTONL3		;NO
	CAIG T4,MORSAF		;HERE ON EOS. IS LINE COUNTER SMALL?
	IFSKP.
	  SETZRO TLNCT,(T2)	;NO, RESET COUNTER
	  CALL TTXOFF		;AND STOP
	ENDIF.	  
	SETZM TTLPOS(T2)	;CLEAR HORIZONTAL AND VERTICAL POSITIONS
	INCR TLNCT,(T2)		;COUNT LINE
	SETZRO <TTCFU,TTNAB>,(T2) ;NO LONGER CONFUSED (WON'T ALWAYS WORK)
	CALL VTUPD		;HOME CURSOR
	JRST VTONL5		;CLEAR LINE AND DONE

;WRAP MODE, NOT END OF SCREEN
VTONL3:	CAIG T4,(T3)		;TOO MANY LINES SINCE LAST STOP
	JRST VTONL4		;NO, DON'T WORRY
	CALL TTXOFF		;YES, DO A MIDSCREEN STOP (YEECH)
	MOVEI T1,MORSAF+1	;AND RIG LINE COUNTER TO DO IT AGAIN
	STOR T1,TLNCT,(T2)	;AT BOTTOM OF SCREEN
VTONL4:	INCR TLNCT,(T2)		;COUNT LINE
	CALL VTONLD		;MOVE CURSOR

;HERE TO CLEAR NEW LINE IF POSSIBLE, THEN EXIT
VTONL5: MOVE T1,TTCHAR(T2)
	TXNN T1,TC%SCL		;CAN WE DO IT
	RET			;NOPE
	MOVEI T1,DPYCEL		;CLEAR EOL FUNCTION
	CALLRET VTOFUN		;DO IT AND LEAVE

VTONLD:	LOAD T3,TTTYP,(T2)	;GET TERM TYPE
	LOAD T3,DPTB,(T3)	;GET DISPLAY TABLE
	SKIPN T1,DPYNL(T3)	;GET NEWLINE FUNCTION
	BUG(VTSMNL,<<T3,TYPE>>)	;MISSING???
	CALL VTSOUT		;DO IT
	SETZRO TLHPS,(T2)	;ZERO HORIZONTAL CURSOR POSITIONS
	SETZRO TPHPS,(T2)
	CALLRET INCLIN		;MAYBE INCREMENT CURSOR POS
	
;CARRIAGE RETURN

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1

VTOCRT:	SETONE TTCRS,(T2)	;JUST REMEMBER WE SAW IT
	RET

; HERE IF WE EVER HAVE TO REALLY DO ONE
VTOCR1:	SAVEAC <T1,T2,T3,T4>
	SETZRO TLHPS,(T2)	; BACK TO LEFT MARGIN
	CALLRET VTUPD		; SO CR WILL ALWAYS BE DONE

;TAB

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1
;
VTOTAB:	LOAD T3,TLHPS,(T2)
	TRZ T3,7		; ROUND UP TO NEXT MULTIPLE OF 8.
	ADDI T3,10
	CALLRET	VTOHR0		; AND HANDLE AS HORIZONTAL MOVE
 
; SPACE
VTOSPC:	MOVEI T1," "
	CALLRET TCOUT		;SEND A SPACE


;FORM FEED
; ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1
;
VTOFFD:	MOVEI T3,TTCHAR(T2) 
	TXNN T3,TC%CLR!TC%SCL	; CAN WE CLEAR SCREEN?
	 JRST VTOFF1		; NO, PROBABLY A PRINTING TERMINAL
	CALLRET	VTOCLR		; YES, CALL IT A FORMFEED

VTOFF1:	LOAD T4,TLNCT,(T2)	;GET PRESENT PAGE POSITION ---
	SETZRO TLNCT,(T2)	;RESET TO TOP OF PAGE
	PUSH P,T3		;SAVE CCOC BITS
	LOAD T3,TPLEN,(T2)	;PAGE SIZE
	JUMPE T3,[ SETZM Q1	;IF ZERO PAGE LENGTH, SAY AT THE END
		JRST VTOFF2]
	IDIVI T4,0(3)
	SUBM T3,Q1		;Q1/ DIFFERENCE TO END OF PAGE
VTOFF2:	POP P,T3
	MOVSI T4,(1B1)
	TDNE T4,TTFLGS(2)	;DEVICE HAS MECH FF?
	TLNE T3,(1B1)		;AND SEND DIRECT REQUESTED?
	JRST VTOFF3		;NO, SIMULATE FF
	CALL TCOUT		;SEND REAL CHARACTER
	JRST VTOFF5		; !!!NEED PADDING!!!

;SIMULATE FORM FEED BY OUTPUTTING AS MANY LINE FEEDS AS ARE NEEDED
;TO GET TO THE TOP OF THE NEXT PAGE

VTOFF3:	PUSH P,TTLPOS(2)	;SAVE LINE AND PAGE POSITIONS  ---
	PUSH P,Q1		;SAVE NUMBER OF LINES LEFT IN PAGE
VTOFF4:	CALL VTONL		;SIMULATE ONE FORM FEED
	SETZRO TLNCT,(T2)	;PREVENT TTSM2 FROM DOING X-OFF ---
	SOSLE 0(P)		;COUNT LF'S
	JRST VTOFF4		;LOOP ON LF'S
	POP P,Q1		;FLUSH TEMP
	POP P,TTLPOS(2)		;RESTORE LINE AND PAGE POSITIONS ---
VTOFF5:	LOAD 1,TPLEN,(2)	;CHECK PAGE LENGTH
	JUMPE T1,R		;DO XOFF UNLESS PLENGTH IS 0
	CALLRET TTXOFF		;DO XOFF

;ESC

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1

VTOESC:	TLNN T3,(3B1)		;00?
	RET			;YES, NO SEND
	TLNE T3,(1B1)		;01 OR 11?
	JRST [	MOVEI T1,"$"	;YES, SEND $
		CALLRET TCOP]
	CALLRET TCOUT		;SEND ACTUAL CODE

;BACKSPACE
; DON'T WRAP BACK IF AT BEGINNING OF LINE
;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1
;
VTOBSP:	MOVEI T3,1
	LOAD T1,TLHPS,(T2)	; IF AT BEGINNING OF LINE
	SKIPE T1		;  DON'T WRAP
	SOJ T1,
	STOR T1,TLHPS,(T2)
	CALLRET VTUPD		; BUT ALWAYS UPDATE CURSOR

; BELL
VTOBEL:	MOVE T1,TTTMOD(T2)	; MAYBE HE WANTS VISIBLE BELL
	TXNN T1,TM%VBL
	JRST VTOBL1		; GUESS NOT
	MOVE T1,TTCHAR(T2)	; HE DOES, IS IT POSSIBLE
	TXNN T1,TC%VBL
	JRST VTOBL1		; NO, GO BEEP
	MOVEI T1,DPYVBL		; YES, DO IT
	CALLRET VTOFUN
VTOBL1:	MOVEI T1,"G"-100	; SEND A NORMAL BEEP.
	CALLRET TCOUT
;TTXOFF - STOP OUTPUT TO A TERMINAL, I.E. PAUSE ON END-OF-PAGE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;CALLED WHEN OUTPUT TO A TERMINAL CAUSES THE PAGE TO FILL UP. IF TERMINAL
;IS IN PAGE MODE, PUTS SPECIAL CHARACTER IN OUTPUT STREAM TO CAUSE 'XOFF' 
;ACTION WHEN ENCOUNTERED AT INTERRUPT LEVEL

TTXOFF:	MOVX T1,TT%PGM		;DISPLAY PROCESSING
	TMNE TTNXO,(T2)		;  AND DOING PAGE STOP?
	TDNN T1,TTFLGS(T2)	;IN PAGE MODE?
	RET			;NO, DO NOTHING
;;;	SKIPE LINKF		;OUTPUTTING TO LINKED TERMINAL?
	TMNE TTLNC,(T2)		;3004 OUTPUTTING TO LINKED TERMINAL
	RET			;YES, DON'T STOP
	TMNN TMMVR,(T2)		;GOING TO STOP. BE VERBOSE?
	IFSKP.
	  CALL TTXVMR		;YES, PRINT [More]
	ELSE.
	  CALL VTOBEL		;NO, OUTPUT BELL TO TELL USER
	ENDIF.
	MOVEI T1,.TTPFC		;PUT SPECIAL FUNCTION CODE IN OUTPUT
	CALLRET TCOUF		; STREAM TO STOP OUTPUT AT THAT POINT

; SEND A VERBOSE [MORE] INDICATION
;	T2/ DYNAMIC DATA
;
TTXVMR: CALL VTONLD		;YES. DO A NEWLINE
	MOVE T3,[POINT 7,[ASCIZ /  [**More**]/]]
TTXVM0:	ILDB T1,T3		;GET CHAR
	JUMPE T1,TTXVM1		;DONE
	PUSH P,T3		;SAVE BYTE PTR
	CALL TCOUT		;SEND THE CHAR
	POP P,T3		;GET PTR BACK
	JRST TTXVM0
TTXVM1:	RET
	SUBTTL TCOUT (THIRD LEVEL OUTPUT)

;OUTPUT ONE CHARACTER TO SPECIFIED TTY LINE
; SEVERAL ENTRY POINTS:
;	SCDTCO - PANIC INFO - SEND EVEN IF FLUSHING OUTPUT, ETC.
;	TCOUM - PUT "TURN OUTPUT ON" FUNCTION CODE IN OUTPUT STREAM - 
;			NOT TO PTY'S - IGNORE ^O ACTION - BINARY
;	TCOUF - PUT FUNCTION ESCAPE CODE IN OUTPUT STREAM -
;			NOT TO PTY'S - BINARY
;	TCOUT - REGULAR CHARACTER - ADD PARITY
;	TCOU1 - REGULAR CHARACTER - DON'T ADD PARITY
;
;ACCEPTS:
;	T1/ CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS

;IF IN SCHEDULER AND UNABLE TO SEND CHARACTER, SETS TCOERR TO -1

;SPECIAL ENTRY POINT WHEN ENTERING FROM TTEMES

;ACCEPTS:
;	T1/ CHARACTER
;	T2/ ADDRESS OF DYNAMIC DATA (FULL-LENGTH OR TTEMES BLOCK)

;RETURNS +1: ALWAYS

;IF UNABLE TO SEND CHARACTER AND IN SCHEDULER, SETS TCOERR TO -1

SCDTCO:	SKIPL CHITAB(T1)	;TEST PARITY BIT FOR THIS CHARACTER
	JRST TCOU6		;NO PARITY NEEDED. GO ON
	CALL SPARTY		;SET PARITY BIT
	JRST TCOU6		;GO STORE IN OUTPUT BUFFER

;PUT MARKER IN OUTPUT STREAM - IGNORE TOFLG

TCOUM:	CALL CKPHYD		;PTY?
	 RET			;YES, DO NOTHING
	JRST TCOUM1		;ENTER OUTPUT SEQUENCE

;PUT FUNCTION ESCAPE CODE IN OUTPUT STREAM

TCOUF:	CALL CKPHYD		;PTY
	 RET			;YES, DO NOTHING
	JRST TCOU3		;GO DO IT

;PHYSICAL LINE. APPLY PARITY

TCOUT:	SKIPL CHITAB(1)		;TEST PARITY BIT FOR THIS CHAR
	JRST TCOU1		;NO PARITY NEEDED. GO ON
	CALL SPARTY		;SET PARITY BIT AS NEEDED

;FULLY ACTIVE LINE. PROCESS LINES LINKED TO THIS ONE

TCOU1:
REPEAT 0,<			;17 BEGIN DELETION
	MOVE C,TTLINK(B)	;ANY LINKS?
	CAME C,[-1]
	CALL TTLNK3		;YES. GO DO THEM
>				;17 END DELETION
;SEE IF THERE IS ROOM IN THE OUTPUT BUFFER

TCOU3:	JN TOFLG,(T2),R		;LOSE CHARACTER IF CTRL/O TYPED
TCOUM1:	DYNST T3		;GET INTERNAL LINE NUMBER
	CAMN T3,CTYINT		;IS THIS AN ALIAS FOR THE CTY?
	RET			;YES. IGNORE CHARATCER
TCOU6:	LOAD 3,TOMAX,(2)	;CAPACITY OF OUTPUT BUFFERS
	SKIPE IMECHF		;IMMEDIATE ECHO CHARACTER?
	ADDI 3,2		;YES. EXTRA ROOM FOR THIS CHARACTER
	CAMLE 3,TTOCT(2)	;FULL?
	JRST TCOU5		;NO
	; ..
	; ..

;ACTION WHEN BUFFER FULL

	SKIPN INSKED		;ARE WE IN THE SCHEDULER?
	SKIPE NSKED		;NO. ARE WE NOSKED?
	JRST [	SETOM TCOERR	;YES. INDICATE FAILURE FOR SCHEDULER
		RET]		; AND RETURN
	TDCALL D,<<PT,CHKPTA>>	;CHECK FOR PTY ACTION NEEDED
	SETONE TTBKO,(T2)	;NOTE BLOCKE FOR OUTPUT EVENT
	PUSH P,1		;SAVE CHARACTER
	DYNST T1		;GET LINE NUMBER
	PUSH P,T1		;SAVE LINE #
	CALL ULKTTY		;UNLOCK THE TTY
	MOVEI 1,TCOTST		;SETUP SCHEDULER TEST WORD
	HRL 1,0(P)		; LINE NO,,TEST ROUTINE ADR
	MOVSI T2,FHV5		;WAIT PRIORITY
	HDISMS
	MOVE T2,0(P)		;GET STATIC LINE NUMBER
	CALL LCKTTY		;LOCK UP THE TTY
	 JRST    [CALL ULKTTY	;UNLOCK THE LINE I CASE IT GOT LOCKED
                  MOVE T2,0(P)  ;GET BACK LINE NUMBER
                  CALL TCOU7	;GET SPECIAL BLOCK
                  JRST .+1]
	ADJSP P,-1		;CLEAN UP STACK
	POP P,T1		;CHARACTER
	JRST TCOU3
;BUFFER IS NOT FULL.  SEE IF THERE IS A BUFFER. IF NOT, GET AS MANY
;AS ARE NEEDED

TCOU5:	TDCALL D,<<PT,CKPTOU>,<MC,CKMCOU>>,RETSKP ;SEE IF OUTPUT POSSIBLE
	 RET
	CALL NSKD1		;+++ 
	CHNOFF DLSCHN		;MUST PREVENT DEASSIGN OF BUFFERS
	SKIPE 3,TTOIN(2)	;BUFFERS EXIST?
	JRST TCOU4		;YES.

;THIS LINE HAS NO OUTPUT BUFFERS. GET SOME IF POSSIBLE. IF NONE
;AVAILABLE, WAIT FOR THEM UNLESS IN SCHEDULER. IN THAT CASE, SET
;ERROR FLAG AND RETURN

	CHNON DLSCHN		;NO. ALLOW DLS INTERRUPTS
	LOAD 3,TTNOU,(2)	;GET NUMBER TO ASSIGN
	CALL TTGTBF		;ASSIGN THEM
	 JRST [	CALL OSKD1	;FAILED. ALLOW SCHEDULING
		SKIPN INSKED	;ARE WE IN THE SCHEDULER?
		SKIPE NSKED	;NO. ARE WE NOSKED?
		JRST [	SETOM TCOERR ;YES. INDICATE ERROR FOR SCHEDULER
			RET]	; AND RETURN
		PUSH P,1	;SAVE CHARACTER
		LOAD 1,TTNOU,(2);NO, CAN WAIT FOR BUFFERS
		MOVSI 1,0(1)	;NUMBER NEEDED
		HRRI 1,TTBUFW
		MDISMS
		POP P,1		;RESTORE CHARACTER
		JRST TCOU5]	;BUFFERS ARE AVAILABLE. GO GET THEM
	CHNOFF DLSCHN
	MOVEM 3,TTOOUT(2)
	MOVEM 3,TTOIN(2)

;BUFFERS ARE AVAILABLE. AC 3 CONTAINS BYTE POINTER FOR ADDING NEXT
;CHARACTER. STORE THE CHARACTER.

TCOU4:	TDNN 3,WRPMSK		;END OF BUFFER?
	JRST [	HRRZ T4,T3	;GET NEXT ONE
		HRR T3,1-TTSIZ(T4)
		MOVEM T3,TTOIN(T2) ;SAVE CHARACTER POINTER
		JRST .+1]
	IDPB T1,TTOIN(T2)	;GET CHARACTER
	AOS 3,TTOCT(2)		;INCREMENT COUNT OF CHARACTERS IN BUFFER
	CHNON DLSCHN		;SAFE TO TURN CHN ON AFTER AOS
	AOS NTTYOT		;COUNT ALL OUTPUT
	CALLRET STRTOU		;START OUTPUT TO LINE IF NEEDED

;SET PARITY BIT IF REQUIRED FOR THIS LINE TYPE
; T2/ DYNAMIC DATA PTR
; T1/ CHARACTER
;RETURN +1 ALWAYS, T1 MODIFIED

SPARTY:	LOAD CX,TLTYP,(T2)	;GET LINE TYPE
	XCT PARTBL(CX)		;SET OR CLEAR BIT
	RET
;HERE WHEN DID TCOTST BLOCK AND AWOKE TO FIND LINE
;HAS BEEN DEASSIGNED

	SWAPCD			;GET HERE ONLY IN PROCESS CONTEXT
TCOU7:	STKVAR <LNNUMB>
	MOVEM T2,LNNUMB		;SAVE LINE NUMBER
TCOU75:	NOSKED			;OWN THE MACHINE
TCOU76:	MOVE T2,LNNUMB		;GET LINE #
	CALL LCKTTY		;CHECK IT NOW
	SKIPA   		;IF UNASSIGNED, GO ON
	JRST [	OKSKED		;ALLOW SCHEDULING
		RET]		;AND DONE
	CALL ULKTTY		;UNLOCK IN CASE IT GOT LOCKED
	JUMPG T2,TCOU77		;IF BLOCK IS SHORT WAIT IT TO BE DEALLOCATED
	MOVE T2,LNNUMB		;LINE # AGAIN
	CALL ASGMSL		;GET A MESSAGE BLOCK
	 JRST TCOU77		;FAILED
	CALL STADY		;SUCCESS. GET DYNAMIC DATA ADDRESS
	 JRST TCOU77		;SOMETHING VERY WRONG. TRY AGAIN
	SETOM TTLINK(T2)	;NO LINKS
	JRST TCOU76		;AND PROCEED

TCOU77:	MOVEI T1,^D1000		;WAIT 1 SEC
	CALL SETBKT		;COMPUTE WAIT
	HRRI T1,BLOCKT		;THE TEST
	RDISMS			;WAIT HERE
	JRST TCOU75		;TRY AGAIN

	ENDSV.			;END STKVAR

	RESCD			;BACK TO RESIDENT MONITOR
;TTLNK3 - SCAN LINK WORD, SENDING CHAR TO LINES SPECIFIED BY NON-777 BYTES
; CALLS THE ROUTINE THAT CALLED IT TO SEND CHAR TO LINKED TERMINALS
;
; CALL WITH	T1/ CHAR
;		T2/ DYN DATA OF OBJECT TTY
;
; RETURNS 	+1

TTLNK3:	MOVE T3,TTLINK(T2)	;17 GET LINK WORD FROM DYNAMIC AREA
	CAMN T3,[-1]		;17 ANY LINKS?
	 RET			;17 NO, NOTHING TO DO THEN
	SKIPE IMECHF		;17 ECHO CHARACTER?
	JRST [	PUSH P,T2	;SAVE DYNAMIC DATA ADDRESS
		JRST TTLN33]	; AND DON'T UNLOCK OBJECT TTY
	DYNST T4		;GET LINE NUMBER
	PUSH P,T4		;SAVE LINE NUMBER
	CALL ULKTTY		;UNLOCK OBJECT TTY FOR A WHILE
TTLN33:	;;;AOS LINKF		;3004 BE SURE CHARS GO OUT
TTLNK2:	SETZ T2,
	LSHC T2,^D9		;GET NEXT FIELD FROM T3
	CAIN 2,777
	JRST TTLNK1		;MEANS NOT IN USE
	PUSH P,T3		;SAVE LINK WORD
	PUSH P,T1		;SAVE CHARACTER
	CALL LCKTTY		;LOCK UP DESTINATION TTY - /T2 DYN DATA
	 JRST TTLNK4		;NOT ACTIVE. DON'T SEND TO IT
;;	TRNN T1,200		;THIS CHARACTER HAVE PARITY?
;;	JRST TTLK11		;NO. GO ON
;;	CALL SPARTY		;SET PARITY BIT
	SETONE TTLNC,(T2)	;3004 DOING LINKED CHARACTER
TTLK11:	CALL @-3(P)		;CALL WHOEVER CALLED US TO SEND CHAR
	SETZRO TTLNC,(T2)	;3004 NOT ANY MORE
TTLNK4:	CALL ULKTTY		;FREE UP THE TTY
	POP P,T1		;RETRIEVE CHAR
	POP P,T3		;RETRIEVE LINK WORD
TTLNK1:	JUMPN T3,TTLNK2		;DO MORE IF ANY
;;;	SOS LINKF		;3004 NO LONGER LINKING
	SKIPE IMECHF		;DOING ECHOING?
	JRST [	POP P,T2	;YES. GET OBJ TTY DYN DATA BACK
		RET]		;AND EXIT
	PUSH P,T1		;SAVE CHAR
	MOVE T2,-1(P)		;GET BACK LINE NUMBER
	CALL LCKTTY		;LOCK OBJECT TTY AGAIN
	 JUMPLE T2,[MOVE T2,-1(P) ;SOMEBODY PUNTED IT, GET LINE NUMBER AGAIN
		CALL TCOU7	;GET A SPECIAL BLOCK
		JRST .+1]	;AND PROCEED
	POP P,T1		;GET CHAR
	ADJSP P,-1		;CLEAN UP STACK
	RET			;AND PROCEED
;TCOTST - CALLED FROM SCHEDULER TO TEST FOR RUNNABLE

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF OUTPUT BUFFER IS NOT TOO FULL TO ADD A CHARACTER TO IT

TCOTST::MOVEI 2,0(1)		;LINE NUMBER TO REGULAR AC
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST 1(T4)		;NOT ACTIVE. SHOULDN'T HAPPEN
	LOAD 1,TOWRN,(2)	;REGULAR WAKEUP COUNT
	SKIPE FKINT(FX)		;BUT IF INTERRUPT WAITING,
	LOAD 1,TOMAX,(2)	;WAKEUP IF BUFFER IS NOT FULL
	CAMLE 1,TTOCT(2)	;AT OR BELOW WAKEUP LEVEL?
	JRST	[SETZRO TTBKO,(T2)	;NOTE WAIT COMPLETED
		JRST 1(4)		;YES
		]
  IFE .MLFLG,<
	JRST 0(4)
  >
  IFN .MLFLG,<
	CALL MLCCKT		;DYNAMIC IS IT MLC TYPE?
	 JRST 0(4)		;NO - STILL BLOCKED
	CALL MLCCKD		;YES- DYNAMIC IS IT MLC OPENED?
	 CAIA			;NO-BETTER LOSEN IT UP
	JRST 0(4)		;YES-NORMAL BLOCKING
	MOVE 1,TTOIN(2)		;MAKE IN AND OUT PTRS SAME
	MOVEM 1,TTOOUT(2)	;AS THOUGH DID OUTPUT
	SETZM TTOCT(2)		;HO,HO  NO MORE CHARS!
	JRST 1(4)		;MLC MAGIC WAKEUP
  >
;TTBUFW - CALLED FROM SCHEDULER TO WAIT FOR BUFFERS

;ACCEPTS:
;	T1/ NUMBER OF BUFFERS NEEDED

;CAUSES WAKEUP IF THE NEEDED NUMBER OF BUFFERS ARE AVAILABLE

TTBUFW:	CAMLE 1,TTFREC
	JRST 0(4)
	JRST 1(4)
	SUBTTL TCI (GET CHAR FROM INPUT BUFFER)

;ROUTINE TO GET CHARACTER FROM LINE INPUT BUFFER
;CONVERT FROM ASCII TO INTERNAL AND GENERATE ECHOS
;AS REQUESTED

;ACCEPTS IN T2/	LINE #
;	CALL TCI
;RETURNS +1:	NEEDED TO BLOCK, CALLER MUST VERIFY IF THE TTY BEING
;			INPUT FROM IS STILL THE CORRECT ONE.  IN
;			PARTICULAR, WAS THE JOB DETACHED?
;	 +2:	SUCCESSFUL, CHARACTER IN T1
;N.B. T2 MUST BE PRESERVED IN THIS ROUTINE

TCI::
TCI1:	LOAD T3,TT%DAM,TTFLGS(T2) ;GET CURRENT DATA MODE
	TRNN T3,1		;TRANSLATING INPUT?
	JRST TCIB		;JUMP IF NOT
	LOAD T1,TYLCH,(T2)	;GET LAST CHARACTER TAKEN FROM INPUT BUFFER
	TMNE TTRFG,(T2)		;REPEAT LAST CHARACTER (BKJFN)?
	JRST [	SETZRO TTRFG,(T2) ;YES. CLEAR FLAG
		TXO T1,TTXECO	;INDICATE ALREADY ECHOED
		JRST TCI3]
	LOAD T3,TYLMD,(T2)	; GET MODE OF LAST CHAR INPUT
	CAIN T1,.CHCRT		;LAST CHAR WAS A CR?
	CAIN T3,.TTBIN		; YES, LAST MODE NON-BINARY?
	JRST [	CALL TCI0	; NO TO EITHER - GET NEXT CHAR FROM BUFFER
		 RETBAD		;NEEDED TO BLOCK. TELL THE CALLER.
		JRST TCI3]	; AND CONTINUE
	MOVE T1,[.CHLFD+TTXECO]	;YES, RETURN LF WITH NO ECHO

;NEXT CHARACTER IS IN RIGHT 9 BITS OF T1. IF IT HAS BEEN ECHOED,
;BIT TTXECO IS SET

TCI3:	CALL TCITTI		;TEST FOR TERMINAL INTERRUPT AND HANDLE IT
	 RETBAD			;IT WAS, RETURN FAILURE

;NOT AN INTERRUPT CHARACTER. RAISE AND/OR ECHO AS NEEDED AND RETURN
;IT TO THE CALLER IN 7 BITS.

	MOVE T4,T1		;T4/ CHARACTER AND ECHO BIT
	ANDI T1,177		;T1/ CHARACTER IN 7 BITS
	MOVE T3,TTFLGS(T2)	;T3/ TTFLGS FOR THIS LINE
	CAIN T1,.CHCRT		;A CR?
	JRST [	CALL TCIECO	;YES, ECHO CR-LF
		MOVEI T1,.CHLFD
		CALL TCIECO
		MOVEI T1,.CHCRT	;RETURN CR THIS TIME
		JRST TCIR]
	CALL TTRAIS		;TRANSLATE, RAISE, ETC.
	CALL TCIECO		;ECHO CHARACTER IF NECESSARY
	JRST TCIR
;TCIB - ENTRY FOR BINARY INPUT

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TCIB

;RETURNS +1: NEEDED TO BLOCK
;	 +2: SUCCESS
;		T1/ CHARACTER

TCIB::	TMNE TTRFG,(T2)		;REPEAT LAST CHARACTER?
	JRST [	SETZRO TTRFG,(T2) ;YES. CLEAR FLAG
		LOAD T1,TYLCH,(T2) ;GET LAST CHARACTER INPUT
		JRST TCIB1]
	MOVEI T3,.TTBIN		;USE BINARY TERINAL DATA MODE
	CALL TCI0		;GET A CHAR
	 RETBAD			;NEEDED TO BLOCK. RETURN TO CALLER.
	CALL TCITTI		;CHECK FOR TERMINAL INTERRUPT
	 RETBAD			;IT WAS, RETURN FAILURE
TCIB1:	ANDI T1,377		;RETURN CHARACTER + PARITY

;ALL ECHOING, ETC., HAS BEEN DONE. STORE IN DYNAMIC DATA AND
;RETURN THE CHARACTER TO THE CALLER

TCIR:	STOR T1,TYLCH,(T2)	;SAVE LAST CHAR
	LOAD T3,TT%DAM,TTFLGS(T2) ; GET CURRENT DATA MODE
	STOR T3,TYLMD,(T2)	; AND STORE AS DATA MODE FOR LAST CHAR INPUT
	RETSKP			;SKIP TO INDICATE BUFFER WASN'T EMPTY
;TCIECO -DO DEFERRED ECHO IF NECESSARY

;ACCEPTS:
;	T1/ CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ TTFLGS FOR THIS LINE
;	T4/ CHARACTER IN 9 BITS

TCIECO:	TXNE T3,TT%ECO		;ECHOS ON?
	TRNE T4,TTXECO		;AND CHARACTER NEEDS ECHO
	RET			;NO, DO NOTHING
	PUSH P,T1		;+++ SAVE 1 FOR CALLER
	PUSH P,T3		;SAVE 3 FOR CALLER
	PUSH P,T4		;SAVE 4 FOR CALLER
	CALL CLOFLG		;CLEAR CTRL-O FLAG IF NECESSARY
	CALL TCOE		;SEND IT
	POP P,T4
	POP P,T3
	POP P,T1		;+++
	RET

;TTCLPS - ROUTINE TO CLEAR PAGE COUNTER ON ENABLED INTERRUPT CHARACTER
;IF LINE IS IN PAGE MODE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCLPS

;RETURNS +1: ALWAYS,
;	ALL AC'S PRESERVED

TTCLPS:	JE TTNXO,(T2),R		;IF NO PAGE STOP, DONE
	SETZRO TLNCT,(B)	;YES. CLEAR PAGE POSITION
	RET			;AND RETURN

;CLEAR CTRL-O FLAG
; T2/ DYNAMIC PTR

CLOFLG:	JNOR <TOFLG,TTFLO>,(T2),R ;RETURN IF NEITHER FLAG SET
	SAVEAC <T1>
	MOVEI T1,.TTMRK		;YES, PUT MARKER IN STREAM
	SKIPE CTRLOF		;BUT ONLY IF NEW MODE
	CALL SKCON		;AND INTERRUPT NOT ENABLED
	IFSKP. <
	  CALL TCOUM>
	SETZRO TOFLG,(T2)	;CLEAR MAIN LEVEL FLAG
	RET
;TCI..

;TEST FOR DEFERRED TERMINAL INTERRUPT CHARACTER.  INITIATE
;INTERRUPT IF NECESSARY.
; T1/ CHARACTER
; T2/ ADDRESS OF DYNAMIC DATA
;	CALL TCITTI
; RETURN +1: INTERRUPT CHAR, INTERRUPT INITIATED
; RETURN +2: NON-INTERRUPT CHAR, T1 PRESERVED

TCITTI:	SAVEAC <Q1>
	MOVEM T1,Q1		;SAVE CHAR
	ANDI T1,177		;EXTRACT ASCII
	CALL GPSICD		;GET PSI CODE IF ANY
	JUMPL T1,TCITT1		;JUMP IF NONE
	MOVE T3,BITS(T1)
	TDNN T3,TTPSI(T2)	;THIS CODE ENABLED?
	JRST TCITT1		;NO

;THIS IS A DEFERRED INTERRUPT CHARACTER.  INITIATE THE INTERRUPT
;AND WAIT UNTIL IT HAS TAKEN

	CALL TTCLPS		;YES. CLEAR OUT PAGE MODE STUFF
	MOVEM T2,Q1		;SAVE ADDRESS OF DYNAMIC DATA
	MOVE T3,T1		;PASS CODE IN T3 FOR TTPSRQ
	NOSKED
	CALL ULKTTY		;ALLOW DEALLOCATION
	DYNST			;T2/ INTERNAL LINE NUMBER
	CALL TTPSRQ		;INITIATE INTERRUPT. RETURNS FORK ID IN 2
	OKSKED
	AOS TTINTS		;COUNT INTERRUPTS
	MOVEI T1,TCIPIT		;SETUP SCHED TEST FOR INTERRUPT PROCESSED
	HRL T1,T2		;GET FORK THAT GOT THE INTERRUPT
	SKIPE FKINT(T2)		;INTERRUPT STILL PENDING?
	MDISMS			;YES, WAIT A WHILE
	MOVE T2,Q1		;RESTORE ADDRESS OF DYNAMIC DATA
	RET			;RETURN NOSKIP TO RELOCK DATA

;NOT AN INTERRUPT CHARACTER.  GIVE SKIP RETURN

TCITT1:	MOVE T1,Q1		;RESTORE INPUT CHAR
	RETSKP			;RETURN TO CONTINUE PROCESSING CHAR

;TCIPIT - SCHEDULER TEST FOR MDISMS. CAUSES WAKEUP IF THE
;PROCESS POINTED TO BY AC 1 HAS NO PENDING INTERRUPTS

;ACCEPTS:
;	T1/ FORK HANDLE

TCIPIT:	SKIPE FKINT(T1)		;SCHED TEST FOR INTERRUPT STILL PENDING
	JRST 0(T4)		;STILL PENDING
	JRST 1(T4)		;COMPLETED
;TCI..

;TCI0 - GET ONE CHARACTER FROM LINE INPUT BUFFER

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ TERMINAL DATA MODE IN BITS 34-35

;RETURNS +1: LINE BUFFER WAS EMPTY, HAD TO WAIT
;	 +2: LINE BUFFER WAS NOT EMPTY,
;		T1/ ASCII CHARACTER + ECHO FLAG IN 9 BITS
; 		TIFCH(T2) SET TO FULL CHAR INPUT IF ITP IN USE
;
;CALLER MUST HAVE CALLED LCKTTY ON THE LINE. IF BLOCK ON INPUT
;WAIT OCCURS, THIS ROUTINE CALLS ULKTTY

TCI0:	MOVE T1,TTTMOD(T2)	; IS ITP IN USE
	TXNN T1,TM%ITP		;
	 JRST TCI00		; NO, HANDLE NORMALLY

; HERE TO GET ITP CHARACTER FROM LINE BUFFER. BUFFER CONTAINS
; CHARACTER IN 7 BITS, + 200 BIT SET IF CHAR IS A PREFIX

TCIIT0:	CALL TCI00		; GET A CHAR
	RETBAD			; NEED TO BLOCK
	JN TIHCP,(T2),TCIIT1	; PREVIOUS CHAR WAS PREFIX, ACT DIFFERENTLY
	TRZN T1,200		; IS THIS A PREFIX CHARACTER?
	JRST [	STOR T1,TIFCH,(T2) ;NO, JUST STORE CHAR
		RETSKP]
	SETONE TIHCP,(T2)	; YES, FLAG IN PREFIX MODE
	STOR T1,TIHCH,(T2)	; SAVE PREFIX CHAR FOR LATER USE
				; => NOTE THAT TIHCH IS THE TOP HALF OF TIFCH
	JRST TCIIT0		; AND TRY FOR SECOND CHARACTER

;HERE IF PREVIOUS CHAR WAS A PREFIX, CONVERT CURRENT CHAR TO 12 BIT ASCII

TCIIT1:	SETZRO TIHCP,(T2)	; CLEAR PREFIX FLAG
	STOR T1,TILCH,(T2)	; SAVE LOW BITS OF FULL CHARACTER 
				; => TILCH IS PART OF TIFCH
	LOAD T3,TIHCH,(T2)	; GET PREFIX BITS
	PUSH P,T1		; SAVE CHAR FOR FLAGS
	ANDI T1,177
	CALL ITPASC		; CONVERT TO 7 BIT ASCII
	POP P,T3		; GET CHAR BACK
	TRNE T3,TTXECO		; 
	IORI T1,TTXECO		; MARK WHETHER CHAR WAS ECHOED
	RETSKP			; HAVE CHAR, GOOD RETURN
; HERE TO GET A NORMAL CHAR FROM BUFFER

TCI00:	NOSKED
	CALL GTTCI		;GET CHAR FROM INPUT BUFFER
	 JRST TCI01		;EMPTY
	OKSKED
	CALL SNDXON		;SEND XON IF NEEDED
	RETSKP			;SKIP TO INDICATE NO WAIT

;TAKE NEXT CHAR FROM TTY INPUT BUFFER
; T2/ TERMINAL DATA BLOCK
; RETURN +1: BUFFER EMPTY
;	+2: T1/ CHAR

GTTCI:	SKIPG T1,TTICT(T2)	;ANY CHARS IN BUFFER?
	RET			;NO
	SKIPN T3,TTIOUT(T2)	;GET POINTER
	BUG(TTICN0)
	HRRZ T4,T3
	TDNN T3,WRPMSK		;AT END OF CURRENT BUFFER?
	HRR T3,1-TTSIZ(T4)	;YES. GO TO NEXT IN CHAIN
	ILDB T1,T3		;GET NEXT CHARACTER
	MOVEM T3,TTIOUT(T2)	;SAVE UPDATED BYTE POINTER
	SOSG TTICT(T2)		;REDUCE COUNT, NOW EMPTY?
	JRST [	SETZB T3,TTIOUT(T2) ;YES, RELEASE BUFFERS
		EXCH T3,TTIIN(T2)
		CALL TTRLBF
		JRST .+1]
	RETSKP
;ACTION IF BUFFER IS EMPTY. MAKE SURE NO OTHER FORK IS WAITING.
;THEN GO INTO INPUT WAIT

TCI01:	OKSKED
TCI11:	LOAD T1,TWFRK,(T2)	;GET FORK WAITING FOR THIS LINE
	CAIE T1,-1		;IS THERE ONE?
	JRST TCIF1		;YES. GO RESOLVE THE CONFLICT

;NO OTHER FORK IS WAITING. GO INTO INPUT WAIT ON THIS LINE
;NOTE: THE TEST ON TTLCK IS A BIG HACK TO KEEP FSIINI HAPPY.
;DON'T TRY TO MAKE USE OF IT FOR ANYTHING ELSE!!
;ALL CALLERS OF TCI SHOULD HAVE CALLED LCKTTY

TCIF2:	STOR T3,TYLMD,(T2)	;SAVE DATA MODE THIS INPUT
	PUSH P,T3		;SAVE DATA MODE
	MOVE T3,FORKX		;GET INDEX OF THIS FORK
	STOR T3,TWFRK,(T2)	;RECORD THIS FORK WAITING FOR TTY
	SETZRO TTFWK,(T2)	;INDICATE NO FORCED WAKEUP
	TDCALL D,<<PT,TCIPTY>,<NT,NETCAP>,<CH,CVTCAP>,<TV,TVTIGA>>
	SETZRO TTWFG,(T2)	;CLEAR WAIT RESTARTED FLAG
	PUSH P,T2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER
	HRL T1,T2		;SAVE LINE NUMBER
	POP P,T2		;RESTORE ADDRESS OF DYNAMIC DATA
;	TMNE TTLCK,(T2)		;DON'T UNLOCK IF IT'S NOT LOCKED
	CALL ULKTTY		;ALLOW DEALLOCATION
	HRRI 1,TCITST		;T1/(LINE NUMBER,,ROUTINE)
	PUSH P,T2
	MOVSI T2,FHV4		;WAIT PRIORITY - BETTER THAN AVERAGE
	HDISMS
	POP P,T2
	POP P,T3		;RESTORE CURRENT MODE
	RET			;GIVE NON-SKIP RETURN TO SAY A BLOCK
				;  OCCURRED

;A FORK IS WAITING FOR INPUT ON THIS TERMINAL. IF IT IS THE CURRENT
;FORK, PROCEED AS USUAL. IF NOT, RESOLVE THE CONFLICT BY HALTING THE
;OTHER FORK IF IT IS INFERIOR TO THIS ONE OR WAITING FOR THE OTHER
;FORK IF IT IS SUPERIOR TO THIS ONE OR IN ANOTHER JOB

TCIF1:	ANDI A,7777
	CAMN A,FORKX		;IS IT THIS FORK?
	JRST TCIF2		;YES. GO TO IT THEN
	CALL ULKTTY		;RELEASE TTY LOCK AND GO OKINT
	CALLRET TTFRKT		;GO RESOLVE CONFLICT BY HALTING FORK
	SUBTTL MISCELLANEOUS ROUTINES

;FORCE WAKEUP OF FORK NOW WAITING FOR SPECIFIED TTY LINE
; 2/ ADDRESS OF DYNAMIC DATA

TTFWAK::PUSH P,FX
	LOAD FX,TWFRK,(2)	;GET INDEX OF FORK IN INPUT WAIT
	CAIN FX,-1		;IS A FORK WAITING?
	JRST TTFW1		;NO
	ANDI FX,7777		;YES, FLUSH FLAGS
	SETONE TWFRK,(T2)	;INDICATE NO FORK WAITING
	SETZRO TTFWK,(T2)	;DON'T FORCE WAKEUP ON THIS FORK
				; UNTIL INPUT BUFFER FULL AGAIN
	CALL TTUBLK		;UNBLOCK THE FORK
TTFW1:	POP P,FX
	RET

;UNBLOCK TTY INPUT FORK ONLY IF STILL WAITING FOR TTY INPUT
; FX/ FORK INDEX
;	CALL TTUBLK
; RETURN +1: ALWAYS, FORK UNBLOCKED IF IN TCITST

TTUBLK:	SAVELN
	MOVE 1,FX		;SETUP ARG
	CALLRET UNBLKF		;TELL SCHED TO UNBLOCK THE FORK

;SCHEDULER TEST ROUTINE FOR FORKS WAITING FOR TTY INPUT
;CALLED WITH JSP 4,
;AC 1 CONTAINS LINE NUMBER
;AC FX CONTAINS FORK NUMBER OF FORK BEING TESTED

TCITST::MOVE T2,T1		;GET LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST 1(4)		;LINE ISN'T ACTIVE. WAKE UP THE PROCESS
	LOAD T1,TWFRK,(T2)	;GET INDEX OF FORK IN INPUT WAIT
	CAIN T1,-1		;IF NONE, WAKEUP
	JRST 1(T4)
	JN <TTFWK,TTWFG>,(T2),1(T4)	;IF FORCED WAKEUP SET, WAKE THE PROCESS
				;WAKEUP IF WE'VE BEEN HERE BEFORE
	SKIPE TTICT(T2)		;WAKEUP IF BUFFER ISN'T EMPTY
TCITS1:	JRST 1(T4)		;WAKE THE PROCESS
	SETONE TTWFG,(T2)	;INDICATE WE'VE BEEN HERE WITHOUT WAKING
	JRST 0(T4)		;DON'T WAKE NOW

;SPECIAL CODE FOR TTY SIMULATORS. THIS ROUTINE PERFORMS THE PROPER
;TESTS FOR THE SPECIAL SIMULATOR. TO USE IT, PUT ITS ADDRESS
;IN THE LINE TYPE VECTOR AT TCIF2+7 AND PATCH IN THE PROPER LINE
;NUMBERS BELOW

TTCTRA:	MOVEI T1,"A"-100	;OUTPUT CHAR IS CONTROL-A
	DYNST (T3)		;GET STATIC DATA IS T3
	CAIL T3,.-.
	CAILE T3,.-.		;WITHIN RANGE?
	RET			;NO. DON'T SEND ^A THEN
	CALLRET TCOUT		;YES. SEND CHARACTER
;'RAISE' INPUT

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T3/ TTFLGS FOR THE LINE

TTRAIS:	TXNE T3,TT%LIC		;IF NOT RAISING INPUT
	CAIGE T1,"A"+40		; OR NOT IN RANGE
	RET			;RETURN UNCHANGED
	CAIG T1,"Z"+40		;IF LOWER CASE ALPHABETIC
	TRZ T1,40		; CONVERT TO UPPER CASE ALPHABETIC
	CAIE T1,.CHALT		;CONVERT OLD ASCII ALTMODE
	CAIN T1,.CHAL2		; AND ALTERNATE FORM
	MOVEI T1,.CHESC		; TO THE ESC CODE
	RET

;GPSICD - GET PSI CODE FOR CHARACTER
; T1/ CHARACTER
;	CALL GPSICD
; RETURN +1 ALWAYS, 
;	T1/ PSI CODE OR -1 IF NOT A POSSIBLE PSI CHAR

GPSICD::CAIL T1,200		;DON'T EVER THINK ABOUT SPECIAL CHARACTERS
	JRST GPSIC2
	CAIG T1," "		;WITHIN NON-PSI CHAR RANGE?
	JRST GPSIC1		;NO
	CAIL T1,175
	JRST GPSIC3		;NO
GPSIC2:	SETO T1,		;YES, RETURN -1
	RET

GPSIC1:	CAIN T1," "		;SPACE?
	SKIPA T1,[^D29]		;YES, RETURN CODE
	CAIG T1,33		;CONTROL CHAR OR ESC?
	RET			;YES, CODE EQUAL CHARACTER
	JRST GPSIC2		;NOT A PSI CHAR

GPSIC3:	CAIN T1,177		;RUBOUT?
	SKIPA T1,[^D28]		;YES, RETURN CODE
	MOVEI T1,^D27		;NO, IS OLD ALT-MODE
	RET

;SKIP IF FLOCHR IS ENABLED AS A PSI
; T2/ DYN PTR

SKCOE:	MOVX CX,1B<FLOCHR>
	TDNN CX,TTPSI(T2)
	RET
	RETSKP

;SKIP IF FLOCHR NOT ENABLED AS A PSI
; T2/ DYN PTR

SKCON:	MOVX CX,1B<FLOCHR>
	TDNE CX,TTPSI(T2)
	RET
	RETSKP
;FULL (12 BIT) CHARACTER INPUT 
; CALLED FROM MTOPR
;
TTIFCI::CALL TCIB		; READ A CHARACTER AND PROCESS AS IF BINARY
	RETBAD			; NEED TO BLOCK
	MOVE T3,TTTMOD(T2)	; IS INTELLIGENT TERMINAL PROTOCOL IN USE?
	TXNN T3,TM%ITP
	JRST TTFCI1		; ASCII TERMINAL, MAY HAVE META KEY
	LOAD T1,TIFCH,(T2)	; GET FULL 12-BIT CHARACTER
	RETSKP			; AND RETURN THAT

TTFCI1:	TRZE T1,200		; META BIT SET?
	TRO T1,400		; YES, SET 12-BIT FORM OF IT
	RETSKP
	SUBTTL TTCH7 (EMPTY TTBBUF, PROCESS TTCS WORDS)

;TELETYPE INPUT CHANNEL 7 ROUTINE
;RUN EVERY SO OFTEN TO MOVE CHARACTERS FROM BIG BUFFER TO LINE BUFFERS,
;GENERATE ECHOS AND HANDLE CARRIER TRANSITIONS
;ENTERED BY CALL FROM SCHED
;CALLED IN SCHEDULER CONTEXT

TTCH7::	SKIPG TTBIGC		;BIG BUFFER EMPTY?
	JRST TTCH7X		;YES, RETURN
	AOS T3,TTBIGO		;NO. INCREMENT POINTER TO LOAD FROM
	CAIN T3,TTBSIZ		;AT END OF TTBBUF?
	SETZB T3,TTBIGO		;YES. POINT TO START OF TTBBUF
	MOVE T1,TTBBUF(T3)	;GET NEXT ENTRY
	SOS TTBIGC		;DECREMENT COUNT OF ENTRIES
	HLRZ T2,T1		;GET LINE NUMBER
	MOVEI Q2,0(T1)		;SAVE ALL ORIGINAL FLAGS
	DECR TTFBB,(T2)		;REDUCE LINE'S COUNT OF TTBBUF ENTRIES
	JN TTFXO,(T2),[		;SEND XON IF NEEDED
		CALL SNDXNS	;SEND XON IF NEEDED
		JRST .+1]
	TRNE T1,TTPIRQ		;NON CONTROLLING TERMINAL PSI?
	JRST [	CALL STADYN	;CONVERT TO DYNAMIC DATA POINTER
		 JRST TTCH7	;NONE
		LOAD T1,TTOPSI,(T2) ;GET PSI
		LOAD T2,TTPSFK,(T2) ;GET FORK
		CAIE T2,-1
		CALL PSIRQ	;IF FORK SETUP, REQUEST INTERRUPT
		JRST TTCH7]	;AND TRY NEXT
	TRNE T1,TTOIRQ		;OUTPUT INTERRUPT REQUEST?
	JRST [	MOVX T3,.TICTO	;YES. OUTPUT BUFFER WENT EMPTY AND PROCESS
		CALL TTPSRQ	; ENABLED FOR INTERRUPT. ISSUE IT
		JRST TTCH7]	;DONE WITH WORD
	TRNE T1,DLSCXF		;CARRIER TRANSITION?
	JRST [	JN TTFEM,(T2),TT7CX ;+++ YES, HANDLE IF REMOTE
		JRST .+1 ]	;+++ ELSE IGNORE
	TRNN T1,DLSRCF		;RECEIVER?
	JRST TTCH7		;NO (SHOULD NOT HAPPEN) - RESUME  SCAN

;A CHARACTER WAS FOUND. SAVE IT IN 8 BITS AND GO STORE IN BUFFER.
;THEN GO GET NEXT WORD FROM TTBBUF

	ANDI T1,377		;GET 7 BITS OF CHARACTER + PARITY
	CALL TTCHI		;PUT CHAR IN LINE BFR
	 NOP			;IGNORE FAILURE
	JRST TTCH7		;DO NEXT
;SEND XON IF NECESSARY
; SNDXON
;	T2/ DYNAMIC
;SNDXNS
;	T2/ STATIC

SNDXON:	SAVEAC <T2>
	DYNST
	JE TTFXO,(T2),R		;DO NOTHING IF NOT XOFF'D
SNDXNS:	TDCALL S,<<FE,SNDXN2>,<MC,MCSXON>,<DZ,DZSXON>> ;SEND XON IF NEEDED
	RET
;TTCH7..

;TTBBUF IS EMPTY. DO DEVICE DEPENDENT FUNCTIONS IF NEEDED

TTCH7X:	CALL CKQLN		;CHECK QUEUED LINES
	CALL TTYQOC		;START OUTPUT ON QUEUED LINES
  IFN .MCFLG,<
	CALL MCSRV>		;PROCESS DATA FROM NET
	SKIPGE TTQCNT		;HAVE SOME SCANNING TO DO?
	RET			;NO. ALL DONE THEN

;BEFORE LEAVING, CHECK 8 LINES TO SEE IF THERE IS A SHORT BLOCK TO RELEASE

TTHNG4:	MOVE T2,TTCQLN		;GET NEXT LINE TO BE CHECKED
	MOVEI T4,10		;LIMIT OF 10 LINES FOR THIS PASS
TTCQ3:	SKIPGE TTQCNT		;ALL DONE?
	JRST TTCQ5		;YES, GO SAVE LINE NUMBER AND RETURN
	CALL CKSBK		;CHECK FOR SHORT BLOCK

;GO TO NEXT LINE. IF THE LINE TYPE CHANGES, DON'T PROCEED WITH THE NEW
;LINE. INSTEAD, GO TO THE NEXT LINE TYPE AFTER THE ONE JUST PROCESSED.
;THIS CODE ASSUMES THAT ALL LINES OF A GIVEN TYPE ARE NUMBERED CONSECUTIVELY.

TTCQ2:	LOAD T3,TTSTY,(T2)	;NO. GET CURRENT TYPE
	ADDI T2,1		;GO TO NEXT LINE ;1005 GET THE RIGHT ACC!
	CAIL T2,NLINES		;VALID LINE NUMBER?
	JRST TTCQ6		;NO. GO TO NEXT LINE TYPE
	LOAD T1,TTSTY,(T2)	;GET TYPE OF NEXT LINE
	CAMN T3,T1		;NEW TYPE?
	JRST TTCQ1		;NO. GO ON

;FINISHED THE CURRENT LINE TYPE OR THE CURRENT TYPE IS NOT TO BE PROCESSED
;GO TO THE NEXT TYPE AND SEE IF IT IS TO BE PROCESSED

TTCQ6:	AOS T3			;GO TO NEXT LINE TYPE
	CAIL T3,NLTYPS		;BEYOND END OF LEGAL TYPES?
	SETZ T3,		;YES. GO BACK TO BEGINNING
	MOVE T2,TT1LIN(T3)	;GET FIRST LINE OF THIS TYPE
	JUMPL T2,TTCQ6		;IF LINE GROUP IS NOT HERE, GO GET NEXT

;PROCESS THIS LINE UNLESS WE HAVE DONE ENOUGH FOR THIS PASS

TTCQ1:	SOJG T4,TTCQ3		;DONE ENOUGH FOR THIS TIME?
TTCQ5:	MOVEM T2,TTCQLN		;YES, START AT THIS LINE NEXT TIME
	RET
;TTCH7...
CKSBK:	SAVET
	CALL STADYN		;POINT TO DYNAMIC DATA
	 SKIPG T2		;NOT FULLY ACTIVE.  ANY DYNAMIC DATA?
	RET			;INACTIVE, BECOMING ACTIVE, OR FULL-LENGTH
	JN <TTLCK,TTSAL>,(T2),R ;DON'T RELEASE IF DOING SENDALL OR LOCKED
	JN TTSHT,(T2),DOLIN2	;IF SHORT AND SENDALL DONE, RELEASE BLOCK
	CALL TTSOBE		;IS OUTPUT COMPLETE?
	 RET			;NOT FINISHED WITH THE BLOCK YET

;HAVE A MESSAGE BLOCK.  RELEASE THE BLOCK AND RELEASE THE ASSOCIATED
;OUTPUT BUFFERS (IF ANY)

	SKIPE T3,TTOOUT(T2)	;RELEASE OUTPUT BUFFERS IF ANY
	CALL TTRLBF		; ARE ASSIGNED

;READY TO RELEASE THE BLOCK.  T2 HAS ITS ADDRESS

DOLIN2:	MOVE T1,T2		;T1/ ADDRESS OF BLOCK TO RELEASE
	DYNST			;GET LINE NUMBER
	SETZM TTACTL(T2)	;INDICATE NO DATA FOR THIS LINE
	CALL RELRES		;RELEASE THE BLOCK
	SOS TTQCNT		;ONE MORE DONE
	RET
;TTCH7..

;TTQAD - ADD ITEM TO CONTROL QUEUE

;ACCEPTS:
;	T1/ TIME UNTIL EVENT (ACTUAL MAY BE LONGER)
;	T2/ INTERNAL LINE NUMBER
;	T3/ ROUTINE TO BE CALLED AT GIVEN TIME
;	  N.B. - ROUTINE MUST BE IN TABLE HEREIN

;	CALL TTQAD (TTQAD1 FOR DEFAULT TIME LIMIT)

;RETURNS +1: ALWAYS

TTQAD1:	MOVEI T1,^D3000		;ITEM TO BE DONE IN 3 SEC.
TTQAD:	SAVEAC <T4>
	ADD T1,TODCLK		;COMPUTE ABSOLUTE TIME TO DO FUNCTION
	CAMLE T1,TTCSTM(T2)	;LATER THAN NOW SET?
	MOVEM T1,TTCSTM(T2)	;YES, SAVE TIME FOR DOING THE FUNCTION
	MOVSI T4,-NTQFN		;SCAN TABLE FOR SPECIFIED ROUTINE
TTQAD2:	CAMN T3,TQFNT(T4)	;THIS ONE?
	JRST TTQAD3		;YES
	AOBJN T4,TTQAD2		;NO
	BUG(TTQADX,<<T3,ADR>>)	;UNKNOWN FUNCTION
	RET

TTQAD3:	MOVE T1,BITS(T4)	;GET BIT TO REPRESENT FUNCTION
	IORM T1,TTCSAD(T2)	;SET IT
	MOVE T3,T2
	IDIVI T3,^D36		;GET LOCATION IN BIT MATRIX
	MOVE T4,BITS(T4)
	IORM T4,TQLNQ(T3)	;NOTE LINE NEEDS SERVICE
	RET
;SERVICE QUEUED LINES

CKQLN:	SAVEAC <P1,P2,P3>
	MOVSI P1,-NTSQWD	;SET TO SCAN BIT MATRIX
CKQL1:	SKIPE T1,TQLNQ(P1)	;ANY LINES HERE?
CKQL2:	JFFO T1,CKQL3		;YES, GET ONE
	AOBJN P1,CKQL1
	RET

CKQL3:	MOVE P2,BITS(T2)	;GET BIT FOR LINE
	HRRZ T3,P1
	IMULI T3,^D36		;COMPUTE LINE NUMBER
	ADD T2,T3
	MOVE T1,TODCLK
	CAMGE T1,TTCSTM(T2)	;TIME TO DO FUNCTION
	JRST CKQL4		;NO, MOVE ON TO NEXT LINE
	ANDCAM P2,TQLNQ(P1)	;REMOVE LINE FROM ATTENTION TABLE
	SKIPE T3,TTCSAD(T2)	;ANY FUNCTIONS REQUESTED?
CKQL5:	JFFO T3,CKQL6		;FIND A FUNCTION TO DO
CKQL4:	MOVN T1,P2		;LOOK AT REST OF WORD ONLY
	ANDCA T1,TQLNQ(P1)
	JRST CKQL2

CKQL6:	MOVE P3,BITS(T4)	;SAVE FUNCTION BIT
	ANDCAM P3,TTCSAD(T2)	;CLEAR FUNCTION REQUEST (MAY BE SET AGAIN BY ROUTINE)
	HRRZ T1,TQFNT(T4)	;GET ROUTINE ADDRESS
	CALL [	SAVEAC <T2>	;SAVE LINE NUMBER
		CALLRET 0(T1)]	;DO FUNCTION
	MOVE T1,TODCLK
	CAMGE T1,TTCSTM(T2)	;TIME BUMPED?
	JRST CKQL4		;YES, QUIT THIS LINE
	MOVN T3,P3		;LOOK AT REST OF BITS
	ANDCA T3,TTCSAD(T2)
	JRST CKQL5

;TABLE OF KNOWN TTQAD FUNCTIONS - MAXIMUM 36

TQFNT:	TTTOBL
	TTSN10
	TTCOF
	TTCON1
	DZHU2
	NTYCOF
	CKSALL
NTQFN==.-TQFNT
IFG NTQFN-^D36,<PRINTX TQFNT TOO LARGE>
;ROUTINE CALLED ONCE A SECOND TO DO CONTROLLER DEPENDENT FUNCTIONS

TTYCHK::PUSH P,Q1		;DO CHECKS FOR DEVICES
	PUSH P,Q2
	MOVSI Q1,-NLTYPS	;CALL FOR ALL DEVICES
	MOVEI T1,SCNTIM		;TIME FOR NEXT SCAN
	MOVEM T1,TTYTIM
TTLILP:	TDCALX Q1,<<DZ,DZCH7D>>,<RET>
	AOBJN Q1,TTLILP		;ALL DEVICES
	POP P,Q2		;RESTORE
	POP P,Q1
	RET			;AND DONE
;TTCH7..

;WORD IN TTBBUF INDICATED CARRIER TRANSITION (DLSCXF WAS SET).
;IF CARONB IS SET, CARRIER WENT ON. IF NOT, CARRIER WENT OFF

TT7CX:	TRNN T1,CARONB		;DID CARRIER JUST COME ON?
	JRST TTCX1		;NO, OFF

;CARRIER WENT ON. IF THE LINE IS IN USE OR A JOB IS BEING
;CREATED ON IT, DON'T GO CREATE ANOTHER JOB ON IT

	SETONE TTCON,(T2)	;SET CARRIER ON FOR THIS LINE
	TDCALL S,<<FE,RSKP>,<DZ,DZ7CX2>>
	 JRST TTCH7		;DO NOTHING
	CALL TTCON1		;CREATE JOB
	JRST TTCH7		;DONE

;TTCON1 - CREATE JOB AS RESULT OF CARRIER COMING ON

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTCON1

;RETURNS +1: ALWAYS

;CARRIER HAS COME ON FOR REAL. TREAT THIS LIKE A CTRL/C AND CREATE
;A JOB IF POSSIBLE

TTCON1:	MOVEM B,C		;SAVE LINE NUMBER
	CALL STADYN		;SEE IF THE LINE IS INACTIVE
	 SKIPE B		;YES. CREATE JOB ON IT IF ALLOWED
	RET			;ACTIVE OR BECOMING ACTIVE. IGNORE CARRIER-ON
	MOVE B,C		;RESTORE LINE NUMBER
	MOVE A,FACTSW		;SEE IF REMOTE LOGINS ALLOWED
	TXNN A,SF%RMT		;...
	JRST [	HRROI A,[ASCIZ /
?LOGGING IN ON DATASETS IS CURRENTLY DISALLOWED.
/]
		CALL TTEMSS	;NO. SAY SO
		RET]		;DONE
	SETONE TTFSP,(B)	;SAY LINE NEEDS SPEED SET
	CALL TTC7SK		;GO CREATE JOB
	 JFCL			;ALWAYS DOES RETSKP
	RET
;TTCH7...

;CARRIER WENT OFF

TTCX1:	JE TTCON,(B),TTCH7	;IF CARRIER WASN'T ALREADY ON, IGNORE IT
	SETZRO TTCON,(B)	;INDICATE CARRIER NO LONGER ON
	TDCALL S,<<FE,RSKP>,<DZ,DZCX2>,<ML,RSKP>,<TV,RSKP>,<CH,RSKP>,<NT,RSKP>>
	 JRST TTCH7		;NOTHING TO DO NOW
	CALL NTYCOF		;DO IT
	JRST TTCH7

;TTCOF - ROUTINE TO SEE IF CARRIER IS STILL OFF.  SCHEDULED (VIA TTQAD)
;TO BE CALLED FOR A LINE WHEN CARRIER GOES OFF ON THE LINE
;NOT USED FOR FRONT END LINES

;ACCEPTS:
;	T2/ LINE NUMBER

;RETURNS +1: ALWAYS
;		T2/ LINE NUMBER

TTCOF:	JN TTCON,(B),R		;IF CARRIER IS BACK ON NOW, DON'T HANGUP
	CALL NTYCOF
	CALLRET TTHU0		;DO HANGUP-REACTIVATE

;
; REMTCJ -- Flush terminal controlling job
; used to clear controlling job value without otherwise
; disturbing the dynamic data (currently only from .ATACH)
; called
;	T2/	Dynamic data
;
REMTCJ::
	SETONE TCJOB,(T2)		; Clear it
	RET				; and return
;NTYCOF - HANDLE CARRIER OFF

;ACCEPTS:
;	2/INTERNAL LINE NUMBER

;	CALL NTYCOF

;RETURN +1: ALWAYS,
;		T2/ LINE NUMBER

;CALLED WHEN CARRIER GOES OFF FOR ANY PHYSICAL LINE. FLUSHES OUTPUT,
;ISSUES AN INTERRUPT IF A PROCESS HAS ENABLED FOR CARRIER-OFF INTERRUPT,
;ISSUES A MONITOR-INTERNAL INTERRUPT THAT CAUSES THE TOP FORK
;TO GO TO JOBCOF IN MEXEC

;ALSO CALLED FOR A LINE ASSOCIATED WITH A PTY WHEN THE PTY IS CLOSED.

NTYCOF::CALL TTCOB1		;FLUSH OUTPUT
	CALL CHKCTT		;SEE IF THIS IS A CONTROLLING TERMINAL
	 CALLRET TTJBDT		;NO. DON'T ISSUE INTERRUPT
	MOVE B,C		;YES. B/ADDRESS OF DYNAMIC DATA
	MOVEI C,.TICRF		;C/CODE FOR THIS CONDITION
	MOVE A,BITS(C)		;GET THE BIT
	PUSH P,B		;SAVE ADDRESS OF DYNAMIC DATA
	TDNE A,TTPSI(B)		;IS THE CODE ENABLED?
	CALL TTPSI2		;YES. GIVE THE INTERRUPT
	POP P,B			;RESTORE ADDRESS OF DYNAMIC DATA
	DYNST			;GET BACK THE LINE NUMBER
	CALLRET TTJBDT		;GO DETACH JOB

;TTJBDT - ROUTINE TO GENERATE AN INTERRUPT WHEN CARRIER GOES OFF

;ACCEPTS:
;	T2/ LINE NUMBER

;RETURNS +1: ALWAYS
;		T2/ LINE NUMBER

;ISSUES AN INTERRUPT TO THE TOP FORK IN THE JOB. CAUSES THE JOB TO
;BE DETACHED

TTJBDT:	CALL TTCOB1		;CLEAR OUTPUT BUFFERS
	CALL CHKCTT		;SEE IF THIS IS A CONTROLLING TERMINAL
	 RET			;NO
	SETONE TOFLG,(T3)	;FLUSH SUBSEQUENT OUTPUT
   REPEAT 0,<			;FOLLOWING CODE DOES NOT
				;WORK BECAUSE IT CAUSES PAGE
				;FAULTS IN SCHEDULER. NEED TO
				;MOVE THIS ELSEWHERE SOME DAY
	TMNE TTAUT,(B)			;IS THIS AN AUTO SPEED LINE?
	SETOM TTSPWD(B)		;YES. INIT SPEED
   >				;END OF REPEAT 0
	PUSH P,B		;SAVE LINE NUMBER
	HRRZ B,JOBPT(A)		;GET TOP FORK INDEX
	MOVX T1,FKPSI0+PSICO%
	IORM 1,FKINT(B)		;REQUEST CARRIER OFF ACTION
	CALL PSIR4
	POP P,B			;RESTORE LINE NUMBER
	RET
;TTCH7..

;CHKCTT - CHECK TO SEE TERMINAL IS A CONTROLLING TERMINAL FOR A JOB

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL CHKCTT

;RETURNS +1: NOT A CONTROLLING TERMINAL
;		T2/ LINE NUMBER
;	 +2: CONTROLLING TERMINAL,
;		T1/ JOB NUMBER
;		T2/ LINE NUMBER
;		T3/ ADDRESS OF DYNAMIC DATA

CHKCTT:	SASUBR <CHKCJN,CHKCSV,CHKCSD>
	SETOM CHKCJN		;SAY NO CONTROLLING JOB
	CALL STADYN		;POINT TO DYNAMIC DATA
	 RET			;NOT ACTIVE
	LOAD C,TCJOB,(B)	;GET OWNING JOB
	CAIN C,-1		;IS THERE ONE?
	RET			;NONE.
	MOVEM C,CHKCJN		;SAVE JOB NUMBER
	MOVEM B,CHKCSD		;RETURN DYNAMIC PTR
	HLRZ A,JOBPT(C)		;GET CONTROLLING TERMINAL FOR JOB
	CAMN A,CHKCSV		;IS THIS THE CONTROLLING TERMINAL?
	RETSKP			;YES, SUCCESS
CHKCT1:	RET			;FAILURE RETURN

	ENDSA.			;END SASUBR

;TTHU0 - HANGUP-REACTIVATE SEQUENCE

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL TTHU0

;RETURNS +1: ALWAYS

;SCHEDULED BY TTCOF WHEN A LINE HAS LOST CARRIER. CAUSES HANGUP OF THE
;LINE FOLLOWED BY ACTIVATE

TTHU0:	TDCALL S,<<FE,TTHU2>,<NT,NVTDTS>,<DZ,DZHU0>,<ML,MLCDE1>,<CH,NVTDTS>,<TV,TVTDTS>>
	RET
	SUBTTL TTCHI (MOVE CHAR FROM TTBBUF TO INPUT BUFFER)

;TTCHI - PROCESS CHARACTER AS INPUT

;ACCEPTS:
;	T1/ CHARACTER IN 8 BITS
;	T2/ INTERNAL LINE NUMBER
;
;	CALL TTCHI
;
;RETURNS +1: ALWAYS
;		T2/ LINE NUMBER
;
;CALLED BY TTCH7 WHEN A CHARACTER HAS BEEN FOUND IN TTBBUF
;INITIATES AN INTERRUPT IF NEEDED; ECHOES IF APPROPRIATE;
;WAKES UP WAITING PROCESS IF NEEDED; STORES CHARACTER IN LINE BUFFER
; 

;CALLED FROM SCHEDULER CONTEXT AND PROCESS CONTEXT
;IF IN PROCESS CONTEXT, MUST BE NOSKED, SO THAT THE SETTING AND
;TESTING OF TCOERR IN TCOUT WILL BE CONSISTENT

;TTCHID - ALTERNATE ENTRY POINT, T2/ DYNAMIC PTR

TTCHID:	SAVEAC <T2,Q1,FX>
	DYNST			;GET LINE NUMBER
	JRST TTCHD1

TTCHI:	CAIL 2,NLINES		;REASONABLE LINE?
	RET			;NO
	SAVEAC <T2,Q1,FX>
TTCHD1:	STKVAR <TTCHSV,TTCHFL>	;MUST COME AFTER SAVELN
	MOVEM T2,TTCHSV		;SAVE LINE NUMBER
;;	MOVEM T1,TTCHIC		;SAVE ORIGINAL CHARACTER
;;	ANDI T1,377		;USE 8 BITS FOR LOCAL COMPARES
	CALL STADYN		;IS THIS A FULLY ACTIVE LINE?
	 JRST TTC7N		;NO. GO HANDLE THIS CASE SEPARATELY
	JN TTNUS,(T2),TTNU1	;JUMP IF NETWORK USER STATE
	MOVE T3,TTTMOD(T2)	;CHECK WHETHER ITP PROCESSING IS DESIRED
	TXNN T3,TM%ITP
	JRST [	MOVEM T1,TTCHIC ; NO, SAVE INPUT CHAR
		ANDX T1,177	; USE 7 BITS FOR LOCAL COMPARES
		JRST TTCHI0]	; GO DO PROCESSING
	CALL TTIITP		;EXECUTE INPUT PROCESSING ROUTINE
	RET			; +1 RETURN - NO CHARACTER, RETURN ERROR
	MOVEM T3,TTCHIC		; +2 RETURN
				;	CHAR FOR LINE BUFFER IN T3
				;	CHAR FOR TESTS IN T1 - ASSUMED 7 BITS
				;	CHAR WITH 200 BIT SET WILL NEVER
				;	 TRIGGER INTERRUPT OR PAGE PROCESSING
; TTCHI...
;CHECK FOR SPECIAL FUNCTION CHARACTERS
;
; FROM HERE ON IN, T1 IS THE CHAR IN 7 BITS. THE 200 BIT WILL BE
; SET IF THE CHAR SHOULD BE IGNORED BY THE FOLLOWING TESTS

TTCHI0:	MOVE T3,TODCLK		;171 GET TIME
	MOVEM T3,TTIDLE(T2)	;171 REMEMBER IT
	JE TTPRM,(T2),TTCHI2	;PERMANENT DATA?
	LOAD T3,TCJOB,(T2)	;YES. GET CONTROLLING JOB
	CAIN T3,-1		;IS THERE ONE?
	JRST TTC7N		;NO, MAYBE START ONE

; CHECK FOR TERMINAL INTERRUPT CHARACTER
TTCHI2:	CALL TTCHIT		;INTERRUPT CHAR?
	JRST TTCH11		;YES, GO PROCESS
				;NO, FALL THROUGH

; SEE IF ANY PAUSE OR UNPAUSE FUNCTIONS REQUIRED
	JE TT%PGM,TTFLGS(T2),TTCHI1	; BYPASS IF NOT IN DISPLAY MODE
	CALL TTCHPF		; HANDLE PAUSE/UNPAUSE CHARACTERS
	JRST [	CALL TTITPK	; USED CHAR, CLEAN OUT LINE BUFFER
		RETSKP]		; AND RETURN

; SEE IF ^O ACTION NEEDED	
TTCHI1:	CALL TTCHOA		; CHECK FOR ^O AND DO PROPER ACTION
	JRST [	CALL TTITPK	; YES, MAYBE CLEAN OUT LINE BUFFER
		RETSKP]		; EAT CHAR AND RETURN
	JRST TTCHI6		; REAL CHARACTER, GO PROCESS IT
;TTCHI...

; CHECK FOR INTERRUPT CHAR
;	T1/ CHAR IN 7 BITS
;	T2/ DYN DATA
;	T1 PRESERVED
; RETURN +1/ CHAR IS INTERRUPT CHAR, +2/ NOT

TTCHIT:	MOVE T3,T1		;COPY CHAR
	CALL GPSICD		;GET PSI CODE FOR CHAR
	EXCH T1,T3		;T1/CHARACTER, T3/CODE OR -1
	JUMPL T3,TCHIC1		;-1 MEANS NO CODE
	MOVE Q1,BITS(T3)	;BIT FOR THIS CODE
	TDNN Q1,TTPSI(T2)	;CODE ENABLED?
TCHIC1:	AOS (P)			;NO, SKIP RETURN
	RET			;YES, +1 RETURN

;CHECK FOR ^O AND ACT IF FOUND
;	T1/ CHAR
;	T2/ DYN DATA
;	T1 PRESERVED
; RETURN +1, ^O FOUND, +2 NOT

TTCHOA:	SKIPE CTRLOF		;NEW CTRL-O HANDLING?
	CAIE T1,FLOCHR		;AND A CTRL-O?
	RETSKP			;NO

;WE HAVE A ^O AND WE WANT MONITOR HANDLING OF IT.  ^O IS A TOGGLE, SO
;WE DO SOMETHING DIFFERENT DEPENDING ON ITS CURRENT STATE.

	CALL CKPHYD		;PTY?
	 RETSKP			;YES, DO NOTHING
	CALL [	SAVEAC <T1>	;YES
		CALLRET TTXONA]	;CLEAR POSSIBLE XOFF
	TMNN TTFLO,(T2)		;ALREADY FLUSHING OUTPUT?
	IFSKP. <
	  CALL CLOFLG		;YES, DO MARKER
	  RET>
	MOVE T1,[POINT 7,[BYTE (7)"[","^","O",".",".",".",.CHDEL]]
	MOVEM T1,TTSAL2(T2)	;SEND INDICATION (WITH FILLS ON CR AND LF)
	SETONE TTHPO,(T2)	;NOTE HP OUTPUT QUEUED
	SETONE TTFLO,(T2)	;FLUSH OUTPUT
	LOAD T3,TWFRK,(T2)	;SEE IF A FORK WAITING
	CAIE T3,-1
	CALL CLOFLG		;YES, PUT MARKER THROUGH
	RET
;TTCHI...
;CHECK FOR PAUSE OR UNPAUSE FUNCTIONS
;	T1/ CHAR 
;	T2/ DYN DATA
;	T1 PRESERVED
;RETURNS +1, CHAR WAS FUNCTION, FUNCTION PERFORMED
;	 +2, CHAR WASN'T A PAUSE/UNPAUSE FUNCTION

TTCHPF:	
; CHECK FOR XOFF/XON AND HANDLE QUICKLY
	CAIN T1,PGMONC		;XON?
	IFNSK.
	  LOAD T3,TTUPC,(T2)	;YES, SEE IF PAGE UNPAUSE CHARACTER TOO
	  CAIE T3,PGMONC
	  CALLRET TTXONC	;NO, XON COMMAND ONLY
	  CALLRET TTXONA	;YES, BOTH
	ENDIF.
	CAIE T1,PGMOFC		;MAYBE XOFF
	JRST TTCHP1		;NO, GO CHECK PAGE CHARACTERS
	JN TTRXF,(T2),R		;YES, SEE IF ALREADY STOPPED
	SETONE TTRXF,(T2)	;YES. INDICATE FRONT-END XOFF
	TMNN <TTSAL,TTHPO>,(T2)	;SPECIAL OUTPUT GOING?
	IFNSK. <
	  TDCALL D,<<FE,TTCHI3>,<MC,MCLNOF>> ;NO, STOP THE LINE
	 >,<
	  TDCALL D,<<FE,TTXON1>,<MC,MCLNON>>> ;YES, RESTART THE LINE
	RET

;CHECK PAGE PAUSE/UNPAUSE CHARACTERS
TTCHP1:	JE TTNXO,(T2),RSKP	;BYPASS IF NOT IN PAUSE EOP MODE
	JN TMMOR,(T2),TTCHP2	;JUMP IF ITS PAGING MODE
	LOAD T3,TTUPC,(T2)	;GET PAGE UNPAUSE CHARACTER
	CAME T1,T3		;IS THIS AN UNPAUSE ON PAGE CHARACTER?
	IFSKP.
	  TMNN TTSFG,(T2)	;ALREADY PAUSING?
	  IFSKP.
	    CALL TTXONP		;YES, RESTART OUTPUT
	    RET			;RETURN NOW, LOSE CHARACTER
	  ENDIF.
	  LOAD T3,TTPPC,(T2)	;NOT PAUSING NOW,
	  CAME T1,T3		;THIS THE PAUSE CHARACTER TOO?
	  IFSKP.
	    CALL TTXOFP		;YES, MAYBE PAUSE NOW
	    IFSKP. <RET>	;RETURN NOW IF PAUSED
	  ENDIF.
	ENDIF.
	LOAD T3,TTPPC,(T2)	;GET PAGE PAUSE CHARACTER
	CAME T1,T3		;AND PAUSE CHARACTER?
	IFSKP.
	  CALL TTXOFP		;YES, MAYBE PAUSE NOW
	  IFSKP. <RET>		;DID PAUSE, LOSE CHARACTER
	ENDIF.
	RETSKP			;DIDN'T DO ANYTHING WITH CHAR
;DO ITS-STYLE PAGING
TTCHP2:	JE TTSFG,(T2),RSKP	;NOT STOPPED, RETURN CHAR
	PUSH P,T1		;3002 SAVE CHARACTER
	CALL TTXONA		;3002 RESTART OUTPUT
	POP P,T1		;3002 GET CHAR BACK
	JE TMMSM,(T2),TTCHP3	;3002 SKIP THIS IF NO SMART MORE PROCESSING
	MOVX T4,1B<.TICMR>	;3002 BIT FOR INTERRUPT ON PAGE-FLUSH
	CAIN T1,.CHDEL		;3002 CHECK FOR DELETE
	TDNN T4,TTPSI(T2)	;3002 INTERRUPT ENABLED?
	JRST TTCHP3		;3002 NO OR NO, SKIP THIS
	MOVX T3,.TICMR		;3002 YES, REQUEST IT
	SAVET			;3002 SAVE DYN DATA ADDRESS
	DYNST			;3002 T2/ INTERNAL LINE NUMBER
	CALLRET TTPSRQ		;3002 REQUEST INTERRUPT, EAT CHARACTER

TTCHP3:	CAIN T1," "		;3002 NO INTERRUPT - CHAR WAS SPACE?
	RET			;3002 YES, LOSE IT
	RETSKP			;3002 NO, PUT IT IN BUFFER
;TTCHI...
;HERE TO HANDLE NORMAL CHARACTER

TTCHI6:	AOS NTTYIN		;COUNT INPUT
	TRNE T1,200		;221 UNLESS A PREFIX CHAR
	JRST TCHI6A		;221
	SETONE TILAC,(T2)	;221 NO DEFERRED INTERRUPT 

TCHI6A:	LOAD T3,TYLMD,(T2)	;CHECK MODE NOW IN FORCE
	CAIE T3,.TTBIN		;BINARY?
	JRST TTCHI4		;NO.
TTMCI1:	LOAD T3,TIMAX,(T2)	;YES. GET CAPACITY OF INPUT BUFFER
	CAMLE T3,TTICT(T2)	;ROOM FOR CHAR IN INPUT BUFFER?
	JRST TTCHI9		;YES. GO PUT IT IN
	RET			;NO. LOSE CHARACTER

;SOME TRANSLATION (OUTPUT OR ECHOING OR BOTH) IS REQUIRED BY TERMINAL
;DATA MODE. SEE IF ECHOING IS REQUIRED

TTCHI4:	JUMPE T1,RSKP		;FLUSH NULLS ASAP
	LOAD T3,TIMAX,(T2)	;CAPACITY OF INPUT BUFFERS
	CAMG T3,TTICT(T2)	;FULL?
	JRST TTCH12		;YES, ECHO BELL
	MOVE T3,TTFLGS(T2)
	TRNE T3,TT%DUM		;REGULAR FDX LINE?
	JRST TTCHI7		;HDX - 'ECHO' IMMED
	TRNN T3,TT%ECO		;ECHOS ON?
	JRST TTCHI9		;NO
	TRNE T3,TT%ECM		;STANDARD ECHO MODE?
	JRST TTCHI7		;NO, IMMEDIATE ALWAYS
	LOAD T4,TWFRK,(T2)	;GET WAITING FORK IF ANY
	CAIN T4,-1		;IS THERE A WAITING FORK?
	JRST TTCHI9		;NO. DON'T ECHO NOW
	; ..
;EITHER IMMEDIATE ECHOING IS REQUIRED OR DEFERRED IS REQUIRED AND
;A FORK IS IN INPUT WAIT ON THIS TERMINAL. ECHO THE CHARACTER NOW
;AND SET TTXECO WITH THE CHARACTER IN TTCHIC. THIS WILL BE STORED
;IN THE LINE BUFFER SO THAT TCI WILL NOT ECHO IT AGAIN

	; ..
TTCHI7:	CALL CLOFLG		;CLEAR CTRL-O FLAG IF NECESSARY
	MOVE T3,TTFLGS(T2)	;GET FLAGS FOR TTRAIS
	SETOM IMECHF		;FLAG ECHO CHARACTER FOR TCOUT
	CAIN T1,.CHCRT		;CR?
	 JRST [	SETZM TCOERR	;INIT ERROR INDICATOR
		CALL TCOE	;YES, ECHO CR-LF
		MOVEI T1,.CHLFD	;ECHO THE LINE FEED
		JRST TTCHI8]
	CALL TTRAIS		;RAISE FOR ECHO IF NECESSARY
TTCHI8:	SETZM TCOERR		;INIT ERROR INDICATOR
	SETZM TTCHFL		;INITIALIZE ECHO INDICATOR
	PUSH P,T1		;SAVE CHAR
	TXNN T1,200		;DON'T ECHO SPECIAL CHARACTER
	CALL TCOE		; ELSE ECHO VIA NORMAL OUTPUT STREAM
	POP P,T1		;GET CHAR BACK
	SKIPE TCOERR		;DID TCOUT FAIL?
	 JRST [	SETZM IMECHF	;FAILED TO ECHO. RESET IMMEDIATE ECHO FLAG
		SETOM TTCHFL	;INDICATE CHARACTER NOT ECHOED
		JRST TTCHI9]	;GO STORE CHARACTER WITHOUT MARKING IT ECHOED
	MOVEI T4,TTXECO		;CHARACTER WAS ECHOED. INDICATE IT
	IORM T4,TTCHIC		; SO THAT TCI WON'T ECHO IT LATER
	SETZM IMECHF		;RESET IMMEDIATE ECHO INDICATOR
	; ..
 ;TTCHI..

;HERE IF THE CHARACTER IS NOT AN INTERRUPT CHARACTER, OR THE
;JOB HAS ENABLED ONLY FOR DEFERRED INTERRUPT ON THE CHARACTER
;IF ECHOING WAS REQUIRED, IT HAS BEEN DONE
;GET INPUT BUFFER IF NEEDED; PUT CHAR IN BUFFER

;	T2/ ADDRESS OF DYNAMIC DATA

	;..
TTCHI9:	SKIPN T3,TTIIN(T2)	;INPUT BUFFERS EXIST?
	JRST [	LOAD T3,TTNIN,(T2);NO, GET NUMBER TO ASSIGN
		CALL TTGTBF	;ASSIGN THEM
		 JRST TTCH12	;NO BUFFERS, DING
		MOVEM T3,TTIOUT(T2) ;SAVE BYTE POINTER FOR REMOVING CHARACTERS
		JRST .+1]
	HRRZ T4,T3		;AT END OF BUFFER?
	TDNN T3,WRPMSK
	HRR T3,1-TTSIZ(T4)	;YES. POINT TO NEXT BUFFER IN CHAIN
	MOVE T4,TTCHIC		;GET INPUT CHARACTER
	IDPB T4,T3		;STORE IN INPUT LINE BUFFER
	MOVEM T3,TTIIN(T2)	;SAVE UPDATED POINTER FOR ADDING TO BUFFER
	AOS T3,TTICT(T2)	;INCREMENT COUNT OF CHARACTERS

;IF INPUT BUFFER IS FULL, SEND XOFF TO TERMINAL

	LOAD T4,TIMAX,(T2)	;GET CAPACITY OF BUFFERS
	CAIL T3,-MINICT(T4)
	JRST [	PUSH P,T2	;SAVE TTY
		DYNST
		TDCALL S,<<FE,SNDXO2>,<DZ,DZSXOF>> ;SEND XOFF
		POP P,T2	;RESTORE LINE
		JRST .+1]
	TMNE TTNUS,(T2)		;NET USER?
	JRST [	CALL REQNS	;YES, QUEUE A SEND
		RETSKP]		;AND DONE

;IF THIS STORE MADE THE BUFFER GO NON-EMPTY, AND JOB HAS ENABLED FOR
;INTERRUPTS ON THAT CONDITION, ISSUE THE INTERRUPT

	CAIN T3,1		;JUST BECAME NON-0?
	CALL TTCH22
	;..
;TTCHI..

;IF A FORK IS IN INPUT WAIT ON THIS TERMINAL, WAKE IT UP IF EITHER
;	1. THE TERMINAL DATA MODE IS BINARY
;	2. THE INPUT BUFFER IS FULL
;	3. THE CHARACTER IS IN A WAKEUP CLASS SPECIFIED BY THE JOB

	;..
	LOAD T3,TWFRK,(T2)	;IF NO FORK WAITING FOR THIS LINE,
	CAIN T3,-1
	JRST TTCH10		; THEN SKIP WAKEUP CHECKS
	LOAD T3,TYLMD,(T2)	;GET TERMINAL DATA MODE FOR LAST CHARACTER
	CAIN T3,.TTBIN		;WAKE ALWAYS IF BINARY
	JRST [	CALL TTFWAK	;WAKE LISTENING PROCESS
		RETSKP]		;RETURN SUCCESS
	LOAD T3,TIMAX,(T2)	;CAPACITY OF INPUT BUFFERING
	SUBI T3,MINCT1		;LESS AN ARBITRARY AMOUNT
	CAMG T3,TTICT(T2)	;BUFFER NOW THAT FULL?
	JRST [	SETONE TTFWK,(T2) ;YES. FORCE WAKEUP OF WAITING FORK
		JRST .+1]
	CAIN T1,.CHCRT		;IS THIS A CARRIAGE RETURN
	MOVEI T1,.CHLFD		;YES-FORCE IT TO BE A LINE FEED
	SKIPL TTCHFL		;DID WE FAIL TO ECHO CHARACTER?
	CALL TTWAKE		;DETERMINE IF CHARACTER IS IN WAKE-UP CLASS
	 JRST [	CALL TTFWAK	;YES, FORCE WAKEUP
   		JRST TTCH1X]
TTCH10:	LOAD FX,TWFRK,(T2)	;GET WAITING FORK IF ANY
	CAIN FX,-1		;IS THERE ONE?
	JRST TTCH1X		;NO, DON'T WAKE
	JE TTFWK,(T2),TTCH1X	;YES. IS THE WAKEUP BIT SET?
	ANDI FX,7777		;YES, FLUSH FLAGS
	CALL TTUBLK		;MAKE THE FORK RUN TO EMPTY BUFFER
TTCH1X:	RETSKP
;TTCHI..

;HERE WHEN RECEIVED TERMINAL INTERRUPT CHARACTER.
;CHECK WHETHER DEFERRED OR IMMEDIATE, INITIATE INTERRUPT IF NECESSARY.

;	T1/ ORIGINAL CHARACTER, 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ THE CODE
;	Q1/ BIT FOR CONTROL CODE FOR THIS CHARACTER


;221 REARRANGED

TTCH11:	LOAD T4,TILAC,(T2)	;GET LAST DEFERRED INTERRUPT CHAR
	SETONE TILAC,(T2)	;THERE ISN'T ONE NOW
	TDNN Q1,TTDPSI(T2)	;DEFERRED CHARACTER?
	JRST TCHI1		;NO, INTERRUPT IMMEDIATELY
	CAMN T4,T1		;LAST CHAR SAME AS THIS ONE?
	JRST TTCHI5		;YES, MAKE IMMEDIATE

;HANDLE DEFERRED INTERRUPT CHARACTER

	STOR T1,TILAC,(T2)	;SAVE THIS DEFERRED INT CHAR ONE
	PUSH P,T1		;SAVE CHAR
	CALL TTFWAK		;FORCE WAKEUP SO PGM CAN SEE INT
	POP P,T1		;GET CHAR BACK
	LOAD T3,TIMAX,(T2)	;MUST PUT DEFERRED CHAR IN BUFFER
	ADDI T3,1		;1 RESERVED FOR INT CHAR
	CAMG T3,TTICT(T2)	;IS ROOM?
	JRST [	DPB T1,TTIIN(T2);NO, SMASH CHAR ON TOP OF LAST ONE
		JRST TCHIX]	;RETURN
	JRST TTCHI9		;YES. PUT IN BUFFER W NO ECHOS

;DEFERRED CHARACTER TWICE IN A ROW

TTCHI5:	PUSH P,T3		;SAVE CODE
	CALL TTCIBF		;CLEAR INPUT BUFFER ON DOUBLE INT
	POP P,T3		;RESTORE CODE
TCHI1:	CALL TTITPK		;221 MAYBE FLUSH SPECIAL CHAR
	CALL TTPSI2		;GO ISSUE THE INTERRUPT
TCHIX:	RETSKP

;TTPSI2 - ISSUE INTERRUPT TO PROCESS THAT HAS ENABLED FOR IT
;VIA ATI

;ACCEPTS:
;	T2/ADDRESS OF DYNAMIC DATA
;	T3/CODE

;	CALL TTPSI2

;RETURNS +1: ALWAYS

;NOTE: TTPSRQ CLOBBERS T2

TTPSI2:	CALL TTCLPS		;CLEAR PAGE COUNTER
	DYNST			;T2/ INTERNAL LINE NUMBER
	CALL TTPSRQ		;REQUEST INTERRUPT FROM PSI SYSTEM
	AOS TTINTS		;COUNT INTERRUPTS
	RET			;AND DONE
;INPUT BUFFER GETTING FULL. SEND BELL AND LOSE CHARACTER

TTCH12:	LOAD T3,TLTYP,(T2)	;CHECK LINE TYPE
	CAIN T3,TT.PTY		;PTY?
	RET			;YES
	MOVEI T1,"G"-100	;NO, ECHO BELL
	CALLRET SCDTCO

;DO INPUT INTERRUPT IF ENABLED

TTCH22:	LOAD T4,TTPSFK,(T2)	;CHECK FOR FORK
	CAIN T4,-1
	JRST TTCH23		;IGNORE IF NOT SET
	LOAD T4,TTIPSI,(T2)	;CHECK FOR NON CONTRL TERM PSI
	CAIL T4,^D36		;CHECKLEGAL
	JRST TTCH23		;NO TRY FOR CONTROL TERMINAL
	SAVET			;SAVE TEMPS
	MOVE T1,T4		;GET PSI
	LOAD T2,TTPSFK,(T2)	;GET FORK
	CALLRET PSIRQ		;DO REQUEST

TTCH23:	MOVX 4,1B<.TICTI>
	TDNN 4,TTPSI(2)		;YES, SEE IF INPUT INTERRUPT WANTED
	RET			;NO
	MOVX 3,.TICTI		;YES, REQUEST IT
	SAVET			;SAVE ACS
	DYNST			;T2/ INTERNAL LINE NUMBER
	CALLRET TTPSRQ		;REQUEST INTERRUPT

;NOTE: DOESN'T SET OR TEST TCOERR. IGNORES FAILURE TO SEND BELL
;SEE IF CHARACTER IS XON OR XOFF AND HANDLE AS NECESSARY
; RETURN +1: WAS XOFF OR XON
; 	+2: WAS NOT XOFF OR XON

TTCHXX:	JE TT%PGM,TTFLGS(T2),RSKP ;IF IGNORING XOFF/XON, CONTINUE
	CAIE T1,PGMONC+1B28
	CAIN T1,PGMONC		;XON?
	IFNSK.
	  CALL TTITPK		;+++ MAYBE FLUSH PREFIX CHAR FROM LINE BUFFER
	  LOAD T3,TTUPC,(T2)	;YES, SEE IF PAGE UNPAUSE CHARACTER TOO
	  CAIE T3,PGMONC
	  CALLRET TTXONC	;NO, XON COMMAND ONLY
	  CALLRET TTXONA	;YES, BOTH
	ENDIF.
	CAIE T1,PGMOFC		;XOF?
	CAIN T1,PGMOFC+1B28
	SKIPA			;YES
	CAIN T1,PGMOFC
	RETSKP			;NO, EXIT
	JN TTRXF,(T2),R		;SEE IF ALREADY STOPPED
	CALL TTITPK		;+++ MAYBE FLUSH PREFIX CHAR FROM LINE BUFFER
TTXOFC:	SETONE TTRXF,(T2)	;YES. INDICATE FRONT-END XOFF
	TMNN <TTSAL,TTHPO>,(T2)	;SPECIAL OUTPUT GOING?
	IFNSK. <
	  TDCALL D,<<FE,TTCHI3>,<MC,MCLNOF>> ;NO, STOP THE LINE
	 >,<
	  TDCALL D,<<FE,TTXON1>,<MC,MCLNON>>> ;YES, RESTART THE LINE
	RET
;TTXON - DO 'XON' - CLEAR STOP FLAG AND RESTART OUTPUT TO TERMINAL IF NECESSARY
; TTXONA - RESTART ALL CASES
; TTXONC - RESTART FROM COMMAND STOP ONLY
; TTXONP - RESTART FROM PAGE STOP ONLY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTXONx

;RETURNS +1: ALWAYS

;CALLED IN ANY OF THE FOLLOWING CASES:
;	CLEAR OUTPUT BUFFER
;	STPAR
;	USER TYPES XON

TTXONA:	SETZRO TTSFG,(T2)	;CLEAR CTRL/S
TTXONC:	JE TTRXF,(T2),TTXON2	;JUMP IF HOST SIMULATED XOF ONLY
	TDCALL D,<<FE,TTXON1>,<MC,MCLNON>>
	SETZRO TTRXF,(T2)
TTXON2:	MOVE 3,TTOCT(2)		;GET COUNT OF CHARACTERS IN OUTPUT BUFFER
	NOSKD1			;NOSKED FOR STRTOU CALL
	CALLRET STRTOU		;RESTART OUTPUT

TTXONP:	SETZRO TTSFG,(T2)
	JRST TTXON2		;RESTART OUTPUT
;HANDLE LINE IN NET USER STATE

TTNU1:
  IFN .MCFLG,<
	CALL TTCHXX		;CHECK FOR XON, XOFF
	 JRST [	JN TTNPM,(T2),RSKP ;IT WAS, FLUSH THE CHAR IF OLD MODE
		JRST .+1]	;OTHERWISE KEEP IT
	LOAD T4,TTUEC,(T2)	;CHECK FOR ESCAPE CHAR
	XOR T4,T1
	JXN T4,177,TTMCI1	;JUMP IF NOT
	SETZRO TTNUS,(T2)	;GET OUT OF NET USER STATE
	LOAD T3,TCJOB,(T2)	;SEE IF HAVE JOB ON THIS LINE
	CAIN T3,-1
	IFSKP.
	  SETZRO TTPRM,(T2)	;YES, CLEAR PERMANENT
	  JRST TTCHIF		;KEEP CHAR IN INPUT STREAM
	ENDIF.
	CALL TNUCLS		;NO, CLOSE CONNECTION
  >				;END IFN .MCFLG
	RETSKP

;DO PAGE PAUSE ON COMMAND FROM USER
;THE HEURISTICS AREN'T NEEDED UNLESS WE ARE USING A CHARACTER THAT
;ALSO HAS SOME OTHER FUNCTION (E.G. ^U).  IN THAT CASE, WE ONLY
;WANT TO DO THE PAUSE IF THE CHARACTER IS NOT PART OF REGULAR TYPEIN

TTXOFP:	LOAD T3,TTPPC,(T2)	;GET PAUSE CHARACTER
	CAIL T3,40		;A CONTROL CHAR?
	IFSKP.
	  MOVE T3,BITS(T3)	;YES, SEE WHAT KIND
	  TDNN T3,TTXOBM	;HAS SYSTEM USE IN INPUT STREAM?
	  JRST TTXFP1		;NO, MUST BE PAUSE. EXECUTE IT
	ENDIF.
	SKIPE TTICT(T2)		;ANY TYPEAHEAD?
	RET			;YES, DO NOTHING
	LOAD T3,TWFRK,(T2)
	CAIN T3,-1		;OR FORK WAITING?
	IFSKP.
	  MOVE T3,TTOCT(T2)	;YES, SEE HOW MUCH OUTPUT QUEUED
	  CAIG T3,^D40		;LOTS?
	  RET			;NO, DON'T PAUSE
	ENDIF.
TTXFP1:	CALL TTITPK		;MAYBE FLUSH PREFIX CHAR FROM LINE BUFFER
	SETONE TTSFG,(T2)	;PAUSE
	RETSKP			;AND EAT CHARACTER

;MASK OF CONTROL CHARACTERS WHICH HAVE DEFINED SYSTEM USE IN
;INPUT STREAM

TTXOBM:	BYTE (1)0,0,0,0,0,0,1,0,1,1,1,1,1,1,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0
;IF LAST CHAR IN LINE INPUT BUFFER WAS A SPECIAL CHAR, FLUSH IT

TTITPK:	MOVE T4,TTTMOD(T2)	;CHECK IF ITP TERMINAL
	TXNN T4,TM%ITP
	RET			;NO, NOTHING TO DO
	LDB T4,TTIIN(T2)	;GET LAST CHAR
	TXNN T4,200		;WAS PREFIX?
	RET			;NO, NOTHING TO DO
	SOSG TTICT(T2)		;YES, DECR COUNT OF CHARS
	JRST [	PUSH P,T3	;EMPTY, FLUSH BUFFERS
		SETZB T3,TTIOUT(T2)
		EXCH T3,TTIIN(T2)
		CALL TTRLBF
		POP P,T3
		RET]
	SETO T4,
	ADJBP T4,TTIIN(T2)	;MOVE POINTER BACK ONE
	MOVEM T4,TTIIN(T2)
	RET
	
;TTCHI..

;RECEIVED CHARACTER ON LINE THAT IS NOT ASSIGNED A FULL-LENGTH
;DYNAMIC BLOCK.

;	T1/ CHARACTER
;	T2/-1 IF LINE IS BECOMING ASSIGNED
;		OR
;	0 IF NOT AT ALL ASSIGNED
;		OR
;	POSITIVE ADDRESS OF SHORT OR TTEMES BLOCK

TTC7N:	ANDI T1,177
	CAIN T1,.CHNUL		;FLUSH NULLS
	RET
	MOVE T4,TTCHSV		;GET LINE NUMBER
	JN TTIGI,(T4),R		;RETURN IF IGNORING CHARACTERS ON THIS LINE
;+++	CAIE T1,.CHCRT		;CR OR LF?
;+++	CAIN T1,.CHLFD
;+++	JRST TTCH71		;YES, TRY TO CREATE JOB
	CAIN T1,.CHCNC		;CONTROL-C?
	JRST TTCH71		;YES.
	JUMPL T2,R		;IF BECOMING ACTIVE, IGNORE
	JUMPE T2,TTCH73		;IF INACTIVE, SEND BELL
	JE TTPRM,(T2),TTCH73	;IF TEMPORARILY ACTIVE AND NOT PERMANENT, SEND BELL
	JN TTBAC,(T2),R		;IF PERMANENT AND BECOMING ACTIVE, IGNORE
TTCH73:	CAIN T1,.CHBEL		;+++ IF ^G, DON'T ECHO IT
	 RET			;+++ SO LOOPBACK CAN BE SAFELY DONE
	HRROI T1,[BYTE(7) .CHBEL]  ;SEND A BELL
	MOVE T2,TTCHSV		;T2/ INTERNAL LINE NUMBER
	CALLRET TTEMES		;GO SEND A BELL AND LOSE CHARACTER

;A CONTROL/C WAS RECEIVED OR CARRIER CAME ON FOR A REMOTE LINE
;IF LINE IS TOTALLY INACTIVE, GO CREATE A JOB ON IT
;IF LINE IS BECOMING ACTIVE, IGNORE THE CHARACTER
;IF LINE HAS SHORT OR MESSAGE BLOCK, IGNORE THE CHARACTER

TTCH71:	JUMPE T2,TTCH75		;ACCEPT IF NOT AT ALL ACTIVE
	JUMPL T2,R		;IGNORE IF BECOMING ACTIVE
	JE TTPRM,(T2),R		;IF NOT PERMANENT, ASSUME BLOCK WILL GO AWAY
	JN TTBAC,(T2),R		;PERMANENT. IGNORE IF BECOMING ACTIVE

;LINE  HAS NO DYMAMIC DATA OR IT HAS A PERMANENT BLOCK AND 1) HAS NO
;CONTROLLING JOB AND 2) IS NOT BECOMING ACTIVE. CREATE A JOB ON IT IF
;LOGINS ARE ALLOWED

TTCH75:	MOVE T1,FACTSW		;SEE WHAT LOGINS ARE ALLOWED
	MOVE T2,TTCHSV		;RESTORE LINE NUMBER
TTC7SJ:	CAMN 2,CTYLNO		;CTY?
	JRST [	TXNE T1,SF%CTY	;YES, CTY LOGIN ALLOWED?
		JRST TTC7SK	;YES, GO LOGIN
		HRROI 1,[ASCIZ/
?LOGGING IN ON THE CTY IS CURRENTLY DISALLOWED.
/]
		CALLRET TTEMSS] ;NO LOGIN ALLOWED ON CTY
	TDCALL S,<<FE,RSKP>,<PT,TTC7S2>,<NT,TTC7SN>,<DZ,RSKP>,<ML,TTC7SN>,<CH,TTC7SN>,<TV,TTC7SN>>
	 JRST [	JUMPL T1,TTC7SK	;IF NEG, GO START A JOB
		RET]		;ELSE FAIL

;LINE IS ON THE FRONT END OR THE DC10. SEE IF LINE IS LOCAL OR REMOTE

TTC7S1:	JN TTFEM,(T2),TTCHS3	;IF REMOTE, GO CHECK REMOTE LOGINS
	TXNE T1,SF%LCL		;LOCAL LOGINS ALLOWED?
	JRST TTC7SK		;YES. GO CREATE JOB
	HRROI 1,[ASCIZ/
?LOGGING IN ON LOCAL TERMINALS IS CURRENTLY DISALLOWED.
/]
	CALLRET TTEMSS		;LOCAL LOGINS NOT ALLOWED. SEND MESSAGE

;LINE IS REMOTE

TTCHS3:	TXNE 1,SF%RMT		;...
	JRST TTC7SK		;YES. GO CREATE JOB
	SETONE TTFSP,(T2)
	HRROI 1,[ASCIZ/
?LOGGING IN ON DATASETS IS CURRENTLY DISALLOWED.
/]
	CALLRET TTEMSS		;REMOTE LOGINS NOT ALLOWED, SEND MESSAGE


;LOGINS ARE ALLOWED.

TTC7SK:	MOVEI 1,JOBSRT		;REQUEST SCHEDULER- START JOB
	HRLI 1,0(2)		;ON SPECIFIED TTY LINE
	SKIPLE T3,TTACTL(T2)
	JRST [	JE TTPRM,(T3),.+1
		SETONE TTBAC,(T3)
		JRST TTC7S3]
	SETOM TTACTL(T2)	;INDICATE LINE BECOMING ACTIVE
TTC7S3:	CALL SCDRQ7
	RETSKP

	ENDSV.			;END STKVAR
; TTWAKE - DETERMINE IF CHARACTER IS IN WAKE-UP CLASS

;ACCEPTS:
;	T1/ 7-BIT ASCII CHARATER
;	T2/ ADDRESS OF DYNAMIC DATA

;RETUNS:	+1, CHARACTER BELONGS TO A WAKE-UP CLASS
;		+2, CHARACTER NOT IN ANY WAKE-UP CLASS

TTWAKE:	LOAD T3,TTFCNT,(T2)	;DECREMENT FIELD WIDTH COUNT
	JUMPLE T3,TTMASK	;JUMP IF FIELD WIDTH DISABLED (=0)
	SOS T3			;ENABLED - DECREMENT THE COUNT
	STOR T3,TTFCNT,(T2)	;SAVE NEW VALUE
	SKIPN T3		;SKIP IF COUNT NOT EXHAUSTED
	RET			;COUNT EXHAUSTED - WAKE PROCESS

;HERE TO CHECK WAKE-UP MASK (FIELD WIDTH DISABLED OR NOT EXHAUSTED)

TTMASK:	MOVE T3,T1		;MOVE THE ASCII CHARACTER
	IDIVI T3,^D32		;COMPUTES WHICH WORD MASK BIT IS IN
	MOVE T4,BITS(T4)	;GET THE BIT MASK FOR TESTING
	ADD T3,T2		;BUMP INTO PROPER WORD OF MASK
	TDNE T4,TTCHR1(T3)	;SKIP IF NO WAKE-UP ON THIS CHARACTER
	RET			;PROCESS SHOULD BE AWAKENED
	CAIE T1,.CHLFD		;IS THIS A LF ON A PTY?
	RETSKP			;NO, NO WAKEUP
	LOAD T3,TLTYP,(T2)
	CAIN T3,TT.PTY		;PTY?
	RET			;YES, WAKEUP
	RETSKP			;PROCESS SHOULD NOT BE AWAKENED
;+++ BEGIN ADDITION

	SUBTTL INPUT PROCESSING ROUTINES

; THESE ROUTINES ARE POINTED TO BY TTRUT IN DYNAMIC DATA.
; ACCEPT	
;	T1/ CHAR
;	T2/ DYNAMIC DATA
; RETURN
;	+1 FOR NO CHAR INPUT, 
;	+2 WITH CHAR TO INPUT IN T3,
;	   CHAR TO USE FOR XON/XOFF AND INTERRUPT TESTS IN T1
;	    NORMAL CHAR EXPECTED TO BE IN 7 BITS, 
;	    200 BIT SET INDICATES SPECIAL OR PREFIX CHAR TO 
;	    BE IGNORED BY TESTS

; INPUT ROUTINES FOR INTELLIGENT TERMINAL PROTOCOL
TTIITP:	JE <TISLH,TICCH>,(T2),TTIIT1 ;NOT IN ESC SEQUENCE,CHECK FOR /034
	SETZRO TISLH,(T2)	; TURN OFF ESC SEEN FLAG
	LOAD T3,TICHR,(T2)	; GET POSSIBLE PREFIX CHAR
	SKIPN T3		; ALREADY EXISTS, USE IT FOR DISPATCH
	MOVEI T3,(T1)		; ELSE THIS IS A PREFIX CHAR...
	CAIL T3,"@"		; POSSIBLE META BITS?
	 CAILE T3,"_"
	 CAIA			; NO, TREAT AS COMMAND
	 JRST ITPESC		; YES, GO BUILD A FULL CHARACTER
	MOVEI T4,ITPTBL		; SEARCH THROUGH TABLE FOR DISPATCH CHAR
TTITP0:	HLRZ CX,(T4)		; GET CHAR FROM TABLE
	JUMPE CX,RSKP		; END OF TABLE, NOT FOUND
	CAIN CX,(T3)		; MATCHING ENTRY?
	 JRST [	HRRZ CX,(T4)	; YES, GO RUN ROUTINE
		JRST (CX) ]
	AOJA T4,TTITP0		; TRY NEXT ENTRY

TTIIT1:	CAIN T1,""		; ITP ESCAPE CHAR?
	 JRST [ SETONE TISLH,(T2)	; YES, FLAG IT
		RET]		; AND NO REAL CHAR INPUT
	MOVE T3,T1		; REGULAR CHARACTER, RETURN AS INPUT
	RETSKP

; DISPATCH TABLE FOR ITP COMMANDS
ITPTBL:	"P"-100,,ITPSCP		; ^\ ^P # # SET CURSOR POSITION
	"Q"-100,,ITPSCQ		; FAKE FOR ^P
	"\"-100,,ITPSLH		; ^\ ^\ INPUT A ^\
	"C"-100,,ITPMNG		; ^\ ^C SCREEN HAS BEEN MUSSED
	"A"-100,,ITPALC		; ^\ ^A INCREMENT ALLOCATION
	"Z"-100,,ITPZAL		; ^\ ^Z ZERO ALLOCATION
	"I"-100,,ITPIAL		; ^\ ^I SET ALLOCATION TO INFINITY
	"S"-100,,ITPSTP		; ^\ ^S STOP OUTPUT
	"R"-100,,ITPRES		; ^\ ^R RESUME OUTPUT
	0			; MARK END OF THE TABLE

; ESCAPED TV CODE
ITPESC:	JN TICCH,(T2),ITPES1	; FIRST TIME THROUGH?
	STOR T1,TICHR,(T2)	; YES, SAVE META BITS
	SETONE TICCH,(T2)	; REMEMBER WE SAW THEM
	ANDI T1,37		; GET 5 META BITS
	TRO T1,200		; FLAG THAT THIS WAS A PREFIX
	MOVE T3,T1		; BOTH LINE BUFFER AND TEST CHAR
	RETSKP			; RETURN CHAR

; ESCAPED CODE LAST TIME, RETURN IT AND COMPOSITE ASCII
ITPES1:	ANDI T1,177		; MASK TO SEVEN BITS
	PUSH P,T1		; SAVE CHARACTER
	CALL ITPASC		; CONVERT TO 7-BIT ASCII IN T1
	POP P,T3		; RESTORE REAL VERSION TO T3
	SETZRO <TICHR,TICCH>,(T2)	;CLEAR FLAGS
	RETSKP
; CONVERT CHARACTER IN T1 TO ASCII USING META PREFIX IN T3
; CALLED TWICE ON PREFIX CHARACTERS, ONCE TO INTERRUPT CHECKING
; AT TTCHI LEVEL AND ONCE FOR TCI0 TO RETURN TO USER.
; ACCEPTS
;		T1/ LOW ORDER BITS OF 12 BIT CHAR
;		T3/ HIGH ORDER BITS OF 12 BIT CHAR
;
; RETURNS
;	+1, ALWAYS
;		T1/ 7-BIT ASCII CHAR

ITPASC:	TRNN T3,1		; %TXCTL ON?
	 JRST ITPAS2		; NO
	CAIL T1,"a"		; YES, IS IT A LOWERCASE LETTER?
	 CAILE T1,"z"
	 CAIA			; NO
	 TRZ T1,40		; YES, UPPERCASIFY IT
	CAIL T1,77		; BETWEEN 077 AND 137?
	 CAILE T1,137
	 CAIA			; NO
	 TRC T1,100		; YES
	CAIN T1,40		; MAKE ^<SPACE> BE NULL
	 SETZ T1,
ITPAS2:	TRNE T3,2		; %TXMTA ON?
	 TRO T1,200		; YES, SET PSEUDO-META
	RET

; SET POSITION (IN RESPONSE TO %TDORS)

ITPSCP:	JN TICCH,(T2),ITPSC1	; FIRST TIME THROUGH?
	STOR T3,TICHR,(T2)	; YES, SAVE STATE
	SETONE TICCH,(T2)
	RET

ITPSC1:	STOR T1,TPVPS,(T2)	; SECOND TIME -- VERTICAL POSITION
	STOR T1,TLVPS,(T2)
	MOVEI T3,"Q"-100	; FAKE COMMAND
	STOR T3,TICHR,(T2)
	RET

ITPSCQ:	STOR T1,TPHPS,(T2)	; HORIZONTAL POS
	STOR T1,TLHPS,(T2)
	SETZRO <TTCFU,TTNAB>,(T2) ; NOT CONFUSED
	SETZRO <TICHR,TICCH>,(T2) ; DONE WITH COMMAND
	RET

; SCREEN HAS BEEN MUNGED

ITPMNG:	RET			; DON'T HANDLE THIS YET

; START/STOP OUTPUT

ITPSTP:	SETONE TTSFG,(T2)	; SHUT OFF OUTPUT (MAYBE SHOULD STOP FE?)
	RET

ITPRES:	CALLRET TTXONP		; ^S FLAG OFF, START LINE
	
; INCREMENT ALLOCATION

ITPALC:	JN TICCH,(T2),ITPAL1	; FIRST TIME THROUGH?
	MOVEI T3,"A"-100	; YES, JUST REMEMBER STATE
	STOR T3,TICHR,(T2)
	SETONE TICCH,(T2)
	RET

ITPAL1:	SETZRO <TICCH,TICHR>,(T2) ; SECOND TIME THROUGH
REPEAT 0,<
	LOAD T3,TIALC,(T2)	; INCREMENT ALLOCATION
	ADDI T3,(T1)
	STOR T3,TIALC,(T2)
>
	RET

; ZERO ALLOCATION
ITPZAL:	
;	SETZRO TIALC,(T2)
	SETONE TIALP,(T2)	; TURN ON ALLOCATION
	RET

; SET ALLOCATION TO INFINITY (TURN IT OFF)
ITPIAL:	SETZRO TIALP,(T2)
	RET

; SEND A REAL ^\
ITPSLH:	MOVE T3,T1		;CHAR TO LINE BUFFER, TOO
	RETSKP
	SUBTTL TTEMES - SEND SHORT MESSAGE FROM SCHEDULER

;ACCEPTS:
;	T1/ BYTE POINTER TO STRING TO BE OUTPUT
;	T2/ LINE NUMBER

;	CALL TTEMES

;RETURNS +1: ALWAYS

;CALLED AT SCHEDULER LEVEL TO SEND A SHORT MESSAGE TO A LINE
;IF LINE IS ACTIVE, APPENDS CHARACTERS TO OUTPUT BUFFER. IF NOT
;ACTIVE, CREATES A MESSAGE-LENGTH DYNAMIC BLOCK FOR THE LINE

;TTEMSS - ENTRY POINT TO CLEAR OUTPUT BUFFER BEFORE OUTPUTTING

TTEMSS:	PUSH P,A		;SAVE STRING POINTER
	CALL TTCOB1		;CLEAR CURRENT GARABGE OUT
	POP P,A			;AND GO SEND THE MESSAGE

;TTEMES - NORMAL ENTRY POINT

TTEMES::SAVELN			;PRESERVE LINE NUMBER
	STKVAR <TTEMBP,TTEMAC,TTEMLN>
	MOVEM T1,TTEMBP		;SAVE BYTE POINTER TO STRING
	MOVEM T2,TTEMLN		;SAVE LINE NUMBER
	MOVEM Q1,TTEMAC		;SAVE WORK REGISTER
	CALL STADYN		;GET POINTER TO DYNAMIC DATA
	 SKIPA			;NOT FULLY ACTIVE
	JRST TTEME2		;FULLY ACTIVE. USE REGULAR BUFFERS
	JUMPL T2,TTEME3		;IF BECOMING ACTIVE, CAN'T SEND MESSAGE
	JUMPE T2,TTEME1		;IF INACTIVE, GO GET A BLOCK
	JN TTSHT,(T2),TTEME3	;IF SHORT BLOCK, CAN'T SEND MESSAGE
	JRST TTEME2		;HAS MESSAGE BLOCK. APPEND STRING
TTEME1:	MOVE T2,TTEMLN		;T2/LINE NUMBER
	CALL ASGMSG		;GET A BLOCK
	 JRST TTEME3		;COULDN'T GET ONE
	MOVE T2,T1		;GET ADDRESS OF DYNAMIC DATA

;T2/ ADDRESS OF DYNAMIC DATA FOR FULL-LENGTH OR MESSAGE BLOCK

TTEME2:
	MOVE T1,TTEMBP		;RESTORE BYTE POINTER
	TLC 1,-1
	TLCN 1,-1		;LH = 777777 ?
	HRLI 1,440700		;YES, MAKE BYTE PTR
	MOVEM T1,TTEMBP		;SAVE BYTE POINTER
TTEME4:	ILDB 1,TTEMBP		;GET CHARACTER
	JUMPE 1,TTEME3		;NULL TERMINATES.
	MOVEI Q1,0(1)		;SAVE THE BYTE
	CALL SCDTCO		;OUTPUT IT
	CAIE Q1,.CHCRT		;A CARRIAGE RETURN?
	CAIN Q1,.CHLFD		;OR A LF?
	SKIPA			;GO FILL
	JRST TTEME4		;NO. GET NEXT CHARACTER
	MOVEI Q1,3		;NUMBER OF FILLS TO DO
TTEME5:	MOVEI A,TTFILL		;THE FILL CHARACTER
	CALL SCDTCO		;OUTPUT IT
	SOJGE Q1,TTEME5		;DO ALL FILLS
	JRST TTEME4		;GO DO NEXT BYTE

TTEME3:	MOVE T1,TTEMBP		;RESTORE BYTE POINTER
	MOVE Q1,TTEMAC		;RESTORE WORK REGISTER
	CALLRET TTYQOC		;GET OUTPUT STARTED

	ENDSV.			;END STKVAR
	SUBTTL BIGSTO (STORE CHAR IN TTBBUF)

;BIGSTO - ROUTINE TO STORE DATA IN TTBBUF
;DATA CONSISTS OF STATUS BITS OR DLSRCF+CHARACTER IN 8 BITS
;CALLED AT INTERRUPT LEVEL OR WITH TELETYPE INTERRUPTS DISABLED
;SOMETIMES CALLED IN SCHEDULER CONTEXT

;ACCEPTS:
;	T1/ (INTERNAL LINE NUMBER,,DATA)
;	T2/ INTERNAL LINE NUMBER (MUST BE PHYSICAL LINE)

;RETURNS +1: ALWAYS

BIGSTO::MOVEI 3,TTBSIZ		;GET SIZE OF TTBBUF
	CAMLE 3,TTBIGC		;HAS TTBBUF OVERFLOWED?
	IFSKP.
	  BUG(TTYBBO)		;YES, LOSE CHARACTER
	  RET
	ENDIF.
	TDCALL S,<<FE,BIGST2>,<DZ,DZBST>>
	 RET			;FLUSH CHAR
	AOS 3,TTBIGI		;NO. POINT TO NEXT WORD IN TTBBUF
	CAIN 3,TTBSIZ		;AT END OF TTBBUF?
	SETZB 3,TTBIGI		;YES. WRAPAROUND
	MOVEM 1,TTBBUF(3)	;STORE CURRENT DATA
	AOS TTBIGC		;COUNT CONTENTS
	RET

;INPUT DONE AND CHARACTER PRESENT (CALLED FROM INTERRUPT ROUTINES)
; T1/ CHARACTER
; T2/ LINE NUMBER
;	CALL TTIDON
; RETURN +1 ALWAYS

TTIDON::CAIE T1,PGMOFC+1B28	;PARITY AND XOFF
	CAIN T1,PGMOFC		;CHECK FOR XOFF
	CALL TTYSTC		;YES CHECK ON WHAT TO DO
TTICNT::TRO T1,DLSRCF		;INDICATE RECEIVED CHARACTER
	HRL T1,T2		;COMBINE LINE NUMBER WITH CHAR
	CALLRET BIGSTO		;PUT IN BIG BUFFER

TTYSTC:	SAVEAC <T1,T2>
	CALL STADYN		;GET DYN ADDRESS
	 RET			;INACTIVE
	JE TT%PGM,TTFLGS(T2),R	;IF NO XOFF, GO AWAY
	CALLRET TTXOFC		;DO XOFF ON COMMAND
	SUBTTL TTSNDO (NON-INTERRUPT CHAR SEND)

;TTSND0 - SEND ROUTINE CALLABLE FROM NON-PI CONTEXT

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTSN10

;RETURNS +1: ALWAYS

;USE THIS ENTRY POINT IF ONLY LINE NUMBER IS AVAILABLE

TTSN10:	NOSKD1
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST [	JUMPG T2,.+1	;IF SEND-ALL OR MESSAGE,PROCEED
		OKSKD1		;NOT ACTIVE
		RET]
	JRST TTSN11

;TTSND0 - MAIN ENTRY POINT

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSND0

;	RETURNS +1: ALWAYS

;STARTS OUTPUT TO THE SPECIFIED LINE

TTSND0:	NOSKD1
TTSN11:	CALLRET STRTOU		;QUEUE START - INCLUDES OKSKD1

;STRTOU - START OUTPUT TO A LINE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC BLOCK
;	T3/ COUNT OF CHARACTERS IN OUTPUT BUFFER

;	CALL STRTOU
;	MUST BE NOSKD1!

;RETURNS +1: ALWAYS OKSKD1

STRTOU:	JN TTOTP,(T2),STRT11	;IF ACTIVE, NO NEED TO START IT
	TDCALL D,<<PT,STRTO2>,<NT,NTTCSO>,<ML,MLCTCO>,<CH,CHTCSO>,<TV,TVTCSO>>
	 SKIPA			;NORMAL START
	JRST STRT11		;NOTHING ELSE TO DO
	SAVELN
	DYNST			;GET LINE NUMBER
	IDIVI T2,^D36		;COMPUTE BIT POSITION IN QUEUE
	MOVE T3,BITS(T3)
	IORM T3,TTSOQ(T2)	;REQUEST START NEXT BIGBUF CYCLE
STRT11:	CALL OSKD1		;ALLOW SCHEDULING NOW
	RET
;ROUTINE TO START OUTPUT ON QUEUED LINES
;CALLED ONLY ON SCHED SHORT CYCLE AT TTCH7X

TTYQOC:	SAVEAC <Q1,Q2>
	MOVSI Q1,-NTSQWD	;SETUP NUMBER OF WORDS TO CHECK
TTYQO5:	SKIPE T1,TTSOQ(Q1)	;ANY QUEUED LINES IN THIS WORD?
TTYQO4:	JFFO T1,TTYQO2		;YES, FIND ONE
	AOBJN Q1,TTYQO5		;DO ALL WORDS
	RET

TTYQO2:	MOVE Q2,BITS(T2)	;CLEAR REQUEST THIS LINE
	ANDCAM Q2,TTSOQ(Q1)	;CLEAR REQUEST BIT
	HRRZ T3,Q1		;COMPUTE LINE NUMBER
	IMULI T3,^D36
	ADD T2,T3
	CALL STADY		;GET DATA ADDRESS
	 JRST TTYQO1		;QUIT IF NONE
	CALL STRTTO		;START PHYSICAL DEVICE
TTYQO1:	MOVN T1,Q2
	ANDCA T1,TTSOQ(Q1)	;LOOK AT REST OF WORD ONLY
	JRST TTYQO4		;CONTINUE

;START PHYSICAL TTY OUTPUT DEVICE
; T2/ DYNAMIC PTR
; RETURN +1 ALWAYS

STRTTO:	SAVEQ			;PROTECT AGAINST SOMEONE HERE TRASHING Q1
	TDCALL D,<<FE,FESTRO>,<DZ,DZSTRO>,<MC,MCSTRO>,<PT,PTYCTM>>
	 NOP
	RET

;CONSTANTS

WRPMSK:	XWD 770000,TTSIZ-1	;MASK FOR WRAPAROUND OF CHAR POINTER
	SUBTTL TTSND (SEND CHAR TO LINE)

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA
;	CALL TTSND
; RETURN +1: NO OUTPUT AVAILABLE
;	+2: T1/ CHARACTER FOR OUTPUT

;CALLED AT INTERRUPT LEVEL
;OR IN SCHEDULER CONTEXT WITH TELETYPE INTERRUPTS DISABLED
;OR IN PROCESS CONTEXT WITH TELETYPE INTERRUPTS DISABLED

;SEND CHARACTER TO TTY LINE,
;FROM OUTPUT BUFFER IF NOT EMPTY; OTHERWISE
;CLEAR OUTPUT-ACTIVE FLAG

TTSND:
TTSND6:	JN <TTSFG,TTRXF>,(T2),[
		SETZRO TTOTP,(T2) ;IF CTRL/S TYPED, CLEAR OUTPUT ACTIVE
		RET]
	TMNN TTHPO,(T2)		;HP MESSAGE QUEUED?
	IFSKP.
	  ILDB T1,TTSAL2(T2)	;YES, GET NEXT CHAR
	  CAIE T1,.CHDEL	;END OF STRING?
	  RETSKP		;NO, RETURN CHARACTER
	  SETZRO TTHPO,(T2)	;RUBOUT MARKS END OF STRING, CLEAR
	ENDIF.
	TMNN TTSAL,(T2)		;SENDALL?
	IFSKP.
	  OPSTR <SKIPG>,TSALC,(T2) ;ANY MORE CHARACTERS TO SEND?
	  IFSKP.
	    ILDB T1,TTSAL2(T2)	;GET NEXT CHARACTER
	    DECR TSALC,(T2)	;DECREMENT COUNT OF REMAINING CHARACTERS
	    TRNE 1,200		;THIS CHARACTER HAVE PARITY?
	    CALL SPARTY		;SET PARITY BIT APPROPRIATELY FOR LINE TYPE
	    RETSKP		;RETURN THE CHAR
	  ENDIF.
	  CALL CLRSAL		;CLEAR SENDALL FOR LINE
	ENDIF.
	CALL GTOCHR		;GET CHAR FROM OUTBUF
	 RET			;EMPTY
	TRZE T1,TTOESC		;A FUNCTION ESCAPE CHARACTER?
	JRST TTSND3		;HANDLE ESCAPE SPECIAL
	JN TTFLO,(T2),TTSND6	;IF FLUSHING OUTPUT, GO GET ANOTHER CHAR
	RETSKP
;GET CHARACTER FROM TTY OUT BFR
; T2/ DYNAMIC PTR
; RETURN +1: BUFFER EMPTY
;	+2: T1/ CHAR (9 BITS)

GTOCHR:	SOSGE TTOCT(T2)		;ARE THERE CHARACTERS IN OUTPUT BUFFER?
	JRST [	SETZRO TTOTP,(T2) ;NO CHARACTERS. CLEAR OUTPUT-ACTIVE
		SETZM TTOCT(T2)	;ZERO COUNTER
		CALLRET CLENUP] ; AND GO RELEASE BUFFERS
	CALL CHKWRN		;SEE IF FORK WAKEUP NEEDED
	SKIPN T3,TTOOUT(T2)	;GET BUFFER POINTER
	BUG(TTONOB)
	TDNE T3,WRPMSK		;AT END OF BUFFER?
	IFSKP.
	  HRRZ T4,T3		;YES GO TO NEXT ONE
	  HRR T3,1-TTSIZ(T4)
	  MOVEM T3,TTOOUT(T2)	;SAVE POINTER
	ENDIF.
	ILDB T1,TTOOUT(T2)	;GET NEXT CHARACTER
	RETSKP

;BACKUP OUTPUT PTR BY ONE (E.G. BECAUSE DTE QUEUE FULL)
; T2/ DYN PTR

BAKTTO:	MOVNI T3,1
	TMNN <TTSAL>,(T2)	;SENDALL?
	IFSKP. <INCR TSALC,(T2)> ;YES, ADJUST COUNT
	TMNN <TTHPO,TTSAL>,(T2)	;HP OR SENDALL STRING?
	IFSKP.
	  ADJBP T3,TTSAL2(T2)	;YES, BACKUP BYTE PTR
	  MOVEM T3,TTSAL2(T2)
	  RET
	ENDIF.
	ADJBP T3,TTOOUT(T2)
	MOVEM T3,TTOOUT(T2)	;RESTORE IT
	AOS TTOCT(T2)		;RESET COUNT
	RET
;FUNCTION ESCAPE CHARACTER ENCOUNTERED IN OUTPUT STREAM
;  CURRENT POSSIBILITIES ARE:
;
;	.TTPFC - TERMINAL PAGE FILL, DO XOFF
;	.TTMRK - STOP FLUSHING OUTPUT
;	.TTBRK - MARK SAFE PLACE FOR CFOBF

TTSND3:	CAILE T1,NTTSCD		;RANGE CHECK, 400 BIT ZEROED IN TEST ABOVE
	JRST TTSILE		;NO GOOD
	XCT TTSCOD(T1)		;DO SOMETHING
	JRST TTSND6		;AND GO GET ANOTHER CHAR

TTSCOD:	JRST TTSILE		;ILLEGAL
	CALL TTSPFC		;.TTPFC - PAGE FULL
	CALL TTSMRK		;.TTMRK - STOP FLUSHING OUTPUT
	JFCL			;.TTBRK - SAFE PLACE FOR CFOBF
NTTSCD=.-TTSCOD

;HANDLERS FOR FUNCTION ESCAPE CODES
; ALL (EXCEPT TTSMRK) MUST IGNORE CODE IF FLUSHING OUTPUT

TTSMRK:	JE TTFLO,(T2),R		;IGNORE IF NOT FLUSHING OUTPUT
	LOAD T1,TTTYP,(T2)	;GET TERMINAL TYPE
	CAIN T1,.TTSUP		;TRY TO DO THE RIGHT THING (YECCH)
	SKIPA T1,[POINT 8,[BYTE (8)"]",%TDCRL,.CHDEL]]
	MOVE T1,[POINT 7,[BYTE (7)"]",.CHCRT,.CHLFD,0,0,0,0,0,.CHDEL]]
	MOVEM T1,TTSAL2(T2)	;SEND INDICATION (WITH FILLS ON CR AND LF)
	SETONE TTCFU,(T2)	;LOSE CURSOR, I GUESS
	SETONE TTHPO,(T2)	;NOTE HP OUTPUT QUEUED
	SETZRO TTFLO,(T2)	;STOP FLUSHING OUTPUT
	RET

TTSPFC:	JN TTFLO,(T2),R		;IGNORE IF FLUSHING OUTPUT
	SETONE TTSFG,(T2)	;YES. SIMULATE CTRL/S
	RET

;HERE FOR ILLEGAL ESCAPE CHAR
TTSILE:	PUSH P,T2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER TO PRINT
	TRO T1,400		;PUT ESC BIT BACK FOR BUG OUTPUT
	BUG(TTILEC,<<1,CHAR>,<2,LINE>>)
	POP P,T2		;RESTORE ADDRESS OF DYNAMIC DATA
	JRST TTSND6

;CHKWRN - CHECK FOR WAKEUP NEEDED FROM OUTPUT BLOCK
;CALLED WHEN CHARACTERS TAKEN FROM OUTPUT BUFFER AND TTOCT REDUCED
; T2/ DYNAMIC DATA PTR

CHKWRN:	JN TTNUS,(T2),R		;DO NOTHING IF NET USEER
	JE TTBKO,(T2),R		;RETURN IMMED IF NO FORK WAITING ON LINE
	LOAD T3,TOWRN,(T2)	;GET WARNING LEVEL COUNT
	CAMLE T3,TTOCT(T2)	;CAN WAKE?
	CALL CHKTOT		;YES, POKE SCHED
	RET

;CHKBKO - CHECK FOR WAKEUP NEEDED ON OUTPUT EVENT
; T2/ DYNAMIC DATA PTR

CHKBKO:	JE TTBKO,(T2),R		;RETURN IMMED IF NO FORK WAITING ON LINE
	CALLRET CHKTOT		;REQUEST CHECK OF OUTPUT-BLOCKED FORKS

;CLENUP - GET RID OF OUTPUT BUFFERS

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL CLENUP

;RETURNS +1: ALWAYS

;OUTPUT BUFFERS ARE EMPTY.  RELEASE THEM. IF INTERRUPT
;ON EMPTY OUTPUT BUFFER IS REQUESTED, PUT A WORD IN TTBBUF WITH BIT
;TTOIRQ SET.  TTCH7 WILL FIND IT WHEN IT IS RUN AGAIN.

CLENUP:	CALL TTRLOB		;RELEASE OUTPUT BUFFERS, SINCE EMPTY
	MOVX 3,1B<.TICTO>
	TMNE <TTMES,TTSHT>,(T2)	;A NORMAL BLOCK?
	RET
	LOAD T1,TTPSFK,(T2)	;GET FORK #
	CAIE T1,-1		;SKIP IF NOT SET
	JRST CLENU1		;SET, NON-CONTROLLING TERMINAL PSI REQUESTED
CLENU2:	TDNN 3,TTPSI(2)		;OUTPUT INTERRUPT WANTED?
	RET			;NO. RETURN
	MOVEI T1,TTOIRQ		;YES, PUT REQUEST IN BIG BUF
	JRST CLENU3

CLENU1:	LOAD T1,TTOPSI,(T2)	;GET PSI CHANNEL NUMBER
	CAIL T1,^D36		;SETUP?
	JRST CLENU2		;NO TRY OLD WAY
	MOVEI T1,TTPIRQ		;SET UP TO DO INTERRUPT
CLENU3:	SAVELN
	DYNST			;GET LINE NUMBER
	HRL T1,T2
	CALLRET BIGSTO		;REQUEST INTERRUPT


;ROUTINES CALLED FROM INTERRUPT ROUTINES

;POST OUTPUT DONE.
; 2/ LINE NUMBER

TTODON::CALL STADY		;GET ADDRESS OF DYNAMIC DATA
	 RET			;RETURN IF BECOMING ACTIVE OR INACTIVE
	CALLRET STRTTO		;START OUTPUT AGAIN
;TTDALL - ROUTINE CALLED FROM POWER RESTART CODE TO DETACH ALL JOBS
	RESCD			;MUST BE RESIDENT

TTDALL::SETZ C,			;START WITH FIRST LINE TYPE
	JRST TTDAL5		;GO CHECK THEM


;GO TO NEXT LINE. IF THE LINE TYPE CHANGES, DON'T PROCEED WITH THE NEW
;LINE. INSTEAD, GO TO THE NEXT LINE TYPE AFTER THE ONE JUST PROCESSED.
;THIS CODE ASSUMES THAT ALL LINES OF A GIVEN TYPE ARE NUMBERED CONSECUTIVELY.

TTDAL3:	LOAD C,TTSTY,(B)	;GET CURRENT TYPE
	ADDI B,1		;GO TO NEXT LINE
	CAIL B,NLINES		;BEYOND END OF LINES?
	JRST TTDAL7		;YES. GO TO NEXT LINE TYPE
	LOAD A,TTSTY,(B)	;GET TYPE OF NEXT LINE
	CAME C,A		;NEW TYPE?
	JRST TTDAL7		;YES. GO INCREMENT THE LINE TYPE

;TRANSFER ACCORDING TO THE VECTOR IN A. CERTAIN TYPES ARE NEVER
;PROCESSED.

TTDAL8:	TDCALX C,<<FE,RSKP>,<NT,RSKP>,<ML,RSKP>,<CH,RSKP>,<TV,RSKP>> ;SKIP IF DETACH SHOULD BE DONE
	 JRST TTDAL7		;DON'T DO IT

;DETACH THE JOB ON THIS LINE IF THERE IS ONE

	CAME B,CTYLNO		;IS THIS THE CTY?
	CALL TTJBDT		;DETACH THE JOB
	JRST TTDAL3		;GO PROCESS NEXT LINE

;FINISHED THE CURRENT LINE TYPE OR THE CURRENT TYPE IS NOT TO BE PROCESSED
;GO TO THE NEXT TYPE AND SEE IF IT IS TO BE PROCESSED

TTDAL7:	AOS C			;GO TO NEXT LINE TYPE
	CAIL C,NLTYPS		;BEYOND END OF LEGAL TYPES?
	RET			;YES. DONE ALL LINES
TTDAL5:	MOVE B,TT1LIN(C)	;GET FIRST LINE OF THIS TYPE
	JRST TTDAL8
;ROUTINES TO ENABLE/DISABEL DATASETS.
;CLOBBERS ALL TEMP REGISTERS:

DTRMEN::TDZA D,D		;GET A ZERO TO DO ENABLE
DTRMDS::MOVEI D,1		;GET A ONE TO DISABLE
	SAVEQ
 	MOVSI Q1,-NLTYPS	;DO ALL LINE TYPES
TTLIL2:	TDCALX Q1,<<FE,FEDABL>>,<RET>
	AOBJN Q1,TTLIL2
	RET

;3005 Begin addition
	SWAPCD
;Call here to get current TTY # (or host if net tty) into T2

HSTTY::	MOVE T2,CTRLTT		;
	TDCALL S,<<NT,NTHST>>	;
	RET			;Value returned in T2

;3005 End addition

	RESCD

TTBUGH:	BUG(BADTTY)
	RET

;3005 Begin addition (1 line)
IF2,<	PURGE TDCALL, ..TDC1, ..TDC2, ..TDC3, TDCALX
>