        NAME    mssset
; File MSSSET.ASM
; Set command module
; edit history:
; Last edit: 4 Jan 1988
; 1 Jan 1988 version 2.30
; 4 Jan 1988 Check current disk on every Status display. [jrd]
; 3 Nov 1987 Fix parsing of Set Display with trailing spaces. [jrd]
; 19 Oct 1987 Cleanup, rewrite num0, allow \### in Set Escape-char. [jrd]
; 27 Aug 1987 Suppress Set Translate msgs if in quiet Take file. [jrd]
; 18 Aug 1987 Change ESC to escape for MASM 4.5+ [jrd]
; 31 July 1987 Increase Macro name space to 50 average names. [jrd]
; 7 July 1987 Change Show Macro to do cr/lf expansion internally. [jrd]
; 31 June 1987 Modify DEFINE Macro command to not parse backslash numbers
;  to binary; instead convert only commas to binary cr and simply store
;  everything else literally for the end user to parse. [jrd]
; 22 June 1987 Fix Set Remote On/Off display bits. [jrd]
; 13 June 1987 Rewrite Define/Do/Show Macro procedures to do automatic
;  deletion of macro space. A macro can be removed by saying Def mac-name <cr>
;  Permit backslash format binary numbers in defintions. Use base 10.
;  Many numerical parsing routines removed to file msster.asm so this file
;  will assemble under MASM 1.25. [jrd]
; 24 May 1987 Add SET DELAY seconds command. [jrd]
; 10 May 1987 Add keywords ON/OFF to Set Trans Input. Default is Off.
;  On/off condition is byte rxtable[256] (0=off, else on). [jrd]
; 24 March 1987 Add path to default disk status display.
;  Revise LOG Command to be LOG PACKETS | SESSION filespec [jrd]
; 21 March 1987 Add Set Translation and Show Translation commands to convert
;  incoming serial port bytes while in Connect mode.
; Add full number parsing code (cnvlin, katio, decout, valout) here too. [jrd]
; 4 Jan 1987 Add jump to keyboard translator when invoking Set Key if global
;  word stkadr (stored here) is non-zero; else use regular Set Key. Stkadr
;  would hold the offset address of the replacement Set Key routine. [jrd]
; 19 Nov 1986 Update trans.(pad and padch) to use the Users preset values
;  for I and S packets. [jrd]
; 1 Oct 1986 Version 2.29a
; 18 Sept 1986 Add 7-bit vs 8-bit flag to flags.remflg to control width
;  of characters being displayed. Part of Set Display command. [jrd]
; 13 Sept 1986 Add \ooo octal # notation to Set Prompt command. [jrd]
; 4 Sept 1986 Add Bob Goeke's change to move comms port table to a system
;  dependent module (typ msx---) to allow 3+ ports and localized idents. [jrd]
; 14 August 1986 Introduce Set Send/Receive End-of-Line [jrd]
; 17 July 1986 Replace Status display proc with better code. [jrd]
; 14 July 1986 Add Long packet support for Set send/rec packet length. [jrd]
; Add Script support, Set Input, from James Sturdevant. [jrd]
; 26 June 1986 Update trans.seol in Set End-of-line so S packets use preferred
;  (user specified) packet terminator. [jrd]
; 26 May 1986 Revise code to permit serial display. DISPLAY command now
;  accepts Quiet, Regular, or Serial arguments. [jrd]
; [2.29] code frozen on 6 May 1986 [jrd]

        public setcom, status, baudprt, prmptr, dodef, stat0
        public setcpt, docom, shomac, dmpname, widmsk, stkadr
        public setrx, shorx, rxtable
        include mssdef.h

macmax  equ     50              ; max # of macros

maketab MACRO                   ; Assembler Macro to make rxtable [jrd]
cnt = 0
        rept 256
        db      cnt             ; initialize table to 0 .. 255
cnt = cnt + 1
        endm
        db      0               ; table off (0) or on (1) indicator
ENDM

datas   segment public 'datas'
        extrn   comand:byte, intake:byte, flags:byte, trans:byte, cptio:byte
        extrn   takadr:word, taklev:byte, inichk:byte, portval:word
        extrn   curdsk:byte, setktab:byte, setkhlp:byte, dtrans:byte
        extrn   spause:byte, filtst:byte, maxtry:byte, imxtry:byte
        extrn   indfto:word, inactv:byte, incasv:byte, inecho:byte
        extrn   comptab:byte, termtb:byte

kerm    db      'Kermit-MS>$'
crlf    db       cr,lf,'$'
crlfsp  db      cr,lf,' ',' ','$'       ; crlf space space
eqs     db      ' = $'
ermes1  db      cr,lf,'?Too many macro names$'
ermes2  db      cr,lf,'?No room for macro definition$'
ermes3  db      cr,lf,'?Not confirmed$'
ermes4  db      cr,lf,'?No room in Take stack to expand macro$'
ermes5  db      cr,lf,'?Not implemented$'
errcap  db      cr,lf,'?Unable to open that file$'
filhlp  db      cr,lf,' Output filename for the log (def: Kermit.Log)$'
dishlp  db      cr,lf,' Quiet (no screen writing), Regular (normal),'
        db      ' Serial (non-formatted screen)'
        db      cr,lf,' and/or 7-BIT (default) or 8-BIT wide characters.$'
remhlp  db      cr,lf,' OFF to show file transfer statistics,'
        db      ' ON for quiet screen$'
macmsg  db      ' Specify macro name followed by body of macro, on same line$'
shmmsg  db      ' Confirm with carriage return $'
prmmsg  db      cr,lf
        db    ' Enter new prompt string or nothing to regain regular prompt.'
        db      cr,lf,' Use \123 notation for special chars (Escape is \27)$'

srxhlp1 db      cr,lf,' Enter   code for received byte   code for'
        db      ' local byte ',cr,lf,' use ascii characters themselves or'
        db      cr,lf,' numerical equivalents of  \nnn  decimal'
        db      ' or \Onnn  octal or \Xnnn  hexadecimal',cr,lf
        db      ' or keywords  ON  or  OFF  (translation is initially off)'
        db      cr,lf,'$'
badrx   db      cr,lf,' Bad byte code$'
shormsg db      cr,lf,' Translation table of received byte codes while'
        db      ' in CONNECT mode'
        db      cr,lf,' Format: [received byte (decimal) -> local byte'
        db      ' (decimal)]',cr,lf,'$'
shopm1  db      ' [\$'                  ; Show Translation material
shopm2  db      ' -> \$'
shopm3  db      '] $'
rxoffmsg db     cr,lf,' Input Translation is off.$'
rxonmsg db      cr,lf,' Input Translation is on.$'
rxtable equ THIS BYTE           ; build 256 byte Translation Input table
        maketab                 ; table rxtable is used by Connect mode.
stkadr  dw      0       ; non-zero if replacement keyboard xlator present
prterr  db      '?Unrecognized value$'
defpmp  db      'Definition string: $'
nonmsg  db      'none$'
delmsg  db      'delete$'
onmsg   db      'on'
offmsg  db      'off'
defcpt  db      'KERMIT.LOG',0          ; default capture filename [jrd]
dmpdefnam db    'KERMIT.SCN',0          ; asciiz default screen dump filename

widmsk  db      7FH                     ; non-pkt display width, def=7 bits
tmp     db      ?,'$'
min     dw      0
max     dw      0
numerr  dw      0
numhlp  dw      0
stflg   db      0               ; Says if setting SEND or RECEIVE parameter.
temp    dw      0
temp1   dw      ?                       ; Temporary storage.
temp2   dw      ?                       ; Temporary storage.

modst   db      'Mode line: $'
locst   db      'Local echo: $'
belon   db      'Ring bell after transfer$'
beloff  db      'No bell after transfer$'
vtemst  db      'Terminal emulation: $'         ; terminal emulator [jrd]
portst  db      'Communications port: $'
capmsg  db      'Logging: $'
dmpmsg  db      'Dump screen file: $'
eofmsg  db      'EOF mode: $'
flost   db      'No flow control used$'
floxmsg db      'Flow control: xon/xoff $'
handst  db      'Handshake used: $'
destst  db      'File destination: $'
diskst  db      'Path: $'
blokst  db      'Block check used: $'
;;ebyst db      '8-bit quoting done only on request$'
;;ebvst db      '8-bit quoting will be done with: $'
sqcst   db      'Send control char prefix: $'
rqcst   db      'Receive control char prefix: $'
debon   db      'Debug mode: $'
flwon   db      'Warning (filename change): $'
parmsg  db      'Parity: $'
abfdst  db      'Discard incomplete file$'
abfkst  db      'Keep incomplete file$'
sndmsg  db      'Send Delay: $'
sndmsg2 db      ' sec, Pause: $'
sndmsg3 db      ' ms$'
ssohst  db      'Send start-of-packet char: $'
rsohst  db      'Receive start-of-packet char: $'
meolst  db      'End-of-Line char  S: ',5eh,'$'
mseol2  db      '  R: ',5eh,'$'
stimst  db      'Send timeout (seconds): $'
rtimst  db      'Receive timeout (seconds): $'
spakst  db      'Send packet size: $'
rpakst  db      'Receive packet size: $'
snpdst  db      '# of send padding chars: $'
rnpdst  db      '# of receive padding chars: $'
retrymsg db     'Retry send/receive packet limit: $'
dispst  db      'Display (vs Remote):$'
remost  db      'Remote (vs Display) $'
timmsg  db      'Timer: $'
escmes  db      'Escape character: $'
scpmsg  db      'Scripts(Input):$'
scpmsne db      ' echo:off, $'
scpmse  db      ' echo:on, $'
casmsi  db      'case:ignore, $'
casmso  db      'case:observe, $'
scptms  db      'def-tmo: $'
scpmsp  db      ' sec, tmo-action:proceed$'
scpmsq  db      ' sec, tmo-action:quit$'
baudrt  db      'Baud rate is $'
unrec   db      'unknown$'

nummsg1 db      cr,lf,'?Use a number between $'
nummsg2 db      ' and $'
dmphlp  db      'Enter name of disk file to hold screen dumps$'
eolhlp  db      cr,lf,'Decimal number between 0 and 31$'
timhlp  db      cr,lf,'Decimal number between 0 and 94$'
quohlp  db      cr,lf,'Decimal number between 33 and 126$'
pakerr  db      cr,lf,'Illegal packet length. Choose a decimal number '
        db      cr,lf,'from 20 to 94 (normal) or to 1000 (long)$'
pakhlp  db      cr,lf,'Decimal number between 20 and 94 (normal) or '
        db      '1000 (long)$'
npdhlp  db      cr,lf,'Decimal number between 0 and 99$'
paderr  db      cr,lf,'Illegal pad character$'
padhlp  db      cr,lf,'Decimal number between 0 and 31 or 127$'
pauhlp  db      cr,lf,'Decimal number between 0 and 127$'
retryhlp db     cr,lf,'Decimal number between 1 and 63$'
delyhlp db      cr,lf,'Delay seconds before sending file (0-63)$'
eschlp  db      cr,lf,'Press literal control code (ex: Cntrl ]) or'
        db      ' enter numerical value in \### form$'
