/**/
v="$VER: WFileList  Rexx FileList and WPL Freq List Creator Williamson 50.02"
/*
   Written for Russell McOrmond
   Based on Falcon File Manager by Robert Williamson 1:167/104.0
        Originally Modified for Falcon CBCS By Tony Jones (2:255/35)
        from Tim Aston's TransAmiga BBS script, FileUtil.trans

   The calling convention is: rx Wfilelist ALL|AREA|FREQ

            all    Creates and archives an all files listing
                   and a Wnotify/XfreqSh/RFS FREQ listing. 

            freq   Creates a Wnotify/XfreqSh/RFS FREQ listing. 
 
      Be sure to change the List command exclusion parameters (EXCLUDE)  
      for those files you want ignored in listings

    Config File Format: (bbslist)
    AREA 1
    NAME "Communications SOFTWARE"
    PATH "BBSFILES:comms/"
    PASSWORD areapassword               <---optional password for area
    
    area.text (areatext) format:
    Simple text file in EACH area, describing the scope of the area. 
    Each  line should begin with AT LEAST ONE SPACE and a blank line should
    terminate.

    file header (htext) format:
    Simple text file describing the system, You may include info on magic 
    filenames, freq times etc...Each line should begin 
    with AT LEAST ONE SPACE and a blank line should terminate.

    You NEED Andy Finkles' WB2 PIPE command.
*/

/* Your system name and address here */
system   = "Hysterics"
listnote = "Available files 1:163/109.0@fidonet, updated nightly"

default  = "  Sorry, there is no description for this area"||cr||cr
/*          ^^ spaces required! */

/* LIST exclusion parameters    */
EXCLUDE     =   '~(area.text|files.bbs|LZTEMP.#?|.info)'

/* WB2 List Lformat parameters  */
LFFREQ      =   '"%N %F%N"'                       /* freq.lst         */
LF_TWENTY   =   '"%-20N%7L %-9D %C"'              /* all files list   */
LF_THIRTY   =   '"%-30N %C"'                      /* areas.bbs        */

/* line wrap parameters */
FLLEN           =   77  /* list line length  */
MARGINALL       =   39  /* margin for LF_TWENTY  - wraptofile prepends a space  */

/*  You must create these files */
bbslist     = "RAM:fileareas.bbs"               /* filearea config  */
htext       = "CFG:filelistheader.txt"          /* System header */
mtext       = "CFG:MAGIC.TXT"                   /* FREQ Magic names */
areatext    = 'area.text'                       /* area description */

/* output files - edit names to suit */
freqlist     = "MAIL:freq.lst"                  /* filename, full path */
allfileslist = "MAIL:ATRONIX.LST"               /* Normal Level List */
allfilesarc  = "MAIL:ATRONIX.LHA"               /* Archived Normal List */

/* Rename this to something else if the     */
/* format used is not compatible with your  */
/* bbs software  (eg: TransAMiga, DLG )     */               
flist        = 'files.bbs'                      /* area desc and files */


/* Configuration of Magic File Names for FREQ List              */
/* Standard MAGIC FileNames That Never Change                   */
/* DO NOT change these entries, these are configured above      */
magic.1 = "FILES    > "allfilesarc                   /* configured above */
magic.2 = "NEWFILES >  Mail:newfiles"                /*  do it yourself  */
magic.3 = "NEW      >  Mail:newfiles"                /*  do it yourself  */
magic.4 = "MAGIC    > "mtext                         /* configured above */
magic.5 = "ABOUT    > "htext                         /* configured above */

/* add your FIXED MAGIC names here */
magic.6     = "ROOFREXX > bbsf6:ROOF/ROOF_REXX.LHA"
magic.7     = "ROOFDOS  > bbsf6:ROOF/ROOF_DOS.LHA"
magic.8     = "ROOFDOCS > bbsf6:ROOF/ROOF_DOCS.LHA"
magic.9     = "ROOFBIN  > bbsf6:ROOF/ROOF_BIN.LHA"
magic.10    = "ROOFRCP  > bbsf6:ROOF/ROOF_RCP.LHA"
magic.11    = "ROOFWPL  > BBSF6:ROOF/ROOF_WPL.LHA"
magic.12    = "ROOF     > BBSF6:ROOF/ROOF.LHA"

/* FileNames that require updating to the latest version should */
/* use '^' instead of '>'                                       */
magic.13    = "FILEMGR      ^ BBSF6:ROOF/FILEMGR_V??.??.LHA"
magic.14    = "FANSI        ^ BBSF2:G&S/FANSI_V?.?.LHA"
magic.15    = "DEKSID       ^ BBSF6:DUTIL/DEK???.LHA"
magic.16    = "BBSLIST      ^ BBSF5:MTL-BBS/BBS?????.LST"

