; File MSSSET.ASM
; Set command module
; edit history:
; [2.29] [jrd]
; Add global name VTSTAT, defined in MSXxxx, to display status of terminal
; emulator (just a ret if none).
; Add Send Pause (# millisec) for msscom module.
; Revise procedures ATOI and num0 to work properly.
; Remove Set Autowrap and place function under Set Terminal Wrap
; Add Set Handshake Code decimal-number, for more general usage.
; Add facility to dump screens to disk files. Mssset records the filename
; and makes it available to system dependent modules for use.
;       [Joe R. Doupnik]
;
; [2.28 jrd]
; Removed reference to cmifi, revised capture to full DOS 2.0 level,
; shorten the status command display process, revise display, sort code.
; J R Doupnik 13 Oct 1985
; Make keywords be displayed in mixed case (for reading ease). 26 Dec 1985
; Correct error in set end-of-line which gave spurious "?Not confirmed"
;    error message. Annotate and clean routine "num0".
; Restore default logging filename of Kermit.log and open any log file
;    for append access. [jrd] 26 Dec 1985
;
; [v2.28]
; Added set mode line on/off (from Edgar Butt, Univ. of Md.)
; Decouple handshake and flow control, decouple both from local echo
; Made set commands check for junk after the command (even though
;    most of the commands return incorrectly) (from Greg Small, UC Berkeley)
; Be more cautious about running out of space when defining macros.
; Skip leading space in macro definitions
; Print info on macro free space in the show macros command (suggested by
;        Greg Small, UC Berkeley)
; Added set autowrap command.
; JD 14 May 1985
;

        public setcom, status, stat0, baudprt, escprt, prmptr, dodef
        public setcpt, docom, shomac, atoi, dmpname
        include mssdef.h

macmax  equ     20                      ; max # of macros

datas   segment public 'datas'
        extrn   comand: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                ; [jrd]

kerm    db      'Kermit-MS>$'
crlf    db       cr,lf,'$'
crlfsp  db      cr,lf,' ',' ','$'       ; crlf space space   [jrd]
eqs     db      ' = $'
ermes1  db      cr,lf,'?Too many macros$'
ermes2  db      cr,lf,'?No room in table for macro$'
ermes3  db      cr,lf,'?Not confirmed$'
ermes4  db      cr,lf,'?No room in take stack to expand macro$'
ermes5  db      cr,lf,'?Not implemented$'
erms23  db      cr,lf,'?Null input not allowed$' ;[jd]
erms24  db      cr,lf,'?Capture file already open (use Close command)$' ;[jd]
erms25  db      cr,lf,'?Input must be numeric$'
errcap  db      cr,lf,'?Unable to open that file$'      ;[jrd]
filhlp  db      ' Input file specification for session logging$'
macmsg  db      ' Specify macro name followed by body of macro $'
shmmsg  db      ' Confirm with carriage return $'
prmmsg  db      ' Enter new prompt string $'
sk1msg  db      ' Decimal scan code for key $'
sk2msg  db      ' Redefinition string for key $'
prterr  db      '?Unrecognized value$'
defpmp  db      'Definition string: $'
esctl   db      'Control-$'        ; [6]
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
tmp     db      ?,'$'
sum     db      0
min     db      0
max     db      0
desta   dw      0
numerr  dw      0
numhlp  dw      0
stflg   db      0               ; Says if setting SEND or RECEIVE parameter.
srtmp   db      0
savsp   dw      0
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]
cm1st   db      'Communications port: 1$'
cm2st   db      'Communications port: 2$'
capmsg  db      'Session 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      'Default disk: $'
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$'
eolst   db      'End-of-line character: $'
pacemsg db      'Send pause time (millisec): $'
ssohst  db      'Send start-of-packet char: $'
rsohst  db      'Receive start-of-packet char: $'
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: $'
dispst  db      'Display (vs Remote): $'
remost  db      'Remote (vs Display) $'
timmsg  db      'Timer: $'
escmes  db      'Escape character: $'
baudrt  db      'Baud rate is $'
b04st   db      '45.5$'
b05st   db      '50$'
b07st   db      '75$'
b11st   db      '110$'
b13st   db      '134.5$'
b15st   db      '150$'
b03st   db      '300$'
b06st   db      '600$'
b12st   db      '1200$'
b18st   db      '1800$'
b20st   db      '2000$'
b24st   db      '2400$'
b48st   db      '4800$'
b96st   db      '9600$'
b19st   db      '19200$'
b38st   db      '38400$'
unrec   db      'unknown$'

dmphlp  db      'Enter name of disk file to hold screen dumps$' ; [jrd]
eolhlp  db      cr,lf,'Decimal number between 0 and 31$'
eolerr  db      cr,lf,'Illegal end-of-line character$'
timerr  db      cr,lf,'Illegal timeout value$'
timhlp  db      cr,lf,'Decimal number between 0 and 94$'
soherr  db      cr,lf,'Illegal start-of-packet character$'
quohlp  db      cr,lf,'Decimal number between 33 and 126$'
quoerr  db      cr,lf,'Illegal control character prefix$'
pakerr  db      cr,lf,'Illegal packet length$'
pakhlp  db      cr,lf,'Decimal number between 20 and 94$'
npderr  db      cr,lf,'Illegal number of pad characters$'
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$'
pauerr  db      cr,lf,'Illegal number of milliseconds$'
eschlp  db      cr,lf,'Press literal control code (ex: Cntrl ])  $'
desterr db      cr,lf,'Illegal destination device$'
dskhlp  db      cr,lf,'Default disk drive to use, such as A:$'
dskerr  db      cr,lf,'Invalid drive specification$'
hnd1hlp db      cr,lf,'xon (24), xoff (17), cr (13), lf (10), bell (7),'
        db      ' esc (27)',cr,lf,' or "code" followed by decimal number$'
