home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msr313src.zip / msssho.asm < prev    next >
Assembly Source File  |  1993-07-12  |  93KB  |  3,238 lines

  1.     name    msssho
  2. ; File MSSSHO.ASM
  3.     include mssdef.h
  4. ;  Copyright (C) 1985, 1993, Trustees of Columbia University in the 
  5. ;  City of New York.  Permission is granted to any individual or institution
  6. ;  to use this software as long as it is not sold for profit.  This copyright
  7. ;  notice must be retained.  This software may not be included in commercial
  8. ;  products without written permission of Columbia University.
  9. ;
  10. ; Show & Status commands
  11. ; edit history:
  12. ; 27 August 1992 version 3.13
  13. ; 6 Sept 1991 version 3.11
  14. ; Last edit 5 Feb 1992
  15.  
  16.     public    shorx, shomac, shcom, shfile, shlog, shpro, shscpt, shserv
  17.     public    shterm, status, statc, stat0, srchkw, srchkww, srchkb, shmem
  18.     public    partab, destab, seoftab, blktab, dmpname, lsesnam, lpktnam
  19.     public    ltranam, incstb, inactb, rxoffmsg, rxonmsg, lnout, lnouts
  20.     public    shosta, begtim, endtim, fsta, ssta    ; statistics procedures
  21.     public    rtmsg, rppos, stpos, rprpos, sppos, perpos, cxerr, frpos
  22.     public    fmtdsp, ermsg, msgmsg, init, cxmsg, intmsg, kbpr, perpr
  23.     public    winpr, windflag, pktsize, clrfln, oldkbt, oldper
  24.     public  wrpmsg, prttab, pasz, shovar, prnname, filekind, filecps
  25.     public    cntlsho
  26.  
  27. mcclen    equ    macmax*10
  28.                 ; equates for screen positioning
  29. scrser    equ    0109H        ; place for server state display line
  30. scrfln    equ    0216H        ; place for file name
  31. scrkind equ    0316h        ; Place for file kind
  32. scrpath equ    0416h        ; Place for current path
  33. scrkb    equ    0516H        ; Place for Kbytes transferred
  34. scrper    equ    0616H        ; Place for percentage transferred
  35.  
  36. scrst    equ    0816H        ; Place for status
  37. scrnp    equ    0a16H        ; Place for number of packets
  38. scrsz    equ    0b16h        ; packet size
  39. scrnrt  equ    0c16H        ; Place for number of retries
  40. screrr  equ    0d16H        ; Place for error msgs
  41. scrmsg    equ    0e16H        ; Last message position
  42. scrsp    equ    0f00H        ; Place for send packet
  43. scrrp    equ    1300H        ; Place for receive packet
  44. scrrpr    equ    1700H        ; Prompt when Kermit ends (does cr/lf)
  45. braceop    equ    7bh        ; opening curly brace
  46. bracecl    equ    7dh        ; closing curly brace
  47.  
  48. data    segment
  49.     extrn    termtb:byte, comptab:byte, portval:word,dtrans:byte,rdbuf:byte
  50.     extrn    trans:byte, curdsk:byte, flags:byte, maxtry:byte, comand:byte
  51.     extrn    spause:word, taklev:byte, takadr:word, alrhms:byte, bdtab:byte
  52.     extrn    denyflg:word, rxtable:byte, mcctab:byte, script:byte
  53.     extrn    errlev:byte, luser:byte, srvtmo:byte, mccptr:word, thsep:byte
  54.     extrn    scpbuflen:word, setchtab:byte, xfchtab:byte, xftyptab:byte
  55.     extrn    tfilsz:word, diskio:byte, tloghnd:word, dosnum:word
  56.     extrn    templp:byte, windused:byte, numpkt:word, verident:byte
  57.     extrn    decbuf:byte, flotab:byte, warntab:byte, valtab:byte
  58.     extrn    valbuf:byte, xfertab1:byte, xfertab2:byte, outpace:word
  59.     extrn    winusedmax:byte, protlist:byte
  60.  
  61. crlf    db       cr,lf,'$'
  62. eqs    db    ' = $'
  63. spaces    db    '    $'
  64.  
  65. outlin1 db    6 dup (' '),'$'
  66. ;;;    version appears here
  67. outlin2 db    cr,lf
  68.         db      cr,lf,'           File name:'
  69.     db    cr,lf,'           File type:'
  70.     db    cr,lf,'        Current path:'
  71.         db      cr,lf,'  KBytes transferred:'
  72.         db      cr,lf
  73.         db      cr,lf
  74.         db      cr,lf,lf
  75.         db      cr,lf,'   Number of packets:'
  76.     db    cr,lf,'       Packet length:'
  77.         db      cr,lf,'   Number of retries: 0'
  78.         db      cr,lf,'          Last error:'
  79.         db      cr,lf,'        Last message:'
  80.         db      cr,lf,'$'
  81.  
  82.  
  83. permsg    db    cr,' Percent transferred:$'
  84. perscale db    ': 0....1....2....3....4....5....6....7....8....9....10$'
  85. lastper    db    0
  86. cxzhlp    db    'X: cancel file, Z: cancel group, E: exit nicely,'
  87.     db    ' C: exit abruptly, Enter: retry$'
  88. blanks    db    10 dup (' '),'$'
  89. erword    db    cr,lf,'Error: $'
  90. msword    db    cr,lf,'Message: $'
  91. rtword    db    cr,lf,'Retry $'
  92. cxzser    db    cr,lf,' Type X to cancel file, Z to cancel group,'
  93.     db    cr,lf,' E to exit nicely, C to quit abruptly,'
  94.     db    cr,lf,' or Enter to retry',cr,lf,'$'
  95. windmsg    db    ' Window slots in use:$'
  96. windmsg2 db    ' of $'
  97. windflag db    0        ; flag to init windows msg, 0=none
  98. oldwind    db    -1        ; last windows in use value
  99. oldper    dw    0        ; old percentage
  100. oldkbt    dw    0        ; old KB transferred
  101. wrpmsg    db    0        ; non-zero if we wrote percent message
  102. fmtdsp    db    0        ; non-zero if formatted display in use
  103. prepksz    dw    0        ; previous packet size
  104. onehun    dw    100
  105. denom    dw    0
  106. temp    dw    0
  107. temp1    dw    0
  108. shmcnt    dw    0
  109. sixteen    dw    16
  110. infms1    db    'Server mode: type Control-C to exit',cr,lf,'$'
  111. infms7    db    'File interrupt',cr,lf,'$'
  112. infms8    db    'File group interrupt',cr,lf,'$'
  113. infms9    db    'User ',5eh,'  interrupt',cr,lf,'$'
  114.  
  115. partab    db    5
  116.     mkeyw    'none (8-bit data) ',PARNON
  117.     mkeyw    'even (7-bit data) ',PAREVN
  118.     mkeyw    'odd (7-bit data) ',PARODD
  119.     mkeyw    'mark (7-bit data) ',PARMRK
  120.     mkeyw    'space (7-bit data) ',PARSPC
  121.  
  122. destab    db    3
  123.     mkeyw    'Disk',1
  124.     mkeyw    'Printer',0
  125.     mkeyw    'Screen',2
  126.  
  127. seoftab    db    2
  128.     mkeyw    'Ctrl-Z',1
  129.     mkeyw    'NoCtrl-Z',0
  130.  
  131. ; What type of block check to use
  132. blktab    db    4
  133.     mkeyw    '1-char-checksum',1
  134.     mkeyw    '2-char-checksum',2
  135.     mkeyw    '3-char-CRC-CCITT',3
  136.     mkeyw    'Blank-free-2','B'-'0'
  137.  
  138. modtab    db    3                ; Mode line status
  139.     mkeyw    'off',0
  140.     mkeyw    'on',1
  141.     mkeyw    'on (owned by host)',2
  142.  
  143. ontab    db    2
  144.     mkeyw    'off',0
  145.     mkeyw    'on',1
  146.  
  147. unkctab db    2            ; unknown character-set disposition
  148.     mkeyw    'keep',0
  149.     mkeyw    'cancel',1
  150.  
  151. logsta    db    8            ; Log Status table
  152.     mkeyw    'off',logoff        ; suspended or no logging
  153.     mkeyw    'Packet',logpkt
  154.     mkeyw    'Session',logses
  155.     mkeyw    'Packet+Session',logpkt+logses
  156.     mkeyw    'Transaction',logtrn
  157.     mkeyw    'Packet+Transaction',logpkt+logtrn
  158.     mkeyw    'Session+Transaction',logses+logtrn
  159.     mkeyw    'Packet+Session+Transaction',logpkt+logses+logtrn
  160.  
  161. dissta    db    6            ; Status of Display mode
  162.     mkeyw    'Quiet, 7-bit',dquiet
  163.     mkeyw    'Regular, 7-bit',dregular
  164.     mkeyw    'Serial, 7-bit',dserial
  165.     mkeyw    'Quiet, 8-bit',dquiet+d8bit
  166.     mkeyw    'Regular, 8-bit',dregular+d8bit
  167.     mkeyw    'Serial, 8-bit',dserial+d8bit
  168.  
  169. endistab db    2            ; Server ENABLE/DISABLE status
  170.     mkeyw    'enabled',0
  171.     mkeyw    'disabled',1
  172.  
  173. inactb    db    2                ; Set Input Timeout Action
  174.     mkeyw    'Proceed',0            ;[jrs]
  175.     mkeyw    'Quit',1            ;[jrs]
  176.  
  177. incstb    db    2                ;[jrs] Set Input Case
  178.     mkeyw    'Ignore',0dfh            ;[jrs]
  179.     mkeyw    'Observe',0ffh            ;[jrs]
  180.  
  181.                 ; Statistics data storage area
  182. fsta    statinfo <>        ; for last operation values
  183. ssta    statinfo <>        ; for session values
  184. sflag    db    0        ; flag for send (1) or receive (0)
  185.                 ;   80h = begtim started
  186.  
  187. statmsg    db   cr,lf,lf,'                               Last Transfer         '
  188.     db    ' Entire Session'
  189.     db    cr,lf,'   Item                      Sent       Rec''d       '
  190.     db    ' Sent       Rec''d',cr,lf,'$'
  191. fchmsg    db    cr,lf,' File characters:    $'
  192. spmsg    db    cr,lf,' Comms port chars:   $'
  193. pktmsg    db    cr,lf,' Packets:            $'
  194. nakmsg    db    cr,lf,' NAKs:               $'
  195. retmsg    db    cr,lf,' Packet retries:     $'
  196. timemsg    db   cr,lf,lf,' Protocol time, secs:$'
  197. chpsmsg    db    cr,lf,' File characters/sec:$'
  198. spedmsg    db    cr,lf,' Comms port bits/sec:$'
  199. filemsg1 db    ' File chars/sec: $'
  200. filemsg2 db    '  Efficiency ($'
  201. filemsg3 db    ' b/s): $'
  202. sndmsg    db    'Sent ',0
  203. rcvmsg    db    'Recv ',0
  204. kind_text db    'text$'
  205. kind_binary db    'binary$'
  206. date    db    '00:00:00 00 Jan 1980',0
  207. datelen    equ    $-date-1
  208. atmsg    db    cr,lf,'  at '
  209. atlen    equ    $-atmsg
  210. fasmsg    db    ' as '
  211. faslen    equ    $-fasmsg
  212. fsucmsg    db    ', completed, bytes: ',0
  213. fbadmsg    db    ', failed, bytes: ',0
  214. fintmsg    db    ', interrupted, bytes: ',0
  215. months    db    'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP'
  216.     db    'OCT','NOV','DEC'
  217.     even
  218. tens    dd    1,10,100,1000,10000,100000,1000000,10000000,100000000
  219.     dd    1000000000
  220. tenslen    equ    ($-tens) / 4    ; number of double words in array tens
  221. lnoutsep db    0        ; non-zero to separate thousands in lnout
  222.                 ; end statistics data area
  223. sixty    dw    60
  224. ten    dw    10
  225.  
  226. logmsg    db    'Kind         Default filename          Status$'
  227. nologmsg db    '(not active)$'
  228. lsesmsg    db    'Session       (Session.log)$'
  229. lpktmsg    db    'Packets       (Packet.log)$'
  230. ltramsg    db    'Transactions  (Transact.log)$'
  231. dmpmsg    db    'Screen Dump, in Connect mode$'
  232. dmpmsg2    db    'Dump screen: $'    ; for general STATUS display
  233. prnmsg    db    'Printer name, in Connect mode: $'
  234. modst    db    'Mode-line: $'
  235. locst    db    'Local echo: $'
  236. duphlf    db    'Duplex: half$'
  237. dupful    db    'Duplex: full$'
  238. belon    db    'Ring bell after transfer$'
  239. beloff    db    'No bell after transfer$'
  240. vtemst    db    'Terminal type: $'        ; terminal emulator
  241. portst    db    'Communications port: $'
  242. capmsg    db    'Logging: $'
  243. eofmsg    db    'EOF mode: $'
  244. flost    db    'No flow control used$'
  245. floxmsg    db    'Flow control: xon/xoff $'
  246. flost1    db    'Flow control: $'
  247. handst    db    'Handshake character: $'
  248. destst    db    'Destination: $'
  249. xtypmsg    db    'File Type: $'
  250. xchmsg    db    'Transfer char-set: $'
  251. xchmsg1    db    'Transfer locking-shift: $'
  252. xchmsg2    db    'Transfer translation: $'
  253. chmsg    db    'File char set: $'
  254. unkmsg    db    'Unknown-char-set: $'
  255. diskst    db    'Dir: $'
  256. blokst    db    'Block check used: $'
  257. sqcst    db    'Send control char prefix: $'
  258. rqcst    db    'Receive control char prefix: $'
  259. debon    db    'Debug: $'
  260. flwon    db    'Collision (file name): $'
  261. parmsg    db    'Parity: $'
  262. abfdst    db    'Incomplete file: discard$'
  263. abfkst    db    'Incomplete file: keep$'
  264. sndmsg1    db    'Send Delay: $'
  265. sndmsg2    db    ' sec, Pause: $'
  266. sndmsg3    db    ' ms$'
  267. msohst    db    'Start-of-Packet char S: ',5eh,'$'
  268. meolst    db    'End-of-Packet char   S: ',5eh,'$'
  269. msrec    db    '  R: ',5eh,'$'
  270. msrecv    db    '  R: $'
  271. tmost    db    'Timeout (seconds)    S: $'
  272. stimst    db    'Send timeout (seconds): $'
  273. rtimst    db    'Receive timeout (seconds): $'
  274. spakst    db    'Send packet size (maximum): $'
  275. rpakst    db    'Receive packet size (maximum): $'
  276. spakst1    db    'Send packet size (current): $'
  277. rpakst1    db    'Receive packet size (current): $'
  278. snpdst    db    'Number of padding chars S: $'
  279. spadst    db    'Padding char S: ',5eh,'$'
  280. retrymsg db    'Retry send/receive packet limit: $'
  281. swinst    db    'Sliding window slots (max): $'
  282. dispst    db    'Display: $'
  283. timmsg    db    'Timer: $'
  284. srvmsg    db    'Timeout (sec) waiting for a transaction: $'
  285. dblmsg    db    'Send double-char: $'
  286. ignmsg    db    'Receive ignore-char: $'
  287. escmes    db    'Escape character: $'
  288. scpmsg    db    'Script commands Echo, If, Input, Output, Pause, Reinput,'
  289.     db    ' Transmit, Wait$'
  290. sechmsg    db    'Input echoing: $'
  291. scasmsg    db    'Case sensitivity: $'
  292. stmo1msg db    'Timeout (seconds): $'
  293. stmo2msg db    'Timeout-action: $'
  294. sxfilmsg db    'Transmit fill-empty-line: $'
  295. sxlfmsg db    'Transmit line-feeds-sent: $'
  296. sxpmtmsg db    'Transmit prompt character: $'
  297. sxpaumsg db    'Transmit pause (millisec): $'
  298. stbufmsg db    'INPUT-buffer-length: $'
  299. stinbmsg db    'INPUT-BUFFER follows:$'
  300. opacemsg db    'Output Pacing (millisec): $'
  301. takon    db    'Take-echo: $'
  302. atton    db    'Attributes packets: $'
  303. sachmsg    db    '  Character-set: $'
  304. sadtmsg    db    '  Date-Time: $'
  305. salnmsg    db    '  Length: $'
  306. satymsg    db    '  Type: $'
  307. baudrt    db    'Speed: $'
  308. unrec    db    'unknown$'
  309. kbdmsg    db    'Keyboard translation: $'
  310. stcntmsg db    'Take/Macro COUNT: $'
  311. stargmsg db    'Take/Macro ARGC: $'
  312. nonemsg    db    'not active$'
  313. sterlmsg db    'Errorlevel: $'
  314. stalrmsg db    'Alarm time: $'
  315. lusrmsg    db    'Login Username: $'
  316. servmsg    db    'Server commands available to remote user: $'
  317. scwdmsg    db    'CD/CWD: $'
  318. sdelmsg    db    'DELETE: $'
  319. sdirmsg    db    'DIR:    $'
  320. sfinmsg    db    'FINISH: $'
  321. sgetmsg    db    'GET:    $'
  322. shstmsg    db    'HOST:   $'
  323. skermsg    db    'KERMIT: $'
  324. slogmsg    db    'LOGIN:  $'
  325. ssndmsg    db    'MESSAGE:$'
  326. sprtmsg    db    'PRINT:  $'
  327. sspcmsg    db    'SPACE:  $'
  328. stypmsg    db    'TYPE:   $'
  329. stekmsg    db    'Term Tek4010 (auto-entry): $'
  330. nonmsg    db    'none$'
  331. onmsg    db    'on'
  332. offmsg    db    'off'
  333. moremsg    db    cr,lf,'-- More -- press space for more,'
  334.     db    ' q or Control-C to quit. $'
  335. rxoffmsg db    cr,lf,'  Input Translation is off$'
  336. rxonmsg    db    cr,lf,'  Input Translation is on$'
  337.  
  338. shormsg    db    cr,lf,'  Translation table of received byte codes while'
  339.     db    ' in CONNECT mode -'
  340.     db    cr,lf,'  Format: [received byte (decimal) -> local byte'
  341.     db    ' (decimal)]',cr,lf,'$'
  342. shopm1    db    ' [\$'            ; Show Translation material
  343. shopm2    db    ' -> \$'
  344. shopm3    db    '] $'
  345. shmmsg    db    ' name of macro, or press ENTER to see all$'
  346. shvmsg    db    ' name of \v(name) variable, or press ENTER to see all$'
  347. shom9m1    db    cr,lf,' Free space (bytes) for names: $'
  348. shom9m3    db    cr,lf,' No macro(s)$'
  349. shom9m4    db    '<cr>$'
  350. memmsg1    db    cr,lf,' DOS free memory (bytes):$'
  351. memmsg2    db    cr,lf,' Total free bytes: $'
  352. varstng    db    cr,lf,' \v($'
  353. cntlmsg1 db    cr,lf,' Unprefixed control codes (sent as-is without'
  354.     db    ' protective prefixing):',cr,lf,' $'
  355. prterr    db    '?Unrecognized value$'
  356. lpktnam    db    'Packet.log',54 dup (0)    ; default packet log filename
  357. lsesnam    db    'Session.log',54 dup (0); default capture/session filename
  358. ltranam    db    'Transact.log',52 dup (0); default transaction log filename
  359. dmpname    db    'Kermit.scn',54 dup (0)    ; file name for screen dumps
  360. prnname    db    'PRN',61 dup (0)    ; file name for printer
  361.  
  362.     even
  363. stent    struc            ; structure for status information table sttab
  364. sttyp    dw    ?        ; type (actually routine to call)
  365. msg    dw    ?        ; message to print
  366. val2    dw    ?        ; needed value: another message, or tbl addr
  367. tstcel    dw    ?        ; address of cell to test, in data segment
  368. basval    dw    0        ; base value, if non-zero
  369. stent    ends
  370.  
  371. sttab    stent    <baudprt>                ; STATUS
  372.     stent    <srchkww,vtemst,termtb,flags.vtflg>    ; terminal emulator
  373.     stent    <srchkw,portst,comptab,flags.comflg>
  374.     stent    <srchkw,modst,modtab,flags.modflg>
  375.     stent    <srchkw,parmsg,partab,parflg,portval>
  376.     stent    <stlnum,spakst,,dtrans.slong>
  377.     stent    <onoff,locst,,ecoflg,portval>
  378.     stent    <stlnum,rpakst,,dtrans.rlong>
  379.     stent    <srchkw,flost1,flotab,floflg,portval>
  380.     stent    <prsar,msohst,msrec,trans.ssoh,trans.rsoh>
  381.     stent    <prhnd>
  382.     stent    <prsar,meolst,msrec,trans.seol,trans.reol>
  383.     stent    <msg2,dupful,duphlf,duplex,portval>
  384.     stent    <prsarv,tmost,msrecv,dtrans.stime,trans.rtime>
  385.     stent    <drnum,diskst,,curdsk>
  386.     stent    <stnum,retrymsg,,maxtry>
  387.     stent    <srchkw,flwon,warntab,flags.flwflg>
  388.     stent    <srchkw,blokst,blktab,dtrans.chklen>
  389.     stent    <srchkw,destst,destab,flags.destflg>
  390.     stent    <srchkw,capmsg,logsta,flags.capflg>
  391.     stent    <msg2,abfkst,abfdst,flags.abfflg>
  392.     stent    <srchkw,debon,logsta,flags.debug>
  393.     stent    <srchkw,dispst,dissta,flags.remflg>
  394.     stent    <onoff,timmsg,,flags.timflg>
  395.     stent    <onechr,escmes,,trans.escchr>
  396.     stent    <srchkw,kbdmsg,ontab,flags.xltkbd>
  397. ;;;    stent    <vtstat>
  398.     dw    0                ; end of table
  399.  
  400. stcom    stent    <srchkw,portst,comptab,flags.comflg>    ; SHOW COMMS
  401.     stent    <baudprt>
  402.     stent    <onoff,locst,,ecoflg,portval>
  403.     stent    <srchkw,parmsg,partab,parflg,portval>
  404.     stent    <prhnd>
  405.     stent    <srchkw,flost1,flotab,floflg,portval>
  406.     stent    <msg2,dupful,duphlf,duplex,portval>
  407.     stent    <srchkw,dispst,dissta,flags.remflg>
  408.     stent    <srchkw,debon,logsta,flags.debug>
  409.     dw    0
  410.  
  411. stfile    stent    <drnum,diskst,,curdsk>            ; SHOW FILE
  412.     stent    <msg2,abfkst,abfdst,flags.abfflg>
  413.     stent    <srchkw,destst,destab,flags.destflg>
  414.     stent    <srchkw,flwon,warntab,flags.flwflg>
  415.     stent    <srchkw,eofmsg,seoftab,flags.eofcz>
  416.     stent    <srchkww,chmsg,setchtab,flags.chrset>
  417.     stent    <srchkw,xtypmsg,xftyptab,dtrans.xtype>
  418.     stent    <srchkw,xchmsg,xfchtab,dtrans.xchset>
  419.     stent    <msg2,beloff,belon,flags.belflg>
  420.     stent    <srchkw,xchmsg2,xfertab2,dtrans.xchri>
  421.     stent    <stmsg,atton>
  422.     stent    <srchkw,xchmsg1,xfertab1,dtrans.lshift>
  423.     stent    <srchkb,sachmsg,ontab,attchr,flags.attflg>
  424.     stent    <srchkw,unkmsg,unkctab,flags.unkchs>
  425.     stent    <srchkb,sadtmsg,ontab,attdate,flags.attflg>
  426.     stent    <stmsg,spaces>
  427.     stent    <srchkb,salnmsg,ontab,attlen,flags.attflg>
  428.     stent    <stmsg,spaces>
  429.     stent    <srchkb,satymsg,ontab,atttype,flags.attflg>
  430.     dw    0
  431.  
  432. stlog    stent    <stmsg,logmsg>                ; SHOW LOG
  433.     stent    <stmsg,lpktmsg>
  434.     stent    <msg2b,nologmsg,lpktnam,logpkt,flags.capflg>
  435.     stent    <stmsg,lsesmsg>
  436.     stent    <msg2b,nologmsg,lsesnam,logses,flags.capflg>
  437.     stent    <stmsg,ltramsg>
  438.     stent    <msg2b,nologmsg,ltranam,logtrn,flags.capflg>
  439.     stent    <stmsg,dmpmsg>
  440.     stent    <stmsg,dmpname>
  441.     stent    <stmsg,prnmsg>
  442.     stent    <stmsg,prnname>
  443.     dw    0
  444.  
  445. stpro    stent    <stlnum,spakst,,dtrans.slong>        ; SHOW PROTOCOL
  446.     stent    <stlnum,rpakst,,dtrans.rlong>
  447.     stent    <stlnum,spakst1,,trans.slong>
  448.     stent    <stlnum,rpakst1,,trans.rlong>
  449.     stent    <stnum,stimst,,dtrans.stime>
  450.     stent    <stnum,rtimst,,trans.rtime>
  451.     stent    <onechr,sqcst,,dtrans.squote>
  452.     stent    <onechr,rqcst,,trans.rquote>
  453.     stent    <prsar,msohst,msrec,trans.ssoh,trans.rsoh>
  454.     stent    <prsarv,snpdst,msrecv,dtrans.spad,trans.rpad>
  455.     stent    <prsar,meolst,msrec,trans.seol,trans.reol>
  456.     stent    <prsar,spadst,msrec,dtrans.spadch,trans.rpadch>
  457.     stent    <onechr,dblmsg,,dtrans.sdbl>
  458.     stent    <onechr,ignmsg,,dtrans.rign>
  459.     stent    <prsnd,sndmsg1>
  460.     stent    <srchkw,blokst,blktab,dtrans.chklen>
  461.     stent    <stnum,retrymsg,,maxtry>
  462.     stent    <stnum,swinst,,dtrans.windo>
  463.     stent    <onoff,timmsg,,flags.timflg>
  464.     stent    <prhnd>
  465.     stent    <srchkw,debon,logsta,flags.debug>
  466.     stent    <srchkw,capmsg,logsta,flags.capflg>
  467.     stent    <srchkw,xtypmsg,xftyptab,dtrans.xtype>
  468.     stent    <srchkww,chmsg,setchtab,flags.chrset>
  469.     stent    <stmsg,atton>
  470.     stent    <srchkw,xchmsg,xfchtab,dtrans.xchset>
  471.     stent    <srchkb,sachmsg,ontab,attchr,flags.attflg>
  472.     stent    <srchkw,xchmsg2,xfertab2,dtrans.xchri>
  473.     stent    <srchkb,sadtmsg,ontab,attdate,flags.attflg>
  474.     stent    <srchkw,xchmsg1,xfertab1,dtrans.lshift>
  475.     stent    <srchkb,salnmsg,ontab,attlen,flags.attflg>
  476.     stent    <stmsg,spaces>
  477.     stent    <srchkb,satymsg,ontab,atttype,flags.attflg>
  478.     dw    0
  479.  
  480. stscpt    stent    <stmsg,scpmsg>                ; SHOW SCRIPT
  481.     stent    <onoff,sechmsg,,script.inecho>
  482.     stent    <srchkw,scasmsg,incstb,script.incasv>
  483.     stent    <stlnum,stmo1msg,,script.indfto>
  484.     stent    <srchkw,stmo2msg,inactb,script.inactv>
  485.     stent    <stalr,stalrmsg>
  486.     stent    <stlnum,stbufmsg,,scpbuflen>
  487.     stent    <stnum,sterlmsg,,errlev>
  488.     stent    <prfil>
  489.     stent    <onoff,sxlfmsg,,script.xmitlf>
  490.     stent    <stlnum,sxpaumsg,,script.xmitpause>
  491.     stent    <onechr,sxpmtmsg,,script.xmitpmt>
  492.     stent    <stcnt,stcntmsg>
  493.     stent    <srchkw,takon,ontab,flags.takflg>
  494.     stent    <starg,stargmsg>
  495.     stent    <stlnum,opacemsg,,outpace>
  496.     stent    <stmsg,stinbmsg>
  497.     stent    <stinbuf>
  498.     dw    0
  499.  
  500. stserv    stent    <pasz,lusrmsg,offset luser>        ; SHOW SERVER
  501.     stent    <stmsg,servmsg>
  502.     stent    <srchkb,scwdmsg,endistab,cwdflg,denyflg>
  503.     stent    <srchkb,skermsg,endistab,kerflg,denyflg>
  504.     stent    <srchkb,sdelmsg,endistab,delflg,denyflg>
  505.     stent    <srchkb,slogmsg,endistab,pasflg,denyflg>
  506.     stent    <srchkb,sdirmsg,endistab,dirflg,denyflg>
  507.     stent    <srchkb,ssndmsg,endistab,sndflg,denyflg>
  508.     stent    <srchkb,sfinmsg,endistab,finflg,denyflg>
  509.     stent    <srchkb,sprtmsg,endistab,prtflg,denyflg>
  510.     stent    <srchkb,sgetmsg,endistab,getsflg,denyflg>
  511.     stent    <srchkb,sspcmsg,endistab,spcflg,denyflg>
  512.     stent    <srchkb,shstmsg,endistab,hostflg,denyflg>
  513.     stent    <srchkb,stypmsg,endistab,typflg,denyflg>
  514.     dw    0
  515. stserv2    stent    <stnum,srvmsg,,srvtmo>
  516.     dw    0
  517.  
  518. stterm    stent    <srchkww,vtemst,termtb,flags.vtflg>    ; SHOW TERMINAL
  519.     stent    <srchkw,dispst,dissta,flags.remflg>
  520.     stent    <srchkw,modst,modtab,flags.modflg>
  521.     stent    <onechr,escmes,,trans.escchr>
  522.     stent    <srchkb,stekmsg,endistab,tekxflg,denyflg>
  523.     stent    <srchkw,kbdmsg,ontab,flags.xltkbd>
  524.     stent    <vtstat>
  525.     dw    0
  526.  
  527. shorxk    stent    <srchkw,kbdmsg,ontab,flags.xltkbd>
  528.     stent    <stmsg,spaces>
  529.     dw    0
  530.  
  531. data    ends
  532.  
  533. code1    segment
  534.     extern    fwrtdir:far, fcsrtype:far
  535. code1    ends
  536.  
  537. code    segment
  538.     extrn    comnd:near, decout:near, locate:near, prtscr:near, strlen:near
  539.     extrn    getbaud:near, vtstat:near, shomodem:near, nvaltoa:near
  540.     extrn    cmblnk:near, prtasz:near, putmod:near, clrmod:near
  541.     extrn    poscur:near, clearl:near, nout:near, dodec:near, buflog:near
  542.     extrn    dec2di:near, katoi:near, atoi:near
  543.  
  544.     assume    cs:code, ds:data, es:nothing
  545.  
  546. fstrlen    proc    far        ; FAR callable versions of items in seg code
  547.     call    strlen        ;  for calling from code segment code1 below
  548.     ret
  549. fstrlen    endp
  550. fdec2di    proc    far
  551.     call    dec2di
  552.     ret
  553. fdec2di    endp
  554. fprtscr    proc    far
  555.     call    prtscr
  556.     ret
  557. fprtscr    endp
  558. fprtasz    proc    far
  559.     call    prtasz
  560.     ret
  561. fprtasz    endp
  562. flnout    proc    far
  563.     call    lnout
  564.     ret
  565. flnout    endp
  566. flnouts    proc    far
  567.     call    lnouts
  568.     ret
  569. flnouts    endp
  570. fnvaltoa proc    far
  571.     call    nvaltoa
  572.     ret
  573. fnvaltoa endp
  574. ; Display asciiz message pointed to by DS:DX on Last error line
  575. ERMSG    PROC    NEAR
  576.     test    flags.remflg,dquiet    ; quiet screen?
  577.     jnz    ermsgx            ; nz = yes
  578.     push    si            ; position cursor to Last Error line
  579.     push    dx            ; save preexisting message pointer
  580.     test    flags.remflg,dserial    ; serial mode display?
  581.     jnz    erpo1            ; nz = yes
  582.     cmp    fmtdsp,0        ; formatted display?
  583.     jne    erpo2            ; ne = yes
  584. erpo1:    mov    ah,prstr
  585.     mov    dx,offset erword    ; put out word Error:
  586.     int    dos
  587.     jmp    short erpo3
  588. erpo2:    mov    dx,screrr
  589.     call    poscur
  590.     call    clearl            ; clear the line
  591. erpo3:    pop    dx            ; restore old pointer
  592.     mov    si,dx            ; string pointer
  593.     mov    cx,10            ; try ten items
  594.     cld
  595. ermsg1:    lodsb
  596.     cmp    al,' '            ; strip these leading spaces
  597.     loope    ermsg1
  598.     dec    si            ; backup to non-space
  599.     push    dx            ; preserve caller's dx
  600.     mov    dx,si
  601.     call    prtasz            ; display asciiz message
  602.     pop    dx
  603.     pop    si
  604. ermsgx:    ret
  605. ERMSG    ENDP
  606.  
  607. ; Decode and display Message packet pointed to by SI.
  608. MSGMSG    PROC    NEAR
  609.     test    flags.remflg,dquiet    ; quiet screen?
  610.     jnz    msgmsgx            ; nz = yes
  611.     cmp    [si].datlen,0        ; anything present?
  612.     je    msgmsgx            ; e = no
  613.     test    flags.remflg,dserial    ; serial mode display?
  614.     jnz    msgms1            ; nz = yes
  615.     cmp    fmtdsp,0        ; formatted display?
  616.     jne    msgms2            ; ne = yes
  617.     cmp    flags.xflg,0        ; packet header seen?
  618.     je    msgms2            ; e = no
  619. msgms1:    mov    ah,prstr
  620.     mov    dx,offset msword    ; put out word Message:
  621.     int    dos
  622.     jmp    short msgms3        ; display the message
  623. msgms2:    push    si
  624.     mov    dx,scrmsg        ; Last message line
  625.     call    poscur
  626.     call    clearl            ; clear the line
  627.     pop    si
  628. msgms3:    call    dodec            ; decode to decbuf, SI is pktinfo ptr
  629.     mov    dx,offset decbuf    ; final error message string, asciiz
  630.     call    prtasz            ; display asciiz message
  631. msgmsgx:ret
  632. MSGMSG    ENDP
  633.  
  634. ; Show number of retries message
  635.  
  636. RTMSG    PROC     NEAR
  637.     test    flags.remflg,dquiet    ; quiet display mode?
  638.     jnz    rtmsx            ; nz = yes
  639.     test    flags.remflg,dserver    ; in server mode?
  640.     jnz    rtms0            ; nz = yes
  641.     cmp    flags.xflg,0        ; receiving to screen?
  642.     jne    rtmsx            ; ne = yes
  643.     cmp    fmtdsp,0        ; formatted display?
  644.     je    rtms1            ; e = no, do as normal
  645. rtms0:    test    flags.remflg,dserial    ; serial mode display?
  646.     jnz    rtms1            ; nz = yes
  647.     push    ax
  648.     push    dx
  649.     push    si
  650.     mov    dx,scrnrt
  651.     call    poscur
  652.     call    clearl
  653.     pop    si
  654.     jmp    short rtms3
  655. rtms1:    push    ax
  656.     push    dx
  657.     mov    dx,offset rtword    ; display word Retry
  658.     mov    ah,prstr
  659.     int    dos
  660. rtms3:    mov    ax,fsta.pretry        ; number of retries
  661.     call    decout            ; write the number of group retries
  662.     pop    dx
  663.     pop    ax
  664. rtmsx:    ret
  665. RTMSG    ENDP
  666.  
  667. ; Reassure user that we acknowledge his ^X/^Z
  668.  
  669. INTMSG    PROC    NEAR
  670.     cmp    flags.cxzflg,0        ; anything there?
  671.     je    int1            ; e = no
  672.     test    flags.remflg,dserver    ; server mode?
  673.     jnz    int4            ; nz = yes
  674.     cmp    flags.xflg,0        ; writing to screen?
  675.     jne    int1            ; ne = yes, nothing to do
  676. int4:    test    flags.remflg,dquiet    ; quiet screen?
  677.     jnz    int1            ; yes, suppress msg
  678.     test    flags.remflg,dserial    ; serial mode display?
  679.     jz    int2            ; z = no
  680.     cmp    fmtdsp,0        ; formatted screen?
  681.     jne    int2            ; ne = yes
  682.     mov    dx,offset crlf        ; output initial cr/lf
  683.     mov    ah,prstr
  684.     int    dos
  685.     jmp    short int3        ; display the message
  686. int2:    mov    dx,scrmsg        ; last message position
  687.     call    poscur
  688.     call    clearl
  689. int3:    mov    dx,offset infms7    ; File interrupted
  690.     cmp    flags.cxzflg,'X'    ; File interrupt? 
  691.     je    int0            ; e = yes
  692.     mov    dx,offset infms8    ; File group interrupted
  693.     cmp    flags.cxzflg,'Z'    ; correct?
  694.     je    int0            ; e = yes
  695.     mov    dl,flags.cxzflg        ; say Control ^letter interrupt
  696.     mov    infms9+6,dl        ; store interrupt code letter
  697.     mov    dx,offset infms9
  698. int0:   mov    ah,prstr
  699.         int    dos
  700. int1:    ret
  701. INTMSG    ENDP
  702.  
  703. ;  Clear Last error and Last message lines
  704. cxerr:    mov    temp,0            ; say last error line
  705.     jmp    short cxcomm        ; do common code
  706.  
  707. CXMSG    PROC    NEAR
  708.     mov    temp,1            ; say last message line
  709.  
  710. cxcomm:    test    flags.remflg,dserver    ; server mode?
  711.     jnz    cxm1            ; nz = yes
  712.     cmp    flags.xflg,0        ; Writing to screen?
  713.     jne    cxm0            ; ne = yes
  714. cxm1:    cmp    fmtdsp,0        ; formatted display?
  715.     je    cxm0            ; e = no
  716.     push    dx
  717.     push     si
  718.     mov    dx,screrr        ; Last Error postion
  719.     cmp    temp,0            ; do last error line?
  720.     je    cxm2            ; e = yes
  721.     mov    dx,scrmsg        ; Last Message position
  722. cxm2:    call    poscur
  723.     call    clearl
  724.     pop    si
  725.     pop    dx
  726. cxm0:    ret
  727. CXMSG    ENDP
  728.  
  729. ;  Clear out the old filename on the screen. 
  730.  
  731. CLRFLN    PROC    NEAR
  732.     test    flags.remflg,dquiet     ; quiet display?
  733.     jnz    clrflnx            ; nz = yes
  734.     test    flags.remflg,dserial    ; serial display mode?
  735.     jnz    clrfln1            ; nz = yes, use just cr/lf
  736.     cmp    fmtdsp,0        ; formatted display?
  737.     je    clrfln1            ; e = no
  738.     mov    dx,scrfln
  739.     call    poscur
  740.     call    clearl            ; clear to end of line
  741.     ret
  742. clrfln1:push    ax            ; for serial display, does cr/lf
  743.     mov    ah,prstr
  744.     mov    dx,offset crlf
  745.     int    dos
  746.     pop    ax
  747. clrflnx:ret
  748. CLRFLN    ENDP
  749.  
  750.             ; display packet quantity and size, SI has pkt ptr
  751. PKTSIZE    PROC    NEAR
  752.     push    ax
  753.     push    dx
  754.     push    si
  755.     cmp    fmtdsp,0        ; formatted display?
  756.     je    pktsiz2            ; e = no, no display
  757.     mov    ax,[si].datlen        ; packet size (data part)
  758.     cmp    trans.chklen,'B'-'0'    ; this special case?
  759.     jne    pktsiz4            ; ne = no
  760.     add    al,2            ; special case is two byte chksum
  761.     jmp    short pktsiz5
  762. pktsiz4:add    al,trans.chklen        ; plus checksum
  763. pktsiz5:adc    ah,0
  764.     cmp    ax,prepksz        ; same as previous packet?
  765.     je    pktsiz2            ; e = yes, skip display of size
  766.     push    ax
  767.     mov    dx,scrsz        ; position cursor
  768.     call    poscur
  769.     pop    ax
  770.     mov    prepksz,ax        ; remember new value
  771.     add    ax,3            ; plus LEN, SEQ, TYPE
  772.     cmp    ax,94            ; larger than Regular?
  773.     jbe    pktsiz1            ; be = no
  774.     add    ax,3            ; add Long Packet len and chksum
  775. pktsiz1:call    decout            ; show packet length
  776.     mov    ah,prstr
  777.     mov    dx,offset blanks    ; spaces to clear old material
  778.     int    dos
  779.                     ; number of packets part
  780. pktsiz2:test    flags.remflg,dquiet    ; quiet screen?
  781.     jnz    pktsiz3            ; nz = yes
  782.     call    nppos            ; number of packets sent
  783.     mov    ax,numpkt        ; number of packets
  784.     call    nout            ; write the packet number
  785. pktsiz3:pop    si
  786.     pop    dx
  787.     pop    ax
  788.     ret
  789. PKTSIZE    ENDP
  790.  
  791. ; some random screen positioning functions
  792. kbpos:    mov    dx,scrkb        ; KBytes transferred
  793.     cmp    fmtdsp,0        ; formatted display?
  794.     jne    setup2            ; ne = yes
  795.     ret                ; else ignore postioning request
  796. perpos:    mov    dx,scrper        ; Percent transferred
  797.     cmp    fmtdsp,0        ; formatted display?
  798.     jne    setup2            ; ne = yes
  799.     ret                ; else ignore postioning request
  800. frpos:    mov    dx,scrmsg        ; say renamed file
  801.     jmp    short setup2
  802. stpos:    mov    dx,scrst        ; status of file transfer
  803.     jmp    short setup2
  804. nppos:    mov    dx,scrnp        ; Number of packets sent
  805.     cmp    fmtdsp,0        ; formatted display?
  806.     jne    setup2            ; ne = yes
  807.     ret
  808. rprpos:    test    flags.remflg,dserial+dquiet ; reprompt position
  809.     jnz    rprpos1            ; nz = no mode line for these
  810.     cmp    fmtdsp,0        ; formatted display?
  811.     je    rprpos1            ; e = no, so no mode line
  812.     call    clrmod            ; clear mode line
  813. rprpos1:mov    dx,scrrpr        ; Reprompt position
  814.     call    setup2            ; position cursor
  815.     mov    fmtdsp,0        ; turn off formatted display flag
  816.     ret
  817. sppos:    mov    dx,scrsp        ; Debug Send packet location
  818.     jmp    short setup1
  819. rppos:    mov    dx,scrrp        ; Debug Receive packet location
  820.     jmp    short setup1
  821.                 ; common service routines for positioning
  822. setup1:    test    flags.remflg,dquiet+dserial; quiet or serial display mode?
  823.     jnz    setupa            ; nz = yes
  824.     cmp    fmtdsp,0        ; non-formatted display?
  825.     je    setupa            ; e = yes
  826.     jmp    poscur
  827. setup2:    test    flags.remflg,dquiet+dserial; quiet or serial display mode?
  828.     jnz    setupa            ; nz = yes
  829.     cmp    fmtdsp,0        ; non-formatted display?
  830.     je    setupa            ; e = yes
  831.     call    poscur            ; no
  832.     jmp    clearl
  833. setupa: test    flags.remflg,dquiet    ; quiet mode?
  834.     jnz    setupx            ; nz = yes, do nothing
  835.     push    ax            ; display cr/lf and return
  836.     push    dx
  837.     mov    dx,offset crlf
  838.     mov    ah,prstr
  839.     int    dos
  840.     pop    dx
  841.     pop    ax
  842. setupx:    ret
  843.  
  844. ; Initialize formatted screen
  845.  
  846. INIT    PROC    NEAR
  847.     mov    windflag,0        ; init windows in use display flag
  848.     test    flags.remflg,dquiet    ; quiet display mode?
  849.     jnz    init4            ; nz = yes
  850.     test    flags.remflg,dserver    ; server mode?
  851.     jnz    init1            ; nz = yes
  852.     cmp    flags.xflg,0        ; destination is screen
  853.     jne    init4            ; ne = yes
  854. init1:    test    flags.remflg,dserial    ; serial mode display?
  855.     jnz    init3            ; nz = yes
  856.  
  857.     xor    al,al            ; cursor off code is zero
  858.     call    fcsrtype        ; turn off PC cursor (IBM-PC dep)
  859.  
  860.     call    cmblnk            ; clear the screen
  861.     mov    dx,offset cxzhlp
  862.     call    putmod            ; write mode line
  863.     mov    fmtdsp,1        ; say doing formatted display
  864.     test    flags.remflg,dserver    ; server mode?
  865.     jz    init2            ; z = no
  866.     mov    dx,scrser        ; move cursor to top of screen
  867.     call    poscur
  868.     mov    ah,prstr
  869.     mov    dx,offset infms1    ; say now in server mode
  870.     int    dos
  871. init2:    call    locate
  872.     mov    ah,prstr        ; put statistics headers on the screen
  873.     mov    dx,offset outlin1
  874.     int    dos
  875.     mov    dx,offset verident
  876.     int    dos
  877.     mov    dx,offset outlin2
  878.     int    dos
  879.     mov    wrpmsg,0        ; haven't printed the messsage yet
  880.     mov    prepksz,0        ; set previous packet size to zero
  881.     mov    di,offset templp    ; 65 byte buffer from mssfil
  882.     call    fwrtdir            ; fill with drive:path
  883.     mov    dx,scrpath
  884.     call    poscur            ; set cursor
  885.     mov    dx,offset templp    ; show string
  886.     call    prtasz
  887.     ret
  888. init3:    mov    ah,prstr
  889.     mov    dx,offset cxzser    ; status line as a text string
  890.     int    dos
  891. init4:    mov    wrpmsg,1        ; suppress display of percentage msg
  892.     mov    fmtdsp,0        ; say doing unformatted display
  893.     ret
  894. INIT    ENDP
  895.  
  896. ; show number of Kilobytes transferred
  897. ; modifies ax
  898. kbpr    proc    near
  899.     test    flags.remflg,dquiet    ; quiet display mode?
  900.     jnz    kbpr1            ; nz = yes, no printing
  901.     push    bx
  902.     mov    ax,tfilsz        ; low order word
  903.     mov    bx,tfilsz+2        ; high order word
  904.     add    ax,512            ; round up, add half the denominator
  905.     adc    bx,0
  906.     rcr    bx,1            ; divide double word by 1024,
  907.     rcr    ax,1            ; by dword shift right 10
  908.     rcr    bx,1
  909.     rcr    ax,1
  910.     mov    al,ah
  911.     mov    ah,bl            ; ax has the result
  912.     pop    bx
  913.     cmp    ax,oldkbt        ; is it the same?
  914.     je    kbpr1            ; yes, skip printing
  915.     mov    oldkbt,ax        ; save new # of kb
  916.     push    ax
  917.     mov    dx,scrkb
  918.     call    poscur            ; position the cursor
  919.     pop    ax
  920.     call    decout            ; print number of KBytes transferred
  921.     mov    ah,prstr
  922.     mov    dx,offset blanks    ; trim off old trailing junk
  923.     int    dos
  924. kbpr1:    ret
  925. kbpr    endp    
  926.  
  927. ; show percent transferred
  928. ; modifies ax
  929. perpr    proc    near
  930.     test    flags.remflg,dquiet    ; quiet display mode?
  931.     jz    perpr1            ; z = no. allow printing
  932.     ret                ; skip printing in remote mode
  933. perpr1:    cmp    diskio.sizehi,0        ; high word of original file size > 0 ?
  934.     jne    perpr3            ; ne = yes, use big file code
  935.     cmp    diskio.sizelo,0        ; anything here at all?
  936.     jne    perpr2            ; ne = yes, use small file code
  937.     mov    wrpmsg,0        ; init flag, prime to clear display
  938.     ret                ; otherwise, quit now
  939. perpr2:    push    cx            ; case for files < 64 Kb
  940.     push    dx
  941.     mov    ax,diskio.sizelo    ; original size (low word)
  942.     mov    denom,ax
  943.     mov    dx,tfilsz+2        ;transferred size times 256 in [dx,ax]
  944.     mov    ax,tfilsz
  945.     mov    dh,dl            ; whole value multiplied by 256
  946.     mov    dl,ah
  947.     mov    ah,al
  948.     xor    al,al
  949.     mov    cx,denom        ; round up, add half the denominator
  950.     shr    cx,1
  951.     add    ax,cx
  952.     adc    dx,0
  953.     div    denom            ; (256*xfer)/orig. ax = quo, dx = rem
  954.     mul    onehun            ; multiply quotient above by 100
  955.     mov    al,ah            ; divide result (ax) by 256
  956.     xor    ah,ah            ; percentage is in ax
  957.     jmp    short perpr5        ; finish in common code
  958.  
  959. perpr3:    cmp    byte ptr diskio.sizehi+1,0 ; file > 16MB? (> 3 bytes)
  960.     jne    perpr4            ; ne = yes, use biggest code
  961.     push    cx            ; case for file size > 64 KB (3 bytes)
  962.     push    dx
  963.     mov    ax,diskio.sizelo    ; original file size low order word
  964.     mov    al,ah            ; divide by 256
  965.     xor    ah,ah            ; clear ah        
  966.     mov    dx,diskio.sizehi    ; high order word
  967.     xchg    dh,dl            ; divide by 256
  968.     xor    dl,dl            ; clear low bits
  969.     or    ax,dx            ; paste together the two parts into ax
  970.     mov    denom,ax        ; denom = original size divided by 512
  971.     mov    dx,tfilsz+2        ; high order word of transferred size
  972.     mov    ax,tfilsz        ; low order word
  973.     mov    cx,denom        ; round up, add half the denominator
  974.     shr    cx,1
  975.     add    ax,cx
  976.     adc    dx,0
  977.     div    denom            ; xfer/(orig/256). ax=quot, dx=rem
  978.     mul    onehun            ; times 100 for 256*percentage, in ax
  979.     mov    al,ah            ; divide ax by 256
  980.     xor    ah,ah
  981.     jmp    short perpr5        ; finish in common code
  982.  
  983. perpr4:    push    cx            ; case for files > 16MB (> 3 bytes)
  984.     push    dx
  985.     mov    ax,tfilsz+2        ; transferred size / 64K in [dx,ax]
  986.     or    ax,ax            ; anything showing yet?
  987.     jz    perpr5            ; z = no, return zero in AX
  988.     xor    dh,dh
  989.     mov    dl,ah
  990.     mov    ah,al            ; value multiplied by 256
  991.     xor    al,al
  992.     mov    cx,diskio.sizehi    ; round up, add half the denominator
  993.     shr    cx,1
  994.     add    ax,cx
  995.     adc    dx,0
  996.     div    diskio.sizehi        ; (256*xfer)/orig. ax = quo, dx = rem
  997.     mul    onehun            ; multiply quotient above by 100
  998.     mov    al,ah            ; divide result (ax) by 256
  999.     xor    ah,ah            ; percentage is in ax
  1000.  
  1001. perpr5:    cmp    ax,oldper        ; same as it was before?
  1002.     je    perpr8            ; yes, don't bother printing
  1003.     cmp    oldper,0        ; inited yet?
  1004.     mov    oldper,ax        ; remember this for next time
  1005.     jl    perpr5a            ; l = needs reiniting of screen
  1006.     cmp    wrpmsg,0        ; did we write the percentage message?
  1007.     jne    perpr6            ; ne = yes, skip this part
  1008. perpr5a:push    ax
  1009.     call    perpos            ; position cursor, clear line
  1010.     mov    dx,offset permsg
  1011.     mov    ah,prstr
  1012.     int    dos            ; write out message
  1013.     mov    dx,scrper
  1014.     inc    dh            ; next row
  1015.     push    dx
  1016.     xor    dl,dl
  1017.     call    setup2            ; clear whole line
  1018.     pop    dx
  1019.     sub    dl,2            ; backup two columns
  1020.     call    poscur            ; set cursor
  1021.     mov    dx,offset perscale    ; show thermometer numeric scale
  1022.     mov    ah,prstr
  1023.     int    dos
  1024.     xor    ax,ax
  1025.     call    perprwork        ; write thermometer
  1026.     pop    ax
  1027.     mov    lastper,0        ; last percentage done
  1028.     mov    wrpmsg,1        ; init flag so we don't do it again
  1029. perpr6: push    ax
  1030.     mov    dx,scrper        ; percentage top line
  1031.     inc    dh
  1032.     sub    dl,6            ; below and to the left
  1033.     call    poscur            ; position the cursor
  1034.     pop    ax
  1035.     cmp    ax,onehun        ; > 100% ?
  1036.     jb    perpr7            ; b = no, accept it
  1037.     mov    ax,onehun        ; else just use 100
  1038. perpr7:    push    ax
  1039.     call    decout
  1040.     mov    dl,25h            ; load a percent sign
  1041.     mov    ah,conout        ; display the character
  1042.     int    dos
  1043.     pop    ax
  1044.     mov    cx,ax            ; current percentage done
  1045.     xchg    al,lastper        ; update last percentage done
  1046.     sub    cl,al            ; minus previous percentage completed
  1047.     jle    perpr8            ; le = no change
  1048. perpr7a:inc    ax            ; write intervening percentages
  1049.     call    perprwork        ; write thermometer
  1050.     loop    perpr7a            ; do all steps
  1051. perpr8:    pop    dx
  1052.     pop    cx
  1053.     ret
  1054.  
  1055. perprwork:push    ax            ; worker to display thermometer
  1056.     mov    dx,scrper
  1057.     inc    al            ; ax is percentage done
  1058.     shr    al,1            ; divide by two
  1059.     add    dl,al            ; get column
  1060.     call    poscur            ; position the cursor
  1061.     pop    ax
  1062.     push    ax
  1063.     mov    dl,0dch            ; half block symbol (IBM-PCs)
  1064.     test    al,1
  1065.     jnz    perprw1            ; nz = odd
  1066.     dec    dl            ; full block symbol
  1067. perprw1:mov    ah,conout        ; display the character
  1068.     int    dos
  1069. perprw2:pop    ax
  1070.     ret
  1071. perpr    endp
  1072.  
  1073. winpr    proc    near            ; print number of active window slots
  1074.     push    ax
  1075.     mov    al,windused        ; window slots used at this moment
  1076.     cmp    al,winusedmax        ; exceeds running max noted?
  1077.     jbe    winpr5            ; be = no
  1078.     mov    winusedmax,al        ; update max
  1079. winpr5:    pop    ax
  1080.     cmp    trans.windo,1        ; windowing in use?
  1081.     jbe    winprx            ; be = no, no message
  1082.     test    flags.remflg,dregular    ; regular display?
  1083.     jz    winprx            ; z = no, no display
  1084.     cmp    fmtdsp,0        ; formatted display?
  1085.     je    winprx            ; e = no, no display here
  1086.     test    flags.remflg,dserver    ; server mode?
  1087.     jnz    winpr4            ; nz = yes, writing to their screen
  1088.     cmp    flags.xflg,0        ; receiving to screen?
  1089.     je    winpr4            ; e = no
  1090. winprx:    ret
  1091. winpr4:    push    ax
  1092.     push    bx
  1093.     push    cx
  1094.     push    dx
  1095.     push    si
  1096.     cmp    windflag,0        ; have we written an initial value?
  1097.     jne    winpr1            ; ne = yes
  1098.     mov    dx,scrnp        ; position cursor
  1099.     dec    dh
  1100.     xor    dl,dl            ; 0 = left most column for text
  1101.     call    poscur
  1102.     call    clearl            ; clear the line
  1103.     mov    ah,prstr
  1104.     mov    dx,offset windmsg    ; the text
  1105.     int    dos
  1106.     xor    al,al            ; display an initial 0
  1107.     mov    oldwind,-1
  1108.     mov    windflag,1        ; say have done the work
  1109.     jmp    short winpr2
  1110. winpr1:    mov    al,windused        ; window slots in use
  1111.     cmp    al,oldwind        ; same as before?
  1112.     je    winpr3            ; e = yes, ignore
  1113. winpr2:    push    ax
  1114.     mov    dx,scrnp        ; position cursor
  1115.     dec    dh
  1116.     call    poscur
  1117.     call    clearl
  1118.     pop    ax
  1119.     mov    oldwind,al        ; remember last value
  1120.     xor    ah,ah
  1121.     call    decout            ; display value
  1122.     mov    ah,prstr
  1123.     mov    dx,offset windmsg2    ; ' of '
  1124.     int    dos
  1125.     mov    al,trans.windo        ; number of window slots
  1126.     xor    ah,ah
  1127.     call    decout
  1128. winpr3:    pop    si
  1129.     pop    dx
  1130.     pop    cx
  1131.     pop    bx
  1132.     pop    ax
  1133.     ret
  1134. winpr    endp
  1135.  
  1136. ; Show file kind (text, binary) and character set, must preserve SI
  1137. filekind proc    near
  1138.     cmp    flags.xflg,0        ; receiving to screen?
  1139.     jne    filekx            ; ne = yes, skip displaying
  1140.     cmp    flags.destflg,2        ; destination is screen?
  1141.     je    filekx            ; e = yes
  1142.     test    flags.remflg,dregular    ; regular display?
  1143.     jz    filekx            ; z = no, no display
  1144.     cmp    fmtdsp,0        ; formatted display?
  1145.     je    filekx            ; e = no, no display here
  1146.     mov    dx,scrkind
  1147.     call    setup2            ; clear to end of line
  1148.     mov    ah,prstr
  1149.     mov    dx,offset kind_text    ; assume text
  1150.     cmp    trans.xtype,0        ; text?
  1151.     je    filek1            ; e = yes
  1152.     mov    dx,offset kind_binary    ; say binary
  1153. filek1:    int    dos
  1154.     cmp    trans.xtype,0        ; text?
  1155.     jne    filekx            ; ne = no
  1156.     push    bx
  1157.     push    cx
  1158.     push    di
  1159.     test    sflag,1            ; send operation?
  1160.     jnz    filek2            ; nz = yes
  1161.     mov    al,trans.xchset        ; transfer character set
  1162.     xor    ah,ah
  1163.     mov    bx,offset xfchtab    ; transfer file character set table
  1164.     jmp    short filek3
  1165. filek2:    mov    bx,offset setchtab    ; file character set table
  1166.     mov    ax,flags.chrset        ; current char set (Code Page)
  1167. filek3:    call    filekwork
  1168.     jc    filek6            ; no match
  1169.     push    di
  1170.     mov    ah,conout
  1171.     mov    dl,','            ; say "text, "
  1172.     int    dos
  1173.     mov    dl,' '
  1174.     int    dos
  1175.     pop    di
  1176.     call    prtscr            ; display cx counted string in ds:di
  1177.  
  1178.     test    sflag,1            ; send operation?
  1179.     jnz    filek4            ; nz = yes
  1180.     mov    bx,offset setchtab    ; file character set table
  1181.     mov    ax,flags.chrset        ; current char set (Code Page)
  1182.     jmp    short filek5
  1183. filek4:    mov    al,trans.xchset        ; transfer character set
  1184.     xor    ah,ah
  1185.     mov    bx,offset xfchtab    ; transfer file character set table
  1186. filek5:    call    filekwork
  1187.     jc    filek6            ; no match
  1188.     push    di
  1189.     mov    ah,conout
  1190.     mov    dl,' '
  1191.     int    dos
  1192.     mov    dl,'t'
  1193.     int    dos
  1194.     mov    dl,'o'
  1195.     int    dos
  1196.     mov    dl,' '
  1197.     int    dos
  1198.     pop    di
  1199.     call    prtscr            ; display cx counted string in ds:di
  1200. filek6:    pop    di
  1201.     pop    cx
  1202.     pop    bx
  1203. filekx:    ret
  1204. filekind endp
  1205.  
  1206. ; Worker for filekind. Enter with BX = offset of keyword table, AX = value
  1207. ; to be matched. Returns carry clear, DI = ptr to string, CX = string length,
  1208. ; else returns carry set.
  1209. filekwork proc    near
  1210.     mov    cl,[bx]            ; number of entries in our table
  1211.     inc    bx            ; point to the data
  1212. filewk1:mov    di,[bx]            ; length of keyword
  1213.     cmp    ax,[bx+di+2]        ; value fields match?
  1214.     je    filewk2            ; e = yes
  1215.     add    bx,di            ; add word length
  1216.     add    bx,4            ; skip count and value fields
  1217.     dec    cl            ; more keywords to check?
  1218.     jnz    filewk1            ; nz = yes, go to it
  1219.     stc                ; say no match
  1220.     ret
  1221. filewk2:mov    cx,di            ; string length
  1222.     mov    di,bx
  1223.     add    di,2            ; transfer char set ident string
  1224.     clc                ; say success
  1225.     ret
  1226. filekwork endp
  1227.  
  1228. ; Show file characters/sec msg and value, use after calling endtim.
  1229. filecps    proc    near
  1230.     test    flags.remflg,dregular    ; regular display?
  1231.     jz    filecpsx        ; z = no, no display
  1232.     cmp    fmtdsp,0        ; formatted display?
  1233.     je    filecpsx        ; e = no, no display here
  1234.     cmp    flags.xflg,0        ; receiving to screen?
  1235.     je    filecps1        ; e = no
  1236. filecpsx:ret
  1237.  
  1238. filecps1:push    bx
  1239.     push    si
  1240.     mov    dx,scrper        ; thermometer line
  1241.     inc    dh            ; percentage scale line
  1242.     call    setup2            ; set cursor, clear to eol
  1243.     mov    dx,offset filemsg1    ; File chars per second
  1244.     mov    ah,prstr
  1245.     int    dos
  1246.     mov    bx,offset fsta        ; last file structure
  1247.     test    sflag,2            ; 0 for rcv, 2 for send
  1248.     jz    filecps2        ; z = receive
  1249.     mov    ax,[bx].fsbyte        ; file bytes sent, low
  1250.     mov    dx,[bx].fsbyte+2    ;  high. [dx,ax] = total file bytes
  1251.     jmp    short filecps3
  1252. filecps2:mov    ax,[bx].frbyte        ; file bytes received, low
  1253.     mov    dx,[bx].frbyte+2    ; file bytes received, high
  1254. filecps3:call    far ptr fshowrk        ; do worker
  1255.     mov    temp,ax            ; file chars/sec
  1256.     mov    temp1,dx        ; high word
  1257.     mov    cx,1
  1258.     call    far ptr fshoprt        ; show result
  1259.     call    filebps            ; get port speed to dx:ax
  1260.     jc    filecps8        ; c = not a number
  1261.     push    ax            ; comms bits/sec
  1262.     push    dx            ; ditto, high part
  1263.     mov    dx,offset filemsg2    ; Efficiency msg
  1264.     mov    ah,prstr
  1265.     int    dos
  1266.     mov    dx,offset rdbuf        ; buffer with asciiz baud string
  1267.     call    prtasz
  1268.     mov    ah,prstr
  1269.     mov    dx,offset filemsg3
  1270.     int    dos
  1271.     mov    ax,temp1        ; high order part of file chars/sec
  1272.     mov    cx,1000
  1273.     mul    cx            ; times 100(%) * 10(bits/char)
  1274.     mov    bx,ax            ; save low order part of product
  1275.     mov    ax,temp            ; low order part of file chars/sec
  1276.     mul    cx
  1277.     add    dx,bx            ; add high orders
  1278.     pop    cx            ; high order part
  1279.     pop    bx            ; comms b/s
  1280. filecps4:jcxz    filecps5        ; z = no high order denominator part
  1281.     shr    cx,1            ; divide bottom by 2
  1282.     rcr    bx,1
  1283.     shr    dx,1            ; divide top by 2
  1284.     rcr    ax,1
  1285.     jmp    short filecps4        ; do again if necessary
  1286. filecps5:mov    cx,bx            ; set up for worker divide dx,ax / cx
  1287.     or    cx,cx
  1288.     jnz    filecps6        ; avoid divide by zero
  1289.     inc    cx
  1290. filecps6:push    bx            ; divide dx,ax by cx, results to dx,ax
  1291.     push    ax
  1292.     mov    ax,dx
  1293.     xor    dx,dx
  1294.     div    cx            ; ax = high quo, dx = high rem
  1295.     mov    bx,ax            ; save high quotient
  1296.     pop    ax
  1297.     div    cx               ; bytes div seconds, ax = quo, dx = rem
  1298.     shl    dx,1            ; prepare remainder for rounding test
  1299.     cmp    dx,cx            ; round up?
  1300.     jb    filecps7        ; b = no
  1301.     add    ax,1            ; round up
  1302.     adc    bx,0            ; ripple carry
  1303. filecps7:mov    dx,bx            ; previous high quotient
  1304.     pop    bx            ; 100 * file bps / (comms bits/sec)
  1305.     mov    cx,2            ; field width
  1306.     call    far ptr fshoprt        ; show efficiency
  1307.     mov    ah,conout
  1308.     mov    dl,'%'
  1309.     int    dos
  1310. filecps8:pop    si
  1311.     pop    bx
  1312.     ret
  1313. filecps    endp
  1314.  
  1315. ; Worker to convert comms port bits/second to number in dx:ax
  1316. ; Returns carry set if value is unkown
  1317. filebps    proc    near
  1318.     mov    bx,portval        ; port pointer
  1319.     mov    ax,[bx].baud        ; baud rate index to AX
  1320.     cmp    al,byte ptr bdtab    ; index versus number of table entries
  1321.     jb    fileb1            ; b = index is in the table
  1322.     stc                ; say unknown
  1323.     ret
  1324. fileb1:    push    si
  1325.     mov    si,offset bdtab        ; ascii rate table
  1326.     mov    cl,[si]            ; number of entries
  1327.     inc    si            ; point to an entry
  1328. fileb2:    mov    bx,[si]            ; length of text string
  1329.     cmp    ax,[si+bx+2]        ; our index vs table entry index
  1330.     je    fileb3            ; e = match
  1331.     add    si,bx            ; skip text
  1332.     add    si,4            ; skip count and index word
  1333.     loop    fileb2            ; look again
  1334.     pop    si
  1335.     stc                ; say unknown
  1336.     ret
  1337.  
  1338. fileb3:    mov    cx,bx            ; length of string
  1339.     mov    ah,cl            ; use ah for atoi below
  1340.     add    si,2            ; point at string
  1341.     push    es
  1342.     push    di
  1343.     mov    bx,ds
  1344.     mov    es,bx
  1345.     mov    di,offset rdbuf        ; work buffer
  1346.     cld
  1347.     rep    movsb            ; copy string
  1348.     xor    al,al
  1349.     stosb                ; asciiz
  1350.     pop    di
  1351.     pop    es
  1352.     mov    si,offset rdbuf
  1353.     call    atoi            ; convert to number in DX:AX, or fail
  1354.     pop    si
  1355.     ret
  1356. filebps    endp
  1357. code    ends
  1358.  
  1359. code1    segment
  1360.     assume    cs:code1
  1361.  
  1362. ; Start recording of statistics for this operation. Enter with al = 0 for
  1363. ; receive, al = 1 for send.
  1364. fbegtim    proc    FAR
  1365.     test    sflag,80h        ; is this a duplicate call?
  1366.     jz    begtim1            ; z = no
  1367.     ret                ; else just return
  1368. begtim1:push    ax
  1369.     push    cx
  1370.     push    dx
  1371.     push    di
  1372.     push    es
  1373.     push    ds
  1374.     pop    es
  1375.     and    al,1
  1376.     mov    sflag,al        ; save direction of xfer (1=send)
  1377.     xor    ax,ax        ; clear statistics counters for this file
  1378.     cld
  1379.     mov    di,offset fsta.prbyte    ; start of the structure
  1380.     mov    cx,offset fsta.xstatus+1-offset fsta.prbyte ; end
  1381.     rep    stosb            ; clear most of the structure
  1382.     pop    es
  1383.     pop    di
  1384.     mov    ah,getdate        ; get current date, convert to ascii
  1385.     int    dos
  1386.     mov    date+9,'0'        ; init day of month
  1387. begtim2:cmp    dl,10            ; day of month. Ten or more days?
  1388.     jl    begtim3            ; l = no
  1389.     sub    dl,10
  1390.     inc    date+9            ; add up tens of days
  1391.     jmp    short begtim2        ; repeat for higher order
  1392. begtim3:add    dl,'0'            ; ascii bias
  1393.     mov    date+10,dl        ; day units
  1394.     mov    dl,dh            ; months (1-12)
  1395.     dec    dl            ; start at zero to index table
  1396.     xor    dh,dh
  1397.     mov    di,dx            ; months
  1398.     shl    di,1
  1399.     add    di,dx            ; times three chars/month
  1400.     mov    al,months[di]        ; get text string for month
  1401.     mov    date+12,al
  1402.     mov    ax,word ptr months[di+1]
  1403.     mov    word ptr date+13,ax
  1404.     mov    ax,cx            ; year since 1980
  1405.     mov    dx,0
  1406.     mov    di,offset date+16    ; destination
  1407.     call    flnout            ; convert number to asciiz in buffer
  1408.                     ; start time
  1409.     mov    ah,gettim        ; DOS time of day, convert to ascii
  1410.     int    dos
  1411.     push    cx
  1412.     push    dx
  1413.     call    timewrk            ; convert to seconds.01 in dx,ax
  1414.     mov    fsta.btime,ax        ; store ss.s   low word of seconds
  1415.     mov    fsta.btime+2,dx        ;  high word of seconds
  1416.     pop    dx
  1417.     pop    cx
  1418.     mov    date,'0'        ; init begin hours field
  1419. begtim4:cmp    ch,10            ; ten or more hours?
  1420.     jl    begtim5            ; l = no
  1421.     sub    ch,10
  1422.     inc    date            ; add up tens of hours
  1423.     jmp    short begtim4        ; repeat for twenties
  1424. begtim5:add    ch,'0'            ; ascii bias
  1425.     mov    date+1,ch        ; store units of hours
  1426.     mov    date+3,'0'        ; minutes field
  1427. begtim6:cmp    cl,10            ; ten or more minutes?
  1428.     jl    begtim7            ; l = no
  1429.     sub    cl,10
  1430.     inc    date+3            ; add up tens of minutes
  1431.     jmp    short begtim6        ; repeat for higher orders
  1432. begtim7:add    cl,'0'            ; ascii bias
  1433.     mov    date+4,cl        ; store units of minutes
  1434.     mov    date+6,'0'        ; seconds field
  1435. begtim8:cmp    dh,10            ; ten or more seconds?
  1436.     jl    begtim9            ; l = no
  1437.     sub    dh,10
  1438.     inc    date+6            ; add up tens of seconds
  1439.     jmp    short begtim8        ; repeat for higher orders
  1440. begtim9:add    dh,'0'            ; ascii bias
  1441.     mov    date+7,dh
  1442.     or    sflag,80h        ; say begtim has been run
  1443.     pop    dx
  1444.     pop    cx
  1445.     pop    ax
  1446.     ret
  1447. fbegtim    endp
  1448.  
  1449. ; Take snapshot of statistics counters at end of an operation
  1450. ; Enter with ax = 0 for a receive operation, ax = 1 for a send. [jrd]
  1451. fendtim    proc    FAR
  1452.     test    sflag,80h    ; called more than once without calling begtim?
  1453.     jnz    endtim1            ; nz = no, so do statistics snapshot
  1454.     ret                ; yes, do nothing
  1455. endtim1:and    sflag,not (1)        ; assume receive operation
  1456.     or    ax,ax            ; send (ax > 0), receive (ax = 0) flag
  1457.     jz    endtim2            ; z = receive opeation
  1458.     or    sflag,1            ; say send operation
  1459. endtim2:push    ax
  1460.     push    cx
  1461.     push    dx
  1462.     mov    ah,gettim        ; get DOS time of day
  1463.     int    dos            ; ch=hh, cl=mm, dh=ss, dl= 0.01 sec
  1464.     call    timewrk            ; convert to seconds.01 in dx,ax
  1465.     sub    al,byte ptr fsta.btime    ; 0.01 sec field, wrapped?
  1466.     jnc    endtim2a        ; nc = no
  1467.     add    al,100            ; unwrap
  1468.     sub    ah,1            ; borrow one second from end seconds
  1469.     sbb    dx,0
  1470. endtim2a:sub    ah,byte ptr fsta.btime+1 ; minus begin time, sec
  1471.     sbb    dx,fsta.btime+2
  1472.     jnc    endtim2b        ; nc = no day straddling
  1473.     add    ah,128            ; part of one day
  1474.     adc    dx,337            ; rest of 86400 sec/day
  1475. endtim2b:mov    fsta.etime,ax        ; elapsed time
  1476.     mov    fsta.etime+2,dx
  1477.     add    al,byte ptr ssta.etime     ; add to session time, 0.01 sec field
  1478.     cmp    al,100            ; larger than 1 sec?
  1479.     jb    endtim2c        ; b = no
  1480.     sub    al,100            ; keep under 1 sec
  1481.     add    ah,1            ; ripple carry seconds
  1482.     adc    dx,0
  1483. endtim2c:mov    byte ptr ssta.etime,al
  1484.     add    byte ptr ssta.etime+1,ah ; seconds low byte
  1485.     adc    ssta.etime+2,dx        ; add to session time, high word
  1486.     mov    ax,fsta.pretry        ; retries for last transfer
  1487.     add    ssta.pretry,ax        ; retries for this session
  1488.  
  1489.     test    sflag,1            ; completing a receive operation?
  1490.     jnz    endtim3            ; nz = no, a send operation
  1491.     mov    ax,fsta.frbyte
  1492.     add    ssta.frbyte,ax        ; session received file bytes, low word
  1493.     mov    ax,fsta.frbyte+2
  1494.     adc    ssta.frbyte+2,ax
  1495.     mov    ax,fsta.prbyte        ; received pkt byte count
  1496.     add    ssta.prbyte,ax
  1497.     mov    ax,fsta.prbyte+2
  1498.     adc    ssta.prbyte+2,ax
  1499.     xor    ax,ax
  1500.     mov    fsta.psbyte,ax        ; don't count reverse channel bytes
  1501.     mov    fsta.psbyte+2,ax
  1502.     jmp    short endtim4
  1503.  
  1504. endtim3:mov    ax,fsta.fsbyte        ; file bytes sent
  1505.     add    ssta.fsbyte,ax        ; session sent file bytes, low word
  1506.     mov    ax,fsta.fsbyte+2
  1507.     adc    ssta.fsbyte+2,ax
  1508.     mov    ax,fsta.psbyte        ; sent pkt byte count
  1509.     add    ssta.psbyte,ax
  1510.     mov    ax,fsta.psbyte+2
  1511.     adc    ssta.psbyte+2,ax
  1512.     xor    ax,ax
  1513.     mov    fsta.prbyte,ax        ; don't count reverse channel bytes
  1514.     mov    fsta.prbyte+2,ax
  1515.  
  1516. endtim4:mov    ax,fsta.nakrcnt     ; NAKs received for this file
  1517.     add    ssta.nakrcnt,ax     ; session received NAKs
  1518.     mov    ax,fsta.nakscnt     ; NAKs sent for this file
  1519.     add    ssta.nakscnt,ax     ; session sent NAKs
  1520.     mov    ax,fsta.prpkt        ; received packet count
  1521.     add    ssta.prpkt,ax
  1522.     mov    ax,fsta.prpkt+2
  1523.     adc    ssta.prpkt+2,ax
  1524.     mov    ax,fsta.pspkt        ; sent packet count
  1525.     add    ssta.pspkt,ax
  1526.     mov    ax,fsta.pspkt+2
  1527.     adc    ssta.pspkt+2,ax
  1528.                     ; do transaction logging
  1529.     cmp    tloghnd,0        ; logging transaction? -1 = not opened
  1530.     jg    endtim5            ; g = logging
  1531.     jmp    endtim12        ; skip logging
  1532. endtim5:push    di            ; kind of transaction
  1533.     push    bx            ; save these registers
  1534.     mov    bx,tloghnd        ; handle for transaction log
  1535.     mov    dx,offset rcvmsg    ; assume receive message
  1536.     test    sflag,1            ; 1 for send, 0 for receive
  1537.     jz    endtim6            ; z = receive
  1538.     mov    dx,offset sndmsg    ; send message
  1539. endtim6:call    fstrlen            ; length of message to cx
  1540.     mov    ah,write2
  1541.     int    dos            ; write kind of transfer
  1542.                     ; File names
  1543.     cmp    diskio.string,0        ; local filename
  1544.     je    endtim9            ; e = no filename
  1545.     test    sflag,1            ; a send operation?
  1546.     jnz    endtim8            ; nz = yes
  1547.                     ; Receive
  1548.     mov    dx,offset fsta.xname    ; remote name
  1549.     call    fstrlen            ; length to cx
  1550.     jcxz    endtim7            ; no name
  1551.     mov    ah,write2
  1552.     int    dos
  1553.     mov    dx,offset diskio.string    ; local name
  1554.     call    fstrlen            ; length to cx
  1555.     mov    si,offset fsta.xname    ; compare these two names
  1556.     mov    di,dx
  1557.     push    ds
  1558.     pop    es
  1559.     repe    cmpsb            ; compare
  1560.     je    endtim9            ; e = same, so no 'as' msg
  1561.     mov    dx,offset fasmsg    ; give 'as' message
  1562.     mov    cx,faslen        ; length
  1563.     mov    ah,write2
  1564.     int    dos
  1565. endtim7:mov    dx,offset diskio.string    ; local name
  1566.     call    fstrlen            ; get length
  1567.     mov    ah,write2        ; write local name
  1568.     int    dos
  1569.     jmp    short endtim9
  1570.  
  1571. endtim8:mov    dx,offset templp    ; Send. local name
  1572.     call    fstrlen
  1573.     mov    ah,write2
  1574.     int    dos
  1575.     cmp    fsta.xname,0        ; using an alias?
  1576.     je    endtim9            ; e = no
  1577.     mov    dx,offset fasmsg    ; give 'as' message
  1578.     mov    cx,faslen
  1579.     mov    ah,write2
  1580.     int    dos
  1581.     mov    dx,offset fsta.xname    ; get alias
  1582.     call    fstrlen
  1583.     mov    ah,write2
  1584.     int    dos
  1585.                     ; status of transfer
  1586. endtim9:mov    dx,offset atmsg        ; say At
  1587.     mov    cx,atlen        ; length
  1588.     mov    bx,tloghnd        ; handle
  1589.     mov    ah,write2
  1590.     int    dos
  1591.     mov    dx,offset date        ; write time and date field
  1592.     mov    cx,datelen        ; length
  1593.     mov    ah,write2
  1594.     int    dos
  1595.     mov    dx,offset fsucmsg    ; assume success message
  1596.     cmp    fsta.xstatus,kssuc    ; 0 = completed successfully?
  1597.     je    endtim10        ; e = completed
  1598.     mov    dx,offset fbadmsg    ; failed message
  1599.     test    fsta.xstatus,ksuser    ; user interrupted?
  1600.     jz    endtim10        ; z = no
  1601.     mov    dx,offset fintmsg    ; interrupted message
  1602. endtim10:call    fstrlen            ; get length to cx
  1603.     mov    ah,write2
  1604.     int    dos
  1605.                     ; file bytes transferred
  1606.     mov    ax,tfilsz        ; file bytes, low word
  1607.     mov    dx,tfilsz+2        ; high word
  1608.     mov    di,offset rdbuf        ; work buffer
  1609.     call    flnouts            ; transform to ascii
  1610.     mov    [di],0a0dh        ; append cr/lf
  1611.     add    di,2            ; count them
  1612.     mov    dx,offset rdbuf        ; start of work buffer
  1613.     mov    cx,di            ; next free byte
  1614.     sub    cx,dx            ; compute length
  1615.     mov    ah,write2
  1616.     int    dos
  1617.     cmp    dosnum,300h+30        ; DOS 3.30 or higher?
  1618.     jb    endtim11        ; b = no
  1619.     mov    ah,68h            ; Commit the file now
  1620.     int    dos
  1621. endtim11:pop    bx
  1622.     pop    di
  1623. endtim12:mov    tfilsz,0        ; clear file size area
  1624.     mov    tfilsz+2,0
  1625.     mov    al,sflag
  1626.     and    al,1            ; pick out send/receive bit
  1627.     shl    al,1            ; move bit up for file chars/sec
  1628.     mov    sflag,al        ; say have done ending once already
  1629.     mov    fsta.xname,0        ; clear statistics "as" name
  1630.     pop    dx
  1631.     pop    cx
  1632.     pop    ax
  1633.     ret
  1634. fendtim    endp
  1635.  
  1636. ; Convert ch=hh, cl=mm, dh=ss, dl= .s to   dx,ah seconds and al 0.01 seconds
  1637. timewrk    proc    near
  1638.     push    bx
  1639.     mov    bl,dl            ; save fractions of seconds
  1640.     push    bx
  1641.     mov    bl,dh            ; clock seconds
  1642.     xor    bh,bh
  1643.     mov    al,ch            ; get hours
  1644.     mov    ch,60
  1645.     mul    ch            ; ax is minutes
  1646.     add    al,cl            ; add clock minutes
  1647.     adc    ah,0
  1648.     mov    cx,60
  1649.     mul    cx            ; minutes to seconds in dx,ax
  1650.     add    ax,bx            ; add clock seconds
  1651.     adc    dx,0
  1652.     mov    dh,dl            ; move up one byte for 0.01 field
  1653.     mov    dl,ah
  1654.     mov    ah,al
  1655.     pop    bx            ; get old 0.01 field (was dl)
  1656.     mov    al,bl
  1657.     pop    bx
  1658.     ret
  1659. timewrk    endp
  1660.  
  1661. fshosta    proc    far            ; STATISTICS display
  1662.     push    bx
  1663.     push    di
  1664.     mov    dx,offset statmsg    ; header
  1665.     mov    ah,prstr
  1666.     int    dos
  1667.     mov    dx,offset fchmsg    ; File characters msg
  1668.     mov    ah,prstr
  1669.     int    dos
  1670.     mov    di,offset ssta        ; session structure
  1671.     mov    bx,offset fsta        ; last file structure
  1672.     mov    ax,[bx].fsbyte        ; last transfer file bytes sent
  1673.     mov    dx,[bx].fsbyte+2
  1674.     mov    cx,12            ; field width
  1675.     call    shoprt            ; show result
  1676.     mov    ax,[bx].frbyte        ; last transfer file bytes received
  1677.     mov    dx,[bx].frbyte+2
  1678.     call    shoprt            ; show result
  1679.     mov    ax,[di].fsbyte        ; session file bytes sent
  1680.     mov    dx,[di].fsbyte+2
  1681.     call    shoprt            ; show result
  1682.     mov    ax,[di].frbyte        ; session file bytes received
  1683.     mov    dx,[di].frbyte+2
  1684.     call    shoprt            ; show result
  1685.  
  1686.     mov    ah,prstr
  1687.     mov    dx,offset spmsg        ; serial port material
  1688.     int    dos
  1689.     mov    ax,[bx].psbyte        ; last transfer port bytes sent
  1690.     mov    dx,[bx].psbyte+2
  1691.     call    shoprt            ; show result
  1692.     mov    ax,[bx].prbyte        ; last transfer port bytes received
  1693.     mov    dx,[bx].prbyte+2
  1694.     call    shoprt            ; show result
  1695.     mov    ax,[di].psbyte        ; session port bytes sent
  1696.     mov    dx,[di].psbyte+2
  1697.     call    shoprt            ; show result
  1698.     mov    ax,[di].prbyte        ; session port bytes received
  1699.     mov    dx,[di].prbyte+2
  1700.     call    shoprt            ; show result
  1701.  
  1702.     mov    dx,offset pktmsg    ; packets material
  1703.     mov    ah,prstr
  1704.     int    dos
  1705.     mov    ax,[bx].pspkt        ; last transfer packets sent
  1706.     mov    dx,[bx].pspkt+2
  1707.     call    shoprt            ; show result
  1708.     mov    ax,[bx].prpkt        ; last transfer packets received
  1709.     mov    dx,[bx].prpkt+2
  1710.     call    shoprt            ; show result
  1711.     mov    ax,[di].pspkt        ; session packets sent
  1712.     mov    dx,[di].pspkt+2
  1713.     call    shoprt            ; show result
  1714.     mov    ax,[di].prpkt        ; session packets received
  1715.     mov    dx,[di].prpkt+2
  1716.     call    shoprt            ; show result
  1717.  
  1718.     mov    dx,offset nakmsg    ; NAKs material
  1719.     mov    ah,prstr
  1720.     int    dos
  1721.     mov    ax,[bx].nakscnt        ; last transfer NAKs sent
  1722.     xor    dx,dx
  1723.     call    shoprt
  1724.     mov    ax,[bx].nakrcnt        ; last transfer NAKs received
  1725.     xor    dx,dx
  1726.     call    shoprt
  1727.     mov    ax,[di].nakscnt        ; session NAKs sent
  1728.     xor    dx,dx
  1729.     call    shoprt
  1730.     mov    ax,[di].nakrcnt        ; session NAKs received
  1731.     xor    dx,dx
  1732.     call    shoprt
  1733.  
  1734.     mov    dx,offset retmsg    ; retries
  1735.     mov    ah,prstr
  1736.     int    dos
  1737.     mov    ax,[bx].pretry        ; last transfer retry count
  1738.     xor    dx,dx
  1739.     mov    cx,18
  1740.     call    shoprt
  1741.     mov    ax,[di].pretry        ; session retries
  1742.     xor    dx,dx
  1743.     mov    cx,24
  1744.     call    shoprt
  1745.  
  1746.     mov    ah,prstr
  1747.     mov    dx,offset crlf
  1748.     int    dos
  1749.     mov    dx,offset windmsg    ; Window slots used/negotiated
  1750.     int    dos
  1751.     mov    al,winusedmax        ; max used
  1752.     xor    ah,ah
  1753.     xor    dx,dx
  1754.     mov    cx,16
  1755.     call    shoprt
  1756.     mov    ah,prstr
  1757.     mov    dx,offset windmsg2
  1758.     int    dos
  1759.     mov    al,trans.windo        ; negotiated
  1760.     xor    ah,ah
  1761.     xor    dx,dx
  1762.     mov    cx,1
  1763.     call    shoprt
  1764.  
  1765.     mov    dx,offset timemsg    ; elapsed time material
  1766.     mov    ah,prstr
  1767.     int    dos
  1768.     mov    cx,15            ; field width
  1769.     call    shoetime        ; show elapsed time as seconds.01
  1770.     xchg    bx,di            ; put session into bx
  1771.     mov    cx,21            ; field width
  1772.     call    shoetime        ; show elapsed time as seconds.01
  1773.     xchg    bx,di            ; unswap pointers
  1774.  
  1775.     mov    dx,offset chpsmsg    ; File chars per second
  1776.     mov    ah,prstr
  1777.     int    dos
  1778.     mov    ax,[bx].frbyte        ; file bytes received, low
  1779.     mov    dx,[bx].frbyte+2    ; file bytes received, high
  1780.     add    ax,[bx].fsbyte        ; file bytes sent, low
  1781.     adc    dx,[bx].fsbyte+2    ;  high. [dx,ax] = total file bytes
  1782.     call    showrk            ; do worker
  1783.     mov    cx,18
  1784.     call    shoprt            ; show result
  1785.     xchg    bx,di            ; swap session and last file pointers
  1786.     mov    ax,[bx].frbyte        ; file bytes received, low
  1787.     mov    dx,[bx].frbyte+2    ; file bytes received, high
  1788.     add    ax,[bx].fsbyte        ; file bytes sent, low
  1789.     adc    dx,[bx].fsbyte+2    ;  high. [dx,ax] = total file bytes
  1790.     call    showrk            ; do worker
  1791.     xchg    bx,di            ; unswap session and last file pointers
  1792.     mov    cx,24
  1793.     call    shoprt            ; show result
  1794.         
  1795.     mov    dx,offset spedmsg    ; speed material
  1796.     mov    ah,prstr
  1797.     int    dos
  1798.     mov    cx,18            ; field width
  1799.     call    showbps            ; do bps display
  1800.     mov    bx,offset ssta        ; session
  1801.     mov    cx,24            ; field width
  1802.     call    showbps            ; do bps display
  1803.     mov    ah,prstr
  1804.     mov    dx,offset crlf
  1805.     int    dos
  1806.     pop    di
  1807.     pop    bx
  1808.     clc
  1809.     ret
  1810. fshosta    endp
  1811.  
  1812. ; Worker for above. Display [BX].etime as seconds.01, field width in CX
  1813. shoetime proc    near
  1814.     mov    ax,[bx].etime        ; elapsed time of last transfer
  1815.     mov    dx,[bx].etime+2
  1816.     mov    al,ah            ; ignore fractions of seconds
  1817.     mov    ah,dl
  1818.     mov    dl,dh
  1819.     xor    dh,dh
  1820.     call    shoprt            ; show result, cx has field width
  1821.     mov    ah,conout
  1822.     mov    dl,'.'
  1823.     int    dos
  1824.     cmp    byte ptr [bx].etime,9    ; small qty of 0.01 sec units?
  1825.     ja    shoetim1        ; a = no
  1826.     mov    dl,'0'
  1827.     int    dos
  1828. shoetim1:mov    al,byte ptr [bx].etime    ; 0.01 sec units
  1829.     xor    ah,ah
  1830.     xor    dx,dx
  1831.     mov    cx,1
  1832.     call    shoprt
  1833.     ret
  1834. shoetime endp
  1835.  
  1836. ; Worker for above
  1837. ; Display baud rate as  10 * total port bytes / elapsed time
  1838. ; BX has structure offset, CX has field width
  1839. showbps    proc    near
  1840.     mov    ax,[bx].prbyte        ; port bytes received, low
  1841.     mov    dx,[bx].prbyte+2    ; port bytes received, high
  1842.     add    ax,[bx].psbyte        ; port bytes sent, low
  1843.     adc    dx,[bx].psbyte+2    ;  high. [dx,ax] = total port bytes
  1844.     push    cx
  1845.     push    bx
  1846.     push    ax            ; save low order part
  1847.     mov    cx,10
  1848.     mov    ax,dx            ; high order part
  1849.     mul    cx            ; high part times 10
  1850.     mov    bx,ax            ; save low order result
  1851.     pop    ax
  1852.     mul    cx            ; low times 10
  1853.     add    dx,bx            ; add high parts
  1854.     pop    bx
  1855.     call    showrk            ; do worker for bytes/sec
  1856.     pop    cx            ; recover field width
  1857.     call    shoprt            ; show result
  1858.     ret
  1859. showbps    endp
  1860.  
  1861. ; Display SHOW STATISTICS line. Enter with dx,ax with long value, cx = width
  1862. fshoprt proc    far
  1863.     call    shoprt
  1864.     ret
  1865. fshoprt    endp
  1866.  
  1867. shoprt    proc    near
  1868.     push    di
  1869.     mov    di,offset rdbuf        ; work space for output
  1870.     call    flnouts            ; show long integer, with separator
  1871.     pop    di
  1872.     mov    dx,offset rdbuf
  1873.     push    bx
  1874.     push    cx
  1875.     push    dx
  1876.     mov    bx,cx            ; field width
  1877.     call    fstrlen            ; length of string in dx
  1878.     sub    bx,cx            ; number of spaces necessary
  1879.     xchg    bx,cx
  1880.     jle    shoprt2            ; le = no spaces
  1881.     mov    dl,' '
  1882.     mov    ah,conout
  1883. shoprt1:int    dos            ; display the leading spaces
  1884.     loop    shoprt1
  1885. shoprt2:pop    dx
  1886.     pop    cx
  1887.     pop    bx
  1888.     call    fprtasz            ; display asciiz string
  1889.     ret
  1890. shoprt    endp
  1891.  
  1892. ; Divide long number in dx,ax by [bx].elapsed time (seconds).
  1893. ; Return result back in dx,ax
  1894. fshowrk proc    far
  1895.     call    showrk
  1896.     ret
  1897. fshowrk    endp
  1898.  
  1899. showrk    proc    near
  1900.     mov    cx,[bx].etime+1        ; low word of sec in cx
  1901.     cmp    byte ptr [bx].etime+2,0    ; high byte of sec zero (< 65536 sec)?
  1902.     jz    showrk1            ; z = yes, ready for arithmetic
  1903.     push    ax            ; else scale values, save byte count
  1904.     push    dx
  1905.     mov    ax,[bx].etime+1        ; elapsed time for file, low word
  1906.     mov    dl,byte ptr [bx].etime+3 ;  high byte
  1907.     xor    dh,dh            ;  ignoring fractions of second
  1908.     shr    ax,1            ; divide seconds by two, low word
  1909.     ror    dx,1            ; get low bit of high word
  1910.     and    dx,8000            ; pick out just that bit
  1911.     or    ax,dx        ; mask in that bit, new time in ax (dx = 0)
  1912.     mov    cx,ax            ; save elapsed time (double-seconds)
  1913.     pop    dx            ; get byte count again
  1914.     pop    ax
  1915.     shr    ax,1            ; divide byte count by two also
  1916.     push    dx
  1917.     ror    dx,1            ; rotate low bit to high position
  1918.     and    dx,8000h        ; get low bit of high word
  1919.     or    ax,dx            ; byte count divided by two, low word
  1920.     pop    dx
  1921.     shr    dx,1            ; and high word
  1922.     jmp    short showrk2
  1923.  
  1924. showrk1:cmp    cx,30            ; small amount of elapsed time?
  1925.     ja    showrk2            ; a = no
  1926.     push    bx
  1927.     push    si
  1928.     mov    bx,100            ; scale in the 0.01 sec part
  1929.     push    ax            ; save low order top
  1930.     mov    ax,dx            ; high order top
  1931.     mul    bx
  1932.     mov    si,ax            ; low order result
  1933.     pop    ax
  1934.     mul    bx            ; low order top
  1935.     add    dx,si            ; dx,ax * 100 in dx,ax
  1936.     push    ax
  1937.     mov    ax,cx            ; seconds
  1938.     mul    bl            ; to units of 0.01 seconds
  1939.     mov    cx,ax
  1940.     pop    ax
  1941.     pop    si
  1942.     pop    bx
  1943.     add    cl,byte ptr [bx].etime    ; 0.01 sec units
  1944.     adc    ch,0            ; elapsed time seconds * 100
  1945.     or    cx,cx
  1946.     jnz    showrk2            ; have a divisor
  1947.     inc    cx            ; else make it 1 (0.01 sec)
  1948.  
  1949. showrk2:push    bx            ; divide dx,ax by cx, results to dx,ax
  1950.     push    ax
  1951.     mov    ax,dx
  1952.     xor    dx,dx
  1953.     div    cx            ; ax = high quo, dx = high rem
  1954.     mov    bx,ax            ; save high quotient
  1955.     pop    ax
  1956.     div    cx               ; bytes div seconds, ax = quo, dx = rem
  1957.     shl    dx,1            ; remainder * 2
  1958.     cmp    dx,cx            ; round up?
  1959.     jb    showrk3            ; b = no
  1960.     add    ax,1            ; round up
  1961.     adc    bx,0
  1962. showrk3:mov    dx,bx            ; previous high quotient
  1963.     pop    bx
  1964.     ret
  1965. showrk    endp
  1966.  
  1967. fshomdef proc    FAR            ; worker, show mac name and def
  1968.     push    ax            ; call with si pointing at macro
  1969.     push    si            ; name, word ptr [si-2] = length
  1970.     push    es
  1971.     cmp    byte ptr[si],0        ; name starts with null char?
  1972.     jne    shomd1            ; ne = no
  1973.     jmp    shomd9            ; yes, TAKE file, ignore
  1974. shomd1:    call    shomdl            ; do newline, check for more/exit
  1975.     jnc    shomd2            ; nc = continue
  1976.     jmp    shomd9            ; exit
  1977. shomd2:    mov    ah,conout
  1978.     mov    dl,' '            ; add a space
  1979.     int    dos
  1980.     inc    bx
  1981.     inc    temp            ; count displayed macros
  1982.     push    cx
  1983.     push    di
  1984.     mov    cx,[si-2]        ; length of definition
  1985.     mov    di,si            ; offset for printing
  1986.     call    fprtscr            ; print counted string
  1987.     pop    di
  1988.     pop    cx
  1989.     mov    ah,prstr
  1990.     mov    dx,offset eqs        ; display equals sign
  1991.     int    dos
  1992.     mov    denom,1            ; set flag to do "," to <cr>
  1993.     cmp    word ptr [si],'%\'    ; substitution variable?
  1994.     jne    shomd2a            ; ne = no
  1995.     mov    denom,0            ; clear bare comma sensitivity flag
  1996. shomd2a:mov    ax,[si-2]        ; length of macro name
  1997.     add    si,ax            ; skip over name
  1998.     add    bx,ax            ; count of chars on line
  1999.     add    bx,3            ; plus " = "
  2000.     mov    es,[si]            ; segment of string structure
  2001.     xor    si,si            ; es:si = address of count + string
  2002.     mov    cx,es:[si]        ; length of string
  2003.     add    si,2            ; si = offset of string text proper
  2004. shomd3:    mov    al,es:[si]        ; get a byte into al
  2005.     inc    si
  2006.     call    shombrk            ; examine for bare comma break
  2007.     cmp    al,' '            ; control char?
  2008.     jae    shomd5            ; ae = no
  2009.     cmp    al,cr            ; carriage return?
  2010.     jne    shomd4            ; ne = no
  2011.     mov    ah,prstr
  2012.     mov    dx,offset shom9m4    ; show <cr>
  2013.     int    dos
  2014.     add    bx,4            ; chars on line
  2015.     cmp    cx,1            ; more to show?
  2016.     je    shomd6            ; e = no
  2017.     call    shomdl            ; new line, check for continue or exit
  2018.     jc    shomd9            ; c = exit
  2019.     mov    ah,conout        ; show two spaces
  2020.     mov    dl,' '            ; the spaces
  2021.     int    dos
  2022.     int    dos
  2023.     add    bx,2
  2024.     cmp    byte ptr es:[si],lf    ; cr followed by linefeed?
  2025.     jne    short shomd6        ; ne = no
  2026.     inc    si            ; skip the leading lf
  2027.     dec    cx
  2028.     jmp    short shomd6
  2029. shomd4:    push    ax
  2030.     mov    ah,conout
  2031.     mov    dl,5eh            ; caret
  2032.     int    dos
  2033.     pop    ax
  2034.     inc    bx
  2035.     add    al,'A'-1        ; add offset to make printable letter
  2036. shomd5:    mov    ah,conout
  2037.     mov    dl,al            ; display it
  2038.     int    dos
  2039.     inc    bx
  2040. shomd6:    cmp    bx,75            ; time to break the line?
  2041.     jb    shomd8            ; b = no
  2042.     cmp    bx,76            ; at an absolute break point
  2043.     jae    shomd7            ; ae = yes
  2044.     cmp    byte ptr es:[si],' '    ; is next char a space?
  2045.     je    shomd8            ; e = yes, show explicitly
  2046. shomd7:    mov    ah,conout        ; display a line break hyphen
  2047.     mov    dl,'-'
  2048.     int    dos
  2049.     call    shomdl            ; check for screen full
  2050.     jc    shomd9            ; c = exit now
  2051.     mov    ah,conout        ; show two spaces
  2052.     xor    bx,bx            ; column counter
  2053. shomd8:    loop    shomd3            ; do whole string
  2054. shomd9:    pop    es
  2055.     pop    si
  2056.     pop    ax
  2057.     ret
  2058.                       ; worker, do "more" and Control-C checking
  2059. shomdl    proc    near
  2060.     inc    temp1            ; count lines displayed
  2061.     xor    bx,bx            ; count of chars on the line
  2062.     cmp    temp1,24        ; done a normal screens' worth?
  2063.     jb    shomdl2            ; b = no
  2064.     mov    ah,prstr
  2065.     mov    dx,offset moremsg    ; say more
  2066.     int    dos
  2067.     mov    temp1,0
  2068.     mov    flags.cxzflg,0        ; clear flag so we can see Control-C
  2069.     mov    ah,0ch            ; clear keyboard buffer
  2070.     mov    al,coninq        ; quiet input
  2071.     int    dos
  2072.     cmp    al,3            ; Control-C?
  2073.     je    shomdl1            ; e = yes
  2074.     cmp    al,'q'            ; q for quit?
  2075.     je    shomdl1            ; e = yes
  2076.     cmp    al,'Q'            ; Q for quit?
  2077.     je    shomdl1            ; e = yes
  2078.     or    al,al            ; scan code?
  2079.     jne    shomdl2            ; ne = no
  2080.     mov    ah,coninq        ; read the second byte
  2081.     int    dos
  2082.     or    al,al            ; null for Control-Break?
  2083.     jne    shomdl2            ; ne = no
  2084. shomdl1:mov    flags.cxzflg,'C'    ; say want to exit now
  2085. shomdl2:mov    ah,prstr
  2086.     mov    dx,offset crlf
  2087.     int    dos
  2088.     cmp    flags.cxzflg,0        ; want to exit?
  2089.     jne    shomdl3            ; ne = yes
  2090.     clc
  2091.     ret
  2092. shomdl3:stc                ; say exit now
  2093.     ret
  2094. shomdl    endp
  2095.  
  2096. ; Examine char in al. If it is a bare comma and byte ptr denom is non-zero
  2097. ; then change AL to Carriage return else return AL unchanged.
  2098. shombrk    proc    near
  2099.     push    dx
  2100.     mov    dx,denom        ; dh=brace cnt, dl=1 for sensitivity
  2101.     or    dl,dl            ; worry about bare commas?
  2102.     jz    shombr3            ; z = no
  2103.     cmp    al,braceop        ; opening brace?
  2104.     jne    shombr1            ; ne = no
  2105.     inc    dh            ; count brace level
  2106. shombr1:cmp    al,bracecl        ; closing brace?
  2107.     jne    shombr2
  2108.     sub    dh,1            ; count down brace level
  2109.     jns    shombr2            ; ns = not below zero
  2110.     xor    dh,dh            ; set brace level to zero
  2111. shombr2:mov    denom,dx        ; store our brace state
  2112.     or    dh,dh            ; inside braces?
  2113.     jnz    shombr3            ; nz = yes
  2114.     cmp    al,','            ; bare comma?
  2115.     jne    shombr3            ; ne = no
  2116.     mov    al,CR            ; replace with bare CR
  2117. shombr3:pop    dx
  2118.     ret
  2119. shombrk    endp
  2120. fshomdef endp
  2121.  
  2122. fshovar    proc    FAR            ; worker for SHOW VARIABLE, SHOVAR
  2123.     cmp    word ptr rdbuf,'v\'    ; did user say \v(name)?
  2124.     jne    fshova2            ; ne = no
  2125.     mov    di,offset rdbuf        ; start plus count
  2126.     mov    si,di
  2127.     add    si,3            ; remove \v(
  2128.     mov    cx,shmcnt        ; length of user spec
  2129.     sub    cx,3
  2130.     mov    shmcnt,cx        ; remember "variable)" part
  2131.     jle    fshova1            ; le = nothing left
  2132.     inc    cx            ; include null in the move
  2133.     mov    ax,ds
  2134.     mov    es,ax
  2135.     cld
  2136.     rep    movsb            ; copy down
  2137.     mov    si,offset rdbuf
  2138.     add    si,shmcnt
  2139.     cmp    byte ptr [si-1],')'    ; did user say ')'?
  2140.     jne    fshova2            ; ne = no
  2141.     mov    byte ptr [si-1],0    ; remove it
  2142.     dec    shmcnt
  2143.     jmp    short fshova2
  2144. fshova1:mov    shmcnt,0        ; make user entry empty
  2145. fshova2:mov    si,offset valtab    ; table of variable names
  2146.     cld
  2147.     lodsb
  2148.     mov    cl,al            ; number of variable entries
  2149.     xor    ch,ch
  2150.     jcxz    fshova7            ; z = none
  2151. fshova3:push    cx            ; save loop counter
  2152.     lodsw                ; length of var name, incl ')'
  2153.     mov    cx,shmcnt        ; length of user's string
  2154.     jcxz    fshova5            ; show all names
  2155.     push    ax            ; save length
  2156.     dec    ax            ; omit ')'
  2157.     cmp    ax,cx            ; var name shorter that user spec?
  2158.     pop    ax            ; recover full length
  2159.     jb    fshova6            ; b = yes, no match
  2160.     push    ax
  2161.     push    si            ; save these around match test
  2162.     mov    di,offset rdbuf        ; user's string
  2163. fshova4:mov    ah,[di]
  2164.     inc    di
  2165.     lodsb                ; al = var name char, ah = user char
  2166.     and    ax,not 2020h        ; clear bits (uppercase chars)
  2167.     cmp    ah,al            ; same?
  2168.     loope    fshova4            ; while equal, do more
  2169.     pop    si            ; restore regs
  2170.     pop    ax
  2171.     jne    fshova6            ; ne = no match
  2172. fshova5:call    fshova8            ; show this name
  2173. fshova6:add    si,ax            ; point to next name, add name length
  2174.     add    si,2            ; and string pointer
  2175.     pop    cx            ; recover loop counter
  2176.     cmp    flags.cxzflg,0        ; does user wish to stop now?
  2177.     jne    fshova7            ; ne = yes
  2178.     loop    fshova3            ; one less macro to examine
  2179. fshova7:mov    flags.cxzflg,0        ; clear flag before exiting
  2180.     ret
  2181.  
  2182. fshova8    proc    near            ; worker for above
  2183.     push    ax
  2184.     mov    ah,prstr
  2185.     mov    dx,offset varstng    ; put out <cr><lf>" \v("
  2186.     int    dos
  2187.     push    si
  2188.     push    cx
  2189.     mov    cx,[si-2]        ; length of name
  2190. fshova9:mov    dl,[si]            ; get a variable character
  2191.     inc    si            ; prep for next char
  2192.     mov    ah,conout
  2193.     int    dos
  2194.     loop    fshova9            ; do the count
  2195.     mov    dl,' '            ; display " = "
  2196.     int    dos
  2197.     mov    dl,'='
  2198.     int    dos
  2199.     mov    dl,' '
  2200.     int    dos
  2201.     mov    bx,[si]            ; get result code to bx
  2202.     xor    dx,dx            ; trim off trailing spaces
  2203.     call    fnvaltoa        ; fill valbuf with string
  2204.     jc    fshova10        ; c = failure
  2205.     mov    cx,di            ; di is string length
  2206.     mov    di,offset valbuf+2    ; string text (skips count word)
  2207.     call    fprtscr            ; display counted string
  2208. fshova10:pop    cx
  2209.     pop    si
  2210.     pop    ax
  2211.     ret
  2212. fshova8    endp                ; end of worker
  2213. fshovar    endp
  2214.  
  2215. code1    ends
  2216.  
  2217. code    segment
  2218.     assume cs:code
  2219.  
  2220. ; SHOW TRANSLATE-RECEIVE
  2221. ; Display characters being changed for Connect mode serial receive translator
  2222.  
  2223. SHORX    PROC    NEAR            ; show translate table of incoming
  2224.                     ; chars, only those changed
  2225.     mov    ah,cmeol        ; get a confirm
  2226.     call    comnd
  2227.     jnc    shorx0a            ; nc = success
  2228.     ret                ; failure
  2229. shorx0a:
  2230.     mov    ah,prstr
  2231.     mov    dx,offset crlf
  2232.     int    dos
  2233.     mov    bx,offset shorxk    ; show keyboard translation
  2234.     call    statc
  2235.     mov    ah,prstr
  2236.     mov    dx,offset rxoffmsg    ; assume translation is off
  2237.     cmp    rxtable+256,0        ; is translation off?
  2238.     je    shorx0            ; e = yes
  2239.     mov    dx,offset rxonmsg    ; say translation is on
  2240. shorx0:    int    dos
  2241.     mov    dx,offset shormsg    ; give title line
  2242.     int    dos
  2243.     xor    cx,cx            ; formatted line counter
  2244.     xor    bx,bx            ; entry subscript
  2245. shorx1:    cmp    rxtable[bx],bl        ; entry same as normal?
  2246.     je    shorx2            ; e = yes, skip it
  2247.     call    shorprt            ; display the entry
  2248. shorx2:    inc    bx            ; next entry
  2249.     cmp    bx,255            ; done all entries yet?
  2250.     jbe    shorx1            ; be = not yet
  2251.     mov    ah,prstr
  2252.     mov    dx,offset crlf        ; end with cr/lf
  2253.     int    dos
  2254.     clc                ; success
  2255.     ret
  2256.                     ; worker routine
  2257. shorprt:cmp    cx,4            ; done five entries for this line?
  2258.     jb    shorpr1            ; b = no
  2259.     mov    ah,prstr
  2260.     mov    dx,offset crlf        ; break line now
  2261.     int    dos
  2262.     xor    cx,cx
  2263. shorpr1:mov    ah,prstr
  2264.     mov    dx,offset shopm1    ; start of display
  2265.     int    dos
  2266.     xor    ah,ah
  2267.     mov    al,bl            ; original byte code
  2268.     call    decout            ; display its value
  2269.     mov    ah,prstr
  2270.     mov    dx,offset shopm2    ; intermediate part of display
  2271.     int    dos
  2272.     xor    ah,ah
  2273.     mov    al,rxtable[bx]        ; new byte code
  2274.     call    decout            ; display its value
  2275.     mov    ah,prstr
  2276.     mov    dx,offset shopm3    ; last part of display
  2277.     int    dos
  2278.     inc    cx            ; count item displayed
  2279.     ret
  2280. SHORX    ENDP
  2281.  
  2282. ; SHOW MACRO [macro name]
  2283.  
  2284. SHOMAC    PROC    NEAR
  2285.     mov    ah,cmword
  2286.     mov    dx,offset rdbuf
  2287.     mov    bx,offset shmmsg
  2288.     mov    comand.cmper,1        ; don't react to \%x variables
  2289.     call    comnd
  2290.     jnc    shoma1a            ; nc = success
  2291.     ret                ; failure
  2292. shoma1a:mov    shmcnt,ax        ; save length of user spec
  2293.     mov    ah,cmeol
  2294.     call    comnd
  2295.     jnc    shoma1b            ; nc = success
  2296.     ret                ; failure
  2297. shoma1b:mov    si,offset mcctab    ; table of macro names
  2298.     cld
  2299.     lodsb
  2300.     mov    cl,al            ; number of macro entries
  2301.     xor    ch,ch
  2302.     jcxz    shom6            ; z = none
  2303.     mov    temp,0            ; count of macros displayed
  2304.     mov    temp1,0            ; lines displayed, for more message
  2305. shom2:    push    cx            ; save loop counter
  2306.     lodsw                ; length of macro name
  2307.     mov    cx,shmcnt        ; length of user's string
  2308.     jcxz    shom4            ; show all names
  2309.     cmp    ax,cx            ; mac name shorter that user spec?
  2310.     jb    shom5            ; b = yes, no match
  2311.     push    ax
  2312.     push    si            ; save these around match test
  2313.     mov    di,offset rdbuf        ; user's string
  2314. shom3:    mov    ah,[di]
  2315.     inc    di
  2316.     lodsb                ; al = mac name char, ah = user char
  2317.     and    ax,not 2020h        ; clear bits (uppercase chars)
  2318.     cmp    ah,al            ; same?
  2319.     loope    shom3            ; while equal, do more
  2320.     pop    si            ; restore regs
  2321.     pop    ax
  2322.     jne    shom5            ; ne = no match
  2323. shom4:    call    fshomdef        ; show this name (FAR)
  2324. shom5:    add    si,ax            ; point to next name, add name length
  2325.     add    si,2            ;  and string pointer
  2326.     pop    cx            ; recover loop counter
  2327.     cmp    flags.cxzflg,0        ; does user wish to stop now?
  2328.     jne    shom5a            ; ne = yes
  2329.     loop    shom2            ; one less macro to examine
  2330. shom5a:    mov    flags.cxzflg,0        ; clear flag before exiting
  2331.     cmp    temp,0            ; did we show any macros?
  2332.     jne    shom7            ; ne = yes
  2333. shom6:    mov    ah,prstr
  2334.     mov    dx,offset shom9m3    ; no entries found
  2335.     int    dos
  2336. shom7:    mov    ah,prstr        ; Summary line
  2337.     mov    dx,offset shom9m1    ; free space: name entries
  2338.     int    dos
  2339.     mov    ax,offset mcctab+mcclen
  2340.     sub    ax,mccptr        ; compute # of free name bytes
  2341.     call    decout
  2342.     mov    ah,prstr
  2343.     mov    dx,offset crlf
  2344.     int    dos
  2345.     clc                ; success
  2346.     ret
  2347. SHOMAC    ENDP
  2348.  
  2349. SHCOM    PROC    NEAR            ; Show Modem
  2350.     mov    ah,cmeol
  2351.     call    comnd            ; get a confirm
  2352.     jc    shcom1            ; c = failure
  2353.     mov    dx,offset crlf
  2354.     mov    ah,prstr
  2355.     int    dos            ; print a crlf
  2356.     mov    bx,offset stcom        ; table of items to be shown
  2357.     call    statc            ; finish in common code
  2358.     call    shomodem
  2359.     clc
  2360. shcom1:    ret
  2361. SHCOM    ENDP
  2362.  
  2363. SHFILE    PROC    NEAR            ; Show File
  2364.     mov    ah,cmeol
  2365.     call    comnd            ; get a confirm
  2366.     jnc    shfile1            ; nc = success
  2367.     ret                ; failure
  2368. shfile1:mov    dx,offset crlf
  2369.     mov    ah,prstr
  2370.     int    dos            ; print a crlf
  2371.     mov    bx,offset stfile    ; table of items to be shown
  2372.     jmp    statc            ; finish in common code
  2373. SHFILE    ENDP
  2374.  
  2375. SHLOG    PROC    NEAR            ; Show Log
  2376.     mov    ah,cmeol
  2377.     call    comnd            ; get a confirm
  2378.     jnc    shlog1            ; nc = success
  2379.     ret                ; failure
  2380. shlog1:    mov    dx,offset crlf
  2381.     mov    ah,prstr
  2382.     int    dos            ; print a crlf
  2383.     mov    bx,offset stlog        ; table of items to be shown
  2384.     jmp    statc            ; finish in common code
  2385. SHLOG    ENDP
  2386.  
  2387. SHMEM    PROC    NEAR            ; Show (free) Memory.   Recursive!
  2388.     mov    ah,cmeol
  2389.     call    comnd            ; get a confirm
  2390.     jnc    shmem1            ; nc = success
  2391.     ret                ; failure
  2392. shmem1:    mov    ah,prstr
  2393.     mov    dx,offset memmsg1    ; header message
  2394.     int    dos
  2395.     mov    word ptr rdbuf,'  '    ; two spaces
  2396.     mov    rdbuf+2,0        ; safety null terminator
  2397.     mov    di,offset rdbuf+1    ; look at first space
  2398.     mov    temp,0            ; total free memory
  2399.     mov    temp1,0            ;  and high word thereof
  2400.     push    es            ; save es
  2401.     call    shmem4            ; allocate memory, recursively
  2402.     mov    dx,offset rdbuf        ; output buffer
  2403.     call    prtasz            ; show pieces
  2404.     mov    dx,offset memmsg2    ; trailer
  2405.     mov    ah,prstr
  2406.     int    dos
  2407.     mov    di,offset rdbuf        ; setup buffer for lnout
  2408.     mov    rdbuf,0
  2409.     mov    ax,temp            ; total free space
  2410.     mov    dx,temp1
  2411.     call    lnouts            ; 32 bit to decimal ascii in di
  2412.     mov    dx,offset rdbuf        ;  with thousands separator
  2413.     call    prtasz
  2414.     pop    es
  2415.     ret
  2416.                     ; worker routine
  2417. shmem4:    mov    bx,0ffffh        ; allocate all memory (must fail)
  2418.     mov    ah,alloc        ; DOS memory allocator
  2419.     int    dos            ; returns available paragraphs in bx
  2420.     jnc    shmem6            ; nc = got it all (not very likely)
  2421.     or    bx,bx            ; bx = # paragraphs alloc'd. Anything?
  2422.     jz    shmem5            ; z = no
  2423.     mov    ah,alloc        ; consume qty now given in bx
  2424.     int    dos
  2425.     jnc    shmem6            ; nc = got the fragment
  2426. shmem5:    ret
  2427. shmem6:    push    ax            ; save allocation segment
  2428.     mov    ax,bx            ; convert paragraphs
  2429.     mul    sixteen            ;  to bytes in dx:ax
  2430.     add    temp,ax            ; running total
  2431.     adc    temp1,dx        ;  32 bits
  2432.     cmp    byte ptr [di],0        ; starting on a null?
  2433.     jne    shmem7            ; ne = no, skip punctuation
  2434.     mov    byte ptr [di],'+'    ; plus punctuation
  2435.     inc    di
  2436. shmem7:    call    lnouts            ; long number to decimal in buffer di
  2437.     call    shmem4            ; recurse
  2438.     pop    es            ; recover allocation segment
  2439.     mov    ah,freemem        ; free the allocation
  2440.     int    dos
  2441.     ret
  2442. SHMEM    ENDP
  2443.  
  2444. SHPRO    PROC    NEAR            ; Show Protocol
  2445.     mov    ah,cmeol
  2446.     call    comnd            ; get a confirm
  2447.     jnc    shpro1            ; nc = success
  2448.     ret                ; failure
  2449. shpro1:    mov    dx,offset crlf
  2450.     mov    ah,prstr
  2451.     int    dos            ; print a crlf
  2452.     mov    bx,offset stpro        ; table of items to be shown
  2453.     jmp    statc            ; finish in common code
  2454. SHPRO    ENDP
  2455.  
  2456. SHSCPT    PROC    NEAR            ; Show Script
  2457.     mov    ah,cmeol
  2458.     call    comnd            ; get a confirm
  2459.     jnc    shscpt1            ; nc = success
  2460.     ret                ; failure
  2461. shscpt1:mov    dx,offset crlf
  2462.     mov    ah,prstr
  2463.     int    dos            ; print a crlf
  2464.     mov    bx,offset stscpt    ; table of items to be shown
  2465.     jmp    statc            ; finish in common code
  2466. SHSCPT    ENDP
  2467.  
  2468. SHSERV    PROC    NEAR            ; Show Server
  2469.     mov    ah,cmeol
  2470.     call    comnd            ; get a confirm
  2471.     jnc    shserv1            ; nc = success
  2472.     ret                ; failure
  2473. shserv1:mov    dx,offset crlf
  2474.     mov    ah,prstr
  2475.     int    dos            ; print a crlf
  2476.     mov    bx,offset stserv2    ; do timeout item
  2477.     call    statc
  2478.     mov    dx,offset crlf
  2479.     mov    ah,prstr
  2480.     int    dos
  2481.     mov    bx,offset stserv    ; table of items to be shown
  2482.     jmp    statc            ; finish in common code
  2483. SHSERV    ENDP
  2484.  
  2485. SHTERM    PROC    NEAR            ; Show Terminal
  2486.     mov    ah,cmeol
  2487.     call    comnd            ; get a confirm
  2488.     jnc    shterm1            ; nc = success
  2489.     ret                ; failure
  2490. shterm1:mov    dx,offset crlf
  2491.     mov    ah,prstr
  2492.     int    dos            ; print a crlf
  2493.     mov    bx,offset stterm    ; table of items to be shown
  2494.     jmp    statc            ; use common code
  2495. SHTERM    ENDP
  2496.  
  2497. ; SHOW VAR of kind \v(name)
  2498. SHOVAR    proc    near
  2499.     mov    ah,cmword
  2500.     mov    dx,offset rdbuf
  2501.     mov    bx,offset shvmsg
  2502.     mov    comand.cmper,1        ; don't react to \%x variables
  2503.     call    comnd
  2504.     jnc    shovar1            ; nc = success
  2505.     ret                ; failure
  2506. shovar1:mov    shmcnt,ax        ; save length of user spec
  2507.     mov    ah,cmeol
  2508.     call    comnd
  2509.     jnc    shovar2            ; nc = success
  2510.     ret                ; failure
  2511. shovar2:call    fshovar            ; call FAR worker
  2512.     ret
  2513. SHOVAR    endp
  2514.  
  2515. begtim    proc    near
  2516.     call    fbegtim            ; call the real FAR routine
  2517.     ret
  2518. begtim    endp
  2519. endtim    proc    near
  2520.     call    fendtim            ; call the real FAR routine
  2521.     ret
  2522. endtim    endp
  2523.  
  2524. ; SHOW STATISTICS command. Displays last operation and session statistics
  2525. shosta    proc    near            ; show file transfer statistics
  2526.     mov    ah,cmeol        ; confirm with carriage return
  2527.     call    comnd
  2528.     jnc    shosta1
  2529.     ret                ; failure
  2530. shosta1:xor    ax,ax
  2531.     call    endtim            ; update statistics, just in case
  2532.     call    fshosta            ; do a far call to worker
  2533.     ret
  2534. shosta    endp
  2535.  
  2536. ; STATUS command
  2537.  
  2538. STATUS    PROC    NEAR
  2539.     mov    ah,cmeol
  2540.     call    comnd            ; get a confirm
  2541.     jnc    stat0a            ; nc = success
  2542.     ret                ; failure
  2543. stat0a:    mov    dx,offset crlf
  2544.     mov    ah,prstr
  2545.     int    dos            ; print a crlf
  2546.                     ; STAT0 is an external ref (in mster)
  2547. STAT0:    call    cmblnk            ; clear the screen
  2548.     call    locate            ; home the cursor
  2549.     mov    bx,offset sttab        ; table to control printing
  2550.     xor    cx,cx            ; column counter
  2551.                     ; STATC is external ref in msx
  2552. STATC:    cmp    word ptr [bx],0        ; end of table?
  2553.     je    statx            ; e = yes
  2554.     cld                ; string direction is forward
  2555.     push    ds
  2556.     pop    es
  2557.     mov    di,offset rdbuf        ; point to destination buffer
  2558.     mov    byte ptr[di],spc    ; start with two spaces
  2559.     inc    di
  2560.     mov    byte ptr[di],spc
  2561.     inc    di
  2562.     push    cx            ; save column number
  2563.     push    bx
  2564.     call    [bx].sttyp        ; call appropriate routine
  2565.     pop    bx
  2566.     pop    cx
  2567.     sub    di,offset rdbuf        ; number of bytes used
  2568.     add    cx,di            ; new line col count
  2569.     push    cx            ; save col number around print
  2570.     mov    cx,di            ; how much to print now
  2571.     mov    di,offset rdbuf        ; source text
  2572.     cmp    cx,2            ; nothing besides our two spaces?
  2573.     jbe    stat5            ; e = yes, forget it
  2574.     call    prtscr            ; print counted string
  2575. stat5:    pop    cx
  2576.     add    bx,size stent        ; look at next entry
  2577.     cmp    word ptr [bx],0        ; at end of table?
  2578.     je    statx            ; e = yes
  2579.     cmp    cx,38            ; place for second display?
  2580.     jbe    stat2            ; be = only half full
  2581.     mov    dx,offset crlf        ; over half full. send cr/lf
  2582.     mov    ah,prstr
  2583.     int    dos
  2584.     xor    cx,cx            ; say line is empty now
  2585.     jmp    statc
  2586. stat2:    mov    ax,cx
  2587.     mov    cx,38            ; where we want to be next time
  2588.     sub    cx,ax            ; compute number of filler spaces
  2589.     or    cx,cx
  2590.     jle    stat4            ; nothing to do
  2591.     mov    ah,conout
  2592.     mov    dl,' '
  2593. stat3:    int    dos            ; fill with spaces
  2594.     loop    stat3            ; do cx times
  2595. stat4:    mov    cx,38            ; current column number
  2596.     jmp    statc            ; and do it
  2597. statx:    clc
  2598.     ret
  2599. STATUS    ENDP
  2600.  
  2601. ; handler routines for status
  2602. ; all are called with di/ destination buffer, bx/ stat ptr. They can change
  2603. ; any register except es:, must update di to the end of the buffer.
  2604.  
  2605.  
  2606. ; Copy dollar sign terminated string to buffer pointed at by preset di.
  2607. stmsg    proc    near
  2608.     push    ds
  2609.     pop    es        ; ensure es points to data segment
  2610.     mov    si,[bx].msg    ; get message address
  2611. stms1:    lodsb            ; get a byte
  2612.     stosb            ; drop it off
  2613.     or    al,al        ; ending on null?
  2614.     jz    stms2        ; z = yes
  2615.     cmp    al,'$'        ; end of message?
  2616.     jne    stms1        ; no, keep going
  2617. stms2:    dec    di        ; else back up ptr
  2618.     ret
  2619. stmsg    endp
  2620.  
  2621. ; get address of test value in stent. Returns address in si
  2622. stval    proc    near
  2623.     mov    si,[bx].basval    ; get base value
  2624.     or    si,si        ; any there?
  2625.     jz    stva1        ; z = no, keep going
  2626.     mov    si,[si]        ; yes, use as base address
  2627. stva1:    add    si,[bx].tstcel    ; add offset of test cell
  2628.     ret            ; and return it
  2629. stval    endp
  2630.  
  2631. ; print a single character
  2632. onechr    proc    near
  2633.     call    stmsg        ; copy message part first
  2634.     call    stval        ; pick up test value address
  2635.     mov    al,[si]        ; this is char to print
  2636.     cmp    al,7fh        ; in graphics region?
  2637.     jb    onech2        ; b = no
  2638.     mov    byte ptr [di],'\' ; do in \numerical form
  2639.     inc    di
  2640.     xor    ah,ah        ; clear high byte
  2641.     jmp    outnum        ; do number part
  2642. onech2:    cmp    al,' '        ; printable?
  2643.     jae    onech1        ; yes, keep going
  2644.     add    al,64        ; make printable
  2645.     mov    byte ptr [di],5eh    ; caret
  2646.     inc    di        ; note ctrl char
  2647. onech1:    stosb            ; drop char off
  2648.     ret
  2649. onechr    endp
  2650.  
  2651. ; numeric field
  2652. stnum    proc    near        ; for 8 bit numbers
  2653.     call    stmsg        ; copy message
  2654.     call    stval        ; pick up value address
  2655.     mov    al,[si]        ; get value
  2656.     xor    ah,ah        ; high order is 0
  2657.     jmp    outnum        ; put number into buffer
  2658. stnum    endp
  2659.  
  2660. stlnum    proc    near        ; for 16 bit numbers
  2661.     call    stmsg        ; copy message
  2662.     call    stval        ; pick up value address
  2663.     mov    ax,[si]        ; get value
  2664.     jmp    outnum        ; put number into buffer
  2665. stlnum    endp
  2666.  
  2667. ; translate the number in ax
  2668. outnum    proc    near
  2669.     xor    dx,dx
  2670.     mov    bx,10
  2671.     div    bx        ; divide to get digit
  2672.     push    dx        ; save remainder digit
  2673.     or    ax,ax        ; test quotient
  2674.     jz    outnu1        ; zero, no more of number
  2675.     call    outnum        ; else call for rest of number
  2676. outnu1:    pop    ax        ; get digit back
  2677.     add    al,'0'        ; make printable
  2678.     stosb            ; drop it off
  2679.     ret
  2680. outnum    endp
  2681.  
  2682. ; on/off field
  2683. onoff    proc    near
  2684.     call    stmsg        ; copy message
  2685.     call    stval        ; get value cell
  2686.     mov    al,[si]
  2687.     mov    si,offset onmsg
  2688.     mov    cx,2        ; assume 2-byte 'ON' message
  2689.     or    al,al        ; test value
  2690.     jnz    onof1        ; on, have right msg
  2691.     mov    si,offset offmsg
  2692.     mov    cx,3
  2693. onof1:    cld
  2694.     push    ds
  2695.     pop    es
  2696.     rep    movsb        ; copy right message in
  2697.     ret
  2698. onoff    endp
  2699.  
  2700. ; print first message if false, second if true
  2701. msg2    proc    near
  2702.     call    stval        ; get value cell
  2703.     mov    al,[si]
  2704.     mov    si,[bx].msg    ; assume off
  2705.     or    al,al        ; is it?
  2706.     jz    msg21        ; yes, continue
  2707.     mov    si,[bx].val2    ; else use alternate message
  2708. msg21:    jmp    stms1        ; handle copy and return
  2709. msg2    endp
  2710.  
  2711. ; print first message if false, second if true, uses bit in byte for value
  2712. msg2b    proc    near
  2713.     call    stbval        ; get bit value cell
  2714.     mov    si,[bx].msg    ; assume off
  2715.     or    al,al        ; is it?
  2716.     jz    msg2b1        ; yes, continue
  2717.     mov    si,[bx].val2    ; else use alternate message
  2718. msg2b1:    jmp    stms1        ; handle copy and return
  2719. msg2b    endp
  2720.  
  2721. ; search a keyword table for a word value, print that value
  2722. srchkww    proc    near
  2723.     call    stmsg        ; copy the first message
  2724.     call    stval
  2725.     mov    ax,[si]        ; get value to hunt for
  2726.     mov    bx,[bx].val2    ; this is table address
  2727.     jmp    prttab        ; and look in table
  2728. srchkww    endp
  2729.  
  2730. ; search a keyword table for a byte value, print that value
  2731. srchkw    proc    near
  2732.     call    stmsg        ; first print message
  2733.     call    stval
  2734.     mov    al,[si]        ; get value to hunt for
  2735.     xor    ah,ah        ; high order is 0
  2736.     mov    bx,[bx].val2    ; this is table address
  2737.     jmp    prttab        ; and look in table
  2738. srchkw    endp
  2739.  
  2740. ; search a keyword table for a bit value, print that value
  2741. srchkb    proc    near
  2742.     call    stmsg            ; first print message
  2743.     call    stbval            ; get bit set or reset
  2744.     mov    bx,[bx].val2        ; this is table address
  2745.     jmp    prttab            ; and look in table
  2746. srchkb    endp
  2747.  
  2748. ; get address of test value in stent.  Returns address in si.
  2749. stbval    proc    near
  2750.     mov    si,[bx].basval        ; get address of test value
  2751.     or    si,si            ; any there?
  2752.     jz    stbva1            ; z = no, quit with no match
  2753.     mov    ax,[si]            ; get value
  2754.     test    ax,[bx].tstcel         ; bit test value against data word
  2755.     jz    stbva1            ; z = they don't match
  2756.     mov    ax,1            ;  match
  2757.     ret
  2758. stbva1:    xor    ax,ax            ; no match
  2759.     ret                ; and return it
  2760. stbval    endp
  2761.  
  2762.  
  2763. ; Print the drive name
  2764. drnum    proc    near
  2765.     call    stmsg        ; copy message part first
  2766.     call    stval        ; pick up test value address
  2767.     mov    ah,gcurdsk    ; Get current disk
  2768.     int    dos
  2769.     inc    al        ; We want 1 == A (not zero)
  2770.     mov    curdsk,al
  2771.     add    al,'@'        ; Make it printable
  2772.     cld
  2773.     push    ds
  2774.     pop    es
  2775.     stosb
  2776.     mov    word ptr [di],'\:'
  2777.     add    di,2        ; end with a colon and backslash
  2778.     mov    byte ptr [di],0    ; terminate in case drive is not ready
  2779.     xor    dl,dl        ; get current drive
  2780.     mov    ah,gcd        ; get current directory
  2781.     mov    si,di        ; current working buffer position
  2782.     int    dos
  2783.     push    cx
  2784.     push    dx
  2785.     mov    dx,di        ; directory string
  2786.     call    strlen        ; length of path part to cx
  2787.     cmp    cx,26        ; too long to show the whole thing?
  2788.     jbe    drnum3        ; be = is ok, show the whole path
  2789.     push    di        ; scan backward for last backslash
  2790.     mov    al,'\'        ; thing to search for
  2791.     std            ; backward
  2792.     mov    di,si        ; start of buffer
  2793.     add    di,cx        ; length of string
  2794.     repne    scasb        ; scan backward for a backslash
  2795.     jcxz    drnum2        ; should not happen, but then again 
  2796.     repne    scasb        ; do again for second to last path part
  2797. drnum2:    cld            ; reset direction flag
  2798.     dec    di        ; move di two places preceding backslash
  2799.     mov    [di],'--'    ; insert a missing path indicator
  2800.     dec    di
  2801.     mov    byte ptr [di],'-'
  2802.     mov    si,di        ; we will show just this part
  2803.     pop    di        ; recover main status pointer
  2804. drnum3:    pop    dx
  2805.     pop    cx
  2806.     
  2807. drnum4:    lodsb            ; copy until null terminator
  2808.     stosb
  2809.     or    al,al        ; end of string?
  2810.     jnz    drnum4        ; nz = no
  2811.     dec    di        ; offset inc of stosb
  2812.     ret
  2813. drnum    endp
  2814.  
  2815.  
  2816. ; Print the screen-dump filename [jrd]
  2817.  
  2818. pasz    proc    near
  2819.     call    stmsg        ; copy message part
  2820.     mov    si,[bx].val2    ; address of asciiz string
  2821.     push    ds
  2822.     pop    es
  2823.     cld
  2824. pasz1:    lodsb            ; get a byte
  2825.     or    al,al        ; at end yet?
  2826.     jz    pasz2        ; z = yes
  2827.     stosb            ; store in buffer
  2828.     jmp    short pasz1    ; keep storing non-null chars
  2829. pasz2:    ret
  2830. pasz    endp
  2831.  
  2832. ; Display unprotected control characters
  2833. cntlsho    proc    near
  2834.     mov    ah,prstr
  2835.     mov    dx,offset cntlmsg1     ; first msg
  2836.     int    dos
  2837.     mov    dx,1            ; do 7-bit unprotected forms
  2838.     call    cntlwk            ; call worker
  2839.     mov    ah,prstr
  2840.     mov    dx,offset crlf
  2841.     int    dos
  2842.     mov    ah,conout
  2843.     mov    dl,' '
  2844.     int     dos
  2845.     mov    dx,8080h        ; do 8-bit unprotected forms
  2846.     call    cntlwk
  2847.     ret
  2848.  
  2849. cntlwk:    mov    cx,32
  2850.     xor    bx,bx
  2851.     xor    si,si            ; items per line counter
  2852. cntlwk1:test    protlist[bx],dl        ; unprotected?
  2853.     jz    cntlwk2            ; z = no
  2854.     mov    ax,bx
  2855.     add    al,dh            ; add possible 128 offset
  2856.     push    dx
  2857.     call    decout
  2858.     mov    ah,conout        ; show space
  2859.     mov    dl,' '
  2860.     int    dos
  2861.     pop    dx
  2862.     inc    si            ; count item displayed
  2863. cntlwk2:inc    bx
  2864.     cmp    si,16            ; done plenty for one line?
  2865.     jb    cntlwk3            ; b = no
  2866.     push    dx
  2867.     mov    ah,prstr
  2868.     mov    dx,offset crlf
  2869.     int    dos
  2870.     mov    ah,conout
  2871.     mov    dl,' '
  2872.     int    dos
  2873.     pop    dx
  2874.     xor    si,si
  2875. cntlwk3:loop    cntlwk1
  2876.     ret
  2877. cntlsho endp
  2878.  
  2879. ; Display Send and Receive chars
  2880. prsar    proc    near
  2881.     call     stmsg        ; display leadin part of message
  2882.     push    ds
  2883.     pop    es
  2884.     cld
  2885.     mov    si,[bx].tstcel    ; get address of first item
  2886.     mov    al,[si]
  2887.     cmp    al,7fh        ; DEL code?
  2888.     jne    prsar1        ; ne = no
  2889.     mov    ax,'1\'        ; say \127
  2890.     cmp    byte ptr [di-1],5eh ; caret present in msg?
  2891.     jne    prsar5        ; ne = no
  2892.     dec    di        ; remove "^"
  2893. prsar5:    stosw
  2894.     mov    ax,'72'
  2895.     stosw
  2896.     jmp    short prsar2
  2897. prsar1:    dec    di        ; remove "^"
  2898.     cmp    al,20h        ; printable now?
  2899.     jae    prsar7        ; ae = yes
  2900.     inc    di        ; restore "^"
  2901.     add    al,40H        ; make it printable
  2902. prsar7:    stosb
  2903. prsar2:    mov    si,[bx].val2    ; get address of second msg
  2904.     call    stms1        ; add that
  2905.     mov    si,[bx].basval    ; second value's address
  2906.     mov    al,[si]        ; second value
  2907.     cmp    al,7fh        ; DEL code?
  2908.     jne    prsar3        ; ne = no
  2909.     mov    ax,'1\'        ; say \127
  2910.     cmp    byte ptr [di-1],5eh ; caret present in msg?
  2911.     jne    prsar6        ; ne = no
  2912.     dec    di        ; remove "^"
  2913. prsar6:    stosw
  2914.     mov    ax,'72'
  2915.     stosw
  2916.     ret
  2917. prsar3:    dec    di        ; remove "^"
  2918.     cmp    al,20h        ; printable now?
  2919.     jae    prsar3a        ; ae = yes
  2920.     inc    di        ; restore "^"
  2921.     add    al,40H        ; make it printable
  2922. prsar3a:stosb
  2923.     ret
  2924. prsar    endp
  2925.  
  2926. ; Display Send and Receive char value
  2927. prsarv    proc    near
  2928.     call     stmsg        ; display leadin part of message
  2929.     mov    si,[bx].tstcel    ; get address of first item
  2930.     mov    al,[si]
  2931.     xor    ah,ah
  2932.     push    bx
  2933.     call    outnum
  2934.     pop    bx
  2935.     mov    si,[bx].val2    ; get address of second msg
  2936.     call    stms1        ; add that
  2937.     mov    si,[bx].basval    ; second value's address
  2938.     mov    al,[si]        ; second value
  2939.     xor    ah,ah
  2940.     jmp    outnum
  2941. prsarv    endp
  2942.  
  2943.  
  2944. ; print Send Delay and Pause
  2945. prsnd    proc    near
  2946.     call    stmsg        ; display leadin part of msg
  2947.     mov    al,trans.sdelay    ; Send Delay (sec)
  2948.     xor    ah,ah
  2949.     call    outnum
  2950.     mov    si,offset sndmsg2 ; second part of msg
  2951.     call    stms1        ; add that
  2952.     mov    ax,spause    ; Send Pause (millisec) 
  2953.     call    outnum
  2954.     mov    si,offset sndmsg3 ; last part of msg
  2955.     jmp    stms1        ; add it too
  2956. prsnd    endp
  2957.  
  2958. ; Print the handshake
  2959. prhnd:    mov    si,offset handst    ; copy in initial message
  2960.     call    stms1
  2961.     mov    si,offset nonmsg    ; assume no handshake
  2962.     mov    bx,portval
  2963.     cmp    [bx].hndflg,0        ; Is handshaking in effect?
  2964.     jne    prh0            ; ne = yes, show what we're using
  2965.     jmp    stms1            ; no, say so and return
  2966. prh0:    xor    ah,ah
  2967.     call    outnum            ; show handshake as decimal number
  2968.     ret
  2969.  
  2970. ; Print the Transmit Fill char
  2971. prfil:    mov    si,offset sxfilmsg    ; copy in initial message
  2972.     call    stms1
  2973.     mov    si,offset nonmsg    ; assume no handshake
  2974.     mov    al,script.xmitfill    ; filling char
  2975.     or    al,al            ; is filling in effect?
  2976.     jnz    prfil1            ; nz = yes, print what we're using
  2977.     jmp    stms1            ; no, say so and return
  2978. prfil1:    push    ds
  2979.     pop    es
  2980.     cld
  2981.     cmp    al,20h            ; printable already?
  2982.     ja    prfil2            ; a = yes
  2983.     push    ax
  2984.     mov    al,5eh            ; control char
  2985.     stosb
  2986.     pop    ax
  2987.     add    al,40H            ; make printable
  2988.     stosb                ; put in buffer
  2989.     ret                ; and return
  2990. prfil2:    cmp    al,126            ; in ordinary printable range?
  2991.     ja    prfil3            ; a = no
  2992.     stosb                ; store in buffer
  2993.     ret
  2994. prfil3:    mov    byte ptr [di],'\'    ; show as \number
  2995.     inc    di
  2996.     xor    ah,ah
  2997.     jmp    outnum            ; do rest of number
  2998.  
  2999. ; Print value from table.  BX is address of table, AX is value of variable
  3000. ; Copy value of table text entry to output buffer (di), given the address
  3001. ; of the table in bx and the value to compare against table values in al.
  3002. prttab    proc    near
  3003.     push    cx            ; save column count
  3004.     mov    cl,[bx]            ; number of entries in our table
  3005.     inc    bx            ; point to the data
  3006. prtta1:    mov    si,[bx]            ; length of keyword
  3007.     cmp    ax,[bx+si+2]        ; value fields match?
  3008.     je    prtta2            ; e = yes
  3009.     add    bx,si            ; add word length
  3010.     add    bx,4            ; skip count and value fields
  3011.     dec    cl            ; more keywords to check?
  3012.     jnz    prtta1            ; nz = yes, go to it
  3013.     pop    cx
  3014.     mov    si,offset prterr
  3015.     jmp    stms1            ; copy dollar terminated string
  3016. prtta2:    push    es
  3017.     push    ds
  3018.     pop    es        ; ensure es points to data segment
  3019.     mov    cx,[bx]        ; get length of counted string
  3020.     push    cx        ; save
  3021.     mov    si,bx
  3022.     add    si,2        ; look at text
  3023.     cld
  3024.     rep    movsb
  3025.     pop    ax
  3026.     pop    es
  3027.     pop    cx        ; original cx
  3028.     add    cx,ax        ; advance column count, return di advanced
  3029.     ret
  3030. prttab    endp
  3031.  
  3032. ; Display port speed
  3033.  
  3034. BAUDPRT    PROC     NEAR
  3035.     mov    si,offset baudrt    ; "Speed: "
  3036.     call    stms1            ; display that part
  3037.     push    di
  3038.     push    cx
  3039.     call    getbaud            ; read baud rate first
  3040.     pop    cx
  3041.     pop    di
  3042.     mov    bx,portval
  3043.     mov    ax,[bx].baud
  3044.     cmp    al,byte ptr bdtab    ; number of table entries
  3045.     jb    bdprt5            ; b = in table
  3046.     mov    si,offset unrec        ; say unrecognized value
  3047.     jmp    stms1            ; display text and return
  3048. bdprt5:    mov    bx,offset bdtab        ; show ascii rate from table
  3049.     jmp    prttab
  3050. BAUDPRT    ENDP
  3051.  
  3052. ; display Take/Macro COUNT
  3053. stcnt    proc    near
  3054.     call    stmsg            ; display leadin part of msg
  3055.     cmp    taklev,0        ; in a Take file or macro?
  3056.     jne    stcnt1            ; ne = yes
  3057.     mov    si,offset nonemsg    ; say none
  3058.     jmp    stms1
  3059. stcnt1:    push    bx
  3060.     mov    bx,takadr        ; current Take structure
  3061.     mov    ax,[bx].takctr        ; get COUNT
  3062.     pop    bx
  3063.     jmp    outnum
  3064. stcnt    endp
  3065.  
  3066. ; display Take/Macro ARGC
  3067. starg    proc    near
  3068.     call    stmsg            ; display leadin part of msg
  3069.     cmp    taklev,0        ; in a Take file or macro?
  3070.     jne    starg1            ; ne = yes
  3071.     mov    si,offset nonemsg    ; say none
  3072.     jmp    stms1
  3073. starg1:    push    bx
  3074.     mov    bx,takadr        ; current Take structure
  3075.     mov    ax,[bx].takargc        ; get ARGC
  3076.     pop    bx
  3077.     jmp    outnum
  3078. starg    endp
  3079.  
  3080. ; ALARM time
  3081. stalr    proc    near
  3082.     call    stmsg            ; display leading part of msg
  3083.     push    bx            ; preserve register
  3084.     xor    bx,bx            ; position index
  3085.     push    ds
  3086.     pop    es
  3087.     cld
  3088. stalr1:    push    bx            ; save around calls
  3089.     cmp    alrhms[bx],10        ; two digits?
  3090.     jae    stalr2            ; ae = yes
  3091.     mov    al,'0'
  3092.     stosb                ; show leading zero
  3093. stalr2:    mov    al,alrhms[bx]        ; show time component
  3094.     xor    ah,ah
  3095.     call    outnum
  3096.     pop    bx            ; recover index
  3097.     inc    bx
  3098.     cmp    bx,3            ; done all fields?
  3099.     jae    stalr3            ; ae = yes
  3100.     mov    al,':'
  3101.     stosb
  3102.     jmp    short stalr1        ; do next field
  3103. stalr3:    pop    bx
  3104.     ret
  3105. stalr    endp
  3106.  
  3107. ; show INPUT buffer
  3108. stinbuf    proc    near
  3109.     push    si
  3110.     push    di
  3111.     push    es
  3112.     mov    di,offset rdbuf
  3113.     mov    byte ptr [di],cr    ; start on the margin
  3114.     inc    di
  3115.     push    di
  3116.     call    buflog            ; get INPUT buffer pointers
  3117.     pop    di
  3118.     mov    bx,cx            ; length of buffer (and max offset)
  3119.     mov    byte ptr [di],'<'    ; start with "<# unread chars>"
  3120.     inc    di
  3121.     push    cx
  3122.     push    dx
  3123.     call    dec2di            ; ax has unread count, bufcnt
  3124.     pop    dx
  3125.     pop    cx
  3126.     mov    byte ptr [di],'>'
  3127.     inc    di
  3128. stinb1:    mov    al,es:[si]        ; extract a buffer char into al
  3129.     inc    si            ; move pointer to next byte
  3130.     test    al,80h            ; high bit set?
  3131.     jz    stinb2            ; z = no
  3132.     mov    byte ptr [di],'~'    ; yes, show a tilde
  3133.     inc    di
  3134. stinb2:    and    al,7fh            ; strip eighth bit
  3135.     cmp    al,' '            ; control code?
  3136.     jae    stinb3            ; ae = no
  3137.     mov    byte ptr [di],'^'    ; yes, show caret
  3138.     inc    di
  3139.     or    al,40h            ; convert char to upper case letter
  3140. stinb3:    mov    [di],al
  3141.     inc    di            ; where to write next byte
  3142.     cmp    di,offset rdbuf+78    ; line full?
  3143.     jb    stinb4            ; b = no, have more room
  3144.     mov    word ptr [di],0a0dh    ; add cr/lf
  3145.     mov    byte ptr [di+2],0
  3146.     mov    dx,offset rdbuf
  3147.     mov    di,dx
  3148.     call    prtasz
  3149. stinb4:    cmp    si,bx            ; beyond end of Input buffer?
  3150.     jb    stinb5            ; b = not yet
  3151.     xor    si,si            ; reset to start of INPUT-buf (wrap)
  3152. stinb5:    loop    stinb1
  3153.     mov    word ptr [di],0a0dh    ; add cr/lf
  3154.     mov    byte ptr [di+2],0
  3155.     mov    dx,offset rdbuf        ; reset to start of our local buffer
  3156.     mov    di,dx
  3157.     call    prtasz
  3158.     pop    es
  3159.     pop    di
  3160.     pop    si
  3161.     xor    cx,cx
  3162.     ret
  3163. stinbuf    endp
  3164.  
  3165. ; LNOUT - Table driven unsigned long integer (32 bit) display
  3166. ; Register dx holds high order word and ax holds low order word of unsigned
  3167. ; long integer to be stored in decimal. Storage area is given by DS:[DI]
  3168. ; DI is incremented for each storage, null terminated.
  3169. ; Table TENS holds set of double word values of ten raised to powers 0 to 9
  3170. ; TENSLEN holds the number of these double words
  3171. ; All registers preserved.    8 March 1987 [jrd]
  3172.  
  3173. lnouts    proc    near            ; do lnout with thousands separator
  3174.     push    ax
  3175.     mov    al,thsep        ; get thousands separator
  3176.     mov    lnoutsep,al        ; tell lnout to use it
  3177.     pop    ax
  3178.     call    lnout            ; compute value to di
  3179.     mov    lnoutsep,0        ; clear for future callers
  3180.     ret
  3181. lnouts    endp
  3182.  
  3183. lnout    proc    near
  3184.     push    ax
  3185.     push    bx
  3186.     push    cx
  3187.     push    dx
  3188.     push    si
  3189.     xor    si,si        ; flag to say start printing (no leading 0's)
  3190.     mov    cx,tenslen    ; number of table entries
  3191. lnout1:    push    cx        ; save loop counter
  3192.     mov    bx,cx        ; index into tens double word table
  3193.     dec    bx        ; index starts at zero
  3194.     add    bx,bx
  3195.     add    bx,bx        ; bx times four (double words to bytes)
  3196.     xor    cx,cx        ; cx is now a counter of subtractions
  3197.  
  3198. lnout2:    cmp    dx,word ptr tens[bx+2]  ; pattern 10**(bx/4), high order part
  3199.     jb    lnout4        ; b = present number is less than pattern
  3200.     ja    lnout3        ; a = present number is larger than pattern
  3201.     cmp    ax,word ptr tens[bx] ; high words match, how about lows
  3202.     jb    lnout4        ; b = present number is smaller than pattern
  3203. lnout3:    sub    ax,word ptr tens[bx]    ; subtract low order words
  3204.     sbb    dx,word ptr tens[bx+2]    ; subtract high order words, w/borrow
  3205.     inc    cl        ; count number of subtractions
  3206.     inc    si        ; flag to indicate printing needed
  3207.     jmp    short lnout2    ; try again to deduct present test pattern
  3208.  
  3209. lnout4:    or    bx,bx        ; doing least significant digit?
  3210.     jz    lnout5        ; z = yes, always print this one
  3211.     or    si,si        ; should we print?
  3212.     jz    lnout6        ; z = no, not yet
  3213. lnout5:    add    cl,'0'        ; get number of subtractions
  3214.     mov    [di],cx        ; store it (ch is still zero), asciiz
  3215.     inc    di
  3216.     cmp    bx,9*4        ; places for thousands separator?
  3217.     je    lnout5a        ; e = yes
  3218.     cmp    bx,6*4
  3219.     je    lnout5a
  3220.     cmp    bx,3*4
  3221.     jne    lnout6        ; ne = no
  3222. lnout5a:mov    cl,lnoutsep    ; get thousands separator
  3223.     jcxz    lnout6        ; z = none
  3224.      mov    word ptr [di],cx
  3225.     inc    di
  3226. lnout6:    pop    cx        ; recover loop counter
  3227.     loop    lnout1
  3228.     pop    si
  3229.     pop    dx
  3230.     pop    cx
  3231.     pop    bx
  3232.     pop    ax
  3233.     ret
  3234. lnout    endp 
  3235.  
  3236. code    ends
  3237.     end
  3238.