/* Where more than one file will be sent for a MAGIC name       */
/* just have multiple entries pointing to same magic name       */
magic.17 = "WELMAT          > BBSF6:WPL_INTRO.LZH"

/* Password Protected Files */
magic.18 = "PFILES !geewiz     BBS:text/Private.list"
magic.19 = "AFILES !bobo       BBS:text/Assist.list"

magic.20 = "MAILSCAN        > BBSF6:FALCON/MailScan_v1.39.LHA"
magic.21 = "ROOFBBS         > bbsf6:ROOF/Roof_BBS.LHA"
magic.22 = "ROOFRCP         > BBSF6:ROOF/ROOF_RCP.LHA"
magic.23 = "ROOFTA          > BBSF6:ROOF/ROOF_TA.LHA"
magic.24 = "ROOFDLG         > BBSF6:ROOF/ROOF_DLG.LHA"

magic.25 = "AREAMGR         ^ BBSF6:ROOF/AM_v????.LHA"
magic.26 = "CFG             > CFG:ROOF.WPL"
magic.27 = "CFG             > CFG:ROOF.CFG"
magic.28 = "BTC             > S:BTC"
magic.29 = "WPL !hoho         BBSF6:WPL/WPL_INTRO.LZH"
magic.30 = "RFS             > BBSF6:WPL/RFS.LHA"
magics = 30
magic.0 = 30
/* NUMBER of MAGIC NAMES */

/* used internally */
fileslist    = "T:ALST-"Pragma('ID')            /* temporary all file */
freqtmp      = "T:FLST-"Pragma('ID')            /* temporary freq list */
msgtmp       = "T:MLST-"Pragma('ID')            /* temporary area list */


script  = "WFileList"
ver     = "v"||right(sv),5)
cr      = '0a'x
CSI     = '9b'x
OFF     = CSI||'0m'
BOLD    = CSI||'1m'
ULINE   = CSI||'4m'
ITALICS = CSI||'3;40m'
quote   = '"'

fmvers  = BOLD||'[36;40m'script ver||OFF

options results
options failat 20

signal on halt
signal on ioerr
signal on break_c
signal on break_d

if ~show("L", "rexxsupport.library") then
    if ~addlib("rexxsupport.library", 0, -30, 0) then
        do
                say "Couldn't access support.library !"
                exit 20
        end

    call close 'STDIN';call open 'STDIN','*','R'

    if ~open('dlst',bbslist, 'R') then
    do
        say "Couldn't open fileareas list !"
        exit 20
    end

parse upper arg fcmd
    if fcmd = "" then call usage
    say cr||ITALICS||" "fmvers||cr||" by Robert Williamson 1:167/104.0@fidonet"||OFF||cr
    lopt=upper(strip(fcmd))              /* LIST type */

    /* Start Area Processing */
    say 'Reading fileareas'
    area = 0
    do while ~eof('dlst')
        blstln=readln('dlst')
        if blstln="" then iterate
        blstkey=upper(left(blstln, 4))
        select
            when blstkey = 'AREA' then
            do
                area=area+1
                Number.area=strip(word(blstln,2) )
            end
            when blstkey= 'NAME' then Name.area=strip( substr(blstln,6,79) )
            when blstkey= 'PATH' then Path.area=strip( substr(blstln,6,40) )
            when blstkey= 'PASS' then Password.area=strip(word(blstln,2) )
            otherwise  nop
            /*say 'Keyword 'blstkey 'not processed'     */
        end  /* select */
    end /*eof*/
    areas=area
    say 'Found 'areas' file areas'

    if lopt = 'ALL' then
    do
        /* open all file listing, put title, date */
        /* and system header in files list */
        say ULINE||"Generating All Files Listing for "system ||OFF ; say
        datum = delstr(space(date(), 1, "-"), 8, 2) time()
        tmpnorm=fileslist'NORMAL'

        say 'Adding header to 'tmpnorm
        open('tbl', tmpnorm, 'W')
        call writech 'tbl', " "fmvers" by Robert Williamson 1:167/104.0@fidonet" ||cr
        call writech 'tbl', " FileListing for" system  datum ||cr ||cr
        close('tbl')

        if ~exists('htext') then
        do
            say 'Adding headerfile' htext 'to 'tmpnorm
            com= 'Type >> "'tmpnorm'" "'htext'"'
            address COMMAND com
        end

        call open_freq

        call process_cmd(areas)

        if exists(freqtmp) then call close_freq

        tmpnorm=fileslist'NORMAL'
    
        address COMMAND 'Copy' tmpnorm allfileslist
        address COMMAND 'FileNote "'allfileslist'" "'listnote'"'

        say 'Archiving 'allfileslist' as 'allfilesarc
        address COMMAND 'lha -2 f "'allfilesarc'" "'allfileslist'"'
        address COMMAND 'FileNote "'allfilesarc'" "'listnote'"'
        say lopt||' File Listing completed'

    end
    if lopt = "FREQ" then 
    do
        call open_freq
        call process_cmd(areas)
        if exists(freqtmp) then call close_freq   
    end
    else call usage