hnd2hlp db      cr,lf,'Decimal number between 0 and 31$'
hnderr  db      cr,lf,'Illegal number, must be 0 to 31$'

sethlp  db      cr,lf,lf
        db       '  Baud or Speed     many speeds      '
        db      '  Key         key + macro 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      COM1/COM2'
        db      cr,lf
        db      '  Destination   Disk/Screen/Printer  '
        db      '  Prompt  string    (new Kermit prompt)'
        db      cr,lf
        db      '  Display   on/off  show xfer counts?'
        db      '  Receive Parameter many things'
        db      cr,lf
        db      '  Dump filespec     screen to disk   '
        db      '  Remote    on/off  show xfer counts?'
        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      '  Warning   on/off  if file renamed'
        db      cr,lf,'$'

settab   db     28
        mkeyw   'Baud',baudst
        mkeyw   'Bell',bellst
        mkeyw   'Block-check-type',blkset
        mkeyw   'Debug',debst
        mkeyw   'Default-disk',dskset
        mkeyw   'Destination',desset
        mkeyw   'Display',disply
        mkeyw   'Dump',setdmp
        mkeyw   'End-of-Line',eolset
        mkeyw   'EOF',seteof
        mkeyw   'Escape',escape
        mkeyw   'Flow-control',floset
        mkeyw   'Handshake',hndset
        mkeyw   'Incomplete',abfset
        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   'Send',sendset
        mkeyw   'Speed',baudst
        mkeyw   'Take-echo',takset
        mkeyw   'Terminal',vts
        mkeyw   'Timer',timset
        mkeyw   'Warning',filwar


seoftab db      2
        mkeyw   'Ctrl-Z',1
        mkeyw   'NoCtrl-Z',0

stsrtb  db      07              ; Number of options.
        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             ; Two entries.
        mkeyw   'off',0
        mkeyw   'on',1

notontab   db      2            ; Two entries.
        mkeyw   'off',1         ; for items where text meaning is inverted.
        mkeyw   'on',0


destab  db      3               ; Three choices. [27c]
        mkeyw   'Disk',1
        mkeyw   'Printer',0
        mkeyw   'Screen',2

; 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. [20d]

abftab  db      2               ; Only two options.
        mkeyw   'Discard',1
        mkeyw   'Keep',0

partab  db      5               ; Five entries.                 [10 start]
        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',esc
        mkeyw   'lf',lf
        mkeyw   'none',0
        mkeyw   'xoff',xoff
        mkeyw   'xon',xon

BStab   db      2                       ;Two entries [19c start]
        mkeyw   'Backspace',0
        mkeyw   'Delete',1

bdtab   db      16              ; 16 entries
        mkeyw   '110',b0110
        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   '600',b0600
        mkeyw   '75',b0075
        mkeyw   '9600',b9600

termtb  db      tttypes+1               ; entries for Status, not Set
        mkeyw   'Heath-19',ttheath
        mkeyw   'None',ttgenrc
        mkeyw   'VT100',ttvt100         ; alias for VT102
        mkeyw   'VT102',ttvt100
        mkeyw   'VT52',ttvt52           ; [jrd]


ten     dw      10                      ; multiplier for setatoi
rdbuf   db      80H DUP(?)              ; scratch string area [jrd]
dmpname db      'KERMIT.SCN',54 dup (0) ; file name for screen dumps [jrd]
prm     db      30 dup(0)               ; Buffer for new prompt.
prmptr  dw      kerm                    ; pointer to prompt
defkw   db      256 dup (?)             ; room for macro name and body
macnum  dw      0                       ; one macro yet
mactab  dw      ibmmac                  ; default ibm mac is macro 0
        dw      macmax dup (?)          ; empty macro table
defptr  dw      macbuf
macbuf  db      macmax*100 dup (?)      ; buffer for macro defs
macbend label   byte                    ; marker for end of macro buffer
rmlft   db      macmax*10               ; space left in set table
mcctab  db      1                       ; macro name table, one initially
        mkeyw   'IBM',0                 ; macro # 0
        db      macmax*10 dup (?)       ; room for rest of macro names
shom9a  db      cr,lf,' Free space: name entries: $'
shom9b  db      ', name characters: $'
shom9c  db      ', body characters: $'

ibmmac  db      imlen-1
        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

; 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   <msg2,cm2st,cm1st,flags.comflg>
        stent   <onoff,modst,,flags.modflg>
        stent   <srchkw,parmsg,partab,parflg,portval>
        stent   <stnum,pacemsg,,spause>
        stent   <onoff,locst,,ecoflg,portval>
        stent   <stnum,stimst,,dtrans.stime>
        stent   <msg2,flost,floxmsg,floflg,portval>
        stent   <onechr,ssohst,,trans.ssoh>
        stent   <prhnd>
        stent   <stnum,spakst,,trans.spsiz>
        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   <stnum,rpakst,,trans.rpsiz>
        stent   <msg2,beloff,belon,flags.belflg>
        stent   <stnum,rnpdst,,trans.rpad>
        stent   <onoff,capmsg,,flags.capflg>
        stent   <onechr,rqcst,,dtrans.squote>
        stent   <onoff,timmsg,,flags.timflg>
        stent   <onechr,eolst,,dtrans.seol>
        stent   <onoff,debon,,flags.debug>
        stent   <pr8bit>
        stent   <onechr,escmes,,trans.escchr>
        stent   <srchkw,blokst,blktab,trans.chklen>
        stent   <srchkw,dispst,notontab,flags.remflg>
        stent   <dmpstat,dmpmsg>
