home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
ccdos.zip
/
cczibm.asm
< prev
next >
Wrap
Assembly Source File
|
1991-09-08
|
166KB
|
3,333 lines
NAME cczibm
; File CCZIBM.ASM
page 60,132
; Terminal emulator module for IBM PC's and compatibles.
;
;CHINESE
ifdef MSDOS
include mszibm.dat
else
include cczibm.dat
endif
code segment public 'code'
extrn prtbout:near, prtnout:near, csrtype:near, trnmod:near
extrn scrmod:near, scrseg:near, scrsync:near, scroff:near
extrn scron:near, atsclr:near, vtscru:near, vtscrd:near
extrn modwrt:near, telmsy:near, scrloc:near, pcwait:near
extrn chgdsp:near, trnprs:near, cptchr:near, tekesc:near
extrn pntchr:near, pntchk:near, pntflsh:near
; extrn procedures are all in module msyibm
extrn tekini:near, tekemu:near, tekend:near, vtrmac:near,vtsmac:near
assume cs:code, ds:datas, es:datas
; This routine initializes the VT100 setups at startup. It is called from
; procedure lclyini in module msyibm.
vsinit proc near
mov vtemu.vtflgst,vsdefaults ; Init to defaults in mssdef.h
mov vtemu.vtflgop,vsdefaults ; Init runtime state to setup items
mov insmod,0 ; turn off insert mode
mov deftabs,0 ; Column 1 has no tab stop
mov ansflgs,0
mov cl,crt_cols ; physical screen width (80)
dec cl ; we count from column 0
mov ch,crt_lins ; physical screen length-1
dec ch ; we count from row 0
mov low_rgt,cx ; store active text area
mov cx,131
mov di,1 ; Starting index for column 2
vsini1: mov al,0 ; Assume we will clear this one
test di,0007H ; Index mod 8 equals 0?
jnz vsini2 ; No, clear it
mov al,0FFH ; Yes, set it
vsini2: mov deftabs[di],al ; Set or clear a tab stop
inc di ; Advance to next
loop vsini1 ; Loop for all
mov cx,slen ; clear linetype array
mov di,0
vsini3: mov linetype[di],0
inc di
loop vsini3
mov vtemu.vttbst,offset deftabs ; addrs of active tabs for STATUS
mov vtemu.vttbs,offset deftabs ; addrs of tabs for setup (SET)
mov vttabs,offset deftabs ; initial source of tabs
call cpytabs ; copy default to active
mov vtemu.att_ptr,offset att_normal ; ptr to video attributes
mov ah,8 ; read current attributes
xor bh,bh ; page 0
int screen
mov scbattr,ah ; save video attributes
mov att_normal,ah ; set att_normal to present colors
call brkatt ; separate colors from blink/bold
rol ah,1 ; reverse foreground & background
rol ah,1 ; RGB bits
rol ah,1
rol ah,1
call addatt ; reinsert bold/blink bits
mov att_reverse,ah ; set att_reverse too
mov ah,byte ptr low_rgt ; right most column (counted from 0)
sub ah,8 ; place marker 9 columns from margin
mov belcol,ah ; store column number to ring bell
ret ; And return
vsinit endp
; Initialization routine.
;
; Call: al/ yflags byte that was passed to Term routine
; dl/ index for baud rate table
; dh/ parity in bits 4-7, number of data bits in bits 0-3
;
ansini proc near
mov yflags,al ; Always save flags
mov ah,vtemu.vtflgst ; setup flags
mov vtflags,ah
mov vttabs,offset deftabs ; tab stop pointer
mov vtemu.vttbst,offset tabs; store here for STATUS
mov al,flags.vtflg ; get current terminal type
mov oldterm,al ; remember it here for soft restarts
mov insmod,0 ; turn off insert mode
mov h19l25,0 ; clear Heath 25th line enable
mov h19ctyp,1 ; set Heath cursor to underline, on
mov anspflg,0 ; clear printer flag
push ax
mov ah,byte ptr low_rgt ; right most column (counted from 0)
sub ah,8 ; place marker 9 columns from margin
mov belcol,ah ; store column number to ring bell
pop ax
cmp dl,lbaudtab ; Wierd index?
jb ansin1 ; No - OK - store it
mov dl,lbaudtab-1 ; Yes - make it the maximum
ansin1: mov baudidx,dl ; Save baud rate index
mov al,dh ; Get parity/number of databits
and al,0FH ; Isolate number of databits
mov datbits,al ; Save
mov cl,4 ; Isolate parity code
shr dh,cl ; Isolate parity code
cmp dh,lpartab ; Weird code?
jb ansin2 ; No - OK - store it
mov dh,lpartab-1 ; Yes - make it the maximum
ansin2: mov parcode,dh ; Save
call scrmod ; Get the screen mode, in MSYxxx
mov cl,crt_cols ; physical screen number columns (80)
dec cl ; we count from column 0 here
mov ch,crt_lins ; physical screen number rows-1 (24)
dec ch ; we count from row 0 here
mov low_rgt,cx ; save as active text screen size
mov oldscrn,cx ; remember old screen dimensions
ansin3: call atreset ; Reset everything
mov ttstate,offset atnrm ; Reset state to "normal"
ret ; And return
ansini endp
; Re-initialization routine. Called when Term was called but screen was
; restored from a previously saved screen, etc.
;
; Call: al/ yflags byte that was passed from msyibm module.
;
ansrei proc near
mov yflags,al ; Always save flags
mov ah,vtemu.vtflgop ; get runtime flags
mov tmpflags,ah
call scrmod ; Get the screen mode
call atsctyp ; set cursor type [rbv]
mov ah,3 ; get cursor position from msy
mov bh,0 ; Page zero
int screen ; physical = logical cursor here
mov cursor,dx ; dh = row, dl = column
mov cl,crt_cols ; physical screen number columns (80)
dec cl ; we count from column 0 here
mov ch,crt_lins ; physical screen number rows-1 (24)
dec ch ; we count from row 0 here
mov low_rgt,cx ; save as active text screen size
cmp linelen,79 ; want 80 cols?
ja ansre2 ; a = no
cmp byte ptr low_rgt,79 ; want 80 cols. Is active screen wider?
jbe ansre2 ; be = no
mov byte ptr low_rgt,79 ; narrow down to 80 columns
ansre2: test vtemu.vtflgop,vswdir ; writing right to left?
jz ansre4 ; z = no, left to right
sub dl,byte ptr low_rgt ; reflect cursor from right side
neg dl
mov cursor,dx ; store as logical position
ansre4: push cx ; save current physical screen size
call stblmds ; Check settable modes, set flags
pop cx
cmp cx,oldscrn ; has screen size changed?
je ansre3 ; e = no, same as last time
mov oldscrn,cx ; remember new size
mov mar_top,0 ; reset scrolling region
mov al,byte ptr low_rgt+1
mov mar_bot,al
jmp atres2 ; better do soft reset
ansre3: ret
ansrei endp
; This routine copies the new tab stops when they have changed.
; Copies all 132 columns.
cpytabs proc near
mov cx,swidth ; number of screen columns
jcxz cpytab1 ; z = none to do
mov si,vttabs ; Source
mov di,offset tabs ; Destination
push es ; save es
push ds
pop es ; set es to datas segment
cld
rep movsb ; Do the copy
pop es ; recover es
cpytab1:ret
cpytabs endp
; This routine checks to see whether any of the settable modes have changed
; (things that can be changed in both SETUP and by host commands), and
; changes those that need to be changed. TMPFLAGS has the new VT100 setup
; flags, VTFLAGS has the old. This routine also updates VTFLAGS.
; Revised by [jrd] to allow MSY to reset scbattr when not in connect mode,
; to do "soft reset" if terminal type has changed, and to do a screen clear
; reset if the actual screen colors have changed.
stblmds proc near
mov al,flags.vtflg ; get current terminal type
cmp al,oldterm ; same as before?
je stblm10 ; e = yes, skip over soft reset
mov oldterm,al ; remember current terminal type
mov insmod,0 ; reset insert mode flag
mov h19l25,0 ; reset heath-19 25th line enable
mov mar_top,0 ; reset top scrolling margin
mov al,byte ptr low_rgt+1 ; and scrolling margin
mov mar_bot,al ; to last normal line on screen
mov ah,byte ptr low_rgt ; right most column (counted from 0)
sub ah,8 ; place marker 9 columns from margin
mov belcol,ah ; store column number to ring bell
and ansflgs,decckm+deckpam+decom+dececho ; save some flags
push bx ; save this register around loop
mov bx,offset linetype ; setup to clear double width chars
mov cx,slen ; number of linetype slots to clear
cmp flags.vtflg,ttvt100 ; VT100 now?
jne stblm0 ; ne = no
or ansflgs,decanm ; set ansi flag bit
stblm0: mov byte ptr [bx],0 ; clear the linetype array to single
inc bx ; width characters
loop stblm0 ; do each line (1 byte per line)
pop bx ; restore bx
stblm10:mov al,tmpflags ; Get the new flags
and ansflgs,not anslnm ; assume we do not want newline
test al,vsnewline ; is newline mode desired?
jz stblm1 ; No - continue
or ansflgs,anslnm ; Yes - set corresponding mode flag
stblm1: and ansflgs,not decawm ; assume not want wrap
test al,vswrap ; Did wrap mode change?
jz stblm2 ; No - continue
or ansflgs,decawm ; Yes - set corresponding mode flag
stblm2:
;; mov ah,vtflags ; old flags
;; xor ah,tmpflags ; new flags
;; test ah,vsshift3 ; pick out char set bit
;; jz stblm4 ; z = no change
;; mov ah,ascset ; assume US ASCII
;; test tmpflags,vsshift3 ; Want UK?
;; jz stblm3 ; No - guessed right
;; mov ah,ukset ; Yes - use UK set
mov ah,vtemu.vtchset ; select char set from setup byte
stblm3: mov chr_sg0,ah ; Set the sets
mov chr_sg1,ah
stblm4: mov ah,oldbatr ; get old screen background scbattr
mov scbattr,ah ; and update working copy
mov ah,att_normal ; get new attributes (Set Term Color)
push bx
mov bh,ah ; get new intensity bit of att_normal
and bh,att_intensity
and curattr,not att_intensity ; char attrs. clear intensity bit
or curattr,bh ; set new intensity
and mlbattr,not att_intensity ; mode line attrs. clear intensity
and scbattr,not att_intensity ; screen background attribute
or scbattr,bh ; set its intensity also
mov bl,scbattr
mov oldbatr,bl ; and save it here as well
pop bx
call brkatt ; separate color and blink/bold
rol ah,1 ; reverse fore/back color fields
rol ah,1
rol ah,1
rol ah,1
call addatt ; put back blink/bold
push bx ; check on color change
mov bh,ah ; new att_reverse pattern
and bh,not(att_intensity+att_blink) ; look at just color bits
mov bl,att_reverse ; previous att_reverse pattern
and bl,not(att_intensity+att_blink) ; look at just color bits
mov att_reverse,ah ; save new reverse pattern
cmp bh,bl ; have any color bits changed?
pop bx ; does not affect flags
je stblm9 ; e = no
mov cursor,0 ; reset cursor position
jmp atres2 ; go to semi-reset
stblm9: ; check on screen normal/reversed
mov al,tmpflags
xor al,vtflags ; Find which ones have changed
test al,vsscreen ; How about screen background?
jz stblm8 ; No - don't touch it
test tmpflags,vsscreen ; Flag to be set?
jnz stblm5 ; Yes - go to it
and ansflgs,not decscnm ; No - cleared (normal video)
and savflgs,not decscnm
mov al,att_normal ; No - get new background
jmp short stblm6 ; And reverse everything
stblm5: or ansflgs,decscnm ; Set (reverse video)
or savflgs,decscnm
mov al,att_reverse ; No - set reverse video
stblm6: call atrss2 ; Reverse screen and cursor attribute
stblm7: mov al,scbattr ; Reset saved attribute also
mov savecu+svattr_index,al
mov oldbatr,al ; and save our attribute
stblm8: mov al,tmpflags ; Get new flags
mov vtflags,al ; Store them
mov ah,2 ; set cursor
mov bh,0 ; page 0
mov dx,cursor
call direction ; set cursor for writing direction
ret
stblmds endp
; Return screen offset - given rol, col in dx, returns offset of the word
; for that character from the screen origin in ax. Preserves all other regs.
; Use same routine in msy to more closely track screen width.
;;scrloc proc near
;; push bx ; We will use bx
;; mov al,dh ; Get row
;; mov bl,swidth ; And length of a line
;; mul bl ; Offset for this row
;; mov dh,0 ; Clear row
;; add ax,dx ; Word offset for this position
;; sal ax,1 ; Make it a byte offset
;; pop bx ; Restore bx
;; ret ; And return
;;scrloc endp
; Fetch status/attributes routine.
;
; Call: al/ "yflags" byte from MSYxxx.
;
; Return: ah/ mode line background attribute
; al/ screen background attribute
; bl/ current cursor attribute
; bh/ ANSI (VT100) mode flags
anstat proc near
mov yflags,al ; Mostly for disleds
mov ah,mlbattr ; Return them our attrs, flags, etc
mov al,scbattr
mov bl,curattr
mov bh,ansflgs
ret
anstat endp
; Routine called when something is typed on the keyboard
;
; Call: No arguments
;
anskbi proc near
mov ttkbi,0FFH ; Just set a flag
ret
anskbi endp
; Routine to do keyclick if flag is set.
;
; Call: No arguments
;
vclick proc near
test vtflags,vskeyclick ; Is the flag on?
jz vclick1 ; No - just return
push bx ; Save some ACs
push di
mov di,500 ; 500 Hertz
mov bx,1 ; For 1 millisecond
call vtsound ; Do it
pop di ; Restore the ACs
pop bx
vclick1:ret
vclick endp
; Routine to do VT100-style bell.
;
; Call: No arguments
;
vtbell proc near
push di
push bx
mov di,880 ; 880 Hertz
mov bx,40 ; For 40 ms
call vtsound ; Do it
pop bx
pop di
ret
vtbell endp
; Routine to make noise of arbitrary frequency for arbitrary duration.
; Similar to routine (with typo removed) in "IBM PC Assembly Language:
; A Guide for Programmers", Leo J. Scanlon, 1983 Robert J. Brady Co.,
; Bowie, MD., page 270. Modified by J R Doupnik to use 0.1 millsec interval.
;
; Call: di/ frequency in Hertz.
; bx/ duration in 1 millisecond units
;
vtsound proc near
push ax ; Save regs
push cx
push dx
mov al,0B6H ; Write timer mode register
out 43H,al
mov dx,14H ; Timer divisor is
mov ax,4F38H ; 1331000/frequency
div di
out 42H,al ; Write timer 2 count low byte
mov al,ah
out 42H,al ; Write timer 2 count high byte
in al,61H ; Get current port B setting
or al,3 ; Turn speaker on
out 61H,al
mov ax,bx ; number of milliseconds to wait
call pcwait ; do the calibrated wait
in al,61H ; Get current port B setting
and al,0fch ; Turn off speaker and timer
out 61H,al
pop dx ; Restore regs
pop cx
pop ax
ret
vtsound endp
; Routine to toggle VT100/VT52/Heath-19 modes. No arguments.
; Use & update global byte flags.vtflg for terminal type and update local
; bit decanm. Note: shifting to Heath-19 here does Not reset the scrolling
; margins mar_top & mar_bot nor reset the double char linetype array.
; [jrd]
ans52t proc near
cmp tekflg,0 ; in Tek sub mode?
jne ans52c ; ne = yes, get out now
cmp flags.vtflg,ttvt100 ; in VT100 mode?
jne ans52a ; ne = no
and ansflgs,not decanm ; reset VT100 ansi mode
mov flags.vtflg,ttvt52 ; say VT52 now (clears vt100 bit)
mov oldterm,ttvt52 ; and remember it
jmp ans52e
ans52a: cmp flags.vtflg,ttvt52 ; in VT52 mode?
jne ans52b ; ne = no
mov flags.vtflg,ttheath ; say Heath-19 now
mov oldterm,ttheath
jmp ans52e
ans52b: cmp flags.vtflg,ttheath ; in Heath-19 mode?
jne ans52c ; ne = no
test denyflg,tekxflg ; is Tek mode disabled?
jz ans52f ; z = no, enabled
mov flags.vtflg,ttvt100 ; say VT100 now
mov oldterm,ttvt100
or ansflgs,decanm ; set, go to VT100 mode
jmp short ans52e
ans52f: call atsc ; save cursor and associated data
mov flags.vtflg,tttek ; set Tek mode
call tekini ; init Tek to switch screens
jmp atnorm ; normal state and return
ans52c: cmp flags.vtflg,tttek ; in Tek mode now?
je ans52d ; e = yes
cmp tekflg,0 ; doing Tek sub mode?
jne ans52d ; ne = yes
jmp atnorm ; else ignore this call
ans52d: call tekend ; exit Tek graphics mode
mov tekflg,0 ; end Tek sub mode (do after tekend)
mov flags.vtflg,ttvt100 ; say VT100 now
mov oldterm,ttvt100
or ansflgs,decanm ; set, go to VT100 mode
call atrc ; restore cursor etc
cmp flags.modflg,0 ; is mode line disabled?
je ans52e ; e = yes, disabled
test yflags,modoff ; Mode line off?
jnz ans52e ; nz = yes - just return
mov al,yflags ; get current flags
or al,modoff ; say mode line is off
call telmsy ; let msy hear the news
call trnmod ; turn it on
ans52e: call chrdef ; Set default character sets
call atsc ; Save cursor etc
call disleds ; Remove or redisplay "LEDs"
jmp atnorm ; Say state is "normal" and return
ans52t endp
; Display "LEDs" routine. Note that this routine
; is not used internally in this module (because it updates the flags from
; MSYIBM). Internally, disleds is used instead. The yflags from MSYIBM are
; needed because we have to know if the mode line is enabled.
;
; Call: al/ yflags from MSYIBM
;
; Return: Current state of "LEDs" displayed on line 25.
;
ansdsl proc near ; Update flags and display "LEDs"
mov yflags,al ; Update the flags
call disleds ; Display LEDs
ret
ansdsl endp
; Internal routine to display LEDs.
disleds:test yflags,modoff ; Mode line off?
jnz disled2 ; Yes - just return
cmp flags.modflg,1 ; mode line on and owned by us?
ja disled2 ; a = no, leave it intact
mov ah,2 ; Position cursor at (slen-1),70
mov bh,0 ; Page zero
mov dh,byte ptr low_rgt+1 ; last screen line - 1
inc dh ; status line
mov dl,led_col ; column for led display
int screen
mov cx,10 ; Length of byte array is ten
mov si,offset ansleds ; The "LEDs"
cmp flags.vtflg,ttvt100 ; VT100 mode?
je disled1 ; e = yes
mov si,offset v52leds ; try VT52
cmp flags.vtflg,ttvt52 ; VT52?
je disled1 ; e = yes
mov si,offset h19leds ; use Heath-19
disled1:lodsb ; Get a character
mov ah,14 ; Write character function
mov bh,0 ; Page zero
int screen
loop disled1 ; Loop for all chars
mov ah,2 ; Reposition cursor when finished
mov bh,0 ; Page zero
mov dx,cursor
call direction ; do Bios screen operation
call atsctyp ; Reset right type of cursor
disled2:ret
; ANSI terminal output routine. Call with character in al.
anstty proc near ; ANSI terminal output
mov dx,cursor ; Some routines need cursor in dx
mov kbiflg,0 ; Clear old flag value
test yflags,trnctl ; Debug mode?
jz anstt1 ; z = no
jmp atdeb ; Yes - just translate control chars
anstt1: cmp ttkbi,0 ; New keyboard input?
je anstt2 ; No - just continue
mov kbiflg,1 ; Yes - set flag
mov kbicsr,dx ; Save old cursor
mov ttkbi,0 ; Clear this flag
anstt2: test anspflg,vtcntp ; print controller on?
jz anstt4 ; z = no
test yflags,capt ; capturing output?
jz anstt3 ; z = no, forget this part
push ax ; save char
call cptchr ; give it captured character
pop ax ; restore character
anstt3: jmp ansmc ; print transparently
; Set Display 7/8 bit filter
anstt4: test flags.remflg,d8bit ; keep 8 bits for displays?
jnz anstt5 ; nz = yes, 8 bits if possible
and al,7fh ; remove high bit
anstt5: cmp al,spc ; control char?
jb anstt6 ; b = yes
cmp ttstate,offset atnrm ; doing displayable text?
jne anstt7 ; ne = no, no translation
; Set Translation filter
anstt6: cmp rxtable+256,0 ; translation turned off?
je anstt7 ; e = yes, no translation
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
anstt7: cmp al,DEL ; ANSI Delete char?
je atdel ; e = yes, ignore it before logging
cmp al,0 ; NUL char?
je atign ; e = yes, ignore it before logging
test yflags,capt ; capturing output?
jz anstt8 ; z = no, forget this part
push ax ; save char
call cptchr ; give it captured character
pop ax ; restore character and keep going
; Direct char to processor module
anstt8: cmp al,20h ; Control character?
jb atctrl ; b = yes, handle it
anstt9: jmp ttstate ; Nope, dispatch according to state
atign: ret ; Something to be ignored
atctrl: mov ah,0 ; Make sure this is zero.
cmp al,escape ; an escape sequence starting?
je atctrl1 ; e = yes, don't print it
test anspflg,vtautop+vtcntp ; printing desired?
jz atctrl1 ; z = no
call pntchr ; print char in al
atctrl1:mov di,ax ; Put it in an index register
shl di,1 ; Make it a word offset
jmp ansspc[di] ; Dispatch
atdel: jmp short atign ; ignore DEL char
atdeb: test yflags,capt ; capturing output?
jz atdeb3 ; z = no, forget this part
push ax ; save char
call cptchr ; give it captured character
pop ax ; restore character and keep going
atdeb3: mov bh,ansflgs ; Save flags and attribute
mov bl,curattr
push bx
push word ptr mar_top ; Save limited scrolling region
push ax ; Save character for a second
mov ah,curattr ; Get attribute
call brkatt ; Break it up
and al,att_intensity ; clear attributes, except bold bit
call addatt ; Put it back together
mov curattr,ah ; Store
or ansflgs,decawm ; Set autowrap temporarily
mov mar_top,0 ; Set scrolling region to entire page
mov al,byte ptr low_rgt+1
mov mar_bot,al
pop ax ; Restore character
test al,80h ; high bit set?
jz atdeb0 ; z = not set
push ax ; Save the character for a second
mov al,7eh ; Output a tilde
call atnrm2
pop ax ; Restore character
and al,7fh ; and remove high bit
atdeb0: cmp al,del ; A DELETE?
je atdeb1 ; Yes - output "^?"
cmp al,20h ; A control character?
jnb atdeb2 ; No - just output char in al
atdeb1: push ax ; Save the character for a second
mov al,5eh ; Output a caret
call atnrm2
pop ax ; Restore character
add al,40h ; Make ^letter (or ^? for DELETE)
and al,7fh ; Clear bit 7 (for DELETE)
atdeb2: call atnrm2 ; Output translated character
pop word ptr mar_top ; Restore scrolling region
pop bx ; And flags and cursor attribute
mov curattr,bl
mov ansflgs,bh
ret
atnorm: mov ttstate,offset atnrm ; Reset state to "normal".
ret
; Normal character processor
atnrm: mov bx,chr_set ; Get character set
cmp byte ptr [bx],ascset ; standard US ascii?
je atnrm2 ; e = yes
cmp byte ptr [bx],alcset ; Alternate character set? [bk]
jne atnrm0b ; ne = no [bk]
cmp al,('a'-1) ; replace a..z with 128d - (a..z) [bk]
jb atnrm2 ; b = out of range
cmp al,'z'
ja atnrm2 ; a = out of range
add al,(80h-('a'-1)) ; map up by 20h
jmp short atnrm2
atnrm0b:cmp byte ptr [bx],sgrset ; "Special" set?
jne atnrm1 ; No - check UK
cmp flags.vtflg,ttheath ; Heath-19?
je atnrm0a ; e = yes
cmp al,137Q ; Yes - is it in the "special" range?
jb atnrm2 ; No - just output the char in al
mov bl,al ; Yes - compute index in bx
mov bh,0
sub bx,137Q
mov al,sgrtab[bx] ; Fetch translation
jmp short atnrm2 ; Output it
atnrm0a:cmp al,94 ; H-19, in range for special graphics?
jb atnrm2 ; b = no
cmp al,126 ; too large?
ja atnrm2 ; a = too large
sub bx,94 ; H-19, offset from caret
mov bl,al
mov bh,0
sub bx,94
mov al,hgrtab[bx] ; fetch translation
jmp short atnrm2
atnrm1: cmp al,'#' ; This thing?
jne atnrm2 ; No - just output it
cmp byte ptr [bx],ukset ; Yes - UK set?
jne atnrm2 ; No - just output it
mov al,156 ; Yeah, show them our pound sign
atnrm2: cmp al,9bh ; ANSI CSI char?
jne atnrm2b ; ne = no
jmp at9bh ; yes, process ANSI CSI as "ESC ["
atnrm2b:mov dx,cursor ; get cursor virtual position
push ax ; save character
call atscur ; set cursor physical position
pop ax
cmp insmod,0 ; insert mode off?
je atnrm3 ; e = yes
push ax ; save char
call inschr ; open a char space in this line
push bx
mov bx,cursor ; get current row
mov bl,bh
mov bh,0
cmp linetype [bx],0 ; single width line?
je atnrm2a ; e = yes
call inschr ; open second space for double width
atnrm2a:pop bx
pop ax ; restore char
atnrm3: ; set cursor before writing char
mov bl,dh ; check for double characteristic
xor bh,bh ; bx = row, in bl
test anspflg,vtautop ; printing desired?
jz atnrm4d ; e = no
call pntchr ; print char in al
cmp linetype [bx],0 ; normal characteristic?
je atnrm4d ; e = yes
push ax ; save current char
mov al,' ' ; add a space for double width
call pntchr
pop ax ; recover char to be processed
atnrm4d:
cmp linetype [bx],0 ; normal characteristic?
je atnrm4a ; e = yes
push ax ; save char
shl dl,1 ; double the column number
mov ah,2 ; set cursor (bh = 0 from above)
call direction ; do Bios screen operation
pop ax ; recover the char
mov ah,9 ; Output char in al to screen
mov bh,0 ; Page zero
mov bl,curattr ; Current attribute
mov cx,1 ; Only one character
int screen
inc dl ; next column
mov ah,2 ; set cursor
call direction ; do Bios screen operation
mov al,' ' ; use a space for doubling
mov ah,9 ; Output to screen
mov bh,0 ; Page zero
mov bl,curattr ; Current attribute
mov cx,1 ; Only one character
int screen
shr dl,1 ; keep "cursor" in single units
jmp atnrm4b ; check autowrap in double width mode
atnrm4a:mov ah,9 ; Output to screen
mov bh,0 ; Page zero
mov bl,curattr ; Current attribute
mov cx,1 ; Only one character
int screen
; set physical cursor after this char
atnrm4b:test ansflgs,decawm ; Autowrap?
jz atnrm5 ; No, continue
mov cx,low_rgt ; copy logical cursor margins to cx
push bx
mov bl,dh ; get row
xor bh,bh
cmp linetype[bx],0 ; single width line?
pop bx ; pop preserves flags
je atnrm4c ; e = yes, single
shr cl,1 ; halve right column # for wide chars
atnrm4c:cmp dl,cl ; wrote in right-most column?
jb atnrm5 ; b = no
inc dl ; say want to use next column
cmp flags.vtflg,ttheath ; emulating a H-19? [uci]
je atscur ; e = yes, show wrap now. [uci]
mov cursor,dx ; virtual cursor position
ret ; exit without moving cursor from eol
atnrm5: mov dx,cursor ; Restore cursor position
inc dl ; Bump cursor
atscur: cmp dl,250 ; To left of column zero?(wide screen)
jb atscu1 ; b = no, continue
mov dl,0 ; Yes - set at column zero
atscu1: mov cx,low_rgt ; copy logical margins; cl=right col
push bx
mov bl,dh ; get row
xor bh,bh
cmp linetype [bx],0 ; single width lines?
pop bx
je atscu1a ; e = yes, single width
shr cl,1 ; halve column # for double wides
atscu1a:cmp dl,cl ; To right of right margin?
jbe atscu3 ; be = no, continue
mov dl,cl ; Yes - assume no autowrap
test ansflgs,decawm ; Autowrap?
jz atscu3 ; No, continue
mov dl,0 ; Yes - set to column zero
cmp dh,byte ptr low_rgt+1 ; at bottom of screen?
je atscu1b ; e = yes
cmp dh,mar_bot ; At bottom of scrolling region?
jl atscu2 ; l = No - bump cursor and continue
atscu1b:mov scroll,1 ; scroll count = 1 line
call atscru ; Scroll up
dec dh ; offset inc dh below
atscu2: inc dh ; Just bump it
atscu3: cmp dh,0 ; Constrain row to valid range
jge atscu4 ; ge = non-negative row, ok
mov dh,0
atscu4: cmp dh,byte ptr low_rgt+1 ; 25th line?
jle atscu5 ; le = no
mov dh,byte ptr low_rgt+1 ; set to 24th line
cmp flags.vtflg,ttheath ; emulating a Heath-19?
jne atscu4a ; ne = no [hlk]
cmp h19l25,0 ; Heath 25th line enabled?
je atscu5 ; e = no
atscu4a:inc dh ; yes, go to line 25 [hlk]
test yflags,modoff ; is mode line off?
jnz atscu8 ; nz = yes
push dx ; save cursor position
call trnmod ; no, turn it off now
and yflags,not modoff ; now say it's on (owned by host)
pop dx
atscu8: mov flags.modflg,2 ; say mode line is owned by host
mov al,yflags ; place to communicate
call telmsy ; tell msy the news
atscu5: push cx ; save cx around screen call
mov cursor,dx ; Set cursor and return
mov ah,2 ; setup for position cursor call
mov bl,dh ; get row
mov bh,0
cmp linetype [bx],0 ; single width line?
je atscu5a ; e = yes
shl dl,1 ; double the column number
call direction ; do Bios screen operation
shr dl,1 ; restore dl (logical column)
jmp short atscu5b
atscu5a:call direction ; do Bios screen operation
atscu5b:pop cx
cmp kbiflg,0 ; Is keyboard input flag set?
je atscu6 ; No - just return
test vtflags,vsmarginbell ; Yes - do we care?
jz atscu6 ; Return if no margin bell
mov dx,cursor ; Get new and old cursors
mov bx,kbicsr
cmp bh,dh ; Same row?
jne atscu6 ; No - just return
cmp bl,belcol ; Old cursor at or left of bell column?
ja atscu6 ; a = no, just return
cmp dl,belcol ; Yes - new cursor past bell column?
jbe atscu6 ; be = no, just return
call vtbell ; Yes - ring the bell
atscu6: ret
; This routine is called to check the cursor position after any kind of cursor
; positioning command. Note that cursor positioning does NOT cause scrolling
; on a VT100 (hence the need for a routine separate from this for "indexing".
;
; Call: dx/ "new" cursor position (modified cursor)
;
; Return: dx/ "new" cursor position adjusted for screen limits (if
; decom is reset), or scrolling region (if decom is set).
;
; Preserves ax, bx, and cx.
;
atccpc: push bx ; save bx and cx
push cx
atccp7: mov cx,low_rgt ; margins, cl = right margin
mov bl,dh ; get row
xor bh,bh
cmp linetype [bx],0 ; single width line?
je atccp0 ; e = yes, single width
shr cl,1 ; halve right margin for double wides
atccp0: cmp dl,250 ; To left of left margin?(wide screen)
jb atccp1 ; b = no, go check right
mov dl,0 ; No, set to left margin
atccp1: cmp dl,cl ; To right of right margin
jbe atccp2 ; be = yes, go check top
mov dl,cl ; No, set to right margin
atccp2: test ansflgs,decom ; Origin mode set?
jnz atccp5 ; Yes, can't go out of scrolling region
cmp dh,0 ; Above top of screen?
jge atccp3 ; ge = no, check bottom
mov dh,0 ; Yes, stop here
atccp3: cmp dh,byte ptr low_rgt+1 ; Below bottom of screen?
jle atccp4 ; le = no, return
mov dh,byte ptr low_rgt+1 ; Yes, stop at bottom margin
cmp flags.vtflg,ttheath ; Heath-19 mode?
jne atccp4 ; ne = no
cmp h19l25,0 ; 25th line enabled?
je atccp4 ; e = no
inc dh ; allow 25th line
atccp4: pop cx
pop bx
ret
atccp5: cmp dh,mar_top ; Above top of scrolling region?
jge atccp6 ; ge = no, check bottom
mov dh,mar_top ; Yes, stop there
atccp6: cmp dh,mar_bot ; Below bottom perhaps?
jle atccp4 ; le = no, return
mov dh,mar_bot ; Yes, stop at the bottom margin
pop cx
pop bx
ret
; This routine is called to adjust the cursor for the "indexing" like commands
; (e.g., index, reverse index, newline, etc.). It contrains the cursor, and
; indicates if scrolling is necessary, and if so, in which direction.
;
; Call: cursor/ "old" cursor position
; dx/ "new" cursor position
;
; Return: ax/ pointer to scrolling routine to call (or to a ret)
; bx/ "old" cursor position
; dx/ "new" cursor position adjusted for screen limits or
; scrolling region, depending on whether the original
; cursor position was inside or outside the scrolling
; region.
;
; On the VT100, a scroll does not occur unless the original cursor position
; was on the top or bottom margin. This routine assumes that when decom is
; set the cursor position is set to the new origin, and that no other routine
; allows the cursor to be positioned outside the scrolling region as long
; as decom is set (which is the way a real VT100 works). Note that for the
; normal case (no limited scrolling region defined) the margins are the same
; as the screen limits and scrolling occurs (as on a "normal" terminal) when
; an attempt is made to index off the screen. Preserves cx.
; Revised 16 June 1987 [jrd]
atccic: push cx
mov cx,low_rgt ; get margins, cl = right margin
mov bl,dh ; get row
xor bh,bh
cmp bl,ch ; Below screen?
ja atcci0 ; a = yes, use single width line
cmp linetype[bx],0 ; single width chars?
je atcci0 ; e = yes, single width
shr cl,1 ; halve margin for double wides
atcci0: mov ax,offset atign ; Assume no scrolling necessary
mov bx,cursor ; Get old cursor
cmp dl,250 ; To left of left margin?(wide screen)
jb atcci1 ; b = no, go check right
mov dl,0 ; No, set to left margin
atcci1: cmp dl,cl ; To right of right margin
jbe atcci2 ; be = yes, go check top
mov dl,cl ; No, set to right margin
atcci2: cmp bh,mar_top ; was old pos at scrolling top margin?
jne atcci5 ; ne = no, check other end
cmp dh,mar_top ; want to go above top margin?
jge atcci7 ; ge = no
mov scroll,1
mov ax,offset atscrd ; Yes, indicate scroll down required
mov dh,mar_top ; Set to top margin
jmp atcci7
atcci5: cmp bh,mar_bot ; Was old position at bottom margin?
jne atcci7 ; ne = no, so don't trap cursor
cmp dh,mar_bot ; want to go below?
jb atcci7 ; b = no, nothing to worry about
mov scroll,1 ; 1 line
mov ax,offset atscru ; Yes, indicate scroll up required
atcci6: mov dh,mar_bot ; Set to bottom margin
pop cx
ret
atcci7: pop cx ; old pos was outside scrolling region
jmp atccpc ; do full screen check and return
; This routine picks an attribute apart into its component "parts" - the
; base attribute for the screen and the "extras" - i.e., blink, intensity
; and underline.
;
; Call: ah/ a cursor attribute
;
; Return: ah/ base attribute for screen (07H normal, 70H reverse).
; al/ "extra" attributes
;
; Note that there is a complementary routine, addatt, for putting attributes
; back together.
;
brkatt: mov al,0 ; Clear returned "extra" attributes
cmp crt_mode,7 ; monochrome display adapter mode?
jne brkat2 ; ne = no. cut this short for color
test ah,att_low_mask ; Any of these on?
jnz brkat1 ; Yes, can't be underline
test ah,att_underline ; Underline?
jz brkat2 ; No, some kind of reverse video
or al,att_underline ; Yes, say underline
test ah,70h ;;att_reverse ; Reverse video + underline?
jz brkat1 ; No, fix up low nibble
and ah,not att_underline ; Yes, clear the underline bit in ah
jmp short brkat2 ; And forge on
brkat1: or ah,att_normal ; Normal - turn on all normal bits
brkat2: test ah,att_intensity ; Intensity attribute on?
jz brkat3 ; No - check blink
or al,att_intensity ; Yes - turn on the bit
brkat3: test ah,att_blink ; Blink on?
jz brkat4 ; No - forge on
or al,att_blink ; Yes - turn on the bit
brkat4: and ah,not(att_intensity+att_blink) ;strip blink/bold, leave color
ret
; This routine builds a cursor attribute given the base attribute for the
; screen background and the "extra" attributes we want (blink, etc.).
;
; Call: ah/ base attribute for background (07H or 70H)
; al/ "extra" attributes (89H for all three)
;
; Return: ah/ base combined with "extras".
;
addatt: test al,att_underline ; Want underline?
jz addat1 ; No - no need for hack
and ah,not att_low_mask ; Yes - clear these bits
addat1: or ah,al ; Or in the attributes
ret
; This routine is called when we want to reverse everything on the screen
; from normal to reverse video, or vice versa. It is called only when
; the decscnm attribute is changed.
;
; Call: no arguments.
;
; This routine may destroy ax-dx
;
revscn: mov dh,byte ptr low_rgt+1 ; Compute last screen offset in ax
inc dh ; One more row to catch mode line
mov dl,crt_cols ; physical width
dec dl ; and we count from 0
call scrloc
mov cx,ax ; Save it in cx for a minute
mov dx,0 ; Compute first screen offset in ax
call scrloc
sub cx,ax ; Compute number of locs to change.
add cx,2
sar cx,1 ; In 16-bit words please
push di ; Save some more acs
push es
push cx ; save word count for Topview
push ax ; save screen displacement
call scrseg ; Get address of screen in ax, es:di
pop ax ; recover displacement
add di,ax ; displacement addr of start of change
call scroff ; Turn screen off if color card
revsc1: mov ax,es:[di] ; Fetch a word
mov bl,al ; Save the character
call brkatt ; Break up the attributes
rol ah,1 ; Reverse the video
rol ah,1 ; Reverse the video
rol ah,1 ; Reverse the video
rol ah,1 ; Reverse the video
call addatt ; Put attributes back together
mov al,bl ; Restore character
mov es:[di],ax ; Stuff into screen memory
add di,2 ; Point di to next word of screen mem
loop revsc1 ; Loop for entire screen
pop cx ; recover word count for Topview
call scrsync ; synch with Topview
call scron ; Turn screen back on if color card
pop es ; Restore segment register
pop di ; And destination index
ret
; Reset-everything routine.
atreset:mov al,0 ; Make cursor disappear for a while
;; call csrtype
mov cursor,0 ; Cursor is at 0,0
mov ansflgs,0 ; reset these flags
mov escdec,0
cmp flags.vtflg,ttvt100 ; VT100?
jne atres7 ; ne = no
mov ansflgs,decanm ; turn on ANSI mode flag
atres7: mov mar_top,0 ; Reset scrolling region
mov al,byte ptr low_rgt+1
mov mar_bot,al
mov ah,vtemu.vtflgst
mov vtemu.vtflgop,ah
mov vtflags,ah
mov insmod,0 ; reset insert mode
mov h19l25,0 ; clear heath 25th line enable
mov h19ctyp,1 ; Heath-19 cursor to underline
mov anspflg,0 ; clear printer flag
mov cx,4 ; Initialize the "LEDs"
mov al,led_off ; Turn them all off
mov di,offset ansleds+6 ; Point to the "LEDs"
push es ; save es
push ds
pop es ; use datas segment for es:di below
cld ; set forward direction
rep stosb ; Do it
pop es
call disleds ; update mode line
mov vttabs,offset deftabs
call cpytabs ; Initialize tab stops
call chrdef ; Set default character set
call vtbell ; Ding bell like VT100
test vtflags,vsnewline ; Want ANSI newline mode?
jz atres1 ; No
or ansflgs,anslnm ; Yes - set it in the mode flags
atres1: test vtflags,vswrap ; How about autowrap?
jz atres2 ; No
or ansflgs,decawm ; Yes - set it in the mode flags
atres2: mov ah,att_normal ; get present normal coloring
call brkatt ; separate color and blink/bold
rol ah,1 ; reverse fore/back color fields
rol ah,1
rol ah,1
rol ah,1
call addatt ; put back blink/bold
mov att_reverse,ah ; this is the reverse video code
mov al,att_normal ; Assume normal video
test vtflags,vsscreen ; Want reverse video?
jz atres3 ; No
or ansflgs,decscnm ; Yes - turn on the mode flag
xchg al,ah ; And reverse the video
atres3: mov cx,slen ; typically 24 but do max lines
mov di,0
atres8: mov linetype[di],0 ; clear the linetype array to single
inc di ; width/height characters
loop atres8
mov curattr,al ; Give cursor and screen nice
mov scbattr,al ; attributes.
mov oldbatr,al ; place to remember long term
mov mlbattr,ah ; Give the other to the mode line
and mlbattr,not att_intensity ; turn off intensity bit
mov video_state,0 ; say normal video
mov ax,0 ; Clear entire screen
mov bx,low_rgt
mov bl,crt_cols
dec bl ; do physical screen
call atsclr
mov dx,cursor ; Set cursor to 0,0
call atscu5
call atsc ; Give saved cursor reasonable values
call atsctyp ; Set right cursor type
mov al,yflags
call telmsy ; update msy about ansflgs state
test yflags,modoff ; is mode line off?
jnz atres9 ; nz = yes
push dx ; save cursor position
call trnmod ; toggle off then on again so we
call trnmod ; use it with current coloring
pop dx
atres9: ret
; Routine to set cursor type (block, underline).
atsctyp:cmp flags.vtflg,ttheath ; Heath-19?
jne atsct0 ; ne = no
mov al,h19ctyp ; get cursor kind and on/off bit
test al,4 ; is cursor to be off?
jz atsct1 ; z = no, al has kind
mov al,0 ; turn off cursor
jmp short atsct1 ; do it
atsct0: mov al,1 ; Assume underline
test vtemu.vtflgop,vscursor ; Want block?
jnz atsct1 ; nz = no, underline
mov al,2 ; Yes
atsct1: call csrtype ; Do it
ret
; Routine to set default character set.
chrdef: mov al,vtemu.vtchset ; get setup default character set
chrde1: mov chr_sg0,al ; reset character sets
mov chr_sg1,al
mov ax,offset chr_sg0 ; select character set zero
mov chr_set,ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; end of part one ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start of part two ;;;;;;;;;;;;;;;;;;;;;;;;;;
; Routine to set special graphics character set (used in VT52 mode).
chrsgs: mov al,sgrset ; Select "graphics" set
jmp chrde1 ; Do it and return
; Control-character handling routines
atbel: call vtbell ; Just ring bell and return
ret
atbs: cmp dl,0 ; Backspace. too far?
je atbs1 ; e = at column 0 already
dec dl ; Backup cursor
atbs1: call atccpc ; Check range
jmp atscu5 ; Set cursor and return
atht: cmp flags.vtflg,ttheath ; Heath-19 mode?
je atht2 ; e = yes. handle specially
mov ch,0
mov cl,byte ptr low_rgt
cmp dl,cl ; At or beyond last column?
jae atbs1 ; Yes, check range, set cursor and ret
mov bh,0 ; Make an index
mov bl,dl ; For column
sub cl,dl ; number of columns to examine
atht1: inc bx ; Tab always moves at least one space
cmp tabs[bx],0 ; Look for non-zero
loopz atht1
mov dl,bl ; Get the new row index
jmp atbs1 ; Check range, set cursor, and return
atht2: mov dx,cursor ; Heath-19. get cursor position
add dl,8 ; tabs are every 8 columns
and dl,not 7 ; do modulo 8
cmp dl,byte ptr low_rgt ; check against right edge
jae atht3 ; ae = out of range
jmp atscu5 ; set cursor and return
atht3: test ansflgs,decawm ; doing line wrapping?
jnz atht4 ; nz = yes. wrap to next line
mov dl,byte ptr low_rgt ; else go to right margin
jmp atscu5 ; set cursor and return
atht4: inc dh ; say want next line down
xor dl,dl ; and left margin
call atccic ; index check
call ax ; do any needed scrolling
atht4a: jmp atscu5 ; reset cursor
atlf: cmp flags.vtflg,ttheath ; Heath-19 mode?
je atlf2 ; e = yes
test ansflgs,anslnm ; New-line mode?
jz atlf2 ; No - just move to next line down
mov dl,0 ; Yes - move to left margin also
atlf2: inc dh ; Index line down
call atccic ; Check indexing
call ax ; Call scrolling routine
jmp atscu5 ; Set cursor
atcr: mov dl,0 ; Go to left margin
jmp atscu5 ; Set cursor and return
atff: cmp ttstate,offset atescf ; parsing escape sequence?
jne atlf ; ne = no, do as line feed
test denyflg,200h ; is auto Tek mode disabled?
jnz atlf ; nz = yes, treat as line feed
call atsc ; save cursor and associated data
JMP TEKESC ; Jump to Tektronix Emulator, al=FF
atso: mov ax,offset chr_sg1 ; Select set G1 and return
mov chr_set,ax
ret
atsi: mov ax,offset chr_sg0 ; Select set G0 and return
mov chr_set,ax
ret
atcan: cmp ttstate,offset atnrm ; doing normal chars (vs esc seq)?
jne atcan1 ; ne = no, assume esc seq
jmp atign ; ignore ^X, ^Z in normal mode
atcan1: mov ttstate,offset atnrm ; Reset state to "normal"
mov al,sgrtab+2 ; replace CAN (^X) by checkerboard
jmp atnrm ; Process char as a normal one
atesc: mov nansarg,0 ; Clear ANSI arguments
mov al,0
mov cx,lansarg
mov di,offset ansargs
push es
push ds
pop es ; use datas segment for es:di below
cld ; set direction forward
rep stosb
pop es
and escdec,not decmode ; Clear "DEC modes" flag
mov h19mod,0 ; clear Heath-19 mode flag
mov ttstate,offset atescf ; Next state is escape follower
ret
atescf: cmp flags.vtflg,ttvt100 ; VT100?
jne atv52f ; ne = not VT100, try others
atescf0:mov cx,lansesc ; Escape follower - get table length
mov di,offset ansesc ; Point di at table
push es
push ds
pop es ; use datas segment for es:di below
cld ; set direction forward
repne scasb ; Find it
pop es
je atescf1 ; Found - now go do something with it
jmp atnorm ; Not there - just ignore it
atescf1:mov di,lansesc - 1 ; Compute word index into jump table
sub di,cx
shl di,1
jmp ansejt[di] ; Dispatch to the routine
atv52f: cmp flags.vtflg,ttheath ; Heath-19?
je ath19f ; e = yes. Use Heath esc seqs
mov ttstate,offset atnrm ; Assume state "normal" on return
mov cx,lv52esc ; Get table length
mov di,offset v52esc ; Point di at table
push es
push ds
pop es ; use datas segment for es:di below
cld ; set direction forward
repne scasb ; Find it
pop es
je atv52f1 ; Found - do something with it
ret ; Not there - just ignore it
atv52f1:mov di,lv52esc - 1 ; Compute word index into jump table
sub di,cx
shl di,1
jmp v52ejt[di] ; Dispatch to the routine
ath19f: mov ttstate,offset atnrm ; Assume state "normal" on return
test ansflgs,decanm ; ansi mode?
jnz atescf0 ; nz = yes, use ansi table
mov cx,lh19esc ; Get table length
mov di,offset h19esc ; Point di at table
push es
push ds
pop es ; use datas segment for es:di below
cld ; set direction forward
repne scasb ; Find it
pop es
je ath19f1 ; Found - do something with it
ret ; Not there - just ignore it
ath19f1:mov di,lh19esc - 1 ; Compute word index into jump table
sub di,cx
shl di,1
jmp h19ejt[di] ; Dispatch to the routine
at9bh: call atesc ; 9bH char (ANSI CSI == ESC [)
mov ttstate,offset atpaa ; next state is parse ansi sequences
ret
; Escape follower routines.
atcsi: mov ttstate,offset atpaa ; Next state is parse ansi args
ret
atpaa: test al,80h ; high bit set?
jz atpaa6 ; z = no
and al,7fh ; strip high bit
cmp al,' ' ; control code remainder?
jae atpaa6 ; ae = no, use 7 bit result
mov ttstate,offset atnrm ; reset state to normal text
jmp atctrl ; execute 7 bit control code
atpaa6: cmp al,'0' ; A digit?
jb atpaa1 ; No - just ignore it
cmp al,'9' ; Maybe - A separator or final char?
ja atpaa2 ; Perhaps - go check it out
mov cl,al ; A digit - convert ASCII to binary
sub cl,'0'
mov ch,0
mov bl,nansarg ; put index in bx [dlk]
xor bh,bh
mov al,ansargs[bx] ; Pick up what we've done so far [dlk]
shl al,1 ; multiply by 10. 2 * al
mov ah,al ; save
shl al,1 ; 4 * al
shl al,1 ; 8 * al
add al,ah ; 10 * al
mov ah,0 ; clear high field
add ax,cx ; add in this digit [dlk]
cmp ax,0feh ; max value is 0ffh [dlk]
jbe atpaa0 ; be = ok [dlk]
mov al,0ffh ; set to max value [dlk]
atpaa0: mov ansargs[bx],al ; Put result back for next time [dlk]
atpaa1: ret ; And return
atpaa2: cmp al,'?' ; The deadly question mark?
jne atpaa2a ; No - check further
or escdec,decmode ; Yes - say DEC modes are coming
ret ; And return
atpaa2a:cmp al,'>' ; Heath private mode?
jne atpaa3 ; ne = no
cmp flags.vtflg,ttheath ; emulating a Heath-19?
jne atpaa3 ; ne = no, ignore this sequence
mov h19mod,1 ; say Heath mode sequence follows
ret
atpaa3: cmp al,';' ; Argument separator?
jne atpaa4 ; No - check for final char
mov al,nansarg ; Get argument index
inc al ; Bump it
cmp al,lansarg ; Too many?
jl atpa3a ; l = no, continue
mov ttstate,offset atnrm ; Reset state to "normal"
ret ; and pretend all is well
; [jrd] jmp atcan ; Yes - abandon sequence on error
atpa3a: mov nansarg,al ; Save it
ret
atpaa4: mov cx,lanstab
mov di,offset anstab ; Look for it in the table
push es
push ds
pop es ; use datas segment for es:di below
cld ; set direction forward
repne scasb
pop es
je atpaa5 ; Found it - go dispatch
cmp al,40h ; in range for a legal terminator?
jb atpaa4a ; b = not in range, ignore
cmp al,7eh ; other end of the range
ja atpaa4a ; a = out of range, ignore
; in range, absorb and become normal
mov ttstate,offset atnrm ; Put state back to normal
atpaa4a:ret ; Just return if it is unknown
atpaa5: mov ttstate,offset atnrm ; Put state back to normal
mov di,lanstab - 1 ; Compute word index into jump table
sub di,cx
shl di,1
jmp ansjmp[di] ; Off into the wild blue
atind: inc dh ; Index - move cursor down one
atind1: call atccic ; Check cursor position
call ax ; Scroll if necessary
mov ttstate,offset atnrm ; Reset state
jmp atscu5 ; Set cursor, etc. and return
atnel: mov dl,0 ; Next line - sort of like CRLF
inc dh ; ... all in one command
jmp atind1 ; Check cursor, etc., and return
atri: dec dh ; Reverse index
jmp atind1 ; Check cursor, etc., and return
athts: call atccpc ; Make sure we have valid column number
mov dh,0 ; Zap row
mov al,0FFH ; Indicates a tab stop
mov di,dx ; Dumb specialized registers
mov tabs[di],al ; Store it
jmp atnorm ; Reset state and return
atsc: mov si,offset curattr ; Save cursor, attribute, char set etc
mov di,offset savecu ; Place to save the stuff
mov cx,lsavecu ; Length of save area
push es ; save es
push ds
pop es ; set es to datas segment
cld
rep movsb ; Save it
pop es
mov cl,ansflgs ; Save a copy of the flags
mov savflgs,cl
jmp atnorm ; Reset state and return
atrc: mov si,offset savecu ; Restore cursor, attributes, etc.
mov di,offset curattr ; Where stuff goes
mov cx,lsavecu ; Length of save area
push es ; save es
push ds
pop es ; set es to datas segment
cld
rep movsb ; Put the stuff back
pop es
mov al,savflgs ; Get saved flags
xor al,ansflgs ; Exclusive-or with current flags
test al,decscnm ; Did screen mode change?
jz atrc1 ; No, just reset saved flags and leave
mov ah,curattr ; Get cursor attribute that was saved
call brkatt ; Break into background & extra stuff
rol ah,1 ; Reverse the background
rol ah,1 ; Reverse the background
rol ah,1 ; Reverse the background
rol ah,1 ; Reverse the background
call addatt ; Put it all back together
mov curattr,ah ; Store
atrc1: mov al,ansflgs ; Reset flags in case called again
and al, not(decckm+deckpam+decom) ; remove old bits [dlk]
and savflgs,(decckm+deckpam+decom) ; remove all but new bits [dlk]
or al,savflgs ; restore saved bits [dlk]
mov ansflgs,al ; update these flags [dlk]
mov savflgs,al
mov dx,cursor ; Get cursor
mov kbiflg,0 ; Don't bother them with beeps here
call atscu5 ; Set cursor
jmp atnorm ; Reset state and return
atkpam: or ansflgs,deckpam ; Turn on the bit
mov al,yflags
call telmsy ; inform msy of new state
jmp atnorm ; Reset state and return
atkpnm: and ansflgs,not deckpam ; Turn off the bit
mov al,yflags
call telmsy ; inform msy of new state
jmp atnorm ; Reset state and return
atris: call atreset ; Reset everything
jmp atnorm ; And state too, return, etc
atsg0: mov ttstate,offset atsg01 ; Setup to get last character
ret
atsg01: call atscs ; Get code for character set
mov chr_sg0,al ; Store it
jmp atnorm ; Reset state etc. and return
atsg1: mov ttstate,offset atsg11 ; Setup to get last character
ret
atsg11: call atscs ; Get code for character set
mov chr_sg1,al ; Store it
jmp atnorm ; Reset state etc. and return
atscs: cmp al,'A' ; UK ASCII set?
jne atscs1 ; No
mov al,ukset ; Yes - give them that and return
ret
atscs1: cmp al,'B' ; US ASCII set?
jne atscs3 ; No
atscs2: mov al,ascset ; Yes - give them that and return
ret
atscs3: cmp al,'0' ; Special graphics set?
jne atscs4 ; ne = no
mov al,sgrset ; Yes - say that's what it is
ret
atscs4: cmp al,'1' ; alt char ROM, std char set?
jne atscs5 ; ne = no
mov al,alcset ; use Alternate character set
ret
atscs5: cmp al,'2' ; alt char ROM, special graphics?
jne atscs2 ; ne = no, use US ASCII
mov al,sgrset ; set graphics
ret
; ESC # Pn series
atsdhl: mov ttstate,offset atsdbl ; set up to parse argument
ret
atsdbl: cmp al,'3' ; Double high lines. Top half?
je atsdh2 ; e = yes
cmp al,'4' ; bottom half?
je atsdh2 ; e = yes
cmp al,'5' ; restore line to single width?
je atsdh1 ; e = yes
cmp al,'6' ; double width single height?
je atsdh2 ; e = yes
cmp al,'8' ; screen alignment?
je atsdh8 ; e = yes
jmp atnorm ; else ignore
atsdh1: call linesgl ; set line to single width
jmp atnorm
atsdh2: call linedbl ; expand the line to double width
jmp atnorm ; set state to normal and ret
atsdh8: call atalign ; do screen alignment
jmp atnorm
atpriv: mov ttstate,offset atnorm ; ignore next char
ret ; and return to normal afterward
atalign proc near ; Fill screen with 'E'
call atreset ; clear system
or ansflgs,decawm ; set wrap
mov cl,byte ptr low_rgt ; number of columns-1
inc cl
mov al,byte ptr low_rgt+1 ; number of rows-1
inc al
mul cl ; ax = number of chars on screen
mov cx,ax
atalig1:push cx
mov al,'E' ; write screen full of E's
call atnrm ; write the 'E'
pop cx
loop atalig1 ; cx times
ret
atalign endp
; This routine may be used to repeat a call to a selected action routine
; for all of the ANSI parameters given in a call. When the action routine
; is called, si will contain the index for the current ANSI parameter (i.e.,
; the current ANSI parameter may be gotten using ansargs[si] for an effective
; address). The action routine may modify any ACs it wants, but cx, si,
; and di are preserved over the call to the action routine, so these may
; not be used for building return values for the original caller. Note that
; if there are no ANSI parameters, the effect is the same as if one ANSI
; parameter with a value of zero was given.
;
; Call: di/ offset of action routine in code seqment
;
atreps: mov cl,nansarg ; Pick up number of parameters
inc cl ; Zero parms is same as 1 zero parm
mov ch,0
mov si,0 ; Init parm index
atrep1: push cx ; Save important acs
push si
push di
call di ; Call indicated routine
pop di ; Restore acs
pop si
pop cx
inc si ; Advance to next parameter
loop atrep1 ; Loop for all
ret ; And return
; Final char (ANSI) routines.
atcup: mov dh,ansargs ; Get the two arguments
mov dl,ansargs+1
cmp dh,0 ; Zero line number?
jne atcup1 ; No - continue
mov dh,1 ; Yes - default to one
atcup1: cmp dl,0 ; Ditto for row
jne atcup2
mov dl,1
atcup2: dec dh ; Now normalize
dec dl
test ansflgs,decom ; Origin mode?
jz atcup4 ; No - skip this stuff
add dh,mar_top ; Yes - it was relative to top margin
jno atcup4 ; If no overflow, continue
mov dh,byte ptr low_rgt+1 ; Otherwise just set to screen bottom
atcup4: cmp dh,byte ptr low_rgt+1 ; going to 25th line? [hlk]
jbe atcup5 ; be = no [dlk]
cmp flags.vtflg,ttheath ; emulating a Heath-19?
jne atcup6 ; ne = no [hlk]
cmp h19l25,0 ; Heath 25th line enabled?
je atcup5 ; e = no
atcup6: mov dh,byte ptr low_rgt+1 ; bottom normal line
inc dh ; the 25th line
jmp atscu4 ; set cursor position and return
atcup5: call atccpc ; Check position
jmp atscu5 ; Set cursor position and return
atcuarg:mov al,ansargs ; Get a cursor move argument
cmp al,0 ; Zero?
jne atcua1 ; No - return
mov al,1 ; Yes - default to one
atcua1: ret ; Return
; Disallow movement to 25th line
atcuu: call atcuarg ; Get cursor move argument in al
sub dh,al ; Compute new cursor position
jnc atcuu1 ; nc = ok [dlk]
xor dh,dh ; overflow, restrict range. [dlk]
atcuu1: call atccic ; check indexing, ignore action in ax
jmp atscu5 ; set the cursor at its new position
atcud: call atcuarg ; Get the argument
add dh,al ; Compute new cursor position
jnc atcud1 ; nc = ok [dlk]
mov dh,byte ptr low_rgt+1 ; default bottom [dlk]
atcud1: call atccic ; check indexing, ignore action in ax
jmp atscu5 ; set the cursor at its new position
; Allow horiz movement on 25th line
atcuf: call atcuarg ; Get the argument
add dl,al ; Compute new cursor position
jnc atcup4 ; If no carry, continue [dlk]
mov dl,byte ptr low_rgt ; Else set to right margin
jmp atcup4 ; Check/set cursor, return
atcub: call atcuarg ; Get the argument
sub dl,al ; Compute new cursor position
jnc atcup4 ; If no carry, continue [dlk]
mov dl,0 ; Else set to left margin
jmp atcup4 ; Check/set cursor, return
ated: mov di,offset ated0 ; Routine to process parm
call atreps ; Do all selected parms
ret
ated0: cmp ansargs[si],0 ; Was arg zero?
jne ated2 ; No - continue
mov ax,dx ; Yes - erase from cursor to end of screen
cmp dx,0 ; cursor at home position?
je atedcom ; e = yes, roll screen before clear
push dx ; save dx
mov bl,dh ; get row number
xor bh,bh
cmp linetype [bx],0 ; single width line?
je ated0a ; e = yes
shl dl,1 ; physical column is twice logical
ated0a: or dl,dl ; starting at left margin?
je ated0b ; e = yes, this goes to single width
inc bl ; else start on next line
ated0b: cmp bl,byte ptr low_rgt+1 ; at the end of the screen?
ja ated0c ; a = yes, stop singling-up
mov byte ptr linetype [bx],0 ; set to single width
inc bx
jmp short ated0b ; loop, reset lines to end of screen
ated0c: mov bx,low_rgt ; erase from cursor to end of screen
mov bl,crt_cols
dec bl ; do physical screen width
call vtsclr ; Clear it
pop dx ; restore dx
ated1: ret
ated2: cmp ansargs[si],1 ; Was arg one?
jne ated3 ; No - continue
mov ax,0 ; Yes - erase from start of screen
; to cursor, inclusive
xor bx,bx ; start at top row (0)
ated2b: cmp bl,dh ; check rows from the top down
jae ated2c ; ae = at or below current line
mov byte ptr linetype [bx],0; set line to single width
inc bx ; inc row
jmp short ated2b ; look at next line
ated2c: or dl,dl ; at left margin of current line?
jne ated2d ; ne = no, leave line width intact
mov byte ptr linetype [bx],0 ; convert to single width
ated2d: mov bl,dh ; get row number
xor bh,bh
cmp linetype [bx],0 ; single width line?
je ated2a ; e = yes
shl dl,1 ; physical column is twice logical
ated2a: mov bx,dx ; cursor position to bx
call vtsclr ; Clear it
ret
ated3: cmp ansargs[si],2 ; Was arg two?
jne ated1 ; ne = no, else erase entire screen
; entry to roll screen before erasing
atedcom:mov al,byte ptr low_rgt+1 ; number of lines on screen
mov scroll,al
call atscru ; scroll them up before erasure
; removes double w/h lines too.
mov ax,0 ; erase from here (home)
mov bx,low_rgt
mov bl,crt_cols
dec bl ; physical width (to here)
call vtsclr ; clear screen
ret
atel: mov di,offset atel0 ; Get routine to call
call atreps ; Repeat for all parameters
ret
atel0: cmp ansargs[si],0 ; Was arg zero?
jne atel2 ; No - continue
mov ax,dx ; Yes - erase from cursor
mov bh,dh ; ...to end of line, inclusive
push bx
mov bl,bh ; get row
mov bh,0
cmp linetype [bx],0 ; single width line?
je atel0a ; e = yes
shl al,1 ; physical column is twice logical
atel0a: pop bx
mov bl,byte ptr low_rgt
call vtsclr ; Clear it
atel1: ret
atel2: cmp ansargs[si],1 ; Was arg one?
jne atel3 ; No - continue
mov ah,dh ; Yes - erase from start of line
mov al,0
mov bx,dx ; ...to cursor, inclusive
push bx
mov bl,dh ; get row
mov bh,0
cmp linetype [bx],0 ; single width line?
pop bx ; pop does not affect flags
je atel2a ; e = yes
shl bl,1 ; physical column is twice logical
atel2a:
call vtsclr ; Clear it
ret
atel3: cmp ansargs[si],2 ; Was arg two?
jne atel1 ; No - ignore it
mov ah,dh ; Yes - erase entire line
mov al,0
mov bh,dh
mov bl,byte ptr low_rgt
mov bl,crt_cols
dec bl ; physical line
call vtsclr ; Clear it
ret
atsgr: mov ah,curattr ; Get current cursor attribute
call brkatt ; Break it apart
mov di,offset atsgr1 ; Routine to call
call atreps ; Repeat for all parms
call addatt ; Put the attributes back together
mov curattr,ah ; Store
ret
atsgr1: mov bl,ansargs[si] ; Fetch an argument
cmp bl,0 ; Zero?
jne atsgr2 ; No
mov al,0 ; Yes - clear the "extras"
mov ah,scbattr ; And reset background
and ah,77h ; clear blink/bold here
mov video_state,0 ; say normal video now
ret
atsgr2: cmp bl,1 ; One?
jne atsgr3 ; No
or al,att_intensity ; Yes - set bold
ret
atsgr3: cmp bl,4 ; Four? Underline. Mods by [jrd]
jne atsgr4 ; ne = no
or al,att_underline ; Yes, set underscore
cmp crt_mode,7 ; monochrome display adapter mode?
je atsgr3a ; e = yes. Otherwise reverse video
; use reversed video rather than blue on black
and al,not att_underline ; clear underline and
rol ah,1 ; reverse the colors
rol ah,1
rol ah,1
rol ah,1
atsgr3a:ret
atsgr4: cmp bl,5 ; Five?
jne atsgr5 ; No
or al,att_blink ; Yes - set blink
ret
atsgr5: cmp bl,7 ; Seven?
jne atsgr6 ; No - just ignore it
cmp video_state,0 ; is video normal?
jne atsgr6 ; ne = no, reversed already, ignore
rol ah,1 ; reverse the colors
rol ah,1
rol ah,1
rol ah,1
mov video_state,1 ; say reversed now
ret
atsgr6: cmp bl,30 ; ANSI color series?
jb atsgrx ; b = no
cmp bl,37 ; foreground set (30-37)?
ja atsgr7 ; a = no, try background set
sub bl,30 ; take away the bias
and ah,not 07H ; clear foreground bits
test bl,1 ; ANSI red?
jz atsgr6a ; z = no
or ah,4 ; IBM red foreground bit
atsgr6a:test bl,2 ; ANSI & IBM green?
jz atsgr6b ; z = no
or ah,2 ; IBM green foreground bit
atsgr6b:test bl,4 ; ANSI blue?
jz atsgr6c ; z = no
or ah,1 ; IBM blue foreground bit
atsgr6c:ret
atsgr7: cmp bl,40 ; background color set?
jb atsgrx ; b = no
cmp bl,47 ; background set is 40-47
ja atsgrx ; nb = no, not a color command
sub bl,40 ; take away the bias
and ah,not 70H ; clear background bits
test bl,1 ; ANSI red?
jz atsgr7a ; z = no
or ah,40h ; IBM red background bit
atsgr7a:test bl,2 ; ANSI & IBM green?
jz atsgr7b ; z = no
or ah,20h ; IBM green background bit
atsgr7b:test bl,4 ; ANSI blue?
jz atsgrx ; z = no
or ah,10h ; IBM blue background bit
atsgrx: ret
attbc: call atccpc ; Make sure cursor is kosher
mov di,offset attbc0 ; Routine to call
call atreps ; Do for all parms
ret
attbc0: cmp ansargs[si],0 ; Was argument zero?
jne attbc2 ; No - check further
mov dh,0 ; Zap row for indexing
mov di,dx
mov tabs[di],0 ; clear tab stop
attbc1: ret
attbc2: cmp ansargs[si],3 ; Was arg 3 (clear all tab stops)?
jne attbc1 ; No - just ignore it
mov cx,swidth ; Get ready to zap swidth columns
mov di,offset tabs ; Point to the tab stop table
mov al,0 ; zero indicates no tab stop
push es ; save es
push ds
pop es ; use datas segment for es:di below
cld ; set direction forward
rep stosb ; Blit full of zeros
pop es
ret
atstbm: mov al,ansargs ; Get the two line number args
mov ah,ansargs+1
cmp al,0 ; Was first zero?
jne atstb1 ; No - continue
mov al,1 ; Yes - default is one
atstb1: cmp ah,0 ; Was second zero?
jne atstb2 ; No - continue
mov ah,byte ptr low_rgt+1 ; Yes - default is last line on screen
inc ah
atstb2: dec al ; Normalize to our coord. system
dec ah
cmp ah,al ; Is size of region at least two lines?
jbe atstb3 ; be = if not, indicate an error
cmp al,0 ; Check against screen limits
jl atstb3
cmp ah,byte ptr low_rgt+1
ja atstb3
mov mar_top,al ; Set the limits
mov mar_bot,ah
mov dx,0 ; Home cursor
call atccpc ; Check cursor (get it inside window)
jmp atscu5 ; Set cursor position and return
atstb3: ret ; ignore bad requests
;;; jmp atcan ; Indicate error and return
atda: cmp ansargs,0 ; Was argument zero?
je decid ; Yes - send the i.d. string
ret ; No - only an echo
at52id: mov ttstate,offset atnrm ; ensure state is correct
decid: mov cx,20 ; assumed length of asciiz string
mov si,offset dastr ; Point to the string
cmp flags.vtflg,ttvt100 ; VT100?
je decid1 ; e = yes
mov si,offset v52str ; No - try VT52 i.d.
cmp flags.vtflg,ttvt52 ; Heath-19 mode?
je decid1 ; e = yes
mov si,offset h19str ; say Heath-19
decid1: cld
lodsb ; Get a byte
cmp al,0 ; end of string?
je decid2 ; e = yes
push cx ; Save the important registers
push si
call prtbout ; Send it to port with no local echo
pop si
pop cx
loop decid1 ; Loop for all characters
decid2: ret
atll: mov di,offset atleds ; Get pointer to routine to call
call atreps ; Repeat for selective parameters
ret
atleds: cmp ansargs[si],0 ; Zero argument?
jne atled3 ; No - check further
mov cx,4 ; Reset the "LEDs"
mov al,led_off ; to all off
mov di,offset ansleds+6 ; Point to the "LEDs"
push es ; save es
push ds
pop es ; make es:di point to datas seg
cld ; move forward
rep stosb
pop es
atled1: call disleds ; Update "LEDs" display and return
atled2: ret
atled3: mov al,ansargs[si] ; Get the argument
cmp al,1 ; Must be .GE. 1
jb atled2 ; If not just ignore it. [dlk]
cmp al,4 ; Must be .LE. 4
ja atled2 ; Ignore if not so. [dlk]
dec al ; Zero base it
cbw ; Convert to index in ax
mov di,ax ; Dumb specialized registers
add al,'1' ; add ascii offset for digit
mov ansleds[di+6],al ; Turn the "LED" on by storing digit
jmp atled1 ; Update display and return
atreqt: cmp ansargs,0 ; Want report?
je atreq1 ; Yes - give report
cmp ansargs,1 ; Want report?
je atreq1 ; Yes - give the report
ret ; Gee, must have been an echo
atreq1: mov al,escape ; Send an escape to start off
call prtbout
mov al,'[' ; Then one of these
call prtbout
mov al,'3' ; We only report on request
cmp ansargs,0 ; was argument a zero?
jne atreq1a ; ne = no
mov al,'2' ; yes
atreq1a:call prtbout
mov al,';' ; Separate
call prtbout
mov bl,parcode ; Get the parity code
mov bh,0
mov al,partab[bx] ; Get VT100 parity code
push ax ; save parity code
call prtnout ; Send number to the port.
mov al,';' ; Separate
call prtbout
mov al,'2' ; Assume 7 data bits
pop bx ; get parity code into bl
cmp bl,1 ; is parity none?
jne atreq2 ; ne = no, so 7 data bits
test flags.remflg,d8bit ; 8 bit display?
jz atreq2 ; z = no
mov al,'1' ; must be eight
atreq2: call prtbout ; Send it to the port
mov al,';' ; Separate
call prtbout
mov bl,baudidx ; Baud rate index
mov bh,0
mov al,baudtab[bx] ; Get DEC baud rate code
push ax
call prtnout ; Send it to the port
mov al,';' ; Separate
call prtbout ; Send it to the port
pop ax
call prtnout ; Send it to the port
mov al,';' ; Separate
call prtbout
mov al,'1' ; Clock rate multiplier is always 1
call prtbout
mov al,';' ; Separate (gasp - for the last time)
call prtbout
mov al,'0' ; Flags are always zero (no STP)
call prtbout
mov al,'x' ; Finally, say what this all was
call prtbout
ret
atdsr: mov di,offset atdsr1 ; Routine to call
call atreps ; Do for all parms
ret
atdsr1: cmp ansargs[si],5 ; Want status?
je rpstat ; Yes - report status
cmp ansargs[si],6 ; Want cursor position?
je rpcup ; Yes - do it
cmp ansargs[si],15 ; Printer status?
je rpstap ; e = yes, do so
ret ; No - must have been an echo
rpstat: mov al,escape ; Tell them we think we are OK
call prtbout
mov al,'['
call prtbout
mov al,'0'
call prtbout
mov al,'n'
call prtbout
ret
rpstap: test escdec,decmode ; Printer status report from
jz rpstap3 ; ESC [ ? 15 n request
mov al,escape
call prtbout
mov al,'['
call prtbout
mov al,'?'
call prtbout
mov al,'1'
call prtbout
mov ah,ioctl ; get printer status, via DOS
mov al,7 ; status for output
push bx
mov bx,4 ; std handle for system printer
int dos
pop bx
jc rpstap1 ; c = call failed
cmp al,0ffh ; code for Ready
jne rpstap1 ; ne = not ready
mov al,'0' ; ready, send final digit
jmp rpstap2
rpstap1:mov al,'3' ; not ready, say printer disconnected
rpstap2:call prtbout
mov al,'n' ; final char of response
call prtbout
rpstap3:ret
rpcup: mov al,escape ; Cursor position - send an escape
call prtbout
mov al,'[' ; And one of these
call prtbout
mov al,byte ptr cursor+1 ; Get row
inc al ; They use coords that start at 1
test ansflgs,decom ; Origin mode set?
jz rpcup1 ; No - continue
sub al,mar_top ; Yes - subtract off top margin
rpcup1: call prtnout ; Output the number
mov al,';' ; Separate
call prtbout
mov al,byte ptr cursor ; Now get the column number
inc al ; Their coords start at 1
call prtnout ; Send it off to the port
mov al,'R' ; Finally end it with this
call prtbout
ret
; ESC [ ? xxx h/l series
atrm: mov modeset,0 ; Say we are resetting modes
mov di,offset atrsm ; Reset/set modes
call atreps ; Repeat for all parms
test ansflgs,decanm ; Did this get reset?
jnz atrm1 ; No - return
cmp flags.vtflg,ttheath ; were we a Heath-19?
je atrm0 ; e = yes, don't change terminal types
mov flags.vtflg,ttvt52 ; Yes. Say VT52 now
atrm0: call chrdef ; Yes - set default char sets
call atsc ; Save cursor status
call disleds ; update terminal type
atrm1: ret
atsm: mov modeset,1 ; Say we are setting modes
mov di,offset atrsm ; Reset/set modes
call atreps ; Repeat for all parms
ret
atrsm: mov al,ansargs[si] ; Pick up the argument
test escdec,decmode ; Is this DEC private mode ([ ?)stuff?
jnz atrsm1 ; nz = yes - go check it out
cmp h19mod,0 ; Heath-19 private mode ([ >)?
je atrsma ; e = no
jmp htrsm1 ; yes, do Heath specific things
atrsma: cmp al,20 ; No - ANSI new-line mode?
jne atrsm0 ; but try insert mode
and vtemu.vtflgop,not vsnewline ; assume resetting
cmp modeset,0 ; resetting?
je atrsmb ; e = yes
or vtemu.vtflgop,vsnewline ; setting
atrsmb: mov al,anslnm ; Yes - get the bit
call atrsflg ; Set or reset it
ret
atrsm0: cmp al,4 ; toggle insert mode?
jne atrsmc ; ne = no
mov al,modeset ; set/reset insert mode
mov insmod,al ; store it
ret
atrsmc: cmp al,12 ; 12? Control local echo
jne atrsmx ; ne = no
cmp modeset,0 ; resetting mode (ESC [ 12 l)?
jne atrsmc1 ; ne = no
or ansflgs,dececho ; remember state here too
or yflags,lclecho ; (l) turn on local echoing
jmp short atrsmc2
atrsmc1:and yflags,not lclecho ; (h) turn off local echoing
and ansflgs,not dececho
atrsmc2:mov al,yflags
call telmsy ; inform msy about echoing state
test yflags,modoff ; is mode line off?
jnz atrsmx ; nz = yes
push dx ; save cursor position
call trnmod ; toggle off then on again so we
call trnmod ; use it with current coloring
pop dx
atrsmx: ret
atrsm1: cmp al,1 ; Cursor keys mode?
jne atrsm2 ; No - check some more
mov al,decckm ; Yes - get the bit
jmp atrsflg ; Set or reset it and return
atrsm2: cmp al,7 ; Auto-wrap?
jne atrsm3 ; No - check some more
and vtemu.vtflgop,not vswrap ; assume resetting line wrap
cmp modeset,0 ; resetting?
je atrsm2a ; e = yes
or vtemu.vtflgop,vswrap ; set the bit
atrsm2a:mov al,decawm ; Yes - get the bit
jmp atrsflg ; Set or reset it and return
atrsm3: cmp al,6 ; Origin mode?
jne atrsm4 ; No - check for video change
jmp atrsom ; Yes - change decom and return
atrsm4: cmp al,5 ; Change the video?
jne atrsm5 ; No - check for VT52 mode set/reset
jmp atrsscnm ; Yes - change it if we have to and ret
atrsm5: cmp al,2 ; Change VT52 compatibility mode?
jne atrsm6 ; No - ignore unknown DEC private modes
cmp flags.vtflg,ttheath ; Heath-19 mode?
je atrsm5a ; e = yes, handle specially
mov al,ascset ; return to US ascii graphics sets
mov chr_sg0,al ; Store it
mov chr_sg1,al ; Store it
mov al,decanm ; Yes - get the flag
jmp atrsflg ; Set or reset it and return
atrsm5a:mov modeset,0 ; Heath-19 ESC [ ? 2 h, reset ansi
mov al,decanm ; the flag needing adjustment
jmp atrsflg ; reset the flag and return
atrsm6: cmp al,3 ; 132/80 column mode change?
jne atrsm7 ; ne = no
push chr_set ; save character set pointer
push word ptr chr_sg0 ; and the G0/G1 values
mov al,ansflgs ; these flags
mov ah,vtflags
push ax
mov al,curattr ; and current video attributes
push ax
mov al,modeset ; pass set/reset request to chgdsp[dlk]
call chgdsp ; call Change Display proc in msy [dlk]
call scrmod ; get current screen mode
cmp modeset,1 ; want 132 cols?
jne atrsm6n ; ne = no, so use 80 columns
mov al,crt_cols ; get current physical screen width
dec al ; we count from column 0 here
mov byte ptr low_rgt,al ; screen capability
mov linelen,131 ; say using wide screen, if possible
jmp short atrsm6e
atrsm6n:mov linelen,79 ; say using 80 columns
cmp byte ptr low_rgt,79 ; want 80 cols, is it wider?
jbe atrsm6e ; be = no
mov byte ptr low_rgt,79 ; narrow down to 80 columns
atrsm6e:CALL ATRES2 ; do partial reset of emulator
pop ax
mov curattr,al ; restore saved items
pop ax
mov ansflgs,al
mov vtflags,ah
pop word ptr chr_sg0 ; restore the G0/G1 values
pop chr_set ; and character set pointer
mov dl,byte ptr low_rgt+1 ; text lines (leave status line intact)
mov mar_top,0
mov mar_bot,dl ; reset scrolling region
xor dx,dx ; new cursor position is 0,0
mov cursor,dx
jmp atscu5 ; place it there and return
atrsm7: cmp al,18 ; 18? 18 & 19 = printer support
jne atrsm8 ; ne = no
cmp modeset,0 ; resetting?
jne atrsm7a ; ne = no, setting
and anspflg,not vtffp ; no form feed after printing
ret
atrsm7a:or anspflg,vtffp ; use form feed after printing
ret
atrsm8: cmp al,19 ; 19?
jne atrsm9 ; ne = no
cmp modeset,0 ; resetting?
jne atrsm8a ; ne = no, setting
and anspflg,not vtextp ; reset print region to scrolling reg
ret
atrsm8a:or anspflg,vtextp ; set print region to whole screen
ret
atrsm9: cmp al,34 ; ESC [ ? 34 h/l? Invoke special macro
jne atrsm10 ; ne = no
cmp modeset,0 ; resetting?
jne atrsm9a ; ne = no, setting
jmp vtrmac ; jump to perform on-line macro
; code is located in file msy
atrsm9a:jmp vtsmac ; do set macro
atrsm10:cmp al,38 ; 38? Enter Tek sub-mode. VT340 seq
jne atrsm11 ; ne = no
cmp modeset,1 ; setting mode (ESC [ ? 38 h)?
jne atrsm11 ; ne = no, ignore sequence
test denyflg,200h ; is auto Tek mode disabled?
jnz atrsm11 ; nz = yes, just ignore command
call atsc ; save cursor and associated data
mov al,0 ; enter with this received character
JMP TEKEMU ; Jump to Tektronix Emulator, al=null
atrsm11:ret
; Heath-19 ESC [ > Ps h or l where Ps = 1, 4, 7, or 9
htrsm1: cmp al,1 ; 25th line?
jne htrsm4 ; ne = no
mov al,modeset ; set/reset flag
mov h19l25,al
cmp al,0 ; resetting? Mods from Dave Tweten
jne htrsmx ; ne = no, enabling. we are done
mov ah,byte ptr low_rgt+1 ; point to status (25th) line
inc ah ; which is here
xor al,al ; from column 0
mov bh,ah ; to same line
mov bl,crt_cols ; physical width
dec bl ; we count from 0
jmp vtsclr ; disabling status line clears it
htrsm4: cmp al,4 ; block/line cursor?
jne htrsm5 ; ne = no
and h19ctyp,4 ; save on/off bit (4)
cmp modeset,0 ; reset?
je htrsm4a ; e = yes
or h19ctyp,2 ; remember block kind here
jmp atsctyp
htrsm4a:or h19ctyp,1 ; remember underline kind here
jmp atsctyp
htrsm5: cmp al,5 ; on/off cursor?
jne htrsm7 ; ne = no
cmp modeset,0 ; on?
je htrsm5a ; e = yes
or h19ctyp,4 ; remember off state in this bit
jmp atsctyp
htrsm5a:and h19ctyp,not 4 ; set cursor on
jmp atsctyp
htrsm7: cmp al,7 ; alternate application keypad?
jne htrsm9 ; ne = no
mov al,deckpam ; get keypad application mode bit
jmp atrsflg ; set or reset appl keypad mode
htrsm9: cmp al,9 ; auto newline mode? (add cr to lf)
jne htrsmx ; ne = no
mov al,anslnm ; get the bit
jmp atrsflg ; set or reset newline mode
htrsmx: ret ; ignore the code
atrsflg:cmp modeset,0 ; Want to reset
je atrsf1 ; Yes - reset it
or ansflgs,al ; No, set. OR in the flag
test al,decanm ; Changing terminal type?
jz atrsfx ; z = no
cmp flags.vtflg,ttheath ; in Heath-19 mode?
je atrsfx ; e = yes, don't flip terminal kinds
mov flags.vtflg,ttvt100 ; say VT100 now
jmp short atrsfx
atrsf1: not al ; Complement
and ansflgs,al ; Clear the bit
not al ; recover the bit
test al,decanm ; Changing terminal type?
jz atrsfx ; z = no
cmp flags.vtflg,ttheath ; in Heath-19 mode?
je atrsfx ; e = yes, don't flip terminal kinds
mov flags.vtflg,ttvt52 ; say VT52 now
atrsfx: push ax
mov al,yflags
call telmsy ; tell msy file about new state
pop ax
ret
atrsom: cmp modeset,0 ; Clearing DEC origin mode?
jne atrsom1 ; ne = no, setting
and ansflgs,not (decom) ; clear the bit
mov dx,0 ; go to the home position
jmp atscu5 ; set cursor and return
atrsom1:or ansflgs,decom ; Set Origin mode
mov dx,cursor ; Get the cursor
mov dl,0 ; go to right margin
mov dh,mar_top ; go to home of scrolling region
jmp atscu5 ; Set the cursor and return
atrsscnm:
cmp modeset,0 ; Setting or resetting?
je atrss1 ; Do reset
test ansflgs,decscnm ; Setting. Is it set already?
jnz atrss3 ; Yes. Don't do it again
or ansflgs,decscnm ; No. Set it
or vtemu.vtflgop,vsscreen ; tell Status display
or vtflags,vsscreen ; and our local flags
mov al,att_reverse ; Want reverse video
jmp short atrss2 ; Do it
atrss1: test ansflgs,decscnm ; Resetting. Is it reset already?
jz atrss3 ; Yes. Don't do it again
and ansflgs,not decscnm ; No. Clear it
and vtemu.vtflgop,not vsscreen ; tell Status display
and vtflags,not vsscreen ; and our local flags
mov al,att_normal ; Want normal video
; Fall through to atrss2
; Note: This is also called from the stblmds initialization routine.
atrss2: push ax
mov scbattr,al ; Set screen background attribute
mov oldbatr,al ; update long term memory too
mov ah,al ; place where brkatt works
call brkatt ; separate color and specials
rol ah,1 ; Reverse the reversal (sic.)
rol ah,1 ; Reverse the reversal (sic.)
rol ah,1 ; Reverse the reversal (sic.)
rol ah,1 ; Reverse the reversal (sic.)
call addatt ; put blink/bold bits back in
mov mlbattr,ah ; For mode line background
mov ah,curattr ; Get current cursor attribute
call brkatt ; Break it up
rol ah,1 ; Reverse its background
rol ah,1 ; Reverse its background
rol ah,1 ; Reverse its background
rol ah,1 ; Reverse its background
call addatt ; Put it back together
mov curattr,ah ; And store it
pop ax
call revscn ; Reverse everything on the screen
atrss3: ret
atctst: mov al,0 ; Init test weight
mov di,offset atcts2 ; Routine to call
call atreps ; Repeat for all parms
test al,80H ; Want to reset?
jz atcts1 ; No - return
call atreset ; Yes - reset everything
atcts1: ret
atcts2: mov ah,ansargs[si] ; Pick up an argument
cmp ah,0 ; Zero?
jne atcts3 ; No - ignore others
or al,80H ; Yes - say we want reset
atcts3: ret
; VT52 compatibility mode routines.
; Return to ANSI mode.
v52ans: or ansflgs,decanm ; Turn ANSI flag back on
mov flags.vtflg,ttvt100 ; Say VT100 now
call chrdef ; Set default char sets
call atsc ; Save cursor status
call disleds ; Put "LEDs" back
jmp atnorm ; Reset state to normal and return
; Reset VT52 (does NOT cause return to VT100 mode)
v52ris: call atreset ; Reset everything
call disleds ; Put "LEDs" back
ret
; Enter VT52 "graphics" mode.
v52egm: call chrsgs ; Set "graphics" char set
jmp atnorm ; Reset state to normal and return
; Exit VT52 "graphics" mode.
v52xgm: call chrdef ; Set default character set
jmp atnorm ; Reset state to normal and return
; VT52 cursor positioning.
v52pos: mov ttstate,offset v52pc1 ; Next state
ret
v52pc1: sub al,' '-1 ; Minus offset
mov ansargs,al ; Stash it here
mov ttstate,offset v52pc2 ; Next state
ret
v52pc2: sub al,' '-1 ; Minus offset
mov ansargs+1,al ; Stash here
call atnorm ; Reset state to "normal"
jmp atcup ; Position and return
; VT52 print controls
v52apb: mov ansargs,5 ; Enter auto print mode
or escdec,decmode ; simulate ESC [ ? 5 i
jmp ansprt ; process command
v52ape: mov ansargs,4 ; Exit auto print mode
or escdec,decmode ; simulate ESC [ ? 4 i
jmp ansprt ; process command
v52pcb: mov ansargs,5 ; Enter printer controller on
or escdec,decmode ; simulate ESC [ ? 5 i
jmp ansprt ; process command
v52pce: mov ansargs,4 ; Exit printer controller on
or escdec,decmode ; simulate ESC [ ? 4 i
jmp ansprt ; process command
v52ps: mov ansargs,0 ; print screen
and escdec,not decmode ; simulate ESC [ 0 i
jmp ansprt ; process command
v52pl: mov ansargs,1 ; print line
or escdec,decmode ; simulate ESC [ ? 1 i
jmp ansprt ; process command
; Heath-19 special functions
h19ans: or ansflgs,decanm ; Turn on ANSI flag. ESC <
call chrdef ; Set default char sets
jmp atnorm ; Reset state to normal and return
; do several "ESC [" ANSI commands
; but don't change terminal types
h19ansa:jmp atcsi ; parse ansi arguments
; clear screen and go home
h19clrs:mov dx,0 ; go to upper left corner
call atscu5 ; do it
mov ax,0 ; clear screen from (0,0)
mov bh,byte ptr low_rgt+1 ; to lower right corner
mov bl,crt_cols ; physical width
dec bl ; we count from 0
jmp vtsclr ; Clear it
; cursor down (scrolls)
h19cud: mov dx,cursor ; get cursor position
inc dh ; say next row down
call atccic ; check position cursor (scrolls)
mov cursor,dx
call ax ; do scrolling
jmp atscu5
; cursor forward (right). ESC C
h19cuf: mov dx,cursor ; get cursor position
inc dl ; move cursor right
cmp dl,byte ptr low_rgt ; beyond right margin
jb h19cuf1 ; b = no. do it
test ansflgs,decawm ; wrap mode on?
jz h19cuf2 ; z = no. just ignore movement
xor dl,dl ; set to left margin
inc dh ; and down a row
call atccic ; adjust position
call ax ; call scrolling routine
h19cuf1:jmp atscu5 ; do positioning and return
h19cuf2:ret ; just return
; set line wrap on
h19wrap:or ansflgs,decawm ; turn on the flag
jmp atnorm
; turn off line wrap
h19nowrp:and ansflgs,not decawm ; turn off the flag
jmp atnorm
h19erb: mov bx,cursor ; erase home to cursor, incl
xor ax,ax ; home
jmp vtsclr ; clear the area, cursor stays put???
h19erl: mov bx,cursor ; erase whole line
mov ax,bx ; get row
xor al,al ; column 0
mov bl,crt_cols ; physical width
dec bl ; we count from 0
jmp vtsclr ; erase whole line, cursor stays put
h19ero: mov bx,cursor ; erase start of line to cursor
mov ax,bx
xor al,al ; start in column 0
jmp vtsclr ; clear that part of line
h19herv:cmp video_state,0 ; is video normal? ESC p
jne h19hrv1 ; ne = no, reversed already, ignore
mov ah,curattr ; current cursor attributes
call brkatt ; breakup attributes byte
rol ah,1 ; reverse foreground to background
rol ah,1
rol ah,1
rol ah,1
call addatt ; put things together again
mov curattr,ah ; and store it
mov video_state,1 ; say we are reversed
h19hrv1:ret
h19hxrv:cmp video_state,0 ; is video normal? ESC q
je h19hxr1 ; e = yes, so just ignore
mov ah,curattr ; current cursor attributes
call brkatt ; breakup attributes byte
rol ah,1 ; reverse foreground to background
rol ah,1
rol ah,1
rol ah,1
call addatt ; put things together again
mov curattr,ah ; and store it
mov video_state,0 ; say we are normal
h19hxr1:ret
h19mbr: mov ttstate,offset hmbr ; Modify baud rate ESC r char
ret ; setup to parse next char
hmbr: jmp atnorm ; discard char (in al)
htsc: cmp flags.vtflg,ttheath ; Heath-19? ESC [ s
jne htscx ; ne = no, ignore
call atsc ; store cursor position and attr
htscx: jmp atnorm ; reset state & return
htrc: cmp flags.vtflg,ttheath ; Heath-19? ESC [ u
jne htrcx ; ne = no, ignore
call atrc ; restore cursor pos and attr
htrcx: jmp atnorm ; reset state & return
; Heath-19 set mode "ESC x "
h19smod:mov ttstate,offset hsmod ; setup to parse rest of seq
ret
hsmod: mov modeset,1 ; say set mode
mov ttstate,offset atnrm
sub al,'0' ; remove ascii bias
jmp htrsm1 ; perform mode set
h19cmod:mov ttstate,offset hcmod ; setup to parse rest of seq
ret
hcmod: mov modeset,0 ; say reset mode
mov ttstate,offset atnrm
sub al,'0' ; remove ascii bias
jmp htrsm1 ; perform mode reset
htrest: cmp flags.vtflg,ttheath ; Heath-19? ESC [ z
jne htrestx ; ne = no, ignore
call atreset ; do a hard reset
htrestx:jmp atnorm ; reset state and return
hrcup: mov al,escape ; send "ESC Y row col" cursor report
call prtbout ; send with no local echo
mov al,'Y'
call prtbout
mov al,byte ptr cursor+1 ; get row
add al,' ' ; add ascii bias
call prtbout ; send it
mov al,byte ptr cursor ; get column
add al,' ' ; add ascii bias
call prtbout ; and send it too
jmp atnorm ; return to terminal mode
; Heath-19 and VT102 additions
inslin: cmp ansargs,0 ; insert line(s). Any args?
jne insli1 ; ne = yes. If no arg use 1
mov ansargs,1 ; insert one line
insli1: mov dl,ansargs
mov scroll,dl
mov dx,cursor ; current position
cmp dh,mar_bot ; below bottom margin?
jae insli3 ; ae = at or below bottom margin
push word ptr mar_top
mov mar_top,dh ; call present position the top
insli2: call atscrd ; scroll down
pop word ptr mar_top ; restore margins
xor dl,dl ; go to left margin
jmp atscu5 ; reposition cursor and return
insli3: ret
dellin: cmp ansargs,0 ; delete line(s). Any args?
jne delli1 ; no arg; use 1
mov ansargs,1 ; insert one line
delli1: mov dl,ansargs
mov scroll,dl ; line count
mov dx,cursor ; where we are presently
cmp dh,mar_bot ; at or below bottom margin?
jae delli3 ; ae = yes
push word ptr mar_top ; save current scrolling margins
mov mar_top,dh ; temp top margin is here
delli2: call atscru ; scroll up
pop word ptr mar_top ; restore scrolling margins
jmp atscu5 ; restore cursor and return
delli3: ret
; Delete character(s)
atdelc: cmp ansargs,0 ; zero becomes one operation
jne atdelc1
mov ansargs,1 ; delete one char. Heath ESC N
atdelc1:mov cl,byte ptr low_rgt ; number of columns on screen
mov dx,cursor ; get present cursor position
push bx
mov bl,dh ; get row
mov bh,0
cmp linetype [bx],0 ; single width line?
je atdelc5 ; e = yes
shl dl,1 ; double the column number
mov bl,ansargs
shl bl,1 ; double # chars to delete
mov ansargs,bl
atdelc5:pop bx
sub cl,dl ; end of screen - current column #
xor ch,ch ; cx = number of chars to move
cmp cx,0 ; zero means just this char
ja atdelc4
inc cx ; say one, this one
atdelc4:push es
push cx ; save word count for Topview
cld
test vtemu.vtflgop,vswdir ; writing left to right?
jz atdelc4a ; z = yes
sub dl,byte ptr low_rgt ; reflect about logical right column
neg dl ; convert to positive value
atdelc4a:
call scrloc ; compute current cursor location
mov di,ax ; temporary storage places
mov si,ax
mov al,ansargs ; get delete count
xor ah,ah ; clear high byte of delete count
cmp al,cl ; clear more than rest of line?
jb atdelc2 ; b = no. some chars left at end
mov al,cl ; say delete all to right, inclusive
atdelc2:cmp al,0 ; zero?
jne atdelc3
inc al ; none or 0 implies one
atdelc3:shl ax,1 ; double: char and its attribute byte
push di ; destination offset
cld ; assume forward for left to right
test vtemu.vtflgop,vswdir ; writing left to right
jz atdelc3a ; z = yes
neg ax ; minus ax, work the other way
std ; movement reverses too
atdelc3a:
add ax,si ; src offset = dest + # deleted words
push ax ; save it
call scroff
call scrseg ; pick up screen segment
mov si,di ; align memory addresses
pop ax ; recover source offset
add si,ax ; add to starting memory address
pop ax ; recover destination offset
add di,ax ; add to destination memory address
push ds ; save ds around the move
push es ; move es into ds to
pop ds ; make ds point to screen memory too
rep movsw
cld ; reset direction to forward
pop ds ; recover normal ds
pop cx ; count for Topview
test vtemu.vtflgop,vswdir ; writing left to right?
jz atdelc6 ; z = yes
sub di,cx ; get correct es:di ending address
sub di,cx ; for scrsync
atdelc6:call scrsync ; synch Topview
pop es
call scron
mov ax,cursor ; get current row
mov bx,cursor
mov bl,byte ptr low_rgt ; last col on screen
mov al,bl
sub al,ansargs ; minus number of locations cleared
inc al
test vtemu.vtflgop,vswdir ; writing left to right?
jz atdelc7 ; z = yes
mov cl,byte ptr low_rgt ; reflect about logical right margin
sub cl,al
mov bl,cl ; end of line to be cleared
mov al,0 ; start of line to be cleared
atdelc7:call atsclr ; clear end of line
atdelcx:mov dx,cursor
jmp atscu5 ; reposition cursor
inschr: mov dx,cursor ; open one char space in current line
push bx
mov bl,dh ; get row
mov bh,0
cmp linetype [bx],0 ; single width line?
je insch2 ; e = yes
shl dl,1 ; double the column number
insch2: pop bx
mov ch,0
mov cl,byte ptr low_rgt ; number of columns on screen
push dx
mov dh,0
sub cx,dx ; compute distance to end
pop dx
or cx,cx
jle insch1 ; le = nothing to move [dlk]
mov dl,byte ptr low_rgt
dec dl ; last col to move
push ax ; save regs
push es ; ditto
push cx ; save count for Topview
test vtemu.vtflgop,vswdir ; writing left to right?
jz insch3 ; z = yes
mov dl,1 ; right-to-left physical EOL-1
call scrloc ; compute position of end of line-1
push ax ; save offset
cld ; remember to move forward
call scroff ; turn off color screen
call scrseg ; get memory address in es:di
pop ax ; recover offset
add di,ax ; source memory address
mov si,di ; align addresses. destination
sub di,2 ; is one char over
jmp short insch4 ; join common code
insch3: ; do normal left to right material
call scrloc ; compute position of end of line-1
push ax ; save offset
std ; remember to move backward
call scroff ; turn off color screen
call scrseg ; get memory address in es:di
pop ax ; recover offset
add di,ax ; source memory address
mov si,di ; align addresses. destination
add di,2 ; is one char over
insch4: push di
push ds ; save ds around move
push es ; put es into ds
pop ds ; ds points to screen memory too
rep movsw
pop ds ; recover normal ds
cld ; reset direction to be forward
pop di
pop cx ; count for Topview
test vtemu.vtflgop,vswdir ; writing left to right?
jz insch5 ; z = yes
add di,cx ; get correct es:di ending address
add di,cx ; for scrsync
insch5: call scrsync ; synch Topview
pop es ; restore regs
pop ax ; ditto
call scron ; turn on screen again
cld ; reset direction
insch1: mov dx,cursor
jmp atscu5 ; position cursor
noins: mov insmod,0 ; turn off insert mode
jmp atnorm ; and return
entins: mov insmod,0ffh ; enter insert mode
jmp atnorm ; and return
ansich proc near ; ANSI insert characters ESC [ Pn @
cmp ansargs,0 ; any arguments?
jne ansic1 ; ne = no, ignore
mov ansargs,1 ; use one
ansic1: push dx ; save cursor
mov insmod,1 ; enter insert mode
push cx
mov cl,ansargs ; get count of inserts
mov ch,0
mov ah,ansflgs ; save flags in ah
and ansflgs,not decawm ; turn off autowrap
push ax ; save char
ansic2: push cx ; save counter
mov al,' ' ; character to write
call atnrm ; do display
pop cx ; recover counter
loop ansic2 ; do cx times
pop ax ; restore char
mov ansflgs,ah ; recover flags
mov ah,0 ; clear register
pop cx
mov insmod,0 ; turn off insert mode
pop dx ; get original cursor
jmp atscu5 ; set cursor
ansich endp
; routines supporting scrolling and double width/height chars
; scroll has number of lines to scroll
atscru proc near ; scroll screen up one line
push ax ; assumes dx holds cursor position
push bx ; returns with dx = old row, new col
push cx
push si
xor bh,bh
mov bl,mar_top ; top line to move
xor ch,ch
mov cl,scroll ; number of lines to move
jcxz atscru5 ; cx = 0. nothing to do
mov al,mar_bot ; bottom line to scroll
sub al,bl ; number of lines minus 1
inc al ; number of lines
cmp al,cl ; scrolling region smaller than scroll?
jge atscru1 ; ge = no, is ok
mov scroll,al ; limit to region
cmp al,1 ; at least one line to scroll?
jge atscru1 ; ge = yes
mov scroll,1 ; no, force one
atscru1:push bx
mov bl,dh ; get row of cursor
mov bh,0
cmp linetype[bx],0 ; single width?
pop bx
je atscru7 ; e = yes
shr dl,1 ; reindex to single width columns
atscru7:mov al,scroll
xor ah,ah
cmp al,byte ptr low_rgt+1 ; number of lines on screen
jbe atscru8 ; be = scrolling not more than that
mov al,byte ptr low_rgt+1 ; limit to screen length
mov scroll,al
atscru8:mov si,ax ; scroll interval
mov bl,mar_top
mov cl,mar_bot
sub cl,bl
inc cl ; number of lines in region
sub cl,scroll ; cx = those needing movement
jcxz atscru3
atscru2:mov al,linetype[bx+si] ; get old type
mov linetype[bx],al ; copy to new higher position
inc bx
loop atscru2
atscru3:mov bl,mar_bot ; set fresh lines to single attribute
mov cl,scroll
mov ch,0
inc cx
atscru4:mov linetype[bx],0
dec bx
loop atscru4 ; clear old bottom lines
atscru5:pop si
pop cx
pop bx
pop ax
test anspflg,vtcntp ; controller print active?
jz atscru6 ; z = no, ok to change screen
ret ; else keep screen intact
atscru6:jmp vtscru ; call & ret the msy scroll routine
atscru endp
atscrd proc near ; scroll screen down one line
push ax ; assumes dx holds cursor position
push bx ; returns with dx = old row, new col
push cx
push si
xor ch,ch
mov cl,scroll ; number of lines to scroll
jcxz atscrd5 ; cx = 0. nothing to do
xor bh,bh
mov bl,mar_bot ; bottom line to move
mov al,bl
mov ah,0
sub al,mar_top ; number of lines minus 1
inc al ; number of lines
cmp al,cl ; scrolling region smaller than scroll?
jge atscrd1 ; ge = no, is ok
mov scroll,al ; limit to region
cmp al,1 ; at least one line to scroll?
jge atscrd1 ; ge = yes
mov scroll,1 ; no, force one
atscrd1:push bx
mov bl,dh ; get row of cursor
mov bh,0
cmp linetype[bx],0 ; single width?
pop bx
je atscrd7 ; e = yes
shr dl,1 ; reindex to single wide columns
atscrd7:mov al,scroll
mov si,ax ; si = scroll
sub bl,scroll ; si + this bx will be new bottom line
mov cl,bl
sub cl,mar_top
inc cl ; number of movements
jcxz atscrd3
atscrd2:mov al,linetype[bx] ; get old line's type
mov linetype[bx+si],al ; copy to new lower position
dec bx
loop atscrd2
atscrd3:mov bl,mar_top
mov bh,0
mov cl,scroll
mov ch,0
inc cx
atscrd4:mov linetype[bx],0 ; clear new top lines
inc bx
loop atscrd4
atscrd5:pop si
pop cx
pop bx
pop ax
test anspflg,vtcntp ; controller print active?
jz atscrd6 ; z = no, ok to change screen
ret ; else keep screen intact
atscrd6:jmp vtscrd ; call & ret the msy scroll routine
atscrd endp
linesgl proc near ; convert line to single width char
push ax
push bx
push cx
push dx
mov bx,cursor
mov bl,bh
xor bh,bh ; bx now holds row
cmp linetype [bx],0 ; is line already single width?
je linsglx ; e = yes
mov linetype [bx],0 ; say will be single now
call scroff ; turn off video
mov dx,cursor
mov dl,0 ; start in column 0
mov cl,byte ptr low_rgt ; number of columns on screen
inc cl
shr cl,1 ; number of columns to do
mov ch,0
push cx ; save around loop below
linsgl1:push cx ; save loop counter
shl dl,1 ; double column number
mov ah,2 ; set cursor
xor bh,bh ; page 0
call direction ; do Bios screen operation
mov ah,8 ; read char and attribute
int screen
push ax ; save char and attribute
shr dl,1 ; restore column
mov ah,2 ; set cursor
call direction ; do Bios screen operation
pop ax ; recover char and attribute
mov bl,ah ; set attribute
mov cx,1 ; one char
mov ah,9 ; write char and attribute
int screen
inc dl ; next column
pop cx
loop linsgl1
pop cx ; recover column counter
mov dl,cl
linsgl2:push cx ; save counter
mov ah,2 ; set cursor
call direction ; do Bios screen operation
mov bh,0
mov bl,scbattr ; screen background
mov al,' '
mov ah,9 ; write char
mov cx,1 ; do one character
call direction ; do Bios screen operation
inc dl ; next column
pop cx
loop linsgl2 ; repeat for all characters
call scron ; turn on the video
linsglx:pop dx
pop cx
pop bx
pop ax
jmp atscur ; update cursor and return
linesgl endp
linedbl proc near ; convert line to double width char
push ax ; must reset physical cursor
push bx ; to same char as before expansion
push cx ; but does not modify variable cursor
push dx
mov bx,cursor
mov bl,bh
xor bh,bh ; bx now holds row
cmp linetype [bx],0 ; is line single width?
jne lindblx ; ne = no. nothing to do
mov linetype [bx],1 ; say will be double width now
mov dx,cursor
mov cl,byte ptr low_rgt ; number of columns on the screen
inc cl
mov ch,0
shr cl,1 ; number of items to do
mov dl,cl
dec dl
call scroff ; turn off the video
lindbl1:push cx ; save loop counter
mov ah,2 ; set cursor
mov bh,0 ; page 0
call direction ; do Bios screen operation
mov ah,8 ; read char and attribute
int screen
push ax ; save char and attribute
shl dl,1 ; double the column number
mov ah,2 ; set cursor
call direction ; do Bios screen operation
pop ax ; recover char and attribute
mov bl,ah ; set attribute
mov cx,1 ; one char
mov ah,9 ; write char and attribute
int screen
inc dl ; move to second column of double
mov ah,2 ; set cursor
call direction ; do Bios screen operation
mov al,' ' ; space as filler
mov ah,9 ; write that char
int screen
dec dl
shr dl,1
dec dl
pop cx
loop lindbl1
call scron ; turn on the video
lindblx:pop dx
pop cx
pop bx
pop ax
jmp atscur ; update the cursor and return
linedbl endp
anstty endp
ansprt proc near ; printer support routines
mov di,offset ansprt0 ; routine to process arguments
call atreps ; Repeat for all parms
ret
ansprt0:mov ah,ansargs[si] ; Pick up the argument
cmp ah,0 ; 0 (print all/part of screen)?
jne ansprt1 ; ne = no
call pntchk ; check printer
jc ansprtx ; c = printer not ready
call pntext ; do whole screen or scrolling extent
jmp atscu5 ; reposition cursor and return
ansprt1:cmp ah,1 ; 1 (print current line)?
jne ansprt4 ; ne = no
call pntchk ; check for printer ready
jc ansprtx ; c = printer not ready
call pntlin ; print current line
call pntflsh ; flush printer buffer
anspr1a:jmp atscu5 ; reposition cursor and return
ansprt4:cmp ah,4 ; 4 (auto print disable)?
jne ansprt5 ; ne = no
test escdec,decmode ; was it ESC [ ? 4 i
jz anspr4a ; z = no, so it was ESC [ 4 i
test anspflg,vtautop ; check state of print flag
jz anspr4a ; z = off already
and anspflg,not vtautop ; auto-print disable
call trnprs ; toggle mode line PRN indicator
anspr4a:jmp ansprtx
ansprt5:cmp ah,5 ; 5 (auto print enable)?
jne ansprtx ; ne = no
call pntchk ; check printer, ignore carry ret
jc ansprtx ; c = printer not ready
test escdec,decmode ; was it ESC [ ? 5 i
jz anspr5a ; z = no
test anspflg,vtautop ; is print already enabled?
jnz ansprtx ; nz = yes, leave trnprs intact
or anspflg,vtautop ; auto-print enabled
jmp short anspr5b
anspr5a:test anspflg,vtcntp ; controller print already enabled?
jnz ansprtx ; nz = yes
or anspflg,vtcntp ; controller print enabled
anspr5b:call trnprs ; toggle on mode line PRN indicator
ansprtx:jmp atnorm
ansprt endp
; State machine active while Media Copy On (Print Controller ON). Copies all
; chars to the printer until (and excluding) Media Copy Off (ESC [ 4 i) has
; been received or the emulator reset. New char is in al. 6 March 1987 [jrd]
ansmc proc near
mov ah,al ; copy active character
and ah,7fh ; strip high bit
cmp ah,escape ; start of MC Off sequence?
jne ansmc1 ; ne = no
call ansmc6 ; playback previously matched chars
mov mccnt,1 ; count matched chars (one now)
mov mcoffs,al ; save full character, with high bit
mov ansargs,0 ; clear first ansi argument
mov nansarg,0 ; number of arguments
ret
ansmc1: mov bx,mccnt ; number of chars matched in MC Off
cmp bx,0 ; have first?
jne ansmc1a ; ne = yes, one or more
jmp pntchr ; print it, ignore errors
ansmc1a:mov mcoffs[bx],al ; save this char, with high bit
inc mccnt ; count saved characters
and al,7fh ; strip high bit
cmp al,'0' ; A digit?
jge ansmc2 ; ge = maybe
jmp ansmc6 ; b = out of range for everything
ansmc2: cmp al,'9' ; maybe, separator or final char?
ja ansmc3 ; a = perhaps, go check it out
mov cl,al ; digit, convert ASCII to binary
sub cl,'0'
mov ch,0
mov bl,nansarg ; put index in bx
xor bh,bh
mov al,ansargs[bx] ; Pick up what we've done so far [dlk]
shl al,1 ; multiply by 10. 2 * al
mov ah,al ; save
shl al,1 ; 4 * al
shl al,1 ; 8 * al
add al,ah ; 10 * al
mov ah,0 ; clear high field
add ax,cx ; add in this digit [dlk]
cmp ax,0feh ; max value is 0ffh [dlk]
jbe ansmc2a ; be = ok [dlk]
mov al,0ffh ; set to max value [dlk]
ansmc2a:mov ansargs[bx],al ; Put result back for next time [dlk]
ret ; And return
ansmc3: cmp al,'[' ; ANSI sequence?
jne ansmc4 ; ne = no, check further
cmp mccnt,2 ; is it the second character?
je ansmc3a ; e = yes, accept and continue
jmp ansmc6 ; no, end match
ansmc3a:ret ; continue
ansmc4: cmp al,';' ; Argument separator?
jne ansmc5 ; ne = no, check for final char
inc nansarg ; yes, count it
mov bl,nansarg ; get argument index
mov bh,0
mov ansargs[bx],0 ; clear next arg field
cmp bl,lansarg ; too many?
jl ansmc4a ; l = no, continue
dec nansarg ; yes, do not add more
jmp ansmc6 ; end match now
ansmc4a:ret ; accept separator and continue
ansmc5: cmp al,'i' ; sequence terminator?
jne ansmc6 ; ne = no, end match
mov bx,-1
mov cl,nansarg ; number of argument values
mov ch,0
inc cx ; no args is same as one
ansmc5a:inc bx
mov al,ansargs[bx] ; get ansi argument
mov ansargs[bx],0ffh ; and zap it to absorb early values
cmp al,4 ; MC OFF value?
loopne ansmc5a ; ne = no, examine all non-matches
jne ansmc6 ; ne = no match, end matching
; MC OFF sequence discovered
mov mccnt,0 ; clear counter
call pntflsh ; flush printer buffer
test anspflg,vtcntp ; was printing active?
jz ansmc5b ; z = no, do nothing
and anspflg,not vtcntp ; yes, disable print controller
call trnprs ; toggle mode line PRN indicator
ansmc5b:jmp ansprt ; done, process arguments in order
; MC OFF sequence not found, playback
ansmc6: push ax ; save break char (in al)
push cx ; playback partial sequence to printer
mov cx,mccnt ; number of chars matched before break
jcxz ansmc6b ; z = none
push si
mov si,offset mcoffs ; string to be played back
cld
ansmc6a:lodsb ; get a char into al
call pntchr ; print it, ignore errors
loop ansmc6a ; do all that came in previously
pop si
ansmc6b:pop cx
pop ax ; recover break char
mov mccnt,0 ; reset to no match and exit
mov nansarg,0
ret
ansmc endp
pntlin proc near ; print whole line given by dx
push ax
push bx
push cx
push dx
xor ch,ch
mov cl,byte ptr low_rgt ; number of columns
mov dl,cl ; Bios column counter, dh = row
inc cl ; actual line length, count it down
test vtemu.vtflgop,vswdir ; writing right to left?
jnz pntlin2 ; nz = yes, do not trim spaces
pntlin1:mov ah,2 ; set cursor
xor bh,bh ; page 0
int screen
mov ah,8 ; read char (al) and attribute (ah)
int screen
cmp al,' ' ; is this a space?
jne pntlin2 ; no, we have the end of the line
dec dl ; else move left one column
loop pntlin1 ; and keep looking for non-space
pntlin2:jcxz pntlin4 ; z = empty line
xor dl,dl ; start in column 0, do cl chars
pntlin3:mov ah,2 ; set cursor
xor bh,bh ; page 0
int screen
mov ah,8 ; read char and attribute
int screen
inc dl ; inc to next column
call pntchr ; print the char (in al)
jc pntlin5 ; c = printer error
loop pntlin3 ; do cx columns
pntlin4:mov al,cr ; add trailing cr/lf for printer
call pntchr
jc pntlin5
mov al,lf
call pntchr
pntlin5:pop dx
pop cx
pop bx
pop ax
ret ; C bit controlled by pntchr
pntlin endp
pntext proc near ; print an extent of lines, depending
push ax ; on flag bit vtextp
push bx
push dx
xor dx,dx ; assume starting at top left
mov bx,low_rgt ; and extending to lower right
test anspflg,vtextp ; full screen wanted?
jnz pntext1 ; nz = yes, else scrolling region
mov dh,mar_top ; top of scrolling region
mov bh,mar_bot ; bottom of scrolling region
pntext1:call pntlin ; print a line
jc pntext2 ; c = printer error
inc dh
cmp dh,bh ; done all requested lines?
jbe pntext1 ; be = not yet, do another
test anspflg,vtffp ; form feed needed at end?
jz pntext2 ; z = no
mov al,ff
call pntchr ; print the form feed char
pntext2:pop dx
pop bx
pop ax
ret
pntext endp
; Do Bios screen operation with consideration for writing direction.
; Enter with normal registers set, preserves register dx.
direction proc near
push dx
test vtemu.vtflgop,vswdir ; writing left to right?
jz direct1 ; z = yes, do Bios function
sub dl,byte ptr low_rgt ; right margin column number
neg dl ; make a positive value again
direct1:int screen
pop dx
ret
direction endp
; Clear screen from AX to BX, where AH = row, AL = column, ditto for BX.
; This routine accomodates right to left writing. BX >= AX.
vtsclr proc near
test vtemu.vtflgop,vswdir ; writing left to right?
jz vtsclr4 ; z = yes
cmp bh,ah ; same row?
je vtsclr2 ; e = yes
push ax ; multiple lines
push bx ; save both coordinates
mov bl,byte ptr low_rgt ; get right most logical column
mov bh,ah ; pick just top line
call vtsclr2 ; delete fraction of top line
pop bx ; recover ending position
push bx
inc ah ; omit top row, now done
dec bh ; omit last line, could be fractional
cmp bh,ah ; any whole lines remaining to delete?
jb vtsclr1 ; b = no, finish up
mov bl,byte ptr low_rgt ; get right most physical column
mov al,0 ; to end of line (on left)
call atsclr ; clear top line and whole remainders
vtsclr1:pop bx ; setup for last line to be cleared
push bx ; get last row again
mov al,0 ; start at logical left margin
jmp short vtsclr3 ; ax and bx are already pushed
vtsclr2:push ax ; erase single line, whole or part
push bx
vtsclr3:mov ah,byte ptr low_rgt ; borrow reg ah (same as bh)
sub ah,bl ; reflect right to left
mov bl,ah
or bl,bl ; overflow?
jns vtsclr5 ; ns = no, is ok
mov bl,0 ; limit to logical screen
vtsclr5:mov ah,byte ptr low_rgt
sub ah,al
mov al,ah
jns vtsclr6
mov al,byte ptr low_rgt ; limit to logical screen
vtsclr6:mov ah,bh ; restore ah
xchg al,bl ; reverse to get physical ax < bx
call atsclr ; erase part/all of single line
pop bx
pop ax
ret
; for writing left to right
vtsclr4:jmp atsclr ; do normal erasure and return
vtsclr endp
code ends
if1
%out [End of pass 1]
else
%out [End of assembly]
endif
end