.TITLE VTMBOX - WRITE A BOX .IDENT /01.3/ .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: VTMBOX.MAC ; Author: Robin Miller ; Date: June 28, 1982 ; ; Description: ; ; This module writes a box on the VT100 using special graphics. ; ; ; Modification History: ; ;- .ENABL AMA .NLIST BEX ; Local equates: BS = 8. ; ASCII FOR BACKSPACE LF = 10. ; ASCII FOR LINE FEED ESC = 27. ; ASCII FOR ESCAPE LRCRNR = 152 ; LOWER-RIGHT CORNER (j) URCRNR = 153 ; UPPER-RIGHT CORNER (k) ULCRNR = 154 ; UPPER-LEFT CORNER (l) LLCRNR = 155 ; LOWER-LEFT CORNER (m) HORLIN = 161 ; HORIZONTAL LINE (q) VERLIN = 170 ; VERTICAL LINE (x) ; Local storage: TLINB:: .WORD 1 ; TOP LINE BLINB:: .WORD 23. ; BOTTOM LINE LCOLB:: .WORD 1 ; LEFT COLUMN RCOLB:: .WORD 132. ; RIGHT COLUMN BSFLG: .WORD 0 ; BACKSPACE FLAG -1/0 = TRUE/FALSE WDFLG: .WORD 0 ; DO WIDTH FLAG -1/0 = TRUE/FLASE ; Macro to move a constant or a character to buffer pointer. .MACRO MOVCHR CHAR .NCHR $$$,^/CHAR/ .IF EQ $$$-1 MOVB #''CHAR,@BUFPTR .IFF MOVB #CHAR,@BUFPTR .ENDC INC BUFPTR .ENDM ;+ ; ; BOX - Action routines for TPARS to draw a box. ; ;- BOXT:: MOV .PNUMB,R0 ; COPY THE TOP LINE CMP R0,#24. ; LINE NUMBER IN RANGE ? BGE FAIL ; IF GE, NO (ERROR) MOV R0,TLINB ; SAVE THE TOP LINE INC R0 ; ADJUST THE LINE # MOV R0,TPLINE ; AND SAVE AS TOP LINE RETURN BOXB:: MOV .PNUMB,R0 ; COPY THE BOTTOM LINE CMP R0,#24. ; LINE NUMBER IN RANGE ? BGT FAIL ; IF GT, NO (ERROR) CMP R0,TLINB ; GREATER THAN TOP LINE ? BLE FAIL ; IF LE, NO (ERROR) MOV R0,BLINB ; SAVE THE BOTTOM LINE DEC R0 ; ADJUST THE BOTTOM LINE MOV R0,BTLINE ; AND SAVE AS BOTTOM LINE RETURN BOXL:: MOV .PNUMB,R0 ; COPY THE COLUMN NUMBER CMP R0,RMARGN ; IS COLUMN WITHIN RANGE ? BGE FAIL ; IF GE, NO (TOO BIG) MOV R0,LCOLB ; SAVE THE COLUMN NUMBER RETURN BOXR:: MOV .PNUMB,R0 ; COPY THE RIGHT COLUMN CMP R0,LCOLB ; RIGHT GREATER THAN LEFT ? BLE FAIL ; IF LE, NO (ERROR) CMP R0,RMARGN ; IS COLUMN WITHIN RANGE ? BGT FAIL ; IF GT, NO (TOO BIG) MOV R0,RCOLB ; SAVE THE RIGHT COLUMN BR BOX ; NOW MAKE THE BOX ; Return failure to TPARS. FAIL: ADD #2,(SP) ; RETURN FAILURE RETURN ; Do the actual boxing. BOX:: MOV BUFPTR,-(SP) ; SAVE CURRENT BUFFER POINTER MOV #MSGBUF,BUFPTR ; SETUP THE OUTPUT BUFFER BIT #B.CLR,STATUS ; NEED TO CLEAR THE SCREEN ? BEQ 10$ ; IF EQ, NO CALL CLRSCR ; YES, DO IT 10$: CALL SGRAPH ; TURN ON SPECIAL GRAPHICS ; Now do the left and bottom lines. MOV #-1,WDFLG ; CHANGE THE WIDTH CALL 100$ ; POSITION THE CURSER MOV #-1,BSFLG ; ALWAYS NEED A BACKSPACE CALL DOVERT ; DO THE VERTICAL LINE CALL CHANGE ; CHANGE THE WIDTH CALL CHKFIL ; CEHCK FOR OUTPUT TO FILE MOVCHR ; MOVE IN LOWER-LEFT CORNER CALL DOHORI ; DO THE HORIZONTAL LINE MOVCHR ; NOW THE LOWER-RIGHT CORNER CALL CHKFIL ; CEHCK FOR OUTPUT TO FILE ; Do the top line. CLR WDFLG ; DON'T CHANGE THE WIDTH CALL 100$ ; POSITION THE CURSER CALL DOHORI ; DO THE HORIZONTAL LINE CALL CHKFIL ; CEHCK FOR OUTPUT TO FILE ; Do the right line. MOV #-1,BSFLG ; PRESUME BS NEEDED MOV RMARGN,R1 ; COPY THE RIGHT MARGIN MOV RCOLB,R2 ; COPY THE RIGHT COLUMN CMP R2,R1 ; DO WE NEED THE BS ? BLT 20$ ; IF LT, YES CLR BSFLG ; NO, WE'RE AT RIGHT MARGIN 20$: MOVCHR ; NOW THE UPPER-RIGHT CORNER CALL DOVERT ; DO THE VERTICAL LINE ; Finished... write the box... CALL USSET ; USASCII CHARACTER SET CALL WRTMSG ; WRITE THE MESSAGE. MOV (SP)+,BUFPTR ; RESTORE ORIGINAL POINTER RETURN ; Start in the upper-left corner. 100$: MOV TLINB,R1 ; COPY THE TOP LINE CALL MAKLIN ; MAKE THE LINE NUMBER MOV LCOLB,R1 ; COPY THE LEFT COLUMN CALL ADJCOL ; ADJUST FOR WIDTH CALL MAKNUM ; MAKE THE COLUMN NUMBER MOVCHR ; FINISH ESCAPE SEQUENCE CALL CHANGE ; CHANGE THE LINE WIDTH MOVCHR ; MOVE IN UPPER-LEFT CORNER RETURN .SBTTL ADJCOL - ADJUST THE COLUMN NUMBER ;+ ; ; ADJCOL - Adjust the column number based on the message width. ; ; Inputs: ; R1 = the column number. ; ; Outputs: ; R1 = the adjusted column number. ; ;- ADJCOL::BIT #B.DBLH!B.DBLW,STATUS ; DOUBLE WIDTH MESSAGE ? BEQ 20$ ; IF EQ, NO (LEAVE ALONE) ; BIT #1,R1 ; IS THIS AN ODD NUMBER ? ; BEQ 10$ ; IF EQ, NO ; INC R1 ; YES, MAKE IT EVEN 10$: ASR R1 ; DIVIDE COLUMN BY TWO BGT 20$ ; IF GT, GOT COLUMN INC R1 ; MUST HAVE BEEN COLUMN 1 20$: RETURN .SBTTL CHANGE - CHANGE THE WIDTH ON THE SCREEN ;+ ; ; CHANGE - Change the width on the screen. ; ; This routine will move the double height, double width, or single ; width message if the WDFLG is set true (-1). ; ; Inputs: ; BUFPTR = the output buffer pointer. ; WDFLG = -1 to change the width. ; ; Outputs: ; BUFPTR = the updated buffer pointer. ; ;- CHANGE: TST WDFLG ; CHANGE THE WIDTH ? BEQ 100$ ; IF EQ, NO ; Double height message. BIT #B.DBLH,STATUS ; DOUBLE HEIGHT ? BEQ 10$ ; IF EQ, NO CALL DHTOP ; YES, DO TOP HALF BR 100$ ; AND RETURN ... ; Double width message. 10$: BIT #B.DBLW,STATUS ; DOUBLE WIDTH ? BEQ 20$ ; IF EQ, NO CALL DWIDTH ; YES, MOVE IT BR 100$ ; AND RETURN ... ; Single width message. 20$: CALL SWIDTH ; PRESUME SINGLE WIDTH 100$: RETURN .SBTTL DOHORI - DO THE HORIZONTAL LINE ;+ ; ; DOHORI - Do the horizontal line. ; ; Inputs: ; BUFPTR = the output buffer pointer. ; LCOLB = left column number ; RCOLB = right column number. ; ; Outputs: ; BUFPTR = the updated buffer pointer. ; R1 is destroyed. ; ;- DOHORI: MOV RCOLB,R1 ; COPY THE RIGHT COLUMN SUB LCOLB,R1 ; SUBTRACT OUT THE LEFT CALL ADJCOL ; ADJUST FOR THE WIDTH DEC R1 ; ADJUST FOR CORNERS BLE 20$ ; IF LE, DONE 10$: MOVCHR ; MOVE IN HORIZONTAL LINE SOB R1,10$ ; LOOP UNTIL DONE 20$: RETURN .SBTTL DOVERT - DO THE VERTICAL LINE ;+ ; ; DOVERT - Do the vertical line. ; ; Inputs: ; BUFPTR = the output buffer pointer. ; TLINB = top line number. ; BLINB = bottom line number. ; BSFLG = Insert backspace flag -1/0 = true/false. ; ; Outputs: ; BUFPTR = the updated buffer pointer. ; R1 is destroyed. ; ;- DOVERT: ; Calculate the number of lines. 5$: MOV BLINB,R1 ; COPY THE BOTTOM LINE SUB TLINB,R1 ; SUBTARCT THE TOP LINE DEC R1 ; ADJUST FOR CORNERS 10$: TST BSFLG ; OUTPUT THE BS SEQUENCE ? BEQ 15$ ; IF EQ, NO (JUST LF) MOVCHR ; USE BACKSPACE/LINEFEED 15$: CALL CDOWN ; MOVCHR ; TO GO DOWN TO NEXT LINE DEC R1 ; DECREMENT COUNT BLT 20$ ; IF LT, DONE CALL CHANGE ; CHANGE THE WIDTH MOVCHR ; MOVE IN VERTICAL LINE BR 10$ ; AND LOOP 20$: RETURN .SBTTL CHKFIL - CHECK FOR OUTPUT TO A FILE ;+ ; ; CHKFIL - Check for output to a file. ; ; If outputting to a file, this routine calls WRTMSG so that the record ; size doesn't get too large. If the record size exceeds the terminal ; width, the terminal driver (both VAX and RSX-11M) will do an automatic ; line wraparound, unless /NOWRAP is specified. Otherwise, if outputting ; to a terminal, the entire message is buffered and output all at once ; to reduce system overhead. ; ; The above statement is true, unfortunatly doing a QIO with a very large ; byte count (over 256 bytes) causes the VT100 to screw up when writing ; a single width box. For this reason, if the byte count exceeds 100 ; bytes, we will also write to resolve this problem. ; ;- CHKFIL::JSR R2,$SAVVR ; SAVE R0 - R2 CALL SETBUF ; GET BYTE COUNT -> R2 CMP R2,#100. ; IS BYTE COUNT TOO LARGE ? BGT 10$ ; IF GT, YES (WRITE IT) BIT #B.FILE,STATUS ; OUTPUTTING TO A FILE ? BEQ 20$ ; IF EQ, NO (CONTINUE) 10$: CALL SAVEC ; MOVE IN SAVE CURSOR CALL WRTMSG ; YES, WRITE THE BUFFER CALL RESTC ; NEXT RECORD DOES RESTORE 20$: RETURN .END