perm filename DISP.MAC[EAL,HE]1 blob
sn#679404 filedate 1982-09-27 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00009 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 .TITLE DISP - Display routines to do I/O from Pascal
C00004 00003 Here is the definition of the Terminal Characteristics slots:
C00007 00004 Misc routines: BEEP, INITSC, REINIT, RESETS, CLEARS & ECHO, ESCINI & ESCINT
C00014 00005 Cursor postioning routines: SHOWCU, RESTCU
C00018 00006 Line output routine: OUTLIN
C00026 00007 Character routines: GETCHAR, ANYCHAR & OUTCHAR
C00030 00008 "Smart Terminal" routines: INSCHAR, DELCHAR, INSLINE & DELLINE
C00034 00009 Aux routines: GETLIN MOVCUR CVI OUTSTR OUTCHR GETCHR OUTST2
C00039 ENDMK
C⊗;
.TITLE DISP - Display routines to do I/O from Pascal
; MACRO definitions.
.MCALL QIOW$S,WTSE$S,CLEF$S,QIO$C,QIOW$C,ASTX$S,MRKT$S
.MACRO PUSH X
.IRP Y,<X>
MOV Y,-(SP)
.ENDM
.ENDM
.MACRO POP X
.IRP Y,<X>
MOV (SP)+,Y
.ENDM
.ENDM
;Here is the definition of the Terminal Characteristics slots:
TTHT = 0 ;Height of screen (number of lines)
TTCLRL = 2 ;What to type to clear to end of line
TTCLRS = 4 ;What to type to clear to end of screen
TTDELC = 6 ;Delete character
TTDELL = 10 ;Delete line
TTINSC = 12 ;Insert a character (may enter "insert mode")
TTINSL = 14 ;Insert line (won't enter insert mode)
TTINSX = 16 ;Cancel insert mode for char insert
TTBOLD = 20 ;Enter bold face mode
TTNORM = 22 ;Enter normal mode
TTCURP = 24 ;Position cursor
TTCURT = 26 ;Kind of cursor positioning req'd: 0="<l>;<c>H", 1=other
T1DAT: .WORD 23. ;TTHT
.WORD T1CLRL ;TTCLRL
.WORD T1CLRS ;TTCLRS
.WORD T1DELC ;TTDELC
.WORD T1DELL ;TTDELL
.WORD T1INSC ;TTINSC
.WORD T1INSL ;TTINSL
.WORD T1INSX ;TTINSX
.WORD T1BOLD ;TTBOLD
.WORD T1NORM ;TTNORM
.WORD T1CURP ;TTCURP
.WORD 0 ;TTCURT
.ENABL LC ;Enable lowercase for the stuff below.
ESC = 33 ;Escape character
LB = 133 ;Left bracket ([)
; Data for the Zenith terminal in ANSI mode:
T1CLRL: .BYTE ESC,LB,'K,0
T1CLRS: .BYTE ESC,LB,'H,ESC,LB,'J,0 ;Go home first then clear
T1DELC: .BYTE ESC,LB,'P,0
T1DELL: .BYTE ESC,LB,'M,0
T1INSC: .BYTE ESC,LB,'4,'h,0
T1INSL: .BYTE ESC,LB,'L,0
T1INSX: .BYTE ESC,LB,'4,'l,0
T1BOLD: .BYTE ESC,LB,'7,'m,0
T1NORM: .BYTE ESC,LB,'m,0
T1CURP: .BYTE ESC,LB,'0,'0,';,'0,'0,'H,0
.EVEN
;Misc routines: BEEP, INITSC, REINIT, RESETS, CLEARS & ECHO, ESCINI & ESCINT
;procedure beep;
PROC BEEP
SAVE R0
BEGIN
MOV #7,R0 ;Just type a BELL
JSR PC,OUTCHR
ENDPR
;function initScreen(lbase: listingarray): integer;
FUNC INITSC,RES,INTEGER
PARAM LBASE,ADDRESS
SAVE R1
BEGIN
MOV LBASE(SP),TBASE ;Remember base address of listing array
JSR PC,GETLIN ;Get our terminal's characteristics (returned in R1)
MOV R1,TERM ;Save terminal type (address of tty table)
MOV TTHT(R1),RES(SP) ;Return screen height from table
ENDPR
;procedure reInitScreen;
PROC REINIT
BEGIN
JSR PC,CLEAR1 ;Clear the screen
ENDPR
;procedure resetScreen;
PROC RESETS
BEGIN
JSR PC,CLEAR1 ;First clear screen
QIO$C SF.SMC,5,3,,,,<SFDAT2,2> ;Reset tty characteristics
ENDPR
;procedure clearScreen;
PROC CLEARS
BEGIN
JSR PC,CLEAR1
ENDPR
CLEAR1: PUSH <R1,R5> ;Save registers we use
MOV TERM,R5 ;Get tty descriptor address
MOV TTCLRS(R5),R1 ;And find how to clear screen
JSR PC,OUTSTR ;Type the stuff
POP <R5,R1>
RTS PC
;procedure echo(on: boolean);
PROC ECHO
PARAM ON,BOOLEAN
BEGIN
;Nothing to do since we never echo anyhow!
ENDPR
;procedure escInit(var flg: boolean);
PROC ESCINI
PARAM FLG,ADDRESS
BEGIN
MOV FLG(SP),ESCFLG ;Get address of flag word;
; Now attach the terminal to our task. Upon reciept of a control-C,
; control is passed to ESCINT. Other characters are buffered by the
; system and passed to the task when a IO.RAL is performed.
; QIO$C IO.ATA,5,3,,,,<CHRAST,,ESCINT> ;This is to do all with ast's
QIOW$S #IO.ATA,#5,#3,,,,<,,#ESCINT>
; Set terminal so it ignores control chars (like ↑O, ↑Q etc) and passes them
; along to the task.
QIO$C SF.SMC,5,3,,,,<SFDAT1,2>
ENDPR
;Come here upon reciept of control-C from terminal...
ESCINT: MOVB #1,@ESCFLG ;Set flag when we get an escape-I interrupt
TST (SP)+ ;Remove event flag# from stack
ASTX$S ;That's all we need to do
TBASE: .WORD 0 ;Location of listing base address
TERM: .WORD T1DAT ;Address of start of terminal data
SFDAT1: .BYTE TC.BIN,1 ;Make terminal ignore control sequences
SFDAT2: .BYTE TC.BIN,0 ;Make terminal recognize them again
ESCFLG: .WORD 0 ;Address of interrupt flag word
;Cursor postioning routines: SHOWCU, RESTCU
;procedure showCursor(line,col: integer);
PROC SHOWCU
PARAM LINE,INTEGER
PARAM COL,INTEGER
VAR CURADR,INTEGER
SAVE <R0,R1>
BEGIN
CMP COL(SP),#80. ;check for line overflow
BLE 5$ ;no
SUB #80.,COL(SP) ;yes - correct column number
INC LINE(SP) ; & bump line number
5$: MOV LINE(SP),R0 ;Set up line and column for cursor addr
MOV COL(SP),R1
JSR PC,MOVCUR
MOV LINE(SP),CULINE ;Save where we moved to
MOV COL(SP),CUCOL
ENDPR
CULINE: .WORD 1 ;Previous line
CUCOL: .WORD 1 ;and column
RESTCU: PUSH <R0,R1> ;Restores cursor to position saved above
MOV CULINE,R0
MOV CUCOL,R1
JSR PC,MOVCUR
POP <R1,R0>
RTS PC
;Line output routine: OUTLIN
;procedure outLine(line,col,start,length: integer);
PROC OUTLINE
PARAM LINE,INTEGER ;Line and column output is to start at
PARAM COL,INTEGER
PARAM START,INTEGER ;Start of text in buffer
PARAM LENGTH,INTEGER ;How much text to display.
VAR TEMP,INTEGER ;Work variable
SAVE <R0,R1,R5>
BEGIN
TST LENGTH(SP) ;Make sure # chars to print > 0
BLE 100$ ;else nothing to do
MOV TERM,R5 ;Terminal descriptor addr in R5
MOV LINE(SP),R0 ;Set up for cursor positioning
MOV COL(SP),R1
JSR PC,MOVCUR ;move cursor to initial position
MOV LENGTH(SP),R0 ;Compute col + length ( + 1)
ADD COL(SP),R0
CMP R0,#81. ;Make sure line won't be too long
BLE 5$ ;Nope - we're ok. It fits on one line
CMP COL(SP),#80. ;Line too long. OK if col > 80.
BGT 5$
MOV #81.,TEMP(SP) ;Find number of chars that fit on 1st line
SUB COL(SP),TEMP(SP)
MOV START(SP),R1 ;Get offset of first char to write
ADD TBASE,R1 ;Array base address + offset = start addr
MOV TEMP(SP),R0 ;Type this number of chars on 1st line
JSR PC,OUTST2 ;Type the string
MOV COL(SP),R0 ;See if we can clear end of line. Does line extend
ADD TEMP(SP),R0 ;all the way to the end?
CMP R0,#81. ;If < 81, we can clear it.
BGE 3$ ;Otherwise don't since that'd erase last char.
MOV TTCLRL(R5),R1 ;and clear rest of line too
JSR PC,OUTSTR
3$: ADD TEMP(SP),START(SP) ;Update starting place in buffer
SUB TEMP(SP),LENGTH(SP) ;And use how many chars overflowed.
MOV LINE(SP),R0 ;Position cursor for overflow line
INC R0 ; (it's on the next line)
MOV #1,R1 ;Put it in the 1st column
JSR PC,MOVCUR
5$: MOV START(SP),R1 ;Now get starting addr of string to type
ADD TBASE,R1 ;Array base address + offset = start addr
MOV LENGTH(SP),R0 ;Move number of chars to print to R0
JSR PC,OUTST2 ;Type the string
MOV COL(SP),R0 ;See if we can clear end of line. Does line extend
ADD LENGTH(SP),R0 ;all the way to the end?
CMP R0,#81. ;If < 81, we can clear it.
BGE 10$ ;Otherwise don't since that'd erase last char.
MOV TTCLRL(R5),R1 ;and clear rest of line too
JSR PC,OUTSTR
10$: JSR PC,RESTCU ;Finally, restore cursor to previous position
100$: ENDPR
;Character routines: GETCHAR, ANYCHAR & OUTCHAR
;function getChar: ascii;
FUNC GETCHAR,RES,CHAR
SAVE R0
BEGIN
JSR PC,GETCHR ;Read one char, don't echo it.
MOV R0,RES(SP) ;Return char
ENDPR
;function anyChar(var ch: ascii): boolean;
FUNC ANYCHAR,RES,BOOLEAN
PARAM CH,ADDRESS
VAR BUFFER,INTEGER
SAVE R0
BEGIN
CLRB @CH(SP) ;Clear result (assume no char)
CLR RES(SP) ;Assume no char - clear flag
QIOW$C SF.GMC,5,17.,,,,<CHRDAT,2> ;Get terminal characteristics.
TSTB CHRDAT+1 ;Any chars waiting?
BEQ 15$ ;No - Exit with results already set
JSR PC,GETCHR ;Yes - Read char & put in R0.
MOVB R0,@CH(SP) ;Return result in VAR param.
MOV #1,RES(SP) ;Indicate we got a char.
15$: ENDPR
CHRDAT: .BYTE TC.TBF,0 ;Get type-ahead buffer count in hi byte
;procedure outChar(line,col: integer; ch: ascii; bold: boolean);
PROC OUTCHAR
PARAM LINE,INTEGER ;Line and column to put char
PARAM COL,INTEGER
PARAM CH,CHAR ;The char to write
PARAM BOLD,BOOLEAN ;Nonzero means type it in boldface
SAVE <R0,R1,R5>
BEGIN
MOV TERM,R5 ;TTY info address
MOV LINE(SP),R0 ;Get ready for cursor setup
MOV COL(SP),R1
JSR PC,MOVCUR ;Move cursor to initial position
TSTB BOLD(SP) ;Bold face output?
BEQ 5$ ;No - don't do it.
MOV TTBOLD(R5),R1 ;Type stuff to make next char bold face
JSR PC,OUTSTR
5$: MOVB CH(SP),R0 ;Stick char to write into R0
JSR PC,OUTCHR
TSTB BOLD(SP) ;Did we type the char in bold face?
BEQ 10$ ;No - we're done
MOV TTNORM(R5),R1 ;Make next char normal
JSR PC,OUTSTR
10$: ENDPR
;"Smart Terminal" routines: INSCHAR, DELCHAR, INSLINE & DELLINE
;procedure insChar(line,col: integer; ch: ascii);
PROC INSCHAR
PARAM LINE,INTEGER
PARAM COL,INTEGER
PARAM CH,CHAR
SAVE <R0,R1,R5>
BEGIN
MOV TERM,R5 ;Address of terminal data block
MOV LINE(SP),R0 ;Move cursor to place to insert a char
MOV COL(SP),R1
JSR PC,MOVCUR
MOV TTBOLD(R5),R1 ;Put terminal in Bold mode
JSR PC,OUTSTR
MOV TTINSC(R5),R1 ;Get what to type to insert a char
JSR PC,OUTSTR ;and type it
MOVB CH(SP),R0
JSR PC,OUTCHR
MOV TTINSX(R5),R1 ;Cancel insert mode
JSR PC,OUTSTR
MOV TTNORM(R5),R1 ;and go back to normal mode (not bold)
JSR PC,OUTSTR
ENDPR
;procedure delChar(line,col: integer);
PROC DELCHAR
PARAM LINE,INTEGER
PARAM COL,INTEGER
SAVE <R0,R1,R5>
BEGIN
MOV TERM,R5 ;Address of terminal data block
MOV LINE(SP),R0 ;Get ready for cursor setup
MOV COL(SP),R1
JSR PC,MOVCUR ;Move cursor to initial position
MOV TTDELC(R5),R1 ;Type stuff to delete one char
JSR PC,OUTSTR
ENDPR
;procedure insLine(line,num: integer);
PROC INSLINE
PARAM LINE,INTEGER
PARAM NUM,INTEGER
SAVE <R0,R1,R2,R3,R5>
BEGIN
MOV TERM,R5 ;Address of terminal data block
MOV LINE(SP),R0 ;Get ready for cursor setup
MOV TTINSL(R5),R2 ;What to type to insert a line
MOV NUM(SP),R3 ;Save number of lines to insert
JSR PC,DOID ;Do insert or delete
ENDPR
;procedure delLine(line,num: integer);
PROC DELLINE
PARAM LINE,INTEGER
PARAM NUM,INTEGER
SAVE <R0,R1,R2,R3,R5>
BEGIN
MOV TERM,R5 ;Address of terminal data block
MOV LINE(SP),R0 ;Save line# for cursor setup
MOV TTDELL(R5),R2 ;What to type to delete a line.
MOV NUM(SP),R3 ;Save number of lines to delete
JSR PC,DOID
ENDPR
;Enter DOID with
; R0 = Line# to start at
; R2 = Addr of cmd from terminal table
; R3 = Number of lines to insert/delete
; R5 = Addr of terminal data block.
DOID: TST R3 ;Anything to do?
BLE 10$ ;(if none all done)
PUSH R3 ;Remember how many lines
MOV #1,R1 ;Move cursor to column 1 (line# already set up)
JSR PC,MOVCUR ;Set up position
5$: MOV R2,R1 ;Set up to type insert/delete command
JSR PC,OUTSTR ;Type stuff to insert or delete 1 line
SOB R3,5$ ;Repeat till done
JSR PC,RESTCU ;Restore cursor position
POP R3 ;Get back how many lines we inserted/deleted
ASH #3,R3 ;multiply by 8 to get # of ticks to wait
MRKT$S #4,R3,#1 ;(each is ~16 msec) so wait .128 sec per line
WTSE$S #4 ;(wait for event flag to be set)
10$: RTS PC
;Aux routines: GETLIN MOVCUR CVI OUTSTR OUTCHR GETCHR OUTST2
GETLIN: MOV #T1DAT,R1 ;Only 1 kind of terminal now
RTS PC
; "MOVCUR" moves the cursor to the address on the screen specified by R0 and R1,
; where R0=line and R1=column. R5 must point to the terminal data block.
; R0 and R1 may be changed.
MOVCUR: PUSH R2
MOV #IOBUF+2,R2 ;Start string conversions here.
INC R0 ;AL thinks they start at 0 but really 1...
CMP R1,#81. ;Line overflow?
BLT 5$ ;If not, continue
INC R0 ;Yes - go to next line
SUB #80.,R1 ;and adjust column # also
5$: JSR PC,CVI ;Convert Line# to decimal
MOVB #';,(R2)+ ;Put in delimeter
MOV R1,R0 ;Now do the column
JSR PC,CVI
MOVB #'H,(R2)+ ;Code to position cursor
CLRB (R2) ;and null for end of string
MOV #IOBUF,R1 ;Now type it
JSR PC,OUTSTR
POP R2
RTS PC
; "CVI" converts a number (in R0) into a digit string starting at (R2).
CVI: PUSH R1 ;SAVE REGISTER
JSR PC,5$ ;Go form number string recursively.
POP R1 ;RESTORE REGISTERS
RTS PC ;ALL DONE
5$: MOV R0,R1 ;POSITION NUMBER FOR DIVISION
CLR R0 ;CLEAR FOR DIVISION
DIV #10.,R0 ;GET LSD
ADD #'0,R1 ;OR ASCII BASE
MOVB R1,-(SP) ;SAVE DIGIT
TST R0 ;Are we done?
BEQ 10$ ;Yes - Store digits
JSR PC,5$ ;REPEAT RECURSIVELY
10$: MOVB (SP)+,(R2)+ ;PUT DIGITS IN STRING
RTS PC
; "OUTSTR" outputs an ASCIZ string, which ends with a zero character.
; A pointer to the start of the string must be loaded into R1.
; If the length of the string is already known, call OUTST2 with R1 pointing
; to the string and R0 containing the length.
; Nothing is changed.
OUTSTR: PUSH <R0,R1> ;Types using WAL
CLR R0 ;Figure out how long the string is
5$: TSTB (R1)+ ;End of string?
BEQ 10$ ;Yes. Type it now
INC R0
BR 5$
10$: POP R1 ;Restore R1 to point to string beginning
JSR PC,OUTST2 ;Go type the string.
POP R0 ;and restore R0
RTS PC ;Done
; "OUTCHR" prints the character in R0. Nothing is changed.
OUTCHR: PUSH <R0,R1> ;Save registers we use
MOVB R0,CHBUF ;Move char to type to core memory
MOV #CHBUF,R1 ;Set up for OUTST2: Addr of string beginning
MOV #1,R0 ;and number of chars to type
JSR PC,OUTST2 ;go type the single char
POP <R1,R0> ;and restore registers
RTS PC
; "GETCHR" reads a character without echoing and returns it in R0.
GETCHR: QIOW$S #IO.RAL!TF.RNE,#5,#17.,,,,<#CHBUF,#1>
MOVB CHBUF,R0 ;and store result
BIC #↑O<177600>,R0 ;Clear parity & upper 8 bits.
RTS PC
; Auxilliary routine to print a string. R1=address, R0=length.
OUTST2: QIOW$S #IO.WAL,#5,#17.,,,,<R1,R0> ;Type the characters.
RTS PC
IOBUF: .BYTE ESC,LB, 0,0, 0,0, 0,0, 0,0, 0,0 ;For positioning cursor
CHBUF: .WORD 0
.END