cleanup:
    call delete(fileslist)
    call delete(freqtmp)      
    call delete(msgtmp)
exit 
   
open_freq:
    say ULINE||"Generating File Request Listing for "system ||OFF ; say
    if ~exists(mtext) then
    do
        call open('lstf',freqtmp,'W')      /* create the file */
        call close('lstf')                 /* delete old one  */
    end
    else do
        address COMMAND 'Copy' mtext freqtmp
    end
    if (magics ~= 0) then call do_magic
return

do_magic:
    CR='0a'x
    if ~open('tfl',freqtmp,'A') then
    do
        Say 'Unable to open 'freqtmp
        call cleanup
        exit 10
    end
    say 'Updating 'magics' Magic names'
    do i=1 to magics
        /*                                                  file/magicname           !password                fullpath */
        if left(word(magic.i,2),1) = '!' then writech('tfl',strip(word(magic.i,1))' 'strip(word(magic.i,2))' 'strip(word(magic.i,3))||CR)
            else if word(magic.i,2) = '>' then writech('tfl',strip(word(magic.i,1))' 'strip(word(magic.i,3))||CR)
        if word(magic.i,2) = '^' then
        do
            close('tfl')
            cmd='List >>'freqtmp word(magic.i,3) LFORMAT '"'word(magic.i,1)' %P%N"'
            address COMMAND cmd
            open('tfl',freqtmp,'A')
        end
    end
    call close('tfl')
return

close_freq:
    address COMMAND 'SORT' freqtmp freqlist   
    if exists("RAM:FREQ.LST") then address COMMAND 'Copy' freqlist "RAM:FREQ.LST"         
    say lopt||' Freq Listing completed'
return

process_cmd:
    areas=arg(1)
    say areas' areas found'
    do area=1 to areas
        if area ~= 0 then
        do
            /* Display info on a area */
            say BOLD||'Area       '||OFF Number.area
            say BOLD||'Name       '||OFF Name.area
            say BOLD||'Path       '||OFF Path.area
            say BOLD||'Password   '||OFF Password.area
            say
            if lopt='FREQ' then
            do
                if Password.area = "PASSWORD."area | Password.area = "" then 
                do
                    address COMMAND 'List >>"'freqtmp'"' Path.area||exclude 'FILES NOHEAD LFORMAT='LFFREQ
                end
                else do
                    SAY 'Area:'area 'Password:'Password.area
                    address COMMAND 'List >>"'freqtmp'"' Path.area||exclude 'FILES NOHEAD LFORMAT="%N !'Password.area' %F%N"'
                end
            end
            else if lopt = 'ALL' then
            do
                if Password.area ~= "PASSWORD."||area then iterate
                dir=addslash(dequote(Path.area))
                /* Update an areas files.bbs from the filenotes */
                listandsort(dir,dir||flist,LF_THIRTY)
                addareatext(dir,dir||flist,areatext,dir||flist,'prepend')

                say 'Appending 'dir Number.area Name.area' to 'fileslist
                btarea=center("AREA: "Number.Area,21)
                btitle=center(Name.Area,41)
                call appendtolist(fileslist,CR||CR)
                call appendtolist(fileslist,'ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¸'||CR)
                call appendtolist(fileslist,'³ °°°°°±±±±±²²²²²ÛÛÛÛÛ²²²²²³'btarea'³²²²²²ÛÛÛÛÛ²²²²²±±±±±°°°°° ³'||CR)
                call appendtolist(fileslist,'ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´'||CR)
                call appendtolist(fileslist,'³ °°°°°±±±±±²²²²²³'btitle'³²²²²²±±±±±°°°°° ³'||CR)
                call appendtolist(fileslist,'ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¾'||CR)
                call listandsort(dir,msgtmp,LF_TWENTY)
                call addareatext(dir,msgtmp,areatext,msgtmp.'prepend')

                /*
                 Appends and wordwraps an files.bbs or newfiles.tmp to an
                 allfiles list or message
                 a leading space is pre-pended, comment lines are not wrapped
                */
                if ~open('ifn',msgtmp,'R') then
                do
                    say 'wraptofile:Cannot open 'msgtmp
                    exit 10
                end
            
                if ~open('ofn',fileslist,'A') then
                do
                    say 'wraptofile:Cannot open 'fileslist
                    exit 10
                end
            
                do while ~eof('ifn')
                    line    = readln('ifn')
                    if left(line,1) ~= " " then
                    do
                        /* add leading space */
                        writech('ofn',' 'wrap_line(line,FLLEN,MARGINALL)) 
                    end /* not a comment line */
                    else do
                            writech('ofn',line||cr)
                    end /* was a comment line */
                end /*eof */
                call close('ifn')
                call close('ofn')
                if Password.area = "PASSWORD."area | Password.area = "" then 
                do
                    address COMMAND 'List >>"'freqtmp'"' Path.area||exclude 'FILES NOHEAD LFORMAT='LFFREQ
                end
                else do
                    SAY 'Area:'area 'Password:'Password.area
                    address COMMAND 'List >>"'freqtmp'"' Path.area||exclude 'FILES NOHEAD LFORMAT="%N !'Password.area' %F%N"'
                end
            end
        end
    end
