Orb/Doxygen/src/filedef.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /******************************************************************************
       
     2  *
       
     3  * 
       
     4  *
       
     5  * Copyright (C) 1997-2008 by Dimitri van Heesch.
       
     6  *
       
     7  * Permission to use, copy, modify, and distribute this software and its
       
     8  * documentation under the terms of the GNU General Public License is hereby 
       
     9  * granted. No representations are made about the suitability of this software 
       
    10  * for any purpose. It is provided "as is" without express or implied warranty.
       
    11  * See the GNU General Public License for more details.
       
    12  *
       
    13  * Documents produced by Doxygen are derivative works derived from the
       
    14  * input used in their production; they are not affected by this license.
       
    15  *
       
    16  */
       
    17 
       
    18 #include "qtbc.h"
       
    19 #include "memberlist.h"
       
    20 #include "classlist.h"
       
    21 #include "filedef.h"
       
    22 #include "doxygen.h"
       
    23 #include "memberdef.h"
       
    24 #include "classdef.h"
       
    25 #include "namespacedef.h"
       
    26 #include "util.h"
       
    27 #include "language.h"
       
    28 #include "outputlist.h"
       
    29 #include "dot.h"
       
    30 #include "message.h"
       
    31 #include "docparser.h"
       
    32 #include "searchindex.h"
       
    33 #include "htags.h"
       
    34 #include "parserintf.h"
       
    35 #include "portable.h"
       
    36 #include "vhdldocgen.h"
       
    37 #include "debug.h"
       
    38 #include "layout.h"
       
    39 
       
    40 //---------------------------------------------------------------------------
       
    41 
       
    42 class DevNullCodeDocInterface : public CodeOutputInterface
       
    43 {
       
    44   public:
       
    45     virtual void codify(const char *) {}
       
    46     virtual void writeCodeLink(const char *,const char *,
       
    47                                const char *,const char *,
       
    48                                const char *) {}
       
    49     virtual void writeLineNumber(const char *,const char *,
       
    50                                  const char *,int) {}
       
    51     virtual void startCodeLine() {}
       
    52     virtual void endCodeLine() {}
       
    53     virtual void startCodeAnchor(const char *) {}
       
    54     virtual void endCodeAnchor() {}
       
    55     virtual void startFontClass(const char *) {}
       
    56     virtual void endFontClass() {}
       
    57     virtual void writeCodeAnchor(const char *) {}
       
    58     virtual void linkableSymbol(int, const char *,Definition *,Definition *) {}
       
    59 };
       
    60 
       
    61 //---------------------------------------------------------------------------
       
    62 
       
    63 /*! create a new file definition, where \a p is the file path, 
       
    64     \a nm the file name, and \a ref is an HTML anchor name if the
       
    65     file was read from a tag file or 0 otherwise
       
    66 */
       
    67 FileDef::FileDef(const char *p,const char *nm,
       
    68                  const char *lref,const char *dn)
       
    69    : Definition((QCString)p+nm,1,nm)
       
    70 {
       
    71   path=p;
       
    72   filepath=path+nm;
       
    73   filename=nm;
       
    74   diskname=dn;
       
    75   if (diskname.isEmpty()) diskname=nm;
       
    76   setReference(lref);
       
    77   classSDict        = 0;
       
    78   includeList       = 0;
       
    79   includeDict       = 0; 
       
    80   includedByList    = 0;
       
    81   includedByDict    = 0; 
       
    82   namespaceSDict    = 0; 
       
    83   srcDefDict        = 0;
       
    84   srcMemberDict     = 0;
       
    85   usingDirList      = 0;
       
    86   usingDeclList     = 0;
       
    87   package           = 0;
       
    88   isSource          = FALSE; 
       
    89   docname           = nm;
       
    90   dir               = 0;
       
    91   if (Config_getBool("FULL_PATH_NAMES"))
       
    92   {
       
    93     docname.prepend(stripFromPath(path.copy()));
       
    94   }
       
    95   m_isJava          = name().right(5)==".java";
       
    96   memberGroupSDict = 0;
       
    97   acquireFileVersion();
       
    98   m_subGrouping=Config_getBool("SUBGROUPING");
       
    99 }
       
   100 
       
   101 /*! destroy the file definition */
       
   102 FileDef::~FileDef()
       
   103 {
       
   104   delete classSDict;
       
   105   delete includeDict;
       
   106   delete includeList;
       
   107   delete includedByDict;
       
   108   delete includedByList;
       
   109   delete namespaceSDict;
       
   110   delete srcDefDict;
       
   111   delete srcMemberDict;
       
   112   delete usingDirList;
       
   113   delete usingDeclList;
       
   114   delete memberGroupSDict;
       
   115 }
       
   116 
       
   117 /*! Compute the HTML anchor names for all members in the class */ 
       
   118 void FileDef::computeAnchors()
       
   119 {
       
   120   MemberList *ml = getMemberList(MemberList::allMembersList);
       
   121   if (ml) setAnchors(0,'a',ml);
       
   122 }
       
   123 
       
   124 void FileDef::distributeMemberGroupDocumentation()
       
   125 {
       
   126   //printf("FileDef::distributeMemberGroupDocumentation()\n");
       
   127   if (memberGroupSDict)
       
   128   {
       
   129     MemberGroupSDict::Iterator mgli(*memberGroupSDict);
       
   130     MemberGroup *mg;
       
   131     for (;(mg=mgli.current());++mgli)
       
   132     {
       
   133       mg->distributeMemberGroupDocumentation();
       
   134     }
       
   135   }
       
   136 }
       
   137 
       
   138 void FileDef::findSectionsInDocumentation()
       
   139 {
       
   140   docFindSections(documentation(),this,0,docFile());
       
   141   if (memberGroupSDict)
       
   142   {
       
   143     MemberGroupSDict::Iterator mgli(*memberGroupSDict);
       
   144     MemberGroup *mg;
       
   145     for (;(mg=mgli.current());++mgli)
       
   146     {
       
   147       mg->findSectionsInDocumentation();
       
   148     }
       
   149   }
       
   150 
       
   151   QListIterator<MemberList> mli(m_memberLists);
       
   152   MemberList *ml;
       
   153   for (mli.toFirst();(ml=mli.current());++mli)
       
   154   {
       
   155     if (ml->listType()&MemberList::declarationLists)
       
   156     {
       
   157       ml->findSectionsInDocumentation();
       
   158     }
       
   159   }
       
   160 }
       
   161 
       
   162 void FileDef::writeDetailedDescription(OutputList &ol,const QCString &title)
       
   163 {
       
   164   if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || 
       
   165       !documentation().isEmpty() ||
       
   166       (Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef())
       
   167      )
       
   168   {
       
   169     ol.writeRuler();
       
   170     ol.pushGeneratorState();
       
   171     ol.disableAllBut(OutputGenerator::Html);
       
   172       ol.writeAnchor(0,"_details"); 
       
   173     ol.popGeneratorState();
       
   174     ol.startGroupHeader();
       
   175     ol.parseText(title);
       
   176     ol.endGroupHeader();
       
   177 
       
   178     ol.startTextBlock();
       
   179     if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
       
   180     {
       
   181       ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
       
   182     }
       
   183     if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") && 
       
   184         !documentation().isEmpty())
       
   185     {
       
   186       ol.pushGeneratorState();
       
   187         ol.disable(OutputGenerator::Man);
       
   188         ol.disable(OutputGenerator::RTF);
       
   189         // ol.newParagraph(); // FIXME:PARA
       
   190         ol.enableAll();
       
   191         ol.disableAllBut(OutputGenerator::Man);
       
   192         ol.writeString("\n\n");
       
   193       ol.popGeneratorState();
       
   194     }
       
   195     if (!documentation().isEmpty())
       
   196     {
       
   197       ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
       
   198     }
       
   199     //printf("Writing source ref for file %s\n",name().data());
       
   200     if (Config_getBool("SOURCE_BROWSER")) 
       
   201     {
       
   202       ol.startParagraph();
       
   203       QCString refText = theTranslator->trDefinedInSourceFile();
       
   204       int fileMarkerPos = refText.find("@0");
       
   205       if (fileMarkerPos!=-1) // should always pass this.
       
   206       {
       
   207         ol.parseText(refText.left(fileMarkerPos)); //text left from marker 1
       
   208         ol.writeObjectLink(0,getSourceFileBase(),
       
   209             0,name());
       
   210         ol.parseText(refText.right(
       
   211               refText.length()-fileMarkerPos-2)); // text right from marker 2
       
   212       }
       
   213       ol.endParagraph();
       
   214     }
       
   215     ol.endTextBlock();
       
   216   }
       
   217 }
       
   218 
       
   219 void FileDef::writeBriefDescription(OutputList &ol)
       
   220 {
       
   221   if (!briefDescription().isEmpty()) 
       
   222   {
       
   223     ol.startParagraph();
       
   224     ol.parseDoc(briefFile(),briefLine(),this,0,
       
   225                 briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
       
   226     ol.pushGeneratorState();
       
   227     ol.disable(OutputGenerator::RTF);
       
   228     ol.writeString(" \n");
       
   229     ol.enable(OutputGenerator::RTF);
       
   230 
       
   231     if (Config_getBool("REPEAT_BRIEF") ||
       
   232         !documentation().isEmpty()
       
   233        )
       
   234     {
       
   235       ol.disableAllBut(OutputGenerator::Html);
       
   236       ol.startTextLink(0,"_details");
       
   237       ol.parseText(theTranslator->trMore());
       
   238       ol.endTextLink();
       
   239     }
       
   240     ol.popGeneratorState();
       
   241     ol.endParagraph();
       
   242 
       
   243     //ol.pushGeneratorState();
       
   244     //ol.disable(OutputGenerator::RTF);
       
   245     //ol.newParagraph();
       
   246     //ol.popGeneratorState();
       
   247   }
       
   248   ol.writeSynopsis();
       
   249 }
       
   250 
       
   251 void FileDef::writeIncludeFiles(OutputList &ol)
       
   252 {
       
   253   if (/*Config_getBool("SHOW_INCLUDE_FILES") &&*/ includeList && 
       
   254       includeList->count()>0)
       
   255   {
       
   256     ol.startTextBlock(TRUE);
       
   257     QListIterator<IncludeInfo> ili(*includeList);
       
   258     IncludeInfo *ii;
       
   259     for (;(ii=ili.current());++ili)
       
   260     {
       
   261       FileDef *fd=ii->fileDef;
       
   262       bool isIDLorJava = FALSE;
       
   263       if (fd)
       
   264       {
       
   265         isIDLorJava = fd->name().right(4)==".idl" ||   // M$ or Corba IDL
       
   266                       fd->name().right(5)==".pidl" ||
       
   267                       fd->name().right(5)==".java" ||  // Sun's Java
       
   268                       fd->name().right(4)==".jsl";     // M$ J#
       
   269       }
       
   270       ol.startTypewriter();
       
   271       if (isIDLorJava) // IDL/Java include
       
   272       {
       
   273         ol.docify("import ");
       
   274       }
       
   275       else if (ii->imported) // Objective-C include
       
   276       {
       
   277         ol.docify("#import ");
       
   278       }
       
   279       else // C/C++ include
       
   280       {
       
   281         ol.docify("#include ");
       
   282       }
       
   283       if (ii->local || isIDLorJava)
       
   284         ol.docify("\"");
       
   285       else
       
   286         ol.docify("<");
       
   287       ol.disable(OutputGenerator::Html);
       
   288       ol.docify(ii->includeName);
       
   289       ol.enableAll();
       
   290       ol.disableAllBut(OutputGenerator::Html);
       
   291       
       
   292       // Here we use the include file name as it appears in the file.
       
   293       // we could also we the name as it is used within doxygen,
       
   294       // then we should have used fd->docName() instead of ii->includeName
       
   295       if (fd && fd->isLinkable())
       
   296       {
       
   297         ol.writeObjectLink(fd->getReference(),
       
   298             fd->generateSourceFile() ? fd->includeName() : fd->getOutputFileBase(),
       
   299             0,ii->includeName);
       
   300         if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !fd->isReference()) 
       
   301         {
       
   302           const char *locStr = (ii->local    || isIDLorJava) ? "yes" : "no";
       
   303           const char *impStr = (ii->imported || isIDLorJava) ? "yes" : "no";
       
   304           Doxygen::tagFile << "    <includes id=\"" 
       
   305                            << convertToXML(fd->getOutputFileBase()) << "\" "
       
   306                            << "name=\"" << convertToXML(fd->name()) << "\" "
       
   307                            << "local=\"" << locStr << "\" "
       
   308                            << "imported=\"" << impStr << "\">"
       
   309                            << convertToXML(ii->includeName)
       
   310                            << "</includes>" 
       
   311                            << endl;
       
   312         }
       
   313       }
       
   314       else
       
   315       {
       
   316         ol.docify(ii->includeName);
       
   317       }
       
   318       
       
   319       ol.enableAll();
       
   320       if (ii->local || isIDLorJava)
       
   321         ol.docify("\"");
       
   322       else
       
   323         ol.docify(">");
       
   324       if (isIDLorJava) 
       
   325         ol.docify(";");
       
   326       ol.endTypewriter();
       
   327       ol.lineBreak();
       
   328     }
       
   329     ol.endTextBlock();
       
   330   }
       
   331 }
       
   332 
       
   333 void FileDef::writeIncludeGraph(OutputList &ol)
       
   334 {
       
   335   if (Config_getBool("HAVE_DOT") /*&& Config_getBool("INCLUDE_GRAPH")*/)
       
   336   {
       
   337     //printf("Graph for file %s\n",name().data());
       
   338     DotInclDepGraph incDepGraph(this,FALSE);
       
   339     if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig())
       
   340     {
       
   341       ol.startTextBlock(); 
       
   342       ol.disable(OutputGenerator::Man);
       
   343       ol.startInclDepGraph();
       
   344       ol.parseText(theTranslator->trInclDepGraph(name()));
       
   345       ol.endInclDepGraph(incDepGraph);
       
   346       ol.enableAll();
       
   347       ol.endTextBlock(TRUE);
       
   348     }
       
   349     //incDepGraph.writeGraph(Config_getString("HTML_OUTPUT"),fd->getOutputFileBase());
       
   350   }
       
   351 }
       
   352 
       
   353 void FileDef::writeIncludedByGraph(OutputList &ol)
       
   354 {
       
   355   if (Config_getBool("HAVE_DOT") /*&& Config_getBool("INCLUDED_BY_GRAPH")*/)
       
   356   {
       
   357     //printf("Graph for file %s\n",name().data());
       
   358     DotInclDepGraph incDepGraph(this,TRUE);
       
   359     if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig())
       
   360     {
       
   361       ol.startTextBlock(); 
       
   362       ol.disable(OutputGenerator::Man);
       
   363       ol.startInclDepGraph();
       
   364       ol.parseText(theTranslator->trInclByDepGraph());
       
   365       ol.endInclDepGraph(incDepGraph);
       
   366       ol.enableAll();
       
   367       ol.endTextBlock(TRUE);
       
   368     }
       
   369     //incDepGraph.writeGraph(Config_getString("HTML_OUTPUT"),fd->getOutputFileBase());
       
   370   }
       
   371 }
       
   372 
       
   373 
       
   374 void FileDef::writeSourceLink(OutputList &ol)
       
   375 {
       
   376   //printf("%s: generateSourceFile()=%d\n",name().data(),generateSourceFile());
       
   377   if (generateSourceFile())
       
   378   {
       
   379     ol.disableAllBut(OutputGenerator::Html);
       
   380     ol.startParagraph();
       
   381     ol.startTextLink(includeName(),0);
       
   382     ol.parseText(theTranslator->trGotoSourceCode());
       
   383     ol.endTextLink();
       
   384     ol.endParagraph();
       
   385     ol.enableAll();
       
   386   }
       
   387 }
       
   388 
       
   389 void FileDef::writeNamespaceDeclarations(OutputList &ol,const QCString &title)
       
   390 {
       
   391   // write list of namespaces
       
   392   if (namespaceSDict) namespaceSDict->writeDeclaration(ol,title);
       
   393 }
       
   394 
       
   395 void FileDef::writeClassDeclarations(OutputList &ol,const QCString &title)
       
   396 {
       
   397   // write list of classes
       
   398   if (classSDict) classSDict->writeDeclaration(ol,0,title,FALSE);
       
   399 }
       
   400 
       
   401 void FileDef::startMemberDeclarations(OutputList &ol)
       
   402 {
       
   403   ol.startMemberSections();
       
   404 }
       
   405 
       
   406 void FileDef::endMemberDeclarations(OutputList &ol)
       
   407 {
       
   408   ol.endMemberSections();
       
   409 }
       
   410 
       
   411 void FileDef::startMemberDocumentation(OutputList &ol)
       
   412 {
       
   413   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
       
   414   {
       
   415     ol.disable(OutputGenerator::Html);
       
   416     Doxygen::suppressDocWarnings = TRUE;
       
   417   }
       
   418 }
       
   419 
       
   420 void FileDef::endMemberDocumentation(OutputList &ol)
       
   421 {
       
   422   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
       
   423   {
       
   424     ol.enable(OutputGenerator::Html);
       
   425     Doxygen::suppressDocWarnings = FALSE;
       
   426   }
       
   427 }
       
   428 
       
   429 void FileDef::writeMemberGroups(OutputList &ol)
       
   430 {
       
   431   /* write user defined member groups */
       
   432   if (memberGroupSDict)
       
   433   {
       
   434     MemberGroupSDict::Iterator mgli(*memberGroupSDict);
       
   435     MemberGroup *mg;
       
   436     for (;(mg=mgli.current());++mgli)
       
   437     {
       
   438       if ((!mg->allMembersInSameSection() || !m_subGrouping) 
       
   439           && mg->header()!="[NOHEADER]")
       
   440       {
       
   441         mg->writeDeclarations(ol,0,0,this,0);
       
   442       }
       
   443     }
       
   444   }
       
   445 }
       
   446 
       
   447 void FileDef::writeAuthorSection(OutputList &ol)
       
   448 {
       
   449   // write Author section (Man only)
       
   450   ol.pushGeneratorState();
       
   451   ol.disableAllBut(OutputGenerator::Man);
       
   452   ol.startGroupHeader();
       
   453   ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
       
   454   ol.endGroupHeader();
       
   455   ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME")));
       
   456   ol.popGeneratorState();
       
   457 }
       
   458 
       
   459 /*! Write the documentation page for this file to the file of output
       
   460     generators \a ol. 
       
   461 */
       
   462 void FileDef::writeDocumentation(OutputList &ol)
       
   463 {
       
   464   //funcList->countDecMembers();
       
   465   
       
   466   //QCString fn = name();
       
   467   //if (Config_getBool("FULL_PATH_NAMES"))
       
   468   //{
       
   469   //  fn.prepend(stripFromPath(getPath().copy()));
       
   470   //}
       
   471 
       
   472   //printf("WriteDocumentation diskname=%s\n",diskname.data());
       
   473   
       
   474   QCString versionTitle;
       
   475   if (!fileVersion.isEmpty())
       
   476   {
       
   477     versionTitle=("("+fileVersion+")");
       
   478   }
       
   479   QCString title = docname+versionTitle;
       
   480   QCString pageTitle=theTranslator->trFileReference(docname);
       
   481 
       
   482   if (Config_getBool("SHOW_DIRECTORIES") && getDirDef())
       
   483   {
       
   484     startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,TRUE);
       
   485     getDirDef()->writeNavigationPath(ol);
       
   486     ol.endQuickIndices();
       
   487     ol.startContents();
       
   488     QCString pageTitleShort=theTranslator->trFileReference(name());
       
   489     startTitle(ol,getOutputFileBase());
       
   490     ol.pushGeneratorState();
       
   491       ol.disableAllBut(OutputGenerator::Html);
       
   492       ol.parseText(pageTitleShort); // Html only
       
   493       ol.enableAll();
       
   494       ol.disable(OutputGenerator::Html);
       
   495       ol.parseText(pageTitle); // other output formats
       
   496     ol.popGeneratorState();
       
   497     addGroupListToTitle(ol,this);
       
   498     endTitle(ol,getOutputFileBase(),title);
       
   499   }
       
   500   else
       
   501   {
       
   502     startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible);
       
   503     startTitle(ol,getOutputFileBase());
       
   504     ol.parseText(pageTitle);
       
   505     addGroupListToTitle(ol,this);
       
   506     endTitle(ol,getOutputFileBase(),title);
       
   507   }
       
   508   if (!fileVersion.isEmpty())
       
   509   {
       
   510     ol.disableAllBut(OutputGenerator::Html);
       
   511     ol.startProjectNumber();
       
   512     ol.docify(versionTitle);
       
   513     ol.endProjectNumber();
       
   514     ol.enableAll();
       
   515   }
       
   516   
       
   517   if (Doxygen::searchIndex)
       
   518   {
       
   519     Doxygen::searchIndex->setCurrentDoc(pageTitle,getOutputFileBase());
       
   520     Doxygen::searchIndex->addWord(localName(),TRUE);
       
   521   }
       
   522   
       
   523   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
       
   524   {
       
   525     Doxygen::tagFile << "  <compound kind=\"file\">" << endl;
       
   526     Doxygen::tagFile << "    <name>" << convertToXML(name()) << "</name>" << endl;
       
   527     Doxygen::tagFile << "    <path>" << convertToXML(getPath()) << "</path>" << endl;
       
   528     Doxygen::tagFile << "    <filename>" 
       
   529                      << convertToXML(getOutputFileBase()) 
       
   530                      << "</filename>" << endl;
       
   531   }
       
   532 
       
   533   //---------------------------------------- start flexible part -------------------------------
       
   534   
       
   535   QListIterator<LayoutDocEntry> eli(
       
   536       LayoutDocManager::instance().docEntries(LayoutDocManager::File));
       
   537   LayoutDocEntry *lde;
       
   538   for (eli.toFirst();(lde=eli.current());++eli)
       
   539   {
       
   540     switch (lde->kind())
       
   541     {
       
   542       case LayoutDocEntry::BriefDesc: 
       
   543         writeBriefDescription(ol);
       
   544         break; 
       
   545       case LayoutDocEntry::MemberDeclStart: 
       
   546         startMemberDeclarations(ol);
       
   547         break; 
       
   548       case LayoutDocEntry::FileIncludes:
       
   549         writeIncludeFiles(ol);
       
   550         break;
       
   551       case LayoutDocEntry::FileIncludeGraph:
       
   552         writeIncludeGraph(ol);
       
   553         break;
       
   554       case LayoutDocEntry::FileIncludedByGraph:
       
   555         writeIncludedByGraph(ol);
       
   556         break;
       
   557       case LayoutDocEntry::FileSourceLink:
       
   558         writeSourceLink(ol);
       
   559         break;
       
   560       case LayoutDocEntry::FileClasses: 
       
   561         {
       
   562           LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
       
   563           writeClassDeclarations(ol,ls->title);
       
   564         }
       
   565         break; 
       
   566       case LayoutDocEntry::FileNamespaces: 
       
   567         {
       
   568           LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
       
   569           writeNamespaceDeclarations(ol,ls->title);
       
   570         }
       
   571         break; 
       
   572       case LayoutDocEntry::MemberGroups: 
       
   573         writeMemberGroups(ol);
       
   574         break; 
       
   575       case LayoutDocEntry::MemberDecl: 
       
   576         {
       
   577           LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
       
   578           writeMemberDeclarations(ol,lmd->type,lmd->title);
       
   579         }
       
   580         break; 
       
   581       case LayoutDocEntry::MemberDeclEnd: 
       
   582         endMemberDeclarations(ol);
       
   583         break;
       
   584       case LayoutDocEntry::DetailedDesc: 
       
   585         {
       
   586           LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
       
   587           writeDetailedDescription(ol,ls->title);
       
   588         }
       
   589         break;
       
   590       case LayoutDocEntry::MemberDefStart: 
       
   591         startMemberDocumentation(ol);
       
   592         break; 
       
   593       case LayoutDocEntry::MemberDef: 
       
   594         {
       
   595           LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
       
   596           writeMemberDocumentation(ol,lmd->type,lmd->title);
       
   597         }
       
   598         break;
       
   599       case LayoutDocEntry::MemberDefEnd: 
       
   600         endMemberDocumentation(ol);
       
   601         break;
       
   602       case LayoutDocEntry::AuthorSection: 
       
   603         writeAuthorSection(ol);
       
   604         break;
       
   605       case LayoutDocEntry::ClassIncludes:
       
   606       case LayoutDocEntry::ClassInheritanceGraph:
       
   607       case LayoutDocEntry::ClassNestedClasses:
       
   608       case LayoutDocEntry::ClassCollaborationGraph:
       
   609       case LayoutDocEntry::ClassAllMembersLink:
       
   610       case LayoutDocEntry::ClassUsedFiles:
       
   611       case LayoutDocEntry::NamespaceNestedNamespaces:
       
   612       case LayoutDocEntry::NamespaceClasses:
       
   613       case LayoutDocEntry::GroupClasses: 
       
   614       case LayoutDocEntry::GroupNamespaces:
       
   615       case LayoutDocEntry::GroupDirs: 
       
   616       case LayoutDocEntry::GroupNestedGroups: 
       
   617       case LayoutDocEntry::GroupFiles:
       
   618       case LayoutDocEntry::GroupGraph: 
       
   619       case LayoutDocEntry::GroupPageDocs:
       
   620       case LayoutDocEntry::DirSubDirs:
       
   621       case LayoutDocEntry::DirFiles:
       
   622       case LayoutDocEntry::DirGraph:
       
   623         err("Internal inconsistency: member %d should not be part of "
       
   624             "LayoutDocManager::File entry list\n",lde->kind());
       
   625         break;
       
   626     }
       
   627   }
       
   628 
       
   629   //---------------------------------------- end flexible part -------------------------------
       
   630 
       
   631   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
       
   632   {
       
   633     writeDocAnchorsToTagFile();
       
   634     Doxygen::tagFile << "  </compound>" << endl;
       
   635   }
       
   636 
       
   637   endFile(ol);
       
   638 
       
   639   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
       
   640   {
       
   641     MemberList *ml = getMemberList(MemberList::allMembersList);
       
   642     if (ml) ml->sort();
       
   643     writeMemberPages(ol);
       
   644   }
       
   645 }
       
   646 
       
   647 void FileDef::writeMemberPages(OutputList &ol)
       
   648 {
       
   649   ol.pushGeneratorState();
       
   650   ol.disableAllBut(OutputGenerator::Html);
       
   651   
       
   652   QListIterator<MemberList> mli(m_memberLists);
       
   653   MemberList *ml;
       
   654   for (mli.toFirst();(ml=mli.current());++mli)
       
   655   {
       
   656     if (ml->listType()&MemberList::documentationLists)
       
   657     {
       
   658       ml->writeDocumentationPage(ol,name(),this);
       
   659     }
       
   660   }
       
   661 
       
   662   ol.popGeneratorState();
       
   663 }
       
   664 
       
   665 void FileDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
       
   666 {
       
   667   static bool createSubDirs=Config_getBool("CREATE_SUBDIRS");
       
   668 
       
   669   ol.writeString("      <div class=\"navtab\">\n");
       
   670   ol.writeString("        <table>\n");
       
   671 
       
   672   MemberList *allMemberList = getMemberList(MemberList::allMembersList);
       
   673   if (allMemberList)
       
   674   {
       
   675     MemberListIterator mli(*allMemberList);
       
   676     MemberDef *md;
       
   677     for (mli.toFirst();(md=mli.current());++mli)
       
   678     {
       
   679       if (md->getFileDef()==this && md->getNamespaceDef()==0 && md->isLinkable())
       
   680       {
       
   681         ol.writeString("          <tr><td class=\"navtab\">");
       
   682         if (md->isLinkableInProject())
       
   683         {
       
   684           if (md==currentMd) // selected item => highlight
       
   685           {
       
   686             ol.writeString("<a class=\"qindexHL\" ");
       
   687           }
       
   688           else
       
   689           {
       
   690             ol.writeString("<a class=\"qindex\" ");
       
   691           }
       
   692           ol.writeString("href=\"");
       
   693           if (createSubDirs) ol.writeString("../../");
       
   694           ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
       
   695           ol.writeString("\">");
       
   696           ol.writeString(md->localName());
       
   697           ol.writeString("</a>");
       
   698         }
       
   699         ol.writeString("</td></tr>\n");
       
   700       }
       
   701     }
       
   702   }
       
   703 
       
   704   ol.writeString("        </table>\n");
       
   705   ol.writeString("      </div>\n");
       
   706 }
       
   707 
       
   708 /*! Write a source listing of this file to the output */
       
   709 void FileDef::writeSource(OutputList &ol)
       
   710 {
       
   711   static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES");
       
   712   static bool latexSourceCode   = Config_getBool("LATEX_SOURCE_CODE");
       
   713   QCString title = docname;
       
   714   if (!fileVersion.isEmpty())
       
   715   {
       
   716     title+=(" ("+fileVersion+")");
       
   717   }
       
   718   QCString pageTitle = theTranslator->trSourceFile(title);
       
   719   ol.disable(OutputGenerator::Man);
       
   720   ol.disable(OutputGenerator::RTF);
       
   721   if (!latexSourceCode) ol.disable(OutputGenerator::Latex);
       
   722 
       
   723   if (Config_getBool("SHOW_DIRECTORIES") && getDirDef())
       
   724   {
       
   725     startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,TRUE);
       
   726     getDirDef()->writeNavigationPath(ol);
       
   727     ol.endQuickIndices();
       
   728     ol.startContents();
       
   729     startTitle(ol,getOutputFileBase());
       
   730     ol.parseText(name());
       
   731     endTitle(ol,getOutputFileBase(),title);
       
   732   }
       
   733   else
       
   734   {
       
   735     startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,TRUE);
       
   736     startTitle(ol,getSourceFileBase());
       
   737     ol.parseText(title);
       
   738     endTitle(ol,getSourceFileBase(),0);
       
   739   }
       
   740 
       
   741   if (isLinkable())
       
   742   {
       
   743     if (latexSourceCode) ol.disable(OutputGenerator::Latex);
       
   744     ol.startTextLink(getOutputFileBase(),0);
       
   745     ol.parseText(theTranslator->trGotoDocumentation());
       
   746     ol.endTextLink();
       
   747     if (latexSourceCode) ol.enable(OutputGenerator::Latex);
       
   748   }
       
   749 
       
   750   ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension());
       
   751   pIntf->resetCodeParserState();
       
   752   ol.startCodeFragment();
       
   753   pIntf->parseCode(ol,0,
       
   754             fileToString(absFilePath(),filterSourceFiles),
       
   755             FALSE,0,this
       
   756            );
       
   757   ol.endCodeFragment();
       
   758   endFile(ol);
       
   759   ol.enableAll();
       
   760 }
       
   761 
       
   762 void FileDef::parseSource()
       
   763 {
       
   764   static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES");
       
   765   DevNullCodeDocInterface devNullIntf;
       
   766   ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension());
       
   767   pIntf->resetCodeParserState();
       
   768   pIntf->parseCode(
       
   769             devNullIntf,0,
       
   770             fileToString(absFilePath(),filterSourceFiles),
       
   771             FALSE,0,this
       
   772            );
       
   773 }
       
   774 
       
   775 void FileDef::addMembersToMemberGroup()
       
   776 {
       
   777   QListIterator<MemberList> mli(m_memberLists);
       
   778   MemberList *ml;
       
   779   for (mli.toFirst();(ml=mli.current());++mli)
       
   780   {
       
   781     if (ml->listType()&MemberList::declarationLists)
       
   782     {
       
   783       ::addMembersToMemberGroup(ml,&memberGroupSDict,this);
       
   784     }
       
   785   }
       
   786 
       
   787   // add members inside sections to their groups
       
   788   if (memberGroupSDict)
       
   789   {
       
   790     MemberGroupSDict::Iterator mgli(*memberGroupSDict);
       
   791     MemberGroup *mg;
       
   792     for (;(mg=mgli.current());++mgli)
       
   793     {
       
   794       if (mg->allMembersInSameSection() && m_subGrouping)
       
   795       {
       
   796         //printf("----> addToDeclarationSection(%s)\n",mg->header().data());
       
   797         mg->addToDeclarationSection();
       
   798       }
       
   799     }
       
   800   }
       
   801 }
       
   802 
       
   803 /*! Adds member definition \a md to the list of all members of this file */
       
   804 void FileDef::insertMember(MemberDef *md)
       
   805 {
       
   806   if (md->isHidden()) return;
       
   807   //printf("%s:FileDef::insertMember(%s (=%p) list has %d elements)\n",
       
   808   //    name().data(),md->name().data(),md,allMemberList.count());
       
   809   MemberList *allMemberList = getMemberList(MemberList::allMembersList);
       
   810   if (allMemberList && allMemberList->findRef(md)!=-1)  // TODO optimize the findRef!
       
   811   { 
       
   812     return;
       
   813   }
       
   814 
       
   815   if (allMemberList==0)
       
   816   {
       
   817     allMemberList = new MemberList(MemberList::allMembersList);;
       
   818     m_memberLists.append(allMemberList);
       
   819   }
       
   820   allMemberList->append(md); 
       
   821   //::addFileMemberNameToIndex(md);
       
   822   switch (md->memberType())
       
   823   {
       
   824     case MemberDef::Variable:     
       
   825     case MemberDef::Property:     
       
   826       addMemberToList(MemberList::decVarMembers,md);
       
   827       addMemberToList(MemberList::docVarMembers,md);
       
   828       break;
       
   829     case MemberDef::Function: 
       
   830       addMemberToList(MemberList::decFuncMembers,md);
       
   831       addMemberToList(MemberList::docFuncMembers,md);
       
   832       break;
       
   833     case MemberDef::Typedef:      
       
   834       addMemberToList(MemberList::decTypedefMembers,md);
       
   835       addMemberToList(MemberList::docTypedefMembers,md);
       
   836       break;
       
   837     case MemberDef::Enumeration:  
       
   838       addMemberToList(MemberList::decEnumMembers,md);
       
   839       addMemberToList(MemberList::docEnumMembers,md);
       
   840       break;
       
   841     case MemberDef::EnumValue:    // enum values are shown inside their enums
       
   842       break;
       
   843     case MemberDef::Define:       
       
   844       addMemberToList(MemberList::decDefineMembers,md);
       
   845       addMemberToList(MemberList::docDefineMembers,md);
       
   846       break;
       
   847     default:
       
   848        err("FileDef::insertMembers(): "
       
   849            "member `%s' with class scope `%s' inserted in file scope `%s'!\n",
       
   850            md->name().data(),
       
   851            md->getClassDef() ? md->getClassDef()->name().data() : "<global>",
       
   852            name().data());
       
   853   }
       
   854   //addMemberToGroup(md,groupId);
       
   855 }
       
   856 
       
   857 /*! Adds compound definition \a cd to the list of all compounds of this file */
       
   858 void FileDef::insertClass(ClassDef *cd)
       
   859 {
       
   860   if (cd->isHidden()) return;
       
   861   if (classSDict==0)
       
   862   {
       
   863     classSDict = new ClassSDict(17);
       
   864   }
       
   865   if (Config_getBool("SORT_BRIEF_DOCS"))
       
   866     classSDict->inSort(cd->name(),cd);
       
   867   else
       
   868     classSDict->append(cd->name(),cd);
       
   869 }
       
   870 
       
   871 /*! Adds namespace definition \a nd to the list of all compounds of this file */
       
   872 void FileDef::insertNamespace(NamespaceDef *nd)
       
   873 {
       
   874   if (nd->isHidden()) return;
       
   875   if (!nd->name().isEmpty() && 
       
   876       (namespaceSDict==0 || namespaceSDict->find(nd->name())==0))
       
   877   {
       
   878     if (namespaceSDict==0)
       
   879     {
       
   880       namespaceSDict = new NamespaceSDict;
       
   881     }
       
   882     if (Config_getBool("SORT_BRIEF_DOCS"))
       
   883       namespaceSDict->inSort(nd->name(),nd);
       
   884     else
       
   885       namespaceSDict->append(nd->name(),nd);
       
   886   }
       
   887 }
       
   888 
       
   889 void FileDef::addSourceRef(int line,Definition *d,MemberDef *md)
       
   890 {
       
   891   //printf("FileDef::addSourceDef(%d,%p,%p)\n",line,d,md);
       
   892   if (d)
       
   893   {
       
   894     if (srcDefDict==0)    srcDefDict    = new QIntDict<Definition>(257);
       
   895     if (srcMemberDict==0) srcMemberDict = new QIntDict<MemberDef>(257);
       
   896     srcDefDict->insert(line,d);
       
   897     if (md) srcMemberDict->insert(line,md);
       
   898     //printf("Adding member %s with anchor %s at line %d to file %s\n",
       
   899     //    md->name().data(),md->anchor().data(),line,name().data());
       
   900   }
       
   901 }
       
   902 
       
   903 Definition *FileDef::getSourceDefinition(int lineNr)
       
   904 {
       
   905   Definition *result=0;
       
   906   if (srcDefDict)
       
   907   {
       
   908     result = srcDefDict->find(lineNr);
       
   909   }
       
   910   return result;
       
   911 }
       
   912 
       
   913 MemberDef *FileDef::getSourceMember(int lineNr)
       
   914 {
       
   915   MemberDef *result=0;
       
   916   if (srcMemberDict)
       
   917   {
       
   918     result = srcMemberDict->find(lineNr);
       
   919   }
       
   920   return result;
       
   921 }
       
   922 
       
   923 
       
   924 void FileDef::addUsingDirective(NamespaceDef *nd)
       
   925 {
       
   926   if (usingDirList==0)
       
   927   {
       
   928     usingDirList = new NamespaceSDict;
       
   929   }
       
   930   if (usingDirList->find(nd->qualifiedName())==0)
       
   931   {
       
   932     usingDirList->append(nd->qualifiedName(),nd);
       
   933   }
       
   934   //printf("%p: FileDef::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count());
       
   935 }
       
   936 
       
   937 NamespaceSDict *FileDef::getUsedNamespaces() const 
       
   938 { 
       
   939   //printf("%p: FileDef::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0);
       
   940   return usingDirList; 
       
   941 }
       
   942 
       
   943 void FileDef::addUsingDeclaration(Definition *d)
       
   944 {
       
   945   if (usingDeclList==0)
       
   946   {
       
   947     usingDeclList = new SDict<Definition>(17);
       
   948   }
       
   949   if (usingDeclList->find(d->qualifiedName())==0)
       
   950   {
       
   951     usingDeclList->append(d->qualifiedName(),d);
       
   952   }
       
   953 }
       
   954 
       
   955 void FileDef::addIncludeDependency(FileDef *fd,const char *incName,bool local,
       
   956                                    bool imported)
       
   957 {
       
   958   //printf("FileDef::addIncludeDependency(%p,%s,%d)\n",fd,incName,local);
       
   959   QCString iName = fd ? fd->absFilePath().data() : incName;
       
   960   if (!iName.isEmpty() && (!includeDict || includeDict->find(iName)==0))
       
   961   {
       
   962     if (includeDict==0)
       
   963     {
       
   964       includeDict   = new QDict<IncludeInfo>(61);
       
   965       includeList   = new QList<IncludeInfo>;
       
   966       includeList->setAutoDelete(TRUE);
       
   967     }
       
   968     IncludeInfo *ii = new IncludeInfo;
       
   969     ii->fileDef     = fd;
       
   970     ii->includeName = incName;
       
   971     ii->local       = local;
       
   972     ii->imported    = imported;
       
   973     includeList->append(ii);
       
   974     includeDict->insert(iName,ii);
       
   975   }
       
   976 }
       
   977 
       
   978 void FileDef::addIncludedUsingDirectives()
       
   979 {
       
   980   if (visited) return;
       
   981   visited=TRUE;
       
   982   //printf("( FileDef::addIncludedUsingDirectives for file %s\n",name().data());
       
   983 
       
   984   NamespaceList nl;
       
   985   if (includeList) // file contains #includes
       
   986   {
       
   987     {
       
   988       QListIterator<IncludeInfo> iii(*includeList);
       
   989       IncludeInfo *ii;
       
   990       for (iii.toFirst();(ii=iii.current());++iii) // foreach #include...
       
   991       {
       
   992         if (ii->fileDef && !ii->fileDef->visited) // ...that is a known file
       
   993         {
       
   994           // recurse into this file
       
   995           ii->fileDef->addIncludedUsingDirectives();
       
   996         }
       
   997       }
       
   998     }
       
   999     {
       
  1000       QListIterator<IncludeInfo> iii(*includeList);
       
  1001       IncludeInfo *ii;
       
  1002       // iterate through list from last to first
       
  1003       for (iii.toLast();(ii=iii.current());--iii)
       
  1004       {
       
  1005         if (ii->fileDef && ii->fileDef!=this)
       
  1006         {
       
  1007           // add using directives
       
  1008           NamespaceSDict *unl = ii->fileDef->usingDirList;
       
  1009           if (unl)
       
  1010           {
       
  1011             NamespaceSDict::Iterator nli(*unl);
       
  1012             NamespaceDef *nd;
       
  1013             for (nli.toLast();(nd=nli.current());--nli)
       
  1014             {
       
  1015               // append each using directive found in a #include file
       
  1016               if (usingDirList==0) usingDirList = new NamespaceSDict;
       
  1017               //printf("Prepending used namespace %s to the list of file %s\n",
       
  1018               //    nd->name().data(),name().data());
       
  1019               if (usingDirList->find(nd->qualifiedName())==0) // not yet added
       
  1020               {
       
  1021                 usingDirList->prepend(nd->qualifiedName(),nd);
       
  1022               }
       
  1023             }
       
  1024           }
       
  1025           // add using declarations
       
  1026           SDict<Definition> *udl = ii->fileDef->usingDeclList;
       
  1027           if (udl)
       
  1028           {
       
  1029             SDict<Definition>::Iterator udi(*udl);
       
  1030             Definition *d;
       
  1031             for (udi.toLast();(d=udi.current());--udi)
       
  1032             {
       
  1033               //printf("Adding using declaration %s\n",d->name().data());
       
  1034               if (usingDeclList==0)
       
  1035               {
       
  1036                 usingDeclList = new SDict<Definition>(17);
       
  1037               }
       
  1038               if (usingDeclList->find(d->qualifiedName())==0)
       
  1039               {
       
  1040                 usingDeclList->prepend(d->qualifiedName(),d);
       
  1041               }
       
  1042             }
       
  1043           }
       
  1044         }
       
  1045       }
       
  1046     }
       
  1047   }
       
  1048   //printf(") end FileDef::addIncludedUsingDirectives for file %s\n",name().data());
       
  1049 }
       
  1050 
       
  1051 
       
  1052 void FileDef::addIncludedByDependency(FileDef *fd,const char *incName,
       
  1053                                       bool local,bool imported)
       
  1054 {
       
  1055   //printf("FileDef::addIncludedByDependency(%p,%s,%d)\n",fd,incName,local);
       
  1056   QCString iName = fd ? fd->absFilePath().data() : incName;
       
  1057   if (!iName.isEmpty() && (includedByDict==0 || includedByDict->find(iName)==0))
       
  1058   {
       
  1059     if (includedByDict==0)
       
  1060     {
       
  1061       includedByDict = new QDict<IncludeInfo>(61);
       
  1062       includedByList = new QList<IncludeInfo>;
       
  1063       includedByList->setAutoDelete(TRUE);
       
  1064     }
       
  1065     IncludeInfo *ii = new IncludeInfo;
       
  1066     ii->fileDef     = fd;
       
  1067     ii->includeName = incName;
       
  1068     ii->local       = local;
       
  1069     ii->imported    = imported;
       
  1070     includedByList->append(ii);
       
  1071     includedByDict->insert(iName,ii);
       
  1072   }
       
  1073 }
       
  1074 
       
  1075 bool FileDef::isIncluded(const QCString &name) const
       
  1076 {
       
  1077   if (name.isEmpty()) return FALSE;
       
  1078   return includeDict!=0 && includeDict->find(name)!=0;
       
  1079 }
       
  1080 
       
  1081 bool FileDef::generateSourceFile() const 
       
  1082 { 
       
  1083   QCString extension = name().right(4);
       
  1084   return !isReference() && 
       
  1085          (Config_getBool("SOURCE_BROWSER") || 
       
  1086            (Config_getBool("VERBATIM_HEADERS") && guessSection(name())==Entry::HEADER_SEC) 
       
  1087          ) &&
       
  1088          extension!=".doc" && extension!=".txt" && extension!=".dox"; 
       
  1089 }
       
  1090 
       
  1091 
       
  1092 void FileDef::addListReferences()
       
  1093 {
       
  1094   {
       
  1095     LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems();
       
  1096     addRefItem(xrefItems.pointer(),
       
  1097                getOutputFileBase(),
       
  1098                theTranslator->trFile(TRUE,TRUE),
       
  1099                getOutputFileBase(),name(),
       
  1100                0
       
  1101               );
       
  1102   }
       
  1103   if (memberGroupSDict)
       
  1104   {
       
  1105     MemberGroupSDict::Iterator mgli(*memberGroupSDict);
       
  1106     MemberGroup *mg;
       
  1107     for (;(mg=mgli.current());++mgli)
       
  1108     {
       
  1109       mg->addListReferences(this);
       
  1110     }
       
  1111   }
       
  1112   QListIterator<MemberList> mli(m_memberLists);
       
  1113   MemberList *ml;
       
  1114   for (mli.toFirst();(ml=mli.current());++mli)
       
  1115   {
       
  1116     if (ml->listType()&MemberList::documentationLists)
       
  1117     {
       
  1118       ml->addListReferences(this);
       
  1119     }
       
  1120   }
       
  1121 }
       
  1122 
       
  1123 //-------------------------------------------------------------------
       
  1124 
       
  1125 static int findMatchingPart(const QCString &path,const QCString dir)
       
  1126 {
       
  1127   int si1;
       
  1128   int pos1=0,pos2=0;
       
  1129   while ((si1=path.find('/',pos1))!=-1)
       
  1130   {
       
  1131     int si2=dir.find('/',pos2);
       
  1132     //printf("  found slash at pos %d in path %d: %s<->%s\n",si1,si2,
       
  1133     //    path.mid(pos1,si1-pos2).data(),dir.mid(pos2).data());
       
  1134     if (si2==-1 && path.mid(pos1,si1-pos2)==dir.mid(pos2)) // match at end
       
  1135     {
       
  1136       return dir.length();
       
  1137     }
       
  1138     if (si1!=si2 || path.mid(pos1,si1-pos2)!=dir.mid(pos2,si2-pos2)) // no match in middle
       
  1139     {
       
  1140       return QMAX(pos1-1,0);
       
  1141     }
       
  1142     pos1=si1+1;
       
  1143     pos2=si2+1;
       
  1144   }
       
  1145   return 0;
       
  1146 }
       
  1147 
       
  1148 static Directory *findDirNode(Directory *root,const QCString &name)
       
  1149 {
       
  1150   QListIterator<DirEntry> dli(root->children());
       
  1151   DirEntry *de;
       
  1152   for (dli.toFirst();(de=dli.current());++dli)
       
  1153   {
       
  1154     if (de->kind()==DirEntry::Dir)
       
  1155     {
       
  1156       Directory *dir = (Directory *)de;
       
  1157       QCString dirName=dir->name();
       
  1158       int sp=findMatchingPart(name,dirName);
       
  1159       //printf("findMatchingPart(%s,%s)=%d\n",name.data(),dirName.data(),sp);
       
  1160       if (sp>0) // match found
       
  1161       {
       
  1162         if ((uint)sp==dirName.length()) // whole directory matches
       
  1163         {
       
  1164           // recurse into the directory
       
  1165           return findDirNode(dir,name.mid(dirName.length()+1));
       
  1166         } 
       
  1167         else // partial match => we need to split the path into three parts
       
  1168         {
       
  1169           QCString baseName     =dirName.left(sp);
       
  1170           QCString oldBranchName=dirName.mid(sp+1);
       
  1171           QCString newBranchName=name.mid(sp+1);
       
  1172           // strip file name from path
       
  1173           int newIndex=newBranchName.findRev('/');
       
  1174           if (newIndex>0) newBranchName=newBranchName.left(newIndex);
       
  1175 
       
  1176           //printf("Splitting off part in new branch \n"
       
  1177           //    "base=%s old=%s new=%s\n",
       
  1178           //    baseName.data(),
       
  1179           //    oldBranchName.data(),
       
  1180           //    newBranchName.data()
       
  1181           //      );
       
  1182           Directory *base = new Directory(root,baseName);
       
  1183           Directory *newBranch = new Directory(base,newBranchName);
       
  1184           dir->reParent(base);
       
  1185           dir->rename(oldBranchName);
       
  1186           base->addChild(dir);
       
  1187           base->addChild(newBranch);
       
  1188           dir->setLast(FALSE);
       
  1189           // remove DirEntry container from list (without deleting it)
       
  1190           root->children().setAutoDelete(FALSE);
       
  1191           root->children().removeRef(dir);
       
  1192           root->children().setAutoDelete(TRUE);
       
  1193           // add new branch to the root
       
  1194           if (!root->children().isEmpty())
       
  1195           {
       
  1196             root->children().last()->setLast(FALSE); 
       
  1197           }
       
  1198           root->addChild(base);
       
  1199           return newBranch;
       
  1200         }
       
  1201       }
       
  1202     }
       
  1203   }
       
  1204   int si=name.findRev('/');
       
  1205   if (si==-1) // no subdir
       
  1206   {
       
  1207     return root; // put the file under the root node.
       
  1208   }
       
  1209   else // need to create a subdir 
       
  1210   {
       
  1211     QCString baseName = name.left(si);
       
  1212     //printf("new subdir %s\n",baseName.data());
       
  1213     Directory *newBranch = new Directory(root,baseName);
       
  1214     if (!root->children().isEmpty())
       
  1215     {
       
  1216       root->children().last()->setLast(FALSE); 
       
  1217     }
       
  1218     root->addChild(newBranch);
       
  1219     return newBranch;
       
  1220   }
       
  1221 }
       
  1222 
       
  1223 static void mergeFileDef(Directory *root,FileDef *fd)
       
  1224 {
       
  1225   QCString rootPath = root->name();
       
  1226   QCString filePath = fd->absFilePath();
       
  1227   //printf("merging %s\n",filePath.data());
       
  1228   Directory *dirNode = findDirNode(root,filePath);
       
  1229   if (!dirNode->children().isEmpty())
       
  1230   {
       
  1231     dirNode->children().last()->setLast(FALSE); 
       
  1232   }
       
  1233   DirEntry *e=new DirEntry(dirNode,fd);
       
  1234   dirNode->addChild(e);
       
  1235 }
       
  1236 
       
  1237 #if 0
       
  1238 static void generateIndent(QTextStream &t,DirEntry *de,int level)
       
  1239 {
       
  1240   if (de->parent())
       
  1241   {
       
  1242     generateIndent(t,de->parent(),level+1);
       
  1243   }
       
  1244   // from the root up to node n do...
       
  1245   if (level==0) // item before a dir or document
       
  1246   {
       
  1247     if (de->isLast())
       
  1248     {
       
  1249       if (de->kind()==DirEntry::Dir)
       
  1250       {
       
  1251         t << "<img " << FTV_IMGATTRIBS(plastnode) << "/>";
       
  1252       }
       
  1253       else
       
  1254       {
       
  1255         t << "<img " << FTV_IMGATTRIBS(lastnode) << "/>";
       
  1256       }
       
  1257     }
       
  1258     else
       
  1259     {
       
  1260       if (de->kind()==DirEntry::Dir)
       
  1261       {
       
  1262         t << "<img " << FTV_IMGATTRIBS(pnode) << "/>";
       
  1263       }
       
  1264       else
       
  1265       {
       
  1266         t << "<img " << FTV_IMGATTRIBS(node) << "/>";
       
  1267       }
       
  1268     }
       
  1269   }
       
  1270   else // item at another level
       
  1271   {
       
  1272     if (de->isLast())
       
  1273     {
       
  1274       t << "<img " << FTV_IMGATTRIBS(blank) << "/>";
       
  1275     }
       
  1276     else
       
  1277     {
       
  1278       t << "<img " << FTV_IMGATTRIBS(vertline) << "/>";
       
  1279     }
       
  1280   }
       
  1281 }
       
  1282 
       
  1283 static void writeDirTreeNode(QTextStream &t,Directory *root,int level)
       
  1284 {
       
  1285   QCString indent;
       
  1286   indent.fill(' ',level*2);
       
  1287   QListIterator<DirEntry> dli(root->children());
       
  1288   DirEntry *de;
       
  1289   for (dli.toFirst();(de=dli.current());++dli)
       
  1290   {
       
  1291     t << indent << "<p>";
       
  1292     generateIndent(t,de,0);
       
  1293     if (de->kind()==DirEntry::Dir)
       
  1294     {
       
  1295       Directory *dir=(Directory *)de;
       
  1296       //printf("%s [dir]: %s (last=%d,dir=%d)\n",indent.data(),dir->name().data(),dir->isLast(),dir->kind()==DirEntry::Dir);
       
  1297       t << "<img " << FTV_IMGATTRIBS(folderclosed) << "/>";
       
  1298       t << dir->name();
       
  1299       t << "</p>\n";
       
  1300       t << indent << "<div>\n";
       
  1301       writeDirTreeNode(t,dir,level+1);
       
  1302       t << indent << "</div>\n";
       
  1303     }
       
  1304     else
       
  1305     {
       
  1306       //printf("%s [file]: %s (last=%d,dir=%d)\n",indent.data(),de->file()->name().data(),de->isLast(),de->kind()==DirEntry::Dir);
       
  1307       t << "<img " << FTV_IMGATTRIBS(doc) << "/>";
       
  1308       t << de->file()->name();
       
  1309       t << "</p>\n";
       
  1310     }
       
  1311   }
       
  1312 }
       
  1313 #endif
       
  1314 
       
  1315 static void addDirsAsGroups(Directory *root,GroupDef *parent,int level)
       
  1316 {
       
  1317   GroupDef *gd=0;
       
  1318   if (root->kind()==DirEntry::Dir)
       
  1319   {
       
  1320     gd = new GroupDef("[generated]",
       
  1321                       1,
       
  1322                       root->path(), // name
       
  1323                       root->name()  // title
       
  1324                      );
       
  1325     if (parent) 
       
  1326     {
       
  1327       parent->addGroup(gd);
       
  1328       gd->makePartOfGroup(parent);
       
  1329     }
       
  1330     else
       
  1331     {
       
  1332       Doxygen::groupSDict->append(root->path(),gd);
       
  1333     }
       
  1334   }
       
  1335   QListIterator<DirEntry> dli(root->children());
       
  1336   DirEntry *de;
       
  1337   for (dli.toFirst();(de=dli.current());++dli)
       
  1338   {
       
  1339     if (de->kind()==DirEntry::Dir)
       
  1340     {
       
  1341       addDirsAsGroups((Directory *)de,gd,level+1);
       
  1342     }
       
  1343   }
       
  1344 }
       
  1345 
       
  1346 void generateFileTree()
       
  1347 {
       
  1348   Directory *root=new Directory(0,"root");
       
  1349   root->setLast(TRUE);
       
  1350   FileNameListIterator fnli(*Doxygen::inputNameList); 
       
  1351   FileName *fn;
       
  1352   for (fnli.toFirst();(fn=fnli.current());++fnli)
       
  1353   {
       
  1354     FileNameIterator fni(*fn);
       
  1355     FileDef *fd;
       
  1356     for (;(fd=fni.current());++fni)
       
  1357     {
       
  1358       mergeFileDef(root,fd);
       
  1359     }
       
  1360   }
       
  1361   //t << "<div class=\"directory\">\n";
       
  1362   //writeDirTreeNode(t,root,0);
       
  1363   //t << "</div>\n";
       
  1364   addDirsAsGroups(root,0,0);
       
  1365   delete root;
       
  1366 }
       
  1367 
       
  1368 //-------------------------------------------------------------------
       
  1369 
       
  1370 void FileDef::combineUsingRelations()
       
  1371 {
       
  1372   if (visited) return; // already done
       
  1373   visited=TRUE;
       
  1374   if (usingDirList)
       
  1375   {
       
  1376     NamespaceSDict::Iterator nli(*usingDirList);
       
  1377     NamespaceDef *nd;
       
  1378     for (nli.toFirst();(nd=nli.current());++nli)
       
  1379     {
       
  1380       nd->combineUsingRelations();
       
  1381     }
       
  1382     for (nli.toFirst();(nd=nli.current());++nli)
       
  1383     {
       
  1384       // add used namespaces of namespace nd to this namespace
       
  1385       if (nd->getUsedNamespaces())
       
  1386       {
       
  1387         NamespaceSDict::Iterator unli(*nd->getUsedNamespaces());
       
  1388         NamespaceDef *und;
       
  1389         for (unli.toFirst();(und=unli.current());++unli)
       
  1390         {
       
  1391           //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data());
       
  1392           addUsingDirective(und);
       
  1393         }
       
  1394       }
       
  1395       // add used classes of namespace nd to this namespace
       
  1396       if (nd->getUsedClasses())
       
  1397       {
       
  1398         SDict<Definition>::Iterator cli(*nd->getUsedClasses());
       
  1399         Definition *ucd;
       
  1400         for (cli.toFirst();(ucd=cli.current());++cli)
       
  1401         {
       
  1402           //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data());
       
  1403           addUsingDeclaration(ucd);
       
  1404         }
       
  1405       }
       
  1406     }
       
  1407   }
       
  1408 }
       
  1409 
       
  1410 bool FileDef::isDocumentationFile() const
       
  1411 {
       
  1412   return name().right(4)==".doc" ||
       
  1413          name().right(4)==".txt" ||
       
  1414          name().right(4)==".dox";
       
  1415 }
       
  1416 
       
  1417 void FileDef::acquireFileVersion()
       
  1418 {
       
  1419   QCString vercmd = Config_getString("FILE_VERSION_FILTER");
       
  1420   if (!vercmd.isEmpty()) 
       
  1421   {
       
  1422     msg("Version of %s : ",filepath.data());
       
  1423     QCString cmd = vercmd+" \""+filepath+"\"";
       
  1424     Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data());
       
  1425     FILE *f=portable_popen(cmd,"r");
       
  1426     if (!f)
       
  1427     {
       
  1428       err("Error: could not execute %s\n",vercmd.data());
       
  1429       return;
       
  1430     }
       
  1431     const int bufSize=1024;
       
  1432     char buf[bufSize];
       
  1433     int numRead = fread(buf,1,bufSize,f);
       
  1434     portable_pclose(f);
       
  1435     if (numRead > 0) 
       
  1436     {
       
  1437       fileVersion = QCString(buf,numRead).stripWhiteSpace();
       
  1438       msg("%s\n",fileVersion.data());
       
  1439     }
       
  1440     else 
       
  1441     {
       
  1442       msg("no version available\n");
       
  1443     }
       
  1444   }
       
  1445 }
       
  1446 
       
  1447 
       
  1448 QCString FileDef::getSourceFileBase() const
       
  1449 { 
       
  1450   if (Htags::useHtags)
       
  1451   {
       
  1452     return Htags::path2URL(filepath);
       
  1453   }
       
  1454   else
       
  1455   {
       
  1456     return convertNameToFile(diskname)+"_source"; 
       
  1457   }
       
  1458 }
       
  1459 
       
  1460 /*! Returns the name of the verbatim copy of this file (if any). */
       
  1461 QCString FileDef::includeName() const 
       
  1462 { 
       
  1463   if (Htags::useHtags)
       
  1464   {
       
  1465     return Htags::path2URL(filepath);
       
  1466   }
       
  1467   else
       
  1468   {
       
  1469     return convertNameToFile(diskname)+"_source"; 
       
  1470   }
       
  1471 }
       
  1472 
       
  1473 MemberList *FileDef::createMemberList(MemberList::ListType lt)
       
  1474 {
       
  1475   m_memberLists.setAutoDelete(TRUE);
       
  1476   QListIterator<MemberList> mli(m_memberLists);
       
  1477   MemberList *ml;
       
  1478   for (mli.toFirst();(ml=mli.current());++mli)
       
  1479   {
       
  1480     if (ml->listType()==lt)
       
  1481     {
       
  1482       return ml;
       
  1483     }
       
  1484   }
       
  1485   // not found, create a new member list
       
  1486   ml = new MemberList(lt);
       
  1487   m_memberLists.append(ml);
       
  1488   return ml;
       
  1489 }
       
  1490 
       
  1491 void FileDef::addMemberToList(MemberList::ListType lt,MemberDef *md)
       
  1492 {
       
  1493   static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
       
  1494   static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS");
       
  1495   MemberList *ml = createMemberList(lt);
       
  1496   if (((ml->listType()&MemberList::declarationLists) && sortBriefDocs) ||
       
  1497       ((ml->listType()&MemberList::documentationLists) && sortMemberDocs)
       
  1498      )
       
  1499     ml->inSort(md);
       
  1500   else
       
  1501     ml->append(md);
       
  1502   if (lt&MemberList::documentationLists)
       
  1503   {
       
  1504     ml->setInFile(TRUE);
       
  1505   }
       
  1506   if (ml->listType()&MemberList::declarationLists) md->setSectionList(this,ml);
       
  1507 }
       
  1508 
       
  1509 MemberList *FileDef::getMemberList(MemberList::ListType lt) const
       
  1510 {
       
  1511   FileDef *that = (FileDef*)this;
       
  1512   MemberList *ml = that->m_memberLists.first();
       
  1513   while (ml)
       
  1514   {
       
  1515     if (ml->listType()==lt)
       
  1516     {
       
  1517       return ml;
       
  1518     }
       
  1519     ml = that->m_memberLists.next();
       
  1520   }
       
  1521   return 0;
       
  1522 }
       
  1523 
       
  1524 void FileDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title)
       
  1525 {
       
  1526   static bool optVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
       
  1527   MemberList * ml = getMemberList(lt);
       
  1528   if (ml) 
       
  1529   {
       
  1530     if (optVhdl) // use specific declarations function
       
  1531     {
       
  1532       VhdlDocGen::writeVhdlDeclarations(ml,ol,0,0,this);
       
  1533     }
       
  1534     else
       
  1535     {
       
  1536       ml->writeDeclarations(ol,0,0,this,0,title,0);
       
  1537     }
       
  1538   }
       
  1539 }
       
  1540 
       
  1541 void FileDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title)
       
  1542 {
       
  1543   MemberList * ml = getMemberList(lt);
       
  1544   if (ml) ml->writeDocumentation(ol,name(),this,title);
       
  1545 }
       
  1546 
       
  1547 bool FileDef::isLinkableInProject() const
       
  1548 {
       
  1549   static bool showFiles = Config_getBool("SHOW_FILES");
       
  1550   return hasDocumentation() && !isReference() && showFiles;
       
  1551 }
       
  1552