home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / txtutl / bishow34.ark / BISHOW34.ASM < prev    next >
Assembly Source File  |  1987-09-25  |  51KB  |  1,981 lines

  1.  
  2. ; BISHOW v34 - buffered bidirectional file scroll utility'
  3. ;
  4. ; Ver 34, 25 Sep 1987, Ernest F. Barnhart, N8DVE, Dayton, OH
  5. ;    - Added cursor off/on for the Kaypro computers.
  6. ;    - Changed back to using control key for real Wordstar
  7. ;         compatibility.
  8. ;    - Changed keys to allow the set function to work correctly.
  9. ;    - Changed format of help screen.
  10. ;    - Changed format of help lines.
  11. ;
  12. ; Ver 33, 29 Sep 86, Charlie Kestner, Hammond, Ind
  13. ;    - clarified the LIBRARY AND SQUEEZE help message
  14. ;         since this is probably version MOST folk would use.
  15. ;    - eliminated having to use control key.  Now just plain
  16. ;         S, D, E, X, E, & C function for Wordstar users.
  17. ;    - changed over some of the command keys for folk who
  18. ;         like to use cursor/numeric pad.  NO need to shift
  19. ;         the numeric pad, plain numbers will do it.
  20. ;    - long help key is now "/".
  21. ;
  22. ; Ver 32, 3 Nov 85, Rod Clark, Seattle WA
  23. ;    - added Wordstar cursor pad (^C now = page down).
  24. ;    - ESC exits, clears screen. Q exits, leaves screen.
  25. ;    - Wrong keys are ignored.  H = brief help. ? = help.
  26. ;    - SHORT  +  SQUEEZE  +    LIBRARY = .COM file < 2k.
  27. ;    - SHORT, no SQUEEZE, no LIBRARY = .COM file < 1k.
  28. ;    - SHORT disables setting each margin interactively
  29. ;         (the command line still sets the right margin and
  30. ;         the page length), but it does let you scroll back
  31. ;         and forth horizontally by tab stops within a file.
  32. ;         The SHORT version gives two sets of cursor keys
  33. ;         (Wordstar and CR/SP etc), but no help display.
  34. ;    - BISHOW (no filename) tells whether it works on .LBR
  35. ;         or squeezed files, or both, or just on plain files.
  36. ;    - and fixed jumbled multiple-line .LBR directory.
  37. ;
  38. ; Ver 31, 15 Jan 84, Frans van Duinen, Toronto, Ont
  39. ;    - made unsqueeze message optional
  40. ;    - added library capability
  41. ;    - fixed bug in conditional assembly of CLRSCR
  42. ;
  43. ; Ver 29, 7 Jan 84, Frans van Duinen, Toronto, Ont
  44. ;    - Modified USQ routines for higher speed (+10%) and
  45. ;         less memory usage.
  46. ;    - made USQ code optional through conditional assembly
  47. ;    - fixed a bug introduced with 2.08 and SHORT=TRUE
  48. ;         (resulted from ASM's inability to nest IF/ENDIF)
  49. ;    - fixed a bug  that reset FCBEX after open, whenever
  50. ;         record 0 was read, (this resulted in BDOS assuming that
  51. ;         the current extent, whose allocation group nos were still
  52. ;         in the FCB, was the correct one.
  53. ;    - Changed exit to clear screen only on Q or ^C exit,
  54. ;         to leave any messages visible
  55. ;    - Made wait after clear screen a cond assembly option
  56. ;
  57. ; Ver 28, 2 Jan 84, Frans van Duinen, Toronto, Ont
  58. ;    - added squeezed file capability
  59. ;    - added sidewise scrolling on ^I, ^L, steps of 8
  60. ;    - Osborne support for cursor keys, clr scr & scr size
  61. ;    - Changed FILBAK rtn to recognize top of file
  62. ;    - Set up flag to avoid unnecessary re-reading of
  63. ;         top of file
  64. ;
  65. ;         The unsqueeze code was lifted from the USQ
  66. ;         base code by Dave Rand (Edmonton, Alberta)
  67. ;         as adapted for LTYPE1 by Sigi Kluger of El
  68. ;         Paso,Texas.  The code was lifted, to allow
  69. ;         continued use of ASM.COM
  70. ;
  71. ;
  72. ; Ver 17, 1 Aug 83, Ted H. Emigh  ...!unc!tucc!emigh
  73. ;    - added screen width specification
  74. ;    - added screen definition commands (see notes below)
  75. ;
  76. ; Ver 16, 2 Jul 83, Chuck Forsberg
  77. ;    - added commands for more, mince, vi familiarity.
  78. ;         Bad command gives help.
  79. ;
  80. ; Ver 15.1, 26 June 83, Dick Mead
  81. ;    - added "?" for help on commands.
  82. ;
  83. ; Ver 15, 31 May 83, Bruce Ratoff
  84. ;    - added 'N' (next line) and 'P' (previous line) cmds
  85. ;    - decreased buffer from 8k to 4k (8k takes too long)
  86. ;
  87. ; Ver 14, 15 May 83, Keith Petersen, W8SDZ
  88. ;    - fixed bug which caused display past end-of-file
  89. ;        and added bogus eof in case none at file end
  90. ;    - added strip of high-order bit in line count routine
  91. ;    - added exit clear of any left-over keyboard character
  92. ;
  93. ; Ver 13, 11 May 83, Keith Petersen, W8SDZ
  94. ;    - fixed to allow assembly with ASM.COM
  95. ;    - fixed screen clear bug when crossing read boundries
  96. ;    - added strip for high-order bit in character before
  97. ;        printing (needed for WordStar files)
  98. ;    - improved stack routines
  99. ;    - fixed bug in console input routine
  100. ;    - removed Z80 dependant code (now works on 8080 too)
  101. ;
  102. ; Ver 12, 06 May 83, Lucien Pan, Toronto, Canada
  103. ;    - fixed some minor bugs
  104. ;    - returns to ccp w/o warm boot
  105. ;    - filters form-feeds (useful in .PRN files)
  106. ;    - scrolls foward/backwards by same number of lines
  107. ;    - disable/enable cursor during scroll for H-19
  108. ;
  109. ; Ver 11, 30 Mar 83 - added BDOS function  6.  W.F.Mcgee
  110. ;
  111. ; Ver 10, 23 Aug 82 Phil Cary, 748 Kenilworth Parkway, Baton
  112. ;         Baton Rouge, LA  70808
  113. ;
  114. ;-----------------------------------------------------------------------
  115. ;
  116. ; BISHOW is a buffered, bidirectional version of SHOW.ASM which first
  117. ; appeared in Interface Age, November, 1981.  That program could only
  118. ; scroll forward in a file, and read records from a disk one at a time
  119. ; as they were sent to the console.  I used SHOW frequently to take a
  120. ; quick look at a file without loading a big text editor, and to examine
  121. ; another file with the RUN command while in Wordstar.    TYPE does not
  122. ; work since it is not a file that Wordstar can load and run.
  123. ;
  124. ; This bidirectional version uses random access reads.    In addition,
  125. ; buffering was added so that the number of disk reads would be reduced
  126. ; and moving back and forth in a moderate sized file would be speeded up.
  127. ; There is a trade-off between the size of the buffer and the length of
  128. ; time it takes to refill the buffer which should be set to the user's
  129. ; preference.
  130. ;
  131. ; There are several customizing items in this program.    One is the
  132. ; equate "MAXREC" which sets the buffer size.  Another is the string
  133. ; in the subroutine "CLRSCR" just after the ORG statement.  This should
  134. ; be changed to erase the screen and home the cursor for the user's
  135. ; terminal.  The program, as written, requires a terminal with an erase
  136. ; screen and home cursor function.  Some terminals do not allow the 80th
  137. ; column to be filled without going to the next line.  For this reason,
  138. ; the screen width ("MAXCHR") initially is set to 79. The screen sizes
  139. ; can be changed using the "S" (screen) command.  The parameters that
  140. ; can be changed are the maximum column displayed ("MAXCHR"), the mini-
  141. ; mum column displayed (allowing you to "window" the output) and the
  142. ; number of lines ("SCROLN").  A zero for the maximum column displayed
  143. ; willgive an unlimited screen width.  The maximum column displayed and
  144. ; the number of lines can be set when calling BISHOW, such as "BISHOW
  145. ; FILENAME.EXT 79 24" will give 79 columns and 24 lines with "BISHOW
  146. ; FILENAME.EXT 79" will give 79 columns with the default number of lines.
  147. ; The last customizing item is the "short" equate.  If this is chosen
  148. ; the multiplicity of command forms is not allowed (see the beginning to
  149. ; change the commands used) and certain messages are shortened.  This
  150. ; will allow BISHOW to fit into a 1K area.  Direct I/O to the console is
  151. ; used to avoid echoing the commands to the console as the CP/M write
  152. ; console function does.
  153. ;
  154. ; Justa small contribution to the public domain software as partial pay-
  155. ; ment for the many fine and educational programs the system has given
  156. ; me.
  157. ;                    - Phil Cary.
  158. ;-----------------------------------------------------------------------
  159. ;Define version number for help message
  160. ;
  161. VERS    EQU    3
  162. REVS    EQU    4
  163. ;
  164. ;
  165. NO    EQU    0
  166. YES    EQU    NOT NO
  167. ;
  168. ; ASCII equates
  169. ;
  170. ENDMSG    EQU    0        ; Null
  171. BS    EQU    8        ; Backspace
  172. TAB    EQU    9        ; Tab
  173. LF    EQU    0AH        ; Line feed
  174. FEED    EQU    0CH        ; Form feed
  175. CR    EQU    0DH        ; Carriage return
  176. EOF    EQU    1AH        ; End of file
  177. ESC    EQU    1BH        ; Escape
  178. SPACE    EQU    20H        ; Space
  179. ;
  180. ;-----------------------------------------------------------------------
  181. ;
  182. ; User settings
  183. ;
  184. KAYPRO    EQU    YES        ; Use cursor on/off function
  185. HEATH    EQU    NO        ; Assemble for H-19 terminal
  186. OSBORNE    EQU    NO        ; Assemble for 52-column screen
  187. ;
  188. SHORT    EQU    NO        ; No SQ or LBR = 1k / with SQ and LBR = 2k
  189. LONG    EQU    YES        ; Duplicate keys, includes help, margin set
  190.  
  191. SQUEEZE    EQU    YES        ; Optional, to handle squeezed files
  192. LIBRARY    EQU    YES        ; Optional, to handle .LBR files
  193. ;
  194. NOWAIT    EQU    YES        ; True = no wait after screen clear
  195. SILENT    EQU    YES        ; True = no superfluous "unsqueezing text" msg
  196. ;
  197.      IF    NOT OSBORNE
  198. SCROLN    EQU    23        ; Number of lines per scroll
  199. MAXCHR    EQU    80        ; Number of characters per line
  200.      ENDIF            ; NOT OSBORNE
  201. ;
  202.      IF    OSBORNE
  203. SCROLN    EQU    24        ; Number of lines per scroll
  204. MAXCHR    EQU    51        ; Number of characters per line
  205.      ENDIF            ; OSBORNE
  206. ;
  207. ; Change the help tables if you change keys
  208. ;
  209. ; Command keys - short version
  210. ;
  211. LINE    EQU    'X'-40H
  212. LINE2    EQU    SPACE
  213. PAGE    EQU    'C'-40H
  214. PAGE2    EQU    CR
  215. LINEUP    EQU    'E'-40H
  216. LINEUP2    EQU    'E'-40H
  217. PAGEUP    EQU    'R'-40H
  218. PAGEUP2    EQU    'R'-40H
  219. ARWLFT    EQU    'S'-40H
  220. ARWLFT2    EQU    'S'-40H
  221. ARWRT    EQU    'D'-40H
  222. ARWRT2    EQU    'D'-40H
  223. TOP    EQU    'T'
  224. TOP2    EQU    '7'
  225. QUIT    EQU    'Q'
  226. QUITCL    EQU    ESC
  227. ;
  228. ; Additional command keys - long version
  229. ;
  230.      IF    LONG
  231. LINE3    EQU    LF
  232. LINE4    EQU    '+'
  233. LINE5    EQU    '2'
  234. LINE6    EQU    '2'
  235. PAGE3    EQU    '3'
  236. PAGE4    EQU    '3'
  237. PAGE5    EQU    '3'
  238. LINEUP3    EQU    '8'
  239. LINEUP4    EQU    '-'
  240. LINEUP5    EQU    '8'
  241. PAGEUP3    EQU    '9'
  242. ARWLFT3    EQU    '4'
  243. ARWRT3    EQU    '6'
  244. SETKEY    EQU    'S'
  245. HUH    EQU    'H'
  246. HUH2    EQU    '/'
  247.      ENDIF            ; LONG
  248. ;
  249. ;-----------------------------------------------------------------------
  250. ;
  251. ; Check help and CLRSCR routines
  252. ;
  253. ;-----------------------------------------------------------------------
  254. ;
  255. BASE    EQU    0        ; Standard zero base CP/M
  256. ;
  257. ; BDOS functions
  258. ;
  259. CONOUT    EQU    2        ; Console write
  260. OPEN    EQU    15        ; Open file
  261. CLOSE    EQU    16        ; Close file
  262. READR    EQU    33        ; Read file random access
  263. STDMA    EQU    26        ; Set dma address
  264. ;
  265. ; Page zero equates
  266. ;
  267. WBOOT    EQU    BASE        ; Warm boot entry point
  268. BDOS    EQU    WBOOT+5        ; BDOS entry point
  269. FCB    EQU    WBOOT+5CH    ; Default fcb drive number
  270. CMDTAIL    EQU    WBOOT+80H    ; Location of command tail
  271. FCBFN    EQU    FCB+1        ; Start of filename
  272. FCBFT    EQU    FCB+9        ; Start of filetype
  273. FCBEX    EQU    FCB+12        ; Current extent number
  274. FCBCRR    EQU    FCB+33        ; Current record number, random access
  275. TPA    EQU    WBOOT+100H    ; Transient program area
  276. ;
  277. ; Operational equates
  278. ;
  279. MAXREC    EQU    32        ; Number of records in buffer
  280. SQSIGN    EQU    0FF76H        ; Signature for SQ files
  281. LBSIGN    EQU    2000H        ; Signature for library files
  282. DLE    EQU    090H        ; Char flag for run compression (SQ)
  283. ;
  284.     ORG    TPA
  285. ;
  286.     JMP    START        ; Skip over next subroutines
  287. ;
  288. ;-----------------------------------------------------------------------
  289. ;
  290. ; Change help tables to reflect key changes
  291. ;
  292.      IF    LONG AND NOT OSBORNE
  293. HELP3:
  294.     CALL    CDISP
  295.     DB    CR,LF,LF
  296.     DB    '  ^E        ^X        ^R        ^C       T    ^S    ^D '
  297.     DB    '   S    H     Q',CR,LF
  298.     DB    'up line  down line  up page  down page  top  left  right'
  299.     DB    '  set  help  quit',CR,LF
  300.     DB    '   8         2         9         3       7     4     6 '
  301.     DB    '   S    /     ESC',CR,LF
  302.     DB    ENDMSG
  303.     JMP    GETCMD
  304.      ENDIF            ; LONG AND NOT OSBORNE
  305. ;
  306.      IF    LONG AND OSBORNE
  307. HELP3:    JMP    HELP2
  308.      ENDIF            ; LONG AND OSBORNE
  309. ;
  310.      IF    LONG AND NOT OSBORNE
  311. HELP2:
  312.     CALL    CDISP
  313.     DB    CR,LF,LF
  314.     DB    '  ^E  - line up     ^R  9 page up     ^S  4 left '
  315.     DB    '    S set        Q quit',CR,LF
  316.     DB    '  ^X  <SP> line     ^C  <CR> page     ^D  6 right'
  317.     DB    '    T  7 top     ESC clear',CR,LF
  318.     DB    ENDMSG
  319.     JMP    GETCMD
  320.      ENDIF            ; LONG AND NOT OSBORNE
  321. ;
  322.      IF    LONG AND OSBORNE
  323. HELP2:
  324.     CALL    CDISP
  325.     DB    CR,LF,LF
  326.     DB    '^E line up  ^R page up  ^S left    T top   Q  quit',CR,LF
  327.     DB    '^X line     ^C page     ^D right   S set  ESC clear',CR,LF
  328.     DB    ENDMSG
  329.     JMP    GETCMD
  330.      ENDIF            ; LONG AND OSBORNE
  331. ;
  332. ; Check your clear code
  333. ;
  334. CLRSCR:
  335.     CALL    CDISP        ; Command to erase screen and home cursor
  336. ;
  337.      IF    NOT (HEATH OR OSBORNE)
  338.     DB    1AH,ENDMSG    ; Put your screen clear string here
  339.      ENDIF            ; NOT (HEATH OR OSBORNE)
  340. ;
  341.      IF    HEATH
  342.     DB    ESC,'E',ENDMSG    ; For H/Z-19 terminal -- Change as required
  343.      ENDIF            ; HEATH
  344. ;
  345.      IF    OSBORNE
  346.     DB    1AH,ENDMSG    ; For Osborne (& Televideo?)
  347.      ENDIF            ; OSBORNE
  348. ;
  349. ;            end of user settings
  350. ;-----------------------------------------------------------------------
  351. ;
  352.      IF    NOT NOWAIT
  353. WAIT:    MVI    B,0        ; Waste time (may or may not be necessary)
  354. WAIT1:    XTHL            ; Good time gobbeler!
  355.     XTHL
  356.     DCR    B
  357.     JNZ    WAIT1
  358.      ENDIF            ; NOT NOWAIT
  359. ;
  360.     RET            ; Return from clrscr
  361. ;-----------------------------------------------------------------------
  362. ;
  363. ;            START OF PROGRAM
  364. ;
  365. ;-----------------------------------------------------------------------
  366. ;
  367. START:
  368.      IF    HEATH
  369.     CALL    CDISP
  370.     DB    ESC,'x5',ENDMSG    ; Disable cursor
  371.      ENDIF            ; HEATH
  372. ;
  373.      IF    KAYPRO
  374.     CALL    CDISP
  375.     DB    ESC,'C4',ENDMSG    ; Disable cursor
  376.      ENDIF            ; KAYPRO
  377. ;
  378.     LXI    H,0        ; Get CCP's stack
  379.     DAD    SP
  380.     SHLD    STACK        ; Save old stack for reinstatement at exit
  381.     LXI    SP,STACK    ; Set new stack
  382.     LXI    H,CMDTAIL    ; Point to command tail
  383.     MOV    B,M        ; Get number of char in tail
  384.     INX    H        ; Point to first character
  385.     INR    B
  386. ;
  387.     CALL    EATSP        ; Step to next non-bl in input
  388.     JZ    OPENF        ; No more characters
  389. ;
  390.     CALL    FILNAM        ; Skip file name, returns <B>=0 or <A>=20H
  391.     JZ    OPENF        ; Only file name in tail
  392. ;
  393. ; Check if there is a member name
  394. ;
  395.     CALL    EATSP        ; Step to next non-bl in input
  396.     JZ    OPENF        ; No more characters
  397.     CPI    '9'+1        ; Numeric?
  398. ;
  399.      IF    LIBRARY
  400.     JNC    MEMB        ; No -
  401.      ENDIF            ; LIBRARY
  402. ;
  403.     CPI    '0'
  404.     JNC    NUMBER        ; Yes - must be width & height
  405. ;
  406.      IF    LIBRARY        ; Have member name (at FCB+11H)
  407. MEMB:    STA    MEMNAM        ; No - have member name
  408.     PUSH    H        ; Posn in command line
  409.     PUSH    B        ; # of chars remaining
  410.     LXI    H,FCB+11H    ; Source
  411.     LXI    D,MEMFCB+1    ; Destination
  412.     MVI    B,11        ; Move name + type
  413.     CALL    MOVE
  414.     LXI    H,FCB+9        ; Is there a suffix
  415.     MOV    A,M
  416.     CPI    SPACE
  417.     JNZ    NUMBR2        ; Yes - leave
  418.     MVI    M,'L'
  419.     INX    H
  420.     MVI    M,'B'
  421.     INX    H
  422.     MVI    M,'R'
  423. ;
  424. NUMBR2:    POP    B
  425.     POP    H
  426.     CALL    FILNAM        ; Skip member name, returns <B>=0 or <A>=20H
  427.     JZ    OPENF        ; End
  428.      ENDIF            ; LIBRARY
  429. ;
  430. ; Handle screen width and height
  431. ;
  432. NUMBER:    LXI    D,CHRMAX    ; Point to chr/line
  433.     CALL    GETNBR        ; Get number of characters/line
  434.     JC    HELP        ; Invalid number
  435.     LXI    D,LINMAX    ; Point to number of lines
  436.     CNZ    GETNBR        ; Call only if characters still in
  437.                 ; __command tail
  438.     JC    HELP        ; Invalid number
  439. ;
  440. OPENF:    CALL    OPNFIL        ; Open file in default FCB
  441. ;
  442.      IF    SQUEEZE
  443.     CALL    CHKSQ        ; Check for squeezed, init if
  444.      ENDIF            ; SQUEEZE
  445. ;
  446.      IF    LIBRARY
  447.     CALL    FILBF0        ; Fill the disk buffer with start of file
  448.     CALL    CHKLB        ; Check for library file
  449.     CALL    CLRSCR
  450.     JMP    WRTFW0        ; Buffer contains top records
  451.      ENDIF            ; LIBRARY
  452. ;
  453. WRTFWD:    CALL    CLRSCR        ; Erase the screen
  454.     CALL    FILBF0        ; Fill the disk buffer with start of file
  455. ;
  456. WRTFW0:    LXI    H,DSKBUF    ; Point to beginning of buffer
  457. ;
  458. WRTFW1:    MOV    A,M        ; Get a character
  459.     CPI    EOF        ; See if eof
  460.     JZ    GETCMD        ; Yes, wait for command
  461.     INX    H        ; Bump pointer
  462.     ANI    7FH        ; Strip high bit
  463.     CPI    FEED        ; Filter form-feeds
  464.     JZ    FILTER        ; __commonly found in .PRN files
  465.     CALL    CO1        ; Put it on console
  466.     CPI    CR        ; See if end of line
  467.     JZ    FWDCNT        ; Yes, adjust line count
  468. ;
  469. WRTFW2:    LXI    D,ENDBUF    ; Get end of buffer address
  470.     CALL    CMPHLDE        ; Is HL> gt DE> (end of buff)
  471.     JC    WRTFW1        ; Continue with next character
  472.     CALL    FILBUF        ; Fill the disk buffer with next records
  473.     JMP    WRTFW0        ; Start over
  474. ;
  475. HELP:    CALL    CLRSCR
  476.     CALL    CDISP
  477.     DB    CR,LF
  478.     DB    'BISHOW  v',(VERS MOD 10)+'0'
  479.     DB    REVS/10+'0',(REVS MOD 10)+'0'
  480.     DB    ', 25 Sep 1987'
  481.     DB    CR,LF,LF
  482. ;
  483.      IF    LIBRARY    AND SQUEEZE
  484.     DB    '  BISHOW is a buffered, bi-directional'
  485.     DB    ' file pager that will display',CR,LF
  486.     DB    '  various forms of text files.  Syntax is:',CR,LF,CR,LF
  487.     DB    '    bishow filename.typ [cols] [lines]',CR,LF,CR,LF
  488.     DB    '  Normal or squeezed ASCII or WordStar '
  489.     DB    'files may be viewed.',CR,LF,CR,LF
  490.     DB    '  A directory of a library file, or a '
  491.     DB    'member of a library file may',CR,LF
  492.     DB    '  be seen.  Syntax is:',CR,LF,CR,LF
  493.     DB    '    bishow librname.lbr',CR,LF
  494.     DB    '    bishow librname membrnam.typ',CR,LF,CR,LF
  495.     DB    '  Note that the .LBR extension MUST be appended to '
  496.     DB    'the library name.',CR,LF
  497.     DB    '  in order to display the librarys directory. ',CR,LF,CR,LF
  498.     DB    '  (Type a  "/"  while viewing a file '
  499.     DB    'to see command summary.)',CR,LF
  500.     DB    ENDMSG
  501.      ENDIF            ; LIBRARY AND SQUEEZE
  502. ;
  503.      IF    LIBRARY    AND NOT    SQUEEZE
  504.     DB    'bishow a:FILnotSQ.lbr '
  505.      ENDIF            ; LIBRARY AND NOT SQUEEZE
  506. ;
  507.      IF    SQUEEZE    AND NOT    LIBRARY
  508.     DB    'bishow a:SQZorNOT.fil '
  509.      ENDIF            ; SQUEEZE AND NOT LIBRARY
  510. ;
  511.      IF    (NOT SQUEEZE) AND (NOT LIBRARY)
  512.     DB    'bishow d:anyPLAIN.fil '
  513.      ENDIF            ; (NOT SQUEEZE) AND (NOT LIBRARY)
  514. ;
  515.      IF    LIBRARY
  516.     DB    '[member] '
  517.      ENDIF            ; LIBRARY
  518. ;
  519.     DB    '[cols [lines]]',CR,LF,ENDMSG
  520.     JMP    EXIT1
  521. ;
  522. FILTER:    PUSH    PSW        ; Save status
  523.     MVI    A,'^'        ; Print '^' in front
  524.     CALL    CO1        ; __of control character
  525.     POP    PSW        ; Restore status
  526.     ADI    40H        ; Mask into displayable char
  527.     CALL    CO1        ; Display filtered control char
  528. ;
  529. FWDCNT:    LDA    LINCNT        ; Get number of lines displayed
  530.     INR    A        ; Bump it
  531.     STA    LINCNT        ; __and store it
  532.     MOV    D,A        ; Save lincnt
  533.     LDA    LINMAX        ; Get max number of line
  534.     CMP    D        ; Compare with line count
  535.     JNZ    WRTFW2        ; If not there, continue, else get command
  536.     XRA    A        ; Zero the
  537.     STA    LINCNT        ; __line count
  538. ;
  539. GETCMD:    PUSH    H
  540.     PUSH    D
  541.     PUSH    B
  542. ;
  543. GETCM1:    CALL    GETIN        ; Get input char if any
  544.     ORA    A        ; Loop till char avail
  545.     JZ    GETCM1
  546.     POP    B
  547.     POP    D
  548.     POP    H
  549.     CPI    'a'        ; Change command to
  550.     JC    GETCM2        ; __upper case
  551.     CPI    'z'+1
  552.     JNC    GETCM2
  553.     XRI    20H        ; Is lower case, make upper case
  554. ;
  555. ; Commands for short version
  556. ;
  557. GETCM2:    CPI    LINE        ; Scroll next line
  558.     JZ    WRTNXT
  559.     CPI    LINE2
  560.     JZ    WRTNXT
  561.     CPI    PAGE        ; Scroll next page
  562.     JZ    WRTFW1
  563.     CPI    PAGE2
  564.     JZ    WRTFW1
  565.     CPI    LINEUP        ; Scroll prev line
  566.     JZ    WRTPRV
  567.     CPI    LINEUP2
  568.     JZ    WRTPRV
  569.     CPI    PAGEUP        ; Scroll page backward
  570.     JZ    WRTBAK
  571.     CPI    PAGEUP2
  572.     JZ    WRTBAK
  573.     CPI    ARWLFT        ; Scroll left
  574.     JZ    ADJMM
  575.     CPI    ARWLFT2
  576.     JZ    ADJMM
  577.     CPI    ARWRT        ; Scroll right
  578.     JZ    ADJMM
  579.     CPI    ARWRT2
  580.     JZ    ADJMM
  581.     CPI    TOP        ; Go to 1st line of file
  582.     JZ    WRTTOP
  583.     CPI    TOP2
  584.     JZ    WRTTOP
  585.     CPI    QUIT        ; Does not clear screen
  586.     JZ    EXIT
  587.     CPI    QUITCL        ; Clears screen
  588.     JZ    EXITCL
  589. ;
  590. ; Commands for long version
  591. ;
  592.      IF    LONG
  593.     CPI    LINE3
  594.     JZ    WRTNXT
  595.     CPI    LINE4
  596.     JZ    WRTNXT
  597.     CPI    LINE5
  598.     JZ    WRTNXT
  599.     CPI    LINE6
  600.     JZ    WRTNXT
  601.     CPI    PAGE3
  602.     JZ    WRTFW1
  603.     CPI    PAGE4
  604.     JZ    WRTFW1
  605.     CPI    PAGE5
  606.     JZ    WRTFW1
  607.     CPI    LINEUP3
  608.     JZ    WRTPRV
  609.     CPI    LINEUP4
  610.     JZ    WRTPRV
  611.     CPI    LINEUP5
  612.     JZ    WRTPRV
  613.     CPI    PAGEUP3
  614.     JZ    WRTBAK
  615.     CPI    ARWLFT3
  616.     JZ    ADJMM
  617.     CPI    ARWRT3
  618.     JZ    ADJMM
  619.     CPI    SETKEY
  620.     JZ    SETSCR
  621.     CPI    HUH
  622.     JZ    HELP2        ; Brief table of commands
  623.     CPI    HUH2
  624.     JZ    HELP3        ; Full table of commands
  625.      ENDIF            ; LONG
  626. ;
  627.     JMP    GETCMD
  628. ;
  629. ; Go to top of file
  630. ;
  631. WRTTOP:    LDA    TOPBUF        ; Get top in buffer flag
  632.     ORA    A
  633.     JNZ    WRTFWD        ; No - the hard way
  634.     CALL    CLRSCR        ; Erase the screen
  635. ;
  636. WRTTO1:    XRA    A
  637.     STA    LINCNT        ; Clear lines put so far
  638.     JMP    WRTFW0        ; Buffer contains top records
  639. ;
  640. ; Write one more line
  641. ;
  642. WRTNXT:    LDA    LINMAX
  643.     DCR    A        ; Fool wrtfw1 to only write one line
  644.     STA    LINCNT
  645.     JMP    WRTFW1
  646. ;
  647. ; Back up one line
  648. ;
  649. WRTPRV:    LDA    LINMAX        ; Back up one screen + 1 line
  650.     INR    A
  651.     JMP    WRTBK0
  652. ;
  653. ; Back up full screen
  654. ;
  655. WRTBAK:    LDA    LINMAX        ; Get screen line count
  656.     ADD    A        ; __multiply by 2
  657. ;
  658. WRTBK0:    INR    A        ; __and add 1
  659.     STA    LINCNT        ; __to backup to previous page
  660.     CALL    CLRSCR        ; Clear the screen
  661. ;
  662. WRTBK1:    LXI    D,DSKBUF    ; Get address of start of buffer start
  663.     CALL    CMPHLDE        ; Is HL> LT DE> (start of buff)
  664.     JC    FILBAK        ; Go refill buffer
  665. ;
  666. WRTBK2:    MOV    A,M        ; Get a character
  667.     ANI    7FH        ; Strip high bit
  668.     DCX    H        ; Decrement buffer
  669.     CPI    CR        ; See if end of line
  670.     JZ    BAKCNT        ; __or form-feed
  671.     CPI    FEED        ; __and adjust line count if so
  672.     JNZ    WRTBK1        ; Else, loop if not
  673. ;
  674. BAKCNT:    LDA    LINCNT        ; Else, get number of lines to move back
  675.     DCR    A        ; __and decrement it
  676.     STA    LINCNT        ; __store it
  677.     JNZ    WRTBK1        ; __and loop if not there
  678.     INX    H        ; Else bump pointer
  679.     INX    H        ; __to account for dcx
  680.     JMP    WRTFW1        ; And go write a screen
  681. ;
  682. ; Test for top of file
  683. ;
  684. FILBAK:    LDA    TOPBUF        ; Get top in buffer flag
  685.     ORA    A
  686.     JZ    WRTTO1        ; Yes - start of file in buffer
  687. ;
  688. ; Start of file not in buffer, step back
  689. ;
  690.     LHLD    RECCNT        ; Get no of records last read
  691.     LXI    D,MAXREC    ; Get the buffer size
  692.     DAD    D        ; Add them
  693.     XCHG            ; __and put them in DE
  694.     LDA    FCBCRR        ; Subtract low order byte
  695.     SUB    E        ; __from current record count
  696.     STA    FCBCRR        ; __and store in current record count
  697.     LDA    FCBCRR+1    ; Same with high order byte
  698.     SBB    D        ; __but with borrow
  699.     JM    WRTFWD        ; If beyond beginning of file, start over
  700.     STA    FCBCRR+1    ; Else, store high order byte
  701.     CALL    FILBUF        ; Fill the buffer
  702.     LXI    H,ENDBUF    ; __and point to end of buffer
  703.     CALL    CLRSCR        ; Clear the screen
  704.     JMP    WRTBK2        ; Continue moving back in file
  705. ;
  706. ; Fill buffer with top of file
  707. ;
  708. FILBF0:    XRA    A        ; Get a 0
  709.     STA    LINCNT        ; Store in line count
  710.     STA    CHRCNT        ; Store in character count
  711.                 ; Do not reset the current extent!!!
  712.                 ; BDOS will switch extents only if the
  713.                 ;   no-specified ( <FCBEX> ) does NOT
  714.                 ;   agree with the wanted no <FCBCRR>
  715.                 ;   .CBCRR Reset to record zero
  716.     STA    FCBCRR
  717. ;
  718.      IF    NOT LIBRARY
  719.     STA    FCBCRR+1    ;
  720.     STA    FCBCRR+2    ; __and clear the overflow
  721.      ENDIF            ; NOT LIBRARY
  722. ;
  723.      IF    LIBRARY
  724.     LHLD    SCZERO        ; Set to record zero for file/member
  725.     SHLD    FCBCRR
  726.      ENDIF            ; LIBRARY
  727. ;
  728. ; Fill buffer from spec'd record
  729. ;
  730. FILBUF:    MVI    B,MAXREC    ; Number of records to read
  731. ;
  732. FILB1S:
  733.      IF    LIBRARY
  734.     LHLD    SCZERO        ; Get top record for member
  735.     XCHG
  736.     LHLD    FCBCRR        ; Is this top of file?
  737.     CALL    CMPHLDE        ; This it? (<A>=0 if equal)
  738.      ENDIF            ; LIBRARY
  739. ;
  740.      IF    NOT LIBRARY
  741.     LHLD    FCBCRR        ; Is this top of file?
  742.     MOV    A,H
  743.     ORA    L
  744.      ENDIF            ; NOT LIBRARY
  745. ;
  746.     STA    TOPBUF        ; Set top of file in buffer flag
  747.     LXI    D,DSKBUF    ; Load start of disk buffer
  748.     LXI    H,0        ; Zero out the
  749.     SHLD    RECCNT        ; __number of records in buffer
  750. ;                ; Z - top, NZ - not top
  751.      IF    SQUEEZE
  752.     LDA    SQFLG        ; Is this a squeezed file
  753.     ORA    A
  754.     JNZ    FILSQ        ; Yes -
  755.      ENDIF            ; SQUEEZE
  756. ;
  757. FILBU1:    PUSH    H        ; Save all
  758.     PUSH    D        ; __registers from
  759.     PUSH    B        ; __BDOS clobber
  760.     MVI    C,STDMA        ; Set dma to
  761.     CALL    BDOS        ; __disk buffer
  762.     LXI    D,FCB        ; Set up to read
  763.     MVI    C,READR        ; __a record
  764.     CALL    BDOS        ; Do it
  765.     ORA    A        ; Read OK?
  766.     LHLD    FCBCRR        ; Get current record number
  767.     INX    H        ; __bump it
  768.     SHLD    FCBCRR        ; __and save it
  769.     LHLD    RECCNT        ; Get records in buffer
  770.     INX    H        ; Bump it
  771.     SHLD    RECCNT        ; Store it
  772.     POP    B
  773.     POP    D
  774.     POP    H
  775.     JNZ    RDERR        ; No, last record read
  776. ;
  777.      IF    LIBRARY
  778.     PUSH    D        ; Save record buffer pointer
  779.     LHLD    FCBCRR        ; Get current record number
  780.     XCHG
  781.     LHLD    SCLAST        ; & get last record for member (or FFFF)
  782.     CALL    CMPHLDE        ; Are we within member
  783.     POP    D
  784.     JC    RDERR        ; No, last record read
  785.      ENDIF            ; LIBRARY
  786. ;
  787.     DCR    B        ; Decrement it
  788.     RZ            ; If done return
  789.     LXI    H,128        ; Else, add 128 to
  790.     DAD    D        ; __DMA address
  791.     XCHG            ; Put it in DE
  792.     JMP    FILBU1        ; Read another record
  793. ;
  794. ; Fill buffer from squeezed file.  This RTN handles mapping from UNSQ
  795. ; record # to record, byte and bit in squeeze stream.  On input (no
  796. ; allowance made for records # over 65535) <B> contains number of records
  797. ; wanted DE> buffer where records wanted,  Ignored in this version,
  798. ; always full DSKBUF
  799. ;
  800.      IF    SQUEEZE
  801. FILSQ:    LHLD    FCBCRR        ; Get # for 1st record wanted
  802.     XCHG
  803.     PUSH    D        ; Save to restore after unsq
  804.     LHLD    NXTREC        ; & 1st record after buffered ones
  805.     CALL    CMPHLDE        ; Consecutive?
  806.     JZ    USQNXT        ; Yes - fine
  807.     JNC    USQBAK        ; No - lower
  808. ;
  809. ; Next record after latest but not consec
  810. ;
  811.     CALL    CDISP
  812.     DB    CR,LF,'Disjoint records',CR,LF,0
  813.     JMP    EXIT        ; Should never happen
  814. ;
  815. USQBAK:    DS    0        ; Going backward
  816.      ENDIF            ; SQUEEZE
  817. ;
  818.      IF    SQUEEZE    AND LIBRARY
  819.     LHLD    SCZERO        ; Get 1st record for member
  820.     CALL    CMPHLDE        ; All the way back to start?
  821.      ENDIF            ; SQUEEZE AND LIBRARYX
  822. ;
  823.      IF    SQUEEZE    AND NOT    LIBRARY
  824.     MOV    A,D        ; All the way?
  825.     ORA    E
  826.      ENDIF            ; SQUEEZE AND NOT LIBRARY
  827. ;
  828.      IF    SQUEEZE
  829.     JNZ    USQNO1        ; No - MUST be prev!!!
  830.     LXI    H,SQMAP+2+8    ; Yes - reset SQMAP index to #3
  831.     SHLD    SQMAP
  832. ;
  833. USQNO1:    LHLD    SQMAP        ; Get index into mapping table
  834.     LXI    D,-8        ; Step back from next, past current to prev
  835.     DAD    D
  836.     SHLD    SQMAP        ; & save updated index for next
  837.     MOV    E,M        ; Get SQ record no
  838.     INX    H
  839.     MOV    D,M
  840.     INX    H
  841.     MOV    C,M        ; Get byte offset
  842.     INX    H
  843.     MOV    A,M        ; & bit offset
  844.     STA    BITLFT
  845.     XRA    A
  846.     STA    RCNT        ; No runs in progress
  847.     STA    SQBYT+1        ; Set offset 1st data byte
  848.     MOV    A,C
  849.     STA    SQBYT        ; For now offset within record only
  850.     LHLD    SQBSC1        ; Get no of first SQ record now in buffer
  851.     XCHG            ; <HL> wanted 1st record, <DE> actual 1st
  852.     CALL    CMPHLDE        ; Is 1st buffer record low/equal 1st data sect?
  853.     JNC    USQ1OK        ; Yes - first wanted record SQ in buffer
  854. ;
  855. ; Max header 1035 bytes + file name)
  856. ;
  857. ; Force reload of SQ buffer
  858. ;
  859.     SHLD    NXTSQS        ; No - 1st data record b/4 1st buffer sect
  860. ;                 (note is probab not record 0
  861. ;                 because of header, eg decoding tree)
  862.     MVI    A,1        ; Set rewind with I/O
  863.     STA    SQREWD        ; Set rewind flag
  864.     XRA    A
  865.     STA    SQEOF        ; Reset end of file on SQ
  866.                 ; Leave current extent alone.  This is
  867.                 ;   how BDOS knows how to switch the
  868.                 ;   extents.  It checks if the current
  869.                 ;   extent no agrees with the wanted
  870.                 ;   record.
  871.     STA    FCBCRR+2    ; & count overflow, should not be needed
  872.     MOV    D,A
  873.     JMP    USQNX1        ; Go adjust buffer pointer
  874.                 ; (NOP since <DE>=0
  875. ;
  876. ; SQ text still in buffer
  877. ;
  878. ; <DE> # of 1st record in SQ buf
  879. ; <HL> # of wanted SQ record
  880. ; (Max 100H SQ records in buffer)
  881. ;
  882. USQ1OK:    MOV    A,L
  883.     SUB    E
  884.     RAR            ; Convert to pages (100H)
  885. ;
  886. ; Know Cy=0 in
  887. ; Leaves carry set if odd number of records
  888. ;
  889.     MOV    D,A
  890.     MVI    A,0        ; Do not disturb Cy
  891.     RAR            ; Pu carry (now 80H or 00H)
  892. ;
  893. USQNX1:    MOV    E,A
  894.     LHLD    SQBYT        ; Get offset of 1st data byte in wanted sect
  895.     DAD    D        ; --> offset in buffer
  896.     LXI    D,SQBUF
  897.     DAD    D        ; Convert to absolute addr
  898.     SHLD    INBUFS        ; & set as next byte to unsqueeze
  899. ;
  900. ; Next record consecutive
  901. ;
  902. USQNXT:    LHLD    NXTSQS        ; Get no of next SQ record
  903.     SHLD    FCBCRR
  904. ;
  905. ; Build mapping table entry
  906. ;
  907.     LHLD    INBUFS        ; Calculate offer in buffer
  908.     LXI    D,-SQBUF
  909.     DAD    D
  910.     MOV    C,L        ; Keep offset within record
  911.     LDA    BITLFT        ; Get bit offset
  912.     MOV    B,A
  913.     ORA    A        ; On byte boundary?
  914.     MOV    A,C
  915.     JNZ    NOTBBY        ; No -
  916.     INR    A        ; Yes - no adj reqd
  917. ;
  918. NOTBBY:    ANI    7FH        ; Ensure sector relative
  919.     DAD    H        ; Convert to record no
  920.     ORA    A        ; Is next byte at start of record?
  921.     JNZ    RECTOK
  922.     DCR    H        ; Yes - step back one record
  923. ;
  924. RECTOK:    DCR    A
  925.     ANI    7FH        ; And adjust byte index
  926.     MOV    E,H
  927.     MVI    D,0
  928.     LHLD    SQBSC1        ; # of 1st record in buffer
  929.     DAD    D
  930.     XCHG            ; <D> absolute SQ record no
  931.     LHLD    SQMAP        ; Get index
  932.     MOV    M,E        ; Save abs SQ record no
  933.     INX    H
  934.     MOV    M,D
  935.     INX    H
  936.     MOV    M,A        ; Save sector relative byte offset
  937.     INX    H
  938.     MOV    M,B        ; Save BITLFT
  939.     INX    H
  940.     SHLD    SQMAP        ; Save new index
  941.      ENDIF            ; SQUEEZE
  942. ;
  943.      IF    SQUEEZE    AND NOT    SILENT
  944.     CALL    CDISP        ; Show msg where is
  945.     DB    '>>> Unsqueezing Text <<<',ENDMSG
  946.                 ; Corrupts display if after CR but before LF
  947.      ENDIF            ; SQUEEZE AND NOT SILENT
  948. ;
  949.      IF    SQUEEZE
  950.     CALL    FILUSQ        ; Fills unsq buffer
  951.      ENDIF            ; SQUEEZE
  952. ;
  953.      IF    SQUEEZE    AND NOT    SILENT
  954.     CALL    CDISP        ; Remove msg just displayed, assumes
  955.                 ; BS works across start of line if reqd
  956.     DB    BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS
  957.     DB    BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS
  958.     DB    '                        '
  959.     DB    BS,BS,BS,BS,BS,BS,BS,BS    ,BS,BS,BS,BS
  960.     DB    BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,0
  961.      ENDIF            ; SQUEEZE AND NOT SILENT
  962. ;
  963.      IF    SQUEEZE
  964.     LHLD    FCBCRR        ; Get no of next SQ record
  965.     SHLD    NXTSQS
  966.     LHLD    NXTADR        ; Calc # of unsq records in buf
  967.     LXI    D,-DSKBUF    ; (as neg no)
  968.     DAD    D        ; Calc length
  969.     DAD    H        ; & convert to records in <H>
  970.     MOV    L,H
  971.     MVI    H,0
  972.     SHLD    RECCNT        ; Save # of records in DSKBUF
  973.     POP    D        ; Get FCBCRR as passed by calling rtn
  974.     DAD    D        ; & calc new one
  975.     SHLD    FCBCRR
  976.     SHLD    NXTREC
  977.     RET
  978.      ENDIF            ; SQUEEZE
  979. ;
  980. ; We only get here if end of file
  981. ;
  982. RDERR:    MVI    A,EOF        ; Get bogus eof
  983.     STAX    D        ; Save at buffer end in case no eof in file
  984.     XRA    A        ; Get a zero to direct to start of buffer
  985.     RET            ; __on ret
  986. ;
  987. OPNFIL:    LDA    FCBFN        ; Point to first letter of filename
  988.     CPI    ' '        ; Anything there?
  989.     JZ    HELP        ; No, give help message
  990.     XRA    A        ; Get a 0
  991.     STA    FCBEX        ; Zero current extent
  992.     LXI    D,FCB        ; File name in default fcb
  993.     MVI    C,OPEN        ; Set up to open
  994.     CALL    BDOS        ; Do it
  995.     INR    A        ; Open OK?
  996.     RNZ            ; Yes
  997.     CALL    CDISP        ; Else, give error msg and quit
  998.     DB    'No File',ENDMSG
  999.     JMP    EXIT1        ; Leave msg on screen on exit
  1000. ;
  1001. GETNBR:    MOV    A,M        ; Get first digit
  1002.     INX    H
  1003.     DCR    B        ; B=number of characters left in buffer
  1004.     RZ            ; No digit
  1005.     CPI    SPACE
  1006.     JZ    GETNBR        ; Wait until next non-space
  1007.     PUSH    D        ; Save location to save number
  1008.     MVI    D,0        ; Initialize number
  1009. ;
  1010. GNUM1:    SUI    30H        ; Change ASCII to number
  1011.     JC    INVNUM        ; Not a number
  1012.     CPI    10
  1013.     CMC
  1014.     JC    INVNUM        ; Not a number
  1015.     PUSH    PSW        ; Save number
  1016.     MOV    A,D        ; Multiply old number by 10
  1017.     ADD    A        ; *2
  1018.     ADD    A        ; *4
  1019.     ADD    A        ; *8
  1020.     ADD    D        ; *9
  1021.     ADD    D        ; *10
  1022.     MOV    D,A
  1023.     POP    PSW        ; Restore new digit
  1024.     ADD    D
  1025.     MOV    D,A
  1026.     MOV    A,M        ; Get next digit
  1027.     INX    H
  1028.     DCR    B
  1029.     JZ    ENDNUM        ; End of number
  1030.     CPI    SPACE
  1031.     JNZ    GNUM1
  1032. ;
  1033. ENDNUM:    MOV    A,D        ; Save number
  1034.     DCR    A        ; Correct number for co routines
  1035.     XCHG            ; Set to restore save location
  1036.     POP    H        ; Restore save location
  1037.     MOV    M,A        ; Save digit
  1038.     XCHG            ; Put buffer location where it belongs
  1039.     MOV    A,B        ; See if any characters left in buffer
  1040.     ORA    A        ; Zero if no characters in buffer
  1041.     RET
  1042. ;
  1043. INVNUM:    POP    D        ; Correct stack
  1044.     RET
  1045. ;
  1046.      IF    LONG
  1047. ASCIIN:    MVI    B,100        ; Divide by 100, then change
  1048.     CALL    DIVIDE        ; __digit to ASCII and store at hl
  1049.     MVI    B,10        ; Divide by 10, then change
  1050.     CALL    DIVIDE        ; __digit to ASCII and store at hl+1
  1051.     MVI    B,30H        ; Change ones place number
  1052.     ADD    B        ; __to ASCII and store at hl+2
  1053.     MOV    M,A
  1054.     DCX    H        ; Delete leading zeroes
  1055.     DCX    H        ; __in the number
  1056.     MVI    C,SPACE        ; __and replace with spaces
  1057.     MOV    A,B
  1058.     CMP    M        ; Check first digit for '0'
  1059.     JNZ    CDISP        ; Not zero
  1060.     MOV    M,C        ; Replace with space
  1061.     INX    H
  1062.     CMP    M        ; Check second digit for '0'
  1063.     JNZ    CDISP        ; Not zero
  1064.     MOV    M,C        ; Replace with space
  1065.      ENDIF            ; LONG
  1066. ;
  1067. CDISP:    XTHL            ; Exchange top of stack and HL
  1068. ;
  1069. CDIS1:    MOV    A,M        ; HL now pointing to db message
  1070.     ORA    A        ; See if 0 at end of message
  1071.     INX    H
  1072.     JZ    CDIS2        ; Yes, restore stack and return
  1073.     CALL    CO        ; No, print the character
  1074.     JMP    CDIS1        ; __and loop
  1075. ;
  1076. CDIS2:    XTHL            ; Get return address on top of stack
  1077.     RET            ; __and return
  1078. ;
  1079. CO:    PUSH    B        ; Save the registers
  1080.     PUSH    D        ; __from BDOS
  1081.     PUSH    H        ; __clobber
  1082. ;
  1083. CO2:    PUSH    PSW
  1084.     MOV    E,A        ; Set up character
  1085.     MVI    C,CONOUT    ; __to send to console
  1086.     CALL    BDOS        ; Do it
  1087.     POP    PSW
  1088. ;
  1089. CO5:    POP    H        ; Restore
  1090.     POP    D        ; __the registers
  1091.     POP    B
  1092.     RET
  1093. ;
  1094. CO1:    PUSH    B        ; Save the registers
  1095.     PUSH    D
  1096.     PUSH    H
  1097.     MOV    E,A
  1098.     LXI    H,CHRCNT    ; Get address of character count
  1099.     CPI    CR        ; See if end of line
  1100.     JZ    ENDLIN        ; Update line information
  1101.     CPI    LF        ; Ignore linefeed
  1102.     JZ    CO2
  1103.     LDA    CHRMAX        ; Get maximum characters per line
  1104.     CMP    M        ; See if too many char
  1105.     JC    CO5        ; Don't print character
  1106.     MOV    A,E        ; Restore and print character
  1107.     CPI    TAB        ; Fix chrcnt for tabs
  1108.     JZ    TABFIX
  1109.     INR    M        ; Increment character count
  1110.     LDA    CHRMIN        ; See if up to minimum display yet
  1111.     CMP    M
  1112.     MOV    A,E        ; Restore character
  1113.     JNC    CO5        ; Do not display character
  1114.     JMP    CO2        ; Finally, display character
  1115. ;
  1116. ENDLIN:    MVI    M,0        ; Reset character count
  1117.     JMP    CO2        ; Print cr
  1118. ;
  1119. TABFIX:    MVI    A,08H        ; Fix chrcnt for tabs
  1120.     ADD    M        ; Increment to next 8-count
  1121.     ANI    0F8H        ; Make into multiple of 8
  1122. ;
  1123. TAB2:    SUB    M        ; Get number of space to go
  1124.     MOV    B,A
  1125. ;
  1126. TAB1:    MVI    A,SPACE        ; Expand tab
  1127.     CALL    CO1
  1128.     DCR    B
  1129.     JNZ    TAB1        ; Still more spaces
  1130.     JMP    CO5        ; Exit routine
  1131. ;
  1132.      IF    LONG
  1133. SETSCR:    PUSH    H
  1134.     PUSH    D
  1135.     PUSH    B
  1136. ;
  1137. GETMAX:    LDA    CHRMAX        ; Get maximum number of characters
  1138.     INR    A
  1139.     LXI    H,HUNS
  1140.     CALL    ASCIIN        ; Put ASCII number in message
  1141.     DB    CR,LF,'Max Column: '
  1142. ;
  1143. HUNS:    DB    30H
  1144.     DB    30H
  1145.     DB    30H
  1146.     DB    ' New? ',ENDMSG
  1147.     CALL    GETINP        ; Read input from console
  1148.     LXI    D,CHRMAX    ; Set new chrmax in memory
  1149.     CALL    GETNBR
  1150.     JC    GETMAX        ; If error, repeat last message
  1151. ;
  1152. GETMIN:    LDA    CHRMIN        ; Get minimum character display
  1153.     INR    A
  1154.     LXI    H,HUN
  1155.     CALL    ASCIIN        ; Put ASCII number in message
  1156.     DB    LF,'Min Column: '
  1157. ;
  1158. HUN:    DB    30H
  1159.     DB    30H
  1160.     DB    30H
  1161.     DB    ' New? ',ENDMSG
  1162.     CALL    GETINP        ; Read input from console
  1163.     LXI    D,CHRMIN    ; Set new chrmax in memory
  1164.     CALL    GETNBR
  1165.     JC    GETMIN        ; If error, repeat last message
  1166. ;
  1167. GETLIN:    LDA    LINMAX        ; Get number of lines per display
  1168.     LXI    H,HUND
  1169.     CALL    ASCIIN        ; Put ASCII number in message
  1170.     DB    LF,'Lines per Page: '
  1171. ;
  1172. HUND:    DB    30H
  1173.     DB    30H
  1174.     DB    30H
  1175.     DB    ' New? ',ENDMSG
  1176.     CALL    GETINP        ; Read input from console
  1177.     LXI    D,LINMAX    ; Set new chrmax in memory
  1178.     CALL    GETNBR
  1179.     JC    GETLIN        ; If error, repeat last message
  1180.     POP    B
  1181.     POP    D
  1182.     POP    H
  1183. ;
  1184. WRTSAM:    LDA    LINMAX        ; Write the same screen
  1185.     JMP    WRTBK0
  1186. ;
  1187. GETINP:    MVI    A,5        ; Get set to read new maximum column
  1188.     STA    CMDTAIL
  1189.     MVI    C,0AH
  1190.     LXI    D,CMDTAIL
  1191.     CALL    BDOS        ; Get maximum column
  1192.     LXI    H,CMDTAIL+1    ; Now, change to ASCII
  1193.     MOV    B,M
  1194.     INX    H
  1195.     INR    B
  1196.     RET            ; Return with input in buffer
  1197.      ENDIF            ; LONG
  1198. ;
  1199. ; Adjust char min/max on cursor left/rt
  1200. ;
  1201. ADJMM:    PUSH    H
  1202.     CPI    ARWLFT        ; Move left (decrease)?
  1203.     JZ    ADJM1        ; Set flag
  1204.     CPI    ARWLFT2
  1205.     JZ    ADJM1
  1206. ;
  1207.      IF    LONG
  1208.     CPI    ARWLFT3
  1209.     JZ    ADJM1
  1210.      ENDIF            ; LONG
  1211. ;
  1212. ADJM1:    LDA    CHRMAX        ; Rightmost char to display
  1213.     MOV    H,A
  1214.     LDA    CHRMIN        ; Leftmost char to display
  1215.     MVI    L,8        ; Scroll by 8
  1216.     JZ    ADJMMD        ; OK - adjust to left
  1217.     ADD    L        ; No - increase min, no limit
  1218.     PUSH    PSW
  1219.     MOV    A,L
  1220.     ADD    H        ; Increase  max
  1221.     JMP    ADJMMS        ; OK - adjust to right
  1222. ;
  1223. ADJMMD:    SUB    L        ; Adjust to left
  1224.     PUSH    PSW
  1225.     MOV    A,H
  1226.     SUB    L
  1227. ;
  1228. ; Adjust to right
  1229. ;
  1230. ADJMMS:    MOV    H,A        ; <H> max
  1231.     POP    PSW        ; <A> min
  1232.     CMP    H        ; Wrap, (max< min)
  1233.     JNC    ADJMMX        ; OK - leave unchanged
  1234.     STA    CHRMIN
  1235.     MOV    A,H
  1236.     STA    CHRMAX
  1237. ;
  1238. ADJMMX:    POP    H
  1239.     LDA    LINMAX        ; Write the same screen
  1240.     JMP    WRTBK0        ; Same effect as WRTSAM above
  1241. ;
  1242.      IF    LONG
  1243. DIVIDE:    MVI    C,'0'-1        ; Extract dividend of a div c
  1244. ;
  1245. DIV1:    INR    C        ; __and store in location pointed
  1246.     SUB    B        ; __to by hl
  1247.     JNC    DIV1
  1248.     ADD    B
  1249.     MOV    M,C        ; Save ASCII digit
  1250.     INX    H        ; Bump pointer to next location
  1251.     RET
  1252.      ENDIF            ; LONG
  1253. ;
  1254. ; Clear screen only on <ESC> exit
  1255. ;
  1256. EXITCL:    CALL    CLRSCR        ; Clear the screen
  1257. ;
  1258. EXIT:    LXI    D,FCB        ; Close file
  1259.     MVI    C,CLOSE        ; --in case this is MP/M
  1260.     CALL    BDOS
  1261. ;
  1262. EXIT1:
  1263.      IF    HEATH
  1264.     CALL    CDISP        ; Re-enable cursor
  1265.     DB    ESC,'y5',ENDMSG
  1266.      ENDIF            ; HEATH
  1267. ;
  1268.      IF    KAYPRO
  1269.     CALL    CDISP
  1270.     DB    ESC,'B4',ENDMSG    ; Enable cursor
  1271.      ENDIF            ; KAYPRO
  1272. ;
  1273.     LHLD    STACK        ; Get old stack
  1274.     SPHL
  1275.     RET            ; Return to CCP
  1276. ;
  1277. ; Check for Library file
  1278. ;
  1279.      IF    LIBRARY
  1280. CHKLB:    XRA    A
  1281.     STA    MEMFCB
  1282.     STA    LBFLG        ; Clear library flag
  1283.     LHLD    DSKBUF        ; Get 1st word in file
  1284.     LXI    D,LBSIGN    ; Get expected value
  1285.     CALL    CMPHLDE
  1286.     JZ    ISLB
  1287. ;
  1288. ; Not library
  1289. ;
  1290.     LDA    MEMNAM        ; Was member specified
  1291.     ORA    A
  1292.     RZ            ; No - ok
  1293.     CALL    CDISP
  1294.     DB    CR,LF,'Not LBR',CR,LF,0
  1295.     JMP    EXIT        ; Get out to leave msg visible
  1296. ;
  1297. ; Is library
  1298. ;
  1299. ISLB:    MVI    A,1
  1300.     STA    LBFLG        ; Yes - set library flag
  1301.     LXI    H,DSKBUF+14    ; Set to dir size (in records)
  1302.     MOV    A,M        ; Assume <255 entries
  1303.     RAL
  1304.     RAL            ; Convert # records to # entries
  1305.     DCR    A        ; Less 1 for file descriptor
  1306.     STA    DIRSIZ        ; Directory size in entries
  1307.     MOV    B,A        ; Save no of entries for loop
  1308.     LXI    H,DSKBUF+20H    ; Set 1st member entry
  1309.     CALL    CDISP        ; Write a blank line before first dir line
  1310.     DB    CR,LF,0
  1311. ;
  1312. ; Loop through directory entries
  1313. ;
  1314. DIRLP:    PUSH    B        ; Save no of entries remaining
  1315.     MOV    A,M        ; Get entry status
  1316.     ORA    A        ; Deleted?
  1317.     JNZ    NYET        ; Yes - skp to next
  1318.     LDA    MEMNAM        ; Do we have member name on command line?
  1319.     ORA    A
  1320.     JZ    DISPM        ; No - display member name routine
  1321. ;
  1322. ; See if this is the requested member
  1323. ;
  1324.     MVI    B,12        ; Length of names + 00H in front
  1325.     LXI    D,MEMFCB
  1326.     CALL    CPSTR        ; Compare names
  1327.     JZ    FOUND
  1328.     JMP    NYET
  1329. ;
  1330. ; Display rather than look for the member
  1331. ;
  1332. DISPM:    MVI    B,11        ; Length of names
  1333.     PUSH    H
  1334.     INX    H        ; Step to actual name
  1335. ;
  1336. DSPMLP:    MOV    A,M
  1337.     CALL    CO        ; Display one char
  1338.     INX    H
  1339.     DCR    B        ; Reduce count remaining
  1340.     JZ    NMEND        ; End of name
  1341.      ENDIF            ; LIBRARY
  1342. ;
  1343.      IF    LIBRARY    AND NOT    OSBORNE
  1344.     MOV    A,B
  1345.     CPI    3        ; Only 3 more?
  1346.     JNZ    DSPMLP        ; No -
  1347.     MVI    A,'.'        ; Yes - put out dot
  1348.     CALL    CO
  1349.      ENDIF            ; LIBRARY AND NOT OSBORNE
  1350. ;
  1351.      IF    LIBRARY
  1352.     JMP    DSPMLP        ; Go for next char
  1353. ;
  1354. ; Have now displayed member name
  1355. ;
  1356. NMEND:    LXI    H,NAMEXC    ; Max no of names across sofar
  1357.     MOV    A,M
  1358.     INX    H        ; Step to names across sofar
  1359.     INR    M        ; Count current
  1360.     CMP    M        ; Over max?
  1361.     JNC    NOTMAX        ; Not yet
  1362.     MVI    M,0        ; Yes - reset
  1363.     CALL    CDISP
  1364.     DB    CR,LF,0
  1365.     JMP    NYET1
  1366. ;
  1367. NOTMAX:    CALL    CDISP
  1368.      ENDIF            ; LIBRARY
  1369. ;
  1370.      IF    LIBRARY    AND NOT    OSBORNE
  1371.     DB    ' '
  1372.      ENDIF            ; LIBRARY AND NOT OSBORNE
  1373. ;
  1374.      IF    LIBRARY
  1375.     DB    '| ',0
  1376. ;
  1377. NYET1:    POP    H        ; Reset to start of this entry
  1378. ;
  1379. NYET:    LXI    B,20H        ; Length of each entry
  1380.     DAD    B        ; Step to next
  1381.     POP    B        ; Get entry count (remaining)
  1382.     DCR    B
  1383.     JNZ    DIRLP        ; More members
  1384.     LDA    MEMNAM        ; Do we have member name on command line?
  1385.     ORA    A
  1386.     JNZ    XLIB        ; If not then display message
  1387.     CALL    CDISP
  1388.     DB    CR,LF,ENDMSG    ; Leave blank line after directory
  1389.     JMP    EXIT
  1390. ;
  1391. XLIB:    CALL    CDISP
  1392.     DB    'Not in LBR',CR,LF,0
  1393.     JMP    EXIT        ; And show the poor schmuck the directory
  1394. ;
  1395. ; Found the member name
  1396. ;
  1397. FOUND:
  1398.     POP    B        ; Clear stack
  1399.     LXI    D,12
  1400.     DAD    D
  1401.     PUSH    H        ; Save pointer for now,
  1402.     INX    H        ; Point to size
  1403.     INX    H
  1404.     MOV    A,M        ; Get low byte
  1405.     INX    H
  1406.     MOV    H,M
  1407.     MOV    L,A
  1408.     ORA    H        ; If a=0 then file is 0k
  1409.     JZ    NULLEN        ; Go complain
  1410.     XTHL            ; Get pointer back, save size
  1411.     MOV    A,M        ; Get file address
  1412.     INX    H
  1413.     MOV    H,M
  1414.     MOV    L,A
  1415.     SHLD    SCZERO        ; Save as first file record
  1416.     POP    D        ; & get size back
  1417.     DAD    D        ; Convert to last record no (inclusive)
  1418.     SHLD    SCLAST
  1419.      ENDIF            ; LIBRARY
  1420. ;
  1421.      IF    LIBRARY    AND SQUEEZE
  1422.     LDA    SQFLG        ; Get SQ flag in case of double squeeze
  1423.     ORA    A
  1424.     JZ    NOLBSQ        ; Ok, library itself not squeezed
  1425.     CALL    CDISP
  1426.     DB    'unSQ LBR',CR,LF,0
  1427.     JMP    EXIT
  1428. ;
  1429. NOLBSQ:    CALL    CHKSQ        ; Check if  member squeezed
  1430.      ENDIF            ; LIBRARY AND SQUEEZE
  1431. ;
  1432.      IF    LIBRARY
  1433.     CALL    FILBF0        ; Refill buffer, now for member
  1434. ;                 (FILBUF handles member offset in library)
  1435.     RET
  1436. ;
  1437. ; Member is empty
  1438. ;
  1439. NULLEN:    CALL    CDISP
  1440.     DB    'Empty',CR,LF,0
  1441.     JMP    EXIT
  1442.      ENDIF            ; LIBRARY
  1443. ;
  1444. ; Get input if any
  1445. ;
  1446. GETIN:    MVI    C,6        ; Direct console I/O
  1447.     MVI    E,0FFH        ; __set up for input
  1448.     CALL    BDOS        ; Get character
  1449.     RET
  1450. ;
  1451. ; Compare strings HL> to DE> over <B>
  1452. ;
  1453. ; <DE> and <B> are changed, <HL> kept
  1454. ;
  1455. CPSTR:    PUSH    H
  1456. ;
  1457. CP$LP:    LDAX    D
  1458.     CMP    M
  1459.     JNZ    CP$EX        ; No match
  1460.     INX    D
  1461.     INX    H
  1462.     DCR    B
  1463.     JNZ    CP$LP
  1464. ;
  1465. CP$EX:    POP    H
  1466.     RET
  1467. ;
  1468. ; Compare <HL> to <DE> Z - equal; C - <HL> less than <DE> if equal
  1469. ; returns <A>=0
  1470. ;
  1471. CMPHLDE:MOV    A,H
  1472.     SUB    D
  1473.     RNZ
  1474.     MOV    A,L
  1475.     SUB    E
  1476.     RET
  1477. ;
  1478. ; Skip blanks in input
  1479. ;
  1480. EATSP:    MOV    A,M        ; Get character if there is one
  1481.     INX    H
  1482.     DCR    B        ; B=number of characters left
  1483.     RZ            ; No more characters
  1484.     CPI    SPACE        ; Ignore spaces
  1485.     JZ    EATSP
  1486.     DCX    H        ; Step back to 1st non-blank
  1487.     INR    B
  1488.     ORA    A        ; Force NZ
  1489.     RET
  1490. ;
  1491. ; Skip name in input
  1492. ;
  1493. FILNAM:    MOV    A,M        ; Get characters in file name
  1494.     INX    H
  1495.     DCR    B        ; B=number of characters left
  1496.     RZ            ; Only file name in tail
  1497.     CPI    SPACE        ; Wait for next space
  1498.     JNZ    FILNAM
  1499.     ORA    A        ; Force NZ
  1500.     RET            ; Blank
  1501. ;
  1502. ; Move from HL> to DE> over <B>
  1503. ;
  1504. MOVE:    MOV    A,M
  1505.     STAX    D
  1506.     INX    H        ; Step to next source
  1507.     INX    D        ; & destination
  1508.     DCR    B        ; Reduce count (00=256)
  1509.     JNZ    MOVE
  1510.     RET
  1511. ;
  1512. ;******************************************************
  1513. ; USQ support code                      *
  1514. ; 10/12/83 by Dave Rand                   *
  1515. ;******************************************************
  1516. ;
  1517. ; Check for SQ file, initialize tree if so
  1518. ;
  1519.      IF    SQUEEZE
  1520. CHKSQ:    XRA    A
  1521.     MOV    L,A
  1522.     MOV    H,L        ; Clear <hl>
  1523.     STA    SQFLG        ; Make sure not set as squeezed yet
  1524.     STA    SQEOF        ; End of file on SQ
  1525.     STA    SQREWD        ; Clear "rewinding" SQ file
  1526.     STA    BITLFT        ; Force init char read
  1527.     STA    RCNT        ; And zero repeats
  1528.     STA    FCBCRR+2    ; And overflow
  1529.     SHLD    NUMVALS        ; Clear # nodes
  1530.      ENDIF            ; SQUEEZE
  1531. ;
  1532.      IF    SQUEEZE    AND LIBRARY
  1533.     LHLD    SCZERO        ; Get 1st record for member
  1534.     SHLD    NXTREC        ; & save as next record
  1535.      ENDIF            ; SQUEEZE AND LIBRARY
  1536. ;
  1537.      IF    SQUEEZE
  1538.     SHLD    FCBCRR        ; Clear next record
  1539.     LXI    H,SQBUF        ; Set to input (squeezed) buffer
  1540.     SHLD    INBUFS
  1541.     SHLD    INBUFU
  1542.     LXI    D,128
  1543.     DAD    D
  1544.     SHLD    SQBUFE        ; Force exit on full buffer aft 1 sect
  1545. ;
  1546. ; Ccauses the SQ buffer to contain records 1+ only (not zero), normally
  1547. ; fine since recort 0 contains only header info.  Record 0 will be re-
  1548. ; read if contains data and needed.  Read and validate signature word.
  1549. ;
  1550.     CALL    GETW        ; Read    1st word in file
  1551.     LXI    D,SQSIGN    ; Get expected value
  1552.     CALL    CMPHLDE
  1553.     RNZ
  1554.     MVI    A,1
  1555.     STA    SQFLG        ; Yes - set flag
  1556.     LHLD    0006        ; Get top of memory
  1557.     LXI    D,SQBUF+100H*128 ; Limit buffer to max 100H
  1558.     CALL    CMPHLDE        ; Records (FILBUF uses 8 bit count <B>)
  1559.     JC    TOPLOW        ; Use top
  1560.     XCHG            ; Use limit
  1561. ;
  1562. TOPLOW:    SHLD    SQBUFE        ; & store as full address
  1563.     CALL    NAMLP        ; Skip past name
  1564.     CALL    USQTBL        ; Validate & load decoding tree
  1565.     JZ    OAK        ; Tree ok
  1566.     CALL    CDISP
  1567.     DB    CR,LF,'Bad SQ tree',CR,LF,0
  1568.     JMP    EXIT
  1569. ;
  1570. OAK:    LXI    H,SQMAP+2    ; Point to 1st entry
  1571.     SHLD    SQMAP        ; Set to 1at entry in SQ mapper
  1572.     RET
  1573. ;
  1574. ; Read and save checksum
  1575. ;
  1576. RDCHKS:    CALL    GETW        ; Get checksum, and store
  1577.     SHLD    FILCHKS
  1578.     RET
  1579. ;
  1580. ; Read and skip name
  1581. ;
  1582. NAMLP:    CALL    GETC        ; Loop to skip name
  1583.     JNZ    EREXT        ; I/O error or unexpected EOF
  1584.     ORA    A
  1585.     JNZ    NAMLP        ; Not yet end of name
  1586.     RET
  1587. ;
  1588. ; Load decoding tree.  This version uses 1 byte abslute node indices
  1589. ; (1-0FFH) and is thus limited to 255 nodes and 255 characters represen-
  1590. ; ted in the squeezed file.  (All different characters present in the
  1591. ; original file as well as any added through run encoding.  Runs of 3 or
  1592. ; more consecutive identical characters are encoded as char, DLE, count,
  1593. ; where count is a one byte field 00 - 0FFh)
  1594. ;
  1595. USQTBL:    CALL    GETW        ; Get no of nodes
  1596.     MOV    A,H
  1597.     ORA    L
  1598.     JZ    NZEXIT        ; Null tree
  1599.     SHLD    NUMVALS
  1600.     MOV    A,H        ; Max 257, 256 char & spec eof
  1601. ;
  1602. ; In this version allow for only 256 different codes, every ASCII and
  1603. ; non-ASCII character would have to be present, or run repeat counts
  1604. ; 128-255 (every one)
  1605. ;
  1606.     ORA    A        ; H/o byte should be zero
  1607.     JNZ    NZEXIT
  1608.     LXI    D,SQTREE    ; Set to decoding tree
  1609. ;
  1610. NODELP:    SHLD    NXTADR        ; Save no of nodes
  1611.     MOV    A,H
  1612.     ORA    L
  1613.     RZ            ; Done all nodes
  1614.     CALL    CVNODE        ; Get node, falg byte in <H>,
  1615.     PUSH    H
  1616.     CALL    CVNODE        ; Get second child/char
  1617.     POP    B
  1618.     MOV    A,B
  1619.     RAL            ; Shift flags to 8, 4 posns
  1620.     ORA    H        ; Combine in 1st child flags
  1621.     XCHG            ; HL> SQTREE, <A>,<C>,<E> node
  1622.     MOV    M,A        ; Store flags in table
  1623.     INX    H
  1624.     MOV    M,C
  1625.     INX    H
  1626.     MOV    M,E
  1627.     INX    H
  1628.     XCHG            ; DE> SQTREE
  1629.     LHLD    NXTADR        ; Nodes remaining
  1630.     DCX    H
  1631.     JMP    NODELP
  1632. ;
  1633. ; Get encoded node.  Our nodes contain 3 bytes: 1) flag byte, 2) left
  1634. ; child index/character and 3) right child index/character.  Codes on
  1635. ; input are 4 bytes, with each half containing an index (1-100h) or
  1636. ; character, where characters are encoded as negative values -(char+1)
  1637. ; EOF is encoded as -(100h+1)
  1638. ;
  1639. CVNODE:    PUSH    D
  1640.     CALL    GETW        ; Get word, child pointer or character
  1641.     POP    D
  1642.     MOV    A,H
  1643.     ORA    A
  1644.     RZ            ; Child index, <H>=0,<L>=index
  1645.     MOV    A,L
  1646.     CMA
  1647.     MOV    L,A        ; Convert character to register form
  1648.     MOV    A,H        ; Get h/o byte again
  1649.     CMA
  1650.     INR    A        ; Conv to 1 if char, 2 if EOF
  1651.     MOV    H,A
  1652.     CPI    1        ; Was that reg char?
  1653.     RZ            ; Yes - complete
  1654.     ADI    3        ; No convert EOF flag to 0100
  1655.     MOV    H,A
  1656.     RET
  1657. ;
  1658. ; Exit with NZ flag
  1659. ;
  1660. NZEXIT:    MVI    A,2        ; Tree error
  1661.     ORA    A        ; Set NZ flag
  1662.     RET
  1663. ;
  1664. ; Fill output buffer (unsqueezed char)
  1665. ;
  1666. FILUSQ:
  1667.     LDA    SQREWD        ; Rewinding SQ input?
  1668.     ORA    A
  1669.     JZ    NOREWD        ; No
  1670. ;
  1671. ; Reload SQ buffer
  1672. ;
  1673.     LHLD    INBUFS
  1674.     PUSH    H        ; Getrf resets
  1675.     CALL    GETRF        ; Yes - reload buffer & get 1st 8 bits
  1676.     POP    H
  1677.     SHLD    INBUFS        ; Set to first data byte to use
  1678. ;
  1679. BADJ:    MOV    C,A
  1680.     LDA    BITLFT        ; Get preset 1st wanted bit no
  1681.     MOV    C,A
  1682.     MVI    A,8
  1683.     SUB    B        ; Calculate adjustment required
  1684. ;
  1685. BADJLP:    DCR    A
  1686.     JZ    BADJFN        ; Bit adjust finished
  1687.     MOV    B,A
  1688.     MOV    A,C
  1689.     RRC
  1690.     MOV    C,A
  1691.     MOV    A,B
  1692.     JMP    BADJLP
  1693. ;
  1694. BADJFN:    STA    BITBUF
  1695.     XRA    A
  1696.     STA    SQREWD        ; And clear rewind flag
  1697. ;
  1698. NOREWD:    LXI    H,DSKBUF    ; Reset buffer pointer
  1699.     XRA    A
  1700. ;
  1701. BUFLP:    SHLD    NXTADR        ; Save as next byte in buffer
  1702.     RNZ            ; End of file (NZ flag)
  1703.     LXI    D,SQTREE    ; Get end of input
  1704.     CALL    CMPHLDE        ; Buffer full (de < HL - not full)
  1705.     JNC    FULL        ; Buffer is full
  1706.     CALL    GETNXT        ; Get next decoded character
  1707. ;
  1708. ; No checksum taken
  1709. ;
  1710.     LHLD    NXTADR        ; Next out buffer posn
  1711.     MOV    M,A        ; Store char returned, may be EOF char
  1712.     INX    H
  1713.     JMP    BUFLP
  1714. ;
  1715. FULL:    XRA    A        ; Ensure Z
  1716.     RET            ; Return on full buffer
  1717. ;
  1718. ; Get next decoded character
  1719. ;
  1720. GETNXT:    LDA    RCNT        ; See if in the middle of
  1721.     ORA    A        ; Repeat sequence...
  1722.     JZ    NORPT
  1723.     DCR    A        ; Yes - reduce repeat remaining
  1724.     STA    RCNT
  1725.     LDA    LAST        ; Get latest char again
  1726.     CMP    A
  1727.     RET            ; Return with Z for ok
  1728. ;
  1729. NORPT:    CALL    DECODE
  1730.     RNZ            ; EOF? <A>=1AH
  1731.     CPI    DLE        ; Run encoding flag?
  1732.     JNZ    NORUN
  1733. ;
  1734. ; Handle DLE
  1735. ;
  1736.     CALL    DECODE        ; Get count
  1737.     RNZ            ; EOF? (is really error after DLE)
  1738.     ORA    A
  1739.     JNZ    RUN        ; Non-zero, real run
  1740.     MVI    A,DLE        ; Dle is encoded as dle,0
  1741.     CMP    A
  1742.     RET
  1743. ;
  1744. ; Run encoding found
  1745. ;
  1746. RUN:    DCR    A        ; Allow for char already retnd
  1747.     DCR    A        ; and this one
  1748.     STA    RCNT        ; Keep count yet to be retd
  1749.     LDA    LAST        ; Return second time
  1750.     CMP    A
  1751.     RET
  1752. ;
  1753. ; Normal character, no run active
  1754. ;
  1755. NORUN:    STA    LAST        ; This may be the start
  1756.     CMP    A
  1757.     RET
  1758. ;
  1759. ;
  1760. ; Read bits and decode to character.  Nnote this version uses 3 bytes
  1761. ; per node, not 4.
  1762. ;   The first byte in each node is a flag byte
  1763. ;     .... x... - left node contains EOF marker
  1764. ;     .... .x.. - right node contains EOF marker
  1765. ;     .... ..x. - left node contains char
  1766. ;     .... ...x - right node contains char
  1767. ;
  1768. DECODE:    LXI    D,0        ; Set to node zero in table
  1769.     LDA    BITBUF        ; Get bits from bit buffer
  1770.     MOV    C,A
  1771. ;
  1772. BITLP:    LDA    BITLFT        ; Any bits remaining?
  1773.     ORA    A
  1774.     JNZ    NXTBIT        ; Yes - go use
  1775.     PUSH    D
  1776.     CALL    GETC        ; No - replenish bit buffer
  1777.     JNZ    BADR        ; Unexpected eof
  1778.     POP    D
  1779.     MOV    C,A
  1780.     MVI    A,8        ; Set as 8 bits inbuffer
  1781. ;
  1782. NXTBIT:    DCR    A
  1783.     STA    BITLFT        ; Save no of bit remaining
  1784.     LXI    H,SQTREE    ; Set to node 0, left child ptr
  1785.     DAD    D
  1786.     DAD    D
  1787.     DAD    D        ; Add in node no (4 bytes/node)
  1788.     MOV    B,M        ; Get flag byte
  1789.     INX    H        ; Step to left child pointer
  1790.     MOV    A,C        ; Get input bits
  1791.     RRC            ; Shuffle LOW-ORDER bit to Carry
  1792.     MOV    C,A
  1793.     MOV    A,B        ; Get flag byte
  1794.     JNC    GETN3        ; Zero input bit,leave at left
  1795.     INX    H        ; Add 1 to point to right child pointer
  1796.     ADD    B        ; Normalize wanted flags to .... x.x.
  1797. ;
  1798. GETN3:    MOV    E,M        ; Pick up child or character
  1799. ;
  1800. ; <D> should always remain zero
  1801. ;
  1802.     ANI    1010B        ; Mask unwanted bits
  1803.     JZ    BITLP        ; Reg child pointer
  1804. ;
  1805. ; Got to character or EOF
  1806. ;
  1807.     ANI    1000B        ; End of file marker?
  1808.     JNZ    GOTEOF        ; Yes - get out with eof
  1809.     MOV    A,C
  1810.     STA    BITBUF        ; Save bit buffer
  1811.     MOV    A,E        ; Get decoded char (neg)
  1812.     RET
  1813. ;
  1814. ; Exit on register EOF
  1815. ;
  1816. GOTEOF:
  1817.     MVI    A,EOF
  1818.     ORA    A
  1819.     RET
  1820. ;
  1821. ; Get input word (low/high, unencoded)
  1822. ;
  1823. GETW:    CALL    GETC
  1824.     JNZ    BADR        ; Unexpected EOF
  1825.     PUSH    PSW
  1826.     CALL    GETC
  1827.     JNZ    BADR        ; Unexpected EOF
  1828.     MOV    H,A
  1829.     POP    PSW
  1830.     MOV    L,A
  1831.     RET
  1832. ;
  1833. EREXT:    DS    0
  1834. ;
  1835. BADR:    CALL    CDISP
  1836.     DB    CR,LF,'EOF?',CR,LF,0
  1837.     JMP    EXIT
  1838. ;
  1839. ; Get single (unencoded) character
  1840. ;
  1841. GETC:    LHLD    INBUFU
  1842.     XCHG
  1843.     LHLD    INBUFS
  1844.     CALL    CMPHLDE        ; End of input buffer?
  1845.     JZ    GETRF        ; Yes
  1846. ;
  1847. GETC1:    MOV    A,M        ; No get next byte
  1848.     INX    H
  1849.     SHLD    INBUFS        ; Save addr of next byte
  1850.     CMP    A
  1851.     RET
  1852. ;
  1853. ; Refill input buffer
  1854. ;
  1855. GETRF:    LDA    SQEOF        ; Is there anything else?
  1856.     ORA    A
  1857.     JZ    GETOK
  1858.     CALL    CDISP
  1859.     DB    CR,LF,'EOF',CR,LF,0
  1860.     JMP    EXIT
  1861. ;
  1862. GETOK:    LHLD    RECCNT        ; Save record count (decoded buffer only)
  1863.     PUSH    H
  1864.     LXI    H,SQBUF        ; Set input buffer as empty,
  1865.     SHLD    INBUFS        ; _and start of buffer
  1866.     XCHG            ; DE> buffer, next record locn
  1867.     LHLD    SQBUFE        ; End of input buffer
  1868.     SHLD    INBUFU        ; Assume no end of file for now
  1869.     MOV    A,L
  1870.     SUB    E
  1871.     MOV    L,A
  1872.     MOV    A,H
  1873.     SBB    D        ; Calc buffer size
  1874.     MOV    H,A
  1875.     DAD    H        ; Convert to no of records
  1876.     MOV    B,H        ; No of records to read
  1877.     LHLD    FCBCRR        ; No of 1st record to read
  1878.     SHLD    SQBSC1
  1879.     CALL    FILBU1        ; Read record into SQBUF
  1880. ;
  1881. ; <B> no of sectors not read if EOF
  1882. ; HL> 128
  1883. ; DE> last sector read, or after if EOF
  1884. ;
  1885.     LHLD    FCBCRR        ; Get next SQ record number
  1886.     SHLD    NXTSQS
  1887.     MOV    A,B        ; Did we fill buffer?
  1888.     ORA    A
  1889.     JZ    GETRF2        ; Yes - no EOF
  1890.     XCHG            ; Eof, adjust buffer end marker
  1891.     SHLD    INBUFU        ; Mark end of buffer used
  1892.     STA    SQEOF        ; and flag EOF
  1893. ;
  1894. ; Input buffer re-filled
  1895. ;
  1896. GETRF2:    POP    H
  1897.     SHLD    RECCNT        ; Restore record count (decoded buffer only)
  1898.     LHLD    INBUFU        ; Get end of buffer
  1899.     XCHG
  1900.     LHLD    INBUFS        ; Get start of buffer
  1901.     CALL    CMPHLDE        ; Something there?
  1902.     JC    GETC1        ; Yes - go for char
  1903.     JMP    EREXT        ; No - read past eof or empty file
  1904. ;
  1905. ; End of baseline USQ code
  1906. ;
  1907. OTBUFE:    DW    0        ; End of decoded char buffer
  1908. INBUFS:    DW    0        ; Start of input buffer
  1909. INBUFU:    DW    0        ; End of used part input buffer
  1910. SQBUFE:    DW    0        ; End of input buffer
  1911. ;
  1912. NXTADR:    DW    DSKBUF        ; Next byte in output buffer
  1913.                 ; Also used when loading tree
  1914. BITLFT:    DS    1        ; No of bits left in bit buffer
  1915. RCNT:    DS    1        ; Run count remaining (DLE)
  1916. FILCHKS:DS    2        ; Checksum read from file
  1917. LAST:    DS    1        ; Last reg char decoded
  1918. BITBUF:    DS    1        ; Latest 8 bits (encoded) from input file
  1919. NUMVALS:DS    2        ; No of nodes in encodng tree
  1920.      ENDIF            ; SQUEEZE
  1921. ;
  1922. ; Memory allocation
  1923. ;
  1924. RECCNT:    DW    0        ; Number of records read into buffer
  1925. LINMAX:    DB    SCROLN        ; Number of write lines on console
  1926. CHRMAX:    DB    MAXCHR-1    ; Number of characters to display per line
  1927. CHRMIN:    DB    0        ; Character to start displaying on line
  1928. CHRCNT:    DS    1        ; Character number in line
  1929. LINCNT:    DS    1        ; Line number on write or move back in buffer
  1930. TOPBUF:    DB    0        ; Top of file is now in buffer
  1931. ;                 Z - yes, NZ - no
  1932. ;
  1933.      IF    SQUEEZE
  1934. NXTREC:    DW    0        ; Next (unsqueezed) record not yet in BSKBUF
  1935. ;                 set (and used) only by FILSQ
  1936. SQFLG:    DB    0        ; File is squeezed
  1937. SQEOF:    DB    0        ; End of file on squeezed file
  1938. SQREWD:    DB    0        ; Flag the SQ input file is being re-read
  1939. ;                 buffer refill rtn (getrf) to set inbufs
  1940. ;                 as per offset in SQBYT, and pre-load
  1941. ;                 bit buffer. Bit buffer to be adj
  1942. ;                 as per Bitlft
  1943. SQBYT:    DW    0        ; Offset of first data byte in SQ buffer
  1944. SQBSC1:    DW    0        ; No of 1st record in SQ buffer
  1945. NXTSQS:    DW    0        ; No of last record in SQ buffer
  1946.      ENDIF            ; SQUEEZE
  1947. ;
  1948.      IF    LIBRARY
  1949. NAMEXC:    DB    (MAXCHR/14)-1    ; No of directory names across display
  1950.     DB    0        ; No of names so far
  1951. DIRSIZ:    DB    0        ; # of members possible in directory
  1952. MEMNAM:    DB    0        ; Member name specified on command line
  1953. SCZERO:    DW    0        ; First record for member
  1954. SCLAST:    DW    0FFFFH        ; Last record for member (included in member)
  1955. ;                 SCZERO and SCLAST are relative in file
  1956. LBFLG:    DB    0        ; File is a library file
  1957. MEMFCB:    DS    12        ; Member name here
  1958.      ENDIF            ; LIBRARY
  1959. ;
  1960.     DS    60        ; Stack area
  1961. STACK:    DS    2        ; Old stack saved here
  1962. DSKBUF    EQU    $        ; Disk buffer area above the program
  1963. ;
  1964. ENDBUF    EQU    DSKBUF+MAXREC*128
  1965. ;
  1966.      IF    SQUEEZE
  1967. SQTREE    EQU    ENDBUF        ; Space for SQ decoding tree
  1968. SQMAP    EQU    SQTREE+256*3
  1969. ;
  1970. ; Space for SQ buffer mapping table contains squeeze record #, squeeze
  1971. ; byte and bit offset for every time DSKBUF was filled.  1st entry con-
  1972. ; tains index to latest mapping triplet to handle run compr straddling
  1973. ; buffer end, should also store rcnt  and last.
  1974. ;
  1975. SQBUF    EQU    SQMAP+100*4    ; (allows for 100 8k buffers)
  1976.      ENDIF            ; SQUEEZE
  1977. ;
  1978. ; Input (squeezed) buffer, runs up to top of free memoryot
  1979. ;
  1980.     END    TPA
  1981.