;;;     stent   <srchkw,remost,ontab,flags.remflg>
        stent   <vtstat>                        ; Terminal status, in MSX
        dw      0                                       ; end of table


sttbuf  db      82 dup (?)      ; buffer for Status display line [jrd]
datas   ends

code    segment public
        extrn cmcfrm:near, prserr:near, comnd:near, dobaud:near
        extrn cmgtch:near, repars:near, coms:near, defkey:near
        extrn inicpt:near, prompt:near, nout:near, prtscr:near
        extrn prkey:near, getbaud:near, isfile:near, strlen:near
        extrn strcpy:near
        extrn vts:near, vtstat:near
        assume  cs:code,ds:datas

; DO command

DOCOM   PROC    NEAR
        mov     dx,offset mcctab
        mov     bx,0
        mov     ah,cmkey
        call    comnd
         jmp    r
        push    bx
        mov     ah,cmcfm
        call    comnd
         pop    bx
         ret
         nop
        pop     bx
        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
        shl     bx,1
        mov     si,mactab[bx]           ; point to macro
        mov     cl,[si]                 ; get size from macro
        mov     ch,0
        inc     si                      ; point to actual definition
        mov     bx,takadr               ; point to current buffer
        mov     [bx].taktyp,0ffh        ; flag as a macro [jrd]
        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 command

DODEF   PROC    NEAR
        cmp     macnum,macmax           ; get current macro count
        jl      dode1                   ; no, go on
        mov     dx,offset ermes1        ; else complain
        jmp     reterr                  ; and return

dode1:  mov     ah,cmtxt
        mov     bx,offset defkw+1       ; buffer for keyword
        mov     dx,offset macmsg
        call    comnd
         ret
         nop
         nop
        cmp     ah,0
        jne     dode2
        ret
dode1a: mov     dx,offset erms23        ; null input not allowed
        jmp     reterr

dode2:  mov     bx,ds                   ; address data segment
        mov     es,bx
        cld                             ; strings go forward
        mov     cl,ah
        mov     ch,0                    ; length
        mov     di,offset defkw+1       ; pointer to keyword
        mov     ah,0                    ; # of chars in keyword
        jcxz    dode1a                  ; empty keyword, complain
        mov     al,' '
        repe    scasb                   ; skip leading blanks
        je      dode1a                  ; all blanks,
        lea     si,[di-1]               ; back up to non-blank
        inc     cx                      ; going to look at it again...
; uppercase keyword, look for end
dode3:  lodsb                           ; get a byte
        cmp     al,'a'
        jb      dode4
        cmp     al,'z'
        ja      dode4
        sub     al,'a'-'A'
        mov     [si-1],al               ; uppercase if necessary
dode4:  inc     ah                      ; increment word count
        cmp     al,' '                  ; is it the break character?
        loopne  dode3                   ; no, loop thru rest of word
dode5:  jne     dode6                   ; ended with break char?
        dec     ah                      ; yes, don't count in length
dode6:  mov     defkw,ah                ; store length in front of it
        add     ah,4                    ; add keyword overhead length
        cmp     ah,rmlft                ; will it fit in buffer?
        jb      dode7                   ; yes, keep going

        mov     dx,offset ermes2        ; else complain
        jmp     reterr

dode7:  mov     bx,defptr               ; free def space
        add     bx,cx                   ; add length of new def'n
        cmp     bx,offset macbend       ; past end?
        jb      dode7a                  ; no, ok to add it
        mov     dx,offset ermes2
        jmp     reterr                  ; won't fit, complain

dode7a: sub     rmlft,ah                ; subtract space used in tbl
        mov     di,defptr               ; pointer to free space
        inc     macnum                  ; count the macro
        mov     bx,macnum
        shl     bx,1                    ; double for word idx!!!
        mov     mactab[bx],di           ; install into table
        mov     [di],cl                 ; store length
        inc     di
        jcxz    dode10                  ; no copy if 0 length

; copy definition into buffer, changing commas to crs
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

dode10: mov     defptr,di               ; update free ptr
        mov     bl,defkw
        mov     bh,0
        lea     di,defkw+1[bx]          ; end of keyword
        mov     al,'$'
        stosb
        mov     ax,macnum
        stosb                           ; low-order
        mov     al,0                    ; high-order is always 0.
        stosb

; now install into table
        mov     bx,offset mcctab
        mov     dx,offset defkw
        call    addtab
        jmp     rskp
DODEF   ENDP

; add an entry to a keyword table
; enter with bx/ table address, dx/ ptr to new entry
; no check is made to see if the entry fits in the table.
addtab  PROC    NEAR
        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...
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,4            ; overhead bytes
        rep     movsb           ; stick it in
        pop     es
        ret                     ; and return
addtab  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 setco2
         nop
setco1: jmp rskp
setco2: cmp comand.cmstat,cmcfm         ; is there a confirm at the end?
        je setco1
        ret
SETCOM  endp


;   SET BAUD or SET SPEED.

BAUDST  PROC    NEAR
        mov dx,offset bdtab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp bau0               ; Didn't get one.
         nop
        pop bx
        mov si,portval
        mov ax,[si].baud        ; Remember original value. [25]
        mov [si].baud,bx        ; Set the baud rate.
        call dobaud             ; Use common code. [19a]
        ret
bau0:   pop bx
        ret
BAUDST  ENDP

; SET BELL on or off.    [17a start]