escerr  db      cr,lf,'?Not a control code$'
dskhlp  db      cr,lf,'Default disk drive to use, such as A:$'
dskerr  db      cr,lf,'Invalid drive specification$'
hnd1hlp db      cr,lf,'xon (17), xoff (19), cr (13), lf (10), bell (7),'
        db      ' esc (27), none (0)'
        db      cr,lf,' or "code" followed by decimal number$'
hnd2hlp db      cr,lf,'Decimal number between 0 and 31$'
intoms  db      'number of seconds to wait before timeout',cr,lf,'$'
loghlp  db      cr,lf,' PACKETS - during file transfers'
        db      cr,lf,' SESSION - during Connect mode'
        db      cr,lf,' followed by optional filename (default is KERMIT.LOG)$'
debhlp  db      cr,lf,' PACKETS - during file transfers'
        db      cr,lf,' SESSION - during Connect mode'
        db      cr,lf,' ON - both packets and sessions'
        db      cr,lf,' OFF - turns off all debugging$'

sethlp  db      cr,lf,lf
        db      '  Baud or Speed     many speeds      '
        db      '  Key         key-ident   definition '
        db      cr,lf
        db      '  Bell    on/off    at end of xfers  '
        db      '  Local-echo        on/off'
        db      cr,lf
        db      '  Block-check-type  checksum/CRC     '
        db      '  Mode-line         on/off'
        db      cr,lf
        db      '  Debug   on/off    display packets  '
        db      '  Parity    even/odd/mark/space/none'
        db      cr,lf
        db      '  Default-disk                       '
        db      '  Port for i/o      1/2/COM1/COM2'
        db      cr,lf
        db      '  Delay   secs  before Sending file  '
        db      '  Prompt  string    (new Kermit prompt)'
        db      cr,lf
        db      '  Destination   Disk/Screen/Printer  '
        db      '  Receive parameter  many things'
        db      cr,lf
        db      '  Display quiet/reg/serial show cnts?'
        db      '  Remote    on/off  show xfer counts?'
        db      cr,lf
        db      '  Dump filespec     screen to disk   '
        db      '  Retry limit for packet send/receive'
        db      cr,lf
        db      '  End-of-line char  cr or whatever   '
        db      '  Send parameter    many things'
        db      cr,lf
        db      '  EOF Ctrl-Z/NoCtrl-Z  ^Z ends file? '
        db      '  Take-echo on/off  display commands?'
        db      cr,lf
        db      '  Escape char  ^]   or whatever      '
        db      '  Terminal  none, Heath-19, VT52, VT102,'
        db      cr,lf
        db      '  Flow-control      xon-xoff or none '
        db      '     and many terminal setup parameters'
        db      cr,lf
        db      '  Handshake xon/xoff/cr/lf/bell/esc..'
        db      '  Timer     on/off  time packet waiting'
        db      cr,lf
        db      '  Incomplete file   keep/discard     '
        db      '  Translation IN  Connect mode rcv',27h,'d char'
        db      cr,lf
        db      '  Input timeout, etc   (for scripts) '
        db      '  Warning   on/off  if file renamed'
        db      cr,lf,'$'

settab   db     32
        mkeyw   'Baud',baudst
        mkeyw   'Bell',bellst
        mkeyw   'Block-check-type',blkset
        mkeyw   'Debug',debst
        mkeyw   'Default-disk',dskset
        mkeyw   'Delay',setdely
        mkeyw   'Destination',desset
        mkeyw   'Display',disply
        mkeyw   'Dump',setdmp
        mkeyw   'End-of-Line',eolset
        mkeyw   'EOF',seteof
        mkeyw   'Escape',escset
        mkeyw   'Flow-control',floset
        mkeyw   'Handshake',hndset
        mkeyw   'Incomplete',abfset
        mkeyw   'Input',inpset
        mkeyw   'Key',setkey
        mkeyw   'Local-echo',lcal
        mkeyw   'Mode-line',modl
        mkeyw   'Parity',setpar
        mkeyw   'Port',coms
        mkeyw   'Prompt',promset
        mkeyw   'Receive',recset
        mkeyw   'Remote',remset
        mkeyw   'Retry',retryset
        mkeyw   'Send',sendset
        mkeyw   'Speed',baudst
        mkeyw   'Take-echo',takset
        mkeyw   'Terminal',vts
        mkeyw   'Timer',timset
        mkeyw   'Translation',setrx
        mkeyw   'Warning',filwar


seoftab db      2
        mkeyw   'Ctrl-Z',1
        mkeyw   'NoCtrl-Z',0

stsrtb  db      8                               ; Number of options.
        mkeyw   'End-of-Line',sreol
        mkeyw   'Packet-length',srpack
        mkeyw   'Padchar',srpad
        mkeyw   'Padding',srnpd
        mkeyw   'Pause',srpaus
        mkeyw   'Quote',srquo
        mkeyw   'Start-of-packet',srsoh
        mkeyw   'Timeout',srtim

ontab   db      2
        mkeyw   'off',0
        mkeyw   'on',1


destab  db      3                       ; Three choices
        mkeyw   'Disk',1
        mkeyw   'Printer',0
        mkeyw   'Screen',2

distab  db      5                       ; Set Display mode [jrd]
        mkeyw   '7-bit',7               ; controls bit d8bit in flags.remflg
        mkeyw   '8-bit',8               ; sets d8bit
        mkeyw   'Quiet',dquiet          ; values defined in header file
        mkeyw   'Regular',dregular
        mkeyw   'Serial',dserial

dissta  db      6                       ; Status of Display mode [jrd]
        mkeyw   'Quiet, 7-bit',dquiet
        mkeyw   'Regular, 7-bit',dregular
        mkeyw   'Serial, 7-bit',dserial
        mkeyw   'Quiet, 8-bit',dquiet+d8bit
        mkeyw   'Regular, 8-bit',dregular+d8bit
        mkeyw   'Serial, 8-bit',dserial+d8bit

; What type of block check to use.
blktab  db      3
        mkeyw   '1-character-checksum',1
        mkeyw   '2-character-checksum',2
        mkeyw   '3-character-CRC-CCITT',3

; If abort when receiving files, can keep what we have or discard

abftab  db      2                       ; Only two options.
        mkeyw   'Discard',1
        mkeyw   'Keep',0

partab  db      5                       ; Five entries
        mkeyw   'even',PAREVN
        mkeyw   'mark',PARMRK
        mkeyw   'none',PARNON
        mkeyw   'odd',PARODD
        mkeyw   'space',PARSPC

flotab  db      2
        mkeyw   'none',flonon
        mkeyw   'xon/xoff',floxon

hndtab  db      8
        mkeyw   'bell',bell
        mkeyw   'code',0ffh             ; allow general numerial code [jrd]
        mkeyw   'cr',cr
        mkeyw   'esc',escape
        mkeyw   'lf',lf
        mkeyw   'none',0
        mkeyw   'xoff',xoff
        mkeyw   'xon',xon

inptab  db      4                               ; Scripts. Set Input
        mkeyw   'Case',inpcas                   ;[jrs]
        mkeyw   'Default-timeout',inptmo        ;[jrs]
        mkeyw   'Echo',inpeco                   ;[jrs]
        mkeyw   'Timeout-action',inpact         ;[jrs]

inactb  db      2                               ; Set Input Timeout Action
        mkeyw   'Proceed',0                     ;[jrs]
        mkeyw   'Quit',1                        ;[jrs]

incstb  db      2                               ;[jrs] Set Input Case
        mkeyw   'Ignore',0dfh                   ;[jrs]
        mkeyw   'Observe',0ffh                  ;[jrs]


bdtab   db      18                      ; 18 entries
        mkeyw   '110',b0110
        mkeyw   '115200',b115200
        mkeyw   '1200',b1200
        mkeyw   '134.5',b01345
        mkeyw   '150',b0150
        mkeyw   '1800',b1800
        mkeyw   '19200',b19200
        mkeyw   '2000',b2000
        mkeyw   '2400',b2400
        mkeyw   '300',b0300
        mkeyw   '38400',b38400
        mkeyw   '45.5',b00455
        mkeyw   '4800',b4800
        mkeyw   '50',b0050
        mkeyw   '57600',b57600
        mkeyw   '600',b0600
        mkeyw   '75',b0075
        mkeyw   '9600',b9600

debtab  db      4                       ; Set Debug command
        mkeyw   'Off',0
        mkeyw   'On',logpkt+logses
        mkeyw   'Packets',logpkt
        mkeyw   'Session',logses

logtab  db      2                       ; LOG command
        mkeyw   'Packets',logpkt
        mkeyw   'Session',logses

logsta  db      4                       ; Log Status table
        mkeyw   'off',logoff            ; suspended or no logging
        mkeyw   'Packets',logpkt
        mkeyw   'Session',logses
        mkeyw   'Packet+Session',logpkt+logses

trnstab db      1                       ; Set Translation table
        mkeyw   'Input',1

prmptr  dw      kerm                    ; pointer to prompt
prm     db      80 dup (?)              ; Buffer for new prompt.
dmpname db      'KERMIT.SCN',54 dup (0) ; file name for screen dumps [jrd]

rdbuf   db      128 dup (?)             ; work space; room for macro def too
                                        ;  and for Status display line

mcctab  db      1                       ; macro name table, one initially
        mkeyw   'IBM',ibmmac            ; offset of definition string (7 bytes)
        db      (macmax*10 - 7) dup (?) ; room for rest of macro names
mcclen  equ     $-mcctab                ; length of mcctab
mccptr  dw      mcctab + 8              ; ptr to first free byte in mcctab

macbuf  equ     this byte               ; buffer of macro strings
ibmmac  db      imlen                   ; startup IBM macro definition
        db      'set timer on',cr,'set parity mark',cr
        db      'set local-echo on',cr,'set handshake xon',cr
        db      'set flow none',cr
imlen   equ     $-ibmmac-1
        db      (macmax*60 -imlen-1) dup (?); space for additonal macro defs
maclen  equ     $ - macbuf              ; length of macbuf
macptr  dw      macbuf+imlen+1          ; ptr to first free byte in macbuf

shom9a  db      cr,lf,' Free space (bytes) for names: $'
shom9c  db      ', for definitions: $'


; structure for status information table sttab.
stent   struc
sttyp   dw      ?               ; type (actually routine to call)
msg     dw      ?               ; message to print
val2    dw      ?               ; needed value: another message, or tbl addr
tstcel  dw      ?               ; address of cell to test, in data segment
basval  dw      0               ; base value, if non-zero
stent   ends

