        title mszibm
        page 60,132
; Terminal emulator module for IBM PC's and compatibles. Emulates Heath-19,
; VT52, and VT102 (without printer modes).
; Change method of displaying underlined characters from IBM official 'blue
; character on a black field' (which shows as a true underline on the mono-
; chrome adatper but not the color ones) to a simple reveral of the video,
; leaving intact the preexisting blink and intensity attributes. Change is
; in procedure atsgr3:  [jrd]
; Add delete char procedure for use when local echoing is done. [jrd]
; Correct code for special character handling in right-most column. Strange
; deletion display is the way a VT100 actually does it.
; Add (partial) code to support Set Term Color fore back.
; Add code to enable use of 25th line by Heath-19 mode. Mode line should be
; off to prevent overwriting normal mode line text and vice versa.
; Add revisions by Howie Kaye (CU) to permit 25th line operation with DEC
; emulation modes. [jrd]
;
; Edit history
; [2.29] [hlk]
; added high/wide mode. for ^[#n.
; fixed dsr request return code
; diddled around with underline mode...right now, it's for monochrome 
; monitors only
;
; [2.29] [jrd]
; Take this code from MS Kermit 2.27 [IU]; upgrade and incorporate in 2.29.
; Add VT102 char/line insert/delete, merge Heath-19 code (add some features).
; Add ability to toggle between Heath-19, VT52, and VT100 modes (Alt minus).
; Make VT52 mode stand alone. Reset (Alt =) does not change terminal type.
; Screen scrolling is located in module msyibm, as are several other support
; procedures needed to communicate with the rest of Kermit.
; "Setup" values are determined by Kermit's Set commands in mssset,
; but some initial values are determined by constant vsdefaults specified
; in mssdefs.h, in case mssset is not called.
; Communication with mssset is via structure vtemu.
; Communication with msyibm is via structure vtemu, public data quantities
; mar_top, mar_bot (screen line number scrolling limits), jwait (retrace flag),
; scbattr (screen background attributes byte),
; and through the public procedures listed below. Note, there are some
; definite machine dependencies left here (time limits being what they are)
; but most have been removed to msyibm.
; Topview support is included for char/line insert/delete.
; The structure of display attributes is that of the IBM PC where screen
; memory is laid out as display char byte, attribute byte, etc. The top
; left corner of the screen is coord 0,0 and the status line ends on 24,79.
; This module uses Bios calls (int 10, video i/o) and in/outs to the timer
; chip for sounds (beeps and key clicks).
; Absorb without action the VT102 printer control escape sequences, especially
; ESC [ Pn i  and  ESC [ ? Pn i.
;    [Joe R. Doupnik, Utah State Univ]
;
; [IU2]         JAH     27-Jun-85
; Add ANSI (VT100) terminal emulator. Put it in a separate module, MSZIBM.
;

        public  anstty, ansini, ansrei, ansdsl, anstat, anskbi ; Entry points
        public  ans52t, vclick, vsinit
        public  mar_top, mar_bot, jwait         ; 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 *

screen  equ     10h                     ; Bios screen call
swidth  equ     80                      ; Must agree with swidth in msyibm.
monochrome equ  7
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               ;[IU1] Type 0 - TTY (no special emulation)
;TTHEATH EQU    1               ;[IU1] Type 1 - HEATH 19
;TTVT52 EQU     2               ; [jrd] Type 2 - VT52
;TTVT100 EQU    3               ;[IU1] Type 3 - ANSI (VT100 subset)
;TTTYPES EQU    4               ;[IU1] Number of terminal types defined

;emulst struc           ; structure of vtemu.xxx for VT100 emulator
;vtflgst db     0       ; VT100 setup flags (from SET)
;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   ; [jrd]
	extrn monmode: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      decid                   ; 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      atlf                    ; FF - Interpreted as ANSI LF
        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', 'ELM'
        db      'NO@[p', 'qvwjk', 'xynz', 'blor'
lh19esc equ     $-h19esc

; Dispatch table for Heath-19 escape sequence table h19esc.
; Two byte sequences of the form ESC char, where char is not in the
; table above, are completely ignored.

h19ejt  dw      v52pos,atcuu,h19cud,h19cuf,h19cub       ; 'YABCD'
        dw      atel,atri,atcup,ated,v52egm             ; 'KIHJF'
        dw      v52xgm,hkpam,hkpnm,h19ans,decid         ; 'G=><Z'
        dw      h19clrs,inslin,dellin                   ; 'ELM'
        dw      atdelc,noins,entins,h19ans,h19herv      ; 'NO@[p'
        dw      h19hxrv,h19wrap,h19nowrp,atsc,atrc      ; 'qvwjk'
        dw      h19smod,h19cmod,hrcup,atreset           ; 'xynz'
        dw      h19erb,h19erl,h19ero,h19mbr             ; 'blor'


; VT52 compatibility mode escape follower table

v52esc  db      'Y','A','B','C','D'
        db      'K','I','H','J','F'
        db      'G','=','>','<','Z'
        db      '7','8','c'
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

; 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,atwdth,decid,atpriv
        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'
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,atnorm


; "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).

;;;dastr        db      esc,'[?c'               ; VT100 with nothing extra.
;;;dastr        db      esc,'[?2c'              ; VT100 with AVO only.
dastr   db      esc,'[?6c'              ; VT102 with AVO and GPO.
ldastr  equ     $-dastr

; Identify response used while in VT52 compatibility mode...

v52str  db      esc,'/Z'
lv52str equ     $-v52str

; Identify ourselves as a Heath-19 terminal. [jrd]

h19str  db      esc,'/K'
lh19str equ     $-h19str

; 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
lbaudtab        equ     $-baudtab

low_rgt dw      ?                       ; Lower right corner of screen window.
linful  db      0                       ; line full flag
yflags  db      ?                       ; Flags from MSYxxx term routine.
video_state db  0                       ; video state (0=normal,1=reversed)
oldbatr db      ?                       ; old scbattr [jrd]
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
jwait   db      0                       ; Flag for scron/scroff.
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      ?                       ; Cursor attribute
cursor  dw      ?                       ; Cursor position
chr_set dw      ?                       ; Ptr. to currently selected char set
lsavecu equ     $-curattr               ; Length of stuff to save.

chr_sg0 db      ascset                  ; Current SG0 set
chr_sg1 db      ascset                  ; Current SG1 set

savecu  db      lsavecu dup (?)         ; Saved cursor, attr., charset, etc.

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 vtdefs.h)

vtflags db      0                       ; VT100 SETUP flags
; (SETUP flags are defined in vtdefs.h)
tmpflags        db      0               ; (Temporary for asnrei/stblmds).

; (tab stops are stored here)           ; [jrd]
tabs    db      80 dup (?)              ; active tab stops.
deftabs db      80 dup (?)              ; default tab stops
vttabs  dw      0                       ; Pointer to default VT100 tab stops

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_row equ     24                      ; Row position for "LEDs" display
led_col equ     70                      ; Column "      "     "       "
led_off equ     '.'                     ; "Off" LED. [jrd]
led_on  equ     '*'                     ; "On" LED. [jrd]
ansleds db      'V102....'              ; "LEDs". (8 bytes)
v52leds db      'VT52    '              ; This is used in VT52 mode.
h19leds db      'Heath19 '              ; For Heath-19 mode [jrd]

nansarg db      0                       ; Index for ANSI argument list
ansargs db      10 dup (0)              ; Room for 10 ANSI arguments
lansarg equ     $-ansargs               ; Max number of ANSI arguments

resetonce db 	0			; reset once on connection
clrscr  db 	1			; flag for reset routine to clear scr
width	db	1			; flag to show what width we are in
widerow	db	0
curchar	db	0
datas   ends


code    segment public
        extrn   prtbout:near, prtnout:near, csrtype:near, trnmod:near
        extrn   scrmod:near, scrseg:near, scrsync:near, scroff:near
        extrn   scron:near, atsclr:near, atscru:near, atscrd:near
        extrn   modlin:near, telmsy:near                          ; [jrd]
                                ; extrn procedures are all in module msyibm

        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     insmod,0                ; turn off insert mode. [jrd]
        mov     deftabs,0               ; Column 1 has no tab stop.
        mov     cx,79D                  ; Loop for 79 columns.
        mov     di,1                    ; Starting index for column 2.
vsini1: mov     al,0                    ; Assume we will clear this one.
        test    di,0007H                ; Index mod 8 equal 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     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.

        ret                             ; And return.
vsinit  endp


; Initialization routine.
;
; Call:         al/     yflags byte that was passed to Term routine.
;               bx/     screen size (max row, col).
;               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     jwait,0                 ; Always clear this.
        mov     insmod,0                ; turn off insert mode. [jrd]
        mov     h19l25,0                ; clear Heath 25th line enable. [jrd]
        mov     low_rgt,bx              ; Save screen size
        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.
	cmp	resetonce, 1		; only clear screen first time we 
	je	ansin3			; connect
	mov	clrscr, 1
	jmp 	ansin4
ansin3:	mov 	clrscr, 0		; if not clring screen, save cursor
	mov 	ax, cursor
	push	ax
ansin4: call    atreset                 ; Reset everything
	mov 	clrscr, 1
	cmp	resetonce, 1
	jne	ansin5			; if we didn't clear screen
	pop	ax			; fix the cursor
	mov	cursor, ax
	mov	dx, ax
	mov     ah,2                    ; Position cursor at 24,70
        mov     bh,0                    ; Page zero.
        int     screen
ansin5:	mov	resetonce, 1
	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.vtflgst        ; get setup flags [jrd]
        mov     tmpflags,ah
        call    scrmod                  ; Get the screen mode.
        mov     al,1                    ; Assume underline cursor.
        test    tmpflags,vscursor       ; Block? (block is flag off?).
        jnz     ansre1                  ; No - we guessed right.
        mov     al,2                    ; Yes - set a block cursor.
ansre1: call    csrtype                 ; (For now, just set to underline)
        mov     dx,cursor               ; Set cursor in case moved.
        mov     ah,2
        mov     bh,0                    ; Page zero.
        int     screen
        mov     bx,vttabs               ; Get address of tab stop table.
        call    cpytabs                 ; copy the new ones.
ansre2: call    stblmds                 ; Check settable modes, set flags.
        ret
ansrei  endp


; This routine copies the new tab stops when they have changed.

cpytabs proc    near
        mov     cx,80D
        mov     si,vttabs               ; Source.
        mov     di,offset tabs          ; Destination.
        rep     movsb                   ; Do the copy.
        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.

stblmds proc    near
        mov     al,tmpflags             ; Get the new flags.
        and     ansflgs,not anslnm      ; assume want newline
        test    al,vsnewline            ; Did newline mode change?
        jz      stblm1                  ; No - continue.
        xor     ansflgs,anslnm          ; Yes - invert corresponding mode flag.
stblm1: and     ansflgs,not decawm      ; assume not want wrap
        test    al,vswrap               ; Did wrap mode change?
        jz      stblm2                  ; No - continue.
        or      ansflgs,decawm          ; Yes - set corresponding mode flag.
stblm2: mov     ah,vtflags              ; old flags
        xor     ah,tmpflags             ; new flags
        test    ah,vsshift3             ; pick out char set bit
        jz      stblm4                  ; z = no change
        mov     ah,ascset               ; assume US ASCII.
        test    tmpflags,vsshift3       ; Want UK?

        jz      stblm3                  ; No - guessed right.
        mov     ah,ukset                ; Yes - use UK set.
stblm3: mov     chr_sg0,ah              ; Set the sets.
        mov     chr_sg1,ah
stblm4: push    ax                      ; screen attributes.  [jrd]
        mov     ah,oldbatr              ; get old screen background scbattr
        mov     scbattr,ah              ; and update working copy
        mov     ah,att_normal
        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
        cmp     att_reverse,ah          ; anything changed?
        je      stblm9                  ; e = no
        mov     att_reverse,ah          ; yes, save new reverse pattern
        pop     ax
        mov     cursor,0                ; reset cursor position
        jmp     atres2                  ; got to semi-reset
stblm9: pop     ax
        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
        test    yflags,modoff           ; is mode line disabled?
        jnz     stblm8                  ; nz = disabled
        call    modlin                  ; rewrite it
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.

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,5000D                ; 5000 Hertz [jrd]
        mov     bx,1                    ; For 0.1 milliseconds. [jrd]
        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
        mov     di,880                  ; 880 Hertz [jrd]
        mov     bx,700                  ; For 70 ms. [jrd]
        call    vtsound                 ; Do it.
        ret
vtbell  endp

; Routine to make noise of arbitrary frequency for arbitrary duration.
; Similar to routine (with typo removed) in "IBM PC Assembly Language:
; A Guide for Programmers", Leo J. Scanlon, 1983 Robert J. Brady Co.,
; Bowie, MD., page 270. Modified by J R Doupnik to use 0.1 millsec interval.
;
; Call:         di/     frequency in Hertz.
;               bx/     duration in 0.5 milliseconds units. [jrd]
;

vtsound proc    near
        push    ax                      ; Save regs.
        push    bx
        push    cx
        push    dx
        push    di
        mov     al,0B6H                 ; Write timer mode register
        out     43H,al
        mov     dx,14H                  ; Timer divisor is
        mov     ax,4F38H                ; 1331000/frequency
        div     di
        out     42H,al                  ; Write timer 2 count low byte
        mov     al,ah
        out     42H,al                  ; Write timer 2 count high byte
        in      al,61H                  ; Get current port B setting
        mov     ah,al                   ; Save in ah
        or      al,3                    ; Turn speaker on.
        out     61H,al
vtsou1: mov     cx,28D                  ; Wait 0.1 millisecond [jrd]
vtsou2: loop    vtsou2
        dec     bx
        jnz     vtsou1                  ; Loop until count expired
        mov     al,ah                   ; Turn speaker off.
        out     61H,al
        pop     di                      ; Restore regs.
        pop     dx
        pop     cx
        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. [jrd]
ans52t  proc    near
        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
        jmp     ans52c
ans52a: cmp     flags.vtflg,ttheath     ; in Heath-19 mode?
        jne     ans52b                  ; ne = no
        mov     flags.vtflg,ttvt100     ; say VT100 now
        or      ansflgs,decanm          ; set, go to VT100 mode
        jmp     ans52c
ans52b: mov     flags.vtflg,ttheath     ; say Heath-19 now
ans52c: 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 24,70
        mov     bh,0                    ; Page zero.
        mov     dx,led_row*100H+led_col
        int     screen
        mov     cx,8                    ; Length of byte array is eight
        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 nine 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?
        jnz     atdeb                   ; Yes - just translate control chars.
        cmp     ttkbi,0                 ; New keyboard input?
        je      anstt1                  ; No - just continue
        mov     kbiflg,1                ; Yes - set flag
        mov     kbicsr,dx               ; Save old cursor
        mov     ttkbi,0                 ; Clear this flag.
anstt1: cmp     al,40Q                  ; Control character?
        jb      atctrl                  ; Yes, handle it.
        cmp     al,del                  ; above delete? [jrd]
        ja      atign                   ; ignore it
        je      atdel                   ; do it
        jmp     ttstate                 ; Nope, dispatch according to state.
atign:  ret                             ; Something to be ignored.

atctrl: mov     ah,0                    ; Make sure this is zero..
        mov     di,ax                   ; Put it in an index register
        shl     di,1                    ; Make it a word offset
        jmp     ansspc[di]              ; Dispatch.

atdel:  mov     ansargs,0               ; Delete one char to left [jrd]
        dec     dl                      ; move back one column
        call    atccpc                  ; check range of cursor
        call    atscu5                  ; move the cursor there and
        jmp     atdelc                  ; delete the char now under cursor

atdeb:  mov     bh,ansflgs              ; Save flags and attribute
        mov     bl,curattr
        push    bx
        push    word ptr mar_top        ; Save limited scrolling region
        and     al,177Q                 ; Make sure bit 7 of char is clear.
        push    ax                      ; Save character for a second
        mov     ah,curattr              ; Get attribute
        call    brkatt                  ; Break it up
        mov     al,0                    ; Clear extra-special stuff
        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
        cmp     al,del                  ; A DELETE?
        je      atdeb1                  ; Yes - output "^?" [jrd]
        cmp     al,40Q                  ; 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,100Q                 ; Make ^letter (or ^? for DELETE)
        and     al,177Q                 ; 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

atnrm:	push 	ax
	call 	atnrm0			; regular character...
        cmp     flags.vtflg,ttvt100     ; emulating a vt100?  
	jne	atnrmz			; no...all done
	cmp	width,1			; double width?
	je	atnrmz			; no...all done
	push	bx
	push	cx
	mov	bx, cursor		; get cursor position
	mov	ch, widerow		; get row we went into wide mode
	sub	bh, ch			; row is in bh
	cmp	bh, 0			; are they the same?
	jne	atnrmx			; nope...reset wide mode
	jmp	atnrmy
atnrmx: mov 	width, 1		; reset, don't display wide
	pop	cx			
	pop	bx
	jmp	atnrmz
atnrmy:	pop	cx			; display wide
	pop	bx
	mov	al, ' '			; insert a space...
	call	atnrm0			; ...for double width
atnrmz:	pop	ax
	ret

atnrm0:	mov     bx,chr_set              ; Get character set
        cmp     byte ptr [bx],sgrset    ; "Special" set?
        jne     atnrm1                  ; No - check UK.
        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.

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: 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]
        pop     ax                      ; restore char
atnrm3: cmp     linful,0                ; line full already? [jrd]
        je      atnrm4                  ; e = no
        push    ax                      ; save character
        mov     dx,cursor               ; get cursor virtual position
        call    atscur                  ; set cursor physical position
        pop     ax
atnrm4: 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
        mov     linful,0                ; assume line is not full yet.
        test    ansflgs,decawm          ; Autowrap?
        jz      atnrm5                  ; No, continue
        cmp     dl,byte ptr low_rgt     ; wrote in right-most column?
        jl      atnrm5                  ; l = no
        mov     linful,1                ; say line is full now
        mov     dl,byte ptr low_rgt     ; inc cursor but don't show on screen
        inc     dl                      ; no more than one position extra
        mov     cursor,dx               ; virtual cursor position
        ret                             ; and exit now
atnrm5: mov     dx,cursor               ; Restore cursor position
        inc     dl                      ; Bump cursor

atscur: cmp     dl,0                    ; To left of column zero?
        jge     atscu1                  ; No, continue
        mov     dl,0                    ; Yes - set at column zero.
atscu1: cmp     dl,byte ptr low_rgt     ; To right of right margin?
        jle     atscu3                  ; No, continue
        mov     dl,byte ptr low_rgt     ; Yes - assume no autowrap.
        test    ansflgs,decawm          ; Autowrap?
        jz      atscu3                  ; No, continue
        mov     dl,0                    ; Yes - set to column zero
        cmp     dh,mar_bot              ; At bottom of scrolling region?
        jne     atscu2                  ; No - bump cursor and continue
	mov	width, 1		; new line...cancel wide mode
        call    atscru                  ; Scroll up.
        jmp     atscu3                  ; Jump over the inc dh
atscu2: inc     dh                      ; Just bump it.
atscu3: cmp     dh,0                    ; Constrain row to valid range.
        jge     atscu4
        mov     dh,0
atscu4: cmp     dh,byte ptr low_rgt+1   ; 25th line?
        jle     atscu5                  ; le = no
        mov     dh,byte ptr low_rgt+1
        cmp     flags.vtflg,ttheath     ; emulating a Heath-19?
        jne     atscu7                  ; ne = no [hlk]
        cmp     h19l25,0                ; Heath 25th line enabled?
        je      atscu5                  ; e = no
atscu7: 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                    ; position cursor
        mov     bh,0                    ; Page zero.
        int     screen
        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,71D                  ; Old cursor at or left of column 72?
        jg      atscu6                  ; No - just return
        cmp     dl,71D                  ; Yes - new cursor past column 72?
        jle     atscu6                  ; 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: cmp     dl,0                    ; To left of left margin?
        jge     atccp1                  ; Yes, go check right
        mov     dl,0                    ; No, set to left margin
atccp1: cmp     dl,byte ptr low_rgt     ; To right of right margin
        jle     atccp2                  ; Yes, go check top
        mov     dl,byte ptr low_rgt     ; 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                  ; No, check bottom
        mov     dh,0                    ; Yes, stop here
atccp3: cmp     dh,byte ptr low_rgt+1   ; Below bottom of screen?
        jle     atccp4                  ; No, return
        mov     dh,byte ptr low_rgt+1   ; Yes, stop at bottom margin
atccp4: ret

atccp5: cmp     dh,mar_top              ; Above top of scrolling region?
        jge     atccp6                  ; No, check bottom
        mov     dh,mar_top              ; Yes, stop there.
atccp6: cmp     dh,mar_bot              ; Below bottom perhaps?
        jle     atccp4                  ; No, return
        mov     dh,mar_bot              ; Yes, stop at the bottom margin
        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.
;

atccic: mov     ax,offset atign         ; Assume no scrolling necessary
        mov     bx,cursor               ; Get old cursor.
        cmp     dl,0                    ; To left of left margin?
        jge     atcci1                  ; Yes, go check right
        mov     dl,0                    ; No, set to left margin
atcci1: cmp     dl,byte ptr low_rgt     ; To right of right margin
        jle     atcci2                  ; Yes, go check top
        mov     dl,byte ptr low_rgt     ; No, set to right margin
atcci2: cmp     dh,mar_top              ; Above top margin?
        jge     atcci5                  ; No, go check bottom one.
        cmp     bh,mar_top              ; Was old position at margin?
        jne     atcci4                  ; No, check against screen limit
        mov     ax,offset atscrd        ; Yes, indicate scroll down required.
        mov     dh,mar_top              ; Set to top margin
atcci3: ret

atcci4: cmp     dh,0                    ; Above screen?
        jge     atcci3                  ; No, just return.
        mov     dh,0                    ; Yes, set to top of screen
        ret

atcci5: cmp     dh,mar_bot              ; Below bottom margin?
        jle     atcci3                  ; No, just return
        cmp     bh,mar_bot              ; Was old position at bottom margin?
        jne     atcci6                  ; No, check against screen limit
        mov     ax,offset atscru        ; Yes, indicate scroll up required.
        mov     dh,mar_bot              ; Set to bottom margin
	mov	width, 1		; new line...cancel wide mode
        ret

atcci6: cmp     dh,byte ptr low_rgt+1   ; Below screen?
        jle     atcci3                  ; No, just return
        mov     dh,byte ptr low_rgt+1   ; Yes, set to bottom of screen
        ret


; 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
        jmp     brkat2          ; cut this short for color
        test    ah,att_low_mask         ; Any of these on?
        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,77h                  ; strip out 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.
        ret


; This routine is called when we want to reverse everything on the screen
; from normal to reverse video, or vice versa.  It is called only when
; the decscnm attribute is changed.
;
; Call:         no arguments.
;
; This routine may destroy ax-dx
;

revscn: mov     dx,low_rgt              ; Compute last screen offset in ax
        inc     dh                      ; One more row to catch mode line
        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


; 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     atres6                  ; ne = no. [jrd]
        mov     ansflgs,decanm          ; turn on ANSI mode flag. [jrd]
atres6: cmp     flags.vtflg,ttheath     ; Heath-19?
        jne     atres7                  ; ne = no
atres7: mov     mar_top,0               ; Reset scrolling region
        mov     al,byte ptr low_rgt+1
        mov     mar_bot,al
        mov     insmod,0                ; reset insert mode. [jrd]
        mov     h19l25,0                ; clear heath 25th line enable
        mov     cx,4                    ; Initialize the "LEDs". [jrd]
        mov     al,led_off              ; Turn them all off.
        mov     di,offset ansleds+4     ; Point to the "LEDs".
        rep     stosb                   ; Do it. [jrd]
        call    disleds                 ; update mode line. [jrd]
        mov     vttabs,offset deftabs   ; [jrd]
        call    cpytabs                 ; Initialize tab stops.
        call    chrdef                  ; Set default character set.
        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     al,att_normal           ; Assume normal video.
        mov     ah,att_reverse
        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     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.
        mov     video_state,0           ; say normal video. [jrd]
	cmp 	clrscr, 0
	je 	atrs3a
        mov     ax,0                    ; Clear entire screen.
        mov     bx,low_rgt
        call    atsclr
        call    vtbell                  ; Ding bell like VT100
atrs3a: mov     bh,0                    ; Page zero.
        mov     bl,mlbattr              ; Assume mode line is on.
        test    yflags,modoff           ; Is it off?
        jz      atres4                  ; z = no, it's on. [jrd]
        mov     bl,scbattr              ; Yes - use screen background attr.
atres4: mov     cx,swidth               ; Eighty columns.
        mov     dh,byte ptr low_rgt+1
        inc     dh
        mov     dl,0                    ; DX is position of start of mode line.
atres5: mov     ah,2                    ; Set cursor.
        int     screen
        mov     ah,8                    ; Read attribute/character.
        int     screen
        push    cx                      ; Save count.
        mov     cx,1                    ; Write one character.
        mov     ah,9                    ; Write character with our attribute.
        int     screen
        inc     dl                      ; Next column next time.
        pop     cx                      ; Restore cx
        loop    atres5                  ; Loop for entire mode line.
        mov     dx,cursor               ; Set cursor to 0,0.
        call    atscu5
        call    atsc                    ; Give saved cursor reasonable values.
        call    atsctyp                 ; Set right cursor type.
        ret

; Routine to set cursor type (block, underline).

atsctyp:mov     al,1                    ; Assume underline.
        test    vtflags,vscursor        ; Want block?
        jnz     atsct1                  ; No.
        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

; 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     flags.vtflg,ttheath     ; Heath-19 mode? [jrd]
        je      atbs2                   ; e = yes. handle differently. [jrd]
        dec     dl                      ; Backup cursor
atbs1:  call    atccpc                  ; Check range
        jmp     atscu5                  ; Set cursor and return
atbs2:  jmp     h19cub                  ; do Heath-19 cursor-back. [jrd]

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?
        jge     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
        call    atscu5                  ; reset cursor
        jmp     atnorm                  ; reset state too.

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
	mov 	width, 1		; can't be doing wide mode anymore
        jmp     atscu5                  ; Set cursor

atcr:   mov     dl,0                    ; Go to left margin
        mov     linful,0                ; say line is empty now.
        jmp     atscu5                  ; Set cursor and return.

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:  mov     ttstate,offset atnrm    ; Put state back to "normal".
        mov     al,177D                 ; Output error character and return
        jmp     atnrm

atesc:  mov     nansarg,0               ; Clear ANSI arguments
        mov     al,0
        mov     cx,lansarg
        mov     di,offset ansargs
        rep     stosb
        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]
        mov     cx,lansesc              ; Escape follower - get table length
        mov     di,offset ansesc        ; Point di at table
        repne   scasb                   ; Find it.
        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.
        repne   scasb                   ; Find it.
        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.
        mov     cx,lh19esc              ; Get table length
        mov     di,offset h19esc        ; Point di at table.
        repne   scasb                   ; Find it.
        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:  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     al,nansarg              ; Three instructions to do what a
        cbw                             ; real machine could do in one...
        mov     di,ax                   ; Get current argument storage index.
        mov     al,ansargs[di]          ; Pick up what we've done so far
        mov     bl,10                   ; Multiply by ten
        mul     bl
        jo      atpaovf                 ; Give error on overflow
        or      al,al                   ; Multiply does not set sign flag
        jl      atpaovf                 ; Our parms must be in range 0-127
        add     al,cl                   ; Add in this digit
        jo      atpaovf                 ; Check for overflow
        mov     ansargs[di],al          ; Put result back for next time
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                  ; No - continue
atpaovf:jmp     atcan                   ; Yes - abandon sequence on error.
atpa3a: mov     nansarg,al              ; Save it.
        ret

