Commit c22d77a7 authored by Dimitri van Heesch's avatar Dimitri van Heesch

Release-1.7.6.1-20120122

parent fd8b446f
DOXYGEN Version 1.7.6.1-20120110
DOXYGEN Version 1.7.6.1-20120122
Please read the installation section of the manual
(http://www.doxygen.org/install.html) for instructions.
--------
Dimitri van Heesch (10 January 2012)
Dimitri van Heesch (22 January 2012)
DOXYGEN Version 1.7.6.1_20120110
DOXYGEN Version 1.7.6.1_20120122
Please read INSTALL for compilation instructions.
......@@ -26,4 +26,4 @@ forum.
Enjoy,
Dimitri van Heesch (dimitri@stack.nl) (10 January 2012)
Dimitri van Heesch (dimitri@stack.nl) (22 January 2012)
......@@ -20,7 +20,7 @@ doxygen_version_minor=7
doxygen_version_revision=6.1
#NOTE: Setting version_mmn to "NO" will omit mmn info from the package.
doxygen_version_mmn=20120110
doxygen_version_mmn=20120122
bin_dirs=`echo $PATH | sed -e "s/:/ /g"`
......
......@@ -19,19 +19,21 @@ HTML_FOOTER =
QUIET = NO
WARNINGS = YES
DISABLE_INDEX = YES
GENERATE_TREEVIEW = YES
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
GENERATE_MAN = NO
GENERATE_LATEX = YES
GENERATE_HTML = YES
GENERATE_HTMLHELP = YES
GENERATE_HTMLHELP = NO
GENERATE_RTF = NO
GENERATE_XML = NO
HTML_COLORSTYLE_SAT = 0
ENABLED_SECTIONS = logo_on
ENABLE_PREPROCESSING = NO
CASE_SENSE_NAMES = NO
IMAGE_PATH = .
INPUT = index.doc install.doc starting.doc docblocks.doc lists.doc \
INPUT = index.doc install.doc starting.doc docblocks.doc markdown.doc \
grouping.doc formulas.doc diagrams.doc preprocessing.doc \
autolink.doc output.doc searching.doc customize.doc custcmd.doc \
external.doc faq.doc trouble.doc features.doc \
......@@ -48,3 +50,4 @@ SEARCHENGINE = NO
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
STRIP_CODE_COMMENTS = NO
HTML_STYLESHEET = doxygen_manual.css
......@@ -38,7 +38,7 @@
\verbatim <a href="linkURL">link text</a> \endverbatim
which will be automatically translated to other output formats by Doxygen.
\section linkclass Links to classes.
\section linkclass Links to classes
All words in the documentation that correspond to a documented class and
contain at least one non-lower case character will automatically be
......@@ -48,14 +48,14 @@
should put a \% in front of the word.
To link to an all lower case symbol, use \ref cmdref "\\ref".
\section linkfile Links to files.
\section linkfile Links to files
All words that contain a dot (<tt>.</tt>) that is not the last character
in the word are considered to be file names.
If the word is indeed the name of a documented input file, a link will
automatically be created to the documentation of that file.
\section linkfunc Links to functions.
\section linkfunc Links to functions
Links to functions are created if one of the following patterns is
encountered:
......@@ -101,7 +101,7 @@
that matches the pattern.
</ol>
\section linkother Links to variables, typedefs, enum types, enum values and defines.
\section linkother Links to other members
All of these entities can be linked to in the same way as described in the
previous section. For sake of clarity it is advised to only use
......
......@@ -2140,13 +2140,35 @@ Commands for visual enhancements
To have multiple words in typewriter font use \<tt\>multiple words\</tt\>.
<hr>
\section cmdcode \\code
\section cmdcode \\code [ '{'<word>'}']
\addindex \\code
Starts a block of code. A code block is treated differently
from ordinary text. It is interpreted as C/C++ code. The names of the
classes and members that are documented are automatically replaced by
links to the documentation.
from ordinary text. It is interpreted as source code. The names of
classes and members and other documented entities are automatically
replaced by links to the documentation.
By default the language that is assumed for syntax highlighting is based
on the location where the \\code block was found. If this part of
a Python file for instance, the syntax highlight will be done according
to the Python syntax.
If it unclear from the context which language is meant (for instance the
comment is in a .txt or .markdown file) then you can also explicitly
indicate the language, by putting the file extension typically
that doxygen associated with the language in curly brackets after the
code block. Here is an example:
\verbatim
\code{.py}
class Python:
pass
\endcode
\code{.cpp}
class Cpp {};
\endcode
\endverbatim
\sa section \ref cmdendcode "\\endcode" and section \ref cmdverbatim "\\verbatim".
......
This diff is collapsed.
......@@ -39,8 +39,8 @@
\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}}
\fancyfoot[LE]{\fancyplain{}{}}
\fancyfoot[CE]{\fancyplain{}{}}
\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize Generated on Fri Dec 16 2011 21\-:40\-:27 for My Project by Doxygen }}
\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize Generated on Fri Dec 16 2011 21\-:40\-:27 for My Project by Doxygen }}
\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen }}
\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen }}
\fancyfoot[CO]{\fancyplain{}{}}
\fancyfoot[RO]{\fancyplain{}{}}
%---------- Internal commands used in this style file ----------------
......
This diff is collapsed.
......@@ -18,6 +18,7 @@
\usepackage{graphicx}
\usepackage{multicol}
\usepackage{float}
\usepackage{geometry}
\usepackage{listings}
\usepackage{color}
\usepackage{ifthen}
......@@ -79,7 +80,7 @@ Written by Dimitri van Heesch\\[2ex]
\chapter{Installation}\label{install}\hypertarget{install}{}\input{install}
\chapter{Getting Started}\label{starting}\hypertarget{starting}{}\input{starting}
\chapter{Documenting the code}\label{docblocks}\hypertarget{docblocks}{}\input{docblocks}
\chapter{Lists}\label{lists}\hypertarget{lists}{}\input{lists}
\chapter{Markdown}\label{markdown}\hypertarget{markdown}{}\input{markdown}
\chapter{Grouping}\label{grouping}\hypertarget{grouping}{}\input{grouping}
\chapter{Including Formulas}\label{formulas}\hypertarget{formulas}{}\input{formulas}
\chapter{Graphs and diagrams}\label{diagrams}\hypertarget{diagrams}{}\input{diagrams}
......
......@@ -19,25 +19,26 @@
\addindex features
<UL>
<li>Requires very little overhead from the writer of the documentation.
Plain text will do, but for more fancy or structured output HTML tags
and/or some of doxygen's special commands can be used.
<li>Cross platform: works on Windows and many Unices (including Linux and
Plain text will do, Markdown is support, and for more fancy or
structured output HTML tags and/or some of doxygen's special commands
can be used.
<li>Cross platform: works on Windows and many Unix flavors (including Linux and
MacOSX).
<li>Indexes, organizes and generates browsable and cross-referenced
output even from undocumented code.
<li>Generates structured XML output for parsed sources, which can be
used by external tools.
<li>Supports C/C++, Java, (Corba and Microsoft) Java, Python, VHDL, PHP
IDL, C#, Objective-C 2.0, and to some extent D and Fortran sources.
IDL, C#, Fortran, TCL, Objective-C 2.0, and to some extent D sources.
<li>Supports documentation of files, namespaces, packages, classes,
structs, unions, templates, variables, functions, typedefs, enums and
defines.
<li>JavaDoc (1.1), qdoc3 (partially), and ECMA-334 (C# spec.) compatible.
<li>Comes with a GUI frontend (Doxywizard) to ease editing the options and run doxygen.
The GUI is available on Windows, Linux, and MacOSX.
<li>Comes with a GUI frontend (Doxywizard) to ease editing the options and
run doxygen. The GUI is available on Windows, Linux, and MacOSX.
<li>Automatically generates class and collaboration diagrams in HTML (as clickable
image maps) and \f$\mbox{\LaTeX}\f$ (as Encapsulated PostScript images).
<li>Uses the dot tool of the Graphviz tool kit to generate
<li>Uses the `dot` tool of the Graphviz tool kit to generate
include dependency graphs, collaboration diagrams, call graphs, directory structure
graphs, and graphical class hierarchy graphs.
<li>Allows grouping of entities in modules and creating a hierarchy of modules.
......
......@@ -14,7 +14,7 @@
* input used in their production; they are not affected by this license.
*
*/
/*! \mainpage
/*! \mainpage Doxygen Manual
\if logo_on
<center>
\htmlonly
......@@ -44,7 +44,7 @@ It can help you in three ways:
You can also visualize the relations between the various elements
by means of include dependency graphs, inheritance diagrams,
and collaboration diagrams, which are all generated automatically.
<li> You can even `abuse' doxygen for creating normal documentation (as I did
<li> You can also use doxygen for creating normal documentation (as I did
for this manual).
</ol>
......@@ -65,7 +65,7 @@ The first part forms a user manual:
documentation quickly.
<li>Section \ref docblocks demonstrates the various ways that code can
be documented.
<li>Section \ref lists show various ways to create lists.
<li>Section \ref markdown show the Markdown formatting supported by doxygen.
<li>Section \ref grouping shows how to group things together.
<li>Section \ref formulas shows how to insert formulas in the documentation.
<li>Section \ref diagrams describes the diagrams and graphs that doxygen can generate.
......
......@@ -19,7 +19,6 @@
\addindex installation
First go to the
<a href="http://www.doxygen.org/download.html">download</a> page
\latexonly({\tt http://www.doxygen.org/download.html})\endlatexonly
to get the latest distribution, if you did not have it already.
This section is divided into the following sections:
......@@ -45,7 +44,6 @@ following to build the executable:
\addindex strip
<li>In order to generate a Makefile for your platform, you need
<a href="http://www.perl.com/">perl</a>
\latexonly(see {\tt http://www.perl.com/})\endlatexonly.
\addindex perl
<li>The configure script assume the availability of standard UNIX tools such
as sed, date, find, uname, mv, cp, cat, echo, tr, cd, and rm.
......@@ -57,17 +55,14 @@ tools should be installed.
<ul>
<li>Qt Software's GUI toolkit
<a href="http://qt.nokia.com/">Qt</A>
\latexonly(see {\tt http://qt.nokia.com/})\endlatexonly
\addindex Qt
version 4.3 or higher.
This is needed to build the GUI front-end doxywizard.
<li>A \f$\mbox{\LaTeX}\f$ distribution: for instance
<a href="http://www.tug.org/interest.html#free">teTeX 1.0</a>
\latexonly (see {\tt http://www.tug.org/interest.html\#free})\endlatexonly.
This is needed for generating LaTeX, Postscript, and PDF output.
<li><a href="http://www.graphviz.org/">
the Graph visualization toolkit version 1.8.10 or higher</a>
\latexonly (see {\tt http://www.graphviz.org/})\endlatexonly.
Needed for the include dependency graphs,
the graphical inheritance graphs, and the collaboration graphs.
If you compile graphviz yourself, make sure you do include
......@@ -83,18 +78,14 @@ tools should be installed.
Compilation is now done by performing the following steps:
<ol>
<li> Unpack the archive, unless you already have done that:
<li>Unpack the archive, unless you already have done that:
\verbatim
gunzip doxygen-$VERSION.src.tar.gz # uncompress the archive
tar xf doxygen-$VERSION.src.tar # unpack it
\endverbatim
gunzip doxygen-$VERSION.src.tar.gz # uncompress the archive
tar xf doxygen-$VERSION.src.tar # unpack it
<li>Run the configure script:
\verbatim
sh ./configure
\endverbatim
sh ./configure
The script tries to determine the platform you use, the make tool
(which \e must be GNU make) and the perl
......@@ -103,9 +94,7 @@ Compilation is now done by performing the following steps:
To override the auto detected platform and compiler you can run
configure as follows:
\verbatim
configure --platform platform-type
\endverbatim
configure --platform platform-type
See the <code>PLATFORMS</code> file for a list of possible platform
options.
......@@ -114,21 +103,15 @@ Compilation is now done by performing the following steps:
front-end, you should run the configure script with
the <code>--with-doxywizard</code> option:
\verbatim
configure --with-doxywizard
\endverbatim
configure --with-doxywizard
For an overview of other configuration options use
\verbatim
configure --help
\endverbatim
configure --help
<li>Compile the program by running make:
\verbatim
make
\endverbatim
make
The program should compile without problems and the binaries
(<code>doxygen</code> and optionally <code>doxywizard</code>)
......@@ -136,9 +119,7 @@ Compilation is now done by performing the following steps:
<li>Optional: Generate the user manual.
\verbatim
make docs
\endverbatim
make docs
To let doxygen generate the HTML documentation.
......@@ -152,9 +133,7 @@ Compilation is now done by performing the following steps:
(you will need <code>pdflatex</code>, <code>makeindex</code>, and
<code>egrep</code> for this).
\verbatim
make pdf
\endverbatim
make pdf
The PDF manual <code>doxygen_manual.pdf</code> will be located
in the latex directory of the distribution. Just
......@@ -168,10 +147,8 @@ Compilation is now done by performing the following steps:
to install doxygen. If you downloaded the binary distribution for UNIX,
type:
\verbatim
./configure
make install
\endverbatim
./configure
make install
Binaries are installed into the directory <code>\<prefix\>/bin</code>.
Use <code>make install_docs</code> to install the
......@@ -204,14 +181,13 @@ directory pointed to by QTDIR on some systems
libs are in /usr/lib).
The solution: go to the root of the doxygen distribution and do:
\verbatim
mkdir qt
cd qt
ln -s your-qt-include-dir-here include
ln -s your-qt-lib-dir-here lib
ln -s your-qt-bin-dir-here bin
export QTDIR=$PWD
\endverbatim
mkdir qt
cd qt
ln -s your-qt-include-dir-here include
ln -s your-qt-lib-dir-here lib
ln -s your-qt-bin-dir-here bin
export QTDIR=$PWD
If you have a csh-like shell you should use <code>setenv QTDIR \$PWD</code>
instead of the <code>export</code> command above.
......@@ -239,24 +215,23 @@ config file).
<b>HP-UX \& Digital UNIX problems</b>
If you are compiling for HP-UX with aCC and you get this error:
\verbatim
/opt/aCC/lbin/ld: Unsatisfied symbols:
alloca (code)
\endverbatim
then you should (according to Anke Selig) edit <code>ce_parse.cpp</code>
and replace
\verbatim
then you should (according to Anke Selig) edit <code>ce_parse.cpp</code>
and replace
extern "C" {
void *alloca (unsigned int);
};
\endverbatim
with
\verbatim
with
#include <alloca.h>
\endverbatim
If that does not help, try removing <code>ce_parse.cpp</code> and let
bison rebuild it (this worked for me).
If that does not help, try removing <code>ce_parse.cpp</code> and let
bison rebuild it (this worked for me).
If you are compiling for Digital UNIX, the same problem can be solved
(according to Barnard Schmallhof) by replacing the following in
......@@ -308,7 +283,7 @@ not have access to a Solaris machine with this compiler. With GNU compiler
it does work and installing Sun patch 111679-13 has also been reported
as a way to fix the problem.
when configuring with <code>--static</code> I got:
when configuring with `--static` I got:
\verbatim
Undefined first referenced
......@@ -318,13 +293,11 @@ dlsym /usr/lib/libc.a(nss_deffinder.o)
dlopen /usr/lib/libc.a(nss_deffinder.o)
\endverbatim
Manually adding <code>-Bdynamic</code> after the target rule in
<code>Makefile.doxygen</code> will fix this:
Manually adding `-Bdynamic` after the target rule in
`Makefile.doxygen` will fix this:
\verbatim
$(TARGET): $(OBJECTS) $(OBJMOC)
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) -Bdynamic
\endverbatim
$(TARGET): $(OBJECTS) $(OBJMOC)
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) -Bdynamic
<b>GCC compiler problems</b>
......@@ -456,11 +429,9 @@ Here is what is required:
<li>The GNU tools flex, bison, and sed.
To get these working on Windows you should install the
<a href="http://sources.redhat.com/cygwin/">cygwin tools</a>
\latexonly(see {\tt http://sources.redhat.com/cygwin/})\endlatexonly
Alternatively, you can also choose to
download only a <a href="http://www.doxygen.org/dl/cygwin_tools.zip">small subset</a>
\latexonly(see {\tt http://www.doxygen.org/dl/cygwin\_tools.zip})\endlatexonly
of the cygwin tools that I put together just to compile doxygen.
As a third alternative one could use the GNUWin32 tools that can be
......@@ -648,7 +619,6 @@ features:
<li><a href="http://www.graphviz.org/">
the Graph visualization toolkit version 1.8.10</a><br>
\latexonly(see {\tt http://www.graphviz.org/})\endlatexonly.
Needed for the include dependency graphs, the graphical inheritance graphs,
and the collaboration graphs.
</ul>
......
......@@ -4,15 +4,16 @@ Doxygen provides a number of ways to create lists of items.
<b>Using dashes</b>
By putting a number of column-aligned minus (-) signs at the start of a
line, a bullet list will automatically be generated. Instead of the minus
sign also plus (+) or asterix (\*) can be used.
By putting a number of column-aligned minus (-) signs at the start of a
line, a bullet list will automatically be generated. Instead of the minus
sign also plus (+) or asterix (\*) can be used.
Numbered lists can also be generated by using a minus followed by a hash
or by using a number followed by a dot.
Numbered lists can also be generated by using a minus followed by a hash
or by using a number followed by a dot.
Nesting of lists is allowed and is based on indentation of the items.<p>
Here is an example:
Nesting of lists is allowed and is based on indentation of the items.<p>
Here is an example:
\verbatim
/*!
* A list of events:
......
This diff is collapsed.
......@@ -16,8 +16,6 @@
*/
/*! \page output Output Formats
\section output_sec Output Formats
\addindex output formats
The following output formats are \e directly supported by doxygen:
......@@ -31,11 +29,9 @@ The following output formats are \e directly supported by doxygen:
<dt><b>RTF</b>
<dd>Generated if \c GENERATE_RTF is set to \c YES in the configuration file.<p>
Note that the RTF output probably only looks nice with Microsoft's
Word 97. If you have success with other programs, please let me know.
Word. If you have success with other programs, please let me know.
<dt><b>XML</b>
<dd>Generated if \c GENERATE_XML is set to \c YES in the configuration file.<p>
<dt><b>Qt Help Project (.qhp)</b>
<dd>Generated if \c GENERATE_QHP is set to \c YES in the configuration file.
</dl>
The following output formats are \e indirectly supported by doxygen:
......@@ -46,6 +42,12 @@ The following output formats are \e indirectly supported by doxygen:
<dt><b>Qt Compressed Help (.qch)</b>
<dd>Generated by Qt's qhelpgenerator tool from the HTML output if
\c GENERATE_QHP is set to \c YES.
<dt><b>Eclipse Help</b>
<dd>Generated from HTML with a special index file that is generated when
\c GENERATE_ECLIPSEHELP is set to \c YES.
<dt><b>XCode DocSets</b>
<dd>Compiled from HTML with a special index file that is generated when
\c GENERATE_DOCSET is set to \c YES.
<dt><b>PostScript</b>
<dd>Generated from the \f$\mbox{\LaTeX}\f$ output by
running <code>make ps</code> in the output directory.
......
/*! \page perlmod Perl Module output format documentation
/*! \page perlmod Perl Module Output
\addindex perlmod
......@@ -21,7 +21,7 @@ useful output, as shown by the Perl Module-based LaTeX generator.
backend or the Perl Module-based LaTeX generator to the
doxygen-develop mailing list. Suggestions are welcome as well.
\section using_perlmod_fmt Using the Perl Module output format.
\section using_perlmod_fmt Usage
<p>When the <b>GENERATE_PERLMOD</b> tag is enabled in the Doxyfile,
running Doxygen generates a number of files in the <b>perlmod/</b>
......@@ -56,7 +56,7 @@ Perl and it's the main purpose of including the Perl Module backend in
Doxygen. See \ref doxydocs_format "below" for details on how
to do this.
\section perlmod_latex Using the Perl Module-based LaTeX generator.
\section perlmod_latex Using the LaTeX generator.
<p>The Perl Module-based LaTeX generator is pretty experimental and
incomplete at the moment, but you could find it useful nevertheless.
......@@ -98,7 +98,7 @@ rules added to <b>doxyrules.make</b>.
</ul>
\subsection pm_pdf_gen Simple creation of PDF and DVI output using the Perl Module-based LaTeX generator.
\subsection pm_pdf_gen Creation of PDF and DVI output
<p>To try this you need to have installed LaTeX, PDFLaTeX and the
packages used by <b>doxylatex.tex</b>.
......@@ -133,7 +133,7 @@ in DVI format.
</ol>
\section doxydocs_format Perl Module documentation format.
\section doxydocs_format Documentation format.
<p>The Perl Module documentation generated by Doxygen is stored in
<b>DoxyDocs.pm</b>. This is a very simple Perl module that contains
......@@ -176,7 +176,7 @@ know the semantics of the nodes of the documentation tree, which we
present in \ref perlmod_tree "this page".
-->
\section doxymodel_format Data structure describing the Perl Module documentation tree.
\section doxymodel_format Data structure
<p>You might be interested in processing the documentation contained
in <b>DoxyDocs.pm</b> without needing to take into account the
......
/*! \page perlmod_tree Nodes in the documentation tree of the Perl Module output format
/*! \page perlmod_tree Perl Module Tree Nodes
<h2>Nodes in the documentation tree of the Perl Module output
format.</h2>
......
This diff is collapsed.
......@@ -87,10 +87,10 @@ Q_EXPORT void *qmemmove( void *dst, const void *src, uint len );
Q_EXPORT char *qstrdup( const char * );
Q_EXPORT inline uint cstrlen( const char *str )
{ return strlen(str); }
{ return (uint)strlen(str); }
Q_EXPORT inline uint qstrlen( const char *str )
{ return str ? strlen(str) : 0; }
{ return str ? (uint)strlen(str) : 0; }
Q_EXPORT inline char *cstrcpy( char *dst, const char *src )
{ return strcpy(dst,src); }
......
......@@ -3031,7 +3031,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") {
g_code->codify(yytext);
int s=0;while (!isId(yytext[s])) s++;
int e=yyleng-1;while (!isId(yytext[e])) e--;
int e=(int)yyleng-1;while (!isId(yytext[e])) e--;
g_name=((QCString)yytext).mid(s,e-s+1);
BEGIN( MemberCall2 );
}
......
This diff is collapsed.
......@@ -387,8 +387,9 @@ static Entry* current = 0 ; // working entry
//static Entry* previous = 0 ; // TODO: remove need for this
static bool needNewEntry;
static QCString sectionLabel;
static QCString sectionTitle;
static QCString g_sectionLabel;
static QCString g_sectionTitle;
static int g_sectionLevel;
static QCString xrefItemKey;
static QCString newXRefItemKey;
static QCString xrefItemTitle;
......@@ -401,7 +402,6 @@ static int braceCount;
static bool insidePre;
static bool parseMore;
static int g_condCount;
static int g_sectionLevel;
static int g_commentCount;
static bool g_spaceBeforeCmd;
......@@ -421,38 +421,40 @@ static QCString g_compoundName;
static void initParser()
{
sectionLabel.resize(0);
sectionTitle.resize(0);
g_sectionLabel.resize(0);
g_sectionTitle.resize(0);
g_memberGroupHeader.resize(0);
}
//-----------------------------------------------------------------------------
static QCString getDocSectionName(int s)
static bool getDocSectionName(int s)
{
switch(s)
{
case Entry::CLASSDOC_SEC: return "\\class";
case Entry::STRUCTDOC_SEC: return "\\struct";
case Entry::UNIONDOC_SEC: return "\\union";
case Entry::EXCEPTIONDOC_SEC: return "\\exception";
case Entry::NAMESPACEDOC_SEC: return "\\namespace";
case Entry::PROTOCOLDOC_SEC: return "\\protocol";
case Entry::CATEGORYDOC_SEC: return "\\category";
case Entry::ENUMDOC_SEC: return "\\enum";
case Entry::PAGEDOC_SEC: return "\\page";
case Entry::VARIABLEDOC_SEC: return "\\var";
case Entry::MEMBERDOC_SEC: return "\\fn";
case Entry::OVERLOADDOC_SEC: return "\\overload";
case Entry::FILEDOC_SEC: return "\\file";
case Entry::DEFINEDOC_SEC: return "\\def";
case Entry::GROUPDOC_SEC: return "\\defgroup";
case Entry::MAINPAGEDOC_SEC: return "\\mainpage";
case Entry::PACKAGEDOC_SEC: return "\\package";
case Entry::DIRDOC_SEC: return "\\dir";
case Entry::EXAMPLE_SEC: return "\\example";
case Entry::MEMBERGRP_SEC: return "\\name";
default: return "";
case Entry::CLASSDOC_SEC:
case Entry::STRUCTDOC_SEC:
case Entry::UNIONDOC_SEC:
case Entry::EXCEPTIONDOC_SEC:
case Entry::NAMESPACEDOC_SEC:
case Entry::PROTOCOLDOC_SEC:
case Entry::CATEGORYDOC_SEC:
case Entry::ENUMDOC_SEC:
case Entry::PAGEDOC_SEC:
case Entry::VARIABLEDOC_SEC:
case Entry::MEMBERDOC_SEC:
case Entry::OVERLOADDOC_SEC:
case Entry::FILEDOC_SEC:
case Entry::DEFINEDOC_SEC:
case Entry::GROUPDOC_SEC:
case Entry::MAINPAGEDOC_SEC:
case Entry::PACKAGEDOC_SEC:
case Entry::DIRDOC_SEC:
case Entry::EXAMPLE_SEC:
case Entry::MEMBERGRP_SEC:
return TRUE;
default:
return FALSE;
}
}
......@@ -461,7 +463,7 @@ static QCString getDocSectionName(int s)
static bool makeStructuralIndicator(Entry::Sections s)
{
//printf("current->section=%x\n",current->section);
if (!getDocSectionName(current->section).isEmpty())
if (getDocSectionName(current->section))
{
return TRUE;
}
......@@ -558,8 +560,9 @@ static void addXRefItem(const char *listName,const char *itemTitle,
docEntry->doc += cmdString;
}
SectionInfo *si=new SectionInfo(listName,anchorLabel,
sectionTitle,SectionInfo::Anchor);
Doxygen::sectionDict.insert(anchorLabel,si);
g_sectionTitle,SectionInfo::Anchor,
g_sectionLevel);
Doxygen::sectionDict.append(anchorLabel,si);
docEntry->anchors->append(si);
}
outputXRef.resize(0);
......@@ -598,14 +601,26 @@ static QCString addFormula()
static void checkFormula();
//-----------------------------------------------------------------------------
static SectionInfo::SectionType sectionLevelToType(int level)
{
if (level>=0 && level<5) return (SectionInfo::SectionType)level;
return SectionInfo::Anchor;
}
static void addSection()
{
sectionTitle+=yytext;
sectionTitle=sectionTitle.stripWhiteSpace();
//printf("Adding new section file=%s label=%s title=%s\n",yyFileName,sectionLabel.data(),sectionTitle.data());
SectionInfo *si = new SectionInfo(yyFileName,sectionLabel,sectionTitle,SectionInfo::Anchor);
// create a new section element
g_sectionTitle+=yytext;
g_sectionTitle=g_sectionTitle.stripWhiteSpace();
SectionInfo *si = new SectionInfo(yyFileName,g_sectionLabel,
g_sectionTitle,sectionLevelToType(g_sectionLevel),g_sectionLevel);
// add section to this entry
current->anchors->append(si);
Doxygen::sectionDict.insert(yytext,si);
// add section to the global dictionary
Doxygen::sectionDict.append(g_sectionLabel,si);
}
//-----------------------------------------------------------------------------
......@@ -1061,7 +1076,22 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
addOutput(yytext);
}
<Comment>^{B}*[1-9][0-9]*"."{B}+ |
<Comment>^{B}*[*+-]{B}+ { // start of autolist
<Comment>^{B}*[*+]{B}+ { // start of autolist
if (!Doxygen::markdownSupport)
{
REJECT;
}
else
{
if (inContext!=OutputXRef)
{
briefEndsAtDot=FALSE;
setOutput(OutputDoc);
}
addOutput(yytext);
}
}
<Comment>^{B}*"-"{B}+ { // start of autolist
if (inContext!=OutputXRef)
{
briefEndsAtDot=FALSE;
......@@ -1492,9 +1522,9 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
/* ----- handle arguments of the section/subsection/.. commands ------- */
<SectionLabel>{LABELID} { // first argyment
sectionLabel=yytext;
g_sectionLabel=yytext;
addOutput(yytext);
sectionTitle.resize(0);
g_sectionTitle.resize(0);
BEGIN(SectionTitle);
}
<SectionLabel>{DOCNL} { // missing argument
......@@ -1511,8 +1541,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
);
BEGIN(Comment);
}
<SectionTitle>[^\n@\\*]*/"\n" { // end of section title
<SectionTitle>[^\n@\\*]*/"\n" { // end of section title
addSection();
addOutput(yytext);
BEGIN( Comment );
......@@ -1527,19 +1556,19 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
addOutput('\n');
}
<SectionTitle>[^\n@\\]* { // any character without special meaning
sectionTitle+=yytext;
g_sectionTitle+=yytext;
addOutput(yytext);
}
<SectionTitle>("\\\\"|"@@"){ID} { // unescape escaped command
sectionTitle+=&yytext[1];
g_sectionTitle+=&yytext[1];
addOutput(yytext);
}
<SectionTitle>{CMD}[$@\\&~<>#%] { // unescape escaped character
sectionTitle+=yytext[1];
g_sectionTitle+=yytext[1];
addOutput(yytext);
}
<SectionTitle>. { // anything else
sectionTitle+=yytext;
g_sectionTitle+=yytext;
addOutput(*yytext);
}
......@@ -1576,8 +1605,8 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
/* ----- handle arguments of the anchor command ------- */
<AnchorLabel>{LABELID} { // found argument
SectionInfo *si = new SectionInfo(yyFileName,yytext,0,SectionInfo::Anchor);
Doxygen::sectionDict.insert(yytext,si);
SectionInfo *si = new SectionInfo(yyFileName,yytext,0,SectionInfo::Anchor,0);
Doxygen::sectionDict.append(yytext,si);
current->anchors->append(si);
addOutput(yytext);
BEGIN( Comment );
......@@ -2646,9 +2675,9 @@ bool parseCommentBlock(/* in */ ParserInterface *parser,
if (Doxygen::markdownSupport)
{
current->brief = processMarkdown(current->brief);
current->doc = processMarkdown(current->doc);
current->inbodyDocs = processMarkdown(current->inbodyDocs);
current->brief = processMarkdown(fileName,current,current->brief);
current->doc = processMarkdown(fileName,current,current->doc);
current->inbodyDocs = processMarkdown(fileName,current,current->inbodyDocs);
}
Debug::print(Debug::CommentScan,0,
......
......@@ -320,10 +320,11 @@ void Definition::addSectionsToDefinition(QList<SectionInfo> *anchorList)
//printf("Add section `%s' to definition `%s'\n",
// si->label.data(),name().data());
SectionInfo *gsi=Doxygen::sectionDict.find(si->label);
//printf("===== label=%s gsi=%p\n",si->label.data(),gsi);
if (gsi==0)
{
gsi = new SectionInfo(*si);
Doxygen::sectionDict.insert(si->label,gsi);
Doxygen::sectionDict.append(si->label,gsi);
}
if (m_impl->sectionDict==0)
{
......@@ -331,20 +332,82 @@ void Definition::addSectionsToDefinition(QList<SectionInfo> *anchorList)
}
if (m_impl->sectionDict->find(gsi->label)==0)
{
m_impl->sectionDict->insert(gsi->label,gsi);
m_impl->sectionDict->append(gsi->label,gsi);
gsi->definition = this;
}
si=anchorList->next();
}
}
bool Definition::hasSections() const
{
makeResident();
//printf("Definition::hasSections(%s) #sections=%d\n",name().data(),
// m_impl->sectionDict ? m_impl->sectionDict->count() : 0);
if (m_impl->sectionDict==0) return FALSE;
SDict<SectionInfo>::Iterator li(*m_impl->sectionDict);
SectionInfo *si;
for (li.toFirst();(si=li.current());++li)
{
if (si->type==SectionInfo::Section ||
si->type==SectionInfo::Subsection ||
si->type==SectionInfo::Subsubsection ||
si->type==SectionInfo::Paragraph)
{
return TRUE;
}
}
return FALSE;
}
void Definition::addSectionsToIndex()
{
makeResident();
if (m_impl->sectionDict==0) return;
//printf("Definition::addSectionsToIndex()\n");
SDict<SectionInfo>::Iterator li(*m_impl->sectionDict);
SectionInfo *si;
int level=0;
for (li.toFirst();(si=li.current());++li)
{
if (si->type==SectionInfo::Section ||
si->type==SectionInfo::Subsection ||
si->type==SectionInfo::Subsubsection ||
si->type==SectionInfo::Paragraph)
{
//printf(" level=%d title=%s\n",level,si->title.data());
int nextLevel = (int)si->type;
if (nextLevel>level)
{
Doxygen::indexList.incContentsDepth();
}
else if (nextLevel<level)
{
Doxygen::indexList.decContentsDepth();
}
Doxygen::indexList.addContentsItem(TRUE,si->title,
getReference(),
getOutputFileBase(),
si->label,
FALSE,
TRUE);
level = nextLevel;
}
}
while (level>0)
{
Doxygen::indexList.decContentsDepth();
level--;
}
}
void Definition::writeDocAnchorsToTagFile()
{
makeResident();
if (!Config_getString("GENERATE_TAGFILE").isEmpty() && m_impl->sectionDict)
{
//printf("%s: writeDocAnchorsToTagFile(%d)\n",name().data(),m_sectionDict->count());
QDictIterator<SectionInfo> sdi(*m_impl->sectionDict);
SDict<SectionInfo>::Iterator sdi(*m_impl->sectionDict);
SectionInfo *si;
for (;(si=sdi.current());++sdi)
{
......
......@@ -260,6 +260,7 @@ class Definition : public DefinitionIntf, public LockableObj
LockingPtr<MemberSDict> getReferencesMembers() const;
LockingPtr<MemberSDict> getReferencedByMembers() const;
bool hasSections() const;
//-----------------------------------------------------------------------------------
// ---- setters -----
......@@ -328,6 +329,8 @@ class Definition : public DefinitionIntf, public LockableObj
void writeDocAnchorsToTagFile();
void setLocalName(const QCString name);
void addSectionsToIndex();
protected:
virtual void flushToDisk() const;
......
......@@ -1720,7 +1720,7 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor)
if (g_sectionDict && g_sectionDict->find(id)==0)
{
//printf("Inserting in dictionary!\n");
g_sectionDict->insert(id,sec);
g_sectionDict->append(id,sec);
}
}
else
......@@ -1736,9 +1736,10 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor)
DocVerbatim::DocVerbatim(DocNode *parent,const QCString &context,
const QCString &text, Type t,bool isExample,
const QCString &exampleFile)
const QCString &exampleFile,const QCString &lang)
: m_context(context), m_text(text), m_type(t),
m_isExample(isExample), m_exampleFile(exampleFile), m_relPath(g_relPath)
m_isExample(isExample), m_exampleFile(exampleFile),
m_relPath(g_relPath), m_lang(lang)
{
m_parent = parent;
}
......@@ -2134,7 +2135,7 @@ void DocSecRefItem::parse()
m_anchor = sec->label;
if (g_sectionDict && g_sectionDict->find(m_target)==0)
{
g_sectionDict->insert(m_target,sec);
g_sectionDict->append(m_target,sec);
}
}
else
......@@ -2278,7 +2279,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
m_parent = parent;
Definition *compound = 0;
QCString anchor;
//printf("DocRef::DocRef(target=%s,context=%s\n",target.data(),context.data());
//printf("DocRef::DocRef(target=%s,context=%s)\n",target.data(),context.data());
ASSERT(!target.isEmpty());
m_relPath = g_relPath;
SectionInfo *sec = Doxygen::sectionDict[target];
......@@ -2299,7 +2300,8 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
else if (resolveLink(context,target,TRUE,&compound,anchor))
{
bool isFile = compound ?
(compound->definitionType()==Definition::TypeFile ? TRUE : FALSE) :
(compound->definitionType()==Definition::TypeFile ||
compound->definitionType()==Definition::TypePage ? TRUE : FALSE) :
FALSE;
m_text = linkToText(compound?compound->getLanguage():SrcLangExt_Unknown,target,isFile);
m_anchor = anchor;
......@@ -2323,6 +2325,8 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
m_file = compound->getOutputFileBase();
m_ref = compound->getReference();
//printf("isFile=%d compound=%s (%d)\n",isFile,compound->name().data(),
// compound->definitionType());
return;
}
else if (compound->definitionType()==Definition::TypeFile &&
......@@ -2334,7 +2338,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
return;
}
}
m_text = linkToText(SrcLangExt_Unknown,target,FALSE);
m_text = target;
warn_doc_error(g_fileName,doctokenizerYYlineno,"warning: unable to resolve reference to `%s' for \\ref command",
qPrint(target));
}
......@@ -4902,6 +4906,11 @@ bool DocPara::injectToken(int tok,const QCString &tokText)
int DocPara::handleStartCode()
{
int retval = doctokenizerYYlex();
QCString lang = g_token->name;
if (!lang.isEmpty() && lang.at(0)!='.')
{
lang="."+lang;
}
// search for the first non-whitespace line, index is stored in li
int i=0,li=0,l=g_token->verb.length();
while (i<l && (g_token->verb.at(i)==' ' || g_token->verb.at(i)=='\n'))
......@@ -4909,7 +4918,7 @@ int DocPara::handleStartCode()
if (g_token->verb.at(i)=='\n') li=i+1;
i++;
}
m_children.append(new DocVerbatim(this,g_context,g_token->verb.mid(li),DocVerbatim::Code,g_isExample,g_exampleName));
m_children.append(new DocVerbatim(this,g_context,g_token->verb.mid(li),DocVerbatim::Code,g_isExample,g_exampleName,lang));
if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"warning: code section ended without end marker");
doctokenizerYYsetStatePara();
return retval;
......@@ -6264,7 +6273,7 @@ int DocSection::parse()
if (m_title.isEmpty()) m_title = sec->label;
if (g_sectionDict && g_sectionDict->find(m_id)==0)
{
g_sectionDict->insert(m_id,sec);
g_sectionDict->append(m_id,sec);
}
}
}
......
......@@ -375,7 +375,7 @@ class DocVerbatim : public DocNode
enum Type { Code, HtmlOnly, ManOnly, LatexOnly, XmlOnly, Verbatim, Dot, Msc };
DocVerbatim(DocNode *parent,const QCString &context,
const QCString &text, Type t,bool isExample,
const QCString &exampleFile);
const QCString &exampleFile,const QCString &lang=QCString());
Kind kind() const { return Kind_Verbatim; }
Type type() const { return m_type; }
QCString text() const { return m_text; }
......@@ -384,14 +384,16 @@ class DocVerbatim : public DocNode
bool isExample() const { return m_isExample; }
QCString exampleFile() const { return m_exampleFile; }
QCString relPath() const { return m_relPath; }
QCString language() const { return m_lang; }
private:
QCString m_context;
QCString m_text;
Type m_type;
bool m_isExample;
Type m_type;
bool m_isExample;
QCString m_exampleFile;
QCString m_relPath;
QCString m_lang;
};
......@@ -1190,6 +1192,9 @@ class DocHtmlRow : public CompAccept<DocHtmlRow>, public DocNode
const HtmlAttribList &attribs() const { return m_attribs; }
int parse();
int parseXml(bool header);
bool isHeading() const { return m_children.count()>0 &&
((DocHtmlCell*)m_children.getFirst())->isHeading();
}
private:
HtmlAttribList m_attribs;
......
......@@ -290,7 +290,8 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md,const char *)
case SrcLangExt_VHDL: lang="vhdl"; break; // VHDL
case SrcLangExt_XML: lang="xml"; break; // DBUS XML
case SrcLangExt_Tcl: lang="tcl"; break; // Tcl
case SrcLangExt_Unknown: lang="unknown"; break; // should not happen!
case SrcLangExt_Markdown:lang="markdown"; break; // Markdown
case SrcLangExt_Unknown: lang="unknown"; break; // should not happen!
}
if (md)
......
......@@ -389,6 +389,7 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}
%x St_TitleA
%x St_TitleV
%x St_Code
%x St_CodeOpt
%x St_XmlCode
%x St_HtmlOnly
%x St_ManOnly
......@@ -696,6 +697,16 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}
return TK_NEWPARA;
}
}
<St_CodeOpt>"{"{LABELID}"}" {
g_token->name = yytext;
g_token->name = g_token->name.mid(1,g_token->name.length()-2);
BEGIN(St_Code);
}
<St_CodeOpt>\n |
<St_CodeOpt>. {
unput(*yytext);
BEGIN(St_Code);
}
<St_Code>{WS}*{CMD}"endcode" {
return RetVal_OK;
}
......@@ -1154,12 +1165,14 @@ void doctokenizerYYsetStateTitleAttrValue()
void doctokenizerYYsetStateCode()
{
g_token->verb="";
BEGIN(St_Code);
g_token->name="";
BEGIN(St_CodeOpt);
}
void doctokenizerYYsetStateXmlCode()
{
g_token->verb="";
g_token->name="";
BEGIN(St_XmlCode);
}
......
......@@ -163,8 +163,6 @@ static bool g_successfulRun = FALSE;
static bool g_dumpSymbolMap = FALSE;
static bool g_dumpConfigAsXML = FALSE;
void clearAll()
{
g_inputFiles.clear();
......@@ -8233,8 +8231,9 @@ static void findMainPage(EntryNav *rootNav)
indexName,
Doxygen::mainPage->name(),
Doxygen::mainPage->title(),
SectionInfo::Page);
Doxygen::sectionDict.insert(indexName,si);
SectionInfo::Page,
0); // level 0
Doxygen::sectionDict.append(indexName,si);
Doxygen::mainPage->addSectionsToDefinition(root->anchors);
}
else
......@@ -8310,7 +8309,7 @@ static void checkPageRelations()
static void resolveUserReferences()
{
QDictIterator<SectionInfo> sdi(Doxygen::sectionDict);
SDict<SectionInfo>::Iterator sdi(Doxygen::sectionDict);
SectionInfo *si;
for (;(si=sdi.current());++sdi)
{
......@@ -9380,7 +9379,7 @@ void initDoxygen()
Doxygen::memGrpInfoDict.setAutoDelete(TRUE);
Doxygen::tagDestinationDict.setAutoDelete(TRUE);
Doxygen::dirRelations.setAutoDelete(TRUE);
Doxygen::citeDict = new CiteDict(256);
Doxygen::citeDict = new CiteDict(257);
}
void cleanUpDoxygen()
......
......@@ -638,7 +638,6 @@ table.doxtable th {
font-size: 110%;
padding-bottom: 4px;
padding-top: 5px;
text-align:left;
}
table.fieldtable {
......
......@@ -638,7 +638,6 @@
" font-size: 110%;\n"
" padding-bottom: 4px;\n"
" padding-top: 5px;\n"
" text-align:left;\n"
"}\n"
"\n"
"table.fieldtable {\n"
......
......@@ -661,7 +661,7 @@ ATTR_SPEC (ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL
ACCESS_SPEC (PRIVATE|PUBLIC)
/* Assume that attribute statements are almost the same as attributes. */
ATTR_STMT {ATTR_SPEC}|DIMENSION
COMMANDS (BLOCK{BS}DATA|DO|SELECT|CASE|WHERE|IF|THEN|ELSE|MODULE{BS_}PROCEDURE|CONTAINS|IMPLICIT{BS}NONE|CONTAINS|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|DEALLOCATE|SIZE|END{BS}IF|END{BS}DO|WHILE|INQUIRE|OPEN|CLOSE|DATA)
COMMANDS (DO|SELECT|CASE|WHERE|IF|THEN|ELSE|MODULE{BS_}PROCEDURE|CONTAINS|IMPLICIT{BS}NONE|CONTAINS|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|DEALLOCATE|SIZE|END{BS}IF|END{BS}DO|WHILE|INQUIRE|OPEN|CLOSE|DATA)
IGNORE (CALL)
/* | */
......@@ -741,7 +741,7 @@ IGNORE (CALL)
}
/*-------- fortran module -----------------------------------------*/
<Start>("program"|"module"|"type"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { //
<Start>("block"{BS}"data"|"program"|"module"|"type"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { //
startScope();
startFontClass("keyword");
codifyLines(yytext);
......
......@@ -230,6 +230,7 @@ IDSYM [a-z_A-Z0-9]
NOTIDSYM [^a-z_A-Z0-9]
SEPARATE [:, \t]
ID [a-z_A-Z%]+{IDSYM}*
ID_ [a-z_A-Z%]*{IDSYM}*
PP_ID {ID}
LABELID [a-z_A-Z]+[a-z_A-Z0-9\-]*
SUBPROG (subroutine|function)
......@@ -299,6 +300,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
%x DocBackLine
%x EndDoc
%x BlockData
%%
/*-----------------------------------------------------------------------------------*/
......@@ -505,6 +507,11 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
<TypedefBody>^{BS}{CONTAINS}/({BS}|\n|!) { BEGIN(TypedefBodyContains); }
/*------ module handling ------------------------------------------------------------*/
<Start>block{BS}data{BS}{ID_} { //
v_type = V_IGNORE;
yy_push_state(BlockData);
defaultProtection = Public;
}
<Start>module|program{BS_} { //
v_type = V_IGNORE;
if(yytext[0]=='m' || yytext[0]=='M')
......@@ -513,6 +520,12 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
yy_push_state(Program);
defaultProtection = Public;
}
<BlockData>^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!) { // end block data
//if (!endScope(current_root))
// yyterminate();
defaultProtection = Public;
yy_pop_state();
}
<Start,ModuleBody,ModuleBodyContains>^{BS}"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!) { // end module
resolveModuleProcedures(moduleProcedures, current_root);
if (!endScope(current_root))
......@@ -660,6 +673,10 @@ private {
subrCurrent.remove(0u);
yy_pop_state() ;
}
<BlockData>{
{ID} {
}
}
<Start,ModuleBody,TypedefBody,SubprogBody>{
^{BS}{TYPE_SPEC}/{SEPARATE} {
/* variable declaration starts */
......
......@@ -31,6 +31,7 @@
#include "language.h"
#include "htmlgen.h"
#include "layout.h"
#include "pagedef.h"
#define MAX_INDENT 1024
......@@ -849,10 +850,17 @@ void FTVHelp::generateTreeViewScripts()
QCString &projName = Config_getString("PROJECT_NAME");
if (projName.isEmpty())
{
LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::MainPage);
t << "\"" << convertToJSString(lne->title()) << "\", ";
if (Doxygen::mainPage && !Doxygen::mainPage->title().isEmpty()) // Use title of main page as root
{
t << "\"" << convertToJSString(Doxygen::mainPage->title()) << "\", ";
}
else // Use default section title as root
{
LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::MainPage);
t << "\"" << convertToJSString(lne->title()) << "\", ";
}
}
else
else // use PROJECT_NAME as root tree element
{
t << "\"" << convertToJSString(projName) << "\", ";
}
......
......@@ -330,12 +330,17 @@ void HtmlDocVisitor::visit(DocStyleChange *s)
void HtmlDocVisitor::visit(DocVerbatim *s)
{
if (m_hide) return;
QCString lang = m_langExt;
if (!s->language().isEmpty()) // explicit language setting
{
lang = s->language();
}
switch(s->type())
{
case DocVerbatim::Code:
forceEndParagraph(s);
m_t << PREFRAG_START;
Doxygen::parserManager->getParser(m_langExt)
Doxygen::parserManager->getParser(lang)
->parseCode(m_ci,s->context(),s->text(),
s->isExample(),s->exampleFile());
m_t << PREFRAG_END;
......
......@@ -2765,7 +2765,7 @@ static void writePageIndex(OutputList &ol)
ol.startContents();
ol.startTextBlock();
bool addToIndex = lne==0 || lne->visible();
if (addToIndex)
if (0 /*addToIndex*/) // skip Related Pages section in navigation index
{
Doxygen::indexList.addContentsItem(TRUE,title,0,"pages",0,TRUE,TRUE);
Doxygen::indexList.incContentsDepth();
......@@ -2777,7 +2777,7 @@ static void writePageIndex(OutputList &ol)
PageDef *pd=0;
for (pdi.toFirst();(pd=pdi.current());++pdi)
{
if ( pd->visibleInIndex())
if (pd->visibleInIndex())
{
QCString pageTitle;
......@@ -2787,6 +2787,7 @@ static void writePageIndex(OutputList &ol)
pageTitle=pd->title();
bool hasSubPages = pd->hasSubPages();
bool hasSections = pd->hasSections();
ol.startIndexListItem();
ol.startIndexItem(pd->getReference(),pd->getOutputFileBase());
......@@ -2801,14 +2802,25 @@ static void writePageIndex(OutputList &ol)
ol.writeString("\n");
if (addToIndex)
{
Doxygen::indexList.addContentsItem(hasSubPages,filterTitle(pageTitle),pd->getReference(),pd->getOutputFileBase(),0,hasSubPages,TRUE);
Doxygen::indexList.addContentsItem(
hasSubPages || hasSections, // isDir
filterTitle(pageTitle), // name
pd->getReference(), // ref
pd->getOutputFileBase(), // file
0, // anchor
hasSubPages || hasSections, // separateIndex
TRUE); // addToNavIndex
if (hasSections)
{
pd->addSectionsToIndex();
}
}
writeSubPages(pd);
ol.endIndexListItem();
}
}
endIndexHierarchy(ol,0);
if (addToIndex)
if (0 /*addToIndex*/) // skip Related Pages section in navigation index
{
Doxygen::indexList.decContentsDepth();
}
......@@ -3445,8 +3457,12 @@ static void writeIndex(OutputList &ol)
if (Doxygen::mainPage)
{
Doxygen::indexList.addContentsItem(Doxygen::mainPage->hasSubPages(),title,0,indexName,0,Doxygen::mainPage->hasSubPages(),TRUE);
if (Doxygen::mainPage->hasSubPages() ||
(!Config_getString("PROJECT_NAME").isEmpty() && mainPageHasTitle())
) // to avoid duplicate entries in the treeview
{
Doxygen::indexList.addContentsItem(Doxygen::mainPage->hasSubPages(),title,0,indexName,0,Doxygen::mainPage->hasSubPages(),TRUE);
}
if (Doxygen::mainPage->hasSubPages())
{
writeSubPages(Doxygen::mainPage);
......
......@@ -53,8 +53,9 @@ static const char *secLabels[maxLevels] =
static const char *getSectionName(int level)
{
static bool compactLatex = Config_getBool("COMPACT_LATEX");
int l = level;
if (Config_getBool("COMPACT_LATEX")) l++;
if (compactLatex) l++;
if (Doxygen::insideMainPage) l--;
return secLabels[QMIN(maxLevels-1,l)];
}
......@@ -62,10 +63,11 @@ static const char *getSectionName(int level)
static int rowspan(DocHtmlCell *cell)
{
int retval = 0;
HtmlAttribList attrs = cell->attribs ();
for (unsigned int i = 0; i < attrs.count(); ++i)
HtmlAttribList attrs = cell->attribs();
uint i;
for (i=0; i<attrs.count(); ++i)
{
if ("rowspan" == attrs.at(i)->name.lower())
if (attrs.at(i)->name.lower()=="rowspan")
{
retval = attrs.at(i)->value.toInt();
break;
......@@ -74,6 +76,24 @@ static int rowspan(DocHtmlCell *cell)
return retval;
}
static int align(DocHtmlCell *cell)
{
HtmlAttribList attrs = cell->attribs();
uint i;
for (i=0; i<attrs.count(); ++i)
{
if (attrs.at(i)->name.lower()=="align")
{
if (attrs.at(i)->value.lower()=="center")
return 1;
else if (attrs.at(i)->value.lower()=="right")
return 2;
else return 0;
}
}
return 0;
}
QCString LatexDocVisitor::escapeMakeIndexChars(const char *s)
{
QCString result;
......@@ -277,26 +297,19 @@ void LatexDocVisitor::visit(DocVerbatim *s)
{
//static bool latexSourceCode = Config_getBool("LATEX_SOURCE_CODE");
if (m_hide) return;
QCString lang = m_langExt;
if (!s->language().isEmpty()) // explicit language setting
{
lang = s->language();
}
switch(s->type())
{
case DocVerbatim::Code:
//if (latexSourceCode)
//{
// m_t << "\n\n\\begin{footnotesize}\\begin{alltt}" << endl;
//}
//else
{
m_t << "\n\\begin{DoxyCode}\n";
}
Doxygen::parserManager->getParser(m_langExt)
->parseCode(m_ci,s->context(),s->text(),
s->isExample(),s->exampleFile());
//if (latexSourceCode)
//{
// m_t << "\\end{alltt}\\end{footnotesize}" << endl;
//}
//else
{
Doxygen::parserManager->getParser(lang)
->parseCode(m_ci,s->context(),s->text(),
s->isExample(),s->exampleFile());
m_t << "\\end{DoxyCode}\n";
}
break;
......@@ -883,9 +896,10 @@ void LatexDocVisitor::visitPost(DocHtmlCaption *)
m_t << "}\n";
}
void LatexDocVisitor::visitPre(DocHtmlRow *)
void LatexDocVisitor::visitPre(DocHtmlRow *r)
{
m_currentColumn = 0;
if (r->isHeading()) m_t << "\\rowcolor{lightgray}";
}
void LatexDocVisitor::visitPost(DocHtmlRow *)
......@@ -896,24 +910,30 @@ void LatexDocVisitor::visitPost(DocHtmlRow *)
QMap<int, int>::Iterator it;
int col = 1;
for (it = m_rowspanIndices.begin(); it != m_rowspanIndices.end(); ++it)
for (it = m_rowspanIndices.begin(); it != m_rowspanIndices.end(); ++it)
{
it.data()--;
if (it.data () <= 0)
{
m_rowspanIndices.remove (it);
}
else if (0 < it.data() - col)
{
m_t << "\\cline{" << col << "-" << it.data() - col << "}";
col = 1 + it.data ();
}
col = 1 + it.data();
}
if (col <= m_currentColumn)
{
m_t << "\\cline{" << col << "-" << m_currentColumn << "}";
}
m_t << "\n";
}
void LatexDocVisitor::visitPre(DocHtmlCell *cell)
void LatexDocVisitor::visitPre(DocHtmlCell *c)
{
if (m_hide) return;
......@@ -927,18 +947,35 @@ void LatexDocVisitor::visitPre(DocHtmlCell *cell)
it++;
}
int rs = rowspan(cell);
if (0 < rs)
int rs = rowspan(c);
if (rs>0)
{
m_inRowspan = TRUE;
m_rowspanIndices[m_currentColumn] = rs;
m_t << "\\multirow{" << rs << "}{\\linewidth}{";
}
int a = align(c);
if (a==1)
{
m_t << "\\PBS\\centering ";
}
else if (a==2)
{
m_t << "\\PBS\\raggedleft ";
}
if (c->isHeading())
{
m_t << "{\\bf ";
}
}
void LatexDocVisitor::visitPost(DocHtmlCell *c)
{
if (m_hide) return;
if (c->isHeading())
{
m_t << "}";
}
if (m_inRowspan)
{
m_inRowspan = FALSE;
......
......@@ -72,18 +72,10 @@ LatexGenerator::~LatexGenerator()
{
}
void LatexGenerator::init()
static void writeLatexMakefile()
{
bool generateBib = !Doxygen::citeDict->isEmpty();
QCString dir=Config_getString("LATEX_OUTPUT");
QDir d(dir);
if (!d.exists() && !d.mkdir(dir))
{
err("Could not create output directory %s\n",dir.data());
exit(1);
}
QCString fileName=dir+"/Makefile";
QFile file(fileName);
if (!file.open(IO_WriteOnly))
......@@ -182,6 +174,66 @@ void LatexGenerator::init()
<< "\trm -f "
#endif
<< "*.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf" << endl;
}
static void writeMakePdfBat()
{
#if defined(_MSC_VER)
if (Config_getBool("USE_PDFLATEX")) // use plain old latex
{
bool generateBib = !Doxygen::citeDict->isEmpty();
QCString mkidx_command = Config_getString("MAKEINDEX_CMD_NAME");
QCString dir=Config_getString("LATEX_OUTPUT");
QCString fileName=dir+"/makepdf.bat";
QFile file(fileName);
if (!file.open(IO_WriteOnly))
{
err("Could not open file %s for writing\n",fileName.data());
exit(1);
}
FTextStream t(&file);
t << "del /s /f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf\n\n";
t << "pdflatex refman\n";
t << "echo ----\n";
t << mkidx_command << " refman.idx\n";
if (generateBib)
{
t << "\tbibtex refman" << endl;
t << "\tpdflatex refman" << endl;
}
t << "echo ----\n";
t << "pdflatex refman\n\n";
t << "setlocal enabledelayedexpansion\n";
t << "set count=5\n";
t << ":repeat\n";
t << "set content=X\n";
t << "for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun LaTeX\" refman.log' ) do set content=\"%%~T\"\n";
t << "if !content! == X for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun to get cross-references right\" refman.log' ) do set content=\"%%~T\"\n";
t << "if !content! == X goto :skip\n";
t << "set /a count-=1\n";
t << "if !count! EQU 0 goto :skip\n\n";
t << "echo ----\n";
t << "pdflatex refman\n";
t << "goto :repeat\n";
t << ":skip\n";
t << "endlocal\n";
}
#endif
}
void LatexGenerator::init()
{
QCString dir=Config_getString("LATEX_OUTPUT");
QDir d(dir);
if (!d.exists() && !d.mkdir(dir))
{
err("Could not create output directory %s\n",dir.data());
exit(1);
}
writeLatexMakefile();
writeMakePdfBat();
createSubDirs(d);
}
......@@ -345,6 +397,7 @@ static void writeDefaultStyleSheetPart1(FTextStream &t)
"\\RequirePackage{longtable}\n"
"\\RequirePackage{verbatim}\n"
"\\RequirePackage{ifthen}\n"
"\\RequirePackage{xtab}\n"
"\\RequirePackage[table]{xcolor}\n\n";
t << "% Use helvetica font instead of times roman\n"
......@@ -788,10 +841,10 @@ static void writeDefaultStyleSheetPart3(FTextStream &t)
t << "{\n";
t << "\\setlength{\\tmplength}\n";
t << " {\\linewidth/(#1)-\\tabcolsep*2-\\arrayrulewidth*(#1+1)/(#1)}\n";
t << " \\par\\begin{tabular*}{\\linewidth}\n";
t << " \\par\\begin{xtabular*}{\\linewidth}\n";
t << " {*{#1}{|>{\\PBS\\raggedright\\hspace{0pt}}p{\\the\\tmplength}}|}\n";
t << "}\n";
t << "{\\end{tabular*}\\par}\n";
t << "{\\end{xtabular*}\\par}\n";
t << "\\newcommand{\\entrylabel}[1]{\n";
t << " {\\parbox[b]{\\labelwidth-4pt}{\\makebox[0pt][l]{%\n";
t << " \\usefont{OT1}{phv}{bc}{n}\\color{darkgray}#1}\\vspace{1.5\\baselineskip}}}}\n";
......
This diff is collapsed.
......@@ -19,8 +19,10 @@
#include <qcstring.h>
#include "parserintf.h"
class Entry;
/** processes string \a s and converts markdown into doxygen/html commands. */
QCString processMarkdown(const QCString &s);
QCString processMarkdown(const QCString &fileName,Entry *e,const QCString &s);
class MarkdownFileParser : public ParserInterface
{
......
......@@ -157,6 +157,7 @@ void marshalSectionInfoList(StorageIntf *s, QList<SectionInfo> *anchors)
marshalQCString(s,si->ref);
marshalInt(s,(int)si->type);
marshalQCString(s,si->fileName);
marshalInt(s,si->level);
}
}
}
......@@ -195,7 +196,7 @@ void marshalSectionDict(StorageIntf *s,SectionDict *sections)
else
{
marshalUInt(s,sections->count());
QDictIterator<SectionInfo> sli(*sections);
SDict<SectionInfo>::IteratorDict sli(*sections);
SectionInfo *si;
for (sli.toFirst();(si=sli.current());++sli)
{
......@@ -576,7 +577,8 @@ QList<SectionInfo> *unmarshalSectionInfoList(StorageIntf *s)
QCString ref = unmarshalQCString(s);
SectionInfo::SectionType type = (SectionInfo::SectionType)unmarshalInt(s);
QCString fileName = unmarshalQCString(s);
result->append(new SectionInfo(fileName,label,title,type,ref));
int level = unmarshalInt(s);
result->append(new SectionInfo(fileName,label,title,type,level,ref));
}
return result;
}
......@@ -619,7 +621,7 @@ SectionDict *unmarshalSectionDict(StorageIntf *s)
QCString key = unmarshalQCString(s);
SectionInfo *si = (SectionInfo *)unmarshalObjPointer(s);
//printf(" unmarshalSectionDict i=%d key=%s si=%s\n",count,key.data(),si->label.data());
result->insert(key,si);
result->append(key,si);
}
return result;
}
......
......@@ -210,6 +210,21 @@ function expandNode(o, node, imm, showRoot)
}
}
function highlightAnchor()
{
var anchor = $($(location).attr('hash'));
if (anchor.parent().attr('class')=='memItemLeft'){
var rows = $('.memberdecls tr[class$=\""'+
window.location.hash.substring(1)+'"\"]').children();
rows.effect('highlight',{},1500);
} else if (anchor.parent().is(":header")) {
anchor.parent().effect('highlight',{},1500);
} else {
var targetDiv = anchor.next();
$(targetDiv).children('.memproto,.memdoc').effect("highlight",{},1500);
}
}
function showNode(o, node, index)
{
if (node.childrenData && !node.expanded) {
......@@ -249,15 +264,12 @@ function showNode(o, node, index)
if ($(location).attr('hash')) {
var link=stripPath($(location).attr('pathname'))+':'+
$(location).attr('hash').substring(1);
a=$('.item a[class*=\""'+link+'"\"]');
a=$('.item a[class$=\""'+link+'"\"]');
}
if (a && a.length) {
a.parent().parent().addClass('selected');
a.parent().parent().attr('id','selected');
var anchor = $($(location).attr('hash'));
var targetDiv = anchor.next();
$(targetDiv).children('.memproto,.memdoc').
effect("highlight", {}, 1500);
highlightAnchor();
} else {
$(n.itemDiv).addClass('selected');
$(n.itemDiv).attr('id','selected');
......@@ -302,7 +314,8 @@ function initNavTree(toroot,relpath)
getScript(relpath+"navtreeindex",function(){
var navTreeIndex = eval('NAVTREEINDEX');
if (navTreeIndex) {
o.breadcrumbs = navTreeIndex[toroot];
var nti = navTreeIndex[toroot+window.location.hash];
o.breadcrumbs = nti ? nti : navTreeIndex[toroot];
if (o.breadcrumbs==null) o.breadcrumbs = navTreeIndex["index.html"];
o.breadcrumbs.unshift(0);
showNode(o, o.node, 0);
......@@ -311,20 +324,12 @@ function initNavTree(toroot,relpath)
$(window).bind('hashchange', function(){
if (window.location.hash && window.location.hash.length>1){
var anchor = $(window.location.hash);
if (anchor.parent().attr('class')=='memItemLeft'){
var rows = $('.memberdecls tr[class$=\""'+
window.location.hash.substring(1)+'"\"]').children();
rows.effect('highlight',{},1500);
} else {
var targetDiv = anchor.next();
$(targetDiv).children('.memproto,.memdoc').effect("highlight",{},1500);
}
highlightAnchor();
var a;
if ($(location).attr('hash')){
var link=stripPath($(location).attr('pathname'))+':'+
$(location).attr('hash').substring(1);
a=$('.item a[class*=\""'+link+'"\"]');
a=$('.item a[class$=\""'+link+'"\"]');
}
if (a && a.length){
$('.item').removeClass('selected');
......
......@@ -210,6 +210,21 @@
" }\n"
"}\n"
"\n"
"function highlightAnchor()\n"
"{\n"
" var anchor = $($(location).attr('hash'));\n"
" if (anchor.parent().attr('class')=='memItemLeft'){\n"
" var rows = $('.memberdecls tr[class$=\\\"\"'+\n"
" window.location.hash.substring(1)+'\"\\\"]').children();\n"
" rows.effect('highlight',{},1500);\n"
" } else if (anchor.parent().is(\":header\")) {\n"
" anchor.parent().effect('highlight',{},1500);\n"
" } else {\n"
" var targetDiv = anchor.next();\n"
" $(targetDiv).children('.memproto,.memdoc').effect(\"highlight\",{},1500);\n"
" }\n"
"}\n"
"\n"
"function showNode(o, node, index)\n"
"{\n"
" if (node.childrenData && !node.expanded) {\n"
......@@ -249,15 +264,12 @@
" if ($(location).attr('hash')) {\n"
" var link=stripPath($(location).attr('pathname'))+':'+\n"
" $(location).attr('hash').substring(1);\n"
" a=$('.item a[class*=\\\"\"'+link+'\"\\\"]');\n"
" a=$('.item a[class$=\\\"\"'+link+'\"\\\"]');\n"
" }\n"
" if (a && a.length) {\n"
" a.parent().parent().addClass('selected');\n"
" a.parent().parent().attr('id','selected');\n"
" var anchor = $($(location).attr('hash'));\n"
" var targetDiv = anchor.next();\n"
" $(targetDiv).children('.memproto,.memdoc').\n"
" effect(\"highlight\", {}, 1500);\n"
" highlightAnchor();\n"
" } else {\n"
" $(n.itemDiv).addClass('selected');\n"
" $(n.itemDiv).attr('id','selected');\n"
......@@ -302,7 +314,8 @@
" getScript(relpath+\"navtreeindex\",function(){\n"
" var navTreeIndex = eval('NAVTREEINDEX');\n"
" if (navTreeIndex) {\n"
" o.breadcrumbs = navTreeIndex[toroot];\n"
" var nti = navTreeIndex[toroot+window.location.hash];\n"
" o.breadcrumbs = nti ? nti : navTreeIndex[toroot];\n"
" if (o.breadcrumbs==null) o.breadcrumbs = navTreeIndex[\"index.html\"];\n"
" o.breadcrumbs.unshift(0);\n"
" showNode(o, o.node, 0);\n"
......@@ -311,20 +324,12 @@
"\n"
" $(window).bind('hashchange', function(){\n"
" if (window.location.hash && window.location.hash.length>1){\n"
" var anchor = $(window.location.hash);\n"
" if (anchor.parent().attr('class')=='memItemLeft'){\n"
" var rows = $('.memberdecls tr[class$=\\\"\"'+\n"
" window.location.hash.substring(1)+'\"\\\"]').children();\n"
" rows.effect('highlight',{},1500);\n"
" } else {\n"
" var targetDiv = anchor.next();\n"
" $(targetDiv).children('.memproto,.memdoc').effect(\"highlight\",{},1500);\n"
" }\n"
" highlightAnchor();\n"
" var a;\n"
" if ($(location).attr('hash')){\n"
" var link=stripPath($(location).attr('pathname'))+':'+\n"
" $(location).attr('hash').substring(1);\n"
" a=$('.item a[class*=\\\"\"'+link+'\"\\\"]');\n"
" a=$('.item a[class$=\\\"\"'+link+'\"\\\"]');\n"
" }\n"
" if (a && a.length){\n"
" $('.item').removeClass('selected');\n"
......
......@@ -120,8 +120,8 @@ class ParserManager
* @param[in] name A symbolic name of the parser, i.e. "c",
* "python", "fortran", "vhdl", ...
* @param[in] parser The parser that is to be used for the
* given extension.
* @param[in] defParser Use this parser as the default parser, using
* given name.
* @param[in] defParser Use this parser as the default parser, used
* for unregistered file extensions.
*/
void registerParser(const char *name,ParserInterface *parser,bool defParser=FALSE)
......
......@@ -328,13 +328,18 @@ void RTFDocVisitor::visit(DocVerbatim *s)
{
if (m_hide) return;
DBG_RTF("{\\comment RTFDocVisitor::visit(DocVerbatim)}\n");
QCString lang = m_langExt;
if (!s->language().isEmpty()) // explicit language setting
{
lang = s->language();
}
switch(s->type())
{
case DocVerbatim::Code: // fall though
m_t << "{" << endl;
m_t << "\\par" << endl;
m_t << rtf_Style_Reset << getStyle("CodeExample");
Doxygen::parserManager->getParser(m_langExt)
Doxygen::parserManager->getParser(lang)
->parseCode(m_ci,s->context(),s->text(),
s->isExample(),s->exampleFile());
//m_t << "\\par" << endl;
......
This diff is collapsed.
......@@ -28,13 +28,17 @@ class Definition;
struct SectionInfo
{
enum SectionType { Page, Section, Subsection,
Subsubsection, Paragraph, Anchor
enum SectionType { Page = 0,
Section = 1,
Subsection = 2,
Subsubsection = 3,
Paragraph = 4,
Anchor = 5
};
SectionInfo(const char *f,const char *l,const char *t,
SectionType st,const char *r=0) :
SectionType st,int lev,const char *r=0) :
label(l), title(t), type(st), ref(r), definition(0),
fileName(f), generated(FALSE)
fileName(f), generated(FALSE), level(lev)
{
}
SectionInfo(const SectionInfo &s)
......@@ -51,12 +55,13 @@ struct SectionInfo
Definition *definition;
QCString fileName;
bool generated;
int level;
};
class SectionDict : public QDict<SectionInfo>
class SectionDict : public SDict<SectionInfo>
{
public:
SectionDict(int size) : QDict<SectionInfo>(size) {}
SectionDict(int size) : SDict<SectionInfo>(size) {}
~SectionDict() {}
};
......
......@@ -1035,8 +1035,8 @@ void TagFileParser::addDocAnchors(Entry *e,const TagAnchorInfoList &l)
//printf("New sectionInfo file=%s anchor=%s\n",
// ta->fileName.data(),ta->label.data());
SectionInfo *si=new SectionInfo(ta->fileName,ta->label,ta->label,
SectionInfo::Anchor,m_tagName);
Doxygen::sectionDict.insert(ta->label,si);
SectionInfo::Anchor,0,m_tagName);
Doxygen::sectionDict.append(ta->label,si);
e->anchors->append(si);
}
else
......
This diff is collapsed.
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