sttab   stent   <baudprt>
        stent   <srchkw,vtemst,termtb,flags.vtflg>      ; terminal emulator
        stent   <srchkw,portst,comptab,flags.comflg>
        stent   <onoff,modst,,flags.modflg>
        stent   <srchkw,parmsg,partab,parflg,portval>
        stent   <prsnd, sndmsg>
        stent   <onoff,locst,,ecoflg,portval>
        stent   <stnum,stimst,,dtrans.stime>
        stent   <msg2,flost,floxmsg,floflg,portval>
        stent   <onechr,ssohst,,trans.ssoh>
        stent   <prhnd>
        stent   <stlnum,spakst,,trans.slongp>
        stent   <drnum,diskst,,curdsk>
        stent   <stnum,snpdst,,dtrans.spad>
        stent   <srchkw,destst,destab,flags.destflg>
        stent   <onechr,sqcst,,trans.rquote>
        stent   <onoff,flwon,,flags.flwflg>
        stent   <stnum,rtimst,,trans.rtime>
        stent   <msg2,abfkst,abfdst,flags.abfflg>
        stent   <onechr,rsohst,,trans.rsoh>
        stent   <srchkw,eofmsg,seoftab,flags.eofcz>
        stent   <stlnum,rpakst,,trans.rlongp>
        stent   <msg2,beloff,belon,flags.belflg>
        stent   <stnum,rnpdst,,trans.rpad>
        stent   <srchkw,capmsg,logsta,flags.capflg>
        stent   <onechr,rqcst,,dtrans.squote>
        stent   <onoff,timmsg,,flags.timflg>
        stent   <preol,meolst>
        stent   <srchkw,debon,logsta,flags.debug>
        stent   <stnum,retrymsg,,maxtry>
        stent   <onechr,escmes,,trans.escchr>
        stent   <srchkw,blokst,blktab,trans.chklen>
        stent   <srchkw,dispst,dissta,flags.remflg>
        stent   <dmpstat,dmpmsg>
        stent   <scpprt,scpmsg>
        stent   <vtstat>                        ; Terminal status, in MSX
        dw      0                               ; end of table

datas   ends

code    segment public 'code'
        extrn prserr:near, comnd:near, dobaud:near, cmblnk:near, locate:near
        extrn cmgtch:near, repars:near, coms:near, defkey:near
        extrn inicpt:near, prompt:near, prtscr:near
        extrn getbaud:near, isfile:near, strlen:near
        extrn strcpy:near, cnvlin:near, katoi:near, decout:near, atoi:near
        extrn vts:near, vtstat:near
        assume  cs:code, ds:datas, es:nothing

; DO defined macro command

DOCOM   PROC    NEAR
        mov     dx,offset mcctab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd
         jmp    r
         nop
        mov     bx,temp
        cmp     taklev,maxtak           ; room in take level?
        jl      docom2                  ; yes, continue
        mov     dx,offset ermes4        ; else complain
        jmp     reterr
docom2: inc     taklev                  ; increment take level (overflow)
        add     takadr,size takinfo
        mov     si,bx                   ; point to macro definition
        mov     cl,[si]                 ; get size from initial byte
        mov     ch,0
        inc     si                      ; point to actual definition
        mov     bx,takadr               ; point to current buffer
        mov     [bx].taktyp,0ffh        ; flag as a macro
        mov     [bx].takptr,si          ; point to beginning of def
        mov     [bx].takchl,cl          ; # of chars left in buffer
        mov     [bx].takcnt,cx          ; and in definition
        mov     word ptr [bx].takcnt+2,0 ; zero high order...
        jmp     rskp
DOCOM   ENDP

; DEFINE macro command
; Data structures comments. Macro name is stored in table mcctab as if we
; had used macro mkeyw, such as       mkeyw 'mymac',offset my_definition.
; In detail:    db      length of name
;               db      'name'
;               db      '$'
;               dw      offset of definition string
; Mcctab begins with a byte holding the number of macros in the table; one,
;  IBM, is established at assembly time. Mcctab is 10*macmax bytes long.
; Pointer mccptr holds the offset of the next free byte in mcctab.
; Definition strings are stored in table macbuf as
;               db      length of definition string below
;               db      'definition string'
; Pointer macptr holds the offset of the next free byte in macbuf. Macbuf
; is nominally 100*macmax bytes long.
; A new definition is read into buffer rdbuf+1, where byte rdbuf is reserved
;  to hold the length of the macro's name during intermediate processing.
; If the definition is absent then the macro is removed from the tables.
; Rewritten 13 June 1987 [jrd]
DODEF   PROC    NEAR
        mov     ah,cmtxt
        mov     bx,offset rdbuf+1       ; buffer for keyword
        mov     dx,offset macmsg
        call    comnd
         jmp    r
         nop
        xchg    ah,al
        xor     ah,ah
        mov     temp,ax                 ; save length of command line
        cmp     ax,0                    ; is command line empty?
        jne     dode1                   ; ne = no
        ret                             ; return not confirmed
dode1:  mov     ah,cmcfm                ; get a confirm
        call    comnd
         jmp    r
         nop
        push    ds                      ; address data segment
        pop     es
        cld                             ; strings go forward
        mov     cx,temp                 ; cmd line len, cx = running counter
        mov     rdbuf,0                 ; number of chars in keyword so far
                                        ; uppercase the keyword, look for end
        mov     si,offset rdbuf+1       ; point at macro name text
dode2:  lodsb                           ; get a byte, dec cx
        cmp     al,'a'                  ; map lower case to upper
        jb      dode3
        cmp     al,'z'
        ja      dode3
        sub     al,'a'-'A'
        mov     [si-1],al               ; uppercase if necessary
dode3:  inc     rdbuf                   ; increment char count of keyword
        cmp     al,' '                  ; is this the break character?
        loopne  dode2                   ; no, loop thru rest of word
        jne     dode4                   ; ended with break char?
        dec     rdbuf                   ; yes, don't count in length
dode4:
        call    remtab                  ; remove any duplicate keyword
        jcxz    dode6                   ; cx = 0 means no keyword
                                ; check for free space for keyword and string
        mov     al,rdbuf                ; keyword text length
        add     al,4                    ; plus overhead bytes
        xor     ah,ah
        add     ax,mccptr               ; add to free space pointer
        cmp     ax,offset mcctab+mcclen ; enough room?
        jb      dode5                   ; b = yes
        mov     dx,offset ermes1        ; too many macro names
        jmp     reterr
dode5:  mov     di,si                   ; scan after keyword name
        mov     al,' '                  ; remove leading spaces in string
        repe    scasb
        je      dode6                   ; e = all spaces
        inc     cx                      ; offset auto decrement of rep
        dec     di                      ; offset auto increment of rep
        mov     si,di                   ; point to start of string text
        mov     dx,di                   ; source of definition text
        call    strlen                  ; get length of string into cx
        mov     ax,cx                   ; length of string
        mov     temp,cx                 ; remember it here
        inc     ax                      ; plus its count byte
        add     ax,macptr               ; plus free space pointer
        cmp     ax,offset macbuf+maclen ; enough room?
        jb      dode7                   ; b = yes

        mov     dx,offset ermes2        ; no room for definition
        jmp     reterr
dode6:  jmp     rskp
                                        ; install new keyword in mcctab
dode7:  cmp     temp,0                  ; temp = length of definition
        je      dode10                  ; e = no def, exit now
        mov     bx,offset mcctab
        mov     dx,offset rdbuf
        call    addtab
                        ; copy definition into buffer, changing commas to CRs
        mov     di,macptr               ; free space in string buffer
        mov     bx,di                   ; look at count byte
        inc     di                      ; skip over count byte
        mov     cx,temp                 ; length of string text
        mov     byte ptr[bx],cl         ; store length of string
dode8:  lodsb                           ; get a byte
        cmp     al,','                  ; comma?
        jne     dode9                   ; no, keep going
        mov     al,cr                   ; else replace with cr
dode9:  stosb
        loop    dode8                   ; keep copying
        mov     cx,temp
        inc     cx                      ; number of bytes copied overall
        add     macptr,cx               ; update free ptr
dode10: jmp     rskp
DODEF   ENDP

; add an entry to a keyword table
; enter with bx = table address, dx = ptr to new entry, macptr = string offset,
; mccptr = offset of free bytes in table mcctab.
; no check is made to see if the entry fits in the table.
addtab  proc    near
        push    cx
        push    si
        push    es
        cld
        mov     ax,ds
        mov     es,ax           ; address data segment
        mov     bp,bx           ; remember where tbl starts
        mov     cl,[bx]         ; pick up length of table
        mov     ch,0
        inc     bx              ; point to actual table...
        jcxz    addta4          ; cx = 0 if table is presently empty

addta1: push    cx              ; preserve count
        mov     si,dx           ; point to entry
        lodsb                   ; get length of new entry
        mov     cl,[bx]         ; and length of table entry...
        mov     ah,0            ; assume they're the same size
        cmp     al,cl           ; are they the same?
        lahf                    ; remember result of comparison...
        jae     addta2          ; is new smaller? no, use table length
        mov     cl,al           ; else use length of new entry
addta2: mov     ch,0
        lea     di,[bx+1]       ; point to actual keyword
        repe    cmpsb           ; compare strings
        pop     cx              ; restore count
        jb      addta4          ; below, insert before this one
        jne     addta3          ; not below or same, keep going
        sahf                    ; same. get back result of length comparison
        jb      addta4          ; if new len is smaller, insert here
        jne     addta3          ; if not same size, keep going
        mov     si,bx           ; else this is where entry goes
        jmp     short addta6    ; no insertion required...
addta3: mov     al,[bx]
        mov     ah,0
        add     bx,ax           ; skip this entry
        add     bx,4            ; len + $ + value...
        loop    addta1          ; and keep looking
addta4: mov     si,bx           ; this is first location to move
        mov     di,bx
        inc     ds:byte ptr [bp] ; remember we're adding one...
        jcxz    addta6          ; no more entries, forget this stuff
        mov     bh,0            ; this stays 0
addta5: mov     bl,[di]         ; get length
        lea     di,[bx+di+4]    ; end is origin + length + 4 for len, $, value
        loop    addta5          ; loop thru remaining keywords
        mov     cx,di
        sub     cx,si           ; compute # of bytes to move
        push    si              ; preserve loc for new entry
        mov     si,di           ; first to move is last
        dec     si              ; minus one
        mov     di,dx           ; new entry
        mov     bl,[di]         ; get length
        lea     di,[bx+si+4]    ; dest is source + length of new + 4
        std                     ; move backwards
        rep     movsb           ; move the table down
        cld                     ; put flag back
        pop     si
addta6: mov     di,si           ; this is where new entry goes
        mov     si,dx           ; this is where it comes from
        mov     cl,[si]         ; length
        mov     ch,0
        add     cx,1            ; count byte
        add     mccptr,cx       ; update free space pointer: cnt+name
        add     mccptr,3        ; plus '$' and pointer to string
        rep     movsb           ; stick it in
        mov     al,'$'          ; add printing terminator
        stosb
        mov     ax,macptr       ; and string offset
        stosw
        pop     es
        pop     si
        pop     cx
        ret
