1 {
2 /***************************************************************************
3 inputhistory.pas
4 ----------------
5
6 ***************************************************************************/
7
8 ***************************************************************************
9 * *
10 * This source is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This code is distributed in the hope that it will be useful, but *
16 * WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
18 * General Public License for more details. *
19 * *
20 * A copy of the GNU General Public License is available on the World *
21 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
22 * obtain it by writing to the Free Software Foundation, *
23 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
24 * *
25 ***************************************************************************
26
27 Author: Mattias Gaertner
28
29 Abstract:
30 History lists for strings and file names.
31 }
32 unit InputHistory;
33
34 {$mode objfpc}{$H+}
35
36 interface
37
38 uses
39 // RTL + LCL
40 Classes, SysUtils, Laz_AVL_Tree,
41 // LCL
42 Dialogs,
43 // LazUtils
44 LazFileCache, LazFileUtils, LazUTF8, AvgLvlTree, Laz2_XMLCfg,
45 // Codetools
46 FileProcs,
47 // IdeIntf
48 ProjectIntf, IDEDialogs,
49 // IDE
50 DiffPatch, LazConf, IDEProcs;
51
52 {$ifdef Windows}
53 {$define CaseInsensitiveFilenames}
54 {$endif}
55
56 const
57 // these are the names of the various history lists in the IDE:
58 hlPublishModuleDestDirs = 'PublishModuleDestinationDirectories';
59 hlPublishModuleFileFilter = 'PublishModuleFileFilter';
60 hlMakeResourceStringSections = 'MakeResourceStringSections';
61 hlMakeResourceStringPrefixes = 'MakeResourceStringPrefixes';
62 hlMakeResourceStringLengths = 'MakeResourceStringLengths';
63 hlCodeToolsDirectories = 'CodeToolsDirectories';
64 hlCompilerOptsImExport = 'CompilerOptsImExport';
65 hlCleanBuildFileMask = 'CleanBuildFileMask';
66
67 type
68 TFileDialogSettings = record
69 InitialDir: string;
70 Width: integer;
71 Height: integer;
72 HistoryList: TStringList;
73 MaxHistory: integer;
74 end;
75
76
77 { THistoryList - a TStringList to store a history list }
78
79 THistoryList = class(TStringList)
80 private
81 FListType: TRecentListType;
82 FMaxCount: integer;
83 FName: string;
84 procedure SetMaxCount(const AValue: integer);
85 procedure SetName(const AValue: string);
86 public
87 constructor Create(TheListType: TRecentListType);
88 destructor Destroy; override;
Pushnull89 function Push(const Entry: string): integer;
90 procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
91 procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
92 procedure AppendEntry(const Entry: string);
IndexOfnull93 function IndexOf(const S: string): Integer; override;
94 public
95 property Name: string read FName write SetName;
96 property MaxCount: integer read FMaxCount write SetMaxCount;
97 property ListType: TRecentListType read FListType;
98 end;
99
100
101 { THistoryLists - list of THistoryList }
102
103 THistoryLists = class
104 private
105 FItems: TList;
GetItemsnull106 function GetItems(Index: integer): THistoryList;
GetXMLListPathnull107 function GetXMLListPath(const Path: string; i: integer; ALegacyList: Boolean): string;
108 public
109 constructor Create;
110 destructor Destroy; override;
111 procedure Clear;
Countnull112 function Count: integer;
113 procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
114 procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string; const ALegacyList: Boolean);
IndexOfNamenull115 function IndexOfName(const Name: string): integer;
GetListnull116 function GetList(const Name: string;
117 CreateIfNotExists: boolean; ListType: TRecentListType): THistoryList;
118 procedure Add(const ListName, Entry: string; ListType: TRecentListType);
119 property Items[Index: integer]: THistoryList read GetItems;
120 end;
121
122
123 { TInputHistories }
124
125 TLazFindInFileSearchOption = (
126 fifMatchCase,
127 fifWholeWord,
128 fifRegExpr,
129 fifMultiLine,
130 fifSearchProject, // search in all project files
131 fifSearchProjectGroup,// search in all files of project group
132 fifSearchOpen, // search in all open files in editor
133 fifSearchActive, // search in active open file in editor
134 fifSearchDirectories,// search in directories
135 fifIncludeSubDirs,
136 fifReplace, // replace and ask user before each replace
137 fifReplaceAll // replace without asking user
138 );
139 TLazFindInFileSearchOptions = set of TLazFindInFileSearchOption;
140
141
142 { TIHIgnoreIDEQuestionList }
143
144 TIHIgnoreIDEQuestionList = class(TIgnoreIDEQuestionList)
145 private
146 FItems: TAvlTree; // tree of TIgnoreIDEQuestionItem
FindNodenull147 function FindNode(const Identifier: string): TAvlTreeNode;
148 public
149 constructor Create;
150 destructor Destroy; override;
151 procedure Clear;
Addnull152 function Add(const Identifier: string;
153 const Duration: TIgnoreQuestionDuration;
154 const Flag: string = ''): TIgnoreIDEQuestionItem; override;
155 procedure Delete(const Identifier: string); override;
Findnull156 function Find(const Identifier: string): TIgnoreIDEQuestionItem; override;
157 procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
158 procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
159 end;
160
161 TInputHistories = class
162 private
163 FCleanOutputFileMask: string;
164 FCleanSourcesFileMask: string;
165 FDiffFlags: TTextDiffFlags;
166 FDiffText2: string;
167 FDiffText2OnlySelection: boolean;
168 FFileDialogSettings: TFileDialogSettings;
169 FFilename: string;
170
171 // Find- and replace-history
172 FFindHistory: TStringList;
173 FFindInFilesSearchOptions: TLazFindInFileSearchOptions;
174 FFindAutoComplete: boolean;
175 FIgnores: TIHIgnoreIDEQuestionList;
176 FLastConvertDelphiPackage: string;
177 FLastConvertDelphiProject: string;
178 FLastConvertDelphiUnit: string;
179 FViewNeedBuildTarget: string;
180 FNewFileType: string;
181 FNewProjectType: string;
182 FReplaceHistory: TStringList;
183 FFindInFilesPathHistory: TStringList;
184 FFindInFilesMaskHistory: TStringList;
185 FMaxFindHistory: Integer;
186
187 // various history lists
188 FHistoryLists: THistoryLists;
189 // file encodings
190 fFileEncodings: TStringToStringTree;
191
192 procedure SetFilename(const AValue: string);
193 protected
194 procedure LoadSearchOptions(XMLConfig: TXMLConfig; const Path: string); virtual; abstract;
195 procedure SaveSearchOptions(XMLConfig: TXMLConfig; const Path: string); virtual; abstract;
196 public
197 constructor Create;
198 destructor Destroy; override;
199 procedure Clear;
200 procedure Load;
201 procedure Save;
202 procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
203 procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
204 procedure SetLazarusDefaultFilename;
205
206 // Find- and replace-history
AddToFindHistorynull207 function AddToFindHistory(const AFindStr: string): boolean;
AddToReplaceHistorynull208 function AddToReplaceHistory(const AReplaceStr: String): boolean;
AddToFindInFilesPathHistorynull209 function AddToFindInFilesPathHistory(const APathStr: String): boolean;
AddToFindInFilesMaskHistorynull210 function AddToFindInFilesMaskHistory(const AMaskStr: String): boolean;
211
212 // filedialog
213 procedure ApplyFileDialogSettings(DestDialog: TFileDialog);
214 procedure StoreFileDialogSettings(SourceDialog: TFileDialog);
215 procedure SetFileDialogSettingsInitialDir(const InitialDir: string);
SelectDirectorynull216 function SelectDirectory(const {%H-}Title: string;
217 MustExist: boolean = true;
218 const InitialDir: string = '';
219 const Directory: string = ''): string;
220 public
221 property Filename: string read FFilename write SetFilename;
222
223 // Find- and replace-history
224 property MaxFindHistory: Integer read FMaxFindHistory write FMaxFindHistory;
225 property FindHistory: TStringList read FFindHistory write FFindHistory;
226 property ReplaceHistory: TStringList read FReplaceHistory write FReplaceHistory;
227 property FindInFilesPathHistory: TStringList read FFindInFilesPathHistory
228 write FFindInFilesPathHistory;
229 property FindInFilesMaskHistory: TStringList read FFindInFilesMaskHistory
230 write FFindInFilesMaskHistory;
231 property FindInFilesSearchOptions: TLazFindInFileSearchOptions
232 read FFindInFilesSearchOptions write FFindInFilesSearchOptions;
233 property FindAutoComplete: boolean read FFindAutoComplete
234 write FFindAutoComplete;
235
236 // filedialogs
237 property FileDialogSettings: TFileDialogSettings
238 read FFileDialogSettings write FFileDialogSettings;
239 property CleanOutputFileMask: string read FCleanOutputFileMask write FCleanOutputFileMask;
240 property CleanSourcesFileMask: string read FCleanSourcesFileMask write FCleanSourcesFileMask;
241
242 // various history lists
243 property HistoryLists: THistoryLists read FHistoryLists;
244
245 // diff dialog
246 property DiffFlags: TTextDiffFlags read FDiffFlags write FDiffFlags;
247 property DiffText2: string read FDiffText2 write FDiffText2;
248 property DiffText2OnlySelection: boolean read FDiffText2OnlySelection
249 write FDiffText2OnlySelection;
250 // new dialog
251 property NewProjectType: string read FNewProjectType write FNewProjectType;
252 property NewFileType: string read FNewFileType write FNewFileType;
253
254 // Delphi conversion
255 property LastConvertDelphiProject: string read FLastConvertDelphiProject
256 write FLastConvertDelphiProject;
257 property LastConvertDelphiPackage: string read FLastConvertDelphiPackage
258 write FLastConvertDelphiPackage;
259 property LastConvertDelphiUnit: string read FLastConvertDelphiUnit
260 write FLastConvertDelphiUnit;
261
262 // View / internals
263 property ViewNeedBuildTarget: string read FViewNeedBuildTarget
264 write FViewNeedBuildTarget;
265
266 // file encodings
267 property FileEncodings: TStringToStringTree read fFileEncodings write fFileEncodings;
268
269 // ignores
270 property Ignores: TIHIgnoreIDEQuestionList read FIgnores;
271 end;
272
273 const
274 LazFindInFileSearchOptionsDefault = [fifSearchOpen, fifIncludeSubDirs];
275 LazFindInFileSearchOptionNames: array[TLazFindInFileSearchOption] of string =(
276 'MatchCase',
277 'WholeWord',
278 'RegExpr',
279 'MultiLine',
280 'SearchProject',
281 'SearchProjectGroup',
282 'SearchOpen',
283 'SearchCurrent',
284 'SearchDirectories',
285 'IncludeSubDirs',
286 'Replace',
287 'ReplaceAll'
288 );
289 IHIgnoreItemDurationNames: array[TIgnoreQuestionDuration] of string = (
290 'IDERestart',
291 '24H',
292 'Forever'
293 );
294
295 var
296 InputHistories: TInputHistories = nil;
297
CompareIHIgnoreItemsnull298 function CompareIHIgnoreItems(Item1, Item2: Pointer): integer;
CompareAnsiStringWithIHIgnoreItemnull299 function CompareAnsiStringWithIHIgnoreItem(AString, Item: Pointer): integer;
300
NameToIHIgnoreItemDurationnull301 function NameToIHIgnoreItemDuration(const s: string): TIgnoreQuestionDuration;
302
303
304 implementation
305
306
307 const
308 DefaultHistoryFile = 'inputhistory.xml';
309 InputHistoryVersion = 1;
310 DefaultDiffFlags = [tdfIgnoreCase,tdfIgnoreEmptyLineChanges,
311 tdfIgnoreLineEnds,tdfIgnoreTrailingSpaces];
312
CompareIHIgnoreItemsnull313 function CompareIHIgnoreItems(Item1, Item2: Pointer): integer;
314 var
315 IgnoreItem1: TIgnoreIDEQuestionItem absolute Item1;
316 IgnoreItem2: TIgnoreIDEQuestionItem absolute Item2;
317 begin
318 Result:=SysUtils.CompareText(IgnoreItem1.Identifier,IgnoreItem2.Identifier);
319 end;
320
CompareAnsiStringWithIHIgnoreItemnull321 function CompareAnsiStringWithIHIgnoreItem(AString, Item: Pointer): integer;
322 var
323 IgnoreItem: TIgnoreIDEQuestionItem absolute Item;
324 begin
325 Result:=SysUtils.CompareText(AnsiString(AString),IgnoreItem.Identifier);
326 end;
327
NameToIHIgnoreItemDurationnull328 function NameToIHIgnoreItemDuration(const s: string): TIgnoreQuestionDuration;
329 begin
330 for Result:=low(TIgnoreQuestionDuration) to high(TIgnoreQuestionDuration) do
331 if SysUtils.CompareText(IHIgnoreItemDurationNames[Result],s)=0 then exit;
332 Result:=iiidIDERestart;
333 end;
334
335 { TInputHistories }
336
337 procedure TInputHistories.SetFilename(const AValue: string);
338 begin
339 FFilename:=AValue;
340 end;
341
342 constructor TInputHistories.Create;
343 begin
344 inherited Create;
345 FFilename:='';
346
347 // Find- and replace-history
348 FMaxFindHistory:=20;
349 FFindAutoComplete:=true;
350 FFindHistory:=TStringList.Create;
351 FReplaceHistory:=TStringList.Create;
352 FFindInFilesPathHistory:=TStringList.Create;
353 FFindInFilesMaskHistory:=TStringList.Create;
354 FFindInFilesSearchOptions:=LazFindInFileSearchOptionsDefault;
355
356 // file dialog
357 FFileDialogSettings.HistoryList:=TStringList.Create;
358 FFileDialogSettings.MaxHistory:=20;
359
360 // various history lists
361 FHistoryLists:=THistoryLists.Create;
362 fFileEncodings:=TStringToStringTree.Create({$IFDEF CaseInsensitiveFilenames}false{$ELSE}true{$ENDIF});
363 FIgnores:=TIHIgnoreIDEQuestionList.Create;
364 IgnoreQuestions:=FIgnores;
365
366 Clear;
367 end;
368
369 destructor TInputHistories.Destroy;
370 begin
371 IgnoreQuestions:=nil;
372 FreeAndNil(FIgnores);
373 FreeAndNil(FHistoryLists);
374 FreeAndNil(FFileDialogSettings.HistoryList);
375 FreeAndNil(FFindHistory);
376 FreeAndNil(FReplaceHistory);
377 FreeAndNil(FFindInFilesPathHistory);
378 FreeAndNil(FFindInFilesMaskHistory);
379 FreeAndNil(fFileEncodings);
380 inherited Destroy;
381 end;
382
383 procedure TInputHistories.Clear;
384 begin
385 FHistoryLists.Clear;
386 FFindHistory.Clear;
387 FReplaceHistory.Clear;
388 FFindInFilesPathHistory.Clear;
389 FFindInFilesMaskHistory.Clear;
390 with FFileDialogSettings do begin
391 HistoryList.Clear;
392 Width:=0;
393 Height:=0;
394 InitialDir:='';
395 end;
396 FDiffFlags:=DefaultDiffFlags;
397 FDiffText2:='';
398 FDiffText2OnlySelection:=false;
399 FNewProjectType:='';
400 FNewFileType:='';
401 FLastConvertDelphiProject:='';
402 FLastConvertDelphiUnit:='';
403 FCleanOutputFileMask:=DefaultProjectCleanOutputFileMask;
404 FCleanSourcesFileMask:=DefaultProjectCleanSourcesFileMask;
405 fFileEncodings.Clear;
406 FIgnores.Clear;
407 end;
408
409 procedure TInputHistories.LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
410 var
411 DiffFlag: TTextDiffFlag;
412 FIFOption: TLazFindInFileSearchOption;
413 begin
414 // Find- and replace-history
415 FMaxFindHistory:=XMLConfig.GetValue(Path+'Find/History/Max',FMaxFindHistory);
416 FFindAutoComplete:=XMLConfig.GetValue(Path+'Find/AutoComplete/Value',FFindAutoComplete);
417 LoadRecentList(XMLConfig,FFindHistory,Path+'Find/History/Find/',rltCaseSensitive);
418 LoadRecentList(XMLConfig,FReplaceHistory,Path+'Find/History/Replace/',rltCaseSensitive);
419 LoadRecentList(XMLConfig,FFindInFilesPathHistory,Path+
420 'FindInFiles/History/Paths/',rltFile);
421 LoadRecentList(XMLConfig,FFindInFilesMaskHistory,Path+
422 'FindInFiles/History/Masks/',rltFile);
423 FFindInFilesSearchOptions:=[];
424 for FIFOption:=Low(TLazFindInFileSearchOption) to High(TLazFindInFileSearchOption)
425 do begin
426 if XMLConfig.GetValue(
427 Path+'FindInFiles/Options/'+LazFindInFileSearchOptionNames[FIFOption],
428 FIFOption in LazFindInFileSearchOptionsDefault)
429 then
430 Include(FFindInFilesSearchOptions,FIFOption);
431 end;
432 LoadSearchOptions(XMLConfig, Path); // Search Options depend on SynEdit.
433
434 // file dialog
435 with FFileDialogSettings do begin
436 Width:=XMLConfig.GetValue(Path+'FileDialog/Width',0);
437 Height:=XMLConfig.GetValue(Path+'FileDialog/Height',0);
438 InitialDir:=XMLConfig.GetValue(Path+'FileDialog/InitialDir','');
439 MaxHistory:=XMLConfig.GetValue(Path+'FileDialog/MaxHistory',20);
440 LoadRecentList(XMLConfig,HistoryList,Path+'FileDialog/HistoryList/',rltFile);
441 end;
442 FCleanOutputFileMask:=XMLConfig.GetValue(Path+'Clean/OutputFilemask',
443 DefaultProjectCleanOutputFileMask);
444 FCleanSourcesFileMask:=XMLConfig.GetValue(Path+'Clean/SourcesFilemask',
445 DefaultProjectCleanSourcesFileMask);
446 // history lists
447 FHistoryLists.LoadFromXMLConfig(XMLConfig,Path+'HistoryLists/');
448 // diff dialog
449 FDiffFlags:=[];
450 for DiffFlag:=Low(TTextDiffFlag) to High(TTextDiffFlag) do begin
451 if XMLConfig.GetValue(
452 Path+'DiffDialog/Options/'+TextDiffFlagNames[DiffFlag],
453 DiffFlag in DefaultDiffFlags)
454 then
455 Include(FDiffFlags,DiffFlag);
456 end;
457 FDiffText2:=XMLConfig.GetValue(Path+'DiffDialog/Text2/Name','');
458 FDiffText2OnlySelection:=
459 XMLConfig.GetValue(Path+'DiffDialog/Text2/OnlySelection',false);
460
461 // new items
462 FNewProjectType:=XMLConfig.GetValue(Path+'New/Project/Type','');
463 FNewFileType:=XMLConfig.GetValue(Path+'New/File/Type','');
464
465 // delphi conversion
466 FLastConvertDelphiProject:=XMLConfig.GetValue(Path+'Conversion/Delphi/Project','');
467 FLastConvertDelphiPackage:=XMLConfig.GetValue(Path+'Conversion/Delphi/Package','');
468 FLastConvertDelphiUnit:=XMLConfig.GetValue(Path+'Conversion/Delphi/Unit','');
469
470 // view internals
471 ViewNeedBuildTarget:=XMLConfig.GetValue(Path+'View/NeedBuild/Target','');
472
473 // encodings
474 LoadStringToStringTree(XMLConfig,fFileEncodings,Path+'FileEncodings/');
475
476 Ignores.LoadFromXMLConfig(XMLConfig,Path+'Ignores/');
477 end;
478
479 procedure TInputHistories.SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
480 var
481 DiffFlag: TTextDiffFlag;
482 FIFOption: TLazFindInFileSearchOption;
483 begin
484 // Find- and replace-history
485 XMLConfig.SetDeleteValue(Path+'Find/History/Max',FMaxFindHistory,20);
486 XMLConfig.SetDeleteValue(Path+'Find/AutoComplete/Value',FFindAutoComplete,true);
487 SaveRecentList(XMLConfig,FFindHistory,Path+'Find/History/Find/');
488 SaveRecentList(XMLConfig,FReplaceHistory,Path+'Find/History/Replace/');
489 SaveRecentList(XMLConfig,FFindInFilesPathHistory,Path+
490 'FindInFiles/History/Paths/');
491 SaveRecentList(XMLConfig,FFindInFilesMaskHistory,Path+
492 'FindInFiles/History/Masks/');
493 for FIFOption:=Low(TLazFindInFileSearchOption)
494 to High(TLazFindInFileSearchOption) do begin
495 XMLConfig.SetDeleteValue(
496 Path+'FindInFiles/Options/'+LazFindInFileSearchOptionNames[FIFOption],
497 FIFOption in FindInFilesSearchOptions,
498 FIFOption in LazFindInFileSearchOptionsDefault);
499 end;
500 SaveSearchOptions(XMLConfig, Path); // Search Options depend on SynEdit.
501
502 // file dialog
503 with FFileDialogSettings do begin
504 XMLConfig.SetDeleteValue(Path+'FileDialog/Width',Width,0);
505 XMLConfig.SetDeleteValue(Path+'FileDialog/Height',Height,0);
506 XMLConfig.SetDeleteValue(Path+'FileDialog/InitialDir',InitialDir,'');
507 XMLConfig.SetDeleteValue(Path+'FileDialog/MaxHistory',MaxHistory,20);
508 SaveRecentList(XMLConfig,HistoryList,Path+'FileDialog/HistoryList/');
509 end;
510 XMLConfig.SetDeleteValue(Path+'Clean/OutputFilemask',FCleanOutputFileMask,
511 DefaultProjectCleanOutputFileMask);
512 XMLConfig.SetDeleteValue(Path+'Clean/SourcesFilemask',FCleanSourcesFileMask,
513 DefaultProjectCleanSourcesFileMask);
514 // history lists
515 FHistoryLists.SaveToXMLConfig(XMLConfig,Path+'HistoryLists/',True);
516 // diff dialog
517 for DiffFlag:=Low(TTextDiffFlag) to High(TTextDiffFlag) do begin
518 XMLConfig.SetDeleteValue(
519 Path+'DiffDialog/Options/'+TextDiffFlagNames[DiffFlag],
520 DiffFlag in DiffFlags,DiffFlag in DefaultDiffFlags);
521 end;
522 XMLConfig.SetDeleteValue(Path+'DiffDialog/Text2/Name',FDiffText2,'');
523 XMLConfig.SetDeleteValue(Path+'DiffDialog/Text2/OnlySelection',
524 FDiffText2OnlySelection,false);
525
526 // new items
527 XMLConfig.SetDeleteValue(Path+'New/Project/Type',FNewProjectType,'');
528 XMLConfig.SetDeleteValue(Path+'New/File/Type',FNewFileType,'');
529
530 // delphi conversion
531 XMLConfig.SetDeleteValue(Path+'Conversion/Delphi/Project',
532 FLastConvertDelphiProject,'');
533 XMLConfig.SetDeleteValue(Path+'Conversion/Delphi/Package',
534 FLastConvertDelphiPackage,'');
535 XMLConfig.SetDeleteValue(Path+'Conversion/Delphi/Unit',
536 FLastConvertDelphiUnit,'');
537
538 // view internals
539 XMLConfig.SetDeleteValue(Path+'View/NeedBuild/Target',ViewNeedBuildTarget,'');
540
541 // encodings
542 SaveStringToStringTree(XMLConfig,fFileEncodings,Path+'FileEncodings/');
543
544 Ignores.SaveToXMLConfig(XMLConfig,Path+'Ignores/');
545 end;
546
547 procedure TInputHistories.SetLazarusDefaultFilename;
548 var
549 ConfFileName: string;
550 begin
551 ConfFileName:=AppendPathDelim(GetPrimaryConfigPath)+DefaultHistoryFile;
552 CopySecondaryConfigFile(DefaultHistoryFile);
553 FFilename:=ConfFilename;
554 end;
555
556 procedure TInputHistories.Load;
557 var
558 XMLConfig: TXMLConfig;
559 //FileVersion: integer;
560 begin
561 try
562 XMLConfig:=TXMLConfig.Create(FFileName);
563 //FileVersion:=XMLConfig.GetValue('InputHistory/Version/Value',0);
564 LoadFromXMLConfig(XMLConfig,'InputHistory/');
565 XMLConfig.Free;
566 except
567 on E: Exception do begin
568 DebugLn('[TCodeToolsOptions.Load] error reading "',FFilename,'" ',E.Message);
569 end;
570 end;
571 end;
572
573 procedure TInputHistories.Save;
574 var
575 XMLConfig: TXMLConfig;
576 begin
577 try
578 InvalidateFileStateCache;
579 XMLConfig:=TXMLConfig.CreateClean(FFileName);
580 XMLConfig.SetDeleteValue('InputHistory/Version/Value',InputHistoryVersion,0);
581 SaveToXMLConfig(XMLConfig,'InputHistory/');
582 XMLConfig.Flush;
583 XMLConfig.Free;
584 except
585 on E: Exception do begin
586 DebugLn('[TInputHistories.Save] error writing "',FFilename,'" ',E.Message);
587 end;
588 end;
589 end;
590
TInputHistories.AddToFindHistorynull591 function TInputHistories.AddToFindHistory(const AFindStr: string): boolean;
592 begin
593 Result:=AddToRecentList(AFindStr,FFindHistory,FMaxFindHistory,rltCaseSensitive);
594 end;
595
TInputHistories.AddToReplaceHistorynull596 function TInputHistories.AddToReplaceHistory(const AReplaceStr: String): boolean;
597 begin
598 Result:=AddToRecentList(AReplaceStr,FReplaceHistory,FMaxFindHistory,rltCaseSensitive);
599 end;
600
TInputHistories.AddToFindInFilesPathHistorynull601 function TInputHistories.AddToFindInFilesPathHistory(const APathStr: String): boolean;
602 begin
603 Result:= AddToRecentList(APathStr,FFindInFilesPathHistory,FMaxFindHistory,rltFile);
604 end;
605
AddToFindInFilesMaskHistorynull606 function TInputHistories.AddToFindInFilesMaskHistory(const AMaskStr: String): boolean;
607 begin
608 Result:= AddToRecentList(AMaskStr,FFindInFilesMaskHistory,FMaxFindHistory,rltFile);
609 end;
610
611 procedure TInputHistories.ApplyFileDialogSettings(DestDialog: TFileDialog);
612 begin
613 DestDialog.InitialDir:=FFileDialogSettings.InitialDir;
614 DestDialog.Width:=FFileDialogSettings.Width;
615 DestDialog.Height:=FFileDialogSettings.Height;
616
617 DestDialog.HistoryList:=FFileDialogSettings.HistoryList;
618 end;
619
620 procedure TInputHistories.StoreFileDialogSettings(SourceDialog: TFileDialog);
621 var s: string;
622 begin
623 FFileDialogSettings.InitialDir:=SourceDialog.InitialDir;
624 FFileDialogSettings.Width:=SourceDialog.Width;
625 FFileDialogSettings.Height:=SourceDialog.Height;
626 s:=ExtractFilePath(FFileDialogSettings.InitialDir);
627 if s<>'' then
628 AddToRecentList(s,FFileDialogSettings.HistoryList,
629 FFileDialogSettings.MaxHistory,rltFile);
630 end;
631
632 procedure TInputHistories.SetFileDialogSettingsInitialDir(const InitialDir: string);
633 begin
634 FFileDialogSettings.InitialDir := InitialDir;
635 end;
636
TInputHistories.SelectDirectorynull637 function TInputHistories.SelectDirectory(const Title: string;
638 MustExist: boolean; const InitialDir: string; const Directory: string): string;
639 var
640 WorkDirectoryDialog: TSelectDirectoryDialog;
641 begin
642 Result:='';
643 WorkDirectoryDialog := TSelectDirectoryDialog.Create(nil);
644 try
645 ApplyFileDialogSettings(WorkDirectoryDialog);
646 if MustExist then
647 WorkDirectoryDialog.Options:=WorkDirectoryDialog.Options+[ofFileMustExist];
648 if InitialDir <> '' then
649 WorkDirectoryDialog.InitialDir := InitialDir;
650 if Directory<>'' then
651 WorkDirectoryDialog.Filename := Directory;
652 if WorkDirectoryDialog.Execute then begin
653 Result := WorkDirectoryDialog.Filename;
654 end;
655 StoreFileDialogSettings(WorkDirectoryDialog);
656 finally
657 WorkDirectoryDialog.Free;
658 end;
659 end;
660
661 { THistoryList }
662
663 procedure THistoryList.SetMaxCount(const AValue: integer);
664 begin
665 if FMaxCount=AValue then exit;
666 FMaxCount:=AValue;
667 end;
668
669 procedure THistoryList.SetName(const AValue: string);
670 begin
671 if FName=AValue then exit;
672 FName:=AValue;
673 end;
674
675 constructor THistoryList.Create(TheListType: TRecentListType);
676 begin
677 FListType:=TheListType;
678 FMaxCount:=20;
679 end;
680
681 destructor THistoryList.Destroy;
682 begin
683 inherited Destroy;
684 end;
685
THistoryList.Pushnull686 function THistoryList.Push(const Entry: string): integer;
687 begin
688 if Entry<>'' then
689 AddToRecentList(Entry,Self,MaxCount,ListType);
690 Result:=-1;
691 end;
692
693 procedure THistoryList.LoadFromXMLConfig(XMLConfig: TXMLConfig;
694 const Path: string);
695 begin
696 if FName='' then
697 FName:=XMLConfig.GetValue(Path+'Name','');
698 FMaxCount:=XMLConfig.GetValue(Path+'MaxCount',MaxCount);
699 FListType:=StrToRecentListType(XMLConfig.GetValue(Path+'Type',''));
700 LoadRecentList(XMLConfig,Self,Path,ListType);
701 end;
702
703 procedure THistoryList.SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
704 begin
705 XMLConfig.SetDeleteValue(Path+'Name',Name,'');
706 XMLConfig.SetDeleteValue(Path+'Type',RecentListTypeNames[ListType],
707 RecentListTypeNames[rltCaseSensitive]);
708 XMLConfig.SetDeleteValue(Path+'MaxCount',MaxCount,20);
709 SaveRecentList(XMLConfig,Self,Path);
710 end;
711
712 procedure THistoryList.AppendEntry(const Entry: string);
713 begin
714 if (Count<MaxCount) and (IndexOf(Entry)<0) then
715 Add(Entry);
716 end;
717
IndexOfnull718 function THistoryList.IndexOf(const S: string): Integer;
719 var
720 i: Integer;
721 begin
722 for i:=0 to Count-1 do
723 if CompareRecentListItem(S,Strings[i],ListType) then
724 exit(i);
725 Result:=-1;
726 end;
727
728 { THistoryLists }
729
THistoryLists.GetItemsnull730 function THistoryLists.GetItems(Index: integer): THistoryList;
731 begin
732 Result:=THistoryList(FItems[Index]);
733 end;
734
GetXMLListPathnull735 function THistoryLists.GetXMLListPath(const Path: string; i: integer;
736 ALegacyList: Boolean): string;
737 begin
738 Result:=Path+TXMLConfig.GetListItemXPath('List', i, ALegacyList, False)+'/';
739 end;
740
741 constructor THistoryLists.Create;
742 begin
743 FItems:=TList.Create;
744 end;
745
746 destructor THistoryLists.Destroy;
747 begin
748 Clear;
749 FItems.Free;
750 inherited Destroy;
751 end;
752
753 procedure THistoryLists.Clear;
754 var i: integer;
755 begin
756 for i:=0 to Count-1 do
757 Items[i].Free;
758 FItems.Clear;
759 end;
760
THistoryLists.Countnull761 function THistoryLists.Count: integer;
762 begin
763 Result:=FItems.Count;
764 end;
765
766 procedure THistoryLists.LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
767 var
768 MergeCount, i: integer;
769 CurList: THistoryList;
770 ListName, ListPath: string;
771 ListType: TRecentListType;
772 IsLegacyList: Boolean;
773 begin
774 IsLegacyList:=XMLConfig.IsLegacyList(Path);
775 MergeCount:=XMLConfig.GetListItemCount(Path, 'List', IsLegacyList);
776 for i:=0 to MergeCount-1 do begin
777 ListPath:=GetXMLListPath(Path,i,IsLegacyList);
778 ListName:=XMLConfig.GetValue(ListPath+'Name','');
779 if ListName='' then continue;
780 ListType:=StrToRecentListType(XMLConfig.GetValue(ListPath+'Type',''));
781 CurList:=GetList(ListName,true,ListType);
782 CurList.LoadFromXMLConfig(XMLConfig,ListPath);
783 end;
784 end;
785
786 procedure THistoryLists.SaveToXMLConfig(XMLConfig: TXMLConfig;
787 const Path: string; const ALegacyList: Boolean);
788 var
789 i, CurID: integer;
790 begin
791 XMLConfig.SetListItemCount(Path,Count,ALegacyList);
792 CurID:=0;
793 for i:=0 to Count-1 do begin
794 if Items[i].Count>0 then begin
795 Items[i].SaveToXMLConfig(XMLConfig,GetXMLListPath(Path,CurID,ALegacyList));
796 inc(CurID);
797 end;
798 end;
799 end;
800
IndexOfNamenull801 function THistoryLists.IndexOfName(const Name: string): integer;
802 begin
803 Result:=Count-1;
804 while (Result>=0) and (UTF8CompareLatinTextFast(Items[Result].Name,Name)<>0) do
805 dec(Result);
806 end;
807
GetListnull808 function THistoryLists.GetList(const Name: string; CreateIfNotExists: boolean;
809 ListType: TRecentListType): THistoryList;
810 var
811 i: integer;
812 begin
813 i:=IndexOfName(Name);
814 if i>=0 then
815 Result:=Items[i]
816 else if CreateIfNotExists then begin
817 Result:=THistoryList.Create(ListType);
818 Result.Name:=Name;
819 FItems.Add(Result);
820 end else
821 Result:=nil;
822 end;
823
824 procedure THistoryLists.Add(const ListName, Entry: string;
825 ListType: TRecentListType);
826 begin
827 GetList(ListName,true,ListType).Push(Entry);
828 end;
829
830 { TIHIgnoreIDEQuestionList }
831
FindNodenull832 function TIHIgnoreIDEQuestionList.FindNode(const Identifier: string): TAvlTreeNode;
833 begin
834 Result:=FItems.FindKey(Pointer(Identifier),@CompareAnsiStringWithIHIgnoreItem);
835 end;
836
837 constructor TIHIgnoreIDEQuestionList.Create;
838 begin
839 FItems:=TAvlTree.Create(@CompareIHIgnoreItems);
840 end;
841
842 destructor TIHIgnoreIDEQuestionList.Destroy;
843 begin
844 FItems.FreeAndClear;
845 FreeAndNil(FItems);
846 inherited Destroy;
847 end;
848
849 procedure TIHIgnoreIDEQuestionList.Clear;
850 begin
851 FItems.FreeAndClear;
852 end;
853
Addnull854 function TIHIgnoreIDEQuestionList.Add(const Identifier: string;
855 const Duration: TIgnoreQuestionDuration; const Flag: string): TIgnoreIDEQuestionItem;
856 var
857 Node: TAvlTreeNode;
858 begin
859 Node:=FindNode(Identifier);
860 if Node<>nil then begin
861 Result:=TIgnoreIDEQuestionItem(Node.Data);
862 end else begin
863 Result:=TIgnoreIDEQuestionItem.Create(Identifier);
864 FItems.Add(Result);
865 end;
866 Result.Duration:=Duration;
867 Result.Date:=Now;
868 Result.Flag:=Flag;
869 end;
870
871 procedure TIHIgnoreIDEQuestionList.Delete(const Identifier: string);
872 var
873 Node: TAvlTreeNode;
874 begin
875 Node:=FindNode(Identifier);
876 if Node<>nil then
877 FItems.FreeAndDelete(Node);
878 end;
879
TIHIgnoreIDEQuestionList.Findnull880 function TIHIgnoreIDEQuestionList.Find(const Identifier: string): TIgnoreIDEQuestionItem;
881 var
882 Node: TAvlTreeNode;
883 begin
884 Node:=FindNode(Identifier);
885 if Node<>nil then
886 Result:=TIgnoreIDEQuestionItem(Node.Data)
887 else
888 Result:=nil;
889 end;
890
891 procedure TIHIgnoreIDEQuestionList.LoadFromXMLConfig(XMLConfig: TXMLConfig;
892 const Path: string);
893 var
894 Cnt: longint;
895 i: Integer;
896 SubPath: String;
897 Identifier: String;
898 ADate: TDateTime;
899 ADuration: TIgnoreQuestionDuration;
900 Item: TIgnoreIDEQuestionItem;
901 CurNow: TDateTime;
902 begin
903 Clear;
904 CurNow:=Now;
905 Cnt:=XMLConfig.GetValue(Path+'Count',0);
906 for i:=1 to Cnt do begin
907 SubPath:=Path+'Item'+IntToStr(i)+'/';
908 Identifier:=XMLConfig.GetValue(SubPath+'Name','');
909 if Identifier='' then continue;
910 if not CfgStrToDate(XMLConfig.GetValue(SubPath+'Date',''),ADate) then continue;
911 ADuration:=NameToIHIgnoreItemDuration(XMLConfig.GetValue(SubPath+'Duration',
912 IHIgnoreItemDurationNames[iiid24H]));
913 //debugln(['TIHIgnoreIDEQuestionList.LoadFromXMLConfig Identifier="',Identifier,'" Date=',DateTimeToStr(ADate),' Diff=',DateTimeToStr(CurNow-ADate),' Duration=',IHIgnoreItemDurationNames[ADuration]]);
914 case ADuration of
915 iiidIDERestart: continue;
916 iiid24H: if Abs(CurNow-ADate)>1 then continue;
917 iiidForever: ;
918 end;
919 Item:=Add(Identifier,ADuration);
920 Item.Date:=ADate;
921 Item.Flag:=XMLConfig.GetValue(SubPath+'Flag','');
922 end;
923 end;
924
925 procedure TIHIgnoreIDEQuestionList.SaveToXMLConfig(XMLConfig: TXMLConfig;
926 const Path: string);
927 var
928 i: Integer;
929 Node: TAvlTreeNode;
930 Item: TIgnoreIDEQuestionItem;
931 SubPath: String;
932 begin
933 i:=0;
934 Node:=FItems.FindLowest;
935 while Node<>nil do begin
936 Item:=TIgnoreIDEQuestionItem(Node.Data);
937 if (Item.Duration<>iiidIDERestart) and (Item.Identifier<>'') then begin
938 inc(i);
939 SubPath:=Path+'Item'+IntToStr(i)+'/';
940 XMLConfig.SetDeleteValue(SubPath+'Name',Item.Identifier,'');
941 XMLConfig.SetDeleteValue(SubPath+'Date',DateToCfgStr(Item.Date),'');
942 XMLConfig.SetDeleteValue(SubPath+'Duration',
943 IHIgnoreItemDurationNames[Item.Duration],
944 IHIgnoreItemDurationNames[iiid24H]);
945 XMLConfig.SetDeleteValue(SubPath+'Flag',Item.Flag,'');
946 end;
947 Node:=FItems.FindSuccessor(Node);
948 end;
949 XMLConfig.SetDeleteValue(Path+'Count',i,0);
950 end;
951
952 end.
953
954