atpaa4: mov     ttstate,offset atnrm    ; Put state back to normal
        mov     cx,lanstab
        mov     di,offset anstab        ; Look for it in the table
        repne   scasb
        je      atpaa5                  ; Found it - go dispatch
        ret                             ; Just return if it is unknown.

atpaa5: 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
        rep     movsb                   ; Save it.
        mov     al,ansflgs              ; Save a copy of the flags.
        mov     savflgs,al              ; ...
        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
        rep     movsb                   ; Put the stuff back.
        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
        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
        jmp     atnorm                  ; Reset state and return.

atkpnm: and     ansflgs,not deckpam     ; Turn off the bit
        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     atscs2                  ; No - just use US ASCII
        mov     al,sgrset               ; Yes - say that's what it is
        ret

atwdth:	mov     ttstate,offset atwd1    ; Setup to get last character
        ret				; of width param

atwd1:  cmp 	al, '5'			; single width...
	je 	atwd2			; set it
	cmp 	al, '3'			; is char between 3 and 6
	jl	atwd3			; nope...invalid...ignore it
	cmp 	al, '6'
	jg	atwd3			
	mov	width, 2		; set double width
	push	ax
	mov	ax, cursor		; save the row we did this in
	mov	widerow, ah
	pop	ax
	jmp 	atwd3
