[Back to DIRS SWAG index] [Back to Main SWAG index] [Original]
{ Updated DIRS.SWG on February 15, 1994 }
Unit PDir;
(*
Palcic Directory Routines
Copyright (C) 1989, Matthew J. Palcic
Requires Turbo Pascal 5.5 or higher
v1.0, 18 Aug 89 - Original release.
*)
INTERFACE
uses Dos,Objects;
(*------------------------------------------------------------------------*)
TYPE
AttrType = Byte;
FileStr = String[12];
BaseEntryPtr = ^BaseEntry;
BaseEntry = object(Node)
Attr: AttrType;
Time: Longint;
Size: Longint;
Name: FileStr;
constructor Init;
destructor Done; virtual;
procedure ConvertRec(S:SearchRec);
function FileName: FileStr; virtual;
function FileExt: ExtStr; virtual;
function FullName: PathStr; virtual;
function FileTime: Longint; virtual;
function FileAttr: AttrType; virtual;
function FileSize: Longint; virtual;
function IsDirectory: Boolean;
constructor Load(var S: Stream);
procedure Store(var S: Stream); virtual;
end;
FileEntryPtr = ^FileEntry;
FileEntry = object(BaseEntry)
constructor Init;
destructor Done; virtual;
procedure ForceExt(E:ExtStr);
procedure ChangeName(P:PathStr); virtual;
(* Change the name in memory *)
procedure ChangePath(P:PathStr); virtual;
procedure ChangeTime(T:Longint); virtual;
procedure ChangeAttr(A:AttrType); virtual;
procedure Erase; virtual;
function Rename(NewName:PathStr): Boolean; virtual;
(* Physically rename file on disk, returns False if Rename fails *)
function ResetTime: Boolean;
function ResetAttr: Boolean;
function SetTime(T:Longint): Boolean; virtual;
function SetAttr(A:AttrType): Boolean; virtual;
constructor Load(var S: Stream);
procedure Store(var S: Stream); virtual;
end;
DirEntryPtr = ^DirEntry;
DirEntry = object(FileEntry)
DirEntries: List;
constructor Init;
constructor Clear;
destructor Done; virtual;
procedure FindFiles(FileSpec: FileStr; Attrib: AttrType);
procedure FindDirectories(FileSpec: FileStr; Attrib: AttrType);
constructor Load(var S: Stream);
procedure Store(var S: Stream); virtual;
end;
DirStream = object(DosStream)
procedure RegisterTypes; virtual;
end;
function ExtensionPos(FName : PathStr): Word;
function CurDir: PathStr;
function ReadString(var S: Stream): String;
procedure WriteString(var S: Stream; Str: String);
(*------------------------------------------------------------------------*)
IMPLEMENTATION
(*--------------------------------------------------------------------*)
(* Methods for BaseEntry *)
(*--------------------------------------------------------------------*)
constructor BaseEntry.Init;
begin
end;
destructor BaseEntry.Done;
begin
end;
procedure BaseEntry.ConvertRec;
begin
Name := S.Name;
Size := S.Size;
Time := S.Time;
Attr := S.Attr;
end;
function BaseEntry.FileName;
begin
FileName := Name;
end;
function BaseEntry.FullName;
begin
FullName := Name;
end;
function BaseEntry.FileExt;
var
ep: word;
begin
ep := ExtensionPos(Name);
if ep > 0 then
FileExt := Copy(Name, Succ(ep), 3)
else
FileExt[0] := #0;
end;
function BaseEntry.FileAttr;
begin
FileAttr := Attr;
end;
function BaseEntry.FileSize;
begin
FileSize := Size;
end;
function BaseEntry.FileTime;
begin
FileTime := Time;
end;
function BaseEntry.IsDirectory;
begin
IsDirectory := (FileAttr and Dos.Directory) = Dos.Directory;
end;
constructor BaseEntry.Load;
begin
S.Read(Attr,SizeOf(Attr));
S.Read(Time,SizeOf(Time));
S.Read(Size,SizeOf(Size));
Name := ReadString(S);
end;
procedure BaseEntry.Store;
begin
S.Write(Attr,SizeOf(Attr));
S.Write(Time,SizeOf(Time));
S.Write(Size,SizeOf(Size));
WriteString(S,Name);
end;
(*--------------------------------------------------------------------*)
(* Methods for FileEntry *)
(*--------------------------------------------------------------------*)
constructor FileEntry.Init;
begin
BaseEntry.Init; (* Call ancestor's Init *)
Name := '';
Size := 0;
Time := $210000; (* Jan. 1 1980, 12:00a *)
Attr := $00; (* ReadOnly = $01;
Hidden = $02;
SysFile = $04;
VolumeID = $08;
Directory = $10;
Archive = $20;
AnyFile = $3F; *)
end;
destructor FileEntry.Done;
begin
BaseEntry.Done;
end;
function FileEntry.Rename;
var
F: File;
begin
Assign(F,FullName);
System.Rename(F,NewName); (* Explicit call to 'System.Rename' avoid
calling method 'FileEntry.Rename' *)
if IOResult = 0 then
begin
ChangePath(NewName);
Rename := True;
end
else
Rename := False;
end;
procedure FileEntry.ForceExt;
var
ep: Word;
TempBool: Boolean;
begin
ep := ExtensionPos(FullName);
if ep > 0 then
TempBool := Rename(Concat(Copy(FullName, 1, ep),FileExt))
else
TempBool := Rename(Concat(FullName,'.',FileExt));
end;
procedure FileEntry.ChangeName;
begin
Name := P;
end;
procedure FileEntry.ChangePath;
begin
Name := P; (* FileEntry object does not handle path *)
end;
procedure FileEntry.ChangeTime;
begin
Time := T;
end;
procedure FileEntry.ChangeAttr;
begin
Attr := A;
end;
procedure FileEntry.Erase;
var
F:File;
begin
Assign(F,FullName);
Reset(F);
System.Erase(F); (* Remove ambiguity about 'Erase' call *)
Close(F);
end;
function FileEntry.ResetTime;
var
F:File;
begin
Assign(F,FullName);
Reset(F);
SetFTime(F,FileTime);
ResetTime := IOResult = 0;
Close(F);
end;
function FileEntry.SetTime;
var
F:File;
begin
Assign(F,FullName);
Reset(F);
SetFTime(F,T);
SetTime := IOResult = 0;
Close(F);
end;
function FileEntry.ResetAttr;
var
F:File;
begin
Assign(F,FullName);
SetFAttr(F,FileAttr);
ResetAttr := IOResult = 0;
end;
function FileEntry.SetAttr;
var
F:File;
begin
ChangeAttr(A);
SetAttr := ResetAttr;
end;
constructor FileEntry.Load;
begin
BaseEntry.Load(S);
end;
procedure FileEntry.Store;
begin
BaseEntry.Store(S);
end;
(*--------------------------------------------------------------------*)
(* Methods for DirEntry *)
(*--------------------------------------------------------------------*)
constructor DirEntry.Init;
var
TempNode: Node;
begin
FileEntry.Init;
DirEntries.Delete;
end;
destructor DirEntry.Done;
begin
DirEntries.Delete;
FileEntry.Done;
end;
constructor DirEntry.Clear;
begin
DirEntries.Clear;
Init;
end;
procedure DirEntry.FindFiles;
var
DirInfo: SearchRec;
TempFile: FileEntryPtr;
begin
FindFirst(FileSpec,Attrib,DirInfo);
while (DosError = 0) do
begin
TempFile := New(FileEntryPtr,Init);
TempFile^.ConvertRec(DirInfo);
DirEntries.Append(TempFile);
FindNext(DirInfo);
end;
end;
procedure DirEntry.FindDirectories;
var
DirInfo: SearchRec;
TempDir: DirEntryPtr;
begin
if FileSpec <> '' then
FindFiles(FileSpec,Attrib and not Dos.Directory);
FindFirst('*.*',Dos.Directory,DirInfo);
while (DosError = 0) do
begin
if (DirInfo.Name[1] <> '.') and
((DirInfo.Attr and Dos.Directory) = Dos.Directory) then
{ if first character is '.' then name is either '.' or '..' }
begin
TempDir := New(DirEntryPtr,Clear);
TempDir^.ConvertRec(DirInfo);
DirEntries.Append(TempDir);
end;
FindNext(DirInfo);
end;
TempDir := DirEntryPtr(DirEntries.First);
while TempDir <> nil do
begin
if TempDir^.IsDirectory then
begin
ChDir(TempDir^.FileName);
TempDir^.FindDirectories(FileSpec,Attrib);
ChDir('..');
end;
TempDir := DirEntryPtr(DirEntries.Next(TempDir));
end;
end;
constructor DirEntry.Load;
begin
FileEntry.Load(S);
DirEntries.Load(S);
end;
procedure DirEntry.Store;
begin
FileEntry.Store(S);
DirEntries.Store(S);
end;
(*--------------------------------------------------------------------*)
(* Methods for DirStream *)
(*--------------------------------------------------------------------*)
procedure DirStream.RegisterTypes;
begin
DosStream.RegisterTypes;
Register(TypeOf(BaseEntry),@BaseEntry.Store,@BaseEntry.Load);
Register(TypeOf(FileEntry),@FileEntry.Store,@FileEntry.Load);
Register(TypeOf(DirEntry),@DirEntry.Store,@DirEntry.Load);
end;
(*---------------------------------------------------------------------*)
(* Miscellaneous Unit procedures and functions *)
(*---------------------------------------------------------------------*)
function ExtensionPos;
var
Index: Word;
begin
Index := Length(FName)+1;
repeat
dec(Index);
until (FName[Index] = '.') OR (Index = 0);
IF (Pos('\', Copy(FName, Succ(Index), SizeOf(FName))) <> 0) THEN Index := 0;
ExtensionPos := Index;
end;
function CurDir;
var
P: PathStr;
begin
GetDir(0,P); { 0 = Current drive }
CurDir := P;
end;
function ReadString;
var
T: String;
L: Byte;
begin
S.Read(L, 1);
T[0] := Chr(L);
S.Read(T[1], L);
IF S.Status = 0 then
ReadString := T
else
ReadString := '';
end;
procedure WriteString;
begin
S.Write(Str, Length(Str) + 1);
end;
(* No initialization code *)
end.
{=============================== DEMO ============================ }
program PDTest;
uses Objects,PDir,Dos;
var
DP: DirEntryPtr;
St: DirStream;
Orig: PathStr;
procedure ProcessDir(D: DirEntryPtr; DirName: PathStr);
var
DirPtr : DirEntryPtr;
begin
DirPtr := DirEntryPtr(D^.DirEntries.First);
while DirPtr <> nil do
begin
if DirPtr^.IsDirectory then
ProcessDir(DirPtr,DirName+'\'+DirPtr^.FileName)
{recursively process subdirectories}
else
WriteLn(DirName+'\'+DirPtr^.FileName);
DirPtr := DirEntryPtr(D^.DirEntries.Next(DirPtr));
end;
end;
begin
Orig := CurDir;
WriteLn('Palcic''s File Finder v1.0');
if ParamCount = 0 then { Syntax is incorrect }
begin
WriteLn;
WriteLn('Syntax: PFF filespec');
WriteLn;
WriteLn('Directory names can not be passed.');
WriteLn;
WriteLn('Example: PFF *.ZIP');
WriteLn;
Halt;
end;
ChDir('C:\');
New(DP,Clear);
WriteLn;
Write('Scanning for ',ParamStr(1),'...');
DP^.FindDirectories(ParamStr(1),Archive);
WriteLn;
WriteLn;
ProcessDir(DP,'C:');
WriteLn;
WriteLn('Back to original directory ',Orig);
ChDir(Orig);
St.Init('PFF.DAT',SCreate);
DP^.Store(St);
St.Done;
Dispose(DP,Done);
end.
[Back to DIRS SWAG index] [Back to Main SWAG index] [Original]