home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / programs / wstar / wsmulcop.lbr / WSMULCOP.ZQ0 / WSMULCOP.Z80
Text File  |  1985-11-24  |  14KB  |  473 lines

  1.     title    'WSMULCOP.Z80'
  2.     listw 95
  3. ;WSMULCOP.Z80
  4. ;A program to make unattended multiple printouts from WordStar
  5. ;  using EX15.COM, a public-domain substitute for SUBMIT.COM.
  6.  
  7. ;WSMULCOP.Z80   copyright 11-19-85 by    M. L. Halbert
  8. ;                    104 Morgan Road
  9. ;                    Oak Ridge, TN 37830
  10. ;
  11. ;        Permission granted for unlimited private use.
  12.  
  13. ;Usage:     A>WSMULCOP
  14. ;------
  15. ;WSMULCOP asks name of file to be printed and no. of copies desired
  16. ;  (up to 99 copies).                              
  17.  
  18. ;Method:  WSMULCOP.COM generates a disk file PR.SUB.  This file is
  19. ;-------    executed by EX15.COM.  PR.SUB consists of:
  20. ;
  21. ;        A:WS
  22. ;        p B:document.ext^[    (or other drivecode,
  23. ;        p B:document.ext^[     if specified)
  24. ;        . . . (n times)
  25. ;        Y PR.SUB
  26. ;
  27. ;    (EX15 converts ^[ to <ESC>, which tells WordStar to
  28. ;    use the defaults for its 6 questions for a P command.)
  29. ;
  30. ;    WSMULCOP.COM places a reference to PR.SUB in the command
  31. ;    tail buffer at 80h and moves part of itself to
  32. ;    high storage (2000H),well above the top of EX15.COM.
  33. ;    (EX15 later relocates itself as well, but that is of no
  34. ;    concern for WSMULCOP.COM.)  The moved segment of WSMULCOP.COM
  35. ;    then loads EX15.COM at 0100H and jumps there, thereby
  36. ;    starting EX15 in motion.  
  37. ;
  38. ;    After the n copies are printed, EX15 erases PR.SUB and
  39. ;    leaves the user at the Opening Menu in WordStar.
  40.  
  41. ;Restrictions:
  42. ;-------------
  43. ;Both WSMULCOP.COM and EX15.COM are assumed to be on A:.
  44. ;The default drivecode of the file to be printed is B:, but
  45. ;  any code may be prefixed to the filename.  Validity of the
  46. ;  drivecode and the existence of the file are not checked until
  47. ;  EX15 tries to execute PR.SUB.
  48.     
  49. ;Assembly:
  50. ;---------
  51. ;Written for the modified Crowe Z80 assembler as supplied by 
  52. ;  Micro Cornucopia on their Kaypro User Disk K-25, identified
  53. ;  as CROWE(JH/DC/JGO) Z80 1.3e.  Although the program is written
  54. ;  with Zilog Z80 mnemonics, only instructions common to the 8080
  55. ;  have been used.
  56. ;Making the .COM file may be accomplished as follows:
  57. ;  *****
  58.  
  59. ;Equates
  60. ;-------
  61. wboot    equ    0        ;start Warm Boot
  62. stsize    equ    20        ;stack size
  63. tpa    equ    100h        ;start of TPA
  64. tail    equ    80h        ;CCP puts command tail here
  65. bdos    equ    05h        ;jump to start of bdos
  66. dfcb    equ    05Ch        ;default file control block
  67. cr    equ    0Dh        ;carriage return
  68. lf    equ    0Ah        ;line feed
  69. ;Next two are for segment of code to be moved out of the way
  70. ;  so EX15.COM can be loaded.
  71. high    equ    2000h        ;well above top of EX15.COM
  72. lenth    equ    20h        ;length of segment to be moved
  73.  
  74.     org    tpa
  75.  
  76. ;Initialization.
  77. ;---------------
  78.     ld    sp,stack    ;set stack pointer
  79. ;Set up default fcb for pr.sub 
  80.     ld    hl,prsub    ;filename in fcb format
  81.     ld    de,dfcb        ;dest. is default fcb
  82.     ld    c,12        ;loop counter
  83.     call    copy
  84. ;Complete dfcb by inserting 24 nulls
  85.     ld    c,24
  86.     sub    a        ;clear 'a'
  87. loop0:    ld    (de),a        ;insert null character
  88.     inc    de
  89.     dec    c
  90.     jp    nz,loop0
  91. ;Delete old pr.sub if it exists.
  92.     ld    de,dfcb
  93.     ld    c,19        ;BDOS service 19, delete file
  94.     call    bdos        ;(no need to check response)
  95. ;Make a directory entry.
  96.     ld    de,dfcb
  97.     ld    c,22        ;BDOS service 22, make a file
  98.     call    bdos
  99.     cp    0FFh        ;a=FFh if unsuccessful
  100.     jp    nz,query1
  101.     ld    de,mess1    ;'dir. full' message
  102.     ld    c,9        ;BDOS service 9:
  103.     call    bdos        ;  Write a string to console
  104.     jp    wboot        ;quit
  105.  
  106. ;Dialog with user, process responses.
  107. ;---------------------------------------
  108. ;Ask for document filename
  109. query1:    ld    de,q1        ;first query
  110.     ld    c,9
  111.     call    bdos
  112.     ld    de,ans1        ;first answer
  113.     ld    c,10        ;BDOS service 10:
  114.     call    bdos        ;  Get a line from console
  115. ;Fill out WordStar print-command line 
  116.     ld    de,combuf    ;start of command-line buffer
  117.     ld    a,'p'
  118.     ld    (de),a
  119.     inc    de
  120.     ld    a,' '
  121.     ld    (de),a
  122.     inc    de
  123. ;Check if user has supplied optional drivecode
  124.     ld    hl,ans1+3    ;get 4th byte
  125.     ld    a,(hl)
  126.     cp    ':'        ;is it a colon?
  127.     jp    z,chars        ;yes, include in buffer
  128.     ld    a,'B'        ;no, setup B: as default 
  129.     ld    (de),a
  130.     inc    de
  131.     ld    a,':'
  132.     ld    (de),a
  133.     inc    de
  134. chars:    ld    hl,ans1+1    ;2nd byte = no. of chars.
  135.     ld    a,(hl)
  136.     ld    c,a        ;put no. of char. in loop counter
  137.     ld    hl,ans1+2    ;start of filename.ext
  138.     call    copy
  139. ;Insert ^[ after filename.ext, which EX15 will convert to <ESC>,
  140. ;  to tell WordStar to choose default print options.
  141.     ld    a,'^'
  142.     ld    (de),a
  143.     inc    de
  144.     ld    a,'['
  145.     ld    (de),a
  146.     inc    de
  147.     ld    a,cr
  148.     ld    (de),a
  149.     inc    de
  150.     ld    a,lf
  151.     ld    (de),a
  152. ;Calculate and save total character count in print-command line
  153.     ld    hl,ans1+3    ;first retrieve 4th byte of ans1
  154.     ld    a,(hl)
  155.     sub    ':'-1        ;= +1 if user supplied colon
  156.     ld    b,a
  157.     ld    hl,ans1+1    ;get no. of chars. in ans1
  158.     ld    a,(hl)
  159.     add    a,6        ;6 added chars: p, ,^,[,cr,lf
  160.     dec    b
  161.     jp    z,storl        ;was colon present?
  162.     add    a,2        ;no, so 2 more added chars (B,:)
  163. storl:    ld    de,length
  164.     ld    (de),a        ;save in 'length'
  165.     jp    query2        ;skip over beep first time
  166.  
  167. ;Ask for number of copies
  168. beep:    ld    e,07        ;07h for beep
  169.     ld    c,2        ;BDOS service 2, output a byte
  170.     call    bdos
  171. query2:    ld    de,q2        ;second query
  172.     ld    c,9
  173.     call    bdos
  174.     ld    de,ans2        ;second answer
  175.     ld    c,10
  176.     call    bdos
  177. ;Decode decimal digits for no. of copies, ncop
  178.     sub    a        ;clear A register
  179.     ld    (ncop),a    ;initialize ncop to zero
  180.     ld    hl,ans2+1    ;2nd byte has digit count
  181.     ld    a,(hl)        ;digit count
  182.     cp    3        ;less than 3 digits?
  183.     jp    nc,beep        ;no, try again
  184.     ld    b,a        ;ok, save for later
  185.     ld    c,a        ;use in loop below
  186. loopc:    inc    hl        ;next position
  187.     dec    c
  188.     jp    nz,loopc    ;c=0 means units digit
  189.     ld    a,(hl)        ;get units digit
  190.     call    chkdig        ;check for valid ASCII digit
  191.     sub    '0'        ;convert from ASCII to hex
  192.     ld    (ncop),a    ;store result
  193.     dec    b        ;finished when b=0
  194.     jp    z,conf        ;yes: only one digit present
  195.     dec    hl        ;no, get tens digit
  196.     ld    a,(hl)
  197.     call    chkdig        ;check for valid ASCII digit
  198.     sub    '0'        ;convert from ASCII to hex
  199. ;Multiply by 10 by adding 10 the correct no. of times
  200.     ld    c,a        ;addition counter
  201.     sub    a        ;clear 'a'
  202. loop3:    add    a,10
  203.     dec    c
  204.     jp    nz,loop3    ;nonzero: not finished
  205.     ld    c,a        ;save for addition to units
  206.     ld    a,(ncop)    ;retrieve units value
  207.     add    a,c
  208.     ld    (ncop),a    ;cumulative result 
  209.  
  210. ;Ask for confirmation
  211. ;  First retrieve ASCII digits for message
  212. conf:    ld    de,conf1+11    ;location of tens digit
  213.     ld    a,' '        ;blank in case no tens digit
  214.     ld    (de),a        ;store blank
  215.     ld    hl,ans2+1    ;get number of digits
  216.     ld    a,(hl)
  217.     cp    1        ;1 digit only?
  218.     jp    z,one        ;yes
  219.     inc    hl        ;no, get tens digit
  220.     ld    a,(hl)
  221.     ld    (de),a        ;enter tens digit
  222. one:    inc    hl
  223.     inc    de
  224.     ld    a,(hl)        ;get units digit
  225.     ld    (de),a        ;enter it in message
  226. ;Initialize filename part of message to blanks
  227.     ld    de,conf1+24    ;location in message for name
  228.     ld    c,14        ;max no. of chars.
  229. loopb:    ld    a,' '        ;blank
  230.     ld    (de),a        ;enter blank
  231.     inc    de
  232.     dec    c
  233.     jp    nz,loopb
  234. ;Enter filename over the blanks
  235.     ld    de,conf1+24    ;location in message for name
  236.     ld    hl,combuf+2    ;start of d:filename
  237.     ld    a,(length)    ;no. of chars. in command line
  238.     sub    6        ;extra chars.
  239.     ld    c,a        ;initialize loop counter
  240.     call    copy
  241. ;Show message on screen
  242.     ld    de,conf1
  243.     ld    c,9
  244.     call    bdos
  245.     ld    de,conf2
  246.     ld    c,9
  247.     call    bdos
  248. ;Response: need check only for Y or y.
  249.     ld    c,1        ;BDOS service 1, get a byte
  250.     call    bdos        ;byte returned in 'a' register
  251.     cp    'y'
  252.     jp    z,enter1
  253.     cp    'Y'
  254.     jp    z,enter1
  255.     jp    query1        ;go back for another dialog
  256.  
  257. ;Enter WordStar print-command lines into write buffer.
  258. ;-----------------------------------------------------
  259. ;Initialize disk-write buffer to 1Ah (EOF char. for ASCII files)
  260. enter1:    call    init
  261.     ld    de,wbuf        ;initialize buffer pointer
  262.     ld    b,128        ;initialize buffer counter
  263. ;Copy first command line (A:WS,cr,lf)
  264.     ld    c,6        ;char. count of first command
  265.     ld    hl,line1    ;location of 1st command line
  266. enter2:    ld    a,(hl)        ;get char. from command line
  267.     ld    (de),a        ;enter character into buffer
  268.     inc    hl        ;increment command line counter
  269.     inc    de        ;increment buffer pointer
  270.     dec    b        ;decrement buffer counter
  271.     dec    c        ;decrement loop counter
  272.     jp    nz,enter2
  273. ;Insert print command ncop times.
  274. ;When counter shows end of write buffer, have to write to disk
  275. ;  and start a new buffer.
  276. loop4:    ld    a,(length)
  277.     ld    c,a        ;char. count of command line
  278.     ld    hl,combuf    ;start of command-line buffer
  279. loop5:    ld    a,(hl)        ;get next character
  280.     ld    (de),a        ;enter character
  281.     inc    hl        ;set up next char. to get
  282.     inc    de        ;dest. pointer for next time
  283.     dec    b        ;at end of buffer?
  284.     jp    nz,contin    ;no, continue with next char.
  285.     call    write        ;yes, go write on disk
  286.     call    init        ;initialize buffer to EOF (1Ah)
  287.     ld    de,wbuf        ;reset buffer pointer
  288.     ld    b,128        ;reinitialize buffer counter
  289. contin:    dec    c        ;check character counter
  290.     jp    nz,loop5    ;if c=0, job is complete
  291. ;Use ncop to count no. of lines remaining to be entered
  292.     ld    hl,ncop        ;get ncop 
  293.     dec    (hl)        ;decrement ncop
  294.     jp    nz,loop4    ;if 0, no more copies needed
  295. ;Enter last line of pr.sub
  296.     ld    hl,erapr    ;command to erase pr.sub
  297.     ld    c,12        ;12 characters in this line
  298. loop6:    ld    a,(hl)
  299.     ld    (de),a
  300.     inc    hl
  301.     inc    de
  302.     dec    b
  303.     jp    nz,keepon    ;if buffer not full, keep on
  304.     call    write        ;buffer full, so write on disk
  305.     call    init        ;initialize buffer to EOF
  306.     ld    de,wbuf        ;reset buffer pointer
  307.     ld    b,128        ;reinitialize buffer counter
  308. keepon:    dec    c
  309.     jp    nz,loop6    ;continue with next character
  310.     call    write        ;write last buffer onto disk
  311. ;Close PR.SUB file 
  312.     ld    de,dfcb
  313.     ld    c,16        ;BDOS service 16:
  314.     call    bdos        ;  Close a file
  315.  
  316. ;PR.SUB now ready.  Set up command tail, load EX15, and go!
  317. ;----------------------------------------------------------
  318. ;Set up fcb for EX15.COM in dfcb location
  319.     ld    de,dfcb
  320.     ld    hl,exfcb    ;'1EX15    COM'
  321.     ld    c,12        ;character count
  322.     call    copy
  323. ;Set remaining 24 bytes in dfcb to nulls
  324.     ld    c,24        ;character count
  325.     sub    a        ;null
  326. loopz:    ld    (de),a    
  327.     inc    de
  328.     dec    c
  329.     jp    nz,loopz
  330. ;Set up command tail to simulate what CCP does
  331.     ld    de,tail        ;start of command tail
  332.     ld    a,9        ;char. count incl. blank
  333.     ld    (de),a        ;goes into 1st byte of tail
  334.     inc    de
  335.     ld    hl,erapr+1    ;' A:PR.SUB'
  336.     ld    c,9        ;char. count incl. blank
  337.     call    copy
  338.     sub    a        ;get a null 
  339.     ld    (de),a        ;null to terminate tail
  340. ;Open file EX15.COM
  341.     ld    de,dfcb
  342.     ld    c,15        ;BDOS service 15:
  343.     call    bdos        ;  Open a file
  344.     cp    0FFh        ;a=FFh if file not found
  345.     jp    nz,setadd
  346.     ld    de,mess3    ;"file not found" message
  347.     ld    c,9        ;write to console
  348.     call    bdos
  349.     jp    wboot        ;quit
  350. ;Set buffer address (destination for read)
  351. setadd:    ld    de,tpa
  352.     ld    c,26
  353.     call    bdos
  354.     jp    hicop        ;skip over subr., data
  355.  
  356. ;Subroutines.
  357. ;------------
  358.  
  359. ;Subroutine to copy from one part of memory to another.
  360. ;  hl is source pointer, de is DEstination pointer,
  361. ;  c is loop counter.  Set up these registers prior to call.
  362. copy:    ld    a,(hl)        ;get character from source
  363.     ld    (de),a        ;put character into destination
  364.     inc    hl        ;increment source pointer
  365.     inc    de        ;increment destination pointer
  366.     dec    c        ;decrement loop counter
  367.     jp    nz,copy
  368.     ret
  369.  
  370. ;Subroutine to check for valid ASCII digit in 'a' register
  371. chkdig:    cp    '0'        ;carry flag set if a < '0'
  372.     jp    c,beep        ;if so, prompt for new input
  373.     cp    '9'+1        ;carry = 0 if a .ge. '9'+1
  374.     jp    nc,beep
  375.     ret
  376.  
  377. ;Subroutine to initialize buffer to EOF character (1Ah)
  378. init:    push    bc
  379.     push    hl
  380.     ld    c,128        ;size of wbuf
  381.     ld    hl,wbuf        ;start of buffer
  382. initbf:    ld    a,1Ah
  383.     ld    (hl),a
  384.     inc    hl
  385.     dec    c
  386.     jp    nz,initbf
  387.     pop    hl
  388.     pop    bc
  389.     ret
  390.  
  391. ;Subroutine to write buffer onto disk.
  392. write:    push    bc        ;save in case loops not done
  393.     push    hl        ;also this--bdos changes hl
  394. ;Set buffer address to start of write buffer.
  395.     ld    de,wbuf        ;start of buffer
  396.     ld    c,26        ;BDOS service 26:
  397.     call    bdos        ;  Set buffer address
  398.     ld    de,dfcb        ;fcb address
  399.     ld    c,21        ;BDOS service 21:
  400.     call    bdos        ;  Sequential write
  401.     cp    0        ;a=0 means no error
  402.     pop    hl        ;restore before return
  403.     pop    bc
  404.     ret    z        ;return if a = 0 (no error)
  405.     ld    de,mess1    ;direc-full message (if a=1)
  406.     cp    1        ;a=1 means directory full
  407.     jp    z,err        ;a not 0 or 1, so must be 2
  408.     ld    de,mess2    ;a=2 means disk full
  409. err:    ld    c,9        ;show error message ...
  410.     call    bdos
  411.     jp    wboot        ;... and quit
  412.  
  413. ;Data and message storage
  414. ;------------------------
  415.     defs    stsize-1    ;lower locations in stack
  416. stack:    defb    0        ;stack "top" (first loc. used)
  417. prsub:    defb    1        ;drivecode for A: in fcb 
  418.     defm    'PR      SUB'    ;filename and type for fcb
  419. wbuf:    defs    128        ;disk-write buffer
  420. line1:    defm    'A:WS'
  421. q1:    defb    cr        ;double duty: end of line1:
  422.     defb    lf        ;             start of q1:
  423.     defb    cr        ;skip a line before query1
  424.     defb    lf
  425.     defm    'File to be printed (give drivecode if not B:): $'
  426. q2:    defb    cr
  427.     defb    lf
  428.     defm    'Number of copies (max=99): $'
  429. ans1:    defb    16        ;answer to q1, 16 chars. max.
  430.     defs    15
  431. ans2:    defb    06        ;answer to q2
  432.     defs    5
  433. combuf:    defs    24        ;for print-command buffer
  434. length:    defb    0        ;chars. in print-command line
  435. ncop:    defb    0        ;no. of copies to be printed
  436. mess1:    defm    'Directory A: full!$'
  437. mess2:    defm    'Disk A: full!$'
  438. mess3:    defm    'EX15.COM not found on A:!$'
  439. conf1:    defb    cr        ;start a new line
  440.     defb    lf
  441.     defb    cr        ;skip a line
  442.     defb    lf
  443.     defm    'Making xx copies of d:document.ext -- $'
  444. conf2:    defm    'OK? (y/n): $'
  445. erapr:    defm    'Y A:PR.SUB'    ;WordStar delete-file command
  446.     defb    cr
  447.     defb    lf
  448. exfcb:    defb    1        ;drivecode for A:
  449.     defm    'EX15    COM'    ;file name
  450.  
  451. ;Copy to high storage
  452. ;--------------------
  453.  
  454. ;Copy part of code (from start: to start:+lenth)
  455. ;  to high location to avoid being overwritten
  456. ;  when EX15.COM is read in.
  457. hicop:    ld    de,high        ;'high' is above top of EX15
  458.     ld    hl,start    ;start of segment to be moved
  459.     ld    c,lenth        ;length of segment to be moved
  460.     call    copy
  461.     jp    high        ;execute the moved segment
  462.  
  463.     org    high
  464.  
  465. ;Read in EX15.COM at tpa
  466. start:    ld    de,dfcb
  467.     ld    c,20        ;BDOS service 20:
  468.     call    bdos        ;  Sequential read
  469.     cp    0        ;a.NE.0 means no more records
  470.     jp    z,start        ;read another record
  471.     jp    tpa        ;start execution of EX15
  472.     end
  473.