addtab  endp

; If new keyword matches an existing one then remove existing keyword,
; its string definition, compress tables mcctab and macbuf, readjust string
; pointers for each macro name, reduce number of macro table entries by one.
; Otherwise, exit with no changes.  13 June 1987 [jrd]
remtab  proc    near
        push    ax
        push    bx
        push    cx
        push    si
        push    di
        mov     si,offset rdbuf+1       ; point to new macro name
        mov     bx,offset mcctab+1      ; table of macro keywords
        mov     temp,0                  ; temp = current keyword
        cmp     byte ptr mcctab,0       ; any macros defined?
        jne     remta1                  ; ne = yes
        jmp     remtax                  ; else exit now
remta1:                                 ; match table keyword and text word
        mov     cl,rdbuf                ; length of user's macro name
        xor     ch,ch
        cmp     cl,byte ptr [bx]        ; compare length vs table keyword
        jne     remta4                  ; ne = not equal lengths, try another
        push    si                      ; lengths match, how about spelling?
        push    bx
        inc     bx                      ; point at start of keyword
remta2: mov     ah,byte ptr [bx]        ; keyword char
        mov     al,byte ptr [si]        ; new text char
        cmp     al,ah                   ; test characters
        jne     remta3                  ; ne = no match
        inc     si                      ; move to next char
        inc     bx
        loop    remta2                  ; loop through entire length
remta3: pop     bx
        pop     si
        jcxz    remta6                  ; z: cx = 0, exit with match;
                                        ;  else select next keyword
remta4: inc     temp                    ; number of keyword to test next
        mov     cx,temp
        cmp     cl,mcctab               ; all done? Recall, temp starts at 0
        jb      remta5                  ; b = not yet
        jmp     remtax                  ; exhausted search, unsuccessfully
remta5: mov     al,byte ptr [bx]        ; cnt (keyword length from macro)
        xor     ah,ah
        add     ax,4                    ; skip over '$' and two byte value
        add     bx,ax                   ; bx = start of next keyword slot
        jmp     remta1                  ; do another comparison
                                        ; new name already present as a macro
remta6: cld                             ; clear macro string and macro name
        push    ds
        pop     es                      ; set es to datas segment
        mov     temp,bx                 ; save ptr to found keyword
        mov     al,byte ptr [bx]        ; cnt (keyword length of macro)
        xor     ah,ah
        add     ax,2                    ; skip cnt and '$'
        add     bx,ax                   ; point to string offset field
        add     ax,2                    ; count offset field bytes
        sub     mccptr,ax               ; readjust free space ptr for names
        push    bx
        mov     bx,[bx]
        mov     temp1,bx                ; temp1 = offset of old string
        mov     al,byte ptr[bx]         ; length of old string
        xor     ah,ah
        inc     ax                      ; plus its count byte
        mov     temp2,ax                ; save here
        pop     bx
                                        ; clear keyword table mcctab
        add     bx,2                    ; compute source = next keyword
        mov     si,bx                   ; address of next keyword
        mov     di,temp                 ; address of found keyword
        mov     cx,offset mcctab+mcclen ; address of buffer end
        sub     cx,si                   ; amount to move
        jcxz    remtax                  ; cx = 0 means none
        rep     movsb                   ; move down keywords (deletes current)
                                        ; revise other string offsets
        mov     si,offset mcctab        ; table of string offsets
        inc     si                      ; skip count byte
        mov     cl,mcctab               ; current number of table entries
        xor     ch,ch
        dec     mcctab                  ; one less keyword
        mov     dx,temp1                ; address of old string
remta7: mov     al,byte ptr[si]         ; cnt of first keyword
        add     al,2                    ; plus cnt and '$'
        xor     ah,ah
        add     si,ax                   ; look at string offset
        cmp     dx,[si]                 ; old address vs this string
        ja      remta8                  ; a = address not affected
        mov     ax,temp2                ; size of old string
        sub     [si],ax                 ; adjust offset downward
remta8: add     si,2                    ; point to next table entry
        loop    remta7
                                        ; remove old string
        mov     di,temp1                ; address of old string = destination
        mov     ax,temp2                ; size of old string field
        mov     si,di
        add     si,ax                   ; plus length: source = next string
        sub     macptr,ax               ; readjust top of buf free string ptr
        mov     cx,offset macbuf+maclen ; end of buffer
        sub     cx,si                   ; number of bytes to move
        jcxz    remtax                  ; cx = 0 means none
        rep     movsb                   ; move down old strings
remtax: pop     di
        pop     si
        pop     cx
        pop     bx
        pop     ax
        ret
remtab  endp


; This is the SET command.

SETCOM  PROC    NEAR
        mov     dx,offset settab        ; Parse a keyword from the set table.
        mov     bx,offset sethlp
        mov     ah,cmkey
        call    comnd
         jmp    r
        call    bx
         jmp    short setco2
         nop
setco1: jmp     rskp
setco2: cmp     comand.cmstat,cmcfm     ; is there a confirm at the end?
        je      setco1                  ; e = yes, ok
        ret                             ; return non-confirmed
SETCOM  endp


;   SET BAUD or SET SPEED.

BAUDST  PROC    NEAR
        mov     dx,offset bdtab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get one.
         nop
        mov     bx,temp
        mov     si,portval
        mov     ax,[si].baud            ; Remember original value
        mov     [si].baud,bx            ; Set the baud rate.
        call    dobaud                  ; Use common code
        ret
BAUDST  ENDP

; SET BELL on or off

BELLST  PROC    NEAR
        mov     dx,offset ontab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd
         jmp    r
         nop
        mov     bx,temp
        mov     flags.belflg,bl
        ret
BELLST  ENDP

; SET BLOCK-CHECK

BLKSET  PROC    NEAR
        mov     dx,offset blktab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get a confirm.
         nop
        mov     bx,temp
        mov     trans.chklen,bl         ; Use this char as the handshake.
        mov     inichk,bl               ; Save here too.
        ret
BLKSET  ENDP

; SET DEBUG {OFF | ON | SESSSION | PACKETS}

DEBST   PROC       NEAR
        mov     dx,offset debtab
        mov     bx,offset debhlp
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get a confirm.
         nop
        mov     bx,temp
        or      flags.debug,bl          ; set the mode, except for Off.
        cmp     bx,0                    ; OFF?
        jne     deb0                    ; ne = no
        mov     flags.debug,0           ; Set the DEBUG flags off.
deb0:   ret
DEBST   ENDP

; SET DESTINATION   of incoming files.

DESSET  PROC    NEAR
        mov     dx,offset destab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get a confirm.
         nop
        mov     bx,temp
        mov     flags.destflg,bl        ; Set the destination flag.
        cmp     bl,2                    ; Is dest the screen?
        jne     desa                    ; No, then done
        mov     flags.xflg,1            ; Remember it here
        ret
desa:   mov     flags.xflg,0            ; Don't write to screen
        ret
DESSET  ENDP

; SET DEFAULT-DISK    for sending/receiving, etc.

DSKSET  PROC    NEAR
        mov     ah,cmfile               ; Parse for drive specification. [jrd]
        mov     dx,offset rdbuf         ; Read into handy buffer.
        mov     bx,offset dskhlp        ; Text of help message.
        call    comnd
         jmp    r
        mov     ah,cmcfm
        call    comnd
         jmp    r
        mov     ah,rdbuf                ; Get the drive they said to use.
        cmp     ah,0                    ; Did they type a bare CR?
        je      dsk0                    ; Yes, complain.
        cmp     ah,'a'                  ; alphabetic?
        jl      dsk2
        sub     ah,'a'-1                ; convert to 1 = a, 2 = b, etc
        jmp     dsk3
dsk2:   cmp     ah,'A'
        jl      dsk0                    ; opps, a non-alpha
        sub     ah,'A'-1                ; convert to numeric
dsk3:   mov     curdsk,ah               ; And remember it.
        dec     ah
        mov     dl,ah
        mov     ah,seldsk
        int     dos
        mov     ah,gcurdsk              ; succeeded? get current disk
        int     dos
        inc     al                      ; map to 1 = a, etc
        cmp     al,curdsk               ; same?
        jne     dsk4                    ; ne = no
        ret
dsk4:   mov     curdsk,al               ; get back actual current disk
dsk0:   mov     ah,prstr
        mov     dx,offset dskerr        ; Illegal drive specification.
        int     dos
        ret
DSKSET  ENDP

; SET DELAY seconds   Used only for SEND command in local mode
SETDELY PROC    NEAR
        mov     min,0                   ; smallest acceptable value
        mov     max,63                  ; largest acceptable value
        mov     numhlp,offset delyhlp   ; help message
        mov     numerr,0                ; complaint message
        call    num0                    ; parse numerical input
        mov     trans.sdelay,al
        ret
SETDELY ENDP

; SET DISPLAY Quiet/Regular/Serial/7-Bit/8-Bit (inverse of Set Remote on/off)
; Accepts two keywords in one command.  [jrd]
disply  proc    near
        mov     ah,cmkey
        mov     dx,offset distab
        mov     bx,offset dishlp
        call    comnd
         jmp    r
        mov     temp1,bx                ; save parsed value
        mov     temp2,0ffh              ; assume no second keyword
        cmp     comand.cmsflg,0         ; first command ended with whitespace?
        je      displ1                  ; e = no, get a confirm
        mov     comand.cmcr,1           ; bare CR's are allowed
        mov     ah,cmkey                ; parse for second keyword
        mov     dx,offset distab
        mov     bx,offset dishlp
        call    comnd
         jmp    displ1                  ; no matching keyword
         nop
         nop
        mov     temp2,bx                ; get key value
displ1: mov     comand.cmcr,0           ; bare CR's are not allowed
        mov     ah,cmcfm
        call    comnd                   ; confirm
         jmp    r                       ; return on failure
         nop
        mov     bx,temp1                ; examine first key value
        cmp     bx,0                    ; check range
        jle     displ3                  ; le = not legal
        cmp     bx,7                    ; 7-8 bit value?
        jge     displ2                  ; ge = yes
        mov     flags.remflg,bl         ; set display mode
        jmp     displ3                  ; check next key value
displ2: cmp     bx,8                    ; set 8-bit wide display?
        ja      displ3                  ; a = bad value
        and     flags.remflg,not d8bit  ; assume want 7 bit mode
        cmp     bx,7                    ; really want 7 bit mode?
        je      displ3                  ; e = yes
        or      flags.remflg,d8bit      ; set 8 bit flag
displ3: mov     bx,temp2                ; examine second key value
        cmp     bx,0                    ; check range
        jle     displ5                  ; le = not legal
        cmp     bx,7                    ; 7-8 bit value?
        jge     displ4                  ; ge = yes
        mov     flags.remflg,bl         ; set display mode
        jmp     displ5                  ; all done
displ4: cmp     bx,8                    ; set 8-bit wide display?
        ja      displ5                  ; a = bad value
        and     flags.remflg,not d8bit  ; assume want 7 bit mode
        cmp     bx,7                    ; really want 7 bit mode?
        je      displ5                  ; e = yes
        or      flags.remflg,d8bit      ; set 8 bit flag
displ5: ret
disply  endp


; Set Dump filename  for saving screen images on disk. [jrd]
; Puts filename in global string dmpname.
setdmp  proc    near
        mov     dx,offset rdbuf         ; work area
        mov     byte ptr rdbuf,0        ; clear it
        mov     bx,offset dmphlp        ; help message
        mov     ah,cmfile               ; allow paths
        call    comnd
         jmp    r
        mov     ah,cmcfm
        call    comnd
         jmp    r
        mov     dx,offset rdbuf         ; assume we will use this text
        call    strlen                  ; filename given?
        mov     si,dx                   ; for strcpy
        cmp     cx,0                    ; length of user's filename
        jg      setdmp1                 ; g = filename is given
        mov     si,offset dmpdefnam     ; no name, use default instead.
setdmp1:mov     di,offset dmpname       ; copy to globally available loc.
        call    strcpy
        ret
setdmp  endp

; SET EOF

seteof  proc    near
        mov     ah,cmkey
        mov     bx,0
        mov     dx,offset seoftab
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd
         jmp    r                       ; error return...
         nop
        mov     bx,temp
        mov     flags.eofcz,bl          ; set value
        ret
seteof  endp

; SET EOL char (for Sent packets)
; Archic, here for downward compatibility
EOLSET  PROC    NEAR
        mov     stflg,'S'               ; set send/receive flag to Send
        jmp     sreol                   ; use Set Send/Rec routine do the work
EOLSET  ENDP

; SET ESCAPE character.
; Accept literal control codes and \### numbers. [jrd] 18 Oct 1987
ESCSET  PROC    NEAR
        mov     ah,cmfile
        mov     dx,offset rdbuf         ; work space
        mov     word ptr rdbuf,0        ; clear it
        mov     bx,offset eschlp        ; help
        call    comnd
         jmp    r
         nop
        cmp     ah,0                    ; anything given?
        jne     escse1                  ; ne = yes
         ret                            ; else  return unconfirmed
escse1: mov     ah,cmcfm                ; get a confirm
        call    comnd
         jmp    r
        nop
        mov     si,offset rdbuf         ; source of chars
        call    katoi                   ; convert escaped numbers to binary
        cmp     ax,spc                  ; is it a control code?
        jae     escse2                  ; ae = no, complain
        cmp     ax,0                    ; non-zero too?
        je      escse2                  ; e = zero
        mov     trans.escchr,al         ; Save new value.
        ret
escse2: mov dx,offset escerr
        jmp     reterr
ESCSET  ENDP

; SET FILEWARNING

FILWAR  PROC    NEAR
        mov     dx,offset ontab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get a confirm.
         nop
        mov     bx,temp
        mov     flags.flwflg,bl         ; Set the filewarning flag.
        ret
FILWAR  ENDP

; SET FLOW-CONTROL

FLOSET  PROC    NEAR
        mov     dx,offset flotab
        xor     bx,bx
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get a confirm.
         nop
        mov     bx,temp
        mov     si,portval
        mov     [si].flowc,bx           ; Flow control value.
        cmp     bx,0                    ; Turning it off?
        je      flo0                    ; Yes.
        mov     [si].floflg,1           ; Say we're doing flow control.
        ret
flo0:   mov     [si].floflg,bl          ; Say we're not doing flow control.
        ret
FLOSET  ENDP

; SET HANDSHAKE
; Add ability to accept general decimal code. [jrd]

HNDSET  PROC    NEAR
        mov     dx,offset hndtab        ; table to scan
        mov     bx,offset hnd1hlp       ; help message
        mov     ah,cmkey
        call    comnd
         jmp    r
        cmp     bl,0ffh                 ; want a general char code?
        jne     hnd1                    ; ne = no
        mov     min,0                   ; get decimal char code
        mov     max,31                  ; range is 0 to 31 decimal
        mov     numhlp,offset hnd2hlp   ; help message.
        mov     numerr,0                ; error message
        call    num0                    ; convert number, return it in ax
        mov     bx,ax                   ; recover numerical code
hnd1:   mov     temp,bx                 ; handshake type
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get a confirm.
         nop
        mov     bx,temp                 ; recover bx
        mov     si,portval
        cmp     bl,0                    ; Setting handshake off?
        je      hnd0                    ; Yes.
        mov     [si].hndflg,1           ; And turn on handshaking.
        mov     [si].hands,bl           ; Use this char as the handshake.
        ret
hnd0:   mov     [si].hndflg,0           ; No handshaking.
        ret
HNDSET  ENDP

;   SET INCOMPLETE file disposition

ABFSET  PROC    NEAR
        mov     dx,offset abftab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ;  Didn't get a confirm.
         nop
        mov     bx,temp
        mov     flags.abfflg,bl         ; Set the aborted file flag.
        ret
ABFSET  ENDP
;
; Set Input commands (default-timeout, timeout-action, case, echo)
; By Jim Strudevant [jrs].
INPSET  PROC    NEAR
        mov     ah,cmkey                ; key word
        mov     dx,offset inptab        ; from inputtable
        mov     bx,0                    ; no hints
        call    comnd                   ; get the word
         jmp    r                       ; they blew it
        call    bx                      ; call the sub command
         jmp    r                       ; bad return
        jmp     rskp                    ; good return
;
; Set Input Default-timeout in seconds
;
inptmo: mov     ah,cmtxt                ; get a line of text
        mov     bx,offset rdbuf         ; put it here
        mov     dx,offset intoms        ; here's some help
        call    comnd                   ; get it
         jmp    r                       ; nothing typed
        mov     cl,ah                   ; get the length
        xor     ch,ch
        mov     si,offset rdbuf         ; set up
        call    atoi                    ; make it a number
         jmp    r                       ; bad number
        mov     indfto,ax               ; save it
        jmp     rskp                    ; good return

;
; Set Input Timeout action (proceed or quit)
;
inpact: mov     ah,cmkey                ; get a keyword
        mov     dx,offset inactb        ; from this list
        mov     bx,0                    ; no hints
        call    comnd                   ; get it
         jmp    r                       ; bad input
        mov     inactv,bl               ; save the action
        jmp     rskp                    ; good return
;
; Set Input Echo on or off
;
inpeco: mov     ah,cmkey                ; get a keyword
        mov     dx,offset ontab         ; from this list
        mov     bx,0                    ; no hints
        call    comnd                   ; get it
         jmp    r                       ; bad input
        mov     inecho,bl               ; save the action
        jmp     rskp                    ; good return
;
; Set Input Case observe or ignore
;
inpcas: mov     ah,cmkey                ; get a keyword
        mov     dx,offset incstb        ; from this list
        mov     bx,0                    ; no hints
        call    comnd                   ; get it
         jmp    r                       ; bad input
        mov     incasv,bl               ; save the action
        jmp     rskp                    ; good return
INPSET  ENDP

; SET KEY
; Jumps to new Set Key routine
setkey  proc    near
        cmp     stkadr,0        ; keyboard translator present? [jrd]
        je      setk4           ; e = no, use this routine
        mov     bx,stkadr       ; yes, get offset of procedure
        jmp     bx              ; jump to keyboard translator [jrd]
setk4:  mov     dx,offset ermes5
        jmp     reterr          ; else print error message
setkey  endp

; SET LOCAL-ECHO {ON | OFF}

LCAL    PROC    NEAR
        mov     dx,offset ontab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx                 ; Save the parsed value.
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get a confirm.
         nop
        mov     bx,temp
        mov     si,portval
        mov     [si].ecoflg,bl          ; Set the local echo flag.
        ret
LCAL    ENDP

; LOG  {PACKETS | SESSION} filename
;   addition for capture of raw output
; revised by [jrd] to use full DOS 2.0 path name

setcpt  proc    near
        mov     dx,offset logtab        ; kinds of logging
        mov     bx,offset loghlp        ; help on kind of logging
        mov     ah,cmkey                ; parse keyword
        call    comnd
         jmp    r
        mov     temp,bx                 ; Save the parsed value.
        mov     dx,offset cptio.string  ; holds the complete filename
        mov     bx,offset filhlp        ; ask for filename
        mov     ah,cmfile               ; allow paths
        call    comnd
         jmp    r
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ;  Didn't get a confirm.
        cmp     flags.capflg,0          ; is capturing active already?
        jne     setcp5                  ; ne = yes, just update kind
        mov     dx,offset cptio.string
        call    strlen                  ; filename given?
        cmp     cx,0                    ; length of user's filename
        jg      setcp4                  ; g = filename is given
        mov     dx,offset defcpt        ; use default name instead.
setcp4: mov     ax,dx                   ; place for filename for isfile.
        call    isfile                  ; does file exist already?
        jc      setcp3                  ; c = does not exist.
        test    byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
        jnz     setcp2                  ; nz = no.
        mov     ah,open2                ; open existing file.
        mov     al,2                    ; opened for reading and writing
        int     dos                     ; do it
        jc      setcp2                  ; if carry bit set then error
        mov     cptio.handle,ax         ; save filehandle
        mov     bx,ax                   ; file handle for seeking
        mov     cx,0ffffh               ; high order displacement (-1 ext)
        mov     dx,-1                   ; low order part of displacement
        mov     ah,lseek                ; seek to EOF (to do appending)
        mov     al,2                    ; says to EOF
        int     dos
        call    inicpt                  ; init capture variables
setcp5: mov     ax,temp                 ; kind of Logging
        or      al,al                   ; is logging off?
        jne     setcp4a                 ; ne = no, add this type to the list
        mov     flags.capflg,al         ; say capture routine is inactive
setcp4a:or      flags.capflg,al         ; accumulate kinds of logging
        jmp     rskp                    ; and return

setcp3: test    filtst.fstat,80h        ; access problem?
        jnz     setcp2                  ; nz = yes, stop here
        mov     ah,creat2               ; function is create, v 2.0
        mov     cl,20H                  ; turn on archive bit
        mov     ch,0
        int     dos                     ; create the file, DOS 2.0
        jc      setcp2                  ; if carry bit set then error
        mov     cptio.handle,ax         ; save filehandle
        call    inicpt                  ; init capture variables
        mov     ax,temp                 ; kind of logging
        or      al,al                   ; is logging off?
        jne     setcp3a                 ; ne = no, add this type to the list
        mov     flags.capflg,al         ; say capture routine is inactive
setcp3a:or      flags.capflg,al         ; accumulate kinds of logging
        jmp     rskp                    ; and return

setcp2: mov     dx,offset errcap        ; give error message
        jmp     reterr                  ; and display it

setcpt  endp

; SET MODE LINE