atwd2:	mov 	width, 1		; set single width
atwd3:	mov	ttstate, offset atnrm
	ret


atpriv: mov     ttstate,offset atnorm   ; ignore next char.
        ret                             ; and return to normal afterward.

; 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]
        jle     atcup5                  ; le = no
        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
atcup6: mov     dh,byte ptr low_rgt+1   ; [hlk]
        inc     dh                      ; go there
        jmp     atscu4                  ; set cursor position & mode line

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.

atcuu:  call    atcuarg                 ; Get cursor move argument in al
        sub     dh,al                   ; Compute new cursor position
        jno     atcup4                  ; If no overflow, continue
        mov     dh,0                    ; Otherwise set to top of screen
        jmp     atcup4                  ; Check/set cursor, return.

atcud:  call    atcuarg                 ; Get the argument
        add     dh,al                   ; Compute new cursor position
        jno     atcup4                  ; If no overflow, continue
        mov     dh,byte ptr low_rgt+1   ; Else set to bottom of screen
        jmp     atcup4                  ; Check/set cursor, return.

atcuf:  call    atcuarg                 ; Get the argument
        add     dl,al                   ; Compute new cursor position
        jno     atcup4                  ; If no overflow, continue
        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
        jno     atcup4                  ; If no overflow, continue
        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...
        mov     bx,low_rgt              ; ...to end of screen, inclusive
        call    atsclr                  ; Clear it.
