	name msyv90
; File MSYV90.ASM
;       Copyright (C) 1982,1991, Trustees of Columbia University in the
;       City of New York.  Permission is granted to any individual or
;       institution to use, copy, or redistribute this software as long as
;       it is not sold for profit and this copyright notice is retained.
; Kermit system dependent module for VICTOR 9000/SIRIUS
;  Use with msuv90.asm and msxv90.asm.
; SPECIAL VERSION WITH NEAR COMPLETE SUPPORT OF TEKTRONIX 4010 EMULATION
; as of MS-DOS KERMIT version 3.02. Victor 9000 Kermit without
; Tektronix emulation will no longer be supported.
;
; Edit history:
; 2 March 1991 version 3.10
; Last modification: 2 March 1991
; 6 Dec 1988 Replace dynamic screen space with static segment aagraph (see
;  NOTE WELL msg below), add control of 7/8 bit displays, add TRANSLATE INPUT
;  table workings. [jrd]
; 1 Mar 1988 add TERMTB terminal status display table and correct use
;  of tektronix mode set to match that implemented in MSYIBM as of version
;  2.30.  Also add use of CAN (control-X) to exit tektronix temporary
;  mode. [bgp]
; 20 Sept 1987 clarify sequence of translation and 8 bit display. [jrd]
; 11 Sept 1987 Modify page_full routine for Tektronix emulation so that
;  the indicator box put in the lower left corner of the screen on page
;  full condition is put in with exclusive or instead of simple or.  Then
;  modified the homescr routine to remove that indicator box using an
;  exclusive or operation if the page full condition exists and to be sure
;  that the old text cursor is removed before moving the current cursor
;  location to the upper left corner. [bgp]
; 7 Sept 1987 Remove keep_delete, filter null in portch, filter DEL in
; terminal read section for VT100 (pass through for Tek), add parmsk. [jrd]
; 29 August 1987 add temporary Tektronix mode so that the receipt of an
;  ESCAPE FF (Tektronix clear screen sequence) will go to Tektronix mode with
;  a clear screen.  It will go back to the previous mode on the receipt of
;  an ESCAPE US sequence or by entering the escape character.
; 29 August 1987 add support for keyboard translation.	This uses a
;  modified version of the translator for the GENERIC MS-DOS version.
;  This modification required the addition of the following routines:
;    CQUERY - help on connect
;    CSTATUS - show status of connect
;    CQUIT - exit from connect
;    CHANG - hangup the phone (drop dtr)
;    DMPSCN - dump the screen
;    TRNPRS - toggle printer dump status
;    SNULL - send a null
;    KDOS - push to DOS
;    KLOGOFF - suspend session logging
;    KLOGON - resume session logging
;    CPAGE - clear tektronix screen
;    CHOME - move to home on tektronix screen
; 9 February 1987 Added set of keep_delete (byte) = 0 if delete to be
;  ignored by serial port routines [bgp]
; 7 August 1986 fill out procedure DUMPSCR - it was borrowed from MSYIBM
;  modified to fit the Victor format.  It required a modification of
;  LCLYINI to get the character set base [bgp]
;      7-DEC-85 ORIGINAL	BGP
;     20-FEB-86 CORRECTED FOR ERROR IN PUTMOD IN MSXV9000	(BGP)
;     22-FEB-86 CLEANED UP CHARACTER SET FOR TEK EMULATION	(BGP)
;     22-FEB-86 ADDED CODE TO SWALLOW ANSI ESCAPE SEQUENCES IN
;		HEATH EMULATION MODE				(BGP)
; ************************************************************
; Remove segment Graph and replace it with memory dynamically allocated
; from DOS via procedure sbrk in mssker.  Do allocation, verify that it
; is in the correct chunk of memory (and fix if necessary), initialize
; scrseg, and clear the area, all done in lclyini.    17 March 86
; Joe R. Doupnik
; Add global procedure Dumpscr, called by Ter in file msster, to dump screen
;   to a file. Just does a beep for now. 13 April 1986 [jrd]
;
; Added 'full' VT100 emulation using code by Andreas Stumpf
; (ZRZS@DS0RUS1I).    The significant parts that are not emulated are
;   esc c  - reset terminal
;   esc N  - ??
;   esc O  - ??
;   esc n  - ??
;   esc l  - ??
;   esc o  - ??
;   esc <  - go to ANSI mode (from VT52)
;   esc [ q    - fiddle with the LED's
;   esc [ h    - some modes not supported
;   esc [ l    - some modes not supported
;   esc [ i    - ??
;   esc [ p    - ??
;   esc [ y    - confidence tests
; and some codes that are not VT100 'standard' are supported
;   esc [ E    - ??
;   esc [ F    - ??
;   esc [ G    - ??
;   esc [ L    - ??
;   esc [ M    - ??
;   esc [ @    - ??
;   esc [ P    - ??
;   esc [ X    - ??
;   esc [ d    - ??
;   esc [ e    - ??
; 22 April 86 Bryan G. Peterson

	public	term, lclyini, vts, vtstat ; entry points
	public	dumpscr, extmacro, vtmacname, vtmaclen, setchtab
	public	cquery, cstatus, cquit, snull, kdos ; [bgp]
	public	klogof, klogon, cpage, chome	; [bgp]
	public	chang, trnprs, dmpscn, chrout	; [bgp]
	public	termtb, trnmod
	public	sescur, sesdisp, setnbios, fcsrtype

; NOTE WELL - The Victor 9000 machine requires high resolution (graphics)
; memory to be located in the first 128KB of system memory, even though
; programs are loaded into the same area(!). Here we define a special graphics
; segment, aagraph, and request the assembler to located segments
; as shown below, with _STACK last!
; Further we MUST place MSYV90.OBJ first in the Link list of .objs.
; [jrd 8 Dec 1988].
;
; Start  Stop   Length Name                   Class
; 00000H 09C5FH 09C60H AAGRAPH                KCODE
; 09C60H 14FB0H 0B351H CODE                   KCODE
; 14FC0H 1768FH 026D0H CODE1                  KCODE
; 17690H 17690H 00000H CODE2                  KCODE
; 17690H 24E9BH 0D80CH DATA                   KDATA
; 24EA0H 2627FH 013E0H DATA1                  KDATA
; 26280H 26280H 00000H _TEXT                  CODE
; 26280H 26280H 00000H _DATA                  DATA
; 26280H 26280H 00000H CONST                  CONST
; 26280H 26280H 00000H _BSS                   BSS
; 26280H 26FC7H 00D48H _STACK                 STACK
;
AAGRAPH	SEGMENT PUBLIC 'kcode'
	DB	40032 DUP (?)		; graphics memory
AAGRAPH	ENDS

; Do the "include mssdef.h" file after the aagraph declaration.
	include mssdef.h

;   Some extra ASCII definitions
ENQ	EQU	5
VTAB	EQU	0BH
ETB	EQU	17H
CAN	EQU	18H
GS	EQU	1DH
US	EQU	1FH

CURSOR_CHR EQU	'_'                     ; The cursor character
CURSOR_TIME EQU 100			; cursor on countdown period
;	this is the number of unsuccessful tries on getting a charcter
;	from the input port before turning on the cursor.

X_MAX	EQU	799
Y_MAX	EQU	399
TEK_X_MAX EQU	1023
TEK_Y_MAX EQU	780
TEXT_X_MAX EQU	789
TEXT_Y_MAX EQU	389
RPLINE	EQU	11			; rows per text line
CPCHAR	EQU	11			; columns per text character
R_MARG	EQU	781			; right margin position
CUR_LEN EQU	10			; length of arms on graphics cursor

FALSE	EQU	0
TRUE	EQU	1

SEG_CRTC EQU	0E800H			; segment for crt controller
OFF_CRTC EQU	0			; offset for crt controller

modfrm	struc				; format of mode line
	db	' Esc-chr:'
m_echr	db	2 dup (?)
	db	' Help:'
m_hlp	db	2 dup (?)
	db	'? Port:'
m_prt	db	1 dup (?)
	db	' Speed:'
m_baud	db	5 dup (?)
	db	' Parity:'
m_par	db	4 dup (?)
	db	' Echo:'
m_echo	db	3 dup (?)
m_term	db	13 dup (' ')            ; 13 bytes for terminal type
m_prn	db	3 dup (' ')             ; show PRN when printer is on
	db	' $'                   ; must be dollar terminated
modfrm	ends

data	segment
	extrn	rdbuf:byte, flags:byte		; to get access to emulation
	extrn	dmpname:byte, filtst:byte, trans:byte, prnhand:word
	extrn	kbdflg:byte,rxtable:byte,taklev:byte,takadr:word,mcctab:byte

termhlp db	CR,LF,'Terminal type of Heath-19, VT102, VT52, none,'
	db	' or Tek4010$'

termtb	db	5
	mkeyw	'Heath-19',ttheath
	mkeyw	'none',ttgenrc
	mkeyw	'Tek4010',tttek
	mkeyw	'VT102',ttvt100
	mkeyw	'VT52',ttvt52

setchtab db	1			; Set File Character-Set table
	mkeyw	'CP437',437		; hardware default Code Page

tty_generic db	' None        '
tty_tek4010 db	' Tektronix   '
tty_heath db	' Heath-19    '
tty_vt102 db	' VT-102      '
tty_vt52 db	' VT-52       '
tty_unkn  db	' Unknown     '
; stuff for screen routines
wflags	label	word		; so we can push yflags
yflags	db	?		; status flags...
	db	0		; extra byte for flags
flags1	db	0		; internal flags.
prtscr	equ	80h			; print screen pressed
inited	equ	08h			; been here before...
wrapped equ	04h			; on if wrapped on last char...
argadr	dw	?			; address of arg blk
crt_cols db	80			; number of screen columns (typ 80)
crt_lins db	24			; number of screen rows - 1 (typ 24)
oldsp	dw	0			; offset to longjmp to for i/o failure

vtmacname dw	0			; pointer to selected macro name
vtmaclen db	0
sescur	dw	0

modbuf	modfrm	<>			; mode line buffer
; routine to call for captured output
captrtn dw	?
; some static data for mode line
unkbaud db	'Unkwn'                 ; must be 5 chars...
baudn	db	' 45.5'
	db	'   50'
	db	'   75'
	db	'  110'
	db	'  135'
	db	'  150'
	db	'  300'
	db	'  600'
	db	' 1200'
	db	' 1800'
	db	' 2000'
	db	' 2400'
	db	' 4800'
	db	' 9600'
	db	'19200'
	db	'38400'
baudnsiz  equ	16			; # of baud rates known (tbl size / 4)
parnams db	'Even'
	db	'Mark'
	db	'None'
	db	'Odd '                  ; must be 4 chars
	db	'Spc '
offmsg	db	'Off'
onmsg	db	'On '
lclmsg	db	'Lcl'
remmsg	db	'Rem'

portno	db	?

tscreen dw	1920 dup (?)		; place to save text screen
tcurloc db	2 dup (?)		; column,row
tscrseg dw	0F000H
rptcur	db	27,'n$'                 ; request cursor location
escseq	db	0			; ANSI escape sequence indicator
					; 0=none, 1=escape, 2=[, <0 eat chars
					; until =0

; stuff for the Tektronix emulation
					; Order is essential:scrloc then scrseg
scrloc	dw	0			; offset of screen memory [jrd]
scrseg	dw	0			; segment of screen memory [jrd]
parmsk	db	?			; 8/7 bit parity mask, for reception
temp_tek db	FALSE			; for temporary tektronix mode [bgp]
temp_mode dw	0			; previous mode for temp tek mode [bgp]
tek_allowed db	TRUE			; flag for screen memory ok
no_tek_msg db	CR,LF,'SCREEN MEMORY ALLOCATION FAILED'
	db	' - TEKTRONIX EMULATION NOT ALLOWED',BELL,CR,LF,'$'
first_in db	TRUE			; this is the first time emulating
intens	db	14			; CRT intensity setting
status_line dw	80 dup (?)		; for CRT status line

bit_mask db	1,2,4,8,16,32,64,128
combine dw	pixel_or
t_combine dw	word_or
start	dw	0,0			; vector start point
endpt	dw	0,0			; end point (victor coords)
cur_x	dw	0			; tek coordinates of current point
cur_y	dw	780
text_x	dw	0			; text cursor location (victor coords)
text_y	dw	0			; upper left corner
cursor_cnt dw	0			; cursor countdown
cursor	db	FALSE			; cursor state flag
full_flag db	FALSE			; flags page full condition
x_inc	dw	1
y_inc	dw	1
delta_x dw	0
delta_y dw	0
part_accum dw	0			; accumulator for line
temp	dw	0			; temporary storage
c_mask	dw	0			; mask for character work
cur_stp dw	1			; graphics cursor step
crs_hor dw	0,0,0			; cursor horizontal line (x1,x2,y)
crs_ver dw	0,0,0			; cursor vertical line (y1,y2,x)
prtesc	db	FALSE			; escape from port in GIN mode
trmesc	db	FALSE			; escape from terminal in GIN mode


graph_mode db	FALSE			; graphics mode flag
echo_supp db	FALSE			; echoplex suppression flag
visible db	0			; 0 to move, 1 to draw
hiy	dw	0
loy	db	0
hix	dw	0
lox	db	0
lsb	db	0
escflag db	0
tekjump dw	TEKTXT,TEKESC,TEKHIY,TEKHIX

; The next variable defines the bit masks for the text font
font	dw	0,20H,70H,20H,20H,0,20H,20H,0,0,0 ; !
	dw	0,88H,88H,88H,0,0,0,0,0,0,0 ; "
	dw	0,88H,88H,3FEH,88H,3FEH,88H,88H,0,0,0 ; #
	dw	0,1FCH,222H,22H,1FCH,220H,222H,1FCH,0,0,0 ; $
	dw	0,10CH,8CH,40H,20H,10H,188H,184H,0,0,0 ; %
	dw	0,10H,28H,10H,28H,144H,84H,178H,0,0,0 ; &
	dw	0,30H,30H,20H,10H,0,0,0,0,0,0 ; '
	dw	0,40H,20H,10H,10H,10H,20H,40H,0,0,0 ; (
	dw	0,10H,20H,40H,40H,40H,20H,10H,0,0,0 ; )
	dw	0,104H,88H,50H,3FEH,50H,88H,104H,0,0,0 ; *
	dw	0,20H,20H,20H,3FEH,20H,20H,20H,0,0,0 ; +
	dw	0,0,0,0,0,0,30H,30H,20H,10H,0 ; ,
	dw	0,0,0,0,3FEH,0,0,0,0,0,0 ; -
	dw	0,0,0,0,0,0,30H,30H,0,0,0 ; .
	dw	0,100H,80H,40H,20H,10H,8,4,0,0,0 ; /
	dw	0,0F8H,184H,242H,222H,212H,10CH,0F8H,0,0,0 ; 0
	dw	0,20H,30H,20H,20H,20H,20H,70H,0,0,0 ; 1
	dw	0,1FCH,202H,200H,1FCH,2,2,3FEH,0,0,0 ; 2
	dw	0,3FEH,100H,80H,1C0H,200H,202H,1FCH,0,0,0 ; 3
	dw	0,102H,102H,102H,3FEH,100H,100H,100H,0,0,0 ; 4
	dw	0,3FEH,2,2,1FEH,200H,200H,1FEH,0,0,0 ; 5
	dw	0,1FCH,2,2,1FEH,202H,202H,1FCH,0,0,0 ; 6
	dw	0,3FEH,100H,80H,40H,20H,20H,20H,0,0,0 ; 7
	dw	0,0F8H,104H,88H,1FCH,202H,202H,1FCH,0,0,0 ; 8
	dw	0,1FCH,202H,202H,3FCH,200H,200H,1FCH,0,0,0 ; 9
	dw	0,0,30H,30H,0,0,30H,30H,0,0,0 ; :
	dw	0,0,30H,30H,0,0,30H,30H,20H,10H,0 ; ;
	dw	0,80H,40H,20H,10H,20H,40H,80H,0,0,0 ; <
	dw	0,0,0,3FEH,0,3FEH,0,0,0,0,0 ; =
	dw	0,8,10H,20H,40H,20H,10H,8,0,0,0 ; >
	dw	0,1FCH,202H,200H,1E0H,20H,0,20H,0,0,0 ; ?
	dw	0,1FCH,202H,3E2H,212H,1E2H,2,1FCH,0,0,0 ; @
	dw	0,70H,88H,104H,3FEH,202H,202H,202H,0,0,0 ; A
	dw	0,0FEH,102H,102H,1FEH,202H,202H,1FEH,0,0,0 ; B
	dw	0,1FCH,202H,2,2,2,202H,1FCH,0,0,0 ; C
	dw	0,1FEH,202H,202H,202H,202H,202H,1FEH,0,0,0 ; D
	dw	0,3FEH,2,2,7EH,2,2,3FEH,0,0,0 ; E
	dw	0,3FEH,2,2,7EH,2,2,2,0,0,0 ; F
	dw	0,1FCH,202H,2,382H,202H,202H,3FCH,0,0,0 ; G
	dw	0,202H,202H,202H,3FEH,202H,202H,202H,0,0,0 ; H
	dw	0,0F8H,20H,20H,20H,20H,20H,0F8H,0,0,0 ; I
	dw	0,3E0H,80H,80H,80H,80H,84H,78H,0,0,0 ; J
	dw	0,202H,102H,82H,7EH,82H,102H,202H,0,0,0 ; K
	dw	0,2,2,2,2,2,2,3FEH,0,0,0 ; L
	dw	0,306H,28AH,252H,222H,202H,202H,202H,0,0,0 ; M
	dw	0,206H,20AH,212H,222H,242H,282H,302H,0,0,0 ; N
	dw	0,1FCH,202H,202H,202H,202H,202H,1FCH,0,0,0 ; O
	dw	0,1FEH,202H,202H,1FEH,2,2,2,0,0,0 ; P
	dw	0,1FCH,202H,202H,202H,282H,102H,2FCH,0,0,0 ; Q
	dw	0,1FEH,202H,202H,1FEH,82H,102H,202H,0,0,0 ; R
	dw	0,1FCH,202H,2,1FCH,200H,202H,1FCH,0,0,0 ; S
	dw	0,3FEH,20H,20H,20H,20H,20H,20H,0,0,0 ; T
	dw	0,202H,202H,202H,202H,202H,302H,2FCH,0,0,0 ; U
	dw	0,202H,202H,202H,104H,88H,50H,20H,0,0,0 ; V
	dw	0,202H,202H,202H,222H,222H,154H,88H,0,0,0 ; W
	dw	0,104H,88H,50H,20H,50H,88H,104H,0,0,0 ; X
	dw	0,202H,104H,88H,50H,20H,20H,20H,0,0,0 ; Y
	dw	0,3FEH,80H,40H,20H,10H,8,3FEH,0,0,0 ; Z
	dw	0,70H,10H,10H,10H,10H,10H,70H,0,0,0 ; [
	dw	0,4,8,10H,20H,40H,80H,100H,0,0,0 ; \
	dw	0,70H,40H,40H,40H,40H,40H,70H,0,0,0 ; ]
	dw	0,20H,70H,0A8H,124H,20H,20H,20H,0,0,0 ; ^
	dw	0,0,0,0,0,0,0,0,0,0,7FFH ; _
	dw	0,10H,20H,40H,0,0,0,0,0,0,0 ; `
	dw	0,0,0,0F8H,100H,1F8H,104H,2F8H,0,0,0 ; a
	dw	0,4,4,0FCH,104H,104H,104H,0FCH,0,0,0 ; b
	dw	0,0,0,0F8H,104H,4,4,1F8H,0,0,0 ; c
	dw	0,100H,100H,1F8H,104H,104H,104H,1F8H,0,0,0 ; d
	dw	0,0,0,0F8H,104H,1FCH,4,1F8H,0,0,0 ; e
	dw	0,20H,50H,10H,38H,10H,10H,10H,0,0,0 ; f
	dw	0,0,0,1F8H,104H,104H,104H,1F8H,100H,100H,0F8H ; g
	dw	0,4,4,0FCH,104H,104H,104H,104H,0,0,0 ; h
	dw	0,0,20H,0,20H,20H,20H,20H,0,0,0 ; i
	dw	0,0,40H,0,40H,40H,40H,40H,40H,50H,20H ; j
	dw	0,4,4,44H,24H,3CH,44H,84H,0,0,0 ; k
	dw	0,30H,20H,20H,20H,20H,20H,0F8H,0,0,0 ; l
	dw	0,0,0,1DEH,222H,222H,222H,222H,0,0,0 ; m
	dw	0,0,0,0FCH,104H,104H,104H,104H,0,0,0 ; n
	dw	0,0,0,0F8H,104H,104H,104H,0F8H,0,0,0 ; o
	dw	0,0,0,0FCH,104H,104H,104H,0FCH,4,4,4 ; p
	dw	0,0,0,1F8H,104H,104H,104H,1F8H,100H,300H,100H ; q
	dw	0,0,0,0FCH,104H,4,4,4,0,0,0 ; r
	dw	0,0,0,0F8H,4,0F8H,100H,0FCH,0,0,0 ; s
	dw	0,10H,10H,78H,10H,10H,50H,20H,0,0,0 ; t
	dw	0,0,0,84H,84H,84H,84H,178H,0,0,0 ; u
	dw	0,0,0,104H,104H,88H,50H,20H,0,0,0 ; v
	dw	0,0,0,222H,222H,222H,222H,1DCH,0,0,0 ; w
	dw	0,0,0,88H,50H,20H,50H,88H,0,0,0 ; x
	dw	0,0,0,104H,104H,104H,104H,1F8H,100H,100H,0F8H ; y
	dw	0,0,0,0F8H,40H,20H,10H,0F8H,0,0,0 ; z
	dw	0,0C0H,20H,20H,10H,20H,20H,0C0H,0,0,0 ; {
	dw	0,20H,20H,20H,20H,20H,20H,20H,0,0,0 ; |
	dw	0,18H,20H,20H,40H,20H,20H,18H,0,0,0 ; }
	dw	0,0,1CH,222H,1C0H,0,0,0,0,0,0 ; ~

; stuff for ANSI emulation [as]
SUPERBIOS equ	0dfh		; SuperBios-Interrupt

tt	struc			; structure of keyboardtable
head	dw	2 dup (?)
kd0	db	104*3 dup (?)
kd12	dw	104*3 dup (?)
extrtabl db	256 dup (?)
tt	ends

afirst	db	0
; Parameterblock for setting/getting of keyboard-table
parmblock db	3
laenge	dw	1196		; length of table
offs	dw	offset oldtable
segm	dw	seg oldtable
; block for call to get Console-driver-address
condev	dw	1
drivadr dd	0		; address of consoledriver
;
oldtable tt	<,,,>		; saved old keytable
numtbl	tt	<,,,>		; Table with Num-Keypad
apptbl	tt	<,,,>		; Table with Appl-Keypad
; In order to avoid smashing stuff that may already be in the multi-char
; sequence table for the keyboard (or as little as possible) put it near the
; end of the table - the following parameters tells how deep into the table
; to start putting stuff
START_EXTRTBL EQU 160
; Cursorsequences ANSI
appcur	db	0		; flag for cursor key modes
curseq	db	3,ESCAPE,'[A',3,ESCAPE,'[B',3,ESCAPE,'[D',3,ESCAPE,'[C'
curapp	db	3,ESCAPE,'OA',3,ESCAPE,'OB',3,ESCAPE,'OD',3,ESCAPE,'OC'
; Applikationkeypad
appkeys db	0		; flag for keypad modes
applik	db	3,ESCAPE,'[A',3,ESCAPE,'[B',3,ESCAPE,'[D',3,ESCAPE,'[C'
	db	3,ESCAPE,'OP',3,ESCAPE,'OQ',3,ESCAPE,'OR',3,ESCAPE,'OS'
	db	3,ESCAPE,'Ow',3,ESCAPE,'Ox',3,ESCAPE,'Oy',3,ESCAPE,'Om'
	db	3,ESCAPE,'Ot',3,ESCAPE,'Ou',3,ESCAPE,'Ov',3,ESCAPE,'Ol'
	db	3,ESCAPE,'Oq',3,ESCAPE,'Or',3,ESCAPE,'Os',3,ESCAPE,'OM'
	db	3,ESCAPE,'Op',3,ESCAPE,'On'
sesctbl db	'DEHMNOZn|o[>=78c<)(#' ; table for char following single ESCAPE
	db	FF		; ESCAPE FF goes temporary tektronix [bgp]
sesclen equ	$-sesctbl
; now the table for routines to process those characters
sescsub dw	processD
	dw	processE
	dw	processH
	dw	processM
	dw	ignore
	dw	ignore
	dw	procc0		; same as ESCAPE [0c
	dw	ignore
	dw	ignore
	dw	ignore
	dw	processbra
	dw	processgt
	dw	processeq
	dw	process7
	dw	process8
	dw	ignore
	dw	ignore
	dw	processrp
	dw	processlp
	dw	processlb
	dw	process_ff	; temporary tektronix mode [bgp]
; table for the last characters in a ESCAPE'[' sequence
mesctbl db	'`EFGABCDHLM@PXKJfghilmrcnpyqde'
mesclen equ	$-mesctbl
; processing routine table for ESCAPE'[' sequences
mescsub dw	proce
	dw	proce
	dw	procuf
	dw	procug
	dw	curmov
	dw	curmov
	dw	curmov
	dw	curmov
	dw	procH
	dw	procL
	dw	procM
	dw	procAt
	dw	procP
	dw	procX
	dw	procK
	dw	procJ
	dw	procH
	dw	procg
	dw	prochl
	dw	ignore
	dw	prochl
	dw	proclm
	dw	procr
	dw	procc
	dw	procn
	dw	ignore
	dw	ignore
	dw	ignore
	dw	procld
	dw	procle
;
top	db	1		; scrolling region margins
bottom	db	24
escpnt	dw	offset escstring
escstring db	80 dup (?)	; save area for Escape sequence
tabstops db	0,0,0,0,0,0,0,0 ; tabulator stops
	db	1,0,0,0,0,0,0,0
	db	1,0,0,0,0,0,0,0
	db	1,0,0,0,0,0,0,0
	db	1,0,0,0,0,0,0,0
	db	1,0,0,0,0,0,0,0
	db	1,0,0,0,0,0,0,0
	db	1,0,0,0,0,0,0,0
	db	1,0,0,0,0,0,0,0
	db	1,0,0,0,0,0,0,0
chrset_mask db	0		; mask for selecting character set

char_base dw	0		; screen character base
crlf	db	cr,lf
dmphand dw	0		; handle for screen dump [bgp]
dumpbuf db	80 dup (?),CR,LF ; line buffer for screen dump
dumpsep db	FF,CR,LF	; put in file between screen dumps
dmperr	db	' WARNING: cannot open the screen dump file$'
data	ends

code1	segment

; Control text cursor. AL = 0 for off, 1 for on (nominally underline)
fcsrtype proc	far
	call	csrtype
	ret
fcsrtype endp
code1	ends

code	segment
	extrn	prtchr:near,outchr:near,cmblnk:near,poscur:near
	extrn	putmod:near,clrmod:near,beep:near,sbrk:near	; [jrd]
	extrn	comnd:near,isfile:near				; [bgp]
	extrn	msuinit:near, keybd:near			; [bgp]
	extrn	pntchr:near, pntflsh:near

	assume	cs:code,ds:data,es:nothing

; do initialization local to this module...
; mainly get console driver address to speed up screen access [as]
; Memory for screen must lie either entirely within the first 64K of memory,
; or within the second 64K of memory due to architecture of the CRT controller
; connections. It must also be aligned on an exact multiple of 32 bytes
; (rather than just on paragraph alignment).
; 7 August 1986 added code to get character set base for dump [bgp]

LCLYINI proc	near
	mov	flags.vtflg,ttvt102 ; start as a VT102
	call	msuinit 	; init keyboard module msuv90 [bgp]
	mov	ah,DCONIO
	mov	dl,ESCAPE	; to set nowrap
	int	DOS
	mov	dl,'w'
	int	DOS
	mov	ax,ds
	mov	es,ax
	mov	ax,14		; function 'get driveraddress'
	mov	bx,offset condev
	int	SUPERBIOS	; address is now in drivadr
				; setup screen
	mov	ax,aagraph	; segment of graphics memory (See Note above)
	cmp	ax,1000H	; start in lower half? [bgp sub-mod]
	jae	lclyini1	; ae = no
	cmp	ax,63BH 	; maximum segment in lower half
	jb	lclyini3	; b = low enough to work, go on
lclyini1:
	cmp	ax,163BH	; maximum segment in top half
	jb	lclyini3	; b = ok - go on
lclyini2:			; Tektronix emulation screen won't work...
	mov	dx,offset no_tek_msg ; tell the user we can't do it
	mov	ah,PRSTR
	int	DOS
	mov	tek_allowed,FALSE ; and flag it
	jmp	lclyini4

lclyini3:			; Tektronix will work fine
	inc	ax		; force round-up
	shr	ax,1		; divide by two
	shl	ax,1		; multiply by two - now multiple of 32
	mov	scrseg,ax	; save it [end bgp sub-mod]
	push	es
	call	clrscr		; make sure it is clear
	pop	es		; end of mod [jrd]
	mov	tek_allowed,TRUE ; flag that tektronix is ok

lclyini4:
	push	es
	mov	ax,0F000H	; point at base of screen memory
	mov	es,ax
	mov	ax,word ptr es:3838 ; note:  this should be the last character
				; of the last line on the screen - if it was
				; cleared as Kermit usually does when it starts
				; up, this will be a space - it must be a space!
	and	ax,7FFH 	; strip off mode bits
	sub	ax,' '          ; minus which char it is
	mov	char_base,ax	; and save it
	pop	es
	ret
LCLYINI endp

; We need to save the arguments to TERM where they are a little more
; accessible than in the way they were passed

ARGINI	proc	near			; read passed arguments
	mov	bx,argadr		; base of argument block
	mov	al,[bx].flgs		; get flags
	and	al,CAPT+EMHEATH+TRNCTL+LCLECHO+MODOFF
	mov	yflags,al		; mask for allowable and save
	and	flags1,not (PRTSCR)	; these are allowable
					; (others remain).
	mov	al,[bx].prt
	cmp	al,portno		; using same port?
	je	argin1			; yes, go on
	and	flags1,not inited	; else re-init stuff
	mov	first_in,TRUE		; graphics too...
argin1:
	mov	portno,al		; update port number
	mov	ax,[bx].captr
	mov	captrtn,ax		; buffer capture routine
	mov	parmsk,0ffh		; parity mask, assume parity = None
	cmp	[bx].parity,parnon	; is parity None?
	je	argini1 		; e = yes, keep all 8 bits
	mov	parmsk,07fh		; else keep lower 7 bits
argini1:ret				; that's it
ARGINI	endp

					; Toggle Mode Line
trnmod	proc	near
	cmp	flags.modflg,1		; mode line enabled and owned by us?
	jne	trnm1			; ne = no, don't touch it
	test	yflags,modoff		; mode line already off?
	jnz	trnm2			; nz = yes, go turn on
	or	yflags,modoff		; say modeline is toggled off
	call	clrmod			; clear mode line
trnm1:	clc				; clear c bit so don't exit Connect
	ret
trnm2:	cmp	flags.vtflg,0		; emulating a terminal?
	jne	trnm3			; ne = yes
	push	dx			; scroll screen to save bottom line
	mov	ah,prstr		; for terminal type none
	mov	dx,offset crlf
	int	dos
	pop	dx
trnm3:	call	modlin			; turn on modeline
	and	yflags,not modoff	; say modeline is not toggled off
	clc
	ret
trnmod	endp

; We need to generate the mode line and output it

MODLIN	proc	near			; turn on mode line
	push	es
	push	ds
	pop	es			; make sure es is correct
	mov	al,trans.escchr		; Connect mode escape character
	mov	modbuf.m_echr,' '       ; first char is initial space
	mov	modbuf.m_hlp,' '        ; goes here too.
	cmp	al,32			; printable?
	jnb	modl1			; yes, keep going
	add	al,40h			; made printable
	mov	modbuf.m_echr,'^'       ; note control char
	mov	modbuf.m_hlp,'^'
modl1:
	mov	modbuf.m_echr+1,al	; fill in character
	mov	modbuf.m_hlp+1,al
	mov	bx,argadr		; get argument block
	mov	al,[bx].baudb		; get baud bits
	mov	si,offset unkbaud	; assume unknown baud
	cmp	al,baudnsiz		; too big?
	jnb	modl2			; yes, use default
	mov	cl,5			; each is 5 bytes long
	mul	cl
	mov	ah,0
	add	ax,offset baudn
	mov	si,ax
modl2:
	mov	cx,size m_baud		; length of baud space
	mov	di,offset modbuf.m_baud
	cld
	rep	movsb			; copy in baud rate
	mov	al,[bx].parity		; get parity code
	mov	cl,2			; each is 4 bytes long...
	shl	al,cl
	mov	ah,0
	add	ax,offset parnams	; names of parity settings
	mov	si,ax
	mov	cx,4			; each is 4 long
	mov	di,offset modbuf.m_par
	rep	movsb
	mov	si,offset remmsg	; Assume remote echoing.
	test	yflags,lclecho		; Is remote side echoing?
	jz	modl4			; Yes, keep going
	mov	si,offset lclmsg	; Else it's local echoing.
modl4:
	mov	cx,3			; size of on/off
	mov	di,offset modbuf.m_echo
	rep	movsb
	mov	al,'1'
	cmp	portno,1		; 1=1
	je	modl5
	mov	al,'2'                  ; 0=2
modl5:
	mov	modbuf.m_prt,al 	; fill in port number
	mov	cl,13
	mov	di,offset modbuf.m_term ; fill in terminal type
	mov	si,offset tty_generic	; assume generic first
	cmp	flags.vtflg,TTGENRC
	je	modl6
	mov	si,offset tty_heath	; try heath
	cmp	flags.vtflg,TTHEATH
	je	modl6
	mov	si,offset tty_vt102	; try vt100
	cmp	flags.vtflg,TTVT100
	je	modl6
	mov	si,offset tty_vt52	; try vt52
	cmp	flags.vtflg,TTVT52
	je	modl6
	mov	si,offset tty_tek4010	; try tektronix
	cmp	flags.vtflg,TTTEK
	je	modl6
	mov	si,offset tty_unkn
modl6:
	rep	movsb
	mov	modbuf.m_prn,' '        ; assume not printing
	mov	modbuf.m_prn+1,' '
	mov	modbuf.m_prn+2,' '
	test	yflags,PRTSCR
	jz	modl7			; not
	mov	modbuf.m_prn,'P'
	mov	modbuf.m_prn+1,'R'
	mov	modbuf.m_prn+2,'N'
modl7:
	mov	dx,offset modbuf	; where it is
	call	putmod
	pop	es
	ret
MODLIN	endp

; This is the entry point for terminal emulation
; Added option of VT100 emulation

TERM	proc	near		; terminal emulator entry point
	mov	oldsp,sp	; remember stack for i/o failure,
	mov	argadr,ax	; save argument ptr
	push	es		; save caller's extra segment address
	mov	ax,seg data
	mov	es,ax
	call	argini		; init options from arg address
	call	save_mode	; [bgp]
	cmp	flags.vtflg,TTTEK ; emulating TEKTRONIX?
	jne	term0		; no
	call	tek4010 	; go look like a TEKTRONIX
	jmp	quit1
term0:
	test	flags1,inited	; have we run yet?
	jz	term1		; no, forget this part
	call	restscr 	; restore screen
	jmp	term2
term1:
	call	cmblnk		; clear it off
term2:
	or	flags1,inited	; remember we've run already.
	call	clrmod		; empty mode line
	test	yflags,modoff	; is mode line disabled?
	jnz	term3		; yes, skip it
	call	modlin		; turn on mode line
term3:
	cmp	flags.vtflg,TTVT100 ; emulating VT100?
	jne	lp
	call	ansie
	jmp	quit
lp:
	call	portchr 	; char at port?
	jnc	lp1		; nc = yes
	jmp	chkinp		; no, keep going
; we want to swallow any ANSI escapes that come for now
; they are all of the form ESCAPE [ nn ; nn ; nn ; nn a
; where n is a numeric character, and a is a non-numeric character
lp1:	test	flags.remflg,d8bit ; keep 8 bits for displays?
	jnz	lp2		; nz = yes
	and	al,7fh		; strip 8th bit
lp2:	cmp	escseq,0	; escape sequence in progress?
	jne	eat_esc_seq	; yes
	cmp	al,ESCAPE	; got an escape?
	jne	no_esc		; no
	mov	escseq,1	; yes, flag it
	jmp	chkinp
eat_esc_seq:
	cmp	escseq,1	; got [?
	jne	eat_esc_seq2	; yes
	cmp	al,FF		; ESCAPE FF is go temp tek mode [bgp]
	jne	eat_esc_seq0	; no [bgp]
	cmp	tek_allowed,FALSE ; is tek mode allowed? [bgp]
	jne	eat_esc_seq00	; yes, do it [bgp]
	mov	dx,offset no_tek_msg ; tell them about it [bgp]
	mov	ah,PRSTR	; [bgp]
	int	DOS		; [bgp]
	jmp	end_esc 	; all through [bgp]
eat_esc_seq00:
	mov	escseq,0	; not doing escape now [bgp]
	call	savescr 	; save current screen [bgp]
	call	tektemp 	; do it for a while [bgp]
	jnc	eat_esc_seq000	; carry=exit like esc char [bgp]
	call	clrmod		; clear mode line [bgp]
	jmp	quit1		; screen already saved [bgp]
eat_esc_seq000:
	call	restscr 	; restore the screen [bgp]
	jmp	end_esc 	; all through [bgp]
eat_esc_seq0:
	cmp	al,'['
	je	eat_esc_seq1
	push	ax		; not [, print esc and char
	mov	al,ESCAPE
	call	outtty		; send the escape
	pop	ax		; and the following character
	mov	escseq,0	; no escape sequence
	jmp	no_esc
eat_esc_seq1:
	mov	escseq,2	; flag [
	jmp	chkinp
eat_esc_seq2:
	cmp	al,';'          ; check for terminator
	je	chkinp
	cmp	al,'0'
	jl	end_esc
	cmp	al,'9'
	jg	end_esc
	jmp	chkinp		; no terminator, keep eating
end_esc:mov	escseq,0	; end of sequence
	jmp	chkinp
no_esc:	cmp	rxtable+256,0		; translation turned off?
	je	no_esc1			; e = yes, no translation
	push	bx
	mov	bx,offset rxtable	; address of translate table
	xlatb				; new char is in al
	pop	bx
no_esc1:call	outtty		; print on terminal

chkinp:	call	keybd		; get and translate a key [bgp]
	jc	quit		; carry=esc character entered - quit [bgp]
	jmp	lp		; keep looping [bgp]
quit:  	call	clrmod		; erase mode line
	call	savescr 	; save screen
quit1: 	call	rest_mode	; [bgp]
	mov	al,yflags
	mov	bx,argadr
	mov	[bx].flgs,al	; update flags in arg block
	pop	es		; restore segment register
	ret			; and return to caller
TERM	endp

; ANSI, VT100 emulation by Andreas Stumpf

ANSIE	proc	near
	cmp	afirst,1	; have we run yet?
	jnz	ansi2		; no, forget this part
	mov	bx,ds		; now restore keyboard too
	mov	es,bx
	mov	bx,offset parmblock
	mov	ax,18
	int	SUPERBIOS
	jmp	ansi3
ansi2:	call	initansi
ansi3:	mov	afirst,1	; remember we've run already.
portc:	call	portchr 	; char at port?
	jc	achkinp 	; c = no, get char from keyboard
	call	doansi		; handle it somehow
achkinp:
	call	keybd		; get and translate a key stroke [bgp]
	jnc	portc		; carry=esc char entered - quit [bgp]
aquit:	call	finiansi	; fix keyboard up
	ret
ANSIE	endp

; DOANSI actually takes care of emulating the ANSI screen control stuff
; code by Andreas Stumpf - it expects the character to be in al

DOANSI	proc	near
	test	flags.remflg,d8bit 	; keep 8 bits for displays?
	jnz	w00a			; nz = yes
	and	al,7fh			; strip 8th bit
w00a:	cmp	al,ESCAPE		; got an escape?
	jne	w00			; ne = no
	jmp	procesc0		; escape terminates Escape-sequence,
w00:					; so it has to be tested first
	cmp	escseq,0		; escape sequence in progress?
	jne	w0a			; ne = yes, no translation
	cmp	rxtable+256,0		; translation turned off?
	je	w0a			; e = yes, no translation
	push	bx
	mov	bx,offset rxtable	; address of translate table
	xlatb				; new char is in al
	pop	bx
w0a:	cmp	al,'X'-40h      ; Control-X ?
	jne	w0
	jmp	ignore
w0:
	cmp	al,'Z'-40h      ; Control-Z
	jne	w01
	jmp	ignore
w01:
	cmp	escseq,0	; escape sequence in progress?
	je	w02
	jmp	procesc 	; yes
w02:
	cmp	al,' '
	jb	controls
	or	al,chrset_mask	; [bgp]
	jmp	noesc
controls:
	cmp	al,LF		; Linefeed,Formfeed and Vertical tab are
				; processed as 'Scroll down, if at
				; bottom margin, same function as ESCAPE'D'
	jne	w1
	jmp	processD	; perform scrolling if necessary
w1:	cmp	al,FF
	jne	w2
	jmp	processD
w2:	cmp	al,11		; vertical tab
	jne	w3
	jmp	processD
w3:	cmp	al,TAB		; horizontal tab
	jne	w4
	call	get_cur_pos	; get cursor position
	mov	al,dh		; work on it here
	mov	cx,80
	sub	cl,al		; # of cols to search for tab
	cmp	cl,0		; already off the end?
	jg	t0		; no
	mov	cl,0
	jmp	t1		; go to right margin
t0:
	xor	ah,ah
	mov	di,offset tabstops
	add	di,ax		; address of first tabstop to look for
	cld
	mov	ax,1		; compare table with 1
	repnz	scasb		; cl=0 is right margin
t1:
	sub	cl,80
	neg	cl
	mov	dh,cl		; set new col pos
	call	set_cur_pos	; done...
	jmp	ignore
w4:	cmp	al,14		; shift to extra set?
	jne	w5
	mov	chrset_mask,80H ; set top bit on these
	jmp	ignore
w5:	cmp	al,15		; shift to normal set?
	jne	w6
	mov	chrset_mask,0	; clear top bit
	jmp	ignore

w6:	cmp	al,DEL		; DEL char? [jrd]
	jne	w7		; ne = no
	jmp	ignore		; ignore DEL
w7:	jmp	noesc		; else echo char to screen.

procesc0:			; start of escape sequence processing
	mov	escpnt,offset escstring
	mov	escseq,1	; flag it
	jmp	doansi_d	; done with it

procesc:			; have just got an escape
	cmp	escseq,1	; single char ESCape ?
	je	procesc1	; yes process it
	inc	escseq
	inc	escpnt		; store escape sequence for
	mov	bx,escpnt	; further processing
	mov	[bx],al
	cmp	escseq,3
	jg	proccont1
	cmp	escseq,0	; [bgp]
	jle	proccont1a	; [bgp]
	cmp	al,'?'          ; 1st char after ESCAPE'[' may be a '?'
	jne	proccont1
proccont1a:
	jmp	doansi_d	; done with it
proccont1:
	cmp	al,';'
	jne	proccont2
	jmp	doansi_d
proccont2:
	cmp	al,'-'          ; may be first char of a number
	jne	proccont3	; continue checking
	mov	bx,escpnt
	cmp	byte ptr [bx-1],'0' ; preceding char in [0..9] ?
	jl	procmin1	; if yes, then syntax error =>
	jmp	ignore		; ignore Escapesequence
procmin1:
	cmp	byte ptr [bx-1],'9'
	jg	procmin2
	jmp	ignore
procmin2:
	jmp	doansi_d
proccont3:
	cmp	al,'0'
	jl	proccont
	cmp	al,'9'
	jg	proccont
	jmp	doansi_d	; ESCAPE-seq hasn't finished yet
proccont:
	jmp	procmulti	; other char than 0..9 ';' => process them
procesc1:	; function dispatcher for single char Escapesequences
	mov	di,offset sesctbl
	mov	cx,sesclen
	cld
	repnz	scasb		; search for legal char following ESCAPE
	cmp	al,[di-1]
	jnz	notrecognized
	mov	bx,sesclen
	sub	bx,cx		; get offset in table
	dec	bx
	shl	bx,1
	add	bx,offset sescsub
	mov	escseq,0	; Escape sequence has finished
	jmp	[bx]
notrecognized:
	jmp	noesc

processbra:			; introduction of multi-char Escapesequence
	mov	escseq,2
	inc	escpnt
	mov	bx,escpnt
	mov	[bx],al 	; save that char
	jmp	doansi_d	; and get next one

processH:
	call	get_cur_pos	; get cursor position
	mov	al,dh		; get column here
	dec	al		; range 0 to 79
	mov	bx,offset tabstops
	xor	ah,ah
	add	bx,ax
	mov	byte ptr [bx],1
	jmp	ignore

processD:
	call	get_cur_pos	; get cursor position
	cmp	dl,bottom	; is it last line?
	je	delline 	; yes, need to insert
	inc	dl		; move down one line
	call	set_cur_pos
	jmp	ignore		; done
delline:			; perform a scroll-up
	push	dx		; save where we were
	mov	dl,top
	mov	dh,1		; goto (top,1)
	call	set_cur_pos
	mov	al,ESCAPE
	call	outtty
	mov	al,'M'          ; delete line
	call	outtty
	pop	dx		; get back where we were
	push	dx
	mov	dh,1		; column 1
	call	set_cur_pos
	mov	al,ESCAPE
	call	outtty
	mov	al,'L'          ; insert line
	call	outtty
	pop	dx		; get it back again
	cmp	dh,1
	je	processD1	; done
	call	set_cur_pos	; move to final position
processD1:
	jmp	ignore

processE:
	mov	al,CR		; same as ESCAPE'D', but in col 1
	call	outtty		; so write out Carriage return
	jmp	processD

processM:
	call	get_cur_pos	; get cursor position
	cmp	dl,top
	je	insline 	; yes, jump to insert
	dec	dl		; move up one
	call	set_cur_pos
	jmp	ignore
insline:			; perform a scroll-down
	push	dx		; save current position
	mov	dl,bottom
	mov	dh,1		; 1. position to bottom margin
	call	set_cur_pos
	mov	al,ESCAPE	; 2. delete line
	call	outtty
	mov	al,'M'
	call	outtty
	mov	dl,top
	mov	dh,1		; 3. position to top margin
	call	set_cur_pos
	mov	al,ESCAPE
	call	outtty
	mov	al,'L'          ; 4. insert line with ESCAPE 'L'
	call	outtty
	pop	dx		; get back my position
	cmp	dh,1		; first col?
	je	processM1	; yes
	call	set_cur_pos
processM1:
	jmp	ignore		; all done

processeq:			; set applikation keypad
	mov	ax,ds
	mov	es,ax
	mov	cx,8
	mov	di, offset apptbl.extrtabl
	add	di,START_EXTRTBL ; don't want to start at the top
	cmp	appcur,0	; cursor keys application ?
	je	peq1
	mov	si,offset curapp
	jmp	peq2
peq1:	mov	si,offset curseq
peq2:	rep	movsw		; move cursor keys to key-table
	mov	appkeys,1
	mov	bx,offset parmblock
	mov	byte ptr [bx],2
	mov	offs,offset apptbl
	mov	ax,18
	int	SUPERBIOS	; set new keytable
	jmp	ignore

processgt:			; set numeric keypad
	mov	ax,ds
	mov	es,ax
	mov	cx,8
	mov	di, offset numtbl.extrtabl
	add	di,START_EXTRTBL ; don't want to start at the top
	cmp	appcur,0
	je	pgt1
	mov	si,offset curapp
	jmp	pgt2
pgt1:	mov	si,offset curseq
pgt2:	rep	movsw
	mov	appkeys,0
	mov	bx,offset parmblock
	mov	byte ptr [bx],2
	mov	offs,offset numtbl
	mov	ax,18
	int	SUPERBIOS
	jmp	ignore

process7:			; save cursor position
	mov	al,ESCAPE
	call	outtty
	mov	al,'j'
	jmp	noesc

process8:			; restore cursor position
	mov	al,ESCAPE
	call	outtty
	mov	al,'k'
	jmp	noesc

process_ff:	; temporary tektronix mode if allowed [bgp]
	cmp	tek_allowed,FALSE ; ok? [bgp]
	jne	process_ff1	; yes [bgp]
	mov	dx,offset no_tek_msg ; tell them [bgp]
	mov	ah,PRSTR	; [bgp]
	int	DOS		; [bgp]
	jmp	ignore		; end of sequence [bgp]
process_ff1:
	call	savescr 	; save the screen [bgp]
	mov	escseq,0	; [bgp]
	call	tektemp 	; [bgp]
	jc	process_ff2	; carry=esc char entered [bgp]
	call	restscr 	; restore the screen [bgp]
	jmp	ignore		; end of sequence [bgp]
process_ff2:
	pop	ax		; return address from call to DOANSI [bgp]
				; this is kludgey but it is necessary to
				; make this look like we are actually at
				; the point right after calling keybd and
				; receiving an esc char.
	call	finiansi	; restore old keyboard [bgp]
	pop	ax		; imagine that we have returned from ANSI [bgp]
	call	clrmod		; clear off the mode line [bgp]
	jmp	quit1		; normal exit but no save screen! [bgp]

procmulti:	; function dispatcher for multi-character escape-sequences
		; AL has terminating character
	mov	cx,ds
	mov	es,cx
	mov	di,offset mesctbl
	mov	cx,mesclen
	cld
	repnz	scasb
	cmp	al,[di-1]
	jnz	notrec		; didn't find it in table
	mov	bx,mesclen
	sub	bx,cx		; get offset in table
	dec	bx
	shl	bx,1
	add	bx,offset mescsub
	jmp	[bx]
notrec: jmp	noesc

curmov: ; process Cursor movements
	cmp	escseq,3	; has no mumeric argument
	jne	pars
curmov0:
	mov	al,ESCAPE
	call	outtty
	mov	bx,escpnt
	mov	al,[bx]
	jmp	noesc		; print it without '['
pars:				; parse numeric argument
	mov	bx,offset escstring+2 ; skip ESCAPE'['
	call	getnum		; getnum returns the number in DL
	xor	dh,dh
	cmp	dl,80
	jg	curmovend
	cmp	dl,0
	jl	curmovend
	je	curmov0
	mov	cx,dx		; becomes loop counter
	mov	bx,escpnt
	mov	bl,[bx] 	; put last char of sequence in bl
parsl2:
	mov	al,ESCAPE
	call	outtty
	mov	al,bl
	call	outtty
	loop	parsl2
curmovend:
	jmp	ignore		; ignore invalid positioning

procg:
	mov	bx,offset escstring+2
	call	getnum
	cmp	dl,0
	jne	procg1
	call	get_cur_pos
	mov	al,dh		; current col here
	dec	al		; range 0 to 79
	mov	bx,offset tabstops
	xor	ah,ah
	add	bx,ax
	mov	byte ptr [bx],0
	jmp	ignore
procg1:
	cmp	dl,3
	jne	procg3
	mov	cx,80
	push	es
	push	ds
	pop	es		; make sure in right segment
	mov	di,offset tabstops
	xor	ax,ax
	rep	stosb
	pop	es		; get old es back
procg3:
	jmp	ignore

procE:
	mov	al,CR		; go to col 1
	call	outtty
procle:
	mov	bx,escpnt
	mov	byte ptr [bx],'B' ; process cursor down
	jmp	curmov

procuF:
	mov	al,CR		; go to col 1
	call	outtty
	mov	bx, escpnt
	mov	byte ptr [bx],'A' ; cursor up
	jmp	curmov

procuG:
	mov	bx,offset escstring+2
	call	getnum
	cmp	dl,0
	jg	procug1
	mov	dl,1
procug1:
	cmp	dl,80
	jle	procug2
	mov	dl,80
procug2:
	mov	cl,dl
	call	get_cur_pos
	mov	dh,cl		; set new column
	call	set_cur_pos
	jmp	ignore

procld:
	mov	bx,offset escstring+2
	call	getnum
	cmp	dl,0
	jg	procld1
	mov	dl,1
procld1:
	cmp	dl,24
	jle	procld2
	mov	dl,24
procld2:
	mov	cl,dl
	call	get_cur_pos
	mov	dl,cl
	call	set_cur_pos
	jmp	ignore

procH:				; position cursor
	mov	bx,offset escstring+2
	call	getnum
	cmp	dl,1
	jge	procH0
	mov	dl,1		; provide default for invalid address
procH0:
	cmp	dl,24
	jg	badH
	cmp	byte ptr [bx],';'
	jne	procH01
	inc	bx
procH01:
	push	dx		; save row value
	call	getnum
	pop	ax		; get it back here
	cmp	dl,1
	jge	procH1
	mov	dl,1
procH1:
	cmp	dl,80
	jg	badH
	mov	dh,dl		; get in right places
	mov	dl,al
	call	set_cur_pos
badH:
	jmp	ignore

procL:
	mov	bx,offset escstring+2
	call	getnum
	mov	cx,dx
	cmp	cx,0
	jg	procL0
	mov	cx,1
	jmp	procL1
procL0:
	cmp	cx,24
	jle	procL1
	mov	cx,1
procL1:
	call	get_cur_pos
	mov	bh,dl
	mov	bl,dh		; save these
procL2: 			; perform a insert line
	mov	dl,bottom
	mov	dh,1
	call	set_cur_pos
	mov	al,ESCAPE
	call	outtty
	mov	al,'M'
	call	outtty
	mov	dl,bh		; get in right place
	mov	dh,bl
	call	set_cur_pos
	mov	al,ESCAPE
	call	outtty
	mov	al,'L'
	call	outtty
	loop	procL2
	jmp	ignore

procM:
	mov	bx,offset escstring+2
	call	getnum
	mov	cx,dx
	cmp	cx,0
	jg	procM0
	mov	cx,1
	jmp	procM1
procM0:
	cmp	cx,24
	jle	procM1
	mov	cx,1
procM1:
	call	get_cur_pos
	mov	bh,dl
	mov	bl,dh
procM2: 			; perform a delete line
	mov	al,ESCAPE
	call	outtty
	mov	al,'M'
	call	outtty
	mov	dl,bottom
	mov	dh,1
	call	set_cur_pos
	mov	al,ESCAPE
	call	outtty
	mov	al,'L'
	call	outtty
	mov	dl,bh		; get in right places
	mov	dh,bl
	call	set_cur_pos
	loop	procM2
	jmp	ignore

procAt: 			; insert blank characters
	mov	bx,offset escstring+2
	call	getnum
	mov	cx,dx
	sub	cx,1
	mov	al,ESCAPE
	call	outtty
	mov	al,'@'
	call	outtty
	mov	al,' '
	call	outtty
	mov	al,BS
	call	outtty
	cmp	cx,0
	jle	procat1
procat2:
	mov	al,' '
	call	outtty
	mov	al,BS
	call	outtty
	loop	procat2
procat1:
	mov	al,ESCAPE
	call	outtty
	mov	al,'O'
	call	outtty
	jmp	ignore

procP:
procX:
	mov	bx,offset escstring+2
	call	getnum
	mov	cx,dx
	cmp	cx,0
	jg	procX1
	mov	cx,1
procX1:
	mov	al,ESCAPE
	call	outtty
	mov	al,'N'
	call	outtty
	loop	procX1
	jmp	ignore

procr:				; set margins
	mov	top,1
	mov	bottom,24
	mov	bx,offset escstring+2
	call	getnum
	cmp	dl,1
	jl	procr1
	cmp	dl,23
	jg	procr1
	mov	top,dl
procr1:
	inc	bx
	call	getnum
	cmp	dl,top
	jl	procr2
	cmp	dl,24
	jg	procr2
	mov	bottom,dl
procr2:
	mov	dh,1		; After inspecting what the VAX EDT editor does,
	mov	dl,1		; it appears that ESCAPE [ Pn r should leave
	call	set_cur_pos	; the cursor in the upper left corner [bgp]
	jmp	ignore

procc:				; Terminal status request
	mov	bx,offset escstring+2
	cmp	byte ptr [bx],'>'
	je	procc2
	cmp	byte ptr [bx],'0'
	je	procc0
	cmp	byte ptr [bx],'c'
	je	procc0
	jmp	ignore
procc0:
	push	wflags		; need to save these
	and	yflags,not lclecho ; force no echo for these
	mov	al,ESCAPE
	call	outprt
	mov	al,'['
	call	outprt
	mov	al,'?'
	call	outprt
	mov	al,'1'
	call	outprt
	mov	al,';'          ; signal AVO option - we sort of have it
	call	outprt
	mov	al,'2'
	call	outprt
	mov	al,'c'
	call	outprt
	pop	wflags		; get back old flags
procc2:
	jmp	ignore

procn:				; device status report
	mov	bx,offset escstring+2
	cmp	byte ptr [bx],'5'
	je	procn5
	cmp	byte ptr [bx],'6'
	je	procn6
	jmp	ignore
procn5: 			; return operating status 'no malfunction'
	push	wflags		; force no echo
	and	yflags,not lclecho
	mov	al,ESCAPE
	call	outprt
	mov	al,'['
	call	outprt
	mov	al,'0'
	call	outprt
	mov	al,'n'
	call	outprt
	pop	wflags
	jmp	ignore
procn6: 			; report cursor position
	push	wflags		; force no echo
	and	yflags,not lclecho
	call	get_cur_pos
	mov	al,dh		; get column here
	sub	al,1fh		; get binary column
	aam
	add	ax,3030h	; change to ASCII
	push	ax
	mov	al,dl		; get line here now
	sub	al,1fh		; convert to binary
	aam			; and to ...
	add	ax,3030h	; ASCII
	mov	bx,ax
	mov	al,ESCAPE     ; put string out in form : ESCAPE'['line';'col'R'
	call	outprt
	mov	al,'['
	call	outprt
	cmp	bh,30h		; don't need leading zero
	je	procc61
	mov	al,bh
	call	outprt
procc61:
	mov	al,bl
	call	outprt
	mov	al,';'
	call	outprt
	pop	bx
	cmp	bh,30h
	je	procc62
	mov	al,bh
	call	outprt
procc62:
	mov	al,bl
	call	outprt
	mov	al,'R'
	call	outprt
	pop	wflags		; get these back
	jmp	ignore

proclm: 			; do screen attributes
	mov	bx,offset escstring+2
proclm1:
	call	getnum
	cmp	dl,0
	jne	proclm2
	mov	al,ESCAPE
	call	outtty
	mov	al,')'
	call	outtty
	mov	al,ESCAPE
	call	outtty
	mov	al,'q'
	call	outtty
	mov	al,ESCAPE
	call	outtty
	mov	al,'1'
	call	outtty
	jmp	proclm5
proclm2:
	cmp	dl,1
	jne	proclm3
	mov	al,ESCAPE
	call	outtty
	mov	al,'('
	call	outtty
	jmp	proclm5
proclm3:
	cmp	dl,4
	jne	proclm4
	mov	al,ESCAPE
	call	outtty
	mov	al,'0'
	call	outtty
	jmp	proclm5
proclm4:
	cmp	dl,7
	jne	proclm5
	mov	al,ESCAPE
	call	outtty
	mov	al,'p'
	call	outtty
proclm5:
	cmp	byte ptr [bx],'m'
	je	proclm6
	inc	bx
	jmp	proclm1
proclm6:
	jmp	ignore

procJ:
	cmp	escseq,3
	je	procJ0
	mov	bx,offset escstring+2 ; skip ESCAPE'['
	call	getnum
	cmp	dl,0
	je	procJ0
	cmp	dl,1
	je	procJ1
	cmp	dl,2
	je	procJ2
	jmp	ignore		; ignore others
procJ0:
	mov	al,ESCAPE
	call	outtty
	mov	al,'J'
	jmp	noesc
procJ1:
	mov	al,ESCAPE
	call	outtty
	mov	al,'b'
	jmp	noesc
procJ2:
	mov	al,ESCAPE
	call	outtty
	mov	al,'E'
	jmp	noesc

prochl:
	mov	bx,offset escstring+2 ; skip ESCAPE'['
	call	getnum
	cmp	[escstring+2],'?'
	je	quest
	mov	bx,escpnt
	mov	bl,[bx] 	; contains 'h' or 'l'
	cmp	dl,4
	jne	not4
	mov	al,ESCAPE
	call	outtty
	mov	al,'@'
	cmp	bl,'l'
	jne	enterins
	mov	al,'O'
enterins:
	jmp	noesc
not4:				; ignore the others
	jmp	ignore
quest:				; sequence like ESCAPE'[?'nn'h'
	mov	bx,escpnt
	mov	bl,[bx]
	cmp	dl,1
	jne	not1
	mov	cx,8
	cmp	appkeys,0
	je	q1
	mov	offs,offset apptbl
	mov	di, offset apptbl.extrtabl
	jmp	q2
q1:	mov	offs,offset numtbl
	mov	di, offset numtbl.extrtabl
q2:	add	di,START_EXTRTBL ; don't want to start at the top
	cmp	bl,'l'
	je	q3
	mov	si,offset curapp
	mov	appcur,1
	jmp	q4
q3:	mov	si,offset curseq
	mov	appcur,0
q4:	rep	movsw
	mov	bx,offset parmblock
	mov	byte ptr [bx],2
	mov	ax,18
	int	SUPERBIOS
	jmp	ignore
not1:
	cmp	dl,5
	jne	not5
	mov	al,ESCAPE
	call	outtty
	mov	al,'p'
	cmp	bl,'h'
	je	isreverse
	mov	al,'q'
isreverse:
	jmp	noesc
not5:
	cmp	dl,7
	jne	not7
	mov	al,ESCAPE
	call	outtty
	mov	al,'v'
	cmp	bl,'h'
	je	autowrap
	mov	al,'w'
autowrap:
	jmp	noesc
not7:				; ignore the others
	jmp	ignore

procK:
	cmp	escseq,3
	je	procK0
	mov	bx,offset escstring+2 ; skip ESCAPE'['
	call	getnum
	cmp	dl,0
	je	procK0
	cmp	dl,1
	je	procK1
	cmp	dl,2
	je	procK2
	jmp	ignore		; ignore others
procK0:
	mov	al,ESCAPE
	call	outtty
	mov	al,'K'
	jmp	noesc
procK1:
	mov	al,ESCAPE
	call	outtty
	mov	al,'o'
	jmp	noesc
procK2:
	mov	al,ESCAPE
	call	outtty
	mov	al,'l'
	jmp	noesc

processrp:
processlp:
processlb:
	mov	escseq,-1	; have to eat one char
	jmp	doansi_d	;
noesc:				; That wasn't valid! (or print last char)
	call	outtty		; print it out...
ignore: 			; Here to flag end of escape or ignore
	mov	escseq,0	; one that we don't like
doansi_d:
	ret			; Here when we have no more to do
DOANSI	endp

; GETNUM gets a number from escapestring, returns it in DL.
;   Input: pointer in BX.  Destroys BX, CX, DH. Finishes on first
;   encounteder non-numeric char except '-'.     Assumes correct syntax
;   ('-' only as first char - checked in procmulti)

GETNUM	proc	near
	xor	dx,dx
	cmp	bx,escpnt	; is it to end of string already?
	jge	getn4		; yes - just exit with zero
	xor	ch,ch		; assume positive number
	cmp	byte ptr [bx],'?' ; first char may be a questionmark
	jne	getn1
	inc	bx
getn1:
	mov	cl,[bx]
	cmp	cl,';'
	je	getn3
	cmp	cl,'-'
	jne	getn2
	mov	ch,-1
getn2:
	cmp	cl,'0'
	jl	getn3
	cmp	cl,'9'
	jg	getn3
	sub	cl,'0'
	shl	dl,1		; multiply by 10 (=1010b)
	mov	dh,dl
	shl	dl,1
	shl	dl,1
	add	dl,dh
	add	dl,cl
	inc	bx
	cmp	bx,escpnt
	jl	getn1
getn3:
	cmp	ch,-1
	jne	getn4
	neg	dx
getn4:
	ret
GETNUM	endp

; initialize keyboard and tables to build it [as]

INITANSI proc	near
	cld
	mov	bx,ds
	mov	es,bx
	mov	bx,offset parmblock
	mov	ax,18
	int	SUPERBIOS	; get old keyboard
	or	ax,ax
	jz	ansi01
	jmp	aend
ansi01: mov	cx,598		; copy it
	mov	si,offset oldtable
	mov	di,offset numtbl
	cld
	rep	movsw
	mov	si,offset numtbl ; Index in Table
	mov	byte ptr [si].kd0+25,7fh ; DEL to Backspace-key

; set cursorkeys
	mov	word ptr [si].kd12+2*88,0A000h	;
	mov	word ptr [si].kd12+2*89,0A000h	; with auto-repeat
	mov	word ptr [si].kd12+2*98,0A000h
	mov	word ptr [si].kd12+2*99,0A000h
	mov	byte ptr [si].kd0+88,START_EXTRTBL ; offset in EXTRtabl
	mov	byte ptr [si].kd0+89,START_EXTRTBL+4
	mov	byte ptr [si].kd0+98,START_EXTRTBL+8
	mov	byte ptr [si].kd0+99,START_EXTRTBL+12
	mov	di,offset numtbl.extrtabl
	add	di,START_EXTRTBL ; Don't want to overwrite stuff
	mov	si,offset curseq
	mov	cx,8
	rep	movsw		; move the new sequences to keytable

; copy complete table to build Applikation-keypad-table
	mov	cx,598
	mov	si,offset numtbl
	mov	di,offset apptbl
	rep	movsw

; now build keypad
	mov	si,offset apptbl
	mov	word ptr [si].kd12+2*28,8000h
	mov	word ptr [si].kd12+2*29,8000h
	mov	word ptr [si].kd12+2*30,8000h
	mov	word ptr [si].kd12+2*31,8000h
	mov	word ptr [si].kd12+2*49,8000h
	mov	word ptr [si].kd12+2*50,8000h
	mov	word ptr [si].kd12+2*51,8000h
	mov	word ptr [si].kd12+2*52,8000h
	mov	word ptr [si].kd12+2*69,8000h
	mov	word ptr [si].kd12+2*70,8000h
	mov	word ptr [si].kd12+2*71,8000h
	mov	word ptr [si].kd12+2*72,8000h
	mov	word ptr [si].kd12+2*90,8000h
	mov	word ptr [si].kd12+2*91,8000h
	mov	word ptr [si].kd12+2*92,8000h
	mov	word ptr [si].kd12+2*93,8000h
	mov	word ptr [si].kd12+2*100,8000h
	mov	word ptr [si].kd12+2*101,8000h	; [bgp]
	mov	word ptr [si].kd12+2*102,8000h
	mov	byte ptr [si].kd0+28,START_EXTRTBL+16 ; offset in EXTRtabl
	mov	byte ptr [si].kd0+29,START_EXTRTBL+20
	mov	byte ptr [si].kd0+30,START_EXTRTBL+24
	mov	byte ptr [si].kd0+31,START_EXTRTBL+28
	mov	byte ptr [si].kd0+49,START_EXTRTBL+32
	mov	byte ptr [si].kd0+50,START_EXTRTBL+36
	mov	byte ptr [si].kd0+51,START_EXTRTBL+40
	mov	byte ptr [si].kd0+52,START_EXTRTBL+44
	mov	byte ptr [si].kd0+69,START_EXTRTBL+48
	mov	byte ptr [si].kd0+70,START_EXTRTBL+52
	mov	byte ptr [si].kd0+71,START_EXTRTBL+56
	mov	byte ptr [si].kd0+72,START_EXTRTBL+60
	mov	byte ptr [si].kd0+90,START_EXTRTBL+64
	mov	byte ptr [si].kd0+91,START_EXTRTBL+68
	mov	byte ptr [si].kd0+92,START_EXTRTBL+72
	mov	byte ptr [si].kd0+93,START_EXTRTBL+76
	mov	byte ptr [si].kd0+100,START_EXTRTBL+80
	mov	byte ptr [si].kd0+101,START_EXTRTBL+80
	mov	byte ptr [si].kd0+102,START_EXTRTBL+84
	mov	di,offset apptbl.extrtabl
	add	di,START_EXTRTBL ; avoid overwriting stuff...
	mov	si,offset applik
	mov	cx,44
	cld
	rep	movsw		; move new keycodes to table
	mov	bx,offset parmblock
	mov	byte ptr [bx],2
	mov	offs,offset numtbl ; set numeric keypad
	mov	ax,18
	int	SUPERBIOS
aend:
	ret
INITANSI endp

; Save old keyboard stuff when exiting [as]

FINIANSI proc	near
	mov	bx,offset parmblock
	mov	byte ptr [bx],2
	mov	dx,offset oldtable
	xchg	dx,offs 	; save old keyboard-type in dx
	mov	ax,18
	int	SUPERBIOS
	xchg	dx,offs 	; restore old keyboard-type
	ret
FINIANSI endp

; Get the current cursor location - row in dl, col in dh
; (1,1) is upper left corner

GET_CUR_POS proc near
	mov	al,ESCAPE	; request cursor location
	call	outtty
	mov	al,'n'
	call	outtty
	mov	ah,CONINQ	; input no check
	int	DOS		; gets the ESCAPE
	int	DOS		; gets the Y
	int	DOS
	sub	al,31
	mov	dl,al
	int	DOS
	sub	al,31
	mov	dh,al
	ret
GET_CUR_POS endp

; Set the cursor location - row in dl, col in dh
; (1,1) is upper left corner

SET_CUR_POS proc near
	push	dx		; save it to be sure
	mov	al,ESCAPE
	call	outtty
	mov	al,'Y'
	call	outtty
	pop	dx
	push	dx
	mov	al,dl		; row
	add	al,31
	call	outtty
	pop	dx
	push	dx
	mov	al,dh		; column
	add	al,31
	call	outtty
	pop	dx
	ret
SET_CUR_POS endp

; Save the screen so we can restore it

SAVESCR proc	near
	push	es		; [bgp]
	call	get_cur_pos	; get cursor location
	mov	tcurloc,dl	; this is line number
	mov	tcurloc+1,dh	; this is column number
	mov	bx,SEG_CRTC	; where crt controller is
	mov	es,bx
	mov	bx,OFF_CRTC
	mov	byte ptr es:[bx],12
	mov	ah,es:1[bx]
	and	ah,7		; only want bottom 3 bits
	mov	byte ptr es:[bx],13
	mov	al,es:1[bx]
	shl	ax,1		; multiply by 2 (was word address)
	mov	si,ax
	push	ds
	pop	es
	mov	ds,tscrseg
	mov	di,offset tscreen
	mov	cx,1920
	cld
	rep	movsw
	push	es
	pop	ds
	call	cmblnk		; let them start with a blank one
	pop	es		; [bgp]
	ret			; and return
SAVESCR endp

; Restore screen from scrsav buffer

RESTSCR proc	near
	push	es		; [bgp]
	call	cmblnk		; start with a clear screen
	mov	si,offset tscreen
	mov	es,tscrseg
	xor	di,di		; start at start
	mov	cx,1920 	; 1920 words to go
	rep	movsw
	mov	dx,word ptr tcurloc ; get cursor location
	call	set_cur_pos
	pop	es		; [bgp]
	ret
RESTSCR endp

; Save the mode line so it can be restored when we are through [bgp]

SAVE_MODE proc	near
	push es 		; to be sure
	mov	bx,SEG_CRTC	; where crt controller is
	mov	es,bx
	mov	bx,OFF_CRTC
	mov	byte ptr es:[bx],12 ; high screen origin register
	mov	ah,es:1[bx]
	and	ah,7		; need bottom 3 bits
	mov	byte ptr es:[bx],13 ; low screen origin register
	mov	al,es:1[bx]
	shl	ax,1		; multiply by 2 (was word address)
	add	ax,3840 	; where status line is
	mov	si,ax
	mov	di,offset status_line ; where to put it
	mov	cx,80		; 80 words long
	push	ds
	pop	es
	mov	ds,tscrseg	; setment of screen
	cld
	rep	movsw
	push	es
	pop	ds		; restore ds
	pop	es		; and this too
	ret
SAVE_MODE endp

; Restore mode line in case someone has something on it [bgp]

REST_MODE proc near
	push	es		; to be sure...
	mov	bx,SEG_CRTC	; where crt controller is
	mov	es,bx
	mov	bx,OFF_CRTC
	mov	byte ptr es:[bx],12 ; high screen origin register
	mov	ah,es:1[bx]
	and	ah,7		; need bottom 3 bits
	mov	byte ptr es:[bx],13 ; low screen origin register
	mov	al,es:1[bx]
	shl	ax,1		; multiply by 2 (was word address)
	add	ax,3840 	; where status line is
	mov	di,ax
	mov	si,offset status_line ; where to get it
	mov	cx,80		; 80 words long
	mov	es,tscrseg	; segment of screen
	cld
	rep	movsw
	pop	es		; restore this
	ret
REST_MODE endp

; Save the screen to a buffer and then append buffer to a disk file. [jrd]
; Default filename is Kermit.scn; actual file can be a device too. Filename
; is determined by mssset and is passed as pointer dmpname.
; This reads the screen that was last saved by savescr - it is expected
; that savescr will be called just before this one.
; 7 August 1986 Add this routine - it is pirated from the file MSYIBM and
; modified to match the Victor's needs.  Note that a screen dump is not
; possible in Tektronix mode (unfortunately) since I'm not sure how to dump
; it in a way that would make sense.  [bgp]

DUMPSCR PROC	NEAR
	cmp	flags.vtflg,TTTEK ; emulating Tektronix?
	jne	dumpxx		; no, save screen
	jmp	dumptek 	; this won't do anything but beep
dumpxx:
	push	ax
	push	bx
	push	cx
	push	dx
	mov	dmphand,-1	; preset illegal handle
	mov	dx,offset dmpname ; name of disk file, from mssset
	mov	ax,dx		; where isfile wants name ptr
	call	isfile		; what kind of file is this?
	jc	dmp5		; c = no such file, create it
	test	byte ptr filtst.dta+21,1FH ; file attributes, ok to write?
	jnz	dmp0		; nz=no.
	mov	al,1		; writing
	mov	ah,OPEN2	; open existing file
	int	DOS
	jc	dmp0		; c=failure
	mov	dmphand,ax	; save file handle
	mov	bx,ax		; need handle here
	mov	cx,0FFFFH	; set up file pointer
	mov	dx,-1		; and offset
	mov	al,2		; move to eof minus one byte
	mov	ah,LSEEK	; and seek the end
	int	DOS
	jmp	dmp1

dmp5:	mov	ah,CREAT2	; file did not exist
	mov	cx,20H		; attributes, archive bit
	int	DOS
	mov	dmphand,ax	; save file handle
	jnc	dmp1		; nc=ok

dmp0:	call	clrmod		; clear place for mode line
	mov	dx,offset dmperr ; get string to put there
	call	putmod		; on mode line...
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	ret

dmp1:	push	di		; read screen buffer, write lines
	push	si
	push	es
	push	ds
	pop	es		; make sure this is right
	mov	cx,24		; 24 lines in buffer
	mov	si,offset tscreen ; where screen is saved
dmp2:	push	cx		; save outer loop counter
	mov	di,offset dumpbuf ; data segment memory
	mov	cx,80		; 80 columns
dmp3:	mov	ax,word ptr es:[si] ; read char + attribute
	and	ax,7FFH 	; take off attributes
	sub	ax,char_base	; minus base
	mov	byte ptr [di],al ; store the char
	inc	si
	inc	si
	inc	di
	loop	dmp3		; do for each column
	std			; set scan backward
	mov	cx,80		; 80 columns
	mov	di,offset dumpbuf+79 ; end of line
	mov	al,' '          ; thing to scan over
	repe	scasb		; scan until non-space
	cld			; set direction forward
	jz	dmp3a		; z=all spaces
	inc	cx
	inc	di
dmp3a:	mov	word ptr [di+1],0A0DH ; append cr/lf
	add	cx,2		; line count + cr/lf
	mov	dx,offset dumpbuf ; array to be written
	mov	bx,dmphand	; need file handle
	mov	ah,WRITE2	; write the line
	int	DOS
	pop	cx		; get line counter again
	loop	dmp2		; do next line
	mov	dx,offset dumpsep ; put in ff/cr/lf
	mov	cx,3		; three bytes overall
	mov	ah,WRITE2	; write them
	mov	bx,dmphand	; file handle
	int	DOS
	mov	ah,CLOSE2	; close the file now
	int	DOS
dmp6:	pop	es
	pop	si
	pop	di
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	ret
dumptek:call	beep		; what else should we do?
	ret
DUMPSCR ENDP

; Come to here to act somewhat like a Tektronix 4010 terminal...
TEK4010 proc	near
	push	es			; this will be used repeatedly
	mov	es,scrseg
	mov	cursor_cnt,CURSOR_TIME	; init cursor countdown timer
	cmp	first_in,FALSE		; been here before?
	je	tek0			; yes
	call	clrscr			; be sure screen is clear
	mov	first_in,FALSE		; flag it
tek0:
	call	set_hires		; set to hires screen
teklp:
	cmp	full_flag,FALSE 	; page full condition
	jne	tekcki1 		; yes, I can't accept anything
	call	portchr 		; char at port?
	jc	tekcki			; c = no, keep going
	call	tekhandle		; go handle the character
tekcki:
	dec	cursor_cnt		; decrement cursor countdown
	jnz	tekcki1 		; not ready
	call	cursor_on		; turn on cursor
tekcki1:
	call	keybd			; get and translate a key [bgp]
	jnc	teklp			; carry=esc char entered - quit [bgp]
tekquit:
	call	reset_hires		; reset to normal screen
	pop	es
	ret
TEK4010 endp

; Come to here to temporarily act somewhat like a Tektronix 4010 terminal...
; Added 29 August 1987 to allow ANSI or VT52 to go directly to Tektronix
; mode.  This is entered at a point where conditions should be like a
; clear screen was just received (ESCAPE FF).  We should exit on the receipt
; of an ESCAPE US sequence or if the esc char is entered from the keyboard.
; If the esc char is entered then return with carry set. [bgp]
; For compatibility we will also exit if a CAN (ctrl-X) is received (to be
; like the IBM-PC version).
TEKTEMP proc	near
	push	es			; this will be used repeatedly
	mov	es,scrseg
	mov	ax,flags.vtflg
	mov	temp_mode,ax		; save current emulation
	mov	flags.vtflg,TTTEK	; set to tek emulation
	mov	temp_tek,TRUE		; this is temporary mode...
	mov	echo_supp,FALSE 	; clear echo suppression
	mov	cursor_cnt,CURSOR_TIME	; init cursor countdown timer
	mov	escflag,0		; not in escape sequence
	mov	graph_mode,FALSE	; in full text mode
	call	clrscr			; be sure screen is clear
	mov	first_in,FALSE		; flag it
	call	set_hires		; set to hires screen
tektlp:
	cmp	full_flag,FALSE 	; page full condition
	jne	tektcki1		; yes, I can't accept anything
	call	portchr 		; char at port?
	jc	tektcki 		; c = no, keep going
	and	al,7fh			; Tek gets only 7 bit characters
	call	tekhandle		; go handle the character
tektcki:
	dec	cursor_cnt		; decrement cursor countdown
	jnz	tektcki1		; not ready
	call	cursor_on		; turn on cursor
tektcki1:
	call	keybd			; get and translate a key
	jnc	tektlp			; carry=esc char entered - quit
	call	reset_hires		; reset to normal screen
	mov	ax,temp_mode
	mov	flags.vtflg,ax		; reset to previous emulation
	mov	temp_tek,FALSE		; clear temp tektronix emulation
	pop	es
	stc				; set carry - this is full quit
	ret
TEKTEMP endp

; Take care of an incoming character

TEKHANDLE proc	near
	cmp	escseq,0		; escape sequence in progress?
	jne	tekhand1		; ne = yes, no translation
	cmp	rxtable+256,0		; translation turned off?
	je	tekhand1		; e = yes, no translation
	push	bx
	mov	bx,offset rxtable	; address of translate table
	xlatb				; new char is in al
	pop	bx
tekhand1:call	capture 		; in case we should
	cmp	al,GS			; Group Separator?
	je	tek2graf		; ->graphics with pen up
	cmp	al,ESCAPE		; Escape?
	je	tek2esc 		; ->handle special commands
	mov	bl,escflag
	xor	bh,bh
	call	tekjump[bx]		; Go to right routine
	mov	cursor_cnt,CURSOR_TIME	; init cursor countdown
	ret
tek2graf:
	mov	visible,0		; Pen up
	mov	escflag,4		; Get HIY next
	mov	graph_mode,TRUE
	ret
tek2esc:
	mov	escflag,2		; ESCAPE handler next
	ret
TEKHANDLE endp

; TEXT mode - just put text on screen

TEKTXT	proc	near
	call	cursor_off		; be sure this is off
	cmp	text_x,TEXT_X_MAX	; off screen?
	jle	tektxta
	mov	text_x,0		; to left margin
	add	text_y,RPLINE
tektxta:
	cmp	text_y,TEXT_Y_MAX
	jle	tektxtb
	call	page_full		; page is full!
	ret				; lost that character, oh well...
tektxtb:
	cmp	al,DEL			; Is it delete?
	jne	tektxt1
	ret
tektxt1:
	cmp	al,' '                  ; Is it control?
	jl	tektxt3
	cmp	echo_supp,FALSE 	; In echoplex suppression?
	jne	tektxt2 		; Yes, don't print it
	call	character		; Output it
	call	inc_char
tektxt2:
	ret
tektxt3:
	cmp	al,BELL
	jne	tektxt4
	call	beep
	mov	echo_supp,FALSE 	; Clear suppression
	ret
tektxt4:
	cmp	al,BS
	jne	tektxt6
	sub	text_x,CPCHAR		; back up one
	cmp	text_x,0
	jge	tektxt5 		; ok
	mov	text_x,R_MARG		; right margin
	sub	text_y,RPLINE		; back one line
	cmp	text_y,0		; top?
	jge	tektxt5
	mov	text_y,0		; top of screen
tektxt5:
	mov	echo_supp,FALSE 	; Clear suppression
	ret
tektxt6:
	cmp	al,TAB
	jne	tektxt7
	call	inc_char
	mov	echo_supp,FALSE 	; Clear suppression
	ret
tektxt7:
	cmp	al,LF			; Line feed?
	jne	tektxt9
	add	text_y,RPLINE		; Down one line
	cmp	text_y,TEXT_Y_MAX	; Past end?
	jle	tektxt8
	call	page_full		; can't go any further!
	ret
tektxt8:
	mov	echo_supp,FALSE 	; Clear suppression
	ret
tektxt9:
	cmp	al,VTAB
	jne	tektxt11
	sub	text_y,RPLINE		; Up one line
	cmp	text_y,0		; Past top?
	jge	tektxt10
	mov	text_y,0
tektxt10:
	mov	echo_supp,FALSE 	; Clear suppression
	ret
tektxt11:
	cmp	al,CR			; It is return?
	jne	tektxt12
	mov	text_x,0		; to left margin
	mov	echo_supp,FALSE 	; Clear suppression
	ret
tektxt12:
	cmp	al,CAN			; Is it CAN (control-X)?
	jne	tektxt13
	cmp	temp_tek,FALSE		; in temporary mode?
	je	tektxt13		; no, just continue!
	mov	echo_supp,FALSE 	; clear suppression
	mov	escflag,0		; place in full text mode
	mov	graph_mode,FALSE
	mov	ax,temp_mode
	mov	flags.vtflg,ax		; reset emulation mode
	mov	temp_tek,FALSE		; clear temporary mode
	pop	ax			; this is return to tekhandle
	pop	ax			; this is return to tektemp
	call	reset_hires		; have to make it look like a tektquit
	pop	es			; with a carry clear state
	clc
	ret
tektxt13:
	ret
TEKTXT	endp

; Move the text position by one char, perform auto wrap, and
; check for page full

INC_CHAR proc	near
	add	text_x,CPCHAR		; Move to next column
	cmp	text_x,TEXT_X_MAX	; Past end?
	jle	inc_char0
	mov	text_x,0		; Left margin
	add	text_y,RPLINE
	cmp	text_y,TEXT_Y_MAX	; Past end?
	jle	inc_char0
	call	page_full		; Take no more!
inc_char0:
	ret
INC_CHAR endp

; ESCAPE mode - check what to do

TEKESC	proc	near
	cmp	al,FF			; Form feed?
	jne	tekesc1
	call	clrscr
	mov	echo_supp,FALSE 	; Clear suppression
	jmp	tekescq
tekesc1:
	cmp	al,CTLZ 		; Control-Z?
	jne	tekesc2
	mov	escflag,0		; Just in case
	mov	echo_supp,TRUE		; echoplex suppression
	call	tekcrs			; Go to cross hairs
	ret				; Last char does its thing
tekesc2:
	cmp	al,ETB			; Make copy?
	jne	tekesc2a
	mov	echo_supp,FALSE 	; Clear suppression
	jmp	tekescq
tekesc2a:
	cmp	al,ENQ			; enquire?
	jne	tekesc3
	mov	echo_supp,TRUE		; echoplex suppression
	call	send_stat
	jmp	tekescq 		; do nothing for now ***
tekesc3:
	cmp	al,US			; return from temp tek mode [bgp]
	jne	tekesc4
	cmp	temp_tek,FALSE		; in temporary mode?
	je	tekescq 		; no, just continue!
	mov	echo_supp,FALSE 	; clear suppression
	mov	escflag,0		; place in full text mode
	mov	graph_mode,FALSE
	mov	ax,temp_mode
	mov	flags.vtflg,ax		; reset emulation mode
	mov	temp_tek,FALSE		; clear temporary mode
	pop	ax			; this is return to tekhandle
	pop	ax			; this is return to tektemp
	call	reset_hires		; have to make it look like a tektquit
	pop	es			; with a carry clear state
	clc
	ret
tekesc4:
	call	tektxt			; It's just text...
tekescq:
	mov	escflag,0		; Now in full text mode
	mov	graph_mode,FALSE
	ret
TEKESC	endp

; Get coordinates   escflag=4->expect hiy, escflag=6->expect hix

TEKHIY	proc	near
tekhix:
	call	cursor_off		; make sure it is off
	cmp	al,CR			; should we exit?
	jne	tekhi1
	mov	cur_x,0 		; go to left margin
	mov	echo_supp,FALSE 	; Clear suppression
	jmp	go2text
tekhi1:
	cmp	al,US			; another exit?
	jne	tekhi2
	mov	echo_supp,FALSE 	; Clear suppression
	jmp	go2text
tekhi2:
	cmp	al,FF
	jne	tekhi3
	call	clrscr
	mov	echo_supp,FALSE 	; Clear suppression
	jmp	go2text
tekhi3:
	cmp	echo_supp,FALSE 	; In suppression
	jne	tekhi4			; Yes, ignore this...
	cmp	al,20H			; control character?
	jl	tekhi4
	cmp	al,40H
	jl	tekhi5			; 20-3F are HIX or HIY
	cmp	al,60H
	jl	tekhi7			; 40-5F are LOX
;   Get to here must be 60-7F -> LOY
	mov	ah,loy			; copy old loy
	mov	lsb,ah			; to lsb (in case 4014)
	and	al,1FH			; low 5 bits
	mov	loy,al
	cmp	escflag,6		; 2nd in a row?
	je	tekhi4			; then previous was lsb anyway
	mov	lsb,0			; clear lsb
	mov	escflag,6		; expect HIX next
tekhi4:
	ret
; Get either HIX or HIY depending on escflag
tekhi5:
	and	ax,1FH
	mov	cl,5
	shl	ax,cl			; multiply by 32
	cmp	escflag,4		; looking for HIY?
	jne	tekhi6			; no, HIX
	mov	hiy,ax
	ret				; leave escflag=4
tekhi6:
	mov	hix,ax
	mov	escflag,4		; look for HIY next
	ret
; Get LOX and do the movement
tekhi7:
	and	al,1FH
	mov	lox,al
	mov	ax,hix
	or	al,lox
	mov	cur_x,ax
	mov	dx,hiy
	or	dl,loy
	mov	cur_y,dx
	call	tek2victor		; convert the coords
	mov	endpt,ax
	mov	endpt+2,dx		; save them
	cmp	visible,0
	je	tekhi8
	call	line			; draw the line
tekhi8:
	mov	visible,1
	mov	ax,endpt
	mov	start,ax
	mov	ax,endpt+2
	mov	start+2,ax		; end is now start
	mov	escflag,4		; want HIY next
	ret
;
go2text:
	mov	escflag,0
	mov	graph_mode,FALSE
	mov	ax,cur_x
	mov	dx,cur_y
	call	tek2victor
	mov	text_x,ax
	sub	dx,10			; mov to upper left corner
	cmp	dx,0
	jge	go2text1
	xor	dx,dx
go2text1:
	mov	text_y,dx
	ret
TEKHIY	endp

; Go to CURSOR mode

TEKCRS	proc	near
	call	cursor_off
	mov	combine,offset pixel_xor
	mov	trmesc,FALSE
	mov	prtesc,FALSE
tekcrs_dr:
	mov	ax,cur_x		; get x
	sub	ax,CUR_LEN		; minus a little
	cmp	ax,0
	jge	tekcrs_dr1
	mov	ax,0
tekcrs_dr1:
	mov	dx,cur_y
	call	tek2victor
	mov	crs_hor,ax
	mov	crs_hor+4,dx
	mov	ax,cur_x
	add	ax,CUR_LEN		; add a little
	cmp	ax,TEK_X_MAX
	jle	tekcrs_dr2
	mov	ax,TEK_X_MAX
tekcrs_dr2:
	mov	dx,cur_y
	call	tek2victor
	mov	crs_hor+2,ax
	mov	dx,cur_y		; now y's
	sub	dx,CUR_LEN		; minus a little
	cmp	dx,0
	jge	tekcrs_dr3
	mov	dx,0
tekcrs_dr3:
	mov	ax,cur_x
	call	tek2victor
	mov	crs_ver,dx
	mov	crs_ver+4,ax
	mov	dx,cur_y
	add	dx,CUR_LEN		; plus a little
	cmp	dx,TEK_Y_MAX
	jle	tekcrs_dr4
	mov	dx,TEK_Y_MAX
tekcrs_dr4:
	mov	ax,cur_x
	call	tek2victor
	mov	crs_ver+2,dx
	call	draw_cursor		; put it on
tekcrs_lp:
	mov	dl,0FFH
	mov	ah,DCONIO		; get character
	int	DOS
	cmp	al,0			; anything?
	jne	tekcrs_hnd		; take care of it
	call	portchr 		; check port character
	jc	tekcrs_lp		; c = nothing there
	cmp	prtesc,FALSE		; received escape?
	je	tekcrs_lp1		; no
	mov	prtesc,FALSE
	cmp	al,FF
	je	tekcrs_abt
	cmp	al,ETB
	je	tekcrs_abt
	cmp	al,ENQ
	jne	tekcrs_lp
	call	send_stat		; send status
	jmp	tekcrs_lp
tekcrs_lp1:
	cmp	al,BELL 		; check for control and clear...
	je	tekcrs_abt
	cmp	al,BS
	je	tekcrs_abt
	cmp	al,CR
	je	tekcrs_abt
	cmp	al,TAB
	je	tekcrs_abt
	cmp	al,LF
	je	tekcrs_abt
	cmp	al,US
	je	tekcrs_abt
	cmp	al,ESCAPE
	jne	tekcrs_lp		; try for more
	mov	prtesc,TRUE
	jmp	tekcrs_lp
tekcrs_abt:
	mov	echo_supp,FALSE 	; clear echo suppression
	mov	escflag,0		; and text mode
	jmp	tekcrs_xt		; and leave
;
tekcrs_hnd:
	cmp	trmesc,FALSE		; received escapes yet?
	jne	tekcrs_hnd2
	cmp	al,ESCAPE		; escape character?
	je	tekcrs_hnd1
	jmp	tekcrs_done		; finished
tekcrs_hnd1:
	mov	trmesc,TRUE		; flag it
	jmp	tekcrs_lp
tekcrs_hnd2:
	cmp	al,'1'                  ; change step?
	jge	tekcrs_hnd2z
	jmp	tekcrs_done
tekcrs_hnd2z:
	cmp	al,'9'
	jle	tekcrs_hnd3
	cmp	al,'A'
	jne	tekcrs_hnd2a
	mov	ax,cur_stp
	add	cur_y,ax
	jmp	tekcrs_und		; remove old and redraw
tekcrs_hnd2a:
	cmp	al,'B'
	jne	tekcrs_hnd2b
	mov	ax,cur_stp
	sub	cur_y,ax
	jmp	tekcrs_und		; remove old and redraw
tekcrs_hnd2b:
	cmp	al,'C'
	jne	tekcrs_hnd2c
	mov	ax,cur_stp
	add	cur_x,ax
	jmp	tekcrs_und
tekcrs_hnd2c:
	cmp	al,'D'
	jne	tekcrs_hnd2d
	mov	ax,cur_stp
	sub	cur_x,ax
	jmp	tekcrs_und
tekcrs_hnd2d:
	jmp	tekcrs_done		; its the one to send
tekcrs_hnd3:
	sub	al,'0'                  ; convert to number
	xor	ah,ah
	mov	cur_stp,ax		; new step value
	mov	trmesc,FALSE
	jmp	tekcrs_lp
tekcrs_und:
	cmp	cur_x,0 		; check for validity
	jge	tekcrs_und1
	mov	cur_x,0
	jmp	tekcrs_und2
tekcrs_und1:
	cmp	cur_x,TEK_X_MAX
	jle	tekcrs_und2
	mov	cur_x,TEK_X_MAX
tekcrs_und2:
	cmp	cur_y,0
	jge	tekcrs_und3
	mov	cur_y,0
	jmp	tekcrs_und4
tekcrs_und3:
	cmp	cur_y,TEK_Y_MAX
	jle	tekcrs_und4
	mov	cur_y,TEK_Y_MAX
tekcrs_und4:
	call	draw_cursor		; remove the cursor
	mov	trmesc,FALSE
	jmp	tekcrs_dr		; and draw new one
tekcrs_done:
	push	cur_y			; want current coords
	push	cur_x			; for sending
	call	send_coord		; send character and coords
tekcrs_xt:
	call	draw_cursor		; remove the cursor
	mov	ax,cur_x
	mov	dx,cur_y		; need to set start point
	call	tek2victor
	mov	start,ax
	mov	start+2,dx
	mov	text_x,ax		; set text point also
	sub	dx,10			; move to upper left corner
	cmp	dx,0
	jge	tekcrs_xt1
	xor	dx,dx
tekcrs_xt1:
	mov	text_y,dx
	mov	combine,offset pixel_or
	ret
TEKCRS	endp

; DRAW CURSOR expects to have the appropriate endpoints in CRS_HOR for
; the horizontal line (x1,x2,y) and CRS_VER for the vertical line (y1,y2,x)

DRAW_CURSOR proc near
	mov	ax,crs_hor
	mov	start,ax
	mov	ax,crs_hor+4
	mov	start+2,ax
	mov	endpt+2,ax
	mov	ax,crs_hor+2
	mov	endpt,ax
	call	line			; draw horizontal line
	mov	ax,crs_ver
	mov	start+2,ax
	mov	ax,crs_ver+4
	mov	start,ax
	mov	endpt,ax
	mov	ax,crs_ver+2
	mov	endpt+2,ax
	call	line			; draw vertical line
	ret
DRAW_CURSOR endp

; Convert TEK coords to VICTOR coords
;   entry:   ax=x, dx=y (tek)
;   exit:   ax=x, dx=y (victor)

TEK2VICTOR proc near
	push	dx			; save y for now
	mov	bx,X_MAX
	mul	bx
	mov	bx,TEK_X_MAX
	div	bx
	cmp	dx,TEK_X_MAX/2		; need to round up?
	jl	tek2vic1
	inc	ax
tek2vic1:
	pop	dx
	push	ax			; save x now
	mov	ax,dx
	mov	bx,Y_MAX
	mul	bx
	mov	bx,TEK_Y_MAX
	div	bx
	cmp	dx,TEK_Y_MAX/2		; need to round up?
	jl	tek2vic2
	inc	ax
tek2vic2:
	sub	ax,Y_MAX		; need to swap it
	neg	ax
	mov	dx,ax
	pop	ax
	ret
TEK2VICTOR endp

; Set the CRT to hires mode

SET_HIRES proc	near
	push	es
	call	crt_lo_inten		; so you don't see so much jump
	mov	ah,DCONIO
	mov	dl,27
	int	DOS
	mov	dl,'E'
	int	DOS			; let's start with a clear screen
	mov	bx,0E800H		; CRT controller segment
	mov	es,bx
; fix the write to work on the VICKI - it has an 8086 [bgp and as]
	mov	byte ptr es:0,0 	; reg 0
	mov	byte ptr es:1,3AH
	mov	byte ptr es:0,1
	mov	byte ptr es:1,32H
	mov	byte ptr es:0,2
	mov	byte ptr es:1,34H
	mov	byte ptr es:0,3
	mov	byte ptr es:1,0C9H
	mov	byte ptr es:0,0AH	; no cursor
	mov	byte ptr es:1,20H
; end VICKI fix
	xor	ah,ah			; assume using lower bank of memory
	test	scrseg,1000H		; really?
	jz	set_hires1
	mov	ah,10H
set_hires1:
	or	ah,20H
; VICKI fix again...
	mov	byte ptr es:0,0CH	; reg 12
	mov	byte ptr es:1,ah
	mov	byte ptr es:0,0DH
	mov	byte ptr es:1,0
	mov	byte ptr es:0,0EH
	mov	byte ptr es:1,0
	mov	byte ptr es:0,0FH
	mov	byte ptr es:1,0
; end VICKI fix
	mov	cx,4e2H 		; 1250 locations to set
	mov	ax,scrseg		; where screen is
	shr	ax,1			; /2
	mov	di,0F000H		; in screen ram
	mov	es,di
	xor	di,di
set_hires2:
	stosw				; set one
	inc	ax			; next one
	loop	set_hires2
	call	crt_hi_inten
	pop	es
	ret
SET_HIRES endp

; Reset the CRT to lo res mode

RESET_HIRES proc near
	push	es
	call	crt_lo_inten		; to minimize jump
	mov	bx,0E800H		; segment for CRT controller
	mov	es,bx
; VICKI fix
	mov	byte ptr es:0,0 	; reg 0
	mov	byte ptr es:1,5CH
	mov	byte ptr es:0,1
	mov	byte ptr es:1,50H
	mov	byte ptr es:0,2
	mov	byte ptr es:1,51H
	mov	byte ptr es:0,3
	mov	byte ptr es:1,0CFH
	mov	byte ptr es:0,0AH
	mov	byte ptr es:1,0 	; steady block cursor
	mov	byte ptr es:0,0CH
	mov	byte ptr es:1,0
	mov	byte ptr es:0,0DH
	mov	byte ptr es:1,0
	mov	byte ptr es:0,0EH
	mov	byte ptr es:1,0
	mov	byte ptr es:0,0FH
	mov	byte ptr es:1,0
; end VICKI fix
	mov	ah,DCONIO
	mov	dl,27
	int	DOS
	mov	dl,'E'
	int	DOS			; insure screen is clear
	call	crt_hi_inten
	pop	es
	ret
RESET_HIRES endp

; Set to lo intensity

CRT_LO_INTEN proc near
	mov	bx,0E804H		; CRT controller segment
	mov	es,bx
	mov	al,es:0 		; get current setting
	mov	ah,al			; save it
	and	al,1CH
	mov	intens,al		; store it
	mov	al,ah
	and	al,0E3H 		; zero intensity
	mov	es:0,al
	ret
CRT_LO_INTEN endp

; Set to hi intensity

CRT_HI_INTEN proc near
	mov	bx,0E804H		; Crt controller segment
	mov	es,bx
	mov	al,es:0 		; Get current setting
	and	al,0E3H 		; Clear intensity
	or	al,intens		; Set to correct value
	mov	es:0,al
	ret
CRT_HI_INTEN endp

; Clear the hires screen area

CLRSCR	proc	near
	les	di,dword ptr scrloc	; get right location
	cld				; increment
	mov	cx,20000		; 40000 bytes
	mov	ax,0
	rep	stosw			; doing it
	jmp	clrscr1
homescr:				; keyboard translator verb entry [bgp]
	call	cursor_off		; make sure it is off
	cmp	full_flag,TRUE		; in page full condition?
	jne	clrscr1 		; no, just go home the cursor
	les	di,dword ptr scrloc	; get screen location
	add	di,38424		; get to lower left corner
	mov	ax,0FFFFH		; want to clear them all
	xor	es:[di],ax		; need to clear page full indicator
	inc	di			; box in the lower left corner which
	inc	di			; was put there when the page filled
	xor	es:[di],ax		; up earlier
	inc	di
	inc	di
	xor	es:[di],ax
	inc	di
	inc	di
	xor	es:[di],ax
clrscr1:
	mov	cur_x,0 		; set to home position
	mov	cur_y,780
	mov	hix,0
	mov	hiy,0
	mov	lox,0
	mov	loy,0
	mov	lsb,0
	mov	start,0
	mov	start+2,0
	mov	text_x,0
	mov	text_y,0
	mov	full_flag,FALSE 	; page isn't full
	mov	cursor,FALSE		; cursor isn't on
	mov	cursor_cnt,CURSOR_TIME	; set up cursor countdown
	ret
CLRSCR	endp

; Put the character in al on the screen at location pointed at by
; text_x,text_y.  Use combination routine pointed at by t_combine

CHARACTER proc	near
	cmp	al,' '                  ; is it a space?
	jne	character1		; no
	ret				; just return...
character1:
	and	al,07FH 		; Be sure it is in range...
	cmp	al,07FH 		; Is it delete?
	jl	character1a
	ret				; Don't do it...
character1a:
	push	ax			; save the character
	mov	ax,text_y
	mov	dx,text_x
	call	convert_loc		; get to where we are going
	les	di,dword ptr scrloc	; get screen location
	add	si,di			; now we are in the right place
	mov	cx,text_y
	and	cx,0FH			; need mod(y,16)
	sub	cx,16
	neg	cx			; how many to do in this section
	cmp	cx,RPLINE		; more than one line?
	jle	character1b
	mov	cx,RPLINE		; make it just one line
character1b:
	mov	temp,cx 		; need to remember this
	pop	ax			; get back the character
	sub	ax,'!'                  ; start with exclamation mark
	xor	ah,ah
	mov	dl,RPLINE		; number of entries per character
	shl	dl,1			; they are word entries
	mul	dl
	mov	di,ax			; where to get bit patterns
	mov	dx,cx			; how many to do
	mov	cx,bx			; this is the number to shift
	or	cx,cx			; look at it
	jnz	character1c
	jmp	character8		; no shifts necessary
character1c:
	cmp	cx,5			; this goes within one word
	jg	character4		; spans word boundaries
character2:
	mov	bx,font[di]
	or	bx,bx			; is it zero?
	jz	character3
	cmp	si,0			; too low? (start at 0 offset) [jrd]
	jb	character3
	cmp	si,39999		; too high? [jrd]
	jae	character3
	shl	bx,cl			; shift to right place
	call	t_combine
character3:
	inc	di
	inc	di
	inc	si
	inc	si
	dec	dx			; done one row
	jnz	character2
	add	si,1568 		; go to top of next major row
	mov	dx,RPLINE		; how many we needed to do
	sub	dx,temp 		; minus how many done
	mov	temp,RPLINE		; claim we have done them all
	jg	character2		; do the rest
	jmp	character10
character4:
	sub	cx,16			; convert to right shift
	neg	cx
	mov	ax,0FFFFH		; need to build mask
	shl	ax,cl
	not	ax
	mov	c_mask,ax
character5:
	mov	bx,font[di]
	or	bx,bx			; zero?
	jz	character5a
	cmp	si,0			; too low? (starts at 0 offset) [jrd]
	jb	character5a
	cmp	si,39999		; too high? [jrd]
	jae	character5a
	jmp	character6
character5a:
	inc	si
	inc	si
	jmp	character7
character6:
	and	bx,c_mask		; mask upper bits
	ror	bx,cl			; get first batch
	call	t_combine
	add	si,32			; next word column
	mov	bx,font[di]
	shr	bx,cl
	call	t_combine
	sub	si,30			; back to right column, plus 2
character7:
	inc	di
	inc	di
	dec	dx			; done one row
	jnz	character5
	add	si,1568 		; go to top of next major row
	mov	dx,RPLINE		; how many we needed to do
	sub	dx,temp 		; minus how many done
	mov	temp,RPLINE		; claim we have done them all
	jg	character5		; do the rest
	jmp	character10
character8:
	mov	bx,font[di]
	or	bx,bx			; is it zero?
	jz	character9
	cmp	si,0			; too low? (starts at 0 offset) [jrd]
	jb	character9
	cmp	si,39999		; too high? [jrd]
	jae	character9
	call	t_combine
character9:
	inc	di
	inc	di
	inc	si
	inc	si
	dec	dx			; done one row
	jnz	character8
	add	si,1568 		; go to top of next major row
	mov	dx,RPLINE		; how many we needed to do
	sub	dx,temp 		; minus how many done
	mov	temp,RPLINE		; claim we have done them all
	jg	character8		; do the rest
	jmp	character10
character10:
	ret
CHARACTER endp

; Cursor on - turn on the cursor if it isn't already on

CURSOR_ON proc	near
	cmp	cursor,FALSE
	jne	c_on_end		; already on
	push	ax			; save this just in case
	mov	t_combine,offset word_xor ; set combine rule
	mov	ax,CURSOR_CHR
	call	character		; print without advancing
	mov	t_combine,offset word_or ; set combine rule
	mov	cursor,TRUE		; flag it
	pop	ax
c_on_end:
	ret
CURSOR_ON endp

; Cursor off - erase the cursor if it is there

CURSOR_OFF proc near
	cmp	cursor,FALSE
	je	c_off_end		; already off
	push	ax
	mov	t_combine,offset word_xor ; set combine rule
	mov	ax,CURSOR_CHR
	call	character		; print without advancing
	mov	t_combine,offset word_or ; set combine rule
	mov	cursor,FALSE		; flag it
	pop	ax
c_off_end:
	ret
CURSOR_OFF endp

; Notify the user that the page is full, and set flag to wait for
; him to clear it.

PAGE_FULL proc	near
	mov	full_flag,TRUE		; page is full!
	call	beep			; make some noise about it
	les	di,dword ptr scrloc	; get screen location
	add	di,38424		; lower left corner
	mov	ax,0FFFFH		; set them all!
	xor	es:[di],ax
	inc	di
	inc	di
	xor	es:[di],ax
	inc	di
	inc	di
	xor	es:[di],ax
	inc	di
	inc	di
	xor	es:[di],ax
	ret
PAGE_FULL endp

; Connect points: start=startx, start+2=starty, endpt=endx, endpt+2=endy
;   Uses combination routine pointed at by combine

LINE	proc	near
	mov	dx,start		; start x
	mov	ax,endpt		; end x
	mov	x_inc,1 		; assume incrementing
	sub	ax,dx
	jnb	line1			; correct
	neg	x_inc
	neg	ax
line1:
	mov	delta_x,ax		; save delta
	mov	dx,start+2		; start y
	mov	ax,endpt+2		; end y
	mov	y_inc,1 		; assume incrementing
	sub	ax,dx
	jnb	line2			; correct
	neg	y_inc
	neg	ax
line2:
	mov	delta_y,ax		; save delta
	les	di,dword ptr scrloc	; point at bit map region
	mov	dx,start
	mov	ax,start+2
	call	set_pixel		; set start point
	mov	ax,delta_y
	cmp	ax,delta_x		; which should we step on
	ja	line_y
;
line_x:
	mov	cx,delta_x		; number of steps
	jcxz	line_x_done		; nothing to do
	mov	ax,cx
	shr	ax,1			; delta_x/2
	mov	part_accum,ax
line_x_loop:
	mov	ax,x_inc
	add	start,ax
	mov	ax,delta_y
	sub	part_accum,ax
	jge	line_x_ok
	mov	ax,y_inc
	add	start+2,ax
	mov	ax,delta_x
	add	part_accum,ax
line_x_ok:
	mov	dx,start
	mov	ax,start+2
	call	set_pixel
	loop	line_x_loop
line_x_done:
	ret
;
line_y:
	mov	cx,delta_y		; number of steps
	jcxz	line_y_done		; nothing to do
	mov	ax,cx
	shr	ax,1			; delta_y/2
	mov	part_accum,ax
line_y_loop:
	mov	ax,y_inc
	add	start+2,ax
	mov	ax,delta_x
	sub	part_accum,ax
	jge	line_y_ok
	mov	ax,x_inc
	add	start,ax
	mov	ax,delta_y
	add	part_accum,ax
line_y_ok:
	mov	dx,start
	mov	ax,start+2
	call	set_pixel
	loop	line_y_loop
line_y_done:
	ret
LINE	endp

; Set pixel at location dx,ax

SET_PIXEL proc	near
	cmp	dx,X_MAX
	ja	set_range
	cmp	ax,Y_MAX
	ja	set_range
	call	convert_loc
	cmp	bx,8			; top byte?
	jb	set_noinc		; no
	inc	si
	sub	bx,8
set_noinc:
	add	si,di			; correct offset to segment
	mov	bl,bit_mask[bx]
	call	combine
	ret
set_range:
	pop	bx			; pop one return address
	ret				; do nothing if off the screen
SET_PIXEL endp

; Convert x and y to word location and word bit number
;   entry: dx=x, ax=y, exit: si=byte number, bx=bit number

CONVERT_LOC proc near
	mov	si,ax
	and	si,0FH			; mod(y,16)
	mov	bx,ax
	and	bx,0FFF0H		; 16*int(y/16)
	shl	bx,1			; *2 (need 50 times)
	add	si,bx			; that's 2
	shl	bx,1			; *4
	shl	bx,1			; *8
	shl	bx,1			; *16
	add	si,bx			; that's 18
	shl	bx,1			; *32
	add	si,bx			; that's 50
	mov	bx,dx
	and	bx,0FFF0H		; 16*int(x/16)
	add	si,bx
	shl	si,1			; byte address
	mov	bx,dx
	and	bx,0FH			; mod(x,16)
	ret
CONVERT_LOC endp

; Or the mask in bl into byte at es:[si]

PIXEL_OR proc	near
	or	es:[si],bl
	ret
PIXEL_OR endp

; Exclusive-or mask in bl into byte at es:[si]

PIXEL_XOR proc	near
	xor	es:[si],bl
	ret
PIXEL_XOR endp

; Or the word in bx into word at es:[si]

WORD_OR proc	near
	or	es:[si],bx
	ret
WORD_OR endp

; Exclusive-or the word in bx into word at es:[si]

WORD_XOR proc	near
	xor	es:[si],bx
	ret
WORD_XOR endp

; Send the status out the back

SEND_STAT proc	near
	cmp	graph_mode,FALSE	; in graph mode?
	je	send_stat1		; No
	push	cur_y			; push current point, y first
	push	cur_x			; then x
	mov	al,39H			; bit 7=0, bit 6=1, bit 5=1 (no hcopy)
					; bit 4=1 (ready for vector)
					; bit 3=0 (graph mode)
					; bit 2=0 (margin 0), bit 1=1
	call	send_coord		; send it out
	ret
;
send_stat1:
	mov	ax,text_y		; get current point
	add	ax,10			; move to lower left corner
	sub	ax,Y_MAX		; need to swap it
	neg	ax
	mov	bx,TEK_Y_MAX		; convert to tek coords
	mul	bx
	mov	bx,Y_MAX
	div	bx
	cmp	dx,Y_MAX/2		; need to round up?
	jl	send_stat2
	inc	ax
send_stat2:
	cmp	ax,TEK_Y_MAX		; up too far?
	jbe	send_stat3		; okay
	mov	ax,TEK_Y_MAX
send_stat3:
	push	ax			; save y
	mov	ax,text_x
	mov	bx,TEK_X_MAX		; convert to tek coords
	mul	bx
	mov	bx,X_MAX
	div	bx
	cmp	dx,X_MAX/2		; need to round up?
	jl	send_stat4
	inc	ax
send_stat4:
	cmp	ax,TEK_X_MAX		; up too far?
	jbe	send_stat5		; okay
	mov	ax,TEK_X_MAX
send_stat5:
	push	ax			; save x
	mov	al,3DH			; bit 7=0, bit 6=1, bit 5=1 (no hcopy)
					; bit 4=1 (ready for vector)
					; bit 3=1 (not graph mode)
					; bit 2=0 (margin 0), bit 1=1
	call	send_coord		; send it out
	ret
SEND_STAT endp

; Send the byte currently in the al register out the port, then follow
; it by the coordinates - x is the first on the stack, y is the second
; on the stack (i.e., x was pushed last, and popped first)

SEND_COORD proc near
	call	outprt			; send byte in al
	pop	cx			; this is the return address
	pop	ax			; this is x coord
	pop	bx			; this is y coord
	push	cx			; return back on
	push	bx			; y back on
	push	ax			; x back on
	mov	cl,5			; shift to hix
	shr	ax,cl
	and	al,31			; keep 5 bits
	or	al,32			; this is hix now
	call	outprt
	pop	ax			; x again
	and	al,31
	or	al,64			; this is lox now
	call	outprt
	pop	ax			; get y coordinate
	push	ax			; save it again for a flash
	mov	cl,5			; shift to hiy
	shr	ax,cl
	and	al,31			; keep 5 bits
	or	al,32			; this is hiy now
	call	outprt
	pop	ax			; y again
	and	al,31
	or	al,96			; this is loy now
	call	outprt
;   Now for the termination string - use CR,EOT - this is the default for
;   the 4051 microcomputer which is supposed to look like a 4012 - I hope
;   they know what they are doing...
	mov	al,13
	call	outprt
	mov	al,4
	call	outprt
	ret
SEND_COORD endp

OUTPRT	proc	near
	test	yflags,lclecho	; echoing?
	jz	outpr1		; z = no, forget it
	cmp	flags.vtflg,TTTEK ; doing TEKTRONIX?
	je	outpr00 	; e = yes, echo it nicely
	cmp	flags.vtflg,TTVT100 ; doing VT100?
	je	outpr0		; e = yes, echo it nicely
	push	ax		; save char
	call	outtty		; print it
	pop	ax		; restore
	jmp	outpr1
outpr00:cmp	full_flag,FALSE 	; page full?
	jne	outpr1			; forget this
	push	ax
	call	tekhandle		; do the job in a smart way
	pop	ax
	jmp	outpr1
outpr0:	push	ax			; save char
	call	doansi
	pop	ax			; restore
outpr1:	mov	ah,al			; this is where outchr expects it
	call	outchr			; output to the port
	jc	outpr4			; c = failure
	ret
outpr4:	jmp	endcon			; failure, end connection
OUTPRT	endp

; Get a character from the serial port in al
; returns with carry clear if a character is available

PORTCHR proc	near
	call	prtchr		; character at port?
	jnc	portc1		; nc = yes
portc0: ret
portc1:	and	al,parmsk	; apply 8/7 bit parity mask
	or	al,al		; is it a null char?
	jz	portc0		; z = yes, ignore it
portc2: clc			; have a character
	ret			; and return
PORTCHR endp

; Put the character in al to the screen
; Directly call the console-driver to get better speed (4 times, ~19200
; baud)  [as]

OUTTTY	proc	near
	call	capture
	push	ax		; these are modified by the driver
	push	bx
	push	cx
	push	dx
	push	si
	push	es
	mov	cl,al
	mov	ax,1
	call	dword ptr drivadr
	pop	es
	pop	si
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	ret			; through
OUTTTY	endp

; Capture char in al to a file if we are supposed to
; Translation taken from msyibm with minimal modification

CAPTURE proc	near
	test	yflags,CAPT	; capturing output?
	jz	nocap		; no forget this part
	push	ax		; save it
	call	captrtn
	pop	ax		; get char back
nocap:	test	flags1,PRTSCR	; should we be printing?
	jz	noprt		; no, go on
	call	pntchr		; printer routine
	jnc	noprt		; nc = successful print
	push	ax
	call	beep		; else make a noise and
	call	trnprs		;  turn off printing
	pop	ax
noprt:	ret
CAPTURE endp

; Set heath emulation on/off.
; Added VT100 emulation switch and TEKTRONIX switch - notifies of
; idiosyncracies if TEKTRONIX selected (also checks for allowability)
; [bgp].  With the addition of the official TEKTRONIX terminal type
; we no longer have to warn about weird results.

VTS	proc	near
	mov	dx,offset termtb
	mov	bx,offset termhlp
	mov	ah,CMKEY
	call	comnd
	jc	vtx		; c = failure
	push	bx
	mov	ah,cmeol
	call	comnd		; Get a confirm
	pop	bx
	jc	vtx
	cmp	bx,TTTEK	; doing TEKTRONIX?
	jne	vt1		; no
	cmp	tek_allowed,FALSE ; can we do TEKTRONIX?
	jne	vt1		; yes
	mov	dx,offset no_tek_msg ; tell him we can't
	mov	ah,PRSTR
	int	DOS
	ret			; don't do anything
vt1:	mov	flags.vtflg,bx	; Set the emulation flag.
vtx:	ret
VTS	endp

VTSTAT	PROC	NEAR		; For Status display [jrd]
	ret			; no emulator status to display
VTSTAT	ENDP

; Control text cursor. AL = 0 for off, 1 for on (nominally underline)
csrtype proc	far
	push	dx
	mov	escstring,ESCAPE
	mov	escstring+1,'y'
	mov	escstring+2,'5'
	mov	escstring+3,'$'
	or	al,al		; set mode?
	jnz	csrty1		; nz = yes
	dec	escstring+1	; 'x' is reset mode ESC x 5
csrty1:	mov	dx,offset escstring ; pass string to screen console
	mov	ah,PRSTR
	int	DOS
	pop	dx
	ret
csrtype endp

; The following are keyboard translator access routines added 29 August 1987.
; They are invoked by a jump instruction.  They must return carry clear to
; continue processing or carry set to exit from Connect mode, in which case
; kbdflg will have the transfer character in it. [bgp]

chrout:	call	outprt		; send a character out the port
	clc
	ret

cpage:	cmp	flags.vtflg,TTTEK   ; only works on tektronix emulation
	jne	cpage1
	call	clrscr		; clear the tektronix screen
	clc
	ret
cpage1:	call	beep
	clc
	ret

chome: 	cmp	flags.vtflg,TTTEK   ; only works on tektronix emulation
	jne	chome1
	call	homescr 	; home the tektronix screen
	clc
	ret
chome1:	call	beep
	clc
	ret

cquery:	mov	al,'?'
	jmp	cmdcom
cstatus:mov	al,'S'
	jmp	cmdcom
cquit:	mov	al,'C'
	jmp	cmdcom
chang:	mov	al,'H'
	jmp	cmdcom
kdos:	mov	al,'P'
	jmp	cmdcom
cmdcom:	mov	kbdflg,al	; pass to msster.asm via kbdflg
	stc			; need to exit connect mode
	ret

dmpscn:	cmp	flags.vtflg,TTTEK   ; emulating tektronix?
	jne	dmpscn1 	; no, do it
	jmp	dmpscn2 	; can't on tektronix...
dmpscn1:call	savescr 	; have to save screen to dump it
	call	dumpscr
	call	restscr 	; need to put it back again too
	clc
	ret
dmpscn2:call	beep		; nothing else to do I guess
	clc
	ret

snull:	xor	ah,ah		; send a null
	call	outchr		; send without echo or logging
	clc
	ret

klogof:	mov	bx,argadr	; need to fix args
	and	[bx].flags,not CAPT ; clear capture flag
	and	yflags,not CAPT ; also local copy
	clc
	ret

klogon:	test	flags.capflg,LOGSES ; logging enabled?
	jz	klogon1
	mov	bx,argadr	; need to fix args
	or	[bx].flags,CAPT ; set capture flag
	or	yflags,CAPT	; also local copy
klogon1:clc
	ret

trnprs:	push	ax			; toggle ^ PrtSc screen to printer
	test	yflags,prtscr		; are we currently printing?
	jnz	trnpr2			; nz = yes, its on and going off
	push	bx
	mov	bx,prnhand		; file handle for system printer
	mov	ah,ioctl
	mov	al,7			; get output status of printer
	int	dos
	pop	bx
	jc	trnpr1			; c = printer not ready
	cmp	al,0ffh			; Ready status?
	je	trnpr2			; e = Ready	
trnpr1:	call	beep			; Not Ready, complain
	jmp	trnpr3			; and ignore request
trnpr2:	xor	yflags,prtscr		; flip the flag
	test	yflags,modoff		; mode line off?
	jnz	trnpr3			; nz = yes
	call	modlin			; else rewrite mode line
trnpr3:	pop	ax
	clc				; return carry clear (don't quit)
	ret

; Error recovery routine used when outchr reports unable to send character
;  or when vtmacro requests exiting Connect mode.
; Exit Connect mode cleanly, despite layers of intermediate calls.
endcon	proc	near
	call	pntflsh			; flush printer buffer
	mov	kbdflg,'C'		; report 'C' to TERM's caller
	mov	sp,oldsp		; recover startup stack pointer
					; TERM caller's return address is now
					; on the top of stack. A longjmp.
	jmp	quit			; exit Connect mode cleanly
endcon	endp


; Invoked by keyboard translator when an unknown keyboard verb is used as
; a string definition, such as {\ktest}. Enter with vtmacname pointing to
; uppercased verb name, asciiz, and vtmaclen set to its length.
extmacro proc	near
	jmp	vtmacro			; finish in common code
extmacro endp

;
; Reference	Macro structure for	db	number of entries (mac names)
;  is file	 table mcctab	   |->	db	length of macroname, excl '$'
;  mssset.asm		each entry |-> 	db	'macroname','$'
;  where these			   |->	dw	segment:0 of definition string
;  are stored.					  (offset part is always 0)	
;		Definition string in 	db	length of <string with null>
;		 buffer macbuf	  	db	'string with trailing null'
;
vtmacro	proc	near			; common code for macros vtsmac,vtrmac
	push	bx			; and Product
	push	cx
	push	si
	push	di
	push	es
	mov	ax,ds
	mov	es,ax
	mov	di,offset rdbuf+1	; macro def buffer starts here
	mov	si,vtmacname		; pointer to macro name
	mov	cl,vtmaclen		; length of macro name<sp/null>text
	xor	ch,ch
	mov	[di-1],cl		; counted string field
	cld
	rep	movsb			; copy to rdbuf
	mov	byte ptr [di],0		; null terminator
	mov	si,offset rdbuf+1	; look for name-text separator
	mov	cl,vtmaclen
	xor	ch,ch
vtmac1:	lodsb
	cmp	al,' '			; space separator?
	je	vtmac1a			; e = yes, stop here
	or	al,al			; null terminator?
	jz	vtmac1a			; e = yes, stop here
	loop	vtmac1
	inc	si			; to do null lenght correctly
vtmac1a:sub	si,offset rdbuf+1+1	; compute length of macro name
	mov	cx,si
	mov	vtmaclen,cl		; save a macro name length
					; check for existence of macro
	mov	bx,offset mcctab	; table of macro names
	mov	cl,[bx]			; number of names in table
	xor	ch,ch
	jcxz	vtmacx			; z = empty table, do nothing
	inc	bx			; point to length of first name
vtmac2:	mov	al,[bx]			; length of this name
	xor	ah,ah
	cmp	al,vtmaclen		; length same as desired keyword?
	jne	vtmac3			; ne = no, search again
	mov	si,bx
	inc	si			; point at first char of name
	push	cx			; save name counter
	push	di			; save reg
	mov	cl,vtmaclen		; length of name, excluding '$'
	xor	ch,ch
	mov	di,vtmacname		; point at desired macro name
	push	es			; save reg
	push	ds
	pop	es			; make es use data segment
	cld
	repe	cmpsb			; match strings
	pop	es			; need current si below
	pop	cx
	pop	di			; recover saved regs
	je	vtmac4			; e = matched
vtmac3:	add	bx,ax			; step to next name, add name length
	add	bx,4			; + count, dollar sign, def word ptr
	loop	vtmac2			; try next name
vtmacx:	pop	es
	pop	di
	pop	si			; no macro, return to Connect mode
	pop	cx
	pop	bx
	ret

vtmac4:	cmp	taklev,maxtak		; room in Take level?
	jge	vtmacx			; ge = no, exit with no action
	inc	taklev			; increment take level
	add	takadr,size takinfo	; make a new Take entry/macro
	mov	bx,takadr		; point to current macro structure
	mov	ax,ds			; segment of rdbuf
	mov	[bx].takbuf,ax		; segment of definition string struc
	mov	cl,rdbuf		; length of whole string
	xor	ch,ch
	mov	[bx].takcnt,cx		; number of chars in definition
	mov	[bx].takargc,0		; our argument count
	mov	[bx].takptr,offset rdbuf+1 ; where to read next command char
	mov	[bx].taktyp,0ffh	; flag as a macro
	pop	es
	pop	di
	pop	si
	pop	cx
	pop	bx
	jmp	endcon			; exit Connect mode
vtmacro	endp

; Service SET NETBIOS-NAME name   command at Kermit prompt level
setnbios proc	near
	ret
setnbios endp
sesdisp	proc	near
	ret
sesdisp	endp

CODE	ends
	end