MODL    PROC    NEAR
        mov     dx,offset ontab         ; parse an on or off
        mov     bx,0                    ; no special help...
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx                 ; save value
        mov     ah,cmcfm
        call    comnd
         jmp    r
         nop
        mov     bx,temp
        mov     flags.modflg,bl         ; set flag appropriately
        ret
MODL    ENDP

; SET PARITY

SETPAR  PROC    NEAR
        mov     dx,offset partab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ;  Didn't get a confirm.
         nop
        mov     bx,temp
        mov     si,portval
        mov     [si].parflg,bl          ; Set the parity flag.
        cmp     bl,parnon               ; Resetting parity to none?
        je      setp0                   ; Yes, reset 8 bit quote character.
        mov     trans.ebquot,dqbin      ; Else, do quoting
        ret                             ; That's it
setp0:  mov     trans.ebquot,'Y'        ; If none, say will quote upon request
        ret
SETPAR  ENDP

; SET PROMPT      Allow user to change the "Kermit-MS>" prompt.
; {string} and \number notation permitted to represent special chars. [jrd]

PROMSET PROC    NEAR
        mov     ah,cmtxt
        mov     bx,offset rdbuf         ; Read in the prompt.
        mov     word ptr [bx],0         ; clear buffer
        mov     dx,offset prmmsg
        call    comnd
         jmp    r
        mov     ah,cmcfm                ; get a confirm
        call    comnd
         jmp    r
        cmp     rdbuf,0                 ; Just a bare CR?
        jne     prom0                   ; ne = no
        mov     ax,offset kerm          ; yes, restore default prompt
        jmp     prom1
prom0:  push    si                      ; parse \### constants into
        push    di                      ;  1 byte binary numbers inline.
        mov     si,offset rdbuf         ; source = new prompt string
        mov     byte ptr [si-1+length rdbuf],0 ; plant null terminator
        mov     di,offset prm           ; destination
        call    cnvlin                  ; convert \### in string to binary
        pop     di
        pop     si
        mov     bx,cx                   ; get byte count
        add     bx,offset prm           ; point to null terminator
        mov     byte ptr [bx],'$'       ; End of string.
        mov     ax,offset prm
prom1:  mov     prmptr,ax               ; Remember it.
        ret
PROMSET ENDP

; SET RETRY value. Changes the packet retry limit. [jrd]

RETRYSET PROC   NEAR
        mov     min,1                   ; smallest acceptable value
        mov     max,63                  ; largest acceptable value
        mov     numhlp,offset retryhlp  ; help message
        mov     numerr,0                ; complaint message
        call    num0                    ; parse numerical input
        mov     maxtry,al
        shl     al,1                    ; quick multiply by two or three
        mov     imxtry,al               ; keep that much
        add     al,maxtry               ; try three times
        js      retrys1                 ; s = sign bit set, too much
        mov     imxtry,al               ; I packets get 3 times as many tries.
retrys1:ret
RETRYSET ENDP

; SET TAKE-ECHO  on or off.

TAKSET  PROC    NEAR
        mov     dx,offset ontab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd
         jmp    r
         nop
        mov     bx,temp
        mov     flags.takflg,bl
        ret
TAKSET  ENDP

; SET TIMER     on or off during file transfer.

TIMSET  PROC    NEAR
        mov     dx,offset ontab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        mov     temp,bx
        mov     ah,cmcfm
        call    comnd
         jmp    r
         nop
        mov     bx,temp
        mov     flags.timflg,bl
        ret
TIMSET  ENDP

; SET SEND parameters

SENDSET PROC    NEAR
        mov     stflg,'S'               ; Setting SEND parameter
sndst0: mov     dx,offset stsrtb        ; Parse a keyword.
        mov     bx,0                    ; no specific help
        mov     ah,cmkey
        call    comnd
         jmp    r                       ; bad user text
        call    bx                      ; call the action routine
         nop
         nop
         nop
        jmp     rskp
SENDSET ENDP

; SET RECEIVE parameters

recset: mov     stflg,'R'               ; Setting RECEIVE paramter.
        jmp     sndst0

remset  proc    near                    ; Set REMOTE ON/OFF
        mov     ah,cmkey
        mov     dx,offset ontab
        mov     bx,offset remhlp
        call    comnd
         jmp    r
         nop
        mov     temp,bx                 ; save parsed value
        mov     ah,cmcfm
        call    comnd                   ; confirm
         jmp    r                       ; return on failure
         nop
        mov     bx,temp
        and     flags.remflg,not (dquiet+dserial+dregular) ; no display bits
        or      bl,bl                   ; want off state? (same as regular)
        jz      remset1                 ; z = yes
        or      flags.remflg,dquiet     ; else on = quiet display
        ret
remset1:or      flags.remflg,dregular   ; off = regular display
        ret
remset  endp


; SET Send and Receive EOL char

sreol   PROC    NEAR
        mov     min,0                   ; lowest acceptable value
        mov     max,1FH                 ; largest acceptable value
        mov     numhlp,offset eolhlp    ; Reuse help message.
        mov     numerr,0                ; error message address
        call    num0                    ; get numerical input
        cmp     stflg,'S'               ; Setting SEND paramter?
        je      sreol1
        mov     trans.reol,al
        jmp     short sreol2
sreol1: mov     dtrans.seol,al
sreol2: mov     ah,dtrans.seol
        mov     trans.seol,ah
        ret
sreol   ENDP


; SET SEND and RECEIVE start-of-header.

srsoh:  mov     min,0
        mov     max,1FH
        mov     numhlp,offset eolhlp    ; Reuse help message.
        mov     numerr,0                ; error message
        call    num0            ; Common routine for parsing numerical input.
        cmp     stflg,'S'               ; Setting SEND paramter?
        je      srsoh1
        mov     trans.rsoh,al           ; set Receive soh
        ret
srsoh1: mov     trans.ssoh,al           ; set Send soh
        ret

; SET SEND and  RECEIVE TIMEOUT.

srtim:  mov     min,0
        mov     max,94
        mov     numhlp,offset timhlp    ; Reuse help message.
        mov     numerr,0                ; error message
        call    num0            ; Common routine for parsing numerical input.
        cmp     stflg,'S'               ; Setting SEND paramter?
        je      srtim1
        mov     trans.rtime,al
        jmp     short srtim2
srtim1: mov     dtrans.stime,al
srtim2: mov     ah,dtrans.stime
        mov     trans.stime,ah
        ret
; SET SEND and RECEIVE PACKET LENGTH.
; Upgraded for long packets. [jrd]

srpack: mov     min,20
        mov     max,maxpack
        mov     numhlp,offset pakhlp    ; help
        mov     numerr,offset pakerr    ; error message
        call    num0
        cmp     stflg,'S'               ; setting send value?
        jne     srpakr                  ; ne = receive
        mov     trans.slongp,ax         ; set send value
        mov     trans.slong,ax          ; and remember what we Set.
        cmp     ax,94                   ; within normal packet range?
        ja      srpak2                  ; a = no
        mov     trans.spsiz,al          ; yes. update regular pkt size too
srpak2: ret
srpakr: mov     trans.rlongp,ax         ; set receive value
        cmp     ax,94                   ; within normal packet range?
        ja      srpak4                  ; a = no
        mov     trans.rpsiz,al          ; yes. update regular pkt size too.
srpak4: ret


; SET SEND and RECEIVE number of padding characters.

srnpd:  mov     min,0
        mov     max,99
        mov     numhlp,offset npdhlp    ; help message
        mov     numerr,0                ; error message
        call    num0                    ; Parse numerical input.
        cmp     stflg,'S'               ; Setting SEND paramter?
        je      srnpd1                  ; e = yes
        mov     trans.rpad,al           ; set Receive padding
        jmp     short srnpd2
srnpd1: mov     dtrans.spad,al          ; set default Send padding
srnpd2: mov     al,dtrans.spad
        mov     trans.spad,al    ; update active array for I and S pkts [jrd]
        ret

; SET SEND and RECEIVE padding character.

srpad:  mov     min,0
        mov     max,127
        mov     numhlp,offset padhlp
        mov     numerr,offset paderr
        call    num0                    ; Parse numerical input.
        cmp     ah,127                  ; This is allowed.
        je      srpad1
        cmp     ah,32
        jb      srpad1                  ; Between 0 and 31 is OK too.
        mov     ah,prstr
        mov     dx,offset paderr
        int     dos
        ret
srpad1: cmp     stflg,'S'               ; Send?
        je      srpad2                  ; e = yes, else Receive
        mov     trans.rpadch,al         ; store receive pad char
        jmp     short srpad3
srpad2: mov     dtrans.spadch,al        ; store Send pad char
srpad3: mov     ah,dtrans.spadch
        mov     trans.spadch,ah  ; update active array for I and S pkts [jrd]
        ret

; SET SEND and  RECEIVE control character prefix.

srquo:  mov     min,33
        mov     max,126
        mov     numhlp,offset quohlp    ; help message
        mov     numerr,0                ; error message
        call    num0                    ; Parse numerical input.
        cmp     stflg,'S'               ; Setting outgoing quote char?
        je      srquo1
        mov     trans.rquote,al         ; set Receive quote char
        jmp     short srquo2
srquo1: mov     dtrans.squote,al        ; set Send quote char
srquo2: mov     ah,dtrans.spadch
        mov     trans.spadch,ah   ; update active array for I and S pkts [jrd]
        ret

; SET SEND Pause number of milliseconds         ; [jrd]

srpaus: mov     min,0
        mov     max,127
        mov     numhlp,offset pauhlp
        mov     numerr,0
        call    num0                    ; Parse numerical input.
        cmp     stflg,'S'               ; Setting SEND paramter?
        je      srpau0
        mov     dx,offset ermes5        ; "Not implemented" msg
        jmp     reterr                  ; print error message
srpau0: mov     spause,al               ; store value
        ret

; SET TRANSLATION INPUT   Connect mode translate incoming characters.
; SET TRANS IN {Original-byte New-byte | ON | OFF}

SETRX   PROC    NEAR                    ; translate incoming serial port char
        mov     ah,cmkey
        mov     dx,offset trnstab       ; direction table (just one entry)
        mov     bx,0                    ; no help
        call    comnd
         jmp    r
        mov     dx,offset rdbuf         ; our work space
        mov     word ptr rdbuf,0        ; insert terminator
        mov     bx,offset srxhlp1       ; first help message
        mov     ah,cmfile               ; parse a word
        call    comnd                   ; get incoming byte pattern
         jmp    r                       ; error if none
        or      ah,ah                   ; any text given?
        jz      setr6                   ; nz = no
        mov     temp,ax                 ; save byte count here
        mov     ax,word ptr rdbuf       ; get first two characters
        or      ax,2020h                ; convert upper to lower case
        cmp     ax,'fo'                 ; first part of word OFF?
        je      setr6                   ; e = yes, go analyze
        cmp     ax,'no'                 ; word ON?
        je      setr6                   ; e = yes, go do it
        mov     si,offset rdbuf         ; convert text to number
        call    katoi                   ; number converter procedure, to ax
        jnc     setr1                   ; nc = success
        cmp     byte ptr temp+1,1       ; just one character given?
        jne     setr6                   ; ne = no, so bad code
