home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / beehive / zcat / bishow32.lbr / BISHOW32.AZM / BISHOW32.ASM
Assembly Source File  |  1991-01-30  |  50KB  |  2,059 lines

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