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

  1.     NAME    mssfil
  2. ; File MSSFIL.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. ; Edit history:
  11. ; 27 August 1992 version 3.13
  12. ; 6 Sept 1991 version 3.11
  13. ; 2 March 1991 version 3.10
  14. ; Last edit 25 May 1993
  15.  
  16.     public    buff, gofil, ptchr, gtchr, getfil, gtnfil, doenc, dodec
  17.     public    encbuf, decbuf, diskio, auxfile, fparse, prtasz, prtscr
  18.     public    strlen, strcat, strcpy, tfilsz, templp, latin1, charids
  19.     public    L1cp437, L1cp850, L1cp860, L1cp863, L1cp865, unique
  20.     public    load, cplatin, goopen, latininv, protlist
  21.  
  22. SIchar    equ    0fh
  23. SOchar    equ    0eh
  24. DLE    equ    10h
  25.  
  26. data    segment
  27.     extrn    flags:byte, trans:byte, denyflg:word, dosnum:word
  28.     extrn    oldkbt:word, oldper:word, filtst:byte, rdbuf:byte, fsta:byte
  29.     extrn    curdsk:byte
  30.  
  31. ermes4  db    'Unable to make unique name',0
  32. ermes9    db    'Printer not ready',0
  33. erms12    db    'Unable to create file ',0
  34. erms13    db    'Error writing output file',0
  35. infms5  db    'Renaming file to $'
  36. infms6    db    cr,lf,'?Unable to open file$'
  37. asmsg    db    ' as $'
  38. crlf    db    cr,lf,'$'
  39. printer    db    'PRN',0
  40. screen    db    'CON',0
  41. loadhlp    db    'filename$'
  42.                 ; DOS special chars allowed in filenames
  43. spchar2    db    '$', 26h, 23h, 40h, 21h, 25h, 27H, '(', ')', '-', 7bh, 7dh
  44.     db    5fh, 5eh, 7eh, 60h
  45. spc2len    equ    $-spchar2
  46.  
  47. textctl    db    cr,lf,tab,bell,ff,ctlz    ; controls allowed in text files
  48. textctlen equ    $-textctl
  49.     even
  50. filflg    db    0        ; input buffer has data, if non-zero
  51. rptct    db    1        ; number of times it's repeated
  52. dblbyte    db    0        ; first of two bytes in a pair
  53. dblbyteflg db    0        ; non-zero if processing second byte of pair
  54. DLEseen    db    0
  55. shiftstate db    0        ; locking shift (0 = unshifted, 80h = shifted)
  56. decoutp    dw    0        ; ptr to proc to dump decode output buffer
  57. encinp    dw    0        ; ptr to proc to refill encode input buffer
  58. dchrcnt dw    0        ; number of chars in the decode file buffer
  59. echrcnt dw    0        ; number of chars in the encode file buffer
  60. dbufpnt dw    0        ; position in file buffer, decoder
  61. ebufpnt dw    0        ; position in file buffer, encoder
  62.                 ;
  63.     db    0        ; this MUST directly preceed decbuf, jpnwrite
  64. decbuf    db    512 dup (0)    ; decoding source buffer
  65.     db    0        ; safety for possible null terminator
  66. encbuf    db    512 dup (0)    ; encoding source buffer
  67.     db    0        ; safety for possible null terminator
  68. protlist db    32 dup (0)     ; list of protected control codes (if = 0)
  69.  
  70. tfilsz    dw    0,0        ; bytes transferred (double word qty)
  71. nmoflg    db    0        ; have override filename, if non-zero
  72. templp    db    65 dup (?)    ; temp for local path part
  73. templf    db    14 dup (?)    ; temp for local filename part
  74. temprp    db    65 dup (?)    ; temp for remote path part
  75. temprf    db    14 dup (?)    ; temp for remote filename part
  76. auxfile    db    65 dup (?)    ; auxillary filename for general use
  77. diskio    filest    <>        ; ditto, for ordinary file transfers
  78. buff    db    buffsz dup (?)    ; use as our Disk Transfer Area
  79. havdot    db    0        ; dot-found status in verify
  80. unum    dw    0        ; unique filename generation number
  81. temp    dw    0
  82.                 ; charids: table of transfer char-set idents
  83. charids dw    7        ; qty, pointers to char set idents
  84.     dw    chtrans,chlatin1,chlatin2,chhebiso,chcyrill,chjapan,chjapanold
  85. chtrans    db    1,'A'        ; Transparent: char count, ident
  86. chlatin1 db    6,'I6/100'    ; Latin1: char count, ident
  87. chlatin2 db    6,'I6/101'    ; Latin2: char count, ident
  88. chhebiso db    6,'I6/138'    ; Hebrew-ISO: char count, ident
  89. chcyrill db    6,'I6/144'    ; Cyrillic: char count, ident
  90. chjapan    db    9,'I14/87/13'    ; Japanese-EUC: char count, ident (new)
  91. chjapanold db    7,'I14/87E'    ; Japanese-EUC: char count, ident (obsolete)
  92.                 ; end of charids info
  93. ;loadtab    db    1        ; LOAD command table
  94. ;    mkeyw    'Transfer-character-set',0
  95. ;
  96. ;filtab    macro
  97. ;    cnt = 128
  98. ;    rept    128            ; 128 idenity entries
  99. ;    db    cnt            ; initialize table to 128 .. 255
  100. ;    cnt = cnt + 1
  101. ;    endm
  102. ;endm
  103. ;
  104. ;userin    equ    this byte        ; LOAD command
  105. ;    filtab                ; init table to idenity
  106. ;namein    db    20 dup (0)        ; name of the character set
  107. ;userout    equ    this byte
  108. ;    filtab                ; init table to idenity
  109. ;nameout db    20 dup (0)        ; name of the character set
  110. ;tblptr    dw    0            ; LOAD command
  111. ;xlines    dw    0            ; LOAD command
  112. ;linecnt dw    0            ; LOAD command
  113. ;badvalue db    cr,lf,'?Bad value on line $'
  114.  
  115. ; Translation tables for byte codes 0a0h..0ffh to map ISO 8859-1 to Code Pages
  116. ; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is
  117. ; considered to be a control code, 80h..9fh are 8-bit controls (C1).
  118. ; Each table is 96 translatable bytes followed by the table size (96), the
  119. ; ISO announcer ident ('A' and a null here); LATIN5/Cyrillic uses 'L'.
  120. ; The decimal tables are from Frank da Cruz working with the formal IBM docs.
  121.                     ; from ISO 8859-1 Latin-1 to Code Page
  122.                         ; to CP437 United States
  123. L1cp437    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  124.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  125.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  126.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  127.     db    20h,0adh,9bh,9ch,  0fh,9dh,7ch,15h    ; column 10
  128.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  129.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  130.     db    2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  131.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  132.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  133.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  134.     db    4fh,55h,55h,55h,  9ah,59h,3fh,0e1h
  135.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  136.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  137.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  138.     db    6fh,97h,0a3h,96h,  81h,79h,3fh,98h
  139.     db    96,'A',0            ; 96 byte set, letter ident
  140.  
  141.                         ; to CP850 Multilingual
  142. L1cp850    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  143.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  144.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  145.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  146.     db    20h,0adh,0bdh,9ch,  0cfh,0beh,0ddh,0f5h    ; column 10
  147.     db    0f9h,0b8h,0a6h,0aeh, 0aah,0f0h,0a9h,0eeh
  148.     db    0f8h,0f1h,0fdh,0fch, 0efh,0e6h,0f4h,0fah ; column 11
  149.     db    0f7h,0fbh,0a7h,0afh, 0ach,0abh,0f3h,0a8h
  150.     db    0b7h,0b5h,0b6h,0c7h, 8eh,8fh,92h,80h    ; column 12
  151.     db    0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h
  152.     db    0d1h,0a5h,0e3h,0e0h, 0e2h,0e5h,99h,9eh    ; column 13
  153.     db    9dh,0ebh,0e9h,0eah, 9ah,0edh,0e8h,0e1h
  154.     db    85h,0a0h,83h,0c6h,  84h,86h,91h,87h    ; column 14
  155.     db    8ah,82h,88h,89h,    8dh,0a1h,8ch,8bh
  156.     db    0d0h,0a4h,95h,0a2h, 93h,0e4h,94h,0f6h    ; column 15
  157.     db    9bh,97h,0a3h,96h,   81h,0ech,0e7h,98h
  158.     db    96,'A',0            ; 96 byte set, letter ident
  159.  
  160.                         ; to CP860 Portugal
  161. L1cp860    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  162.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  163.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  164.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  165.     db    20h,0adh,9bh,9ch,  0fh,59h,7ch,15h    ; column 10
  166.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  167.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  168.     db    2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  169.     db    91h,86h,8fh,8eh,   41h,41h,41h,80h    ; column 12
  170.     db    92h,90h,89h,45h,   8bh,98h,49h,49h
  171.     db    44h,0a5h,0a9h,9fh, 8ch,99h,4fh,58h    ; column 13
  172.     db    4fh,9dh,96h,55h,   9ah,59h,3fh,0e1h
  173.     db    85h,0a0h,83h,84h,  61h,61h,61h,87h    ; column 14
  174.     db    8ah,82h,88h,65h,   8dh,0a1h,69h,69h
  175.     db    3fh,0a4h,95h,0a2h, 93h,94h,6fh,0f6h    ; column 15
  176.     db    6fh,97h,0a3h,75h,  81h,79h,3fh,79h
  177.     db    96,'A',0            ; 96 byte set, letter ident
  178.  
  179.                         ; to CP861 Iceland
  180. L1cp861    db    80h,0fch,82h,83h,  84h,85h,86h,87h    ; column 8
  181.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  182.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  183.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  184.     db    20h,0adh,43h,9ch,  0fh,59h,7ch,15h    ; column 10
  185.     db    22h,3fh,0a6h,0aeh,  0aah,16h,3fh,2dh
  186.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  187.     db    2ch,31h,3fh,0afh,  0ach,0abh,3fh,0a8h
  188.     db    41h,0a4h,41h,41h,  8eh,8fh,92h,80h    ; column 12
  189.     db    45h,90h,45h,45h,   49h,0a5h,49h,49h
  190.     db    8bh,4eh,4fh,0a6h,  4fh,4fh,99h,58h    ; column 13
  191.     db    9dh,55h,0a7h,55h,  9ah,97h,8dh,0e1h
  192.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  193.     db    8ah,82h,88h,89h,   69h,0a1h,69h,69h
  194.     db    8ch,6eh,6fh,0a2h,  93h,6fh,94h,0f6h    ; column 15
  195.     db    9bh,75h,0a3h,96h,  81h,98h,95h,79h
  196.     db    96,'A',0            ; 96 byte set, letter ident
  197.  
  198.                         ; to CP863 Canada-French
  199. L1cp863    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  200.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  201.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  202.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  203.     db    20h,3fh,9bh,9ch,   98h,59h,0a0h,8fh    ; column 10
  204.     db    0a4h,40h,61h,0aeh, 0aah,0c4h,3fh,0a7h
  205.     db    0f8h,0f1h,0fdh,0a6h, 0a1h,0e6h,86h,0fah    ; column 11
  206.     db    0a5h,31h,6fh,0afh, 0ach,0abh,0adh,3fh
  207.     db    8eh,41h,84h,41h,   41h,41h,41h,80h    ; column 12
  208.     db    91h,90h,92h,94h,   49h,49h,0a8h,95h
  209.     db    44h,4eh,4fh,4fh,   99h,4fh,4fh,58h    ; column 13
  210.     db    4fh,9dh,55h,9eh,   9ah,59h,3fh,0e1h
  211.     db    85h,61h,83h,61h,   61h,61h,61h,87h    ; column 14
  212.     db    8ah,82h,88h,89h,   69h,69h,8ch,8bh
  213.     db    3fh,6eh,6fh,0a2h,  93h,6fh,6fh,0f6h    ; column 15
  214.     db    6fh,97h,0a3h,96h,  81h,79h,3fh,79h
  215.     db    96,'A',0            ; 96 byte set, letter ident
  216.                         ; to CP865 Norway
  217. L1cp865    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  218.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  219.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  220.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  221.     db    20h,0adh,3fh,9ch,  0afh,59h,7ch,15h    ; column 10
  222.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,0c4h
  223.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  224.     db    2ch,31h,0a7h,03fh, 0ach,0abh,3fh,0a8h
  225.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  226.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  227.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  228.     db    9dh,55h,55h,55h,  9ah,59h,3fh,0e1h
  229.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  230.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  231.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  232.     db    9bh,97h,0a3h,96h,  81h,79h,3fh,98h
  233.     db    96,'A',0            ; 96 byte set, letter ident
  234.                             ; Latin2 to CP852
  235. L2cp852    db 174,175,176,177,178,179,180,185,186,187,188,191,192,193,194,195
  236.     db 196,197,200,201,202,203,204,205,206,217,218,219,220,223,240,254
  237.     db 255,164,244,157,207,149,151,245,249,230,184,155,141,170,166,189
  238.     db 248,165,242,136,239,150,152,243,247,231,173,156,171,241,167,190
  239.     db 232,181,182,198,142,145,143,128,172,144,168,211,183,214,215,210
  240.     db 209,227,213,224,226,138,153,158,252,222,233,235,154,237,221,225
  241.     db 234,160,131,199,132,146,134,135,159,130,169,137,216,161,140,212
  242.     db 208,228,229,162,147,139,148,246,253,133,163,251,129,236,238,250
  243.     db    96,'B',0            ; 96 byte set, letter ident
  244.  
  245.                 ; Hebrew-ISO to Code Page 862, GLeft
  246. HIcp862    db 158,159,160,161,162,163,164,165,166,167,168,169,173,176,177,178
  247.     db 179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194
  248.     db 255,195,155,156,196,157,197,198,199,200,201,174,170,202,203,204
  249.     db 248,241,253,206,207,230,208,249,209,210,246,175,172,171,211,212
  250.     db 213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228
  251.     db 229,231,232,233,234,235,236,237,238,239,240,242,243,244,245,205
  252.     db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  253.     db 144,145,146,147,148,149,150,151,152,153,154,247,250,251,252,254
  254.     db    96,'H',0
  255.  
  256.                             ; Latin5 to CP866
  257. L5cp866    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  258.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  259.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  260.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  261.     db    0ffh,0f0h,3fh,3fh,  0f2h,53h,49h,4fh    ; column 10
  262.     db    4ah,3fh,3fh,48h,   4bh,2dh,0f6h,3fh
  263.     db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 11
  264.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  265.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 12
  266.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  267.     db    0a0h,0a1h,0a2h,0a3h,0a4h,0a5h,0a6h,0a7h ; column 13
  268.     db    0a8h,0a9h,0aah,0abh,0ach,0adh,0aeh,0afh
  269.     db    0e0h,0e1h,0e2h,0e3h,0e4h,0e5h,0e6h,0e7h ; column 14
  270.     db    0e8h,0e9h,0eah,0ebh,0ech,0edh,0eeh,0efh
  271.     db    0fch,0f1h,3fh,3fh, 0f3h,73h,69h,0f5h    ; column 15
  272.     db    6ah,3fh,3fh,68h,   6bh,15h,0f7h,3fh
  273.     db    96,'L',0            ; 96 byte set, Latin5/Cyrillic
  274.  
  275.  
  276. ;yl143[]   /* Latin-1 to IBM Code Page 437 */
  277. ; Although the IBM CDRA does not include an official translation between CP437
  278. ; and ISO Latin Alphabet 1, it does include an official, invertible
  279. ; translation between CP437 and CP850 (page 196), and another from CP850 to
  280. ; Latin-1 (CP819) (page 153).  This translation was obtained with a two-step
  281. ; process based on those tables.
  282.  
  283. iL1cp437 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  284.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  285.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  286.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  287.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  288.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  289.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  290.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  291.     db 96,'A',0                ; 96 byte set, letter ident
  292.  
  293. ;yl185[]   /* Latin-1 to IBM Code Page 850 */
  294. ; This is IBM's official invertible translation.  Reference: IBM Character
  295. ; Data Representation Architecture (CDRA), Level 1, Registry, SC09-1291-00
  296. ; (1990), p.152.  (Note: Latin-1 is IBM Code Page 00819.)
  297. iL1cp850 db 186,205,201,187,200,188,204,185,203,202,206,223,220,219,254,242
  298.     db 179,196,218,191,192,217,195,180,194,193,197,176,177,178,213,159
  299.     db 255,173,189,156,207,190,221,245,249,184,166,174,170,240,169,238
  300.     db 248,241,253,252,239,230,244,250,247,251,167,175,172,171,243,168
  301.     db 183,181,182,199,142,143,146,128,212,144,210,211,222,214,215,216
  302.     db 209,165,227,224,226,229,153,158,157,235,233,234,154,237,232,225
  303.     db 133,160,131,198,132,134,145,135,138,130,136,137,141,161,140,139
  304.     db 208,164,149,162,147,228,148,246,155,151,163,150,129,236,231,152
  305.     db 96,'A',0                ; 96 byte set, letter ident
  306.  
  307. ; invertable Latin-1 to CP861 
  308. iL1cp861 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  309.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  310.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  311.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  312.     db 148,164,152,150,145,154,227,195,132,130,137,136,134,165,138,164
  313.     db 139,208,202,166,200,158,205,206,157,149,167,141,140,151,141,139
  314.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  315.     db 140,177,143,190, 20, 21,247,184,155,168,183,185,179,152,149,160
  316.     db 96,'A',0                ; 96 byte set, letter ident
  317.  
  318. ; 128 byte translation tables from Code Pages to ISO 8859-1 Latin1 or Latin5
  319. ; For GRight only (high bit set).
  320.                             ; from Code Page 437
  321. cp437L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  322.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  323.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  324.     db    0ffh,0d6h,0dch,0a2h, 0a3h,0a5h,3fh,3fh
  325.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  326.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0bbh
  327.     db    16 dup (3fh)                 ; column 11
  328.     db    16 dup (3fh)                 ; column 12
  329.     db    16 dup (3fh)                 ; column 13
  330.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  331.     db    5 dup(3fh),            0f8h,3fh,3fh
  332.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  333.     db    0b0h,0b7h,0b7h,3fh,3fh,        0b2h,3fh,3fh
  334.                              ; from Code Page 850
  335. cp850L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  336.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  337.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  338.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,0d7h,3fh
  339.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  340.     db    0bfh,0aeh,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  341.     db    5 dup (3fh),              0c1h,0c2h,0c0h ; column 11
  342.     db    0a9h, 4 dup (3fh),      0a2h,0a5h,3fh
  343.     db    6 dup (3fh),0e3h,0c3h, 7 dup (3fh),0a4h     ; column 12
  344.     db    0f0h,0d0h,0cah,0cbh, 0c8h,0b9h,0cdh,0ceh ; column 13
  345.     db    0cfh, 4 dup (3fh),       0a6h,0cch,3fh
  346.     db    0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,0feh ; column 14
  347.     db    0deh,0dah,0dbh,0d9h, 0fdh,0ddh,0afh,0b4h
  348.     db    0adh,0b1h,3dh,0beh,  0b6h,0a7h,0f7h,0b8h ; column 15
  349.     db    0b0h,0a8h,0b7h,0b9h, 0b3h,0b2h,3fh,20h
  350.  
  351.                              ; from Code Page 860
  352. cp860L1    db    0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8
  353.     db    0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h
  354.     db    0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9
  355.     db    0cdh,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h
  356.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  357.     db    0bfh,0d2h,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  358.     db    16 dup (3fh)                 ; column 11
  359.     db    16 dup (3fh)                 ; column 12
  360.     db    16 dup (3fh)                 ; column 13
  361.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  362.     db    5 dup(3fh),            0f8h,3fh,3fh
  363.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  364.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  365.  
  366.                             ; from Code Page 861
  367. cp861L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  368.     db    0eah,0ebh,0e8h,0d0h, 0f0h,0deh,0c4h,0c5h
  369.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0feh,0fbh,0ddh ; column 9
  370.     db    0fdh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  371.     db    0e1h,0edh,0f3h,0fah, 0c1h,0cdh,0d3h,0dah ; column 10
  372.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0bbh
  373.     db    16 dup (3fh)                 ; column 11
  374.     db    16 dup (3fh)                 ; column 12
  375.     db    16 dup (3fh)                 ; column 13
  376.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  377.     db    5 dup(3fh),            0f8h,3fh,3fh
  378.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  379.     db    0b0h,0b7h,0b7h,3fh,3fh,        0b2h,3fh,3fh
  380.  
  381.                              ; from Code Page 863
  382. cp863L1    db    0c7h,0fch,0e9h,0e2h, 0c2h,0e0h,0b6h,0e7h ; column 8
  383.     db    0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h
  384.     db    0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0f9h ; column 9
  385.     db    0a4h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh
  386.     db    0a6h,0b4h,0f3h,0fah, 0a8h,0b8h,0b3h,0afh ; column 10
  387.     db    0ceh,3fh,0ach,0bdh,  0bch,0beh,0abh,0bbh
  388.     db    16 dup (3fh)                 ; column 11
  389.     db    16 dup (3fh)                 ; column 12
  390.     db    16 dup (3fh)                 ; column 13
  391.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  392.     db    5 dup(3fh),            0f8h,3fh,3fh
  393.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  394.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  395.                                   ; from Code Page 865
  396. cp865L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  397.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  398.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  399.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  400.     db    0e2h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  401.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0a4h
  402.     db    16 dup (3fh)                 ; column 11
  403.     db    16 dup (3fh)                 ; column 12
  404.     db    16 dup (3fh)                 ; column 13
  405.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  406.     db    5 dup(3fh),            0f8h,3fh,3fh
  407.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  408.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  409.                     ; from Code Page 852 to LATIN2
  410. cp852L2    db 199,252,233,226,228,249,230,231,179,235,213,245,238,172,196,198
  411.     db 201,197,229,244,246,165,181,166,182,214,220,171,187,163,215,232
  412.     db 225,237,243,250,161,177,174,190,202,234,173,188,200,186,128,129
  413.     db 130,131,132,133,134,193,194,204,170,135,136,137,138,175,191,139
  414.     db 140,141,142,143,144,145,195,227,146,147,148,149,150,151,152,164
  415.     db 240,208,207,203,239,210,205,206,236,153,154,155,156,222,217,157
  416.     db 211,223,212,209,241,242,169,185,192,218,224,219,253,221,254,180
  417.     db 158,189,178,183,162,167,247,184,176,168,255,251,216,248,159,160
  418.  
  419.                     ; Code Page 862 to Hebrew-ISO
  420. cp862HI db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  421.     db 240,241,242,243,244,245,246,247,248,249,250,162,163,165,128,129
  422.     db 130,131,132,133,134,135,136,137,138,139,172,189,188,140,171,187
  423.     db 141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156
  424.     db 157,158,159,161,164,166,167,168,169,170,173,174,175,223,179,180
  425.     db 182,184,185,190,191,192,193,194,195,196,197,198,199,200,201,202
  426.     db 203,204,205,206,207,208,181,209,210,211,212,213,214,215,216,217
  427.     db 218,177,219,220,221,222,186,251,176,183,252,253,254,178,255,160
  428.  
  429.                      ; from Code Page 866 to LATIN5
  430. cp866L5    db    0b0h,0b1h,0b2h,0b3h, 0b4h,0b5h,0b6h,0b7h ; column 8
  431.     db    0b8h,0b9h,0bah,0bbh, 0bch,0bdh,0beh,0bfh
  432.     db    0c0h,0c1h,0c2h,0c3h, 0c4h,0c5h,0c6h,0c7h ; column 9
  433.     db    0c8h,0c9h,0cah,0cbh, 0cch,0cdh,0ceh,0cfh
  434.     db    0d0h,0d1h,0d2h,0d3h, 0d4h,0d5h,0d6h,0d7h ; column 10
  435.     db    0d8h,0d9h,0dah,0dbh, 0dch,0ddh,0deh,0dfh
  436.     db    16 dup (3fh)                 ; column 11
  437.     db    16 dup (3fh)                 ; column 12
  438.     db    16 dup (3fh)                 ; column 13
  439.     db    0e0h,0e1h,0e2h,0e3h, 0e4h,0e5h,0e6h,0e7h ; column 14
  440.     db    0e8h,0e9h,0eah,0ebh, 0ech,0edh,0eeh,0efh
  441.     db    0a1h,0f1h,0a4h,0f4h, 0a7h,0f7h,0aeh,0feh ; column 15
  442.     db    4 dup (3fh),         0f0h,3fh,3fh,0a0h
  443.  
  444. ;y43l1[]   /* IBM Code Page 437 to Latin-1 */
  445. ;  This table is the inverse of yl143[].
  446. icp437L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  447.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  448.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  449.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  450.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  451.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  452.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  453.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  454.  
  455. ;y85l1[]   /* IBM Code Page 850 to Latin-1 */
  456. ;  This is from IBM CDRA page 153.  It is the inverse of yl185[].
  457. icp850L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  458.     db 201,230,198,244,246,242,251,249,255,214,220,248,163,216,215,159
  459.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  460.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,162,165,147
  461.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  462.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  463.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  464.     db 173,177,143,190,182,167,247,184,176,168,183,185,179,178,142,160
  465.  
  466. ;y86l1[]   /* IBM Code Page 861 to Latin-1 */
  467. ;  This table is the inverse of yl186[].
  468. icp861L1 db 199,252,233,226,228,224,229,231,234,235,232,208,240,222,196,197
  469.     db 201,230,198,244,246,254,251,221,253,214,220,248,163,216,215,159
  470.     db 225,237,243,250,193,205,211,218,191,174,172,189,188,161,171,187
  471.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  472.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  473.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  474.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  475.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  476. data    ends
  477.  
  478. code    segment
  479.     extrn    decout:near, isfile:near, newfn:near, comnd:near, atoi:near
  480.     extrn    ermsg:near, clrfln:near, frpos:near, kbpr:near, perpr:near
  481.  
  482.     assume  cs:code, ds:data, es:nothing
  483.  
  484. ; Set register BX to the offset of the ISO Latin-1 table appropriate to the
  485. ; currently active Code Page. Defaults to CP437 if no CP found.
  486. LATIN1    proc    near
  487.     push    ax
  488.     mov    ax,flags.chrset
  489.     mov    bx,offset L1cp437    ; assume CP437
  490.     cmp    ax,437            ; current Code Page is 437?
  491.     je    latin1x            ; e = yes
  492.     mov    bx,offset L1cp850    ; assume CP850
  493.     cmp    ax,850            ; current Code Page is 850?
  494.     je    latin1x            ; e = yes
  495.     mov    bx,offset L1cp860    ; assume CP860
  496.     cmp    ax,860            ; current Code Page is 860?
  497.     je    latin1x            ; e = yes
  498.     mov    bx,offset L1cp861    ; assume CP861
  499.     cmp    ax,861            ; current Code Page is 861?
  500.     je    latin1x            ; e = yes
  501.     mov    bx,offset L2cp852    ; assume CP852
  502.     cmp    ax,852            ; current Code Page is 852?
  503.     je    latin1x            ; e = yes
  504.     mov    bx,offset HIcp862    ; assume CP862
  505.     cmp    ax,862            ; current Code Page is 862?
  506.     je    latin1x            ; e = yes
  507.     mov    bx,offset L1cp863    ; assume CP863
  508.     cmp    ax,863            ; current Code Page is 863?
  509.     je    latin1x            ; e = yes
  510.     mov    bx,offset L1cp865    ; assume CP865
  511.     cmp    ax,865            ; current Code Page is 865?
  512.     je    latin1x            ; e = yes
  513.     mov    bx,offset L5cp866    ; assume CP866
  514.     cmp    ax,866            ; current Code Page is 866?
  515.     je    latin1x            ; e = yes
  516. ;    mov    bx,offset userin    ; user loadable incoming table
  517. ;    cmp    ax,1            ; User-defined table?
  518. ;    je    latin1x            ; e = yes
  519.     mov    bx,offset L1cp437    ; default to CP437
  520. latin1x:pop    ax
  521.     ret
  522. LATIN1    endp
  523.  
  524. ; Call after LATIN1. Revise BX to point to invertible tables rather than
  525. ; readable translation tables.
  526. latininv proc    near
  527.     cmp    trans.xchri,0        ; readable (vs invertible)?
  528.     je    latinvx            ; e = yes, do nothing
  529.     cmp    bx,offset L1cp437    ; this table in use?
  530.     jne    latinv1            ; ne = no
  531.     mov    bx,offset iL1cp437    ; use invertible instead
  532.     ret
  533. latinv1:cmp    bx,offset L1cp850    ; this table in use?
  534.     jne    latinv2            ; ne = no
  535.     mov    bx,offset iL1cp850    ; use invertible instead
  536.     ret
  537. latinv2:cmp    bx,offset L1cp861    ; this table?
  538.     jne    latinvx            ; ne = no
  539.     mov    bx,offset iL1cp861    ; use invertible instead
  540. latinvx:ret
  541. latininv endp
  542.  
  543. ; Set BX to offset of table for Code Page to ISO 8859-1 Latin1/Latin5
  544. cplatin proc    near
  545.     push    ax
  546.     mov    ax,flags.chrset
  547.     mov    bx,offset cp437L1    ; assume CP437
  548.     cmp    ax,437            ; current Code Page is 437?
  549.     je    cplatx            ; e = yes
  550.     mov    bx,offset cp850L1    ; assume CP850
  551.     cmp    ax,850            ; current Code Page is 850?
  552.     je    cplatx            ; e = yes
  553.     mov    bx,offset cp860L1    ; assume CP860
  554.     cmp    ax,860            ; current Code Page is 860?
  555.     je    cplatx            ; e = yes
  556.     mov    bx,offset cp861L1    ; assume CP861
  557.     cmp    ax,861            ; current Code Page is 861?
  558.     je    cplatx            ; e = yes
  559.     mov    bx,offset cp852L2    ; assume CP852
  560.     cmp    ax,852            ; current Code Page is 852?
  561.     je    cplatx            ; e = yes
  562.     mov    bx,offset cp862HI    ; assume CP862
  563.     cmp    ax,862            ; current Code Page is 862?
  564.     je    cplatx            ; e = yes
  565.     mov    bx,offset cp863L1    ; assume CP863
  566.     cmp    ax,863            ; current Code Page is 863?
  567.     je    cplatx            ; e = yes
  568.     mov    bx,offset cp865L1    ; assume CP865
  569.     cmp    ax,865            ; current Code Page is 865?
  570.     je    cplatx            ; e = yes
  571.     mov    bx,offset cp866L5    ; assume CP866 for LATIN5
  572.     cmp    ax,866            ; corrent Code Page is 866?
  573.     je    cplatx            ; e = yes
  574. ;    mov    bx,offset userout    ; user loadable outgoing table
  575. ;    cmp    ax,1            ; User-table?
  576. ;    je    cplatx            ; e = yes
  577.     mov    bx,offset cp437L1    ; default to CP437
  578. cplatx:    pop    ax
  579.     ret
  580. cplatin endp
  581.  
  582. ; Call after CPLATIN. Revise BX to point to invertible tables rather than
  583. ; readable translation tables.
  584. cpinvert proc    near
  585.     cmp    trans.xchri,0        ; readable (vs invertible)?
  586.     je    cpinverx        ; e = yes, do nothing
  587.     cmp    bx,offset cp437L1    ; this table in use?
  588.     jne    cpinver1        ; ne = no
  589.     mov    bx,offset icp437L1    ; use invertible instead
  590.     ret
  591. cpinver1:cmp    bx,offset cp850L1    ; this table in use?
  592.     jne    cpinver2        ; ne = no
  593.     mov    bx,offset icp850L1    ; use invertible instead
  594.     ret
  595. cpinver2:cmp    bx,offset cp861L1    ; this table in use?
  596.     jne    cpinverx        ; ne = no
  597.     mov    bx,offset icp861L1    ; use invertible instead
  598. cpinverx:ret
  599. cpinvert endp
  600.  
  601. ; Output the chars in a packet, called only by receiver code.
  602. ; Enter with SI equal to pktinfo structure pointer.
  603. PTCHR:    mov    decoutp,offset outbuf  ; routine to call when buffer gets full
  604.     jmp    short decode
  605.  
  606.  
  607. ; Dodecoding.
  608. ; Decode packet to buffer decbuf. Overflow of decbuf yields error ???
  609. ; Modifies regs BX, CX.
  610. ; Enter with SI equal to pktinfo structure pointer.
  611. dodec    proc    near
  612.     push    ax            ; save reg
  613.     mov    ah,dblbyteflg        ; preserve state
  614.     mov    al,dblbyte
  615.     push    ax
  616.     mov    al,shiftstate
  617.     mov    ah,DLEseen
  618.     push    ax
  619.     mov    dblbyteflg,0        ; init decode as doubles
  620.     mov    shiftstate,0        ; init shift states
  621.     mov    DLEseen,0        ; init escape
  622.     mov    decoutp,offset dnulr    ; routine to dump buffer (null)
  623.     call    decode
  624.     pop    ax
  625.     mov    shiftstate,al        ; restore decoder state
  626.     mov    DLEseen,ah
  627.     pop    ax
  628.     mov    dblbyteflg,ah
  629.     mov    dblbyte,al
  630.     push    bx
  631.     mov    bx,dbufpnt        ; next char position
  632.     mov    byte ptr [bx],0        ; null terminator
  633.     pop    bx
  634.      pop    ax
  635.     ret
  636. dodec    endp
  637.  
  638. dnulr:    ret                ; dummy buffer emptier
  639.  
  640. ; Enter with [si].datlen = length of data, [si].datadr = dw address of data,
  641. ; DECOUTP = pointer to routine which writes output buffer
  642. ; Returns DBUFPNT = pointer to output buffer address (offset part).
  643. ; Trans.lshift is non-zero if locking shift encoding is active.
  644. ; DLEseen is non-zero if a DLE char (Control-P) is decoded while locking shift
  645. ; is active; under these circumstances DLE escapes DLE, SI, and SO to be
  646. ; data characters. Under locking shift rules SO (Control-N) shifts high bit
  647. ; data to non-high bit data (and we thus reverse this); SI (Control-O)
  648. ; cancels SO.
  649. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while
  650. ; performing Japanese translation; dblbyte is the first byte of the pair.
  651. ; All packets are decoded except I, S, and A types.
  652. ; Flushes output buffer before returning.
  653. ; Returns carry clear if success, otherwise carry set
  654. decode    proc    near
  655.     push    si
  656.     push    di
  657.     push    es
  658.     push    dx
  659.     push    ds
  660.     pop    es
  661.     cld                ; forward direction
  662.     mov    dchrcnt,length decbuf    ; size of output buffer
  663.     mov    dbufpnt,offset decbuf ; decoded data placed here pending output
  664.     mov    cx,[si].datlen        ; length of source buffer data
  665.     les    si,[si].datadr        ; source buffer address to es:[si]
  666.     mov    di,dbufpnt        ; destination of data
  667.     mov    bl,trans.squote        ; regular quote char
  668.     xor    dh,dh            ; assume no quote char
  669.     cmp    trans.ebquot,'N'    ; any 8-bit quoting?
  670.     je    decod1            ; e = no quoting
  671.     cmp    trans.ebquot,'Y'    ; or not doing it?
  672.     je    decod1            ; e = no need to quote
  673.     mov    dh,trans.ebquot        ; otherwise use 8-bit quote char
  674.  
  675. decod1:    mov    rptct,1            ; reset repeat count
  676.     or    cx,cx            ; any more chars in source?
  677.     jg    decod2            ; g = yes
  678.     jmp    decod6            ; else, we're through
  679. decod2:    mov    al,es:[si]        ; pick up a char
  680.     inc    si
  681.     dec    cx            ; count number left
  682.     cmp    al,trans.rptq        ; repeat quote char?
  683.     jne    dcod2a            ; ne = no, continue processing it
  684.     or    al,al            ; doing repeat quoting? (0 if no)
  685.     jz    dcod2a            ; z = no, skip this part
  686.     mov    al,es:[si]        ; get the size
  687.     inc    si
  688.     dec    cx            ; modify buffer count
  689.     sub    al,20H            ; make count numeric
  690.     mov    rptct,al        ; remember how many repetitions
  691.     mov    al,es:[si]        ; get the char to repeat
  692.     inc    si
  693.     dec    cx            ; modify buffer count
  694.  
  695. dcod2a:    xor    ah,ah            ; assume no 8-bit quote char
  696.     cmp    al,dh            ; is this the 8-bit quot char?
  697.     jne    decod3            ; ne = no
  698.     mov    al,es:[si]        ; yes, get the real character
  699.     inc    si
  700.     dec    cx            ; decrement # chars in packet
  701.     mov    ah,80H            ; turn on high bit
  702. decod3:    cmp    al,bl            ; quote char?
  703.     jne    decod4            ; ne = no, proceed
  704.     mov    al,es:[si]        ; get the quoted character
  705.     inc    si
  706.     dec    cx            ; decrement # of chars in packet
  707.     or    ah,al            ; save parity (combine with prefix)
  708.     and    ax,807fh        ; only parity in ah, remove it in al
  709.     cmp    al,bl            ; quote char?
  710.     je    decod4            ; e = yes, just go write it out
  711.     cmp    al,dh            ; 8-bit quote char?
  712.     je    decod4            ; e = yes, just go write it out
  713.     cmp    al,trans.rptq        ; repeat quote character?
  714.     je    decod4            ; e = yes, just write it out
  715.     cmp    al,3fh            ; char less than '?' ?
  716.     jb    decod4            ; b = yes; leave it intact
  717.     cmp    al,5fh            ; char greater than '_' ?
  718.     ja    decod4            ; a = yes; leave it alone
  719.     add    al,40H            ; make it a control char again
  720.     and    al,7FH            ; modulo 128 (includes DEL)
  721. decod4:    xor    ah,shiftstate        ; modify high bit by shiftstate
  722.         or    al,ah            ; or in parity
  723.  
  724.     cmp    trans.lshift,lock_disable ; locking shift disabled?
  725.     je    decod5            ; e = yes
  726.     mov    ah,al
  727.     xor    ah,shiftstate        ; adjust high bit by shift state
  728.     cmp    ah,DLE            ; DLE?
  729.     jne    dcod4c            ; ne = no
  730.     cmp    DLEseen,0        ; has DLE been escaped (by DLE)?
  731.     je    dcod4b            ; e = no, make this the escape
  732.     mov    DLEseen,0        ; unescape now
  733.     jmp    short decod5        ; process the literal DLE
  734.                     ; handle repeat counted DLE's
  735. dcod4b:    shr    rptct,1            ; divide by two, carry has lsb
  736.     rcl    DLEseen,1        ; pickup carry bit if odd number
  737.     jmp    short decod5        ; write the DLE's
  738.  
  739. dcod4c:    cmp    DLEseen,0        ; DLE prefix seen?
  740.     mov    DLEseen,0        ; clear it now too
  741.     jne    decod5            ; ne = yes, prefixed, do literal
  742.     cmp    ah,SIchar        ; SI?
  743.     jne    dcod4d            ; ne = no
  744.     mov    shiftstate,0        ; say exiting shifted state
  745.     jmp    decod1            ; nothing to write
  746. dcod4d:    cmp    ah,SOchar        ; SO?
  747.     jne    decod5            ; ne = no
  748.     mov    shiftstate,80h        ; say entering shifted state
  749.     jmp    decod1            ; nothing to write
  750.  
  751. decod5:    push    cx
  752.     mov    cl,rptct        ; repeat count
  753.     xor    ch,ch
  754.     or    cl,cl
  755.     jle    decod5c            ; le = nothing to do (94 max)
  756.     cmp    cx,dchrcnt        ; needed vs space available
  757.     jbe    decod5a            ; be = enough space for rptct chars
  758.     mov    cx,dchrcnt        ; insufficient space, do dchrcnt
  759. decod5a:sub    rptct,cl        ; reduce number left to be written
  760.     sub    dchrcnt,cx        ; reduce output free space
  761.     pushf                ; save sub status flags
  762.     shr    cx,1
  763.     jnc    decod5b            ; nc = an even number
  764.     mov    [di],al            ; store the odd byte
  765.     inc    di
  766.     jcxz    decod5d            ; z = nothing else to write
  767. decod5b:mov    ah,al            ; make a copy for word writes
  768.     push    bx            ; source is es:[si], dest is ds:[di]
  769.     push    es            ; save and swap ds and es
  770.     push    ds
  771.     mov    bx,es
  772.     pop    es            ; old ds to es
  773.     push    ds            ; restore
  774.     mov    ds,bx            ; old es to ds
  775.     rep    stosw            ; store cx words
  776.     pop    ds
  777.     pop    es
  778.     pop    bx
  779. decod5d:popf                ; recover flags from sub dchrcnt,cx
  780.     jg    decod5c            ; g = space remaining in output buffer
  781.     push    dx            ; flush output buffer
  782.     push    bx
  783.     push    ax            ; save the char
  784.     push    es
  785.     call    decoutp            ; output the buffer
  786.     pop    es
  787.     pop    ax            ; recover repeated char
  788.     pop    bx
  789.     pop    dx
  790.     jc    decod7            ; c = error if disk is full
  791.     mov    di,dbufpnt
  792.     pop    cx
  793.     jmp    short decod5        ; see if more chars need be written
  794. decod5c:pop    cx            ; recover main loop counter
  795.     jmp    decod1            ; get next source character
  796.     
  797. decod6:    mov    dbufpnt,di            ; flush buffer before exiting decode
  798.     push    cx
  799.     push    es
  800.     call    decoutp            ; flush output buffer before final ret
  801.     pop    es
  802. decod7:    pop    cx
  803.  
  804.     pop    dx
  805.     pop    es
  806.     pop    di
  807.     pop    si
  808.     ret                ; return successfully if carry clear
  809. decode    endp
  810.  
  811. outbuf    proc    near            ; output decbuf, reset bufpnt & chrcnt
  812.     mov    cx,length decbuf    ; get full size of buffer
  813.     sub    cx,dchrcnt        ; minus space remaining = # to write
  814.     jg    outbu2            ; g = something to do
  815.     jmp    outbf1
  816. outbu2:    mov    dx,offset decbuf    ; address of buffer
  817.     cmp    trans.xtype,1        ; File Type Binary?
  818.     je    outbu5            ; e = yes, no translation
  819.     cmp    flags.destflg,1        ; disk destination?
  820.     je    outbu5            ; e = yes, DOS will do it
  821.     cmp    flags.eofcz,0        ; end on Control-Z?
  822.     je    outbu5            ; e = no
  823.     push    cx            ; else map Control-Z to space
  824.     push    di
  825.     mov    di,seg decbuf
  826.     mov    es,di            ; data to es
  827.     mov    di,dx            ; scan buffer es:di, cx chars worth
  828.     mov    al,ctlz            ; look for Control-Z
  829.     cld
  830. outbu3:    repne    scasb
  831.     jne    outbu4            ; ne = found no Control-Z's
  832.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  833.     jcxz    outbu4            ; z = examined all chars
  834.     jmp    short outbu3        ; until examined everything
  835. outbu4:    pop    di
  836.     pop    cx
  837.                     ; Character set translation section
  838. outbu5:    cmp    trans.xtype,1        ; File Type Binary?
  839.     je    outbu7            ; e = yes, no translation
  840.     cmp    trans.xchset,xfr_xparent ; Transfer Transparent?
  841.     je    outbu7            ; e = yes, no translation
  842.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  843.     jne    outbu5a            ; ne = no
  844.     call    jpnwrite        ; do special decoding
  845.     jmp    outbu7
  846. outbu5a:push    cx
  847.     push    si
  848.     push    di
  849.     mov    di,seg decbuf
  850.     mov    es,di
  851.     call    latin1            ; set BX to xfr char set to CP table
  852.     call    latininv        ; select invertable or readable set
  853.     mov    si,offset decbuf    ; scan this buffer
  854.     mov    di,si
  855.     cld
  856. outbu6:    lodsb                ; get a char
  857.     test    al,80h            ; GRight?
  858.     jnz    outbu6a            ; nz = yes
  859.     cmp    bx,offset iL1cp437    ; using invertable Latin1 to CP437?
  860.     jne    outbu6c            ; ne = no
  861.     cmp    ah,127            ; 127 goes to 28?
  862.     jne    outbu6e            ; ne = no
  863.     mov    al,28            ; 127 to 28
  864.     jmp    short outbu6b
  865. outbu6e:cmp    al,21            ; special case?
  866.     ja    outbu6b            ; a = no
  867.     cmp    al,20            ; special case?
  868.     jb    outbu6b            ; b = no
  869.     mov    ah,al
  870.     mov    al,244            ; 20 to 244
  871.     cmp    ah,21            ; special case?
  872.     jne    outbu6b            ; ne = no
  873.     mov    al,245            ; preset one answer
  874.     je    outbu6b            ; e = yes, 21 to 245
  875.     mov    al,244            ; 22 to 244
  876.     jmp    short outbu6b
  877. outbu6c:cmp    bx,offset iL1cp850    ; using invertible Latin1 to CP850?
  878.     jne    outbu6b            ; ne = no
  879.     cmp    al,26            ; special case?
  880.     jne    outbu6d            ; ne = no
  881.     mov    al,127            ; 26 to 127
  882.     jmp    outbu6b
  883. outbu6d:cmp    al,127            ; special case?
  884.     jne    outbu6b            ; ne = no
  885.     mov    al,28            ; 127 to 28
  886.     jmp    short outbu6b
  887. outbu6a:and    al,not 80h        ; strip high bit
  888.     xlatb                ; translate via bx table
  889. outbu6b:stosb                ; store char
  890.     loop    outbu6            ; do all concerned
  891.     pop    di
  892.     pop    si
  893.     pop    cx
  894.  
  895. outbu7:    push    bx
  896.     mov    bx,diskio.handle    ; file handle
  897.     mov    ah,write2        ; write cx bytes
  898.     int    dos
  899.     pop    bx
  900.     jc    outbf0            ; c set means writing error
  901.     cmp    ax,cx            ; did we write all the bytes?
  902.     je    outbf1            ; e = yes
  903.     push    bx
  904.     mov    bx,offset decbuf
  905.     add    bx,ax            ; look at break character
  906.     cmp    byte ptr [bx],ctlz    ; ended on Control-Z?
  907.     pop    bx
  908.     je    outbf1            ; e = yes, say no error
  909. outbf0: mov    dx,offset erms13    ; Error writing device
  910.     cmp    flags.xflg,0        ; writing to screen?
  911.     jne    outbf0a            ; ne = yes
  912.     cmp    flags.destflg,0        ; writing to printer?
  913.     jne    outbf0a            ; ne = no
  914.     mov    dx,offset ermes9    ; Printer not ready message
  915. outbf0a:call    ermsg
  916.     stc                ; return failure
  917.     ret
  918.  
  919. outbf1:    add    tfilsz,cx        ; count received chars
  920.     adc    tfilsz+2,0
  921.     add    fsta.frbyte,cx
  922.     adc    fsta.frbyte+2,0
  923.     test    flags.remflg,dserial    ; serial mode display?
  924.     jnz    outb11            ; nz = yes, skip kbyte and % displays
  925.     cmp    flags.xflg,0        ; receiving to screen?
  926.     jne    outb11            ; ne = yes
  927.     call    kbpr            ; display kilobytes done
  928.     call    perpr            ; display percentage done
  929. outb11:    mov    dbufpnt,offset decbuf    ; address for beginning
  930.     mov    dchrcnt,length decbuf    ; size of empty buffer
  931.     clc                ; return success
  932.     ret
  933. outbuf    endp
  934.  
  935. ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp)
  936. ; Reread buffer decbuf to convert from transfer character set
  937. ; Japanese-EUC into Shift-JIS (Code Page 932). Double char translation state
  938. ; is maintained across file buffers. Init dblbyte to 0 before each new file.
  939. ; Returns registers
  940. ;    cx      number of bytes written in the buffer
  941. ;    dx      address of the output buffer
  942. ;            this points decbuf or decbuf-1, depending on dblbyteflg
  943. ; Output is otherwise written over the input. [rewritten by jrd]
  944. jpnwrite proc    near            ; [HF] write Japanese to file
  945.     push    si            ; decbuf is read/written
  946.     push    di            ; cx has incoming/outgoing byte count
  947.     push    bx            ; dblbyte has earlier first byte
  948.     push    es            ; dblbyteflg is state from prev call
  949.     mov    dx,ds
  950.     mov    es,dx
  951.     cld                ; restore state from previous call
  952.     mov    dl,dblbyteflg        ; state, non-zero if doing second byte
  953.     mov    ah,dblbyte        ;  and first byte from previous read
  954.     mov    si,offset decbuf    ; read/write this buffer
  955.     mov    di,si            ; set the address for write
  956.     mov    bx,si            ; save for computing output buf length
  957.     or    dl,dl            ; carry-in of a double byte char?
  958.     jz    jpnwri1            ; z = no
  959.     dec    di            ; start output one byte before decbuf
  960.     dec    bx            ; adjust the start address
  961. jpnwri1:lodsb                ; get a byte
  962.     or    dl,dl            ; processing 2nd byte of a pair?
  963.     jnz    jpnwri3            ; nz = yes, do second byte processor
  964.                     ; first byte processor
  965.     cmp    al,80h            ; 8th bit on?
  966.     jb    jpnwri5            ; b = no, this is a single char
  967.     cmp    al,8eh            ; JIS X 0201 Katakana prefix?
  968.     je    jpnwri2            ; e = yes, is first of two chars
  969.     cmp    al,0a1h            ; JIS X 0208 Kanji ?
  970.     jb    jpnwri5            ; b = no, is single char
  971.     cmp    al,0feh
  972.     ja    jpnwri5            ; a = no, is single char
  973. jpnwri2:mov    ah,al            ; save first of two chars
  974.     mov    dl,1            ; say need second char of pair
  975.     jmp    short jpnwri6        ; read second byte
  976.                     ; process second char of two byte pair
  977. jpnwri3:cmp    ah,8eh            ; was first char JIS X 0201 Katakana?
  978.     jne    jpnwri4            ; ne = no
  979.     or    al,80h            ; make sure 8th bit is on
  980.     jmp    short jpnwri5        ; write one char
  981. jpnwri4:call    jpnxtof            ; xfer -> file char code conversion
  982.     xchg    ah,al
  983.     stosb                ; write first byte
  984.     xchg    ah,al            ; and second byte
  985. jpnwri5:stosb                ; write a char
  986.     xor    dl,dl            ; clear multi-byte counter
  987. jpnwri6:loop    jpnwri1
  988.     mov    dblbyteflg,dl        ; save state info
  989.     mov    dblbyte,ah        ; and the first byte of a pair
  990.     sub    di,bx            ; find number of chars written
  991.     mov    cx,di            ; return new count in CX
  992.     mov    dx,bx            ; return new buffer address for write
  993.     pop    es            ; can be decbuf - 1 if carry-in of dbl
  994.     pop    bx
  995.     pop    di
  996.     pop    si
  997.     clc
  998.     ret
  999. jpnwrite endp
  1000.  
  1001. ; Transfer character code (EUC) to file character code (Shift-JIS) converter.
  1002. ; input      AH: 1st byte of EUC code
  1003. ;            AL: 2nd byte of EUC code
  1004. ; output     AH: 1st byte of Shift-JIS code
  1005. ;            AL: 2nd byte of Shift-JIS code
  1006. ; From EUC to Shift-JIS
  1007. ;   code1 = (EUC_code1 & 0x7f);
  1008. ;   code2 = (EUC_code2 & 0x7f);
  1009. ;   if( code1 & 1)
  1010. ;     code2 += 0x1f;
  1011. ;   else
  1012. ;     code2 += 0x7d;
  1013. ;   if( code2 >= 0x7f ) code2++;
  1014. ;   code1 = ((code1 - 0x21) >> 1) + 0x81;
  1015. ;   if( code1 > 0x9f ) code1 += 0x40;
  1016. ;   [ fputc( code1, file ); fputc( code2, file ); ]
  1017. ;
  1018. jpnxtof    proc    near
  1019.     and    ax,7f7fh        ; mask both 8-th bits
  1020.     test    ah,1
  1021.     jz    jpnxtof1
  1022.     add    al,1fh
  1023.     jmp    short jpnxtof2
  1024. jpnxtof1:add    al,7dh
  1025. jpnxtof2:cmp    al,7fh
  1026.     jb    jpnxtof3
  1027.     inc    al
  1028. jpnxtof3:sub    ah,21h
  1029.     shr    ah,1
  1030.     add    ah,81h
  1031.     cmp    ah,9fh
  1032.     jbe    jpnxtof4
  1033.     add    ah,40h
  1034. jpnxtof4:ret
  1035. jpnxtof    endp
  1036.  
  1037. ; Get chars from file, encode them to pktinfo structure pointed to by si
  1038.  
  1039. gtchr:    mov    [si].datlen,0        ; say no output data yet
  1040.     cmp    filflg,0        ; is there anything in the buffer?
  1041.     jne    gtchr0            ; ne = yes, use that material first
  1042.     call    inbuf            ; do initial read from source
  1043.     jc    gtchr1            ; c = no more chars, go return EOF
  1044. gtchr0:    mov    encinp,offset inbuf    ; buffer refiller routine
  1045.     jmp    short encode
  1046.  
  1047. gtchr1:    mov    [si].datlen,0        ; report EOF
  1048.     mov    flags.eoflag,1        ; say eof
  1049.     stc                ; return failure
  1050.     ret
  1051.  
  1052. ; Do encoding.
  1053. ; Enter with CX = data size, source of data is encbuf, si is pktinfo ptr.
  1054. ; Writes output to area pointed to by [si].datadr.
  1055. ; Returns char count in cx and [si].datlen with carry clear if success,
  1056. ; else carry set if overflow.
  1057. ; SI is preserved
  1058. doenc:    clc
  1059.     jcxz    doen0            ; cx = 0 means nothing to encode
  1060.     mov    ah,dblbyteflg        ; preserve state
  1061.     mov    al,dblbyte
  1062.     push    ax
  1063.     mov    al,shiftstate        ; locking shift state
  1064.     mov    ah,DLEseen        ; DLE state
  1065.     push    ax            ; save
  1066.     mov    dblbyteflg,0        ; init encode as doubles
  1067.     mov    shiftstate,0        ; init shift states
  1068.     mov    DLEseen,0
  1069.     mov    echrcnt,cx        ; number of bytes of source data
  1070.     mov    ebufpnt,offset encbuf    ; source of data
  1071.     mov    encinp,offset nulref    ; null routine for refilling buffer
  1072.     call    encode            ; make a packet with size in AX
  1073.     mov    cx,ax
  1074.     pop    ax            ; restore state
  1075.     mov    shiftstate,al
  1076.     mov    DLEseen,ah
  1077.     pop    ax
  1078.     mov    dblbyteflg,ah
  1079.     mov    dblbyte,al
  1080. doen0:    ret
  1081.  
  1082. nulref:    mov    echrcnt,0        ; no data to return
  1083.     stc
  1084.     ret
  1085.  
  1086. ; encode - writes data portion of kermit packet into [[si].datadr].
  1087. ; expects encinp to contain the address of a routine to refill the buffer,
  1088. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  1089. ; the maximum size of the data packet, ebufpnt to contain a pointer to
  1090. ; the source of the characters, and [si].datadr to be output address.
  1091. ; Trans.lshift is non-zero if locking shift encoding is active.
  1092. ; While locking shift is active DLE escapes DLE, SI, and SO to be
  1093. ; data characters. Under locking shift rules SO (Control-N) shifts high bit
  1094. ; data to non-high bit data; SI (Control-O) cancels SO. Shiftstate is
  1095. ; 0 for non-shifted state, 80h for shifted state.
  1096. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while
  1097. ; performing Japanese translation; dblbyte is the first byte of the pair.
  1098. ; Returns: AX = the number of characters actually written to the buffer
  1099. ; All packets except I, S, and A types are encoded.
  1100. ; Packet space is precomputed allowing for prefixes other than locking shifts.
  1101. ; Returns carry clear for success, carry set otherwise.
  1102.  
  1103. encode    proc    near
  1104.     push    es
  1105.     push    si            ; save caller's si
  1106.     mov    cx,trans.maxdat        ; maximum packet size
  1107.     les    di,[si].datadr        ; address of output buffer to es:[di]
  1108.     mov    temp,di            ; remember output buffer start address
  1109.     mov    si,ebufpnt        ; pointer into source buffer
  1110.     mov    dl,trans.rquote        ; send quote char
  1111.     xor    dh,dh            ; assume no 8-bit quoting
  1112.     mov    al,trans.ebquot        ; 8-bit quote
  1113.     cmp    al,'N'            ; refusing 8-bit quoting?
  1114.     je    encod10            ; e = yes
  1115.     cmp    al,'Y'            ; or can but won't?
  1116.     je    encod10            ; e = yes, else specific char
  1117.     mov    dh,0ffh            ; remember we have to do 8-bit quotes
  1118.                     ; top of read loop
  1119. encod10:or    cx,cx            ; any space left in output buffer?
  1120.     jge    encod11            ; ge = yes
  1121.     mov    ax,di            ; current output location
  1122.     sub    ax,temp            ; minus start of buffer, ret cnt in AX
  1123.     mov    ebufpnt,si        ; update pointer into source buffer
  1124.     pop    si            ; restore caller's si
  1125.     pop    es
  1126.     mov    [si].datlen,ax
  1127.     clc                ; success
  1128.     ret
  1129.  
  1130. encod11:cmp    echrcnt,0        ; any data in buffer?
  1131.     jg    encod20            ; g = yes, skip over buffer refill
  1132.     push    es
  1133.     call    encinp            ; get another buffer full
  1134.     pop    es
  1135.     jnc    encod14            ; nc = success
  1136.  
  1137. encod12:pop    si            ; restore user's si
  1138.     sub    di,temp            ; minus start of buffer
  1139.     or    di,di            ; buffer empty?
  1140.     jz    encod13            ; z = yes
  1141.     mov    ax,di            ; report size encoded
  1142.     mov    [si].datlen,ax
  1143.     pop    es
  1144.     clc                ; success
  1145.     ret                ; return success
  1146. encod13:xor    ax,ax            ; empty buffer
  1147.         mov    flags.eoflag,1        ; set eof flag
  1148.     mov    filflg,al        ; nothing in input buffer
  1149.     mov    [si].datlen,ax
  1150.     pop    es
  1151.     stc                ; failure
  1152.     ret                ; return failure
  1153.  
  1154. encod14:mov    si,ebufpnt        ; update position in source buffer
  1155.     cmp    echrcnt,0         ; any characters returned?
  1156.     je    encod12            ; e = none, assume eof
  1157.  
  1158. encod20:cld                ; forward direction
  1159.     lodsb
  1160.     dec    echrcnt            ; decrement input count
  1161.     mov    ah,al
  1162.     and    ah,80h            ; keep high bit in ah
  1163.     mov    rptct,1            ; say have one copy of this char
  1164.     cmp    al,'Z'-40H        ; is this a control-Z?
  1165.     jne    encd30            ; ne = no, skip eof-processing
  1166.     cmp    flags.eofcz,0           ; is a Control-Z an end of file?
  1167.     je    encd30            ; e = no
  1168.     cmp    trans.xtype,1        ; file type binary?
  1169.     je    encd30            ; e = yes, send as is
  1170.     mov    flags.eoflag,1        ; yes, set eof flag
  1171.     mov    filflg,0        ; say no more source data in buffer
  1172.     mov    echrcnt,0        ; ditto
  1173.     jmp    short encod12        ; set character count and return
  1174.  
  1175.                     ; analyze current char (al)
  1176. encd30:    cmp    echrcnt,0        ; doing the last character?
  1177.     jle    encod40            ; le = yes, there is no next character
  1178.     or    cx,cx            ; space left in output buffer?
  1179.     jle    encod40a        ; le = no, not enough for rpt prefix
  1180.     cmp    al,[si]            ; this is char the same as the next?
  1181.     jne    encod40            ; no, do this char independently
  1182.     cmp    trans.rptq,0        ; allowed to do repeat prefixing?
  1183.     je    encod40            ; e = no
  1184.     push    cx            ; scan for repeats in input buffer
  1185.     push    bx
  1186.     mov    cx,echrcnt        ; count of bytes left in input buf
  1187.     inc    cx            ; will reread current byte
  1188.     cmp    cx,94            ; max prefix of 94
  1189.     jbe    encod31            ; be = ok, else limit scan to 94
  1190.     mov    cx,94
  1191. encod31:xor    bx,bx            ; count of copies of this char in buf
  1192. encod32:inc    bx
  1193.     cmp    [si+bx-1],al        ; new [si+bx-1] same as current (al)?
  1194.     loope    encod32            ; e = yes, do all of interest
  1195.     cmp    bx,3            ; enough repeats to use prefix?
  1196.     jae    encod33            ; ae = yes
  1197.     mov    bx,1            ; say do one char
  1198. encod33:mov    rptct,bl        ; bl is qty repeated overall
  1199.     dec    bx            ; ax = number of extra chars (>1)
  1200.     add    si,bx            ; move forward by repeat group
  1201.     sub    echrcnt,bx        ; input buffer counter too
  1202.     pop    bx
  1203.     pop    cx
  1204.  
  1205.                     ; test for locking shift applicability
  1206. encod40:or    cx,cx            ; enough space left in output buffer?
  1207.     jle    encod50            ; le = no, not enough for prefix
  1208.     cmp    trans.lshift,lock_disable ; locking shifts disabled?
  1209.     je    encod50            ; e = yes, skip this material
  1210.     cmp    ah,shiftstate        ; change of high bit status?
  1211.     jne    encod41            ; ne = yes
  1212. encod40a:jmp    encod50            ; no, stay in same lock state
  1213.                     ; change of high bit
  1214. encod41:mov    bx,echrcnt        ; count chars remaining to be read
  1215.     add    bl,rptct        ; add repeat count
  1216.     adc    bh,0
  1217.     cmp    bx,4            ; at least 4 more chars to examine?
  1218.     jb    encod50            ; b = no, not worth a lock change
  1219.     cmp    rptct,4            ; enough repeats to take short cut?
  1220.     jae    encod43            ; ae = plenty of repeats
  1221.  
  1222.     push    ax            ; look for change of shift state
  1223.     push    cx
  1224.     push    si
  1225.     mov    cl,rptct        ; repeat count
  1226.     xor    ch,ch
  1227.     dec    cx            ; count is one for no repeats
  1228.     sub    si,cx            ; back up over repeated chars
  1229.     mov    cx,4            ; look ahead 4 chars
  1230. encod42:lodsb                ; read ahead
  1231.     and    al,80h            ; pick out high bit
  1232.     cmp    al,ah            ; high bit the same?
  1233.     loope    encod42            ; loop while same
  1234.     pop    si
  1235.     pop    cx
  1236.     pop    ax
  1237.     jne    encod50            ; ne = differ, don't change lock
  1238.                     ; change locking shift state
  1239. encod43:mov    es:[di],dl        ; insert quote char (#)
  1240.     inc    di            ; adjust output buffer pointer
  1241.     dec    cx
  1242.     push    ax
  1243.     mov    ah,shiftstate        ; get current shift state
  1244.     xor    ah,80h            ; toggle shift state
  1245.     mov    shiftstate,ah        ; remember it
  1246.     mov    al,SIchar+40h        ; assume going into unshifted state
  1247.     or    ah,ah            ; to unshifted state now?
  1248.     jz    encod44            ; z = yes, go to unshifted state
  1249.     mov    al,SOchar+40h        ; say go to shifted state
  1250. encod44:stosb                ; put lock char into packet
  1251.     dec    cx
  1252.     pop    ax            ; recover current character
  1253.                     ; end of locking shift tests
  1254. encod50:or    dh,dh            ; doing 8-bit quoting?
  1255.     jz    encod60            ; z = no, forget this
  1256.     cmp    trans.lshift,lock_disable ; locking shift disabled?
  1257.     je    encod57            ; e = yes
  1258.     cmp    ah,shiftstate        ; different than current shift state?
  1259.     jne    encod58            ; ne = yes, specials will be prefixed
  1260.     push    ax            ; save char (stripped of high bit)
  1261.     and    al,7fh            ; consider high bit controls too
  1262.     cmp    al,SIchar        ; SI (Control-O)?
  1263.     je    encod53            ; e = yes
  1264.     cmp    al,SOchar        ; SO (Control-N)?
  1265.     je    encod53            ; e = yes
  1266.     cmp    al,DLE            ; DLE (Control-P)?
  1267.     jne    encod54            ; ne = no
  1268. encod53:mov    al,dl            ; stuff a quote (#)
  1269.     stosb
  1270.     dec    cx
  1271.     mov    al,DLE + 40h        ; then a DLE prefix (P)
  1272.     stosb
  1273.     dec    cx            ; account for it in buffer size
  1274. encod54:pop    ax            ; exit with original char in AL
  1275.     jmp    short encod60        ; no 8-bit prefixing needed here
  1276.  
  1277. encod57:cmp    ah,shiftstate        ; different than current shift state?
  1278.     je    encod60            ; e = no, don't send quoted form
  1279. encod58:cmp    rptct,1            ; doing repeats?
  1280.     jbe    encod59            ; be = no
  1281.     push    ax            ; do repeat prefixing - save data
  1282.     mov    al,trans.rptq        ; insert repeat prefix char
  1283.     stosb
  1284.     dec    cx            ; account for it in buffer size
  1285.     mov    al,rptct        ; get the repeat count
  1286.     add    al,20h            ; make it printable
  1287.     stosb                ; insert into buffer
  1288.     dec    cx
  1289.     pop    ax            ; get back the actual character
  1290. encod59:mov    bl,trans.ebquot        ; get 8-bit quote char
  1291.     mov    es:[di],bl        ; put in packet
  1292.     inc    di
  1293.     dec    cx            ; decrement # of chars left
  1294.     jmp    short encod60b
  1295.                     ; common prefix testing section
  1296. encod60:cmp    rptct,1            ; doing repeats?
  1297.     jbe    encod60b        ; be = no
  1298.     push    ax            ; do repeat prefixing - save data
  1299.     mov    al,trans.rptq        ; insert repeat prefix char
  1300.     stosb
  1301.     dec    cx            ; account for it in buffer size
  1302.     mov    al,rptct        ; get the repeat count
  1303.     add    al,20h            ; make it printable
  1304.     stosb                ; insert into buffer
  1305.     dec    cx
  1306.     pop    ax            ; get back the actual character
  1307.  
  1308. encod60b:and    al,7fh            ; turn off 8th bit in character
  1309.     cmp    al,' '            ; compare to a space
  1310.     jae    encod61            ; ae = not a control code
  1311.     push    bx            ; check for unprefixed selections
  1312.     mov    bl,al            ; as 1=7-bit, 80h=8-bit, 81h=both
  1313.     xor    bh,bh
  1314.     mov    bl,protlist[bx]        ; get 8 and 7 bit encoding rules
  1315.     or    bl,bl            ; anything being excepted from prefix?
  1316.     jz    encod60a        ; z = no
  1317.     test    bl,ah            ; 8-bit unprefixed?
  1318.     jnz    encod60a        ; nz = yes
  1319.     or    ah,ah            ; is it a 7-bit char in reality?
  1320.     jnz    encod60a        ; nz = no
  1321.     and    bl,1            ; text 7 bit unprefixed
  1322. encod60a:pop    bx
  1323.     jz    encod64            ; z = char needs quoting
  1324.     jmp    short encod67        ; store char as-is
  1325. encod61:
  1326.     cmp    al,del            ; delete?
  1327.     je    encod64            ; e = yes, go quote it
  1328.     cmp    al,dl            ; quote char?
  1329.     je    encod65            ; e = yes, go add it
  1330.     or    dh,dh            ; doing 8-bit quoting?
  1331.     jz    encod62            ; z = no, don't translate it
  1332.     cmp    al,trans.ebquot        ; 8-bit quote char?
  1333.     je    encod65            ; e = yes, just output with quote
  1334. encod62:cmp    trans.rptq,0        ; doing repeat prefixing?
  1335.     je    encod67            ; e = no, don't check for quote char
  1336.     cmp    al,trans.rptq        ; repeat quote character?
  1337.     je    encod65            ; e = yes, then quote it
  1338.     jmp    short encod67        ; else don't quote it
  1339.                     ; control code section
  1340. encod64:xor    al,40h            ; control char, uncontrollify
  1341. encod65:mov    es:[di],dl        ; insert control quote char
  1342.     inc    di
  1343.     dec    cx
  1344. encod67:or    al,ah            ; restore high bit, if stripped
  1345.     or    dh,dh            ; doing eight bit quoting?
  1346.     jz    encod68            ; z = no, retain high bit
  1347.     and    al,not 80h        ; strip high bit
  1348. encod68:stosb
  1349.     dec    cx            ; decrement output buffer counter
  1350.     jmp    encod10            ; get fresh input
  1351. encode    endp 
  1352.  
  1353. ; Fill encode source buffer, report KB and percentage done.
  1354. ; Return carry clear for success
  1355. ; modifies ax
  1356. inbuf    proc    near
  1357.     cmp    flags.eoflag,0        ; reached the end?
  1358.     je    inbuf0            ; e = no
  1359.     stc                ; return failure
  1360.     ret
  1361. inbuf0:    push    dx
  1362.     push    bx
  1363.     push    cx
  1364.     mov    bx,diskio.handle    ; get file handle
  1365.     mov    cx,buffsz        ; record size
  1366.     mov    dx,offset buff        ; buffer
  1367.     mov    ebufpnt,dx        ; buffer pointer
  1368.     cmp    trans.xtype,1        ; [HF3] File type binary?
  1369.     je    inbuf0a            ; [HF3] e = yes, no translation
  1370.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1371.     jne    inbuf0a            ; ne = no
  1372.     shr    cx,1            ; allow for double char encoding
  1373.     mov    dx,offset rdbuf        ; use this as source buffer
  1374. inbuf0a:mov    ah,readf2        ; read a record
  1375.     int    dos
  1376.     jnc    inbuf7            ; nc = no error
  1377.     mov    flags.cxzflg,'X'    ; error, set ^X flag
  1378.      jmp    short inbuf1        ; and truncate the file here
  1379. inbuf7:    or    ax,ax            ; any bytes read?
  1380.     jnz    inbuf2            ; nz = yes (the number read)
  1381. inbuf1:    mov    flags.eoflag,1        ; set End-of-File
  1382.     mov    filflg,0        ; buffer empty
  1383.     mov    echrcnt,0        ; zero bytes left in buffer
  1384.     pop    cx
  1385.     pop    bx
  1386.     pop    dx
  1387.     stc                ; failure
  1388.     ret
  1389.  
  1390. inbuf2:    cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1391.     jne    inbuf2a            ; ne = no
  1392.     call    jpnread            ; revise buffer for Japanese
  1393. inbuf2a:add    tfilsz,ax        ; total the # bytes transferred so far
  1394.     adc    tfilsz+2,0        ; it's a double word
  1395.     mov    echrcnt,ax        ; number of chars read from file
  1396.     add    fsta.fsbyte,ax
  1397.     adc    fsta.fsbyte+2,0
  1398.     mov    filflg,1        ; buffer not empty
  1399.     test    flags.remflg,dserial    ; serial display mode?
  1400.     jnz    inbuf3            ; nz = yes, skip kbyte and % display
  1401.     push    si
  1402.     push     ax
  1403.     call    kbpr            ; show kilobytes sent
  1404.     call    perpr            ; show percent sent
  1405.     pop    ax
  1406.     pop    si
  1407.                     ; Character set translation section
  1408. inbuf3:    cmp    trans.xchset,xfr_xparent ; Transparent transfer char set?
  1409.     je    inbuf6            ; e = yes, no translation
  1410.     cmp    trans.xtype,1        ; File Type Binary?
  1411.     je    inbuf6            ; e = yes, no translation
  1412.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1413.     je    inbuf6            ; e = yes, processed already
  1414.     push    ax            ; save buffer count
  1415.     mov    cx,ax            ; loop counter
  1416.     push    si
  1417.     push    di
  1418.     call    cplatin            ; set bx to offset CP to Xfr chr table
  1419.     call    cpinvert        ; check readable vs invertible set
  1420.     mov    si,offset buff        ; scan this buffer
  1421.     push    es
  1422.     mov    di,ds
  1423.     mov    es,di
  1424.     mov    di,si
  1425.     cld
  1426. inbuf4:    lodsb                ; get a char
  1427.     cmp    bx,offset icp437L1    ; invertible CP 437 to Latin1?
  1428.     jne    inbuf4b            ; ne = no
  1429.     mov    ah,al
  1430.     cmp    ah,127            ; special case?
  1431.     jne    inbuf4d            ; ne = no
  1432.     mov    al,26            ; 127 to 26
  1433.     jmp    short inbuf5
  1434. inbuf4d:cmp    al,20            ; range for special cases?
  1435.     jb    inbuf5            ; b = no
  1436.     cmp    al,21
  1437.     ja    inbuf5            ; a = no
  1438.     mov    al,167
  1439.     je    inbuf5            ; 21 to 167
  1440.     mov    al,182
  1441.     jmp    short inbuf5        ; 20 to 182
  1442. inbuf4b:cmp    bx,offset icp850L1    ; invertible CP 850 to Latin1?
  1443.     jne    inbuf4a            ; ne = no
  1444.     cmp    al,28            ; special case?
  1445.     jne    inbuf4c            ; ne = no
  1446.     mov    al,127            ; 28 to 127
  1447.     jmp    short inbuf5
  1448. inbuf4c:cmp    al,127            ; special case?
  1449.     jne    inbuf4a
  1450.     mov    al,26            ; 127 to 26
  1451. inbuf4a:test    al,80h            ; GRight?
  1452.     jz    inbuf5            ; z = no
  1453.     and    al,not 80h        ; strip high bit
  1454.     xlatb                ; translate via bx table
  1455. inbuf5:    stosb                ; store char
  1456.     loop    inbuf4            ; do all concerned
  1457.     pop    es
  1458.     pop    di
  1459.     pop    si
  1460.     pop    ax
  1461. inbuf6:    pop    cx
  1462.     pop    bx
  1463.     pop    dx
  1464.     clc                ; success
  1465.     ret
  1466. inbuf    endp
  1467.  
  1468. ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp)
  1469. ; Read buffer rdbuf to convert from file character set Shift-JIS (Code Page 
  1470. ; 932) to transfer character set Japanese-EUC. Double char translation state
  1471. ; is maintained across file buffers. Init dblbyte to 0 before each new file.
  1472. ; Output is written to buff, with byte count in register AX. The output
  1473. ; could be twice the size of the input. [rewritten by jrd]
  1474. jpnread    proc    near            ; [HF] read Japanese from file
  1475.     push    si
  1476.     push    di
  1477.     push    es
  1478.     mov    cx,ax            ; number of chars in source buffer
  1479.     mov    ax,ds
  1480.     mov    es,ax
  1481.     mov    dl,dblbyteflg        ; get state info from previous call
  1482.     mov    ah,dblbyte        ;  first byte too
  1483.     mov    si,offset rdbuf        ; read from here
  1484.     mov    di,offset buff        ; write to here (avoids overwrites)
  1485.     cld
  1486. jpnrea1:lodsb                ; get a byte
  1487.     or    dl,dl            ; doing first byte?
  1488.     jnz    jpnread3        ; nz = no, second of a pair
  1489.     cmp    al,81h            ; is it Kanji?
  1490.     jb    jpnrea5            ; b = no
  1491.     cmp    al,0fch
  1492.     ja    jpnrea5            ; a = no
  1493.     cmp    al,9fh
  1494.     jbe    jpnrea2            ; be = yes
  1495.     cmp    al,0e0h
  1496.     jb    jpnrea5            ; b = no
  1497. jpnrea2:mov    ah,al            ; AL is first byte of Kanji, save it
  1498.     mov    dl,1            ; say ready to do second byte next
  1499.     jmp    short jpnrea8        ; continue loop
  1500.  
  1501. jpnread3:cmp    al,40h            ; is second byte Kanji?
  1502.     jb    jpnrea6            ; b = no
  1503.     cmp    al,0fch
  1504.     ja    jpnrea6            ; a = no
  1505.     cmp    al,7eh
  1506.     jbe    jpnrea4            ; be = yes
  1507.     cmp    al,80h
  1508.     jb    jpnrea6            ; b = no
  1509. jpnrea4:call    jpnftox            ; convert to xfer char code
  1510.     jmp    short jpnrea6        ; write the pair
  1511.  
  1512. jpnrea5:cmp    al,0a1h            ; Katakana?
  1513.     jb    jpnrea7            ; b = no
  1514.     cmp    al,0dfh
  1515.     ja    jpnrea7            ; a = no
  1516.     mov    ah,8eh            ; set Katakana prefix
  1517. jpnrea6:xchg    ah,al            ; write two bytes
  1518.     stosb                ; store first byte
  1519.     xchg    ah,al            ; get second byte into AL again
  1520. jpnrea7:stosb                ; store a byte
  1521.     xor    dl,dl            ; say all bytes have been written
  1522. jpnrea8:loop    jpnrea1
  1523.     mov    dblbyteflg,dl        ; save state info
  1524.     mov    dblbyte,ah        ; and first char of a pair
  1525.     sub    di,offset buff        ; compute number of bytes written
  1526.     mov    ax,di            ; report new count in AX
  1527.     pop    es
  1528.     pop    di
  1529.     pop    si
  1530.     ret
  1531. jpnread    endp
  1532.  
  1533. ; File character code (Shift-JIS) to xfer character code (EUC) converter.
  1534. ; From Shift-JIS to EUC
  1535. ;   if( code1 <= 0x9f )
  1536. ;     code1 -= 0x71;
  1537. ;   else
  1538. ;     code1 -= 0xb1;
  1539. ;   code1 = code1 * 2 + 1;
  1540. ;   if( code2 > 0x7f ) code2 -= 1;
  1541. ;   if( code2 >= 0x9e ){
  1542. ;     code2 -= 0x7d;
  1543. ;     code1 += 1;
  1544. ;   } else
  1545. ;     code2 -= 0x1f;
  1546. ;   EUC_code1 = (code1 | 0x80);
  1547. ;   EUC_code2 = (code2 | 0x80);
  1548. ;   [ fputc( EUC_code1, packet ); fputc( EUC_code2, packet ); ]
  1549. ;
  1550. jpnftox    proc    near
  1551.     cmp    ah,9fh
  1552.     ja    jpnftox1
  1553.     sub    ah,71h
  1554.     jmp    short jpnftox2
  1555. jpnftox1:sub    ah,0b1h
  1556. jpnftox2:shl    ah,1
  1557.     inc    ah
  1558.     cmp    al,7fh
  1559.     jbe    jpnftox3
  1560.     dec    al
  1561. jpnftox3:cmp    al,9eh
  1562.     jb    jpnftox4
  1563.     sub    al,7dh
  1564.     inc    ah
  1565.     jmp    jpnftox5
  1566. jpnftox4:sub    al,1fh
  1567. jpnftox5:or    ax,8080h
  1568.     ret
  1569. jpnftox    endp
  1570.  
  1571. ; GETFIL, called only by send code
  1572. ; Enter with raw filename pattern in diskio.string
  1573. ; Returns carry clear if success, else carry set
  1574. getfil    proc    near
  1575.     mov    dblbyteflg,0        ; clear encoder state variable
  1576.     mov    shiftstate,0        ; locking shift state
  1577.     mov    DLEseen,0        ; escape state
  1578.     mov    filflg,0        ; say nothing is in the buffer
  1579.     mov    flags.eoflag,0        ; not the end of file
  1580.     mov    dx,offset diskio.dta    ; data transfer address
  1581.     mov    ah,setdma        ; set disk transfer address
  1582.     int    dos
  1583.     xor    cx,cx            ; attributes: find only normal files
  1584.     mov    dx,offset diskio.string ; filename string (may have wild cards)
  1585.     mov    ah,first2        ; DOS 2.0 search for first
  1586.     int    dos            ; get file's characteristics
  1587.     pushf                ; save c flag
  1588.     mov    ah,setdma        ; reset dta address
  1589.     mov    dx,offset buff        ; restore dta
  1590.     int    dos
  1591.     popf                ; restore status of search for first
  1592.     jnc    getfi1            ; nc = ok so far
  1593.     ret                ; else take error exit
  1594. getfi1:    jmp    getfcom            ; do common code
  1595. getfil    endp
  1596.  
  1597.  
  1598. ; GTNFIL called by send code to get next file.
  1599. ; Returns carry clear for success, carry set for failure.
  1600. gtnfil    proc    near
  1601.     mov    dblbyteflg,0        ; clear encoder state variable
  1602.     mov    shiftstate,0        ; locking shift state
  1603.     mov    DLEseen,0        ; escape state
  1604.     cmp    flags.cxzflg,'Z'    ; Did we have a ^Z?
  1605.     jne    gtnfi1            ; ne = no, else done sending files
  1606.     stc                ; carry set for failure
  1607.     ret                ; take failure exit
  1608.  
  1609. gtnfi1:    xor    al,al
  1610.     mov    filflg,al        ; nothing in the DMA
  1611.     mov    flags.eoflag,al        ; not the end of file
  1612.     mov    dx,offset diskio.dta    ; point at dta
  1613.     mov    ah,setdma        ; set the dta address
  1614.     int    dos
  1615.     mov    ah,next2        ; DOS 2.0 search for next
  1616.     int    dos
  1617.     pushf                ; save carry flag
  1618.     mov    ah,setdma        ; restore dta
  1619.     mov    dx,offset buff
  1620.     int    dos
  1621.     popf                ; recover carry flag
  1622.     jnc    getfcom            ; nc = success, do common code
  1623.     ret                ; carry    set means no more files found
  1624. gtnfil    endp
  1625.                     ; worker for getfil, gtnfil
  1626. getfcom    proc    near
  1627.     push    si
  1628.     push    di
  1629.     mov    dx,offset diskio.string    ; original file spec (may be wild)
  1630.     mov    di,offset templp    ; place for path part
  1631.     mov    si,offset templf    ; place for filename part
  1632.     call    fparse            ; split them
  1633.     mov    si,offset diskio.fname    ; current filename from DOS
  1634.     call    strcat            ; (di)= local path + diskio.fname
  1635.     mov    di,offset encbuf    ; name to send to host (no path)
  1636.     call    strcpy              ; new string = old path + DOS's filename
  1637.     push    bx
  1638.     push    cx
  1639.     test    flags.remflg,dquiet    ; quiet display?
  1640.     jnz    getfco1            ; e = yes, do not display filename
  1641.     call    clrfln            ; position cursor & blank out the line
  1642.     mov    dx,offset templp
  1643.     call    prtasz
  1644. getfco1:call    newfn            ; update encbuf with "send as" name
  1645.     pop    cx
  1646.     pop    bx
  1647.     mov    ah,open2        ; file open
  1648.     xor    al,al            ; 0 = open readonly
  1649.     cmp    dosnum,300h        ; at or above DOS 3?
  1650.     jb    getfco2            ; b = no, so no shared access
  1651.     or    al,40h            ; open readonly, deny none
  1652. getfco2:mov    dx,offset templp    ; filename string with path
  1653.     int    dos
  1654.     jc    getfco3            ; c = failed to open the file
  1655.     mov    diskio.handle,ax    ; save file handle
  1656.     xor    ax,ax
  1657.     mov    tfilsz,ax        ; set bytes sent to zero
  1658.     mov    tfilsz+2,ax
  1659.     mov    ax,-1            ; get a minus one
  1660.     mov    oldkbt,ax
  1661.     mov    oldper,ax
  1662.     clc                ; carry clear for success
  1663. getfco3:pop    si
  1664.     pop    di
  1665.     ret
  1666. getfcom    endp
  1667.  
  1668. ; Get the file name from the data portion of the F packet or from locally
  1669. ; specified override filename (in auxfile), displays the filename, does any
  1670. ; manipulation of the filename necessary, including changing the name to
  1671. ; prevent collisions. Returns carry clear for success. Failures return
  1672. ; carry set with dx pointing at error message text.
  1673. ; Called by file receive module in mssrcv.asm.
  1674.  
  1675. gofil    proc    near
  1676.     mov    si,offset decbuf    ; filename in packet
  1677.     mov    di,offset diskio.string    ; place where prtfn finds name
  1678.     call    strcpy            ; copy pkt filename to diskio.string
  1679.     mov    di,offset fsta.xname    ; statistics external filespec area
  1680.     call    strcpy            ; record external name
  1681.     cmp    auxfile,0        ; have override name?
  1682.     jne    gofil1            ; ne = yes
  1683.     cmp    flags.xflg,0        ; receiving to screen?
  1684.     jne    gofil0a            ; ne = yes, filename becomes CON
  1685.     cmp    flags.destflg,1        ; destination is disk?
  1686.     je    gofil1            ; e = yes
  1687.     mov    di,offset printer    ; assume PRN is local file name
  1688.     jb    gofil0b            ; b = yes
  1689. gofil0a:mov    di,offset screen    ; use CON (screen) as local file name
  1690.     mov    flags.xflg,1        ; say receiving to screen
  1691. gofil0b:xchg    di,si            ; di --> decbuf, si --> file name
  1692.     call    strcpy            ; put local name (si) into decbuf
  1693.     mov    nmoflg,1        ; say that we have a replacement name
  1694.     jmp    gofil9            ; final filename is now in 'decbuf'
  1695.  
  1696. gofil1:    xor    ax,ax
  1697.     mov    nmoflg,al        ; assume no override name
  1698.     cmp    auxfile,al        ; overriding name from other side?
  1699.     jne    gofi1e            ; ne = yes
  1700.     jmp    gofil4            ; e = no, get the other end's filename
  1701. gofi1e:    mov    nmoflg,1        ; say using an override name
  1702.     mov    ax,offset auxfile    ; get local override filename
  1703.     cmp    word ptr auxfile+1,003ah; colon+null?(primative drive spec A:)
  1704.     je    gofil3        ; e = yes, skip screwy DOS response (No Path)
  1705.     cmp    word ptr auxfile,'..'    ; parent directory?
  1706.     jne    gofi1g            ; ne = no
  1707.     cmp    word ptr auxfile+1,002eh ; dot dot + null?
  1708.     je    gofi1b            ; e = yes, process as directory
  1709. gofi1g:    cmp    word ptr auxfile,002eh    ; dot + null (current dir)?
  1710.     je    gofi1b            ; e = yes, process as directory
  1711.     call    isfile            ; does it exist?
  1712.     jnc    gofi1f            ; nc = file exists
  1713.     test    filtst.fstat,80h    ; serious error?
  1714.     jz    gofil3            ; z = no, just no such file
  1715.     jmp    gofi18a            ; else quit here
  1716. gofi1f:    test    byte ptr filtst.dta+21,10H ; subdirectory name?
  1717.     jnz    gofi1b            ; nz = yes
  1718.     cmp    filtst.fname,2eh    ; directory name?
  1719.     je    gofi1b            ; e = yes, process as directory
  1720.     cmp    auxfile+2,5ch        ; a root directory like b:\?
  1721.     jne    gofi1d            ; ne = no. (DOS is not helpful with roots)
  1722.     cmp    auxfile+3,0        ; and is it terminated in a null?
  1723.     je    gofi1b            ; e = yes, so it is a root spec
  1724. gofi1d:    test    byte ptr filtst.dta+21,0fh   ; r/o, hidden, system, vol label?
  1725.     jz    gofil3            ; z = no
  1726.      jmp    gofi18a               ; yes. Complain and don't transfer file
  1727. gofi1b:    mov    dx,offset auxfile    ; auxfile is a (sub)directory name
  1728.     call    strlen            ; get its length w/o terminator
  1729.     jcxz    gofil2            ; zero length
  1730.     dec    cx            ; examine last char
  1731.     push    bx            ; save bx
  1732.     mov    bx,cx
  1733.     add    bx,dx
  1734.     cmp    byte ptr [bx],5ch    ; ends in backslash?
  1735.     je    gofil2            ; e = yes
  1736.     cmp    byte ptr [bx],2fh    ; maybe forward slash?
  1737.     je    gofil2            ; e = yes
  1738.     mov    byte ptr [bx + 1],5ch    ; no slash yet. use backslash
  1739.     mov    byte ptr [bx + 2],0    ; plant new terminator
  1740. gofil2:    pop    bx
  1741.  
  1742. gofil3:    mov    di,offset templp    ; local path
  1743.     mov    si,offset templf    ; local filename
  1744.     mov    dx,offset auxfile    ; local string
  1745.     call    fparse            ; split local string
  1746.     mov    di,offset temprp    ; remote path
  1747.     mov    si,offset temprf    ; remote file
  1748.     mov    dx,offset decbuf    ; remote string
  1749.     mov    decbuf+64,0        ; force filename to be <= 64 chars
  1750.     call    fparse            ; split remote string
  1751.     test    flags.remflg,dserver    ; running in Server mode?
  1752.     jz    gofi3c            ; z = no
  1753.     test    denyflg,sndflg        ; is Deny Send mode in operation?
  1754.     jz    gofi3c            ; z = no
  1755.     mov    temprp,0        ; DENY, means remove remote path
  1756. gofi3c:    mov    si,offset templp    ; copy local path to
  1757.     mov    di,offset decbuf    ;  final filename
  1758.     call    strcpy            ; do the copy
  1759.     mov    si,offset templf    ; assume using local file name
  1760.     cmp    byte ptr templf,0    ; local file name given?
  1761.     jne    gofi3b            ; ne = yes
  1762.     mov    si,offset temprf    ; else use remote file name
  1763. gofi3b:    call    strcat            ; append path and filename again
  1764.                     ; offset decbuf holds the new filename
  1765.                     ;
  1766.                 ; recheck legality of filename in 'decbuf'
  1767. gofil4:    mov    decbuf+64,0        ; guard against long filenames
  1768.     mov    di,offset temprp    ; remote path
  1769.     mov    si,offset temprf    ; remote file
  1770.     mov    dx,offset decbuf    ; remote string
  1771.     call    strlen            ; get original size
  1772.     push    cx            ; remember it
  1773.     call    fparse            ; further massage filename
  1774.     push    si            ; put pieces back together
  1775.     call    verfil            ; verify each char in temprf string
  1776.     mov    si,di            ; get path part first
  1777.     mov    di,dx            ; set destination
  1778.     call    strcpy            ; copy in path part
  1779.     pop    si            ; recover (new) filename
  1780.     cmp    byte ptr [si],'.'    ; does filename part start with a dot?
  1781.     jne    gofil5            ; ne = no
  1782.     push    di            ; save regs
  1783.     push    si
  1784.     mov    di,offset rdbuf        ; a work area
  1785.     mov    byte ptr [di],'X'    ; start name with letter X
  1786.     inc    di
  1787.     call    strcpy            ; copy rest of filename
  1788.     mov    di,si
  1789.     mov    si,offset rdbuf      ; copy new name back to original location
  1790.     call    strcpy
  1791.     pop    si            ; restore regs
  1792.     pop    di    
  1793. gofil5:    call    strcat            ; append it
  1794.     call    strlen            ; see if we chopped out something
  1795.     pop    si            ; get original length (from push cx above)
  1796.     cmp    cx,si            ; same size?
  1797.     je    gofil9            ; e = yes
  1798.     mov    nmoflg,1        ; say that we have a replacement name
  1799.                 ; filename is now in 'decbuf', all converted
  1800. gofil9:    test    flags.remflg,dquiet    ; quiet display mode?
  1801.     jnz    gofi10            ; nz = yes, don't print it
  1802.     test    flags.remflg,dserial    ; serial display mode?
  1803.     jz    gofi9a            ; z = no
  1804.     mov    ah,prstr
  1805.     mov    dx,offset crlf        ; display cr/lf
  1806.     int    dos
  1807. gofi9a:    call    prtfn            ; show packet filename
  1808.     cmp    nmoflg,0        ; using local override name?
  1809.     je    gofil9b            ; e = no
  1810.     cmp    flags.xflg,0        ; receiving to screen? (X versus F)
  1811.     jne    gofil9b            ; ne = yes
  1812.     mov    ah,prstr
  1813.     mov    dx,offset asmsg        ; print " as "
  1814.     int    dos
  1815.     mov    dx,offset decbuf    ; plus the local filename
  1816.     call    prtasz            ; print asciiz string
  1817. gofil9b:mov    ah,flags.remflg        ; display a following cr/lf?
  1818.     and    ah,dserial        ; for serial display mode
  1819.     or    ah,flags.xflg        ; receiving to screen
  1820.     jz    gofi10            ; z = neither, no cr/lf
  1821.     mov    ah,prstr        ; finish the line with cr/lf
  1822.     mov    dx,offset crlf
  1823.     int    dos
  1824. gofi10:    mov    ax,offset decbuf    ; point to name
  1825.     cmp    flags.flwflg,1        ; overwrite existing file?
  1826.     jne    gofi10b            ; ne = no
  1827.     jmp    gofi16            ; e = yes
  1828. gofi10b:call    isfile            ; does it exist?
  1829.     mov    ax,offset decbuf    ; reload ptr in case
  1830.     jc    gofi16            ; carry set = no, just proceed
  1831.     mov    ah,open2        ; could it be a device name?
  1832.     xor    al,al            ; open readonly
  1833.     cmp    dosnum,300h        ; above DOS 2?
  1834.     jb    gofi10a            ; b = no, so no shared access
  1835.     or    al,40h            ; open for reading, deny none
  1836. gofi10a:mov    dx,offset decbuf    ; the filename
  1837.     int    dos
  1838.     jc    gofi11            ; c = cannot open so just proceed
  1839.     mov    bx,ax            ; file handle
  1840.     mov    ah,ioctl
  1841.     xor    al,al            ; 0 = get info
  1842.     int    dos
  1843.     mov    ah,close2        ; close it
  1844.     int    dos
  1845.     mov    ax,offset decbuf    ; point to filename again
  1846.     test    dl,80h            ; ISDEV bit set?
  1847.     jz    gofi11            ; z = no, not a device
  1848.     jmp    gofi16            ; device, use name as given
  1849. gofi11:    cmp    flags.flwflg,4        ; no-supersede existing file?
  1850.     jne    gofi12            ; ne = no (i.e., do a rename)
  1851.     mov    flags.cxzflg,'X'    ; say stop this file
  1852.     mov    word ptr decbuf,'UN'
  1853.     mov    decbuf+2,'L'        ; file name of NUL
  1854.     mov    decbuf+3,0        ; asciiz
  1855.     jmp    short gofi13
  1856. gofi12:    mov    ax,offset decbuf    ; point to filename again
  1857.     call    unique            ; generate unique name
  1858.     jc    gofi14            ; could not generate a unique name
  1859.     test    flags.remflg,dquiet    ; quiet display mode?
  1860.     jnz    gofi13            ; nz = yes, skip printing
  1861.     push    ax            ; save unique name again
  1862.     call    frpos            ; position cursor
  1863.     mov    ah,prstr           ; say we are renaming the file
  1864.     mov    dx,offset infms5
  1865.     int    dos
  1866.     pop    ax            ; get name back into ax again
  1867.     push    ax            ; save around these calls
  1868.     mov    dx,ax            ; print current filename
  1869.     call    prtasz            ; display filename
  1870.     pop    ax            ; pointer to name, again
  1871. gofi13:    jmp    short gofi16        ; and go handle file
  1872.  
  1873. gofi14:    mov    dx,offset ermes4
  1874.     call    ermsg
  1875.     stc                ; failure, dx has msg pointer
  1876.     ret
  1877.  
  1878. gofi16:    mov    si,ax             ; pointer to (maybe new) name
  1879.     mov    di,offset diskio.string    ; filename, used in open
  1880.     mov    dx,di            ;  for isfile and open below
  1881.     call    strcpy             ; copy name to diskio.string
  1882.     xor    ax,ax
  1883.     mov    diskio.sizehi,ax    ; original file size is unknown
  1884.     mov    diskio.sizelo,ax    ; double word
  1885.     mov    tfilsz,ax        ; set bytes received to zero
  1886.     mov    tfilsz+2,ax
  1887.     mov    ax,-1            ; get a minus one
  1888.     mov    oldkbt,ax
  1889.     mov    oldper,ax
  1890.     clc                ; finished composing filename
  1891.     ret                ; in diskio.string
  1892.                     ; Come here to formally open the file
  1893.  
  1894. gofi18a:mov    si,ax             ; pointer to local override name
  1895.     mov    di,offset diskio.string    ; filename, used in open
  1896.     call    strcpy             ; copy name to diskio.string
  1897.                     ; fall    through to gofi18
  1898. gofi18:    test    flags.remflg,dquiet    ; quiet display mode?
  1899.     jnz    gofi19            ; nz = yes, don't try printing
  1900.     mov    dx,offset erms12    ; unable to create file
  1901.     call    ermsg
  1902.     push    dx
  1903.     mov    dx,offset diskio.string    ; print offending name
  1904.     call    prtasz            ; display filename
  1905.     pop    dx
  1906. gofi19:    stc                ; failure, dx has msg pointer
  1907.     ret
  1908. gofil    endp
  1909.  
  1910. ; Open file for writing with name in diskio.string
  1911. goopen    proc    near
  1912.     mov    dblbyteflg,0        ; clear decoder state variable
  1913.     mov    shiftstate,0        ; locking shift state
  1914.     mov    DLEseen,0        ; escape state
  1915.     mov    dx,offset diskio.string    ; filename, asciiz
  1916.     mov    diskio.handle,0        ; clear handle of previous usage
  1917.     mov    ax,dx            ; filename for isfile
  1918.     call    isfile        ; check for read-only/system/vol-label/dir
  1919.     jc    goopen1            ; c = file does not exist
  1920.     test    byte ptr filtst.dta+21,1fh    ; the no-no file attributes
  1921.     jnz    gofi18            ; nz = do not write over one of these
  1922. goopen1:test    filtst.fstat,80h    ; access problem?
  1923.     jnz    gofi18            ; nz = yes, quit here
  1924.     mov    diskio.handle,-1    ; clear handle of previous usage
  1925.     mov    ah,creat2        ; create file
  1926.     xor    cx,cx            ; 0 = attributes bits
  1927.     int    dos
  1928.     jc    goopen2            ; c = did not work, try regular open
  1929.     mov    diskio.handle,ax    ; save file handle here
  1930.     clc                ; carry clear for success
  1931.     ret
  1932. goopen2:test    byte ptr filtst.dta+21,1bh    ; r/o, hidden, volume label?
  1933.     jnz    gofi18            ; we won't touch these
  1934.     mov    ah,open2           ; open existing file (usually a device)
  1935.     mov    al,1+1            ; open for writing
  1936.     int    dos
  1937.     jc    gofi18            ; carry set means can't open
  1938.     mov    diskio.handle,ax    ; file handle
  1939.     clc                ; carry clear for success
  1940.     ret
  1941. goopen    endp
  1942.  
  1943. ; Given incoming filename in 'decbuf'.  Verify that each char is legal
  1944. ; (if not change it to an "X"), force max of three chars after a period (dot)
  1945. ; Source is at ds:si (si is changed here).
  1946.  
  1947. VERFIL    PROC    NEAR
  1948.     push    es            ; verify each char in 'data'
  1949.     push    cx
  1950.     push    ds
  1951.     pop    es
  1952.     mov    havdot,0        ; say no dot found in name yet
  1953.     cld
  1954. verfi1:    lodsb                ; get a byte of name from si
  1955.     and    al,7fH            ; strip any eighth bit
  1956.     jz    verfi5            ; z = end of name
  1957.     cmp    al,'.'            ; a dot?
  1958.     jne    verfi2            ; ne = no
  1959.     cmp    havdot,0        ; have one dot already?
  1960.     jne    verfi3            ; ne = yes, change to X
  1961.     mov    byte ptr [si+3],0    ; forceably end filename after 3 char ext
  1962.     mov    havdot,1        ; say have a dot now
  1963.     jmp    short verfi4        ; continue
  1964. verfi2:    cmp    al,3ah            ; colon?
  1965.     je    verfi4
  1966.     cmp    al,5ch            ; backslash path separator?
  1967.     je    verfi4
  1968.     cmp    al,2fh            ; or forward slash?
  1969.     je    verfi4
  1970.     cmp    al,'0'
  1971.     jb    verfi3            ; see if it's a legal char < '0'
  1972.     cmp    al,'9'
  1973.     jbe    verfi4            ; it's between 0-9 so it's OK
  1974.     cmp    al,'A'
  1975.     jb    verfi3            ; check for a legal punctuation char
  1976.     cmp    al,'Z'
  1977.     jbe    verfi4            ; it's A-Z so it's OK
  1978.     cmp    al,'a'
  1979.     jb    verfi3            ; check for a legal punctuation char
  1980.     cmp    al,'z'
  1981.     ja    verfi3
  1982.     and    al,5FH            ; it's a-z, capitalize
  1983.     jmp    short verfi4        ; continue with no change
  1984.  
  1985. verfi3:    push    di            ; special char. Is it on the list?
  1986.     mov    di,offset spchar2    ; list of acceptable special chars
  1987.     mov    cx,spc2len
  1988.     cld
  1989.     repne    scasb            ; search string for input char
  1990.     pop    di
  1991.     je    verfi4            ; e = in table, return it
  1992.     mov    al,'X'            ; else illegal, replace with "X"
  1993.     mov    nmoflg,1        ; say we have a replacement filename
  1994. verfi4:    mov    [si-1],al        ; update name
  1995.     jmp    short verfi1        ; loop thru rest of name
  1996. verfi5:    mov    byte ptr[si-1],0    ; make sure it's null terminated
  1997.     pop    cx
  1998.     pop    es
  1999.     ret
  2000. VERFIL    ENDP
  2001.  
  2002. ; find a unique filename.
  2003. ; Enter with a pointer to a (null-terminated) filename in ax
  2004. ; Return with same pointer but with a new name (or old if failure)
  2005. ; Success = carry clear; failure = carry set
  2006. ; The idea is to pad out the main name part (8 chars) with ascii zeros and
  2007. ; then change the last chars successively to a 1, 2, etc. until
  2008. ; a unique name is found. All registers are preserved
  2009. ; Make empty main name fields start with letter X, not digit 0
  2010. unique    proc    near
  2011.     push    bx
  2012.     push    cx
  2013.     push    dx
  2014.     push    si
  2015.     push    di
  2016.     push    es
  2017.     push    ax            ; save address of source string
  2018.     mov    dx,ds            ; make es use ds segment
  2019.     mov    es,dx
  2020.     mov    dx,ax            ; point at original filename string
  2021.     mov    di,offset templp    ; place for path
  2022.     mov    si,offset templf    ; place for filename
  2023.     call    fparse            ; separate path (di) and filename (si)
  2024.     mov    dx,di            ; point at path part
  2025.     call    strlen            ; put length in cx
  2026.     mov    si,ax            ; point to original string
  2027.     add    si,cx            ; point to filename part
  2028.     mov    di,offset templf    ; destination is temporary location
  2029.     xor    cx,cx            ; a counter
  2030.     cld                ; set direction to be forward
  2031. uniq1:    lodsb                ; get a byte
  2032.     cmp    al,'.'            ; have a dot?
  2033.     je    uniq2            ; e = yes
  2034.     or    al,al            ; maybe    null at end?
  2035.     jnz    uniq3            ; nz = no, continue loop
  2036.  
  2037. uniq2:    cmp    cl,8            ; have we copied any chars before dot?
  2038.     jge    uniq3            ; ge = all 8
  2039.     mov    byte ptr [di],'0'    ; avoid clobbers; pad with 0's
  2040.     or    cl,cl            ; first char of filename?
  2041.     jnz    uniq2a            ; nz = no
  2042.     mov    byte ptr [di],'X'    ; start name with letter X, not 0
  2043. uniq2a:    inc    di            ; and count the output chars
  2044.     inc    cl            ; and this counter too
  2045.     jmp    short uniq2        ; continue until filled 8 slots
  2046. uniq3:    inc    cl            ; cl = # char in destination
  2047.     stosb                ; store the char
  2048.     or    al,al            ; null at end?
  2049.     jnz    uniq1            ; nz = no, continue copying
  2050.  
  2051.     mov    templf+7,'1'        ; put '1' in last name char
  2052.     mov    unum,1            ; start with this generation digit
  2053.  
  2054. uniq4:    mov    di,offset rdbuf        ; build a temporary full filename
  2055.     mov    si,offset templp    ; path part
  2056.     call    strcpy            ; copy that much
  2057.     mov    si,offset templf    ; get rebuilt filename part
  2058.     call    strcat            ; paste that to the end
  2059.     mov    ax,offset rdbuf        ; point to full name
  2060.     call    isfile            ; does it exist?
  2061.     jc    uniq6            ; c = no, succeed now
  2062.  
  2063.     inc    unum            ; move to next generation
  2064.     mov    di,offset templf+7    ; point to last name char
  2065.     mov    cx,7            ; max # of digits to play with
  2066.     mov    bx,10            ; divisor (16 bits)
  2067.     mov    ax,unum            ; low order part of generation #
  2068. uniq5:    xor    dx,dx            ; high order part of generation #
  2069.     div    bx            ; compute digit (unum / 10)
  2070.     add    dl,'0'            ; make remainder part printable
  2071.     mov    [di],dl            ; put into right place
  2072.     or    ax,ax            ; any more to do? (quotient nonzero)
  2073.     jz    uniq4            ; z = no, try this name
  2074.     dec    di            ; else decrement char position
  2075.     loop    uniq5            ;   and keep making a number
  2076.     stc                ; failure: set carry, keep old name
  2077.     jmp    short uniq7        ;   and exit
  2078.  
  2079. uniq6:    pop    di            ; address of original filename
  2080.     push    ax            ; save for exit clean up
  2081.     mov    si,offset rdbuf
  2082.     call    strcpy            ; copy new filename over old
  2083.     clc                ; success: clear carry flag
  2084. uniq7:    pop    ax
  2085.     pop    es
  2086.     pop    di
  2087.     pop    si
  2088.     pop    dx
  2089.     pop    cx
  2090.     pop    bx
  2091.     ret
  2092. unique    endp
  2093.     
  2094.  
  2095. ; strlen -- computes the length, excluding the terminator, of an asciiz
  2096. ;    string. Input: ds:dx = address of the string
  2097. ;        Output: cx = the byte count
  2098. ;    All registers except cx are preserved
  2099. ;
  2100. STRLEN    PROC    NEAR
  2101.     push    di
  2102.     push    es
  2103.     push    ax
  2104.     mov    ax,ds            ; use proper segment address
  2105.     mov    es,ax
  2106.     mov    di,dx
  2107.     mov    cx,0ffffh        ; large byte count
  2108.     cld                ; set direction to be forward
  2109.     xor    al,al            ; item sought is a null
  2110.     repne    scasb            ; search for it
  2111.     add    cx,2            ; add for -1 and auto dec in scasb
  2112.     neg    cx              ; convert to count, excluding terminator
  2113.     pop    ax
  2114.     pop    es
  2115.     pop    di
  2116.     ret
  2117. STRLEN    ENDP
  2118.  
  2119. ; strcat -- concatenates asciiz string 2 to the end of asciiz string 1
  2120. ;    offset of string 1 is expected to be in ds:di. input & output
  2121. ;    offset of string 2 is expected to be in ds:si. input only (unchanged)
  2122. ;    Preserves all registers. No error returns, returns normally via ret
  2123. ;
  2124. STRCAT    PROC    NEAR
  2125.     push    di            ; save work registers
  2126.     push    si
  2127.     push    es
  2128.     push    dx
  2129.     push    cx
  2130.     push    ax
  2131.     mov    ax,ds            ; get data segment value
  2132.     mov    es,ax            ; set es to ds for implied es:di usage
  2133.     mov    dx,di
  2134.     call    strlen        ; get length (w/o terminator) of dest string
  2135.     add    di,cx            ; address of first terminator
  2136.     mov    dx,si            ; start offset of source string
  2137.     call    strlen            ; find its length too (in cx)
  2138.     inc    cx            ; include its terminator in the count
  2139.     cld
  2140.     rep    movsb        ; copy source string to end of output string
  2141.     pop    ax
  2142.     pop    cx
  2143.     pop    dx
  2144.     pop    es
  2145.     pop    si
  2146.     pop    di
  2147.     ret
  2148. STRCAT    ENDP
  2149.  
  2150. ; strcpy -- copies asciiz string pointed to by ds:si into area pointed to by
  2151. ;    ds:di. Returns via ret. All registers are preserved
  2152. ;
  2153. STRCPY    PROC    NEAR
  2154.     cmp    si,di            ; same place?
  2155.     jne    strcpy1            ; ne = no
  2156.     ret                ; having done nothing
  2157. strcpy1:mov    byte ptr [di],0        ; clear destination string
  2158.     call    strcat            ; let strcat do the real work
  2159.     ret
  2160. STRCPY    ENDP
  2161.  
  2162. ; fparse -- separate the drive:path part from the filename.ext part of an
  2163. ;    asciiz string. Characters separating parts are  \ or / or :
  2164. ;    Inputs:    asciiz input full filename string offset in ds:dx
  2165. ;        asciiz path offset in ds:di
  2166. ;        asciiz filename offset in ds:si
  2167. ;    Outputs: the above strings in the indicated spots
  2168. ;    Strategy is simple. Reverse scan input string until one of the
  2169. ;    three separators is encountered and then cleave at that point
  2170. ;    Simple filename construction restrictions added 30 Dec 1985;
  2171. ;    to wit: mainname limited to 8 chars or less,
  2172. ;    extension field limited to 3 chars or less and is found by searching
  2173. ;    for first occurence of a dot in the filename field. Thus the whole
  2174. ;    filename part is restricted to 12 (8+dot+3) chars plus a null
  2175. ;    All registers are preserved. Return is always via ret
  2176. ;    (Microsoft should have written this for DOS 2.x et seq.)
  2177.  
  2178. FPARSE    PROC    NEAR
  2179.     push    cx            ; local counter
  2180.     push    ax            ; local work area
  2181.     push    es            ; implied segment register for di
  2182.     push    di            ; offset of path part of output
  2183.     push    si            ; offset of file name part of output
  2184.     mov    ax,ds            ; get data segment value
  2185.     mov    es,ax            ; set es to ds for implied es:di usage
  2186.     mov    byte ptr [si],0        ; clear outputs
  2187.     mov    byte ptr [di],0
  2188.  
  2189.     push    si            ; save original file name address
  2190.     mov    si,dx            ; get original string address
  2191.     call    strcpy            ; copy string to original di
  2192.     call    strlen            ; find length (w/o terminator), in cx
  2193.     mov    si,di            ; address of string start
  2194.     add    si,cx
  2195.     dec    si            ; si = address of last non-null char
  2196.     jcxz    fpars5            ; if null skip the path scan
  2197.                     ; now find last path char, if any
  2198.                     ; start at the end of input string
  2199.     std                 ; set direction to be backward
  2200. fpars4:    lodsb                 ; get a byte (dec's si afterward)
  2201.     cmp    al,5ch            ; is it a backslash ('\')? 
  2202.     je    fpars6          ; e = yes
  2203.     cmp    al,2fh            ; or forward slash ('/')?
  2204.     je    fpars6          ; e = yes
  2205.     cmp    al,3ah            ; or even the drive terminator colon?
  2206.     je    fpars6            ; e = yes
  2207.     loop    fpars4             ; else keep looking until cx == 0
  2208.                       ; si is at beginning of file name
  2209. fpars5:    dec    si            ; dec for inc below
  2210. fpars6:    inc    si
  2211.     inc    si            ; si now points at first filename char
  2212.                     ; cx holds number of path chars
  2213.                     ; get original file name address (si)
  2214.     pop    di            ; and make it place to copy filename
  2215.     cld                ; reset direction to be forward
  2216.     mov    ax,si            ; ax holds filename address for awhile
  2217.     push    dx
  2218.     mov    dx,si            ; strlen wants string pointer in dx
  2219.     call    strlen            ; get length of filename part into cx
  2220.     pop    dx
  2221.     jcxz    fpar7a            ; any chars to look at? z = no
  2222. fpars7:    cmp    byte ptr [si],'.'    ; look for a dot in filename
  2223.     je    fpars8            ; e = found one
  2224.     inc    si            ; look at next filename char
  2225.     loop    fpars7            ; keep looking until cx = zero
  2226. fpar7a:    mov    si,ax            ; no dot. recover starting address
  2227.     mov    byte ptr [si+8],0    ; forcably truncate mainname to 8 char
  2228.     call    strcpy            ; copy this part to filename field
  2229.     jmp    short fparsx        ;  and exit
  2230. fpars8: mov    byte ptr [si+4],0   ; plant terminator after dot + 3 ext chars
  2231.     mov    cx,si
  2232.     sub    cx,ax        ; cx now = number of chars in mainname field
  2233.     cmp    cx,9            ; more than 8?
  2234.     jb    fpars9            ; b = no, we're safe
  2235.     mov    cx,8             ; limit ourselves to 8 chars in mainname
  2236. fpars9: push    si             ; remember address of dot and extension
  2237.     mov    si,ax            ; point to start of input filename
  2238.     rep    movsb            ; copy cx chars from si to di (output)
  2239.     mov    byte ptr [di],0        ; plant terminator where dot goes
  2240.     pop    si            ; source = dot and extension address
  2241.     call    strcat        ; append the dot & ext to the filename field
  2242. fparsx: mov    si,ax        ; recover start of filename in input string
  2243.     mov    byte ptr [si],0        ; terminate path field
  2244.     pop    si
  2245.     pop    di
  2246.     pop    es
  2247.     pop    ax
  2248.     pop    cx
  2249.     ret
  2250. FPARSE    ENDP    
  2251.  
  2252. ; Print filename in offset diskio.string.
  2253. PRTFN    PROC    NEAR
  2254.     test    flags.remflg,dquiet    ; quiet display mode?
  2255.     jnz    prtfn1            ; nz = yes, don't display filename
  2256.     push    ax            ; saves for messy clrfln routine
  2257.     push    bx
  2258.     push    dx
  2259.     call    clrfln            ; position cursor & blank out the line
  2260.     mov    dx,offset diskio.string
  2261.     call    prtasz
  2262.     pop    dx
  2263.     pop    bx
  2264.     pop    ax
  2265. prtfn1:    ret
  2266. PRTFN    ENDP
  2267.  
  2268.  
  2269. ; Print string to screen from offset ds:di for # bytes given in cx,
  2270. ; regardless of $'s.  All registers are preserved.
  2271.  
  2272. PRTSCR    PROC    NEAR
  2273.     jcxz    prtscr4            ; cx = zero means nothing to show
  2274.     push    ax
  2275.     push    bx
  2276.     push    dx
  2277.     mov    dx,di            ; source ptr for DOS
  2278.     cmp    flags.eofcz,0        ; end on Control-Z?
  2279.     jne    prtscr3            ; ne = yes, let DOS do it
  2280.     push    cx            ; else map Control-Z to space
  2281.     push    di
  2282.     push    es
  2283.     push    ds
  2284.     pop    es            ; data to es
  2285.     mov    al,ctlz            ; look for Control-Z
  2286.     cld                ; scan buffer es:di, cx chars worth
  2287. prtscr1:repne    scasb
  2288.     jne    prtscr2            ; ne = found no Control-Z's
  2289.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  2290.     jcxz    prtscr2            ; z = examined all chars
  2291.     jmp    short prtscr1        ; until examined everything
  2292. prtscr2:pop    es
  2293.     pop    di
  2294.     pop    cx
  2295. prtscr3:mov    bx,1            ; stdout file handle
  2296.     mov    ah,write2
  2297.     int    dos
  2298.     pop    dx
  2299.     pop    bx
  2300.     pop    ax
  2301. prtscr4:ret
  2302. PRTSCR    ENDP
  2303.  
  2304. ; Print to screen asciiz string given in ds:dx. Everything preserved.
  2305. PRTASZ    PROC    NEAR
  2306.     push    cx
  2307.     push    di
  2308.     call    strlen            ; get length of asciiz string
  2309.     mov    di,dx            ; where prtscr looks
  2310.     call    prtscr            ; print counted string
  2311.     pop    di
  2312.     pop    cx
  2313.     ret
  2314. PRTASZ    ENDP
  2315.  
  2316. ;;; Load a translation table for file transfer
  2317. load    proc    near
  2318. ;;    mov    dx,offset loadtab    ; keyword Transfer-character-set
  2319. ;;    xor    bx,bx            ; help
  2320. ;;    mov    ah,cmkey
  2321. ;;    call    comnd
  2322. ;;    jnc    load0
  2323. ;;    ret
  2324. ;;load0:    mov    dx,offset rdbuf        ; buffer for filename
  2325. ;;    mov    word ptr rdbuf,0
  2326. ;;    mov    bx,offset loadhlp    ; help
  2327. ;;    mov    ah,cmword
  2328. ;;    call    comnd            ; get filename
  2329. ;;    jnc    load1            ; nc = success
  2330. ;;    ret                ; failure
  2331. ;;load1:    mov    ax,offset rdbuf        ; place for filename for isfile
  2332. ;;    call    isfile            ; does file exist?
  2333. ;;    jnc    load1b
  2334. ;;load1a:    mov    dx,offset infms6    ; unable to open file
  2335. ;;    mov    ah,prstr
  2336. ;;    int    dos
  2337. ;;    stc
  2338. ;;    ret                ; c = does not exist
  2339. ;;load1b:    mov    dx,ax
  2340. ;;    mov    cx,134
  2341. ;;    mov    ah,open2        ; file open
  2342. ;;    xor    al,al            ; 0 = open readonly
  2343. ;;    cmp    dosnum,300h        ; at or above DOS 2?
  2344. ;;    jb    load2            ; b = no, so no shared access
  2345. ;;    or    al,40h            ; open readonly, deny none
  2346. ;;load2:    int    dos
  2347. ;;    jc    load1a            ; if carry then error
  2348. ;;    mov    diskio.handle,ax    ; file handle
  2349. ;;                    ; read and parse lines
  2350. ;;    mov    linecnt,0        ; line counter
  2351. ;;    call    readln            ; L1, read and discard table name
  2352. ;;    jc    load5            ; c = failure
  2353. ;;    call    readln            ; L2, COMMON or LOCAL
  2354. ;;    jc    load5            ; c = failure
  2355. ;;    mov    ax,word ptr rdbuf
  2356. ;;    or    ax,2020h        ; to lower case
  2357. ;;    mov    tblptr,offset userin
  2358. ;;    cmp    ax,'oc'            ; "common"? (on the wire to local)
  2359. ;;    je    load4            ; e = yes
  2360. ;;    mov    tblptr,offset userout
  2361. ;;    cmp    ax,'ol'            ; "local"? (local to on the wire)
  2362. ;;    jne    load5            ; ne = no, fail
  2363. ;;
  2364. ;;load4:    call    readln            ; L3 name of comms line char set
  2365. ;;    jnc    load6            ; success
  2366. ;;load5:    jmp    loadx
  2367. ;;
  2368. ;;load6:    call    readln            ; L4 bytes per char in above set
  2369. ;;    jc    load5
  2370. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2371. ;;    call    atoi            ; ax has value
  2372. ;;    jc    load5            ; c = no number
  2373. ;;    cmp    ax,1            ; one byte per char?
  2374. ;;    jne    load5            ; ne = no, fail here
  2375. ;;
  2376. ;;    call    readln            ; L5 chars/plane (94/96/128)
  2377. ;;    jc    load7            ; c = failure
  2378. ;;    mov    dx,offset rdbuf
  2379. ;;    call    strlen
  2380. ;;    mov    ah,cl
  2381. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2382. ;;    call    atoi            ; ax has value
  2383. ;;    jc    load7            ; c = no number
  2384. ;;    cmp    ax,128            ; too many?
  2385. ;;    ja    load7            ; a = yes, fail here
  2386. ;;
  2387. ;;    call    readln            ; L6 name of local display char set
  2388. ;;    jnc    load8
  2389. ;;load7:    jmp    loadx
  2390. ;;
  2391. ;;load8:    call    readln            ; L7 bytes per char in above set
  2392. ;;    jc    load7
  2393. ;;    mov    dx,offset rdbuf
  2394. ;;    call    strlen
  2395. ;;    mov    ah,cl
  2396. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2397. ;;    call    atoi            ; ax has value
  2398. ;;    jc    load7            ; c = no number
  2399. ;;    cmp    ax,1            ; one byte per char?
  2400. ;;    jne    load7            ; ne = no, fail here
  2401. ;;
  2402. ;;    call    readln            ; L8 chars/plane (94/96/128)
  2403. ;;    jc    load7            ; failure
  2404. ;;    mov    dx,offset rdbuf
  2405. ;;    call    strlen
  2406. ;;    mov    ah,cl
  2407. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2408. ;;    call    atoi            ; ax has value
  2409. ;;    jc    load7            ; c = no number
  2410. ;;    cmp    ax,128            ; too many?
  2411. ;;    ja    load7            ; a = yes, fail here
  2412. ;;
  2413. ;;    call    readln            ; L9 designator of comms line set
  2414. ;;    jc    load8
  2415. ;;    call    readln            ; L10 Version of comms line set
  2416. ;;    jc    load8
  2417. ;;    call    readln            ; L11 Registration num of comms set
  2418. ;;    jc    load8
  2419. ;;    call    readln            ; L12 direction of writing
  2420. ;;    jc    load8
  2421. ;;    call    readln            ; L13 number of entries in table below
  2422. ;;    jc    load7
  2423. ;;    mov    dx,offset rdbuf
  2424. ;;    call    strlen
  2425. ;;    mov    ah,cl
  2426. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2427. ;;    call    atoi            ; ax has value
  2428. ;;    jc    load7            ; c = no number
  2429. ;;    mov    xlines,ax
  2430. ;;
  2431. ;;    call    readln            ; L14 count of filler lines before
  2432. ;;    jc    load7            ;  table below
  2433. ;;    mov    dx,offset rdbuf
  2434. ;;    call    strlen            ; length to cx
  2435. ;;    mov    ah,cl
  2436. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2437. ;;    call    atoi            ; ax has value
  2438. ;;    jc    load7            ; c = no number
  2439. ;;    mov    cx,ax            ; count of filler lines
  2440. ;;    jcxz    load10            ; z = none
  2441. ;;load9:    push    cx
  2442. ;;    call    readln            ; L15 et seq, filler lines
  2443. ;;    pop    cx            ; read and discard
  2444. ;;    jc    loadx
  2445. ;;    loop    load9
  2446. ;;
  2447. ;;load10:    dec    xlines            ; Translation data lines
  2448. ;;    cmp    xlines,0        ; any left?
  2449. ;;    jge    load11            ; ge = yes
  2450. ;;    jmp    loady
  2451. ;;load11:    call    readln            ; translation table line(s)
  2452. ;;    jc    loadx            ; c = failure
  2453. ;;    mov    si,offset rdbuf        ; the buffer
  2454. ;;    mov    dx,si
  2455. ;;    call    strlen            ; length to cx
  2456. ;;    mov    ah,cl            ; count for atoi
  2457. ;;    call    atoi            ; get "from" number
  2458. ;;    jc    loadx            ; failure
  2459. ;;    test    al,80h            ; referring to high bit set (GR)?
  2460. ;;    jnz    load12            ; nz = yes
  2461. ;;    jmp    loadx
  2462. ;;load12:    and    ax,not 0ff80h        ; strip bit for GR table
  2463. ;;    mov    temp,ax            ; save here
  2464. ;;    mov    dx,si
  2465. ;;    call    strlen
  2466. ;;    mov    ah,cl            ; count
  2467. ;;    call    atoi            ; get "to" number
  2468. ;;    mov    bx,tblptr        ; point at table
  2469. ;;    add    bx,temp            ; locate entry
  2470. ;;    mov    [bx],al            ; store new value
  2471. ;;    jmp    load10            ; repeat til done
  2472. ;;
  2473. ;;loadx:    mov    dx,offset badvalue    ; complain
  2474. ;;    mov    ah,prstr
  2475. ;;    int    dos
  2476. ;;    mov    ax,linecnt        ; show line number
  2477. ;;    call    decout
  2478. ;;    mov    ah,conout
  2479. ;;    mov    dl,':'
  2480. ;;    int    dos
  2481. ;;    mov    dx,offset rdbuf        ; show the line
  2482. ;;    call    prtasz
  2483. ;;loady:    mov    bx,diskio.handle
  2484. ;;    mov    ah,close2        ; close the file
  2485. ;;    int    dos
  2486.     clc
  2487.     ret
  2488. load    endp
  2489. ;;
  2490. ;;readln    proc    near
  2491. ;;    push    ax
  2492. ;;    push    bx
  2493. ;;    push    cx
  2494. ;;    push    dx
  2495. ;;    push    di
  2496. ;;    inc    linecnt            ; line counter
  2497. ;;    mov    cx,82            ; 82 bytes, including trailer
  2498. ;;    mov    temp,0            ; leading whitespace and comment flgs
  2499. ;;    mov    di,offset rdbuf        ; destination buffer
  2500. ;;    mov    bx,diskio.handle    ; file handle
  2501. ;;readln1:push    cx            ; read from file
  2502. ;;    mov    cx,1            ; read 1 char
  2503. ;;    mov    dx,di            ; place here
  2504. ;;    mov    byte ptr [di],0        ; insert terminator
  2505. ;;    mov    ah,readf2
  2506. ;;    int    dos
  2507. ;;    pop    cx
  2508. ;;    jc    readlnx            ; c = read failure
  2509. ;;    or    ax,ax            ; count of bytes read
  2510. ;;    jz    readlnx            ; z means end of file
  2511. ;;    cmp    byte ptr [di],LF    ; LF?
  2512. ;;    je    readln3            ; e = yes, ignore it
  2513. ;;    cmp    byte ptr [di],CR    ; end of line?
  2514. ;;    je    readln4            ; e = yes, exit
  2515. ;;    cmp    byte ptr [di],';'    ; start of comment?
  2516. ;;    jne    readln6            ; ne = no
  2517. ;;    mov    byte ptr temp+1,1    ; say comment has started
  2518. ;;    jmp    short readln3        ; do not store it
  2519. ;;readln6:cmp    byte ptr temp+1,0    ; seen comment semicolon yet?
  2520. ;;    jne    readln3            ; ne = yes, do not store comment
  2521. ;;    cmp    byte ptr temp,0        ; seen non-spacing char yet?
  2522. ;;    jne    readln2            ; ne = yes
  2523. ;;    cmp    byte ptr [di],' '    ; is this a space?
  2524. ;;    je    readln3            ; e = yes, skip it
  2525. ;;    cmp    byte ptr [di],TAB    ; or a tab?
  2526. ;;    je    readln3            ; e = yes, skip it
  2527. ;;    mov    byte ptr temp,1        ; say have seen non-spacing char
  2528. ;;readln2:cmp    flags.takflg,0        ; echo Take files?
  2529. ;;    je    readln2a        ; e = no
  2530. ;;    mov    ah,conout
  2531. ;;    mov    dl,byte ptr [di]
  2532. ;;    int    dos
  2533. ;;readln2a:inc    di            ; next storage cell
  2534. ;;readln3:loop    readln1            ; loop til end of line
  2535. ;;readln4:cmp    flags.takflg,0        ; echo Take files?
  2536. ;;    je    readln4a        ; e = no
  2537. ;;    mov    ah,prstr
  2538. ;;    mov    dx,offset crlf
  2539. ;;    int    dos
  2540. ;;readln4a:clc
  2541. ;;    mov    byte ptr [di],0        ; insert final terminator
  2542. ;;    jmp    short readlnx
  2543. ;;
  2544. ;;readln5:stc                ; set carry for failure to read
  2545. ;;readlnx:pop    di
  2546. ;;    pop    dx
  2547. ;;    pop    cx
  2548. ;;    pop    bx
  2549. ;;    pop    ax
  2550. ;;    ret
  2551. ;;readln    endp
  2552. code    ends 
  2553.     end
  2554.