Commit 34ca5820 authored by dimitri's avatar dimitri

Release-1.5.2-20070610

parent 23c13fc1
DOXYGEN Version 1.5.2-20070506 DOXYGEN Version 1.5.2-20070610
Please read the installation section of the manual Please read the installation section of the manual
(http://www.doxygen.org/install.html) for instructions. (http://www.doxygen.org/install.html) for instructions.
-------- --------
Dimitri van Heesch (06 May 2007) Dimitri van Heesch (10 June 2007)
...@@ -54,26 +54,24 @@ install: doxywizard_install ...@@ -54,26 +54,24 @@ install: doxywizard_install
$(INSTTOOL) -m 755 bin/doxygen $(INSTALL)/bin $(INSTTOOL) -m 755 bin/doxygen $(INSTALL)/bin
$(INSTTOOL) -m 755 bin/doxytag $(INSTALL)/bin $(INSTTOOL) -m 755 bin/doxytag $(INSTALL)/bin
$(INSTTOOL) -d $(INSTALL)/$(MAN1DIR) $(INSTTOOL) -d $(INSTALL)/$(MAN1DIR)
cat doc/doxygen.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > $(INSTALL)/$(MAN1DIR)/doxygen.1 ; \ cat doc/doxygen.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxygen.1
cat doc/doxytag.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > $(INSTALL)/$(MAN1DIR)/doxytag.1 ; \ $(INSTTOOL) -m 644 doxygen.1 $(INSTALL)/$(MAN1DIR)/doxygen.1
cat doc/doxywizard.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > $(INSTALL)/$(MAN1DIR)/doxywizard.1 ; rm doxygen.1
cat doc/doxytag.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxytag.1
$(INSTTOOL) -m 644 doxytag.1 $(INSTALL)/$(MAN1DIR)/doxytag.1
rm doxytag.1
cat doc/doxywizard.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxywizard.1
$(INSTTOOL) -m 644 doxywizard.1 $(INSTALL)/$(MAN1DIR)/doxywizard.1
rm doxywizard
install_docs: install_docs:
$(INSTTOOL) -d $(DOCDIR) $(INSTTOOL) -d $(DOCDIR)
$(MAKE) -C examples $(MAKE) -C examples
$(MAKE) -C doc $(MAKE) -C doc
$(MAKE) -C latex $(MAKE) -C latex
cp latex/doxygen_manual.pdf $(DOCDIR) $(INSTTOOL) -m 644 latex/doxygen_manual.pdf $(DOCDIR)
#cp -r doc $(DOCDIR)
cp -r examples $(DOCDIR) cp -r examples $(DOCDIR)
cp -r html $(DOCDIR) cp -r html $(DOCDIR)
#echo "DOXYGEN = $(INSTALL)" > $(DOCDIR)/doc/Makefile
#echo "DOXYDOCS = .." >> $(DOCDIR)/doc/Makefile
#echo "VERSION = $(VERSION)" >> $(DOCDIR)/doc/Makefile
#echo "PERL = $(PERL)" >> $(DOCDIR)/doc/Makefile
#cat doc/Makefile.in >> $(DOCDIR)/doc/Makefile
#rm -rf $(DOCDIR)/doc
#rm -rf $(DOCDIR)/latex
docs: FORCE docs: FORCE
cd examples ; $(MAKE) cd examples ; $(MAKE)
......
DOXYGEN Version 1.5.2_20070506 DOXYGEN Version 1.5.2_20070610
Please read INSTALL for compilation instructions. Please read INSTALL for compilation instructions.
...@@ -17,4 +17,4 @@ to subscribe to the lists or to visit the archives. ...@@ -17,4 +17,4 @@ to subscribe to the lists or to visit the archives.
Enjoy, Enjoy,
Dimitri van Heesch (dimitri@stack.nl) (06 May 2007) Dimitri van Heesch (dimitri@stack.nl) (10 June 2007)
...@@ -20,7 +20,7 @@ doxygen_version_minor=5 ...@@ -20,7 +20,7 @@ doxygen_version_minor=5
doxygen_version_revision=2 doxygen_version_revision=2
#NOTE: Setting version_mmn to "NO" will omit mmn info from the package. #NOTE: Setting version_mmn to "NO" will omit mmn info from the package.
doxygen_version_mmn=20070506 doxygen_version_mmn=20070610
bin_dirs=`echo $PATH | sed -e "s/:/ /g"` bin_dirs=`echo $PATH | sed -e "s/:/ /g"`
...@@ -214,10 +214,7 @@ if test -z "$f_platform"; then ...@@ -214,10 +214,7 @@ if test -z "$f_platform"; then
UNIX_SV:4.2*) UNIX_SV:4.2*)
f_platform=unixware-g++ f_platform=unixware-g++
;; ;;
Cygwin:*) Cygwin:*|CYGWIN:*)
f_platform=win32-g++
;;
CYGWIN:*)
f_platform=win32-g++ f_platform=win32-g++
;; ;;
*MiNT:*) *MiNT:*)
......
...@@ -33,7 +33,7 @@ CASE_SENSE_NAMES = NO ...@@ -33,7 +33,7 @@ CASE_SENSE_NAMES = NO
IMAGE_PATH = . IMAGE_PATH = .
INPUT = index.doc install.doc starting.doc docblocks.doc lists.doc \ INPUT = index.doc install.doc starting.doc docblocks.doc lists.doc \
grouping.doc formulas.doc diagrams.doc preprocessing.doc \ grouping.doc formulas.doc diagrams.doc preprocessing.doc \
autolink.doc output.doc external.doc faq.doc trouble.doc history.doc features.doc \ autolink.doc output.doc custcmd.doc external.doc faq.doc trouble.doc history.doc features.doc \
doxygen_usage.doc doxytag_usage.doc \ doxygen_usage.doc doxytag_usage.doc \
doxywizard_usage.doc installdox_usage.doc \ doxywizard_usage.doc installdox_usage.doc \
config.doc commands.doc htmlcmds.doc xmlcmds.doc language.doc \ config.doc commands.doc htmlcmds.doc xmlcmds.doc language.doc \
......
...@@ -163,6 +163,7 @@ followed by the descriptions of the tags grouped by category. ...@@ -163,6 +163,7 @@ followed by the descriptions of the tags grouped by category.
\refitem cfg_man_extension MAN_EXTENSION \refitem cfg_man_extension MAN_EXTENSION
\refitem cfg_man_links MAN_LINKS \refitem cfg_man_links MAN_LINKS
\refitem cfg_man_output MAN_OUTPUT \refitem cfg_man_output MAN_OUTPUT
\refitem cfg_max_dot_graph_depth MAX_DOT_GRAPH_DEPTH
\refitem cfg_max_initializer_lines MAX_INITIALIZER_LINES \refitem cfg_max_initializer_lines MAX_INITIALIZER_LINES
\refitem cfg_mscgen_path MSCGEN_PATH \refitem cfg_mscgen_path MSCGEN_PATH
\refitem cfg_multiline_cpp_is_brief MULTILINE_CPP_IS_BRIEF \refitem cfg_multiline_cpp_is_brief MULTILINE_CPP_IS_BRIEF
...@@ -1771,10 +1772,23 @@ TAGFILES = file1=loc1 "file2 = loc2" ... </pre> ...@@ -1771,10 +1772,23 @@ TAGFILES = file1=loc1 "file2 = loc2" ... </pre>
<dt>\c DOT_GRAPH_MAX_NODES <dd> <dt>\c DOT_GRAPH_MAX_NODES <dd>
\addindex DOT_GRAPH_MAX_NODES \addindex DOT_GRAPH_MAX_NODES
The \c MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of The \c MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
nodes that will be shown in the graph. If the number of nodes in a graph nodes that will be shown in the graph. If the number of nodes in a graph
becomes larger than this value, doxygen will truncate the graph, which is becomes larger than this value, doxygen will truncate the graph, which is
visualized by representing a node as a red box. Note that doxygen will always visualized by representing a node as a red box. Note that doxygen if the number
show the root nodes and its direct children regardless of this setting. of direct children of the root node in a graph is already larger than
\c MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note
that the size of a graph can be further restricted by \c MAX_DOT_GRAPH_DEPTH.
\anchor cfg_max_dot_graph_depth
<dt>\c MAX_DOT_GRAPH_DEPTH <dd>
\addindex MAX_DOT_GRAPH_DEPTH
The \c MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
graphs generated by dot. A depth value of 3 means that only nodes reachable
from the root by following a path via at most 3 edges will be shown. Nodes
that lay further from the root node will be omitted. Note that setting this
option to 1 or 2 may greatly reduce the computation time needed for large
code bases. Also note that the size of a graph can be further restricted by
\c DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction (the default).
\anchor cfg_dot_image_format \anchor cfg_dot_image_format
<dt>\c DOT_IMAGE_FORMAT <dd> <dt>\c DOT_IMAGE_FORMAT <dd>
......
...@@ -75,6 +75,7 @@ The first part forms a user manual: ...@@ -75,6 +75,7 @@ The first part forms a user manual:
and members in the documentation. and members in the documentation.
<li>Section \ref output shows how to generate the various output formats <li>Section \ref output shows how to generate the various output formats
supported by doxygen. supported by doxygen.
<li>Section \ref custcmd show how to define and use custom commands in your comments.
<li>Section \ref external explains how to let doxygen create links to externally generated documentation. <li>Section \ref external explains how to let doxygen create links to externally generated documentation.
<li>Section \ref faq gives answers to frequently asked questions. <li>Section \ref faq gives answers to frequently asked questions.
<li>Section \ref trouble tells you what to do when you have problems. <li>Section \ref trouble tells you what to do when you have problems.
......
...@@ -38,14 +38,17 @@ If you downloaded the source distribution, you need at least the ...@@ -38,14 +38,17 @@ If you downloaded the source distribution, you need at least the
following to build the executable: following to build the executable:
<ul> <ul>
<li>The <a href="ftp://prep.ai.mit.edu/pub/gnu/">GNU</a> tools <li>The <a href="ftp://prep.ai.mit.edu/pub/gnu/">GNU</a> tools
flex, bison and make flex, bison and GNU make, and strip
\addindex flex \addindex flex
\addindex bison \addindex bison
\addindex make \addindex make
\addindex strip
<li>In order to generate a Makefile for your platform, you need <li>In order to generate a Makefile for your platform, you need
<a href="http://www.perl.com/">perl</a> <a href="http://www.perl.com/">perl</a>
\latexonly(see {\tt http://www.perl.com/})\endlatexonly. \latexonly(see {\tt http://www.perl.com/})\endlatexonly.
\addindex perl \addindex perl
<li>The configure script assume the availibility of standard Unix tools such
as sed, date, find, uname, mv, cp, cat, echo, tr, cd, and rm.
</ul> </ul>
To take full advantage of doxygen's features the following additional To take full advantage of doxygen's features the following additional
...@@ -56,7 +59,7 @@ tools should be installed. ...@@ -56,7 +59,7 @@ tools should be installed.
<A HREF="http://www.trolltech.com/products/qt.html">Qt</A> <A HREF="http://www.trolltech.com/products/qt.html">Qt</A>
\latexonly(see {\tt http://www.trolltech.com/products/qt.html})\endlatexonly \latexonly(see {\tt http://www.trolltech.com/products/qt.html})\endlatexonly
\addindex Qt \addindex Qt
version 3.2 or higher. version 3.3 or higher.
This is needed to build the GUI front-end doxywizard. This is needed to build the GUI front-end doxywizard.
<li>A \f$\mbox{\LaTeX}\f$ distribution: for instance <li>A \f$\mbox{\LaTeX}\f$ distribution: for instance
<a href="http://www.tug.org/interest.html#free">teTeX 1.0</a> <a href="http://www.tug.org/interest.html#free">teTeX 1.0</a>
...@@ -70,8 +73,11 @@ tools should be installed. ...@@ -70,8 +73,11 @@ tools should be installed.
If you compile graphviz yourself, make sure you do include If you compile graphviz yourself, make sure you do include
freetype support (which requires the freetype library and header files), freetype support (which requires the freetype library and header files),
otherwise the graphs will not render proper text labels. otherwise the graphs will not render proper text labels.
<li>The ghostscript interpreter. To be found at <li>For formulas or if you do not wish to use pdflatex, the ghostscript interpreter
is needed. You can find it at
<a href="http://www.ghostscript.com/">www.ghostscript.com</a>. <a href="http://www.ghostscript.com/">www.ghostscript.com</a>.
<li>In order to generate doxygen's own documentation, Python is needed, you
can find it at <a href="http://www.python.org">www.python.org</a>.
</ul> </ul>
Compilation is now done by performing the following steps: Compilation is now done by performing the following steps:
...@@ -104,7 +110,7 @@ Compilation is now done by performing the following steps: ...@@ -104,7 +110,7 @@ Compilation is now done by performing the following steps:
See the <code>PLATFORMS</code> file for a list of possible platform See the <code>PLATFORMS</code> file for a list of possible platform
options. options.
If you have Qt-3.2.x or higher installed and want to build the GUI If you have Qt-3.3.x installed and want to build the GUI
front-end, you should run the configure script with front-end, you should run the configure script with
the <code>--with-doxywizard</code> option: the <code>--with-doxywizard</code> option:
...@@ -136,13 +142,11 @@ Compilation is now done by performing the following steps: ...@@ -136,13 +142,11 @@ Compilation is now done by performing the following steps:
To let doxygen generate the HTML documentation. To let doxygen generate the HTML documentation.
\note You will need the stream editor <code>sed</code> for this,
but this should be available on any Unix platform.
The HTML directory of the distribution will now contain the html The HTML directory of the distribution will now contain the html
documentation (just point a HTML browser to the file documentation (just point a HTML browser to the file
<code>index.html</code> in the <code>index.html</code> in the
html directory). html directory). You will need the <code>python</code> interpreter
for this.
<li>Optional: Generate a PDF version of the manual <li>Optional: Generate a PDF version of the manual
(you will need <code>pdflatex</code>, <code>makeindex</code>, and (you will need <code>pdflatex</code>, <code>makeindex</code>, and
......
...@@ -39,7 +39,11 @@ Here is the list of tags supported by doxygen: ...@@ -39,7 +39,11 @@ Here is the list of tags supported by doxygen:
file. Ignored by doxygen at the moment. file. Ignored by doxygen at the moment.
<li><tt>\<item\></tt> List item. Can only be used inside a <tt>\<list\></tt> context. <li><tt>\<item\></tt> List item. Can only be used inside a <tt>\<list\></tt> context.
<li><tt>\<list type="type"\></tt> Starts a list, supported types are <tt>bullet</tt> <li><tt>\<list type="type"\></tt> Starts a list, supported types are <tt>bullet</tt>
or <tt>number</tt>. A list consists of a number of <tt>\<item\></tt> tags. or <tt>number</tt> and <tt>table</tt>.
A list consists of a number of <tt>\<item\></tt> tags.
A list of type table, is a two column table which can have
a header.
<li><tt>\<listheader\></tt> Starts the header of a list of type "table".
<li><tt>\<para\></tt> Identifies a paragraph of text. <li><tt>\<para\></tt> Identifies a paragraph of text.
<li><tt>\<param name="paramName"\></tt> Marks a piece of text as the documentation <li><tt>\<param name="paramName"\></tt> Marks a piece of text as the documentation
for parameter "paramName". Similar to for parameter "paramName". Similar to
...@@ -56,6 +60,7 @@ Here is the list of tags supported by doxygen: ...@@ -56,6 +60,7 @@ Here is the list of tags supported by doxygen:
to "member". Similar to using \ref cmdsa "\\sa" member. to "member". Similar to using \ref cmdsa "\\sa" member.
<li><tt>\<summary\></tt> Identifies the brief description. <li><tt>\<summary\></tt> Identifies the brief description.
Similar to using \ref cmdbrief "\\brief". Similar to using \ref cmdbrief "\\brief".
<li><tt>\<term\></tt> Part of a <tt>\<list\></tt> command.
<li><tt>\<value\></tt> Identifies a property. Ignored by doxygen. <li><tt>\<value\></tt> Identifies a property. Ignored by doxygen.
</ul> </ul>
......
...@@ -596,7 +596,7 @@ void ClassDef::internalInsertMember(MemberDef *md, ...@@ -596,7 +596,7 @@ void ClassDef::internalInsertMember(MemberDef *md,
m_impl->isAbstract=TRUE; m_impl->isAbstract=TRUE;
} }
::addClassMemberNameToIndex(md); //::addClassMemberNameToIndex(md);
if (addToAllList && if (addToAllList &&
!(Config_getBool("HIDE_FRIEND_COMPOUNDS") && !(Config_getBool("HIDE_FRIEND_COMPOUNDS") &&
md->isFriend() && md->isFriend() &&
...@@ -982,6 +982,192 @@ void ClassDef::showUsedFiles(OutputList &ol) ...@@ -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 // write all documentation for this class
void ClassDef::writeDocumentation(OutputList &ol) void ClassDef::writeDocumentation(OutputList &ol)
{ {
...@@ -1140,182 +1326,7 @@ void ClassDef::writeDocumentation(OutputList &ol) ...@@ -1140,182 +1326,7 @@ void ClassDef::writeDocumentation(OutputList &ol)
} }
} }
writeClassDiagrams(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();
}
}
// write link to list of all members (HTML only) // write link to list of all members (HTML only)
if (m_impl->allMemberNameInfoSDict && if (m_impl->allMemberNameInfoSDict &&
......
...@@ -310,6 +310,7 @@ class ClassDef : public Definition ...@@ -310,6 +310,7 @@ class ClassDef : public Definition
void mergeMembers(); void mergeMembers();
void distributeMemberGroupDocumentation(); void distributeMemberGroupDocumentation();
void writeDocumentation(OutputList &ol); void writeDocumentation(OutputList &ol);
void writeClassDiagrams(OutputList &ol);
void writeDocumentationForInnerClasses(OutputList &ol); void writeDocumentationForInnerClasses(OutputList &ol);
void writeMemberDocumentation(OutputList &ol); void writeMemberDocumentation(OutputList &ol);
void writeMemberPages(OutputList &ol); void writeMemberPages(OutputList &ol);
......
...@@ -162,7 +162,8 @@ CommandMap htmlTagMap[] = ...@@ -162,7 +162,8 @@ CommandMap htmlTagMap[] =
{ "exception", XML_EXCEPTION }, { "exception", XML_EXCEPTION },
{ "include", XML_INCLUDE }, { "include", XML_INCLUDE },
{ "item", XML_ITEM }, { "item", XML_ITEM },
{ "list", XML_LIST }, { "list", XML_LIST }, // type="table|bullet|number"
{ "listheader", XML_LISTHEADER },
{ "para", XML_PARA }, { "para", XML_PARA },
{ "param", XML_PARAM }, { "param", XML_PARAM },
{ "paramref", XML_PARAMREF }, { "paramref", XML_PARAMREF },
...@@ -172,14 +173,15 @@ CommandMap htmlTagMap[] = ...@@ -172,14 +173,15 @@ CommandMap htmlTagMap[] =
{ "see", XML_SEE }, { "see", XML_SEE },
{ "seealso", XML_SEEALSO }, { "seealso", XML_SEEALSO },
{ "summary", XML_SUMMARY }, { "summary", XML_SUMMARY },
{ "term", XML_TERM },
{ "value", XML_VALUE }, { "value", XML_VALUE },
{ 0, 0 } { 0, 0 }
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
Mapper *Mappers::cmdMapper = new Mapper(cmdMap); Mapper *Mappers::cmdMapper = new Mapper(cmdMap,TRUE);
Mapper *Mappers::htmlTagMapper = new Mapper(htmlTagMap); Mapper *Mappers::htmlTagMapper = new Mapper(htmlTagMap,FALSE);
void Mappers::freeMappers() void Mappers::freeMappers()
{ {
......
...@@ -158,16 +158,18 @@ enum HtmlTagType ...@@ -158,16 +158,18 @@ enum HtmlTagType
XML_INCLUDE = XML_CmdMask + 5, XML_INCLUDE = XML_CmdMask + 5,
XML_ITEM = XML_CmdMask + 6, XML_ITEM = XML_CmdMask + 6,
XML_LIST = XML_CmdMask + 7, XML_LIST = XML_CmdMask + 7,
XML_PARA = XML_CmdMask + 8, XML_LISTHEADER = XML_CmdMask + 8,
XML_PARAM = XML_CmdMask + 9, XML_PARA = XML_CmdMask + 9,
XML_PARAMREF = XML_CmdMask + 10, XML_PARAM = XML_CmdMask + 10,
XML_PERMISSION = XML_CmdMask + 11, XML_PARAMREF = XML_CmdMask + 11,
XML_REMARKS = XML_CmdMask + 12, XML_PERMISSION = XML_CmdMask + 12,
XML_RETURNS = XML_CmdMask + 13, XML_REMARKS = XML_CmdMask + 13,
XML_SEE = XML_CmdMask + 14, XML_RETURNS = XML_CmdMask + 14,
XML_SEEALSO = XML_CmdMask + 15, XML_SEE = XML_CmdMask + 15,
XML_SUMMARY = XML_CmdMask + 16, XML_SEEALSO = XML_CmdMask + 16,
XML_VALUE = XML_CmdMask + 17 XML_SUMMARY = XML_CmdMask + 17,
XML_TERM = XML_CmdMask + 18,
XML_VALUE = XML_CmdMask + 19
}; };
...@@ -177,11 +179,12 @@ class Mapper ...@@ -177,11 +179,12 @@ class Mapper
int map(const char *n) int map(const char *n)
{ {
QCString name=n; QCString name=n;
if (!m_cs) name=name.lower();
int *result; 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); m_map.setAutoDelete(TRUE);
const CommandMap *p = cm; const CommandMap *p = cm;
...@@ -193,6 +196,7 @@ class Mapper ...@@ -193,6 +196,7 @@ class Mapper
} }
private: private:
QDict<int> m_map; QDict<int> m_map;
bool m_cs;
}; };
struct Mappers struct Mappers
......
...@@ -61,6 +61,10 @@ static QCString g_blockName; ...@@ -61,6 +61,10 @@ static QCString g_blockName;
static int g_lastCommentContext; static int g_lastCommentContext;
static bool g_inSpecialComment; static bool g_inSpecialComment;
static QCString g_aliasString;
static int g_blockCount;
static int g_lastBlockContext;
static void replaceCommentMarker(const char *s,int len) static void replaceCommentMarker(const char *s,int len)
{ {
const char *p=s; const char *p=s;
...@@ -223,27 +227,11 @@ static QCString handleCondCmdInAliases(const QCString &s) ...@@ -223,27 +227,11 @@ static QCString handleCondCmdInAliases(const QCString &s)
/** copies string \a s with length \a len to the output, while /** copies string \a s with length \a len to the output, while
* replacing any alias commands found in the string. * 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 result = resolveAliasCmd(s);
QCString in=s; //printf("replaceAliases(%s)->'%s'\n",s,result.data());
int p=0,i,l; copyToOutput(result,result.length());
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);
} }
...@@ -274,6 +262,7 @@ void replaceComment(int offset); ...@@ -274,6 +262,7 @@ void replaceComment(int offset);
%x VerbatimCode %x VerbatimCode
%x ReadLine %x ReadLine
%x CondLine %x CondLine
%x ReadAliasArgs
%% %%
...@@ -300,8 +289,7 @@ void replaceComment(int offset); ...@@ -300,8 +289,7 @@ void replaceComment(int offset);
} }
g_blockHeadCol=g_col; g_blockHeadCol=g_col;
copyToOutput("/**",3); copyToOutput("/**",3);
//copyToOutput(yytext+i,yyleng-i); replaceAliases(yytext+i);
replaceAliases(yytext+i,yyleng-i);
g_inSpecialComment=TRUE; g_inSpecialComment=TRUE;
BEGIN(SComment); BEGIN(SComment);
} }
...@@ -310,8 +298,7 @@ void replaceComment(int offset); ...@@ -310,8 +298,7 @@ void replaceComment(int offset);
int i=17; //=strlen("//##Documentation"); int i=17; //=strlen("//##Documentation");
g_blockHeadCol=g_col; g_blockHeadCol=g_col;
copyToOutput("/**",3); copyToOutput("/**",3);
//copyToOutput(yytext+i,yyleng-i); replaceAliases(yytext+i);
replaceAliases(yytext+i,yyleng-i);
BEGIN(SComment); BEGIN(SComment);
} }
<Scan>"//"/.*\n { /* one line C++ comment */ <Scan>"//"/.*\n { /* one line C++ comment */
...@@ -521,17 +508,37 @@ void replaceComment(int offset); ...@@ -521,17 +508,37 @@ void replaceComment(int offset);
if (*yytext=='\n') g_lineNr++; if (*yytext=='\n') g_lineNr++;
BEGIN(g_condCtx); BEGIN(g_condCtx);
} }
<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias without arguments
QCString *pValue=Doxygen::aliasDict[yytext+1]; replaceAliases(yytext);
if (pValue) }
{ <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments
QCString val = handleCondCmdInAliases(*pValue); g_lastBlockContext=YY_START;
copyToOutput(val.data(),val.length()); g_blockCount=1;
} g_aliasString=yytext;
else BEGIN( ReadAliasArgs );
{ }
copyToOutput(yytext,yyleng); <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>. { <ReadLine>. {
copyToOutput(yytext,yyleng); copyToOutput(yytext,yyleng);
......
...@@ -1078,12 +1078,13 @@ void Config::check() ...@@ -1078,12 +1078,13 @@ void Config::check()
s=aliasList.first(); s=aliasList.first();
while (s) 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; QCString alias=s;
alias=alias.stripWhiteSpace(); 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()); alias.data());
} }
s=aliasList.next(); s=aliasList.next();
...@@ -1250,16 +1251,12 @@ void Config::check() ...@@ -1250,16 +1251,12 @@ void Config::check()
Config_getBool("INLINE_INFO")=FALSE; Config_getBool("INLINE_INFO")=FALSE;
} }
#if 0 int &depth = Config_getInt("MAX_DOT_GRAPH_DEPTH");
if (Config_getString("RTF_OUTPUT_ENCODING").isEmpty()) if (depth==0)
{
Config_getString("RTF_OUTPUT_ENCODING")="ISO-8859-1";
}
if (Config_getString("LATEX_OUTPUT_ENCODING").isEmpty())
{ {
Config_getString("LATEX_OUTPUT_ENCODING")="ISO-8859-1"; depth=1000;
} }
#endif
// add default words if needed // add default words if needed
QStrList &annotationFromBrief = Config_getList("ABBREVIATE_BRIEF"); QStrList &annotationFromBrief = Config_getList("ABBREVIATE_BRIEF");
...@@ -2072,7 +2069,9 @@ void Config::create() ...@@ -2072,7 +2069,9 @@ void Config::create()
"If the SOURCE_BROWSER tag is set to YES then a list of source files will \n" "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" "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" "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 FALSE
); );
cb = addBool( cb = addBool(
...@@ -2895,14 +2894,27 @@ void Config::create() ...@@ -2895,14 +2894,27 @@ void Config::create()
"The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of \n" "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" "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" "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" "visualized by representing a node as a red box. Note that doxygen if the number \n"
"show the root nodes and its direct children regardless of this setting. \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 0,10000, 50
); );
ci->addDependency("HAVE_DOT"); 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_WIDTH");
addObsolete("MAX_DOT_GRAPH_HEIGHT"); addObsolete("MAX_DOT_GRAPH_HEIGHT");
addObsolete("MAX_DOT_GRAPH_DEPTH");
cb = addBool( cb = addBool(
"DOT_TRANSPARENT", "DOT_TRANSPARENT",
"Set the DOT_TRANSPARENT tag to YES to generate images with a transparent \n" "Set the DOT_TRANSPARENT tag to YES to generate images with a transparent \n"
......
...@@ -536,6 +536,18 @@ static bool insideOL(DocNode *n) ...@@ -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 */ ///*! Returns TRUE iff node n is a child of a language node */
//static bool insideLang(DocNode *n) //static bool insideLang(DocNode *n)
//{ //{
...@@ -2820,6 +2832,43 @@ int DocHtmlCell::parse() ...@@ -2820,6 +2832,43 @@ int DocHtmlCell::parse()
return retval; 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() int DocHtmlRow::parse()
...@@ -2888,6 +2937,68 @@ endrow: ...@@ -2888,6 +2937,68 @@ endrow:
return retval; 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() int DocHtmlTable::parse()
...@@ -2958,6 +3069,48 @@ getrow: ...@@ -2958,6 +3069,48 @@ getrow:
return retval==RetVal_EndTable ? RetVal_OK : retval; 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 DocHtmlTable::numCols() const
{ {
uint cols=0; uint cols=0;
...@@ -4788,6 +4941,10 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag ...@@ -4788,6 +4941,10 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag
break; break;
case XML_EXAMPLE: case XML_EXAMPLE:
case XML_DESCRIPTION: case XML_DESCRIPTION:
if (insideTable(this))
{
retval=RetVal_TableCell;
}
break; break;
case XML_C: case XML_C:
handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs); handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs);
...@@ -4836,19 +4993,31 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag ...@@ -4836,19 +4993,31 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag
} }
break; break;
case XML_ITEM: 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; retval=RetVal_ListItem;
} }
else
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <item> tag found");
}
break; break;
case XML_RETURNS: case XML_RETURNS:
retval = handleSimpleSection(DocSimpleSect::Return,TRUE); retval = handleSimpleSection(DocSimpleSect::Return,TRUE);
g_hasReturnCommand=TRUE; g_hasReturnCommand=TRUE;
break; 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: case XML_SEE:
// I'm not sure if <see> is the same as <seealso> or if it // I'm not sure if <see> is the same as <seealso> or if it
// should you link a member without producing a section. The // should you link a member without producing a section. The
...@@ -4923,14 +5092,25 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag ...@@ -4923,14 +5092,25 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag
case XML_LIST: case XML_LIST:
{ {
QString type; QString type;
findAttribute(tagHtmlAttribs,"type",&type);
DocHtmlList::Type listType = DocHtmlList::Unordered; DocHtmlList::Type listType = DocHtmlList::Unordered;
if (findAttribute(tagHtmlAttribs,"type",&type) && type=="number") if (type=="number")
{ {
listType=DocHtmlList::Ordered; listType=DocHtmlList::Ordered;
} }
DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,listType); if (type=="table")
m_children.append(list); {
retval=list->parseXml(); 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; break;
case XML_INCLUDE: case XML_INCLUDE:
...@@ -5078,6 +5258,9 @@ int DocPara::handleHtmlEndTag(const QString &tagName) ...@@ -5078,6 +5258,9 @@ int DocPara::handleHtmlEndTag(const QString &tagName)
// ignore </a> tag (can be part of <a name=...></a> // ignore </a> tag (can be part of <a name=...></a>
break; break;
case XML_TERM:
m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE));
break;
case XML_SUMMARY: case XML_SUMMARY:
case XML_REMARKS: case XML_REMARKS:
case XML_PARA: case XML_PARA:
...@@ -5094,6 +5277,7 @@ int DocPara::handleHtmlEndTag(const QString &tagName) ...@@ -5094,6 +5277,7 @@ int DocPara::handleHtmlEndTag(const QString &tagName)
handleStyleLeave(this,m_children,DocStyleChange::Code,"c"); handleStyleLeave(this,m_children,DocStyleChange::Code,"c");
break; break;
case XML_ITEM: case XML_ITEM:
case XML_LISTHEADER:
case XML_INCLUDE: case XML_INCLUDE:
case XML_PERMISSION: case XML_PERMISSION:
case XML_DESCRIPTION: case XML_DESCRIPTION:
......
...@@ -1140,6 +1140,7 @@ class DocHtmlCell : public CompAccept<DocHtmlCell>, public DocNode ...@@ -1140,6 +1140,7 @@ class DocHtmlCell : public CompAccept<DocHtmlCell>, public DocNode
void markLast(bool v=TRUE) { m_isLast=v; } void markLast(bool v=TRUE) { m_isLast=v; }
const HtmlAttribList &attribs() const { return m_attribs; } const HtmlAttribList &attribs() const { return m_attribs; }
int parse(); int parse();
int parseXml();
private: private:
DocNode * m_parent; DocNode * m_parent;
...@@ -1179,6 +1180,7 @@ class DocHtmlRow : public CompAccept<DocHtmlRow>, public DocNode ...@@ -1179,6 +1180,7 @@ class DocHtmlRow : public CompAccept<DocHtmlRow>, public DocNode
void accept(DocVisitor *v) { CompAccept<DocHtmlRow>::accept(this,v); } void accept(DocVisitor *v) { CompAccept<DocHtmlRow>::accept(this,v); }
const HtmlAttribList &attribs() const { return m_attribs; } const HtmlAttribList &attribs() const { return m_attribs; }
int parse(); int parse();
int parseXml(bool header);
private: private:
DocNode * m_parent; DocNode * m_parent;
...@@ -1199,6 +1201,7 @@ class DocHtmlTable : public CompAccept<DocHtmlTable>, public DocNode ...@@ -1199,6 +1201,7 @@ class DocHtmlTable : public CompAccept<DocHtmlTable>, public DocNode
bool hasCaption() { return m_caption!=0; } bool hasCaption() { return m_caption!=0; }
const HtmlAttribList &attribs() const { return m_attribs; } const HtmlAttribList &attribs() const { return m_attribs; }
int parse(); int parse();
int parseXml();
uint numCols() const; uint numCols() const;
void accept(DocVisitor *v); void accept(DocVisitor *v);
......
...@@ -91,123 +91,6 @@ static void writeGraphFooter(QTextStream &t) ...@@ -91,123 +91,6 @@ static void writeGraphFooter(QTextStream &t)
t << "}" << endl; 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 /*! converts the rectangles in a client site image map into a stream
* \param t the stream to which the result is written. * \param t the stream to which the result is written.
* \param mapName the name of the map file. * \param mapName the name of the map file.
...@@ -348,45 +231,21 @@ static void resetReNumbering() ...@@ -348,45 +231,21 @@ static void resetReNumbering()
s_newNumber.resize(s_max_newNumber); 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) static bool readBoundingBoxEPS(const char *fileName,int *width,int *height)
{ {
QCString bb("%%PageBoundingBox:");
QFile f(fileName); QFile f(fileName);
if (!f.open(IO_ReadOnly)) return FALSE; if (!f.open(IO_ReadOnly)) return FALSE;
const int maxLineLen=1024; const int maxLineLen=1024;
char buf[maxLineLen]; char buf[maxLineLen];
while (!f.atEnd()) while (!f.atEnd())
{ {
int numBytes = f.readLine(buf,maxLineLen); int numBytes = f.readLine(buf,maxLineLen-1); // read line
buf[numBytes-1]='\0'; buf[numBytes]='\0';
if (strncmp(buf,"%%PageBoundingBox: ",15)==0) if (strncmp(buf,bb.data(),bb.length()-1)==0) // found PageBoundBox string
{ {
int x,y; 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; return FALSE;
} }
...@@ -396,33 +255,6 @@ static bool readBoundingBoxEPS(const char *fileName,int *width,int *height) ...@@ -396,33 +255,6 @@ static bool readBoundingBoxEPS(const char *fileName,int *width,int *height)
return FALSE; 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 // since dot silently reproduces the input file when it does not
// support the PNG format, we need to check the result. // support the PNG format, we need to check the result.
static void checkDotResult(const QCString &imgName) static void checkDotResult(const QCString &imgName)
...@@ -583,6 +415,7 @@ DotNode::DotNode(int n,const char *lab,const char *tip, const char *url, ...@@ -583,6 +415,7 @@ DotNode::DotNode(int n,const char *lab,const char *tip, const char *url,
, m_classDef(cd) , m_classDef(cd)
, m_visible(FALSE) , m_visible(FALSE)
, m_truncated(Unknown) , m_truncated(Unknown)
, m_distance(1000)
{ {
} }
...@@ -672,6 +505,11 @@ void DotNode::deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes) ...@@ -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) static QCString convertLabel(const QCString &l)
{ {
QCString result; QCString result;
...@@ -847,9 +685,15 @@ void DotNode::writeArrow(QTextStream &t, ...@@ -847,9 +685,15 @@ void DotNode::writeArrow(QTextStream &t,
) )
{ {
t << " Node"; 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"; 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 << " ["; t << " [";
if (pointBack) t << "dir=back,"; if (pointBack) t << "dir=back,";
t << "color=\"" << edgeColorMap[ei->m_color] t << "color=\"" << edgeColorMap[ei->m_color]
...@@ -864,7 +708,7 @@ void DotNode::writeArrow(QTextStream &t, ...@@ -864,7 +708,7 @@ void DotNode::writeArrow(QTextStream &t,
) )
{ {
if (pointBack) if (pointBack)
t << ",arrowtail=\"" <<arrowStyle[ei->m_color] << "\""; t << ",arrowtail=\"" << arrowStyle[ei->m_color] << "\"";
else else
t << ",arrowhead=\"" << arrowStyle[ei->m_color] << "\""; t << ",arrowhead=\"" << arrowStyle[ei->m_color] << "\"";
} }
...@@ -1445,7 +1289,7 @@ DotGfxHierarchyTable::~DotGfxHierarchyTable() ...@@ -1445,7 +1289,7 @@ DotGfxHierarchyTable::~DotGfxHierarchyTable()
int DotClassGraph::m_curNodeNumber = 0; int DotClassGraph::m_curNodeNumber = 0;
void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, 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; if (Config_getBool("HIDE_UNDOC_CLASSES") && !cd->isLinkable()) return;
...@@ -1478,6 +1322,7 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, ...@@ -1478,6 +1322,7 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot,
bn->addChild(n,prot,edgeStyle,label); bn->addChild(n,prot,edgeStyle,label);
n->addParent(bn); n->addParent(bn);
} }
bn->setDistance(distance);
//printf(" add exiting node %s of %s\n",bn->m_label.data(),n->m_label.data()); //printf(" add exiting node %s of %s\n",bn->m_label.data(),n->m_label.data());
} }
else // new class else // new class
...@@ -1507,11 +1352,12 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, ...@@ -1507,11 +1352,12 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot,
bn->addChild(n,prot,edgeStyle,label); bn->addChild(n,prot,edgeStyle,label);
n->addParent(bn); n->addParent(bn);
} }
bn->setDistance(distance);
m_usedNodes->insert(className,bn); m_usedNodes->insert(className,bn);
//printf(" add new child node `%s' to %s hidden=%d url=%s\n", //printf(" add new child node `%s' to %s hidden=%d url=%s\n",
// className.data(),n->m_label.data(),cd->isHidden(),tmp_url.data()); // 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, ...@@ -1557,10 +1403,13 @@ void DotClassGraph::determineVisibleNodes(QList<DotNode> &queue,
{ {
while (queue.count()>0 && maxNodes>0) while (queue.count()>0 && maxNodes>0)
{ {
static int maxDistance = Config_getInt("MAX_DOT_GRAPH_DEPTH");
DotNode *n = queue.take(0); DotNode *n = queue.take(0);
//printf("*** Processing node %p queue=%d maxNodes=%d m_children=%p m_parents=%p\n", //printf("*** Processing node %p queue=%d maxNodes=%d m_children=%p "
// n,queue.count(),maxNodes,n->m_children,n->m_parents); // "m_parents=%p distance=%d maxDistance=%d\n",
if (!n->isVisible()) // not yet processed // 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"); //printf(" Marked as visible!\n");
n->markAsVisible(); n->markAsVisible();
...@@ -1589,7 +1438,7 @@ void DotClassGraph::determineVisibleNodes(QList<DotNode> &queue, ...@@ -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", //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n",
// cd->name().data(),distance,base); // cd->name().data(),distance,base);
...@@ -1607,7 +1456,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) ...@@ -1607,7 +1456,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base)
//printf("-------- inheritance relation %s->%s templ=`%s'\n", //printf("-------- inheritance relation %s->%s templ=`%s'\n",
// cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data());
addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName, 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) ...@@ -1642,14 +1491,15 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base)
} }
} }
addClass(ucd->classDef,n,EdgeInfo::Purple,label,0, addClass(ucd->classDef,n,EdgeInfo::Purple,label,0,
ucd->templSpecifiers,base); ucd->templSpecifiers,base,distance);
} }
} }
} }
// ---- Add template instantiation relations // ---- 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 if (base) // template relations for base classes
{ {
...@@ -1663,7 +1513,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) ...@@ -1663,7 +1513,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base)
if (templInstance==cd) if (templInstance==cd)
{ {
addClass(templMaster,n,EdgeInfo::Orange,cli.currentKey(),0, 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) ...@@ -1678,7 +1528,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base)
for (;(templInstance=cli.current());++cli) for (;(templInstance=cli.current());++cli)
{ {
addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),0, addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),0,
0,FALSE); 0,FALSE,distance);
} }
} }
} }
...@@ -1703,23 +1553,25 @@ DotClassGraph::DotClassGraph(ClassDef *cd,DotNode::GraphType t) ...@@ -1703,23 +1553,25 @@ DotClassGraph::DotClassGraph(ClassDef *cd,DotNode::GraphType t)
TRUE, // is a root node TRUE, // is a root node
cd cd
); );
m_startNode->setDistance(0);
m_usedNodes = new QDict<DotNode>(1009); m_usedNodes = new QDict<DotNode>(1009);
m_usedNodes->insert(className,m_startNode); m_usedNodes->insert(className,m_startNode);
//printf("Root node %s\n",cd->name().data()); //printf("Root node %s\n",cd->name().data());
//if (m_recDepth>0) //if (m_recDepth>0)
//{ //{
buildGraph(cd,m_startNode,TRUE); buildGraph(cd,m_startNode,TRUE,1);
if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE); if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE,1);
//} //}
int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES");
int directChildNodes = 1; int maxNodes = nodes;
if (m_startNode->m_children!=0) //int directChildNodes = 1;
directChildNodes+=m_startNode->m_children->count(); //if (m_startNode->m_children!=0)
if (t==DotNode::Inheritance && m_startNode->m_parents!=0) // directChildNodes+=m_startNode->m_children->count();
directChildNodes+=m_startNode->m_parents->count(); //if (t==DotNode::Inheritance && m_startNode->m_parents!=0)
if (directChildNodes>maxNodes) maxNodes=directChildNodes; // directChildNodes+=m_startNode->m_parents->count();
//if (directChildNodes>maxNodes) maxNodes=directChildNodes;
QList<DotNode> openNodeQueue; QList<DotNode> openNodeQueue;
openNodeQueue.append(m_startNode); openNodeQueue.append(m_startNode);
determineVisibleNodes(openNodeQueue,maxNodes,t==DotNode::Inheritance); determineVisibleNodes(openNodeQueue,maxNodes,t==DotNode::Inheritance);
...@@ -1738,65 +1590,23 @@ bool DotClassGraph::isTrivial() const ...@@ -1738,65 +1590,23 @@ bool DotClassGraph::isTrivial() const
return m_startNode->m_children==0; return m_startNode->m_children==0;
} }
DotClassGraph::~DotClassGraph() bool DotClassGraph::isTooBig() const
{ {
deleteNodes(m_startNode); static int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES");
delete m_usedNodes; 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 DotClassGraph::~DotClassGraph()
void writeDotGraph(DotNode *root,
DotNode::GraphType gt,
GraphOutputFormat format,
const QCString &baseName,
bool lrRank,
bool renderParents,
int distance,
bool backArrows,
bool reNumber
)
{ {
// generate the graph description for dot deleteNodes(m_startNode);
//printf("writeDotGraph(%s,%d,lrRank=%d)\n",baseName.data(),backArrows,lrRank); delete m_usedNodes;
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();
}
} }
#endif
/*! Computes a 16 byte md5 checksum for a given dot graph. /*! Computes a 16 byte md5 checksum for a given dot graph.
* The md5 checksum is returned as a 32 character ASCII string. * The md5 checksum is returned as a 32 character ASCII string.
...@@ -1818,10 +1628,16 @@ QCString computeMd5Signature(DotNode *root, ...@@ -1818,10 +1628,16 @@ QCString computeMd5Signature(DotNode *root,
writeGraphHeader(md5stream); writeGraphHeader(md5stream);
if (lrRank) if (lrRank)
{ {
md5stream << "rankdir=LR;" << endl; md5stream << " rankdir=LR;" << endl;
} }
root->clearWriteFlag(); 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) if (renderParents && root->m_parents)
{ {
QListIterator<DotNode> dnli(*root->m_parents); QListIterator<DotNode> dnli(*root->m_parents);
...@@ -1892,95 +1708,6 @@ static bool updateDotGraph(DotNode *root, ...@@ -1892,95 +1708,6 @@ static bool updateDotGraph(DotNode *root,
return FALSE; 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 DotClassGraph::diskName() const
{ {
QCString result=m_diskName.copy(); QCString result=m_diskName.copy();
...@@ -2174,7 +1901,7 @@ void DotClassGraph::writeDEF(QTextStream &t) ...@@ -2174,7 +1901,7 @@ void DotClassGraph::writeDEF(QTextStream &t)
int DotInclDepGraph::m_curNodeNumber = 0; int DotInclDepGraph::m_curNodeNumber = 0;
void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd,int distance)
{ {
QList<IncludeInfo> *includeFiles = QList<IncludeInfo> *includeFiles =
m_inverse ? fd->includedByFileList() : fd->includeFileList(); m_inverse ? fd->includedByFileList() : fd->includeFileList();
...@@ -2207,6 +1934,7 @@ void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) ...@@ -2207,6 +1934,7 @@ void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd)
{ {
n->addChild(bn,0,0,0); n->addChild(bn,0,0,0);
bn->addParent(n); bn->addParent(n);
bn->setDistance(distance);
} }
else else
{ {
...@@ -2214,17 +1942,19 @@ void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) ...@@ -2214,17 +1942,19 @@ void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd)
if (bfd) tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString(); if (bfd) tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString();
QCString tooltip = fd->briefDescriptionAsTooltip(); QCString tooltip = fd->briefDescriptionAsTooltip();
bn = new DotNode( bn = new DotNode(
m_curNodeNumber++, m_curNodeNumber++, // n
ii->includeName, ii->includeName, // label
tooltip, tooltip, // tip
tmp_url, tmp_url, // url
0 //distance FALSE, // rootNode
0 // cd
); );
n->addChild(bn,0,0,0); n->addChild(bn,0,0,0);
bn->addParent(n); bn->addParent(n);
m_usedNodes->insert(in,bn); 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 ...@@ -2235,8 +1965,9 @@ void DotInclDepGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes
{ {
while (queue.count()>0 && maxNodes>0) while (queue.count()>0 && maxNodes>0)
{ {
static int maxDistance = Config_getInt("MAX_DOT_GRAPH_DEPTH");
DotNode *n = queue.take(0); DotNode *n = queue.take(0);
if (!n->isVisible()) // not yet processed if (!n->isVisible() && n->distance()<maxDistance) // not yet processed
{ {
n->markAsVisible(); n->markAsVisible();
maxNodes--; maxNodes--;
...@@ -2293,15 +2024,17 @@ DotInclDepGraph::DotInclDepGraph(FileDef *fd,bool inverse) ...@@ -2293,15 +2024,17 @@ DotInclDepGraph::DotInclDepGraph(FileDef *fd,bool inverse)
tmp_url.data(), tmp_url.data(),
TRUE // root node TRUE // root node
); );
m_startNode->setDistance(0);
m_usedNodes = new QDict<DotNode>(1009); m_usedNodes = new QDict<DotNode>(1009);
m_usedNodes->insert(fd->absFilePath(),m_startNode); m_usedNodes->insert(fd->absFilePath(),m_startNode);
buildGraph(m_startNode,fd); buildGraph(m_startNode,fd,1);
int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES");
int directChildNodes = 1; int maxNodes = nodes;
if (m_startNode->m_children!=0) //int directChildNodes = 1;
directChildNodes+=m_startNode->m_children->count(); //if (m_startNode->m_children!=0)
if (directChildNodes>maxNodes) maxNodes=directChildNodes; // directChildNodes+=m_startNode->m_children->count();
//if (directChildNodes>maxNodes) maxNodes=directChildNodes;
QList<DotNode> openNodeQueue; QList<DotNode> openNodeQueue;
openNodeQueue.append(m_startNode); openNodeQueue.append(m_startNode);
determineVisibleNodes(openNodeQueue,maxNodes); determineVisibleNodes(openNodeQueue,maxNodes);
...@@ -2351,10 +2084,10 @@ QCString DotInclDepGraph::writeGraph(QTextStream &out, ...@@ -2351,10 +2084,10 @@ QCString DotInclDepGraph::writeGraph(QTextStream &out,
QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT"); QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
if (updateDotGraph(m_startNode, if (updateDotGraph(m_startNode,
DotNode::CallGraph, DotNode::Dependency,
baseName, baseName,
format, format,
TRUE, // lrRank FALSE, // lrRank
FALSE, // renderParents FALSE, // renderParents
m_inverse // backArrows m_inverse // backArrows
) )
...@@ -2450,6 +2183,13 @@ bool DotInclDepGraph::isTrivial() const ...@@ -2450,6 +2183,13 @@ bool DotInclDepGraph::isTrivial() const
return m_startNode->m_children==0; 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) void DotInclDepGraph::writeXML(QTextStream &t)
{ {
QDictIterator<DotNode> dni(*m_usedNodes); QDictIterator<DotNode> dni(*m_usedNodes);
...@@ -2593,11 +2333,12 @@ DotCallGraph::DotCallGraph(MemberDef *md,bool inverse) ...@@ -2593,11 +2333,12 @@ DotCallGraph::DotCallGraph(MemberDef *md,bool inverse)
m_usedNodes->insert(uniqueId,m_startNode); m_usedNodes->insert(uniqueId,m_startNode);
buildGraph(m_startNode,md); buildGraph(m_startNode,md);
int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES");
int directChildNodes = 1; int maxNodes = nodes;
if (m_startNode->m_children!=0) //int directChildNodes = 1;
directChildNodes+=m_startNode->m_children->count(); //if (m_startNode->m_children!=0)
if (directChildNodes>maxNodes) maxNodes=directChildNodes; // directChildNodes+=m_startNode->m_children->count();
//if (directChildNodes>maxNodes) maxNodes=directChildNodes;
QList<DotNode> openNodeQueue; QList<DotNode> openNodeQueue;
openNodeQueue.append(m_startNode); openNodeQueue.append(m_startNode);
determineVisibleNodes(openNodeQueue,maxNodes); determineVisibleNodes(openNodeQueue,maxNodes);
...@@ -2730,6 +2471,13 @@ bool DotCallGraph::isTrivial() const ...@@ -2730,6 +2471,13 @@ bool DotCallGraph::isTrivial() const
return m_startNode->m_children==0; 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) DotDirDeps::DotDirDeps(DirDef *dir) : m_dir(dir)
...@@ -3433,5 +3181,5 @@ void DotGroupCollaboration::writeGraphHeader(QTextStream &t) ...@@ -3433,5 +3181,5 @@ void DotGroupCollaboration::writeGraphHeader(QTextStream &t)
t << " edge [fontname=\"FreeSans.ttf\",fontsize=8," t << " edge [fontname=\"FreeSans.ttf\",fontsize=8,"
"labelfontname=\"FreeSans.ttf\",labelfontsize=8];\n"; "labelfontname=\"FreeSans.ttf\",labelfontsize=8];\n";
t << " node [fontname=\"FreeSans.ttf\",fontsize=10,shape=record];\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 ...@@ -82,6 +82,7 @@ class DotNode
int number() const { return m_number; } int number() const { return m_number; }
bool isVisible() const { return m_visible; } bool isVisible() const { return m_visible; }
TruncState isTruncated() const { return m_truncated; } TruncState isTruncated() const { return m_truncated; }
int distance() const { return m_distance; }
private: private:
void colorConnectedNodes(int curColor); void colorConnectedNodes(int curColor);
...@@ -89,6 +90,7 @@ class DotNode ...@@ -89,6 +90,7 @@ class DotNode
bool hasNonReachableChildren, bool reNumber=FALSE); bool hasNonReachableChildren, bool reNumber=FALSE);
void writeArrow(QTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn, void writeArrow(QTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn,
EdgeInfo *ei,bool topDown, bool pointBack=TRUE, bool reNumber=FALSE); EdgeInfo *ei,bool topDown, bool pointBack=TRUE, bool reNumber=FALSE);
void setDistance(int distance);
const DotNode *findDocNode() const; // only works for acyclic graphs! const DotNode *findDocNode() const; // only works for acyclic graphs!
void markAsVisible(bool b=TRUE) { m_visible=b; } void markAsVisible(bool b=TRUE) { m_visible=b; }
void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; } void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; }
...@@ -106,6 +108,7 @@ class DotNode ...@@ -106,6 +108,7 @@ class DotNode
ClassDef * m_classDef; //!< class representing this node (can be 0) ClassDef * m_classDef; //!< class representing this node (can be 0)
bool m_visible; //!< is the node visible in the output bool m_visible; //!< is the node visible in the output
TruncState m_truncated; //!< does the node have non-visible children/parents 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 DotGfxHierarchyTable;
friend class DotClassGraph; friend class DotClassGraph;
...@@ -155,6 +158,7 @@ class DotClassGraph ...@@ -155,6 +158,7 @@ class DotClassGraph
DotClassGraph(ClassDef *cd,DotNode::GraphType t); DotClassGraph(ClassDef *cd,DotNode::GraphType t);
~DotClassGraph(); ~DotClassGraph();
bool isTrivial() const; bool isTrivial() const;
bool isTooBig() const;
QCString writeGraph(QTextStream &t,GraphOutputFormat f,const char *path, QCString writeGraph(QTextStream &t,GraphOutputFormat f,const char *path,
const char *relPath, bool TBRank=TRUE,bool imageMap=TRUE); const char *relPath, bool TBRank=TRUE,bool imageMap=TRUE);
...@@ -163,12 +167,12 @@ class DotClassGraph ...@@ -163,12 +167,12 @@ class DotClassGraph
QCString diskName() const; QCString diskName() const;
private: 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 determineVisibleNodes(QList<DotNode> &queue,int &maxNodes,bool includeParents);
void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents); void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents);
void addClass(ClassDef *cd,DotNode *n,int prot,const char *label, void addClass(ClassDef *cd,DotNode *n,int prot,const char *label,
const char *usedName,const char *templSpec, const char *usedName,const char *templSpec,
bool base); bool base,int distance);
DotNode * m_startNode; DotNode * m_startNode;
QDict<DotNode> * m_usedNodes; QDict<DotNode> * m_usedNodes;
...@@ -187,11 +191,12 @@ class DotInclDepGraph ...@@ -187,11 +191,12 @@ class DotInclDepGraph
const char *relPath, const char *relPath,
bool writeImageMap=TRUE); bool writeImageMap=TRUE);
bool isTrivial() const; bool isTrivial() const;
bool isTooBig() const;
QCString diskName() const; QCString diskName() const;
void writeXML(QTextStream &t); void writeXML(QTextStream &t);
private: private:
void buildGraph(DotNode *n,FileDef *fd); void buildGraph(DotNode *n,FileDef *fd,int distance);
void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes); void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes);
void determineTruncatedNodes(QList<DotNode> &queue); void determineTruncatedNodes(QList<DotNode> &queue);
...@@ -213,6 +218,7 @@ class DotCallGraph ...@@ -213,6 +218,7 @@ class DotCallGraph
const char *path,const char *relPath,bool writeImageMap=TRUE); const char *path,const char *relPath,bool writeImageMap=TRUE);
void buildGraph(DotNode *n,MemberDef *md); void buildGraph(DotNode *n,MemberDef *md);
bool isTrivial() const; bool isTrivial() const;
bool isTooBig() const;
void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes); void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes);
void determineTruncatedNodes(QList<DotNode> &queue); void determineTruncatedNodes(QList<DotNode> &queue);
......
...@@ -6397,7 +6397,7 @@ static void addEnumValuesToEnums(EntryNav *rootNav) ...@@ -6397,7 +6397,7 @@ static void addEnumValuesToEnums(EntryNav *rootNav)
// must create them here // must create them here
e->loadEntry(g_storage); e->loadEntry(g_storage);
MemberDef *fmd = addVariableToFile(e,MemberDef::EnumValue, MemberDef *fmd = addVariableToFile(e,MemberDef::EnumValue,
md->getOuterScope() ? md->getOuterScope()->name() : "", md->getOuterScope() ? md->getOuterScope()->name() : QCString(),
e->name(),TRUE,0); e->name(),TRUE,0);
md->insertEnumField(fmd); md->insertEnumField(fmd);
fmd->setEnumScope(md); fmd->setEnumScope(md);
...@@ -6659,6 +6659,43 @@ static void findDocumentedEnumValues() ...@@ -6659,6 +6659,43 @@ static void findDocumentedEnumValues()
findDEV(*Doxygen::functionNameSDict); 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' // computes the relation between all members. For each member `m'
...@@ -8560,49 +8597,13 @@ void readFormulaRepository() ...@@ -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() static void expandAliases()
{ {
QDictIterator<QCString> adi(Doxygen::aliasDict); QDictIterator<QCString> adi(Doxygen::aliasDict);
QCString *s; QCString *s;
for (adi.toFirst();(s=adi.current());++adi) for (adi.toFirst();(s=adi.current());++adi)
{ {
aliasesProcessed.clear(); *s = expandAlias(adi.currentKey(),*s);
// avoid expanding this command recursively
aliasesProcessed.insert(adi.currentKey(),(void *)0x8);
// expand embedded commands
*s = expandAliasesRec(*s);
} }
} }
...@@ -8678,7 +8679,6 @@ void readAliases() ...@@ -8678,7 +8679,6 @@ void readAliases()
} }
expandAliases(); expandAliases();
escapeAliases(); escapeAliases();
aliasesProcessed.clear();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
...@@ -9880,6 +9880,7 @@ void generateOutput() ...@@ -9880,6 +9880,7 @@ void generateOutput()
writeGroupIndex(*outputList); writeGroupIndex(*outputList);
msg("Generating class documentation...\n"); msg("Generating class documentation...\n");
addMembersToIndex();
generateClassDocs(); generateClassDocs();
if (Config_getBool("HAVE_DOT") && Config_getBool("GRAPHICAL_HIERARCHY")) if (Config_getBool("HAVE_DOT") && Config_getBool("GRAPHICAL_HIERARCHY"))
...@@ -9979,7 +9980,7 @@ void generateOutput() ...@@ -9979,7 +9980,7 @@ void generateOutput()
QDir::setCurrent(Config_getString("HTML_OUTPUT")); QDir::setCurrent(Config_getString("HTML_OUTPUT"));
if (portable_system(Config_getString("HHC_LOCATION"), "index.hhp", FALSE)) 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); QDir::setCurrent(oldDir);
} }
......
...@@ -391,7 +391,7 @@ void FileDef::writeDocumentation(OutputList &ol) ...@@ -391,7 +391,7 @@ void FileDef::writeDocumentation(OutputList &ol)
{ {
//printf("Graph for file %s\n",name().data()); //printf("Graph for file %s\n",name().data());
DotInclDepGraph incDepGraph(this,FALSE); DotInclDepGraph incDepGraph(this,FALSE);
if (!incDepGraph.isTrivial()) if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig())
{ {
ol.startTextBlock(); ol.startTextBlock();
ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Man);
...@@ -409,7 +409,7 @@ void FileDef::writeDocumentation(OutputList &ol) ...@@ -409,7 +409,7 @@ void FileDef::writeDocumentation(OutputList &ol)
{ {
//printf("Graph for file %s\n",name().data()); //printf("Graph for file %s\n",name().data());
DotInclDepGraph incDepGraph(this,TRUE); DotInclDepGraph incDepGraph(this,TRUE);
if (!incDepGraph.isTrivial()) if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig())
{ {
ol.startTextBlock(); ol.startTextBlock();
ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Man);
...@@ -723,7 +723,7 @@ void FileDef::insertMember(MemberDef *md) ...@@ -723,7 +723,7 @@ void FileDef::insertMember(MemberDef *md)
m_memberLists.append(allMemberList); m_memberLists.append(allMemberList);
} }
allMemberList->append(md); allMemberList->append(md);
::addFileMemberNameToIndex(md); //::addFileMemberNameToIndex(md);
switch (md->memberType()) switch (md->memberType())
{ {
case MemberDef::Variable: case MemberDef::Variable:
......
...@@ -577,18 +577,26 @@ void HtmlDocVisitor::visitPre(DocHtmlList *s) ...@@ -577,18 +577,26 @@ void HtmlDocVisitor::visitPre(DocHtmlList *s)
{ {
if (m_hide) return; if (m_hide) return;
if (s->type()==DocHtmlList::Ordered) if (s->type()==DocHtmlList::Ordered)
{
m_t << "<ol" << htmlAttribsToString(s->attribs()) << ">\n"; m_t << "<ol" << htmlAttribsToString(s->attribs()) << ">\n";
}
else else
{
m_t << "<ul" << htmlAttribsToString(s->attribs()) << ">\n"; m_t << "<ul" << htmlAttribsToString(s->attribs()) << ">\n";
}
} }
void HtmlDocVisitor::visitPost(DocHtmlList *s) void HtmlDocVisitor::visitPost(DocHtmlList *s)
{ {
if (m_hide) return; if (m_hide) return;
if (s->type()==DocHtmlList::Ordered) if (s->type()==DocHtmlList::Ordered)
{
m_t << "</ol>"; m_t << "</ol>";
else }
else
{
m_t << "</ul>"; m_t << "</ul>";
}
if (!s->isPreformatted()) m_t << "\n"; if (!s->isPreformatted()) m_t << "\n";
} }
......
...@@ -873,7 +873,7 @@ void HtmlGenerator::writeCodeLink(const char *ref,const char *f, ...@@ -873,7 +873,7 @@ void HtmlGenerator::writeCodeLink(const char *ref,const char *f,
if (f) t << f << Doxygen::htmlFileExtension; if (f) t << f << Doxygen::htmlFileExtension;
if (anchor) t << "#" << anchor; if (anchor) t << "#" << anchor;
t << "\""; t << "\"";
if (tooltip) t << " title=\"" << tooltip << "\""; if (tooltip) t << " title=\"" << convertToXML(tooltip) << "\"";
t << ">"; t << ">";
docify(name); docify(name);
t << "</a>"; t << "</a>";
......
...@@ -1667,7 +1667,8 @@ void initClassMemberIndices() ...@@ -1667,7 +1667,8 @@ void initClassMemberIndices()
void addClassMemberNameToIndex(MemberDef *md) void addClassMemberNameToIndex(MemberDef *md)
{ {
static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS"); static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS");
ClassDef *cd; ClassDef *cd=0;
if (md->isLinkableInProject() && if (md->isLinkableInProject() &&
(cd=md->getClassDef()) && (cd=md->getClassDef()) &&
cd->isLinkableInProject() && cd->isLinkableInProject() &&
......
...@@ -237,21 +237,22 @@ static void writeDefaultHeaderPart1(QTextStream &t) ...@@ -237,21 +237,22 @@ static void writeDefaultHeaderPart1(QTextStream &t)
} }
if (Config_getBool("PDF_HYPERLINKS")) if (Config_getBool("PDF_HYPERLINKS"))
{ {
t << "\\ifx\\pdfoutput\\undefined" << endl t << "\\usepackage{ifpdf}" << endl
<< "\\usepackage[ps2pdf," << endl << "\\ifpdf" << endl
<< "\\usepackage[pdftex," << endl
<< " pagebackref=true," << endl << " pagebackref=true," << endl
<< " colorlinks=true," << endl << " colorlinks=true," << endl
<< " linkcolor=blue," << endl << " linkcolor=blue," << endl
<< " unicode" << endl << " unicode" << endl
<< " ]{hyperref}" << endl << " ]{hyperref}" << endl
<< "\\usepackage{pspicture}" << endl
<< "\\else" << endl << "\\else" << endl
<< "\\usepackage[pdftex," << endl << "\\usepackage[ps2pdf," << endl
<< " pagebackref=true," << endl << " pagebackref=true," << endl
<< " colorlinks=true," << endl << " colorlinks=true," << endl
<< " linkcolor=blue," << endl << " linkcolor=blue," << endl
<< " unicode" << endl << " unicode" << endl
<< " ]{hyperref}" << endl << " ]{hyperref}" << endl
<< "\\usepackage{pspicture}" << endl
<< "\\fi" << endl; << "\\fi" << endl;
} }
// Try to get the command for switching on the language // Try to get the command for switching on the language
......
...@@ -772,10 +772,15 @@ bool MemberDef::isLinkableInProject() const ...@@ -772,10 +772,15 @@ bool MemberDef::isLinkableInProject() const
static bool extractStatic = Config_getBool("EXTRACT_STATIC"); static bool extractStatic = Config_getBool("EXTRACT_STATIC");
makeResident(); makeResident();
if (isHidden()) return FALSE;
//printf("MemberDef::isLinkableInProject(name=%s)\n",name().data()); //printf("MemberDef::isLinkableInProject(name=%s)\n",name().data());
if (isHidden())
{
//printf("is hidden\n");
return FALSE;
}
if (m_impl->templateMaster) if (m_impl->templateMaster)
{ {
//printf("has template master\n");
return m_impl->templateMaster->isLinkableInProject(); return m_impl->templateMaster->isLinkableInProject();
} }
if (name().isEmpty() || name().at(0)=='@') if (name().isEmpty() || name().at(0)=='@')
...@@ -2157,7 +2162,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, ...@@ -2157,7 +2162,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
) )
{ {
DotCallGraph callGraph(this,FALSE); DotCallGraph callGraph(this,FALSE);
if (!callGraph.isTrivial()) if (!callGraph.isTrivial() && !callGraph.isTooBig())
{ {
msg("Generating call graph for function %s\n",qualifiedName().data()); msg("Generating call graph for function %s\n",qualifiedName().data());
ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Man);
...@@ -2172,8 +2177,8 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, ...@@ -2172,8 +2177,8 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
&& isFunction() && Config_getBool("HAVE_DOT") && isFunction() && Config_getBool("HAVE_DOT")
) )
{ {
DotCallGraph callerGraph(this, true); DotCallGraph callerGraph(this, TRUE);
if (!callerGraph.isTrivial()) if (!callerGraph.isTrivial() && !callerGraph.isTooBig())
{ {
msg("Generating caller graph for function %s\n",qualifiedName().data()); msg("Generating caller graph for function %s\n",qualifiedName().data());
ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Man);
......
...@@ -98,7 +98,7 @@ void writeMscGraphFromFile(const char *inFile,const char *outDir, ...@@ -98,7 +98,7 @@ void writeMscGraphFromFile(const char *inFile,const char *outDir,
// go to the html output directory (i.e. path) // go to the html output directory (i.e. path)
QDir::setCurrent(outDir); QDir::setCurrent(outDir);
//printf("Going to dir %s\n",QDir::currentDirPath().data()); //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 mscArgs;
QCString extension; QCString extension;
if (format==MSC_BITMAP) if (format==MSC_BITMAP)
...@@ -151,7 +151,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir, ...@@ -151,7 +151,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir,
QCString mscExe = "mscgen"; QCString mscExe = "mscgen";
QCString mscArgs = "-T ismap -i \""; QCString mscArgs = "-T ismap -i \"";
mscArgs+=inFile + ".msc\" -o \""; mscArgs+=inFile + ".msc\" -o \"";
mscArgs+=outFile + ".map\""; mscArgs+=outFile + "\"";
int exitCode; int exitCode;
if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0) if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0)
...@@ -162,7 +162,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir, ...@@ -162,7 +162,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir,
QString result; QString result;
QTextOStream tmpout(&result); QTextOStream tmpout(&result);
convertMapFile(tmpout, outFile+".map", relPath); convertMapFile(tmpout, outFile, relPath);
QDir().remove(outFile); QDir().remove(outFile);
QDir::setCurrent(oldDir); QDir::setCurrent(oldDir);
......
...@@ -179,7 +179,7 @@ void NamespaceDef::insertMember(MemberDef *md) ...@@ -179,7 +179,7 @@ void NamespaceDef::insertMember(MemberDef *md)
m_memberLists.append(allMemberList); m_memberLists.append(allMemberList);
} }
allMemberList->append(md); allMemberList->append(md);
::addNamespaceMemberNameToIndex(md); //::addNamespaceMemberNameToIndex(md);
//static bool sortBriefDocs=Config_getBool("SORT_BRIEF_DOCS"); //static bool sortBriefDocs=Config_getBool("SORT_BRIEF_DOCS");
switch(md->memberType()) switch(md->memberType())
{ {
......
...@@ -620,7 +620,8 @@ class TranslatorChinese : public Translator ...@@ -620,7 +620,8 @@ class TranslatorChinese : public Translator
*/ */
virtual QCString trNamespaces() virtual QCString trNamespaces()
{ {
return "Namespaces"; // return "Namespaces";
return "名字空间";
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
......
...@@ -116,8 +116,9 @@ void TextGeneratorOLImpl::writeLink(const char *extRef,const char *file, ...@@ -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 :-) // an inheritance tree of depth of 100000 should be enough for everyone :-)
const int maxInheritanceDepth = 100000; const int maxInheritanceDepth = 100000;
bool isId(char c) bool isId(int c)
{ {
if (c<0 || c>255) return FALSE;
return c=='_' || isalnum(c); return c=='_' || isalnum(c);
} }
...@@ -6080,3 +6081,166 @@ QCString parseCommentAsText(const QString &doc,const QCString &fileName,int line ...@@ -6080,3 +6081,166 @@ QCString parseCommentAsText(const QString &doc,const QCString &fileName,int line
return result.data(); 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 &paramValue)
{
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); ...@@ -187,7 +187,7 @@ QCString showFileDefMatches(const FileNameDict *fnDict,const char *n);
int guessSection(const char *name); int guessSection(const char *name);
bool isId(char c); bool isId(int c);
QCString removeRedundantWhiteSpace(const QCString &s); QCString removeRedundantWhiteSpace(const QCString &s);
...@@ -334,5 +334,14 @@ QCString transcodeCharacterStringToUTF8(const QCString &input); ...@@ -334,5 +334,14 @@ QCString transcodeCharacterStringToUTF8(const QCString &input);
QCString recodeString(const QCString &str,const char *fromEncoding,const char *toEncoding); 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 #endif
...@@ -189,7 +189,7 @@ void writeXMLLink(QTextStream &t,const char *extRef,const char *compoundId, ...@@ -189,7 +189,7 @@ void writeXMLLink(QTextStream &t,const char *extRef,const char *compoundId,
if (anchorId) t << "member"; else t << "compound"; if (anchorId) t << "member"; else t << "compound";
t << "\""; t << "\"";
if (extRef) t << " external=\"" << extRef << "\""; if (extRef) t << " external=\"" << extRef << "\"";
if (tooltip) t << " tooltip=\"" << tooltip << "\""; if (tooltip) t << " tooltip=\"" << convertToXML(tooltip) << "\"";
t << ">"; t << ">";
writeXMLString(t,text); writeXMLString(t,text);
t << "</ref>"; t << "</ref>";
......
...@@ -43,7 +43,7 @@ TMAKE_LFLAGS_SHAPP = -shared ...@@ -43,7 +43,7 @@ TMAKE_LFLAGS_SHAPP = -shared
TMAKE_LFLAGS_SHLIB = -shared -h $(TARGET1) TMAKE_LFLAGS_SHLIB = -shared -h $(TARGET1)
TMAKE_LFLAGS_SONAME = TMAKE_LFLAGS_SONAME =
TMAKE_LIBS = TMAKE_LIBS = -liconv
TMAKE_LIBS_X11 = -lXext -lX11 -lm TMAKE_LIBS_X11 = -lXext -lX11 -lm
TMAKE_LIBS_QT = -lqt TMAKE_LIBS_QT = -lqt
TMAKE_LIBS_QT_MT = -lqt-mt TMAKE_LIBS_QT_MT = -lqt-mt
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment