mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-17 22:22:48 +02:00
301 lines
9.9 KiB
ObjectPascal
301 lines
9.9 KiB
ObjectPascal
unit FileFind;
|
|
{
|
|
This component performs file search with or without recursing subfolders,
|
|
with events generated on file match and on change scanning folder.
|
|
Written in Delphi3, but I suppose it will work on Delphi1 and Delphi2 also
|
|
Version 1.0
|
|
|
|
// following 3 Additions by David R Hazlehurst 4/6/98 (drarh@tcp.co.uk)
|
|
TStringList to store list of files found. (called "FilesFound")
|
|
Support for multiple wildcards in the one search. (SearchFile property)
|
|
Added flag to indicate if searching already or not.
|
|
|
|
Properties:
|
|
property Stop : boolean - Set to true if you want to cancel searching.
|
|
property SearchFile : shortstring - Set starting path and file mask for searching (e.g. "c:\*.doc").
|
|
property RecurseSubFolders : boolean - Do recursing or not.
|
|
property FilesFound : TStringList - drh : list of files found (read only)
|
|
property Searching : boolean - drh : Indicates if a search is in progress (read only)
|
|
Event handlers:
|
|
property OnFileFind : TFindFileEvent - On match found
|
|
property OnChangeFolder : TChangeFolderEvent - On change folder
|
|
property OnFinish : TNotifyEvent - On end of searching
|
|
Methods:
|
|
procedure Start; - Start searching.
|
|
|
|
This component is freeware.
|
|
I guarantee you nothing concering this code, but you can use it as you wish.
|
|
|
|
Happy coding
|
|
|
|
This component is dedicated to the girl I love... B.
|
|
|
|
Jem Naadi Ahmed
|
|
Bulsoft
|
|
Bulgaria
|
|
25 May, 1998
|
|
|
|
jemna@yahoo.com
|
|
Any comments will be welcome.
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Following changes by David R Hazlehurst (drarh@tcp.co.uk) 4th June 1998
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
Reformatted some of the layout to suit my style (indents, tabs, spacing, etc).
|
|
|
|
Create contructor moved to "public" block of type def.
|
|
|
|
Added property to store list of files found ("FilesFound").
|
|
This makes it easier for the user of the control to get the list info.
|
|
|
|
Added code to create string list in contructor
|
|
Added destructor event to handle destruction of string list created within the create event
|
|
|
|
Added a public "Searching" flag to indicate if search is already underway. This will
|
|
not prevent you from calling "start" again, but does provide a means of checking to see
|
|
if the user already started searching. You can then decide if you want to start a new
|
|
search. Another reason for making this optional rather than stopping you from searching
|
|
outright, is in case an error occurs while searching and you may not get past the search
|
|
block. Of course, you can add a block to the code if you really want it.
|
|
|
|
Improved the "start" procedure as follows:
|
|
the "SearchFile" parameter can now accept multiple wildcards to search
|
|
for more than one file type. Each wildcard is sepearted by ";" as per
|
|
the shell. Each type is searched in order given. So, for example:
|
|
|
|
SearchFile := 'c:\*.bat;*.sys'
|
|
|
|
could return "c:\autoexec.bat" and "c:\config.sys", as well as others.
|
|
|
|
|
|
end of my list.
|
|
|
|
Im not claiming ideal solutions here, they were just the first things that
|
|
occurred to me (from my requirements), and hey, they work. By all means, improve
|
|
on my "improvements" if you wish. I would also be interested in the results.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
29.11.2004 - ported to FPC/lazarus by barko, OPINFOS d.o.o.
|
|
|
|
}
|
|
|
|
interface
|
|
|
|
uses LResources,
|
|
SysUtils, Classes, LazFileUtils, Graphics, Controls, Forms, Dialogs;
|
|
|
|
type
|
|
TFindFileEvent = procedure(fullpath:string;info:TSearchRec)of object;
|
|
TChangeFolderEvent = procedure(fullpath:string;info:TSearchRec)of object;
|
|
|
|
TFileSearch = class(TComponent)
|
|
private
|
|
{ Private declarations }
|
|
fRec : boolean;
|
|
fStop : boolean;
|
|
fSearching : boolean;
|
|
fFilesFound : TStringList;
|
|
fFileFindEvent : TFindFileEvent;
|
|
fChangeFolderEvent : TChangeFolderEvent;
|
|
fFinishEvent : TNotifyEvent;
|
|
fdirName : shortstring;
|
|
protected
|
|
{ Protected declarations }
|
|
procedure ScanDir(ffdirName:string;attr:word);
|
|
|
|
public
|
|
{ Public declarations }
|
|
constructor Create(aOwner:TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
procedure Start;
|
|
|
|
property Searching : boolean read fSearching;
|
|
|
|
published
|
|
{ Published declarations }
|
|
property Stop : boolean read fStop write fStop default false;
|
|
property SearchFile : shortstring read fdirName write fdirName;
|
|
property FilesFound : TStringList read fFilesFound;
|
|
property RecurseSubFolders : boolean read fRec write fRec default true;
|
|
property OnFileFind : TFindFileEvent read fFileFindEvent write fFileFindEvent;
|
|
property OnChangeFolder : TChangeFolderEvent read fChangeFolderEvent write fChangeFolderEvent;
|
|
property OnFinish : TNotifyEvent read fFinishEvent write fFinishEvent;
|
|
end;
|
|
|
|
const
|
|
{$IFNDEF LINUX} // barko
|
|
delimeter = '\';
|
|
{$ELSE}
|
|
delimeter = '/';
|
|
{$ENDIF} // barko
|
|
|
|
|
|
procedure Register;
|
|
|
|
implementation
|
|
|
|
{$R filefind.res}
|
|
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents('Samples', [TFileSearch]);
|
|
end;
|
|
|
|
constructor TFileSearch.Create(aOwner:TComponent);
|
|
begin
|
|
inherited create(aOwner);
|
|
|
|
fFilesFound := TStringList.Create; // drh 4/6/98: Create results list
|
|
fRec := true;
|
|
fSearching := false; // drh 4/6/98: Initialise "Searching" flag
|
|
fStop := false;
|
|
end;
|
|
|
|
// drh 4/6/98: Added destructor handler
|
|
destructor TFileSearch.Destroy;
|
|
begin
|
|
fFilesFound.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TFileSearch.Start;
|
|
var
|
|
i, newWildCard : Integer;
|
|
curSearchPath, wildCards : String;
|
|
srchPaths : TStringList;
|
|
begin
|
|
fStop := false;
|
|
|
|
fSearching := True; // drh 4/6/98: flag to indicate we are searching
|
|
fFilesFound.Clear; // drh 4/6/98: new search, so no files should be listed
|
|
|
|
// Look for ";" wildcard seperators.
|
|
// loop through replacing the "filename" with each wildcard...
|
|
newWildCard := Pos( ';', fDirName);
|
|
|
|
if newWildCard > 0 then
|
|
begin
|
|
curSearchPath := Copy( fdirName, 1, newWildCard-1);
|
|
wildCards := Copy( fdirName, newWildCard+1, length(fDirName) );
|
|
|
|
srchPaths := TStringList.Create;
|
|
srchPaths.Add( curSearchPath );
|
|
|
|
// Build up a list of search paths by looping through each wildcard
|
|
while length(wildCards) > 0 do
|
|
begin
|
|
curSearchPath := ExtractFilePath( curSearchPath );
|
|
newWildCard := Pos( ';', wildCards );
|
|
|
|
if newWildCard > 0 then
|
|
begin
|
|
curSearchPath := curSearchPath + Copy(wildCards, 1, newWildCard-1);
|
|
wildCards := Copy(wildCards, newWildCard+1, length(wildCards) );
|
|
end
|
|
else
|
|
begin
|
|
curSearchPath := curSearchPath + wildCards;
|
|
wildCards := '';
|
|
end;
|
|
|
|
srchPaths.Add( curSearchPath );
|
|
end;
|
|
|
|
// Well, we got the paths, lets start searching them shall we?
|
|
for i := 0 to srchPaths.Count - 1 do
|
|
ScanDir(srchPaths.Strings[i], faAnyFile);
|
|
|
|
// get rid of search paths.
|
|
srchPaths.Free;
|
|
end
|
|
else // no other wildcards to search, just a single file def
|
|
ScanDir(fdirName, faAnyFile);
|
|
|
|
// drh 4/6/98:
|
|
// the following was moved here from end of "ScanDir", just in
|
|
// case multiple searches are being carried out (do not want
|
|
// multiple end of search events being fired).
|
|
if Assigned( fFinishEvent ) then
|
|
fFinishEvent( Self ); // notify user that searching is complete.
|
|
|
|
fSearching := False; // drh 4/6/98: flag indicates we arnt searching any more
|
|
end;
|
|
|
|
procedure TFileSearch.ScanDir(ffdirName:string; attr:word);
|
|
const
|
|
{$IFNDEF LINUX} // barko
|
|
fi : string = '*.*';
|
|
{$ELSE}
|
|
fi : string = '*';
|
|
{$ENDIF} // barko
|
|
p : string = '.';
|
|
pp : string = '..' ;
|
|
var
|
|
path : string;
|
|
doserror : integer;
|
|
sfi : string;
|
|
|
|
procedure showq(fullpath:string; FolderInfo:TSearchRec);
|
|
var
|
|
dirq : TSearchRec;
|
|
begin
|
|
if assigned(fChangeFolderEvent) then
|
|
fChangeFolderEvent(fullpath,FolderInfo);
|
|
|
|
doserror := FindFirstUTF8(fullpath+sfi,attr,dirq);
|
|
|
|
while (doserror = 0)and(not fstop) do
|
|
begin
|
|
if (dirq.name<>p) and (dirq.name<>pp) and (assigned(fFileFindEvent)) then
|
|
begin
|
|
fFileFindEvent( fullpath, dirq );
|
|
fFilesFound.Add( fullpath + dirq.Name ); // drh 4/6/98: Add filename to list of those found thus far
|
|
end;
|
|
|
|
doserror := FindNextUTF8(dirq);
|
|
application.processMessages;
|
|
end;
|
|
FindCloseUTF8(dirq);// barko
|
|
|
|
end; // showq
|
|
|
|
procedure ScanLDir(fffdirName:string; fInfo:TSearchRec);
|
|
var
|
|
dirinfo : TSearchRec;
|
|
begin
|
|
showq(fffDirName, fInfo);
|
|
dosError := FindFirstUTF8(fffDirName+fi, faAnyfile, dirInfo);
|
|
|
|
while (doserror = 0) and (not fstop) do
|
|
begin
|
|
application.ProcessMessages;
|
|
|
|
if (dirInfo.name<>p) and (dirInfo.name<>pp) then
|
|
if (dirInfo.attr and faDirectory <> 0) and (frec) then
|
|
ScanLDir(fffdirName+dirinfo.name+delimeter, dirInfo);
|
|
|
|
dosError := FindNextUTF8(dirInfo);
|
|
application.ProcessMessages;
|
|
end;
|
|
FindCloseUTF8(dirInfo); // barko
|
|
|
|
end; // ScanLDir
|
|
|
|
var
|
|
fInfo : TSearchRec;
|
|
fPath : string;
|
|
begin // ScanDir
|
|
|
|
path := ExtractFilePath( ffDirName );
|
|
sfi := ExtractFileName( ffDirName );
|
|
|
|
fPath := Copy(path, 1, length(Path) - 1 );
|
|
|
|
FindFirstUTF8(fPath, faAnyfile, fInfo);
|
|
ScanLDir(Path, fInfo);
|
|
FindCloseUTF8(fInfo); // barko
|
|
end; // ScanDir
|
|
|
|
end.
|