home *** CD-ROM | disk | FTP | other *** search
- _STRUCTURED PROGRAMMING COLUMN_
- by Jeff Duntemann
-
-
- [LISTING ONE]
-
- UNIT DirList; { By Jeff Duntemann; for DDJ 4/92 }
-
- INTERFACE
-
- USES Crt,DOS,Objects, { Standard Borland units }
- When2; { From DDJ 1/91 }
- TYPE
- String40 = STRING[40];
- PDirEntry = ^TDirEntry;
- TDirEntry =
- OBJECT(TObject)
- Path : PathStr; { Predefined in Dos unit as STRING[79] }
- Entry : SearchRec; { Also predefined in the Dos unit }
- DirLine : String40; { Preformatted directory info string }
- CONSTRUCTOR Init(APath : PathStr; ASearchRec : SearchRec);
- PROCEDURE FormatDirLine;
- END;
- PDirEntryCollection = ^TDirEntryCollection;
- TDirEntryCollection =
- OBJECT(TSortedCollection)
- CONSTRUCTOR InitDir(ALimit,ADelta : Integer;
- Path, Mask : STRING;
- Attr : Word);
- CONSTRUCTOR InitCommandLine(ALimit,ADelta : Integer; StartParam : Integer);
- CONSTRUCTOR InitTree(Alimit,ADelta : Integer;
- Path,Mask : STRING;
- Attr : Word);
- FUNCTION Compare(Key1,Key2 : Pointer) : Integer; VIRTUAL;
- PROCEDURE AddDir(Path,Mask : STRING;
- Attr : Word);
- PROCEDURE TreeScan(Path,Mask : STRING; Attr : Word);
- END;
-
- IMPLEMENTATION
- VAR
- Stamp : When; { Global When stamp for time/date string processing }
- {----------------------------------------}
- { Methods: TDirEntry }
- {----------------------------------------}
- CONSTRUCTOR TDirEntry.Init(APath : PathStr; ASearchRec : SearchRec);
- BEGIN
- TObject.Init;
- Path := APath;
- Entry := ASearchRec;
- FormatDirLine;
- END;
- PROCEDURE TDirEntry.FormatDirLine;
- VAR
- DotPos : Integer;
- WorkString,Blanker : String40;
- BEGIN
- Stamp.PutWhenStamp(Entry.Time);
- DirLine := ' ';
- Blanker := DirLine;
- {If the entry has the directory attribute, format differently: }
- IF (Entry.Attr AND $10) <> 0 THEN { Bit 4 is the directory attribute }
- BEGIN
- Insert(Entry.Name,DirLine,1); { No extensions on subdirectory names }
- Insert('<DIR>',DirLine,14) { Tell the world it's a subdirectory }
- END
- ELSE
- {This compound statement separates the file from its extension }
- { and converts the file size to a string. Note that we did not }
- { insert a file size figure into DirLine for subdirectory entries. }
- BEGIN
- DotPos := Pos('.',Entry.Name);
- IF DotPos > 0 THEN { File name has an extension }
- WorkString := Copy(Entry.Name,1,DotPos-1) +
- Copy(Blanker,1,9-DotPos) + '.' +
- Copy(Entry.Name,DotPos+1,Length(Entry.Name)-DotPos)
- ELSE { File name has no extension }
- WorkString := Entry.Name +
- Copy(Blanker,1,8-Length(Entry.Name)) + '.';
- Insert(WorkString,DirLine,1);
- Str(Entry.Size:7,WorkString);
- Insert(WorkString,DirLine,15);
- END;
- Insert(Stamp.GetDateString,DirLine,24);
- Insert(Stamp.GetTimeString,DirLine,34); { Finally, insert the time }
- Delete(DirLine,42,Length(DirLine)-42);
- END;
- {----------------------------------------}
- { Methods: TDirEntryCollection }
- {----------------------------------------}
- CONSTRUCTOR TDirEntryCollection.InitDir(ALimit,ADelta : Integer;
- Path,Mask : STRING;
- Attr : Word);
- BEGIN
- TSortedCollection.Init(Alimit,ADelta);
- AddDir(Path,Mask,Attr);
- END;
-
- CONSTRUCTOR TDirEntryCollection.InitCommandLine(ALimit,ADelta : Integer;
- StartParam : Integer);
- VAR
- I : Integer;
- SR : SearchRec; { Defined in the Dos unit }
- DEP : PDirEntry;
- Path : PathStr; { Defined in the Dos unit as STRING[79]; }
- Dir : DirStr; { Defined in the Dos unit as STRING[67]; }
- Name : NameStr; { Defined in the Dos unit as STRING[8]; }
- Ext : ExtStr; { Defined in the Dos unit as STRING[4]; }
- BEGIN
- TSortedCollection.Init(ALimit,ADelta);
- FOR I := StartParam TO ParamCount DO
- BEGIN
- FSplit(ParamStr(I),Dir,Name,Ext);
- AddDir(Dir,Name+Ext,AnyFile);
- END;
- END;
-
- CONSTRUCTOR TDirEntryCollection.InitTree(Alimit,ADelta : Integer;
- Path,Mask : STRING;
- Attr : Word);
- BEGIN
- TSortedCollection.Init(Alimit,ADelta);
- TreeScan(Path,Mask,Attr);
- END;
-
- FUNCTION TDirEntryCollection.Compare(Key1,Key2 : Pointer) : Integer;
- BEGIN
- IF (PDirEntry(Key1)^.Path + PDirEntry(Key1)^.Entry.Name) =
- (PDirEntry(Key2)^.Path + PDirEntry(Key2)^.Entry.Name) THEN
- Compare := 0
- ELSE
- IF (PDirEntry(Key1)^.Path + PDirEntry(Key1)^.Entry.Name) <
- (PDirEntry(Key2)^.Path + PDirEntry(Key2)^.Entry.Name) THEN
- Compare := -1
- ELSE Compare := 1;
- END;
-
- PROCEDURE TDirEntryCollection.AddDir(Path,Mask : STRING;
- Attr : Word);
- VAR
- I : Integer;
- SR : SearchRec;
- DEP : PDirEntry;
- BEGIN
- FindFirst(Path+Mask,Attr,SR);
- IF DosError = 0 THEN
- BEGIN
- DEP := New(PDirEntry,Init(Path,SR));
- Insert(DEP);
- REPEAT
- FindNext(SR);
- IF DosError = 0 THEN
- BEGIN
- DEP := New(PDirEntry,Init(Path,SR));
- Insert(DEP);
- END;
- UNTIL DosError <> 0;
- END;
- END;
-
- PROCEDURE TDirEntryCollection.TreeScan(Path,Mask : STRING;
- Attr : Word);
- VAR
- I : Integer;
- SR : SearchRec;
- DEP : PDirEntry;
- NextDirectory : STRING;
- BEGIN
- fillchar(SR,sizeof(SR),0);
- { We look for and search any subdirectories first: }
- IF Path <> '\' THEN Path := Path + '\';
- FindFirst(Path+'*.*',Directory,SR);
- WHILE (DOSError <> 2) AND (DOSError <> 18) DO
- BEGIN
- IF ((SR.Attr AND Directory) = Directory )
- AND (SR.Name[1] <> '.') THEN { We have a subdirectory }
- BEGIN
- NextDirectory := Path + SR.Name;
- TreeScan(NextDirectory,Mask,Attr);
- END;
- FindNext(SR);
- END;
- { At this point, we're in a directory that has no unsearched }
- { subdirectories, so we can search for files matching Mask: }
- AddDir(Path,Mask,Attr);
- END;
-
- { No initialization section }
- END.
-
-
-
- [LISTING TWO]
-
- PROGRAM JFind; { By Jeff Duntemann; from DDJ 4/92 }
-
- USES DOS,CRT,Printer, { Standard Borland units }
- DirList; { From DDJ for 4/92 }
- VAR
- Console : TEXT;
- FileSpecs : STRING;
- I : Integer;
- FilesFound : PDirEntryCollection;
-
- PROCEDURE DisplayFoundFiles(FilesFound : PDirEntryCollection);
- { This is the FAR local routine passed to the iterator method. }
- { It's called once for each item in the collection: }
- PROCEDURE DisplayOneFile(Target : PDirEntry); FAR;
- BEGIN
- Write(Console,Copy(Target^.DirLine,13,Length(Target^.DirLine)),' ');
- Writeln(Console,Target^.Path,Target^.Entry.Name);
- END;
-
- BEGIN
- { This is how you iterate a procedure over a collection: }
- FilesFound^.ForEach(@DisplayOneFile);
- END;
-
- BEGIN { JFIND Main }
- Assign(Console,''); { This allows us to use Standard Output }
- Rewrite(Console); { for Write/Writeln statements }
- IF ParamCount = 0 THEN
- BEGIN
- Writeln(Console,'>>>JFIND<<< by Jeff Duntemann');
- Writeln(Console);
- Writeln(Console,'Invocation syntax:');
- Writeln(Console);
- Writeln(Console,' JFIND <filespec>,[<filespec>..] CR');
- Writeln(Console);
- END
- ELSE
- BEGIN
- FilesFound := New(PDirEntryCollection,Init(256,16));
- FOR I := 1 TO ParamCount DO
- FilesFound^.TreeScan('\',ParamStr(I),AnyFile);
- IF FilesFound^.Count > 0 THEN
- BEGIN
- DisplayFoundFiles(FilesFound);
- Writeln(Console);
- END
- ELSE
- Writeln(Console,'No files match that file spec.');
- END;
- END.
-
-
-