.TITLE V10IO .IDENT /260583/ .ENABL LC ; ; ; ; ; Written by Ray Di Marco ; 20-Apr-82. ; ; ; Version 200483/02 ; ; ;-------------------------------------------------------------------------- ; ; This module contains the primitive I/O drivers needed by the "CONIO" module ; to use a VT100 type terminal as console. These routines addhere to the ; calling sequences specified in the CONIO module. Note that the routines ; preserve all registers. The entry points are ; ; V10.CO outputs a character (in R0) to the terminal. ; V10.LO output a .ascii or .asciz string @R0 to the terminal. ; V10.CI returns a character (in R0) from the terminal. ; V10.LI inputs a .asciz string from terminal into buffer @R0. ; V10.EL erases line whose coordinates are passed in R0 (see V10.XY) ; V10.ES erases all of screen and homes cusor ; V10.XY positions cusor at Y=hob and X=lob of R0. ; ; The two output routines CO/LO support two special characters that allow the ; user to highlight output. Codes 203!8 and 204!8 respectively turn high ; lighting on and off. The two input routines (LI/LO) ignore any ; character and convert escape sequences into an equivalent one byte code. ; This code is generated by setting bit 7 of the last character in the ; sequence ; ; This module will operate correctly under RT-11, TSX-plus and RSTS/E as long ; as it is managed by the CONIO module that carries out special operating ; specific initialization. The RSTS users must ensure that the following ; terminal characteristics have been set up ; ; FORM;NO UPARROW;STALL;SCOPE;TAB ; .SBTTL Modifications ; ; 26-May-83 correct logic error in XY positioning code. ; ; The top left corner of the screen corresponds to line 0, column 0 ; in DBSMNG applications. Correct error in XY position code that made ; corner correspond to line 0, column 1. ; .SBTTL DECLARATIONS ; ; .MCALL .TTYOUT,.TTYIN ; I/O MACROS .MCALL .PUSH,.POP ; STACKING ; .GLOBL V10.CI,V10.CO ; CHARACTER IN/OUT .GLOBL V10.LI,V10.LO ; LINE IN/OUT .GLOBL V10.ES,V10.EL ; ERASE SCREEN/LINE .GLOBL V10.XY ; POSITION CUSOR ; ; .IIF NDF,BS, BS = 'H-'@ ; BACKSPACE .IIF NDF,TAB, TAB = 'I-'@ ; TAB .IIF NDF,LF, LF = 'J-'@ ; LINEFEED .IIF NDF,CR, CR = 'M-'@ ; CARRIAGE RETURN .IIF NDF,ESC, ESC = 33 ; ESCAPE .IIF NDF,SPACE, SPACE = 40 ; SPACE .IIF NDF,DELIMT, DELIMT = '; ; DELIMITER .IIF NDF,ESCOUT, ESCOUT = 233 ; Equivalent to ESC under RSTS .IIF NDF,DELETE, DELETE = 177 ; DELETE ; ; .PSECT CODE ; OPEN CODE SECTION ; ------ ---- .SBTTL Macro Definitions ; ; ; .OUT outputs via V10.CO either one or more characters. ; .MACRO .OUT CHAR .IF B, CALL V10.CO .MEXIT .ENDC MOV R0,-(SP) .IRP X, MOVB X,R0 CALL V10.CO .ENDR MOV (SP)+,R0 .ENDM .OUT ; ; ; .SEQ Output an escape sequence to VT100. ; .MACRO .SEQ STR MOV R0,-(SP) MOV #ESCOUT,R0 CALL V10.CO .IRPC X, MOVB #''X,R0 CALL V10.CO .ENDR MOV (SP)+,R0 .ENDM .SEQ ; ; .SBTTL Entry - "V10.CI" ... Equivalent .TTYIN ; ; This routine will input one character from the console. It performs ; a number of special operations in as such that it discards certain ; control characters and converts escape sequences into a single ; character. ; ; Accept all characters other than which is ignored, or a ; which requires special processing. ; V10.CI: .TTYIN ; R0 = char BIC #^C377,R0 ; mask to 8 bits CMP R0,#LF ; ? BEQ V10.CI ; yes -> ignore CMP R0,#ESC ; ? BEQ 1000$ ; yes -> special RETURN ; all done ; ; Have an . The VT100 generates three letter escape sequences. ; See if third character is in 7000$ table. If is, translate character ; and then exit. If not, set bit 7 and return it. ; 1000$: .TTYIN ; get second character .TTYIN ; get third character .PUSH R1 ; save R1 MOV #7000$,R1 ; R1 -> translation table 1100$: CMPB R0,(R1) ; match? BEQ 1400$ ; yes -> skip TST (R1)+ ; point next entry BNE 1100$ ; loop till get EOT BIS #200,R0 ; set bit 7 BR 1500$ ; exit 1400$: MOVB 1(R1),R0 ; R0 = character 1500$: BIC #^C377,R0 ; mask to 8 bits .POP R1 ; restore RETURN ; exit ; ; Translation table for special codes. ; 7000$: .Byte 'A,200+'A ; Cup .Byte 'B,200+'B ; Cdn .Byte 'C,200+'C ; Crt .Byte 'D,200+'D ; Clt .Byte 'P,200+'P ; PF1 .Byte 'Q,200+'Q ; PF2 .Byte 'R,200+'R ; PF3 .Byte 'S,200+'S ; PF4 .BYTE 0,0 ; EOT ; .SBTTL Entry - "V10.CO" ... Equivalent .TTYOUT ; ; ; This routine is called to output thye character in R0. It translates ; a number of special characters into escape sequences for the VT100. ; V10.CO: CMPB R0,#ESCOUT ; Special escape BEQ 1000$ ; yes -> output escape CMPB R0,#ESC ; Normal escape BEQ 1000$ ; yes -> output escape TSTB R0 ; Special? BMI 2000$ ; yes -> process .TTYOUT ; output char RETURN ; Exit ; ; Output an escape. ; 1000$: .PUSH R0 ; save .TTYOUT #ESCOUT ; output escape .POP R0 ; restore RETURN ; exit ; ; Foreground, Increase intensity. ; 2000$: CMPB R0,#203 ; want FG on? BNE 2100$ ; no -> skip .SEQ <[0;1m> ; turn up intensity RETURN ; all done ; ; Exit FOREGROUND highlight. ; 2100$: CMPB R0,#204 ; want FG off? BNE 2200$ ; no -> skip .SEQ <[0m> ; turn off attributes RETURN ; all done ; 2200$: RETURN ; ignore special char ; ; .SBTTL Entry - "V10.LO" ... Equivalent .PRINT ; ; Output an ascii string to the terminal. Use V10.CO to output ; characters. ; V10.LO: .PUSH ; save MOV R0,R1 ; R1 -> string 100$: MOVB (R1)+,R0 ; R0 = character BEQ 2000$ ; eos -> skip BPL 200$ ; ok -> skip CMPB R0,#200 ; special terminator? BEQ 2700$ ; yes -> exit 200$: CALL V10.CO ; output char BR 100$ ; LOOP ; 2000$: .OUT <#CR,#LF> ; output 2700$: .POP ; restore RETURN ; EXIT ; ; .SBTTL Entry - "V10.LI" ... Equivalent .GTLIN ; ; Have to perform equivalent of .GTLIN operation. Difference is that ; we trap out any unwanted control characters and handle ^U and DELETE ; in SCOPE mode. ; ; Set up registers. ; V10.LI: .PUSH ; save MOV R0,R1 ; R1 -> buffer CLR R2 ; R2 = counter ; ; Normal characters go dirrectly in buffer. Control codes ; and DELETE are handled by routines in 1000$ table. ; 100$: CALL V10.CI ; input char CMPB R0,#40 ; control char? BLO 200$ ; yes -> skip CMPB R0,#DELETE ; delete? BEQ 200$ ; yes -> skip MOVB R0,(R1)+ ; save character CALL V10.CO ; echo INC R2 ; up count BR 100$ ; LOOP ; 200$: MOV #1000$,R3 ; R3 -> table 210$: CMPB R0,(R3) ; match? BEQ 220$ ; yes -> exit ADD #4,R3 ; point next entry TST (R3) ; EOT? BNE 210$ ; no -> loop 220$: CALL @2(R3) ; dispatch BR 100$ ; LOOP ; ; ; ; Table that correlates special codes with routine to perform ; function. ; 1000$: .WORD 15,1100$ ; CR -> exit .WORD 'U-'@,1200$ ; ^U -> delete line .WORD DELETE,1300$ ; DEL-> delete last char .WORD 0,1170$ ; eot ; ; ; Terminate input. ; 1100$: CLRB (R1) ; null at eol .OUT <#CR,#LF> ; output CR/LF ADD #2,SP ; discard call address .POP ; restore 1170$: RETURN ; all done ; ; ; Delete all input. ; 1200$: CALL 1300$ ; delete char TST R2 ; any left? BNE 1200$ ; yes -> loop RETURN ; all done ; ; ; Delete last character. ; 1300$: TST R2 ; any characters to delete? BEQ 1370$ ; no -> exit .OUT <#BS,#SPACE,#BS> ; DEC R1 ; down pointer DEC R2 ; down counter 1370$: RETURN ; DONE ; .SBTTL Entry - "V10.EL" ... erase line @R0 ; ; ; This routine positions the cusor at the coordinate passed in R0 ; and then causes the line to be erased. ; V10.EL: CALL V10.XY ; Position on line .SEQ <[2K> ; order erase RETURN ; ALL DONE ; ; .SBTTL Entry - "V10.ES" ... erase all of screen ; ; ; This routine erases all the screen and positions the cusor on ; the HOME coordinate. ; V10.ES: .SEQ <[2J> ; clear screen .SEQ <[H> ; home cusor RETURN ; done ; ; .SBTTL Entry - "V10.XY" ... position cusor @ R0=Y:X ; ; ; This routine cuases the cusor to be positioned at X,Y. The coordinates ; are passed as follows- ; X == LOB OF R0 ; Y == HOB OF R0 ; ; *** Note DBSMNG gives origin coordinates 0,0 ; VT100 gives origin coordinates 1,1 ; ; V10.XY: .PUSH ; save SWAB R0 ; R0 = X:Y (ie Y in LOB) .SEQ <[> ; indicate start of sequence INC R0 ; add 1 to Y coordinate CALL 1000$ ; output coordinate .OUT #DELIMT ; delimiter needed MOV (SP),R0 ; R0 = Y:X INC R0 ; add 1 to X coordinate CALL 1000$ ; output X coordinate .OUT #'H ; indicate is position operation .POP ; restore RETURN ; done ; 1000$: MOV R0,R1 ; COORDINATE -> R1 BIC #^C177,R1 ; DISCARD HOBITS CLR R0 ; CLEAR ACCUMULATOR CMP R1,#99. ; IN RANGE? BLOS 1100$ ; IN RANGE -> OK CLR R1 ; MAKE 0 1100$: CMP R1,#10. ; > 10? BLO 1200$ ; NO -> DONE WITH 10'S INC R0 ; UP ACCUMULATOR SUB #10.,R1 ; DOWN NUMBER BR 1100$ ; LOOP 1200$: ADD #'0,R0 ; MAKE ASCII .OUT ; SEND IT OUT ADD #'0,R1 ; MAKE ASCII .OUT R1 ; SEND OUT RETURN ; ALL DONE ; .END