# FILE= VTLIB.RAT INCLUDE/NL DEFIN INCLUDE VTDEFIN.RAT # DEFINE (DIRECT=BIGY) DEFINE (DOWN=BIGB) DEFINE (LEFT=BIGD) DEFINE (RIGHT=BIGC) DEFINE (UP=BIGA) # #This package of subroutines provides easy control of the vidio functions # of a VT52 or VT100. #It also is a good example of how RATFOR provides elegant and readable # solutions to programming problems. #The main program must include VTDEFIN.RAT to define the symbolic constants # for the control functions, and CVTLIB.RAT to define the common block, # which passes the logical unit number to the subroutine that does all the # output, VTSEND. Note that in an overlaid program, VTSEND must be in the # root. The mainline must also specify whether the terminal is a VT52 or VT100 # unless the first call is VTSET(ANSIMODE) OR VTSET (NONANSI), which sets # VTYPE as well as sending an escape sequence to set the terminal as specified. #Most functions can be done just by calling VTSET with the # symbolic for the desired function as a parameter, eg CALL VTSET(HOME) # moves the cursor to the home position and CALL VTSET(ALTKP) puts the # terminal in alternate keypad mode. #Routines named VT1xxx do functions available only on the VT100, if VTYPE is # not set to VT100, these routines do nothing. # VTSET handles all mode control for both VT52 and VT100. VTFUNC handles only # VT52 functions but is included for compatibility with older versions. # Other routines do the same functions for both terminals. #Study the VT100 manual carefully, many of the functions are not at all # straightforward or obvious, but VTTEST.RAT should help. #To minimize the amount of IO, VTSEND buffers all control codes until # its buffer is full or until it is told to flush the buffer. It does # QIO write-alls so the terminal handler does not interfere by inserting # and by converting tabs to blanks. # # #$ VTCLRL - ERASE (CLEAR) ALL OR PART OF LINE ON VT52 OR VT100. # VT52 DOES ONLY "ERASE TO END" FUNCTION. # VT100 ALSO DOES "TOP TO CURSOR" AND "ALL". # SUBROUTINE VTCLRL (MODE) # INTEGER MODE # INCLUDE CVTLIB # CALL VTSEND (ESCAPE) IF (VTYPE == VT100) { CALL VTSEND (LBRACK) CALL VTSEND (MODE) } #ELSE, CURSOR TO END CALL VTSEND (BIGK) CALL VTSEND (FLUSH) # RETURN END # #$ VTCLRS - ERASE (CLEAR) ALL OR PART OF VT52 OR VT100 SCREEN. # VT52 DOES ONLY "ERASE TO END" FUNCTION. VT100 ALSO DOES "TOP TO CURSOR" AND "ALL". # SUBROUTINE VTCLRS (MODE) # INTEGER MODE # INCLUDE CVTLIB # CALL VTSEND (ESCAPE) IF (VTYPE == VT100) { CALL VTSEND (LBRACK) CALL VTSEND (MODE) } #ELSE, CURSOR TO END CALL VTSEND (BIGJ) CALL VTSEND (FLUSH) # RETURN END # # #$ VTCURS - SUBROUTINE TO DO RELATIVE CURSOR MOVEMENTS # PARAMETERS ARE RELATIVE LINES OR COLS TO MOVE. # NEGATIVE FOR UP OR LEFT; POSITIVE FOR DOWN OR RIGHT # SUBROUTINE VTCURS (LINES, COLS) # INTEGER LINES, COLS, I, J, SITOC CHARACTER BUF(4) INCLUDE CVTLIB # IF (VTYPE == VT52) { IF (LINES != 0) DO I=1,IABS(LINES) { #VT52 CALL VTSEND(ESCAPE) IF (LINES > 0) CALL VTSEND (DOWN) ELSE CALL VTSEND (UP) } IF (COLS != 0) DO I=1,IABS (COLS) { CALL VTSEND (ESCAPE) IF (COLS > 0) CALL VTSEND (RIGHT) ELSE CALL VTSEND (LEFT) } } # ELSE IF (VTYPE == VT100) { IF (LINES != 0) { CALL VTSEND (ESCAPE) #VT100 CALL VTSEND (LBRACK) I=SITOC (IABS(LINES), BUF, 3) FOR (J=1; J <= I; INCREMENT(J)) CALL VTSEND (BUF(J)) IF (LINES > 0) CALL VTSEND (DOWN) #MOVE DOWN ELSE CALL VTSEND (UP) #MOVE UP } IF (COLS != 0) { CALL VTSEND (ESCAPE) CALL VTSEND (LBRACK) I=SITOC (IABS(COLS), BUF, 3) FOR (J=1; J <= I; INCREMENT(J)) CALL VTSEND (BUF(J)) IF (COLS > 0) CALL VTSEND (RIGHT) #MOVE RIGHT ELSE CALL VTSEND (LEFT) #MOVE LEFT } } CALL VTSEND (FLUSH) #FORCE IMMEDIATE OUTPUT # RETURN END # #$ VTDCA - SUBROUTINE TO DO DIRECT CURSOR ADDRESSING ON VT52 OR VT100. # PARAMETERS ARE THE ABSOLUTE POSITION ON THE SCREEN WHERE YOU WANT # CURSOR. THIS RELIES ON THE CRT TO HANDLE OFF-SCREEN ORDERS. # SUBROUTINE VTDCA (LINE, COL) # INTEGER LINE, COL, I, J, SITOC CHARACTER BUF(4) # INCLUDE CVTLIB # CALL VTSEND (ESCAPE) IF (VTYPE == VT52) { CALL VTSEND (DIRECT) #VT52 CALL VTSEND (31+LINE) CALL VTSEND (31+COL) } ELSE IF (VTYPE == VT100) { CALL VTSEND (LBRACK) I=SITOC (LINE, BUF, 3) #VT100 FOR (J=1; J <= I; INCREMENT(J)) CALL VTSEND (BUF(J)) CALL VTSEND (SEMICOL) I=SITOC (COL, BUF, 3) FOR (J=1; J <= I; INCREMENT(J)) CALL VTSEND (BUF(J)) CALL VTSEND (BIGH) } CALL VTSEND (FLUSH) #FORCE IMMEDIATE OUTPUT RETURN END # #$ VTFUNC - SUBROUTINE TO EXECUTE ESCAPE SEQUENCE FUNCTIONS ON VT52 ## INCLUDED FOR COMPATIBILITY WITH OLDER PROGRAMS ONLY. ## NEW PROGRAMS SHOULD USE 'VTSET' INSTEAD. # # WORKS FOR THE FOLLOWING VT52 FUNCTIONS: # HOLD, NOHOLD HOLD SCREEN MODE # ALTKP, NOALTKP ALTERNATE KEYPAD MODE # ERASEL, ERASES ERASE FROM HERE TO END OF LINE, SCREEN # HOME MOVE CURSOR TO UPPER LEFTHAND CORNOR # GRAPH, NOGRAPH GRAPHICS MODE # UP, DOWN MOVE CURSOR UP OR DOWN 1 LINE # RIGHT, LEFT MOVE CURSOR RIGHT OR LEFT 1 COLUMN #### NOTE: THESE VALUES ARE NOT DEFINED IN THE CURRENT VTDEF.RAT !!!! # SUBROUTINE VTFUNC (FUNC) # CHARACTER FUNC #THE VT52 CONTROL CODE DESIRED # CALL VTSEND (ESCAPE) CALL VTSEND (FUNC) CALL VTSEND (FLUSH) #FORCE IMMEDIATE OUTPUT # RETURN END # #$ VTLABL - SUBROUTINE TO WRITE VERTICALLY ON THE SCREEN. # CURSOR MUST FIRST BE MOVED TO STARTING POSITION ON SCREEN. # 'OUTBUF' MUST BE A STRING TERMINATED WITH AN 'EOS'. # SUBROUTINE VTLABL (OUTBUF) # CHARACTER OUTBUF(1) # FOR (I=1; OUTBUF(I) != EOS; INCREMENT(I)) { CALL VTSEND (OUTBUF(I)) CALL VTCURS (1,-1) #BACKUP 1 COL AND GO DOWN 1 LINE } RETURN END # #$ VTSEND - SUBROUTINE TO BUFFER AND SEND CHARACTERS TO THE TERMINAL. # NOTE THAT BOTH CVTLIB AND THIS ROUTINE (BECAUSE OF 'LAST') MUST # BE IN ROOT. IF DESIRED, THE QIO CALL CAN BE REPLACED WITH A WRITE. # SUBROUTINE VTSEND (CHAR) # INCLUDE CVTLIB # CHARACTER CHAR, BUFR(30) INTEGER IB(6) DATA LAST /0/ DATA IB /6*0/ # IF (CHAR != FLUSH) { INCREMENT (LAST) BUFR(LAST)=CHAR } IF (LAST >= 30 \ CHAR == FLUSH) { ## WRITE (VTLUN,1) (BUFR(N),N=1,LAST) ; 1 FORMAT ($,"+",30A1) CALL GETADR (IB(1), BUFR) IB(2)=LAST # NUMBER OF CHARS TO WRITE CALL QIO (264, VTLUN, 1, , ,IB,IDS) #IO.WAL (WRITE ALL) CALL WAITFR (1) LAST=0 #RESET COUNTER } # RETURN END # #$ VTSET - SUBROUTINE TO SET AND RESET TERMINAL MODES. # SUBROUTINE VTSET (MODE) # INTEGER MODE # INCLUDE CVTLIB # CALL VTSEND (ESCAPE) IF (MODE == ALTKP \ MODE == NOALTKP) #SAME FOR VT52 & VT100 CALL VTSEND (MODE) ELSE IF (MODE == ANSIMODE) { CALL VTSEND (LESS) VTYPE = VT100 #NOW IN VT100/ANSI MODE CALL VTSEND (ESCAPE) CALL VTSEND (RPAREN) #ALSO SET UP SPECIAL GRAPHICS CHAR SET CALL VTSEND (DIG0) #AS THE ALT. SET SELECTED BY A CTRL/N } ELSE IF (MODE == NONANSI) { CALL VTSEND (LBRACK) CALL VTSEND (QMARK) CALL VTSEND (DIG2) CALL VTSEND (LETL) VTYPE = VT52 #NOW IN VT52 MODE } ELSE IF (VTYPE == VT52) { IF (MODE == SCROLLUP) CALL VTSEND (NEWLINE) #SPURIOUS ESC PUT OUT ABOVE IS IGNORED ELSE IF (MODE == SCROLLDWN) CALL VTSEND (BIGI) #DIFFERENT THEN VT100 ELSE CALL VTSEND (MODE) } ELSE IF (VTYPE == VT100) { IF (MODE == HOME) #SPECIAL CASE IN VT100 MODE) CALL VTDCA (1,1) ELSE IF (MODE == GRAPH) CALL VTSEND (14) #DIFFERENT CODE THEN VT52, CTRL/N ELSE IF (MODE == NOGRAPH) CALL VTSEND (15) #DIFFERENT CODE THEN VT52,CTRL/O ELSE IF (MODE == SAVEC) CALL VTSEND (DIG7) ELSE IF (MODE == RESTOREC) CALL VTSEND (DIG8) ELSE IF (MODE == RESETVT) CALL VTSEND (LETC) #RESET TERMINAL FUNCTION ELSE IF (MODE == SCROLLUP) CALL VTSEND (BIGD) ELSE IF (MODE == SCROLLDWN) CALL VTSEND (BIGM) #REVERSE INDEX ELSE { CALL VTSEND (LBRACK) CALL VTSEND (QMARK) CALL VTSEND (IABS(MODE)) IF (MODE > 0) CALL VTSEND (LETH) #SYMBOLS FOR 'SET' MODES ARE >0 ELSE CALL VTSEND (LETL) #SYMBOLS FOR 'RESET' MODES ARE <0 } } # CALL VTSEND (FLUSH) RETURN END # #$ VT1ATT - SET VT100 CHARACTER VIDIO ATTRIBUTES # (WORKS CORRECTLY ONLY IF ADVANCED VIDIO OPTION IS INSTALLED) # SUBROUTINE VT1ATT (MODE) # INTEGER MODE # INCLUDE CVTLIB # IF (VTYPE == VT100) { CALL VTSEND (ESCAPE) CALL VTSEND (LBRACK) CALL VTSEND (MODE) CALL VTSEND (LETM) CALL VTSEND (FLUSH) } RETURN END # #$ VT1LED - CONTROL VT100 KEYBOARD LIGHTS. # SUBROUTINE VT1LED (LIGHT) # INTEGER LIGHT # INCLUDE CVTLIB # IF (VTYPE == VT100 ) { CALL VTSEND (ESCAPE) CALL VTSEND (LBRACK) CALL VTSEND (LIGHT) #CHARACTER VALUE CALL VTSEND (LETQ) CALL VTSEND (FLUSH) } RETURN END # #$ VT1SIZ - CONTROL THE HEIGTH/WIDTH OF CURRENT LINE ON VT100. # SUBROUTINE VT1SIZ (MODE) # INTEGER MODE # INCLUDE CVTLIB # IF (VTYPE == VT100) { CALL VTSEND (ESCAPE) CALL VTSEND (SHARP) CALL VTSEND (MODE) CALL VTSEND (FLUSH) } RETURN END # #$ VT1SR - SPECIFY SIZE OF VT100 SCROLLING REGION. # SUBROUTINE VT1SR (TOP, BOT) # INTEGER TOP, BOT, SITOC, I, J CHARACTER BUF(4) # INCLUDE CVTLIB # IF (VTYPE == VT100 & BOT > TOP) { CALL VTSEND (ESCAPE) CALL VTSEND (LBRACK) I=SITOC (TOP, BUF, 3) #CONVERT TO CHAR STRING FOR (J=1; J <= I; INCREMENT(J)) CALL VTSEND (BUF(J)) CALL VTSEND (SEMICOL) I=SITOC (BOT, BUF, 3) FOR (J=1; J <= I; INCREMENT(J)) CALL VTSEND (BUF(J)) CALL VTSEND (LETR) CALL VTSEND (FLUSH) } RETURN END # #$ VT1TAB - SET/CLEAR TAB STOPS ON VT100. # SUBROUTINE VT1TAB (MODE) # INTEGER MODE # INCLUDE CVTLIB # IF (VTYPE == VT100) { CALL VTSEND (ESCAPE) IF (MODE == SETTAB) CALL VTSEND (MODE) #SET TAB AT PRESENT POSITION ELSE { CALL VTSEND (LBRACK) CALL VTSEND (MODE) CALL VTSEND (LETG) } CALL VTSEND (FLUSH) } RETURN END