Kaynağa Gözat

+ Added Topic support

michael 21 yıl önce
ebeveyn
işleme
433693deca
4 değiştirilmiş dosya ile 622 ekleme ve 165 silme
  1. 72 27
      utils/fpdoc/dglobals.pp
  2. 322 116
      utils/fpdoc/dw_html.pp
  3. 165 19
      utils/fpdoc/dw_latex.pp
  4. 63 3
      utils/fpdoc/dwriter.pp

+ 72 - 27
utils/fpdoc/dglobals.pp

@@ -73,6 +73,12 @@ resourcestring
   SDocValuesForEnum = 'Enumeration values for type %s';
   SDocSourcePosition = 'Source position: %s line %d';
 
+  // Topics
+  SDocRelatedTopics = 'Related topics';
+  SDocUp = 'Up';
+  SDocNext = 'Next';
+  SDocPrevious = 'Previous';
+  
 type
 
   // Assumes a list of TObject instances and frees them on destruction
@@ -132,6 +138,7 @@ type
     FSeeAlso: TDOMElement;
     FFirstExample: TDOMElement;
     FLink: String;
+    FTopicNode : Boolean;
   public
     constructor Create(const AName: String; ANode: TDOMElement);
     destructor Destroy; override;
@@ -151,6 +158,7 @@ type
     property SeeAlso: TDOMElement read FSeeAlso;
     property FirstExample: TDOMElement read FFirstExample;
     property Link: String read FLink;
+    Property TopicNode : Boolean Read FTopicNode;
   end;
 
 
@@ -848,7 +856,7 @@ begin
     exit;
   end;
 
-  if ALinkDest[1] = '#' then
+  if (ALinkDest[1] = '#') or (not assigned(AModule)) then
     Result := FindAbsoluteLink(ALinkDest)
   else
   begin
@@ -929,13 +937,31 @@ procedure TFPDocEngine.AddDocFile(const AFilename: String);
       Subnode := Subnode.NextSibling;
     end;
   end;
-
+  
+  Procedure ReadTopics(TopicNode : TDocNode);
+  
+  Var
+    SubNode : TDOMNode;
+    
+  begin
+    SubNode:=TopicNode.FNode.FirstChilD;
+    While Assigned(SubNode) do
+      begin
+      If (SubNode.NodeType=ELEMENT_NODE) and (SubNode.NodeName='topic') then
+        With ReadNode(TopicNode,TDomElement(SubNode)) do
+          // We could allow recursion here, but we won't, because it doesn't work on paper.
+          FTopicNode:=True;
+      SubNode:=Subnode.NextSibling;  
+      end;
+  end;
+  
 var
   i: Integer;
   Node, Subnode, Subsubnode: TDOMNode;
   Element: TDOMElement;
   Doc: TXMLDocument;
-  PackageDocNode, ModuleDocNode: TDocNode;
+  PackageDocNode, TopicNode,ModuleDocNode: TDocNode;
+  
 begin
   ReadXMLFile(Doc, AFilename);
   DescrDocs.Add(Doc);
@@ -943,30 +969,44 @@ begin
 
   Node := Doc.DocumentElement.FirstChild;
   while Assigned(Node) do
-  begin
-    if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'package') then
     begin
+    if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'package') then
+      begin
       PackageDocNode := ReadNode(RootDocNode, TDOMElement(Node));
-
       // Scan all 'module' elements within this package element
       Subnode := Node.FirstChild;
       while Assigned(Subnode) do
-      begin
-        if (Subnode.NodeType = ELEMENT_NODE) and
-	  (Subnode.NodeName = 'module') then
-	begin
-	  ModuleDocNode := ReadNode(PackageDocNode, TDOMElement(Subnode));
-
-	  // Scan all 'element' elements within this module element
-	  Subsubnode := Subnode.FirstChild;
-	  while Assigned(Subsubnode) do
-	  begin
-	    if (Subsubnode.NodeType = ELEMENT_NODE) and
-	      (Subsubnode.NodeName = 'element') then
-	      ReadNode(ModuleDocNode, TDOMElement(Subsubnode));
-	    Subsubnode := Subsubnode.NextSibling;
-	  end;
-	end;
+        begin
+        if (Subnode.NodeType = ELEMENT_NODE) then
+          begin
+          If (Subnode.NodeName = 'module') then
+            begin
+            ModuleDocNode := ReadNode(PackageDocNode, TDOMElement(Subnode));
+            // Scan all 'element' elements within this module element
+            Subsubnode := Subnode.FirstChild;
+	    while Assigned(Subsubnode) do
+              begin
+	      if (Subsubnode.NodeType = ELEMENT_NODE) then
+	        begin
+	        if (Subsubnode.NodeName = 'element') then
+	          ReadNode(ModuleDocNode, TDOMElement(Subsubnode))
+	        else if (SubSubNode.NodeName='topic') then
+	          begin
+	          TopicNode:=ReadNode(ModuleDocNode,TDomElement(SubSubNode));
+	          TopicNode.FTopicNode:=True;
+	          ReadTopics(TopicNode);
+	          end;  
+	        end;    
+	      Subsubnode := Subsubnode.NextSibling;
+	      end;
+	    end
+	  else if (SubNode.NodeName='topic') then
+	    begin
+	    TopicNode:=ReadNode(PackageDocNode,TDomElement(SubNode));  
+	    TopicNode.FTopicNode:=True;
+	    ReadTopics(TopicNode);
+	    end;
+	  end;   
         Subnode := Subnode.NextSibling;
       end;
     end;