BELLST  PROC    NEAR
        mov dx,offset ontab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd
         jmp bel0
         nop
        pop bx
        mov flags.belflg,bl
        ret
bel0:   pop bx
        ret
BELLST  ENDP                     ;    [17a end]

; SET BLOCK-CHECK

BLKSET  PROC    NEAR
        mov dx,offset blktab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp blk0               ; Didn't get a confirm.
         nop
        pop bx
        mov trans.chklen,bl     ; Use this char as the handshake.
        mov inichk,bl           ; Save here too.
        ret
blk0:   pop bx
        ret
BLKSET  ENDP

; SET DEBUG mode on or off.

DEBST   PROC       NEAR
        mov dx,offset ontab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp deb0               ; Didn't get a confirm.
         nop
        pop bx
        mov flags.debug,bl      ; Set the DEBUG flag.
        ret
deb0:   pop bx
        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
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp des0               ; Didn't get a confirm.
         nop
        pop bx
        mov flags.destflg,bl    ; Set the destination flag.
        cmp bl,2                ; Is dest the screen? [27c]
        jne desa                ; No, then done. [27c]
        mov flags.xflg,1        ; Remember it here. [27c]
        ret
desa:   mov flags.xflg,0        ; Don't write to screem [27c]
        ret
des0:   pop bx
        ret
DESSET  ENDP

; SET DEFAULT-DISK    for sending/receiving, etc.

DSKSET  PROC    NEAR
        mov comand.cmcr,1       ; Don't want filename specified.
        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
dsk1:   mov bx,offset rdbuf
        mov ah,[bx]             ; 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 [jrd]
        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          ; check if we 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 DISPLAY ON/OFF      (inverse of Set Remote on/off)
disply  proc    near
        call    remset          ; call the Set Remote Command
         jmp r                  ; error return
        mov     bl,flags.remflg ; get the pertinent flag
        xor     bl,1            ; invert sense of flag (uses on/off = 1/0)
        mov     flags.remflg,bl ; and store it
        jmp     rskp            ; return normally
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                ; get a confirm
;;      call    comnd
;;       jmp    r                       ; no confirm
        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
        jmp     rskp
setdmp  endp

; SET EOF

seteof  proc    near
        mov ah,cmkey
        mov bx,0
        mov dx,offset seoftab
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd
         jmp seteo1             ; error return...
         nop
        pop bx
        mov flags.eofcz,bl      ; set value
        jmp rskp                ; and return
seteo1: pop bx
        ret
seteof  endp

; SET EOL char

EOLSET  PROC    NEAR
        mov min,0               ; lowest acceptable value. [jrd]
        mov max,1FH             ; largest acceptable value. [jrd]
        mov sum,0               ; accumulated value. [jrd]
        mov tmp,10              ; base 10 arithmetic
        mov temp1,0             ; flag for number building in progress. [jrd]
        mov desta,offset dtrans.seol    ; destination address for value. [jrd]
        mov numhlp,offset eolhlp        ; help message address. [jrd]
        mov numerr,offset eolerr        ; error message address. [jrd]
        mov ah,0
        call num0               ; get numerical input. [jrd]
        mov comand.cmstat,cmcfm ;simulate a confirm has been requested. [jrd]
        ret                     ; [jrd]
EOLSET  ENDP

; Common routine for parsing numerical input.
; Annotation added by [jrd].

num0:   call cmgtch             ; Get a user's input char into AH. [jrd]
        cmp ah,0                ; terminator (bit 8 set)? [jrd]
        js num1                 ; s = sign set = yes. [jrd]
        cmp ah,'0'              ; between 0 and 9 (ascii)? [jrd]
        jl num1                 ; l = no. [jrd]
        cmp ah,'9'
        ja num1                 ; a = no. [jrd]
        mov temp1,1             ; say number building has commenced. [jrd]
        sub ah,'0'              ; remove ascii bias: char minus '0'. [jrd]
        mov dl,ah               ; save input binary value. [jrd]
        mov al,sum              ; multiply current sum by 10. [jrd]
        mul tmp                 ; 10 (tmp, byte) times AL put into AL. [jrd]
        add al,dl
        mov sum,al              ; sum = (old sum)*10 + (new value). [jrd]
        jmp num0                ; read another user character. [jrd]

num1:   and ah,7FH              ; Examine non-numerical input char. [jrd]
        cmp ah,cr
        jne num2                ; ne = not a cr. [jrd]
        cmp temp1,0             ; number building in progress? [jrd]
        je num21                ; e = not yet. [jrd]
        mov al,sum              ; well let's see if it's within specs. [jrd]
        cmp al,min
        jl num3                 ; l = below minimums (shoddy worksmanship)[jrd]
        cmp al,max
        jg num3                 ; g = above maximums (too rich for us). [jrd]
        mov bx,desta            ; Ah, it fits. Get destination address. [jrd]
        mov [bx],al             ; save result there and return. [jrd]
        ret

num2:   cmp ah,03FH             ; Question mark?
        je num4
num21:  mov ah,prstr
        mov dx,offset ermes3    ; "?Not confirmed" [jrd]
        int dos
        jmp prserr              ; can't parse that string. [jrd]
num3:   mov ah,prstr
        mov dx,numerr           ; get address of numeric error message. [jrd]
        int dos
        jmp prserr              ; can't parse that string. [jrd]
