home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msk316src.zip / MSSFIL.ASM < prev    next >
Assembly Source File  |  1999-04-24  |  126KB  |  3,334 lines

  1.     NAME    mssfil
  2. ; File MSSFIL.ASM
  3.     include mssdef.h
  4. ;    Copyright (C) 1982, 1999, Trustees of Columbia University in the 
  5. ;    City of New York.  The MS-DOS Kermit software may not be, in whole 
  6. ;    or in part, licensed or sold for profit as a software product itself,
  7. ;    nor may it be included in or distributed with commercial products
  8. ;    or otherwise distributed by commercial concerns to their clients 
  9. ;    or customers without written permission of the Office of Kermit 
  10. ;    Development and Distribution, Columbia University.  This copyright 
  11. ;    notice must not be removed, altered, or obscured.
  12. ;
  13. ; Edit history
  14. ; 12 Jan 1995 version 3.14
  15. ; Last edit
  16. ; 12 Jan 1995
  17. ; 27 August 1992 version 3.13
  18. ; 6 Sept 1991 version 3.11
  19. ; 2 March 1991 version 3.10
  20.  
  21.     public    buff, gofil, ptchr, gtchr, getfil, gtnfil, doenc, dodec
  22.     public    encbuf, decbuf, diskio, auxfile, fparse, prtasz, prtscr
  23.     public    strlen, strcat, strcpy, tfilsz, templp, latin1, charids
  24.     public    L1cp437, L1cp850, L1cp860, L1cp863, L1cp865, unique
  25.     public    cplatin, goopen, latininv, protlist, jpnxtof, templf
  26.     public    jpnftox, echrcnt, rcvpathflg, sndpathflg, atfile, atflag
  27.     public    l5cp866, lccp866r, k8cp866r, k7cp866r, cp866koi7, cp866koi8
  28.     public    cp866lci, crcword, lastfsize
  29.  
  30. SIchar    equ    0fh
  31. SOchar    equ    0eh
  32. DLE    equ    10h
  33.  
  34. data    segment
  35.     extrn    flags:byte, trans:byte, dtrans:byte, denyflg:word,dosnum:word
  36.     extrn    oldkbt:word, oldper:word, filtst:byte, rdbuf:byte, fsta:byte
  37.     extrn    curdsk:byte, fdate:byte, ftime:byte, wrpmsg:byte
  38.     extrn    rfileptr:word, findkind:byte, rpathname:byte, rfilename:byte
  39.     extrn    sendkind:byte
  40.  
  41. ermes4  db    'Unable to make unique name',0
  42. ermes9    db    'Printer not ready',0
  43. erms12    db    'Unable to create file ',0
  44. erms13    db    'Error writing output file',0
  45. infms5  db    'Renaming file to $'
  46. infms6    db    cr,lf,'?Unable to open file$'
  47. asmsg    db    ' as $'
  48. crlf    db    cr,lf,'$'
  49. printer    db    'PRN',0
  50. screen    db    'CON',0
  51. vacuum    db    'NUL',0
  52. loadhlp    db    'filename$'
  53.                 ; DOS special chars allowed in filenames
  54. spchar2    db    '$', 26h, 23h, 40h, 21h, 25h, 27H, '(', ')', '-', 7bh, 7dh
  55.     db    5fh, 5eh, 7eh, 60h
  56. spc2len    equ    $-spchar2
  57.  
  58. textctl    db    cr,lf,tab,bell,ff,ctlz    ; controls allowed in text files
  59. textctlen equ    $-textctl
  60.     even
  61. filflg    db    0        ; input buffer has data, if non-zero
  62. rptct    db    1        ; number of times it's repeated
  63. dblbyte    db    0        ; first of two bytes in a pair
  64. dblbyteflg db    0        ; non-zero if processing second byte of pair
  65. DLEseen    db    0
  66. shiftstate db    0        ; locking shift (0 = unshifted, 80h = shifted)
  67. decoutp    dw    0        ; ptr to proc to dump decode output buffer
  68. encinp    dw    0        ; ptr to proc to refill encode input buffer
  69. dchrcnt dw    0        ; number of chars in the decode file buffer
  70. echrcnt dw    0        ; number of chars in the encode file buffer
  71. dbufpnt dw    0        ; position in file buffer, decoder
  72. ebufpnt dw    0        ; position in file buffer, encoder
  73. crcword    dw    0        ; CRC-16 accumulator
  74. lastfsize dw    0,0        ; size of last transferred file
  75.  
  76.     db    0        ; this MUST directly preceed decbuf, jpnwrite
  77. decbuf    db    decbuflen dup (0) ; decoding source buffer
  78.     db    0        ; safety for possible null terminator
  79. encbuf    db    encbuflen dup (0) ; encoding source buffer
  80.     db    0        ; safety for possible null terminator
  81. protlist db    32 dup (0)     ; list of protected control codes (if = 0)
  82.  
  83. tfilsz    dw    0,0        ; bytes transferred (double word qty)
  84. nmoflg    db    0        ; have override filename, if non-zero
  85. templp    db    65 dup (0)    ; temp for local path part
  86. templf    db    14 dup (0)    ; temp for local filename part
  87. temprp    db    65 dup (0)    ; temp for remote path part
  88. temprf    db    14 dup (0)    ; temp for remote filename part
  89. auxfile    db    65 dup (0)    ; auxillary filename for general use
  90. atfile    db    67 dup (0)    ; at sign sending source file
  91. atflag    db    0        ; non-zero if using at sign file sending
  92. diskio    filest    <>        ; for ordinary file transfers
  93. buff    db    buffsz dup (?)    ; use as our Disk Transfer Area
  94. unum    dw    0        ; unique filename generation number
  95. ifdef    no_terminal
  96. rcvpathflg db    0        ; remove(0)/retain(1) remote paths on RECEIVE
  97. else
  98. rcvpathflg db    1        ; remove(0)/retain(1) remote paths on RECEIVE
  99. endif    ; no_terminal          BBS flavor gets no receive pathnames
  100. sndpathflg db    0        ; remove(0)/retain(1) local paths on SEND
  101. temp    dw    0
  102.                 ; charids: table of transfer char-set idents
  103. charids dw    7        ; qty, pointers to char set idents
  104.     dw    chtrans,chlatin1,chlatin2,chhebiso,chcyrill,chjapan,chjapanold
  105. chtrans    db    1,'A'        ; Transparent: char count, ident
  106. chlatin1 db    6,'I6/100'    ; Latin1: char count, ident
  107. chlatin2 db    6,'I6/101'    ; Latin2: char count, ident
  108. chhebiso db    6,'I6/138'    ; Hebrew-ISO: char count, ident
  109. chcyrill db    6,'I6/144'    ; Cyrillic: char count, ident
  110. chjapan    db    9,'I14/87/13'    ; Japanese-EUC: char count, ident (new)
  111. chjapanold db    7,'I14/87E'    ; Japanese-EUC: char count, ident (obsolete)
  112.                 ; end of charids info
  113. ;loadtab    db    1        ; LOAD command table
  114. ;    mkeyw    'Transfer-character-set',0
  115. ;
  116. ;filtab    macro
  117. ;    cnt = 128
  118. ;    rept    128            ; 128 idenity entries
  119. ;    db    cnt            ; initialize table to 128 .. 255
  120. ;    cnt = cnt + 1
  121. ;    endm
  122. ;endm
  123. ;
  124. ;userin    equ    this byte        ; LOAD command
  125. ;    filtab                ; init table to idenity
  126. ;namein    db    20 dup (0)        ; name of the character set
  127. ;userout    equ    this byte
  128. ;    filtab                ; init table to idenity
  129. ;nameout db    20 dup (0)        ; name of the character set
  130. ;tblptr    dw    0            ; LOAD command
  131. ;xlines    dw    0            ; LOAD command
  132. ;linecnt dw    0            ; LOAD command
  133. ;badvalue db    cr,lf,'?Bad value on line $'
  134.  
  135. cacheptr    dw 0
  136. cachelen    dw 0
  137. cacheseg    dw 0
  138. data    ends
  139.  
  140. data1    segment
  141. ; Translation tables for byte codes 0a0h..0ffh to map ISO 8859-1 to Code Pages
  142. ; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is
  143. ; considered to be a control code, 80h..9fh are 8-bit controls (C1).
  144. ; Each table is 96 translatable bytes followed by the table size (96), the
  145. ; ISO announcer ident ('A' and a null here); LATIN5/Cyrillic uses 'L'.
  146. ; The decimal tables are from Frank da Cruz working with the formal IBM docs.
  147.                     ; from ISO 8859-1 Latin-1 to Code Page
  148.                         ; to CP437 United States
  149. L1cp437    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  150.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  151.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  152.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  153.     db    20h,0adh,9bh,9ch,  0fh,9dh,7ch,15h    ; column 10
  154.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  155.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  156.     db    2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  157.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  158.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  159.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  160.     db    4fh,55h,55h,55h,   9ah,59h,3fh,0e1h
  161.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  162.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  163.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  164.     db    6fh,97h,0a3h,96h,  81h,79h,3fh,98h
  165.     db    96,'A',0            ; 96 byte set, letter ident
  166.  
  167.                         ; to CP850 Multilingual
  168. L1cp850    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  169.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  170.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  171.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  172.     db    20h,0adh,0bdh,9ch,  0cfh,0beh,0ddh,0f5h    ; column 10
  173.     db    0f9h,0b8h,0a6h,0aeh, 0aah,0f0h,0a9h,0eeh
  174.     db    0f8h,0f1h,0fdh,0fch, 0efh,0e6h,0f4h,0fah ; column 11
  175.     db    0f7h,0fbh,0a7h,0afh, 0ach,0abh,0f3h,0a8h
  176.     db    0b7h,0b5h,0b6h,0c7h, 8eh,8fh,92h,80h    ; column 12
  177.     db    0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h
  178.     db    0d1h,0a5h,0e3h,0e0h, 0e2h,0e5h,99h,9eh    ; column 13
  179.     db    9dh,0ebh,0e9h,0eah, 9ah,0edh,0e8h,0e1h
  180.     db    85h,0a0h,83h,0c6h,  84h,86h,91h,87h    ; column 14
  181.     db    8ah,82h,88h,89h,    8dh,0a1h,8ch,8bh
  182.     db    0d0h,0a4h,95h,0a2h, 93h,0e4h,94h,0f6h    ; column 15
  183.     db    9bh,97h,0a3h,96h,   81h,0ech,0e7h,98h
  184.     db    96,'A',0            ; 96 byte set, letter ident
  185.  
  186.                         ; to CP860 Portugal
  187. L1cp860    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  188.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  189.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  190.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  191.     db    20h,0adh,9bh,9ch,  0fh,59h,7ch,15h    ; column 10
  192.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  193.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  194.     db    2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  195.     db    91h,86h,8fh,8eh,   41h,41h,41h,80h    ; column 12
  196.     db    92h,90h,89h,45h,   8bh,98h,49h,49h
  197.     db    44h,0a5h,0a9h,9fh, 8ch,99h,4fh,58h    ; column 13
  198.     db    4fh,9dh,96h,55h,   9ah,59h,3fh,0e1h
  199.     db    85h,0a0h,83h,84h,  61h,61h,61h,87h    ; column 14
  200.     db    8ah,82h,88h,65h,   8dh,0a1h,69h,69h
  201.     db    3fh,0a4h,95h,0a2h, 93h,94h,6fh,0f6h    ; column 15
  202.     db    6fh,97h,0a3h,75h,  81h,79h,3fh,79h
  203.     db    96,'A',0            ; 96 byte set, letter ident
  204.  
  205.                         ; to CP861 Iceland
  206. L1cp861    db    80h,0fch,82h,83h,  84h,85h,86h,87h    ; column 8
  207.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  208.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  209.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  210.     db    20h,0adh,43h,9ch,  0fh,59h,7ch,15h    ; column 10
  211.     db    22h,3fh,0a6h,0aeh,  0aah,16h,3fh,2dh
  212.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  213.     db    2ch,31h,3fh,0afh,  0ach,0abh,3fh,0a8h
  214.     db    41h,0a4h,41h,41h,  8eh,8fh,92h,80h    ; column 12
  215.     db    45h,90h,45h,45h,   49h,0a5h,49h,49h
  216.     db    8bh,4eh,4fh,0a6h,  4fh,4fh,99h,58h    ; column 13
  217.     db    9dh,55h,0a7h,55h,  9ah,97h,8dh,0e1h
  218.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  219.     db    8ah,82h,88h,89h,   69h,0a1h,69h,69h
  220.     db    8ch,6eh,6fh,0a2h,  93h,6fh,94h,0f6h    ; column 15
  221.     db    9bh,75h,0a3h,96h,  81h,98h,95h,79h
  222.     db    96,'A',0            ; 96 byte set, letter ident
  223.  
  224.                         ; to CP863 Canada-French
  225. L1cp863    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  226.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  227.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  228.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  229.     db    20h,3fh,9bh,9ch,   98h,59h,0a0h,8fh    ; column 10
  230.     db    0a4h,40h,61h,0aeh, 0aah,0c4h,3fh,0a7h
  231.     db    0f8h,0f1h,0fdh,0a6h, 0a1h,0e6h,86h,0fah    ; column 11
  232.     db    0a5h,31h,6fh,0afh, 0ach,0abh,0adh,3fh
  233.     db    8eh,41h,84h,41h,   41h,41h,41h,80h    ; column 12
  234.     db    91h,90h,92h,94h,   49h,49h,0a8h,95h
  235.     db    44h,4eh,4fh,4fh,   99h,4fh,4fh,58h    ; column 13
  236.     db    4fh,9dh,55h,9eh,   9ah,59h,3fh,0e1h
  237.     db    85h,61h,83h,61h,   61h,61h,61h,87h    ; column 14
  238.     db    8ah,82h,88h,89h,   69h,69h,8ch,8bh
  239.     db    3fh,6eh,6fh,0a2h,  93h,6fh,6fh,0f6h    ; column 15
  240.     db    6fh,97h,0a3h,96h,  81h,79h,3fh,79h
  241.     db    96,'A',0            ; 96 byte set, letter ident
  242.                         ; to CP865 Norway
  243. L1cp865    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  244.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  245.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  246.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  247.     db    20h,0adh,3fh,9ch,  0afh,59h,7ch,15h    ; column 10
  248.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,0c4h
  249.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  250.     db    2ch,31h,0a7h,03fh, 0ach,0abh,3fh,0a8h
  251.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  252.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  253.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  254.     db    9dh,55h,55h,55h,  9ah,59h,3fh,0e1h
  255.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  256.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  257.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  258.     db    9bh,97h,0a3h,96h,  81h,79h,3fh,98h
  259.     db    96,'A',0            ; 96 byte set, letter ident
  260.                             ; Latin2 to CP852
  261. L2cp852    db 174,175,176,177,178,179,180,185,186,187,188,191,192,193,194,195
  262.     db 196,197,200,201,202,203,204,205,206,217,218,219,220,223,240,254
  263.     db 255,164,244,157,207,149,151,245,249,230,184,155,141,170,166,189
  264.     db 248,165,242,136,239,150,152,243,247,231,173,156,171,241,167,190
  265.     db 232,181,182,198,142,145,143,128,172,144,168,211,183,214,215,210
  266.     db 209,227,213,224,226,138,153,158,252,222,233,235,154,237,221,225
  267.     db 234,160,131,199,132,146,134,135,159,130,169,137,216,161,140,212
  268.     db 208,228,229,162,147,139,148,246,253,133,163,251,129,236,238,250
  269.     db    96,'B',0            ; 96 byte set, letter ident
  270.  
  271.                 ; Hebrew-ISO to Code Page 862, GLeft
  272. HIcp862    db 158,159,160,161,162,163,164,165,166,167,168,169,173,176,177,178
  273.     db 179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194
  274.     db 255,195,155,156,196,157,197,198,199,200,201,174,170,202,203,204
  275.     db 248,241,253,206,207,230,208,249,209,210,246,175,172,171,211,212
  276.     db 213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228
  277.     db 229,231,232,233,234,235,236,237,238,239,240,242,243,244,245,205
  278.     db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  279.     db 144,145,146,147,148,149,150,151,152,153,154,247,250,251,252,254
  280.     db    96,'H',0
  281.  
  282.                             ; Latin5 to CP866
  283. L5cp866    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  284.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  285.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  286.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  287.     db    0ffh,0f0h,3fh,3fh,  0f2h,53h,49h,4fh    ; column 10
  288.     db    4ah,3fh,3fh,48h,   4bh,2dh,0f6h,3fh
  289.     db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 11
  290.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  291.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 12
  292.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  293.     db    0a0h,0a1h,0a2h,0a3h,0a4h,0a5h,0a6h,0a7h ; column 13
  294.     db    0a8h,0a9h,0aah,0abh,0ach,0adh,0aeh,0afh
  295.     db    0e0h,0e1h,0e2h,0e3h,0e4h,0e5h,0e6h,0e7h ; column 14
  296.     db    0e8h,0e9h,0eah,0ebh,0ech,0edh,0eeh,0efh
  297.     db    0fch,0f1h,3fh,3fh, 0f3h,73h,69h,0f5h    ; column 15
  298.     db    6ah,3fh,3fh,68h,   6bh,15h,0f7h,3fh
  299.     db    96,'L',0            ; 96 byte set, Latin5/Cyrillic
  300.  
  301. ;yl143[]   /* Latin-1 to IBM Code Page 437 */
  302. ; Although the IBM CDRA does not include an official translation between CP437
  303. ; and ISO Latin Alphabet 1,it does include an official,invertible
  304. ; translation between CP437 and CP850 (page 196),and another from CP850 to
  305. ; Latin-1 (CP819) (page 153).  This translation was obtained with a two-step
  306. ; process based on those tables.
  307.  
  308. iL1cp437 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,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  313.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  314.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  315.     db 173,177,143,190,20,21,247,184,176,168,183,185,179,178,142,160
  316.     db 96,'A',0                ; 96 byte set,letter ident
  317.  
  318. ;yl185[]   /* Latin-1 to IBM Code Page 850 */
  319. ; This is IBM's official invertible translation.  Reference: IBM Character
  320. ; Data Representation Architecture (CDRA),Level 1, Registry, SC09-1291-00
  321. ; (1990), p.152.  (Note: Latin-1 is IBM Code Page 00819.)
  322. iL1cp850 db 186,205,201,187,200,188,204,185,203,202,206,223,220,219,254,242
  323.     db 179,196,218,191,192,217,195,180,194,193,197,176,177,178,213,159
  324.     db 255,173,189,156,207,190,221,245,249,184,166,174,170,240,169,238
  325.     db 248,241,253,252,239,230,244,250,247,251,167,175,172,171,243,168
  326.     db 183,181,182,199,142,143,146,128,212,144,210,211,222,214,215,216
  327.     db 209,165,227,224,226,229,153,158,157,235,233,234,154,237,232,225
  328.     db 133,160,131,198,132,134,145,135,138,130,136,137,141,161,140,139
  329.     db 208,164,149,162,147,228,148,246,155,151,163,150,129,236,231,152
  330.     db 96,'A',0                ; 96 byte set, letter ident
  331.  
  332. ; invertable Latin-1 to CP861 
  333. iL1cp861 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  334.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  335.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  336.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  337.     db 148,164,152,150,145,154,227,195,132,130,137,136,134,165,138,164
  338.     db 139,208,202,166,200,158,205,206,157,149,167,141,140,151,141,139
  339.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  340.     db 140,177,143,190, 20, 21,247,184,155,168,183,185,179,152,149,160
  341.     db 96,'A',0                ; 96 byte set, letter ident
  342.  
  343.  
  344. ; 128 byte translation tables from Code Pages to ISO 8859-1 Latin1 or Latin5
  345. ; For GRight only (high bit set).
  346.                             ; from Code Page 437
  347. cp437L1    db    0c7h,0fch,0e9h,0e2h,0e4h,0e0h,0e5h,0e7h ; column 8
  348.     db    0eah,0ebh,0e8h,0efh,0eeh,0ech,0c4h,0c5h
  349.     db    0c9h,0e6h,0c6h,0f4h,0f6h,0f2h,0fbh,0f9h ; column 9
  350.     db    0ffh,0d6h,0dch,0a2h,0a3h,0a5h,3fh,3fh
  351.     db    0e1h,0edh,0f3h,0fah,0f1h,0d1h,0aah,0bah ; column 10
  352.     db    0bfh,3fh,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  353.     db    16 dup (3fh)                 ; column 11
  354.     db    16 dup (3fh)                 ; column 12
  355.     db    16 dup (3fh)                 ; column 13
  356.     db    3fh,0dfh,4 dup (3fh),        0b5h,3fh ; column 14
  357.     db    5 dup(3fh),            0f8h,3fh,3fh
  358.     db    3fh,0b1h,4 dup (3fh),        0f7h,3fh ; column 15
  359.     db    0b0h,0b7h,0b7h,3fh,3fh,        0b2h,3fh,3fh
  360.                              ; from Code Page 850
  361. cp850L1    db    0c7h,0fch,0e9h,0e2h,0e4h,0e0h,0e5h,0e7h ; column 8
  362.     db    0eah,0ebh,0e8h,0efh,0eeh,0ech,0c4h,0c5h
  363.     db    0c9h,0e6h,0c6h,0f4h,0f6h,0f2h,0fbh,0f9h ; column 9
  364.     db    0ffh,0d6h,0dch,0f8h,0a3h,0d8h,0d7h,3fh
  365.     db    0e1h,0edh,0f3h,0fah,0f1h,0d1h,0aah,0bah ; column 10
  366.     db    0bfh,0aeh,0ach,0bdh,0bch,0a1h,0abh,0bbh
  367.     db    5 dup (3fh),             0c1h,0c2h,0c0h ; column 11
  368.     db    0a9h,4 dup (3fh),      0a2h,0a5h,3fh
  369.     db    6 dup (3fh),0e3h,0c3h,7 dup (3fh),0a4h     ; column 12
  370.     db    0f0h,0d0h,0cah,0cbh,0c8h,0b9h,0cdh,0ceh ; column 13
  371.     db    0cfh, 4 dup (3fh),       0a6h,0cch,3fh
  372.     db    0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,0feh ; column 14
  373.     db    0deh,0dah,0dbh,0d9h, 0fdh,0ddh,0afh,0b4h
  374.     db    0adh,0b1h,3dh,0beh,  0b6h,0a7h,0f7h,0b8h ; column 15
  375.     db    0b0h,0a8h,0b7h,0b9h, 0b3h,0b2h,3fh,20h
  376.  
  377.                              ; from Code Page 860
  378. cp860L1    db    0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8
  379.     db    0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h
  380.     db    0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9
  381.     db    0cdh,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h
  382.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  383.     db    0bfh,0d2h,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  384.     db    16 dup (3fh)                 ; column 11
  385.     db    16 dup (3fh)                 ; column 12
  386.     db    16 dup (3fh)                 ; column 13
  387.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  388.     db    5 dup(3fh),            0f8h,3fh,3fh
  389.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  390.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  391.  
  392.                             ; from Code Page 861
  393. cp861L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  394.     db    0eah,0ebh,0e8h,0d0h, 0f0h,0deh,0c4h,0c5h
  395.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0feh,0fbh,0ddh ; column 9
  396.     db    0fdh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  397.     db    0e1h,0edh,0f3h,0fah, 0c1h,0cdh,0d3h,0dah ; column 10
  398.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0bbh
  399.     db    16 dup (3fh)                 ; column 11
  400.     db    16 dup (3fh)                 ; column 12
  401.     db    16 dup (3fh)                 ; column 13
  402.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  403.     db    5 dup(3fh),            0f8h,3fh,3fh
  404.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  405.     db    0b0h,0b7h,0b7h,3fh,3fh,        0b2h,3fh,3fh
  406.  
  407.                              ; from Code Page 863
  408. cp863L1    db    0c7h,0fch,0e9h,0e2h, 0c2h,0e0h,0b6h,0e7h ; column 8
  409.     db    0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h
  410.     db    0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0f9h ; column 9
  411.     db    0a4h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh
  412.     db    0a6h,0b4h,0f3h,0fah, 0a8h,0b8h,0b3h,0afh ; column 10
  413.     db    0ceh,3fh,0ach,0bdh,  0bch,0beh,0abh,0bbh
  414.     db    16 dup (3fh)                 ; column 11
  415.     db    16 dup (3fh)                 ; column 12
  416.     db    16 dup (3fh)                 ; column 13
  417.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  418.     db    5 dup(3fh),            0f8h,3fh,3fh
  419.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  420.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  421.                                   ; from Code Page 865
  422. cp865L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  423.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  424.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  425.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  426.     db    0e2h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  427.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0a4h
  428.     db    16 dup (3fh)                 ; column 11
  429.     db    16 dup (3fh)                 ; column 12
  430.     db    16 dup (3fh)                 ; column 13
  431.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  432.     db    5 dup(3fh),            0f8h,3fh,3fh
  433.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  434.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  435.  
  436.                     ; from Code Page 852 to LATIN2
  437. cp852L2    db 199,252,233,226,228,249,230,231,179,235,213,245,238,172,196,198
  438.     db 201,197,229,244,246,165,181,166,182,214,220,171,187,163,215,232
  439.     db 225,237,243,250,161,177,174,190,202,234,173,188,200,186,128,129
  440.     db 130,131,132,133,134,193,194,204,170,135,136,137,138,175,191,139
  441.     db 140,141,142,143,144,145,195,227,146,147,148,149,150,151,152,164
  442.     db 240,208,207,203,239,210,205,206,236,153,154,155,156,222,217,157
  443.     db 211,223,212,209,241,242,169,185,192,218,224,219,253,221,254,180
  444.     db 158,189,178,183,162,167,247,184,176,168,255,251,216,248,159,160
  445.  
  446.                     ; Code Page 862 to Hebrew-ISO
  447. cp862HI db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  448.     db 240,241,242,243,244,245,246,247,248,249,250,162,163,165,128,129
  449.     db 130,131,132,133,134,135,136,137,138,139,172,189,188,140,171,187
  450.     db 141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156
  451.     db 157,158,159,161,164,166,167,168,169,170,173,174,175,223,179,180
  452.     db 182,184,185,190,191,192,193,194,195,196,197,198,199,200,201,202
  453.     db 203,204,205,206,207,208,181,209,210,211,212,213,214,215,216,217
  454.     db 218,177,219,220,221,222,186,251,176,183,252,253,254,178,255,160
  455.  
  456.                      ; from Code Page 866 to LATIN5
  457. cp866L5    db    0b0h,0b1h,0b2h,0b3h, 0b4h,0b5h,0b6h,0b7h ; column 8
  458.     db    0b8h,0b9h,0bah,0bbh, 0bch,0bdh,0beh,0bfh
  459.     db    0c0h,0c1h,0c2h,0c3h, 0c4h,0c5h,0c6h,0c7h ; column 9
  460.     db    0c8h,0c9h,0cah,0cbh, 0cch,0cdh,0ceh,0cfh
  461.     db    0d0h,0d1h,0d2h,0d3h, 0d4h,0d5h,0d6h,0d7h ; column 10
  462.     db    0d8h,0d9h,0dah,0dbh, 0dch,0ddh,0deh,0dfh
  463.     db    16 dup (3fh)                 ; column 11
  464.     db    16 dup (3fh)                 ; column 12
  465.     db    16 dup (3fh)                 ; column 13
  466.     db    0e0h,0e1h,0e2h,0e3h, 0e4h,0e5h,0e6h,0e7h ; column 14
  467.     db    0e8h,0e9h,0eah,0ebh, 0ech,0edh,0eeh,0efh
  468.     db    0a1h,0f1h,0a4h,0f4h, 0a7h,0f7h,0aeh,0feh ; column 15
  469.     db    4 dup (3fh),         0f0h,3fh,3fh,0a0h
  470.  
  471. ;y43l1[]   /* IBM Code Page 437 to Latin-1 */
  472. ;  This table is the inverse of yl143[].
  473. icp437L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  474.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  475.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  476.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  477.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  478.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  479.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  480.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  481.  
  482. ;y85l1[]   /* IBM Code Page 850 to Latin-1 */
  483. ;  This is from IBM CDRA page 153.  It is the inverse of yl185[].
  484. icp850L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  485.     db 201,230,198,244,246,242,251,249,255,214,220,248,163,216,215,159
  486.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  487.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,162,165,147
  488.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  489.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  490.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  491.     db 173,177,143,190,182,167,247,184,176,168,183,185,179,178,142,160
  492.  
  493. ;y86l1[]   /* IBM Code Page 861 to Latin-1 */
  494. ;  This table is the inverse of yl186[].
  495. icp861L1 db 199,252,233,226,228,224,229,231,234,235,232,208,240,222,196,197
  496.     db 201,230,198,244,246,254,251,221,253,214,220,248,163,216,215,159
  497.     db 225,237,243,250,193,205,211,218,191,174,172,189,188,161,171,187
  498.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  499.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  500.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  501.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  502.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  503.  
  504. UNK    equ    '?'
  505.  
  506. ;Latin/Cyrillic -> CP866 Readable:
  507. lccp866r db 196,179,192,217,191,218,195,193,180,194,197,176,177,178,211,216
  508.     db 205,186,200,188,187,201,204,202,185,203,206,223,220,219,254,253
  509.     db 255,240,132,131,242, 83, 73,244, 74,139,141,151,138, 45,246,135
  510.     db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  511.     db 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
  512.     db 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175
  513.     db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  514.     db 252,241,164,163,243,115,105,245,106,171,173,231,170,181,247,167
  515.  
  516. ;Latin/Cyrillic -> CP866 Invertible:
  517. lccp866i db 196,179,192,217,191,218,195,193,180,194,197,176,177,178,211,216
  518.     db 205,186,200,188,187,201,204,202,185,203,206,223,220,219,254,253
  519.     db 255,240,208,207,242,189,183,244,184,212,213,214,210,182,246,209
  520.     db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  521.     db 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
  522.     db 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175
  523.     db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  524.     db 252,241,221,215,243,199,190,245,198,249,250,251,248,181,247,222
  525.  
  526. ;KOI8 to CP866 Readable:
  527. k8cp866r db  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  528.     db  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
  529.     db  UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  530.     db  UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  531.     db  238,160,161,230,164,165,228,163,229,168,169,170,171,172,173,174
  532.     db  175,239,224,225,226,227,166,162,236,235,167,232,237,233,231,234
  533.     db  158,128,129,150,132,133,148,131,149,136,137,138,139,140,141,142
  534.     db  143,159,144,145,146,147,134,130,156,155,135,152,157,153,151,UNK
  535.  
  536. ;KOI7 to CP866 Readable:
  537. k7cp866r db   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15
  538.      db  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
  539.      db  32, 33, 34, 35,253, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
  540.      db  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,UNK
  541.      db  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79
  542.      db  80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
  543.      db 158,128,129,150,132,133,148,131,149,136,137,138,139,140,141,142
  544.      db 143,159,144,145,146,147,134,130,156,155,135,152,157,153,151,UNK
  545.  
  546. ;CP866 Invertible -> Latin/Cyrillic:
  547. cp866lci db 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191
  548.     db 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
  549.     db 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
  550.     db 139,140,141,129,136,253,173,166,168,152,145,148,147,165,246,132
  551.     db 130,135,137,134,128,138,248,245,146,149,151,153,150,144,154,163
  552.     db 162,175,172,142,169,170,171,243,143,131,133,157,156,242,255,155
  553.     db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  554.     db 161,241,164,244,167,247,174,254,252,249,250,251,240,159,158,160
  555.  
  556. ; CP866 to KOI7:
  557. cp866koi7 db  97, 98,119,103,100,101,118,122,105,106,107,108,109,110,111,112
  558.     db 114,115,116,117,102,104, 99,126,123,125, 39,121,120,124, 96,113
  559.     db  97, 98,119,103,100,101,118,122,105,106,107,108,109,110,111,112
  560.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  561.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  562.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  563.     db 114,115,116,117,102,104, 99,126,123,125, 39,121,120,124, 96,113
  564.     db 101,101,UNK,UNK, 73, 73,117,117,UNK,UNK,UNK,UNK,UNK, 36,UNK, 32
  565.  
  566. ; CP866 to KOI8:
  567. cp866koi8 db 225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240
  568.     db 242,243,244,245,230,232,227,254,251,253,223,249,248,252,224,241
  569.     db 193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208
  570.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  571.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  572.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  573.     db 210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209
  574.     db 229,197,UNK,UNK, 73,105,245,213,UNK,UNK,UNK,UNK,UNK, 36,UNK, 32
  575. data1    ends
  576.  
  577. ;  L/C = ISO Latin/Cyrillic
  578. ;  CP866R = Readable      <-- use this for terminal emulation
  579. ;  CP866I = Invertible    <-- use this for file transfer
  580. ;  KOI8   = "Old" KOI-8   <-- use this for terminal emulation
  581. ;  KOI7   = Short KOI     <-- use this for terminal emulation
  582. ;
  583. ;KOI8 and KOI7 are used only as terminal character sets, so they only
  584. ;need to be readable.  So since we aren't worried about keyboarding, we
  585. ;only need five tables:
  586. ;
  587. ; CP866I -> L/C    (for file transfer) 
  588. ; L/C    -> CP866I (for file transfer) 
  589. ; L/C    -> CP866R (terminal emulation)
  590. ; KOI8   -> CP866R (terminal emulation)
  591. ; KOI7   -> CP866R (terminal emulation)
  592. ;
  593. ; L/C   CP866R  CP866I   KOI8   KOI7    UNICODE 
  594. ;  0       0       0       0      0      0x0000 
  595. ;  1       1       1       1      1      0x0001 
  596. ;  2       2       2       2      2      0x0002 
  597. ;  3       3       3       3      3      0x0003 
  598. ;  4       4       4       4      4      0x0004 
  599. ;  5       5       5       5      5      0x0005 
  600. ;  6       6       6       6      6      0x0006 
  601. ;  7       7       7       7      7      0x0007 
  602. ;  8       8       8       8      8      0x0008 
  603. ;  9       9       9       9      9      0x0009 
  604. ; 10      10      10      10     10      0x000A 
  605. ; 11      11      11      11     11      0x000B 
  606. ; 12      12      12      12     12      0x000C 
  607. ; 13      13      13      13     13      0x000D 
  608. ; 14      14      14      14     14      0x000E 
  609. ; 15      15      15      15     15      0x000F 
  610. ; 16      16      16      16     16      0x0010 
  611. ; 17      17      17      17     17      0x0011 
  612. ; 18      18      18      18     18      0x0012 
  613. ; 19      19      19      19     19      0x0013 
  614. ; 20      20      20      20     20      0x0014 
  615. ; 21      21      21      21     21      0x0015 
  616. ; 22      22      22      22     22      0x0016 
  617. ; 23      23      23      23     23      0x0017 
  618. ; 24      24      24      24     24      0x0018 
  619. ; 25      25      25      25     25      0x0019 
  620. ; 26      26      26      26     26      0x001A 
  621. ; 27      27      27      27     27      0x001B 
  622. ; 28      28      28      28     28      0x001C 
  623. ; 29      29      29      29     29      0x001D 
  624. ; 30      30      30      30     30      0x001E 
  625. ; 31      31      31      31     31      0x001F 
  626. ; 32      32      32      32     32      0x0020    SPACE 
  627. ; 33      33      33      33     33      0x0021    EXCLAMATION MARK 
  628. ; 34      34      34      34     34      0x0022    QUOTATION MARK 
  629. ; 35      35      35      35     35      0x0023    NUMBER SIGN 
  630. ; 36      36      36      36     36      0x0024    DOLLAR SIGN 
  631. ; 37      37      37      37     37      0x0025    PERCENT SIGN 
  632. ; 38      38      38      38     38      0x0026    AMPERSAND 
  633. ; 39      39      39      39     39      0x0027    APOSTROPHE 
  634. ; 40      40      40      40     40      0x0028    LEFT PARENTHESIS 
  635. ; 41      41      41      41     41      0x0029    RIGHT PARENTHESIS 
  636. ; 42      42      42      42     42      0x002A    ASTERISK 
  637. ; 43      43      43      43     43      0x002B    PLUS SIGN 
  638. ; 44      44      44      44     44      0x002C    COMMA 
  639. ; 45      45      45      45     45      0x002D    HYPHEN, MINUS SIGN 
  640. ; 46      46      46      46     46      0x002E    PERIOD, FULL STOP 
  641. ; 47      47      47      47     47      0x002F    SOLIDUS, SLASH 
  642. ; 48      48      48      48     48      0x0030    DIGIT ZERO 
  643. ; 49      49      49      49     49      0x0031    DIGIT ONE 
  644. ; 50      50      50      50     50      0x0032    DIGIT TWO 
  645. ; 51      51      51      51     51      0x0033    DIGIT THREE 
  646. ; 52      52      52      52     52      0x0034    DIGIT FOUR 
  647. ; 53      53      53      53     53      0x0035    DIGIT FIVE 
  648. ; 54      54      54      54     54      0x0036    DIGIT SIX 
  649. ; 55      55      55      55     55      0x0037    DIGIT SEVEN 
  650. ; 56      56      56      56     56      0x0038    DIGIT EIGHT 
  651. ; 57      57      57      57     57      0x0039    DIGIT NINE 
  652. ; 58      58      58      58     58      0x003A    COLON 
  653. ; 59      59      59      59     59      0x003B    SEMICOLON 
  654. ; 60      60      60      60     60      0x003C    LEFT ANGLE BRACKET 
  655. ; 61      61      61      61     61      0x003D    EQUALS SIGN 
  656. ; 62      62      62      62     62      0x003E    RIGHT ANGLE BRACKET 
  657. ; 63      63      63      63     63      0x003F    QUESTION MARK 
  658. ; 64      64      64      64     64      0x0040    COMMERCIAL AT SIGN 
  659. ; 65      65      65      65     65      0x0041    CAPITAL LETTER A 
  660. ; 66      66      66      66     66      0x0042    CAPITAL LETTER B 
  661. ; 67      67      67      67     67      0x0043    CAPITAL LETTER C 
  662. ; 68      68      68      68     68      0x0044    CAPITAL LETTER D 
  663. ; 69      69      69      69     69      0x0045    CAPITAL LETTER E 
  664. ; 70      70      70      70     70      0x0046    CAPITAL LETTER F 
  665. ; 71      71      71      71     71      0x0047    CAPITAL LETTER G 
  666. ; 72      72      72      72     72      0x0048    CAPITAL LETTER H 
  667. ; 73      73      73      73     73      0x0049    CAPITAL LETTER I 
  668. ; 74      74      74      74     74      0x004A    CAPITAL LETTER J 
  669. ; 75      75      75      75     75      0x004B    CAPITAL LETTER K 
  670. ; 76      76      76      76     76      0x004C    CAPITAL LETTER L 
  671. ; 77      77      77      77     77      0x004D    CAPITAL LETTER M 
  672. ; 78      78      78      78     78      0x004E    CAPITAL LETTER N 
  673. ; 79      79      79      79     79      0x004F    CAPITAL LETTER O 
  674. ; 80      80      80      80     80      0x0050    CAPITAL LETTER P 
  675. ; 81      81      81      81     81      0x0051    CAPITAL LETTER Q 
  676. ; 82      82      82      82     82      0x0052    CAPITAL LETTER R 
  677. ; 83      83      83      83     83      0x0053    CAPITAL LETTER S 
  678. ; 84      84      84      84     84      0x0054    CAPITAL LETTER T 
  679. ; 85      85      85      85     85      0x0055    CAPITAL LETTER U 
  680. ; 86      86      86      86     86      0x0056    CAPITAL LETTER V 
  681. ; 87      87      87      87     87      0x0057    CAPITAL LETTER W 
  682. ; 88      88      88      88     88      0x0058    CAPITAL LETTER X 
  683. ; 89      89      89      89     89      0x0059    CAPITAL LETTER Y 
  684. ; 90      90      90      90     90      0x005A    CAPITAL LETTER Z 
  685. ; 91      91      91      91     91      0x005B    LEFT SQUARE BRACKET 
  686. ; 92      92      92      92     92      0x005C    REVERSE SOLIDUS, BACKSLASH 
  687. ; 93      93      93      93     93      0x005D    RIGHT SQUARE BRACKET 
  688. ; 94      94      94      94     94      0x005E    CIRCUMFLEX ACCENT 
  689. ; 95      95      95      95     95      0x005F    LOW LINE, UNDERLINE 
  690. ; 96      96      96      96     64      0x0060    GRAVE ACCENT 
  691. ; 97      97      97      97     65      0x0061    SMALL LETTER a 
  692. ; 98      98      98      98     66      0x0062    SMALL LETTER b 
  693. ; 99      99      99      99     67      0x0063    SMALL LETTER c 
  694. ;100     100     100     100     68      0x0064    SMALL LETTER d 
  695. ;101     101     101     101     69      0x0065    SMALL LETTER e 
  696. ;102     102     102     102     70      0x0066    SMALL LETTER f 
  697. ;103     103     103     103     71      0x0067    SMALL LETTER g 
  698. ;104     104     104     104     72      0x0068    SMALL LETTER h 
  699. ;105     105     105     105     73      0x0069    SMALL LETTER i 
  700. ;106     106     106     106     74      0x006A    SMALL LETTER j 
  701. ;107     107     107     107     75      0x006B    SMALL LETTER k 
  702. ;108     108     108     108     76      0x006C    SMALL LETTER l 
  703. ;109     109     109     109     77      0x006D    SMALL LETTER m 
  704. ;110     110     110     110     78      0x006E    SMALL LETTER n 
  705. ;111     111     111     111     79      0x006F    SMALL LETTER o 
  706. ;112     112     112     112     80      0x0070    SMALL LETTER p 
  707. ;113     113     113     113     81      0x0071    SMALL LETTER q 
  708. ;114     114     114     114     82      0x0072    SMALL LETTER r 
  709. ;115     115     115     115     83      0x0073    SMALL LETTER s 
  710. ;116     116     116     116     84      0x0074    SMALL LETTER t 
  711. ;117     117     117     117     85      0x0075    SMALL LETTER u 
  712. ;118     118     118     118     86      0x0076    SMALL LETTER v 
  713. ;119     119     119     119     87      0x0077    SMALL LETTER w 
  714. ;120     120     120     120     88      0x0078    SMALL LETTER x 
  715. ;121     121     121     121     89      0x0079    SMALL LETTER y 
  716. ;122     122     122     122     90      0x007A    SMALL LETTER z 
  717. ;123     123     123     123     91      0x007B    LEFT BRACE 
  718. ;124     124     124     124     92      0x007C    VERTICAL BAR 
  719. ;125     125     125     125     93      0x007D    RIGHT BRACE 
  720. ;126     126     126     126     94      0x007E    TILDE 
  721. ;127     127     127     127    127      0x00A0    RUBOUT, DELETE 
  722. ;128     196     196     128      0 
  723. ;129     179     179     129      1 
  724. ;130     192     192     130      2 
  725. ;131     217     217     131      3 
  726. ;132     191     191     132      4 
  727. ;133     218     218     133      5 
  728. ;134     195     195     134      6 
  729. ;135     193     193     135      7 
  730. ;136     180     180     136      8 
  731. ;137     194     194     137      9 
  732. ;138     197     197     138     10 
  733. ;139     176     176     139     11 
  734. ;140     177     177     140     12 
  735. ;141     178     178     141     13 
  736. ;142     211     211     142     14 
  737. ;143     216     216     143     15 
  738. ;144     205     205     144     16 
  739. ;145     186     186     145     17 
  740. ;146     200     200     146     18 
  741. ;147     188     188     147     19 
  742. ;148     187     187     148     20 
  743. ;149     201     201     149     21 
  744. ;150     204     204     150     22 
  745. ;151     202     202     151     23 
  746. ;152     185     185     152     24 
  747. ;153     203     203     153     25 
  748. ;154     206     206     154     26 
  749. ;155     223     223     155     27 
  750. ;156     220     220     156     28 
  751. ;157     219     219     157     29 
  752. ;158     254     254     158     30 
  753. ;159     253     253     159     31             
  754. ;160     255     255     UNK     32      0x0401    No-break space 
  755. ;161     240     240     229    101      0x0402    Cyrillic Io 
  756. ;162     132     208     UNK    UNK      0x0403    Serbocroation Dje 
  757. ;163     131     207     UNK    UNK      0x0404    Macedonian Gje 
  758. ;164     242     242     UNK    UNK      0x0405    Ukranian Ie 
  759. ;165      83     189     83      83      0x0406    Macedonian Dze 
  760. ;166      73     183      73     73      0x0407    Cyrillic I 
  761. ;167     244     244     73      73      0x0408    Ukranian Yi 
  762. ;168      74     184      74     74      0x0409    Cyrillic Je 
  763. ;169     139     212     UNK    UNK      0x040A    Cyrillic Lje 
  764. ;170     141     213     UNK    UNK      0x040B    Cyrillic Nje 
  765. ;171     151     214     UNK    UNK      0x040C    Serbocroation Chje 
  766. ;172     138     210     235    107      0x00AD    Macedonian Kje 
  767. ;173      45     182     UNK     45      0x040E    Soft hyphen 
  768. ;174     246     246     245    117      0x040F    Bielorussian Short U 
  769. ;175     135     209     UNK    UNK      0x0410    Cyrillic Dze 
  770. ;176     128     128     225     97      0x0411    Cyrillic A 
  771. ;177     129     129     226     98      0x0412    Cyrillic Be 
  772. ;178     130     130     247    119      0x0413    Cyrillic Ve 
  773. ;179     131     131     231    103      0x0414    Cyrillic Ghe 
  774. ;180     132     132     228    100      0x0415    Cyrillic De 
  775. ;181     133     133     229    101      0x0416    Cyrillic Ie 
  776. ;182     134     134     246    118      0x0417    Cyrillic Zhe 
  777. ;183     135     135     250    122      0x0418    Cyrillic Ze 
  778. ;184     136     136     233    105      0x0419    Cyrillic I 
  779. ;185     137     137     234    106      0x041A    Cyrillic Short I 
  780. ;186     138     138     235    107      0x041B    Cyrillic Ka 
  781. ;187     139     139     236    108      0x041C    Cyrillic El 
  782. ;188     140     140     237    109      0x041D    Cyrillic Em 
  783. ;189     141     141     238    110      0x041E    Cyrillic En 
  784. ;190     142     142     239    111      0x041F    Cyrillic O 
  785. ;191     143     143     240    112      0x0420    Cyrillic Pe 
  786. ;192     144     144     242    114      0x0421    Cyrillic Er 
  787. ;193     145     145     243    115      0x0422    Cyrillic Es 
  788. ;194     146     146     244    116      0x0423    Cyrillic Te 
  789. ;195     147     147     245    117      0x0424    Cyrillic U 
  790. ;196     148     148     230    102      0x0425    Cyrillic Ef 
  791. ;197     149     149     232    104      0x0426    Cyrillic Ha 
  792. ;198     150     150     227     99      0x0427    Cyrillic Tse 
  793. ;199     151     151     254    126      0x0428    Cyrillic Che 
  794. ;200     152     152     251    123      0x0429    Cyrillic Sha 
  795. ;201     153     153     253    125      0x042A    Cyrillic Shcha 
  796. ;202     154     154     255     39      0x042B    Cyrillic Hard Sign 
  797. ;203     155     155     249    121      0x042C    Cyrillic Yeri 
  798. ;204     156     156     248    120      0x042D    Cyrillic Soft Sign 
  799. ;205     157     157     252    124      0x042E    Cyrillic E 
  800. ;206     158     158     224     96      0x042F    Cyrillic Yu 
  801. ;207     159     159     241    113      0x0430    Cyrillic Ya 
  802. ;208     160     160     193     97      0x0431    Cyrillic a 
  803. ;209     161     161     194     98      0x0432    Cyrillic be 
  804. ;210     162     162     215    119      0x0433    Cyrillic ve 
  805. ;211     163     163     199    103      0x0434    Cyrillic ghe 
  806. ;212     164     164     196    100      0x0435    Cyrillic de 
  807. ;213     165     165     197    101      0x0436    Cyrillic ie 
  808. ;214     166     166     214    118      0x0437    Cyrillic zhe 
  809. ;215     167     167     218    122      0x0438    Cyrillic ze 
  810. ;216     168     168     201    105      0x0439    Cyrillic i 
  811. ;217     169     169     202    106      0x043A    Cyrillic Short i 
  812. ;218     170     170     203    107      0x043B    Cyrillic ka 
  813. ;219     171     171     204    108      0x043C    Cyrillic el 
  814. ;220     172     172     205    109      0x043D    Cyrillic em 
  815. ;221     173     173     206    110      0x043E    Cyrillic en 
  816. ;222     174     174     207    111      0x043F    Cyrillic o 
  817. ;223     175     175     208    112      0x0440    Cyrillic pe 
  818. ;224     224     224     210    114      0x0441    Cyrillic er 
  819. ;225     225     225     211    115      0x0442    Cyrillic es 
  820. ;226     226     226     212    116      0x0443    Cyrillic te 
  821. ;227     227     227     213    117      0x0444    Cyrillic u 
  822. ;228     228     228     198    102      0x0445    Cyrillic ef 
  823. ;229     229     229     200    104      0x0446    Cyrillic ha 
  824. ;230     230     230     195     99      0x0447    Cyrillic tse 
  825. ;231     231     231     222    126      0x0448    Cyrillic che 
  826. ;232     232     232     219    123      0x0449    Cyrillic sha 
  827. ;233     233     233     221    125      0x044A    Cyrillic shcha 
  828. ;234     234     234     223     39      0x044B    Cyrillic hard sign 
  829. ;235     235     235     217    121      0x044C    Cyrillic yeri 
  830. ;236     236     236     216    120      0x044D    Cyrillic soft sign 
  831. ;237     237     237     220    124      0x044E    Cyrillic e 
  832. ;238     238     238     192     96      0x044F    Cyrillic yu 
  833. ;239     239     239     209    113      0x2116    Cyrillic ya 
  834. ;240     252     252     UNK    UNK      0x0451    Number Acronym 
  835. ;241     241     241     197     10      0x0452    Cyrillic io 
  836. ;242     164     221     UNK    UNK      0x0453    Serbocroation dje 
  837. ;243     163     215     UNK    UNK      0x0454    Macedonian gje 
  838. ;244     243     243     UNK    UNK      0x0455    Ukranian ie 
  839. ;245     115     199     115     83      0x0456    Macedonian dze 
  840. ;246     105     190     105     73      0x0457    Cyrillic i 
  841. ;247     245     245     105     73      0x0458    Ukranian yi 
  842. ;248     106     198     106     74      0x0459    Cyrillic je 
  843. ;249     171     249     UNK    UNK      0x045A    Cyrillic lje 
  844. ;250     173     250     UNK    UNK      0x045B    Cyrillic nje 
  845. ;251     231     251     UNK    UNK      0x045C    Serbocroatian chje 
  846. ;252     170     248     203    107      0x00A7    Macedonian kje 
  847. ;253     181     181     UNK    UNK      0x045E    Paragraph sign 
  848. ;254     247     247     213    117      0x045F    Bielorussian short u 
  849. ;255     167     222     UNK    UNK                Cyrillic dze 
  850.  
  851. code1    segment
  852.     extrn    isfile:far,decout:far, rfprep:far, rgetfile:far, newfn:near
  853. extrn malloc:far
  854.     assume    cs:code1
  855. code1    ends
  856.  
  857. code    segment
  858.     extrn    comnd:near
  859.     extrn    ermsg:near,clrfln:far,frpos:near,kbpr:near,perpr:near
  860.  
  861.     assume  cs:code,ds:data,es:nothing
  862.  
  863. ; Set DS:BX to the ISO Latin-1 table appropriate to the
  864. ; currently active Code Page. Defaults to CP437 if no CP found.
  865. LATIN1    proc    near
  866.     push    ax
  867.     mov    ax,seg flags
  868.     mov    DS,ax
  869.     mov    ax,flags.chrset        ; in segment data
  870.     mov    bx,seg L1cp437
  871.     mov    DS,bx            ; set returned DS to table
  872.     mov    bx,offset L1cp437    ; assume CP437
  873.     cmp    ax,437            ; current Code Page is 437?
  874.     je    latin1x            ; e = yes
  875.     mov    bx,offset L1cp850    ; assume CP850
  876.     cmp    ax,850            ; current Code Page is 850?
  877.     je    latin1x            ; e = yes
  878.     mov    bx,offset L1cp860    ; assume CP860
  879.     cmp    ax,860            ; current Code Page is 860?
  880.     je    latin1x            ; e = yes
  881.     mov    bx,offset L1cp861    ; assume CP861
  882.     cmp    ax,861            ; current Code Page is 861?
  883.     je    latin1x            ; e = yes
  884.     mov    bx,offset L2cp852    ; assume CP852
  885.     cmp    ax,852            ; current Code Page is 852?
  886.     je    latin1x            ; e = yes
  887.     mov    bx,offset HIcp862    ; assume CP862
  888.     cmp    ax,862            ; current Code Page is 862?
  889.     je    latin1x            ; e = yes
  890.     mov    bx,offset L1cp863    ; assume CP863
  891.     cmp    ax,863            ; current Code Page is 863?
  892.     je    latin1x            ; e = yes
  893.     mov    bx,offset L1cp865    ; assume CP865
  894.     cmp    ax,865            ; current Code Page is 865?
  895.     je    latin1x            ; e = yes
  896.     mov    bx,offset L5cp866    ; assume CP866
  897.     cmp    ax,866            ; current Code Page is 866?
  898.     je    latin1x            ; e = yes
  899.     mov    bx,offset L1cp437    ; default to CP437
  900. latin1x:pop    ax
  901.     ret
  902. LATIN1    endp
  903.  
  904. ; Call after LATIN1. Revise DS:BX to point to invertible tables rather than
  905. ; readable translation tables. Does not change DS.
  906. latininv proc    near
  907.     push    ax
  908.     push    ds
  909.     mov    ax,seg trans
  910.     mov    ds,ax
  911.     cmp    trans.xchri,0        ; readable (vs invertible)?
  912.     pop    ds
  913.     pop    ax
  914.     je    latinvx            ; e = yes, do nothing
  915.     cmp    bx,offset L1cp437    ; this table in use?
  916.     jne    latinv1            ; ne = no
  917.     mov    bx,offset iL1cp437    ; use invertible instead
  918.     jmp    short latinvx
  919. latinv1:cmp    bx,offset L1cp850    ; this table in use?
  920.     jne    latinv2            ; ne = no
  921.     mov    bx,offset iL1cp850    ; use invertible instead
  922.     jmp    short latinvx
  923. latinv2:cmp    bx,offset L1cp861    ; this table?
  924.     jne    latinvx            ; ne = no
  925.     mov    bx,offset iL1cp861    ; use invertible instead
  926. latinvx:ret
  927. latininv endp
  928.  
  929. ; Set DS:BX to the table for Code Page to ISO 8859-1 Latin1/Latin5
  930. cplatin proc    near
  931.     push    ax
  932.     mov    ax,seg flags
  933.     mov    DS,ax
  934.     mov    ax,flags.chrset
  935.     mov    bx,seg cp437L1
  936.     mov    DS,bx            ; set returned DS to table
  937.     mov    bx,offset cp437L1    ; assume CP437
  938.     cmp    ax,437            ; current Code Page is 437?
  939.     je    cplatx            ; e = yes
  940.     mov    bx,offset cp850L1    ; assume CP850
  941.     cmp    ax,850            ; current Code Page is 850?
  942.     je    cplatx            ; e = yes
  943.     mov    bx,offset cp860L1    ; assume CP860
  944.     cmp    ax,860            ; current Code Page is 860?
  945.     je    cplatx            ; e = yes
  946.     mov    bx,offset cp861L1    ; assume CP861
  947.     cmp    ax,861            ; current Code Page is 861?
  948.     je    cplatx            ; e = yes
  949.     mov    bx,offset cp852L2    ; assume CP852
  950.     cmp    ax,852            ; current Code Page is 852?
  951.     je    cplatx            ; e = yes
  952.     mov    bx,offset cp862HI    ; assume CP862
  953.     cmp    ax,862            ; current Code Page is 862?
  954.     je    cplatx            ; e = yes
  955.     mov    bx,offset cp863L1    ; assume CP863
  956.     cmp    ax,863            ; current Code Page is 863?
  957.     je    cplatx            ; e = yes
  958.     mov    bx,offset cp865L1    ; assume CP865
  959.     cmp    ax,865            ; current Code Page is 865?
  960.     je    cplatx            ; e = yes
  961.     mov    bx,offset cp866L5    ; assume CP866 for LATIN5
  962.     cmp    ax,866            ; corrent Code Page is 866?
  963.     je    cplatx            ; e = yes
  964.     mov    bx,offset cp437L1    ; default to CP437
  965. cplatx:    pop    ax
  966.     ret
  967. cplatin endp
  968.  
  969. ; Call after CPLATIN. Revise DS:BX to point to invertible tables rather than
  970. ; readable translation tables.
  971. cpinvert proc    near
  972.     push    ds
  973.     push    ax
  974.     mov    ax,seg trans
  975.     mov    ds,ax
  976.     cmp    trans.xchri,0        ; readable (vs invertible)?
  977.     pop    ax
  978.     pop    ds
  979.     je    cpinverx        ; e = yes, do nothing
  980.     cmp    bx,offset cp437L1    ; this table in use?
  981.     jne    cpinver1        ; ne = no
  982.     mov    bx,offset icp437L1    ; use invertible instead
  983.     ret
  984. cpinver1:cmp    bx,offset cp850L1    ; this table in use?
  985.     jne    cpinver2        ; ne = no
  986.     mov    bx,offset icp850L1    ; use invertible instead
  987.     ret
  988. cpinver2:cmp    bx,offset cp861L1    ; this table in use?
  989.     jne    cpinverx        ; ne = no
  990.     mov    bx,offset icp861L1    ; use invertible instead
  991. cpinverx:ret
  992. cpinvert endp
  993.  
  994. ; Output the chars in a packet, called only by receiver code.
  995. ; Enter with SI equal to pktinfo structure pointer.
  996. PTCHR:    mov    decoutp,offset outbuf  ; routine to call when buffer gets full
  997.     jmp    short decode
  998.  
  999.  
  1000. ; Dodecoding.
  1001. ; Decode packet to buffer decbuf. Overflow of decbuf yields error ???
  1002. ; Modifies regs BX, CX.
  1003. ; Enter with SI equal to pktinfo structure pointer.
  1004. dodec    proc    near
  1005.     push    ax            ; save reg
  1006.     mov    ah,dblbyteflg        ; preserve state
  1007.     mov    al,dblbyte
  1008.     push    ax
  1009.     mov    al,shiftstate
  1010.     mov    ah,DLEseen
  1011.     push    ax
  1012.     mov    dblbyteflg,0        ; init decode as doubles
  1013.     mov    shiftstate,0        ; init shift states
  1014.     mov    DLEseen,0        ; init escape
  1015.     mov    decoutp,offset dnulr    ; routine to dump buffer (null)
  1016.     call    decode
  1017.     pop    ax
  1018.     mov    shiftstate,al        ; restore decoder state
  1019.     mov    DLEseen,ah
  1020.     pop    ax
  1021.     mov    dblbyteflg,ah
  1022.     mov    dblbyte,al
  1023.     push    bx
  1024.     mov    bx,dbufpnt        ; next char position
  1025.     mov    byte ptr [bx],0        ; null terminator
  1026.     pop    bx
  1027.      pop    ax
  1028.     ret
  1029. dodec    endp
  1030.  
  1031. dnulr:    mov    dbufpnt,di         ; point off end of buffer
  1032.     stc                ; fail if needs this
  1033.     ret                ; dummy buffer emptier
  1034.  
  1035. ; Enter with [si].datlen = length of data, [si].datadr = dw address of data,
  1036. ; DECOUTP = pointer to routine which writes output buffer
  1037. ; Returns DBUFPNT = pointer to output buffer address (offset part).
  1038. ; Trans.lshift is non-zero if locking shift encoding is active.
  1039. ; DLEseen is non-zero if a DLE char (Control-P) is decoded while locking shift
  1040. ; is active; under these circumstances DLE escapes DLE, SI, and SO to be
  1041. ; data characters. Under locking shift rules SO (Control-N) shifts high bit
  1042. ; data to non-high bit data (and we thus reverse this); SI (Control-O)
  1043. ; cancels SO.
  1044. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while
  1045. ; performing Japanese translation; dblbyte is the first byte of the pair.
  1046. ; All packets are decoded except I, S, and A types.
  1047. ; Flushes output buffer before returning.
  1048. ; Returns carry clear if success, otherwise carry set
  1049. decode    proc    near
  1050.     push    si
  1051.     push    di
  1052.     push    es
  1053.     push    dx
  1054.     push    ds
  1055.     pop    es
  1056.     cld                ; forward direction
  1057.     mov    dchrcnt,decbuflen    ; size of output buffer
  1058.     mov    dbufpnt,offset decbuf ; decoded data placed here pending output
  1059.     mov    decbuf,0        ; nothing written yet
  1060.     mov    cx,[si].datlen        ; length of source buffer data
  1061.     les    si,[si].datadr        ; source buffer address to es:[si]
  1062.     mov    di,dbufpnt        ; destination of data
  1063.     mov    bl,trans.squote        ; regular quote char
  1064.     xor    dh,dh            ; assume no quote char
  1065.     cmp    trans.ebquot,'N'    ; any 8-bit quoting?
  1066.     je    decod1            ; e = no quoting
  1067.     cmp    trans.ebquot,'Y'    ; or not doing it?
  1068.     je    decod1            ; e = no need to quote
  1069.     mov    dh,trans.ebquot        ; otherwise use 8-bit quote char
  1070.  
  1071. decod1:    mov    rptct,1            ; reset repeat count
  1072.     or    cx,cx            ; any more chars in source?
  1073.     jg    decod2            ; g = yes
  1074.     jmp    decod6            ; else, we're through
  1075. decod2:    mov    al,es:[si]        ; pick up a char
  1076.     inc    si
  1077.     dec    cx            ; count number left
  1078.     cmp    al,trans.rptq        ; repeat quote char?
  1079.     jne    dcod2a            ; ne = no, continue processing it
  1080.     mov    al,es:[si]        ; get the size
  1081.     inc    si
  1082.     dec    cx            ; modify buffer count
  1083.     sub    al,20H            ; make count numeric
  1084.     mov    rptct,al        ; remember how many repetitions
  1085.     mov    al,es:[si]        ; get the char to repeat
  1086.     inc    si
  1087.     dec    cx            ; modify buffer count
  1088.  
  1089. dcod2a:    xor    ah,ah            ; assume no 8-bit quote char
  1090.     or    dh,dh            ; using 8-bit quoting?
  1091.     jz    decod3            ; z = no
  1092.     cmp    al,dh            ; is this the 8-bit quot char?
  1093.     jne    decod3            ; ne = no
  1094.     mov    al,es:[si]        ; yes, get the real character
  1095.     inc    si
  1096.     dec    cx            ; decrement # chars in packet
  1097.     mov    ah,80H            ; turn on high bit
  1098. decod3:    cmp    al,bl            ; quote char?
  1099.     jne    decod4            ; ne = no, proceed
  1100.     mov    al,es:[si]        ; get the quoted character
  1101.     inc    si
  1102.     dec    cx            ; decrement # of chars in packet
  1103.     or    ah,al            ; save parity (combine with prefix)
  1104.     and    ax,807fh        ; only parity in ah, remove it in al
  1105.     cmp    al,bl            ; quote char?
  1106.     je    decod4            ; e = yes, just go write it out
  1107.     cmp    al,dh            ; 8-bit quote char?
  1108.     je    decod4            ; e = yes, just go write it out
  1109.     cmp    trans.rptq,0        ; disabled repeat quoting?
  1110.     je    decod3a            ; e = yes, disabled
  1111.     cmp    al,trans.rptq        ; repeat quote character?
  1112.     je    decod4            ; e = yes, just write it out
  1113. decod3a:cmp    al,3fh            ; char less than '?' ?
  1114.     jb    decod4            ; b = yes; leave it intact
  1115.     cmp    al,5fh            ; char greater than '_' ?
  1116.     ja    decod4            ; a = yes; leave it alone
  1117.     add    al,40H            ; make it a control char again
  1118.     and    al,7FH            ; modulo 128 (includes DEL)
  1119. decod4:    xor    ah,shiftstate        ; modify high bit by shiftstate
  1120.         or    al,ah            ; or in parity
  1121.  
  1122.     cmp    trans.lshift,lock_disable ; locking shift disabled?
  1123.     je    decod5            ; e = yes
  1124.     mov    ah,al
  1125.     xor    ah,shiftstate        ; adjust high bit by shift state
  1126.     cmp    ah,DLE            ; DLE?
  1127.     jne    dcod4c            ; ne = no
  1128.     cmp    DLEseen,0        ; has DLE been escaped (by DLE)?
  1129.     je    dcod4b            ; e = no, make this the escape
  1130.     mov    DLEseen,0        ; unescape now
  1131.     jmp    short decod5        ; process the literal DLE
  1132.                     ; handle repeat counted DLE's
  1133. dcod4b:    shr    rptct,1            ; divide by two, carry has lsb
  1134.     rcl    DLEseen,1        ; pickup carry bit if odd number
  1135.     jmp    short decod5        ; write the DLE's
  1136.  
  1137. dcod4c:    cmp    DLEseen,0        ; DLE prefix seen?
  1138.     mov    DLEseen,0        ; clear it now too
  1139.     jne    decod5            ; ne = yes, prefixed, do literal
  1140.     cmp    ah,SIchar        ; SI?
  1141.     jne    dcod4d            ; ne = no
  1142.     mov    shiftstate,0        ; say exiting shifted state
  1143.     jmp    decod1            ; nothing to write
  1144. dcod4d:    cmp    ah,SOchar        ; SO?
  1145.     jne    decod5            ; ne = no
  1146.     mov    shiftstate,80h        ; say entering shifted state
  1147.     jmp    decod1            ; nothing to write
  1148.  
  1149. decod5:    push    cx
  1150.     mov    cl,rptct        ; repeat count
  1151.     xor    ch,ch
  1152.     or    cl,cl
  1153.     jle    decod5c            ; le = nothing to do (94 max)
  1154.     cmp    cx,dchrcnt        ; needed vs space available
  1155.     jbe    decod5a            ; be = enough space for rptct chars
  1156.     mov    cx,dchrcnt        ; insufficient space, do dchrcnt
  1157. decod5a:sub    rptct,cl        ; reduce number left to be written
  1158.     sub    dchrcnt,cx        ; reduce output free space
  1159.     pushf                ; save sub status flags
  1160.     shr    cx,1
  1161.     jnc    decod5b            ; nc = an even number
  1162.     mov    [di],al            ; store the odd byte
  1163.     inc    di
  1164.     jcxz    decod5d            ; z = nothing else to write
  1165. decod5b:mov    ah,al            ; make a copy for word writes
  1166.     push    bx            ; source is es:[si], dest is ds:[di]
  1167.     push    es            ; save and swap ds and es
  1168.     push    ds
  1169.     mov    bx,es
  1170.     pop    es            ; old ds to es
  1171.     push    ds            ; restore
  1172.     mov    ds,bx            ; old es to ds
  1173.     rep    stosw            ; store cx words
  1174.     pop    ds
  1175.     pop    es
  1176.     pop    bx
  1177. decod5d:popf                ; recover flags from sub dchrcnt,cx
  1178.     jg    decod5c            ; g = space remaining in output buffer
  1179.     push    dx            ; flush output buffer
  1180.     push    bx
  1181.     push    ax            ; save the char
  1182.     push    es
  1183.     call    decoutp            ; output the buffer
  1184.     pop    es
  1185.     pop    ax            ; recover repeated char
  1186.     pop    bx
  1187.     pop    dx
  1188.     jc    decod7            ; c = error if disk is full
  1189.     mov    di,dbufpnt
  1190.     pop    cx
  1191.     jmp    short decod5        ; see if more chars need be written
  1192. decod5c:pop    cx            ; recover main loop counter
  1193.     jmp    decod1            ; get next source character
  1194.     
  1195. decod6:    mov    dbufpnt,di            ; flush buffer before exiting decode
  1196.     push    cx
  1197.     push    es
  1198.     call    decoutp            ; flush output buffer before final ret
  1199.     pop    es
  1200.  
  1201.     test    flags.remflg,dserial+dquiet ; serial/quiet mode display?
  1202.     jnz    decod7            ; nz = yes, skip kbyte and % displays
  1203.     cmp    decoutp,offset outbuf    ; decoding to disk?
  1204.     jne    decod7            ; ne = no
  1205.     cmp    flags.xflg,0        ; receiving to screen?
  1206.     jne    decod7            ; ne = yes
  1207.     call    kbpr            ; display kilobytes done
  1208.     call    perpr            ; display percentage done
  1209.  
  1210. decod7:    pop    cx
  1211.     pop    dx
  1212.     pop    es
  1213.     pop    di
  1214.     pop    si
  1215.     ret                ; return successfully if carry clear
  1216. decode    endp
  1217.  
  1218. outbuf    proc    near            ; output decbuf, reset bufpnt & chrcnt
  1219.     mov    cx,decbuflen        ; get full size of buffer
  1220.     sub    cx,dchrcnt        ; minus space remaining = # to write
  1221.     jg    outbu2            ; g = something to do
  1222.     jmp    outbf1
  1223. outbu2:    mov    dx,offset decbuf    ; address of buffer
  1224.     cmp    trans.xtype,1        ; File Type Binary?
  1225.     je    outbu5            ; e = yes, no translation
  1226.     cmp    flags.destflg,dest_disk    ; disk destination?
  1227.     je    outbu5            ; e = yes, DOS will do it
  1228.     cmp    flags.eofcz,0        ; end on Control-Z?
  1229.     je    outbu5            ; e = no
  1230.     push    cx            ; else map Control-Z to space
  1231.     push    di
  1232.     mov    di,seg decbuf
  1233.     mov    es,di            ; data to es
  1234.     mov    di,dx            ; scan buffer es:di, cx chars worth
  1235.     mov    al,ctlz            ; look for Control-Z
  1236.     cld
  1237. outbu3:    repne    scasb
  1238.     jne    outbu4            ; ne = found no Control-Z's
  1239.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  1240.     jcxz    outbu4            ; z = examined all chars
  1241.     jmp    short outbu3        ; until examined everything
  1242. outbu4:    pop    di
  1243.     pop    cx
  1244.                     ; Character set translation section
  1245. outbu5:    cmp    trans.xtype,1        ; File Type Binary?
  1246.     je    outbu7            ; e = yes, no translation
  1247.     cmp    trans.xchset,xfr_xparent ; Transfer Transparent?
  1248.     je    outbu7            ; e = yes, no translation
  1249.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1250.     jne    outbu5a            ; ne = no
  1251.     call    jpnwrite        ; do special decoding
  1252.     jmp    outbu7
  1253. outbu5a:push    cx
  1254.     push    di
  1255.     push    es
  1256.     PUSH    DS
  1257.     call    latin1            ; set DS:BX to xfr char set to CP table
  1258.     call    latininv        ; select invertable or readable set
  1259.     mov    di,seg decbuf
  1260.     mov    es,di
  1261.     mov    di,offset decbuf    ; scan this buffer
  1262.     cld
  1263. outbu6:    mov    al,es:[di]        ; get a char, keep pointer fixed
  1264.     test    al,80h            ; GRight?
  1265.     jnz    outbu6a            ; nz = yes
  1266.     cmp    bx,offset iL1cp437    ; using invertable Latin1 to CP437?
  1267.     jne    outbu6c            ; ne = no
  1268.     cmp    ah,127            ; 127 goes to 28?
  1269.     jne    outbu6e            ; ne = no
  1270.     mov    al,28            ; 127 to 28
  1271.     jmp    short outbu6b
  1272. outbu6e:cmp    al,21            ; special case?
  1273.     ja    outbu6b            ; a = no
  1274.     cmp    al,20            ; special case?
  1275.     jb    outbu6b            ; b = no
  1276.     mov    ah,al
  1277.     mov    al,244            ; 20 to 244
  1278.     cmp    ah,21            ; special case?
  1279.     jne    outbu6b            ; ne = no
  1280.     mov    al,245            ; preset one answer
  1281.     je    outbu6b            ; e = yes, 21 to 245
  1282.     mov    al,244            ; 22 to 244
  1283.     jmp    short outbu6b
  1284. outbu6c:cmp    bx,offset iL1cp850    ; using invertible Latin1 to CP850?
  1285.     jne    outbu6b            ; ne = no
  1286.     cmp    al,26            ; special case?
  1287.     jne    outbu6d            ; ne = no
  1288.     mov    al,127            ; 26 to 127
  1289.     jmp    outbu6b
  1290. outbu6d:cmp    al,127            ; special case?
  1291.     jne    outbu6b            ; ne = no
  1292.     mov    al,28            ; 127 to 28
  1293.     jmp    short outbu6b
  1294. outbu6a:and    al,not 80h        ; strip high bit
  1295.     xlatb                ; translate via bx table
  1296. outbu6b:stosb                ; store char
  1297.     loop    outbu6            ; do all concerned
  1298.     POP    DS
  1299.     pop    es
  1300.     pop    di
  1301.     pop    cx
  1302.  
  1303. outbu7:    push    bx
  1304.     mov    bx,diskio.handle    ; file handle
  1305.     or    bx,bx
  1306.     jle    outbf0            ; le = illegal handle, fail
  1307.     mov    ah,write2        ; write cx bytes from DS:DX
  1308.     int    dos
  1309.     pop    bx
  1310.     jc    outbf0            ; c set means writing error
  1311.     cmp    trans.xcrc,0        ; do transfer CRC?
  1312.     je    outbf7a            ; e = no
  1313.     push    cx
  1314.     mov    cx,ax            ; count to crc
  1315.     call    crc            ; compute CRC-16
  1316.     pop    cx
  1317. outbf7a:cmp    ax,cx            ; did we write all the bytes?
  1318.     je    outbf1            ; e = yes
  1319.     push    bx
  1320.     mov    bx,offset decbuf
  1321.     add    bx,ax            ; look at break character
  1322.     cmp    byte ptr [bx],ctlz    ; ended on Control-Z?
  1323.     pop    bx
  1324.     je    outbf1            ; e = yes, say no error
  1325.  
  1326. outbf0: mov    dx,offset erms13    ; Error writing device
  1327.     cmp    flags.xflg,0        ; writing to screen?
  1328.     jne    outbf0a            ; ne = yes
  1329.     cmp    flags.destflg,dest_printer ; writing to printer?
  1330.     jne    outbf0a            ; ne = no
  1331.     mov    dx,offset ermes9    ; Printer not ready message
  1332. outbf0a:call    ermsg
  1333.     stc                ; return failure
  1334.     ret
  1335.  
  1336. outbf1:    add    tfilsz,cx        ; count received chars
  1337.     adc    tfilsz+2,0
  1338.     add    fsta.frbyte,cx
  1339.     adc    fsta.frbyte+2,0
  1340.     mov    dbufpnt,offset decbuf    ; address for beginning
  1341.     mov    dchrcnt,decbuflen    ; size of empty buffer
  1342.     clc                ; return success
  1343.     ret
  1344. outbuf    endp
  1345.  
  1346. ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp)
  1347. ; Reread buffer decbuf to convert from transfer character set
  1348. ; Japanese-EUC into Shift-JIS (Code Page 932). Double char translation state
  1349. ; is maintained across file buffers. Init dblbyte to 0 before each new file.
  1350. ; Returns registers
  1351. ;    cx      number of bytes written in the buffer
  1352. ;    dx      address of the output buffer
  1353. ;            this points decbuf or decbuf-1, depending on dblbyteflg
  1354. ; Output is otherwise written over the input. [rewritten by jrd]
  1355. jpnwrite proc    near            ; [HF] write Japanese to file
  1356.     push    si            ; decbuf is read/written
  1357.     push    di            ; cx has incoming/outgoing byte count
  1358.     push    bx            ; dblbyte has earlier first byte
  1359.     push    es            ; dblbyteflg is state from prev call
  1360.     mov    dx,ds
  1361.     mov    es,dx
  1362.     cld                ; restore state from previous call
  1363.     mov    dl,dblbyteflg        ; state, non-zero if doing second byte
  1364.     mov    ah,dblbyte        ;  and first byte from previous read
  1365.     mov    si,offset decbuf    ; read/write this buffer
  1366.     mov    di,si            ; set the address for write
  1367.     mov    bx,si            ; save for computing output buf length
  1368.     or    dl,dl            ; carry-in of a double byte char?
  1369.     jz    jpnwri1            ; z = no
  1370.     dec    di            ; start output one byte before decbuf
  1371.     dec    bx            ; adjust the start address
  1372. jpnwri1:lodsb                ; get a byte
  1373.     or    dl,dl            ; processing 2nd byte of a pair?
  1374.     jnz    jpnwri3            ; nz = yes, do second byte processor
  1375.                     ; first byte processor
  1376.     cmp    al,80h            ; 8th bit on?
  1377.     jb    jpnwri5            ; b = no, this is a single char
  1378.     cmp    al,8eh            ; JIS X 0201 Katakana prefix?
  1379.     je    jpnwri2            ; e = yes, is first of two chars
  1380.     cmp    al,0a1h            ; JIS X 0208 Kanji ?
  1381.     jb    jpnwri5            ; b = no, is single char
  1382.     cmp    al,0feh
  1383.     ja    jpnwri5            ; a = no, is single char
  1384. jpnwri2:mov    ah,al            ; save first of two chars
  1385.     mov    dl,1            ; say need second char of pair
  1386.     jmp    short jpnwri6        ; read second byte
  1387.                     ; process second char of two byte pair
  1388. jpnwri3:cmp    ah,8eh            ; was first char JIS X 0201 Katakana?
  1389.     jne    jpnwri4            ; ne = no
  1390.     or    al,80h            ; make sure 8th bit is on
  1391.     jmp    short jpnwri5        ; write one char
  1392. jpnwri4:call    jpnxtof            ; xfer -> file char code conversion
  1393.     xchg    ah,al
  1394.     stosb                ; write first byte
  1395.     xchg    ah,al            ; and second byte
  1396. jpnwri5:stosb                ; write a char
  1397.     xor    dl,dl            ; clear multi-byte counter
  1398. jpnwri6:loop    jpnwri1
  1399.     mov    dblbyteflg,dl        ; save state info
  1400.     mov    dblbyte,ah        ; and the first byte of a pair
  1401.     sub    di,bx            ; find number of chars written
  1402.     mov    cx,di            ; return new count in CX
  1403.     mov    dx,bx            ; return new buffer address for write
  1404.     pop    es            ; can be decbuf - 1 if carry-in of dbl
  1405.     pop    bx
  1406.     pop    di
  1407.     pop    si
  1408.     clc
  1409.     ret
  1410. jpnwrite endp
  1411.  
  1412. ; Transfer character code (EUC) to file character code (Shift-JIS) converter.
  1413. ; input      AH: 1st byte of EUC code
  1414. ;            AL: 2nd byte of EUC code
  1415. ; output     AH: 1st byte of Shift-JIS code
  1416. ;            AL: 2nd byte of Shift-JIS code
  1417. ; From EUC to Shift-JIS
  1418. ;   code1 = (EUC_code1 & 0x7f);
  1419. ;   code2 = (EUC_code2 & 0x7f);
  1420. ;   if( code1 & 1)
  1421. ;     code2 += 0x1f;
  1422. ;   else
  1423. ;     code2 += 0x7d;
  1424. ;   if( code2 >= 0x7f ) code2++;
  1425. ;   code1 = ((code1 - 0x21) >> 1) + 0x81;
  1426. ;   if( code1 > 0x9f ) code1 += 0x40;
  1427. ;   [ fputc( code1, file ); fputc( code2, file ); ]
  1428. ;
  1429. jpnxtof    proc    near
  1430.     and    ax,7f7fh        ; mask both 8-th bits
  1431.     test    ah,1
  1432.     jz    jpnxtof1
  1433.     add    al,1fh
  1434.     jmp    short jpnxtof2
  1435. jpnxtof1:add    al,7dh
  1436. jpnxtof2:cmp    al,7fh
  1437.     jb    jpnxtof3
  1438.     inc    al
  1439. jpnxtof3:sub    ah,21h
  1440.     shr    ah,1
  1441.     add    ah,81h
  1442.     cmp    ah,9fh
  1443.     jbe    jpnxtof4
  1444.     add    ah,40h
  1445. jpnxtof4:ret
  1446. jpnxtof    endp
  1447.  
  1448. ; Get chars from file, encode them to pktinfo structure pointed to by si
  1449.  
  1450. gtchr    proc    near
  1451.     mov    [si].datlen,0        ; say no output data yet
  1452.     cmp    filflg,0        ; is there anything in the buffer?
  1453.     jne    gtchr0            ; ne = yes, use that material first
  1454.     call    inbuf            ; do initial read from source
  1455.     jc    gtchr1            ; c = no more chars, go return EOF
  1456. gtchr0:    mov    encinp,offset inbuf    ; buffer refiller routine
  1457.     call    encode
  1458.     test    flags.remflg,dserial+dquiet ; serial/quiet display mode?
  1459.     jnz    gtchr2            ; nz = yes, skip kbyte and % display
  1460.     push    si
  1461.     push     ax
  1462.     call    kbpr            ; show kilobytes sent
  1463.     call    perpr            ; show percent sent
  1464.     pop    ax
  1465.     pop    si
  1466.     clc
  1467. gtchr2:    ret
  1468.  
  1469. gtchr1:    mov    [si].datlen,0        ; report EOF
  1470.     mov    flags.eoflag,1        ; say eof
  1471.     test    flags.remflg,dserial+dquiet ; serial/quiet display mode?
  1472.     jnz    gtchr3            ; nz = yes, skip kbyte and % display
  1473.     push    si            ; do here so 100% sent shows
  1474.     push     ax
  1475.     call    kbpr            ; show kilobytes sent
  1476.     call    perpr            ; show percent sent
  1477.     pop    ax
  1478.     pop    si
  1479. gtchr3:stc                ; return failure
  1480.     ret
  1481. gtchr    endp
  1482.  
  1483. ; Kermit encoding rules:
  1484. ; Prefix codes per se are sent as <control prefix, #><data byte>
  1485. ; C0 and C1 control codes are prefixed by <control prefix, #><data byte>
  1486. ; 8th bit set prefixing is <8th bit prefix, &><composite byte>
  1487. ;  where composite byte is <control prefix><data byte>
  1488. ; Run length encoding is <rle prefix, ~><count><composite byte>
  1489. ;  where composite byte is <8th bit prefix><control prefix><data byte>
  1490. ; So far the maximum transmitted size of any raw byte is three bytes, 
  1491. ; and a run of them is six bytes.
  1492. ;
  1493. ; Locking shifts, applies only if locking shifts have been negotiated.
  1494. ; Data whose lower seven bits are DLE, SI, SO data are sent as other C0/C1
  1495. ; codes, but they are preceeded by DLE. Such pairs of control codes are
  1496. ; subject to control code prefixing (#) and 8th bit prefixing (&); runs
  1497. ; of them are preceeded by the <rle prefix><count> byte pair.
  1498. ; Control SO locks on implication of 8th bit set on all following data,
  1499. ; and that data is sent without the 8th bit set.
  1500. ; Control SI unlocks SO shift.
  1501. ; DLE, SI, and SO shift controls are sent as bare control codes, unencoded.
  1502. ; A single shift operation is used when appropriate to change the state
  1503. ;  of implied 8th bit value (set or reset). The 8th bit prefix character
  1504. ;  is used as a prefix to denote: change the 8th bit from the current state
  1505. ;  to the opposite value for the following data byte only.
  1506. ;
  1507. ;The Control Prefix
  1508. ;   For transparency on serial communication links that are sensitive to
  1509. ;   control characters, the file sender precedes each C0 and C1 control with
  1510. ;   the control prefix, normally "#" (ASCII 35), and then encodes the control
  1511. ;   character itself by "exclusive-ORing" it with 64 decimal (i.e. inverting
  1512. ;   bit 6) to produce a character in the printable ASCII range.  For example,
  1513. ;   Control-C (ASCII 3) becomes "#C" (3 XOR 64 = 67, which is the ASCII code
  1514. ;   for the letter C).  Similarly, NUL becomes "#@", Control-A becomes "#A",
  1515. ;   Control-Z becomes "#Z", Escape becomes "#[", and DEL becomes "#?".  The
  1516. ;   receiver decodes by discarding the prefix and XORing the character with
  1517. ;   64 again.  For example, in "#C", C = ASCII 67, and 67 XOR 64 = 3 =
  1518. ;   Control-C.  Control prefixing is mandatory.  The control prefix is also
  1519. ;   used for quoting prefix characters that occur in the data itself; see
  1520. ;   "The Prefix Quote" below.
  1521. ;
  1522. ;The 8th-bit Prefix
  1523. ;   When one or both of the two Kermit programs knows that the connection
  1524. ;   between them is not transparent to the 8th bit (e.g. because the Kermit
  1525. ;   PARITY variable is not NONE, or because the program always operates that
  1526. ;   way), a feature called "8th-bit prefixing" is used if the two Kermit
  1527. ;   programs negotiate an agreement to do so.  The 8th-bit prefix is Kermit's
  1528. ;   single shift, normally the ampersand character "&" (ASCII 38).  When the
  1529. ;   file sender encounters an 8-bit character, it inserts the "&" prefix in
  1530. ;   front of it, and then inserts the data character itself with its 8th bit
  1531. ;   set to 0.  If the data character is a control character, it is inserted
  1532. ;   after the 8th-bit prefix in control-prefixed form.  Examples: an "A" with
  1533. ;   its 8th bit set to 1 ("<1>A") becomes "&A"; a Control-A with its 8th bit
  1534. ;   set to 1 ("<1><SOH>") becomes "&#A".
  1535. ;
  1536. ;The Repeat-Count Prefix
  1537. ;   The repeat-count prefix provides a simple form of data compression.  It
  1538. ;   is used only when both Kermit programs support this feature and agree to
  1539. ;   use it.  This prefix, normally tilde "~" (ASCII 126), precedes a repeat
  1540. ;   count, which can range from 0 to 94.  The repeat count is encoded as a
  1541. ;   printable ASCII character in the range SP (32) - tilde (126) by adding
  1542. ;   32.  For example, a series of 36 G's would be encoded as "~DG" (D = ASCII
  1543. ;   68 - 32 = 36).  The repeat-count prefix applies to the following prefixed
  1544. ;   sequence, which may be a single character ("~DG"), an 8th-bit prefixed
  1545. ;   character ("~D&G" = 36 Control-G characters with their 8th bits set to
  1546. ;   1), a control-prefixed character ("~D#M" = 36 Control-M's), or an
  1547. ;   8th-bit-and-control-prefixed character ("~~&#Z" = 94 Control-Z's with
  1548. ;   their 8th bits set to 1).
  1549. ;
  1550. ;The Prefix Quote
  1551. ;   The control prefix, normally "#", is also used to quote the control
  1552. ;   prefix itself if it occurs in the data: "##", meaning that the "#"
  1553. ;   character should be taken literally.  If 8th-bit prefixing is in effect,
  1554. ;   the control prefix also quotes the 8th-bit prefix: "#&", so "#&D" stands
  1555. ;   for "&D" rather than "<1>D".  If repeat count prefixing is in effect, the
  1556. ;   control prefix is also used to quote the repeat count prefix: "#~", so
  1557. ;   "#~CG" stands for "~CG" rather than 35 "G" characters.  So the complete
  1558. ;   meaning of the "#" prefix is: if the value of the following character is
  1559. ;   77, 64-95, 192-223 or 205, the prefixed character is to be XORed with 64,
  1560. ;   otherwise it is to be taken literally.  The prefix quote can also be used
  1561. ;   harmlessly to quote 8th-bit or repeat-count prefixing characters even
  1562. ;   when these types of prefixing are not in effect.
  1563. ;
  1564. ;  Examples, using notation of <high bit><lower 7 bits>:
  1565. ;
  1566. ;  Original data stream
  1567. ;  <0>A<0>B<0>C<1>D<1>E<1>F<1>G<1>H<1>I<0>J<0>K<0>L<0>M  (13 characters)
  1568. ;  would be transmitted like this with single shifts:
  1569. ;  &A&B&C&D&E&F&G&H&I&J&K&L&M                            (26 characters)
  1570. ; and like this with locking shifts:
  1571. ;   ABC<SO>DEFGHI<SI>JKLM                                 (15 characters)
  1572. ; On an 8-bit connection, of course, this string of characters can be
  1573. ; transmitted as-is, with no overhead at all.
  1574. ;
  1575. ; Now suppose we have the following character sequence:
  1576. ;  <1>A<1>B<1>C<0>D<1>E<1>F<1>G<0>H<1>I<1>J<1>K<0>L<1>M  (13 characters)
  1577. ; Several isolated 7-bit characters are found in the middle of a long run
  1578. ; of 8-bit characters. Using locking shifts alone, this would be encoded as:
  1579. ; <SO>ABC<SI>D<SO>EFG<SI>H<SO>IJK<SI>L<SO>M              (20 characters)
  1580. ; But using a combination of locking and single shifts, it can be encoded more
  1581. ; compactly, as in this example, in which "&" is the single-shift character:
  1582. ; <SO>ABC&DEFG&HIJK&LM                                   (17 characters)
  1583. ;
  1584. ;
  1585.  
  1586. ; Do encoding.
  1587. ; Enter with CX = data size, source of data is encbuf, si is pktinfo ptr.
  1588. ; Writes output to area pointed to by [si].datadr.
  1589. ; Returns char count in cx and [si].datlen with carry clear if success,
  1590. ; else carry set if overflow.
  1591. ; SI is preserved
  1592. doenc:    clc
  1593.     jcxz    doen0            ; cx = 0 means nothing to encode
  1594.     mov    ah,dblbyteflg        ; preserve state
  1595.     mov    al,dblbyte
  1596.     push    ax
  1597.     mov    al,shiftstate        ; locking shift state
  1598.     mov    ah,DLEseen        ; DLE state
  1599.     push    ax            ; save
  1600.     mov    dblbyteflg,0        ; init encode as doubles
  1601.     mov    shiftstate,0        ; init shift states
  1602.     mov    DLEseen,0
  1603.     mov    echrcnt,cx        ; number of bytes of source data
  1604.     mov    ebufpnt,offset encbuf    ; source of data
  1605.     mov    encinp,offset nulref    ; null routine for refilling buffer
  1606.     call    encode            ; make a packet with size in AX
  1607.     mov    cx,ax
  1608.     pop    ax            ; restore state
  1609.     mov    shiftstate,al
  1610.     mov    DLEseen,ah
  1611.     pop    ax
  1612.     mov    dblbyteflg,ah
  1613.     mov    dblbyte,al
  1614. doen0:    ret
  1615.  
  1616. nulref:    mov    echrcnt,0        ; no data to return
  1617.     stc
  1618.     ret
  1619.  
  1620. ; encode - writes data portion of kermit packet into [[si].datadr].
  1621. ; expects encinp to contain the address of a routine to refill the buffer,
  1622. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  1623. ; the maximum size of the data packet, ebufpnt to contain a pointer to
  1624. ; the source of the characters, and [si].datadr to be output address.
  1625. ; Trans.lshift is non-zero if locking shift encoding is active.
  1626. ; While locking shift is active DLE escapes DLE, SI, and SO to be
  1627. ; data characters. Under locking shift rules SO (Control-N) shifts high bit
  1628. ; data to non-high bit data; SI (Control-O) cancels SO. Shiftstate is
  1629. ; 0 for non-shifted state, 80h for shifted state.
  1630. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while
  1631. ; performing Japanese translation; dblbyte is the first byte of the pair.
  1632. ; Returns: AX = the number of characters actually written to the buffer
  1633. ; All packets except I, S, and A types are encoded.
  1634. ; Packet space is precomputed allowing for prefixes other than locking shifts.
  1635. ; Returns carry clear for success, carry set otherwise.
  1636.  
  1637. encode    proc    near
  1638.     push    es
  1639.     push    si            ; save caller's si
  1640.     mov    cx,trans.maxdat        ; maximum packet size
  1641.     cmp    cx,[si].datsize        ; buffer capacity of this slot
  1642.     jbe    encod1            ; be = not overflowing slot
  1643.     mov    cx,[si].datsize        ; use smaller pkt buffer
  1644. encod1:    les    di,[si].datadr        ; address of output buffer to es:[di]
  1645.     mov    temp,di            ; remember output buffer start address
  1646.     mov    si,ebufpnt        ; pointer into source buffer
  1647.     mov    dl,trans.rquote        ; send quote char
  1648.     xor    dh,dh            ; assume no 8-bit quoting
  1649.     mov    al,trans.ebquot        ; 8-bit quote
  1650.     cmp    al,'N'            ; refusing 8-bit quoting?
  1651.     je    encod10            ; e = yes
  1652.     cmp    al,'Y'            ; or can but won't?
  1653.     je    encod10            ; e = yes, else specific char
  1654.     mov    dh,0ffh            ; remember we have to do 8-bit quotes
  1655.                     ; top of read loop
  1656. encod10:or    cx,cx            ; any space left in output buffer?
  1657.     jg    encod11            ; g = yes
  1658.     mov    ax,di            ; current output location
  1659.     sub    ax,temp            ; minus start of buffer, ret cnt in AX
  1660.     mov    ebufpnt,si        ; update pointer into source buffer
  1661.     pop    si            ; restore caller's si
  1662.     pop    es
  1663.     mov    [si].datlen,ax
  1664.     clc                ; success
  1665.     ret
  1666.  
  1667. encod11:cmp    echrcnt,0        ; any data in buffer?
  1668.     jg    encod20            ; g = yes, skip over buffer refill
  1669.     push    es
  1670.     call    encinp            ; get another buffer full
  1671.     pop    es
  1672.     jnc    encod14            ; nc = success
  1673.  
  1674. encod12:pop    si            ; restore user's si
  1675.     sub    di,temp            ; minus start of buffer
  1676.     or    di,di            ; buffer empty?
  1677.     jz    encod13            ; z = yes
  1678.     mov    ax,di            ; report size encoded
  1679.     mov    [si].datlen,ax
  1680.     pop    es
  1681.     clc                ; success
  1682.     ret                ; return success
  1683. encod13:xor    ax,ax            ; empty buffer
  1684.         mov    flags.eoflag,1        ; set eof flag
  1685.     mov    filflg,al        ; nothing in input buffer
  1686.     mov    [si].datlen,ax
  1687.     pop    es
  1688.     stc                ; failure
  1689.     ret                ; return failure
  1690.  
  1691. encod14:mov    si,ebufpnt        ; update position in source buffer
  1692.     cmp    echrcnt,0         ; any characters returned?
  1693.     je    encod12            ; e = none, assume eof
  1694.  
  1695. encod20:cld                ; forward direction
  1696.     lodsb
  1697.     dec    echrcnt            ; decrement input count
  1698.     mov    ah,al
  1699.     and    ah,80h            ; keep high bit in ah
  1700.     mov    rptct,1            ; say have one copy of this char
  1701.     cmp    al,'Z'-40H        ; is this a control-Z?
  1702.     jne    encd30            ; ne = no, skip eof-processing
  1703.     cmp    flags.eofcz,0           ; is a Control-Z an end of file?
  1704.     je    encd30            ; e = no
  1705.     cmp    trans.xtype,1        ; file type binary?
  1706.     je    encd30            ; e = yes, send as is
  1707.     mov    flags.eoflag,1        ; yes, set eof flag
  1708.     mov    filflg,0        ; say no more source data in buffer
  1709.     mov    echrcnt,0        ; ditto
  1710.     jmp    short encod12        ; set character count and return
  1711.  
  1712.                     ; analyze current char (al)
  1713. encd30:    cmp    echrcnt,0        ; doing the last character?
  1714.     jle    encod40            ; le = yes, there is no next character
  1715.     or    cx,cx            ; space for repeat group in output?
  1716.     jle    encod40a        ; le = no, not enough for rpt prefix
  1717.     cmp    al,[si]            ; this is char the same as the next?
  1718.     jne    encod40            ; no, do this char independently
  1719.     cmp    trans.rptq,0        ; repeat prefixing disabled?
  1720.     je    encod40            ; e = yes
  1721.     push    cx            ; scan for repeats in input buffer
  1722.     push    bx
  1723.     mov    cx,echrcnt        ; count of bytes left in input buf
  1724.     inc    cx            ; will reread current byte
  1725.     cmp    cx,94            ; max prefix of 94
  1726.     jbe    encod31            ; be = ok, else limit scan to 94
  1727.     mov    cx,94
  1728. encod31:xor    bx,bx            ; count of copies of this char in buf
  1729. encod32:inc    bx
  1730.     cmp    [si+bx-1],al        ; new [si+bx-1] same as current (al)?
  1731.     loope    encod32            ; e = yes, do all of interest
  1732.     cmp    bx,3            ; enough repeats to use prefix?
  1733.     jae    encod33            ; ae = yes
  1734.     mov    bx,1            ; say do one char
  1735. encod33:mov    rptct,bl        ; bl is qty repeated overall
  1736.     dec    bx            ; bx = number of extra chars (>1)
  1737.     add    si,bx            ; move forward by repeat group
  1738.     sub    echrcnt,bx        ; adjust input buffer counter too
  1739.     pop    bx
  1740.     pop    cx
  1741.  
  1742.                     ; test for locking shift applicability
  1743. encod40:cmp    cx,2            ; space left for prefixed lock?
  1744.     jb    encod50            ; b = no, not enough for prefix
  1745.     cmp    trans.lshift,lock_disable ; locking shifts disabled?
  1746.     je    encod50            ; e = yes, skip this material
  1747.     cmp    ah,shiftstate        ; change of high bit status?
  1748.     jne    encod41            ; ne = yes
  1749. encod40a:jmp    encod50            ; no, stay in same lock state
  1750.                     ; change of high bit
  1751. encod41:mov    bx,echrcnt        ; count chars remaining to be read
  1752.     add    bl,rptct        ; add repeat count
  1753.     adc    bh,0
  1754.     cmp    bx,4            ; at least 4 more chars to examine?
  1755.     jb    encod50            ; b = no, not worth a lock change
  1756.     cmp    rptct,4            ; enough repeats to take short cut?
  1757.     jae    encod43            ; ae = plenty of repeats
  1758.     push    ax            ; look for change of shift state
  1759.     push    cx
  1760.     push    si
  1761.     mov    cl,rptct        ; repeat count
  1762.     xor    ch,ch
  1763.     dec    cx            ; count is one for no repeats
  1764.     sub    si,cx            ; back up over repeated chars
  1765.     mov    cx,4            ; look ahead 4 chars
  1766. encod42:lodsb                ; read ahead
  1767.     and    al,80h            ; pick out high bit
  1768.     cmp    al,ah            ; high bit the same?
  1769.     loope    encod42            ; loop while same
  1770.     pop    si
  1771.     pop    cx
  1772.     pop    ax
  1773.     jne    encod50            ; ne = differ, don't change lock
  1774.                     ; change locking shift state
  1775. encod43:mov    es:[di],dl        ; insert quote char (#)
  1776.     inc    di            ; adjust output buffer pointer
  1777.     dec    cx
  1778.     push    ax
  1779.     mov    ah,shiftstate        ; get current shift state
  1780.     xor    ah,80h            ; toggle shift state
  1781.     mov    shiftstate,ah        ; remember it
  1782.     mov    al,SIchar+40h        ; assume going into unshifted state
  1783.     or    ah,ah            ; to unshifted state now?
  1784.     jz    encod44            ; z = yes, go to unshifted state
  1785.     mov    al,SOchar+40h        ; say go to shifted state
  1786. encod44:stosb                ; put lock char into packet
  1787.     dec    cx
  1788.     pop    ax            ; recover current character
  1789.                     ; end of locking shift tests
  1790.  
  1791. encod50:or    dh,dh            ; doing 8-bit quoting?
  1792.     jz    encod60            ; z = no, forget this
  1793.     cmp    trans.lshift,lock_disable ; locking shift disabled?
  1794.     je    encod57            ; e = yes
  1795.     cmp    ah,shiftstate        ; different than current shift state?
  1796.     jne    encod58            ; ne = yes, specials will be prefixed
  1797.     push    ax            ; save char (stripped of high bit)
  1798.     and    al,7fh            ; consider high bit controls too
  1799.     cmp    al,SIchar        ; SI (Control-O)?
  1800.     je    encod53            ; e = yes
  1801.     cmp    al,SOchar        ; SO (Control-N)?
  1802.     je    encod53            ; e = yes
  1803.     cmp    al,DLE            ; DLE (Control-P)?
  1804.     jne    encod54            ; ne = no
  1805. encod53:mov    al,dl            ; stuff a quote (#)
  1806.     stosb
  1807.     dec    cx
  1808.     mov    al,DLE + 40h        ; then a DLE prefix (P)
  1809.     stosb
  1810.     dec    cx            ; account for it in buffer size
  1811. encod54:pop    ax            ; exit with original char in AL
  1812.     jmp    short encod60        ; no 8-bit prefixing needed here
  1813.  
  1814. encod57:cmp    ah,shiftstate        ; different than current shift state?
  1815.     je    encod60            ; e = no, don't send quoted form
  1816. encod58:cmp    rptct,1            ; doing repeats?
  1817.     jbe    encod59            ; be = no
  1818.     cmp    trans.rptq,0        ; disabled?
  1819.     je    encod59            ; e = yes
  1820.     push    ax            ; do repeat prefixing - save data
  1821.     mov    al,trans.rptq        ; insert repeat prefix char
  1822.     stosb
  1823.     dec    cx            ; account for it in buffer size
  1824.     mov    al,rptct        ; get the repeat count
  1825.     add    al,20h            ; make it printable
  1826.     stosb                ; insert into buffer
  1827.     dec    cx
  1828.     pop    ax            ; get back the actual character
  1829. encod59:mov    bl,trans.ebquot        ; get 8-bit quote char
  1830.     mov    es:[di],bl        ; put in packet
  1831.     inc    di
  1832.     dec    cx            ; decrement # of chars left
  1833.     jmp    short encod60b
  1834.                     ; common prefix testing section
  1835. encod60:cmp    rptct,1            ; doing repeats?
  1836.     jbe    encod60b        ; be = no
  1837.     cmp    trans.rptq,0        ; repeat quoting disabled?
  1838.     je    encod60b        ; e = yes, disabled
  1839.     push    ax            ; do repeat prefixing - save data
  1840.     mov    al,trans.rptq        ; insert repeat prefix char
  1841.     stosb
  1842.     dec    cx            ; account for it in buffer size
  1843.     mov    al,rptct        ; get the repeat count
  1844.     add    al,20h            ; make it printable
  1845.     stosb                ; insert into buffer
  1846.     dec    cx
  1847.     pop    ax            ; get back the actual character
  1848.  
  1849. encod60b:and    al,7fh            ; turn off 8th bit in character
  1850.     cmp    al,' '            ; compare to a space
  1851.     jae    encod61            ; ae = not a control code
  1852.     cmp    al,trans.ssoh        ; always prefix this item
  1853.     je    encod64
  1854.     cmp    al,trans.seol        ; always prefix this item
  1855.     je    encod64
  1856.     push    bx            ; check for unprefixed selections
  1857.     mov    bl,al            ; as 1=7-bit, 80h=8-bit, 81h=both
  1858.     xor    bh,bh
  1859.     mov    bl,protlist[bx]        ; get 8 and 7 bit encoding rules
  1860.     or    bl,bl            ; anything being excepted from prefix?
  1861.     jz    encod60a        ; z = no
  1862.     test    bl,ah            ; 8-bit unprefixed?
  1863.     jnz    encod60a        ; nz = yes
  1864.     cmp    ah,80h            ; is it a 7-bit char in reality?
  1865.     je    encod60a        ; e = no (prefix it)
  1866.     and    bl,1            ; text 7 bit unprefixed
  1867. encod60a:pop    bx
  1868.     jz    encod64            ; z = char needs quoting
  1869.     jmp    short encod67        ; store char as-is
  1870. encod61:cmp    al,DEL            ; delete?
  1871.     je    encod64            ; e = yes, go quote it
  1872.     cmp    al,dl            ; quote char?
  1873.     je    encod65            ; e = yes, go add it
  1874.     or    dh,dh            ; doing 8-bit quoting?
  1875.     jz    encod62            ; z = no, don't translate it
  1876.     cmp    al,trans.ebquot        ; 8-bit quote char?
  1877.     je    encod65            ; e = yes, just output with quote
  1878. encod62:cmp    trans.rptq,0        ; repeat prefixing disabled?
  1879.     je    encod67            ; e = yes, don't check for quote char
  1880.     cmp    al,trans.rptq        ; repeat quote character?
  1881.     je    encod65            ; e = yes, then quote it
  1882.     jmp    short encod67        ; else don't quote it
  1883.                     ; control code section
  1884. encod64:xor    al,40h            ; control char, uncontrollify
  1885. encod65:mov    es:[di],dl        ; insert control quote char
  1886.     inc    di
  1887.     dec    cx
  1888. encod67:or    al,ah            ; restore high bit, if stripped
  1889.     or    dh,dh            ; doing eight bit quoting?
  1890.     jz    encod68            ; z = no, retain high bit
  1891.     and    al,not 80h        ; strip high bit
  1892. encod68:stosb
  1893.     dec    cx            ; decrement output buffer counter
  1894.     jmp    encod10            ; get fresh input
  1895. encode    endp 
  1896.  
  1897. ; Fill encode source buffer, report KB and percentage done.
  1898. ; Return carry clear for success
  1899. ; modifies ax
  1900. inbuf    proc    near
  1901.     cmp    flags.eoflag,0        ; reached the end?
  1902.     je    inbuf0            ; e = no
  1903.     stc                ; return failure
  1904.     ret
  1905. inbuf0:    push    dx
  1906.     push    bx
  1907.     push    cx
  1908.     mov    bx,diskio.handle    ; get file handle
  1909.     mov    cx,buffsz        ; record size
  1910.     mov    dx,offset buff        ; buffer
  1911.     mov    ebufpnt,dx        ; buffer pointer
  1912.     cmp    trans.xtype,1        ; [HF3] File type binary?
  1913.     je    inbuf0a            ; [HF3] e = yes, no translation
  1914.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1915.     jne    inbuf0a            ; ne = no
  1916.     shr    cx,1            ; allow for double char encoding
  1917.     mov    dx,offset rdbuf        ; use this as source buffer
  1918. inbuf0a:mov    ah,readf2        ; read a record
  1919.     call    readcache        ; use internal cache
  1920. ;;;    int    dos            ;  if not using internal cache
  1921.     jnc    inbuf7            ; nc = no error
  1922.     mov    flags.cxzflg,'X'    ; error, set ^X flag
  1923.      jmp    short inbuf1        ; and truncate the file here
  1924. inbuf7:    push    cx
  1925.     mov    cx,ax            ; count for crc
  1926.     call    crc            ; compute CRC-16
  1927.     pop    cx
  1928.     or    ax,ax            ; any bytes read?
  1929.     jnz    inbuf2            ; nz = yes (the number read)
  1930. inbuf1:    mov    flags.eoflag,1        ; set End-of-File
  1931.     mov    filflg,0        ; buffer empty
  1932.     mov    echrcnt,0        ; zero bytes left in buffer
  1933.     pop    cx
  1934.     pop    bx
  1935.     pop    dx
  1936.     stc                ; failure
  1937.     ret
  1938.  
  1939. inbuf2:    cmp    trans.xtype,1        ;[HF]941012 type binary ?
  1940.     je    inbuf3            ;[HF]941012 e = yes
  1941.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1942.     jne    inbuf3            ; ne = no
  1943.     call    jpnread            ; revise buffer for Japanese chars
  1944. inbuf3:    add    tfilsz,ax        ; total the # bytes transferred so far
  1945.     adc    tfilsz+2,0        ; it's a double word
  1946.     mov    echrcnt,ax        ; number of chars read from file
  1947.     add    fsta.fsbyte,ax
  1948.     adc    fsta.fsbyte+2,0
  1949.     mov    filflg,1        ; buffer not empty
  1950.                     ; Character set translation section
  1951.     cmp    trans.xtype,1        ; File Type Binary?
  1952.     je    inbuf6            ; e = yes, no translation
  1953.     cmp    trans.xchset,xfr_xparent ; Transparent transfer char set?
  1954.     je    inbuf6            ; e = yes, no translation
  1955.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1956.     je    inbuf6            ; e = yes, processed already
  1957.     push    ax            ; save buffer count
  1958.     mov    cx,ax            ; loop counter
  1959.     push    di
  1960.     push    es
  1961.     PUSH    DS
  1962.     call    cplatin            ; set DS:BX to CP to Xfr chr table
  1963.     call    cpinvert        ; check readable vs invertible set
  1964.     mov    di,seg buff
  1965.     mov    es,di
  1966.     mov    di,offset buff        ; scan this buffer
  1967.     cld
  1968. inbuf4:    mov    al,es:[di]        ; get a char, keep pointer fixed
  1969.     cmp    bx,offset icp437L1    ; invertible CP 437 to Latin1?
  1970.     jne    inbuf4b            ; ne = no
  1971.     mov    ah,al
  1972.     cmp    ah,127            ; special case?
  1973.     jne    inbuf4d            ; ne = no
  1974.     mov    al,26            ; 127 to 26
  1975.     jmp    short inbuf5
  1976. inbuf4d:cmp    al,20            ; range for special cases?
  1977.     jb    inbuf5            ; b = no
  1978.     cmp    al,21
  1979.     ja    inbuf5            ; a = no
  1980.     mov    al,167
  1981.     je    inbuf5            ; 21 to 167
  1982.     mov    al,182
  1983.     jmp    short inbuf5        ; 20 to 182
  1984. inbuf4b:cmp    bx,offset icp850L1    ; invertible CP 850 to Latin1?
  1985.     jne    inbuf4a            ; ne = no
  1986.     cmp    al,28            ; special case?
  1987.     jne    inbuf4c            ; ne = no
  1988.     mov    al,127            ; 28 to 127
  1989.     jmp    short inbuf5
  1990. inbuf4c:cmp    al,127            ; special case?
  1991.     jne    inbuf4a
  1992.     mov    al,26            ; 127 to 26
  1993. inbuf4a:test    al,80h            ; GRight?
  1994.     jz    inbuf5            ; z = no
  1995.     and    al,not 80h        ; strip high bit
  1996.     xlatb                ; translate via bx table
  1997. inbuf5:    stosb                ; store char
  1998.     loop    inbuf4            ; do all concerned
  1999.     POP    DS
  2000.     pop    es
  2001.     pop    di
  2002.     pop    ax
  2003. inbuf6:    pop    cx
  2004.     pop    bx
  2005.     pop    dx
  2006.     clc                ; success
  2007.     ret
  2008. inbuf    endp
  2009. code    ends
  2010.  
  2011. code1    segment
  2012.     assume cs:code1
  2013.  
  2014. ; An automatic disk read cache
  2015. cachesize equ 8192
  2016. readcache    proc    far
  2017.     cmp    cacheseg,0        ; have cache buffer?
  2018.     jne    readc1            ; ne = yes
  2019.     mov    cacheptr,0        ; offset of zero in cache
  2020.     mov    cachelen,0        ; bytes of data in cache
  2021.     mov    ax,cachesize        ; cache size, bytes
  2022.     call    malloc
  2023.     mov    cacheseg,ax        ; seg of cache
  2024.     jnc    readc1            ; nc = success
  2025.     mov    cacheseg,0        ; failed
  2026.     stc
  2027.     ret
  2028.  
  2029. readc1:    cmp    filflg,0        ; should cache be empty?
  2030.     je    readc2            ; e = yes, read from disk
  2031.     cmp    cachelen,0        ; bytes in cache
  2032.     jne    readc4            ; ne = have some cached bytes
  2033. readc2:    mov    bx,diskio.handle    ; get file handle
  2034.     mov    cx,cachesize        ; number of bytes wanted
  2035.     push    ds
  2036.     mov    ax,cacheseg
  2037.     mov    ds,ax            ; destination is ds:dx
  2038.     xor    dx,dx            ; offset zero
  2039.     mov    ah,readf2        ; read a record
  2040.     int    dos
  2041.     pop    ds
  2042.     jnc    readc3            ; nc = success, ax has byte count
  2043.     push    es            ; read failure
  2044.     mov    ax,cacheseg
  2045.     mov    es,ax            ; seg of separately malloc'd buffer
  2046.     mov    ah,freemem        ; free it
  2047.     int    dos
  2048.     pop    es
  2049.     xor    ax,ax
  2050.     mov    cacheseg,ax
  2051.     stc
  2052.     ret                ; return error
  2053.  
  2054. readc3:    mov    cacheptr,0        ; read from start
  2055.     mov    cachelen,ax        ; bytes now in cache
  2056.     or    ax,ax            ; end of file (ax = 0)?
  2057.     jnz    readc4            ; nz = no
  2058.     push    es
  2059.     mov    ax,cacheseg
  2060.     mov    es,ax            ; seg of separately malloc'd buffer
  2061.     mov    ah,freemem        ; free it
  2062.     int    dos
  2063.     pop    es
  2064.     mov    cacheseg,0
  2065.     xor    ax,ax            ; report ax 0 and carry clear for EOF
  2066.     clc
  2067.     ret                ; return empty
  2068.  
  2069. readc4:    mov    cx,cachelen        ; bytes in cache
  2070.     cmp    cx,buffsz        ; larger than buff?
  2071.     jbe    readc5            ; be = no
  2072.     mov    cx,buffsz        ; use smaller size
  2073. readc5:    push    cx
  2074.     push    si
  2075.     push    di
  2076.     push    es
  2077.     push    ds
  2078.     mov    si,ds
  2079.     mov    es,si
  2080.     mov    di,offset buff        ; es:di is destination es:buff
  2081.     mov    si,cacheptr        ; ds:si is source cacheseg:cacheptr
  2082.     mov    ax,cacheseg
  2083.     mov    ds,ax
  2084.     cld
  2085.     shr    cx,1
  2086.     rep    movsw            ; do words
  2087.     jnc    readc6            ; nc = even byte count
  2088.     movsb                ; do odd byte
  2089. readc6:    pop    ds
  2090.     pop    es
  2091.     pop    di
  2092.     pop    si
  2093.     pop    cx
  2094.     add    cacheptr,cx        ; where to read next
  2095.     sub    cachelen,cx        ; bytes remaining
  2096.     mov    ax,cx            ; return ax to caller
  2097.     clc
  2098.     ret
  2099. readcache endp
  2100. code1    ends
  2101.  
  2102. code    segment
  2103.     assume cs:code
  2104.  
  2105. ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp)
  2106. ; Read buffer rdbuf to convert from file character set Shift-JIS (Code Page 
  2107. ; 932) to transfer character set Japanese-EUC. Double char translation state
  2108. ; is maintained across file buffers. Init dblbyte to 0 before each new file.
  2109. ; Output is written to buff, with byte count in register AX. The output
  2110. ; could be twice the size of the input. [rewritten by jrd]
  2111. jpnread    proc    near            ; [HF] read Japanese from file
  2112.     push    si
  2113.     push    di
  2114.     push    es
  2115.     mov    cx,ax            ; number of chars in source buffer
  2116.     mov    ax,ds
  2117.     mov    es,ax
  2118.     mov    dl,dblbyteflg        ; get state info from previous call
  2119.     mov    ah,dblbyte        ;  first byte too
  2120.     mov    si,offset rdbuf        ; read from here
  2121.     mov    di,offset buff        ; write to here (avoids overwrites)
  2122.     cld
  2123. jpnrea1:lodsb                ; get a byte
  2124.     or    dl,dl            ; doing first byte?
  2125.     jnz    jpnread3        ; nz = no, second of a pair
  2126.     cmp    al,81h            ; is it Kanji?
  2127.     jb    jpnrea5            ; b = no
  2128.     cmp    al,0fch
  2129.     ja    jpnrea5            ; a = no
  2130.     cmp    al,9fh
  2131.     jbe    jpnrea2            ; be = yes
  2132.     cmp    al,0e0h
  2133.     jb    jpnrea5            ; b = no
  2134. jpnrea2:mov    ah,al            ; AL is first byte of Kanji, save it
  2135.     mov    dl,1            ; say ready to do second byte next
  2136.     jmp    short jpnrea8        ; continue loop
  2137.  
  2138. jpnread3:cmp    al,40h            ; is second byte Kanji?
  2139.     jb    jpnrea6            ; b = no
  2140.     cmp    al,0fch
  2141.     ja    jpnrea6            ; a = no
  2142.     cmp    al,7eh
  2143.     jbe    jpnrea4            ; be = yes
  2144.     cmp    al,80h
  2145.     jb    jpnrea6            ; b = no
  2146. jpnrea4:call    jpnftox            ; convert to xfer char code
  2147.     jmp    short jpnrea6        ; write the pair
  2148.  
  2149. jpnrea5:cmp    al,0a1h            ; Katakana?
  2150.     jb    jpnrea7            ; b = no
  2151.     cmp    al,0dfh
  2152.     ja    jpnrea7            ; a = no
  2153.     mov    ah,8eh            ; set Katakana prefix
  2154. jpnrea6:xchg    ah,al            ; write two bytes
  2155.     stosb                ; store first byte
  2156.     xchg    ah,al            ; get second byte into AL again
  2157. jpnrea7:stosb                ; store a byte
  2158.     xor    dl,dl            ; say all bytes have been written
  2159. jpnrea8:loop    jpnrea1
  2160.     mov    dblbyteflg,dl        ; save state info
  2161.     mov    dblbyte,ah        ; and first char of a pair
  2162.     sub    di,offset buff        ; compute number of bytes written
  2163.     mov    ax,di            ; report new count in AX
  2164.     pop    es
  2165.     pop    di
  2166.     pop    si
  2167.     ret
  2168. jpnread    endp
  2169.  
  2170. ; File character code (Shift-JIS) to xfer character code (EUC) converter.
  2171. ; From Shift-JIS to EUC
  2172. ;   if( code1 <= 0x9f )
  2173. ;     code1 -= 0x71;
  2174. ;   else
  2175. ;     code1 -= 0xb1;
  2176. ;   code1 = code1 * 2 + 1;
  2177. ;   if( code2 > 0x7f ) code2 -= 1;
  2178. ;   if( code2 >= 0x9e ){
  2179. ;     code2 -= 0x7d;
  2180. ;     code1 += 1;
  2181. ;   } else
  2182. ;     code2 -= 0x1f;
  2183. ;   EUC_code1 = (code1 | 0x80);
  2184. ;   EUC_code2 = (code2 | 0x80);
  2185. ;   [ fputc( EUC_code1, packet ); fputc( EUC_code2, packet ); ]
  2186. ;
  2187. jpnftox    proc    near
  2188.     cmp    ah,9fh
  2189.     ja    jpnftox1
  2190.     sub    ah,71h
  2191.     jmp    short jpnftox2
  2192. jpnftox1:sub    ah,0b1h
  2193. jpnftox2:shl    ah,1
  2194.     inc    ah
  2195.     cmp    al,7fh
  2196.     jbe    jpnftox3
  2197.     dec    al
  2198. jpnftox3:cmp    al,9eh
  2199.     jb    jpnftox4
  2200.     sub    al,7dh
  2201.     inc    ah
  2202.     jmp    jpnftox5
  2203. jpnftox4:sub    al,1fh
  2204. jpnftox5:or    ax,8080h
  2205.     ret
  2206. jpnftox    endp
  2207.  
  2208. ; Calculate the CRC of the string whose address is in DS:DX, length CX bytes.
  2209. ; Returns the CRC in crcword.  Destroys CX.
  2210. ; The CRC is based on the SDLC polynomial: x**16 + x**12 + x**5 + 1.
  2211. ; Original by Edgar Butt  28 Oct 1987 [ebb].
  2212. crc    proc    near
  2213.     push    ax
  2214.     push    bx
  2215.     push    dx
  2216.     mov    bx,dx            ; point to buffer in ds:dx
  2217.     mov    dx,crcword        ; accumulated CRC-16
  2218.     jcxz    crc1
  2219. crc0:    push    cx
  2220.     mov    ah,[bx]            ; get the next char of the string
  2221.         inc    bx
  2222.         xor    dl,ah            ; XOR input with lo order byte of CRC
  2223.         mov    ah,dl            ; copy it
  2224.     mov    cl,4            ; load shift count
  2225.         shl    ah,cl            ; shift copy
  2226.         xor    ah,dl            ; XOR to get quotient byte in ah
  2227.         mov    dl,dh            ; high byte of CRC becomes low byte
  2228.         mov    dh,ah            ; initialize high byte with quotient
  2229.         xor    al,al
  2230.         shr    ax,cl            ; shift quotient byte
  2231.         xor    dl,ah            ; XOR (part of) it with CRC
  2232.         shr    ax,1            ; shift it again
  2233.         xor    dx,ax            ; XOR it again to finish up
  2234.     pop    cx
  2235.     loop    crc0
  2236. crc1:   mov    crcword,dx        ; accumulated CRC
  2237.     pop    dx
  2238.     pop    bx
  2239.     pop    ax
  2240.     ret
  2241. crc    endp
  2242. code    ends
  2243.  
  2244. code1    segment
  2245.     assume cs:code1
  2246.  
  2247. ; GETFIL, called only by send code
  2248. ; Enter with raw filename pattern in diskio.string
  2249. ; Returns carry clear if success, else carry set
  2250. getfil    proc    far
  2251.     mov    dblbyteflg,0        ; clear encoder state variable
  2252.     mov    shiftstate,0        ; locking shift state
  2253.     mov    DLEseen,0        ; escape state
  2254.     mov    filflg,0        ; say nothing is in the buffer
  2255.     mov    flags.eoflag,0        ; not the end of file
  2256.     cmp    atflag,0        ; at sign file list?
  2257.     je    getfil2            ; e = no
  2258.             ; get a filename to diskio.string from file atfile+2
  2259.     call    readatfile
  2260.     jnc    getfil2            ; nc = success
  2261.     ret                ; else return carry set for failure
  2262. getfil2:mov    al,1            ; 1 = get files by rgetfile
  2263.     or    al,sendkind        ; recursive bit (4) from send routine
  2264.     mov    findkind,al        ; kind of operation to do
  2265.     mov    dx,offset diskio.string ; filename string (may be wild)
  2266.     cmp    sndpathflg,2        ; use absolute path?
  2267.     jne    getfil2c        ; ne = no
  2268.     mov    decbuf,0        ; build buffer, clear it
  2269.     xor    al,al            ; mapped drive letter (0 = current)
  2270.     mov    ah,gcurdsk        ; get current disk
  2271.     int    dos
  2272.     inc    al            ; make 1 == drive A (not zero)
  2273.     mov    si,dx            ; supplied text string
  2274.     cmp    byte ptr [si+1],':'    ; drive letter?
  2275.     jne    getfil2a        ; ne = no
  2276.     mov    ax,[si]            ; get drive letter:
  2277.     mov    word ptr decbuf,ax    ; start build buffer
  2278.     and    al,not 20h        ; to upper case
  2279.     sub    al,'A'-1        ; map A = 1 etc
  2280.     add    si,2            ; skip letter:
  2281. getfil2a:cmp    byte ptr [si],'\'    ; root indicator present?
  2282.     je    getfil2b        ; e = yes, done with prefix
  2283.     push    si
  2284.     mov    si,offset decbuf    ; build buffer
  2285.     mov    ah,al            ; drive index (A = 1)
  2286.     add    ah,'A'-1        ; to ASCII
  2287.     mov    [si],ah            ; store letter
  2288.     mov    word ptr [si+1],'\:'    ; append :\ for rooting
  2289.     add    si,3            ; skip over drive:\
  2290.     mov    ah,gcd            ; get current directory
  2291.     mov    dl,al            ; get drive letter indicator
  2292.     int    dos            ; get ds:si = asciiz path (no drive)
  2293.     mov    di,offset decbuf
  2294.     mov    word ptr temp,0+'\'    ; \ termination
  2295.     mov    si,offset temp
  2296.     call    strcat            ; append termination, ASCIIZ
  2297.     pop    si
  2298. getfil2b:mov    di,offset decbuf    ; build buffer
  2299.     call    strcat            ; append current path components
  2300.     mov    dx,offset diskio.string ; filename string (may have wild cards)
  2301.     mov    si,offset decbuf    ; move from decbuf to diskio.string
  2302.     mov    di,dx
  2303.     call    strcpy            ; move all to diskio.string in ds:dx
  2304. getfil2c:call    strlen            ; length of path\filename to CX
  2305.     call    rfprep            ; setup to search for items, ds:dx
  2306.     call    rgetfile        ; get filename from disk
  2307.     pushf                ; save c flag
  2308.     mov    ah,setdma        ; reset dta address
  2309.     mov    dx,offset buff        ; restore dta
  2310.     int    dos
  2311.     popf                ; restore status of search for first
  2312.     jnc    getfi1            ; nc = ok so far
  2313.     ret                ; else take error exit
  2314. getfi1:    jmp    getfcom            ; do common code
  2315. getfil    endp
  2316.  
  2317.  
  2318. ; GTNFIL called by send code to get next file.
  2319. ; Returns carry clear for success, carry set for failure.
  2320. gtnfil    proc    far
  2321.     xor    al,al
  2322.     mov    dblbyteflg,al        ; clear encoder state variable
  2323.     mov    shiftstate,al        ; locking shift state
  2324.     mov    DLEseen,al        ; escape state
  2325.     mov    auxfile,al        ; clear override name
  2326.     cmp    flags.cxzflg,'Z'    ; Did we have a ^Z?
  2327.     jne    gtnfi1            ; ne = no, else done sending files
  2328.     stc                ; carry set for failure
  2329.     ret                ; take failure exit
  2330.  
  2331. gtnfi1:    mov    filflg,al        ; nothing in the DMA
  2332.     mov    flags.eoflag,al        ; not the end of file
  2333.     call    rgetfile        ; get next file
  2334.     pushf                ; save carry flag
  2335.     mov    ah,setdma        ; restore dta
  2336.     mov    dx,offset buff
  2337.     int    dos
  2338.     popf                ; recover carry flag
  2339.     jnc    getfcom            ; nc = success, do common code
  2340.     cmp    atflag,0        ; at sign file list?
  2341.     jne    getfil            ; ne = yes
  2342.     stc
  2343.     ret                ; carry    set means no more files found
  2344. gtnfil    endp
  2345.                     ; worker for getfil, gtnfil
  2346. getfcom    proc    far
  2347.     push    si
  2348.     push    di
  2349.     mov    si,rfileptr        ; pointer to search dta
  2350.     mov    di,offset diskio.dta    ; global dta for this code
  2351.     mov    cx,43            ; bytes in a dta
  2352.     push    es
  2353.     cld
  2354.     mov    ax,ds
  2355.     mov    es,ax
  2356.     rep    movsb            ; copy work dta to diskio
  2357.     pop    es
  2358.     mov    di,offset encbuf    ; name to send to host (no path)
  2359.     mov    byte ptr [di],0
  2360.     cmp    sndpathflg,0        ; include SEND PATH?
  2361.     je    getfco4            ; e = no
  2362.     cmp    auxfile,0        ; already have an override name?
  2363.     jne    getfco4            ; ne = yes
  2364.     mov    si,offset rpathname    ; path
  2365.     cmp    byte ptr [si+1],':'    ; drive present?
  2366.     jne    getfco5            ; ne = no
  2367.     add    si,2            ; skip drive letter
  2368. getfco5:cmp    sndpathflg,2        ; use absolute path?
  2369.     je    getfco6            ; e = yes
  2370.     cmp    byte ptr [si],'\'    ; has leading \?
  2371.     jne    getfco6            ; ne = no
  2372.     inc    si            ; skip leading \
  2373. getfco6:call    strcpy
  2374. getfco4:mov    si,offset diskio.fname    ; where workers see filename
  2375.     call    strcat            ; append found filename
  2376.     mov    si,offset encbuf    ; fwdslash uses si
  2377.     call    fwdslash        ; convert slashes to forward kind
  2378.     test    flags.remflg,dquiet    ; quiet display?
  2379.     jnz    getfco1            ; e = yes, do not display filename
  2380.     call    clrfln            ; position cursor & blank out the line
  2381.     mov    dx,offset encbuf    ; name host sees
  2382.     call    prtasz
  2383. getfco1:call    newfn            ; update encbuf with "send as" name
  2384.     mov    si,offset rpathname    ; actual path
  2385.     mov    di,offset diskio.string    ; work buffer
  2386.     call    strcpy
  2387.     mov    si,offset diskio.fname    ; plus found filename
  2388.     call    strcat
  2389.     mov    dx,di            ; ds:dx is filename to open
  2390.     mov    ah,open2        ; file open
  2391.     xor    al,al            ; 0 = open readonly
  2392.     cmp    dosnum,300h        ; at or above DOS 3?
  2393.     jb    getfco2            ; b = no, so no shared access
  2394.     or    al,40h            ; open readonly, deny none
  2395. getfco2:int    dos
  2396.     jc    getfco3            ; c = failed to open the file
  2397.     mov    diskio.handle,ax    ; save file handle
  2398.     xor    ax,ax
  2399.     mov    tfilsz,ax        ; set bytes sent to zero
  2400.     mov    tfilsz+2,ax
  2401.     mov    ax,-1            ; get a minus one
  2402.     mov    oldkbt,ax
  2403.     mov    oldper,ax
  2404.     clc                ; carry clear for success
  2405. getfco3:pop    si
  2406.     pop    di
  2407.     ret
  2408. getfcom    endp
  2409.  
  2410. ; Read line from file in atfile+2, return unpadded ASCIIZ string to
  2411. ; diskio.string.
  2412. ; Return carry clear if success, else carry set.
  2413. readatfile proc    near
  2414.     cmp    word ptr atfile,0    ; file handle, open?
  2415.     jne    reada3            ; ne = is open, do a read line
  2416.     mov    dx,offset atfile+3    ; get filename, skip handle and @
  2417.     mov    di,dx
  2418.     mov    cx,64            ; max length of a filename.
  2419. reada1:    cmp    byte ptr [di],' '    ; whitespace or control code?
  2420.     jbe    reada2            ; be = yes, found termination
  2421.     inc    di            ; else look at next char
  2422.     loop    reada1            ; limit search
  2423. reada2:    mov    byte ptr [di],0        ; make asciiz
  2424.     mov    ah,open2        ; DOS 2 open file
  2425.     xor    al,al            ; open for reading
  2426.     int    dos
  2427.     mov    word ptr atfile,ax    ; store file handle
  2428.     jnc    reada3            ; nc = open ok, read from file
  2429.     mov    word ptr atfile,0    ; say file is closed
  2430.     ret                ; carry set for fail
  2431.  
  2432. reada3:    mov    bx,word ptr atfile    ; file handle
  2433.     mov    cx,63            ; # of bytes to read
  2434.     mov    di,offset diskio.string    ; destination
  2435.     mov    ah,ioctl        ; ioctl, is this the console device?
  2436.     xor    al,al            ; get device info
  2437.     int    dos
  2438.     and    dl,81h            ; ISDEV and ISCIN bits needed together
  2439.     cmp    dl,81h            ; Console input device?
  2440.     jne    reada5            ; ne = no, use regular file i/o
  2441. reada4:    mov    ah,coninq        ; read console, no echo
  2442.     int    dos
  2443.     cmp    al,CR            ; end of the line yet?
  2444.     je    reada4b            ; e = yes
  2445.     cmp    al,' '            ; whitespace?
  2446.     je    reada4            ; e = yes
  2447.     cmp    al,TAB
  2448.     je    reada4
  2449.     cmp    al,'C'-40h        ; Control-C?
  2450.     jne    reada4a            ; ne = no
  2451.     stc
  2452.     ret                ; return failure
  2453. reada4a:mov    [di],al
  2454.     inc    di
  2455.     loop    reada4            ; keep reading
  2456. reada4b:mov    byte ptr [di],0        ; insert terminator
  2457.     jmp    short reada6        ; finish up
  2458.  
  2459. reada5:    mov    dx,di            ; destination ptr
  2460.     push    cx
  2461.     push    es
  2462.     mov    cx,seg diskio
  2463.     mov    es,cx
  2464.     mov    cx,1            ; one byte
  2465.     mov    byte ptr [di],0        ; insert null terminator, clears line
  2466.     mov    ah,readf2        ; DOS 2 read from file
  2467.     int    dos
  2468.     pop    es
  2469.     pop    cx
  2470.     or    ax,ax            ; bytes read, zero?
  2471.     je    reada6            ; e = yes, exit reading
  2472.     mov    al,[di]            ; byte just read
  2473.     cmp    al,' '            ; white space?
  2474.     je    reada5            ; e = yes, skip
  2475.     cmp    al,TAB            ; white space?
  2476.     je    reada5            ; e = yes, skip
  2477.     cmp    al,','            ; comma separator?
  2478.     je    reada5a            ; e = yes
  2479.     cmp    al,CR            ; first part of line terminator?
  2480.     je    reada5            ; e = yes, skip
  2481.     cmp    al,LF            ; end of the line yet?
  2482.     je    reada5a            ; e = yes
  2483.     inc    di            ; where to write next time
  2484.     loop    reada5            ; keep reading
  2485. reada5a:mov    byte ptr [di],0        ; insert terminator
  2486.     cmp    diskio.string,0        ; empty field?
  2487.     jne    reada6            ; ne = no
  2488.     jmp    readatfile        ; start over
  2489.  
  2490. reada6:    cmp    diskio.string,0        ; anything present?
  2491.     jne    reada7            ; ne = yes
  2492.     mov    bx,word ptr atfile    ; file handle
  2493.     mov    ah,close2        ; close file (wanted just one line)
  2494.     int    dos
  2495.     mov    word ptr atfile,0    ; clear handle
  2496.     mov    atflag,0
  2497.     stc                ; say EOF
  2498.     ret
  2499. reada7:    clc                ; say success
  2500.     ret
  2501. readatfile endp
  2502. code1    ends
  2503.  
  2504. code    segment
  2505.     assume cs:code
  2506.  
  2507. ; Get the file name from the data portion of the F packet or from locally
  2508. ; specified override filename (in auxfile), displays the filename, does any
  2509. ; manipulation of the filename necessary, including changing the name to
  2510. ; prevent collisions. Returns carry clear for success. Failures return
  2511. ; carry set with dx pointing at error message text.
  2512. ; Called by file receive module in mssrcv.asm.
  2513.  
  2514. gofil    proc    near
  2515.     mov    si,offset decbuf    ; filename in packet
  2516.     call    bakslash        ; convert / to \
  2517.     mov    di,offset diskio.string
  2518.     call    strcpy            ; copy pkt filename to diskio.string
  2519.     mov    di,offset fsta.xname    ; statistics external filespec area
  2520.     call    strcpy            ; record external name
  2521.     cmp    rcvpathflg,0        ; RECEIVE PATHNAMES enabled?
  2522.     jne    gofil0c            ; ne = yes
  2523.     cmp    auxfile,0        ; in use already?
  2524.     jne    gofil0c            ; ne = yes
  2525.     mov    auxfile,'.'        ; dot+nul forces use of current dir
  2526.     mov    auxfile+1,0
  2527.     jmp    short gofil0d
  2528.  
  2529. gofil0c:cmp    auxfile,0        ; have override name?
  2530.     jne    gofil1            ; ne = yes
  2531. gofil0d:cmp    flags.xflg,0        ; receiving to screen?
  2532.     jne    gofil0a            ; ne = yes, filename becomes CON
  2533.     cmp    flags.destflg,dest_disk    ; destination is disk?
  2534.     je    gofil1            ; e = yes
  2535.     mov    di,offset printer    ; assume PRN is local file name
  2536.     jb    gofil0b            ; b = yes
  2537. gofil0a:mov    di,offset screen    ; use CON (screen) as local file name
  2538.     mov    flags.xflg,1        ; say receiving to screen
  2539. gofil0b:xchg    di,si            ; di --> decbuf, si --> file name
  2540.     call    strcpy            ; put local name (si) into decbuf
  2541.     mov    nmoflg,1        ; say that we have a replacement name
  2542.     jmp    gofil9            ; final filename is now in 'decbuf'
  2543.  
  2544. gofil1:    xor    ax,ax
  2545.     mov    nmoflg,al        ; assume no override name
  2546.     cmp    auxfile,al        ; overriding name from other side?
  2547.     jne    gofi1e            ; ne = yes
  2548.     jmp    gofil4            ; e = no, get the other end's filename
  2549. gofi1e:    mov    nmoflg,1        ; say using an override name
  2550.     mov    ax,offset auxfile    ; get local override filename
  2551.     cmp    word ptr auxfile+1,003ah; colon+null?(primative drive spec A:)
  2552.     je    gofil3        ; e = yes, skip screwy DOS response (No Path)
  2553.     cmp    word ptr auxfile,'..'    ; parent directory?
  2554.     jne    gofi1g            ; ne = no
  2555.     cmp    word ptr auxfile+1,002eh ; dot dot + null?
  2556.     je    gofi1b            ; e = yes, process as directory
  2557. gofi1g:    cmp    word ptr auxfile,002eh    ; dot + null (current dir)?
  2558.     je    gofi1b            ; e = yes, process as directory
  2559.     call    isfile            ; does it exist?
  2560.     jnc    gofi1f            ; nc = file exists
  2561.     test    filtst.fstat,80h    ; serious error?
  2562.     jz    gofil3            ; z = no, just no such file
  2563.     jmp    gofi18a            ; else quit here
  2564. gofi1f:    test    byte ptr filtst.dta+21,10H ; subdirectory name?
  2565.     jnz    gofi1b            ; nz = yes
  2566.     cmp    filtst.fname,2eh    ; directory name?
  2567.     je    gofi1b            ; e = yes, process as directory
  2568.     cmp    auxfile+2,5ch        ; a root directory like b:\?
  2569.     jne    gofi1d            ; ne = no. (DOS is not helpful with roots)
  2570.     cmp    auxfile+3,0        ; and is it terminated in a null?
  2571.     je    gofi1b            ; e = yes, so it is a root spec
  2572. gofi1d:    test    byte ptr filtst.dta+21,0fh   ; r/o, hidden, system, vol label?
  2573.     jz    gofil3            ; z = no
  2574.      jmp    gofi18a               ; yes. Complain and don't transfer file
  2575. gofi1b:    mov    dx,offset auxfile    ; auxfile is a (sub)directory name
  2576.     call    strlen            ; get its length w/o terminator
  2577.     jcxz    gofil2            ; zero length
  2578.     dec    cx            ; examine last char
  2579.     push    bx            ; save bx
  2580.     mov    bx,cx
  2581.     add    bx,dx
  2582.     cmp    byte ptr [bx],5ch    ; ends in backslash?
  2583.     je    gofil2            ; e = yes
  2584.     cmp    byte ptr [bx],2fh    ; maybe forward slash?
  2585.     je    gofil2            ; e = yes
  2586.     mov    byte ptr [bx + 1],5ch    ; no slash yet. use backslash
  2587.     mov    byte ptr [bx + 2],0    ; plant new terminator
  2588. gofil2:    pop    bx
  2589.  
  2590. gofil3:    mov    di,offset templp    ; local path
  2591.     mov    si,offset templf    ; local filename
  2592.     mov    dx,offset auxfile    ; local string
  2593.     call    fparse            ; split local string
  2594.     mov    di,offset temprp    ; remote path
  2595.     mov    si,offset temprf    ; remote file
  2596.     mov    dx,offset decbuf    ; remote string
  2597.     mov    decbuf+64,0        ; force filename to be <= 64 chars
  2598.     call    fparse            ; split remote string
  2599.     test    flags.remflg,dserver    ; running in Server mode?
  2600.     jz    gofi3c            ; z = no
  2601.     test    denyflg,sndflg        ; is Deny Send mode in operation?
  2602.     jz    gofi3c            ; z = no
  2603.     mov    temprp,0        ; DENY, means remove remote path
  2604. gofi3c:    mov    si,offset templp    ; copy local path to
  2605.     mov    di,offset decbuf    ;  final filename
  2606.     call    strcpy            ; do the copy
  2607.     mov    si,offset templf    ; assume using local file name
  2608.     cmp    byte ptr templf,0    ; local file name given?
  2609.     jne    gofi3b            ; ne = yes
  2610.     mov    si,offset temprf    ; else use remote file name
  2611. gofi3b:    call    strcat            ; append path and filename again
  2612.                     ; offset decbuf holds the new filename
  2613.                     ;
  2614.                 ; recheck legality of filename in 'decbuf'
  2615. gofil4:    mov    decbuf+64,0        ; guard against long filenames
  2616.     mov    di,offset temprp    ; remote path
  2617.     mov    si,offset temprf    ; remote file
  2618.     mov    dx,offset decbuf    ; remote string
  2619.     call    strlen            ; get original size
  2620.     push    cx            ; remember it
  2621.     call    fparse            ; further massage filename
  2622.  
  2623.     cmp    rcvpathflg,1        ; receive relative etc pathnames?
  2624.     je    gofil21            ; e = relative
  2625.     ja    gofil22            ; a = absolute
  2626.     mov    byte ptr [di],0        ; remove remote path for no path
  2627.     jmp    short gofil23
  2628. gofil21:cmp    byte ptr [di],'\'    ; rooted path when relative wanted?
  2629.     jne    gofil22            ; ne = no
  2630.     inc    di            ; skip leading '\'
  2631. gofil22:call    mkpath            ; make path from ds:di path string
  2632. gofil23:push    si            ; put pieces back together
  2633.     call    verfil            ; verify each char in temprf string
  2634.     mov    si,di            ; get path part first
  2635.     mov    di,dx            ; set destination to decbuf
  2636.     call    strcpy            ; copy in path part
  2637.     pop    si            ; recover (new) filename
  2638.  
  2639.     cmp    byte ptr [si],'.'    ; does filename part start with a dot?
  2640.     jne    gofil5            ; ne = no
  2641.     push    di            ; save regs
  2642.     push    si
  2643.     mov    di,offset rdbuf        ; a work area
  2644.     mov    byte ptr [di],'X'    ; start name with letter X
  2645.     inc    di
  2646.     call    strcpy            ; copy rest of filename
  2647.     mov    di,si
  2648.     mov    si,offset rdbuf      ; copy new name back to original location
  2649.     call    strcpy
  2650.     pop    si            ; restore regs
  2651.     pop    di    
  2652. gofil5:    call    strcat            ; append it
  2653.     call    strlen            ; see if we chopped out something
  2654.     pop    si            ; get original length (from push cx above)
  2655.     cmp    cx,si            ; same size?
  2656.     je    gofil9            ; e = yes
  2657.     mov    nmoflg,1        ; say that we have a replacement name
  2658.                 ; filename is now in 'decbuf', all converted
  2659. gofil9:    test    flags.remflg,dquiet    ; quiet display mode?
  2660.     jnz    gofi10            ; nz = yes, don't print it
  2661.     test    flags.remflg,dserial    ; serial display mode?
  2662.     jz    gofi9a            ; z = no
  2663.     mov    ah,prstr
  2664.     mov    dx,offset crlf        ; display cr/lf
  2665.     int    dos
  2666. gofi9a:    call    prtfn            ; show packet filename
  2667.     cmp    nmoflg,0        ; using local override name?
  2668.     je    gofil9b            ; e = no
  2669.     cmp    flags.xflg,0        ; receiving to screen? (X versus F)
  2670.     jne    gofil9b            ; ne = yes
  2671.     mov    ah,prstr
  2672.     mov    dx,offset asmsg        ; print " as "
  2673.     int    dos
  2674.     mov    dx,offset decbuf    ; plus the local filename
  2675.     call    prtasz            ; print asciiz string
  2676. gofil9b:mov    ah,flags.remflg        ; display a following cr/lf?
  2677.     and    ah,dserial        ; for serial display mode
  2678.     or    ah,flags.xflg        ; receiving to screen
  2679.     jz    gofi10            ; z = neither, no cr/lf
  2680.     mov    ah,prstr        ; finish the line with cr/lf
  2681.     mov    dx,offset crlf
  2682.     int    dos
  2683. gofi10:    mov    filtst.fstat2,0        ; 0 = assume is a disk file
  2684.     mov    ah,open2
  2685.     xor    al,al            ; open readonly
  2686.     cmp    dosnum,300h        ; above DOS 2?
  2687.     jb    gofi10a            ; b = no, so no shared access
  2688.     or    al,40h            ; open for reading, deny none
  2689. gofi10a:mov    dx,offset decbuf    ; the filename
  2690.     int    dos
  2691.     jc    gofi16            ; c = cannot open so just proceed
  2692.     mov    bx,ax            ; file handle
  2693.     mov    ah,ioctl
  2694.     xor    al,al            ; 0 = get info
  2695.     int    dos
  2696.     mov    ah,close2        ; close it
  2697.     int    dos
  2698.     mov    ax,offset decbuf    ; point to filename again
  2699.     and    dl,80h            ; ISDEV bit
  2700.     mov    filtst.fstat2,dl    ; 0 = disk file, else device
  2701.     test    dl,80h            ; ISDEV bit set?
  2702.     jz    gofi11            ; z = no, not a device
  2703.     jmp    gofi16            ; device, use name as given
  2704. gofi11:    cmp    flags.flwflg,filecol_discard    ; no-supersede existing file?
  2705.     jne    gofi12            ; ne = no (i.e., do a rename)
  2706.     cmp    flags.flwflg,filecol_update ; updating?
  2707.     je    gofi16            ; e = yes, delay opening
  2708.     cmp    flags.flwflg,filecol_overwrite    ; overwrite existing file?
  2709.     je    gofi16            ; e = yes
  2710.  
  2711. gofi11a:mov    flags.cxzflg,'X'    ; say stop this file
  2712.     mov    word ptr decbuf,'UN'
  2713.     mov    decbuf+2,'L'        ; file name of NUL
  2714.     mov    decbuf+3,0        ; asciiz
  2715.     jmp    short gofi13
  2716. gofi12:    cmp    flags.flwflg,filecol_rename ; rename existing file?
  2717.     jne    gofi16            ; ne = no
  2718.     mov    ax,offset decbuf    ; point to filename again
  2719.     call    unique            ; generate unique name
  2720.     jc    gofi14            ; could not generate a unique name
  2721.     test    flags.remflg,dquiet    ; quiet display mode?
  2722.     jnz    gofi13            ; nz = yes, skip printing
  2723.     push    ax            ; save unique name again
  2724.     call    frpos            ; position cursor
  2725.     mov    ah,prstr           ; say we are renaming the file
  2726.     mov    dx,offset infms5
  2727.     int    dos
  2728.     pop    ax            ; get name back into ax again
  2729.     push    ax            ; save around these calls
  2730.     mov    dx,ax            ; print current filename
  2731.     call    prtasz            ; display filename
  2732.     pop    ax            ; pointer to name, again
  2733. gofi13:    jmp    short gofi16        ; and go handle file
  2734.  
  2735. gofi14:    mov    dx,offset ermes4
  2736.     call    ermsg
  2737.     stc                ; failure, dx has msg pointer
  2738.     ret
  2739.  
  2740. gofi16:    mov    si,offset decbuf    ; pointer to (maybe new) name
  2741.     mov    di,offset diskio.string    ; filename, used in open
  2742.     call    strcpy             ; copy name to diskio.string
  2743.     xor    ax,ax
  2744.     mov    diskio.sizehi,ax    ; original file size is unknown
  2745.     mov    diskio.sizelo,ax    ; double word
  2746.     mov    tfilsz,ax        ; set bytes received to zero
  2747.     mov    tfilsz+2,ax
  2748.     mov    ax,-1            ; get a minus one
  2749.     mov    oldkbt,ax
  2750.     mov    oldper,ax
  2751.     mov    wrpmsg,al
  2752.     clc                ; finished composing filename
  2753.     ret                ; in diskio.string
  2754.  
  2755. gofi18a:mov    si,ax             ; pointer to local override name
  2756.     mov    di,offset diskio.string    ; filename, used in open
  2757.     call    strcpy             ; copy name to diskio.string
  2758.                     ; fall    through to gofi18
  2759. gofi18:    test    flags.remflg,dquiet    ; quiet display mode?
  2760.     jnz    gofi19            ; nz = yes, don't try printing
  2761.     mov    dx,offset erms12    ; unable to create file
  2762.     call    ermsg
  2763.     push    dx
  2764.     mov    dx,offset diskio.string    ; print offending name
  2765.     call    prtasz            ; display filename
  2766.     pop    dx
  2767. gofi19:    stc                ; failure, dx has msg pointer
  2768.     ret
  2769. gofil    endp
  2770.  
  2771. ; Open file for writing with name in diskio.string
  2772. goopen    proc    near
  2773.     xor    ax,ax
  2774.     mov    dblbyteflg,al        ; clear decoder state variable
  2775.     mov    shiftstate,al        ; locking shift state
  2776.     mov    DLEseen,al        ; escape state
  2777.     mov    tfilsz,ax        ; set bytes received to zero
  2778.     mov    tfilsz+2,ax
  2779.     mov    ax,-1            ; get a minus one
  2780.     mov    oldkbt,ax
  2781.     mov    oldper,ax
  2782.  
  2783.     cmp    diskio.handle,-1    ; is handle unused?
  2784.     je    goopen5            ; e = yes
  2785.     mov    dx,diskio.handle    ; close the file now
  2786.     mov    ah,close2
  2787.     int    dos
  2788.     mov    diskio.handle,-1    ; clear handle of previous usage
  2789. goopen5:mov    ax,offset diskio.string    ; filename, asciiz
  2790.     call    isfile        ; check for read-only/system/vol-label/dir
  2791.     jc    goopen1            ; c = file does not exist
  2792.     test    byte ptr filtst.dta+21,1fh    ; the no-no file attributes
  2793.     jnz    gofi18            ; nz = do not write over one of these
  2794.     jmp    short goopen2        ; open existing
  2795.  
  2796. goopen1:test    filtst.fstat,80h    ; access problem?
  2797.     jnz    gofi18            ; nz = yes, quit here
  2798.     mov    dx,offset diskio.string    ; filename, asciiz
  2799.     mov    ah,creat2        ; create file
  2800.     xor    cx,cx            ; 0 = attributes bits
  2801.     int    dos
  2802.     jc    goopen2            ; c = did not work, try regular open
  2803.     mov    diskio.handle,ax    ; save file handle here
  2804.     xor    dx,dx            ; file size, high word
  2805.     xor    ax,ax            ; low word
  2806.     clc                ; carry clear for success
  2807.     ret
  2808. goopen2:test    byte ptr filtst.dta+21,1bh    ; r/o, hidden, volume label?
  2809.     jnz    gofi18            ; we won't touch these
  2810.     mov    dx,offset diskio.string    ; filename, asciiz
  2811.     mov    ah,open2           ; open existing file (usually a device)
  2812.     mov    al,1+1            ; open for writing
  2813.     int    dos
  2814.     jc    gofi18            ; carry set means can't open
  2815.     mov    diskio.handle,ax    ; file handle
  2816.     cmp    flags.flwflg,filecol_update ; updating?
  2817.     jne    goopen2c        ; ne = no
  2818.     mov    ah,fileattr        ; get file date/time attributes
  2819.     xor    al,al            ; get, not set
  2820.     mov    bx,diskio.handle    ; file handle
  2821.     int    dos            ; dx=date, cx=time
  2822.     cmp    dx,word ptr fdate    ; date is earlier than our file?
  2823.     ja    goopen2a        ; a = yes, skip file
  2824.     jb    goopen2c        ; b = incoming date is later
  2825.     cmp    cx,word ptr ftime    ; same date, how about time
  2826.     jb    goopen2c        ; b = later time, get the file
  2827. goopen2a:mov    dx,diskio.handle    ; file handle
  2828.     mov    ah,close2        ; close it
  2829.     int    dos
  2830.     mov    flags.cxzflg,'X'    ; say stop this file
  2831.     mov    ah,open2
  2832.     mov    al,1            ; open for writing
  2833.     cmp    dosnum,300h        ; above DOS 2?
  2834.     jb    goopen2b        ; b = no, so no shared access
  2835.     or    al,40h            ; open for reading, deny none
  2836. goopen2b:mov    dx,offset vacuum    ; NUL as a filename
  2837.     int    dos
  2838.     mov    diskio.handle,ax    ; file handle
  2839.     stc                ; carry set for failure
  2840.     ret
  2841.  
  2842. goopen2c:cmp    flags.flwflg,filecol_append ; append to existing file?
  2843.     je    goopen3            ; e = yes
  2844.     clc                ; carry clear for success
  2845.     ret
  2846. goopen3:mov    bx,diskio.handle    ; file handle for seeking
  2847.     xor    cx,cx            ; high order displacement
  2848.     xor    dx,dx            ; low order part of displacement
  2849.     mov    ah,lseek        ; seek to EOF (to do appending)
  2850.     mov    al,2            ; says to EOF
  2851.     int    dos
  2852.     ret                ; return DX:AX as new file pointer
  2853. goopen    endp
  2854.  
  2855. ; Given incoming filename in 'decbuf'.  Verify that each char is legal
  2856. ; (if not change it to an "X"), force max of three chars after a period (dot)
  2857. ; Source is at ds:si (si is changed here).
  2858.  
  2859. VERFIL    PROC    FAR
  2860.     push    es            ; verify each char in 'data'
  2861.     push    cx
  2862.     push    ds
  2863.     pop    es
  2864.     push    bx
  2865.     xor    bx,bx            ; bl = have dot, bh = 8 char count
  2866.     cld
  2867. verfi1:    lodsb                ; get a byte of name from si
  2868.     and    al,7fH            ; strip any eighth bit
  2869.     jz    verfi5            ; z = end of name
  2870.     cmp    al,'.'            ; a dot?
  2871.     jne    verfi2            ; ne = no
  2872.     cmp    bl,0            ; have one dot already?
  2873.     jne    verfi3            ; ne = yes, change to X
  2874.     mov    byte ptr [si+3],0    ; forceably end filename after 3 char ext
  2875.     mov    bl,1            ; say have a dot now
  2876.     jmp    short verfi4        ; continue
  2877. verfi2:    or    bl,bl            ; have read a dot?
  2878.     jnz    verfi2a            ; nz = yes
  2879.     inc    bh            ; count base
  2880.     cmp    bh,8            ; done all base bytes?
  2881.     ja    verfi1            ; a = yes, discard excess
  2882. verfi2a:cmp    al,3ah            ; colon?
  2883.     je    verfi4
  2884.     cmp    al,5ch            ; backslash path separator?
  2885.     je    verfi4
  2886.     cmp    al,2fh            ; or forward slash?
  2887.     je    verfi4
  2888.     cmp    al,'0'
  2889.     jb    verfi3            ; see if it's a legal char < '0'
  2890.     cmp    al,'9'
  2891.     jbe    verfi4            ; it's between 0-9 so it's OK
  2892.     cmp    al,'A'
  2893.     jb    verfi3            ; check for a legal punctuation char
  2894.     cmp    al,'Z'
  2895.     jbe    verfi4            ; it's A-Z so it's OK
  2896.     cmp    al,'a'
  2897.     jb    verfi3            ; check for a legal punctuation char
  2898.     cmp    al,'z'
  2899.     ja    verfi3
  2900.     and    al,5FH            ; it's a-z, capitalize
  2901.     jmp    short verfi4        ; continue with no change
  2902.  
  2903. verfi3:    push    di            ; special char. Is it on the list?
  2904.     mov    di,offset spchar2    ; list of acceptable special chars
  2905.     mov    cx,spc2len
  2906.     cld
  2907.     repne    scasb            ; search string for input char
  2908.     pop    di
  2909.     je    verfi4            ; e = in table, return it
  2910.     mov    al,'X'            ; else illegal, replace with "X"
  2911.     mov    nmoflg,1        ; say we have a replacement filename
  2912. verfi4:    mov    [si-1],al        ; update name
  2913.     jmp    short verfi1        ; loop thru rest of name
  2914. verfi5:    mov    byte ptr[si-1],0    ; make sure it's null terminated
  2915.     pop    bx
  2916.     pop    cx
  2917.     pop    es
  2918.     ret
  2919. VERFIL    ENDP
  2920.  
  2921. ; find a unique filename.
  2922. ; Enter with a pointer to a (null-terminated) filename in ax
  2923. ; Return with same pointer but with a new name (or old if failure)
  2924. ; Success = carry clear; failure = carry set
  2925. ; The idea is to pad out the main name part (8 chars) with ascii zeros and
  2926. ; then change the last chars successively to a 1, 2, etc. until
  2927. ; a unique name is found. All registers are preserved
  2928. ; Make empty main name fields start with letter X, not digit 0
  2929. unique    proc    near
  2930.     push    bx
  2931.     push    cx
  2932.     push    dx
  2933.     push    si
  2934.     push    di
  2935.     push    es
  2936.     push    ax            ; save address of source string
  2937.     mov    dx,ds            ; make es use ds segment
  2938.     mov    es,dx
  2939.     mov    dx,ax            ; point at original filename string
  2940.     mov    di,offset templp    ; place for path
  2941.     mov    si,offset templf    ; place for filename
  2942.     call    fparse            ; separate path (di) and filename (si)
  2943.     mov    dx,di            ; point at path part
  2944.     call    strlen            ; put length in cx
  2945.     mov    si,ax            ; point to original string
  2946.     add    si,cx            ; point to filename part
  2947.     mov    di,offset templf    ; destination is temporary location
  2948.     xor    cx,cx            ; a counter
  2949.     cld                ; set direction to be forward
  2950. uniq1:    lodsb                ; get a byte
  2951.     cmp    al,'.'            ; have a dot?
  2952.     je    uniq2            ; e = yes
  2953.     or    al,al            ; maybe    null at end?
  2954.     jnz    uniq3            ; nz = no, continue loop
  2955.  
  2956. uniq2:    cmp    cl,8            ; have we copied any chars before dot?
  2957.     jge    uniq3            ; ge = all 8
  2958.     mov    byte ptr [di],'0'    ; avoid clobbers; pad with 0's
  2959.     or    cl,cl            ; first char of filename?
  2960.     jnz    uniq2a            ; nz = no
  2961.     mov    byte ptr [di],'X'    ; start name with letter X, not 0
  2962. uniq2a:    inc    di            ; and count the output chars
  2963.     inc    cl            ; and this counter too
  2964.     jmp    short uniq2        ; continue until filled 8 slots
  2965. uniq3:    inc    cl            ; cl = # char in destination
  2966.     stosb                ; store the char
  2967.     or    al,al            ; null at end?
  2968.     jnz    uniq1            ; nz = no, continue copying
  2969.  
  2970.     mov    templf+7,'1'        ; put '1' in last name char
  2971.     mov    unum,1            ; start with this generation digit
  2972.  
  2973. uniq4:    mov    di,offset rdbuf        ; build a temporary full filename
  2974.     mov    si,offset templp    ; path part
  2975.     call    strcpy            ; copy that much
  2976.     mov    si,offset templf    ; get rebuilt filename part
  2977.     call    strcat            ; paste that to the end
  2978.     mov    ax,offset rdbuf        ; point to full name
  2979.     call    isfile            ; does it exist?
  2980.     jc    uniq6            ; c = no, succeed now
  2981.  
  2982.     inc    unum            ; move to next generation
  2983.     mov    di,offset templf+7    ; point to last name char
  2984.     mov    cx,7            ; max # of digits to play with
  2985.     mov    bx,10            ; divisor (16 bits)
  2986.     mov    ax,unum            ; low order part of generation #
  2987. uniq5:    xor    dx,dx            ; high order part of generation #
  2988.     div    bx            ; compute digit (unum / 10)
  2989.     add    dl,'0'            ; make remainder part printable
  2990.     mov    [di],dl            ; put into right place
  2991.     or    ax,ax            ; any more to do? (quotient nonzero)
  2992.     jz    uniq4            ; z = no, try this name
  2993.     dec    di            ; else decrement char position
  2994.     loop    uniq5            ;   and keep making a number
  2995.     stc                ; failure: set carry, keep old name
  2996.     jmp    short uniq7        ;   and exit
  2997.  
  2998. uniq6:    pop    di            ; address of original filename
  2999.     push    ax            ; save for exit clean up
  3000.     mov    si,offset rdbuf
  3001.     call    strcpy            ; copy new filename over old
  3002.     clc                ; success: clear carry flag
  3003. uniq7:    pop    ax
  3004.     pop    es
  3005.     pop    di
  3006.     pop    si
  3007.     pop    dx
  3008.     pop    cx
  3009.     pop    bx
  3010.     ret
  3011. unique    endp
  3012. code    ends 
  3013.  
  3014. code1    segment
  3015.     assume cs:code1    
  3016.  
  3017. ; strlen -- computes the length, excluding the terminator, of an asciiz
  3018. ;    string. Input: ds:dx = address of the string
  3019. ;        Output: cx = the byte count
  3020. ;    All registers except cx are preserved
  3021. ;
  3022. STRLEN    PROC    FAR
  3023.     push    di
  3024.     push    es
  3025.     push    ax
  3026.     mov    ax,ds            ; use proper segment address
  3027.     mov    es,ax
  3028.     mov    di,dx
  3029.     mov    cx,0ffffh        ; large byte count
  3030.     cld                ; set direction to be forward
  3031.     xor    al,al            ; item sought is a null
  3032.     repne    scasb            ; search for it
  3033.     add    cx,2            ; add for -1 and auto dec in scasb
  3034.     neg    cx              ; convert to count, excluding terminator
  3035.     pop    ax
  3036.     pop    es
  3037.     pop    di
  3038.     ret
  3039. STRLEN    ENDP
  3040.  
  3041. ; strcat -- concatenates asciiz string 2 to the end of asciiz string 1
  3042. ;    offset of string 1 is expected to be in ds:di. input & output
  3043. ;    offset of string 2 is expected to be in ds:si. input only (unchanged)
  3044. ;    Preserves all registers. No error returns, returns normally via ret
  3045. ;
  3046. STRCAT    PROC    FAR
  3047.     push    di            ; save work registers
  3048.     push    si
  3049.     push    es
  3050.     push    dx
  3051.     push    cx
  3052.     push    ax
  3053.     mov    ax,ds            ; get data segment value
  3054.     mov    es,ax            ; set es to ds for implied es:di usage
  3055.     mov    dx,di
  3056.     call    strlen        ; get length (w/o terminator) of dest string
  3057.     add    di,cx            ; address of first terminator
  3058.     mov    dx,si            ; start offset of source string
  3059.     call    strlen            ; find its length too (in cx)
  3060.     inc    cx            ; include its terminator in the count
  3061.     cld
  3062.     rep    movsb        ; copy source string to end of output string
  3063.     pop    ax
  3064.     pop    cx
  3065.     pop    dx
  3066.     pop    es
  3067.     pop    si
  3068.     pop    di
  3069.     ret
  3070. STRCAT    ENDP
  3071.  
  3072. ; strcpy -- copies asciiz string pointed to by ds:si into area pointed to by
  3073. ;    ds:di. Returns via ret. All registers are preserved
  3074. ;
  3075. STRCPY    PROC    FAR
  3076.     cmp    si,di            ; same place?
  3077.     jne    strcpy1            ; ne = no
  3078.     ret                ; having done nothing
  3079. strcpy1:mov    byte ptr [di],0        ; clear destination string
  3080.     call    strcat            ; let strcat do the real work
  3081.     ret
  3082. STRCPY    ENDP
  3083.  
  3084. ; fparse -- separate the drive:path part from the filename.ext part of an
  3085. ;    asciiz string. Characters separating parts are  \ or / or :
  3086. ;    Inputs:    asciiz input full filename string offset in ds:dx
  3087. ;        asciiz path offset in ds:di
  3088. ;        asciiz filename offset in ds:si
  3089. ;    Outputs: the above strings in the indicated spots
  3090. ;    Strategy is simple. Reverse scan input string until one of the
  3091. ;    three separators is encountered and then cleave at that point
  3092. ;    Simple filename construction restrictions added 30 Dec 1985;
  3093. ;    to wit: mainname limited to 8 chars or less,
  3094. ;    extension field limited to 3 chars or less and is found by searching
  3095. ;    for first occurence of a dot in the filename field. Thus the whole
  3096. ;    filename part is restricted to 12 (8+dot+3) chars plus a null
  3097. ;    All registers are preserved. Return is always via ret
  3098. ;    (Microsoft should have written this for DOS 2.x et seq.)
  3099.  
  3100. FPARSE    PROC    FAR
  3101.     push    cx            ; local counter
  3102.     push    ax            ; local work area
  3103.     push    es            ; implied segment register for di
  3104.     push    di            ; offset of path part of output
  3105.     push    si            ; offset of file name part of output
  3106.     mov    ax,ds            ; get data segment value
  3107.     mov    es,ax            ; set es to ds for implied es:di usage
  3108.     mov    byte ptr [si],0        ; clear outputs
  3109.     mov    byte ptr [di],0
  3110.  
  3111.     push    si            ; save original file name address
  3112.     mov    si,dx            ; get original string address
  3113.     call    strcpy            ; copy string to original di
  3114.     call    strlen            ; find length (w/o terminator), in cx
  3115.     mov    si,di            ; address of string start
  3116.     add    si,cx
  3117.     dec    si            ; si = address of last non-null char
  3118.     jcxz    fpars5            ; if null skip the path scan
  3119.                     ; now find last path char, if any
  3120.                     ; start at the end of input string
  3121.     std                 ; set direction to be backward
  3122. fpars4:    lodsb                 ; get a byte (dec's si afterward)
  3123.     cmp    al,5ch            ; is it a backslash ('\')? 
  3124.     je    fpars6          ; e = yes
  3125.     cmp    al,2fh            ; or forward slash ('/')?
  3126.     je    fpars6          ; e = yes
  3127.     cmp    al,3ah            ; or even the drive terminator colon?
  3128.     je    fpars6            ; e = yes
  3129.     loop    fpars4             ; else keep looking until cx == 0
  3130.                       ; si is at beginning of file name
  3131. fpars5:    dec    si            ; dec for inc below
  3132. fpars6:    inc    si
  3133.     inc    si            ; si now points at first filename char
  3134.                     ; cx holds number of path chars
  3135.                     ; get original file name address (si)
  3136.     pop    di            ; and make it place to copy filename
  3137.     cld                ; reset direction to be forward
  3138.     mov    ax,si            ; ax holds filename address for awhile
  3139.     push    dx
  3140.     mov    dx,si            ; strlen wants string pointer in dx
  3141.     call    strlen            ; get length of filename part into cx
  3142.     pop    dx
  3143.     jcxz    fpar7a            ; any chars to look at? z = no
  3144. fpars7:    cmp    byte ptr [si],'.'    ; look for a dot in filename
  3145.     je    fpars8            ; e = found one
  3146.     inc    si            ; look at next filename char
  3147.     loop    fpars7            ; keep looking until cx = zero
  3148. fpar7a:    mov    si,ax            ; no dot. recover starting address
  3149.     mov    byte ptr [si+8],0    ; forcably truncate mainname to 8 char
  3150.     call    strcpy            ; copy this part to filename field
  3151.     jmp    short fparsx        ;  and exit
  3152. fpars8: mov    byte ptr [si+4],0   ; plant terminator after dot + 3 ext chars
  3153.     mov    cx,si
  3154.     sub    cx,ax        ; cx now = number of chars in mainname field
  3155.     cmp    cx,9            ; more than 8?
  3156.     jb    fpars9            ; b = no, we're safe
  3157.     mov    cx,8             ; limit ourselves to 8 chars in mainname
  3158. fpars9: push    si             ; remember address of dot and extension
  3159.     mov    si,ax            ; point to start of input filename
  3160.     rep    movsb            ; copy cx chars from si to di (output)
  3161.     mov    byte ptr [di],0        ; plant terminator where dot goes
  3162.     pop    si            ; source = dot and extension address
  3163.     call    strcat        ; append the dot & ext to the filename field
  3164. fparsx: mov    si,ax        ; recover start of filename in input string
  3165.     mov    byte ptr [si],0        ; terminate path field
  3166.     pop    si
  3167.     pop    di
  3168.     pop    es
  3169.     pop    ax
  3170.     pop    cx
  3171.     ret
  3172. FPARSE    ENDP    
  3173.  
  3174. ; Print filename in offset diskio.string.
  3175. PRTFN    PROC    FAR
  3176.     test    flags.remflg,dquiet    ; quiet display mode?
  3177.     jnz    prtfn1            ; nz = yes, don't display filename
  3178.     push    ax            ; saves for messy clrfln routine
  3179.     push    bx
  3180.     push    dx
  3181.     call    clrfln            ; position cursor & blank out the line
  3182.     mov    dx,offset diskio.string
  3183.     call    prtasz
  3184.     pop    dx
  3185.     pop    bx
  3186.     pop    ax
  3187. prtfn1:    ret
  3188. PRTFN    ENDP
  3189.  
  3190.  
  3191. ; Print string to screen from offset ds:di for # bytes given in cx,
  3192. ; regardless of $'s.  All registers are preserved.
  3193.  
  3194. PRTSCR    PROC    FAR
  3195.     jcxz    prtscr4            ; cx = zero means nothing to show
  3196.     push    ax
  3197.     push    bx
  3198.     push    dx
  3199.     mov    dx,di            ; source ptr for DOS
  3200.     cmp    flags.eofcz,0        ; end on Control-Z?
  3201.     jne    prtscr3            ; ne = yes, let DOS do it
  3202.     push    cx            ; else map Control-Z to space
  3203.     push    di
  3204.     push    es
  3205.     push    ds
  3206.     pop    es            ; data to es
  3207.     mov    al,ctlz            ; look for Control-Z
  3208.     cld                ; scan buffer es:di, cx chars worth
  3209. prtscr1:repne    scasb
  3210.     jne    prtscr2            ; ne = found no Control-Z's
  3211.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  3212.     jcxz    prtscr2            ; z = examined all chars
  3213.     jmp    short prtscr1        ; until examined everything
  3214. prtscr2:pop    es
  3215.     pop    di
  3216.     pop    cx
  3217. prtscr3:mov    bx,1            ; stdout file handle
  3218.     mov    ah,write2
  3219.     int    dos
  3220.     pop    dx
  3221.     pop    bx
  3222.     pop    ax
  3223. prtscr4:ret
  3224. PRTSCR    ENDP
  3225.  
  3226. ; Print to screen asciiz string given in ds:dx. Everything preserved.
  3227. PRTASZ    PROC    FAR
  3228.     push    cx
  3229.     push    di
  3230.     call    strlen            ; get length of asciiz string
  3231.     mov    di,dx            ; where prtscr looks
  3232.     call    prtscr            ; print counted string
  3233.     pop    di
  3234.     pop    cx
  3235.     ret
  3236. PRTASZ    ENDP
  3237.  
  3238. ; Convert \ in string at ds:si to forward slash. Preserve all but AX.
  3239. fwdslash proc    far
  3240.     push    si
  3241.     push    di
  3242.     push    es
  3243.     cld
  3244.     mov    ax,ds
  3245.     mov    es,ax
  3246.     mov    di,si
  3247. fwds1:    lodsb
  3248.     cmp    al,'\'            ; backslash?
  3249.     jne    fwds2            ; ne = no
  3250.     mov    al,'/'            ; forward slash
  3251. fwds2:    stosb
  3252.     or    al,al            ; end of string?
  3253.     loopnz    fwds1            ; loop while string
  3254.     pop    es
  3255.     pop    di
  3256.     pop    si
  3257.     ret
  3258. fwdslash endp
  3259.  
  3260. ; Convert / in string at ds:si to back slash. Preserve all but AX.
  3261. bakslash proc    far
  3262.     push    si
  3263.     push    di
  3264.     push    es
  3265.     cld
  3266.     mov    ax,ds
  3267.     mov    es,ax
  3268.     mov    di,si
  3269. baks1:    lodsb
  3270.     cmp    al,'/'            ; forward slash?
  3271.     jne    baks2            ; ne = no
  3272.     mov    al,'\'            ; back slash
  3273. baks2:    stosb
  3274.     or    al,al            ; end of string?
  3275.     loopnz    baks1            ; loop while string
  3276.     pop    es
  3277.     pop    di
  3278.     pop    si
  3279.     ret
  3280. bakslash endp
  3281.  
  3282. ; Create directories for path string in ds:di
  3283. ; Omit elements starting with a dot
  3284. mkpath    proc    far
  3285.     push    bx
  3286.     push    dx
  3287.     push    si
  3288.     push    di
  3289.     push    es
  3290.     mov    si,ds
  3291.     mov    es,si
  3292.     cld
  3293.     mov    si,di
  3294.     mov    dx,di
  3295.     mov    bx,dx        ;start of current element
  3296. mkp1:    lodsb
  3297.     or    al,al
  3298.     jz    mkp4        ; z = end of string
  3299.     cmp    al,'/'        ; forward slash?
  3300.     jne    mkp1a        ; ne = no
  3301.     mov    al,'\'        ; convert to backslash
  3302. mkp1a:    cmp    al,'\'        ; path separator?
  3303.     je    mkp2        ; e = yes
  3304.     stosb
  3305.     jmp    short mkp1
  3306. mkp2:    mov    byte ptr [di],0 ; terminator
  3307.     cmp    byte ptr [bx],'.' ; element starts with dot?
  3308.     jne    mkp3        ; ne = no
  3309.     mov    di,bx        ; overwrite it
  3310.     mov    byte ptr [di],0    ; nullify it
  3311.     jmp    short mkp1    ; get next path element
  3312.  
  3313. mkp3:    push    si
  3314.     mov    si,bx        ; si to start of this element
  3315.     call    verfil        ; mung string
  3316.     mov    di,si        ; where to write next
  3317.     pop    si
  3318.     mov    ah,39h        ; mkdir from ds:dx
  3319.     int    dos
  3320.     dec    di
  3321.     mov    al,'\'        ; put back separator
  3322.     stosb
  3323.     mov    bx,di        ; where next element starts
  3324.     jmp    short mkp1
  3325. mkp4:    pop    es
  3326.     pop    di
  3327.     pop    si
  3328.     pop    dx
  3329.     pop    bx
  3330.     ret
  3331. mkpath    endp
  3332. code1    ends 
  3333.     end
  3334.