NAME mszibm ; File MSZIBM.ASM page 60,132 ; Terminal emulator module for IBM PC's and compatibles. Emulates Heath-19, ; VT52, and VT102. Original version done by James Harvey, Indiana Purdue ; Univ, for MS Kermit 2.27. Taken from there by Joe Doupnik, Utah State Univ ; for MS Kermit 2.29 et seq. ; Edit history ; Last edit: 14 March 1988 ; 14 March 1988 Update V2.30 code for NEC APCIII -- RFGoeke ; 6 Jan 1988 Remove erasing into mode line on to-end-of-screen calls. [jrd] ; 1 Jan 1988 version 2.30 ; 29 Dec 1987 Absorb escape sequences of the form ESC [ ... <40h to 7fh> ; to sense but not act on unknown legally formatted ANSI escapes. [jrd] ; 28 Dec 1987 Add corrections from Frank da Cruz: home cursor on select/desel ; origin mode, make select/deselect ansi mode return to US ascii graphics ; rendition sets (where is this item documented?). [jrd] ; 12 Dec 1987 Sense denyflg to supress automatic Tek mode when ESC Control-L ; is received; part of ENABLE/DISABLE command. [jrd] ; 4 Dec 1987 Strip high bit of chars within escape sequences, test for end of ; transparent print without high bit but playback 8 bit intermediates. [jrd] ; 16 Nov 1987 Add multiple timed retries on printer status. [jrd] ; 5 Nov 1987 Add Tektronix terminal type, including ESC FF branch to Tek ; mode and toggling among terminal types. [jrd] ; 28 Oct 1987 Remove NUL and DEL chars from normal logging and display, ; ignore Control-X and -Z unless in an esc sequence. [jrd] ; 3 Oct 1987 Remove cursor action for DEL when local echo is on. [jrd] ; 11 Sept 1987 Remove Translation Input from emulator proper. ; 23 Aug 1987 Add byte vtemu.vtflgop to hold emulator runtime values as ; distinct from the vtemu.vtflgst setup values so a reset restores setups. ; 19 Aug 1987 Make sure cursor type is correct on warm start, from Bob Babcock ; 18 Aug 1987 Change ESC to escape for MASM 4.5+. Add Heath graphics, ; add screen alignment, redo line wrap material, size screen from crt_cols ; and crt_rows given by MSYxxx. [jrd] ; 31 June 1987 Clear counter mccnt when completing transparent print. [jrd] ; 17 June 1987 Correct jump from atreset to atres2 when changing 80/132 cols ; and always copy all 132 columns of tabs. [jrd] ; 16 June 1987 Fix bug in cursor positioning when outside scrolling region, ; thanks to Richard Saxton. Remove global byte jwait (for msy), add code to ; clear the status line when the Heath-19 is commanded to disable that line ; (wierd, but Dave says that's the way H-19's work), thanks to Dave Tweten. ; 8 June 1987 Tell file msy... about change of keypad applications mode. [jrd] ; 31 May 1987 Correct several Heath-19 problems: use ansi escape table when ; in ansi mode, reject ESC [ (hold screen mode), use correct cursor left, ; remember cursor type (underline/block/on/off) separately from VT100 setup. ; Thanks to Dave Tweten. [jrd] ; 10 May 1987 Move input translate table rxtable within this emulator, ; don't translate if debug is active, don't translate escape sequences, ; no translation if controller print is active, make byte anspflg global ; so msyibm can sense print screen status. Add print controls for VT52. [jrd] ; 4 May 1987 Correct several jumps to be signed for scrolling region. [jrd] ; 7 April 1987 Fix cursor wrap for H-19's, from Mike Iglesias [uci] ; Fix cursor wrap top to bottom when reverse indexing, from Matt Tomlinson. ; Fix tests for cursor left of left margin for wide screens by comparing ; column number exceeding 250D. [jrd] ; 28 March 1987 Use global variable low_rgt vs proc call for it. [jrd] ; 24 March 1987 In vtsound, always use most recent port 61h state. [jrd] ; 22 March 1987 Add call to proc chgdsp (change display adapter) to shift ; between 80 and 132 columns, from David L. Knoell. [jrd] ; 14 March 1987 Correct small bugs. Change signed jumps to unsigned plus ; allow screen widths to 132 columns, thanks to David Knoell. ; Add constants Swidth (132) and Slen (43) as max screen dimensions and ; base screen ops on low_rgt (high = row, low = column of lower right corner, ; counted from 0,0) dimensions stated by msyibm. [jrd] ; 6 March 87 Add transparent printing when ANSI Media Copy (ESC [ 5 i) is ; active. [jrd] ; 19 Feb 1987 correct problem in atccic of cursor being forced into scrolling ; region if starting point was outside the region. [jrd] ; 27 Oct 1986 correct typo for anspflg under atnrm3: [jrd] ; 16 Oct 1986 keep several ansflg bits under warm start, correct screen, ; linewrap, and newline status under warm start. ; 1 Oct 1986 Version 2.29a ; 20 Sept 1986 revise procedure atccic to use proper scrolling limits. [jrd] ; 1 Sept 1986 Add 8 bit wide comms when parity = none. In debug mode high bit ; set shows as tilde then rest of 7 bit code. [jrd] ; 27 August 1986 Add full VT102 printer support. DOS printer operations used ; so printer can be redirected; requires Kermit's Critical Error routine in ; mssker.asm to avoid "Abort, Retry, Ignore" msgs on screen. Shows printer ; not ready msg on mode line and quits printing operation if PRN not ready. ; Correct indexing of cursor when it is outside limited scrolling region.[jrd] ; Fix parameter decanm not being updated in stblmds under soft reset. ; 21 May 1986 [jrd] ; [2.29] code frozen on 6 May 1986 [jrd] ; [Joe R. Doupnik, Utah State Univ] ; public anstty, ansini, ansrei, ansdsl, anstat, anskbi ; Entry points public ans52t, vsinit ; no vclick for NEC public mar_top, mar_bot, anspflg ; data for msyap3 include mssdef.h ; * Disclaimer * ; ; DEC and VT are trademarks of Digital Equipment Corporation. ; ; There is a naming convention ; for the ANSI and VT100 functions and flags; generally, the stuff in the ; symbol after "ans" or "at" is the function or mode mnemonic used in the ; VT100 manual. ; ; Every effort has been made to make the VT100 emulation as much like the ; real thing as possible. The reference used was the VT100 User's Guide, 2nd ; ed. Jan. 1979, DEC part no. EK-VT100-UG. Some aspects of the behavior ; of the terminal (e.g., the interaction of the "origin mode", limited ; scrolling region, and indexing), were gleaned from programming experiments ; on an actual VT100 terminal. Implemented features include: (1) Limited ; scolling region, (2) Settable tab stops, (3) Special "graphics" character ; set and UK ASII set, (4) All graphic renditions (underline, blink, and ; high intensity), (5) Simulated "LEDs" on the mode line, (6) Screen mode ; (normal or reverse video), (7) All terminal reports (status, active position, ; terminal parameters, and device attributes), (8) The ANSI new-line mode and ; several of the DEC private modes, including keypad application, cursor key, ; screen, auto-wrap, and origin, (9) cursor position/graphic rendition/ ; character set save/restore, and last (and probably least): (10) VT52 com- ; patibility mode. Also, various details of behavior required by the ANSI ; standard (e.g. most control characters do not affect the interpretation of ; the current escape sequence, relative cursor positioning (up, down, left ; right, and of course tab) stop at the screen margins, etc.) have been ; scrupulously observed. ; ; This was the first thing I ever wrote in 8088 assembler (some of it was ; stolen from MSYIBM), and one of the constraints was that the emulator ; should work with a vanilla PC with a monochrome monitor. Given these and ; other constraints, no attempt was made to implement the following VT100 ; features: (1) Smooth scolling, (2) 132 column lines, (3) Auto repeat, ; (5) Interlace/no interlace, (6) Double-width/double-height lines. The ; escape sequences to set and reset these are recognized, but ignored. ; ; - James A. Harvey, IUPUI Computing Services, DEC Systems Group ; ; * End of Disclamer * ; --------------------------------------------------------------------------- ; ; Description of the global entry points and calls on external routines ; needed by this emulator. [jrd] ; ; vsinit - start up routine called as Kermit initializes. Takes no arguments. ; Sets up address pointers to tabs, reads default terminal parameters ; reads current screen coloring. Examines and updates structure ; "vtemu." which is how mssset communicates changed information ; about many Set Term parameters; "flags." is a Kermit structure ; carrying the other Set Term parameters. ; anstty - starting point for displaying a character, delivered in AL. ; Returns when the display operation is completed and that may ; take many many instructions. All normal "characters received by ; the terminal" are provided by calling anstty with the char in AL. ; ansini - entry point to initialize the emulator. It requires information ; from msy in four registers: the Kermit terminal routine flags ; "yflags" (used mainly to sense debug mode and the mode line toggle) ; "low_rgt" (bh = row, bl = column of the lower right display corner) ; "lbaudtab" (index into baud rate table, for status reporting) ; "lpartab" (index into parity table, for status reporting) ; Ansini causes a full reset of the emulator, including screen ; clearing and a beep. Ansini is also called by msy in response to ; sensing the Alt = key combination to fully reset the emulator. ; ansrei - entry point to reinitialize the emulator. Nearly the same as ; ansini except operating flags, tabs, etc are retained from the ; previous emulator session. Items which can be changed by Set Term ; are examined and updated. The msy flags "yflags" are needed. ; This is the warm-restart entry point used when connect mode ; is reentered gracefully. The screen is cleared only if the coloring ; has changed. The starting cursor location is whereever msy puts it. ; ansdsl - display "led" (status line) information. Invoked by msy when ; the mode line is constructed so the emulator can write the ; terminal type and the VT100 led status lights when Connect mode ; is started. Requires "yflags" from msy to sense whether the mode ; line is to be shown. ; anstat - reports our working flags and screen coloring to msy. Nearly ; obselete but not quite. Reads msy "yflags" and reports "mlbattr" ; the video attributes used on the mode line, "scbattr" the video ; attributes of an empty character cell (background), "curattr" ; the video attributes of displayable characters, and "ansflgs" ; the emulator's working flags (needed for keyboard translations ; done in msy). ; anskbi - a routine called by msy to notify the emulator that a character ; is available from the keyboard. No character is read, just flag ; ttkbi is set. This is actually used only to beep when the cursor ; goes beyond column 72 and the margin bell flag is on. ; ans52t - called by msy to change terminal types "on the fly" without ; fully updating all operating parameters and without losing setup ; information. Msy senses the Alt minus key and calls ans52t with ; no arguments. Ans52t cycles among VT102, VT52 and Heath-19 modes. ; vclick - called by msy to cause a click sound. Simulates keyboard clicks, ; sort of anyway. No arguments. ; other modules in msy are called by this file to handle screen scrolling ; mode line on/off, output to the serial port (reports), screen ; particulars (location, cursor shape, blanking). The list is ; the set of code extrn procedures below; all are in file msy. ; ; data exchange is directly with msy to assist in scrolling (varaibles ; "mar_top", "mar_bot") and in sensing the non-connect ; mode screen coloring ("scbattr"). Screen coloring controlled by ; the emulator is not permitted to influence the non-connect mode ; screens whereas the emulator attempts to use the regular Kermit ; screen colors as defaults. The kind of terminal to emulate is ; held in byte "flags.vtflg" which is set by Set Term and by this ; module for global information within Kermit. ; ; The emulator assumes the screen is laid out in the manner of a conventional ; IBM monochrome or color graphics adapter running in 80 column TEXT ; modes. That layout is one word per displayable location starting at ; the upper left corner (0,0) and running contiguously to the lower ; right corner (24,79). Each word holds the displayable character in ; the low order byte and the display attributes in the high order ; byte. Attributes are, from high to low bits: blinking on, back- ; ground red, green, and blue on, high intensity, foreground red, ; green, and blue on. Normal white chars on a black field is 07H. ; The starting segment of screen memory is given by msy module ; "scrseg" to be TopView/MS Windows compatible. Msy module "scrsync" ; is used to inform these windowing environments of memory updates. ; Variable "crt_mode" is set by msy to indicate which IBM display ; mode is active; only the monochrome and CGA modes are recognized. ; Direct reading and writing of display memory is done, compatibly ; with TopView/Windows, to attain speed over Bios and DOS calls ; when editing of previously entered text is needed. However, IBM ; Bios interrupt 10H is used where possible for normal cursor ; movement/sensing and writing of new characters. See the IBM PC ; hardware Technical Reference Manuals for further details. ; ; Many things have been added, or modified since James Harvey donated this ; code to Columbia University for use in Kermit. [jrd] ; --------------------------------------------------------------------------- ; This macro flips the rev_video bit of attribute in ah. RFG ; NB this neither changes any other attribute nor any other register flip_rev_video macro local flip,flop test ah,att_rev_video jnz flip or ah,att_rev_video jmp flop flip: and ah,not att_rev_video flop: nop endm screen equ 19H ; Bios screen call (NEC special) printer equ 1BH ; Bios printer call (NEC special) swidth equ 132 ; assumed max screen width [dlk] slen equ 43 ; assumed max screen length [jrd] att_low_mask equ 1fH ; Various NEC attribute-related equates att_overline equ 01H ; this is all NEC version stuff RFG att_blink equ 02H att_rev_video equ 04H att_underline equ 08H att_intensity equ 04H ; same as reverse video nec_black equ 00H ; This table gives colors RFG nec_blue equ 20H ; (only bits 8,7,6 count) nec_red equ 40H nec_magenta equ 60H nec_green equ 80H nec_cyan equ 0A0H nec_yellow equ 0C0H nec_white equ 0E0H ; VT100 status flags ansflg ;anslnm equ 01H ; ANSI line feed/new line mode ;decckm equ 02H ; VT100 cursor keys mode ;deckpam equ 04H ; VT100 keypad application mode ;decscnm equ 08H ; VT100 screen mode (n.y.i.) ;decom equ 10H ; VT100 origin mode ;decawm equ 20H ; VT100 autowrap mode ;decanm equ 40H ; ANSI(VT100)/VT52 mode ;decmode equ 80H ; "?" seen in lead-in ;;;;;;;;;;;;;;;; items for reference from mssdef.h ;;;;;;;;;;;;; ; VT100 SETUP mode flags ;vsscreen equ 40H ; Screen mode (0 = normal video) ;vscursor equ 20H ; Cursor (0 = block) ;vsmarginbell equ 10H ; Margin bell (0 = off) ;vskeyclick equ 08H ; Keyclick (0 = off) ;vsshift3 equ 04H ; Shift-3 (0 = American pound sign) ;vswrap equ 02H ; Line wrap around (0 = no wrap) ;vsnewline equ 01H ; ANSI new line (0 = off) ;vsdefaults equ 0+vscursor ;[IU1] Definitions for terminal emulation ;TTGENRC EQU 0 ; Type 0 - TTY (no special emulation) ;TTHEATH EQU 1 ; Type 1 - HEATH 19 ;TTVT52 EQU 2 ; Type 2 - VT52 ;TTVT100 EQU 3 ; Type 3 - ANSI (VT100 subset) ;TTTEK EQU 4 ; Type 4: Tektronix 4010 ;TTTYPES equ 5 ; Number of terminal types defined ;emulst struc ; structure of vtemu.xxx for VT100 emulator ;vtflgst db 0 ; VT100 setup flags (from SET) ;vtflgop db 0 ; VT100 runtime flags, like setup flags (here & STAT) ;vttbs dw 0 ; pointer to default tab stops, for SET ;vttbst dw 0 ; pointer to active tab stops, for STATUS ;att_ptr dw 0 ; pointer to normal & reverse video attributes ;emulst ends ;;;;;;;;;;;;;;;; end references ;;;;;;;;;;;;;;;;;;;; datas segment public 'datas' extrn vtemu:byte, crt_mode:byte, scbattr:byte, flags:byte extrn crt_lins:byte, crt_cols:byte, rxtable:byte, denyflg:word extrn tekflg:byte ; Early versions of MASM have a bug that causes it to consider the ; expression (offset foo) as non-relocatable if used in an arithmetic ; operation (for example, "sub di,offset foo"), and if foo is defined ; within the first 256 bytes of the data segment. ; ANSI special character table - 32 entries indexed by control char value ansspc dw 5 dup (atign) ; ignore NUL,SOH,STX,ETX,EOT dw atign ; ENQ - answerback message dw atign ; ACK - ignore dw atbel ; BEL - ring terminal bell dw atbs ; BS - ANSI backspace dw atht ; HT - ANSI tab dw atlf ; LF - ANSI line feed dw atlf ; VT - Interpreted as ANSI LF dw atff ; FF - do as LF (but ESC FF does Tek) dw atcr ; CR - ANSI carriage-return dw atso ; SO - Select char set G1 dw atsi ; SI - Select char set G0 dw 8 DUP (atign) ; ignore DLE,DC1,DC2,DC3,DE4,NAK,SYN,ETB dw atcan ; CAN - cancel ANSI sequence dw atign ; EM - ignore dw atcan ; SUB - treat as CAN dw atesc ; ESC - ANSI CSI. dw 4 DUP (atign) ; ignore FS,GS,RS,US ; Heath-19 mode escape follower table h19esc db 'YABCD', 'KIHJF', 'G=>','<','Z' db '7','8','c','^','_' db 'W','X',']','V' lv52esc equ $-v52esc ; length of table ; Dispatch for v52esc table v52ejt dw v52pos,atcuu,atcud,atcuf,atcub dw atel,atri,atcup,ated,v52egm dw v52xgm,atkpam,atkpnm,v52ans,decid dw atsc,atrc,v52ris,v52apb,v52ape dw v52pcb,v52pce,v52ps,v52pl ; ANSI escape special character table ansesc db '[','D','E','M','H' db '7','8','=','>','c' db '(',')','#','Z','<' db 'P','*' lansesc equ $-ansesc ; length of table ; Dispatch for ansesc table ansejt dw atcsi,atind,atnel,atri,athts dw atsc,atrc,atkpam,atkpnm,atris dw atsg0,atsg1,atsdhl,at52id,atnorm dw atpriv,atpriv ; Final char table for ANSI escape sequences (ESC [ Pn ; ... Pm ch) anstab db 'H','A','B','C','D' db 'K','J','m','g','r' db 'c','q','x','n','f' db 'l','h','y','P','L' db 'M','i','s','u','z' db '@' lanstab equ $-anstab ; Define table length ; Dispatch for anstab table ansjmp dw atcup,atcuu,atcud,atcuf,atcub dw atel,ated,atsgr,attbc,atstbm dw atda,atll,atreqt,atdsr,atcup dw atrm,atsm,atctst,atdelc,inslin dw dellin,ansprt,htsc,htrc,htrest dw ansich ; "Special graphics" set translation table for characters 137 (octal) ; through 176 when the special graphics set is selected. Some characters ; (142, 143, 144, 145, 150, 151, 157, 160, 162, 163, and 174) do not ; have exact equivalents in the available set on the IBM, so a (some- ; times reasonably close) substitution is made. Table is indexed by ; ASCII char value minus 137 octal for chars 137-176 octal. sgrtab db 032,004,177,026,023 db 027,025,248,241,021 db 018,217,191,218,192 db 197,196,196,196,196 db 196,195,180,193,194 db 179,243,242,227,157 db 156,250 ; Device attributes response string. (Note: If "with AVO" causes problems, ; change the last parameter from "2" to "0". The default is to indicate ; the AVO option is present because the emulator can set all of the graphic ; rendition attributes (bold, blink, etc.) independently). A VT100 reports ; as ESC [ ? 1 ; 2 c but a VT102 uses ESC [ ? 6 ; 2 c. dastr db escape,'[?6;2c' ; VT102 ldastr equ $-dastr ; Identify response used while in VT52 compatibility mode... v52str db escape,'/Z' lv52str equ $-v52str ; Identify response when a Heath-19 terminal. [jrd] h19str db escape,'/K' lh19str equ $-h19str ; ANSI Escape sequence to turn off Media Copy (Print Controller Off) mcoff db escape,'[4i' mcofflen equ $-mcoff ; length of sequence mcoffs db 4 dup (0) ; received chars in sequence mccnt dw ? ; counter of matched char in mcoff ; Parity code translation table partab db 5 ; Even db 3 ; Mark db 1 ; None db 4 ; Odd db 2 ; Space lpartab equ $-partab ; Baud rate code translation table baudtab db 0 ; 45.5 - no VT100 code (call it 50) db 0 ; 50 db 8 ; 75 db 16 ; 110 db 24 ; 134.5 db 32 ; 150 db 48 ; 300 db 56 ; 600 db 64 ; 1200 db 72 ; 1800 db 80 ; 2000 db 88 ; 2400 db 104 ; 4800 db 112 ; 9600 db 120 ; 19200 db 128 ; 38400 extended beyond DEC [jrd] lbaudtab equ $-baudtab belcol db ? ; column at which to ring margin bell yflags db ? ; Flags from MSYxxx term routine. video_state db 0 ; video state (0=normal,1=reversed) oldbatr db ? ; old scbattr [jrd] oldterm db ? ; terminal type from previous entry baudidx db ? ; Index into baud rate table parcode db ? ; Parity code (0-4) datbits db ? ; Number of databits (7 or 8) savflgs db ? ; Saved flags for atsc/atrc. modeset db ? ; Temp for atsm/atrm. h19mod db ? ; flag for atsm/atrm. h19l25 db ? ; Heath-19 25th line enabled flag insmod db ? ; Insert mode on (1) or off (0).[jrd] kbicsr dw ? ; Cursor when keyboard input typed kbiflg db ? ; Set/reset for keyboard input ttstate dw offset atnrm ; terminal automata state. ; Start of stuff to save for ESC 7 fxn ukset equ 0 ; Set 1 = UK ASCII set ascset equ 1 ; Set 2 = US ASCII set sgrset equ 2 ; Set 3 = "Special graphics set" svattr_index equ 0 ; To set saved cursor attribute only. curattr db 07h ; Cursor attribute cursor dw 0 ; Cursor position chr_set dw offset chr_sg0 ; Ptr. to currently selected char set chr_sg0 db ascset ; Current SG0 set chr_sg1 db ascset ; Current SG1 set lsavecu equ $-curattr ; Length of stuff to save. savecu db lsavecu dup (?) ; Saved cursor, attr., charset, etc. h19ctyp db 1 ; H-19 cursor type (1=ul, 2=bk, 4=off) att_normal db 07H ; retain order: normal then reverse att_reverse db 70H mlbattr db ? ; Mode line background attribute ansflgs db 0 ; ANSI/VT100 mode flags ; (flags are defined in mssdefs.h) vtflags db 0 ; VT100 SETUP flags ; (SETUP flags are defined in mssdefs.h) tmpflags db 0 ; (Temporary for asnrei/stblmds). ; (tab stops are stored here) ; [jrd] tabs db swidth dup (?) ; active tab stops. deftabs db swidth dup (?) ; default tab stops vttabs dw 0 ; Pointer to default VT100 tab stops ; byte per line, type of line: 0=normal, 1=double wide, 2=double high [jrd] linetype db slen dup (?) linelen db 79 ; active screen line length (79, 131) low_rgt dw 0 ; text screen dimensions. ; byte low_rgt = max columns (79) ; byte low_rgt+1 = max rows (23) ttkbi db 0 ; Flag for keyboard input seen. ; Scrolling region - do not separate or change order of mar_top & mar_bot. mar_top db ? ; Scrolling region top margin mar_bot db ? ; Scrolling region bottom margin led_col equ 65 ; column position for "LEDs" display led_off equ '.' ; "Off" LED. [jrd] ansleds db 'VT102 ....' ; "LEDs".Terminal ident (10 bytes) v52leds db ' VT52 ' ; This is used in VT52 mode. h19leds db ' Heath-19 ' ; For Heath-19 mode [jrd] ; message for mode line [jrd] pntmsg db 'Printer not ready, printing request skipped.' pntmsgl equ $-pntmsg ; length of pntmsg nansarg db 0 ; Index for ANSI argument list ansargs db 16 dup (0) ; Room for 16 ANSI arguments lansarg equ $-ansargs ; Max number of ANSI arguments ; printer support data anspflg db 0 ; printer flag bits and definitions vtautop equ 1 ; autoprint enabled (1) vtcntp equ 2 ; controller print enabled (1) vtextp equ 4 ; printer extent set (1) vtffp equ 8 ; form feed wanted at end of print (1) datas ends code segment public 'code' extrn prtbout:near, prtnout:near, csrtype:near, trnmod:near extrn scrmod:near, scrseg:near, scrsync:near, scroff:near extrn scron:near, atsclr:near, vtscru:near, vtscrd:near extrn modwrt:near, telmsy:near, scrloc:near, pcwait:near extrn chgdsp:near, trnprs:near, cptchr:near, tekesc:near ; extrn procedures are all in module msyibm extrn tekini:near, tekemu:near, tekend:near extrn beep:near ; NEC use assume cs:code, ds:datas, es:datas ; This routine initializes the VT100 setups at startup. It is called from ; procedure lclyini in module msyibm. vsinit proc near mov vtemu.vtflgst,vsdefaults ; Init to defaults in mssdef.h mov vtemu.vtflgop,vsdefaults ; Init runtime state to setup items mov insmod,0 ; turn off insert mode. [jrd] mov deftabs,0 ; Column 1 has no tab stop. mov cl,crt_cols ; physical screen width (80) dec cl ; we count from column 0 mov ch,crt_lins ; physical screen length-1 dec ch ; we count from row 0 mov low_rgt,cx ; store active text area mov cx,131 mov di,1 ; Starting index for column 2. vsini1: mov al,0 ; Assume we will clear this one. test di,0007H ; Index mod 8 equals 0? jnz vsini2 ; No, clear it. mov al,0FFH ; Yes, set it. vsini2: mov deftabs[di],al ; Set or clear a tab stop. inc di ; Advance to next. loop vsini1 ; Loop for all. mov cx,slen ; clear linetype array [jrd] mov di,0 vsini3: mov linetype[di],0 inc di loop vsini3 mov vtemu.vttbst,offset deftabs ; addrs of active tabs for STATUS mov vtemu.vttbs,offset deftabs ; addrs of tabs for setup (SET) mov vttabs,offset deftabs ; initial source of tabs. [jrd] call cpytabs ; copy default to active [jrd] mov vtemu.att_ptr,offset att_normal ; ptr to video attributes[jrd] mov ah,8 ; read current attributes xor bh,bh ; page 0 int screen mov scbattr,ah ; save video attributes mov att_normal,ah ; set att_normal to present colors flip_rev_video ; NEC mov att_reverse,ah ; set att_reverse too. mov ah,byte ptr low_rgt ; right most column (counted from 0) sub ah,8 ; place marker 9 columns from margin mov belcol,ah ; store column number to ring bell ret ; And return. vsinit endp ; Initialization routine. ; ; Call: al/ yflags byte that was passed to Term routine. ; dl/ index for baud rate table ; dh/ parity in bits 4-7, number of data bits in bits 0-3 ; ansini proc near mov yflags,al ; Always save flags mov ah,vtemu.vtflgst ; setup flags [jrd] mov vtflags,ah mov vttabs,offset deftabs ; tab stop pointer. mov vtemu.vttbst,offset tabs; store here for STATUS [jrd] mov al,flags.vtflg ; get current terminal type mov oldterm,al ; remember it here for soft restarts mov insmod,0 ; turn off insert mode. [jrd] mov h19l25,0 ; clear Heath 25th line enable. [jrd] mov h19ctyp,1 ; set Heath cursor to underline, on mov anspflg,0 ; clear printer flag [jrd] push ax mov ah,byte ptr low_rgt ; right most column (counted from 0) sub ah,8 ; place marker 9 columns from margin mov belcol,ah ; store column number to ring bell pop ax cmp dl,lbaudtab ; Wierd index? jb ansin1 ; No - OK - store it. mov dl,lbaudtab-1 ; Yes - make it the maximum. ansin1: mov baudidx,dl ; Save baud rate index mov al,dh ; Get parity/number of databits and al,0FH ; Isolate number of databits mov datbits,al ; Save. mov cl,4 ; Isolate parity code shr dh,cl ; Isolate parity code cmp dh,lpartab ; Weird code? jb ansin2 ; No - OK - store it. mov dh,lpartab-1 ; Yes - make it the maximum. ansin2: mov parcode,dh ; Save. call scrmod ; Get the screen mode, in MSYxxx mov cl,crt_cols ; physical screen number columns (80) dec cl ; we count from column 0 here mov ch,crt_lins ; physical screen number rows-1 (24) dec ch ; we count from row 0 here mov low_rgt,cx ; save as active text screen size ansin3: call atreset ; Reset everything mov ttstate,offset atnrm ; Reset state to "normal". ret ; And return. ansini endp ; Re-initialization routine. Called when Term was called but screen was ; restored from a previously saved screen, etc. ; ; Call: al/ yflags byte that was passed from msyibm module. ; ansrei proc near mov yflags,al ; Always save flags mov ah,vtemu.vtflgop ; get runtime flags [jrd] mov tmpflags,ah call scrmod ; Get the screen mode. call atsctyp ; set cursor type [rbv] mov ah,3 ; get cursor position from msy mov bh,0 ; Page zero. int screen mov cursor,dx ; dh = row, dl = column mov cl,crt_cols ; physical screen number columns (80) dec cl ; we count from column 0 here mov ch,crt_lins ; physical screen number rows-1 (24) dec ch ; we count from row 0 here mov low_rgt,cx ; save as active text screen size cmp linelen,79 ; want 80 cols? ja ansre2 ; a = no cmp byte ptr low_rgt,79 ; want 80 cols. Is active screen wider? jbe ansre2 ; be = no mov byte ptr low_rgt,79 ; narrow down to 80 columns ansre2: call stblmds ; Check settable modes, set flags. ret ansrei endp ; This routine copies the new tab stops when they have changed. ; Copies all 132 columns. cpytabs proc near mov cx,swidth ; number of screen columns jcxz cpytab1 ; z = none to do mov si,vttabs ; Source. mov di,offset tabs ; Destination. push es ; save es push ds pop es ; set es to datas segment cld rep movsb ; Do the copy. pop es ; recover es cpytab1:ret cpytabs endp ; This routine checks to see whether any of the settable modes have changed ; (things that can be changed in both SETUP and by host commands), and ; changes those that need to be changed. TMPFLAGS has the new VT100 setup ; flags, VTFLAGS has the old. This routine also updates VTFLAGS. ; Revised by [jrd] to allow MSY to reset scbattr when not in connect mode, ; to do "soft reset" if terminal type has changed, and to do a screen clear ; reset if the actual screen colors have changed. stblmds proc near mov al,flags.vtflg ; get current terminal type [jrd] cmp al,oldterm ; same as before? je stblm10 ; e = yes, skip over soft reset. mov oldterm,al ; remember current terminal type mov insmod,0 ; reset insert mode flag mov h19l25,0 ; reset heath-19 25th line enable mov mar_top,0 ; reset top scrolling margin mov al,byte ptr low_rgt+1 ; and scrolling margin mov mar_bot,al ; to last normal line on screen mov ah,byte ptr low_rgt ; right most column (counted from 0) sub ah,8 ; place marker 9 columns from margin mov belcol,ah ; store column number to ring bell and ansflgs,decckm+deckpam+decom ; save some flags push bx ; save this register around loop mov bx,offset linetype ; setup to clear double width chars mov cx,slen ; number of linetype slots to clear cmp flags.vtflg,ttvt100 ; VT100 now? jne stblm0 ; ne = no or ansflgs,decanm ; set ansi flag bit stblm0: mov byte ptr [bx],0 ; clear the linetype array to single inc bx ; width characters. loop stblm0 ; do each line (1 byte per line) pop bx ; restore bx stblm10:mov al,tmpflags ; Get the new flags. and ansflgs,not anslnm ; assume we do not want newline test al,vsnewline ; is newline mode desired? jz stblm1 ; No - continue. or ansflgs,anslnm ; Yes - set corresponding mode flag. stblm1: and ansflgs,not decawm ; assume not want wrap test al,vswrap ; Did wrap mode change? jz stblm2 ; No - continue. or ansflgs,decawm ; Yes - set corresponding mode flag. stblm2: mov ah,vtflags ; old flags xor ah,tmpflags ; new flags test ah,vsshift3 ; pick out char set bit jz stblm4 ; z = no change mov ah,ascset ; assume US ASCII. test tmpflags,vsshift3 ; Want UK? jz stblm3 ; No - guessed right. mov ah,ukset ; Yes - use UK set. stblm3: mov chr_sg0,ah ; Set the sets. mov chr_sg1,ah stblm4: push ax ; very necessary! NEC version mov al,oldbatr ; keep old value around a bit mov ah,att_normal ; get new attributes (Set Term Color) mov scbattr,ah ; and update working copy mov oldbatr,ah ; and save it here as well flip_rev_video mov att_reverse,ah ; and configure the reverse mov mlbattr,ah ; and also here for mode line and ah,not att_low_mask ; look at color only and al,not att_low_mask cmp ah,al ; has anything changed? pop ax je stblm9 ; e = no mov cursor,0 ; reset cursor position jmp atres2 ; go to semi-reset stblm9: ; check on screen normal/reversed. mov al,tmpflags xor al,vtflags ; Find which ones have changed. test al,vsscreen ; How about screen background? jz stblm8 ; No - don't touch it. test tmpflags,vsscreen ; Flag to be set? jnz stblm5 ; Yes - go to it. and ansflgs,not decscnm ; No - cleared (normal video). and savflgs,not decscnm mov al,att_normal ; No - get new background. jmp short stblm6 ; And reverse everything. stblm5: or ansflgs,decscnm ; Set (reverse video). or savflgs,decscnm mov al,att_reverse ; No - set reverse video. stblm6: call atrss2 ; Reverse screen and cursor attribute. stblm7: mov al,scbattr ; Reset saved attribute also. mov savecu+svattr_index,al mov oldbatr,al ; and save our attribute stblm8: mov al,tmpflags ; Get new flags. mov vtflags,al ; Store them. ret stblmds endp ; Return screen offset - given rol, col in dx, returns offset of the word ; for that character from the screen origin in ax. Preserves all other acs. ; Use same routine in msy to more closely track screen width. [jrd] ;;scrloc proc near ;; push bx ; We will use bx. ;; mov al,dh ; Get row. ;; mov bl,swidth ; And length of a line ;; mul bl ; Offset for this row ;; mov dh,0 ; Clear row. ;; add ax,dx ; Word offset for this position ;; sal ax,1 ; Make it a byte offset ;; pop bx ; Restore bx. ;; ret ; And return. ;;scrloc endp ; Fetch status/attributes routine. ; ; Call: al/ "yflags" byte from MSYxxx. ; ; Return: ah/ mode line background attribute ; al/ screen background attribute ; bl/ current cursor attribute ; bh/ ANSI (VT100) mode flags anstat proc near mov yflags,al ; Mostly for disleds mov ah,mlbattr ; Return them our attrs, flags, etc. mov al,scbattr mov bl,curattr mov bh,ansflgs ret anstat endp ; Routine called when something is typed on the keyboard ; ; Call: No arguments ; anskbi proc near mov ttkbi,0FFH ; Just set a flag ret anskbi endp ; vclick omitted for NEC vtbell proc near call beep ; NEC form ret vtbell endp ; vtsound omitted for NEC ; Routine to toggle VT100/VT52/Heath-19 modes. No arguments. ; Use & update global byte flags.vtflg for terminal type and update local ; bit decanm. Note: shifting to Heath-19 here does Not reset the scrolling ; margins mar_top & mar_bot nor reset the double char linetype array. ; [jrd] ans52t proc near cmp tekflg,0 ; in Tek sub mode? jne ans52c ; ne = yes, get out now cmp flags.vtflg,ttvt100 ; in VT100 mode? jne ans52a ; ne = no and ansflgs,not decanm ; reset VT100 ansi mode mov flags.vtflg,ttvt52 ; say VT52 now (clears vt100 bit) mov oldterm,ttvt52 ; and remember it jmp ans52e ans52a: cmp flags.vtflg,ttvt52 ; in VT52 mode? jne ans52b ; ne = no mov flags.vtflg,ttheath ; say Heath-19 now mov oldterm,ttheath jmp ans52e ans52b: cmp flags.vtflg,ttheath ; in Heath-19 mode? jne ans52c ; ne = no call atsc ; save cursor and associated data mov flags.vtflg,tttek ; set Tek mode call tekini ; init Tek to switch screens jmp atnorm ; normal state and return ans52c: cmp flags.vtflg,tttek ; in Tek mode now? je ans52d ; e = yes cmp tekflg,0 ; doing Tek sub mode? jne ans52d ; ne = yes jmp atnorm ; else ignore this call ans52d: call tekend ; exit Tek graphics mode mov tekflg,0 ; end Tek sub mode (do after tekend) mov flags.vtflg,ttvt100 ; say VT100 now mov oldterm,ttvt100 or ansflgs,decanm ; set, go to VT100 mode call atrc ; restore cursor etc cmp flags.modflg,0 ; is mode line disabled? [jrd] je ans52e ; e = yes, disabled [jrd] test yflags,modoff ; Mode line off? jnz ans52e ; nz = yes - just return. mov al,yflags ; get current flags or al,modoff ; say mode line is off call telmsy ; let msy hear the news call trnmod ; turn it on ans52e: call chrdef ; Set default character sets call atsc ; Save cursor etc. call disleds ; Remove or redisplay "LEDs". jmp atnorm ; Say state is "normal" and return. ans52t endp ; Display "LEDs" routine. Note that this routine ; is not used internally in this module (because it updates the flags from ; MSYIBM). Internally, disleds is used instead. The yflags from MSYIBM are ; needed because we have to know if the mode line is enabled. ; ; Call: al/ yflags from MSYIBM ; ; Return: Current state of "LEDs" displayed on line 25. ; ansdsl proc near ; Update flags and display "LEDs" mov yflags,al ; Update the flags. call disleds ; Display LEDs ret ansdsl endp ; Internal routine to display LEDs. disleds:test yflags,modoff ; Mode line off? jnz disled2 ; Yes - just return. ;; mov al,0 ; Turn cursor off. ;; call csrtype mov ah,2 ; Position cursor at (slen-1),70 mov bh,0 ; Page zero. mov dh,byte ptr low_rgt+1 ; last screen line - 1 inc dh ; status line mov dl,led_col ; column for led display int screen mov cx,10 ; Length of byte array is ten mov si,offset ansleds ; The "LEDs" cmp flags.vtflg,ttvt100 ; VT100 mode? je disled1 ; e = yes mov si,offset v52leds ; try VT52 cmp flags.vtflg,ttvt52 ; VT52? je disled1 ; e = yes mov si,offset h19leds ; use Heath-19 disled1:lodsb ; Get a character push si ; an NEC addition RFG mov ah,14 ; Write character function mov bh,0 ; Page zero. int screen ; ... pop si ; an NEC addition RFG loop disled1 ; Loop for all chars mov ah,2 ; Reposition cursor when finished mov bh,0 ; Page zero mov dx,cursor int screen call atsctyp ; Reset right type of cursor. disled2:ret ; ANSI terminal output routine. Call with character in al. anstty proc near ; ANSI terminal output. mov dx,cursor ; Some routines need cursor in dx. mov kbiflg,0 ; Clear old flag value test yflags,trnctl ; Debug mode? jz anstt1 ; z = no jmp atdeb ; Yes - just translate control chars. anstt1: cmp ttkbi,0 ; New keyboard input? je anstt2 ; No - just continue mov kbiflg,1 ; Yes - set flag mov kbicsr,dx ; Save old cursor mov ttkbi,0 ; Clear this flag. anstt2: test anspflg,vtcntp ; print controller on? jz anstt4 ; z = no test yflags,capt ; capturing output? jz anstt3 ; z = no, forget this part push ax ; save char call cptchr ; give it captured character pop ax ; restore character anstt3: jmp ansmc ; print transparently ; Set Display 7/8 bit filter anstt4: test flags.remflg,d8bit ; keep 8 bits for displays? jnz anstt5 ; nz = yes, 8 bits if possible and al,7fh ; remove high bit anstt5: cmp al,spc ; control char? jb anstt6 ; b = yes cmp ttstate,offset atnrm ; doing displayable text? jne anstt7 ; ne = no, no translation ; Set Translation filter anstt6: cmp rxtable+256,0 ; translation turned off? je anstt7 ; e = yes, no translation mov bx,offset rxtable ; address of translate table [jrd] xlatb ; new char is in al anstt7: cmp al,DEL ; ANSI Delete char? je atdel ; e = yes, ignore it before logging cmp al,0 ; NUL char? je atign ; e = yes, ignore it before logging test yflags,capt ; capturing output? jz anstt8 ; z = no, forget this part push ax ; save char call cptchr ; give it captured character pop ax ; restore character and keep going ; Direct char to processor module anstt8: cmp al,20h ; Control character? jb atctrl ; b = yes, handle it. anstt9: jmp ttstate ; Nope, dispatch according to state. atign: ret ; Something to be ignored. atctrl: mov ah,0 ; Make sure this is zero.. cmp al,escape ; an escape sequence starting? je atctrl1 ; e = yes, don't print it test anspflg,vtautop+vtcntp ; printing desired? jz atctrl1 ; z = no call pntchr ; print char in al atctrl1:mov di,ax ; Put it in an index register shl di,1 ; Make it a word offset jmp ansspc[di] ; Dispatch. atdel: jmp short atign ; ignore DEL char ;; test yflags,lclecho ; doing local echoing? ;; jz atign ; z = no, ignore character ;; mov ansargs,0 ; Delete one char to left [jrd] ;; cmp dl,0 ; at column 0 already? ;; je atdel1 ; e = yes ;; dec dl ; move back one column ;;atdel1: call atscu5 ; move the cursor there and ;; jmp atdelc ; delete the char now under cursor atdeb: test yflags,capt ; capturing output? jz atdeb3 ; z = no, forget this part push ax ; save char call cptchr ; give it captured character pop ax ; restore character and keep going atdeb3: mov bh,ansflgs ; Save flags and attribute mov bl,curattr push bx push word ptr mar_top ; Save limited scrolling region push ax ; Save character for a second mov ah,curattr ; Get attribute call brkatt ; Break it up and al,0 ; NEC clear all attributes call addatt ; Put it back together mov curattr,ah ; Store or ansflgs,decawm ; Set autowrap temporarily mov mar_top,0 ; Set scrolling region to entire page mov al,byte ptr low_rgt+1 mov mar_bot,al pop ax ; Restore character test al,80h ; high bit set? [jrd] jz atdeb0 ; z = not set push ax ; Save the character for a second mov al,7eh ; Output a tilde [jrd] call atnrm2 pop ax ; Restore character and al,7fh ; and remove high bit atdeb0: cmp al,del ; A DELETE? je atdeb1 ; Yes - output "^?" [jrd] cmp al,20h ; A control character? jnb atdeb2 ; No - just output char in al. atdeb1: push ax ; Save the character for a second mov al,5eh ; Output a caret [jrd] call atnrm2 pop ax ; Restore character add al,40h ; Make ^letter (or ^? for DELETE) and al,7fh ; Clear bit 7 (for DELETE) atdeb2: call atnrm2 ; Output translated character pop word ptr mar_top ; Restore scrolling region pop bx ; And flags and cursor attribute mov curattr,bl mov ansflgs,bh ret atnorm: mov ttstate,offset atnrm ; Reset state to "normal". ret ; Normal character processor atnrm: mov bx,chr_set ; Get character set cmp byte ptr [bx],sgrset ; "Special" set? jne atnrm1 ; No - check UK. cmp flags.vtflg,ttheath ; Heath-19? je atnrm0a ; e = yes cmp al,137Q ; Yes - is it in the "special" range? jb atnrm2 ; No - just output the char in al. mov bl,al ; Yes - compute index in bx. mov bh,0 sub bx,137Q mov al,sgrtab[bx] ; Fetch translation. jmp short atnrm2 ; Output it. atnrm0a:cmp al,94 ; H-19, in range for special graphics? jb atnrm2 ; b = no cmp al,126 ; too large? ja atnrm2 ; a = too large sub bx,94 ; H-19, offset from caret mov bl,al mov bh,0 sub bx,94 mov al,hgrtab[bx] ; fetch translation jmp short atnrm2 atnrm1: cmp al,'#' ; This thing? jne atnrm2 ; No - just output it cmp byte ptr [bx],ukset ; Yes - UK set? jne atnrm2 ; No - just output it. mov al,156 ; Yeah, show them our pound sign. atnrm2: mov dx,cursor ; get cursor virtual position push ax ; save character call atscur ; set cursor physical position pop ax cmp insmod,0 ; insert mode off? [jrd] je atnrm3 ; e = yes [jrd] push ax ; save char call inschr ; open a char space in this line [jrd] push bx mov bx,cursor ; get current row mov bl,bh mov bh,0 cmp linetype [bx],0 ; single width line? je atnrm2a ; e = yes call inschr ; open second space for double width atnrm2a:pop bx pop ax ; restore char atnrm3: ; set cursor before writing char mov bl,dh ; check for double characteristic xor bh,bh ; bx = row, in bl test anspflg,vtautop ; printing desired? [jrd] jz atnrm4d ; e = no call pntchr ; print char in al cmp linetype [bx],0 ; normal characteristic? je atnrm4d ; e = yes push ax ; save current char mov al,' ' ; add a space for double width call pntchr pop ax ; recover char to be processed atnrm4d: cmp linetype [bx],0 ; normal characteristic? je atnrm4a ; e = yes push ax ; save char shl dl,1 ; double the column number mov ah,2 ; set cursor (bh = 0 from above) int screen pop ax ; recover the char mov ah,9 ; Output char in al to screen [jrd] mov bh,0 ; Page zero mov bl,curattr ; Current attribute mov cx,1 ; Only one character int screen inc dl ; next column mov ah,2 ; set cursor int screen mov al,' ' ; use a space for doubling mov ah,9 ; Output to screen [jrd] mov bh,0 ; Page zero mov bl,curattr ; Current attribute mov cx,1 ; Only one character int screen shr dl,1 ; keep "cursor" in single units jmp atnrm4b ; check autowrap in double width mode atnrm4a:mov ah,9 ; Output to screen [jrd] mov bh,0 ; Page zero mov bl,curattr ; Current attribute mov cx,1 ; Only one character int screen ; set physical cursor after this char atnrm4b:test ansflgs,decawm ; Autowrap? jz atnrm5 ; No, continue mov cx,low_rgt ; copy logical cursor margins to cx push bx mov bl,dh ; get row xor bh,bh cmp linetype[bx],0 ; single width line? pop bx ; pop preserves flags je atnrm4c ; e = yes, single shr cl,1 ; halve right column # for wide chars atnrm4c:cmp dl,cl ; wrote in right-most column? jb atnrm5 ; b = no inc dl ; say want to use next column cmp flags.vtflg,ttheath ; emulating a H-19? [uci] je atscur ; e = yes, show wrap now. [uci] mov cursor,dx ; virtual cursor position ret ; exit without moving cursor from eol atnrm5: mov dx,cursor ; Restore cursor position inc dl ; Bump cursor atscur: cmp dl,250 ; To left of column zero?(wide screen) jb atscu1 ; b = no, continue mov dl,0 ; Yes - set at column zero. atscu1: mov cx,low_rgt ; copy logical margins; cl=right col push bx mov bl,dh ; get row xor bh,bh cmp linetype [bx],0 ; single width lines? pop bx je atscu1a ; e = yes, single width shr cl,1 ; halve column # for double wides atscu1a:cmp dl,cl ; To right of right margin? jbe atscu3 ; be = no, continue mov dl,cl ; Yes - assume no autowrap. test ansflgs,decawm ; Autowrap? jz atscu3 ; No, continue mov dl,0 ; Yes - set to column zero cmp dh,byte ptr low_rgt+1 ; at bottom of screen? je atscu1b ; e = yes cmp dh,mar_bot ; At bottom of scrolling region? jl atscu2 ; l = No - bump cursor and continue atscu1b:call atscru ; Scroll up. dec dh ; offset inc dh below atscu2: inc dh ; Just bump it. atscu3: cmp dh,0 ; Constrain row to valid range. jge atscu4 ; ge = non-negative row, ok mov dh,0 atscu4: cmp dh,byte ptr low_rgt+1 ; 25th line? jle atscu5 ; le = no mov dh,byte ptr low_rgt+1 ; set to 24th line cmp flags.vtflg,ttheath ; emulating a Heath-19? jne atscu4a ; ne = no [hlk] cmp h19l25,0 ; Heath 25th line enabled? je atscu5 ; e = no jmp short atscu4b ; do 25th line atscu4a:test ansflgs,decom ; Origin mode active? ;;;## jz atscu5 ; z = no, no 25th line allowed atscu4b:inc dh ; yes, go to line 25 [hlk] test yflags,modoff ; is mode line off? jnz atscu8 ; nz = yes push dx ; save cursor position call trnmod ; no, turn it off now. pop dx atscu8: mov flags.modflg,0 ; and disable mode line. [jrd] mov al,yflags ; place to communicate [jrd] call telmsy ; tell msy the news. [jrd] atscu5: push cx ; save cx around screen call mov cursor,dx ; Set cursor and return. mov ah,2 ; setup for position cursor call. mov bl,dh ; get row mov bh,0 cmp linetype [bx],0 ; single width line? je atscu5a ; e = yes shl dl,1 ; double the column number int screen ; set the physical cursor shr dl,1 ; restore dl (logical column) jmp short atscu5b atscu5a:int screen atscu5b:pop cx cmp kbiflg,0 ; Is keyboard input flag set? je atscu6 ; No - just return test vtflags,vsmarginbell ; Yes - do we care? jz atscu6 ; Return if no margin bell. mov dx,cursor ; Get new and old cursors mov bx,kbicsr cmp bh,dh ; Same row? jne atscu6 ; No - just return cmp bl,belcol ; Old cursor at or left of bell column? ja atscu6 ; a = no, just return cmp dl,belcol ; Yes - new cursor past bell column? jbe atscu6 ; be = no, just return call vtbell ; Yes - ring the bell atscu6: ret ; This routine is called to check the cursor position after any kind of cursor ; positioning command. Note that cursor positioning does NOT cause scrolling ; on a VT100 (hence the need for a routine separate from this for "indexing". ; ; Call: dx/ "new" cursor position (modified cursor) ; ; Return: dx/ "new" cursor position adjusted for screen limits (if ; decom is reset), or scrolling region (if decom is set). ; ; Preserves ax, bx, and cx. ; atccpc: push bx ; save bx and cx push cx atccp7: mov cx,low_rgt ; margins, cl = right margin mov bl,dh ; get row xor bh,bh cmp linetype [bx],0 ; single width line? je atccp0 ; e = yes, single width shr cl,1 ; halve right margin for double wides atccp0: cmp dl,250 ; To left of left margin?(wide screen) jb atccp1 ; b = no, go check right mov dl,0 ; No, set to left margin atccp1: cmp dl,cl ; To right of right margin jbe atccp2 ; be = yes, go check top mov dl,cl ; No, set to right margin atccp2: test ansflgs,decom ; Origin mode set? jnz atccp5 ; Yes, can't go out of scrolling region cmp dh,0 ; Above top of screen? jge atccp3 ; ge = no, check bottom mov dh,0 ; Yes, stop here atccp3: cmp dh,byte ptr low_rgt+1 ; Below bottom of screen? jle atccp4 ; le = no, return mov dh,byte ptr low_rgt+1 ; Yes, stop at bottom margin cmp flags.vtflg,ttheath ; Heath-19 mode? jne atccp4 ; ne = no cmp h19l25,0 ; 25th line enabled? je atccp4 ; e = no inc dh ; allow 25th line atccp4: pop cx pop bx ret atccp5: cmp dh,mar_top ; Above top of scrolling region? jge atccp6 ; ge = no, check bottom mov dh,mar_top ; Yes, stop there. atccp6: cmp dh,mar_bot ; Below bottom perhaps? jle atccp4 ; le = no, return mov dh,mar_bot ; Yes, stop at the bottom margin pop cx pop bx ret ; This routine is called to adjust the cursor for the "indexing" like commands ; (e.g., index, reverse index, newline, etc.). It contrains the cursor, and ; indicates if scrolling is necessary, and if so, in which direction. ; ; Call: cursor/ "old" cursor position ; dx/ "new" cursor position ; ; Return: ax/ pointer to scrolling routine to call (or to a ret) ; bx/ "old" cursor position ; dx/ "new" cursor position adjusted for screen limits or ; scrolling region, depending on whether the original ; cursor position was inside or outside the scrolling ; region. ; ; On the VT100, a scroll does not occur unless the original cursor position ; was on the top or bottom margin. This routine assumes that when decom is ; set the cursor position is set to the new origin, and that no other routine ; allows the cursor to be positioned outside the scrolling region as long ; as decom is set (which is the way a real VT100 works). Note that for the ; normal case (no limited scrolling region defined) the margins are the same ; as the screen limits and scrolling occurs (as on a "normal" terminal) when ; an attempt is made to index off the screen. Preserves cx. ; Revised 16 June 1987 [jrd] atccic: push cx mov cx,low_rgt ; get margins, cl = right margin mov bl,dh ; get row xor bh,bh cmp bl,ch ; Below screen? [jrd] jg atcci0 ; g = yes, use single width line cmp linetype[bx],0 ; single width chars? je atcci0 ; e = yes, single width shr cl,1 ; halve margin for double wides atcci0: mov ax,offset atign ; Assume no scrolling necessary mov bx,cursor ; Get old cursor. cmp dl,250 ; To left of left margin?(wide screen) jb atcci1 ; b = no, go check right mov dl,0 ; No, set to left margin atcci1: cmp dl,cl ; To right of right margin jbe atcci2 ; be = yes, go check top mov dl,cl ; No, set to right margin atcci2: cmp bh,mar_top ; was old pos at scrolling top margin? jne atcci5 ; ne = no, check other end cmp dh,mar_top ; want to go above top margin? jge atcci7 ; ge = no mov ax,offset atscrd ; Yes, indicate scroll down required. mov dh,mar_top ; Set to top margin jmp atcci7 atcci5: cmp bh,mar_bot ; Was old position at bottom margin? jne atcci7 ; ne = no, so don't trap cursor cmp dh,mar_bot ; want to go below? jb atcci7 ; b = no, nothing to worry about mov ax,offset atscru ; Yes, indicate scroll up required. atcci6: mov dh,mar_bot ; Set to bottom margin pop cx ret atcci7: pop cx ; old pos was outside scrolling region jmp atccpc ; do full screen check and return ; This routine picks an attribute apart into its component "parts" - the ; base attribute for the screen and the "extras" - i.e., blink, intensity ; and underline. ; ; Call: ah/ a cursor attribute ; ; Return: ah/ base attribute for screen (07H normal, 70H reverse). ; al/ "extra" attributes ; ; Note that there is a complementary routine, addatt, for putting attributes ; back together... ; rewriten for the NEC RFG brkatt: mov al,ah ; two copies of attribues and al,att_low_mask ; the extras only here and ah,not att_low_mask ; the colors only here ret ; This routine builds a cursor attribute given the base attribute for the ; screen background and the "extra" attributes we want (blink, etc.). ; ; Call: ah/ base attribute for background (07H or 70H) ; al/ "extra" attributes (89H for all three) ; ; Return: ah/ base combined with "extras". ; ; modified for NEC as above RFG addatt: or ah,al ; simply put them together ret ; This routine is called when we want to reverse everything on the screen ; from normal to reverse video, or vice versa. It is called only when ; the decscnm attribute is changed. ; ; Call: no arguments. ; ; This routine may destroy ax-dx ; revscn: mov dh,byte ptr low_rgt+1 ; Compute last screen offset in ax inc dh ; One more row to catch mode line mov dl,crt_cols ; physical width dec dl ; and we count from 0 call scrloc mov cx,ax ; Save it in cx for a minute mov dx,0 ; Compute first screen offset in ax call scrloc sub cx,ax ; Compute number of locs to change.. add cx,2 sar cx,1 ; In 16-bit words please... push di ; Save some more acs push es push cx ; save word count for Topview [jrd] push ax ; save screen displacement call scrseg ; Get address of screen in ax, es:di pop ax ; recover displacement add di,ax ; displacement addr of start of change call scroff ; Turn screen off if color card. revsc1: mov ah,byte ptr es:[di] ; NEC form. Fetch a word flip_rev_video mov byte ptr es:[di],ah ; Stuff word back add di,2 ; Point di to next word of screen mem. loop revsc1 ; Loop for entire screen. pop cx ; recover word count for Topview [jrd] call scrsync ; synch with Topview call scron ; Turn screen back on if color card. pop es ; Restore segment register pop di ; And destination index ret ; Reset-everything routine. atreset:mov al,0 ; Make cursor disappear for a while. ;; call csrtype mov cursor,0 ; Cursor is at 0,0 mov ansflgs,0 ; reset these flags[jrd] cmp flags.vtflg,ttvt100 ; VT100? [jrd] jne atres7 ; ne = no. [jrd] mov ansflgs,decanm ; turn on ANSI mode flag. [jrd] atres7: mov mar_top,0 ; Reset scrolling region mov al,byte ptr low_rgt+1 mov mar_bot,al mov ah,vtemu.vtflgst mov vtemu.vtflgop,ah mov vtflags,ah mov insmod,0 ; reset insert mode. [jrd] mov h19l25,0 ; clear heath 25th line enable mov h19ctyp,1 ; Heath-19 cursor to underline [jrd] mov anspflg,0 ; clear printer flag [jrd] mov cx,4 ; Initialize the "LEDs". [jrd] mov al,led_off ; Turn them all off. mov di,offset ansleds+6 ; Point to the "LEDs". push es ; save es push ds pop es ; use datas segment for es:di below cld ; set forward direction rep stosb ; Do it. [jrd] pop es call disleds ; update mode line. [jrd] mov vttabs,offset deftabs ; [jrd] call cpytabs ; Initialize tab stops. call chrdef ; Set default character set. call vtbell ; Ding bell like VT100 test vtflags,vsnewline ; Want ANSI newline mode? jz atres1 ; No. or ansflgs,anslnm ; Yes - set it in the mode flags. atres1: test vtflags,vswrap ; How about autowrap? jz atres2 ; No. or ansflgs,decawm ; Yes - set it in the mode flags. atres2: mov ah,att_normal ; NEC. get present normal coloring flip_rev_video mov att_reverse,ah ; this is the reverse video code mov al,att_normal ; Assume normal video. test vtflags,vsscreen ; Want reverse video? jz atres3 ; No. or ansflgs,decscnm ; Yes - turn on the mode flag... xchg al,ah ; And reverse the video. atres3: mov cx,slen ; typically 24 but do max lines [jrd] mov di,0 atres8: mov linetype[di],0 ; clear the linetype array to single inc di ; width/height characters. loop atres8 mov curattr,al ; Give cursor and screen nice mov scbattr,al ; attributes.. mov oldbatr,al ; place to remember long term mov mlbattr,ah ; Give the other to the mode line. ; and mlbattr,not att_intensity ; no intensity for NEC - RFG mov video_state,0 ; say normal video. [jrd] mov ax,0 ; Clear entire screen. mov bx,low_rgt mov bl,crt_cols dec bl ; do physical screen call atsclr mov dx,cursor ; Set cursor to 0,0. call atscu5 call atsc ; Give saved cursor reasonable values. call atsctyp ; Set right cursor type. mov al,yflags call telmsy ; update msy about ansflgs state test yflags,modoff ; is mode line off? jnz atres9 ; nz = yes push dx ; save cursor position call trnmod ; toggle off then on again so we call trnmod ; use it with current coloring pop dx atres9: ret ; Routine to set cursor type (block, underline). atsctyp:cmp flags.vtflg,ttheath ; Heath-19? jne atsct0 ; ne = no mov al,h19ctyp ; get cursor kind and on/off bit test al,4 ; is cursor to be off? jz atsct1 ; z = no, al has kind mov al,0 ; turn off cursor jmp short atsct1 ; do it atsct0: mov al,1 ; Assume underline. test vtflags,vscursor ; Want block? jnz atsct1 ; nz = no, underline mov al,2 ; Yes. atsct1: call csrtype ; Do it. ret ; Routine to set default character set. chrdef: mov al,ascset ; Assume US ASCII. test vtflags,vsshift3 ; Want UK for default? jz chrde1 ; No. mov al,ukset ; Yes - use the UK set. chrde1: mov chr_sg0,al ; Reset character sets. mov chr_sg1,al mov ax,offset chr_sg0 ; Select character set zero. mov chr_set,ax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; end of part one ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start of part two ;;;;;;;;;;;;;;;;;;;;;;;;;; ; Routine to set special graphics character set (used in VT52 mode). chrsgs: mov al,sgrset ; Select "graphics" set. jmp chrde1 ; Do it and return. ; Control-character handling routines atbel: call vtbell ; Just ring bell and return. ret atbs: cmp dl,0 ; Backspace. too far? je atbs1 ; e = at column 0 already. dec dl ; Backup cursor atbs1: call atccpc ; Check range jmp atscu5 ; Set cursor and return atht: cmp flags.vtflg,ttheath ; Heath-19 mode? [jrd] je atht2 ; e = yes. handle specially. [jrd] cmp dl,byte ptr low_rgt ; At or beyond last column? jae atbs1 ; Yes, check range, set cursor and ret mov al,0 ; For ORing. mov bh,0 ; Make an index mov bl,dl ; For column. atht1: inc bx ; Tab always moves at least one space. or al,tabs[bx] ; Look for non-zero. jz atht1 ; ... mov dl,bl ; Get the new row index jmp atbs1 ; Check range, set cursor, and return atht2: mov dx,cursor ; Heath-19. get cursor position add dl,8 ; tabs are every 8 columns and dl,not 7 ; do modulo 8 cmp dl,byte ptr low_rgt ; check against right edge jae atht3 ; ae = out of range jmp atscu5 ; set cursor and return atht3: test ansflgs,decawm ; doing line wrapping? jnz atht4 ; nz = yes. wrap to next line mov dl,byte ptr low_rgt ; else go to right margin jmp atscu5 ; set cursor and return atht4: inc dh ; say want next line down xor dl,dl ; and left margin call atccic ; index check call ax ; do any needed scrolling atht4a: jmp atscu5 ; reset cursor atlf: cmp flags.vtflg,ttheath ; Heath-19 mode? [jrd] je atlf2 ; e = yes [jrd] test ansflgs,anslnm ; New-line mode? jz atlf2 ; No - just move to next line down mov dl,0 ; Yes - move to left margin also. atlf2: inc dh ; Index line down call atccic ; Check indexing call ax ; Call scrolling routine jmp atscu5 ; Set cursor atcr: mov dl,0 ; Go to left margin jmp atscu5 ; Set cursor and return. atff: cmp ttstate,offset atescf ; parsing escape sequence? jne atlf ; ne = no, do as line feed test denyflg,200h ; is auto Tek mode disabled? jnz atlf ; nz = yes, treat as line feed. call atsc ; save cursor and associated data JMP TEKESC ; Jump to Tektronix Emulator, al=FF atso: mov ax,offset chr_sg1 ; Select set G1 and return mov chr_set,ax ret atsi: mov ax,offset chr_sg0 ; Select set G0 and return mov chr_set,ax ret atcan: cmp ttstate,offset atnrm ; doing normal chars (vs esc seq)? jne atcan1 ; ne = no, assume esc seq jmp atign ; ignore ^X, ^Z in normal mode atcan1: mov ttstate,offset atnrm ; Reset state to "normal". mov al,sgrtab+2 ; replace CAN (^X) by checkerboard jmp atnrm ; Process char as a normal one atesc: mov nansarg,0 ; Clear ANSI arguments mov al,0 mov cx,lansarg mov di,offset ansargs push es push ds pop es ; use datas segment for es:di below cld ; set direction forward rep stosb pop es and ansflgs,not decmode ; Clear "DEC modes" flag. mov h19mod,0 ; clear Heath-19 mode flag mov ttstate,offset atescf ; Next state is escape follower ret atescf: cmp flags.vtflg,ttvt100 ; VT100? [jrd] jne atv52f ; ne = not VT100, try others. [jrd] atescf0:mov cx,lansesc ; Escape follower - get table length mov di,offset ansesc ; Point di at table push es push ds pop es ; use datas segment for es:di below cld ; set direction forward repne scasb ; Find it. pop es je atescf1 ; Found - now go do something with it jmp atnorm ; Not there - just ignore it. atescf1:mov di,lansesc - 1 ; Compute word index into jump table. sub di,cx shl di,1 jmp ansejt[di] ; Dispatch to the routine. atv52f: cmp flags.vtflg,ttheath ; Heath-19? [jrd] je ath19f ; e = yes. Use Heath esc seqs. [jrd] mov ttstate,offset atnrm ; Assume state "normal" on return. mov cx,lv52esc ; Get table length mov di,offset v52esc ; Point di at table. push es push ds pop es ; use datas segment for es:di below cld ; set direction forward repne scasb ; Find it. pop es je atv52f1 ; Found - do something with it. ret ; Not there - just ignore it. atv52f1:mov di,lv52esc - 1 ; Compute word index into jump table. sub di,cx shl di,1 jmp v52ejt[di] ; Dispatch to the routine. ath19f: mov ttstate,offset atnrm ; Assume state "normal" on return. test ansflgs,decanm ; ansi mode? jnz atescf0 ; nz = yes, use ansi table mov cx,lh19esc ; Get table length mov di,offset h19esc ; Point di at table. push es push ds pop es ; use datas segment for es:di below cld ; set direction forward repne scasb ; Find it. pop es je ath19f1 ; Found - do something with it. ret ; Not there - just ignore it. ath19f1:mov di,lh19esc - 1 ; Compute word index into jump table. sub di,cx shl di,1 jmp h19ejt[di] ; Dispatch to the routine. ; Escape follower routines. atcsi: mov ttstate,offset atpaa ; Next state is parse ansi args. ret atpaa: test al,80h ; high bit set? jz atpaa6 ; z = no and al,7fh ; strip high bit cmp al,' ' ; control code remainder? jae atpaa6 ; ae = no, use 7 bit result mov ttstate,offset atnrm ; reset state to normal text jmp atctrl ; execute 7 bit control code atpaa6: cmp al,'0' ; A digit? jb atpaa1 ; No - just ignore it. cmp al,'9' ; Maybe - A separator or final char? ja atpaa2 ; Perhaps - go check it out mov cl,al ; A digit - convert ASCII to binary sub cl,'0' mov bl,nansarg ; put index in bx [dlk] xor bh,bh mov al,ansargs[bx] ; Pick up what we've done so far [dlk] shl al,1 ; multiply by 10. 2 * al mov ah,al ; save shl al,1 ; 4 * al shl al,1 ; 8 * al add al,ah ; 10 * al mov ah,0 ; clear high field add ax,cx ; add in this digit [dlk] cmp ax,0feh ; max value is 0ffh [dlk] jbe atpaa0 ; be = ok [dlk] mov al,0ffh ; set to max value [dlk] atpaa0: mov ansargs[bx],al ; Put result back for next time [dlk] atpaa1: ret ; And return atpaa2: cmp al,'?' ; The deadly question mark? jne atpaa2a ; No - check further. or ansflgs,decmode ; Yes - say DEC modes are coming. ret ; And return. atpaa2a:cmp al,'>' ; Heath private mode? [jrd] jne atpaa3 ; ne = no cmp flags.vtflg,ttheath ; emulating a Heath-19? jne atpaa3 ; ne = no, ignore this sequence mov h19mod,1 ; say Heath mode sequence follows. ret atpaa3: cmp al,';' ; Argument separator? jne atpaa4 ; No - check for final char. mov al,nansarg ; Get argument index inc al ; Bump it. cmp al,lansarg ; Too many? jl atpa3a ; l = no, continue mov ttstate,offset atnrm ; Reset state to "normal". ret ; and pretend all is well [jrd] ; [jrd] jmp atcan ; Yes - abandon sequence on error. atpa3a: mov nansarg,al ; Save it. ret atpaa4: mov cx,lanstab mov di,offset anstab ; Look for it in the table push es push ds pop es ; use datas segment for es:di below cld ; set direction forward repne scasb pop es je atpaa5 ; Found it - go dispatch cmp al,40h ; in range for a legal terminator? jb atpaa4a ; b = not in range, ignore cmp al,7eh ; other end of the range ja atpaa4a ; a = out of range, ignore ; in range, absorb and become normal mov ttstate,offset atnrm ; Put state back to normal atpaa4a:ret ; Just return if it is unknown. atpaa5: mov ttstate,offset atnrm ; Put state back to normal mov di,lanstab - 1 ; Compute word index into jump table. sub di,cx shl di,1 jmp ansjmp[di] ; Off into the wild blue... atind: inc dh ; Index - move cursor down one. atind1: call atccic ; Check cursor position. call ax ; Scroll if necessary. mov ttstate,offset atnrm ; Reset state. jmp atscu5 ; Set cursor, etc. and return. atnel: mov dl,0 ; Next line - sort of like CRLF... inc dh ; ... all in one command jmp atind1 ; Check cursor, etc., and return. atri: dec dh ; Reverse index... jmp atind1 ; Check cursor, etc., and return. athts: call atccpc ; Make sure we have valid column number. mov dh,0 ; Zap row mov al,0FFH ; Indicates a tab stop mov di,dx ; Dumb specialized registers. mov tabs[di],al ; Store it. jmp atnorm ; Reset state and return. atsc: mov si,offset curattr ; Save cursor, attribute, char set etc. mov di,offset savecu ; Place to save the stuff. mov cx,lsavecu ; Length of save area push es ; save es push ds pop es ; set es to datas segment cld rep movsb ; Save it. pop es mov cl,ansflgs ; Save a copy of the flags. mov savflgs,cl ; ... jmp atnorm ; Reset state and return. atrc: mov si,offset savecu ; Restore cursor, attributes, etc.. mov di,offset curattr ; Where stuff goes mov cx,lsavecu ; Length of save area push es ; save es push ds pop es ; set es to datas segment cld rep movsb ; Put the stuff back. pop es mov al,savflgs ; Get saved flags xor al,ansflgs ; Exclusive-or with current flags test al,decscnm ; Did screen mode change? jz atrc1 ; No, just reset saved flags and leave mov ah,curattr ; Get cursor attribute that was saved flip_rev_video ; NEC. Flip it mov curattr,ah ; Store atrc1: mov al,ansflgs ; Reset flags in case called again and al, not(decckm+deckpam+decom) ; remove old bits [dlk] and savflgs,(decckm+deckpam+decom) ; remove all but new bits [dlk] or al,savflgs ; restore saved bits [dlk] mov ansflgs,al ; update these flags [dlk] mov savflgs,al mov dx,cursor ; Get cursor mov kbiflg,0 ; Don't bother them with beeps here call atscu5 ; Set cursor. jmp atnorm ; Reset state and return. atkpam: or ansflgs,deckpam ; Turn on the bit mov al,yflags call telmsy ; inform msy of new state jmp atnorm ; Reset state and return. atkpnm: and ansflgs,not deckpam ; Turn off the bit mov al,yflags call telmsy ; inform msy of new state jmp atnorm ; Reset state and return. atris: call atreset ; Reset everything jmp atnorm ; And state too, return, etc. atsg0: mov ttstate,offset atsg01 ; Setup to get last character ret atsg01: call atscs ; Get code for character set mov chr_sg0,al ; Store it. jmp atnorm ; Reset state etc. and return atsg1: mov ttstate,offset atsg11 ; Setup to get last character ret atsg11: call atscs ; Get code for character set mov chr_sg1,al ; Store it. jmp atnorm ; Reset state etc. and return atscs: cmp al,'A' ; UK ASCII set? jne atscs1 ; No. mov al,ukset ; Yes - give them that and return ret atscs1: cmp al,'B' ; US ASCII set? jne atscs3 ; No. atscs2: mov al,ascset ; Yes - give them that and return ret atscs3: cmp al,'0' ; Special graphics set? jne atscs4 ; ne = no mov al,sgrset ; Yes - say that's what it is ret atscs4: cmp al,'1' ; alt char ROM, std char set? [jrd] jne atscs5 ; ne = no mov al,ascset ; use US ASCII set ret atscs5: cmp al,'2' ; alt char ROM, special graphics?[jrd] jne atscs2 ; ne = no, use US ASCII mov al,sgrset ; set graphics ret ; ESC # Pn series. [jrd] atsdhl: mov ttstate,offset atsdbl ; set up to parse argument ret atsdbl: cmp al,'3' ; Double high lines. Top half? [jrd] je atsdh2 ; e = yes cmp al,'4' ; bottom half? je atsdh2 ; e = yes cmp al,'5' ; restore line to single width? je atsdh1 ; e = yes cmp al,'6' ; double width single height? je atsdh2 ; e = yes cmp al,'8' ; screen alignment? je atsdh8 ; e = yes jmp atnorm ; else ignore atsdh1: call linesgl ; set line to single width jmp atnorm atsdh2: call linedbl ; expand the line to double width jmp atnorm ; set state to normal and ret atsdh8: call atalign ; do screen alignment jmp atnorm atpriv: mov ttstate,offset atnorm ; ignore next char. ret ; and return to normal afterward. atalign proc near ; Fill screen with 'E' call atreset ; clear system or ansflgs,decawm ; set wrap mov cl,byte ptr low_rgt ; number of columns-1 inc cl mov al,byte ptr low_rgt+1 ; number of rows-1 inc al mul cl ; ax = number of chars on screen mov cx,ax atalig1:push cx mov al,'E' ; write screen full of E's call atnrm ; write the 'E' pop cx loop atalig1 ; cx times ret atalign endp ; This routine may be used to repeat a call to a selected action routine ; for all of the ANSI parameters given in a call. When the action routine ; is called, si will contain the index for the current ANSI parameter (i.e., ; the current ANSI parameter may be gotten using ansargs[si] for an effective ; address). The action routine may modify any ACs it wants, but cx, si, ; and di are preserved over the call to the action routine, so these may ; not be used for building return values for the original caller. Note that ; if there are no ANSI parameters, the effect is the same as if one ANSI ; parameter with a value of zero was given. ; ; Call: di/ offset of action routine in code seqment ; atreps: mov cl,nansarg ; Pick up number of parameters inc cl ; Zero parms is same as 1 zero parm. mov ch,0 mov si,0 ; Init parm index atrep1: push cx ; Save important acs push si push di call di ; Call indicated routine pop di ; Restore acs pop si pop cx inc si ; Advance to next parameter loop atrep1 ; Loop for all ret ; And return. ; Final char (ANSI) routines. atcup: mov dh,ansargs ; Get the two arguments mov dl,ansargs+1 cmp dh,0 ; Zero line number? jne atcup1 ; No - continue mov dh,1 ; Yes - default to one. atcup1: cmp dl,0 ; Ditto for row jne atcup2 mov dl,1 atcup2: dec dh ; Now normalize dec dl test ansflgs,decom ; Origin mode? jz atcup4 ; No - skip this stuff add dh,mar_top ; Yes - it was relative to top margin jno atcup4 ; If no overflow, continue mov dh,byte ptr low_rgt+1 ; Otherwise just set to screen bottom atcup4: cmp dh,byte ptr low_rgt+1 ; going to 25th line? [hlk] jbe atcup5 ; be = no [dlk] cmp flags.vtflg,ttheath ; emulating a Heath-19? [jrd] jne atcup6 ; ne = no [hlk] cmp h19l25,0 ; Heath 25th line enabled? je atcup5 ; e = no mov dh,byte ptr low_rgt+1 ; [hlk] inc dh ; go there jmp atscu4 ; set cursor position & mode line atcup6: test ansflgs,decom ; origin mode? [jrd] ;;;## jz atcup5 ; z = no, no 25th line stuff allowed mov dh,byte ptr low_rgt+1 ; bottom normal line inc dh ; the 25th line jmp atscu4 ; set cursor position and return atcup5: call atccpc ; Check position jmp atscu5 ; Set cursor position and return. atcuarg:mov al,ansargs ; Get a cursor move argument cmp al,0 ; Zero? jne atcua1 ; No - return mov al,1 ; Yes - default to one. atcua1: ret ; Return. ; Disallow movement to 25th line. atcuu: call atcuarg ; Get cursor move argument in al sub dh,al ; Compute new cursor position jnc atcuu1 ; nc = ok [dlk] xor dh,dh ; overflow, restrict range. [dlk] atcuu1: call atccic ; check indexing, ignore action in ax jmp atscu5 ; set the cursor at its new position atcud: call atcuarg ; Get the argument add dh,al ; Compute new cursor position jnc atcud1 ; nc = ok [dlk] mov dh,byte ptr low_rgt+1 ; default bottom [dlk] atcud1: call atccic ; check indexing, ignore action in ax jmp atscu5 ; set the cursor at its new position ; Allow horiz movement on 25th line. atcuf: call atcuarg ; Get the argument add dl,al ; Compute new cursor position jnc atcup4 ; If no carry, continue [dlk] mov dl,byte ptr low_rgt ; Else set to right margin jmp atcup4 ; Check/set cursor, return. atcub: call atcuarg ; Get the argument sub dl,al ; Compute new cursor position jnc atcup4 ; If no carry, continue [dlk] mov dl,0 ; Else set to left margin jmp atcup4 ; Check/set cursor, return. ated: mov di,offset ated0 ; Routine to process parm. call atreps ; Do all selected parms. ret ated0: cmp ansargs[si],0 ; Was arg zero? jne ated2 ; No - continue mov ax,dx ; Yes - erase from cursor to end of screen push dx ; save dx mov bl,dh ; get row number xor bh,bh cmp linetype [bx],0 ; single width line? je ated0a ; e = yes shl dl,1 ; physical column is twice logical ated0a: or dl,dl ; starting at left margin? je ated0b ; e = yes, this goes to single width inc bl ; else start on next line ated0b: cmp bl,byte ptr low_rgt+1 ; at the end of the screen? ja ated0c ; a = yes, stop singling-up mov byte ptr linetype [bx],0 ; set to single width inc bx jmp short ated0b ; loop, reset lines to end of screen ated0c: mov bx,low_rgt ; erase from cursor to end of screen mov bl,crt_cols dec bl ; do physical screen width call atsclr ; Clear it. pop dx ; restore dx ated1: ret ated2: cmp ansargs[si],1 ; Was arg one? jne ated3 ; No - continue mov ax,0 ; Yes - erase from start of screen... ; ...to cursor, inclusive xor bx,bx ; start at top row (0) ated2b: cmp bl,dh ; check rows from the top down jae ated2c ; ae = at or below current line mov byte ptr linetype [bx],0; set line to single width inc bx ; inc row jmp short ated2b ; look at next line ated2c: or dl,dl ; at left margin of current line? jne ated2d ; ne = no, leave line width intact mov byte ptr linetype [bx],0 ; convert to single width ated2d: mov bl,dh ; get row number xor bh,bh cmp linetype [bx],0 ; single width line? je ated2a ; e = yes shl dl,1 ; physical column is twice logical ated2a: mov bx,dx ; cursor position to bx call atsclr ; Clear it. ret ated3: cmp ansargs[si],2 ; Was arg two? jne ated1 ; No - ignore it. mov ax,0 ; Yes - erase entire screen. mov bx,low_rgt mov bl,crt_cols dec bl ; physical width call atsclr ; Clear it. push bx push cx ; set all 24 lines to single width mov cl,byte ptr low_rgt+1 ; number of last line xor ch,ch inc cx ; count from one xor bx,bx ated3a: mov linetype [bx],0 inc bx loop ated3a pop cx pop bx ret atel: mov di,offset atel0 ; Get routine to call call atreps ; Repeat for all parameters. ret atel0: cmp ansargs[si],0 ; Was arg zero? jne atel2 ; No - continue mov ax,dx ; Yes - erase from cursor... mov bh,dh ; ...to end of line, inclusive push bx mov bl,bh ; get row mov bh,0 cmp linetype [bx],0 ; single width line? je atel0a ; e = yes shl al,1 ; physical column is twice logical atel0a: pop bx mov bl,byte ptr low_rgt call atsclr ; Clear it. atel1: ret atel2: cmp ansargs[si],1 ; Was arg one? jne atel3 ; No - continue mov ah,dh ; Yes - erase from start of line... mov al,0 mov bx,dx ; ...to cursor, inclusive push bx mov bl,dh ; get row mov bh,0 cmp linetype [bx],0 ; single width line? pop bx ; pop does not affect flags je atel2a ; e = yes shl bl,1 ; physical column is twice logical atel2a: call atsclr ; Clear it. ret atel3: cmp ansargs[si],2 ; Was arg two? jne atel1 ; No - ignore it. mov ah,dh ; Yes - erase entire line. mov al,0 mov bh,dh mov bl,byte ptr low_rgt mov bl,crt_cols dec bl ; physical line call atsclr ; Clear it. ret atsgr: mov ah,curattr ; Get current cursor attribute call brkatt ; Break it apart. mov di,offset atsgr1 ; Routine to call. call atreps ; Repeat for all parms. call addatt ; Put the attributes back together mov curattr,ah ; Store. ret atsgr1: mov bl,ansargs[si] ; Fetch an argument cmp bl,0 ; Zero? jne atsgr2 ; No. mov al,0 ; Yes - clear the "extras" mov ah,scbattr ; And reset background. and ah,not att_blink ; NEC. clear blink/bold here mov video_state,0 ; say normal video now. [jrd] ret atsgr2: cmp bl,1 ; One? jne atsgr3 ; No. or al,att_intensity ; Yes - set bold ret atsgr3: cmp bl,4 ; Four? Underline. Mods by [jrd] jne atsgr4 ; No. or al,att_underline ; NEC. Yes, set underscore. atsgr3a:ret atsgr4: cmp bl,5 ; Five? jne atsgr5 ; No. or al,att_blink ; Yes - set blink ret atsgr5: cmp bl,7 ; Seven? jne atsgr6 ; No - just ignore it. cmp video_state,0 ; is video normal? [jrd] jne atsgr6 ; ne = no, reversed already, ignore xchg al,ah ; NEC flip_rev_video xchg ah,al mov video_state,1 ; say reversed now. ret ; Set for NEC colors RFG ; just take 30-37 and map it into high bits of attribute atsgr6: cmp bl,30 ; ANSI color series? [jrd] jb atsgrx ; b = no. cmp bl,37 ; foreground set (30-37)? ja atsgrx ; don't accept background RFG mov ah,curattr ; get current attributes and ah,att_low_mask ; clear color bits test bl,1 ; ANSI red? jz atsgr6a ; z = no or ah,nec_red atsgr6a:test bl,2 ; ANSI & IBM green? jz atsgr6b ; z = no or ah,nec_green atsgr6b:test bl,4 ; ANSI blue? jz atsgr6c ; z = no or ah,nec_blue atsgr6c:mov curattr,ah ; store the results. atsgrx: ret attbc: call atccpc ; Make sure cursor is kosher mov di,offset attbc0 ; Routine to call call atreps ; Do for all parms ret attbc0: cmp ansargs[si],0 ; Was argument zero? jne attbc2 ; No - check further mov dh,0 ; Zap row for indexing mov di,dx mov tabs[di],0 ; clear tab stop attbc1: ret attbc2: cmp ansargs[si],3 ; Was arg 3 (clear all tab stops)? jne attbc1 ; No - just ignore it. mov cx,swidth ; Get ready to zap swidth columns mov di,offset tabs ; Point to the tab stop table. mov al,0 ; zero indicates no tab stop. push es ; save es push ds pop es ; use datas segment for es:di below cld ; set direction forward rep stosb ; Blit full of zeros. pop es ret atstbm: mov al,ansargs ; Get the two line number args mov ah,ansargs+1 cmp al,0 ; Was first zero? jne atstb1 ; No - continue mov al,1 ; Yes - default is one atstb1: cmp ah,0 ; Was second zero? jne atstb2 ; No - continue mov ah,byte ptr low_rgt+1 ; Yes - default is last line on screen inc ah atstb2: dec al ; Normalize to our coord. system dec ah cmp ah,al ; Is size of region at least two lines? jbe atstb3 ; be = if not, indicate an error. cmp al,0 ; Check against screen limits. jl atstb3 cmp ah,byte ptr low_rgt+1 ja atstb3 mov mar_top,al ; Set the limits mov mar_bot,ah mov dx,0 ; Home cursor call atccpc ; Check cursor (get it inside window) jmp atscu5 ; Set cursor position and return. atstb3: ret ; ignore bad requests ;;; jmp atcan ; Indicate error and return. atda: cmp ansargs,0 ; Was argument zero? je decid ; Yes - send the i.d. string. ret ; No - only an echo... at52id: mov ttstate,offset atnrm ; ensure state is correct decid: mov cx,ldastr ; Length of the string mov si,offset dastr ; Point to the string cmp flags.vtflg,ttvt100 ; VT100? [jrd] je decid1 ; e = yes [jrd] mov cx,lv52str ; No - try VT52 i.d. [jrd] mov si,offset v52str cmp flags.vtflg,ttvt52 ; Heath-19 mode? [jrd] je decid1 ; e = yes. [jrd] mov cx,lh19str ; length of Heath-19 ident string mov si,offset h19str ; say Heath-19. [jrd] decid1: cld lodsb ; Get a byte push cx ; Save the important registers push si call prtbout ; Send it to port with no local echo pop si pop cx loop decid1 ; Loop for all characters ret atll: mov di,offset atleds ; Get pointer to routine to call call atreps ; Repeat for selective parameters. ret atleds: cmp ansargs[si],0 ; Zero argument? jne atled3 ; No - check further. mov cx,4 ; Reset the "LEDs". [jrd] mov al,led_off ; to all off. mov di,offset ansleds+6 ; Point to the "LEDs". push es ; save es push ds pop es ; make es:di point to datas seg cld ; move forward rep stosb ; [jrd] pop es atled1: call disleds ; Update "LEDs" display and return. atled2: ret atled3: mov al,ansargs[si] ; Get the argument cmp al,1 ; Must be .GE. 1 jb atled2 ; If not just ignore it. [dlk] cmp al,4 ; Must be .LE. 4 ja atled2 ; Ignore if not so. [dlk] dec al ; Zero base it. cbw ; Convert to index in ax. mov di,ax ; Dumb specialized registers. add al,'1' ; add ascii offset for digit mov ansleds[di+6],al ; Turn the "LED" on by storing digit jmp atled1 ; Update display and return. atreqt: cmp ansargs,0 ; Want report? je atreq1 ; Yes - give report cmp ansargs,1 ; Want report? je atreq1 ; Yes - give the report. ret ; Gee, must have been an echo... atreq1: mov al,escape ; Send an escape to start off... call prtbout mov al,'[' ; Then one of these... call prtbout mov al,'3' ; We only report on request... cmp ansargs,0 ; was argument a zero? jne atreq1a ; ne = no mov al,'2' ; yes atreq1a:call prtbout mov al,';' ; Separate call prtbout mov bl,parcode ; Get the parity code mov bh,0 mov al,partab[bx] ; Get VT100 parity code push ax ; save parity code call prtnout ; Send number to the port.. mov al,';' ; Separate call prtbout mov al,'2' ; Assume 7 data bits pop bx ; get parity code into bl cmp bl,1 ; is parity none? jne atreq2 ; ne = no, so 7 data bits test flags.remflg,d8bit ; 8 bit display? jz atreq2 ; z = no mov al,'1' ; must be eight. atreq2: call prtbout ; Send it to the port mov al,';' ; Separate call prtbout mov bl,baudidx ; Baud rate index mov bh,0 mov al,baudtab[bx] ; Get DEC baud rate code push ax call prtnout ; Send it to the port mov al,';' ; Separate call prtbout ; Send it to the port pop ax call prtnout ; Send it to the port mov al,';' ; Separate call prtbout mov al,'1' ; Clock rate multiplier is always 1 call prtbout mov al,';' ; Separate (gasp - for the last time) call prtbout mov al,'0' ; Flags are always zero (no STP) call prtbout mov al,'x' ; Finally, say what this all was. call prtbout ret atdsr: mov di,offset atdsr1 ; Routine to call call atreps ; Do for all parms. ret atdsr1: cmp ansargs[si],5 ; Want status? je rpstat ; Yes - report status cmp ansargs[si],6 ; Want cursor position? je rpcup ; Yes - do it. cmp ansargs[si],15 ; Printer status? [jrd] je rpstap ; e = yes, do so. ret ; No - must have been an echo rpstat: mov al,escape ; Tell them we think we are OK call prtbout mov al,'[' call prtbout mov al,'0' call prtbout mov al,'n' call prtbout ret rpstap: test ansflgs,decmode ; Printer status report from [jrd] jz rpstap3 ; ESC [ ? 15 n request mov al,escape call prtbout mov al,'[' call prtbout mov al,'?' call prtbout mov al,'1' call prtbout mov ah,ioctl ; get printer status, via DOS mov al,7 ; status for output push bx mov bx,4 ; std handle for system printer int dos pop bx jc rpstap1 ; c = call failed cmp al,0ffh ; code for Ready jne rpstap1 ; ne = not ready mov al,'0' ; ready, send final digit jmp rpstap2 rpstap1:mov al,'3' ; not ready, say printer disconnected rpstap2:call prtbout mov al,'n' ; final char of response call prtbout rpstap3:ret rpcup: mov al,escape ; Cursor position - send an escape call prtbout mov al,'[' ; And one of these call prtbout mov al,byte ptr cursor+1 ; Get row inc al ; They use coords that start at 1. test ansflgs,decom ; Origin mode set? jz rpcup1 ; No - continue sub al,mar_top ; Yes - subtract off top margin rpcup1: call prtnout ; Output the number. mov al,';' ; Separate call prtbout mov al,byte ptr cursor ; Now get the column number. inc al ; Their coords start at 1. call prtnout ; Send it off to the port. mov al,'R' ; Finally end it with this call prtbout ret ; ESC [ ? xxx h/l series atrm: mov modeset,0 ; Say we are resetting modes mov di,offset atrsm ; Reset/set modes. call atreps ; Repeat for all parms. test ansflgs,decanm ; Did this get reset? jnz atrm1 ; No - return. cmp flags.vtflg,ttheath ; were we a Heath-19? je atrm0 ; e = yes, don't change terminal types mov flags.vtflg,ttvt52 ; Yes. Say VT52 now. [jrd] atrm0: call chrdef ; Yes - set default char sets. call atsc ; Save cursor status. call disleds ; update terminal type atrm1: ret atsm: mov modeset,1 ; Say we are setting modes mov di,offset atrsm ; Reset/set modes. call atreps ; Repeat for all parms. ret atrsm: mov al,ansargs[si] ; Pick up the argument. test ansflgs,decmode ; Is this DEC private mode ([ ?)stuff? jnz atrsm1 ; nz = yes - go check it out. cmp h19mod,0 ; Heath-19 private mode ([ >)? je atrsma ; e = no jmp htrsm1 ; yes, do Heath specific things. atrsma: cmp al,20 ; No - ANSI new-line mode? jne atrsm0 ; but try insert mode. [jrd] and vtemu.vtflgop,not vsnewline ; assume resetting cmp modeset,0 ; resetting? je atrsmb ; e = yes or vtemu.vtflgop,vsnewline ; setting atrsmb: mov al,anslnm ; Yes - get the bit call atrsflg ; Set or reset it ret atrsm0: cmp al,4 ; toggle insert mode? [jrd] jne atrsmx ; ne = no [jrd] mov al,modeset ; set/reset insert mode [jrd] mov insmod,al ; store it. [jrd] atrsmx: ret atrsm1: cmp al,1 ; Cursor keys mode? jne atrsm2 ; No - check some more mov al,decckm ; Yes - get the bit. jmp atrsflg ; Set or reset it and return. atrsm2: cmp al,7 ; Auto-wrap? jne atrsm3 ; No - check some more and vtemu.vtflgop,not vswrap ; assume resetting line wrap cmp modeset,0 ; resetting? je atrsm2a ; e = yes or vtemu.vtflgop,vswrap ; set the bit atrsm2a:mov al,decawm ; Yes - get the bit jmp atrsflg ; Set or reset it and return. atrsm3: cmp al,6 ; Origin mode? jne atrsm4 ; No - check for video change jmp atrsom ; Yes - change decom and return. atrsm4: cmp al,5 ; Change the video? jne atrsm5 ; No - check for VT52 mode set/reset. jmp atrsscnm ; Yes - change it if we have to and ret. atrsm5: cmp al,2 ; Change VT52 compatibility mode? jne atrsm6 ; No - ignore unknown DEC private modes cmp flags.vtflg,ttheath ; Heath-19 mode? [jrd] je atrsm5a ; e = yes, handle specially. [jrd] mov al,ascset ; return to US ascii graphics sets mov chr_sg0,al ; Store it. mov chr_sg1,al ; Store it. mov al,decanm ; Yes - get the flag. jmp atrsflg ; Set or reset it and return. atrsm5a:mov modeset,0 ; Heath-19 ESC [ ? 2 h, reset ansi mov al,decanm ; the flag needing adjustment jmp atrsflg ; reset the flag and return atrsm6: cmp al,3 ; 132/80 column mode change? [jrd] jne atrsm7 ; ne = no mov al,modeset ; pass set/reset request to chgdsp[dlk] call chgdsp ; call Change Display proc in msy [dlk] call scrmod ; get current screen mode cmp modeset,1 ; want 132 cols? jne atrsm6n ; ne = no, so use 80 columns push ax mov al,crt_cols ; get current physical screen width dec al ; we count from column 0 here mov byte ptr low_rgt,al ; screen capability pop ax mov linelen,131 ; say using wide screen, if possible jmp short atrsm6e atrsm6n:mov linelen,79 ; say using 80 columns cmp byte ptr low_rgt,79 ; want 80 cols, is it wider? jbe atrsm6e ; be = no mov byte ptr low_rgt,79 ; narrow down to 80 columns atrsm6e: CALL ATRES2 ; do partial reset of emulator xor ax,ax ; clear screen from 0,0 mov bh,byte ptr low_rgt+1 ; to end of text lines (typ. line 24) mov bl,crt_cols ; physical width dec bl ; we count from 0 call atsclr ; do the clear push bx ; save regs. [jrd] push cx mov cl,byte ptr low_rgt+1 ; text lines (leave status line intact) mov mar_top,0 mov mar_bot,cl ; reset scrolling region xor ch,ch xor bx,bx atrsm6a:mov linetype [bx],0 ; reset linetype to single chars inc bx loop atrsm6a pop cx pop bx xor dx,dx ; new cursor position is 0,0 mov cursor,dx jmp atscu5 ; place it there and return atrsm7: cmp al,18 ; 18? 18 & 19 = printer support [jrd] jne atrsm8 ; ne = no cmp modeset,0 ; resetting? jne atrsm7a ; ne = no, setting and anspflg,not vtffp ; no form feed after printing ret atrsm7a:or anspflg,vtffp ; use form feed after printing ret atrsm8: cmp al,19 ; 19? [jrd] jne atrsm9 ; ne = no cmp modeset,0 ; resetting? jne atrsm8a ; ne = no, setting and anspflg,not vtextp ; reset print region to scrolling reg. ret atrsm8a:or anspflg,vtextp ; set print region to whole screen ret atrsm9: cmp al,38 ; 38? Enter Tek sub-mode. VT340 seq jne atrsm10 ; ne = no cmp modeset,1 ; setting mode (ESC [ ? 38 h)? jne atrsm10 ; ne = no, ignore sequence test denyflg,200h ; is auto Tek mode disabled? jnz atrsm10 ; nz = yes, just ignore command call atsc ; save cursor and associated data mov al,0 ; enter with this received character JMP TEKEMU ; Jump to Tektronix Emulator, al=null atrsm10:ret ; Heath-19 ESC [ > Ps h or l where Ps = 1, 4, 7, or 9. [jrd] htrsm1: cmp al,1 ; 25th line? jne htrsm4 ; ne = no mov al,modeset ; set/reset flag mov h19l25,al cmp al,0 ; resetting? Mods from Dave Tweten jne htrsmx ; ne = no, enabling. we are done mov ah,byte ptr low_rgt+1 ; point to status (25th) line inc ah ; which is here xor al,al ; from column 0 mov bh,ah ; to same line mov bl,crt_cols ; physical width dec bl ; we count from 0 jmp atsclr ; disabling status line clears it htrsm4: cmp al,4 ; block/line cursor? jne htrsm5 ; ne = no and h19ctyp,4 ; save on/off bit (4) cmp modeset,0 ; reset? je htrsm4a ; e = yes or h19ctyp,2 ; remember block kind here jmp atsctyp htrsm4a:or h19ctyp,1 ; remember underline kind here jmp atsctyp htrsm5: cmp al,5 ; on/off cursor? jne htrsm7 ; ne = no cmp modeset,0 ; on? je htrsm5a ; e = yes or h19ctyp,4 ; remember off state in this bit jmp atsctyp htrsm5a:and h19ctyp,not 4 ; set cursor on jmp atsctyp htrsm7: cmp al,7 ; alternate application keypad? jne htrsm9 ; ne = no mov al,deckpam ; get keypad application mode bit jmp atrsflg ; set or reset appl keypad mode htrsm9: cmp al,9 ; auto newline mode? (add cr to lf) jne htrsmx ; ne = no mov al,anslnm ; get the bit jmp atrsflg ; set or reset newline mode htrsmx: ret ; ignore the code atrsflg:cmp modeset,0 ; Want to reset je atrsf1 ; Yes - reset it. or ansflgs,al ; No, set. OR in the flag test al,decanm ; Changing terminal type? [jrd] jz atrsfx ; z = no [jrd] cmp flags.vtflg,ttheath ; in Heath-19 mode? [jrd] je atrsfx ; e = yes, don't flip terminal kinds. mov flags.vtflg,ttvt100 ; say VT100 now. [jrd] jmp short atrsfx atrsf1: not al ; Complement and ansflgs,al ; Clear the bit not al ; recover the bit. [jrd] test al,decanm ; Changing terminal type? [jrd] jz atrsfx ; z = no cmp flags.vtflg,ttheath ; in Heath-19 mode? [jrd] je atrsfx ; e = yes, don't flip terminal kinds. mov flags.vtflg,ttvt52 ; say VT52 now. [jrd] atrsfx: push ax mov al,yflags call telmsy ; tell msy file about new state pop ax ret atrsom: cmp modeset,0 ; Clearing DEC origin mode? jne atrsom1 ; ne = no, setting and ansflgs,not (decom) ; clear the bit mov dx,0 ; go to the home position jmp atscu5 ; set cursor and return atrsom1:or ansflgs,decom ; Set Origin mode mov dx,cursor ; Get the cursor mov dl,0 ; go to right margin mov dh,mar_top ; go to home of scrolling region jmp atscu5 ; Set the cursor and return atrsscnm: cmp modeset,0 ; Setting or resetting? je atrss1 ; Do reset. test ansflgs,decscnm ; Setting. Is it set already? jnz atrss3 ; Yes. Don't do it again. or ansflgs,decscnm ; No. Set it. or vtemu.vtflgop,vsscreen ; tell Status display or vtflags,vsscreen ; and our local flags mov al,att_reverse ; Want reverse video. jmp short atrss2 ; Do it. atrss1: test ansflgs,decscnm ; Resetting. Is it reset already? jz atrss3 ; Yes. Don't do it again. and ansflgs,not decscnm ; No. Clear it. and vtemu.vtflgop,not vsscreen ; tell Status display and vtflags,not vsscreen ; and our local flags mov al,att_normal ; Want normal video. ; Fall through to atrss2... ; Note: This is also called from the stblmds initialization routine. atrss2: push ax mov scbattr,al ; Set screen background attribute mov oldbatr,al ; update long term memory too. mov ah,al ; place where brkatt works flip_rev_video ; NEC form mov mlbattr,ah mov ah,curattr flip_rev_video mov curattr,ah pop ax call revscn ; Reverse everything on the screen. atrss3: ret atctst: mov al,0 ; Init test weight mov di,offset atcts2 ; Routine to call call atreps ; Repeat for all parms test al,80H ; Want to reset? jz atcts1 ; No - return. call atreset ; Yes - reset everything. atcts1: ret atcts2: mov ah,ansargs[si] ; Pick up an argument. cmp ah,0 ; Zero? jne atcts3 ; No - ignore others. or al,80H ; Yes - say we want reset atcts3: ret ; VT52 compatibility mode routines. ; Return to ANSI mode. v52ans: or ansflgs,decanm ; Turn ANSI flag back on. mov flags.vtflg,ttvt100 ; Say VT100 now. [jrd] call chrdef ; Set default char sets. call atsc ; Save cursor status. call disleds ; Put "LEDs" back. jmp atnorm ; Reset state to normal and return. ; Reset VT52 (does NOT cause return to VT100 mode). [jrd] v52ris: call atreset ; Reset everything. call disleds ; Put "LEDs" back. ret ; Enter VT52 "graphics" mode. v52egm: call chrsgs ; Set "graphics" char set. jmp atnorm ; Reset state to normal and return. ; Exit VT52 "graphics" mode. v52xgm: call chrdef ; Set default character set. jmp atnorm ; Reset state to normal and return. ; VT52 cursor positioning. v52pos: mov ttstate,offset v52pc1 ; Next state. ret v52pc1: sub al,' '-1 ; Minus offset. mov ansargs,al ; Stash it here. mov ttstate,offset v52pc2 ; Next state. ret v52pc2: sub al,' '-1 ; Minus offset. mov ansargs+1,al ; Stash here. call atnorm ; Reset state to "normal". jmp atcup ; Position and return. ; VT52 print controls v52apb: mov ansargs,5 ; Enter auto print mode or ansflgs,decmode ; simulate ESC [ ? 5 i jmp ansprt ; process command v52ape: mov ansargs,4 ; Exit auto print mode or ansflgs,decmode ; simulate ESC [ ? 4 i jmp ansprt ; process command v52pcb: mov ansargs,5 ; Enter printer controller on and ansflgs,not decmode ; simulate ESC [ 5 i jmp ansprt ; process command v52pce: mov ansargs,4 ; Exit printer controller on and ansflgs,not decmode ; simulate ESC [ 4 i jmp ansprt ; process command v52ps: mov ansargs,0 ; print screen and ansflgs,not decmode ; simulate ESC [ 0 i jmp ansprt ; process command v52pl: mov ansargs,1 ; print line or ansflgs,decmode ; simulate ESC [ ? 1 i jmp ansprt ; process command ; Heath-19 special functions [jrd] h19ans: or ansflgs,decanm ; Turn on ANSI flag. ESC < call chrdef ; Set default char sets. jmp atnorm ; Reset state to normal and return. ; do several "ESC [" ANSI commands ; but don't change terminal types h19ansa:jmp atcsi ; parse ansi arguments. ; clear screen and go home h19clrs:mov dx,0 ; go to upper left corner call atscu5 ; do it mov ax,0 ; clear screen from (0,0) mov bh,byte ptr low_rgt+1 ; to lower right corner mov bl,crt_cols ; physical width dec bl ; we count from 0 jmp atsclr ; cursor down (scrolls) h19cud: mov dx,cursor ; get cursor position inc dh ; say next row down call atccic ; check position cursor (scrolls) mov cursor,dx call ax ; do scrolling jmp atscu5 ; cursor forward (right). ESC C h19cuf: mov dx,cursor ; get cursor position inc dl ; move cursor right cmp dl,byte ptr low_rgt ; beyond right margin jb h19cuf1 ; b = no. do it test ansflgs,decawm ; wrap mode on? jz h19cuf2 ; z = no. just ignore movement xor dl,dl ; set to left margin inc dh ; and down a row call atccic ; adjust position call ax ; call scrolling routine h19cuf1:jmp atscu5 ; do positioning and return h19cuf2:ret ; just return ; set line wrap on h19wrap:or ansflgs,decawm ; turn on the flag jmp atnorm ; turn off line wrap h19nowrp:and ansflgs,not decawm ; turn off the flag jmp atnorm h19erb: mov bx,cursor ; erase home to cursor, incl. xor ax,ax ; home jmp atsclr ; clear the area, cursor stays put??? h19erl: mov bx,cursor ; erase whole line mov ax,bx ; get row xor al,al ; column 0 mov bl,crt_cols ; physical width dec bl ; we count from 0 jmp atsclr ; erase whole line, cursor stays put h19ero: mov bx,cursor ; erase start of line to cursor mov ax,bx xor al,al ; start in column 0 jmp atsclr ; clear that part of line h19herv:cmp video_state,0 ; is video normal? ESC p jne h19hrv1 ; ne = no, reversed already, ignore mov ah,curattr ; current cursor attributes flip_rev_video mov curattr,ah ; and store it mov video_state,1 ; say we are reversed h19hrv1:ret h19hxrv:cmp video_state,0 ; is video normal? ESC q je h19hxr1 ; e = yes, so just ignore mov ah,curattr ; current cursor attributes flip_rev_video ; NEC form mov curattr,ah ; and store it mov video_state,0 ; say we are normal h19hxr1:ret h19mbr: mov ttstate,offset hmbr ; Modify baud rate ESC r char ret ; setup to parse next char hmbr: jmp atnorm ; discard char (in al) htsc: cmp flags.vtflg,ttheath ; Heath-19? ESC [ s jne htscx ; ne = no, ignore call atsc ; store cursor position and attr. htscx: jmp atnorm ; reset state & return htrc: cmp flags.vtflg,ttheath ; Heath-19? ESC [ u jne htrcx ; ne = no, ignore call atrc ; restore cursor pos and attr. htrcx: jmp atnorm ; reset state & return ; Heath-19 set mode "ESC x " h19smod:mov ttstate,offset hsmod ; setup to parse rest of seq ret hsmod: mov modeset,1 ; say set mode mov ttstate,offset atnrm sub al,'0' ; remove ascii bias jmp htrsm1 ; perform mode set h19cmod:mov ttstate,offset hcmod ; setup to parse rest of seq ret hcmod: mov modeset,0 ; say reset mode mov ttstate,offset atnrm sub al,'0' ; remove ascii bias jmp htrsm1 ; perform mode reset htrest: cmp flags.vtflg,ttheath ; Heath-19? ESC [ z jne htrestx ; ne = no, ignore call atreset ; do a hard reset htrestx:jmp atnorm ; reset state and return hrcup: mov al,escape ; send "ESC Y row col" cursor report call prtbout ; send with no local echo mov al,'Y' call prtbout mov al,byte ptr cursor+1 ; get row add al,' ' ; add ascii bias call prtbout ; send it mov al,byte ptr cursor ; get column add al,' ' ; add ascii bias call prtbout ; and send it too jmp atnorm ; return to terminal mode ; Heath-19 and VT102 additions [jrd] inslin: cmp ansargs,0 ; insert line(s). Any args? [jrd] jne insli1 ; ne = yes. If no arg use 1 mov ansargs,1 ; insert one line. insli1: mov dx,cursor ; current position cmp dh,mar_bot ; below bottom margin? jae insli3 ; ae = at or below bottom margin push word ptr mar_top mov mar_top,dh ; call present position the top push cx ; save a reg mov cl,ansargs ; get repeat count xor ch,ch ; clear high byte insli2: call atscrd ; scroll down loop insli2 ; repeat until done (cx times) pop cx ; restore reg pop word ptr mar_top ; restore margins xor dl,dl ; go to left margin jmp atscu5 ; reposition cursor and return insli3: ret dellin: cmp ansargs,0 ; delete line(s). Any args? [jrd] jne delli1 ; no arg; use 1 mov ansargs,1 ; insert one line. delli1: mov dx,cursor ; where we are presently cmp dh,mar_bot ; at or below bottom margin? jae delli3 ; ae = yes. push word ptr mar_top ; save current scrolling margins mov mar_top,dh ; temp top margin is here push cx ; save a reg mov cl,ansargs ; get repeat count xor ch,ch ; clear high byte delli2: call atscru ; scroll up loop delli2 ; repeat until done (cx times) pop cx ; restore reg pop word ptr mar_top ; restore scrolling margins. jmp atscu5 ; restore cursor and return delli3: ret ; Delete character(s) atdelc: cmp ansargs,0 ; zero becomes one operation jne atdelc1 mov ansargs,1 ; delete one char. Heath ESC N atdelc1:mov cl,byte ptr low_rgt ; number of columns on screen. mov dx,cursor ; get present cursor position push bx mov bl,dh ; get row mov bh,0 cmp linetype [bx],0 ; single width line? je atdelc5 ; e = yes shl dl,1 ; double the column number mov bl,ansargs shl bl,1 ; double # chars to delete mov ansargs,bl atdelc5:pop bx sub cl,dl ; end of screen - current column # xor ch,ch ; cx = number of chars to move cmp cx,0 ; zero means just this char ja atdelc4 inc cx ; say one, this one atdelc4:push es push cx ; save word count for Topview cld call scrloc ; compute current cursor location mov di,ax ; temporary storage places mov si,ax mov al,ansargs ; get delete count xor ah,ah ; clear high byte of delete count cmp al,cl ; clear more than rest of line? jb atdelc2 ; b = no. some chars left at end mov al,cl ; say delete all to right, inclusive atdelc2:cmp al,0 ; zero? jne atdelc3 inc al ; none or 0 impiles one. atdelc3:shl ax,1 ; double: char and its attribute byte push di ; destination offset add ax,si ; src offset = dest + # deleted words push ax ; save it call scroff call scrseg ; pick up screen segment mov si,di ; align memory addresses pop ax ; recover source offset add si,ax ; add to starting memory address pop ax ; recover destination offset add di,ax ; add to destination memory address push ds ; save ds around the move push es ; move es into ds to pop ds ; make ds point to screen memory too rep movsw pop ds ; recover normal ds pop cx ; count for Topview call scrsync ; synch Topview pop es call scron mov ax,cursor ; get current row mov bx,cursor mov bl,byte ptr low_rgt ; last col on screen mov al,bl sub al,ansargs ; minus number of locations cleared inc al call atsclr ; clear end of line atdelcx:mov dx,cursor jmp atscu5 ; reposition cursor inschr: mov dx,cursor ; open one char space in current line push bx mov bl,dh ; get row mov bh,0 cmp linetype [bx],0 ; single width line? je insch2 ; e = yes shl dl,1 ; double the column number insch2: pop bx mov ch,0 mov cl,byte ptr low_rgt ; number of columns on screen push dx mov dh,0 sub cx,dx ; compute distance to end pop dx or cx,cx jle insch1 ; le = nothing to move... [dlk] mov dl,byte ptr low_rgt dec dl ; last col to move push ax ; save regs push es ; ditto push cx ; save count for Topview call scrloc ; compute position of end of line-1 push ax ; save offset std ; remember to move backward call scroff ; turn off color screen call scrseg ; get memory address in es:di pop ax ; recover offset add di,ax ; source memory address mov si,di ; align addresses. destination add di,2 ; is one char over push di push ds ; save ds around move push es ; put es into ds pop ds ; ds points to screen memory too rep movsw pop ds ; recover normal ds cld ; reset direction to be forward pop di pop cx ; count for Topview call scrsync ; synch Topview pop es ; restore regs pop ax ; ditto call scron ; turn on screen again cld ; reset direction insch1: mov dx,cursor jmp atscu5 ; position cursor noins: mov insmod,0 ; turn off insert mode jmp atnorm ; and return entins: mov insmod,0ffh ; enter insert mode... jmp atnorm ; and return ansich proc near ; ANSI insert characters ESC [ @ cmp ansargs,0 ; any arguments? jne ansic1 ; ne = no, ignore mov ansargs,1 ; use one ansic1: push dx ; save cursor mov insmod,1 ; enter insert mode push cx mov cl,ansargs ; get count of inserts mov ch,0 push ax ; save char ansic2: push cx ; save counter mov al,' ' ; character to write call atnrm ; do display pop cx ; recover counter loop ansic2 ; do cx times pop ax ; restore char pop cx mov insmod,0 ; turn off insert mode pop dx ; get original cursor jmp atscu5 ; set cursor ansich endp ; routines supporting scrolling and double width/height chars [jrd] atscru proc near ; scroll screen up one line push ax ; assumes dx holds cursor position push bx ; returns with dx = old row, new col push cx xor ch,ch mov cl,mar_bot ; bottom line to move xor bh,bh mov bl,mar_top ; top line to move sub cx,bx ; cx = number of lines to move jcxz atscru2 ; cx = 0. nothing to do atscru1:mov al,linetype[bx+1] mov linetype[bx],al ; move line types up one line inc bx loop atscru1 mov linetype[bx],0 ; clear new line's type ; reindex column of cursor cmp linetype[bx-1],0 ; was old bottom line double wide? je atscru2 ; e = no shr dl,1 ; reindex to single wide columns atscru2:pop cx pop bx pop ax test anspflg,vtcntp ; controller print active? jz atscru3 ; z = no, ok to change screen ret ; else keep screen intact atscru3:jmp vtscru ; call & ret the msy scroll routine atscru endp atscrd proc near ; scroll screen down one line push ax ; assumes dx holds cursor position push bx ; returns with dx = old row, new col push cx xor ch,ch mov cl,mar_top ; top line to move xor bh,bh mov bl,mar_bot ; bottom line to move sub cx,bx neg cx ; cx = number of lines to move jcxz atscrd2 ; cx = 0. nothing to do atscrd1:mov al,linetype[bx-1] mov linetype[bx],al ; move line types down one line dec bx loop atscrd1 mov linetype[bx],0 ; clear new line's type ; reindex column of cursor cmp linetype[bx+1],0 ; was old top line double wide? je atscrd2 ; e = no shr dl,1 ; reindex to single wide columns atscrd2:pop cx pop bx pop ax test anspflg,vtcntp ; controller print active? jz atscrd3 ; z = no, ok to change screen ret ; else keep screen intact atscrd3:jmp vtscrd ; call & ret the msy scroll routine atscrd endp linesgl proc near ; convert line to single width char push ax push bx push cx push dx mov bx,cursor mov bl,bh xor bh,bh ; bx now holds row cmp linetype [bx],0 ; is line already single width? je linsglx ; e = yes mov linetype [bx],0 ; say will be single now. call scroff ; turn off video mov dx,cursor mov dl,0 ; start in column 0 mov cx,40 ; number of columns to do linsgl1:push cx ; save loop counter shl dl,1 ; double column number mov ah,2 ; set cursor xor bh,bh ; page 0 int screen mov ah,8 ; read char and attribute int screen push ax ; save char and attribute shr dl,1 ; restore column mov ah,2 ; set cursor int screen pop ax ; recover char and attribute mov bl,ah ; set attribute mov cx,1 ; one char mov ah,9 ; write char and attribute int screen inc dl ; next column pop cx loop linsgl1 mov cx,40 mov dl,40 mov ah,2 ; set cursor int screen mov bl,scbattr ; screen background mov al,' ' mov ah,9 ; write char int screen ; write 40 spaces call scron ; turn on the video linsglx:pop dx pop cx pop bx pop ax jmp atscur ; update cursor and return linesgl endp linedbl proc near ; convert line to double width char push ax ; must reset physical cursor push bx ; to same char as before expansion push cx ; but does not modify variable cursor push dx mov bx,cursor mov bl,bh xor bh,bh ; bx now holds row cmp linetype [bx],0 ; is line single width? jne lindblx ; ne = no. nothing to do mov linetype [bx],1 ; say will be double width now. mov dx,cursor mov dl,39 ; start with col 39 mov cx,40 call scroff ; turn off the video lindbl1:push cx ; save loop counter mov ah,2 ; set cursor mov bh,0 ; page 0 int screen mov ah,8 ; read char and attribute int screen push ax ; save char and attribute shl dl,1 ; double the column number mov ah,2 ; set cursor int screen pop ax ; recover char and attribute mov bl,ah ; set attribute mov cx,1 ; one char mov ah,9 ; write char and attribute int screen inc dl ; move to second column of double. mov ah,2 ; set cursor int screen mov al,' ' ; space as filler mov ah,9 ; write that char int screen dec dl shr dl,1 dec dl pop cx loop lindbl1 call scron ; turn on the video lindblx:pop dx pop cx pop bx pop ax jmp atscur ; update the cursor and return linedbl endp anstty endp ansprt proc near ; printer support routines. [jrd] cmp ansargs,0 ; 0 (print all/part of screen)? jne ansprt1 ; ne = no call pntchk ; check printer jc ansprtx ; c = printer not ready call pntext ; do whole screen or scrolling extent jmp atscu5 ; reposition cursor and return ansprt1:cmp ansargs,1 ; 1 (print current line)? jne ansprt4 ; ne = no call pntchk ; check for printer ready jc ansprtx ; c = printer not ready call pntlin ; print current line anspr1a:jmp atscu5 ; reposition cursor and return ansprt4:cmp ansargs,4 ; auto print disable? jne ansprt5 ; ne = no test ansflgs,decmode ; was it ESC [ ? 4 i jz anspr4a ; z = no, so it was ESC [ 4 i test anspflg,vtautop ; check state of print flag jz anspr4a ; z = off already call trnprs ; toggle mode line PRN indicator and anspflg,not vtautop ; auto-print disable anspr4a:jmp ansprtx ansprt5:cmp ansargs,5 ; auto print enable? jne ansprtx ; ne = no call pntchk ; check printer, ignore carry ret jc ansprtx ; c = printer not ready test ansflgs,decmode ; was it ESC [ ? 5 i jz anspr5a ; z = no test anspflg,vtautop ; is print already enabled? jnz ansprtx ; nz = yes, leave trnprs intact call trnprs ; toggle on mode line PRN indicator or anspflg,vtautop ; auto-print enabled jmp short ansprtx anspr5a:or anspflg,vtcntp ; controller print enabled ansprtx:jmp atnorm ansprt endp ; State machine active while Media Copy On (Print Controller ON). Copies all ; chars to the printer until (and excluding) Media Copy Off (ESC [ 4 i) has ; been received or the emulator reset. New char is in al. 6 March 1987 [jrd] ansmc proc near mov ah,al ; copy active character and ah,7fh ; strip high bit cmp ah,byte ptr mcoff ; start of MC Off sequence? jne ansmc1 ; ne = no call ansmc4 ; playback previously matched chars mov mccnt,1 ; count matched chars (one now) mov mcoffs,al ; save full character, with high bit jmp short ansmcx ; and exit ansmc1: push bx ; check for char in MC Off sequence mov bx,mccnt ; number of chars matched in MC Off mov mcoffs[bx],al ; save this char, with high bit cmp al,byte ptr mcoff[bx] ; match expected char in sequence? pop bx jne ansmc3 ; ne = no, play back partial match inc mccnt ; count new match cmp mccnt,mcofflen ; matched all char in sequence? jne ansmcx ; ne = not yet, wait for more and anspflg,not vtcntp ; yes, disable print controller mov mccnt,0 ; clear counter jmp short ansmcx ; all done ansmc3: call ansmc4 ; playback previously matched chars call pntchr ; print current char, ignore errors mov mccnt,0 ; reset to no match and exit ansmcx: ret ; common exit ; local worker procedure ansmc4: push ax ; save break char (in al) push cx ; playback partial sequence to printer mov cx,mccnt ; number of chars matched before break jcxz ansmc4b ; z = none push si mov si,offset mcoffs ; string to be played back cld ansmc4a:lodsb ; get a char into al call pntchr ; print it, ignore errors loop ansmc4a ; do all that came in previously pop si ansmc4b:pop cx pop ax ; recover break char ret ansmc endp ; Check for PRN (DOS's printer) being ready. If ready, return with C clear. ; Otherwise, write Not Ready msg on mode line and return with C bit set. ; N.B. DOS Critical Error will occur here if PRN is not ready. [jrd] pntchk proc near push dx push cx push ax mov cx,10 ; ten retries before declaring error pntchk0:mov ah,ioctl ; get printer status, via DOS mov al,7 ; status for output push bx mov bx,4 ; std handle for system printer int dos pop bx jc pntchk1 ; c = call failed cmp al,0ffh ; code for Ready je pntchk3 ; e = yes, assume printer is ready. pntchk1:push cx ; save counter, just in case mov ax,100 ; wait 100 millisec call pcwait pop cx loop pntchk0 ; and try a few more times test yflags,modoff ; is mode line off? jnz pntchk2 ; nz = off, skip msg push bx push si mov si,offset pntmsg ; say printer not ready mov cx,pntmsgl ; length call modwrt ; write alternate mode line, in msy pop si pop bx pntchk2:pop ax pop cx pop dx stc ; say printer not ready ret pntchk3:pop ax pop cx pop dx clc ; say printer is ready ret pntchk endp ; Print on PRN the char in register al. On success return with C bit clear. ; On failure call procedure pntchk and return its C bit (typically C set). pntchr proc near push dx push ax mov ah,lstout ; uses file handle 4 mov dl,al int dos pop ax pop dx jnc pntchr2 ; nc = success call pntchk ; c = error (printer not ready) pntchr2:ret pntchr endp pntlin proc near ; print whole line given by dx push ax push bx push cx push dx xor dl,dl ; start in column 0 xor ch,ch mov cl,byte ptr low_rgt ; number of columns mov dl,cl ; Bios column counter inc cl ; actual line length, count it down pntlin1:mov ah,2 ; set cursor xor bh,bh ; page 0 int screen mov ah,8 ; read char (al) and attribute (ah) int screen cmp al,' ' ; is this a space? jne pntlin2 ; no, we have the end of the line dec dl ; else move left one column loop pntlin1 ; and keep looking for non-space pntlin2:jcxz pntlin4 ; z = empty line xor dl,dl ; start in column 0, do cl chars pntlin3:mov ah,2 ; set cursor xor bh,bh ; page 0 int screen mov ah,8 ; read char and attribute int screen inc dl ; inc to next column call pntchr ; print the char (in al) jc pntlin5 ; c = printer error loop pntlin3 ; do cx columns pntlin4:mov al,cr ; add trailing cr/lf for printer call pntchr jc pntlin5 mov al,lf call pntchr pntlin5:pop dx pop cx pop bx pop ax ret ; C bit controlled by pntchr pntlin endp pntext proc near ; print an extent of lines, depending push ax ; on flag bit vtextp. push bx push dx xor dx,dx ; assume starting at top left mov bx,low_rgt ; and extending to lower right test anspflg,vtextp ; full screen wanted? jnz pntext1 ; nz = yes, else scrolling region mov dh,mar_top ; top of scrolling region mov bh,mar_bot ; bottom of scrolling region pntext1:call pntlin ; print a line jc pntext2 ; c = printer error inc dh cmp dh,bh ; done all requested lines? jbe pntext1 ; be = not yet, do another test anspflg,vtffp ; form feed needed at end? jz pntext2 ; z = no. mov al,ff call pntchr ; print the form feed char pntext2:pop dx pop bx pop ax ret pntext endp code ends if1 %out [End of pass 1] else %out [End of assembly] endif end