num4:   mov ah,prstr            ; user typed a question mark. [jrd]
        mov dx,numhlp           ; address of help message. [jrd]
        int dos
        mov dx,offset crlf
        int dos
        mov dx,comand.cmprmp    ; redisplay command prompt. [jrd]
        int dos
        mov bx,comand.cmdptr
        mov al,'$'              ; for DOS display. [jrd]
        mov [bx],al             ; terminate input to date (before '?'). [jrd]
        mov dx,offset comand.cmdbuf
        int dos                 ; display input to date (before '?'). [jrd]
        dec comand.cmcptr               ; Don't count the dollar sign.
        dec comand.cmccnt               ; Or the question mark.
        mov comand.cmaflg,0             ; Check for more input.
        jmp repars

; SET ESCAPE character.     [6 start]

ESCAPE  PROC    NEAR
        call cmgtch             ; Get a char.
        cmp ah,0
        jns es1                 ; Terminator or no?
        and ah,7FH              ; Turn off minus bit.
        cmp ah,'?'
        jne es0
        mov dx,offset eschlp
        mov ah,prstr
        int dos
        mov dx,offset crlf
        int dos
        mov dx,comand.cmprmp
        int dos
        mov bx,comand.cmdptr
        mov al,'$'
        mov [bx],al
        mov dx,offset comand.cmdbuf
        int dos
        dec comand.cmcptr               ; Ignore dollar sign.
        dec comand.cmccnt
        mov comand.cmaflg,0
        jmp repars
es0:    mov ah,prstr
        mov dx,offset ermes3
        int dos
        ret
es1:            mov temp,ax
        mov ah,cmcfm
        call comnd
         jmp es0
         nop                    ; Take up 3 bytes.
        mov ax,temp
        mov trans.escchr,ah     ; Save new value.
        ret
ESCAPE  ENDP                    ; [6 end]

; SET FILEWARNING

FILWAR  PROC    NEAR
        mov dx,offset ontab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp fil0               ; Didn't get a confirm.
         nop
        pop bx
        mov flags.flwflg,bl     ; Set the filewarning flag.
        ret
fil0:   pop bx
        ret
FILWAR  ENDP

; SET FLOW-CONTROL

FLOSET  PROC    NEAR
        mov dx,offset flotab
        xor bx,bx
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp flox               ; Didn't get a confirm.
         nop
        pop bx
        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
flox:   pop bx
        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 [jrd]
        mov ah,cmkey
        call comnd
         jmp r
        cmp bl,0ffh             ; want a general char code? [jrd]
        jne hnd1                ; ne = no
        call hnd2               ; yes, get numerical input
        mov bx,temp             ; recover binary value
hnd1:   push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp hndx               ; Didn't get a confirm.
         nop
        pop 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

hnd2:   mov min,0                       ; get decimal char code [jrd]
        mov max,31                      ; range is 0 to 31 decimal
        mov sum,0
        mov tmp,10
        mov desta,offset temp           ; where result is stored
        mov numhlp,offset hnd2hlp       ; help message.
        mov numerr,offset hnderr        ; error message
        mov temp1,0
        jmp num0                ; Common routine for parsing numerical input.

hndx:   pop bx
        ret
HNDSET  ENDP

;   SET INCOMPLETE file disposition

ABFSET  PROC    NEAR
        mov dx,offset abftab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp abf0               ;  Didn't get a confirm.
         nop
        pop bx
        mov flags.abfflg,bl     ; Set the aborted file flag.
        ret
abf0:   pop bx
        ret
ABFSET  ENDP

; SET KEY

setkey  proc    near
        cmp     setktab,0       ; any table?
        jne     setk0           ; yes, use it
        mov     dx,offset ermes5
        jmp     reterr          ; else print error message
setk0:  mov     dx,offset setktab       ; set key options
        mov     bx,offset setkhlp
        mov     ah,cmkey
        call    comnd
         jmp    r
        cmp     bx,-1           ; do we have scan code?
        jne     setk1           ; yes, skip this part

        mov     ah,cmtxt
        mov     bx,offset rdbuf ; handy buffer
        mov     dx,offset sk1msg
        call    comnd
         jmp    r               ; fail return
        mov     si,offset rdbuf ; this is parsed number
        call    atoi            ; Convert input to real number.
         jmp    reterr          ; No good.
        mov     bx,ax           ; put accumulation into bl
setat3: cmp     bx,0            ; is scan code 0?
        jne     setk2           ; no, have scan code, look for def

setk1:  push    bx              ; save our scan code
        mov     ah,cmcfm
        call    comnd
         jmp    short setkx     ; no good, pop bx and return
        nop                     ; waste a byte
        pop     bx
; scan code is in bl, ask for string part
setk2:  push    bx
        mov     dx,offset defpmp
        call    prompt
        mov     ah,cmtxt
        mov     bx,offset rdbuf
        mov     dx,offset sk2msg
        call    comnd           ; read the definition
         jmp    short setkx     ; pop bx and fail return
         nop
        mov     cl,ah
        mov     ch,0            ; set up length of definition
        pop     ax              ; get scan code back
        mov     si,offset rdbuf ; point to definition
        call    defkey          ; go define the key
        jmp     rskp            ; and return
setkx:  pop     bx              ; pop junk off stack
        ret                     ; and return
setkey  endp

; SET LOCAL

LCAL    PROC    NEAR
        mov dx,offset ontab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx                 ; Save the parsed value.
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp lcl0               ;  Didn't get a confirm.
         nop
        pop bx
        mov si,portval
        mov [si].ecoflg,bl       ; Set the local echo flag.
        ret
lcl0:   pop bx
        ret
LCAL    ENDP

; SET LOG   filename
;   addition for capture of raw output
; revised by [jrd] to use full DOS 2.0 path name

setcpt  proc    near
        test    flags.capflg,0FFH
        jz      setcp1                  ; no capture file, keep going
        mov     dx,offset erms24
        jmp     reterr
