  ------------------------------------------------------------------------
  FileUtil unit                             by Sebastian Groeneveld (2000)
  ------------------------------------------------------------------------

  Usage
  =====

  Add the following line to your program:

  $INCLUDE "FileUtil.inc"


  Constants
  =========

  'Mode numbers, used with OpenFile
  %Input        = 1
  %Output       = 2
  %Append       = 3
  %Random       = 4
  %Binary       = 5

  'Bit flag, used with OpenFile and CopyFile
  %Overwrite    = 128

  'Returned by CopyFile
  %Success      = -1     'File successfully copied
  %Err_Abort    =  1     'User or callback routine aborted
  %Err_Source   =  2     'Source file does not exist
  %Err_Target   =  3     'Target file exists and not allowed to overwrite
  %Err_Opening  =  4     'Unable to open source or target
  %Err_Other   >=  5     'Return value contains PB error code


  New datatype
  ============

  TYPE FileInfo
      Path      AS ASCIIZ * 261    'File's folder
      DOSName   AS ASCIIZ * 13     'DOS filename in 8.3 format
      LongName  AS ASCIIZ * 261    'Win9x long filename
      Attr      AS INTEGER         'File attribute
      Size      AS LONG            'File size
      Date      AS STRING * 10     'File date (mm-dd-yyyy)
      Time      AS STRING * 8      'File time (hh:mm:ss)
  END TYPE


  Public routines
  ===============

  -----
  FUNCTION Match( BYVAL S1 AS STRING, BYVAL S2 AS STRING ) AS INTEGER

  Returns -1 if S1 is equal to S2 (NOT case-sensitive)

  -----
  FUNCTION MatchStart( BYVAL S1 AS STRING, BYVAL S2 AS STRING ) AS INTEGER

  Returns -1 if S1 starts with S2 or vice versa (NOT case-sensitive). If
  any of both strings is a NULL string, it returns 0.

  -----
  FUNCTION Rinstr( BYVAL Main AS STRING, BYVAL Part AS STRING) AS INTEGER

  Returns last position of Part in Main. If Part begins with "ANY" the
  Main string is scanned for any character in Part, similar to the use
  of the ANY keyword with INSTR.

  -----
  FUNCTION MakePath( BYVAL PathName AS STRING ) AS STRING

  Returns a path name, ready for appending a filename. In fact it makes
  sure the PathName ends with a backslash (\).

  -----
  FUNCTION PathOf( BYVAL FileSpec AS STRING ) AS STRING

  Returns the path of the given file specification.
  "D:\Folder\Filename.Ext" would return "D:\Folder\"

  -----
  FUNCTION FileOf( BYVAL FileSpec AS STRING ) AS STRING

  Returns the file of the given file specification.
  "D:\Folder\Filename.Ext" would return "Filename.Ext"

  -----
  FUNCTION ExtensionOf( BYVAL FileSpec AS STRING ) AS STRING

  Returns the extension of the given file specification.
  "D:\Folder\Filename.Ext" would return "Ext"

  -----
  FUNCTION StripExtensionOf( BYVAL FileSpec AS STRING ) AS STRING

  Returns all but the extension of the given file specification.
  "D:\Folder\Filename.Ext" would return "D:\Folder\Filename"

  -----
  FUNCTION FileExists( BYVAL FileName AS STRING ) AS INTEGER

  Returns -1 if the specified file exists. You can also use long filenames
  if running under Win9x. It will not detect paths.

  -----
  FUNCTION PathExists( BYVAL PathName AS STRING ) AS INTEGER

  Returns -1 if the specified path exists. You can also use long filenames
  if running under Win9x. It will not detect files.

  -----
  FUNCTION GetFileInfo( BYVAL FileName AS STRING, I AS FileInfo ) AS INTEGER

  Returns -1 if the information could be read successfully. The information
  for the specified file is returned in I of type FileInfo (see above).
  Note that even if you use a relative path (eg. "..\") or no path at all,
  the variable I.path will be filled in correctly. You can also use long
  filenames.

  -----
  FUNCTION KillFile( BYVAL FileName AS STRING ) AS INTEGER

  This function deletes a file, even if it has the hidden, system or
  readonly attribute set. It returns -1 if the file no longer exists (or
  never existed). You can also use long filenames.

  -----
  FUNCTION OpenFile( BYVAL FileName AS STRING, BYVAL Mode AS INTEGER) _
                                                                 AS INTEGER

  Returns the PowerBasic file handle of the opened file. For Mode you can
  use any of the constants listed above. If you try to open a file for
  output (ie. write-access) and the file already exists, the call will fail
  and return 0, unless you add %Overwrite to the Mode. You can also use
  long filenames, even when creating a new file.

  -----
  SUB CloseFile( FileHandle AS INTEGER )

  This routine closes a file, and sets its FileHandle to zero.

  -----
  FUNCTION RenameFile( BYVAL Source AS STRING, BYVAL Target AS STRING ) _
                                                                 AS INTEGER

  Renames file Source to Target. It will fail if Source does not exist, or
  Target does. It returns -1 if the rename operation was successful. You can
  also use long filenames.

  -----
  FUNCTION CopyFile( BYVAL Source AS STRING  , BYVAL Target   AS STRING, _
                     BYVAL Mode   AS INTEGER , BYVAL Callback AS DWORD ) _
                                                                 AS INTEGER

  Copies a file to another destination. The target file will not be
  overwritten if it already exists, unless Mode is set to %Overwrite. You
  can also use long filenames. The Callback variable is a CODEPTR32 of any
  routine, that has been declared as follows:
      SUB AnyCallbackName ( Percentage AS INTEGER, Abortflag AS INTEGER )

  This routine will be called after each chunk that has been transferred.
  The first parameter passed to the callback routine contains the percentage
  that has been copied, the second parameter can be set to non-zero by the
  callback routine to abort the copy process. A useful purpose of this
  routine is to display a progress bar, or to abort when the user presses
  the Escape key.

  This routine is faster if you use a large string segment allocation size,
  which can be set with $STRING (default is 32k, largest possible value).
  The file's date/time stamp and the attributes will also be copied.

  The function returns %Success (-1) if the file has been copied succesfully.
  For other return value see the constants above.

  -----
  FUNCTION LFN( BYVAL FileName AS STRING, BYVAL Flags AS INTEGER) AS STRING

  Returns the long filename of any existing file. Flags is a bitmapped
  variable.
  If bit 0 is set, subst drives are not expanded.
  If bit 1 is set, only the filename is returned without pathname.
  This routine is copied from the WinLIB unit by 'Sureal - Ray'.

  -----
  FUNCTION SFN( BYVAL FileName AS STRING, BYVAL Flags AS INTEGER) AS STRING

  Returns the short filename of any existing file. Flags is a bitmapped
  variable.
  If bit 0 is set, subst drives are not expanded.
  If bit 1 is set, only the filename is returned without pathname.
  This routine is copied from the WinLIB unit by 'Sureal - Ray'.

  -----
  FUNCTION AttrString( BYVAL FileAttr AS INTEGER ) AS STRING

  This is just a fancy routine to convert a file attribute to a displayable
  string, in the form "RHSAD" or "_H_A_".

  -----
  FUNCTION MakeDOSFilename( BYVAL FileName   AS STRING,  _
                            BYVAL FakeWin95  AS INTEGER )  AS STRING

  This routine converts any filename to a proper DOS filename in 8.3 format.
  Spaces are removed, the file and extension are truncated separately and
  the path is also converted. If you set FakeWin95 to non-zero, the filename
  will be truncated using the Win95 style with a tilde and a digit. There is
  no guarantee however that this is the real short filename used for the
  given file in Win95.


  Example
  =======

  DIM i     AS FileInfo
  DIM F     AS STRING
  DIM Path  AS STRING

  Path = ".\"
  F = DIR$(Path + "*.*", 55)

  DO WHILE LEN(F)
      GetFileInfo Path + F, i

      PRINT USING "\      \ \ \  #########,  \        \  \      \  \   \"; _
          StripExtensionOf(i.DOSName); _
          ExtensionOf(i.DOSName); _
          i.Size; _
          i.Date; _
          i.Time; _
          AttrString(i.Attr)

      F = DIR$
  LOOP