return 0

listandsort:
/* list <tdir> with <lfmt> and sort to <tfile> */
    tdir        =       arg(1)
    tfile       =       arg(2)
    lfmt    =       arg(3)
    las =   'PIPE LIST 'tdir||exclude' FILES NOHEAD LFORMAT 'lfmt' | SORT In: 'tfile
    address command las
return 0

/* add a line to a file list                */
/* appendtolist(outputfilename, 'string')   */
appendtolist:
    outfn=dequote(arg(1))

    if ~exists(outfn) then
    do
        say 'appendtolist:Cannot append to 'outfn
        return 20
    end
    else do
        open('tlst',outfn,'A')
        call writech('tlst',arg(2))
        close('tlst')
    end
return 0

/* prepend area.text to files.bbs                               */
/*    addareatext(dir,files.bbs,area.text,output)               */
/*    addareatext(dir,files.bbs,area.text,output,where)         */
/* where= append or prepend(DEFAULT)                            */
/*  example:                                                    */
/*    call addareatext(Path.area,availlist,areatext,availlist)  */
addareatext:
    inlist      =   arg(2)
    descfile    =   addslash(dequote(arg(1)))||arg(3)
    tolist      =   arg(4)
    where       =   arg(5)

    if ~exists(inlist) then
    do
        say 'addareatext: cannot find 'inlist
        return 20
    end
    
    if ~exists(descfile) then
    do
        say 'addareatext: cannot find 'descfile' using 'default 
        if where='append' then
        do
            call open('ds',descfile,'a')
            call writech('ds',default)
        end
        else do
            call open('ds',descfile,'w')
            call writech('ds',default)
        end
        call close('ds')  
    end
    if where = 'append' then
    do
        call join(inlist,descfile,tolist)
    end
    else do
        call join(descfile,inlist,tolist)
    end
return 0

wrap_line:
    text        =   arg(1)
    right_edge  =   arg(2)  /* line length */
    left_edge   =   arg(3)  /*   margin    */

    new_text = ''

    do while length(text) > 0
        broken_word = 0
        if length(text) < right_edge then
        do
            new_text = new_text || text || '0a'x
            text = ''
        end
        else do
            temp_text = strip(text,l)
            diff = length(text) - length(temp_text)
            first_break = lastpos(' ',temp_text,right_edge - diff)
            break_point = first_break + diff
            if left_edge = break_point then
            do
                break_point = right_edge - 1
                broken_word = 1
            end

            new_text = new_text || strip(left(text,break_point),t)
            if broken_word then
            do
                new_text = new_text || '-'
            end
            new_text = new_text || '0a'x
            text = copies(' ',left_edge) || strip(right(text,length(text) - break_point),l)
        end
    end
return new_text

/* general procedures */

/*
        join -- a 'front end' for join. Fixes a problem with join.
        uses a tempfile if target filename is same as one to cat
*/
join:
    x=arg(1)' 'arg(2)' 'arg(3)
    temp = 'arexxtempfile'
    do i=1 to (words(x)-1)
        if word(x,i) = word(x,words(x)) then
        do
            oops = word(x,words(x))
            x = delword(x,words(x))||'TO '||temp
            address COMMAND 'Join' x
            address COMMAND 'Copy ' temp ' ' oops
            call delete(temp)
            return 0
        end
    end
    x=arg(1)' 'arg(2)' TO 'arg(3)
    address COMMAND 'Join' x
return 0

addslash:
    curr = arg(1)
    select
        when right(curr, 1) = ":" then nop
            when right(curr, 1) = "/" then nop
                otherwise curr = curr"/"
    end
return curr

/* a useful procedure by Walt Sullivan  */
dequote:
    parse arg thing
    parse var thing '"' unq_thing '"'
    if unq_thing ~= "" then return unq_thing
return thing

usage:
    say 'The calling convention is: rx Wfilelist ALL|AREA'
    say '    freq  Creates freq list'
    say '    all   Creates and archives an all files listing'
    say '          and a Wnotify FREQ listing.' 
    exit 0
end
/*
  Error handling
*/

halt:
ioerr:
break_c:
break_d:
    call writech(stdout,cr)
    exit 10