setcp1: mov     dx,offset cptio.string  ; holds the complete filename
        mov     bx,offset filhlp
        mov     ah,cmfile               ; allow paths
        call    comnd
         jmp    r
        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? [jrd]
        jc      setcp3                  ; c = does not exist. [jrd]
        test    byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
        jnz     setcp2                  ; nz = no.
        mov     ah,open2                ; open existing file. [jrd]
        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
        mov     flags.capflg,0FFH       ; say capture routine is active
        jmp     rskp                    ; and return

setcp3: 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     flags.capflg,0FFH       ; say capture routine is active
        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
        push    bx                      ; save value
        mov     ah,cmcfm
        call    comnd
         pop    bx                      ; isn't this horrible?
         ret
         nop
        pop     bx
        mov     flags.modflg,bl         ; set flag appropriately
        jmp     rskp                    ; and return
MODL    ENDP

; SET PARITY.                           [10 start]

SETPAR  PROC    NEAR
        mov dx,offset partab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp par0               ;  Didn't get a confirm.
         nop
        pop bx
        mov si,portval
        mov [si].parflg,bl      ; Set the parity flag.
        cmp bl,parnon           ; Resetting parity to none? [21b]
        je setp0                ; Yes, reset 8 bit quote character. [21b]
        mov trans.ebquot,dqbin  ; Else, do quoting.    [21b]
        ret                     ; That's it.  [21b]
setp0:  mov trans.ebquot,'Y'    ; If none, say will quote upon request. [21b]
        ret
par0:   pop bx
        ret
SETPAR  ENDP                                                    ; [10 end]

; SET PROMPT      Allow user to change the "Kermit-MS>" prompt.

PROMSET PROC    NEAR
        mov ah,cmtxt
        mov bx,offset prm               ; Read in the prompt.
        mov dx,offset prmmsg
        call comnd
         jmp r
        cmp ah,0                        ; Just a bare CR?
        jne prom0
        mov ax,offset kerm
        jmp prom1
prom0:  mov byte ptr [bx],'$'           ; End of string.
        mov ax,offset prm
prom1:  mov prmptr,ax                   ; Remember it.
        jmp rskp
PROMSET ENDP

; SET TAKE-ECHO  on or off.

TAKSET  PROC    NEAR
        mov dx,offset ontab
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd
         jmp tak0
         nop
        pop bx
        mov flags.takflg,bl
        ret
tak0:   pop bx
        ret
TAKSET  ENDP                     ;    [17a end]

; 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
        push bx
        mov ah,cmcfm
        call comnd
         jmp tim0
         nop
        pop bx
        mov flags.timflg,bl
        ret
tim0:   pop bx
        ret
TIMSET  ENDP                     ;    [17a end]

; SET SEND parameters

SENDSET PROC    NEAR
        mov stflg,'S'           ; Setting SEND parameter
sndst0: mov dx,offset stsrtb    ; Parse a keyword.
        mov bx,0
        mov ah,cmkey
        call comnd
         jmp r
        call bx
         nop
         nop
         nop
        jmp rskp
SENDSET ENDP

; SET RECEIVE parameters

recset: mov stflg,'R'           ; Setting RECEIVE paramter.
        jmp sndst0

remset  proc    near
        mov     ah,cmkey
        mov     dx,offset ontab
        mov     bx,0
        call    comnd
         jmp    r
        push    bx              ; save parsed value
        mov     ah,cmcfm
        call    comnd           ; confirm
         pop    bx
         ret                    ; return on failure
         nop
        pop     bx
        mov     flags.remflg,bl ; set remote setting
        jmp     rskp            ; and return
remset  endp

; SET SEND and RECEIVE start-of-header.

srsoh:  mov min,0
        mov max,1FH
        mov sum,0
        mov tmp,10
        mov desta,offset trans.ssoh     ; Assume SEND.
        cmp stflg,'S'                   ; Setting SEND paramter?
        je srsoh0
        mov desta,offset trans.rsoh
srsoh0: mov numhlp,offset eolhlp        ; Reuse help message.
        mov numerr,offset soherr
        mov temp1,0
        jmp num0                ; Common routine for parsing numerical input.

; SET SEND and RECEIVE TIMEOUT.

srtim:  mov min,0
        mov max,94
        mov sum,0
        mov tmp,10
        mov desta,offset dtrans.stime   ; Assume SEND.
        cmp stflg,'S'                   ; Setting SEND paramter?
        je srtim0
        mov desta,offset trans.rtime
srtim0: mov numhlp,offset timhlp        ; Reuse help message.
        mov numerr,offset timerr
        mov temp1,0
        jmp num0                ; Common routine for parsing numerical input.

; SET SEND and RECEIVE PACKET LENGTH.

srpack: mov min,20
        mov max,94
        mov sum,0
        mov tmp,10
        mov desta,offset trans.spsiz
        cmp stflg,'S'           ; Setting SEND paramter?
        je srpak0
        mov desta,offset trans.rpsiz
srpak0: mov numhlp,offset pakhlp
        mov numerr,offset pakerr
        mov temp1,0
        jmp num0                ; Parse numerical input.

; SET SEND and RECEIVE number of padding characters.

srnpd:  mov min,0
        mov max,99
        mov sum,0
        mov tmp,10
        mov desta,offset dtrans.spad
        cmp stflg,'S'           ; Setting SEND paramter?
        je srnpd0
        mov desta,offset trans.rpad
srnpd0: mov numhlp,offset npdhlp
        mov numerr,offset npderr
        mov temp1,0
        jmp num0                ; Parse numerical input.

; SET SEND and RECEIVE padding character.

