home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / zcpr2 / xdir3.mqc / XDIR3.MAC
Encoding:
Text File  |  1985-02-10  |  41.3 KB  |  1,930 lines

  1. ;
  2. ;  PROGRAM:  XDIR III
  3. ;  AUTHOR:  RICHARD CONN
  4. ;  VERSION:  1.6
  5. ;  DATE:  19 NOV 83
  6. ;  PREVIOUS VERSIONS:  1.5 (9 JAN 83), 1.4 (6 JAN 83), 1.3 (7 DEC 82)
  7. ;  PREVIOUS VERSIONS:  1.2 (2 NOV 82), 1.1 (30 OCT 82), 1.0 (20 OCT 82)
  8. ;
  9. vers    equ    16
  10.  
  11. ;
  12. ;    This program is Copyright (c) 1982, 1983 by Richard Conn
  13. ;    All Rights Reserved
  14. ;
  15. ;    ZCPR2 and its utilities, including this one, are released
  16. ; to the public domain.  Anyone who wishes to USE them may do so with
  17. ; no strings attached.  The author assumes no responsibility or
  18. ; liability for the use of ZCPR2 and its utilities.
  19. ;
  20. ;    The author, Richard Conn, has sole rights to this program.
  21. ; ZCPR2 and its utilities may not be sold without the express,
  22. ; written permission of the author.
  23. ;
  24.  
  25.  
  26. ;
  27. ;  XDIR III -- Extended Disk Directory Program
  28. ;        CP/M 2.2 and ZCPR2 Version
  29. ;
  30. ;    XDIR III produces a formatted, alphabetized listing of the contents
  31. ; of the disk directory of the implied (current logged-in) or specified disk.
  32. ;
  33. ;    XDIR III is invoked by a command line of the following form --
  34. ;
  35. ;        XDIR dir:filename.typ ooo...
  36. ; or
  37. ;
  38. ;        XDIR /oooo...
  39. ;
  40. ; where:
  41. ;    dir is an optional directory name or a disk/user specification (du)
  42. ;    if dir is omitted, XDIR III defaults to the current disk/user
  43. ;    filename.typ is an ambiguous file name and type (* and ? may be used)
  44. ;    o are option letters as follows:
  45. ;        Aa - Set the attributes of the files to be displayed;
  46. ;            a=S for System Files, a=N for Non-System Files
  47. ;            a=A for All Files (System and Non-System)
  48. ;        D  - Send Output to Disk as well as screen
  49. ;        Ff - Engage File Name Buffer Facility
  50. ;            f=L to Log File Names to Disk
  51. ;            f=P to Print Names Logged to Disk
  52. ;            f=S to Scan Disk for File Names and Compare to Logged
  53. ;        I  - Inspect files selected by FL option for inclusion
  54. ;        N  - Negate selection; select those files which do NOT
  55. ;            match the ambiguous file name
  56. ;        Oo - Set Output Parameters;
  57. ;            o=A to Toggle File Attributes, o=F to Form Feed at end
  58. ;            o=G to Toggle Grouping, o=H to Toggle Hor/Vert
  59. ;        P  - Print display as well as show it on the screen
  60. ;        PF - Same as POF
  61. ; Options may be combined as desired; note that AA is the same as AS and AN,
  62. ; but AS by itself negates AN and vice-versa, with AN taking precident
  63. ;
  64.  
  65.  
  66. ;
  67. ;  CP/M Equates
  68. ;
  69. base    equ    0
  70. wboot    equ    base
  71. bdose    equ    base+5
  72. fcb    equ    base+5ch
  73. buff    equ    base+80h
  74. cr    equ    0dh
  75. ff    equ    0ch
  76. lf    equ    0ah
  77. esize    equ    16    ; size of directory entries
  78. optch    equ    '/'    ; option char
  79. maxent    equ    51    ; maximum number of entries/screen
  80.  
  81. ;
  82. ;  External Routines
  83. ;
  84.     ext    bdos    ; BDOS
  85.     ext    zfname    ; file name parser with named directories
  86.     ext    zgpins    ; init buffers
  87.     ext    dbuffer    ; disk routines
  88.     ext    dfree
  89.     ext    diralpha
  90.     ext    dirsload
  91.     ext    dirpack
  92.     ext    dirnpack
  93.     ext    dirsel
  94.     ext    dparam
  95.     ext    fsize
  96.     ext    fo0$open    ; byte-oriented file output
  97.     ext    fo0$close
  98.     ext    f0$put
  99.     ext    fo1$open
  100.     ext    fo1$close
  101.     ext    f1$put
  102.     ext    fi1$open
  103.     ext    fi1$close
  104.     ext    f1$get
  105.     ext    bbline    ; input line editor
  106.     ext    retud    ; get current user and disk
  107.     ext    print    ; print routines
  108.     ext    pstr
  109.     ext    lpstr
  110.     ext    lcrlf
  111.     ext    caps    ; capitalize char
  112.     ext    cin    ; console in char
  113.     ext    lout    ; print char
  114.     ext    cout    ; console out char
  115.     ext    crlf    ; new line
  116.     ext    madc    ; a as dec chars in memory
  117.     ext    mhldc    ; hl as dec chars in memory
  118.     ext    fillb    ; memory fill
  119.     ext    moveb    ; memory move
  120.     ext    codend    ; beginning of buffer area
  121.  
  122. ;
  123. ;  Branch to Start of Program
  124. ;
  125.     jmp    start
  126.  
  127. ;
  128. ;******************************************************************
  129. ;
  130. ;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
  131. ;
  132. ;    This data block precisely defines the data format for
  133. ; initial features of a ZCPR2 system which are required for proper
  134. ; initialization of the ZCPR2-Specific Routines in SYSLIB.
  135. ;
  136.  
  137. ;
  138. ;  EXTERNAL PATH DATA
  139. ;
  140. EPAVAIL:
  141.     DB    0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
  142. EPADR:
  143.     DW    40H    ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
  144.  
  145. ;
  146. ;  INTERNAL PATH DATA
  147. ;
  148. INTPATH:
  149.     DB    0,0    ; DISK, USER FOR FIRST PATH ELEMENT
  150.             ; DISK = 1 FOR A, '$' FOR CURRENT
  151.             ; USER = NUMBER, '$' FOR CURRENT
  152.     DB    0,0
  153.     DB    0,0
  154.     DB    0,0
  155.     DB    0,0
  156.     DB    0,0
  157.     DB    0,0
  158.     DB    0,0    ; DISK, USER FOR 8TH PATH ELEMENT
  159.     DB    0    ; END OF PATH
  160.  
  161. ;
  162. ;  MULTIPLE COMMAND LINE BUFFER DATA
  163. ;
  164. MCAVAIL:
  165.     DB    0FFH    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
  166. MCADR:
  167.     DW    0FF00H    ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
  168.  
  169. ;
  170. ;  DISK/USER LIMITS
  171. ;
  172. MDISK:
  173.     DB    4    ; MAXIMUM NUMBER OF DISKS
  174. MUSER:
  175.     DB    31    ; MAXIMUM USER NUMBER
  176.  
  177. ;
  178. ;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
  179. ;
  180. DOK:
  181.     DB    0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
  182. UOK:
  183.     DB    0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
  184.  
  185. ;
  186. ;  PRIVILEGED USER DATA
  187. ;
  188. PUSER:
  189.     DB    10    ; BEGINNING OF PRIVILEGED USER AREAS
  190. PPASS:
  191.     DB    'chdir',0    ; PASSWORD FOR MOVING INTO PRIV USER AREAS
  192.     DS    41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
  193.  
  194. ;
  195. ;  CURRENT USER/DISK INDICATOR
  196. ;
  197. CINDIC:
  198.     DB    '$'    ; USUAL VALUE (FOR PATH EXPRESSIONS)
  199.  
  200. ;
  201. ;  DMA ADDRESS FOR DISK TRANSFERS
  202. ;
  203. DMADR:
  204.     DW    80H    ; TBUFF AREA
  205.  
  206. ;
  207. ;  NAMED DIRECTORY INFORMATION
  208. ;
  209. NDRADR:
  210.     DW    00000H    ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
  211. NDNAMES:
  212.     DB    64    ; MAX NUMBER OF DIRECTORY NAMES
  213. DNFILE:
  214.     DB    'NAMES   '    ; NAME OF DISK NAME FILE
  215.     DB    'DIR'        ; TYPE OF DISK NAME FILE
  216.  
  217. ;
  218. ;  REQUIREMENTS FLAGS
  219. ;
  220. EPREQD:
  221.     DB    0FFH    ; EXTERNAL PATH?
  222. MCREQD:
  223.     DB    0FFH    ; MULTIPLE COMMAND LINE?
  224. MXREQD:
  225.     DB    0FFH    ; MAX USER/DISK?
  226. UDREQD:
  227.     DB    0FFH    ; ALLOW USER/DISK CHANGE?
  228. PUREQD:
  229.     DB    0FFH    ; PRIVILEGED USER?
  230. CDREQD:
  231.     DB    0FFH    ; CURRENT INDIC AND DMA?
  232. NDREQD:
  233.     DB    0FFH    ; NAMED DIRECTORIES?
  234. Z2CLASS:
  235.     DB    3    ; CLASS 3
  236.     DB    'ZCPR2'
  237.     DS    10    ; RESERVED
  238.  
  239. ;
  240. ;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
  241. ;
  242. ;******************************************************************
  243. ;
  244.  
  245. ;
  246. ;  Other Buffers (Set by GENINS)
  247. ;
  248. igrp:    db    0ffh    ; Group by file type and name
  249. ifmt:    db    0    ; vertical format
  250. iatt:    db    10000000b    ; Non-System files only
  251. iscn:    db    0    ; 0=dir display, 0ffh=scan for files by default
  252. fenab:    db    0ffh    ; enable F options (0=no)
  253. lenab:    db    0ffh    ; enable FL option (0=no)
  254. asenab:    db    0ffh    ; enable AS option (0=no)
  255. irs:    db    0ffh    ; enable attribute display (0=no)
  256. iff:    db    0    ; enable form feed at end (0=no)
  257.  
  258. ;
  259. ;  Buffers
  260. ;
  261. aflg:    ds    1    ; attibute flag
  262. dflg:    ds    1    ; disk output on flag
  263. fflg:    ds    1    ; 0=no file name buffer function
  264. gflg:    ds    1    ; 0=group by name/type
  265. hflg:    ds    1    ; 0=vertical list
  266. iflg:    ds    1    ; 0=no inspect
  267. nflg:    ds    1    ; 0=no negate
  268. pflg:    ds    1    ; printer output on flag
  269. fopt:    ds    1    ; file name buffer option
  270. crcnt:    ds    1    ; entry counter
  271. fmark:    ds    1    ; first file marker
  272. dflgt:    ds    1    ; temp flags
  273. pflgt:    ds    1
  274. dflgs:    ds    1
  275. pflgs:    ds    1
  276. rsflg:    ds    1    ; RS Display Flag
  277. ffflg:    ds    1    ; form feed flag
  278. disk:    ds    1    ; selected disk
  279. curdisk:
  280.     ds    1    ; current disk
  281. rem:    ds    1    ; remainder buffer
  282. firstf:    ds    2    ; ptr to first file of group to print
  283. totfil:    ds    2    ; total number of files on disk
  284. fcount:    ds    2    ; count of files
  285. countf:    ds    2    ; down count of files
  286. freesiz:
  287.     ds    2    ; amount of free space on disk
  288. totsiz:
  289.     ds    2    ; total size of all files
  290. ptr1:    ds    2    ; col output ptrs
  291. ptr2:    ds    2
  292. ptr3:    ds    2
  293. entptr:    ds    2    ; current entry ptr
  294. numbuf:    ds    6    ; number buffer
  295. dfnbuf:
  296.     ds    12    ; disk file name buffer
  297. dskfcb:
  298.     db    0
  299.     db    'XDIR    DIR'
  300.     db    0,0,0,0
  301.     ds    16
  302.     ds    4
  303. fnfcb:
  304.     db    0
  305.     db    'FNAMES  DIR'
  306.     db    0,0,0,0
  307.     ds    16
  308.     ds    4
  309. cmdlne:
  310.     ds    210    ; 210 bytes for command line
  311.     ds    100    ; 100 bytes for stack
  312. stack:    ds    2    ; stack ptr
  313.     db    0
  314.  
  315. ;
  316. ;  Command Line Option Table
  317. ;
  318. optab:
  319.     db    'A'
  320.     dw    opta
  321.     db    'D'
  322.     dw    optd
  323.     db    'F'
  324.     dw    optf
  325.     db    'I'
  326.     dw    opti
  327.     db    'N'
  328.     dw    optn
  329.     db    'O'
  330.     dw    opto
  331.     db    'P'
  332.     dw    optp
  333.     db    0
  334.  
  335. ;
  336. ;  **** Start of XDIR III ****
  337. ;
  338. start:
  339.  
  340. ;  Save stack ptr for return later
  341.     lxi    h,0    ; get stack
  342.     dad    sp
  343.     shld    stack    ; save stack ptr for return
  344.     lxi    sp,stack
  345.  
  346. ;  Mark end of command line
  347.     lxi    h,buff    ; place ending zero in command line buffer
  348.     mov    a,m    ; get char count
  349.     inx    h    ; pt to first char
  350.     add    l    ; pt to after last char
  351.     mov    l,a
  352.     mov    a,h
  353.     aci    0
  354.     mov    h,a
  355.     mvi    m,0    ; store ending zero
  356.  
  357. ;  Save command line in CMDLNE buffer
  358.     lxi    h,buff+1    ; copy input line into command line buffer
  359.     lxi    d,cmdlne
  360. start1:
  361.     mov    a,m    ; get byte
  362.     stax    d    ; put byte
  363.     inx    h    ; pt to next
  364.     inx    d
  365.     ora    a    ; end of line?
  366.     jnz    start1
  367.  
  368. ;  Initialize ZCPR2 buffers in SYSLIB
  369.     call    zgpins    ; do init
  370.  
  371. ;  Get and save current user number
  372. noext:
  373.     call    retud    ; get current user and disk
  374.     mov    a,c    ; get user into A
  375.     sta    aflg    ; current user number
  376.     mov    a,b    ; get disk into A
  377.     sta    curdisk    ; current disk number
  378.     mvi    a,0ffh    ; set default user flag
  379.     sta    disk    ; default disk selected
  380.  
  381. ;  Set flag values
  382.     lda    irs    ; get RS display option
  383.     sta    rsflg    ; set RS display option
  384.     lda    iff    ; get form feed option
  385.     sta    ffflg    ; set form feed option
  386.     lda    igrp    ; set grouping (file name/type or type/name)
  387.     sta    gflg
  388.     lda    ifmt    ; set listing format (vertical or horizontal, 0=vert)
  389.     sta    hflg
  390.     lda    iatt    ; set file attributes
  391.     mov    c,a    ; save in c
  392.     lda    aflg    ; get current user number
  393.     ora    c    ; mask in file attributes
  394.     sta    aflg    ; save flag
  395.     lda    iscn    ; set initial function (Scan or Dir)
  396.     sta    fflg
  397.     xra    a    ; A=0
  398.     sta    nflg    ; set no negation
  399.     sta    dflg    ; set no disk output
  400.     sta    pflg    ; set no printer output
  401.     sta    iflg    ; set no file name inspection (for /FP)
  402.  
  403. ;  Assume wild file name
  404.     lxi    h,fcb+1    ; store '?' chars
  405.     mvi    a,'?'
  406.     mvi    b,11    ; 11 chars
  407.     call    fillb
  408.  
  409. ;  Scan command line for options
  410.     lxi    h,cmdlne    ; pt to first char
  411.     call    sblank    ; skip over blanks
  412.     ora    a    ; end of line?
  413.     jz    xdir    ; begin main processing
  414.     inx    h    ; prep for invalid option
  415.     cpi    optch    ; option?
  416.     jz    opt    ; process options
  417.     dcx    h    ; ok to process for dir:filename.typ form
  418. ;  Process for DIR:FILENAME.TYP form
  419.     push    h    ; save ptr to first char of file name
  420.     call    codend    ; get scratch area ptr
  421.     mov    b,h    ; bc pts to scratch area
  422.     mov    c,l
  423.     pop    h    ; get ptr to first char of file name
  424.     lxi    d,fcb    ; extract file name into fcb, and get user and disk
  425. ;  named directory scan
  426.     call    zfname    ; hl pts to first char of file name, de pts to fcb,
  427.             ;   bc pts to scratch area
  428. ;  scan complete -- check for valid user and disk
  429.     jnz    udok    ; no user or disk number error
  430.     call    print
  431.     db    cr,lf,'Error -- Invalid Dir or DU Given'
  432.     db    cr,lf,0
  433.     jmp    return
  434. ;  scan complete -- look for possible following option char
  435. udok:
  436.     call    sblank    ; skip over blanks
  437.     mov    a,m    ; option char follows?
  438.     cpi    optch
  439.     jnz    skipo
  440.     inx    h    ; skip over option char
  441. ;  HL now pts to possible set of options
  442. skipo:
  443.     lda    udreqd    ; enable user and disk selection?
  444.     ora    a    ; 0=no
  445.     jnz    skipo1
  446.     lxi    b,0ffffh    ; select defaults for disk and user
  447. ;  check for disk select and select if so
  448. skipo1:
  449.     mov    a,b    ; disk number in a
  450.     sta    disk
  451.     cpi    0ffh    ; default?
  452.     jz    skipd    ; skip disk selection if so
  453.     push    b    ; save bc
  454.     push    h    ; save hl ptr
  455.     mov    e,b    ; disk number in e
  456.     dcr    e    ; adjust to 0-15
  457.     mvi    c,14    ; select disk
  458.     lda    dok    ; ok to select a disk?
  459.     ora    a    ; 0=no
  460.     cnz    bdos
  461.     pop    h    ; get hl ptr
  462.     pop    b    ; get bc
  463. ;  check for user select and select if so
  464. skipd:
  465.     mov    a,c    ; user number in a
  466.     cpi    0ffh    ; default?
  467.     jz    selcu    ; select current user if so
  468.     cpi    '?'    ; all users?
  469.     jz    selau    ; select all users if so
  470.     ani    1fh    ; mask for user number
  471. setusr:
  472.     mov    c,a    ; result in c
  473.     lda    aflg    ; get attribute flag
  474.     ani    0c0h    ; get rid of old user
  475.     ora    c    ; mask in user number
  476.     sta    aflg    ; set attribute flag
  477.     jmp    opt    ; now process options
  478. ;  select current user
  479. selcu:
  480.     lda    aflg    ; get current user
  481.     ani    1fh    ; select user number only
  482.     jmp    setusr
  483. ;  select all users
  484. selau:
  485.     lda    aflg    ; get attribute flag
  486.     ori    20h    ; select all users
  487.     sta    aflg
  488.  
  489. ;  Look for options -- main loop; HL pts to next char
  490. opt:
  491.     mov    a,m    ; get option char
  492.     inx    h    ; pt to next
  493.     ora    a    ; end of line?
  494.     jz    xdir    ; begin main processing
  495.     cpi    ' '    ; skip over spaces
  496.     jz    opt
  497.     cpi    optch    ; option char?
  498.     jz    opterr    ; loop back if so
  499.     lxi    d,optab    ; pt to option table
  500.     mov    b,a    ; option char in b
  501. ;  Scan option table
  502. opt1:
  503.     ldax    d    ; get option table char
  504.     ora    a    ; end of table?
  505.     jz    opterr    ; invalid option error
  506.     cmp    b    ; compare to passed option
  507.     jz    opt2    ; process if match
  508.     inx    d    ; skip address
  509.     inx    d
  510.     inx    d    ; pt to next opt char
  511.     jmp    opt1
  512. ;  Process option found
  513. opt2:
  514.     inx    d    ; pt to low-order address
  515.     ldax    d    ; get it
  516.     mov    c,a    ; low in C
  517.     inx    d    ; pt to high-order address
  518.     ldax    d    ; get it
  519.     mov    b,a    ; high in B
  520.     push    b    ; BC on stack
  521.     ret        ; Process option routine
  522. ;  Option A -- File Attributes
  523. opta:
  524.     mov    a,m    ; get next option letter
  525.     cpi    'N'    ; Non-System files?
  526.     jz    optan
  527.     cpi    'S'    ; System files?
  528.     jz    optas
  529.     cpi    'A'    ; All files?
  530.     jnz    opterr    ; error if not
  531. ;  Option AA -- All Files
  532. optaa:
  533.     lda    asenab    ; enable system files?
  534.     ora    a    ; 0=no
  535.     jz    optan
  536.     mvi    c,11000000b    ; System and Non-system
  537. optaret:
  538.     lda    aflg    ; get flag
  539.     ani    3fh    ; leave in user selection
  540.     ora    c    ; mask in sys/non-sys
  541.     sta    aflg    ; restore flag
  542.     inx    h    ; pt to next
  543.     jmp    opt
  544. ;  Option AS -- System Files
  545. optas:
  546.     lda    asenab    ; enable system files?
  547.     ora    a    ; 0=no
  548.     jz    optan
  549.     mvi    c,01000000b    ; System Only
  550.     jmp    optaret
  551. ;  Option AN -- Non-System Files
  552. optan:
  553.     mvi    c,10000000b    ; Non-system Only
  554.     jmp    optaret
  555.  
  556. ;  Option F - select file name buffer functions
  557. optf:
  558.     mvi    a,0ffh    ; set flag
  559.     sta    fflg
  560.     mov    a,m    ; get option char
  561.     sta    fopt
  562.     cpi    'L'    ; log file names to disk
  563.     jz    optfok
  564.     cpi    'P'    ; print names of files
  565.     jz    optfok
  566.     cpi    'S'    ; scan disk for files
  567.     jz    optfok
  568.     jmp    opterr    ; error otherwise
  569. optfok:
  570.     inx    h    ; pt to next option letter
  571.     jmp    opt
  572.  
  573. ;  Option I -- enable it; inspect for FL option only
  574. opti:
  575.     mvi    a,0ffh    ; ON
  576.     sta    iflg
  577.     jmp    opt
  578.  
  579. ;  Option D -- enable it; Disk output
  580. optd:
  581.     mvi    a,0ffh    ; ON
  582.     sta    dflg
  583.     jmp    opt
  584.  
  585. ;  Option P -- enable it; Printer output
  586. optp:
  587.     mvi    a,0ffh    ; ON
  588.     sta    pflg
  589.     mov    a,m    ; get possible 2nd letter
  590.     cpi    'F'    ; set form feed if F
  591.     jnz    opt    ; process as next option letter if not F
  592.     inx    h    ; pt to next
  593.     jmp    optof
  594.  
  595. ;  Option O -- control Output parameters
  596. opto:
  597.     mov    a,m    ; get 2nd letter
  598.     inx    h    ; pt to next
  599.     cpi    'A'    ; attributes?
  600.     jz    optoa
  601.     cpi    'F'    ; form feed?
  602.     jz    optof
  603.     cpi    'G'    ; grouping?
  604.     jz    optog
  605.     cpi    'H'    ; horizontal/vertical?
  606.     jz    optoh
  607.     dcx    h    ; adjust back
  608.     jmp    opterr
  609. ;  Toggle File Attributes Flag
  610. optoa:
  611.     lda    rsflg    ; flip flag
  612.     cma
  613.     sta    rsflg
  614.     jmp    opt
  615. ;  Toggle Form Feed Flag
  616. optof:
  617.     lda    ffflg    ; flip flag
  618.     cma
  619.     sta    ffflg
  620.     jmp    opt
  621. ;  Toggle Grouping
  622. optog:
  623.     lda    gflg    ; flip flag
  624.     cma
  625.     sta    gflg    ; 0=file name and type
  626.     jmp    opt
  627. ;  Toggle Horizontal/Vertical Listing
  628. optoh:
  629.     lda    hflg    ; flip flag
  630.     cma
  631.     sta    hflg    ; 0=vertical
  632.     jmp    opt
  633.  
  634. ;  Option N -- enable it; Negate Selection
  635. optn:
  636.     mvi    a,0ffh    ; ON
  637.     sta    nflg
  638.     jmp    opt
  639.  
  640. ;  Option error message
  641. opterr:
  642.     xra    a    ; set no disk or printer output
  643.     sta    dflg
  644.     sta    pflg
  645.     call    banner    ; print banner
  646.     call    print
  647.     db    '     Invalid Option --> ',0
  648.     dcx    h    ; pt to first char
  649.     call    pstr    ; print string pted to by hl
  650.     call    print
  651.     db    cr,lf,'XDIR III command lines are:'
  652.     db    cr,lf,'        XDIR dir:filename.typ ooo...'
  653.     db    cr,lf,'or        XDIR /oooo...'
  654.     db    cr,lf,'where:    dir: is optional and indicates selected '
  655.     db    'directory (DIR or DU form)'
  656.     db    cr,lf,'    filename.typ is an ambiguous file name and type '
  657.     db    '(also optional)'
  658.     db    cr,lf,'    o are option letters as follows:'
  659.     db    cr,lf,'        Aa - Set and Display of file attributes'
  660.     db    cr,lf,'          a=S for System, a=N for Non-System'
  661.     db    cr,lf,'          a=A for All Files (System and Non-System)'
  662.     db    cr,lf,'        D  - Send Output to Disk File XDIR.DIR'
  663.     db    cr,lf,'        Ff - Enable a File Buffer Function'
  664.     db    cr,lf,'          f=L for Log Names to FNAMES.DIR'
  665.     db    cr,lf,'          f=P to Print Names stored in FNAMES.DIR'
  666.     db    cr,lf,'          f=S to Scan Disk and Compare to FNAMES.DIR'
  667.     db    cr,lf,'        I  - Inspect Logged Files (for FL Option Only)'
  668.     db    cr,lf,'        N  - Negate selection'
  669.     db    cr,lf,'        Oo - Toggle Output Control Options'
  670.     db    cr,lf,'          o=A for File Attributes, o=F for Form Feed'
  671.     db    cr,lf,'          o=G for Grouping, o=H for Horiz/Vert Format'
  672.     db    cr,lf,'        P  - Send display to printer'
  673.     db    cr,lf,'        PF - Same as POF (Abbreviated Form)'
  674.     db    cr,lf,' Options may be combined as desired',0
  675.  
  676. ;  Return to CP/M
  677. return:
  678.     lda    dflg    ; disk output?
  679.     ora    a    ; 0=no
  680.     cnz    fo0$close    ; close file if so
  681.     lhld    stack    ; get old stack ptr
  682.     sphl
  683.     ret        ; return to CP/M
  684.  
  685. ;  Memory Overflow Error
  686. memerr:
  687.     call    printx
  688.     db    cr,lf,'TPA Error',cr,lf,0
  689.     jmp    return
  690.  
  691. ;  Print banner of XDIR III
  692. banner:
  693.     call    printx
  694.     db    'XDIR III, Version '
  695.     db    vers/10+'0','.',(vers mod 10)+'0',0
  696.     ret
  697.  
  698. ;
  699. ;  Begin XDIR III processing
  700. ;
  701. xdir:
  702.  
  703. ;  This section disables the /Ff option and /FL option if default set
  704.     lda    fenab    ; enable FFLG? (/Ff option)
  705.     ora    a    ; 0=no
  706.     jnz    xdst1
  707.     xra    a    ; turn off FFLG
  708.     sta    fflg
  709. xdst1:
  710.     lda    lenab    ; enable FL option?
  711.     ora    a    ; 0=no
  712.     jnz    xdst2
  713.     lda    fflg    ; FFLG on?
  714.     ora    a    ; 0=no
  715.     jz    xdst2
  716.     lda    fopt    ; check for L
  717.     cpi    'L'
  718.     jnz    xdst2
  719.     mvi    a,'P'    ; switch L to P
  720.     sta    fopt
  721. xdst2:
  722.     lda    fflg    ; file name buffer option?
  723.     ora    a    ; 0=no
  724.     jz    xdirst
  725.     xra    a    ; A=0
  726.     sta    gflg    ; group by file name and type
  727.     lda    fopt    ; print immediately if P option
  728.     cpi    'P'    ; print?
  729.     jnz    xdirst
  730.     call    banner    ; print banner
  731.     jmp    xdirfp    ; print file names
  732.  
  733. ;  Check for Print Option and Ask for and Print Header if so
  734. xdirst:
  735.     lda    pflg    ; printer output?
  736.     ora    a    ; 0=no
  737.     jz    xdirgo
  738.     call    print    ; message to user
  739.     db    cr,lf,'XDIR III Print -- Please Input Header: ',0
  740.     xra    a    ; no caps
  741.     call    bbline    ; input line from user
  742.     ora    a    ; no chars?
  743.     jz    xdirgo
  744.     call    lcrlf    ; new line
  745.     call    lpstr    ; print header line
  746.     call    lcrlf    ; new line
  747.  
  748. ;  Get Files from Disk
  749. xdirgo:
  750.     call    crlf    ; new line on console
  751.     call    codend    ; end of code
  752.     call    dbuffer    ; set buffers
  753.     jz    memerr    ; memory overflow error?
  754.     push    h    ; save regs
  755.     push    d
  756.     call    dfree    ; compute amount of free space on disk
  757.     xchg        ; amount in hl
  758.     shld    freesiz    ; save free space count
  759.     pop    d    ; get regs
  760.     pop    h
  761.     call    dirsload    ; load with sizing information
  762.     jz    memerr    ; memory overflow error?
  763.     push    h    ; save hl
  764.     mov    h,b    ; HL=number of files loaded
  765.     mov    l,c
  766.     shld    totfil    ; save total count
  767.     push    b    ; save bc
  768.     lda    curdisk    ; prepare to relog in disk
  769.     mov    e,a
  770.     mvi    c,14    ; select disk
  771.     lda    disk    ; was disk changed?
  772.     cpi    0ffh    ; 0ffh if not
  773.     cnz    bdos
  774.  
  775. ;  Open disk file if necessary for disk output
  776.     lda    dflg    ; disk output?
  777.     ora    a    ; 0=no
  778.     jz    xdir0
  779.     lxi    d,dskfcb    ; open disk file for char output
  780.     call    fo0$open    ; open file for output
  781. xdir0:
  782.     pop    b    ; get count
  783.     pop    h    ; get ptr
  784.  
  785. ;  Continue processing; select desired files
  786.     lda    aflg    ; get file attributes
  787.     lxi    d,fcb    ; get ptr to fcb
  788.     call    dirsel    ; select files
  789.  
  790. ;  Now, pack and alphabetize directory
  791.     lda    nflg    ; negate selection?
  792.     ora    a    ; 0=no
  793.     cz    dirpack    ; select marked entries
  794.     cnz    dirnpack    ; select unmarked entries
  795.     lda    gflg    ; get grouping flag
  796.     call    diralpha    ; alphabetize directory
  797.     shld    firstf    ; save ptr to first file
  798.     mov    h,b    ; HL=file count
  799.     mov    l,c
  800.     shld    fcount    ; save file count
  801.     shld    countf    ; save file down count
  802.     lxi    h,0    ; set file size counter
  803.     shld    totsiz    ; save counter
  804.     lda    dflg    ; set temp flags
  805.     sta    dflgt
  806.     lda    pflg
  807.     sta    pflgt
  808.  
  809. ;
  810. ;  Major feature selection --
  811. ;    Two major features of XDIR are selected at this time:
  812. ;        1.  Directory Display Functions
  813. ;        2.  File Name Buffer Functions
  814. ;    At this point, the following key values are know:
  815. ;        FIRSTF - Pointer to First File
  816. ;        FCOUNT, COUNTF - Number of Files
  817. ;
  818.     lda    fflg    ; get flag
  819.     ora    a    ; Z=Directory Display, NZ=File Name Buffer Fcts
  820.     jnz    xdirf    ; Do File Name Buffer Fcts
  821.  
  822. ;
  823. ;  Main Directory Print Routine -- This routine displays the directory to
  824. ;  the console, printer, or disk as desired
  825. ;
  826. ;  Print header lines and one screen of entries
  827. xdir2:
  828.     lda    dflg    ; save disk and print output flags
  829.     sta    dflgs
  830.     lda    pflg
  831.     sta    pflgs
  832.     lda    dflgt    ; use temp flags
  833.     sta    dflg
  834.     lda    pflgt
  835.     sta    pflg
  836.     xra    a    ; A=0
  837.     sta    dflgt    ; clear temp flags so no banner 2nd time around
  838.     sta    pflgt
  839.  
  840. ;  Print: Main Banner
  841.     call    banner    ; print banner
  842.  
  843. ;  Print: Horizontal/Vertical Listing Message
  844.     call    printx
  845.     db    '    ',0
  846.     lda    hflg    ; get horizontal/vertical flag
  847.     ora    a    ; 0=vertical
  848.     jnz    xdir2a
  849.     call    printx
  850.     db    'Vertical',0
  851.     jmp    xdir3
  852. xdir2a:
  853.     call    printx
  854.     db    'Horizontal',0
  855.  
  856. ;  Print: Listing by File Name and Type or Type and Name Message
  857. xdir3:
  858.     call    printx
  859.     db    ' Listing by File ',0
  860.     lda    gflg    ; grouping flag
  861.     ora    a    ; 0=name and type
  862.     jnz    xdir3a
  863.     call    printx
  864.     db    'Name and Type',0
  865.     jmp    xdir4
  866. xdir3a:
  867.     call    printx
  868.     db    'Type and Name',0
  869.  
  870. ;  Print:  Disk and User
  871. xdir4:
  872.     call    printx    ; print everywhere
  873.     db    cr,lf,' Disk: ',0
  874.     lda    curdisk    ; get current disk
  875.     mov    c,a    ; ... in C
  876.     lda    disk    ; default disk?
  877.     cpi    0ffh
  878.     jz    xdir4a
  879.     dcr    a    ; adjust disk number for following conversion
  880.     mov    c,a    ; get selected disk
  881. xdir4a:
  882.     mov    a,c    ; print disk in C
  883.     adi    'A'    ; convert to ASCII
  884.     call    coutx    ; print everywhere
  885.     call    printx    ; print everywhere
  886.     db    '  User: ',0
  887.     lda    aflg    ; get user number
  888.     ani    20h    ; all?
  889.     jz    xdir4b
  890.     call    printx
  891.     db    'All',0
  892.     jmp    xdir5
  893. xdir4b:
  894.     lda    aflg    ; get selected user
  895.     ani    1fh    ; select user number
  896.     lxi    d,numbuf    ; store number in buffer
  897.     call    madc    ; get number
  898.     mvi    b,3    ; 3 digits
  899.     call    prnumx    ; print number everywhere
  900.  
  901. ;  Print: Selected File Attributes
  902. xdir5:
  903.     call    printx
  904.     db    ', File Attributes: ',0
  905.     lda    aflg    ; get flag
  906.     push    psw    ; save A
  907.     ani    80h    ; Non-system?
  908.     jz    xdir5a
  909.     call    printx
  910.     db    ' Non-System',0
  911. xdir5a:
  912.     pop    psw    ; get A
  913.     ani    40h    ; System?
  914.     jz    xdir5b
  915.     call    printx
  916.     db    ' System',0
  917.  
  918. ;  See if any files selected
  919. xdir5b:
  920.     lhld    countf    ; get file down count
  921.     mov    a,h    ; any files?
  922.     ora    l
  923.     jnz    xdir6
  924.     call    printx    ; print everywhere
  925.     db    cr,lf,'No files selected -- ',0
  926.     jmp    xdir11
  927.  
  928. ;
  929. ;  This is the main looping entry point for each screen display
  930. ;
  931. xdir6:
  932.     lda    aflg    ; all users selected?
  933.     ani    20h
  934.     jnz    xdir6a
  935. ;
  936. ;  This is the header which is printed if the files in only one user area are
  937. ;    displayed
  938. ;
  939.     call    printx    ; specific user selected
  940.     db    cr,lf,cr,lf
  941.     db    'Filename.Typ Size K',0
  942.     lda    rsflg
  943.     ora    a    ; Z=no
  944.     jz    xd6rs1
  945.     call    printx
  946.     db    ' RS',0
  947. xd6rs1:
  948.     call    printx
  949.     db    '   Filename.Typ Size K',0
  950.     lda    rsflg
  951.     ora    a    ; Z=no
  952.     jz    xd6rs2
  953.     call    printx
  954.     db    ' RS',0
  955. xd6rs2:
  956.     call    printx
  957.     db    '   Filename.Typ Size K',0
  958.     lda    rsflg
  959.     ora    a
  960.     jz    xd6rs3
  961.     call    printx
  962.     db    ' RS',0
  963. xd6rs3:
  964.     call    printx
  965.     db    cr,lf
  966.     db    '-------- --- ------',0
  967.     lda    rsflg
  968.     ora    a
  969.     jz    xd6rs4
  970.     call    printx
  971.     db    ' --',0
  972. xd6rs4:
  973.     call    printx
  974.     db    '   -------- --- ------',0
  975.     lda    rsflg
  976.     ora    a
  977.     jz    xd6rs5
  978.     call    printx
  979.     db    ' --',0
  980. xd6rs5:
  981.     call    printx
  982.     db    '   -------- --- ------',0
  983.     lda    rsflg
  984.     ora    a
  985.     jz    xd6rs6
  986.     call    printx
  987.     db    ' --',0
  988. xd6rs6:
  989.     jmp    xdir6b
  990. ;
  991. ;  This is the header which is printed if the files in all user areas are
  992. ;    displayed
  993. ;
  994. xdir6a:
  995.     call    printx    ; all users selected
  996.     db    cr,lf,cr,lf
  997.     db    ' U Filename.Typ Size K',0
  998.     lda    rsflg
  999.     ora    a
  1000.     jz    xd6ars1
  1001.     call    printx
  1002.     db    ' RS',0
  1003. xd6ars1:
  1004.     call    printx
  1005.     db    '  U Filename.Typ Size K',0
  1006.     lda    rsflg
  1007.     ora    a
  1008.     jz    xd6ars2
  1009.     call    printx
  1010.     db    ' RS',0
  1011. xd6ars2:
  1012.     call    printx
  1013.     db    '  U Filename.Typ Size K',0
  1014.     lda    rsflg
  1015.     ora    a
  1016.     jz    xd6ars3
  1017.     call    printx
  1018.     db    ' RS',0
  1019. xd6ars3:
  1020.     call    printx
  1021.     db    cr,lf
  1022.     db    ' - -------- --- ------',0
  1023.     lda    rsflg
  1024.     ora    a
  1025.     jz    xd6ars4
  1026.     call    printx
  1027.     db    ' --',0
  1028. xd6ars4:
  1029.     call    printx
  1030.     db    '  - -------- --- ------',0
  1031.     lda    rsflg
  1032.     ora    a
  1033.     jz    xd6ars5
  1034.     call    printx
  1035.     db    ' --',0
  1036. xd6ars5:
  1037.     call    printx
  1038.     db    '  - -------- --- ------',0
  1039.     lda    rsflg
  1040.     ora    a
  1041.     jz    xdir6b
  1042.     call    printx
  1043.     db    ' --',0
  1044.  
  1045. ;
  1046. ;  Prepare Columnar Output
  1047. ;
  1048. xdir6b:
  1049.     lda    dflgs    ; restore disk and print flags
  1050.     sta    dflg
  1051.     lda    pflgs
  1052.     sta    pflg
  1053.     lhld    countf    ; get file count down
  1054.     lxi    d,maxent    ; assume maxent entries to print
  1055.     mov    a,h    ; within range?
  1056.     ora    a    ; outside of range if not
  1057.     jnz    xdir7    ; subtract entries to print from total entries
  1058.     mov    a,l    ; within range?
  1059.     cpi    maxent    ; less than maxent entries left?
  1060.     jnc    xdir7    ; subtract entries to print from total entries
  1061.     mov    d,h    ; DE=HL=number of entries to print
  1062.     mov    e,l
  1063. xdir7:
  1064.     mov    a,l    ; subtract entries to print (DE) from total (HL)
  1065.     sub    e
  1066.     mov    l,a
  1067.     mov    a,h
  1068.     sbb    d
  1069.     mov    h,a    ; HL=result
  1070.     shld    countf    ; save new down count
  1071.     mov    b,h    ; BC=count
  1072.     mov    c,l
  1073.     lhld    firstf    ; pt to first file
  1074. ;
  1075. ;  At this point, BC=number of remaining entries, DE=number of entries to
  1076. ;    print, and HL pts to first entry to print
  1077. ;
  1078.     shld    ptr1    ; save ptr to 1st entry
  1079.     lda    hflg    ; horizontal listing?
  1080.     ora    a    ; 0ffh = yes
  1081.     jnz    xdir7c    ; don't worry about columns if horizontal
  1082.     push    d    ; save count
  1083.     call    divde3    ; divide DE by 3, result*esize in BC, remainder in A
  1084.     lxi    d,esize    ; DE=ESIZE (size of entry)
  1085.     dad    b    ; add BC as a minimum
  1086.     ora    a    ; any remainder?
  1087.     jz    xdir7a    ; skip if none
  1088.     dad    d    ; add in ESIZE for additional length of 1st col
  1089. xdir7a:
  1090.     shld    ptr2    ; save ptr to col 2
  1091.     dad    b    ; add BC as a minimum
  1092.     cpi    2    ; if remainder 2, add ESIZE for additional
  1093.     jc    xdir7b
  1094.     dad    d    ; add in ESIZE
  1095. xdir7b:
  1096.     shld    ptr3    ; save ptr to col 3
  1097.     pop    d    ; get count in de
  1098. ;
  1099. ;  Main entry print routine
  1100. ;
  1101. xdir7c:
  1102.     mvi    d,1    ; set 3's counter
  1103. xdir8:
  1104.     lhld    ptr1    ; pt to first entry
  1105.     call    prentry    ; print entry
  1106.     shld    ptr1    ; put ptr
  1107.     lda    hflg    ; horizontal?
  1108.     ora    a    ; 0ffh = yes
  1109.     jnz    xdir9
  1110.     dcr    e    ; count down
  1111.     jz    xdir10
  1112.     lhld    ptr2    ; get ptr
  1113.     call    prentry    ; print entry
  1114.     shld    ptr2    ; put ptr
  1115.     dcr    e    ; count down
  1116.     jz    xdir10
  1117.     lhld    ptr3    ; get ptr
  1118.     call    prentry    ; print entry
  1119.     shld    ptr3    ; put ptr
  1120. xdir9:
  1121.     dcr    e    ; count down
  1122.     jnz    xdir8    ; continue if not zero
  1123.     shld    firstf    ; save ptr to first of next set of entries to print
  1124.     lhld    countf    ; get count of remaining entries
  1125. ;
  1126. ;  At this point, HL=number of entries left
  1127. ;
  1128.     mov    a,h    ; anything left?
  1129.     ora    l
  1130.     jz    xdir10
  1131.     lda    dflg    ; no message if disk or printer output
  1132.     mov    b,a
  1133.     lda    pflg
  1134.     ora    b
  1135.     jnz    xdir6
  1136.     call    print    ; screen break
  1137.     db    cr,lf,' --> Screen Break -- Type any char to cont <-- ',0
  1138.     call    cin    ; get response
  1139.     cpi    3    ; abort?
  1140.     jz    return
  1141.     jmp    xdir6    ; new screen display
  1142. ;
  1143. ;  Print end statistics and exit
  1144. ;
  1145. xdir10:
  1146.     call    crlfx    ; new line
  1147.     lhld    fcount    ; print file count
  1148.     call    prhlx    ; print it everywhere
  1149.     call    printx
  1150.     db    ' Files Occupying ',0
  1151.     lhld    totsiz    ; get total of file sizes
  1152.     call    prhlx    ; print it everywhere
  1153.     call    printx
  1154.     db    'K, ',0
  1155.     lhld    totfil    ; print total file count
  1156.     call    prhlx    ; print it everywhere
  1157.     call    printx
  1158.     db    ' Files on Disk and ',0
  1159.  
  1160. ;
  1161. ;  Print Amount of Free Space Left on Disk
  1162. ;    Entry Point if No Files Found
  1163. ;
  1164. xdir11:
  1165.     lhld    freesiz    ; get amount of free space
  1166.     call    prhlx    ; print it everywhere
  1167.     call    printx
  1168.     db    'K Free',0
  1169.     lda    dflg    ; if disk or printer output, new line
  1170.     mov    b,a
  1171.     lda    pflg
  1172.     ora    b
  1173.     jz    return
  1174.     call    crlfx    ; new line for disk and/or printer
  1175.     lda    pflg    ; print output
  1176.     mov    b,a
  1177.     lda    ffflg    ; form feed
  1178.     ana    b    ; if print and form feed ... NZ is set
  1179.     mvi    a,ff    ; form feed char
  1180.     cnz    lout    ; form feed to printer
  1181.     jmp    return
  1182.  
  1183. ;
  1184. ;  File Name Buffer Functions
  1185. ;
  1186. xdirf:
  1187.     call    banner    ; print banner
  1188.     lda    iscn    ; just scan?
  1189.     ora    a    ; 0=no
  1190.     jnz    xdirfs
  1191.     lda    fopt    ; get option of F command
  1192.     cpi    'L'    ; log names to disk?
  1193.     jz    xdirfl
  1194.     cpi    'S'    ; scan names on disk?
  1195.     jz    xdirfs
  1196. ;
  1197. ;  File Name Print Option; /FP option
  1198. ;
  1199. xdirfp:
  1200.     call    openin    ; open FNAMES.DIR for input
  1201. xdfp0:
  1202.     call    printx
  1203.     db    cr,lf,cr,lf
  1204.     db    'Printout of Recorded File Names --',cr,lf,'     ',0
  1205. ;  Extract File Name Count
  1206.     call    f1$get    ; get low count
  1207.     jnz    geterr
  1208.     mov    l,a    ; save in L
  1209.     call    f1$get    ; get high count
  1210.     jnz    geterr
  1211.     mov    h,a    ; save in H
  1212.     push    h    ; save HL
  1213.     call    prhlx    ; print HL everywhere
  1214.     call    printx
  1215.     db    ' File Names Recorded',cr,lf,0
  1216.     call    prfhdr    ; print file name header
  1217.     pop    h    ; get HL
  1218.     mvi    c,0    ; set entry counter
  1219.  
  1220. ;
  1221. ;  Loop for extracting names from FNAMES.DIR and printing them
  1222. ;
  1223. xdfp1:
  1224.     mov    a,h    ; no more entries?
  1225.     ora    l
  1226.     jz    xdfp2
  1227.     dcx    h    ; count down
  1228.     call    getdfn    ; get next disk file name from FNAMES.DIR
  1229.     call    prfnfx    ; print file name entry
  1230.     inr    c    ; increment count
  1231.     mov    a,c    ; new line time?
  1232.     ani    3
  1233.     cz    crlfx
  1234.     jmp    xdfp1
  1235. xdfp2:
  1236.     call    fi1$close
  1237.     call    crlfx    ; new line
  1238.     jmp    return
  1239.  
  1240. ;
  1241. ;  Log File Names to Disk; /FL option
  1242. ;    Structure of FNAMES.DIR file is:
  1243. ;        File Name Count, Low-Order Byte
  1244. ;        File Name Count, High-Order Byte
  1245. ;        File Names, stored as 12 bytes -- User Number, FN, and FT
  1246. ;
  1247. xdirfl:
  1248.     lxi    d,fnfcb    ; open file for output
  1249.     call    fo1$open
  1250.     jz    xdfl1
  1251.     call    printx
  1252.     db    cr,lf,'Cannot Open FNAMES.DIR for Output -- Aborting',cr,lf,0
  1253.     jmp    return
  1254.  
  1255. ;  Log Files to Disk with possible initial inspect and select by user
  1256. xdfl1:
  1257.     lda    iflg    ; inspect?
  1258.     ora    a    ; 0=no
  1259.     cnz    flinsp    ; inspect if selected
  1260.  
  1261. ;  Print file count
  1262.     call    printx
  1263.     db    cr,lf,cr,lf
  1264.     db    'Logging File Names to Disk --',cr,lf,'     ',0
  1265.     lhld    fcount    ; get count
  1266.     call    prhlx    ; print it
  1267.     call    printx
  1268.     db    ' File Names to be Logged to Disk',cr,lf,0
  1269.  
  1270. ;  Check file count and print appropriate header
  1271.     lhld    fcount    ; get number of files
  1272.     mov    a,h    ; any files?
  1273.     ora    l
  1274.     jz    xdfl1a
  1275.     call    prfhdr    ; print file name header
  1276.     jmp    xdfl1b
  1277. xdfl1a:
  1278.     call    printx    ; no files
  1279.     db    '     No Files to be Logged',0
  1280.  
  1281. ;  Store file count to disk
  1282. xdfl1b:
  1283.     mov    a,l    ; store low count
  1284.     call    f1$put
  1285.     jnz    puterr
  1286.     mov    a,h    ; store high count
  1287.     call    f1$put
  1288.     jnz    puterr
  1289.     xchg        ; ... in DE
  1290.     lhld    firstf    ; pt to first file
  1291.     mvi    c,0    ; set display counter
  1292.  
  1293. ;  Loop to store files names
  1294. xdfl2:
  1295.     mov    a,d    ; done?
  1296.     ora    e
  1297.     jz    xdfl3
  1298.     dcx    d    ; count down
  1299.  
  1300. ;  Write entry to disk
  1301.     push    d    ; save count
  1302.     push    h    ; save ptr to file
  1303.     mov    a,m    ; get user number
  1304.     call    f1$put    ; save it
  1305.     jnz    puterr
  1306.     lxi    d,numbuf    ; print user number
  1307.     push    d    ; save ptr
  1308.     call    madc
  1309.     pop    d    ; get ptr
  1310.     inx    d    ; pt to 1st digit
  1311.     ldax    d    ; get it
  1312.     call    coutx
  1313.     inx    d    ; pt to last digit
  1314.     ldax    d    ; get it
  1315.     call    coutx
  1316.     mvi    a,' '    ; <SP>
  1317.     call    coutx
  1318.     inx    h    ; pt to FN
  1319.     mvi    b,8    ; 8 chars
  1320.     call    xdput
  1321.     mvi    a,'.'
  1322.     call    coutx
  1323.     mvi    b,3    ; 3 chars
  1324.     call    xdput
  1325.     mvi    a,' '    ; print <SP>
  1326.     call    coutx
  1327.     call    coutx
  1328.     inr    c    ; increment count
  1329.     mov    a,c    ; get count
  1330.     ani    3
  1331.     cz    crlfx
  1332.     pop    h    ; get ptr to first file
  1333.     pop    d    ; get count
  1334.     push    b
  1335.     lxi    b,esize    ; pt to next file
  1336.     dad    b
  1337.     pop    b
  1338.     jmp    xdfl2
  1339.  
  1340. ;  Done with creation of FNAMES.DIR
  1341. xdfl3:
  1342.     call    fo1$close    ; close file
  1343.     call    crlfx
  1344.     jmp    return
  1345.  
  1346. ;  Write B chars pted to by HL to FNAMES.DIR and user
  1347. xdput:
  1348.     mov    a,m    ; get char
  1349.     call    coutx    ; print it everywhere
  1350.     call    f1$put    ; put it on disk
  1351.     jnz    puterr
  1352.     inx    h    ; pt to next
  1353.     dcr    b    ; count down
  1354.     jnz    xdput
  1355.     ret
  1356.  
  1357. ;
  1358. ;  Inspect Files for Logging to Disk
  1359. ;
  1360. flinsp:
  1361.     lhld    fcount    ; get count of files
  1362.     xchg        ; ... in DE
  1363.     mov    a,d    ; any files selected?
  1364.     ora    e
  1365.     rz        ; abort if none
  1366.  
  1367. ;  Inspection banner
  1368.     call    printx
  1369.     db    cr,lf,'Inspection of Files for Logging to Disk',0
  1370.     lhld    firstf    ; pt to first file
  1371.  
  1372. ;  Main inspection loop
  1373. flil1:
  1374.     mov    a,d    ; any files selected?
  1375.     ora    e
  1376.     jz    flil3    ; done if not
  1377.     dcx    d    ; count down
  1378.     push    d    ; save count
  1379.     lxi    d,dfnbuf    ; copy file name to buffer
  1380.     mvi    b,12    ; 12 bytes
  1381.     call    moveb
  1382.     call    printx
  1383.     db    cr,lf,'Log ',0
  1384.     call    prfnfx    ; print file name for prompt
  1385.     call    printx
  1386.     db    ' to Disk (Y/N/<CR>=Y)? ',0
  1387.     call    cin    ; get response
  1388.     call    caps    ; capitalize
  1389.     call    coutx
  1390.     cpi    'N'    ; No?
  1391.     jz    flil2
  1392.     mov    a,m    ; mark user number
  1393.     ori    80h
  1394.     mov    m,a
  1395. flil2:
  1396.     lxi    d,esize    ; skip to next entry
  1397.     dad    d
  1398.     pop    d    ; get count
  1399.     jmp    flil1
  1400. flil3:
  1401.     lhld    fcount    ; get number of files
  1402.     mov    b,h    ; count in BC
  1403.     mov    c,l
  1404.     lhld    firstf    ; pt to first file
  1405.     call    dirpack    ; pack directory
  1406.     mov    h,b    ; new count in HL
  1407.     mov    l,c
  1408.     shld    fcount    ; set counts
  1409.     shld    countf
  1410.     ret
  1411.  
  1412. ;
  1413. ;  Error Message for Output
  1414. ;
  1415. puterr:
  1416.     call    printx
  1417.     db    cr,lf,'Error in Writing to Disk -- Aborting',cr,lf,0
  1418.     jmp    return
  1419.  
  1420. ;
  1421. ;  Scan Disk for File Names; /FS option
  1422. ;
  1423. xdirfs:
  1424.     call    printx
  1425.     db    cr,lf,'File Name Scanner',0
  1426.     call    openin    ; open FNAMES.DIR for input
  1427. xdfs1:
  1428.     call    printx
  1429.     db    cr,lf,'Files Named in FNAMES.DIR missing from Disk --',cr,lf,0
  1430.  
  1431. ;  Get file name count
  1432.     call    f1$get    ; get file name count from disk
  1433.     jnz    geterr
  1434.     mov    c,a    ; store low
  1435.     call    f1$get
  1436.     jnz    geterr
  1437.     mov    b,a    ; store high
  1438.     lhld    fcount    ; get count of number of files
  1439.     xchg        ; ... in DE
  1440.     lhld    firstf    ; pt to first file
  1441.     xra    a    ; A=0
  1442.     sta    crcnt    ; set counter for CRLF
  1443.     sta    fmark    ; mark no first file yet
  1444.  
  1445. ;
  1446. ;  At this point, HL pts to first file in buffer, DE is number of files in
  1447. ;    buffer, and BC is number of files in FNAMES.DIR
  1448. ;
  1449.     mov    a,b    ; any names in FNAMES.DIR?
  1450.     ora    c
  1451.     jz    xdfs5    ; mark all names in buffer if not
  1452.     call    getdfn    ; get first disk name
  1453. xdfs2:
  1454.     mov    a,b    ; see if any more files in FNAMES.DIR
  1455.     ora    c
  1456.     jz    xdfs5    ; mark rest of files in buffer and continue
  1457.     mov    a,d    ; see if any more files in buffer
  1458.     ora    e
  1459.     jz    xdfs6    ; name rest of files in FNAMES.DIR as missing and cont
  1460.     call    compfn    ; compare to file name pted to by HL
  1461.     jz    xdfs3a    ; advance to next file if they match
  1462.     jc    xdfs3    ; mark file name pted to by HL as additional
  1463.     lda    fmark    ; first file?
  1464.     ora    a    ; 0=yes
  1465.     jnz    xdfs2a
  1466.     mvi    a,0ffh    ; set mark
  1467.     sta    fmark
  1468.     call    prfhdr    ; print header
  1469. xdfs2a:
  1470.     call    prfnfx    ; print file name in FNAMES.DIR
  1471.     dcx    b    ; count down
  1472.     mov    a,b    ; done?
  1473.     ora    c
  1474.     jz    xdfs2
  1475.     call    getdfn    ; get next name
  1476.     lda    crcnt    ; get entry counter
  1477.     inr    a    ; increment
  1478.     sta    crcnt
  1479.     ani    3    ; mask
  1480.     cz    crlfx    ; new line every 4
  1481.     jmp    xdfs2
  1482. xdfs3:
  1483.     mov    a,m    ; get user number
  1484.     ori    80h    ; mark it
  1485.     mov    m,a    ; put it back
  1486.     jmp    xdfs4
  1487. xdfs3a:
  1488.     call    getdfn    ; get next name
  1489.     dcx    b    ; count down on names
  1490. xdfs4:
  1491.     push    d    ; save count
  1492.     lxi    d,esize    ; pt to next entry
  1493.     dad    d
  1494.     pop    d    ; get count
  1495.     dcx    d    ; count down
  1496.     jmp    xdfs2    ; continue
  1497.  
  1498. ;  Mark rest of files in buffer
  1499. xdfs5:
  1500.     mov    a,d    ; check count
  1501.     ora    e
  1502.     jz    xdfs7
  1503.     dcx    d    ; count down
  1504.     mov    a,m    ; get user number
  1505.     ori    80h    ; mark it
  1506.     mov    m,a    ; put user number
  1507.     lxi    b,esize    ; skip to next file
  1508.     dad    b
  1509.     jmp    xdfs5    ; continue
  1510.  
  1511. ;  Name rest of files in FNAMES.DIR as missing
  1512. xdfs6:
  1513.     call    prfnfx    ; print file name in FNAMES.DIR
  1514.     dcx    b    ; count down
  1515.     mov    a,b    ; done?
  1516.     ora    c
  1517.     jz    xdfs7    ; next phase
  1518.     lda    crcnt    ; get entry counter
  1519.     inr    a    ; increment
  1520.     sta    crcnt
  1521.     ani    3    ; mask
  1522.     cz    crlfx    ; new line every 4
  1523.     call    getdfn    ; get next name
  1524.     jmp    xdfs6
  1525.  
  1526. ;  Part 2 of Scan - Name Additional Files
  1527. xdfs7:
  1528.     lda    fmark    ; no files printed?
  1529.     ora    a    ; 0=none
  1530.     jnz    xdfs7a
  1531.     call    printx
  1532.     db    '   No Files Missing',0
  1533. xdfs7a:
  1534.     xra    a    ; A=0
  1535.     sta    fmark    ; set mark for 2nd part
  1536.     call    printx
  1537.     db    cr,lf,'Additional Files on Disk NOT in FNAMES.DIR --',cr,lf,0
  1538.     lhld    fcount    ; get count of files
  1539.     xchg        ; ... in DE
  1540.     lhld    firstf    ; pt to first file
  1541.     xra    a    ; A=0
  1542.     sta    crcnt    ; set counter
  1543. xdfs8:
  1544.     mov    a,d    ; check count
  1545.     ora    e
  1546.     jz    xdfs9    ; done if zero
  1547.     dcx    d    ; count down
  1548.     mov    a,m    ; get user number
  1549.     ani    80h    ; marked?
  1550.     jz    xdfs8b    ; skip if not
  1551.     mov    a,m    ; get user number
  1552.     ani    7fh    ; mask
  1553.     mov    m,a    ; replace
  1554.     lda    fmark    ; first time?
  1555.     ora    a    ; 0=yes
  1556.     jnz    xdfs8a
  1557.     mvi    a,0ffh    ; set mark
  1558.     sta    fmark
  1559.     call    prfhdr    ; print header
  1560. xdfs8a:
  1561.     push    d    ; save count
  1562.     lxi    d,dfnbuf    ; copy to buffer for print
  1563.     mvi    b,12    ; 12 bytes
  1564.     call    moveb    ; copy
  1565.     pop    d
  1566.     call    prfnfx    ; print file name
  1567.     lda    crcnt    ; count down
  1568.     inr    a
  1569.     sta    crcnt
  1570.     ani    3    ; new line?
  1571.     cz    crlfx
  1572. xdfs8b:
  1573.     lxi    b,esize    ; pt to next entry
  1574.     dad    b
  1575.     jmp    xdfs8    ; continue
  1576.  
  1577. ;  Done with Scan
  1578. xdfs9:
  1579.     lda    fmark    ; no files printed?
  1580.     ora    a    ; 0=none
  1581.     jnz    xdfs9a
  1582.     call    printx
  1583.     db    '   No Additional Files',0
  1584. xdfs9a:
  1585.     call    printx
  1586.     db    cr,lf,'File Scan Complete',cr,lf,0
  1587.     jmp    return
  1588.  
  1589. ;
  1590. ;  Compare file name pted to by HL with that in DFNBUF; return with Z if same,
  1591. ;    C if (HL)<(DFNBUF)
  1592. ;
  1593. compfn:
  1594.     push    h    ; save regs
  1595.     push    d
  1596.     push    b
  1597.     lxi    d,dfnbuf    ; pt to buffer
  1598.     xchg        ; DE pts to file name, HL pts to DFNBUF
  1599.     push    h    ; save ptrs
  1600.     push    d
  1601.     mvi    b,11    ; compare FN and FT
  1602. cfn1:
  1603.     inx    h    ; pt to next
  1604.     inx    d
  1605.     mov    a,m    ; get char from DFNBUF
  1606.     ani    7fh    ; mask MSB
  1607.     mov    c,a    ; save in C
  1608.     ldax    d    ; get name in memory buffer
  1609.     ani    7fh    ; mask MSB
  1610.     cmp    c    ; compare to name in DFNBUF
  1611.     jnz    cfn2    ; not same, so exit with flag set
  1612.     dcr    b    ; count down
  1613.     jnz    cfn1
  1614.     pop    d    ; same so far, so compare user numbers
  1615.     pop    h
  1616.     mov    a,m    ; get user number
  1617.     ani    7fh    ; mask MSB
  1618.     mov    c,a    ; save in C
  1619.     ldax    d    ; get user number
  1620.     ani    7fh    ; mask MSB
  1621.     cmp    c    ; compare
  1622.     push    h    ; fill stack for ext
  1623.     push    h
  1624. cfn2:
  1625.     pop    h    ; clear stack
  1626.     pop    h
  1627.     pop    b    ; get regs and exit
  1628.     pop    d
  1629.     pop    h
  1630.     ret
  1631.  
  1632. ;
  1633. ;  General Utility Routines
  1634. ;
  1635.  
  1636. ;
  1637. ;  Print user and file name stored in DFNBUF for /Ff functions
  1638. ;
  1639. prfnfx:
  1640.     push    h    ; save regs
  1641.     push    d
  1642.     push    b
  1643.     lxi    h,dfnbuf    ; pt to first byte of buffer
  1644.     mov    a,m        ; get first byte (user number)
  1645.     lxi    d,numbuf    ; convert to chars in memory
  1646.     call    madc
  1647.     lxi    d,numbuf+1    ; pt to first char
  1648.     ldax    d    ; get it
  1649.     call    coutx
  1650.     inx    d    ; pt to 2nd char
  1651.     ldax    d    ; get it
  1652.     call    coutx
  1653.     mvi    a,' '    ; <SP>
  1654.     call    coutx
  1655.     inx    h    ; pt to FN
  1656.     mvi    b,8    ; 8 chars for FN
  1657.     call    prch
  1658.     mvi    a,'.'
  1659.     call    coutx
  1660.     mvi    b,3    ; 3 chars for FT
  1661.     call    prch
  1662.     mvi    a,' '    ; 2 <SP>
  1663.     call    coutx
  1664.     call    coutx
  1665.     pop    b    ; get regs
  1666.     pop    d
  1667.     pop    h
  1668.     ret
  1669. ;
  1670. ;  Get next User Number, FN, and FT from disk and save it in buffer
  1671. ;
  1672. getdfn:
  1673.     push    h    ; save regs
  1674.     push    d
  1675.     push    b
  1676.     lxi    h,dfnbuf    ; pt to buffer
  1677.     mvi    b,12    ; 12 bytes
  1678. getdf1:
  1679.     call    f1$get    ; get user
  1680.     jnz    geterr
  1681.     mov    m,a    ; store user
  1682.     inx    h    ; pt to next
  1683.     dcr    b    ; count down
  1684.     jnz    getdf1
  1685.     pop    b    ; restore regs
  1686.     pop    d
  1687.     pop    h
  1688.     ret
  1689. ;
  1690. ;  Print File Buffer Names Header Everywhere
  1691. ;
  1692. prfhdr:
  1693.     call    printx
  1694.     db    '     Horizontal Listing by File Name and Type',cr,lf
  1695.     db    ' U Filename.Typ  '
  1696.     db    ' U Filename.Typ  '
  1697.     db    ' U Filename.Typ  '
  1698.     db    ' U Filename.Typ',cr,lf
  1699.     db    ' - -------- ---  '
  1700.     db    ' - -------- ---  '
  1701.     db    ' - -------- ---  '
  1702.     db    ' - -------- ---',cr,lf,0
  1703.     ret
  1704. ;
  1705. ;  Get Error Message and Abort
  1706. ;
  1707. geterr:
  1708.     call    printx
  1709.     db    cr,lf,'Premature EOF -- Aborting',cr,lf,0
  1710.     jmp    return
  1711. ;
  1712. ;  Open FNAMES.DIR for byte-oriented input
  1713. ;
  1714. openin:
  1715.     lxi    d,fnfcb    ; open file
  1716.     call    fi1$open    ; open for input
  1717.     rz
  1718.     call    printx
  1719.     db    cr,lf,'FNAMES.DIR Not Found -- Aborting',cr,lf,0
  1720.     jmp    return
  1721. ;
  1722. ;  Print disk entry for normal directory display functions
  1723. ;
  1724. prentry:
  1725.     dcr    d    ; count <CRLF> counter
  1726.     jnz    prent1
  1727.     mvi    d,3    ; reset count
  1728.     call    crlfx
  1729. prent1:
  1730.     shld    entptr    ; save entry ptr
  1731.     lda    aflg    ; all users selected?
  1732.     ani    20h
  1733.     jz    prent2
  1734. ;
  1735. ;  The following prints the user number if all user numbers are selected
  1736. ;
  1737.     push    h    ; save regs
  1738.     push    d
  1739.     push    b
  1740.     mov    a,m    ; get user number
  1741.     ani    1fh    ; mask it
  1742.     lxi    d,numbuf
  1743.     call    madc    ; convert to chars in memory
  1744.     lxi    h,numbuf+1    ; pt to first char
  1745.     mov    a,m    ; get it
  1746.     call    coutx
  1747.     inx    h    ; get 2nd char
  1748.     mov    a,m
  1749.     call    coutx
  1750.     mvi    a,' '    ; print <SP>
  1751.     call    coutx
  1752.     pop    b    ; get regs
  1753.     pop    d
  1754.     pop    h
  1755. prent2:
  1756.     inx    h    ; pt to first char of file name
  1757.     mvi    b,8    ; print 8 chars
  1758.     call    prch
  1759.     mvi    a,'.'    ; print dot
  1760.     call    coutx
  1761.     push    h    ; save RS ptr
  1762.     mvi    b,3    ; print 3 chars
  1763.     call    prch
  1764.     push    d    ; save de
  1765.     lhld    entptr    ; pt to entry
  1766.     mvi    a,' '    ; skip 2 spaces
  1767.     call    coutx
  1768.     call    coutx
  1769.     call    fsize    ; compute file size
  1770.     lhld    totsiz    ; get total file size counter
  1771.     dad    d    ; add in new file
  1772.     shld    totsiz    ; save new total file size counter
  1773.     xchg        ; get file size into HL
  1774.     call    prhlx    ; print HL value
  1775.     pop    d    ; get de
  1776.     pop    h    ; pt to RS
  1777.     lda    rsflg    ; print RS fields?
  1778.     ora    a    ; Z=no
  1779.     jz    pren2a
  1780.     mvi    a,' '    ; print 1 space
  1781.     call    coutx
  1782.     mvi    b,'R'    ; letter
  1783.     call    prletx    ; print R if bit set
  1784.     inx    h
  1785.     mvi    b,'S'    ; letter
  1786.     call    prletx    ; print S if bit set
  1787.     dcx    h    ; ... for following inx h
  1788. pren2a:
  1789.     inx    h    ; point correctly
  1790.     mvi    a,' '    ; 1 space
  1791.     call    coutx
  1792.     lda    aflg    ; all users?
  1793.     ani    20h
  1794.     jnz    prent3
  1795. ;
  1796. ;  The following prints 2 additional spaces if only one user area is selected
  1797. ;
  1798.     mvi    a,' '    ; 2 more spaces for not all users
  1799.     call    coutx
  1800.     call    coutx
  1801. prent3:
  1802.     lxi    b,6    ; pt to next entry
  1803.     dad    b
  1804.     ret
  1805. ;
  1806. ;  Print B chars pted to by HL
  1807. ;
  1808. prch:
  1809.     mov    a,m    ; get char
  1810.     inx    h    ; pt to next
  1811.     ani    7fh    ; mask out msb
  1812.     cpi    ' '    ; within range?
  1813.     jnc    prch1    ; print special char if not valid char
  1814.     mvi    a,'?'    ; print ? if not valid char
  1815. prch1:
  1816.     call    coutx    ; print it
  1817.     dcr    b    ; count down
  1818.     jnz    prch
  1819.     ret
  1820. ;
  1821. ;  Extended Print Routines
  1822. ;
  1823. prletx:
  1824.     mov    a,m    ; get byte
  1825.     ani    80h    ; look at msb
  1826.     jz    prlets
  1827.     mov    a,b    ; get letter
  1828.     call    coutx
  1829.     ret
  1830. prlets:
  1831.     mvi    a,' '    ; print <sp>
  1832.     call    coutx
  1833.     ret
  1834. prhlx:
  1835.     lxi    d,numbuf    ; store in number buffer
  1836.     call    mhldc    ; hl into memory as decimal
  1837.     mvi    b,5    ; 5 digits
  1838. prnumx:
  1839.     lxi    h,numbuf    ; pt to buffer
  1840. prnum:
  1841.     mov    a,m    ; get digit
  1842.     inx    h    ; pt to next
  1843.     call    coutx    ; print everywhere
  1844.     dcr    b    ; count down
  1845.     jnz    prnum
  1846.     ret
  1847. printx:
  1848.     xthl        ; pt to string
  1849. prxl:
  1850.     mov    a,m    ; get byte
  1851.     inx    h    ; pt to next
  1852.     ora    a    ; done?
  1853.     jz    prxld
  1854.     call    coutx    ; print everywhere
  1855.     jmp    prxl
  1856. prxld:
  1857.     xthl        ; set ret adr
  1858.     ret
  1859. coutx:
  1860.     push    b    ; save bc
  1861.     push    psw    ; save char
  1862.     ani    7fh    ; mask out msb
  1863.     mov    b,a    ; char in B
  1864.     call    cout    ; print to screen
  1865.     lda    pflg    ; printer on?
  1866.     ora    a    ; 0=no
  1867.     mov    a,b    ; get char
  1868.     cnz    lout    ; printer output if on
  1869.     lda    dflg    ; disk on?
  1870.     ora    a    ; 0=no
  1871.     mov    a,b    ; get char
  1872.     cnz    f0$put    ; output to file
  1873.     pop    psw    ; get char
  1874.     pop    b    ; get bc
  1875.     ret
  1876. crlfx:
  1877.     push    psw    ; save A
  1878.     call    printx
  1879.     db    cr,lf,0
  1880.     pop    psw    ; get A
  1881.     ret
  1882. ;
  1883. ;  Divide DE by 3; return with BC=result*esize, a=remainder
  1884. ;
  1885. divde3:
  1886.     push    d    ; save de, hl
  1887.     push    h
  1888.     mvi    d,0    ; make sure D=0
  1889.     mov    a,e    ; value in A
  1890. divd31:
  1891.     sui    3    ; subtract 3
  1892.     jc    divd32
  1893.     jz    divd33
  1894.     inr    d    ; add 1 to result
  1895.     jmp    divd31
  1896. divd32:
  1897.     adi    3    ; add back in
  1898.     jmp    divd34
  1899. divd33:
  1900.     inr    d    ; add 1 for even division
  1901. divd34:
  1902.     sta    rem    ; save remainder
  1903.     lxi    b,esize
  1904.     lxi    h,0
  1905. divd35:
  1906.     mov    a,d    ; done?
  1907.     ora    a    ; 0=yes
  1908.     jz    divd36
  1909.     dcr    d
  1910.     dad    b    ; add in another ESIZE
  1911.     jmp    divd35
  1912. divd36:
  1913.     mov    b,h    ; BC is result
  1914.     mov    c,l
  1915.     lda    rem    ; A is remainder
  1916.     pop    h    ; restore regs
  1917.     pop    d
  1918.     ret
  1919. ;
  1920. ;  Skip blanks
  1921. ;
  1922. sblank:
  1923.     mov    a,m    ; pt to char
  1924.     cpi    ' '    ; blank?
  1925.     rnz
  1926.     inx    h    ; pt to next
  1927.     jmp    sblank
  1928.  
  1929.     end
  1930.