UNIT FileReco;
  {-Provides the FileRecord object, for storing data about files,-}
  {-and the FileRecordList object, a collection of FileRecords.  -}
  {-Directories are stored using a pointer to a PStrCollection   -}
  {-and an index into that collection.  The directory collection -}
  {-must be complete *BEFORE* using these objects, and must not  -}
  {-be changed while these objects are in use.                   -}
(**) INTERFACE (**)
USES WinTypes, WinProcs, WObjects, Strings;
TYPE
  PFileRecord = ^TFileRecord;
  TFileRecord = OBJECT(TObject)
    Name       : PChar;   {-Filename and extension only           -}
    Flags      : Byte;    {-Bit 0 for directory; bit 1 for changed-}
    Dir        : Word;    {-Index into DL; indicates the home ... -}
    DL         : PStrCollection; {-directory for this file.       -}
    Time, Size : LongInt; {-Date/time stamp and file size.        -}
    CONSTRUCTOR Init(iName : PChar; yesDir : Boolean; iDir : Word;
      iTime, iSize : LongInt; iDL : PStrCollection);
    DESTRUCTOR Done; Virtual;
    PROCEDURE SetChanged;
    FUNCTION GetDir    : Word;
    FUNCTION GetTime   : LongInt;
    FUNCTION GetSize   : LongInt;
    FUNCTION GetName   : PChar;
    FUNCTION IsDir     : Boolean;
    FUNCTION IsChanged : Boolean;
    FUNCTION GetFullName(P : PChar) : PChar;
  END;

  PFileRecordList = ^TFileRecordList;
  TFileRecordList = OBJECT(TSortedCollection)
      {-A sorted collection of PFileRecords-}
    FUNCTION Compare(Key1, Key2 : Pointer) : Integer; Virtual;
  END;

  PStrICollection = ^TStrICollection;
  TStrICollection = OBJECT(TStrCollection)
      {-Just like a TStrCollection, but Compare is case-insensitive-}
    FUNCTION Compare(Key1, Key2 : Pointer) : Integer; Virtual;
  END;

(**) IMPLEMENTATION (**)
CONST
  fr_Dir     = 1;
  fr_Changed = 2;
{--------------------------------------------------}
{ TFileRecordList's methods                        }
{--------------------------------------------------}

  FUNCTION TFileRecordList.Compare(Key1, Key2 : Pointer) : Integer;
  VAR
    K1 : PFileRecord ABSOLUTE Key1;
    K2 : PFileRecord ABSOLUTE Key2;
  BEGIN
      {-The list of directories is sorted, so if the Dir field of-}
      {-one PFileRecord is less/greater than that of another, the-}
      {-whole record is considered less/greater.  If Dir is the  -}
      {-same, less/greater is determined by a case-insensitive   -}
      {-comparison of the filenames.                             -}
    IF K1^.GetDir < K2^.GetDir THEN Compare := -1
    ELSE IF K1^.GetDir > K2^.GetDir THEN Compare := 1
    ELSE Compare := StrIComp(K1^.GetName, K2^.GetName);
  END;

{--------------------------------------------------}
{ TFileRecord's methods                            }
{--------------------------------------------------}
  CONSTRUCTOR TFileRecord.Init(iName : PChar; yesDir : Boolean;
    iDir : Word; iTime, iSize : LongInt; iDL : PStrCollection);
  BEGIN
    TObject.Init;
    Name  := StrNew(iName);
    Flags := Ord(yesDir);
    Dir   := iDir;
    Time  := iTime;
    Size  := iSize;
    DL    := iDL;
  END;

  DESTRUCTOR TFileRecord.Done;
  BEGIN
    StrDispose(Name);
    TObject.Done;
  END;

  PROCEDURE TFileRecord.SetChanged;
  BEGIN Flags := Flags OR fr_Changed; END;

  FUNCTION TFileRecord.GetDir : Word;
  BEGIN GetDir := Dir; END;

  FUNCTION TFileRecord.GetTime : LongInt;
  BEGIN GetTime := Time; END;

  FUNCTION TFileRecord.GetSize : LongInt;
  BEGIN GetSize := Size; END;

  FUNCTION TFileRecord.GetName : PChar;
  BEGIN GetName := Name; END;

  FUNCTION TFileRecord.GetFullName(P : PChar) : PChar;
    {-PChar P must be allocated by CALLING routine.-}
  BEGIN
    StrCopy(P, PChar(DL^.At(Dir)));
    StrCat(P, Name);
    GetFullName := P;
  END;

  FUNCTION TFileRecord.isDir : Boolean;
  BEGIN IsDir := Flags AND fr_Dir <> 0; END;

  FUNCTION TFileRecord.isChanged : Boolean;
  BEGIN IsChanged := Flags AND fr_Changed <> 0; END;

{--------------------------------------------------}
{ TStrICollection's methods                        }
{--------------------------------------------------}
  FUNCTION TStrICollection.Compare(Key1, Key2: Pointer): Integer;
  BEGIN
    Compare := StrIComp(Key1, Key2);
  END;

END.