srpad:  mov min,0
        mov max,127
        mov sum,0
        mov tmp,10
        mov srtmp,0FFH          ; Haven't seen anything yet.
        mov desta,offset srtmp
        mov numhlp,offset padhlp
        mov numerr,offset paderr
        mov temp1,0
        mov savsp,sp
        call num0               ; Parse numerical input.
        mov sp,savsp
        mov temp,offset trans.spadch
        cmp stflg,'S'
        je srpad1
        mov temp,offset trans.rpadch
srpad1: mov bx,offset srtmp
        mov ah,[bx]
        cmp ah,0FFH             ; Did they end up not doing the command?
        je srpad3
        cmp ah,127              ; This is allowed.
        je srpad2
        cmp ah,32
        jb srpad2               ; Between 0 and 31 is OK too.
        mov ah,prstr
        mov dx,offset paderr
        int dos
        ret
srpad2: mov bx,temp             ; Set the real pad char.
        mov [bx],ah
srpad3: ret

; SET SEND and RECEIVE control character prefix.

srquo:  mov min,33
        mov max,126
        mov sum,0
        mov tmp,10
        mov desta,offset trans.rquote   ; Used for outgoing packets.
        cmp stflg,'S'                   ; Setting outgoing quote char?
        je srquo0
        mov desta,offset dtrans.squote  ; For incoming quote char.
srquo0: mov numhlp,offset quohlp
        mov numerr,offset quoerr
        mov temp1,0
        jmp num0                        ; Parse numerical input.

; SET SEND Pause number of milliseconds         ; [jrd]

srpaus: mov min,0
        mov max,127
        mov sum,0
        mov tmp,10
        mov desta,offset spause
        cmp stflg,'S'           ; Setting SEND paramter?
        je srpau0
        jmp r                   ; parse error if Receive Pause
srpau0: mov numhlp,offset pauhlp
        mov numerr,offset pauerr
        mov temp1,0
        jmp num0                ; Parse numerical input.


; Convert input in buffer pointed to by SI to real number which is returned
; in AX.  Enter with string size in AX.
; Return on failure, return skip on success.      Revised by [jrd]
ATOI    PROC    NEAR
        mov     bx,0            ; high order of this stays 0. [jrd]
        mov     tmp,0           ; No input yet. [27f]
        mov     cl,ah           ; Number of chars of input.
        mov     ch,0            ; size of string
        mov     ax,0            ; init sum
        jcxz    atoi4           ; Fail on no input.
atoi0:  xchg    al,bl           ; save current sum in bl
        lodsb                   ; grab a byte
        cmp     al,' '          ; leading space?
        jne     atoi1           ; no, continue
        xchg    al,bl           ; put sum back into al
        jmp     short atoi2     ; and continue loop
atoi1:  xchg    al,bl           ; put sum back into al
        cmp     bl,'9'
        ja      atoi5           ; out of range, fail
        cmp     bl,'0'
        jb      atoi5
        mul     ten             ; current sum * 10. dx = high, ax = low
        sub     bl,'0'          ; convert to binary
        add     ax,bx           ; add to sum
        mov     tmp,1           ; Got some legal input. [27f]
atoi2:  loop    atoi0           ; loop thru all chars
        cmp     tmp,0           ; Anything besides spaces? [27f]
        je      atoi4           ; No so fail. [27f]
        jmp     rskp
atoi4:  mov     dx,offset erms23        ; complain and return
        ret
atoi5:  mov     dx,offset erms25        ; Input must be numeric
        ret
ATOI    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.
        jne shom2               ; No, he wants specific macro expanded.
        mov si,offset mcctab    ; Table of macro names.
        lodsb
        mov cl,al               ; Number of macro entries.
        mov ch,0
shom0:  jcxz shom1              ; 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
        int dos
        pop ax
        mov ah,0
        add si,ax               ; Skip over name.
        inc si                  ; Get to macro number.
        mov bx,[si]             ; Pick it up.
        call expmac             ; Expand the macro.
        dec cx
        add si,2                ; Skip over macro number.
        jmp shom0               ; And do the rest.
shom1:  mov ah,prstr
        mov dx,offset shom9a    ; free space: name entries
        int dos
        mov ax,macmax
        sub ax,macnum           ; compute # of free name entries
        call nout
        mov ah,prstr
        mov dx,offset shom9b    ; name characters
        int dos
        mov al,rmlft
        mov ah,0
        call nout
        mov ah,prstr
        mov dx,offset shom9c    ; body characters
        int dos
        mov ax,offset macbend
        sub ax,defptr
        call nout
        mov ah,prstr
        mov dx,offset crlf
        int dos
        jmp rskp
shom2:  mov ah,prstr
        mov dx,offset ermes3
        int dos
        jmp rskp
SHOMAC  ENDP

; Expand the macro, called with BX/macro number.
expmac: push si
        push cx
        mov si,offset mactab    ; Table of address expansions.
        shl bx,1                ; Double and use as index into table.
        mov si,[si+bx]          ; Get address of expansion in question.
        mov ax,si               ; Address of string.
        inc ax                  ; Don't print length.
        mov cl,[si]             ; Length of string.
        mov ch,0
        call prkey              ; Print it.
        pop cx
        pop si
        ret

; 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 is an external ref (in msterm.asm)
STAT0:  mov dx,offset crlf
        mov ah,prstr
        int dos                 ; print an initial crlf
        push    es              ; save es
        mov     ax,ds
        mov     es,ax           ; address data segment
        cld                     ; string direction is forward
        mov     di,offset sttbuf ; point to destination buffer
        mov     bx,offset sttab ; table to control printing
        mov     al,' '          ; start with a space
        stosb                   ; put it into the buffer
        stosb                   ; and another (two leading spaces) [jrd]
        mov     ax,0            ; say new line not finished
