diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/classdef.cpp | 365 | ||||
-rw-r--r-- | src/classdef.h | 1 | ||||
-rw-r--r-- | src/cmdmapper.cpp | 8 | ||||
-rw-r--r-- | src/cmdmapper.h | 28 | ||||
-rw-r--r-- | src/commentcnv.l | 77 | ||||
-rw-r--r-- | src/config.l | 42 | ||||
-rw-r--r-- | src/docparser.cpp | 198 | ||||
-rw-r--r-- | src/docparser.h | 3 | ||||
-rw-r--r-- | src/dot.cpp | 476 | ||||
-rw-r--r-- | src/dot.h | 12 | ||||
-rw-r--r-- | src/doxygen.cpp | 81 | ||||
-rw-r--r-- | src/filedef.cpp | 6 | ||||
-rw-r--r-- | src/htmldocvisitor.cpp | 10 | ||||
-rw-r--r-- | src/htmlgen.cpp | 2 | ||||
-rw-r--r-- | src/index.cpp | 3 | ||||
-rw-r--r-- | src/latexgen.cpp | 9 | ||||
-rw-r--r-- | src/memberdef.cpp | 13 | ||||
-rw-r--r-- | src/msc.cpp | 6 | ||||
-rw-r--r-- | src/namespacedef.cpp | 2 | ||||
-rw-r--r-- | src/translator_cn.h | 3 | ||||
-rw-r--r-- | src/util.cpp | 166 | ||||
-rw-r--r-- | src/util.h | 11 | ||||
-rw-r--r-- | src/xmlgen.cpp | 2 |
23 files changed, 846 insertions, 678 deletions
diff --git a/src/classdef.cpp b/src/classdef.cpp index a5bca00..bbfe3e8 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -596,7 +596,7 @@ void ClassDef::internalInsertMember(MemberDef *md, m_impl->isAbstract=TRUE; } - ::addClassMemberNameToIndex(md); + //::addClassMemberNameToIndex(md); if (addToAllList && !(Config_getBool("HIDE_FRIEND_COMPOUNDS") && md->isFriend() && @@ -982,6 +982,192 @@ void ClassDef::showUsedFiles(OutputList &ol) } +void ClassDef::writeClassDiagrams(OutputList &ol) +{ + // count direct inheritance relations + int count=0; + BaseClassDef *ibcd; + if (m_impl->inheritedBy) + { + ibcd=m_impl->inheritedBy->first(); + while (ibcd) + { + ClassDef *icd=ibcd->classDef; + if ( icd->isVisibleInHierarchy()) count++; + ibcd=m_impl->inheritedBy->next(); + } + } + if (m_impl->inherits) + { + ibcd=m_impl->inherits->first(); + while (ibcd) + { + ClassDef *icd=ibcd->classDef; + if ( icd->isVisibleInHierarchy()) count++; + ibcd=m_impl->inherits->next(); + } + } + + + bool renderDiagram = FALSE; + if (Config_getBool("HAVE_DOT") && Config_getBool("CLASS_GRAPH")) + // write class diagram using dot + { + DotClassGraph inheritanceGraph(this,DotNode::Inheritance); + if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.startDotGraph(); + ol.parseText(theTranslator->trClassDiagram(displayName())); + ol.endDotGraph(inheritanceGraph); + if (Config_getBool("GENERATE_LEGEND")) + { + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + ol.writeString("<center><font size=\"2\">["); + ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); + ol.docify(theTranslator->trLegend()); + ol.endHtmlLink(); + ol.writeString("]</font></center>"); + ol.popGeneratorState(); + } + ol.popGeneratorState(); + renderDiagram = TRUE; + } + } + else if (Config_getBool("CLASS_DIAGRAMS") && count>0) + // write class diagram using build-in generator + { + ClassDiagram diagram(this); // create a diagram of this class. + ol.startClassDiagram(); + ol.disable(OutputGenerator::Man); + ol.parseText(theTranslator->trClassDiagram(displayName())); + ol.enable(OutputGenerator::Man); + ol.endClassDiagram(diagram,getOutputFileBase(),displayName()); + renderDiagram = TRUE; + } + + if (Config_getBool("CLASS_DIAGRAMS") && renderDiagram) + { + ol.disableAllBut(OutputGenerator::Man); + } + + if (m_impl->inherits && (count=m_impl->inherits->count())>0) + { + //parseText(ol,theTranslator->trInherits()+" "); + + QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count()); + QRegExp marker("@[0-9]+"); + int index=0,newIndex,matchLen; + // now replace all markers in inheritLine with links to the classes + while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) + { + ol.parseText(inheritLine.mid(index,newIndex-index)); + bool ok; + uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); + BaseClassDef *bcd=m_impl->inherits->at(entryIndex); + if (ok && bcd) + { + ClassDef *cd=bcd->classDef; + if (cd->isLinkable()) + { + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <base"; + if (bcd->prot==Protected) + { + Doxygen::tagFile << " protection=\"protected\""; + } + else if (bcd->prot==Private) + { + Doxygen::tagFile << " protection=\"private\""; + } + if (bcd->virt==Virtual) + { + Doxygen::tagFile << " virtualness=\"virtual\""; + } + Doxygen::tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; + } + ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()+bcd->templSpecifiers); + } + else + { + ol.docify(cd->displayName()); + } + } + else + { + err("Error: invalid marker %d in inherits list!\n",entryIndex); + } + index=newIndex+matchLen; + } + ol.parseText(inheritLine.right(inheritLine.length()-index)); + ol.newParagraph(); + } + + // write subclasses + if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0) + { + QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count()); + QRegExp marker("@[0-9]+"); + int index=0,newIndex,matchLen; + // now replace all markers in inheritLine with links to the classes + while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) + { + ol.parseText(inheritLine.mid(index,newIndex-index)); + bool ok; + uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); + BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); + if (ok && bcd) + { + ClassDef *cd=bcd->classDef; + if (cd->isLinkable()) + { + ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()); + } + else + { + ol.docify(cd->displayName()); + } + writeInheritanceSpecifier(ol,bcd); + } + index=newIndex+matchLen; + } + ol.parseText(inheritLine.right(inheritLine.length()-index)); + ol.newParagraph(); + } + + if (Config_getBool("CLASS_DIAGRAMS") && renderDiagram) + { + ol.enableAll(); + } + + if (Config_getBool("HAVE_DOT") && Config_getBool("COLLABORATION_GRAPH")) + { + DotClassGraph usageImplGraph(this,DotNode::Collaboration); + if (!usageImplGraph.isTrivial()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.startDotGraph(); + ol.parseText(theTranslator->trCollaborationDiagram(displayName())); + ol.endDotGraph(usageImplGraph); + if (Config_getBool("GENERATE_LEGEND")) + { + ol.disableAllBut(OutputGenerator::Html); + ol.writeString("<center><font size=\"2\">["); + ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); + ol.docify(theTranslator->trLegend()); + ol.endHtmlLink(); + ol.writeString("]</font></center>"); + } + ol.popGeneratorState(); + } + } + +} + // write all documentation for this class void ClassDef::writeDocumentation(OutputList &ol) { @@ -1140,182 +1326,7 @@ void ClassDef::writeDocumentation(OutputList &ol) } } - - if (Config_getBool("CLASS_DIAGRAMS")) ol.disableAllBut(OutputGenerator::Man); - - - // write super classes - int count; - if (m_impl->inherits && (count=m_impl->inherits->count())>0) - { - //parseText(ol,theTranslator->trInherits()+" "); - - QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count()); - QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; - // now replace all markers in inheritLine with links to the classes - while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) - { - ol.parseText(inheritLine.mid(index,newIndex-index)); - bool ok; - uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inherits->at(entryIndex); - if (ok && bcd) - { - ClassDef *cd=bcd->classDef; - if (cd->isLinkable()) - { - if (!Config_getString("GENERATE_TAGFILE").isEmpty()) - { - Doxygen::tagFile << " <base"; - if (bcd->prot==Protected) - { - Doxygen::tagFile << " protection=\"protected\""; - } - else if (bcd->prot==Private) - { - Doxygen::tagFile << " protection=\"private\""; - } - if (bcd->virt==Virtual) - { - Doxygen::tagFile << " virtualness=\"virtual\""; - } - Doxygen::tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; - } - ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()+bcd->templSpecifiers); - } - else - { - ol.docify(cd->displayName()); - } - } - else - { - err("Error: invalid marker %d in inherits list!\n",entryIndex); - } - index=newIndex+matchLen; - } - ol.parseText(inheritLine.right(inheritLine.length()-index)); - ol.newParagraph(); - } - - // write subclasses - if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0) - { - QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count()); - QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; - // now replace all markers in inheritLine with links to the classes - while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) - { - ol.parseText(inheritLine.mid(index,newIndex-index)); - bool ok; - uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); - if (ok && bcd) - { - ClassDef *cd=bcd->classDef; - if (cd->isLinkable()) - { - ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()); - } - else - { - ol.docify(cd->displayName()); - } - writeInheritanceSpecifier(ol,bcd); - } - index=newIndex+matchLen; - } - ol.parseText(inheritLine.right(inheritLine.length()-index)); - ol.newParagraph(); - } - - if (Config_getBool("CLASS_DIAGRAMS")) ol.enableAll(); - - - count=0; - BaseClassDef *ibcd; - if (m_impl->inheritedBy) - { - ibcd=m_impl->inheritedBy->first(); - while (ibcd) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - ibcd=m_impl->inheritedBy->next(); - } - } - if (m_impl->inherits) - { - ibcd=m_impl->inherits->first(); - while (ibcd) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - ibcd=m_impl->inherits->next(); - } - } - - - if (Config_getBool("HAVE_DOT") && Config_getBool("CLASS_GRAPH")) - // write class diagram using dot - { - DotClassGraph inheritanceGraph(this,DotNode::Inheritance); - if (!inheritanceGraph.isTrivial()) - { - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - ol.startDotGraph(); - ol.parseText(theTranslator->trClassDiagram(displayName())); - ol.endDotGraph(inheritanceGraph); - if (Config_getBool("GENERATE_LEGEND")) - { - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - ol.writeString("<center><font size=\"2\">["); - ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); - ol.docify(theTranslator->trLegend()); - ol.endHtmlLink(); - ol.writeString("]</font></center>"); - ol.popGeneratorState(); - } - ol.popGeneratorState(); - } - } - else if (Config_getBool("CLASS_DIAGRAMS") && count>0) - // write class diagram using build-in generator - { - ClassDiagram diagram(this); // create a diagram of this class. - ol.startClassDiagram(); - ol.disable(OutputGenerator::Man); - ol.parseText(theTranslator->trClassDiagram(displayName())); - ol.enable(OutputGenerator::Man); - ol.endClassDiagram(diagram,getOutputFileBase(),displayName()); - } - - if (Config_getBool("HAVE_DOT") && Config_getBool("COLLABORATION_GRAPH")) - { - DotClassGraph usageImplGraph(this,DotNode::Collaboration); - if (!usageImplGraph.isTrivial()) - { - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - ol.startDotGraph(); - ol.parseText(theTranslator->trCollaborationDiagram(displayName())); - ol.endDotGraph(usageImplGraph); - if (Config_getBool("GENERATE_LEGEND")) - { - ol.disableAllBut(OutputGenerator::Html); - ol.writeString("<center><font size=\"2\">["); - ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); - ol.docify(theTranslator->trLegend()); - ol.endHtmlLink(); - ol.writeString("]</font></center>"); - } - ol.popGeneratorState(); - } - } + writeClassDiagrams(ol); // write link to list of all members (HTML only) if (m_impl->allMemberNameInfoSDict && diff --git a/src/classdef.h b/src/classdef.h index 2153def..b03ae52 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -310,6 +310,7 @@ class ClassDef : public Definition void mergeMembers(); void distributeMemberGroupDocumentation(); void writeDocumentation(OutputList &ol); + void writeClassDiagrams(OutputList &ol); void writeDocumentationForInnerClasses(OutputList &ol); void writeMemberDocumentation(OutputList &ol); void writeMemberPages(OutputList &ol); diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index 352095c..c4469c7 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -162,7 +162,8 @@ CommandMap htmlTagMap[] = { "exception", XML_EXCEPTION }, { "include", XML_INCLUDE }, { "item", XML_ITEM }, - { "list", XML_LIST }, + { "list", XML_LIST }, // type="table|bullet|number" + { "listheader", XML_LISTHEADER }, { "para", XML_PARA }, { "param", XML_PARAM }, { "paramref", XML_PARAMREF }, @@ -172,14 +173,15 @@ CommandMap htmlTagMap[] = { "see", XML_SEE }, { "seealso", XML_SEEALSO }, { "summary", XML_SUMMARY }, + { "term", XML_TERM }, { "value", XML_VALUE }, { 0, 0 } }; //---------------------------------------------------------------------------- -Mapper *Mappers::cmdMapper = new Mapper(cmdMap); -Mapper *Mappers::htmlTagMapper = new Mapper(htmlTagMap); +Mapper *Mappers::cmdMapper = new Mapper(cmdMap,TRUE); +Mapper *Mappers::htmlTagMapper = new Mapper(htmlTagMap,FALSE); void Mappers::freeMappers() { diff --git a/src/cmdmapper.h b/src/cmdmapper.h index 586e766..d5a2376 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -158,16 +158,18 @@ enum HtmlTagType XML_INCLUDE = XML_CmdMask + 5, XML_ITEM = XML_CmdMask + 6, XML_LIST = XML_CmdMask + 7, - XML_PARA = XML_CmdMask + 8, - XML_PARAM = XML_CmdMask + 9, - XML_PARAMREF = XML_CmdMask + 10, - XML_PERMISSION = XML_CmdMask + 11, - XML_REMARKS = XML_CmdMask + 12, - XML_RETURNS = XML_CmdMask + 13, - XML_SEE = XML_CmdMask + 14, - XML_SEEALSO = XML_CmdMask + 15, - XML_SUMMARY = XML_CmdMask + 16, - XML_VALUE = XML_CmdMask + 17 + XML_LISTHEADER = XML_CmdMask + 8, + XML_PARA = XML_CmdMask + 9, + XML_PARAM = XML_CmdMask + 10, + XML_PARAMREF = XML_CmdMask + 11, + XML_PERMISSION = XML_CmdMask + 12, + XML_REMARKS = XML_CmdMask + 13, + XML_RETURNS = XML_CmdMask + 14, + XML_SEE = XML_CmdMask + 15, + XML_SEEALSO = XML_CmdMask + 16, + XML_SUMMARY = XML_CmdMask + 17, + XML_TERM = XML_CmdMask + 18, + XML_VALUE = XML_CmdMask + 19 }; @@ -177,11 +179,12 @@ class Mapper int map(const char *n) { QCString name=n; + if (!m_cs) name=name.lower(); int *result; - return !name.isEmpty() && (result=m_map.find(name.lower())) ? *result: 0; + return !name.isEmpty() && (result=m_map.find(name)) ? *result: 0; } - Mapper(const CommandMap *cm) : m_map(89) + Mapper(const CommandMap *cm,bool caseSensitive) : m_map(89), m_cs(caseSensitive) { m_map.setAutoDelete(TRUE); const CommandMap *p = cm; @@ -193,6 +196,7 @@ class Mapper } private: QDict<int> m_map; + bool m_cs; }; struct Mappers diff --git a/src/commentcnv.l b/src/commentcnv.l index 9b9a946..b12d9d8 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -61,6 +61,10 @@ static QCString g_blockName; static int g_lastCommentContext; static bool g_inSpecialComment; +static QCString g_aliasString; +static int g_blockCount; +static int g_lastBlockContext; + static void replaceCommentMarker(const char *s,int len) { const char *p=s; @@ -223,27 +227,11 @@ static QCString handleCondCmdInAliases(const QCString &s) /** copies string \a s with length \a len to the output, while * replacing any alias commands found in the string. */ -static void replaceAliases(const char *s,int len) +static void replaceAliases(const char *s) { - static QRegExp cmd("[@\\\\][a-z_A-Z][a-z_A-Z0-9]*"); - QCString in=s; - int p=0,i,l; - while ((i=cmd.match(in,p,&l))!=-1) - { - copyToOutput(s+p,i-p); - QCString *pValue=Doxygen::aliasDict[in.mid(i+1,l-1)]; - if (pValue) - { - QCString val = handleCondCmdInAliases(*pValue); - copyToOutput(val.data(),val.length()); - } - else - { - copyToOutput(s+i,l); - } - p=i+l; - } - copyToOutput(s+p,len-p); + QCString result = resolveAliasCmd(s); + //printf("replaceAliases(%s)->'%s'\n",s,result.data()); + copyToOutput(result,result.length()); } @@ -274,6 +262,7 @@ void replaceComment(int offset); %x VerbatimCode %x ReadLine %x CondLine +%x ReadAliasArgs %% @@ -300,8 +289,7 @@ void replaceComment(int offset); } g_blockHeadCol=g_col; copyToOutput("/**",3); - //copyToOutput(yytext+i,yyleng-i); - replaceAliases(yytext+i,yyleng-i); + replaceAliases(yytext+i); g_inSpecialComment=TRUE; BEGIN(SComment); } @@ -310,8 +298,7 @@ void replaceComment(int offset); int i=17; //=strlen("//##Documentation"); g_blockHeadCol=g_col; copyToOutput("/**",3); - //copyToOutput(yytext+i,yyleng-i); - replaceAliases(yytext+i,yyleng-i); + replaceAliases(yytext+i); BEGIN(SComment); } <Scan>"//"/.*\n { /* one line C++ comment */ @@ -521,17 +508,37 @@ void replaceComment(int offset); if (*yytext=='\n') g_lineNr++; BEGIN(g_condCtx); } -<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias - QCString *pValue=Doxygen::aliasDict[yytext+1]; - if (pValue) - { - QCString val = handleCondCmdInAliases(*pValue); - copyToOutput(val.data(),val.length()); - } - else - { - copyToOutput(yytext,yyleng); - } +<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias without arguments + replaceAliases(yytext); + } +<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments + g_lastBlockContext=YY_START; + g_blockCount=1; + g_aliasString=yytext; + BEGIN( ReadAliasArgs ); + } +<ReadAliasArgs>[^{}\n\*]+ { + g_aliasString+=yytext; + } +<ReadAliasArgs>\n { + g_aliasString+=yytext; + g_lineNr++; + } +<ReadAliasArgs>"{" { + g_aliasString+=yytext; + g_blockCount++; + } +<ReadAliasArgs>"}" { + g_aliasString+=yytext; + g_blockCount--; + if (g_blockCount==0) + { + replaceAliases(g_aliasString); + BEGIN( g_lastBlockContext ); + } + } +<ReadAliasArgs>. { + g_aliasString+=yytext; } <ReadLine>. { copyToOutput(yytext,yyleng); diff --git a/src/config.l b/src/config.l index 0fad432..e3faf84 100644 --- a/src/config.l +++ b/src/config.l @@ -1078,12 +1078,13 @@ void Config::check() s=aliasList.first(); while (s) { - QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*[ \t]*="); + QRegExp re1("[a-z_A-Z][a-z_A-Z0-9]*[ \t]*="); // alias without argument + QRegExp re2("[a-z_A-Z][a-z_A-Z0-9]*{[0-9]*}[ \t]*="); // alias with argument QCString alias=s; alias=alias.stripWhiteSpace(); - if (alias.find(re)!=0) + if (alias.find(re1)!=0 && alias.find(re2)!=0) { - config_err("Illegal alias format `%s'. Use \"name=value\"\n", + config_err("Illegal alias format `%s'. Use \"name=value\" or \"name(n)=value\", where n is the number of arguments\n", alias.data()); } s=aliasList.next(); @@ -1250,16 +1251,12 @@ void Config::check() Config_getBool("INLINE_INFO")=FALSE; } -#if 0 - if (Config_getString("RTF_OUTPUT_ENCODING").isEmpty()) - { - Config_getString("RTF_OUTPUT_ENCODING")="ISO-8859-1"; - } - if (Config_getString("LATEX_OUTPUT_ENCODING").isEmpty()) + int &depth = Config_getInt("MAX_DOT_GRAPH_DEPTH"); + if (depth==0) { - Config_getString("LATEX_OUTPUT_ENCODING")="ISO-8859-1"; + depth=1000; } -#endif + // add default words if needed QStrList &annotationFromBrief = Config_getList("ABBREVIATE_BRIEF"); @@ -2072,7 +2069,9 @@ void Config::create() "If the SOURCE_BROWSER tag is set to YES then a list of source files will \n" "be generated. Documented entities will be cross-referenced with these sources. \n" "Note: To get rid of all source code in the generated output, make sure also \n" - "VERBATIM_HEADERS is set to NO. \n", + "VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH \n" + "then you must also enable this option. If you don't then doxygen will produce \n" + "a warning and turn it on anyway \n", FALSE ); cb = addBool( @@ -2895,14 +2894,27 @@ void Config::create() "The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of \n" "nodes that will be shown in the graph. If the number of nodes in a graph \n" "becomes larger than this value, doxygen will truncate the graph, which is \n" - "visualized by representing a node as a red box. Note that doxygen will always \n" - "show the root nodes and its direct children regardless of this setting. \n", + "visualized by representing a node as a red box. Note that doxygen if the number \n" + "of direct children of the root node in a graph is already larger than \n" + "MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note \n" + "that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. \n", 0,10000, 50 ); ci->addDependency("HAVE_DOT"); + ci = addInt( + "MAX_DOT_GRAPH_DEPTH", + "The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the \n" + "graphs generated by dot. A depth value of 3 means that only nodes reachable \n" + "from the root by following a path via at most 3 edges will be shown. Nodes \n" + "that lay further from the root node will be omitted. Note that setting this \n" + "option to 1 or 2 may greatly reduce the computation time needed for large \n" + "code bases. Also note that the size of a graph can be further restricted by \n" + "DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n", + 0,1000,0 + ); + ci->addDependency("HAVE_DOT"); addObsolete("MAX_DOT_GRAPH_WIDTH"); addObsolete("MAX_DOT_GRAPH_HEIGHT"); - addObsolete("MAX_DOT_GRAPH_DEPTH"); cb = addBool( "DOT_TRANSPARENT", "Set the DOT_TRANSPARENT tag to YES to generate images with a transparent \n" diff --git a/src/docparser.cpp b/src/docparser.cpp index da673bf..01d88ae 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -536,6 +536,18 @@ static bool insideOL(DocNode *n) //--------------------------------------------------------------------------- +static bool insideTable(DocNode *n) +{ + while (n) + { + if (n->kind()==DocNode::Kind_HtmlTable) return TRUE; + n=n->parent(); + } + return FALSE; +} + +//--------------------------------------------------------------------------- + ///*! Returns TRUE iff node n is a child of a language node */ //static bool insideLang(DocNode *n) //{ @@ -2820,6 +2832,43 @@ int DocHtmlCell::parse() return retval; } +int DocHtmlCell::parseXml() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlCell::parseXml() start\n")); + + // parse one or more paragraphs + bool isFirst=TRUE; + DocPara *par=0; + do + { + par = new DocPara(this); + if (isFirst) { par->markFirst(); isFirst=FALSE; } + m_children.append(par); + retval=par->parse(); + if (retval==TK_HTMLTAG) + { + int tagId=Mappers::htmlTagMapper->map(g_token->name); + if (tagId==XML_ITEM && g_token->endTag) // found </item> tag + { + retval=TK_NEWPARA; // ignore the tag + } + else if (tagId==XML_DESCRIPTION && g_token->endTag) // found </description> tag + { + retval=TK_NEWPARA; // ignore the tag + } + } + } + while (retval==TK_NEWPARA); + if (par) par->markLast(); + + DBG(("DocHtmlCell::parseXml() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + //--------------------------------------------------------------------------- int DocHtmlRow::parse() @@ -2888,6 +2937,68 @@ endrow: return retval; } +int DocHtmlRow::parseXml(bool isHeading) +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlRow::parseXml() start\n")); + + bool isFirst=TRUE; + DocHtmlCell *cell=0; + + // get next token + int tok=doctokenizerYYlex(); + // skip whitespace + while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); + // should find a html tag now + if (tok==TK_HTMLTAG) + { + int tagId=Mappers::htmlTagMapper->map(g_token->name); + if (tagId==XML_TERM && !g_token->endTag) // found <term> tag + { + } + else if (tagId==XML_DESCRIPTION && !g_token->endTag) // found <description> tag + { + } + else // found some other tag + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <term> or <description> tag but " + "found <%s> instead!",g_token->name.data()); + doctokenizerYYpushBackHtmlTag(g_token->name); + goto endrow; + } + } + else if (tok==0) // premature end of comment + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking" + " for a html description title"); + goto endrow; + } + else // token other than html token + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <td> or <th> tag but found %s token instead!", + tokToString(tok)); + goto endrow; + } + + do + { + cell=new DocHtmlCell(this,g_token->attribs,isHeading); + cell->markFirst(isFirst); + isFirst=FALSE; + m_children.append(cell); + retval=cell->parseXml(); + } + while (retval==RetVal_TableCell || retval==RetVal_TableHCell); + if (cell) cell->markLast(TRUE); + +endrow: + DBG(("DocHtmlRow::parseXml() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + //--------------------------------------------------------------------------- int DocHtmlTable::parse() @@ -2958,6 +3069,48 @@ getrow: return retval==RetVal_EndTable ? RetVal_OK : retval; } +int DocHtmlTable::parseXml() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlTable::parseXml() start\n")); + + // get next token + int tok=doctokenizerYYlex(); + // skip whitespace + while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); + // should find a html tag now + int tagId=0; + bool isHeader=FALSE; + if (tok==TK_HTMLTAG) + { + tagId=Mappers::htmlTagMapper->map(g_token->name); + if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag + { + retval=RetVal_TableRow; + } + if (tagId==XML_LISTHEADER && !g_token->endTag) // found <listheader> tag + { + retval=RetVal_TableRow; + isHeader=TRUE; + } + } + + // parse one or more rows + while (retval==RetVal_TableRow) + { + DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs); + m_children.append(tr); + retval=tr->parseXml(isHeader); + isHeader=FALSE; + } + + DBG(("DocHtmlTable::parseXml() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval==RetVal_EndTable ? RetVal_OK : retval; +} + uint DocHtmlTable::numCols() const { uint cols=0; @@ -4788,6 +4941,10 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag break; case XML_EXAMPLE: case XML_DESCRIPTION: + if (insideTable(this)) + { + retval=RetVal_TableCell; + } break; case XML_C: handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs); @@ -4836,19 +4993,31 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag } break; case XML_ITEM: - if (!insideUL(this) && !insideOL(this)) + case XML_LISTHEADER: + if (insideTable(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <item> tag found"); + retval=RetVal_TableRow; } - else + else if (insideUL(this) || insideOL(this)) { retval=RetVal_ListItem; } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <item> tag found"); + } break; case XML_RETURNS: retval = handleSimpleSection(DocSimpleSect::Return,TRUE); g_hasReturnCommand=TRUE; break; + case XML_TERM: + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE)); + if (insideTable(this)) + { + retval=RetVal_TableCell; + } + break; case XML_SEE: // I'm not sure if <see> is the same as <seealso> or if it // should you link a member without producing a section. The @@ -4923,14 +5092,25 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag case XML_LIST: { QString type; + findAttribute(tagHtmlAttribs,"type",&type); DocHtmlList::Type listType = DocHtmlList::Unordered; - if (findAttribute(tagHtmlAttribs,"type",&type) && type=="number") + if (type=="number") { listType=DocHtmlList::Ordered; } - DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,listType); - m_children.append(list); - retval=list->parseXml(); + if (type=="table") + { + DocHtmlTable *table = new DocHtmlTable(this,tagHtmlAttribs); + m_children.append(table); + retval=table->parseXml(); + } + else + { + HtmlAttribList emptyList; + DocHtmlList *list = new DocHtmlList(this,emptyList,listType); + m_children.append(list); + retval=list->parseXml(); + } } break; case XML_INCLUDE: @@ -5078,6 +5258,9 @@ int DocPara::handleHtmlEndTag(const QString &tagName) // ignore </a> tag (can be part of <a name=...></a> break; + case XML_TERM: + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE)); + break; case XML_SUMMARY: case XML_REMARKS: case XML_PARA: @@ -5094,6 +5277,7 @@ int DocPara::handleHtmlEndTag(const QString &tagName) handleStyleLeave(this,m_children,DocStyleChange::Code,"c"); break; case XML_ITEM: + case XML_LISTHEADER: case XML_INCLUDE: case XML_PERMISSION: case XML_DESCRIPTION: diff --git a/src/docparser.h b/src/docparser.h index 64b382d..bd51317 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -1140,6 +1140,7 @@ class DocHtmlCell : public CompAccept<DocHtmlCell>, public DocNode void markLast(bool v=TRUE) { m_isLast=v; } const HtmlAttribList &attribs() const { return m_attribs; } int parse(); + int parseXml(); private: DocNode * m_parent; @@ -1179,6 +1180,7 @@ class DocHtmlRow : public CompAccept<DocHtmlRow>, public DocNode void accept(DocVisitor *v) { CompAccept<DocHtmlRow>::accept(this,v); } const HtmlAttribList &attribs() const { return m_attribs; } int parse(); + int parseXml(bool header); private: DocNode * m_parent; @@ -1199,6 +1201,7 @@ class DocHtmlTable : public CompAccept<DocHtmlTable>, public DocNode bool hasCaption() { return m_caption!=0; } const HtmlAttribList &attribs() const { return m_attribs; } int parse(); + int parseXml(); uint numCols() const; void accept(DocVisitor *v); diff --git a/src/dot.cpp b/src/dot.cpp index 808dcca..603fc38 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -91,123 +91,6 @@ static void writeGraphFooter(QTextStream &t) t << "}" << endl; } -#if 0 -/*! converts the rectangles in a server site image map into a client - * site image map. - * \param t the stream to which the result is written. - * \param mapName the name of the map file. - * \param relPath the relative path to the root of the output directory - * (used in case CREATE_SUBDIRS is enabled). - * \param urlOnly if FALSE the url field in the map contains an external - * references followed by a $ and then the URL. - * \returns TRUE if succesful. - */ -static bool convertMapFile(QTextStream &t,const char *mapName, - const QCString relPath, bool urlOnly=FALSE) -{ - QFile f(mapName); - if (!f.open(IO_ReadOnly)) - { - err("Error opening map file %s for inclusion in the docs!\n",mapName); - return FALSE; - } - const int maxLineLen=1024; - char buf[maxLineLen]; - char url[maxLineLen]; - char ref[maxLineLen]; - int x1,y1,x2,y2; - while (!f.atEnd()) - { - bool isRef = FALSE; - int numBytes = f.readLine(buf,maxLineLen); - buf[numBytes-1]='\0'; - //printf("ReadLine `%s'\n",buf); - if (strncmp(buf,"rect",4)==0) - { - // obtain the url and the coordinates in the order used by graphviz-1.5 - sscanf(buf,"rect %s %d,%d %d,%d",url,&x1,&y1,&x2,&y2); - - if ( strcmp(url,"\\ref") == 0 ) - { - isRef = TRUE; - sscanf(buf,"rect %s %s %d,%d %d,%d",ref,url,&x1,&y1,&x2,&y2); - } - - // later versions of graphviz corrected the y coordinate order - // the rule is that y2>=y1, so test and switch if needed - if (y2<y1) - { - int temp=y2; - y2=y1; - y1=temp; - } - // there shouldn't be any need for this for known versions of graphviz - // but it can't do any harm to check that x follows the rules as well - if (x2<x1) - { - int temp=x2; - x2=x1; - x1=temp; - } - if (urlOnly) - { - t << "<area href=\""; - - if ( isRef ) - { - // handle doxygen \ref tag URL reference - QCString *dest; - DocRef *df = new DocRef( (DocNode*) 0, url ); - if (!df->ref().isEmpty()) - { - if ((dest=Doxygen::tagDestinationDict[df->ref()])) t << *dest << "/"; - } - if (!df->file().isEmpty()) t << relPath << df->file() << Doxygen::htmlFileExtension; - if (!df->anchor().isEmpty()) t << "#" << df->anchor(); - } - else - { - t << url; - } - t << "\" shape=\"rect\" coords=\"" - << x1 << "," << y1 << "," << x2 << "," << y2 << "\"" - << " alt=\"\">" << endl; - } - else // name and external reference are separated by a $ - { - char *refPtr = url; - char *urlPtr = strchr(url,'$'); - //printf("url=`%s'\n",url); - if (urlPtr) - { - QCString *dest; - *urlPtr++='\0'; - //printf("refPtr=`%s' urlPtr=`%s'\n",refPtr,urlPtr); - //printf("Found url=%s coords=%d,%d,%d,%d\n",url,x1,y1,x2,y2); - t << "<area "; - if (*refPtr!='\0') - { - t << "doxygen=\"" << refPtr << ":"; - if ((dest=Doxygen::tagDestinationDict[refPtr])) t << *dest << "/"; - t << "\" "; - } - t << "href=\"" << relPath; - if (*refPtr!='\0') - { - if ((dest=Doxygen::tagDestinationDict[refPtr])) t << *dest << "/"; - } - t << urlPtr << "\" shape=\"rect\" coords=\"" - << x1 << "," << y1 << "," << x2 << "," << y2 << "\"" - << " alt=\"\">" << endl; - } - } - } - } - - return TRUE; -} -#endif - /*! converts the rectangles in a client site image map into a stream * \param t the stream to which the result is written. * \param mapName the name of the map file. @@ -348,45 +231,21 @@ static void resetReNumbering() s_newNumber.resize(s_max_newNumber); } -#if 0 -static bool readBoundingBoxDot(const char *fileName,int *width,int *height) -{ - QFile f(fileName); - if (!f.open(IO_ReadOnly)) return FALSE; - const int maxLineLen=1024; - char buf[maxLineLen]; - while (!f.atEnd()) - { - int numBytes = f.readLine(buf,maxLineLen); - buf[numBytes-1]='\0'; - if (strncmp(buf,"\tgraph [bb",10)==0) - { - int x,y; - if (sscanf(buf,"\tgraph [bb= \"%d,%d,%d,%d\"];",&x,&y,width,height)!=4) - { - return FALSE; - } - return TRUE; - } - } - return FALSE; -} -#endif - static bool readBoundingBoxEPS(const char *fileName,int *width,int *height) { + QCString bb("%%PageBoundingBox:"); QFile f(fileName); if (!f.open(IO_ReadOnly)) return FALSE; const int maxLineLen=1024; char buf[maxLineLen]; while (!f.atEnd()) { - int numBytes = f.readLine(buf,maxLineLen); - buf[numBytes-1]='\0'; - if (strncmp(buf,"%%PageBoundingBox: ",15)==0) + int numBytes = f.readLine(buf,maxLineLen-1); // read line + buf[numBytes]='\0'; + if (strncmp(buf,bb.data(),bb.length()-1)==0) // found PageBoundBox string { int x,y; - if (sscanf(buf,"%%%%PageBoundingBox: %d %d %d %d",&x,&y,width,height)!=4) + if (sscanf(buf+bb.length(),"%d %d %d %d",&x,&y,width,height)!=4) { return FALSE; } @@ -396,33 +255,6 @@ static bool readBoundingBoxEPS(const char *fileName,int *width,int *height) return FALSE; } -#if 0 -/*! returns TRUE if class cd is a leaf (i.e. has no visible children) - */ -static bool isLeaf(ClassDef *cd) -{ - BaseClassList *bcl = cd->subClasses(); - if (bcl->count()>0) // class has children, check their visibility - { - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()); ++bcli ) - { - ClassDef *bClass = bcd->classDef; - //if (bClass->isLinkable() || !isLeaf(bClass)) return FALSE; - - // if class is not a leaf - if (!isLeaf(bClass)) return FALSE; - // or class is not documented in this project - if (!Config_getBool("ALLEXTERNALS") && !bClass->isLinkableInProject()) return FALSE; - // or class is not documented and all ALLEXTERNALS = YES - if (Config_getBool("ALLEXTERNALS") && !bClass->isLinkable()) return FALSE; - } - } - return TRUE; -} -#endif - // since dot silently reproduces the input file when it does not // support the PNG format, we need to check the result. static void checkDotResult(const QCString &imgName) @@ -583,6 +415,7 @@ DotNode::DotNode(int n,const char *lab,const char *tip, const char *url, , m_classDef(cd) , m_visible(FALSE) , m_truncated(Unknown) + , m_distance(1000) { } @@ -672,6 +505,11 @@ void DotNode::deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes) } } +void DotNode::setDistance(int distance) +{ + if (distance<m_distance) m_distance = distance; +} + static QCString convertLabel(const QCString &l) { QCString result; @@ -847,9 +685,15 @@ void DotNode::writeArrow(QTextStream &t, ) { t << " Node"; - if (topDown) t << reNumberNode(cn->number(),reNumber); else t << reNumberNode(m_number,reNumber); + if (topDown) + t << reNumberNode(cn->number(),reNumber); + else + t << reNumberNode(m_number,reNumber); t << " -> Node"; - if (topDown) t << reNumberNode(m_number,reNumber); else t << reNumberNode(cn->number(),reNumber); + if (topDown) + t << reNumberNode(m_number,reNumber); + else + t << reNumberNode(cn->number(),reNumber); t << " ["; if (pointBack) t << "dir=back,"; t << "color=\"" << edgeColorMap[ei->m_color] @@ -864,7 +708,7 @@ void DotNode::writeArrow(QTextStream &t, ) { if (pointBack) - t << ",arrowtail=\"" <<arrowStyle[ei->m_color] << "\""; + t << ",arrowtail=\"" << arrowStyle[ei->m_color] << "\""; else t << ",arrowhead=\"" << arrowStyle[ei->m_color] << "\""; } @@ -1445,7 +1289,7 @@ DotGfxHierarchyTable::~DotGfxHierarchyTable() int DotClassGraph::m_curNodeNumber = 0; void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, - const char *label,const char *usedName,const char *templSpec,bool base) + const char *label,const char *usedName,const char *templSpec,bool base,int distance) { if (Config_getBool("HIDE_UNDOC_CLASSES") && !cd->isLinkable()) return; @@ -1478,6 +1322,7 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, bn->addChild(n,prot,edgeStyle,label); n->addParent(bn); } + bn->setDistance(distance); //printf(" add exiting node %s of %s\n",bn->m_label.data(),n->m_label.data()); } else // new class @@ -1507,11 +1352,12 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, bn->addChild(n,prot,edgeStyle,label); n->addParent(bn); } + bn->setDistance(distance); m_usedNodes->insert(className,bn); //printf(" add new child node `%s' to %s hidden=%d url=%s\n", // className.data(),n->m_label.data(),cd->isHidden(),tmp_url.data()); - buildGraph(cd,bn,base); + buildGraph(cd,bn,base,distance+1); } } @@ -1557,10 +1403,13 @@ void DotClassGraph::determineVisibleNodes(QList<DotNode> &queue, { while (queue.count()>0 && maxNodes>0) { + static int maxDistance = Config_getInt("MAX_DOT_GRAPH_DEPTH"); DotNode *n = queue.take(0); - //printf("*** Processing node %p queue=%d maxNodes=%d m_children=%p m_parents=%p\n", - // n,queue.count(),maxNodes,n->m_children,n->m_parents); - if (!n->isVisible()) // not yet processed + //printf("*** Processing node %p queue=%d maxNodes=%d m_children=%p " + // "m_parents=%p distance=%d maxDistance=%d\n", + // n,queue.count(),maxNodes,n->m_children,n->m_parents,n->distance(), + // maxDistance); + if (!n->isVisible() && n->distance()<maxDistance) // not yet processed { //printf(" Marked as visible!\n"); n->markAsVisible(); @@ -1589,7 +1438,7 @@ void DotClassGraph::determineVisibleNodes(QList<DotNode> &queue, } } -void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) +void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base,int distance) { //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n", // cd->name().data(),distance,base); @@ -1607,7 +1456,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) //printf("-------- inheritance relation %s->%s templ=`%s'\n", // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName, - bcd->templSpecifiers,base); + bcd->templSpecifiers,base,distance); } } } @@ -1642,14 +1491,15 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) } } addClass(ucd->classDef,n,EdgeInfo::Purple,label,0, - ucd->templSpecifiers,base); + ucd->templSpecifiers,base,distance); } } } // ---- Add template instantiation relations - if (Config_getBool("TEMPLATE_RELATIONS")) + static bool templateRelations = Config_getBool("TEMPLATE_RELATIONS"); + if (templateRelations) { if (base) // template relations for base classes { @@ -1663,7 +1513,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) if (templInstance==cd) { addClass(templMaster,n,EdgeInfo::Orange,cli.currentKey(),0, - 0,TRUE); + 0,TRUE,distance); } } } @@ -1678,7 +1528,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) for (;(templInstance=cli.current());++cli) { addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),0, - 0,FALSE); + 0,FALSE,distance); } } } @@ -1703,23 +1553,25 @@ DotClassGraph::DotClassGraph(ClassDef *cd,DotNode::GraphType t) TRUE, // is a root node cd ); + m_startNode->setDistance(0); m_usedNodes = new QDict<DotNode>(1009); m_usedNodes->insert(className,m_startNode); //printf("Root node %s\n",cd->name().data()); //if (m_recDepth>0) //{ - buildGraph(cd,m_startNode,TRUE); - if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE); + buildGraph(cd,m_startNode,TRUE,1); + if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE,1); //} - int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); - int directChildNodes = 1; - if (m_startNode->m_children!=0) - directChildNodes+=m_startNode->m_children->count(); - if (t==DotNode::Inheritance && m_startNode->m_parents!=0) - directChildNodes+=m_startNode->m_parents->count(); - if (directChildNodes>maxNodes) maxNodes=directChildNodes; + static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int maxNodes = nodes; + //int directChildNodes = 1; + //if (m_startNode->m_children!=0) + // directChildNodes+=m_startNode->m_children->count(); + //if (t==DotNode::Inheritance && m_startNode->m_parents!=0) + // directChildNodes+=m_startNode->m_parents->count(); + //if (directChildNodes>maxNodes) maxNodes=directChildNodes; QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineVisibleNodes(openNodeQueue,maxNodes,t==DotNode::Inheritance); @@ -1738,65 +1590,23 @@ bool DotClassGraph::isTrivial() const return m_startNode->m_children==0; } -DotClassGraph::~DotClassGraph() +bool DotClassGraph::isTooBig() const { - deleteNodes(m_startNode); - delete m_usedNodes; + static int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int numNodes = 0; + numNodes+= m_startNode->m_children ? m_startNode->m_children->count() : 0; + if (m_graphType==DotNode::Inheritance) + { + numNodes+= m_startNode->m_parents ? m_startNode->m_parents->count() : 0; + } + return numNodes>=maxNodes; } -#if 0 -void writeDotGraph(DotNode *root, - DotNode::GraphType gt, - GraphOutputFormat format, - const QCString &baseName, - bool lrRank, - bool renderParents, - int distance, - bool backArrows, - bool reNumber - ) +DotClassGraph::~DotClassGraph() { - // generate the graph description for dot - //printf("writeDotGraph(%s,%d,lrRank=%d)\n",baseName.data(),backArrows,lrRank); - QFile f; - f.setName(baseName+".dot"); - if (f.open(IO_WriteOnly)) - { - QTextStream t(&f); - writeGraphHeader(t); - if (lrRank) - { - t << " rankdir=LR;" << endl; - } - root->clearWriteFlag(); - root->write(t,gt,format,gt!=DotNode::CallGraph,TRUE,distance,backArrows,reNumber); - if (renderParents && root->m_parents) - { - //printf("rendering parents!\n"); - QListIterator<DotNode> dnli(*root->m_parents); - DotNode *pn; - for (dnli.toFirst();(pn=dnli.current());++dnli) - { - if (pn->m_distance<=distance) - { - root->writeArrow(t, - gt, - format, - pn, - pn->m_edgeInfo->at(pn->m_children->findRef(root)), - FALSE, - backArrows, - reNumber - ); - } - pn->write(t,gt,format,TRUE,FALSE,distance,backArrows,reNumber); - } - } - writeGraphFooter(t); - f.close(); - } + deleteNodes(m_startNode); + delete m_usedNodes; } -#endif /*! Computes a 16 byte md5 checksum for a given dot graph. * The md5 checksum is returned as a 32 character ASCII string. @@ -1818,10 +1628,16 @@ QCString computeMd5Signature(DotNode *root, writeGraphHeader(md5stream); if (lrRank) { - md5stream << "rankdir=LR;" << endl; + md5stream << " rankdir=LR;" << endl; } root->clearWriteFlag(); - root->write(md5stream,gt,format,gt!=DotNode::CallGraph,TRUE,backArrows,reNumber); + root->write(md5stream, + gt, + format, + gt!=DotNode::CallGraph && gt!=DotNode::Dependency, + TRUE, + backArrows, + reNumber); if (renderParents && root->m_parents) { QListIterator<DotNode> dnli(*root->m_parents); @@ -1892,95 +1708,6 @@ static bool updateDotGraph(DotNode *root, return FALSE; } -#if 0 -static bool findMaximalDotGraph(DotNode *root, - int maxDist, - const QCString &baseName, - QDir &thisDir, - DotNode::GraphType gt, - GraphOutputFormat format, - bool lrRank /*=FALSE*/, - bool renderParents /*=FALSE*/, - bool backArrows /*=TRUE*/ - ) -{ - bool reNumber=TRUE; - int minDistance=1; // min distance that shows only direct children. - int curDistance; //=QMIN(2,maxDist); // current distance to try - int maxDistance=maxDist; // max distance that show whole graph - int width=0; - int height=0; - int maxDotGraphWidth = Config_getInt("MAX_DOT_GRAPH_WIDTH"); - int maxDotGraphHeight = Config_getInt("MAX_DOT_GRAPH_HEIGHT"); - int lastFit=minDistance; - - // binary search for the maximal inheritance depth that fits in a reasonable - // sized image (dimensions: Config_getInt("MAX_DOT_GRAPH_WIDTH"), Config_getInt("MAX_DOT_GRAPH_HEIGHT")) - while (minDistance<=maxDistance) - { - curDistance = (minDistance+maxDistance)/2; - - writeDotGraph(root,gt,format,baseName,lrRank,renderParents, - curDistance,backArrows,reNumber); - - // create annotated dot file - DotRunner dotRun(baseName+".dot"); - dotRun.addJob("dot",baseName+"_tmp.dot"); - if (!dotRun.run()) - { - return FALSE; - } - - // extract bounding box from the result - readBoundingBoxDot(baseName+"_tmp.dot",&width,&height); - width = width *96/72; // 96 pixels/inch, 72 points/inch - height = height*96/72; // 96 pixels/inch, 72 points/inch - //printf("Found bounding box (%d,%d) max (%d,%d)\n",width,height, - // Config_getInt("MAX_DOT_GRAPH_WIDTH"),Config_getInt("MAX_DOT_GRAPH_HEIGHT")); - - // remove temporary dot file - thisDir.remove(baseName+"_tmp.dot"); - - bool graphFits=(width<maxDotGraphWidth && height<maxDotGraphHeight); - if (graphFits) // graph is small enough - { - lastFit=curDistance; - minDistance=curDistance+1; - //printf("Image fits [%d-%d]\n",minDistance,maxDistance); - } - else // graph does not fit anymore with curDistance - { - //printf("Image does not fit [%d-%d]\n",minDistance,maxDistance); - maxDistance=curDistance-1; - } - } - //printf("lastFit=%d\n",lastFit); - - bool hasLRRank = (lrRank || - (minDistance==1 && - width>Config_getInt("MAX_DOT_GRAPH_WIDTH") && - !Config_getBool("UML_LOOK") - ) - ); - - writeDotGraph(root, - gt, - format, - baseName, - hasLRRank, - renderParents, - lastFit, - backArrows, - reNumber - ); - if (reNumber) - { - resetReNumbering(); - } - return TRUE; -} -#endif - QCString DotClassGraph::diskName() const { QCString result=m_diskName.copy(); @@ -2174,7 +1901,7 @@ void DotClassGraph::writeDEF(QTextStream &t) int DotInclDepGraph::m_curNodeNumber = 0; -void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) +void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd,int distance) { QList<IncludeInfo> *includeFiles = m_inverse ? fd->includedByFileList() : fd->includeFileList(); @@ -2207,6 +1934,7 @@ void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) { n->addChild(bn,0,0,0); bn->addParent(n); + bn->setDistance(distance); } else { @@ -2214,17 +1942,19 @@ void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) if (bfd) tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString(); QCString tooltip = fd->briefDescriptionAsTooltip(); bn = new DotNode( - m_curNodeNumber++, - ii->includeName, - tooltip, - tmp_url, - 0 //distance + m_curNodeNumber++, // n + ii->includeName, // label + tooltip, // tip + tmp_url, // url + FALSE, // rootNode + 0 // cd ); n->addChild(bn,0,0,0); bn->addParent(n); m_usedNodes->insert(in,bn); + bn->setDistance(distance); - if (bfd) buildGraph(bn,bfd); + if (bfd) buildGraph(bn,bfd,distance+1); } } } @@ -2235,8 +1965,9 @@ void DotInclDepGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes { while (queue.count()>0 && maxNodes>0) { + static int maxDistance = Config_getInt("MAX_DOT_GRAPH_DEPTH"); DotNode *n = queue.take(0); - if (!n->isVisible()) // not yet processed + if (!n->isVisible() && n->distance()<maxDistance) // not yet processed { n->markAsVisible(); maxNodes--; @@ -2293,15 +2024,17 @@ DotInclDepGraph::DotInclDepGraph(FileDef *fd,bool inverse) tmp_url.data(), TRUE // root node ); + m_startNode->setDistance(0); m_usedNodes = new QDict<DotNode>(1009); m_usedNodes->insert(fd->absFilePath(),m_startNode); - buildGraph(m_startNode,fd); - - int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); - int directChildNodes = 1; - if (m_startNode->m_children!=0) - directChildNodes+=m_startNode->m_children->count(); - if (directChildNodes>maxNodes) maxNodes=directChildNodes; + buildGraph(m_startNode,fd,1); + + static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int maxNodes = nodes; + //int directChildNodes = 1; + //if (m_startNode->m_children!=0) + // directChildNodes+=m_startNode->m_children->count(); + //if (directChildNodes>maxNodes) maxNodes=directChildNodes; QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineVisibleNodes(openNodeQueue,maxNodes); @@ -2351,10 +2084,10 @@ QCString DotInclDepGraph::writeGraph(QTextStream &out, QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT"); if (updateDotGraph(m_startNode, - DotNode::CallGraph, + DotNode::Dependency, baseName, format, - TRUE, // lrRank + FALSE, // lrRank FALSE, // renderParents m_inverse // backArrows ) @@ -2450,6 +2183,13 @@ bool DotInclDepGraph::isTrivial() const return m_startNode->m_children==0; } +bool DotInclDepGraph::isTooBig() const +{ + static int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int numNodes = m_startNode->m_children ? m_startNode->m_children->count() : 0; + return numNodes>=maxNodes; +} + void DotInclDepGraph::writeXML(QTextStream &t) { QDictIterator<DotNode> dni(*m_usedNodes); @@ -2593,11 +2333,12 @@ DotCallGraph::DotCallGraph(MemberDef *md,bool inverse) m_usedNodes->insert(uniqueId,m_startNode); buildGraph(m_startNode,md); - int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); - int directChildNodes = 1; - if (m_startNode->m_children!=0) - directChildNodes+=m_startNode->m_children->count(); - if (directChildNodes>maxNodes) maxNodes=directChildNodes; + static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int maxNodes = nodes; + //int directChildNodes = 1; + //if (m_startNode->m_children!=0) + // directChildNodes+=m_startNode->m_children->count(); + //if (directChildNodes>maxNodes) maxNodes=directChildNodes; QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineVisibleNodes(openNodeQueue,maxNodes); @@ -2730,6 +2471,13 @@ bool DotCallGraph::isTrivial() const return m_startNode->m_children==0; } +bool DotCallGraph::isTooBig() const +{ + static int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int numNodes = m_startNode->m_children ? m_startNode->m_children->count() : 0; + return numNodes>=maxNodes; +} + //------------------------------------------------------------- DotDirDeps::DotDirDeps(DirDef *dir) : m_dir(dir) @@ -3433,5 +3181,5 @@ void DotGroupCollaboration::writeGraphHeader(QTextStream &t) t << " edge [fontname=\"FreeSans.ttf\",fontsize=8," "labelfontname=\"FreeSans.ttf\",labelfontsize=8];\n"; t << " node [fontname=\"FreeSans.ttf\",fontsize=10,shape=record];\n"; - t << "rankdir=LR;\n"; + t << " rankdir=LR;\n"; } @@ -82,6 +82,7 @@ class DotNode int number() const { return m_number; } bool isVisible() const { return m_visible; } TruncState isTruncated() const { return m_truncated; } + int distance() const { return m_distance; } private: void colorConnectedNodes(int curColor); @@ -89,6 +90,7 @@ class DotNode bool hasNonReachableChildren, bool reNumber=FALSE); void writeArrow(QTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn, EdgeInfo *ei,bool topDown, bool pointBack=TRUE, bool reNumber=FALSE); + void setDistance(int distance); const DotNode *findDocNode() const; // only works for acyclic graphs! void markAsVisible(bool b=TRUE) { m_visible=b; } void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; } @@ -106,6 +108,7 @@ class DotNode ClassDef * m_classDef; //!< class representing this node (can be 0) bool m_visible; //!< is the node visible in the output TruncState m_truncated; //!< does the node have non-visible children/parents + int m_distance; //!< shortest path to the root node friend class DotGfxHierarchyTable; friend class DotClassGraph; @@ -155,6 +158,7 @@ class DotClassGraph DotClassGraph(ClassDef *cd,DotNode::GraphType t); ~DotClassGraph(); bool isTrivial() const; + bool isTooBig() const; QCString writeGraph(QTextStream &t,GraphOutputFormat f,const char *path, const char *relPath, bool TBRank=TRUE,bool imageMap=TRUE); @@ -163,12 +167,12 @@ class DotClassGraph QCString diskName() const; private: - void buildGraph(ClassDef *cd,DotNode *n,bool base); + void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance); void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes,bool includeParents); void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents); void addClass(ClassDef *cd,DotNode *n,int prot,const char *label, const char *usedName,const char *templSpec, - bool base); + bool base,int distance); DotNode * m_startNode; QDict<DotNode> * m_usedNodes; @@ -187,11 +191,12 @@ class DotInclDepGraph const char *relPath, bool writeImageMap=TRUE); bool isTrivial() const; + bool isTooBig() const; QCString diskName() const; void writeXML(QTextStream &t); private: - void buildGraph(DotNode *n,FileDef *fd); + void buildGraph(DotNode *n,FileDef *fd,int distance); void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes); void determineTruncatedNodes(QList<DotNode> &queue); @@ -213,6 +218,7 @@ class DotCallGraph const char *path,const char *relPath,bool writeImageMap=TRUE); void buildGraph(DotNode *n,MemberDef *md); bool isTrivial() const; + bool isTooBig() const; void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes); void determineTruncatedNodes(QList<DotNode> &queue); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 12d0004..3042aa0 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -6397,7 +6397,7 @@ static void addEnumValuesToEnums(EntryNav *rootNav) // must create them here e->loadEntry(g_storage); MemberDef *fmd = addVariableToFile(e,MemberDef::EnumValue, - md->getOuterScope() ? md->getOuterScope()->name() : "", + md->getOuterScope() ? md->getOuterScope()->name() : QCString(), e->name(),TRUE,0); md->insertEnumField(fmd); fmd->setEnumScope(md); @@ -6659,6 +6659,43 @@ static void findDocumentedEnumValues() findDEV(*Doxygen::functionNameSDict); } +//---------------------------------------------------------------------- + +static void addMembersToIndex() +{ + MemberName *mn; + MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); + // for each member name + for (mnli.toFirst();(mn=mnli.current());++mnli) + { + MemberDef *md; + MemberNameIterator mni(*mn); + // for each member definition + for (mni.toFirst();(md=mni.current());++mni) + { + addClassMemberNameToIndex(md); + } + } + MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); + // for each member name + for (fnli.toFirst();(mn=fnli.current());++fnli) + { + MemberDef *md; + MemberNameIterator mni(*mn); + // for each member definition + for (mni.toFirst();(md=mni.current());++mni) + { + if (md->getNamespaceDef()) + { + addNamespaceMemberNameToIndex(md); + } + else + { + addFileMemberNameToIndex(md); + } + } + } +} //---------------------------------------------------------------------- // computes the relation between all members. For each member `m' @@ -8560,49 +8597,13 @@ void readFormulaRepository() //---------------------------------------------------------------------------- -static QDict<void> aliasesProcessed; - -static QCString expandAliasesRec(const QCString s) -{ - QCString result; - static QRegExp cmdPat("[\\\\@][a-z_A-Z][a-z_A-Z0-9]*"); - QCString value=s; - int i,p=0,l; - while ((i=cmdPat.match(value,p,&l))!=-1) - { - result+=value.mid(p,i-p); - QCString cmd=value.mid(i+1,l-1); - //printf("Found command '%s'\n",cmd.data()); - QCString *aliasText=Doxygen::aliasDict.find(cmd); - if (aliasesProcessed.find(cmd)==0 && aliasText) // expand the alias - { - aliasesProcessed.insert(cmd,(void *)0x8); - result+=expandAliasesRec(*aliasText); - aliasesProcessed.remove(cmd); - } - else // command is not an alias - { - result+=value.mid(i,l); - } - p=i+l; - } - result+=value.right(value.length()-p); - - //printf("expandAliases '%s'->'%s'\n",s.data(),result.data()); - return result; -} - static void expandAliases() { QDictIterator<QCString> adi(Doxygen::aliasDict); QCString *s; for (adi.toFirst();(s=adi.current());++adi) { - aliasesProcessed.clear(); - // avoid expanding this command recursively - aliasesProcessed.insert(adi.currentKey(),(void *)0x8); - // expand embedded commands - *s = expandAliasesRec(*s); + *s = expandAlias(adi.currentKey(),*s); } } @@ -8678,7 +8679,6 @@ void readAliases() } expandAliases(); escapeAliases(); - aliasesProcessed.clear(); } //---------------------------------------------------------------------------- @@ -9880,6 +9880,7 @@ void generateOutput() writeGroupIndex(*outputList); msg("Generating class documentation...\n"); + addMembersToIndex(); generateClassDocs(); if (Config_getBool("HAVE_DOT") && Config_getBool("GRAPHICAL_HIERARCHY")) @@ -9979,7 +9980,7 @@ void generateOutput() QDir::setCurrent(Config_getString("HTML_OUTPUT")); if (portable_system(Config_getString("HHC_LOCATION"), "index.hhp", FALSE)) { - err("Error: failed to run html help compiler on index.hhp"); + err("Error: failed to run html help compiler on index.hhp\n"); } QDir::setCurrent(oldDir); } diff --git a/src/filedef.cpp b/src/filedef.cpp index ecbb102..45b7ea6 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -391,7 +391,7 @@ void FileDef::writeDocumentation(OutputList &ol) { //printf("Graph for file %s\n",name().data()); DotInclDepGraph incDepGraph(this,FALSE); - if (!incDepGraph.isTrivial()) + if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) { ol.startTextBlock(); ol.disable(OutputGenerator::Man); @@ -409,7 +409,7 @@ void FileDef::writeDocumentation(OutputList &ol) { //printf("Graph for file %s\n",name().data()); DotInclDepGraph incDepGraph(this,TRUE); - if (!incDepGraph.isTrivial()) + if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) { ol.startTextBlock(); ol.disable(OutputGenerator::Man); @@ -723,7 +723,7 @@ void FileDef::insertMember(MemberDef *md) m_memberLists.append(allMemberList); } allMemberList->append(md); - ::addFileMemberNameToIndex(md); + //::addFileMemberNameToIndex(md); switch (md->memberType()) { case MemberDef::Variable: diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index 2b8d88d..58f06c1 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -577,18 +577,26 @@ void HtmlDocVisitor::visitPre(DocHtmlList *s) { if (m_hide) return; if (s->type()==DocHtmlList::Ordered) + { m_t << "<ol" << htmlAttribsToString(s->attribs()) << ">\n"; + } else + { m_t << "<ul" << htmlAttribsToString(s->attribs()) << ">\n"; + } } void HtmlDocVisitor::visitPost(DocHtmlList *s) { if (m_hide) return; if (s->type()==DocHtmlList::Ordered) + { m_t << "</ol>"; - else + } + else + { m_t << "</ul>"; + } if (!s->isPreformatted()) m_t << "\n"; } diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 3dbec0e..d923186 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -873,7 +873,7 @@ void HtmlGenerator::writeCodeLink(const char *ref,const char *f, if (f) t << f << Doxygen::htmlFileExtension; if (anchor) t << "#" << anchor; t << "\""; - if (tooltip) t << " title=\"" << tooltip << "\""; + if (tooltip) t << " title=\"" << convertToXML(tooltip) << "\""; t << ">"; docify(name); t << "</a>"; diff --git a/src/index.cpp b/src/index.cpp index dc8cdd5..c745659 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -1667,7 +1667,8 @@ void initClassMemberIndices() void addClassMemberNameToIndex(MemberDef *md) { static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS"); - ClassDef *cd; + ClassDef *cd=0; + if (md->isLinkableInProject() && (cd=md->getClassDef()) && cd->isLinkableInProject() && diff --git a/src/latexgen.cpp b/src/latexgen.cpp index a64ad22..ab06be0 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -237,21 +237,22 @@ static void writeDefaultHeaderPart1(QTextStream &t) } if (Config_getBool("PDF_HYPERLINKS")) { - t << "\\ifx\\pdfoutput\\undefined" << endl - << "\\usepackage[ps2pdf," << endl + t << "\\usepackage{ifpdf}" << endl + << "\\ifpdf" << endl + << "\\usepackage[pdftex," << endl << " pagebackref=true," << endl << " colorlinks=true," << endl << " linkcolor=blue," << endl << " unicode" << endl << " ]{hyperref}" << endl - << "\\usepackage{pspicture}" << endl << "\\else" << endl - << "\\usepackage[pdftex," << endl + << "\\usepackage[ps2pdf," << endl << " pagebackref=true," << endl << " colorlinks=true," << endl << " linkcolor=blue," << endl << " unicode" << endl << " ]{hyperref}" << endl + << "\\usepackage{pspicture}" << endl << "\\fi" << endl; } // Try to get the command for switching on the language diff --git a/src/memberdef.cpp b/src/memberdef.cpp index d00516b..dffbb82 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -772,10 +772,15 @@ bool MemberDef::isLinkableInProject() const static bool extractStatic = Config_getBool("EXTRACT_STATIC"); makeResident(); - if (isHidden()) return FALSE; //printf("MemberDef::isLinkableInProject(name=%s)\n",name().data()); + if (isHidden()) + { + //printf("is hidden\n"); + return FALSE; + } if (m_impl->templateMaster) { + //printf("has template master\n"); return m_impl->templateMaster->isLinkableInProject(); } if (name().isEmpty() || name().at(0)=='@') @@ -2157,7 +2162,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, ) { DotCallGraph callGraph(this,FALSE); - if (!callGraph.isTrivial()) + if (!callGraph.isTrivial() && !callGraph.isTooBig()) { msg("Generating call graph for function %s\n",qualifiedName().data()); ol.disable(OutputGenerator::Man); @@ -2172,8 +2177,8 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, && isFunction() && Config_getBool("HAVE_DOT") ) { - DotCallGraph callerGraph(this, true); - if (!callerGraph.isTrivial()) + DotCallGraph callerGraph(this, TRUE); + if (!callerGraph.isTrivial() && !callerGraph.isTooBig()) { msg("Generating caller graph for function %s\n",qualifiedName().data()); ol.disable(OutputGenerator::Man); diff --git a/src/msc.cpp b/src/msc.cpp index aa4ad88..f68858a 100644 --- a/src/msc.cpp +++ b/src/msc.cpp @@ -98,7 +98,7 @@ void writeMscGraphFromFile(const char *inFile,const char *outDir, // go to the html output directory (i.e. path) QDir::setCurrent(outDir); //printf("Going to dir %s\n",QDir::currentDirPath().data()); - QCString mscExe = Config_getString("MSC_PATH")+"mscgen"+portable_commandExtension(); + QCString mscExe = Config_getString("MSCGEN_PATH")+"mscgen"+portable_commandExtension(); QCString mscArgs; QCString extension; if (format==MSC_BITMAP) @@ -151,7 +151,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir, QCString mscExe = "mscgen"; QCString mscArgs = "-T ismap -i \""; mscArgs+=inFile + ".msc\" -o \""; - mscArgs+=outFile + ".map\""; + mscArgs+=outFile + "\""; int exitCode; if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0) @@ -162,7 +162,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir, QString result; QTextOStream tmpout(&result); - convertMapFile(tmpout, outFile+".map", relPath); + convertMapFile(tmpout, outFile, relPath); QDir().remove(outFile); QDir::setCurrent(oldDir); diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index 1ebaaf9..fe69505 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -179,7 +179,7 @@ void NamespaceDef::insertMember(MemberDef *md) m_memberLists.append(allMemberList); } allMemberList->append(md); - ::addNamespaceMemberNameToIndex(md); + //::addNamespaceMemberNameToIndex(md); //static bool sortBriefDocs=Config_getBool("SORT_BRIEF_DOCS"); switch(md->memberType()) { diff --git a/src/translator_cn.h b/src/translator_cn.h index 4c3168b..7689a0c 100644 --- a/src/translator_cn.h +++ b/src/translator_cn.h @@ -620,7 +620,8 @@ class TranslatorChinese : public Translator */ virtual QCString trNamespaces() { - return "Namespaces"; + // return "Namespaces"; + return "Ãû×Ö¿Õ¼ä"; } ////////////////////////////////////////////////////////////////////////// diff --git a/src/util.cpp b/src/util.cpp index 6521f81..0723ae4 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -116,8 +116,9 @@ void TextGeneratorOLImpl::writeLink(const char *extRef,const char *file, // an inheritance tree of depth of 100000 should be enough for everyone :-) const int maxInheritanceDepth = 100000; -bool isId(char c) +bool isId(int c) { + if (c<0 || c>255) return FALSE; return c=='_' || isalnum(c); } @@ -6080,3 +6081,166 @@ QCString parseCommentAsText(const QString &doc,const QCString &fileName,int line return result.data(); } +//-------------------------------------------------------------------------------------- + +static QDict<void> aliasesProcessed; + +QCString expandAliasRec(const QCString s) +{ + QCString result; + static QRegExp cmdPat("[\\\\@][a-z_A-Z][a-z_A-Z0-9]*"); + QCString value=s; + int i,p=0,l; + while ((i=cmdPat.match(value,p,&l))!=-1) + { + result+=value.mid(p,i-p); + QCString args = extractAliasArgs(value,i+l); + bool hasArgs = !args.isEmpty(); // found directly after command + QCString cmd; + if (hasArgs) + { + int numArgs = countAliasArguments(args); + cmd = value.mid(i+1,l-1)+QCString().sprintf("{%d}",numArgs); // alias name + {n} + } + else + { + cmd = value.mid(i+1,l-1); + } + //printf("Found command '%s' args='%s'\n",cmd.data(),args.data()); + QCString *aliasText=Doxygen::aliasDict.find(cmd); + if (aliasesProcessed.find(cmd)==0 && aliasText) // expand the alias + { + //printf("is an alias!\n"); + aliasesProcessed.insert(cmd,(void *)0x8); + QCString val = *aliasText; + if (hasArgs) + { + val = replaceAliasArguments(val,args); + //printf("replace '%s'->'%s' args='%s'\n", + // aliasText->data(),val.data(),args.data()); + } + result+=expandAliasRec(val); + aliasesProcessed.remove(cmd); + p=i+l; + if (hasArgs) p+=args.length()+2; + } + else // command is not an alias + { + //printf("not an alias!\n"); + result+=value.mid(i,l); + p=i+l; + } + } + result+=value.right(value.length()-p); + + //printf("expandAliases '%s'->'%s'\n",s.data(),result.data()); + return result; +} + +static QCString replaceAliasArgument(const QCString &aliasValue,int paramNum, + const QCString ¶mValue) +{ + QCString result = aliasValue; + QCString paramMarker; + paramMarker.sprintf("\\%d",paramNum); + int markerLen = paramMarker.length(); + int p=0,i; + while ((i=aliasValue.find(paramMarker,p))!=-1) // search for marker + { + //printf("Found marker '%s' at %d len=%d for param '%s' in '%s'\n", + // paramMarker.data(),i,markerLen,paramValue.data(),aliasValue.data()); + if (i==0 || aliasValue.at(i-1)!='\\') // found unescaped marker + { + QCString before = result.left(i); + QCString after = result.mid(i+markerLen); + result = before + paramValue + after; + p=i+paramValue.length(); + } + else // ignore escaped markers + { + p=i+1; + } + } + result = expandAliasRec(substitute(result,"\\,",",")); + //printf("replaceAliasArgument('%s',%d,'%s')->%s\n", + // aliasValue.data(),paramNum,paramValue.data(),result.data()); + return result; +} + +QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argList) +{ + QCString result = aliasValue; + QList<QCString> args; + int p=0,i,c=1; + for (i=0;i<(int)argList.length();i++) + { + if (argList.at(i)==',' && (i==0 || argList.at(i-1)!='\\')) + { + result = replaceAliasArgument(result,c,argList.mid(p,i-p)); + p=i+1; + c++; + } + } + if (p<(int)argList.length()) + { + result = replaceAliasArgument(result,c,argList.right(argList.length()-p)); + } + return result; +} + +int countAliasArguments(const QCString argList) +{ + int count=1; + int l = argList.length(); + int i; + for (i=0;i<l;i++) + { + if (argList.at(i)==',' && (i==0 || argList.at(i-1)!='\\')) count++; + } + return count; +} + +QCString extractAliasArgs(const QCString &args,int pos) +{ + int i; + int bc=0; + if (args.at(pos)=='{') // alias has argument + { + for (i=pos;i<(int)args.length();i++) + { + if (args.at(i)=='{') bc++; + if (args.at(i)=='}') bc--; + if (bc==0) + { + //printf("extractAliasArgs('%s')->'%s'\n",args.data(),args.mid(pos+1,i-pos-1).data()); + return args.mid(pos+1,i-pos-1); + } + } + } + return ""; +} + +QCString resolveAliasCmd(const QCString aliasCmd) +{ + QCString result; + aliasesProcessed.clear(); + //printf("Expanding: '%s'\n",aliasCmd.data()); + result = expandAliasRec(aliasCmd); + //printf("Expanding result: '%s'->'%s'\n",aliasCmd.data(),result.data()); + return result; +} + +QCString expandAlias(const QCString &aliasName,const QCString &aliasValue) +{ + QCString result; + aliasesProcessed.clear(); + // avoid expanding this command recursively + aliasesProcessed.insert(aliasName,(void *)0x8); + // expand embedded commands + //printf("Expanding: '%s'->'%s'\n",aliasName.data(),aliasValue.data()); + result = expandAliasRec(aliasValue); + //printf("Expanding result: '%s'->'%s'\n",aliasName.data(),result.data()); + return result; +} + + @@ -187,7 +187,7 @@ QCString showFileDefMatches(const FileNameDict *fnDict,const char *n); int guessSection(const char *name); -bool isId(char c); +bool isId(int c); QCString removeRedundantWhiteSpace(const QCString &s); @@ -334,5 +334,14 @@ QCString transcodeCharacterStringToUTF8(const QCString &input); QCString recodeString(const QCString &str,const char *fromEncoding,const char *toEncoding); +QCString extractAliasArgs(const QCString &args,int pos); + +int countAliasArguments(const QCString argList); + +QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argList); + +QCString resolveAliasCmd(const QCString aliasCmd); +QCString expandAlias(const QCString &aliasName,const QCString &aliasValue); + #endif diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index 1cc8375..e66bea3 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -189,7 +189,7 @@ void writeXMLLink(QTextStream &t,const char *extRef,const char *compoundId, if (anchorId) t << "member"; else t << "compound"; t << "\""; if (extRef) t << " external=\"" << extRef << "\""; - if (tooltip) t << " tooltip=\"" << tooltip << "\""; + if (tooltip) t << " tooltip=\"" << convertToXML(tooltip) << "\""; t << ">"; writeXMLString(t,text); t << "</ref>"; |