home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
extra
/
nyenhuis3.arc
/
MSZIBM.ASM
< prev
Wrap
Assembly Source File
|
1990-01-16
|
182KB
|
5,314 lines
NAME mszibm
; File MSZIBM.ASM
include mssdef.h
; Terminal emulator module for IBM PC's and compatibles. Emulates Heath-19,
; VT52, VT102, and VT320. Original version for VT100 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 15 Jan 1990
; 29 May 1989 Rewrite and expand to DEC VT320 level. [jrd]
; 5 Oct 1988 Add controls to write from right to left, using bit vswdir in
; the setup bytes vtemu.vtflgst and vtemu.vtflgop. The concept was invented
; by Baruch Cochavy, IIT, Haifa, Israel; the current code is by [jrd].
; If vswdir is non-zero writing is done starting on the visual right side.
; Procedures direction and vtsclr accomdate most directional details. The
; implementation here retains DX and CURSOR as logical values while the
; physical screen coordinates are conditioned via proc direction and
; several sections of special code. Screen printing is done full width if
; writing right to left. Outside mszibm the logical cursor = physical. [jrd]
; 1 Jan 1988 version 2.30
; [Joe R. Doupnik, Utah State Univ]
public anstty, ansini, ansrei, ansdsl, anskbi ; Entry points
public ans52t, vsinit, tabset, tabclr, istabs
public mar_top, mar_bot, anspflg, scroll, video_state ; for msyibm
public dnparam, dparam, dlparam, dninter, dinter, emubufc, emubuf
public emubufl, dcsstrf, nrc2cp, cpdecsg
; * 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.
; 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.
; 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 terminal types.
; 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.
;
; Many things have been added or modified since James Harvey donated this
; code to Columbia University for use in Kermit. [jrd]
; Character sets in VT320 and VT102 modes:
; ASCII ("B"/94)
; ISO Latin-1 ("A"/96)
; DEC UK-ASCII ("A"/94, available only in VT102 mode)
; DEC Supplemental Graphics ("%5"/94),
; DEC Technical Graphics (">"/94), an extension taken from the VT340,
; DEC Special Graphics ("0"/94 and "2"/94)
; ALT-ROM (Kermit specific, "1"/94/96)
; DEC National Replacement Chars (all 12 sets)
; Startup:
; GL = G0 = G1 = ASCII (or ALT-ROM if selected by SET TERM CHAR ALT-ROM),
; GR = G2 = G3 = ISO Latin-1.
; When an NRC is selected by SET TERM CHAR <country> and enabled by
; CSI ? 42 h the NRC table replaces G0..G3 at the time of selection. When
; thus designated and selected incoming characters are forced to 7 bits and
; 8-bit Controls (outgoing) is turned off. No designation means no selection.
; Selecting a character set with the wrong sized designator yields no action.
;
; References:
; "PT200 Programmers Reference Guide", 1984, Prime Computer # DOC 8621-001P
; "Video Terminal Model H19, Operation", 1979, Heath Company # 595-2284-05
; "VT100 User's Guide", 2nd ed., Jan 1979, DEC # EK-VT100-UG
; "Rainbow 100+/100B Terminal Emulation Manual", June 1984, DEC # QV069-GZ
; "Installing and Using The VT320 Video Terminal", June 1987,
; DEC # EK-VT320-UU-001
; "VT320 Programmer Reference Manual", July 1987, DEC # EK-VT320-RM-001
; ---------------------------------------------------------------------------
swidth equ 132 ; assumed max screen width
slen equ 60 ; assumed max screen length
maxparam equ 10 ; number of ESC and DCS Parameters
maxinter equ 10 ; number of ESC and DCS Intermediates
gsize equ 128 ; character set storage size
; anspflg bit field definitions:
; prtscr equ 1 ; used in msyibm print screen toggle
vtautop equ 1 ; autoprint enabled (1)
vtcntp equ 2 ; controller print enabled (1)
vtextp equ 4 ; printer extent set (1)
vtffp equ 10h ; form feed wanted at end of print (1)
h19l25 equ 1 ; h19stat, line 25 enabled
h19alf equ 2 ; h19stat, auto cr/lf when cr seen
; display save-info for dspstate
dsptype equ 1 ; main (0) or status line (1) flag
dspdecom equ 2 ; remembered origin mode (1=on)
; DEC emulator status flags (bits in words vtemu.vtflgst and vtemu.vtflgop)
;anslnm equ 1H ; ANSI line feed/new line mode
;decawm equ 2H ; DEC autowrap mode
;decscnm equ 80H ; DEC screen mode
;decckm equ 200H ; DEC cursor keys mode
;deckpam equ 400H ; DEC keypad application mode
;decom equ 800H ; DEC origin mode
;deccol equ 1000H ; DEC column mode (0=80 col)
;decanm equ 2000H ; ANSI mode
;dececho equ 4000H ; ANSI local echo on (1 = on)
; Terminal SETUP mode flags (joint with bits above, some name dups)
;vsnewline equ 1H ; ANSI new line (0 = off)
;vswrap equ 2H ; Line wrap around (0 = no wrap)
;vsnrcm equ 4H ; National Rep Char set (0=none)
;vswdir equ 8H ; Writing direction (0=left, 1 right)
;vskeyclick equ 10H ; Keyclick (0 = off)
;vsmarginbell equ 20H ; Margin bell (0 = off)
;vscursor equ 40H ; Cursor (0 = block, 1 = underline)
;vsscreen equ 80H ; Screen (0 = normal, 1 = rev. video)
;vscntl equ 100h ; 8 or 7 bit controls (1 = 8-bit)
;vsdefaults equ 0+vscursor
; Kinds of terminals available
;ttgenrc equ 0 ; Type 0: no emulation done by Kermit
;ttheath equ 1 ; Type 1: Heath-19
;ttvt52 equ 2 ; Type 2: VT52
;ttvt100 equ 3 ; Type 3: VT102
;ttvt320 equ 4 ; Type 4: VT320
;tttek equ 5 ; Type 5: Tektronix 4010
;TTTYPES equ 6 ; Number of terminal types defined
;emulst struc ; structure of vtemu.xxx for VTxxx emulator
;vtflgst dw 0 ; DEC setup flags (from SET)
;vtflgop dw 0 ; DEC 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
;vtchset db 1 ; value of default character set (1=US-ascii)
;att_ptr dw 0 ; pointer to normal & reverse video attributes
;emulst ends
;;;;;;;;;;;;;;;; end references ;;;;;;;;;;;;;;;;;;;;
data segment public 'data'
extrn vtemu:byte, scbattr:byte, flags:byte, yflags:byte
extrn crt_lins:byte, crt_cols:byte, rxtable:byte, denyflg:word
extrn tekflg:byte, vtclear:byte, dosnum:word, chcontrol:byte
extrn parstate:word, pardone:word, parfail:word, nparam:word,
extrn param:word, lparam:byte, ninter:word, inter:byte
extrn L1cp437:byte, L1cp850:byte, L1cp860:byte, L1cp863:byte
extrn L1cp865:byte
even ; C0 7-bit control code table
ansc0 dw 5 dup (atign) ; NUL, SOH, STX, ETX, EOT
dw atign,atign,vtbell,atbs,atht ; ENQ, ACK, BEL, BS, HT
dw atlf, atlf, atff, atcr,atls1 ; LF, VT, FF, CR, SO
dw atls0, 4 dup (atign) ; SI, DLE, DC1, DC2, DC3
dw 4 dup (atign), atcan ; DC4, NAK, SYN, ETB, CAN
dw atign, atcan,atesc,atign,atign ; EM, SUB, ESC, FS, GS
dw 2 dup (atign) ; RS, US
; C1 8-bit control code table
ansc1 dw 4 dup (atign),atind ; ignore 4, IND
dw atnel,atign,atign,athts,atign ; NEL, SSA, ESA, HTS, HTJ
dw atign,atign,atign,atri, atign ; VTS, PLD, PLU, RI, SS2
dw atign,atdcs,3 dup (atign) ; SS3, DCS, PU1, PU2, STS
dw 5 dup (atign) ; CCH, MW, SPA, EPA, ignore
dw atign,atign,atcsi,atgotst,atdcsnul; ignore 2, CSI, ST, OSC
dw 2 dup (atdcsnul) ; PM, APC
; Heath-19 mode escape follower table
h19esc db 36 ; number of entries
dw h19ejt ; address of action routines
db '<=>@A','BCDEF','GHIJK','LMNOY','Z[bjk','lnopq','rvwxy','z'
; Dispatch table for Heath-19 escape sequence table h19esc
even
h19ejt dw h19sans, atkpam, atkpnm, entins, atcuu ; '<=>@A'
dw atcud, atcuf, atcub, h19clrs, v52sgm ; 'BCDEF'
dw chrdef, atcup, atri, ated, atel ; 'GHIJK'
dw inslin, dellin, atdelc, noins, v52pos ; 'LMNOY'
dw decid, h19csi, h19esos, h19sc, h19rc ; 'Z[bjk'
dw h19erl, hrcup, h19ero, h19herv, h19hxrv ; 'lnopq'
dw atnorm, h19wrap, h19nowrp,h19smod, h19cmod ; 'rvwxy'
dw atxreset ; 'z'
h19ans db 21 ; Heath-19 ANSI style escape sequences
dw h19jmp ; address of action routine table
db 'ABCDH','JKLMP','fhlmn','pqrsu','z'
; Heath-19 action table for h19ans
even
h19jmp dw atcuu, atcud, atcuf, atcub, atcup ; 'ABCDH'
dw h19ed, atel, inslin, dellin, atdelc ; 'JKLMP'
dw atcup, atsm, atrm, atsgr, rpcup ; 'fhlmn'
dw atign, atign, atign, h19sc, h19rc ; 'pqrsu'
dw atxreset ; 'z'
; VT52 compatibility mode escape follower table
v52esc db 23 ; number of entries
dw v52ejt ; address of action routines
db '78<=>', 'ABCDF', 'GHIJK', 'VWXYZ'
db ']',5eh,5fh ; 5eh = caret, 5fh = underscore
; Dispatch for v52esc table
even
v52ejt dw atsc, atrc, v52ans, atkpam, atkpnm ; '78<=>'
dw atcuu, atcud, atcuf, atcub, v52sgm ; 'ABCDF'
dw chrdef, atcup, atri, ated, atel ; 'GHIJK'
dw v52pl, v52pcb, v52pce, v52pos, decid ; 'VWXYZ'
dw v52ps, v52pcb, v52pce ; ']^_'
; VT320/VT102 ANSI mode escape follower table
ansesc db 37 ; number of entries
dw ansejt ; address of action routines
db '01234','5678<', '=>?AB', 'DEFGH', 'MNOPZ'
db '[\]',5eh,5fh ; 5eh = caret, 5fh=underscore
db 'cno',7bh,7ch ; 7bh=left curly brace, 7ch=vert bar
db 7dh,7eh ; 7dh=right curly brace, 7eh=tilde
; Dispatch for ansesc table
even
ansejt dw atdgf0, atdgf1, atdgf0, atsdhl, atsdhl ; '01234'
dw 4 dup (atsdhl), atdgfu ; '5678<'
dw atkpam, atdgft, atdgfq, atdgfA, atdgfB ; '=>?AB'
dw atind, atnel, ats7c, ats8c, athts ; 'DEFGH'
dw atri, atss2, atss3, atdcs, decid ; 'MNOPZ'
dw atcsi, atgotst, 3 dup(atdcsnul) ; '[\]^_'
dw atxreset,atls2, atls3, atpriv, atls3r ; 'cno{|'
dw atls2r, atls1r ; '}~'
; Final char table for VT320/VT102 ANSI escape sequences
anstab db 38 ; number of entries
dw ansjmp ; address of action routines
db '@ABCD','EFGHI','JKLMP','RXacd','efghi','lmnpq','ruwxy'
db 'z',7dh,7eh ; 7dh=right curly brace, 7eh=tilde
; Dispatch for anstab table
even
ansjmp dw ansich, atcuu, atcud, atcuf, atcub ; '@ABCD'
dw atcnl, atcpl, atcha, atcup, atcht ; 'EFGHI'
dw ated, atel, inslin, dellin, atdelc ; 'JKLMP'
dw rpcup, atech, atcuf, atda, atcva ; 'RXacd'
dw atcud, atcup, attbc, atsm, ansprt ; 'efghi'
dw atrm, atsgr, atdsr, decscl, atll ; 'lmnpq'
dw atstbm, atrqtsr,atrqpsr,atreqt, atctst ; 'ruwxy'
dw atxreset,atsasd, atssdt ; 'z}~'
; Final character table for Device Control Strings (DCS, ESC P)
dcstab db 5 ; number of entries
dw dcsjmp ; address of action routines
db 'pqu',7bh,7ch ; 7bh = left curly brace
; Dispatch for dcstab table
even
dcsjmp dw atcrqq, atcrq, atupss, atdcsnul, atudk ; 'pqu{|'
;;; DCS Ps $ p string ST page 209 restore color palette
; Heath-19 special graphics characters to CP437. Use as offsets from caret
; (94D)
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,177,219, 25,220 ; h,i,j,k,l
db 220,223,223,223,222 ; m,n,o,p,q
db 16,194,180,193,195 ; r,s,t,u,v
db 'X','/','\',223,220 ; w,x,y,z,left curly brace
db 221,222, 20 ; vertical bar,right curly brace,tilde
hgrtabl equ ($-hgrtab)
; VT320/VT102 "Special graphics" set translation table for characters 95..126d
; when the special graphics set is selected. Some characters (98, 99, 100,
; 101, 104, 105, 111, 112, 114, 115, and 116) do not have exact equivalents
; in the available set on the IBM, so a close substitution is made.
; Table is indexed by ASCII char value minus 95 for chars 95..126d.
sgrtab db 32, 4,177, 26, 23, 27, 25,248,241, 21
db 18,217,191,218,192, 197,196,196,196,196
db 196,195,180,193,194, 179,243,242,227,157
db 156,250
sgrtabl equ $-sgrtab
; DEC National Replacement Char sets, one table for each Code Page
; CP437
; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
nrc437 db 23h,40h,5bh,5ch,5dh,5eh ; 0, ASCII, "B", dispatch ref
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'B',0 ; 94 byte set, letter pair
db 9ch,40h,5bh,5ch,5dh,5eh ; 1, British, "A"
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'A',0
db 9ch,3fh,98h,0abh,7ch,5eh ; 2, Dutch, "4"
db 5fh,60h,22h,9fh,0ach,27h
db 94,'4',0
db 23h,40h,8eh,99h,8fh,9ah ; 3, Finnish, "5"
db 5fh,82h,84h,94h,86h,81h
db 94,'5',0
db 9ch,85h,0f8h,87h,15h,5eh ; 4, French, "R"
db 5fh,60h,82h,97h,8ah,22h
db 94,'R',0
db 23h,85h,83h,87h,88h,8ch ; 5, French Canadian, "9"
db 5fh,93h,82h,97h,8ah,96h
db 94,'9',0
db 23h,15h,8eh,99h,9ah,5eh ; 6, German, "K"
db 5fh,60h,84h,94h,81h,0e1h
db 94,'K',0
db 9ch,15h,0f8h,87h,82h,5eh ; 7, Italian, "Y"
db 5fh,97h,85h,95h,8ah,8dh
db 94,'Y',0
db 23h,40h,92h,0edh,8fh,5eh ; 8, Norwegian/Danish, "'"
db 5fh,60h,91h,0edh,86h,7eh
db 94,60h,0
db 23h,40h,8eh,80h,99h,5eh ; 9, Portugese, "%6"
db 5fh,60h,0a6h,87h,0a7h,7eh
db 94,'%','6'
db 9ch,15h,8ch,0a5h,0a8h,5eh ; 10, Spanish, "Z"
db 5fh,60h,60h,0f8h,0a4h,87h
db 94,'Z',0
db 23h,90h,8eh,99h,8fh,9ah ; 11, Swedish, "7"
db 5fh,82h,84h,94h,86h,81h
db 94,'7',0
db 97h,85h,82h,87h,88h,8ch ; 12, Swiss, "="
db 8ah,93h,84h,94h,81h,96h
db 94,'=',0
; CP850
; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
nrc850 db 23h,40h,5bh,5ch,5dh,5eh ; 0, ASCII, "B", dispatch ref
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'B',0 ; 94 byte set, letter pair
db 9ch,40h,5bh,5ch,5dh,5eh ; 1, British, "A"
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'A',0
db 9ch,0f3h,98h,0abh,7ch,5eh ; 2, Dutch, "4"
db 5fh,60h,22h,9fh,0ach,27h
db 94,'4',0
db 23h,40h,8eh,99h,8fh,9ah ; 3, Finnish, "5"
db 5fh,82h,84h,94h,86h,81h
db 94,'5',0
db 9ch,85h,0f8h,87h,15h,5eh ; 4, French, "R"
db 5fh,60h,82h,97h,8ah,22h
db 94,'R',0
db 23h,85h,83h,87h,88h,8ch ; 5, French Canadian, "9"
db 5fh,93h,82h,97h,8ah,96h
db 94,'9',0
db 23h,15h,8eh,99h,9ah,5eh ; 6, German, "K"
db 5fh,60h,84h,94h,81h,0e1h
db 94,'K',0
db 9ch,15h,0f8h,87h,82h,5eh ; 7, Italian, "Y"
db 5fh,97h,85h,95h,8ah,8dh
db 94,'Y',0
db 23h,40h,92h,09dh,8fh,5eh ; 8, Norwegian/Danish, "'"
db 5fh,60h,91h,09bh,86h,7eh
db 94,60h,0
db 23h,40h,0b5h,80h,0e5h,5eh ; 9, Portugese, "%6"
db 5fh,60h,61h,87h,0e4h,7eh
db 94,'%','6'
db 9ch,15h,0adh,0a5h,0a8h,5eh ; 10, Spanish, "Z"
db 5fh,60h,60h,0f8h,0a4h,87h
db 94,'Z',0
db 23h,90h,8eh,99h,8fh,9ah ; 11, Swedish, "7"
db 5fh,82h,84h,94h,86h,81h
db 94,'7',0
db 97h,85h,82h,87h,88h,8ch ; 12, Swiss, "="
db 8ah,93h,84h,94h,81h,96h
db 94,'=',0
; CP860
; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
nrc860 db 23h,40h,5bh,5ch,5dh,5eh ; 0, ASCII, "B", dispatch ref
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'B',0 ; 94 byte set, letter pair
db 9ch,40h,5bh,5ch,5dh,5eh ; 1, British, "A"
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'A',0
db 9ch,3fh,79h,0abh,7ch,5eh ; 2, Dutch, "4"
db 5fh,60h,22h,3fh,0ach,27h
db 94,'4',0
db 23h,40h,41h,4fh,41h,9ah ; 3, Finnish, "5"
db 5fh,82h,61h,6fh,61h,81h
db 94,'5',0
db 9ch,85h,0f8h,87h,15h,5eh ; 4, French, "R"
db 5fh,60h,82h,97h,8ah,22h
db 94,'R',0
db 23h,85h,83h,87h,88h,69h ; 5, French Canadian, "9"
db 5fh,93h,82h,97h,8ah,75h
db 94,'9',0
db 23h,15h,41h,4fh,9ah,5eh ; 6, German, "K"
db 5fh,60h,61h,6fh,81h,0e1h
db 94,'K',0
db 9ch,15h,0f8h,87h,82h,5eh ; 7, Italian, "Y"
db 5fh,97h,85h,95h,8ah,8dh
db 94,'Y',0
db 23h,40h,3fh,0edh,41h,5eh ; 8, Norwegian/Danish, "'"
db 5fh,60h,3fh,0edh,61h,7eh
db 94,60h,0
db 23h,40h,8eh,80h,99h,5eh ; 9, Portugese, "%6"
db 5fh,60h,84h,87h,94h,7eh
db 94,'%','6'
db 9ch,15h,0adh,0a5h,0a8h,5eh ; 10, Spanish, "Z"
db 5fh,60h,60h,0f8h,0a4h,87h
db 94,'Z',0
db 23h,90h,41h,4fh,41h,9ah ; 11, Swedish, "7"
db 5fh,82h,61h,6fh,61h,75h
db 94,'7',0
db 97h,85h,82h,87h,88h,69h ; 12, Swiss, "="
db 8ah,93h,61h,6fh,81h,75h
db 94,'=',0
; CP863
; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
nrc863 db 23h,40h,5bh,5ch,5dh,5eh ; 0, ASCII, "B", dispatch ref
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'B',0 ; 94 byte set, letter pair
db 9ch,40h,5bh,5ch,5dh,5eh ; 1, British, "A"
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'A',0
db 9ch,0adh,79h,0abh,7ch,5eh ; 2, Dutch, "4"
db 5fh,60h,0a4h,9fh,0ach,0a1h
db 94,'4',0
db 23h,40h,41h,4fh,41h,55h ; 3, Finnish, "5"
db 5fh,82h,61h,6fh,61h,81h
db 94,'5',0
db 9ch,85h,0f8h,87h,15h,5eh ; 4, French, "R"
db 5fh,60h,82h,97h,8ah,0a4h
db 94,'R',0
db 23h,85h,83h,87h,88h,8ch ; 5, French Canadian, "9"
db 5fh,93h,82h,97h,8ah,96h
db 94,'9',0
db 23h,15h,41h,4fh,9ah,5eh ; 6, German, "K"
db 5fh,60h,61h,6fh,81h,0e1h
db 94,'K',0
db 9ch,15h,0f8h,87h,82h,5eh ; 7, Italian, "Y"
db 5fh,97h,6fh,85h,8ah,69h
db 94,'Y',0
db 23h,40h,3fh,0edh,41h,5eh ; 8, Norwegian/Danish, "'"
db 5fh,60h,0efh,0edh,61h,7eh
db 94,60h,0
db 23h,40h,41h,80h,4fh,5eh ; 9, Portugese, "%6"
db 5fh,60h,61h,87h,6fh,7eh
db 94,'%','6'
db 9ch,15h,3fh,4eh,3fh,5eh ; 10, Spanish, "Z"
db 5fh,60h,60h,0f8h,6eh,87h
db 94,'Z',0
db 23h,90h,41h,4fh,41h,9ah ; 11, Swedish, "7"
db 5fh,82h,61h,6fh,61h,81h
db 94,'7',0
db 97h,85h,82h,87h,88h,8ch ; 12, Swiss, "="
db 8ah,93h,61h,6fh,81h,96h
db 94,'=',0
; CP865
; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
nrc865 db 23h,40h,5bh,5ch,5dh,5eh ; 0, ASCII, "B", dispatch ref
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'B',0 ; 94 byte set, letter pair
db 9ch,40h,5bh,5ch,5dh,5eh ; 1, British, "A"
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'A',0
db 9ch,3fh,98h,0abh,7ch,5eh ; 2, Dutch, "4"
db 5fh,60h,22h,9fh,0ach,27h
db 94,'4',0
db 23h,40h,8eh,99h,8fh,9ah ; 3, Finnish, "5"
db 5fh,82h,84h,94h,86h,81h
db 94,'5',0
db 9ch,85h,0f8h,87h,15h,5eh ; 4, French, "R"
db 5fh,60h,82h,97h,8ah,22h
db 94,'R',0
db 23h,85h,83h,87h,88h,8ch ; 5, French Canadian, "9"
db 5fh,93h,82h,97h,8ah,96h
db 94,'9',0
db 23h,15h,8eh,99h,9ah,5eh ; 6, German, "K"
db 5fh,60h,84h,94h,81h,0e1h
db 94,'K',0
db 9ch,15h,0f8h,87h,82h,5eh ; 7, Italian, "Y"
db 5fh,97h,85h,95h,8ah,8dh
db 94,'Y',0
db 23h,40h,92h,9dh,8fh,5eh ; 8, Norwegian/Danish, "'"
db 5fh,60h,91h,9bh,86h,7eh
db 94,60h,0
db 23h,40h,41h,80h,4fh,5eh ; 9, Portugese, "%6"
db 5fh,60h,61h,87h,6fh,7eh
db 94,'%','6'
db 9ch,15h,0adh,0a5h,0a8h,5eh ; 10, Spanish, "Z"
db 5fh,60h,60h,0f8h,0a4h,87h
db 94,'Z',0
db 23h,90h,8eh,99h,8fh,9ah ; 11, Swedish, "7"
db 5fh,82h,84h,94h,86h,81h
db 94,'7',0
db 97h,85h,82h,87h,88h,8ch ; 12, Swiss, "="
db 8ah,93h,84h,94h,81h,96h
db 94,'=',0
;NRC to DEC keyboard codes, North American (ASCII is nrckbd 1),+ALT-ROM+transp
nrckbd db 1,2,8,6,14,4,7,9,13,16,15,12,11,1,1,1
; Translation tables for byte codes 0a0h..0ffh to map DEC Multinational
; Character Set (DEC Supplemental Graphic) to Code Pages.
; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is
; considered to be a control code, 80h..9fh are 8-bit controls (C1).
; Each table is 94 translatable bytes followed by the table size (94), the
; ISO announcer ident '%5'.
; from DEC Multinational to Code Page
; to CP437
MNcp437 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8
db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh
db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9
db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh
db 0h,0adh,9bh,9ch, 20h,9dh,20h,15h ; column 10
db 0fh,40h,0a6h,0aeh, 20h,20h,20h,20h
db 0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0feh ; column 11
db 2eh,60h,0a7h,0afh, 0ach,0abh,20h,0a8h
db 85h,0a0h,83h,83h, 8eh,8fh,92h,80h ; column 12
db 8ah,90h,88h,89h, 8dh,0a1h,8ch,8bh
db 20h,0a5h,95h,0a2h, 93h,94h,94h,4fh ; column 13
db 0edh,97h,0a3h,96h, 9ah,59h,20h,0e1h
db 85h,0a0h,83h,84h, 84h,86h,91h,87h ; column 14
db 8ah,82h,88h,89h, 8dh,0a1h,8ch,8bh
db 20h,0a4h,95h,0a2h, 93h,94h,94h,6fh ; column 15
db 0edh,97h,0a3h,96h, 81h,98h,20h,0h
db 94,'%','5' ; 94 byte set, letter ident
; to CP850
MNcp850 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8
db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh
db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9
db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh
db 0h,0adh,0bdh,9ch, 20h,0beh,20h,15h ; column 10
db 0cfh,0b8h,0a6h,0aeh, 20h,20h,20h,20h
db 0f8h,0f1h,0fdh,0fch, 20h,0e6h,14h,0feh ; column 11
db 2eh,0fbh,0a7h,0afh, 0ach,0abh,20h,0a8h
db 0b7h,0b5h,0b6h,0b5h, 8eh,8fh,92h,80h ; column 12
db 0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h
db 20h,0a5h,0e3h,0e0h, 0e2h,0e5h,99h,4fh ; column 13
db 9dh,0ebh,0e9h,0eah, 9ah,0edh,20h,0e1h
db 85h,0a0h,83h,61h, 84h,86h,91h,87h ; column 14
db 8ah,82h,88h,89h, 8dh,0a1h,8ch,8bh
db 20h,0a4h,95h,0a2h, 93h,0e4h,94h,6fh ; column 15
db 9bh,97h,0a3h,96h, 81h,0ech,20h,0h
db 94,'%','5' ; 94 byte set, letter ident
; to CP860
MNcp860 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8
db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh
db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9
db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh
db 0h,0adh,9bh,9ch, 20h,59h,20h,15h ; column 10
db 0fh,3fh,0a6h,0aeh, 20h,20h,20h,20h
db 0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0feh ; column 11
db 2eh,60h,0a7h,0afh, 0ach,0abh,20h,0a8h
db 85h,0a0h,83h,83h, 8eh,8fh,92h,80h ; column 12
db 8ah,90h,88h,89h, 8dh,0a1h,8ch,8bh
db 20h,0a5h,95h,0a2h, 93h,94h,94h,4fh ; column 13
db 0edh,97h,0a3h,96h, 9ah,59h,20h,0e1h
db 85h,0a0h,83h,84h, 84h,86h,91h,87h ; column 14
db 8ah,82h,88h,89h, 8dh,0a1h,8ch,8bh
db 20h,0a4h,95h,0a2h, 93h,94h,94h,6fh ; column 15
db 0edh,97h,0a3h,96h, 81h,98h,20h,0h
db 94,'%','5' ; 94 byte set, letter ident
; to CP863
MNcp863 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8
db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh
db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9
db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh
db 0h,0adh,9bh,9ch, 20h,9dh,20h,15h ; column 10
db 98h,40h,61h,0aeh, 20h,20h,20h,20h
db 0f8h,0f1h,0fdh,33h, 20h,0e6h,86h,0feh ; column 11
db 2eh,31h,6fh,0afh, 0ach,0abh,20h,3fh
db 8eh,41h,84h,41h, 41h,41h,3fh,80h ; column 12
db 91h,90h,92h,94h, 49h,49h,88h,95h
db 20h,4eh,4fh,4fh, 99h,4fh,4fh,4fh ; column 13
db 0edh,9dh,55h,0aeh, 55h,59h,20h,0e1h
db 85h,61h,83h,61h, 61h,61h,3fh,87h ; column 14
db 8ah,82h,88h,89h, 69h,69h,8ch,8bh
db 20h,6eh,6fh,0a2h, 93h,6fh,6fh,6fh ; column 15
db 0edh,97h,0a3h,96h, 75h,79h,20h,0h
db 94,'%','5' ; 94 byte set, letter ident
; to CP865
MNcp865 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8
db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh
db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9
db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh
db 0h,0adh,3fh,9ch, 20h,3fh,20h,15h ; column 10
db 0afh,3fh,0a6h,0aeh, 20h,20h,20h,20h
db 0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0feh ; column 11
db 2eh,31h,0a7h,03fh, 0ach,0abh,20h,0a8h
db 41h,41h,41h,41h, 8eh,8fh,92h,80h ; column 12
db 45h,90h,45h,45h, 49h,49h,49h,49h
db 20h,0a5h,4fh,4fh, 4fh,4fh,99h,4fh ; column 13
db 0edh,55h,55h,55h, 9ah,59h,20h,0e1h
db 85h,0a0h,83h,61h, 84h,86h,91h,87h ; column 14
db 8ah,82h,88h,89h, 8dh,0a1h,8ch,8bh
db 20h,0a4h,95h,0a2h, 93h,6fh,94h,6fh ; column 15
db 0edh,97h,0a3h,96h, 81h,79h,20h,0h
db 94,'%','5' ; 94 byte set, letter ident
; 128 byte translation tables from Code Pages to DEC Multinational char set
; (DEC Supplemental Graphic). For GRight only (high bit set).
; from Code Page 437
cp437MN db 0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
db 0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
db 0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
db 0ffh,0d6h,0dch,0a2h, 0a3h,0a5h,3fh,3fh
db 0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
db 0bfh,3fh,0ach,0bdh, 0bch,0a1h,0abh,0bbh
db 16 dup (3fh) ; column 11
db 16 dup (3fh) ; column 12
db 16 dup (3fh) ; column 13
db 3fh,0dfh, 4 dup (3fh), 0b5h,3fh ; column 14
db 5 dup(3fh), 0f8h,3fh,3fh
db 3fh,0b1h, 4 dup (3fh), 0h,3fh ; column 15
db 0b0h, 4 dup (3fh), 0b2h,0b7h,3fh
; from Code Page 850
cp850MN db 0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
db 0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
db 0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
db 0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,58h,3fh
db 0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
db 0bfh,0aeh,0ach,0bdh, 0bch,0a1h,0abh,0bbh
db 5 dup (3fh), 0c1h,0c2h,0c0h ; column 11
db 0a9h, 4 dup (3fh), 0a2h,0a5h,0ach
db 6 dup (3fh),0e3h,0c3h, 7 dup (3fh),0a4h ; column 12
db 0f0h,0d0h,0cah,0cbh, 0c8h,0b9h,0cdh,0ceh ; column 13
db 0cfh, 4 dup (3fh), 7ch,0cch,3fh
db 0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,0deh ; column 14
db 0feh,0dah,0dbh,0d9h, 0fdh,0ddh,0afh,0b4h
db 0adh,0b1h,3dh,0beh, 0b6h,0a7h,00h,22h ; column 15
db 0b0h,0a8h,3fh,0b9h, 0b2h,0b3h,0b7h,20h
; from Code Page 860
cp860MN db 0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8
db 0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h
db 0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9
db 0cch,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h
db 0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
db 0bfh,0d2h,0ach,0bdh, 0bch,0a1h,0abh,0bbh
db 16 dup (3fh) ; column 11
db 16 dup (3fh) ; column 12
db 16 dup (3fh) ; column 13
db 3fh,0dfh, 4 dup (3fh), 0b5h,3fh ; column 14
db 5 dup(3fh), 0f8h,3fh,3fh
db 3fh,0b1h, 4 dup (3fh), 0h,3fh ; column 15
db 0b0h, 4 dup (3fh), 0b2h,0b7h,3fh
; from Code Page 863
cp863MN db 0c7h,0fch,0e9h,0e2h, 0e2h,0e0h,0b6h,0a2h ; column 8
db 0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h
db 0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0fah ; column 9
db 0a4h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh
db 7ch,0b4h,0f3h,0fah, 0a8h,0a8h,0b3h,0afh ; column 10
db 0ceh,3fh,0ach,0bdh, 0bch,0beh,0abh,0bbh
db 16 dup (3fh) ; column 11
db 16 dup (3fh) ; column 12
db 16 dup (3fh) ; column 13
db 3fh,0dfh, 4 dup (3fh), 0b5h,3fh ; column 14
db 5 dup(3fh), 0f8h,3fh,3fh
db 3fh,0b1h, 4 dup (3fh), 0h,3fh ; column 15
db 0b0h, 4 dup (3fh), 0b2h,0b7h,3fh
; from Code Page 865
cp865MN db 0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
db 0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
db 0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0fah ; column 9
db 0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
db 0e2h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
db 0bfh,3fh,0ach,0bdh, 0bch,0a1h,0abh,0a4h
db 16 dup (3fh) ; column 11
db 16 dup (3fh) ; column 12
db 16 dup (3fh) ; column 13
db 3fh,0dfh, 4 dup (3fh), 0b5h,3fh ; column 14
db 5 dup(3fh), 0f8h,3fh,3fh
db 3fh,0b1h, 4 dup (3fh), 0h,3fh ; column 15
db 0b0h, 4 dup (3fh), 0b2h,0b7h,3fh
; Dec Technical set to CP437, CP860, CP863, CP865
; Note: CP850 lacks the symbols so expect trash
dectech db 32 dup (0) ; columns 8 and 9
db 0h,0fbh,0dah,0c4h, 0f4h,0f5h,0b3h,0dah ; column 10
db 0c0h,0bfh,0d9h,28h,28h,29h,29h,0b4h
db 0c3h,3ch,3eh,5ch, 2fh,0bfh,0d9h,03eh ; column 11
db 0a8h,20h,20h,20h, 0f3h,3dh,0f2h,3fh
db 1eh,0ech,0ech,0f6h,1eh,1fh,0e8h,0e2h ; column 12
db 0f7h,0f7h,0e9h,58h,3fh,1dh,1ah,0f0h
db 0e3h,3fh,20h,0e4h, 20h,20h,0fbh,0eah ; column 13
db 3fh,54h,3fh,3fh, 0efh,55h,5eh,76h
db 0aah,0e0h,0e1h,78h,0ebh,0eeh,0edh,3fh ; column 14
db 6eh,69h,0e9h,6bh, 3fh,20h,76h,3fh
db 0e3h,3fh,70h,0e5h, 0e7h,0a8h,9fh,77h ; column 15
db 45h,76h,3fh,1bh, 18h,1ah,19h,7fh
db 94,3eh,0 ; 94 byte set, letter ident
; Device attributes response string. A VT100 reports as ESC [ ? 1 ; 2 c
; Make strings asciiz.
v32str db escape,'[?63;1;2;4;8;9;15c',0; VT320, level 3,
; 132 col, printer, Sixel graphics, UDkeys,NRC,DEC Tech Chars
v32sda db escape,'[>24;0;0c',0 ; VT320 secondary DA response
v102str db escape,'[?6c',0 ; VT102
v52str db escape,'/Z',0 ; VT100 in VT52 compatibility mode
h19str db escape,'/K',0 ; Heath-19 (says plain VT52)
; parity code translation table
partab db 5,3,1,4,2 ; even, mark, none, odd, space
lpartab equ $-partab
parcode db 0 ; parity code (0-4)
; baud rate code translation table
; 45.5 - no VT100 code (call it 50),50,75,110,134.5,150,300,600,1200,
; 1800,2000,2400,4800,9600,19200,38400,57600,115200 extended beyond DEC
baudtab db 0,0,8,16,24,32,48,56,64,72,80,88,104,112,120,128,128,128
lbaudtab equ $-baudtab
baudidx db 0 ; index into baud rate table
datbits db 7 ; number of databits (7 or 8)
ttstate dw offset atnrm ; terminal automata state
ttstateST dw offset atnorm ; state for action after ST seen
att_normal db 07H ; default normal screen coloring
oldterm db 0 ; terminal type from previous entry
iniflgs dw 0 ; status flags at entry time
modeset db 0 ; temp for atsm/atrm
anspflg db 0 ; printer flag bits and definitions
h19stat db 0 ; H-19 extra status bits
h19ctyp db 1 ; H-19 cursor type (1=ul, 2=bk, 4=off)
h19cur dw 0 ; H-19 saved cursor position
atctype db 1 ; VTxxx cursor type (1=ul,2=bk, 4=off)
insmod db 0 ; insert mode on (1) or off (0)
belcol db 72 ; column at which to ring margin bell
kbicsr dw 0 ; cursor when keyboard input typed
kbiflg db 0 ; set/reset for keyboard input
ttkbi db 0 ; flag for keyboard input seen
transflg db 0 ; flag to say TRANSLATE INPUT worked
setptr dw 0 ; hold offset of designated char set
upss db 96,'A',0,0 ; User Preferred Supplemental Set
; size, ident (DEC Supplemental Gr)
; Start of save cursor material
savelist equ this byte ; top of list of things to save
cursor dw 0 ; cursor position
curattr db 07h ; cursor attribute
svattr_index equ $-savelist ; offset of saved cursor attribute
video_state db 0 ; video state (0=normal, 1=reversed)
atwrap db 0 ; autowrap flag
GLptr dw 0 ; pointer to char set for GL
GRptr dw 0 ; pointer to char set for GR
SSptr dw 0 ; pointer to char set for single shift
G0set db gsize+3 dup (0) ; make G0..G3 char set space
G1set db gsize+3 dup (0)
G2set db gsize+3 dup (0)
G3set db gsize+3 dup (0)
lsavecu equ $-savelist ; length of stuff to save
savecu db lsavecu dup (0) ; saved cursor, attr., charset, etc
savflgs dw 0 ; saved flags for atsc/atrc
; End of save cursor matieral
; tab stops, stored here
tabs db (swidth+7)/8 dup (0) ; active tab stops, one column per bit
deftabs db (swidth+7)/8 dup (0) ; default (setup) tab stops
; byte per line, type of line: 0=normal, 1=double wide, 2=double high
linetype db slen dup (0)
low_rgt dw 0 ; text screen dimensions
; byte low_rgt = max column (79)
; byte low_rgt+1 = max row (23)
oldscrn dw 0 ; old screen. hi=rows-1, low=cols-1
; Scrolling region - do not separate or change order of mar_top & mar_bot
mar_top db 0 ; scrolling region top margin
mar_bot db 23 ; scrolling region bottom margin
scroll db 1 ; lines to scroll
dspstate db 0 ; Display state (mode)line work byte
dspmsave dw 0 ; saved main dsp scrolling margins
dspcstat dw 0 ; saved cursor pos for status line
dspcmain dw 0 ; saved cursor pos for main display
led_col equ 65 ; column position for "LEDs" display
led_off equ '.' ; "Off" LED
v32leds db 'VT320 ' ; VT320 mode (all 10 characters)
ansleds db 'VT102 ....' ; VT102 mode
v52leds db 'VT52 ' ; VT52 mode
h19leds db 'Heath-19 ' ; Heath-19 mode
even ; Control sequence storage area
dnparam dw 0 ; number of parameters for DCS
dparam dw maxparam dup (0) ; Parameters for DCS
dlparam db 0 ; a single letter Parameter for DCS
dninter dw 0 ; number of DCS intermediates
dinter db maxinter dup (0) ; Intermediates for DCS
dcsstrf db 0 ; Final char of DCS
emubufc dw 0 ; count of chars in string buffer
emubuf db 66 dup (0) ; emulator string storage buffer
db 0 ; safety for string overflow
emubufl dw $-emubuf ; length of emulator buffer
data ends
code2 segment public 'code2'
extrn tekini:far, tekemu:far, tekend:far
code2 ends
code segment public 'code'
extrn prtbout:near, prtnout:near, csrtype:near, atsclr:near
extrn vtscru:near, vtscrd:near, chgdsp:near, trnprs:near
extrn cptchr:near, pntchr:near, pntchk:near, setpos:near
extrn pntflsh:near, vtbell:near, vtrmac:near,vtsmac:near
extrn getpos:near, setatch:near, getatch:near, putchar:near
extrn revideo:near, getbold:near, setbold:near, clrbold:near
extrn getblink:near, setblink:near, clrblink:near, getunder:near
extrn setunder:near, clrunder:near, revscn:near, setcolor:near
extrn clrmod:near, modlin:near, setudk:near, udkclear:near
extrn setrev:near, clrrev:near
extrn out8bit:near, atparse:near, atpclr:near, atdispat:near
extrn insdecom:near, tekinq:near, tekpal:near, dec2di:near
assume cs:code, ds:data, es:nothing
; 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 ; e = 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 ttstate ; print transparently
anstt4: or al,al ; NUL char?
jz atign ; z = 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 vtemu.vtchset,12 ; ASCII (0) or NRC's (1-12) active?
ja anstt8b ; a = no
cmp vtemu.vtchset,0 ; ASCII?
je anstt8b ; e = yes
and al,7fh ; yes, NRCs force chars to 7-bits
anstt8b:test al,not 9fh ; control chars (0-1fh, 80h-9fh)?
jnz anstt9 ; nz = no
jmp atctrl ; process control chars
anstt9: jmp ttstate ; dispatch according to state
anstty endp
atign: ret ; something to be ignored
atnorm: mov ttstate,offset atnrm ; reset state to "normal"
mov ttstateST,offset atnorm ; reset state for ST seen
ret
atnrm proc near ; Normal character (in AL) processor
cmp rxtable+256,0 ; TRANSLATION INPUT turned off?
je atnrm14 ; e = yes, use ISO mechanisms
mov bx,offset rxtable ; address of translate table
mov ah,al ; copy char
xlatb ; new char is in al
cmp ah,al ; different (translation requested)?
jne short atnrm13 ; ne = yes, skip ISO-2022 mechanism
atnrm14:cmp SSptr,0 ; single shift needed?
je atnrm10 ; e = no
and al,not 80h ; strip high bit
mov bx,SSptr ; pointer to desired char set
mov SSptr,0 ; clear single shift indicator
jmp short atnrm12 ; process
atnrm10:test al,80h ; high bit set for GRight?
jnz atnrm11 ; nz = yes
mov bx,GLptr ; GL char set
jmp short atnrm12 ; process
atnrm11:and al,not 80h ; strip high bit
mov bx,GRptr ; GR char set
atnrm12:xlatb ; translate al to new char in al
atnrm13:cmp al,DEL ; ANSI Delete char?
jne atnrm2 ; ne = no
ret ; ignore DEL
; use atnrm2: for debug simple tty dsp
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?
je atnrm3 ; e = yes
push ax
call inschr ; open a char space in this line
push bx
mov bx,cursor ; get current row
mov bl,bh
xor bh,bh
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
; set cursor before writing char
atnrm3: mov bl,dh ; check for double characteristic
xor bh,bh ; bx = row, in bl
test anspflg,vtautop ; printing desired?
jz atnrm4d ; e = no
call pntchr ; print char in al
cmp linetype [bx],0 ; normal characteristic?
je atnrm4d ; e = yes
push ax ; save current char
mov al,' ' ; add a space for double width
call pntchr
pop ax ; recover char to be processed
atnrm4d:
cmp linetype [bx],0 ; normal characteristic?
je atnrm4a ; e = yes
shl dl,1 ; double the column number
push dx
call direction ; set dx to desired position
call setpos ; set cursor position
pop dx
mov ah,curattr ; current attribute
call setatch ; write char (al) and attribute (ah)
inc dl ; next column
push dx
call direction ; set dx to desired position
call setpos ; set cursor position
pop dx
mov al,' ' ; use a space for doubling
mov ah,curattr ; current attribute
call setatch ; write char (al) and attribute (ah)
shr dl,1 ; keep "cursor" in single units
jmp atnrm4b ; check autowrap in double width mode
atnrm4a:mov ah,curattr ; current attribute
call setatch ; write char (al) and attribute (ah)
; set physical cursor after this char
atnrm4b:test vtemu.vtflgop,decawm ; Autowrap active?
jz atnrm5 ; z = no
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 atwrap ; turn on wrap flag
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
mov atwrap,0 ; say not about to wrap
atscur: cmp dl,250 ; left of column zero? (wide screen)
jb atscu1 ; b = no, continue
mov dl,0 ; set at column zero
atscu1: mov cl,byte ptr low_rgt ; copy logical margin; 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 ; right of right margin?
jbe atscu3 ; be = no, continue
mov dl,cl ; assume no autowrap
test vtemu.vtflgop,decawm ; Autowrap?
jz atscu3 ; z = no
mov dl,0 ; set to column zero
cmp dh,byte ptr low_rgt+1 ; at bottom of screen?
je atscu1b ; e = yes
cmp dh,mar_bot ; at bottom of scrolling region?
jl atscu2 ; l = No - bump cursor and continue
atscu1b:mov scroll,1 ; scroll count = 1 line
call atscru ; scroll up
dec dh ; offset inc dh below
atscu2: inc dh ; just bump it
atscu3: or dh,dh ; 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]
test h19stat,h19l25 ; Heath 25th line enabled?
jz atscu5 ; z = no
atscu4a:inc dh ; go to line 25 [hlk]
test yflags,modoff ; is mode line off?
jnz atscu4b ; nz = yes
push dx ; save cursor position
call clrmod ; clear the line
or yflags,modoff ; now say it's off (owned by host)
pop dx
atscu4b:mov flags.modflg,2 ; say mode line is owned by host
atscu5: mov cursor,dx ; Set cursor and return
push dx
mov bl,dh ; get row
xor bh,bh ; clear high byte
cmp linetype [bx],0 ; single width line?
je atscu5a ; e = yes
shl dl,1 ; double the column number
atscu5a:call direction ; set dx to desired position
call setpos ; set cursor physical position
pop dx
test vtemu.vtflgop,vsmarginbell; do we care about margin bell?
jz atscu6 ; z = no, return if no margin bell
cmp kbiflg,0 ; is keyboard input flag set?
je atscu6 ; e = no, just return
mov bx,kbicsr ; cursor at previous keyboard input
cmp bh,dh ; same row as now?
jne atscu6 ; ne = no, just return
cmp bl,belcol ; old cursor at or left of bell column?
ja atscu6 ; a = no, just return
cmp dl,belcol ; new cursor past bell column?
jbe atscu6 ; be = no, just return
call vtbell ; ring the bell
atscu6: ret
atnrm endp
; Control-character dispatcher
atctrl: cmp al,escape ; an escape sequence starting?
je atctrl1 ; e = yes, don't print it
cmp al,CSI ; this kind of escape?
je atctrl1 ; e = yes
test anspflg,vtautop+vtcntp ; printing desired?
jz atctrl1 ; z = no
call pntchr ; print char in al
atctrl1:xor ah,ah ; clear for word use below
test al,80h ; high bit set?
jnz atctrl2 ; nz = yes
mov di,ax ; use AL as a word index
shl di,1
jmp ansc0[di] ; dispatch on C0 control codes
atctrl2:and al,not 80h ; strip high bit
mov di,ax ; use AL as a word index
shl di,1
jmp ansc1[di] ; dispatch on C1 control codes
; Control code routines
atbs: or dl,dl ; Backspace, too far?
jz atbs1 ; z = at column 0 already
dec dl ; backup cursor
atbs1: call atccpc ; check range
jmp atscu5 ; set cursor and return
atht: cmp flags.vtflg,ttheath ; Horizontal Tab, Heath-19 mode?
je atht2 ; e = yes, handle specially
xor ch,ch
mov cl,byte ptr low_rgt
cmp dl,cl ; at or beyond last column?
jae atbs1 ; ae = yes check range, set cursor
atht1: inc dl ; tab always moves at least one column
push si
mov si,vtemu.vttbst ; active buffer
call istabs ; returns carry set if at a tabstop
pop si
jc atht1a ; c = at a tabstop
loopz atht1
atht1a: 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
jbe atht3 ; be = in range
mov dl,byte ptr low_rgt ; else go to right margin
atht3: jmp atscu5 ; set cursor and return
atlf: test vtemu.vtflgop,anslnm ; Line Feed, New-line mode?
jz atlf2 ; z = no, just move to next line down
xor dl,dl ; 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: xor dl,dl ; Carriage Return, go to left margin
cmp flags.vtflg,ttheath ; Heath-19?
jne atcr1 ; ne = no
test h19stat,h19alf ; auto line feed on?
jnz atlf2 ; nz = yes, do the LF part above
atcr1: jmp atscu5 ; set cursor and return
atff: cmp ttstate,offset atescf ; Form Feed, parsing escape sequence?
jne atlf ; ne = no, do as line feed
test denyflg,tekxflg ; is auto Tek mode disabled?
jnz atlf ; nz = yes, treat as line feed
call atsc ; save cursor and associated data
mov al,escape
call TEKEMU
mov al,FF
call TEKEMU ; feed to Tektronix Emulator, al=FF
jmp atnorm
atcan: mov ttstate,offset atnrm ; CAN, say doing normal chars
mov parstate,0 ; clear esc seq parser
ret
atesc: mov ttstate,offset atescf ; ESC, next state is escape follower
ret
; Respond to character following Escape, dispatch on that char
atescf: call atpclr ; clear parser argument list
mov bx,offset ansesc ; ANSI escape table
cmp flags.vtflg,ttvt320 ; VT320?
je atescf2 ; e = yes
cmp flags.vtflg,ttvt100 ; VT100?
je atescf2 ; e = yes
mov bx,offset v52esc ; VT52 escape table
cmp flags.vtflg,ttvt52 ; VT52?
je atescf1 ; e = yes
mov bx,offset h19esc ; use Heath-19 table
cmp flags.vtflg,ttheath ; Heath-19?
je atescf1 ; e = yes
ret ; return on error
atescf1:mov ttstate,offset atnrm ; reset state to "normal"
jmp atdispat ; perform dispatch via table in BX
atescf2:mov bx,offset ansesc ; ANSI escape table, for atdispat
test al,not (2fh) ; in intermediates (column 2)?
jnz atescf1 ; nz = no, dispatch on this char
mov ttstate,offset atescf2 ; stay in this state til col 3 or more
mov bx,ninter ; number of intermediates
cmp bx,maxinter ; done enough already?
jae atescf3 ; ae = yes, ignore the excess
mov inter[bx],al ; store this one
inc ninter ; one more
atescf3:ret ; get more input
; CSI, char 9bh (ANSI CSI == ESC [)
atcsi: mov ttstate,offset atparse ; next state is parse control seq
mov pardone,offset atcsi1 ; where to jmp when done
mov parfail,offset atnorm ; where to jmp if failure
ret ; get next char
atcsi1: mov bx,offset anstab ; ANSI Final character table
mov ttstate,offset atnrm ; reset state to "normal"
jmp atdispat ; dispatch on character
h19csi: test vtemu.vtflgop,decanm ; Heath-19 "ESC [", is ANSI mode on?
jnz h19csi1 ; nz = yes
mov ttstate,offset atnrm ; else ignore the "[" (kbd lock)
ret
h19csi1:mov ttstate,offset atparse ; H-19, ESC [ parser
mov pardone,offset h19csi2 ; where to jmp when done
mov parfail,offset atnorm ; where to jmp if failure
ret ; get next char
h19csi2:mov bx,offset h19ans ; H-19 ANSI Final character table
mov ttstate,offset atnrm ; reset state to "normal"
jmp atdispat ; dispatch on character
; Process Device Control Strings (DCS or ESC P lead-in chars, already read).
atdcs: mov ttstate,offset atparse ; next state is parse control seq
mov pardone,offset atdcs1 ; where to jmp when done
mov parfail,offset atnorm ; where to jmp if failure
ret
atdcs1: mov dcsstrf,al ; record Final char
mov emubufc,0 ; clear string count
mov cx,maxparam ; number of DCS parameters
push si ; copy these to the DCS area so that
push di ; they are not lost when an ST is
push es ; parsed (parser clears ESC items)
push ds
pop es
mov si,offset param ; ESC paramater storage area, numeric
mov di,offset dparam ; DCS parameter storage area, numeric
cld
rep movsw ; copy set to DCS storage area
mov cl,lparam ; copy letter Paramter
mov dlparam,cl
mov cx,maxinter ; number of intermediate characters
mov si,offset inter ; source
mov di,offset dinter ; destination
rep movsb
mov si,nparam ; number of parameters
mov dnparam,si
mov si,ninter
mov dninter,si ; number of intermediates
pop es
pop di
pop si
mov ttstateST,offset atnorm ; default ST completion state
mov emubufc,0 ; clear processed string length
mov al,dcsstrf ; get DCS Final char
mov bx,offset dcstab ; DCS dispatch table
call atdispat ; go to DCS handler
ret
; Process ST or ESC \ String Terminator.
atgotst:jmp ttstateST ; go to state for ST arrival
; Read and discard OSC (ESC ]), PM (ESC ^), APC (ESC _) control sequences
; through final ST (ESC \) terminator.
atdcsnul:mov dcsstrf,0 ; simulate a null (dummy) Final char
mov emubufc,0 ; clear string count
mov ttstate,offset atdcsnul1 ; keep coming here
mov ttstateST,offset atnorm ; where to go when ST has been seen
atdcsnul1:ret ; consume chars
; User Definable Key processor of DCS strings.
atudk: cmp dinter,0 ; no intermediates?
je atudk1 ; e = correct
jmp atdcsnul ; bad, consume the rest
atudk1: cmp dparam,1 ; is initial Parameter Pc a 1?
jae atudk2 ; ae = yes, clear only this key
call udkclear ; clear all UDKeys
mov dparam,1 ; and turn off Parameter
atudk2: mov ttstate,offset atudk3 ; next state is get a substring
mov ttstateST, offset atudk6 ; for when ST has been seen
ret
atudk3: cmp al,';' ; string separator?
je atudk5 ; e = yes, process string to-date
mov bx,emubufc ; count of chars in string buffer
cmp bx,emubufl ; too many?
jae atudk4 ; ae = too many, ignore extras
mov emubuf[bx],al ; store the char
inc emubufc ; count it
atudk4: ret
atudk5: mov si,offset emubuf ; address of string buffer is DS:SI
mov cx,emubufc ; count of buffer contents
call setudk ; insert string definition
mov emubufc,0 ; clear string buffer
ret
atudk6: call atudk5 ; ST seen, process last string
jmp atnorm ; reset state to normal
; Call this routine to deliver Parameters in succession. Each call points to
; a Parameter as param[si], where si is maintained here. If there are no
; Parameters the effect is the same as one Parameter with a value of zero.
; Enter with di = offset of action routine to be called for each Parameter.
; cx, si, and di are preserved over the call to the action routine.
atreps proc near
mov si,0 ; initialize parm index
mov cx,nparam ; number of Parameters
or cx,cx ; zero?
jnz atrep1 ; nz = no
inc cx ; zero parms is same as 1
atrep1: push cx ; save loop counter
push si ; save parameter index
push di ; save call vector
call DI ; call indicated routine
pop di ; restore registers
pop si
pop cx
add si,2 ; advance to next parameter
loop atrep1 ; loop for all
ret
atreps endp
; Action routines
atind: inc dh ; IND (index), move cursor down one
atind1: call atccic ; check cursor position
call ax ; scroll if necessary
jmp atscu5 ; set cursor, etc. and return
atnel: xor dl,dl ; NEL, next line - sort of like CRLF
inc dh ; ... all in one command
jmp atind1 ; check cursor, etc., and return
atri: cmp flags.vtflg,ttheath ; Heath-19?
jne atri1 ; ne = no
cmp dh,byte ptr low_rgt+1 ; on 25th line?
jbe atri1 ; be = no
ret ; no vertical for Heath on 25th line
atri1: dec dh ; RI, reverse index
jmp atind1 ; check cursor, etc., and return
; HTS, horizontal tab set in this col
athts: call atccpc ; make column number valid
mov si,vtemu.vttbst ; active buffer
jmp tabset ; say set tab in this column (DL)
; DECSC
atsc: mov si,offset savelist ; 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 data segment
cld
shr cx,1 ; divide by two for word moves
jnc atsc1 ; nc = even number of bytes
movsb ; do the odd byte
atsc1: rep movsw ; save it
pop es
mov cx,vtemu.vtflgop ; save a copy of the flags
mov savflgs,cx
ret
; DECRC
atrc: mov si,offset savecu ; restore cursor, attributes, etc
mov di,offset savelist ; where stuff goes
mov cx,lsavecu ; length of save area
push es ; save es
push ds
pop es ; set es to data segment
cld
shr cx,1 ; divide by two for word moves
jnc atrc1 ; nc = even number of bytes
movsb ; do the odd byte
atrc1: rep movsw ; put the stuff back
pop es
mov ax,savflgs ; get saved flags
xor ax,vtemu.vtflgop ; exclusive-or with current flags
test ax,vsscreen ; did screen mode change?
jz atrc3 ; z = no, reset saved flags and leave
mov ah,curattr ; get cursor attribute that was saved
call revideo ; get reversed video attributes (AH)
mov curattr,ah ; store
atrc3: mov ax,vtemu.vtflgop ; reset flags in case called again
and ax, not(decckm+deckpam+decom) ; remove old bits [dlk]
and savflgs,(decckm+deckpam+decom) ; remove all but new bits [dlk]
or ax,savflgs ; restore saved bits [dlk]
mov vtemu.vtflgop,ax ; update these flags [dlk]
mov savflgs,ax
mov dx,cursor ; get cursor
mov kbiflg,0 ; don't bother them with beeps here
jmp atscu5 ; set cursor
atkpam: or vtemu.vtflgop,deckpam ; turn on keypad applications mode
ret
atkpnm: and vtemu.vtflgop,not deckpam ; turn off keypad applications mode
ret
atpriv: mov ttstate,offset atnorm ; ignore next char
ret ; and return to normal afterward
; ISO 2022 three byte Announcer Summary <ESC> <space> <final char>
;Esc Sequence 7-Bit Environment 8-Bit Environment
;---------- ------------------------ ----------------------------------
;<ESC><SP>A G0->GL G0->GL
;<ESC><SP>B G0-(SI)->GL, G1-(SO)->GL G0-(LS0)->GL, G1-(LS1)->GL
;<ESC><SP>C (not used) G0->GL, G1->GR
;<ESC><SP>D G0-(SI)->GL, G1-(SO)->GL G0->GL, G1->GR
;<ESC><SP>E Full preservation of shift functions in 7 & 8 bit environments
;<ESC><SP>F C1 represented as <ESC>F C1 represented as <ESC>F
;<ESC><SP>G C1 represented as <ESC>F C1 represented as 8-bit quantity
;<ESC><SP>H All graphic character sets have 94 characters
;<ESC><SP>I All graphic character sets have 94 or 96 characters
;<ESC><SP>J In a 7 or 8 bit environment, a 7 bit code is used
;<ESC><SP>K In an 8 bit environment, an 8 bit code is used
;<ESC><SP>L Level 1 of ISO 4873 is used
;<ESC><SP>M Level 2 of ISO 4873 is used
;<ESC><SP>N Level 3 of ISO 4873 is used
;<ESC><SP>P G0 is used in addition to any other sets:
; G0 -(SI)-> GL G0 -(LS0)-> GL
;<ESC><SP>R G1 is used in addition to any other sets:
; G1 -(SO)-> GL G1 -(LS1)-> GL
;<ESC><SP>S G1 is used in addition to any other sets:
; G1 -(SO)-> GL G1 -(LS1R)-> GR
;<ESC><SP>T G2 is used in addition to any other sets:
; G2 -(LS2)-> GL G2 -(LS2)-> GL
;<ESC><SP>U G2 is used in addition to any other sets:
; G2 -(LS2)-> GL G2 -(LS2R)-> GR
;<ESC><SP>V G3 is used in addition to any other sets:
; G3 -(LS2)-> GL G3 -(LS3)-> GL
;<ESC><SP>W G3 is used in addition to any other sets:
; G3 -(LS2)-> GL G3 -(LS3R)-> GR
;<ESC><SP>Z G2 is used in addition to any other sets:
; SS2 invokes a single character from G2
;<ESC><SP>[ G3 is used in addition to any other sets:
; SS3 invokes a single character from G3
;
; ISO Escape Sequences for Alphabet Designation ("F" = Final char)
; Sequence Function Invoked By
; <ESC>(F assigns 94-character graphics set "F" to G0. SI or LS0
; <ESC>)F assigns 94-character graphics set "F" to G1. SO or LS1
; <ESC>*F assigns 94-character graphics set "F" to G2. SS2 or LS2
; <ESC>+F assigns 94-character graphics set "F" to G3. SS3 or LS3
; <ESC>-F assigns 96-character graphics set "F" to G1. SO or LS1
; <ESC>.F assigns 96-character graphics set "F" to G2. SS2 or LS2
; <ESC>/F assigns 96-character graphics set "F" to G3. SS3 or LS3
; <ESC>$(F assigns multibyte character set "F" to G0. SI or LS0
; <ESC>$)F assigns multibyte character set "F" to G1. SO or LS1
; <ESC>$*F assigns multibyte character set "F" to G2. SS2 or LS2
; <ESC>$+F assigns multibyte character set "F" to G3. SS3 or LS3
;
; Designate character sets, AL has final character, inter has all preceeding.
atdgfA: call atdgset ; 'A' ISO Latin-1, UK-ASCII
jc atdgfA1 ; c = no matching pointer
cmp inter,'+' ; in the 94 byte set?
ja atdgfA2 ; a = no
cmp flags.vtflg,ttvt100 ; doing a VT102?
jne atdgfA1 ; ne = no
call chrinit ; UK-ASCII
mov di,setptr ; get set pointer
mov byte ptr[di+23h],156 ; replace sharp 2/3 with Sterling sign
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov byte ptr[di+gsize+1],'A' ; set ident code
mov byte ptr[di+gsize+2],0
atdgfA1:ret
atdgfA2:call latin1 ; set si to Latin-1 table offset
jmp cpyset
atdgfB: call atdgset ; 'B' ASCII, get setptr from inter
jc atdgfA1 ; c = no matching pointer
cmp inter,'+' ; in the 94 byte set?
ja atdgfA1 ; a = no, ignore
jmp chrinit ; init the set to ASCII
atdgf0: call atdgset ; '0', '2', DEC Special Graphics
jc atdgfA1 ; c = no matching pointer
cmp inter,'+' ; in the 94 byte set?
ja atdgfA1 ; a = no, ignore
atdg52: call chrinit ; init set to ASCII
push si
push di
push es
push ds
pop es ; point es at data segment
mov di,setptr ; address of char set table
add di,95 ; replace chars 95-126, skip controls
mov si,offset sgrtab ; special graphics table
mov cx,sgrtabl ; table length
cmp flags.vtflg,ttheath ; Heath-19 rather than VT52?
jne atdgf53 ; ne = no, not a Heath
mov si,offset hgrtab ; use Heath-19 table
mov cx,hgrtabl
dec di ; replace chars 94-126
atdgf53:cld
rep movsb ; replace chars with <s|h>grtab items
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov byte ptr[di+gsize+1],'0' ; set ident code
mov byte ptr[di+gsize+2],0
pop es
pop di
pop si
ret
atdgf1: call atdgset ; '1' ALT-ROM
jc atdgfA1 ; c = no matching pointer
call chrinit ; init set to ASCII
push si
push di
push es
push ds
pop es ; point es at data segment
mov di,setptr
add di,60h ; replace a..z with 20h + (a..z)
mov si,di ; special graphics table
mov cx,27 ; number of chars to do (a..z)
cld
atdgf1a:lodsb ; get a char
add al,20h ; map up by 20h
stosb
loop atdgf1a
mov di,setptr
mov byte ptr[di+gsize],96 ; say this is a 96 byte set
mov byte ptr[di+gsize+1],'1' ; set ident code
mov byte ptr[di+gsize+2],0
pop es
pop di
pop si
ret
atdgft: call atdgset ; '>' Dec Technical Set
jc atdgft1 ; c = no matching pointer
cmp inter,'+' ; in the 94 byte set?
ja atdgft1 ; a = no
mov si,offset dectech ; source data
jmp cpyset ; copy the set
atdgft1:cmp ninter,0 ; ESC > set numeric keypad?
jne atdgft2 ; ne = no
and vtemu.vtflgop,not deckpam ; turn off application keypad bit
atdgft2:ret
; '<' User Preferred Supplemental Set
atdgfu: call atdgset ; get set pointer
jc atdgfu3 ; c = no matching pointer
cmp inter,',' ; designating the 96 char set?
jb atdgfu1 ; b = no, want 94
call latin1 ; set si to Latin-1 table offset
cmp word ptr upss+1,0+'A' ; is ISO Latin-1 the preferred set?
je atdgfu2 ; e = yes, set it up
jmp atdgfu3 ; else do nothing
atdgfu1:call decsupg ; SI=source data is DEC Supplement Gr.
cmp word ptr upss+1,'5%' ; DEC Supplemental Graphics?
jne atdgfu3 ; ne = no
atdgfu2:jmp cpyset ; copy the set
atdgfu3:ret
atdgfq: call atdgset ; '?' Transparent
jc atdgfu3 ; c = no matching pointer
call chrinit ; init set to ASCII
push si
push di
push es
push ds
pop es ; point es at data segment
mov di,setptr ; point at character set
mov si,di ;
mov cx,gsize ; number of chars to do, 128
cld
atdgfq1:lodsb ; get a char
add al,80h ; map up by 80h
stosb
loop atdgfq1
mov di,setptr
mov byte ptr[di+gsize],96 ; say this is a 96 byte set
mov byte ptr[di+gsize+1],'?' ; set ident code
mov byte ptr[di+gsize+2],0
pop es
pop di
pop si
ret
; ESC <...> <1-8> series
atsdhl: cmp ninter,1 ; just one intermediate?
jne atsdh0 ; ne = no
cmp inter,'#' ; this intermediate?
jne atsdhx ; ne = no, ignore
cmp al,'3' ; Double high lines. Top half?
je atsdh2 ; e = yes
cmp al,'4' ; bottom half?
je atsdh2 ; e = yes
cmp al,'5' ; restore line to single width?
je atsdh1 ; e = yes
cmp al,'6' ; double width single height?
je atsdh2 ; e = yes
cmp al,'8' ; screen alignment?
je atsdh8 ; e = yes
atsdhx: ret ; else ignore
atsdh1: jmp linesgl ; set line to single width
atsdh2: jmp linedbl ; expand the line to double width
atsdh8: jmp atalign ; do screen alignment
atsdh0: cmp ninter,0 ; zero intermediates?
jne atdgf5 ; ne = no, try for more
cmp al,'7' ; save cursor?
jne atsdh0a ; ne = no
jmp atsc ; do save cursor, ESC 7
atsdh0a:cmp al,'8' ; restore cursor?
jne atsdh0b ; ne = no
jmp atrc ; do restore cursor, ESC 8
atsdh0b:ret
atdgf5: cmp ninter,2 ; two intermediates?
jne atdgf5a ; ne = no, ignore remainder
cmp al,'5' ; '%5' DEC Supplemental Graphic?
jne atdgf5a ; ne = no
cmp inter,'+' ; in the 94 byte set?
ja atdgf5a ; a = no, ignore
cmp inter[1],'%' ; '%5'?
jne atdgf5a ; ne = no
mov ninter,1 ; help atdgset find our set
call atdgset ; get set pointer
jc atdgf5a ; c = no matching pointer
call decsupg ; SI = source data
jmp cpyset ; copy the set
atdgf5a:ret
; worker for atdgf routines
atdgset:cmp ninter,2 ; too many intermediates?
ja atdgsex ; a = yes, ignore
cmp inter,'(' ; 94 char sets, designate G0?
je atdgse0 ; e = yes
cmp inter,')' ; G1?
je atdgse1
cmp flags.vtflg,ttvt320 ; VT320?
jne atdgsex ; ne = no, G2 & G3 fixed for VT102
cmp inter,'*' ; G2?
je atdgse2
cmp inter,'+' ; G3?
je atdgse3
cmp inter,'-' ; 96 char sets, designate G1?
je atdgse1
cmp inter,'.' ; G2?
je atdgse2
cmp inter,'/' ; G3?
je atdgse3
atdgsex:stc ; carry set for failure
ret
atdgse0:mov setptr,offset G0set ; designate G0 set
clc
ret
atdgse1:mov setptr,offset G1set ; designate G1 set
clc
ret
atdgse2:mov setptr,offset G2set ; designate G2 set
clc
ret
atdgse3:mov setptr,offset G3set ; designate G3 set
clc
ret
; S7C1T/S8C1T select 7/8-bit controls
ats7c: cmp flags.vtflg,ttvt320 ; in VT320 mode?
jne ats7ca ; ne = no, ignore command
cmp ninter,1
jne ats7ca
cmp inter,' ' ; proper intermediate?
jne ats7ca ; ne = no
and vtemu.vtflgop,not vscntl ; turn off 8-bit controls bit
ats7ca:ret ; done
ats8c: cmp inter,' ' ; proper intermediate?
jne ats8ca ; ne = no
cmp ninter,1
jne ats8ca
or vtemu.vtflgop,vscntl ; turn on 8-bit controls bit
ats8ca: ret
; Designate User Preferred Supplemental Set as
; 'A' ISO Latin-1 or '%5' DEC Supplemental Graphics
; Store the selection letters in array upss for later use by ESC <char> '<'
atupss: cmp word ptr dinter,0+'!' ; "!u" proper intermediate?
je atupss0
jmp atdcsnul ; consume unknown command
atupss0:mov ah,94 ; assume 94 byte set
cmp dparam,1 ; 96 byte char size indicator?
jb atupss1 ; b = no, 94
ja atupss2 ; a = illegal Parameter
mov ah,96 ; say 96
atupss1:mov upss,ah ; store char set size
mov ttstateST,offset atupss4; where to go when ST has been seen
mov emubufc,0 ; clear buffer count
mov ttstate,offset atupss2 ; next state is get string
ret
atupss2:mov bx,emubufc ; count of chars in string buffer
cmp bx,emubufl ; too many?
jae atupss3 ; ae = too many, ignore extras
mov emubuf[bx],al ; store the char
inc emubufc ; count it
atupss3:ret
atupss4:mov si,emubufc ; count of chars in string
mov emubuf[si],0 ; terminate string in null
mov ax,word ptr emubuf ; copy two chars from string to
mov word ptr upss+1,ax ; upss char set ident storage area
mov emubufc,0 ; clear the string count
ret
; Select/map character sets
atls0: mov GLptr,offset G0set ; LS0, map G0 char set into GLeft
ret ; Control-O
atls1: mov GLptr,offset G1set ; LS1, map G1 char set into GLeft
ret ; Control-N
atls1r: cmp ninter,0 ; any intermediate chars?
jne atlsx ; ne = yes, not a Locking Shift
mov GRptr,offset G1set ; LS1R, map G1 char set into GRight
ret
atss2: cmp ninter,0 ; any intermediate chars?
jne atlsx ; ne = yes, not a Single Shift
mov SSptr,offset G2set ; SS2, use G2 for next graphics only
ret
atls2: cmp ninter,0 ; any intermediate chars?
jne atlsx ; ne = yes, not a Locking Shift
mov GLptr,offset G2set ; LS2, map G2 char set into GLeft
ret
atls2r: cmp ninter,0 ; any intermediate chars?
jne atlsx ; ne = yes, not a Locking Shift
mov GRptr,offset G2set ; LS2R, map G2 char set into GRight
ret
atss3: cmp ninter,0 ; any intermediate chars?
jne atlsx ; ne = yes, not a Single Shift
mov SSptr,offset G3set ; SS3, use G3 for next graphics only
ret
atls3: cmp ninter,0 ; any intermediate chars?
jne atlsx ; ne = yes, not a Locking Shift
mov GLptr,offset G3set ; LS3, map G3 char set into GLeft
ret
atls3r: cmp ninter,0 ; any intermediate chars?
jne atlsx ; ne = yes, not a Locking Shift
mov GRptr,offset G3set ; LS3R, map G3 char set into GRight
atlsx: ret
; Initialize a char set to ASCII values 0..127 and ident of 94/B
; Enter with setptr holding offset of G0set, G1set, G2set, or G3set char set
chrinit proc near
push ax
push cx
push di
push es
mov di,setptr ; char set to init (G0..G3)
mov cx,gsize ; number of bytes to do
xor al,al ; initial value
push ds
pop es ; set es to data segment
cld
chrini1:stosb ; copy value to char set table
inc al
loop chrini1
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov byte ptr[di+gsize+1],'B' ; set ident code to ASCII "B"
mov byte ptr[di+gsize+2],0
pop es
pop di
pop cx
pop ax
ret
chrinit endp
; copy gsize+3 bytes from (si) to (setptr)
cpyset proc near
push es
push ds
pop es
cld
mov cx,gsize+3 ; gsize chars plus three ident bytes
mov di,setptr ; destination
rep movsb
pop es
ret
cpyset endp
; Move National Replacement Characters into all four tables.
; Turns off vscntl (8-bit controls).
; Places NRC chars in G0set, G1set, G2set, and G3set tables.
; Also allows selection of ALT-ROM the same way, does not turn off vscntl.
setnrc proc near
mov cl,vtemu.vtchset ; get country number
xor ch,ch
or cl,cl
jnz setnrc7
ret ; 0 is out of range
setnrc7:cmp cl,12 ; 1-12 is the range
jbe setnrc1 ; be = in range
cmp vtemu.vtchset,13 ; want ALT-ROM?
jne setnrc8 ; ne = no
mov inter,'(' ; say ALT-ROM in G0 set
mov ninter,1 ; one intermediate char
jmp atdgf1 ; do ALT-ROM setup
setnrc8:cmp vtemu.vtchset,14 ; Transparent (14)?
jne setnrc4 ; ne = no, unknown
mov inter,'.' ; say 96 byte transparent in G2 set
mov ninter,1 ; one intermediate char
jmp atdgfq ; do Transparent setup
setnrc1:test vtemu.vtflgop,vsnrcm ; doing National Replacement Chars?
jz setnrc4 ; z = no
push bx
push si
push di
push es
push ds
pop es
and vtemu.vtflgop,not vscntl ; turn off 8-bit controls
call nrc2cp ; set si to table of NRC replacments
sub si,cx ; minus one
shl cx,1 ; 15 bytes per NRC entry
shl cx,1
shl cx,1
shl cx,1
add si,cx ; +16, source, point at this entry
mov cx,12 ; do first 12 bytes of them
mov setptr,offset G0set ; destination, do G0set
push si
push cx
call setnrc5 ; do the setup
pop cx
pop si
mov setptr,offset G1set ; do G1set
push si
push cx
call setnrc5 ; do the setup
pop cx
pop si
cmp flags.vtflg,ttvt320 ; VT320?
jne setnrc3 ; ne = no, no NRCs to G2 and G3
mov setptr,offset G2set ; do G2set
push si
push cx
call setnrc5 ; do the setup
pop cx
pop si
mov setptr,offset G3set ; do G3set
call setnrc5 ; do the setup
setnrc3:pop es
pop di
pop si
pop bx
setnrc4:ret
; worker routine
setnrc5:call chrinit ; init table to ascii
; copy from NRC table (si) to set pointed at by di, cx chars
push si ; plus 3 ident bytes at table end.
call nrc2cp ; set si to NRC table
mov bx,si ; bx = location of old chars
pop si
cld
xor ah,ah
setnrc6:mov al,[bx] ; get location of new char
inc bx
mov di,setptr ; start of destination table
add di,ax ; destination of new char
movsb ; move replacement char from nrc list
loop setnrc6
mov di,setptr
add di,gsize ; look at end of set, to id bytes
movsw ; copy set size and two ident chars
movsb
ret
setnrc endp
; Routine to set default character set.
chrdef proc near
mov GLptr,offset G0set ; map G0 set to GLeft
mov GRptr,offset G2set ; map G2 set to GRight
mov SSptr,0 ; clear single shift
test vtemu.vtflgop,vsnrcm ; NRC's active?
jz chrdef1 ; z = no
jmp setnrc ; nz = yes, set them
chrdef1:mov setptr,offset G0set
call chrinit ; make ASCII
cmp vtemu.vtchset,13 ; want default of ALT-ROM or Transpar
jne chrdef2 ; ne = no
call setnrc ; use NRC code to setup G0
chrdef2:mov setptr,offset G1set
mov si,offset G0set
call cpyset ; copy G0set to G1set
mov setptr,offset G2set
call chrinit ; make G2 = ASCII
cmp flags.vtflg,ttvt320 ; VT320?
jne chrdef3 ; ne = no, make G2 = G3 = ASCII
call latin1 ; set si to Latin-1 table offset
cmp vtemu.vtchset,15 ; SET TERM CHAR LATIN-1?
je chrdef2a ; e = yes
call decsupg ; else DEC Supplement Graph (DEC-MCS)
cmp vtemu.vtchset,0 ; SET TERM CHAR ASCII?
je chrdef3 ; e = yes, ascii in both halves
chrdef2a:call cpyset ; copy Latin-1 to G2
chrdef3:mov setptr,offset G3set
mov si,offset G2set
call cpyset ; copy G2set to G3set
cmp vtemu.vtchset,14 ; SET TERM CHAR TRANSPARENT?
jne chrdef4 ; ne = no
mov setptr,offset G2set
call setnrc ; use NRC code to setup G2
mov setptr,offset G1set
mov si,offset G2set
call cpyset ; copy G2set to G1set for VT100's
ret
chrdef4:call decsupg ; source data is DEC Supplement Gr.
cmp word ptr upss+1,'5%' ; DEC Supplemental Graphics?
jne chrdef5 ; ne = no
mov setptr,offset G2set ; G2 to DEC Supp Gr
call cpyset ; copy the set
mov setptr,offset G3set ; G3 to DEC Supp Gr
call cpyset
chrdef5:ret
chrdef endp
; Set register SI to the offset of the ISO Latin-1 table appropriate to the
; currently active Code Page. Defaults to CP437 if no CP found.
LATIN1 proc near
push bx
push dx
cmp dosnum,0300h+30 ; DOS version 3.30 or higher?
jb latin1a ; b = no, no Code Pages
mov ax,6601h ; get global Code Page
int dos ; bx=active Code Page, dx=boot CP
cmp bx,437 ; current Code Page is 437?
je latin1a ; e = yes
mov si,offset L1cp850 ; assume CP850
cmp bx,850 ; current Code Page is 850?
je latin1x ; e = yes
mov si,offset L1cp860 ; assume CP860
cmp bx,860 ; current Code Page is 860?
je latin1x ; e = yes
mov si,offset L1cp863 ; assume CP863
cmp bx,863 ; current Code Page is 863?
je latin1x ; e = yes
mov si,offset L1cp865 ; assume CP865
cmp bx,865 ; current Code Page is 865?
je latin1x ; e = yes
latin1a:mov si,offset L1cp437 ; default to CP437
latin1x:pop dx
pop bx
ret
LATIN1 endp
; Set register SI to the offset of the DEC Multinational char set (DEC
; Supplemental Graphics) table appropriate to the currently active Code Page.
; Defaults to CP437 if no CP found.
DECSUPG proc near
push bx
push dx
cmp dosnum,0300h+30 ; DOS version 3.30 or higher?
jb decsu1a ; b = no, no Code Pages
mov ax,6601h ; get global Code Page
int dos ; bx=active Code Page, dx=boot CP
cmp bx,437 ; current Code Page is 437?
je decsu1a ; e = yes
mov si,offset MNcp850 ; assume CP850
cmp bx,850 ; current Code Page is 850?
je decsu1x ; e = yes
mov si,offset MNcp860 ; assume CP860
cmp bx,860 ; current Code Page is 860?
je decsu1x ; e = yes
mov si,offset MNcp863 ; assume CP863
cmp bx,863 ; current Code Page is 863?
je decsu1x ; e = yes
mov si,offset MNcp865 ; assume CP865
cmp bx,865 ; current Code Page is 865?
je decsu1x ; e = yes
decsu1a:mov si,offset MNcp437 ; default to CP437
decsu1x:pop dx
pop bx
ret
DECSUPG endp
; Set reg BX to offset of table for Code Page to DEC Multinational Char Set
; (DEC Supplemental Graphics)
CPDECSG proc near
mov bx,offset cp437MN ; assume CP437
cmp flags.chrset,437 ; current Code Page is 437?
je cpdecsx ; e = yes
mov bx,offset cp850MN ; assume CP850
cmp flags.chrset,850 ; current Code Page is 850?
je cpdecsx ; e = yes
mov bx,offset cp860MN ; assume CP860
cmp flags.chrset,860 ; current Code Page is 860?
je cpdecsx ; e = yes
mov bx,offset cp863MN ; assume CP863
cmp flags.chrset,863 ; current Code Page is 863?
je cpdecsx ; e = yes
mov bx,offset cp865MN ; assume CP865
cmp flags.chrset,865 ; current Code Page is 865?
je cpdecsx ; e = yes
mov bx,offset cp437MN ; default to CP437
CPDECSX:ret
CPDECSG endp
; Set register SI to the offset of the NRC table appropriate to the
; currently active Code Page. Defaults to CP437 if no CP found.
NRC2CP proc near
push bx
push dx
cmp dosnum,0300h+30 ; DOS version 3.30 or higher?
jb nrc2cp1 ; b = no, no Code Pages
mov ax,6601h ; get global Code Page
int dos ; bx=active Code Page, dx=boot CP
cmp bx,437 ; current Code Page is 437?
je nrc2cp1 ; e = yes
mov si,offset NRC850 ; assume CP850
cmp bx,850 ; current Code Page is 850?
je nrc2cpx ; e = yes
mov si,offset NRC860 ; assume CP860
cmp bx,860 ; current Code Page is 860?
je nrc2cpx ; e = yes
mov si,offset NRC863 ; assume CP863
cmp bx,863 ; current Code Page is 863?
je nrc2cpx ; e = yes
mov si,offset NRC865 ; assume CP865
cmp bx,865 ; current Code Page is 865?
je nrc2cpx ; e = yes
nrc2cp1:mov si,offset NRC437 ; default to CP437
nrc2cpx:pop dx
pop bx
ret
NRC2CP endp
; cursor movements
atcup: test dspstate,dsptype ; on VT320 status line?
jz atcup0 ; z = no
mov param,0 ; yes, do not change rows
mov param+2,0
atcup0: mov dh,byte ptr param ; get row,col parameters
mov dl,byte ptr param+2 ; dh is row, dl is column
or dh,dh ; zero row number?
jz atcup1 ; z = yes, continue
dec dh ; normalize to 0,0 system
atcup1: or dl,dl ; ditto for column
jz atcup2
dec dl
atcup2: test vtemu.vtflgop,decom ; Origin mode?
jz atcup3 ; z = no, skip this stuff
add dh,mar_top ; yes, it was relative to top margin
jno atcup3 ; if no overflow, continue
mov dh,byte ptr low_rgt+1 ; otherwise just set to screen bottom
atcup3: mov al,byte ptr low_rgt ; right margin
cmp dl,al ; too far to the right?
jbe atcup4 ; ne = no
mov dl,al ; limit to right margin
atcup4: mov ah,byte ptr low_rgt+1 ; last regular text line
cmp dh,ah ; going to 25th line?
jbe atcup7 ; be = no
inc ah ; "25th" status line
cmp flags.vtflg,ttheath ; emulating a Heath-19?
je atcup5 ; e = yes
cmp dh,ah ; going too far?
je atcup8 ; e = no
dec ah
mov dh,ah ; last normal row
jmp atcup8 ; set cursor here
atcup5: cmp dh,ah ; going too far?
ja atcup6 ; a = yes
test h19stat,h19l25 ; Heath 25th mode line enabled?
jnz atcup8 ; nz = yes
atcup6: mov dh,byte ptr cursor+1 ; do not change rows
atcup7: call atccpc ; check position
atcup8: jmp atscu5 ; set cursor position and return
atcuarg:mov al,byte ptr param ; worker, get cursor movement argument
or al,al ; zero?
jnz atcua1 ; nz = no
inc al ; default to one
atcua1: ret
; cursor up
atcuu: cmp dh,byte ptr low_rgt+1 ; on 25th line?
jbe atcuu1 ; be = no
ret ; no vertical for Heath on 25th line
atcuu1: call atcuarg ; get cursor move up argument into al
sub dh,al ; compute new cursor position
jnc atcuu2 ; nc = ok [dlk]
xor dh,dh ; overflow, restrict range. [dlk]
atcuu2: call atccic ; check indexing, ignore action in ax
jmp atscu5 ; set the cursor at its new position
atcud: call atcuarg ; cursor down
cmp dh,byte ptr low_rgt+1 ; on 25th line now?
jbe atcud1 ; be = no
ret ; else leave it on status line
atcud1: add dh,al ; compute new cursor position
jnc atcud2 ; nc = ok [dlk]
mov dh,byte ptr low_rgt+1 ; default bottom [dlk]
atcud2: 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 ; cursor forward
add dl,al ; compute new cursor position
jnc atcup3 ; nc = no problem
mov dl,byte ptr low_rgt ; else set to right margin
jmp atcup3 ; check/set cursor, return
atcub: call atcuarg ; cursor back
sub dl,al ; compute new cursor position
jnc atcub1 ; nc = no problem
xor dl,dl ; else set to left margin
atcub1: jmp atcup3 ; check/set cursor, return
atcha: call atcuarg ; absolute horizontal address
mov dl,al ; new column, counted from 1
sub al,1 ; column, count from 0 internally
jnc atcha1 ; nc = no problem
xor dl,dl ; else set to left margin
atcha1: jmp atcup3 ; check/set cursor, return
atcht: call atcuarg ; move cursor forward # horiz tabs
inc dl ; next column
mov cl,al ; number of tabstops to locate
xor ch,ch
mov si,offset tabs ; active tabs buffer
atcht1: cmp dl,byte ptr low_rgt ; at end of line?
jae atcht2 ; ae = yes, stop here
call istabs ; is dl column a tabstop?
inc dl ; try next column, preserves carry
jnc atcht1 ; nc = no, find one
loop atcht1 ; do cx tabstops
atcht2: jmp atcup3 ; set cursor
atcva: mov byte ptr param+2,dh ; set column in second parameter
mov param+3,0 ; high byte
jmp atcup ; do absolute vertical positioning
atcnl: call atcuarg ; do # Next-Lines
cmp dh,byte ptr low_rgt+1 ; on 25th line now?
jbe atcnl1 ; be = no
ret ; else leave it on status line
atcnl1: add dh,al ; number to do
xor dl,dl ; cursor to left margin
call atccic ; check cursor position
call ax ; scroll if necessary
jmp atscu5 ; set cursor, etc. and return
atcpl: call atcuarg ; do # Previous-Lines
cmp dh,byte ptr low_rgt+1 ; on 25th line now?
jbe atcpl1 ; be = no
ret ; else leave it on status line
atcpl1: mov cl,al ; number to do
xor ch,ch
xor dl,dl ; set to column zero
atcpl2: dec dh ; do one line
push cx ; save counter
call atccic ; check cursor position
call ax ; scroll if necessary
call atscu5 ; set cursor
pop cx
loop atcpl2 ; do cx times
ret
; Screen erasure commands
; Erase in display
ated: cmp ninter,0 ; zero intermediates?
je ated0 ; e = yes, else quit
ret
ated0: cmp param,0 ; was arg zero?
jne ated1 ; ne = no
jmp ereos ; do erase cursor to end of screen
ated1: cmp param,1 ; was arg one?
jne ated2 ; ne = no
jmp ersos ; do erase start of screen to cursor
ated2: cmp param,2 ; was arg two?
je ated2a ; e = yes, erase entire screen
ret ; else ignore
ated2a: push dx ; save dynamic cursor
xor dx,dx ; say cursor is at 0,0
call ereos ; erase cursor to end of screen
pop dx ; recover cursor
ret
; Erase in current line
atel: cmp ninter,0 ; zero intermediates?
je atel0 ; e = yes, else quit
ret
atel0: cmp param,0 ; was arg zero?
jne atel1 ; ne = no
mov al,dl ; erase from cursor
mov bl,crt_cols ; to end of line, inclusive
dec bl ; physical line
jmp erinline ; do the erasure
atel1: cmp param,1 ; was arg one?
jne atel2 ; ne = no
xor al,al ; erase from start of line
mov bl,dl ; to cursor, inclusive
jmp erinline ; do the erasure
atel2: cmp param,2 ; was arg two?
jne atel3 ; ne = no, ignore
xor al,al ; erase entire line
mov bl,crt_cols
dec bl ; physical line
jmp erinline ; clear it
atel3: ret
; ECH, erase chars in this line
atech: mov ax,dx ; get cursor position
mov bx,ax ; erase ax to bx
add bl,byte ptr param ; number of characters
jmp erinline ; erase in this line
; Set Graphics Rendition commands (video attributes)
atsgr: cmp lparam,0 ; any letter parameter?
jne atsgr0 ; ne = yes, fail
mov ah,curattr ; get current cursor attribute
mov di,offset atsgr1 ; routine to call
call atreps ; repeat for all parms
mov curattr,ah ; store new attribute byte
atsgr0: ret
atsgr1: mov bx,param[si] ; fetch an argument
or bl,bl ; 0, clear all attributes?
jnz atsgr2 ; nz = no, do selectively below
call clrbold ; clear bold attribute
call clrblink ; clear blink attribute
call clrunder ; clear underline attribute
jmp clrrev ; clear reverse video attribute
atsgr2: cmp bl,1 ; 1, set bold?
jne atsgr3 ; ne = no
jmp setbold ; set bold attribute
atsgr3: cmp bl,4 ; 4, set underline?
jne atsgr4 ; ne = no
jmp setunder ; set underline attribute
atsgr4: cmp bl,5 ; 5, set blink?
jne atsgr5 ; ne = no
jmp setblink ; set blink attribute
atsgr5: cmp bl,7 ; 7, reverse video for chars?
jne atsgr6 ; ne = no, try coloring
jmp setrev ; set reversed video attribute (AH)
atsgr6: cmp flags.vtflg,ttheath ; Heath-19?
jne atsgr9 ; ne = no
cmp bl,10 ; 10, enter graphics mode?
jne atsgr7 ; ne = no
push ax ; save ah
mov al,'F' ; simulate final char of 'F'
call v52sgm ; do character setup like VT52
pop ax
ret
atsgr7: cmp bl,11 ; 11, exit graphics mode?
jne atsgr8 ; ne = no, ignore
push ax ; save ah
mov al,'G' ; simulate final char of 'G'
call v52sgm ; do character setup like VT52
pop ax
atsgr8: ret
atsgr9: cmp flags.vtflg,ttvt320 ; VT320?
jne atsgr13 ; ne = no, 22-27 are VT320 only
cmp bl,22 ; 22, bold off?
jne atsgr10 ; ne = no
jmp clrbold
atsgr10:cmp bl,24 ; 24, underline off?
jne atsgr11 ; ne = no
jmp clrunder
atsgr11:cmp bl,25 ; 25, blinking off?
jne atsgr12 ; ne = no
jmp clrblink
atsgr12:cmp bl,27 ; 27, reverse video off?
jne atsgr13 ; ne = no
jmp clrrev ; clear reversed video attribute (AH)
atsgr13:jmp setcolor ; BL = color, AH = attribute byte
; Tabulation char commands
attbc: call atccpc ; make sure cursor is kosher
cmp ninter,0 ; zero intermediates?
je attbc0 ; e = yes, else quit
ret
; Tabstop set/clears
attbc0: cmp param,0 ; was argument zero?
jne attbc1 ; ne = no
push si
mov si,vtemu.vttbst ; active buffer
call tabclr ; clear tabstop in column DL
pop si
ret
attbc1: cmp param,3 ; was arg 3 (clear all tab stops)?
je attbc2 ; e = yes
ret ; else ignore
attbc2: mov cx,(swidth+7)/8 ; get ready to zap swidth columns
mov di,offset tabs ; point to the tab stop table
xor al,al ; zero indicates no tab stop
push es ; save es
push ds
pop es ; use data segment for es:di below
cld ; set direction forward
rep stosb ; clear all bits
pop es
ret
; set scrolling margins
atstbm: test dspstate,dsptype ; on status line?
jnz atstb3 ; nz = yes, ignore this command
mov al,byte ptr param ; get the two line number args
mov ah,byte ptr param+2
or al,al ; was first zero?
jnz atstb1 ; nz = no, continue
inc al ; default is one
atstb1: or ah,ah ; was second zero?
jnz atstb2 ; nz = no
mov ah,byte ptr low_rgt+1 ; yes, default is last line on screen
inc ah
atstb2: dec al ; normalize to 0,0 coordinate system
dec ah
cmp ah,al ; size of region at least two lines?
jbe atstb3 ; be = no, indicate an error
cmp al,0 ; check against screen limits
jl atstb3 ; l = out of range
cmp ah,byte ptr low_rgt+1
ja atstb3 ; a = too far down
mov mar_top,al ; set the limits
mov mar_bot,ah
xor dx,dx ; Home cursor
call atccpc ; check cursor (get it inside window)
jmp atscu5 ; set cursor position and return
atstb3: ret ; ignore bad requests
; Device attributes commands
atda: cmp param,0 ; was argument zero?
je decid ; e = send the i.d. string
ret ; no, only an echo
decid: mov cx,20 ; assumed length of asciiz string
mov si,offset v32str ; VT320 ident string
cmp flags.vtflg,ttvt320 ; VT320?
je decid2 ; e = yes
mov si,offset v102str
cmp flags.vtflg,ttvt100 ; VT100?
je decid2 ; e = yes
mov si,offset v52str
cmp flags.vtflg,ttvt52 ; Heath-19 mode?
je decid2 ; e = yes
mov si,offset h19str ; say Heath-19
decid2: cmp lparam,'>' ; this letter parameter?
jne decid3 ; ne = no
cmp flags.vtflg,ttvt320 ; VT320 mode?
jne decid4 ; ne = no, ignore
mov si,offset v32sda ; Secondary DA response string
decid3: cld
lodsb ; read string
or al,al ; end of string?
jz decid4 ; z = yes
push cx
push si
call prtbout ; send it to port with no local echo
pop si
pop cx
loop decid3 ; do all characters
decid4: ret
; Display LED's
atll: mov di,offset atleds ; get pointer to routine to call
call atreps ; repeat for selective parameters
ret
atleds: cmp param[si],0 ; zero argument?
jne atled3 ; ne = no, check further
mov cx,4 ; reset the "LEDs"
mov al,led_off ; to all off
mov di,offset ansleds+6 ; point to the "LEDs"
push es ; save es
push ds
pop es ; make es:di point to data seg
cld ; move forward
rep stosb
pop es
atled1: call ansdsl ; update "LEDs" display and return
atled2: ret
atled3: mov ax,param[si] ; get the argument
cmp al,1 ; must be 1 to 4
jb atled2 ; b = out of range
cmp al,4
ja atled2 ; a = out of range
dec ax ; zero base it
mov di,ax
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
; Set/Reset mode commands
; ESC [ ? xxx h/l Set/Reset series
atrm: mov modeset,0 ; say we are resetting modes
mov di,offset atrsm ; Reset/Set modes
call atreps ; repeat for all parms
test vtemu.vtflgop,decanm ; did ansi mode get reset?
jnz atrm1 ; nz = no, return
cmp flags.vtflg,ttheath ; were we a Heath-19?
je atrm0 ; e = yes, don't change terminal types
mov flags.vtflg,ttvt52 ; say VT52 now
atrm0: call chrdef ; set default char sets
call atsc ; save cursor status
call ansdsl ; 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 ax,param[si] ; pick up the argument
cmp lparam,'?' ; DEC private mode? ESC [ ?
je atrsm1 ; e = yes, do DEC specific things
cmp lparam,'>' ; Heath-19 private mode? ESC [ >
jne atrsma ; ne = no
jmp htrsm1 ; do Heath specific things
; ANSI level
atrsma: cmp al,20 ; 20, ANSI new-line mode?
jne atrsm0 ; ne = no, try insert mode
and vtemu.vtflgop,not vsnewline ; assume resetting
cmp modeset,0 ; resetting?
je atrsmb ; e = yes
or vtemu.vtflgop,vsnewline ; setting
atrsmb: mov ax,anslnm ; get the flag bit
jmp atrsflg ; set or reset it
atrsm0: cmp al,4 ; toggle insert mode?
jne atrsmc ; ne = no
mov al,modeset ; set/reset insert mode
mov insmod,al ; store it
ret
atrsmc: cmp al,12 ; 12? Control local echo
jne atrsmx ; ne = no
cmp modeset,0 ; resetting mode (ESC [ 12 l)?
jne atrsmc1 ; ne = no
or vtemu.vtflgop,dececho ; remember state here too
or yflags,lclecho ; (l) turn on local echoing
jmp short atrsmc2
atrsmc1:and yflags,not lclecho ; (h) turn off local echoing
and vtemu.vtflgop,not dececho
atrsmc2:test yflags,modoff ; is mode line off?
jnz atrsmx ; nz = yes
push dx ; save cursor position
call modlin ; write mode line
pop dx
atrsmx: ret
; DEC specifics
atrsm1: cmp al,1 ; cursor keys mode?
jne atrsm2 ; ne = no
mov ax,decckm ; get the bit
jmp atrsflg ; set or reset it and return
atrsm2: cmp al,7 ; Auto-wrap?
jne atrsm3 ; ne = no
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 ax,decawm ; get the bit
jmp atrsflg ; set or reset it and return
atrsm3: cmp al,6 ; Origin mode?
jne atrsm4 ; ne = no
jmp atrsom ; change decom and return
atrsm4: cmp al,5 ; change the video?
jne atrsm5 ; ne = no
jmp atrsscnm ; yes, change it if necessary
atrsm5: cmp al,2 ; Change VT52 compatibility mode?
jne atrsm6 ; ne = no
test dspstate,dsptype ; on status line?
jnz atrsm5b ; nz = yes, ignore switch
cmp flags.vtflg,ttheath ; Heath-19 mode?
jne atrsm5a ; ne = no
mov modeset,0 ; Heath ESC [ ? 2 h resets ANSI mode
atrsm5a:mov ax,decanm ; get ansi mode flag
jmp atrsflg ; set or reset it
atrsm5b:ret
atrsm6: cmp al,3 ; 132/80 column mode change?
jne atrsm7 ; ne = no
mov al,curattr ; save current video attributes
push ax
mov al,modeset ; pass set/reset request to chgdsp[dlk]
call chgdsp ; call Change Display proc in msy [dlk]
and vtemu.vtflgop,not deccol; assume mode is reset
cmp modeset,1 ; want 132 cols?
jne atrsm6n ; ne = no, so use 80 columns
cmp crt_cols,80 ; see if it worked
jbe atrsm6n ; be = no, do not set the status bit
or vtemu.vtflgop,deccol ; set the status bit
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
jmp short atrsm6e
atrsm6n:cmp byte ptr low_rgt,79 ; want 80 cols, is it wider?
jbe atrsm6e ; be = no
mov byte ptr low_rgt,79 ; narrow down to 80 columns
atrsm6e:CALL ATRES2 ; do partial reset of emulator
pop ax
mov curattr,al ; restore saved items
mov dl,byte ptr low_rgt+1 ; text lines (leave status line intact)
mov mar_top,0
mov mar_bot,dl ; reset scrolling region
xor dx,dx ; new cursor position is 0,0
mov cursor,dx
jmp atscu5 ; place it there and return
atrsm7: cmp al,18 ; 18? 18 & 19 = printer support
jne atrsm8 ; ne = no
cmp modeset,0 ; resetting?
jne atrsm7a ; ne = no, setting
and anspflg,not vtffp ; no form feed after printing
ret
atrsm7a:or anspflg,vtffp ; use form feed after printing
ret
atrsm8: cmp al,19 ; 19, print region?
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,25 ; ESC [ ? 25 h/l? cursor on/off
jne atrsm10 ; ne = no
mov al,4 ; assume cursor to be turned off (4)
cmp modeset,0 ; resetting (invisible cursor)?
je atrsm9a ; e = yes
mov al,1 ; assume underline (1)
test vtemu.vtflgop,vscursor ; underline?
jnz atrsm9a ; nz = yes
inc al ; block (2)
atrsm9a:mov atctype,al ; save VTxxx cursor type here
jmp atsctyp ; set the cursor type
atrsm10:cmp al,34 ; ESC [ ? 34 h/l? Invoke special macro
jne atrsm11 ; ne = no
cmp modeset,0 ; resetting?
jne atrsm10a ; ne = no, setting
jmp vtrmac ; jump to perform on-line macro
; code is located in file msy
atrsm10a:jmp vtsmac ; do set macro
atrsm11:cmp al,38 ; 38? Enter Tek sub-mode. VT340 seq
jne atrsm12 ; ne = no
cmp modeset,1 ; setting mode (ESC [ ? 38 h)?
jne atrsm12 ; ne = no, ignore sequence
test denyflg,tekxflg ; is auto Tek mode disabled?
jnz atrsm12 ; nz = yes, just ignore command
call atsc ; save cursor and associated data
xor al,al ; enter with this received character
call TEKEMU ; go to Tektronix Emulator, al=null
jmp atnorm
atrsm12:cmp al,42 ; 42, use NRC 7-bit command?
jne atrsm15 ; ne = no
cmp flags.vtflg,ttvt320 ; VT320 mode?
jne atrsm14 ; ne = no
cmp vtemu.vtchset,0 ; ASCII?
je atrsm14 ; e = yes, no NRC
cmp vtemu.vtchset,12 ; highest NRC ident?
ja atrsm14 ; a = not NRC
cmp modeset,0 ; resetting?
je atrsm13 ; e = yes
or vtemu.vtflgop,vsnrcm ; set NRC flag bit
jmp chrdef ; and set NRC characters
atrsm13:mov ax,vtemu.vtflgop ; run time flags
and vtemu.vtflgop,not vsnrcm ; turn off NRC flag bit
or vtemu.vtflgop,vscntl ; turn on 8-bit controls
jmp chrdef
atrsm14:ret
atrsm15:cmp al,66 ; 66, keypad to applications mode?
jne atrsm16 ; ne = no
cmp flags.vtflg,ttvt320 ; VT320 mode?
jne atrsm16 ; ne = no
mov ax,deckpam ; bit to control
jmp atrsflg ; control the flag and return
atrsm16:ret
; Heath-19 ESC [ > Ps h or l where Ps = 1, 4, 7, or 9
htrsm1: cmp al,1 ; 25th line?
jne htrsm4 ; ne = no
and h19stat,not h19l25 ; clear 25th line bit
cmp modeset,0 ; clearing?
je htrsm1a ; e = yes
or h19stat,h19l25 ; set bit
jmp htrsmx ; we are done
htrsm1a:mov ah,byte ptr low_rgt+1 ; point to status (25th) line
inc ah ; which is here
xor al,al ; from column 0
mov bh,ah ; to same line
mov bl,crt_cols ; physical width
dec bl ; we count from 0
jmp vtsclr ; disabling status line clears it
htrsm4: cmp al,4 ; 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 ; 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 ; 7, alternate application keypad?
jne htrsm8 ; ne = no
mov ax,deckpam ; get keypad application mode bit
jmp atrsflg ; set or reset appl keypad mode
htrsm8: cmp al,8 ; 8, received CR => CR/LF?
jne htrsm9
and h19stat,not h19alf ; clear autoline feed bit
cmp modeset,0 ; resetting?
je htrsmx ; yes
or h19stat,h19alf ; turn on the mode
ret
htrsm9: cmp al,9 ; 9, auto newline mode? (add cr to lf)
jne htrsmx ; ne = no
mov ax,anslnm ; get the bit
jmp atrsflg ; set or reset newline mode
htrsmx: ret ; ignore the code
atrsflg:cmp modeset,0 ; reset?
je atrsf1 ; e = yes, reset it
or vtemu.vtflgop,ax ; set, OR in the flag
test ax,decanm ; changing ansi mode?
jz atrsfx ; z = no
cmp flags.vtflg,ttheath ; in Heath-19 mode?
je atrsfx ; e = yes, don't flip terminal kinds
mov al,oldterm ; terminal type at startup
mov flags.vtflg,al ; restore it
ret
atrsf1: not ax ; reset bit, complement
and vtemu.vtflgop,ax ; clear the bit
not ax ; recover the bit
test ax,decanm ; changing ansi mode?
jz atrsfx ; z = no
cmp flags.vtflg,ttheath ; in Heath-19 mode?
je atrsfx ; e = yes, don't flip terminal kinds
mov flags.vtflg,ttvt52 ; say VT52 now
atrsfx: ret
; Set/Clear Origin mode
atrsom: test dspstate,dsptype ; on status line?
jz atrsom1 ; z = no
ret ; else ignore this command
atrsom1:cmp modeset,0 ; clearing DEC origin mode?
jne atrsom2 ; ne = no, setting
and vtemu.vtflgop,not decom ; reset Origin mode
xor dx,dx ; go to the home position
jmp atscu5 ; set cursor and return
atrsom2:or vtemu.vtflgop,decom ; set Origin mode
mov dx,cursor ; get the cursor
xor dl,dl ; 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 ; resetting?
je atrss1 ; e = yes, reset
test vtemu.vtflgop,vsscreen ; setting, set already?
jnz atrss3 ; nz = yes, don't do it again
or vtemu.vtflgop,vsscreen ; set and tell Status display
jmp short atrss2 ; do it
atrss1: test vtemu.vtflgop,vsscreen ; resetting, reset already?
jz atrss3 ; z = yes, don't do it again
and vtemu.vtflgop,not vsscreen ; clear and tell Status
; fall through to atrss2
; Note: This is also called from the stblmds initialization routine.
; Reverse video the entire screen, update scbattr and curattr to match.
atrss2: push ax
mov ah,scbattr ; current screen attributes
call revideo ; reverse them
mov scbattr,ah ; set screen background attribute
mov ah,curattr ; get current cursor attribute
call revideo ; reverse it
mov curattr,ah ; store it
pop ax
call revscn ; reverse everything on the screen
atrss3: ret
; Self tests
atctst: cmp inter,0 ; any intermediate char?
jne atcts3 ; ne = yes, not a selftest command
cmp param,2 ; VT102 selftest?
je atcts1 ; e = yes
cmp param,4 ; VT320 selftest?
jne atcts3 ; ne = no, ignore
atcts1: test dspstate,dsptype ; cursor is on status line?
jz atcts2 ; z = no
push param ; save first parameter
mov ah,inter ; and first intermediate char
push ax
mov param,0 ; select main display
mov inter,'$' ; setup proper intermediate
call atssdt ; select status line of off
call atsasd ; select main display
pop ax
pop param ; restore parameter
mov inter,ah ; and intermediate char
atcts2: xor al,al ; init test weight
mov di,offset atcts4 ; routine to call
call atreps ; repeat for all parms
test al,80H ; reset?
jz atcts3 ; z = no, return
call atreset ; reset everything
atcts3: ret
atcts4: or si,si ; initial arg?
jz atcts5 ; z = yes, skip it (examined above)
cmp param[si],0 ; any argument?
jne atcts5 ; ne = no, ignore others
or al,80H ; say we want reset
atcts5: ret
atalign proc near ; Align screen, fill screen with 'E's
test dspstate,dsptype ; is cursor on status line?
jz atalig1 ; z = no
ret ; yes, ignore the command
atalig1:cmp flags.modflg,0 ; is mode line off?
je atalig2 ; e = yes
and yflags,not modoff ; say it's on
mov flags.modflg,1 ; and owned by us
atalig2:call atreset ; clear system
or vtemu.vtflgop,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
atalig3:push cx
mov al,'E' ; write screen full of E's
call atnrm ; write the 'E'
pop cx
loop atalig3 ; cx times
ret
atalign endp
; Reports
atreqt: cmp param,1 ; want report?
jbe atreq1 ; be = yes
atreq0: ret ; Gee, must have been an echo
atreq1: cmp flags.vtflg,ttvt100 ; VT102?
jne atreq0 ; ne = no, ignore
mov al,CSI
call out8bit ; send CSI or ESC [
mov al,'3' ; we report only upon request
cmp param,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
xor bh,bh
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,';'
call prtbout
mov bl,baudidx ; baud rate index
xor bh,bh
mov al,baudtab[bx] ; get DEC baud rate code
push ax
call prtnout ; send it to the port
mov al,';'
call prtbout
pop ax
call prtnout ; send baud rate code to the port
mov al,';'
call prtbout
mov al,'1' ; clock rate multiplier is always 1
call prtbout
mov al,';'
call prtbout
mov al,'0' ; Flags are always zero (no STP)
call prtbout
mov al,'x'
call prtbout
ret
; Single Controls
; Note DEC manual incorrectly says DECSCL's do a hard rather than soft reset
decscl: cmp inter,'!' ; "CSI ! p" soft reset?
jne decsc0 ; ne = no
jmp atsres ; do a soft reset
decsc0: cmp inter,'"' ; "CSI Psc; Ps1 " p" operating level?
je decsc1 ; e = yes
cmp inter,'$' ; "CSI Pn $ p" DECRQM?
jne decsc0a ; ne = no, ignore others
jmp decsc5 ; do isolated controls report
decsc0a:ret ; else ignore
decsc1: cmp param,61 ; Psc, select VT100?
jne decsc2 ; ne = no
mov flags.vtflg,ttvt100 ; set VT100
mov oldterm,ttvt100 ; and remember it
and vtemu.vtflgop,not vscntl ; turn off 8-bit controls
jmp atsres ; do soft reset of emulator
decsc2: cmp param,62 ; VT2xx level?
je decsc3 ; e = yes
cmp param,63 ; VT3xx level?
je decsc3 ; e = yes
ret ; else ignore
decsc3: cmp param[2],2 ; Ps1, range here is 0, 1, 2
ja decsc4 ; a = out of range, ignore
mov flags.vtflg,ttvt320 ; set VT320 mode
mov oldterm,ttvt320
call atsres ; do soft reset of emulator
and vtemu.vtflgop,not vscntl ; turn off 8-bit controls
cmp param[2],1 ; select 7-bit controls?
je decsc4 ; e = yes, we have done so
or vtemu.vtflgop,vscntl ; turn on 8-bit controls
decsc4: ret
; single controls report request
decsc5: cmp lparam,'?' ; want DEC Private modes?
jne decsc5a ; ne = no
call decscpre ; do standard prefix
mov al,'2' ; assume mode is reset
call decsc20 ; do DEC Private mode report
jmp decscend ; do end of sequence
decsc5a:cmp inter,0 ; intermediate char?
je decsc5b ; e = no, ignore
call decscpre ; do standard prefix
mov al,'2' ; assume mode is reset
call decsc5c ; do ANSI report
jmp decscend ; do end of sequence
decsc5b:ret ; else return failure
; ANSI report:
decsc5c:cmp param,2 ; 2, Keyboard action?
jne decsc6 ; ne = no
ret
decsc6: cmp param,3 ; control representation?
jne decsc7 ; ne = no
ret ; say reset(acting on controls)
decsc7: cmp param,4 ; 4, Insert/Replace mode?
jne decsc8 ; ne = no
cmp insmod,0 ; insert mode off?
je decsc7a ; e = yes, off
dec al ; say is on
decsc7a:ret
decsc8: cmp param,10 ; 10, Horizontal editing?
jne decsc9 ; ne = no
mov al,'4' ; permanently reset
ret
decsc9: cmp param,12 ; 12, Send/Receive (local echo)?
jne decsc11 ; ne = no
test vtemu.vtflgop,dececho ; set?
jz decsc12 ; z = no
dec al ; say set
ret
decsc11:cmp param,20 ; 20, new line mode?
jne decsc13 ; ne = no
test vtemu.vtflgop,anslnm ; new line set?
jz decsc12 ; z = no, reset
dec al ; say set
decsc12:ret
decsc13:mov al,'0' ; say not recognized
ret
; DEC Private mode report
decsc20:cmp param,1 ; 1, cursor keys?
jne decsc22 ; ne = no
test vtemu.vtflgop,decckm ; set?
jz decsc31 ; z = no, reset
dec al
ret
decsc22:cmp param,2 ; 2, ANSI mode
jne decsc24 ; ne = no
test vtemu.vtflgop,decanm ; set?
jz decsc31 ; z = no, reset
dec al
ret
decsc24:cmp param,3 ; 3, column
jne decsc26 ; ne = no
test vtemu.vtflgop,deccol ; 132 column mode set?
jz decsc31 ; z = no, reset (80 columns)
dec al
ret
decsc26:cmp param,4 ; 4, scrolling mode
je decsc31 ; e = yes always say reset (jump)
;
cmp param,5 ; 5, screen
jne decsc28 ; ne = no
test vtemu.vtflgop,decscnm ; set (light background)?
jz decsc31 ; z = no, reset
dec al
ret
decsc28:cmp param,6 ; 6, Origin mode?
jne decsc30 ; ne = no
test dspstate,dsptype ; on status line?
jz decsc29 ; z = no, main display
test dspstate,dspdecom ; main display Origin mode set?
jz decsc31 ; z = no, reset
dec al
ret
decsc29:test vtemu.vtflgop,decom ; Origin mode set?
jz decsc31 ; z = no, reset
dec al
ret
decsc30:cmp param,7 ; 7, autowrap?
jne decsc32 ; ne = no
test vtemu.vtflgop,decawm ; set?
jz decsc31 ; z = no, reset
dec al
decsc31:ret ; common return point
decsc32:cmp param,8 ; 8, autorepeat?
jne decsc34 ; ne = no
dec al
ret ; say set
decsc34:cmp param,18 ; 18, print Form Feed?
jne decsc36 ; ne = no
test anspflg,vtffp ; set?
jz decsc31 ; z = no, reset
dec al
ret
decsc36:cmp param,19 ; 19, printer extent?
jne decsc38 ; ne = no
test anspflg,vtextp ; set?
jz decsc31 ; z = no, reset
dec al
ret
decsc38:cmp param,25 ; 25, text cursor enabled?
jne decsc40 ; ne = no
test atctype,4 ; 4 is off
jnz decsc31 ; nz = off/disabled
dec al ; say enabled
ret
decsc40:cmp param,42 ; 42, NRC's
jne decsc42 ; ne = no
cmp flags.vtflg,ttvt320 ; VT320?
jne decsc31 ; ne = no
test vtemu.vtflgop,vsnrcm ; NRC's active?
jz decsc31 ; z = no
dec al ; say enabled
ret
decsc42:cmp param,66 ; 66, numeric keypad?
jne decsc44 ; ne = no
test vtemu.vtflgop,deckpam ; set?
jz decsc31 ; z = no, reset
dec al ; say set
ret
decsc44:cmp param,68 ; 68, keyboard usage?
jne decsc45 ; ne = no
mov al,'4' ; say always typewriter mode
ret
decsc45:mov al,'0' ; say unknown kind
ret
decscpre:mov al,CSI ; do standard report beginning
call out8bit
mov al,byte ptr param ; get parameter
call prtnout ; send the number
mov al,';'
call prtbout
ret
decscend:call prtbout ; do standard rpt end, send char in al
mov al,'$'
call prtbout
mov al,'y'
call prtbout
ret
; DEC style Soft Reset
; Note: graphics rendition is NOT changed by soft reset, DEC manual is wrong.
atsres proc near ; do soft reset of terminal
test dspstate,dsptype ; on status line?
jz atsres1 ; z = no, on main display
mov param,0
mov inter,'$' ; setup entry for atsasd
call atsasd ; select main display
atsres1:and vtemu.vtflgop,not(decawm+decckm+deckpam+decom) ; these go off
mov insmod,0 ; insert mode off
mov mar_top,0 ; reset scrolling margins
mov al,byte ptr low_rgt+1
mov mar_bot,al ; to full screen
mov anspflg,0 ; clear printer flag
mov al,1 ; restore cursor, assume underline (1)
test vtemu.vtflgop,vscursor ; underline?
jnz atsres2 ; nz = yes
inc al ; block (2)
atsres2:mov atctype,al ; save VTxxx cursor type here
call atsctyp ; set the cursor type
push cursor
mov cursor,0 ; set save cursor to Home
call atsc ; save attributes
pop cursor ; restore active cursor
call chrdef ; set default character set
jmp ansdsl ; update status line
atsres endp
; DECRQSS/DECRPSS Control Settings
; Handle DCS ... q string ST
atcrq: cmp ninter,1 ; one intermediate?
je atcrq1 ; e = yes
ja atcrq0 ; a = too many
jmp atcrqq ; none, do Sixel DCS params q...ST
atcrq0: mov ttstate,offset atdcsnul ; not understood, consume til ST
atcrq1: cmp inter,'$' ; correct intermediate?
jne atcrq0 ; ne = no
cmp nparam,0 ; and no parameters?
jne atcrq0 ; ne = have some, not ours
mov ttstateST,offset atcrq4 ; set state for ST arrival
mov ttstate,offset atcrq2 ; next state gets string contents
mov emubufc,0 ; clear buffer counter
mov word ptr emubuf,0 ; empty start of buffer
ret
atcrq2: mov bx,emubufc ; count of chars in string buffer
cmp bx,emubufl ; too many?
jae atcrq3 ; ae = too many, ignore extras
mov emubuf[bx],al ; store the char
inc emubufc ; count it
atcrq3: ret
; here after ST has been seen
atcrq4: cmp emubufc,2 ; max string chars we want
jbe atcrq4a ; be = ok
jmp atnorm ; a = too many, ignore
atcrq4a:mov ax,word ptr emubuf ; get first two chars
cmp ax,'}$' ; select active display?
jne atcrq5 ; ne = no
jmp atcrqd ; do the routine
atcrq5: cmp ax,'q"' ; set char attribute?
jne atcrq6 ; ne = no
jmp atcrqxx ; say we can't do this one
atcrq6: cmp ax,'p"' ; set conformance level?
jne atcrq7 ; ne = no
jmp atcrqp
atcrq7: cmp ax,'~$' ; set status line type
jne atcrq8
jmp atcrqt
atcrq8: cmp ax,'r' ; set top and bottom margins?
jne atcrq9
jmp atcrqr
atcrq9: cmp ax,'m' ; set graphic rendition?
jne atcrq10
jmp atcrqm
atcrq10:jmp atcrqxx ; unknown command
; DCS $ q response routines
atcrqr: call atcrqbeg ; 'r', top/bottom margins
test dspstate,dsptype ; doing status line display?
jz atcrqr2 ; z = no
mov al,byte ptr dspmsave ; get saved top margin
inc al
call prtnout
mov al,';'
call prtbout
mov al,byte ptr dspmsave+1 ; get saved bottom margin
jmp short atcrqr3 ; finish up
atcrqr2:mov al,mar_top ; top margin
inc al ; move to 1,1 system
call prtnout
mov al,';'
call prtbout
mov al,mar_bot
atcrqr3:inc al ; move to 1,1 system
call prtnout
mov al,'r' ; final char
jmp atcrqend ; do epilogue
atcrqm: call atcrqbeg ; 'm', graphics rendition
mov al,'0' ; say start with all attributes off
call prtbout
mov ah,scbattr ; current attribute
call getbold ; returns ah with bold attr or 0
or ah,ah ; bold set?
je atcrqm2 ; e = no
mov al,';'
call prtbout
mov al,'1' ; say bold is on
call prtbout
atcrqm2:mov ah,scbattr
call getunder ; underline
or ah,ah ; underline on?
je atcrqm3 ; e = no, do next
mov al,';'
call prtbout
mov al,'4' ; say underlining is on
call prtbout
atcrqm3:mov ah,scbattr
call getblink ; blinking
or ah,ah ; blinking on?
je atcrqm4 ; e = no
mov al,';'
call prtbout
mov al,'5' ; say blinking is on
call prtbout
atcrqm4:cmp video_state,0 ; chars in reversed video?
je atcrqm5 ; e = no
mov al,';'
call prtbout
mov al,'7' ; say underlining is on
call prtbout
atcrqm5:mov al,'m' ; final char
jmp atcrqend ; do epilogue
atcrqd: call atcrqbeg ; '$}', writing to screen/status line
mov al,'0' ; assume writing to main display
test dspstate,dsptype ; get type of display
jz atcrqd2 ; z = main display
inc al ; say writing to mode line
atcrqd2:call prtbout
mov al,'$' ; final chars
call prtbout
mov al,7dh ; right curly brace
jmp atcrqend ; do epilogue
atcrqt: call atcrqbeg ; '$~', status line
mov al,'0' ; assume mode line is off
test yflags,modoff ; is mode line off?
jnz atcrqt2 ; nz = yes
mov al,'2' ; mode line is on and host writable
atcrqt2:call prtbout
mov al,'c' ; final chars
call prtbout
mov al,7eh ; tilde
jmp atcrqend ; do epilogue
; '"p' set conformance level
atcrqp: cmp oldterm,ttvt100 ; main-mode terminal is VT102?
je atcrqp2 ; e = yes
cmp oldterm,ttvt320 ; how about VT320?
je atcrqp2 ; e = yes
jmp atcrqxx ; say invalid request
atcrqp2:mov al,DCS ; '"p', conformance level
call out8bit
mov al,'0' ; valid request
call prtbout
mov al,'$'
call prtbout
mov al,61 ; assume VT102
cmp oldterm,ttvt100 ; are we a VT102?
jne atcrqp3 ; ne = no
call prtnout
jmp short atcrqp5 ; finish the report
atcrqp3:mov al,63 ; say VT320
call prtnout
mov al,';'
call prtbout
mov al,'2' ; assume 8-bit controls are on
test vtemu.vtflgop,vscntl ; 8-bit controls active?
jnz atcrqp4 ; nz = yes
mov al,'1' ; else say only 7-bit controls
atcrqp4:call prtbout
atcrqp5:mov al,'"' ; final characters
call prtbout
mov al,'p'
jmp atcrqend ; do epilogue
atcrqbeg:mov al,DCS ; report prologue
call out8bit
mov al,'0' ; valid request
call prtbout
mov al,'$'
jmp prtbout
atcrqend:call prtbout ; report epilogue, al has char
mov al,STCHR ; string terminator
jmp out8bit
atcrqxx:mov al,DCS ; report invalid request
call out8bit
mov al,'1' ; invalid request
call prtbout
mov al,'$'
cmp emubufc,1 ; any first char?
jb atcrqend ; b = no
call prtbout
mov al,emubuf ; first string char
cmp emubufc,2 ; two string chars?
jne atcrqend ; ne = no
call prtbout
mov al,emubuf+1 ; second string char
jmp atcrqend ; do epilogue
; DCS P1; P2; P3 <char> Sixel command
atcrqq: cmp dcsstrf,'q' ; final char of 'q'? Sixel draw
je atcrqq1 ; e = yes
cmp dcsstrf,'p' ; 'p', restore palette?
jne atcrqq0 ; ne = no
cmp dinter,'$' ; DCS 2 $ p?
jne atcrqq0 ; ne = no
cmp param,2 ; this too?
je atcrqq1 ; e = yes
atcrqq0:jmp atdcsnul ; consume unknown command
atcrqq1:test denyflg,tekxflg ; is auto Tek mode disabled?
jnz atcrqq0 ; nz = yes, consume
mov di,offset emubuf ; temp buffer
mov byte ptr [di],escape ; do ESC ^L to erase screen
inc di
mov byte ptr [di],FF
inc di
mov byte ptr [di],escape ; start DCS
inc di
mov byte ptr [di],'P'
inc di
mov ax,dparam[0] ; get first parameter
call dec2di
mov byte ptr [di],';'
inc di
mov ax,dparam[2] ; get second parameter
call dec2di ; write ascii value
mov byte ptr [di],';'
inc di
mov ax,dparam[4] ; get third parameter
call dec2di ; write ascii value
mov al,dcsstrf
mov byte ptr [di],al ; final char
mov byte ptr [di+1],0 ; terminator
mov di,offset emubuf
mov al,yflags ; get yflags
and al,capt ; save logging bit
push ax
and yflags,not capt ; turn off logging bit
atcrqq2:mov al,[di]
inc di
or al,al ; at the end?
jz atcrqq3 ; z = yes
push di
call tekemu ; feed Tek emulator this string
pop di
jmp short atcrqq2 ; do another string member
atcrqq3:mov chcontrol,1 ; turn on full cell char writing
pop ax ; recover logging bit
or yflags,al ; restate logging bit
jmp atnorm
; Device Status Reports
atdsr: mov di,offset atdsr1 ; routine to call
call atreps ; do for all parms
ret
; DSR workers
atdsr1: cmp lparam,0 ; any intermediate?
jne atdsr2 ; ne = yes, an intermediate
cmp param[si],5 ; operating status report?
je rpstat ; e = yes
cmp param[si],6 ; cursor position report?
je rpcup ; e = yes
atdsr2: cmp lparam,'?' ; DEC mode queries for below?
jne atdsr3 ; no, skip them
cmp param[si],15 ; printer status report?
je rpstap ; e = yes
cmp param[si],25 ; UDK status?
jne atdsr3 ; ne = no
jmp rpudk ; do udk status rpt
atdsr3: cmp param[si],26 ; keyboard type?
jne atdsr4 ; ne = no
jmp rpkbd ; do keyboard type report
atdsr4: cmp param[si],256 ; WordPerfect Tek screen query?
jne atdsr5 ; ne = no
jmp tekrpt ; do Tek report
atdsr5: ret ; must have been an echo
rpstat: mov al,CSI ; operating status query
call out8bit
mov al,'0' ; tell them we think we are OK
call prtbout
mov al,'n'
call prtbout
ret
rpcup: mov al,CSI ; cursor position report
call out8bit
mov al,byte ptr cursor+1 ; get row
inc al ; map to origin at 1,1 system
test vtemu.vtflgop,decom ; Origin mode set?
jz rpcup1 ; z = no
sub al,mar_top ; subtract off top margin
rpcup1: call prtnout ; output the number
mov al,';'
call prtbout
mov al,byte ptr cursor ; column number
inc al ; map to origin at 1,1 system
call prtnout
mov al,'R' ; final char
call prtbout
ret
rpstap: mov al,CSI ; printer port query
call out8bit ; send CSI or ESC [ ? 10 or 13 n
mov al,'?' ; 10 = printer ready, 13 = not ready
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 short rpstap2
rpstap1:mov al,'3' ; not ready, say printer disconnected
rpstap2:call prtbout
mov al,'n' ; final char of response
call prtbout
ret
rpudk: mov al,CSI ; response to UDK locked query
call out8bit
mov al,'?'
call prtbout
mov al,20 ; say keys are unlocked (locked=21)
call prtnout
mov al,'n' ; final char
call prtbout
ret
rpkbd: mov al,CSI ; response to kbd type query
call out8bit
mov al,'?'
call prtbout
mov al,27 ; keyboard dialect follows
call prtnout
mov al,';'
call prtbout
mov bl,vtemu.vtchset ; get Kermit NRC code (0-13)
xor bh,bh
mov al,nrckbd[bx] ; get DEC keyboard code from table
call prtnout
mov al,'n'
call prtbout
ret
tekrpt: call tekinq ; get Tek screen size and num colors
push cx ; screen colors
push bx ; screen width
push ax ; screen height
mov al,CSI ; response to Tek query
call out8bit
mov al,'?'
call prtbout
mov di,offset emubuf ; working buffer
mov byte ptr [di],0 ; insert terminator
mov ax,256 ; first parameter
call dec2di ; write ascii digits
mov byte ptr [di],';' ; separator
inc di
pop ax ; get screen height
call dec2di
mov byte ptr [di],';' ; separator
inc di
pop ax ; get screen width
call dec2di
mov byte ptr [di],';' ; separator
inc di
pop ax ; get number screen color (0, 1 or 16)
call dec2di
mov byte ptr[di],'n' ; end of sequence
inc di
mov cx,di ; compute string length
mov di,offset emubuf
sub cx,di
tekrpt1:mov al,[di] ; get a string char
inc di
call prtbout ; send it
loop tekrpt1
ret
atrqtsr:cmp flags.vtflg,ttheath ; Heath-19? ESC [ u
jne atrqts1 ; ne = no
cmp nparam,0 ; ought to have no parameters
jne atrqts2 ; ne = oops, not H-19 command, ignore
jmp atrc ; H19, restore cursor pos and attrib
atrqts1:cmp inter,'$' ; VT320 Terminal State Rpt DECRQTSR?
jne atrqts2 ; ne = no
cmp param,1 ; report required?
je atrqts4 ; e = yes
cmp param,2 ; VT340 color palette report?
jne atrqts1a ; ne = no
call tekinq ; get Tek screen state
call tekpal ; do palette report in Tek emulator
atrqts1a:ret
atrqts2:cmp inter,'&' ; DECRQUPSS, User preferred Supp Set?
je atrqts5 ; e = yes
ret ; else ignore
atrqts4:mov al,DCS ; Terminal state report
call out8bit ; output as 7- or 8-bit quantity
mov al,byte ptr param
call prtnout ; output as ascii digits, no echo
mov al,'$'
call prtbout ; output char, no echo
mov al,'s' ; Final char to main DCS part
call prtbout
mov al,STCHR ; terminator to empty string
call out8bit
ret
atrqts5:mov al,DCS ; User Preferred Supplemental Set
call out8bit ; report
mov al,'0' ; assume 94 byte set
cmp word ptr upss,94 ; 94 byte set?
jne atrqts6 ; ne = no
inc al ; change to 96 byte size
atrqts6:call prtbout
mov al,'!'
call prtbout
mov al,'u'
call prtbout
mov al,upss+1 ; first ident char
call prtbout
mov al,upss+2 ; second char, if any
or al,al
jz atrqts7 ; z = no second char
call prtbout
atrqts7:mov al,STCHR
call out8bit
ret
; Request Presentation State Report
atrqpsr:cmp inter,'$' ; proper form?
jne atrqps1 ; ne = no, ignore
cmp param,1 ; cursor report?
je atrqps2 ; e = yes
cmp param,2 ; tabstop report?
jne atrqps1 ; ne = no, ignore
jmp atrqps40 ; do tabstop report
atrqps1:ret ; else ignore
atrqps2:mov al,DCS ; cursor report, start
call out8bit
mov al,'1'
call prtbout
mov al,'$'
call prtbout
mov al,'u'
call prtbout
mov al,dh ; row of cursor
inc al ; count from 1,1
call prtnout ; output number
mov al,';'
call prtbout
mov al,dl ; column of cursor
inc al ; count from 1,1
call prtnout ; output number
mov al,';'
call prtbout
mov al,'1' ; video page, always 1 for VT320
call prtbout
mov al,';'
call prtbout
mov al,40h ; start bit field template
cmp video_state,1 ; reverse video char writing on?
jne atrqps3 ; ne = no
or al,8 ; set the bit
atrqps3:call getblink ; ah will be non-zero if blinking
or ah,ah ; blinking?
je atrqps4 ; z = no
or al,4 ; set the bit
atrqps4:call getunder ; ah will be non-zero if underlining
or ah,ah ; underlining?
je atrqps5 ; z = no
or al,2 ; set the bit
atrqps5:call getbold ; ah will be non-zero if bolding
or ah,ah ; bold?
je atrqps6 ; z = no
or al,1 ; set the bit
atrqps6:call prtbout
mov al,';'
call prtbout
mov al,40h ; Satt (Selective params), none here
call prtbout ; output required skeleton
mov al,';'
call prtbout
mov al,40h ; Sflag (shift/wrap/origin mode)
cmp atwrap,0 ; wrap pending?
je atrqps7 ; e = no
or al,8 ; set the bit
atrqps7:cmp SSptr,offset G3set ; SS3: G3 mapped to GL for next char?
jne atrqps8 ; ne = no
or al,4 ; set the bit
atrqps8:cmp SSptr,offset G2set ; SS2: G2 mapped to GL for next char?
jne atrqps9 ; ne = no
or al,2 ; set the bit
atrqps9:test vtemu.vtflgop,decom ; Origin mode set?
jz atrqps10 ; z = no
or al,1 ; set the bit
atrqps10:call prtbout
mov al,';'
call prtbout
mov al,'0' ; Pgl, say which set is in GL
mov si,GLptr ; setup for worker
call atrqps30 ; worker returns proper al
call prtbout
mov al,';'
call prtbout
mov al,'0' ; Pgr, say which set is in GR
mov si,GRptr ; setup for worker
call atrqps30 ; worker returns proper al
call prtbout
mov al,';'
call prtbout
mov al,40h ; Scss, char set size bit field
call atrqp15 ; call worker to fill in al
call prtbout
mov al,';'
call prtbout
mov bx,offset G0set ; Sdesig, get 1-2 letter ident
call atrqps20 ; G0, let worker fill in response
mov bx,offset G1set
call atrqps20 ; G1, let worker fill in response
mov bx,offset G2set
call atrqps20 ; G2, let worker fill in response
mov bx,offset G3set
call atrqps20 ; G3, let worker fill in response
mov al,STCHR ; String terminator
call out8bit
ret
; worker for Character set size reporting
atrqp15:cmp G0set+96,gsize ; is G0 a 96 byte set?
jne atrqp16 ; ne = no
or al,1 ; say 96
atrqp16:cmp G1set+96,gsize ; is G1 a 96 byte set?
jne atrqp17 ; ne = no
or al,2 ; say 96
atrqp17:cmp G2set+96,gsize ; G2 set?
jne atrqp18
or al,4 ; say 96
atrqp18:cmp G3set+96,gsize ; G3 set?
jne atrqp19
or al,8 ; say 96
atrqp19:ret ; return with al setup
; worker for Character set ident reporting at atrqps16: et seq
atrqps20:mov al,[bx+gsize+1] ; Gn set pointer, first letter
call prtbout
mov al,[bx+gsize+2] ; second letter
or al,al ; is there one?
jz atrqps21 ; z = no, nothing there
call prtbout
atrqps21:ret
; worker. Enter with SI holding GLptr or GRptr and al = '0'
; Returns al = '0' .. '3' to match set pointed at
atrqps30:cmp si,offset G0set ; si points at G0?
je atrqps31 ; e = yes
inc al ; try next set
cmp si,offset G1set ; si points at G1?
je atrqps31
inc al
cmp si,offset G2set ; si points at G2?
je atrqps31
inc al ; must be G3
atrqps31:ret
atrqps40:mov al,DCS ; start tabstop report
call out8bit
mov al,'2' ; tabs
call prtbout
mov al,'$'
call prtbout
mov al,'u'
call prtbout
mov cl,byte ptr low_rgt ; right most column number
inc cl ; number of columns
xor ch,ch
push dx ; save dx
mov dx,0 ; dh for done one output, dl = column
mov si,offset tabs ; active tabs buffer
atrqps41:call istabs ; tab inquiry routine, column is in dl
jnc atrqps43 ; nc = no tab
or dh,dh ; sent one value already?
je atrqps42 ; e = no, so no separator
mov al,';' ; separator (DEC used '/')
call prtbout
atrqps42:mov al,dl ; get column
inc al ; count columns from 1 for host
call prtnout ; output the number
inc dh ; say sent a number
atrqps43:inc dl ; next column, say sent one output
loop atrqps41 ; do the rest
pop dx ; recover dx
mov al,STCHR ; string terminator
call out8bit
ret
; Process Restore Presentation Reports, for cursor and tab stops
; Uses bytes dinter+5 and dinter+6 as internal variables
atrp: cmp dinter,0+'$' ; correct intermediate?
je atrp1 ; e = yes
jmp atcrqxx ; send back "illegal restore" response
atrp1: cmp dparam,1 ; cursor info?
je atrp4 ; e = yes
mov modeset,1 ; say setting tabs
call atrpw ; call worker to do ascii to binary
dec dl ; count internally from col 0
call tabset ; set tab in column dl
atrp3: mov emubufc,0 ; clear the string count
ret
; start cursor info report playback
atrp4: cmp dinter+5,0 ; our internal counter in vacant byte
jne atrp5 ; not initial byte
inc dinter+5 ; point to next item next time
call atrpw ; ascii to binary worker
xchg dh,dl ; get row to correct byte
mov dl,byte ptr cursor+1 ; get column
jmp atscu5 ; set the cursor
atrp5: cmp dinter+5,1 ; column?
jne atrp6
inc dinter+5 ; point to next item next time
call atrpw ; ascii to binary worker
mov dh,byte ptr cursor ; get row
jmp atscu5 ; set the cursor
atrp6: cmp dinter+5,2 ; page?
jne atrp7
inc dinter+5 ; omit page byte
ret
atrp7: cmp dinter+5,3
jne atrp8
inc dinter+5 ; Srend
mov al,emubuf ; string byte
mov ah,curattr ; attributes field
; ought to clear attributes first
test al,1 ; set bold?
jz atrp7a ; z = no
call setbold
atrp7a: test al,2 ; set underline?
jz atrp7b ; z = no
call setunder
atrp7b: test al,4 ; set blink?
jz atrp7c ; z = no
call setblink
atrp7c: mov curattr,ah ; attributes so far
test al,8 ; set per char rev video?
jz atrp7d ; z = no
cmp video_state,0 ; reversed already?
jne atrp7d ; ne = yes
call revideo
inc video_state ; say reversed now
mov curattr,ah
atrp7d: ret
atrp8: cmp dinter+5,4
jne atrp9
inc dinter+5 ; Satt, skip it
ret
atrp9: cmp dinter+5,5
jne atrp10
inc dinter+5
mov al,emubuf ; string byte
mov ah,al
and ah,8 ; autowrap bit
mov atwrap,ah ; set it
mov SSptr,0 ; say no single shift needed
test al,4 ; SS3 bit?
jz atrp9a ; z = no
mov SSptr,offset G3set ; set the pointer
atrp9a: test al,2 ; SS2 bit?
jz atrp9b ; z = no
mov SSptr,offset G2set ; set the pointer
atrp9b: and vtemu.vtflgop,not decom ; clear origin bit
test al,1 ; origin mode?
jz atrp9c ; z = no
or vtemu.vtflgop,decom ; set origin mode
atrp9c: ret
atrp10: cmp dinter+5,6 ; Pgl
jne atrp11
inc dinter+5
mov al,emubuf ; string byte
call atrpw5 ; call worker to setup bx with ptr
mov GLptr,bx
ret
atrp11: cmp dinter+5,7 ; Pgr
jne atrp12
inc dinter+5
mov al,emubuf ; string byte
call atrpw5 ; call worker to setup bx with ptr
mov GRptr,bx
ret
atrp12: cmp dinter+5,8 ; Scss
jne atrp13 ; ne = no
inc dinter+5
mov al,emubuf ; string byte
and al,0fh ; strip ascii bias
mov dinter+6,al ; save here for Sdesig byte, next
ret
atrp13: cmp dinter+5,9 ; Sdesig
jne atrp14
inc dinter+5
mov si,offset emubuf ; string
xor cx,cx ; init loop counter to 0
atrp13a:mov al,'(' ; assume G0 is 94 byte set
add al,cl ; plus loop index to get set pointer
shr dinter+6,1 ; get set size bit
jnc atrp13b ; e = correct
add al,4 ; map to 96 byte indicator
atrp13b:mov inter,al ; store size byte as intermediate
mov ninter,1 ; one char
cld
atrp13c:lodsb ; next string byte
test al,not 2fh ; is there a second intermediate byte?
jnz atrp13d ; nz = no
mov inter+1,al ; store intermediate
inc ninter ; count them
jmp short atrp13c ; try again for a Final char
atrp13d:push si
push cx
mov bx,offset ansesc ; table to use
call atdispat ; dispatch on final char to set ptr
pop cx
pop si
inc cx
cmp cx,3 ; doing last one?
jbe atrp13a ; be = no, do all four
ret
atrp14: jmp atcrqxx ; send back "illegal restore" response
; worker, ascii string to decimal byte
atrpw: mov cx,emubufc ; length of this string
jcxz atrpw3 ; nothing there
mov si,offset emubuf ; address of string
xor dl,dl ; init final value
cld
atrpw2: lodsb ; read a digit
sub al,'0' ; ascii to numeric
jc atrpw3 ; c = trouble
shl dl,1 ; previous contents times 10
mov dh,dl
shl dl,1
shl dl,1
add dl,dh
add dl,al ; plus new value
loop atrpw2 ; do all digits
atrpw3: ret
; char set selector worker
atrpw5: cmp al,'0' ; bx gets G0set...G3set, based on AL
jne atrpw5a
mov bx,offset G0set
ret
atrpw5a:cmp al,'1'
jne atrpw5b
mov bx,offset G1set
ret
atrpw5b:cmp al,'2'
jne atrpw5c
mov bx,offset G2set
ret
atrpw5c:mov bx,offset G3set
ret
; VT52 compatibility mode routines.
; Return to ANSI mode.
v52ans: or vtemu.vtflgop,decanm ; turn on ANSI flag
mov al,oldterm ; terminal type at startup
cmp al,ttvt52 ; was VT52 the prev kind?
jne v52ans1 ; ne = no
mov al,ttvt320 ; use VT320
v52ans1:mov oldterm,al
mov flags.vtflg,al ; restore it
call chrdef ; set default char sets
call atsc ; save cursor status
jmp ansdsl ; put "LEDs" back
; VT52 cursor positioning.
v52pos: mov ttstate,offset v52pc1 ; next state
ret
v52pc1: sub al,' '-1 ; minus offset
xor ah,ah
mov param,ax ; stash it here
mov ttstate,offset v52pc2 ; next state
ret
v52pc2: sub al,' '-1 ; minus offset
xor ah,ah
mov param+2,ax ; stash here
mov ttstate,offset atnrm ; reset state to "normal"
jmp atcup ; position and return
; VT52 print controls
v52ps: mov param,0 ; print screen
mov lparam,0
jmp ansprt ; simulate ESC [ 0 i
v52pl: mov param,1 ; print line
jmp short v52pcom ; simulate ESC [ ? 1 i
v52pcb: mov param,5 ; Enter printer controller on
jmp short v52pcom ; simulate ESC [ ? 5 i
v52pce: mov param,4 ; Exit printer controller on
; jmp short v52pcom ; simulate ESC [ ? 4 i
v52pcom:mov lparam,'?' ; simulate ESC [ ? <number> i
jmp ansprt ; process command
v52sgm: mov setptr,offset G0set ; enter/exit special graphics mode
jmp atdg52 ; construct G0set, AL has 'F' or 'G'
; Heath-19 special functions
h19sans:or vtemu.vtflgop,decanm ; Turn on ANSI flag. ESC <
jmp chrdef ; set default char sets
; clear screen and go home
h19ed: cmp param,0 ; Erase cursor to end of screen?
jne h19ed2 ; ne = no
mov ax,dx ; start at cursor
mov bh,byte ptr low_rgt+1 ; lower right corner
cmp bh,dh ; on status line?
jae h19ed1 ; ae = no
mov bh,dh ; put end on status line
h19ed1: mov bl,crt_cols ; physical width
dec bl ; we count from 0
jmp vtsclr ; clear it
h19ed2: cmp param,1 ; erase start of display to cursor?
je h19esos ; e = yes
cmp param,2 ; erase entire screen?
je h19clrs ; e = yes
ret ; else ignore
; erase entire screen
h19clrs:cmp dh,byte ptr low_rgt+1 ; on status line?
ja h19erl ; a = yes, do just erase in line
xor dx,dx ; go to upper left corner
call atscu5 ; do it
xor ax,ax ; clear screen from (0,0)
mov bh,byte ptr low_rgt+1 ; to lower right corner
mov bl,crt_cols ; physical width
dec bl ; we count from 0
jmp vtsclr ; clear it
h19erl: xor al,al ; erase whole line
mov bl,crt_cols ; physical width
dec bl ; we count from 0
jmp erinline ; erase whole line, cursor stays put
h19ero: xor al,al ; erase start of line to cursor
mov bl,dl
jmp erinline ; clear that part of line
; erase start of screen to cursor
h19esos:cmp dh,byte ptr low_rgt+1 ; on status line?
ja h19ero ; a = yes, do just erase in line
jmp ersos ; do regular erase start of screen
h19wrap:or vtemu.vtflgop,decawm ; turn on line wrapping
ret
h19nowrp:and vtemu.vtflgop,not decawm ; turn off line wrapping
ret
h19herv:mov ah,curattr ; get current cursor attribute
mov curattr,ah ; store new attribute byte
call setrev ; ESC p set reversed video
mov curattr,ah ; store new attribute byte
ret
h19hxrv:mov ah,curattr ; get current cursor attribute
call clrrev ; ESC q set normal video
mov curattr,ah ; store new attribute byte
ret
h19sc: mov dx,cursor
mov h19cur,dx ; save cursor position
ret
h19rc: mov dx,h19cur ; saved cursor position
jmp atscu5 ; set cursor and 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
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
ret
; Insert/Delete characters and lines
inslin proc near
mov dx,param ; insert line
or dx,dx ; any args?
jne insli1 ; ne = yes
inc dx ; insert one line
insli1: mov scroll,dl ; lines to scroll
mov dx,cursor ; current position
cmp dh,mar_bot ; below bottom margin?
ja insli3 ; a = below bottom margin
push word ptr mar_top
mov mar_top,dh ; call present position the top
call atscrd ; scroll down
pop word ptr mar_top ; restore margins
xor dl,dl ; go to left margin
jmp atscu5 ; reposition cursor and return
insli3: ret
inslin endp
dellin proc near
mov dx,param ; delete line(s)
or dx,dx ; any args?
jne delli1 ; ne = yes
inc dx ; insert one line
delli1: mov scroll,dl ; line count
mov dx,cursor ; where we are presently
cmp dh,mar_bot ; at or below bottom margin?
jae delli3 ; ae = yes, do not scroll
push word ptr mar_top ; save current scrolling margins
mov mar_top,dh ; temp top margin is here
call atscru ; scroll up
pop word ptr mar_top ; restore scrolling margins
jmp atscu5 ; restore cursor and return
delli3: ret
dellin endp
ansich proc near ; ANSI insert characters ESC [ Pn @
mov cx,param
or cx,cx ; any arguments?
jne ansic1 ; ne = no, ignore
inc cx ; use one
ansic1: push bx ; use this as insert/delete flag
mov bh,1 ; do an insert operation
ansic2: call insdel ; do common insert/delete code
pop bx
ret
ansich endp
inschr proc near ; insert open (space) char at cursor
push bx ; use this as insert/delete flag
mov bh,1 ; do an insert operation
mov cx,1 ; do one character
call insdel ; do common insert/delete code
pop bx
ret
inschr endp
atdelc proc near
mov cx,param ; Delete characters(s)
or cx,cx ; zero becomes one operation
jne atdelc1
inc cx ; delete one char. Heath ESC N
atdelc1:push bx ; use this as insert/delete flag
mov bh,-1 ; do a delete operation
atdelc2:call insdel ; do common insert/delete code
pop bx
ret
atdelc endp
; Common code for insert/delete char
insdel proc near ; SI has insert/delete code
mov dx,cursor ; logical cursor
mov bl,byte ptr low_rgt ; number of columns on screen - 1
push bx
mov bl,dh ; cursor row
xor bh,bh ; bx holds cursor row
cmp linetype [bx],0 ; is line already single width?
je insdel1 ; e = yes
add dl,dl ; double the cursor column
add cx,cx ; double repeat count
insdel1:mov bl,byte ptr low_rgt ; physical left margin
inc bl ; number of screen columns
sub bl,dl ; width - cursor
cmp cx,bx ; skipping more than screen width?
jbe insdel2 ; be = no
mov cx,bx ; limit to screen width please
insdel2:pop bx
; dh=logical cursor row, dl= logical cursor column, cx has repeat count
; bl = logical screen width - 1, bh = +1 for insert, -1 for delete chars.
jmp insdecom ; do system dependent operation
insdel endp
noins: mov insmod,0 ; turn off insert mode
ret
entins: mov insmod,0ffh ; enter insert mode
ret
; Line type to/from single or double
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
mov dh,byte ptr cursor+1 ; row
xor dl,dl ; start in column 0
mov cl,byte ptr low_rgt ; number of columns on screen
inc cl
shr cl,1 ; number of columns to do
xor ch,ch
push cx ; save around loop below
linsgl1:push cx ; save loop counter
push dx
shl dl,1 ; double column number
call direction ; set dx to desired position
call setpos ; set cursor position
call getatch ; read char (al) and attribute (ah)
pop dx
push dx
call direction ; set dx to desired position
call setpos ; set cursor position
pop dx
call setatch ; write char (al) and attribute (ah)
inc dl ; next column
pop cx
loop linsgl1
pop cx ; recover column counter
mov dl,cl
linsgl2:push cx ; save counter
push dx
call direction ; set dx to desired position
call setpos ; set cursor position
mov ah,scbattr ; screen background
mov al,' '
call setatch ; write char
pop dx
pop cx
inc dl ; next column
loop linsgl2 ; repeat for all characters
linsglx:pop dx
pop cx
pop bx
pop ax
jmp atscur ; update cursor and return
linesgl endp
linedbl proc near ; convert line to double width char
push ax ; must reset physical cursor
push bx ; to same char as before expansion
push cx ; but does not modify variable cursor
push dx
mov bx,cursor
mov bl,bh
xor bh,bh ; bx now holds row
cmp linetype [bx],0 ; is line single width?
jne lindblx ; ne = no. nothing to do
mov linetype [bx],1 ; say will be double width now
mov dx,cursor
mov cl,byte ptr low_rgt ; number of columns on the screen
inc cl
xor ch,ch
shr cl,1 ; number of items to do
mov dl,cl
dec dl
lindbl1:push cx ; save loop counter
push dx
call direction ; set dx to desired position
call setpos ; set cursor position
call getatch ; read char (al) and attribute (ah)
pop dx
shl dl,1 ; double the column number
push dx
call direction ; set dx to desired position
call setpos ; set cursor position
pop dx
call setatch ; write char and attribute
inc dl ; move to second column of double
push dx
call direction ; set dx to desired position
call setpos ; set cursor position
pop dx
mov al,' ' ; space as filler
call setatch ; write that char
dec dl
shr dl,1
dec dl
pop cx
loop lindbl1
lindblx:pop dx
pop cx
pop bx
pop ax
jmp atscur ; update the cursor and return
linedbl endp
; Printer support routines
ansprt proc near
mov di,offset ansprt0 ; routine to process arguments
call atreps ; repeat for all parms
ret
ansprt0:mov ax,param[si] ; pick up the argument
or ax,ax ; 0 (print all/part of screen)?
jnz ansprt1 ; nz = 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 ax,1 ; 1 (print current line)?
jne ansprt4 ; ne = no
call pntchk ; check for printer ready
jc ansprtx ; c = printer not ready
call pntlin ; print current line
call pntflsh ; flush printer buffer
jmp atscu5 ; reposition cursor and return
ansprt4:cmp ax,4 ; 4 (auto print disable)?
jne ansprt5 ; ne = no
cmp lparam,'?' ; was it ESC [ ? 4 i
jne anspr4a ; ne = no, so it was ESC [ 4 i
test anspflg,vtautop ; check state of print flag
jz anspr4a ; z = off already
or anspflg,vtautop ; say auto-print enabled to toggle off
jmp trnprs ; toggle mode line PRN indicator
anspr4a:ret
ansprt5:cmp ax,5 ; 5 (auto print enable)?
jne ansprtx ; ne = no
call pntchk ; check printer, ignore carry ret
jc ansprtx ; c = printer not ready
cmp lparam,'?' ; was it ESC [ ? 5 i
jne anspr5a ; ne = no
test anspflg,vtautop ; is print already enabled?
jnz ansprtx ; nz = yes, leave trnprs intact
and anspflg,not vtautop ; say auto-print disabled to toggle on
jmp trnprs ; toggle on mode line PRN indicator
anspr5a:test anspflg,vtcntp ; controller print already enabled?
jnz ansprtx ; nz = yes
and anspflg,not vtautop ; clear single-char flag for toggling
or anspflg,vtcntp ; controller print enabled
mov emubufc,0 ; clear string buffer
mov ttstate,offset ansmc ; do transparent print
jmp trnprs ; toggle on mode line PRN indicator
ansprtx:ret
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) or a
; repeated Media Copy On (ESC [ 5 i) has been received or the emulator reset.
; New char is in al.
ansmc proc near
mov ttstate,offset ansmc ; stay in this state
cmp al,escape ; start a new sequence?
je ansmc1 ; e = yes
cmp al,CSI ; start a new sequence?
je ansmc0a ; e = yes
mov emubufc,0 ; say no matched chars
jmp pntchr ; print char in al, ignore errors
; CSI seen
ansmc0a:call ansmc5 ; playback previous matches
mov ttstate,offset ansmc3 ; get numeric arg
mov emubufc,2 ; say matched "ESC ["
mov word ptr emubuf,escape+256*'[' ; store them
ret
; ESC seen
ansmc1: call ansmc5 ; playback previous matches
mov ttstate,offset ansmc2 ; get left square bracket
mov emubufc,1 ; one char matched
mov emubuf,al ; store it
ret
ansmc2: cmp al,'[' ; right square bracket?
je ansmc2a ; e = yes
call ansmc5 ; playback previous matches
jmp pntchr ; print char in al, ignore errors
ansmc2a:inc emubufc ; say matched "ESC ["
mov emubuf+1,al ; store it
mov ttstate,offset ansmc3 ; get numeric arg
ret
; CSI or ESC [ seen
ansmc3: inc emubufc ; another char
mov emubuf+2,al ; store it
cmp al,'4' ; possible MC OFF?
je ansmc3a ; e = yes
cmp al,'5' ; possible repeated MC ON?
je ansmc3a ; e = yes
cmp al,'6' ; possible CSI 6 i?
je ansmc3a ; e = yes, keep for a while
jmp ansmc5 ; no, playback previously matched
ansmc3a:mov ttstate,offset ansmc4 ; get 'i' Final char
ret
ansmc4: inc emubufc ; last char
mov emubuf+3,al ; store it
cmp al,'i' ; correct Final char?
je ansmc4a ; e = yes
jmp ansmc5 ; playback previous matches
; CSI 4 i, CSI 5 i, or CSI 6 i seen
ansmc4a:cmp emubuf+2,'4' ; was it CSI 4 i MC OFF?
je ansmc4b ; e = yes
cmp al,'5' ; repeated CSI 5 i MC ON?
je ansmc7 ; e = yes, ignore it
cmp flags.vtflg,ttvt100 ; must be CSI 6 i. VT102?
jne ansmc5 ; ne = no, replay it
jmp short ansmc7 ; yes, VT102's absorb CSI 6 i
; Media OFF found
ansmc4b:mov ttstate,offset atnorm ; return to normal state
call pntflsh ; flush printer buffer
test anspflg,vtcntp ; was printing active?
jz ansmc7 ; z = no
and anspflg,not vtcntp ; yes, disable print controller
jmp trnprs ; toggle mode line PRN indicator
; playback emubufc matched chars
ansmc5: mov cx,emubufc ; matched char count
jcxz ansmc7 ; z = none
push ax ; save current char in al
push si
mov si,offset emubuf ; matched sequence, cx chars worth
cld
ansmc6: lodsb ; get a char
call pntchr ; print it, ignore errors
loop ansmc6 ; do all matched chars
pop si
pop ax
ansmc7: mov ttstate,offset ansmc ; reset state to the beginning
ret
ansmc endp
pntlin proc near ; print whole line given by dx
push ax
push bx
push cx
push dx
xor ch,ch
mov cl,byte ptr low_rgt ; number of columns
mov dl,cl ; Bios column counter, dh = row
inc cl ; actual line length, count it down
test vtemu.vtflgop,vswdir ; writing right to left?
jnz pntlin2 ; nz = yes, do not trim spaces
pntlin1:call setpos ; set cursor
call getatch ; read char (al) and attribute (ah)
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:call setpos ; set cursor
call getatch ; read char (al) and attribute (ah)
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
; Set cursor coordinate DL (row) with consideration for writing direction.
direction proc near
test vtemu.vtflgop,vswdir ; writing left to right?
jz direct1 ; z = yes, no changes needed
sub dl,byte ptr low_rgt ; right margin column number
neg dl ; make a positive value again
direct1:ret
direction endp
; Erase from cursor (DX, inclusive) to end of screen
; sense double width/height
ereos proc near
mov ax,dx ; erase from cursor to end of screen
or dx,dx ; cursor at home position?
jnz ereos1 ; nz = no
; e = yes, roll screen before clear
push word ptr mar_top
mov al,byte ptr low_rgt+1 ; bottom row number
mov mar_bot,al
mov mar_top,0 ; row of cursor
inc al ; number of lines to scroll
mov scroll,al
call atscru ; scroll them up before erasure
pop word ptr mar_top
; removes double w/h lines too
xor ax,ax ; erase from here (home)
mov bh,byte ptr low_rgt+1 ; bh = bottom row number
mov bl,crt_cols ; bl = physical columns
dec bl ; physical width (to here)
call vtsclr ; clear screen
ret
ereos1: push dx ; save dx
mov bl,dh ; get row number
xor bh,bh
cmp linetype [bx],0 ; single width line?
je ereos2 ; e = yes
shl dl,1 ; physical column is twice logical
ereos2: or dl,dl ; starting at left margin?
je ereos3 ; e = yes, this goes to single width
inc bl ; else start on next line
ereos3: cmp bl,byte ptr low_rgt+1 ; at the end of the screen?
ja ereos4 ; a = yes, stop singling-up
mov byte ptr linetype [bx],0 ; set to single width
inc bx
jmp short ereos3 ; loop, reset lines to end of screen
ereos4: mov bx,low_rgt ; erase from cursor to end of screen
mov bl,crt_cols
dec bl ; do physical screen width
call vtsclr ; clear it
pop dx ; restore dx
ret
ereos endp
; Erase from start of screen to cursor (inclusive), sense double width/height
ersos proc near
xor ax,ax ; erase from start of screen
; to cursor, inclusive
xor bx,bx ; start at top row (0)
ersos1: cmp bl,dh ; check rows from the top down
jae ersos2 ; ae = at or below current line
mov byte ptr linetype [bx],0; set line to single width
inc bx ; inc row
jmp short ersos1 ; look at next line
ersos2: or dl,dl ; at left margin of current line?
jne ersos3 ; ne = no, leave line width intact
mov byte ptr linetype [bx],0 ; convert to single width
ersos3: mov bl,dh ; get row number
xor bh,bh
cmp linetype [bx],0 ; single width line?
je ersos4 ; e = yes
shl dl,1 ; physical column is twice logical
ersos4: mov bx,dx ; cursor position to bx
call vtsclr ; clear it
ret
ersos endp
; Erase in line, from column AL to column BL, in row DH
erinline proc near
mov ah,dh ; set row
mov bh,dh
push bx
mov bl,dh ; get row
xor bh,bh
cmp linetype [bx],0 ; single width line?
pop bx ; pop does not affect flags
je erinli1 ; e = yes
shl bl,1 ; physical column is twice logical
erinli1:call vtsclr ; clear it
ret
erinline endp
; Clear screen from AX to BX, where AH = row, AL = column, ditto for BX.
; This routine accomodates right to left writing. BX >= AX.
vtsclr proc near
test vtemu.vtflgop,vswdir ; writing left to right?
jz vtsclr4 ; z = yes
cmp bh,ah ; same row?
je vtsclr2 ; e = yes
push ax ; multiple lines
push bx ; save both coordinates
mov bl,byte ptr low_rgt ; get right most logical column
mov bh,ah ; pick just top line
call vtsclr2 ; delete fraction of top line
pop bx ; recover ending position
push bx
inc ah ; omit top row, now done
dec bh ; omit last line, could be fractional
cmp bh,ah ; any whole lines remaining to delete?
jb vtsclr1 ; b = no, finish up
mov bl,byte ptr low_rgt ; get right most physical column
xor al,al ; to end of line (on left)
call atsclr ; clear top line and whole remainders
vtsclr1:pop bx ; setup for last line to be cleared
push bx ; get last row again
xor al,al ; start at logical left margin
jmp short vtsclr3 ; ax and bx are already pushed
vtsclr2:push ax ; erase single line, whole or part
push bx
vtsclr3:mov ah,byte ptr low_rgt ; borrow reg ah (same as bh)
sub ah,bl ; reflect right to left
mov bl,ah
or bl,bl ; overflow?
jns vtsclr5 ; ns = no, is ok
xor bl,bl ; limit to logical screen
vtsclr5:mov ah,byte ptr low_rgt
sub ah,al
mov al,ah
jns vtsclr6
mov al,byte ptr low_rgt ; limit to logical screen
vtsclr6:mov ah,bh ; restore ah
xchg al,bl ; reverse to get physical ax < bx
call atsclr ; erase part/all of single line
pop bx
pop ax
ret
; for writing left to right
vtsclr4:jmp atsclr ; do normal erasure and return
vtsclr endp
; routines supporting scrolling and double width/height chars
; scroll has number of lines to scroll
atscru proc near ; scroll screen up one line
push ax ; assumes dx holds cursor position
push bx ; returns with dx = old row, new col
push cx
push si
xor bh,bh
mov bl,mar_top ; top line to move
xor ch,ch
mov cl,scroll ; number of lines to move
mov al,mar_bot ; bottom line to scroll
sub al,bl ; number of lines minus 1
inc al ; number of lines
cmp al,cl ; scrolling region smaller than scroll?
jge atscru1 ; ge = no, is ok
mov scroll,al ; limit to region
cmp al,1 ; at least one line to scroll?
jge atscru1 ; ge = yes
mov scroll,1 ; no, force one
atscru1:mov al,scroll
mov ah,byte ptr low_rgt+1 ; last text line on screen
inc ah ; number of screen lines
cmp al,ah ; exceeds number of lines on screen?
jbe atscru8 ; be = scrolling not more than that
mov al,ah ; limit to screen length
mov scroll,al
atscru8:xor ah,ah
mov si,ax ; scroll interval
mov bl,mar_top
mov cl,mar_bot
sub cl,bl
inc cl ; number of lines in region
sub cl,scroll ; cx = those needing movement
cmp cl,0
jle atscru3
atscru2:mov al,linetype[bx+si] ; get old type
mov linetype[bx],al ; copy to new higher position
inc bx
loop atscru2
atscru3:mov bl,mar_bot ; set fresh lines to single attribute
mov cl,scroll ; number of fresh lines (qty scrolled)
xor ch,ch
atscru4:mov linetype[bx],0
dec bx
loop atscru4 ; clear old bottom lines
mov bl,dh ; get row of cursor
xor bh,bh
cmp linetype[bx],0 ; single width?
je atscru5 ; e = yes
shr dl,1 ; reindex to single width columns
atscru5:pop si
pop cx
pop bx
pop ax
test anspflg,vtcntp ; controller print active?
jz atscru6 ; z = no, ok to change screen
ret ; else keep screen intact
atscru6:jmp vtscru ; call & ret the msy scroll routine
atscru endp
atscrd proc near ; scroll screen down scroll lines
push ax ; assumes dx holds cursor position
push bx ; returns with dx = old row, new col
push cx
push si
xor ch,ch
mov cl,scroll ; number of lines to scroll
xor bh,bh
mov bl,mar_bot ; bottom line to move
mov al,bl
xor ah,ah
sub al,mar_top ; number of lines minus 1
inc al ; number of lines
cmp al,cl ; scrolling region smaller than scroll?
jge atscrd1 ; ge = no, is ok
mov scroll,al ; limit to region
cmp al,1 ; at least one line to scroll?
jge atscrd1 ; ge = yes
mov scroll,1 ; no, force one
atscrd1:mov al,scroll
mov si,ax ; si = scroll
mov bl,dh ; get row of cursor
xor bh,bh ; make into an index
sub bl,scroll ; si + this bx will be new bottom line
mov cl,bl
sub cl,mar_top
inc cl
cmp cl,0
jle atscrd3
atscrd2:mov al,linetype[bx] ; get old line's type
mov linetype[bx+si],al ; copy to new lower position
dec bx
loop atscrd2
atscrd3:mov bl,mar_top ; start with this line
xor bh,bh
mov cl,scroll ; number of lines scrolled
xor ch,ch
atscrd4:mov linetype[bx],0 ; clear new top lines
inc bx
loop atscrd4
mov bl,dh ; get row of cursor
xor bh,bh
cmp linetype[bx],0 ; single width?
je atscrd5 ; e = yes
shr dl,1 ; reindex to single width columns
atscrd5:pop si
pop cx
pop bx
pop ax
test anspflg,vtcntp ; controller print active?
jz atscrd6 ; z = no, ok to change screen
ret ; else keep screen intact
atscrd6:jmp vtscrd ; call & ret the msy scroll routine
atscrd endp
; Returns carry set if column in DL is a tab stop, else carry clear.
; Enter with column number in DL (starts at column 0, max of swidth-1)
; and tabstop buffer offset in SI.
istabs proc near
push bx
push cx
mov cl,dl ; column number (0 to swidth-1)
and cl,00000111b ; keep bit in byte (0-7)
inc cl ; map to 1-8
mov bl,dl ; column
shr bl,1 ; bl / 8 to get byte
shr bl,1
shr bl,1
xor bh,bh ; clear high byte
mov bl,[si+bx] ; get a byte of tab bits
ror bl,cl ; rotate to put tab-set bit into carry
pop cx
pop bx
ret
istabs endp
; Modify (set/clear) a tabstop. Enter with DL holding column (0 to swidth-1)
; Set a tabstop into buffer pointed at by SI.
tabset proc near
mov modeset,1 ; set a tabstop
jmp short modtabs
tabset endp
; Clear a tabstop
tabclr proc near
mov modeset,0 ; clear a tabstop
jmp short modtabs
tabclr endp
; Worker for set/clear tabstop, si has pointer to tabstops array
modtabs:push bx
push cx
mov cl,dl ; column number (0 to swidth-1)
and cl,00000111b ; keep bit in byte (0-7)
mov ch,1 ; tab bit to change
shl ch,cl ; shift to bit-in-byte position
mov bl,dl ; column
shr bl,1 ; bl / 8 to get byte
shr bl,1
shr bl,1
xor bh,bh ; clear high byte
mov cl,[si+bx] ; get byte of tabs bits
not ch ; invert bit marker to create hole
and cl,ch ; clear the tab bit
not ch ; recover setting pattern
cmp modeset,0 ; clear the tab bit?
jz modtab1 ; z = yes
or cl,ch ; set the tab bit
modtab1:mov [si+bx],cl ; store tab byte
pop cx
pop bx
ret
; 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 savflgs,vsdefaults
mov iniflgs,vsdefaults
mov insmod,0 ; turn off insert mode
xor dl,dl ; Column 1 has no tab stop
mov si,vtemu.vttbs ; from the cold-start buffer
call tabclr ; clear that tabstop
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
push es
push ds
pop es
cld
mov al,1 ; set tabs at columns 9, spaced by 8
mov cx,(swidth-1)/8 ; bytes to do, at 8 bits/byte
mov di,offset deftabs+1 ; starting byte for column 9 (1...)
rep stosb
mov cx,slen ; clear linetype array
mov di,offset linetype
rep stosb
pop es
mov vtemu.vttbst,offset tabs ; addrs of active tabs for STATUS
mov vtemu.vttbs,offset deftabs ; addrs of tabs for setup (SET)
call cpytabs ; copy default to active
mov vtemu.att_ptr,offset att_normal ; ptr to video attributes
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
vsinit endp
; Initialization routine.
; Enter with dl = index for baud rate table
; dh = parity in bits 4-7, number of data bits in bits 0-3
ansini proc near
mov ax,vtemu.vtflgst ; setup flags
mov vtemu.vtflgop,ax
mov iniflgs,ax
mov savflgs,ax
mov al,flags.vtflg ; get current terminal type
mov oldterm,al ; remember it here for soft restarts
mov anspflg,0 ; clear printing flag
mov al,byte ptr low_rgt ; right most column (counted from 0)
sub al,8 ; place marker 9 columns from margin
mov belcol,al ; store column number to ring bell
cmp dl,lbaudtab ; out of range index?
jb ansin1 ; b = no, 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
shr dh,cl ; isolate parity code
cmp dh,lpartab ; out of range code?
jb ansin2 ; b = no, store it
mov dh,lpartab-1 ; make it the maximum
ansin2: mov parcode,dh ; save
mov cl,crt_cols ; physical screen number columns (80)
dec cl ; we count from column 0 here
mov ch,crt_lins ; physical screen number rows-1 (24)
dec ch ; we count from row 0 here
mov low_rgt,cx ; save as active text screen size
mov oldscrn,cx ; remember old screen dimensions
jmp atreset ; reset everything
ansini endp
atxreset proc near ; Reset via host command
cmp nparam,0 ; need no Parameters, no Intermediates
jne atxres1 ; ne = not a reset
cmp ninter,0
je atreset ; e = none, it is a reset
atxres1:ret ; ignore command
atxreset endp
atreset proc near ; Reset-everything routine
mov cursor,0 ; cursor is at 0,0
mov al,1 ; assume underline cursor
test vtemu.vtflgst,vscursor ; kind of cursor in setup
jnz atres0 ; nz = underline
dec al ; else say block
atres0: mov atctype,al ; VTxxx cursor type
mov h19cur,0 ; Heath-19 saved cursor
mov dspstate,0 ; saved modeline state
call udkclear ; clear User Definable Key contents
push vtemu.vtflgst ; setup flags
pop vtemu.vtflgop ; operational flags
and vtemu.vtflgop,not vscntl ; assume no 8-bit controls
mov al,oldterm ; get terminal at entry time
mov flags.vtflg,al ; use it again
cmp flags.vtflg,ttvt100 ; VT100?
je atres1 ; e = yes, turn on ansi mode
cmp flags.vtflg,ttvt320 ; VT320?
jne atres1a ; ne = no, no ansi, no 8-bit controls
test vtemu.vtflgst,vscntl ; want 8-bit controls?
jz atres1 ; z = no
or vtemu.vtflgop,vscntl ; turn on 8-bit controls
atres1: or vtemu.vtflgop,decanm ; turn on ANSI mode
atres1a:mov mar_top,0 ; reset scrolling region
mov al,byte ptr low_rgt+1
mov mar_bot,al
mov cx,4 ; initialize the "LEDs"
mov al,led_off ; turn off all of them
mov di,offset ansleds+6 ; point to the "LEDs"
push es ; save es
push ds
pop es ; use data segment for es:di below
cld ; set forward direction
rep stosb
pop es
call ansdsl ; update mode line
call cpytabs ; initialize tab stops
cmp flags.vtflg,ttvt320 ; VT320?
je atres1b ; e = yes
cmp flags.vtflg,ttvt100 ; VT102?
jne atres1c ; ne = no
atres1b:mov al,vtemu.vtchset ; setup char set
cmp al,1 ; in range for NRCs?
jb atres1c ; b = no
cmp al,12 ; highest NRC ident?
ja atres1c ; a = not NRC
or vtemu.vtflgop,vsnrcm ; set NRC flag bit to activate NRCs
atres1c:mov vtemu.vtchop,al ; remember char set
call chrdef ; set default character sets
call vtbell ; ring bell like VT100
cmp flags.modflg,2 ; mode line owned by host?
jne atres2 ; ne = no
mov flags.modflg,1 ; say now owned by us
; ATRES2 used in 80/132 col resetting
ATRES2: mov cx,slen ; typically 24 but do max lines
mov di,0
atres3: mov linetype[di],0 ; clear the linetype array to single
inc di ; width/height characters
loop atres3
mov ah,att_normal ; get present normal coloring
call clrbold ; clear attributes
call clrblink
call clrunder
mov scbattr,ah ; set background attributes
mov curattr,ah ; and cursor attributes
test vtemu.vtflgop,vsscreen ; want reverse video?
jz atres4 ; z = no
call atrss2 ; reverse screen and attributes (ah)
atres4: mov video_state,0 ; say normal per char video
xor ax,ax ; starting location
mov bh,crt_lins ; number or rows on screen
dec bh ; count from 0
mov bl,crt_cols ; number of columns on screen
dec bl ; count from 0
call atsclr ; clear the whole screen
mov dx,cursor ; get cursor
call atscu5 ; set cursor
call atsctyp ; set right cursor type
cmp flags.modflg,1 ; mode line on and owned by us?
jne atres5 ; ne = no, leave it alone
test yflags,modoff ; mode line supposed to be off?
jnz atres5 ; nz = yes
push dx
call modlin ; write normal mode line
pop dx
atres5: call atpclr ; clear parser work area
mov parstate,0 ; reset parser
mov emubufc,0 ; clear work buffer
mov atwrap,0 ; clear wrap flag
mov SSptr,0 ; clear single shift flag
mov insmod,0 ; reset insert mode
mov h19stat,0 ; clear heath extended status byte
mov h19ctyp,1 ; Heath-19 cursor to underline
mov anspflg,0 ; clear printer flag
call atsc ; save cursor information
mov ttstate,offset atnrm ; normal state
ret
atreset endp
; Re-initialization routine. Called when Term was called but screen was
; restored from a previously saved screen, etc.
ansrei proc near
call atsctyp ; set cursor type [rbv]
call getpos ; get cursor position from msy
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
test vtemu.vtflgop,deccol ; want 80 columns?
jnz ansre2 ; nz = 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 direction ; cursor to writing direction column
mov cursor,dx ; store as logical position
push cx ; save current physical screen size
call stblmds ; check settable modes, set flags
pop cx
cmp cx,oldscrn ; has screen size changed?
je ansre3 ; e = no, same as last time
mov oldscrn,cx ; remember new size
mov mar_top,0 ; reset scrolling region
mov al,byte ptr low_rgt+1
mov mar_bot,al
jmp atres2 ; better do soft reset
ansre3: ret
ansrei endp
; This routine checks to see whether any of the settable modes have changed
; (things that can be changed in both SETUP and by host commands), and
; changes those that need to be changed. TMPFLAGS has the new VT100 setup
; flags, VTFLAGS has the old. This routine also updates VTFLAGS.
; Revised by [jrd] to allow MSY to reset scbattr when not in connect mode,
; to do "soft reset" if terminal type has changed, and to do a screen clear
; reset if the actual screen colors have changed.
stblmds proc near
mov al,flags.vtflg ; get current terminal type
cmp al,oldterm ; same as before?
je stblm10 ; e = yes, skip over soft reset
mov oldterm,al ; remember current terminal type
mov insmod,0 ; reset insert mode flag
and iniflgs,not vsnrcm ; turn off NRC bit from last time
mov mar_top,0 ; reset top scrolling margin
mov al,byte ptr low_rgt+1 ; and scrolling margin
mov mar_bot,al ; to last normal line on screen
mov ah,byte ptr low_rgt ; right most column (counted from 0)
sub ah,8 ; place marker 9 columns from margin
mov belcol,ah ; store column number to ring bell
;;;; and ansflgs,decckm+deckpam+decom+dececho+vscntl ; 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
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
cmp flags.vtflg,ttvt320 ; VT320?
je stblm0b ; e = yes
cmp flags.vtflg,ttvt100 ; VT100 now?
jne stblm10 ; ne = no
stblm0b:or vtemu.vtflgop,decanm ; set ansi flag bit
stblm10:mov al,vtemu.vtchset ; setup character set
cmp al,vtemu.vtchop ; operational character set
je stblm3 ; e = same, no changes needed
mov vtemu.vtchop,al ; remember this set
and vtemu.vtflgop,not vsnrcm ; clear NRC active bit
and vtemu.vtflgst,not vsnrcm
cmp al,1 ; in range for NRC?
jb stblm11 ; b = no
cmp al,12 ; above NRCs?
ja stblm11 ; a = yes
or vtemu.vtflgop,vsnrcm ; set NRC active bit
or vtemu.vtflgst,vsnrcm
and vtemu.vtflgop,not vscntl ; no 8-bit controls
stblm11:call chrdef ; init char sets
stblm3: cmp vtclear,1 ; screen need updating?
jb stblm9 ; b = no
ja stblm3a ; 2 or more means do a reset
mov ah,att_normal ; 1, get new normal attributes setting
mov scbattr,ah ; store new values
mov curattr,ah
jmp short stblm9
stblm3a:mov cursor,0 ; reset cursor position
jmp atres2 ; go to semi-reset
; check on screen normal/reversed
stblm9: mov ax,iniflgs ; flags at last entry
xor ax,vtemu.vtflgst ; find which setup ones have changed
test ax,vsscreen ; screen background?
jz stblm8 ; z = no, don't touch it
test vtemu.vtflgop,vsscreen ; reverse video flag set?
jnz stblm5 ; nz = yes, do it
and vtemu.vtflgop,not vsscreen ; cleared (normal video)
jmp short stblm6 ; reverse everything
stblm5: or vtemu.vtflgop,vsscreen ; set (reverse video)
stblm6: call atrss2 ; reverse screen and cursor attribute
mov ah,scbattr ; reset saved attribute also
mov savecu+svattr_index,ah
stblm8: cmp flags.modflg,2 ; mode line enabled and owned by host?
je stblm9a ; e = yes, leave it alone
call clrmod ; clear the mode line
test yflags,modoff ; mode line supposed to be off?
jnz stblm9a ; nz = yes
call modlin ; write normal mode line
and yflags,not modoff ; say modeline is not toggled off
stblm9a:mov dx,cursor ; logical cursor
push dx
call direction ; set cursor for writing direction
call setpos ; set the cursor physical position
pop dx
push vtemu.vtflgst
pop iniflgs ; remember setup flags at this entry
ret
stblmds endp
; Routine called when something is typed on the keyboard
anskbi proc near
mov ttkbi,0FFH ; just set a flag
ret
anskbi endp
; This routine copies the new tab stops when they have changed.
; Copies all 132 columns.
cpytabs proc near
mov cx,(swidth+7)/8 ; number of bytes in screen width
jcxz cpytab1 ; z = none to do
mov si,offset deftabs ; source is setup array
mov di,offset tabs ; destination is active array
push es ; save es
push ds
pop es ; set es to data segment
cld
rep movsb ; do the copy
pop es ; recover es
cpytab1:ret
cpytabs endp
; Routine to toggle VT100/VT52/Heath-19 modes. No arguments.
; Use & update global byte flags.vtflg for terminal type and update local
; bit decanm. Note: shifting to Heath-19 here does Not reset the scrolling
; margins mar_top & mar_bot nor reset the double char linetype array.
ans52t proc near
cmp tekflg,0 ; in Tek sub mode?
je ans52h ; e = no
jmp ans52e ; yes, get out now
ans52h: cmp flags.vtflg,ttvt320 ; in VT320 mode?
jne ans52a ; ne = no
or vtemu.vtflgop,decanm ; set ansi mode
mov flags.vtflg,ttvt100 ; say VT100 now
mov oldterm,ttvt100 ; and remember it
jmp ans52g
ans52a: cmp flags.vtflg,ttvt100 ; in VT100 mode?
jne ans52b ; ne = no
and vtemu.vtflgop,not decanm ; reset ansi mode
mov flags.vtflg,ttvt52 ; say VT52 now (clears ansi bit)
mov oldterm,ttvt52 ; and remember it
jmp ans52g
ans52b: cmp flags.vtflg,ttvt52 ; in VT52 mode?
jne ans52c ; ne = no
cmp dspstate,dsptype ; on status line?
jz ans52b1 ; z = no
push param ; save these two fellows
mov ah,inter
push ax
mov param,0 ; setup call to atsasd
mov inter,'$'
call atsasd ; get back to main display screen
pop ax
pop param ; recover parsing parameters
mov inter,ah
ans52b1:mov flags.vtflg,ttheath ; say Heath-19 now
mov oldterm,ttheath
jmp ans52g
ans52c: cmp flags.vtflg,ttheath ; in Heath-19 mode?
jne ans52e ; ne = no
test denyflg,tekxflg ; is Tek mode disabled?
jz ans52d ; z = no, enabled
mov flags.vtflg,ttvt320 ; say VT320 now
mov oldterm,ttvt320
or vtemu.vtflgop,decanm ; set, go to VT320 mode
jmp short ans52f ; end Tek mode
ans52d: call atsc ; save cursor and associated data
mov flags.vtflg,tttek ; set Tek mode
mov tekflg,0 ; not a sub mode
call tekini ; init Tek to switch screens
jmp atnorm ; normal state and return
ans52e: cmp flags.vtflg,tttek ; in Tek mode now?
je ans52f ; e = yes
cmp tekflg,0 ; doing Tek sub mode?
jne ans52f ; ne = yes
jmp atnorm ; else ignore this call
ans52f: call tekend ; exit Tek graphics mode
mov flags.vtflg,ttvt320 ; say VT320 now
mov oldterm,ttvt320
or vtemu.vtflgop,decanm ; set, go to VT320 mode
call atrc ; restore cursor etc
cmp flags.modflg,0 ; is mode line disabled?
je ans52g ; e = yes, disabled
test yflags,modoff ; Mode line off?
jnz ans52g ; nz = yes, return
ans52g: call atsc ; save cursor etc
call ansdsl ; remove or redisplay "LEDs"
jmp atnorm ; set state to "normal" and return
ans52t endp
; Display "LEDs" routine. yflags from MSYIBM is needed to know if the mode
; line is enabled. Display current state of "LEDs" on line 25.
ansdsl proc near ; display "LEDs"
test yflags,modoff ; mode line off?
jnz ansdsl2 ; nz = yes, just return
cmp flags.modflg,1 ; mode line on and owned by us?
jne ansdsl2 ; ne = no, leave it intact
mov dh,byte ptr low_rgt+1 ; last screen line - 1
inc dh ; status line
mov dl,led_col ; column for led display
call setpos ; set cursor position at (slen-1),70
mov cx,10 ; length of byte array is ten
cld
mov si,offset v32leds ; VT320 ident
cmp flags.vtflg,ttvt320 ; VT320?
je ansdsl1 ; e = yes
mov si,offset ansleds ; VT102 ident
cmp flags.vtflg,ttvt100 ; VT100 mode?
je ansdsl1 ; e = yes
mov si,offset v52leds ; VT52 ident
cmp flags.vtflg,ttvt52 ; VT52?
je ansdsl1 ; e = yes
mov si,offset h19leds ; Heath-19 ident
ansdsl1:lodsb ; get a character
call putchar ; write character, increment cursor
loop ansdsl1 ; loop for all chars
mov dx,cursor ; reposition cursor when finished
push dx
call direction ; set dx to desired position
call setpos ; set cursor position
pop dx
ansdsl2:ret
ansdsl endp
; 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.
atccic proc near
push cx
mov cl,byte ptr low_rgt ; get right margin
mov bl,dh ; get row
xor bh,bh
cmp bl,crt_lins ; below screen?
jae atcci0 ; ae = 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 ; left of left margin? (wide screen)
jb atcci1 ; b = no, go check right
xor dl,dl ; set to left margin
atcci1: cmp dl,cl ; right of right margin
jbe atcci2 ; be = yes, go check top
mov dl,cl ; set to right margin
atcci2: pop cx
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 atcci5 ; ge = no
mov scroll,1
mov ax,offset atscrd ; indicate scroll down required
mov dh,mar_top ; set to top margin
jmp atcci7
atcci5: cmp bh,mar_bot ; was old position at bottom margin?
jne atcci7 ; ne = no, so don't trap cursor
cmp dh,mar_bot ; want to go below?
jb atcci7 ; b = no, nothing to worry about
mov scroll,1 ; 1 line
mov ax,offset atscru ; indicate scroll up required
mov dh,mar_bot ; set to bottom margin
ret
atcci7: jmp atccpc ; old pos was outside scrolling region
atccic endp
; 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 proc near
push bx ; save bx and cx
push cx
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
xor dl,dl ; set to left margin
atccp1: cmp dl,cl ; to right of right margin?
jbe atccp2 ; be = yes, go check top
mov dl,cl ; set to right margin
atccp2: pop cx
pop bx
test vtemu.vtflgop,decom ; Origin mode set?
jnz atccp5 ; nz = yes, stay in scrolling region
cmp dh,0 ; above top of screen?
jge atccp3 ; ge = no, check bottom
xor dh,dh ; 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 ; stop at bottom margin
cmp flags.vtflg,ttheath ; Heath-19 mode?
jne atccp4 ; ne = no
test h19stat,h19l25 ; 25th line enabled?
jz atccp4 ; z = no
inc dh ; allow 25th line
atccp4: 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
ret
atccpc endp
; Select Active Display. When selecting the status line make new scrolling
; margins be just the status line and force on Origin mode. Save the regular
; margins and origin mode for restoration when regular display is re-selected.
atsasd proc near
cmp inter,'$' ; correct intermediate?
jne atsasd1 ; ne = no
cmp param,1 ; select which display
jb atsasd4 ; b = select main display
ja atsasd1 ; a = illegal value
cmp flags.modflg,2 ; mode line host owned?
jne atsasd1 ; ne = no, ignore command
test dspstate,dsptype ; was previous display = status line?
jz atsasd2 ; z = no
atsasd1:ret ; else do nothing
atsasd2:push word ptr mar_top ; save scrolling margins
pop dspmsave ; save scrolling margins
or dspstate,dsptype ; say status line is active
mov al,byte ptr low_rgt+1 ; get last text line
inc al ; status line
mov mar_top,al
mov mar_bot,al ; new scrolling margins
and dspstate,not dspdecom ; clear remembered origin mode
test vtemu.vtflgop,decom ; was origin mode active?
jz atsasd3 ; z = no
or dspstate,dspdecom ; remember origin mode was active
atsasd3:or vtemu.vtflgop,decom ; set origin mode
push cursor ; get current main display cursor
pop dspcmain ; save it
mov dx,dspcstat ; get status line cursor
mov dh,mar_top ; set row
jmp atscu5 ; set cursor
atsasd4:test dspstate,dsptype ; was previous display = status line?
jnz atsasd5 ; nz = yes
ret ; else do nothing
atsasd5:push dspmsave ; restore scrolling margins
pop word ptr mar_top
and vtemu.vtflgop,not decom ; clear origin mode bit
test dspstate,dspdecom ; was origin mode on for main screen?
jz atsasd6 ; z = no
or vtemu.vtflgop,decom ; set it now
atsasd6:push cursor ; get status line cursor position
pop dspcstat ; save it
mov dx,dspcmain ; get saved cursor position
mov dspstate,0 ; say now doing main screen
jmp atscu5 ; set cursor
atsasd endp
atssdt proc near ; Select Status Line Type, DECSSDT
cmp inter,'$' ; correct intermediate char?
je atssdt1 ; e = yes
ret
atssdt1:test dspstate,dsptype ; on mode line already?
jnz atssdt4 ; nz = yes, cannot reselect now
cmp param,0 ; turn off status line?
jne atssdt2 ; ne = no
push dx ; save cursor position
call clrmod ; clear the line
pop dx
or yflags,modoff ; now say it's off
mov flags.modflg,1 ; say mode line is owned by us
ret
atssdt2:cmp param,1 ; regular status line?
jne atssdt3
push dx
call modlin ; turn on regular mode line
pop dx
and yflags,not modoff ; and say it's on
mov flags.modflg,1 ; say mode line is owned by us
ret
atssdt3:cmp param,2 ; host writable?
jne atssdt4 ; ne = no
mov flags.modflg,2 ; say mode line is owned by host
atssdt4:ret
atssdt endp
; Routine to set cursor type (off, block, underline).
atsctyp:cmp flags.vtflg,ttheath ; Heath-19?
jne atsct1 ; ne = no
mov al,h19ctyp ; get cursor kind and on/off bit
test al,4 ; is cursor to be off?
jz atsct4 ; z = no, al has kind
xor al,al ; turn off cursor
jmp short atsct4 ; do it
atsct1: test atctype,4 ; VTxxx cursor type, off?
jz atsct2 ; z = no
xor al,al
jmp short atsct4 ; turn it off
atsct2: mov al,1 ; assume underline
test vtemu.vtflgop,vscursor ; block?
jnz atsct3 ; nz = no, underline
mov al,2
atsct3: mov atctype,al ; save VTxxx cursor type here
atsct4: call csrtype ; set the cursor type
ret
atdeb proc near ; Debug, display all chars in tty style
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 bl,curattr ; save attribute
push bx
push word ptr mar_top ; save limited scrolling region
push ax ; save character for a second
mov ah,curattr ; get attribute
call clrblink ; clear blink attribute
call clrunder ; clear underline attribute
mov curattr,ah ; store
or vtemu.vtflgop,decawm ; set autowrap temporarily
mov mar_top,0 ; set scrolling region to entire page
mov al,byte ptr low_rgt+1
mov mar_bot,al
pop ax ; restore character
test al,80h ; high bit set?
jz atdeb0 ; z = not set
push ax ; save the character for a second
mov al,7eh ; output a tilde
call atnrm2
pop ax ; restore character
and al,7fh ; and remove high bit
atdeb0: cmp al,del ; DELETE?
je atdeb1 ; e = yes, output "^?"
cmp al,20h ; control character?
jnb atdeb2 ; nb = no, just output char in al
atdeb1: push ax ; save the character for a second
mov al,5eh ; output a caret
call atnrm2
pop ax ; restore character
add al,40h ; make ^letter (or ^? for DELETE)
and al,7fh ; clear bit 7 (for DELETE)
atdeb2: call atnrm2 ; output translated character
pop word ptr mar_top ; restore scrolling region,
pop bx ; flags, and cursor attribute
mov curattr,bl
ret
atdeb endp
code ends
end