The TGraphicsControl.Canvas is a clipping window to the parent
-canvas.
If you ask for the Canvas.Width or Canvas.Height, you are actually
+
+ The TGraphicsControl.Canvas is a clipping window to the parent
+canvas.
+ If you ask for the Canvas.Width or Canvas.Height, you are actually
getting the parent control's Canvas dimensions. To get the dimensions of the
TGraphicControl, you must query the ClientRect.
diff --git a/ide/lazdoc.pas b/ide/lazdoc.pas
index 86aa7fb346..8e8ff03ef9 100644
--- a/ide/lazdoc.pas
+++ b/ide/lazdoc.pas
@@ -31,21 +31,20 @@ unit LazDoc;
interface
uses
- Classes, SysUtils,
- LCLProc,
- CodeToolManager, CodeCache, FileProcs,
+ Classes, SysUtils, LCLProc, FileUtil,
+ CodeToolManager, CodeCache, FileProcs, AvgLvlTree,
Laz_DOM, Laz_XMLRead, Laz_XMLWrite,
- LazHelpIntf,
- EnvironmentOpts;
+ MacroIntf, PackageIntf, LazHelpIntf, ProjectIntf, LazIDEIntf,
+ IDEProcs, PackageDefs, EnvironmentOpts;
type
{ TLazFPDocFile }
TLazFPDocFile = class
public
- Doc: TXMLdocument;
Filename: string;
- ChangeStep: integer;
+ Doc: TXMLdocument;
+ ChangeStep: integer;// the CodeBuffer.ChangeStep value, when Doc was build
CodeBuffer: TCodeBuffer;
destructor Destroy; override;
end;
@@ -54,7 +53,7 @@ type
TLazDocManager = class
private
- FDocs: TFPList;// list of loaded TLazFPDocFile
+ FDocs: TAvgLvlTree;// tree of loaded TLazFPDocFile
public
constructor Create;
destructor Destroy; override;
@@ -64,12 +63,28 @@ type
out ADocFile: TLazFPDocFile): Boolean;
function GetFPDocFilenameForHelpContext(
Context: TPascalHelpContextList): string;
- function GetFPDocFilenameForSource(const SrcFilename: string): string;
+ function GetFPDocFilenameForSource(SrcFilename: string;
+ ResolveIncludeFiles: Boolean): string;
procedure FreeDocs;
end;
+
+function CompareLazFPDocFilenames(Data1, Data2: Pointer): integer;
+function CompareAnsistringWithLazFPDocFile(Key, Data: Pointer): integer;
+
implementation
+function CompareLazFPDocFilenames(Data1, Data2: Pointer): integer;
+begin
+ Result:=CompareFilenames(TLazFPDocFile(Data1).Filename,
+ TLazFPDocFile(Data2).Filename);
+end;
+
+function CompareAnsistringWithLazFPDocFile(Key, Data: Pointer): integer;
+begin
+ Result:=CompareFilenames(AnsiString(Key),TLazFPDocFile(Data).Filename);
+end;
+
{ TLazFPDocFile }
destructor TLazFPDocFile.Destroy;
@@ -80,7 +95,7 @@ end;
constructor TLazDocManager.Create;
begin
- FDocs:=TFPList.Create;
+ FDocs:=TAvgLvlTree.Create(@CompareLazFPDocFilenames);
end;
destructor TLazDocManager.Destroy;
@@ -92,13 +107,13 @@ end;
function TLazDocManager.FindFPDocFile(const Filename: string): TLazFPDocFile;
var
- i: Integer;
+ Node: TAvgLvlTreeNode;
begin
- for i:=0 to FDocs.Count-1 do begin
- Result:=TLazFPDocFile(FDocs[i]);
- if CompareFilenames(Result.Filename,Filename)=0 then exit;
- end;
- Result:=nil;
+ Node:=FDocs.FindKey(Pointer(Filename),@CompareAnsistringWithLazFPDocFile);
+ if Node<>nil then
+ Result:=TLazFPDocFile(Node.Data)
+ else
+ Result:=nil;
end;
function TLazDocManager.LoadFPDocFile(const Filename: string; UpdateFromDisk,
@@ -125,6 +140,8 @@ begin
// no update needed
exit(true);
end;
+
+ DebugLn(['TLazDocManager.LoadFPDocFile parsing ',ADocFile.Filename]);
// parse XML
ADocFile.ChangeStep:=ADocFile.CodeBuffer.ChangeStep;
@@ -152,37 +169,111 @@ begin
for i:=0 to Context.Count-1 do begin
if Context.Items[i].Descriptor<>pihcFilename then continue;
SrcFilename:=Context.Items[i].Context;
- Result:=GetFPDocFilenameForSource(SrcFilename);
+ Result:=GetFPDocFilenameForSource(SrcFilename,true);
exit;
end;
end;
-function TLazDocManager.GetFPDocFilenameForSource(const SrcFilename: string
- ): string;
+function TLazDocManager.GetFPDocFilenameForSource(SrcFilename: string;
+ ResolveIncludeFiles: Boolean): string;
var
SrcDir: String;
FPDocName: String;
-begin
- SrcDir:=ExtractFilePath(SrcFilename);
- FPDocName:=lowercase(ExtractFileNameOnly(SrcFilename))+'.xml';
- // check if SrcFilename is in one of the project directories
-
- // check if SrcFilename is in one of package directories
-
- // check if SrcFilename is one of the Lazarus sources
-
- // search in the default LazDoc paths
+ SearchPath: String;
+ procedure CheckIfInProject(AProject: TLazProject);
+ var
+ ProjectDirs: String;
+ begin
+ if AProject=nil then exit;
+ if (AProject.FindFile(SrcFilename,[pfsfOnlyProjectFiles])<>nil) then begin
+ SearchPath:=SearchPath+';'+AProject.LazDocPaths;
+ exit;
+ end;
+ // search in project directories
+ if not FilenameIsAbsolute(SrcFilename) then exit;
+ ProjectDirs:=AProject.LazCompilerOptions.OtherUnitFiles;
+ if FindPathInSearchPath(PChar(SrcDir),length(SrcDir),
+ PChar(ProjectDirs),length(ProjectDirs))<>nil
+ then
+ SearchPath:=SearchPath+';'+AProject.LazDocPaths;
+ end;
+
+ procedure CheckIfInAPackage;
+ var
+ PkgList: TList;
+ i: Integer;
+ Dirs: String;
+ APackage: TLazPackage;
+ begin
+ if not FilenameIsAbsolute(SrcFilename) then exit;
+ PkgList:=PackageEditingInterface.GetOwnersOfUnit(SrcFilename);
+ if PkgList=nil then exit;
+ try
+ for i:=0 to PkgList.Count-1 do begin
+ if TObject(PkgList[i]) is TLazPackage then begin
+ APackage:=TLazPackage(PkgList[i]);
+ Dirs:=APackage.CompilerOptions.OtherUnitFiles;
+ if FindPathInSearchPath(PChar(SrcDir),length(SrcDir),
+ PChar(Dirs),length(Dirs))<>nil
+ then begin
+ // TODO: add lazdoc paths to package
+ //SearchPath:=SearchPath+';'+APackage.LazDocPaths;
+ end;
+ end;
+ end;
+ finally
+ PkgList.Free;
+ end;
+ end;
+
+ procedure CheckIfInLazarus;
+ var
+ LazDir: String;
+ begin
+ if not FilenameIsAbsolute(SrcFilename) then exit;
+ LazDir:=AppendPathDelim(EnvironmentOptions.LazarusDirectory);
+ if FileIsInPath(SrcFilename,LazDir+'lcl') then begin
+ SearchPath:=SearchPath+';'+LazDir+SetDirSeparators('docs/xml/lcl');
+ end;
+ end;
+
+var
+ CodeBuf: TCodeBuffer;
+begin
Result:='';
+
+ if ResolveIncludeFiles then begin
+ CodeBuf:=CodeToolBoss.FindFile(SrcFilename);
+ if CodeBuf<>nil then begin
+ CodeBuf:=CodeToolBoss.GetMainCode(CodeBuf);
+ if CodeBuf<>nil then begin
+ SrcFilename:=CodeBuf.Filename;
+ end;
+ end;
+ end;
+
+ if not FilenameIsPascalSource(SrcFilename) then exit;
+
+ SrcDir:=ExtractFilePath(SrcFilename);
+
+ SearchPath:='';
+ CheckIfInProject(LazarusIDE.ActiveProject);
+ CheckIfInAPackage;
+ CheckIfInLazarus;
+ // finally add default paths
+ SearchPath:=SearchPath+';'+EnvironmentOptions.LazDocPaths;
+ // substitute macros
+ IDEMacros.SubstituteMacros(SearchPath);
+
+ FPDocName:=lowercase(ExtractFileNameOnly(SrcFilename))+'.xml';
+ DebugLn(['TLazDocManager.GetFPDocFilenameForSource Search ',FPDocName,' in "',SearchPath,'"']);
+ Result:=SearchFileInPath(FPDocName,'',SearchPath,';',ctsfcAllCase);
end;
procedure TLazDocManager.FreeDocs;
-var
- i: Integer;
begin
- for i:=FDocs.Count-1 downto 0 do
- TObject(FDocs[i]).Free;
- FDocs.Clear;
+ FDocs.FreeAndClear;
end;
end.
diff --git a/ide/lazdocfrm.lfm b/ide/lazdocfrm.lfm
index d39fd44a7f..7b8a05110a 100644
--- a/ide/lazdocfrm.lfm
+++ b/ide/lazdocfrm.lfm
@@ -151,7 +151,6 @@ object LazDocForm: TLazDocForm
end
object InheritedTabSheet: TTabSheet
Caption = 'InheritedTabSheet'
- TabVisible = False
object InheritedShortLabel: TLabel
Left = 5
Height = 13
@@ -172,9 +171,36 @@ object LazDocForm: TLazDocForm
Width = 732
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Top = 2
+ ReadOnly = True
TabOrder = 0
Text = 'InheritedShortEdit'
end
+ object MoveToInheritedButton: TButton
+ Height = 26
+ Top = 54
+ Width = 143
+ AutoSize = True
+ BorderSpacing.InnerBorder = 4
+ Caption = 'MoveToInheritedButton'
+ OnClick = MoveToInheritedButtonClick
+ TabOrder = 1
+ end
+ object CopyFromInheritedButton: TButton
+ AnchorSideLeft.Control = MoveToInheritedButton
+ AnchorSideLeft.Side = asrBottom
+ AnchorSideTop.Control = MoveToInheritedButton
+ AnchorSideTop.Side = asrCenter
+ Left = 153
+ Height = 26
+ Top = 54
+ Width = 155
+ AutoSize = True
+ BorderSpacing.Left = 10
+ BorderSpacing.InnerBorder = 4
+ Caption = 'CopyFromInheritedButton'
+ OnClick = CopyFromInheritedButtonClick
+ TabOrder = 2
+ end
end
end
object Panel1: TPanel
diff --git a/ide/lazdocfrm.lrs b/ide/lazdocfrm.lrs
index 36662261ee..9fc591c83c 100644
--- a/ide/lazdocfrm.lrs
+++ b/ide/lazdocfrm.lrs
@@ -47,128 +47,137 @@ LazarusResources.Add('TLazDocForm','FORMDATA',[
+#6'Height'#2#26#3'Top'#2#28#5'Width'#3#137#0#7'Anchors'#11#5'akTop'#7'akRigh'
+'t'#0#8'AutoSize'#9#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#19'Browse'
+'ExampleButton'#7'OnClick'#7#24'BrowseExampleButtonClick'#8'TabOrder'#2#1#0#0
- +#0#9'TTabSheet'#17'InheritedTabSheet'#7'Caption'#6#17'InheritedTabSheet'#10
- +'TabVisible'#8#0#6'TLabel'#19'InheritedShortLabel'#4'Left'#2#5#6'Height'#2#13
- +#3'Top'#2#4#5'Width'#2'm'#7'Caption'#6#19'InheritedShortLabel'#5'Color'#7#6
- +'clNone'#11'ParentColor'#8#0#0#5'TEdit'#18'InheritedShortEdit'#22'AnchorSide'
- +'Left.Control'#7#17'InheritedTabSheet'#21'AnchorSideTop.Control'#7#19'Inheri'
- +'tedShortLabel'#18'AnchorSideTop.Side'#7#9'asrBottom'#23'AnchorSideRight.Con'
- +'trol'#7#17'InheritedTabSheet'#20'AnchorSideRight.Side'#7#9'asrBottom'#6'Hei'
- +'ght'#2#23#3'Top'#2#19#5'Width'#3#220#2#7'Anchors'#11#5'akTop'#6'akLeft'#7'a'
- +'kRight'#0#17'BorderSpacing.Top'#2#2#8'TabOrder'#2#0#4'Text'#6#18'InheritedS'
- +'hortEdit'#0#0#0#0#6'TPanel'#6'Panel1'#6'Height'#2'u'#5'Width'#2#17#5'Align'
- +#7#6'alLeft'#10'BevelOuter'#7#6'bvNone'#11'FullRepaint'#8#14'ParentShowHint'
- +#8#8'ShowHint'#9#8'TabOrder'#2#1#0#12'TSpeedButton'#16'BoldFormatButton'#6'H'
- +'eight'#2#17#5'Width'#2#17#5'Align'#7#5'alTop'#5'Color'#7#9'clBtnFace'#10'Gl'
- +'yph.Data'#10#182#1#0#0#178#1#0#0'/* XPM */'#10'static char *graphic[] = {'
- +#10'"17 17 2 1",'#10'". c None",'#10'", c #000000",'#10'".................",'
- +#10'".................",'#10'".................",'#10'".................",'
- +#10'"....,,,,,,,,.....",'#10'".....,,,..,,,....",'#10'".....,,,..,,,....",'
- +#10'".....,,,..,,,....",'#10'".....,,,,,,,.....",'#10'".....,,,..,,,....",'
- ,#10'".....,,,..,,,....",'#10'".....,,,..,,,....",'#10'"....,,,,,,,,.....",'
- +#10'".................",'#10'".................",'#10'".................",'
- +#10'"................."}'#10#9'NumGlyphs'#2#0#7'OnClick'#7#17'FormatButtonCl'
- +'ick'#0#0#12'TSpeedButton'#18'ItalicFormatButton'#3'Tag'#2#1#6'Height'#2#17#3
- +'Top'#2#17#5'Width'#2#17#5'Align'#7#5'alTop'#5'Color'#7#9'clBtnFace'#10'Glyp'
- +'h.Data'#10#197#1#0#0#193#1#0#0'/* XPM */'#10'static char *graphic[] = {'#10
- +'"17 17 3 1",'#10'". c None",'#10'", c #000000",'#10'"- c #9696AF",'#10'"...'
- +'..............",'#10'".................",'#10'".................",'#10'"...'
- +'.....,,,,,....",'#10'".........,,-.....",'#10'"........-,,......",'#10'"...'
- +'.....,,-......",'#10'".......-,,.......",'#10'".......,,-.......",'#10'"...'
- +'...-,,........",'#10'"......,,-........",'#10'"....,,,,,,.......",'#10'"...'
+ +#0#9'TTabSheet'#17'InheritedTabSheet'#7'Caption'#6#17'InheritedTabSheet'#0#6
+ +'TLabel'#19'InheritedShortLabel'#4'Left'#2#5#6'Height'#2#13#3'Top'#2#4#5'Wid'
+ +'th'#2'm'#7'Caption'#6#19'InheritedShortLabel'#5'Color'#7#6'clNone'#11'Paren'
+ +'tColor'#8#0#0#5'TEdit'#18'InheritedShortEdit'#22'AnchorSideLeft.Control'#7
+ +#17'InheritedTabSheet'#21'AnchorSideTop.Control'#7#19'InheritedShortLabel'#18
+ +'AnchorSideTop.Side'#7#9'asrBottom'#23'AnchorSideRight.Control'#7#17'Inherit'
+ +'edTabSheet'#20'AnchorSideRight.Side'#7#9'asrBottom'#6'Height'#2#23#3'Top'#2
+ +#19#5'Width'#3#220#2#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#17'Border'
+ +'Spacing.Top'#2#2#8'ReadOnly'#9#8'TabOrder'#2#0#4'Text'#6#18'InheritedShortE'
+ +'dit'#0#0#7'TButton'#21'MoveToInheritedButton'#6'Height'#2#26#3'Top'#2'6'#5
+ +'Width'#3#143#0#8'AutoSize'#9#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6
+ +#21'MoveToInheritedButton'#7'OnClick'#7#26'MoveToInheritedButtonClick'#8'Tab'
+ +'Order'#2#1#0#0#7'TButton'#23'CopyFromInheritedButton'#22'AnchorSideLeft.Con'
+ +'trol'#7#21'MoveToInheritedButton'#19'AnchorSideLeft.Side'#7#9'asrBottom'#21
+ +'AnchorSideTop.Control'#7#21'MoveToInheritedButton'#18'AnchorSideTop.Side'#7
+ +#9'asrCenter'#4'Left'#3#153#0#6'Height'#2#26#3'Top'#2'6'#5'Width'#3#155#0#8
+ +'AutoSize'#9#18'BorderSpacing.Left'#2#10#25'BorderSpacing.InnerBorder'#2#4#7
+ +'Caption'#6#23'CopyFromInheritedButton'#7'OnClick'#7#28'CopyFromInheritedBut'
+ ,'tonClick'#8'TabOrder'#2#2#0#0#0#0#6'TPanel'#6'Panel1'#6'Height'#2'u'#5'Widt'
+ +'h'#2#17#5'Align'#7#6'alLeft'#10'BevelOuter'#7#6'bvNone'#11'FullRepaint'#8#14
+ +'ParentShowHint'#8#8'ShowHint'#9#8'TabOrder'#2#1#0#12'TSpeedButton'#16'BoldF'
+ +'ormatButton'#6'Height'#2#17#5'Width'#2#17#5'Align'#7#5'alTop'#5'Color'#7#9
+ +'clBtnFace'#10'Glyph.Data'#10#182#1#0#0#178#1#0#0'/* XPM */'#10'static char '
+ +'*graphic[] = {'#10'"17 17 2 1",'#10'". c None",'#10'", c #000000",'#10'"...'
+'..............",'#10'".................",'#10'".................",'#10'"...'
+ +'..............",'#10'"....,,,,,,,,.....",'#10'".....,,,..,,,....",'#10'"...'
+ +'..,,,..,,,....",'#10'".....,,,..,,,....",'#10'".....,,,,,,,.....",'#10'"...'
+ +'..,,,..,,,....",'#10'".....,,,..,,,....",'#10'".....,,,..,,,....",'#10'"...'
+ +'.,,,,,,,,.....",'#10'".................",'#10'".................",'#10'"...'
+'..............",'#10'"................."}'#10#9'NumGlyphs'#2#0#7'OnClick'#7
- +#17'FormatButtonClick'#0#0#12'TSpeedButton'#21'UnderlineFormatButton'#3'Tag'
- +#2#2#6'Height'#2#17#3'Top'#2'"'#5'Width'#2#17#5'Align'#7#5'alTop'#5'Color'#7
- +#9'clBtnFace'#10'Glyph.Data'#10#197#1#0#0#193#1#0#0'/* XPM */'#10'static cha'
- +'r *graphic[] = {'#10'"17 17 3 1",'#10'". c None",'#10'", c #000000",'#10'"-'
- +' c #848484",'#10'".................",'#10'".................",'#10'".......'
- +'..........",'#10'"....,,,,.,,,,....",'#10'".....,,...,,.....",'#10'".....,,'
- +'...,,.....",'#10'".....,,...,,.....",'#10'".....,,...,,.....",'#10'".....,,'
- +'...,,.....",'#10'".....,,...,,.....",'#10'".....,,-.-,,.....",'#10'"......,'
- +',,,,......",'#10'".................",'#10'"....,,,,,,,,,....",'#10'".......'
- +'..........",'#10'".................",'#10'"................."}'#10#9'NumGly'
- +'phs'#2#0#7'OnClick'#7#17'FormatButtonClick'#0#0#12'TSpeedButton'#19'InsertC'
- +'odeTagButton'#3'Tag'#2#3#6'Height'#2#17#3'Top'#2'3'#5'Width'#2#17#5'Align'#7
- +#5'alTop'#5'Color'#7#9'clBtnFace'#10'Glyph.Data'#10#253#9#0#0#249#9#0#0'/* X'
- +'PM */'#13#10'static char * InsertCodeTag_xpm[] = {'#13#10'"17 15 112 2",'#13
- +#10'" '#9'c None",'#13#10'". '#9'c #ECE9D8",'#13#10'"+ '#9'c #FFF0CF",'#13
- +#10'"@ '#9'c #FFEDC5",'#13#10'"# '#9'c #FBE8C5",'#13#10'"$ '#9'c #EDDAC5",'
- +#13#10'"% '#9'c #F4E8DB",'#13#10'"& '#9'c #FAEDD5",'#13#10'"* '#9'c #F3D49E"'
- +','#13#10'"= '#9'c #BF9855",'#13#10'"- '#9'c #C89D55",'#13#10'"; '#9'c #BC8E'
- +'5A",'#13#10'"> '#9'c #7C6135",'#13#10'", '#9'c #B18655",'#13#10'"'' '#9'c #'
- +'916940",'#13#10'") '#9'c #C3AC93",'#13#10'"! '#9'c #CCA76A",'#13#10'"~ '#9
- +'c #80684A",'#13#10'"{ '#9'c #DCAA63",'#13#10'"] '#9'c #A8834A",'#13#10'"^ '
- +#9'c #977443",'#13#10'"/ '#9'c #B99052",'#13#10'"( '#9'c #947047",'#13#10'"_'
- +' '#9'c #896842",'#13#10'": '#9'c #C4955E",'#13#10'"< '#9'c #87653F",'#13#10
- +'"[ '#9'c #A37A4E",'#13#10'"} '#9'c #F0E1CF",'#13#10'"| '#9'c #BD964F",'#13
- +#10'"1 '#9'c #977740",'#13#10'"2 '#9'c #7C6038",'#13#10'"3 '#9'c #9C7749",'
- +#13#10'"4 '#9'c #866340",'#13#10'"5 '#9'c #BA8D59",'#13#10'"6 '#9'c #634430"'
- +','#13#10'"7 '#9'c #8A6542",'#13#10'"8 '#9'c #C99761",'#13#10'"9 '#9'c #CC9B'
- +'62",'#13#10'"0 '#9'c #6C5842",'#13#10'"a '#9'c #82705A",'#13#10'"b '#9'c #A'
- +'47C4F",'#13#10'"c '#9'c #614A2F",'#13#10'"d '#9'c #906C45",'#13#10'"e '#9'c'
- +' #7C513C",'#13#10'"f '#9'c #AD7F54",'#13#10'"g '#9'c #B78858",'#13#10'"h '#9
- +'c #A4825B",'#13#10'"i '#9'c #8D7A65",'#13#10'"j '#9'c #927D67",'#13#10'"k '
- +#9'c #93705B",'#13#10'"l '#9'c #3F3636",'#13#10'"m '#9'c #D3D3D3",'#13#10'"n'
- +' '#9'c #CE9E60",'#13#10'"o '#9'c #755738",'#13#10'"p '#9'c #A77951",'#13#10
- +'"q '#9'c #CE9C63",'#13#10'"r '#9'c #3B271D",'#13#10'"s '#9'c #825F4B",'#13
- +#10'"t '#9'c #D6D5D3",'#13#10'"u '#9'c #EEEAE0",'#13#10'"v '#9'c #AB7A53",'
- +#13#10'"w '#9'c #745438",'#13#10'"x '#9'c #A77B50",'#13#10'"y '#9'c #948B83"'
- +','#13#10'"z '#9'c #261313",'#13#10'"A '#9'c #8B6843",'#13#10'"B '#9'c #6347'
- +'30",'#13#10'"C '#9'c #4B3924",'#13#10'"D '#9'c #B58757",'#13#10'"E '#9'c #8'
- +'16347",'#13#10'"F '#9'c #ECEAE0",'#13#10'"G '#9'c #735438",'#13#10'"H '#9'c'
- +' #A2774E",'#13#10'"I '#9'c #C0915C",'#13#10'"J '#9'c #A37B4E",'#13#10'"K '#9
- +'c #6D5134",'#13#10'"L '#9'c #7C593C",'#13#10'"M '#9'c #917C63",'#13#10'"N '
- +#9'c #99938C",'#13#10'"O '#9'c #B5B1AC",'#13#10'"P '#9'c #E8E8E8",'#13#10'"Q'
- +' '#9'c #866B4D",'#13#10'"R '#9'c #8C6D49",'#13#10'"S '#9'c #684F32",'#13#10
- +'"T '#9'c #1D130E",'#13#10'"U '#9'c #B58657",'#13#10'"V '#9'c #8E6C44",'#13
- +#10'"W '#9'c #A67E50",'#13#10'"X '#9'c #81623E",'#13#10'"Y '#9'c #6D5234",'
- +#13#10'"Z '#9'c #5F4D37",'#13#10'"` '#9'c #978E85",'#13#10'" .'#9'c #ECEAE2"'
- +','#13#10'"..'#9'c #CAC7C4",'#13#10'"+.'#9'c #8F7658",'#13#10'"@.'#9'c #4A31'
- +'24",'#13#10'"#.'#9'c #B98859",'#13#10'"$.'#9'c #885842",'#13#10'"%.'#9'c #4'
- +'63222",'#13#10'"&.'#9'c #CB9A62",'#13#10'"*.'#9'c #3D231E",'#13#10'"=.'#9'c'
- +' #39271C",'#13#10'"-.'#9'c #876E51",'#13#10'";.'#9'c #938778",'#13#10'">.'#9
- +'c #D7D5D3",'#13#10'",.'#9'c #DFDFDF",'#13#10'"''.'#9'c #9E9891",'#13#10'").'
- ,#9'c #908C87",'#13#10'"!.'#9'c #918A88",'#13#10'"~.'#9'c #8F8B87",'#13#10'"{'
- +'.'#9'c #989188",'#13#10'"].'#9'c #BEBAB5",'#13#10'". . . . . . . . . . . . '
- +'. . . . . ",'#13#10'". . . . . . . . . . . . . . . . . ",'#13#10'". . . . .'
- +' + @ # $ % . . . . . . . ",'#13#10'". . & * = - ; > , '' ) . . . . . . ",'
- +#13#10'"! ~ { ] ^ / ( _ : < [ } . . . . . ",'#13#10'"| 1 2 3 4 5 6 7 8 9 0 a'
- +' . . . . . ",'#13#10'"b c d e f g h i j k l m . . . . . ",'#13#10'"n o p q '
- +'r s t . . . u . . . . . . ",'#13#10'", q v w x y . . . . . . . . . . . ",'
- +#13#10'"z A B C D E F . . . . . . . . . . ",'#13#10'"G H I J K L M N N O P .'
- +' . . . . . ",'#13#10'"Q R S T U V W X X Y Z ` .. . . . ",'#13#10'". ..+.@.'
- +'#.$.%.9 q &.*.=.X -.;.>.. ",'#13#10'". . . ,.''.N ).N N N !.~.{.-.-.].. ",'
- +#13#10'". . . . . . . . . . . . . . . . . "};'#13#10#9'NumGlyphs'#2#0#7'OnCl'
- +'ick'#7#17'FormatButtonClick'#0#0#12'TSpeedButton'#18'InsertRemarkButton'#3
- +'Tag'#2#4#6'Height'#2#17#3'Top'#2'D'#5'Width'#2#17#5'Align'#7#5'alTop'#5'Col'
- +'or'#7#9'clBtnFace'#10'Glyph.Data'#10#218#1#0#0#214#1#0#0'/* XPM */'#13#10's'
- +'tatic char * InsertRemark_xpm[] = {'#13#10'"17 17 2 1",'#13#10'" '#9'c #ECE'
- +'9D8",'#13#10'".'#9'c #0000FF",'#13#10'" ",'#13#10'" '
- +' ",'#13#10'" ",'#13#10'" ... ... ",'#13#10
- +'" .. .. ",'#13#10'" .. .. ",'#13#10'" .. .. "'
- +','#13#10'" .. .. ",'#13#10'" ... ... ",'#13#10'" .. '
- +' .. ",'#13#10'" .. .. ",'#13#10'" .. .. ",'#13#10'"'
- +' .. .. ",'#13#10'" ... ... ",'#13#10'" ",'
- +#13#10'" ",'#13#10'" "};'#13#10#9'NumGlyphs'
- +#2#0#7'OnClick'#7#17'FormatButtonClick'#0#0#12'TSpeedButton'#18'InsertVarTag'
- +'Button'#3'Tag'#2#5#6'Height'#2#17#3'Top'#2'U'#5'Width'#2#17#5'Align'#7#5'al'
- +'Top'#5'Color'#7#9'clBtnFace'#10'Glyph.Data'#10#219#2#0#0#215#2#0#0'/* XPM *'
- +'/'#13#10'static char * InsertVarTag_xpm[] = {'#13#10'"17 17 18 1",'#13#10'"'
- +' '#9'c #ECE9D8",'#13#10'".'#9'c #D4D4D4",'#13#10'"+'#9'c #AAAAAA",'#13#10'"'
- +'@'#9'c #E6E6E6",'#13#10'"#'#9'c #000000",'#13#10'"$'#9'c #CCCCCC",'#13#10'"'
- +'%'#9'c #C4C4C4",'#13#10'"&'#9'c #888888",'#13#10'"*'#9'c #444444",'#13#10'"'
- +'='#9'c #999999",'#13#10'"-'#9'c #666666",'#13#10'";'#9'c #222222",'#13#10'"'
- +'>'#9'c #BBBBBB",'#13#10'",'#9'c #5E5E5E",'#13#10'"'''#9'c #808080",'#13#10
- +'")'#9'c #FFFFFF",'#13#10'"!'#9'c #777777",'#13#10'"~'#9'c #4C4C4C",'#13#10
- +'" ",'#13#10'" ",'#13#10'" "'
- +','#13#10'" ",'#13#10'" ",'#13#10'" '
- +' ",'#13#10'" .+++..++ .+++ ",'#13#10'" @#$#@%&*=@-;&> ",'#13#10'"'
- +' ,*, ;>,'')'''' ",'#13#10'" .;. -!~~>~~> ",'#13#10'" '
- +' ",'#13#10'" ",'#13#10'" ",'#13#10'" '
- +' ",'#13#10'" ",'#13#10'" ",'#13#10
- +'" "};'#13#10#9'NumGlyphs'#2#0#7'OnClick'#7#17'FormatButtonC'
- +'lick'#0#0#0#11'TOpenDialog'#10'OpenDialog'#5'Title'#6#17'Open example file'
- +#6'Filter'#6#28'pascal file|*.pas; *.pp; *.p'#11'FilterIndex'#2#0#4'left'#2
- +'@'#3'top'#2#24#0#0#0
+ +#17'FormatButtonClick'#0#0#12'TSpeedButton'#18'ItalicFormatButton'#3'Tag'#2#1
+ +#6'Height'#2#17#3'Top'#2#17#5'Width'#2#17#5'Align'#7#5'alTop'#5'Color'#7#9'c'
+ +'lBtnFace'#10'Glyph.Data'#10#197#1#0#0#193#1#0#0'/* XPM */'#10'static char *'
+ +'graphic[] = {'#10'"17 17 3 1",'#10'". c None",'#10'", c #000000",'#10'"- c '
+ +'#9696AF",'#10'".................",'#10'".................",'#10'"..........'
+ +'.......",'#10'"........,,,,,....",'#10'".........,,-.....",'#10'"........-,'
+ +',......",'#10'"........,,-......",'#10'".......-,,.......",'#10'".......,,-'
+ +'.......",'#10'"......-,,........",'#10'"......,,-........",'#10'"....,,,,,,'
+ +'.......",'#10'".................",'#10'".................",'#10'"..........'
+ +'.......",'#10'".................",'#10'"................."}'#10#9'NumGlyphs'
+ +#2#0#7'OnClick'#7#17'FormatButtonClick'#0#0#12'TSpeedButton'#21'UnderlineFor'
+ +'matButton'#3'Tag'#2#2#6'Height'#2#17#3'Top'#2'"'#5'Width'#2#17#5'Align'#7#5
+ +'alTop'#5'Color'#7#9'clBtnFace'#10'Glyph.Data'#10#197#1#0#0#193#1#0#0'/* XPM'
+ +' */'#10'static char *graphic[] = {'#10'"17 17 3 1",'#10'". c None",'#10'", '
+ +'c #000000",'#10'"- c #848484",'#10'".................",'#10'"..............'
+ +'...",'#10'".................",'#10'"....,,,,.,,,,....",'#10'".....,,...,,..'
+ +'...",'#10'".....,,...,,.....",'#10'".....,,...,,.....",'#10'".....,,...,,..'
+ +'...",'#10'".....,,...,,.....",'#10'".....,,...,,.....",'#10'".....,,-.-,,..'
+ +'...",'#10'"......,,,,,......",'#10'".................",'#10'"....,,,,,,,,,.'
+ +'...",'#10'".................",'#10'".................",'#10'"..............'
+ +'..."}'#10#9'NumGlyphs'#2#0#7'OnClick'#7#17'FormatButtonClick'#0#0#12'TSpeed'
+ +'Button'#19'InsertCodeTagButton'#3'Tag'#2#3#6'Height'#2#17#3'Top'#2'3'#5'Wid'
+ +'th'#2#17#5'Align'#7#5'alTop'#5'Color'#7#9'clBtnFace'#10'Glyph.Data'#10#253#9
+ +#0#0#249#9#0#0'/* XPM */'#13#10'static char * InsertCodeTag_xpm[] = {'#13#10
+ +'"17 15 112 2",'#13#10'" '#9'c None",'#13#10'". '#9'c #ECE9D8",'#13#10'"+ '
+ +#9'c #FFF0CF",'#13#10'"@ '#9'c #FFEDC5",'#13#10'"# '#9'c #FBE8C5",'#13#10'"$'
+ +' '#9'c #EDDAC5",'#13#10'"% '#9'c #F4E8DB",'#13#10'"& '#9'c #FAEDD5",'#13#10
+ +'"* '#9'c #F3D49E",'#13#10'"= '#9'c #BF9855",'#13#10'"- '#9'c #C89D55",'#13
+ +#10'"; '#9'c #BC8E5A",'#13#10'"> '#9'c #7C6135",'#13#10'", '#9'c #B18655",'
+ +#13#10'"'' '#9'c #916940",'#13#10'") '#9'c #C3AC93",'#13#10'"! '#9'c #CCA76A'
+ +'",'#13#10'"~ '#9'c #80684A",'#13#10'"{ '#9'c #DCAA63",'#13#10'"] '#9'c #A88'
+ +'34A",'#13#10'"^ '#9'c #977443",'#13#10'"/ '#9'c #B99052",'#13#10'"( '#9'c #'
+ +'947047",'#13#10'"_ '#9'c #896842",'#13#10'": '#9'c #C4955E",'#13#10'"< '#9
+ +'c #87653F",'#13#10'"[ '#9'c #A37A4E",'#13#10'"} '#9'c #F0E1CF",'#13#10'"| '
+ +#9'c #BD964F",'#13#10'"1 '#9'c #977740",'#13#10'"2 '#9'c #7C6038",'#13#10'"3'
+ +' '#9'c #9C7749",'#13#10'"4 '#9'c #866340",'#13#10'"5 '#9'c #BA8D59",'#13#10
+ +'"6 '#9'c #634430",'#13#10'"7 '#9'c #8A6542",'#13#10'"8 '#9'c #C99761",'#13
+ +#10'"9 '#9'c #CC9B62",'#13#10'"0 '#9'c #6C5842",'#13#10'"a '#9'c #82705A",'
+ +#13#10'"b '#9'c #A47C4F",'#13#10'"c '#9'c #614A2F",'#13#10'"d '#9'c #906C45"'
+ +','#13#10'"e '#9'c #7C513C",'#13#10'"f '#9'c #AD7F54",'#13#10'"g '#9'c #B788'
+ +'58",'#13#10'"h '#9'c #A4825B",'#13#10'"i '#9'c #8D7A65",'#13#10'"j '#9'c #9'
+ +'27D67",'#13#10'"k '#9'c #93705B",'#13#10'"l '#9'c #3F3636",'#13#10'"m '#9'c'
+ +' #D3D3D3",'#13#10'"n '#9'c #CE9E60",'#13#10'"o '#9'c #755738",'#13#10'"p '#9
+ +'c #A77951",'#13#10'"q '#9'c #CE9C63",'#13#10'"r '#9'c #3B271D",'#13#10'"s '
+ +#9'c #825F4B",'#13#10'"t '#9'c #D6D5D3",'#13#10'"u '#9'c #EEEAE0",'#13#10'"v'
+ +' '#9'c #AB7A53",'#13#10'"w '#9'c #745438",'#13#10'"x '#9'c #A77B50",'#13#10
+ +'"y '#9'c #948B83",'#13#10'"z '#9'c #261313",'#13#10'"A '#9'c #8B6843",'#13
+ +#10'"B '#9'c #634730",'#13#10'"C '#9'c #4B3924",'#13#10'"D '#9'c #B58757",'
+ +#13#10'"E '#9'c #816347",'#13#10'"F '#9'c #ECEAE0",'#13#10'"G '#9'c #735438"'
+ +','#13#10'"H '#9'c #A2774E",'#13#10'"I '#9'c #C0915C",'#13#10'"J '#9'c #A37B'
+ +'4E",'#13#10'"K '#9'c #6D5134",'#13#10'"L '#9'c #7C593C",'#13#10'"M '#9'c #9'
+ +'17C63",'#13#10'"N '#9'c #99938C",'#13#10'"O '#9'c #B5B1AC",'#13#10'"P '#9'c'
+ ,' #E8E8E8",'#13#10'"Q '#9'c #866B4D",'#13#10'"R '#9'c #8C6D49",'#13#10'"S '#9
+ +'c #684F32",'#13#10'"T '#9'c #1D130E",'#13#10'"U '#9'c #B58657",'#13#10'"V '
+ +#9'c #8E6C44",'#13#10'"W '#9'c #A67E50",'#13#10'"X '#9'c #81623E",'#13#10'"Y'
+ +' '#9'c #6D5234",'#13#10'"Z '#9'c #5F4D37",'#13#10'"` '#9'c #978E85",'#13#10
+ +'" .'#9'c #ECEAE2",'#13#10'"..'#9'c #CAC7C4",'#13#10'"+.'#9'c #8F7658",'#13
+ +#10'"@.'#9'c #4A3124",'#13#10'"#.'#9'c #B98859",'#13#10'"$.'#9'c #885842",'
+ +#13#10'"%.'#9'c #463222",'#13#10'"&.'#9'c #CB9A62",'#13#10'"*.'#9'c #3D231E"'
+ +','#13#10'"=.'#9'c #39271C",'#13#10'"-.'#9'c #876E51",'#13#10'";.'#9'c #9387'
+ +'78",'#13#10'">.'#9'c #D7D5D3",'#13#10'",.'#9'c #DFDFDF",'#13#10'"''.'#9'c #'
+ +'9E9891",'#13#10'").'#9'c #908C87",'#13#10'"!.'#9'c #918A88",'#13#10'"~.'#9
+ +'c #8F8B87",'#13#10'"{.'#9'c #989188",'#13#10'"].'#9'c #BEBAB5",'#13#10'". .'
+ +' . . . . . . . . . . . . . . . ",'#13#10'". . . . . . . . . . . . . . . . .'
+ +' ",'#13#10'". . . . . + @ # $ % . . . . . . . ",'#13#10'". . & * = - ; > , '
+ +''' ) . . . . . . ",'#13#10'"! ~ { ] ^ / ( _ : < [ } . . . . . ",'#13#10'"| '
+ +'1 2 3 4 5 6 7 8 9 0 a . . . . . ",'#13#10'"b c d e f g h i j k l m . . . . '
+ +'. ",'#13#10'"n o p q r s t . . . u . . . . . . ",'#13#10'", q v w x y . . .'
+ +' . . . . . . . . ",'#13#10'"z A B C D E F . . . . . . . . . . ",'#13#10'"G '
+ +'H I J K L M N N O P . . . . . . ",'#13#10'"Q R S T U V W X X Y Z ` .. . . '
+ +'. ",'#13#10'". ..+.@.#.$.%.9 q &.*.=.X -.;.>.. ",'#13#10'". . . ,.''.N ).N '
+ +'N N !.~.{.-.-.].. ",'#13#10'". . . . . . . . . . . . . . . . . "};'#13#10#9
+ +'NumGlyphs'#2#0#7'OnClick'#7#17'FormatButtonClick'#0#0#12'TSpeedButton'#18'I'
+ +'nsertRemarkButton'#3'Tag'#2#4#6'Height'#2#17#3'Top'#2'D'#5'Width'#2#17#5'Al'
+ +'ign'#7#5'alTop'#5'Color'#7#9'clBtnFace'#10'Glyph.Data'#10#218#1#0#0#214#1#0
+ +#0'/* XPM */'#13#10'static char * InsertRemark_xpm[] = {'#13#10'"17 17 2 1",'
+ +#13#10'" '#9'c #ECE9D8",'#13#10'".'#9'c #0000FF",'#13#10'" "'
+ +','#13#10'" ",'#13#10'" ",'#13#10'" ... '
+ +' ... ",'#13#10'" .. .. ",'#13#10'" .. .. ",'#13#10'"'
+ +' .. .. ",'#13#10'" .. .. ",'#13#10'" ... ... ",'
+ +#13#10'" .. .. ",'#13#10'" .. .. ",'#13#10'" .. '
+ +'.. ",'#13#10'" .. .. ",'#13#10'" ... ... ",'#13#10'" '
+ +' ",'#13#10'" ",'#13#10'" "};'
+ +#13#10#9'NumGlyphs'#2#0#7'OnClick'#7#17'FormatButtonClick'#0#0#12'TSpeedButt'
+ +'on'#18'InsertVarTagButton'#3'Tag'#2#5#6'Height'#2#17#3'Top'#2'U'#5'Width'#2
+ +#17#5'Align'#7#5'alTop'#5'Color'#7#9'clBtnFace'#10'Glyph.Data'#10#219#2#0#0
+ +#215#2#0#0'/* XPM */'#13#10'static char * InsertVarTag_xpm[] = {'#13#10'"17 '
+ +'17 18 1",'#13#10'" '#9'c #ECE9D8",'#13#10'".'#9'c #D4D4D4",'#13#10'"+'#9'c '
+ +'#AAAAAA",'#13#10'"@'#9'c #E6E6E6",'#13#10'"#'#9'c #000000",'#13#10'"$'#9'c '
+ +'#CCCCCC",'#13#10'"%'#9'c #C4C4C4",'#13#10'"&'#9'c #888888",'#13#10'"*'#9'c '
+ +'#444444",'#13#10'"='#9'c #999999",'#13#10'"-'#9'c #666666",'#13#10'";'#9'c '
+ +'#222222",'#13#10'">'#9'c #BBBBBB",'#13#10'",'#9'c #5E5E5E",'#13#10'"'''#9'c'
+ +' #808080",'#13#10'")'#9'c #FFFFFF",'#13#10'"!'#9'c #777777",'#13#10'"~'#9'c'
+ +' #4C4C4C",'#13#10'" ",'#13#10'" ",'#13#10'"'
+ +' ",'#13#10'" ",'#13#10'" ",'
+ +#13#10'" ",'#13#10'" .+++..++ .+++ ",'#13#10'" @#$#@%&*=@-'
+ +';&> ",'#13#10'" ,*, ;>,'')'''' ",'#13#10'" .;. -!~~>~~> ",'#13#10'"'
+ +' ",'#13#10'" ",'#13#10'" ",'
+ +#13#10'" ",'#13#10'" ",'#13#10'" '
+ +' ",'#13#10'" "};'#13#10#9'NumGlyphs'#2#0#7'OnClick'#7#17
+ +'FormatButtonClick'#0#0#0#11'TOpenDialog'#10'OpenDialog'#5'Title'#6#17'Open '
+ +'example file'#6'Filter'#6#28'pascal file|*.pas; *.pp; *.p'#11'FilterIndex'#2
+ +#0#4'left'#2'@'#3'top'#2#24#0#0#0
]);
diff --git a/ide/lazdocfrm.pas b/ide/lazdocfrm.pas
index 1a1293fdcb..d5bf8fb105 100644
--- a/ide/lazdocfrm.pas
+++ b/ide/lazdocfrm.pas
@@ -23,9 +23,8 @@
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
***************************************************************************
-}
-{
+
see for todo list: http://wiki.lazarus.freepascal.org/index.php/LazDoc
}
@@ -42,27 +41,55 @@ uses
LCLProc, LResources, StdCtrls, Buttons, ComCtrls, Controls, Dialogs,
ExtCtrls, Forms, Graphics,
SynEdit,
- CodeToolManager, CodeCache,
+ CodeAtom, CodeCache, CodeToolManager,
Laz_DOM, Laz_XMLRead, Laz_XMLWrite,
IDEHelpIntf, LazHelpIntf,
- IDEProcs, LazarusIDEStrConsts, LazDoc;
-
-const
- SHORT = 1;
- DESCR = 2;
- ERRORS = 4;
- SEEALSO = 5;
- EXAMPLE = 6;
- NODEITEMS = EXAMPLE; //always make nodeitems equal to higest element
+ IDEProcs, LazarusIDEStrConsts, LazDocSelectInherited, LazDoc;
type
- TFPDocNode = array [1..NODEITEMS] of String;
+ TFPDocItem = (
+ fpdiShort,
+ fpdiDescription,
+ fpdiErrors,
+ fpdiSeeAlso,
+ fpdiExample
+ );
+
+ TFPDocNode = array [TFPDocItem] of String;
+ TLazDocFormFlag = (
+ ldffCaptionNeedsUpdate,
+ ldffInheritedNeedsUpdate,
+ ldffInheritedEntriesNeedUpdate
+ );
+ TLazDocFormFlags = set of TLazDocFormFlag;
+
+ { TLazDocInheritedEntry }
+
+ TLazDocInheritedEntry = class
+ public
+ SrcFilename: string;
+ Caret: TPoint;
+ DocFilename: string;
+ DocFilenameValid: Boolean;
+ DocFile: TLazFPDocFile;
+ DocFileValid: Boolean;
+ PascalContext: TPascalHelpContextList;
+ PascalContextValid: Boolean;
+ DOMNodeValid: Boolean;
+ DOMNode: TDOMNode;
+ ValuesValid: Boolean;
+ Values: TFPDocNode;
+ destructor Destroy; override;
+ end;
+
{ TLazDocForm }
TLazDocForm = class(TForm)
AddLinkButton: TButton;
BrowseExampleButton: TButton;
+ CopyFromInheritedButton: TButton;
+ MoveToInheritedButton: TButton;
InheritedShortEdit: TEdit;
ExampleEdit: TEdit;
InheritedShortLabel: TLabel;
@@ -90,6 +117,7 @@ type
SeeAlsoTabSheet: TTabSheet;
procedure AddLinkButtonClick(Sender: TObject);
procedure BrowseExampleButtonClick(Sender: TObject);
+ procedure CopyFromInheritedButtonClick(Sender: TObject);
procedure DeleteLinkButtonClick(Sender: TObject);
procedure DocumentationTagChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
@@ -98,37 +126,56 @@ type
procedure FormatButtonClick(Sender: TObject);
procedure LinkChange(Sender: TObject);
procedure LinkListBoxClick(Sender: TObject);
+ procedure ApplicationIdle(Sender: TObject);
+ procedure MoveToInheritedButtonClick(Sender: TObject);
private
+ FCaretXY: TPoint;
FChanged: Boolean;
- FCurrentElement: TPascalHelpContextList;
- FDoc: TXMLdocument;
- FDocFileName: String;
FLazDocBoss: TLazDocManager;
- FLinkIndex: Integer;
- function ElementFromNode(Node: TDOMNode): TFPDocNode;
+ FFlags: TLazDocFormFlags;
+ fUpdateLock: Integer;
+ fEntry: TLazDocInheritedEntry;
+ fInheritedEntries: TFPList; // list of TLazDocInheritedEntry. Entry 0 is current.
+ function GetValuesFromNode(Node: TDOMNode): TFPDocNode;
+ function GetDoc: TXMLdocument;
+ function GetDocFile: TLazFPDocFile;
function GetFirstChildValue(n: TDOMNode): String;
- function GetFirstElement: TDOMNode;
- function GetModuleNode: TDOMNode;
- function GetNearestSourceElement(const SrcFilename: string;
+ function GetFirstElement(ADoc: TXMLdocument): TDOMNode;
+ function GetModuleNode(ADoc: TXMLdocument): TDOMNode;
+ function GetSourceContext(const SrcFilename: string;
const CaretPos: TPoint): TPascalHelpContextList;
+ function GetSourceFilename: string;
function MakeLink: String;
- function NodeByPascalContext(const AContext: TPascalHelpContextList): TDOMNode;
- function GetElementName(const AContext: TPascalHelpContextList): string;
- procedure GetElementList;
- procedure InsertElement(const ElementName: String);
+ function NodeByPascalContext(ADoc: TXMLdocument;
+ const AContext: TPascalHelpContextList): TDOMNode;
+ function GetContextTitle(const AContext: TPascalHelpContextList): string;
+ procedure UpdateLinkIdComboBox;
procedure Save;
- procedure SetDocFileName(const Value: String);
+ function WriteNode(Entry: TLazDocInheritedEntry; DocNode: TFPDocNode;
+ Interactive: Boolean): Boolean;
procedure UpdateCaption;
+ procedure UpdateValueControls;
+ procedure UpdateInheritedControls;
+ procedure UpdateInherited;
+ procedure UpdateInheritedEntries(All: Boolean);
+ procedure ClearInherited(UpdateControls: Boolean);
+ function FindInheritedEntry: TLazDocInheritedEntry;
+ procedure MoveToInherited(DestEntry: TLazDocInheritedEntry);
public
procedure Reset;
procedure UpdateLazDoc(const SrcFilename: string; const Caret: TPoint);
- property DocFileName: String read FDocFileName write SetDocFileName;
- property Doc: TXMLdocument read FDoc;
+ procedure BeginUpdate;
+ procedure EndUpdate;
+ procedure ClearEntry(DoSave: Boolean);
+ property DocFile: TLazFPDocFile read GetDocFile;
+ property Doc: TXMLdocument read GetDoc;
property LazDocBoss: TLazDocManager read FLazDocBoss;
+ property SourceFilename: string read GetSourceFilename;
+ property CaretXY: TPoint read FCaretXY;
end;
var
- LazDocForm: TLazDocForm;
+ LazDocForm: TLazDocForm = nil;
procedure DoShowLazDoc;
@@ -144,22 +191,22 @@ begin
LazDocForm.Show;
end;
-function TLazDocForm.GetModuleNode: TDOMNode;
+function TLazDocForm.GetModuleNode(ADoc: TXMLdocument): TDOMNode;
var
n: TDOMNode;
begin
Result:=nil;
- if doc=nil then exit;
+ if ADoc=nil then exit;
- //get first node
- n := doc.FindNode('fpdoc-descriptions');
+ // get first node
+ n := ADoc.FindNode('fpdoc-descriptions');
if n=nil then exit;
- //proceed to package (could there be more packages in one file??)
+ // proceed to package (could there be more packages in one file??)
n := n.FirstChild;
if n=nil then exit;
- //proceed to module (could there be more modules in one file??)
+ // proceed to module (could there be more modules in one file??)
n := n.FirstChild;
while (n<>nil) and (n.NodeName <> 'module') do
n := n.NextSibling;
@@ -167,12 +214,12 @@ begin
Result := n;
end;
-function TLazDocForm.GetFirstElement: TDOMNode;
+function TLazDocForm.GetFirstElement(ADoc: TXMLdocument): TDOMNode;
var
Node: TDOMNode;
begin
//get first module node
- Node := GetModuleNode;
+ Node := GetModuleNode(ADoc);
//proceed to element
Node := Node.FirstChild;
@@ -182,7 +229,7 @@ begin
Result := Node;
end;
-procedure TLazDocForm.GetElementList;
+procedure TLazDocForm.UpdateLinkIdComboBox;
// fills LinkIdComboBox.Items
var
n: TDOMNode;
@@ -199,7 +246,7 @@ begin
end;
//get first element node
- n := GetFirstElement;
+ n := GetFirstElement(Doc);
//search all elements
while Assigned(n) do
@@ -217,40 +264,13 @@ begin
end;
end;
-procedure TLazDocForm.SetDocFileName(const Value: String);
-begin
- LinkIdComboBox.Clear;
-
- if (Value <> FDocFileName) then begin
- // reset Self
- Reset;
-
- FDocFileName := Value;
-
- if Assigned(doc) then
- FreeAndNil(doc);
-
- if FileExistsCached(Value) then begin
- ReadXMLFile(doc, FDocFileName);
- end;
-
- UpdateCaption;
-
- GetElementList;
-
- {$ifdef dbgLazDoc}
- DebugLn('TLazDocForm.SetDocFileName: document is set: ' + Value);
- {$endif}
- end;
-end;
-
procedure TLazDocForm.FormCreate(Sender: TObject);
begin
FLazDocBoss:=TLazDocManager.Create;
+ fEntry:=TLazDocInheritedEntry.Create;
+
Caption := lisLazDocMainFormCaption;
- FLinkIndex := -1;
-
with PageControl do
begin
Page[0].Caption := lisLazDocShortTag;
@@ -273,14 +293,19 @@ begin
DeleteLinkButton.Caption := lisLazDocDeleteLinkButton;
BrowseExampleButton.Caption := lisLazDocBrowseExampleButton;
-
+
+ MoveToInheritedButton.Caption:='Move entries to inherited';
+
Reset;
+
+ Application.AddOnIdleHandler(@ApplicationIdle);
end;
procedure TLazDocForm.FormDestroy(Sender: TObject);
begin
- FreeAndNil(fDoc);
- FreeAndNil(FCurrentElement);
+ ClearInherited(false);
+ Application.RemoveAllHandlersOfObject(Self);
+ FreeAndNil(fEntry);
FreeAndNil(FLazDocBoss);
end;
@@ -324,10 +349,10 @@ end;
procedure TLazDocForm.LinkChange(Sender: TObject);
begin
- if FLinkIndex = -1 then
+ if LinkListBox.ItemIndex<0 then
Exit;
- LinkListBox.Items.Strings[FLinkIndex] := MakeLink;
+ LinkListBox.Items.Strings[LinkListBox.ItemIndex] := MakeLink;
end;
procedure TLazDocForm.LinkListBoxClick(Sender: TObject);
@@ -335,22 +360,22 @@ var
strTmp: String;
intTmp: Integer;
intStart: Integer;
+ LinkIndex: LongInt;
begin
//split the link into Id and Text
- FLinkIndex := LinkListBox.ItemIndex;
-
- if FLinkIndex = -1 then
+ LinkIndex := LinkListBox.ItemIndex;
+ if LinkIndex = -1 then
Exit;
- intStart := PosEx('"', LinkListBox.Items[FLinkIndex], 1);
+ intStart := PosEx('"', LinkListBox.Items[LinkIndex], 1);
- intTmp := PosEx('"', LinkListBox.Items[FLinkIndex], intStart + 1);
+ intTmp := PosEx('"', LinkListBox.Items[LinkIndex], intStart + 1);
- LinkIdComboBox.Text := Copy(LinkListBox.Items[FLinkIndex],
+ LinkIdComboBox.Text := Copy(LinkListBox.Items[LinkIndex],
intStart + 1, intTmp - intStart - 1);
- strTmp := Copy(LinkListBox.Items[FLinkIndex], intTmp + 2,
- Length(LinkListBox.Items[FLinkIndex]));
+ strTmp := Copy(LinkListBox.Items[LinkIndex], intTmp + 2,
+ Length(LinkListBox.Items[LinkIndex]));
if strTmp = '>' then
LinkTextEdit.Text := ''
@@ -358,66 +383,89 @@ begin
LinkTextEdit.Text := Copy(strTmp, 1, Length(strTmp) - Length(''));
end;
-procedure TLazDocForm.InsertElement(const ElementName: String);
-var
- n: TDOMNode;
- child: TDOMNode;
+procedure TLazDocForm.ApplicationIdle(Sender: TObject);
begin
- if doc=nil then exit;
-
- // UNUSED. Do we still need this?
- Exit;
-
- // preparations being made for adding nodes
- // having to finalize adding comment
-
- // get first module node
- n := GetModuleNode;
- if n=nil then exit;
-
- // TODO: insert element comment (important or not!!)
- child := doc.CreateComment('test');
- n.AppendChild(child);
-
- child := doc.CreateElement('element');
- TDOMElement(child).SetAttribute('name', ElementName);
- child.AppendChild(doc.CreateElement('short'));
- child.AppendChild(doc.CreateElement('descr'));
- child.AppendChild(doc.CreateElement('errors'));
- child.AppendChild(doc.CreateElement('seealso'));
- child.AppendChild(doc.CreateElement('example'));
- n.AppendChild(child);
+ if ldffInheritedNeedsUpdate in FFlags then
+ UpdateInherited
+ else if ldffInheritedEntriesNeedUpdate in FFlags then
+ UpdateInheritedEntries(false);
+end;
+procedure TLazDocForm.MoveToInheritedButtonClick(Sender: TObject);
+var
+ i: Integer;
+ Entry: TLazDocInheritedEntry;
+ Candidates: TFPList;
+ LazDocSelectInheritedDlg: TLazDocSelectInheritedDlg;
+begin
+ if fInheritedEntries=nil then exit;
+ Candidates:=nil;
+ LazDocSelectInheritedDlg:=nil;
try
- WriteXMLFile(doc, FDocFileName);
- except
- on E: Exception do begin
- MessageDlg('Write error',
- 'unable to write file '+FDocFileName+#13
- +E.Message,
- mtError,[mbCancel],0);
+ // find all entries till the first inherited entry with a description
+ for i:=1 to fInheritedEntries.Count-1 do begin
+ Entry:=TLazDocInheritedEntry(fInheritedEntries[i]);
+ if Entry.ValuesValid then begin
+ if Candidates=nil then
+ Candidates:=TFPList.Create;
+ Candidates.Add(Entry);
+ if Entry.Values[fpdiShort]<>'' then break;
+ end;
end;
+
+ // choose one entry
+ if (Candidates=nil) or (Candidates.Count=0) then exit;
+ if Candidates.Count=1 then begin
+ // there is only one candidate
+ Entry:=TLazDocInheritedEntry(Candidates[0]);
+ if Entry.Values[fpdiShort]<>'' then begin
+ // the inherited entry already contains a description.
+ // ask if it should be really replacement
+ if QuestionDlg('Confirm replace',
+ GetContextTitle(Entry.PascalContext)+' already contains the help:'+#13
+ +Entry.Values[fpdiShort],
+ mtConfirmation,[mrYes,'Replace',mrCancel],0)<>mrYes then exit;
+ end;
+ end else begin
+ // there is more than one candidate
+ // => ask which one to replace
+ LazDocSelectInheritedDlg:=TLazDocSelectInheritedDlg.Create(nil);
+ LazDocSelectInheritedDlg.InheritedComboBox.Items.Clear;
+ for i:=0 to Candidates.Count-1 do begin
+ Entry:=TLazDocInheritedEntry(Candidates[i]);
+ LazDocSelectInheritedDlg.InheritedComboBox.Items.Add(
+ GetContextTitle(Entry.PascalContext));
+ end;
+ if LazDocSelectInheritedDlg.ShowModal<>mrOk then exit;
+ i:=LazDocSelectInheritedDlg.InheritedComboBox.ItemIndex;
+ if i<0 then exit;
+ Entry:=TLazDocInheritedEntry(Candidates[i]);
+ end;
+
+ // move the content of the current entry to the inherited entry
+ MoveToInherited(Entry);
+ finally
+ LazDocSelectInheritedDlg.Free;
+ Candidates.Free;
end;
end;
-function TLazDocForm.NodeByPascalContext(
+function TLazDocForm.NodeByPascalContext(ADoc: TXMLdocument;
const AContext: TPascalHelpContextList): TDOMNode;
var
Node: TDOMNode;
ElementName: String;
begin
Result := Nil;
-
- if not Assigned(doc) then Exit;
+ if not Assigned(ADoc) then Exit;
// get first element node
- ElementName:=GetElementName(AContext);
-
+ ElementName:=GetContextTitle(AContext);
if ElementName='' then exit;
//DebugLn('TLazDocForm.NodeByPascalContext ElementName="',ElementName,'"');
// search elements for ElementName
- Node:=GetFirstElement;
+ Node:=GetFirstElement(ADoc);
while Node<>nil do begin
if (Node is TDomElement)
and (CompareText(TDomElement(Node).GetAttribute('name'),ElementName)=0) then
@@ -440,14 +488,15 @@ begin
Result := Node;
end;
-function TLazDocForm.GetElementName(const AContext: TPascalHelpContextList
+function TLazDocForm.GetContextTitle(const AContext: TPascalHelpContextList
): string;
-// get codetools path. for example: TButton.Align
+// get codetools path. for fpdiExample: TButton.Align
var
Level: Integer;
begin
- Level:=0;
Result:='';
+ if AContext=nil then exit;
+ Level:=0;
while (Levelnil then
+ Result:=DocFile.Doc
+ else
+ Result:=nil;
+end;
+
+function TLazDocForm.GetDocFile: TLazFPDocFile;
+begin
+ Result:=fEntry.DocFile;
+end;
+
+function TLazDocForm.GetSourceContext(const SrcFilename: string;
const CaretPos: TPoint): TPascalHelpContextList;
begin
Result:=LazarusHelp.ConvertSourcePosToPascalHelpContext(CaretPos,SrcFilename);
-
//if Result<>nil then
// DebugLn('TLazDocForm.GetNearestSourceElement Result=',Result.AsString);
end;
+function TLazDocForm.GetSourceFilename: string;
+begin
+ Result:=fEntry.SrcFilename;
+end;
+
procedure TLazDocForm.UpdateCaption;
var
strCaption: String;
begin
+ if fUpdateLock>0 then begin
+ Include(FFlags,ldffCaptionNeedsUpdate);
+ exit;
+ end;
+ Exclude(FFlags,ldffCaptionNeedsUpdate);
+
strCaption := lisLazDocMainFormCaption + ' - ';
- if FCurrentElement <> nil then
- strCaption := strCaption + GetElementName(FCurrentElement) + ' - '
+ if fEntry.PascalContext <> nil then
+ strCaption := strCaption + GetContextTitle(fEntry.PascalContext) + ' - '
else
strCaption := strCaption + lisLazDocNoTagCaption + ' - ';
- if FDocFileName <> '' then
- Caption := strCaption + FDocFileName
+ if DocFile<>nil then
+ Caption := strCaption + DocFile.Filename
else
Caption := strCaption + lisLazDocNoTagCaption;
+ DebugLn(['TLazDocForm.UpdateCaption ',Caption]);
+end;
+
+procedure TLazDocForm.UpdateValueControls;
+var
+ EnabledState: Boolean;
+begin
+ EnabledState := fEntry.DOMNode<>nil;
+
+ if Assigned(fEntry.DOMNode) then
+ begin
+ ShortEdit.Text := fEntry.Values[fpdiShort];
+ DescrMemo.Lines.Text := ConvertLineEndings(fEntry.Values[fpdiDescription]);
+ ErrorsMemo.Lines.Text := ConvertLineEndings(fEntry.Values[fpdiErrors]);
+ LinkListBox.Items.Text := ConvertLineEndings(fEntry.Values[fpdiSeeAlso]);
+ LinkIdComboBox.Text := '';
+ LinkTextEdit.Clear;
+ ExampleEdit.Text := ConvertLineEndings(fEntry.Values[fpdiExample]);
+ end
+ else
+ begin
+ ShortEdit.Text := lisLazDocNoDocumentation;
+ DescrMemo.Lines.Text := lisLazDocNoDocumentation;
+ ErrorsMemo.Lines.Text := lisLazDocNoDocumentation;
+ LinkIdComboBox.Text := lisLazDocNoDocumentation;
+ LinkTextEdit.Text := lisLazDocNoDocumentation;
+ LinkListBox.Clear;
+ ExampleEdit.Text := lisLazDocNoDocumentation;
+ end;
+
+ ShortEdit.Enabled := EnabledState;
+ DescrMemo.Enabled := EnabledState;
+ ErrorsMemo.Enabled := EnabledState;
+ LinkIdComboBox.Enabled := EnabledState;
+ LinkTextEdit.Enabled := EnabledState;
+ LinkListBox.Enabled := EnabledState;
+ AddLinkButton.Enabled := EnabledState;
+ DeleteLinkButton.Enabled := EnabledState;
+ ExampleEdit.Enabled := EnabledState;
+ BrowseExampleButton.Enabled := EnabledState;
+end;
+
+procedure TLazDocForm.UpdateInheritedControls;
+var
+ Entry: TLazDocInheritedEntry;
+begin
+ Entry:=FindInheritedEntry;
+ DebugLn(['TLazDocForm.UpdateInheritedControls ',dbgsName(Entry)]);
+ if Entry=nil then begin
+ InheritedShortEdit.Text:='';
+ InheritedShortEdit.Enabled:=false;
+ InheritedShortLabel.Caption:='no inherited description found';
+ end else begin
+ InheritedShortEdit.Text:=Entry.Values[fpdiShort];
+ InheritedShortEdit.Enabled:=true;
+ InheritedShortLabel.Caption:='Short description of '
+ +GetContextTitle(Entry.PascalContext);
+ end;
+ MoveToInheritedButton.Enabled:=(fInheritedEntries<>nil)
+ and (fInheritedEntries.Count>1);
+end;
+
+procedure TLazDocForm.UpdateInherited;
+var
+ ListOfPCodeXYPosition: TFPList;
+ CurCodePos: PCodeXYPosition;
+ i: Integer;
+ CodeBuffer: TCodeBuffer;
+ NewInherited: TLazDocInheritedEntry;
+begin
+ if fUpdateLock>0 then begin
+ Include(FFlags,ldffInheritedNeedsUpdate);
+ exit;
+ end;
+ Exclude(FFlags,ldffInheritedNeedsUpdate);
+
+ ClearInherited(true);
+ DebugLn(['TLazDocForm.UpdateInherited ']);
+ if DocFile=nil then exit;
+ if DocFile.CodeBuffer=nil then exit;
+ CodeBuffer:=CodeToolBoss.LoadFile(SourceFilename,true,false);
+ if CodeBuffer=nil then exit;
+
+ ListOfPCodeXYPosition:=nil;
+ try
+ // get all possible declarations of this identifier
+ if not CodeToolBoss.FindDeclarationAndOverload(CodeBuffer,
+ CaretXY.X,CaretXY.Y,ListOfPCodeXYPosition,[])
+ then
+ exit;
+ debugln('TLazDocForm.UpdateInherited Success Overloads=',dbgs(ListOfPCodeXYPosition.Count));
+ // convert the source positions in pascal help context list
+ if ListOfPCodeXYPosition=nil then exit;
+ for i:=0 to ListOfPCodeXYPosition.Count-1 do begin
+ CurCodePos:=PCodeXYPosition(ListOfPCodeXYPosition[i]);
+ debugln('TLazDocForm.UpdateInherited C ',CurCodePos^.Code.Filename,' X=',dbgs(CurCodePos^.X),' Y=',dbgs(CurCodePos^.Y));
+ if fInheritedEntries=nil then
+ fInheritedEntries:=TFPList.Create;
+ NewInherited:=TLazDocInheritedEntry.Create;
+ NewInherited.SrcFilename:=CurCodePos^.Code.Filename;
+ NewInherited.Caret.X:=CurCodePos^.X;
+ NewInherited.Caret.Y:=CurCodePos^.Y;
+ fInheritedEntries.Add(NewInherited);
+ end;
+ finally
+ FreeListOfPCodeXYPosition(ListOfPCodeXYPosition);
+ end;
+ Include(FFlags,ldffInheritedEntriesNeedUpdate);
+end;
+
+procedure TLazDocForm.UpdateInheritedEntries(All: Boolean);
+var
+ i: Integer;
+ Entry: TLazDocInheritedEntry;
+ CurInheritedEntry: TLazDocInheritedEntry;
+begin
+ if fUpdateLock>0 then begin
+ Include(FFlags,ldffInheritedEntriesNeedUpdate);
+ exit;
+ end;
+
+ CurInheritedEntry:=FindInheritedEntry;
+ if (CurInheritedEntry=nil) and (fInheritedEntries<>nil) then begin
+ for i:=0 to fInheritedEntries.Count-1 do begin
+ Entry:=TLazDocInheritedEntry(fInheritedEntries[i]);
+ //DebugLn(['TLazDocForm.UpdateInheritedEntries ',Entry.SrcFilename,' ',dbgs(Entry.Caret)]);
+ // find fpdoc file
+ if not Entry.DocFilenameValid then begin
+ Entry.DocFilenameValid:=true;
+ Entry.DocFilename:=
+ LazDocBoss.GetFPDocFilenameForSource(Entry.SrcFilename,true);
+ //DebugLn(['TLazDocForm.UpdateInheritedEntries Source=',Entry.SrcFilename,' -> FPDoc=',Entry.DocFilename]);
+ if not All then exit;
+ end;
+ // read fpdoc file
+ if not Entry.DocFileValid then begin
+ Entry.DocFileValid:=true;
+ //DebugLn(['TLazDocForm.UpdateInheritedEntries Parsing ',Entry.DocFilename,' ...']);
+ if (Entry.DocFilename<>'') then begin
+ if not LazDocBoss.LoadFPDocFile(Entry.DocFilename,true,false,
+ Entry.DocFile)
+ then
+ Entry.DocFile:=nil;
+ if not All then exit;
+ end;
+ end;
+ // get codetools path
+ if not Entry.PascalContextValid then begin
+ Entry.PascalContextValid:=true;
+ Entry.PascalContext:=LazarusHelp.ConvertSourcePosToPascalHelpContext(
+ Entry.Caret,Entry.SrcFilename);
+ //DebugLn(['TLazDocForm.UpdateInheritedEntries Pascal=',Entry.PascalContext.AsString]);
+ if not All then exit;
+ end;
+ // get fpdoc values
+ if (not Entry.ValuesValid)
+ and Entry.PascalContextValid and (Entry.PascalContext<>nil)
+ and Entry.DocFileValid and (Entry.DocFile<>nil)
+ and (Entry.DocFile.Doc<>nil) then begin
+ //DebugLn(['TLazDocForm.UpdateInheritedEntries get fpdoc values ',Entry.PascalContext.AsString]);
+ Entry.DOMNode := NodeByPascalContext(Entry.DocFile.Doc,Entry.PascalContext);
+ Entry.DOMNodeValid:=true;
+ Entry.ValuesValid:=true;
+ if Entry.DOMNode<>nil then begin
+ Entry.Values := GetValuesFromNode(Entry.DOMNode);
+ if CurInheritedEntry=nil then begin
+ CurInheritedEntry:=FindInheritedEntry;
+ if CurInheritedEntry<>nil then
+ UpdateInheritedControls;
+ end;
+ end;
+ if not All then exit;
+ end;
+ end;
+ end;
+ Exclude(FFlags,ldffInheritedEntriesNeedUpdate);
+end;
+
+procedure TLazDocForm.ClearInherited(UpdateControls: Boolean);
+var
+ i: Integer;
+begin
+ //DebugLn(['TLazDocForm.ClearInherited UpdateControls=',UpdateControls]);
+ if fInheritedEntries<>nil then begin
+ for i:=0 to fInheritedEntries.Count-1 do
+ TObject(fInheritedEntries[i]).Free;
+ FreeAndNil(fInheritedEntries);
+ end;
+ if UpdateControls then
+ UpdateInheritedControls;
+end;
+
+function TLazDocForm.FindInheritedEntry: TLazDocInheritedEntry;
+var
+ i: Integer;
+begin
+ if fInheritedEntries=nil then
+ exit(nil);
+ for i:=1 to fInheritedEntries.Count-1 do begin
+ Result:=TLazDocInheritedEntry(fInheritedEntries[i]);
+ if Result.ValuesValid and (Result.Values[fpdiShort]<>'') then
+ exit;
+ end;
+ Result:=nil;
+end;
+
+procedure TLazDocForm.MoveToInherited(DestEntry: TLazDocInheritedEntry);
+begin
+ DebugLn(['TLazDocForm.MoveToInherited ',DestEntry.PascalContext.AsString]);
+ if not fEntry.ValuesValid then begin
+ DebugLn(['TLazDocForm.MoveToInherited not fEntry.NodeValid']);
+ exit;
+ end;
+ if DestEntry.PascalContext=nil then begin
+ DebugLn(['TLazDocForm.MoveToInherited DestEntry.PascalContext=nil']);
+ exit;
+ end;
+ if fEntry.PascalContext.IsEqual(DestEntry.PascalContext) then begin
+ DebugLn(['TLazDocForm.MoveToInherited fEntry=DestEntry']);
+ exit;
+ end;
+ DebugLn(['TLazDocForm.MoveToInherited Writing to inherited node ...']);
+ if WriteNode(DestEntry,fEntry.Values,true) then begin
+ DebugLn(['TLazDocForm.MoveToInherited clearing current node ...']);
+ ClearEntry(true);
+ UpdateInherited;
+ end;
end;
procedure TLazDocForm.Reset;
begin
- FreeAndNil(Doc);
- FreeAndNil(FCurrentElement);
- FDocFileName := '';
- UpdateCaption;
+ ClearInherited(true);
+ FreeAndNil(FEntry.PascalContext);
+ FEntry.DocFile:=nil;
+ FEntry.DocFileValid:=false;
+ FEntry.DOMNode:=nil;
+ FEntry.DOMNodeValid:=false;
+ FEntry.ValuesValid:=false;
// clear all element editors/viewers
ShortEdit.Clear;
@@ -567,79 +869,134 @@ end;
procedure TLazDocForm.UpdateLazDoc(const SrcFilename: string;
const Caret: TPoint);
var
- dn: TFPDocNode;
- n: TDOMNode;
- EnabledState: Boolean;
NewElement: TPascalHelpContextList;
+ DocFilename: String;
+ DocFileChanged: Boolean;
begin
- if not Assigned(doc) then
- begin
- {$ifdef dbgLazDoc}
- DebugLn('TLazDocForm.UpdateLazDoc: document is not set');
- {$endif}
-
- Exit;
- end;
-
// save the current changes to documentation
Save;
-
- // check if visible
- if not Visible then exit;
-
- // fetch source context
- NewElement:=GetNearestSourceElement(SrcFilename, Caret);
- // avoid circles and overhead
- if (NewElement<>nil) and (FCurrentElement<>nil)
- and (NewElement.IsEqual(FCurrentElement)) then begin
- NewElement.Free;
- exit;
+ BeginUpdate;
+ try
+ // check if visible
+ if not Visible then exit;
+
+ if (SrcFilename=SourceFilename) and (CompareCaret(Caret,CaretXY)=0) then
+ exit;
+ FCaretXY:=Caret;
+ DocFileChanged:=false;
+
+ if SrcFilename<>SourceFilename then begin
+ fEntry.SrcFilename:=SrcFilename;
+
+ // search the fpdoc xml file for this unit
+ // Note: if this is an include file, find the unit
+ DocFilename:=LazDocBoss.GetFPDocFilenameForSource(SrcFilename,true);
+ if (DocFile=nil) or (CompareFilenames(DocFile.Filename,DocFilename)<>0)
+ then begin
+ // DocFile changed
+ DebugLn(['TLazDocForm.UpdateLazDoc DocFilename=',DocFilename]);
+ DocFileChanged:=true;
+ Reset;
+ if DocFilename<>'' then begin
+ try
+ //DebugLn(['TLazDocForm.UpdateLazDoc DocFilename=',DocFilename]);
+ if LazDocBoss.LoadFPDocFile(DocFilename,true,false,
+ fEntry.DocFile)
+ then begin
+ fEntry.DocFileValid:=true;
+ end else begin
+ DebugLn(['TLazDocForm.UpdateLazDoc FAILED DocFilename=',DocFilename]);
+ fEntry.DocFile:=nil;
+ end;
+ except
+ on E: Exception do begin
+ fEntry.DocFile:=nil;
+ MessageDlg('Error in LazDoc',
+ 'File: '+DocFilename+#13
+ +'Error: '+E.Message,
+ mtError,[mbCancel],0);
+ end;
+ end;
+ end;
+ end;
+
+ UpdateCaption;
+ UpdateLinkIdComboBox;
+ end;
+
+ if not Assigned(Doc) then
+ begin
+ { $ifdef dbgLazDoc}
+ DebugLn('TLazDocForm.UpdateLazDoc: document is not set');
+ { $endif}
+
+ Exit;
+ end;
+
+ // fetch source context
+ NewElement:=GetSourceContext(SrcFilename, Caret);
+ DebugLn(['TLazDocForm.UpdateLazDoc ',NewElement]);
+
+ // avoid circles and overhead
+ if (not DocFileChanged) then begin
+ if ((NewElement<>nil) and (fEntry.PascalContext<>nil)
+ and (NewElement.IsEqual(fEntry.PascalContext)))
+ or ((NewElement=nil) and (fEntry.PascalContext=nil)) then begin
+ DebugLn(['TLazDocForm.UpdateLazDoc Same entry']);
+ NewElement.Free;
+ exit;
+ end;
+ end;
+
+ FreeAndNil(fEntry.PascalContext);
+ fEntry.PascalContext := NewElement;
+ fEntry.PascalContextValid:=true;
+
+ fEntry.DOMNode:=NodeByPascalContext(Doc,fEntry.PascalContext);
+ fEntry.DOMNodeValid:=true;
+
+ if Assigned(fEntry.DOMNode) then
+ begin
+ fEntry.Values := GetValuesFromNode(fEntry.DOMNode);
+ fEntry.ValuesValid:=true;
+ end else
+ fEntry.ValuesValid:=false;
+
+ UpdateCaption;
+
+ UpdateValueControls;
+ FChanged := False;
+
+ ClearInherited(true);
+ Include(FFlags,ldffInheritedNeedsUpdate);
+ finally
+ EndUpdate;
end;
+end;
- FreeAndNil(FCurrentElement);
- FCurrentElement := NewElement;
-
- UpdateCaption;
+procedure TLazDocForm.BeginUpdate;
+begin
+ inc(fUpdateLock);
+end;
- n := NodeByPascalContext(FCurrentElement);
-
- EnabledState := Assigned(n);
-
- if Assigned(n) then
- begin
- dn := ElementFromNode(n);
-
- ShortEdit.Text := dn[SHORT];
- DescrMemo.Lines.Text := ConvertLineEndings(dn[DESCR]);
- ErrorsMemo.Lines.Text := ConvertLineEndings(dn[ERRORS]);
- LinkListBox.Items.Text := ConvertLineEndings(dn[SEEALSO]);
- LinkIdComboBox.Text := '';
- LinkTextEdit.Clear;
- ExampleEdit.Text := ConvertLineEndings(dn[EXAMPLE]);
- end
- else
- begin
- ShortEdit.Text := lisLazDocNoDocumentation;
- DescrMemo.Lines.Text := lisLazDocNoDocumentation;
- ErrorsMemo.Lines.Text := lisLazDocNoDocumentation;
- LinkIdComboBox.Text := lisLazDocNoDocumentation;
- LinkTextEdit.Text := lisLazDocNoDocumentation;
- LinkListBox.Clear;
- ExampleEdit.Text := lisLazDocNoDocumentation;
+procedure TLazDocForm.EndUpdate;
+begin
+ dec(fUpdateLock);
+ if fUpdateLock<0 then RaiseGDBException('');
+ if fUpdateLock=0 then begin
+ if ldffCaptionNeedsUpdate in FFlags then UpdateCaption;
end;
+end;
- FChanged := False;
-
- ShortEdit.Enabled := EnabledState;
- DescrMemo.Enabled := EnabledState;
- ErrorsMemo.Enabled := EnabledState;
- LinkIdComboBox.Enabled := EnabledState;
- LinkTextEdit.Enabled := EnabledState;
- LinkListBox.Enabled := EnabledState;
- AddLinkButton.Enabled := EnabledState;
- DeleteLinkButton.Enabled := EnabledState;
- ExampleEdit.Enabled := EnabledState;
- BrowseExampleButton.Enabled := EnabledState;
+procedure TLazDocForm.ClearEntry(DoSave: Boolean);
+begin
+ FChanged:=true;
+ ShortEdit.Text:='';
+ DescrMemo.Text:='';
+ ErrorsMemo.Text:='';
+ LinkListBox.Items.Clear;
+ ExampleEdit.Text:='';
+ if DoSave then Save;
end;
function ToUnixLineEnding(const s: String): String;
@@ -667,13 +1024,47 @@ end;
procedure TLazDocForm.Save;
var
- Node: TDOMNode;
- S: String;
- NodeWritten: array [1..NODEITEMS] of Boolean;
- i: Integer;
+ DocNode: TFPDocNode;
+begin
+ // nothing changed => exit
+ if not FChanged then Exit;
+ if Doc=nil then exit;
+
+ DocNode[fpdiShort]:=ShortEdit.Text;
+ DocNode[fpdiDescription]:=DescrMemo.Text;
+ DocNode[fpdiErrors]:=ErrorsMemo.Text;
+ DocNode[fpdiSeeAlso]:=LinkListBox.Items.Text;
+ DocNode[fpdiExample]:=ExampleEdit.Text;
+ if not WriteNode(fEntry,DocNode,true) then begin
+ DebugLn(['TLazDocForm.Save FAILED']);
+ end else begin
+ FChanged := False;
+ end;
+end;
- procedure CheckAndWriteNode(NodeName: String; NodeText: String;
- NodeIndex: Integer);
+function TLazDocForm.WriteNode(Entry: TLazDocInheritedEntry;
+ DocNode: TFPDocNode; Interactive: Boolean): Boolean;
+var
+ Node: TDOMNode;
+ CurNodeName: String;
+ NodeWritten: array [TFPDocItem] of Boolean;
+ i: TFPDocItem;
+ TopNode: TDOMNode;
+
+ function Check(Test: boolean; const Msg: string): Boolean;
+ begin
+ Result:=Test;
+ if not Test then exit;
+ DebugLn(['TLazDocForm.WriteNode ERROR ',Msg]);
+ if Interactive then begin;
+ MessageDlg('Write error',
+ 'Error writing "'+Entry.DocFilename+'"'#13
+ +Msg,mtError,[mbCancel],0);
+ end;
+ end;
+
+ procedure CheckAndWriteNode(const NodeName: String; NodeText: String;
+ NodeIndex: TFPDocItem);
var
child: TDOMNode;
begin
@@ -682,11 +1073,11 @@ var
NodeName);
{$endif}
- if S = NodeName then
+ if CurNodeName = NodeName then
begin
if not Assigned(Node.FirstChild) then
begin
- child := doc.CreateTextNode(ToUnixLineEnding(NodeText));
+ child := Entry.DocFile.Doc.CreateTextNode(ToUnixLineEnding(NodeText));
Node.AppendChild(child);
end
else
@@ -695,7 +1086,12 @@ var
end;
end;
- procedure CheckAndWriteExampleNode(NodeText: String);
+ procedure CheckAndWriteNode(const NodeName: String; NodeType: TFPDocItem);
+ begin
+ CheckAndWriteNode(NodeName,DocNode[NodeType],NodeType);
+ end;
+
+ procedure CheckAndWriteExampleNode(const NodeText: String);
var
FileAttribute: TDOMAttr;
begin
@@ -703,16 +1099,16 @@ var
DebugLn('TLazDocForm.Save[CheckAndWriteExampleNode]');
{$endif}
- if S = 'example' then
+ if CurNodeName = 'example' then
begin
- FileAttribute := doc.CreateAttribute('file');
+ FileAttribute := Entry.DocFile.Doc.CreateAttribute('file');
FileAttribute.Value := NodeText;
- node.Attributes.SetNamedItem(FileAttribute);
- NodeWritten[EXAMPLE] := True;
+ Node.Attributes.SetNamedItem(FileAttribute);
+ NodeWritten[fpdiExample] := True;
end;
end;
- procedure InsertNodeElement(ElementName: String; ElementText: String);
+ procedure InsertNodeElement(const ElementName, ElementText: String);
var
child: TDOMNode;
FileAttribute: TDOMAttr;
@@ -722,77 +1118,83 @@ var
ElementName);
{$endif}
- child := doc.CreateElement(ElementName);
+ child := Entry.DocFile.doc.CreateElement(ElementName);
if ElementName='example' then begin
- FileAttribute := doc.CreateAttribute('file');
+ FileAttribute := Entry.DocFile.Doc.CreateAttribute('file');
FileAttribute.Value := ElementText;
child.Attributes.SetNamedItem(FileAttribute);
end
else
- child.AppendChild(doc.CreateTextNode(ToUnixLineEnding(ElementText)));
- Node.AppendChild(child);
+ child.AppendChild(Entry.DocFile.Doc.CreateTextNode(
+ ToUnixLineEnding(ElementText)));
+ TopNode.AppendChild(child);
end;
begin
- // nothing changed, so exit
- if not FChanged then Exit;
- if Doc=nil then exit;
+ Result:=false;
+ if Check(Entry=nil,'Entry=nil') then exit;
+ if Check(Entry.DocFile=nil,'Entry.DocFile=nil') then exit;
+ if Check(Entry.DocFile.Doc=nil,'Entry.DocFile.Doc=nil') then exit;
+ if Check(Entry.PascalContext=nil,'Entry.PascalContext=nil') then exit;
+ if Check(not Entry.DOMNodeValid,'not Entry.DOMNodeValid') then exit;
- Node := NodeByPascalContext(FCurrentElement);
-
- if not Assigned(Node) then
+ if Entry.DOMNode=nil then begin
+ // no old node found
+ // TODO: create a new node
+ Check(false,'no old node found. TODO: implement creating a new.');
Exit;
+ end;
+
+ TopNode := Entry.DOMNode;
// reset all nodes
- for i := 1 to NODEITEMS do
+ for i := Low(TFPDocItem) to High(TFPDocItem) do
NodeWritten[i] := False;
// write all known nodes to XML
- Node := Node.FirstChild;
+ Node := TopNode.FirstChild;
while Assigned(Node) do
begin
if (Node.NodeType = ELEMENT_NODE) then
begin
- S := Node.NodeName;
-
- CheckAndWriteNode('short', ShortEdit.Text, SHORT);
- CheckAndWriteNode('descr', DescrMemo.Text, DESCR);
- CheckAndWriteNode('errors', ErrorsMemo.Text, ERRORS);
- CheckAndWriteNode('seealso', LinkListBox.Caption, SEEALSO);
- CheckAndWriteExampleNode(ExampleEdit.Text);
+ CurNodeName := Node.NodeName;
+ CheckAndWriteNode('short', fpdiShort);
+ CheckAndWriteNode('descr', fpdiDescription);
+ CheckAndWriteNode('errors', fpdiErrors);
+ CheckAndWriteNode('seealso', fpdiSeeAlso);
+ CheckAndWriteExampleNode(DocNode[fpdiExample]);
end;
Node := Node.NextSibling;
end;
// add new nodes to XML if not already updated
- Node := NodeByPascalContext(FCurrentElement);
- for i := 1 to NODEITEMS do
+ for i := Low(TFPDocItem) to High(TFPDocItem) do
if NodeWritten[i] = False then
case i of
- SHORT:
- InsertNodeElement('short', ShortEdit.Text);
- DESCR:
- InsertNodeElement('descr', DescrMemo.Text);
- ERRORS:
- InsertNodeElement('errors', ErrorsMemo.Text);
- SEEALSO:
- InsertNodeElement('seealso', LinkListBox.Caption);
- EXAMPLE:
- InsertNodeElement('example', ExampleEdit.Text);
+ fpdiShort:
+ InsertNodeElement('short', DocNode[fpdiShort]);
+ fpdiDescription:
+ InsertNodeElement('descr', DocNode[fpdiDescription]);
+ fpdiErrors:
+ InsertNodeElement('errors', DocNode[fpdiErrors]);
+ fpdiSeeAlso:
+ InsertNodeElement('seealso', DocNode[fpdiSeeAlso]);
+ fpdiExample:
+ InsertNodeElement('example', DocNode[fpdiExample]);
end;
+ // write fpdoc xml file
try
- WriteXMLFile(doc, FDocFileName);
+ WriteXMLFile(Doc, DocFile.Filename);
+ Result:=true;
except
on E: Exception do begin
MessageDlg('Write error',
- 'unable to write file '+FDocFileName+#13
+ 'unable to write file '+DocFile.Filename+#13
+E.Message,
mtError,[mbCancel],0);
end;
end;
-
- FChanged := False;
end;
procedure TLazDocForm.DocumentationTagChange(Sender: TObject);
@@ -811,35 +1213,58 @@ end;
procedure TLazDocForm.AddLinkButtonClick(Sender: TObject);
begin
- FLinkIndex := -1;
-
if Trim(LinkIdComboBox.Text) <> '' then
begin
LinkListBox.Items.Add(MakeLink);
-
FChanged := True;
end;
end;
procedure TLazDocForm.BrowseExampleButtonClick(Sender: TObject);
begin
+ if Doc=nil then exit;
if OpenDialog.Execute then
ExampleEdit.Text := SetDirSeparators(ExtractRelativepath(
- ExtractFilePath(FDocFileName), OpenDialog.FileName));
+ ExtractFilePath(DocFile.Filename), OpenDialog.FileName));
+end;
+
+procedure TLazDocForm.CopyFromInheritedButtonClick(Sender: TObject);
+var
+ InhEntry: TLazDocInheritedEntry;
+begin
+ InhEntry:=FindInheritedEntry;
+ if InhEntry=nil then exit;
+ if (not InhEntry.ValuesValid) then exit;
+ if InhEntry.Values[fpdiShort]='' then exit;
+ if ShortEdit.Text<>'' then begin
+ if QuestionDlg('Confirm replace',
+ GetContextTitle(fEntry.PascalContext)+' already contains the help:'+#13
+ +ShortEdit.Text,
+ mtConfirmation,[mrYes,'Replace',mrCancel],0)<>mrYes then exit;
+ end;
+ fEntry.Values:=InhEntry.Values;
+ fEntry.ValuesValid:=true;
+
+ UpdateValueControls;
+ FChanged:=true;
end;
procedure TLazDocForm.DeleteLinkButtonClick(Sender: TObject);
begin
- if FLinkIndex >= 0 then
- begin
- LinkListBox.Items.Delete(FLinkIndex);
-
- FLinkIndex := -1;
-
+ if LinkListBox.ItemIndex >= 0 then begin
+ LinkListBox.Items.Delete(LinkListBox.ItemIndex);
FChanged := True;
end;
end;
+{ TLazDocInheritedEntry }
+
+destructor TLazDocInheritedEntry.Destroy;
+begin
+ FreeAndNil(PascalContext);
+ inherited Destroy;
+end;
+
initialization
{$I lazdocfrm.lrs}
diff --git a/ide/lazdocselectinherited.lfm b/ide/lazdocselectinherited.lfm
new file mode 100644
index 0000000000..e73a9c2f55
--- /dev/null
+++ b/ide/lazdocselectinherited.lfm
@@ -0,0 +1,43 @@
+object LazDocSelectInheritedDlg: TLazDocSelectInheritedDlg
+ Left = 294
+ Height = 75
+ Top = 164
+ Width = 330
+ HorzScrollBar.Page = 329
+ VertScrollBar.Page = 74
+ Caption = 'LazDocSelectInheritedDlg'
+ OnCreate = FormCreate
+ object InheritedComboBox: TComboBox
+ Left = 8
+ Height = 25
+ Top = 8
+ Width = 312
+ Anchors = [akTop, akLeft, akRight]
+ AutoCompleteText = [cbactEndOfLineComplete, cbactSearchAscending]
+ MaxLength = 0
+ TabOrder = 0
+ Text = 'InheritedComboBox'
+ end
+ object OkButton: TButton
+ Left = 24
+ Height = 25
+ Top = 40
+ Width = 75
+ BorderSpacing.InnerBorder = 4
+ Caption = 'OkButton'
+ Default = True
+ ModalResult = 1
+ TabOrder = 1
+ end
+ object CancelButton: TButton
+ Left = 136
+ Height = 25
+ Top = 40
+ Width = 75
+ BorderSpacing.InnerBorder = 4
+ Cancel = True
+ Caption = 'CancelButton'
+ ModalResult = 2
+ TabOrder = 2
+ end
+end
diff --git a/ide/lazdocselectinherited.lrs b/ide/lazdocselectinherited.lrs
new file mode 100644
index 0000000000..076499d1db
--- /dev/null
+++ b/ide/lazdocselectinherited.lrs
@@ -0,0 +1,17 @@
+{ This is an automatically generated lazarus resource file }
+
+LazarusResources.Add('TLazDocSelectInheritedDlg','FORMDATA',[
+ 'TPF0'#25'TLazDocSelectInheritedDlg'#24'LazDocSelectInheritedDlg'#4'Left'#3'&'
+ +#1#6'Height'#2'K'#3'Top'#3#164#0#5'Width'#3'J'#1#18'HorzScrollBar.Page'#3'I'
+ +#1#18'VertScrollBar.Page'#2'J'#7'Caption'#6#24'LazDocSelectInheritedDlg'#8'O'
+ +'nCreate'#7#10'FormCreate'#0#9'TComboBox'#17'InheritedComboBox'#4'Left'#2#8#6
+ +'Height'#2#25#3'Top'#2#8#5'Width'#3'8'#1#7'Anchors'#11#5'akTop'#6'akLeft'#7
+ +'akRight'#0#16'AutoCompleteText'#11#22'cbactEndOfLineComplete'#20'cbactSearc'
+ +'hAscending'#0#9'MaxLength'#2#0#8'TabOrder'#2#0#4'Text'#6#17'InheritedComboB'
+ +'ox'#0#0#7'TButton'#8'OkButton'#4'Left'#2#24#6'Height'#2#25#3'Top'#2'('#5'Wi'
+ +'dth'#2'K'#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#8'OkButton'#7'Defa'
+ +'ult'#9#11'ModalResult'#2#1#8'TabOrder'#2#1#0#0#7'TButton'#12'CancelButton'#4
+ +'Left'#3#136#0#6'Height'#2#25#3'Top'#2'('#5'Width'#2'K'#25'BorderSpacing.Inn'
+ +'erBorder'#2#4#6'Cancel'#9#7'Caption'#6#12'CancelButton'#11'ModalResult'#2#2
+ +#8'TabOrder'#2#2#0#0#0
+]);
diff --git a/ide/lazdocselectinherited.pas b/ide/lazdocselectinherited.pas
new file mode 100644
index 0000000000..dd42f5190d
--- /dev/null
+++ b/ide/lazdocselectinherited.pas
@@ -0,0 +1,63 @@
+{
+/***************************************************************************
+ LazDocFrm.pas
+ -------------
+
+ ***************************************************************************/
+
+ ***************************************************************************
+ * *
+ * This source is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This code is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * General Public License for more details. *
+ * *
+ * A copy of the GNU General Public License is available on the World *
+ * Wide Web at . You can also *
+ * obtain it by writing to the Free Software Foundation, *
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ ***************************************************************************
+}
+unit LazDocSelectInherited;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
+ Buttons;
+
+type
+
+ { TLazDocSelectInheritedDlg }
+
+ TLazDocSelectInheritedDlg = class(TForm)
+ OkButton: TButton;
+ CancelButton: TButton;
+ InheritedComboBox: TComboBox;
+ procedure FormCreate(Sender: TObject);
+ end;
+
+implementation
+
+{ TLazDocSelectInheritedDlg }
+
+procedure TLazDocSelectInheritedDlg.FormCreate(Sender: TObject);
+begin
+ Caption:='Select an inherited entry';
+ OkButton.Caption:='Ok';
+ CancelButton.Caption:='Cancel';
+end;
+
+initialization
+ {$I lazdocselectinherited.lrs}
+
+end.
+
diff --git a/ide/project.pp b/ide/project.pp
index a15e00a3b5..c51dfe3124 100644
--- a/ide/project.pp
+++ b/ide/project.pp
@@ -422,14 +422,6 @@ type
{ TProject }
- TProjectFileSearchFlag = (
- pfsfResolveFileLinks,
- pfsfOnlyEditorFiles,
- pfsfOnlyVirtualFiles,
- pfsfOnlyProjectFiles
- );
- TProjectFileSearchFlags = set of TProjectFileSearchFlag;
-
TEndUpdateProjectEvent =
procedure(Sender: TObject; ProjectChanged: boolean) of object;
@@ -590,6 +582,8 @@ type
function UnitWithUnitname(const AnUnitname: string): TUnitInfo;
function SearchFile(const ShortFilename: string;
SearchFlags: TSearchIDEFileFlags): TUnitInfo;
+ function FindFile(const AFilename: string;
+ SearchFlags: TProjectFileSearchFlags): TLazProjectFile; override;
// units in editor
procedure CloseEditorIndex(EditorIndex:integer);
@@ -3426,6 +3420,12 @@ begin
end;
end;
+function TProject.FindFile(const AFilename: string;
+ SearchFlags: TProjectFileSearchFlags): TLazProjectFile;
+begin
+ Result:=UnitInfoWithFilename(AFilename, SearchFlags);
+end;
+
function TProject.IndexOfFilename(const AFilename: string): integer;
begin
Result:=UnitCount-1;
diff --git a/ide/revision.inc b/ide/revision.inc
index 96568f847c..b73d5d9d23 100644
--- a/ide/revision.inc
+++ b/ide/revision.inc
@@ -1,2 +1,2 @@
// Created by Svn2RevisionInc
-const RevisionStr = '9724:9725M';
+const RevisionStr = '9728M';
diff --git a/ide/uniteditor.pp b/ide/uniteditor.pp
index d5c4311b6b..3bf2c950fb 100644
--- a/ide/uniteditor.pp
+++ b/ide/uniteditor.pp
@@ -579,7 +579,6 @@ type
procedure ShowLazDoc;
procedure UpdateLazDoc;
- procedure LazDocNewPage;
property Editors[Index:integer]:TSourceEditor read GetEditors;
function EditorCount:integer;
@@ -2864,99 +2863,19 @@ end;
procedure TSourceNotebook.ShowLazDoc;
begin
DoShowLazDoc;
- LazDocNewPage;
-end;
-
-function FindLazDocPathFromFile(const AFileName: string): string;
-var
- i: integer;
- fn: string;
- SearchPaths: String;
- PathList: TStrings;
-begin
- Result := '';
- if not FilenameIsAbsolute(AFileName) then exit;
- if not FilenameIsPascalSource(AFileName) then exit;
-
- // add global lazdoc paths
- SearchPaths:=EnvironmentOptions.LazDocPaths;
- // if this is a project file then add project lazdoc paths
- if Project1.UnitInfoWithFilename(AFileName,[pfsfOnlyProjectFiles])<>nil then
- SearchPaths:=LazarusIDE.ActiveProject.LazDocPaths+';'+SearchPaths;
-
- // replace macros
- IDEMacros.SubstituteMacros(SearchPaths);
- SearchPaths:=TrimSearchPath(SearchPaths,'');
-
- //DebugLn('FindLazDocPathFromFile AFileName="',AFileName,'" SearchPaths="',SearchPaths,'"');
-
- // search xml file in all directories
- fn := PathDelim + ChangeFileExt(ExtractFileName(AFileName), '.xml');
- PathList:=SplitString(SearchPaths,';');
- try
- for i:=0 to PathList.Count-1 do begin
- if FilenameIsAbsolute(PathList[i])
- and FileExistsCached(TrimFilename(PathList[i] + fn)) then
- begin
- Result := PathList[i];
- break;
- end;
- end;
- finally
- PathList.Free;
- end;
- //DebugLn('FindLazDocPathFromFile Result="',Result,'"');
-end;
-
-procedure TSourceNotebook.LazDocNewPage;
-var
- SrcEdit: TSourceEditor;
- DocPath: string;
- NewDocPath: string;
-begin
- //DebugLn('TSourceNotebook.LazDocNewPage ',dbgs(Assigned(LazDocForm)));
- if Assigned(LazDocForm) then
- begin
- SrcEdit:=GetActiveSE;
- if SrcEdit=nil then exit;
-
- DocPath := FindLazDocPathFromFile(SrcEdit.FileName);
-
- if DocPath <> '' then
- begin
- // load the .xml file
- NewDocPath:=DocPath + PathDelim +
- ChangeFileExt(ExtractFileName(SrcEdit.FileName),'.xml');
- if NewDocPath<>LazDocForm.DocFileName then begin
- LazDocForm.DocFileName := NewDocPath;
- UpdateLazDoc;
- end;
- end
- else
- LazDocForm.Reset;
- end;
+ UpdateLazDoc;
end;
procedure TSourceNotebook.UpdateLazDoc;
var
SrcEdit: TSourceEditor;
- DocPath: string;
CaretPos: TPoint;
begin
if LazDocForm = nil then exit;
-
SrcEdit:=GetActiveSE;
-
- // find a path that contains the .xml file
- DocPath := FindLazDocPathFromFile(SrcEdit.FileName);
-
- if DocPath <> '' then
- begin
- CaretPos := SrcEdit.EditorComponent.CaretXY;
- LazDocForm.UpdateLazDoc(SrcEdit.Filename,CaretPos);
- end
- else
- LazDocForm.Reset;
+ if SrcEdit=nil then exit;
+ CaretPos := SrcEdit.EditorComponent.CaretXY;
+ LazDocForm.UpdateLazDoc(SrcEdit.Filename,CaretPos);
end;
function TSourceNotebook.OnSynCompletionPaintItem(const AKey: string;
@@ -5274,8 +5193,6 @@ var TempEditor:TSourceEditor;
Begin
TempEditor:=GetActiveSE;
- LazDocNewPage;
-
//writeln('TSourceNotebook.NotebookPageChanged ',Notebook.Pageindex,' ',TempEditor <> nil,' fAutoFocusLock=',fAutoFocusLock);
if TempEditor <> nil then
begin
@@ -5298,6 +5215,8 @@ Begin
FOnEditorVisibleChanged(sender);
CheckCurrentCodeBufferChanged;
end;
+
+ UpdateLazDoc;
end;
Procedure TSourceNotebook.ProcessParentCommand(Sender: TObject;
diff --git a/ideintf/projectintf.pas b/ideintf/projectintf.pas
index 375a800254..a8b21e7370 100644
--- a/ideintf/projectintf.pas
+++ b/ideintf/projectintf.pas
@@ -498,6 +498,14 @@ type
{ TLazProject - interface class to a Lazarus project }
+ TProjectFileSearchFlag = (
+ pfsfResolveFileLinks,
+ pfsfOnlyEditorFiles,
+ pfsfOnlyVirtualFiles,
+ pfsfOnlyProjectFiles
+ );
+ TProjectFileSearchFlags = set of TProjectFileSearchFlag;
+
TLazProject = class(TPersistent)
private
FLazCompilerOptions: TLazCompilerOptions;
@@ -535,6 +543,8 @@ type
procedure AddPackageDependency(const PackageName: string); virtual; abstract;
function ShortDescription: string;
procedure ClearModifieds;
+ function FindFile(const AFilename: string;
+ SearchFlags: TProjectFileSearchFlags): TLazProjectFile; virtual; abstract;
public
property MainFileID: Integer read GetMainFileID write SetMainFileID;
property Files[Index: integer]: TLazProjectFile read GetFiles;
diff --git a/lcl/interfaces/gtk/gtkproc.inc b/lcl/interfaces/gtk/gtkproc.inc
index a4c182ab3e..911ff18b7f 100644
--- a/lcl/interfaces/gtk/gtkproc.inc
+++ b/lcl/interfaces/gtk/gtkproc.inc
@@ -369,19 +369,6 @@ begin
result := gdk_window_get_colormap(Drawable);
end;
-function FormToX11Window(const AForm: TCustomForm): X.TWindow;
-var
- GdkWindow: PGdkWindowPrivate;
- Widget: PGtkWidget;
-begin
- Result:=0;
- if (AForm=nil) or (not AForm.HandleAllocated) then exit;
- Widget:=PGtkWidget(AForm.Handle);
- GdkWindow := PGdkWindowPrivate(Widget^.window);
- if GdkWindow=nil then exit;
- Result := GdkWindow^.xwindow;
-end;
-
{$EndIf}
{$Ifdef GTK2}
@@ -1097,6 +1084,21 @@ begin
{$ENDIF}
end;
+{$IFDEF HasGtkX}
+function FormToX11Window(const AForm: TCustomForm): X.TWindow;
+var
+ GdkWindow: PGdkWindowPrivate;
+ Widget: PGtkWidget;
+begin
+ Result:=0;
+ if (AForm=nil) or (not AForm.HandleAllocated) then exit;
+ Widget:=PGtkWidget(AForm.Handle);
+ GdkWindow := PGdkWindowPrivate(Widget^.window);
+ if GdkWindow=nil then exit;
+ Result := GdkWindow^.xwindow;
+end;
+{$ENDIF}
+
{------------------------------------------------------------------------------
procedure SetComboBoxText(ComboWidget: PGtkCombo; const NewText: string);