home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
msr313src.zip
/
mszibm.asm
< prev
next >
Wrap
Assembly Source File
|
1993-07-12
|
294KB
|
9,030 lines
NAME mszibm
; File MSZIBM.ASM
include mssdef.h
; Copyright (C) 1982,1993, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or
; institution to use, copy, or redistribute this software as long as
; it is not sold for profit and this copyright notice is retained.
;
; Terminal emulator module for IBM PC's and compatibles. Emulates Heath-19,
; VT52, VT102, and VT320, Honeywell VIP7809, Prime PT200, DG D463, and D470.
; 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
; 8 July 1993 version 3.13
; 6 Sept 1991 version 3.11
; Last edit 7 July 1993
; 6 Feb 1993 Add DG 470 color terminal.
; 6 Jan 1993. Add CSI ? 35 h/l as DEC macro to shift keyboard maps. In Kermit
; these invoke new macro names KEYBOARDS and KEYBOARDR, respectively. From
; Shalom Mitz, shmitz@coma.huji.ac.il.
; April 1992 Add Data General D463 terminal emulation.
; 7 Sept 1992 Add small extra code from htb to more fully emulate Prime PT200
; 20 July 1990 Include terminal type of VT100 as the same as VT102 but with
; a different ident response. Also include terminal type of HONEYWELL VIP7809
; as a VT100 with a VT100 ident response, with a canned response to ENQ, and
; another to ESC y. Honeywell material is from Frank Dreano,
; dreano@trout.nosc.mil.
; 29 May 1989 Rewrite and expand to DEC VT320 level.
; 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.
; Procedure direction accomdates 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.
; 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, tekflg
public mar_top, mar_bot, anspflg, scroll, cursor, curattr
public dnparam, dparam, dlparam, dninter, dinter, emubufc, emubuf
public emubufl, dcsstrf, upss, MNlatin
public GRptr, G0set, G1set, G2set, G3set
public savezlen, savezoff, blinkdis, protectena, dghscrdis
public linescroll, xltkey, dgkbl, dgwindcomp, atctype, dgcross
public dgnctoggle, apcstring
;
; DEC and VT are trademarks of Digital Equipment Corporation.
;
; Description of the global entry points and calls on external routines
; needed by this emulator.
;
; 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 word "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.
;
; Startup in D463/D470 mode:
; GL = G0 = ASCII
; GR = G1 = Data General International if using 8-bit characters, else
; GR = G1 = Data General Word Processing.
;
; 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
; "VT330/340 Programmer Ref Manual", 2nd ed, May 1988,
; Vol 1: Text programming DEC # EK-VT3XX-TP-002
; Vol 2: Graphics programming DEC # EK-VT3XX-GP-002
; "Programming the Display Terminal: Models D217, D413, and D463", Data
; General Corp, 014-00211-00, 1991.
; "Installing and Operating Your D216E+, D217, D413, and D463 Display
; Terminals", Data General Corp, 014-002057-01, 1991.
; "Dasher D470C Color Display Terminal, Programmer's Reference Manual",
; Data General Corp, 014-001015, 1984.
; ---------------------------------------------------------------------------
vswidth equ 207 ; cross correlate with msyibm
swidth equ 207 ; 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)
att_bold equ 08h ; bold in main video word
att_blink equ 80h ; blinking in main video word
att_protect equ 01h ; protected in vsatt
att_uline equ 02h ; underscored in vsatt
att_rev equ 04h ; reversed video in vsatt
braceop equ 7bh ; opening curly brace
bracecl equ 7dh ; closing curly brace
; 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)
;vshscroll equ 4000h ; horiz scroll (0=auto, 1=manual)
;vscompress equ 8000h ; compressed text(0=graphics,1=132col)
;vsdefaults equ 0+vscursor
; Kinds of terminals available
;ttgenrc equ 0 ; no emulation done by Kermit
;ttheath equ 1 ; Heath-19
;ttvt52 equ 2 ; VT52
;ttvt100 equ 4 ; VT100
;ttvt102 equ 8 ; VT102
;ttvt220 equ 10h ; VT220
;ttvt320 equ 20h ; VT320
;tttek equ 40h ; Tektronix 4010
;tthoney equ 80h ; Honeywell VIP7809
;ttpt200 equ 100h ; Prime PT200
;ttd463 equ 200h ; Data General D463
;ttd470 equ 400h ; Data General D440
;TTTYPES equ 12 ; Number of terminal types defined
;; tekflg bits in byte
;tek_active equ 1 ; actively in graphics mode
;tek_tek equ 2 ; Tek terminal
;tek_dec equ 4 ; Tek submode of DEC terminals
;tek_sg equ 8 ; special graphics mode
;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
extrn vtemu:byte, scbattr:byte, flags:byte, yflags:byte
extrn crt_lins:byte, rxtable:byte, denyflg:word, low_rgt:word
extrn vtclear:byte, dosnum:word, chcontrol:byte, apcenable:byte
extrn parstate:word, pardone:word, parfail:word, nparam:word
extrn param:word, lparam:byte, ninter:word, inter:byte, ttyact:byte
extrn L1cp437:byte, L1cp850:byte, L1cp860:byte, L1cp863:byte
extrn L1cp865:byte, modbuf:byte, extattr:byte, rdbuf:byte
extrn vtenqenable:byte, vtcpage:word
even ; C0 7-bit control code table
ansc0 dw 5 dup (atign) ; NUL, SOH, STX, ETX, EOT
dw atenq,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, atnrm, 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 atign,atign,protena,protdis,atign ; CCH, MW, SPA, EPA,ignore
dw atign,atign,atcsi,atgotst,atdcsnul; ignore 2, CSI, ST, OSC
dw atdcsnul, atapc ; 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, atri0, 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, atri0, ated, atel ; 'GHIJK'
dw v52pl, v52pcb, v52pce, v52pos, decid ; 'VWXYZ'
dw v52ps, v52pcb, v52pce ; ']^_'
; Prime PT200 escape follower table
pt200esc db 38 ; number of entries
dw p20ejt ; address of action routines
db '01234','5678<', '=>?AB', 'DEFGH', 'JMNOP'
db 'Z[\]',5eh ; 5eh = caret
db 5fh,'cno',7bh ; 5fh=underscore, 7bh=left curly brace
db 7ch,7dh,7eh ; 7ch=vert bar, 7dh=right curly brace, 7eh=tilde
; Dispatch for p20esc
even
p20ejt dw atdgf0, atdgf1, atdgf0, atsdhl, atsdhl ; '01234'
dw 4 dup (atsdhl), atdgfu ; '5678<'
dw atkpam, atnorm, p20ed, atdgfA, atdgfB ; '=>?AB'
dw atind, atnel, ats7c, ats8c, athts ; 'DEFGH'
dw ated, atri, atss2, atss3, atdcs ; 'JMNOP'
dw decid, atcsi, atgotst, 2 dup(atdcsnul) ; 'Z[\]^'
dw atdcsnul, atxreset,atls2, atls3, atpriv ; '_cno{'
dw atls3r, atls2r, atls1r ; '|}~'
; VT320/VT102/VT100/Honewell ANSI mode escape follower table
ansesc db 49 ; number of entries
dw ansejt ; address of action routines
db '01234','56789','<=>?A','BCDEF','GHKLMN','OPQRV'
db 'WYZ[\',']',5eh,5fh ; 5eh = caret, 5fh=underscore
db 60h,'c','fgno',7bh ; 7bh=left curly brace, 7ch=vert bar
db 7ch,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), atdgnrc ; '56789'
dw atdgfu,atkpam, atdgft, atdgfq, atdgfA ; '<=>?A'
dw atdgfB,atdgnrc, atind0, atnel0,ats7c ; 'BCDEF'
dw ats8c, athts0, atdgnrc, atdgnrc,atri0, atss2 ; 'GHKLMN'
dw atss3, atdcs0, atdgnrc, atdgnrc,protena ; 'OPQRV'
dw protdis,decid, atdgnrc, atcsi0, atgotst0 ; 'WYZ[\'
dw 2 dup (atdcsnul0),atapc, athoncls, atxreset ; ']^_`c'
dw atdgnrc,atdgnrc,atls2,atls3, atpriv ; 'fgno{'
dw atls3r, atls2r, atls1r ; '|}~'
; Final char table for VT320/VT102/VT100/Honeywell ANSI control sequences
anstab db 38 ; number of entries
dw ansjmp ; address of action routines
db '@ABCD','EFGHI','JKLMP', 'Xacde','fghil','mnpqr','uwxyz'
db 7ch,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 atech, atcuf, atda, atcva, atcud ; 'Xacde'
dw atcup, attbc, atsm, ansprt, atrm ; 'fghil'
dw atsgr, atdsr, decscl, decsca, atstbm ; 'mnpqr'
dw atrqtsr,atrqpsr,atreqt, atctst, atxreset ; 'uwxyz'
dw atscpp, atsasd, atssdt ; '|}~'
; 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
; Data General D463/D470 terminal section
dgescape equ 1eh ; DG escape char (RS)
even ; DG C0 7-bit control code table
dgc0 dw atign,dgprtfm,dgrevidoff,dgblkena,dgblkdis;NUL,SOH,STX,ETX,EOT
dw dgrwa,atign,vtbell,dgwinhome,atign ; ENQ, ACK, BEL, BS, HT
dw dglf, dgeol, dgewin, dgcr,dgblkon ; LF, VT, FF, CR, SO
dw dgblkoff,dgwwa,dgprtwn,dgrollena,dgrolldis ;SI,DLE,DC1,DC2,DC3
dw dguson,dgusoff,dgrevidon,dgcuu,dgcuf ; DC4, NAK, SYN, ETB, CAN
dw dgcub, dgcud,dgansi,dgdimon,dgdimoff ; EM, SUB, ESC, FS, GS
dw dgesc, atign ; RS, US
; DG D463/D470 DG-escape (RS) follower table
dgesctab db 17 ; number of entries
dw dgejt ; address of action routines
db 'ABCDE','FGHIJ','KLMNO','PR'
; Dispatch for dgesctab table
even
dgejt dw dgsfc, dgsbc, dgrmid, dgrevidon, dgrevidoff ; 'ABCDE'
dw dgFSERIES, dgGSERIES, dgscrup, dgscrdn, inschr ; 'FGHIJ'
dw dgdelc, dggline, atign, atls1, atls0 ; 'KLMNO'
dw dgunix, dgRSERIES ; 'PR'
fltable db 60 ; RS F letter dispatch table
dw faction ; table of action routines
db '789;<', '>?ABC', 'DEFGH', 'IJKLM', 'NOPQR'
db 'STUVW', 'XYZ[\', ']^_`a', 'bcdef', 'hikmq'
db 'rstvw', 'xz{}~'
; Dispatch for fltable table
even
faction dw dgign2n, atign, dggrid, atign, atign ; '789;<'
dw dgalign, dgprt, atreset, dgsetw, dgsleft ; '>?ABC'
dw dgsright, dgescn, dgeeos, dgshome, dginsl ; 'DEFGH'
dw dgdell, dgnarrow, dgwide, dgpton, dgptoff ; 'IJKLM'
dw dgchatr, dgrhso, dgwsa, dgsct, dgdefch ; 'NOPQR'
dw dgscs, dgign1n, dg78bit, protena, protdis ; 'STUVW'
dw dgsetmar, dgsetamar, dgrnmar, dgilbm, dgdlbm ; 'XYZ[\'
dw dghsdis, dghsena, dgshcol, dgprt3a, atign ; ']^_`a'
dw dgrsa, dgscmap, dgrchr, dgresch, dgskl ; 'bcdef'
dw atign, atign, atnorm, atnorm, dgdcs ; 'hikmq'
dw dgsclk, dgign1n, dgrss, dgrwc, dgrnmod ; 'rstvw'
dw dgppb, dgs25l, dgsmid, dgnscur, dgign2n ; 'xz{}~'
gltable db 14 ; RS G letter dispatch table
dw gaction ; table of action routines
db '018:>','?@ABC','HInp'
; Dispatch for gltable table
even
gaction dw dggarc, dggbar, dggline, dggpoly, dggcloc ; '018:>'
dw dggrcl, dggcatt, dggcrst, dggcon, dggcoff ; '?@ABC'
dw dggctrk, atnorm, atnorm, dggsetp ; 'HInp'
rltable db 6 ; Data General D463/D470 RS R series
dw raction
db '@ABCD','E'
; Dispatch for rltable table
raction dw dgign2n, dgsps, dgsfield, dgspage, dgsdo ; '@ABCD'
dw dgdhdw ; 'E'
;; Notes on char set idents
; Kermit ident size ident comment designator
; 0 94 'B',0 ASCII "B"
; 1 94 'A',0 British NRC "A"
; 2 94 '4',0 Dutch NRC "4"
; 3 94 '5',0 Finnish NRC (also "C") "5"
; 4 94 'R',0 French NRC (also "f") "R"
; 5 94 '9',0 French Canadian NRC "9"
; 6 94 'K',0 German NRC "K"
; 7 94 'Y',0 Italian NRC "Y"
; 8 94 '`',0 Norwegian/Danish NRC "`"
; 9 94 '%','6' Portugese NRC ("L","g") "%6"
; 10 94 'Z',0 Spanish NRC "Z"
; 11 94 '7',0 Swedish NRC "7"
; 12 94 '=',0 Swiss NRC "="
; 13 94 '=','%' DEC Hebrew NRC "=%'
; 14 94 '1',0 Alt-ROM "1"
; 15 96 '?',0 Transparent "?"
; 16 96 'A',0 Latin1 "A"
; 17 94 '%','5' DEC Multinat (Sup Gr) "%5"
; 18 94 '>',0 DEC Technical ">"
; 19 94 '0',0 DEC-Special "0","2"
; 20 94 'D','I' DG International "DI"
; 21 94 'D','L' DG Line Drawing "DL"
; 22 94 'D','W' DG Word Processing "DW"
; 23 96 'B',0 Latin2 "B"
; 24 96 'H',0 Hebrew-ISO "H"
; 25 94 '"','4' DEC Hebrew ""4"
; 100 94 'D','U' DG soft set filler "DU"
;; End of notes
; 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)
; Data General Line Drawing Character Set, based on CP437, starting in 10/0
dgldc db 20h,0dah,0bfh,0c0h,0d9h,0c2h,0b4h,0c3h ; 2/0
db 0c1h,0c5h,0b3h,0c4h,0c2h,0b4h,0c3h,0c1h
db 0b3h,0c9h,0bbh,0c8h,0bch,0cbh,0b9h,0cch ; 3/0
db 0cah,0ceh,0bah,0cdh,0c4h,0f6h,9bh,3fh
db 3fh,3fh,3fh ; 4/0
dgldclen equ ($-dgldc)
; 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, referenced to Latin1
nrclat 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 0a3h,40h,5bh,5ch,5dh,5eh ; 1, British, "A"
db 5fh,60h,7bh,7ch,7dh,7eh
db 94,'A',0
db 0a3h,0beh,0ffh,0bdh,7ch,5eh ; 2, Dutch, "4"
db 5fh,60h,0a8h,66h,0bch,0b4h
db 94,'4',0
db 23h,40h,0c4h,0d6h,0c5h,0dch ; 3, Finnish, "5"
db 5fh,0e9h,0e4h,0f6h,0e5h,0fch
db 94,'5',0
db 0a3h,0e0h,0b0h,0e7h,0a7h,5eh ; 4, French, "R"
db 5fh,60h,0e9h,0f9h,0e8h,0fbh
db 94,'R',0
db 23h,0e0h,0e2h,0e7h,0eah,0eeh ; 5, French Canadian, "9"
db 5fh,0f4h,0e9h,0f9h,0e8h,0f8h
db 94,'9',0
db 23h,0a7h,0c4h,0d6h,0dch,5eh ; 6, German, "K"
db 5fh,60h,0e4h,0f6h,0fch,0dfh
db 94,'K',0
db 0a3h,0a7h,0b0h,0e7h,0e9h,5eh ; 7, Italian, "Y"
db 5fh,97h,0e0h,0f2h,0e8h,0ech
db 94,'Y',0
db 23h,40h,0c6h,0d8h,0c5h,5eh ; 8, Norwegian/Danish, "`"
db 5fh,60h,0e6h,0f8h,0e5h,7eh
db 94,60h,0
db 23h,60h,0c3h,0c7h,0d5h,5eh ; 9, Portugese, "%6"
db 5fh,60h,0e3h,0e7h,0f5h,7eh
db 94,'%','6'
db 0a3h,0a7h,0a1h,0d1h,0bfh,5eh ; 10, Spanish, "Z"
db 5fh,60h,0b0h,0f1h,0e7h,7eh
db 94,'Z',0
db 23h,0c9h,0c4h,0d6h,0c5h,0dch ; 11, Swedish, "7"
db 5fh,0e9h,0e4h,0f6h,0e5h,0fch
db 94,'7',0
db 0f9h,0e0h,0e9h,0e7h,0eah,0eeh ; 12, Swiss, "="
db 0e8h,0f4h,0e4h,0f6h,0fch,0fbh
db 94,'=',0
nrcfinal db 'A45CRf9QKY`E6Z7H=Lg' ; NRC country letters
nrcflen equ $-nrcfinal ; "%6" "%=" done separately
nrcnum db 1,2,3,3,4,4,5,5,6,7,8,8,8,10,11,11,12,9,9
; country numbers matching
; nrcfinal letters
;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,1,1,1,1,1
;NRC to DG keyboard codes, North American + ALT-ROM+transparent
nrcdgkbd db 19h,1ah,0,1dh,1bh,18h,1ch,17h,1fh,0,1eh,1dh,14h,19h, 19h,18h
db 19h,19h,19h,19h,19h
; DG char set idents to Kermit set idents
; DG set values 0 1 2 3 4 5 6 7 8 9 0a 0b 0c 0d 0e 0f hex
dgchtab db 0,0,1,4,6,11,10,8, 12,100,100,100,100,100,20,100 ; decimal
; 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
db 22,21,100,15,17,19,100, 100,100,100,100,100,100, 0,15,16
; 20h and above map to soft set filler 100
db 100 ; filler set
; 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 128 translatable bytes followed by the table size (94) and the
; ISO announcer ident '%5'.
MNlatin db 0a4h,0a6h,0a8h,0ach,0adh,0aeh,0afh,0b4h ; Latin1 code points
db 0beh,0d0h,0d7h,0deh,0f0h,0fdh,0feh,0ffh
db 20h,20h,0a4h,20h,20h,20h,20h,20h ; MN values there
db 20h,20h,3fh,20h,20h,0ffh,20h,20h
; 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
; Data General Word Processing to CP 437
dgwpcp437 db 20h,0dah,0c0h,0bfh, 0d9h,9fh,'~',8h ; column 10
db 0e4h,0e4h,0f4h,0f5h, 0fbh,8h,0ech,8h
db '0','1',0fdh,'3', '4','5','6','7' ; column 11
db '8','9',8h,0c9h, 1bh,8h,1ah,0fah
db 13h,0e0h,0e1h,8h, 0ebh,8h,8h,0fch ; column 12
db 0e9h,8h,8h,8h, 0e6h,8h,0eeh,8h
db 8h,8h,0e5h,0e7h, 8h,0edh,8h,8h ; column 13
db 8h,0eah,1eh,14h, 4 dup (8h)
db 0c3h,04h,010h,010h, 011h,1eh,1fh,9 dup (8h) ; column 14
db '0','1','2','3', '4','5','6','7' ; column 15
db '8','9',3fh,18h, 1ah,1bh,19h,20h
db 94,'D','W' ; 94 byte set, letter idents
dgwplen equ $-dgwpcp437 ; table size
; Convert Data General International to Latin1.
; DGI chars at these code points translate to the
; value used as a code point in the Latin1 table.
; Thus the second byte, 0ach, DGI not sign, in its
; row 2 col 10 translates to Latin1 not sign in row 12
; col 10. Columns 8 and 9 are C1 controls.
dgi2lat db 0a0h,0ach,0bdh,0b5h, 0b2h,0b3h,0a4h,0a2h ; column 10
db 0a3h,0aah,0bah,0a1h, 0bfh,0a9h,0aeh,3fh
db 0bbh,0abh,0b6h,3fh, 3fh,0a5h,0b1h,3fh ; column 11
db 3fh,0b7h,60h,0a7h, 0b0h,0a8h,0b4h,3fh
db 0c1h,0c0h,0c2h,0c4h, 0c3h,0c5h,0c6h,0c7h ; column 12
db 0c9h,0c8h,0cah,0cbh, 0cdh,0cch,0ceh,0cfh
db 0d1h,0d3h,0d2h,0d4h, 0d6h,0d5h,0d8h,3fh ; column 13
db 0dah,0d9h,0dbh,0dch, 0a0h,59h,0a0h,0a0h
db 0e1h,0e0h,0e2h,0e4h, 0e3h,0e5h,0e6h,0e7h ; column 14
db 0e9h,0e8h,0eah,0ebh, 0edh,0ech,0eeh,0efh
db 0f1h,0f3h,0f2h,0f4h, 0f6h,0f5h,0f8h,3fh ; column 15
db 0fah,0f9h,0fbh,0fch, 0dfh,0ffh,0a0h,0a0h
dgi2len equ $-dgi2lat
; Device attributes response string. Make strings asciiz.
v32str db escape,'[?63;1;2;4;6;8;9;15c',0 ; VT320, level 3, 132 col,
;printer, selective chars, Sixel graphics, UDkeys, NRC, DEC Tech Chars
v32sda db escape,'[>24;0;0c',0 ; VT320 secondary DA response
v22str db escape,'[?62;1;2;4;6;8;9;15c',0; VT220, level 2, etc as above
v102str db escape,'[?6c',0 ; VT102
v100str db escape,'[?1c',0 ; vanilla VT100
v52str db escape,'/Z',0 ; VT100 in VT52 compatibility mode
h19str db escape,'/K',0 ; Heath-19 (says plain VT52)
VIPstr db escape,'[8p OT',03h,escape,'[y7813 P GC A ',03h,0
VIPstrl equ $-VIPstr ; Honeywell MOD400 3.1 id for ESC [ y
ENQhstr db '7813 P GC A',03h ; Honeywell MOD400 4.0 id string
ENQhstrl equ $-ENQhstr
pt20str db escape,'! ~0 ~..6~C~2 ~$',0 ; Prime PT200
ENQstr db 'MS-DOS KERMIT' ; generic enquiry response
ENQstrl equ $-ENQstr
; 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,64,8
lbaudtab equ $-baudtab-1 ; last two are 1200/75 for split speeds
baudidx db 0 ; index into baud rate table
datbits db 7 ; number of databits (7 or 8)
;;;;;;;;;;;;;;; start session save area
even
savezoff label word
ttstate dw offset atnrm ; terminal automata state
ttstateST dw offset atnorm ; state for action after ST seen
apcstring dw 0 ; segment of apcmacro memory
bracecount db 0 ; count of curly braces in APC string
att_normal db 07H ; default normal screen coloring
oldterm dw 0 ; terminal type from previous entry
tekflg db 0 ; Tek mode active flag
old8bit db -1 ; flags.remflg setting for D463/D470
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
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
atescftab dw ansesc ; offset of esc follower table
setptr dw 0 ; hold offset of designated char set
upss db 96,'A',0,0 ; User Preferred Supplemental Set
; size, ident (DEC Supplemental Gr)
; 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) ; single/double width chars for a line
linescroll db slen dup (0) ; horizontal scroll for each line
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
mar_left db 0 ; left margin
mar_right db vswidth-1 ; right margin
savdgmar dw 0 ; DG saved right/left margins
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
G0set db gsize+3 dup (0),0 ; G0..G3 char set space
G1set db gsize+3 dup (0),1 ; last byte is permanent set index
G2set db gsize+3 dup (0),2 ; and should never be changed
G3set db gsize+3 dup (0),3
; Start of save cursor material
savelist equ this byte ; top of list of things to save
havesaved db 0 ; if have saved anything
cursor dw 0 ; cursor position
savextattr db 0 ; extended display attributes
curattr db 07h ; cursor attribute
svattr_index equ $-savelist ; offset of saved cursor attribute
savscbattr db 1 ; normal background attributes
atctype db 1 ; VTxxx cursor type (1=ul,2=bk,0/4=off)
savflgs dw 0 ; saved flags for atsc/atrc
atwrap db 0 ; autowrap flag
decrlm db 0 ; host controlled right-left writing
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
Gsetid db 4 dup (0) ; set numbers 0..24 of char set
lsavecu equ $-savelist ; length of stuff to save
savecu db lsavecu dup (0) ; saved cursor, attr., charset, etc
; End of save cursor material
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
; DG windows structure
dgwindcnt dw 1 ; DG count of active windows
dgwindow dw 25 dup (0) ; DG window [mar_top,mar_bot]
dgwindcomp db 25 dup (0) ; DG window compress (0=80,1=132 cols)
dgcaller dw atnorm ; DG hex proc callback address
numdigits db 0 ; DG hex digits remaining to be done
dgnum dw 0 ; DG numerical result
protectena db 0 ; DG protected mode enabled
blinkdis db 0 ; DG blink disabled
dgroll db 1 ; DG roll (0=disabled, 1=enabled)
dghscrdis db 0 ; DG horz scroll disabled (if 1)
dgcursave dw 16 dup (0) ; DG cursor position named save area
dgctypesave db 16 dup (0) ; DG cursor type named save area
dgcross db 0 ; DG crosshair activity: 0=off, 1=on
; 2 = track keypad, 4= track mouse
dg463fore db 0 ; DG D463 Polygon fill foregnd color
dgaltid dw 0 ; DG alt term id from host (0=none)
dgkbl db 0 ; DG keyboard language
dglinepat dw 0ffffh ; DG line drawing pattern
thisline db 0 ; linetype for current line
scroll db 1 ; lines to scroll, temp worker
savezlen dw ($-savezoff) ; length of z save area
;;;;;;;;;;;;;;;;; end of session save area
;note low_rgt dw 0 ; text screen dimensions
; byte low_rgt = max column (79)
; byte low_rgt+1 = max row (23)
led_col equ 65 ; column position for "LEDs" display
led_off equ '.' ; "Off" LED
v320leds db 'VT320 ....' ; VT320 mode (all 10 characters)
v220leds db 'VT220 ....' ; VT220 mode
v102leds db 'VT102 ....' ; VT102 mode
v100leds db 'VT100 ....' ; VT100 mode
v52leds db 'VT52 ' ; VT52 mode
h19leds db 'Heath-19 ' ; Heath-19 mode
honeyleds db 'Honey ....' ; Honeywell VIP 7809
pt20leds db 'PT200 ....' ; Prime PT200
d470leds db 'D470 ' ; D470 series from Data General
d470model db 'D470' ; D470 response for Read New Model ID
d463leds db 'D463 ' ; D463 series from Data General
d463model db 'D463' ; D463 response for Read New Model ID
;;d413model db 'D413' ; D413 response for Read New Model ID
data ends
code2 segment
extrn tekini:far, tekemu:far, tekend:far, teksetcursor:far
extrn dgline:far, dgbar:far, dgcrosson:far, dgcrossoff:far
extrn dgcrossrpt:far, dgsetcrloc:far, dgarc:far, dgpoly:far
code2 ends
code segment
extrn cptchr:near, pntchr:near, pntchk:near, pntflsh:near
extrn modlin:near, latin1:near
extrn clrmod:near, dec2di:near, latininv:near, trnprs:near
extrn dgsettek:far, vtksmac:near, vtkrmac:near, product:near
assume ds:data, es:nothing
fmodlin proc far
call modlin
ret
fmodlin endp
fclrmod proc far
call clrmod
ret
fclrmod endp
fcptchr proc far
call cptchr
ret
fcptchr endp
fdec2di proc far
call dec2di
ret
fdec2di endp
fpntchr proc far
call pntchr
ret
fpntchr endp
fpntchk proc far
call pntchk
ret
fpntchk endp
fpntflsh proc far
call pntflsh
ret
fpntflsh endp
ftrnprs proc far
call trnprs
ret
ftrnprs endp
fvtksmac proc far
call vtksmac
ret
fvtksmac endp
fvtkrmac proc far
call vtkrmac
ret
fvtkrmac endp
fproduct proc far
call product
ret
fproduct endp
flatin1 proc far
push flags.chrset
mov ax,vtcpage ; get current terminal Code Page
mov flags.chrset,ax ; tell file transfer part
call latin1
call latininv
pop flags.chrset
ret
flatin1 endp
code ends
code1 segment
extrn prtbout:near, prtnout:near, csrtype:near, atsclr:near
extrn vtscru:near, vtscrd:near, chgdsp:near
extrn setpos:near, setudk:near, udkclear:near, vtbell:near
extrn setatch:near, qsetatch:near, getatch: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 setrev:near, clrrev:near, tekrpal:near
extrn tekinq:near, tekpal:near, tekrpal:near
extrn atparse:near, atpclr:near, atdispat:near, apcmacro:near
extrn setprot:near, clrprot:near, frepaint:far, touchup:near
assume cs:code1, ds:data, es:nothing
; Terminal display routine. Call with character incoming character in AL
anstty proc near
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 flags.capflg,logses ; capturing output?
jz anstt3 ; z = no, forget this part
push ax ; save char
call fcptchr ; give it captured character
pop ax ; restore character
anstt3: jmp ttstate ; print transparently
anstt4: test flags.vtflg,ttd463+ttd470 ; DG D463/D470 mode?
jnz anstt4a ; nz = yes, must pass nulls
or al,al ; NUL char?
jz atign ; z = yes, ignore it before logging
anstt4a:test yflags,capt ; capturing output?
jz anstt8 ; z = no, forget this part
call fcptchr ; give it captured character
; Direct char to processor module
anstt8: test flags.vtflg,ttd463+ttd470 ; DG D463/D470 mode?
jnz anstt10 ; nz = yes
cmp vtemu.vtchset,13 ; ASCII (0) or NRC's (1-13) 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
cmp al,20h ; C0 control code?
jb anstt8c ; b = yes
cmp vtemu.vtchset,15 ; TRANSPARENT?
je anstt9 ; e = yes, pass all others
anstt8c:jmp atctrl ; dispatch on control code
anstt9: jmp ttstate ; dispatch according to state
; DG D463/D470 terminal
anstt10:test flags.remflg,d8bit ; use high bit?
jnz anstt11 ; nz = yes
and al,7fh ; 7 bit terminal only
anstt11:test anspflg,vtcntp ; controller (transparent) printing?
jnz anstt12 ; nz = yes, go through filter routine
cmp al,20h ; C0 control code?
jae anstt12 ; ae = no, do according to ttstate
cmp ttstate,offset atnrm ; normal text processing?
jne anstt12 ; ne = no, pass controls to state
jmp dgctrl ; do DG controls
anstt12:jmp ttstate ; process regularly
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 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 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
atnrm14:cmp al,DEL ; ANSI Delete char?
jne atnrm2 ; ne = no
ret ; ignore DEL
; use atdeb for debug simple tty dsp
atnrm2: mov dx,cursor ; get cursor virtual position
push bx
mov bl,dh ; get row
xor bh,bh
mov bl,linetype[bx] ; line width
mov thisline,bl ; save for current reference
pop bx
test vtemu.vtflgop,decawm ; Autowrap active?
jz atnrm2a ; z = no
mov cl,mar_right ; logical right margin
cmp thisline,0 ; single width line?
je atnrm2c ; e = yes, single
test flags.vtflg,ttd463+ttd470 ; D463/D470?
jnz atnrm2c ; nz = yes, these double the margins
shr cl,1 ; halve right column # for wide chars
atnrm2c:cmp dl,cl ; want to write beyond right margin?
jb atnrm2a ; b = no
cmp atwrap,0 ; autowrap pending?
je atnrm2a ; e = no
test anspflg,vtautop ; printing desired?
jz atnrm2a ; e = no
push dx
push ax ; save char
mov dh,atwrap ; get 1+last display line's row
dec dh ; up one line
call pntlin ; print line
mov al,LF ; terminate in LF
call fpntchr
call fpntflsh ; flush printer buffer
pop ax ; recover char in AL
pop dx
atnrm2a:push ax ; save character
call getatch ; check for protected field
test cl,att_protect ; protected?
jz atnrm2d ; z = no
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jz atnrm2d ; z = no
call dgcuf ; do DG cursor right
mov dx,cursor
atnrm2d:cmp decrlm,0 ; host right-left mode active?
je atnrm2e ; e = no
cmp atwrap,0 ; wrap pending?
je atnrm2e ; e = no
mov dl,mar_right
inc dl ; set to wrap in normal sense
atnrm2e: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
cmp thisline,0 ; single width line?
je atnrm2b ; e = yes
call inschr ; open second space for double width
atnrm2b:pop ax ; restore char
; set cursor before writing char
atnrm3: cmp thisline,0 ; check for double characteristic
je atnrm3a ; e = normal, not doubles
shl dl,1 ; double the column number
atnrm3a:
push dx
call direction ; set dx to desired position
mov ah,curattr ; current attribute
mov cl,extattr ; extended attribute
call setatch ; write char (al) and attribute (ah)
pop dx
cmp thisline,0 ; check for double characteristic
je atnrm4 ; e = normal, not doubles
cmp decrlm,0 ; host writing direction active?
je atnrm3b ; e = no
dec dl ; next col
jmp short atnrm3c
atnrm3b:inc dl ; next column
atnrm3c:push dx
call direction ; set dx to desired position
mov al,' ' ; use a space for doubling
mov ah,curattr ; current attribute
mov cl,extattr ; extended attribute
call setatch ; write char (al) and attribute (ah)
pop dx
shr dl,1 ; keep "cursor" in single units
atnrm4: test flags.vtflg,ttd463+ttd470+ttheath ; D463, D470 or H-19?
jz atnrm4d ; z = no
jmp dgcuf ; do DG cursor forward
atnrm4d:test vtemu.vtflgop,decawm ; Autowrap active?
jz atnrm5 ; z = no
cmp decrlm,0 ; host writing left to right?
je atnrm4e ; e = no
or dl,dl ; wrote in left most col?
jnz atnrm5 ; nz = no
mov dl,mar_right ; set next column to the right
jmp short atnrm4b ; do not move cursor now
atnrm4e:mov cl,mar_right ; logical right margin
cmp thisline,0 ; single width line?
je atnrm4a ; e = yes, single
shr cl,1 ; halve right column # for wide chars
atnrm4a:cmp dl,cl ; wrote in right-most column?
jb atnrm5 ; b = no
inc dl ; say want to use next column
atnrm4b:mov atwrap,dh ; turn on wrap flag with 1 + this row
inc atwrap ; so 0 means no wrap pending
test flags.vtflg,ttheath ; H-19?
jnz atscur ; nz = yes, show wrap now
mov cursor,dx ; virtual cursor position
ret ; exit without moving cursor from eol
atnrm5: mov dx,cursor ; restore cursor position
cmp decrlm,0 ; host writing direction active?
je atnrm5a ; e = no
or dl,dl
jz atnrm5b
dec dl ; next column
jmp short atnrm5b
atnrm5a:inc dl ; next column
atnrm5b:mov atwrap,0 ; say not about to wrap
;; jmp short atscur
atnrm endp
atscur: cmp dl,mar_left ; left of left margin?
jae atscu1 ; ae = no, continue
mov dl,mar_left ; set at left margin
atscu1: mov cl,mar_right ; 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
test flags.vtflg,ttd463+ttd470 ; D463/D470?
jnz atscu1a ; nz = yes, these double the margins
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,mar_left ; set to left margin
cmp decrlm,0 ; host right-left mode active?
je atscu1e ; e = no
mov dl,mar_right
atscu1e: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:test flags.vtflg,ttd463+ttd470 ; D463/D470?
jz atscu1d ; z = no
cmp dgroll,0 ; is DG roll enabled?
jne atscu1d ; ne = yes, do the scroll
mov dh,mar_top ; move to top of window
jmp short atscu3
atscu1d: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
xor dh,dh
atscu4: cmp dh,byte ptr low_rgt+1 ; 25th line?
jle atsetcur ; 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 atsetcur ; 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 fclrmod ; 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
atsetcur: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 atsetcu1 ; e = yes
shl dl,1 ; double the column number
atsetcu1: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 atsetcu2 ; z = no, return if no margin bell
cmp kbiflg,0 ; is keyboard input flag set?
je atsetcu2 ; e = no, just return
mov bx,kbicsr ; cursor at previous keyboard input
cmp bh,dh ; same row as now?
jne atsetcu2 ; ne = no, just return
cmp bl,belcol ; old cursor at or left of bell column?
ja atsetcu2 ; a = no, just return
cmp dl,belcol ; new cursor past bell column?
jbe atsetcu2 ; be = no, just return
call vtbell ; ring the bell
atsetcu2:ret
; 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
cmp al,18h ; CAN (cancel)?
je atctrl6 ; e = yes
cmp al,1ah ; SUB (treated as CAN)?
je atctrl6 ; e = yes
cmp ttstate,offset atdcsnul ; consuming a DCS?
jne atctrl5 ; ne = no
ret ; consume
atctrl5:cmp ttstate,offset atesc1 ; state is second char of ST?
jne atctrl6 ; ne = no
jmp ttstate ; go process second char
atctrl6:test anspflg,vtcntp ; printing desired?
jz atctrl1 ; z = no
call fpntchr ; 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
atctrl3: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
test flags.vtflg,ttvt320+ttvt220 ; doing VT320/VT220?
jz atctrl3 ; z = no, trim back to C0
atctrl4:jmp ansc1[di] ; dispatch on C1 control codes
; Control code routines
atbs: cmp decrlm,0 ; host writing direction active?
jne atbs2 ; ne = yes
or dl,dl ; Backspace, too far?
jz atbs1 ; z = at column 0 already
dec dl ; backup cursor
atbs1: call atccpc ; check range
mov atwrap,0 ; cancel wrap pending
jmp atsetcur ; set cursor and return
atbs2: cmp dl,mar_right ; at right margin now?
je atbs1 ; e = yes, stop
inc dl
jmp short atbs1
atht: cmp flags.vtflg,ttheath ; Horizontal Tab, Heath-19 mode?
je atht2 ; e = yes, handle specially
xor ch,ch
mov cl,mar_right
cmp dl,cl ; at or beyond last column?
jae atht1a ; 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: call atccpc ; check range
atht1b: call atsetcur ; set cursor and return
ret
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,mar_right ; check against right edge
jbe atht3 ; be = in range
mov dl,mar_right ; else go to right margin
atht3: jmp atht1b ; set cursor and return
atlf: test vtemu.vtflgop,anslnm ; Line Feed, New-line mode?
jz atlf2 ; z = no, just move to next line down
atlf1: mov dl,mar_left ; move to left margin also
cmp decrlm,0 ; host writing direction active?
je atlf2 ; e = no
mov dl,mar_right
atlf2: test anspflg,vtautop ; printing desired?
jz atlf3 ; e = no
push dx
push ax ; save char
call pntlin ; print current line
pop ax ; recover char in AL, print it too
call fpntchr
call fpntflsh ; flush printer buffer
pop dx
atlf3: inc dh ; index line down
call atccic ; check indexing
call ax ; call scrolling routine
jmp atsetcur ; set cursor
atcr: mov dl,mar_left ; Carriage Return, go to left margin
mov atwrap,0 ; cancel wrap pending
cmp decrlm,0 ; host writing direction active?
je atcr2 ; e = no
mov dl,mar_right
atcr2: 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 atsetcur ; set cursor and return
atff: cmp ttstate,offset atescf ; Form Feed, parsing escape sequence?
jne atlf ; ne = no, do as line feed
atff1: 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 parstate,0 ; CAN, clear esc seq parser
jmp atnorm
atenq: mov cx,ENQhstrl ; length of Honeywell string
mov si,offset ENQhstr ; ptr to string
mov ttyact,0 ; start grouping for networks
cmp flags.vtflg,tthoney ; ENQ, Honeywell terminal?
je atenq1 ; e = yes
cmp vtenqenable,0 ; VTxxx response enabled?
je atenq2 ; e = no
mov cx,ENQstrl ; length of string
mov si,offset ENQstr ; ptr to string
atenq1: cld
lodsb ; get a byte
push cx ; save regs
push si
call prtbout ; send to port WITHOUT echo
pop si
pop cx
loop atenq1 ; loop for all characters
mov ttstate, offset atnrm ; reset to normal and return
mov ttyact,1 ; end group output for networks
atenq2: ret
atesc: cmp ttstate,offset atdcsnul ; consuming a DCS?
jne atesc3 ; ne = no
mov ttstate,offset atesc1 ; stay here
ret
atesc1: cmp al,'\' ; end of ST?
je atesc2 ; e = yes
jmp atdcsnul ; continue to consume DCS
atesc2: jmp atgotst ; reset DCS processing
atesc3: 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 atescftab,offset ansesc; ANSI escape table, for atdispat
mov cx,flags.vtflg
test cx,ttvt320+ttvt220+ttvt102+ttvt100+tthoney ; VT320 etc?
jnz atescf2 ; nz = yes
mov atescftab,offset v52esc ; VT52 escape table
cmp cx,ttvt52 ; VT52?
je atescf1 ; e = yes
mov atescftab,offset h19esc ; use Heath-19 table
cmp cx,ttheath ; Heath-19?
je atescf1 ; e = yes
mov atescftab,offset pt200esc
cmp cx,ttpt200 ; Prime PT200?
je atescf2 ; e = yes
ret ; return on error
atescf1:mov ttstate,offset atnrm ; reset state to "normal"
mov bx,atescftab ; get offset of escape follower table
jmp atdispat ; perform dispatch via table in BX
atescf2: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 [)
atcsi0: cmp ninter,0 ; any intermediates from ESC..[?
je atcsi ; e = no, else not this item
jmp atnorm ; reset state to "normal"
; enter here with real CSI char
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
jmp atpclr ; clear parser parameters and return
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).
atdcs0: cmp ninter,0 ; any intermediates?
je atdcs ; e = no, else not this item
jmp atnorm ; reset state to normal
; enter here with real DCS char
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.
atgotst0:cmp ninter,0 ; any intermediates in ESC..\?
je atgotst ; e = no, else not this item
jmp atnorm ; reset state to normal
; enter here with real ST char
atgotst:jmp ttstateST ; go to state for ST arrival
; Read and discard OSC (ESC ]), PM (ESC ^) control sequences
; through final ST (ESC \) terminator.
atdcsnul0:cmp ninter,0 ; any intermediates in ESC..\?
je atdcsnul ; e = no, else not this item
ret
; enter here with real ST char
atdcsnul:mov dcsstrf,0 ; simulate a null (dummy) Final char
mov emubufc,0 ; clear string count
mov ttstate,offset atdcsnul ; keep coming here
mov ttstateST,offset atnorm ; where to go when ST has been seen
ret ; consume chars
; Process Application Process Control string (APC or ESC _ lead-in chars,
; already read). Mallocs 1KB buffer, passes buffer to apcmacro for execution
; as a Take file. Curly braces protect comma command separators.
atapc: cmp ninter,0 ; any intermediates?
je atapc0 ; e = no, else not this item
jmp atnorm ; reset state to normal
; enter here with real DCS char
atapc0: mov ax,apcstring ; old string buffer segment
or ax,ax ; used?
jz atapc1 ; z = no
push es
mov es,ax
mov ah,freemem ; free that string memory
int dos
pop es
mov apcstring,0 ; clear pointer
atapc1: mov bx,(1024+3+15)/16 ; 1K buffer
mov cx,bx ; remember desired paragraphs
mov ah,alloc ; allocate a memory block
int dos
jc atapc2 ; c = error, not enough memory
cmp bx,cx ; obtained vs wanted
jae atapc3 ; ae = enough
push es
mov es,ax ; allocated segment
mov ah,freemem ; free it again
int dos
pop es
atapc2: jmp atnorm ; fail
atapc3: mov apcstring,ax ; remember segment
mov bracecount,0 ; count of curly braces in string
mov emubufc,0 ; preset string buffer count
mov ttstate,offset atapc4 ; next state is read string
mov ttstateST,offset atapc5 ; where to go when ST has been seen
ret
; read bytes of APC string
atapc4: mov bx,emubufc ; count of buffer chars
cmp bx,1024 ; too many?
ja atapc6 ; a = yes, ignore string
push es
mov cx,apcstring ; segment of string buffer
mov es,cx
cmp al,braceop ; opening brace?
jne atapc4a ; ne = no
inc bracecount ; count up braces
atapc4a:cmp al,bracecl ; closing brace?
jne atapc4b ; ne = no
sub bracecount,1 ; count down braces
jnc atapc4b ; nc = not below zero
mov bracecount,0 ; clamp to zero
atapc4b:cmp al,',' ; comma command separator?
jne atapc4c ; ne = no
cmp bracecount,0 ; in curly braces?
jne atapc4c ; ne = yes, leave comma as comma
mov al,CR ; replace bare comma as CR
atapc4c:xor ah,ah
mov es:[bx],ax ; store incoming byte + null
pop es
inc emubufc ; count bytes in buffer
ret ; accumulate more bytes
atapc5: mov ax,apcstring ; get here upon ST for APC
or ax,ax ; string buffer in use?
jz atapc6 ; z = no, quit
mov ttstate,offset atnrm ; reinit state before leaving
mov ttstateST,offset atnorm
mov bracecount,0 ; count of curly braces in string
cmp apcenable,0 ; is APCMACRO enabled?
je atapc6 ; e = no, quit
push es
mov es,ax
mov bx,emubufc ; count of bytes in string
mov byte ptr es:[bx],CR ; append CR C to renter Connect mode
mov byte ptr es:[bx+1],'C'
add bx,2 ; two more bytes in buffer
pop es
mov cx,bx ; CX used to pass string length
call APCMACRO ; create and execute Take file
; does not return if success
atapc6: mov ax,apcstring ; segment of string buffer
or ax,ax ; in use?
jz atapc7 ; z = no
mov es,ax
mov ah,freemem ; free buffer
int dos
atapc7: mov apcstring,0 ; clear buffer
mov emubufc,0 ; clear string count
mov bracecount,0 ; count of curly braces in string
jmp atnorm ; exit this sequence
; User Definable Key processor of DCS strings.
atudk: cmp dinter,0 ; no intermediates?
je atudk1 ; e = correct
mov ninter,0 ; setup atdcsnul for proper form
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
xor si,si ; 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
atind0: cmp ninter,0 ; any intermediates?
je atind ; e = no, else not this item
ret
atind: inc dh ; IND (index), move cursor down one
atind1: call atccic ; check cursor position
call ax ; scroll if necessary
jmp atsetcur ; set cursor, etc. and return
atnel0: cmp ninter,0 ; any intermediates from ESC..E?
je atnel ; e = no, else not this item
jmp atdgnrc ; try Nowegian/Danish NRC designator
; enter here with real NEL char
atnel: mov dl,mar_left ; NEL, next line - sort of like CRLF
inc dh ; ... all in one command
jmp short atind1 ; check cursor, etc., and return
atri0: cmp ninter,0 ; any intermediates?
je atri ; e = no, else not this item
ret
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 short atind1 ; check cursor, etc., and return
; HTS, horizontal tab set in this col
athts0: cmp ninter,0 ; any intermediates from ESC..H?
je athts ; e = no, else not this item
jmp atdgnrc ; try Swedish NRC designator
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 cl,extattr ; extended attributes
mov savextattr,cl ; it's real storage is in msyibm
mov cl,scbattr
mov savscbattr,cl
mov havesaved,1 ; say have saved something
mov cx,lsavecu ; length of save area
push es ; save es
mov ax,data ; seg of save area
mov es,ax ; 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: cmp havesaved,0 ; saved anything yet?
jne atrc1 ; ne = yes
ret
atrc1: 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
mov ax,seg savecu ; seg of savecu storage
mov ds,ax
mov ax,seg savelist ; seg of regular storage
mov es,ax
cld
shr cx,1 ; divide by two for word moves
jnc atrc2 ; nc = even number of bytes
movsb ; do the odd byte
atrc2: rep movsw ; put the stuff back
pop ds
pop es
mov al,savextattr ; extended attributes
mov extattr,al
mov al,savscbattr
mov scbattr,al
mov ax,savflgs ; get saved flags
xor ax,vtemu.vtflgop ; exclusive-or with current flags
mov al,atctype ; get cursor shape
call csrtype ; restore it
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]
or vtemu.vtflgop,ax ; update these flags
mov savflgs,ax
mov bx,offset Gsetid ; restore character sets
call chrsetup ; go remake G0..G3
mov dx,cursor ; get cursor
mov kbiflg,0 ; don't bother them with beeps here
jmp atsetcur ; set cursor
atkpam: cmp ninter,0 ; any intermediates?
jne atkpam1 ; ne = yes, not this item
or vtemu.vtflgop,deckpam ; turn on keypad applications mode
ret
atkpam1:jmp atdgnrc ; try Swiss NRC designator
atkpnm: and vtemu.vtflgop,not deckpam ; turn off keypad applications mode
ret ; (to numeric mode)
; Privileged sequence, ignore it
atpriv: cmp ninter,0 ; any intermediates?
jne atpriv1 ; ne = yes, not this item
mov ttstate,offset atnorm ; ignore next char
atpriv1: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, 96 'A' is Latin1
mov ax,flags.vtflg ; terminal type
test ax,ttvt320+ttvt220+ttvt102+ttvt100+tthoney ; VTxxx?
jz atdgfA1 ; z = no
jmp mkukascii ; make UK ASCII table
atdgfA1:ret
atdgfA2:jmp mklatin1 ; make Latin1 char set
atdgfA3:jmp atdgnrc ; try British NRC
atdgfB: call atdgset ; 'B' ASCII, get setptr from inter
jc atdgfA1 ; c = no matching pointer
cmp inter,'+' ; in the 94 byte set?
ja atdgfB1 ; a = no, do Latin2
jmp mkascii ; make US ASCII set
atdgfB1:jmp mklatin2 ; make Latin2 ("B"/96)
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
jmp mkdecspec ; init set to DEC Special Graphics
atdgf1: call atdgset ; '1' ALT-ROM
jc atdgf1b ; c = no matching pointer
jmp mkaltrom ; make ALT-ROM set
atdgf1b:
; cmp ninter,0 ; ESC 1? (Special enter Tek mode)
; jne atdgf1c ; ne = some, not ESC 1
; cmp nparam,0
; jne atdgf1c ; ne = some, not ESC 1
; jmp atff1 ; treat the same as ESC ^L
atdgf1c:ret
atdgft: call atdgset ; '>' Dec Technical Set
jc atdgft1 ; c = no matching pointer
cmp inter,'+' ; in the 94 byte set?
ja atdgft1 ; a = no
jmp mkdectech ; make DEC Tech set
atdgft1:cmp ninter,0 ; ESC > DECKNPNM set numeric keypad?
jne atdgft2 ; ne = no
and vtemu.vtflgop,not deckpam ; turn off application keypad bit
atdgft2:ret ; (to numeric)
; '<' User Preferred Supplemental Set
atdgfu: call atdgset ; get set pointer
jc atdgfu2 ; c = no matching pointer
cmp inter,',' ; designating the 96 char set?
jb atdgfu1 ; b = no, want 94
cmp word ptr upss+1,0+'A' ; is ISO Latin-1 the preferred set?
jne atdgfu0a ; ne = no
jmp mklatin1 ; make Latin1 set
atdgfu0a:cmp word ptr upss+1,0+'H' ; is Hebrew-ISO preferred?
jne atdgfu2 ; ne = no
jmp mklatin_Hebrew ; make Hebrew-ISO
atdgfu1:cmp word ptr upss+1,'5%' ; DEC Supplemental Graphics?
jne atdgfu1a ; ne = no
jmp mkdecmn ; make DEC Multinat/Supp Gr
atdgfu1a:cmp word ptr upss+1,'4"' ; DEC Hebrew?
jne atdgfu2
jmp mkdec_Hebrew ; make DEC Hebrew
atdgfu2:ret
atdgfq: call atdgset ; '?' Transparent
jc atdgfu2 ; c = no matching pointer
jmp mkxparent ; make transparent table
; ESC <...> <1-8> series
atsdhl: cmp ninter,1 ; just one intermediate?
jne atsdh0 ; ne = no
cmp inter,'#' ; this intermediate?
jne atdgnrc ; ne = no, try NRC char set designator
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,'6' ; '%6' NRC designator?
je atdgnrc ; e = yes, do that above
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
jmp mkdecmn ; make DEC Multinat/Supp Gr
atdgf5a:ret
; Enter with Final esc char in al, others in array inter. Setup Gn if success.
atdgnrc proc near ; check for NRC set designator
cmp ninter,0 ; ESC Z?
jne atdgnr1 ; ne = no
cmp al,'Z' ; the Z?
jne atdgnrx ; ne = not ESC Z
jmp atda ; process ident request
atdgnr1:cmp inter,'+' ; in the 94 byte set?
ja atdgnrx ; a = no, ignore
call findctry ; find NRC country number in CX
jc atdgnrx ; c = not found, ignore
mov ninter,1 ; help atdgset find our set
call atdgset ; check for Gn designator
jc atdgnrx ; c = not found
jmp mknrc ; make NRC set
atdgnrx:ret ; ignore
atdgnrc endp
; Find NRC country number, putting it into CX, given Final char in AL and
; intermediates in array inter. Return carry set if not found.
findctry proc near
cmp ninter,2 ; second intermediate (%)?
jb findct1 ; b = no
ja findct3 ; a = three or more, no match
mov ah,inter+1 ; get NRC intermediate
cmp ax,'%6' ; Portugese NRC?
jne findct4 ; ne = no, try Hebrew
mov cx,9 ; Portuguese NRC is number 9
clc
ret
findct4:cmp ax,'%=' ; Hebrew NRC?
jne findct3 ; ne = no, fail
mov cx,13 ; Hebrew NRC is number 13
clc
ret
findct1:cmp ninter,0 ; no intermediate?
je findct3 ; e = yes, no designator, fail
mov cx,nrcflen ; number of NRC letters to consider
cld
push di ; save regs
push es
push ds
pop es
mov di,offset nrcfinal ; list of NRC final chars
repne scasb ; look for a match
pop es ; recover reg
jne findct2 ; ne = failed
dec di ; compenstate for auto-inc
sub di,offset nrcfinal ; get distance covered
mov cl,nrcnum[di] ; country number from parallel list
xor ch,ch ; return number in CX
pop di
clc ; success
ret
findct2:pop di ; carry set = failure
findct3:stc
ret
findctry endp
; Worker for atdgf routines. Return setptr looking at Gnset (n=0..3) and
; carry clear, based on ninter=1, inter = Gn designator. Carry set if fail.
; Modifies AL
atdgset proc near
cmp ninter,1 ; one intermediate?
jne atdgsex ; ne = no, ignore
mov al,inter ; inter, from parser
cmp al,'(' ; 94 char sets, designate G0?
je atdgse0 ; e = yes
cmp al,')' ; G1?
je atdgse1
cmp al,'*' ; G2?
je atdgse2
cmp al,'+' ; G3?
je atdgse3
cmp al,'-' ; 96 char sets, designate G1?
je atdgse1
cmp al,'.' ; G2?
je atdgse2
cmp al,'/' ; 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
atdgset endp
; S7C1T/S8C1T select 7/8-bit controls
ats7c: test flags.vtflg,ttvt320+ttvt220 ; in VT320/VT220 mode?
jz atdgsex ; z = no, ignore command
cmp ninter,1 ; one intermediate?
jne ats7ca ; ne = no
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 ; just one?
jne ats8ca ; ne = no
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, or
; 'H' Hebrew-ISO, or '"','4' DEC-Hebrew
; Store the selection letters in array upss for later use by ESC <char> '<'
atupss: cmp word ptr dinter,0+'!' ; "!u" proper intermediate?
je atupss0 ; e = yes
mov ninter,0 ; set up atdcsnul for proper form
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
; 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
mov bx,offset emubuf ; temp table of char set idents
mov word ptr [bx],0 ; G0 and G1 to ASCII
mov al,vtemu.vtchset ; user specifed char set for GL
mov byte ptr [bx+2],al ; set G2 and G3 to user selected set
mov byte ptr [bx+3],al
test flags.vtflg,ttvt320+ttvt220
jnz chrdef1 ; nz = yes, 8-bit terminals
mov GRptr,offset G1set ; map G1 set to GRight
mov byte ptr [bx+1],18 ; assume Dec Special Graphics in G1
chrdef1:test vtemu.vtflgop,vsnrcm ; doing National Replacement Chars?
jz chrdef2 ; z = no
mov al,vtemu.vtchset ; get country number
mov dgkbl,al ; keyboard language
cmp al,13 ; max NRC country
ja chrdef2 ; a = out of bounds, ignore
and vtemu.vtflgop,not vscntl ; turn off 8-bit controls
mov ah,al ; country number 1..12
mov [bx],al ; set G0
test flags.vtflg,ttd463+ttd470 ; D463/D470?
jnz chrdef2 ; nz = yes, don't touch G1..G3 here
mov [bx+1],ah
mov word ptr [bx],ax ; same char set in G0..G3
mov word ptr [bx+2],ax
chrdef2:test flags.vtflg,ttd463+ttd470 ; D463/D470?
jz chrdef5 ; z = no (should have all cases now)
mov al,20 ; D463/D470 DG International to G1
test flags.remflg,d8bit ; 8 bit mode?
jnz chrdef4 ; nz = yes
chrdef3:mov al,22 ; D463/D470 DG Word Processing to G1
chrdef4:mov [bx+1],al ; D463/D470 G1 default
mov dgkbl,al ; DG keyboard language
mov ah,[bx] ; G0
or ah,ah ; using NRCs?
jz chrdef5 ; z = no
mov dgkbl,ah ; yes, state NRC in use for kbd
chrdef5:call chrsetup ; worker to setup G0..G3
; do table of Gn overrides
mov bx,offset vtemu.vttable ; table of char set overrides
call chrsetup ; worker to setup G0..G3
ret
chrdef endp
; Load G0..G3 with character sets whose idents (0..24) are in byte array
; pointed to by BX. Update Gsetid with those byte idents enroute.
chrsetup proc near
push ninter ; preserve these
mov ch,inter
push cx ; save them
mov ninter,1 ; one intermediate
mov inter,'(' ; init inter for atdgset
xor cx,cx ; count sets from 0
chrset1:push cx ; save loop counter
push bx
call atdgset ; get setptr = offset Gnset (n=0..3)
mov al,[bx] ; get char set ident from 4 byte list
cmp al,0ffh ; none?
je chrset90 ; e = none
mov bx,cx ; update Gsetid table with set ident
mov Gsetid[bx],al
or al,al ; ASCII (0)?
jnz chrset13 ; nz = no
call mkascii ; make ASCII
jmp chrset90
chrset13:cmp al,13 ; in NRC's?
ja chrset14 ; a = no
mov cl,al ; put country number in cx
xor ch,ch
call mknrc ; setup an NRC, using cx and setptr
jmp short chrset90
chrset14:cmp al,14 ; want ALT-ROM?
jne chrset15 ; ne = no
call mkaltrom ; do ALT-ROM setup
jmp short chrset90
chrset15:cmp al,15 ; Transparent (15)?
jne chrset16 ; ne = no
call mkxparent ; do Transparent setup
jmp short chrset90
chrset16:cmp al,16 ; Latin1 (16)?
jne chrset17
cmp setptr,offset G0set ; want 96 byte set in G0?
je chrset90 ; e = yes, can not do this
call mklatin1 ; make Latin1
jmp short chrset90
chrset17:cmp al,17 ; DEC-MCS (17)?
jne chrset18 ; ne = no
call mkdecmn ; make DEC Supplement Graph (DEC-MCS)
jmp short chrset90
chrset18:cmp al,18 ; DEC-Technical (18)?
jne chrset19 ; ne = no
call mkdectech ; make DEC Technical
jmp short chrset90
chrset19:cmp al,19 ; DEC-Special-Graphics?
jne chrset20 ; ne = no
call mkdecspec ; make DEC Special Graphics
jmp short chrset90
chrset20:cmp al,20 ; DG International?
jne chrset21 ; ne = no
call mkdgint ; make DG International
jmp short chrset90
chrset21:cmp al,21 ; DG Line Drawing?
jne chrset22 ; ne = no
call mkdgld ; make DG line drawing
jmp short chrset90
chrset22:cmp al,22 ; DG Word Processing?
jne chrset23 ; ne = no
call mkdgwp ; make DG Word Procssing
jmp short chrset90
chrset23:cmp al,23 ; Latin1/CP852?
jne chrset24 ; ne = no
call mklatin2
jmp short chrset90
chrset24:cmp al,24 ; Hebrew-ISO (CP862)?
jne chrset100 ; ne = no
call mklatin_hebrew
jmp short chrset90
chrset100:cmp al,100 ; possible DG soft set?
jne chrset90 ; ne = no
test flags.vtflg,ttd463+ttd470 ; D463/D470?
jz chrset90 ; z = no
call mkdgtr ; do it
chrset90:pop bx
pop cx
inc bx ; next byte of table
inc inter ; next set pointer
inc cx
cmp cx,4 ; done all sets?
jae chrset92 ; ae = yes
jmp chrset1 ; b = no (counting sets as 0..3)
chrset92:pop cx ; recover saved parsing items
mov inter,cl ; restore
pop ninter ; this too
ret
chrsetup endp
; copy gsize+3 bytes from (si) to (setptr)
cpyset proc near
push di
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
pop di
ret
cpyset endp
; Make Data General International to Gn table.
; Enter with destination in setptr
mkdgint proc near
push si
push di
call flatin1 ; get BX to Code Page dependent Latin1
call cpyset ; copy in Latin1
mov di,setptr
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],20 ; store our char set ident
add di,20h ; where new chars start
mov si,offset dgi2lat ; source = code points in Latin1
mov cx,dgi2len ; number of new chars
push es
push ds
pop es
cld
mkdgin1:lodsb ; read Latin1 code point from dgi2lat
cmp al,80h ; "?" unknown indicator or ASCII?
jb mkdgin2 ; b = yes, reproduce it literally
sub al,80h ; map down to indexable value
xlatb ; translate through Latin1 table
mkdgin2:stosb ; store in active table
loop mkdgin1 ; do all necessary
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov word ptr[di+gsize+1],'ID' ; set ident code
pop es
pop di
pop si
ret
mkdgint endp
; Make Data General line drawing graphics to Gn table.
; Enter with destination in setptr
mkdgld proc near
push si
push di
mov di,setptr
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],21 ; store our char set ident
mov cx,gsize ; first fill with spaces
mov al,20h
push es
push ds
pop es
push di ; save starting location
cld
rep stosb ; spaces
pop di
add di,20h ; where new chars start
mov si,offset dgldc ; replacement chars
mov cx,dgldclen ; number of new chars
rep movsb ; copy them to the table
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov word ptr[di+gsize+1],'LD' ; set ident code
pop es
pop di
pop si
ret
mkdgld endp
; Make Data General word processing to Gn table.
; Enter with destination in setptr
mkdgwp proc near
push si
push di
mov di,setptr
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],22 ; store our char set ident
mov cx,gsize ; first fill with spaces
mov al,20h
push es
push ds
pop es
push di ; save starting location
cld
rep stosb ; spaces
pop di
add di,20h ; where new chars start
mov si,offset dgwpcp437 ; replacement chars
mov cx,dgwplen ; number of new chars
rep movsb ; copy them to the table
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov word ptr[di+gsize+1],'WD' ; set ident code
pop es
pop di
pop si
ret
mkdgwp endp
; Make Data General soft set filler to Gn table.
; Enter with destination in setptr
mkdgtr proc near
push si
push di
mov di,setptr
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],100 ; store our char set ident
mov cx,gsize ; fill with "?"
mov al,'?'
push es
push ds
pop es
cld
rep stosb ; fill with "?"
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov word ptr[di+gsize+1],'UD' ; set ident code
pop es
pop di
pop si
ret
mkdgtr endp
; Make DEC Alt-ROM to Gn table.
; Enter with destination in setptr
mkaltrom proc near
call mkascii ; init set to ASCII
push si
push di
push es
push ds
pop es ; point es at data segment
mov di,setptr
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],14 ; store our char set ident
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
decalt1:lodsb ; get a char
add al,20h ; map up by 20h
stosb
loop decalt1
mov di,setptr
mov byte ptr[di+gsize],96 ; say this is a 96 byte set
mov word ptr[di+gsize+1],0+'1' ; set ident code
pop es
pop di
pop si
ret
mkaltrom endp
; Make DEC special graphics to Gn table.
; Enter with destination in setptr
mkdecspec proc near
call mkascii ; init set to ASCII
push si
push di
mov di,setptr
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],19 ; store our char set ident
add di,95 ; replace chars 95-126
mov si,offset sgrtab ; use DEC special graphics table
mov cx,sgrtabl ; table length
test flags.vtflg,ttheath ; Heath rather than VT?
jz mkdecsp1 ; z = no
mov si,offset hgrtab ; use Heath table
mov cx,hgrtabl
dec di ; work from 94 rather than 95
mkdecsp1:push es
push ds
pop es
cld
rep movsb ; replace chars with sgrtab items
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov word ptr[di+gsize+1],0+'0' ; set ident code
pop es
pop di
pop si
clc
ret
mkdecspec endp
; Make Dec Technical to Gn table
; Enter with destination in setptr
mkdectech proc near
push si
push di
mov di,setptr
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],18 ; store our char set ident
mov si,offset dectech ; source data
call cpyset ; copy the set to setptr's place
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 96 byte set
mov word ptr[di+gsize+1],0+'>' ; set ident code
pop di
pop si
clc
ret
mkdectech endp
; Make Heath-19 special graphics to Gn table. Enter with dest of setptr.
; 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
mkascii proc near
push ax
push cx
push di
push es
mov di,setptr ; char set to init (G0..G3)
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],0 ; store our char set ident
mov cx,gsize ; number of bytes to do
xor al,al ; initial value
push ds
pop es ; set es to data segment
cld
mkascii1:stosb ; copy value to char set table
inc al
loop mkascii1
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov word ptr[di+gsize+1],0+'B' ; set ident code to ASCII "B"
pop es
pop di
pop cx
pop ax
ret
mkascii endp
; Make UK ASCII to table Gn
; Enter with destination in setptr
mkukascii proc near
call mkascii ; make US ASCII table
push di
mov di,setptr ; get set pointer
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],1 ; store our char set ident
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 word ptr[di+gsize+1],0+'A' ; set ident code
pop di
ret
mkukascii endp
; Make DEC Multinational Char Set (DEC-MCS/DEC Supplemental Graphics)
; and put into Gn table indicated by AL = 0..3
; Enter with destination in setptr
mkdecmn proc near
push si
push di
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],17 ; store our char set ident
call flatin1 ; get Latin1 to BX
mov si,bx
call cpyset ; copy the set, gsize+3 bytes
mov si,offset MNlatin ; get update table
mov di,setptr
mov cx,16 ; number of updates
xor bh,bh
mkdecmn1:mov bl,[si] ; get Latin1 code point to be changed
and bl,not 80h ; map down to 0..127 range
mov al,[si+16] ; get new value
mov [di+bx],al ; store new value
inc si
loop mkdecmn1
mov di,setptr
mov byte ptr[di+gsize],96 ; say this is a 96 byte set
mov word ptr[di+gsize+1],'5%' ; set ident code
pop di
pop si
ret
mkdecmn endp
; Put transparent char set (128..255) into Gn table.
; Enter with destination in setptr
mkxparent proc near
call mkascii ; init set to ASCII
push si
push di
mov di,setptr ; point at character set
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],1 ; store our char set ident
mov cx,gsize ; number of chars to do, 128
cld
mov al,cl ; start with 128 char value
push es
push ds
pop es ; point es at data segment
mkxpar2:stosb ; store codes 128..255
inc al
loop mkxpar2
mov di,setptr
mov byte ptr[di+gsize],96 ; say this is a 96 byte set
mov word ptr[di+gsize+1],0+'?' ; set ident code
pop es
pop di
pop si
ret
mkxparent endp
; Construct NRC table.
; Enter with destination in setptr
; and CX holding the desired country code (1..13).
mknrc proc near
call mkascii ; init set to ASCII
push bx
push cx
push si
push di
push word ptr emubuf
push word ptr emubuf+2
push es
mov di,setptr
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],cl ; store our char set ident
mov emubuf+2,cl ; local copy
cmp cl,13 ; DEC Hebrew case?
je mknrc10 ; e = yes
; copy from NRC table (si) to set pointed at by di, cx chars
; plus 3 ident bytes at table end
mov word ptr emubuf,offset nrclat ; start of NRC to Latin1 table
mov ax,cx ; country code 1..12
mov bl,15 ; 15 bytes per entry
mul bl ; distance down the table to country
add word ptr emubuf,ax ; point at country line
mov cx,12 ; do 12 bytes of new chars
push ds
pop es
cld
call flatin1 ; returns BX = Latin1 to CPnnn table
xor si,si
mknrc2: mov al,nrclat[si] ; get code point to change
xor ah,ah
mov di,setptr ; start of destination table
add di,ax ; destination of new char
push bx
mov bx,word ptr emubuf ; ptr to country entries
mov al,[bx+si] ; read char from NRC table
pop bx
inc si
test al,80h ; in GR Latin1 area?
jz mknrc3 ; z = no, in ASCII GL area
and al,not 80h ; trim high bit for xlat
xlatb ; translate through Latin1 Code Page
mknrc3: stosb ; move replacement char from nrc list
loop mknrc2
mov di,setptr
test flags.vtflg,ttd463+ttd470 ; D463/D470?
jz mknrc8 ; z = no
mov cl,emubuf+2 ; country code again
cmp cl,3 ; French NRC?
jne mknrc4 ; ne = no
mov al,07fh ; apply DG French NRC patch
jmp short mknrc7
mknrc4: cmp cl,6 ; Spanish NRC?
jne mknrc5 ; ne = no
mov al,07fh ; apply DG Spanish NRC patch
jmp short mknrc7
mknrc5: cmp cl,7 ; DG Danish/Norweigen NRC?
jne mknrc6 ; ne = no
mov al,0fch ; apply DG Danish/Norweigen NRC patch
jmp short mknrc7
mknrc6: cmp cl,8 ; Swiss NRC?
jne mknrc7 ; ne = no
mov al,0e9h ; apply DG Swiss NRC patch
mknrc7: and al,not 80h
xlatb ; push through Latin1 translation
mov [di+7fh],al ; new value
mknrc8: add di,gsize ; look at end of set, to id bytes
movsb ; copy set size and two ident chars
movsw
jmp short mknrc11
mknrc10:mov vtcpage,862 ; Hebrew NRC CP862
call flatin1 ; get SI appropriate for Code Page
mov si,bx ; point to Latin 1 for this code page
add si,6*16 ; get Hebrew part of CP862
mov di,ds
mov es,di
mov di,setptr
add di,6*16
mov cx,27 ; number of characters
cld
rep movsb
mknrc11:pop es
pop word ptr emubuf+2
pop word ptr emubuf
pop di
pop si
pop cx
pop bx
ret
mknrc endp
; Construct Latin1 table to Gn table.
; Enter with destination in setptr
mklatin1 proc near
push si
push di
mov di,setptr ; destination
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],16 ; store our char set ident
call flatin1 ; get BX appropriate for Code Page
mov si,bx
mov cx,gsize ; bytes
push es
push ds
pop es
cld
rep movsb ; copy bytes
mov di,setptr
mov byte ptr[di+gsize],96 ; say this is a 96 byte set
mov word ptr[di+gsize+1],0+'A' ; set ident code
pop es
pop di
pop si
ret
mklatin1 endp
; Construct Latin2 table to Gn table.
; Enter with destination in setptr
mklatin2 proc near
push si
push di
mov di,setptr ; destination
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],16 ; store our char set ident
mov vtcpage,852 ; set emulator's CP to CP852
call flatin1 ; get BX appropriate for Code Page
mov si,bx
mov cx,gsize ; bytes
push es
push ds
pop es
cld
rep movsb ; copy bytes
mov di,setptr
mov byte ptr[di+gsize],96 ; say this is a 96 byte set
mov word ptr[di+gsize+1],0+'B' ; set ident code
pop es
pop di
pop si
ret
mklatin2 endp
; Make DEC Hebrew (94) 8-bit Supplemental
; Same code points as Hebrew-ISO at this time
mkdec_Hebrew proc near
call mklatin_hebrew
push es
push ds
pop es
mov di,setptr
mov byte ptr[di+gsize],94 ; say this is a 94 byte set
mov word ptr[di+gsize+1],'4"' ; set ident code
pop es
ret
mkdec_Hebrew endp
; Make Hebrew-ISO (96) 8-bit Supplemental to Gn pointer
; Enter with destination in setptr
; Presumes CP 862 is loaded
mklatin_Hebrew proc near
push si
push di
mov di,setptr ; destination
mov al,[di+gsize+3] ; get Gn number (0..3)
xor ah,ah
mov si,ax
mov Gsetid[si],24 ; store our char set ident
mov cx,gsize ; bytes
mov vtcpage,862 ; set emulator's CP to CP862
call flatin1 ; get BX appropriate for Code Page
mov si,bx
push es
push ds
pop es
cld
rep movsb ; copy bytes
mov di,setptr
mov byte ptr[di+gsize],96 ; say this is a 96 byte set
mov word ptr[di+gsize+1],0+'H' ; set ident code
pop es
pop di
pop si
ret
mklatin_Hebrew endp
; Get output byte in AL from keyboard raw reader and convert through active
; Code Page translations. Return final output byte in AL
; Return modified char code, depending on SET TERM CHAR-SET and active
; Code Page. Enter and exit with char in AL.
xltkey proc FAR
cmp al,80h ; regular ASCII key?
jb xltkey1 ; b = yes, do not translate
cmp flags.xltkbd,0 ; keyboard translation is off?
jne xltkey2 ; ne = no
xltkey1:ret
xltkey2:push es
push ds
pop es
push di
mov di,GRptr ; high bit is where GR points
mov cx,gsize
add di,cx
std
repne scasb ; scan looking for this code
cld
jne xltkey3 ; ne = not found
inc di ; backup to found code
sub di,GRptr ; minus start
or di,80h ; put back high bit
mov ax,di ; AL is the byte value
xltkey3:pop di
pop es
ret
xltkey endp
; cursor movements
atcup: test dspstate,dsptype ; on VT320 status line?
jz atcup0 ; z = no
mov param,0 ; yes, do not change rows
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,mar_right ; 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
atcup4a:jmp atsetcur ; 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 atsetcur ; 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 atsetcur ; 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 atsetcur ; 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 dl,1 ; column, count from 0 internally
jns atcha1 ; ns = 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,mar_right ; 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: inc dl ; count columns from 1 here
mov byte ptr param+2,dl ; 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: mov cl,al ; number to do
xor ch,ch
atcnl2: push cx
inc dh ; number to do
mov dl,mar_left
call atccic ; check cursor position
call ax ; scroll if necessary
call atsetcur ; set cursor, etc. and return
pop cx
loop atcnl2
ret
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
mov dl,mar_left
atcpl2: dec dh ; do one line
push cx ; save counter
call atccic ; check cursor position
call ax ; scroll if necessary
call atsetcur ; 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 try protected mode
ret
ated0: cmp lparam,0
je ated0a
jmp atedsel
ated0a: 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
push word ptr mar_top
mov mar_bot,dh
mov mar_top,0 ; row of cursor
inc dh ; number of lines to scroll
mov scroll,dh
call atscru ; scroll them up before erasure
pop word ptr mar_top
pop dx
call ersos ; erase start of screen to cursor
call ereos ; erase cursor to end of screen
ret
atedsel proc near ; DECSED selective erase in display
cmp lparam,'?' ; proper intermediate?
jne atedsel3 ; ne = no
mov ax,param ; get parameter
or ax,ax ; 0?
jnz atedsel1 ; nz = no
mov al,mar_top ; 0: erase cursor to end of screen
mov ah,mar_bot ; save margins
push ax
mov mar_top,dh ; use current row
mov ah,byte ptr low_rgt+1 ; bottom screen row for text
mov mar_bot,ah
call erprot ; do protected mode erasure
pop ax
mov mar_top,al ; restore margins
mov mar_bot,ah
jmp short atedsel3
atedsel1:cmp al,1 ; 1? erase start of line to cursor
jne atedsel2 ; ne = no
mov al,mar_top ; 1: erase start to cursor
mov ah,mar_bot ; save margins
push ax
mov al,mar_right
mov ah,dl ; save right margin and cursor col
push ax
mov mar_right,dl ; stop at current cursor
mov dl,mar_left ; start at this pseudo cursor
mov mar_top,dh ; use current row
mov mar_bot,dh
call erprot ; do protected mode erasure
pop ax
mov mar_right,al ; restore right margin
mov dl,ah ; restore cursor row
pop ax
mov mar_top,al ; restore margins
mov mar_bot,ah
jmp short atedsel3
atedsel2:cmp al,2 ; 2? erase whole line
jne atedsel3 ; ne = no
mov al,mar_top ; 2: erase whole screen
mov ah,mar_bot ; save margins
push ax
mov ah,mar_right
mov al,mar_left
push ax
push dx ; save cursor
xor dx,dx ; set to top left corner
mov mar_right,dl ; starting point
mov mar_top,dh
mov ax,low_rgt ; lower right corner of text area
mov mar_left,al ; start at this pseudo cursor
mov mar_bot,ah
call erprot ; do protected mode erasure
pop dx ; restore cursor
pop ax
mov mar_left,al
mov mar_right,ah
pop ax
mov mar_top,al ; restore margins
mov mar_bot,ah
atedsel3:ret
atedsel endp
p20ed: xor dx,dx ; Prime PT200, set cursor to 0,0
call ereos ; erase cursor to end of screen
jmp atsetcur ; put cursor at 0,0 and return
; Erase in current line
atel: cmp ninter,0 ; zero intermediates?
je atel0 ; e = yes
ret
atel0: cmp lparam,0 ; letter parameter?
je atel0a
jmp atelsel ; try protected mode erasure
atel0a: cmp param,0 ; was arg zero?
jne atel1 ; ne = no
mov al,dl ; erase from cursor
mov bl,byte ptr low_rgt ; to end of line, inclusive
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,byte ptr low_rgt
jmp erinline ; clear it
atel3: ret
atelsel proc near ; DECSEL selective erase in line
cmp lparam,'?' ; proper intermediate?
jne atelsel3 ; ne = no
mov ax,param ; get parameter
or ax,ax ; 0?
jnz atelsel1 ; nz = no
mov al,mar_top ; 0: erase cursor to end of line
mov ah,mar_bot ; save margins
push ax
mov mar_top,dh ; use current row
mov mar_bot,dh
call erprot ; do protected mode erasure
pop ax
mov mar_top,al ; restore margins
mov mar_bot,ah
ret
atelsel1:cmp al,1 ; 1? erase start of line to cursor
jne atelsel2 ; ne = no
mov al,mar_top ; 1: erase start to cursor
mov ah,mar_bot ; save margins
push ax
mov al,mar_right
mov ah,dl ; save right margin and cursor col
push ax
mov mar_right,dl ; stop at current cursor
mov dl,mar_left ; start at this pseudo cursor
mov mar_top,dh ; use current row
mov mar_bot,dh
call erprot ; do protected mode erasure
pop ax
mov mar_right,al ; restore right margin
mov dl,ah ; restore cursor row
pop ax
mov mar_top,al ; restore margins
mov mar_bot,ah
ret
atelsel2:cmp al,2 ; 2? erase whole line
jne atelsel3 ; ne = no
mov al,mar_top ; 2: erase whole line
mov ah,mar_bot ; save margins
push ax
mov ah,dl ; save right margin and cursor col
push ax
mov mar_right,dl ; stop at current cursor
mov dl,mar_left ; start at this pseudo cursor
mov mar_top,dh ; use current row
mov mar_bot,dh
call erprot ; do protected mode erasure
pop ax
mov dl,ah ; restore cursor row
pop ax
mov mar_top,al ; restore margins
mov mar_bot,ah
atelsel3:ret
atelsel endp
; ECH, erase chars in this line
atech: mov ax,dx ; get cursor position
mov bx,ax ; erase ax to bx
cmp byte ptr param,0 ; 0 argument
je atech1 ; e = yes
dec bl ; count from 1
atech1: 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 clrrev ; clear reverse video attribute
call clrunder ; clear underline attribute
mov extattr,0 ; clear extended attributes
ret
atsgr2: cmp bl,1 ; 1, set bold?
jne atsgr2a ; ne = no
jmp setbold ; set bold attribute
atsgr2a:cmp flags.vtflg,ttpt200 ; PT200 '2' = half intensity
jne atsgr3 ; ne = no, do next attrib test
cmp bl,2 ; PT200 - 2, set bold?
jne atsgr3 ; ne = no
jmp setbold ; set half intensity
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: test flags.vtflg,ttvt320+ttvt220 ; VT320/VT220?
jz atsgr8 ; z = no, 22-27 are VT220/320 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
or al,al ; 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
jmp atsetcur ; 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: cmp ninter,0 ; any intermediates?
je decid1 ; e = no, else not this item
jmp atdgnrc ; try Spanish NRC designator
decid1: mov ax,flags.vtflg ; get terminal ident type
mov cx,30 ; assumed length of asciiz string
mov si,offset v32str ; VT320 ident string
cmp ax,ttvt320 ; VT320?
je decid2 ; e = yes
mov si,offset v22str
cmp ax,ttvt220 ; VT220?
je decid2 ; e = yes
mov si,offset v102str
cmp ax,ttvt102 ; VT102?
je decid2 ; e = yes
mov si,offset v100str
cmp ax,ttvt100 ; VT100?
je decid2 ; e = yes
cmp ax,tthoney ; Honeywell?
je decid2 ; e = yes
mov si,offset v52str
cmp ax,ttvt52 ; VT52?
je decid2 ; e = yes
mov si,offset h19str
cmp ax,ttheath ; Heath-19 mode?
je decid2 ; e = yes
mov si,offset pt20str ; Prime PT200 string
decid2: cmp lparam,'>' ; this letter parameter?
jne decid3 ; ne = no
test al,ttvt320+ttvt220 ; VT320/VT220 mode?
jz decid4 ; z = 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: push si ; set LED indicators
call getled ; set si to term type (led) string
mov di,si
pop si
jc atled2 ; c = no leds 1..4, ignore
atled4: cmp param[si],0 ; zero argument?
jne atled3 ; ne = no, check further
mov al,led_off ; set all off
mov ah,al
mov [di+6],ax ; where dots go after name
mov [di+6+2],ax
atled1: test yflags,modoff ; mode line supposed to be off?
jnz atled2 ; nz = yes
push dx
call fmodlin ; update status line
pop dx
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
push di
add di,ax
add al,'1' ; add ascii offset for digit
mov [di+6],al ; turn the "LED" on by storing digit
pop di
jmp short atled1 ; update display and return
decsca proc near ; DEC Select Character Attributes
cmp ninter,1 ; one intermediate?
jne atll ; no, try led routine
cmp inter,'"' ; CSI Pn " q ?
jne decsca2 ; ne = no
cmp param,1 ; 0, 2 mean protected mode goes off
jne decsca1 ; ne = not 1, protected mode goes on
call setprot ; start protecting
ret
decsca1:call clrprot ; end protecting
decsca2:ret
decsca endp
; 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
cmp flags.vtflg,ttpt200 ; were we a PT200?
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
test yflags,modoff ; mode line supposed to be off?
jnz atrm1 ; nz = yes
call fmodlin ; update mode line
atrm1: ret
atsm: mov modeset,1 ; say we are setting modes
mov di,offset atrsm ; Reset/Set modes
jmp atreps ; repeat for all parms
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 yflags,lclecho ; (l) turn on local echoing
jmp short atrsmc2
atrsmc1:and yflags,not lclecho ; (h) turn off local echoing
atrsmc2:test yflags,modoff ; is mode line off?
jnz atrsmx ; nz = yes
push dx ; save cursor position
call fmodlin ; 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
call atrsflg ; set or reset it
test yflags,modoff ; mode line supposed to be off?
jnz atrsm5b ; nz = yes
push dx ; save cursor position
call fmodlin ; write mode line
pop dx
atrsm5b:ret
atrsm6: cmp al,3 ; 132/80 column mode change?
jne atrsm7 ; ne = no
mov al,curattr ; save current video attributes
mov ah,extattr ; and extended attributes
push ax
xor ah,ah ; high byte: not exiting Connect mode
and vtemu.vtflgop,not deccol; assume mode is reset
mov al,modeset ; pass set/reset request to chgdsp
or al,al
jz atrsm6a ; z = set 80 columns
or vtemu.vtflgop,deccol ; assume it will work (tell msy)
atrsm6a:call chgdsp ; call Change Display proc in msy
and vtemu.vtflgop,not deccol; assume mode is reset
cmp modeset,0 ; want 80 cols?
je atrsm6n ; e = yes, else 132 cols
cmp byte ptr low_rgt,79
jbe atrsm6b
or vtemu.vtflgop,deccol ; set the status bit
mov byte ptr low_rgt,132-1 ; screen capability
jmp short atrsm6e
atrsm6b:and vtemu.vtflgst,not deccol; turn off setup 132 col bit too
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:test flags.vtflg,ttd463+ttd470 ; D463/D470?
jnz atrsm6f ; nz = yes, no reset for DG terminals
CALL ATRES2 ; do partial reset of emulator
atrsm6f:pop ax
mov curattr,al ; restore saved items
mov extattr,ah
test flags.vtflg,ttd463+ttd470 ; D463/D470?
jz atrsm6g ; z = no
call frepaint ; repaint new screen
ret ; D463/D470 gets no other changes
atrsm6g:mov dx,low_rgt ; text lines (leave status line intact)
mov mar_top,0
mov mar_bot,dh ; reset scrolling region
mov dl,byte ptr low_rgt ; right margin
mov mar_right,dl
mov mar_left,0
xor dx,dx ; new cursor position is 0,0
mov cursor,dx
jmp atsetcur ; 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
; DECRLM (alt VT320 right/left write)
atrsm10:cmp al,34 ; ESC [ ? 34 h/l? Invoke special macro
jne atrsm10b ; ne = no
and vtemu.vtflgop,not vswdir; writing direction to normal
and vtemu.vtflgst,not vswdir; writing direction to normal
cmp modeset,0 ; resetting?
jne atrsm10a ; ne = no, setting
mov decrlm,0 ; writing direction to left to right
ret
atrsm10a:mov decrlm,1 ; writing direction to right to left
ret
; DECHEBM (alt VT320 keyboard map)
atrsm10b:cmp al,35 ; ESC [ ? 35 h/l? Invoke special macro
jne atrsm10d ; ne = no
cmp modeset,0 ; resetting?
jne atrsm10c ; ne = no, setting
call fvtkrmac ; perform on-line macro
ret
; code is located in file msy
atrsm10c:call fvtksmac ; do set macro
ret
atrsm10d:cmp al,36 ; DECHEM Hebrew encoding mode?
jne atrsm11 ; ne = no
cmp modeset,0 ; resetting?
jne atrsm10e ; ne = no
mov al,13 ; Hebrew NRC
mov ah,al ; GR = GL = 13
or vtemu.vtflgop,vsnrcm ; set NRC active bit
or vtemu.vtflgst,vsnrcm
and vtemu.vtflgop,not vscntl ; no 8-bit controls
jmp short atrsm10f
atrsm10e:mov al,17 ; DEC Multinational set (17)
xor ah,ah ; GLeft is ASCII (0)
and vtemu.vtflgop,not vsnrcm ; clear NRC active bit
and vtemu.vtflgst,not vsnrcm
atrsm10f:mov vtemu.vtchset,al
mov bx,offset emubuf ; temp table of char set idents
xchg ah,al ; order correctly
mov [bx],ax ; char sets for G0..G3
mov [bx+2],ax
call chrsetup ; invoke NRC
ret
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
test flags.vtflg,ttvt320+ttvt220 ; VT320/VT220 mode?
jz atrsm14 ; z = no
cmp vtemu.vtchset,0 ; ASCII?
je atrsm14 ; e = yes, no NRC
cmp vtemu.vtchset,13 ; 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
test flags.vtflg,ttvt320+ttvt220 ; VT320/VT220 mode?
jz atrsm16 ; z = no
mov ax,deckpam ; bit to control
jmp atrsflg ; control the flag and return
atrsm16:ret
; VT340 CSI number $ | number is 0 or 80 for 80 cols, 132 for 132 columns
; DECSCPP, set columns per page
atscpp: cmp inter,'$' ; correct intermediate letter?
jne atscpp2 ; ne = no, ignore
cmp ninter,1 ; one intermediate?
jne atscpp2 ; ne = no, ignore
mov modeset,1 ; assume 132 columns wanted
cmp param,80 ; 80 or 132 columns?
ja atscpp1 ; a = 132 columns
mov modeset,0 ; set to 80 columns
atscpp1:mov al,3 ; set up CSI ? 3 h/l command
jmp atrsm6 ; process that command
atscpp2: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,byte ptr low_rgt ; physical width
call vtsclr ; disabling status line clears it
ret
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 ax,oldterm ; terminal type at startup
mov flags.vtflg,ax ; 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 atsetcur ; 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 atsetcur ; 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
call revscn ; reverse everything on the screen
pop ax
atrss3: ret
; Self tests DECTST
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 atcts6 ; ne = no
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
jmp atreset ; reset everything
atcts3: ret
atcts4: or si,si ; initial arg?
jz atcts5 ; z = yes, skip it (examined above)
cmp param[si],1 ; power up test (0, 1) included?
ja atcts5 ; a = no, ignore printer/comms/repeats
or al,80H ; say we want reset
atcts5: ret
atcts6: cmp nparam,0 ; absence of parameters?
jne atcts5 ; ne = no, ignore sequence
jmp athoney ; try Honeywell ESC [ y ident response
atalign proc near ; Align screen, fill screen with 'E's
mov al,'E' ; char to use as filler
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:push ax ; save displayed char
push vtemu.vtflgst ; save setup flags
mov ax,vtemu.vtflgop ; operational flags
and ax,deccol ; get 80/132 column indicator
and vtemu.vtflgst,not deccol ; clear for set below
or vtemu.vtflgst,ax ; set it so reset preserves it
call atreset ; clear system
pop vtemu.vtflgst ; recover setup flags
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
pop ax ; recover displayed char in AL
mov emubuf,al ; keep it here while looping
atalig3:push cx
mov al,emubuf ; write screen full of this char
call atnrm ; write the 'E' or whatever
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: test flags.vtflg,ttvt102+ttvt100+tthoney ; VT102 etc?
jz atreq0 ; z = no, ignore
mov ttyact,0 ; group output for networks
mov al,CSI
call prtbout ; send CSI or ESC [
mov al,'3' ; we report only upon request
cmp param,0 ; was argument a zero?
jne atreq1b ; ne = no
mov al,'2' ; yes
atreq1b: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 ; sending speed index
mov al,';'
call prtbout
pop ax
cmp bl,lbaudtab-1 ; using the split speed entry?
jne atreq2a ; ne = no
mov al,[bx+1] ; get trailing receive speed (75 baud)
atreq2a:call prtnout ; receiving speed index
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 ttyact,1 ; end group output for networks
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,ttvt102 ; set VT102
mov oldterm,ttvt102 ; and remember it
and vtemu.vtflgop,not vscntl ; turn off 8-bit controls
mov al,anspflg ; preserve screen print flag
push ax
call atsres ; do soft reset of emulator
pop ax
mov anspflg,al
ret
decsc2: cmp param,62 ; go to VT2xx level?
jne decsc3 ; ne = no
test flags.vtflg,ttvt320+ttvt102 ; at VT300/VT102 level now?
jnz decsc3a ; nz = yes, don't change types
mov flags.vtflg,ttvt220 ; set VT220 mode
mov oldterm,ttvt220
jmp short decsc3b ; finish up
decsc3: cmp param,63 ; go to VT300 level?
jne decsc4 ; ne = no
decsc3a:mov flags.vtflg,ttvt320 ; set VT320 mode
mov oldterm,ttvt320
decsc3b:cmp param[2],2 ; Ps1, range here is 0, 1, 2
ja decsc4 ; a = out of range, ignore
mov al,anspflg ; preserve screen print flag
push ax
call atsres ; do soft reset of emulator
pop ax
mov anspflg,al
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
decsc5c:mov cx,param ; ANSI report:
cmp cx,2 ; 2, Keyboard action?
jne decsc6 ; ne = no
ret
decsc6: cmp cx,3 ; control representation?
jne decsc7 ; ne = no
ret ; say reset(acting on controls)
decsc7: cmp cx,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 cx,10 ; 10, Horizontal editing?
jne decsc9 ; ne = no
mov al,'4' ; permanently reset
ret
decsc9: cmp cx,12 ; 12, Send/Receive (local echo)?
jne decsc11 ; ne = no
test yflags,lclecho ; echoing on?
jz decsc12 ; z = no
dec al ; say set
ret
decsc11:cmp cx,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:mov cx,param
cmp cx,1 ; 1, cursor keys?
jne decsc22 ; ne = no
test vtemu.vtflgop,decckm ; set?
jz decsc31 ; z = no, reset
dec al
ret
decsc22:cmp cx,2 ; 2, ANSI mode
jne decsc24 ; ne = no
test vtemu.vtflgop,decanm ; set?
jz decsc31 ; z = no, reset
dec al
ret
decsc24:cmp cx,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 cx,4 ; 4, scrolling mode
je decsc31 ; e = yes always say reset (jump)
;
cmp cx,5 ; 5, screen
jne decsc28 ; ne = no
test vtemu.vtflgop,decscnm ; set (light background)?
jz decsc31 ; z = no, reset
dec al
ret
decsc28:cmp cx,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 cx,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 cx,8 ; 8, autorepeat?
jne decsc34 ; ne = no
dec al
ret ; say set
decsc34:cmp cx,18 ; 18, print Form Feed?
jne decsc36 ; ne = no
test anspflg,vtffp ; set?
jz decsc31 ; z = no, reset
dec al
ret
decsc36:cmp cx,19 ; 19, printer extent?
jne decsc38 ; ne = no
test anspflg,vtextp ; set?
jz decsc31 ; z = no, reset
dec al
ret
decsc38:cmp cx,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 cx,42 ; 42, NRC's
jne decsc42 ; ne = no
test flags.vtflg,ttvt320+ttvt220 ; VT320/VT220?
jz decsc31 ; z = no
test vtemu.vtflgop,vsnrcm ; NRC's active?
jz decsc31 ; z = no
dec al ; say enabled
ret
decsc42:cmp cx,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 cx,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 ttyact,0 ; group output for networks
mov al,CSI ; do standard report beginning
call prtbout
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 ttyact,1 ; end group output for networks
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
call fmodlin ; rewrite mode line
ret
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 ninter,0 ; set up atdcsnul for proper form
mov ttstate,offset atdcsnul ; not understood, consume til ST
ret
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,'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
call getbold ; returns ah with bold attr or 0
or ah,ah ; bold set?
jz atcrqm2 ; z = no
mov al,';'
call prtbout
mov al,'1' ; say bold is on
call prtbout
atcrqm2:call getunder ; underline
or cl,cl ; underline on?
jz atcrqm3 ; z = 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?
jz atcrqm4 ; z = no
mov al,';'
call prtbout
mov al,'5' ; say blinking is on
call prtbout
atcrqm4:test extattr,att_rev ; chars in reversed video?
jz atcrqm5 ; z = 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 VT100?
je atcrqp2 ; e = yes
cmp oldterm,tthoney ; Honeywell?
je atcrqp2 ; e = yes
cmp oldterm,ttvt102 ; VT102?
je atcrqp2 ; e = yes
cmp oldterm,ttvt320 ; how about VT320?
je atcrqp2 ; e = yes
jmp atcrqxx ; say invalid request
atcrqp2:mov ttyact,0 ; group output for networks
mov al,DCS ; '"p', conformance level
call prtbout
mov al,'0' ; valid request
call prtbout
mov al,'$'
call prtbout
mov al,61 ; assume VT102
cmp oldterm,ttvt100 ; VT100?
je atcrqp2a ; e = yes
cmp oldterm,tthoney ; Honeywell
je atcrqp2a ; e = yes
cmp oldterm,ttvt102 ; are we a VT102?
jne atcrqp3 ; ne = no
atcrqp2a: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 ttyact,0 ; group output for networks
mov al,DCS ; report prologue
call prtbout
mov al,'0' ; valid request
call prtbout
mov al,'$'
jmp prtbout
atcrqend:call prtbout ; report epilogue, al has char
mov ttyact,1 ; end group output for networks
mov al,STCHR ; string terminator
jmp prtbout
atcrqxx:mov ttyact,0 ; group output for networks
mov al,DCS ; report invalid request
call prtbout
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?
jne atcrqq1 ; ne = no
call tekinq ; get Tek screen state
jmp tekrcol ; restore palette
atcrqq0:mov ninter,0 ; setup atdcsnul for proper form
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 fdec2di
mov byte ptr [di],';'
inc di
mov ax,dparam[2] ; get second parameter
call fdec2di ; write ascii value
mov byte ptr [di],';'
inc di
mov ax,dparam[4] ; get third parameter
call fdec2di ; 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
; State machine to process DCS strings of type "p" (restore color palette)
; Enter with "p" char in AL.
tekrcol proc near
mov ttstate,offset tekrco1 ; next state is get parameter
mov ttstateST,offset tekrcost ; go here on ST
push es
push ds
pop es
mov cx,5 ; five words
xor ax,ax
mov di,offset param ; clear parameters Pc,Pu,Px,Py,Pz
cld
rep stosw
pop es
mov nparam,0 ; work on initial parameter first
ret
tekrco1:push bx
mov bx,nparam ; parameter number
shl bx,1 ; make it a word index
mov cx,param[bx] ; accumulated parameter
call getdec ; accumulate decimal value
mov param[bx],cx ; remember accumulation
pop bx
jnc tekrcos1 ; nc = got a digit char
inc nparam ; say have another complete parameter
cmp al,'/' ; this kind of separator?
je tekrco3 ; e = yes, finish
cmp al,';' ; break char is separator?
jne tekrco4 ; ne = no, decode current sequence
tekrco3:cmp nparam,5 ; have 5 params already?
jb tekrcos1 ; n = no, continue reading
tekrco4:call tekrpal ; process parameters in msgibm file
jmp tekrcol ; start over on next field
tekrcost:mov ttstate,offset atnrm ; get here on ST
mov ttstateST,offset atnorm ; default ST completion state
cmp nparam,5 ; enough parameters to finish cmd?
jb tekrcos1 ; b = no, abandon it
call tekrpal ; update from last data item
tekrcos1:ret
tekrcol endp
; Accumulate decimal value in CX using ascii char in al.
; Return with value in CX. Return carry clear if ended on a digit,
; return carry set and ascii char in al if ended on a non-digit.
getdec proc near
cmp al,'0' ; a number?
jb getdecx ; b = no, quit
cmp al,'9'
ja getdecx ; a = not a number, quit
sub al,'0' ; remove ascii bias
xchg cx,ax ; put char in cx, decimal value in ax
push dx ; save reg
push bx
mov bx,10
mul bx ; times ten for a new digit
pop bx
pop dx ; recover reg, ignore overflow
add al,cl ; add current digit
adc ah,0 ; 16 bits worth
xchg ax,cx ; rpt cnt back to cx
clc ; say found a digit
ret
getdecx:stc ; say non-digit (in al)
ret
getdec endp
; Device Status Reports
atdsr: mov di,offset atdsr1 ; routine to call
call atreps ; do for all parms
ret
; DSR workers
atdsr1: mov ax,param[si]
cmp lparam,0 ; any intermediate?
jne atdsr2 ; ne = yes, an intermediate
cmp ax,5 ; operating status report?
je rpstat ; e = yes
cmp ax,6 ; cursor position report?
je rpcup ; e = yes
ret
atdsr2: cmp lparam,'?' ; DEC mode queries for below?
jne atdsr3 ; no, skip them
cmp ax,6 ; VT340 cursor report?
je rpcup ; e = yes
cmp ax,15 ; printer status report?
je rpstap ; e = yes
cmp ax,25 ; UDK status?
jne atdsr3 ; ne = no
jmp rpudk ; do udk status rpt
atdsr3: cmp ax,26 ; keyboard type?
jne atdsr4 ; ne = no
jmp rpkbd ; do keyboard type report
atdsr4: cmp ax,256 ; WordPerfect Tek screen query?
jne atdsr5 ; ne = no
jmp tekrpt ; do Tek report
atdsr5: ret ; must have been an echo
rpstat: mov ttyact,0 ; group output for networks
mov al,CSI ; operating status query
call prtbout
mov al,'0' ; tell them we think we are OK
call prtbout
mov ttyact,1 ; end group output for networks
mov al,'n'
call prtbout
ret
rpcup: mov ttyact,0 ; group output for networks
mov al,CSI ; cursor position report
call prtbout
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 ttyact,1 ; end group output for networks
mov al,'R' ; final char
call prtbout
ret
rpstap: mov ttyact,0 ; group output for networks
mov al,CSI ; printer port query
call prtbout ; 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 ttyact,1 ; end group output for networks
mov al,'n' ; final char of response
call prtbout
ret
rpudk: mov ttyact,0 ; group output for networks
mov al,CSI ; response to UDK locked query
call prtbout
mov al,'?'
call prtbout
mov al,20 ; say keys are unlocked (locked=21)
call prtnout
mov ttyact,1 ; end group output for networks
mov al,'n' ; final char
call prtbout
ret
rpkbd: mov ttyact,0 ; group output for networks
mov al,CSI ; response to kbd type query
call prtbout
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 ttyact,1 ; end group output for networks
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 ttyact,0 ; group output for networks
mov al,CSI ; response to Tek query
call prtbout
mov al,'?'
call prtbout
mov di,offset emubuf ; working buffer
mov byte ptr [di],0 ; insert terminator
mov ax,256 ; first parameter
call fdec2di ; write ascii digits
mov byte ptr [di],';' ; separator
inc di
pop ax ; get screen height
call fdec2di
mov byte ptr [di],';' ; separator
inc di
pop ax ; get screen width
call fdec2di
mov byte ptr [di],';' ; separator
inc di
pop ax ; get number screen color (0, 1 or 16)
call fdec2di
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
cmp cx,1 ; last char?
ja tekrpt2 ; a = no
mov ttyact,1 ; end group output for networks
tekrpt2: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 prtbout ; 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 prtbout
ret
atrqts5:mov al,DCS ; User Preferred Supplemental Set
call prtbout ; report
mov al,'0' ; assume 94 byte set
cmp upss,94 ; 94 byte set?
je atrqts6 ; e = yes
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 prtbout
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 prtbout
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
test extattr,att_rev ; reverse video char writing on?
jz atrqps3 ; z = no
or al,8 ; set the bit
atrqps3:call getblink ; ah will be non-zero if blinking
or ah,ah ; blinking?
jz atrqps4 ; z = no
or al,4 ; set the bit
atrqps4:call getunder ; ah will be non-zero if underlining
or cl,cl ; underlining?
jz atrqps5 ; z = no
or al,2 ; set the bit
atrqps5:call getbold ; ax will be non-zero if bolding
or ah,ah ; bold?
jz atrqps6 ; z = no
or al,1 ; set the bit
atrqps6:call prtbout
mov al,';'
call prtbout
mov al,40h ; Satt (Selective params)
test extattr,att_protect ; is char protected?
jz atrqps6a ; z = no
or al,1 ; say char is protected
atrqps6a: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 prtbout
ret
; worker for Character set size reporting
atrqp15:cmp G0set+gsize,96 ; is G0 a 96 byte set?
jne atrqp16 ; ne = no
or al,1 ; say 96
atrqp16:cmp G1set+gsize,96 ; is G1 a 96 byte set?
jne atrqp17 ; ne = no
or al,2 ; say 96
atrqp17:cmp G2set+gsize,96 ; G2 set?
jne atrqp18
or al,4 ; say 96
atrqp18:cmp G3set+gsize,96 ; 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 prtbout
mov al,'2' ; tabs
call prtbout
mov al,'$'
call prtbout
mov al,'u'
call prtbout
mov cl,mar_right ; right most column number
inc cl ; number of columns
xor ch,ch
push dx ; save dx
xor dx,dx ; 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 prtbout
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 atsetcur ; 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 atsetcur ; 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
call setrev ; set reversed video
mov curattr,ah ; gather main attributes
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
; 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.
; Also CSI Pn; Pn; Pn; Pn ~ invokes Lotus macro PRODUCT
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 atsetcur ; 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 atsetcur ; set cursor
atsasd endp
atssdt proc near ; Select Status Line Type, DECSSDT
cmp inter,'$' ; correct intermediate char?
je atssdt1 ; e = yes
cmp ninter,0 ; no intermediates?
jne atssdt0 ; ne = no
call fproduct ; do PRODUCT macro
atssdt0: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 fclrmod ; 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 fmodlin ; 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
; VT52 compatibility mode routines.
; Return to ANSI mode.
v52ans: or vtemu.vtflgop,decanm ; turn on ANSI flag
mov ax,oldterm ; terminal type at startup
cmp ax,ttvt52 ; was VT52 the prev kind?
jne v52ans1 ; ne = no
mov ax,ttvt320 ; use VT320
v52ans1:mov oldterm,ax
mov flags.vtflg,ax ; restore it
call chrdef ; set default char sets
call atsc ; save cursor status
test yflags,modoff ; mode line supposed to be off?
jnz v52ans2 ; nz = yes
call fmodlin ; rewrite mode line
v52ans2:ret
; 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
cmp al,'F' ; enter VT52 graphics mode?
jne v52sgm1 ; ne = no, exit and return to ASCII
jmp mkdecspec ; 'G' make DEC special graphics in G0
v52sgm1:jmp mkascii ; make ASCII in G0
; 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 bx,low_rgt ; lower right corner
cmp bh,dh ; on status line?
jae h19ed1 ; ae = no
mov bh,dh ; put end on status line
h19ed1: call vtsclr ; clear it
ret
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 atsetcur ; do it
xor ax,ax ; clear screen from (0,0)
mov bx,low_rgt ; to lower right corner
call vtsclr ; clear it
ret
h19erl: xor al,al ; erase whole line
mov bl,byte ptr low_rgt ; physical width
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 cl,extattr
call setrev ; ESC p set reversed video
mov curattr,ah ; store new attribute byte
ret
h19hxrv:mov ah,curattr ; get current cursor attribute
mov cl,extattr
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 atsetcur ; 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 ax,param ; insert line
or ax,ax ; any args?
jne insli1 ; ne = yes
inc ax ; insert one line
insli1: mov scroll,al ; 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 atsetcur ; reposition cursor and return
insli3: ret
inslin endp
dellin proc near
mov ax,param ; delete line(s)
or ax,ax ; any args?
jne delli1 ; ne = yes
inc ax ; insert one line
delli1: mov scroll,al ; 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 atsetcur ; restore cursor
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
jnz 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 ; BH has insert/delete code
mov dx,cursor ; logical cursor
cmp decrlm,0 ; host writing direction active?
je insdel11 ; e = no
call hldirection
insdel11:
cmp thisline,0 ; is line already single width?
je insdel1 ; e = yes
add dl,dl ; double the cursor column
add cx,cx ; double repeat count
test flags.vtflg,ttd463+ttd470 ; D463/D470?
jz insdel1 ; z = no
shl mar_right,1 ; this one doubles the margins
insdel1:mov bl,mar_right
inc bl ; number of screen columns
sub bl,dl ; width - cursor
cmp cl,bl ; skipping more than screen width?
jbe insdel2 ; be = no
mov cl,bl ; limit to screen width please
insdel2:
; 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.
mov bl,cl ; offset
xor ch,ch
or bh,bh ; ins or del?
jl insdel5 ; l = delete
; Insert processor
mov cl,mar_right ; right margin
sub cl,dl ; minus cursor location
mov dl,mar_right ; start at right margin
insdel4:push cx
push dx
sub dl,bl ; back up by offset
call hldirection
call getatch ; read char from vscreen
pop dx
push dx
call hldirection
call qsetatch ; write it farther to the right
pop dx
pop cx
dec dl ; backup one column
loop insdel4
jmp short insdel7
; Delete processor
insdel5:mov cl,mar_right ; right margin
sub cl,dl ; minus starting position
sub cl,bl ; minus displacement (num deletes)
inc cl ; count column 0
or cl,cl
jle insdel7
insdel6:push cx
push dx
add dl,bl ; look to right
call hldirection
call getatch ; read char from vscreen
pop dx
push dx
call hldirection
call qsetatch ; write it farther to the left
pop dx
pop cx
inc dl ; next column
loop insdel6
insdel7:mov cl,bl ; fill count
xor ch,ch
jcxz insdel9 ; z = empty
mov ah,scbattr ; get fill
mov al,' '
insdel8:push cx
xor cl,cl ; extended attributes
push dx
call hldirection
call qsetatch ; write new char
pop dx
inc dl ; next column
pop cx
loop insdel8
insdel9:mov dx,cursor ; logical cursor again
cmp thisline,0 ; is line already single width?
je insde10 ; e = yes
add dl,dl ; move to double char cell
test flags.vtflg,ttd463+ttd470 ; D463/D470?
jz insde10 ; z = no
shr mar_right,1 ; this one doubles the margins
insde10:call atsetcur ; set it to current char
mov dl,dh ; rows to update
call touchup
mov dx,cursor ; in case we are called indirectly
ret
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,dx ; 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,mar_right ; number of columns on screen - 1
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 getatch ; read char (al) and attribute (ah)
pop dx ; logical attribute to cl
push dx
call direction ; set dx to desired position
call qsetatch ; write char (al) and attribute (ah)
pop dx ; and logical attribute is in cl
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
mov ah,scbattr ; screen background
xor cl,cl ; extended attribute
mov al,' '
call qsetatch ; write char
pop dx
pop cx
inc dl ; next column
loop linsgl2 ; repeat for all characters
mov dl,dh ; rows to touchup
call touchup
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,dx ; 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 cl,mar_right ; number of columns on the screen - 1
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 getatch ; read char (al) and attribute (ah)
pop dx ; extended attribute is in cl
shl dl,1 ; double the column number
push dx
call direction ; set dx to desired position
call qsetatch ; write char and attribute
pop dx
inc dl ; move to second column of double
push dx
call direction ; set dx to desired position
mov al,' ' ; space as filler
call qsetatch ; write that char
pop dx
dec dl
shr dl,1
dec dl
pop cx
loop lindbl1
mov dl,dh ; rows to touchup
call touchup
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
cmp ninter,0 ; unwanted intermediates?
jne anspr4a ; ne = got one, illegal here
call fpntchk ; check printer
call pntext ; do whole screen or scrolling extent
jmp atsetcur ; reposition cursor and return
ansprt1:cmp ax,1 ; 1 (print current line)?
jne ansprt4 ; ne = no
call fpntchk ; check for printer ready
call pntlin ; print current line
mov al,LF
call fpntchr
call fpntflsh ; flush printer buffer
jmp atsetcur ; 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
call ftrnprs ; toggle mode line PRN indicator
anspr4a:ret
ansprt5:cmp ax,5 ; 5 (auto print enable)?
jne ansprtx ; ne = no
call fpntchk ; check printer, ignore carry ret
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
call ftrnprs ; toggle on mode line PRN indicator
ret
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
call ftrnprs ; 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
call fpntchr ; print char in al, ignore errors
ret
; CSI seen
ansmc0a:call ansmc5 ; playback previous matches
call atpclr ; clear parser
mov pardone,offset ansmc4 ; where to go when done
mov parfail,offset ansmc5 ; where to go when fail, playback
mov ttstate,offset ansmc3 ; get numeric arg
mov emubuf,CSI ; stuff CSI
mov emubufc,1
ret
; Escape 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,'[' ; left square bracket?
je ansmc2a ; e = yes
call ansmc5 ; playback previous matches
call fpntchr ; print char in al, ignore errors
ret
ansmc2a:inc emubufc ; say matched "ESC ["
mov emubuf+1,al ; store left square brace
call atpclr ; clear parser
mov pardone,offset ansmc4 ; where to go when done
mov parfail,offset ansmc5 ; where to go when fail, playback
mov ttstate,offset ansmc3 ; get numeric arg
ret
; CSI or ESC [ seen
ansmc3: inc emubufc ; another char
mov bx,emubufc ; qty stored
mov emubuf[bx-1],al ; store it
mov ah,al ; check for C0 and C1 controls
and ah,not 80h
cmp ah,20h ; control range?
jb ansmc5 ; b = yes, mismatch, playback
jmp atparse ; parse control sequence
; parse succeeded, al has Final char
ansmc4: cmp al,'i' ; correct Final char?
jne ansmc5 ; ne = no, playback previous matches
cmp lparam,0 ; missing letter parameter?
jne ansmc5 ; ne = no, mismatch
cmp ninter,0 ; missing intermediates?
jne ansmc5 ; ne = no, mismatch
mov cx,nparam ; number of parameters
xor bx,bx ; subscript
ansmc4a:mov ax,param[bx]
add bx,2 ; next param
cmp ax,4 ; CSI 4 i MC OFF?
je ansmc4b ; e = yes, stop printing
loop ansmc4a ; keep trying all parameters
jmp short ansmc7 ; forget this one, start over
; Media OFF found
ansmc4b:mov ttstate,offset atnrm ; return to normal state
call fpntflsh ; flush printer buffer
test anspflg,vtcntp ; was printing active?
jz ansmc7 ; z = no
and anspflg,not vtcntp ; yes, disable print controller
call ftrnprs ; toggle mode line PRN indicator
ret
; 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 fpntchr ; print it, ignore errors
loop ansmc6 ; do all matched chars
pop si
pop ax
mov emubufc,cx ; clear this counter
ansmc7: mov ttstate,offset ansmc ; reset state to the beginning
ret
ansmc endp
dgprt proc near ; RS F ? <char> DG Print routines
mov ttstate,offset dgprt1 ; get the <char>
ret
dgprt1: mov ttstate,offset atnrm ; reset state
cmp al,0 ; Simulprint off?
jne dgprt2 ; ne = no
mov al,7 ; reform to be VT autoprint off
dgprt2: cmp al,1 ; Simulprint on?
jne dgprt3 ; ne = no
mov al,8 ; reform to be VT autoprint on
dgprt3: cmp al,3 ; Print Pass Through on?
jne dgprt4 ; ne = no
dgprt3a: ; RS F ` alternative to RS F ? 3
test anspflg,vtcntp ; controller print already enabled?
jnz dgprt7 ; 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 dgmc ; do transparent print
call ftrnprs ; toggle on mode line PRN indicator
ret
dgprt4: cmp al,8 ; VT-style autoprint on?
jne dgprt5 ; ne = no
call fpntchk ; check printer, ignore carry ret
test anspflg,vtautop ; is print already enabled?
jnz dgprt7 ; nz = yes, leave trnprs intact
and anspflg,not vtautop ; say auto-print disabled to toggle on
call ftrnprs ; toggle on mode line PRN indicator
ret
dgprt5: cmp al,7 ; VT-style autoprint off?
jne dgprt6 ; ne = no
test anspflg,vtautop ; check state of print flag
jz dgprt7 ; z = off already
or anspflg,vtautop ; say auto-print enabled to toggle off
call ftrnprs ; toggle mode line PRN indicator
ret
dgprt6: cmp al,':' ; Print Screen?
jne dgprt7 ; ne = no
mov ah,mar_bot ; save margins
mov al,mar_top
push ax
mov mar_top,0 ; set to full screen height
mov al,byte ptr low_rgt+1 ; bottom text row
mov mar_bot,al
push cursor
xor dx,dx ; cursor to home
call dgprtwn ; print this window
pop cursor
pop ax
mov mar_top,al ; restore margins
mov mar_bot,ah
dgprt7: ret
dgprt endp
dgppb proc near ; RS F x <n> Printer Pass back to host
mov bx,offset dgppb1 ; call back routine
jmp get1n ; setup consume one <n>
dgppb1: mov al,dgescape ; send RS R x 0 cannot set
call prtbout ; out, no echo
mov al,'R'
call prtbout
mov al,'x'
call prtbout
mov al,'0' ; say cannot set NRC printer mode
call prtbout
ret
dgppb endp
; State machine active while DG Simulprint is On. Copies all chars to the
; printer until and excluding Simulprint Off (RS F ? 0) has been received
; or the emulator reset.
; New char is in al.
dgmc proc near
mov ttstate,offset dgmc ; stay in this state
cmp al,dgescape ; start a new sequence?
je dgmc1 ; e = yes
mov emubufc,0 ; say no matched chars
call fpntchr ; print char in al, ignore errors
ret
; RS seen
dgmc1: call ansmc5 ; playback previous matches
mov ttstate,offset dgmc2 ; get next char
mov emubufc,1 ; one char matched
mov emubuf,al ; store it
ret
dgmc2: cmp al,'F' ; 'F' part of RS F ? 2
jne dgmc7 ; ne = no
inc emubufc ; say matched "RS F"
mov emubuf+1,al ; store it
mov ttstate,offset dgmc3 ; get query char
ret
; RS F seen
dgmc3: cmp al,'?' ; 'F' part of RS F ? 2
jne dgmc4 ; ne = no
inc emubufc ; say matched "RS F ?"
mov emubuf+1,al ; store it
mov ttstate,offset dgmc5 ; get final char
ret
dgmc4: cmp al,'a' ; RS F a alternative?
jne dgmc7 ; ne = no
jmp short dgmc8 ; finish up
dgmc5: cmp al,'2' ; RS F ? seen, correct final char?
je dgmc8 ; e = yes
dgmc7: call ansmc5 ; playback previous matches
call fpntchr ; print char in al, ignore errors
mov ttstate,offset dgmc ; start over
ret
dgmc8: mov ttstate,offset atnrm ; return to normal state
call fpntflsh ; flush printer buffer
test anspflg,vtcntp ; was printing active?
jz dgmc9 ; z = no
and anspflg,not vtcntp ; yes, disable print controller
mov al,6 ; send Control-F to host
call prtbout ; output, no echo
call ftrnprs ; toggle mode line PRN indicator
dgmc9: ret
dgmc endp
pntlin proc near ; print whole line given by dx
push ax
push bx
push cx
push dx
xor ch,ch
mov cl,mar_right ; number of columns - 1
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
cmp decrlm,0 ; host writing direction active?
jne pntlin2 ; ne = yes
pntlin1:push cx
call getatch ; read char (al) and attribute (ah)
pop cx ; and extended bit pair to cl
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:push cx
call getatch ; read char (al) and attribute (ah)
pop cx
inc dl ; inc to next column
call fpntchr ; print the char (in al)
jc pntlin5 ; c = printer error
loop pntlin3 ; do cx columns
pntlin4:mov al,cr ; add trailing cr for printer
call fpntchr
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
mov al,LF
call fpntchr
jc pntext2
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 fpntchr ; 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.
; Active only under local writing direction control
direction proc near
test vtemu.vtflgop,vswdir ; writing left to right?
jz direct1 ; z = yes, no changes needed
sub dl,mar_right ; right margin column number
neg dl ; make a positive value again
direct1:ret
direction endp
; Like direction, but functions if host writing direction decrlm is active
; as well as local control
hldirection proc near
cmp decrlm,0 ; host mode inactive?
jne hldirect1 ; ne = no, obey
test vtemu.vtflgop,vswdir ; writing left to right?
jz hldirect2 ; z = yes, no changes needed
hldirect1:sub dl,mar_right ; right margin column number
neg dl ; make a positive value again
hldirect2:ret
hldirection 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,dh ; 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 bx,low_rgt ; bh = bottom row number
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 ax,dx ; cursor
pop dx
mov bx,low_rgt ; erase from cursor to end of screen
call vtsclr ; clear it
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 al,1
shl bl,1 ; physical column is twice logical
erinli1:cmp bl,byte ptr low_rgt ; wider than the physical screen?
jb erinli2 ; b = no, not wider than screen
mov bl,byte ptr low_rgt ; physical width
erinli2:cmp al,byte ptr low_rgt
jb erinli3
mov al,byte ptr low_rgt
erinli3:call vtsclr ; clear it
ret
erinline endp
; General erasure command which skips over protected chars.
; Preset margins and cursor to obtain all three erasure kinds.
erprot proc near ; erase cursor to end of region
mov cursor,dx ; preserve cursor
erprot1:push dx
call direction
call getatch ; read a char, get attributes
pop dx
cmp protectena,0 ; is protected mode enabled?
je erprot4 ; e = no, erase all
test cl,att_protect ; protected mode?
jnz erprot2 ; nz = yes, retain it
erprot4:xor cl,cl ; clear extended attributes
mov ah,scbattr ; background attributes
mov al,' '
push dx
call direction
call qsetatch ; quietly update char
pop dx
erprot2:inc dl ; next column
cmp dl,mar_right ; did right margin?
jbe erprot1 ; be = no
mov dl,mar_left ; rest to left margin
inc dh ; next line down
cmp dh,mar_bot ; did the last row?
jbe erprot1 ; be = no
erprot3:mov dl,byte ptr cursor+1 ; starting line, dh is ending line
mov dh,mar_bot
call touchup ; repaint part of screen
mov dx,cursor
ret
erprot 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,mar_right
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,mar_right ; 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,mar_right ; 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,mar_right
sub ah,al
mov al,ah
jns vtsclr6
mov al,mar_right ; 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
mov al,linescroll[bx+si] ; get horizontal scroll value
mov linescroll[bx],al ; copy too
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
mov linescroll[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
mov al,linescroll[bx] ; get per line horizontal scroll
mov linescroll[bx+si],al ; copy too
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
mov linescroll[bx],0
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 VT 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
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
xor al,al ; get a zero
mov cx,slen ; clear linetype array
mov di,offset linetype
rep stosb
mov cx,slen
mov di,offset linescroll ; clear horiz scroll per line
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 ax,flags.vtflg ; get current terminal type
cmp ax,tttek ; non-text?
je ansin3 ; e = yes
mov oldterm,ax ; remember it here for soft restarts
ansin3: 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-2 ; yes, make it the maximum (128)
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 cx,low_rgt
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 ; any intermediates?
je atreset ; e = none, it is a reset
atxres1:ret ; ignore command
atxreset endp
atreset proc near ; Reset-everything routine
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jnz atres9
test tekflg,tek_sg ; special graphics active?
jz atres9 ; z = no
call tekend ; exit special graphics
atres9: mov ax,apcstring ; seg of apcmacro memory area
or ax,ax ; empty?
jz atres10 ; z = yes
mov es,ax
mov ah,freemem
int dos ; free that memory
atres10:mov apcstring,0
mov bracecount,0 ; APC-macro worker variables
mov cursor,0 ; cursor is at 0,0
mov havesaved,0 ; unmark saved cursor section
mov al,1 ; assume underline cursor
test vtemu.vtflgst,vscursor ; kind of cursor in setup
jnz atres0 ; nz = underline
inc 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
mov decrlm,0 ; host writing direction to left-right
and vtemu.vtflgop,not vscntl ; assume no 8-bit controls
mov ax,oldterm ; get terminal at entry time
or ax,ax ; inited yet? (initing Tek too)
jnz atres0a ; nz = yes
mov ax,ttvt320 ; pretend initing VT320
jmp short atres0b
atres0a:mov flags.vtflg,ax ; use it again
atres0b:test ax,ttvt102+ttvt100+tthoney+ttpt200 ; VT100 class?
jnz atres1 ; nz = yes, turn on ansi mode
test ax,ttvt320+ttvt220 ; VT320/VT220?
jz atres1a ; z = 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 ax,low_rgt ; virtual screen lower right corner
mov mar_bot,ah ; logical bottom of screen
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jz atres1d ; z = no
mov al,79 ; trim to 80 col screen
atres1d:mov mar_right,al ; logical right edge of screen
mov mar_left,0 ; DG left/right margins
mov old8bit,-1 ; flags.remflg d8bit status, clear
xor al,al ; ax is top/bottom margin
mov dgwindow,ax ; init to first window to full screen
mov dgwindcnt,1 ; DG window count, 1 = full screen
mov cx,25
xor bx,bx
atres1i:mov dgwindcomp[bx],al ; set lines to uncompressed
inc bx
loop atres1i
xor ax,ax
mov savdgmar,ax ; clear DG saved margins
mov protectena,al ; disable protected fields
mov blinkdis,al ; disable blink disable
mov dgroll,1 ; DG roll enabled
mov dgaltid,ax ; DG alternate model id, clear it
mov dghscrdis,al ; DG horz scroll disable is disabled
mov cx,16
xor bx,bx
atres1e:mov dgcursave[bx],ax ; clear DG cursor named save area
add bx,2
loop atres1e
mov cx,slen/2
xor bx,bx
atres1f:mov word ptr linescroll[bx],ax ; clear DG per line horiz scroll
add bx,2
loop atres1f
mov dgnum,ax ; DG worker word, to be safe
call dgcrossoff ; DG turn off crosshair
mov dgcross,al ; DG crosshair activity, off
mov dglinepat,0ffffh ; DG line pattern, default all dots
mov dgcaller,offset atign ; DG default callback, ignorance
mov numdigits,al ; more DG stuff
mov param[0],ax ; setup call to atleds
xor si,si
call atleds ; clear the LED indicators
call cpytabs ; initialize tab stops
test flags.vtflg,ttvt320+ttvt220+ttvt102+ttvt100+tthoney+ttd463+ttd470
jz atres1c ; z = no
mov al,vtemu.vtchset ; setup char set
cmp al,1 ; in range for NRCs?
jb atres1c ; b = no
cmp al,13 ; 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 atres1h ; ne = no
mov flags.modflg,1 ; say now owned by us
atres1h:xor ax,ax ; not exiting connect mode, 80 col
test vtemu.vtflgst,deccol ; need 132 columns?
jz atres1g ; z = no, use 80 columns
inc al ; say set 132 column mode
atres1g:call chgdsp ; call Change Display proc in msy
and vtemu.vtflgop,not deccol; assume mode is reset (80 cols)
cmp byte ptr low_rgt,79 ; is screen narrow now?
jbe atres2 ; be = yes
or vtemu.vtflgop,deccol ; set the status bit
; ATRES2 used in 80/132 col resetting
ATRES2: mov cx,slen ; typically 24 but do max lines
xor di,di
xor al,al
atres3: mov linetype[di],al ; clear the linetype array to single
mov linescroll[di],al ; horizontal scroll per line
inc di
loop atres3
mov ah,att_normal ; get present normal coloring
test vtemu.vtflgop,vsscreen ; want reverse video?
jz atres4 ; z = no
call revideo ; reverse them
atres4: mov scbattr,ah ; set background attributes
mov curattr,ah ; and cursor attributes
mov extattr,0 ; no reverse video, no underline
mov dx,cursor ; get cursor
call atsetcur ; set cursor
call atsctyp ; set right cursor type
xor ax,ax ; starting location
mov bx,low_rgt ; ending location
call vtsclr ; clear the whole screen
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 fmodlin ; write normal mode line
pop dx
atres5: test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jz atres6 ; z = no
or vtemu.vtflgop,decawm ; Autowrap active
or vtemu.vtflgst,decawm ; Autowrap active
atres6: call atpclr ; clear parser work area
xor ax,ax
mov parstate,ax ; reset parser
mov emubufc,ax ; clear work buffer
mov atwrap,al ; clear wrap flag
mov SSptr,ax ; clear single shift flag
mov insmod,al ; reset insert mode
mov h19stat,al ; clear heath extended status byte
mov h19ctyp,1 ; Heath-19 cursor to underline
mov anspflg,al ; clear printer flag
call atsc ; save cursor information
jmp atnorm ; set normal state
atreset endp
; Re-initialization routine. Called when Term was called but screen was
; restored from a previously saved screen, etc.
ansrei proc near
mov dx,cursor
call atsctyp ; set cursor type [rbv]
mov ax,vtemu.vtflgst ; setup
or ax,vtemu.vtflgop ; operational
test ax,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
and vtemu.vtflgop,not deccol
ansre2: jmp stblmds ; check settable modes, set flags
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 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 ax,flags.vtflg ; get current terminal type
cmp ax,tttek ; non-text?
je stblm10 ; e = yes
cmp ax,oldterm ; same as before?
je stblm10 ; e = yes, skip over soft reset
mov oldterm,ax ; 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
push es
push ds
pop es
xor al,al ; get a zero
mov di,offset linetype ; line type to single width chars
mov cx,slen ; screen length
cld
rep stosb ; clear
mov di,offset linescroll ; line horizontal scroll to none
mov cx,slen
rep stosb
pop es
and vtemu.vtflgop,not decanm
test flags.vtflg,ttvt320+ttvt220+ttvt102+ttvt100+tthoney+ttpt200
jz stblm10 ; z = no, not ansi class
or vtemu.vtflgop,decanm ; set ansi flag bit
stblm10:test flags.vtflg,ttd463+ttd470 ; D463/D470?
jz stblm10a ; z = no
mov cx,24 ; emulation screen lines
xor al,al
xor bx,bx
stblm10b:or al,dgwindcomp[bx] ; is any line compressed (!= 0)?
inc bx ; if so remember as non-zero
loop stblm10b
or al,al ; found any compressed lines?
jz stblm10e ; z = no
test vtemu.vtflgop,vscompress ; allowed to use graphics for it?
jnz stblm10d ; nz = no, use 132 column text mode
test tekflg,tek_active+tek_sg ; special graphics mode active?
jnz stblm10e ; nz = yes
stblm10c:call dgsettek ; setup special graphics mode
jmp short stblm10e
stblm10d:mov al,3 ; prep call on atrsm6, 132/80 col
mov modeset,1 ; say want 132 columns
call atrsm6 ; common worker
cmp byte ptr low_rgt,79
jbe stblm10c ; did not work, use graphics anyway
stblm10e:mov al,flags.remflg ; get 7/8 bit configuration
and al,d8bit ; select the control bit
cmp old8bit,al ; changed?
je stblm10a ; e = no
mov old8bit,al ; save new state
mov vtemu.vtchop,-1 ; force change below
stblm10a: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,13 ; 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: test vtemu.vtflgst,vswdir ; writing direction set?
jz stblm3c ; z = no
mov decrlm,0 ; yes, suppress host indicator
stblm3c:mov ax,iniflgs ; flags at last entry
xor ax,vtemu.vtflgst ; find which setup ones have changed
test ax,deccol ; screen width?
jz stblm3b ; z = no, don't touch it
mov ax,vtemu.vtflgst ; Setup bits
and ax,deccol ; select screen width
and vtemu.vtflgop,not deccol ; clear operational flag bit
or vtemu.vtflgop,ax ; set current width desired
or al,ah ; collapse all bits
mov modeset,al ; non-zero if 132 columns
mov al,3 ; setup call to atrsm6
call atrsm6 ; adjust display width
stblm3b:cmp vtclear,1 ; screen need updating?
mov vtclear,0 ; preserves cpu status bits
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
push es
mov ax,seg data1
mov es,ax
mov ah,scbattr ; reset saved attribute also
mov es:savecu+svattr_index,ah
pop es
stblm8: cmp flags.modflg,2 ; mode line enabled and owned by host?
je stblm9a ; e = yes, leave it alone
call fclrmod ; clear the mode line
test yflags,modoff ; mode line supposed to be off?
jnz stblm9a ; nz = yes
call fmodlin ; 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
call frepaint
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 between text and Tek graphics modes. No arguments.
; Text terminal type remembered in byte OLDTERM.
ans52t proc FAR
mov ax,flags.vtflg
cmp ax,tttek ; in Tek mode now?
je ans52b ; e = yes, exit Tek mode
test tekflg,tek_active ; doing Tek sub mode?
jnz ans52b ; nz = yes
test ax,ttd463+ttd470 ; DG 463/D470?
jnz ans52e ; nz = yes, go into DG graphics mode
test denyflg,tekxflg ; is Tek mode disabled?
jnz ans52a ; nz = yes, disabled
mov oldterm,ax ; save text terminal type here
call atsc ; save cursor and associated data
mov flags.vtflg,tttek ; set Tek mode
mov tekflg,tek_tek ; not a sub mode
call tekini ; init Tek to switch screens
ans52a: call atnorm
ret
ans52b: call tekend ; exit Tek graphics mode
mov ax,oldterm
or ax,ax ; inited yet?
jnz ans52c ; nz = yes
mov ax,ttvt320 ; fall back for initing
ans52c: mov flags.vtflg,ax ; say text terminal now
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jnz ans52f ; nz = yes, cursor is ok already
call atrc ; restore cursor etc
call atsc ; save cursor etc
ans52f: mov tekflg,0 ; say not doing tek submode now
mov al,atctype
call atsctyp ; set correct cursor type
test yflags,modoff ; is mode line off?
jnz ans52d ; nz = yes
push dx ; save cursor position
call frepaint ; restore text screen
call fmodlin ; write mode line
pop dx
ans52d: call atnorm
ret
; DG D473 graphics mode entry
ans52e: mov oldterm,ax ; save text terminal type here
call dgsettek ; switch to DG graphics
jmp short ans52d
ans52t endp
; Honeywell VIP 3.1 i.d. string [FD]
athoney proc near
cmp flags.vtflg,tthoney ; Honeywell mode?
jne athone3 ; ne = no, ignore
mov ttyact,0 ; group for networks
mov cx,VIPstrl ; length of string
mov si,offset VIPstr ; ptr to string
cld
athone1:lodsb ; get a byte
push cx ; save regs
push si
call prtbout ; print WITHOUT echo
pop si
pop cx
cmp cx,1 ; last char?
ja athone2 ; a = not yet
mov ttyact,1 ; end of network grouping
athone2:loop athone1 ; loop for all characters
athone3:jmp atnorm
athoney endp
athoncls proc near ; Honeywell ESC accent screen clear
cmp nparam,0 ; absence of parameters?
jne athoncl1 ; ne = no, fail
cmp ninter,0 ; any intermediates?
jne athoncl2 ; ne = yes, not this item
cmp flags.vtflg,tthoney ; doing Honeywell emulation?
jne athoncl1 ; ne = no
xor dx,dx ; move cursor to Home position
call ereos ; erase to end of screen
xor dx,dx
jmp atsetcur ; set cursor and return
athoncl1:ret
athoncl2:jmp atdgnrc ; try Norwegian/Danish NRC designation
athoncls endp
; Data General D463/D470 support routines
; Data General mode C0 control codes
dgctrl proc near
test anspflg,vtcntp ; printing desired?
jz dgctrl1 ; z = no
call fpntchr ; print char in al
dgctrl1:and ax,001fh ; clear for word use below
mov di,ax ; use AL as a word index
shl di,1
jmp dgc0[di] ; dispatch on DG C0 control codes
dgctrl endp
; Consume ESC ... Final
dgansi proc near
mov ttstate,offset dgansi1 ; come here til end or break
ret
dgansi1:cmp al,20h ; control code?
jb dgansi2 ; b = yes, break
cmp al,'[' ; end of ANSI escape sequence part?
je dgansi2 ; e = yes, get parms, intermediates
cmp al,40h ; parameters, intermediates?
jae dgansi3 ; ae = no, consider it to be a final
dgansi2:ret ; else stay in this state
dgansi3:jmp atnorm ; reset state to normal
dgansi endp
dgesc proc near ; Parse Data General RS commands
mov dgnum,0 ; clear numerical result
mov ttstate,offset dgesc1 ; set up to get next char
ret
dgesc1: mov bx,offset dgesctab ; dispatch table
mov ttstate,offset atnrm ; reset state
jmp atdispat ; dispatch on char in AL
dgesc endp
; Parse RS F/G <letter><DGnumber>(repeated)
; F/G has been read, letter is next
dgFSERIES:mov ttstate,offset Fdisp ; dispatcher for incoming RS F
ret
Fdisp: mov ttstate,offset atnrm ; normal state
mov bx,offset fltable ; table of letters
jmp atdispat ; dispatch to action routine
dgGSERIES:mov ttstate,offset Gdisp ; dispatcher for incoming RS G
ret
Gdisp: mov ttstate,offset atnrm ; normal state
mov bx,offset gltable ; table of letters
jmp atdispat ; dispatch to action routine
dgRSERIES:mov ttstate,offset Rdisp ; dispatcher for incoming RS R
ret
Rdisp: mov ttstate,offset atnrm ; normal state
mov bx,offset rltable ; table of letters
jmp atdispat ; dispatch to action routine
; DG <n>,<nn>,<nnn> processors. Enter with BX holding callback address.
; Returns number in dgnum and resets state to atnrm.
; get one DG numeric
get1n: mov ttstate,offset getnum ; worker routine
mov dgnum,0 ; clear numerical result
mov numdigits,1 ; wanted qty of digits
mov dgcaller,bx ; call back address
ret
; get two DG hex digits
get2n: mov ttstate,offset getnum ; worker routine
mov dgnum,0 ; clear numerical result
mov numdigits,2 ; wanted qty of digits
mov dgcaller,bx ; call back address
ret
; get three DG hex digits
get3n: mov ttstate,offset getnum ; worker routine
mov dgnum,0 ; clear numerical result
mov numdigits,3 ; wanted qty of digits
mov dgcaller,bx ; call back address
ret
get3loc:mov ttstate,offset getloc ; get three DG Location digits
mov dgnum,0
mov numdigits,3
mov dgcaller,bx
ret
getloc proc near
mov bl,numdigits ; number of digits remaining
xor bh,bh
or al,al ; is it truely null (RS L cmd stuff)?
jz getloc3 ; z = yes, exit now
and al,00011111b ; keep only five lower bits
mov emubuf[bx],al ; save byte
dec numdigits ; say one more digit done
dec bx
or bx,bx ; done all?
jz getloc1 ; z = yes
ret ; else stay in state getloc
getloc1:mov cx,3 ; three digits
getloc2:mov bx,cx
mov al,emubuf[bx] ; stored in reverse order
push cx
mov bx,dgnum ; get current value
mov cl,5
shl bx,cl ; times 32
add bl,al ; add current digit
adc bh,0
mov dgnum,bx ; keep result
pop cx
loop getloc2
clc ; clear carry to say not null term
jmp short getloc4
getloc3:stc ; set carry to say ended on NULL
getloc4:mov bx,dgcaller ; get callback address
mov dgcaller,offset atign ; reset default DG callback processor
mov ttstate,offset atnrm ; set normal state
jmp bx ; go to callback address
getloc endp
; Return binary number in dgnum. When done it resets state to atnrm,
; clears callback address. Note that this proc accepts ALL bytes and uses
; only the four lower bits, regardless of what the DG manuals suggest.
getnum proc near
and al,0fh ; keep lower four bits
mov cl,4
mov bx,dgnum ; get current value
shl bx,cl ; times 16
and al,0fh ; keep lower four bits
add bl,al ; add current digit
adc bh,0
mov dgnum,bx ; keep result
dec numdigits ; say one more digit done
cmp numdigits,0 ; done all?
jz getnum2 ; z = yes
ret ; else stay in this state
getnum2:mov bx,dgcaller ; get callback address
mov dgcaller,offset atign ; reset default DG callback processor
mov ttstate,offset atnrm ; set normal state
jmp bx ; go to callback address
getnum endp
out2n proc near ; send <nn> report from value in AL
push cx
mov ch,al ; preserve a copy
mov cl,4
shr al,cl ; get high nibble
and al,0fh
add al,'0' ; ascii bias
call prtbout
mov al,ch ; recover copy
and al,0fh ; get low nibble
add al,'0'
call prtbout
pop cx
ret
out2n endp
out2na proc near ; send <nn> report from value in AL
push cx
mov ch,al ; preserve a copy
mov cl,4
shr al,cl ; get high nibble
and al,0fh
add al,'@' ; ascii bias
call prtbout
mov al,ch ; recover copy
and al,0fh ; get low nibble
add al,'@'
call prtbout
pop cx
ret
out2na endp
dgign1n proc near ; ignore a <n> command
mov bx,offset atnorm ; ignore the <n>
jmp get1n
dgign1n endp
dgign2n proc near ; ignore a <nn> command
mov bx,offset atnorm ; ignore the <nn>
jmp get2n
dgign2n endp
dgprtfm proc near ; Control-A DG print form
mov cursor,dx ; save cursor location
dgprtf1:mov dl,mar_right ; start at right margin
mov cl,dl
sub cl,mar_left ; minus left
inc cl
xor ch,ch ; number of columns to do
dgprtf3:push cx
call dgprta ; get char which would be printed
pop cx
cmp al,' ' ; space?
jne dgprtf4 ; ne = no, end scan here
dec dl ; scan backward another column
loop dgprtf3
dgprtf4:jcxz dgprtf6 ; z = empty line
mov dl,mar_left ; start at left margin
dgprtf5:push cx
push dx
call dgprta ; get printable
call fpntchr ; print char in al
pop dx
pop cx
jc dgprtf7 ; c = printer error
inc dl
loop dgprtf5 ; do count
dgprtf6:mov al,CR ; line terminator for printer
push dx
call fpntchr
pop dx
jc dgprtf7 ; c = printer error
mov al,LF
push dx
call fpntchr
pop dx
jc dgprtf7 ; c = printer error
inc dh ; next row down
cmp dh,mar_bot ; below window now?
jbe dgprtf1 ; be = no
dgprtf7:mov al,6 ; Control-F to host when done
call prtbout ; output, no echo
mov dx,cursor
ret
dgprtfm endp
dgprta proc near ; worker, report printable char at dx
call getatch ; read char (al) and attribute (ah)
cmp protectena,0 ; protected mode enabled
je dgprta1 ; e = no
test cl,att_protect ; protected mode?
jnz dgprta2 ; nz = yes, use a space
ret ; else use as-is
dgprta1:test ah,att_bold ; bold?
jnz dgprta3 ; nz = yes, use as-is
dgprta2:mov al,' ' ; replace with space
dgprta3:ret
dgprta endp
dgprtwn proc near ; Control-Q DG print window
mov cursor,dx ; save cursor location
dgprtw1:mov dl,mar_right ; start at right margin
mov cl,dl
sub cl,mar_left
inc cl
xor ch,ch ; number of columns to do
dgprtw3:push cx
call dgprtb ; get char which would be printed
pop cx
cmp al,' ' ; space?
jne dgprtw4 ; ne = no, end scan here
dec dl ; scan backward another column
loop dgprtw3
dgprtw4:jcxz dgprtw6 ; z = empty line
mov dl,mar_left ; start at left margin
dgprtw5:push cx
push dx
call dgprtb ; get printable
call fpntchr ; print char in al
pop dx
pop cx
jc dgprtw7 ; c = printer error
inc dl
loop dgprtw5 ; do count
dgprtw6:mov al,CR ; line terminator for printer
push dx
call fpntchr
pop dx
jc dgprtw7 ; c = printer error
mov al,LF
push dx
call fpntchr
pop dx
jc dgprtw7 ; c = printer error
inc dh ; next row down
cmp dh,mar_bot ; below window now?
jbe dgprtw1 ; be = no
dgprtw7:mov al,6 ; Control-F to host when done
call prtbout ; output, no echo
mov dx,cursor
ret
dgprtwn endp
dgprtb proc near ; worker to yield printable char
call getatch ; read char (al) and attribute (ah)
test al,80h ; high bit set?
jnz dgprtb1 ; nz = yes, use a space
cmp al,20h ; in printables?
ja dgprtb2 ; a = yes
dgprtb1:mov al,' ' ; replace with space
dgprtb2:ret
dgprtb endp
dgrevidon:mov ah,curattr ; RS D Control-V reverse video on
call setrev ; reverse video on
mov curattr,ah ; store new attribute byte
ret
dgrevidoff:mov ah,curattr ; RS E Control-B reverse video off
call clrrev ; 2, reverse video off
mov curattr,ah ; store new attribute byte
ret
dgblkena:mov blinkdis,0 ; Control-C DG blink enable
ret
dgblkdis:mov blinkdis,1 ; Control-D DG blink disable
ret
dgblkon proc near ; Control-N DG Blink on
cmp blinkdis,0 ; disabled?
jne dgblkon1 ; ne = blink is disabled
mov ah,curattr ; get current cursor attribute
call setblink ; blink enable
mov curattr,ah ; store new attribute byte
dgblkon1:ret
dgblkon endp
dgblkoff proc near ; Control-O DG Blink off
mov ah,curattr ; get current cursor attribute
call clrblink ; blink disable
mov curattr,ah ; store new attribute byte
ret
dgblkoff endp
dgwinhome proc near ; Control-H DG window home
mov dl,mar_left ; want to skip protected chars too
mov dh,mar_top
mov cursor,dx ; remember for protected checking
jmp dgsetcur ; do protected mode positioning
dgwinhome endp
dguson proc near ; Control-T DG underscoring on
mov ah,curattr ; get current cursor attribute
call setunder
mov curattr,ah ; store new attribute byte
ret
dguson endp
dgusoff proc near ; Control-U DG underscoring off
mov ah,curattr ; get current cursor attribute
call clrunder
mov curattr,ah ; store new attribute byte
ret
dgusoff endp
dgdimon proc near ; Control-\ DG dim on
mov ah,curattr ; get current cursor attribute
call clrbold
mov curattr,ah ; store new attribute byte
ret
dgdimon endp
dgdimoff proc near ; Control-] DG dim off
mov ah,curattr ; get current cursor attribute
call setbold
mov curattr,ah ; store new attribute byte
ret
dgdimoff endp
dgsfc proc near ; RS A <color>, set foreground color
mov ttstate,offset dgsfc1 ; state to get next char
ret
dgsfc1: mov ttstate,offset atnrm ; reset state
test flags.vtflg,ttd463 ; D463?
jz dgsfc2 ; z = no, D470
mov ah,curattr ; current coloring
test al,0fh ; setting to background?
jnz dgsfc1a ; nz = no
mov cl,4
rol ah,cl ; get background coloring
dgsfc1a:and ah,0fh ; keep foreground
mov dg463fore,ah ; polygon foreground coloring
ret
dgsfc2: cmp al,100 ; select ACM mode?
je dgsfc5 ; ne = no
dgsfc3: and al,0fh ; keep lower 4 bits
jz dgsfc4 ; z = black
xor al,8 ; invert DG intensity bit
jnz dgsfc4
or al,8 ; pick up dark grey as second except'n
dgsfc4: mov ah,curattr
and ah,not 0Fh ; remove foreground
or ah,al ; set new foreground
mov ah,scbattr
and ah,not 0Fh
or ah,al
mov curattr,ah ; save it
mov scbattr,ah
ret
dgsfc5: mov ah,att_normal ; get normal background colors
mov scbattr,ah
mov curattr,ah ; set current to them
dgsfcx: ret
dgsfc endp
dgsbc proc near ; RS B <color>, set background color
mov ttstate,offset dgsbc1 ; state to get next char
ret
dgsbc1: mov ttstate,offset atnrm ; reset state
test flags.vtflg,ttd463 ; D463?
jnz dgsbcx ; nz = yes, ignore command
cmp al,100 ; select ACM mode?
je dgsbc2 ; e = yes
and al,0fh ; mask out all but IBM PC background
jz dgsbc3 ; z = black
and al,7 ; remove IBM PC blinking bit
mov cl,4
shl al,cl ; move bits to high nibble
dgsbc3: mov ah,curattr
and ah,0fh ; remove background
or ah,al ; set new background
mov curattr,ah ; save it
mov ah,scbattr
and ah,0fh ; remove background
or ah,al ; set new background
mov scbattr,ah ; save it
ret
dgsbc2: mov ah,att_normal ; get normal background colors
mov scbattr,ah ; set current to them
mov curattr,ah ; set current to them
dgsbcx: ret
dgsbc endp
dgeol proc near ; Control-K DG erase cursor to eol
mov ax,dx ; cursor position
mov bx,ax
mov bl,mar_right ; end of line
call atsclr ; erase from ax to bx
ret
dgeol endp
dgeeos proc near ; RS F F DG erase cursor to end/scrn
jmp erprot
dgeeos endp
dgescn proc near ; RS F E DG erase from 0,0 to eos
xor dh,dh
mov dl,mar_left ; left margin, top row
call dggetmar ; get margins for this window
call atsetcur ; set cursor
mov ah,curattr
call clrunder ; clear underline attribute
call clrblink ; clear blink
call setbold ; aka clear dim
call clrrev ; clear reverse video attribute
mov curattr,ah ; and cursor attributes
mov extattr,0 ; clear extended attributes
xor ax,ax ; erase from 0,0
mov bh,byte ptr low_rgt+1 ; to end of screen
mov bl,vswidth-1
call atsclr ; clear screen
ret
dgescn endp
dgewin proc near ; Control-L DG erase window
mov ah,mar_top ; from top line of window
mov bh,mar_bot ; to bottom line of window
mov al,mar_left ; left margin
mov bl,mar_right ; right margin
cmp savdgmar,0 ; saved permanent margin?
je dgewin1 ; e = no, mar_left/right are permanent
mov al,byte ptr savdgmar ; use permanent l/r margins
mov bl,byte ptr savdgmar+1
dgewin1:call atsclr ; clear the area
jmp dgwinhome ; do DG window home
dgewin endp
dgsleft proc near ; RS F C <nn> DG Scroll Left
mov bx,offset dgslef1 ; get <nn>
jmp get2n
dgslef1:mov ax,dgnum ; qty columns to scroll
jmp dglrworker ; do common worker
dgsleft endp
dgsright proc near ; RS F D <nn> DG Scroll Right
mov bx,offset dgsrig1 ; get <nn>
jmp get2n
dgsrig1:mov ax,dgnum
neg ax ; go right
jmp dglrworker ; do common worker
dgsright endp
; Worker to assist dgsleft/dgsright horizontal scroll. Enter with AX holding
; the additional scroll value, negative for scrolling left. Updates array
; linescroll.
dglrworker proc near
cmp dghscrdis,0 ; horiz scrolling disabled?
je dglrwor1 ; e = no
ret ; else ignore request
dglrwor1:mov bl,mar_top ; do entire DG window
xor bh,bh
mov cl,mar_bot
xor ch,ch
sub cx,bx
inc cx ; number of lines in the window
cmp cl,byte ptr low_rgt+1 ; includes whole screen?
jbe dglrwor2 ; be = no
inc cx ; include status line
dglrwor2:push cx
mov cl,linescroll[bx] ; get horz scroll value
xor ch,ch
add cx,ax ; accumulate scroll
jge dglrwor3 ; ge = non-negative
xor cx,cx ; set to zero
dglrwor3:cmp cx,127 ; max scroll
jbe dglrwor4 ; be = in limits
mov cl,127 ; set to max left
dglrwor4:cmp linescroll[bx],cl ; any change?
je dglrwor5 ; e = no
mov linescroll[bx],cl ; set scroll
push dx
mov dl,bl
mov dh,bl ; start/stop line numbers
call touchup ; repaint just this line
pop dx
dglrwor5:inc bx ; next line
pop cx
loop dglrwor2
ret
dglrworker endp
dginsl proc near ; RS F H DG Insert Line in window
push dx ; save cursor
mov param,0 ; set up ANSI call
call inslin ; do insert line, can scroll
pop dx ; recover cursor
jmp atsetcur ; reset cursor
dginsl endp
dgdell proc near ; RS F I DG Delete Line in window
mov scroll,1 ; line count
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
ret
dgdell endp
dgnarrow proc near ; RS F J DG select normal spacing
mov cx,dgwindcnt ; number of windows
xor bx,bx
jcxz dgnarr3 ; z = none
inc cx ; let implied last window be seen
dgnarr1:cmp dh,byte ptr dgwindow[bx+1] ; look at window bottom edge
jbe dgnarr3 ; be = cursor is in this window
add bx,2 ; skip two margin bytes
loop dgnarr1 ; next window
dgnarr2:ret
dgnarr3:mov cx,dgwindow[bx] ; get mar_top and mar_bot (ch)
push cx ; save margins for touchup below
mov bl,cl ; mar_top
xor bh,bh
sub ch,cl ; mar_bot - mar_top = lines in win -1
xchg ch,cl
xor ch,ch
inc cx
xor ax,ax ; zero and make ah a changed flag
dgnarr4:xchg al,dgwindcomp[bx] ; set this window to normal width
add ah,al ; remember if window line were wide
xor al,al ; get zero again
inc bx
loop dgnarr4 ; do all lines in the window
mov cl,byte ptr low_rgt+1 ; see if any screen lines are wide
inc cl ; text lines
xor ch,ch
xor bx,bx
xor al,al
dgnarr5:cmp dgwindcomp[bx],0 ; count wide lines
je dgnarr6 ; e = narrow
inc al
jmp short dgnarr7 ; one wide line is enough to count
dgnarr6:inc bx
loop dgnarr5
dgnarr7:pop cx ; margins
test tekflg,tek_active+tek_sg ; special graphics mode active?
jz dgnarr8 ; z = no
or ah,ah ; any line widths changed?
jz dgnarr7a ; z = no
push dx
mov dx,cx ; cx = saved margins
call touchup ; dl, dh are start stop rows
pop dx
dgnarr7a:ret
dgnarr8:or al,al ; count of wide lines
jz dgnarr9 ; z = all are narrow, go to 80 cols
ret ; leave screen as-is with wide line(s)
dgnarr9:mov al,3 ; prep call on atrsm6, 132/80 col
mov modeset,0 ; say want 80 columns
jmp atrsm6 ; common worker
dgnarrow endp
dgwide proc near ; RS F K DG select compressed spacing
mov cx,dgwindcnt ; number of windows
xor bx,bx
jcxz dgwide3 ; z = none, means one as whole screen
inc cx ; let implied last window be seen
dgwide1:cmp dh,byte ptr dgwindow[bx+1] ; look at window bottom edge
jbe dgwide3 ; be = cursor is in this window
add bx,2 ; skip two margin bytes
loop dgwide1 ; next window
dgwide2:ret
dgwide3:mov cx,dgwindow[bx] ; get mar_top and mar_bot (ch)
push cx ; save them for touchup below
mov bl,cl ; mar_top
xor bh,bh
sub ch,cl ; mar_bot - mar_top = lines in win -1
xchg ch,cl
xor ch,ch
inc cx
mov ax,1 ; al is set, ah is changed flag
dgwide5:xchg al,dgwindcomp[bx] ; set this line to wide width
dec al ; convert old 1 to a zero
add ah,al ; accumulate changes
mov al,1 ; get a 1 again
inc bx
loop dgwide5 ; do all lines in the window
pop cx ; margins
test vtemu.vtflgop,vscompress ; allowed to use graphics for it?
jnz dgwide8 ; nz = no, use 132 column text mode
test tekflg,tek_active+tek_sg ; special graphics mode active?
jnz dgwide7 ; nz = yes
dgwide6:push cx
push dx
call dgsettek ; setup special graphics mode
pop dx
pop cx
ret
dgwide7:or ah,ah ; any changes to width?
jz dgwide7a ; z = no
push dx
mov dx,cx ; saved margins
call touchup ; dl, dh are start stop rows
pop dx
dgwide7a:ret
dgwide8:mov al,3 ; prep call on atrsm6, 132/80 col
mov modeset,1 ; say want 132 columns
call atrsm6 ; common worker
cmp byte ptr low_rgt,79
jbe dgwide6 ; did not work, use graphics anyway
ret
dgwide endp
; Toggle Normal/Compressed modes from the keyboard.
dgnctoggle proc far
mov dx,cursor ; get cursor
mov bl,dh ; get row
xor bh,bh
cmp dgwindcomp[bx],0 ; normal mode?
je dgnctog4 ; e = yes, do compressed
call dgnarrow ; do normal
ret
dgnctog4:call dgwide ; do compressed
ret
dgnctoggle endp
dgdelc proc near ; RS K DG Delete char
mov param,0 ; set up ANSI call for one char
jmp atdelc ; do delete
dgdelc endp
dgilbm proc near ; RS F [ Insert line between margins
mov al,dghscrdis ; save horz scrolling disable flag
push ax ; save til the end
mov dghscrdis,1 ; disable horz scrolling for this cmd
mov cursor,dx ; save this
mov dl,mar_left ; start at the left side
mov dh,mar_bot ; bottom of window
or dh,dh ; row zero?
jz dgilbm2 ; z = yes, just clear the line
dgilbm1:dec dh ; up one row
call getatch ; read a char
inc dh ; go down a row
call qsetatch ; write the char
inc dl ; next column
cmp dl,mar_right ; off end of row yet?
jbe dgilbm1 ; be = no
or dh,dh ; finished top row?
jz dgilbm2 ; z = yes
dec dh ; redo this one row up
mov dl,mar_left ; reset to left window margin
cmp dh,byte ptr cursor+1 ; finished cursor row yet?
jae dgilbm1 ; ae = no
dgilbm2:mov dx,cursor ; clear line cursor was on
mov al,mar_left ; from left margin
mov bl,mar_right ; to right window margin
call erinline ; clear the window line
mov dl,dh
mov dh,mar_bot ; lines changed
call touchup ; redisplay the new material
mov dx,cursor
pop ax ; recover horz scroll disable flag
mov dghscrdis,al
ret
dgilbm endp
dgdlbm proc near ; RS F \ Delete line between margins
mov al,dghscrdis ; get horizontal scroll disable flag
push ax ; save til the end
mov dghscrdis,1 ; disable horz scrolling for this cmd
mov cursor,dx ; save cursor position
mov dl,mar_left ; start at the left side
dgdlbm1:inc dh ; down one row
call getatch ; read a char
dec dh ; go up a row
call qsetatch ; write the char
inc dl ; next column
cmp dl,mar_right ; off end of row yet?
jbe dgdlbm1 ; be = no
inc dh ; redo this one row down
mov dl,mar_left ; reset to left window margin
cmp dh,mar_bot ; finished bottom row yet
jbe dgdlbm1 ; be = no
mov dh,mar_bot ; clear last line in window
mov al,mar_left
mov bl,mar_right
call erinline ; clear the window line
pop ax ; recover horz scroll disable flag
mov dghscrdis,al
mov dx,cursor
mov dl,dh ; region changed
mov dh,mar_bot
call touchup
ret
dgdlbm endp
dgscs proc near ; RS F S <nn> DG Select Char Set
mov bx,dgscs1 ; setup for <nn> value
jmp get2n
dgscs1: mov bx,dgnum ; get DG char set idents
cmp bl,1fh ; last hard char set
jbe dgscs2 ; be = in the hard sets
mov bl,20h ; specify default soft set of trash
dgscs2: or bl,bl ; use "keyboard language"?
jnz dgscs3 ; nz = no
mov bl,vtemu.vtchset ; get setup char set
cmp bl,13 ; top of the NRCs
jbe short dgscs4 ; as keyboard language
xor bx,bx ; default to ASCII
dgscs3: mov bl,dgchtab[bx] ; translate to Kermit idents
dgscs4: cmp GLptr,offset G0set ; are we shifted out?
jne dgscs5 ; ne = yes, presume G1set
mov Gsetid,bl ; new set ident for G0
jmp short dgscs6
dgscs5: mov Gsetid+1,bl ; new set ident for G1
dgscs6: mov bx,offset Gsetid ; pass list of sets to setup
jmp chrsetup ; go make the new set
dgscs endp
dgalign proc near ; RS F > char DG fill screen with char
mov ttstate,offset dgalig1 ; get char
ret
dgalig1:mov ttstate,offset atnrm ; reset state
jmp atalig1 ; do DEC alignment work, char in AL
dgalign endp
dggrid proc near ; RS F 9 char DG fill screen with grid
mov al,'#' ; set grid char in standard place
jmp atalig1 ; do DEC alignment work, char in AL
dggrid endp
dgrolldis:mov dgroll,0 ; Control-S DG roll disable
ret
dgrollena:mov dgroll,1 ; Control-R DG roll enable
ret
dghsena:mov dghscrdis,0 ; RS F ^ DG horiz scroll enable
mov dx,cursor
jmp atsetcur ; set cursor to cause screen update
dghsdis:mov dghscrdis,1 ; RS F ] DG horiz scroll disable
ret
dgpton: call setprot ; RS F L DG Protect on
ret
dgptoff:call clrprot ; RS F M DG Protect off
ret
protena:mov protectena,1 ; RS F V DG Protect enable
ret ;
protdis:mov protectena,0 ; RS F W DG Protect disable
ret ;
dg78bit proc near ; RS F U <n> DG Select 7/8 bit ops
mov bx,dg78bit1 ; get <n>
jmp get1n
dg78bit1:cmp dgnum,1 ; 0 is 7 bit, 1 is 8 bit
ja dg78bit3 ; a = illegal value, ignore
je dg78bit2 ; e = 1
and flags.remflg,not d8bit ; 7-bit, chop DG high bit
ret
dg78bit2:or flags.remflg,d8bit ; 8-bit
dg78bit3:ret
dg78bit endp
dgdhdw proc near ; RS R E <n> DG Double high/wide
mov bx,offset dgdhdw1
jmp get1n ; set up for <n> arg
dgdhdw1:mov ax,dgnum ; get <nn> result
or ax,ax ; 2 and above are double highs
jz dgdhdw2
mov al,2 ; map double highs to 2
jmp linedbl ; make line double width
dgdhdw2:jmp linesgl ; make single width
dgdhdw endp
dgs25l proc ; RS F z <n> DG go to/set status line
mov bx,offset dgs25l1 ; prep for <n> mode value
jmp get1n
dgs25l1:mov ax,dgnum ; get mode
or ax,ax ; 0, 25th line is status?
jnz dgs25l2 ; nz = no
mov param,1 ; turn on regular mode line
jmp atssdt1 ; do main worker
dgs25l2:cmp al,3 ; blank the line?
jne dgs25l3 ; ne = no
jmp atssdt1 ; do main worker
cmp al,2 ; use as ordinary text?
jne dgs25l3 ; ne = no
ret ; ignore this request
dgs25l3:cmp al,1 ; get msg for line?
je dgs25l4 ; e = yes
ret
dgs25l4:mov bx,offset dgs25l5 ; prep for <nn> text
jmp get2n
dgs25l5:mov dspcmain,dx ; save cursor in special area
mov dspstate,dsptype ; say on status line
mov al,mar_left
mov ah,mar_right
mov dspmsave,ax ; save margins
mov mar_left,0 ; set left to screen left
call fclrmod ; clear the line
and yflags,not modoff ; say modeline is not toggled off
mov flags.modflg,2 ; say mode line is owned by host
mov dh,byte ptr low_rgt+1 ; bottom text line
inc dh ; status line
xor dl,dl ; absolute left margin
call atsetcur ; set cursor
cmp dgnum,0 ; chars of text
je dgs25l7 ; e = yes
mov ttstate,offset dgs25l6 ; come here for text
ret
dgs25l6:mov ttstate,offset atnrm ; reset state
call atnrm ; write the character
dec dgnum ; one less to do
cmp dgnum,0 ; done?
jle dgs25l7 ; le = yes
ret ; stay on status line
dgs25l7:mov dx,dspcmain ; restore cursor
mov ax,dspmsave ; saved margins
mov mar_left,al
mov mar_right,ah
mov dspstate,0 ; no longer on mode line
jmp atsetcur ; set cursor
dgs25l endp
dgnscur proc near ; RS F } <n> <n> DG cursor named save
mov bx,offset dgnscu1 ; get <n> memory cell (name, 0..15)
jmp get1n
dgnscu1:mov ax,dgnum ; get cell number
mov word ptr emubuf,ax ; save here
mov bx,offset dgnscu2 ; get <n> save (0) / restore (1)
jmp get1n
dgnscu2:mov bx,word ptr emubuf ; get named subscript
mov ax,dgnum ; get op code
cmp ax,1 ; save?
jb dgnscu3 ; b = save
ja dgnscu4 ; a = illegal, ignore
mov al,dgctypesave[bx] ; get cursor size/type
mov atctype,al ; active type
call csrtype ; set it
mov dx,dgcursave[bx] ; restore cursor position from storage
mov cursor,dx ; remember for protected checking
jmp dgsetcur ; set the cursor DG style
dgnscu3:mov dgcursave[bx],dx ; save cursor
mov al,atctype ; get cursor type
mov dgctypesave[bx],al ; save
dgnscu4:ret
dgnscur endp
dgsps proc near ; DG dual emulation set split screen
mov ttstate,offset dgsps1 ; RS R A 0 <nn><n> or RS R A 1 <nn>
ret
dgsps1: mov bx,offset atnrm ; setup to ignore command
cmp al,1 ; 0 or 1 expected
ja dgsps3 ; a = illegal, ignore
je dgsps2 ; e = case 1 <nn>
jmp get3n ; case 0 <nn><n> as <nnn>
dgsps2: jmp get2n
dgsps3: ret
dgsps endp
dgdcs proc near ; RS F q <nn><nn> Dealloc Char Sets
mov bx,offset dgdcs1 ; ignore for now
jmp get2n
dgdcs1: mov bx,offset atnrm
jmp get2n
dgdcs endp
dgdefch proc near ; RS F R <char> 12<nn>'s Def Char
mov ttstate,dgdefc1 ; get and discard char
mov emubufc,0 ; set counter
ret
dgdefc1:inc emubufc ; count a <nn> pair
cmp emubufc,12 ; done all?
jae dgdefc2 ; ae = yes
mov bx,offset dgdefc1 ; absorb 12 <nn> pairs
jmp get2n
dgdefc2:mov emubufc,0 ; clear counter
jmp atnorm ; reset state
dgdefch endp
dgrchr proc near ; RS F d DG Read Chars Remaining
mov al,dgescape ; response string
call prtbout
mov al,'o'
call prtbout
mov al,'9'
call prtbout
mov al,'0' ; high part of 10 bit count
;graphics mov al,'_'
call prtbout
mov al,'0' ; low part of 10 bit count
;graphics mov al,'_'
call prtbout
ret
dgrchr endp
dgresch proc near ; RS F e <n><n> DG Reserve Character
mov bx,offset atnorm ; discard
jmp get2n
dgresch endp
dgskl proc near ; RS F f <n> DG Set Kbd Language
mov bx,offset dgskl1
jmp get1n ; get parameter
dgskl1: mov ax,dgnum ; 0=setup, 1=DG Int, 2=Latin1
cmp ax,2 ; in range?
ja dgskl4 ; a = no
cmp ax,1 ; DG International?
je dgskl2 ; e = yes
ja dgskl3 ; a = no, Latin1
mov al,vtemu.vtchset ; get setup char set
mov dgkbl,al ; store keyboard language ident
ret
dgskl2: mov dgkbl,20 ; DG International
ret
dgskl3: mov dgkbl,16 ; Latin1
dgskl4: ret
dgskl endp
dgsdo proc near ; RS R B <n><n><n> Set Device Options
mov bx,offset dgsdo1 ; get first <n>
jmp get1n
dgsdo1: mov bx,offset atnrm ; get second and third <n>'s
jmp get2n ; discard all
dgsdo endp
dgsfield:mov bx,offset dgsfie1 ; RS F C <ss><rr> Field attributes
jmp get2n ; get first <nn>
dgsfie1:mov bx,offset atnrm ; discard proc
jmp get2n ; get second <nn>
dgspage:mov bx,offset dgspag1 ; RS F D <ss><rr> Page attributes
jmp get2n ; get first <nn>
dgspag1:mov bx,offset atnrm ; discard proc
jmp get2n ; get second <nn>
dgsetw proc near ; RS F B <nn><n>.. Set windows
mov dgwindcnt,0 ; count of windows entries
mov emubuf+4,0 ; normal(0)/compressed (!0) flag
dgsetw1:mov bx,offset dgsetw2 ; next processor
jmp get2n ; get a <nn> window length
dgsetw2:mov ax,dgnum
mov word ptr emubuf,ax ; save around get1n work
mov bx,offset dgsetw2a ; get <n> 0/1, compressed mode
jmp get1n
dgsetw2a:mov ax,dgnum
mov emubuf+4,al ; save copy for just this window
mov ax,word ptr emubuf ; <nn> length, 0 (end) to 24
or ax,ax ; end of set indicator?
jnz dgsetw2b ; nz = no
mov ax,24 ; pseudo end
dgsetw2b:xchg al,ah ; put row in ah
mov bx,dgwindcnt ; get subscript
cmp bx,24 ; too many windows? (24 == DG limit)
ja dgsetw7 ; a = yes, else accept data
inc bx
mov dgwindcnt,bx ; update counter (1 == one window)
dec bx
shl bx,1 ; index words
or bx,bx ; initial window?
jnz dgsetw3 ; nz = no
xor al,al ; start at 0,0
jmp short dgsetw4
dgsetw3:mov al,byte ptr dgwindow[bx-1] ; previous ending line
inc al ; start this window down one line
dgsetw4:add ah,al ; new mar_bot = new mar_top + skip
dec ah ; count lines from zero
cmp ah,byte ptr low_rgt+1 ; bottom of displayable screen?
jb dgsetw5 ; b = no
mov ah,byte ptr low_rgt+1 ; clamp to that bottom
dgsetw5:mov dgwindow[bx],ax ; save [al=mar_top,ah=mar_bot] pair
mov al,ah ; get current bottom
mov ah,byte ptr low_rgt+1 ; last text line
mov dgwindow[bx+2],ax ; fill remaining space with next wind
push bx ; setup new margins, keep window ptr
mov dghscrdis,0 ; horz scroll disable is disabled
mov cx,slen ; max screen length
mov al,mar_left
xor bx,bx
dgsetw6:mov linescroll[bx],al ; horiz scroll left margin to edge
inc bx
loop dgsetw6
pop bx ; recover current line count in bx
mov al,emubuf+4 ; get compressed/normal for this wind
mov dh,byte ptr dgwindow[bx+1]; set cursor to bottom row of window
or al,al ; to regular width?
jnz dgsetw7 ; nz = no, to compressed
call dgnarrow ; to normal width
jmp short dgsetw8
dgsetw7:call dgwide ; compress things
dgsetw8:mov bx,dgwindcnt ; get window count
or bx,bx ; any windows (0 = no)
jz dgsetw9
dec bx ; count from 0
shl bx,1 ; count words
mov al,byte ptr low_rgt+1 ; last text line on screen (typ 23)
cmp byte ptr dgwindow[bx+1],al ; DG limit of 24 lines?
jb dgsetw1 ; b = not reached yet, keep going
dgsetw9:call dgshome ; do necessary DG Screen Home
ret
dgsetw endp
dgwwa proc near ; Control-P col row
mov ttstate,offset dgwwa1 ; DG Write window address (win rel)
ret ; get raw binary col
dgwwa1: mov emubuf,al ; save col
mov ttstate,offset dgwwa2 ; get raw binary row
ret
dgwwa2: mov ttstate,offset atnrm ; reset state
cmp al,127 ; 127 means use current row
je dgwwa3 ; e = yes
add al,mar_top ; relative to window top
mov dh,al ; set cursor row
dgwwa3: xor al,al ; get a zero
xchg al,emubuf ; get raw column, clear temp word
cmp al,127 ; 127 means use current column
je dgwwa4 ; e = yes
add al,mar_left ; add left margin
mov dl,al ; new cursor position
dgwwa4: cmp dh,mar_bot ; below bottom of window?
jbe dgwwa5 ; be = no, in bounds
mov dh,mar_bot ; peg at bottom
dgwwa5: cmp dl,mar_right ; beyond right margin?
jbe dgwwa6 ; be = no, in bounds
mov dl,mar_right ; peg at right
dgwwa6: jmp atsetcur ; set cursor within window
dgwwa endp
dgwsa proc near ; RS F P <nn><nn> Write screen address
mov bx,offset dgwsa1 ; get <nn> col
jmp get2n
dgwsa1: mov ax,dgnum ; absolute column
mov ah,mar_right ; right most virtual column
cmp al,-1 ; means same screen column?
je dgwsa2a ; e = yes
cmp al,ah ; beyond right screen limit?
jbe dgwsa2 ; be = no
mov al,ah ; peg at the right
dgwsa2: mov byte ptr cursor,al ; column of cursor
dgwsa2a:mov bx,offset dgwsa3 ; get <nn> row
jmp get2n
dgwsa3: mov ax,dgnum ; get absolute row
mov ah,byte ptr low_rgt+1 ; last text row
cmp al,-1 ; means same screen row?
je dgwsa5 ; e = yes
cmp al,ah ; below text screen?
jbe dgwsa4 ; be = no
mov al,ah ; peg at the bottom
dgwsa4: mov byte ptr cursor+1,al ; new row
dgwsa5: mov dx,cursor
call dggetmar ; get margins for this dx
call getatch ; check for protected field
test cl,att_protect ; protected?
jz dgwsa6 ; z = no
jmp dgcuf ; do DG cursor right
dgwsa6: jmp atsetcur ; set cursor physical position
dgwsa endp
dgshome proc near ; RS F G DG Screen Home
xor dh,dh ; absolute screen top
call dggetmar ; get margins for this dx
mov dl,mar_left ; go to left margin
jmp atsetcur ; set the cursor
dgshome endp
dgsetmar proc near ; RS F X <nn> <nn> Set margins
call dggetmar ; get margins for this window row
mov bx,offset dgsetm1 ; get <nn> left margin
jmp get2n
dgsetm1:mov al,mar_left ; current left margin
mov emubuf,al
mov ax,dgnum ; get left margin info
cmp al,-1 ; use current margin?
je dgsetm2 ; e = yes
mov emubuf,al ; set left margin
dgsetm2:mov bx,offset dgsetm3 ; get right margin
jmp get2n
dgsetm3:mov ax,dgnum ; get right margin info
cmp al,-1 ; use current margin?
jne dgsetm4 ; ne = no
mov al,vswidth-1 ; use full screen
dgsetm4:cmp al,vswidth-1 ; check sanity
ja dgsetmx ; a = too large a right margin
or al,al ; how about zero too?
jz dgsetmx ; z = bad value
cmp al,mar_left ; getting things on the wrong side?
ja dgsetm5 ; a = no
mov al,mar_left
inc al ; one column wide screen
dgsetm5:mov mar_right,al ; set right margin
cmp mar_left,vswidth-1 ; this side too
jae dgsetmx ; ae = too large
mov al,emubuf ; new left
mov mar_left,al ; new left
mov byte ptr cursor,al ; set cursor to left margin
mov dx,cursor
mov emubuf,al ; preset args for dgschw1
mov al,mar_right
mov emubuf+1,al
jmp dgschw1 ; try to show both margins, set cursor
dgsetmx:jmp dggetmar ; fail back to current margins
dgsetmar endp
dgsetamar proc near ; DG RS F Y <nn><nn><nn>
cmp savdgmar,0 ; have we saved l/r margins?
jne dgsetam0 ; ne = yes, don't save current
mov ah,mar_right ; save originals
mov al,mar_left
mov savdgmar,ax ; saved
dgsetam0:mov bx,offset dgsetam1 ; Set Alternate Margins
jmp get2n ; get cursor row
dgsetam1:mov ax,dgnum ; cursor row wrt top margin
mov bl,dh ; row of cursor
cmp al,-1 ; use current row?
je dgsetam2 ; e = yes
mov bl,mar_top ; get row at top of this window
add bl,al ; new cursor row is mar_top + new
dgsetam2:cmp bl,mar_bot ; below window?
jbe dgsetam3 ; be = no
mov bl,mar_bot ; clamp to window bottom
dgsetam3:mov byte ptr param,bl ; save cursor row
mov bx,offset dgsetam4 ; get <nn> col of new left margin
jmp get2n
dgsetam4:mov ax,dgnum
mov bl,byte ptr savdgmar ; get permanent left margin
cmp al,-1 ; use current left margin?
je dgsetam5 ; e = yes
add bl,al ; new left, wrt old left
dgsetam5:mov param+2,bx ; save left margin
mov bx,offset dgsetam6 ; get <nn> right margin
jmp get2n
dgsetam6:mov ax,dgnum
mov bl,byte ptr savdgmar+1 ; current right margin
cmp al,-1 ; use current right margin?
je dgsetam7 ; e = yes
mov bl,al
add bl,byte ptr param+2 ; relative to new left margin
cmp bl,byte ptr savdgmar+1 ; exceeds old right_margin?
jbe dgsetam7 ; be = no
mov bl,byte ptr savdgmar+1 ; yes, use old right_margin
dgsetam7:cmp bl,vswidth-1 ; too far right?
ja dgsetam9 ; a = yes, abandon the command
mov mar_right,bl ; alt right margin
mov al,byte ptr param+2 ; get alt left margin
mov mar_left,al
mov dl,al ; cursor to left margin
mov dh,byte ptr param ; get row for cursor
mov dghscrdis,1 ; horz scroll disabled (if 1)
call atsetcur ; set cursor
dgsetam9:ret
dgsetamar endp
dgrnmar proc near ; RS F Z DG Restore normal margins
cmp savdgmar,0 ; anything saved?
jz dgrnma1 ; z = no, do nothing
xor ax,ax ; get a null
xchg ax,savdgmar ; recover saved margins, clear saved
mov mar_left,al
mov mar_right,ah
dgrnma1:ret
dgrnmar endp
; Worker. Given cursor in dx, set mar_top, mar_bot based on finding the
; DG window for that cursor row.
dggetmar proc near
mov cx,dgwindcnt ; number of windows
xor bx,bx
jcxz dggetma2 ; z = none
inc cx ; let implied last window be seen
dggetma1:cmp dh,byte ptr dgwindow[bx+1] ; look at window bottom edge
jbe dggetma3 ; be = cursor is in this window
add bx,2 ; skip two margin bytes
loop dggetma1 ; next window
dggetma2:ret
dggetma3:mov ax,dgwindow[bx] ; DG Window structure
mov mar_top,al
mov mar_bot,ah
ret
dggetmar endp
; Worker. Given cursor in dx, and al=mar_top, ah=mar_bot
; store these margins in the window structure for that row, based on
; finding the DG window for that cursor row.
dgstoremar proc near
push cx
mov cx,dgwindcnt ; number of windows
xor bx,bx
jcxz dgstore2 ; z = none
dgstore1:cmp dh,byte ptr dgwindow[bx+1] ; look at window bottom edge
jbe dgstore2 ; be = cursor is in this window
add bx,2 ; skip two margin bytes
loop dgstore1 ; next window
xor bx,bx ; fail, use first window slot
dgstore2:pop cx
mov dgwindow[bx],ax
ret
dgstoremar endp
dgsmid proc near ; RS F { <nn><n> DG Set Model ID
mov bx,offset dgsmid1 ; setup for <nn>
jmp get2n
dgsmid1:mov ax,dgnum ; get new model id
mov byte ptr dgaltid,al ; save
mov bx,dgsmid2 ; get graphics possible (1) bit
jmp get1n
dgsmid2:mov ax,dgnum
mov byte ptr dgaltid+1,al
ret
dgsmid endp
dgscrup proc near ; DG RS H
mov scroll,1
call atscru ; scroll up one line
ret
dgscrup endp
dgscrdn proc near ; DG RS I
mov scroll,1
call atscrd ; scroll down one line
ret
dgscrdn endp
dgcuu proc near ; Control-W DG cursor up
mov cursor,dx ; remember for worker
dgcuu1: cmp dh,mar_top ; above the top margin?
ja dgcuu2 ; a = not on top margin
mov dh,mar_bot ; roll to bottom margin
inc dh
dgcuu2: dec dh ; go up one row
call dgcurpchk ; do proteced mode check
jc dgcub1 ; c = protected, do cursor back
jmp atsetcur ; set the cursor
dgcuu endp
dgcud proc near ; Control-Z DG cursor down
mov cursor,dx ; remember for worker
dgcud1: cmp dh,mar_bot ; below the bottom text line?
jb dgcud2 ; b = no
mov dh,mar_top ; roll to top margin
dec dh
dgcud2: inc dh ; go down one row
call dgcurpchk ; check for protected cell
jc dgcuf1 ; c = on protected cell, go forward
jmp dgsetcur ; set cursor
dgcud endp
dgcuf proc near ; Control-X DG cursor forward
mov cursor,dx ; remember where we started
cmp dl,mar_right ; test for about to wrap
jb dgcuf1 ; b = not wrapping
test anspflg,vtautop ; printing desired?
jz dgcuf1 ; e = no
push dx ; save cursor value
call pntlin ; print line current line
mov al,LF ; terminate in LF
call fpntchr
call fpntflsh ; flush printer buffer
mov atwrap,0
pop dx
dgcuf1: cmp dl,mar_right ; to right of right margin?
jb dgcuf5 ; b = not on right margin
mov dl,mar_left ; go to left margin
inc dh ; and down one
cmp dh,mar_bot ; below bottom line now?
jbe dgcuf6 ; be = no
mov dh,mar_bot ; stay on bottom line
cmp dgroll,0 ; is roll mode disabled?
jne dgcuf3 ; ne = no, do the scroll
mov dh,mar_top ; yes, wrap to top
jmp short dgcuf6
dgcuf3: mov scroll,1
call atsetcur ; set cursor before the scroll
call atscru ; scroll up one line
ret
dgcuf5: inc dl ; go right one column
dgcuf6: call dgcurpchk ; check protection
jc dgcuf1 ; c = stepped on protected cell
jmp atsetcur ; set cursor
dgcuf endp
dgcub proc near ; Control-Y DG cursor left
mov cursor,dx ; remember for worker
dgcub1: cmp dl,mar_left ; to left of left margin?
ja dgcub2 ; a = no
mov dl,mar_right ; go to right margin
jmp dgcuu1 ; and do a cursor up
dgcub2: dec dl ; go left one column
call dgcurpchk ; check protection
jc dgcub1 ; c = stepped on protected cell
jmp atsetcur ; set real cursor and exit
dgcub endp
dgcurpchk proc near
cmp protectena,0 ; protected mode enabled?
je dgcurpc1 ; e = no
call getatch ; read char under new cursor position
test cl,att_protect ; protected?
jz dgcurpc1 ; z = no, accept this position
cmp dx,cursor ; is this where we started?
je dgcurpc1 ; e = yes
stc ; say stepping on protected char cell
ret
dgcurpc1:clc ; say no other action needed
ret
dgcurpchk endp
; Worker for cursor cmds. Skips protected fields, but remembers if we have
; come full circle and then does a cursor right from there. Enter with
; pre-motion cursor in "cursor", new desired position in dx.
dgsetcur proc near
call dgcurpchk ; call protected cell checker
jnc dgsetcu1 ; nc = ok, accept this position
jmp dgcuf1 ; do cursor forward
dgsetcu1:mov bl,dh ; get row
xor bh,bh
cmp dl,linescroll[bx] ; to left of visible screen?
jae dgsetcu2 ; ae = no
mov emubuf,dl ; set desired left margin
mov cl,mar_right
mov emubuf+2,cl ; set desired right margin
mov cursor,dx ; preset for dgschw1
jmp dgschw1 ; do Show Window to track cursor
dgsetcu2:jmp atsetcur ; set real cursor and exit
dgsetcur endp
dglf proc near ; Control-J DG New Line
test anspflg,vtautop ; printing desired?
jz dglf1 ; e = no
push dx ; save cursor
call pntlin ; print line
mov al,LF ; terminate in LF
call fpntchr
call fpntflsh ; flush printer buffer
mov atwrap,0
pop dx
dglf1: mov dl,mar_left ; to left margin
cmp dh,mar_bot ; on bottom margin?
jb dglf3 ; b = no
cmp dgroll,0 ; is roll disabled
je dglf2 ; e = yes, do home
call dgsetcur ; set cursor, does show columns too
mov scroll,1
jmp atscru ; do a scroll up by one line
dglf2: mov dh,mar_top ; do window Home
jmp short dglf4
dglf3: inc dh ; down one row
dglf4: jmp dgsetcur ; set cursor wrt protected mode
dglf endp
dgcr proc near ; DG Control-M
mov dl,mar_left ; go to left margin, same row
jmp dgsetcur ; set cursor, with protected mode
dgcr endp
dgrmid proc near ; RS C DG Read Model ID
mov al,dgescape ; resp RS o # <mm> <x> <y>
call prtbout
mov al,'o'
call prtbout
mov al,'#'
call prtbout
mov al,'6' ; 6 is DG D413/D463
test flags.vtflg,ttd470 ; D470?
jz dgrmid6 ; z = no
mov al,44 ; 44 is DG D470
dgrmid6:cmp byte ptr dgaltid,0 ; alternate ID given?
je dgrmid1 ; e = no
mov al,byte ptr dgaltid ; use alternate
dgrmid1:call prtbout
xor al,al ; <x> byte, clear it
test flags.remflg,d8bit ; using 8 bits?
jz dgrmid2 ; z = no
or al,10h ; say 8-bit mode
dgrmid2:push ax
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
jnc dgrmid3 ; nc = call succeeded
mov al,0ffh
dgrmid3:cmp al,0ffh ; code for Ready
pop ax
jne dgrmid4 ; ne = not ready
or al,8 ; say printer present
dgrmid4:or al,40h
call prtbout ; send composite byte
mov bl,vtemu.vtchset ; get Kermit NRC code (0-13)
xor bh,bh
mov al,nrcdgkbd[bx] ; <y>, get DG keyboard code from table
or al,50h ; 01+kbd installed (no graphics)
or al,20h ; say have graphics
cmp byte ptr dgaltid,0 ; alternate id given?
je dgrmid5 ; e = no
cmp byte ptr dgaltid+1,0 ; host wants to say no graphics?
jne dgrmid5 ; ne = no, let things stand
and al,not 20h ; remove graphics bit
dgrmid5:call prtbout
ret
dgrmid endp
; D470 command, absent from D463's
dgscmap proc near ; RS F c <n><n><n><n> DG set color map
mov bx,offset dgscmap1 ; get language ident
jmp get3n ; get three of the <n>'s
dgscmap1:mov bx,offset dgscmap2 ; get the fourth
jmp get1n
dgscmap2:ret
dgscmap endp
dgshcol proc near ; RS F _ <nn><nn> DG Show Columns
mov bx,offset dgshco1 ; get left col to show
jmp get2n
dgshco1:mov ax,dgnum ; left column to show, is dominant
mov cx,vswidth ; max columns in vscreen
dec cx ; max column ident
sub cl,byte ptr low_rgt ; visible display width - 1
sbb ch,0 ; max left column showable
cmp ax,cx ; want further right than this?
jbe dgshco2 ; be = no
mov ax,cx ; limit to max
dgshco2:mov emubuf,al ; save max left col to show
mov bx,offset dgshco3 ; get right col to show
jmp get2n
dgshco3:mov ax,dgnum ; right col
mov emubuf+1,al
cmp dghscrdis,0 ; is horizontal scrolling disabled?
je dgschw1 ; e = no
ret ; disabled, ignore this command
; worker. emubuf=wanted visible left, emubuf+1=wanted visible right margin
dgschw1:mov bl,mar_top ; get window top
xor bh,bh
mov cl,mar_bot
sub cl,bl
inc cl
xor ch,ch ; lines in window
mov al,emubuf+1 ; desired right margin
sub al,emubuf ; minus desired left
cmp al,byte ptr low_rgt ; more than a screen's width?
jbe dgschw2 ; be = no
mov al,emubuf ; desired left
add al,byte ptr low_rgt ; plus screen width
mov emubuf+1,al ; chop desired rm to give one screen
dgschw2:mov al,linescroll[bx] ; get scroll now in effect
cmp emubuf,al ; is left margin to left of screen?
jb dgshw4 ; b = yes, put it on screen
je dgshw8 ; e = there now, do nothing
mov ah,emubuf+1 ; right margin to use
add al,byte ptr low_rgt ; visible right edge
cmp al,ah ; visible vs wanted right edge
jae dgshw8 ; ae = rm visible now, do nothing
sub ah,al ; distance right margin is invisible
xchg ah,al
add al,linescroll[bx] ; new shift plus current shift
jmp short dgshw5
dgshw4: mov al,emubuf ; new scroll
dgshw5: mov linescroll[bx],al ; horiz scroll for this line (window)
inc bx
loop dgshw5 ; do all lines in this window
mov dx,cursor
cmp dl,al ; is cursor off to the left?
jae dgshw6 ; ae = no
mov dl,al ; offset cursor too
dgshw6: add al,byte ptr low_rgt ; visible right edge
cmp dl,al ; cursor is on screen?
jbe dgshw7 ; be = yes
mov dl,al ; move cursor to right edge
dgshw7: mov cursor,dx
mov dl,mar_top ; region affected
mov dh,mar_bot
call touchup ; repaint based on new linescroll
dgshw8: mov dx,cursor ; update visible cursor
jmp atsetcur ; set cursor, updates screen
dgshcol endp
dgrnmod proc near ; RS F w DG Read New Model ID
mov al,dgescape ; resp RS o w <c><s><r><n><res>
call prtbout
mov al,'o'
call prtbout
mov al,'w'
call prtbout
; mov al,'3' ; <c> D413 level graphics terminal
mov al,'8' ; <c> D470/D463 graphics terminal
call prtbout
mov al,'0' ; <s> pair, 01 is D470/D463
call prtbout
mov al,'1'
call prtbout
mov al,'0' ; <r> rev level as <nn>
call prtbout ; report 00
mov al,'0'
call prtbout
mov cx,4
;; mov si,offset d413model ; 8 char name, all printables
mov si,offset d463model ; graphics term name, 8 printables
test flags.vtflg,ttd470 ; D470?
jz dgrnmo1 ; z = no
mov si,offset d470model
dgrnmo1:lodsb
push cx
call prtbout
pop cx
loop dgrnmo1
mov cx,4+4 ; <reserved> four spaces
dgrnmo2:mov al,' '
push cx
call prtbout
pop cx
loop dgrnmo2
ret
dgrnmod endp
dgunix proc near ; RS P @ <n> DG Unix mode
mov ttstate,offset dgunix1 ; setup to ignore @
ret
dgunix1:mov bx,offset atnrm ; consume the <n>
jmp get1n
dgunix endp
dgsct proc near ; RS F Q <n> DG Set Cursor Type
mov bx,offset dgsct1
jmp get1n ; get the <n> arg
dgsct1: mov ax,dgnum ; get cursor type
or al,al ; case 0, invisible/off?
jnz dgsct2 ; nz = no
call csrtype ; set text cursor bits, keep kind
or atctype,4 ; remember, is off
jmp short dgsct5
dgsct2: cmp al,2 ; standard 1,2? (underline, block)
jbe dgsct4 ; be = yes
sub al,5
neg al ; 5 - AL
js dgsct6 ; s = out of range, ignore
jnz dgsct4 ; nz = cases 3 and 4 (block, uline)
mov al,atctype ; case 5, use saved cursor type
and al,not 4 ; remove invisible bit
dgsct4: mov atctype,al ; save text cursor type here
push ax
or vtemu.vtflgop,vscursor ; set to underlined
test al,2 ; setting to block?
jz dgsct4a ; z = no, underline
and vtemu.vtflgop,not vscursor ; say block in status word
dgsct4a:call csrtype ; set the cursor bits
pop ax
dgsct5: test tekflg,tek_active+tek_sg ; special graphics mode active?
jz dgsct6 ; z = no
mov dx,cursor
call teksetcursor ; set new cursor
dgsct6: ret
dgsct endp
dgchatr proc near ; RS F N <nnn><n><n> DG change attrib
mov bx,offset dgchat1 ; get <nnn> qty chars to change
jmp get3n
dgchat1:mov ax,dgnum ; qty chars to change
mov word ptr emubuf,ax ; save
mov bx,offset dgchat2 ; get <n> set list
jmp get1n
dgchat2:mov ax,dgnum ; bitfield for characteristics
mov emubuf+2,al ; save set list
mov bx,offset dgchat3 ; get final <n> reset list
jmp get1n
dgchat3:mov bl,byte ptr dgnum ; get reset list to BL
mov emubuf+3,bl ; save reset list
mov bh,emubuf+2 ; set list
and bh,bl ; get toggle bits
mov emubuf+4,bh ; save toggle list here
not bh ; clear out bits processed here
and emubuf+2,bh ; update set list
and emubuf+3,bh ; update reset list
mov cursor,dx ; save cursor location
mov cx,word ptr emubuf ; qty of bytes to change, max
or cx,cx ; some count?
jnz dgchag4 ; nz = something to do
ret
dgchag4:mov al,extattr ; preserve settable attributes
mov ah,scbattr
push ax
dgchag4a:push cx ; save loop counter
call getatch ; get video in ah, extended att in cl
mov extattr,cl ; place extended where procs can see
mov emubuf+5,al ; save char
call dgchag10 ; process this char
mov al,emubuf+5 ; restore char
call qsetatch ; quietly update the char
pop cx
inc dl ; next column
cmp dl,mar_right ; at the right margin?
jbe dgchag5 ; be = no, not yet
mov dl,mar_left ; wrap to left and next line
inc dh ; next line down
cmp dh,mar_bot ; below the window bottom?
ja dgchag6 ; a = yes, all done
dgchag5:loop dgchag4a ; do more chars
dgchag6:pop ax
mov extattr,al ; restore setables
mov scbattr,ah
mov dl,byte ptr cursor+1 ; dl = starting row, dh = ending row
mov dh,mar_bot
call touchup ; repaint part of screen
mov dx,cursor ; reset cursor location
ret
; worker for dgchag ; do toggle mode
dgchag10:mov bh,emubuf+4 ; toggle list
or bh,bh ; any work?
jz dgchag20 ; z = no
test bh,1 ; blink?
jz dgchag11 ; z = no
xor ah,att_blink ; xor blink
dgchag11:test bh,2 ; underscore?
jz dgchag13 ; z = no
test cl,att_uline ; is it set now?
jz dgchag12 ; z = no
call clrunder ; reset it
jmp short dgchag13
dgchag12:call setunder ; set it
dgchag13:test bh,4 ; reverse video
jz dgchag15 ; z = no
test cl,att_rev ; reversed now?
jz dgchag14 ; z = no
call clrrev ; unreverse it
jmp short dgchag15
dgchag14:call setrev ; reverse it
dgchag15:test bh,8 ; Dim
jz dgchag20
xor ah,att_bold
; do set list from emubuf+2
dgchag20:mov bh,emubuf+2 ; get set list
or bh,bh ; any work?
jz dgchag30 ; z = no
test bh,1 ; blink?
jz dgchag21 ; z = no
call setblink ; set blink
dgchag21:test bh,2 ; underscore?
jz dgchag22 ; z = no
call setunder ; set underline
dgchag22:test bh,4 ; reverse video?
jz dgchag23 ; z = no
call setrev ; set reverse video
dgchag23:test bh,8 ; dim?
jz dgchag30 ; z = no
call clrbold ; set Dim
; do reset list from emubuf+3
dgchag30:mov bh,emubuf+3 ; get reset list
or bh,bh ; any work?
jz dgchag34 ; z = no
test bh,1 ; blink?
jz dgchag31 ; z = no
call clrblink ; clear blink
dgchag31:test bh,2 ; underscore?
jz dgchag32 ; z = no
call clrunder ; clear underscore
dgchag32:test bh,4 ; reverse video?
jz dgchag33 ; z = no
call clrrev
dgchag33:test bh,8 ; Dim?
jz dgchag34 ; z = no
call setbold ; reset dim
dgchag34:ret ; end of callable worker
dgchatr endp
dgsclk proc near ; RS r <n> <pos> <time> DG Set Clock
mov bx,offset dgsclk1 ; set up to get <n><0000>
jmp get3n
dgsclk1:mov bx,offset dgsclk2 ; setup to get HH
jmp get1n
dgsclk2:mov ttstate,offset dgsclk3 ; setup to get ":"
ret
dgsclk3:mov bx,offset atnrm ; absorb final MM
jmp get1n
dgsclk endp
dgrss proc near ; RS F t DG Report Screen Size
mov al,dgescape ; resp RS o < <5 more items>
call prtbout
mov al,'o'
call prtbout
mov al,'<'
call prtbout
mov al,byte ptr low_rgt+1 ; number of screen rows -1
inc al
call out2n ; first item
mov al,207 ; number of screen cols (DG hard #)
call out2n ; second item
mov al,mar_bot
sub al,mar_top
inc al ; third item, num rows in window
call out2n
mov al,mar_right
sub al,mar_left
inc al ; fourth item, num cols in window
call out2n
mov al,01110000b ; fifth item, status
call prtbout
ret
dgrss endp
dgrhso proc near ; RS F O DG Read Horz Scroll Offset
mov al,dgescape ; resp RS o : <nn>
call prtbout
mov al,'o'
call prtbout
mov al,':'
call prtbout
mov bl,dh ; get current row
xor bh,bh
mov al,linescroll[bx] ; get scroll value
call out2na
ret
dgrhso endp
dgrwa proc near ; Control-E DG Read Window Address
mov al,1fh ; Response string Control-_ col row
call prtbout
mov al,dl ; col, raw binary
call prtbout
mov al,dh ; row, raw binary
call prtbout
ret
dgrwa endp
dgrsa proc near ; RS F b DG Read Screen Address
mov al,dgescape ; resp RS o 8 <nn> <nn>
call prtbout
mov al,'o'
call prtbout
mov al,'8'
call prtbout
mov al,byte ptr cursor ; column
call out2na
mov al,byte ptr cursor+1 ; row
call out2na
ret
dgrsa endp
dgrwc proc near ; RS F v <r1> <c1> <r2> <c2>
mov emubufc,0 ; counter. DG Read Window Contents
dgrwc1: mov bx,offset dgrwc2
jmp get2n ; read <nn>
dgrwc2: mov bx,emubufc ; get counter
inc emubufc
mov ax,dgnum ; r1, c1, r2, or c2
mov emubuf[bx],al ; save here
cmp bx,3 ; done all four?
jb dgrwc1 ; b = no, get more
mov dh,emubuf ; starting row
cmp dh,emubuf+2 ; versus ending row
ja dgrwc8 ; a = fail if wrong order
dgrwc3: mov dl,emubuf+3 ; ending column
mov cl,dl
sub cl,emubuf+1 ; minus starting column
jl dgrwc8 ; fail if wrong order
inc cl ; number of cells to examine
xor ch,ch
dgrwc4: push cx
push dx
call direction
call getatch ; read char into AL at cursor dx
pop dx
pop cx
cmp al,' ' ; space?
jne dgrwc5 ; found non-space
dec dl
loop dgrwc4
dgrwc5: jcxz dgrwc7 ; z = only spaces on the line
mov dl,emubuf+1 ; staring column
dgrwc6: push cx
push dx
call direction
call getatch ; get char and attribute
call prtbout ; send char in al
pop dx
pop cx
inc dl ; across the row
loop dgrwc6 ; do all interesting cols
dgrwc7: push dx
mov al,CR ; send line terminators
call prtbout
mov al,LF
call prtbout
pop dx
inc dh ; next row down
cmp dh,emubuf+2 ; beyond last row?
jbe dgrwc3 ; be = no
mov dx,cursor
mov emubufc,0 ; clear counter
dgrwc8: ret
dgrwc endp
; Data General D463/D470 graphics commands
dggline proc near ; RS L and RS G 8 DG line drawing
call dgsettek ; setup special graphics mode
dggline1:mov bx,offset dggline2 ; get <NNN> x coord
jmp get3loc
dggline2:jc dggline9 ; c = read null terminator
mov ax,dgnum ; start x coord
mov param+0,ax ; save here
mov param+4,ax ; and here
mov bx,offset dggline3 ; get <NNN> y coord
jmp get3loc
dggline3:jc dggline9
mov ax,dgnum
mov param+2,ax ; start y
mov param+6,ax ; and here
dggline4:mov bx,offset dggline5 ; get <NNN> end x coord
jmp get3loc
dggline5:jc dggline8 ; c = ending on single coord, do a dot
mov ax,dgnum
mov param+4,ax ; end x
mov bx,offset dggline6 ; get <NNN> end y coord
jmp get3loc
dggline6:jc dggline9 ; c = null char
mov ax,dgnum ; end y
mov param+6,ax
call dggline8 ; plot line
jmp short dggline4 ; continue gathering coord pairs
dggline8:
push word ptr mar_top ; mar_top in low byte
push dglinepat ; line pattern
push param+6 ; end y
push param+4 ; end x
push param+2 ; start y
push param+0 ; start x
call dgline ; do the line
add sp,12 ; clear the argument stack
mov ax,param+4 ; old end is new beginning
mov param,ax
mov ax,param+6
mov param+2,ax
dggline9:ret
dggline endp
dggarc proc near ; RS G 0 DG arc drawing
mov bx,offset dggarc1 ; get <NNN> x coord
jmp get3loc
dggarc1:jc dggarc9 ; unexpected terminator
mov ax,dgnum ; x coord
mov param,ax ; save here
mov bx,offset dggarc2 ; get <NNN> y coord
jmp get3loc
dggarc2:jc dggarc9
mov ax,dgnum
mov param+2,ax
mov bx,offset dggarc3 ; get <NNN> radius
jmp get3loc
dggarc3:jc dggarc9
mov ax,dgnum
mov param+4,ax
mov bx,offset dggarc4 ; get <NNN> start angle
jmp get3loc
dggarc4:jc dggarc9
mov ax,dgnum
mov param+6,ax
mov bx,offset dggarc5 ; get <NNN> end angle
jmp get3loc
dggarc5:call dgsettek ; setup graphics mode
mov al,mar_bot ; bottom margin in PC text lines
xor ah,ah
push ax
mov al,mar_top ; top margin in PC text lines
push ax
push dgnum ; end angle
push param+6 ; start angle
push param+4 ; radius
push param+2 ; start y
push param+0 ; start x
call dgarc ; draw the arc in msgibm
add sp,14 ; clean stack
dggarc9:ret
dggarc endp
dggbar proc near ; RS G 1 DG bar drawing
call dgsettek ; setup special graphics mode
mov bx,offset dggbar1 ; get <NNN> x coord, lower left
jmp get3loc
dggbar1:jc dggbar9 ; c = unexpected terminator
mov ax,dgnum ; x coord
mov param,ax ; save here
mov bx,offset dggbar2 ; get <NNN> y coord
jmp get3loc
dggbar2:jc dggbar9
mov ax,dgnum
mov param+2,ax
mov bx,offset dggbar3 ; get <NNN> width
jmp get3loc
dggbar3:jc dggbar9
mov ax,dgnum
mov param+4,ax
mov bx,offset dggbar4 ; get <NNN> height
jmp get3loc
dggbar4:jc dggbar9
mov ax,dgnum
mov param+6,ax
mov bx,offset dggbar5 ; get <n> foreground/background
jmp get1n
dggbar5:jc dggbar9
xor ah,ah
mov al,mar_bot
push ax
mov al,mar_top
push ax
push dgnum ; fore(1) or background (0) color
push param+6 ; height
push param+4 ; width
push param+2 ; start y lower left corner
push param+0 ; start x
call dgbar ; msgibm bar drawer
add sp,14 ; clean stack
dggbar9:ret
dggbar endp
dggpoly proc near ; RS G : DG polygon fill drawing
mov word ptr rdbuf,0 ; count argument pairs
dggpol1:mov bx,offset dggpol2 ; get <NNN> x coord
jmp get3loc
dggpol2:jc dggpol4 ; c = got null terminator
mov ax,dgnum ; x coord
mov param,ax ; save here
mov bx,offset dggpol3 ; get <NNN> y coord
jmp get3loc
dggpol3:jc dggpol4
mov bx,word ptr rdbuf ; vertex index
shl bx,1 ; count words
shl bx,1 ; count pairs
mov cx,param ; x coord
mov ax,dgnum ; y coord
mov word ptr rdbuf+2[bx],cx ; stuff x
mov word ptr rdbuf+2[bx+2],ax ; stuff y
inc word ptr rdbuf ; another vertex in list
jmp short dggpol1 ; get another vertex
dggpol4:cmp word ptr rdbuf,3 ; minimum viable point count
jb dggpol6 ; b = insufficient qty
mov bx,word ptr rdbuf ; vertex index
shl bx,1 ; count words
shl bx,1 ; count pairs
mov al,mar_top
xor ah,ah
mov word ptr rdbuf+2[bx],ax ; top margin, PC text lines
mov al,mar_bot
mov word ptr rdbuf+2[bx+2],ax ; bottom margin, PC text lines
call dgsettek ; setup special graphics mode
mov al,curattr ; save current coloring
push ax
test flags.vtflg,ttd463 ; D463?
jz dgpoly5 ; z = no
and al,0f0h ; remove foreground
or al,dg463fore ; OR in D463 foreground color
mov curattr,al ; set drawing coloring
dgpoly5:call dgpoly ; call worker in msgibm
pop ax
mov curattr,al ; restore coloring
dggpol6:ret
dggpoly endp
dggsetp proc near ; RS G p 1 DG Set Pattern
mov ttstate,offset dggset1 ; setup to read the 1
ret
dggset1:cmp al,'1' ; correct?
je dggset2 ; e = yes
dggsetx:jmp atnorm ; fail and reset state
dggset2:mov ttstate,offset dggset3 ; setup to read <offset>
mov dglinepat,0 ; init line pattern to all zeros
call dgsettek ; setup special graphics mode
ret
dggset3:sub al,'@' ; remove ASCII bias
jc dggset9 ; c = failure
and al,1fh ; keep lower five bits
xor ah,ah
mov param,ax ; save initial bit position
mov cl,al
rcl dglinepat,cl ; rotate initial pattern
mov ttstate,offset dggset4 ; setup to read <n> 0/1 bit
ret
dggset4:or al,al ; null terminator?
jz dggset6 ; z = yes
and al,0fh ; keep lower four bits of <n>
cmp al,1 ; legal values are 0, 1, and other
jbe dggset5 ; be = 0 or 1
xor al,al ; above 1 is made to be zero
dggset5:rcr al,1
rcr dglinepat,1 ; put into line pattern high bit
inc param ; count bit added to pattern
ret ; continue in state dggset4
dggset6:mov cx,16 ; bits in pattern
sub cx,param ; get pattern bit count
jle dggset9 ; le = rotated enough
mov ax,dglinepat ; pattern
mov bx,ax ; a copy
mov cx,param ; pattern bit count
mov dx,16 ; overall bits
dggset6a:sub dx,cx ; minus original pattern
jg dggset7 ; g = still have room to copy
je dggset8 ; e = all done
neg dx
mov cx,dx ; else tag end
dggset7:ror ax,cl ; rotate pattern to starting position
or ax,bx ; move in a copy
jmp short dggset6a
dggset8:mov dglinepat,ax ; store line pattern
dggset9:mov ttstate,offset atnrm
ret
dggsetp endp
dggrcl proc near ; RS G ? | DG Read Cursor Location
mov ttstate,offset dggrcl1
ret
dggrcl1:mov ttstate,atnrm ; reset state
cmp al,'|' ; correct terminator?
jne dggrcl3 ; ne = no
dggrcl2:call dgcrossrpt ; generate report in msgibm
dggrcl3:ret
dggrcl endp
dggcon proc near ; RS G B DG Cursor on
call dgsettek ; setup special graphics mode
call dgcrosson ; turn on crosshair
ret
dggcon endp
dggcoff proc near ; RS G C DG Cursor off
call dgcrossoff ; turn off crosshair
ret
dggcoff endp
dggcloc proc near ; RS G > | <NNN> <NNN> DG Cursor loc
mov ttstate,offset dggclo1 ; get vertical bar
ret
dggclo1:mov ttstate,offset atnrm ; reset state
cmp al,'|' ; correct character?
je dggclo2 ; e = yes
ret
dggclo2:mov bx,offset dggclo3 ; get <nnn> x ordinate
jmp get3loc ; as 15 bit location argument
dggclo3:mov ax,dgnum
mov param,ax ; got x ordinate
mov bx,offset dggclo4 ; get <nnn> y ordinate
jmp get3loc ; as 15 bit location argument
dggclo4:mov bx,dgnum ; setup registers for call
mov ax,param
call dgsetcrloc ; setup crosshair location
ret
dggcloc endp
dggctrk proc near ; RS G H <n> DG Cursor track
mov bx,offset dggctr1
jmp get1n
dggctr1:and al,2+4 ; pick out our trackables
and dgcross,not (2+4) ; preserve on/of bit (1)
or dgcross,al ; track keypad (2) and/or mouse (4)
ret
dggctrk endp
dggcatt proc near ; RS G @ DG graphics cursor attribute
mov al,dgescape
call prtbout
mov al,'o'
call prtbout
mov al,','
call prtbout
mov al,'0' ; say crosshair is off
test dgcross,1 ; is it on?
jz dggcatt1 ; z = no
inc al ; say '1' for on
dggcatt1:call prtbout ; output <v1>
mov al,'0' ; <v2> is always 0 for not blinking
call prtbout
mov al,'1' ; <v3> is 1 for long crosshair, D463
test flags.vtflg,ttd470 ; D470?
jz dggcatt2 ; z = no
dec al ; <v3> is 0 for short crosshair, D470
dggcatt2:call prtbout
mov al,dgcross ; get tracked devices
and al,2+4 ; pick out just devices
add al,'0' ; bias
call prtbout ; output <v4>
mov al,CR ; terminal character
call prtbout
ret
dggcatt endp
dggcrst proc near ; RS G A DG Cursor reset
call dgcrossoff ; turn off crosshair
mov dgcross,0 ; and no kind of tracking
ret
dggcrst endp
; End of Data General specific routines
; 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 cx,10 ; length of the array
call getled ; set si to string, c set if no leds
push es
mov di,ds
mov es,di
mov di,led_col+offset modbuf ; mode line buffer, our position
cld
rep movsb
pop es
ansdsl2:ret
ansdsl endp
; Return pointer to "led" display in si, set carry if terminal type does
; not have leds 1..4.
getled proc near
mov ax,flags.vtflg ; terminal type
mov si,offset v320leds ; VT320 ident
cmp ax,ttvt320 ; VT320?
je getled2 ; e = yes
mov si,offset v220leds ; VT220 ident
cmp ax,ttvt220 ; VT220?
je getled2 ; e = yes
mov si,offset v102leds ; VT102 ident
cmp ax,ttvt102 ; VT102 mode?
je getled2 ; e = yes
mov si,offset v100leds
cmp ax,ttvt100 ; VT100?
je getled2 ; e = yes
mov si,offset honeyleds
cmp ax,tthoney ; Honeywell?
je getled2 ; e = yes
mov si,offset v52leds ; VT52 ident
cmp ax,ttvt52 ; VT52?
je getled1 ; e = yes, no leds
mov si,offset pt20leds
cmp ax,ttpt200 ; Prime PT200?
je getled2 ; e = yes
mov si,offset d463leds
cmp ax,ttd463 ; DG D463?
je getled1 ; e = yes, but no led dots
mov si,offset d470leds
cmp ax,ttd470 ; DG D470?
je getled1 ; e = yes, but no led dots
mov si,offset h19leds ; Heath-19 ident
getled1:stc ; c = set, does not have leds 1..4
ret
getled2:clc ; c = clear, has leds 1..4
ret
getled 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
test flags.vtflg,ttd463+ttd470 ; DG terminal?
jz atcci0a ; z = no
mov cl,mar_right
cmp dl,mar_left ; left of left margin?
jae atcci1 ; ae = no
mov dl,mar_right ; fold to right
dec dh ; and go up
jmp short atcci1
atcci0a: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 ; left of right margin
jbe atcci2 ; be = yes, go check top
mov dl,cl ; set to right margin
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jz atcci2 ; z = no
mov dl,mar_left ; to left margin
inc dh ; and down one
atcci2: pop cx
cmp bh,mar_top ; was old pos above scroll top margin?
jb atcci7 ; b = yes
cmp dh,mar_top ; want to go above top margin?
jge atcci5 ; ge = no
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jz atcci3 ; z = no
mov dh,mar_bot ; roll over to bottom margin
ret
atcci3: mov scroll,1
mov ax,offset atscrd ; indicate scroll down required
mov dh,mar_top ; set to top margin
ret
atcci5: cmp bh,mar_bot ; old position below bottom margin?
ja atcci7 ; a = yes
cmp dh,mar_bot ; want to go below?
jbe atcci6 ; be = 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
atcci6: ret
atcci7: jmp short 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: test flags.vtflg,ttd463+ttd470 ; DG terminal?
jz atccp0a ; z = no
mov cl,mar_right
cmp dl,mar_left ; left of margin?
jae atccp1 ; ae = no
mov dl,mar_right ; go to right margin
dec dh ; do a cursor up
jmp short atccp1 ; do a cursor up
atccp0a: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
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jz atccp2 ; z = no
mov dl,mar_left ; to left margin
jmp atlf ; do a LF operation now
atccp2: pop cx
pop bx
test vtemu.vtflgop,decom ; Origin mode set?
jnz atccp5 ; nz = yes, stay in scrolling region
or dh,dh ; above top of screen?
jae atccp3 ; ae = no, check bottom
xor dh,dh ; stop here
atccp3: cmp dh,byte ptr low_rgt+1 ; below bottom of screen?
jbe atccp4 ; be = no, stay in margins
mov dh,byte ptr low_rgt+1 ; stop at end of text screen
cmp flags.vtflg,ttheath ; Heath-19 mode?
jne atccp4 ; ne = no
test h19stat,h19l25 ; 25th line enabled?
jnz atccp4 ; nz = yes
inc dh ; allow 25th line
atccp4: ret
atccp5: cmp dh,mar_top ; above top of scrolling region?
jae atccp6 ; ae = no, check bottom
mov dh,mar_top ; yes, stop there
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jz atccp6 ; z = no
mov dh,mar_bot ; roll to bottom
ret
atccp6: cmp dh,mar_bot ; below bottom perhaps?
jbe atccp4 ; be = no, return
mov dh,mar_bot ; yes, stop at the bottom margin
test flags.vtflg,ttd463+ttd470 ; DG D463/D470?
jz atccp7 ; z = no
mov dh,mar_top ; roll to top
atccp7: ret
atccpc endp
; Routine to set cursor type (off, block, underline).
; 4 = do not show, but keep block/underline attributes.
; 2 = block, 1 = 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?
jnz atsct3 ; z = no
atsct2: mov al,1 ; assume underline
test vtemu.vtflgop,vscursor ; block?
jnz atsct3 ; nz = no, underline
inc al
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
call fcptchr ; give it captured character
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 extattr,0 ; extended 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 ; DEL?
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 DEL)
and al,7fh ; clear bit 7 (for DEL)
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
code1 ends
end