ated1:  ret

ated2:  cmp     ansargs[si],1           ; Was arg one?
        jne     ated3                   ; No - continue
        mov     ax,0                    ; Yes -  erase from start of screen...
        mov     bx,dx                   ; ...to cursor, inclusive
        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
        call    atsclr                  ; Clear it.
        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
        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
        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
        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.
        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.
	cmp 	monmode, monochrome	; monochrome monitor???
	jne	atsg3a			; ne = no
        or      al,att_underline        ; Yes, set underscore [Blue on Black]
                        ; use reversed video rather than blue on black
	ret			
atsg3a:        			
        and     al,not att_underline    ; clear underline and [jrd]
	rol     ah,1                    ; reverse the video [jrd]
	rol     ah,1                    ; [jrd]
	rol     ah,1                    ; [jrd]
	rol     ah,1                    ; end of modification [jrd]
        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                    ; Yes - reverse the video.
        rol     ah,1                    ; Yes - reverse the video.
        rol     ah,1                    ; Yes - reverse the video.
        rol     ah,1                    ; Yes - reverse the video.
        mov     video_state,1           ; say reversed now.

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
        mov     ah,curattr              ; get current attributes
        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:mov     curattr,ah              ; store the results.

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
        mov     ah,curattr              ; get current attributes
        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      atsgr7c                 ; z = no
        or      ah,10h                  ; IBM blue background bit
