1 {
2  *****************************************************************************
3   See the file COPYING.modifiedLGPL.txt, included in this distribution,
4   for details about the license.
5  *****************************************************************************
6 
7   Author: Mattias Gaertner
8 
9   Abstract:
10     Find in files dialog form.
11 
12 }
13 unit FindInFilesDlg;
14 
15 {$mode objfpc}{$H+}
16 
17 interface
18 
19 uses
20   Classes, SysUtils,
21   // LCL
22   LCLProc, Controls, StdCtrls, Forms, Buttons, ExtCtrls, Dialogs, ButtonPanel,
23   // Codetools
24   FileProcs,
25   // LazUtils
26   LazFileUtils,
27   // SynEdit
28   SynEditTypes, SynEdit,
29   // IdeIntf
30   MacroIntf, IDEWindowIntf, SrcEditorIntf, IDEHelpIntf, IDEDialogs,
31   ProjectGroupIntf,
32   // IDE
33   LazarusIDEStrConsts, InputHistory, InputhistoryWithSearchOpt, EditorOptions, Project,
34   IDEProcs, SearchFrm, SearchResultView, EnvironmentOpts;
35 
36 type
37   { TLazFindInFilesDialog }
38 
39   TLazFindInFilesDialog = class(TForm)
40     ButtonPanel1: TButtonPanel;
41     ReplaceCheckBox: TCheckBox;
42     ReplaceTextComboBox: TComboBox;
43     IncludeSubDirsCheckBox: TCheckBox;
44     FileMaskComboBox: TComboBox;
45     DirectoriesBrowse: TBitBtn;
46     DirectoriesComboBox: TComboBox;
47     DirectoriesLabel: TLabel;
48     FileMaskLabel: TLabel;
49     DirectoriesOptionsGroupBox: TGroupBox;
50     OptionsCheckGroupBox: TCheckGroup;
51     SelectDirectoryDialog: TSelectDirectoryDialog;
52     TextToFindComboBox: TComboBox;
53     TextToFindLabel: TLabel;
54     WhereRadioGroup: TRadioGroup;
55     procedure DirectoriesBrowseClick(Sender: TObject);
56     procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
57     procedure FormCreate(Sender: TObject);
58     procedure FormShow(Sender: TObject);
59     procedure HelpButtonClick(Sender: TObject);
60     procedure OKButtonClick(Sender : TObject);
61     procedure ReplaceCheckBoxChange(Sender: TObject);
62     procedure WhereRadioGroupClick(Sender: TObject);
63   private
64     FProject: TProject;
GetFindTextnull65     function GetFindText: string;
GetOptionsnull66     function GetOptions: TLazFindInFileSearchOptions;
GetReplaceTextnull67     function GetReplaceText: string;
GetSynOptionsnull68     function GetSynOptions: TSynSearchOptions;
69     procedure SetFindText(const NewFindText: string);
70     procedure SetOptions(NewOptions: TLazFindInFileSearchOptions);
71     procedure SetReplaceText(const AValue: string);
72     procedure SetSynOptions(NewOptions: TSynSearchOptions);
73     procedure UpdateReplaceCheck;
74     procedure UpdateDirectoryOptions;
75   public
76     property Options: TLazFindInFileSearchOptions read GetOptions
77                                                   write SetOptions;
78     property FindText: string read GetFindText write SetFindText;
79     property ReplaceText: string read GetReplaceText write SetReplaceText;
80     property SynSearchOptions: TSynSearchOptions read GetSynOptions
81                                                  write SetSynOptions;
GetBaseDirectorynull82     function GetBaseDirectory: string;
83     procedure LoadHistory;
84     procedure SaveHistory;
85     procedure FindInSearchPath(SearchPath: string);
86     procedure FindInFilesPerDialog(AProject: TProject);
87     procedure InitFindText;
88     procedure InitFromLazSearch(Sender: TObject);
89     procedure FindInFiles(AProject: TProject; const AFindText: string);
GetResolvedDirectoriesnull90     function GetResolvedDirectories: string;
Executenull91     function Execute: boolean;
92     property LazProject: TProject read FProject write FProject;
93   end;
94 
FindInFilesDialognull95 function FindInFilesDialog: TLazFindInFilesDialog;
96 
97 implementation
98 
99 var  // WhereRadioGroup's ItemIndex in a more informative form.
100   ItemIndProject: integer = 0;
101   ItemIndProjectGroup: integer = -1;
102   ItemIndOpenFiles: integer   = 1;
103   ItemIndDirectories: integer = 2;
104   ItemIndActiveFile: integer = 3;
105 
106 var
107   FindInFilesDialogSingleton: TLazFindInFilesDialog = nil;
108 
109 function FindInFilesDialog: TLazFindInFilesDialog;
110 begin
111   if FindInFilesDialogSingleton = nil then
112     FindInFilesDialogSingleton := TLazFindInFilesDialog.Create(Application);
113   Result := FindInFilesDialogSingleton;
114 end;
115 
116 {$R *.lfm}
117 
118 { TLazFindInFilesDialog }
119 
120 procedure TLazFindInFilesDialog.SetFindText(const NewFindText: string);
121 begin
122   TextToFindComboBox.Text := NewFindText;
123   TextToFindComboBox.SelectAll;
124   ActiveControl := TextToFindComboBox;
125 end;
126 
GetFindTextnull127 function TLazFindInFilesDialog.GetFindText: string;
128 begin
129   Result := TextToFindComboBox.Text;
130 end;
131 
GetReplaceTextnull132 function TLazFindInFilesDialog.GetReplaceText: string;
133 begin
134   Result:=ReplaceTextComboBox.Text;
135 end;
136 
137 procedure TLazFindInFilesDialog.WhereRadioGroupClick(Sender: TObject);
138 begin
139   UpdateDirectoryOptions;
140 end;
141 
142 procedure TLazFindInFilesDialog.DirectoriesBrowseClick(Sender: TObject);
143 var
144   Dir: String;
145   OldDirs: String;
146   p: Integer;
147 begin
148   InitIDEFileDialog(SelectDirectoryDialog);
149   // use the first directory as initialdir for the dialog
150   OldDirs:=GetResolvedDirectories;
151   p:=1;
152   repeat
153     Dir:=GetNextDirectoryInSearchPath(OldDirs,p);
154     if Dir='' then break;
155     if DirectoryExistsUTF8(Dir) then break;
156   until false;
157   if Dir<>'' then
158     SelectDirectoryDialog.InitialDir := Dir
159   else
160     SelectDirectoryDialog.InitialDir := GetBaseDirectory;
161 
162   if SelectDirectoryDialog.Execute then
163     DirectoriesComboBox.Text := AppendPathDelim(TrimFilename(SelectDirectoryDialog.FileName));
164   StoreIDEFileDialog(SelectDirectoryDialog);
165 end;
166 
167 procedure TLazFindInFilesDialog.FormClose(Sender: TObject; var CloseAction: TCloseAction);
168 begin
169   IDEDialogLayoutList.SaveLayout(Self);
170 end;
171 
172 procedure TLazFindInFilesDialog.FormCreate(Sender: TObject);
173 begin
174   Caption := srkmecFindInFiles;
175 
176   TextToFindLabel.Caption := dlgTextToFind;
177   ReplaceCheckBox.Caption := dlgReplaceWith;
178 
179   OptionsCheckGroupBox.Caption := lisOptions;
180   OptionsCheckGroupBox.Items[0] := dlgCaseSensitive;
181   OptionsCheckGroupBox.Items[1] := dlgWholeWordsOnly;
182   OptionsCheckGroupBox.Items[2] := dlgRegularExpressions;
183   OptionsCheckGroupBox.Items[3] := lisFindFileMultiLinePattern;
184 
185   WhereRadioGroup.Caption:=lisFindFileWhere;
186   WhereRadioGroup.Items[ItemIndProject]     := lisFindFilesearchAllFilesInProject;
187   if ProjectGroupManager<>nil then
188   begin
189     ItemIndProjectGroup:=1;
190     WhereRadioGroup.Items.Insert(ItemIndProjectGroup, lisFindFilesSearchInProjectGroup);
191     ItemIndOpenFiles:=2;
192     ItemIndDirectories:=3;
193     ItemIndActiveFile:=4;
194   end;
195   WhereRadioGroup.Items[ItemIndOpenFiles]   := lisFindFilesearchAllOpenFiles;
196   WhereRadioGroup.Items[ItemIndDirectories] := lisFindFilesearchInDirectories;
197   WhereRadioGroup.Items[ItemIndActiveFile]  := lisFindFilesearchInActiveFile;
198 
199   DirectoriesOptionsGroupBox.Caption := lisDirectories;
200   DirectoriesComboBox.Hint:=lisMultipleDirectoriesAreSeparatedWithSemicolons;
201   DirectoriesLabel.Caption := lisFindFileDirectories;
202   FileMaskLabel.Caption := lisFindFileFileMask;
203 
204   IncludeSubDirsCheckBox.Caption := lisFindFileIncludeSubDirectories;
205 
206   ButtonPanel1.HelpButton.Caption := lisMenuHelp;
207   ButtonPanel1.CancelButton.Caption := lisCancel;
208 
209   ReplaceCheckBox.Enabled:=true;
210 
211   UpdateReplaceCheck;
212   UpdateDirectoryOptions;
213 
214   AutoSize:=IDEDialogLayoutList.Find(Self,false)=nil;
215   IDEDialogLayoutList.ApplyLayout(Self);
216 end;
217 
218 procedure TLazFindInFilesDialog.FormShow(Sender: TObject);
219 begin
220   TextToFindComboBox.DropDownCount:=EnvironmentOptions.DropDownCount;
221   ReplaceTextComboBox.DropDownCount:=EnvironmentOptions.DropDownCount;
222   DirectoriesComboBox.DropDownCount:=EnvironmentOptions.DropDownCount;
223   FileMaskComboBox.DropDownCount:=EnvironmentOptions.DropDownCount;
224 end;
225 
226 procedure TLazFindInFilesDialog.HelpButtonClick(Sender: TObject);
227 begin
228   LazarusHelp.ShowHelpForIDEControl(Self);
229 end;
230 
231 procedure TLazFindInFilesDialog.OKButtonClick(Sender : TObject);
232 var
233   Directories, Dir: String;
234   p: Integer;
235 begin
236   if (WhereRadioGroup.ItemIndex=ItemIndDirectories) then
237   begin
238     Directories:=GetResolvedDirectories;
239     p:=1;
240     repeat
241       Dir:=GetNextDirectoryInSearchPath(Directories,p);
242       if (Dir<>'') and not DirectoryExistsUTF8(Dir) then
243       begin
244         IDEMessageDialog(lisEnvOptDlgDirectoryNotFound,
245                    Format(dlgSeachDirectoryNotFound,[Dir]),
246                    mtWarning, [mbOk]);
247         ModalResult:=mrNone;
248         Break;
249       end;
250     until Dir='';
251   end;
252 end;
253 
254 procedure TLazFindInFilesDialog.ReplaceCheckBoxChange(Sender: TObject);
255 begin
256   UpdateReplaceCheck;
257 end;
258 
259 procedure TLazFindInFilesDialog.SetOptions(NewOptions: TLazFindInFileSearchOptions);
260 var
261   NewItemIndex: Integer;
262 begin
263   OptionsCheckGroupBox.Checked[0] := fifMatchCase in NewOptions;
264   OptionsCheckGroupBox.Checked[1] := fifWholeWord in NewOptions;
265   OptionsCheckGroupBox.Checked[2] := fifRegExpr in NewOptions;
266   OptionsCheckGroupBox.Checked[3] := fifMultiLine in NewOptions;
267   IncludeSubDirsCheckBox.Checked := fifIncludeSubDirs in NewOptions;
268   ReplaceCheckBox.Checked := [fifReplace,fifReplaceAll]*NewOptions<>[];
269 
270   NewItemIndex:=ItemIndProject;
271   if fifSearchProject in NewOptions then
272     NewItemIndex := ItemIndProject;
273   if (fifSearchProjectGroup in NewOptions) and (ItemIndProjectGroup>=0) then
274     NewItemIndex := ItemIndProjectGroup;
275   if fifSearchOpen        in NewOptions then NewItemIndex := ItemIndOpenFiles;
276   if fifSearchDirectories in NewOptions then NewItemIndex := ItemIndDirectories;
277   if fifSearchActive      in NewOptions then NewItemIndex := ItemIndActiveFile;
278   WhereRadioGroup.ItemIndex:=NewItemIndex;
279 
280   UpdateReplaceCheck;
281   UpdateDirectoryOptions;
282 end;
283 
GetOptionsnull284 function TLazFindInFilesDialog.GetOptions: TLazFindInFileSearchOptions;
285 var
286   Where: Integer;
287 begin
288   Result := [];
289   if OptionsCheckGroupBox.Checked[0] then Include(Result, fifMatchCase);
290   if OptionsCheckGroupBox.Checked[1] then Include(Result, fifWholeWord);
291   if OptionsCheckGroupBox.Checked[2] then Include(Result, fifRegExpr);
292   if OptionsCheckGroupBox.Checked[3] then Include(Result, fifMultiLine);
293   if IncludeSubDirsCheckBox.Checked then Include(Result, fifIncludeSubDirs);
294   if ReplaceCheckBox.Checked then Include(Result, fifReplace);
295 
296   Where:=WhereRadioGroup.ItemIndex;
297   if Where=ItemIndProject then Include(Result, fifSearchProject)
298   else if Where=ItemIndProjectGroup then Include(Result, fifSearchProjectGroup)
299   else if Where=ItemIndOpenFiles then Include(Result, fifSearchOpen)
300   else if Where=ItemIndDirectories then Include(Result, fifSearchDirectories)
301   else Include(Result, fifSearchActive);
302 end;
303 
GetSynOptionsnull304 function TLazFindInFilesDialog.GetSynOptions: TSynSearchOptions;
305 begin
306   Result := [];
307   if OptionsCheckGroupBox.Checked[0] then Include(Result, ssoMatchCase);
308   if OptionsCheckGroupBox.Checked[1] then Include(Result, ssoWholeWord);
309   if OptionsCheckGroupBox.Checked[2] then Include(Result, ssoRegExpr);
310   if OptionsCheckGroupBox.Checked[3] then Include(Result, ssoRegExprMultiLine);
311   if ReplaceCheckBox.Checked then Include(Result, ssoReplace);
312 end;//GetSynOptions
313 
314 procedure TLazFindInFilesDialog.SetReplaceText(const AValue: string);
315 begin
316   ReplaceTextComboBox.Text := AValue;
317 end;
318 
319 procedure TLazFindInFilesDialog.SetSynOptions(NewOptions: TSynSearchOptions);
320 begin
321   OptionsCheckGroupBox.Checked[0] := ssoMatchCase in NewOptions;
322   OptionsCheckGroupBox.Checked[1] := ssoWholeWord in NewOptions;
323   OptionsCheckGroupBox.Checked[2] := ssoRegExpr in NewOptions;
324   OptionsCheckGroupBox.Checked[3] := ssoRegExprMultiLine in NewOptions;
325   ReplaceCheckBox.Checked := ([ssoReplace,ssoReplaceAll]*NewOptions <> []);
326 
327   UpdateReplaceCheck;
328 end;//SetSynOptions
329 
330 procedure TLazFindInFilesDialog.UpdateReplaceCheck;
331 begin
332   ReplaceTextComboBox.Enabled:=ReplaceCheckBox.Checked;
333   if ReplaceCheckBox.Checked then
334     ButtonPanel1.OKButton.Caption := lisBtnReplace
335   else
336     ButtonPanel1.OKButton.Caption := lisBtnFind;
337 end;
338 
339 procedure TLazFindInFilesDialog.UpdateDirectoryOptions;
340 begin
341   if WhereRadioGroup.ItemIndex = ItemIndDirectories then
342   begin
343     DirectoriesOptionsGroupBox.Enabled := true;
344     DirectoriesBrowse.Enabled:=true;
345     DirectoriesComboBox.Enabled:=true;
346   end
347   else if WhereRadioGroup.ItemIndex = ItemIndProjectGroup then
348   begin
349     DirectoriesOptionsGroupBox.Enabled := true;
350     DirectoriesBrowse.Enabled:=false;
351     DirectoriesComboBox.Enabled:=false;
352   end else
353     DirectoriesOptionsGroupBox.Enabled := false;
354 end;
355 
GetBaseDirectorynull356 function TLazFindInFilesDialog.GetBaseDirectory: string;
357 begin
358   Result:='';
359   if Project1<>nil then
360     Result:=Project1.Directory;
361   if Result='' then
362     Result:=GetCurrentDirUTF8;
363 end;
364 
365 const
366   SharedOptions = [ssoMatchCase,ssoWholeWord,ssoRegExpr,ssoRegExprMultiLine];
367 
368 procedure TLazFindInFilesDialog.LoadHistory;
369 
370   procedure AssignToComboBox(AComboBox: TComboBox; Strings: TStrings);
371   begin
372     AComboBox.Items.Assign(Strings);
373     if AComboBox.Items.Count>0 then
374       AComboBox.ItemIndex := 0;
375   end;
376 
377   procedure AddFileToComboBox(AComboBox: TComboBox; Filename: string);
378   var
379     i: Integer;
380   begin
381     if Filename='' then exit;
382     Filename:=AppendPathDelim(TrimFilename(Filename));
383     for i:=0 to AComboBox.Items.Count-1 do begin
384       if CompareFilenames(Filename,AComboBox.Items[i])=0 then begin
385         // move to front (but not top, top should be the last used directory)
386         if i>2 then
387           AComboBox.Items.Move(i,1);
388         exit;
389       end;
390     end;
391     // insert in front (but not top, top should be the last used directory)
392     if AComboBox.Items.Count>0 then
393       i:=1
394     else
395       i:=0;
396     AComboBox.Items.Insert(i,Filename);
397   end;
398 
399 var
400   SrcEdit: TSourceEditorInterface;
401 begin
402   SrcEdit := SourceEditorManagerIntf.ActiveEditor;
403   //DebugLn('TSourceNotebook.LoadFindInFilesHistory ',dbgsName(TextToFindComboBox),' ',dbgsName(FindHistory));
404   TextToFindComboBox.Items.Assign(InputHistories.FindHistory);
405   ReplaceTextComboBox.Items.Assign(InputHistories.ReplaceHistory);
406   if not EditorOpts.FindTextAtCursor then begin
407     if TextToFindComboBox.Items.Count>0 then begin
408       //debugln('TSourceNotebook.LoadFindInFilesHistory A TextToFindComboBox.Text=',TextToFindComboBox.Text);
409       TextToFindComboBox.ItemIndex:=0;
410       TextToFindComboBox.SelectAll;
411       //debugln('TSourceNotebook.LoadFindInFilesHistory B TextToFindComboBox.Text=',TextToFindComboBox.Text);
412     end;
413   end;
414   // show last used directories and directory of current file
415   AssignToComboBox(DirectoriesComboBox, InputHistories.FindInFilesPathHistory);
416   if (SrcEdit<>nil) and (FilenameIsAbsolute(SrcEdit.FileName)) then
417     AddFileToComboBox(DirectoriesComboBox, ExtractFilePath(SrcEdit.FileName));
418   if DirectoriesComboBox.Items.Count>0 then
419     DirectoriesComboBox.Text:=DirectoriesComboBox.Items[0];
420   // show last used file masks
421   AssignToComboBox(FileMaskComboBox, InputHistories.FindInFilesMaskHistory);
422   Options := InputHistories.FindInFilesSearchOptions;
423   //share basic options with FindReplaceDlg
424   SynSearchOptions := InputHistoriesSO.FindOptions[False] * SharedOptions;
425 end;
426 
427 procedure TLazFindInFilesDialog.SaveHistory;
428 var
429   Dir: String;
430 begin
431   if ReplaceCheckBox.Checked then
432     InputHistories.AddToReplaceHistory(ReplaceText);
433   InputHistories.AddToFindHistory(FindText);
434   Dir:=AppendPathDelim(TrimFilename(DirectoriesComboBox.Text));
435   if Dir<>'' then
436     InputHistories.AddToFindInFilesPathHistory(Dir);
437   InputHistories.AddToFindInFilesMaskHistory(FileMaskComboBox.Text);
438   InputHistories.FindInFilesSearchOptions:=Options;
439   //share basic options with FindReplaceDlg
440   InputHistoriesSO.FindOptions[False] := InputHistoriesSO.FindOptions[False] - SharedOptions
441                                               + (SynSearchOptions*SharedOptions);
442   InputHistories.Save;
443 end;
444 
445 procedure TLazFindInFilesDialog.FindInSearchPath(SearchPath: string);
446 begin
447   debugln(['TLazFindInFilesDialog.FindInSearchPath ',SearchPath]);
448   InitFindText;
449   LoadHistory;
450   DirectoriesComboBox.Text:=SearchPath;
451   WhereRadioGroup.ItemIndex:=ItemIndDirectories;
452   // disable replace. Find in files is often called,
453   // but almost never to replace with the same parameters
454   Options := Options-[fifReplace,fifReplaceAll];
455   Execute;
456 end;
457 
458 procedure TLazFindInFilesDialog.FindInFilesPerDialog(AProject: TProject);
459 begin
460   InitFindText;
461   FindInFiles(AProject, FindText);
462 end;
463 
464 procedure TLazFindInFilesDialog.InitFindText;
465 var
466   TempEditor: TSourceEditorInterface;
467   NewFindText: String;
468 begin
469   NewFindText:='';
470   TempEditor := SourceEditorManagerIntf.ActiveEditor;
471   if TempEditor <> nil
472   then //with TempEditor.EditorComponent do
473   begin
474     if EditorOpts.FindTextAtCursor
475     then begin
476       if TempEditor.SelectionAvailable and (TempEditor.BlockBegin.Y = TempEditor.BlockEnd.Y)
477       then NewFindText := TempEditor.Selection
478       else NewFindText := TSynEdit(TempEditor.EditorControl).GetWordAtRowCol(TempEditor.CursorTextXY);
479     end else begin
480       if InputHistories.FindHistory.Count>0 then
481         NewFindText:=InputHistories.FindHistory[0];
482     end;
483   end;
484   FindText:=NewFindText;
485 end;
486 
487 procedure TLazFindInFilesDialog.InitFromLazSearch(Sender: TObject);
488 var
489   Dir: String;
490 begin
491   Dir:=AppendPathDelim(TrimFilename(TLazSearch(Sender).SearchDirectories));
492   if Dir<>'' then
493     DirectoriesComboBox.Text:= Dir;
494   Options:= TLazSearch(Sender).SearchOptions;
495   FileMaskComboBox.Text:= TLazSearch(Sender).SearchMask;
496 end;
497 
498 procedure TLazFindInFilesDialog.FindInFiles(AProject: TProject; const AFindText: string);
499 begin
500   LazProject:=AProject;
501   LoadHistory;
502 
503   // if there is no FindText, use the most recently used FindText
504   FindText:= AFindText;
505   if (FindText = '') and (InputHistories.FindHistory.Count > 0) then
506     FindText := InputHistories.FindHistory[0];
507 
508   // disable replace. Find in files is often called,
509   // but almost never to replace with the same parameters
510   Options := Options-[fifReplace,fifReplaceAll];
511   Execute;
512 end;
513 
GetResolvedDirectoriesnull514 function TLazFindInFilesDialog.GetResolvedDirectories: string;
515 begin
516   Result:=DirectoriesComboBox.Text;
517   IDEMacros.SubstituteMacros(Result);
518   Result:=TrimSearchPath(Result,GetBaseDirectory,true,true);
519 end;
520 
Executenull521 function TLazFindInFilesDialog.Execute: boolean;
522 var
523   SearchForm: TSearchProgressForm;
524   Where: Integer;
525 begin
526   if ShowModal=mrOk then
527   begin
528     Result:=true;
529     SaveHistory;
530 
531     SearchForm:= TSearchProgressForm.Create(SearchResultsView);
532     with SearchForm do begin
533       SearchOptions     := self.Options;
534       SearchText        := self.FindText;
535       ReplaceText       := self.ReplaceText;
536       SearchMask        := self.FileMaskComboBox.Text;
537       SearchDirectories := self.GetResolvedDirectories;
538     end;
539 
540     try
541       if FindText <> '' then
542       begin
543         Where:=WhereRadioGroup.ItemIndex;
544         if Where=ItemIndProject then
545         begin
546           if LazProject=nil then
547             SearchForm.DoSearchProject(Project1)
548           else
549             SearchForm.DoSearchProject(LazProject);
550         end else if Where=ItemIndProjectGroup then
551         begin
552           SearchForm.SearchOptions:=SearchForm.SearchOptions-[fifIncludeSubDirs];
553           SearchForm.DoSearchProjectGroup;
554         end
555         else if Where=ItemIndOpenFiles then
556           SearchForm.DoSearchOpenFiles
557         else if Where=ItemIndDirectories then
558           SearchForm.DoSearchDirs
559         else
560           SearchForm.DoSearchActiveFile;
561       end;
562     finally
563       FreeAndNil(SearchForm);
564     end;
565   end else
566     Result:=false;
567 
568   FProject:=nil;
569 end;
570 
571 end.
572 
573