setr1:  mov     min,ax                  ; save byte code here
        mov     dx,offset rdbuf         ; our work space
        mov     word ptr rdbuf,0        ; insert terminator
        mov     bx,offset srxhlp1       ; first help message
        mov     ah,cmfile               ; parse a word
        call    comnd                   ; get incoming byte pattern
         jmp    r
        or      ah,ah                   ; any text given?
        jz      setr6                   ; z = no
        mov     temp,ax                 ; save byte count here
        mov     si,offset rdbuf         ; convert text to number
        call    katoi                   ; number converter procedure
        jnc     setr3                   ; nc = success
        cmp     byte ptr temp+1,1       ; just one character given?
        jne     setr6                   ; ne = no, so bad code or ON/OFF
setr3:  mov     max,ax                  ; save byte code here
        mov     ah,cmcfm                ; get a confirm
        call    comnd
         jmp    r                       ; no confirm
        mov     bx,min                  ; bl = incoming byte code
        xor     bh,bh
        mov     ax,max                  ; al = local (translated) byte code
        mov     rxtable [bx],al         ; store in rx translate table
        jmp     rskp

setr6:  mov     ah,cmcfm                ; get a confirm
        call    comnd
         jmp    r                       ; no confirm
        mov     dx,offset badrx         ; assume bad construction
        or      word ptr rdbuf,2020h    ; convert to lower case
        or      rdbuf+2,20h             ; first three chars
        cmp     word ptr rdbuf,'fo'     ; key word OFF?
        jne     setr8                   ; ne = no
        cmp     rdbuf+2,'f'             ; last letter of OFF?
        jne     setr8
        mov     rxtable+256,0           ; OFF is status byte = zero
        mov     dx,offset rxoffmsg      ; say translation is turned off
        jmp     setr9
setr8:  cmp     word ptr rdbuf,'no'     ; keyword ON?
        jne     setr9a                  ; ne = no, error
        mov     rxtable+256,1           ; ON is status byte non-zero
        mov     dx,offset rxonmsg       ; say translation is turned on
setr9:  cmp     intake,0                ; executing from a Take file?
        je      setr9a                  ; e = no
        cmp     flags.takflg,0          ; echo contents of Take file?
        je      setr10                  ; e = no
setr9a: mov     ah,prstr                ; bad number message
        int     dos
setr10: ret
SETRX   ENDP

; SHOW TRANSLATE-RECEIVE
; Display characters being changed for Connect mode serial receive translator.

SHORX   PROC    NEAR                    ; show translate table of incoming
                                        ; chars, only those changed
        mov     ah,cmcfm                ; get a confirm
        call    comnd
          jmp   r                       ; no confirm
        mov     ah,prstr
        mov     dx,offset rxoffmsg      ; assume translation is off
        cmp     rxtable+256,0           ; is translation off?
        je      shorx0                  ; e = yes
        mov     dx,offset rxonmsg       ; say translation is on
shorx0: int     dos
        mov     dx,offset shormsg       ; give title line
        int     dos
        xor     cx,cx                   ; formatted line counter
        xor     bx,bx                   ; entry subscript
shorx1: cmp     rxtable[bx],bl          ; entry same as normal?
        je      shorx2                  ; e = yes, skip it
        call    shoprt                  ; print the entry
shorx2: inc     bx                      ; next entry
        cmp     bx,255                  ; done all entries yet?
        jbe     shorx1                  ; be = not yet
        mov     ah,prstr
        mov     dx,offset crlf          ; end with cr/lf
        int     dos
        jmp     rskp

shoprt: cmp     cx,4                    ; done five entries for this line?
        jb      shopr1                  ; b = no
        mov     ah,prstr
        mov     dx,offset crlf          ; break line now
        int     dos
        xor     cx,cx
shopr1: mov     ah,prstr
        mov     dx,offset shopm1        ; start of display
        int     dos
        xor     ah,ah
        mov     al,bl                   ; original byte code
        call    decout                  ; display its value
        mov     ah,prstr
        mov     dx,offset shopm2        ; intermediate part of display
        int     dos
        xor     ah,ah
        mov     al,rxtable[bx]          ; new byte code
        call    decout                  ; display its value
        mov     ah,prstr
        mov     dx,offset shopm3        ; last part of display
        int     dos
        inc     cx                      ; count item displayed
        ret
SHORX   ENDP


; SHOW defined macros.

SHOMAC  PROC    NEAR
        mov     ah,cmtxt
        mov     bx,offset rdbuf
        mov     dx,offset shmmsg
        call    comnd
         jmp    r
        cmp     ah,0                    ; Bare CR means show all macros.
        je      shom1                   ; e = show all macros
        jmp     shom6                   ; No, he wants specific macro expanded.
shom1:  mov     si,offset mcctab        ; Table of macro names.
        cld
        lodsb
        mov     cl,al                   ; Number of macro entries.
        mov     ch,0
shom2:  jcxz    shom5                   ; Done if none left to display.
        lodsb                           ; Length of macro name.
        push    ax                      ; Don't forget it.
        mov     ah,prstr
        mov     dx,offset crlfsp        ; Go to new line.
        int     dos
        mov     dx,si                   ; Print macro name.
        int     dos
        mov     dx,offset eqs           ; display equals sign
        int     dos
        pop     ax                      ; recover length of macro name
        mov     ah,0
        add     si,ax                   ; Skip over name.
        add     si,1                    ; skip '$' field
        push    cx                      ; save regs
        push    si
        mov     si,[si]                 ; si = offset of count + string
        mov     cl,byte ptr [si]        ; length of string
        xor     ch,ch
        inc     si                      ; si = offset of string text proper
        mov     ah,conout
shom3:  lodsb                           ; get a byte into al
        cmp     al,' '                  ; control char?
        jae     shom3a                  ; ae = no
        cmp     al,cr                   ; carriage return?
        je      shom3a                  ; e = yes, handle separately
        push    ax
        mov     dl,5eh                  ; caret
        int     dos
        pop     ax
        add     al,'A'-1                ; add offset to make printable letter
shom3a: mov     dl,al                   ; display it
        int     dos
        cmp     al,cr                   ; binary carriage return?
        jne     shom4                   ; ne = no
        mov     dl,lf                   ; binary carriage returns are expanded
        int     dos
        mov     dl,' '                  ; to cr/lf/space/space
        int     dos
        int     dos
shom4:  loop    shom3                   ; do whole string
        pop     si
        pop     cx
        dec     cx
        add     si,2                    ; Skip over string offset
        jmp     shom2                   ; And do the rest.
shom5:  mov     ah,prstr
        mov     dx,offset shom9a        ; free space: name entries
        int     dos
        mov     ax,offset mcctab+mcclen
        sub     ax,mccptr               ; compute # of free name bytes
        call    decout
        mov     ah,prstr
        mov     dx,offset shom9c        ; body characters
        int     dos
        mov     ax,offset macbuf+maclen
        sub     ax,macptr
        call    decout
        mov     ah,prstr
        mov     dx,offset crlf
        int     dos
        jmp     rskp
shom6:  mov     ah,prstr
        mov     dx,offset ermes3
        int     dos
        jmp     rskp
SHOMAC  ENDP


; STATUS command. Revised by [jrd]

STATUS  PROC    NEAR
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get a confirm.
        mov     dx,offset crlf
        mov     ah,prstr
        int     dos                     ; print a crlf
STAT0:  call    cmblnk                  ; clear the screen
        call    locate                  ; home the cursor
        push    es                      ; STAT0 is an external ref (in mster)
        push    bx
        push    di
        mov     bx,ds
        mov     es,bx
        cld
        mov     bx,offset sttab         ; table to control printing
        xor     cx,cx                   ; column counter
stat1:  cmp     word ptr [bx],0         ; end of table?
        je      statx                   ; e = yes
        cld                             ; string direction is forward
        mov     di,offset rdbuf         ; point to destination buffer
        mov     byte ptr[di],spc        ; start with two spaces
        inc     di
        mov     byte ptr[di],spc
        inc     di
        push    cx                      ; save column number
        push    bx
        call    [bx].sttyp              ; call appropriate routine
        pop     bx
        pop     cx
        sub     di,offset rdbuf         ; number of bytes used
        add     cx,di                   ; new line col count
        push    cx                      ; save col number around print
        mov     cx,di                   ; how much to print now
        mov     di,offset rdbuf         ; source text
        call    prtscr                  ; print counted string
        pop     cx
        cmp     cx,38                   ; place for second display?
        jbe     stat2                   ; be = only half full
        mov     dx,offset crlf          ; over half full. send cr/lf
        mov     ah,prstr
        int     dos
        xor     cx,cx                   ; say line is empty now
        jmp     stat4
stat2:  mov     ax,cx
        mov     cx,38                   ; where we want to be next time
        sub     cx,ax                   ; compute number of filler spaces
        or      cx,cx
        jle     stat3a                  ; nothing to do
        mov     ah,conout
        mov     dl,' '
stat3:  int     dos                     ; fill with spaces
        loop    stat3                   ; do cx times
stat3a: mov     cx,38                   ; current column number
stat4:  add     bx,size stent           ; look at next entry
        jmp     stat1                   ; and do it
statx:  pop     di
        pop     bx
        pop     es
        jmp     rskp
STATUS  ENDP

; handler routines for status
; all are called with di/ destination buffer, bx/ stat ptr. They can change
; any register except es:, must update di to the end of the buffer.

; copy the message into the buffer
stmsg   proc    near
        push    ds
        pop     es              ; ensure es points to datas segment
        mov     si,[bx].msg     ; get message address
stms1:  lodsb                   ; get a byte
        stosb                   ; drop it off
        cmp     al,'$'          ; end of message?
        jne     stms1           ; no, keep going
        dec     di              ; else back up ptr
        ret
stmsg   endp

; get address of test value in stent. Returns address in si
stval   proc    near
        mov     si,[bx].basval  ; get base value
        cmp     si,0            ; any there?
        je      stva1           ; no, keep going
        mov     si,[si]         ; yes, use as base address
stva1:  add     si,[bx].tstcel  ; add offset of test cell
        ret                     ; and return it
stval   endp

; print a single character
onechr  proc    near
        call    stmsg           ; copy message part first
        call    stval           ; pick up test value address
        mov     al,[si]         ; this is char to print
        cmp     al,' '          ; printable?
        jae     onech1          ; yes, keep going
        add     al,64           ; make printable.
        mov     byte ptr [di],5eh       ; caret
        inc     di              ; note ctrl char
onech1: stosb                   ; drop char off
        ret
onechr  endp