atsgr7c:mov     curattr,ah              ; store the results.

atsgrx: ret

attbc:  call    atccpc                  ; Make sure cursor is kosher
        mov     di,offset attbc0        ; Routine to call
        call    atreps                  ; Do for all parms
        ret

attbc0: cmp     ansargs[si],0           ; Was argument zero?
        jne     attbc2                  ; No - check further
        mov     dh,0                    ; Zap row for indexing
        mov     di,dx
        mov     tabs[di],00H            ; 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 80 columns
        mov     di,offset tabs          ; Point to the tab stop table.
        mov     al,00H                  ; Indicates no tab stop.
        rep     stosb                   ; Blit full of zeros.
        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?
        jle     atstb3                  ; If not, indicate an error.
        cmp     al,0                    ; Check against screen limits.
        jl      atstb3
        cmp     ah,byte ptr low_rgt+1
        jg      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: 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...
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: 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+4     ; Point to the "LEDs".
        rep     stosb                   ; [jrd]
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
        jl      atled2                  ; If not just ignore it.
        cmp     al,4                    ; Must be .LE. 4
        jg      atled2                  ; Ignore if not so.
        dec     al                      ; Zero base it.
        cbw                             ; Convert to index in ax.
        mov     di,ax                   ; Dumb specialized registers.
        mov     ansleds[di+4],led_on    ; Turn the "LED" on by storing '*'
        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,esc                  ; Send an escape to start off...
        call    prtbout
        mov     al,'['                  ; Then one of these...
        call    prtbout
        mov     al,'3'                  ; We only report on request...
        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
        call    prtnout                 ; Send number to the port..
        mov     al,';'                  ; Separate
        call    prtbout
        mov     al,'2'                  ; Assume 7 data bits
        cmp     datbits,7               ; Is it seven?
        je      atreq2
        mov     al,'1'                  ; No - 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
        call    prtnout                 ; Send it to the port
        mov     al,';'                  ; Separate (gee this is boring)
        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.
        ret                             ; No - must have been an echo

