.TITLE SCREEN VT52 "WATCH" FOR TECO-11 .IDENT "0005" .NLIST TTM .LIST TOC,MEB,BEX .SBTTL VT52 "WATCH" FOR TECO-11 .SBTTL ASSEMBLY PARAMETERS ; I$$SOB ASSEMBLE FOR HARDWARE 'SOB' INSTRUCTION ; I$$MUL ASSEMBLE FOR HARDWARE 'MUL' INSTRUCTION .SBTTL GENERAL PDP-11 DEFINITIONS ; GENERAL REGISTERS R0 = %0 R1 = %1 R2 = %2 R3 = %3 R4 = %4 R5 = %5 SP = %6 PC = %7 .SBTTL CHARACTER DEFINITIONS TAB = 011 ;ASCII HORIZONTAL TAB LF = 012 ;ASCII LINE FEED CR = 015 ;ASCII CARRIAGE RETURN ESC = 033 ;ASCII ESCAPE (ALSO CALLED ALTMODE) SPACE = 040 ;ASCII SPACE DEL = 177 ;ASCII DELETE (ALSO CALLED RUBOUT) .SBTTL DEFAULT AND SET UP THE ASSEMBLY PARAMETERS H.SIZE = 80. ;HORIZONTAL WIDTH V.SIZE = 24. ;VERTICAL SIZE .IF NDF I$$SOB .MACRO SOB REG,DST DEC REG BNE DST .ENDM SOB .SBTTL ASSEMBLED WITHOUT HARDWARE 'SOB' INSTRUCTION .IFF .SBTTL ASSEMBLED WITH HARDWARE 'SOB' INSTRUCTION .ENDC .IF NDF I$$MUL .MACRO MULT AMT JSR PC,MUL'AMT .ENDM MULT .SBTTL ASSEMBLED WITHOUT HARDWARE 'MUL' INSTRUCTION .IFF .MACRO MULT AMT MUL #AMT'.,R1 .ENDM MULT .SBTTL ASSEMBLED WITH HARDWARE 'MUL' INSTRUCTION .ENDC .SBTTL SCOPE "WATCH" ROUTINE .CSECT SCREEN SCREEN: .WORD SCRWSZ ;THE READ/WRITE DATA REGION'S SIZE .IIF NE .-SCREEN-2, .ERROR ;ENTRY POINT IS INCORRECTLY LOCATED WATCH: BIT #512.,ETYPE(R5) ;IS THE SCOPE AVAILABLE? BEQ 10$ ;NOPE, QUICKLY EXIT MOV R0,BUSTRT+RWSIZE(R5) ;SAVE THE CALLING ARGUMENT BMI 20$ ;ARG <0, PROCESS A REAL CALL CLR INITFL+RWSIZE(R5) ;ARG >=0, FORGET THE ENTIRE SCREEN 10$: RTS PC ;EXIT 20$: MOV NWATCH(R5),R0 ;RESTORE ARGUMENT TO OLD ARGUMENT JSR R4,SAVREG ;SAVE ALL REGISTERS MOV BUSTRT+RWSIZE(R5),R0 ;GET CALLING ARGUMENT BACK AGAIN COM R0 ;MAKE COUNT OF CHANGED LINES POSITIVE BEQ DOIT ;BRANCH IF NO SPECIAL SCREEN MODS MOV #24.,R1 ;PUT MAXIMUM LEGAL COUNT INTO ODD REG CMP R0,R1 ;IS ARGUMENT OVER MAXIMUM? BHI 30$ ;YES, USE MAXIMUM MOV R0,R1 ;NO, USE ARGUMENT 30$: MULT 40 ;MULTIPLY LINE COUNT BY 40. TO GET WORDS MOV #MAPST+RWSIZE,R0 ;BUILD A POINTER ADD R5,R0 ; TO THE MAP 40$: CLR (R0)+ ;CLEAR WHAT WE THINK IT LOOKS LIKE SOB R1,40$ ; FOR THAT MANY LINES MOV #-1,PRELIN+RWSIZE(R5) ;CLOBBER LAST KNOWN CURSOR CLRB OUTDNE ;RESET THE OUTPUT OCCURRED FLAG RTS PC ; AND EXIT .GLOBL ETYPE, RWSIZE, NWATCH, SAVREG, OUTDNE DOIT: MOV ETYPE(R5),-(SP) ;SAVE ENTERING EDIT FLAG VALUE BIS #1,ETYPE(R5) ; AND, THEN, ENSURE IMAGE MODE OUTPUT JSR R4,SETJSR ;SET UP FOR .WORD FTRANS ; COUNTING LINES MOV P(R5),-(SP) ;SAVE CURRENT POINTER ;CLR R0 ;SET THE ARGUMENT JSR PC,.VVV.V ;DO 0L (START OF CURSOR LINE) MOV R1,R4 ;SET START OF THE CURSOR LINE MOV ZZ(R5),R1 ;GET TOTAL SIZE OF TEXT BUFFER SUB R4,R1 ; AND FIND SIZE TO END OF BUFFER JSR PC,DOTEXT ;NOW COUNT LINES IN THAT TEXT MOV #V.SIZE,R0 ;SET THE SCREEN'S SIZE MOV NWATCH(R5),-(SP) ;GET THE STANDARD CURSOR LINE NUMBER BEQ 10$ ;ZERO, MAKE IT VALID CMP R0,(SP) ;MIGHT BE VALID, CHECK UPPER LIMIT BHI 20$ ;IT IS VALID, USE IT 10$: MOV #16.,(SP) ;USE A DEFAULT STANDARD IF INVALID 20$: SUB BUSTRT+RWSIZE(R5),R0 ;CALC LINE NUMBER OF CURSOR LINE CMP R0,(SP) ;SHOULD WE USE THE CALCULATED VALUE? BLOS 30$ ;NOPE, USE STANDARD MOV R0,(SP) ;YEP, USE CALCULATED 30$: MOV #CHCKBL+RWSIZE,R2 ;GET POINTER TO CHECKING BUFFER ADD R5,R2 ; ABSOLUTELY MOV R2,-(SP) ;SAVE START OF THE BUFFER CLR (R2) ;INDICATE NO FUDGE MOVEMENT INITIALLY TSTB OUTDNE ;HAS ANY TERMINAL OUTPUT BEEN DONE? BEQ 40$ ;NOPE CLR INITFL+RWSIZE(R5) ;YEP, INDICATE SCREEN UNKNOWN 40$: TST INITFL+RWSIZE(R5) ;DO WE KNOW WHAT'S ON THE SCREEN? BPL 50$ ;BRANCH IF NOT INC (R2) ;SET THE FLAG WORD 50$: JSR R4,SETJSR ;SET UP FOR .WORD FTRANS ; COUNTING LINES .GLOBL ETYPE, P, .VVV.V, ZZ, NWATCH, RWSIZE, OUTDNE LINES: MOV #FCHAR,OUTCHR+RWSIZE(R5) ;RESET OUTPUT ROUTINE MOV P(R5),LINPTR+RWSIZE(R5) ;SAVE OLD LINE INDEX BEQ TRYMOV ;AT TOP OF PAGE, QUIT FOR NOW MOV #-1,R0 ;GET TO START OF PREVIOUS TEXT LINE JSR PC,.VVV.V ;USING TECO'S MOVER MOV R1,R4 ;NEW 'P' IS RETURNED IN R1, MAKE COPY SUB LINPTR+RWSIZE(R5),R1 ;MAKE R1 CONTAIN NEG R1 ; ONLY CHARS IN -1L CMP R1,#15. ;15. OR MORE CHARACTERS HERE? BLO 20$ ;NOPE, DON'T PUT INTO CHECKING BUFFER TST BUSTRT+RWSIZE(R5) ;IS THIS THE FIRST TIME THROUGH?? BEQ 20$ ;YES, FIRST TIME, DON'T BUFFER THE LINE MOV (SP),R2 ;GET CHECKING BUFFER POINTER TSTB (R2) ;IS IT ALREADY FILLED? BLE 20$ ;YEP, DON'T REUSE IT THEN NEG (R2)+ ;ELSE MARK AS USED NOW MOV R2,BUINDX+RWSIZE(R5) ; AND SET STARTING FILL IN POINTER MOV #CCHAR,OUTCHR+RWSIZE(R5) ; AND CHANGE THE OUTPUT ROUTINE MOV #40.,R0 ;SET SIZE OF BUFFER IN WORDS 10$: MOV (PC)+,(R2)+ ;BLANK THE .BYTE SPACE,SPACE SOB R0,10$ ; WHOLE BUFFER 20$: MOV BUSTRT+RWSIZE(R5),SVSTRT+RWSIZE(R5) ;SAVE STARTING VALUE JSR PC,DOTEXT ;FORMAT A LINE MOV BUSTRT+RWSIZE(R5),R0 ;GET FINISHING LINE NUMBER TST CHCKBL+RWSIZE(R5) ;DOES CHECKING BUFFER LINE NEED SETTING? BPL 30$ ;NOPE MOVB R0,CHCKBL+1+RWSIZE(R5) ;YEP, SO SAVE LINE NUMBER 30$: CMP R0,2(SP) ;WOULD WE BE AT TOP? BLO LINES ;BRANCH IF NOT MOV SVSTRT+RWSIZE(R5),BUSTRT+RWSIZE(R5) ;RESTORE CORRECT VALUE .GLOBL RWSIZE TRYMOV: MOV (SP)+,R2 ;GET CHECKING BUFFER POINTER TSTB (R2)+ ;DID WE FILL IT? BGE OUTPUT ;NOPE MOVB (R2)+,R0 ;SAVE THE "BUSTRT" VALUE MOV BUSTRT+RWSIZE(R5),R1 ;GET ENDING "BUSTRT" VALUE SUB R0,R1 ;CALCULATE THE BUFFERED LINE NUMBER MULT 80 ;FIND OFFSET OF THE BUFFERED LINE MOV R1,(SP) ; AND SAVE IT MOV #MOVTBL-2,R4 ;GET THE MOVEMENT TABLE 10$: TST (R4)+ ;SKIP OVER THE UNUSED MOVE AMOUNT CMP R4,#MOVTBE ;ARE MORE MOVES POSSIBLE? BHIS OUTPUT ;NO, PUNT ON IT MOV (SP),R1 ;YES, GET THE BUFFERED LINE'S OFFSET ADD (R4)+,R1 ;BUILD OFFSET POINTER FOR THIS TRY CMP R1,#MAPND-MAPST ;IS THIS OFFSET OUT OF THE SCREEN? BHIS 10$ ;TOO FAR OUT, GO TRY ANOTHER MOVE ADD #MAPST+RWSIZE,R1 ;INDEX TO SCREEN MAP ADD R5,R1 ; ABSOLUTELY MOV R2,R3 ;SET POINTER TO CHECK BUFFER MOV #40.,R0 ; AND LOAD A COUNTER 20$: CMP (R3)+,(R1)+ ;MATCH?? BNE 10$ ;NO SOB R0,20$ ;YES, LOOP MOV (R4)+,R1 ;TOTAL MATCH!! GET THE MOVMENT AMOUNT CLR R2 ;SET CURSOR TO COLUMN 0 MOV #V.SIZE-1,BUSTRT+RWSIZE(R5) ;ASSUME WE ARE GOING UP MOV #LFSEQ,R3 ;SEQUENCE TO RAISE SCREEN MOV R1,R4 ;SAVE THAT MOVE COUNT BEQ OUTPUT ;NO MOVEMENT, SO QUIT BPL 30$ ;ASSUMPTION RIGHT MOV #REVSEQ,R3 ;SEQUENCE TO LOWER SCREEN CLR BUSTRT+RWSIZE(R5) ;FIX TO LOWER SCREEN NEG R4 ;MAKE COUNT POSITIVE 30$: JSR PC,DOSEQ ;POSITION THE SCREEN SOB R4,30$ ; THE CORRECT NUMBER OF TIMES .GLOBL RWSIZE MOV #MAPST+RWSIZE,R2 ;SET POINTER TO START OF MAP ADD R5,R2 ; ABSOLUTE MOV R2,R0 ;BUILD POINTER ADD #MAPND-MAPST,R0 ; TO END OF MAP MULT 80 ;CALC OFFSET TO START MOVE FROM BMI 60$ ;BRANCH IF TO MOVE INTERNAL MAP DOWN ADD R2,R1 ;ADD IN MAP BASE 40$: MOV (R1)+,(R2)+ ;MOVE THE DATA CMP R1,R0 ;DID WE MOVE LAST DATA BYTE? BLO 40$ ;BRANCH IF NOT 50$: MOV (PC)+,(R2)+ ;FILL REMAINDER WITH BLANKS .BYTE SPACE,SPACE CMP R2,R0 ;ARE WE AT END OF TABLE? BLO 50$ ;BRANCH IF NOT BR OUTPUT ;ELSE DONE SHIFTING 60$: ADD R0,R1 ;POINT TO END OF DATA TO BE MOVED 70$: MOV -(R1),-(R0) ;MOVE THE DATA CMP R1,R2 ;ARE WE AT THE TOP? BHI 70$ ;BRANCH IF NOT 80$: MOV (PC)+,-(R0) ;BLANK FILL REMAINDER .BYTE SPACE,SPACE CMP R0,R2 ;ARE WE AT TOP? BHI 80$ ;BRANCH IF NOT .GLOBL RWSIZE OUTPUT: TST (SP)+ ;JUNK THE STACK ITEM JSR R4,SETJSR ;SET UP FOR .WORD RTRANS ; THE REAL OUTPUT MOV LINPTR+RWSIZE(R5),R4 ;GET STARTING POINT OF TEXT MOV ZZ(R5),R1 ;GET END OF TEXT SUB R4,R1 ; AND FIND AMOUNT OF TEXT TO DO MOV #MAPST+RWSIZE,BUINDX+RWSIZE(R5) ;INIT THE INDEX INTO THE MAP ADD R5,BUINDX+RWSIZE(R5) ; ABSOLUTE TST INITFL+RWSIZE(R5) ;DO WE KNOW THE STATE OF THE SCREEN? BMI 10$ ;BRANCH IF YES CLR R2 ;CLEAR THE COLUMN NUMBER CLR MAPST+RWSIZE(R5) ;CLOBBER THE LAST COPY OF THE MAP MOV #-1,PRELIN+RWSIZE(R5) ;CLOBBER LAST KNOWN CURSOR JSR PC,CLREND ;CLEAR THE SCREEN 10$: MOV (SP),P(R5) ;FINALLY REFIX POINTER ADD TXSTOR(R5),(SP) ;COMPUTE CURSOR POINTER MOV (SP),UNDERC+RWSIZE(R5) ;SAVE POSITION OF UNDER SCORE MOV #V.SIZE-1,CURLIN+RWSIZE(R5) ;PRESET CURSOR AT END OF MOV #H.SIZE-1,CURCHR+RWSIZE(R5) ; SCREEN JSR PC,DOTEXT ;NOW REALLY UPDATE THE SCREEN MOV CURLIN+RWSIZE(R5),BUSTRT+RWSIZE(R5) ;SET THE LINE FOR CURSOR MOV CURCHR+RWSIZE(R5),R2 ;SET THE COLUMN JSR PC,SETCUR ;MOVE THE CURSOR MOV (SP)+,R0 ;GET ABS CURSOR LOCATION TST P(R5) ;IS CURSOR AT START OF TEXT? BEQ 20$ ;YES, CANNOT BE AFTER ANYTHING... CMPB -(R0),#CR ;IMMEDIATELY AFTER A ? BNE 20$ ;NOPE MOV #CURSEQ,R3 ;YEP, SET FANCY SEQUENCE JSR PC,DOTYPE ; AND OUTPUT IT CLRB @CURABS+RWSIZE(R5) ; BUT FORGET THAT LOCATION IN THE MAP 20$: JSR PC,TYPEFC ;FORCE OUT ANY PARTIAL BUFFER MOV #-1,INITFL+RWSIZE(R5) ;NOW WE KNOW WHAT'S ON THE SCREEN CLRB OUTDNE ;ALSO CLEAR TERMINAL OUTPUT FLAG ROR (SP)+ ;DO WE NEED TO CLEAR IMAGE OUTPUT? BCS 30$ ;NOPE, IT WAS SET ON ENTRY BIC #1,ETYPE(R5) ;YEP, SO CLEAR IT ALREADY 30$: RTS PC ;FINALLY WE CAN EXIT .GLOBL RWSIZE, ZZ, P, TXSTOR, TYPEFC, OUTDNE, ETYPE DOTEXT: ADD TXSTOR(R5),R4 ;MAKE POINTER ABSOLUTE MOV R1,-(SP) ;SAVE THE CHARACTER COUNT BR 70$ ;INITIALIZE COLUMN COUNTER AND POINTER 10$: CMPB (R4),#CR ;AVOID SEQUENCE IF OVERFLOW ON BEQ 60$ ;BRANCH IF MOV #200,R0 ;ELSE SET THE OVERFLOW "CHARACTER" BIT #400,ETYPE(R5) ;ALLOWING LINE OVERFLOWS? BEQ 20$ ;YEP, SO DO IT INC R4 ;NOPE, EAT THE CHARACTER CMP R2,#H.SIZE-1 ;WHERE ARE WE?? BHIS 40$ ;REALLY AT THE END, PUNT ON IT JSR PC,@OUTCHR+RWSIZE(R5) ;PUT OVERFLOW "CHARACTER" THERE BR 40$ ;THEN CONTINUE 20$: INC (SP) ;REMEMBER TO GET THE CHARACTER AGAIN MOV R2,RTMOST+RWSIZE(R5) ;SET HIGHEST COLUMN NUMBER CLR R2 ;SIMULATE CARRIAGE RETURN JSR PC,NEWLIN ;FIX SCREEN BHIS 140$ ;BRANCH IF AT BOTTOM OF SCREEN JSR PC,@OUTCHR+RWSIZE(R5) ;OUTPUT OVERFLOW "CHARACTER" MOV #SPACE,R0 ;FOLLOW IT WITH A 30$: JSR PC,@OUTCHR+RWSIZE(R5) ;OUTPUT CHARACTER 40$: CMP R4,UNDERC+RWSIZE(R5) ;IS THIS WHERE THE CURSOR BELONGS? BNE 50$ ;BRANCH IF NOT MOV R1,CURABS+RWSIZE(R5) ;SAVE ABSOLUTE POSITION IN MAP MOV BUSTRT+RWSIZE(R5),CURLIN+RWSIZE(R5) ;SAVE THE LINE NUMBER MOV R2,CURCHR+RWSIZE(R5) ;SAVE THE COLUMN NUMBER CMP R2,#H.SIZE ;IS THE COLUMN NUMBER ILLEGAL? BLO 50$ ;NOPE MOV #H.SIZE-1,CURCHR+RWSIZE(R5) ;YEP, SO FIX IT ALREADY 50$: DEC (SP) ;KNOCK DOWN CHARACTER COUNT BMI 130$ ;BRANCH IF NO MORE FOR END OF SCREEN CMP R2,#H.SIZE-2 ;ABOUT TO OVERFLOW? BHIS 10$ ;BRANCH IF TRUE 60$: MOVB (R4)+,R0 ;GET A BYTE OF TEXT BIC #^C177,R0 ;CLEAN OFF CHARACTER CMP R0,#DEL ;IS IT ? BEQ 110$ ;BRANCH IF YES CMP R0,#SPACE ;IS IT SPECIAL? BHIS 30$ ;BRANCH IF NOT CMP R0,#TAB ;IS IT A ? BEQ 100$ ;BRANCH IF IT IS BLO 110$ ;BRANCH IF MUST BE REGULAR CONTROL CHAR CMP R0,#CR ;IS CHAR A ? BNE 80$ ;BRANCH IF IT IS, RESET COLUMN COUNTER CMP R2,RTMOST+RWSIZE(R5) ;SAVE RIGHT MOST COLUMN ON LINE BLOS 70$ ;BRANCH IF NOT AT IT MOV R2,RTMOST+RWSIZE(R5) ;SAVE IT FOR CLEARING REMAINDER 70$: CLR R2 ;RESET COLUMN COUNTER MOV BUINDX+RWSIZE(R5),R1 ;SET POINTER INTO MAP BR 40$ ; AND CONTINUE .GLOBL TXSTOR, ETYPE, RWSIZE 80$: BHI 110$ ;BRANCH IF > , MAY BE ? SUB #LF,R0 ;R0=0 FOR , R0=1 FOR , R0=2 FOR ASL R0 ;R0=0 FOR , R0=2 FOR , R0=4 FOR 90$: JSR PC,NEWLIN ;HANDLE A NEW SCOPE LINE BHIS 140$ ;BRANCH IF AT BOTTOM OF SCREEN DEC R0 ;KEEP COUNT FOR 'S AND 'S BMI 40$ ;BRANCH IF DONE WITH CHAR BR 90$ ;ELSE CONTINUE 100$: MOV #SPACE,R0 ;OUT SPACES TO TAB STOP JSR PC,@OUTCHR+RWSIZE(R5) ;OUTPUT THE CHARACTER BIT R2,#7 ;AT A TAB STOP? BEQ 40$ ;BRANCH IF SO CMP R2,#H.SIZE-2 ;ELSE ABOUT TO OVERFLOW LINE? BLO 100$ ;NOPE, LOOP BR 40$ ;YES, QUIT 110$: MOV #'$,-(SP) ;GUESS AT CMP R0,#ESC ;GOOD GUESS?? BEQ 120$ ;YES, GOES AS "$" ADD #100,R0 ;NO, PUT CHARACTER INTO RANGE BIC #^C<177>,R0 ; AND MASK IT FOR SAFETY MOV R0,(SP) ;SAVE CHARACTER MOV #'^,R0 ;PRINT ARROW JSR PC,@OUTCHR+RWSIZE(R5) ;OUTPUT THE CHAR 120$: MOV (SP)+,R0 ;GET THE CHAR BACK BR 30$ ; AND CONTINUE 130$: SUB TXSTOR(R5),R4 ;MAKE TEXT POINTER RELATIVE AGAIN CMP R4,ZZ(R5) ;AT END OF BUFFER NOW? BNE 140$ ;NOPE CMP R2,#H.SIZE ;YEP, ANY ROOM LEFT ON THIS LINE? BHIS 140$ ;SORRY, NO ROOM LEFT MOV #201,R0 ;ROOM, SET END OF BUFFER "CHARACTER" JSR PC,@OUTCHR+RWSIZE(R5) ; AND OUTPUT IT 140$: TST (SP)+ ;JUNK THE CHARACTER COUNTER CLREND: MOV #EEOSEQ,R3 ;SET EOS SEQUENCE FOR BLANKING MOV #MAPND+RWSIZE,R0 ;POINT TO END OF SCREEN MAP ADD R5,R0 ; ABSOLUTELY JMP @OUTBLN+RWSIZE(R5) ;CALL BLANKER FOR REST OF SCREEN .GLOBL RWSIZE, TXSTOR, ZZ NEWLIN: MOV R0,-(SP) ;SAVE FOR LATER MOV R2,-(SP) ;ALSO SAVE COLUMN POSITIN MOV BUINDX+RWSIZE(R5),R0 ;CALCULATE END OF ADD #80.,R0 ; LINE POINTER MOV #CLNSEQ,R3 ;SET SEQ TO CLEAR ONLY THIS LINE JSR PC,@OUTBLN+RWSIZE(R5) ;ERASE THE REMAINDER OF LINE IF ANYTHING CLR RTMOST+RWSIZE(R5) ;CLEAR IT FOR NEW LINE MOV R0,BUINDX+RWSIZE(R5) ;UPDATE TO NEW LINE ON SCREEN FACE INC BUSTRT+RWSIZE(R5) ;FLAG A NEW LINE DONE MOV R0,R1 ;SET NEW MAP POINTER TST (SP) ;GET THE COLUMN POSITION BEQ 20$ ;BRANCH IF AT COLUMN 0, NORMAL CASE CMP BUSTRT+RWSIZE(R5),#V.SIZE ;ALREADY OFF THE SCREEN? BHIS 20$ ;YES, FORGET IT CLR R2 ;NO, START FROM COLUMN 0 MOV #SPACE,R0 ; AND USE SPACES FOR BLANKING 10$: JSR PC,@OUTCHR+RWSIZE(R5) ;OUTPUT ONE BLANK CMP R2,(SP) ;UP TO THE CURSOR POSITION YET? BLO 10$ ;NOPE, CONTINUE 20$: MOV (SP)+,R2 ;RESET COLUMN POSITION MOV (SP)+,R0 ;GET BACK FLAG FOR TYPE OF CHAR CMP BUSTRT+RWSIZE(R5),#V.SIZE ;'BHIS' BRANCHES IF AT BOTTOM RTS PC ;RETURN SETJSR: MOV #OUTCHR+RWSIZE,R3 ;GET ADDRESS OF FIRST VECTOR ADD R5,R3 ; ABSOLUTELY MOV (R4)+,R2 ;GET POINTER TO THE TABLE 10$: MOV (R2)+,(R3)+ ;PUT IN A NEW ADDRESS BNE 10$ ;LOOP THROUGH LIST CLR (R3)+ ;CLEAR "BUSTRT" ALSO RTS R4 ;THEN EXIT .IF NDF I$$MUL MUL80: ASL R1 ;*80. IS *40.*2 MUL40: MOV R1,-(SP) ;SAVE *1 ASL R1 ;NOW *2 ASL R1 ;NOW *4 ADD (SP)+,R1 ;NOW *5 ASL R1 ;NOW *10. ASL R1 ;NOW *20. ASL R1 ;NOW *40. RTS PC ;SO EXIT .ENDC .GLOBL RWSIZE VTBLNK: MOV R1,-(SP) ;SAVE MOV R2,-(SP) ; WORK MOV R4,-(SP) ; REGS MOV R0,-(SP) ;ADDRESS TO STOP AT CMP R2,RTMOST+RWSIZE(R5) ;CHECK FOR RIGHTMOST USED COLUMN BHIS 10$ ;R2 IS RIGHT MOV RTMOST+RWSIZE(R5),R2 ;FIX R2 10$: MOV BUINDX+RWSIZE(R5),R1 ;GET ADDRESS OF CURRENT LINE ADD R2,R1 ;POINT TO WHERE WE ARE IN BUFFER MOV #-1,R4 ;SET FLAG TO CLEAR EOS IF NEEDED 20$: CMP R1,(SP) ;ARE WE AT END YET? BHIS 60$ ;BRANCH IF YES BIT R1,#1 ;ON WORD BOUNDARY? BEQ 40$ ;BRANCH IF YES CMPB #SPACE,(R1)+ ;IS THIS A BLANK ALREADY? BEQ 20$ ;BRANCH IF YES MOVB #SPACE,-1(R1) ;SET IT TO A BLANK INC R4 ;DO WE HAVE TO CLEAR END OF SCREEN? BNE 20$ ;BRANCH IF ALREADY DONE 30$: JSR PC,DOSEQ ;CLEAR LINE OR SCREEN BR 20$ ;CONTINUE THE CLEAR LOOP 40$: CMP (PC)+,(R1)+ ;ARE THESE BLANKS ALREADY? .BYTE SPACE,SPACE BEQ 50$ ;YES MOV #SPACE*400+SPACE,-2(R1) ;SET LAST TWO TO BLANKS INC R4 ;DO WE HAVE TO CLEAR TO EOS? BEQ 30$ ;BRANCH IF WE NEED TO 50$: CMP R1,(SP) ;ARE WE AT END YET? BLO 40$ ;NOT YET 60$: MOV (SP)+,R0 ;RESTORE THE LIMIT MOV (SP)+,R4 ;RESTORE MOV (SP)+,R2 ; WORK MOV (SP)+,R1 ; REGS RTS PC ;EXIT .GLOBL RWSIZE VTCHAR: CMPB R0,(R1)+ ;ARE CHARACTERS THE SAME?? BEQ FCHAR ;BRANCH IF YES, DON'T SEND IT! JSR PC,SETCUR ;POSITION THE CURSOR MOVB R0,-1(R1) ;SAVE THE CHARACTER BPL 10$ ;NOT SPECIAL ASLB R0 ;SPECIAL, MAKE INTO AN INDEX MOV SEQS(R0),R3 ; AND GET THE SEQUENCE POINTER JSR PC,DOTYPE ; AND OUTPUT IT BR 20$ ;THEN CONTINUE 10$: JSR PC,TYPEBF ;NOW SEND CHARACTER 20$: INC PRECOL+RWSIZE(R5) ;INDICATE CURSOR MOVED 1 TO THE RIGHT FCHAR: INC R2 ;ADVANCE COLUMN NUMBER RTS PC ; THEN EXIT .ENABL LSB CCHAR: INC R2 ;ADVANCE COLUMN NUMBER MOVB R0,(R1)+ ;SAVE THE CHARACTER BGT 10$ ;NORMAL, CONTINUE NEG CHCKBL+RWSIZE(R5) ;SPECIAL, SAY THIS LINE NOT FILLED FBLNK: MOV #FCHAR,OUTCHR+RWSIZE(R5) ;RESET THE OUTPUT ROUTINE 10$: RTS PC ;THEN RETURN .DSABL LSB .GLOBL TYPEBF, RWSIZE .ENABL LSB SETCUR: MOV R0,-(SP) ;SAVE R0 MOV BUSTRT+RWSIZE(R5),R0 ;GET LINE NUMBER CMP R0,PRELIN+RWSIZE(R5) ;IS THIS THE RIGHT LINE? BNE 10$ ;BRANCH IF NOT, MUST SET CURSOR MOV #V.SIZE,R0 ;SET TO NOT VERTICALLY POSITION CURSOR ;THIS IS TO HELP STOP VT52 FROM FLICKER CMP R2,PRECOL+RWSIZE(R5) ;ARE WE AT RIGHT CURSOR POSITION? BEQ 30$ ;BRANCH IF YES, DON'T MOVE IT 10$: MOV BUSTRT+RWSIZE(R5),PRELIN+RWSIZE(R5) ;SAVE CURSOR POS ON SCREEN MOV R2,PRECOL+RWSIZE(R5) ; BOTH LINE AND COLUMN MOV R3,-(SP) ;SAVE R3 OVER SEQUENCES MOV #DIRSEQ,R3 ;POINT TO DIRECT CURSOR ADDRESS CODE JSR PC,DOTYPE ; AND OUTPUT IT ADD #40,R0 ;ADJUST LINE NUMBER JSR PC,TYPEBF ; AND OUTPUT IT MOV R2,R0 ;NOW SET COLUMN NUMBER ADD #40,R0 ;ADJUST COLUMN NUMBER JSR PC,TYPEBF ; AND OUTPUT IT 20$: MOV (SP)+,R3 ;RESTORE R3 30$: MOV (SP)+,R0 ;RESTORE R0 RTS PC ; AND EXIT DOSEQ: JSR PC,SETCUR ;SET UP THE CURSOR DOTYPE: MOV R0,-(SP) ;SAVE R0 MOV R3,-(SP) ; AND R3 40$: MOVB (R3)+,R0 ;GET A CHARACTER ASLB R0 ;IS IT THE ENDING 200? BEQ 20$ ;YES ASR R0 ;NO, RESTORE CHARACTER JSR PC,TYPEBF ;ELSE BUFFER IT BR 40$ ; AND CONTINUE .DSABL LSB .GLOBL RWSIZE, TYPEBF RTRANS: .WORD VTCHAR, VTBLNK, 0 FTRANS: .WORD FCHAR, FBLNK, 0 MOVTBL: .WORD 000000*80., 000000 $$$$$$ = 1 .REPT V.SIZE/2 .WORD +$$$$$$*80., +$$$$$$ .WORD -$$$$$$*80., -$$$$$$ $$$$$$ = $$$$$$+1 .ENDR MOVTBE: SEQS: .WORD OVRSEQ,EOBSEQ EOBSEQ: .BYTE ESC,'F,'A+40,ESC,'G,200 CURSEQ: .BYTE ESC,'F,'K+40,ESC,'G,ESC,'D,200 OVRSEQ: .BYTE ESC,'F,'H+40,ESC,'G,200 CLNSEQ: .BYTE ESC,'K,200 DIRSEQ: .BYTE ESC,'Y,200 EEOSEQ: .BYTE ESC,'J,200 LFSEQ: .BYTE LF,200 REVSEQ: .BYTE ESC,'I,200 .EVEN ; THE LAYOUT OF THE READ/WRITE REGION .ASECT . = 0 OUTCHR: .BLKW ;OUTPUT A CHARACTER OUTBLN: .BLKW ;END OF LINE OR BUFFER CLEANER RTMOST: .BLKW ;INITED TO ZERO AS END OF LIST BUSTRT: .BLKW ;LINE COUNTER, INITED TO ZERO LINPTR: .BLKW ;CHAR COUNTER (P) OF LINE STARTS SVSTRT: .BLKW ;SAVED LINE COUNTER INITFL: .BLKW ;>=0 IMPLIES UNKNOWN SCREEN STATE BUINDX: .BLKW ;CONTAINS LINE INDEX INTO SCREEN MAP CURLIN: .BLKW ;CONTAINS LINE NUMBER OF CURSOR CURCHR: .BLKW ;CONTAINS COLUMN NUMBER OF CURSOR CURABS: .BLKW ;CONTAINS ABSOLUTE MAP POSITION OF CURSOR UNDERC: .BLKW ;CHARACTER POS OF UNDER SCORE PRELIN: .BLKW ;LAST SET LINE TO SCREEN PRECOL: .BLKW ;LAST SET COLUMN TO SCREEN CHCKBL: .BLKW ;FLAG WORD .BLKB 80. ;ROOM FOR CHARS MAPST: .BLKB 80.*24. ;LAST KNOWN SCREEN MAPND: ;END OF SCREEN MAP SCRWSZ: ;SIZE OF READ/WRITE REGION .END