! APM FILES utility.     R Thonnes et al 6/84
! Parameters:
! Target is file name or names. Wild cards accepted in filename but not directory
! Default is all files for current directory.
! Output is output file name (default = console)
! Full   specifies that size and date info should be displayed for each file
! Order  may be by date or alphabetic
! Hide   specifies whether "hidden" files (beginning with '.') are to be
!        suppressed (default = yes)
! One line of total files and blocks in the directory is displayed when wild
! cards are used.
! If Totals is specified only this line is displayed.
!
! GDMR 02/02/87   Fixed to recognise hierarchic directories properly.
!                 Case-mangling "improved" slightly
! GDMR 09/02/87   NInfo removed from Util.Imp to here, with addition of
!                 event-3 trap
! JHB  21/04/88   Takes screen width from SCREENCOLS rather than assuming 80.
!                 Note o/p to files will retain this width.

option  "-nocheck-nodiag"
@16_3FA0 byte  screenrows,screencols
include  "inc:util.imp"
include  "inc:fs.imp"
include  "inc:fsutil.imp"

begin 

externalstring (255)fnspec  FINFO(string (255)directory,integer  number)


string (255)fn  Ninfo(string (255) filename)
   string (255) response = "Dummy"
      on  3 start 
         result  = filename . "    " . event_message
      finish 
      length(response) = fcommr('N' << 8, filename, charno(response, 1), 255)
      result  = response
end 


routinespec  files(string (255)target)

! PAM interface

constinteger  dateorder=1,alphaorder=2
string (255)target="",output="", s=""
integer  full=0,hide=16_80000000
byte  order=dateorder,tots=0

defineparam("Target",target,0)
defineparam("Output",output,pamnewgroup)
definebooleanparams("Full",full,0)
definebooleanparams("Hide",hide,0)
defineenumparam("Order,Date,Alpha",order,0)
define enum param("ALL,TOtals",tots,0) ;!JHB mod to display totals only.
processparameters(cliparam)

! Main program

openoutput(1,output) and  selectoutput(1) unless  output=""
files(target)

! End of main program

string (255)fn  standardise(string (255) s)
integer  i, case = 0
bytename  k
  result  = "" if  s = ""
  for  i = 1,1,length(s) cycle 
    k == charno(s,i)
    if  'A'<=k&95<='Z' start 
      k = k&95+case; case = 32
    else  if  k = ' '
      result  = s
    else 
      case = 0
    finish 
  repeat 
  result  = s
end 

predicate  split at last colon(string (255) what,
                               string (*)name  before, after)
   integer  i, pos = 0
      false  if  what = ""
      ! Look for the last colon
      for  i = 1, 1, length(what) cycle 
         pos = i if  charno(what, i) = ':'
      repeat 
      false  if  pos = 0;  ! None found
      before = sub string(what, 1, pos - 1)
      after = sub string(what, pos + 1, length(what))
      true 
end 


routine  files(string (255)target)
string (255)directory,file,thisfile, full name
  routine  dofiles
  recordformat  f(record (f)name  left,right,string (255)s)
  record (f)name  root, this
  constinteger  fieldwid=13
  integer  printed,maxperline

    routine  separate(integer  len)
      if  len<0 start 
        newline unless  printed=0; printed = 0
      elseif  printed=maxperline
        printed = 0; newline
      else 
        spaces(fieldwid-len)
      finish 
    end 

    record (f)map  add(record (f)name  cell,tree)
      result  == cell if  tree==nil
      if  cell_s<tree_s then  tree_left == add(cell,tree_left) c 
      else                   tree_right == add(cell,tree_right)
      result  == tree
    end 

    routine  print(record (f)name  tree)
      returnif  tree==nil
      print(tree_left)
      if  full=0 start 
        printstring(tree_s); printed = printed+1
        separate(length(tree_s))
      else 
        full name = directory . ":" . tree_s
        length(full name) = length(full name) - 1 c 
          if  charno(full name, length(full name)) = '?'
        printline(standardise(ninfo(full name)))
      finish 
      print(tree_right)
    end 

    predicate  hidden(string (*)name  s)
      falseif  hide=0 or  charno(file,1)='.'
      trueif  length(s)=0
      trueif  charno(s,1)='.'
      false 
    end 

    onevent  3,9 start 
      print(root)
      separate(-1)
      return 
    finish 

    printed=0
    maxperline = screencols//fieldwid
    root == nil
    cycle 
      readline(thisfile)
      thisfile = standardise(thisfile)
      unless  hidden(thisfile) start 
        if  matches(thisfile,file) start 
          if  order=alphaorder start 
            this == new(this)
            this_left == nil; this_right == nil; this_s = thisfile
            root == add(this,root)
          elseif  full=0
            printstring(thisfile); printed = printed+1
            separate(length(thisfile))
          else 
            full name = directory . ":" . this file
            length(full name) = length(full name) - 1 c 
              if  charno(full name, length(full name)) = '?'
            printline(standardise(ninfo(full name)))
          finish 
        finish 
      finish 
    repeat 
  end 

  onevent  3,4,9 start 
    printline(event_message)
    stop 
  finish 

  file = target and  directory = current directory unless  c 
    split at last colon(target, directory, file)
  file = "*" if  file=""
  if  wildness(file)>0 start 
    printline(finfo(directory,0))
    if  tots = 0 start 
       openinput(1, directory.":Directory")
       select input(1)
       dofiles
    finish 
  else 
    full name = directory . ":" . file
    length(full name) = length(full name) - 1 c 
      if  charno(full name, length(full name)) = '?'
    printline(standardise(ninfo(full name)))
  finish 
end 

endofprogram