rpstat: mov     al,esc                  ; Tell them we think we are OK
        call    prtbout
        mov     al,'['
        call    prtbout
        mov     al,'0'                  ; supress the zero to avoid
        call    prtbout                 ; upsetting some hosts. [jrd]
        mov     al,'n'			; the 0 belongs...put it back
        call    prtbout
        ret

rpcup:  mov     al,esc                  ; 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

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                   ; 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                  ; Yes - go check it out.
        cmp     h19mod,0                ; Heath-19 private mode?
        jne     htrsm1                  ; ne = yes, do Heath specific things.
        cmp     al,20                   ; No - ANSI new-line mode?
        jne     atrsm0                  ;  but try insert mode. [jrd]
        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
        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      atrsm6                  ; e = yes, ignore this one. [jrd]
        mov     al,decanm               ; Yes - get the flag.
        jmp     atrsflg                 ; Set or reset it and return.

atrsm6: cmp     al,3                    ; 132/80 column mode change? [jrd]
        jne     atrsm7                  ; ne = no
        xor     ax,ax                   ; clear screen from 0,0
        mov     bx,word ptr low_rgt     ; to end of line 24
        call    atsclr                  ; do the clear
        xor     dx,dx                   ; new cursor position is 0,0
        mov     cursor,dx
        jmp     atscu5                  ; place it there and return

