1 { Extern help options frame for Lazarus IDE.
2
3 Copyright (C) 2010 Mattias Gaertner mattias@freepascal.org
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version with the following modification:
9
10 As a special exception, the copyright holders of this library give you
11 permission to link this library with independent modules to produce an
12 executable, regardless of the license terms of these independent modules,and
13 to copy and distribute the resulting executable under terms of your choice,
14 provided that you also meet, for each linked independent module, the terms
15 and conditions of the license of that module. An independent module is a
16 module which is not derived from or based on this library. If you modify
17 this library, you may extend this exception to your version of the library,
18 but you are not obligated to do so. If you do not wish to do so, delete this
19 exception statement from your version.
20
21 This program is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
24 for more details.
25
26 You should have received a copy of the GNU Library General Public License
27 along with this library; if not, write to the Free Software Foundation,
28 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.
29 }
30
31 unit ExternHelpFrm;
32
33 {$mode objfpc}{$H+}
34
35 interface
36
37 uses
38 Classes, SysUtils,
39 // LCL
40 LResources, Forms, Controls, Graphics, Dialogs, ComCtrls, Buttons, StdCtrls,
41 ExtCtrls, ButtonPanel, HelpIntfs,
42 // LazUtils
43 FileUtil, LazFileUtils, LazStringUtils, LazConfigStorage, LazLoggerBase, LazUTF8,
44 // IdeIntf
45 LazHelpIntf, PackageIntf, MacroIntf, IDEOptionsIntf, IDEOptEditorIntf,
46 LazIDEIntf, BaseIDEIntf, IDEDialogs, IDEImagesIntf, SrcEditorIntf;
47
48 const
49 ExternHelpConfigVersion = 1;
50 var
51 ExternHelpOptionID: integer = 2000;
52 ExternHelpOptionGeneralID: integer = 1000;
53
54 resourcestring
55 ehrsGroupTitle = 'Extern help';
56 ehrsName = 'Name';
57 ehrsUnitFileOrUnitDirectory = 'Unit file or unit directory';
58 ehrsURL = 'URL';
59 ehrsHelp = 'Help';
60 ehrsAddNewItem = 'Add new item';
61 ehrsDeleteItem = 'Delete item';
62 ehrsBrowseForPath = 'Browse for path';
63 ehrsGeneral = 'General';
64 ehrsBrowse = 'Browse ...';
65 ehrsMacrofy = 'Use macros';
66 ehrsReplaceCommonDirectoriesWithMacros = 'Replace common directories with '
67 +'macros';
68 ehrsEditorFile = 'Editor file ...';
69 ehrsStoreThisURLIn = 'Store this URL in';
70 ehrsIncludeSubDirectories = 'Include sub directories';
71 ehrsSelectAFileFromTheSourceEditor = 'Select a file from the source editor';
72 ehrsChooseAPascalUnit = 'Choose a pascal unit';
73 ehrsSelectFile = 'Select file';
74 ehrsDirectoryNotFound = 'Directory not found: %s';
75 ehrsFileNotFound = 'File not found: %s';
76 ehrsWarning = 'Warning';
77 ehrsExternal = 'External';
78 ehrsMySettings = 'My settings (default)';
79
80 type
81
82 { TExternHelpFileSelector }
83
84 TExternHelpFileSelector = class(TForm)
85 published
86 FileListBox: TListBox;
87 ButtonPanel1: TButtonPanel;
88 procedure ButtonPanel1OKButtonClick(Sender: TObject);
89 public
90 constructor Create(TheOwner: TComponent); override;
91 end;
92
93 { TExternHelpItem }
94
95 TExternHelpItem = class
96 private
97 FChangeStep: integer;
98 fChilds: TFPList;
99 FFilename: string;
100 FName: string;
101 FStoreIn: string;
102 FURL: string;
103 FWithSubDirectories: boolean;
GetChildCountnull104 function GetChildCount: integer;
GetChildrennull105 function GetChildren(Index: integer): TExternHelpItem;
106 procedure SetFilename(const AValue: string);
107 procedure SetName(const AValue: string);
108 procedure SetStoreIn(const AValue: string);
109 procedure SetURL(const AValue: string);
110 procedure SetWithSubDirectories(const AValue: boolean);
111 public
112 Parent: TExternHelpItem;
113 constructor Create;
114 destructor Destroy; override;
115 procedure Clear;
116 procedure AddChild(Item: TExternHelpItem);
117 procedure MoveChild(FromPos, ToPos: integer);
118 procedure RemoveChild(Index: integer);
119 procedure DeleteChild(Index: integer);
120 procedure DeleteChild(Child: TExternHelpItem);
IndexOfnull121 function IndexOf(Child: TExternHelpItem): integer;
IsEqualnull122 function IsEqual(Item: TExternHelpItem; WithName: boolean): boolean;
IsDirectorynull123 function IsDirectory: boolean;
124 procedure Assign(Src: TExternHelpItem; WithName: boolean);
125 procedure IncreaseChangeStep; virtual;
126 property Name: string read FName write SetName;
127 property Filename: string read FFilename write SetFilename;
128 property WithSubDirectories: boolean read FWithSubDirectories write SetWithSubDirectories;
129 property URL: string read FURL write SetURL;
130 property StoreIn: string read FStoreIn write SetStoreIn;
131 property ChildCount: integer read GetChildCount;
132 property Children[Index: integer]: TExternHelpItem read GetChildren;
133 property ChangeStep: integer read FChangeStep;
134 end;
135
136 TExternHelpOptions = class;
137
138 { TExternHelpRootItem }
139
140 TExternHelpRootItem = class(TExternHelpItem)
141 public
142 Owner: TExternHelpOptions;
143 procedure IncreaseChangeStep; override;
144 end;
145
146 { TExternalHelpDatabase }
147
148 TExternalHelpDatabase = class(THelpDatabase)
149 public
150 constructor Create(TheOwner: TComponent); override;
151 destructor Destroy; override;
ShowHelpnull152 function ShowHelp(Query: THelpQuery; BaseNode, NewNode: THelpNode;
153 QueryItem: THelpQueryItem;
154 var ErrMsg: string): TShowHelpResult; override;
155 end;
156
157 { TExternHelpOptions }
158
159 TExternHelpOptions = class(TAbstractIDEEnvironmentOptions)
160 private
161 FChangeStep: integer;
162 FFilename: string;
163 FHelpDB: TExternalHelpDatabase;
164 FLastSavedChangeStep: integer;
165 procedure SetFilename(const AValue: string);
166 procedure PkgFileLoaded(Sender: TObject);
167 procedure LoadNode(Config: TConfigStorage; Path: string; Node: TExternHelpItem);
168 procedure SaveNode(Config: TConfigStorage; Path: string; Node: TExternHelpItem);
169 public
170 RootItem: TExternHelpRootItem;
171 constructor Create;
172 destructor Destroy; override;
173 procedure Clear;
174 procedure ClearItemsStoredInUserSettings;
175 procedure ClearItemsStoredInPackages(Parent: TExternHelpItem;
176 const Name: string = '*');
GetGroupCaptionnull177 class function GetGroupCaption: string; override;
GetInstancenull178 class function GetInstance: TAbstractIDEOptions; override;
Loadnull179 function Load(Config: TConfigStorage; KeepPackageOpts: boolean): TModalResult; virtual;
Savenull180 function Save(Config: TConfigStorage): TModalResult; virtual;
181 procedure LoadOptionsFromPackage(Pkg: TIDEPackage; Parent: TExternHelpItem);
182 procedure LoadOptionsFromPackages;
183 procedure SaveOptionsToPackage(Pkg: TIDEPackage);
184 procedure SaveOptionsToPackages;
LoadFromFilenull185 function LoadFromFile(Filename: string; KeepPackageOpts: boolean): TModalResult; virtual;
SaveToFilenull186 function SaveToFile(Filename: string): TModalResult; virtual;
Loadnull187 function Load(KeepPackageOpts: boolean): TModalResult; virtual;
Savenull188 function Save: TModalResult; virtual;
GetFullFilenamenull189 function GetFullFilename: string;
IsEqualnull190 function IsEqual(Src: TExternHelpOptions): boolean;
191 procedure Assign(Src: TExternHelpOptions); reintroduce;
192 procedure IncreaseChangeStep;
193 procedure UpdateHelpDB;
194 property Filename: string read FFilename write SetFilename;
195 property ChangeStep: integer read FChangeStep;
196 property LastSavedChangeStep: integer read FLastSavedChangeStep;
197 property HelpDB: TExternalHelpDatabase read FHelpDB;
198 end;
199
200 type
201
202 { TExternHelpGeneralOptsFrame }
203
204 TExternHelpGeneralOptsFrame = class(TAbstractIDEOptionsEditor)
205 AddSpeedButton: TSpeedButton;
206 SelEditorFileButton: TButton;
207 WithSubDirsCheckBox: TCheckBox;
208 FileUseMacrosButton: TButton;
209 DeleteSpeedButton: TSpeedButton;
210 FileBrowseButton: TButton;
211 FilenameEdit: TEdit;
212 FilenameLabel: TLabel;
213 HelpBitBtn: TBitBtn;
214 ItemsTreeView: TTreeView;
215 NameEdit: TEdit;
216 NameLabel: TLabel;
217 Splitter1: TSplitter;
218 StoreComboBox: TComboBox;
219 StoreLabel: TLabel;
220 URLLabel: TLabel;
221 URLMemo: TMemo;
222 procedure AddSpeedButtonClick(Sender: TObject);
223 procedure DeleteSpeedButtonClick(Sender: TObject);
224 procedure FileBrowseButtonClick(Sender: TObject);
225 procedure FileUseMacrosButtonClick(Sender: TObject);
226 procedure FilenameEditChange(Sender: TObject);
227 procedure FilenameEditEditingDone(Sender: TObject);
228 procedure ItemsTreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
229 State: TDragState; var Accept: Boolean);
230 procedure ItemsTreeViewEdited(Sender: TObject; Node: TTreeNode;
231 var S: string);
232 procedure ItemsTreeViewEditing(Sender: TObject; Node: TTreeNode;
233 var AllowEdit: Boolean);
234 procedure ItemsTreeViewEndDrag(Sender, Target: TObject; X, Y: Integer);
235 procedure ItemsTreeViewMouseMove(Sender: TObject; Shift: TShiftState; X,
236 Y: Integer);
237 procedure ItemsTreeViewSelectionChanged(Sender: TObject);
238 procedure ItemsTreeViewStartDrag(Sender: TObject;
239 var DragObject: TDragObject);
240 procedure NameEditChange(Sender: TObject);
241 procedure NameEditEditingDone(Sender: TObject);
242 procedure SelEditorFileButtonClick(Sender: TObject);
243 procedure StoreComboBoxEditingDone(Sender: TObject);
244 procedure URLMemoEditingDone(Sender: TObject);
245 procedure WithSubDirsCheckBoxEditingDone(Sender: TObject);
246 private
247 FOptions: TExternHelpOptions;
248 FDragNode: TTreeNode;
249 FMySettingsCaption: string;
250 procedure FillItemsTreeView;
251 procedure NameChanged(TVNode: TTreeNode; var NewName: string;
252 UpdateTree, UpdateEdit: boolean);
253 procedure StoreInChanged(TVNode: TTreeNode; var NewStoreIn: string;
254 UpdateTree, UpdateEdit: boolean);
255 procedure SelectionChanged;
FindTVNodenull256 function FindTVNode(NodeText: string): TTreeNode;
CreateUniqueNamenull257 function CreateUniqueName(Prefix: string): string;
258 procedure FillStoreInCombobox;
Macrofynull259 function Macrofy(Filename: string): string;
260 public
261 constructor Create(TheOwner: TComponent); override;
262 destructor Destroy; override;
GetTitlenull263 function GetTitle: String; override;
264 procedure ReadSettings(AOptions: TAbstractIDEOptions); override;
265 procedure Setup(ADialog: TAbstractOptionsEditorDialog); override;
SupportedOptionsClassnull266 class function SupportedOptionsClass: TAbstractIDEOptionsClass; override;
267 procedure WriteSettings(AOptions: TAbstractIDEOptions); override;
268 property Options: TExternHelpOptions read FOptions;
269 end;
270
271 var
272 ExternHelpOptions: TExternHelpOptions = nil;
273
274 procedure Register;
275
276 implementation
277
278 {$R *.lfm}
279
280 procedure Register;
281 begin
282 ExternHelpOptions:=TExternHelpOptions.Create;
283 ExternHelpOptionID:=GroupHelp;
284 ExternHelpOptionGeneralID:=RegisterIDEOptionsEditor(ExternHelpOptionID,
285 TExternHelpGeneralOptsFrame,ExternHelpOptionGeneralID)^.Index;
286 try
287 ExternHelpOptions.Load(false);
288 ExternHelpOptions.LoadOptionsFromPackages;
289 except
290 on E: Exception do begin
291 DebugLn(['Error reading externhelp options ',ExternHelpOptions.Filename,': ',E.Message]);
292 end;
293 end;
294 ExternHelpOptions.UpdateHelpDB;
295 end;
296
297 { TExternHelpOptions }
298
299 procedure TExternHelpOptions.SetFilename(const AValue: string);
300 begin
301 if FFilename=AValue then exit;
302 FFilename:=AValue;
303 end;
304
305 procedure TExternHelpOptions.PkgFileLoaded(Sender: TObject);
306 begin
307 if Sender is TIDEPackage then
308 LoadOptionsFromPackage(TIDEPackage(Sender),RootItem);
309 end;
310
311 procedure TExternHelpOptions.LoadNode(Config: TConfigStorage; Path: string;
312 Node: TExternHelpItem);
313 var
314 i, NewCount: Integer;
315 NewItem: TExternHelpItem;
316 begin
317 Node.Name:=Config.GetValue(Path+'Name','');
318 Node.Filename:=Config.GetValue(Path+'Filename/Value','');
319 Node.WithSubDirectories:=Config.GetValue(Path+'WithSubDirectories/Value',false);
320 Node.URL:=Config.GetValue(Path+'URL/Value','');
321 NewCount:=Config.GetValue(Path+'ChildCount',0);
322 for i:=1 to NewCount do begin
323 NewItem:=TExternHelpItem.Create;
324 NewItem.StoreIn:=Node.StoreIn;
325 Node.AddChild(NewItem);
326 LoadNode(Config,Path+'Item'+IntToStr(i)+'/',NewItem);
327 end;
328 end;
329
330 procedure TExternHelpOptions.SaveNode(Config: TConfigStorage; Path: string;
331 Node: TExternHelpItem);
332 var
333 i: Integer;
334 begin
335 Config.SetDeleteValue(Path+'Name',Node.Name,'');
336 Config.SetDeleteValue(Path+'Filename/Value',Node.Filename,'');
337 Config.SetDeleteValue(Path+'WithSubDirectories/Value',Node.WithSubDirectories,false);
338 Config.SetDeleteValue(Path+'URL/Value',Node.URL,'');
339 Config.SetDeleteValue(Path+'ChildCount',Node.ChildCount,0);
340 for i:=1 to Node.ChildCount do
341 SaveNode(Config,Path+'Item'+IntToStr(i)+'/',Node.Children[i-1]);
342 end;
343
344 constructor TExternHelpOptions.Create;
345 var
346 OldHelpDB: THelpDatabase;
347 begin
348 RootItem:=TExternHelpRootItem.Create;
349 RootItem.Owner:=Self;
350 Filename:='externhelp.xml';
351 OldHelpDB:=HelpDatabases.FindDatabase('External help');
352 if OldHelpDB is TExternalHelpDatabase then
353 FHelpDB:=TExternalHelpDatabase(OldHelpDB)
354 else
355 FHelpDB:=TExternalHelpDatabase(HelpDatabases.CreateHelpDatabase('External help',
356 TExternalHelpDatabase,true));
357 PackageEditingInterface.AddHandlerOnPackageFileLoaded(@PkgFileLoaded);
358 end;
359
360 destructor TExternHelpOptions.Destroy;
361 begin
362 FreeAndNil(RootItem);
363 // FHelpDB is freed by the IDE
364 inherited Destroy;
365 end;
366
367 procedure TExternHelpOptions.Clear;
368 begin
369 RootItem.Clear;
370 end;
371
372 procedure TExternHelpOptions.ClearItemsStoredInUserSettings;
373 var
374 i: Integer;
375 Item: TExternHelpItem;
376 begin
377 if RootItem<>nil then begin
378 for i:=RootItem.ChildCount-1 downto 0 do begin
379 Item:=RootItem.Children[i];
380 if (Item.StoreIn='') then
381 Item.Free;
382 end;
383 end;
384 end;
385
386 procedure TExternHelpOptions.ClearItemsStoredInPackages(Parent: TExternHelpItem;
387 const Name: string);
388 var
389 i: Integer;
390 Item: TExternHelpItem;
391 begin
392 if Parent<>nil then begin
393 for i:=Parent.ChildCount-1 downto 0 do begin
394 Item:=Parent.Children[i];
395 if (Item.StoreIn<>'')
396 and (Name='*') or (SysUtils.CompareText(Item.StoreIn,Name)=0) then
397 Item.Free;
398 end;
399 end;
400 end;
401
402 procedure TExternHelpOptions.LoadOptionsFromPackage(Pkg: TIDEPackage;
403 Parent: TExternHelpItem);
404 var
405 Cnt: integer;
406 i: Integer;
407 Path: String;
408 NewItem: TExternHelpItem;
409 begin
410 if Pkg.Name='' then exit;
411 ClearItemsStoredInPackages(Parent,Pkg.Name);
412 Path:='ExternHelp/';
413 Cnt:=Pkg.CustomOptions.GetValue(Path+'Count',0);
414 //DebugLn(['TExternHelpOptions.LoadOptionsFromPackage ',Pkg.Name,' Cnt=',Cnt]);
415 for i:=1 to Cnt do begin
416 NewItem:=TExternHelpItem.Create;
417 Parent.AddChild(NewItem);
418 NewItem.StoreIn:=Pkg.Name;
419 LoadNode(Pkg.CustomOptions,Path+'Item'+IntToStr(i)+'/',NewItem);
420 end;
421 end;
422
423 procedure TExternHelpOptions.LoadOptionsFromPackages;
424 var
425 i: Integer;
426 begin
427 if PackageEditingInterface=nil then exit;
428 ClearItemsStoredInPackages(RootItem,'*');
429 for i:=0 to PackageEditingInterface.GetPackageCount-1 do
430 LoadOptionsFromPackage(PackageEditingInterface.GetPackages(i),RootItem);
431 end;
432
433 procedure TExternHelpOptions.SaveOptionsToPackage(Pkg: TIDEPackage);
434 var
435 Cnt: Integer;
436 Path: String;
437 Item: TExternHelpItem;
438 i: Integer;
439 TmpRoot: TExternHelpItem;
440 Changed: Boolean;
441 begin
442 if Pkg.Name='' then exit;
443 //DebugLn(['TExternHelpOptions.SaveOptionsToPackage START ',Pkg.Name]);
444
445 // check if something changed
446 TmpRoot:=TExternHelpItem.Create;
447 try
448 LoadOptionsFromPackage(Pkg,TmpRoot);
449 Changed:=false;
450 Cnt:=0;
451 for i:=0 to RootItem.ChildCount-1 do begin
452 Item:=RootItem.Children[i];
453 if SysUtils.CompareText(Item.StoreIn,Pkg.Name)<>0 then continue;
454 if (Cnt=TmpRoot.ChildCount)
455 or (not TmpRoot.Children[Cnt].IsEqual(Item,true)) then begin
456 Changed:=true;
457 break;
458 end;
459 inc(Cnt);
460 end;
461 if TmpRoot.ChildCount>Cnt then Changed:=true;
462 if not Changed then exit;
463 finally
464 TmpRoot.Free;
465 end;
466 DebugLn(['TExternHelpOptions.SaveOptionsToPackage CHANGED: ',Pkg.Name]);
467
468 // save to package and mark it modified
469 Path:='ExternHelp';
470 Pkg.CustomOptions.DeletePath(Path);
471 Path:=Path+'/';
472 Cnt:=0;
473 for i:=0 to RootItem.ChildCount-1 do begin
474 Item:=RootItem.Children[i];
475 //DebugLn(['TExternHelpOptions.SaveOptionsToPackage ',Item.Name,' StoreIN=',Item.StoreIn,' ',SysUtils.CompareText(Item.StoreIn,Pkg.Name)=0]);
476 if SysUtils.CompareText(Item.StoreIn,Pkg.Name)<>0 then continue;
477 inc(Cnt);
478 SaveNode(Pkg.CustomOptions,Path+'Item'+IntToStr(Cnt)+'/',Item);
479 end;
480 Pkg.CustomOptions.SetDeleteValue(Path+'Count',Cnt,0);
481 Pkg.Modified:=True;
482 //DebugLn(['TExternHelpOptions.SaveOptionsToPackage MODIFIED: ',Pkg.Name]);
483 end;
484
485 procedure TExternHelpOptions.SaveOptionsToPackages;
486 var
487 i: Integer;
488 Pkg: TIDEPackage;
489 begin
490 if PackageEditingInterface=nil then exit;
491 for i:=0 to PackageEditingInterface.GetPackageCount-1 do begin
492 Pkg:=PackageEditingInterface.GetPackages(i);
493 if Pkg.ReadOnly then continue;
494 SaveOptionsToPackage(Pkg);
495 end;
496 end;
497
TExternHelpOptions.GetGroupCaptionnull498 class function TExternHelpOptions.GetGroupCaption: string;
499 begin
500 Result:=ehrsGroupTitle;
501 end;
502
TExternHelpOptions.GetInstancenull503 class function TExternHelpOptions.GetInstance: TAbstractIDEOptions;
504 begin
505 Result:=ExternHelpOptions;
506 end;
507
Loadnull508 function TExternHelpOptions.Load(Config: TConfigStorage;
509 KeepPackageOpts: boolean): TModalResult;
510 var
511 Path: String;
512 begin
513 Result:=mrOk;
514 if KeepPackageOpts then
515 ClearItemsStoredInUserSettings
516 else
517 Clear;
518 Path:='ExternHelp/';
519 LoadNode(Config,Path+'Items/',RootItem);
520 end;
521
TExternHelpOptions.Savenull522 function TExternHelpOptions.Save(Config: TConfigStorage): TModalResult;
523 var
524 Path: String;
525 Item: TExternHelpItem;
526 i: Integer;
527 Cnt: Integer;
528 begin
529 Result:=mrOk;
530 Path:='ExternHelp/';
531 Cnt:=0;
532 for i:=1 to RootItem.ChildCount do begin
533 Item:=RootItem.Children[i-1];
534 if Item.StoreIn<>'' then continue;
535 inc(Cnt);
536 SaveNode(Config,Path+'Items/Item'+IntToStr(Cnt)+'/',Item);
537 end;
538 Config.SetDeleteValue(Path+'Items/ChildCount',Cnt,0);
539 end;
540
TExternHelpOptions.LoadFromFilenull541 function TExternHelpOptions.LoadFromFile(Filename: string;
542 KeepPackageOpts: boolean): TModalResult;
543 var
544 Config: TConfigStorage;
545 begin
546 Config:=GetIDEConfigStorage(Filename,true);
547 try
548 Result:=Load(Config,KeepPackageOpts);
549 finally
550 Config.Free;
551 end;
552 end;
553
TExternHelpOptions.SaveToFilenull554 function TExternHelpOptions.SaveToFile(Filename: string): TModalResult;
555 var
556 Config: TConfigStorage;
557 begin
558 Config:=GetIDEConfigStorage(Filename,false);
559 try
560 Result:=Save(Config);
561 //DebugLn(['TExternHelpOptions.SaveToFile ',Filename,' ',Config.GetFilename]);
562 Config.WriteToDisk;
563 //DebugLn(['TExternHelpOptions.SaveToFile exists=',FileExistsUTF8(GetFullFilename)]);
564 finally
565 Config.Free;
566 end;
567 end;
568
Loadnull569 function TExternHelpOptions.Load(KeepPackageOpts: boolean): TModalResult;
570 begin
571 Result:=LoadFromFile(Filename,KeepPackageOpts);
572 FLastSavedChangeStep:=ChangeStep;
573 end;
574
TExternHelpOptions.Savenull575 function TExternHelpOptions.Save: TModalResult;
576 var
577 FullFilename: String;
578 begin
579 FullFilename:=GetFullFilename;
580 if FileExistsUTF8(FullFilename)
581 and (FLastSavedChangeStep=ChangeStep) then
582 Result:=mrOK;
583 Result:=SaveToFile(Filename);
584 FLastSavedChangeStep:=ChangeStep;
585 end;
586
GetFullFilenamenull587 function TExternHelpOptions.GetFullFilename: string;
588 begin
589 Result:=Filename;
590 if FilenameIsAbsolute(Result) then exit;
591 Result:=AppendPathDelim(LazarusIDE.GetPrimaryConfigPath)+Result;
592 end;
593
TExternHelpOptions.IsEqualnull594 function TExternHelpOptions.IsEqual(Src: TExternHelpOptions): boolean;
595 begin
596 Result:=RootItem.IsEqual(Src.RootItem,false);
597 end;
598
599 procedure TExternHelpOptions.Assign(Src: TExternHelpOptions);
600 begin
601 RootItem.Assign(Src.RootItem,false);
602 end;
603
604 procedure TExternHelpOptions.IncreaseChangeStep;
605 begin
606 if FChangeStep=high(FChangeStep) then
607 FChangeStep:=low(FChangeStep)
608 else
609 inc(FChangeStep);
610 end;
611
612 procedure TExternHelpOptions.UpdateHelpDB;
613
614 procedure RegisterItem(Item: TExternHelpItem);
615 var
616 i: Integer;
617 HelpNode: THelpNode;
618 ItemFilename: String;
619 SrcFilter: THelpDBISourceFile;
620 begin
621 if (Item.Filename<>'') and (Item.URL<>'') then begin
622 ItemFilename:=GetForcedPathDelims(Item.Filename);
623 // create a help node for this topic
624 HelpNode:=THelpNode.CreateURL(HelpDB,Item.Name,Item.URL);
625 // create a filter for the source file(s)
626 if Item.IsDirectory then
627 SrcFilter:=THelpDBISourceDirectory.Create(HelpNode,
628 ItemFilename,'*.pp;*.pas',Item.WithSubDirectories)
629 else
630 SrcFilter:=THelpDBISourceFile.Create(HelpNode,ItemFilename);
631 HelpDB.RegisterItem(SrcFilter);
632 end;
633
634 for i:=0 to Item.ChildCount-1 do
635 RegisterItem(Item.Children[i]);
636 end;
637
638 begin
639 HelpDB.UnregisterAllItems;
640 RegisterItem(RootItem);
641 end;
642
643 { TExternHelpGeneralOptsFrame }
644
645 procedure TExternHelpGeneralOptsFrame.ItemsTreeViewEdited(Sender: TObject;
646 Node: TTreeNode; var S: string);
647 begin
648 NameChanged(Node,S,false,true);
649 end;
650
651 procedure TExternHelpGeneralOptsFrame.FilenameEditEditingDone(Sender: TObject);
652 var
653 s: String;
654 TVNode: TTreeNode;
655 Item: TExternHelpItem;
656 Msg: String;
657 Filename: String;
658 begin
659 TVNode:=ItemsTreeView.Selected;
660 if (TVNode=nil) or (not (TObject(TVNode.Data) is TExternHelpItem)) then exit;
661 Item:=TExternHelpItem(TVNode.Data);
662 s:=FilenameEdit.Text;
663 s:=TrimFilename(s);
664 if s<>Item.Filename then begin
665 Filename:=s;
666 if s='' then begin
667 // ok, allow simple deactivate
668 end else begin
669 ForcePathDelims(Filename);
670 IDEMacros.SubstituteMacros(Filename);
671 Msg:='';
672 if (Filename<>'') and (Filename[length(Filename)]=PathDelim) then begin
673 if not DirPathExists(Filename) then
674 Msg:=Format(ehrsDirectoryNotFound, [Filename]);
675 end else begin
676 if not FileExistsUTF8(Filename) then
677 Msg:=Format(ehrsFileNotFound, [Filename]);
678 end;
679 if Msg<>'' then begin
680 MessageDlg(ehrsWarning, Msg, mtWarning, [mbIgnore], 0);
681 end;
682 end;
683 Item.Filename:=s;
684 if not Item.IsDirectory then
685 Item.WithSubDirectories:=false;
686 WithSubDirsCheckBox.Enabled:=Item.IsDirectory;
687 end;
688 end;
689
690 procedure TExternHelpGeneralOptsFrame.ItemsTreeViewDragOver(Sender,
691 Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
692 var
693 TVNode: TTreeNode;
694 InsertType: TTreeViewInsertMarkType;
695 begin
696 if State=dsDragEnter then ;
697 if (Source<>ItemsTreeView) or (FDragNode=nil) then begin
698 Accept:=false;
699 exit;
700 end;
701 ItemsTreeView.GetInsertMarkAt(X,Y,TVNode,InsertType);
702 if (TVNode<>nil) then
703 if (TVNode=FDragNode) or TVNode.HasAsParent(FDragNode)
704 or FDragNode.HasAsParent(TVNode) then begin
705 Accept:=false;
706 exit;
707 end;
708 end;
709
710 procedure TExternHelpGeneralOptsFrame.AddSpeedButtonClick(Sender: TObject);
711 var
712 SelTVNode: TTreeNode;
713 Item: TExternHelpItem;
714 TVNode: TTreeNode;
715 SelItem: TExternHelpItem;
716 begin
717 SelTVNode:=ItemsTreeView.Selected;
718 Item:=TExternHelpItem.Create;
719 Item.Name:=CreateUniqueName('Item');
720 if (SelTVNode<>nil) and (TObject(SelTVNode.Data) is TExternHelpItem) then
721 begin
722 // init with values of selected node
723 SelItem:=TExternHelpItem(SelTVNode.Data);
724 Item.Filename:=SelItem.Filename;
725 Item.URL:=SelItem.URL;
726 Item.StoreIn:=SelItem.StoreIn;
727 SelItem.Parent.AddChild(Item);
728 end else
729 Options.RootItem.AddChild(Item);
730 TVNode:=ItemsTreeView.Items.AddObject(SelTVNode,Item.Name,Item);
731 ItemsTreeView.Selected:=TVNode;
732 end;
733
734 procedure TExternHelpGeneralOptsFrame.DeleteSpeedButtonClick(Sender: TObject);
735 var
736 SelTVNode: TTreeNode;
737 Item: TExternHelpItem;
738 begin
739 SelTVNode:=ItemsTreeView.Selected;
740 if (SelTVNode=nil) or (not (TObject(SelTVNode.Data) is TExternHelpItem)) then exit;
741 Item:=TExternHelpItem(SelTVNode.Data);
742 // select next
743 if SelTVNode.GetNext<>nil then
744 ItemsTreeView.Selected:=SelTVNode.GetNext
745 else
746 ItemsTreeView.Selected:=SelTVNode.GetPrev;
747 // delete in treeview
748 SelTVNode.Free;
749 // delete in Options
750 Item.Free;
751 end;
752
753 procedure TExternHelpGeneralOptsFrame.FileBrowseButtonClick(Sender: TObject);
754 var
755 OpenDialog: TOpenDialog;
756 Filename: String;
757 SelTVNode: TTreeNode;
758 Item: TExternHelpItem;
759 begin
760 OpenDialog:=TOpenDialog.Create(nil);
761 try
762 InitIDEFileDialog(OpenDialog);
763 OpenDialog.Title:=ehrsChooseAPascalUnit;
764 if not OpenDialog.Execute then exit;
765 Filename:=Macrofy(TrimFilename(OpenDialog.FileName));
766 FilenameEdit.Text:=Filename;
767 SelTVNode:=ItemsTreeView.Selected;
768 if (SelTVNode<>nil) and (TObject(SelTVNode.Data) is TExternHelpItem) then
769 begin
770 Item:=TExternHelpItem(SelTVNode.Data);
771 Item.Filename:=Filename;
772 end;
773 finally
774 OpenDialog.Free;
775 end;
776 end;
777
778 procedure TExternHelpGeneralOptsFrame.FileUseMacrosButtonClick(Sender: TObject);
779 var
780 Filename: String;
781 begin
782 Filename:=TrimFilename(FilenameEdit.Text);
783 FilenameEdit.Text:=Macrofy(Filename);
784 end;
785
786 procedure TExternHelpGeneralOptsFrame.FilenameEditChange(Sender: TObject);
787 var
788 s: String;
789 TVNode: TTreeNode;
790 begin
791 TVNode:=ItemsTreeView.Selected;
792 if (TVNode=nil) or (not (TObject(TVNode.Data) is TExternHelpItem)) then exit;
793 s:=FilenameEdit.Text;
794 s:=TrimFilename(s);
795 WithSubDirsCheckBox.Enabled:=(s<>'') and (s[length(s)] in ['/','\']);
796 end;
797
798 procedure TExternHelpGeneralOptsFrame.ItemsTreeViewEditing(Sender: TObject;
799 Node: TTreeNode; var AllowEdit: Boolean);
800 begin
801 if AllowEdit or (Node=nil) then ;
802 end;
803
804 procedure TExternHelpGeneralOptsFrame.ItemsTreeViewEndDrag(Sender,
805 Target: TObject; X, Y: Integer);
806 begin
807 FDragNode:=nil;
808 if (Target=nil) or (X=0) or (Y=0) then ;
809 ItemsTreeView.Options:=ItemsTreeView.Options-[tvoAutoInsertMark];
810 end;
811
812 procedure TExternHelpGeneralOptsFrame.ItemsTreeViewMouseMove(Sender: TObject;
813 Shift: TShiftState; X, Y: Integer);
814 var
815 TVNode: TTreeNode;
816 begin
817 if not (ssLeft in Shift) then begin
818 // no left mouse button => stop showing insert mark
819 //if tvoAutoInsertMark in ItemsTreeView.Options then DebugLn(['TExternHelpGeneralOptsFrame.ItemsTreeViewMouseMove no left']);
820 ItemsTreeView.Options:=ItemsTreeView.Options-[tvoAutoInsertMark];
821 FDragNode:=nil;
822 end else if (not ItemsTreeView.Dragging) then begin
823 // left mouse button is presses and not yet dragging => start dragging
824 TVNode:=ItemsTreeView.GetNodeAt(X,Y);
825 if (TVNode<>nil) then begin
826 // a node to drag => start dragging
827 FDragNode:=TVNode;
828 ItemsTreeView.BeginDrag(true);
829 ItemsTreeView.Options:=ItemsTreeView.Options-[tvoAutoInsertMark];
830 //DebugLn(['TExternHelpGeneralOptsFrame.ItemsTreeViewMouseMove START']);
831 end else begin
832 // no node to drag
833 ItemsTreeView.Options:=ItemsTreeView.Options-[tvoAutoInsertMark];
834 FDragNode:=nil;
835 //DebugLn(['TExternHelpGeneralOptsFrame.ItemsTreeViewMouseMove no node']);
836 end;
837 end;
838 end;
839
840 procedure TExternHelpGeneralOptsFrame.ItemsTreeViewSelectionChanged(
841 Sender: TObject);
842 begin
843 SelectionChanged;
844 end;
845
846 procedure TExternHelpGeneralOptsFrame.ItemsTreeViewStartDrag(Sender: TObject;
847 var DragObject: TDragObject);
848 begin
849 if DragObject=nil then ;
850 ItemsTreeView.Options:=ItemsTreeView.Options+[tvoAutoInsertMark];
851 end;
852
853 procedure TExternHelpGeneralOptsFrame.NameEditChange(Sender: TObject);
854 var
855 S: String;
856 begin
857 S:=NameEdit.Text;
858 NameChanged(ItemsTreeView.Selected,S,true,false);
859 end;
860
861 procedure TExternHelpGeneralOptsFrame.NameEditEditingDone(Sender: TObject);
862 var
863 S: String;
864 begin
865 S:=NameEdit.Text;
866 NameChanged(ItemsTreeView.Selected,S,true,true);
867 end;
868
869 procedure TExternHelpGeneralOptsFrame.SelEditorFileButtonClick(Sender: TObject);
870 var
871 Selector: TExternHelpFileSelector;
872 i: Integer;
873 Filename: String;
874 Files: TStringList;
875 j: Integer;
876 Filename2: String;
877 SelTVNode: TTreeNode;
878 Item: TExternHelpItem;
879 begin
880 if SourceEditorManagerIntf=nil then exit;
881 Files:=TStringList.Create;
882 Selector:=TExternHelpFileSelector.Create(GetParentForm(Self));
883 try
884 // collect open editor files
885 for i:=0 to SourceEditorManagerIntf.SourceEditorCount-1 do begin
886 Filename:=SourceEditorManagerIntf.SourceEditors[i].FileName;
887 j:=Files.Count-1;
888 while (j>=0) and (CompareFilenames(Files[j],Filename)<>0) do dec(j);
889 if j>=0 then continue;
890 Files.Add(Filename);
891 end;
892 // shorten file names
893 for i:=0 to Files.Count-1 do begin
894 Filename:=ExtractFileName(Files[i]);
895 j:=Files.Count-1;
896 while (j>=0)
897 and ((i=j) or (CompareFilenames(ExtractFileName(Files[j]),Filename)<>0)) do
898 dec(j);
899 if (j<0) then begin
900 // short file is unique => use short file
901 Files[i]:=Filename;
902 end;
903 end;
904 Selector.FileListBox.Items:=Files;
905 Selector.Position:=poOwnerFormCenter;
906 Selector.Caption:=ehrsSelectFile;
907 if Files.Count>0 then
908 Selector.FileListBox.ItemIndex:=0;
909 if (Selector.ShowModal=mrOK) then begin
910 i:=Selector.FileListBox.ItemIndex;
911 if i>=0 then begin
912 Filename2:=Selector.FileListBox.Items[i];
913 for i:=0 to SourceEditorManagerIntf.SourceEditorCount-1 do begin
914 Filename:=SourceEditorManagerIntf.SourceEditors[i].FileName;
915 if (CompareFilenames(Filename2,Filename)=0)
916 or (CompareFilenames(Filename2,ExtractFileName(Filename))=0) then
917 begin
918 Filename:=Macrofy(FileName);
919 FilenameEdit.Text:=Filename;
920 SelTVNode:=ItemsTreeView.Selected;
921 if (SelTVNode<>nil) and (TObject(SelTVNode.Data) is TExternHelpItem)
922 then begin
923 Item:=TExternHelpItem(SelTVNode.Data);
924 Item.Filename:=Filename;
925 end;
926 exit;
927 end;
928 end;
929 end;
930 end;
931 finally
932 Selector.Free;
933 Files.Free;
934 end;
935 end;
936
937 procedure TExternHelpGeneralOptsFrame.StoreComboBoxEditingDone(Sender: TObject);
938 var
939 S: String;
940 begin
941 S:=StoreComboBox.Text;
942 StoreInChanged(ItemsTreeView.Selected,S,true,true);
943 end;
944
945 procedure TExternHelpGeneralOptsFrame.URLMemoEditingDone(Sender: TObject);
946 var
947 s: String;
948 TVNode: TTreeNode;
949 Item: TExternHelpItem;
950 begin
951 URLMemo.Lines.Delimiter:=' ';
952 s:=URLMemo.Lines.DelimitedText;
953 TVNode:=ItemsTreeView.Selected;
954 if (TVNode=nil) or (not (TObject(TVNode.Data) is TExternHelpItem)) then exit;
955 Item:=TExternHelpItem(TVNode.Data);
956 s:=Trim(s);
957 if s<>Item.URL then begin
958 Item.URL:=s;
959 end;
960 end;
961
962 procedure TExternHelpGeneralOptsFrame.WithSubDirsCheckBoxEditingDone(
963 Sender: TObject);
964 var
965 TVNode: TTreeNode;
966 Item: TExternHelpItem;
967 begin
968 TVNode:=ItemsTreeView.Selected;
969 if (TVNode=nil) or (not (TObject(TVNode.Data) is TExternHelpItem)) then exit;
970 Item:=TExternHelpItem(TVNode.Data);
971 Item.WithSubDirectories:=WithSubDirsCheckBox.Checked;
972 end;
973
974 procedure TExternHelpGeneralOptsFrame.FillItemsTreeView;
975
976 procedure Add(ParentItem: TExternHelpItem; ParentTVNode: TTreeNode);
977 var
978 i: Integer;
979 Item: TExternHelpItem;
980 TVNode: TTreeNode;
981 begin
982 for i:=0 to ParentItem.ChildCount-1 do begin
983 Item:=ParentItem.Children[i];
984 TVNode:=ItemsTreeView.Items.AddChildObject(ParentTVNode,Item.Name,Item);
985 Add(Item,TVNode);
986 TVNode.Expanded:=true;
987 end;
988 end;
989
990 begin
991 ItemsTreeView.BeginUpdate;
992 ItemsTreeView.Items.Clear;
993 Add(Options.RootItem,nil);
994 ItemsTreeView.EndUpdate;
995 end;
996
997 procedure TExternHelpGeneralOptsFrame.NameChanged(TVNode: TTreeNode;
998 var NewName: string; UpdateTree, UpdateEdit: boolean);
999 var
1000 Item: TExternHelpItem;
1001 begin
1002 NewName:=Trim(NewName);
1003 if (TVNode<>nil) and (TObject(TVNode.Data) is TExternHelpItem) then begin
1004 Item:=TExternHelpItem(TVNode.Data);
1005 Item.Name:=NewName;
1006 if UpdateTree then
1007 TVNode.Text:=NewName;
1008 if UpdateEdit then
1009 NameEdit.Text:=NewName;
1010 end;
1011 end;
1012
1013 procedure TExternHelpGeneralOptsFrame.StoreInChanged(TVNode: TTreeNode; var
1014 NewStoreIn: string; UpdateTree, UpdateEdit: boolean);
1015 var
1016 Item: TExternHelpItem;
1017 begin
1018 NewStoreIn:=Trim(NewStoreIn);
1019 if NewStoreIn=FMySettingsCaption then
1020 NewStoreIn:='';
1021 if (TVNode<>nil) and (TObject(TVNode.Data) is TExternHelpItem) then begin
1022 Item:=TExternHelpItem(TVNode.Data);
1023 Item.StoreIn:=NewStoreIn;
1024 if UpdateTree then
1025 ;
1026 if UpdateEdit then
1027 StoreComboBox.Text:=NewStoreIn;
1028 end;
1029 end;
1030
1031 procedure TExternHelpGeneralOptsFrame.SelectionChanged;
1032 var
1033 TVNode: TTreeNode;
1034 Item: TExternHelpItem;
1035 s: String;
1036 ItemFilename: String;
1037 begin
1038 TVNode:=ItemsTreeView.Selected;
1039 Item:=nil;
1040 if (TVNode<>nil) and (TObject(TVNode.Data) is TExternHelpItem) then
1041 Item:=TExternHelpItem(TVNode.Data);
1042 DisableAlign;
1043 try
1044 if Item<>nil then begin
1045 NameEdit.Enabled:=true;
1046 NameEdit.Text:=Item.Name;
1047 FilenameEdit.Enabled:=true;
1048 ItemFilename:=GetForcedPathDelims(Item.Filename);
1049 FilenameEdit.Text:=ItemFilename;
1050 WithSubDirsCheckBox.Enabled:=Item.IsDirectory;
1051 WithSubDirsCheckBox.Checked:=Item.WithSubDirectories;
1052 URLMemo.Enabled:=true;
1053 URLMemo.Lines.Text:=Item.URL;
1054 StoreComboBox.Enabled:=Item.Parent=Options.RootItem;
1055 s:=Item.StoreIn;
1056 if s='' then s:=FMySettingsCaption;
1057 StoreComboBox.Text:=s;
1058 end else begin
1059 NameEdit.Enabled:=false;
1060 NameEdit.Text:='';
1061 FilenameEdit.Enabled:=false;
1062 FilenameEdit.Text:='';
1063 WithSubDirsCheckBox.Enabled:=false;
1064 WithSubDirsCheckBox.Checked:=false;
1065 URLMemo.Enabled:=false;
1066 URLMemo.Lines.Text:='';
1067 StoreComboBox.Enabled:=false;
1068 StoreComboBox.Text:='';
1069 end;
1070 finally
1071 EnableAlign;
1072 end;
1073 end;
1074
FindTVNodenull1075 function TExternHelpGeneralOptsFrame.FindTVNode(NodeText: string): TTreeNode;
1076 begin
1077 Result:=ItemsTreeView.Items.GetFirstNode;
1078 while (Result<>nil) and (SysUtils.CompareText(Result.Text,NodeText)<>0) do
1079 Result:=Result.GetNext;
1080 end;
1081
CreateUniqueNamenull1082 function TExternHelpGeneralOptsFrame.CreateUniqueName(Prefix: string): string;
1083 var
1084 i: Integer;
1085 begin
1086 i:=0;
1087 repeat
1088 inc(i);
1089 Result:=Prefix+IntToStr(i);
1090 until FindTVNode(Result)=nil;
1091 end;
1092
1093 procedure TExternHelpGeneralOptsFrame.FillStoreInCombobox;
1094 var
1095 sl: TStringListUTF8Fast;
1096 i: Integer;
1097 begin
1098 sl:=TStringListUTF8Fast.Create;
1099 try
1100 for i:=0 to PackageEditingInterface.GetPackageCount-1 do
1101 sl.Add(PackageEditingInterface.GetPackages(i).Name);
1102 sl.Sort;
1103 sl.Insert(0, Trim(FMySettingsCaption));
1104 StoreComboBox.Items.Assign(sl);
1105 finally
1106 sl.Free;
1107 end;
1108 end;
1109
Macrofynull1110 function TExternHelpGeneralOptsFrame.Macrofy(Filename: string): string;
1111
1112 procedure CheckPath(PathMacro: string; var s: string);
1113 var
1114 Value: String;
1115 begin
1116 Value:=PathMacro;
1117 if (not IDEMacros.SubstituteMacros(Value)) or (Value='')
1118 or (Value[1]='$') then
1119 exit;
1120 Value:=ChompPathDelim(Value);
1121 if (CompareFilenames(copy(s,1,length(Value)),Value)=0)
1122 and ((length(s)<=length(Value)) or (s[length(Value)+1]=PathDelim)) then
1123 begin
1124 // filename is a file in the macro path
1125 s:=PathMacro+copy(s,length(Value)+1,length(s));
1126 exit;
1127 end;
1128 end;
1129
1130 begin
1131 Result:=Filename;
1132 CheckPath('$(FPCSrcDir)',Result);
1133 CheckPath('$(LazarusDir)',Result);
1134 end;
1135
1136 constructor TExternHelpGeneralOptsFrame.Create(TheOwner: TComponent);
1137 begin
1138 inherited Create(TheOwner);
1139 FOptions:=TExternHelpOptions.Create;
1140 IDEImages.AssignImage(AddSpeedButton, 'laz_add');
1141 IDEImages.AssignImage(DeleteSpeedButton, 'laz_delete');
1142 end;
1143
1144 destructor TExternHelpGeneralOptsFrame.Destroy;
1145 begin
1146 FreeAndNil(FOptions);
1147 inherited Destroy;
1148 end;
1149
TExternHelpGeneralOptsFrame.GetTitlenull1150 function TExternHelpGeneralOptsFrame.GetTitle: String;
1151 begin
1152 Result:=ehrsExternal;
1153 end;
1154
1155 procedure TExternHelpGeneralOptsFrame.ReadSettings(AOptions: TAbstractIDEOptions);
1156 begin
1157 if not (AOptions is TAbstractIDEHelpOptions) then exit;
1158 Options.Assign(ExternHelpOptions);
1159 FillStoreInCombobox;
1160 FillItemsTreeView;
1161 ItemsTreeView.Selected:=ItemsTreeView.Items.GetFirstNode;
1162 SelectionChanged;
1163 end;
1164
1165 procedure TExternHelpGeneralOptsFrame.Setup(ADialog: TAbstractOptionsEditorDialog);
1166 begin
1167 if ADialog=nil then ;
1168 NameLabel.Caption:=ehrsName;
1169 FilenameLabel.Caption:=ehrsUnitFileOrUnitDirectory;
1170 URLLabel.Caption:=ehrsURL;
1171 HelpBitBtn.Caption:=ehrsHelp;
1172 AddSpeedButton.Hint:=ehrsAddNewItem;
1173 DeleteSpeedButton.Hint:=ehrsDeleteItem;
1174 FileBrowseButton.Caption:=ehrsBrowse;
1175 FileBrowseButton.Hint:=ehrsBrowseForPath;
1176 FileUseMacrosButton.Caption:=ehrsMacrofy;
1177 FileUseMacrosButton.Hint:=ehrsReplaceCommonDirectoriesWithMacros;
1178 SelEditorFileButton.Caption:=ehrsEditorFile;
1179 SelEditorFileButton.Hint:=ehrsSelectAFileFromTheSourceEditor;
1180 WithSubDirsCheckBox.Caption:=ehrsIncludeSubDirectories;
1181 StoreLabel.Caption:=ehrsStoreThisURLIn;
1182 FMySettingsCaption:=ehrsMySettings;
1183 end;
1184
TExternHelpGeneralOptsFrame.SupportedOptionsClassnull1185 class function TExternHelpGeneralOptsFrame.SupportedOptionsClass: TAbstractIDEOptionsClass;
1186 begin
1187 Result:=TAbstractIDEHelpOptions;
1188 end;
1189
1190 procedure TExternHelpGeneralOptsFrame.WriteSettings(AOptions: TAbstractIDEOptions);
1191 begin
1192 if not (AOptions is TAbstractIDEHelpOptions) then exit;
1193 if ExternHelpOptions.IsEqual(Options) then exit;
1194 ExternHelpOptions.Assign(Options);
1195 try
1196 ExternHelpOptions.Save;
1197 except
1198 on E: Exception do begin
1199 DebugLn(['TExternHelpGeneralOptsFrame.WriteSettings unable to write file ',ExternHelpOptions.Filename,': ',E.Message]);
1200 end;
1201 end;
1202 ExternHelpOptions.SaveOptionsToPackages;
1203 ExternHelpOptions.UpdateHelpDB;
1204 end;
1205
1206 { TExternHelpItem }
1207
GetChildCountnull1208 function TExternHelpItem.GetChildCount: integer;
1209 begin
1210 Result:=fChilds.Count;
1211 end;
1212
TExternHelpItem.GetChildrennull1213 function TExternHelpItem.GetChildren(Index: integer): TExternHelpItem;
1214 begin
1215 Result:=TExternHelpItem(fChilds[Index]);
1216 end;
1217
1218 procedure TExternHelpItem.SetFilename(const AValue: string);
1219 begin
1220 if FFilename=AValue then exit;
1221 FFilename:=AValue;
1222 IncreaseChangeStep;
1223 end;
1224
1225 procedure TExternHelpItem.SetName(const AValue: string);
1226 begin
1227 if FName=AValue then exit;
1228 FName:=AValue;
1229 IncreaseChangeStep;
1230 end;
1231
1232 procedure TExternHelpItem.SetStoreIn(const AValue: string);
1233 begin
1234 if FStoreIn=AValue then exit;
1235 FStoreIn:=AValue;
1236 IncreaseChangeStep;
1237 end;
1238
1239 procedure TExternHelpItem.SetURL(const AValue: string);
1240 begin
1241 if FURL=AValue then exit;
1242 FURL:=AValue;
1243 IncreaseChangeStep;
1244 end;
1245
1246 procedure TExternHelpItem.SetWithSubDirectories(const AValue: boolean);
1247 begin
1248 if FWithSubDirectories=AValue then exit;
1249 FWithSubDirectories:=AValue;
1250 IncreaseChangeStep;
1251 end;
1252
1253 constructor TExternHelpItem.Create;
1254 begin
1255 fChilds:=TFPList.Create;
1256 end;
1257
1258 destructor TExternHelpItem.Destroy;
1259 begin
1260 if Parent<>nil then
1261 Parent.RemoveChild(Parent.IndexOf(Self));
1262 Clear;
1263 FreeAndNil(fChilds);
1264 inherited Destroy;
1265 end;
1266
1267 procedure TExternHelpItem.Clear;
1268 var
1269 i: Integer;
1270 Child: TExternHelpItem;
1271 begin
1272 if (ChildCount=0) and (URL='') and (Filename='') and (StoreIn='') then exit;
1273 for i:=fChilds.Count-1 downto 0 do begin
1274 Child:=Children[i];
1275 Child.Parent:=nil;
1276 Child.Free;
1277 end;
1278 fChilds.Clear;
1279 fURL:='';
1280 FFilename:='';
1281 FWithSubDirectories:=false;
1282 FStoreIn:='';
1283 IncreaseChangeStep;
1284 end;
1285
1286 procedure TExternHelpItem.AddChild(Item: TExternHelpItem);
1287 begin
1288 Item.Parent:=Self;
1289 fChilds.Add(Item);
1290 IncreaseChangeStep;
1291 end;
1292
1293 procedure TExternHelpItem.MoveChild(FromPos, ToPos: integer);
1294 begin
1295 if FromPos=ToPos then exit;
1296 fChilds.Move(FromPos,ToPos);
1297 IncreaseChangeStep;
1298 end;
1299
1300 procedure TExternHelpItem.RemoveChild(Index: integer);
1301 begin
1302 Children[Index].Parent:=nil;
1303 fChilds.Delete(Index);
1304 IncreaseChangeStep;
1305 end;
1306
1307 procedure TExternHelpItem.DeleteChild(Index: integer);
1308 begin
1309 Children[Index].Free;
1310 end;
1311
1312 procedure TExternHelpItem.DeleteChild(Child: TExternHelpItem);
1313 begin
1314 Child.Free;
1315 end;
1316
IndexOfnull1317 function TExternHelpItem.IndexOf(Child: TExternHelpItem): integer;
1318 begin
1319 Result:=fChilds.IndexOf(Child);
1320 end;
1321
TExternHelpItem.IsEqualnull1322 function TExternHelpItem.IsEqual(Item: TExternHelpItem; WithName: boolean
1323 ): boolean;
1324 var
1325 i: Integer;
1326 begin
1327 Result:=((not WithName) or (Name=Item.Name))
1328 and (Filename=Item.Filename)
1329 and (WithSubDirectories=Item.WithSubDirectories)
1330 and (URL=Item.URL)
1331 and (StoreIn=Item.StoreIn)
1332 and (ChildCount=Item.ChildCount);
1333 if Result then begin
1334 for i:=0 to ChildCount-1 do
1335 if not (Children[i].IsEqual(Item.Children[i],true)) then exit(false);
1336 end;
1337 end;
1338
IsDirectorynull1339 function TExternHelpItem.IsDirectory: boolean;
1340 begin
1341 Result:=(Filename<>'') and (Filename[length(Filename)] in ['/','\']);
1342 end;
1343
1344 procedure TExternHelpItem.Assign(Src: TExternHelpItem; WithName: boolean);
1345 var
1346 i: Integer;
1347 Item: TExternHelpItem;
1348 begin
1349 if WithName then Name:=Src.Name;
1350 Filename:=Src.Filename;
1351 WithSubDirectories:=Src.WithSubDirectories;
1352 URL:=Src.URL;
1353 StoreIn:=Src.StoreIn;
1354 for i:=0 to Src.ChildCount-1 do begin
1355 if ChildCount<=i then begin
1356 Item:=TExternHelpItem.Create;
1357 AddChild(Item);
1358 IncreaseChangeStep;
1359 end else begin
1360 Item:=Children[i];
1361 end;
1362 Item.Assign(Src.Children[i],true);
1363 end;
1364 while ChildCount>Src.ChildCount do begin
1365 DeleteChild(ChildCount-1);
1366 IncreaseChangeStep;
1367 end;
1368 end;
1369
1370 procedure TExternHelpItem.IncreaseChangeStep;
1371 begin
1372 if Parent<>nil then Parent.IncreaseChangeStep;
1373 if FChangeStep=High(FChangeStep) then
1374 FChangeStep:=low(FChangeStep)
1375 else
1376 inc(FChangeStep);
1377 end;
1378
1379 { TExternHelpRootItem }
1380
1381 procedure TExternHelpRootItem.IncreaseChangeStep;
1382 begin
1383 inherited IncreaseChangeStep;
1384 Owner.IncreaseChangeStep;
1385 end;
1386
1387 { TExternalHelpDatabase }
1388
1389 constructor TExternalHelpDatabase.Create(TheOwner: TComponent);
1390 begin
1391 inherited Create(TheOwner);
1392 end;
1393
1394 destructor TExternalHelpDatabase.Destroy;
1395 begin
1396 inherited Destroy;
1397 end;
1398
TExternalHelpDatabase.ShowHelpnull1399 function TExternalHelpDatabase.ShowHelp(Query: THelpQuery; BaseNode,
1400 NewNode: THelpNode; QueryItem: THelpQueryItem; var ErrMsg: string
1401 ): TShowHelpResult;
1402 var
1403 ContextList: TPascalHelpContextList;
1404 Identifier: String;
1405 AUnitName: String;
1406 i: Integer;
1407 Context: String;
1408 p: LongInt;
1409 URL: String;
1410 ShowNode: THelpNode;
1411 Viewer: THelpViewer;
1412 begin
1413 //DebugLn(['TExternalHelpDatabase.ShowHelp ',DbgSName(Query)]);
1414 if (Query is THelpQueryPascalContexts)
1415 and (QueryItem is TPascalHelpContextList) then begin
1416 // a pascal context query
1417 ContextList:=TPascalHelpContextList(QueryItem);
1418 if (ContextList.Count>0) and (ContextList.List[0].Descriptor=pihcFilename)
1419 then begin
1420 // extract unit filename
1421 AUnitName:=ExtractFileNameOnly(ContextList.List[0].Context);
1422 DebugLn('TExternalHelpDatabase.ShowHelp A Unitname=',AUnitname,' NewNode.HelpType=',dbgs(ord(NewNode.HelpType)),' NewNode.Title=',NewNode.Title,' NewNode.URL=',NewNode.URL);
1423 if AUnitName<>'' then begin
1424
1425 // extract identifier
1426 Identifier:='';
1427 for i:=0 to ContextList.Count-1 do begin
1428 Context:=ContextList.List[i].Context;
1429 case ContextList.List[i].Descriptor of
1430
1431 pihcProperty,pihcVariable,pihcType,pihcConst:
1432 begin
1433 Identifier:=Context;
1434 break;
1435 end;
1436
1437 pihcProcedure:
1438 begin
1439 // chomp parameters ToDo: overloaded procs
1440 p:=System.Pos('(',Context);
1441 if p>0 then
1442 Context:=copy(Context,1,p-1);
1443 Identifier:=Context;
1444 break;
1445 end;
1446
1447 end;
1448 end;
1449
1450 if Identifier<>'' then begin
1451 DebugLn(['TExternalHelpDatabase.ShowHelp Identifier=',Identifier]);
1452 // replace special macros (Identifier)
1453 URL:=NewNode.URL;
1454 repeat
1455 p:=PosI('$(identifier)',URL);
1456 if p<1 then break;
1457 URL:=copy(URL,1,p-1)+Identifier
1458 +copy(URL,p+length('$(identifier)'),length(URL));
1459 until false;
1460
1461 // replace global macros
1462 if (IDEMacros<>nil) then
1463 IDEMacros.SubstituteMacros(URL);
1464
1465 DebugLn(['TExternalHelpDatabase.ShowHelp URL=',URL]);
1466
1467 // find HTML viewer
1468 Result:=FindViewer('text/html',ErrMsg,Viewer);
1469 if Result<>shrSuccess then exit;
1470
1471 // call viewer
1472 ShowNode:=nil;
1473 try
1474 ShowNode:=THelpNode.CreateURL(Self,NewNode.Title,URL);
1475 Result:=Viewer.ShowNode(ShowNode,ErrMsg);
1476 finally
1477 ShowNode.Free;
1478 end;
1479 exit;
1480 end;
1481 end;
1482 end;
1483 end;
1484
1485 // otherwise use default
1486 Result:=inherited ShowHelp(Query, BaseNode, NewNode, QueryItem, ErrMsg);
1487 end;
1488
1489 { TExternHelpFileSelector }
1490
1491 procedure TExternHelpFileSelector.ButtonPanel1OKButtonClick(Sender: TObject);
1492 begin
1493 ModalResult:=mrOk;
1494 end;
1495
1496 constructor TExternHelpFileSelector.Create(TheOwner: TComponent);
1497 begin
1498 inherited CreateNew(TheOwner);
1499
1500 FileListBox:=TListBox.Create(Self);
1501 with FileListBox do begin
1502 Name:='FileListBox';
1503 Align:=alClient;
1504 BorderSpacing.Around:=6;
1505 Parent:=Self;
1506 end;
1507
1508 ButtonPanel1:=TButtonPanel.Create(Self);
1509 with ButtonPanel1 do begin
1510 Name:='ButtonPanel1';
1511 Align:=alBottom;
1512 ShowBevel:=false;
1513 ShowButtons:=[pbOK,pbCancel];
1514 OKButton.OnClick:=@ButtonPanel1OKButtonClick;
1515 OKButton.ModalResult:=mrNone;
1516 Parent:=Self;
1517 end;
1518 end;
1519
1520 finalization
1521 FreeAndNil(ExternHelpOptions);
1522
1523 end.
1524
1525