@@ -976,10 +1016,12 @@ end;
 
 function TFPDocEngine.FindDocNode(AElement: TPasElement): TDocNode;
 begin
-  if AElement.InheritsFrom(TPasUnresolvedTypeRef) then
-    Result := FindDocNode(AElement.GetModule, AElement.Name)
-  else
-    Result := RootDocNode.FindChild(AElement.PathName);
+  Result:=Nil;
+  If Assigned(AElement) then
+    if AElement.InheritsFrom(TPasUnresolvedTypeRef) then
+      Result := FindDocNode(AElement.GetModule, AElement.Name)
+    else
+      Result := RootDocNode.FindChild(AElement.PathName);
 end;
 
 function TFPDocEngine.FindDocNode(ARefModule: TPasModule;
@@ -1094,7 +1136,10 @@ end.
 
 {
   $Log$
-  Revision 1.2  2003-11-28 12:51:37  sg
+  Revision 1.3  2004-06-06 10:53:02  michael
+  + Added Topic support
+
+  Revision 1.2  2003/11/28 12:51:37  sg
   * Added support for source references
 
   Revision 1.1  2003/03/17 23:03:20  michael

+ 322 - 116
utils/fpdoc/dw_html.pp

@@ -30,7 +30,9 @@ const
   ClassesSubindex = 4;
   ProcsSubindex = 5;
   VarsSubindex = 6;
-
+  // Maybe needed later for topic overview ??
+  TopicsSubIndex = 7;
+   
   // Subpage indices for classes
   PropertiesByInheritanceSubindex = 1;
   PropertiesByNameSubindex = 2;
@@ -173,6 +175,7 @@ type
     procedure AppendKw(Parent: TDOMNode; const AText: DOMString);
     function AppendPasSHFragment(Parent: TDOMNode; const AText: String;
       AShFlags: Byte): Byte;
+    Procedure AppendShortDescr(AContext : TPasElement;Parent: TDOMNode; DocNode : TDocNode);
     procedure AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
     procedure AppendDescr(AContext: TPasElement; Parent: TDOMNode;
       DescrNode: TDOMElement; AutoInsertBlock: Boolean);
@@ -192,11 +195,15 @@ type
 
     procedure AppendTitle(const AText: DOMString);
     procedure AppendMenuBar(ASubpageIndex: Integer);
+    procedure AppendTopicMenuBar(Topic : TTopicElement);
     procedure AppendSourceRef(AElement: TPasElement);
     procedure FinishElementPage(AElement: TPasElement);
+    Procedure AppendSeeAlsoSection(AElement : TPasElement;DocNode : TDocNode);
+    Procedure AppendExampleSection(AElement : TPasElement;DocNode : TDocNode);
 
     procedure CreatePageBody(AElement: TPasElement; ASubpageIndex: Integer); virtual;
     procedure CreatePackagePageBody;
+    Procedure CreateTopicPageBody(AElement : TTopicElement);
     procedure CreateModulePageBody(AModule: TPasModule; ASubpageIndex: Integer);
     procedure CreateConstPageBody(AConst: TPasConst);
     procedure CreateTypePageBody(AType: TPasType);
@@ -204,6 +211,7 @@ type
     procedure CreateClassMemberPageBody(AElement: TPasElement);
     procedure CreateVarPageBody(AVar: TPasVariable);
     procedure CreateProcPageBody(AProc: TPasProcedureBase);
+    Procedure CreateTopicLinks(Node : TDocNode; PasElement : TPasElement);
   public
     constructor Create(AEngine: TFPDocEngine; AAllocator: TFileAllocator;
       APackage: TPasPackage);
@@ -280,19 +288,20 @@ begin
   else if AElement.ClassType = TPasModule then
     Result := LowerCase(AElement.Name) + PathDelim + 'index'
   else
-  begin
+    begin
     Result := LowerCase(AElement.PathName);
     i := 1;
-    if Result[1] = '#' then
-    begin
+    if (Length(Result)>0) and (Result[1]='#') then
+      begin
       while Result[i] <> '.' do
         Inc(i);
-      Result := Copy(Result, i + 1, Length(Result));
-    end;
+      Result:=Copy(Result,i+1,Length(Result));
+      end;
     i := 1;
-    while Result[i] <> '.' do
+    while (I<=Length(Result)) and (Result[i]<>'.') do
       Inc(i);
-    Result[i] := PathDelim;
+    If (I<=Length(Result)) and (I>0) then
+      Result[i]:= PathDelim;
   end;
 
   if ASubindex > 0 then
@@ -302,9 +311,18 @@ end;
 
 function TLongNameFileAllocator.GetRelativePathToTop(AElement: TPasElement): String;
 begin
-  if AElement.ClassType = TPasPackage then
+  if (AElement.ClassType=TPasPackage) then
     Result := ''
-  else
+  else if (AElement.ClassType=TTopicElement) then
+    begin
+    If (AElement.Parent.ClassType=TTopicElement) then
+      Result:='../'+GetRelativePathToTop(AElement.Parent)
+    else if (AElement.Parent.ClassType=TPasPackage) then
+      Result:=''
+    else if (AElement.Parent.ClassType=TPasModule) then
+      Result:='../';
+    end  
+  else 
     Result := '../';
 end;
 
@@ -327,6 +345,49 @@ constructor THTMLWriter.Create(AEngine: TFPDocEngine; AAllocator: TFileAllocator
         Allocator.GetFilename(AElement, ASubpageIndex));
   end;
 
+  procedure AddTopicPages(AElement: TPasElement);
+
+  var
+    PreviousTopic,
+    TopicElement : TTopicElement;
+    PageInfo : TPageInfo;
+    DocNode,
+    TopicNode : TDocNode;
+
+  begin
+    DocNode:=Engine.FindDocNode(AElement);
+    If not Assigned(DocNode) then 
+      exit;
+    TopicNode:=DocNode.FirstChild;
+    PreviousTopic:=Nil;
+    While Assigned(TopicNode) do
+      begin
+      If TopicNode.TopicNode then
+        begin
+        TopicElement:=TTopicElement.Create(TopicNode.Name,AElement);
+        Topics.Add(TopicElement);
+        TopicElement.TopicNode:=TopicNode;
+        TopicElement.Previous:=PreviousTopic;
+        If Assigned(PreviousTopic) then
+          PreviousTopic.Next:=TopicElement;
+        PreviousTopic:=TopicElement;  
+        if AElement is TTopicElement then
+          TTopicElement(AElement).SubTopics.Add(TopicElement);
+        PageInfo := TPageInfo.Create;
+        PageInfo.Element := TopicElement;
+        PageInfo.SubpageIndex := 0;
+        PageInfos.Add(PageInfo);
+        Allocator.AllocFilename(TopicElement,0);
+        Engine.AddLink(TopicElement.PathName, Allocator.GetFilename(TopicElement,0));
+        if AElement is TTopicElement then
+          TTopicElement(AElement).SubTopics.Add(TopicElement)
+        else // Only one level of recursion.
+          AddTopicPages(TopicElement);
+        end;
+      TopicNode:=TopicNode.NextSibling;
+      end;
+  end;
+
   procedure AddPages(AElement: TPasElement; ASubpageIndex: Integer;
     AList: TList);
   var
@@ -350,6 +411,7 @@ constructor THTMLWriter.Create(AEngine: TFPDocEngine; AAllocator: TFileAllocator
     DidAutolink: Boolean;
   begin
     AddPage(AModule, 0);
+    AddTopicPages(AModule);
     with AModule do
     begin
       if InterfaceSection.ResStrings.Count > 0 then
@@ -432,7 +494,10 @@ begin
 
   // Allocate page for the package itself, if a name is given (i.e. <> '#')
   if Length(Package.Name) > 1 then
+    begin
     AddPage(Package, 0);
+    AddTopicPages(Package);
+    end;
 
   for i := 0 to Package.Modules.Count - 1 do
     ScanModule(TPasModule(Package.Modules[i]));
@@ -1145,21 +1210,25 @@ begin
   FreeMem(Line);
 end;
 
-procedure THTMLWriter.AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
-var
-  DocNode: TDocNode;
+Procedure THTMLWriter.AppendShortDescr(AContext: TPasElement; Parent: TDOMNode; DocNode : TDocNode);
+
 begin
-  DocNode := Engine.FindDocNode(Element);
   if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
-  begin
+    begin
     PushOutputNode(Parent);
     try
-      if not ConvertShort(Element, DocNode.ShortDescr) then
+      if not ConvertShort(AContext,TDomElement(DocNode.ShortDescr)) then
         WriteLn(SErrInvalidShortDescr);
     finally
       PopOutputNode;
     end;
-  end;
+    end;
+end;
+
+procedure THTMLWriter.AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
+
+begin
+  AppendShortDescr(Element,Parent,Engine.FindDocNode(Element));
 end;
 
 procedure THTMLWriter.AppendDescr(AContext: TPasElement; Parent: TDOMNode;
@@ -1181,7 +1250,8 @@ procedure THTMLWriter.AppendDescrSection(AContext: TPasElement;
 begin
   if not IsDescrNodeEmpty(DescrNode) then
   begin
-    AppendText(CreateH2(Parent), ATitle);
+    If (ATitle<>'') then // Can be empty for topic.
+      AppendText(CreateH2(Parent), ATitle);
     AppendDescr(AContext, Parent, DescrNode, True);
   end;
 end;
@@ -1491,7 +1561,55 @@ begin
   AppendText(CreateH1(BodyElement), AText);
 end;
 
+procedure THTMLWriter.AppendTopicMenuBar(Topic : TTopicElement);
+
+var
+  TableEl, TREl, ParaEl, TitleEl: TDOMElement;
+
+  procedure AddLink(El : TPasElement; const AName: String);
+  begin
+    AppendText(ParaEl, '[');
+    AppendText(CreateLink(ParaEl, ResolveLinkWithinPackage(El,0)),AName);
+    AppendText(ParaEl, ']');
+  end;
+
+begin
+  TableEl := CreateEl(BodyElement, 'table');
+  TableEl['cellpadding'] := '4';
+  TableEl['cellspacing'] := '0';
+  TableEl['border'] := '0';
+  TableEl['width'] := '100%';
+  TableEl['class'] := 'bar';
+  TREl := CreateTR(TableEl);
+  ParaEl := CreateEl(CreateTD(TREl), 'b');
+  If Assigned(Topic.Previous) then
+    AddLink(Topic.Previous,SDocPrevious);
+  If Assigned(Topic.Parent) then
+    AddLink(Topic.Parent,SDocUp);
+  if Assigned(Topic.Next) then
+    AddLink(Topic.Next,SDocNext);
+  if Length(SearchPage) > 0 then
+    begin
+    AppendText(ParaEl, '[');
+    AppendText(CreateLink(ParaEl, SearchPage), SDocSearch);
+    AppendText(ParaEl, ']');
+    end;
+  ParaEl := CreateTD(TREl);
+  ParaEl['align'] := 'right';
+  TitleEl := CreateEl(ParaEl, 'span');
+  TitleEl['class'] := 'bartitle';
+  if Assigned(Module) then
+    AppendText(TitleEl, Format(SDocUnitTitle, [Module.Name]));
+  if Assigned(Package) then
+  begin
+    AppendText(TitleEl, ' (');
+    AppendHyperlink(TitleEl, Package);
+    AppendText(TitleEl, ')');
+  end;
+end;
+
 procedure THTMLWriter.AppendMenuBar(ASubpageIndex: Integer);
+
 var
   TableEl, TREl, ParaEl, TitleEl: TDOMElement;
 
@@ -1560,107 +1678,151 @@ begin
     [AElement.SourceFilename, AElement.SourceLinenumber]));
 end;
 
-procedure THTMLWriter.FinishElementPage(AElement: TPasElement);
+Procedure THTMLWriter.AppendSeeAlsoSection(AElement : TPasElement;DocNode : TDocNode);
+
 var
-  DocNode: TDocNode;
-  IsFirstSeeAlso: Boolean;
   Node: TDOMNode;
   TableEl, El, TREl, TDEl, ParaEl, NewEl, DescrEl: TDOMElement;
   s: String;
   f: Text;
+  IsFirstSeeAlso : Boolean;
+  
+begin
+  if Not (Assigned(DocNode) and Assigned(DocNode.SeeAlso)) then
+    Exit;
+  IsFirstSeeAlso := True;
+  Node:=DocNode.SeeAlso.FirstChild;
+  While Assigned(Node) do
+    begin
+    if (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='link') then
+      begin
+       if IsFirstSeeAlso then
+         begin
+         IsFirstSeeAlso := False;
+         AppendText(CreateH2(BodyElement), SDocSeeAlso);
+         TableEl := CreateTable(BodyElement);
+         end;
+       El:=TDOMElement(Node);
+       TREl:=CreateTR(TableEl);
+       ParaEl:=CreatePara(CreateTD_vtop(TREl));
+       s:= ResolveLinkID(El['id']);
+       if Length(s)=0 then
+         begin
+         WriteLn(Format(SErrUnknownLinkID, [El['id']]));
+         NewEl := CreateEl(ParaEl,'b')
+         end 
+       else
+         NewEl := CreateLink(ParaEl,s);
+       AppendText(NewEl,El['id']);
+       DescrEl := Engine.FindShortDescr(AElement.GetModule, El['id']);
+       if Assigned(DescrEl) then
+         begin
+         AppendNbSp(CreatePara(CreateTD(TREl)), 2);
+         ParaEl := CreatePara(CreateTD(TREl));
+         ParaEl['class'] := 'cmt';
+         PushOutputNode(ParaEl);
+         try
+           ConvertShort(AElement, DescrEl);
+         finally
+           PopOutputNode;
+         end;  
+         end;
+       end; // Link node
+     Node := Node.NextSibling;
+     end; // While
+end;
+
+Procedure THTMLWriter.AppendExampleSection(AElement : TPasElement;DocNode : TDocNode);
+
+var
+  Node: TDOMNode;
+//  TableEl, El, TREl, TDEl, ParaEl, NewEl, DescrEl: TDOMElement;
+  s: String;
+  f: Text;
+  
+begin
+  if not (Assigned(DocNode) and Assigned(DocNode.FirstExample)) then
+    Exit;
+  Node := DocNode.FirstExample;
+  while Assigned(Node) do
+    begin
+    if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'example') then
+      begin
+      AppendText(CreateH2(BodyElement), SDocExample);
+      try
+        Assign(f, Engine.GetExampleFilename(TDOMElement(Node)));
+        Reset(f);
+        try
+          PushOutputNode(BodyElement);
+	  DescrBeginCode(False, TDOMElement(Node)['highlighter']);
+          while not EOF(f) do
+            begin
+            ReadLn(f, s);
+	    DescrWriteCodeLine(s);
+            end;
+	  DescrEndCode;
+          PopOutputNode;
+        finally
+          Close(f);
+        end;
+      except
+        on e: Exception do
+          begin
+          e.Message := '[example] ' + e.Message;
+          raise;
+          end;
+      end;
+      end;
+    Node := Node.NextSibling;
+    end;
+end;
+
+procedure THTMLWriter.FinishElementPage(AElement: TPasElement);
+
+var
+  DocNode: TDocNode;
+
 begin
   DocNode := Engine.FindDocNode(AElement);
-  if Assigned(DocNode) and Assigned(DocNode.Descr) then
-    AppendDescrSection(AElement, BodyElement, DocNode.Descr, SDocDescription);
-  // ###
+  If Assigned(DocNode) then
+    begin
+    // Description
+    if Assigned(DocNode.Descr) then
+      AppendDescrSection(AElement, BodyElement, DocNode.Descr, SDocDescription);
 
-  // Append "Errors" section
-  if Assigned(DocNode) and Assigned(DocNode.ErrorsDoc) then
-    AppendDescrSection(AElement, BodyElement, DocNode.ErrorsDoc, SDocErrors);
+    // Append "Errors" section
+    if Assigned(DocNode.ErrorsDoc) then
+      AppendDescrSection(AElement, BodyElement, DocNode.ErrorsDoc, SDocErrors);
 
-      // Append "See also" section
-      if Assigned(DocNode) and Assigned(DocNode.SeeAlso) then
-      begin
-        IsFirstSeeAlso := True;
-	Node := DocNode.SeeAlso.FirstChild;
-	while Assigned(Node) do
-	begin
-	  if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'link') then
-	  begin
-	    if IsFirstSeeAlso then
-	    begin
-	      IsFirstSeeAlso := False;
-	      AppendText(CreateH2(BodyElement), SDocSeeAlso);
-	      TableEl := CreateTable(BodyElement);
-	    end;
+    // Append "See also" section
+    AppendSeeAlsoSection(AElement,DocNode);
 
-	    El := TDOMElement(Node);
-	    TREl := CreateTR(TableEl);
-	    ParaEl := CreatePara(CreateTD_vtop(TREl));
-	    s := ResolveLinkID(El['id']);
-	    if Length(s) = 0 then
-	    begin
-	      WriteLn(Format(SErrUnknownLinkID, [El['id']]));
-	      NewEl := CreateEl(ParaEl, 'b')
-	    end else
-	      NewEl := CreateLink(ParaEl, s);
-	    AppendText(NewEl, El['id']);
+    // Append examples, if present
+    AppendExampleSection(AElement,DocNode);
+    end;
+end;
 
-	    DescrEl := Engine.FindShortDescr(AElement.GetModule, El['id']);
-	    if Assigned(DescrEl) then
-	    begin
-	      AppendNbSp(CreatePara(CreateTD(TREl)), 2);
-	      ParaEl := CreatePara(CreateTD(TREl));
-	      ParaEl['class'] := 'cmt';
-
-	      PushOutputNode(ParaEl);
-	      try
-		ConvertShort(AElement, DescrEl);
-	      finally
-		PopOutputNode;
-	      end;
-	    end;
-	  end;
-	  Node := Node.NextSibling;
-	end;
-      end;
+Procedure THTMLWriter.CreateTopicPageBody(AElement : TTopicElement);
 
-      // Append examples, if present
-      if Assigned(DocNode) and Assigned(DocNode.FirstExample) then
-      begin
-        Node := DocNode.FirstExample;
-	while Assigned(Node) do
-	begin
-	  if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'example') then
-	  begin
-	    AppendText(CreateH2(BodyElement), SDocExample);
-	    try
-	      Assign(f, Engine.GetExampleFilename(TDOMElement(Node)));
-	      Reset(f);
-	      try
-	        PushOutputNode(BodyElement);
-		DescrBeginCode(False, TDOMElement(Node)['highlighter']);
-	        while not EOF(f) do
-	        begin
-	          ReadLn(f, s);
-		  DescrWriteCodeLine(s);
-	        end;
-		DescrEndCode;
-	        PopOutputNode;
-	      finally
-	        Close(f);
-	      end;
-	    except
-	      on e: Exception do
-	      begin
-	        e.Message := '[example] ' + e.Message;
-	        raise;
-	      end;
-	    end;
-	  end;
-	  Node := Node.NextSibling;
-	end;
-      end;
+var
+  DocNode: TDocNode;
+  TableEl, TREl: TDOMElement;
+  I : Integer;
+  S : String;
+  
+begin
+  AppendTopicMenuBar(AElement);
+  DocNode:=AElement.TopicNode;
+  if Assigned(DocNode) then  // should always be true, but we're being careful.
+    begin
+    AppendShortDescr(AElement,TitleElement, DocNode);
+    AppendShortDescr(AElement,CreateH2(BodyElement), DocNode);
+    if Assigned(DocNode.Descr) then
+       AppendDescrSection(nil, BodyElement, DocNode.Descr, '');
+    AppendSeeAlsoSection(AElement,DocNode);
+    CreateTopicLinks(DocNode,AElement);
+    AppendExampleSection(AElement,DocNode);
+    end;
 end;
 
 procedure THTMLWriter.CreatePageBody(AElement: TPasElement;
@@ -1678,10 +1840,10 @@ begin
 
   if AElement.ClassType = TPasPackage then
     CreatePackagePageBody
-  else
-  begin
+  else 
+    begin
     Element := AElement;
-    while Element.ClassType <> TPasModule do
+    while (Element<>Nil) and (Element.ClassType<>TPasModule) do
       Element := Element.Parent;
     Module := TPasModule(Element);
 
@@ -1698,7 +1860,9 @@ begin
     else if AElement.ClassType = TPasVariable then
       CreateVarPageBody(TPasVariable(AElement))
     else if AElement.InheritsFrom(TPasProcedureBase) then
-      CreateProcPageBody(TPasProcedure(AElement));
+      CreateProcPageBody(TPasProcedure(AElement))
+    else if AElement.ClassType = TTopicELement then
+      CreateTopicPageBody(TTopicElement(AElement))
   end;
 end;
 
@@ -1724,8 +1888,43 @@ begin
   end;
 
   DocNode := Engine.FindDocNode(Package);
-  if Assigned(DocNode) and Assigned(DocNode.Descr) then
-    AppendDescrSection(nil, BodyElement, DocNode.Descr, SDocDescription);
+  if Assigned(DocNode) then
+    begin
+    if Assigned(DocNode.Descr) then
+       AppendDescrSection(nil, BodyElement, DocNode.Descr, SDocDescription);
+    CreateTopicLinks(DocNode,Package);
+    end;
+end;
+
+Procedure THTMLWriter.CreateTopicLinks(Node : TDocNode; PasElement : TPasElement);
+
+var
+  DocNode: TDocNode;
+  TableEl, TREl: TDOMElement;
+  First : Boolean;
+  ThisTopic: TPasElement;
+        
+begin
+  DocNode:=Node.FirstChild;
+  First:=True;
+  While Assigned(DocNode) do
+    begin
+    If DocNode.TopicNode then
+      begin
+      if first then
+        begin
+        First:=False;
+        AppendText(CreateH2(BodyElement), SDocRelatedTopics);
+        TableEl := CreateTable(BodyElement);
+        end;
+      TREl := CreateTR(TableEl);
+      ThisTopic:=FindTopicElement(DocNode);
+      if Assigned(ThisTopic) then
+        AppendHyperlink(CreateCode(CreatePara(CreateTD_vtop(TREl))), ThisTopic);
+      AppendShortDescrCell(TREl, ThisTopic);
+      end;
+    DocNode:=DocNode.NextSibling;
+    end;    
 end;
 
 procedure THTMLWriter.CreateModulePageBody(AModule: TPasModule;
@@ -1767,8 +1966,12 @@ procedure THTMLWriter.CreateModulePageBody(AModule: TPasModule;
     end;
 
     DocNode := Engine.FindDocNode(AModule);
-    if Assigned(DocNode) and Assigned(DocNode.Descr) then
-      AppendDescrSection(AModule, BodyElement, DocNode.Descr, SDocOverview);
+    if Assigned(DocNode) then
+      begin
+      if Assigned(DocNode.Descr) then
+        AppendDescrSection(AModule, BodyElement, DocNode.Descr, SDocOverview);
+      CreateTopicLinks(DocNode,AModule);
+      end;
   end;
 
   procedure CreateSimpleSubpage(const ATitle: DOMString; AList: TList);
@@ -2593,7 +2796,10 @@ end.
 
 {
   $Log$
-  Revision 1.5  2003-11-28 12:51:37  sg
+  Revision 1.6  2004-06-06 10:53:02  michael
+  + Added Topic support
+
+  Revision 1.5  2003/11/28 12:51:37  sg
   * Added support for source references
 
   Revision 1.4  2003/04/22 00:00:05  sg

+ 165 - 19
utils/fpdoc/dw_latex.pp

@@ -143,8 +143,12 @@ type
     procedure WriteProperty(PropDecl: TPasProperty);
     procedure WriteExample(ADocNode: TDocNode);
     procedure WriteSeeAlso(ADocNode: TDocNode);
+    procedure WriteSeeAlso(ADocNode: TDocNode; InList : Boolean);
     procedure SortElementList(List : TList);
     Function  ShowMember(M : TPasElement) : boolean;
+    Procedure ProcessPackage;
+    Procedure ProcessTopics(DocNode : TDocNode; Alevel : Integer);
+    Procedure WriteTopicNode(Node : TDocNode; Level : Integer);
   public
     constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine);
     procedure WriteDoc;
@@ -167,6 +171,43 @@ constructor TLaTeXWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
       AddLabel(TPasElement(AList[i]));
   end;
 
+  procedure AddTopicPages(AElement: TPasElement);
+
+  var
+    PreviousTopic,
+    TopicElement : TTopicElement;
+    DocNode,
+    TopicNode : TDocNode;
+
+  begin
+    DocNode:=Engine.FindDocNode(AElement);
+    If not Assigned(DocNode) then 
+      exit;
+    TopicNode:=DocNode.FirstChild;
+    PreviousTopic:=Nil;
+    While Assigned(TopicNode) do
+      begin
+      If TopicNode.TopicNode then
+        begin
+        TopicElement:=TTopicElement.Create(TopicNode.Name,AElement);
+        Topics.Add(TopicElement);
+        TopicElement.TopicNode:=TopicNode;
+        TopicElement.Previous:=PreviousTopic;
+        If Assigned(PreviousTopic) then
+          PreviousTopic.Next:=TopicElement;
+        PreviousTopic:=TopicElement;  
+        if AElement is TTopicElement then
+          TTopicElement(AElement).SubTopics.Add(TopicElement);
+        Engine.AddLink(TopicElement.PathName, GetLabel(TopicElement));
+        if AElement is TTopicElement then
+          TTopicElement(AElement).SubTopics.Add(TopicElement)
+        else // Only one level of recursion.
+          AddTopicPages(TopicElement);
+        end;
+      TopicNode:=TopicNode.NextSibling;
+      end;
+  end;
+
   procedure ScanModule(AModule: TPasModule);
   var
     i, j, k: Integer;
@@ -177,6 +218,7 @@ constructor TLaTeXWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
     DidAutolink: Boolean;
   begin
     AddLabel(AModule);
+    AddTopicPages(AModule);
     with AModule do
     begin
       AddList(AModule, InterfaceSection.ResStrings);
@@ -243,15 +285,93 @@ begin
 
   // Allocate label for the package itself, if a name is given (i.e. <> '#')
   if Length(Package.Name) > 1 then
+    begin
     AddLabel(Package);
-
+    AddTopicPages(Package);
+    end;
   for i := 0 to Package.Modules.Count - 1 do
     ScanModule(TPasModule(Package.Modules[i]));
 end;
 
+Procedure TLatexWriter.ProcessPackage;
+
+var
+  i: Integer;
+  UnitRef: TPasType;
+  DocNode: TDocNode;
+  First : Boolean;
+  
+begin
+  DocNode:=Engine.FindDocNode(Package);
+  if Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.Descr) then
+    begin
+    WriteLnF('\section{%s}', [EscapeTex(SDocOverview)]);
+    WriteDescr(Package, DocNode.Descr);
+    Writeln('');
+    end;
+  WriteSeeAlso(DocNode,True);
+  ProcessTopics(DocNode,1);
+end;
+
+Procedure TlatexWriter.ProcessTopics(DocNode : TDocNode; Alevel : Integer);
+
+Var
+  Node : TDocNode;
+  First : Boolean;
+  
+begin
+  If Not Assigned(DocNode) then
+    Exit;
+  Node:=DocNode.FirstChild;
+  First:=True;
+  While Assigned(Node) do
+    begin
+    If Node.TopicNode then
+      begin
+      WriteTopicNode(Node,ALevel);
+      First:=False;
+      end;
+    Node:=Node.NextSibling;
+    end;
+end;
+
+Procedure TLatexWriter.WriteTopicNode(Node : TDocNode; Level : Integer);
+
+Var
+  Element : TTopicElement;
+  SubNode : TDocNode;
+  
+begin
+  Element:=FindTopicElement(Node);
+  If Not Assigned(Element) then 
+    Exit;
+  Case Level of
+    1 : Write('\section{');
+    2 : Write('\subsection{');
+    3 : Write('\subsubsection{');
+  end;
+  WriteDescr(Element,Node.ShortDescr);
+  Writeln('}');
+  WriteLabel(Element);
+  If Assigned(Node.Descr) then
+    WriteDescr(Element,Node.Descr);
+  WriteSeeAlso(Node,True);
+  If Level<3 then
+    begin
+    SubNode:=Node.FirstChild;
+    While Assigned(SubNode) do
+      begin
+      If SubNode.TopicNode then
+        WriteTopicNode(SubNode,Level+1);
+      SubNode:=SubNode.NextSibling;
+      end;
+    end;  
+end;
+
 procedure TLaTeXWriter.WriteDoc;
 var
   i : Integer;
+  DocNode : TDocNode;
   
 begin
   PackageName := LowerCase(Copy(Package.Name, 2, 255));
@@ -262,6 +382,7 @@ begin
   try
     WriteLn('% This file has been created automatically by FPDoc,');
     WriteLn('% (c) 2000-2003 by Areca Systems GmbH / Sebastian Guenther ([email protected])');
+    ProcessPackage;
     for i := 0 to Package.Modules.Count - 1 do
     begin
       Module := TPasModule(Package.Modules[i]);
@@ -269,6 +390,9 @@ begin
       WriteLn('');
       WriteLnF('\chapter{%s}', [EscapeTex(Format(SDocUnitTitle, [Module.Name]))]);
       WriteLabel(Module);
+      DocNode:=Engine.FindDocNode(Module);
+      If Assigned(DocNode) then
+        ProcessTopics(DocNode,1);
       ProcessSection(Module.InterfaceSection);
     end;
   finally
@@ -900,30 +1024,49 @@ begin
 end;
 
 procedure TLateXWriter.WriteSeeAlso(ADocNode: TDocNode);
+
+begin
+  WriteSeeAlso(ADocNode,False);
+end;
+
+procedure TLateXWriter.WriteSeeAlso(ADocNode: TDocNode; InList : Boolean);
+
 var
   Node: TDOMNode;
   s: String;
+  First : Boolean;
+  
 begin
-  if Assigned(ADocNode) and Assigned(ADocNode.SeeAlso) and
-    Assigned(ADocNode.SeeAlso.FirstChild) then
-  begin
-    Writeln('\SeeAlso');
-    Node := ADocNode.SeeAlso.FirstChild;
-    while Assigned(Node) do
-    begin 
-      if (Node.NodeType = ELEMENT_NODE) and 
-        (Node.NodeName = 'link') then
+  if Not (Assigned(ADocNode) and Assigned(ADocNode.SeeAlso)) then 
+    Exit;
+  Node := ADocNode.SeeAlso.FirstChild;
+  First:=True;
+  while Assigned(Node) do
+    begin
+    if (Node.NodeType = ELEMENT_NODE) and 
+       (Node.NodeName = 'link') then
       begin
-        S:=TDomElement(Node)['id'];
-        DescrBeginLink(S);
-        Writeln(S);
-        DescrEndLink();
-        if Assigned(Node.NextSibling) Then
-          Writeln(',');
+      If First then
+        begin
+        If InList then
+          begin
+          Writeln('');
+          Writeln('\begin{FPCList}');
+          end;
+        Writeln('\SeeAlso');
+        First:=False;
+        end
+      else  
+        Writeln(',');
+      S:=TDomElement(Node)['id'];
+      DescrBeginLink(S);
+      Writeln(S);
+      DescrEndLink();
       end;  
-      Node:=Node.NextSibling;  
+    Node:=Node.NextSibling;  
     end;
-  end;   
+  If Inlist and Not First then
+    Writeln('\end{FPCList}');   
 end;
 
 procedure TLaTeXWriter.WriteClasses(ASection: TPasSection);
@@ -1302,7 +1445,10 @@ end.
 
 {
   $Log$
-  Revision 1.4  2003-03-18 19:28:44  michael
+  Revision 1.5  2004-06-06 10:53:02  michael
+  + Added Topic support
+
+  Revision 1.4  2003/03/18 19:28:44  michael
   + Some changes to output handling, more suitable for tex output
 
   Revision 1.3  2003/03/18 19:12:29  michael

+ 63 - 3
utils/fpdoc/dwriter.pp

@@ -52,10 +52,21 @@ resourcestring
 
 
 type
+  // Phony element for pas pages.
+
+  TTopicElement = Class(TPaselement)
+    Constructor Create(const AName: String; AParent: TPasElement); override;
+    Destructor Destroy; override;
+    TopicNode : TDocNode;
+    Previous,
+    Next : TPasElement;
+    Subtopics : TList;
+  end;
 
   TFPDocWriter = class
   private
-    FEngine: TFPDocEngine;
+    FEngine : TFPDocEngine;
+    FTopics : TList;
   protected
 
     procedure Warning(AContext: TPasElement; const AMsg: String);
@@ -80,6 +91,7 @@ type
     procedure ConvertExtShortOrNonSectionBlocks(AContext: TPasElement;
       Node: TDOMNode);
     function ConvertSimpleBlock(AContext: TPasElement; Node: TDOMNode): Boolean;
+    Function FindTopicElement(Node : TDocNode): TTopicElement;
 
     procedure DescrWriteText(const AText: DOMString); virtual; abstract;
     procedure DescrBeginBold; virtual; abstract;
@@ -128,7 +140,9 @@ type
     procedure DescrEndTableCell; virtual; abstract;
   public
     constructor Create(AEngine: TFPDocEngine);
-    property Engine: TFPDocEngine read FEngine;
+    destructor Destroy;  override;
+    property Engine : TFPDocEngine read FEngine;
+    Property Topics : TList Read FTopics;
   end;
 
 
@@ -141,6 +155,35 @@ constructor TFPDocWriter.Create(AEngine: TFPDocEngine);
 begin
   inherited Create;
   FEngine := AEngine;
+  FTopics:=Tlist.Create;
+end;
+
+destructor TFPDocWriter.Destroy; 
+
+Var
+  i : integer;
+
+begin
+  For I:=0 to FTopics.Count-1 do
+    TTopicElement(FTopics[i]).Free;
+  FTopics.Free;
+  Inherited;
+end;
+
+Function TFPDocWriter.FindTopicElement(Node : TDocNode): TTopicElement;
+
+Var
+  I : Integer;
+  
+begin
+  Result:=Nil;
+  I:=FTopics.Count-1;
+  While (I>=0) and (Result=Nil) do
+    begin
+    If (TTopicElement(FTopics[i]).TopicNode=Node) Then
+      Result:=TTopicElement(FTopics[i]);
+    Dec(I);  
+    end;
 end;
 
 
@@ -752,13 +795,30 @@ begin
     Result := False;
 end;
 
+Constructor TTopicElement.Create(const AName: String; AParent: TPasElement); 
+
+begin
+  Inherited Create(AName,AParent);
+  SubTopics:=TList.Create;
+end;
+
+Destructor TTopicElement.Destroy;
+
+begin
+  // Actual subtopics are freed by TFPDocWriter Topics list.
+  SubTopics.Free;
+  Inherited;
+end;
 
 end.
 
 
 {
   $Log$
-  Revision 1.1  2003-03-17 23:03:20  michael
+  Revision 1.2  2004-06-06 10:53:02  michael
+  + Added Topic support
+
+  Revision 1.1  2003/03/17 23:03:20  michael
   + Initial import in CVS
 
   Revision 1.9  2003/03/13 22:02:13  sg