home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
4dos
/
4utils.zip
/
4FF.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-10-31
|
15KB
|
440 lines
PROGRAM FileFind;
{$A+,B-,D-,E-,F-,G+,I-,L+,N-,O-,R-,S-,V-,X-}
{$M 16384,0,65530}
(* ----------------------------------------------------------------------
A 4DOS-aware file finder. It searches in .LZH archives too.
(c) 1992, 1993 Copyright by David Frey,
Urdorferstrasse 30
8952 Schlieren ZH
Switzerland
Code created using Turbo Pascal 6.0 (c) Borland International 1990
DISCLAIMER: This program is freeware: you are allowed to use, copy
and change it free of charge, but you may not sell or hire
4FF. The copyright remains in my hands.
If you make any (considerable) changes to the source code,
please let me know. (send me a copy or a listing).
I would like to see what you have done.
I, David Frey, the author, provide absolutely no warranty of
any kind. The user of this software takes the entire risk of
damages, failures, data losses or other incidents.
NOTES: Turbo Pascal 6.0 required for compiling. (sorry, but I'm
using FormatStr for output)
ENHANCEMENTS: adapted to 4DOS 4.01 - when redirecting into files,
full descriptions will be shown, otherwise the
descriptions will be truncated at the right screen margin.
paging switch (/p) added.
Fast screen output when no redirected output has been used.
Searches for Read Only / Hidden directories, too.
ARJ File scanning added.
----------------------------------------------------------------------- *)
USES {$IFOPT G+} Test286, {$ENDIF}
Objects, Drivers,
Crt, Dos, StringDateHandling, HandleINIFile,
ScanLZHFiles, ScanZIPFiles, ScanARJFiles, Globals;
CONST Header= '4FF 4DOS File Find 1.7 -- (c) David Frey 1992, 1993';
VAR DescBuffer: ARRAY[0..512] OF CHAR;
VAR ActDir, StartDir : STRING;
DescArray : DescArrayType;
FileSpecArray : FileSpecArrayType;
DescFile : TEXT;
DescLine : STRING;
DescLineNr : WORD;
Desc : DescStr;
DescStart : BYTE;
DescEnd : BYTE;
DescFound : BOOLEAN;
i,l : WORD;
k : BYTE;
FileSpecs : BYTE;
ps,fs : STRING;
IORes : INTEGER;
Templ : STRING;
OldCtrlBreakHandler : POINTER;
OldCtrlBreakState : BOOLEAN;
BrokeOut : BOOLEAN;
PROCEDURE MyCtrlBreakHandler; FAR;
BEGIN
ExitProc := OldCtrlBreakHandler; SetCBreak(OldCtrlBreakState);
{$I-}
ChDir(ActDir); IORes := IOResult;
IF BrokeOut THEN
BEGIN
WriteLn(Output);
WriteLn(Output,' EXITING - User broke out of program.');
WriteLn(Output);
END;
Close(Output);
IF NOT Redirected THEN NormVideo;
END;
PROCEDURE ShowFileData(VAR search: SearchRec;VAR Path: PathStr;VAR Desc: DescStr);
VAR i : INTEGER;
BEGIN
IF BareOutput THEN
Write(Output,Path,Search.Name,' ')
ELSE
BEGIN
IF FileCount = 0 THEN
BEGIN
WriteLn(Output); IF DoPage THEN TestForMoreMsg;
WriteLn(Output,Path); IF DoPage THEN TestForMoreMsg;
END;
InfoArray[0] := LONGINT(@search.Name);
SizeStr := FormattedLongIntStr(search.Size,7);
InfoArray[1] := LONGINT(@SizeStr);
UnpackTime(search.Time,DateRec);
Date := FormDate(DateRec); Time := FormTime(DateRec);
InfoArray[2] := LONGINT(@Date);
InfoArray[3] := LONGINT(@Time);
AttrStr := '....';
IF search.Attr AND ReadOnly = ReadOnly THEN AttrStr[1] := 'r';
IF search.Attr AND Hidden = Hidden THEN AttrStr[2] := 'h';
IF search.Attr AND SysFile = SysFile THEN AttrStr[3] := 's';
IF search.Attr AND Archive = Archive THEN AttrStr[4] := 'a';
InfoArray[4] := LONGINT(@AttrStr);
InfoArray[5] := LONGINT(@Desc);
FormatStr(s,'%-12s %8s '+DateTempl+' '+TimeTempl+' %4s '+DescTempl,InfoArray);
WriteLn(Output,s); IF DoPage THEN TestForMoreMsg;
INC(TotalSize,Search.Size); INC(DirSize,Search.Size);
INC(TotalFileCount); INC(FileCount);
END;
END; (* ShowFileData *)
PROCEDURE BuildList(Dir: DirStr; VAR FileSpec: FileSpecArrayType; FileSpecs: BYTE;
Attr: BYTE);
VAR Search: SearchRec;
DescFileExists: BOOLEAN;
l,i,k : BYTE;
BEGIN (* BuildList *)
FileCount := 0; DirSize := 0;
Attr := Attr AND NOT Directory AND NOT VolumeId;
OldLHFileName := ''; OldZipFileName := '';
l := Length(Dir); s := Dir;
IF (l>3) AND (s[l] = '\') THEN Delete(s,l,1);
ChDir(s);
{$I-}
Assign(DescFile,'DESCRIPT.ION'); SetTextBuf(DescFile,DescBuffer);
Reset(DescFile);
DescFileExists := (IOResult = 0);
IF DescFileExists THEN
BEGIN
DescLineNr := 1;
WHILE NOT Eof(DescFile) AND (DescLineNr <= MaxComments) DO
BEGIN
ReadLn(DescFile,DescLine); DescStart := Pos(' ',DescLine);
DescEnd := Pos(#4,DescLine); IF DescEnd = 0 THEN DescEnd := Length(DescLine)+1;
Desc := Copy(DescLine,DescStart+1,DescEnd-1);
StripLeadingSpaces(Desc);
i := 1; l := Length(DescLine);
REPEAT
IF (DescLine[i] >= 'A') AND (DescLine[i] <= 'Z') THEN
BEGIN DescLine[i] := Char(Ord(DescLine[i])+32); END;
INC(i);
UNTIL (i=l) OR (DescLine[i] = ' ');
DescArray[DescLineNr] := DescLine; INC(DescLineNr);
END;
DEC(DescLineNr);
IF DescLineNr = MaxComments THEN
BEGIN
WriteLn(Output); IF DoPage THEN TestForMoreMsg;
WriteLn(Output,'WARNING: description line buffer full, some comments may not appear.'); IF DoPage THEN TestForMoreMsg;
WriteLn(Output); IF DoPage THEN TestForMoreMsg;
END;
{$I-}
Close(DescFile); IORes := IOResult;
END;
IF DoScanLZHArchives THEN
BEGIN
FindFirst('????????.LZH',ReadOnly+Archive,Search);
WHILE DosError = 0 DO
BEGIN
SearchInLZHFile(FileSpec,FileSpecs,Dir,Search);
FindNext(Search);
END;
END;
IF DoScanZIPArchives THEN
BEGIN
FindFirst('????????.ZIP',ReadOnly+Archive,Search);
WHILE DosError = 0 DO
BEGIN
SearchInZIPFile(FileSpec,FileSpecs,Dir,Search);
FindNext(Search);
END;
END;
IF DoScanARJArchives THEN
BEGIN
FindFirst('????????.ARJ',ReadOnly+Archive,Search);
WHILE DosError = 0 DO
BEGIN
SearchInARJFile(FileSpec,FileSpecs,Dir,Search);
FindNext(Search);
END;
END;
FOR k := 1 TO FileSpecs DO
BEGIN
FindFirst(FileSpec[k], Attr, Search);
WHILE DosError = 0 DO
BEGIN
IF NOT ExactAttr OR (ExactAttr AND (Search.Attr = Attr)) THEN
BEGIN
DownString(Search.Name);
Desc := '';
IF (NOT DescFileExists OR (Search.Name = 'descript.ion')) THEN
ShowFileData(search,Dir,Desc)
ELSE
BEGIN
i := 1;
REPEAT
DescStart := Pos(' ',DescArray[i]);
DescFound := (Copy(DescArray[i],1,DescStart-1) = Search.Name);
IF NOT DescFound THEN INC(i);
UNTIL DescFound OR (i>DescLineNr);
IF NOT DescFound THEN Desc := ''
ELSE Desc := Copy(DescArray[i],DescStart+1,255);
ShowFileData(search,Dir,Desc);
END;
END;
FindNext(Search);
END;
END;
IF NOT BareOutput AND (FileCount > 0) THEN
BEGIN
Templ := '%-4s entr';
IF FileCount = 1 THEN Templ := Templ + 'y, '
ELSE Templ := Templ + 'ies,';
Templ := Templ+' %10s Bytes';
FileStr := FormattedIntStr(FileCount,4); InfoArray[0] := LONGINT(@FileStr);
SizeStr := FormattedLongIntStr(DirSize,10);InfoArray[1] := LONGINT(@SizeStr);
FormatStr(s,Templ,InfoArray);
WriteLn(Output,s); IF DoPage THEN TestForMoreMsg;
END;
FindFirst('????????. ',Directory+ReadOnly+Hidden,Search);
WHILE DosError = 0 DO
BEGIN
IF (Search.Attr = Directory) AND
(Search.Name <> '.') AND (Search.Name <> '..') THEN
BuildList(Dir+Search.Name+'\',FileSpec,FileSpecs,Attr);
FindNext(Search);
END;
{$I-}
ChDir('..'); IORes := IOResult;
END; (* BuildList *)
FUNCTION DriveValid(C: CHAR): BOOLEAN; ASSEMBLER;
ASM
MOV DL,C
MOV AH,36H
SUB DL,'A'-1
Int 21H
INC AX
JE @@2
@@1:
MOV AL,1
@@2:
END; (* DriveValid *)
PROCEDURE GiveHelp;
BEGIN
WriteLn(Output);
WriteLn(Output,Header);
WriteLn(Output);
WriteLn(Output,'This program is freeware: you are allowed to use, copy it free');
WriteLn(Output,'of charge, but you may not sell or hire 4FF.');
WriteLn(Output);
WriteLn(Output,'usage: 4FF [/a:[-]rash][/l][/z][/s][/b][/d][/m:nn][/?] [start dir\]{filenames}');
WriteLn(Output);
WriteLn(Output,' /a:rash search for files with these attributes set.');
WriteLn(Output,' /l do not search in .lzh archive files.');
WriteLn(Output,' /z do not search in .zip archive files.');
WriteLn(Output,' /j do not search in .arj archive files.');
WriteLn(Output,' /s scan only subdirectories of given path `start-dir''');
WriteLn(Output,' /b bare listing (omits size, date, and descriptions)');
WriteLn(Output,' /d scan all hard disks (address floppy drives explicitely)');
WriteLn(Output,' /m:nn set right margin to nn');
WriteLn(Output,' /p page output');
WriteLn(Output,' /? this help display.');
HALT;
END; (* GiveHelp *)
BEGIN
GetCBreak(OldCtrlBreakState); SetCBreak(FALSE);
OldCtrlBreakHandler := ExitProc; ExitProc := @MyCtrlBreakHandler;
BrokeOut := FALSE;
GetDir(0,ActDir);
IF (ParamStr(1) = '/?') OR (ParamStr(1) = '-?') THEN GiveHelp;
IF TextRec(Output).Name[0] <> #0 THEN
BEGIN
Str(DescLen,DescTempl); DescTempl := '%-'+DescTempl+'s';
END;
BareOutput := FALSE; ExactAttr := FALSE;
SubDirectories := FALSE; AllDrives := FALSE;
DoScanLZHArchives := TRUE; DoScanZIPArchives := TRUE;
DoScanARJArchives := TRUE;
FileSpecArray[1] := '*.*'; FileSpecs := 1; StartDir := '';
i := 1; l := 0;
REPEAT
ps := ParamStr(i);
IF ps[1] = '/' THEN ps[1] := '-';
IF ps[1] = '-' THEN
BEGIN
s := Copy(ps,2,255); DownString(s);
IF DoScanLZHArchives THEN DoScanLZHArchives := (s <>'l');
IF DoScanZIPArchives THEN DoScanZIPArchives := (s <>'z');
IF DoScanARJArchives THEN DoScanARJArchives := (s <>'j');
IF NOT SubDirectories THEN SubDirectories := (s='s');
IF NOT BareOutput THEN BareOutput := (s='b');
IF NOT AllDrives THEN AllDrives := (s='d');
IF NOT DoPage AND NOT Redirected THEN DoPage := (s='p');
IF s[1] = 'a' THEN
BEGIN
s := Copy(s,Pos(':',s)+1,255);
Attr := 0; AttrStr := '....'; ExactAttr := TRUE;
IF (Pos('r',s) > 0) AND (Pos('-r',s) = 0) THEN BEGIN INC(Attr,ReadOnly); AttrStr[1] := 'r'; END;
IF (Pos('h',s) > 0) AND (Pos('-h',s) = 0) THEN BEGIN INC(Attr,Hidden ); AttrStr[2] := 'h'; END;
IF (Pos('s',s) > 0) AND (Pos('-s',s) = 0) THEN BEGIN INC(Attr,SysFile ); AttrStr[3] := 's'; END;
IF (Pos('a',s) > 0) AND (Pos('-a',s) = 0) THEN BEGIN INC(Attr,Archive ); AttrStr[4] := 'a'; END;
END;
IF ps[2] = 'm' THEN
BEGIN
Delete(ps,1,3); Val(ps,k,IORes);
MaxViewLength := k-31-Length(DateFormat)-Length(TimeFormat);
Str(MaxViewLength,DescTempl); DescTempl := '%-'+DescTempl+'s';
END;
INC(l);
END;
INC(i);
UNTIL (i>ParamCount) OR (ps[1] <> '-');
IF l < ParamCount THEN
BEGIN
FOR i := l+1 TO ParamCount DO
BEGIN
FSplit(FExpand(ParamStr(i)),Path,Name,Ext);
IF (Path <> '') AND (StartDir = '') THEN StartDir := Path;
IF Name = '' THEN Name := '*';
IF Ext = '' THEN Ext := '.*';
FileSpecArray[i-l] := Name+Ext; DownString(FileSpecArray[i-l]);
END;
FileSpecs := ParamCount-l;
END;
IF StartDir = '' THEN StartDir := ActDir;
IF SubDirectories THEN Path := StartDir
ELSE Path := Copy(StartDir,1,3);
IF NOT BareOutput THEN
BEGIN
WriteLn(Output,Header);
WriteLn(Output);
WriteLn(Output,'This program is freeware: you are allowed to use,');
WriteLn(Output,'copy it free of charge, but you may not sell or hire 4FF.');
WriteLn(Output);
IF FileSpecs = 1 THEN WriteLn(Output,'Filename = ',FileSpecArray[1],'.')
ELSE
BEGIN
Write(Output, 'Filenames = ');
FOR i := 1 TO FileSpecs DO
BEGIN
Write(Output,FileSpecArray[i]);
IF i < FileSpecs THEN Write(Output,', ')
ELSE WriteLn(Output,'.');
END;
END;
IF AllDrives THEN WriteLn(Output,'Scanning all drives.')
ELSE WriteLn(Output,'Path = ',Path);
Line := 7;
IF ExactAttr THEN
BEGIN
WriteLn(Output,'Attributes= ',AttrStr); INC(Line);
END;
END;
IF DoScanLZHArchives OR DoScanZIPArchives OR DoScanARJArchives THEN InstallBuffer;
TotalFileCount := 0; TotalSize := 0; BrokeOut := TRUE;
IF NOT AllDrives THEN
BEGIN
s := Path; l := Length(s);
IF (l > 3) AND (s[l] = '\') THEN Delete(s,l,1);
BuildList(Path,FileSpecArray,FileSpecs,Attr)
END
ELSE
FOR Drive := 'C' TO 'Z' DO
IF DriveValid(Drive) THEN BuildList(Drive+':\',FileSpecArray,FileSpecs,Attr);
BrokeOut := FALSE;
IF NOT BareOutput THEN
BEGIN
IF TotalFileCount = 0 THEN s := 'no files found.'
ELSE
BEGIN
Templ := '%s file';
IF TotalFileCount = 1 THEN Templ := Templ +', '
ELSE Templ := Templ +'s,';
Templ := Templ+' %10s Bytes';
FileStr := FormattedIntStr(TotalFileCount,4); InfoArray[0] := LONGINT(@FileStr);
SizeStr := FormattedLongIntStr(TotalSize,10); InfoArray[1] := LONGINT(@SizeStr);
FormatStr(s,Templ,InfoArray);
END;
WriteLn(Output,'------------------------------------------------'); IF DoPage THEN TestForMoreMsg;
WriteLn(Output,s); IF DoPage THEN TestForMoreMsg;
END
ELSE WriteLn(Output);
IF DoScanLZHArchives OR DoScanZIPArchives OR DoScanARJArchives THEN FreeBuffer;
END.