From 2f2c92352bb47ba535a2f8effe3b4d70d40dcd28 Mon Sep 17 00:00:00 2001 From: mattias Date: Fri, 12 May 2006 08:27:08 +0000 Subject: [PATCH] code templates: fixed reading new lines at start of template git-svn-id: trunk@9259 - --- components/codetools/codetoolmanager.pas | 8 +- components/codetools/finddeclarationtool.pas | 28 +- components/codetools/pascalreadertool.pas | 2 +- components/synedit/syneditautocomplete.pp | 24 ++ converter/delphiunit2laz.pas | 18 +- ide/codemacroprompt.pas | 5 +- ide/codetemplatesdlg.pas | 107 +++--- ide/compileroptionsdlg.pp | 2 +- ide/environmentopts.pp | 25 +- ide/findrenameidentifier.pas | 6 +- ide/helpmanager.pas | 232 +++++++------ ide/ideprocs.pp | 75 +++-- ide/lazdocfrm.lfm | 95 +++--- ide/lazdocfrm.lrs | 328 +++++++++---------- ide/lazdocfrm.pas | 285 ++++++++-------- ide/main.pp | 7 +- ide/project.pp | 4 +- ide/projectopts.pp | 7 +- ide/uniteditor.pp | 96 +++--- ideintf/helphtml.pas | 3 +- ideintf/helpintf.pas | 31 +- ideintf/projectintf.pas | 6 +- lcl/include/application.inc | 5 +- packager/packagesystem.pas | 3 +- 24 files changed, 766 insertions(+), 636 deletions(-) diff --git a/components/codetools/codetoolmanager.pas b/components/codetools/codetoolmanager.pas index 5c0064782a..5c86072094 100644 --- a/components/codetools/codetoolmanager.pas +++ b/components/codetools/codetoolmanager.pas @@ -327,7 +327,8 @@ type out NewCode: TCodeBuffer; out NewX, NewY, NewTopLine: integer): Boolean; function FindDeclarationAndOverload(Code: TCodeBuffer; X,Y: integer; - var ListOfPCodeXYPosition: TFPList): boolean; + var ListOfPCodeXYPosition: TFPList; + Flags: TFindDeclarationListFlags): boolean; function FindMainDeclaration(Code: TCodeBuffer; X,Y: integer; out NewCode: TCodeBuffer; out NewX, NewY, NewTopLine: integer): boolean; @@ -1596,7 +1597,8 @@ begin end; function TCodeToolManager.FindDeclarationAndOverload(Code: TCodeBuffer; X, - Y: integer; var ListOfPCodeXYPosition: TFPList): boolean; + Y: integer; var ListOfPCodeXYPosition: TFPList; + Flags: TFindDeclarationListFlags): boolean; var CursorPos: TCodeXYPosition; begin @@ -1613,7 +1615,7 @@ begin {$ENDIF} try Result:=FCurCodeTool.FindDeclarationAndOverload(CursorPos, - ListOfPCodeXYPosition); + ListOfPCodeXYPosition,Flags); except on e: Exception do Result:=HandleException(e); end; diff --git a/components/codetools/finddeclarationtool.pas b/components/codetools/finddeclarationtool.pas index bb021e3dd7..acc8f31a90 100644 --- a/components/codetools/finddeclarationtool.pas +++ b/components/codetools/finddeclarationtool.pas @@ -486,6 +486,11 @@ type TFindSrcStartType = ( fsstIdentifier ); + + TFindDeclarationListFlag = ( + fdlfWithoutEmptyProperties // omit properties without type and attributes + ); + TFindDeclarationListFlags = set of TFindDeclarationListFlag; const AllFindSmartFlags = [fsfIncludeDirective]; @@ -713,7 +718,8 @@ type Node: TCodeTreeNode): TFindContext; function FindDeclarationAndOverload(const CursorPos: TCodeXYPosition; - out ListOfPCodeXYPosition: TFPList): boolean; + out ListOfPCodeXYPosition: TFPList; + Flags: TFindDeclarationListFlags): boolean; function FindClassAndAncestors(ClassNode: TCodeTreeNode; out ListOfPFindContext: TFPList): boolean; function FindContextClassAndAncestors(const CursorPos: TCodeXYPosition; @@ -3030,8 +3036,8 @@ begin end; function TFindDeclarationTool.FindDeclarationAndOverload( - const CursorPos: TCodeXYPosition; out ListOfPCodeXYPosition: TFPList - ): boolean; + const CursorPos: TCodeXYPosition; out ListOfPCodeXYPosition: TFPList; + Flags: TFindDeclarationListFlags): boolean; var CurCursorPos: TCodeXYPosition; NewTool: TFindDeclarationTool; @@ -3039,15 +3045,19 @@ var NewPos: TCodeXYPosition; NewTopLine: integer; CurTool: TFindDeclarationTool; + OldPositions: TFPList; + Add: Boolean; begin Result:=true; ListOfPCodeXYPosition:=nil; AddCodePosition(ListOfPCodeXYPosition,CursorPos); NewTool:=nil; NewNode:=nil; + OldPositions:=nil; ActivateGlobalWriteLock; try + AddCodePosition(OldPositions,CursorPos); CurCursorPos:=CursorPos; CurTool:=Self; try @@ -3055,8 +3065,15 @@ begin +[fsfSearchSourceName], NewTool,NewNode,NewPos,NewTopLine) do begin - if IndexOfCodePosition(ListOfPCodeXYPosition,@NewPos)>=0 then break; - AddCodePosition(ListOfPCodeXYPosition,NewPos); + if IndexOfCodePosition(OldPositions,@NewPos)>=0 then break; + AddCodePosition(OldPositions,NewPos); + Add:=true; + if (fdlfWithoutEmptyProperties in Flags) + and (NewNode.Desc=ctnProperty) + and (NewTool.PropNodeIsTypeLess(NewNode)) then + Add:=false; + if Add then + AddCodePosition(ListOfPCodeXYPosition,NewPos); CurCursorPos:=NewPos; CurTool:=NewTool; {debugln('TFindDeclarationTool.FindDeclarationAndOverload ', @@ -3074,6 +3091,7 @@ begin end; finally DeactivateGlobalWriteLock; + FreeListOfPCodeXYPosition(OldPositions); end; end; diff --git a/components/codetools/pascalreadertool.pas b/components/codetools/pascalreadertool.pas index 835f4b634c..6b7c4c868c 100644 --- a/components/codetools/pascalreadertool.pas +++ b/components/codetools/pascalreadertool.pas @@ -1500,7 +1500,7 @@ begin ReadNextAtom; // read 'property' end; ReadNextAtom; // read name - ReadNextAtom; + ReadNextAtom; // read colon, skip parameters if CurPos.Flag=cafEdgedBracketOpen then begin ReadTilBracketClose(true); ReadNextAtom; diff --git a/components/synedit/syneditautocomplete.pp b/components/synedit/syneditautocomplete.pp index 4cddb11c29..c94f745b01 100644 --- a/components/synedit/syneditautocomplete.pp +++ b/components/synedit/syneditautocomplete.pp @@ -474,6 +474,9 @@ var BorlandDCI: boolean; i, j, Len: integer; s, sCompl, sComment, sComplValue: string; + {$IFDEF SYN_LAZARUS} + TemplateStarted: Boolean; + {$ENDIF} procedure SaveEntry; begin @@ -497,6 +500,9 @@ begin sCompl := ''; sComment := ''; sComplValue := ''; + {$IFDEF SYN_LAZARUS} + TemplateStarted:=false; + {$ENDIF} for i := 0 to fAutoCompleteList.Count - 1 do begin s := fAutoCompleteList[i]; Len := Length(s); @@ -521,9 +527,18 @@ begin sComment := Copy(s, j, Len); if sComment[Length(sComment)] = ']' then SetLength(sComment, Length(sComment) - 1); + {$IFDEF SYN_LAZARUS} + TemplateStarted:=true; + {$ENDIF} end else begin + {$IFDEF SYN_LAZARUS} + if not TemplateStarted then + sComplValue := sComplValue + #13#10; + TemplateStarted:=false; + {$ELSE} if sComplValue <> '' then sComplValue := sComplValue + #13#10; + {$ENDIF} sComplValue := sComplValue + s; end; end else begin @@ -534,9 +549,18 @@ begin SaveEntry; // new completion entry sCompl := s; + {$IFDEF SYN_LAZARUS} + TemplateStarted:=true; + {$ENDIF} end else if (Len > 0) and (s[1] = '=') then begin + {$IFDEF SYN_LAZARUS} + if not TemplateStarted then + sComplValue := sComplValue + #13#10; + TemplateStarted:=false; + {$ELSE} if sComplValue <> '' then sComplValue := sComplValue + #13#10; + {$ENDIF} sComplValue := sComplValue + Copy(s, 2, Len); end; end; diff --git a/converter/delphiunit2laz.pas b/converter/delphiunit2laz.pas index 46d50d2ebc..2f3b4d33f0 100644 --- a/converter/delphiunit2laz.pas +++ b/converter/delphiunit2laz.pas @@ -546,7 +546,7 @@ var procedure ReadDelphiPackages; var DelphiPackages: String; - Pkgs: TStringList; + Pkgs: TStrings; i: Integer; Pkg: string; begin @@ -554,11 +554,15 @@ var //DebugLn('ReadDelphiPackages DelphiPackages=',DelphiPackages); Pkgs:=SplitString(DelphiPackages,';'); if Pkgs=nil then exit; - for i:=0 to Pkgs.Count-1 do begin - Pkg:=Pkgs[i]; - DebugLn('ReadDelphiPackages Pkg=',Pkg); - AddPackageDependency(Pkg,'rtl,dbrtl','FCL'); - AddPackageDependency('LCL'); + try + for i:=0 to Pkgs.Count-1 do begin + Pkg:=Pkgs[i]; + DebugLn('ReadDelphiPackages Pkg=',Pkg); + AddPackageDependency(Pkg,'rtl,dbrtl','FCL'); + AddPackageDependency('LCL'); + end; + finally + Pkgs.Free; end; end; @@ -763,7 +767,7 @@ end; function ExpandDelphiSearchPath(const SearchPath: string; AProject: TProject): string; var - Paths: TStringList; + Paths: TStrings; i: Integer; CurPath: String; j: Integer; diff --git a/ide/codemacroprompt.pas b/ide/codemacroprompt.pas index a894a19126..1b68165921 100644 --- a/ide/codemacroprompt.pas +++ b/ide/codemacroprompt.pas @@ -79,7 +79,6 @@ begin LazarusIDE.SaveSourceEditorChangesToCodeCache(-1); // remove first line (i.e. macro enabled flag) - Pattern:=TemplateValue; i:=length(CodeTemplateMakroMagic); while (i<=length(Pattern)) and (not (Pattern[i] in [#10,#13])) do inc(i); if (i0) and (p.y<=AEditor.Lines.Count) then begin s:=AEditor.Lines[p.y-1]; while (IndentLenlength(s)) or (s[IndentLen]<=' ')) do + and ((IndentLen>length(s)) or (s[IndentLen] in [#9,' '])) do inc(IndentLen); end; IndentLen:=AEditor.LogicalToPhysicalCol(s,IndentLen);// consider tabs diff --git a/ide/codetemplatesdlg.pas b/ide/codetemplatesdlg.pas index 906a69f06e..07e673791a 100644 --- a/ide/codetemplatesdlg.pas +++ b/ide/codetemplatesdlg.pas @@ -257,7 +257,7 @@ function CodeMakroProcedureHead(const Parameter: string; InteractiveValue: TPersistent; SrcEdit: TSourceEditorInterface; var Value, ErrorMsg: string): boolean; var - Params: TStringList; + Params: TStrings; Param: string; i: Integer; Attributes: TProcHeadAttributes; @@ -266,59 +266,61 @@ begin // parse attributes Params:=SplitString(Parameter,','); - try - Attributes:=[]; - for i:=0 to Params.Count-1 do begin - Param:=Params[i]; - if CompareText(Param,'WithStart')=0 then - Include(Attributes,phpWithStart) - else if CompareText(Param,'WithStart')=0 then - Include(Attributes,phpWithStart) - else if CompareText(Param,'WithoutClassKeyword')=0 then - Include(Attributes,phpWithoutClassKeyword) - else if CompareText(Param,'AddClassName')=0 then - Include(Attributes,phpAddClassName) - else if CompareText(Param,'WithoutClassName')=0 then - Include(Attributes,phpWithoutClassName) - else if CompareText(Param,'WithoutName')=0 then - Include(Attributes,phpWithoutName) - else if CompareText(Param,'WithoutParamList')=0 then - Include(Attributes,phpWithoutParamList) - else if CompareText(Param,'WithVarModifiers')=0 then - Include(Attributes,phpWithVarModifiers) - else if CompareText(Param,'WithParameterNames')=0 then - Include(Attributes,phpWithParameterNames) - else if CompareText(Param,'WithoutParamTypes')=0 then - Include(Attributes,phpWithoutParamTypes) - else if CompareText(Param,'WithDefaultValues')=0 then - Include(Attributes,phpWithDefaultValues) - else if CompareText(Param,'WithResultType')=0 then - Include(Attributes,phpWithResultType) - else if CompareText(Param,'WithOfObject')=0 then - Include(Attributes,phpWithOfObject) - else if CompareText(Param,'WithCallingSpecs')=0 then - Include(Attributes,phpWithCallingSpecs) - else if CompareText(Param,'WithProcModifiers')=0 then - Include(Attributes,phpWithProcModifiers) - else if CompareText(Param,'WithComments')=0 then - Include(Attributes,phpWithComments) - else if CompareText(Param,'InUpperCase')=0 then - Include(Attributes,phpInUpperCase) - else if CompareText(Param,'CommentsToSpace')=0 then - Include(Attributes,phpCommentsToSpace) - else if CompareText(Param,'WithoutBrackets')=0 then - Include(Attributes,phpWithoutBrackets) - else if CompareText(Param,'WithoutSemicolon')=0 then - Include(Attributes,phpWithoutSemicolon) - else begin - Result:=false; - ErrorMsg:='Unknown Option: "'+Param+'"'; - exit; + if Params<>nil then begin + try + Attributes:=[]; + for i:=0 to Params.Count-1 do begin + Param:=Params[i]; + if CompareText(Param,'WithStart')=0 then + Include(Attributes,phpWithStart) + else if CompareText(Param,'WithStart')=0 then + Include(Attributes,phpWithStart) + else if CompareText(Param,'WithoutClassKeyword')=0 then + Include(Attributes,phpWithoutClassKeyword) + else if CompareText(Param,'AddClassName')=0 then + Include(Attributes,phpAddClassName) + else if CompareText(Param,'WithoutClassName')=0 then + Include(Attributes,phpWithoutClassName) + else if CompareText(Param,'WithoutName')=0 then + Include(Attributes,phpWithoutName) + else if CompareText(Param,'WithoutParamList')=0 then + Include(Attributes,phpWithoutParamList) + else if CompareText(Param,'WithVarModifiers')=0 then + Include(Attributes,phpWithVarModifiers) + else if CompareText(Param,'WithParameterNames')=0 then + Include(Attributes,phpWithParameterNames) + else if CompareText(Param,'WithoutParamTypes')=0 then + Include(Attributes,phpWithoutParamTypes) + else if CompareText(Param,'WithDefaultValues')=0 then + Include(Attributes,phpWithDefaultValues) + else if CompareText(Param,'WithResultType')=0 then + Include(Attributes,phpWithResultType) + else if CompareText(Param,'WithOfObject')=0 then + Include(Attributes,phpWithOfObject) + else if CompareText(Param,'WithCallingSpecs')=0 then + Include(Attributes,phpWithCallingSpecs) + else if CompareText(Param,'WithProcModifiers')=0 then + Include(Attributes,phpWithProcModifiers) + else if CompareText(Param,'WithComments')=0 then + Include(Attributes,phpWithComments) + else if CompareText(Param,'InUpperCase')=0 then + Include(Attributes,phpInUpperCase) + else if CompareText(Param,'CommentsToSpace')=0 then + Include(Attributes,phpCommentsToSpace) + else if CompareText(Param,'WithoutBrackets')=0 then + Include(Attributes,phpWithoutBrackets) + else if CompareText(Param,'WithoutSemicolon')=0 then + Include(Attributes,phpWithoutSemicolon) + else begin + Result:=false; + ErrorMsg:='Unknown Option: "'+Param+'"'; + exit; + end; end; - end; - finally - Params.Free; + finally + Params.Free; + end; end; //debugln('CodeMakroProcedureHead B '); @@ -916,6 +918,7 @@ begin if UseMakrosCheckBox.Checked then NewValue:=CodeTemplateMakroMagic+LineEnding+NewValue; SynAutoComplete.CompletionValues[a]:=NewValue; + //DebugLn('TCodeTemplateDialog.SaveCurCodeTemplate NewValue="',NewValue,'" SynAutoComplete.CompletionValues[a]="',SynAutoComplete.CompletionValues[a],'"'); end; { TLazCodeMacros } diff --git a/ide/compileroptionsdlg.pp b/ide/compileroptionsdlg.pp index 5c23ebbdb1..7db26e278a 100644 --- a/ide/compileroptionsdlg.pp +++ b/ide/compileroptionsdlg.pp @@ -566,7 +566,7 @@ procedure TfrmCompilerOptions.InhTreeViewSelectionChanged(Sender: TObject); var ANode: TTreeNode; ChildData: PInheritedNodeData; - sl: TStringList; + sl: TStrings; begin ANode:=InhTreeView.Selected; if (ANode=nil) or (ANode.Data=nil) then begin diff --git a/ide/environmentopts.pp b/ide/environmentopts.pp index e87034bed2..9d54acd150 100644 --- a/ide/environmentopts.pp +++ b/ide/environmentopts.pp @@ -42,7 +42,7 @@ uses InputHistory, EditorOptions, IDETranslations; const - EnvOptsVersion: integer = 105; + EnvOptsVersion: integer = 106; //---------------------------------------------------------------------------- @@ -222,7 +222,7 @@ type fCharcaseFileAction : TCharCaseFileAction; fAmbiguousFileAction: TAmbiguousFileAction; - FLazDocPathList: TStrings; + FLazDocPaths: string; // language ID (see LazarusTranslations in translations.pas) fLanguageID: string; @@ -396,7 +396,7 @@ type write fCharcaseFileAction; // lazdoc - property LazDocPathList: TStrings read FLazDocPathList write FLazDocPathList; + property LazDocPaths: string read FLazDocPaths write FLazDocPaths; // language property LanguageID: string read fLanguageID write fLanguageID; @@ -649,6 +649,9 @@ procedure SetComboBoxText(AComboBox:TComboBox; const AText:AnsiString); procedure SetComboBoxText(AComboBox:TComboBox; const AText:AnsiString; MaxCount: integer); +const + DefaultLazDocPath = '$(LazarusDir)/docs/xml/lcl'; + implementation @@ -892,7 +895,7 @@ begin fPascalFileExtension:=petPAS; fCharcaseFileAction:=ccfaAutoRename; - FLazDocPathList:=TStringList.Create; + FLazDocPaths:=SetDirSeparators(DefaultLazDocPath); end; destructor TEnvironmentOptions.Destroy; @@ -914,7 +917,6 @@ begin fIDEWindowLayoutList.Free; FConfigStore.Free; FXMLCfg.Free; - FLazDocPathList.Free; inherited Destroy; end; @@ -1175,9 +1177,9 @@ begin LoadPascalFileExt(Path+''); //lazdoc - if FLazDocPathList<>nil then - FLazDocPathList.Text := - XMLConfig.GetValue(Path+'LazDoc/Paths', FLazDocPathList.Text); + FLazDocPaths := XMLConfig.GetValue(Path+'LazDoc/Paths', DefaultLazDocPath); + if FileVersion<=105 then + FLazDocPaths:=LineBreaksToDelimiter(FLazDocPaths,';'); if FileVersion>=103 then begin fCharcaseFileAction:=CharCaseFileActionNameToType(XMLConfig.GetValue( @@ -1399,8 +1401,7 @@ begin AmbiguousFileActionNames[afaAsk]); //lazdoc - if FLazDocPathList<>nil then - XMLConfig.SetValue(Path+'LazDoc/Paths', FLazDocPathList.Text); + XMLConfig.SetDeleteValue(Path+'LazDoc/Paths',FLazDocPaths,DefaultLazDocPath); // object inspector FObjectInspectorOptions.SaveBounds:=false; @@ -2332,7 +2333,7 @@ begin AmbiguousFileActionRadioGroup.ItemIndex := ord(AmbiguousFileAction); //lazdoc - LazDocListBox.Items.AddStrings(LazDocPathList); + SplitString(LazDocPaths,';',LazDocListBox.Items); end; end; @@ -2473,7 +2474,7 @@ begin PascalFileExtension:=petPAS; //lazdoc - LazDocPathList.Assign(LazDocListBox.Items); + LazDocPaths:=StringListToText(LazDocListBox.Items,';',true); CharcaseFileAction := TCharCaseFileAction(CharcaseFileActionRadioGroup.ItemIndex); AmbiguousFileAction := TAmbiguousFileAction(AmbiguousFileActionRadioGroup.ItemIndex); diff --git a/ide/findrenameidentifier.pas b/ide/findrenameidentifier.pas index 088fa04f7e..e10ffc3341 100644 --- a/ide/findrenameidentifier.pas +++ b/ide/findrenameidentifier.pas @@ -352,13 +352,9 @@ end; procedure TFindRenameIdentifierDialog.SaveToOptions( Options: TFindRenameIdentifierOptions); -var - ExtraFileList: TStringList; begin Options.Rename:=RenameCheckBox.Checked; - ExtraFileList:=SplitString(ExtraFilesEdit.Text,';'); - Options.ExtraFiles.Assign(ExtraFileList); - ExtraFileList.Free; + SplitString(ExtraFilesEdit.Text,';',Options.ExtraFiles,true); Options.RenameTo:=NewEdit.Text; Options.SearchInComments:=ScopeCommentsCheckBox.Checked; case ScopeRadioGroup.ItemIndex of diff --git a/ide/helpmanager.pas b/ide/helpmanager.pas index 4f5096b0aa..30ed18b8b1 100644 --- a/ide/helpmanager.pas +++ b/ide/helpmanager.pas @@ -69,14 +69,14 @@ type procedure mnuHelpConfigureHelpClicked(Sender: TObject); procedure mnuHelpOnlineHelpClicked(Sender: TObject); private - FFCLHelpDBPath: THelpBasePathObject; - FLCLHelpDBPath: THelpBasePathObject; + FFCLHelpDBPath: THelpBaseURLObject; + FLCLHelpDBPath: THelpBaseURLObject; FMainHelpDB: THelpDatabase; FMainHelpDBPath: THelpBasePathObject; FRTLHelpDB: THelpDatabase; FFCLHelpDB: THelpDatabase; FLCLHelpDB: THelpDatabase; - FRTLHelpDBPath: THelpBasePathObject; + FRTLHelpDBPath: THelpBaseURLObject; procedure RegisterIDEHelpDatabases; procedure RegisterDefaultIDEHelpViewers; procedure FindDefaultBrowser(var DefaultBrowser, Params: string); @@ -97,15 +97,20 @@ type var ErrMsg: string): TShowHelpResult; override; procedure ShowHelpForMessage(Line: integer); override; procedure ShowHelpForObjectInspector(Sender: TObject); override; + + function ConvertSourcePosToPascalHelpContext(const CaretPos: TPoint; + const Filename: string): TPascalHelpContextList; override; + function ConvertCodePosToPascalHelpContext( + ACodePos: PCodeXYPosition): TPascalHelpContextList; public property FCLHelpDB: THelpDatabase read FFCLHelpDB; - property FCLHelpDBPath: THelpBasePathObject read FFCLHelpDBPath; + property FCLHelpDBPath: THelpBaseURLObject read FFCLHelpDBPath; property LCLHelpDB: THelpDatabase read FLCLHelpDB; - property LCLHelpDBPath: THelpBasePathObject read FLCLHelpDBPath; + property LCLHelpDBPath: THelpBaseURLObject read FLCLHelpDBPath; property MainHelpDB: THelpDatabase read FMainHelpDB; property MainHelpDBPath: THelpBasePathObject read FMainHelpDBPath; property RTLHelpDB: THelpDatabase read FRTLHelpDB; - property RTLHelpDBPath: THelpBasePathObject read FRTLHelpDBPath; + property RTLHelpDBPath: THelpBaseURLObject read FRTLHelpDBPath; end; { THelpSelectorDialog } @@ -205,6 +210,8 @@ begin Selection:=Nodes[i]; Result:=shrSuccess; end; + end else begin + Result:=shrCancel; end; finally Dialog.Free; @@ -219,6 +226,7 @@ begin case ShowResult of shrNone: ErrorCaption:=lisCodeTemplError; shrSuccess: exit; + shrCancel: exit; shrDatabaseNotFound: ErrorCaption:=lisHelpDatabaseNotFound; shrContextNotFound: ErrorCaption:=lisHelpContextNotFound; shrViewerNotFound: ErrorCaption:=lisHelpViewerNotFound; @@ -234,6 +242,7 @@ function TIDEHelpDatabases.GetBaseDirectoryForBasePathObject( BasePathObject: TObject): string; begin Result:=''; + DebugLn('TIDEHelpDatabases.GetBaseDirectoryForBasePathObject BasePathObject=',dbgsName(BasePathObject)); if (BasePathObject is THelpBasePathObject) then Result:=THelpBasePathObject(BasePathObject).BasePath else if (BasePathObject=HelpBoss) or (BasePathObject=MainIDEInterface) then @@ -302,7 +311,7 @@ procedure THelpManager.RegisterIDEHelpDatabases; TFPDocHTMLHelpDatabase,true); HTMLHelp:=FRTLHelpDB as TFPDocHTMLHelpDatabase; HTMLHelp.DefaultBaseURL:=lihRTLURL; - FRTLHelpDBPath:=THelpBasePathObject.Create; + FRTLHelpDBPath:=THelpBaseURLObject.Create; HTMLHelp.BasePathObject:=FRTLHelpDBPath; // FPDoc nodes for units in the RTL @@ -325,7 +334,7 @@ procedure THelpManager.RegisterIDEHelpDatabases; TFPDocHTMLHelpDatabase,true); HTMLHelp:=FFCLHelpDB as TFPDocHTMLHelpDatabase; HTMLHelp.DefaultBaseURL:=lihFCLURL; - FFCLHelpDBPath:=THelpBasePathObject.Create; + FFCLHelpDBPath:=THelpBaseURLObject.Create; HTMLHelp.BasePathObject:=FFCLHelpDBPath; // FPDoc nodes for units in the FCL @@ -348,7 +357,7 @@ procedure THelpManager.RegisterIDEHelpDatabases; TFPDocHTMLHelpDatabase,true); HTMLHelp:=FLCLHelpDB as TFPDocHTMLHelpDatabase; HTMLHelp.DefaultBaseURL:=lihLCLURL; - FLCLHelpDBPath:=THelpBasePathObject.Create; + FLCLHelpDBPath:=THelpBaseURLObject.Create; HTMLHelp.BasePathObject:=FLCLHelpDBPath; // FPDoc nodes for units in the LCL @@ -387,6 +396,7 @@ constructor THelpManager.Create(TheOwner: TComponent); begin inherited Create(TheOwner); HelpBoss:=Self; + LazarusHelp:=Self; HelpOpts:=THelpOptions.Create; HelpOpts.SetDefaultFilename; HelpDatabases:=TIDEHelpDatabases.Create; @@ -410,6 +420,7 @@ begin FreeThenNil(FFCLHelpDBPath); FreeThenNil(FLCLHelpDBPath); HelpBoss:=nil; + LazarusHelp:=nil; inherited Destroy; end; @@ -513,97 +524,6 @@ function THelpManager.ShowHelpForSourcePosition(const Filename: string; Result:=ShowHelpForFPCKeyWord(KeyWord); end; - function ConvertCodePosToPascalHelpContext(ACodePos: PCodeXYPosition - ): TPascalHelpContextList; - - procedure AddContext(Descriptor: TPascalHelpContextType; - const Context: string); - var - CurContext: TPascalHelpContext; - begin - CurContext.Descriptor:=Descriptor; - CurContext.Context:=Context; - Result.Add(CurContext); - debugln(' AddContext Descriptor=',dbgs(ord(Descriptor)),' Context="',Context,'"'); - end; - - procedure AddContextsBackwards(Tool: TCodeTool; - Node: TCodeTreeNode); - begin - if Node=nil then exit; - AddContextsBackwards(Tool,Node.Parent); - case Node.Desc of - ctnUnit, ctnPackage, ctnProgram, ctnLibrary: - AddContext(pihcSourceName,Tool.GetSourceName); - ctnVarDefinition: - AddContext(pihcVariable,Tool.ExtractDefinitionName(Node)); - ctnTypeDefinition: - AddContext(pihcType,Tool.ExtractDefinitionName(Node)); - ctnConstDefinition: - AddContext(pihcConst,Tool.ExtractDefinitionName(Node)); - ctnProperty: - AddContext(pihcProperty,Tool.ExtractPropName(Node,false)); - ctnProcedure: - AddContext(pihcProcedure,Tool.ExtractProcName(Node, - [phpWithoutClassName])); - ctnProcedureHead: - AddContext(pihcParameterList,''); - end; - end; - - var - MainCodeBuffer: TCodeBuffer; - Tool: TCustomCodeTool; - CleanPos: integer; - i: Integer; - Node: TCodeTreeNode; - IncludeChain: TFPList; - ConversionResult: LongInt; - begin - Result:=nil; - // find code buffer - if ACodePos^.Code=nil then begin - debugln('WARNING: ConvertCodePosToPascalHelpContext ACodePos.Code=nil'); - exit; - end; - Result:=TPascalHelpContextList.Create; - // add filename and all filenames of the include chain - IncludeChain:=nil; - try - CodeToolBoss.GetIncludeCodeChain(ACodePos^.Code,true,IncludeChain); - if IncludeChain=nil then begin - debugln('WARNING: ConvertCodePosToPascalHelpContext IncludeChain=nil'); - exit; - end; - for i:=0 to IncludeChain.Count-1 do - AddContext(pihcFilename,TCodeBuffer(IncludeChain[i]).Filename); - MainCodeBuffer:=TCodeBuffer(IncludeChain[0]); - finally - IncludeChain.Free; - end; - // find code tool - Tool:=CodeToolBoss.FindCodeToolForSource(MainCodeBuffer); - if not (Tool is TCodeTool) then begin - debugln('WARNING: ConvertCodePosToPascalHelpContext not (Tool is TCodeTool) MainCodeBuffer=',MainCodeBuffer.Filename); - exit; - end; - // convert cursor position to clean position - ConversionResult:=Tool.CaretToCleanPos(ACodePos^,CleanPos); - if ConversionResult<>0 then begin - // position not in clean code, maybe a comment, maybe behind last line - // => ignore - exit; - end; - // find node - Node:=Tool.FindDeepestNodeAtPos(CleanPos,false); - if Node=nil then begin - // position not in a scanned pascal node, maybe in between - // => ignore - exit; - end; - AddContextsBackwards(TCodeTool(Tool),Node); - end; - procedure CollectDeclarations(CodeBuffer: TCodeBuffer); var NewList: TPascalHelpContextList; @@ -617,7 +537,7 @@ function THelpManager.ShowHelpForSourcePosition(const Filename: string; try // get all possible declarations of this identifier if CodeToolBoss.FindDeclarationAndOverload(CodeBuffer,CodePos.X,CodePos.Y, - ListOfPCodeXYPosition) then + ListOfPCodeXYPosition,[fdlfWithoutEmptyProperties]) then begin debugln('THelpManager.ShowHelpForSourcePosition B Success ',dbgs(ListOfPCodeXYPosition.Count)); // convert the source positions in pascal help context list @@ -668,6 +588,99 @@ begin CollectDeclarations(CodeBuffer); end; +function THelpManager.ConvertCodePosToPascalHelpContext( + ACodePos: PCodeXYPosition): TPascalHelpContextList; + + procedure AddContext(Descriptor: TPascalHelpContextType; + const Context: string); + var + CurContext: TPascalHelpContext; + begin + CurContext.Descriptor:=Descriptor; + CurContext.Context:=Context; + Result.Add(CurContext); + //debugln(' AddContext Descriptor=',dbgs(ord(Descriptor)),' Context="',Context,'"'); + end; + + procedure AddContextsBackwards(Tool: TCodeTool; + Node: TCodeTreeNode); + begin + if Node=nil then exit; + AddContextsBackwards(Tool,Node.Parent); + case Node.Desc of + ctnUnit, ctnPackage, ctnProgram, ctnLibrary: + AddContext(pihcSourceName,Tool.GetSourceName); + ctnVarDefinition: + AddContext(pihcVariable,Tool.ExtractDefinitionName(Node)); + ctnTypeDefinition: + AddContext(pihcType,Tool.ExtractDefinitionName(Node)); + ctnConstDefinition: + AddContext(pihcConst,Tool.ExtractDefinitionName(Node)); + ctnProperty: + AddContext(pihcProperty,Tool.ExtractPropName(Node,false)); + ctnProcedure: + AddContext(pihcProcedure,Tool.ExtractProcName(Node, + [phpWithoutClassName])); + ctnProcedureHead: + AddContext(pihcParameterList,Tool.ExtractProcHead(Node, + [phpWithoutClassKeyword,phpWithoutClassName,phpWithoutName, + phpWithoutSemicolon])); + end; + end; + +var + MainCodeBuffer: TCodeBuffer; + Tool: TCustomCodeTool; + CleanPos: integer; + i: Integer; + Node: TCodeTreeNode; + IncludeChain: TFPList; + ConversionResult: LongInt; +begin + Result:=nil; + // find code buffer + if ACodePos^.Code=nil then begin + debugln('WARNING: ConvertCodePosToPascalHelpContext ACodePos.Code=nil'); + exit; + end; + Result:=TPascalHelpContextList.Create; + // add filename and all filenames of the include chain + IncludeChain:=nil; + try + CodeToolBoss.GetIncludeCodeChain(ACodePos^.Code,true,IncludeChain); + if IncludeChain=nil then begin + debugln('WARNING: ConvertCodePosToPascalHelpContext IncludeChain=nil'); + exit; + end; + for i:=0 to IncludeChain.Count-1 do + AddContext(pihcFilename,TCodeBuffer(IncludeChain[i]).Filename); + MainCodeBuffer:=TCodeBuffer(IncludeChain[0]); + finally + IncludeChain.Free; + end; + // find code tool + Tool:=CodeToolBoss.FindCodeToolForSource(MainCodeBuffer); + if not (Tool is TCodeTool) then begin + debugln('WARNING: ConvertCodePosToPascalHelpContext not (Tool is TCodeTool) MainCodeBuffer=',MainCodeBuffer.Filename); + exit; + end; + // convert cursor position to clean position + ConversionResult:=Tool.CaretToCleanPos(ACodePos^,CleanPos); + if ConversionResult<>0 then begin + // position not in clean code, maybe a comment, maybe behind last line + // => ignore + exit; + end; + // find node + Node:=Tool.FindDeepestNodeAtPos(CleanPos,false); + if Node=nil then begin + // position not in a scanned pascal node, maybe in between + // => ignore + exit; + end; + AddContextsBackwards(TCodeTool(Tool),Node); +end; + procedure THelpManager.ShowHelpForMessage(Line: integer); function ParseMessage(MsgItem: TIDEMessageLine): TStringList; @@ -720,6 +733,23 @@ begin end; end; +function THelpManager.ConvertSourcePosToPascalHelpContext( + const CaretPos: TPoint; const Filename: string): TPascalHelpContextList; +var + CodePos: TCodeXYPosition; + Code: TCodeBuffer; + ACodeTool: TCodeTool; +begin + Result:=nil; + Code:=CodeToolBoss.FindFile(Filename); + if Code=nil then exit; + CodePos.Code:=Code; + CodePos.X:=CaretPos.X; + CodePos.Y:=CaretPos.Y; + if not CodeToolBoss.Explore(Code,ACodeTool,false) then exit; + Result:=ConvertCodePosToPascalHelpContext(@CodePos); +end; + initialization {$i helpmanager.lrs} diff --git a/ide/ideprocs.pp b/ide/ideprocs.pp index 70cb806b77..0b9e60987e 100644 --- a/ide/ideprocs.pp +++ b/ide/ideprocs.pp @@ -183,8 +183,11 @@ function CrossReplaceChars(const Src: string; PrefixChar: char; function SimpleSyntaxToRegExpr(const Src: string): string; function NameToValidIdentifier(const s: string): string; function BinaryStrToText(const s: string): string; -function SplitString(const s: string; Delimiter: char): TStringList; +function SplitString(const s: string; Delimiter: char): TStrings; +procedure SplitString(const s: string; Delimiter: char; AddTo: TStrings; + ClearList: boolean = true); function SpecialCharsToSpaces(const s: string): string; +function LineBreaksToDelimiter(const s: string; Delimiter: char): string; function StringListToText(List: TStrings; const Delimiter: string; IgnoreEmptyLines: boolean = false): string; @@ -1471,6 +1474,30 @@ begin //DebugLn('TabsToSpaces ',dbgs(length(Result))); end; +procedure SplitString(const s: string; Delimiter: char; AddTo: TStrings; + ClearList: boolean); +var + SLen: Integer; + StartPos: Integer; + EndPos: Integer; +begin + if ClearList then AddTo.Clear; + SLen:=length(s); + StartPos:=1; + EndPos:=1; + repeat + if (EndPos<=sLen) and (s[EndPos]<>Delimiter) then + inc(EndPos) + else begin + if EndPos>StartPos then + AddTo.Add(copy(s,StartPos,EndPos-StartPos)); + StartPos:=EndPos+1; + if StartPos>sLen then exit; + inc(EndPos); + end; + until false; +end; + {------------------------------------------------------------------------------- function SpecialCharsToSpaces(const s: string): string; -------------------------------------------------------------------------------} @@ -1486,6 +1513,29 @@ begin Result:=Trim(Result); end; +function LineBreaksToDelimiter(const s: string; Delimiter: char): string; +var + p: Integer; + StartPos: LongInt; +begin + Result:=s; + p:=1; + while (p<=length(Result)) do begin + if Result[p] in [#10,#13] then begin + StartPos:=p; + repeat + inc(p); + until (p>length(Result)) or (not (Result[p] in [#10,#13])); + if p<=length(Result) then + Result:=copy(Result,1,StartPos-1)+Delimiter+copy(Result,p,length(Result)) + else + Result:=copy(Result,1,StartPos-1); + end else begin + inc(p); + end; + end; +end; + function StringListToText(List: TStrings; const Delimiter: string; IgnoreEmptyLines: boolean): string; var @@ -1602,29 +1652,12 @@ begin end; {------------------------------------------------------------------------------- - function SplitString(const s: string; Delimiter: char): TStringList; + function SplitString(const s: string; Delimiter: char): TStrings; -------------------------------------------------------------------------------} -function SplitString(const s: string; Delimiter: char): TStringList; -var - SLen: Integer; - StartPos: Integer; - EndPos: Integer; +function SplitString(const s: string; Delimiter: char): TStrings; begin Result:=TStringList.Create; - SLen:=length(s); - StartPos:=1; - EndPos:=1; - repeat - if (EndPos<=sLen) and (s[EndPos]<>Delimiter) then - inc(EndPos) - else begin - if EndPos>StartPos then - Result.Add(copy(s,StartPos,EndPos-StartPos)); - StartPos:=EndPos+1; - if StartPos>sLen then exit; - inc(EndPos); - end; - until false; + SplitString(s,Delimiter,Result,false); end; {------------------------------------------------------------------------------- diff --git a/ide/lazdocfrm.lfm b/ide/lazdocfrm.lfm index 2540630112..230d057876 100644 --- a/ide/lazdocfrm.lfm +++ b/ide/lazdocfrm.lfm @@ -4,8 +4,9 @@ object LazDocForm: TLazDocForm ClientHeight = 117 ClientWidth = 753 OnCreate = FormCreate + OnDestroy = FormDestroy OnResize = FormResize - PixelsPerInch = 96 + PixelsPerInch = 95 HorzScrollBar.Page = 752 VertScrollBar.Page = 116 Left = 390 @@ -23,27 +24,30 @@ object LazDocForm: TLazDocForm Width = 736 object ShortTabSheet: TTabSheet Caption = 'ShortTabSheet' - ClientHeight = 91 - ClientWidth = 728 - Height = 91 - Width = 728 + ClientHeight = 87 + ClientWidth = 732 + Left = 2 + Height = 87 + Top = 2 + Width = 732 object ShortEdit: TEdit Align = alTop - BorderSpacing.OnChange = nil BorderSpacing.Right = 2 OnChange = DocumentationTagChange TabOrder = 0 Text = 'ShortEdit' Height = 23 - Width = 726 + Width = 730 end end object DescrTabSheet: TTabSheet Caption = 'DescrTabSheet' - ClientHeight = 91 - ClientWidth = 728 - Height = 91 - Width = 728 + ClientHeight = 87 + ClientWidth = 732 + Left = 2 + Height = 87 + Top = 2 + Width = 732 object DescrMemo: TMemo Align = alClient BorderSpacing.Right = 2 @@ -53,19 +57,20 @@ object LazDocForm: TLazDocForm ) OnChange = DocumentationTagChange TabOrder = 0 - Height = 87 - Width = 726 + Height = 83 + Width = 730 end end object ErrorsTabSheet: TTabSheet Caption = 'ErrorsTabSheet' - ClientHeight = 91 - ClientWidth = 728 - Height = 91 - Width = 728 + ClientHeight = 87 + ClientWidth = 732 + Left = 2 + Height = 87 + Top = 2 + Width = 732 object ErrorsMemo: TMemo Align = alClient - BorderSpacing.OnChange = nil BorderSpacing.Right = 2 BorderSpacing.Bottom = 4 Lines.Strings = ( @@ -73,56 +78,55 @@ object LazDocForm: TLazDocForm ) OnChange = DocumentationTagChange TabOrder = 0 - Height = 87 - Width = 726 + Height = 83 + Width = 730 end end object SeeAlsoTabSheet: TTabSheet Caption = 'SeeAlsoTabSheet' - ClientHeight = 91 - ClientWidth = 728 - Height = 91 - Width = 728 + ClientHeight = 87 + ClientWidth = 732 + Left = 2 + Height = 87 + Top = 2 + Width = 732 object LinkListBox: TListBox Align = alBottom Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.OnChange = nil BorderSpacing.Right = 2 BorderSpacing.Bottom = 4 OnClick = LinkListBoxClick TabOrder = 0 - Height = 60 + TopIndex = -1 + Height = 56 Top = 27 - Width = 726 + Width = 730 end object AddLinkButton: TButton Anchors = [akTop, akRight] AutoSize = True - BorderSpacing.OnChange = nil BorderSpacing.Right = 6 BorderSpacing.InnerBorder = 2 Caption = 'AddLinkButton' OnClick = AddLinkButtonClick TabOrder = 1 AnchorSideRight.Control = DeleteLinkButton - Left = 570 + Left = 574 Height = 23 Width = 75 end object DeleteLinkButton: TButton Anchors = [akTop, akRight] AutoSize = True - BorderSpacing.OnChange = nil BorderSpacing.InnerBorder = 2 Caption = 'DeleteLinkButton' OnClick = DeleteLinkButtonClick TabOrder = 2 - Left = 651 + Left = 655 Height = 23 Width = 75 end object LinkTextEdit: TEdit - BorderSpacing.OnChange = nil OnChange = LinkChange TabOrder = 3 Text = 'LinkTextEdit' @@ -132,6 +136,7 @@ object LazDocForm: TLazDocForm Width = 328 end object LinkIdComboBox: TComboBox + AutoCompleteText = [cbactEndOfLineComplete, cbactSearchAscending] MaxLength = 0 OnChange = LinkChange TabOrder = 4 @@ -143,29 +148,29 @@ object LazDocForm: TLazDocForm end object ExampleTabSheet: TTabSheet Caption = 'ExampleTabSheet' - ClientHeight = 91 - ClientWidth = 728 - Height = 91 - Width = 728 + ClientHeight = 87 + ClientWidth = 732 + Left = 2 + Height = 87 + Top = 2 + Width = 732 object ExampleEdit: TEdit Align = alTop - BorderSpacing.OnChange = nil BorderSpacing.Right = 2 OnChange = DocumentationTagChange TabOrder = 0 Text = 'ExampleEdit' Height = 23 - Width = 726 + Width = 730 end object BrowseExampleButton: TButton Anchors = [akTop, akRight] AutoSize = True - BorderSpacing.OnChange = nil BorderSpacing.InnerBorder = 2 Caption = 'BrowseExampleButton' OnClick = BrowseExampleButtonClick TabOrder = 1 - Left = 651 + Left = 655 Height = 25 Top = 28 Width = 75 @@ -174,7 +179,6 @@ object LazDocForm: TLazDocForm end object Panel1: TPanel Align = alLeft - BorderSpacing.OnChange = nil BevelOuter = bvNone ClientHeight = 117 ClientWidth = 17 @@ -186,7 +190,7 @@ object LazDocForm: TLazDocForm Width = 17 object BoldFormatButton: TSpeedButton Align = alTop - BorderSpacing.OnChange = nil + Color = clBtnFace Glyph.Data = { B20100002F2A2058504D202A2F0A7374617469632063686172202A6772617068 69635B5D203D207B0A22313720313720322031222C0A222E2063204E6F6E6522 @@ -210,7 +214,7 @@ object LazDocForm: TLazDocForm end object ItalicFormatButton: TSpeedButton Align = alTop - BorderSpacing.OnChange = nil + Color = clBtnFace Glyph.Data = { C10100002F2A2058504D202A2F0A7374617469632063686172202A6772617068 69635B5D203D207B0A22313720313720332031222C0A222E2063204E6F6E6522 @@ -237,7 +241,7 @@ object LazDocForm: TLazDocForm end object UnderlineFormatButton: TSpeedButton Align = alTop - BorderSpacing.OnChange = nil + Color = clBtnFace Glyph.Data = { C10100002F2A2058504D202A2F0A7374617469632063686172202A6772617068 69635B5D203D207B0A22313720313720332031222C0A222E2063204E6F6E6522 @@ -264,6 +268,7 @@ object LazDocForm: TLazDocForm end object InsertCodeTagButton: TSpeedButton Align = alTop + Color = clBtnFace Glyph.Data = { F90900002F2A2058504D202A2F0D0A7374617469632063686172202A20496E73 657274436F64655461675F78706D5B5D203D207B0D0A22313720313520313132 @@ -355,6 +360,7 @@ object LazDocForm: TLazDocForm end object InsertRemarkButton: TSpeedButton Align = alTop + Color = clBtnFace Glyph.Data = { D60100002F2A2058504D202A2F0D0A7374617469632063686172202A20496E73 65727452656D61726B5F78706D5B5D203D207B0D0A2231372031372032203122 @@ -381,6 +387,7 @@ object LazDocForm: TLazDocForm end object InsertVarTagButton: TSpeedButton Align = alTop + Color = clBtnFace Glyph.Data = { D70200002F2A2058504D202A2F0D0A7374617469632063686172202A20496E73 6572745661725461675F78706D5B5D203D207B0D0A2231372031372031382031 diff --git a/ide/lazdocfrm.lrs b/ide/lazdocfrm.lrs index 231086b34d..f1e4c64527 100644 --- a/ide/lazdocfrm.lrs +++ b/ide/lazdocfrm.lrs @@ -3,168 +3,168 @@ LazarusResources.Add('TLazDocForm','FORMDATA',[ 'TPF0'#11'TLazDocForm'#10'LazDocForm'#11'BorderStyle'#7#13'bsSizeToolWin'#7'C' +'aption'#6#13'LazDoc editor'#12'ClientHeight'#2'u'#11'ClientWidth'#3#241#2#8 - +'OnCreate'#7#10'FormCreate'#8'OnResize'#7#10'FormResize'#13'PixelsPerInch'#2 - +'`'#18'HorzScrollBar.Page'#3#240#2#18'VertScrollBar.Page'#2't'#4'Left'#3#134 - +#1#6'Height'#2'u'#3'Top'#3'p'#2#5'Width'#3#241#2#0#12'TPageControl'#11'PageC' - +'ontrol'#10'ActivePage'#7#14'ErrorsTabSheet'#5'Align'#7#8'alClient'#8'TabInd' - +'ex'#2#2#8'TabOrder'#2#0#11'TabPosition'#7#8'tpBottom'#4'Left'#2#17#6'Height' - +#2'u'#5'Width'#3#224#2#0#9'TTabSheet'#13'ShortTabSheet'#7'Caption'#6#13'Shor' - +'tTabSheet'#12'ClientHeight'#2'['#11'ClientWidth'#3#216#2#6'Height'#2'['#5'W' - +'idth'#3#216#2#0#5'TEdit'#9'ShortEdit'#5'Align'#7#5'alTop'#22'BorderSpacing.' - +'OnChange'#13#19'BorderSpacing.Right'#2#2#8'OnChange'#7#22'DocumentationTagC' - +'hange'#8'TabOrder'#2#0#4'Text'#6#9'ShortEdit'#6'Height'#2#23#5'Width'#3#214 - +#2#0#0#0#9'TTabSheet'#13'DescrTabSheet'#7'Caption'#6#13'DescrTabSheet'#12'Cl' - +'ientHeight'#2'['#11'ClientWidth'#3#216#2#6'Height'#2'['#5'Width'#3#216#2#0#5 - +'TMemo'#9'DescrMemo'#5'Align'#7#8'alClient'#19'BorderSpacing.Right'#2#2#20'B' - +'orderSpacing.Bottom'#2#4#13'Lines.Strings'#1#6#9'DescrMemo'#0#8'OnChange'#7 - +#22'DocumentationTagChange'#8'TabOrder'#2#0#6'Height'#2'W'#5'Width'#3#214#2#0 - +#0#0#9'TTabSheet'#14'ErrorsTabSheet'#7'Caption'#6#14'ErrorsTabSheet'#12'Clie' - +'ntHeight'#2'['#11'ClientWidth'#3#216#2#6'Height'#2'['#5'Width'#3#216#2#0#5 - +'TMemo'#10'ErrorsMemo'#5'Align'#7#8'alClient'#22'BorderSpacing.OnChange'#13 - +#19'BorderSpacing.Right'#2#2#20'BorderSpacing.Bottom'#2#4#13'Lines.Strings'#1 - +#6#10'ErrorsMemo'#0#8'OnChange'#7#22'DocumentationTagChange'#8'TabOrder'#2#0 - +#6'Height'#2'W'#5'Width'#3#214#2#0#0#0#9'TTabSheet'#15'SeeAlsoTabSheet'#7'Ca' - +'ption'#6#15'SeeAlsoTabSheet'#12'ClientHeight'#2'['#11'ClientWidth'#3#216#2#6 - +'Height'#2'['#5'Width'#3#216#2#0#8'TListBox'#11'LinkListBox'#5'Align'#7#8'al' - +'Bottom'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#8'akBottom'#0#22'Border' - +'Spacing.OnChange'#13#19'BorderSpacing.Right'#2#2#20'BorderSpacing.Bottom'#2 - +#4#7'OnClick'#7#16'LinkListBoxClick'#8'TabOrder'#2#0#6'Height'#2'<'#3'Top'#2 - +#27#5'Width'#3#214#2#0#0#7'TButton'#13'AddLinkButton'#7'Anchors'#11#5'akTop' - +#7'akRight'#0#8'AutoSize'#9#22'BorderSpacing.OnChange'#13#19'BorderSpacing.R' - +'ight'#2#6#25'BorderSpacing.InnerBorder'#2#2#7'Caption'#6#13'AddLinkButton'#7 - +'OnClick'#7#18'AddLinkButtonClick'#8'TabOrder'#2#1#23'AnchorSideRight.Contro' - +'l'#7#16'DeleteLinkButton'#4'Left'#3':'#2#6'Height'#2#23#5'Width'#2'K'#0#0#7 - +'TButton'#16'DeleteLinkButton'#7'Anchors'#11#5'akTop'#7'akRight'#0#8'AutoSiz' - +'e'#9#22'BorderSpacing.OnChange'#13#25'BorderSpacing.InnerBorder'#2#2#7'Capt' - +'ion'#6#16'DeleteLinkButton'#7'OnClick'#7#21'DeleteLinkButtonClick'#8'TabOrd' - +'er'#2#2#4'Left'#3#139#2#6'Height'#2#23#5'Width'#2'K'#0#0#5'TEdit'#12'LinkTe' - +'xtEdit'#22'BorderSpacing.OnChange'#13#8'OnChange'#7#10'LinkChange'#8'TabOrd' - +'er'#2#3#4'Text'#6#12'LinkTextEdit'#4'Left'#3#235#0#6'Height'#2#21#3'Top'#2#1 - +#5'Width'#3'H'#1#0#0#9'TComboBox'#14'LinkIdComboBox'#9'MaxLength'#2#0#8'OnCh' - +'ange'#7#10'LinkChange'#8'TabOrder'#2#4#4'Text'#6#14'LinkIdComboBox'#6'Heigh' - +'t'#2#21#3'Top'#2#1#5'Width'#3#227#0#0#0#0#9'TTabSheet'#15'ExampleTabSheet'#7 - +'Caption'#6#15'ExampleTabSheet'#12'ClientHeight'#2'['#11'ClientWidth'#3#216#2 - +#6'Height'#2'['#5'Width'#3#216#2#0#5'TEdit'#11'ExampleEdit'#5'Align'#7#5'alT' - +'op'#22'BorderSpacing.OnChange'#13#19'BorderSpacing.Right'#2#2#8'OnChange'#7 - +#22'DocumentationTagChange'#8'TabOrder'#2#0#4'Text'#6#11'ExampleEdit'#6'Heig' - +'ht'#2#23#5'Width'#3#214#2#0#0#7'TButton'#19'BrowseExampleButton'#7'Anchors' - +#11#5'akTop'#7'akRight'#0#8'AutoSize'#9#22'BorderSpacing.OnChange'#13#25'Bor' - +'derSpacing.InnerBorder'#2#2#7'Caption'#6#19'BrowseExampleButton'#7'OnClick' - +#7#24'BrowseExampleButtonClick'#8'TabOrder'#2#1#4'Left'#3#139#2#6'Height'#2 - +#25#3'Top'#2#28#5'Width'#2'K'#0#0#0#0#6'TPanel'#6'Panel1'#5'Align'#7#6'alLef' - +'t'#22'BorderSpacing.OnChange'#13#10'BevelOuter'#7#6'bvNone'#12'ClientHeight' - +#2'u'#11'ClientWidth'#2#17#11'FullRepaint'#8#14'ParentShowHint'#8#8'ShowHint' - +#9#8'TabOrder'#2#1#6'Height'#2'u'#5'Width'#2#17#0#12'TSpeedButton'#16'BoldFo' - +'rmatButton'#5'Align'#7#5'alTop'#22'BorderSpacing.OnChange'#13#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'#6'H' - +'eight'#2#17#5'Width'#2#17#0#0#12'TSpeedButton'#18'ItalicFormatButton'#5'Ali' - ,'gn'#7#5'alTop'#22'BorderSpacing.OnChange'#13#10'Glyph.Data'#10#197#1#0#0#193 - +#1#0#0'/* XPM */'#10'static char *graphic[] = {'#10'"17 17 3 1",'#10'". c No' - +'ne",'#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'#6 - +'Height'#2#17#3'Top'#2#17#5'Width'#2#17#3'Tag'#2#1#0#0#12'TSpeedButton'#21'U' - +'nderlineFormatButton'#5'Align'#7#5'alTop'#22'BorderSpacing.OnChange'#13#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'#6'Height'#2#17#3'Top'#2'"'#5'Width'#2#17#3'Tag'#2#2 - +#0#0#12'TSpeedButton'#19'InsertCodeTagButton'#5'Align'#7#5'alTop'#10'Glyph.D' - +'ata'#10#253#9#0#0#249#9#0#0'/* XPM */'#13#10'static char * InsertCodeTag_xp' - +'m[] = {'#13#10'"17 15 112 2",'#13#10'" '#9'c None",'#13#10'". '#9'c #ECE9D' - +'8",'#13#10'"+ '#9'c #FFF0CF",'#13#10'"@ '#9'c #FFEDC5",'#13#10'"# '#9'c #FB' - +'E8C5",'#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 #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 #7C60' - +'38",'#13#10'"3 '#9'c #9C7749",'#13#10'"4 '#9'c #866340",'#13#10'"5 '#9'c #B' - +'A8D59",'#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 #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 #EEEA' - +'E0",'#13#10'"v '#9'c #AB7A53",'#13#10'"w '#9'c #745438",'#13#10'"x '#9'c #A' - +'77B50",'#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 #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 #8162' - +'3E",'#13#10'"Y '#9'c #6D5234",'#13#10'"Z '#9'c #5F4D37",'#13#10'"` '#9'c #9' - +'78E85",'#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 #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'OnClick'#7#17'FormatButtonClick'#6'Height'#2#17#3 - +'Top'#2'3'#5'Width'#2#17#3'Tag'#2#3#0#0#12'TSpeedButton'#18'InsertRemarkButt' - +'on'#5'Align'#7#5'alTop'#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'NumGlyp' - +'hs'#2#0#7'OnClick'#7#17'FormatButtonClick'#6'Height'#2#17#3'Top'#2'D'#5'Wid' - +'th'#2#17#3'Tag'#2#4#0#0#12'TSpeedButton'#18'InsertVarTagButton'#5'Align'#7#5 - +'alTop'#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'#6'Height'#2#17#3'Top' - +#2'U'#5'Width'#2#17#3'Tag'#2#5#0#0#0#11'TOpenDialog'#10'OpenDialog'#5'Title' - +#6#17'Open example file'#6'Filter'#6#28'pascal file|*.pas; *.pp; *.p'#11'Fil' - +'terIndex'#2#0#5'Title'#6#17'Open example file'#4'left'#2'@'#3'top'#2#24#0#0 - +#0 + +'OnCreate'#7#10'FormCreate'#9'OnDestroy'#7#11'FormDestroy'#8'OnResize'#7#10 + +'FormResize'#13'PixelsPerInch'#2'_'#18'HorzScrollBar.Page'#3#240#2#18'VertSc' + +'rollBar.Page'#2't'#4'Left'#3#134#1#6'Height'#2'u'#3'Top'#3'p'#2#5'Width'#3 + +#241#2#0#12'TPageControl'#11'PageControl'#10'ActivePage'#7#14'ErrorsTabSheet' + +#5'Align'#7#8'alClient'#8'TabIndex'#2#2#8'TabOrder'#2#0#11'TabPosition'#7#8 + +'tpBottom'#4'Left'#2#17#6'Height'#2'u'#5'Width'#3#224#2#0#9'TTabSheet'#13'Sh' + +'ortTabSheet'#7'Caption'#6#13'ShortTabSheet'#12'ClientHeight'#2'W'#11'Client' + +'Width'#3#220#2#4'Left'#2#2#6'Height'#2'W'#3'Top'#2#2#5'Width'#3#220#2#0#5'T' + +'Edit'#9'ShortEdit'#5'Align'#7#5'alTop'#19'BorderSpacing.Right'#2#2#8'OnChan' + +'ge'#7#22'DocumentationTagChange'#8'TabOrder'#2#0#4'Text'#6#9'ShortEdit'#6'H' + +'eight'#2#23#5'Width'#3#218#2#0#0#0#9'TTabSheet'#13'DescrTabSheet'#7'Caption' + +#6#13'DescrTabSheet'#12'ClientHeight'#2'W'#11'ClientWidth'#3#220#2#4'Left'#2 + +#2#6'Height'#2'W'#3'Top'#2#2#5'Width'#3#220#2#0#5'TMemo'#9'DescrMemo'#5'Alig' + +'n'#7#8'alClient'#19'BorderSpacing.Right'#2#2#20'BorderSpacing.Bottom'#2#4#13 + +'Lines.Strings'#1#6#9'DescrMemo'#0#8'OnChange'#7#22'DocumentationTagChange'#8 + +'TabOrder'#2#0#6'Height'#2'S'#5'Width'#3#218#2#0#0#0#9'TTabSheet'#14'ErrorsT' + +'abSheet'#7'Caption'#6#14'ErrorsTabSheet'#12'ClientHeight'#2'W'#11'ClientWid' + +'th'#3#220#2#4'Left'#2#2#6'Height'#2'W'#3'Top'#2#2#5'Width'#3#220#2#0#5'TMem' + +'o'#10'ErrorsMemo'#5'Align'#7#8'alClient'#19'BorderSpacing.Right'#2#2#20'Bor' + +'derSpacing.Bottom'#2#4#13'Lines.Strings'#1#6#10'ErrorsMemo'#0#8'OnChange'#7 + +#22'DocumentationTagChange'#8'TabOrder'#2#0#6'Height'#2'S'#5'Width'#3#218#2#0 + +#0#0#9'TTabSheet'#15'SeeAlsoTabSheet'#7'Caption'#6#15'SeeAlsoTabSheet'#12'Cl' + +'ientHeight'#2'W'#11'ClientWidth'#3#220#2#4'Left'#2#2#6'Height'#2'W'#3'Top'#2 + +#2#5'Width'#3#220#2#0#8'TListBox'#11'LinkListBox'#5'Align'#7#8'alBottom'#7'A' + +'nchors'#11#5'akTop'#6'akLeft'#7'akRight'#8'akBottom'#0#19'BorderSpacing.Rig' + +'ht'#2#2#20'BorderSpacing.Bottom'#2#4#7'OnClick'#7#16'LinkListBoxClick'#8'Ta' + +'bOrder'#2#0#8'TopIndex'#2#255#6'Height'#2'8'#3'Top'#2#27#5'Width'#3#218#2#0 + +#0#7'TButton'#13'AddLinkButton'#7'Anchors'#11#5'akTop'#7'akRight'#0#8'AutoSi' + +'ze'#9#19'BorderSpacing.Right'#2#6#25'BorderSpacing.InnerBorder'#2#2#7'Capti' + +'on'#6#13'AddLinkButton'#7'OnClick'#7#18'AddLinkButtonClick'#8'TabOrder'#2#1 + +#23'AnchorSideRight.Control'#7#16'DeleteLinkButton'#4'Left'#3'>'#2#6'Height' + +#2#23#5'Width'#2'K'#0#0#7'TButton'#16'DeleteLinkButton'#7'Anchors'#11#5'akTo' + +'p'#7'akRight'#0#8'AutoSize'#9#25'BorderSpacing.InnerBorder'#2#2#7'Caption'#6 + +#16'DeleteLinkButton'#7'OnClick'#7#21'DeleteLinkButtonClick'#8'TabOrder'#2#2 + +#4'Left'#3#143#2#6'Height'#2#23#5'Width'#2'K'#0#0#5'TEdit'#12'LinkTextEdit'#8 + +'OnChange'#7#10'LinkChange'#8'TabOrder'#2#3#4'Text'#6#12'LinkTextEdit'#4'Lef' + +'t'#3#235#0#6'Height'#2#21#3'Top'#2#1#5'Width'#3'H'#1#0#0#9'TComboBox'#14'Li' + +'nkIdComboBox'#16'AutoCompleteText'#11#22'cbactEndOfLineComplete'#20'cbactSe' + +'archAscending'#0#9'MaxLength'#2#0#8'OnChange'#7#10'LinkChange'#8'TabOrder'#2 + +#4#4'Text'#6#14'LinkIdComboBox'#6'Height'#2#21#3'Top'#2#1#5'Width'#3#227#0#0 + +#0#0#9'TTabSheet'#15'ExampleTabSheet'#7'Caption'#6#15'ExampleTabSheet'#12'Cl' + +'ientHeight'#2'W'#11'ClientWidth'#3#220#2#4'Left'#2#2#6'Height'#2'W'#3'Top'#2 + +#2#5'Width'#3#220#2#0#5'TEdit'#11'ExampleEdit'#5'Align'#7#5'alTop'#19'Border' + +'Spacing.Right'#2#2#8'OnChange'#7#22'DocumentationTagChange'#8'TabOrder'#2#0 + +#4'Text'#6#11'ExampleEdit'#6'Height'#2#23#5'Width'#3#218#2#0#0#7'TButton'#19 + +'BrowseExampleButton'#7'Anchors'#11#5'akTop'#7'akRight'#0#8'AutoSize'#9#25'B' + +'orderSpacing.InnerBorder'#2#2#7'Caption'#6#19'BrowseExampleButton'#7'OnClic' + +'k'#7#24'BrowseExampleButtonClick'#8'TabOrder'#2#1#4'Left'#3#143#2#6'Height' + +#2#25#3'Top'#2#28#5'Width'#2'K'#0#0#0#0#6'TPanel'#6'Panel1'#5'Align'#7#6'alL' + +'eft'#10'BevelOuter'#7#6'bvNone'#12'ClientHeight'#2'u'#11'ClientWidth'#2#17 + +#11'FullRepaint'#8#14'ParentShowHint'#8#8'ShowHint'#9#8'TabOrder'#2#1#6'Heig' + +'ht'#2'u'#5'Width'#2#17#0#12'TSpeedButton'#16'BoldFormatButton'#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'NumGlyp' + +'hs'#2#0#7'OnClick'#7#17'FormatButtonClick'#6'Height'#2#17#5'Width'#2#17#0#0 + +#12'TSpeedButton'#18'ItalicFormatButton'#5'Align'#7#5'alTop'#5'Color'#7#9'cl' + ,'BtnFace'#10'Glyph.Data'#10#197#1#0#0#193#1#0#0'/* XPM */'#10'static char *g' + +'raphic[] = {'#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'#6'Height'#2#17#3'Top'#2#17#5'Width'#2 + +#17#3'Tag'#2#1#0#0#12'TSpeedButton'#21'UnderlineFormatButton'#5'Align'#7#5'a' + +'lTop'#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'#6'Height'#2#17 + +#3'Top'#2'"'#5'Width'#2#17#3'Tag'#2#2#0#0#12'TSpeedButton'#19'InsertCodeTagB' + +'utton'#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 #A8834A"' + +','#13#10'"^ '#9'c #977443",'#13#10'"/ '#9'c #B99052",'#13#10'"( '#9'c #9470' + +'47",'#13#10'"_ '#9'c #896842",'#13#10'": '#9'c #C4955E",'#13#10'"< '#9'c #8' + +'7653F",'#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 #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 #D3D3' + +'D3",'#13#10'"n '#9'c #CE9E60",'#13#10'"o '#9'c #755738",'#13#10'"p '#9'c #A' + +'77951",'#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 #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 #E8E8' + +'E8",'#13#10'"Q '#9'c #866B4D",'#13#10'"R '#9'c #8C6D49",'#13#10'"S '#9'c #6' + +'84F32",'#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 #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 #8F8' + +'B87",'#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'NumGlyph' + +'s'#2#0#7'OnClick'#7#17'FormatButtonClick'#6'Height'#2#17#3'Top'#2'3'#5'Widt' + +'h'#2#17#3'Tag'#2#3#0#0#12'TSpeedButton'#18'InsertRemarkButton'#5'Align'#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'#6'Height'#2#17#3'Top'#2'D' + +#5'Width'#2#17#3'Tag'#2#4#0#0#12'TSpeedButton'#18'InsertVarTagButton'#5'Alig' + +'n'#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'FormatButt' + +'onClick'#6'Height'#2#17#3'Top'#2'U'#5'Width'#2#17#3'Tag'#2#5#0#0#0#11'TOpen' + +'Dialog'#10'OpenDialog'#5'Title'#6#17'Open example file'#6'Filter'#6#28'pasc' + +'al file|*.pas; *.pp; *.p'#11'FilterIndex'#2#0#5'Title'#6#17'Open example fi' + +'le'#4'left'#2'@'#3'top'#2#24#0#0#0 ]); diff --git a/ide/lazdocfrm.pas b/ide/lazdocfrm.pas index d0af5cf2d0..f2768a8b6e 100644 --- a/ide/lazdocfrm.pas +++ b/ide/lazdocfrm.pas @@ -38,25 +38,14 @@ unit LazDocFrm; interface uses - Buttons, - Classes, - ComCtrls, - Controls, - Dialogs, - DOM, - ExtCtrls, - Forms, - Graphics, - IDEProcs, - LazarusIDEStrConsts, - LCLProc, - LResources, - StdCtrls, - StrUtils, + Classes, SysUtils, StrUtils, + LCLProc, LResources, StdCtrls, Buttons, ComCtrls, Controls, Dialogs, + ExtCtrls, Forms, Graphics, SynEdit, - SysUtils, - XMLread, - XMLwrite; + CodeToolManager, CodeCache, + Laz_DOM, Laz_XMLRead, Laz_XMLWrite, + HelpIntf, + IDEProcs, LazarusIDEStrConsts; const SHORT = 1; @@ -101,43 +90,42 @@ type procedure DeleteLinkButtonClick(Sender: TObject); procedure DocumentationTagChange(Sender: TObject); procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); procedure FormResize(Sender: TObject); procedure FormatButtonClick(Sender: TObject); procedure LinkChange(Sender: TObject); procedure LinkListBoxClick(Sender: TObject); private - { private declarations } - FLinkIndex: Integer; FChanged: Boolean; + FCurrentElement: TPascalHelpContextList; + FDoc: TXMLdocument; FDocFileName: String; - FCurrentElement: String; - FLastElement: String; - function GetModuleNode: TDOMNode; - function GetFirstElement: TDOMNode; - procedure GetElementList; - function MakeLink: String; - procedure SetDocFileName(Value: String); - procedure InsertElement(ElementName: String); - function NodeByName(ElementName: String): TDOMNode; - function GetFirstChildValue(n: TDOMNode): String; + FLinkIndex: Integer; function ElementFromNode(Node: TDOMNode): TFPDocNode; - function ExtractFuncProc(startpos: tpoint; keyword: String; + function ExtractFuncProc(const startpos: TPoint; const keyword: String; src: tStrings): String; - function GetNearestSourceElement(source: tStrings; - caretpos: tpoint): String; - procedure SetCaption; + function GetFirstChildValue(n: TDOMNode): String; + function GetFirstElement: TDOMNode; + function GetModuleNode: TDOMNode; + function GetNearestSourceElement(const SrcFilename: string; + const CaretPos: TPoint): TPascalHelpContextList; + function MakeLink: String; + function NodeByPascalContext(const AContext: TPascalHelpContextList): TDOMNode; + function GetElementName(const AContext: TPascalHelpContextList): string; + procedure GetElementList; + procedure InsertElement(const ElementName: String); procedure Save; + procedure SetDocFileName(const Value: String); + procedure UpdateCaption; public - { public declarations } procedure Reset; - procedure UpdateLazDoc(source: TStrings; pos: TPoint); + procedure UpdateLazDoc(const SrcFilename: string; const Caret: TPoint); property DocFileName: String read FDocFileName write SetDocFileName; + property Doc: TXMLdocument read FDoc; end; var LazDocForm: TLazDocForm; - doc: TXMLdocument = Nil; -//maybe better to make it a member field of TLazFormDoc procedure DoShowLazDoc; @@ -173,17 +161,17 @@ end; function TLazDocForm.GetFirstElement: TDOMNode; var - n: TDOMNode; + Node: TDOMNode; begin //get first module node - n := GetModuleNode; + Node := GetModuleNode; //proceed to element - n := n.FirstChild; - while n.NodeName <> 'element' do - n := n.NextSibling; + Node := Node.FirstChild; + while Node.NodeName <> 'element' do + Node := Node.NextSibling; - Result := n; + Result := Node; end; procedure TLazDocForm.GetElementList; @@ -220,13 +208,13 @@ begin end; end; -procedure TLazDocForm.SetDocFileName(Value: String); +procedure TLazDocForm.SetDocFileName(const Value: String); begin LinkIdComboBox.Clear; - if FileExists(Value) and (Value <> FDocFileName) then + if FileExistsCached(Value) and (Value <> FDocFileName) then begin - //reset Self + // reset Self Reset; FDocFileName := Value; @@ -236,7 +224,7 @@ begin ReadXMLFile(doc, FDocFileName); - SetCaption; + UpdateCaption; GetElementList; @@ -275,8 +263,12 @@ begin BrowseExampleButton.Caption := lisLazDocBrowseExampleButton; Reset; +end; - Resize; +procedure TLazDocForm.FormDestroy(Sender: TObject); +begin + FreeAndNil(fDoc); + FreeAndNil(FCurrentElement); end; procedure TLazDocForm.FormResize(Sender: TObject); @@ -355,7 +347,7 @@ begin LinkTextEdit.Text := Copy(strTmp, 1, Length(strTmp) - Length('')); end; -procedure TLazDocForm.InsertElement(ElementName: String); +procedure TLazDocForm.InsertElement(const ElementName: String); var n: TDOMNode; child: TDOMNode; @@ -384,46 +376,73 @@ begin WriteXMLFile(doc, FDocFileName); end; -function TLazDocForm.NodeByName(ElementName: String): TDOMNode; +function TLazDocForm.NodeByPascalContext( + const AContext: TPascalHelpContextList): TDOMNode; var - n: TDOMNode; + Node: TDOMNode; + ElementName: String; begin Result := Nil; - if not Assigned(doc) then - begin - {$ifdef dbgLazDoc} - DebugLn('TLazDocForm.NodeByName: document is not set'); - {$endif} + if not Assigned(doc) then Exit; - Exit; - end; + // get first element node + ElementName:=GetElementName(AContext); - //get first element node - n := GetFirstElement; + if ElementName='' then exit; + //DebugLn('TLazDocForm.NodeByPascalContext ElementName="',ElementName,'"'); - //search elements for ElementName - while Assigned(n) and (TDomElement(n)['name'] <> ElementName) do - begin - n := n.NextSibling; - - //no element found - if not Assigned(n) then + // search elements for ElementName + Node:=GetFirstElement; + while Node<>nil do begin + if (Node is TDomElement) + and (CompareText(TDomElement(Node).GetAttribute('name'),ElementName)=0) then begin + break; + end; + Node:=Node.NextSibling; + end; + + if Node=nil then begin + // no element found + if not Assigned(Node) then begin + // if there is no node, then fpdoc has not created an element InsertElement(ElementName); Exit; end; - - while n.NodeName = '#comment' do - n := n.NextSibling; end; {$ifdef dbgLazDoc} - DebugLn('TLazDocForm.NodeByName: element node found where name is: ' + + DebugLn('TLazDocForm.NodeByPascalContext: element node found where name is: ' + ElementName); {$endif} - Result := n; + Result := Node; +end; + +function TLazDocForm.GetElementName(const AContext: TPascalHelpContextList + ): string; +var + Level: Integer; +begin + // get first element node + Level:=0; + Result:=''; + while (Level'' then Result:=Result+'.'; + Result:=Result+AContext.Items[Level].Context; + end; + pihcFilename: ; + pihcSourceName: ; + else + DebugLn('TLazDocForm.NodeByPascalContext unsupported type: "',AContext.Items[Level].Context,'"'); + exit; // unsupported type + end; + inc(Level); + end; end; function TLazDocForm.GetFirstChildValue(n: TDOMNode): String; @@ -478,8 +497,8 @@ begin end; end; -function TLazDocForm.ExtractFuncProc(startpos: tpoint; - keyword: String; src: tStrings): String; +function TLazDocForm.ExtractFuncProc(const startpos: TPoint; + const keyword: String; src: tStrings): String; var xpos: Integer; ypos: Integer; @@ -501,57 +520,23 @@ begin end; end; -function TLazDocForm.GetNearestSourceElement(source: tStrings; - caretpos: tpoint): String; -var - xpos: Integer; - ypos: Integer; +function TLazDocForm.GetNearestSourceElement(const SrcFilename: string; + const CaretPos: TPoint): TPascalHelpContextList; begin - //find preceding keyword - xpos := Succ(caretpos.x); - ypos := caretpos.y; - while (xpos > 0) or (ypos > 0) do - begin - Dec(xpos); + Result:=LazarusHelp.ConvertSourcePosToPascalHelpContext(CaretPos,SrcFilename); - if xpos < 0 then - begin - Dec(ypos); - xpos := length(source[ypos]); - end; - - //check for keywords - if PosEx('procedure', source[ypos], xpos) = 1 then - begin - Result := ExtractFuncProc(Point(xpos, ypos), 'procedure', source); - Exit; - end; - if PosEx('function', source[ypos], xpos) = 1 then - begin - Result := ExtractFuncProc(Point(xpos, ypos), 'function', source); - Exit; - end; - if PosEx('constructor', source[ypos], xpos) = 1 then - begin - Result := ExtractFuncProc(Point(xpos, ypos), 'constructor', source); - Exit; - end; - if PosEx('desctructor', source[ypos], xpos) = 1 then - begin - Result := ExtractFuncProc(Point(xpos, ypos), 'desctructor', source); - Exit; - end; - end; + //if Result<>nil then + // DebugLn('TLazDocForm.GetNearestSourceElement Result=',Result.AsString); end; -procedure TLazDocForm.SetCaption; +procedure TLazDocForm.UpdateCaption; var strCaption: String; begin strCaption := lisLazDocMainFormCaption + ' - '; - if FCurrentElement <> '' then - strCaption := strCaption + FCurrentElement + ' - ' + if FCurrentElement <> nil then + strCaption := strCaption + GetElementName(FCurrentElement) + ' - ' else strCaption := strCaption + lisLazDocNoTagCaption + ' - '; @@ -564,9 +549,9 @@ end; procedure TLazDocForm.Reset; begin FreeAndNil(Doc); - FCurrentElement := ''; + FreeAndNil(FCurrentElement); FDocFileName := ''; - SetCaption; + UpdateCaption; //clear all element editors/viewers ShortEdit.Clear; @@ -580,11 +565,13 @@ begin FChanged := False; end; -procedure TLazDocForm.UpdateLazDoc(source: TStrings; pos: TPoint); +procedure TLazDocForm.UpdateLazDoc(const SrcFilename: string; + const Caret: TPoint); var dn: TFPDocNode; n: TDOMNode; EnabledState: Boolean; + NewElement: TPascalHelpContextList; begin if not Assigned(doc) then begin @@ -595,21 +582,22 @@ begin Exit; end; - //save the current changes to documentation + // save the current changes to documentation Save; - FCurrentElement := GetNearestSourceElement(source, pos); + NewElement:=GetNearestSourceElement(SrcFilename, Caret); + // avoid circles and overhead + if (NewElement<>nil) and (FCurrentElement<>nil) + and (NewElement.IsEqual(FCurrentElement)) then begin + NewElement.Free; + exit; + end; - //do not continue if FCurrentElement=FLastElement - //or FCurrentElement is empty (J. Reyes) - if (FCurrentElement = FLastElement) or (FCurrentElement = '') then - Exit; + FCurrentElement := NewElement; - SetCaption; + UpdateCaption; - FLastElement := FCurrentElement; - - n := NodeByName(FCurrentElement); + n := NodeByPascalContext(FCurrentElement); EnabledState := Assigned(n); @@ -675,7 +663,7 @@ end; procedure TLazDocForm.Save; var - n: TDOMNode; + Node: TDOMNode; S: String; NodeWritten: array [1..NODEITEMS] of Boolean; i: Integer; @@ -692,13 +680,13 @@ var if S = NodeName then begin - if not Assigned(n.FirstChild) then + if not Assigned(Node.FirstChild) then begin child := doc.CreateTextNode(ToUnixLineEnding(NodeText)); - n.AppendChild(child); + Node.AppendChild(child); end else - n.FirstChild.NodeValue := ToUnixLineEnding(NodeText); + Node.FirstChild.NodeValue := ToUnixLineEnding(NodeText); NodeWritten[NodeIndex] := True; end; end; @@ -714,30 +702,30 @@ var child := doc.CreateElement(ElementName); child.AppendChild(doc.CreateTextNode(ToUnixLineEnding(ElementText))); - n.AppendChild(child); + Node.AppendChild(child); end; begin - //nothing changed, so exit + // nothing changed, so exit if not FChanged then Exit; - n := NodeByName(FCurrentElement); + Node := NodeByPascalContext(FCurrentElement); - if not Assigned(n) then + if not Assigned(Node) then Exit; - //reset all nodes + // reset all nodes for i := 1 to NODEITEMS do NodeWritten[i] := False; - //write all known nodes to XML - n := n.FirstChild; - while Assigned(n) do + // write all known nodes to XML + Node := Node.FirstChild; + while Assigned(Node) do begin - if (n.NodeType = ELEMENT_NODE) then + if (Node.NodeType = ELEMENT_NODE) then begin - S := n.NodeName; + S := Node.NodeName; CheckAndWriteNode('short', ShortEdit.Text, SHORT); CheckAndWriteNode('descr', DescrMemo.Text, DESCR); @@ -746,11 +734,11 @@ begin CheckAndWriteNode('example', '', EXAMPLE); end; - n := n.NextSibling; + Node := Node.NextSibling; end; - //add new nodes to XML if not already updated - n := NodeByName(FCurrentElement); + // add new nodes to XML if not already updated + Node := NodeByPascalContext(FCurrentElement); for i := 1 to NODEITEMS do if NodeWritten[i] = False then case i of @@ -820,7 +808,4 @@ end; initialization {$I lazdocfrm.lrs} -finalization - FreeAndNil(doc) - end. diff --git a/ide/main.pp b/ide/main.pp index c666adf056..3881e3b5e0 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -214,6 +214,7 @@ type procedure mnuViewFormsClicked(Sender: TObject); procedure mnuViewUnitDependenciesClicked(Sender: TObject); procedure mnuViewUnitInfoClicked(Sender: TObject); + procedure mnuViewLazDocClicked(Sender: TObject); procedure mnuViewCodeExplorerClick(Sender: TObject); procedure mnuViewMessagesClick(Sender: TObject); procedure mnuViewSearchResultsClick(Sender: TObject); @@ -266,7 +267,6 @@ type procedure mnuToolGuessMisplacedIFDEFClicked(Sender: TObject); procedure mnuToolMakeResourceStringClicked(Sender: TObject); procedure mnuToolDiffClicked(Sender: TObject); - procedure mnuToolLazDocClicked(Sender: TObject); //DBlaszijk 5-sep-05 procedure mnuToolConvertDFMtoLFMClicked(Sender: TObject); procedure mnuToolCheckLFMClicked(Sender: TObject); procedure mnuToolConvertDelphiUnitClicked(Sender: TObject); @@ -1982,7 +1982,7 @@ begin itmViewInspector.OnClick := @mnuViewInspectorClicked; itmViewSourceEditor.OnClick := @mnuViewSourceEditorClicked; itmViewCodeExplorer.OnClick := @mnuViewCodeExplorerClick; - itmViewLazDoc.OnClick := @mnuToolLazDocClicked; //DBlaszijk 5-sep-05 + itmViewLazDoc.OnClick := @mnuViewLazDocClicked; //DBlaszijk 5-sep-05 itmViewUnits.OnClick := @mnuViewUnitsClicked; itmViewForms.OnClick := @mnuViewFormsClicked; itmViewUnitDependencies.OnClick := @mnuViewUnitDependenciesClicked; @@ -3208,8 +3208,7 @@ begin DoDiff; end; -//DBlaszijk 5-sep-05 -procedure TMainIDE.mnuToolLazDocClicked(Sender: TObject); +procedure TMainIDE.mnuViewLazDocClicked(Sender: TObject); begin SourceNotebook.ShowLazDoc; end; diff --git a/ide/project.pp b/ide/project.pp index 30a52ba152..1fc59ecd52 100644 --- a/ide/project.pp +++ b/ide/project.pp @@ -1628,7 +1628,7 @@ begin xmlconfig.SetDeleteValue(Path+'General/Title/Value', Title,''); //lazdoc - xmlconfig.SetValue(Path+'LazDoc/Paths', LazDocPathList.Text); + xmlconfig.SetDeleteValue(Path+'LazDoc/Paths', LazDocPaths, ''); // Save the compiler options CompilerOptions.SaveToXMLConfig(XMLConfig,'CompilerOptions/'); @@ -1973,7 +1973,7 @@ begin Title := xmlconfig.GetValue(Path+'General/Title/Value', ''); // Lazdoc - LazDocPathList.Text := xmlconfig.GetValue(Path+'LazDoc/Paths', ''); + LazDocPaths := xmlconfig.GetValue(Path+'LazDoc/Paths', ''); {$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject E reading comp sets');{$ENDIF} // Load the compiler options diff --git a/ide/projectopts.pp b/ide/projectopts.pp index e672fbe05a..b4dc8be9bc 100644 --- a/ide/projectopts.pp +++ b/ide/projectopts.pp @@ -38,7 +38,7 @@ interface uses Arrow, Buttons, LCLProc, Classes, CodeToolManager, Controls, Dialogs, ExtCtrls, Forms, Graphics, IDEOptionDefs, IDEWindowIntf, LazarusIDEStrConsts, - LCLIntf, LResources, Project, ProjectIntf, StdCtrls, SysUtils; + LCLIntf, LResources, Project, ProjectIntf, StdCtrls, SysUtils, IDEProcs; type @@ -293,7 +293,7 @@ begin AlwaysBuildCheckBox.Checked := (pfAlwaysBuild in AProject.Flags); //lazdoc - LazDocListBox.Items.Assign(Project.LazDocPathList); + SplitString(Project.LazDocPaths,';',LazDocListBox.Items,true); end; procedure TProjectOptionsDialog.ProjectOptionsClose(Sender: TObject; @@ -347,7 +347,8 @@ begin SetProjectTitle; //lazdoc - Project.LazDocPathList.Assign(LazDocListBox.Items); + + Project.LazDocPaths:=StringListToText(LazDocListBox.Items,';',true); end; IDEDialogLayoutList.SaveLayout(Self); diff --git a/ide/uniteditor.pp b/ide/uniteditor.pp index a5734938cd..ca379bbf46 100644 --- a/ide/uniteditor.pp +++ b/ide/uniteditor.pp @@ -50,7 +50,8 @@ uses SynEditTypes, SynEdit, SynRegExpr, SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion, // IDE interface - ProjectIntf, HelpIntf, SrcEditorIntf, MenuIntf, LazIDEIntf, IDEWindowIntf, + MacroIntf, ProjectIntf, HelpIntf, SrcEditorIntf, MenuIntf, LazIDEIntf, + IDEWindowIntf, // IDE units LazarusIDEStrConsts, LazConf, IDECommands, EditorOptions, KeyMapping, Project, WordCompletion, FindReplaceDialog, FindInFilesDlg, IDEProcs, IDEOptionDefs, @@ -567,9 +568,9 @@ type constructor Create(AOwner: TComponent); override; destructor Destroy; override; - procedure ShowLazDoc; //DBlaszijk 11-sep-05 - procedure UpdateLazDoc; //DBlaszijk 11-sep-05 - procedure LazDocNewPage; //DBlaszijk 11-sep-05 + procedure ShowLazDoc; + procedure UpdateLazDoc; + procedure LazDocNewPage; property Editors[Index:integer]:TSourceEditor read GetEditors; function EditorCount:integer; @@ -2812,52 +2813,70 @@ begin LazDocNewPage; end; -function FindPathFromFile(FileNamePath: string): string; +function FindLazDocPathFromFile(const AFileName: string): string; var i: integer; fn: string; - pathlist: TStrings; + SearchPaths: String; + PathList: TStrings; begin Result := ''; - pathlist := TStringList.Create; + if not FilenameIsAbsolute(AFileName) then exit; + if not FilenameIsPascalSource(AFileName) then exit; - //get global lazdoc paths - pathlist.AddStrings(EnvironmentOptions.LazDocPathList); - //get project lazdoc paths - pathlist.AddStrings(LazarusIDE.ActiveProject.LazDocPathList); - - fn := SetDirSeparators('/') + ChangeFileExt(ExtractFileName(FileNamePath), '.xml'); - for i:= 0 to Pred(pathlist.Count) do - if FileExists(pathlist[i] + fn) then - begin - Result := pathlist[i]; - pathlist.Free; - 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; - pathlist.Free; + //DebugLn('FindLazDocPathFromFile Result="',Result,'"'); end; procedure TSourceNotebook.LazDocNewPage; var SrcEdit: TSourceEditor; DocPath: string; + NewDocPath: string; begin - //try to find if the file belongs to LCL - //for other projects the location of the doc file could - //be found through the lpi file + //DebugLn('TSourceNotebook.LazDocNewPage ',dbgs(Assigned(LazDocForm))); if Assigned(LazDocForm) then begin SrcEdit:=GetActiveSE; + if SrcEdit=nil then exit; + + DocPath := FindLazDocPathFromFile(SrcEdit.FileName); - DocPath := FindPathFromFile(SrcEdit.FileName); - if DocPath <> '' then begin - //load the .xml file - LazDocForm.DocFileName := DocPath + SetDirSeparators('/') + + // load the .xml file + NewDocPath:=DocPath + PathDelim + ChangeFileExt(ExtractFileName(SrcEdit.FileName),'.xml'); - - UpdateLazDoc; + if NewDocPath<>LazDocForm.DocFileName then begin + LazDocForm.DocFileName := NewDocPath; + UpdateLazDoc; + end; end else LazDocForm.Reset; @@ -2870,19 +2889,17 @@ var DocPath: string; CaretPos: TPoint; begin + if LazDocForm = nil then exit; + SrcEdit:=GetActiveSE; - //find a path that contains the .xml file - DocPath := FindPathFromFile(SrcEdit.FileName); + // find a path that contains the .xml file + DocPath := FindLazDocPathFromFile(SrcEdit.FileName); if DocPath <> '' then begin CaretPos := SrcEdit.EditorComponent.CaretXY; - Dec(CaretPos.x); - Dec(CaretPos.y); - - LazDocForm.UpdateLazDoc(SrcEdit.EditorComponent.Lines, - CaretPos); + LazDocForm.UpdateLazDoc(SrcEdit.Filename,CaretPos); end else LazDocForm.Reset; @@ -5128,6 +5145,8 @@ begin Statusbar.Panels[3].Text := PanelFilename; end; Statusbar.EndUpdate; + + UpdateLazDoc; End; function TSourceNotebook.FindBookmark(BookmarkID: integer): TSourceEditor; @@ -5460,17 +5479,12 @@ begin FOnCtrlMouseUp(Sender,Button,Shift,X,Y); end; end; - if Assigned(LazDocForm) then - UpdateLazDoc; end; procedure TSourceNotebook.EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin - if not Assigned(LazDocForm) then Exit; - if Key in [VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_END, VK_HOME] then - UpdateLazDoc; end; procedure TSourceNotebook.ShowSynEditHint(const MousePos: TPoint); diff --git a/ideintf/helphtml.pas b/ideintf/helphtml.pas index e4494b8677..a0a77ed482 100644 --- a/ideintf/helphtml.pas +++ b/ideintf/helphtml.pas @@ -189,7 +189,8 @@ begin end else if (BasePathObject<>nil) and (Databases<>nil) then begin Result:=Databases.GetBaseURLForBasePathObject(BasePathObject); //debugln('THTMLHelpDatabase.GetEffectiveBaseURL using BasePathObject="',Result,'"'); - end else if DefaultBaseURL<>'' then begin + end; + if (Result='') and (DefaultBaseURL<>'') then begin Result:=DefaultBaseURL; if (IDEMacros<>nil) then IDEMacros.SubstituteMacros(Result); diff --git a/ideintf/helpintf.pas b/ideintf/helpintf.pas index fc56ba5629..07172e78f6 100644 --- a/ideintf/helpintf.pas +++ b/ideintf/helpintf.pas @@ -38,6 +38,7 @@ type TShowHelpResult = ( shrNone, shrSuccess, + shrCancel, shrDatabaseNotFound, shrContextNotFound, shrViewerNotFound, @@ -77,7 +78,6 @@ type TPascalHelpContextList = class(THelpQueryItem) private FCount: integer; - // TODO: convert to dynamic array, when fpc 1.0 support is removed. fItems: TPascalHelpContextPtr; function GetItems(Index: integer): TPascalHelpContext; public @@ -706,12 +706,16 @@ type var ErrMsg: string): TShowHelpResult; virtual; abstract; procedure ShowHelpForMessage(Line: integer); virtual; abstract; procedure ShowHelpForObjectInspector(Sender: TObject); virtual; abstract; + + function ConvertSourcePosToPascalHelpContext(const CaretPos: TPoint; + const Filename: string): TPascalHelpContextList; virtual; abstract; end; var HelpDatabases: THelpDatabases; // initialized by the IDE HelpViewers: THelpViewers; // initialized by the IDE + LazarusHelp: TBaseHelpManager; // initialized by the IDE //============================================================================== { Showing help (how it works): @@ -1540,9 +1544,9 @@ function THelpDatabases.GetBaseURLForBasePathObject(BasePathObject: TObject begin // this method will be overriden by the IDE // provide some useful defaults: - if (BasePathObject is THelpBaseURLObject) then - Result:=THelpBaseURLObject(BasePathObject).BaseURL - else begin + if (BasePathObject is THelpBaseURLObject) then begin + Result:=THelpBaseURLObject(BasePathObject).BaseURL; + end else begin // otherwise fetch a filename Result:=GetBaseDirectoryForBasePathObject(BasePathObject); if Result='' then exit; @@ -1927,10 +1931,10 @@ end; function THelpDatabases.ShowHelpSelector(Query: THelpQuery; Nodes: THelpNodeQueryList; var ErrMsg: string; var Selection: THelpNodeQuery): TShowHelpResult; +// to override // Nodes is a list of THelpNode begin Result:=shrSelectorError; - // TODO ErrMsg:='THelpDatabases.ShowHelpSelector not implemented'; end; @@ -2371,10 +2375,23 @@ begin end; function TPascalHelpContextList.AsString: string; +var + i: Integer; + Item: TPascalHelpContext; begin Result:=''; - if Count>0 then begin - Result:=fItems[0].Context; + for i:=0 to Count-1 do begin + Item:=Items[i]; + case Item.Descriptor of + pihcFilename: Result:=Result+Item.Context; + pihcSourceName: ; + pihcProperty: Result:=Result+' property '+Item.Context; + pihcProcedure: Result:=Result+' procedure/function '+Item.Context; + pihcParameterList: Result:=Result+Item.Context; + pihcVariable: Result:=Result+' var '+Item.Context; + pihcType: Result:=Result+' type '+Item.Context; + pihcConst: Result:=Result+' const '+Item.Context; + end; end; end; diff --git a/ideintf/projectintf.pas b/ideintf/projectintf.pas index 57f9ddd017..5d606475ee 100644 --- a/ideintf/projectintf.pas +++ b/ideintf/projectintf.pas @@ -506,7 +506,7 @@ type FSessionModified: boolean; fTitle: String; FSessionStorage: TProjectSessionStorage; - FLazDocPathList: TStrings; + FLazDocPaths: string; protected FFlags: TProjectFlags; procedure SetLazCompilerOptions(const AValue: TLazCompilerOptions); @@ -557,7 +557,7 @@ type write SetSessionModified; // project session data (not units, data), // units have their own SessionModified - property LazDocPathList: TStrings read FLazDocPathList; + property LazDocPaths: string read FLazDocPaths write FLazDocPaths; end; TLazProjectClass = class of TLazProject; @@ -1067,12 +1067,10 @@ constructor TLazProject.Create(ProjectDescription: TProjectDescriptor); begin inherited Create; FSessionStorage:=pssInProjectInfo; - FLazDocPathList := TStringList.Create; end; destructor TLazProject.Destroy; begin - FreeAndNil(FLazDocPathList); inherited Destroy; end; diff --git a/lcl/include/application.inc b/lcl/include/application.inc index 2396cc2246..b7c816e00b 100644 --- a/lcl/include/application.inc +++ b/lcl/include/application.inc @@ -1400,7 +1400,6 @@ begin if Assigned(FOnEndSession) then FOnEndSession(Self); end; - {------------------------------------------------------------------------------ procedure TApplication.IntfQueryEndSession(var Cancel : Boolean); ------------------------------------------------------------------------------} @@ -1410,8 +1409,6 @@ begin if Assigned(FOnQueryEndSession) then FOnQueryEndSession(Cancel); end; - - {------------------------------------------------------------------------------ procedure TApplication.DoBeforeMouseMessage(CurMouseControl: TControl); ------------------------------------------------------------------------------} @@ -1602,4 +1599,4 @@ function TApplication.UpdateAction(TheAction: TBasicAction): Boolean; begin Result := False; if Assigned(FOnActionUpdate) then FOnActionUpdate(TheAction,Result); -end; \ No newline at end of file +end; diff --git a/packager/packagesystem.pas b/packager/packagesystem.pas index 40a0fa50b7..80c723cfff 100644 --- a/packager/packagesystem.pas +++ b/packager/packagesystem.pas @@ -1724,7 +1724,8 @@ function TLazPackageGraph.FindFPCConflictUnit(APackage: TLazPackage; Cnt:=Pkg1.FileCount; for i:=0 to Cnt-1 do begin CurFile:=Pkg1.Files[i]; - if CurFile.FileType in (PkgFileUnitTypes-[pftVirtualUnit]) then begin + if (CurFile.FileType in (PkgFileUnitTypes-[pftVirtualUnit])) + and (pffAddToPkgUsesSection in CurFile.Flags) then begin Result:=CheckUnitName(CurFile.UnitName); if Result then begin File1:=CurFile;