; numeric field...
stnum   proc    near            ; for 8 bit numbers
        call    stmsg           ; copy message
        call    stval           ; pick up value address
        mov     al,[si]         ; get value
        mov     ah,0            ; high order is 0
        call    outnum          ; put number into buffer
        ret
stnum   endp

stlnum  proc    near            ; for 16 bit numbers [jrd]
        call    stmsg           ; copy message
        call    stval           ; pick up value address
        mov     ax,[si]         ; get value
        call    outnum          ; put number into buffer
        ret
stlnum  endp

; Common routine for parsing numerical input.
; Enter with numhlp = offset of help message, numerr = offset of optional
;  error message, min, max = allowable range of values.
; Returns value in ax, or does parse error return.
; Changes ax,bx,dx,si.                  [jrd] 18 Oct 1987
num0:   mov     dx,offset rdbuf+1       ; were to put text
        mov     word ptr rdbuf,0        ; clear the buffer
        mov     bx,numhlp               ; help text
        mov     ah,cmfile               ; get a word
        call    comnd
         jmp    r
        mov     ah,cmcfm
        call    comnd                   ; Get a confirm.
         jmp    r                       ; Didn't get one.
         nop
        mov     si,offset rdbuf+1
        cmp     rdbuf+1,'\'             ; already quoted?
        je      num0a                   ; e = yes
        mov     rdbuf,'\'               ; add a numerical quote
        dec     si                      ; point to our escape char
num0a:  call    katoi                   ; convert number in rdbuf
        jc      num0er                  ; c = no number, error
        cmp     ax,max                  ; largest permitted value
        ja      num0er                  ; a = error
        cmp     ax,min                  ; smallest permitted value
        jb      num0er                  ; b = error
        ret                             ; return value in ax

num0er: mov     ah,prstr
        mov     dx,numerr               ; comand-specific error message, if any
        cmp     dx,0                    ; was any given?
        je      num0e1                  ; e = no, use generic msg
        int     dos                     ; show given error message
        jmp     short num0e2
num0e1: mov     dx,offset nummsg1       ; get address of numeric error message.
        int     dos
        mov     ax,min                  ; smallest permitted number
        call    decout                  ; display decimal number in ax
        mov     ah,prstr
        mov     dx,offset nummsg2       ; "and"
        int     dos
        mov     ax,max                  ; largest permitted number
        call    decout
num0e2: jmp     prserr                  ; parsing error

; translate the number in ax...
outnum  proc    near
        cwd
        mov     bx,10
        div     bx              ; divide to get digit
        push    dx              ; save remainder digit
        or      ax,ax           ; test quotient
        jz      outnu1          ; zero, no more of number
        call    outnum          ; else call for rest of number
outnu1: pop     ax              ; get digit back
        add     al,'0'          ; make printable
        stosb                   ; drop it off
        ret
outnum  endp

; on/off field
onoff   proc    near
        call    stmsg           ; copy message
        call    stval           ; get value cell
        mov     al,[si]
        mov     si,offset onmsg
        mov     cx,2            ; assume 2-byte 'ON' message
        or      al,al           ; test value
        jnz     onof1           ; on, have right msg
        mov     si,offset offmsg
        mov     cx,3
onof1:  rep     movsb           ; copy right message in
        ret
onoff   endp

; print first message if false, second if true
msg2    proc    near
        call    stval           ; get value cell
        mov     al,[si]
        mov     si,[bx].msg     ; assume off
        or      al,al           ; is it?
        jz      msg21           ; yes, continue
        mov     si,[bx].val2    ; else use alternate message
msg21:  jmp     stms1           ; handle copy and return
msg2    endp

; search a keyword table for a value, print that value
srchkw  proc    near
        call    stmsg           ; first print message
        call    stval
        mov     al,[si]         ; get value to hunt for
        mov     ah,0            ; high order is 0
        mov     bx,[bx].val2    ; this is table address
        jmp     prttab          ; and look in table.
srchkw  endp


; Print the drive name.
drnum   proc    near
        call    stmsg           ; copy message part first
        call    stval           ; pick up test value address
;;;     mov     al,[si]         ; this is char to print
        mov     ah,gcurdsk      ; Get current disk.
        int     dos
        inc     al              ; We want 1 == A (not zero).
        mov     curdsk,al
        add     al,'@'          ; Make it printable.
        cld
        stosb
        mov     byte ptr [di],':'
        inc     di
        mov     byte ptr [di],'\'
        inc     di              ; end with a colon and backslash
        mov     dl,0            ; get current drive
        mov     ah,gcd          ; get current directory
        mov     si,di           ; current working buffer position
        int     dos
        push    cx
        push    dx
        mov     dx,di           ; directory string
        call    strlen          ; length of path part to cx
        cmp     cx,26           ; too long to show the whole thing?
        jbe     drnum3          ; be = is ok, show the whole path
        push    di              ; scan backward for last backslash
        mov     al,'\'          ; thing to search for
        std                     ; backward
        mov     di,si           ; start of buffer
        add     di,cx           ; length of string
        repne   scasb           ; scan backward for a backslash
        jcxz    drnum2          ; should not happen, but then again ...
        repne   scasb           ; do again for second to last path part
drnum2: cld                     ; reset direction flag
        dec     di              ; move di two places preceding backslash
        mov     [di],'--'       ; insert a missing path indicator
        dec     di
        mov     byte ptr [di],'-'
        mov     si,di           ; we will show just this part
        pop     di              ; recover main status pointer
drnum3: pop     dx
        pop     cx

drnum4: lodsb                   ; copy until null terminator
        stosb
        cmp     al,0            ; end of string?
        je      drnum5          ; e = yes
        jmp     short drnum4    ; do all
drnum5: dec     di              ; offset inc of stosb
        ret
drnum   endp


; Print the screen-dump filename [jrd]

dmpstat proc    near
        call    stmsg           ; copy message part
        mov     si,offset dmpname ; address of filename
dmpstat1:lodsb                  ; get a byte
        cmp     al,0            ; at end yet?
        je      dmpstat2        ; e = yes
        stosb                   ; store in buffer
        jmp     short dmpstat1  ; keep storing non-null chars
dmpstat2:ret
dmpstat endp

; print the End-of-Line characters
preol   proc    near
        call    stmsg           ; display leadin part of message
        mov     al,dtrans.seol  ; send eol char
        add     al,40H          ; make it printable
        stosb
        mov     si,offset mseol2 ; second part of message
        call    stms1           ; add that
        mov     al,trans.reol   ; receive eol char
        add     al,40H          ; make it printable
        stosb
        ret
preol   endp

; print Send Delay and Pause
prsnd   proc    near
        call    stmsg           ; display leadin part of msg
        mov     al,trans.sdelay ; Send Delay (sec)
        xor     ah,ah
        call    outnum
        mov     si,offset sndmsg2 ; second part of msg
        call    stms1           ; add that
        mov     al,spause       ; Send Pause (millisec)
        call    outnum
        mov     si,offset sndmsg3 ; last part of msg
        call    stms1           ; add it too
        ret
prsnd   endp

; Print the handshake.
prhnd:  mov     si,offset handst        ; copy in initial message
        call    stms1
        mov     si,offset nonmsg        ; assume no handshake
        mov     bx,portval
        cmp     [bx].hndflg,0           ; Is handshaking in effect?
        jne     prh0                    ; Yes, print what we're using.
        jmp     stms1                   ; no, say so and return
prh0:   mov     al,5eh                  ; Doing handshaking with control char.
        stosb
        mov     al,[bx].hands
        add     al,40H                  ; Make printable.
        stosb                           ; put in buffer
        ret                             ; and return

; Print the pad character in AL.
prpad:  cmp     al,127                  ; Are they using a delete?
        jne     prpad0
        mov     ah,prstr
        mov     dx,offset delmsg
        int     dos
        ret
prpad0: mov     dl,5eh                  ; caret
        mov     ah,conout
        push    ax
        int     dos
        pop     ax
        mov     dl,al
        add     dl,40H                  ; Make printable.
        int     dos
        ret

; Print value from table.   BX/address of table, AL/value of variable.
prttab: mov     cl,[bx]                 ; Number of entries in our table.
        inc     bx                      ; Point to the data.
prtt0:  mov     dl,[bx]                 ; Length of keyword.
        inc     bx                      ; Point to keyword.
        mov     dh,0
        inc     dx                      ; Account for "$" in table.
        mov     si,dx                   ; Put to index register.
        cmp     ax,[bx+si]              ; Is this the one?
        je      prtt1
        add     bx,dx                   ; Go to end of keyword.
        add     bx,2                    ; Point to next keyword.
        dec     cl                      ; Any more keywords to check?
        jnz     prtt0                   ; Yes, go to it.
        mov     bx,offset prterr
prtt1:  mov     si,bx
        jmp     stms1                   ; copy in message
        ret                             ; and return

; Print the baud rate

BAUDPRT PROC     NEAR
        mov     si,offset baudrt        ; "Baud rate is"
        call    stms1                   ; display that part
        call    getbaud                 ; read baud rate first
        mov     bx,portval
        mov     ax,[bx].baud
        cmp     al,byte ptr bdtab       ; number of table entries
        jb      bdprt5                  ; b = in table
        mov     si,offset unrec         ; say unrecognized value
        jmp     stms1                   ; display text and return
bdprt5: mov     bx,offset bdtab         ; show ascii rate from table
        call    prttab
        ret
BAUDPRT ENDP
                                        ; Scripts - Status
scpprt  proc    near                    ; display script settings on a line
        call    stmsg                   ; copy leading part of message
        mov     si,offset scpmsne       ; echo off
        cmp     inecho,0                ; echo state
        je      scppre                  ; e = off
        mov     si,offset scpmse        ; echo on
scppre: call    stms1                   ; add to buffer
        mov     si,offset casmsi        ; "ignore"
        cmp     incasv,0dfh             ; case state
        je      scpprc
        mov     si,offset casmso        ; "observe"
scpprc: call    stms1                   ; add to buffer
        mov     si,offset scptms        ; default timeout
        call    stms1                   ; add to buffer
        mov     ax,indfto               ; timeout value
        call    outnum                  ; add ascii rendition to buffer
        mov     si,offset scpmsp        ; "proceed"
        cmp     inactv,0                ; action on timeout, proceed?
        je      scppra                  ; e = yes
        mov     si,offset scpmsq        ; "quit"
scppra: call    stms1
        ret
scpprt  endp


; Jumping to this location is like retskp.    It assumes the instruction
;    after the call is a jmp addr.

RSKP    PROC    NEAR
        pop     bp
        add     bp,3
        push    bp
        ret
RSKP    ENDP

; Jumping here is the same as a ret.

R       PROC    NEAR
        ret
R       ENDP

; routine to print an error message, then retskp
; expects message in dx
reterr  proc    near
        mov     ah,prstr
        int     dos
        jmp     rskp
reterr  endp

code    ends

if1
        %out [End of pass 1]
else
        %out [End of assembly]
endif
        end
