PageRenderTime 24ms CodeModel.GetById 7ms app.highlight 10ms RepoModel.GetById 0ms app.codeStats 1ms

/ide/codeexplopts.pas

http://github.com/graemeg/lazarus
Pascal | 920 lines | 797 code | 72 blank | 51 comment | 72 complexity | e73a2b62566992b06f92ecf1f2d06032 MD5 | raw file
  1{
  2/***************************************************************************
  3                              CodeExplOpts.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.        *
 24 *                                                                         *
 25 ***************************************************************************
 26
 27  Abstract:
 28    Dialog for the options of the code explorer.
 29}
 30unit CodeExplOpts;
 31
 32{$mode objfpc}{$H+}
 33
 34interface
 35
 36uses
 37  // RTL + FCL + LCL
 38  Classes, SysUtils,
 39  LCLProc, Forms, Controls, Graphics, Dialogs, Buttons,
 40  // CodeTools
 41  BasicCodeTools, FileProcs,
 42  // LazUtils
 43  AvgLvlTree, Laz2_XMLCfg, LazFileUtils, LazFileCache,
 44  // IDEIntf
 45  IDEOptionsIntf,
 46  // IDE
 47  LazConf, IDEProcs, LazarusIDEStrConsts;
 48
 49type
 50  { TCodeExplorerOptions }
 51  
 52  TCodeExplorerPage = (
 53    cepNone,
 54    cepCode,
 55    cepDirectives
 56    );
 57
 58  TCodeExplorerRefresh = (
 59    cerManual,  // only via refresh button
 60    cerSwitchEditorPage,// everytime the source editor switches to another page
 61    cerOnIdle // on idle
 62    );
 63    
 64  TCodeExplorerMode = (
 65    cemCategory, // Category - Delphi like
 66    cemSource    // Follows Source Code
 67  );
 68  
 69  TCodeExplorerCategory = (
 70    cecNone,
 71    cecUses,
 72    cecTypes,
 73    cecVariables,
 74    cecConstants,
 75    cecProperties,
 76    cecProcedures,
 77    cecCodeObserver,
 78    cecSurrounding
 79    );
 80  TCodeExplorerCategories = set of TCodeExplorerCategory;
 81
 82  TCEObserverCategory = (
 83    cefcLongProcs,    // procedures with many lines of code
 84    cefcLongParamLists, // procedures with many parameters
 85    cefcEmptyProcs,  // procs without code (can contain comments)
 86    cefcNestedProcs, // procs with a lot of nested sub procs
 87    cefcUnnamedConsts, // numbers, strings in statements
 88    cefcEmptyBlocks,   // empty begin..end block (not even a comment)
 89    cefcWrongIndentation, // possible missing lines or begin blocks
 90    cefcPublishedPropWithoutDefault, // published properties without default specifier
 91    cefcUnsortedClassVisibility, // public,private,protected,published keywords are not sorted
 92    cefcEmptyClassSections, // empty public,private,protected,published section
 93    cefcUnsortedClassMembers, // member of a public,private,protected,published section is not sorted alphabetically
 94    cefcToDos  // todo comment
 95    );
 96  TCEObserverCategories = set of TCEObserverCategory;
 97
 98  TCEObserverCategoryGroup = (ocgComplexity, ocgEmpty, ocgStyle, ocgOther);
 99
100const
101  FirstCodeExplorerCategory = cecUses;
102  DefaultCodeExplorerCategories = [cecUses,
103               cecTypes,cecVariables,cecConstants,cecProcedures];
104  cefcAll = [low(TCEObserverCategory)..high(TCEObserverCategory)];
105  DefaultCodeExplorerPage = cepCode;
106  DefaultCodeObserverCategories = [
107    cefcLongProcs,
108    cefcEmptyProcs,
109    cefcUnnamedConsts,
110    cefcEmptyBlocks,
111    cefcWrongIndentation,
112    cefcPublishedPropWithoutDefault,
113    cefcToDos
114    ];
115  DefaultCOLongProcLineCount = 50;
116  DefaultCOLongParamListCount = 6;
117  DefaultCONestedProcCount = 3;
118  DefaultCOureCharConst = false;
119  DefaultCOIgnoreConstants: array[1..2] of ansistring // Note: keep this asciiz
120    = (
121    '0',
122    '1'
123    );
124  DefaultCOIgnoreConstInFuncs: array[1..15] of ansistring // Note: keep this asciiz
125    = (
126    'Assert',
127    'Debug',
128    'DebugLn',
129    'DbgOut',
130    'write',
131    'writeln',
132    'Format',
133    'FormatBuf',
134    'StrFmt',
135    'StrLFmt',
136    'FmtStr',
137    'FloatToStrF',
138    'FloatToStr',
139    'CurrToStrF',
140    'FormatDateTime'
141    );
142
143type
144
145  TCodeExplorerOptions = class(TAbstractIDEEnvironmentOptions)
146  private
147    FCategories: TCodeExplorerCategories;
148    FChangeStep: integer;
149    FObserveCharConst: boolean;
150    FCOIgnoreConstInFuncs: TStringToStringTree;
151    FLongParamListCount: integer;
152    FLongProcLineCount: integer;
153    FNestedProcCount: integer;
154    FObserverCategories: TCEObserverCategories;
155    FFollowCursor: boolean;
156    FMode : TCodeExplorerMode;
157    FObserverIgnoreConstants: TAvgLvlTree;// tree of AnsiString
158    FOptionsFilename: string;
159    FPage: TCodeExplorerPage;
160    FRefresh: TCodeExplorerRefresh;
161    FSavedChangeStep: integer;
162    function GetModified: boolean;
163    procedure SetCategories(const AValue: TCodeExplorerCategories);
164    procedure SetFollowCursor(const AValue: boolean);
165    procedure SetLongParamListCount(const AValue: integer);
166    procedure SetLongProcLineCount(const AValue: integer);
167    procedure SetMode(const AValue: TCodeExplorerMode);
168    procedure SetModified(AValue: boolean);
169    procedure SetNestedProcCount(const AValue: integer);
170    procedure SetObserveCharConst(const AValue: boolean);
171    procedure SetObserverCategories(const AValue: TCEObserverCategories);
172    procedure SetPage(AValue: TCodeExplorerPage);
173    procedure SetRefresh(const AValue: TCodeExplorerRefresh);
174  public
175    class function GetGroupCaption:string; override;
176    class function GetInstance: TAbstractIDEOptions; override;
177    procedure DoAfterWrite(Restore: boolean); override;
178  public
179    constructor Create;
180    destructor Destroy; override;
181    procedure Clear;
182    procedure Assign(Source: TPersistent); override;
183    procedure Load;
184    procedure Save;
185    procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
186    procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
187    procedure IncreaseChangeStep;
188    property Modified: boolean read GetModified write SetModified;
189  public
190    // observer: ignore constants
191    function CreateListOfCOIgnoreConstants: TStrings;
192    procedure SetListOf_COIgnoreConstants(List: TStrings; Add: boolean);
193    function COIgnoreConstant(p: PChar): boolean;// test if atom is in COIgnoreConstants
194    function COIgnoreConstants_AreDefault(Exactly: boolean): boolean; // true if COIgnoreConstants contain/are default values
195    function COIgnoreConstant_IsDefault(const Atom: string): boolean; // true if Atom is in default values
196    procedure Add_COIgnoreConstant(const Atom: string);
197    procedure Clear_COIgnoreConstants;
198    procedure LoadDefaults_COIgnoreConstants;
199  public
200    // observer: ignore constants in functions
201    function CreateListOfCOIgnoreConstInFuncs: TStrings;
202    procedure SetListOf_COIgnoreConstInFuncs(List: TStrings; Add: boolean);
203    function COIgnoreConstInFunc(const Func: string): boolean;// test if function is in COIgnoreConstInFuncs
204    function COIgnoreConstInFuncs_AreDefault(Exactly: boolean): boolean; // true if COIgnoreConstInFuncs contain/are default values
205    function COIgnoreConstInFuncs_IsDefault(const Func: string): boolean; // true if Atom is in default values
206    procedure Add_COIgnoreConstInFuncs(const Func: string);
207    procedure Clear_COIgnoreConstInFuncs;
208    procedure LoadDefaults_COIgnoreConstInFuncs;
209  public
210    property Refresh: TCodeExplorerRefresh read FRefresh write SetRefresh default cerSwitchEditorPage;
211    property Mode: TCodeExplorerMode read FMode write SetMode default cemCategory;
212    property OptionsFilename: string read FOptionsFilename write FOptionsFilename;
213    property FollowCursor: boolean read FFollowCursor write SetFollowCursor default true;
214    property Categories: TCodeExplorerCategories read FCategories write SetCategories default DefaultCodeExplorerCategories;
215    property Page: TCodeExplorerPage read FPage write SetPage default DefaultCodeExplorerPage;
216    property ChangeStep: integer read FChangeStep write FChangeStep;
217  public
218    // Observer
219    property ObserveCharConst: boolean read FObserveCharConst write SetObserveCharConst default DefaultCOureCharConst;
220    property ObserverCategories: TCEObserverCategories read FObserverCategories write SetObserverCategories default DefaultCodeObserverCategories;
221    property ObserverIgnoreConstants: TAvgLvlTree read FObserverIgnoreConstants;
222    property COIgnoreConstInFuncs: TStringToStringTree read FCOIgnoreConstInFuncs;
223    property LongParamListCount: integer read FLongParamListCount write SetLongParamListCount default DefaultCOLongParamListCount;
224    property LongProcLineCount: integer read FLongProcLineCount write SetLongProcLineCount default DefaultCOLongProcLineCount;
225    property NestedProcCount: integer read FNestedProcCount write SetNestedProcCount default DefaultCONestedProcCount;
226  end;
227
228const
229  CodeExplorerVersion = 1;
230
231  cerDefault = cerSwitchEditorPage;
232
233  CodeExplorerPageNames: array[TCodeExplorerPage] of string = (
234    '?',
235    'Code',
236    'Directives'
237    );
238  CodeExplorerRefreshNames: array[TCodeExplorerRefresh] of string = (
239    'Manual',
240    'SwitchEditorPage',
241    'OnIdle'
242    );
243  CodeExplorerModeNames: array[TCodeExplorerMode] of string = (
244    'Category',
245    'Source'
246    );
247  CodeExplorerCategoryNames: array[TCodeExplorerCategory] of string = (
248    '?',
249    'Uses',
250    'Types',
251    'Variables',
252    'Constants',
253    'Properties',
254    'Procedures',
255    'CodeObserver',
256    'Surrounding'
257    );
258  CodeObserverCategoryNames: array[TCEObserverCategory] of string = (
259    'LongProcs',
260    'LongParamLists',
261    'EmptyProcs',
262    'NestedProcs',
263    'UnnamedConsts',
264    'EmptyBlocks',
265    'WrongIndentation',
266    'PublishedPropWithoutDefault',
267    'UnsortedClassVisibility',
268    'EmptyClassSections',
269    'UnsortedClassMembers',
270    'ToDos'
271    );
272
273var
274  CodeExplorerOptions: TCodeExplorerOptions = nil; // set by the IDE
275
276function CodeExplorerPageNameToEnum(const s: string): TCodeExplorerPage;
277function CodeExplorerRefreshNameToEnum(const s: string): TCodeExplorerRefresh;
278function CodeExplorerModeNameToEnum(const s: string): TCodeExplorerMode;
279function CodeExplorerCategoryNameToEnum(const s: string): TCodeExplorerCategory;
280function CodeExplorerLocalizedString(const c: TCodeExplorerCategory): string;
281function CodeObserverCatNameToEnum(const s: string): TCEObserverCategory;
282function CodeExplorerLocalizedString(const c: TCEObserverCategory): string;
283function dbgs(c: TCodeExplorerCategory): string; overload;
284
285implementation
286
287function CodeExplorerPageNameToEnum(const s: string): TCodeExplorerPage;
288begin
289  for Result:=Low(TCodeExplorerPage) to High(TCodeExplorerPage) do
290    if SysUtils.CompareText(CodeExplorerPageNames[Result],s)=0 then exit;
291  Result:=DefaultCodeExplorerPage;
292end;
293
294function CodeExplorerRefreshNameToEnum(const s: string): TCodeExplorerRefresh;
295begin
296  for Result:=Low(TCodeExplorerRefresh) to High(TCodeExplorerRefresh) do
297    if SysUtils.CompareText(CodeExplorerRefreshNames[Result],s)=0 then exit;
298  Result:=cerDefault;
299end;
300
301function CodeExplorerModeNameToEnum(const s: string): TCodeExplorerMode;
302begin
303  for Result:=Low(TCodeExplorerMode) to High(TCodeExplorerMode) do
304    if SysUtils.CompareText(CodeExplorerModeNames[Result],s)=0 then exit;
305  Result:=cemCategory;
306end;
307
308function CodeExplorerCategoryNameToEnum(const s: string): TCodeExplorerCategory;
309begin
310  for Result:=FirstCodeExplorerCategory to High(TCodeExplorerCategory) do
311    if SysUtils.CompareText(CodeExplorerCategoryNames[Result],s)=0 then exit;
312  Result:=cecTypes;
313end;
314
315function CodeExplorerLocalizedString(const c: TCodeExplorerCategory): string;
316begin
317  case c of
318  cecUses: Result:=lisCEUses;
319  cecTypes: Result:=lisCETypes;
320  cecVariables: Result:=lisCEVariables;
321  cecConstants: Result:=lisCEConstants;
322  cecProcedures: Result:=lisCEProcedures;
323  cecProperties: Result:=lisCEProperties;
324  cecCodeObserver: Result:=lisCodeObserver;
325  cecSurrounding: Result:=lisCESurrounding;
326  else Result:='?';
327  end;
328end;
329
330function CodeObserverCatNameToEnum(const s: string): TCEObserverCategory;
331begin
332  for Result:=low(TCEObserverCategory) to High(TCEObserverCategory) do
333    if SysUtils.CompareText(CodeObserverCategoryNames[Result],s)=0 then exit;
334  Result:=cefcLongProcs;
335end;
336
337function CodeExplorerLocalizedString(const c: TCEObserverCategory): string;
338begin
339  case c of
340  cefcLongProcs: Result:=lisCELongProcedures;
341  cefcLongParamLists: Result:=lisCEManyParameters;
342  cefcEmptyProcs: Result:=lisCEEmptyProcedures;
343  cefcNestedProcs: Result:=lisCEManyNestedProcedures;
344  cefcUnnamedConsts: Result:=lisCEUnnamedConstants;
345  cefcEmptyBlocks: Result:=lisCEEmptyBlocks;
346  cefcWrongIndentation: Result:=lisCEWrongIndentation;
347  cefcPublishedPropWithoutDefault: Result:=lisCEPublishedPropertyWithoutDefault;
348  cefcUnsortedClassVisibility: Result:=lisCEUnsortedVisibility;
349  cefcEmptyClassSections: Result:=lisCEEmptyClassSections;
350  cefcUnsortedClassMembers: Result:=lisCEUnsortedMembers;
351  cefcToDos: Result:=lisCEToDos;
352  else Result:='?';
353  end;
354end;
355
356function dbgs(c: TCodeExplorerCategory): string;
357begin
358  Result:=CodeExplorerCategoryNames[c];
359end;
360
361{ TCodeExplorerOptions }
362
363procedure TCodeExplorerOptions.SetRefresh(const AValue: TCodeExplorerRefresh);
364begin
365  if FRefresh=AValue then exit;
366  FRefresh:=AValue;
367  IncreaseChangeStep;
368end;
369
370procedure TCodeExplorerOptions.SetMode(const AValue: TCodeExplorerMode);
371begin
372  if FMode=AValue then exit;
373  FMode:=AValue;
374  IncreaseChangeStep;
375end;
376
377procedure TCodeExplorerOptions.SetModified(AValue: boolean);
378begin
379  if AValue then
380    IncreaseChangeStep
381  else
382    FSavedChangeStep:=FChangeStep;
383end;
384
385procedure TCodeExplorerOptions.SetNestedProcCount(const AValue: integer);
386begin
387  if FNestedProcCount=AValue then exit;
388  FNestedProcCount:=AValue;
389  IncreaseChangeStep;
390end;
391
392procedure TCodeExplorerOptions.SetObserveCharConst(const AValue: boolean);
393begin
394  if FObserveCharConst=AValue then exit;
395  FObserveCharConst:=AValue;
396  IncreaseChangeStep;
397end;
398
399procedure TCodeExplorerOptions.SetObserverCategories(
400  const AValue: TCEObserverCategories);
401begin
402  if FObserverCategories=AValue then exit;
403  FObserverCategories:=AValue;
404  IncreaseChangeStep;
405end;
406
407procedure TCodeExplorerOptions.SetPage(AValue: TCodeExplorerPage);
408begin
409  if FPage=AValue then Exit;
410  FPage:=AValue;
411  IncreaseChangeStep;
412end;
413
414procedure TCodeExplorerOptions.SetFollowCursor(const AValue: boolean);
415begin
416  if FFollowCursor=AValue then exit;
417  FFollowCursor:=AValue;
418  IncreaseChangeStep;
419end;
420
421procedure TCodeExplorerOptions.SetLongParamListCount(const AValue: integer);
422begin
423  if FLongParamListCount=AValue then exit;
424  FLongParamListCount:=AValue;
425  IncreaseChangeStep;
426end;
427
428procedure TCodeExplorerOptions.SetLongProcLineCount(const AValue: integer);
429begin
430  if FLongProcLineCount=AValue then exit;
431  FLongProcLineCount:=AValue;
432  IncreaseChangeStep;
433end;
434
435procedure TCodeExplorerOptions.SetCategories(
436  const AValue: TCodeExplorerCategories);
437begin
438  if FCategories=AValue then exit;
439  FCategories:=AValue;
440  IncreaseChangeStep;
441end;
442
443function TCodeExplorerOptions.GetModified: boolean;
444begin
445  Result:=FSavedChangeStep<>FChangeStep;
446end;
447
448constructor TCodeExplorerOptions.Create;
449begin
450  FOptionsFilename:=AppendPathDelim(GetPrimaryConfigPath)+'codeexploreroptions.xml';
451  FObserverIgnoreConstants:=TAvgLvlTree.Create(TListSortCompare(@CompareAtom));
452  FCOIgnoreConstInFuncs:=TStringToStringTree.Create(false);
453  Clear;
454  LoadDefaults_COIgnoreConstants;
455  LoadDefaults_COIgnoreConstInFuncs;
456end;
457
458destructor TCodeExplorerOptions.Destroy;
459begin
460  Clear_COIgnoreConstants;
461  FreeAndNil(FObserverIgnoreConstants);
462  FreeAndNil(FCOIgnoreConstInFuncs);
463  inherited Destroy;
464end;
465
466class function TCodeExplorerOptions.GetGroupCaption: string;
467begin
468  Result := dlgGroupCodeExplorer;
469end;
470
471class function TCodeExplorerOptions.GetInstance: TAbstractIDEOptions;
472begin
473  Result := CodeExplorerOptions;
474end;
475
476procedure TCodeExplorerOptions.DoAfterWrite(Restore: boolean);
477begin
478  if not Restore then
479    Save;
480end;
481
482procedure TCodeExplorerOptions.Clear;
483begin
484  IncreaseChangeStep;
485  FMode:=cemCategory;
486  FRefresh:=cerDefault;
487  FFollowCursor:=true;
488  FPage:=DefaultCodeExplorerPage;
489  FCategories:=DefaultCodeExplorerCategories;
490  FObserverCategories:=DefaultCodeObserverCategories;
491  FLongProcLineCount:=DefaultCOLongProcLineCount;
492  FLongParamListCount:=DefaultCOLongParamListCount;
493  FNestedProcCount:=DefaultCONestedProcCount;
494  FObserveCharConst:=DefaultCOureCharConst;
495  Clear_COIgnoreConstants;
496  Clear_COIgnoreConstInFuncs;
497end;
498
499procedure TCodeExplorerOptions.Assign(Source: TPersistent);
500var
501  Src: TCodeExplorerOptions;
502  List: TStrings;
503begin
504  if Source is TCodeExplorerOptions then begin
505    IncreaseChangeStep;
506    Src:=TCodeExplorerOptions(Source);
507    FRefresh:=Src.Refresh;
508    FMode:=Src.Mode;
509    FFollowCursor:=Src.FollowCursor;
510    FPage:=Src.Page;
511    FCategories:=Src.Categories;
512    FObserverCategories:=Src.ObserverCategories;
513    FLongProcLineCount:=Src.LongProcLineCount;
514    FLongParamListCount:=Src.LongParamListCount;
515    FNestedProcCount:=Src.NestedProcCount;
516    FObserveCharConst:=Src.ObserveCharConst;
517    List:=Src.CreateListOfCOIgnoreConstants;
518    try
519      SetListOf_COIgnoreConstants(List,false);
520    finally
521      List.Free;
522    end;
523    List:=Src.CreateListOfCOIgnoreConstInFuncs;
524    try
525      SetListOf_COIgnoreConstInFuncs(List,false);
526    finally
527      List.Free;
528    end;
529  end else
530    inherited Assign(Source);
531end;
532
533procedure TCodeExplorerOptions.Load;
534var
535  XMLConfig: TXMLConfig;
536  //FileVersion: integer;
537begin
538  if not FileExistsUTF8(FOptionsFilename) then
539  begin
540    Clear;
541    LoadDefaults_COIgnoreConstants;
542    LoadDefaults_COIgnoreConstInFuncs;
543    Exit;
544  end;
545  try
546    XMLConfig:=TXMLConfig.Create(FOptionsFilename);
547    //FileVersion:=XMLConfig.GetValue('CodeExplorer/Version/Value',0);
548    LoadFromXMLConfig(XMLConfig,'CodeExplorer/');
549    XMLConfig.Free;
550  except
551    on E: Exception do begin
552      DebugLn('[TCodeExplorerOptions.Load]  error reading "',FOptionsFilename,'" ',E.Message);
553    end;
554  end;
555end;
556
557procedure TCodeExplorerOptions.Save;
558var
559  XMLConfig: TXMLConfig;
560begin
561  if FileExistsCached(FOptionsFilename) and not Modified then exit;
562  try
563    InvalidateFileStateCache;
564    XMLConfig:=TXMLConfig.CreateClean(FOptionsFilename);
565    XMLConfig.SetDeleteValue('CodeExplorer/Version/Value',
566      CodeExplorerVersion,0);
567    SaveToXMLConfig(XMLConfig,'CodeExplorer/');
568    XMLConfig.Flush;
569    XMLConfig.Free;
570    Modified:=false;
571  except
572    on E: Exception do begin
573      DebugLn('[TCodeExplorerOptions.Save]  error writing "',FOptionsFilename,'" ',E.Message);
574    end;
575  end;
576end;
577
578procedure TCodeExplorerOptions.LoadFromXMLConfig(XMLConfig: TXMLConfig;
579  const Path: string);
580var
581  c: TCodeExplorerCategory;
582  f: TCEObserverCategory;
583  CurPath: String;
584  List: TStringList;
585begin
586  IncreaseChangeStep;
587  Clear;
588  FRefresh:=CodeExplorerRefreshNameToEnum(
589                                   XMLConfig.GetValue(Path+'Refresh/Value',''));
590  FMode:=CodeExplorerModeNameToEnum(
591                                   XMLConfig.GetValue(Path+'Mode/Value',''));
592  FFollowCursor:=XMLConfig.GetValue(Path+'FollowCursor',true);
593  FPage:=CodeExplorerPageNameToEnum(XMLConfig.GetValue(Path+'Page/Value',''));
594
595  FCategories:=[];
596  for c:=FirstCodeExplorerCategory to high(TCodeExplorerCategory) do
597    if XMLConfig.GetValue(Path+'Categories/'+CodeExplorerCategoryNames[c],
598      c in DefaultCodeExplorerCategories) then
599        Include(FCategories,c);
600  FObserverCategories:=[];
601  for f:=low(TCEObserverCategory) to high(TCEObserverCategory) do
602  begin
603    CurPath:=Path+'CodeObserver/'+CodeObserverCategoryNames[f]+'/';
604    if XMLConfig.GetValue(CurPath+'Show',f in DefaultCodeObserverCategories)
605    then
606      Include(FObserverCategories,f);
607    case f of
608    cefcLongProcs:
609      FLongProcLineCount:=XMLConfig.GetValue(CurPath+'LineCount/Value',
610                                                 DefaultCOLongProcLineCount);
611    cefcLongParamLists:
612      FLongParamListCount:=XMLConfig.GetValue(CurPath+'Count/Value',
613                                                 DefaultCOLongParamListCount);
614    cefcNestedProcs:
615      FNestedProcCount:=XMLConfig.GetValue(CurPath+'Count/Value',
616                                                 DefaultCONestedProcCount);
617    cefcUnnamedConsts:
618      begin
619        FObserveCharConst:=XMLConfig.GetValue(CurPath+'CharConsts/Value',
620                                                 DefaultCOureCharConst);
621        // load standard ObserverIgnoreConstants
622        if XMLConfig.GetValue(CurPath+'Ignore/ContainsDefaults',true) then
623          LoadDefaults_COIgnoreConstants;
624        // load custom ObserverIgnoreConstants
625        List:=TStringList.Create;
626        try
627          LoadStringList(XMLConfig,List,CurPath+'Ignore/');
628          SetListOf_COIgnoreConstants(List,true);
629        finally
630          List.Free;
631        end;
632        // load standard COIgnoreConstInFuncs
633        if XMLConfig.GetValue(CurPath+'IgnoreInFuncs/ContainsDefaults',true) then
634          LoadDefaults_COIgnoreConstInFuncs;
635        // load custom COIgnoreConstInFuncs
636        List:=TStringList.Create;
637        try
638          LoadStringList(XMLConfig,List,CurPath+'IgnoreFuncs/');
639          SetListOf_COIgnoreConstInFuncs(List,true);
640        finally
641          List.Free;
642        end;
643      end;
644    end;
645  end;
646end;
647
648procedure TCodeExplorerOptions.SaveToXMLConfig(XMLConfig: TXMLConfig;
649  const Path: string);
650var
651  c: TCodeExplorerCategory;
652  f: TCEObserverCategory;
653  CurPath: String;
654  List: TStrings;
655  ContainsDefaults: Boolean;
656  i: Integer;
657begin
658  XMLConfig.SetDeleteValue(Path+'Refresh/Value',
659                           CodeExplorerRefreshNames[FRefresh],
660                           CodeExplorerRefreshNames[cerDefault]);
661  XMLConfig.SetDeleteValue(Path+'Mode/Value',
662                           CodeExplorerModeNames[FMode],
663                           CodeExplorerModeNames[cemCategory]);
664  XMLConfig.SetDeleteValue(Path+'FollowCursor',FFollowCursor,true);
665  XMLConfig.SetDeleteValue(Path+'Page/Value',CodeExplorerPageNames[FPage],
666                           CodeExplorerPageNames[DefaultCodeExplorerPage]);
667
668  for c:=FirstCodeExplorerCategory to high(TCodeExplorerCategory) do
669    XMLConfig.SetDeleteValue(Path+'Categories/'+CodeExplorerCategoryNames[c],
670      c in FCategories,c in DefaultCodeExplorerCategories);
671  for f:=low(TCEObserverCategory) to high(TCEObserverCategory) do
672  begin
673    CurPath:=Path+'CodeObserver/'+CodeObserverCategoryNames[f]+'/';
674    XMLConfig.SetDeleteValue(CurPath+'Show',
675      f in FObserverCategories,f in DefaultCodeObserverCategories);
676    case f of
677    cefcLongProcs:
678      XMLConfig.SetDeleteValue(CurPath+'LineCount/Value',
679                           FLongProcLineCount,DefaultCOLongProcLineCount);
680    cefcLongParamLists:
681      XMLConfig.SetDeleteValue(CurPath+'Count/Value',
682                           FLongParamListCount,DefaultCOLongParamListCount);
683    cefcNestedProcs:
684      XMLConfig.SetDeleteValue(CurPath+'Count/Value',
685                           FNestedProcCount,DefaultCONestedProcCount);
686    cefcUnnamedConsts:
687      begin
688        XMLConfig.SetDeleteValue(CurPath+'CharConsts/Value',
689                           FObserveCharConst,DefaultCOureCharConst);
690        // save standard ObserverIgnoreConstants
691        ContainsDefaults:=COIgnoreConstants_AreDefault(false);
692        XMLConfig.SetDeleteValue(CurPath+'Ignore/ContainsDefaults',
693           ContainsDefaults,true);
694        // save ObserverIgnoreConstants
695        List:=CreateListOfCOIgnoreConstants;
696        try
697          for i:=List.Count-1 downto 0 do
698            if COIgnoreConstant_IsDefault(List[i]) then
699              List.Delete(i);
700          SaveStringList(XMLConfig,List,CurPath+'Ignore/');
701        finally
702          List.Free;
703        end;
704        // save standard COIgnoreConstInFuncs
705        ContainsDefaults:=COIgnoreConstInFuncs_AreDefault(false);
706        XMLConfig.SetDeleteValue(CurPath+'IgnoreInFuncs/ContainsDefaults',
707           ContainsDefaults,true);
708        // save COIgnoreConstInFuncs
709        List:=CreateListOfCOIgnoreConstInFuncs;
710        try
711          for i:=List.Count-1 downto 0 do
712            if COIgnoreConstInFuncs_IsDefault(List[i]) then
713              List.Delete(i);
714          SaveStringList(XMLConfig,List,CurPath+'IgnoreInFuncs/');
715        finally
716          List.Free;
717        end;
718      end;
719    end;
720  end;
721end;
722
723procedure TCodeExplorerOptions.IncreaseChangeStep;
724begin
725  if FChangeStep=high(integer) then
726    FChangeStep:=low(integer)
727  else
728    inc(FChangeStep);
729end;
730
731function TCodeExplorerOptions.CreateListOfCOIgnoreConstants: TStrings;
732var
733  AVLNode: TAvgLvlTreeNode;
734  s: String;
735begin
736  Result:=TStringList.Create;
737  AVLNode:=ObserverIgnoreConstants.FindLowest;
738  while AVLNode<>nil do begin
739    s:=GetAtomString(PChar(AVLNode.Data),false);
740    if s<>'' then
741      Result.Add(s);
742    AVLNode:=ObserverIgnoreConstants.FindSuccessor(AVLNode);
743  end;
744end;
745
746procedure TCodeExplorerOptions.Clear_COIgnoreConstants;
747var
748  AVLNode: TAvgLvlTreeNode;
749  s: String;
750begin
751  if FObserverIgnoreConstants.Count=0 then exit;
752  IncreaseChangeStep;
753  s:='';
754  AVLNode:=FObserverIgnoreConstants.FindLowest;
755  while AVLNode<>nil do begin
756    // decrease reference counter
757    Pointer(s):=AVLNode.Data;
758    s:='';
759    AVLNode:=FObserverIgnoreConstants.FindSuccessor(AVLNode);
760  end;
761  if s='' then ; // omit fpc note
762  FObserverIgnoreConstants.Clear;
763end;
764
765procedure TCodeExplorerOptions.SetListOf_COIgnoreConstants(List: TStrings;
766  Add: boolean);
767var
768  i: Integer;
769begin
770  IncreaseChangeStep;
771  if not Add then
772    Clear_COIgnoreConstants;
773  for i:=0 to List.Count-1 do
774    Add_COIgnoreConstant(List[i]);
775end;
776
777procedure TCodeExplorerOptions.LoadDefaults_COIgnoreConstants;
778var
779  i: Integer;
780begin
781  if COIgnoreConstants_AreDefault(true) then exit;
782  IncreaseChangeStep;
783  Clear_COIgnoreConstants;
784  for i:=low(DefaultCOIgnoreConstants) to high(DefaultCOIgnoreConstants) do
785    Add_COIgnoreConstant(DefaultCOIgnoreConstants[i]);
786end;
787
788function TCodeExplorerOptions.CreateListOfCOIgnoreConstInFuncs: TStrings;
789var
790  AVLNode: TAvgLvlTreeNode;
791  s: String;
792begin
793  Result:=TStringList.Create;
794  AVLNode:=COIgnoreConstInFuncs.Tree.FindLowest;
795  while AVLNode<>nil do begin
796    s:=PStringToStringItem(AVLNode.Data)^.Name;
797    if s<>'' then
798      Result.Add(s);
799    AVLNode:=COIgnoreConstInFuncs.Tree.FindSuccessor(AVLNode);
800  end;
801end;
802
803procedure TCodeExplorerOptions.SetListOf_COIgnoreConstInFuncs(List: TStrings;
804  Add: boolean);
805var
806  i: Integer;
807begin
808  IncreaseChangeStep;
809  if not Add then
810    Clear_COIgnoreConstInFuncs;
811  for i:=0 to List.Count-1 do
812    Add_COIgnoreConstInFuncs(List[i]);
813end;
814
815function TCodeExplorerOptions.COIgnoreConstInFunc(const Func: string): boolean;
816begin
817  Result:=FCOIgnoreConstInFuncs.Contains(Func);
818end;
819
820function TCodeExplorerOptions.COIgnoreConstInFuncs_AreDefault(Exactly: boolean
821  ): boolean;
822const
823  DefCount = high(DefaultCOIgnoreConstInFuncs)-Low(DefaultCOIgnoreConstInFuncs)+1;
824var
825  i: Integer;
826begin
827  if Exactly and (FCOIgnoreConstInFuncs.Count=DefCount) then
828    exit(false);
829  if FCOIgnoreConstInFuncs.Count<DefCount then exit(false);
830  for i:=low(DefaultCOIgnoreConstInFuncs) to high(DefaultCOIgnoreConstInFuncs) do
831    if not COIgnoreConstInFunc(DefaultCOIgnoreConstInFuncs[i]) then
832      exit(false);
833  Result:=true;
834end;
835
836function TCodeExplorerOptions.COIgnoreConstInFuncs_IsDefault(const Func: string
837  ): boolean;
838var
839  i: Integer;
840begin
841  for i:=low(DefaultCOIgnoreConstants) to high(DefaultCOIgnoreConstants) do
842    if SysUtils.CompareText(Func,DefaultCOIgnoreConstants[i])=0 then
843      exit(true);
844  Result:=false;
845end;
846
847procedure TCodeExplorerOptions.Add_COIgnoreConstInFuncs(const Func: string);
848begin
849  if Func='' then exit;
850  if COIgnoreConstInFunc(Func) then exit;
851  IncreaseChangeStep;
852  FCOIgnoreConstInFuncs.Values[Func]:='';
853end;
854
855procedure TCodeExplorerOptions.Clear_COIgnoreConstInFuncs;
856begin
857  if FCOIgnoreConstInFuncs.Count=0 then exit;
858  IncreaseChangeStep;
859  FCOIgnoreConstInFuncs.Clear;
860end;
861
862procedure TCodeExplorerOptions.LoadDefaults_COIgnoreConstInFuncs;
863var
864  i: Integer;
865begin
866  if COIgnoreConstInFuncs_AreDefault(true) then exit;
867  IncreaseChangeStep;
868  Clear_COIgnoreConstInFuncs;
869  for i:=low(DefaultCOIgnoreConstInFuncs) to high(DefaultCOIgnoreConstInFuncs) do
870    Add_COIgnoreConstInFuncs(DefaultCOIgnoreConstInFuncs[i]);
871end;
872
873function TCodeExplorerOptions.COIgnoreConstant(p: PChar): boolean;
874begin
875  Result:=FObserverIgnoreConstants.Find(p)<>nil;
876end;
877
878procedure TCodeExplorerOptions.Add_COIgnoreConstant(const Atom: string);
879var
880  s: String;
881begin
882  if Atom='' then exit;
883  if COIgnoreConstant(PChar(Atom)) then exit;
884  IncreaseChangeStep;
885  s:=Atom;
886  FObserverIgnoreConstants.Add(Pointer(s));
887  Pointer(s):=nil;
888end;
889
890function TCodeExplorerOptions.COIgnoreConstants_AreDefault(Exactly: boolean
891  ): boolean;
892const
893  DefCount = high(DefaultCOIgnoreConstants)-Low(DefaultCOIgnoreConstants)+1;
894var
895  i: Integer;
896begin
897  if Exactly and (FObserverIgnoreConstants.Count=DefCount) then
898    exit(false);
899  if FObserverIgnoreConstants.Count<DefCount then exit(false);
900  for i:=low(DefaultCOIgnoreConstants) to high(DefaultCOIgnoreConstants) do
901    if not COIgnoreConstant(PChar(DefaultCOIgnoreConstants[i])) then
902      exit(false);
903  Result:=true;
904end;
905
906function TCodeExplorerOptions.COIgnoreConstant_IsDefault(const Atom: string
907  ): boolean;
908var
909  i: Integer;
910begin
911  for i:=low(DefaultCOIgnoreConstants) to high(DefaultCOIgnoreConstants) do
912    if CompareAtom(PChar(Atom),PChar(DefaultCOIgnoreConstants[i]),false)=0 then
913      exit(true);
914  Result:=false;
915end;
916
917initialization
918  RegisterIDEOptionsGroup(GroupCodeExplorer, TCodeExplorerOptions);
919end.
920