.Title VT100 Screen Subroutines .Enabl LC .MCALL .TTYOUT,.TTYIN .sbttl . Program Specs ; ; John Freymann, Jr. Test & Evaluation Services ; 32 Carver Hall, Iowa State University, Ames, Iowa 50011 ; ; VT100 ; MACRO-11 Version ; ; This is a set of routines that are used for doing ; cursor manipulation on the VT100 type terminal ; ; These routines are written for ANSI Mode Cursor Control ; ; NOTE: If the routine begins with PCxxxx the routine is ; a private code routine this means it may not run ; on terminals other than the DEC VT100 or terminals ; that emulate the DEC VT100 ; ; This software has been sponsored by Iowa State University ; Ames,Iowa. Neither the University nor any of its affiliates ; makes any warranty expressed or implied for the correctness ; of this software. ; ; These routines were written using the ANSI standard codes as ; stated in the Datamedia DT80/1 Programmers Guide ; ; Updates: ; Original version 5-Feb-82 JPF ; PCSTBM Calling instructions corrected 5-Feb-82 JPF ; READVT added 5-Feb-82 JPF ; GRPHVT added 11-Feb-82 JPF ; PSECT changed 15-Feb-82 JPF ; VT100 Labeled 15-Feb-82 JPF ; Cursor positioning now handle invalid args 15-Feb-82 JPF ; PCSTBM handles invalid args 15-Feb-82 JPF (see calling ins) ; Auto Wrap Mode added 6-May-82 PJL ; .page .sbttl . Subroutine calling instructions ; ; These subroutines have been written to be called using ; the standard DEC FORTRAN parameter passing sequence. ; if using Pascal use the FORTRAN keyword. ; ; The no parameter routines can be called by ; ; CALL routine ; ; where routine is one of the following routines: ; ; SGRP SGRBO SGRU SGRBL SGRR ; SCSSG SCSAS SCSG1 SCSG0 ; PCDHLU PCDHLL PCDSWL PCDWL ; CUH IND NEL RI PCSC PCRC ; CLREOL CLRBOL CLRLN CLREOS CLRBOS CLRSCR CLRSCH ; PCCOL8 PCCOL1 PCKPAM PCKPNM PCOMA PCOMR ; DSRCP RIS HTS TBC TBCA ; PCLL0 PCLL1 PCLL2 PCLL3 PCLL4 ; PCAWMS PCAWMR ; ; The following are the routines that have parameters. ; All parameters are integer ; ; CALL CUU(irow) where irow is input number of rows to ; CALL CUD(irow) move the cursor ; ; CALL CUF(icol) where icol is input number of columns to ; CALL CUB(icol) move the cursor ; ; CALL CUP(xrow,ycol) where xrow is the input row number (1-24) ; and ycol is the input column (1-132) ; ; CALL CPR(row,col) where row is the output row number of ; the current cursor position and col is ; the output column of the current cursor ; positions ; ; CALL PCSTBM(top,bottom) where top is the top row of the scroll ; region and bottom is the bottom row of ; the scroll region ; ; CALL READVT(flag,charc) where flag is a word set to 1 if this ; is an escape sequence or a 0 if only ; a character is read. See routine ; heading for more details. ; ; CALL GRPHVT(ascii) where ascii is an ascii character ; equivalent to a VT100 graphics ; character. If there isn't a grphic ; equivalent then the actual character ; is sent to the terminal. ; ; NOTE: If a non-positive arg is passed to cuu,cud,cub,cuf or cup ; the argument is assumed to be one. For PCSTBM the args are ; set to top = 1 bottom = 24. ; ; for more information consult the ANSI Standard or your terminals ; programming guide. ; .page .sbttl . Constant Definitions .Psect VT100 VT100:: esc=33 ; escape character semcol=73 ; the semicolon pnd=43 ; # symbol so=16 ; shift out si=17 ; shift in eql=75 ; = symbol gtr=76 ; > symbol ; .sbttl CSF Set up the control sequence function macro .macro csf .ttyout #esc .ttyout #'[ .endm ; .sbttl Conversion routines for ASCII to Integer and Integer to ASCII ; .sbttl ACDINT Convert ASCII Coded Decimal to Integer ACDINT:: clr R1 ; zero out the return register Get1: movb (r2)+,R0 ; move character to conversion register beq adcdon ; if this is the zero byte then done sub #'0,R0 ; subtract the character value "0" mul #10.,R1 ; multiply previous value to add digit add r0,r1 ; add new digit br Get1 ; convert next character Adcdon: rts pc ; return to main the integer is in R1 ; .sbttl INTADC Convert Integer to ASCII Coded Decimal INTADC:: mov #dec,r4 ; load the decimal table address clr r2 ; no significant digits yet getdig: clr r0 ; zero the quotient div (r4)+,r0 ; get the quotient and the remainder tst r2 ; any sig figs yet ? bne send ; yes then send this tst r0 ; no then is this significant? beq getdig ; no then get next digit inc r2 ; we have sig figs! send: add #'0,r0 ; convert to ascii decimal character .ttyout ; send the character tst (r4) ; is this the last digit? bne getdig ; no then get next digit rts pc ; return to main ; ; this is the power of 10 table dec: .word 10000.,1000.,100.,10.,1,0 .page .sbttl . These are the character rendition routines ; .sbttl SGRP Select graphics rendition Primary (normal) SGRP:: csf .ttyout #'0 .ttyout #'m rts pc ; .sbttl SGRBO Select grarphics rendition Bold SGRBO:: csf .ttyout #'1 .ttyout #'m rts pc ; .sbttl SGRU Select graphics rendition Underline SGRU:: csf .ttyout #'4 .ttyout #'m rts pc ; .sbttl SGRBL Select graphics rendition Blink SGRBL:: csf .ttyout #'5 .ttyout #'m rts pc ; .sbttl SGRR Select graphics rendition Reverse Video SGRR:: csf .ttyout #'7 .ttyout #'m rts pc ; .page .sbttl . These are the special character set routines ; .sbttl SCSSG Select character set Special Graphics G1 SCSSG:: .ttyout #esc .ttyout #') .ttyout #'0 rts pc ; .sbttl SCSAS Select character set ASCII G1 SCSAS:: .ttyout #esc .ttyout #') .ttyout #'B rts pc ; .sbttl SCSG1 Select Character set G1 SCSG1:: .ttyout #so rts pc ; .sbttl SCSG0 Select character set G0 SCSG0:: .ttyout #si rts pc ; .sbttl GRPHVT Write special graphics characters GRPHVT:: jsr pc,SCSSG ; set up g1 as special characters jsr pc,SCSG1 ; enable G1 character set .ttyout @2(r5) ; get and send the ascii equivalent jsr pc,SCSG0 ; reset to ascii character set rts pc ; return to pgm ; .page .sbttl . Special Display Functions ; .sbttl PCDHLU Double height-width display upper portion PCDHLU:: .ttyout #esc .ttyout #pnd .ttyout #'3 rts pc ; .sbttl PCDHLL Double height-width display lower portion PCDHLL:: .ttyout #esc .ttyout #pnd .ttyout #'4 rts pc ; .sbttl PCDSWL Single width single height line PCDSWL:: .ttyout #esc .ttyout #pnd .ttyout #'5 rts pc ; .sbttl PCDWL Double width single height line PCDWL:: .ttyout #esc .ttyout #pnd .ttyout #'6 rts pc ; .page .sbttl . These are the cursor position routines ; .sbttl CUU Cursor Up CUU:: csf mov @2(r5),r1 ; get the number of rows that you want ble 1$ ; if zero or less go up 1 row jsr pc,INTADC ; to go up and send it 1$: .ttyout #'A ; send the delimiter rts pc ; .sbttl CUD Cursor Down CUD:: csf mov @2(r5),r1 ; get the number of rows that you want ble 1$ ; if zero or less go down 1 row jsr pc,INTADC ; to go down and send it 1$: .ttyout #'B ; send the delimiter rts pc ; .sbttl CUF Cursor Forward (right) CUF:: csf mov @2(r5),r1 ; get the number of columns that you want to ble 1$ ; if zero or less go forward 1 col jsr pc,INTADC ; go right and send it 1$: .ttyout #'C ; delimit the command rts pc ; .sbttl CUB Cursor Backward (left) CUB:: csf mov @2(r5),r1 ; get the number of columns that you want to ble 1$ ; if zero or less go back 1 col jsr pc,INTADC ; go to the left and send it 1$: .ttyout #'D ; delimit the command rts pc ; .sbttl CUP Cursor position to X,Y CUP:: csf mov @2(r5),r1 ; get the cursor line number ble 1$ ; if not valid goto row 1 jsr pc,INTADC ; send the cursor position 1$: .ttyout #semcol ; send the parameter delimiter mov @4(r5),r1 ; get the cursor column number ble 2$ ; if not valid goto col 1 jsr pc,INTADC ; send the cursor column position 2$: .ttyout #'H ; send command delimiter rts pc ; .sbttl CUH Cursor Home CUH:: csf .ttyout #'H rts pc ; .sbttl IND Index the cursor (down one row) IND:: .ttyout #esc .ttyout #'D rts pc ; .sbttl NEL New line (cr lf the cursor) NEL:: .ttyout #esc .ttyout #'E rts pc ; .sbttl RI Reverse Index the cursor (up one row) RI:: .ttyout #esc .ttyout #'M rts pc ; .sbttl PCSC Save Cursor Atributes PCSC:: .ttyout #esc .ttyout #'7 rts pc ; .sbttl PCRC Restore the saved cursor attributes PCRC:: .ttyout #esc .ttyout #'8 rts pc ; .page .sbttl . These are the screen erase routines ; .sbttl CLREOL Clear from cursor to eol CLREOL:: csf .ttyout #'K rts pc ; .sbttl CLRBOL Clear from beginning of line to cursor CLRBOL:: csf .ttyout #'1 .ttyout #'K rts pc ; .sbttl CLRLN Clear the entire line CLRLN:: csf .ttyout #'2 .ttyout #'K rts pc ; .sbttl CLREOS Clear from cursor to EOS CLREOS:: csf .ttyout #'J rts pc ; .sbttl CLRBOS Clear from beginning of screen to cursor CLRBOS:: csf .ttyout #'1 .ttyout #'J rts pc ; .sbttl CLRSCR Clear entire screen CLRSCR:: csf .ttyout #'2 .ttyout #'J rts pc ; .sbttl CLRSCH Clear Entire Screen and Home the cursor CLRSCH:: csf call CLRSCR call CUH rts pc ; .page .sbttl . These are the terminal mode setting routines ; .sbttl PCCOL8 Set the terminal to column 80 mode PCCOL8:: csf .ttyout #'? .ttyout #'3 .ttyout #'l rts pc ; .sbttl PCCOL1 Set the terminal to 132 columns PCCOL1:: csf .ttyout #'? .ttyout #'3 .ttyout #'h rts pc ; .sbttl PCKPAM Set terminal keypad to application mode PCKPAM:: .ttyout #esc .ttyout #eql rts pc ; .sbttl PCKPNM Set terminal keypad to numeric mode PCKPNM:: .ttyout #esc .ttyout #gtr rts pc ; .sbttl PCOMA Set terminal to absolute origin mode PCOMA:: csf .ttyout #'? .ttyout #'6 .ttyout #'l rts pc ; .sbttl PCOMR Set terminal to relative origin mode PCOMR:: csf .ttyout #'? .ttyout #'6 .ttyout #'h rts pc ; .sbttl PCSTBM Set Top & Bottom Margins PCSTBM:: csf mov @2(r5),r1 ; get the top margin row number bgt 1$ ; if valid then send mov #1,r1 ; not valid set top to top line 1$: jsr pc,INTADC ; send parm .ttyout #semcol ; send parameter delimiter mov @4(r5),r1 ; get bottom margin row number bgt 2$ ; if valid then send mov #24.,r1 ; set bottom to bottom margin 2$: jsr pc,INTADC ; send parm .ttyout #'r ; send delimiter rts pc ; .sbttl PCAWMS Set Auto Wrap Mode PCAWMS:: csf .ttyout #'? .ttyout #'7 .ttyout #'h return ; .sbttl PCAWMR Reset Auto Wrap Mode PCAWMR:: csf .ttyout #'? .ttyout #'7 .ttyout #'l ;lower case L return .page .sbttl . Miscellaneous functions ; .sbttl DSRCP Device Status Report Cursor Position DSRCP:: csf .ttyout #'6 .ttyout #'n rts pc ; .sbttl RIS Reset to Initial State (power up & self-test) RIS:: .ttyout #esc .ttyout #'c rts pc ; .sbttl HTS Horizontal Tab Set HTS:: .ttyout #esc .ttyout #'H rts pc ; .sbttl TBC Tab Clear (horizontal) TBC:: csf .ttyout #'g rts pc ; .sbttl TBCA Tab Clear All (hoizontal) TBCA:: csf .ttyout #'3 .ttyout #'g rts pc ; .page .sbttl CPR Get Cursor Position Report CPR:: clrb spcmod ; clear the special mode change flag bit #10000,@#44 ; is the terminal in special mode bne modset ; yes then continue incb spcmod ; set special mode flag that we set mode bis #10000,@#44 ; set terminal to special mode modset: mov #-1,@2(r5) ; store the error return values mov #-1,@4(r5) mov #2,r3 ; store the number of parameters mov r5,r4 ; get the parameter block address add #2,r4 ; point to the first parameter movb #semcol,Delim ; set up the first delimiter call DSRCP ; send the request for cursor position .ttyin ; get character cmpb #esc,R0 ; is it escape ? bne err1 ; if not then exec err routine .ttyin ; get next char cmpb #'[,R0 ; is it [ delimiter bne err1 ; if not then exec err routine getprm: mov #buf1,r1 ; load buffer address getchr: .ttyin ; get char cmpb delim,R0 ; is this a parameter delimiter? beq conprm ; if it is send the parameter movb R0,(R1)+ ; put the char into the buffer br getchr ; go get the next char Conprm: clrb (r1)+ ; put a zerobyte to delimit string mov #buf1,r2 ; load the buffer address for ACDINT jsr pc,ACDINT ; convert the buffer to integer format mov r1,@(r4)+ ; return to fortran parameter block and inc movb #'R,Delim ; change the delimiter sob r3,getprm ; if not last parameter get the next parm err1: tstb spcmod ; did we set to special mode? beq excpr ; no then exit bic #10000,@#44 ; reset terminal to normal mode excpr: rts pc ; return to main ; this is the character buffer Buf1: .byte 0,0,0,0,0,0 Delim: .byte 0 spcmod: .byte 0 ; .page .sbttl READVT Read the terminal for control sequences DESCRIPTION <<** ; ; John Freymann, Jr. Test & Evaluation 4-Feb-82 ; ; ReadVT is designed to get cursor commands from the ; console and strip off the control sequence. If ; the command read did not start with an then ; only one character is read and it is returned to the ; program as argument #2 and agrument #1 is set to 0. ; If the first character was an then the escape ; is striped and the second char is checked for control ; sequence validity. ; If the second character is invalid ; then arg #1 is set to 1 and arg #2 is set to a nul ; (only 2 characters are read), this is an error condition. ; If a valid sequence is found the third character is ; gotten from the terminal and it is return as the second ; argument and the first argument is set to 1. ; If the first character isn't an escape then the char is ; echoed and returned as arg#2 arg#1 is set to 0 (if in spec ; mode before the call to readtt then the character is NOT echoed ; .page .sbttl READVT Routine ; ReadVT:: clr 100$ ; clr the flag for special mode bit #10000,@#44 ; is terminal in special mode? bne 5$ ; yes then test for uplo bis #10000,100$ ; no then set flag that we set mode bis #10000,@#44 ; set terminal to special mode 5$: bit #40000,@#44 ; is terminal in uplo? bne 6$ ; yes then get sequence bis #40000,@#44 ; set terminal to uplo bis #40000,100$ ; set flag bit for uplo 6$: clr @2(r5) ; set the flag to character .ttyin ; get the first char cmpb r0,#esc ; is it an escape? bne 20$ ; no then send it back as character .ttyin ; get second control character inc @2(r5) ; this is a control not a character cmpb r0,#'[ ; is it a cursor control? beq 10$ ; yes then get last char cmpb r0,#'O ; is it keypad control? beq 10$ ; yes then get last char. clrb @4(r5) ; this is an invalid control sequence br 30$ ; return to main 10$: .ttyin ; get the control id char. br 26$ ; send it back 20$: bit #40000,100$ ; did we set uplo? beq 25$ ; no then send back character cmpb r0,#'a ; is it lower alpha? blt 25$ ; no then send it cmpb r0,#'z ; is it lower alpha? bgt 25$ ; no then send it sub #40,r0 ; convert to upper case 25$: bit #10000,100$ ; did we set special mode beq 26$ ; no then send character to pgm .ttyout ; if we did echo the character 26$: movb r0,@4(r5) ; stick char in 2nd argument 30$: bit #40000,100$ ; did we set uplo? beq 35$ ; no then did we set special mode bic #40000,@#44 ; set to upper 35$: bit #10000,100$ ; did we set special mode beq 40$ ; no then exit bic #10000,@#44 ; set to normal mode 40$: rts pc ; Return to main 100$: .word 0 ; special mode flag ; .page .sbttl . These are the Led control functions ; .sbttl PCLL0 Extinquish all Leds PCLL0:: CSF .ttyout #'0 .ttyout #'q rts pc ; .sbttl PCLL1 Light Led #L1 PCLL1:: Csf .ttyout #'1 .ttyout #'q rts pc ; .sbttl PCLL2 Light Led #L2 PCLL2:: Csf .ttyout #'2 .ttyout #'q rts pc ; .sbttl PCLL3 Light Led #L3 PCLL3:: Csf .ttyout #'3 .ttyout #'q rts pc ; .sbttl PCLL4 Light Led #L4 PCLL4:: Csf .ttyout #'4 .ttyout #'q rts pc ; .end