.TITLE VTM - VT100 MESSAGE FORMATTER .IDENT /04.11/ .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: VTM.MAC ; Author: Robin Miller ; Date: June 10, 1982 ; ; Description: ; ; This program is format a message for a VT100 terminal. Various ; options are available (documented in VTPARS.MAC). The default is to ; clear the screen and and write the message in double height characters ; centered in the middle of the screen. ; ; ; Modification History: ; ;- .ENABL AMA .NLIST BEX .MCALL ALUN$S, DIR$, EXIT$S, EXST$S, GLUN$, GMCR$, GTSK$, QIOW$ .MCALL GCMLB$, GCML$ .MCALL CLOSE$, FINIT$, NMBLK$ .MCALL FSRSZ$, FDBDF$, FDAT$A, FDOP$A, FDRC$A, FDBF$A .SBTTL LOCAL EQUATES ; Local equates: LF = 10. ; ASCII FOR LINE FEED CR = 13. ; ASCII FOR CARRIAGE RETURN ESC = 27. ; ASCII FOR ESCAPE DEFLIN = 12. ; DEFAULT FIRST LINE TOPLIN = 1 ; DEFAULT TOP LINE BOTLIN = 23. ; DEFAULT BOTTOM LINE PRMLIN = 24. ; DEFAULT PROMPT LINE LFMARG = 1 ; DEFAULT LEFT MARGIN RTMARG = 80. ; DEFAULT RIGHT MARGIN DEPTH = 2 ; DEPTH OF COMMAND FILES CMDSIZ = 256. ; SIZE OF COMMAND LINE BUFFER INSIZE = 256. ; SIZE OF INPUT BUFFER FILSIZ = 100. ; SIZE OF FILE NAME BUFFER TILUN == 1 ; TERMINAL INPUT LUN TIEFN == 1 ; TERMINAL INPUT EFN TOLUN == 2 ; TERMINAL OUTPUT LUN TOEFN == 2 ; TERMINAL OUTPUT EFN ERRLUN == 3 ; ERROR MESSAGE LUN ERREFN == 3 ; ERROR MESSAGE EFN ERRSIZ == 80. ; SIZE OF ERROR MESSAGES OUTLUN == 4 ; OUTPUT FILE LUN OUTEFN == 4 ; OUTPUT FILE EFN OUTSIZ = 512. ; SIZE OF OUTPUT BUFFER TTYLUN == 5 ; ADDITIONAL TTY LUN TTYEFN == 5 ; AND THE EVENT FLAG ; Macro to generate error message. .MACRO ERRMSG LABEL,MSG .NCHR $$$, .PSECT $ERMSG,RO,D,REL,CON LABEL: .ASCII "MSG" .EVEN .PSECT MOV #LABEL,R1 MOV #$$$,R2 CALL OUTMSG .ENDM ; Macro to move a constant or a single character. .MACRO MOVCHR CHAR .NCHR $$$,^/CHAR/ .IF EQ $$$-1 MOVB #''CHAR,@BUFPTR .IFF MOVB #CHAR,@BUFPTR .ENDC INC BUFPTR .ENDM ; Macro to move a message to the buffer pointer. .MACRO MOVMSG LABEL MOV #LABEL,R0 CALL MOVEC .ENDM ; Various buffers. .PSECT $$ZZZZ,RW,D,REL,CON ; FORCE BUFFERS TO END OF TASK BUFPTR::.WORD INBUF ; POINTER TO MESSAGE BUFFER FILPTR::.WORD FILNAM ; POINTER TO FILENAME STORAGE MSGBUF::.BLKB OUTSIZ ; MESSAGE OUTPUT BUFFER CMDBUF::.BLKB CMDSIZ ; COMMAND FILE INPUT BUFFER INBUF:: .BLKB INSIZE ; PARSED INPUT BUFFER ERRBUF::.BLKB ERRSIZ ; ERROR MESSAGE BUFFER FILNAM::.BLKB FILSIZ ; STORAGE FOR ASCII FILE NAME ; LARGE FOR VAX/VMS FILE NAMES .PSECT ; RETURN TO ORIGINAL PSECT .SBTTL STATUS BIT DEFINITIONS ; Status bit definitions: B.CLR == 1 ; CLEAR SCREEN OPTION (DEFAULT) B.CENT == 2 ; CENTER MESSAGE ON THE SCREEN B.WIDE == 4 ; WIDE / NARROW SCREEN 0 = NARROW B.ATTR == 10 ; NEED TO REMOVE ATTRIBUTES B.DBLH == 20 ; DOUBLE HEIGHT CHARACTERS B.DBLW == 40 ; DOUBLE WIDTH CHARACTERS B.FILE == 100 ; OUTPUT TO FILE INSTEAD OF TTY B.ITTY == 200 ; INPUT IS FROM THE TERMINAL B.ICNT == 400 ; ITERATION COUNT SPECIFIED B.COL == 1000 ; COLUMN NUMBER SPECIFIED B.RJUS == 2000 ; RIGHT JUSTIFY MESSAGE B.LJUS == 4000 ; LEFT JUSTIFY MESSAGE B.DOIT == 10000 ; DO CURSER POSITIONING B.CTRC == 20000 ; CONTROL/C WAS TYPED B.EXIT == 40000 ; SHOW WE ARE EXITING B.ERRS == 100000 ; ERROR SEEN SOMEWHERE ; Second status bit definitions: B.REL == 1 ; RELATIVE LINE NUMBER B.DIR == 2 ; DIRECTION +/- = 0/1 .SBTTL LOCAL AND GLOBAL STORAGE AREA ; Local and global storage area. STATUS::.WORD B.CLR!B.CENT!B.DBLH ; STATUS WORD FOR OPTIONS ; SET THE DEFAULT FLAGS ; = CLEAR / CENTER / DOUBLE HEIGHT STAT1:: .WORD 0 ; SECOND STATUS WORD COLUMN::.WORD 0 ; USER SPECIFIED COLUMN # ESCCNT::.WORD 0 ; # OF VT100 CHARACTERS MOVED ICOUNT::.WORD 0 ; ITERATION COUNT -1 = INFINITE COUNT:: .WORD 0 ; CHARACTER COUNT TO CENTER ; MESSAGE IN MIDDLE OF SCREEN LINE:: .WORD DEFLIN ; STARTING LINE NUMBER RELNUM::.WORD 0 ; RELATIVE LINE COUNT PRLINE::.WORD PRMLIN ; PROMPT LINE NUMBER TPLINE::.WORD TOPLIN ; TOP LINE NUMBER BTLINE::.WORD BOTLIN ; BOTTOM LINE NUMBER LMARGN::.WORD LFMARG ; LEFT MARGIN RMARGN::.WORD RTMARG ; RIGHT MARGIN REGTOP::.WORD 0 ; TOP LINE OF SCROLL REGION REGBOT::.WORD 0 ; BOTTOM LINE OF SCROLL REGION DELAYT::.WORD 0 ; AMOUNT OF TIME TO DELAY TTYNAM::.WORD 0 ; OUTPUT TERMINAL NAME TTYNUM::.WORD 0 ; OUTPUT TERMINAL NUMBER BEOPT:: .WORD 0 ; POINTER TO BEGINNING OF ; LAST OPTION FOR ERRORS ; Get Command Line control block. GCLBLK::GCMLB$ DEPTH,VTM,CMDBUF,TILUN,,CMDSIZ TIUNIT: .WORD 0 ; UNIT NUMBER OF TI0: GETTSK: GTSK$ TSKBUF ; GET TASK PARAMETERS TSKBUF: .BLKW 16. ; AND THE BUFFER MRKFLG::.WORD 0 ; MARK TIME ACTIVE -1 = TRUE VAXFLG::.WORD 0 ; RUNNING ON VAX/VMS -1 = TRUE ATTACH: QIOW$ IO.ATA,TOLUN,TOEFN,,TIOSB,,<,,CTRLC> FUNC:: .WORD IO.WBT!TF.WAL ; FUNCTION FOR RSX-11M TIOSB:: .BLKW 2 ; TERMINAL I/O STATUS BLOCK BUFADR::.WORD 0 ; OUTPUT BUFFER ADDRESS BYTCNT::.WORD 0 ; OUTPUT BUFFER BYTE COUNT LUN:: .WORD 0 ; CURRENT LUN FOR QIOW$ EFN:: .WORD 0 ; AND THE EFN GETLUN::GLUN$ TILUN,LUNBUF ; GET LUN INFORMATION LUNBUF::.BLKW 6 ; AND THE BUFFER TTUNIT == LUNBUF+G.LUNU ; POINTER TO UNIT NUMBER .SBTTL FILE DESCRIPTOR BLOCKS ;+ ; ; There is a FDB used for each LUN so VTM will operate properly ; on VAX/VMS. Normally I'd assign TI0: to input, output, and ; the error LUNs. But this prevents VTM from running in BATCH ; and command procedures on VAX/VMS. ; ;- FSRSZ$ 4 ; FILE STORAGE FOR 4 OPEN FILES TIFDB:: FDBDF$ ; FDB FOR TERMINAL INPUT FDAT$A R.VAR,FD.CR,,, ; VARIABLE LENGTH RECORDS FDRC$A ,CMDBUF,CMDSIZ ; LOCATE MODE / MAX SIZE FDOP$A TILUN,,DEFNB,FO.RD ; OPEN FOR READ FDBF$A TIEFN,CMDSIZ,, ; INIT BLOCK BUFFER SECTION TOFDB:: FDBDF$ ; FDB FOR TERMINAL OUTPUT FDAT$A R.VAR,,,, ; VARIABLE LENGTH RECORDS FDRC$A ,MSGBUF,OUTSIZ ; LOCATE MODE / MAX SIZE FDOP$A TOLUN,,OUTNB,FO.WRT ; OPEN FOR WRITE FDBF$A TOEFN,OUTSIZ,, ; INIT BLOCK BUFFER SECTION ERRFDB:: FDBDF$ ; FDB FOR ERROR MESSAGES FDAT$A R.VAR,FD.CR,,, ; VARIABLE LENGTH RECORDS FDRC$A ,ERRBUF,ERRSIZ ; LOCATE MODE / MAX SIZE FDOP$A ERRLUN,,ERRNB,FO.WRT ; OPEN FOR WRITE FDBF$A ERREFN,OUTSIZ,, ; INIT BLOCK BUFFER SECTION OUTFDB:: FDBDF$ ; FDB FOR OUTPUT FILE FDAT$A R.VAR,,,, ; VARIABLE LENGTH RECORDS FDRC$A ,MSGBUF,OUTSIZ ; LOCATE MODE / MAX SIZE FDOP$A OUTLUN,,DEFNB,FO.WRT!FA.NSP ; OPEN FOR WRITE FDBF$A OUTEFN,OUTSIZ,, ; INIT BLOCK BUFFER SECTION ; Default file name blocks. OUTNB: NMBLK$ VTM,OUT,,SY,0 ; TERMINAL OUTPUT ERRNB: NMBLK$ VTM,ERR,,SY,0 ; ERROR MESSAGES DEFNB: NMBLK$ VTM,DAT,,SY,0 ; OUTPUT FILE NAME BLOCK ; Terminal output devices: TISTR: .ASCIZ "TI0:" ; TI0: FOR RSX-11M SYSIN: .ASCIZ "SYS$INPUT:" ; INPUT FOR VAX/VMS SYSOUT: .ASCIZ "SYS$OUTPUT:" ; OUTPUT FOR VAX/VMS SYSERR: .ASCIZ "SYS$ERROR:" ; ERRORS FOR VAX/VMS .EVEN .SBTTL VTM - MAIN LINE CODE ;+ ; ; VTM - Main line code. ; ; This program is used to format a message for a VT100 terminal. ; ;- .ENABL LSB VTM:: MOV @#.FSRPT,R0 ; GET POINTER TO FSR TST A.DFUI(R0) ; HAS .FINIT BEEN DONE (DDT) BNE 10$ ; IF NE, YES (DO ONLY ONCE) FINIT$ ; DO THE FINIT 10$: DIR$ #GETLUN ; GET LUN INFORMATION CALL CHKDIR ; CHECK/REPORT DIRECTIVE ERROR MOVB GETLUN+G.LUNU,TIUNIT ; SAVE THE TERMINAL UNIT # DIR$ #GETTSK ; GET TASK PARAMETERS CALL CHKDIR ; CHECK/REPORT DIRECTIVE ERROR CLR VAXFLG ; PRESUME NOT ON VAX/VMS CMPB #5,TSKBUF+G.TSSY ; ARE WE ON VAX/VMS ? BNE 20$ ; IF NE, NO MOV #-1,VAXFLG ; YES, SET THE FLAG TRUE MOV #IO.WAL,FUNC ; FUNCTION CODE FOR VAX/VMS DEC BTLINE ; ADJUST BOTTOM LINE DEC PRLINE ; ADJUST PROMPT LINE DEC BLINB ; ADJUST BOTTOM BOX LINE ; Open the input, output, and error LUNS. For RSX-11M, these ; should be asssigned at TKB time to TI:. That way they can ; be reassigned using the REAssign MCR command to a disk. ; For VAX/VMS, SYS$INPUT, SYS$OUTPUT, and SYS$ERROR are used. ; These can be reassigned using the ASSIGN/USER file SYS$xxxxx. ; Do SYS$ERROR first incase we get errors on the others. 20$: MOV #ERRFDB,R0 ; ERROR MESSAGE FDB MOV #TISTR,R1 ; USE TI0: ON RSX-11M TST VAXFLG ; ARE WE ON VAX/VMS ? BEQ 25$ ; IF EQ, NO MOV #SYSERR,R1 ; YES, WRITE TO SYS$ERROR 25$: CALL OPENW ; OPEN THE LUN FOR WRITE BCS 100$ ; IF CS, ERROR ; Now do the input LUN (SYS$INPUT). MOV #TIFDB,R0 ; TERMINAL INPUT FDB MOV #TISTR,R1 ; USE TI0: ON RSX-11M TST VAXFLG ; ARE WE ON VAX/VMS ? BEQ 30$ ; IF EQ, NO MOV #SYSIN,R1 ; YES, READ FROM SYS$INPUT 30$: CALL OPENR ; OPEN THE LUN FOR READ BCS 100$ ; IF CS, ERROR CLOSE$ ; NOW CLOSE IT SO GCML$ ; CAN READ IT ; Open the output LUN (SYS$OUTPUT). MOV #TOFDB,R0 ; TERMINAL OUTPUT FDB MOV #TISTR,R1 ; USE TI0: ON RSX-11M TST VAXFLG ; ARE WE ON VAX/VMS ? BEQ 40$ ; IF EQ, NO MOV #SYSOUT,R1 ; YES, WRITE TO SYS$OUTPUT 40$: CALL OPENW ; OPEN THE LUN FOR WRITE BCS 100$ ; IF CS, ERROR BITB #FD.TTY,F.RCTL(R0) ; IS OUTPUT TO A TERMINAL ? BEQ 50$ ; IF EQ, NO CLOSE$ ; YES, CLOSE THE FILE DIR$ #ATTACH ; ATTACH WITH CTRL/C AST CALL CHKDIR ; CHECK/REPORT DIRECTIVE ERROR 50$: MOV #GCLBLK,R0 ; ADDRESS OF CONTROL BLOCK BISB #GE.CON!GE.LC,G.MODE(R0) ; SET FOR CONTINUATION ; LINES AND LOWERCASE INPUT MOV F.DFNB(R0),R1 ; ADDRESS OF FILE NAME BLOCK MOV #^RVTM,N.FTYP(R1) ; DEFAULT EXTENSION TO .VTM BR GETCMD ; AND CONTINUE ... ; We've had an error openning the input or output LUNs. 100$: MOV F.ERR(R0),R0 ; COPY THE ERROR CODE CALL WRTERR ; TRY TO WRITE THE ERROR JMP EXISEV ; EXIT WITH SEVERE ERROR .DSABL LSB ; Get the command line and check for errors. .ENABL LSB GETCMD::MOV #GCLBLK,R0 ; ADDRESS OF CONTROL BLOCK GCML$ ; GET A COMMAND LINE BCC GOTCMD ; IF CC, GOT A COMMAND CMPB #GE.EOF,G.ERR(R0) ; END OF FILE DETECTED ? BNE 10$ ; IF NE, NO JMP EXIT ; YES, EXIT ; For the errors GE.IOR & GE.OPR, F.ERR in the FDB has the error code. 10$: CMPB #GE.IOR,G.ERR(R0) ; I/O ERROR DETECTED ? BEQ 20$ ; IF EQ, YES CMPB #GE.OPR,G.ERR(R0) ; FILE OPEN ERROR ? BEQ 20$ ; IF EQ, YES CMPB #GE.BIF,G.ERR(R0) ; SYNTAX ERROR ? BEQ 30$ ; IF EQ, YES CMPB #GE.MDE,G.ERR(R0) ; MAX @ DEPTH EXCEEDED ? BNE 20$ ; IF NE, NO (TRY FCS ERROR) ERRMSG TOOMNY,<%VTM-F-TOOMANY, maximum @ file depth exceeded.> JMP EXIT ; CONSIDER THIS FATAL ; Report an error message. 20$: MOV F.ERR(R0),R0 ; COPY THE ERROR CODE CALL WRTERR ; WRITE THE ERROR MESSAGE BR GETCMD ; AND GET THE NEXT COMMAND 30$: ERRMSG SYNERR,<%VTM-W-SYNERR, syntax error.> BR GETCMD ; GET THE NEXT COMMAND .DSABL LSB ; Got a command line. GOTCMD::MOV #GCLBLK,R0 ; ADDRESS OF CONTROL BLOCK MOV G.CMLD(R0),R3 ; COPY THE BYTE COUNT ; BEQ GETCMD ; IF EQ, NOTHING INPUT BIS #B.ITTY,STATUS ; PRESUME INPUT FROM TTY BITB #FD.TTY,F.RCTL(R0) ; INPUT FROM THE TERMINAL ? BNE 10$ ; IF NE, YES BIC #B.ITTY,STATUS ; NO, MUST BE FROM FILE 10$: MOV G.CMLD+2(R0),R4 ; INPUT BUFFER ADDRESS TST R3 ; IS THERE A BYTE COUNT ? BGT 15$ ; IF EQ, YES (CONTINUE) JMP NOMSG ; NO MESSAGE TO OUTPUT 15$: MOV R4,R0 ; COPY THE BUFFER ADDRESS ADD R3,R0 ; POINT TO END OF LINE CLRB (R0) ; NOW, TERMINATE WITH NULL CALL CVTOPT ; CONVERT OPTIONS TO UPPERCASE ; ; Use TPARS to parse the command line. ; ; Inputs: ; R1 = bit 0 in the low byte controls processing of blanks/tabs: ; if 0, ignore blanks, if 1 then pass blanks and tabs. ; the high byte contains the number of characters that ; keywords are alloewed to be abbreviated (0 = exact). ; R3 = the input string byte count, ; R4 = the input buffer address. ; ; Outputs: ; R3 = zero on success or ; remaining byte count on syntax error. ; R4 = end of input string or ; updated buffer address on syntax error. ; BIC #B.COL,STATUS ; MUST SPECIFY COLUMN NUMBER BIC #B.DOIT,STATUS ; SOME COMMANDS FORCE CURSERING BIC #B.LJUS!B.RJUS,STATUS ; THESE ARE ALSO ONE SHOTS MOV #INBUF,BUFPTR ; INITIALIZE THE BUFFER POINTER CLR COUNT ; CHARACTER COUNT FOR CENTERING MOV #<<400*1>+1>,R1 ; PASS BLANKS, MATCH 1 CHARACTER MOV #KEYWRD,R2 ; ADDRESS OF KEYWORD TABLE MOV #START,R5 ; STARTING TRANSITION ADDRESS CALL .TPARS ; NOW DO THE PARSE BIT #B.CTRC,STATUS ; WAS CTRL/C TYPED ? BEQ 17$ ; IF EQ, NO JMP EXIT ; YES, EXIT NOW 17$: BCC 30$ ; IF CC, SUCCESS (.TPARS) MOV BEOPT,R4 ; POINTER TO LAST OPTION ; On syntax errors, output the remaining characters. 20$: MOVB (R4)+,@BUFPTR ; COPY THE REST OF THE LINE BEQ 30$ ; IF EQ, FINISHED INC BUFPTR ; POINT TO NEXT LOCATION INC COUNT ; COUNT THIS CHARACTER BR 20$ ; LOOP UNTIL DONE 30$: BIT #B.ATTR,STATUS ; ARE ATTRIBUTES STILL ON ? BEQ 40$ ; IF EQ, NO CALL ATTOFF ; YES, TURN THEM OFF 40$: CLRB @BUFPTR ; TERMINATE THE INPUT BUFFER ; See if we should clear the screen. MOV #MSGBUF,BUFPTR ; STORE USER MESSAGE HERE CLRB @BUFPTR ; INITIALIZE THE FIRST BYTE BIT #B.CLR,STATUS ; SHOULD WE CLEAR THE SCREEN ? BEQ 50$ ; IF EQ, NO CALL CLRSCR ; MOVE IN SCLEAR SCREEN ; If there is no message to write, check the input buffer. 50$: TST COUNT ; USER SPECIFY A MESSAGE ? BGT 60$ ; IF GT, YES (CONTINUE) BIT #B.DOIT,STATUS ; DO CURSER POSITIONING ? BNE 60$ ; IF NE, YES MOVMSG INBUF ; COPY THE INPUT BUFFER BR 120$ ; AND CONTINUE ... ; Form the first half of the message. 60$: MOV LINE,R1 ; COPY THE STARTING LINE # CALL MAKLIN ; MAKE THE ASCII LINE # CALL MAKCOL ; MAKE THE ASCII COLUMN # BIT #B.DBLW,STATUS ; DOUBLE WIDTH MESSAGE ? BEQ 70$ ; IF EQ, NO CALL DWIDTH ; MOVE THE DOUBLE WIDTH BR 80$ ; AND CONTINUE ... 70$: BIT #B.DBLH,STATUS ; DOUBLE HEIGHT MESSAGE ? BEQ 80$ ; IF EQ, NO CALL DHTOP ; MOVE IN THE TOP HALF 80$: MOVMSG ; COPY THE MESSAGE ; Form the second half of the message. BIT #B.DBLH,STATUS ; DOUBLE HEIGHT MESSAGE ? BEQ 100$ ; IF EQ, NO (SINGLE LINE) TST FENTRY ; OUTPUTTING TO A FILE ? BEQ 90$ ; IF EQ, NO (APPEND MORE) CALL WRTMSG ; YES, WRITE FIRST HALF ; SO RECORD ISN'T TOO BIG 90$: INC LINE ; POINT TO THE NEXT LINE # MOV LINE,R1 ; NOW COPY IT FOR MAKLIN CALL MAKLIN ; MAKE THE ASCII LINE # CALL MAKCOL ; MAKE THE ASCII COLUMN # CALL DHBOT ; MOVE THE BOTTOM HALF MOVMSG ; COPY THE MESSAGE AGAIN 100$: INC LINE ; POINT TO THE NEXT LINE # CALL CHKLIN ; CHECK RANGE OF LINE # 120$: TSTB MSGBUF ; IS THERE ANYTHING TO OUTPUT ? BEQ NOMSG ; IF EQ, NO (GET NEXT COMMAND) CALL WRTMSG ; WRITE THE CURRENT BUFFER BIT #B.ICNT,STATUS ; ITERATION COUNT SPECIFIED ? BEQ NOMSG ; IF EQ, NO (CONTINUE...) CMP #-1,ICOUNT ; LOOP INFINITLY ? BEQ 130$ ; IF EQ, YES DEC ICOUNT ; ARE WE FINISHED ? BNE 130$ ; IF NE, MORE TO GO BIC #B.ICNT,STATUS ; NO MORE ITERATION COUNT BR NOMSG ; AND CONTINUE ... 130$: JMP GOTCMD ; NOPE, USE SAME COMMAND ; If input is from the terminal, write the ending sequence ; to position to and clear the prompt line. NOMSG: CALL WRTEND ; WRITE THE ENDING MESSAGE JMP GETCMD ; GET THE NEXT COMMAND .SBTTL CHKLIN - CHECK THE LINE NUMBER ;+ ; ; CHKLIN - Check the line number to ensure its not too large. ; ; If the current line number is too large, we'll use the top line number. ; ; Inputs: ; LINE = the current line number. ; ; Outputs: ; All registers are preserved. ; ;- CHKLIN::MOV BTLINE,-(SP) ; COPY THE BOTTOM LINE BIT #B.DBLH,STATUS ; DOUBLE HEIGHT OUTPUT ? BEQ 10$ ; IF EQ, NO DEC (SP) ; YES, ADJUST BY ONE 10$: CMP LINE,(SP)+ ; ARE WE PAST THE BOTTOM ? BLE 20$ ; IF LE, NO MOV TPLINE,LINE ; YES, BACK TO THE TOP LINE 20$: RETURN .SBTTL MAKE THE ASCII LINE NUMBER ;+ ; ; MAKLIN - Makes the ASCII line number for VT100 escape sequence. ; ; Inputs: ; BUFPTR = pointer to the output buffer. ; R1 = the binary line number. ; ; Outputs: ; BUFPTR = updated buffer pointer. ; ; All registers are preserved. ; ;- MAKLIN::JSR R2,$SAVVR ; SAVE R0 - R2 MOVCHR ; MOVE IN THE MOVCHR <[> ; ESCAPE SEQUENCE CALL MAKNUM ; MAKE AN ASCII LINE # MOVCHR <;> ; PREPARE FOR COLUMN # RETURN .SBTTL MAKNUM - MAKE AN ASCII DECIMAL NUMBER ;+ ; ; MAKNUM - Make an ASCII decimal number. ; ; Inputs: ; BUFPTR = pointer to the output buffer. ; R1 = the binary number. ; ; Outputs: ; BUFPTR = updated buffer pointer. ; ; All registers are preserved. ; ;- MAKNUM::JSR R2,$SAVVR ; SAVE REGISTERS R0 - R2 MOV BUFPTR,R0 ; COPY THE BUFFER POINTER CLR R2 ; SET FOR ZERO SUPPRESSION CALL $CBDMG ; CONVERT TO DECIMAL ASCII MOV R0,BUFPTR ; SAVE THE NEW BUFFER ADDRESS RETURN .SBTTL MAKCOL - MAKE THE ASCII COLUMN NUMBER ;+ ; ; MAKCOL - Makes the ASCII column number for VT100 escape sequence. ; ; Inputs: ; BUFPTR = the output buffer address. ; COUNT = contains the message byte count. ; ; Outputs: ; BUFPTR = updated output buffer address. ; ; All registers are preserved. ; ;- MAKCOL::JSR R2,$SAVVR ; SAVE REGISTERS R0 - R2 BIT #B.COL,STATUS ; WAS COLUMN # SPECIFIED ? BEQ 10$ ; IF EQ, NO MOV COLUMN,R1 ; YES, COPY IT CALL ADJCOL ; ADJUST COLUMN BY WIDTH BR 50$ ; AND CONTINUE ... ; Check for left justification. 10$: BIT #B.LJUS,STATUS ; WANT TO LEFT JUSTIFY ? BEQ 30$ ; IF EQ, NO 20$: MOV LMARGN,R1 ; YES, USE LEFT MARGIN BR 50$ ; AND CONVERT IT ; See if message should be centered. 30$: MOV RMARGN,R1 ; COPY THE RIGHT MARGIN CALL ADJCOL ; ADJUST COLUMN BY WIDTH MOV COUNT,R2 ; COPY THE COUNT CMP R2,R1 ; IS LINE TOO WIDE ? BLE 40$ ; IF LE, NO MOV R1,R2 ; YES, TRUNCATE IT 40$: SUB R2,R1 ; CALCULATE COLUMN # ; Check for right justification. BIT #B.RJUS,STATUS ; RIGHT JUSTIFY MESSAGE ? BNE 45$ ; IF NE, YES (NO DIVIDE) ; Center the message. BIT #B.CENT,STATUS ; CENTER THE MESSAGE ? BEQ 20$ ; IF EQ, NO (LEFT MARGIN) ASR R1 ; DIVIDE BY 2 45$: INC R1 ; ADJUST COLUMN BY 1 50$: CALL MAKNUM ; MAKE THE ASCII LINE # MOVCHR ; END OF CURSER ADDRESSING ; If clear screen disabled, clear line where curser is. BIT #B.CLR,STATUS ; CLEAR SCREEN ENABLED ? BNE 60$ ; IF NE, YES ; CALL CLIN ; NO, CLEAR THE LINE 60$: RETURN .SBTTL WRTEND - WRITE THE ENDING MESSAGE ;+ ; ; WRTEND - Write the ending message to the terminal. ; ; This routine is used to position to the prompt line and clear the ; prompt line if input is from the terminal. If the input is from ; a command file, the prompt line is not written until we hit EOF. ; ; Inputs: ; None ; ; Outputs: ; BUFPTR = the updated buffer pointer. ; R0 and R1 are destroyed. ; ;- WRTEND::BIT #B.EXIT,STATUS ; ARE WE NOW EXITING ? BNE 5$ ; IF NE, YES (DO PROMPT) BIT #B.ITTY,STATUS ; INPUT COMING FROM TTY ? BEQ 30$ ; IF EQ, NO (SKIP ERASE) 5$: CALL MAKPRL ; MAKE THE PROMPT LINE CALL CLIN ; NO, ERASE THE LINE THEN ; On RSX-11M, back the cursor up one line since the MCR prompt ; is preceded by a line feed. 10$: TST VAXFLG ; ARE WE RUNNING ON VAX/VMS ? BNE 20$ ; IF NE, YES (CONTINUE ...) CALL CUP ; NO, BACK THE CURSOR UP 20$: CALL SETBUF ; SET BUFFER AND BYTE COUNT CALL WRTTTY ; WRITE IT TO THE TERMINAL 30$: RETURN .SBTTL MAKPRL - MAKE THE PROMPT LINE ;+ ; ; MAKPRL - Make the prompt line. ; ; This routine is used to position to the prompt line. ; ; Inputs: ; None ; ; Outputs: ; BUFPTR = the updated buffer pointer. ; R0 and R1 are destroyed. ; ;- MAKPRL::MOV #MSGBUF,BUFPTR ; SET THE BUFFER POINTER BIT #B.REL,STAT1 ; SPECIFY A RELATIVE LINE ? BEQ 10$ ; IF EQ, NO CALL MAKRPL ; YES, GO MAKE IT 10$: MOV PRLINE,R1 ; COPY THE PROMPT LINE # CALL MAKLIN ; MAKE THE ASCII LINE # MOVCHR <1> ; MOVE IN COLUMN ONE MOVCHR ; AND THE LAST PART RETURN .SBTTL CLOFIL - CLOSE THE OUTPUT FILE (IF OPEN) ;+ ; ; CLOFIL - Close the output file (if open). ; ; Inputs: ; None ; ; Outputs: ; Register R0 is destroyed. ; ;- CLOFIL::TST OUTFDB+F.BDB ; IS THERE A FILE OPEN ? BEQ 10$ ; IF EQ, NO (RETURN) MOV #OUTFDB,R0 ; ADDRESS OF OUTPUT FDB CALL .TRNCL ; YES, TRUNCATE AND CLOSE BIC #B.FILE,STATUS ; SHOW OUTPUT FILE CLOSED CLR FENTRY ; DISABLE OUTPUT TO FILE MOV #FILNAM,FILPTR ; RESET THE FILE NAME POINTER CLRB @FILPTR ; MAKE IT A NULL STRING 10$: RETURN ; Do cleanup and exit. EXIT:: BIS #B.EXIT,STATUS ; SHOW WE ARE EXITING CALL MAKPRL ; MAKE THE PROMPT LINE CALL WRTMSG ; WRITE IT EVERYWHERE CALL CLOFIL ; CLOSE THE FILE (IF OPEN) CALL WRTEND ; WRITE THE ENDING MESSAGE CLOSE$ #TOFDB ; CLOSE THE TERMINAL OUTPUT CLOSE$ #ERRFDB ; CLOSE THE ERROR MESSAGE BIT #B.CTRC,STATUS ; WAS CTRL/C TYPED TO ABORT ? BNE EXIWAR ; IF NE, YES (EXIT W/WARNING) BIT #B.ERRS,STATUS ; WAS AN ERROR SEEN SOMEWHERE ? BNE EXIERR ; YES, EXIT WITH ERROR BR EXISUC ; NOPE, EXIT WITH SUCCESS .SBTTL COMMON EXIT ROUTINES ; ; Common exit routines: ; EXISUC::MOV #EX$SUC,R0 ; SET SUCCESS STATUS BR EXST ; AND EXIT WITH STATUS EXIWAR::MOV #EX$WAR,R0 ; SET WARNING STATUS BR EXST ; AND EXIT WITH STATUS EXIERR::MOV #EX$ERR,R0 ; SET ERROR STATUS BR EXST ; AND EXIT WITH STATUS EXISEV::MOV #EX$SEV,R0 ; SET SEVERE STATUS ; Exit with status in R0. EXST:: EXST$S R0 ; EXIT WITH STATUS EXIT$S ; IN CASE EXST$S FAILS .END VTM