+TITLE READCH TELETYPE DEVICE HANDLER FOR MUDDLE
+
+RELOCATABLE
+
+.INSRT MUDDLE >
+
+SYSQ
+
+IF1,[
+IFE ITS,.INSRT STENEX >
+]
+
+.GLOBAL BUFRIN,CHRCNT,SYSCHR,ECHO,BYTPTR,ERASCH,KILLCH,BRKCH,AGC,CHRWRD,W1CHAR,GWB
+.GLOBAL IOIN2,READC,WRONGC,BRFCHR,ESCAP,TTYOPE,MTYI,MTYO,IMTYO,INMTYO,NOTTY,DEMFLG,TTYOP2,OPSYS
+.GLOBAL IBLOCK,PVSTOR,SPSTOR
+.GLOBAL RRESET,TTICHN,TTOCHN,CHANNO,STATUS,BRFCH2,TTYBLK,TTYUNB,WAITNS
+.GLOBAL EXBUFR,INCHAR,BYTDOP,BUFSTR,LSTCH,CHNCNT,DIRECT,IOINS,IBLOCK,INCONS
+.GLOBAL BADCHN,WRONGD,CHNLOS,MODE1,MODE2,GMTYO,IDVAL,GETCHR,PAGLN,LINLN
+.GLOBAL RDEVIC,DEMFLG,READ,MAKACT,CITOP,MPOPJ,CIMAGE,GTLPOS,LINPOS
+.GLOBAL NTTYPE,CLRSTR
+
+TTYOUT==1
+TTYIN==2
+
+; FLAGS CONCERNING TTY CHANNEL STATE
+
+N.ECHO==1 ; NO INPUT ECHO
+N.CNTL==2 ; NO RUBOUT ^L ^D ECHO
+N.IMED==4 ; ALL CHARS WAKE UP
+N.IME1==10 ; SOON WILL BE N.IMED
+CNTLPC==20 ; USE ^P CODE MODE IOT
+N.ESC==40
+
+; OPEN BLOCK MODE BITS
+OUT==1
+IMAGEM==4
+ASCIIM==0
+UNIT==0
+
+IFE ITS,[
+
+DP%AG1==200000,,0
+DP%AG2==100000,,0
+
+TC%MOV==400000,,0
+TC%CLR==40000,,0
+
+.VTUP==3
+.VTMOV==7
+.VTCLR==15
+.VTCEL==17
+.VTBEC==21
+]
+
+; READC IS CALLED BY PUSHJ P,READC
+; B POINTS TO A TTY FLAVOR CHANNEL
+; ONE CHARACTER IS RETURNED IN A
+; BECOMES INTERRUPTABLE IF NO CHARACTERS EXISTS
+
+; HERE TO ASK SYSTEM FOR SOME CHARACTERS
+
+INCHAR: IRP A,,[0,C,D,E] ;SAVE ACS
+ PUSH P,A
+ TERMIN
+ MOVE E,BUFRIN(B) ; GET AUX BUFFER
+ MOVE D,BYTPTR(E)
+ HLRE 0,E ;FIND END OF BUFFER
+ SUBM E,0
+ ANDI 0,-1 ;ISOLATE RH
+ MOVE C,SYSCHR(E) ; GET FLAGS
+
+INCHR1: TRNE C,N.IMED+N.CNTL ; SKIP IF NOT IMMEDIATE
+ JRST DONE
+ TLZE C,N.ESC ; SKIP IF NOT ESCAPED
+ JRST INCHR2 ; ESCAPED
+ CAMN A,ESCAP(E) ; IF ESCAPE
+ TLO C,N.ESC ; REMEMBER
+ CAMN A,BRFCH2(E)
+ JRST BRF
+ CAMN A,BRFCHR(E) ;BUFFER PRINT CHAR
+ JRST CLEARQ ;MAYBE CLEAR SCREEN
+ CAMN A,BRKCH(E) ;IS THIS A BREAK?
+ JRST DONE ;YES, DONE
+ CAMN A,ERASCH(E) ;ARE IS IT ERASE?
+ JRST ERASE ;YES, GO PROCESS
+ CAMN A,KILLCH(E) ;OR KILL
+ JRST KILL
+
+INCHR2: PUSHJ P,PUTCHR ;PUT ACHAR IN BUFFER
+INCHR3: MOVEM D,BYTPTR(E)
+ JRST DONE1
+
+DONE: SKIPL A ; IF JUST BUFFER FORCE, SKIP
+ PUSHJ P,PUTCHR ; STORE CHAR
+ MOVEI A,N.IMED ; TURN OFF IMEDIACY
+ ANDCAM A,SYSCHR(E)
+ MOVEM D,BYTPTR(E)
+ PUSH TP,$TCHAN ; SAVE CHANNEL
+ PUSH TP,B
+ MOVE A,CHRCNT(E) ; GET # OF CHARS
+ SETZM CHRCNT(E)
+ PUSH P,A
+ ADDI A,4 ; ROUND UP
+ IDIVI A,5 ; AND DOWN
+ PUSHJ P,IBLOCK ; GET CORE
+ HLRE A,B ; FIND D.W.
+ SUBM B,A
+ MOVSI 0,TCHRS+.VECT. ; GET TYPE
+ MOVEM 0,(A) ; AND STORE
+ MOVEI D,-1(B) ; COPY PNTR
+ MOVE C,(P) ; CHAR COUNT
+ HRLI D,010700
+ HRLI C,TCHSTR
+ PUSH TP,$TUVEC
+ PUSH TP,B
+ PUSHJ P,INCONS ; CONS IT ON
+ MOVE C,-2(TP) ; GET CHAN BACK
+ MOVEI D,EXBUFR(C) ; POINT TO BUFFER LIST
+ HRRZ 0,(D) ; LAST?
+ JUMPE 0,.+3
+ MOVE D,0
+ JRST .-3 ; GO UNTIL END
+ HRRM B,(D) ; SPLICE
+
+; HERE TO BLT IN BUFFER
+
+ MOVE D,BUFRIN(C) ; POINT TO COMPLETED BUFFER
+ HRRZ C,(TP) ; START OF NEW STRING
+ HRLI C,BYTPTR+1(D) ; 1ST WORD OF CHARS
+ MOVE E,[010700,,BYTPTR(E)]
+ EXCH E,BYTPTR(D) ; END OF STRING
+ MOVEI E,-BYTPTR(E)
+ ADD E,(TP) ; ADD TO START
+ BLT C,-1(E)
+ MOVE B,-2(TP) ; CHANNEL BACK
+ POP P,C
+ SOJG C,.+3
+ MOVE E,BUFRIN(B)
+ SETZM BYTPTR+1(E)
+ SUB TP,[4,,4] ; FLUSH JUNK
+ PUSHJ P,TTYUNB ; UNBLOCK THIS TTY
+DONE1: IRP A,,[E,D,C,0]
+ POP P,A
+ TERMIN
+ POPJ P,
+\f
+; HERE TO ERASE A CHARACTER
+
+BARFC1: PUSHJ P,RUBALT ; CAN WE RUBOUT AN ALTMODE?
+ JRST BARFCR ; NO, C.R.
+ JRST ERASAL
+
+ERASE: SKIPN CHRCNT(E) ;ANYTHING IN BUFFER?
+ JRST BARFC1 ;NO, MAYBE TYPE CR
+
+ERASAL: SOS CHRCNT(E) ;DELETE FROM COUNT
+ LDB A,D ;RE-GOBBLE LAST CHAR
+IFN ITS,[
+ LDB C,[600,,STATUS(B)] ; CHECK FOR DISPLAY
+ CAIE C,2 ; SKIP IF IT IS
+]
+IFE ITS,[
+ HLRE C,STATUS(B) ; CONTAINS RESULT OF GTTYP
+ SKIPN DELSTR(C) ; INTERESTING DELETION METHOD?
+]
+ JUMPGE C,TYPCHR ; DELETE BY ECHOING DELETED CHAR
+ SKIPN ECHO(E) ; SKIP IF ECHOABLE
+ JRST NECHO
+ PUSHJ P,CHRTYP ; FOUND OUT DISPLAY BEHAVIOR
+ SKIPGE C,FIXIM2(C) ; METHOD OF FLUSHING THIS CHARACTER
+ JRST (C) ; DISPATCH TO FUNNY ONES
+
+NOTFUN: PUSHJ P,DELCHR ; DELETE ONE CHARACTER
+ SOJG C,.-1 ; AND LOOP UNTIL GOT THEM ALL
+
+; REJOINS HERE TO UPDATE BUFFER POINTER, ETC.
+NECHO: ADD D,[70000,,0] ;DECREMENT BYTE POINTER
+ JUMPGE D,INCHR3 ;AND GO ON, UNLESS BYTE POINTER LOST
+ SUB D,[430000,,1] ;FIX UP BYTE POINTER
+ JRST INCHR3
+\f
+; RUB OUT A CHARACTER BY ECHOING IT (NON-DISPLAYS)
+TYPCHR: SKIPE C,ECHO(E)
+ XCT C
+ JRST NECHO
+
+; SPECIAL HACKS FOR RUBBING OUT ON DISPLAYS
+
+; RUB OUT A LINE FEED
+LFKILL: PUSHJ P,LNSTRV
+ JRST NECHO
+
+LNSTRV: PUSH P,0 ; STORE USEFUL DATA
+IFN ITS,[
+ TLO 0,CNTLPC ; SWITCH ON TEMPORARY ^P MODE
+ MOVEI A,20 ; ^P
+ XCT ECHO(E)
+ MOVEI A,"U ; U , MOVE UP ONE LINE
+ XCT ECHO(E)
+]
+IFE ITS,[
+ PUSH P,B
+ MOVE B,TTOCHN+1
+ HLRE A,STATUS(B) ; terminal type
+ JUMPGE A,UPCRF
+ MOVE A,1(B) ; DISPLAY IN VTS MODE
+ MOVEI B,.VTUP
+ VTSOP
+ JRST UPCXIT
+UPCRF: PUSHJ P,GETPOS ; HERE FOR DISPLAY STUFF IN IMAGE MODE
+ SOS LINPOS(B)
+ PUSHJ P,SETPOS
+UPCXIT: POP P,B
+]
+ POP P,0 ; RESTORE USEFUL DATA
+ POPJ P,
+
+; RUB OUT A BACK SPACE
+BSKILL: PUSHJ P,GETPOS ; CURRENT POSITION TO A
+ PUSHJ P,SETPOS ; POSITION DISPLAY CURSOR
+ PUSH P,0 ; STORE USEFUL DATA
+IFN ITS,[
+ TLO 0,CNTLPC ; SWITCH ON TEMPORARY ^P MODE
+ MOVEI A,20 ; ^P
+ XCT ECHO(E)
+ MOVEI A,"L ; L , DELETE TO END OF LINE
+ XCT ECHO(E)
+]
+IFE ITS,[
+ HLRE A,STATUS(B)
+ JUMPGE A,CLECRF
+ PUSH P,B
+ MOVE A,1(B)
+ MOVEI B,.VTCEL
+ VTSOP
+ POP P,B
+ JRST CLEXIT
+
+CLECRF: MOVEI 0,EOLSTR(A)
+ PUSHJ P,STBOUT
+]
+CLEXIT: POP P,0 ; RESTORE USEFUL DATA
+ JRST NECHO
+
+; RUB OUT A TAB
+TBKILL: PUSHJ P,GETPOS
+ ANDI A,7
+ SUBI A,10 ; A -NUMBER OF DELS TO DO
+ PUSH P,A
+ PUSHJ P,DELCHR
+ AOSE (P)
+ JRST .-2
+ SUB P,[1,,1]
+ JRST NECHO
+
+; ROUTINE TO DEL CHAR ON DISPLAY
+DELCHR: PUSH P,0 ; STORE USEFUL DATA
+IFN ITS,[
+ TLO 0,CNTLPC ; SWITCH ON TEMPORARY ^P MODE
+ MOVEI A,20
+ XCT ECHO(E)
+ MOVEI A,"X
+ XCT ECHO(E)
+]
+IFE ITS,[
+ HLRE A,STATUS(B)
+ JUMPGE A,DELCRF
+ PUSH P,B
+ MOVE A,1(B)
+ MOVEI B,.VTBEC ;BACKSPACE AND ERASE
+ VTSOP
+ POP P,B
+ JRST DELXIT
+DELCRF: MOVEI 0,DELSTR(A)
+ PUSHJ P,STBOUT
+]
+DELXIT: POP P,0 ;RESTORE USEFUL DATA
+ POPJ P,
+
+; DELETE FOUR-CHARACTER LOSSAGES
+FOURQ: PUSH P,CNOTFU
+FOURQ2: MOVEI C,2 ; FOR ^Z AND ^_
+ CAMN B,TTICHN+1 ; SKIP IF NOT CONSOLE TTY
+ MOVEI C,4
+CNOTFU: POPJ P,NOTFUN
+
+; HERE IF KILLING A C.R., RE-POSITION CURSOR
+CRKILL: PUSHJ P,GETPOS ; COMPUTE LINE POS
+ PUSHJ P,SETPOS
+ JRST NECHO
+\f
+; HERE TO SET CURRENT CURSOR POSITION, USUALLY TO END OF LINE
+; A/ POSITION TO GO TO
+SETPOS: PUSH P,0 ; STORE USEFUL DATA
+IFN ITS,[
+ TLO 0,CNTLPC ; SWITCH ON TEMPORARY ^P MODE
+ PUSH P,A ; SAVE POS
+ MOVEI A,20
+ XCT ECHO(E)
+ MOVEI A,"H
+ XCT ECHO(E)
+ POP P,A
+ ADDI A,10 ; MINIMUM CURSOR POS
+ XCT ECHO(E) ; HORIZ POSIT AT END OF LINE
+]
+IFE ITS,[
+ HLRE 0,STATUS(B)
+ JUMPGE ABPCRF
+
+ PUSH P,B ; VTS ABSOLUTE POSITIONING
+ PUSH P,C
+ PUSH P,A
+ PUSHJ P,GTLPOS
+ HRL C,A ; LINE NUMBER
+ POP P,A
+ HRR C,A ; COLUMN NUMBER
+ MOVE A,1(B)
+ MOVEI B,.VTMOV
+ HRLI B,(DP%AG1+DP%AG2)
+ VTSOP
+ POP P,C
+ POP P,B
+ JRST ABPXIT
+
+ABPCRF: ADD 0,[SETZ POSTAB]
+ XCT @0 ; ROUTINES FOR ABSOLUTE POSITIONING (UGH)
+]
+ABPXIT: POP P,0 ; RESTORE USEFUL DATA
+ POPJ P,
+
+; HERE TO CALCULATE CURRENT CURSOR POSITION
+; RETURNS A/ CURSOR POS (CORRESPONDS TO EOL, TOO)
+GETPOS: PUSH P,0
+ MOVEI 0,0 ; COUNT OF CHARACTER POSITIONS
+ PUSH P,[010700,,BYTPTR(E)] ; POINT TO BUFFER
+ PUSH P,CHRCNT(E) ; NUMBER THEREOF
+
+GETPO1: SOSGE (P) ; COUNT DOWN
+ JRST GETPO2
+ ILDB A,-1(P) ; CHAR FROM BUFFER
+ CAIN A,15 ; SKIP IF NOT CR
+ MOVEI 0,0 ; C.R., RESET COUNT
+ PUSHJ P,CHRTYP ; GET TYPE
+ XCT FIXIM3(C) ; GET FIXED COUNT
+ ADD 0,C
+ JRST GETPO1
+
+GETPO2: MOVE A,0 ; RET COUNT
+ MOVE 0,-2(P) ; RESTORE AC 0
+ SUB P,[3,,3]
+ POPJ P,
+
+; FIGURE OUT HOW MANY CHARACTER POSITIONS A CHARACTER TAKES
+CHRTYP: MOVEI C,0 ; NUMBER OF FLUSHEES
+ CAILE A,37 ; SKIP IF CONTROL CHAR
+ POPJ P,
+ PUSH TP,$TCHAN
+ PUSH TP,B ; SAVE CHAN
+ IDIVI A,12. ; FIND SPECIAL HACKS
+ MOVE A,FIXIML(A) ; GET CONT WORD
+ IMULI B,3
+ ROTC A,3(B) ; GET CODE IN B
+ ANDI B,7
+ MOVEI C,(B)
+ MOVE B,(TP) ; RESTORE CHAN
+ SUB TP,[2,,2]
+ POPJ P,
+
+; TABLE OF HOW MANY OR HOW TO FIND OUT
+FIXIM2: 1
+ 2
+ SETZ FOURQ
+ SETZ CRKILL
+ SETZ LFKILL
+ SETZ BSKILL
+ SETZ TBKILL
+
+; TABLE OF WHAT TO ADD TO HPOS ON ENCOUNTERING CHARACTER
+FIXIM3: MOVEI C,1
+ MOVEI C,2
+ PUSHJ P,FOURQ2
+ MOVEI C,0
+ MOVEI C,0
+ MOVNI C,1
+ PUSHJ P,CNTTAB
+
+; HORRIBLE KLUDGE TO COUNT SPACES FOR A TAB
+CNTTAB: ANDCMI 0,7 ; GET COUNT INCUDING TAB HACK
+ ADDI 0,10
+ MOVEI C,0
+ POPJ P,
+
+; TYPE TABLE FOR EACH CONTROL CHARACTER
+FIXIML: 111111,,115641 ; CNTL @ABCDE,,FGHIJK
+ 131111,,111111 ; LMNOPQ,,RSTUVW
+ 112011,,120000 ; XYZ LBRAK \ RBRAK,,^ _
+\f
+; HERE TO KILL THE WHOLE BUFFER
+
+KILL: PUSHJ P,RUBALT ; COULD WE RUB OUT ALT MODE
+ JFCL
+ CLEARM CHRCNT(E) ;NONE LEFT NOW
+ MOVE D,[010700,,BYTPTR(E)] ;RESET POINTER
+
+BARFCR:
+IFN ITS,[
+ MOVE A,ERASCH(E) ;GET THE ERASE CHAR
+ CAIN A,177 ;IS IT RUBOUT?
+]
+ PUSHJ P,CRLF1 ; PRINT CR-LF
+ JRST INCHR3
+
+; SKIP IF CAN RUB OUT AN ALTMODE
+RUBALT: PUSH TP,$TCHAN
+ PUSH TP,B
+ HRRZ A,FSAV(TB) ; ARE WE IN READ ?
+ CAIE A,READ
+ JRST RUBAL1
+ MOVEI A,(TP)
+ SUBI A,(TB)
+IFN ITS,CAIG A,53 ; SOMEWHAT HEURISTIC (WATCH OUT IN NEW VERSIONS!!!!!!)
+IFE ITS,CAIG A,17
+ JRST RUBAL1
+ HRRZ A,BUFSTR-1(B) ; IS BUFFER OF SAME RUN OUT?
+ JUMPN A,RUBAL1 ; NO
+ MOVE B,IMQUOTE INCHAN
+ PUSHJ P,IDVAL ; REALLY CHECK IT OUT
+ MOVE C,(TP)
+ CAME C,B
+ JRST RUBAL1
+ MOVE A,BUFSTR-1(B)
+ MOVE B,BUFSTR(B)
+ PUSHJ P,CITOP
+ ANDI A,-1
+ MOVE D,[10700,,BYTPTR(E)]
+ MOVE E,(TP)
+ MOVE E,BUFRIN(E)
+ MOVEM A,CHRCNT(E)
+; CHECK WINNAGE OF BUFFER
+ ILDB 0,D
+ ILDB C,B
+ CAIE 0,(C)
+ JRST RUBAL1
+ SOJG A,.-4
+ MOVE B,(TP)
+ MOVEM D,BYTPTR(E)
+ MOVE A,[JRST RETREA]
+ MOVEM A,WAITNS(B)
+ AOS (P)
+ SUB TP,[2,,2]
+ POPJ P,
+
+RUBAL1: MOVE B,(TP)
+ MOVE D,[010700,,BYTPTR(E)]
+ SETZM CHRCNT(E)
+ SUB TP,[2,,2]
+ POPJ P,
+
+RETREA: PUSHJ P,MAKACT
+ HRLI A,TFRAME
+ PUSH TP,A
+ PUSH TP,B
+ MCALL 1,RETRY
+ JRST TTYBLK
+\f
+; HERE TO CLEAR SCREEN AND RETYPE BUFFER
+
+CLEARQ:
+IFN ITS,[
+ MOVE A,STATUS(B) ; FIGURE OUT CONSOLE TYPE
+ ANDI A,77
+ CAIN A,2 ; DISPLAY?
+]
+IFE ITS,[
+ HLRE A,STATUS(B)
+ SKIPE CLRSTR(A) ; TRY IT ONLY ON DISPLAYS
+]
+ PUSHJ P,CLR ; CLEAR SCREEN
+
+; HERE TO RETYPE BUFFER
+
+BRF: MOVE C,[010700,,BYTPTR(E)] ;POINT TO START OF BUFFER
+ SKIPN ECHO(E) ;ANY ECHO INS?
+ JRST NECHO
+IFE ITS,PUSH P,B
+ MOVE B,TTOCHN+1
+ PUSHJ P,CRLF2
+IFE ITS,AOS LINPOS(B)
+ PUSH P,CHRCNT(E)
+BRF1: SOSGE (P)
+ JRST DECHO
+ ILDB A,C ;GOBBLE CHAR
+ XCT ECHO(E) ;ECHO IT
+IFE ITS,[
+ CAIN A,12
+ AOS LINPOS(B)
+]
+ JRST BRF1 ;DO FOR ENTIRE BUFFER
+
+DECHO: SUB P,[1,,1]
+IFE ITS,POP P,B
+ JRST INCHR3
+
+; ROUTINE TO CRLF ON ANY TTY
+
+CRLF1: SKIPN ECHO(E)
+ POPJ P, ; NO ECHO INS
+CRLF2: MOVEI A,15
+ XCT ECHO(E)
+ MOVEI A,12
+ XCT ECHO(E)
+ POPJ P,
+
+; CLEAR SCREEN
+CLR: SKIPN C,ECHO(E) ;ONLY IF INS EXISTS
+ POPJ P,
+ PUSH P,0
+IFN ITS,[
+ TLO 0,CNTLPC ;SWITCH ON TEMPORARY ^P MODE
+ MOVEI A,20 ;ERASE SCREEN
+ XCT C
+ MOVEI A,103
+ XCT C
+]
+IFE ITS,[
+ JUMPGE A,CLRCRF
+ PUSH P,B
+ MOVE A,1(B)
+ MOVEI B,.VTCLR
+ VTSOP
+ POP P,B
+ JRST CLRXIT
+
+CLRCRF: MOVEI 0,CLRSTR(A)
+ PUSHJ P,STBOUT
+ PUSH P,B
+ MOVE B,TTOCHN+1
+ SETZM LINPOS(B)
+ POP P,B
+]
+CLRXIT: POP P,0 ;RESTORE USEFUL DATA
+ POPJ P,
+
+IFE ITS,[
+
+STBOUT: PUSH P,B
+ SKIPE IMAGFL
+ JRST STBOU1
+ MOVE A,1(B)
+ HRRZ B,STATUS(B)
+ TRZ B,300
+ SFMOD
+STBOU1: HRLI 0,440700
+ ILDB A,0
+ JUMPE A,STBOUX
+ PBOUT
+ JRST .-3
+
+STBOUX: SKIPE IMAGFL
+ JRST STBOU2
+ MOVE B,(P)
+ MOVE A,1(B)
+ HRRZ B,STATUS(B)
+ SFMOD
+STBOU2: POP P,B
+ POPJ P,
+\f
+; SPECIAL CASE GOODIES FOR DISPLAY TERMINALS
+
+NTTYPE==40 ; MAX TERMINAL TYPES SUPPORTED
+
+
+; HOW TO CLEAR SCREENS ON TOPS-20/TENEX
+CLRSTR: 0
+ 0
+ 0
+ 0
+ ASCII /\7f\12/ ; ITS SOFTWARE
+ ASCII /\1d\1e/ ; DATAMEDIA
+ ASCII /\eH\eJ/ ; HP2640
+ 0
+ 0
+ 0
+ 0
+ ASCII /\eH\eJ/ ; VT50
+ 0
+ ASCII /\e(\7f/ ; GT40
+ 0
+ ASCII /\eH\eJ/ ; VT52
+ 0
+ 0
+ ASCII /\eH\eJ/ ; VT100
+ ASCII /\eH\eJ/ ; TELERAY
+ ASCII /\eH\eJ/ ; H19
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+IFN <.-CLRSTR>-NTTYPE,PRINTC /ERROR -- CLEAR SCREEN TABLE LOSES
+/
+
+; HOW TO RUB OUT ON VARIOUS TERMINALS
+DELSTR: 0
+ 0
+ 0
+ 0
+ ASCII /\7f\v\7f\ 6/ ; ITS SOFTWARE DISPLAY
+ 0
+ ASCII /\eD\eK/ ; HP2640
+ 0
+ 0
+ 0
+ 0
+ ASCII /\eD\eK/ ; VT50
+ 0
+ 0
+ 0
+ ASCII /\eD\eK/ ; VT52
+ 0
+ 0
+ ASCII /\eD\eK/ ; VT100
+ ASCII /\eD\eK/ ; TELERAY
+ ASCII /\eD\eK/ ; H19
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+IFN <.-DELSTR>-NTTYPE,PRINTC /ERROR -- DELETE TABLE LOSES
+/
+
+; CLEAR TO EOL
+EOLSTR: 0
+ 0
+ 0
+ 0
+ ASCII /\7f\ 5/ ; ITS SOFTWARE DISPLAY
+ 0
+ ASCII /\eK/ ; HP2640
+ 0
+ 0
+ 0
+ 0
+ ASCII /\eK/ ; VT50
+ 0
+ 0
+ 0
+ ASCII /\eK/ ; VT52
+ 0
+ 0
+ ASCII /\eK/ ; VT100
+ ASCII /\eK/ ; TELERAY
+ ASCII /\eK/ ; H19
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+IFN <.-EOLSTR>-NTTYPE,PRINTC /ERROR -- END OF LINE TABLE LOSES
+/
+
+POSTAB: JFCL
+ JFCL
+ JFCL
+ JFCL
+ PUSHJ P,PSOFT ; ITS SOFTWARE
+ JFCL
+ PUSHJ P,PVT52 ; HP2640
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+ PUSHJ P,PVT52 ; VT50
+ JFCL
+ JFCL
+ JFCL
+ PUSHJ P,PVT52 ; VT52
+ JFCL
+ JFCL
+ PUSHJ P,PVT52 ; VT100
+ PUSHJ P,PVT52 ; TELERAY
+ PUSHJ P,PVT52 ; H19
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+ JFCL
+IFN <.-POSTAB>-NTTYPE,PRINTC /ERROR -- ABSOLUTE POSITION TABLE LOSES
+/
+
+
+
+\f
+; ROUTINES FOR ABSOLUTE POSITIONING ON TENEX/TOPS-20
+
+PSOFT: PUSH P,A
+ PUSHJ P,TNXIMG
+ MOVEI A,177
+ XCT ECHO(E)
+ MOVEI A,21
+ XCT ECHO(E)
+ PUSHJ P,GTLPOS
+ XCT ECHO(E)
+ POP P,A
+ XCT ECHO(E)
+ PUSHJ P,TNXASC
+ POPJ P,
+
+PVT52: PUSH P,A
+ PUSHJ P,TNXIMG
+ MOVEI A,33
+ XCT ECHO(E)
+ MOVEI A,"Y
+ XCT ECHO(E)
+ PUSHJ P,GTLPOS
+ ADDI A,40 ; MUDDLE PAGES START AT 0, VT52 AT 1
+ XCT ECHO(E)
+ POP P,A
+ ADDI A,40 ; DITTO COLUMNS
+ XCT ECHO(E)
+ PUSHJ P,TNXASC
+ POPJ P,
+
+TNXIMG: PUSH P,B
+ MOVE A,1(B)
+ MOVE B,STATUS(B)
+ TRZ B,300
+ SFMOD
+ POP P,B
+ POPJ P,
+
+TNXASC: PUSH P,B
+ MOVE A,1(B)
+ HRRZ B,STATUS(B)
+ SFMOD
+ POP P,B
+ POPJ P,
+]
+\f
+PUTCHR: AOS CHRCNT(E) ;COUNT THIS CHARACTER
+ IBP D ;BUMP BYTE POINTER
+IFE ITS,[
+ HRRZ C,D
+ ADDI C,(E)
+ CAIG 0,(C) ;DONT SKIP IF BUFFER FULL
+]
+IFN ITS, CAIG 0,@D ;DONT SKIP IF BUFFER FULL
+ PUSHJ P,BUFULL ;GROW BUFFER
+IFE ITS,[
+ CAIN A,37 ; CHANGE EOL TO CRLF
+ MOVEI A,15
+]
+ DPB A,D ;CLOBBER BYTE POINTER IN
+ MOVE C,SYSCHR(E) ; FLAGS
+IFE ITS,[
+ POPJ P,
+]
+IFN ITS,[
+ TRNN C,N.IMED+N.CNTL
+ CAIE A,15 ; IF CR INPUT, FOLLOW WITH LF
+ POPJ P,
+ MOVEI A,12 ; GET LF
+ JRST PUTCHR
+]
+; BUFFER FULL, GROW THE BUFFER
+
+BUFULL: MOVEM D,BYTPTR(E)
+ PUSH TP,$TCHAN ;SAVE B
+ PUSH TP,B
+ PUSH P,A ; SAVE CURRENT CHAR
+ HLRE A,BUFRIN(B)
+ MOVNS A
+ ADDI A,100 ; MAKE ONE LONGER
+ PUSHJ P,IBLOCK ; GET IT
+ MOVE A,(TP) ;RESTORE CHANNEL POINTER
+ SUB TP,[2,,2] ;AND REMOVE CRUFT
+ MOVE E,BUFRIN(A) ;GET AUX BUFFER POINTER
+ MOVEM B,BUFRIN(A)
+ HLRE 0,E ;RECOMPUTE 0
+ MOVSI E,(E)
+ HRRI E,(B) ; POINT TO DEST
+ SUB B,0
+ BLT E,(B)
+ MOVEI 0,100-2(B)
+ MOVE B,A
+ MOVE E,BUFRIN(B)
+ POP P,A
+ MOVE D,BYTPTR(E)
+ POPJ P,
+
+; SUBROUTINE TO FLUSH BUFFER
+
+RRESET: SETZM LSTCH(B) ; CLOBBER RE-USE CHAR
+ MOVE E,BUFRIN(B) ;GET AUX BUFFER
+ SETZM CHRCNT(E)
+ MOVEI D,N.IMED+N.IME1
+ ANDCAM D,SYSCHR(E)
+ MOVE D,[010700,,BYTPTR(E)] ;RESET BYTE POINTER
+ MOVEM D,BYTPTR(E)
+ MOVE D,CHANNO(B) ;GOBBLE CHANNEL
+IFN ITS,[
+ SETZM CHNCNT(D) ; FLUSH COUNTERS
+ LSH D,23. ;POSITION
+ IOR D,[.RESET 0]
+ XCT D ;RESET ITS CHANNEL
+]
+IFE ITS,[
+ MOVEI A,100 ; TTY IN JFN
+ CFIBF
+]
+ SETZM EXBUFR(B) ; CLOBBER STAKED BUFFS
+ MOVEI C,BUFSTR-1(B) ; FIND D.W.
+ PUSHJ P,BYTDOP
+ SUBI A,2
+ HRLI A,010700
+ MOVEM A,BUFSTR(B)
+ HLLZS BUFSTR-1(B)
+ POPJ P,
+\f
+; SUBROUTINE TO ESTABLISH ECHO IOINS
+
+MFUNCTION ECHOPAIR,SUBR
+
+ ENTRY 2
+
+ GETYP A,(AB) ;CHECK ARG TYPES
+ GETYP C,2(AB)
+ CAIN A,TCHAN ;IS A CHANNEL
+ CAIE C,TCHAN ;IS C ALSO
+ JRST WRONGT ;NO, ONE OF THEM LOSES
+
+ MOVE A,1(AB) ;GET CHANNEL
+ PUSHJ P,TCHANC ; VERIFY TTY IN
+ MOVE D,3(AB) ;GET OTHER CHANNEL
+ HRRZ 0,-2(D) ; GET BITS
+ TRC 0,C.OPN+C.PRIN
+ TRNE 0,C.OPN+C.PRIN
+ JRST WRONGD
+
+ MOVE B,BUFRIN(A) ;GET A'S AUX BUFFER
+IFN ITS,[
+ HRLZ C,CHANNO(D) ; GET CHANNEL
+ LSH C,5
+ IOR C,[.IOT A] ; BUILD AN IOT
+ MOVEM C,ECHO(B) ;CLOBBER
+]
+CHANRT: MOVE A,(AB)
+ MOVE B,1(AB) ;RETURN 1ST ARG
+ JRST FINIS
+
+TCHANC: HRRZ 0,-2(A) ; GET BITS
+ TRC 0,C.OPN+C.READ
+ TRNE 0,C.OPN+C.READ
+ JRST BADCHN
+IFN ITS,[
+ LDB C,[600,,STATUS(A)] ;GET A CODE
+ CAILE C,2 ;MAKE SURE A TTY FLAVOR DEVICE
+ JRST WRONGC
+ POPJ P,
+]
+IFE ITS,[
+ PUSH P,A
+ MOVE A,1(A)
+ DVCHR
+ LDB A,[221100,,B] ;DEVICE TYPE FIELD
+ CAIE A,12 ;TTY
+ CAIN A,13 ;PTY
+ SKIPA
+ JRST WRONGC ;NOT A TTY, HOPE WE DON'T GET HERE IN LISTEN
+ POP P,A
+ POPJ P,
+]
+\f
+; TTY OPEN
+
+IFE ITS,[
+TTYOPEN:
+TTYOP2: SKIPE DEMFLG
+ POPJ P,
+ MOVE C,TTOCHN+1
+ HLLZS IOINS-1(C)
+ MOVEI A,-1 ; TERMINAL; STAYS HERE THROUGHOUT ROUTINE
+ MOVEI 2,175100 ; MAGIC BITS (SEE TENEX MANUAL)
+ SFMOD ; ZAP
+ RFMOD ; LETS FIND SCREEN SIZE
+ MOVEM B,STATUS(C)
+ LDB B,[220700,,B] ; GET PAGE WIDTH
+ JUMPG B,.+2
+ MOVEI B,80. ; MUST BE VIRTUAL, SO MAKE IT 80.
+ MOVEM B,LINLN(C)
+ LDB B,[310700,,STATUS(C)] ; AND LENGTH
+ MOVEM B,PAGLN(C)
+ SKIPE OPSYS ; CHECK FOR TOPS-20
+ JRST NONVTS ; ONLY TOPS-20 CAN HAVE VTS
+ RTCHR
+ ERJMP NONVTS ; NO RTCHR JSYS, HENCE NO VTS
+ TLNN B,(TC%MOV+TC%CLR) ; HAS MINIMAL CHARACTERISTICS?
+ JRST NONVTS ; NO GOOD ENOUGH FOR US
+ MOVNI B,1 ; TERMINAL TYPE -1 IS VTS DISPLAY
+ JRST HASVTS ; WINS
+
+NONVTS: PUSH P,C ; IDIOT GETTYP CLOBBERS C
+ GTTYP ; FIND TERMINAL TYPE
+ POP P,C
+HASVTS: HRLM B,STATUS(C) ; USED TO FIGURE OUT DISPLAY STUFF
+ MOVE B,STATUS(C)
+ MOVE C,TTICHN+1
+ MOVEM B,STATUS(C) ; SET UP INCHAN TOO
+ RFCOC ; GET CURRENT
+ AND B,[036377,,-1] ; CHANGE FOR ^@, ^A AND ^D (FOR NOW)
+ SFCOC ; AND RESUSE IT
+
+ POPJ P,
+]
+
+IFN ITS,[
+TTYOP2: .SUSET [.RTTY,,C]
+ SETZM NOTTY
+ JUMPL C,TTYNO ; DONT HAVE TTY
+
+TTYOPEN:
+ SKIPE NOTTY
+ POPJ P,
+ DOTCAL OPEN,[[1000,,TTYIN],[[SIXBIT /TTY /]]]
+ JRST TTYNO
+ DOTCAL OPEN,[[1000,,TTYOUT],[[SIXBIT /TTY /]],[5000,,1]]
+ FATAL CANT OPEN TTY
+ DOTCAL TTYGET,[[1000,,TTYOUT],[2000,,0],[2000,,A],[2000,,B]]
+ FATAL .CALL FAILURE
+ DOTCAL TTYSET,[[1000,,TTYOUT],MODE1,MODE2,B]
+ FATAL .CALL FAILURE
+
+SETCHN: MOVE B,TTICHN+1 ;GET CHANNEL
+ MOVEI C,TTYIN ;GET ITS CHAN #
+ MOVEM C,CHANNO(B)
+ .STATUS TTYIN,STATUS(B) ;CLOBBER STATUS
+
+ MOVE B,TTOCHN+1 ;GET OUT CHAN
+ MOVEI C,TTYOUT
+ MOVEM C,CHANNO(B)
+ .STATUS TTYOUT,STATUS(B)
+ SETZM IMAGFL ;RESET IMAGE MODE FLAG
+ HLLZS IOINS-1(B)
+ DOTCAL RSSIZE,[[1000,,TTYOUT],[2000,,C],[2000,,D]]
+ FATAL .CALL RSSIZE LOSSAGE
+ MOVEM C,PAGLN(B)
+ MOVEM D,LINLN(B)
+ POPJ P,
+
+; HERE IF TTY WONT OPEN
+
+TTYNO: SETOM NOTTY
+ POPJ P,
+]
+
+GTLPOS:
+IFN ITS,[
+ DOTCAL RCPOS,[[CHANNO(B)],[2000,,A]]
+ JFCL
+ HLRZS A
+ POPJ P,
+]
+IFE ITS,[
+ PUSH P,B
+ MOVE B,TTOCHN+1
+ HLRE A,STATUS(B)
+ JUMPGE A,GETCRF
+ MOVE A,1(B)
+ RFPOS
+ HLRZ A,B
+ SKIPA
+GETCRF: MOVE A,LINPOS(B)
+ POP P,B
+ POPJ P,
+]
+
+MTYI: SKIPN DEMFLG ; SKIP IF DEMON
+ SKIPE NOTTY ; SKIP IF HAVE TTY
+ FATAL TRIED TO USE NON-EXISTANT TTY
+
+; TRY TO AVOID HANGING IN .IOT TO TTY
+
+IFN ITS,[
+ DOTCAL IOT,[[1000,,TTYIN],[A],[5000,,1000]]
+ JFCL
+]
+IFE ITS,[
+
+MTYI1: PBIN
+]
+ POPJ P,
+
+INMTYO: ; BOTH ARE INTERRUPTABLE
+MTYO: ENABLE
+ PUSHJ P,IMTYO
+ DISABLE
+ POPJ P,
+
+; NON-INTERRUPTABLE VERSION, FOR ECHO INSTRUCTION AND SUCHLIKE
+IMTYO: SKIPE NOTTY
+ POPJ P, ; IGNORE, DONT HAVE TTY
+
+IFN ITS,[
+ CAIN A,177 ;DONT OUTPUT A DELETE
+ POPJ P,
+ PUSH P,B
+ MOVEI B,0 ; SETUP CONTROL BITS
+ TLNE 0,CNTLPC ; SKIP IF ^P MODE SWITCH IS OFF
+ MOVEI B,%TJDIS ; SWITCH ON TEMPORARY ^P MODE
+ DOTCAL IOT,[[1000,,TTYOUT],[A],[4000,,B]]
+ JFCL
+ POP P,B
+]
+IFE ITS, PBOUT
+ POPJ P,
+
+; HERE FOR TYO TO ANY TTY FLAVOR DEVICE
+IFN ITS,[
+GMTYO: PUSH P,0
+IFE ITS,[
+ HRRZ 0,IOINS-1(B) ; GET FLAG
+ SKIPE 0
+ PUSHJ P,REASCI ; RE-OPEN TTY
+]
+ HRLZ 0,CHANNO(B)
+ ASH 0,5
+ IOR 0,[.IOT A]
+ CAIE A,177 ; DONE OUTPUT A DELETE
+ XCT 0
+ POP P,0
+ POPJ P,
+
+REASCI: PUSH P,A
+ PUSH P,C
+IFE ITS,[
+ PUSH P,B
+ MOVE A,1(B)
+ RFMOD
+ TRO B,102
+ SFMOD
+ STPAR
+ POP P,B ]
+
+ POP P,C
+ POP P,A
+ HLLZS IOINS-1(B)
+ CAMN B,TTOCHN+1
+ SETZM IMAGFL
+ POPJ P,
+]
+
+
+WRONGC: FATAL TTYECHO--NOT ON A TTY-TYPE CHANNEL
+
+
+
+; HERE TO HANDLE TTY BLOCKING AND UNBLOCKING
+
+TTYBLK: PUSH TP,$TCHAN
+ PUSH TP,B
+ PUSH P,0
+ PUSH P,E ; SAVE SOME ACS
+IFN ITS,[
+ MOVE A,CHANNO(B) ; GET CHANNEL NUMBER
+ SOSG CHNCNT(A) ; ANY PENDING CHARS
+ JRST TTYBL1
+ SETZM CHNCNT(A)
+ MOVEI 0,1
+ LSH 0,(A)
+ .SUSET [.SIFPI,,0] ; SLAM AN INT ON
+]
+TTYBL1: MOVE C,BUFRIN(B)
+ MOVE A,SYSCHR(C) ; GET FLAGS
+ TRZ A,N.IMED
+ TRZE A,N.IME1 ; IF WILL BE
+ TRO A,N.IMED ; THE MAKE IT
+ MOVEM A,SYSCHR(C)
+IFN ITS,[
+ MOVE A,[.CALL TTYIOT] ; NON-BUSY WAIT (IF CHAR READ, LEAVE IN BUFFER
+ ; TO LET IT BE READ AT INTERRUPT LEVEL)
+ SKIPE NOTTY
+ MOVE A,[.SLEEP A,]
+]
+IFE ITS,[
+ MOVE A,[PUSHJ P,TNXIN]
+]
+ MOVEM A,WAITNS(B)
+ PUSH TP,$TCHSTR
+ PUSH TP,CHQUOTE BLOCKED
+ PUSH TP,$TPVP
+ PUSH TP,PVSTOR+1
+ MCALL 2,INTERRUPT
+ MOVSI A,TCHAN
+ MOVE PVP,PVSTOR+1
+ MOVEM A,BSTO(PVP)
+ MOVE B,(TP)
+ ENABLE
+REBLK: MOVEI A,-1 ; IN CASE SLEEPING
+ XCT WAITNS(B) ; NOW WAIT
+ JFCL
+IFE ITS, JRST .-3
+IFN ITS, JRST CHRSNR ; SNARF CHAR
+REBLK1: DISABLE ; FALL THROUG=> UNBLOCKED
+ MOVE PVP,PVSTOR+1
+ SETZM BSTO(PVP)
+ POP P,E
+ POP P,0
+ MOVE B,(TP)
+ SUB TP,[2,,2]
+ POPJ P,
+IFN ITS,[
+CHRSNR: SKIPN DEMFLG ; SKIP IF DEMON
+ SKIPE NOTTY ; TTY?
+ JRST REBLK ; NO, JUST RESET AND BLOCK
+ .SUSET [.SIFPI,,[1_<TTYIN>]]
+ JRST REBLK ; AND GO BACK
+
+TTYIOT: SETZ
+ SIXBIT /IOT/
+ 1000,,TTYIN
+ 0
+ 405000,,20000
+]
+; HERE TO UNBLOCK TTY
+
+TTYUNB: MOVE A,WAITNS(B) ; GET INS
+ CAMN A,[JRST REBLK1]
+ JRST TTYUN1
+ MOVE A,[JRST REBLK1] ; LEAVE THE SLEEP
+ MOVEM A,WAITNS(B)
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ PUSH TP,$TCHSTR
+ PUSH TP,CHQUOTE UNBLOCKED
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ MCALL 2,INTERRUPT
+ MOVE B,(TP) ; RESTORE CHANNEL
+ SUB TP,[2,,2]
+TTYUN1: POPJ P,
+
+IFE ITS,[
+; TENEX BASIC TTY I/O ROUTINE
+
+TNXIN: PUSHJ P,MTYI
+ DISABLE
+ PUSHJ P,INCHAR
+ ENABLE
+ POPJ P,
+]
+MFUNCTION TTYECHO,SUBR
+
+ ENTRY 2
+
+ GETYP 0,(AB)
+ CAIE 0,TCHAN
+ JRST WTYP1
+ MOVE A,1(AB) ; GET CHANNEL
+ PUSHJ P,TCHANC ; MAKE SURE IT IS TTY INPUT
+ MOVE E,BUFRIN(A) ; EXTRA INFO BUFFER
+IFN ITS,[
+ DOTCAL TTYGET,[CHANNO(A),[2000,,B],[2000,,C],[2000,,0]]
+ FATAL .CALL FAILURE
+]
+IFE ITS,[
+ MOVEI A,100 ; TTY JFN
+ RFMOD ; MODE IN B
+ TRZ B,6000 ; TURN OFF ECHO
+]
+ GETYP D,2(AB) ; ARG 2
+ CAIE D,TFALSE ; SKIP IF WANT ECHO OFF
+ JRST ECHOON
+
+IFN ITS,[
+ ANDCM B,[606060,,606060]
+ ANDCM C,[606060,,606060]
+
+ DOTCAL TTYSET,[CHANNO(A),B,C,0]
+ FATAL .CALL FAILURE
+]
+IFE ITS,[
+ SFMOD
+]
+
+ MOVEI B,N.ECHO+N.CNTL ; SET FLAGS
+ IORM B,SYSCHR(E)
+
+ JRST CHANRT
+
+ECHOON:
+IFN ITS,[
+ IOR B,[202020,,202020]
+ IOR C,[202020,,200020]
+ DOTCAL TTYSET,[CHANNO(A),B,C,0]
+ FATAL .CALL FAILURE
+]
+IFE ITS,[
+ TRO B,4000
+ SFMOD
+]
+ MOVEI A,N.ECHO+N.CNTL
+ ANDCAM A,SYSCHR(E)
+ JRST CHANRT
+
+
+
+; USER SUBR FOR INSTANT CHARACTER SNARFING
+
+MFUNCTION UTYI,SUBR,TYI
+
+ ENTRY
+ CAMGE AB,[-3,,]
+ JRST TMA
+ MOVE A,(AB)
+ MOVE B,1(AB)
+ JUMPL AB,.+3
+ MOVE B,IMQUOTE INCHAN
+ PUSHJ P,IDVAL ; USE INCHAN
+ GETYP 0,A ; GET TYPE
+ CAIE 0,TCHAN
+ JRST WTYP1
+IFN ITS,[
+ LDB 0,[600,,STATUS(B)]
+ CAILE 0,2
+ JRST WTYP1
+ SKIPN A,LSTCH(B) ; ANY READ AHEAD CHAR
+ JRST UTYI1 ; NO, SKIP
+ ANDI A,-1
+ SETZM LSTCH(B)
+ TLZN A,400000 ; ! HACK?
+ JRST UTYI2 ; NO, OK
+ HRRM A,LSTCH(B) ; YES SAVE
+ MOVEI A,"! ; RET AN !
+ JRST UTYI2
+
+UTYI1: MOVE 0,IOINS(B)
+ CAME 0,[PUSHJ P,GETCHR]
+ JRST WTYP1
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ MOVE C,BUFRIN(B)
+ MOVEI D,N.IME1+N.IMED
+ IORM D,SYSCHR(C) ; CLOBBER IT IN
+ DOTCAL TTYGET,[CHANNO(B),[2000,,A],[2000,,D],[2000,,0]]
+ FATAL .CALL FAILURE
+ PUSH P,A
+ PUSH P,0
+ PUSH P,D ; SAVE THEM
+ IOR D,[030303,,030303]
+ IOR A,[030303,,030303]
+ DOTCAL TTYSET,[CHANNO(B),A,D,0]
+ FATAL .CALL FAILURE
+ MOVNI A,1
+ SKIPE CHRCNT(C) ; ALREADY SOME?
+ PUSHJ P,INCHAR
+ MOVE C,BUFRIN(B) ; GET BUFFER BACK
+ MOVEI D,N.IME1
+ IORM D,SYSCHR(C)
+ PUSHJ P,GETCHR
+ MOVE B,1(TB)
+ MOVE C,BUFRIN(B)
+ MOVEI D,N.IME1+N.IMED
+ ANDCAM D,SYSCHR(C)
+ POP P,D
+ POP P,0
+ POP P,C
+ DOTCAL TTYSET,[CHANNO(B),C,D,0]
+ FATAL .CALL FAILURE
+UTYI2: MOVEI B,(A) ]
+IFE ITS,[
+ MOVE A,1(B) ;GET JFN FOR INPUT
+ ENABLE
+ BIN ;SNARF A CHARACTER
+ DISABLE
+]
+ MOVSI A,TCHRS
+ JRST FINIS
+
+MFUNCTION IMAGE,SUBR
+ ENTRY
+ JUMPGE AB,TFA ; 1 OR 2 ARGS NEEDED
+ GETYP A,(AB) ;GET THE TYPE OF THE ARG
+ CAIE A,TFIX ;CHECK IT FOR CORRECT TYPE
+ JRST WTYP1 ;WAS WRONG...ERROR EXIT
+ HLRZ 0,AB
+ CAIL 0,-2
+ JRST USEOTC
+ CAIE 0,-4
+ JRST TMA
+ GETYP 0,2(AB)
+ CAIE 0,TCHAN
+ JRST WTYP2
+ MOVE B,3(AB) ; GET CHANNEL
+IMAGE1: MOVE A,1(AB)
+ PUSHJ P,CIMAGE
+ JRST FINIS
+
+CIMAGE: SUBM M,(P)
+IFN ITS,[
+ LDB 0,[600,,STATUS(B)]
+ CAILE 0,2 ; MUST BE TTY
+ JRST IMAGFO
+ MOVE 0,IOINS(B)
+ CAMN 0,[PUSHJ P,MTYO]
+ JRST .+3
+ CAME 0,[PUSHJ P,GMTYO]
+ JRST WRONGD ]
+IFE ITS,[
+ MOVE 0,CHANNO(B) ; SEE IF TTY
+ CAIE 0,101
+ JRST IMAGFO
+]
+
+IFN ITS,[
+ DOTCAL IOT,[[5000,,2000],[CHANNO(B)],[A]]
+ JFCL
+ MOVE B,A
+]
+IFE ITS,[
+ SKIPE IMAGFL
+ JRST IMGOK
+
+ PUSH P,A
+ PUSH P,B
+ MOVSI A,1
+ HRROI B,[ASCIZ /TTY:/]
+ GTJFN
+ HALTF
+ MOVE B,[074000,,102000]
+ OPENF
+ HALTF
+ HRRZM A,IMAGFL
+ POP P,B
+ POP P,A
+IMGOK: MOVE B,IMAGFL
+ EXCH A,B
+ BOUT
+
+
+IMGEXT: MOVSI A,TFIX
+ JRST MPOPJ
+
+
+IMAGFO: PUSH TP,$TCHAN ;IMAGE OUTPUT FOR NON TTY
+ PUSH TP,B
+ PUSH P,A
+ HRRZ 0,-2(B) ; GET BITS
+ TRC 0,C.OPN+C.PRIN
+ TRNE 0,C.OPN+C.PRIN
+ JRST BADCHN
+ MOVE B,(TP)
+ PUSHJ P,GWB ; MAKE SURE CHANNEL HAS BUFFER
+ MOVE A,(P) ; GET THE CHARACTER TO DO
+ PUSHJ P,W1CHAR
+ POP P,B
+ MOVSI A,TFIX
+ SUB TP,[2,,2]
+ JRST MPOPJ
+
+
+USEOTC: MOVSI A,TATOM
+ MOVE B,IMQUOTE OUTCHAN
+ PUSHJ P,IDVAL
+ GETYP 0,A
+ CAIE 0,TCHAN
+ MOVE B,TTOCHN+1
+ MOVE A,1(B)
+ JRST IMAGE1
+
+IFN ITS,[
+IMGBLK: OUT+IMAGEM+UNIT,,(SIXBIT /TTY/)
+ 0
+ 0
+]
+
+
+IMPURE
+IMAGFL: 0
+PURE
+
+
+END
+\f
\ No newline at end of file