Split up files.
[pdp10-muddle.git] / sumex / readch.mcr116
diff --git a/sumex/readch.mcr116 b/sumex/readch.mcr116
new file mode 100644 (file)
index 0000000..bec13f5
--- /dev/null
@@ -0,0 +1,872 @@
+TITLE READC TELETYPE DEVICE HANDLER FOR MUDDLE\r
+\r
+RELOCATABLE\r
+\r
+.INSRT MUDDLE >\r
+\r
+SYSQ\r
+\r
+IF1,[\r
+IFE ITS,.INSRT MUDSYS;STENEX >\r
+]\r
+\r
+.GLOBAL BUFRIN,CHRCNT,SYSCHR,ECHO,BYTPTR,ERASCH,KILLCH,BRKCH,AGC,CHRWRD,W1CHAR,GWB\r
+.GLOBAL IOIN2,READC,WRONGC,BRFCHR,ESCAP,TTYOPE,MTYI,MTYO,NOTTY,TTYOP2,IBLOCK\r
+.GLOBAL RRESET,TTICHN,TTOCHN,CHANNO,STATUS,BRFCH2,TTYBLK,TTYUNB,WAITNS\r
+.GLOBAL EXBUFR,INCHAR,BYTDOP,BUFSTR,LSTCH,CHNCNT,DIRECT,IOINS,IBLOCK,INCONS\r
+.GLOBAL BADCHN,WRONGD,CHNLOS,MODE1,MODE2,GMTYO,IDVAL,GETCHR,PAGLN,LINLN\r
+.GLOBAL RDEVIC\r
+TTYOUT==1\r
+TTYIN==2\r
+\r
+; FLAGS CONCERNING TTY CHANNEL STATE\r
+\r
+N.ECHO==1                      ; NO INPUT ECHO\r
+N.CNTL==2                      ; NO RUBOUT ^L ^D ECHO\r
+N.IMED==4                      ; ALL CHARS WAKE UP\r
+N.IME1==10                     ; SOON WILL BE N.IMED\r
+\r
+\r
+; OPEN BLOCK MODE BITS\r
+OUT==1\r
+IMAGEM==4\r
+ASCIIM==0\r
+UNIT==0\r
+\r
+\r
+; READC IS CALLED BY PUSHJ P,READC\r
+; B POINTS TO A TTY FLAVOR CHANNEL\r
+; ONE CHARACTER IS RETURNED IN  A\r
+; BECOMES INTERRUPTABLE IF NO CHARACTERS EXISTS\r
+\r
+; HERE TO ASK SYSTEM FOR SOME CHARACTERS\r
+\r
+INCHAR:        IRP     A,,[0,C,D,E]    ;SAVE ACS\r
+       PUSH    P,A\r
+       TERMIN\r
+       MOVE    E,BUFRIN(B)             ; GET AUX BUFFER\r
+       MOVE    D,BYTPTR(E)\r
+       HLRE    0,E             ;FIND END OF BUFFER\r
+       SUBM    E,0\r
+       ANDI    0,-1            ;ISOLATE RH\r
+       MOVE    C,SYSCHR(E)     ; GET FLAGS\r
+\r
+INCHR1:        TRNE    C,N.IMED+N.CNTL ; SKIP IF NOT IMMEDIATE\r
+       JRST    DONE\r
+       TLZE    D,40            ; SKIP IF NOT ESCAPED\r
+       JRST    INCHR2          ; ESCAPED\r
+       CAMN    A,ESCAP(E)      ; IF ESCAPE\r
+       TLO     D,40            ; REMEMBER\r
+       CAMN    A,BRFCH2(E)\r
+       JRST    BRF\r
+       CAMN    A,BRFCHR(E)             ;BUFFER PRINT CHAR\r
+       JRST    CLEARQ          ;MAYBE CLEAR SCREEN\r
+       CAMN    A,BRKCH(E)      ;IS THIS A BREAK?\r
+       JRST    DONE            ;YES, DONE\r
+       CAMN    A,ERASCH(E)     ;ARE IS IT ERASE?\r
+       JRST    ERASE           ;YES, GO PROCESS\r
+       CAMN    A,KILLCH(E)     ;OR KILL\r
+       JRST    KILL\r
+\r
+INCHR2:        PUSHJ   P,PUTCHR        ;PUT ACHAR IN BUFFER\r
+INCHR3:        MOVEM   D,BYTPTR(E)\r
+       JRST    DONE1\r
+\r
+DONE:  SKIPL   A               ; IF JUST BUFFER FORCE, SKIP\r
+       PUSHJ   P,PUTCHR        ; STORE CHAR\r
+       MOVEI   A,N.IMED        ; TURN OFF IMEDIACY\r
+       ANDCAM  A,SYSCHR(E)\r
+       MOVEM   D,BYTPTR(E)\r
+       PUSH    TP,$TCHAN       ; SAVE CHANNEL\r
+       PUSH    TP,B\r
+       MOVE    A,CHRCNT(E)     ; GET # OF CHARS\r
+       SETZM   CHRCNT(E)\r
+       PUSH    P,A\r
+       ADDI    A,4             ; ROUND UP\r
+       IDIVI   A,5             ; AND DOWN\r
+       PUSHJ   P,IBLOCK        ; GET CORE\r
+       HLRE    A,B             ; FIND D.W.\r
+       SUBM    B,A\r
+       MOVSI   0,TCHRS+.VECT.  ; GET TYPE\r
+       MOVEM   0,(A)           ; AND STORE\r
+       MOVEI   D,(B)           ; COPY PNTR\r
+       POP     P,C             ; CHAR COUNT\r
+       HRLI    D,440700\r
+       HRLI    C,TCHSTR\r
+       PUSH    TP,C\r
+       PUSH    TP,D\r
+       PUSHJ   P,INCONS        ; CONS IT ON\r
+       MOVE    C,-2(TP)        ; GET CHAN BACK\r
+       MOVEI   D,EXBUFR(C)     ; POINT TO BUFFER LIST\r
+       HRRZ    0,(D)           ; LAST?\r
+       JUMPE   0,.+3\r
+       MOVE    D,0\r
+       JRST    .-3             ; GO UNTIL END\r
+       HRRM    B,(D)           ; SPLICE\r
+\r
+; HERE TO BLT IN BUFFER\r
+\r
+       MOVE    D,BUFRIN(C)     ; POINT TO COMPLETED BUFFER\r
+       HRRZ    C,(TP)          ; START OF NEW STRING\r
+       HRLI    C,BYTPTR+1(D)   ; 1ST WORD OF CHARS\r
+       MOVE    E,[010700,,BYTPTR(E)]\r
+       EXCH    E,BYTPTR(D)     ; END OF STRING\r
+       MOVEI   E,-BYTPTR(E)\r
+       ADD     E,(TP)          ; ADD TO START\r
+       BLT     C,-1(E)\r
+       MOVE    B,-2(TP)        ; CHANNEL BACK\r
+       SUB     TP,[4,,4]       ; FLUSH JUNK\r
+       PUSHJ   P,TTYUNB        ; UNBLOCK THIS TTY\r
+DONE1: IRP     A,,[E,D,C,0]\r
+       POP     P,A\r
+       TERMIN\r
+       POPJ    P,\r
+\r
+\r
+ERASE: SKIPN   CHRCNT(E)       ;ANYTHING IN BUFFER?\r
+       JRST    BARFCR  ;NO, MAYBE TYPE CR\r
+\r
+       SOS     CHRCNT(E)       ;DELETE FROM COUNT\r
+       LDB     A,D             ;RE-GOBBLE LAST CHAR\r
+IFN ITS,[\r
+       LDB     C,[600,,STATUS(B)]      ; CHECK FOR IMLAC\r
+       CAIE    C,2             ; SKIP IF IT IS\r
+]\r
+       JRST    TYPCHR\r
+       SKIPN   ECHO(E)         ; SKIP IF ECHOABLE\r
+       JRST    NECHO\r
+       PUSHJ   P,CHRTYP        ; FOUND OUT IMALC BEHAVIOR\r
+       SKIPGE  C,FIXIM2(C)\r
+       JRST    (C)\r
+NOTFUN:        PUSHJ   P,DELCHR\r
+       SOJG    C,.-1\r
+\r
+NECHO: ADD     D,[70000,,0]    ;DECREMENT BYTE POINTER\r
+       JUMPGE  D,INCHR3        ;AND GO ON, UNLESS BYTE POINTER LOST\r
+       SUB     D,[430000,,1]   ;FIX UP BYTE POINTER\r
+       JRST    INCHR3\r
+\r
+LFKILL:        PUSHJ   P,LNSTRV\r
+       JRST    NECHO\r
+\r
+BSKILL:        PUSHJ   P,GETPOS        ; CURRENT POSITION TO A\r
+       PUSHJ   P,SETPOS        ; POSITION IMLAC CURSOR\r
+       MOVEI   A,20            ; ^P\r
+       XCT     ECHO(E)\r
+       MOVEI   A,"L            ; L , DELETE TO END OF LINE\r
+       XCT     ECHO(E)\r
+       JRST    NECHO\r
+\r
+TBKILL:        PUSHJ   P,GETPOS\r
+       ANDI    A,7\r
+       SUBI    A,10            ; A -NUMBER OF DELS TO DO\r
+       PUSH    P,A\r
+       PUSHJ   P,DELCHR\r
+       AOSE    (P)\r
+       JRST    .-2\r
+\r
+       SUB     P,[1,,1]\r
+       JRST    NECHO\r
+TYPCHR:\r
+IFE ITS,[\r
+       PUSH    P,A             ; USE TENEX SLASH RUBOUT\r
+       MOVEI   A,"\\r
+       SKIPE   C,ECHO(E)\r
+       XCT     C\r
+       POP     P,A\r
+]\r
+       SKIPE   C,ECHO(E)\r
+       XCT     C\r
+       JRST    NECHO\r
+\r
+; ROUTINE TO DEL CHAR ON IMLAC\r
+\r
+DELCHR:        MOVEI   A,20\r
+       XCT     ECHO(E)\r
+       MOVEI   A,"X\r
+       XCT     ECHO(E)\r
+       POPJ    P,\r
+\r
+; HERE FOR SPECIAL IMLAC HACKS\r
+\r
+FOURQ: PUSH    P,CNOTFU\r
+FOURQ2:        MOVEI   C,2             ; FOR ^Z AND ^_\r
+       CAMN    B,TTICHN+1(TVP) ; SKIP IF NOT CONSOLE TTY\r
+       MOVEI   C,4\r
+CNOTFU:        POPJ    P,NOTFUN\r
+\r
+CNECHO:        JRST    NECHO\r
+\r
+LNSTRV:        MOVEI   A,20            ; ^P\r
+       XCT     ECHO(E)\r
+       MOVEI   A,"U\r
+       XCT     ECHO(E)\r
+       POPJ    P,\r
+\r
+; HERE IF KILLING A C.R., RE-POSITION CURSOR\r
+\r
+CRKILL:        PUSHJ   P,GETPOS        ; COMPUTE LINE POS\r
+       PUSHJ   P,SETPOS\r
+       JRST    NECHO\r
+\r
+SETPOS:        PUSH    P,A             ; SAVE POS\r
+       MOVEI   A,20\r
+       XCT     ECHO(E)\r
+       MOVEI   A,"H\r
+       XCT     ECHO(E)\r
+       POP     P,A\r
+       XCT     ECHO(E)         ; HORIZ POSIT AT END OF LINE\r
+       POPJ    P,0\r
+\r
+GETPOS:        PUSH    P,0\r
+       MOVEI   0,10            ; MINIMUM CURSOR POS\r
+       PUSH    P,[010700,,BYTPTR(E)]   ; POINT TO BUFFER\r
+       PUSH    P,CHRCNT(E)     ; NUMBER THEREOF\r
+\r
+GETPO1:        SOSGE   (P)             ; COUNT DOWN\r
+       JRST    GETPO2\r
+       ILDB    A,-1(P)         ; CHAR FROM BUFFER\r
+       CAIN    A,15            ; SKIP IF NOT CR\r
+       MOVEI   0,10            ; C.R., RESET COUNT\r
+       PUSHJ   P,CHRTYP        ; GET TYPE\r
+       XCT     FIXIM3(C)       ; GET FIXED COUNT\r
+       ADD     0,C\r
+       JRST    GETPO1\r
+\r
+GETPO2:        MOVE    A,0             ; RET COUNT\r
+       MOVE    0,-2(P)         ; RESTORE AC 0\r
+       SUB     P,[3,,3]\r
+       POPJ    P,\r
+\r
+CHRTYP:        MOVEI   C,0             ; NUMBER OF FLUSHEES\r
+       CAILE   A,37            ; SKIP IF CONTROL CHAR\r
+       POPJ    P,\r
+       PUSH    TP,$TCHAN\r
+       PUSH    TP,B            ; SAVE CHAN\r
+       IDIVI   A,12.           ; FIND SPECIAL HACKS\r
+       MOVE    A,FIXIML(A)     ; GET CONT WORD\r
+       IMULI   B,3\r
+       ROTC    A,3(B)          ; GET CODE IN B\r
+       ANDI    B,7\r
+       MOVEI   C,(B)\r
+       MOVE    B,(TP)          ; RESTORE CHAN\r
+       SUB     TP,[2,,2]\r
+       POPJ    P,\r
+\r
+FIXIM2:        1\r
+       2\r
+       SETZ    FOURQ\r
+       SETZ    CRKILL\r
+       SETZ    LFKILL\r
+       SETZ    BSKILL\r
+       SETZ    TBKILL\r
+\r
+FIXIM3:        MOVEI   C,1\r
+       MOVEI   C,2\r
+       PUSHJ   P,FOURQ2\r
+       MOVEI   C,0\r
+       MOVEI   C,0\r
+       MOVNI   C,1\r
+       PUSHJ   P,CNTTAB\r
+\r
+CNTTAB:        ANDCMI  0,7     ; GET COUNT INCUDING TAB HACK\r
+       ADDI    0,10\r
+       MOVEI   C,0\r
+       POPJ    P,\r
+       \r
+FIXIML:        111111,,115641  ; CNTL @ABCDE,,FGHIJK\r
+       131111,,111111  ; LMNOPQ,,RSTUVW\r
+       112011,,120000  ; XYZ LBRAK \ RBRAK,,^  _\r
+\r
+; HERE TO KILL THE WHOLE BUFFER\r
+\r
+KILL:  CLEARM  CHRCNT(E)       ;NONE LEFT NOW\r
+       MOVE    D,[010700,,BYTPTR(E)]   ;RESET POINTER\r
+\r
+BARFCR:\r
+IFN ITS,[\r
+       MOVE    A,ERASCH(E)     ;GET THE ERASE CHAR\r
+       CAIN    A,177           ;IS IT RUBOUT?\r
+]\r
+       PUSHJ   P,CRLF1         ; PRINT CR-LF\r
+       JRST    INCHR3\r
+\r
+CLEARQ:\r
+IFN ITS,[\r
+       MOVE    A,STATUS(B)     ;CHECK CONSOLE KIND\r
+       ANDI    A,77\r
+       CAIN    A,2             ;DATAPOINT?\r
+       PUSHJ   P,CLR           ;YES, CLEAR SCREEN\r
+]\r
+\r
+BRF:   MOVE    C,[010700,,BYTPTR(E)]   ;POINT TO START OF BUFFER\r
+       SKIPN   ECHO(E)         ;ANY ECHO INS?\r
+       JRST    NECHO\r
+\r
+       PUSHJ   P,CRLF2\r
+       PUSH    P,CHRCNT(E)\r
+\r
+       SOSGE   (P)\r
+       JRST    DECHO\r
+       ILDB    A,C                     ;GOBBLE CHAR\r
+       XCT     ECHO(E)         ;ECHO IT\r
+       JRST    .-4             ;DO FOR ENTIRE BUFFER\r
+\r
+DECHO: SUB     P,[1,,1]\r
+       JRST    INCHR3\r
+\r
+CLR:   SKIPN   C,ECHO(E)       ;ONLY IF INS EXISTS\r
+       POPJ    P,\r
+       MOVEI   A,20            ;ERASE SCREEN\r
+       XCT     C\r
+       MOVEI   A,103\r
+       XCT     C\r
+       POPJ    P,\r
+\r
+PUTCHR:        AOS     CHRCNT(E)       ;COUNT THIS CHARACTER\r
+       IBP     D               ;BUMP BYTE POINTER\r
+       CAIG    0,@D            ;DONT SKIP IF BUFFER FULL\r
+       PUSHJ   P,BUFULL                ;GROW BUFFER\r
+IFE ITS,[\r
+       CAIN    A,37            ; CHANGE EOL TO CRLF\r
+       MOVEI   A,15\r
+]\r
+       DPB     A,D             ;CLOBBER BYTE POINTER IN\r
+       MOVE    C,SYSCHR(E)     ; FLAGS\r
+       TRNN    C,N.IMED+N.CNTL\r
+       CAIE    A,15            ; IF CR INPUT, FOLLOW WITH LF\r
+       POPJ    P,\r
+       MOVEI   A,12            ; GET LF\r
+       JRST    PUTCHR\r
+\r
+; BUFFER FULL, GROW THE BUFFER\r
+\r
+BUFULL:        PUSH    TP,$TCHAN       ;SAVE B\r
+       PUSH    TP,B\r
+       PUSH    P,A             ; SAVE CURRENT CHAR\r
+       HLRE    A,BUFRIN(B)\r
+       MOVNS   A\r
+       ADDI    A,100           ; MAKE ONE LONGER\r
+       PUSHJ   P,IBLOCK        ; GET IT\r
+       MOVE    A,(TP)          ;RESTORE CHANNEL POINTER\r
+       SUB     TP,[2,,2]       ;AND REMOVE CRUFT\r
+       MOVE    E,BUFRIN(A)     ;GET AUX BUFFER POINTER\r
+       MOVEM   B,BUFRIN(A)\r
+       HLRE    0,E             ;RECOMPUTE 0\r
+       MOVSI   E,(E)\r
+       HRRI    E,(B)           ; POINT TO DEST\r
+       SUB     B,0\r
+       BLT     E,(B)\r
+       MOVEI   0,100-2(B)\r
+       MOVE    B,A\r
+       POP     P,A\r
+       POPJ    P,\r
+\r
+; ROUTINE TO CRLF ON ANY TTY\r
+\r
+CRLF1: SKIPN   ECHO(E)\r
+       POPJ    P,              ; NO ECHO INS\r
+CRLF2: MOVEI   A,15\r
+       XCT     ECHO(E)\r
+       MOVEI   A,12\r
+       XCT     ECHO(E)\r
+       POPJ    P,\r
+\r
+; SUBROUTINE TO FLUSH BUFFER\r
+\r
+RRESET:        SETZM   LSTCH(B)        ; CLOBBER RE-USE CHAR\r
+       MOVE    E,BUFRIN(B)             ;GET AUX BUFFER\r
+       SETZM   CHRCNT(E)\r
+       MOVEI   D,N.IMED+N.IME1\r
+       ANDCAM  D,SYSCHR(E)\r
+       MOVE    D,[010700,,BYTPTR(E)]   ;RESET BYTE POINTER\r
+       MOVEM   D,BYTPTR(E)\r
+       MOVE    D,CHANNO(B)     ;GOBBLE CHANNEL\r
+       SETZM   CHNCNT(D)       ; FLUSH COUNTERS\r
+IFN ITS,[\r
+       LSH     D,23.           ;POSITION\r
+       IOR     D,[.RESET 0]\r
+       XCT     D               ;RESET ITS CHANNEL\r
+]\r
+IFE ITS,[\r
+       MOVEI   A,100           ; TTY IN JFN\r
+       CFIBF\r
+]\r
+       SETZM   EXBUFR(B)       ; CLOBBER STAKED BUFFS\r
+       MOVEI   C,BUFSTR-1(B)   ; FIND D.W.\r
+       PUSHJ   P,BYTDOP\r
+       SUBI    A,2\r
+       HRLI    A,010700\r
+       MOVEM   A,BUFSTR(B)\r
+       HLLZS   BUFSTR-1(B)\r
+       POPJ    P,\r
+\r
+; SUBROUTINE TO ESTABLISH ECHO IOINS\r
+\r
+MFUNCTION ECHOPAIR,SUBR\r
+\r
+       ENTRY   2\r
+\r
+       GETYP   A,(AB)          ;CHECK ARG TYPES\r
+       GETYP   C,2(AB)\r
+       CAIN    A,TCHAN         ;IS A CHANNEL\r
+       CAIE    C,TCHAN         ;IS C ALSO\r
+       JRST    WRONGT          ;NO, ONE OF THEM LOSES\r
+\r
+       MOVE    A,1(AB)         ;GET CHANNEL\r
+       PUSHJ   P,TCHANC        ; VERIFY TTY IN\r
+       MOVE    D,3(AB)         ;GET OTHER CHANNEL\r
+       MOVEI   B,DIRECT-1(D)   ;AND ITS DIRECTION\r
+       PUSHJ   P,CHRWRD\r
+       JFCL\r
+       CAME    B,[ASCII /PRINT/]\r
+       JRST    WRONGD\r
+\r
+       MOVE    B,BUFRIN(A)     ;GET A'S AUX BUFFER\r
+       HRLZ    C,CHANNO(D)     ; GET CHANNEL\r
+       LSH     C,5\r
+       IOR     C,[.IOT A]      ; BUILD AN IOT\r
+       MOVEM   C,ECHO(B)               ;CLOBBER\r
+CHANRT:        MOVE    A,(AB)\r
+       MOVE    B,1(AB)         ;RETURN 1ST ARG\r
+       JRST    FINIS\r
+\r
+TCHANC:        MOVEI   B,DIRECT-1(A)   ;GET DIRECTION\r
+       PUSHJ   P,CHRWRD        ; CONVERT\r
+       JFCL\r
+       CAME    B,[ASCII /READ/]\r
+       JRST    WRONGD\r
+       LDB     C,[600,,STATUS(A)]      ;GET A CODE\r
+       CAILE   C,2             ;MAKE SURE A TTY FLAVOR DEVICE\r
+       JRST    WRONGC\r
+       POPJ    P,\r
+IFE ITS,[\r
+TTYOPEN:\r
+TTYOP2:        MOVEI   A,-1            ; TENEX JFN FOR TERMINAL\r
+       MOVEI   2,145100        ; MAGIC BITS (SEE TENEX MANUAL)\r
+       SFMOD                   ; ZAP\r
+       RFMOD                   ; LETS FIND SCREEN SIZE\r
+       LDB     A,[220700,,B]   ; GET PAGE WIDTH\r
+       LDB     B,[310700,,B]   ; AND LENGTH\r
+       MOVE    C,TTOCHN+1(TVP)\r
+       MOVEM   A,LINLN(C)\r
+       MOVEM   B,PAGLN(C)\r
+       MOVEI   A,-1            ; NOW HACK CNTL CHAR STUFF\r
+       RFCOC                   ; GET CURRENT\r
+       AND     B,[036377,,-1]  ; CHANGE FOR ^@, ^A AND ^D (FOR NOW)\r
+       SFCOC                   ; AND RESUSE IT\r
+\r
+       POPJ    P,\r
+]\r
+\r
+IFN ITS,[\r
+TTYOP2:        .SUSET  [.RTTY,,C]\r
+       SETZM   NOTTY\r
+       JUMPL   C,TTYNO         ; DONT HAVE TTY\r
+\r
+TTYOPEN:\r
+       SKIPE   NOTTY\r
+       POPJ    P,\r
+       .OPEN   TTYIN,[SIXBIT /   TTY/]\r
+       JRST    TTYNO\r
+       .OPEN   TTYOUT,[21,,(SIXBIT /TTY/)]     ;AND OUTPUT\r
+       FATAL CANT OPEN TTY\r
+       DOTCAL  TTYGET,[[1000,,TTYOUT],[2000,,0],[2000,,A],[2000,,B]]\r
+       FATAL .CALL FAILURE\r
+       DOTCAL  TTYSET,[[1000,,TTYOUT],MODE1,MODE2,B]\r
+       FATAL .CALL FAILURE\r
+       \r
+SETCHN:        MOVE    B,TTICHN+1(TVP) ;GET CHANNEL\r
+       MOVEI   C,TTYIN         ;GET ITS CHAN #\r
+       MOVEM   C,CHANNO(B)\r
+       .STATUS TTYIN,STATUS(B) ;CLOBBER STATUS\r
+\r
+       MOVE    B,TTOCHN+1(TVP) ;GET OUT CHAN\r
+       MOVEI   C,TTYOUT\r
+       MOVEM   C,CHANNO(B)\r
+       .STATUS TTYOUT,STATUS(B)\r
+       SETZM   IMAGFL          ;RESET IMAGE MODE FLAG\r
+       HLLZS   IOINS-1(B)\r
+       DOTCAL  RSSIZE,[[1000,,TTYOUT],[2000,,C],[2000,,D]]\r
+       FATAL   .CALL RSSIZE LOSSAGE\r
+       MOVEM   C,PAGLN(B)\r
+       MOVEM   D,LINLN(B)\r
+       POPJ    P,\r
+\r
+; HERE IF TTY WONT OPEN\r
+\r
+TTYNO: SETOM   NOTTY\r
+       POPJ    P,\r
+]\r
+\r
+MTYI:  SKIPE   NOTTY           ; SKIP IF HAVE TTY\r
+       FATAL TRIED TO USE NON-EXISTANT TTY\r
+IFN ITS,       .IOT    TTYIN,A\r
+IFE ITS,       PBIN\r
+       POPJ    P,\r
+\r
+MTYO:  SKIPE   NOTTY\r
+       POPJ    P,              ; IGNORE, DONT HAVE TTY\r
+       SKIPE   IMAGFL          ;SKIP RE-OPENING IF ALREADY IN ASCII\r
+       PUSHJ   P,MTYO1 ;WAS IN IMAGE...RE-OPEN\r
+       CAIE    A,177           ;DONT OUTPUT A DELETE\r
+IFN ITS,       .IOT    TTYOUT,A\r
+IFE ITS,       PBOUT\r
+       POPJ    P,\r
+\r
+MTYO1: MOVE    B,TTOCHN+1(TVP)\r
+       PUSH    P,0\r
+       PUSHJ   P,REASCI\r
+       POP     P,0\r
+       POPJ    P,\r
+\r
+; HERE FOR TYO TO ANY TTY FLAVOR DEVICE\r
+\r
+GMTYO: PUSH    P,0\r
+       HRRZ    0,IOINS-1(B)    ; GET FLAG\r
+       SKIPE   0\r
+       PUSHJ   P,REASCI        ; RE-OPEN TTY\r
+       HRLZ    0,CHANNO(B)\r
+       ASH     0,5\r
+       IOR     0,[.IOT A]\r
+       CAIE    A,177           ; DONE OUTPUT A DELETE\r
+       XCT     0\r
+       POP     P,0\r
+       POPJ    P,\r
+\r
+REASCI:        PUSH    P,A\r
+       PUSH    P,C\r
+       PUSHJ   P,DEVTOC\r
+       HRLI    C,21            ; ASCII GRAPHIC BIT\r
+       MOVE    A,CHANNO(B)     ; GET CHANNEL\r
+       ASH     A,23.           ; TO AC FIELD\r
+       IOR     A,[.OPEN 0,C]\r
+       XCT     A\r
+       FATAL TTY OPEN LOSSAGE\r
+       POP     P,C\r
+       POP     P,A\r
+       HLLZS   IOINS-1(B)\r
+       CAMN    B,TTOCHN+1(TVP)\r
+       SETZM   IMAGFL\r
+       POPJ    P,\r
+\r
+\r
+\r
+WRONGC:        PUSH    TP,$TATOM\r
+       PUSH    TP,EQUOTE NOT-A-TTY-TYPE-CHANNEL\r
+       JRST    CALER1\r
+\r
+\r
+\r
+; HERE TO HANDLE TTY BLOCKING AND UNBLOCKING\r
+\r
+TTYBLK:        PUSH    TP,$TCHAN\r
+       PUSH    TP,B\r
+       PUSH    P,0\r
+       PUSH    P,E             ; SAVE SOME ACS\r
+IFN ITS,[\r
+       MOVE    A,CHANNO(B)     ; GET CHANNEL NUMBER\r
+       SOSG    CHNCNT(A)       ; ANY PENDING CHARS\r
+       JRST    TTYBL1\r
+       SETZM   CHNCNT(A)\r
+       MOVEI   0,1\r
+       LSH     0,(A)\r
+       .SUSET  [.SIFPI,,0]     ; SLAM AN INT ON\r
+]\r
+TTYBL1:        MOVE    C,BUFRIN(B)\r
+       MOVE    A,SYSCHR(C)     ; GET FLAGS\r
+       TRZ     A,N.IMED\r
+       TRZE    A,N.IME1        ; IF WILL BE\r
+       TRO     A,N.IMED        ; THE MAKE IT\r
+       MOVEM   A,SYSCHR(C)\r
+IFN ITS,[\r
+       MOVE    A,[.CALL TTYIOT]; NON-BUSY WAIT\r
+       SKIPE   NOTTY\r
+       MOVE    A,[.SLEEP A,]\r
+]\r
+IFE ITS,[\r
+       MOVE    A,[PUSHJ P,TNXIN]\r
+]\r
+       MOVEM   A,WAITNS(B)\r
+       PUSH    TP,$TCHSTR\r
+       PUSH    TP,CHQUOTE BLOCKED\r
+       PUSH    TP,$TPVP\r
+       PUSH    TP,PVP\r
+       MCALL   2,INTERRUPT\r
+       MOVSI   A,TCHAN\r
+       MOVEM   A,BSTO(PVP)\r
+       MOVE    B,(TP)\r
+       ENABLE\r
+REBLK: MOVEI   A,-1            ; IN CASE SLEEPING\r
+       XCT     WAITNS(B)       ; NOW WAIT\r
+       JFCL\r
+IFE ITS,       JRST    .-3\r
+IFN ITS,       JRST    CHRSNR  ; SNARF CHAR\r
+REBLK1:        DISABLE                 ; FALL THROUG=> UNBLOCKED\r
+       SETZM   BSTO(PVP)\r
+       POP     P,E\r
+       POP     P,0\r
+       MOVE    B,(TP)\r
+       SUB     TP,[2,,2]\r
+       POPJ    P,\r
+\r
+CHRSNR:        SKIPE   NOTTY           ; TTY?\r
+       JRST    REBLK           ; NO, JUST RESET AND BLOCK\r
+       .SUSET  [.SIFPI,,[1_<TTYIN>]]\r
+       JRST    REBLK           ; AND GO BACK\r
+\r
+TTYIOT:        SETZ\r
+       SIXBIT /IOT/\r
+       1000,,TTYIN\r
+       0\r
+       405000,,20000\r
+\r
+; HERE TO UNBLOCK TTY\r
+\r
+TTYUNB:        MOVE    A,WAITNS(B)     ; GET INS\r
+       CAMN    A,[JRST REBLK1]\r
+       JRST    TTYUN1\r
+       MOVE    A,[JRST REBLK1] ; LEAVE THE SLEEP\r
+       MOVEM   A,WAITNS(B)\r
+       PUSH    TP,$TCHAN\r
+       PUSH    TP,B\r
+       PUSH    TP,$TCHSTR\r
+       PUSH    TP,CHQUOTE UNBLOCKED\r
+       PUSH    TP,$TCHAN\r
+       PUSH    TP,B\r
+       MCALL   2,INTERRUPT\r
+       MOVE    B,(TP)          ; RESTORE CHANNEL\r
+       SUB     TP,[2,,2]\r
+TTYUN1:        POPJ    P,\r
+\r
+IFE ITS,[\r
+; TENEX BASIC TTY I/O ROUTINE\r
+\r
+TNXIN: PUSHJ   P,MTYI\r
+       PUSHJ   P,INCHAR\r
+       POPJ    P,\r
+]\r
+MFUNCTION TTYECHO,SUBR\r
+\r
+       ENTRY   2\r
+\r
+       GETYP   0,(AB)\r
+       CAIE    0,TCHAN\r
+       JRST    WTYP1\r
+       MOVE    A,1(AB)         ; GET CHANNEL\r
+       PUSHJ   P,TCHANC        ; MAKE SURE IT IS TTY INPUT\r
+       MOVE    E,BUFRIN(A)     ; EXTRA INFO BUFFER\r
+IFN ITS,[\r
+       DOTCAL  TTYGET,[CHANNO(A),[2000,,B],[2000,,C],[2000,,0]]\r
+       FATAL .CALL FAILURE\r
+]\r
+IFE ITS,[\r
+       MOVEI   A,100           ; TTY JFN\r
+       RFMOD                   ; MODE IN B\r
+       TRZ     B,6000          ; TURN OFF ECHO \r
+]\r
+       GETYP   D,2(AB)         ; ARG 2\r
+       CAIE    D,TFALSE        ; SKIP IF WANT ECHO OFF\r
+       JRST    ECHOON\r
+\r
+IFN ITS,[\r
+       ANDCM   B,[606060,,606060]\r
+       ANDCM   C,[606060,,606060]\r
+\r
+       DOTCAL  TTYSET,[CHANNO(A),B,C,0]\r
+       FATAL .CALL FAILURE\r
+]\r
+IFE ITS,[\r
+       SFMOD\r
+]\r
+\r
+       MOVEI   B,N.ECHO+N.CNTL ; SET FLAGS\r
+       IORM    B,SYSCHR(E)\r
+\r
+       JRST    CHANRT\r
+\r
+ECHOON:\r
+IFN ITS,[\r
+       IOR     B,[202020,,202020]\r
+       IOR     C,[202020,,202020]\r
+       DOTCAL  TTYSET,[CHANNO(A),B,C,0]\r
+       FATAL .CALL FAILURE\r
+]\r
+IFE ITS,[\r
+       TRO     B,4000\r
+       SFMOD\r
+]\r
+       MOVEI   A,N.ECHO+N.CNTL\r
+       ANDCAM  A,SYSCHR(E)\r
+       JRST    CHANRT\r
+\r
+\r
+\r
+; USER SUBR FOR INSTANT CHARACTER SNARFING\r
+\r
+MFUNCTION UTYI,SUBR,TYI\r
+\r
+       ENTRY\r
+       CAMGE   AB,[-3,,]\r
+       JRST    TMA\r
+       MOVE    A,(AB)\r
+       MOVE    B,1(AB)\r
+       JUMPL   AB,.+3\r
+       MOVE    B,IMQUOTE INCHAN\r
+       PUSHJ   P,IDVAL         ; USE INCHAN\r
+       GETYP   0,A             ; GET TYPE\r
+       CAIE    0,TCHAN\r
+       JRST    WTYP1\r
+       LDB     0,[600,,STATUS(B)]\r
+       CAILE   0,2\r
+       JRST    WTYP1\r
+       SKIPN   A,LSTCH(B)      ; ANY READ AHEAD CHAR\r
+       JRST    UTYI1           ; NO, SKIP\r
+       SETZM   LSTCH(B)\r
+       TLZN    A,400000        ; ! HACK?\r
+       JRST    UTYI2           ; NO, OK\r
+       MOVEM   A,LSTCH(B)      ; YES SAVE\r
+       MOVEI   A,"!            ; RET AN !\r
+       JRST    UTYI2\r
+\r
+UTYI1: MOVE    0,IOINS(B)\r
+       CAME    0,[PUSHJ P,GETCHR]\r
+       JRST    WTYP1\r
+       PUSH    TP,$TCHAN\r
+       PUSH    TP,B\r
+       MOVE    C,BUFRIN(B)\r
+       MOVEI   D,N.IME1+N.IMED \r
+       IORM    D,SYSCHR(C)     ; CLOBBER IT IN\r
+       DOTCAL  TTYGET,[CHANNO(B),[2000,,A],[2000,,D],[2000,,0]]\r
+       FATAL .CALL FAILURE\r
+       PUSH    P,A\r
+       PUSH    P,0\r
+       PUSH    P,D             ; SAVE THEM\r
+       IOR     D,[030303,,030303]\r
+       IOR     A,[030303,,030303]\r
+       DOTCAL  TTYSET,[CHANNO(B),A,D,0]\r
+       FATAL .CALL FAILURE\r
+       MOVNI   A,1\r
+       SKIPE   CHRCNT(C)       ; ALREADY SOME?\r
+       PUSHJ   P,INCHAR\r
+       MOVE    C,BUFRIN(B)     ; GET BUFFER BACK\r
+       MOVEI   D,N.IME1\r
+       IORM    D,SYSCHR(C)\r
+       PUSHJ   P,GETCHR\r
+       MOVE    B,1(TB)\r
+       MOVE    C,BUFRIN(B)\r
+       MOVEI   D,N.IME1+N.IMED\r
+       ANDCAM  D,SYSCHR(C)\r
+       POP     P,D\r
+       POP     P,0\r
+       POP     P,C\r
+       DOTCAL  TTYSET,[CHANNO(B),C,D,0]\r
+       FATAL .CALL FAILURE\r
+UTYI2: MOVEI   B,(A)\r
+       MOVSI   A,TCHRS\r
+       JRST    FINIS\r
+\r
+MFUNCTION      IMAGE,SUBR\r
+       ENTRY\r
+       JUMPGE  AB,TFA          ; 1 OR 2 ARGS NEEDED\r
+       GETYP   A,(AB)          ;GET THE TYPE OF THE ARG\r
+       CAIE    A,TFIX          ;CHECK IT FOR CORRECT TYPE\r
+       JRST    WTYP1           ;WAS WRONG...ERROR EXIT\r
+       HLRZ    0,AB\r
+       CAIL    0,-2\r
+       JRST    USEOTC\r
+       CAIE    0,-4\r
+       JRST    TMA\r
+       GETYP   0,2(AB)\r
+       CAIE    0,TCHAN\r
+       JRST    WTYP2\r
+       MOVE    B,3(AB)         ; GET CHANNEL\r
+IMAGE1:        LDB     0,[600,,STATUS(B)]\r
+       CAILE   0,2             ; MUST BE TTY\r
+       JRST    IMAGFO\r
+       MOVE    0,IOINS(B)\r
+       CAMN    0,[PUSHJ P,MTYO]\r
+       JRST    .+3\r
+       CAME    0,[PUSHJ P,GMTYO]\r
+       JRST    WRONGD\r
+       HRRZ    0,IOINS-1(B)\r
+       JUMPE   0,OPNIMG\r
+IMGIOT:        MOVE    A,1(AB)         ;GET VALUE\r
+       HRLZ    0,CHANNO(B)\r
+       ASH     0,5\r
+       IOR     0,[.IOT A]\r
+       XCT     0\r
+IMGEXT:        MOVE    A,(AB)          ;RETURN THE ORIGINAL ARG\r
+       MOVE    B,1(AB)\r
+       JRST    FINIS           ;EXIT\r
+\r
+\r
+IMAGFO:        PUSH    TP,$TCHAN       ;IMAGE OUTPUT FOR NON TTY\r
+       PUSH    TP,B\r
+       MOVEI   B,DIRECT-1(B)\r
+       PUSHJ   P,CHRWRD\r
+       JFCL\r
+       CAME    B,[ASCII /PRINT/]\r
+       CAMN    B,[<ASCII /PRINT/>+1]\r
+       JRST    .+2\r
+       JRST    BADCHN          ; CHANNEL COULDNT BE BLESSED\r
+       MOVE    B,(TP)\r
+       PUSHJ   P,GWB           ; MAKE SURE CHANNEL HAS BUFFER\r
+       MOVE    A,1(AB)         ; GET THE CHARACTER TO DO\r
+       PUSHJ   P,W1CHAR\r
+       MOVE    A,(AB)\r
+       MOVE    B,1(AB)         ;RETURN THE FIX\r
+       JRST    FINIS\r
+\r
+\r
+USEOTC:        MOVSI   A,TATOM\r
+       MOVE    B,IMQUOTE OUTCHAN\r
+       PUSHJ   P,IDVAL\r
+       GETYP   0,A\r
+       CAIE    0,TCHAN\r
+       MOVE    B,TTICHN+1(TVP)\r
+       JRST    IMAGE1\r
+\r
+OPNIMG:        HLLOS   IOINS-1(B)\r
+       CAMN    B,TTOCHN+1(TVP)\r
+       SETOM   IMAGFL\r
+       PUSHJ   P,DEVTOC\r
+       HRLI    C,41            ; SUPER IMAGE BIT\r
+       MOVE    A,CHANNO(B)\r
+       ASH     A,23.\r
+       IOR     A,[.OPEN 0,C]\r
+       XCT     A\r
+       FATAL TTY OPEN LOSSAGE\r
+       JRST    IMGIOT\r
+\r
+DEVTOC:        PUSH    P,D\r
+       PUSH    P,E\r
+       PUSH    P,0\r
+       PUSH    P,A\r
+       MOVE    D,RDEVIC(B)\r
+       MOVE    E,[220600,,C]\r
+       MOVEI   A,3\r
+       MOVEI   C,0\r
+       ILDB    0,D\r
+       SUBI    0,40\r
+       IDPB    0,E\r
+       SOJG    A,.-3\r
+       POP     P,A\r
+       POP     P,0\r
+       POP     P,E\r
+       POP     P,D\r
+       POPJ    P,\r
+\r
+IMGBLK:        OUT+IMAGEM+UNIT,,(SIXBIT /TTY/)\r
+       0\r
+       0\r
+\r
+\r
+\r
+IMPURE\r
+IMAGFL:        0\r
+PURE\r
+\r
+\r
+END\r
+\f\r