.TITLE WRTBUF - CONVERT SPECIAL CHAR AND WRITE BUFFER .IDENT /01.9/ .ENABL LC ;+ ; ; Free software BY ; Project Software & Development, Inc. ; ; This software is furnished for free and may be used and copied as ; desired. This software or any other copies thereof may be provided ; or otherwise made available to any other person. No title to and ; ownership of the software is hereby transferred or allowed. ; ; The information in this software is subject to change without notice ; and should not be construed as a commitment by PROJECT SOFTWARE ; AND DEVELOPMENT, INC. ; ; PROJECT SOFTWARE assumes no responsibility for the use or reliability ; of this software on any equipment whatsoever. ; ; Project Software & Development, Inc. ; 14 Story St. ; Cambridge, Ma. 02138 ; 617-661-1444 ; ; ; Title: WRTBUF ; Author: Robin Miller ; Date: October 29, 1981 ; ; Description: ; ; This routine is used to convert special characters and then write ; the buffer to the terminal. Special characters are control characters ; and vertical format characters for the line printer. ; ; Modification History: ; ;- .ENABL AMA .MCALL QIOW$S ; Special characters. NULL = 0 ; ASCII FOR NULL BELL = 7 ; ASCII FOR BELL BS = 10 ; ASCII FOR BACKSPACE HT = 11 ; ASCII FOR HORIZONTAL TAB LF = 12 ; ASCII FOR LINE FEED VT = 13 ; ASCII FOR VERTICAL TAB FF = 14 ; ASCII FOR FORM FEED CR = 15 ; ASCII FOR CARRIAGE RETURN ESC = 33 ; ASCII FOR ESCAPE SPACE = 40 ; ASCII FOR SPACE DEL = 177 ; ASCII FOR DELETE TYOSIZ = 160. ; TERMINAL OUTPUT BUFFER ; LARGE TO ALLOW FOR VFU IVFC: .BYTE 0 ; INTERNAL FORMAT CONTROL VFUFLG: .BYTE 0 ; VERTICAL FORMAT FLAG REVFLG: .BYTE 0 ; TERMINAL IN REVERSE VIDEO REMFLG: .BYTE 0 ; REMOVE ATTRIBUTES DONE SAVBUF: .WORD 0 ; SAVE BUFFER START HERE SPCTBL: .BYTE ,,,,,,NULL ; Special character output strings. Same as EDT. .NLIST BEX SPCSTR: .ASCIZ "" SPCLEN = .-SPCSTR .ASCIZ "" .ASCIZ "" .ASCIZ "" .ASCIZ "" .ASCIZ "" ; More special characters... for VT100 only. NEWLIN: .BYTE ,'(,'0,'h,,'(,'B,0 ; NL SPCSIZ = .-NEWLIN-1 MORE: .BYTE ,'(,'0,'`,,'(,'B,0 ; DIAMOND REV: .BYTE ,'[,'7,'m,0 ; REVERSE VIDEO REVL = <.-REV>-1 REM: .BYTE ,'[,'0,'m,0 ; REMOVE ATTRIBUTES REML = <.-REM>-1 RSIZE = TYOBUF:: .BLKB TYOSIZ ; TERMINAL OUTPUT BUFFER .EVEN ;+ ; ; WRTBUF - Convert special characters and write buffer to terminal. ; ; This routine attempts to do more than it should. A few of the things ; it does are listed below: ; ; o convert two types of line printer VFU bytes. ; o skips control characters in non-see-all mode yet attempts. ; to allow overprint and special graphics on the VT100. ; o skips the margin indent taking tabs into account. ; o converts tabs to spaces for the Tektronix (it's dumb). ; o converts control characters and various things in see-all mode. ; o attempts to take hardcopy terminals into account. ; o attempts to detect and handle internal carriage control. ; ; Inputs: ; FDBADR = Address of the FDB ; ; Outputs: ; All registers are preserved. ; ;- WRTBUF:: CALL $SAVAL ; SAVE R0 - R5 CLRB IVFC ; PRESUME NO INTERNAL VFC CLRB VFUFLG ; PRESUME NO VFU BYTES CLR REVFLG ; NOT IN REVERSE VIDEO MOV FDBADR,R0 ; COPY THE FDB ADDRESS MOV F.NRBD(R0),R1 ; COPY THE BYTE COUNT MOV F.NRBD+2(R0),R0 ; COPY THE BUFFER ADDRESS ; Special handling of backing up partial page. BIT #B.BACK,STATUS ; ARE WE BACKING UP ? BEQ 10$ ; IF EQ, NO DEC BCKCNT ; ADJUST THE COUNT BPL 10$ ; IF EQ, MORE COUNT INC LINCNT ; COUNT THE LINE RETURN ; AND RETURN ... ; Special handling of internal carriage control. 10$: BIT #SESW,SWMASK ; ARE WE IN SEE-ALL MODE ? BNE 20$ ; IF NE, YES (DISPLAY ALL) CMP R1,#2 ; POSSIBLE ? BNE 20$ ; IF NE, NO CMPB (R0),#CR ; CARRIAGE RETURN BNE 20$ ; IF NE, NO CMPB 1(R0),#LF ; LINE FEED ? BNE 20$ ; IF NE, NO RETURN ; SKIP THIS RECORD 20$: TST R1 ; GOT A BYTE COUNT ? BGT 40$ ; IF GT, YES 30$: MOV #TYOBUF,R2 ; TYPEOUT BUFFER JMP DOQIO ; GO OUTPUT THE BUFFER 40$: MOV MARGIN,R3 ; INDENT THE MARGIN ? BEQ 90$ ; IF EQ, NO ; Indent the margin. CLR R2 ; CALCULATED BYTE COUNT 50$: CMPB (R0),#HT ; HORIZONTAL TAB ? BNE 80$ ; IF NE, NO CLR R4 ; CLEAR HIGH BITS FOR DIVIDE MOV R2,R5 ; COPY CALCULATED BYTE COUNT DIV #8.,R4 ; DIVIDE BY THE TAB SIZE MOV #8.,R4 ; PRESUME MAXIMUM TAB SIZE TST R5 ; DO WE HAVE THE SPACE COUNT ? BEQ 60$ ; IF EQ, NO (USE MAXIMUM SIZE) SUB R5,R4 ; CALCULATE SPACE COUNT 60$: DEC R4 ; ADJUST THE SPACE COUNT BEQ 80$ ; IF EQ, FINISHED INC R2 ; BUMP CALCULATED BYTE COUNT SOB R3,60$ ; ADJUST THE MARGIN COUNT ; If less than a full TAB stop, inserts remaining spaces. MOV #TYOBUF,R2 ; MARGIN COUNT EXHAUSTED 70$: MOVB #SPACE,(R2)+ ; MOVE IN A SPACE SOB R4,70$ ; LOOP TILL DONE INC R0 ; NEXT BYTE POSITION DEC R1 ; ADJUST THE BYTE COUNT BEQ 30$ ; IF EQ, END OF RECORD BR 100$ ; AND CONTINUE ... 80$: INC R2 ; CALCULATED BYTE COUNT DEC R3 ; ADJUST MARGIN COUNT INC R0 ; POINT TO NEXT BYTE DEC R1 ; DECREMENT BYTE COUNT BEQ 30$ ; IF EQ, END OF RECORD TST R3 ; MORE MARGIN COUNT ? BGT 50$ ; IF GT, YES 90$: MOV #TYOBUF,R2 ; TYPEOUT BUFFER 100$: MOV R2,SAVBUF ; SAVE START OF BUFFER MOV #TYOSIZ-8.,R3 ; ALLOW FOR SPECIAL BYTES ; Format characters for output. FMTBUF: CALL CKSRCH ; CHECK FOR A SEARCH STRING ; BIT #SESW,SWMASK ; ARE WE IN SEE-ALL MODE ? ; BNE 200$ ; IF NE, YES (SKIP VFU) BIT #VFSW,SWMASK ; SHOULD WE CONVERT THE VFU ? BEQ 200$ ; IF EQ, NO (SKIP IT) ; Check for line printer VFU byte. 100$: BITB #200,(R0) ; IS IT A VFU BYTE ? BEQ 200$ ; IF EQ, NO INCB VFUFLG ; SHOW VFU IN BUFFER BITB #100,(R0) ; SKIP FUNCTION (Data Printer) ? BEQ 120$ ; IF EQ, NO ; Change VFU skip function to a form feed. 110$: MOVB #FF,(R0) ; CHANGE IT TO FORM FEED BR 200$ ; AND PROCESS IT ; Data Printer skip to channel 1 = 301, space 1 = 201. ; Data Products skip to channel 1 = 200, space 1 = 221. 120$: BITB #37,(R0) ; SKIP CHANNEL 1 (Data Products) ? BEQ 110$ ; IF EQ, PRESUME YES ; Change VFU space function to 's. MOVB (R0),R4 ; GET THE SPACE BYTE BIC #^C17,R4 ; ISOLATE THE COUNT DEC R4 ; BIAS BY -1 BGT 130$ ; IF GT, GOT A COUNT JMP NXTBYT ; ELSE, DO NEXT BYTE 130$: CMP #2,R3 ; ROOM IN OUTPUT BUFFER ? BGT 140$ ; IF GT, NO (TYPE IT) MOVB #CR,(R2)+ ; MOVE IN CARRIAGE RETURN MOVB #LF,(R2)+ ; AND THE LINE FEED INC LINCNT ; COUNT THIS LINE SUB #2,R3 ; ADJUST BYTE COUNT BEQ 140$ ; IF EQ, TYPE IT TSTB TERM ; IS THIS A HARDCOPY ? BEQ 135$ ; IF EQ, YES CMP LINCNT,MAXLIN ; EXCEED LINE COUNT ? BGE 140$ ; IF GE, TIME TO STOP 135$: SOB R4,130$ ; AND LOOP TILL DONE BR NXTBYT ; DO THE NEXT BYTE 140$: JMP DOQIO ; GO OUTPUT THE BUFFER ; Not a VFU byte, check for special characters. 200$: MOV #SPCTBL,R4 ; SPECIAL CHARACTERS TABLE BICB #200,(R0) ; CLEAR THE PARITY BIT CMPB (R0),#DEL ; DELETE CHARACTER ? BEQ 210$ ; IF EQ, YES CMPB (R0),#SPACE ; CONTROL CHARACTER ? BGE 300$ ; IF GE, NO CMPB (R0),#HT ; HORIZONTAL TAB ? BEQ 270$ ; YES, CONVERT TO SPACES ; Got a special character. 210$: BIT #FFSW,SWMASK ; PASS FORMFEEDS ? BNE 215$ ; IF NE, YES (CHECK FF) TSTB TERM ; OUTPUT TO A HARDCOPY ? BNE 220$ ; IF NE, NO (CONVERT FF) ; Special hardcopy processing. 215$: CMPB (R0),#FF ; IS THIS A FORM FEED ? BEQ 300$ ; IF EQ, YES (PASS IT) 220$: BIT #SESW,SWMASK ; SEE-ALL MODE ? BNE 230$ ; IF NE, YES CMPB (R0),#CR ; CARRIAGE RETURN ? BEQ 300$ ; IF EQ, YES (ALLOW OVERPRINT) CMPB (R0),#BS ; BACKSPACE ? BEQ 300$ ; IF EQ, YES (ALLOW OVERPRINT) CMPB (R0),#BELL ; RING THE BELL ? BEQ 300$ ; IF EQ, YES (ALLOW THIS) CMPB (R0),#ESC ; IS IT ESCAPE ? BEQ 300$ ; IF EQ, YES (ALLOW THIS ?) CMPB (R0),#LF ; IS THIS A LINE FEED ? BNE NXTBYT ; IF NE, NO (IGNORE IT) ; Special handling of internal carriage control. INCB IVFC ; SHOW INTERNAL VFC INC LINCNT ; ADJUST THE LINE COUNT BR 300$ ; COPY IT TO OUTPUT BUFFER ; Convert special non-printable characters in SEE-ALL mode. 230$: TSTB (R4) ; END OF TABLE ? BEQ 260$ ; IF EQ, YES CMPB (R0),(R4)+ ; SPECIAL CHARACTER ? BNE 230$ ; IF NE, NO DEC R4 ; POINT AT ACTUAL CHAR SUB #SPCTBL,R4 ; SUBTRACT OUT BASE MUL #SPCLEN,R4 ; CALCULATE THE OFFSET ADD #SPCSTR,R5 ; ADD IN START OF TABLE 245$: CMP #,R3 ; ROOM IN THE BUFFER ? BGT DOQIO ; IF GT, NO (TYPE IT) ; Move special character string. 250$: MOVB (R5)+,(R2) ; COPY SPECIAL STRING BEQ NXTBYT ; IF EQ, DO NEXT BYTE INC R2 ; NEXT OUTPUT POSITION DEC R3 ; ADJUST THE BYTE COUNT BR 250$ ; DO NEXT CHARACTER ; Convert control character to ^char. 260$: CMP #2,R3 ; ROOM IN OUTPUT BUFFER ? BGT DOQIO ; IF GT, NO (TYPE IT) MOVB #'^,(R2)+ ; MOVE THE UP ARROW MOVB (R0),R4 ; COPY THE CONTROL CHAR ADD #64.,R4 ; MAKE IT PRINTABLE MOVB R4,(R2)+ ; MOVE IT SUB #2,R3 ; ADJUST BYTE COUNT BEQ DOQIO ; IF EQ, BUFFER FULL BR NXTBYT ; ELSE, DO NEXT BYTE ; Convert horizontal tabs to spaces. 270$: MOV R2,R5 ; COPY THE BUFFER ADDRESS SUB SAVBUF,R5 ; CALCULATE BYTE COUNT TSTB REVFLG ; REVERSE VIDEO IN BUFFER ? BEQ 272$ ; IF EQ, NO SUB #REVL,R5 ; ADJUST THE BYTE COUNT 271$: TSTB REMFLG ; REVERSE VIDEO REMOVED ? BEQ 272$ ; IF EQ, NO SUB #REML,R5 ; ADJUST THE BYTE COUNT 272$: CLR R4 ; CLEAR THE HIGH BITS DIV #8.,R4 ; DIVIDE BY THE TAB SIZE MOV #8.,R4 ; PRESUME FULL TAB STOP TST R5 ; GOT A SPACE COUNT ? BEQ 275$ ; IF EQ, NO (FULL TAB STOP) SUB R5,R4 ; CALCULATE SPACE COUNT 275$: MOVB #SPACE,(R2)+ ; MOVE IN A SPACE DEC R3 ; ADJUST BYTE COUNT BEQ DOQIO ; IF EQ, BUFFER FULL DEC R4 ; ADJUST SPACE COUNT BGT 275$ ; IF GT, MORE TO GO BR NXTBYT ; ELSE, DO NEXT BYTE 300$: MOVB (R0),(R2)+ ; COPY TO OUTPUT BUFFER DEC R3 ; ADJUST THE BYTE COUNT TSTB TERM ; IS THIS A HARDCOPY ? BEQ NXTBYT ; IF EQ, YES (CONTINUE) CMP LINCNT,MAXLIN ; EXCEED LINE COUNT ? BGE DOQIO ; IF GE, YES (QUIT) ; Process next character. NXTBYT: INC R0 ; POINT TO NEXT CHARACTER DEC R1 ; DECREMENT THE BYTE COUNT BLE DOQIO ; IF LE, ALL DONE TST R3 ; EXCEEDING LINE WIDTH ? BLE DOQIO ; IF LE, YES JMP FMTBUF ; ELSE, FORMAT NEXT CHAR ; Do QIO to write buffer to terminal. DOQIO: TSTB VFUFLG ; PRINTER VFU IN BUFFER ? BNE 10$ ; IF NE, YES CMPB -1(R2),#LF ; WAS LAST BYTE A LINE FEED BNE 10$ ; IF NE, NO DEC R2 ; YES, DON'T OUTPUT DEC LINCNT ; ADJUST THE LINE COUNT 10$: MOV R2,R4 ; COPY THE BUFFER ADDRESS SUB #TYOBUF,R4 ; CALCULATE THE BYTE COUNT BNE 20$ ; IF NE, GOT ONE MOVB #NULL,(R2)+ ; SET FOR NULL RECORD INC R4 ; SET BYTE COUNT TO 1 20$: MOV LINWID,R5 ; COPY THE LINE WIDTH TSTB REVFLG ; REVERSE VIDEO IN BUFFER ? BEQ 30$ ; IF EQ, NO ADD #RSIZE,R5 ; YES, ALLOW WIDER LINE 30$: CMP R4,R5 ; EXCEEDING LINE WIDTH ? BLE 50$ ; IF LE, NO CMP R5,#132. ; ARE WE LISTING NARROW ? BLT 40$ ; IF LT, YES (TRUNCATE) TSTB VFUFLG ; PRINTER VFU IN BUFFER ? BNE 50$ ; IF NE, YES (LEAVE B.C.) 40$: MOV R5,R4 ; SET THE MAXIMUM WIDTH BIT #SESW,SWMASK ; SEE-ALL MODE ? BEQ 70$ ; IF EQ, NO CMPB #T.V100,TTYPE ; ARE WE ON A VT100 ? BNE 70$ ; IF NE, NO MOV #TYOBUF,R2 ; START OF OUTPUT BUFFER DEC R4 ; ADJUST THE BYTE COUNT ADD R4,R2 ; LAST BYTE TO OUTPUT MOV #MORE,R5 ; SET TO SHOW MORE ON LINE BR 60$ ; BR TO COMMON LOOP 50$: BIT #SESW,SWMASK ; SEE-ALL MODE ? BEQ 70$ ; IF EQ, NO CMPB #T.V100,TTYPE ; ARE WE ON A VT100 ? BNE 70$ ; IF NE, NO MOV #NEWLIN,R5 ; YES, SHOW END OF LINE 60$: MOVB (R5)+,(R2)+ ; COPY SPECIAL SEQUENCE BNE 60$ ; IF NE, MORE TO GO ADD #SPCSIZ,R4 ; SIZE OF SPECIAL BYTES ; Finally output the formatted buffer. 70$: QIOW$S #IO.WAL,#OUTLUN,#OUTEFN,,#TIOSB,,<#TYOBUF,R4,#40> INC LINCNT ; BUMP THE LINE COUNT TSTB REVFLG ; REVERSE VIDEO ON SCREEN ? BEQ 80$ ; IF EQ, NO TSTB REMFLG ; REVERSE VIDEO REMOVED ? BNE 80$ ; IF NE, YES CALL REMATR ; NOPE, REMOVE ATTRIBUTES 80$: RETURN ;+ ; ; CKSRCH - Check current record for search string record. ; ;- CKSRCH: BIT #B.SRCH,STATUS ; IS A SEARCH STRING ACTIVE ? BEQ 100$ ; IF EQ, NO CMPB #T.V100,TTYPE ; ARE WE ON A VT100 ? BNE 100$ ; IF NE, NO CMP SRECRD,CURREC ; POSSIBLY THIS RECORD ? BNE 100$ ; IF NE, NO CMP SRECRD+2,CURREC+2 ; REALLY THIS RECORD ? BNE 100$ ; IF NE, NO CMP R0,SBEGIN ; BEGINNING OF SEARCH STRING ? BNE 20$ ; IF NE, NO (TRY END) ; Add reverse video on VT100. MOV #REV,R4 ; REVERSE VIDEO BYTES INCB REVFLG ; SHOW IN REVERSE VIDEO 10$: MOVB (R4)+,(R2)+ ; MOVE TO OUTPUT BUFFER BNE 10$ ; LOOP TILL DONE DEC R2 ; POINT AT THE NULL SUB #REVL,R3 ; ADJUST BUFFER BYTE COUNT BR 100$ ; FINISHED FOR NOW 20$: CMP R0,SEND ; END OF SEARCH STRING ? BNE 100$ ; IF NE, NO ; Remove attributes from the VT100. MOV #REM,R4 ; REMOVE ATTRIBUTE BYTES 30$: MOVB (R4)+,(R2)+ ; MOVE TO OUTPUT BUFFER BNE 30$ ; LOOP UNTIL DONE DEC R2 ; POINT TO THE NULL SUB #REML,R3 ; ADJUST BUFFER BYTE COUNT INCB REMFLG ; SHOW REMOVE IS IN BUFFER 100$: RETURN .END