atrsm7: 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
        ret

htrsm4: cmp     al,4                    ; block/line cursor?
        jne     htrsm7                  ; ne = no
        cmp     modeset,0               ; reset?
        je      htrsm4a                 ; e = yes
        mov     al,1                    ; set underline cursor
        jmp     csrtype
htrsm4a:mov     al,2                    ; set block cursor
        jmp     csrtype

htrsm7: cmp     al,7                    ; alternate application keypad?
        jne     htrsm9                  ; ne = no
        mov     al,decanm               ; get ansi keypad mode bit
        jmp     atrsflg                 ; set or reset alt 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]
        ret
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: ret


atrsom: mov     al,decom                ; Get the flag
        cmp     modeset,0               ; Clearing DEC origin mode?
        je      atrsflg                 ; Yes - just do it.
        test    ansflgs,decom           ; Mode already set?
        jz      atrsom1                 ; No - set it and position cursor
        ret                             ; Yes - just return.
atrsom1:or      ansflgs,decom           ; Set it.
        mov     dx,cursor               ; Get the cursor
        call    atccpc                  ; Make sure we are in scrolling region.
        call    atscu5                  ; Set the cursor
        ret


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.
        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.
        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,37Q                  ; Minus offset.
        mov     ansargs,al              ; Stash it here.
        mov     ttstate,offset v52pc2   ; Next state.
        ret

