home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msr313src.tar.gz
/
msr313src.tar
/
mszap3.asm
< prev
next >
Wrap
Assembly Source File
|
1988-08-16
|
172KB
|
3,493 lines
NAME mszibm
; File MSZIBM.ASM
page 60,132
; Terminal emulator module for IBM PC's and compatibles. Emulates Heath-19,
; VT52, and VT102. Original version done by James Harvey, Indiana Purdue
; Univ, for MS Kermit 2.27. Taken from there by Joe Doupnik, Utah State Univ
; for MS Kermit 2.29 et seq.
; Edit history
; Last edit: 14 March 1988
; 14 March 1988 Update V2.30 code for NEC APCIII -- RFGoeke
; 6 Jan 1988 Remove erasing into mode line on to-end-of-screen calls. [jrd]
; 1 Jan 1988 version 2.30
; 29 Dec 1987 Absorb escape sequences of the form ESC [ ... <40h to 7fh>
; to sense but not act on unknown legally formatted ANSI escapes. [jrd]
; 28 Dec 1987 Add corrections from Frank da Cruz: home cursor on select/desel
; origin mode, make select/deselect ansi mode return to US ascii graphics
; rendition sets (where is this item documented?). [jrd]
; 12 Dec 1987 Sense denyflg to supress automatic Tek mode when ESC Control-L
; is received; part of ENABLE/DISABLE command. [jrd]
; 4 Dec 1987 Strip high bit of chars within escape sequences, test for end of
; transparent print without high bit but playback 8 bit intermediates. [jrd]
; 16 Nov 1987 Add multiple timed retries on printer status. [jrd]
; 5 Nov 1987 Add Tektronix terminal type, including ESC FF branch to Tek
; mode and toggling among terminal types. [jrd]
; 28 Oct 1987 Remove NUL and DEL chars from normal logging and display,
; ignore Control-X and -Z unless in an esc sequence. [jrd]
; 3 Oct 1987 Remove cursor action for DEL when local echo is on. [jrd]
; 11 Sept 1987 Remove Translation Input from emulator proper.
; 23 Aug 1987 Add byte vtemu.vtflgop to hold emulator runtime values as
; distinct from the vtemu.vtflgst setup values so a reset restores setups.
; 19 Aug 1987 Make sure cursor type is correct on warm start, from Bob Babcock
; 18 Aug 1987 Change ESC to escape for MASM 4.5+. Add Heath graphics,
; add screen alignment, redo line wrap material, size screen from crt_cols
; and crt_rows given by MSYxxx. [jrd]
; 31 June 1987 Clear counter mccnt when completing transparent print. [jrd]
; 17 June 1987 Correct jump from atreset to atres2 when changing 80/132 cols
; and always copy all 132 columns of tabs. [jrd]
; 16 June 1987 Fix bug in cursor positioning when outside scrolling region,
; thanks to Richard Saxton. Remove global byte jwait (for msy), add code to
; clear the status line when the Heath-19 is commanded to disable that line
; (wierd, but Dave says that's the way H-19's work), thanks to Dave Tweten.
; 8 June 1987 Tell file msy... about change of keypad applications mode. [jrd]
; 31 May 1987 Correct several Heath-19 problems: use ansi escape table when
; in ansi mode, reject ESC [ (hold screen mode), use correct cursor left,
; remember cursor type (underline/block/on/off) separately from VT100 setup.
; Thanks to Dave Tweten. [jrd]
; 10 May 1987 Move input translate table rxtable within this emulator,
; don't translate if debug is active, don't translate escape sequences,
; no translation if controller print is active, make byte anspflg global
; so msyibm can sense print screen status. Add print controls for VT52. [jrd]
; 4 May 1987 Correct several jumps to be signed for scrolling region. [jrd]
; 7 April 1987 Fix cursor wrap for H-19's, from Mike Iglesias [uci]
; Fix cursor wrap top to bottom when reverse indexing, from Matt Tomlinson.
; Fix tests for cursor left of left margin for wide screens by comparing
; column number exceeding 250D. [jrd]
; 28 March 1987 Use global variable low_rgt vs proc call for it. [jrd]
; 24 March 1987 In vtsound, always use most recent port 61h state. [jrd]
; 22 March 1987 Add call to proc chgdsp (change display adapter) to shift
; between 80 and 132 columns, from David L. Knoell. [jrd]
; 14 March 1987 Correct small bugs. Change signed jumps to unsigned plus
; allow screen widths to 132 columns, thanks to David Knoell.
; Add constants Swidth (132) and Slen (43) as max screen dimensions and
; base screen ops on low_rgt (high = row, low = column of lower right corner,
; counted from 0,0) dimensions stated by msyibm. [jrd]
; 6 March 87 Add transparent printing when ANSI Media Copy (ESC [ 5 i) is
; active. [jrd]
; 19 Feb 1987 correct problem in atccic of cursor being forced into scrolling
; region if starting point was outside the region. [jrd]
; 27 Oct 1986 correct typo for anspflg under atnrm3: [jrd]
; 16 Oct 1986 keep several ansflg bits under warm start, correct screen,
; linewrap, and newline status under warm start.
; 1 Oct 1986 Version 2.29a
; 20 Sept 1986 revise procedure atccic to use proper scrolling limits. [jrd]
; 1 Sept 1986 Add 8 bit wide comms when parity = none. In debug mode high bit
; set shows as tilde then rest of 7 bit code. [jrd]
; 27 August 1986 Add full VT102 printer support. DOS printer operations used
; so printer can be redirected; requires Kermit's Critical Error routine in
; mssker.asm to avoid "Abort, Retry, Ignore" msgs on screen. Shows printer
; not ready msg on mode line and quits printing operation if PRN not ready.
; Correct indexing of cursor when it is outside limited scrolling region.[jrd]
; Fix parameter decanm not being updated in stblmds under soft reset.
; 21 May 1986 [jrd]
; [2.29] code frozen on 6 May 1986 [jrd]
; [Joe R. Doupnik, Utah State Univ]
;
public anstty, ansini, ansrei, ansdsl, anstat, anskbi ; Entry points
public ans52t, vsinit ; no vclick for NEC
public mar_top, mar_bot, anspflg ; data for msyap3
include mssdef.h
; * Disclaimer *
;
; DEC and VT are trademarks of Digital Equipment Corporation.
;
; There is a naming convention
; for the ANSI and VT100 functions and flags; generally, the stuff in the
; symbol after "ans" or "at" is the function or mode mnemonic used in the
; VT100 manual.
;
; Every effort has been made to make the VT100 emulation as much like the
; real thing as possible. The reference used was the VT100 User's Guide, 2nd
; ed. Jan. 1979, DEC part no. EK-VT100-UG. Some aspects of the behavior
; of the terminal (e.g., the interaction of the "origin mode", limited
; scrolling region, and indexing), were gleaned from programming experiments
; on an actual VT100 terminal. Implemented features include: (1) Limited
; scolling region, (2) Settable tab stops, (3) Special "graphics" character
; set and UK ASII set, (4) All graphic renditions (underline, blink, and
; high intensity), (5) Simulated "LEDs" on the mode line, (6) Screen mode
; (normal or reverse video), (7) All terminal reports (status, active position,
; terminal parameters, and device attributes), (8) The ANSI new-line mode and
; several of the DEC private modes, including keypad application, cursor key,
; screen, auto-wrap, and origin, (9) cursor position/graphic rendition/
; character set save/restore, and last (and probably least): (10) VT52 com-
; patibility mode. Also, various details of behavior required by the ANSI
; standard (e.g. most control characters do not affect the interpretation of
; the current escape sequence, relative cursor positioning (up, down, left
; right, and of course tab) stop at the screen margins, etc.) have been
; scrupulously observed.
;
; This was the first thing I ever wrote in 8088 assembler (some of it was
; stolen from MSYIBM), and one of the constraints was that the emulator
; should work with a vanilla PC with a monochrome monitor. Given these and
; other constraints, no attempt was made to implement the following VT100
; features: (1) Smooth scolling, (2) 132 column lines, (3) Auto repeat,
; (5) Interlace/no interlace, (6) Double-width/double-height lines. The
; escape sequences to set and reset these are recognized, but ignored.
;
; - James A. Harvey, IUPUI Computing Services, DEC Systems Group
;
; * End of Disclamer *
; ---------------------------------------------------------------------------
;
; Description of the global entry points and calls on external routines
; needed by this emulator. [jrd]
;
; vsinit - start up routine called as Kermit initializes. Takes no arguments.
; Sets up address pointers to tabs, reads default terminal parameters
; reads current screen coloring. Examines and updates structure
; "vtemu." which is how mssset communicates changed information
; about many Set Term parameters; "flags." is a Kermit structure
; carrying the other Set Term parameters.
; anstty - starting point for displaying a character, delivered in AL.
; Returns when the display operation is completed and that may
; take many many instructions. All normal "characters received by
; the terminal" are provided by calling anstty with the char in AL.
; ansini - entry point to initialize the emulator. It requires information
; from msy in four registers: the Kermit terminal routine flags
; "yflags" (used mainly to sense debug mode and the mode line toggle)
; "low_rgt" (bh = row, bl = column of the lower right display corner)
; "lbaudtab" (index into baud rate table, for status reporting)
; "lpartab" (index into parity table, for status reporting)
; Ansini causes a full reset of the emulator, including screen
; clearing and a beep. Ansini is also called by msy in response to
; sensing the Alt = key combination to fully reset the emulator.
; ansrei - entry point to reinitialize the emulator. Nearly the same as
; ansini except operating flags, tabs, etc are retained from the
; previous emulator session. Items which can be changed by Set Term
; are examined and updated. The msy flags "yflags" are needed.
; This is the warm-restart entry point used when connect mode
; is reentered gracefully. The screen is cleared only if the coloring
; has changed. The starting cursor location is whereever msy puts it.
; ansdsl - display "led" (status line) information. Invoked by msy when
; the mode line is constructed so the emulator can write the
; terminal type and the VT100 led status lights when Connect mode
; is started. Requires "yflags" from msy to sense whether the mode
; line is to be shown.
; anstat - reports our working flags and screen coloring to msy. Nearly
; obselete but not quite. Reads msy "yflags" and reports "mlbattr"
; the video attributes used on the mode line, "scbattr" the video
; attributes of an empty character cell (background), "curattr"
; the video attributes of displayable characters, and "ansflgs"
; the emulator's working flags (needed for keyboard translations
; done in msy).
; anskbi - a routine called by msy to notify the emulator that a character
; is available from the keyboard. No character is read, just flag
; ttkbi is set. This is actually used only to beep when the cursor
; goes beyond column 72 and the margin bell flag is on.
; ans52t - called by msy to change terminal types "on the fly" without
; fully updating all operating parameters and without losing setup
; information. Msy senses the Alt minus key and calls ans52t with
; no arguments. Ans52t cycles among VT102, VT52 and Heath-19 modes.
; vclick - called by msy to cause a click sound. Simulates keyboard clicks,
; sort of anyway. No arguments.
; other modules in msy are called by this file to handle screen scrolling
; mode line on/off, output to the serial port (reports), screen
; particulars (location, cursor shape, blanking). The list is
; the set of code extrn procedures below; all are in file msy.
;
; data exchange is directly with msy to assist in scrolling (varaibles
; "mar_top", "mar_bot") and in sensing the non-connect
; mode screen coloring ("scbattr"). Screen coloring controlled by
; the emulator is not permitted to influence the non-connect mode
; screens whereas the emulator attempts to use the regular Kermit
; screen colors as defaults. The kind of terminal to emulate is
; held in byte "flags.vtflg" which is set by Set Term and by this
; module for global information within Kermit.
;
; The emulator assumes the screen is laid out in the manner of a conventional
; IBM monochrome or color graphics adapter running in 80 column TEXT
; modes. That layout is one word per displayable location starting at
; the upper left corner (0,0) and running contiguously to the lower
; right corner (24,79). Each word holds the displayable character in
; the low order byte and the display attributes in the high order
; byte. Attributes are, from high to low bits: blinking on, back-
; ground red, green, and blue on, high intensity, foreground red,
; green, and blue on. Normal white chars on a black field is 07H.
; The starting segment of screen memory is given by msy module
; "scrseg" to be TopView/MS Windows compatible. Msy module "scrsync"
; is used to inform these windowing environments of memory updates.
; Variable "crt_mode" is set by msy to indicate which IBM display
; mode is active; only the monochrome and CGA modes are recognized.
; Direct reading and writing of display memory is done, compatibly
; with TopView/Windows, to attain speed over Bios and DOS calls
; when editing of previously entered text is needed. However, IBM
; Bios interrupt 10H is used where possible for normal cursor
; movement/sensing and writing of new characters. See the IBM PC
; hardware Technical Reference Manuals for further details.
;
; Many things have been added, or modified since James Harvey donated this
; code to Columbia University for use in Kermit. [jrd]
; ---------------------------------------------------------------------------
; This macro flips the rev_video bit of attribute in ah. RFG
; NB this neither changes any other attribute nor any other register
flip_rev_video macro
local flip,flop
test ah,att_rev_video
jnz flip
or ah,att_rev_video
jmp flop
flip: and ah,not att_rev_video
flop: nop
endm
screen equ 19H ; Bios screen call (NEC special)
printer equ 1BH ; Bios printer call (NEC special)
swidth equ 132 ; assumed max screen width [dlk]
slen equ 43 ; assumed max screen length [jrd]
att_low_mask equ 1fH ; Various NEC attribute-related equates
att_overline equ 01H ; this is all NEC version stuff RFG
att_blink equ 02H
att_rev_video equ 04H
att_underline equ 08H
att_intensity equ 04H ; same as reverse video
nec_black equ 00H ; This table gives colors RFG
nec_blue equ 20H ; (only bits 8,7,6 count)
nec_red equ 40H
nec_magenta equ 60H
nec_green equ 80H
nec_cyan equ 0A0H
nec_yellow equ 0C0H
nec_white equ 0E0H
; VT100 status flags ansflg
;anslnm equ 01H ; ANSI line feed/new line mode
;decckm equ 02H ; VT100 cursor keys mode
;deckpam equ 04H ; VT100 keypad application mode
;decscnm equ 08H ; VT100 screen mode (n.y.i.)
;decom equ 10H ; VT100 origin mode
;decawm equ 20H ; VT100 autowrap mode
;decanm equ 40H ; ANSI(VT100)/VT52 mode
;decmode equ 80H ; "?" seen in lead-in
;;;;;;;;;;;;;;;; items for reference from mssdef.h ;;;;;;;;;;;;;
; VT100 SETUP mode flags
;vsscreen equ 40H ; Screen mode (0 = normal video)
;vscursor equ 20H ; Cursor (0 = block)
;vsmarginbell equ 10H ; Margin bell (0 = off)
;vskeyclick equ 08H ; Keyclick (0 = off)
;vsshift3 equ 04H ; Shift-3 (0 = American pound sign)
;vswrap equ 02H ; Line wrap around (0 = no wrap)
;vsnewline equ 01H ; ANSI new line (0 = off)
;vsdefaults equ 0+vscursor
;[IU1] Definitions for terminal emulation
;TTGENRC EQU 0 ; Type 0 - TTY (no special emulation)
;TTHEATH EQU 1 ; Type 1 - HEATH 19
;TTVT52 EQU 2 ; Type 2 - VT52
;TTVT100 EQU 3 ; Type 3 - ANSI (VT100 subset)
;TTTEK EQU 4 ; Type 4: Tektronix 4010
;TTTYPES equ 5 ; Number of terminal types defined
;emulst struc ; structure of vtemu.xxx for VT100 emulator
;vtflgst db 0 ; VT100 setup flags (from SET)
;vtflgop db 0 ; VT100 runtime flags, like setup flags (here & STAT)
;vttbs dw 0 ; pointer to default tab stops, for SET
;vttbst dw 0 ; pointer to active tab stops, for STATUS
;att_ptr dw 0 ; pointer to normal & reverse video attributes
;emulst ends
;;;;;;;;;;;;;;;; end references ;;;;;;;;;;;;;;;;;;;;
datas segment public 'datas'
extrn vtemu:byte, crt_mode:byte, scbattr:byte, flags:byte
extrn crt_lins:byte, crt_cols:byte, rxtable:byte, denyflg:word
extrn tekflg:byte
; Early versions of MASM have a bug that causes it to consider the
; expression (offset foo) as non-relocatable if used in an arithmetic
; operation (for example, "sub di,offset foo"), and if foo is defined
; within the first 256 bytes of the data segment.
; ANSI special character table - 32 entries indexed by control char value
ansspc dw 5 dup (atign) ; ignore NUL,SOH,STX,ETX,EOT
dw atign ; ENQ - answerback message
dw atign ; ACK - ignore
dw atbel ; BEL - ring terminal bell
dw atbs ; BS - ANSI backspace
dw atht ; HT - ANSI tab
dw atlf ; LF - ANSI line feed
dw atlf ; VT - Interpreted as ANSI LF
dw atff ; FF - do as LF (but ESC FF does Tek)
dw atcr ; CR - ANSI carriage-return
dw atso ; SO - Select char set G1
dw atsi ; SI - Select char set G0
dw 8 DUP (atign) ; ignore DLE,DC1,DC2,DC3,DE4,NAK,SYN,ETB
dw atcan ; CAN - cancel ANSI sequence
dw atign ; EM - ignore
dw atcan ; SUB - treat as CAN
dw atesc ; ESC - ANSI CSI.
dw 4 DUP (atign) ; ignore FS,GS,RS,US
; Heath-19 mode escape follower table
h19esc db 'YABCD', 'KIHJF', 'G=><Z', 'ELM'
db 'NO@p', 'qvwjk', 'xynz', 'blor'
lh19esc equ $-h19esc
; Dispatch table for Heath-19 escape sequence table h19esc.
; Two byte sequences of the form ESC char, where char is not in the
; table above, are completely ignored.
h19ejt dw v52pos,atcuu,h19cud,h19cuf,atbs ; 'YABCD'
dw atel,atri,atcup,ated,v52egm ; 'KIHJF'
dw v52xgm,atkpam,atkpnm,h19ans,decid ; 'G=><Z'
dw h19clrs,inslin,dellin ; 'ELM'
dw atdelc,noins,entins,h19herv ; 'NO@p'
dw h19hxrv,h19wrap,h19nowrp,atsc,atrc ; 'qvwjk'
dw h19smod,h19cmod,hrcup,atreset ; 'xynz'
dw h19erb,h19erl,h19ero,h19mbr ; 'blor'
; Heath-19 special graphics characters. Use as offsets from caret (94D) [jrd]
hgrtab db 249,17,179,196,197 ; caret,underscore,accent grave,a,b
db 191,217,192,218,241 ; c,d,e,f,g
db 26,219,246,25,220 ; h,i,j,k,l
db 220,223,223,223,222 ; m,n,o,p,q
db 16,203,185,202,204 ; r,s,t,u,v
db 'X','/','\','-','-' ; w,x,y,z,{
db 221,222,20 ; |,},~
; VT52 compatibility mode escape follower table
v52esc db 'Y','A','B','C','D'
db 'K','I','H','J','F'
db 'G','=','>','<','Z'
db '7','8','c','^','_'
db 'W','X',']','V'
lv52esc equ $-v52esc ; length of table
; Dispatch for v52esc table
v52ejt dw v52pos,atcuu,atcud,atcuf,atcub
dw atel,atri,atcup,ated,v52egm
dw v52xgm,atkpam,atkpnm,v52ans,decid
dw atsc,atrc,v52ris,v52apb,v52ape
dw v52pcb,v52pce,v52ps,v52pl
; ANSI escape special character table
ansesc db '[','D','E','M','H'
db '7','8','=','>','c'
db '(',')','#','Z','<'
db 'P','*'
lansesc equ $-ansesc ; length of table
; Dispatch for ansesc table
ansejt dw atcsi,atind,atnel,atri,athts
dw atsc,atrc,atkpam,atkpnm,atris
dw atsg0,atsg1,atsdhl,at52id,atnorm
dw atpriv,atpriv
; Final char table for ANSI escape sequences (ESC [ Pn ; ... Pm ch)
anstab db 'H','A','B','C','D'
db 'K','J','m','g','r'
db 'c','q','x','n','f'
db 'l','h','y','P','L'
db 'M','i','s','u','z'
db '@'
lanstab equ $-anstab ; Define table length
; Dispatch for anstab table
ansjmp dw atcup,atcuu,atcud,atcuf,atcub
dw atel,ated,atsgr,attbc,atstbm
dw atda,atll,atreqt,atdsr,atcup
dw atrm,atsm,atctst,atdelc,inslin
dw dellin,ansprt,htsc,htrc,htrest
dw ansich
; "Special graphics" set translation table for characters 137 (octal)
; through 176 when the special graphics set is selected. Some characters
; (142, 143, 144, 145, 150, 151, 157, 160, 162, 163, and 174) do not
; have exact equivalents in the available set on the IBM, so a (some-
; times reasonably close) substitution is made. Table is indexed by
; ASCII char value minus 137 octal for chars 137-176 octal.
sgrtab db 032,004,177,026,023
db 027,025,248,241,021
db 018,217,191,218,192
db 197,196,196,196,196
db 196,195,180,193,194
db 179,243,242,227,157
db 156,250
; Device attributes response string. (Note: If "with AVO" causes problems,
; change the last parameter from "2" to "0". The default is to indicate
; the AVO option is present because the emulator can set all of the graphic
; rendition attributes (bold, blink, etc.) independently). A VT100 reports
; as ESC [ ? 1 ; 2 c but a VT102 uses ESC [ ? 6 ; 2 c.
dastr db escape,'[?6;2c' ; VT102
ldastr equ $-dastr
; Identify response used while in VT52 compatibility mode...
v52str db escape,'/Z'
lv52str equ $-v52str
; Identify response when a Heath-19 terminal. [jrd]
h19str db escape,'/K'
lh19str equ $-h19str
; ANSI Escape sequence to turn off Media Copy (Print Controller Off)
mcoff db escape,'[4i'
mcofflen equ $-mcoff ; length of sequence
mcoffs db 4 dup (0) ; received chars in sequence
mccnt dw ? ; counter of matched char in mcoff
; Parity code translation table
partab db 5 ; Even
db 3 ; Mark
db 1 ; None
db 4 ; Odd
db 2 ; Space
lpartab equ $-partab
; Baud rate code translation table
baudtab db 0 ; 45.5 - no VT100 code (call it 50)
db 0 ; 50
db 8 ; 75
db 16 ; 110
db 24 ; 134.5
db 32 ; 150
db 48 ; 300
db 56 ; 600
db 64 ; 1200
db 72 ; 1800
db 80 ; 2000
db 88 ; 2400
db 104 ; 4800
db 112 ; 9600
db 120 ; 19200
db 128 ; 38400 extended beyond DEC [jrd]
lbaudtab equ $-baudtab
belcol db ? ; column at which to ring margin bell
yflags db ? ; Flags from MSYxxx term routine.
video_state db 0 ; video state (0=normal,1=reversed)
oldbatr db ? ; old scbattr [jrd]
oldterm db ? ; terminal type from previous entry
baudidx db ? ; Index into baud rate table
parcode db ? ; Parity code (0-4)
datbits db ? ; Number of databits (7 or 8)
savflgs db ? ; Saved flags for atsc/atrc.
modeset db ? ; Temp for atsm/atrm.
h19mod db ? ; flag for atsm/atrm.
h19l25 db ? ; Heath-19 25th line enabled flag
insmod db ? ; Insert mode on (1) or off (0).[jrd]
kbicsr dw ? ; Cursor when keyboard input typed
kbiflg db ? ; Set/reset for keyboard input
ttstate dw offset atnrm ; terminal automata state.
; Start of stuff to save for ESC 7 fxn
ukset equ 0 ; Set 1 = UK ASCII set
ascset equ 1 ; Set 2 = US ASCII set
sgrset equ 2 ; Set 3 = "Special graphics set"
svattr_index equ 0 ; To set saved cursor attribute only.
curattr db 07h ; Cursor attribute
cursor dw 0 ; Cursor position
chr_set dw offset chr_sg0 ; Ptr. to currently selected char set
chr_sg0 db ascset ; Current SG0 set
chr_sg1 db ascset ; Current SG1 set
lsavecu equ $-curattr ; Length of stuff to save.
savecu db lsavecu dup (?) ; Saved cursor, attr., charset, etc.
h19ctyp db 1 ; H-19 cursor type (1=ul, 2=bk, 4=off)
att_normal db 07H ; retain order: normal then reverse
att_reverse db 70H
mlbattr db ? ; Mode line background attribute
ansflgs db 0 ; ANSI/VT100 mode flags
; (flags are defined in mssdefs.h)
vtflags db 0 ; VT100 SETUP flags
; (SETUP flags are defined in mssdefs.h)
tmpflags db 0 ; (Temporary for asnrei/stblmds).
; (tab stops are stored here) ; [jrd]
tabs db swidth dup (?) ; active tab stops.
deftabs db swidth dup (?) ; default tab stops
vttabs dw 0 ; Pointer to default VT100 tab stops
; byte per line, type of line: 0=normal, 1=double wide, 2=double high [jrd]
linetype db slen dup (?)
linelen db 79 ; active screen line length (79, 131)
low_rgt dw 0 ; text screen dimensions.
; byte low_rgt = max columns (79)
; byte low_rgt+1 = max rows (23)
ttkbi db 0 ; Flag for keyboard input seen.
; Scrolling region - do not separate or change order of mar_top & mar_bot.
mar_top db ? ; Scrolling region top margin
mar_bot db ? ; Scrolling region bottom margin
led_col equ 65 ; column position for "LEDs" display
led_off equ '.' ; "Off" LED. [jrd]
ansleds db 'VT102 ....' ; "LEDs".Terminal ident (10 bytes)
v52leds db ' VT52 ' ; This is used in VT52 mode.
h19leds db ' Heath-19 ' ; For Heath-19 mode [jrd]
; message for mode line [jrd]
pntmsg db 'Printer not ready, printing request skipped.'
pntmsgl equ $-pntmsg ; length of pntmsg
nansarg db 0 ; Index for ANSI argument list
ansargs db 16 dup (0) ; Room for 16 ANSI arguments
lansarg equ $-ansargs ; Max number of ANSI arguments
; printer support data
anspflg db 0 ; printer flag bits and definitions
vtautop equ 1 ; autoprint enabled (1)
vtcntp equ 2 ; controller print enabled (1)
vtextp equ 4 ; printer extent set (1)
vtffp equ 8 ; form feed wanted at end of print (1)
datas ends
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 procedures are all in module msyibm
extrn tekini:near, tekemu:near, tekend:near
extrn beep:near ; NEC use
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. [jrd]
mov deftabs,0 ; Column 1 has no tab stop.
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 [jrd]
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. [jrd]
call cpytabs ; copy default to active [jrd]
mov vtemu.att_ptr,offset att_normal ; ptr to video attributes[jrd]
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
flip_rev_video ; NEC
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 [jrd]
mov vtflags,ah
mov vttabs,offset deftabs ; tab stop pointer.
mov vtemu.vttbst,offset tabs; store here for STATUS [jrd]
mov al,flags.vtflg ; get current terminal type
mov oldterm,al ; remember it here for soft restarts
mov insmod,0 ; turn off insert mode. [jrd]
mov h19l25,0 ; clear Heath 25th line enable. [jrd]
mov h19ctyp,1 ; set Heath cursor to underline, on
mov anspflg,0 ; clear printer flag [jrd]
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
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 [jrd]
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
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: call stblmds ; Check settable modes, set flags.
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 [jrd]
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 ; 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.
stblm3: mov chr_sg0,ah ; Set the sets.
mov chr_sg1,ah
stblm4: push ax ; very necessary! NEC version
mov al,oldbatr ; keep old value around a bit
mov ah,att_normal ; get new attributes (Set Term Color)
mov scbattr,ah ; and update working copy
mov oldbatr,ah ; and save it here as well
flip_rev_video
mov att_reverse,ah ; and configure the reverse
mov mlbattr,ah ; and also here for mode line
and ah,not att_low_mask ; look at color only
and al,not att_low_mask
cmp ah,al ; has anything changed?
pop ax
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.
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 acs.
; Use same routine in msy to more closely track screen width. [jrd]
;;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
; vclick omitted for NEC
vtbell proc near
call beep ; NEC form
ret
vtbell endp
; vtsound omitted for NEC
; 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
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? [jrd]
je ans52e ; e = yes, disabled [jrd]
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.
;; mov al,0 ; Turn cursor off.
;; call csrtype
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
push si ; an NEC addition RFG
mov ah,14 ; Write character function
mov bh,0 ; Page zero.
int screen ; ...
pop si ; an NEC addition RFG
loop disled1 ; Loop for all chars
mov ah,2 ; Reposition cursor when finished
mov bh,0 ; Page zero
mov dx,cursor
int screen
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 [jrd]
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
;; test yflags,lclecho ; doing local echoing?
;; jz atign ; z = no, ignore character
;; mov ansargs,0 ; Delete one char to left [jrd]
;; cmp dl,0 ; at column 0 already?
;; je atdel1 ; e = yes
;; dec dl ; move back one column
;;atdel1: call atscu5 ; move the cursor there and
;; jmp atdelc ; delete the char now under cursor
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,0 ; NEC clear all attributes
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? [jrd]
jz atdeb0 ; z = not set
push ax ; Save the character for a second
mov al,7eh ; Output a tilde [jrd]
call atnrm2
pop ax ; Restore character
and al,7fh ; and remove high bit
atdeb0: cmp al,del ; A DELETE?
je atdeb1 ; Yes - output "^?" [jrd]
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 [jrd]
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],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:
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? [jrd]
je atnrm3 ; e = yes [jrd]
push ax ; save char
call inschr ; open a char space in this line [jrd]
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? [jrd]
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)
int screen
pop ax ; recover the char
mov ah,9 ; Output char in al to screen [jrd]
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
int screen
mov al,' ' ; use a space for doubling
mov ah,9 ; Output to screen [jrd]
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 [jrd]
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: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
jmp short atscu4b ; do 25th line
atscu4a:test ansflgs,decom ; Origin mode active?
;;;## jz atscu5 ; z = no, no 25th line allowed
atscu4b: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.
pop dx
atscu8: mov flags.modflg,0 ; and disable mode line. [jrd]
mov al,yflags ; place to communicate [jrd]
call telmsy ; tell msy the news. [jrd]
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
int screen ; set the physical cursor
shr dl,1 ; restore dl (logical column)
jmp short atscu5b
atscu5a:int screen
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? [jrd]
jg atcci0 ; g = 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 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 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...
; rewriten for the NEC RFG
brkatt:
mov al,ah ; two copies of attribues
and al,att_low_mask ; the extras only here
and ah,not att_low_mask ; the colors only here
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".
;
; modified for NEC as above RFG
addatt: or ah,al ; simply put them together
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 [jrd]
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 ah,byte ptr es:[di] ; NEC form. Fetch a word
flip_rev_video
mov byte ptr es:[di],ah ; Stuff word back
add di,2 ; Point di to next word of screen mem.
loop revsc1 ; Loop for entire screen.
pop cx ; recover word count for Topview [jrd]
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[jrd]
cmp flags.vtflg,ttvt100 ; VT100? [jrd]
jne atres7 ; ne = no. [jrd]
mov ansflgs,decanm ; turn on ANSI mode flag. [jrd]
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. [jrd]
mov h19l25,0 ; clear heath 25th line enable
mov h19ctyp,1 ; Heath-19 cursor to underline [jrd]
mov anspflg,0 ; clear printer flag [jrd]
mov cx,4 ; Initialize the "LEDs". [jrd]
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. [jrd]
pop es
call disleds ; update mode line. [jrd]
mov vttabs,offset deftabs ; [jrd]
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 ; NEC. get present normal coloring
flip_rev_video
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 [jrd]
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 ; no intensity for NEC - RFG
mov video_state,0 ; say normal video. [jrd]
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 vtflags,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,ascset ; Assume US ASCII.
test vtflags,vsshift3 ; Want UK for default?
jz chrde1 ; No.
mov al,ukset ; Yes - use the UK 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? [jrd]
je atht2 ; e = yes. handle specially. [jrd]
cmp dl,byte ptr low_rgt ; At or beyond last column?
jae atbs1 ; Yes, check range, set cursor and ret
mov al,0 ; For ORing.
mov bh,0 ; Make an index
mov bl,dl ; For column.
atht1: inc bx ; Tab always moves at least one space.
or al,tabs[bx] ; Look for non-zero.
jz 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? [jrd]
je atlf2 ; e = yes [jrd]
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 ansflgs,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? [jrd]
jne atv52f ; ne = not VT100, try others. [jrd]
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? [jrd]
je ath19f ; e = yes. Use Heath esc seqs. [jrd]
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.
; 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 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 ansflgs,decmode ; Yes - say DEC modes are coming.
ret ; And return.
atpaa2a:cmp al,'>' ; Heath private mode? [jrd]
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]
; [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
flip_rev_video ; NEC. Flip it
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? [jrd]
jne atscs5 ; ne = no
mov al,ascset ; use US ASCII set
ret
atscs5: cmp al,'2' ; alt char ROM, special graphics?[jrd]
jne atscs2 ; ne = no, use US ASCII
mov al,sgrset ; set graphics
ret
; ESC # Pn series. [jrd]
atsdhl: mov ttstate,offset atsdbl ; set up to parse argument
ret
atsdbl: cmp al,'3' ; Double high lines. Top half? [jrd]
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? [jrd]
jne atcup6 ; ne = no [hlk]
cmp h19l25,0 ; Heath 25th line enabled?
je atcup5 ; e = no
mov dh,byte ptr low_rgt+1 ; [hlk]
inc dh ; go there
jmp atscu4 ; set cursor position & mode line
atcup6: test ansflgs,decom ; origin mode? [jrd]
;;;## jz atcup5 ; z = no, no 25th line stuff allowed
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
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 atsclr ; 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 atsclr ; Clear it.
ret
ated3: cmp ansargs[si],2 ; Was arg two?
jne ated1 ; No - ignore it.
mov ax,0 ; Yes - erase entire screen.
mov bx,low_rgt
mov bl,crt_cols
dec bl ; physical width
call atsclr ; Clear it.
push bx
push cx ; set all 24 lines to single width
mov cl,byte ptr low_rgt+1 ; number of last line
xor ch,ch
inc cx ; count from one
xor bx,bx
ated3a: mov linetype [bx],0
inc bx
loop ated3a
pop cx
pop bx
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 atsclr ; 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 atsclr ; 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 atsclr ; 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,not att_blink ; NEC. clear blink/bold here
mov video_state,0 ; say normal video now. [jrd]
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 ; No.
or al,att_underline ; NEC. Yes, set underscore.
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? [jrd]
jne atsgr6 ; ne = no, reversed already, ignore
xchg al,ah ; NEC
flip_rev_video
xchg ah,al
mov video_state,1 ; say reversed now.
ret
; Set for NEC colors RFG
; just take 30-37 and map it into high bits of attribute
atsgr6: cmp bl,30 ; ANSI color series? [jrd]
jb atsgrx ; b = no.
cmp bl,37 ; foreground set (30-37)?
ja atsgrx ; don't accept background RFG
mov ah,curattr ; get current attributes
and ah,att_low_mask ; clear color bits
test bl,1 ; ANSI red?
jz atsgr6a ; z = no
or ah,nec_red
atsgr6a:test bl,2 ; ANSI & IBM green?
jz atsgr6b ; z = no
or ah,nec_green
atsgr6b:test bl,4 ; ANSI blue?
jz atsgr6c ; z = no
or ah,nec_blue
atsgr6c:mov curattr,ah ; store the results.
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,ldastr ; Length of the string
mov si,offset dastr ; Point to the string
cmp flags.vtflg,ttvt100 ; VT100? [jrd]
je decid1 ; e = yes [jrd]
mov cx,lv52str ; No - try VT52 i.d. [jrd]
mov si,offset v52str
cmp flags.vtflg,ttvt52 ; Heath-19 mode? [jrd]
je decid1 ; e = yes. [jrd]
mov cx,lh19str ; length of Heath-19 ident string
mov si,offset h19str ; say Heath-19. [jrd]
decid1: cld
lodsb ; Get a byte
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
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". [jrd]
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 ; [jrd]
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? [jrd]
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 ansflgs,decmode ; Printer status report from [jrd]
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. [jrd]
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 ansflgs,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. [jrd]
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? [jrd]
jne atrsmx ; ne = no [jrd]
mov al,modeset ; set/reset insert mode [jrd]
mov insmod,al ; store it. [jrd]
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? [jrd]
je atrsm5a ; e = yes, handle specially. [jrd]
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? [jrd]
jne atrsm7 ; ne = no
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
push ax
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
pop ax
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
xor ax,ax ; clear screen from 0,0
mov bh,byte ptr low_rgt+1 ; to end of text lines (typ. line 24)
mov bl,crt_cols ; physical width
dec bl ; we count from 0
call atsclr ; do the clear
push bx ; save regs. [jrd]
push cx
mov cl,byte ptr low_rgt+1 ; text lines (leave status line intact)
mov mar_top,0
mov mar_bot,cl ; reset scrolling region
xor ch,ch
xor bx,bx
atrsm6a:mov linetype [bx],0 ; reset linetype to single chars
inc bx
loop atrsm6a
pop cx
pop bx
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 [jrd]
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? [jrd]
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,38 ; 38? Enter Tek sub-mode. VT340 seq
jne atrsm10 ; ne = no
cmp modeset,1 ; setting mode (ESC [ ? 38 h)?
jne atrsm10 ; ne = no, ignore sequence
test denyflg,200h ; is auto Tek mode disabled?
jnz atrsm10 ; 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
atrsm10:ret
; Heath-19 ESC [ > Ps h or l where Ps = 1, 4, 7, or 9. [jrd]
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 atsclr ; 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? [jrd]
jz atrsfx ; z = no [jrd]
cmp flags.vtflg,ttheath ; in Heath-19 mode? [jrd]
je atrsfx ; e = yes, don't flip terminal kinds.
mov flags.vtflg,ttvt100 ; say VT100 now. [jrd]
jmp short atrsfx
atrsf1: not al ; Complement
and ansflgs,al ; Clear the bit
not al ; recover the bit. [jrd]
test al,decanm ; Changing terminal type? [jrd]
jz atrsfx ; z = no
cmp flags.vtflg,ttheath ; in Heath-19 mode? [jrd]
je atrsfx ; e = yes, don't flip terminal kinds.
mov flags.vtflg,ttvt52 ; say VT52 now. [jrd]
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
flip_rev_video ; NEC form
mov mlbattr,ah
mov ah,curattr
flip_rev_video
mov curattr,ah
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. [jrd]
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). [jrd]
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 ansflgs,decmode ; simulate ESC [ ? 5 i
jmp ansprt ; process command
v52ape: mov ansargs,4 ; Exit auto print mode
or ansflgs,decmode ; simulate ESC [ ? 4 i
jmp ansprt ; process command
v52pcb: mov ansargs,5 ; Enter printer controller on
and ansflgs,not decmode ; simulate ESC [ 5 i
jmp ansprt ; process command
v52pce: mov ansargs,4 ; Exit printer controller on
and ansflgs,not decmode ; simulate ESC [ 4 i
jmp ansprt ; process command
v52ps: mov ansargs,0 ; print screen
and ansflgs,not decmode ; simulate ESC [ 0 i
jmp ansprt ; process command
v52pl: mov ansargs,1 ; print line
or ansflgs,decmode ; simulate ESC [ ? 1 i
jmp ansprt ; process command
; Heath-19 special functions [jrd]
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 atsclr
; 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 atsclr ; 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 atsclr ; 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 atsclr ; 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
flip_rev_video
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
flip_rev_video ; NEC form
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 [jrd]
inslin: cmp ansargs,0 ; insert line(s). Any args? [jrd]
jne insli1 ; ne = yes. If no arg use 1
mov ansargs,1 ; insert one line.
insli1: 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
push cx ; save a reg
mov cl,ansargs ; get repeat count
xor ch,ch ; clear high byte
insli2: call atscrd ; scroll down
loop insli2 ; repeat until done (cx times)
pop cx ; restore reg
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? [jrd]
jne delli1 ; no arg; use 1
mov ansargs,1 ; insert one line.
delli1: 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
push cx ; save a reg
mov cl,ansargs ; get repeat count
xor ch,ch ; clear high byte
delli2: call atscru ; scroll up
loop delli2 ; repeat until done (cx times)
pop cx ; restore reg
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
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 impiles one.
atdelc3:shl ax,1 ; double: char and its attribute byte
push di ; destination offset
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
pop ds ; recover normal ds
pop cx ; count for Topview
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
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
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
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
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 [ @
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
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
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 [jrd]
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
xor ch,ch
mov cl,mar_bot ; bottom line to move
xor bh,bh
mov bl,mar_top ; top line to move
sub cx,bx ; cx = number of lines to move
jcxz atscru2 ; cx = 0. nothing to do
atscru1:mov al,linetype[bx+1]
mov linetype[bx],al ; move line types up one line
inc bx
loop atscru1
mov linetype[bx],0 ; clear new line's type
; reindex column of cursor
cmp linetype[bx-1],0 ; was old bottom line double wide?
je atscru2 ; e = no
shr dl,1 ; reindex to single wide columns
atscru2:pop cx
pop bx
pop ax
test anspflg,vtcntp ; controller print active?
jz atscru3 ; z = no, ok to change screen
ret ; else keep screen intact
atscru3: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
xor ch,ch
mov cl,mar_top ; top line to move
xor bh,bh
mov bl,mar_bot ; bottom line to move
sub cx,bx
neg cx ; cx = number of lines to move
jcxz atscrd2 ; cx = 0. nothing to do
atscrd1:mov al,linetype[bx-1]
mov linetype[bx],al ; move line types down one line
dec bx
loop atscrd1
mov linetype[bx],0 ; clear new line's type
; reindex column of cursor
cmp linetype[bx+1],0 ; was old top line double wide?
je atscrd2 ; e = no
shr dl,1 ; reindex to single wide columns
atscrd2:pop cx
pop bx
pop ax
test anspflg,vtcntp ; controller print active?
jz atscrd3 ; z = no, ok to change screen
ret ; else keep screen intact
atscrd3: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 cx,40 ; number of columns to do
linsgl1:push cx ; save loop counter
shl dl,1 ; double column number
mov ah,2 ; set cursor
xor bh,bh ; page 0
int screen
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
int screen
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
mov cx,40
mov dl,40
mov ah,2 ; set cursor
int screen
mov bl,scbattr ; screen background
mov al,' '
mov ah,9 ; write char
int screen ; write 40 spaces
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 dl,39 ; start with col 39
mov cx,40
call scroff ; turn off the video
lindbl1:push cx ; save loop counter
mov ah,2 ; set cursor
mov bh,0 ; page 0
int screen
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
int screen
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
int screen
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. [jrd]
cmp ansargs,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 ansargs,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
anspr1a:jmp atscu5 ; reposition cursor and return
ansprt4:cmp ansargs,4 ; auto print disable?
jne ansprt5 ; ne = no
test ansflgs,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
call trnprs ; toggle mode line PRN indicator
and anspflg,not vtautop ; auto-print disable
anspr4a:jmp ansprtx
ansprt5:cmp ansargs,5 ; auto print enable?
jne ansprtx ; ne = no
call pntchk ; check printer, ignore carry ret
jc ansprtx ; c = printer not ready
test ansflgs,decmode ; was it ESC [ ? 5 i
jz anspr5a ; z = no
test anspflg,vtautop ; is print already enabled?
jnz ansprtx ; nz = yes, leave trnprs intact
call trnprs ; toggle on mode line PRN indicator
or anspflg,vtautop ; auto-print enabled
jmp short ansprtx
anspr5a:or anspflg,vtcntp ; controller print enabled
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,byte ptr mcoff ; start of MC Off sequence?
jne ansmc1 ; ne = no
call ansmc4 ; playback previously matched chars
mov mccnt,1 ; count matched chars (one now)
mov mcoffs,al ; save full character, with high bit
jmp short ansmcx ; and exit
ansmc1: push bx ; check for char in MC Off sequence
mov bx,mccnt ; number of chars matched in MC Off
mov mcoffs[bx],al ; save this char, with high bit
cmp al,byte ptr mcoff[bx] ; match expected char in sequence?
pop bx
jne ansmc3 ; ne = no, play back partial match
inc mccnt ; count new match
cmp mccnt,mcofflen ; matched all char in sequence?
jne ansmcx ; ne = not yet, wait for more
and anspflg,not vtcntp ; yes, disable print controller
mov mccnt,0 ; clear counter
jmp short ansmcx ; all done
ansmc3: call ansmc4 ; playback previously matched chars
call pntchr ; print current char, ignore errors
mov mccnt,0 ; reset to no match and exit
ansmcx: ret ; common exit
; local worker procedure
ansmc4: push ax ; save break char (in al)
push cx ; playback partial sequence to printer
mov cx,mccnt ; number of chars matched before break
jcxz ansmc4b ; z = none
push si
mov si,offset mcoffs ; string to be played back
cld
ansmc4a:lodsb ; get a char into al
call pntchr ; print it, ignore errors
loop ansmc4a ; do all that came in previously
pop si
ansmc4b:pop cx
pop ax ; recover break char
ret
ansmc endp
; Check for PRN (DOS's printer) being ready. If ready, return with C clear.
; Otherwise, write Not Ready msg on mode line and return with C bit set.
; N.B. DOS Critical Error will occur here if PRN is not ready. [jrd]
pntchk proc near
push dx
push cx
push ax
mov cx,10 ; ten retries before declaring error
pntchk0: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 pntchk1 ; c = call failed
cmp al,0ffh ; code for Ready
je pntchk3 ; e = yes, assume printer is ready.
pntchk1:push cx ; save counter, just in case
mov ax,100 ; wait 100 millisec
call pcwait
pop cx
loop pntchk0 ; and try a few more times
test yflags,modoff ; is mode line off?
jnz pntchk2 ; nz = off, skip msg
push bx
push si
mov si,offset pntmsg ; say printer not ready
mov cx,pntmsgl ; length
call modwrt ; write alternate mode line, in msy
pop si
pop bx
pntchk2:pop ax
pop cx
pop dx
stc ; say printer not ready
ret
pntchk3:pop ax
pop cx
pop dx
clc ; say printer is ready
ret
pntchk endp
; Print on PRN the char in register al. On success return with C bit clear.
; On failure call procedure pntchk and return its C bit (typically C set).
pntchr proc near
push dx
push ax
mov ah,lstout ; uses file handle 4
mov dl,al
int dos
pop ax
pop dx
jnc pntchr2 ; nc = success
call pntchk ; c = error (printer not ready)
pntchr2:ret
pntchr endp
pntlin proc near ; print whole line given by dx
push ax
push bx
push cx
push dx
xor dl,dl ; start in column 0
xor ch,ch
mov cl,byte ptr low_rgt ; number of columns
mov dl,cl ; Bios column counter
inc cl ; actual line length, count it down
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
code ends
if1
%out [End of pass 1]
else
%out [End of assembly]
endif
end