stat01: cmp     word ptr [bx],0 ; end of table?
        je      stat03          ; safety [jrd]
        push    bx
        push    di              ; remember important values
        push    ax
        call    [bx].sttyp      ; call the appropriate routine
        pop     ax
        pop     cx              ; return buffer value
        pop     bx              ; and ptr
        or      ax,ax           ; do we need a newline?
        jne     stat03          ; yes, go put one in
        sub     cx,di           ; else see how many columns they used
        add     cx,37           ; this is where we'd like to be
        jge     stat02          ; if cx is negative here, we have a problem...
        mov     cx,1            ; make cx non-negative
        mov     di,offset sttbuf
        jmp     stat06          ; someone used a whole line
stat02: mov     al,' '
        rep     stosb           ; add right # of spaces
        mov     ax,1            ; note we need a newline next time
        jmp     short stat05    ; and keep looping around

stat03: mov     cx,4
        mov     si,offset crlfsp ; cr lf space space [jrd]
        rep     movsb           ; append crlf to string
        mov     cx,di           ; current buffer address
        mov     ax,offset sttbuf; buffer start address
        mov     di,ax           ; point to start of buffer
        sub     cx,ax           ; cx = char count
        call    prtscr          ; print the line
stat06: xor     ax,ax           ; reset newline flag [jrd]
        cmp     word ptr [bx],0 ; at end of the table;
        je      stat04          ; e = yes.
        add     bx,size stent   ; look at next entry
        cmp     word ptr [bx],0 ; at end of the table;
        jne     stat01          ; ne = no.
stat04: pop     es
        jmp rskp

stat05: add     bx,size stent   ; advance to next one
        cmp     word ptr [bx],0 ; end of table?
        jne     stat01          ; ne = no
        je      stat03          ; e = yes, dump last line
STATUS  ENDP

; handler routines for status
; all are called with di/ destination buffer, bx/ stat ptr.     They
; can change any register but the segment registers, must update
; di to the end of the buffer.

; copy the message into the buffer
stmsg   proc    near
        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                     ; and return
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                     ; and return
onechr  endp

; numeric field...
stnum   proc    near
        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                     ; and return
stnum   endp

; 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                     ; and return
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                     ; and return
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
        add     al,'@'          ; Make it printable.
        stosb
        mov     byte ptr [di],':'
        inc     di              ; end with a colon
        ret                     ; and return
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
        stosb                   ; store in buffer
        cmp     al,0            ; at end yet?
        jne     dmpstat1
        ret
dmpstat endp

; print 8-bit quoting
pr8bit  proc    near
        mov     bl,trans.ebquot ; get quote char
        mov     si,offset ebyst ; assume no 8-bit quoting
        cmp     bl,'Y'          ; on request only?
        je      pr8bi1          ; yes, continue
        mov     si,offset ebvst ; else variable
pr8bi1: call    stms1           ; copy message in
        cmp     bl,'Y'          ; not doing it?
        je      pr8bi2          ; no, forget this part
        mov     [di],bl         ; else drop off char too
        inc     di
pr8bi2: ret                     ; and return
pr8bit  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
prtt2:  jmp stms1               ; copy in message
        ret                     ; and return

; print the escape character in readable format.

ESCPRT  PROC    NEAR            ; [6 start]
        mov dl,trans.escchr
        cmp dl,' '
        jge escpr2
        push dx
        mov ah,prstr
        mov dx,offset esctl
        int dos
        pop dx
        add dl,040H             ; Make it printable.
escpr2: mov ah,conout
        int dos
        ret
ESCPRT  ENDP                    ; [6 end]

; Print the baud rate. [19a]

BAUDPRT PROC     NEAR
        call getbaud            ; read baud rate first
        mov si,portval
        mov ax,[si].baud
        mov dx,offset b48st     ; Assume 4800 baud.
        cmp ax,B4800
        jnz bdprt0
        jmp bdprt2
bdprt0: mov dx,offset b12st
        cmp ax,B1200
        jnz bdprt1
        jmp bdprt2
bdprt1: mov dx,offset b18st
        cmp ax,B1800
        jz bdprt2
        mov dx,offset b24st
        cmp ax,B2400
        jz bdprt2
        mov dx,offset b96st
        cmp ax,B9600
        jz bdprt2
        mov dx,offset b03st
        cmp ax,B0300
        jz bdprt2
        mov dx,offset b04st
        cmp ax,B00455
        jz bdprt2
        mov dx,offset b05st
        cmp ax,B0050
        jz bdprt2
        mov dx,offset b07st
        cmp ax,b0075
        jz bdprt2
        mov dx,offset b11st
        cmp ax,B0110
        jz bdprt2
        mov dx,offset b13st
        cmp ax,B01345
        jz bdprt2
        mov dx,offset b15st
        cmp ax,B0150
        jz bdprt2
        mov dx,offset b06st
        cmp ax,B0600
        je bdprt2
        mov dx,offset b20st
        cmp ax,B2000
        jz bdprt2
        mov dx,offset b19st
        cmp ax,B19200
        jz bdprt2
        mov dx,offset b38st
        cmp ax,B38400
        jz bdprt2
        mov dx,offset unrec     ; Unrecognized baud rate.
bdprt2: mov si,offset baudrt    ; "Baud rate is"
        call stms1              ; display that part
        mov si,dx               ; this is baud rate itself
        jmp stms1               ; go copy it and return
BAUDPRT 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