v52pc2: sub     al,37Q                  ; Minus offset.
        mov     ansargs+1,al            ; Stash here.
        call    atnorm                  ; Reset state to "normal".
        jmp     atcup                   ; Position and return.

                                        ; Heath-19 special functions  [jrd]

                                        ; do several "ESC ["  ANSI commands
                                        ; but don't change terminal types
h19ans: 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     bx,low_rgt              ; to lower right corner
        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

                                        ; cursor back (left). ESC D
h19cub: mov     dx,cursor               ; cursor position (dh=row, dl=col)
        or      dl,dl                   ; if col > 0 then just backup
        jg      h19cub1                 ; g = col > 0
        test    ansflgs,decawm          ; line wrap on?
        jz      h19cub2                 ; z = no, stay at left margin
        or      dh,dh                   ; at row 0 (top of screen)?
        jz      h19cub2                 ; z = yes. don't scroll
        mov     dl,byte ptr low_rgt     ; set to right margin
        inc     dl                      ; + 1 to offset dec below.
        dec     dh                      ; go up a row
h19cub1:dec     dl                      ; back up one column
h19cub2:call    atccic                  ; check cursor position
        call    ax                      ; call scrolling routine
        jmp     atscu5                  ; set cursor and return

                                        ; set line wrap on
h19wrap:or      ansflgs,decawm          ; turn on the flag
        ret

                                        ; turn off line wrap
h19nowrp:and    ansflgs,not decawm      ; turn off the flag
        ret

hkpam:  or      ansflgs,decanm          ; set alt appl keypad mode
        ret

hkpnm:  and     ansflgs,not decanm      ; clear alt appl keypad mode
        ret

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     bl,byte ptr low_rgt     ; end of line
        mov     ax,cursor               ; get row
        xor     al,al                   ; column 0
        jmp     atsclr                  ; erase whole line, cursor stays put

h19ero: mov     bx,cursor               ; erase start of line to cursor
        mov     ax,cursor
        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)

                                        ; Heath-19 set mode "ESC x "
h19smod:mov     ttstate,offset hsmod    ; setup to parse rest of seq
        ret

hsmod:  cmp     al,'1'                  ; enable 25th line?
        jne     hsmod4                  ; ne = no
        mov     h19l25,1                ; enable the mode
        jmp     hsmodx

hsmod4: cmp     al,'4'                  ; set cursor type?
        jne     hsmodx                  ; ignore if not 4
        mov     al,2                    ; say want block cursor
        call    csrtype                 ; do it
hsmodx: jmp     atnorm                  ; reset state & return

                                        ; Heath-19 reset mode "ESC y "
h19cmod:mov     ttstate,offset hcmod    ; setup to parse rest of seq
        ret
hcmod:  cmp     al,'1'                  ; disable 25th line?
        jne     hcmod4                  ; ne = no
        mov     h19l25,0                ; disable 25th line mode.
        jmp     hsmodx

hcmod4: cmp     al,'4'                  ; change cursor type?
        jne     hsmodx                  ; ignore if not 4
        mov     al,1                    ; say want underline cursor
        call    csrtype                 ; do it
hcmodx: jmp     atnorm                  ; reset state & return

hrcup:  mov     al,esc                  ; 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                  ; no arg; use 1
        mov     ansargs,1               ; insert one line.
insli1: mov     dx,cursor               ; current position
        mov     dl,0                    ; go to right margin
        push    word ptr mar_top
        push    cx                      ; save a reg
        mov     cl,ansargs              ; get repeat count
        xor     ch,ch                   ; clear high byte
        mov     mar_top,dh              ; call present position the top
insli2: call    atscrd                  ; scroll down
        loop    insli2                  ; repeat until done (cx times)
        pop     cx                      ; restore reg
        pop     word ptr mar_top        ; restore margins
        mov     dx,cursor               ; original screen row
        xor     dl,dl                   ; go to left margin
        jmp     atscu5                  ; reposition cursor and return

dellin: cmp     ansargs,0               ; delete line(s). Any args? [jrd]
        jne     delli1                  ; no arg; use 1
        mov     ansargs,1               ; insert one line.
delli1: push    word ptr mar_top        ; save current scrolling margins
        mov     dx,cursor               ; where we are presently
        mov     dl,0                    ; use left margin
        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.
        mov     dx,cursor               ; use same location
        jmp     atscu5                  ; restore cursor and return

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
        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    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
        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
        mov     cl,byte ptr low_rgt     ; number of columns on screen
        sub     cl,dl                   ; compute distance to end
        xor     ch,ch                   ; clear top half of offset
        jcxz    insch1                  ; nothing to move...
        mov     jwait,0                 ; short wait time.
        mov     dl,byte ptr low_rgt
        sub     dl,2                    ; 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    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     cx                      ; count for Topview
        call    scrsync                 ; synch Topview
        pop     es                      ; restore regs
        pop     ax                      ; ditto
        call    scron                   ; turn on screen again
        cld                             ; reset direction
insch1: mov     dx,cursor
        jmp     atscu5                  ; position cursor

noins:  mov     insmod,0                ; turn off insert mode
        jmp     atnorm                  ; and return

entins: mov     insmod,0ffh             ; enter insert mode...
        jmp     atnorm                  ; and return

anstty  endp

code    ends

if1
        %out [End of pass 1]
else
        %out [End of assembly]
endif

        end



