NAME msz55x ; File MSZ55X.ASM ; System dependent file for Sanyo 55x series. ; Done by Robert W. Babcock and Joe H. White. ; For version which replaces the BIOS keycode translation table, ; use -dMODIFIED flag to MASM. 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 20 April 1988, add color trans. table for monochrome systems [rwb] ; 15 Sept 1987 version which runs with or without optional video board [rwb] ; Use bios calls for video output. Also change test for monochrome [jhw] ; monitor from crt_mode = 7 to 2. Set swidth and slen back to 80 and 25 [jhw] ; Make vtsound public so it can be called from msx55x. [rwb] ; ; 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, vclick, vsinit public vtsound ; [rwb] public mar_top, mar_bot, anspflg ; data for msyibm 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] ; --------------------------------------------------------------------------- screen equ 10h ; Bios screen call swidth equ 132 ; assumed max screen width [dlk] slen equ 43 ; assumed max screen length [jrd] att_low_mask equ 06H ; Various attribute-related equates ;;;att_reverse equ 70H ; these two are now storable items ;;;att_normal equ 07H ; to allow external settings. [jrd] att_underline equ 01H att_intensity equ 08H att_blink equ 80H ; 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 usevb:byte 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) trtbl db 0h,1h,2h,3h,1h,2h,3h,7h ; color translation table db 7h,9h,0ah,0bh,9h,0ah,0bh,0fh db 10h,14h,15h,16h,14h,15h,16h,18h db 18h,19h,1ah,1bh,1ch,1dh,1eh,1fh db 20h,24h,25h,26h,24h,25h,26h,28h db 28h,29h,2ah,2bh,2ch,2dh,2eh,2fh db 30h,34h,35h,36h,34h,35h,36h,38h db 38h,39h,3ah,3bh,3ch,3dh,3eh,3fh db 41h,41h,42h,43h,41h,42h,43h,47h db 47h,49h,4ah,4bh,49h,4ah,4bh,4fh db 51h,51h,52h,53h,51h,52h,53h,57h db 57h,59h,5ah,5bh,59h,5ah,5bh,5fh db 61h,61h,62h,63h,61h,62h,63h,67h db 67h,69h,6ah,6bh,69h,6ah,6bh,6fh db 70h,74h,75h,76h,74h,75h,76h,78h db 78h,79h,7ah,7bh,7ch,7dh,7eh,7fh 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 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 call brkatt ; separate colors from blink/bold rol ah,1 ; reverse foreground & background rol ah,1 ; RGB bits. rol ah,1 rol ah,1 call addatt ; reinsert bold/blink bits 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: mov ah,oldbatr ; get old screen background scbattr mov scbattr,ah ; and update working copy mov ah,att_normal ; get new attributes (Set Term Color) push bx mov bh,ah ; get new intensity bit of att_normal and bh,att_intensity and curattr,not att_intensity ; char attrs. clear intensity bit or curattr,bh ; set new intensity and mlbattr,not att_intensity ; mode line attrs. clear intensity and scbattr,not att_intensity ; screen background attribute or scbattr,bh ; set its intensity also mov bl,scbattr mov oldbatr,bl ; and save it here as well pop bx call brkatt ; separate color and blink/bold rol ah,1 ; reverse fore/back color fields rol ah,1 rol ah,1 rol ah,1 call addatt ; put back blink/bold push bx ; check on color change mov bh,ah ; new att_reverse pattern and bh,not(att_intensity+att_blink) ; look at just color bits mov bl,att_reverse ; previous att_reverse pattern and bl,not(att_intensity+att_blink) ; look at just color bits mov att_reverse,ah ; save new reverse pattern cmp bh,bl ; have any color bits changed? pop bx ; does not affect flags 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 ; Routine to do keyclick if flag is set. ; ; Call: No arguments ; vclick proc near test vtflags,vskeyclick ; Is the flag on? jz vclick1 ; No - just return push bx ; Save some ACs push di mov di,8 ; 5000 Hertz [rwb] mov bx,1 ; For 3 milliseconds. [rwb] call vtsound ; Do it. pop di ; Restore the ACs pop bx vclick1:ret vclick endp ; Routine to do VT100-style bell. ; ; Call: No arguments ; vtbell proc near push di push bx mov di,45 ; 880 Hertz [rwb] mov bx,22 ; For 70 ms. [rwb] call vtsound ; Do it. pop bx pop di ret vtbell endp ; Routine to make noise of arbitrary frequency for arbitrary duration. ; Derived from a routine in December 1984 Soft Sector, page 28. [rwb] ; Frequency and duration parameters are different than in the IBM ver. [rwb] ; Sound is generated by toggling the break bit in the keyboard UART [rwb] ; ; Call: di/ frequency is 40KHz / di value [rwb] ; bx/ duration is 3.2 msec * bx value [rwb] ; These approximate values break down badly for di < 10 [rwb] ; or if an accelerator board is installed. [rwb] vtsound proc near push ax ; Save regs. push bx push cx mov ax,35h ; UART cmd with break bit off vtsou1: mov cx,di xor al,8 ; toggle break bit out 3ah,al ; send it to UART vtsou2: dec ah jnz vtsou3 dec bx ; count down duration jz vtsou4 vtsou3: loop vtsou2 ; frequency count down jmp vtsou1 vtsou4: mov al,35h out 3ah,al ; turn off break bit on exit pop cx ; Restore regs. pop bx pop ax ret vtsound endp ; Routine to toggle VT100/VT52/Heath-19 modes. No arguments. ; Use & update global byte flags.vtflg for terminal type and update local ; bit decanm. Note: shifting to Heath-19 here does Not reset the scrolling ; margins mar_top & mar_bot nor reset the double char linetype array. ; [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 mov ah,14 ; Write character function mov bh,0 ; Page zero. int screen ; ... 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,att_intensity ; clear attributes, except bold bit 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... ; brkatt: mov al,0 ; Clear returned "extra" attributes cmp crt_mode,2 ; monochrome display adapter mode? jnz brkat1 ; Yes, can't be underline test ah,att_underline ; Underline? jz brkat2 ; No, some kind of reverse video or al,att_underline ; Yes, say underline test ah,70h ;;att_reverse ; Reverse video + underline? jz brkat1 ; No, fix up low nibble and ah,not att_underline ; Yes, clear the underline bit in ah jmp short brkat2 ; And forge on. brkat1: or ah,att_normal ; Normal - turn on all normal bits brkat2: test ah,att_intensity ; Intensity attribute on? jz brkat3 ; No - check blink or al,att_intensity ; Yes - turn on the bit brkat3: test ah,att_blink ; Blink on? jz brkat4 ; No - forge on or al,att_blink ; Yes - turn on the bit brkat4: and ah,not(att_intensity+att_blink) ;strip blink/bold, leave color 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". ; addatt: test al,att_underline ; Want underline? jz addat1 ; No - no need for hack and ah,not att_low_mask ; Yes - clear these bits addat1: or ah,al ; Or in the attributes. ; When a monochrome monitor is used on a Sanyo with a video board, some [rwb] ; "colors" are completely invisible. Following code guarantees all text ; is visible. test usevb,1 ; video board in use? jz addat2 ; z = no cmp crt_mode,2 ; monochrome? jne addat2 ; ne = no push bx mov bx,offset trtbl ; point at translate table xchg al,ah ; get original attribute in al and al,7fH ; translate table only half length xlat ; translate attribute xchg al,ah ; return in ah pop bx addat2: 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 ; [begin jhw] ; Modified to use bios calls for Sanyo without video board ; revscn: test usevb,1 ; video board in use? jz revscnv ; z = no 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 ax,es:[di] ; Fetch a word mov bl,al ; Save the character call brkatt ; Break up the attributes rol ah,1 ; Reverse the video rol ah,1 ; Reverse the video rol ah,1 ; Reverse the video rol ah,1 ; Reverse the video call addatt ; Put attributes back together mov al,bl ; Restore character mov es:[di],ax ; Stuff into screen memory. 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 revscnv:mov ax,0300h ; save cursor position on stack int screen push dx mov dx,0 revs1: mov ax,0200h int screen mov ax,0800h ; read character at cursor int screen mov bh,al ; char/attrib in al/ah call brkatt ; redo the attribute rol ah,1 rol ah,1 rol ah,1 rol ah,1 call addatt ; reassemble attributes mov bl,ah ; set up char/attrib in al/bl mov al,bh ; mov cx,1 mov ah,09h ; write char/attrib to screen int screen cmp dl,79 ; end of line? jae revs7 ; yes, go to next line inc dl ; else, go to next char jmp revs1 revs7: mov dl,0 cmp dh,24 ; bottom of screen? (done?) jae revs8 ; yes, finish up inc dh ; no, go to next line jmp revs1 revs8: pop dx ; restore cursor to where it was mov ax,0200h int screen ; end jhw [end jhw] 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 ; get present normal coloring call brkatt ; separate color and blink/bold rol ah,1 ; reverse fore/back color fields rol ah,1 rol ah,1 rol ah,1 call addatt ; put back blink/bold 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 ; turn off intensity bit 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 call brkatt ; Break into background & extra stuff rol ah,1 ; Reverse the background rol ah,1 ; Reverse the background rol ah,1 ; Reverse the background rol ah,1 ; Reverse the background call addatt ; Put it all back together 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 ;;;## test yflags,modoff ; is mode line disabled? jz ated0d ; z = yes, don't extend erase inc bh ; yes, extend erase to 25th line ated0d: ;;;## 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 ;;;## test yflags,modoff ; is mode line disabled? jz ated3b ; z = yes, don't extend erase inc bh ; yes, extend erase to 25th line ated3b: ;;;## 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,77h ; 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 ; Yes, set underscore. cmp crt_mode,2 ; monochrome display adapter mode? je atsgr3a ; e = yes. Otherwise reverse video ; use reversed video rather than blue on black and al,not att_underline ; clear underline and [jrd] rol ah,1 ; reverse the colors [jrd] rol ah,1 ; [jrd] rol ah,1 ; [jrd] rol ah,1 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 rol ah,1 ; reverse the colors rol ah,1 rol ah,1 rol ah,1 mov video_state,1 ; say reversed now. ret atsgr6: cmp bl,30 ; ANSI color series? [jrd] jb atsgrx ; b = no. cmp bl,37 ; foreground set (30-37)? ja atsgr7 ; a = no, try background set. sub bl,30 ; take away the bias and ah,not 07H ; clear foreground bits test bl,1 ; ANSI red? jz atsgr6a ; z = no or ah,4 ; IBM red foreground bit atsgr6a:test bl,2 ; ANSI & IBM green? jz atsgr6b ; z = no or ah,2 ; IBM green foreground bit atsgr6b:test bl,4 ; ANSI blue? jz atsgr6c ; z = no or ah,1 ; IBM blue foreground bit atsgr6c:ret atsgr7: cmp bl,40 ; background color set? jb atsgrx ; b = no cmp bl,47 ; background set is 40-47 ja atsgrx ; nb = no, not a color command. sub bl,40 ; take away the bias and ah,not 70H ; clear background bits test bl,1 ; ANSI red? jz atsgr7a ; z = no or ah,40h ; IBM red background bit atsgr7a:test bl,2 ; ANSI & IBM green? jz atsgr7b ; z = no or ah,20h ; IBM green background bit atsgr7b:test bl,4 ; ANSI blue? jz atsgrx ; z = no or ah,10h ; IBM blue background bit 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 call brkatt ; separate color and specials rol ah,1 ; Reverse the reversal (sic.) rol ah,1 ; Reverse the reversal (sic.) rol ah,1 ; Reverse the reversal (sic.) rol ah,1 ; Reverse the reversal (sic.) call addatt ; put blink/bold bits back in mov mlbattr,ah ; For mode line background mov ah,curattr ; Get current cursor attribute call brkatt ; Break it up rol ah,1 ; Reverse its background rol ah,1 ; Reverse its background rol ah,1 ; Reverse its background rol ah,1 ; Reverse its background call addatt ; Put it back together. mov curattr,ah ; And store it. 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 call brkatt ; breakup attributes byte rol ah,1 ; reverse foreground to background rol ah,1 rol ah,1 rol ah,1 call addatt ; put things together again 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 call brkatt ; breakup attributes byte rol ah,1 ; reverse foreground to background rol ah,1 rol ah,1 rol ah,1 call addatt ; put things together again 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 test usevb,1 ; video board in use? jz atdelv1 ; z = no 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 jmp short atdelv2 ; modify to use Sanyo bios sideways shift [begin jhw] ; (can't write to video RAM) atdelv1:mov al,ansargs ; no. of positions to shift mov ah,73h ; Sanyo bios sideways scroll mov cx,dx ; cursor position -- now mov dl,79 ; end of line coord. in dx mov bh,scbattr ; attribute for cleared position int screen ; [end jhw] atdelv2: 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 test usevb,1 ; video board in use? jnz insv1 ; nz = yes push ax ; mov al,1 ; shift one space (for use later) insv1: 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 test usevb,1 ; video board in use? jnz insv2 ; nz= yes mov al,2 ; and the number of cols to shift insv2: 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] test usevb,1 ; video board in use? jz insv3 ; z = no 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 jmp short insv4 ; use bios calls since Sanyo can't write ; to video RAM [begin jhw] insv3: mov ah,72h ; Sanyo sideways bios scroll mov cx,dx ; set left end of scroll region mov dl,79 ; set right end mov bh,scbattr ; attributes of cleared region int screen ; [end jhw] insv4: insch1: mov dx,cursor test usevb,1 ; video board in use? jnz insv5 ; nz = yes pop ax ; [jhw] insv5: 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 ah,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