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