home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / list / qlist15.lbr / QLIST15.AZM / QLIST15.ASM
Assembly Source File  |  1987-01-05  |  37KB  |  1,633 lines

  1. ;***********************************************************
  2. ;      QLIST.ASM  Copyright (C) 1985 by UCS, inc.
  3. ;***********************************************************
  4.  
  5. VER    EQU    15    ; Version 1.5 January 03/87
  6.  
  7. ; Version 1.5  January 03/87
  8. ;      Fixed  bug with tab expansion;  margin offset  spaces
  9. ;      should  not  count  when calculating next mod  8  tab
  10. ;      stop.
  11. ;                       - IC
  12. ;
  13. ; Version 1.4  March 19/86
  14. ;      Fixed  several  bugs  with  headers  under  different
  15. ;      combinations  of  compressed  print/expanded  header.
  16. ;      Added  code  to    allow header message to  show  total
  17. ;      space  availabe for header with all  combinations  of
  18. ;      compressed/expanded.   Made  REVO a flag that can  be
  19. ;      changed with DDT.
  20. ;                       - IC
  21. ; Version 1.3  Feb 18/86
  22. ;      Changed    string print subroutine to use high bit  set
  23. ;      as end of string marker instead of '0'.     This allows
  24. ;      strings    containing  a  zero to be sent    to  printer.
  25. ;      Since I found that I used the $O options most of  the
  26. ;      time,  I  also added a switch to allow all options to
  27. ;      be the default and $O to signify no  options.   Moved
  28. ;      the expanded and compressed print strings to 103H and
  29. ;      added  spare  bytes  so that they  could  be  changed
  30. ;      without having to re-assemble the entire program.
  31. ;                       - IC
  32. ; Version 1.2  Jan 22/86
  33. ;      Added  compressed  print and expanded title  options.
  34. ;      Minor (mostly cosmetic) changes to other code.
  35. ;                       - Ian Cottrell
  36. ;                     Sysop, ICBBS
  37. ;                     Ottawa, Ont, Canada
  38. ;                     (613)-990-9774
  39. ;
  40. ; Version 1.1  11/30/1985
  41. ;      Fixed nasty bug when printing files on other than the
  42. ;      default drive.
  43. ;                       - JG
  44. ;
  45. ; Version 1.0  10/02/1985  by Jim Gronek
  46. ;
  47. ;
  48. ; QLIST  is a file lister that will automatically  unsqueeze
  49. ; files  before  listing.    QLIST  allows  you  to   select
  50. ; formatting options for the listing, including; left margin
  51. ; setting,  line feed recognition,  page headers, compressed
  52. ; print  for  body  of listing and expanded  print  for  the
  53. ; headers  (if    your printer supports these  features),  and
  54. ; page to start/stop printing.
  55. ;
  56. ; QLIST  is  based on KPLISTER,  but lacks  the  Okidata  92
  57. ; printer options selection feature,  and Kaypro video codes
  58. ; of KPLISTER.     QLIST is a generic file lister for use with
  59. ; ANY  Z-80 based,   CP/M 2.2 or 3.0 system and any printer.
  60. ; NOTE     - If  you  desire   expanded  print   headings   or
  61. ; compressed  print  in  the body,  you  must  provide    your
  62. ; printer equates before assembly.   The source code is  set
  63. ; to support a Fujitsu DX2200 printer.
  64. ;
  65. ; QLIST combines the functions of LISTT16 ((C) Irv Hoff) and
  66. ; USQB.REL  ((C)  Dave Rand) to provide greater  flexibility
  67. ; for the user.
  68. ;
  69. ; QLIST must be executed with a filename.typ argument.     The
  70. ; syntax is as follows:
  71. ;
  72. ;   QLIST filename.typ [$o]
  73. ;   where: $   is the options menu flag
  74. ;       $O  toggles the formatting options for
  75. ;           the listing (see below)
  76. ;       $S  sends output to the CRT only
  77. ;
  78. ; The  byte stored at REVO allows you to select the  default
  79. ; setting for the formatting options switch, $O.  If REVO is
  80. ; true (non-zero),  then QLIST assumes that you always    want
  81. ; the formatting options and will prompt you for all allowed
  82. ; options if no options menu flag is entered.  In this case,
  83. ; entering  $O on the command line will cause options to  be
  84. ; suppressed.    If REVO is false (zero),  then the operation
  85. ; of  the $O switch is reversed (i.e.  $O means use options,
  86. ; no $O means no options).
  87. ;
  88. ; If executed without a filename argument,  QLIST will    exit
  89. ; to CP/M with a warm boot.
  90. ;
  91. ; If  you wish to patch QLIST without recompiling,  the REVO
  92. ; flag    is at 104H.   Set to 0 for normal ($O  required  for
  93. ; options)  or    0FFH for reverse options (no  $O  required).
  94. ; The  compressed  print on string starts at 104H  to  109H,
  95. ; compressed  off  at 10AH to 10FH,  expanded on at 110H  to
  96. ; 115H and expanded off at 116H to 11CH.   Remember that the
  97. ; last byte of each of these strings must have the high  bit
  98. ; set.
  99. ;
  100. ; QLIST  may  be assembled with ASM ((C) DRI),    LASM or  MAC
  101. ; ((C) DRI).
  102.  
  103.     ORG    100H
  104.  
  105. ;-------------------- configuration --------------------
  106.  
  107. FALSE    EQU    00H
  108. TRUE    EQU    NOT FALSE
  109.  
  110. CTLC    EQU    'C'-40H        ; Control-c to terminate
  111. BELL    EQU    'G'-40H        ; Control-g for bell
  112. BS    EQU    'H'-40H        ; Control-h for backspace
  113. TAB    EQU    'I'-40H        ; Control-i for tab
  114. LF    EQU    'J'-40H        ; Control-j for linefeed
  115. FFD    EQU    'L'-40H        ; Control-l for formfeed
  116. CR    EQU    'M'-40H        ; Control-m for carriage return
  117. SI    EQU    'V'-40H        ; Control-v for synch idle
  118. CTLX    EQU    'X'-40H        ; Control-x to terminate
  119. EOF    EQU    'Z'-40H        ; Control-z for end-of-file
  120.  
  121. FCB1    EQU    05CH        ; Location of file control block
  122. TBUFF    EQU    080H        ; Buffer for file control block
  123. TEXT    EQU    054        ; Number of lines of text per page
  124. PAGENM    EQU    3
  125.  
  126. ESC    EQU    1BH        ; Escape character
  127.  
  128. ; BDOS equates
  129.  
  130. BDOS    EQU    05H        ; System call entry point
  131. CONIN    EQU    01H        ; Get keyboard character
  132. CONOUT    EQU    02H        ; Crt output routine
  133. LIST    EQU    05H        ; List device output
  134. PSTRING    EQU    09H        ; Console output string
  135. CINPUT    EQU    0AH        ; Console input line
  136. STATUS    EQU    0BH        ; Console status
  137.  
  138. ;    print format options table
  139. ;    set the following equates as desired:
  140.  
  141. OPTS    EQU    TRUE        ; True to allow any options
  142. RPOPT    EQU    FALSE        ; True to allow roll paper option
  143. MGNOPT    EQU    TRUE        ; True to allow margin option
  144. FFOPT    EQU    TRUE        ; True to allow forms feed option
  145. HDGOPT    EQU    TRUE        ; True to allow heading option
  146. SSPGOPT    EQU    TRUE        ; True to allow start/stop page option
  147. CMPOPT    EQU    TRUE        ; True to use compressed print for body
  148.                 ; Be sure to set CMPON and CMPOF below
  149. EXPOPT    EQU    TRUE        ; True to use expanded print for titles
  150.                 ; Be sure to set EXPON and EXPOF below
  151.  
  152. NWIDTH    EQU    78        ; Paper width for normal print
  153. NPGCOL    EQU    68        ; Start column of page number for normal print
  154. CWIDTH    EQU    130        ; Paper width for compressed print
  155. CPGCOL    EQU    120        ; Start column of page number for compressed
  156.  
  157. ;  end of print options table
  158.  
  159. BEGIN:    JMP    OKPRNT        ; Jump around signon message
  160.  
  161. REVO    DB    0FFH        ; Reverse options flag
  162.  
  163.      IF    CMPOPT        ; NOTE:  Last character of these strings
  164.                 ;   must have the high bit set (i.e. '+80H')
  165. CMPON:    DB    15+80H        ; Enter compressed print for Fujitsu DX2200
  166.     DB    0,0,0,0,0    ; Spares to allow change without re-assemble
  167. CMPOF:    DB    18+80H        ; Return to normal print for Fujitsu DX2200
  168.     DB    0,0,0,0,0    ; Spares
  169.      ENDIF
  170.  
  171.      IF    EXPOPT
  172. EXPON:    DB    14+80H        ; Enter expanded print for Fujitsu DX2200
  173.     DB    0,0,0,0,0    ; Spares
  174. EXPOF:    DB    20+80H        ; Cancel expanded print for Fujitsu DX2200
  175.     DB    0,0,0,0,0    ; Spares
  176.      ENDIF
  177.  
  178. TTABN:    DB    NWIDTH-1    ; Default - adjust later if necessary
  179. PAGCOL:    DB    NPGCOL        ; Default - adjust later if necessary
  180. FLAG:    DB    ' '
  181.  
  182. ; misc storage locations
  183.  
  184. SAVSTK:    DW    0        ; Storage for user's stack
  185. CCP:    DB    0        ; MSB of CCP address
  186. COLMN:    DB    0        ; Current column count
  187. LCNT:    DB    0        ; Current line count
  188. FRMFD:    DB    0        ; Form feed flag
  189. NOTAB:    DB    0        ; Tear tab flag
  190. START:    DB    0        ; Start indicator
  191. PAGIND:    DB    0        ; New page indicator
  192. COMPRS:    DB    0        ; Compressed print flag
  193. EXPAND:    DB    0        ; Expanded title flag
  194. MARGIN:    DB    0        ; Number of spaces to indent
  195. FLEN:    DB    0        ; Length of filename in header
  196. HLEN:    DB    0        ; Max length of header message
  197.  
  198.  
  199. ; file handling data
  200.  
  201. BUFADR:    DW    $-$
  202. FILEADR:DW    $-$
  203. FILELEN:DB    0,0
  204. FILEPTR:DB    0,0
  205. FILESIZ:DB    0,0
  206. FCB:    DB    0,0,0,0,0,0,0,0,0,0,0,0
  207.     DB    0,0,0,0,0,0,0,0,0,0,0,0
  208.     DB    0,0,0,0,0,0,0,0,0,0,0,0
  209.  
  210. ; heading line for hard copy
  211.  
  212. HEAD1:    DB    SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,'  '
  213. HEAD2:    DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  214.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  215.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  216.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  217.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  218.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  219.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  220.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0
  221. HEAD3:    DB    'Page '
  222. HEAD4:    DB    SI,SI,'1',CR,LF,LF,LF+80H
  223. PAGES:    DB    SI,SI,'1   '
  224. PAGEQ:    DB    SI,SI,'    '
  225. QUIT:    DB    CR,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF+80H
  226. QUITR:    DB    CR,LF,LF,LF,LF+80H
  227. TURNUP:    DB    CR,LF,LF,LF,LF,LF,LF,LF,LF,LF,CR,LF+80H
  228.  
  229. MSG1:    DB    CR,LF
  230.     DB    '   QLIST v'
  231.     DB    VER/10+'0','.',VER MOD 10+'0'
  232.     DB    ' File Listing Utility (Unsqueezes)  '
  233.     DB    CR,LF
  234.     DB    '         Copyright (C) 1985 by UCS, inc.         '
  235.     DB    CR,LF,LF+80H
  236.  
  237. MERRR:    DB    '      == No filename was specified ==     '
  238.     DB    BELL,CR,LF
  239.     DB    ' (use $S after filename.typ for CRT only) '
  240.     DB    BELL,CR,LF
  241.     DB    ' (use $O  after filename.typ for options) '
  242.     DB    BELL,CR,LF
  243.     DB    '( ^X or ^C  aborts at end of current line)'
  244.     DB    CR,LF+80H
  245.  
  246. MERRN:    DB    ' == No file by that name on this disk == '
  247.     DB    CR,LF+80H
  248.  
  249. MERRW:    DB    '== No ambiguous filenames (*/?) please =='
  250.     DB    CR,LF+80H
  251.  
  252. MSG1B:    DB    ' Do you want tear tabs to use roll paper? (Y/N): ',' '+80H
  253. MSG1C:    DB    '        Number of spaces for left margin (0-99): ',' '+80H
  254. MSG1D:    DB    '             Accept Form Feed Characters? (Y/N): ',' '+80H
  255. MSG1E:    DB    ' Heading/date or title (055 character limit) is:  '
  256.     DB    CR,LF,LF,'---> ',' '+80H
  257. MSG1F:    DB    CR,LF
  258.     DB    '       Start printing at page # (Default = 1)  : ',' '+80H
  259. MSG1G:    DB    '        Quit printing at page # (Default = End): ',' '+80H
  260. MSG1H:    DB    '     Do you want to use compressed print? (Y/N): ',' '+80H
  261. MSG1J:    DB    '            Use expanded print for title? (Y/N): ',' '+80H
  262. MSG2:    DB    '                                Highest page is: ',' '+80H
  263. MSG3:    DB    CR,LF+80H
  264.  
  265. OKPRNT:    LXI    H,0        ; Save ccp's stack
  266.     DAD    SP        ;
  267.     SHLD    SAVSTK        ;
  268.  
  269. ; sign-on message
  270.  
  271.     LXI    H,MSG1
  272.     CALL    STRNGC
  273.  
  274. ; see if any file was requested
  275.  
  276. TITL:    LXI    H,TBUFF        ; Get ptr to command line tail
  277.     MOV    A,M        ; And get # chars in buffer
  278.     ORA    A        ; Check for none
  279.     JZ    ERRORR        ; Xfr - no command line tail
  280.     LHLD    MEMRY        ; Force to mod 256 address
  281.     LXI    D,257        ;
  282.     DAD    D        ;
  283.     MVI    A,0        ;
  284.     MOV    L,A        ;
  285.     SHLD    MEMRY        ;
  286.     LXI    D,128        ; Compute adr of local stack
  287.     DAD    D        ; [ 128 bytes above end of program ]
  288.     SPHL            ; Load stack register
  289.  
  290. ; calculate maximum available buffer size
  291.  
  292.     LHLD    MEMRY        ; Get adr of first available byte
  293.                 ; [stored by link or l80]
  294.     LXI    D,256+1032    ; Compensate for stack and table
  295.     DAD    D        ;
  296.     SHLD    BUFADR        ; Save adr of beginning of buffer
  297.     SHLD    FILEADR        ;
  298.     XCHG            ; Buffer adr to de
  299.     LDA    BDOS+2        ; Get msb of bdos adr to a
  300.     SUI    8        ; And decr by 8 [2k] for ccp
  301.     MOV    H,A        ; And move to h
  302.     STA    CCP        ; Also save as ccp adr msb
  303.     XRA    A        ; Zero-set a
  304.  
  305. ; calculate the difference to get space available
  306.  
  307.     SUB    E        ; Subtract buffer adr [de] from ccp
  308.     MOV    L,A        ; Adr to get buffer length
  309.     MOV    A,H        ; Result in hl
  310.     SBB    D        ;
  311.     MOV    H,A        ;
  312.  
  313. ; free space available now in 'hl', so store for buffer size
  314.  
  315.     SHLD    FILESIZ        ; Save buffer length
  316.  
  317. ; move file name into heading buffer
  318. ; check for any 'wild card' characters and if present show error
  319.  
  320.     LXI    H,FCB1        ; Get ptr to default fcb
  321.     MVI    B,11        ; And char count for file name
  322.  
  323. TITL1:    INX    H        ; Incr fcb ptr and
  324.     MOV    A,M        ; Fetch byte
  325.     CPI    '?'        ; Check for '?' - 'wild card'
  326.     JZ    ERRORW        ; Xfr - got '?' - illegal
  327.     DCR    B        ; Decr char count
  328.     JNZ    TITL1        ; Xfr - not through with name
  329.  
  330. ; open requested file to read the data to list
  331.  
  332.     LXI    H,FCB1        ; Move file name from default fcb
  333.     LXI    D,FCB        ; Get ptr to internal fcb
  334.     MVI    C,12        ; And length of disk, name, & type
  335.     CALL    STORE        ; And move to internal fcb
  336.     XRA    A        ; Zero set extent and record count fields
  337.     STA    FCB+12        ; Of fcb for bdos
  338.     STA    FCB+32        ;
  339.     LHLD    FILESIZ        ; Initialize read routine values
  340.     SHLD    FILELEN        ;
  341.     SHLD    FILEPTR        ;
  342.     LXI    D,FCB        ; Get fcb pointer for bdos
  343.     MVI    C,15        ; Cp/m 'open file' code
  344.     CALL    BDOS        ;
  345.     INR    A        ; Check for open error
  346.     JZ    ERRORN        ; Xfr - had open error
  347.  
  348. ; if yes, see if a drive was mentioned, do not print that
  349.  
  350.     LXI    H,TBUFF+3    ; Get ptr to 2nd data char
  351.     MOV    A,M        ; And fetch it
  352.     CPI    ':'        ; Check for disk separator
  353.     JZ    TITL2        ; Xfr - have disk specification
  354.     LXI    H,TBUFF        ; Reset ptr to beginning of data
  355.     INX    H        ; Incr past first blank
  356.  
  357. ; move the file name and heading/date into the buffer
  358.  
  359. TITL2:    LXI    D,HEAD1        ; Get ptr to heading buffer
  360.     MVI    B,0        ; Zero counter
  361.  
  362. TITL2A:    INX    H        ; Incr command line ptr and
  363.     MOV    A,M        ;   fetch byte
  364.     ORA    A        ; Check for terminator
  365.     JZ    TITL2B        ; Xfr - got terminator - end of line
  366.     CPI    ' '        ; Check for end of file name
  367.     JZ    TITL2B        ; Xfr - got blank - end of file name
  368.     STAX    D        ; Store byte in heading buffer
  369.     INX    D        ;   and incr buffer ptr
  370.     INR    B        ;     and counter
  371.     JMP    TITL2A        ; Go do next
  372.  
  373. TITL2B:
  374.      IF    NOT OPTS OR NOT    HDGOPT
  375.     DCX    D        ; Point to last char in heading buffer
  376.     LDAX    D        ; Get it
  377.     ORI    80H        ; Set high bit for printer output routine
  378.     STAX    D        ; Put it back
  379.      ENDIF            ; NOT OPTS OR NOT HDGOPT
  380.  
  381. TITL2C:    MOV    A,B        ; Store length of
  382.     STA    FLEN        ;   filename in header
  383.     MOV    A,M        ; Loop til end of line or option flag
  384.     ORA    A
  385.     JZ    NOOPT        ; No options
  386.     INX    H
  387.     CPI    '$'        ; Check for command line options
  388.     JNZ    TITL2C        ; Xfr - no command line options
  389.     DCX    H        ; Back-up to prior char position
  390.     MVI    M,0        ; And store line terminator
  391.     INX    H        ; Incr back to option byte,
  392.     MOV    A,M        ; Fetch it,
  393.     STA    FLAG        ; And store it for later
  394.     CPI    'S'        ; Check for 'screen only'
  395.     JNZ    THEAD        ; If not, continue
  396.     DCX    D        ; Else, point to last char in heading buffer
  397.     LDAX    D        ; Get it
  398.     ORI    80H        ; Set high bit for printer output routine
  399.     STAX    D        ; Put it back
  400.     JMP    GOPT6        ; Now skip options - 'screen only'
  401.  
  402. THEAD:    LDA    REVO        ; Get reverse options flag
  403.     ORA    A        ; Is set?
  404.     JZ    GOPT0        ; If no, skip
  405.     XRA    A        ; Else, reverse options, so clear 'O'
  406.     STA    FLAG
  407.     DCX    D        ; Point to last char in heading buffer
  408.     LDAX    D        ; Get it
  409.     ORI    80H        ; Set high bit for printer output routine
  410.     STAX    D        ; Put it back
  411.     JMP    GOPT6
  412.  
  413. EOL:
  414.      IF    NOT OPTS OR NOT    HDGOPT
  415.     DCX    D        ; Point to last char in heading buffer
  416.     LDAX    D        ; Get it
  417.     ORI    80H        ; Set high bit for printer output routine
  418.     STAX    D        ; Put it back
  419.      ENDIF            ; NOT OPTS OR NOT HDGOPT
  420.  
  421. NOOPT:    LDA    REVO        ; Get reverse options flag
  422.     ORA    A        ; Is set?
  423.     JZ    GOPT6        ; If not, skip options
  424.     MVI    A,'O'        ; Else, reverse options, so store 'O'
  425.     STA    FLAG
  426.  
  427. ;    get options from user
  428.  
  429. GOPT0:                ; Get 'tear tabs' option
  430.      IF    OPTS AND RPOPT
  431.     LXI    H,MSG1B        ; Output 'tear tabs' message
  432.     CALL    STRNGC        ;
  433.     CALL    INPUT        ; Get user's reply
  434.     ANI    5FH        ; Force upper case
  435.     CPI    'Y'        ; And check for 'yes'
  436.     JNZ    GOPT0A        ; Xfr - not 'yes' - assume 'no'
  437.     INR    A
  438.     STA    NOTAB
  439. GOPT0A:    CALL    NEWLINE        ; Do cr, lf on console
  440.      ENDIF            ; Opts and rpopt
  441.  
  442. ;    get left margin option
  443.  
  444. GOPT1:
  445.      IF    OPTS AND MGNOPT
  446.     LXI    H,MSG1C        ; Output left margin message
  447.     CALL    STRNGC        ;
  448.     CALL    DECINP        ; Get decimal number from user
  449.     MOV    A,H        ; And check range
  450.     ORA    A        ;
  451.     JNZ    PRHC2        ; Xfr - too big
  452.     MOV    A,L        ;
  453.     CPI    100        ;
  454.     JNC    PRHC2        ; Xfr - too big
  455.     STA    MARGIN        ; Save value
  456.     MOV    B,A        ; Temporarily save in B
  457.     LDA    EXPAND        ; Using expanded title?
  458.     ORA    A
  459.     JZ    PRHC1
  460.     RAR            ; If so, divide by 2
  461.     MOV    B,A        ; New value to B
  462. PRHC1:    LDA    PAGCOL        ; Get column for page
  463.     SUB    B        ; Adjust for indent
  464.     STA    PAGCOL        ; Now restore
  465.     CALL    NEWLINE        ; Do cr, lf on console
  466.     JMP    GOPT2
  467.  
  468. PRHC2:    MVI    A,BELL        ; Ring bell on error
  469.     CALL    COUT        ;
  470.     JMP    GOPT1        ; Go try again
  471.      ENDIF            ; Opts and mgnopt
  472.  
  473. ;    get form feed option
  474.  
  475. GOPT2:
  476.      IF    OPTS AND FFOPT
  477.     LXI    H,MSG1D        ; Output form feed message
  478.     CALL    STRNGC        ;
  479.     CALL    INPUT        ; Get user's reply
  480.     ANI    5FH        ; Force upper case
  481.     CPI    'Y'        ; And check for 'yes'
  482.     JNZ    GOPT2A        ; Xfr - not 'yes' - assume 'no'
  483.     STA    FRMFD        ; Set form feed switch
  484. GOPT2A:    CALL    NEWLINE        ; Do cr, lf on console
  485.      ENDIF            ; Opts and ffdopt
  486.  
  487. GOPT3:
  488.      IF    OPTS AND CMPOPT
  489.     LDA    FLAG        ; Check for 'o' option
  490.     CPI    'O'        ;
  491.     JNZ    GOPT4        ; Xfr - not 'o' option
  492.     LXI    H,MSG1H        ; Output compressed print message
  493.     CALL    STRNGC
  494.     CALL    INPUT        ; Get user's reply
  495.     ANI    5FH        ; Force upper case
  496.     CPI    'Y'        ; And check for 'yes'
  497.     JNZ    GOPT3A        ; Xfr - not 'yes' - assume 'no'
  498.     STA    COMPRS        ; Set compressed print flag
  499.     MVI    A,CWIDTH    ; Get width for compressed
  500.     STA    TTABN        ; Store it for tear tabs
  501.     MVI    A,CPGCOL    ; Get page number column for expanded
  502.     STA    PAGCOL        ; Store it
  503. GOPT3A:    CALL    NEWLINE        ; Do cr, lf on console
  504.      ENDIF            ; Opts and cmpopt
  505.  
  506. GOPT4:
  507.      IF    OPTS AND EXPOPT
  508.     LDA    FLAG        ; Check for 'o' option
  509.     CPI    'O'        ;
  510.     JNZ    GOPT5        ; Xfr - not 'o' option
  511.     LXI    H,MSG1J        ; Output expanded title message
  512.     CALL    STRNGC
  513.     CALL    INPUT        ; Get user's reply
  514.     ANI    5FH        ; Force upper case
  515.     CPI    'Y'        ; And check for 'yes'
  516.     JNZ    GOPT4A        ; Xfr - not 'yes' - assume 'no'
  517.     STA    EXPAND        ; Set form feed switch
  518. GOPT4A:    CALL    NEWLINE        ; Do cr, lf on console
  519.      ENDIF            ; Opts and expopt
  520.  
  521. ;    get heading option
  522.  
  523. GOPT5:
  524.      IF    OPTS AND HDGOPT
  525.     LDA    FLEN        ; Get length of filename in header
  526.     ADI    3        ; Extra blanks
  527.     MOV    B,A        ; Store in B
  528.     LDA    EXPAND        ; Expanded header?
  529.     ORA    A
  530.     JZ    GOPT5A        ; If not, skip
  531.     MOV    A,B        ; Else, get length of filename + blanks
  532.     RLC            ; Double it
  533.     MOV    B,A        ; Store it again
  534. GOPT5A:    LDA    MARGIN        ; Get number of indent spaces
  535.     ADD    B        ; Add 'em
  536.     MOV    B,A        ; Put it back
  537.     LDA    PAGCOL        ; Get start column for page number
  538.     SUB    B        ; Calculate max length available for header
  539.     MOV    B,A        ; Save it
  540.     LDA    EXPAND        ; Expanded header
  541.     ORA    A
  542.     JZ    GOPT5B        ; If not, skip
  543.     MOV    A,B        ; Else, get available length
  544.     RRC            ; Divide by 2
  545.     MOV    B,A        ; Put it back
  546.     STA    HLEN        ; Store for later
  547. GOPT5B:    CALL    CONV        ; Convert to BCD for printing
  548.     LXI    H,MSG1E+24    ; Point to # of chars in header
  549.     MOV    A,D        ; Get first digit
  550.     ADI    '0'        ; Add ASCII bias
  551.     MOV    M,A        ; Insert it into message
  552.     INX    H        ; Point next
  553.     MOV    A,E        ; Get last 2 digits
  554.     ANI    0F0H        ; Mask off low nibble
  555.     RRC            ; Move to low nibble
  556.     RRC
  557.     RRC
  558.     RRC
  559.     ADI    '0'        ; Add ASCII bias
  560.     MOV    M,A        ; Into message
  561.     INX    H        ; Point next
  562.     MOV    A,E        ; Get digits again
  563.     ANI    0FH        ; Mask off high nibble
  564.     ADI    '0'        ; ASCII bias
  565.     MOV    M,A        ; Last one
  566.     LXI    H,MSG1E        ; Output heading message
  567.     CALL    STRNGC
  568.     LDA    HLEN        ; Get max length of input
  569.     CALL    GETSTR        ; Get input from console
  570.     ORA    A        ; Check for no input
  571.     JZ    GOPT5C        ; Xfr - no input
  572.     MOV    C,A        ; Move input count to C for move
  573.     LXI    D,HEAD2        ; And get pointer to destination
  574.     CALL    STORE        ; Move input to heading buffer
  575.     DCX    D        ; Point to last char in heading buffer
  576.     LDAX    D        ; Get it
  577.     ORI    80H        ; Set high bit for printer output routine
  578.     STAX    D        ; Put it back
  579. GOPT5C:    CALL    NEWLINE        ; Do cr, lf on console
  580.      ENDIF            ; Opts and hdgopt
  581.  
  582. ;    get start and stop page
  583.  
  584. GOPT6:
  585.      IF    OPTS AND SSPGOPT
  586.     LXI    H,MSG1F        ; Output start page message
  587.     CALL    STRNGC        ;
  588.     MVI    A,4        ; Get max length of input
  589.     CALL    GETSTR        ; Get input data from console
  590.     ORA    A        ; Check for no input
  591.     JZ    GOPT6A        ; Return - no input
  592.     MOV    C,A        ; Move input count to c for move
  593.     LXI    D,PAGES+2    ; And get destination ptr
  594.     CALL    STORE        ; Move input to page number
  595. GOPT6A:    CALL    NEWLINE        ; Do cr, lf on console
  596.  
  597. ;    get stop page
  598.  
  599. GOPT7:    LXI    H,MSG1G        ; Output stop page message
  600.     CALL    STRNGC        ;
  601.     MVI    A,4        ; Get max length of input
  602.     CALL    GETSTR        ; Get input data
  603.     ORA    A        ; Check for no input
  604.     JZ    GOPT7A        ; Return - no input
  605.     MOV    C,A        ; Move input count to c for move
  606.     LXI    D,PAGEQ+2    ; And destination pointer
  607.     CALL    STORE        ; Move input to quit page number
  608. GOPT7A:    CALL    NEWLINE        ; Do cr, lf on console
  609.      ENDIF            ; Opts and ssgopt
  610.  
  611. ; check for squeezed file
  612.  
  613. CHKSQ:    CALL    NEWPG        ; Begin on a new page
  614.     LXI    D,FCB        ; Read 1st record in random mode
  615.     MVI    C,21H        ; Cp/m 'read random' code
  616.     CALL    BDOS        ;
  617.     LDA    80H        ; Fetch 1st byte of file and
  618.     CPI    76H        ; Check for 'squeezed' signature
  619.     JNZ    MAIN        ; Xfr - not 'squeezed'
  620.     LDA    81H        ; Now check 2nd byte for
  621.     CPI    0FFH        ; 'squeezed' signature
  622.     JNZ    MAIN        ; Xfr - not 'squeezed'
  623.     LHLD    MEMRY        ; Compute address of table
  624.     LXI    D,128        ;
  625.     DAD    D        ;
  626.     PUSH    H        ; And move it to bc for uinit
  627.     POP    B        ;
  628.     LHLD    BUFADR        ; Get address of usq buffer to hl
  629.     LDA    CCP        ; Get msb of ccp adr as end of buffer
  630.     MOV    D,A        ; And put in d for uinit
  631.     CALL    UINIT        ; Initialize unsqueeze routine
  632.     CALL    USQ        ; Now unsqueeze and print it
  633.     CALL    BUFULL        ; Output final buffer full
  634.     JMP    ROLL
  635.  
  636. MAIN:    CALL    GETCH        ; Get a byte from the file
  637.     CPI    EOF        ; Was if eof?
  638.     JZ    ROLL        ; Xfr - end of file
  639.     CALL    PCHR        ; Output the byte
  640.     JMP    MAIN
  641.  
  642. ; main print loop for squeezed files
  643.  
  644. BUFULL:    PUSH    H        ; Save all registers for usq
  645.     PUSH    D        ;
  646.     PUSH    B        ;
  647.     PUSH    PSW        ;
  648.     LHLD    BUFADR        ; Initialize buffer ptr
  649.  
  650. BUFLP:    MOV    A,M        ; Get byte from buffer
  651.     CPI    EOF        ; And check for eof
  652.     JZ    BUFEX        ; Xfr - got eof - prepare to return
  653.     PUSH    H        ; Save buffer ptr
  654.     CALL    PCHR        ; Ouptut byte
  655.     POP    H        ; Restore buffer ptr and
  656.     INX    H        ; Incr to next byte
  657.     LDA    CCP        ; Check for end of buffer
  658.     CMP    H        ;
  659.     JNZ    BUFLP        ; Xfr - not at end of buffer yet
  660.  
  661. BUFEX:    POP    PSW        ; Restore usq's registers
  662.     POP    B        ;
  663.     POP    D        ;
  664.     POP    H        ;
  665.     RET
  666.  
  667. ;    error routine for usq
  668.  
  669. EREXT:    CALL    PRINT
  670.     DB    CR,LF,' Unsqueeze error ',BELL,CR,LF+80H
  671.     JMP    0
  672.  
  673. ;    routine to output characters for both types of input file
  674.  
  675. PCHR:    CPI    ' '        ; Check for control chars
  676.     JC    PCH4        ; Xfr - got control char
  677.  
  678. PCH3:    CALL    WRITE2        ; Output char to con and lst
  679.     XRA    A        ; Set zero for return
  680.     STA    PAGIND        ; And turn off top of page indic.
  681.     RET
  682.  
  683. PCH4:    CPI    CR        ; Check for cr
  684.     JZ    PCH5        ; Xfr - got cr
  685.     CPI    FFD        ; Check for form feed
  686.     JZ    PCH6        ; Xfr - got form feed
  687.     CPI    LF        ; Check for line feed
  688.     JZ    PCH7        ; Xfr got line feed
  689.     CPI    TAB        ; Check for tab
  690.     JZ    PCH8        ; Xfr got tab
  691.     JMP    PCH9
  692.  
  693. ; handle 'cr' char.
  694.  
  695. PCH5:    LDA    PAGIND        ; Skip cr at top of new page
  696.     ORA    A        ;
  697.     RNZ            ; Xfr - at top
  698.     CALL    ABORT        ; Check for operator abort
  699.     MVI    A,CR        ; Output a cr to con and lst
  700.     JMP    PCH3
  701.  
  702. ; handle form feed char.
  703.  
  704. PCH6:    LDA    PAGIND        ; Skip form feeds at top of new page
  705.     ORA    A        ;
  706.     RNZ            ; Return - at top
  707.     CALL    ABORT        ; Check for operator abort
  708.     LDA    FRMFD        ; Check for normal form feed wanted
  709.     ORA    A        ;
  710.     RZ            ; Return - ignore form feeds
  711.     JMP    PCH71        ; Go do new page
  712.  
  713. ; handle 'lf' chars.
  714.  
  715. PCH7:    LDA    PAGIND        ; Skip line feeds at top of new page
  716.     ORA    A        ;
  717.     RNZ            ; Return - at top
  718.     LDA    LCNT        ; Incr line count
  719.     INR    A        ;
  720.     STA    LCNT        ; And store updated value
  721.     CPI    TEXT        ; Check for max lines per page
  722.     JNC    PCH71        ; Xfr - max exceeded
  723.     MVI    A,LF        ; Output a line feed to con and lst
  724.     CALL    WRITE3        ;
  725.     CALL    INDENT        ; Do left margin indent
  726.     XRA    A        ; Set zero for return
  727.     RET
  728.  
  729. ;    'lf'  and lines/page exceeded so start a new page
  730.  
  731. PCH71:    CALL    ABORT        ; Check for operator abort
  732.     PUSH    PSW        ; Save byte
  733.     CALL    TTABS        ; Output 'tear tabs' if wanted
  734.     CALL    NMBR        ; Incr page number
  735.     CALL    CKSP        ; Check for 'end page'
  736.     CALL    INDENT        ; Do left margin
  737.     LDA    EXPAND        ; Expanded print for title?
  738.     ORA    A
  739.     JZ    PCH72        ; If not, carry on
  740.     LXI    H,EXPON        ; Else, set printer to expanded print
  741.     CALL    STRNGP
  742. PCH72:    LXI    H,HEAD1        ; Output page heading to con and lst
  743.     CALL    STRNGB
  744.     CALL    PAGNO        ; Output page number to con and lst
  745.     LDA    EXPAND        ; Were we expanded?
  746.     ORA    A
  747.     JZ    PCH73
  748.     LXI    H,EXPOF        ; If so, printer back to normal
  749.     CALL    STRNGP
  750. PCH73:    CALL    NEWPG        ; Initial for new page
  751.     POP    PSW        ; Restore original byte
  752.     RET
  753.  
  754. ; handle tab characters
  755.  
  756. PCH8:    PUSH    B        ; Create some work space
  757.     LDA    (MARGIN)    ; Get margin offset
  758.     MOV    B,A        ; Save in B
  759. PCH81:    MVI    A,' '        ; Output blanks to next mod 8 column
  760.     CALL    WRITE2        ; To con and lst
  761.     LDA    COLMN        ; Check for mod 8 column
  762.     SUB    B        ; Margin spaces don't count
  763.     ANI    7        ;
  764.     JNZ    PCH81        ; Xfr - not mod 8 yet
  765.     XRA    A        ; Set zero for return
  766.     POP    B        ; Restore BC
  767.     RET
  768.  
  769. ; display control-characters
  770.  
  771. PCH9:    PUSH    PSW        ; Save byte
  772.     MVI    A,'^'        ; Output a '^' as control indicator
  773.     CALL    WRITE2        ; To con and lst
  774.     POP    PSW        ; Restore byte
  775.     ADI    40H        ; And shift to alphabetic
  776.     CALL    WRITE2        ; And output to con and lst
  777.     RET
  778.  
  779. ;-----> getstr    get a string from the console.    uses BDOS bufferd console
  780. ;        input and the BDOS default i/o buffer [80h].
  781. ;        max. length of input in a
  782.  
  783. GETSTR:    STA    TBUFF        ; Store max length in buffer for bdos
  784.     LXI    D,TBUFF        ; Get ptr to buffer for bdos
  785.     MVI    C,0AH        ; Cp/m 'buffered console input' code
  786.     CALL    BDOS        ;
  787.     LDA    TBUFF+1        ; Get count of input chars
  788.     LXI    H,TBUFF+2    ; Get pointer to input data
  789.     RET
  790.  
  791. ;-----< getstr
  792.  
  793. ;-----> decinp    get decimal input from console and convert to binary
  794. ;        binary value returned in hl.  max 5 char input
  795. ;        destroys b and de.
  796.  
  797. DECINP:    MVI    A,6        ; Get max length of input
  798.     CALL    GETSTR        ; Get input from console
  799.     XCHG            ; Input data ptr to de
  800.     LXI    H,0        ; Initialize result to zero
  801.     ORA    A        ; Check for no input
  802.     RZ            ; Return - nothing input
  803.     MOV    B,A        ; Move count to b
  804. DI1:    LDAX    D        ; Get input byte,
  805.     INX    D        ; Decr pointer,
  806.     PUSH    D        ; And save pointer
  807.     SUI    '0'        ; Convert char to binary
  808.     JC    DI2        ; Xfr - char not numeric - ignore
  809.     CPI    10        ; Check other end of numeric range
  810.     JNC    DI2        ; Xfr - char not numeric - ignore
  811.     DAD    H        ; Multiply accumulated result by ten
  812.     PUSH    H        ; [ 8 x result + 2 x result]
  813.     DAD    H        ;
  814.     DAD    H        ;
  815.     POP    D        ; Restore 2 x result value
  816.     DAD    D        ;
  817.     ORA    A        ; Add current digit to result
  818.     ADD    L        ;
  819.     MOV    L,A        ;
  820.     MVI    A,0        ;
  821.     ADD    H        ;
  822.     MOV    H,A        ;
  823. DI2:    POP    D        ; Restore pointer to ascii input
  824.     DCR    B        ; Decr input count
  825.     JNZ    DI1        ; Xfr - not through
  826.     RET
  827.  
  828. ;    console buffer for decinp
  829.  
  830. TEMP:    DB    5        ; Buffer length [5 bytes]
  831.     DB    0        ; Input count [set by bdos]
  832.     DB    0,0,0,0,0    ; Actual buffer
  833.  
  834. ;-----> conv    convert hex number in B to BCD in DE
  835. ;        destroys B and DE
  836.  
  837. CONV:    LXI    D,0        ; Ready to receive number
  838.     MOV    A,B        ; Hex number now in A
  839.     SUI    100
  840.     JC    CONV1
  841.     INR    D
  842.     MOV    B,A
  843.     JMP    CONV+3
  844. CONV1:    MOV    A,B
  845.     SUI    10
  846.     JC    CONV2
  847.     INR    E
  848.     MOV    B,A
  849.     JMP    CONV1+1
  850. CONV2:    MOV    A,E
  851.     RLC
  852.     RLC
  853.     RLC
  854.     RLC
  855.     ORA    B
  856.     MOV    E,A
  857.     RET
  858.  
  859. ;-----> abort    check for operator abort - ctl-c or ctl-x
  860.  
  861. ABORT:    MVI    C,STATUS    ; Check console status
  862.     CALL    BDOS        ;
  863.     RAR            ; Check for data present
  864.     RNC            ; Return - no data input
  865.     MVI    C,CONIN        ; Read con
  866.     CALL    BDOS        ;
  867.     CPI    CTLC        ; Check for control-c
  868.     JZ    ABORT1        ; Xfr - got ctl-c - abort program
  869.     CPI    CTLX        ; Check for control-x
  870.     JNZ    ABORT        ; Xfr - not ctl-x - ignore input
  871.  
  872. ABORT1:    LDA    NOTAB        ; Check for 'tear tabs' wanted
  873.     ORA    A        ;
  874.     JZ    EXIT        ; Xfr - no - return to cp/m
  875.  
  876. ;    add 'tear tabs' for roll paper
  877.  
  878.     LXI    H,TURNUP    ; Print 10 blank lines
  879.     CALL    STRNGP        ;
  880.     LXI    H,QUITR-7    ; Print 6 blank lines
  881.     CALL    STRNGP        ;
  882.     JMP    EXIT        ; Return to ccp - no warm boot
  883.  
  884. ABORT2:    LXI    H,QUITR-3    ; Print 2 blank lines
  885.     CALL    STRNGC        ;
  886.     JMP    EXIT        ; Return to ccp - no warm boot
  887.  
  888. ; check to see if ready to stop printing yet
  889.  
  890. CKSP:    PUSH    H
  891.     PUSH    D
  892.     PUSH    B
  893.     LXI    H,PAGEQ+2
  894.  
  895. CKSP1:    INX    H
  896.     MOV    A,M
  897.     CPI    ' '
  898.     JNZ    CKSP1
  899.     DCX    H
  900.     LXI    D,HEAD4+2
  901.     MVI    C,PAGENM
  902.  
  903. CKSP2:    LDAX    D
  904.     CMP    M
  905.     JNZ    CKSP3
  906.     DCX    D
  907.     DCX    H
  908.     DCR    C
  909.     JNZ    CKSP2
  910.     JMP    ABORT1
  911.  
  912. CKSP3:    POP    B
  913.     POP    D
  914.     POP    H
  915.     RET
  916.  
  917. ; check to see if ready to start printing yet
  918.  
  919. CKST:    PUSH    H
  920.     PUSH    D
  921.     PUSH    B
  922.     LXI    H,PAGES+2
  923.  
  924. CKST1:    INX    H
  925.     MOV    A,M
  926.     CPI    ' '
  927.     JNZ    CKST1
  928.     DCX    H
  929.     LXI    D,HEAD4+2
  930.     MVI    C,PAGENM
  931.  
  932. CKST2:    LDAX    D
  933.     CMP    M
  934.     JNZ    CKST4
  935.     DCX    D
  936.     DCX    H
  937.     DCR    C
  938.     JNZ    CKST2
  939.     STA    START
  940.     MVI    A,CR
  941.     CALL    WRITEP
  942.     LDA    NOTAB
  943.     ORA    A
  944.     CNZ    TTABS
  945.     LDA    COMPRS        ; Test for compressed print
  946.     ORA    A
  947.     JZ    NOCOMP
  948.     LXI    H,CMPON        ; Set printer to compress print
  949.     CALL    STRNGP
  950. NOCOMP:    CALL    INDENT
  951.     LDA    EXPAND        ; Test for expanded print in title
  952.     ORA    A
  953.     JZ    CKST3
  954.     LXI    H,EXPON        ; Expanded print for title
  955.     CALL    STRNGP
  956.  
  957. CKST3:    LXI    H,HEAD1
  958.     CALL    STRNGB
  959.     CALL    PAGNO
  960.     LDA    EXPAND        ; Test for expanded print in title
  961.     ORA    A
  962.     JZ    CKST4
  963.     LXI    H,EXPOF        ; Now turn off expanded print
  964.     CALL    STRNGP
  965.  
  966. CKST4:    POP    B
  967.     POP    D
  968.     POP    H
  969.     RET
  970.  
  971. ; see if anything already in the buffer
  972.  
  973. DISK1:    LHLD    FILELEN
  974.     XCHG
  975.     LHLD    FILEPTR
  976.     MOV    A,L
  977.     SUB    E
  978.     MOV    A,H
  979.     SBB    D
  980.     JC    DISK5
  981.  
  982. ; if empty, fill buffer
  983.  
  984.     LXI    H,0
  985.     SHLD    FILEPTR
  986.  
  987. ; get next disk sector, check for end-of-file marker
  988.  
  989. DISK2:    XCHG
  990.     LHLD    FILELEN
  991.     MOV    A,E
  992.     SUB    L
  993.     MOV    A,D
  994.     SBB    H
  995.     JNC    DISK4
  996.  
  997. ; otherwise get next sector
  998.  
  999.     LHLD    FILEADR
  1000.     DAD    D
  1001.     XCHG
  1002.     MVI    C,26
  1003.     CALL    BDOS
  1004.     LXI    D,FCB
  1005.     MVI    C,20
  1006.     CALL    BDOS
  1007.     ORA    A
  1008.     JNZ    DISK3
  1009.     LXI    D,TBUFF
  1010.     LHLD    FILEPTR
  1011.     DAD    D
  1012.     SHLD    FILEPTR
  1013.     JMP    DISK2
  1014.  
  1015. ; reset for end-of-file marker location
  1016.  
  1017. DISK3:    LHLD    FILEPTR
  1018.     SHLD    FILELEN
  1019.  
  1020. ; set for buffer full
  1021.  
  1022. DISK4:    LXI    D,TBUFF
  1023.     MVI    C,26
  1024.     CALL    BDOS
  1025.     LXI    H,0
  1026.     SHLD    FILEPTR
  1027.  
  1028. ; get the next character from the buffer
  1029.  
  1030. DISK5:    XCHG
  1031.     LHLD    FILEADR
  1032.     DAD    D
  1033.     XCHG
  1034.     LHLD    FILELEN
  1035.     MOV    A,L
  1036.     ORA    H
  1037.     MVI    A,EOF
  1038.     RZ
  1039.     LDAX    D
  1040.     LHLD    FILEPTR
  1041.     INX    H
  1042.     SHLD    FILEPTR
  1043.     RET
  1044.  
  1045. ; exit if having a problem opening a file
  1046.  
  1047. ERROR:    CALL    STRNGC
  1048.     JMP    EXIT
  1049.  
  1050. ERRORR:    LXI    H,MERRR
  1051.     JMP    ERROR
  1052.  
  1053. ERRORN:    LXI    H,MERRN
  1054.     JMP    ERROR
  1055.  
  1056. ERRORW:    LXI    H,MERRW
  1057.     JMP    ERROR
  1058.  
  1059. ;    exit routine
  1060.  
  1061. EXIT:    XRA    A
  1062.     LDA    COMPRS        ; See if printer was in compressed mode
  1063.     ORA    A
  1064.     JZ    EXIT1
  1065.     LXI    H,CMPOF        ; Restore printer to normal print
  1066.     CALL    STRNGP
  1067. EXIT1:    LHLD    SAVSTK
  1068.     SPHL
  1069.     JMP    0
  1070.  
  1071. ; ouptut a cr, lf pair to the console
  1072.  
  1073. NEWLINE:LXI    H,MSG3        ; Get pointer to cr, lf
  1074.     CALL    STRNGC        ; Now output it
  1075.     RET
  1076.  
  1077. ; get a character from the buffer
  1078.  
  1079. GETCH:    CALL    DISK1
  1080.     ANI    7FH
  1081.     RET
  1082.  
  1083. ; indent for new left margin, if requested
  1084.  
  1085. INDENT:    PUSH    PSW
  1086.     PUSH    B        ; Save user's bc
  1087.     LDA    MARGIN        ; Get count of margin chars
  1088.     INR    A        ; And compensate for test before use
  1089.     MOV    B,A        ; And move to b
  1090. ID1:    DCR    B        ; Decr margin count
  1091.     JZ    IDEX        ; Xfr - through
  1092.     MVI    A,' '        ; Output a blank
  1093.     CALL    WRITEP        ;
  1094.     JMP    ID1        ; Go do next
  1095. IDEX:    LDA    MARGIN        ; Compensate for margin in other calculations
  1096.     STA    COLMN
  1097.     POP    B        ; Restore user's BC
  1098.     POP    PSW
  1099.     RET
  1100.  
  1101. ; get a character from the keyboard
  1102.  
  1103. INPUT:    PUSH    H
  1104.     PUSH    B
  1105.     MVI    C,CONIN
  1106.     CALL    BDOS
  1107.     ANI    7FH
  1108.     POP    B
  1109.     POP    H
  1110.     CPI    CTLC
  1111.     JZ    ABORT2
  1112.     CPI    CTLX
  1113.     JZ    ABORT2
  1114.     RET
  1115.  
  1116. ; set parameters for a new page
  1117.  
  1118. NEWPG:    XRA    A        ; Zero-set line count and
  1119.     STA    LCNT        ; Print column
  1120.     STA    COLMN        ;
  1121.     MVI    A,0FFH        ; Turn on new page indicator
  1122.     STA    PAGIND        ;
  1123.     LDA    START
  1124.     ORA    A
  1125.     CZ    CKST
  1126.     JMP    INDENT
  1127.  
  1128. ; increment the page number for hard copy
  1129.  
  1130. NMBR:    LXI    H,HEAD4+2
  1131.     MVI    C,PAGENM
  1132.  
  1133. NMBR1:    MOV    A,M
  1134.     CPI    ' '
  1135.     JZ    NMBR2
  1136.     CPI    SI
  1137.     JNZ    NMBR3
  1138.  
  1139. NMBR2:    MVI    A,'0'
  1140.  
  1141. NMBR3:    INR    A
  1142.     MOV    M,A
  1143.     CPI    '9'+1
  1144.     JNZ    NMBR4
  1145.     MVI    M,'0'
  1146.     DCX    H
  1147.     DCR    C
  1148.     JNZ    NMBR1
  1149.  
  1150. NMBR4:    RET
  1151.  
  1152. ; if no print, tell what maximum page was
  1153.  
  1154. NOPNT:    LXI    H,MSG3
  1155.     CALL    STRNGC
  1156.     LXI    H,MSG2
  1157.     CALL    STRNGC
  1158.     LXI    H,HEAD4
  1159.     CALL    STRNGC
  1160.     JMP    EXIT
  1161.  
  1162. ; to start a new page
  1163.  
  1164. NUPAGE:    LXI    H,TURNUP
  1165.     JMP    STRNGB
  1166.  
  1167. ; display and print the page number
  1168.  
  1169. PAGNO:    LDA    PAGCOL
  1170.     MOV    B,A
  1171.     LDA    EXPAND        ; See if expanded print is wanted
  1172.     ORA    A
  1173.     JZ    PAGNO1        ; If no, carry on
  1174.     MOV    A,B        ; Else, divide page # column
  1175.     RAR            ;   by 2
  1176.     MOV    B,A
  1177. PAGNO1:    MVI    A,' '
  1178.     CALL    WRITE2
  1179.     LDA    COLMN
  1180.     ADI    1
  1181.     SUB    B
  1182.     JC    PAGNO1
  1183.     LXI    H,HEAD3
  1184.     JMP    STRNGB
  1185.  
  1186. ; roll up page to terminate
  1187.  
  1188. ROLL:    LDA    START
  1189.     ORA    A
  1190.     JZ    NOPNT
  1191.     MVI    A,CR
  1192.     CALL    WRITEP
  1193.  
  1194. ROLL1:    LDA    LCNT
  1195.     INR    A
  1196.     STA    LCNT
  1197.     CPI    TEXT
  1198.     JNC    ROLL2
  1199.     MVI    A,LF
  1200.     CALL    WRITEP
  1201.     JMP    ROLL1
  1202.  
  1203. ROLL2:    CALL    TTABS
  1204.     LDA    NOTAB
  1205.     ORA    A
  1206.     JZ    EXIT
  1207.     LXI    H,QUIT
  1208.     CALL    STRNGP
  1209.     JMP    EXIT
  1210.  
  1211. ; ignore cr, lf, ffd or eof at top of any new page
  1212.  
  1213. SKIP:    CALL    GETCH
  1214.     CPI    CR
  1215.     JZ    SKIP
  1216.     CPI    LF
  1217.     JZ    SKIP
  1218.     CPI    EOF
  1219.     JZ    ROLL
  1220.     CPI    FFD
  1221.     JZ    SKIP
  1222.     RET
  1223.  
  1224. ; transfer a string of chars. from one area to another
  1225.  
  1226. STORE:    MOV    A,M
  1227.     STAX    D
  1228.     INX    H
  1229.     INX    D
  1230.     DCR    C
  1231.     JNZ    STORE
  1232.     RET
  1233.  
  1234. ; print and display a string of characters
  1235.  
  1236. STRNGB:    MOV    A,M
  1237.     PUSH    PSW        ; Save for later
  1238.     ANI    7FH        ; Remove any high bits
  1239.     CALL    WRITE2
  1240.     POP    PSW        ; Now restore
  1241.     RLC            ; Test for high bit set
  1242.     RC            ; If so, all done
  1243.     INX    H        ; Else, continue
  1244.     JMP    STRNGB
  1245.  
  1246. ; write ascii string to crt only
  1247.  
  1248. STRNGC:    MOV    A,M
  1249.     PUSH    PSW        ; Save for later
  1250.     ANI    7FH        ; Remove any high bits
  1251.     CALL    COUT
  1252.     POP    PSW        ; Now restore
  1253.     RLC            ; Test for high bit set
  1254.     RC            ; If so, all done
  1255.     INX    H
  1256.     JMP    STRNGC
  1257.  
  1258. ; print an in-line message
  1259.  
  1260. PRINT:    XTHL            ; Retrieve message address from stack
  1261.     CALL    STRNGC        ; Print string
  1262.     INX    H        ; Incr past terminator
  1263.     XTHL            ; Restore return address to stack
  1264.     RET
  1265.  
  1266. ; print a string of characters
  1267.  
  1268. STRNGP:    MOV    A,M
  1269.     PUSH    PSW        ; Save for later
  1270.     ANI    7FH        ; Remove any high bits
  1271.     CALL    WRITEP
  1272.     POP    PSW        ; Now restore
  1273.     RLC            ; Test for high bit set
  1274.     RC            ; If so, all done
  1275.     INX    H        ; Else, continue
  1276.     JMP    STRNGP
  1277.  
  1278. ; adds tear tabs for roll paper
  1279.  
  1280. TTABS:    LDA    NOTAB
  1281.     ORA    A
  1282.     JZ    NUPAGE
  1283.     LXI    H,QUITR
  1284.     CALL    STRNGB
  1285.     MVI    A,'-'
  1286.     CALL    WRITE3
  1287.     LDA    TTABN
  1288.     MOV    B,A
  1289.  
  1290. TTABS1:    MVI    A,' '
  1291.     CALL    WRITE3
  1292.     DCR    B
  1293.     JNZ    TTABS1
  1294.     MVI    A,'-'
  1295.     CALL    WRITE2
  1296.     LXI    H,QUITR
  1297.     CALL    STRNGB
  1298.     XRA    A
  1299.     STA    COLMN
  1300.     RET
  1301.  
  1302. ; write char. to crt
  1303.  
  1304. WRITE2:    CPI    SI
  1305.     RZ
  1306.     CPI    CR
  1307.     JZ    WRITE3
  1308.     CPI    LF
  1309.     JZ    WRITE3
  1310.     PUSH    PSW
  1311.     LDA    COLMN
  1312.     INR    A
  1313.     STA    COLMN
  1314.     POP    PSW
  1315.  
  1316. WRITE3:    CALL    WRITEC
  1317.  
  1318. ; write char. to printer
  1319.  
  1320. WRITE1:    CALL    WRITEP
  1321.     RET
  1322.  
  1323. ; write ascii character to crt
  1324.  
  1325. WRITEC:    MOV    E,A
  1326.     LDA    START
  1327.     ORA    A
  1328.     MOV    A,E
  1329.     RZ
  1330.  
  1331. COUT:    PUSH    H
  1332.     PUSH    D
  1333.     PUSH    B
  1334.     PUSH    PSW
  1335.     MOV    E,A
  1336.     MVI    C,CONOUT
  1337.     CALL    BDOS
  1338.     POP    PSW
  1339.     POP    B
  1340.     POP    D
  1341.     POP    H
  1342.     RET
  1343.  
  1344. ; write ascii character to printer
  1345.  
  1346. WRITEP:    CPI    SI
  1347.     RZ
  1348.     MOV    E,A
  1349.     LDA    FLAG
  1350.     CPI    'S'
  1351.     RZ
  1352.     LDA    START
  1353.     ORA    A
  1354.     RZ
  1355.     PUSH    H
  1356.     PUSH    B
  1357.     MVI    C,LIST
  1358.     CALL    BDOS
  1359.     POP    B
  1360.     POP    H
  1361.     RET
  1362.  
  1363. DLE    EQU    090H
  1364.  
  1365. ;-----> uinit    initialize the unsqueeze routine with values from the
  1366. ;        user; hl = address of usq buffer, de = adr of top of buffer,
  1367. ;        bc = adr of 1032 byte table
  1368.  
  1369. UINIT:    SHLD    BUFF        ; Store buffer address
  1370.     SHLD    NEXTADR        ;
  1371.     MOV    A,D        ; Store high order byte of top adr
  1372.     STA    TOPRAM        ;
  1373.     PUSH    B        ; Store adr of table
  1374.     POP    H        ;
  1375.     SHLD    TABLE        ;
  1376.     RET
  1377.  
  1378. ;-----< uinit
  1379.  
  1380. ;this is start of baseline usq code
  1381.  
  1382. USQ:    XRA    A        ; Force init char read
  1383.     STA    NUMLFT
  1384.     STA    RCNT        ; And zero repeats
  1385.     LHLD    LASTMEM
  1386.     SHLD    SOB
  1387.     SHLD    EOB
  1388.     CALL    GETW
  1389. USQ1:    CALL    GETW        ; Get cksum, and store
  1390.     SHLD    FILECRC
  1391. USQ2:    CALL    GET1
  1392.     JNZ    EREXT
  1393.     ORA    A
  1394.     JNZ    USQ2
  1395. USQ3A:    CALL    GETW
  1396.     SHLD    NUMVALS
  1397.     LXI    D,258
  1398.     CALL    CMPDEHL
  1399.     JC    USQ3B
  1400.     CALL    ERREXT
  1401.     DB    CR,LF,' File has illegal decode size. Aborting. '
  1402.     DB    BELL,CR,LF+80H
  1403.  
  1404. USQ3B:    XCHG
  1405.     LHLD    TABLE
  1406.     XCHG
  1407. USQ4:    SHLD    MAX
  1408.     MOV    A,H
  1409.     ORA    L
  1410.     JZ    USQ5
  1411.     PUSH    D
  1412.     CALL    GETW
  1413.     POP    D
  1414.     XCHG
  1415.     MOV    M,E
  1416.     INX    H
  1417.     MOV    M,D
  1418.     INX    H
  1419.     PUSH    H
  1420.     CALL    GETW
  1421.     XCHG
  1422.     POP    H
  1423.     MOV    M,E
  1424.     INX    H
  1425.     MOV    M,D
  1426.     INX    H
  1427.     XCHG
  1428.     LHLD    MAX
  1429.     DCX    H
  1430.     JMP    USQ4
  1431.  
  1432. USQ5:    LXI    H,0
  1433. USQ6:    PUSH    H
  1434.     CALL    GETNXT
  1435.     POP    H
  1436.     JNZ    USQ8
  1437.     MOV    E,A
  1438.     MVI    D,0
  1439.     DAD    D
  1440.     PUSH    H
  1441.     PUSH    PSW
  1442.     LHLD    NEXTADR        ; Point to load address
  1443.     LDA    TOPRAM        ; Check against end page of tpa
  1444.     CMP    H        ; If at same page, yes
  1445.     JNZ    NOFULL        ; Buffer is not full yet
  1446.     CALL    BUFULL        ; Buffer full, process buffer
  1447.     LHLD    BUFF        ; Reset buffer pointer
  1448. NOFULL:    POP    PSW
  1449.     MOV    M,A
  1450.     INX    H
  1451.     SHLD    NEXTADR
  1452.     POP    H
  1453.     JMP    USQ6
  1454.  
  1455. USQ8:    XCHG
  1456.     LHLD    FILECRC
  1457.     CALL    CMPDEHL
  1458. USQ9:    RZ
  1459.     CALL    PRINT
  1460.     DB    CR,LF,' ERROR - Checksum error in file '
  1461.     DB    BELL+80H
  1462.     JMP    EREXT
  1463.  
  1464. ERREXT:    POP    H
  1465.     MOV    A,M
  1466.     ORA    A
  1467.     JZ    EREXT
  1468.     INX    H
  1469.     PUSH    H
  1470.     CALL    COUT
  1471.     JMP    ERREXT
  1472.  
  1473. CMPDEHL:MOV    A,H
  1474.     CMP    D
  1475.     RNZ
  1476.     MOV    A,L
  1477.     CMP    E
  1478.     RET
  1479.  
  1480. GET1:    LHLD    EOB
  1481.     XCHG
  1482.     LHLD    SOB
  1483.     CALL    CMPDEHL
  1484.     JZ    GET1R
  1485.     MOV    A,M
  1486.     INX    H
  1487.     SHLD    SOB
  1488.     CMP    A
  1489.     RET
  1490.  
  1491. GET1R:    LHLD    LASTMEM
  1492.     SHLD    SOB
  1493.     SHLD    EOB
  1494. GET1R1:    PUSH    H
  1495.     XCHG
  1496.     MVI    C,26
  1497.     CALL    BDOS
  1498.     LXI    D,FCB
  1499.     MVI    C,20
  1500.     CALL    BDOS
  1501.     POP    H
  1502.     ORA    A
  1503.     JNZ    GET1R2
  1504.     LXI    D,128
  1505.     DAD    D
  1506.     XCHG
  1507.     LHLD    ENDMEM
  1508.     CALL    CMPDEHL
  1509.     XCHG
  1510.     JNC    GET1R1
  1511. GET1R2:    SHLD    EOB
  1512.     XCHG
  1513.     LHLD    SOB
  1514.     CALL    CMPDEHL
  1515.     JNZ    GET1
  1516.     MVI    A,255
  1517.     ORA    A
  1518.     RET
  1519.  
  1520. GETW:    CALL    GET1
  1521.     JNZ    BADR
  1522.     PUSH    PSW
  1523.     CALL    GET1
  1524.     JNZ    BADR
  1525.     MOV    H,A
  1526.     POP    PSW
  1527.     MOV    L,A
  1528.     RET
  1529.  
  1530. BADR:    CALL    PRINT
  1531.     DB    CR,LF,'Premature EOF on file... aborted.'
  1532.     DB    BELL+80H
  1533.     JMP    0
  1534.  
  1535. GETNXT:    LDA    RCNT        ; See if in the middle of
  1536.     ORA    A        ; Repeat sequence...
  1537.     JZ    GETN7
  1538.     DCR    A
  1539.     STA    RCNT
  1540.     LDA    LAST
  1541.     CMP    A
  1542.     RET
  1543. GETN7:    CALL    GETN4
  1544.     CPI    DLE
  1545.     JNZ    GETN5
  1546.     CALL    GETN4
  1547.     ORA    A
  1548.     JNZ    GETN6
  1549.     MVI    A,DLE        ; Dle is encoded as dle,0
  1550.     CMP    A
  1551.     RET
  1552. GETN6:    DCR    A
  1553.     DCR    A
  1554.     STA    RCNT
  1555.     LDA    LAST
  1556.     CMP    A
  1557.     RET
  1558. GETN5:    STA    LAST
  1559.     CMP    A
  1560.     RET
  1561.  
  1562. GETN4:    LXI    D,0        ; Pointer @ sot
  1563.     LDA    CHAR
  1564.     MOV    C,A
  1565. GETN1:    LDA    NUMLFT
  1566.     ORA    A
  1567.     JNZ    GETN2
  1568.     PUSH    D
  1569.     CALL    GET1
  1570.     JNZ    BADR
  1571.     POP    D
  1572.     MOV    C,A
  1573.     MVI    A,8
  1574. GETN2:    DCR    A
  1575.     STA    NUMLFT
  1576.     MOV    A,C
  1577.     RRC
  1578.     MOV    C,A
  1579.     LHLD    TABLE
  1580.     JNC    GETN3
  1581.     INX    H
  1582.     INX    H        ; Add 2 to point to right node
  1583. GETN3:    DAD    D
  1584.     DAD    D
  1585.     DAD    D
  1586.     DAD    D        ; Ok.. pointing close to right plc..
  1587.     MOV    E,M
  1588.     INX    H
  1589.     MOV    D,M
  1590.     MOV    A,D
  1591.     ANI    128
  1592.     JZ    GETN1
  1593.     MOV    A,C
  1594.     STA    CHAR
  1595.     MOV    A,D
  1596.     CPI    254        ; Is special eof?
  1597.     MVI    A,EOF
  1598.     JZ    GETEOF        ; Yup
  1599.     MOV    A,E
  1600.     CMA
  1601.     CMP    A
  1602.     RET
  1603.  
  1604. GETEOF:    POP    H
  1605.     ORA    A
  1606.     RET
  1607.  
  1608. ;end of baseline usq code
  1609.  
  1610. LASTMEM:DW    80H
  1611. ENDMEM:    DW    80H+127
  1612. SOB:    DW    80H
  1613. EOB:    DW    80H
  1614.  
  1615. ;    the following values are initialized by uinit with values
  1616. ;    supplied by the user
  1617.  
  1618. BUFF:    DW    $-$
  1619. TOPRAM:    DB    0
  1620. TABLE:    DW    $-$
  1621. NEXTADR:DW    $-$
  1622. NUMLFT:    DS    1
  1623. RCNT:    DS    1
  1624. FILECRC:DS    2
  1625. LAST:    DS    1
  1626. CHAR:    DS    1
  1627. NUMVALS:DS    2
  1628. MAX:    DS    2
  1629. MEMRY:    DW    PRGEND
  1630. PRGEND    EQU    $
  1631.  
  1632.     END
  1633.